refactor(team): update tracking logic and enhance test coverage
- Replaced `ensureTracking` and `stopTracking` with a single `setTracking` function in `TeamDataService` to streamline task change presence tracking. - Updated related tests to reflect the new tracking logic and ensure proper function calls. - Added `activeToolCalls` property to various service interfaces to improve state management during provisioning operations.
This commit is contained in:
parent
93f160d731
commit
16238276fb
6 changed files with 28 additions and 9 deletions
|
|
@ -147,11 +147,7 @@ describe('TeamDataService', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('starts and stops task change presence tracking outside getTeamData', async () => {
|
it('starts and stops task change presence tracking outside getTeamData', async () => {
|
||||||
const ensureTracking = vi.fn(async () => ({
|
const setTracking = vi.fn(async () => undefined);
|
||||||
projectFingerprint: 'project-fingerprint',
|
|
||||||
logSourceGeneration: 'generation-1',
|
|
||||||
}));
|
|
||||||
const stopTracking = vi.fn(async () => undefined);
|
|
||||||
|
|
||||||
const service = new TeamDataService(
|
const service = new TeamDataService(
|
||||||
{
|
{
|
||||||
|
|
@ -178,8 +174,7 @@ describe('TeamDataService', () => {
|
||||||
deleteTasks: vi.fn(async () => undefined),
|
deleteTasks: vi.fn(async () => undefined),
|
||||||
} as never,
|
} as never,
|
||||||
{
|
{
|
||||||
ensureTracking,
|
setTracking,
|
||||||
stopTracking,
|
|
||||||
} as never
|
} as never
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -187,8 +182,8 @@ describe('TeamDataService', () => {
|
||||||
service.setTaskChangePresenceTracking('my-team', false);
|
service.setTaskChangePresenceTracking('my-team', false);
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
|
|
||||||
expect(ensureTracking).toHaveBeenCalledWith('my-team');
|
expect(setTracking).toHaveBeenNthCalledWith(1, 'my-team', 'change_presence', true);
|
||||||
expect(stopTracking).toHaveBeenCalledWith('my-team');
|
expect(setTracking).toHaveBeenNthCalledWith(2, 'my-team', 'change_presence', false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('surfaces controller reconcile failures', async () => {
|
it('surfaces controller reconcile failures', async () => {
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,7 @@ interface RunLike {
|
||||||
provisioningComplete: boolean;
|
provisioningComplete: boolean;
|
||||||
leadMsgSeq: number;
|
leadMsgSeq: number;
|
||||||
pendingToolCalls: { name: string; preview: string }[];
|
pendingToolCalls: { name: string; preview: string }[];
|
||||||
|
activeToolCalls: Map<string, unknown>;
|
||||||
pendingDirectCrossTeamSendRefresh: boolean;
|
pendingDirectCrossTeamSendRefresh: boolean;
|
||||||
lastLeadTextEmitMs: number;
|
lastLeadTextEmitMs: number;
|
||||||
leadRelayCapture: null;
|
leadRelayCapture: null;
|
||||||
|
|
@ -166,6 +167,7 @@ function attachRun(
|
||||||
provisioningComplete: opts?.provisioningComplete ?? false,
|
provisioningComplete: opts?.provisioningComplete ?? false,
|
||||||
leadMsgSeq: 0,
|
leadMsgSeq: 0,
|
||||||
pendingToolCalls: [],
|
pendingToolCalls: [],
|
||||||
|
activeToolCalls: new Map(),
|
||||||
pendingDirectCrossTeamSendRefresh: false,
|
pendingDirectCrossTeamSendRefresh: false,
|
||||||
lastLeadTextEmitMs: 0,
|
lastLeadTextEmitMs: 0,
|
||||||
leadRelayCapture: null,
|
leadRelayCapture: null,
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ vi.mock('@main/utils/pathDecoder', async (importOriginal) => {
|
||||||
import { TeamProvisioningService } from '@main/services/team/TeamProvisioningService';
|
import { TeamProvisioningService } from '@main/services/team/TeamProvisioningService';
|
||||||
import { ClaudeBinaryResolver } from '@main/services/team/ClaudeBinaryResolver';
|
import { ClaudeBinaryResolver } from '@main/services/team/ClaudeBinaryResolver';
|
||||||
import { spawnCli } from '@main/utils/childProcess';
|
import { spawnCli } from '@main/utils/childProcess';
|
||||||
|
import { setAppDataBasePath } from '@main/utils/pathDecoder';
|
||||||
|
|
||||||
function createFakeChild() {
|
function createFakeChild() {
|
||||||
const writeSpy = vi.fn((_data: unknown, cb?: (err?: Error | null) => void) => {
|
const writeSpy = vi.fn((_data: unknown, cb?: (err?: Error | null) => void) => {
|
||||||
|
|
@ -109,11 +110,13 @@ describe('TeamProvisioningService post-compact lifecycle', () => {
|
||||||
tempClaudeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'claude-team-compact-'));
|
tempClaudeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'claude-team-compact-'));
|
||||||
tempTeamsBase = path.join(tempClaudeRoot, 'teams');
|
tempTeamsBase = path.join(tempClaudeRoot, 'teams');
|
||||||
tempTasksBase = path.join(tempClaudeRoot, 'tasks');
|
tempTasksBase = path.join(tempClaudeRoot, 'tasks');
|
||||||
|
setAppDataBasePath(tempClaudeRoot);
|
||||||
fs.mkdirSync(tempTeamsBase, { recursive: true });
|
fs.mkdirSync(tempTeamsBase, { recursive: true });
|
||||||
fs.mkdirSync(tempTasksBase, { recursive: true });
|
fs.mkdirSync(tempTasksBase, { recursive: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
setAppDataBasePath(null);
|
||||||
try {
|
try {
|
||||||
fs.rmSync(tempClaudeRoot, { recursive: true, force: true });
|
fs.rmSync(tempClaudeRoot, { recursive: true, force: true });
|
||||||
} catch {
|
} catch {
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,7 @@ describe('TeamProvisioningService prepare/auth behavior', () => {
|
||||||
timeoutHandle: null,
|
timeoutHandle: null,
|
||||||
fsMonitorHandle: null,
|
fsMonitorHandle: null,
|
||||||
claudeLogLines: [],
|
claudeLogLines: [],
|
||||||
|
activeToolCalls: new Map(),
|
||||||
leadActivityState: 'active',
|
leadActivityState: 'active',
|
||||||
leadContextUsage: null,
|
leadContextUsage: null,
|
||||||
};
|
};
|
||||||
|
|
@ -205,6 +206,7 @@ describe('TeamProvisioningService prepare/auth behavior', () => {
|
||||||
timeoutHandle: null,
|
timeoutHandle: null,
|
||||||
fsMonitorHandle: null,
|
fsMonitorHandle: null,
|
||||||
claudeLogLines: [],
|
claudeLogLines: [],
|
||||||
|
activeToolCalls: new Map(),
|
||||||
leadActivityState: 'active',
|
leadActivityState: 'active',
|
||||||
leadContextUsage: null,
|
leadContextUsage: null,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import {
|
||||||
} from '@main/services/team/TeamProvisioningService';
|
} from '@main/services/team/TeamProvisioningService';
|
||||||
import { ClaudeBinaryResolver } from '@main/services/team/ClaudeBinaryResolver';
|
import { ClaudeBinaryResolver } from '@main/services/team/ClaudeBinaryResolver';
|
||||||
import { spawnCli } from '@main/utils/childProcess';
|
import { spawnCli } from '@main/utils/childProcess';
|
||||||
|
import { setAppDataBasePath } from '@main/utils/pathDecoder';
|
||||||
|
|
||||||
function createFakeChild() {
|
function createFakeChild() {
|
||||||
const writeSpy = vi.fn((_data: unknown, cb?: (err?: Error | null) => void) => {
|
const writeSpy = vi.fn((_data: unknown, cb?: (err?: Error | null) => void) => {
|
||||||
|
|
@ -72,11 +73,13 @@ describe('TeamProvisioningService prompt content (solo mode discipline)', () =>
|
||||||
tempClaudeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'claude-team-prompts-'));
|
tempClaudeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'claude-team-prompts-'));
|
||||||
tempTeamsBase = path.join(tempClaudeRoot, 'teams');
|
tempTeamsBase = path.join(tempClaudeRoot, 'teams');
|
||||||
tempTasksBase = path.join(tempClaudeRoot, 'tasks');
|
tempTasksBase = path.join(tempClaudeRoot, 'tasks');
|
||||||
|
setAppDataBasePath(tempClaudeRoot);
|
||||||
fs.mkdirSync(tempTeamsBase, { recursive: true });
|
fs.mkdirSync(tempTeamsBase, { recursive: true });
|
||||||
fs.mkdirSync(tempTasksBase, { recursive: true });
|
fs.mkdirSync(tempTasksBase, { recursive: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
setAppDataBasePath(null);
|
||||||
// Best-effort cleanup of temp dir (per-test)
|
// Best-effort cleanup of temp dir (per-test)
|
||||||
try {
|
try {
|
||||||
fs.rmSync(tempClaudeRoot, { recursive: true, force: true });
|
fs.rmSync(tempClaudeRoot, { recursive: true, force: true });
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,7 @@ function attachAliveRun(
|
||||||
},
|
},
|
||||||
leadMsgSeq: 0,
|
leadMsgSeq: 0,
|
||||||
pendingToolCalls: [],
|
pendingToolCalls: [],
|
||||||
|
activeToolCalls: new Map(),
|
||||||
pendingDirectCrossTeamSendRefresh: false,
|
pendingDirectCrossTeamSendRefresh: false,
|
||||||
lastLeadTextEmitMs: 0,
|
lastLeadTextEmitMs: 0,
|
||||||
activeCrossTeamReplyHints: [],
|
activeCrossTeamReplyHints: [],
|
||||||
|
|
@ -348,6 +349,19 @@ describe('TeamProvisioningService relayLeadInboxMessages', () => {
|
||||||
(service as unknown as { runs: Map<string, unknown> }).runs.set('run-1', {
|
(service as unknown as { runs: Map<string, unknown> }).runs.set('run-1', {
|
||||||
runId: 'run-1',
|
runId: 'run-1',
|
||||||
teamName,
|
teamName,
|
||||||
|
request: {
|
||||||
|
teamName,
|
||||||
|
members: [{ name: 'team-lead', role: 'team-lead' }],
|
||||||
|
},
|
||||||
|
activeToolCalls: new Map(),
|
||||||
|
pendingToolCalls: [],
|
||||||
|
leadMsgSeq: 0,
|
||||||
|
pendingDirectCrossTeamSendRefresh: false,
|
||||||
|
lastLeadTextEmitMs: 0,
|
||||||
|
activeCrossTeamReplyHints: [],
|
||||||
|
pendingInboxRelayCandidates: [],
|
||||||
|
silentUserDmForward: null,
|
||||||
|
silentUserDmForwardClearHandle: null,
|
||||||
child: { stdin: { writable: true, write: writeSpy } },
|
child: { stdin: { writable: true, write: writeSpy } },
|
||||||
processKilled: false,
|
processKilled: false,
|
||||||
cancelRequested: false,
|
cancelRequested: false,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue