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:
iliya 2026-03-29 02:01:07 +02:00
parent 93f160d731
commit 16238276fb
6 changed files with 28 additions and 9 deletions

View file

@ -147,11 +147,7 @@ describe('TeamDataService', () => {
});
it('starts and stops task change presence tracking outside getTeamData', async () => {
const ensureTracking = vi.fn(async () => ({
projectFingerprint: 'project-fingerprint',
logSourceGeneration: 'generation-1',
}));
const stopTracking = vi.fn(async () => undefined);
const setTracking = vi.fn(async () => undefined);
const service = new TeamDataService(
{
@ -178,8 +174,7 @@ describe('TeamDataService', () => {
deleteTasks: vi.fn(async () => undefined),
} as never,
{
ensureTracking,
stopTracking,
setTracking,
} as never
);
@ -187,8 +182,8 @@ describe('TeamDataService', () => {
service.setTaskChangePresenceTracking('my-team', false);
await Promise.resolve();
expect(ensureTracking).toHaveBeenCalledWith('my-team');
expect(stopTracking).toHaveBeenCalledWith('my-team');
expect(setTracking).toHaveBeenNthCalledWith(1, 'my-team', 'change_presence', true);
expect(setTracking).toHaveBeenNthCalledWith(2, 'my-team', 'change_presence', false);
});
it('surfaces controller reconcile failures', async () => {

View file

@ -134,6 +134,7 @@ interface RunLike {
provisioningComplete: boolean;
leadMsgSeq: number;
pendingToolCalls: { name: string; preview: string }[];
activeToolCalls: Map<string, unknown>;
pendingDirectCrossTeamSendRefresh: boolean;
lastLeadTextEmitMs: number;
leadRelayCapture: null;
@ -166,6 +167,7 @@ function attachRun(
provisioningComplete: opts?.provisioningComplete ?? false,
leadMsgSeq: 0,
pendingToolCalls: [],
activeToolCalls: new Map(),
pendingDirectCrossTeamSendRefresh: false,
lastLeadTextEmitMs: 0,
leadRelayCapture: null,

View file

@ -32,6 +32,7 @@ vi.mock('@main/utils/pathDecoder', async (importOriginal) => {
import { TeamProvisioningService } from '@main/services/team/TeamProvisioningService';
import { ClaudeBinaryResolver } from '@main/services/team/ClaudeBinaryResolver';
import { spawnCli } from '@main/utils/childProcess';
import { setAppDataBasePath } from '@main/utils/pathDecoder';
function createFakeChild() {
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-'));
tempTeamsBase = path.join(tempClaudeRoot, 'teams');
tempTasksBase = path.join(tempClaudeRoot, 'tasks');
setAppDataBasePath(tempClaudeRoot);
fs.mkdirSync(tempTeamsBase, { recursive: true });
fs.mkdirSync(tempTasksBase, { recursive: true });
});
afterEach(() => {
setAppDataBasePath(null);
try {
fs.rmSync(tempClaudeRoot, { recursive: true, force: true });
} catch {

View file

@ -149,6 +149,7 @@ describe('TeamProvisioningService prepare/auth behavior', () => {
timeoutHandle: null,
fsMonitorHandle: null,
claudeLogLines: [],
activeToolCalls: new Map(),
leadActivityState: 'active',
leadContextUsage: null,
};
@ -205,6 +206,7 @@ describe('TeamProvisioningService prepare/auth behavior', () => {
timeoutHandle: null,
fsMonitorHandle: null,
claudeLogLines: [],
activeToolCalls: new Map(),
leadActivityState: 'active',
leadContextUsage: null,
};

View file

@ -36,6 +36,7 @@ import {
} from '@main/services/team/TeamProvisioningService';
import { ClaudeBinaryResolver } from '@main/services/team/ClaudeBinaryResolver';
import { spawnCli } from '@main/utils/childProcess';
import { setAppDataBasePath } from '@main/utils/pathDecoder';
function createFakeChild() {
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-'));
tempTeamsBase = path.join(tempClaudeRoot, 'teams');
tempTasksBase = path.join(tempClaudeRoot, 'tasks');
setAppDataBasePath(tempClaudeRoot);
fs.mkdirSync(tempTeamsBase, { recursive: true });
fs.mkdirSync(tempTasksBase, { recursive: true });
});
afterEach(() => {
setAppDataBasePath(null);
// Best-effort cleanup of temp dir (per-test)
try {
fs.rmSync(tempClaudeRoot, { recursive: true, force: true });

View file

@ -174,6 +174,7 @@ function attachAliveRun(
},
leadMsgSeq: 0,
pendingToolCalls: [],
activeToolCalls: new Map(),
pendingDirectCrossTeamSendRefresh: false,
lastLeadTextEmitMs: 0,
activeCrossTeamReplyHints: [],
@ -348,6 +349,19 @@ describe('TeamProvisioningService relayLeadInboxMessages', () => {
(service as unknown as { runs: Map<string, unknown> }).runs.set('run-1', {
runId: 'run-1',
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 } },
processKilled: false,
cancelRequested: false,