pi-crew 0.1.44 → 0.1.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/agents/analyst.md +11 -11
- package/agents/critic.md +11 -11
- package/agents/executor.md +11 -11
- package/agents/explorer.md +11 -11
- package/agents/planner.md +11 -11
- package/agents/reviewer.md +11 -11
- package/agents/security-reviewer.md +11 -11
- package/agents/test-engineer.md +11 -11
- package/agents/verifier.md +11 -11
- package/agents/writer.md +11 -11
- package/docs/refactor-tasks-phase3.md +394 -394
- package/docs/refactor-tasks-phase4.md +564 -564
- package/docs/refactor-tasks-phase5.md +402 -402
- package/docs/refactor-tasks-phase6.md +662 -662
- package/docs/research-extension-examples.md +297 -297
- package/docs/research-extension-system.md +324 -324
- package/docs/research-optimization-plan.md +548 -548
- package/docs/research-phase10-distillation.md +198 -198
- package/docs/research-phase11-distillation.md +201 -201
- package/docs/research-pi-coding-agent.md +357 -357
- package/docs/research-source-pi-crew-reference.md +174 -174
- package/docs/runtime-flow.md +148 -148
- package/docs/source-runtime-refactor-map.md +83 -83
- package/index.ts +6 -6
- package/package.json +1 -1
- package/src/agents/agent-serializer.ts +34 -34
- package/src/extension/cross-extension-rpc.ts +82 -82
- package/src/extension/register.ts +8 -1
- package/src/extension/registration/commands.ts +18 -2
- package/src/extension/registration/compaction-guard.ts +125 -125
- package/src/extension/registration/subagent-tools.ts +148 -148
- package/src/extension/registration/team-tool.ts +26 -8
- package/src/extension/run-bundle-schema.ts +89 -89
- package/src/extension/run-maintenance.ts +43 -43
- package/src/extension/team-tool/cancel.ts +105 -102
- package/src/extension/team-tool/context.ts +1 -0
- package/src/extension/team-tool/handle-settings.ts +188 -188
- package/src/extension/team-tool/inspect.ts +41 -41
- package/src/extension/team-tool/lifecycle-actions.ts +79 -79
- package/src/extension/team-tool/plan.ts +19 -19
- package/src/extension/team-tool/respond.ts +83 -66
- package/src/extension/team-tool/run.ts +1 -0
- package/src/i18n.ts +184 -184
- package/src/observability/exporters/otlp-exporter.ts +77 -77
- package/src/prompt/prompt-runtime.ts +72 -72
- package/src/runtime/agent-control.ts +63 -63
- package/src/runtime/agent-memory.ts +72 -72
- package/src/runtime/agent-observability.ts +114 -114
- package/src/runtime/async-marker.ts +26 -26
- package/src/runtime/attention-events.ts +28 -28
- package/src/runtime/background-runner.ts +53 -53
- package/src/runtime/child-pi.ts +444 -444
- package/src/runtime/completion-guard.ts +190 -190
- package/src/runtime/crew-agent-records.ts +8 -0
- package/src/runtime/delivery-coordinator.ts +153 -142
- package/src/runtime/direct-run.ts +35 -35
- package/src/runtime/foreground-control.ts +82 -82
- package/src/runtime/green-contract.ts +46 -46
- package/src/runtime/group-join.ts +106 -106
- package/src/runtime/heartbeat-gradient.ts +28 -28
- package/src/runtime/heartbeat-watcher.ts +124 -124
- package/src/runtime/live-agent-control.ts +87 -87
- package/src/runtime/live-agent-manager.ts +85 -85
- package/src/runtime/live-control-realtime.ts +36 -36
- package/src/runtime/live-session-runtime.ts +305 -305
- package/src/runtime/overflow-recovery.ts +175 -156
- package/src/runtime/parallel-research.ts +44 -44
- package/src/runtime/pi-json-output.ts +111 -111
- package/src/runtime/policy-engine.ts +79 -79
- package/src/runtime/progress-event-coalescer.ts +43 -43
- package/src/runtime/recovery-recipes.ts +74 -74
- package/src/runtime/retry-executor.ts +64 -64
- package/src/runtime/role-permission.ts +39 -39
- package/src/runtime/session-resources.ts +25 -25
- package/src/runtime/session-snapshot.ts +59 -59
- package/src/runtime/session-usage.ts +79 -79
- package/src/runtime/sidechain-output.ts +29 -29
- package/src/runtime/stale-reconciler.ts +199 -179
- package/src/runtime/supervisor-contact.ts +59 -59
- package/src/runtime/task-display.ts +38 -38
- package/src/runtime/task-output-context.ts +127 -127
- package/src/runtime/task-runner/live-executor.ts +101 -101
- package/src/runtime/task-runner/progress.ts +119 -119
- package/src/runtime/task-runner/result-utils.ts +14 -14
- package/src/runtime/task-runner/state-helpers.ts +22 -22
- package/src/runtime/team-runner.ts +13 -4
- package/src/runtime/worker-heartbeat.ts +21 -21
- package/src/runtime/worker-startup.ts +57 -57
- package/src/state/state-store.ts +43 -0
- package/src/state/task-claims.ts +44 -44
- package/src/state/types.ts +2 -0
- package/src/state/usage.ts +29 -29
- package/src/subagents/async-entry.ts +1 -1
- package/src/subagents/index.ts +3 -3
- package/src/subagents/live/control.ts +1 -1
- package/src/subagents/live/manager.ts +1 -1
- package/src/subagents/live/realtime.ts +1 -1
- package/src/subagents/live/session-runtime.ts +1 -1
- package/src/subagents/manager.ts +1 -1
- package/src/subagents/spawn.ts +1 -1
- package/src/teams/team-serializer.ts +38 -38
- package/src/types/diff.d.ts +18 -18
- package/src/ui/crew-footer.ts +101 -101
- package/src/ui/crew-select-list.ts +111 -111
- package/src/ui/crew-widget.ts +5 -1
- package/src/ui/dashboard-panes/mailbox-pane.ts +2 -1
- package/src/ui/dashboard-panes/metrics-pane.ts +34 -34
- package/src/ui/dynamic-border.ts +25 -25
- package/src/ui/layout-primitives.ts +106 -106
- package/src/ui/loaders.ts +158 -158
- package/src/ui/powerbar-publisher.ts +1 -1
- package/src/ui/render-diff.ts +119 -119
- package/src/ui/render-scheduler.ts +143 -143
- package/src/ui/run-snapshot-cache.ts +56 -37
- package/src/ui/snapshot-types.ts +5 -0
- package/src/ui/spinner.ts +17 -17
- package/src/ui/status-colors.ts +58 -58
- package/src/ui/syntax-highlight.ts +116 -116
- package/src/utils/atomic-write.ts +33 -33
- package/src/utils/completion-dedupe.ts +63 -63
- package/src/utils/frontmatter.ts +68 -68
- package/src/utils/git.ts +262 -262
- package/src/utils/ids.ts +12 -12
- package/src/utils/names.ts +27 -27
- package/src/utils/redaction.ts +44 -44
- package/src/utils/safe-paths.ts +47 -47
- package/src/utils/sleep.ts +32 -32
- package/src/workflows/validate-workflow.ts +40 -40
- package/src/worktree/branch-freshness.ts +45 -45
- package/teams/default.team.md +12 -12
- package/teams/fast-fix.team.md +11 -11
- package/teams/implementation.team.md +18 -18
- package/teams/parallel-research.team.md +14 -14
- package/teams/research.team.md +11 -11
- package/teams/review.team.md +12 -12
- package/workflows/default.workflow.md +29 -29
- package/workflows/fast-fix.workflow.md +22 -22
- package/workflows/implementation.workflow.md +38 -38
- package/workflows/parallel-research.workflow.md +46 -46
- package/workflows/research.workflow.md +22 -22
- package/workflows/review.workflow.md +30 -30
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import type { TeamRunManifest } from "../state/types.ts";
|
|
3
|
-
import { resolveRealContainedPath } from "../utils/safe-paths.ts";
|
|
4
|
-
import { projectCrewRoot } from "../utils/paths.ts";
|
|
5
|
-
import { listRuns } from "./run-index.ts";
|
|
6
|
-
import { logInternalError } from "../utils/internal-error.ts";
|
|
7
|
-
|
|
8
|
-
export interface PruneRunsResult {
|
|
9
|
-
kept: string[];
|
|
10
|
-
removed: string[];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function isFinished(run: TeamRunManifest): boolean {
|
|
14
|
-
return run.status === "completed" || run.status === "failed" || run.status === "cancelled" || run.status === "blocked";
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function isSafeToPrune(cwd: string, run: TeamRunManifest): boolean {
|
|
18
|
-
try {
|
|
19
|
-
const crewRoot = projectCrewRoot(cwd);
|
|
20
|
-
resolveRealContainedPath(crewRoot, run.stateRoot);
|
|
21
|
-
resolveRealContainedPath(crewRoot, run.artifactsRoot);
|
|
22
|
-
return true;
|
|
23
|
-
} catch {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function pruneFinishedRuns(cwd: string, keep: number): PruneRunsResult {
|
|
29
|
-
const crewRoot = projectCrewRoot(cwd);
|
|
30
|
-
const finished = listRuns(cwd).filter((run) => run.cwd === cwd && isFinished(run)).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
31
|
-
const kept = finished.slice(0, keep).map((run) => run.runId);
|
|
32
|
-
const removed: string[] = [];
|
|
33
|
-
for (const run of finished.slice(keep)) {
|
|
34
|
-
if (!isSafeToPrune(cwd, run)) {
|
|
35
|
-
logInternalError("prune.path-unsafe", new Error(`Skipping unsafe prune: stateRoot=${run.stateRoot}, artifactsRoot=${run.artifactsRoot}`), `runId=${run.runId}`);
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
fs.rmSync(run.stateRoot, { recursive: true, force: true });
|
|
39
|
-
fs.rmSync(run.artifactsRoot, { recursive: true, force: true });
|
|
40
|
-
removed.push(run.runId);
|
|
41
|
-
}
|
|
42
|
-
return { kept, removed };
|
|
43
|
-
}
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import type { TeamRunManifest } from "../state/types.ts";
|
|
3
|
+
import { resolveRealContainedPath } from "../utils/safe-paths.ts";
|
|
4
|
+
import { projectCrewRoot } from "../utils/paths.ts";
|
|
5
|
+
import { listRuns } from "./run-index.ts";
|
|
6
|
+
import { logInternalError } from "../utils/internal-error.ts";
|
|
7
|
+
|
|
8
|
+
export interface PruneRunsResult {
|
|
9
|
+
kept: string[];
|
|
10
|
+
removed: string[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function isFinished(run: TeamRunManifest): boolean {
|
|
14
|
+
return run.status === "completed" || run.status === "failed" || run.status === "cancelled" || run.status === "blocked";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function isSafeToPrune(cwd: string, run: TeamRunManifest): boolean {
|
|
18
|
+
try {
|
|
19
|
+
const crewRoot = projectCrewRoot(cwd);
|
|
20
|
+
resolveRealContainedPath(crewRoot, run.stateRoot);
|
|
21
|
+
resolveRealContainedPath(crewRoot, run.artifactsRoot);
|
|
22
|
+
return true;
|
|
23
|
+
} catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function pruneFinishedRuns(cwd: string, keep: number): PruneRunsResult {
|
|
29
|
+
const crewRoot = projectCrewRoot(cwd);
|
|
30
|
+
const finished = listRuns(cwd).filter((run) => run.cwd === cwd && isFinished(run)).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
31
|
+
const kept = finished.slice(0, keep).map((run) => run.runId);
|
|
32
|
+
const removed: string[] = [];
|
|
33
|
+
for (const run of finished.slice(keep)) {
|
|
34
|
+
if (!isSafeToPrune(cwd, run)) {
|
|
35
|
+
logInternalError("prune.path-unsafe", new Error(`Skipping unsafe prune: stateRoot=${run.stateRoot}, artifactsRoot=${run.artifactsRoot}`), `runId=${run.runId}`);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
fs.rmSync(run.stateRoot, { recursive: true, force: true });
|
|
39
|
+
fs.rmSync(run.artifactsRoot, { recursive: true, force: true });
|
|
40
|
+
removed.push(run.runId);
|
|
41
|
+
}
|
|
42
|
+
return { kept, removed };
|
|
43
|
+
}
|
|
@@ -1,103 +1,106 @@
|
|
|
1
|
-
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
2
|
-
import { withRunLockSync } from "../../state/locks.ts";
|
|
3
|
-
import { loadRunManifestById, saveRunTasks, updateRunStatus } from "../../state/state-store.ts";
|
|
4
|
-
import { saveCrewAgents, recordFromTask } from "../../runtime/crew-agent-records.ts";
|
|
5
|
-
import { writeForegroundInterruptRequest } from "../../runtime/foreground-control.ts";
|
|
6
|
-
import { logInternalError } from "../../utils/internal-error.ts";
|
|
7
|
-
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
8
|
-
import { result, type TeamContext } from "./context.ts";
|
|
9
|
-
|
|
10
|
-
export interface AbortOwnedResult {
|
|
11
|
-
abortedIds: string[];
|
|
12
|
-
missingIds: string[];
|
|
13
|
-
foreignIds: string[];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Classify task IDs by ownership.
|
|
18
|
-
* - Tasks with status "queued" or "running" that belong to the current session → abortedIds
|
|
19
|
-
* - Task IDs not found in the run → missingIds
|
|
20
|
-
* - Tasks with status "queued" or "running" that belong to a different session → foreignIds
|
|
21
|
-
* - Tasks already completed/failed/cancelled → neither (not included in any list)
|
|
22
|
-
*
|
|
23
|
-
* Currently, task ownership is determined by the manifest's run-level ownership.
|
|
24
|
-
* Since tasks in a single run are all owned by the session that created the run,
|
|
25
|
-
* the ownerSessionId comes from the context. Foreign detection compares
|
|
26
|
-
* the requesting session against the run's creating session.
|
|
27
|
-
*/
|
|
28
|
-
export function abortOwned(
|
|
29
|
-
runId: string,
|
|
30
|
-
taskIds: string[] | undefined,
|
|
31
|
-
ctx: TeamContext,
|
|
32
|
-
): AbortOwnedResult {
|
|
33
|
-
const loaded = loadRunManifestById(ctx.cwd, runId);
|
|
34
|
-
if (!loaded) return { abortedIds: [], missingIds: taskIds ?? [], foreignIds: [] };
|
|
35
|
-
|
|
36
|
-
const result: AbortOwnedResult = { abortedIds: [], missingIds: [], foreignIds: [] };
|
|
37
|
-
const taskMap = new Map(loaded.tasks.map((t) => [t.id, t] as const));
|
|
38
|
-
const targetIds = taskIds ?? loaded.tasks.map((t) => t.id);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
result.abortedIds.push(id);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return result;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function handleCancel(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
59
|
-
if (!params.runId) return result("Cancel requires runId.", { action: "cancel", status: "error" }, true);
|
|
60
|
-
const loaded = loadRunManifestById(ctx.cwd, params.runId);
|
|
61
|
-
if (!loaded) return result(`Run '${params.runId}' not found.`, { action: "cancel", status: "error" }, true);
|
|
62
|
-
return withRunLockSync(loaded.manifest, () => {
|
|
63
|
-
if ((loaded.manifest.status === "completed" || loaded.manifest.status === "cancelled") && !params.force) return result(`Run ${loaded.manifest.runId} is already ${loaded.manifest.status}; nothing to cancel. Use force: true to mark it cancelled anyway.`, { action: "cancel", status: "ok", runId: loaded.manifest.runId, artifactsRoot: loaded.manifest.artifactsRoot });
|
|
64
|
-
|
|
65
|
-
// Classify tasks for foreign-aware cancellation
|
|
66
|
-
const abortResult = abortOwned(loaded.manifest.runId, undefined, ctx);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
1
|
+
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
2
|
+
import { withRunLockSync } from "../../state/locks.ts";
|
|
3
|
+
import { loadRunManifestById, saveRunTasks, updateRunStatus } from "../../state/state-store.ts";
|
|
4
|
+
import { saveCrewAgents, recordFromTask } from "../../runtime/crew-agent-records.ts";
|
|
5
|
+
import { writeForegroundInterruptRequest } from "../../runtime/foreground-control.ts";
|
|
6
|
+
import { logInternalError } from "../../utils/internal-error.ts";
|
|
7
|
+
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
8
|
+
import { result, type TeamContext } from "./context.ts";
|
|
9
|
+
|
|
10
|
+
export interface AbortOwnedResult {
|
|
11
|
+
abortedIds: string[];
|
|
12
|
+
missingIds: string[];
|
|
13
|
+
foreignIds: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Classify task IDs by ownership.
|
|
18
|
+
* - Tasks with status "queued" or "running" that belong to the current session → abortedIds
|
|
19
|
+
* - Task IDs not found in the run → missingIds
|
|
20
|
+
* - Tasks with status "queued" or "running" that belong to a different session → foreignIds
|
|
21
|
+
* - Tasks already completed/failed/cancelled → neither (not included in any list)
|
|
22
|
+
*
|
|
23
|
+
* Currently, task ownership is determined by the manifest's run-level ownership.
|
|
24
|
+
* Since tasks in a single run are all owned by the session that created the run,
|
|
25
|
+
* the ownerSessionId comes from the context. Foreign detection compares
|
|
26
|
+
* the requesting session against the run's creating session.
|
|
27
|
+
*/
|
|
28
|
+
export function abortOwned(
|
|
29
|
+
runId: string,
|
|
30
|
+
taskIds: string[] | undefined,
|
|
31
|
+
ctx: TeamContext,
|
|
32
|
+
): AbortOwnedResult {
|
|
33
|
+
const loaded = loadRunManifestById(ctx.cwd, runId);
|
|
34
|
+
if (!loaded) return { abortedIds: [], missingIds: taskIds ?? [], foreignIds: [] };
|
|
35
|
+
|
|
36
|
+
const result: AbortOwnedResult = { abortedIds: [], missingIds: [], foreignIds: [] };
|
|
37
|
+
const taskMap = new Map(loaded.tasks.map((t) => [t.id, t] as const));
|
|
38
|
+
const targetIds = taskIds ?? loaded.tasks.map((t) => t.id);
|
|
39
|
+
const foreignRun = typeof loaded.manifest.ownerSessionId === "string" && loaded.manifest.ownerSessionId !== ctx.sessionId;
|
|
40
|
+
|
|
41
|
+
for (const id of targetIds) {
|
|
42
|
+
const task = taskMap.get(id);
|
|
43
|
+
if (!task) {
|
|
44
|
+
result.missingIds.push(id);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (task.status !== "queued" && task.status !== "running" && task.status !== "waiting") continue;
|
|
48
|
+
if (foreignRun) {
|
|
49
|
+
result.foreignIds.push(id);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
result.abortedIds.push(id);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function handleCancel(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
59
|
+
if (!params.runId) return result("Cancel requires runId.", { action: "cancel", status: "error" }, true);
|
|
60
|
+
const loaded = loadRunManifestById(ctx.cwd, params.runId);
|
|
61
|
+
if (!loaded) return result(`Run '${params.runId}' not found.`, { action: "cancel", status: "error" }, true);
|
|
62
|
+
return withRunLockSync(loaded.manifest, () => {
|
|
63
|
+
if ((loaded.manifest.status === "completed" || loaded.manifest.status === "cancelled") && !params.force) return result(`Run ${loaded.manifest.runId} is already ${loaded.manifest.status}; nothing to cancel. Use force: true to mark it cancelled anyway.`, { action: "cancel", status: "ok", runId: loaded.manifest.runId, artifactsRoot: loaded.manifest.artifactsRoot });
|
|
64
|
+
|
|
65
|
+
// Classify tasks for foreign-aware cancellation
|
|
66
|
+
const abortResult = abortOwned(loaded.manifest.runId, undefined, ctx);
|
|
67
|
+
if (abortResult.abortedIds.length === 0 && abortResult.foreignIds.length > 0) {
|
|
68
|
+
return result(`Run ${loaded.manifest.runId} belongs to another session; not cancelled.`, { action: "cancel", status: "error", runId: loaded.manifest.runId, foreignIds: abortResult.foreignIds } as never, true);
|
|
69
|
+
}
|
|
70
|
+
const cancellableIds = new Set(abortResult.abortedIds);
|
|
71
|
+
|
|
72
|
+
const tasks = loaded.tasks.map((task) => {
|
|
73
|
+
if (cancellableIds.has(task.id) && (task.status === "queued" || task.status === "running" || task.status === "waiting")) {
|
|
74
|
+
return { ...task, status: "cancelled" as const, finishedAt: new Date().toISOString(), error: "Run cancelled by user request." };
|
|
75
|
+
}
|
|
76
|
+
return task;
|
|
77
|
+
});
|
|
78
|
+
saveRunTasks(loaded.manifest, tasks);
|
|
79
|
+
try {
|
|
80
|
+
saveCrewAgents(loaded.manifest, tasks.map((task) => recordFromTask(loaded.manifest, task, "child-process")));
|
|
81
|
+
} catch (error) {
|
|
82
|
+
logInternalError("team-tool.handleCancel.crewAgents", error, `runId=${loaded.manifest.runId}`);
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
writeForegroundInterruptRequest(loaded.manifest, "Run cancelled by user request.");
|
|
86
|
+
} catch (error) {
|
|
87
|
+
logInternalError("team-tool.handleCancel.interruptRequest", error, `runId=${loaded.manifest.runId}`);
|
|
88
|
+
}
|
|
89
|
+
const updated = updateRunStatus(loaded.manifest, "cancelled", "Run cancelled by user request. Already-finished worker processes are not retroactively changed.");
|
|
90
|
+
|
|
91
|
+
// Build descriptive message including foreign/missing info
|
|
92
|
+
const parts = [`Cancelled run ${updated.runId}.`];
|
|
93
|
+
if (abortResult.foreignIds.length > 0) parts.push(` ${abortResult.foreignIds.length} task(s) belong to another session and were not cancelled: ${abortResult.foreignIds.join(", ")}.`);
|
|
94
|
+
if (abortResult.missingIds.length > 0) parts.push(` ${abortResult.missingIds.length} task ID(s) not found: ${abortResult.missingIds.join(", ")}.`);
|
|
95
|
+
|
|
96
|
+
return result(parts.join(""), {
|
|
97
|
+
action: "cancel",
|
|
98
|
+
status: "ok",
|
|
99
|
+
runId: updated.runId,
|
|
100
|
+
artifactsRoot: updated.artifactsRoot,
|
|
101
|
+
abortedIds: abortResult.abortedIds,
|
|
102
|
+
missingIds: abortResult.missingIds,
|
|
103
|
+
foreignIds: abortResult.foreignIds,
|
|
104
|
+
});
|
|
105
|
+
});
|
|
103
106
|
}
|
|
@@ -4,6 +4,7 @@ import type { TeamToolDetails } from "../team-tool-types.ts";
|
|
|
4
4
|
import { toolResult, type PiTeamsToolResult } from "../tool-result.ts";
|
|
5
5
|
|
|
6
6
|
export type TeamContext = Pick<ExtensionContext, "cwd"> & Partial<Pick<ExtensionContext, "model">> & {
|
|
7
|
+
sessionId?: string;
|
|
7
8
|
modelRegistry?: unknown;
|
|
8
9
|
sessionManager?: { getBranch?: () => unknown[] };
|
|
9
10
|
events?: { emit?: (event: string, data: unknown) => void };
|