@ponythewhite/base-context 1.0.12 → 1.0.14
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 +13 -0
- package/dist/base-context-runtime/pyproject.toml +1 -1
- package/dist/base-context-runtime/uv.lock +1 -1
- package/dist/build-info.json +1 -1
- package/dist/bundle/amazon-bedrock.js +3 -3
- package/dist/bundle/{anthropic-BJVPUMPB.js → anthropic-AXUXEET7.js} +1 -1
- package/dist/bundle/{azure-openai-responses-ERRMAXK6.js → azure-openai-responses-J3NTJKEO.js} +2 -2
- package/dist/bundle/{bundled-modules-WCGPZI2H.js → bundled-modules-UODO7ZR7.js} +5 -5
- package/dist/bundle/{chunk-FOGKLC7V.js → chunk-72LSQYUV.js} +1 -1
- package/dist/bundle/{chunk-MUFZODP5.js → chunk-EGFIZABJ.js} +1 -1
- package/dist/bundle/{chunk-AEMRBMI2.js → chunk-IEM74GZ5.js} +9 -9
- package/dist/bundle/{chunk-25VYRAC6.js → chunk-JKKXN6JE.js} +72 -0
- package/dist/bundle/{chunk-IAKHCQA2.js → chunk-NLRWERWA.js} +37 -32
- package/dist/bundle/{chunk-YGV3Y4AD.js → chunk-SX7CAXWU.js} +23 -5
- package/dist/bundle/{chunk-Q6UAHLII.js → chunk-V6LOBH6X.js} +2 -2
- package/dist/bundle/{cli-main-CTYDQHFE.js → cli-main-6GXXIMQQ.js} +4 -4
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/{google-4GA4YMUX.js → google-QLKV2ZLC.js} +2 -2
- package/dist/bundle/{google-vertex-7AMALD7D.js → google-vertex-UGLUZV6B.js} +2 -2
- package/dist/bundle/{main-GVGK354K.js → main-HF64B4HM.js} +5 -5
- package/dist/bundle/{mistral-74BXMNRM.js → mistral-2ITSLHYF.js} +1 -1
- package/dist/bundle/{openai-codex-responses-COXNC4IH.js → openai-codex-responses-FRREQXS3.js} +5 -4
- package/dist/bundle/{openai-completions-BCSA5Q6S.js → openai-completions-HF6UPPLW.js} +1 -1
- package/dist/bundle/{openai-responses-ONCIZSJS.js → openai-responses-LRTMBDFW.js} +2 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +6 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomous.d.ts +2 -0
- package/dist/core/autonomous.d.ts.map +1 -1
- package/dist/core/autonomous.js +4 -0
- package/dist/core/autonomous.js.map +1 -1
- package/dist/core/canonical-context.d.ts.map +1 -1
- package/dist/core/canonical-context.js +7 -0
- package/dist/core/canonical-context.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +1 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/public-context.d.ts.map +1 -1
- package/dist/core/public-context.js +2 -0
- package/dist/core/public-context.js.map +1 -1
- package/dist/core/view-units.d.ts.map +1 -1
- package/dist/core/view-units.js +3 -0
- package/dist/core/view-units.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/daemon/daemon-mode.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-mode.js +4 -3
- package/dist/modes/daemon/daemon-mode.js.map +1 -1
- package/dist/modes/daemon/daemon-supervisor.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-supervisor.js +11 -5
- package/dist/modes/daemon/daemon-supervisor.js.map +1 -1
- package/dist/modes/daemon/daemon-worker-protocol.d.ts +3 -0
- package/dist/modes/daemon/daemon-worker-protocol.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-worker-protocol.js +2 -0
- package/dist/modes/daemon/daemon-worker-protocol.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +24 -21
- package/dist/modes/print-mode.js.map +1 -1
- package/docs/compaction.md +36 -7
- package/docs/context-management.md +16 -10
- package/docs/json.md +14 -1
- package/docs/long-running-agents.md +23 -2
- package/docs/providers.md +17 -0
- package/docs/settings.md +20 -11
- package/package.json +4 -4
|
@@ -9,6 +9,7 @@ export declare const DAEMON_WORKER_INSTANCE_ID_ENV = "BASE_CONTEXT_INTERNAL_DAEM
|
|
|
9
9
|
export declare const DAEMON_WORKER_ACTIVE_SESSION_ID_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_ACTIVE_SESSION_ID";
|
|
10
10
|
export declare const DAEMON_WORKER_SUPERVISOR_SOCKET_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_SUPERVISOR_SOCKET";
|
|
11
11
|
export declare const DAEMON_WORKER_RECOVERY_JOURNAL_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RECOVERY_JOURNAL";
|
|
12
|
+
export declare const DAEMON_WORKER_RLM_LEDGER_SESSION_DIR_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RLM_LEDGER_SESSION_DIR";
|
|
12
13
|
export declare const DAEMON_WORKER_STARTUP_GATE_FD_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_STARTUP_GATE_FD";
|
|
13
14
|
export declare const DAEMON_WORKER_STARTUP_GATE_COMMIT = "start\n";
|
|
14
15
|
export type DaemonWorkerLifecycle = "starting" | "ready" | "recovering" | "stopping" | "failed";
|
|
@@ -179,6 +180,8 @@ export interface DaemonWorkerDescriptor {
|
|
|
179
180
|
rootSessionId?: string;
|
|
180
181
|
sessionFile?: string;
|
|
181
182
|
sessionDir?: string;
|
|
183
|
+
/** Supervisor-assigned journal scope, independent of transcript storage. */
|
|
184
|
+
rlmLedgerSessionDir?: string;
|
|
182
185
|
createdAt: string;
|
|
183
186
|
updatedAt: string;
|
|
184
187
|
lifecycle: DaemonWorkerLifecycle;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon-worker-protocol.d.ts","sourceRoot":"","sources":["../../../src/modes/daemon/daemon-worker-protocol.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,+BAA+B,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAC/G,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAE9E,OAAO,EAAE,0BAA0B,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAErG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,sBAAsB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAElG,eAAO,MAAM,sBAAsB,wCAAwC,CAAC;AAC5E,eAAO,MAAM,uBAAuB,8CAA8C,CAAC;AACnF,eAAO,MAAM,6BAA6B,oDAAoD,CAAC;AAC/F,eAAO,MAAM,mCAAmC,0DAA0D,CAAC;AAC3G,eAAO,MAAM,mCAAmC,mDAAmD,CAAC;AACpG,eAAO,MAAM,kCAAkC,yDAAyD,CAAC;AACzG,eAAO,MAAM,iCAAiC,wDAAwD,CAAC;AACvG,eAAO,MAAM,iCAAiC,YAAY,CAAC;AAC3D,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG,OAAO,GAAG,YAAY,GAAG,UAAU,GAAG,QAAQ,CAAC;AAGhG,MAAM,MAAM,0BAA0B,GACnC;IACA,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,IAAI,CAAC;CACf,GACD;IAAE,IAAI,EAAE,kBAAkB,CAAA;CAAE,CAAC;AAEhC,uFAAuF;AACvF,eAAO,MAAM,+BAA+B,iBAAiB,CAAC;AAE9D,2FAA2F;AAC3F,eAAO,MAAM,uCAAuC,mBAAmB,CAAC;AAExE,uHAAuH;AACvH,eAAO,MAAM,4BAA4B,QAAS,CAAC;AAEnD,MAAM,MAAM,uBAAuB,GAChC;IACA,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACnB,GACD;IACA,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG,0BAA0B,CAAC,MAAM,CAAC,CAAC;IAC1E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAC;IAC9C,eAAe,CAAC,EAAE,QAAQ,GAAG,aAAa,GAAG,SAAS,CAAC;CACtD,CAAC;AAEL,MAAM,WAAW,uBAAuB;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,0BAA0B,GACnC,CAAC,uBAAuB,GAAG;IAAE,EAAE,EAAE,QAAQ,CAAA;CAAE,CAAC,GAC5C,CAAC,uBAAuB,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC,GAC/D,CAAC,uBAAuB,GAAG;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC,GACzF;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5C,MAAM,WAAW,4BAA6B,SAAQ,uBAAuB;IAC5E,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,yBAAyB;IACzC,YAAY,EAAE,4BAA4B,EAAE,CAAC;CAC7C;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,yBAAyB,CAoB9F;AAED,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,aAAa,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC;AAE7E,MAAM,WAAW,0BAA0B;IAC1C,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,mBAAmB,GAAG,0BAA0B,CAMnG;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;CACzB;AAED,qFAAqF;AACrF,MAAM,MAAM,iBAAiB,GAAG;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,gBAAgB,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;AAElE,MAAM,MAAM,mBAAmB,GAC5B;IACA,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,oBAAoB,EAAE,MAAM,CAAC;CAC5B,GACD;IACA,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,kBAAkB,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACjD,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC7B,GACD;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,oBAAoB,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,gCAAgC,CAAC;IAAC,KAAK,EAAE,qBAAqB,CAAA;CAAE,GACrF;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,6BAA6B,CAAA;CAAE,GACpD;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,yBAAyB,CAAA;CAAE,GAChD;IACA,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,gCAAgC,CAAC;IACvC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACb,GACD;IACA,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,wBAAwB,CAAC;IAC/B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,yBAAyB,CAAC;IAClC,YAAY,CAAC,EAAE,+BAA+B,CAAC;CAC9C,GACD;IACA,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,uBAAuB,CAAC;IAC9B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,yBAAyB,CAAC;IAClC,YAAY,CAAC,EAAE,+BAA+B,CAAC;CAC9C,GACD;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,uBAAuB,CAAA;CAAE,GAC9C;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,sBAAsB,CAAA;CAAE,GAC7C;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,sBAAsB,CAAA;CAAE,CAAC;AAEjD,MAAM,MAAM,uBAAuB,GAAG,mBAAmB,SAAS,MAAM,QAAQ,GAC7E,QAAQ,SAAS;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,GACpB,KAAK,GACN,KAAK,CAAC;AAET,MAAM,WAAW,sBAAsB;IACtC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,qBAAqB,CAAC;IACjC,aAAa,EAAE,0BAA0B,CAAC;IAC1C,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kGAAkG;IAClG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kFAAkF;IAClF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,sBAAsB,GAAG,sBAAsB,CAuCxG;AAED,wBAAgB,qBAAqB,CAAC,WAAW,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAE3F;AAED,wBAAgB,8BAA8B,CAAC,WAAW,GAAE,MAAM,CAAC,UAAwB,GAAG,IAAI,CAmBjG;AAED,wBAAgB,sBAAsB,CAAC,WAAW,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAEvG;AAED,wBAAgB,sCAAsC,CAAC,WAAW,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAM3G;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,uBAAuB,CAuB1F","sourcesContent":["import { closeSync, readFileSync } from \"node:fs\";\nimport type { AgentSessionMessageDeliveryMode, AgentSessionMessageSender } from \"../../core/agent-messages.js\";\nimport type { IdleEvictionMinutes } from \"../../core/session-action-store.js\";\n\nexport { SESSION_LEASE_OWNER_ID_ENV, SESSION_LEASES_ENABLED_ENV } from \"../../core/session-lease.js\";\n\nimport type { WorkerRosterEntry } from \"./agent-roster.js\";\nimport type { DaemonClientCapability, DaemonCommand, DaemonOutbound } from \"./daemon-protocol.js\";\n\nexport const DAEMON_WORKER_ROLE_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER\";\nexport const DAEMON_WORKER_TOKEN_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_TOKEN\";\nexport const DAEMON_WORKER_INSTANCE_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_INSTANCE_ID\";\nexport const DAEMON_WORKER_ACTIVE_SESSION_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_ACTIVE_SESSION_ID\";\nexport const DAEMON_WORKER_SUPERVISOR_SOCKET_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_SUPERVISOR_SOCKET\";\nexport const DAEMON_WORKER_RECOVERY_JOURNAL_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RECOVERY_JOURNAL\";\nexport const DAEMON_WORKER_STARTUP_GATE_FD_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_STARTUP_GATE_FD\";\nexport const DAEMON_WORKER_STARTUP_GATE_COMMIT = \"start\\n\";\nexport type DaemonWorkerLifecycle = \"starting\" | \"ready\" | \"recovering\" | \"stopping\" | \"failed\";\n\n// Worker->supervisor roster frames live outside the client-facing DaemonOutbound schema.\nexport type DaemonWorkerRosterOutbound =\n\t| {\n\t\t\ttype: \"roster_delta\";\n\t\t\tentries: WorkerRosterEntry[];\n\t\t\tremovedAgentIds?: string[];\n\t\t\tsnapshot?: true;\n\t }\n\t| { type: \"roster_heartbeat\" };\n\n/** Advertised by new workers in the worker_auth response; absent on legacy workers. */\nexport const DAEMON_WORKER_ROSTER_CAPABILITY = \"agent_roster\";\n\n/** Advertised in the worker_auth response by workers that accept peer transport grants. */\nexport const DAEMON_WORKER_PEER_TRANSPORT_CAPABILITY = \"peer_transport\";\n\n/** Idle keepalive cadence for worker->supervisor roster frames; the supervisor staleness threshold derives from it. */\nexport const ROSTER_HEARTBEAT_INTERVAL_MS = 15_000;\n\nexport type DaemonWorkerFrameHeader =\n\t| {\n\t\t\tkind: \"command\";\n\t\t\trequestId: string;\n\t\t\tcommandType: string;\n\t }\n\t| {\n\t\t\tkind: \"outbound\";\n\t\t\trequestId?: string;\n\t\t\toutboundType: DaemonOutbound[\"type\"] | DaemonWorkerRosterOutbound[\"type\"];\n\t\t\tactiveSessionId?: string;\n\t\t\tsnapshotId?: string;\n\t\t\tsessionEventType?: string;\n\t\t\tpayloadEncoding?: \"jsonl\" | \"assistant-delta\";\n\t\t\tsnapshotPurpose?: \"attach\" | \"replacement\" | \"catchup\";\n\t };\n\nexport interface DaemonRlmCapacityOrigin {\n\tsessionFile?: string;\n\tsessionId: string;\n}\n\nexport type DaemonRlmCapacityOperation =\n\t| (DaemonRlmCapacityOrigin & { op: \"status\" })\n\t| (DaemonRlmCapacityOrigin & { op: \"set\"; maxSubagents: number })\n\t| (DaemonRlmCapacityOrigin & { op: \"reserve\"; reservationId: string; residentRoot?: true })\n\t| { op: \"release\"; reservationId: string };\n\nexport interface DaemonRlmCapacityReservation extends DaemonRlmCapacityOrigin {\n\treservationId: string;\n\tresidentRoot?: true;\n}\n\nexport interface DaemonRlmCapacitySnapshot {\n\treservations: DaemonRlmCapacityReservation[];\n}\n\nexport function isDaemonRlmCapacitySnapshot(value: unknown): value is DaemonRlmCapacitySnapshot {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"reservations\" in value &&\n\t\tArray.isArray(value.reservations) &&\n\t\tvalue.reservations.every(\n\t\t\t(entry: unknown) =>\n\t\t\t\ttypeof entry === \"object\" &&\n\t\t\t\tentry !== null &&\n\t\t\t\t\"reservationId\" in entry &&\n\t\t\t\ttypeof entry.reservationId === \"string\" &&\n\t\t\t\tentry.reservationId.length > 0 &&\n\t\t\t\t\"sessionId\" in entry &&\n\t\t\t\ttypeof entry.sessionId === \"string\" &&\n\t\t\t\tentry.sessionId.length > 0 &&\n\t\t\t\t(!(\"sessionFile\" in entry) || entry.sessionFile === undefined || typeof entry.sessionFile === \"string\") &&\n\t\t\t\t(!(\"residentRoot\" in entry) || entry.residentRoot === undefined || entry.residentRoot === true),\n\t\t)\n\t);\n}\n\nexport type DaemonCreateCommand = Extract<DaemonCommand, { type: \"create\" }>;\n\nexport interface DurableDaemonCreateCommand {\n\ttype: \"create\";\n\tsessionPath?: string;\n\tnoSession?: boolean;\n}\n\nexport function durableDaemonCreateCommand(command: DaemonCreateCommand): DurableDaemonCreateCommand {\n\treturn {\n\t\ttype: \"create\",\n\t\t...(command.sessionPath !== undefined ? { sessionPath: command.sessionPath } : {}),\n\t\t...(command.noSession !== undefined ? { noSession: command.noSession } : {}),\n\t};\n}\n\n/**\n * A single-use, worker-memory-only admission for one direct peer, scoped to one active-session\n * slot (stable across switch_session/new_session/fork) of one worker incarnation. The session pin\n * is a routing/accident guard, not a privilege boundary: ticket holders already hold supervisor\n * access, which can attach to, switch, or kill any session.\n */\nexport interface DaemonWorkerPeerGrant {\n\tgrantId: string;\n\ttoken: string;\n\texpiresAt: string;\n\tpurpose: \"session_client\";\n\tworkerInstanceId: string;\n\tactiveSessionId: string;\n\tissuerGeneration: string;\n}\n\n/** Commands a direct peer may send before it holds an authenticated session role. */\nexport type DaemonPeerCommand = {\n\tid?: string;\n\ttype: \"peer_auth\";\n\tgrantId: string;\n\ttoken: string;\n\tworkerInstanceId: string;\n\tpurpose: \"session_client\";\n};\n\nexport type DaemonPeerCommandBody = Omit<DaemonPeerCommand, \"id\">;\n\nexport type DaemonWorkerCommand =\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_auth\";\n\t\t\ttoken: string;\n\t\t\tworkerInstanceId?: string;\n\t\t\tsupervisorGeneration: string;\n\t\t\tsupervisorPid: number;\n\t\t\tsupervisorProcessStartId?: string;\n\t\t\tsupervisorSocketPath: string;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_subscribe\";\n\t\t\tactiveSessionId: string;\n\t\t\tcapabilities?: readonly DaemonClientCapability[];\n\t\t\tsupportsExtensionUi?: boolean;\n\t }\n\t| { id?: string; type: \"worker_unsubscribe\"; activeSessionId: string }\n\t| { id?: string; type: \"worker_register_peer_transport\"; grant: DaemonWorkerPeerGrant }\n\t| { id?: string; type: \"worker_archive_and_shutdown\" }\n\t| { id?: string; type: \"worker_get_rlm_capacity\" }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_passivate_idle_children\";\n\t\t\tidleEvictionMinutes: IdleEvictionMinutes;\n\t\t\tnow: number;\n\t\t\tlimit: number;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_message\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tmessage: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_result\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tsummary: string;\n\t\t\tfindings: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| { id?: string; type: \"worker_prepare_update\" }\n\t| { id?: string; type: \"worker_commit_update\" }\n\t| { id?: string; type: \"worker_cancel_update\" };\n\nexport type DaemonWorkerCommandBody = DaemonWorkerCommand extends infer TCommand\n\t? TCommand extends { id?: string }\n\t\t? Omit<TCommand, \"id\">\n\t\t: never\n\t: never;\n\nexport interface DaemonWorkerDescriptor {\n\tversion: 1 | 2;\n\tworkerId: string;\n\tpid: number;\n\tprocessStartId?: string;\n\tsocketPath: string;\n\trecoveryJournalPath: string;\n\torphanProcessJournalPath?: string;\n\tsupervisorSocketPath: string;\n\tauthenticationToken: string;\n\tworkerInstanceId?: string;\n\trootActiveSessionId: string;\n\t/** Stable protocol client that owns this worker. Omitted for resident sessions. */\n\townerClientId?: string;\n\trootSessionId?: string;\n\tsessionFile?: string;\n\tsessionDir?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlifecycle: DaemonWorkerLifecycle;\n\tcreateCommand: DurableDaemonCreateCommand;\n\tconsecutiveFailures: number;\n\t/** Durable intent written before root termination so replacement supervisors never recover it. */\n\tstopRequestedAt?: string;\n\t/** Complete the root's archived lifecycle state after its process has stopped. */\n\tarchiveOnStop?: boolean;\n\tlastFailureAt?: string;\n\tlastError?: string;\n}\n\nexport function durableDaemonWorkerDescriptor(descriptor: DaemonWorkerDescriptor): DaemonWorkerDescriptor {\n\tconst versionOneCreateCommand = descriptor.createCommand as unknown as { config?: unknown };\n\tconst versionOneConfig =\n\t\tdescriptor.version === 1 &&\n\t\ttypeof versionOneCreateCommand.config === \"object\" &&\n\t\tversionOneCreateCommand.config !== null\n\t\t\t? (versionOneCreateCommand.config as Record<string, unknown>)\n\t\t\t: undefined;\n\tconst sessionDir =\n\t\tdescriptor.sessionDir ??\n\t\t(typeof versionOneConfig?.sessionDir === \"string\" ? versionOneConfig.sessionDir : undefined);\n\treturn {\n\t\tversion: 2,\n\t\tworkerId: descriptor.workerId,\n\t\tpid: descriptor.pid,\n\t\t...(descriptor.processStartId !== undefined ? { processStartId: descriptor.processStartId } : {}),\n\t\tsocketPath: descriptor.socketPath,\n\t\trecoveryJournalPath: descriptor.recoveryJournalPath,\n\t\t...(descriptor.orphanProcessJournalPath !== undefined\n\t\t\t? { orphanProcessJournalPath: descriptor.orphanProcessJournalPath }\n\t\t\t: {}),\n\t\tsupervisorSocketPath: descriptor.supervisorSocketPath,\n\t\tauthenticationToken: descriptor.authenticationToken,\n\t\t...(descriptor.workerInstanceId !== undefined ? { workerInstanceId: descriptor.workerInstanceId } : {}),\n\t\trootActiveSessionId: descriptor.rootActiveSessionId,\n\t\t...(descriptor.ownerClientId !== undefined ? { ownerClientId: descriptor.ownerClientId } : {}),\n\t\t...(descriptor.rootSessionId !== undefined ? { rootSessionId: descriptor.rootSessionId } : {}),\n\t\t...(descriptor.sessionFile !== undefined ? { sessionFile: descriptor.sessionFile } : {}),\n\t\t...(sessionDir !== undefined ? { sessionDir } : {}),\n\t\tcreatedAt: descriptor.createdAt,\n\t\tupdatedAt: descriptor.updatedAt,\n\t\tlifecycle: descriptor.lifecycle,\n\t\tcreateCommand: durableDaemonCreateCommand(descriptor.createCommand),\n\t\tconsecutiveFailures: descriptor.consecutiveFailures,\n\t\t...(descriptor.stopRequestedAt !== undefined ? { stopRequestedAt: descriptor.stopRequestedAt } : {}),\n\t\t...(descriptor.archiveOnStop !== undefined ? { archiveOnStop: descriptor.archiveOnStop } : {}),\n\t\t...(descriptor.lastFailureAt !== undefined ? { lastFailureAt: descriptor.lastFailureAt } : {}),\n\t\t...(descriptor.lifecycle === \"failed\" ? { lastError: \"Waiting for a client with fresh runtime context\" } : {}),\n\t};\n}\n\nexport function isDaemonWorkerProcess(environment: NodeJS.ProcessEnv = process.env): boolean {\n\treturn environment[DAEMON_WORKER_ROLE_ENV] === \"1\";\n}\n\nexport function waitForDaemonWorkerStartupGate(environment: NodeJS.ProcessEnv = process.env): void {\n\tconst rawFd = environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tif (rawFd === undefined) {\n\t\treturn;\n\t}\n\tdelete environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tconst fd = Number(rawFd);\n\tif (!Number.isInteger(fd) || fd < 3) {\n\t\tthrow new Error(\"Daemon session worker has an invalid startup gate\");\n\t}\n\tlet marker: string;\n\ttry {\n\t\tmarker = readFileSync(fd, \"utf8\");\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n\tif (marker !== DAEMON_WORKER_STARTUP_GATE_COMMIT) {\n\t\tthrow new Error(\"Daemon session worker startup was cancelled\");\n\t}\n}\n\nexport function daemonWorkerInstanceId(environment: NodeJS.ProcessEnv = process.env): string | undefined {\n\treturn environment[DAEMON_WORKER_INSTANCE_ID_ENV] || undefined;\n}\n\nexport function requireDaemonWorkerAuthenticationToken(environment: NodeJS.ProcessEnv = process.env): string {\n\tconst token = environment[DAEMON_WORKER_TOKEN_ENV];\n\tif (!token) {\n\t\tthrow new Error(\"Daemon session worker is missing its authentication token\");\n\t}\n\treturn token;\n}\n\nexport function isDaemonWorkerFrameHeader(value: unknown): value is DaemonWorkerFrameHeader {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\tconst candidate = value as Record<string, unknown>;\n\tif (candidate.kind === \"command\") {\n\t\treturn typeof candidate.requestId === \"string\" && typeof candidate.commandType === \"string\";\n\t}\n\treturn (\n\t\tcandidate.kind === \"outbound\" &&\n\t\ttypeof candidate.outboundType === \"string\" &&\n\t\t(candidate.requestId === undefined || typeof candidate.requestId === \"string\") &&\n\t\t(candidate.activeSessionId === undefined || typeof candidate.activeSessionId === \"string\") &&\n\t\t(candidate.snapshotId === undefined || typeof candidate.snapshotId === \"string\") &&\n\t\t(candidate.sessionEventType === undefined || typeof candidate.sessionEventType === \"string\") &&\n\t\t(candidate.snapshotPurpose === undefined ||\n\t\t\tcandidate.snapshotPurpose === \"attach\" ||\n\t\t\tcandidate.snapshotPurpose === \"replacement\" ||\n\t\t\tcandidate.snapshotPurpose === \"catchup\") &&\n\t\t(candidate.payloadEncoding === undefined ||\n\t\t\tcandidate.payloadEncoding === \"jsonl\" ||\n\t\t\tcandidate.payloadEncoding === \"assistant-delta\")\n\t);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"daemon-worker-protocol.d.ts","sourceRoot":"","sources":["../../../src/modes/daemon/daemon-worker-protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { closeSync, readFileSync } from \"node:fs\";\nimport type { AgentSessionMessageDeliveryMode, AgentSessionMessageSender } from \"../../core/agent-messages.js\";\nimport type { IdleEvictionMinutes } from \"../../core/session-action-store.js\";\n\nexport { SESSION_LEASE_OWNER_ID_ENV, SESSION_LEASES_ENABLED_ENV } from \"../../core/session-lease.js\";\n\nimport type { WorkerRosterEntry } from \"./agent-roster.js\";\nimport type { DaemonClientCapability, DaemonCommand, DaemonOutbound } from \"./daemon-protocol.js\";\n\nexport const DAEMON_WORKER_ROLE_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER\";\nexport const DAEMON_WORKER_TOKEN_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_TOKEN\";\nexport const DAEMON_WORKER_INSTANCE_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_INSTANCE_ID\";\nexport const DAEMON_WORKER_ACTIVE_SESSION_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_ACTIVE_SESSION_ID\";\nexport const DAEMON_WORKER_SUPERVISOR_SOCKET_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_SUPERVISOR_SOCKET\";\nexport const DAEMON_WORKER_RECOVERY_JOURNAL_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RECOVERY_JOURNAL\";\nexport const DAEMON_WORKER_RLM_LEDGER_SESSION_DIR_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RLM_LEDGER_SESSION_DIR\";\nexport const DAEMON_WORKER_STARTUP_GATE_FD_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_STARTUP_GATE_FD\";\nexport const DAEMON_WORKER_STARTUP_GATE_COMMIT = \"start\\n\";\nexport type DaemonWorkerLifecycle = \"starting\" | \"ready\" | \"recovering\" | \"stopping\" | \"failed\";\n\n// Worker->supervisor roster frames live outside the client-facing DaemonOutbound schema.\nexport type DaemonWorkerRosterOutbound =\n\t| {\n\t\t\ttype: \"roster_delta\";\n\t\t\tentries: WorkerRosterEntry[];\n\t\t\tremovedAgentIds?: string[];\n\t\t\tsnapshot?: true;\n\t }\n\t| { type: \"roster_heartbeat\" };\n\n/** Advertised by new workers in the worker_auth response; absent on legacy workers. */\nexport const DAEMON_WORKER_ROSTER_CAPABILITY = \"agent_roster\";\n\n/** Advertised in the worker_auth response by workers that accept peer transport grants. */\nexport const DAEMON_WORKER_PEER_TRANSPORT_CAPABILITY = \"peer_transport\";\n\n/** Idle keepalive cadence for worker->supervisor roster frames; the supervisor staleness threshold derives from it. */\nexport const ROSTER_HEARTBEAT_INTERVAL_MS = 15_000;\n\nexport type DaemonWorkerFrameHeader =\n\t| {\n\t\t\tkind: \"command\";\n\t\t\trequestId: string;\n\t\t\tcommandType: string;\n\t }\n\t| {\n\t\t\tkind: \"outbound\";\n\t\t\trequestId?: string;\n\t\t\toutboundType: DaemonOutbound[\"type\"] | DaemonWorkerRosterOutbound[\"type\"];\n\t\t\tactiveSessionId?: string;\n\t\t\tsnapshotId?: string;\n\t\t\tsessionEventType?: string;\n\t\t\tpayloadEncoding?: \"jsonl\" | \"assistant-delta\";\n\t\t\tsnapshotPurpose?: \"attach\" | \"replacement\" | \"catchup\";\n\t };\n\nexport interface DaemonRlmCapacityOrigin {\n\tsessionFile?: string;\n\tsessionId: string;\n}\n\nexport type DaemonRlmCapacityOperation =\n\t| (DaemonRlmCapacityOrigin & { op: \"status\" })\n\t| (DaemonRlmCapacityOrigin & { op: \"set\"; maxSubagents: number })\n\t| (DaemonRlmCapacityOrigin & { op: \"reserve\"; reservationId: string; residentRoot?: true })\n\t| { op: \"release\"; reservationId: string };\n\nexport interface DaemonRlmCapacityReservation extends DaemonRlmCapacityOrigin {\n\treservationId: string;\n\tresidentRoot?: true;\n}\n\nexport interface DaemonRlmCapacitySnapshot {\n\treservations: DaemonRlmCapacityReservation[];\n}\n\nexport function isDaemonRlmCapacitySnapshot(value: unknown): value is DaemonRlmCapacitySnapshot {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"reservations\" in value &&\n\t\tArray.isArray(value.reservations) &&\n\t\tvalue.reservations.every(\n\t\t\t(entry: unknown) =>\n\t\t\t\ttypeof entry === \"object\" &&\n\t\t\t\tentry !== null &&\n\t\t\t\t\"reservationId\" in entry &&\n\t\t\t\ttypeof entry.reservationId === \"string\" &&\n\t\t\t\tentry.reservationId.length > 0 &&\n\t\t\t\t\"sessionId\" in entry &&\n\t\t\t\ttypeof entry.sessionId === \"string\" &&\n\t\t\t\tentry.sessionId.length > 0 &&\n\t\t\t\t(!(\"sessionFile\" in entry) || entry.sessionFile === undefined || typeof entry.sessionFile === \"string\") &&\n\t\t\t\t(!(\"residentRoot\" in entry) || entry.residentRoot === undefined || entry.residentRoot === true),\n\t\t)\n\t);\n}\n\nexport type DaemonCreateCommand = Extract<DaemonCommand, { type: \"create\" }>;\n\nexport interface DurableDaemonCreateCommand {\n\ttype: \"create\";\n\tsessionPath?: string;\n\tnoSession?: boolean;\n}\n\nexport function durableDaemonCreateCommand(command: DaemonCreateCommand): DurableDaemonCreateCommand {\n\treturn {\n\t\ttype: \"create\",\n\t\t...(command.sessionPath !== undefined ? { sessionPath: command.sessionPath } : {}),\n\t\t...(command.noSession !== undefined ? { noSession: command.noSession } : {}),\n\t};\n}\n\n/**\n * A single-use, worker-memory-only admission for one direct peer, scoped to one active-session\n * slot (stable across switch_session/new_session/fork) of one worker incarnation. The session pin\n * is a routing/accident guard, not a privilege boundary: ticket holders already hold supervisor\n * access, which can attach to, switch, or kill any session.\n */\nexport interface DaemonWorkerPeerGrant {\n\tgrantId: string;\n\ttoken: string;\n\texpiresAt: string;\n\tpurpose: \"session_client\";\n\tworkerInstanceId: string;\n\tactiveSessionId: string;\n\tissuerGeneration: string;\n}\n\n/** Commands a direct peer may send before it holds an authenticated session role. */\nexport type DaemonPeerCommand = {\n\tid?: string;\n\ttype: \"peer_auth\";\n\tgrantId: string;\n\ttoken: string;\n\tworkerInstanceId: string;\n\tpurpose: \"session_client\";\n};\n\nexport type DaemonPeerCommandBody = Omit<DaemonPeerCommand, \"id\">;\n\nexport type DaemonWorkerCommand =\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_auth\";\n\t\t\ttoken: string;\n\t\t\tworkerInstanceId?: string;\n\t\t\tsupervisorGeneration: string;\n\t\t\tsupervisorPid: number;\n\t\t\tsupervisorProcessStartId?: string;\n\t\t\tsupervisorSocketPath: string;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_subscribe\";\n\t\t\tactiveSessionId: string;\n\t\t\tcapabilities?: readonly DaemonClientCapability[];\n\t\t\tsupportsExtensionUi?: boolean;\n\t }\n\t| { id?: string; type: \"worker_unsubscribe\"; activeSessionId: string }\n\t| { id?: string; type: \"worker_register_peer_transport\"; grant: DaemonWorkerPeerGrant }\n\t| { id?: string; type: \"worker_archive_and_shutdown\" }\n\t| { id?: string; type: \"worker_get_rlm_capacity\" }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_passivate_idle_children\";\n\t\t\tidleEvictionMinutes: IdleEvictionMinutes;\n\t\t\tnow: number;\n\t\t\tlimit: number;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_message\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tmessage: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_result\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tsummary: string;\n\t\t\tfindings: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| { id?: string; type: \"worker_prepare_update\" }\n\t| { id?: string; type: \"worker_commit_update\" }\n\t| { id?: string; type: \"worker_cancel_update\" };\n\nexport type DaemonWorkerCommandBody = DaemonWorkerCommand extends infer TCommand\n\t? TCommand extends { id?: string }\n\t\t? Omit<TCommand, \"id\">\n\t\t: never\n\t: never;\n\nexport interface DaemonWorkerDescriptor {\n\tversion: 1 | 2;\n\tworkerId: string;\n\tpid: number;\n\tprocessStartId?: string;\n\tsocketPath: string;\n\trecoveryJournalPath: string;\n\torphanProcessJournalPath?: string;\n\tsupervisorSocketPath: string;\n\tauthenticationToken: string;\n\tworkerInstanceId?: string;\n\trootActiveSessionId: string;\n\t/** Stable protocol client that owns this worker. Omitted for resident sessions. */\n\townerClientId?: string;\n\trootSessionId?: string;\n\tsessionFile?: string;\n\tsessionDir?: string;\n\t/** Supervisor-assigned journal scope, independent of transcript storage. */\n\trlmLedgerSessionDir?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlifecycle: DaemonWorkerLifecycle;\n\tcreateCommand: DurableDaemonCreateCommand;\n\tconsecutiveFailures: number;\n\t/** Durable intent written before root termination so replacement supervisors never recover it. */\n\tstopRequestedAt?: string;\n\t/** Complete the root's archived lifecycle state after its process has stopped. */\n\tarchiveOnStop?: boolean;\n\tlastFailureAt?: string;\n\tlastError?: string;\n}\n\nexport function durableDaemonWorkerDescriptor(descriptor: DaemonWorkerDescriptor): DaemonWorkerDescriptor {\n\tconst versionOneCreateCommand = descriptor.createCommand as unknown as { config?: unknown };\n\tconst versionOneConfig =\n\t\tdescriptor.version === 1 &&\n\t\ttypeof versionOneCreateCommand.config === \"object\" &&\n\t\tversionOneCreateCommand.config !== null\n\t\t\t? (versionOneCreateCommand.config as Record<string, unknown>)\n\t\t\t: undefined;\n\tconst sessionDir =\n\t\tdescriptor.sessionDir ??\n\t\t(typeof versionOneConfig?.sessionDir === \"string\" ? versionOneConfig.sessionDir : undefined);\n\treturn {\n\t\tversion: 2,\n\t\tworkerId: descriptor.workerId,\n\t\tpid: descriptor.pid,\n\t\t...(descriptor.processStartId !== undefined ? { processStartId: descriptor.processStartId } : {}),\n\t\tsocketPath: descriptor.socketPath,\n\t\trecoveryJournalPath: descriptor.recoveryJournalPath,\n\t\t...(descriptor.orphanProcessJournalPath !== undefined\n\t\t\t? { orphanProcessJournalPath: descriptor.orphanProcessJournalPath }\n\t\t\t: {}),\n\t\tsupervisorSocketPath: descriptor.supervisorSocketPath,\n\t\tauthenticationToken: descriptor.authenticationToken,\n\t\t...(descriptor.workerInstanceId !== undefined ? { workerInstanceId: descriptor.workerInstanceId } : {}),\n\t\trootActiveSessionId: descriptor.rootActiveSessionId,\n\t\t...(descriptor.ownerClientId !== undefined ? { ownerClientId: descriptor.ownerClientId } : {}),\n\t\t...(descriptor.rootSessionId !== undefined ? { rootSessionId: descriptor.rootSessionId } : {}),\n\t\t...(descriptor.sessionFile !== undefined ? { sessionFile: descriptor.sessionFile } : {}),\n\t\t...(sessionDir !== undefined ? { sessionDir } : {}),\n\t\t...(descriptor.rlmLedgerSessionDir !== undefined ? { rlmLedgerSessionDir: descriptor.rlmLedgerSessionDir } : {}),\n\t\tcreatedAt: descriptor.createdAt,\n\t\tupdatedAt: descriptor.updatedAt,\n\t\tlifecycle: descriptor.lifecycle,\n\t\tcreateCommand: durableDaemonCreateCommand(descriptor.createCommand),\n\t\tconsecutiveFailures: descriptor.consecutiveFailures,\n\t\t...(descriptor.stopRequestedAt !== undefined ? { stopRequestedAt: descriptor.stopRequestedAt } : {}),\n\t\t...(descriptor.archiveOnStop !== undefined ? { archiveOnStop: descriptor.archiveOnStop } : {}),\n\t\t...(descriptor.lastFailureAt !== undefined ? { lastFailureAt: descriptor.lastFailureAt } : {}),\n\t\t...(descriptor.lifecycle === \"failed\" ? { lastError: \"Waiting for a client with fresh runtime context\" } : {}),\n\t};\n}\n\nexport function isDaemonWorkerProcess(environment: NodeJS.ProcessEnv = process.env): boolean {\n\treturn environment[DAEMON_WORKER_ROLE_ENV] === \"1\";\n}\n\nexport function waitForDaemonWorkerStartupGate(environment: NodeJS.ProcessEnv = process.env): void {\n\tconst rawFd = environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tif (rawFd === undefined) {\n\t\treturn;\n\t}\n\tdelete environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tconst fd = Number(rawFd);\n\tif (!Number.isInteger(fd) || fd < 3) {\n\t\tthrow new Error(\"Daemon session worker has an invalid startup gate\");\n\t}\n\tlet marker: string;\n\ttry {\n\t\tmarker = readFileSync(fd, \"utf8\");\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n\tif (marker !== DAEMON_WORKER_STARTUP_GATE_COMMIT) {\n\t\tthrow new Error(\"Daemon session worker startup was cancelled\");\n\t}\n}\n\nexport function daemonWorkerInstanceId(environment: NodeJS.ProcessEnv = process.env): string | undefined {\n\treturn environment[DAEMON_WORKER_INSTANCE_ID_ENV] || undefined;\n}\n\nexport function requireDaemonWorkerAuthenticationToken(environment: NodeJS.ProcessEnv = process.env): string {\n\tconst token = environment[DAEMON_WORKER_TOKEN_ENV];\n\tif (!token) {\n\t\tthrow new Error(\"Daemon session worker is missing its authentication token\");\n\t}\n\treturn token;\n}\n\nexport function isDaemonWorkerFrameHeader(value: unknown): value is DaemonWorkerFrameHeader {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\tconst candidate = value as Record<string, unknown>;\n\tif (candidate.kind === \"command\") {\n\t\treturn typeof candidate.requestId === \"string\" && typeof candidate.commandType === \"string\";\n\t}\n\treturn (\n\t\tcandidate.kind === \"outbound\" &&\n\t\ttypeof candidate.outboundType === \"string\" &&\n\t\t(candidate.requestId === undefined || typeof candidate.requestId === \"string\") &&\n\t\t(candidate.activeSessionId === undefined || typeof candidate.activeSessionId === \"string\") &&\n\t\t(candidate.snapshotId === undefined || typeof candidate.snapshotId === \"string\") &&\n\t\t(candidate.sessionEventType === undefined || typeof candidate.sessionEventType === \"string\") &&\n\t\t(candidate.snapshotPurpose === undefined ||\n\t\t\tcandidate.snapshotPurpose === \"attach\" ||\n\t\t\tcandidate.snapshotPurpose === \"replacement\" ||\n\t\t\tcandidate.snapshotPurpose === \"catchup\") &&\n\t\t(candidate.payloadEncoding === undefined ||\n\t\t\tcandidate.payloadEncoding === \"jsonl\" ||\n\t\t\tcandidate.payloadEncoding === \"assistant-delta\")\n\t);\n}\n"]}
|
|
@@ -6,6 +6,7 @@ export const DAEMON_WORKER_INSTANCE_ID_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKE
|
|
|
6
6
|
export const DAEMON_WORKER_ACTIVE_SESSION_ID_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_ACTIVE_SESSION_ID";
|
|
7
7
|
export const DAEMON_WORKER_SUPERVISOR_SOCKET_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_SUPERVISOR_SOCKET";
|
|
8
8
|
export const DAEMON_WORKER_RECOVERY_JOURNAL_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RECOVERY_JOURNAL";
|
|
9
|
+
export const DAEMON_WORKER_RLM_LEDGER_SESSION_DIR_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RLM_LEDGER_SESSION_DIR";
|
|
9
10
|
export const DAEMON_WORKER_STARTUP_GATE_FD_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_STARTUP_GATE_FD";
|
|
10
11
|
export const DAEMON_WORKER_STARTUP_GATE_COMMIT = "start\n";
|
|
11
12
|
/** Advertised by new workers in the worker_auth response; absent on legacy workers. */
|
|
@@ -64,6 +65,7 @@ export function durableDaemonWorkerDescriptor(descriptor) {
|
|
|
64
65
|
...(descriptor.rootSessionId !== undefined ? { rootSessionId: descriptor.rootSessionId } : {}),
|
|
65
66
|
...(descriptor.sessionFile !== undefined ? { sessionFile: descriptor.sessionFile } : {}),
|
|
66
67
|
...(sessionDir !== undefined ? { sessionDir } : {}),
|
|
68
|
+
...(descriptor.rlmLedgerSessionDir !== undefined ? { rlmLedgerSessionDir: descriptor.rlmLedgerSessionDir } : {}),
|
|
67
69
|
createdAt: descriptor.createdAt,
|
|
68
70
|
updatedAt: descriptor.updatedAt,
|
|
69
71
|
lifecycle: descriptor.lifecycle,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon-worker-protocol.js","sourceRoot":"","sources":["../../../src/modes/daemon/daemon-worker-protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { closeSync, readFileSync } from \"node:fs\";\nimport type { AgentSessionMessageDeliveryMode, AgentSessionMessageSender } from \"../../core/agent-messages.js\";\nimport type { IdleEvictionMinutes } from \"../../core/session-action-store.js\";\n\nexport { SESSION_LEASE_OWNER_ID_ENV, SESSION_LEASES_ENABLED_ENV } from \"../../core/session-lease.js\";\n\nimport type { WorkerRosterEntry } from \"./agent-roster.js\";\nimport type { DaemonClientCapability, DaemonCommand, DaemonOutbound } from \"./daemon-protocol.js\";\n\nexport const DAEMON_WORKER_ROLE_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER\";\nexport const DAEMON_WORKER_TOKEN_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_TOKEN\";\nexport const DAEMON_WORKER_INSTANCE_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_INSTANCE_ID\";\nexport const DAEMON_WORKER_ACTIVE_SESSION_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_ACTIVE_SESSION_ID\";\nexport const DAEMON_WORKER_SUPERVISOR_SOCKET_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_SUPERVISOR_SOCKET\";\nexport const DAEMON_WORKER_RECOVERY_JOURNAL_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RECOVERY_JOURNAL\";\nexport const DAEMON_WORKER_STARTUP_GATE_FD_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_STARTUP_GATE_FD\";\nexport const DAEMON_WORKER_STARTUP_GATE_COMMIT = \"start\\n\";\nexport type DaemonWorkerLifecycle = \"starting\" | \"ready\" | \"recovering\" | \"stopping\" | \"failed\";\n\n// Worker->supervisor roster frames live outside the client-facing DaemonOutbound schema.\nexport type DaemonWorkerRosterOutbound =\n\t| {\n\t\t\ttype: \"roster_delta\";\n\t\t\tentries: WorkerRosterEntry[];\n\t\t\tremovedAgentIds?: string[];\n\t\t\tsnapshot?: true;\n\t }\n\t| { type: \"roster_heartbeat\" };\n\n/** Advertised by new workers in the worker_auth response; absent on legacy workers. */\nexport const DAEMON_WORKER_ROSTER_CAPABILITY = \"agent_roster\";\n\n/** Advertised in the worker_auth response by workers that accept peer transport grants. */\nexport const DAEMON_WORKER_PEER_TRANSPORT_CAPABILITY = \"peer_transport\";\n\n/** Idle keepalive cadence for worker->supervisor roster frames; the supervisor staleness threshold derives from it. */\nexport const ROSTER_HEARTBEAT_INTERVAL_MS = 15_000;\n\nexport type DaemonWorkerFrameHeader =\n\t| {\n\t\t\tkind: \"command\";\n\t\t\trequestId: string;\n\t\t\tcommandType: string;\n\t }\n\t| {\n\t\t\tkind: \"outbound\";\n\t\t\trequestId?: string;\n\t\t\toutboundType: DaemonOutbound[\"type\"] | DaemonWorkerRosterOutbound[\"type\"];\n\t\t\tactiveSessionId?: string;\n\t\t\tsnapshotId?: string;\n\t\t\tsessionEventType?: string;\n\t\t\tpayloadEncoding?: \"jsonl\" | \"assistant-delta\";\n\t\t\tsnapshotPurpose?: \"attach\" | \"replacement\" | \"catchup\";\n\t };\n\nexport interface DaemonRlmCapacityOrigin {\n\tsessionFile?: string;\n\tsessionId: string;\n}\n\nexport type DaemonRlmCapacityOperation =\n\t| (DaemonRlmCapacityOrigin & { op: \"status\" })\n\t| (DaemonRlmCapacityOrigin & { op: \"set\"; maxSubagents: number })\n\t| (DaemonRlmCapacityOrigin & { op: \"reserve\"; reservationId: string; residentRoot?: true })\n\t| { op: \"release\"; reservationId: string };\n\nexport interface DaemonRlmCapacityReservation extends DaemonRlmCapacityOrigin {\n\treservationId: string;\n\tresidentRoot?: true;\n}\n\nexport interface DaemonRlmCapacitySnapshot {\n\treservations: DaemonRlmCapacityReservation[];\n}\n\nexport function isDaemonRlmCapacitySnapshot(value: unknown): value is DaemonRlmCapacitySnapshot {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"reservations\" in value &&\n\t\tArray.isArray(value.reservations) &&\n\t\tvalue.reservations.every(\n\t\t\t(entry: unknown) =>\n\t\t\t\ttypeof entry === \"object\" &&\n\t\t\t\tentry !== null &&\n\t\t\t\t\"reservationId\" in entry &&\n\t\t\t\ttypeof entry.reservationId === \"string\" &&\n\t\t\t\tentry.reservationId.length > 0 &&\n\t\t\t\t\"sessionId\" in entry &&\n\t\t\t\ttypeof entry.sessionId === \"string\" &&\n\t\t\t\tentry.sessionId.length > 0 &&\n\t\t\t\t(!(\"sessionFile\" in entry) || entry.sessionFile === undefined || typeof entry.sessionFile === \"string\") &&\n\t\t\t\t(!(\"residentRoot\" in entry) || entry.residentRoot === undefined || entry.residentRoot === true),\n\t\t)\n\t);\n}\n\nexport type DaemonCreateCommand = Extract<DaemonCommand, { type: \"create\" }>;\n\nexport interface DurableDaemonCreateCommand {\n\ttype: \"create\";\n\tsessionPath?: string;\n\tnoSession?: boolean;\n}\n\nexport function durableDaemonCreateCommand(command: DaemonCreateCommand): DurableDaemonCreateCommand {\n\treturn {\n\t\ttype: \"create\",\n\t\t...(command.sessionPath !== undefined ? { sessionPath: command.sessionPath } : {}),\n\t\t...(command.noSession !== undefined ? { noSession: command.noSession } : {}),\n\t};\n}\n\n/**\n * A single-use, worker-memory-only admission for one direct peer, scoped to one active-session\n * slot (stable across switch_session/new_session/fork) of one worker incarnation. The session pin\n * is a routing/accident guard, not a privilege boundary: ticket holders already hold supervisor\n * access, which can attach to, switch, or kill any session.\n */\nexport interface DaemonWorkerPeerGrant {\n\tgrantId: string;\n\ttoken: string;\n\texpiresAt: string;\n\tpurpose: \"session_client\";\n\tworkerInstanceId: string;\n\tactiveSessionId: string;\n\tissuerGeneration: string;\n}\n\n/** Commands a direct peer may send before it holds an authenticated session role. */\nexport type DaemonPeerCommand = {\n\tid?: string;\n\ttype: \"peer_auth\";\n\tgrantId: string;\n\ttoken: string;\n\tworkerInstanceId: string;\n\tpurpose: \"session_client\";\n};\n\nexport type DaemonPeerCommandBody = Omit<DaemonPeerCommand, \"id\">;\n\nexport type DaemonWorkerCommand =\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_auth\";\n\t\t\ttoken: string;\n\t\t\tworkerInstanceId?: string;\n\t\t\tsupervisorGeneration: string;\n\t\t\tsupervisorPid: number;\n\t\t\tsupervisorProcessStartId?: string;\n\t\t\tsupervisorSocketPath: string;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_subscribe\";\n\t\t\tactiveSessionId: string;\n\t\t\tcapabilities?: readonly DaemonClientCapability[];\n\t\t\tsupportsExtensionUi?: boolean;\n\t }\n\t| { id?: string; type: \"worker_unsubscribe\"; activeSessionId: string }\n\t| { id?: string; type: \"worker_register_peer_transport\"; grant: DaemonWorkerPeerGrant }\n\t| { id?: string; type: \"worker_archive_and_shutdown\" }\n\t| { id?: string; type: \"worker_get_rlm_capacity\" }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_passivate_idle_children\";\n\t\t\tidleEvictionMinutes: IdleEvictionMinutes;\n\t\t\tnow: number;\n\t\t\tlimit: number;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_message\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tmessage: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_result\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tsummary: string;\n\t\t\tfindings: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| { id?: string; type: \"worker_prepare_update\" }\n\t| { id?: string; type: \"worker_commit_update\" }\n\t| { id?: string; type: \"worker_cancel_update\" };\n\nexport type DaemonWorkerCommandBody = DaemonWorkerCommand extends infer TCommand\n\t? TCommand extends { id?: string }\n\t\t? Omit<TCommand, \"id\">\n\t\t: never\n\t: never;\n\nexport interface DaemonWorkerDescriptor {\n\tversion: 1 | 2;\n\tworkerId: string;\n\tpid: number;\n\tprocessStartId?: string;\n\tsocketPath: string;\n\trecoveryJournalPath: string;\n\torphanProcessJournalPath?: string;\n\tsupervisorSocketPath: string;\n\tauthenticationToken: string;\n\tworkerInstanceId?: string;\n\trootActiveSessionId: string;\n\t/** Stable protocol client that owns this worker. Omitted for resident sessions. */\n\townerClientId?: string;\n\trootSessionId?: string;\n\tsessionFile?: string;\n\tsessionDir?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlifecycle: DaemonWorkerLifecycle;\n\tcreateCommand: DurableDaemonCreateCommand;\n\tconsecutiveFailures: number;\n\t/** Durable intent written before root termination so replacement supervisors never recover it. */\n\tstopRequestedAt?: string;\n\t/** Complete the root's archived lifecycle state after its process has stopped. */\n\tarchiveOnStop?: boolean;\n\tlastFailureAt?: string;\n\tlastError?: string;\n}\n\nexport function durableDaemonWorkerDescriptor(descriptor: DaemonWorkerDescriptor): DaemonWorkerDescriptor {\n\tconst versionOneCreateCommand = descriptor.createCommand as unknown as { config?: unknown };\n\tconst versionOneConfig =\n\t\tdescriptor.version === 1 &&\n\t\ttypeof versionOneCreateCommand.config === \"object\" &&\n\t\tversionOneCreateCommand.config !== null\n\t\t\t? (versionOneCreateCommand.config as Record<string, unknown>)\n\t\t\t: undefined;\n\tconst sessionDir =\n\t\tdescriptor.sessionDir ??\n\t\t(typeof versionOneConfig?.sessionDir === \"string\" ? versionOneConfig.sessionDir : undefined);\n\treturn {\n\t\tversion: 2,\n\t\tworkerId: descriptor.workerId,\n\t\tpid: descriptor.pid,\n\t\t...(descriptor.processStartId !== undefined ? { processStartId: descriptor.processStartId } : {}),\n\t\tsocketPath: descriptor.socketPath,\n\t\trecoveryJournalPath: descriptor.recoveryJournalPath,\n\t\t...(descriptor.orphanProcessJournalPath !== undefined\n\t\t\t? { orphanProcessJournalPath: descriptor.orphanProcessJournalPath }\n\t\t\t: {}),\n\t\tsupervisorSocketPath: descriptor.supervisorSocketPath,\n\t\tauthenticationToken: descriptor.authenticationToken,\n\t\t...(descriptor.workerInstanceId !== undefined ? { workerInstanceId: descriptor.workerInstanceId } : {}),\n\t\trootActiveSessionId: descriptor.rootActiveSessionId,\n\t\t...(descriptor.ownerClientId !== undefined ? { ownerClientId: descriptor.ownerClientId } : {}),\n\t\t...(descriptor.rootSessionId !== undefined ? { rootSessionId: descriptor.rootSessionId } : {}),\n\t\t...(descriptor.sessionFile !== undefined ? { sessionFile: descriptor.sessionFile } : {}),\n\t\t...(sessionDir !== undefined ? { sessionDir } : {}),\n\t\tcreatedAt: descriptor.createdAt,\n\t\tupdatedAt: descriptor.updatedAt,\n\t\tlifecycle: descriptor.lifecycle,\n\t\tcreateCommand: durableDaemonCreateCommand(descriptor.createCommand),\n\t\tconsecutiveFailures: descriptor.consecutiveFailures,\n\t\t...(descriptor.stopRequestedAt !== undefined ? { stopRequestedAt: descriptor.stopRequestedAt } : {}),\n\t\t...(descriptor.archiveOnStop !== undefined ? { archiveOnStop: descriptor.archiveOnStop } : {}),\n\t\t...(descriptor.lastFailureAt !== undefined ? { lastFailureAt: descriptor.lastFailureAt } : {}),\n\t\t...(descriptor.lifecycle === \"failed\" ? { lastError: \"Waiting for a client with fresh runtime context\" } : {}),\n\t};\n}\n\nexport function isDaemonWorkerProcess(environment: NodeJS.ProcessEnv = process.env): boolean {\n\treturn environment[DAEMON_WORKER_ROLE_ENV] === \"1\";\n}\n\nexport function waitForDaemonWorkerStartupGate(environment: NodeJS.ProcessEnv = process.env): void {\n\tconst rawFd = environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tif (rawFd === undefined) {\n\t\treturn;\n\t}\n\tdelete environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tconst fd = Number(rawFd);\n\tif (!Number.isInteger(fd) || fd < 3) {\n\t\tthrow new Error(\"Daemon session worker has an invalid startup gate\");\n\t}\n\tlet marker: string;\n\ttry {\n\t\tmarker = readFileSync(fd, \"utf8\");\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n\tif (marker !== DAEMON_WORKER_STARTUP_GATE_COMMIT) {\n\t\tthrow new Error(\"Daemon session worker startup was cancelled\");\n\t}\n}\n\nexport function daemonWorkerInstanceId(environment: NodeJS.ProcessEnv = process.env): string | undefined {\n\treturn environment[DAEMON_WORKER_INSTANCE_ID_ENV] || undefined;\n}\n\nexport function requireDaemonWorkerAuthenticationToken(environment: NodeJS.ProcessEnv = process.env): string {\n\tconst token = environment[DAEMON_WORKER_TOKEN_ENV];\n\tif (!token) {\n\t\tthrow new Error(\"Daemon session worker is missing its authentication token\");\n\t}\n\treturn token;\n}\n\nexport function isDaemonWorkerFrameHeader(value: unknown): value is DaemonWorkerFrameHeader {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\tconst candidate = value as Record<string, unknown>;\n\tif (candidate.kind === \"command\") {\n\t\treturn typeof candidate.requestId === \"string\" && typeof candidate.commandType === \"string\";\n\t}\n\treturn (\n\t\tcandidate.kind === \"outbound\" &&\n\t\ttypeof candidate.outboundType === \"string\" &&\n\t\t(candidate.requestId === undefined || typeof candidate.requestId === \"string\") &&\n\t\t(candidate.activeSessionId === undefined || typeof candidate.activeSessionId === \"string\") &&\n\t\t(candidate.snapshotId === undefined || typeof candidate.snapshotId === \"string\") &&\n\t\t(candidate.sessionEventType === undefined || typeof candidate.sessionEventType === \"string\") &&\n\t\t(candidate.snapshotPurpose === undefined ||\n\t\t\tcandidate.snapshotPurpose === \"attach\" ||\n\t\t\tcandidate.snapshotPurpose === \"replacement\" ||\n\t\t\tcandidate.snapshotPurpose === \"catchup\") &&\n\t\t(candidate.payloadEncoding === undefined ||\n\t\t\tcandidate.payloadEncoding === \"jsonl\" ||\n\t\t\tcandidate.payloadEncoding === \"assistant-delta\")\n\t);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"daemon-worker-protocol.js","sourceRoot":"","sources":["../../../src/modes/daemon/daemon-worker-protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { closeSync, readFileSync } from \"node:fs\";\nimport type { AgentSessionMessageDeliveryMode, AgentSessionMessageSender } from \"../../core/agent-messages.js\";\nimport type { IdleEvictionMinutes } from \"../../core/session-action-store.js\";\n\nexport { SESSION_LEASE_OWNER_ID_ENV, SESSION_LEASES_ENABLED_ENV } from \"../../core/session-lease.js\";\n\nimport type { WorkerRosterEntry } from \"./agent-roster.js\";\nimport type { DaemonClientCapability, DaemonCommand, DaemonOutbound } from \"./daemon-protocol.js\";\n\nexport const DAEMON_WORKER_ROLE_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER\";\nexport const DAEMON_WORKER_TOKEN_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_TOKEN\";\nexport const DAEMON_WORKER_INSTANCE_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_INSTANCE_ID\";\nexport const DAEMON_WORKER_ACTIVE_SESSION_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_ACTIVE_SESSION_ID\";\nexport const DAEMON_WORKER_SUPERVISOR_SOCKET_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_SUPERVISOR_SOCKET\";\nexport const DAEMON_WORKER_RECOVERY_JOURNAL_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RECOVERY_JOURNAL\";\nexport const DAEMON_WORKER_RLM_LEDGER_SESSION_DIR_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RLM_LEDGER_SESSION_DIR\";\nexport const DAEMON_WORKER_STARTUP_GATE_FD_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_STARTUP_GATE_FD\";\nexport const DAEMON_WORKER_STARTUP_GATE_COMMIT = \"start\\n\";\nexport type DaemonWorkerLifecycle = \"starting\" | \"ready\" | \"recovering\" | \"stopping\" | \"failed\";\n\n// Worker->supervisor roster frames live outside the client-facing DaemonOutbound schema.\nexport type DaemonWorkerRosterOutbound =\n\t| {\n\t\t\ttype: \"roster_delta\";\n\t\t\tentries: WorkerRosterEntry[];\n\t\t\tremovedAgentIds?: string[];\n\t\t\tsnapshot?: true;\n\t }\n\t| { type: \"roster_heartbeat\" };\n\n/** Advertised by new workers in the worker_auth response; absent on legacy workers. */\nexport const DAEMON_WORKER_ROSTER_CAPABILITY = \"agent_roster\";\n\n/** Advertised in the worker_auth response by workers that accept peer transport grants. */\nexport const DAEMON_WORKER_PEER_TRANSPORT_CAPABILITY = \"peer_transport\";\n\n/** Idle keepalive cadence for worker->supervisor roster frames; the supervisor staleness threshold derives from it. */\nexport const ROSTER_HEARTBEAT_INTERVAL_MS = 15_000;\n\nexport type DaemonWorkerFrameHeader =\n\t| {\n\t\t\tkind: \"command\";\n\t\t\trequestId: string;\n\t\t\tcommandType: string;\n\t }\n\t| {\n\t\t\tkind: \"outbound\";\n\t\t\trequestId?: string;\n\t\t\toutboundType: DaemonOutbound[\"type\"] | DaemonWorkerRosterOutbound[\"type\"];\n\t\t\tactiveSessionId?: string;\n\t\t\tsnapshotId?: string;\n\t\t\tsessionEventType?: string;\n\t\t\tpayloadEncoding?: \"jsonl\" | \"assistant-delta\";\n\t\t\tsnapshotPurpose?: \"attach\" | \"replacement\" | \"catchup\";\n\t };\n\nexport interface DaemonRlmCapacityOrigin {\n\tsessionFile?: string;\n\tsessionId: string;\n}\n\nexport type DaemonRlmCapacityOperation =\n\t| (DaemonRlmCapacityOrigin & { op: \"status\" })\n\t| (DaemonRlmCapacityOrigin & { op: \"set\"; maxSubagents: number })\n\t| (DaemonRlmCapacityOrigin & { op: \"reserve\"; reservationId: string; residentRoot?: true })\n\t| { op: \"release\"; reservationId: string };\n\nexport interface DaemonRlmCapacityReservation extends DaemonRlmCapacityOrigin {\n\treservationId: string;\n\tresidentRoot?: true;\n}\n\nexport interface DaemonRlmCapacitySnapshot {\n\treservations: DaemonRlmCapacityReservation[];\n}\n\nexport function isDaemonRlmCapacitySnapshot(value: unknown): value is DaemonRlmCapacitySnapshot {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"reservations\" in value &&\n\t\tArray.isArray(value.reservations) &&\n\t\tvalue.reservations.every(\n\t\t\t(entry: unknown) =>\n\t\t\t\ttypeof entry === \"object\" &&\n\t\t\t\tentry !== null &&\n\t\t\t\t\"reservationId\" in entry &&\n\t\t\t\ttypeof entry.reservationId === \"string\" &&\n\t\t\t\tentry.reservationId.length > 0 &&\n\t\t\t\t\"sessionId\" in entry &&\n\t\t\t\ttypeof entry.sessionId === \"string\" &&\n\t\t\t\tentry.sessionId.length > 0 &&\n\t\t\t\t(!(\"sessionFile\" in entry) || entry.sessionFile === undefined || typeof entry.sessionFile === \"string\") &&\n\t\t\t\t(!(\"residentRoot\" in entry) || entry.residentRoot === undefined || entry.residentRoot === true),\n\t\t)\n\t);\n}\n\nexport type DaemonCreateCommand = Extract<DaemonCommand, { type: \"create\" }>;\n\nexport interface DurableDaemonCreateCommand {\n\ttype: \"create\";\n\tsessionPath?: string;\n\tnoSession?: boolean;\n}\n\nexport function durableDaemonCreateCommand(command: DaemonCreateCommand): DurableDaemonCreateCommand {\n\treturn {\n\t\ttype: \"create\",\n\t\t...(command.sessionPath !== undefined ? { sessionPath: command.sessionPath } : {}),\n\t\t...(command.noSession !== undefined ? { noSession: command.noSession } : {}),\n\t};\n}\n\n/**\n * A single-use, worker-memory-only admission for one direct peer, scoped to one active-session\n * slot (stable across switch_session/new_session/fork) of one worker incarnation. The session pin\n * is a routing/accident guard, not a privilege boundary: ticket holders already hold supervisor\n * access, which can attach to, switch, or kill any session.\n */\nexport interface DaemonWorkerPeerGrant {\n\tgrantId: string;\n\ttoken: string;\n\texpiresAt: string;\n\tpurpose: \"session_client\";\n\tworkerInstanceId: string;\n\tactiveSessionId: string;\n\tissuerGeneration: string;\n}\n\n/** Commands a direct peer may send before it holds an authenticated session role. */\nexport type DaemonPeerCommand = {\n\tid?: string;\n\ttype: \"peer_auth\";\n\tgrantId: string;\n\ttoken: string;\n\tworkerInstanceId: string;\n\tpurpose: \"session_client\";\n};\n\nexport type DaemonPeerCommandBody = Omit<DaemonPeerCommand, \"id\">;\n\nexport type DaemonWorkerCommand =\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_auth\";\n\t\t\ttoken: string;\n\t\t\tworkerInstanceId?: string;\n\t\t\tsupervisorGeneration: string;\n\t\t\tsupervisorPid: number;\n\t\t\tsupervisorProcessStartId?: string;\n\t\t\tsupervisorSocketPath: string;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_subscribe\";\n\t\t\tactiveSessionId: string;\n\t\t\tcapabilities?: readonly DaemonClientCapability[];\n\t\t\tsupportsExtensionUi?: boolean;\n\t }\n\t| { id?: string; type: \"worker_unsubscribe\"; activeSessionId: string }\n\t| { id?: string; type: \"worker_register_peer_transport\"; grant: DaemonWorkerPeerGrant }\n\t| { id?: string; type: \"worker_archive_and_shutdown\" }\n\t| { id?: string; type: \"worker_get_rlm_capacity\" }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_passivate_idle_children\";\n\t\t\tidleEvictionMinutes: IdleEvictionMinutes;\n\t\t\tnow: number;\n\t\t\tlimit: number;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_message\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tmessage: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_result\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tsummary: string;\n\t\t\tfindings: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| { id?: string; type: \"worker_prepare_update\" }\n\t| { id?: string; type: \"worker_commit_update\" }\n\t| { id?: string; type: \"worker_cancel_update\" };\n\nexport type DaemonWorkerCommandBody = DaemonWorkerCommand extends infer TCommand\n\t? TCommand extends { id?: string }\n\t\t? Omit<TCommand, \"id\">\n\t\t: never\n\t: never;\n\nexport interface DaemonWorkerDescriptor {\n\tversion: 1 | 2;\n\tworkerId: string;\n\tpid: number;\n\tprocessStartId?: string;\n\tsocketPath: string;\n\trecoveryJournalPath: string;\n\torphanProcessJournalPath?: string;\n\tsupervisorSocketPath: string;\n\tauthenticationToken: string;\n\tworkerInstanceId?: string;\n\trootActiveSessionId: string;\n\t/** Stable protocol client that owns this worker. Omitted for resident sessions. */\n\townerClientId?: string;\n\trootSessionId?: string;\n\tsessionFile?: string;\n\tsessionDir?: string;\n\t/** Supervisor-assigned journal scope, independent of transcript storage. */\n\trlmLedgerSessionDir?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlifecycle: DaemonWorkerLifecycle;\n\tcreateCommand: DurableDaemonCreateCommand;\n\tconsecutiveFailures: number;\n\t/** Durable intent written before root termination so replacement supervisors never recover it. */\n\tstopRequestedAt?: string;\n\t/** Complete the root's archived lifecycle state after its process has stopped. */\n\tarchiveOnStop?: boolean;\n\tlastFailureAt?: string;\n\tlastError?: string;\n}\n\nexport function durableDaemonWorkerDescriptor(descriptor: DaemonWorkerDescriptor): DaemonWorkerDescriptor {\n\tconst versionOneCreateCommand = descriptor.createCommand as unknown as { config?: unknown };\n\tconst versionOneConfig =\n\t\tdescriptor.version === 1 &&\n\t\ttypeof versionOneCreateCommand.config === \"object\" &&\n\t\tversionOneCreateCommand.config !== null\n\t\t\t? (versionOneCreateCommand.config as Record<string, unknown>)\n\t\t\t: undefined;\n\tconst sessionDir =\n\t\tdescriptor.sessionDir ??\n\t\t(typeof versionOneConfig?.sessionDir === \"string\" ? versionOneConfig.sessionDir : undefined);\n\treturn {\n\t\tversion: 2,\n\t\tworkerId: descriptor.workerId,\n\t\tpid: descriptor.pid,\n\t\t...(descriptor.processStartId !== undefined ? { processStartId: descriptor.processStartId } : {}),\n\t\tsocketPath: descriptor.socketPath,\n\t\trecoveryJournalPath: descriptor.recoveryJournalPath,\n\t\t...(descriptor.orphanProcessJournalPath !== undefined\n\t\t\t? { orphanProcessJournalPath: descriptor.orphanProcessJournalPath }\n\t\t\t: {}),\n\t\tsupervisorSocketPath: descriptor.supervisorSocketPath,\n\t\tauthenticationToken: descriptor.authenticationToken,\n\t\t...(descriptor.workerInstanceId !== undefined ? { workerInstanceId: descriptor.workerInstanceId } : {}),\n\t\trootActiveSessionId: descriptor.rootActiveSessionId,\n\t\t...(descriptor.ownerClientId !== undefined ? { ownerClientId: descriptor.ownerClientId } : {}),\n\t\t...(descriptor.rootSessionId !== undefined ? { rootSessionId: descriptor.rootSessionId } : {}),\n\t\t...(descriptor.sessionFile !== undefined ? { sessionFile: descriptor.sessionFile } : {}),\n\t\t...(sessionDir !== undefined ? { sessionDir } : {}),\n\t\t...(descriptor.rlmLedgerSessionDir !== undefined ? { rlmLedgerSessionDir: descriptor.rlmLedgerSessionDir } : {}),\n\t\tcreatedAt: descriptor.createdAt,\n\t\tupdatedAt: descriptor.updatedAt,\n\t\tlifecycle: descriptor.lifecycle,\n\t\tcreateCommand: durableDaemonCreateCommand(descriptor.createCommand),\n\t\tconsecutiveFailures: descriptor.consecutiveFailures,\n\t\t...(descriptor.stopRequestedAt !== undefined ? { stopRequestedAt: descriptor.stopRequestedAt } : {}),\n\t\t...(descriptor.archiveOnStop !== undefined ? { archiveOnStop: descriptor.archiveOnStop } : {}),\n\t\t...(descriptor.lastFailureAt !== undefined ? { lastFailureAt: descriptor.lastFailureAt } : {}),\n\t\t...(descriptor.lifecycle === \"failed\" ? { lastError: \"Waiting for a client with fresh runtime context\" } : {}),\n\t};\n}\n\nexport function isDaemonWorkerProcess(environment: NodeJS.ProcessEnv = process.env): boolean {\n\treturn environment[DAEMON_WORKER_ROLE_ENV] === \"1\";\n}\n\nexport function waitForDaemonWorkerStartupGate(environment: NodeJS.ProcessEnv = process.env): void {\n\tconst rawFd = environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tif (rawFd === undefined) {\n\t\treturn;\n\t}\n\tdelete environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tconst fd = Number(rawFd);\n\tif (!Number.isInteger(fd) || fd < 3) {\n\t\tthrow new Error(\"Daemon session worker has an invalid startup gate\");\n\t}\n\tlet marker: string;\n\ttry {\n\t\tmarker = readFileSync(fd, \"utf8\");\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n\tif (marker !== DAEMON_WORKER_STARTUP_GATE_COMMIT) {\n\t\tthrow new Error(\"Daemon session worker startup was cancelled\");\n\t}\n}\n\nexport function daemonWorkerInstanceId(environment: NodeJS.ProcessEnv = process.env): string | undefined {\n\treturn environment[DAEMON_WORKER_INSTANCE_ID_ENV] || undefined;\n}\n\nexport function requireDaemonWorkerAuthenticationToken(environment: NodeJS.ProcessEnv = process.env): string {\n\tconst token = environment[DAEMON_WORKER_TOKEN_ENV];\n\tif (!token) {\n\t\tthrow new Error(\"Daemon session worker is missing its authentication token\");\n\t}\n\treturn token;\n}\n\nexport function isDaemonWorkerFrameHeader(value: unknown): value is DaemonWorkerFrameHeader {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\tconst candidate = value as Record<string, unknown>;\n\tif (candidate.kind === \"command\") {\n\t\treturn typeof candidate.requestId === \"string\" && typeof candidate.commandType === \"string\";\n\t}\n\treturn (\n\t\tcandidate.kind === \"outbound\" &&\n\t\ttypeof candidate.outboundType === \"string\" &&\n\t\t(candidate.requestId === undefined || typeof candidate.requestId === \"string\") &&\n\t\t(candidate.activeSessionId === undefined || typeof candidate.activeSessionId === \"string\") &&\n\t\t(candidate.snapshotId === undefined || typeof candidate.snapshotId === \"string\") &&\n\t\t(candidate.sessionEventType === undefined || typeof candidate.sessionEventType === \"string\") &&\n\t\t(candidate.snapshotPurpose === undefined ||\n\t\t\tcandidate.snapshotPurpose === \"attach\" ||\n\t\t\tcandidate.snapshotPurpose === \"replacement\" ||\n\t\t\tcandidate.snapshotPurpose === \"catchup\") &&\n\t\t(candidate.payloadEncoding === undefined ||\n\t\t\tcandidate.payloadEncoding === \"jsonl\" ||\n\t\t\tcandidate.payloadEncoding === \"assistant-delta\")\n\t);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-mode.d.ts","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAK5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAGnE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,yEAAyE;IACzE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;CAC/B;AAgBD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/G;AAED,wBAAsB,0BAA0B,CAC/C,UAAU,EAAE,eAAe,EAC3B,OAAO,EAAE,gBAAgB,GACvB,OAAO,CAAC,MAAM,CAAC,CAEjB","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `pi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { ImageContent } from \"@ponythewhite/base-context-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.js\";\nimport { type AgentAutonomousStatus, type AutonomousLimitReason, autonomousLimitReason } from \"../core/autonomous.js\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.js\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.js\";\nimport { InProcessAgentConnection } from \"./agent-connection/in-process-agent-connection.js\";\nimport type { AgentConnection } from \"./agent-connection/types.js\";\nimport { latestAutonomousGateAttempt, selectHeadlessTerminalResult } from \"./headless-completion.js\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\nfunction describeAutonomousLimit(status: AgentAutonomousStatus, reason: AutonomousLimitReason): string {\n\tif (reason === \"maxContinuations\") {\n\t\treturn `maxContinuations reached (${status.continuationsUsed}/${status.limits.maxContinuations})`;\n\t}\n\tif (reason === \"maxTurns\") {\n\t\treturn `maxTurns reached (${status.turnsUsed}/${status.limits.maxTurns})`;\n\t}\n\tif (reason === \"maxTokens\") {\n\t\treturn `maxTokens reached (${status.tokensUsed}/${status.limits.maxTokens})`;\n\t}\n\tconst elapsed = status.startedAt === undefined ? 0 : Math.max(0, Date.now() - status.startedAt);\n\treturn `timeoutMs reached (${elapsed}/${status.limits.timeoutMs})`;\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst connection = new InProcessAgentConnection(runtimeHost);\n\treturn runPrintModeWithConnectionInternal(connection, options, () => connection.bindHeadlessExtensions());\n}\n\nexport async function runPrintModeWithConnection(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n): Promise<number> {\n\treturn runPrintModeWithConnectionInternal(connection, options);\n}\n\nasync function runPrintModeWithConnectionInternal(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n\tbindHeadlessExtensions?: () => Promise<void>,\n): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet disposed = false;\n\tlet unsubscribe: (() => void) | undefined;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeConnection = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait connection.dispose();\n\t};\n\n\tfor (const signal of [\n\t\t\"SIGINT\",\n\t\t\"SIGTERM\",\n\t\t...(process.platform === \"win32\" ? [] : [\"SIGHUP\"]),\n\t] as NodeJS.Signals[]) {\n\t\tconst handler = () => {\n\t\t\tkillTrackedDetachedChildren();\n\t\t\tvoid disposeConnection().finally(() => {\n\t\t\t\tconst exitCode = signal === \"SIGINT\" ? 130 : signal === \"SIGHUP\" ? 129 : 143;\n\t\t\t\tprocess.exit(exitCode);\n\t\t\t});\n\t\t};\n\t\tprocess.on(signal, handler);\n\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t}\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = await connection.getSessionHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tunsubscribe = connection.subscribe((event) => {\n\t\t\tif (mode === \"json\" && event.type === \"session_event\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event.event)}\\n`);\n\t\t\t}\n\t\t\tif (event.type === \"extension_error\") {\n\t\t\t\tconsole.error(`Extension error (${event.extensionPath}): ${event.error}`);\n\t\t\t}\n\t\t});\n\t\tawait bindHeadlessExtensions?.();\n\n\t\tif (initialMessage) {\n\t\t\tawait connection.promptAndWait(initialMessage, { images: initialImages });\n\t\t}\n\t\tfor (const message of messages) {\n\t\t\tawait connection.promptAndWait(message);\n\t\t}\n\n\t\tconst autonomousStatus = await connection.waitForHeadlessCompletion();\n\t\
|
|
1
|
+
{"version":3,"file":"print-mode.d.ts","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAK5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAGnE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,yEAAyE;IACzE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;CAC/B;AAgBD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/G;AAED,wBAAsB,0BAA0B,CAC/C,UAAU,EAAE,eAAe,EAC3B,OAAO,EAAE,gBAAgB,GACvB,OAAO,CAAC,MAAM,CAAC,CAEjB","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `pi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { ImageContent } from \"@ponythewhite/base-context-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.js\";\nimport { type AgentAutonomousStatus, type AutonomousLimitReason, autonomousLimitReason } from \"../core/autonomous.js\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.js\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.js\";\nimport { InProcessAgentConnection } from \"./agent-connection/in-process-agent-connection.js\";\nimport type { AgentConnection } from \"./agent-connection/types.js\";\nimport { latestAutonomousGateAttempt, selectHeadlessTerminalResult } from \"./headless-completion.js\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\nfunction describeAutonomousLimit(status: AgentAutonomousStatus, reason: AutonomousLimitReason): string {\n\tif (reason === \"maxContinuations\") {\n\t\treturn `maxContinuations reached (${status.continuationsUsed}/${status.limits.maxContinuations})`;\n\t}\n\tif (reason === \"maxTurns\") {\n\t\treturn `maxTurns reached (${status.turnsUsed}/${status.limits.maxTurns})`;\n\t}\n\tif (reason === \"maxTokens\") {\n\t\treturn `maxTokens reached (${status.tokensUsed}/${status.limits.maxTokens})`;\n\t}\n\tconst elapsed = status.startedAt === undefined ? 0 : Math.max(0, Date.now() - status.startedAt);\n\treturn `timeoutMs reached (${elapsed}/${status.limits.timeoutMs})`;\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst connection = new InProcessAgentConnection(runtimeHost);\n\treturn runPrintModeWithConnectionInternal(connection, options, () => connection.bindHeadlessExtensions());\n}\n\nexport async function runPrintModeWithConnection(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n): Promise<number> {\n\treturn runPrintModeWithConnectionInternal(connection, options);\n}\n\nasync function runPrintModeWithConnectionInternal(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n\tbindHeadlessExtensions?: () => Promise<void>,\n): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet disposed = false;\n\tlet unsubscribe: (() => void) | undefined;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeConnection = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait connection.dispose();\n\t};\n\n\tfor (const signal of [\n\t\t\"SIGINT\",\n\t\t\"SIGTERM\",\n\t\t...(process.platform === \"win32\" ? [] : [\"SIGHUP\"]),\n\t] as NodeJS.Signals[]) {\n\t\tconst handler = () => {\n\t\t\tkillTrackedDetachedChildren();\n\t\t\tvoid disposeConnection().finally(() => {\n\t\t\t\tconst exitCode = signal === \"SIGINT\" ? 130 : signal === \"SIGHUP\" ? 129 : 143;\n\t\t\t\tprocess.exit(exitCode);\n\t\t\t});\n\t\t};\n\t\tprocess.on(signal, handler);\n\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t}\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = await connection.getSessionHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tunsubscribe = connection.subscribe((event) => {\n\t\t\tif (mode === \"json\" && event.type === \"session_event\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event.event)}\\n`);\n\t\t\t}\n\t\t\tif (event.type === \"extension_error\") {\n\t\t\t\tconsole.error(`Extension error (${event.extensionPath}): ${event.error}`);\n\t\t\t}\n\t\t});\n\t\tawait bindHeadlessExtensions?.();\n\n\t\tif (initialMessage) {\n\t\t\tawait connection.promptAndWait(initialMessage, { images: initialImages });\n\t\t}\n\t\tfor (const message of messages) {\n\t\t\tawait connection.promptAndWait(message);\n\t\t}\n\n\t\tconst autonomousStatus = await connection.waitForHeadlessCompletion();\n\t\tconst { primary, compactionOutcomes } = selectHeadlessTerminalResult(await connection.getMessages());\n\t\tif (primary?.role === \"assistant\") {\n\t\t\tif (primary.stopReason === \"error\" || primary.stopReason === \"aborted\") {\n\t\t\t\tconsole.error(primary.errorMessage || `Request ${primary.stopReason}`);\n\t\t\t\texitCode = 1;\n\t\t\t} else if (mode === \"text\") {\n\t\t\t\tfor (const content of primary.content) {\n\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (primary) {\n\t\t\tif (mode === \"text\") writeRawStdout(`${primary.content}\\n`);\n\t\t\tif (!primary.details.success || primary.details.severity === \"error\") exitCode = 1;\n\t\t}\n\t\tfor (const outcome of compactionOutcomes) {\n\t\t\tif (mode === \"text\" || outcome.details.outcome === \"failed\") console.error(outcome.content);\n\t\t\tif (outcome.details.outcome === \"failed\") exitCode = 1;\n\t\t}\n\n\t\tconst autonomousLimit = autonomousLimitReason(autonomousStatus);\n\t\tif (autonomousStatus.enabled && autonomousStatus.gates.commands.length > 0 && autonomousStatus.lastGateFailure) {\n\t\t\tconst limitText = autonomousLimit\n\t\t\t\t? `; autonomous limit reached: ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`\n\t\t\t\t: \"\";\n\t\t\tconsole.error(\n\t\t\t\t`Autonomous quality gate still failing after attempt ${latestAutonomousGateAttempt(autonomousStatus)}/${autonomousStatus.gates.maxRetries}: ${autonomousStatus.lastGateFailure.exitText}${limitText}`,\n\t\t\t);\n\t\t\texitCode = 1;\n\t\t} else if (\n\t\t\tautonomousStatus.enabled &&\n\t\t\tautonomousLimit &&\n\t\t\t(autonomousStatus.gates.commands.length === 0 ||\n\t\t\t\tautonomousStatus.gates.commands.some((command) => autonomousStatus.gateAttempts[command] !== 0))\n\t\t) {\n\t\t\tconsole.error(\n\t\t\t\t`Autonomous run stopped before terminal evidence; ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`,\n\t\t\t);\n\t\t\texitCode = 1;\n\t\t}\n\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeConnection();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
|
package/dist/modes/print-mode.js
CHANGED
|
@@ -85,31 +85,31 @@ async function runPrintModeWithConnectionInternal(connection, options, bindHeadl
|
|
|
85
85
|
await connection.promptAndWait(message);
|
|
86
86
|
}
|
|
87
87
|
const autonomousStatus = await connection.waitForHeadlessCompletion();
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (primary
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
writeRawStdout(`${content.text}\n`);
|
|
99
|
-
}
|
|
88
|
+
const { primary, compactionOutcomes } = selectHeadlessTerminalResult(await connection.getMessages());
|
|
89
|
+
if (primary?.role === "assistant") {
|
|
90
|
+
if (primary.stopReason === "error" || primary.stopReason === "aborted") {
|
|
91
|
+
console.error(primary.errorMessage || `Request ${primary.stopReason}`);
|
|
92
|
+
exitCode = 1;
|
|
93
|
+
}
|
|
94
|
+
else if (mode === "text") {
|
|
95
|
+
for (const content of primary.content) {
|
|
96
|
+
if (content.type === "text") {
|
|
97
|
+
writeRawStdout(`${content.text}\n`);
|
|
100
98
|
}
|
|
101
99
|
}
|
|
102
100
|
}
|
|
103
|
-
|
|
101
|
+
}
|
|
102
|
+
else if (primary) {
|
|
103
|
+
if (mode === "text")
|
|
104
104
|
writeRawStdout(`${primary.content}\n`);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
if (!primary.details.success || primary.details.severity === "error")
|
|
106
|
+
exitCode = 1;
|
|
107
|
+
}
|
|
108
|
+
for (const outcome of compactionOutcomes) {
|
|
109
|
+
if (mode === "text" || outcome.details.outcome === "failed")
|
|
109
110
|
console.error(outcome.content);
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
111
|
+
if (outcome.details.outcome === "failed")
|
|
112
|
+
exitCode = 1;
|
|
113
113
|
}
|
|
114
114
|
const autonomousLimit = autonomousLimitReason(autonomousStatus);
|
|
115
115
|
if (autonomousStatus.enabled && autonomousStatus.gates.commands.length > 0 && autonomousStatus.lastGateFailure) {
|
|
@@ -119,7 +119,10 @@ async function runPrintModeWithConnectionInternal(connection, options, bindHeadl
|
|
|
119
119
|
console.error(`Autonomous quality gate still failing after attempt ${latestAutonomousGateAttempt(autonomousStatus)}/${autonomousStatus.gates.maxRetries}: ${autonomousStatus.lastGateFailure.exitText}${limitText}`);
|
|
120
120
|
exitCode = 1;
|
|
121
121
|
}
|
|
122
|
-
else if (autonomousStatus.enabled &&
|
|
122
|
+
else if (autonomousStatus.enabled &&
|
|
123
|
+
autonomousLimit &&
|
|
124
|
+
(autonomousStatus.gates.commands.length === 0 ||
|
|
125
|
+
autonomousStatus.gates.commands.some((command) => autonomousStatus.gateAttempts[command] !== 0))) {
|
|
123
126
|
console.error(`Autonomous run stopped before terminal evidence; ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`);
|
|
124
127
|
exitCode = 1;
|
|
125
128
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-mode.js","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `pi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { ImageContent } from \"@ponythewhite/base-context-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.js\";\nimport { type AgentAutonomousStatus, type AutonomousLimitReason, autonomousLimitReason } from \"../core/autonomous.js\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.js\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.js\";\nimport { InProcessAgentConnection } from \"./agent-connection/in-process-agent-connection.js\";\nimport type { AgentConnection } from \"./agent-connection/types.js\";\nimport { latestAutonomousGateAttempt, selectHeadlessTerminalResult } from \"./headless-completion.js\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\nfunction describeAutonomousLimit(status: AgentAutonomousStatus, reason: AutonomousLimitReason): string {\n\tif (reason === \"maxContinuations\") {\n\t\treturn `maxContinuations reached (${status.continuationsUsed}/${status.limits.maxContinuations})`;\n\t}\n\tif (reason === \"maxTurns\") {\n\t\treturn `maxTurns reached (${status.turnsUsed}/${status.limits.maxTurns})`;\n\t}\n\tif (reason === \"maxTokens\") {\n\t\treturn `maxTokens reached (${status.tokensUsed}/${status.limits.maxTokens})`;\n\t}\n\tconst elapsed = status.startedAt === undefined ? 0 : Math.max(0, Date.now() - status.startedAt);\n\treturn `timeoutMs reached (${elapsed}/${status.limits.timeoutMs})`;\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst connection = new InProcessAgentConnection(runtimeHost);\n\treturn runPrintModeWithConnectionInternal(connection, options, () => connection.bindHeadlessExtensions());\n}\n\nexport async function runPrintModeWithConnection(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n): Promise<number> {\n\treturn runPrintModeWithConnectionInternal(connection, options);\n}\n\nasync function runPrintModeWithConnectionInternal(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n\tbindHeadlessExtensions?: () => Promise<void>,\n): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet disposed = false;\n\tlet unsubscribe: (() => void) | undefined;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeConnection = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait connection.dispose();\n\t};\n\n\tfor (const signal of [\n\t\t\"SIGINT\",\n\t\t\"SIGTERM\",\n\t\t...(process.platform === \"win32\" ? [] : [\"SIGHUP\"]),\n\t] as NodeJS.Signals[]) {\n\t\tconst handler = () => {\n\t\t\tkillTrackedDetachedChildren();\n\t\t\tvoid disposeConnection().finally(() => {\n\t\t\t\tconst exitCode = signal === \"SIGINT\" ? 130 : signal === \"SIGHUP\" ? 129 : 143;\n\t\t\t\tprocess.exit(exitCode);\n\t\t\t});\n\t\t};\n\t\tprocess.on(signal, handler);\n\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t}\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = await connection.getSessionHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tunsubscribe = connection.subscribe((event) => {\n\t\t\tif (mode === \"json\" && event.type === \"session_event\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event.event)}\\n`);\n\t\t\t}\n\t\t\tif (event.type === \"extension_error\") {\n\t\t\t\tconsole.error(`Extension error (${event.extensionPath}): ${event.error}`);\n\t\t\t}\n\t\t});\n\t\tawait bindHeadlessExtensions?.();\n\n\t\tif (initialMessage) {\n\t\t\tawait connection.promptAndWait(initialMessage, { images: initialImages });\n\t\t}\n\t\tfor (const message of messages) {\n\t\t\tawait connection.promptAndWait(message);\n\t\t}\n\n\t\tconst autonomousStatus = await connection.waitForHeadlessCompletion();\n\t\tif (mode === \"text\") {\n\t\t\tconst { primary, compactionOutcomes } = selectHeadlessTerminalResult(await connection.getMessages());\n\t\t\tif (primary?.role === \"assistant\") {\n\t\t\t\tif (primary.stopReason === \"error\" || primary.stopReason === \"aborted\") {\n\t\t\t\t\tconsole.error(primary.errorMessage || `Request ${primary.stopReason}`);\n\t\t\t\t\texitCode = 1;\n\t\t\t\t} else {\n\t\t\t\t\tfor (const content of primary.content) {\n\t\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (primary) {\n\t\t\t\twriteRawStdout(`${primary.content}\\n`);\n\t\t\t\tif (!primary.details.success || primary.details.severity === \"error\") exitCode = 1;\n\t\t\t}\n\t\t\tfor (const outcome of compactionOutcomes) {\n\t\t\t\tconsole.error(outcome.content);\n\t\t\t\tif (outcome.details.outcome === \"failed\") exitCode = 1;\n\t\t\t}\n\t\t}\n\n\t\tconst autonomousLimit = autonomousLimitReason(autonomousStatus);\n\t\tif (autonomousStatus.enabled && autonomousStatus.gates.commands.length > 0 && autonomousStatus.lastGateFailure) {\n\t\t\tconst limitText = autonomousLimit\n\t\t\t\t? `; autonomous limit reached: ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`\n\t\t\t\t: \"\";\n\t\t\tconsole.error(\n\t\t\t\t`Autonomous quality gate still failing after attempt ${latestAutonomousGateAttempt(autonomousStatus)}/${autonomousStatus.gates.maxRetries}: ${autonomousStatus.lastGateFailure.exitText}${limitText}`,\n\t\t\t);\n\t\t\texitCode = 1;\n\t\t} else if (autonomousStatus.enabled && autonomousStatus.gates.commands.length === 0 && autonomousLimit) {\n\t\t\tconsole.error(\n\t\t\t\t`Autonomous run stopped before terminal evidence; ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`,\n\t\t\t);\n\t\t\texitCode = 1;\n\t\t}\n\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeConnection();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"print-mode.js","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `pi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { ImageContent } from \"@ponythewhite/base-context-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.js\";\nimport { type AgentAutonomousStatus, type AutonomousLimitReason, autonomousLimitReason } from \"../core/autonomous.js\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.js\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.js\";\nimport { InProcessAgentConnection } from \"./agent-connection/in-process-agent-connection.js\";\nimport type { AgentConnection } from \"./agent-connection/types.js\";\nimport { latestAutonomousGateAttempt, selectHeadlessTerminalResult } from \"./headless-completion.js\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\nfunction describeAutonomousLimit(status: AgentAutonomousStatus, reason: AutonomousLimitReason): string {\n\tif (reason === \"maxContinuations\") {\n\t\treturn `maxContinuations reached (${status.continuationsUsed}/${status.limits.maxContinuations})`;\n\t}\n\tif (reason === \"maxTurns\") {\n\t\treturn `maxTurns reached (${status.turnsUsed}/${status.limits.maxTurns})`;\n\t}\n\tif (reason === \"maxTokens\") {\n\t\treturn `maxTokens reached (${status.tokensUsed}/${status.limits.maxTokens})`;\n\t}\n\tconst elapsed = status.startedAt === undefined ? 0 : Math.max(0, Date.now() - status.startedAt);\n\treturn `timeoutMs reached (${elapsed}/${status.limits.timeoutMs})`;\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst connection = new InProcessAgentConnection(runtimeHost);\n\treturn runPrintModeWithConnectionInternal(connection, options, () => connection.bindHeadlessExtensions());\n}\n\nexport async function runPrintModeWithConnection(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n): Promise<number> {\n\treturn runPrintModeWithConnectionInternal(connection, options);\n}\n\nasync function runPrintModeWithConnectionInternal(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n\tbindHeadlessExtensions?: () => Promise<void>,\n): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet disposed = false;\n\tlet unsubscribe: (() => void) | undefined;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeConnection = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait connection.dispose();\n\t};\n\n\tfor (const signal of [\n\t\t\"SIGINT\",\n\t\t\"SIGTERM\",\n\t\t...(process.platform === \"win32\" ? [] : [\"SIGHUP\"]),\n\t] as NodeJS.Signals[]) {\n\t\tconst handler = () => {\n\t\t\tkillTrackedDetachedChildren();\n\t\t\tvoid disposeConnection().finally(() => {\n\t\t\t\tconst exitCode = signal === \"SIGINT\" ? 130 : signal === \"SIGHUP\" ? 129 : 143;\n\t\t\t\tprocess.exit(exitCode);\n\t\t\t});\n\t\t};\n\t\tprocess.on(signal, handler);\n\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t}\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = await connection.getSessionHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tunsubscribe = connection.subscribe((event) => {\n\t\t\tif (mode === \"json\" && event.type === \"session_event\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event.event)}\\n`);\n\t\t\t}\n\t\t\tif (event.type === \"extension_error\") {\n\t\t\t\tconsole.error(`Extension error (${event.extensionPath}): ${event.error}`);\n\t\t\t}\n\t\t});\n\t\tawait bindHeadlessExtensions?.();\n\n\t\tif (initialMessage) {\n\t\t\tawait connection.promptAndWait(initialMessage, { images: initialImages });\n\t\t}\n\t\tfor (const message of messages) {\n\t\t\tawait connection.promptAndWait(message);\n\t\t}\n\n\t\tconst autonomousStatus = await connection.waitForHeadlessCompletion();\n\t\tconst { primary, compactionOutcomes } = selectHeadlessTerminalResult(await connection.getMessages());\n\t\tif (primary?.role === \"assistant\") {\n\t\t\tif (primary.stopReason === \"error\" || primary.stopReason === \"aborted\") {\n\t\t\t\tconsole.error(primary.errorMessage || `Request ${primary.stopReason}`);\n\t\t\t\texitCode = 1;\n\t\t\t} else if (mode === \"text\") {\n\t\t\t\tfor (const content of primary.content) {\n\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (primary) {\n\t\t\tif (mode === \"text\") writeRawStdout(`${primary.content}\\n`);\n\t\t\tif (!primary.details.success || primary.details.severity === \"error\") exitCode = 1;\n\t\t}\n\t\tfor (const outcome of compactionOutcomes) {\n\t\t\tif (mode === \"text\" || outcome.details.outcome === \"failed\") console.error(outcome.content);\n\t\t\tif (outcome.details.outcome === \"failed\") exitCode = 1;\n\t\t}\n\n\t\tconst autonomousLimit = autonomousLimitReason(autonomousStatus);\n\t\tif (autonomousStatus.enabled && autonomousStatus.gates.commands.length > 0 && autonomousStatus.lastGateFailure) {\n\t\t\tconst limitText = autonomousLimit\n\t\t\t\t? `; autonomous limit reached: ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`\n\t\t\t\t: \"\";\n\t\t\tconsole.error(\n\t\t\t\t`Autonomous quality gate still failing after attempt ${latestAutonomousGateAttempt(autonomousStatus)}/${autonomousStatus.gates.maxRetries}: ${autonomousStatus.lastGateFailure.exitText}${limitText}`,\n\t\t\t);\n\t\t\texitCode = 1;\n\t\t} else if (\n\t\t\tautonomousStatus.enabled &&\n\t\t\tautonomousLimit &&\n\t\t\t(autonomousStatus.gates.commands.length === 0 ||\n\t\t\t\tautonomousStatus.gates.commands.some((command) => autonomousStatus.gateAttempts[command] !== 0))\n\t\t) {\n\t\t\tconsole.error(\n\t\t\t\t`Autonomous run stopped before terminal evidence; ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`,\n\t\t\t);\n\t\t\texitCode = 1;\n\t\t}\n\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeConnection();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
|
package/docs/compaction.md
CHANGED
|
@@ -35,18 +35,19 @@ or loss from a summary alone.
|
|
|
35
35
|
|
|
36
36
|
### When It Triggers
|
|
37
37
|
|
|
38
|
-
Auto-compaction uses
|
|
38
|
+
Auto-compaction uses 90% of the model context window as its default soft target:
|
|
39
39
|
|
|
40
40
|
```
|
|
41
|
-
softTarget =
|
|
41
|
+
softTarget = floor(0.9 * contextWindow)
|
|
42
42
|
threshold = min(contextWindow - reserveTokens, max(softTarget, fixedContextTokens + 4 * keepRecentTokens))
|
|
43
43
|
contextTokens > threshold
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
With default `keepRecentTokens` of 20000 and `reserveTokens` of 16384, before
|
|
47
|
-
fixed-context headroom raises the target, the thresholds are
|
|
48
|
-
272000-token model,
|
|
49
|
-
model. The model-window
|
|
47
|
+
fixed-context headroom raises the target, the thresholds are 244800 for a
|
|
48
|
+
272000-token model, 111616 for a 128000-token model, and 47616 for a 64000-token
|
|
49
|
+
model. The model-window reserve can therefore trigger compaction before 90%.
|
|
50
|
+
The model-window ceiling always applies.
|
|
50
51
|
|
|
51
52
|
`fixedContextTokens` estimates current system instructions, tool schemas, the
|
|
52
53
|
current TaskFrame and latest harness snapshot. It does not count all historical
|
|
@@ -68,6 +69,33 @@ budgets remain separate; see [context management](context-management.md#model-aw
|
|
|
68
69
|
|
|
69
70
|
You can also trigger manually with `/compact [instructions]`, where optional instructions focus the summary — for example `/compact focus on the auth refactor, remember the exact migration command`. The instructions are passed to the summarization prompt with high priority, persisted on the `CompactionEntry`, and shown on the `[compaction]` message in the TUI.
|
|
70
71
|
|
|
72
|
+
### Agent-Requested Compaction
|
|
73
|
+
|
|
74
|
+
The agent can request compaction before the automatic threshold, including when
|
|
75
|
+
using Astra. The bundled `compact` skill is enabled by default and runs from the
|
|
76
|
+
Python REPL:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
await compact.status()
|
|
80
|
+
await compact.run("keep the remaining plan and exact test names")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`status()` reports `tokens`, `context_window`, `percent`, and `scheduled`. Usage
|
|
84
|
+
can be unknown immediately after compaction. `run()` schedules compaction at the
|
|
85
|
+
next turn boundary, not in the middle of the Python cell. It returns
|
|
86
|
+
`{"scheduled": True}` when accepted, or `{"scheduled": False, "reason": ...}`
|
|
87
|
+
when no turn is active or there is nothing to compact yet. Optional instructions
|
|
88
|
+
focus the summary. Repeating the request before the boundary updates them.
|
|
89
|
+
Interrupted tool work can continue after the checkpoint; this does not start new
|
|
90
|
+
work after an otherwise completed turn.
|
|
91
|
+
|
|
92
|
+
This request does not depend on the automatic threshold or `compaction.enabled`.
|
|
93
|
+
It requires context optimization to be on. `compaction.agentCallable: false`
|
|
94
|
+
disables the skill, and disabling Python or bundled skills can remove its normal
|
|
95
|
+
entry point. Each recursive agent uses its own session's compaction path; children
|
|
96
|
+
inherit the parent's compact-skill availability. There is no Astra-specific gate.
|
|
97
|
+
A request compacts the requesting session, not the whole agent tree.
|
|
98
|
+
|
|
71
99
|
### How It Works
|
|
72
100
|
|
|
73
101
|
1. **Find cut point**: Walk backwards from newest message, accumulating token estimates until `keepRecentTokens` (default 20k, configurable in `~/.base-context/settings.json` or `<project-dir>/.base-context/settings.json`) is reached
|
|
@@ -455,10 +483,11 @@ Configure compaction in `~/.base-context/settings.json` or `<project-dir>/.base-
|
|
|
455
483
|
| `enabled` | `true` | Enable auto-compaction |
|
|
456
484
|
| `reserveTokens` | `16384` | Headroom used by the compaction threshold |
|
|
457
485
|
| `keepRecentTokens` | `20000` | Estimated recent-token target for the retained tail |
|
|
458
|
-
| `targetTokens` |
|
|
486
|
+
| `targetTokens` | 90% of the model context window | Positive safe integer to override the soft target, or `"model-limit"` for the model-window threshold; fixed-context headroom and the model reserve still apply as described above |
|
|
487
|
+
| `agentCallable` | `true` | Expose the `compact` skill so the agent can request earlier compaction |
|
|
459
488
|
|
|
460
489
|
Disable automatic compaction with `"compaction": { "enabled": false }`. Manual
|
|
461
|
-
`/compact`
|
|
490
|
+
`/compact` and agent-requested compaction remain available while `context.mode` is `"on"`. Setting `context.mode`
|
|
462
491
|
to `"off"` disables context optimization, including manual compaction; logging,
|
|
463
492
|
recovery, limits and other non-optimization ownership remain active.
|
|
464
493
|
|
|
@@ -84,22 +84,28 @@ In supported native Responses/Codex selection paths, historical assistant litera
|
|
|
84
84
|
|
|
85
85
|
See [SDK request-token profiles](sdk.md#explicit-request-token-budget-profiles) for the exact scope and configuration.
|
|
86
86
|
|
|
87
|
-
Ordinary [compaction](compaction.md) uses a separate
|
|
88
|
-
`
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
Ordinary [compaction](compaction.md) uses a separate soft target of 90% of the
|
|
88
|
+
model context window: `floor(0.9 * contextWindow)`. The actual trigger also leaves
|
|
89
|
+
`4 * keepRecentTokens` above estimated fixed context, then caps the result at
|
|
90
|
+
`contextWindow - reserveTokens`. Fixed context includes current system
|
|
91
91
|
instructions, tool schemas, the current TaskFrame and latest harness snapshot,
|
|
92
92
|
not every historical message. This avoids repeated ineffective summaries of
|
|
93
93
|
noncompactable instructions.
|
|
94
94
|
|
|
95
|
-
With small fixed context, default
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
`
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
With small fixed context, default thresholds are 244800 estimated tokens for a
|
|
96
|
+
272000-token model, 111616 for a 128000-token model, and 47616 for a 64000-token
|
|
97
|
+
model. The model-window reserve can trigger compaction before 90%. Set
|
|
98
|
+
`compaction.targetTokens` to a positive safe integer to replace the soft target
|
|
99
|
+
(still subject to fixed-context headroom), or `"model-limit"` to use exactly
|
|
100
|
+
`contextWindow - reserveTokens`. Required replay groups are not clipped to meet
|
|
101
|
+
this target. Summaries can add calls and rereads; this is not a strict request
|
|
101
102
|
cap, an optimality guarantee, or evidence of a deployment's actual limit.
|
|
102
103
|
|
|
104
|
+
The agent can request an earlier checkpoint from the Python REPL with
|
|
105
|
+
`await compact.run()`, independently of the automatic threshold. It can inspect
|
|
106
|
+
usage with `await compact.status()`. This is enabled by default for all models,
|
|
107
|
+
including Astra; see [agent-requested compaction](compaction.md#agent-requested-compaction).
|
|
108
|
+
|
|
103
109
|
## Stable context epochs
|
|
104
110
|
|
|
105
111
|
An epoch is a committed context choice: selected source recipes, task-frame text, and the accepted request contract. Within an epoch, unchanged context stays stable. A new selection or relevant resource change requires an accepted boundary rather than an unrecorded rewrite of the prefix.
|
package/docs/json.md
CHANGED
|
@@ -75,8 +75,21 @@ Followed by events as they occur:
|
|
|
75
75
|
{"type":"agent_end","messages":[...]}
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
+
## Completion and Errors
|
|
79
|
+
|
|
80
|
+
JSON mode has the same exit-status rules as text print mode. Terminal assistant errors or aborts, failed session commands, failed compaction, and unfinished autonomous runs stopped by a limit return a nonzero exit status. A configured gate that has not run is not a passed gate. Error diagnostics go to stderr; stdout remains a JSON event stream. Recovered intermediate errors do not by themselves make the final result fail.
|
|
81
|
+
|
|
82
|
+
An unknown explicit `--model` fails startup instead of falling back to the saved model. Startup failures can occur before the session header is emitted.
|
|
83
|
+
|
|
84
|
+
Keep stderr and check the process exit status. An `agent_end` event means the agent loop ended, not that the task succeeded: inspect the terminal assistant's `stopReason` and `errorMessage`, and any gate or compaction failure. Codex error diagnostics retain supplied flat or nested error messages and codes; an empty provider error cannot reveal a cause the provider did not send.
|
|
85
|
+
|
|
86
|
+
Record the first session header's `id` when launching a run. Use that session ID with lifecycle commands; neither cwd nor an operating-system process title uniquely identifies a session. See [Long-Running Agents](long-running-agents.md#daemon-backed-sessions) for client-owned versus resident lifetimes.
|
|
87
|
+
|
|
78
88
|
## Example
|
|
79
89
|
|
|
90
|
+
Use `pipefail` so the filter does not hide a failing CLI exit status:
|
|
91
|
+
|
|
80
92
|
```bash
|
|
81
|
-
|
|
93
|
+
set -o pipefail
|
|
94
|
+
base-context --mode json "List files" 2>run.err | jq -c 'select(.type == "message_end")'
|
|
82
95
|
```
|