@code-yeongyu/senpi 2026.11.6-2 → 2026.11.9
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 +52 -0
- package/dist/bundle/chunks/{bun-extension-importer-RCGPQTI2.js → bun-extension-importer-GQ6IKEXD.js} +2 -2
- package/dist/bundle/chunks/{chunk-GSKCWXXG.js → chunk-3CRPNPTR.js} +1 -1
- package/dist/bundle/chunks/{chunk-RQ6CHXQ2.js → chunk-3TZQXZKH.js} +1 -1
- package/dist/bundle/chunks/{chunk-QN2BHP3M.js → chunk-44BJPS5I.js} +1 -1
- package/dist/bundle/chunks/{chunk-WGRKM3N6.js → chunk-45MVD7BU.js} +1 -1
- package/dist/bundle/chunks/chunk-4JIBEZZE.js +106 -0
- package/dist/bundle/chunks/{chunk-CF5OGBC4.js → chunk-4NYNMAYF.js} +1 -1
- package/dist/bundle/chunks/{chunk-X5ZVYNOL.js → chunk-4UR6UFBH.js} +1 -1
- package/dist/bundle/chunks/{chunk-LNPAT22L.js → chunk-527Q2UYM.js} +9 -8
- package/dist/bundle/chunks/{chunk-HLM46XEB.js → chunk-622VYTRI.js} +1 -1
- package/dist/bundle/chunks/{chunk-GKAYPJ4E.js → chunk-7PROV6BB.js} +1 -1
- package/dist/bundle/chunks/{chunk-4E7GDG4H.js → chunk-7VMEE62L.js} +1 -1
- package/dist/bundle/chunks/{chunk-ECW7VBMB.js → chunk-HXNXISJD.js} +1 -1
- package/dist/bundle/chunks/{chunk-C7OKUC7L.js → chunk-K3UHGDUQ.js} +1 -1
- package/dist/bundle/chunks/{chunk-47PPZKPO.js → chunk-LM6DOWQH.js} +4 -4
- package/dist/bundle/chunks/chunk-LPYBKMPT.js +2 -0
- package/dist/bundle/chunks/{chunk-2FDW2LQL.js → chunk-M7GF73FO.js} +2 -2
- package/dist/bundle/chunks/{chunk-D5MRJWUK.js → chunk-OCMGRBJ5.js} +221 -229
- package/dist/bundle/chunks/{chunk-TIPKAMSS.js → chunk-SGAFIMAU.js} +1 -1
- package/dist/bundle/chunks/{chunk-7PSBD5KS.js → chunk-STGOYIXC.js} +1 -1
- package/dist/bundle/chunks/{chunk-DSWDJ7HT.js → chunk-WQ4RBPMS.js} +1 -1
- package/dist/bundle/chunks/{chunk-7III44PV.js → chunk-WX2HB4DD.js} +1 -1
- package/dist/bundle/chunks/chunk-XZDCMDUH.js +2 -0
- package/dist/bundle/chunks/{chunk-GNSMNSL7.js → chunk-Y5L4UFMI.js} +2 -2
- package/dist/bundle/chunks/{cli-main-T74YJGIF.js → cli-main-E4NDWAUD.js} +1 -1
- package/dist/bundle/chunks/{dispatch-BAK2YZKD.js → dispatch-VDIYSXQN.js} +1 -1
- package/dist/bundle/chunks/{hand-entry-AYRUGE2A.js → hand-entry-5X5Z5Y3D.js} +1 -1
- package/dist/bundle/chunks/{headless-host-ES74ZB6M.js → headless-host-YXUGONR3.js} +1 -1
- package/dist/bundle/chunks/{host-command-YRXZE4TV.js → host-command-VHX2ILLM.js} +1 -1
- package/dist/bundle/chunks/{host-session-command-N7IN7ZDV.js → host-session-command-P3MRW63Z.js} +1 -1
- package/dist/bundle/chunks/interactive-mode-XUSBLLWI.js +2 -0
- package/dist/bundle/chunks/main-3TWVKTJN.js +2 -0
- package/dist/bundle/chunks/{multi-session-host-XSUJDHFZ.js → multi-session-host-HRGM66PY.js} +20 -17
- package/dist/bundle/chunks/{package-manager-cli-GLUNPQJU.js → package-manager-cli-WSH7U4YE.js} +1 -1
- package/dist/bundle/chunks/{role-RRFFHZF5.js → role-4BUU46VW.js} +3 -3
- package/dist/bundle/chunks/{rotation-stream-BN2YK2MC.js → rotation-stream-TODBIHXJ.js} +1 -1
- package/dist/bundle/chunks/rpc-mode-OAPIV46G.js +2 -0
- package/dist/bundle/chunks/{run-attached-tui-W236SEOR.js → run-attached-tui-MXCC5IZR.js} +1 -1
- package/dist/bundle/chunks/{runtime-session-OBXYK4PI.js → runtime-session-VO3X4OE3.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-B2EJTBOE.js → schedule-command-MX56D6UE.js} +1 -1
- package/dist/bundle/chunks/{session-control-endpoint-YIMLHGLG.js → session-control-endpoint-IL6ERD4U.js} +1 -1
- package/dist/bundle/chunks/{session-picker-E6ZONUJB.js → session-picker-6VRC25MJ.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +114 -110
- package/dist/bundle/cli.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/core/agent-session-runtime.d.ts +2 -0
- package/dist/core/agent-session-runtime.js +9 -2
- package/dist/core/agent-session-services.d.ts +2 -0
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session.d.ts +32 -3
- package/dist/core/agent-session.js +142 -29
- package/dist/core/credential-pool/rotation-slots.d.ts +3 -3
- package/dist/core/credential-pool/state-store.d.ts +1 -1
- package/dist/core/egress/classify.d.ts +8 -3
- package/dist/core/egress/classify.js +177 -158
- package/dist/core/egress/console-redactor.d.ts +7 -0
- package/dist/core/egress/console-redactor.js +74 -0
- package/dist/core/egress/credentials.d.ts +73 -0
- package/dist/core/egress/credentials.js +20 -0
- package/dist/core/egress/device-custody.d.ts +1 -1
- package/dist/core/egress/device-custody.js +18 -15
- package/dist/core/egress/device-proxy-call.d.ts +59 -0
- package/dist/core/egress/device-proxy-call.js +148 -0
- package/dist/core/egress/device-proxy-lost-calls.d.ts +27 -0
- package/dist/core/egress/device-proxy-lost-calls.js +28 -0
- package/dist/core/egress/device-proxy-ports.d.ts +49 -0
- package/dist/core/egress/device-proxy-ports.js +2 -0
- package/dist/core/egress/device-proxy-request.d.ts +34 -0
- package/dist/core/egress/device-proxy-request.js +69 -0
- package/dist/core/egress/device-proxy-waits.d.ts +40 -0
- package/dist/core/egress/device-proxy-waits.js +67 -0
- package/dist/core/egress/device-proxy.d.ts +3 -0
- package/dist/core/egress/device-proxy.js +214 -0
- package/dist/core/egress/endpoint.js +2 -1
- package/dist/core/egress/entry-verify.d.ts +13 -0
- package/dist/core/egress/entry-verify.js +33 -0
- package/dist/core/egress/hpke.d.ts +63 -0
- package/dist/core/egress/hpke.js +192 -0
- package/dist/core/egress/key-policy-template.d.ts +7 -1
- package/dist/core/egress/ledger-schema.d.ts +80 -0
- package/dist/core/egress/ledger-schema.js +117 -0
- package/dist/core/egress/ledger.d.ts +55 -0
- package/dist/core/egress/ledger.js +159 -0
- package/dist/core/egress/pinned-infra.d.ts +23 -2
- package/dist/core/egress/pinned-infra.js +9 -2
- package/dist/core/egress/placement-claim.d.ts +69 -0
- package/dist/core/egress/placement-claim.js +115 -0
- package/dist/core/egress/pool-state.d.ts +18 -0
- package/dist/core/egress/pool-state.js +5 -0
- package/dist/core/egress/redact.d.ts +10 -0
- package/dist/core/egress/redact.js +134 -0
- package/dist/core/egress/sealed-format.d.ts +101 -0
- package/dist/core/egress/sealed-format.js +174 -0
- package/dist/core/egress/sealed-source.d.ts +35 -0
- package/dist/core/egress/sealed-source.js +140 -0
- package/dist/core/egress/verified-keys.js +1 -1
- package/dist/core/egress/wire.d.ts +228 -0
- package/dist/core/egress/wire.js +49 -0
- package/dist/core/extensions/builtin/ask-user/escape-residue.d.ts +50 -0
- package/dist/core/extensions/builtin/ask-user/escape-residue.js +113 -0
- package/dist/core/extensions/builtin/ask-user/extension.js +7 -1
- package/dist/core/extensions/builtin/ask-user/resume.js +2 -1
- package/dist/core/extensions/builtin/ask-user/tool.d.ts +3 -0
- package/dist/core/extensions/builtin/ask-user/tool.js +8 -0
- package/dist/core/extensions/builtin/goal/index.js +46 -0
- package/dist/core/extensions/builtin/goal/stop-pause.d.ts +1 -0
- package/dist/core/extensions/builtin/goal/stop-pause.js +4 -2
- package/dist/core/extensions/builtin/monitor-state-event.d.ts +26 -0
- package/dist/core/extensions/builtin/monitor-state-event.js +2 -0
- package/dist/core/extensions/builtin/permission-system/index.js +10 -4
- package/dist/core/extensions/builtin/permission-system/preset-registry.d.ts +2 -0
- package/dist/core/extensions/builtin/permission-system/preset-registry.js +11 -0
- package/dist/core/extensions/builtin/permission-system/settings.d.ts +2 -0
- package/dist/core/extensions/builtin/permission-system/settings.js +10 -1
- package/dist/core/extensions/builtin/terminal/background-age.d.ts +25 -0
- package/dist/core/extensions/builtin/terminal/background-age.js +91 -0
- package/dist/core/extensions/builtin/terminal/extension-state.d.ts +1 -1
- package/dist/core/extensions/builtin/terminal/extension-state.js +21 -3
- package/dist/core/extensions/builtin/terminal/notify.d.ts +6 -0
- package/dist/core/extensions/builtin/terminal/notify.js +39 -5
- package/dist/core/extensions/builtin/terminal/session-bundle.d.ts +9 -2
- package/dist/core/extensions/builtin/terminal/session-bundle.js +36 -1
- package/dist/core/extensions/builtin/terminal/settings.d.ts +2 -0
- package/dist/core/extensions/builtin/terminal/settings.js +8 -0
- package/dist/core/extensions/builtin/terminal/tools/background-auto-reap.d.ts +15 -0
- package/dist/core/extensions/builtin/terminal/tools/background-auto-reap.js +87 -0
- package/dist/core/extensions/builtin/terminal/tools/bash.d.ts +3 -1
- package/dist/core/extensions/builtin/terminal/tools/bash.js +44 -15
- package/dist/core/extensions/builtin/terminal/tools/child-placement.d.ts +8 -0
- package/dist/core/extensions/builtin/terminal/tools/child-placement.js +43 -6
- package/dist/core/extensions/builtin/terminal/tools/context.d.ts +14 -2
- package/dist/core/extensions/bun-extension-importer.js +4 -3
- package/dist/core/extensions/bun-extension-load-turns.d.ts +4 -0
- package/dist/core/extensions/bun-extension-load-turns.js +45 -0
- package/dist/core/extensions/bun-extension-registry.d.ts +1 -0
- package/dist/core/extensions/bun-extension-registry.js +19 -1
- package/dist/core/extensions/loader.js +5 -0
- package/dist/core/extensions/session-control-types.d.ts +15 -0
- package/dist/core/extensions/session-control-types.js +11 -0
- package/dist/core/extensions/session-dialog-api.d.ts +5 -0
- package/dist/core/extensions/session-dialog-api.js +13 -0
- package/dist/core/extensions/types.d.ts +14 -1
- package/dist/core/external-admission.d.ts +16 -2
- package/dist/core/external-admission.js +22 -4
- package/dist/core/permission-decision.d.ts +22 -0
- package/dist/core/permission-decision.js +53 -0
- package/dist/core/permission-mode.d.ts +56 -0
- package/dist/core/permission-mode.js +133 -0
- package/dist/core/retry-fallback/controller-types.d.ts +6 -0
- package/dist/core/retry-fallback/controller.d.ts +9 -0
- package/dist/core/retry-fallback/controller.js +34 -3
- package/dist/core/retry-fallback/unusable.d.ts +25 -1
- package/dist/core/retry-fallback/unusable.js +87 -2
- package/dist/core/retry-fallback/usage-limit.d.ts +6 -1
- package/dist/core/retry-fallback/usage-limit.js +12 -4
- package/dist/core/sdk.d.ts +6 -1
- package/dist/core/sdk.js +3 -0
- package/dist/core/session-log.js +1 -1
- package/dist/core/stall-warning.d.ts +41 -0
- package/dist/core/stall-warning.js +72 -0
- package/dist/core/terminal-settings.d.ts +1 -0
- package/dist/core/turn-origin.d.ts +31 -0
- package/dist/core/turn-origin.js +64 -0
- package/dist/modes/interactive/components/remote-delivery-message.d.ts +2 -1
- package/dist/modes/interactive/components/remote-delivery-message.js +13 -5
- package/dist/modes/rpc/admit-external-message-command.d.ts +37 -0
- package/dist/modes/rpc/admit-external-message-command.js +61 -0
- package/dist/modes/rpc/admit-external-message-wire.d.ts +42 -0
- package/dist/modes/rpc/admit-external-message-wire.js +55 -0
- package/dist/modes/rpc/client-input-handler.d.ts +2 -0
- package/dist/modes/rpc/client-input-handler.js +2 -0
- package/dist/modes/rpc/connection-handler.js +30 -5
- package/dist/modes/rpc/connection-roles.d.ts +6 -0
- package/dist/modes/rpc/connection-roles.js +13 -0
- package/dist/modes/rpc/delegated-drive-origin.d.ts +9 -0
- package/dist/modes/rpc/delegated-drive-origin.js +16 -0
- package/dist/modes/rpc/effect-commands.d.ts +7 -1
- package/dist/modes/rpc/host-bare-endpoint-registration.d.ts +7 -0
- package/dist/modes/rpc/host-bare-endpoint-registration.js +35 -0
- package/dist/modes/rpc/host-capabilities.d.ts +2 -0
- package/dist/modes/rpc/host-capabilities.js +3 -0
- package/dist/modes/rpc/host-handover-parked.d.ts +11 -0
- package/dist/modes/rpc/host-handover-parked.js +17 -0
- package/dist/modes/rpc/host-handover-reopen.js +18 -6
- package/dist/modes/rpc/host-handover-resident-writer.d.ts +16 -0
- package/dist/modes/rpc/host-handover-resident-writer.js +57 -0
- package/dist/modes/rpc/host-idle-handover.js +1 -0
- package/dist/modes/rpc/host-warm.d.ts +16 -1
- package/dist/modes/rpc/host-warm.js +33 -6
- package/dist/modes/rpc/method-classes-schema-delivery.d.ts +32 -0
- package/dist/modes/rpc/method-classes-schema-delivery.js +22 -0
- package/dist/modes/rpc/method-classes-schema-session.d.ts +36 -0
- package/dist/modes/rpc/method-classes-schema-session.js +3 -0
- package/dist/modes/rpc/method-classes-schema.d.ts +36 -0
- package/dist/modes/rpc/method-classes.d.ts +2 -0
- package/dist/modes/rpc/method-classes.js +4 -0
- package/dist/modes/rpc/multi-session-host.js +6 -1
- package/dist/modes/rpc/permission-preset-command.d.ts +6 -0
- package/dist/modes/rpc/permission-preset-command.js +27 -0
- package/dist/modes/rpc/rpc-input-validation.js +4 -3
- package/dist/modes/rpc/rpc-mutation-response-types.d.ts +7 -0
- package/dist/modes/rpc/rpc-response-types.d.ts +2 -1
- package/dist/modes/rpc/rpc-session-command-types.d.ts +6 -1
- package/dist/modes/rpc/rpc-session-event-types.d.ts +5 -2
- package/dist/modes/rpc/rpc-session-state-types.d.ts +2 -1
- package/dist/modes/rpc/rpc-session-state.js +2 -0
- package/dist/modes/rpc/session-attachment-commands.js +3 -3
- package/dist/modes/rpc/session-event-writer-connections.js +1 -0
- package/dist/modes/rpc/session-event-writer.d.ts +1 -1
- package/dist/modes/rpc/session-registry-attach.d.ts +0 -9
- package/dist/modes/rpc/session-registry-attach.js +16 -3
- package/dist/modes/rpc/session-registry-types.d.ts +2 -0
- package/dist/modes/rpc/session-registry.d.ts +2 -0
- package/dist/modes/rpc/session-registry.js +16 -3
- package/dist/modes/rpc/session-router-close.js +43 -6
- package/dist/modes/rpc/session-router-context.js +2 -0
- package/dist/modes/rpc/session-router-occupancy.js +2 -11
- package/dist/modes/rpc/session-router-open-profile.js +4 -0
- package/dist/modes/rpc/session-router-open.d.ts +1 -1
- package/dist/modes/rpc/session-router-open.js +6 -17
- package/dist/modes/rpc/session-router-residency.d.ts +24 -0
- package/dist/modes/rpc/session-router-residency.js +90 -0
- package/dist/modes/rpc/session-router-routing.js +7 -1
- package/dist/modes/rpc/session-status.js +4 -1
- package/dist/modes/rpc/session-worker.js +4 -0
- package/dist/modes/rpc/tool-child/terminal-jobs.d.ts +1 -0
- package/dist/modes/rpc/tool-child/terminal-jobs.js +17 -1
- package/dist/modes/rpc/worker-session-registry.js +5 -2
- package/docs/engine-socket/fixtures/admission-routes/h-legacy.json +1 -1
- package/docs/engine-socket/fixtures/rpc-inbound-samples.json +29 -2
- package/docs/extensions.md +12 -0
- package/docs/rpc.md +129 -12
- package/docs/terminal-tools.md +25 -1
- package/native/socket-secret/prebuilds/win32-arm64/senpi_socket_secret.win32-arm64.node +0 -0
- package/native/socket-secret/prebuilds/win32-x64/senpi_socket_secret.win32-x64.node +0 -0
- package/package.json +6 -6
- package/dist/bundle/chunks/chunk-C7HEEBFH.js +0 -2
- package/dist/bundle/chunks/chunk-XCMII2VQ.js +0 -98
- package/dist/bundle/chunks/interactive-mode-B5SQDLH7.js +0 -2
- package/dist/bundle/chunks/main-UQFVFCNY.js +0 -2
- package/dist/bundle/chunks/rpc-mode-JYN3E7P7.js +0 -2
|
@@ -56,6 +56,7 @@ import { CompactionLifecycleCoordinator } from "./compaction/lifecycle.js";
|
|
|
56
56
|
import { isTurnStuckOnContextOverflow } from "./compaction/stuck-overflow.js";
|
|
57
57
|
import { isWarmSummaryAnchorValid } from "./compaction/warm-anchor.js";
|
|
58
58
|
import { CONTINUE_FROM_LEAF_CUSTOM_TYPE, CONTINUE_FROM_LEAF_DIRECTIVE, ContinueFromLeafError, trackTurnAdmission, } from "./continue-from-leaf.js";
|
|
59
|
+
import { getCredentialAccounts } from "./credential-accounts.js";
|
|
59
60
|
import { credentialRecoveryRevision } from "./credential-recovery-revision.js";
|
|
60
61
|
import { admitCursorHistory, cursorAdmissionBudgetBytes } from "./cursor-history-admission.js";
|
|
61
62
|
import { DEFAULT_THINKING_LEVEL } from "./defaults.js";
|
|
@@ -95,6 +96,8 @@ import { deliveryIdOf, ExternalAdmission } from "./external-admission.js";
|
|
|
95
96
|
import { HELD_INPUT_ENTRY, HeldInputs, heldInputHistory } from "./held-inputs.js";
|
|
96
97
|
import { shouldWarnHighReasoning } from "./high-reasoning-warning.js";
|
|
97
98
|
import { customTurnOrigin, inputAttributionOf, inputOriginOf } from "./input-origin.js";
|
|
99
|
+
import { copyInputTurnMark, hasInputTurnMark, inputTurnMark, markInputTurnOrigin, noteRunStart, noteUserMessageStart, } from "./turn-origin.js";
|
|
100
|
+
import { releaseDecisionPreset } from "./permission-decision.js";
|
|
98
101
|
import { markInterrupted } from "./interrupted-tool-result.js";
|
|
99
102
|
import { deliveredReceipts, itemNoticeMessage, QueuedDeliveryCleared, } from "./itemized-send.js";
|
|
100
103
|
import { LazyToolActivation } from "./lazy-tool-activation.js";
|
|
@@ -134,7 +137,7 @@ import { createFallbackLogger } from "./retry-fallback/log.js";
|
|
|
134
137
|
import { createModelConfigErrorReporter, isModelConfigFailure, } from "./retry-fallback/model-config-error.js";
|
|
135
138
|
import { ProbeBackScheduler } from "./retry-fallback/probe-scheduler.js";
|
|
136
139
|
import { REQUEST_SHAPE_FAILURE_TEXT, REQUEST_SHAPE_RECOVERY_ENTRY_TYPE, REQUEST_SHAPE_RECOVERY_NOTE, RequestShapeRecovery, } from "./retry-fallback/request-shape.js";
|
|
137
|
-
import { AccountUsageLimitError, describeUsageLimitEntry, describeUsageLimitMessage, usageLimitScope, } from "./retry-fallback/usage-limit.js";
|
|
140
|
+
import { AccountUsageLimitError, formatResetTime, describeUsageLimitEntry, describeUsageLimitMessage, usageLimitScope, } from "./retry-fallback/usage-limit.js";
|
|
138
141
|
import { recordRungFailure } from "./retry-fallback/exhaustion.js";
|
|
139
142
|
import { limitResetAt } from "./retry-fallback/limit-reset.js";
|
|
140
143
|
import { validateFallbackChains } from "./retry-fallback/validate.js";
|
|
@@ -156,6 +159,7 @@ import { formatSkillInvocationPrompt, formatSkillReferenceBody, parseSkillInvoca
|
|
|
156
159
|
import { BUILTIN_SLASH_COMMANDS } from "./slash-commands.js";
|
|
157
160
|
import { bootstrapRuntime, buildToolRegistry, isBuiltinExtensionPath, } from "./runtime/bootstrap.js";
|
|
158
161
|
import { toolInfoOf } from "./tool-info.js";
|
|
162
|
+
import { PendingQueueLedger, queueEntryLabel, STALL_WARNING_MS, watchForStall, } from "./stall-warning.js";
|
|
159
163
|
import { stopResumeDirective } from "./stop-resume-directive.js";
|
|
160
164
|
import { StructuredSessionLane } from "./structured-session-lane.js";
|
|
161
165
|
import { clampThinkingSelection, getSupportedThinkingLevels, getThinkingClampNotice, supportsMax, supportsXhigh, } from "./thinking-levels.js";
|
|
@@ -436,6 +440,8 @@ export class AgentSession {
|
|
|
436
440
|
this._unregisterMemoryReport = () => { };
|
|
437
441
|
this._eventListeners = [];
|
|
438
442
|
this._agentEventQueue = Promise.resolve();
|
|
443
|
+
/** What `_agentEventQueue` still holds, so a tool call stalled behind it can say what it waits on (senpi#6189). */
|
|
444
|
+
this._agentEventQueueLedger = new PendingQueueLedger();
|
|
439
445
|
this._lifecycleEvents = new LifecycleEventSequencer();
|
|
440
446
|
/**
|
|
441
447
|
* Exact message objects whose message_end persistence is still queued.
|
|
@@ -669,7 +675,10 @@ export class AgentSession {
|
|
|
669
675
|
if (event.type === "agent_start") {
|
|
670
676
|
this._lifecycleBinding.startRun();
|
|
671
677
|
this._requestSelectedModel = undefined;
|
|
678
|
+
noteRunStart(this.sessionManager);
|
|
672
679
|
}
|
|
680
|
+
if (event.type === "message_start" && (event.message.role === "user" || hasInputTurnMark(event.message)))
|
|
681
|
+
noteUserMessageStart(this.sessionManager, event.message);
|
|
673
682
|
// Bind now: the core can start another run before this event's asynchronous delivery.
|
|
674
683
|
const bound = event.type === "agent_start" ? { ...event, runId: this._lifecycleBinding.controller.ledger.runId } : event;
|
|
675
684
|
queuedEvent = bound;
|
|
@@ -758,7 +767,8 @@ export class AgentSession {
|
|
|
758
767
|
this._lifecycleEvents.release(heldLifecycle, (held) => this._emit(held));
|
|
759
768
|
return this._processAgentEvent(queuedEvent, signal);
|
|
760
769
|
};
|
|
761
|
-
const
|
|
770
|
+
const tracked = this._agentEventQueueLedger.track(queueEntryLabel(queuedEvent), deliverThenProcess);
|
|
771
|
+
const processing = this._agentEventQueue.then(tracked, tracked);
|
|
762
772
|
this._agentEventQueue =
|
|
763
773
|
pendingEnd !== undefined
|
|
764
774
|
? processing.finally(() => {
|
|
@@ -780,7 +790,8 @@ export class AgentSession {
|
|
|
780
790
|
this._structuredLane = new StructuredSessionLane(config.internalChannel, (deliver) => {
|
|
781
791
|
if (!this._unsubscribeAgent)
|
|
782
792
|
return;
|
|
783
|
-
|
|
793
|
+
const tracked = this._agentEventQueueLedger.track("structured_record", deliver);
|
|
794
|
+
this._agentEventQueue = this._agentEventQueue.then(tracked, tracked);
|
|
784
795
|
}, (control) => this._recoveryIdentity?.own(control));
|
|
785
796
|
this.sessionManager = config.sessionManager;
|
|
786
797
|
this._unsubscribeRecovery = this.sessionManager.onRecovery((recovery) => {
|
|
@@ -1147,7 +1158,7 @@ export class AgentSession {
|
|
|
1147
1158
|
this._modelRuntime.hasConfiguredAuth(model.provider));
|
|
1148
1159
|
if (available)
|
|
1149
1160
|
return available;
|
|
1150
|
-
throw new AccountUsageLimitError(sessionModel.provider, this._retryFallback.accountError(sessionModel.provider), this._retryFallback.accountResetAt(sessionModel.provider));
|
|
1161
|
+
throw new AccountUsageLimitError(sessionModel.provider, this._retryFallback.accountError(sessionModel.provider), this._retryFallback.accountResetAt(sessionModel.provider), this._retryFallback.widenedFamiliesOf(sessionModel.provider));
|
|
1151
1162
|
}
|
|
1152
1163
|
_logCompactionModelFallback(override, reason, sessionModel) {
|
|
1153
1164
|
const notice = `${override}\u0000${reason}`;
|
|
@@ -1290,33 +1301,56 @@ export class AgentSession {
|
|
|
1290
1301
|
};
|
|
1291
1302
|
}
|
|
1292
1303
|
async preflightToolCall(toolCall, args, options = {}) {
|
|
1304
|
+
// Neither wait below has a deadline of its own: one that never settles is logged once, never cut short (senpi#6189).
|
|
1305
|
+
// The call's own `timeout` bounds its execution, not this phase, which includes a human permission decision.
|
|
1306
|
+
const thresholdMs = STALL_WARNING_MS;
|
|
1307
|
+
const warnStalled = (event, elapsedMs, queue) => this._sessionLogger.warn(event, {
|
|
1308
|
+
toolCallId: toolCall.id,
|
|
1309
|
+
toolName: toolCall.name,
|
|
1310
|
+
...(options.parentToolCallId ? { parentToolCallId: options.parentToolCallId } : {}),
|
|
1311
|
+
thresholdMs,
|
|
1312
|
+
elapsedMs,
|
|
1313
|
+
...queue,
|
|
1314
|
+
});
|
|
1293
1315
|
if (options.waitForEventQueue !== false) {
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
}
|
|
1302
|
-
const runner = this._extensionRunner;
|
|
1303
|
-
if (!runner.hasHandlers("tool_call")) {
|
|
1304
|
-
return undefined;
|
|
1316
|
+
const queueWatch = watchForStall(thresholdMs, (elapsedMs) => warnStalled("tool_call_event_queue_stalled", elapsedMs, this._agentEventQueueLedger.snapshot()));
|
|
1317
|
+
try {
|
|
1318
|
+
await this._agentEventQueue;
|
|
1319
|
+
}
|
|
1320
|
+
finally {
|
|
1321
|
+
queueWatch.stop();
|
|
1322
|
+
}
|
|
1305
1323
|
}
|
|
1324
|
+
const preflightWatch = watchForStall(thresholdMs, (elapsedMs) => warnStalled("tool_call_preflight_stalled", elapsedMs));
|
|
1306
1325
|
try {
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
if (err instanceof Error) {
|
|
1317
|
-
throw err;
|
|
1326
|
+
const signal = options.signal ?? this.agent.signal;
|
|
1327
|
+
// A call released by Stop never runs: block it without asking its hooks (a permission prompt) about it.
|
|
1328
|
+
// Callers such as executeTool only honor an explicit block, so returning nothing here would let it run.
|
|
1329
|
+
if ((await this._waitForToolBarrier(toolCall, signal)) && signal?.aborted) {
|
|
1330
|
+
return { block: true, reason: "Operation aborted" };
|
|
1331
|
+
}
|
|
1332
|
+
const runner = this._extensionRunner;
|
|
1333
|
+
if (!runner.hasHandlers("tool_call")) {
|
|
1334
|
+
return undefined;
|
|
1318
1335
|
}
|
|
1319
|
-
|
|
1336
|
+
try {
|
|
1337
|
+
return await runner.emitToolCall({
|
|
1338
|
+
type: "tool_call",
|
|
1339
|
+
toolName: toolCall.name,
|
|
1340
|
+
toolCallId: toolCall.id,
|
|
1341
|
+
...(options.parentToolCallId ? { parentToolCallId: options.parentToolCallId } : {}),
|
|
1342
|
+
input: args,
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
catch (err) {
|
|
1346
|
+
if (err instanceof Error) {
|
|
1347
|
+
throw err;
|
|
1348
|
+
}
|
|
1349
|
+
throw new Error(`Extension failed, blocking execution: ${String(err)}`);
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
finally {
|
|
1353
|
+
preflightWatch.stop();
|
|
1320
1354
|
}
|
|
1321
1355
|
}
|
|
1322
1356
|
async _emitAfterToolCallHooks(toolCall, args, result, isError, parentToolCallId) {
|
|
@@ -3448,6 +3482,7 @@ export class AgentSession {
|
|
|
3448
3482
|
*/
|
|
3449
3483
|
dispose() {
|
|
3450
3484
|
this._disposed = true;
|
|
3485
|
+
releaseDecisionPreset(this.sessionManager);
|
|
3451
3486
|
this._unsubscribeSecurityNotices?.();
|
|
3452
3487
|
this._unfollowProviderAccountChanges();
|
|
3453
3488
|
this.securityNotices.dispose();
|
|
@@ -3717,6 +3752,19 @@ export class AgentSession {
|
|
|
3717
3752
|
_warnDeadline(event, detail) {
|
|
3718
3753
|
this._sessionLogger.warn(event, { detail });
|
|
3719
3754
|
}
|
|
3755
|
+
/**
|
|
3756
|
+
* End the running turn because the process hosting this session is stopping (an RPC host shutting down or
|
|
3757
|
+
* restarting): a system abort whose `agent_end` carries `abortCause: { kind: "host_shutdown" }`, never a user abort.
|
|
3758
|
+
*/
|
|
3759
|
+
async abortForHostShutdown() {
|
|
3760
|
+
if (!this.isStreaming)
|
|
3761
|
+
return;
|
|
3762
|
+
if (this._abortCause === undefined)
|
|
3763
|
+
this._abortCause = { kind: "host_shutdown" };
|
|
3764
|
+
await this._abortActiveAgentAndRetry("system");
|
|
3765
|
+
if (!this.isIdle)
|
|
3766
|
+
await this._waitForIdleAfterAbort();
|
|
3767
|
+
}
|
|
3720
3768
|
/** Adapter for the deadline owner interface: end the turn through the normal system abort. */
|
|
3721
3769
|
async abortTurnForDeadline() {
|
|
3722
3770
|
await this._abortActiveAgentAndRetry("system");
|
|
@@ -4302,6 +4350,42 @@ export class AgentSession {
|
|
|
4302
4350
|
* @throws Error if streaming and no streamingBehavior specified
|
|
4303
4351
|
* @throws Error if no model selected or no API key available (when not streaming)
|
|
4304
4352
|
*/
|
|
4353
|
+
/**
|
|
4354
|
+
* A provider whose stored credential pools two or more accounts: whether any of them can serve `modelId` now
|
|
4355
|
+
* (no live block, and no live block on that model), and the accounts with why each is out. A cooling account is
|
|
4356
|
+
* not usable until its cooldown ends, so an automated loop never probes a spent pool turn after turn (senpi#3131).
|
|
4357
|
+
* Undefined for a single-credential provider, or when pool health cannot be read (the hold then stays).
|
|
4358
|
+
* Reads pool health only, never key material.
|
|
4359
|
+
*/
|
|
4360
|
+
async _pooledAccountHealth(provider, modelId) {
|
|
4361
|
+
const storage = this._modelRuntime.authStorage;
|
|
4362
|
+
if (storage === undefined)
|
|
4363
|
+
return undefined;
|
|
4364
|
+
let summaries;
|
|
4365
|
+
try {
|
|
4366
|
+
summaries = await getCredentialAccounts(storage, provider);
|
|
4367
|
+
}
|
|
4368
|
+
catch {
|
|
4369
|
+
return undefined;
|
|
4370
|
+
}
|
|
4371
|
+
const accounts = summaries.filter((account) => account.unused !== true);
|
|
4372
|
+
if (accounts.length < 2)
|
|
4373
|
+
return undefined;
|
|
4374
|
+
const now = Date.now();
|
|
4375
|
+
const blocksModel = (blocked) => blocked.until > now &&
|
|
4376
|
+
(blocked.model === modelId ||
|
|
4377
|
+
new RegExp(`(?:^|[^a-z])${blocked.model}(?:[^a-z]|$)`, "i").test(modelId));
|
|
4378
|
+
const usable = accounts.some((account) => !account.blocked && !(account.blockedModels ?? []).some(blocksModel));
|
|
4379
|
+
const accountsOut = accounts
|
|
4380
|
+
.map((account) => {
|
|
4381
|
+
const reason = account.blockedReason ?? "blocked";
|
|
4382
|
+
return account.blockedUntil === undefined
|
|
4383
|
+
? `${account.name} (${reason})`
|
|
4384
|
+
: `${account.name} (${reason} until ${formatResetTime(account.blockedUntil)})`;
|
|
4385
|
+
})
|
|
4386
|
+
.join(", ");
|
|
4387
|
+
return { usable, accountsOut };
|
|
4388
|
+
}
|
|
4305
4389
|
async prompt(text, options) {
|
|
4306
4390
|
this._standingRecovery = undefined;
|
|
4307
4391
|
const barrierError = options?.toolBarrier === undefined ? undefined : toolBarrierSpecError(options.toolBarrier);
|
|
@@ -4586,6 +4670,13 @@ export class AgentSession {
|
|
|
4586
4670
|
const model = this.model;
|
|
4587
4671
|
// A turn the user started asks the provider again unless it stated when the limit resets (senpi#5568);
|
|
4588
4672
|
// automated turns keep the remembered hold so a loop never hammers a spent account (senpi#3131).
|
|
4673
|
+
// A pooled provider is out only when no account can serve: one account's billing or limit is that
|
|
4674
|
+
// account's, and the pool's own block already routes around it (senpi#5590).
|
|
4675
|
+
const pool = model && !this._pendingModelSwitch && this._retryFallback.isProviderSpent(model.provider)
|
|
4676
|
+
? await this._pooledAccountHealth(model.provider, model.id)
|
|
4677
|
+
: undefined;
|
|
4678
|
+
if (model && pool?.usable)
|
|
4679
|
+
this._retryFallback.releaseAccountHold(model.provider);
|
|
4589
4680
|
if (model &&
|
|
4590
4681
|
!this._pendingModelSwitch &&
|
|
4591
4682
|
this._retryFallback.isProviderSpent(model.provider) &&
|
|
@@ -4595,7 +4686,21 @@ export class AgentSession {
|
|
|
4595
4686
|
const errorMessage = this._retryFallback.accountError(model.provider);
|
|
4596
4687
|
// Routing around a remembered failure did not observe another provider failure.
|
|
4597
4688
|
if (!(await this._retryFallback.tryFallback("transient", { errorMessage }, false))) {
|
|
4598
|
-
throw new AccountUsageLimitError(model.provider, errorMessage, this._retryFallback.accountResetAt(model.provider));
|
|
4689
|
+
throw new AccountUsageLimitError(model.provider, errorMessage, this._retryFallback.accountResetAt(model.provider), this._retryFallback.widenedFamiliesOf(model.provider), pool?.accountsOut);
|
|
4690
|
+
}
|
|
4691
|
+
}
|
|
4692
|
+
// A family held by a weekly limit that named no family binds automated turns the same way, so a loop
|
|
4693
|
+
// moves to another family or stops instead of hammering the held one (senpi#5596, senpi#3131).
|
|
4694
|
+
const heldFamily = this.model && !this._pendingModelSwitch && attributionOf(options) !== "user"
|
|
4695
|
+
? this._retryFallback.heldFamily(this.model)
|
|
4696
|
+
: undefined;
|
|
4697
|
+
if (this.model && heldFamily) {
|
|
4698
|
+
this._retryFallback.resetTurn();
|
|
4699
|
+
this._fallbackTurnFailures = [];
|
|
4700
|
+
if (!(await this._retryFallback.tryFallback("transient", { errorMessage: heldFamily.errorMessage }, false))) {
|
|
4701
|
+
throw new AccountUsageLimitError(this.model.provider, heldFamily.errorMessage, undefined, [
|
|
4702
|
+
heldFamily.family,
|
|
4703
|
+
]);
|
|
4599
4704
|
}
|
|
4600
4705
|
}
|
|
4601
4706
|
}
|
|
@@ -4890,6 +4995,7 @@ export class AgentSession {
|
|
|
4890
4995
|
...clientMessageIdentity(options),
|
|
4891
4996
|
};
|
|
4892
4997
|
this._userInputSources.set(userMessage, options?.source ?? "interactive");
|
|
4998
|
+
markInputTurnOrigin(userMessage, inputTurnMark(options ?? {}));
|
|
4893
4999
|
messages.push(userMessage);
|
|
4894
5000
|
// Consume next-turn messages transactionally: a final admission rejection
|
|
4895
5001
|
// restores them in their original order rather than dropping or duplicating
|
|
@@ -5402,6 +5508,9 @@ export class AgentSession {
|
|
|
5402
5508
|
// stays unstamped: unknown origin, never defaulted to a trusted source.
|
|
5403
5509
|
if (input.source !== undefined)
|
|
5404
5510
|
this._userInputSources.set(message, input.source);
|
|
5511
|
+
// Restored input with no source keeps no mark: an unmarked turn is engine work, never a trusted origin.
|
|
5512
|
+
if (input.source !== undefined)
|
|
5513
|
+
markInputTurnOrigin(message, inputTurnMark(input));
|
|
5405
5514
|
if (input.inputId !== undefined)
|
|
5406
5515
|
this._queuedInputDispositions.track(message, input.inputId);
|
|
5407
5516
|
this._queuedMessages.set(queuedId, message);
|
|
@@ -5575,6 +5684,7 @@ export class AgentSession {
|
|
|
5575
5684
|
async sendCustomMessage(message, options, deferredTurnClaim, releasedWake, itemized, onQueued) {
|
|
5576
5685
|
// Normalize the legacy untyped content boundary before persisting a retry payload.
|
|
5577
5686
|
const deliveryMessage = { ...message, content: message.content ?? [] };
|
|
5687
|
+
copyInputTurnMark(message, deliveryMessage);
|
|
5578
5688
|
if (this._sizesOnlyStartup && options?.triggerTurn === true) {
|
|
5579
5689
|
// Size inspection makes no model call (#3483) and owes no work: no ticket, custody record or session file.
|
|
5580
5690
|
this._pendingNextTurnMessages.push({ role: "custom", ...deliveryMessage, timestamp: Date.now() });
|
|
@@ -5789,6 +5899,8 @@ export class AgentSession {
|
|
|
5789
5899
|
: message.details,
|
|
5790
5900
|
timestamp: Date.now(),
|
|
5791
5901
|
};
|
|
5902
|
+
// A delivery that found a run already streaming becomes a steer or follow-up: it keeps the origin it was admitted with.
|
|
5903
|
+
copyInputTurnMark(message, appMessage);
|
|
5792
5904
|
if (this._sizesOnlyStartup && options?.triggerTurn === true) {
|
|
5793
5905
|
// Size inspection makes no model call (#3483): keep the message for a turn that never starts.
|
|
5794
5906
|
this._pendingNextTurnMessages.push(appMessage);
|
|
@@ -6376,7 +6488,8 @@ export class AgentSession {
|
|
|
6376
6488
|
return id;
|
|
6377
6489
|
},
|
|
6378
6490
|
emit: (event) => this._lifecycleEvents.emit(event, (lifecycle) => this._emit(lifecycle), (run) => {
|
|
6379
|
-
|
|
6491
|
+
const tracked = this._agentEventQueueLedger.track(queueEntryLabel(event), run);
|
|
6492
|
+
this._agentEventQueue = this._agentEventQueue.then(tracked, tracked);
|
|
6380
6493
|
void this._agentEventQueue.catch(() => { });
|
|
6381
6494
|
}),
|
|
6382
6495
|
holdInterruptedRun: () => {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { Credential } from "@earendil-works/pi-ai";
|
|
2
2
|
import { type ConfigValue } from "@earendil-works/pi-ai/utils/config-reference";
|
|
3
|
+
import type { PoolState } from "../egress/pool-state.ts";
|
|
3
4
|
import type { RunSlot } from "./failover.ts";
|
|
4
5
|
import type { AccountStrategy } from "./selection-order.ts";
|
|
5
|
-
import { type CredentialSlotRepository } from "./state-store.ts";
|
|
6
6
|
export type RotationLane = "stored" | "env";
|
|
7
7
|
/** Hands a half-open probe lease back, if the slot still holds that exact lease. */
|
|
8
|
-
export declare function releaseProbeLease(repository:
|
|
8
|
+
export declare function releaseProbeLease(repository: PoolState, providerId: string, lane: RotationLane, slotName: string, leaseId: string): Promise<void>;
|
|
9
9
|
export type RotationSlot = RunSlot & {
|
|
10
10
|
lane: RotationLane;
|
|
11
11
|
/** Env-lane key material for the attempt; never serialized or persisted. */
|
|
@@ -25,7 +25,7 @@ export type RotationSources = {
|
|
|
25
25
|
providerId: string;
|
|
26
26
|
credential: Credential | undefined;
|
|
27
27
|
env: (name: string) => string | undefined;
|
|
28
|
-
repository:
|
|
28
|
+
repository: PoolState;
|
|
29
29
|
policy?: {
|
|
30
30
|
affinity?: boolean;
|
|
31
31
|
accountStrategy?: AccountStrategy;
|
|
@@ -149,7 +149,7 @@ export type HalfOpenLease = {
|
|
|
149
149
|
* wins the probe lease; everyone else keeps treating the slot as unavailable
|
|
150
150
|
* until the lease expires or the probe settles the block.
|
|
151
151
|
*/
|
|
152
|
-
export declare function acquireHalfOpenLease(repository: CredentialSlotRepository, providerId: string, laneId: string, slotId: string, options?: {
|
|
152
|
+
export declare function acquireHalfOpenLease(repository: Pick<CredentialSlotRepository, "mutateSlotState">, providerId: string, laneId: string, slotId: string, options?: {
|
|
153
153
|
now?: number;
|
|
154
154
|
leaseTtlMs?: number;
|
|
155
155
|
}): Promise<HalfOpenLease | undefined>;
|
|
@@ -12,8 +12,13 @@ export type FieldClass = "public" | "sealed" | "device-only" | "endpoint" | "for
|
|
|
12
12
|
export type Custody = "sealed" | "device";
|
|
13
13
|
export type ProviderCapability = "cloud" | "local-only" | "ambient-credential" | "callback-stream";
|
|
14
14
|
/** models.json, keyed by schema path: `.` nests, `[]` is an array item, `.{key}` a record key, `.*` a record value. */
|
|
15
|
-
export declare
|
|
15
|
+
export declare function modelsJsonFieldClasses(): Readonly<Record<string, FieldClass>>;
|
|
16
16
|
/** Fields the runtime types add on top of the models.json schema (`model-config.ts`). */
|
|
17
|
-
export declare const MODELS_JSON_TYPE_ONLY_FIELDS:
|
|
18
|
-
|
|
17
|
+
export declare const MODELS_JSON_TYPE_ONLY_FIELDS: {
|
|
18
|
+
readonly "providers.*.models[].samplingParams.{key}": "public";
|
|
19
|
+
readonly "providers.*.models[].samplingParams.*": "forces-device";
|
|
20
|
+
readonly "providers.*.modelOverrides.*.samplingParams.{key}": "public";
|
|
21
|
+
readonly "providers.*.modelOverrides.*.samplingParams.*": "forces-device";
|
|
22
|
+
};
|
|
23
|
+
export declare function classifyModelsJsonField(path: string, classes?: Readonly<Record<string, FieldClass>>): FieldClass | undefined;
|
|
19
24
|
//# sourceMappingURL=classify.d.ts.map
|