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
|
@@ -97,6 +97,9 @@ export function createWriteAgentRuntime(options: WriteAgentRuntimeOptions) {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
async function startWriteAgent(teamName: string, member: Member, prompt: string): Promise<string> {
|
|
100
|
+
if (["checkpoint", "checkpointAssignment", "continueFrom", "continue_from"].some(field => Reflect.get(member, field) !== undefined)) {
|
|
101
|
+
throw new Error("Checkpoint-enabled agents require in-process lead admission; legacy terminal startup is unsupported.");
|
|
102
|
+
}
|
|
100
103
|
assertWriterUsesConfiguredLevel(member);
|
|
101
104
|
if (!options.terminal) {
|
|
102
105
|
throw new Error("pi-extended-teams requires running inside tmux for write agents.");
|
|
@@ -9,10 +9,12 @@ import { cleanupAgentSessionFolders, cleanupOrphanedTeams } from "../internal/se
|
|
|
9
9
|
import { summarizeSessionUsage } from "../internal/session-usage";
|
|
10
10
|
import { formatElapsed, formatTokenCount } from "../ui/renderers";
|
|
11
11
|
import { isWorkflowSpawnedMember } from "../../src/utils/workflow-metadata";
|
|
12
|
-
import {
|
|
12
|
+
import { globalSettingsPath, projectSettingsPath } from "../../src/utils/settings";
|
|
13
|
+
import { normalizeRepairPolicy } from "../../src/results/repair-policy";
|
|
13
14
|
import { generateLifecycleRunId } from "../../src/utils/lifecycle-tombstone";
|
|
14
15
|
import { cleanupStaleSessionContextReferences } from "../internal/session-context-reference";
|
|
15
16
|
import { cleanupStalePrivateAgentSessions } from "../internal/agent-session-files";
|
|
17
|
+
import { expireCheckpoints } from "../../src/results/checkpoint-retention";
|
|
16
18
|
|
|
17
19
|
export const LEAD_ORCHESTRATION_GUIDANCE = `\n\npi-extended-teams lead orchestration rules:\n- Choose tiers by the agent's intended outcome, not by vague task importance. read-review is the normal default for focused review, verification, and bounded synthesis.\n- Use read-collect when the lane gathers bounded facts without owning the conclusion. Use read-analyze when it must explain behavior or root cause across connected evidence. Reserve read-critical for irreducible high-stakes security, architecture, concurrency, migration, or data-correctness reasoning.\n- For edits, use write-patch for a narrow localized change, write-feature for a bounded feature with a known design, write-system for a cross-cutting integration/refactor within explicitly claimed files, and write-critical only for high-risk security, concurrency, recovery, migration, or data-integrity changes.\n- Prefer the canonical read-*/write-* tiers. Legacy reading-*/writing-* names are compatibility aliases for this minor release, not intent guidance.\n- A spawned agent owns its assigned lane until it reports, blocks, fails, or the user cancels it. Do not duplicate, take over, test, edit, or synthesize that same lane in parallel; work only on clearly unrelated lanes.\n- When no unrelated work remains, end the turn. The extension resumes you when a report arrives. One get_agent_status snapshot is allowed when current status is needed; do not repeatedly call it, sleep, busy-wait, loop on inbox/status, send nudges, do dummy work, or treat healthy silence as failure.\n- Wait for the actual report before synthesizing. Intervene only on a reported blocker/error, actual health failure, or explicit user cancellation/change.\n- For durable bug, security, or testing claims from an agent report or backlog, concrete, reproducible findings with file/line evidence or a focused failing regression may proceed directly to TDD repair.
|
|
18
20
|
- Use a separate read-only confirmation only when evidence is missing or weak, the claim is disputed, or irreducible high-risk uncertainty remains; never reconfirm an already confirmed finding.`;
|
|
@@ -42,6 +44,27 @@ export function isInboxFileWatchEvent(inboxFile: string, filename: string | Buff
|
|
|
42
44
|
return !changedName || changedName === inboxBase || changedName === `${inboxBase}.lock`;
|
|
43
45
|
}
|
|
44
46
|
|
|
47
|
+
function hasPersistedTeamSettings(ctx: any): boolean {
|
|
48
|
+
if (fs.existsSync(globalSettingsPath())) return true;
|
|
49
|
+
return typeof ctx.cwd === "string"
|
|
50
|
+
&& ctx.isProjectTrusted?.() === true
|
|
51
|
+
&& fs.existsSync(projectSettingsPath(ctx.cwd));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function registerAgentReportRenderer(pi: any): void {
|
|
55
|
+
pi.registerMessageRenderer?.("pi-extended-teams-report", (message: any, _renderOptions: any, theme: any) => {
|
|
56
|
+
const d = message.details || {};
|
|
57
|
+
const meta = [
|
|
58
|
+
d.elapsedMs ? formatElapsed(d.elapsedMs) : "",
|
|
59
|
+
typeof d.tokens === "number" ? `${formatTokenCount(d.tokens)} tok` : "",
|
|
60
|
+
].filter(Boolean).join(" · ");
|
|
61
|
+
const mark = d.ok === false ? theme.fg("warning", "✗") : theme.fg("success", "✓");
|
|
62
|
+
const headline = `${mark} ${d.name || "agent"} reported${meta ? ` · ${meta}` : ""}`;
|
|
63
|
+
const body = typeof message.content === "string" ? message.content : "";
|
|
64
|
+
return new Text(`${theme.bold(headline)}\n\n${body}`, 0, 0);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
45
68
|
export function registerExtensionEvents(pi: any, options: RegisterEventsOptions): void {
|
|
46
69
|
let teammateWakeIfUnread: (() => Promise<void>) | null = null;
|
|
47
70
|
let teammatePendingInboxWake = false;
|
|
@@ -122,17 +145,7 @@ export function registerExtensionEvents(pi: any, options: RegisterEventsOptions)
|
|
|
122
145
|
}
|
|
123
146
|
};
|
|
124
147
|
|
|
125
|
-
|
|
126
|
-
const d = message.details || {};
|
|
127
|
-
const meta = [
|
|
128
|
-
d.elapsedMs ? formatElapsed(d.elapsedMs) : "",
|
|
129
|
-
typeof d.tokens === "number" ? `${formatTokenCount(d.tokens)} tok` : "",
|
|
130
|
-
].filter(Boolean).join(" · ");
|
|
131
|
-
const mark = d.ok === false ? theme.fg("warning", "✗") : theme.fg("success", "✓");
|
|
132
|
-
const headline = `${mark} ${d.name || "agent"} reported${meta ? ` · ${meta}` : ""}`;
|
|
133
|
-
const body = typeof message.content === "string" ? message.content : "";
|
|
134
|
-
return new Text(`${theme.bold(headline)}\n\n${body}`, 0, 0);
|
|
135
|
-
});
|
|
148
|
+
registerAgentReportRenderer(pi);
|
|
136
149
|
|
|
137
150
|
pi.on("session_start", async (_event: any, ctx: any) => {
|
|
138
151
|
paths.ensureDirs();
|
|
@@ -163,14 +176,14 @@ export function registerExtensionEvents(pi: any, options: RegisterEventsOptions)
|
|
|
163
176
|
} catch {
|
|
164
177
|
// Session-start janitors are best-effort and must not block initialization.
|
|
165
178
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
if (
|
|
179
|
+
try {
|
|
180
|
+
for (const diagnostic of await expireCheckpoints()) ctx.ui?.notify?.(diagnostic, "warning");
|
|
181
|
+
} catch (error) {
|
|
182
|
+
ctx.ui?.notify?.(`Checkpoint expiry: ${String(error)}`, "warning");
|
|
183
|
+
}
|
|
184
|
+
if (!hasPersistedTeamSettings(ctx)) {
|
|
172
185
|
ctx.ui?.notify?.(
|
|
173
|
-
"
|
|
186
|
+
"pi-extended-teams is not configured yet. Run /pi-extended-teams-onboard for agent-led model and shared-extension setup.",
|
|
174
187
|
"warning"
|
|
175
188
|
);
|
|
176
189
|
}
|
|
@@ -399,13 +412,16 @@ export function registerExtensionEvents(pi: any, options: RegisterEventsOptions)
|
|
|
399
412
|
if (member.thinking) modelInfo += ` with thinking level: ${member.thinking}`;
|
|
400
413
|
modelInfo += `. When reporting your model or thinking level, use these exact values.`;
|
|
401
414
|
}
|
|
415
|
+
const repairGuidance = normalizeRepairPolicy(member?.repairPolicy)
|
|
416
|
+
? "Call report_and_exit when finished. If it returns an unaccepted repair request, remain active, repair only the assigned scope, and resubmit. Report blocked or failed if repair is unsafe. Claims and shutdown wait for an accepted final report."
|
|
417
|
+
: undefined;
|
|
402
418
|
if ((member?.role ?? "write") === "write") {
|
|
403
419
|
const workflowGuard = member && isWorkflowSpawnedMember(member)
|
|
404
420
|
? "\n- Workflow mode: do not create helper fanout yourself. Ask team-lead with send_message for an explicit workflow assignment."
|
|
405
421
|
: "\n- If you need read-only help, ask team-lead with send_message. The lead decides whether to spawn another agent.";
|
|
406
|
-
roleSpecificGuidance = `\n\nEdit-agent rules:\n- Before editing or writing any repository file, call claim_file with every path you intend to change and wait for the claim to be granted.\n- If claim_file reports conflicts, do not edit those files; coordinate with your lead instead.${workflowGuard}\n- Release claims with release_file as soon as you are done editing those paths.\n- When your work is finished, call report_and_exit. It sends your final report, releases any remaining file claims, and shuts you down. Do not wait for the lead to kill you
|
|
422
|
+
roleSpecificGuidance = `\n\nEdit-agent rules:\n- Before editing or writing any repository file, call claim_file with every path you intend to change and wait for the claim to be granted.\n- If claim_file reports conflicts, do not edit those files; coordinate with your lead instead.${workflowGuard}\n- Release claims with release_file as soon as you are done editing those paths.\n- ${repairGuidance ?? "When your work is finished, call report_and_exit. It sends your final report, releases any remaining file claims, and shuts you down. Do not wait for the lead to kill you."}`;
|
|
407
423
|
} else {
|
|
408
|
-
roleSpecificGuidance = `\n\nRead-agent rules:\n- You are read-only: investigate and report. Do not edit files or make any mutating changes.\n- When finished, produce your final report and stop. Do not wait for the lead to kill you
|
|
424
|
+
roleSpecificGuidance = `\n\nRead-agent rules:\n- You are read-only: investigate and report. Do not edit files or make any mutating changes.\n- ${repairGuidance ?? "When finished, produce your final report and stop. Do not wait for the lead to kill you."}`;
|
|
409
425
|
}
|
|
410
426
|
rosterInfo = `\n\n${options.formatRosterForPrompt(await options.buildRoster(teamName))}\nUse this roster as a snapshot. If you need updated roster or liveness details, ask team-lead with send_message. Do not poll.`;
|
|
411
427
|
} catch {
|