pi-extended-teams 2.2.10 → 2.3.1
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/README.md +182 -2
- package/extensions/agents/read-agent-report.ts +11 -2
- package/extensions/agents/read-agent-session-lifecycle.ts +25 -10
- package/extensions/agents/read-agent.ts +387 -65
- package/extensions/agents/write-agent.ts +3 -0
- package/extensions/events/register-events.ts +37 -21
- package/extensions/index.ts +257 -60
- package/extensions/internal/pi-check-operations.ts +24 -0
- package/extensions/internal/session-files.ts +10 -2
- package/extensions/runtime/lead-attachment.ts +91 -0
- package/extensions/runtime/reload-owner.ts +107 -0
- package/extensions/runtime/team-host.ts +124 -0
- package/extensions/runtime/teammate-interrupt.ts +11 -5
- package/extensions/runtime/types.ts +4 -0
- package/extensions/team/lifecycle.ts +26 -0
- package/extensions/team/session-cost.ts +225 -0
- package/extensions/tools/agent-communication-tools.ts +24 -8
- package/extensions/tools/agent-status-tool.ts +50 -7
- package/extensions/tools/coordination-tools.ts +78 -8
- package/extensions/tools/public-team-tools.ts +51 -0
- package/extensions/tools/task-runtime-tools.ts +23 -4
- package/extensions/tools/team-tools.ts +365 -107
- package/extensions/ui/activity-colors.ts +50 -0
- package/extensions/ui/agent-follow-view.ts +15 -11
- package/extensions/ui/agent-navigation.ts +35 -1
- package/extensions/ui/checkpoints-command.ts +28 -0
- package/extensions/ui/onboarding-command.ts +218 -0
- package/extensions/ui/status-widget.ts +22 -14
- package/package.json +1 -1
- package/skills/teams.md +16 -0
- package/src/orchestration/index.ts +19 -1
- package/src/orchestration/status-projection.ts +2 -3
- package/src/orchestration/types.ts +9 -1
- package/src/results/check-journal.ts +149 -0
- package/src/results/check-policy.ts +86 -0
- package/src/results/check-runner.ts +110 -0
- package/src/results/checkpoint-assignment.ts +60 -0
- package/src/results/checkpoint-policy.ts +20 -0
- package/src/results/checkpoint-report.ts +109 -0
- package/src/results/checkpoint-retention.ts +15 -0
- package/src/results/completion-group-delivery.ts +66 -0
- package/src/results/completion-group-recovery.ts +61 -0
- package/src/results/completion-group-wake.ts +62 -0
- package/src/results/completion-group.ts +290 -0
- package/src/results/continuation-recipient.ts +37 -0
- package/src/results/durable-json.ts +29 -0
- package/src/results/repair-policy.ts +24 -0
- package/src/results/report-result.ts +77 -0
- package/src/results/source-identity.ts +115 -0
- package/src/results/specialist-checkpoint.ts +227 -0
- package/src/results/verification-controller.ts +308 -0
- package/src/utils/messaging.ts +47 -10
- package/src/utils/models.ts +13 -0
- package/src/utils/paths.ts +4 -0
- package/src/utils/report-events.ts +95 -10
- package/src/utils/settings.ts +24 -0
- package/src/utils/teams.ts +3 -1
- package/src/utils/write-queue.ts +3 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { StringEnum } from "../internal/schema";
|
|
3
|
+
import { ACCEPTED_FAVORITE_MODEL_SLOTS } from "../../src/utils/settings";
|
|
4
|
+
import { CheckPolicySchema } from "../../src/results/check-policy";
|
|
5
|
+
import { RepairPolicySchema } from "../../src/results/repair-policy";
|
|
6
|
+
import { CheckpointPolicySchema } from "../../src/results/checkpoint-policy";
|
|
7
|
+
import { CompletionGroupPolicySchema } from "../../src/results/completion-group";
|
|
8
|
+
|
|
9
|
+
const levelDescription = "Required intent tier. Configured favorites take priority; an unconfigured tier inherits the current lead model and thinking. Read tiers: read-collect gathers bounded facts without owning the conclusion; read-review is the normal default for focused review, verification, and bounded synthesis; read-analyze explains behavior or root cause across connected evidence; read-critical is only for irreducible high-stakes security, architecture, concurrency, migration, or data-correctness reasoning. Write tiers: write-patch makes a narrow localized change; write-feature implements a bounded feature with a known design; write-system owns a cross-cutting integration or refactor within explicitly claimed files; write-critical is only for high-risk security, concurrency, recovery, migration, or data-integrity changes. Prefer canonical tiers; legacy reading-*/writing-* aliases remain accepted for this minor release. Do not pass role, model, or thinking directly; see README.md.";
|
|
10
|
+
const base = {
|
|
11
|
+
name: Type.Optional(Type.String({ description: "Stable display name. Defaults to a generated agent name." })),
|
|
12
|
+
prompt: Type.String({ description: "The agent's assignment, relevant prior context, evidence already gathered, constraints, and report shape." }),
|
|
13
|
+
cwd: Type.Optional(Type.String({ description: "Working directory. Defaults to the lead session cwd." })),
|
|
14
|
+
checks: Type.Optional(CheckPolicySchema),
|
|
15
|
+
repair: Type.Optional(RepairPolicySchema),
|
|
16
|
+
checkpoint: Type.Optional(CheckpointPolicySchema),
|
|
17
|
+
continue_from: Type.Optional(Type.String({ description: "Continue this checkpoint as a fresh recipient/run with the current assignment and tier. name is a prefix, not a recipient to reuse." })),
|
|
18
|
+
session_context: Type.Optional(StringEnum(["none", "lazy"] as const, { description: "Optional filtered snapshot of the lead's active session branch. Use lazy only when omitted session history may materially affect the lane; the child reads it on demand rather than receiving transcript content in its prompt.", default: "none" })),
|
|
19
|
+
metadata: Type.Optional(Type.Record(Type.String(), Type.Any())),
|
|
20
|
+
allow_nested_read_agents: Type.Optional(Type.Boolean({ description: "Opt in eligible depth-0 write-feature/write-critical agents to restricted read-only child spawning.", default: false })),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Metadata is available before session_start without creating a second queue,
|
|
24
|
+
// lifecycle controller, or execution owner during host reload.
|
|
25
|
+
export const publicTeamToolMetadata = {
|
|
26
|
+
get_agent_status: {
|
|
27
|
+
name: "get_agent_status", label: "Get Agent Status",
|
|
28
|
+
description: "Get one read-only snapshot of one or all agents owned by this parent. Omit agent_name to inspect all. This call is allowed when current status is needed; it never waits, polls, stops, or changes agents. Do not call it repeatedly. Final reports arrive automatically and resume this agent.",
|
|
29
|
+
parameters: Type.Object({ agent_name: Type.Optional(Type.String({ description: "One owned agent to inspect. Omit to inspect all owned agents." })) }),
|
|
30
|
+
},
|
|
31
|
+
spawn_agent: {
|
|
32
|
+
name: "spawn_agent", label: "Spawn Agent",
|
|
33
|
+
description: "Spawn one agent by intent tier only. Configured favorites take priority; an unconfigured tier inherits the current lead model and thinking. Give it the relevant goal, decisions, prior attempts, inspected evidence, constraints, and expected delta rather than a context-free task. Use session_context=lazy only as an on-demand fallback when omitted session history may materially matter; it never replaces a good mission prompt. read-review is the normal read default; use read-collect for bounded fact gathering, read-analyze for connected explanation/root cause, and read-critical only for irreducible high-stakes reasoning. For edits, choose write-patch, write-feature, write-system, or the rare high-risk write-critical by scope and risk. After spawning, do not duplicate or take over its lane; work only on unrelated work, then end the turn so the automatic report can resume you. One get_agent_status snapshot is allowed when current status is needed; never sleep, busy-wait, repeatedly read inbox/status, or treat healthy silence as failure. Wait for the actual report before synthesizing; intervene only on a reported blocker/error, actual health failure, or explicit user cancellation. model_slot selects behavior, model, and thinking; do not pass role, model, or thinking directly.",
|
|
34
|
+
parameters: Type.Object({ ...base, model_slot: StringEnum(ACCEPTED_FAVORITE_MODEL_SLOTS, { description: levelDescription, default: "read-review" }) }),
|
|
35
|
+
},
|
|
36
|
+
spawn_swarm_agents: {
|
|
37
|
+
name: "spawn_swarm_agents", label: "Spawn Swarm Agents",
|
|
38
|
+
description: "Spawn a batch by intent tier only. Configured favorites take priority; unconfigured tiers inherit the current lead model and thinking. Give each lane the relevant goal, decisions, prior attempts, inspected evidence, constraints, and expected delta. Use session_context=lazy selectively as an on-demand fallback, never instead of a good mission prompt. Use read-review as the normal default, read-collect for bounded collection lanes, read-analyze for connected explanation, and read-critical only for irreducible high-stakes reasoning; choose write-patch/feature/system/critical by edit scope and risk. Each spawned lane is delegation-locked: do not duplicate or take it over. After unrelated work is done, end the turn so automatic reports can resume you. One get_agent_status snapshot is allowed when current status is needed; never sleep, busy-wait, repeatedly read inbox/status, or intervene early. Synthesize only after actual reports; intervene only on blocker/error, actual failure, or explicit cancellation. Each agent gets model_slot directly or from defaults; do not pass role, model, or thinking directly.",
|
|
39
|
+
parameters: Type.Object({
|
|
40
|
+
defaults: Type.Optional(Type.Object({
|
|
41
|
+
cwd: Type.Optional(Type.String()), checks: Type.Optional(CheckPolicySchema), repair: Type.Optional(RepairPolicySchema),
|
|
42
|
+
checkpoint: Type.Optional(CheckpointPolicySchema), model_slot: Type.Optional(StringEnum(ACCEPTED_FAVORITE_MODEL_SLOTS, { description: levelDescription })),
|
|
43
|
+
metadata: Type.Optional(Type.Record(Type.String(), Type.Any())),
|
|
44
|
+
session_context: Type.Optional(StringEnum(["none", "lazy"] as const, { description: "Shared lazy session-reference policy.", default: "none" })),
|
|
45
|
+
allow_nested_read_agents: Type.Optional(Type.Boolean({ description: "Shared opt-in for eligible depth-0 write-feature/write-critical agents.", default: false })),
|
|
46
|
+
})),
|
|
47
|
+
completion_group: Type.Optional(CompletionGroupPolicySchema),
|
|
48
|
+
agents: Type.Array(Type.Object({ ...base, model_slot: Type.Optional(StringEnum(ACCEPTED_FAVORITE_MODEL_SLOTS, { description: levelDescription })) }), { description: "Agents to spawn as one batch. Each one must have model_slot directly or inherit it from defaults." }),
|
|
49
|
+
}),
|
|
50
|
+
},
|
|
51
|
+
};
|
|
@@ -11,6 +11,7 @@ import type { ReadAgentTeardownResult } from "../agents/read-agent-session-lifec
|
|
|
11
11
|
import type { ShutdownTeammateOptions } from "../team/lifecycle";
|
|
12
12
|
import { readLifecycleTombstone } from "../../src/utils/lifecycle-tombstone";
|
|
13
13
|
import type { TeammateInterruptResult } from "../runtime/teammate-interrupt";
|
|
14
|
+
import { effectiveTaskOutcome } from "../../src/results/report-result";
|
|
14
15
|
|
|
15
16
|
export interface TaskRuntimeToolsOptions {
|
|
16
17
|
isTeammate: boolean;
|
|
@@ -18,7 +19,7 @@ export interface TaskRuntimeToolsOptions {
|
|
|
18
19
|
runningReadAgents: Map<string, RunningReadAgent>;
|
|
19
20
|
readAgentKey(teamName: string, agentName: string): string;
|
|
20
21
|
interruptTeammate?(agentName: string): Promise<TeammateInterruptResult>;
|
|
21
|
-
cancelQueuedAgent?(teamName: string, agentName: string): boolean
|
|
22
|
+
cancelQueuedAgent?(teamName: string, agentName: string): boolean | Promise<boolean>;
|
|
22
23
|
shutdownTeammate(teamName: string, member: Member, options?: ShutdownTeammateOptions): Promise<ReadAgentTeardownResult>;
|
|
23
24
|
getTeamName(): string | null | undefined;
|
|
24
25
|
}
|
|
@@ -56,7 +57,7 @@ export function registerTaskRuntimeTools(pi: any, options: TaskRuntimeToolsOptio
|
|
|
56
57
|
const teamName = options.getTeamName();
|
|
57
58
|
if (!teamName) throw new Error("No active agent session. Spawn an agent first.");
|
|
58
59
|
|
|
59
|
-
if (options.cancelQueuedAgent?.(teamName, params.agent_name)) {
|
|
60
|
+
if (await options.cancelQueuedAgent?.(teamName, params.agent_name)) {
|
|
60
61
|
return {
|
|
61
62
|
content: [{ type: "text", text: `Cancelled queued agent ${params.agent_name}.` }],
|
|
62
63
|
details: { session: teamName, agentName: params.agent_name, stopped: true, queued: true, reason: params.reason },
|
|
@@ -147,6 +148,10 @@ export function registerTaskRuntimeTools(pi: any, options: TaskRuntimeToolsOptio
|
|
|
147
148
|
if (!member) {
|
|
148
149
|
const fence = await readLifecycleTombstone(teamName, params.agent_name);
|
|
149
150
|
if (fence.status !== "absent") {
|
|
151
|
+
const completedReport = !options.isTeammate && fence.status === "occupied"
|
|
152
|
+
? (await reportEvents.listTeamReportEvents(teamName, { agentName: params.agent_name }))
|
|
153
|
+
.filter(report => report.result?.runId === fence.tombstone.runId && report.result.repair).at(-1)
|
|
154
|
+
: undefined;
|
|
150
155
|
const details = {
|
|
151
156
|
agentName: params.agent_name,
|
|
152
157
|
alive: false,
|
|
@@ -157,12 +162,17 @@ export function registerTaskRuntimeTools(pi: any, options: TaskRuntimeToolsOptio
|
|
|
157
162
|
startupStalled: false,
|
|
158
163
|
runtime: await runtime.readRuntimeStatus(teamName, params.agent_name).catch(() => null),
|
|
159
164
|
teardownState: "quarantined",
|
|
165
|
+
...(completedReport ? { completedReport } : {}),
|
|
160
166
|
removedMember: false,
|
|
161
167
|
releasedClaims: [],
|
|
162
168
|
tombstone: fence.status === "occupied" ? fence.tombstone : undefined,
|
|
163
169
|
error: fence.status === "corrupt" ? fence.error : undefined,
|
|
164
170
|
};
|
|
165
|
-
|
|
171
|
+
const text = [formatTeammateStatusForModel(params.agent_name, details),
|
|
172
|
+
completedReport ? `Full report: ${completedReport.reportPath}; repair ledger: ${completedReport.result!.repair!.journalPath}` : undefined,
|
|
173
|
+
...(completedReport?.checks?.map(check => `Check ${check.checkId}: ${check.state}; full log: ${check.logPath}`) ?? []),
|
|
174
|
+
].filter(Boolean).join("\n\n");
|
|
175
|
+
return { content: [{ type: "text", text }], details };
|
|
166
176
|
}
|
|
167
177
|
if (options.isTeammate) throw new Error(`Agent ${params.agent_name} not found`);
|
|
168
178
|
const latestReport = (await reportEvents.listTeamReportEvents(teamName, {
|
|
@@ -177,6 +187,14 @@ export function registerTaskRuntimeTools(pi: any, options: TaskRuntimeToolsOptio
|
|
|
177
187
|
: undefined;
|
|
178
188
|
const text = [
|
|
179
189
|
`Agent ${params.agent_name} is no longer active. Recovered its latest persisted ${latestReport.status} report from ${reportPath}.`,
|
|
190
|
+
latestReport.result
|
|
191
|
+
? `Task: ${latestReport.result.outcome ?? "unspecified"}; verification: ${latestReport.result.verification.state}; acceptance: ${latestReport.result.acceptance.state}. Report ID: ${latestReport.result.reportId}.`
|
|
192
|
+
: undefined,
|
|
193
|
+
latestReport.result?.repair
|
|
194
|
+
? `Repair: ${latestReport.result.repair.state}; effective task: ${effectiveTaskOutcome(latestReport.result) ?? "unspecified"}; ledger: ${latestReport.result.repair.journalPath}.`
|
|
195
|
+
: undefined,
|
|
196
|
+
latestReport.checks?.map(check => `Check ${check.checkId}: ${check.state}; exit ${check.exitCode ?? "unknown"}; full log: ${check.logPath}`).join("\n"),
|
|
197
|
+
latestReport.result?.verification.error,
|
|
180
198
|
recoverySessionFile
|
|
181
199
|
? `Its durable child transcript is available at ${recoverySessionFile}. Use the read tool on that path if the report is incomplete.`
|
|
182
200
|
: undefined,
|
|
@@ -246,7 +264,8 @@ export function registerTaskRuntimeTools(pi: any, options: TaskRuntimeToolsOptio
|
|
|
246
264
|
removedMember: teardown?.removedMember ?? false,
|
|
247
265
|
error: teardown?.error ?? lifecycleError,
|
|
248
266
|
};
|
|
249
|
-
|
|
267
|
+
const text = [formatTeammateStatusForModel(params.agent_name, details), details.error].filter(Boolean).join("\n\n");
|
|
268
|
+
return { content: [{ type: "text", text }], details };
|
|
250
269
|
},
|
|
251
270
|
renderResult(result: any, { expanded }: any, theme: any) {
|
|
252
271
|
return renderTeammateStatus(result, expanded, theme);
|