@code-yeongyu/senpi 2026.10.25-4 → 2026.10.26-2
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 +47 -0
- package/dist/bundle/chunks/{anthropic-messages-WBASBTIW.js → anthropic-messages-ODSFJCXR.js} +3 -3
- package/dist/bundle/chunks/{args-B444OQBK.js → args-SWKJAYQD.js} +1 -1
- package/dist/bundle/chunks/azure-openai-responses-REGXS4XO.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +3 -3
- package/dist/bundle/chunks/chunk-2XF6W6F6.js +410 -0
- package/dist/bundle/chunks/{chunk-WDPQ6CZJ.js → chunk-4QVORFQ2.js} +1 -1
- package/dist/bundle/chunks/{chunk-6AOVUTUR.js → chunk-5W3DTM2J.js} +2 -2
- package/dist/bundle/chunks/{chunk-E6WYH3ZL.js → chunk-6GAMRAVM.js} +9 -7
- package/dist/bundle/chunks/{chunk-N7IN46Q5.js → chunk-7IZH2KQX.js} +9 -7
- package/dist/bundle/chunks/{chunk-7GZUFOM3.js → chunk-ARSENVDY.js} +1 -1
- package/dist/bundle/chunks/{chunk-STMXIBXF.js → chunk-CNDPCYNT.js} +1 -1
- package/dist/bundle/chunks/{chunk-XF3LJC3O.js → chunk-CYOHFREV.js} +1 -1
- package/dist/bundle/chunks/{chunk-E6D4RIT7.js → chunk-DNDZPKIQ.js} +2 -2
- package/dist/bundle/chunks/{chunk-E4LBKOZG.js → chunk-EQNUL2WB.js} +4 -4
- package/dist/bundle/chunks/{chunk-2RB5EL4X.js → chunk-ESNSRUW4.js} +1 -1
- package/dist/bundle/chunks/{chunk-4AOMNOGY.js → chunk-FQDARFHT.js} +1 -1
- package/dist/bundle/chunks/{chunk-BWA4FVFW.js → chunk-GPPOPK76.js} +3 -3
- package/dist/bundle/chunks/{chunk-SBGIXMX3.js → chunk-GWGNVYPB.js} +1 -1
- package/dist/bundle/chunks/{chunk-KKD4CYCI.js → chunk-H4WJ4LY3.js} +1 -1
- package/dist/bundle/chunks/{chunk-V2UYXTRR.js → chunk-HWTD4QF3.js} +1 -1
- package/dist/bundle/chunks/chunk-I2WFLKZ2.js +5 -0
- package/dist/bundle/chunks/{chunk-WD6WBYC5.js → chunk-IHKHCWWG.js} +1 -1
- package/dist/bundle/chunks/{chunk-T36LJ6MW.js → chunk-IY4G44MN.js} +1 -1
- package/dist/bundle/chunks/{chunk-BZ7726QO.js → chunk-J2YAYTB2.js} +1 -1
- package/dist/bundle/chunks/{chunk-UFJ2K7Q7.js → chunk-JH7MVRNJ.js} +1 -1
- package/dist/bundle/chunks/chunk-KBSFTXAT.js +2 -0
- package/dist/bundle/chunks/{chunk-OLCDIITS.js → chunk-KRO63T4Q.js} +1 -1
- package/dist/bundle/chunks/{chunk-TTU2RNVX.js → chunk-KTDIIF2F.js} +1 -1
- package/dist/bundle/chunks/{chunk-KNVNKDER.js → chunk-L2O6K3SJ.js} +1 -1
- package/dist/bundle/chunks/{chunk-3BTN337S.js → chunk-NDNIMC5W.js} +1 -1
- package/dist/bundle/chunks/{chunk-ITGYN22E.js → chunk-ODRGPC5S.js} +1 -1
- package/dist/bundle/chunks/{chunk-4MOZXOJX.js → chunk-PDG4XWO2.js} +1 -1
- package/dist/bundle/chunks/{chunk-3QCYBOKN.js → chunk-PPECSSWX.js} +1 -1
- package/dist/bundle/chunks/{chunk-4P7WARQZ.js → chunk-PY4ZQHTN.js} +1 -1
- package/dist/bundle/chunks/{chunk-C2MQ4QXN.js → chunk-RPW3XQW3.js} +48 -42
- package/dist/bundle/chunks/{chunk-JMOUU75H.js → chunk-RQ5JTXUC.js} +1 -1
- package/dist/bundle/chunks/chunk-TQ67PB7U.js +13 -0
- package/dist/bundle/chunks/{chunk-5JJDR6XI.js → chunk-UJPG4ROT.js} +1 -1
- package/dist/bundle/chunks/{chunk-FHXR4ZAC.js → chunk-XM36IFP3.js} +1 -1
- package/dist/bundle/chunks/{chunk-PT6JJUN2.js → chunk-XMNPK472.js} +1 -1
- package/dist/bundle/chunks/{client-WTYEICLH.js → chunk-Y3TMJV3J.js} +3 -3
- package/dist/bundle/chunks/{chunk-GSSD3R5X.js → chunk-Z6BREXV3.js} +1 -1
- package/dist/bundle/chunks/{chunk-KXB5WIS5.js → chunk-Z6SAQ5O3.js} +1 -1
- package/dist/bundle/chunks/{chunk-LOIF6PHI.js → chunk-ZAUVY6ZC.js} +3 -3
- package/dist/bundle/chunks/{chunk-7CNOCJCN.js → chunk-ZP6JJDYV.js} +1 -1
- package/dist/bundle/chunks/cli-main-Q2GA53XM.js +3 -0
- package/dist/bundle/chunks/client-LOS6GSEW.js +2 -0
- package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-K5H6BJP3.js → cloudflare-workers-ai-system-one-WDHT7BBV.js} +1 -1
- package/dist/bundle/chunks/cursor-agent.js +3 -3
- package/dist/bundle/chunks/devin-agent.js +3 -3
- package/dist/bundle/chunks/dispatch-5R3TYAYB.js +9 -0
- package/dist/bundle/chunks/google-generative-ai-FHYFXKLA.js +2 -0
- package/dist/bundle/chunks/google-vertex-5DWE5U5K.js +2 -0
- package/dist/bundle/chunks/{help-fast-path-3Z26DQSV.js → help-fast-path-FETLIF3W.js} +1 -1
- package/dist/bundle/chunks/host-command-XEB7SHT3.js +2 -0
- package/dist/bundle/chunks/{host-lifecycle-3VHHIGDL.js → host-lifecycle-HX3EGRRW.js} +1 -1
- package/dist/bundle/chunks/host-lifecycle.js +2 -2
- package/dist/bundle/chunks/{host-session-command-56XF6ACS.js → host-session-command-FFN52LXJ.js} +1 -1
- package/dist/bundle/chunks/{host-socket-request-QL2WEZTN.js → host-socket-request-K4LCUOUD.js} +1 -1
- package/dist/bundle/chunks/interactive-mode-5DEKY3YW.js +2 -0
- package/dist/bundle/chunks/{mcp-presenter-bootstrap-XUSCQVRC.js → mcp-presenter-bootstrap-FOMKF4TU.js} +1 -1
- package/dist/bundle/chunks/{mistral-conversations-DH44NOYV.js → mistral-conversations-I2PI7DDF.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-Z2CW4SDM.js → multi-session-host-OPR5VBFO.js} +6 -7
- package/dist/bundle/chunks/{openai-codex-responses-SERAFKAS.js → openai-codex-responses-WSEX6SH7.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-BZB5O45A.js → openai-completions-YCBHTBSS.js} +1 -1
- package/dist/bundle/chunks/openai-responses-GXNSQF4A.js +3 -0
- package/dist/bundle/chunks/{package-manager-cli-N55U6PEO.js → package-manager-cli-W55E3LHP.js} +1 -1
- package/dist/bundle/chunks/{pi-messages-VXATX45B.js → pi-messages-O6GISIRW.js} +2 -2
- package/dist/bundle/chunks/{role-JVSBNKGE.js → role-SHIZQKK4.js} +1 -1
- package/dist/bundle/chunks/{rotation-stream-CBGCBYHV.js → rotation-stream-2PCZWNKF.js} +1 -1
- package/dist/bundle/chunks/rpc-mode-IDUJTSYS.js +2 -0
- package/dist/bundle/chunks/{rpc-monitor-source-AE3C6EQV.js → rpc-monitor-source-DRZXJHTL.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-VS7CZC2J.js → schedule-command-B7RRSANU.js} +1 -1
- package/dist/bundle/chunks/session-control-endpoint-LMZH5JLH.js +3 -0
- package/dist/bundle/chunks/{session-picker-E4KUJDLO.js → session-picker-DTGBOXDR.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +214 -205
- package/dist/bundle/chunks/{typesafe-system-one-P75WJ767.js → typesafe-system-one-XGYJJVSE.js} +1 -1
- package/dist/bundle/cli.js +2 -2
- package/dist/bundle/host-supervisor.js +2 -2
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -1
- package/dist/cli/host-command-args.d.ts +1 -0
- package/dist/cli/host-command-args.js +5 -0
- package/dist/cli/host-command.js +7 -1
- package/dist/cli.js +21 -3
- package/dist/core/agent-session.d.ts +11 -1
- package/dist/core/agent-session.js +19 -2
- package/dist/core/extensions/builtin/compaction/index.js +7 -1
- package/dist/core/extensions/builtin/herdr/index.js +9 -5
- package/dist/core/extensions/builtin/mcp/auth/oauth-issuer.d.ts +6 -0
- package/dist/core/extensions/builtin/mcp/auth/oauth-issuer.js +25 -0
- package/dist/core/extensions/builtin/mcp/auth/oauth-provider.d.ts +3 -3
- package/dist/core/extensions/builtin/mcp/auth/oauth-provider.js +50 -19
- package/dist/core/extensions/builtin/mcp/auth/oauth-refresh.js +4 -3
- package/dist/core/extensions/builtin/mcp/auth/oauth.js +19 -12
- package/dist/core/extensions/builtin/mcp/catalog-cache.d.ts +2 -1
- package/dist/core/extensions/builtin/mcp/catalog-cache.js +19 -6
- package/dist/core/extensions/builtin/mcp/catalog.d.ts +3 -2
- package/dist/core/extensions/builtin/mcp/catalog.js +20 -3
- package/dist/core/extensions/builtin/mcp/expose/call.d.ts +2 -1
- package/dist/core/extensions/builtin/mcp/expose/call.js +2 -1
- package/dist/core/extensions/builtin/mcp/expose/register.js +1 -1
- package/dist/core/extensions/builtin/mcp/expose/schema-compat.d.ts +2 -2
- package/dist/core/extensions/builtin/mcp/expose/schema-compat.js +11 -1
- package/dist/core/extensions/builtin/mcp/invocation.js +16 -2
- package/dist/core/extensions/builtin/mcp/modern/dispatch.js +1 -0
- package/dist/core/extensions/builtin/mcp/modern/parameter-headers.d.ts +4 -1
- package/dist/core/extensions/builtin/mcp/modern/parameter-headers.js +33 -35
- package/dist/core/extensions/builtin/mcp/modern/request.d.ts +1 -1
- package/dist/core/extensions/builtin/mcp/modern/request.js +4 -1
- package/dist/core/extensions/builtin/mcp/modern/sdk-bridge.js +18 -3
- package/dist/core/extensions/builtin/mcp/modern/stdio-probe.js +23 -0
- package/dist/core/extensions/builtin/mcp/modern/subscriptions.d.ts +14 -0
- package/dist/core/extensions/builtin/mcp/modern/subscriptions.js +226 -0
- package/dist/core/extensions/builtin/mcp/modern/tool-schema.d.ts +13 -0
- package/dist/core/extensions/builtin/mcp/modern/tool-schema.js +75 -0
- package/dist/core/extensions/builtin/mcp/modern/tools.d.ts +107 -0
- package/dist/core/extensions/builtin/mcp/modern/tools.js +53 -0
- package/dist/core/extensions/builtin/mcp/modern/transport.d.ts +2 -0
- package/dist/core/extensions/builtin/mcp/modern/transport.js +4 -2
- package/dist/core/extensions/builtin/mcp/resources.js +4 -0
- package/dist/core/extensions/builtin/mcp/tool-client.d.ts +13 -0
- package/dist/core/extensions/builtin/mcp/tool-client.js +17 -0
- package/dist/core/extensions/builtin/mcp/tool-contracts.d.ts +19 -0
- package/dist/core/extensions/builtin/mcp/tool-contracts.js +2 -0
- package/dist/core/extensions/builtin/mcp/wrap.js +2 -2
- package/dist/core/extensions/builtin/permission-system/bash-command-segments.d.ts +37 -0
- package/dist/core/extensions/builtin/permission-system/bash-command-segments.js +899 -0
- package/dist/core/extensions/builtin/permission-system/parsers.d.ts +2 -0
- package/dist/core/extensions/builtin/permission-system/parsers.js +44 -10
- package/dist/core/extensions/builtin/terminal/extension-state.js +2 -1
- package/dist/core/extensions/builtin/vertex-model-garden/auth.d.ts +9 -0
- package/dist/core/extensions/builtin/vertex-model-garden/auth.js +17 -1
- package/dist/core/extensions/builtin/websearch/websearch/providers/google.d.ts +6 -0
- package/dist/core/extensions/builtin/websearch/websearch/providers/google.js +6 -1
- package/dist/core/extensions/types.d.ts +2 -0
- package/dist/core/lifecycle-children.d.ts +3 -1
- package/dist/core/lifecycle-children.js +79 -15
- package/dist/core/lifecycle-record.js +1 -24
- package/dist/core/lifecycle-session-binding.js +2 -1
- package/dist/core/lifecycle-wait-items.d.ts +17 -0
- package/dist/core/lifecycle-wait-items.js +72 -0
- package/dist/core/model-runtime.js +6 -1
- package/dist/core/provider-api-key-auth.d.ts +6 -1
- package/dist/core/provider-api-key-auth.js +11 -4
- package/dist/core/provider-composer.d.ts +8 -1
- package/dist/core/provider-composer.js +7 -3
- package/dist/core/sdk.js +4 -1
- package/dist/core/session-activity.js +2 -0
- package/dist/core/session-lifecycle-types.d.ts +20 -4
- package/dist/core/session-lifecycle.js +35 -4
- package/dist/core/structured-session-lane.d.ts +33 -0
- package/dist/core/structured-session-lane.js +62 -0
- package/dist/core/work-custody-record.d.ts +2 -1
- package/dist/core/work-custody-record.js +2 -0
- package/dist/core/work-obligations.d.ts +1 -1
- package/dist/core/work-obligations.js +8 -2
- package/dist/modes/interactive/session-control-commands.js +21 -4
- package/dist/modes/interactive/session-control-rpc-commands.d.ts +1 -1
- package/dist/modes/interactive/session-control-rpc-commands.js +19 -0
- package/dist/modes/json-event.d.ts +79 -1
- package/dist/modes/json-event.js +79 -1
- package/dist/modes/rpc/compact-content-index.d.ts +85 -0
- package/dist/modes/rpc/compact-content-index.js +254 -0
- package/dist/modes/rpc/compact-content-store.d.ts +59 -0
- package/dist/modes/rpc/compact-content-store.js +134 -0
- package/dist/modes/rpc/compact-index-pages.d.ts +12 -0
- package/dist/modes/rpc/compact-index-pages.js +31 -0
- package/dist/modes/rpc/compact-session-state.d.ts +83 -0
- package/dist/modes/rpc/compact-session-state.js +197 -0
- package/dist/modes/rpc/compact-spool-dir.d.ts +8 -0
- package/dist/modes/rpc/compact-spool-dir.js +94 -0
- package/dist/modes/rpc/compact-spool-storage.d.ts +53 -0
- package/dist/modes/rpc/compact-spool-storage.js +162 -0
- package/dist/modes/rpc/compact-storage-io.d.ts +28 -0
- package/dist/modes/rpc/compact-storage-io.js +25 -0
- package/dist/modes/rpc/compact-transition.d.ts +41 -0
- package/dist/modes/rpc/compact-transition.js +12 -0
- package/dist/modes/rpc/connection-handler.d.ts +4 -0
- package/dist/modes/rpc/connection-handler.js +51 -13
- package/dist/modes/rpc/connection-question-bridge.d.ts +2 -1
- package/dist/modes/rpc/connection-question-bridge.js +6 -2
- package/dist/modes/rpc/extension-ui-response.d.ts +7 -2
- package/dist/modes/rpc/extension-ui-response.js +27 -7
- package/dist/modes/rpc/get-snapshot.d.ts +18 -0
- package/dist/modes/rpc/get-snapshot.js +43 -0
- package/dist/modes/rpc/host-capabilities.js +3 -0
- package/dist/modes/rpc/host-ensure-start.js +6 -3
- package/dist/modes/rpc/host-ensure-types.d.ts +2 -0
- package/dist/modes/rpc/host-ensure.js +1 -0
- package/dist/modes/rpc/host-handoff.d.ts +2 -0
- package/dist/modes/rpc/host-handover-request.d.ts +1 -1
- package/dist/modes/rpc/host-handover-request.js +4 -3
- package/dist/modes/rpc/host-handover-wire.js +6 -0
- package/dist/modes/rpc/host-idle-handover.d.ts +2 -0
- package/dist/modes/rpc/host-idle-handover.js +3 -1
- package/dist/modes/rpc/host-observe-request.js +1 -0
- package/dist/modes/rpc/host-runner.d.ts +1 -0
- package/dist/modes/rpc/host-runner.js +9 -7
- package/dist/modes/rpc/host-successor.js +4 -0
- package/dist/modes/rpc/json-normal-value.d.ts +6 -0
- package/dist/modes/rpc/json-normal-value.js +100 -0
- package/dist/modes/rpc/mcp-presenter-bootstrap.js +5 -0
- package/dist/modes/rpc/media-placeholders.d.ts +9 -3
- package/dist/modes/rpc/media-placeholders.js +12 -4
- package/dist/modes/rpc/rpc-host-command-types.d.ts +2 -0
- package/dist/modes/rpc/rpc-question-types.d.ts +1 -0
- package/dist/modes/rpc/rpc-read-response-types.d.ts +7 -0
- package/dist/modes/rpc/rpc-session-command-types.d.ts +6 -0
- package/dist/modes/rpc/rpc-session-state-types.d.ts +3 -0
- package/dist/modes/rpc/rpc-session-state.js +2 -0
- package/dist/modes/rpc/rpc-types.d.ts +1 -0
- package/dist/modes/rpc/security-presentations.js +2 -1
- package/dist/modes/rpc/session-attachment-gate.js +1 -0
- package/dist/modes/rpc/session-binding.js +30 -17
- package/dist/modes/rpc/session-command-activity.js +1 -0
- package/dist/modes/rpc/session-event-fanout.d.ts +1 -1
- package/dist/modes/rpc/session-event-fanout.js +17 -9
- package/dist/modes/rpc/session-event-writer.d.ts +2 -0
- package/dist/modes/rpc/session-event-writer.js +24 -5
- package/dist/modes/rpc/session-extension-ui-requests.d.ts +2 -1
- package/dist/modes/rpc/session-extension-ui-requests.js +15 -10
- package/dist/modes/rpc/session-held.js +1 -0
- package/dist/modes/rpc/session-record-stream.d.ts +3 -3
- package/dist/modes/rpc/session-record-stream.js +3 -3
- package/dist/modes/rpc/session-status-stream.d.ts +2 -1
- package/dist/modes/rpc/session-status-stream.js +8 -2
- package/dist/modes/rpc/session-status-subscriptions.d.ts +2 -1
- package/dist/modes/rpc/session-status-subscriptions.js +4 -0
- package/dist/modes/rpc/session-structured-lanes.d.ts +12 -0
- package/dist/modes/rpc/session-structured-lanes.js +24 -0
- package/dist/modes/rpc/session-worker-client.js +6 -5
- package/dist/modes/rpc/session-worker.js +5 -2
- package/dist/modes/rpc/snapshot-types.d.ts +29 -0
- package/dist/modes/rpc/snapshot-types.js +2 -0
- package/dist/modes/rpc/structured-session-records.d.ts +12 -0
- package/dist/modes/rpc/structured-session-records.js +88 -0
- package/dist/modes/rpc/ui-answer-ledger.d.ts +13 -0
- package/dist/modes/rpc/ui-answer-ledger.js +34 -0
- package/dist/senpi +21 -3
- package/docs/extensions.md +7 -1
- package/docs/mcp.md +20 -0
- package/docs/rpc.md +61 -2
- package/package.json +7 -6
- package/dist/bundle/chunks/azure-openai-responses-7I45DI72.js +0 -2
- package/dist/bundle/chunks/chunk-DMI55M2N.js +0 -2
- package/dist/bundle/chunks/chunk-DODH3N6U.js +0 -410
- package/dist/bundle/chunks/chunk-J37GRED2.js +0 -5
- package/dist/bundle/chunks/chunk-TBU6VYHN.js +0 -13
- package/dist/bundle/chunks/cli-main-YYH3IBC6.js +0 -3
- package/dist/bundle/chunks/dispatch-MXG5YWLV.js +0 -9
- package/dist/bundle/chunks/google-generative-ai-UM5Y7T6B.js +0 -2
- package/dist/bundle/chunks/google-vertex-OKU2VQHL.js +0 -2
- package/dist/bundle/chunks/host-command-TDLLHXVI.js +0 -2
- package/dist/bundle/chunks/interactive-mode-OEPULLZK.js +0 -2
- package/dist/bundle/chunks/openai-responses-TNHQ6SJS.js +0 -3
- package/dist/bundle/chunks/rpc-mode-ETXQWEB2.js +0 -2
- package/dist/bundle/chunks/session-control-endpoint-4LEIDIVI.js +0 -3
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { clientFacingIdentity } from "./client-admission-record.js";
|
|
2
2
|
import { ClientAdmissions } from "./client-admissions.js";
|
|
3
3
|
import { ClientMessageEvents } from "./client-message-events.js";
|
|
4
|
-
/** Subscribes `output` to the session's records; returns the unsubscribe. */
|
|
5
|
-
export function subscribeSessionRecords(session, output, onAbortSource = () => { }) {
|
|
4
|
+
/** Subscribes `output` to the session's records (from `source`, by default `session.subscribe`); returns the unsubscribe. */
|
|
5
|
+
export function subscribeSessionRecords(session, output, onAbortSource = () => { }, source = (listener) => session.subscribe(listener)) {
|
|
6
6
|
const correlatedEvents = new ClientMessageEvents(output, () => ClientAdmissions.forSession(session).hasIdentities);
|
|
7
|
-
return
|
|
7
|
+
return source((event) => {
|
|
8
8
|
if (event.type === "session_lifecycle") {
|
|
9
9
|
// The connection adds the routing handle; classic stdio has no envelope.
|
|
10
10
|
const { sessionId: _sessionId, ...record } = event;
|
|
@@ -67,7 +67,8 @@ export declare class SessionStatusStream {
|
|
|
67
67
|
publishEffect(sessionId: string, status: EffectStatus): void;
|
|
68
68
|
seal(sessionId: string, terminal: SessionStatusTerminal, cause: SessionStatusCause, by: SessionStatusActor): void;
|
|
69
69
|
forget(sessionId: string): void;
|
|
70
|
-
|
|
70
|
+
dialogTargets(sessionId: string): readonly string[];
|
|
71
|
+
mirrorTargets(sessionId: string, recordType: string, dialogs?: boolean): readonly string[];
|
|
71
72
|
matchingConnections(sessionId: string): ReadonlyMap<string, boolean>;
|
|
72
73
|
/** The live view, falling back to the last one seen once the registry has dropped a sealed entry. */
|
|
73
74
|
private currentView;
|
|
@@ -171,8 +171,14 @@ export class SessionStatusStream {
|
|
|
171
171
|
this.lastViews.delete(sessionId);
|
|
172
172
|
this.lastChanges.delete(sessionId);
|
|
173
173
|
}
|
|
174
|
-
|
|
175
|
-
|
|
174
|
+
dialogTargets(sessionId) {
|
|
175
|
+
return this.mirrorTargets(sessionId, "ui_request_pending", true);
|
|
176
|
+
}
|
|
177
|
+
mirrorTargets(sessionId, recordType, dialogs = false) {
|
|
178
|
+
const subscriptions = [...this.pendings.values(), ...this.subscriptions.values()].filter((subscription) => (dialogs ? subscription.options.dialogs === true : true) &&
|
|
179
|
+
(recordType === "snapshot_marker" || dialogs
|
|
180
|
+
? subscription.options.mirror.kind !== "none"
|
|
181
|
+
: mirrorsRecord(subscription.options.mirror, recordType)));
|
|
176
182
|
if (subscriptions.length === 0)
|
|
177
183
|
return [];
|
|
178
184
|
const entry = this.source?.entryView(sessionId) ?? this.lastViews.get(sessionId)?.entry;
|
|
@@ -29,6 +29,7 @@ export interface SubscriptionOptions {
|
|
|
29
29
|
readonly includeContext: boolean;
|
|
30
30
|
readonly mirror: MirrorSelection;
|
|
31
31
|
readonly effects: boolean;
|
|
32
|
+
readonly dialogs?: boolean;
|
|
32
33
|
}
|
|
33
34
|
export interface SubscriptionRefusal {
|
|
34
35
|
readonly reason: string;
|
|
@@ -36,7 +37,7 @@ export interface SubscriptionRefusal {
|
|
|
36
37
|
}
|
|
37
38
|
export declare function parseSubscription(request: Readonly<Pick<Extract<RpcCommand, {
|
|
38
39
|
type: "subscribe_sessions";
|
|
39
|
-
}>, "sessions" | "mirror" | "include_workers" | "include_context" | "effects">>): {
|
|
40
|
+
}>, "sessions" | "mirror" | "include_workers" | "include_context" | "effects" | "dialogs">>): {
|
|
40
41
|
readonly options: SubscriptionOptions;
|
|
41
42
|
} | {
|
|
42
43
|
readonly refusal: SubscriptionRefusal;
|
|
@@ -59,12 +59,16 @@ export function parseSubscription(request) {
|
|
|
59
59
|
const includeContext = optionalBoolean(request.include_context, "include_context");
|
|
60
60
|
if (typeof includeContext === "object")
|
|
61
61
|
return { refusal: includeContext };
|
|
62
|
+
const dialogs = optionalBoolean(request.dialogs, "dialogs");
|
|
63
|
+
if (typeof dialogs === "object")
|
|
64
|
+
return { refusal: dialogs };
|
|
62
65
|
const effects = optionalBoolean(request.effects, "effects");
|
|
63
66
|
if (typeof effects === "object")
|
|
64
67
|
return { refusal: effects };
|
|
65
68
|
return {
|
|
66
69
|
options: {
|
|
67
70
|
selector: selector.selector,
|
|
71
|
+
dialogs: dialogs ?? false,
|
|
68
72
|
// A childrenOf subscription exists to watch machine-driven children, which open as workers.
|
|
69
73
|
includeWorkers: includeWorkers ?? selector.selector.kind === "childrenOf",
|
|
70
74
|
includeContext: includeContext ?? false,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type StructuredReceiver = (record: object) => void;
|
|
2
|
+
/**
|
|
3
|
+
* Per-session receivers of the internal structured lane (senpi#4272): the host-side owner of seeded records and
|
|
4
|
+
* block controls (S03/S04) registers here. Legacy sockets, stdout and the replay snapshot never read it.
|
|
5
|
+
*/
|
|
6
|
+
export declare class SessionStructuredLanes {
|
|
7
|
+
private readonly receivers;
|
|
8
|
+
observe(sessionId: string, receiver: StructuredReceiver): () => void;
|
|
9
|
+
accept(sessionId: string, record: object): void;
|
|
10
|
+
}
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=session-structured-lanes.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-session receivers of the internal structured lane (senpi#4272): the host-side owner of seeded records and
|
|
3
|
+
* block controls (S03/S04) registers here. Legacy sockets, stdout and the replay snapshot never read it.
|
|
4
|
+
*/
|
|
5
|
+
export class SessionStructuredLanes {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.receivers = new Map();
|
|
8
|
+
}
|
|
9
|
+
observe(sessionId, receiver) {
|
|
10
|
+
const receivers = this.receivers.get(sessionId) ?? new Set();
|
|
11
|
+
receivers.add(receiver);
|
|
12
|
+
this.receivers.set(sessionId, receivers);
|
|
13
|
+
return () => {
|
|
14
|
+
receivers.delete(receiver);
|
|
15
|
+
if (receivers.size === 0 && this.receivers.get(sessionId) === receivers)
|
|
16
|
+
this.receivers.delete(sessionId);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
accept(sessionId, record) {
|
|
20
|
+
for (const receiver of [...(this.receivers.get(sessionId) ?? [])])
|
|
21
|
+
receiver(record);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=session-structured-lanes.js.map
|
|
@@ -5,6 +5,7 @@ import { ownProcessStartedAtMs } from "../../core/extensions/builtin/terminal/pr
|
|
|
5
5
|
import { isSecurityNoticeState } from "../../core/security-notices.js";
|
|
6
6
|
import { createWebViewBroker } from "../../core/webview/webview-broker.js";
|
|
7
7
|
import { roleConnection } from "./connection-roles.js";
|
|
8
|
+
import { answeredUiRequestId } from "./extension-ui-response.js";
|
|
8
9
|
import { subscriptionLimits } from "../../core/subscription-limits/limit-store.js";
|
|
9
10
|
import { SessionWorkerRequests } from "./session-worker-requests.js";
|
|
10
11
|
import { acknowledge, acknowledgeGrant } from "./session-worker-signals.js";
|
|
@@ -125,11 +126,11 @@ export class SessionWorkerClient {
|
|
|
125
126
|
if (writer.handleMcpForm(command))
|
|
126
127
|
return;
|
|
127
128
|
const connection = writer.currentConnection();
|
|
128
|
-
|
|
129
|
-
command
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
writer.acceptWorkerGrantResponse(sessionId,
|
|
129
|
+
const grantAnswer = "type" in command && command.type === "extension_ui_response"
|
|
130
|
+
? answeredUiRequestId(command)
|
|
131
|
+
: undefined;
|
|
132
|
+
if (grantAnswer !== undefined &&
|
|
133
|
+
writer.acceptWorkerGrantResponse(sessionId, grantAnswer, connection) === false)
|
|
133
134
|
return;
|
|
134
135
|
await this.request({
|
|
135
136
|
type: "command",
|
|
@@ -76,7 +76,8 @@ class WorkerEventWriter extends SessionEventWriter {
|
|
|
76
76
|
}));
|
|
77
77
|
}
|
|
78
78
|
enqueue(_sessionId, record) {
|
|
79
|
-
|
|
79
|
+
const line = JSON.stringify(record);
|
|
80
|
+
if (Buffer.byteLength(line) > SESSION_WORKER_LIMITS.outputBytes)
|
|
80
81
|
failWorker("session_worker_output_limit");
|
|
81
82
|
const session = entry?.runtime?.session;
|
|
82
83
|
if (!session)
|
|
@@ -97,7 +98,9 @@ class WorkerEventWriter extends SessionEventWriter {
|
|
|
97
98
|
failWorker("session_worker_snapshot_limit");
|
|
98
99
|
exchange((signal) => ({
|
|
99
100
|
type: "output",
|
|
100
|
-
|
|
101
|
+
// Keep one JSON-normal transfer format, including toJSON and non-cloneable fields.
|
|
102
|
+
// S12 replaces this whole-record serialization with compact records and permits.
|
|
103
|
+
record: JSON.parse(line),
|
|
101
104
|
connection: this.currentConnection(),
|
|
102
105
|
signal,
|
|
103
106
|
activity,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { SessionEntry } from "../../core/session-manager.ts";
|
|
2
|
+
import type { RpcExtensionUIRequest } from "./rpc-question-types.ts";
|
|
3
|
+
import type { RpcSessionState } from "./rpc-session-state-types.ts";
|
|
4
|
+
export type RpcSnapshot = {
|
|
5
|
+
readonly state: RpcSessionState;
|
|
6
|
+
readonly entries: SessionEntry[];
|
|
7
|
+
readonly next_before: string | null;
|
|
8
|
+
readonly history_truncated: boolean;
|
|
9
|
+
readonly markerId: string;
|
|
10
|
+
};
|
|
11
|
+
export type RpcSnapshotMarker = {
|
|
12
|
+
readonly type: "snapshot_marker";
|
|
13
|
+
readonly sessionId: string;
|
|
14
|
+
readonly markerId: string;
|
|
15
|
+
};
|
|
16
|
+
export type UiRequestChange = {
|
|
17
|
+
readonly type: "ui_request_pending";
|
|
18
|
+
readonly uiRequestId: string;
|
|
19
|
+
readonly method: RpcExtensionUIRequest["method"];
|
|
20
|
+
readonly request: RpcExtensionUIRequest;
|
|
21
|
+
} | {
|
|
22
|
+
readonly type: "ui_request_settled";
|
|
23
|
+
readonly uiRequestId: string;
|
|
24
|
+
readonly disposition: "answered" | "cancelled";
|
|
25
|
+
};
|
|
26
|
+
export type RpcUiRequestEvent = UiRequestChange & {
|
|
27
|
+
readonly sessionId: string;
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=snapshot-types.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AgentSession } from "../../core/agent-session.ts";
|
|
2
|
+
/**
|
|
3
|
+
* The engine-socket compact-updates rollout flag (`<brand>_ENGINE_SOCKET_COMPACT_UPDATES`), explicit-true only.
|
|
4
|
+
* Off, no session holds a structured subscription and every destination keeps its existing bytes.
|
|
5
|
+
*/
|
|
6
|
+
export declare function structuredLaneEnabled(): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* The session's internal structured lane, correlated like its legacy records: seeded `toJsonEvent` projections of
|
|
9
|
+
* every session event plus the three block controls, in session order. Never a legacy destination.
|
|
10
|
+
*/
|
|
11
|
+
export declare function subscribeStructuredSessionRecords(session: AgentSession, output: (record: object) => void): () => void;
|
|
12
|
+
//# sourceMappingURL=structured-session-records.d.ts.map
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { getAssistantCapture } from "@earendil-works/pi-ai";
|
|
2
|
+
import { envValue } from "../../core/brand.js";
|
|
3
|
+
import { toJsonEvent } from "../json-event.js";
|
|
4
|
+
import { subscribeSessionRecords } from "./session-record-stream.js";
|
|
5
|
+
/**
|
|
6
|
+
* The engine-socket compact-updates rollout flag (`<brand>_ENGINE_SOCKET_COMPACT_UPDATES`), explicit-true only.
|
|
7
|
+
* Off, no session holds a structured subscription and every destination keeps its existing bytes.
|
|
8
|
+
*/
|
|
9
|
+
export function structuredLaneEnabled() {
|
|
10
|
+
const value = envValue("ENGINE_SOCKET_COMPACT_UPDATES");
|
|
11
|
+
return value === "1" || value === "true";
|
|
12
|
+
}
|
|
13
|
+
const SEEDS = { blockSeeds: 1 };
|
|
14
|
+
/**
|
|
15
|
+
* Admits a block's records only after its own seed or insert reached this subscriber, so a subscriber that attached
|
|
16
|
+
* mid-message gets no seed, delta or control for that message, never a wrong one. A started block whose next record
|
|
17
|
+
* has no capture, or that has no accepted end when the message ends, is invalid: its later records are dropped and
|
|
18
|
+
* the assistant `message_end` names it in `invalidatedBlocks`, so a reader rebuilds it from the terminal message.
|
|
19
|
+
* A terminal that rewrote blocks from `rewrittenFrom` on invalidates every block at or above that index, and a
|
|
20
|
+
* `message_end` with no interpretable terminal capture (cancel, idle timeout) invalidates every block of the message.
|
|
21
|
+
* Blocks are addressed by the capture's own index (`capture.contentIndex ?? event.contentIndex`), never a drifted public one.
|
|
22
|
+
*/
|
|
23
|
+
class SeededBlockGate {
|
|
24
|
+
accept(record) {
|
|
25
|
+
if (record.type === "message_block_state" || record.type === "message_block_metadata")
|
|
26
|
+
return this.control(record, record.type === "message_block_state" ? record.phase : undefined);
|
|
27
|
+
if (record.type === "message_tool_arguments_reset")
|
|
28
|
+
return this.control(record);
|
|
29
|
+
if (record.type === "message_start" && record.message.role === "assistant") {
|
|
30
|
+
const seeded = toJsonEvent(record, SEEDS);
|
|
31
|
+
this.blocks = seeded && new Map();
|
|
32
|
+
return seeded;
|
|
33
|
+
}
|
|
34
|
+
if (record.type === "message_end" && record.message.role === "assistant")
|
|
35
|
+
return this.end(record);
|
|
36
|
+
if (record.type !== "message_update")
|
|
37
|
+
return toJsonEvent(record, SEEDS);
|
|
38
|
+
if (!this.blocks)
|
|
39
|
+
return undefined;
|
|
40
|
+
const seeded = toJsonEvent(record, SEEDS);
|
|
41
|
+
const update = record.assistantMessageEvent;
|
|
42
|
+
if (!("contentIndex" in update))
|
|
43
|
+
return seeded;
|
|
44
|
+
const index = getAssistantCapture(record)?.contentIndex ?? update.contentIndex;
|
|
45
|
+
const starts = update.type === "text_start" || update.type === "thinking_start" || update.type === "toolcall_start";
|
|
46
|
+
if (!starts && this.blocks.get(index) !== "open")
|
|
47
|
+
return undefined;
|
|
48
|
+
const ends = update.type === "text_end" || update.type === "thinking_end" || update.type === "toolcall_end";
|
|
49
|
+
this.blocks.set(index, seeded ? (ends ? "ended" : "open") : "invalid");
|
|
50
|
+
return seeded;
|
|
51
|
+
}
|
|
52
|
+
control(record, phase) {
|
|
53
|
+
const state = this.blocks?.get(record.contentIndex);
|
|
54
|
+
if (!this.blocks || state === "invalid")
|
|
55
|
+
return undefined;
|
|
56
|
+
if (phase === "insert")
|
|
57
|
+
this.blocks.set(record.contentIndex, "open");
|
|
58
|
+
else if (state === undefined || (phase === "end" && state !== "open"))
|
|
59
|
+
return undefined;
|
|
60
|
+
else if (phase === "end")
|
|
61
|
+
this.blocks.set(record.contentIndex, "ended");
|
|
62
|
+
return record;
|
|
63
|
+
}
|
|
64
|
+
end(record) {
|
|
65
|
+
const capture = getAssistantCapture(record);
|
|
66
|
+
const rewrittenFrom = capture?.message === undefined ? 0 : (capture.rewrittenFrom ?? Number.POSITIVE_INFINITY);
|
|
67
|
+
const invalidatedBlocks = [...(this.blocks ?? [])].flatMap(([index, state]) => state === "ended" && index < rewrittenFrom ? [] : [index]);
|
|
68
|
+
this.blocks = undefined;
|
|
69
|
+
const seeded = toJsonEvent(record, SEEDS) ?? record;
|
|
70
|
+
return invalidatedBlocks.length === 0
|
|
71
|
+
? seeded
|
|
72
|
+
: { ...seeded, invalidatedBlocks: invalidatedBlocks.sort((a, b) => a - b) };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The session's internal structured lane, correlated like its legacy records: seeded `toJsonEvent` projections of
|
|
77
|
+
* every session event plus the three block controls, in session order. Never a legacy destination.
|
|
78
|
+
*/
|
|
79
|
+
export function subscribeStructuredSessionRecords(session, output) {
|
|
80
|
+
const gate = new SeededBlockGate();
|
|
81
|
+
return subscribeSessionRecords(session, output, undefined, (listener) => session.subscribeStructured((record) => {
|
|
82
|
+
const accepted = gate.accept(record);
|
|
83
|
+
// Correlation reads only `type`, `role` and outer fields, which seeded records and controls keep.
|
|
84
|
+
if (accepted)
|
|
85
|
+
listener(accepted);
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=structured-session-records.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Session-generation receipts: deliberately never persisted to the transcript. */
|
|
2
|
+
export type UiAnswerReceipt = {
|
|
3
|
+
readonly uiRequestId: string;
|
|
4
|
+
readonly answerId?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare class UiAnswerLedger {
|
|
7
|
+
private readonly answers;
|
|
8
|
+
lookup(uiRequestId: string, answerId: string | undefined): "replay" | "already_answered" | undefined;
|
|
9
|
+
record(uiRequestId: string, answerId: string | undefined): void;
|
|
10
|
+
snapshot(): UiAnswerReceipt[];
|
|
11
|
+
}
|
|
12
|
+
export declare function sessionUiAnswerLedger(session: object): UiAnswerLedger;
|
|
13
|
+
//# sourceMappingURL=ui-answer-ledger.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export class UiAnswerLedger {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.answers = new Map();
|
|
4
|
+
}
|
|
5
|
+
lookup(uiRequestId, answerId) {
|
|
6
|
+
const receipt = this.answers.get(uiRequestId);
|
|
7
|
+
if (!receipt)
|
|
8
|
+
return undefined;
|
|
9
|
+
return answerId !== undefined && answerId === receipt.answerId ? "replay" : "already_answered";
|
|
10
|
+
}
|
|
11
|
+
record(uiRequestId, answerId) {
|
|
12
|
+
if (this.answers.has(uiRequestId))
|
|
13
|
+
return;
|
|
14
|
+
this.answers.set(uiRequestId, { uiRequestId, ...(answerId === undefined ? {} : { answerId }) });
|
|
15
|
+
if (this.answers.size > 1024) {
|
|
16
|
+
const oldest = this.answers.keys().next();
|
|
17
|
+
if (!oldest.done)
|
|
18
|
+
this.answers.delete(oldest.value);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
snapshot() {
|
|
22
|
+
return [...this.answers.values()].slice(-64).map((receipt) => ({ ...receipt }));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const ledgers = new WeakMap();
|
|
26
|
+
export function sessionUiAnswerLedger(session) {
|
|
27
|
+
let ledger = ledgers.get(session);
|
|
28
|
+
if (!ledger) {
|
|
29
|
+
ledger = new UiAnswerLedger();
|
|
30
|
+
ledgers.set(session, ledger);
|
|
31
|
+
}
|
|
32
|
+
return ledger;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=ui-answer-ledger.js.map
|
package/dist/senpi
CHANGED
|
@@ -10,7 +10,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
10
10
|
import "./valid-cwd.js";
|
|
11
11
|
import "./internal-role.js";
|
|
12
12
|
import { spawn, spawnSync } from "node:child_process";
|
|
13
|
-
import { existsSync, realpathSync } from "node:fs";
|
|
13
|
+
import { existsSync, fstatSync, realpathSync } from "node:fs";
|
|
14
14
|
import { dirname, join } from "node:path";
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
16
|
import { processBunRuntimeOptions, resolveBunReexec } from "./bun-runtime.js";
|
|
@@ -20,6 +20,24 @@ import { APP_NAME, DISPLAY_VERSION, findNodePackageDir, getAgentDir, getInstallP
|
|
|
20
20
|
import { hasInheritedInspectorOption, releaseInheritedInspectorForChild } from "./inspector-policy.js";
|
|
21
21
|
import { prepareRuntimeSnapshot } from "./runtime-snapshot/enter.js";
|
|
22
22
|
import { handleBootstrapSelfUpdate } from "./self-update-bootstrap.js";
|
|
23
|
+
/** Only a presenter-enabled launch may carry its reserved private channel through CLI re-execution. */
|
|
24
|
+
function reexecStdio() {
|
|
25
|
+
const argv = process.argv.slice(2);
|
|
26
|
+
const presenter = argv.indexOf("--mcp-presenter-fd");
|
|
27
|
+
if (presenter < 0 || argv[presenter + 1] !== "4")
|
|
28
|
+
return "inherit";
|
|
29
|
+
try {
|
|
30
|
+
const stat = fstatSync(4);
|
|
31
|
+
if (!stat.isSocket() && !stat.isFIFO())
|
|
32
|
+
return "inherit";
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return "inherit";
|
|
36
|
+
}
|
|
37
|
+
const owner = argv.indexOf("--owner-fd");
|
|
38
|
+
const lifetime = (owner >= 0 && argv[owner + 1] === "3") || process.env.SENPI_RPC_HOST_WATCH_FD === "3";
|
|
39
|
+
return ["inherit", "inherit", "inherit", lifetime ? 3 : "ignore", 4];
|
|
40
|
+
}
|
|
23
41
|
// Upstream's `cli/setup.ts` helper is deliberately not used here: this launcher only decides the
|
|
24
42
|
// runtime and process structure, and `cli-main.ts` performs the equivalent process/title/env/http
|
|
25
43
|
// setup for both entry paths (Node launcher and the Bun binary).
|
|
@@ -52,7 +70,7 @@ function reexecUnderBunIfNeeded() {
|
|
|
52
70
|
return false;
|
|
53
71
|
}
|
|
54
72
|
const result = spawnSync(decision.bunPath, [scriptRealPath, ...process.argv.slice(2)], {
|
|
55
|
-
stdio:
|
|
73
|
+
stdio: reexecStdio(),
|
|
56
74
|
windowsHide: true,
|
|
57
75
|
});
|
|
58
76
|
if (result.signal) {
|
|
@@ -125,7 +143,7 @@ async function spawnFullCli() {
|
|
|
125
143
|
return await new Promise((resolve, reject) => {
|
|
126
144
|
const child = spawn(process.execPath, [...process.execArgv, fullCliPath, ...args], {
|
|
127
145
|
env: childEnvironment,
|
|
128
|
-
stdio:
|
|
146
|
+
stdio: reexecStdio(),
|
|
129
147
|
});
|
|
130
148
|
child.on("error", (error) => {
|
|
131
149
|
reject(error);
|
package/docs/extensions.md
CHANGED
|
@@ -2170,7 +2170,13 @@ session-notice identity. Restart redelivers unconsumed queued messages once, but
|
|
|
2170
2170
|
never replays a consumed result or reruns an interrupted tool.
|
|
2171
2171
|
|
|
2172
2172
|
`pi.lifecycle.reportChild({ taskId, childSessionId, runEpoch, generation, state,
|
|
2173
|
-
waitingOn?, terminal? })` persists runner-owned child state.
|
|
2173
|
+
label?, since?, waitingOn?, terminal? })` persists runner-owned child state. `label`
|
|
2174
|
+
is a producer-authored name and `since` is the child's own state-entry time (ISO);
|
|
2175
|
+
an unparseable `since` is dropped. `waitingOn` takes the `SessionLifecycle.waitingOn`
|
|
2176
|
+
shape described in [RPC session lifecycle](rpc.md#session-lifecycle), named lists
|
|
2177
|
+
included; its counts stay authoritative and the child's human waits are not kept.
|
|
2178
|
+
A nonterminal report appears in the parent's `waitingOn.childReports` as
|
|
2179
|
+
`{ taskId, childSessionId, runEpoch, state, label?, since? }`. Stale epoch/generation
|
|
2174
2180
|
pairs are ignored; a higher `runEpoch` clears the old terminal status. Terminal
|
|
2175
2181
|
values are `completed`, `error`, `lost`, `interrupted`, and `cancelled`. Child UI
|
|
2176
2182
|
requests remain automatically answered by their runners, not routed to a person.
|
package/docs/mcp.md
CHANGED
|
@@ -386,6 +386,26 @@ above.
|
|
|
386
386
|
|
|
387
387
|
## Resources and prompts
|
|
388
388
|
|
|
389
|
+
MCP 2026-07-28 tool schemas use JSON Schema 2020-12 by default. Explicit
|
|
390
|
+
2020-12 declarations are supported; other dialect declarations produce
|
|
391
|
+
`MCP_SCHEMA_UNSUPPORTED_DIALECT`. Tool discovery, the disk cache, and MCP
|
|
392
|
+
exposure retain the full schema, including `$defs`, `$ref` siblings, and
|
|
393
|
+
`additionalProperties`. Boolean roots use an equivalent `allOf` container
|
|
394
|
+
at the object-shaped model-tool API boundary.
|
|
395
|
+
|
|
396
|
+
Modern structured results may be any JSON value, including `null`, `false`,
|
|
397
|
+
and `0`. Successful results with an `outputSchema` must contain conforming
|
|
398
|
+
`structuredContent`; execution-error results are exempt. Validation never
|
|
399
|
+
coerces values, inserts defaults, removes properties, or fetches references
|
|
400
|
+
from the network. Unresolved references are rejected. Schemas are bounded
|
|
401
|
+
to 64 nesting levels and 16,384 JSON nodes; `format` is an annotation.
|
|
402
|
+
|
|
403
|
+
Object-only model providers may require a lossy schema adaptation in the AI
|
|
404
|
+
provider layer. That wire adaptation does not change MCP's source schema
|
|
405
|
+
or the arguments sent to the server: modern calls validate the model's
|
|
406
|
+
arguments without coercion. Legacy connections retain the SDK's existing
|
|
407
|
+
schema validation and compatibility conversion.
|
|
408
|
+
|
|
389
409
|
- `mcp_list_resources` / `mcp_read_resource` register automatically when a
|
|
390
410
|
connected server lists resources.
|
|
391
411
|
- Mention `@mcp:<server>/<uri>` in your prompt to inline a resource's content
|
package/docs/rpc.md
CHANGED
|
@@ -145,8 +145,23 @@ The shared `SessionLifecycle` type is exported by `@code-yeongyu/senpi`:
|
|
|
145
145
|
- `seq`, `epoch`, `epochOrigin` (`human` or `automatic`), `humanInputRevision`,
|
|
146
146
|
`selfSettleEligible`, `restoring`, `persisted`, `runPaused`, and `since` (ISO time).
|
|
147
147
|
- `role` (`root` or `child`), `rootSessionId`, and optional `parentSessionId` and `taskId`.
|
|
148
|
-
- Optional `waitingOn`: `{ children, background, human
|
|
149
|
-
`source
|
|
148
|
+
- Optional `waitingOn`: `{ children, background, human, childSources?, childReports?, childReportsOmitted? }`.
|
|
149
|
+
`children` and each source's `activeCount` are the authoritative counts; every named list below is
|
|
150
|
+
supplemental and may be incomplete, so never derive a count from a list's length. `children` is the
|
|
151
|
+
larger of the nonterminal child reports and the summed `childSources` counts.
|
|
152
|
+
Background entries carry `source`, `activeCount`, optional `items`, optional `omittedItems`, and
|
|
153
|
+
optional `retryAtMs`. `childSources` entries carry `source`, `activeCount`, optional `items`, and
|
|
154
|
+
optional `omittedItems`. Each item is `{ id, label?, startedAt? }` (`startedAt` is ISO time), taken
|
|
155
|
+
from the producer's `wake_source_state` snapshot: its `items`, or the legacy `monitors` list when
|
|
156
|
+
`items` is missing or null. Terminal monitors are named by their stable `mon_` id. Each list is a
|
|
157
|
+
snapshot: entries whose `id` is not a non-blank string are dropped, duplicates collapse to one entry
|
|
158
|
+
per `id`, the list is sorted by `id`, and at most 32 entries are kept. `omittedItems` is the
|
|
159
|
+
producer's own omitted count plus any valid items cut at 32; it is not `activeCount` minus the list
|
|
160
|
+
length. Invalid detail drops only the detail, never the count.
|
|
161
|
+
`childReports` lists nonterminal reports from `reportChild` as
|
|
162
|
+
`{ taskId, childSessionId, runEpoch, state, label?, since? }`, excluding reports about the session
|
|
163
|
+
itself, sorted by `taskId` and capped at 32; `childReportsOmitted` counts the reports cut by that cap.
|
|
164
|
+
Human entries carry `kind`,
|
|
150
165
|
`originSessionId`, `requestId`, `revision`, `since`, and optional child identity/label.
|
|
151
166
|
Human kinds are `question`, `approval`, `goal_blocked`, `goal_paused`, `stalled`,
|
|
152
167
|
and `interrupted_run`; attention remains visible even when a hold wins precedence.
|
|
@@ -1644,6 +1659,7 @@ A multi-session host advertising the capability `session_status` pushes one `ses
|
|
|
1644
1659
|
- `include_context`: carry each session's published `context` on its records; default `false`.
|
|
1645
1660
|
- `mirror`: `"none"` (default), `"all"` or an array of record types (`["message_update", "tool_execution_start"]`). The matched sessions' records of those types are also delivered to this connection. Mirroring is an explicit opt-in open to every subscriber of the host (the socket is per user, mode 0600): it is not an attachment and does not keep a session alive. Worker content is mirrored only with `include_workers: true`.
|
|
1646
1661
|
- `effects`: also deliver `effect_status` receipts of matched sessions; default `true` for `childrenOf`, `false` otherwise. Each `effect_status` is enqueued after the record that caused the transition and shares the subscription's `seq`.
|
|
1662
|
+
- `dialogs`: with capability `dialog_observer`, also deliver the `ui_request_pending` and `ui_request_settled` records of matched sessions; default `false`. It takes effect only together with a `mirror` selection, stays observing, and grants no answering authority (see "UI-answer receipts and dialog observation").
|
|
1647
1663
|
|
|
1648
1664
|
Response:
|
|
1649
1665
|
|
|
@@ -3425,6 +3441,14 @@ If an extension cancelled:
|
|
|
3425
3441
|
|
|
3426
3442
|
### State
|
|
3427
3443
|
|
|
3444
|
+
#### get_snapshot
|
|
3445
|
+
|
|
3446
|
+
Atomic snapshot cursor (capability `snapshot_cursor`). Subscribe with `mirror` before taking a snapshot to cut the live record stream at a source-issued cursor rather than at response arrival. Terminal control endpoints support the same command.
|
|
3447
|
+
|
|
3448
|
+
`get_snapshot {sessionId, tail?, maxBytes?, observe?: true}` returns `{state, entries, next_before, history_truncated, markerId}`. `state` uses the existing `get_state` projection, including `pendingDialogs` and `pendingQuestions`. `entries` is the newest tail, in chronological order. `tail` defaults to 100 and accepts non-negative integers; `maxBytes` defaults to 8 MiB and accepts positive integers, capped at 48 MiB. The byte bound applies to serialized history entries. An entry that does not fit ends the tail; it is never silently skipped. `history_truncated` reports omitted history; `next_before` is the oldest returned entry's id when older history remains, otherwise null (also null when no entry fits).
|
|
3449
|
+
|
|
3450
|
+
State capture, history capture, and enqueueing `{type: "snapshot_marker", sessionId, markerId}` are one synchronous operation. The marker goes only to the requesting connection, only when a matching subscription has `mirror` enabled (including a list of selected record types). Other subscribers never receive that marker. Apply the snapshot and then records after its marker; a post-marker record can arrive **before** the correlated response. A reader without a mirrored subscription receives the snapshot response but no marker record. `observe: true` does not attach or refresh activity.
|
|
3451
|
+
|
|
3428
3452
|
#### get_state
|
|
3429
3453
|
|
|
3430
3454
|
Get current session state.
|
|
@@ -5490,6 +5514,22 @@ With enforcement, only the authority's winning whole-form action admits once.
|
|
|
5490
5514
|
The host advertises `mcp_form_presenter_v1` only when enforcement is enabled;
|
|
5491
5515
|
the capability reports protocol support, not authority to present or answer a form.
|
|
5492
5516
|
|
|
5517
|
+
The public `host ensure` and `host handoff` commands accept the same deployment option,
|
|
5518
|
+
separately from `--launch-spec`. Add `--mcp-presenter-fd 4` with a live inherited duplex
|
|
5519
|
+
channel to enroll the launch owner of a new host. The runtime-selecting CLI re-exec,
|
|
5520
|
+
supervisor and host child preserve that channel. The option alone enables enforcement,
|
|
5521
|
+
not a presenter; fd 4 alone does not enable enforcement.
|
|
5522
|
+
|
|
5523
|
+
An enforcing predecessor keeps enforcement in its successor, including when an older
|
|
5524
|
+
handoff caller omits the option. Conditional `handoff --when idle` carries the non-secret
|
|
5525
|
+
`mcp_presenter_enforcement` boolean in `begin_handover`, independently of the launch
|
|
5526
|
+
specification and environment. It uses only the existing authenticated owner's channel
|
|
5527
|
+
for fresh successor enrollment; the CLI cannot enroll itself into the predecessor.
|
|
5528
|
+
Reuse and already-current handover answers report the serving host's actual capabilities.
|
|
5529
|
+
Neither a successful CLI exit nor an equal `runtimeBuildId` proves enforcement or
|
|
5530
|
+
enrollment. A deployment requesting enforcement against an unenforced existing host must
|
|
5531
|
+
coordinate a replacement, not force-restart another owner's busy host.
|
|
5532
|
+
|
|
5493
5533
|
The native launch owner enrolls an Ed25519 public key through an inherited private
|
|
5494
5534
|
bootstrap channel. Descriptor 4 is reserved for this channel; descriptor 3 remains
|
|
5495
5535
|
the separate owner-lifetime channel. Enrollment and management proofs sign the
|
|
@@ -5901,6 +5941,25 @@ Dismiss any dialog method. The extension receives `undefined` (for select/input/
|
|
|
5901
5941
|
{"type": "extension_ui_response", "id": "uuid-3", "cancelled": true}
|
|
5902
5942
|
```
|
|
5903
5943
|
|
|
5944
|
+
### UI-answer receipts and dialog observation
|
|
5945
|
+
|
|
5946
|
+
With capability `ui_answer_ledger`, `extension_ui_response` accepts an optional `answerId` string of 1-256 characters. The response preserves the frame's correlation `id` and adds `disposition`:
|
|
5947
|
+
|
|
5948
|
+
- `applied`: success; the pending request was settled once.
|
|
5949
|
+
- `replay`: success; this `(uiRequestId, answerId)` pair was already applied, with no repeated delivery.
|
|
5950
|
+
- `already_answered`: failure; the request was already settled with a different answer id.
|
|
5951
|
+
- `unknown`: failure; no pending request or receipt exists (`unknown_extension_ui_request`).
|
|
5952
|
+
|
|
5953
|
+
A malformed answer (for example `invalid_answer_id` or `question_incomplete`) is refused without a `disposition` and leaves its request pending. A single-session stdio connection still ignores an unnamed response that matches no request; a named response always gets a reply.
|
|
5954
|
+
|
|
5955
|
+
`get_state.answeredUiRequests` contains the latest 64 receipts, oldest first, as `{uiRequestId, answerId?}`. Receipts are session-local and memory-only, retained for that session's life in the host generation. The ledger evicts FIFO beyond 1,024 requests; replay does not extend retention. Omitting `answerId` keeps the short-form answer contract but provides no named replay identity. A restart, unloaded session, or evicted receipt is not proof of non-execution.
|
|
5956
|
+
|
|
5957
|
+
With capability `dialog_observer`, `subscribe_sessions` accepts `dialogs?: boolean` (default false). A matching `dialogs: true` subscription must also enable `mirror`. It receives these new records on its connection FIFO:
|
|
5958
|
+
|
|
5959
|
+
`{type: "ui_request_pending", sessionId, uiRequestId, method, request}` when a dialog or question is registered, with its original request frame; `{type: "ui_request_settled", sessionId, uiRequestId, disposition: "answered" | "cancelled"}` when it settles. Timeout and lifecycle teardown count as cancellation. The feed survives the command connection's departure while the session remains loaded. A dialog already present in the snapshot is not emitted again.
|
|
5960
|
+
|
|
5961
|
+
The subscription remains observing: it creates no attachment and carries no correlated `response` records. The original select, confirm, input, and editor `extension_ui_request` records remain targeted, not mirrored. Use a separate attached command connection for answers; dialog observation grants no answering authority.
|
|
5962
|
+
|
|
5904
5963
|
## Error Handling
|
|
5905
5964
|
|
|
5906
5965
|
Failed commands return a response with `success: false`:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/senpi",
|
|
3
|
-
"version": "2026.10.
|
|
3
|
+
"version": "2026.10.26-2",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"piConfig": {
|
|
@@ -71,10 +71,11 @@
|
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"@earendil-works/chord": "0.99.1",
|
|
74
|
-
"@earendil-works/pi-agent-core": "npm:@code-yeongyu/senpi-agent-core@2026.10.
|
|
75
|
-
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.10.
|
|
76
|
-
"@earendil-works/pi-tui": "npm:@code-yeongyu/senpi-tui@2026.10.
|
|
74
|
+
"@earendil-works/pi-agent-core": "npm:@code-yeongyu/senpi-agent-core@2026.10.26-2",
|
|
75
|
+
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.10.26-2",
|
|
76
|
+
"@earendil-works/pi-tui": "npm:@code-yeongyu/senpi-tui@2026.10.26-2",
|
|
77
77
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
78
|
+
"ajv": "8.20.0",
|
|
78
79
|
"chalk": "6.0.0",
|
|
79
80
|
"cross-spawn": "7.0.6",
|
|
80
81
|
"diff": "9.0.0",
|
|
@@ -92,8 +93,8 @@
|
|
|
92
93
|
"yaml": "2.9.1",
|
|
93
94
|
"@anthropic-ai/claude-agent-sdk": "0.3.306",
|
|
94
95
|
"@anthropic-ai/sdk": "0.127.0",
|
|
95
|
-
"@code-yeongyu/senpi-codemode": "2026.10.
|
|
96
|
-
"@earendil-works/pi-pty": "npm:@code-yeongyu/senpi-pty@2026.10.
|
|
96
|
+
"@code-yeongyu/senpi-codemode": "2026.10.26-2",
|
|
97
|
+
"@earendil-works/pi-pty": "npm:@code-yeongyu/senpi-pty@2026.10.26-2",
|
|
97
98
|
"@modelcontextprotocol/sdk": "1.32.1",
|
|
98
99
|
"@mozilla/readability": "0.6.0",
|
|
99
100
|
"linkedom": "0.18.13",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
-
import{AzureOpenAI}from"./chunk-CD2HJK4C.js";import{getPiUserAgent}from"./chunk-QTG7MY2X.js";import{buildBaseOptions}from"./chunk-GSSD3R5X.js";import{retryProviderRequest}from"./chunk-EDOW5W5H.js";import{deriveOpenAIPromptCacheKey}from"./chunk-3BTN337S.js";import{formatProviderError,normalizeProviderError}from"./chunk-TAV6QZFM.js";import"./chunk-PELNNWGO.js";import{convertResponsesMessages,convertResponsesTools,processResponsesStream}from"./chunk-E4LBKOZG.js";import"./chunk-GVSBCJFI.js";import"./chunk-HK46JMSC.js";import{createGrammarToolInputProperties}from"./chunk-4P7WARQZ.js";import"./chunk-WDTJ6JKE.js";import{getProviderEnvValue}from"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import{clampThinkingLevel,getDeclaredTools,resolveTranscript,resolveTranscriptTools,supportsMax}from"./chunk-6AOVUTUR.js";import"./chunk-45SZOLCU.js";import{AssistantMessageEventStream}from"./chunk-DMI55M2N.js";import{headersToRecord}from"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";var DEFAULT_AZURE_API_VERSION="v1",AZURE_TOOL_CALL_PROVIDERS=new Set(["openai","chatgpt-subscription","opencode","azure-openai-responses"]),OPENAI_RESPONSES_MIN_OUTPUT_TOKENS=16;function parseDeploymentNameMap(value){let map=new Map;if(!value)return map;for(let entry of value.split(",")){let trimmed=entry.trim();if(!trimmed)continue;let[modelId,deploymentName]=trimmed.split("=",2);!modelId||!deploymentName||map.set(modelId.trim(),deploymentName.trim())}return map}function resolveDeploymentName(model,options){return options?.azureDeploymentName?options.azureDeploymentName:parseDeploymentNameMap(getProviderEnvValue("AZURE_OPENAI_DEPLOYMENT_NAME_MAP",options?.env)).get(model.id)||model.id}function formatAzureOpenAIError(error){return formatProviderError(normalizeProviderError(error),"Azure OpenAI API error")}var stream=(model,context,options)=>{let stream2=new AssistantMessageEventStream,normalizedContext=resolveTranscript(context,model.compat?.supportsMidConvoSystemMessages);return(async()=>{let deploymentName=resolveDeploymentName(model,options),output={role:"assistant",content:[],api:"azure-openai-responses",provider:model.provider,model:model.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"pending",timestamp:Date.now()};try{let apiKey=options?.apiKey;if(!apiKey)throw new Error(`No API key for provider: ${model.provider}`);let client=createClient(model,apiKey,options),grammarToolInputProperties=createGrammarToolInputProperties(getDeclaredTools(normalizedContext.messages),model.compat?.supportsOpenAIGrammarTools??!1),params=buildParams(model,normalizedContext,options,deploymentName,grammarToolInputProperties),nextParams=await options?.onPayload?.(params,model);nextParams!==void 0&&(params=nextParams);let requestOptions={...options?.signal?{signal:options.signal}:{},...options?.timeoutMs!==void 0?{timeout:options.timeoutMs}:{},maxRetries:0},{data:openaiStream,response}=await retryProviderRequest(()=>client.responses.create(params,requestOptions).withResponse(),{maxRetries:options?.maxRetries,maxRetryDelayMs:options?.maxRetryDelayMs,signal:options?.signal});if(await options?.onResponse?.({status:response.status,headers:headersToRecord(response.headers)},model),stream2.push({type:"start",partial:output}),await processResponsesStream(openaiStream,output,stream2,model,{onProviderStreamEvent:options?.onProviderStreamEvent,grammarToolInputProperties}),options?.signal?.aborted)throw new Error("Request was aborted");if(output.stopReason==="pending")throw new Error("Azure OpenAI Responses stream ended without a stop reason");if(output.stopReason==="aborted"||output.stopReason==="error")throw new Error(output.errorMessage||"An unknown error occurred");stream2.push({type:"done",reason:output.stopReason,message:output}),stream2.end()}catch(error){for(let block of output.content)delete block.index,delete block.partialJson,delete block.customInput;output.stopReason=options?.signal?.aborted?"aborted":"error",output.errorMessage=formatAzureOpenAIError(error),stream2.push({type:"error",reason:output.stopReason,error:output}),stream2.end()}})(),stream2},streamSimple=(model,context,options)=>{let apiKey=options?.apiKey;if(!apiKey)throw new Error(`No API key for provider: ${model.provider}`);let base={...buildBaseOptions(model,context,options,apiKey),toolChoice:options?.toolChoice},clampedReasoning=options?.reasoning?clampThinkingLevel(model,options.reasoning):void 0,reasoningEffort=clampedReasoning==="off"?void 0:clampedReasoning==="max"&&supportsMax(model)?"max":clampedReasoning==="max"?"high":clampedReasoning;return stream(model,context,{...base,reasoningEffort})};function normalizeAzureBaseUrl(baseUrl){let trimmed=baseUrl.trim().replace(/\/+$/,""),url;try{url=new URL(trimmed)}catch{throw new Error(`Invalid Azure OpenAI base URL: ${baseUrl}`)}let isAzureHost=url.hostname.endsWith(".openai.azure.com")||url.hostname.endsWith(".cognitiveservices.azure.com")||url.hostname.endsWith(".ai.azure.com"),normalizedPath=url.pathname.replace(/\/+$/,"");return isAzureHost&&(normalizedPath===""||normalizedPath==="/"||normalizedPath==="/openai"||normalizedPath==="/openai/v1/responses")&&(url.pathname="/openai/v1",url.search=""),url.toString().replace(/\/+$/,"")}function buildDefaultBaseUrl(resourceName){return`https://${resourceName}.openai.azure.com/openai/v1`}function resolveAzureConfig(model,options){let apiVersion=options?.azureApiVersion||getProviderEnvValue("AZURE_OPENAI_API_VERSION",options?.env)||DEFAULT_AZURE_API_VERSION,baseUrl=options?.azureBaseUrl?.trim()||getProviderEnvValue("AZURE_OPENAI_BASE_URL",options?.env)?.trim()||void 0,resourceName=options?.azureResourceName||getProviderEnvValue("AZURE_OPENAI_RESOURCE_NAME",options?.env),resolvedBaseUrl=baseUrl;if(!resolvedBaseUrl&&resourceName&&(resolvedBaseUrl=buildDefaultBaseUrl(resourceName)),!resolvedBaseUrl&&model.baseUrl&&(resolvedBaseUrl=model.baseUrl),!resolvedBaseUrl)throw new Error("Azure OpenAI base URL is required. Set AZURE_OPENAI_BASE_URL or AZURE_OPENAI_RESOURCE_NAME, or pass azureBaseUrl, azureResourceName, or model.baseUrl.");return{baseUrl:normalizeAzureBaseUrl(resolvedBaseUrl),apiVersion}}function createClient(model,apiKey,options){let headers={"User-Agent":getPiUserAgent(),...model.headers};options?.headers&&Object.assign(headers,options.headers);let{baseUrl,apiVersion}=resolveAzureConfig(model,options);return new AzureOpenAI({apiKey,apiVersion,dangerouslyAllowBrowser:!0,fetch:options?.fetch,defaultHeaders:headers,baseURL:baseUrl})}function buildParams(model,context,options,deploymentName,grammarToolInputProperties=createGrammarToolInputProperties(getDeclaredTools(context.messages),model.compat?.supportsOpenAIGrammarTools??!1)){let requestedReasoningEffort=options?.reasoningEffort??(options?.reasoningSummary?"medium":void 0),mappedReasoningEffort=requestedReasoningEffort===void 0?void 0:model.thinkingLevelMap?.[requestedReasoningEffort],reasoningEffort=mappedReasoningEffort===void 0?requestedReasoningEffort:mappedReasoningEffort,reasoningRequested=reasoningEffort!=null,reasoningUnavailable=reasoningEffort===null,supportsAdditionalTools=model.compat?.supportsAdditionalTools??!1,supportsToolSearch=model.compat?.supportsToolSearch??!1,transcriptTools=resolveTranscriptTools(context.messages,supportsAdditionalTools||supportsToolSearch),messages=convertResponsesMessages(model,context,AZURE_TOOL_CALL_PROVIDERS,{grammarToolInputProperties,supportsMidConvoSystemMessages:model.compat?.supportsMidConvoSystemMessages??!1,supportsAdditionalTools,supportsToolSearch,toolOptions:{supportsStrictMode:model.compat?.supportsStrictMode??!0,supportsOpenAIGrammarTools:model.compat?.supportsOpenAIGrammarTools??!1}}),params={model:deploymentName,input:messages,stream:!0,...(options?.cacheRetention??model.cacheRetention)==="none"?{}:{prompt_cache_key:deriveOpenAIPromptCacheKey(model.id,context)},store:!1};return options?.maxTokens&&(params.max_output_tokens=Math.max(options.maxTokens,OPENAI_RESPONSES_MIN_OUTPUT_TOKENS)),options?.temperature!==void 0&&(params.temperature=options?.temperature),transcriptTools.requestTools.length>0&&(params.tools=convertResponsesTools(transcriptTools.requestTools,{supportsStrictMode:model.compat?.supportsStrictMode??!0,supportsOpenAIGrammarTools:model.compat?.supportsOpenAIGrammarTools??!1})),options?.toolChoice!==void 0&&(params.tool_choice=options.toolChoice),model.reasoning&&(reasoningRequested?(params.reasoning={effort:reasoningEffort,...options?.reasoningSummary===null?{}:{summary:options?.reasoningSummary||"auto"}},params.include=["reasoning.encrypted_content"]):!reasoningUnavailable&&model.thinkingLevelMap?.off!==null&&(params.reasoning={effort:model.thinkingLevelMap?.off??"none"})),Object.assign(params,model.samplingParams,options?.samplingParams),params}export{stream,streamSimple};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
-
var FifoQueue=class{constructor(){this.incoming=[],this.outgoing=[]}get length(){return this.incoming.length+this.outgoing.length}enqueue(value){this.incoming.push(value)}dequeue(){if(this.outgoing.length===0)for(;this.incoming.length>0;)this.outgoing.push(this.incoming.pop());return this.outgoing.pop()}},EventStream=class{#queue;#queueHead;#failed;#error;#localWorkDepth;constructor(isComplete,extractResult){this.#queue=[],this.#queueHead=0,this.waiting=new FifoQueue,this.done=!1,this.#failed=!1,this.#localWorkDepth=0,this.isComplete=isComplete,this.extractResult=extractResult,this.finalResultPromise=new Promise((resolve,reject)=>{this.resolveFinalResult=resolve,this.rejectFinalResult=reject}),this.finalResultPromise.catch(()=>{})}get queue(){return this.#queue.slice(this.#queueHead)}#enqueue(event){this.#queue.push(event)}#dequeue(){let event=this.#queue[this.#queueHead];if(event===void 0)throw new Error("EventStream queue underflow");return this.#queueHead++,this.#queueHead>1024&&this.#queueHead*2>=this.#queue.length&&(this.#queue=this.#queue.slice(this.#queueHead),this.#queueHead=0),event}push(event){if(this.done)return;this.isComplete(event)&&(this.done=!0,this.resolveFinalResult(this.extractResult(event)));let waiter=this.waiting.dequeue();waiter?waiter.resolve({value:event,done:!1}):this.#enqueue(event)}end(result){for(this.done=!0,result!==void 0&&this.resolveFinalResult(result);this.waiting.length>0;){let waiter=this.waiting.dequeue();waiter&&waiter.resolve({value:void 0,done:!0})}}fail(error){if(!this.done)for(this.done=!0,this.#failed=!0,this.#error=error,this.rejectFinalResult(error);this.waiting.length>0;){let waiter=this.waiting.dequeue();waiter&&waiter.reject(error)}}[Symbol.asyncIterator](){return{next:()=>this.#queueHead<this.#queue.length?Promise.resolve({value:this.#dequeue(),done:!1}):this.#failed?Promise.reject(this.#error):this.done?Promise.resolve({value:void 0,done:!0}):new Promise((resolve,reject)=>this.waiting.enqueue({resolve,reject}))}}result(){return this.finalResultPromise}async trackLocalWork(work){this.#localWorkDepth++;try{return await work}finally{this.#localWorkDepth--}}hasPendingLocalWork(){return this.#localWorkDepth>0}},AssistantMessageEventStream=class extends EventStream{constructor(){super(event=>event.type==="done"||event.type==="error",event=>{if(event.type==="done")return event.message;if(event.type==="error")return event.error;throw new Error("Unexpected event type for final result")})}};function createAssistantMessageEventStream(){return new AssistantMessageEventStream}function formatThrownValue(value){return value instanceof Error?value.message||value.name:typeof value=="string"?value:String(value)}function extractDiagnosticError(error){if(!(error instanceof Error))return{name:"ThrownValue",message:formatThrownValue(error)};let code=error.code;return{name:error.name||void 0,message:error.message||error.name,stack:error.stack,code:typeof code=="string"||typeof code=="number"?code:void 0}}function createAssistantMessageDiagnostic(type,error,details){return{type,timestamp:Date.now(),error:extractDiagnosticError(error),details}}function appendAssistantMessageDiagnostic(message,diagnostic){message.diagnostics=[...message.diagnostics??[],diagnostic]}export{EventStream,AssistantMessageEventStream,createAssistantMessageEventStream,formatThrownValue,extractDiagnosticError,createAssistantMessageDiagnostic,appendAssistantMessageDiagnostic};
|