@piagent/platform 1.25.0 → 1.26.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/CHANGELOG.md +39 -2
- package/README.md +1 -1
- package/README.vi.md +1 -1
- package/docs/command-reference-vietnamese.md +2 -2
- package/docs/company-dev-commands.md +68 -0
- package/docs/distribution-standard.md +6 -6
- package/docs/harness-conformance.md +154 -0
- package/docs/languages.json +2 -2
- package/docs/managed-local-acceptance.md +38 -0
- package/docs/operator-manual-vietnamese.md +7 -7
- package/docs/publishing-for-teams.md +2 -0
- package/docs/release-install-policy.md +2 -2
- package/docs/team-onboarding.md +2 -2
- package/docs-site/architecture.html +1 -1
- package/docs-site/benchmark.html +1 -1
- package/docs-site/commands.html +1 -1
- package/docs-site/content/en/index.html +4 -4
- package/docs-site/content/en/whats-new.html +12 -0
- package/docs-site/content/index.html +4 -4
- package/docs-site/content/whats-new.html +12 -0
- package/docs-site/context-engine.html +1 -1
- package/docs-site/ecosystem.html +1 -1
- package/docs-site/en/architecture.html +1 -1
- package/docs-site/en/benchmark.html +1 -1
- package/docs-site/en/commands.html +1 -1
- package/docs-site/en/context-engine.html +1 -1
- package/docs-site/en/ecosystem.html +1 -1
- package/docs-site/en/index.html +5 -5
- package/docs-site/en/mcp-approval.html +1 -1
- package/docs-site/en/mcp-auth.html +1 -1
- package/docs-site/en/mcp-servers.html +1 -1
- package/docs-site/en/mcp.html +1 -1
- package/docs-site/en/permissions.html +1 -1
- package/docs-site/en/profiles.html +1 -1
- package/docs-site/en/quickstart.html +1 -1
- package/docs-site/en/runtime.html +1 -1
- package/docs-site/en/scope.html +1 -1
- package/docs-site/en/security.html +1 -1
- package/docs-site/en/team.html +1 -1
- package/docs-site/en/whats-new.html +13 -1
- package/docs-site/en/windows.html +1 -1
- package/docs-site/en/workflows.html +1 -1
- package/docs-site/index.html +5 -5
- package/docs-site/mcp-approval.html +1 -1
- package/docs-site/mcp-auth.html +1 -1
- package/docs-site/mcp-servers.html +1 -1
- package/docs-site/mcp.html +1 -1
- package/docs-site/permissions.html +1 -1
- package/docs-site/profiles.html +1 -1
- package/docs-site/quickstart.html +1 -1
- package/docs-site/runtime.html +1 -1
- package/docs-site/scope.html +1 -1
- package/docs-site/security.html +1 -1
- package/docs-site/team.html +1 -1
- package/docs-site/whats-new.html +13 -1
- package/docs-site/windows.html +1 -1
- package/docs-site/workflows.html +1 -1
- package/evals/private-holdout-v1/public-exposure.v2.json +2 -2
- package/package.json +1 -1
- package/packages/piagent-core/managed/background-process.mjs +101 -0
- package/packages/piagent-core/managed/checkpoints.mjs +69 -0
- package/packages/piagent-core/managed/command-tools.mjs +5 -2
- package/packages/piagent-core/managed/continuation.mjs +8 -0
- package/packages/piagent-core/managed/doctor.mjs +4 -4
- package/packages/piagent-core/managed/pi-host.mjs +19 -0
- package/packages/piagent-core/managed/sandbox-diagnostic.mjs +4 -2
- package/packages/piagent-core/managed/session.mjs +3 -3
- package/packages/piagent-core/managed/tool-boundary.mjs +45 -18
- package/packages/piagent-core/managed/tool-worker.mjs +3 -1
- package/packages/piagent-core/managed/ts-diagnostics-server.mjs +102 -0
- package/packages/piagent-core/managed/ts-diagnostics.mjs +59 -0
- package/packages/piagent-core/managed/workflow.mjs +9 -1
- package/packages/piagent-core/package.json +1 -1
- package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-B8CsDh3B.js → MarkdownMessage-BpNzOP6f.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/index-DWkb1mpZ.js +232 -0
- package/packages/piagent-webui/dist/client/index.html +1 -1
- package/packages/piagent-webui/gateway/managed-gateway.mjs +2 -1
- package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +4 -4
- package/packages/piagent-webui/server/transcript-projection.ts +9 -3
- package/packages/piagent-webui/shared/process-copy.ts +10 -0
- package/schemas/piagent-webui/transcript-v1.schema.json +13 -1
- package/scripts/company-terminal.mjs +12 -0
- package/scripts/piagent-studio.mjs +20 -7
- package/packages/piagent-webui/dist/client/assets/index-CiLLJu4R.js +0 -231
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<meta name="csp-nonce" content="__PIAGENT_CSP_NONCE__" />
|
|
8
8
|
<meta name="piagent-webui-mode" content="__PIAGENT_WEBUI_MODE__" />
|
|
9
9
|
<title>Piagent WebUI</title>
|
|
10
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
+
<script type="module" crossorigin src="/assets/index-DWkb1mpZ.js"></script>
|
|
11
11
|
<link rel="stylesheet" crossorigin href="/assets/index-B5XOKQy-.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
@@ -2,6 +2,7 @@ import { managedThinkingLevels, nearestLevel } from '../../piagent-core/managed/
|
|
|
2
2
|
import { ManagedBrokerClient } from '../../piagent-core/managed/broker-client.mjs';
|
|
3
3
|
import { ManagedSession } from '../../piagent-core/managed/session.mjs';
|
|
4
4
|
import { fastAllowed } from '../../piagent-core/managed/fast-mode.mjs';
|
|
5
|
+
import { PI_HOST_VERSION } from '../../piagent-core/managed/pi-host.mjs';
|
|
5
6
|
import fs from 'node:fs';
|
|
6
7
|
|
|
7
8
|
// A company model as the new chat page sees it: the thinking levels its
|
|
@@ -43,7 +44,7 @@ export async function startManagedGateway({ config, configPath, cwd, agentDir, p
|
|
|
43
44
|
return {session:runtime.session,dispose:()=>runtime.dispose()};
|
|
44
45
|
} catch(error) { if(runtime) await runtime.dispose(); else await broker.dispose(); throw error; }
|
|
45
46
|
};
|
|
46
|
-
const gateway=await startPiagentGateway({packageRoot,agentDir,expectedPiVersion:
|
|
47
|
+
const gateway=await startPiagentGateway({packageRoot,agentDir,expectedPiVersion:PI_HOST_VERSION,managed:{host,models,runtimeFactory:factory,project:registerProject?cwd:null}});
|
|
47
48
|
return gateway;
|
|
48
49
|
} finally { if(probe) await probe.dispose(); else await probeBroker.dispose(); }
|
|
49
50
|
}
|
|
@@ -218,8 +218,8 @@ export class SessionRuntimeSupervisor {
|
|
|
218
218
|
expectedOperationRef: string | null; messageRequestId?: string; images?: unknown[] }, sessionRevision: string, options: { deferDispatch?: boolean } = {}):
|
|
219
219
|
Promise<SessionSendResult> {
|
|
220
220
|
await this.acquire(sessionRef);
|
|
221
|
-
const active = this.#active.get(sessionRef), session = active?.runtime.session;
|
|
222
|
-
if (!active
|
|
221
|
+
const active = this.#active.get(sessionRef), session = active?.runtime.session; if (!active || !session) throw new Error("session-runtime-unavailable");
|
|
222
|
+
if (payload.delivery === "new-operation" && payload.expectedOperationRef === null && active.operationRef && !active.settling && session.isStreaming && !active.runtime.beginWireOperation) payload = { ...payload, delivery: "follow-up", expectedOperationRef: active.operationRef }; // a message from another tab waits for the running turn, as in the Terminal
|
|
223
223
|
if (payload.delivery !== "new-operation") {
|
|
224
224
|
if (active.runtime.beginWireOperation) throw new Error("provider-wire-queued-input-unsupported");
|
|
225
225
|
if (!active.operationRef || active.operationRef !== payload.expectedOperationRef || active.settling || !session.isStreaming) throw new Error("session-operation-conflict");
|
|
@@ -405,11 +405,11 @@ export class SessionRuntimeSupervisor {
|
|
|
405
405
|
await this.acquire(sessionRef);
|
|
406
406
|
const active = this.#active.get(sessionRef), session = active?.runtime.session;
|
|
407
407
|
if (!active || !session?.sessionManager) throw new Error("session-runtime-unavailable");
|
|
408
|
-
|
|
408
|
+
// One appended entry the turn neither reads nor waits on, so no busy check: renamed mid-turn, as Pi's own /name is.
|
|
409
409
|
const current = String(session.sessionManager.getSessionName?.() ?? "").trim();
|
|
410
410
|
if (current === title.trim()) return "no-change";
|
|
411
411
|
session.sessionManager.appendSessionInfo(title);
|
|
412
|
-
this.#touchCreated(sessionRef);
|
|
412
|
+
const created = this.#created.get(sessionRef); if (created) created.name = title; this.#touchCreated(sessionRef); // listed from memory until its first message
|
|
413
413
|
return "renamed";
|
|
414
414
|
}
|
|
415
415
|
async fork(sessionRef: string, entryRef: string | null, title: string | null): Promise<string> {
|
|
@@ -37,9 +37,10 @@ type TranscriptItem = { messageRef: string; parentMessageRef: string | null; rol
|
|
|
37
37
|
summary?: ToolSummary; change?: ToolChange; result?: ToolResult }>; usage?: TurnUsage; model?: string; process?: HarnessProcess; turnEnd?: TurnEnd };
|
|
38
38
|
type HarnessFinding = { severity: "blocking" | "major" | "minor"; file: string; line: number | null; issue: string };
|
|
39
39
|
type HarnessIssue = { kind: "wrong_premise" | "conflicts_with_request" | "ambiguous" | "out_of_scope"; detail: string };
|
|
40
|
-
type HarnessProcess = { phase: "plan" | "verify" | "review" | "final" | "objection" | "answer" | "claims" | "rejudge" | "dispute" | "continue"; outcome?: string; loop?: number; maxLoops?: number;
|
|
40
|
+
type HarnessProcess = { phase: "plan" | "verify" | "review" | "final" | "objection" | "answer" | "claims" | "rejudge" | "dispute" | "continue" | "undo"; outcome?: string; loop?: number; maxLoops?: number;
|
|
41
41
|
verified?: boolean; reviewed?: boolean; blockingOpen?: number; planOpen?: number; planDone?: number; planSteps?: number; round?: number; maxRounds?: number; idle?: number; planSkipped?: true; verifyPolicy?: string; reviewPolicy?: string; reviewUnavailable?: string;
|
|
42
|
-
findings?: HarnessFinding[]; role?: "scout" | "research" | "verify" | "review"; by?: "main" | "harness"; disputes?: number; unchanged?: true; issues?: HarnessIssue[]; claims?: { claim: string }[]
|
|
42
|
+
findings?: HarnessFinding[]; role?: "scout" | "research" | "verify" | "review"; by?: "main" | "harness"; disputes?: number; unchanged?: true; issues?: HarnessIssue[]; claims?: { claim: string }[];
|
|
43
|
+
undo?: { result: "done" | "refused" | "busy" | "none" | "failed"; restored: number; removed: number; files: string[]; more?: boolean } };
|
|
43
44
|
export type TranscriptDocument = { schemaVersion: 1; version: "piagent-webui-transcript-v1"; generatedAt: string; identity: TranscriptIdentity;
|
|
44
45
|
revision: TranscriptRevision; eventCursor: string; state: "ready" | "unavailable"; items: TranscriptItem[];
|
|
45
46
|
page: { beforeCursor: string | null; nextBeforeCursor: string | null; hasOlder: boolean; limit: number; truncated: boolean }; reasonCode: string | null };
|
|
@@ -197,7 +198,8 @@ function toolCalls(message: any, sessionRef: string, role: TranscriptItem["role"
|
|
|
197
198
|
const PROCESS_OUTCOMES = ["no_change", "interrupted", "disputed", "blocking_open", "unverified", "review_unavailable", "unreviewed", "clean"];
|
|
198
199
|
// A helper's objection to its brief, a failed claim, a disagreement handed to the member.
|
|
199
200
|
// "continue": the harness sent the agent back to a checklist with open steps.
|
|
200
|
-
|
|
201
|
+
// "undo": the member's /undo put the last turn's files back (checkpoints.mjs).
|
|
202
|
+
const PROCESS_PHASES = ["plan", "verify", "review", "final", "objection", "answer", "claims", "rejudge", "dispute", "continue", "undo"];
|
|
201
203
|
const ISSUE_KINDS = ["wrong_premise", "conflicts_with_request", "ambiguous", "out_of_scope"], HELPER_ROLES = ["scout", "research", "verify", "review"];
|
|
202
204
|
const POLICY_MODES = ["off", "suggest", "require"];
|
|
203
205
|
function harnessProcess(details: any): HarnessProcess | null {
|
|
@@ -233,6 +235,10 @@ function harnessProcess(details: any): HarnessProcess | null {
|
|
|
233
235
|
.map((i: any) => ({ kind: i.kind, detail: safeText(i.detail).full.slice(0, 400) }));
|
|
234
236
|
if (Array.isArray(details.claims)) out.claims = details.claims.filter((c: any) => typeof c?.claim === "string" && c.claim.trim()).slice(0, 10)
|
|
235
237
|
.map((c: any) => ({ claim: safeText(c.claim).full.slice(0, 500) }));
|
|
238
|
+
const count = (n: unknown) => Number.isInteger(n) && (n as number) >= 0 ? Math.min(n as number, 100000) : 0;
|
|
239
|
+
if (details.phase === "undo" && ["done", "refused", "busy", "none", "failed"].includes(details.undo?.result)) out.undo = { result: details.undo.result,
|
|
240
|
+
restored: count(details.undo.restored), removed: count(details.undo.removed), ...(details.undo.more === true ? { more: true } : {}),
|
|
241
|
+
files: (Array.isArray(details.undo.files) ? details.undo.files : []).filter((f: unknown) => typeof f === "string" && f).slice(0, 5).map((f: string) => safeText(f).full.slice(0, 300)) };
|
|
236
242
|
return out;
|
|
237
243
|
}
|
|
238
244
|
function role(message: any): TranscriptItem["role"] | null {
|
|
@@ -8,6 +8,7 @@ export type ProcessCopyInput = {
|
|
|
8
8
|
disputes?: number; unchanged?: boolean;
|
|
9
9
|
findings?: Array<{ severity: string; file?: string; line?: number | null; issue: string }>;
|
|
10
10
|
claims?: Array<{ claim: string }>; issues?: Array<{ kind: string; detail: string }>;
|
|
11
|
+
undo?: { result: string; restored: number; removed: number; files: string[]; more?: boolean };
|
|
11
12
|
};
|
|
12
13
|
const pick = (locale: CopyLocale, vi: string, en: string) => locale === "vi" ? vi : en;
|
|
13
14
|
const SEVERITY: Record<string, [string, string]> = { blocking: ["blocking", "blocking"], major: ["major", "major"], minor: ["minor", "minor"] };
|
|
@@ -51,6 +52,15 @@ export function headlineText(process: ProcessCopyInput, locale: CopyLocale): str
|
|
|
51
52
|
case "claims": return pick(locale, `Harness: ${who} đánh fail ${count} claim, gửi lại main agent`, `Harness: ${who} marked ${count} claim(s) as failed; sent back to the main agent`);
|
|
52
53
|
case "rejudge": return process.role === "verify" ? pick(locale, `Harness: ${who} check lại các claim cùng câu trả lời của main agent`, `Harness: ${who} checks the claims again with the main agent's answer`)
|
|
53
54
|
: pick(locale, `Harness: main agent giải thích thay vì fix, ${who} xem xét lại lời giải thích`, `Harness: the main agent answered instead of fixing; ${who} judges the answer`);
|
|
55
|
+
case "undo": {
|
|
56
|
+
const u = process.undo, files = u?.files?.length ? ` (${u.files.join(", ")})` : "";
|
|
57
|
+
if (u?.result === "done") return pick(locale, `Đã hoàn tác lượt trước: ${u.restored} file trả về như trước, ${u.removed} file lượt đó tạo đã xoá${files}.${u.more ? " Gửi /undo lần nữa để hoàn tác lượt trước nữa." : ""} Commit trong lượt đó vẫn giữ.`,
|
|
58
|
+
`Undid the last turn: ${u.restored} file(s) restored, ${u.removed} file(s) it created removed${files}.${u.more ? " Send /undo again to undo the turn before." : ""} Commits made in that turn stay.`);
|
|
59
|
+
if (u?.result === "refused") return pick(locale, `Không hoàn tác: file lượt trước đã sửa lại bị đổi tiếp sau đó${files}; hoàn tác sẽ ghi đè thay đổi đó.`, `Not undone: a file the last turn changed was changed again since${files}; undoing would overwrite that change.`);
|
|
60
|
+
if (u?.result === "busy") return pick(locale, "Đang có một lượt chạy: chờ nó xong (hoặc dừng nó) rồi /undo.", "A turn is running: wait for it (or stop it), then /undo.");
|
|
61
|
+
if (u?.result === "none") return pick(locale, "Không có lượt nào để hoàn tác (chỉ áp dụng cho project là git repository, từ khi mở cuộc trò chuyện).", "There is no turn to undo (git repositories only, since the conversation opened).");
|
|
62
|
+
return pick(locale, "Không đọc được trạng thái project; không hoàn tác.", "The project's state could not be read; nothing was undone.");
|
|
63
|
+
}
|
|
54
64
|
case "dispute": return pick(locale, `Main agent và ${who} vẫn conflict sau 2 lượt, bạn quyết định`, `The main agent and the ${who} still disagree after two rounds; your call`);
|
|
55
65
|
default: return "";
|
|
56
66
|
}
|
|
@@ -157,7 +157,19 @@
|
|
|
157
157
|
"additionalProperties": false,
|
|
158
158
|
"required": ["phase"],
|
|
159
159
|
"properties": {
|
|
160
|
-
"phase": { "enum": ["plan", "verify", "review", "final", "objection", "answer", "claims", "rejudge", "dispute", "continue"] },
|
|
160
|
+
"phase": { "enum": ["plan", "verify", "review", "final", "objection", "answer", "claims", "rejudge", "dispute", "continue", "undo"] },
|
|
161
|
+
"undo": {
|
|
162
|
+
"type": "object",
|
|
163
|
+
"additionalProperties": false,
|
|
164
|
+
"required": ["result", "restored", "removed", "files"],
|
|
165
|
+
"properties": {
|
|
166
|
+
"result": { "enum": ["done", "refused", "busy", "none", "failed"] },
|
|
167
|
+
"restored": { "type": "integer", "minimum": 0, "maximum": 100000 },
|
|
168
|
+
"removed": { "type": "integer", "minimum": 0, "maximum": 100000 },
|
|
169
|
+
"files": { "type": "array", "maxItems": 5, "items": { "type": "string", "maxLength": 300 } },
|
|
170
|
+
"more": { "type": "boolean" }
|
|
171
|
+
}
|
|
172
|
+
},
|
|
161
173
|
"outcome": { "enum": ["no_change", "interrupted", "disputed", "blocking_open", "unverified", "review_unavailable", "unreviewed", "clean"] },
|
|
162
174
|
"role": { "enum": ["scout", "research", "verify", "review"] },
|
|
163
175
|
"by": { "enum": ["main", "harness"] },
|
|
@@ -9,6 +9,7 @@ import { pathToFileURL } from 'node:url';
|
|
|
9
9
|
|
|
10
10
|
import { registerTerminalUpdateOffer } from '../packages/piagent-core/runtime/update/terminal-update-offer.mjs';
|
|
11
11
|
import { parseFailure } from '../packages/piagent-core/runtime/managed-failure.mjs';
|
|
12
|
+
import { checkpointsOf } from '../packages/piagent-core/managed/checkpoints.mjs';
|
|
12
13
|
import { companyFailureText } from '../packages/piagent-webui/shared/company-copy.ts';
|
|
13
14
|
import { headlineText, outcomeText, processItems } from '../packages/piagent-webui/shared/process-copy.ts';
|
|
14
15
|
import { turnEndCopy, turnEndOf } from '../packages/piagent-webui/shared/turn-end.ts';
|
|
@@ -83,6 +84,17 @@ export function companyTerminalExtension({ managed, packageRoot, sdkRoot, bindin
|
|
|
83
84
|
ctx.ui.notify(PERMISSION_TEXT[session.permission] ?? PERMISSION_TEXT['workspace-write'], 'info');
|
|
84
85
|
} });
|
|
85
86
|
|
|
87
|
+
// /undo: the files the last turn changed go back to how they were before
|
|
88
|
+
// it, unless one changed again since (checkpoints.mjs).
|
|
89
|
+
pi.registerCommand('undo', {
|
|
90
|
+
description: 'Hoàn tác file mà lượt trước của agent đã sửa (project là git repository)',
|
|
91
|
+
handler: async (_args, ctx) => {
|
|
92
|
+
const session = managed();
|
|
93
|
+
if (!session?.boundary) { ctx.ui.notify('Cuộc trò chuyện này chưa sẵn sàng.', 'error'); return; }
|
|
94
|
+
try { ctx.ui.notify((await checkpointsOf(session).undo()).text, 'info'); }
|
|
95
|
+
catch (error) { ctx.ui.notify(`Không hoàn tác được: ${String(error?.message ?? error).slice(0, 300)}`, 'error'); }
|
|
96
|
+
} });
|
|
97
|
+
|
|
86
98
|
// Fast mode, where the team's Harness allows it; off until the member turns it on.
|
|
87
99
|
const showFast = (ctx) => ctx.ui?.setStatus?.('agent-watch-fast', managed()?.session?.managedFastState?.() === 'on' ? 'Fast' : undefined);
|
|
88
100
|
pi.on('session_start', async (_event, ctx) => showFast(ctx));
|
|
@@ -14,12 +14,13 @@ const digest = file => createHash('sha256').update(fs.readFileSync(file)).digest
|
|
|
14
14
|
process.removeAllListeners('warning');
|
|
15
15
|
process.on('warning', warning => { if (warning.name !== 'ExperimentalWarning') process.stderr.write(`${warning.name}: ${warning.message}\n`); });
|
|
16
16
|
const args = process.argv.slice(2), flags = new Map();
|
|
17
|
-
if (args.includes('--help')) { console.log('piagent studio [--web [--no-open] | --serve | --check | --doctor | --prompt <text>] [--config <Agent Watch configuration>] [--project <folder>]\nDefaults: the configuration imported into ~/.pi/agent and the current project. Personal sessions remain under pi / piagent dashboard.'); process.exit(0); }
|
|
17
|
+
if (args.includes('--help')) { console.log('piagent studio [--web [--no-open] | --serve | --check | --doctor | --prompt <text> [--json]] [--config <Agent Watch configuration>] [--project <folder>]\nDefaults: the configuration imported into ~/.pi/agent and the current project. Personal sessions remain under pi / piagent dashboard.\n--json with --prompt writes the event stream of `pi --mode json` (JSONL on stdout; failures on stderr, exit 1).'); process.exit(0); }
|
|
18
18
|
for (let i = 0; i < args.length; i++) {
|
|
19
|
-
if (['--check', '--doctor', '--web', '--serve', '--no-open'].includes(args[i])) { flags.set(args[i], true); continue; }
|
|
19
|
+
if (['--check', '--doctor', '--web', '--serve', '--no-open', '--json'].includes(args[i])) { flags.set(args[i], true); continue; }
|
|
20
20
|
if (!['--config', '--project', '--prompt'].includes(args[i]) || flags.has(args[i]) || !args[i + 1]) throw Error('managed-launch-arguments');
|
|
21
21
|
flags.set(args[i], args[++i]);
|
|
22
22
|
}
|
|
23
|
+
if (flags.has('--json') && !flags.has('--prompt')) throw Error('managed-launch-arguments');
|
|
23
24
|
const home = os.homedir();
|
|
24
25
|
// Do this before importing the SDK: it must not discover personal keys, Node
|
|
25
26
|
// preload hooks, proxy overrides or provider endpoints from an ambient shell.
|
|
@@ -133,11 +134,23 @@ try {
|
|
|
133
134
|
const host = await api.createAgentSessionRuntime(factory, { cwd, agentDir, sessionManager: api.SessionManager.create(cwd, path.join(agentDir, 'sessions')) });
|
|
134
135
|
if (flags.get('--check')) console.log('agent-watch-auto: connected; native context; isolated tools; no inference sent.');
|
|
135
136
|
else if (flags.has('--prompt')) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
137
|
+
if (flags.has('--json')) {
|
|
138
|
+
// The event stream of `pi --mode json`, from Pi's own serializer: the
|
|
139
|
+
// session header, then every session event as one JSON line. Company
|
|
140
|
+
// events (managed_helpers, the Harness's agent-watch-process notes)
|
|
141
|
+
// come in the same stream.
|
|
142
|
+
const { toJsonEvent } = await import(pathToFileURL(path.join(config.sdk_root, 'dist/modes/json-event.js')).href);
|
|
143
|
+
const header = current.session.sessionManager.getHeader?.();
|
|
144
|
+
if (header) process.stdout.write(JSON.stringify(header) + '\n');
|
|
145
|
+
current.session.subscribe(event => process.stdout.write(JSON.stringify(toJsonEvent(event)) + '\n'));
|
|
146
|
+
await current.session.prompt(flags.get('--prompt'));
|
|
147
|
+
} else {
|
|
148
|
+
current.session.subscribe(event => {
|
|
149
|
+
if (event.type === 'message_update' && event.assistantMessageEvent.type === 'text_delta') process.stdout.write(event.assistantMessageEvent.delta);
|
|
150
|
+
if (event.type === 'message_end' && ['agent-watch-helper-receipt','agent-watch-review-status'].includes(event.message?.customType)) process.stderr.write(String(event.message.content) + '\n');
|
|
151
|
+
});
|
|
152
|
+
await current.session.prompt(flags.get('--prompt')); process.stdout.write('\n');
|
|
153
|
+
}
|
|
141
154
|
const last=current.session.messages.filter(message=>message.role==='assistant').at(-1);
|
|
142
155
|
if (last?.stopReason === 'error') {
|
|
143
156
|
// Already says who failed and why, ending in its stable [code].
|