@code-yeongyu/senpi 2026.11.6-2 → 2026.11.9-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 +64 -0
- package/dist/bundle/chunks/{bun-extension-importer-RCGPQTI2.js → bun-extension-importer-GQ6IKEXD.js} +2 -2
- 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-D5MRJWUK.js → chunk-7CFORZPE.js} +221 -229
- 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-C7OKUC7L.js → chunk-K3UHGDUQ.js} +1 -1
- package/dist/bundle/chunks/{chunk-7III44PV.js → chunk-LHSWAJJL.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-ECW7VBMB.js → chunk-NDSWTAYJ.js} +1 -1
- package/dist/bundle/chunks/{chunk-GSKCWXXG.js → chunk-Q6NR6644.js} +1 -1
- 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-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-XBEFQW5A.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-QFEY3JMQ.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-YGL3QHU6.js +2 -0
- package/dist/bundle/chunks/main-5SD4DHMC.js +2 -0
- package/dist/bundle/chunks/{multi-session-host-XSUJDHFZ.js → multi-session-host-PGRHY3JP.js} +20 -17
- package/dist/bundle/chunks/{package-manager-cli-GLUNPQJU.js → package-manager-cli-SADLU7QX.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-27TC7W6K.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
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** The schema of `admit_external_message`, a relayed peer-agent message admitted as a delivery (senpi#6233). */
|
|
2
|
+
import Type from "typebox";
|
|
3
|
+
export declare const DELIVERY_RECORD_SCHEMAS: {
|
|
4
|
+
admit_external_message: Type.TObject<{
|
|
5
|
+
id: Type.TOptional<Type.TString>;
|
|
6
|
+
admissionId: Type.TOptional<Type.TString>;
|
|
7
|
+
type: Type.TLiteral<"admit_external_message">;
|
|
8
|
+
} & {
|
|
9
|
+
readonly sessionId: Type.TOptional<Type.TString>;
|
|
10
|
+
} & {
|
|
11
|
+
readonly deliveryId: Type.TString;
|
|
12
|
+
readonly text: Type.TString;
|
|
13
|
+
readonly sender: Type.TOptional<Type.TUnion<[Type.TObject<{
|
|
14
|
+
kind: Type.TLiteral<"agent">;
|
|
15
|
+
session_id: Type.TString;
|
|
16
|
+
name: Type.TOptional<Type.TString>;
|
|
17
|
+
}>, Type.TObject<{
|
|
18
|
+
kind: Type.TLiteral<"command_line">;
|
|
19
|
+
user: Type.TOptional<Type.TString>;
|
|
20
|
+
}>, Type.TObject<{
|
|
21
|
+
kind: Type.TLiteral<"external">;
|
|
22
|
+
platform: Type.TString;
|
|
23
|
+
author: Type.TOptional<Type.TString>;
|
|
24
|
+
}>]>>;
|
|
25
|
+
readonly displayText: Type.TOptional<Type.TString>;
|
|
26
|
+
readonly deliverAs: Type.TUnion<[Type.TLiteral<string>, ...Type.TLiteral<string>[]]>;
|
|
27
|
+
readonly expectedTurnId: Type.TOptional<Type.TString>;
|
|
28
|
+
readonly whenIdle: Type.TOptional<Type.TUnion<[Type.TLiteral<string>, ...Type.TLiteral<string>[]]>>;
|
|
29
|
+
readonly chainCount: Type.TOptional<Type.TInteger>;
|
|
30
|
+
}>;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=method-classes-schema-delivery.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** The schema of `admit_external_message`, a relayed peer-agent message admitted as a delivery (senpi#6233). */
|
|
2
|
+
import Type from "typebox";
|
|
3
|
+
import { Id, literals, Opt, OptId, OptStr, Str, session } from "./method-classes-schema-fields.js";
|
|
4
|
+
/** `SessionControlSender`: each kind's fields and no other, so nothing beyond the label rides along. */
|
|
5
|
+
const DeliverySender = Type.Union([
|
|
6
|
+
Type.Object({ kind: Type.Literal("agent"), session_id: Id, name: OptId }, { additionalProperties: false }),
|
|
7
|
+
Type.Object({ kind: Type.Literal("command_line"), user: OptId }, { additionalProperties: false }),
|
|
8
|
+
Type.Object({ kind: Type.Literal("external"), platform: Id, author: OptId }, { additionalProperties: false }),
|
|
9
|
+
]);
|
|
10
|
+
export const DELIVERY_RECORD_SCHEMAS = {
|
|
11
|
+
admit_external_message: session("admit_external_message", {
|
|
12
|
+
deliveryId: Id,
|
|
13
|
+
text: Str,
|
|
14
|
+
sender: Opt(DeliverySender),
|
|
15
|
+
displayText: OptStr,
|
|
16
|
+
deliverAs: literals("steer", "followUp"),
|
|
17
|
+
expectedTurnId: OptId,
|
|
18
|
+
whenIdle: Opt(literals("start", "queue")),
|
|
19
|
+
chainCount: Opt(Type.Integer({ minimum: 1, maximum: Number.MAX_SAFE_INTEGER })),
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=method-classes-schema-delivery.js.map
|
|
@@ -1,6 +1,33 @@
|
|
|
1
1
|
/** The schemas of the session-routed inbound records (senpi#4324). */
|
|
2
2
|
import Type from "typebox";
|
|
3
3
|
export declare const SESSION_RECORD_SCHEMAS: {
|
|
4
|
+
admit_external_message: Type.TObject<{
|
|
5
|
+
id: Type.TOptional<Type.TString>;
|
|
6
|
+
admissionId: Type.TOptional<Type.TString>;
|
|
7
|
+
type: Type.TLiteral<"admit_external_message">;
|
|
8
|
+
} & {
|
|
9
|
+
readonly sessionId: Type.TOptional<Type.TString>;
|
|
10
|
+
} & {
|
|
11
|
+
readonly deliveryId: Type.TString;
|
|
12
|
+
readonly text: Type.TString;
|
|
13
|
+
readonly sender: Type.TOptional<Type.TUnion<[Type.TObject<{
|
|
14
|
+
kind: Type.TLiteral<"agent">;
|
|
15
|
+
session_id: Type.TString;
|
|
16
|
+
name: Type.TOptional<Type.TString>;
|
|
17
|
+
}>, Type.TObject<{
|
|
18
|
+
kind: Type.TLiteral<"command_line">;
|
|
19
|
+
user: Type.TOptional<Type.TString>;
|
|
20
|
+
}>, Type.TObject<{
|
|
21
|
+
kind: Type.TLiteral<"external">;
|
|
22
|
+
platform: Type.TString;
|
|
23
|
+
author: Type.TOptional<Type.TString>;
|
|
24
|
+
}>]>>;
|
|
25
|
+
readonly displayText: Type.TOptional<Type.TString>;
|
|
26
|
+
readonly deliverAs: Type.TUnion<[Type.TLiteral<string>, ...Type.TLiteral<string>[]]>;
|
|
27
|
+
readonly expectedTurnId: Type.TOptional<Type.TString>;
|
|
28
|
+
readonly whenIdle: Type.TOptional<Type.TUnion<[Type.TLiteral<string>, ...Type.TLiteral<string>[]]>>;
|
|
29
|
+
readonly chainCount: Type.TOptional<Type.TInteger>;
|
|
30
|
+
}>;
|
|
4
31
|
prompt: Type.TObject<{
|
|
5
32
|
id: Type.TOptional<Type.TString>;
|
|
6
33
|
admissionId: Type.TOptional<Type.TString>;
|
|
@@ -478,6 +505,15 @@ export declare const SESSION_RECORD_SCHEMAS: {
|
|
|
478
505
|
} & {
|
|
479
506
|
readonly enabled: Type.TBoolean;
|
|
480
507
|
}>;
|
|
508
|
+
set_permission_preset: Type.TObject<{
|
|
509
|
+
id: Type.TOptional<Type.TString>;
|
|
510
|
+
admissionId: Type.TOptional<Type.TString>;
|
|
511
|
+
type: Type.TLiteral<"set_permission_preset">;
|
|
512
|
+
} & {
|
|
513
|
+
readonly sessionId: Type.TOptional<Type.TString>;
|
|
514
|
+
} & {
|
|
515
|
+
readonly permissionPreset: Type.TString;
|
|
516
|
+
}>;
|
|
481
517
|
set_auto_retry: Type.TObject<{
|
|
482
518
|
id: Type.TOptional<Type.TString>;
|
|
483
519
|
admissionId: Type.TOptional<Type.TString>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** The schemas of the session-routed inbound records (senpi#4324). */
|
|
2
2
|
import Type from "typebox";
|
|
3
3
|
import { Bool, Id, Images, literals, ModelEntries, Num, Opt, OptBool, OptId, OptNum, OptPath, OptStr, PathStr, RetryFallback, RPC_INBOUND_LIMITS, Secret, Str, Strings, session, ThinkingLevel, } from "./method-classes-schema-fields.js";
|
|
4
|
+
import { DELIVERY_RECORD_SCHEMAS } from "./method-classes-schema-delivery.js";
|
|
4
5
|
/** A thread call's hop count: 1 for the first call of a chain, one more per hop. */
|
|
5
6
|
const ChainCount = Type.Integer({ minimum: 1, maximum: Number.MAX_SAFE_INTEGER });
|
|
6
7
|
const steerOrFollowUp = (type) => session(type, {
|
|
@@ -131,6 +132,7 @@ const STATE_AND_MODEL_SCHEMAS = {
|
|
|
131
132
|
set_follow_up_mode: session("set_follow_up_mode", { mode: literals("all", "one-at-a-time") }),
|
|
132
133
|
compact: session("compact", { customInstructions: OptStr }),
|
|
133
134
|
set_auto_compaction: session("set_auto_compaction", { enabled: Bool }),
|
|
135
|
+
set_permission_preset: session("set_permission_preset", { permissionPreset: Id }),
|
|
134
136
|
set_auto_retry: session("set_auto_retry", { enabled: Bool }),
|
|
135
137
|
abort_retry: session("abort_retry", {}),
|
|
136
138
|
set_retry_fallback: session("set_retry_fallback", { retryFallback: RetryFallback }),
|
|
@@ -219,6 +221,7 @@ const SURFACE_AND_ACCOUNT_SCHEMAS = {
|
|
|
219
221
|
};
|
|
220
222
|
export const SESSION_RECORD_SCHEMAS = {
|
|
221
223
|
...PROMPTING_SCHEMAS,
|
|
224
|
+
...DELIVERY_RECORD_SCHEMAS,
|
|
222
225
|
...STATE_AND_MODEL_SCHEMAS,
|
|
223
226
|
...BASH_AND_TREE_SCHEMAS,
|
|
224
227
|
...SURFACE_AND_ACCOUNT_SCHEMAS,
|
|
@@ -29,6 +29,33 @@ export type RpcInboundSchemaDisagreements<Schemas extends RpcInboundSchemaTable>
|
|
|
29
29
|
[K in RpcMethodType]: Agrees<RpcInboundRecordOf<K>, Static<Schemas[K]>> extends true ? never : K;
|
|
30
30
|
}[RpcMethodType];
|
|
31
31
|
export declare const RPC_INBOUND_SCHEMAS: {
|
|
32
|
+
readonly admit_external_message: import("typebox").TObject<{
|
|
33
|
+
id: import("typebox").TOptional<import("typebox").TString>;
|
|
34
|
+
admissionId: import("typebox").TOptional<import("typebox").TString>;
|
|
35
|
+
type: import("typebox").TLiteral<"admit_external_message">;
|
|
36
|
+
} & {
|
|
37
|
+
readonly sessionId: import("typebox").TOptional<import("typebox").TString>;
|
|
38
|
+
} & {
|
|
39
|
+
readonly deliveryId: import("typebox").TString;
|
|
40
|
+
readonly text: import("typebox").TString;
|
|
41
|
+
readonly sender: import("typebox").TOptional<import("typebox").TUnion<[import("typebox").TObject<{
|
|
42
|
+
kind: import("typebox").TLiteral<"agent">;
|
|
43
|
+
session_id: import("typebox").TString;
|
|
44
|
+
name: import("typebox").TOptional<import("typebox").TString>;
|
|
45
|
+
}>, import("typebox").TObject<{
|
|
46
|
+
kind: import("typebox").TLiteral<"command_line">;
|
|
47
|
+
user: import("typebox").TOptional<import("typebox").TString>;
|
|
48
|
+
}>, import("typebox").TObject<{
|
|
49
|
+
kind: import("typebox").TLiteral<"external">;
|
|
50
|
+
platform: import("typebox").TString;
|
|
51
|
+
author: import("typebox").TOptional<import("typebox").TString>;
|
|
52
|
+
}>]>>;
|
|
53
|
+
readonly displayText: import("typebox").TOptional<import("typebox").TString>;
|
|
54
|
+
readonly deliverAs: import("typebox").TUnion<[import("typebox").TLiteral<string>, ...import("typebox").TLiteral<string>[]]>;
|
|
55
|
+
readonly expectedTurnId: import("typebox").TOptional<import("typebox").TString>;
|
|
56
|
+
readonly whenIdle: import("typebox").TOptional<import("typebox").TUnion<[import("typebox").TLiteral<string>, ...import("typebox").TLiteral<string>[]]>>;
|
|
57
|
+
readonly chainCount: import("typebox").TOptional<import("typebox").TInteger>;
|
|
58
|
+
}>;
|
|
32
59
|
readonly get_protocol_info: import("typebox").TObject<{
|
|
33
60
|
id: import("typebox").TOptional<import("typebox").TString>;
|
|
34
61
|
admissionId: import("typebox").TOptional<import("typebox").TString>;
|
|
@@ -852,6 +879,15 @@ export declare const RPC_INBOUND_SCHEMAS: {
|
|
|
852
879
|
} & {
|
|
853
880
|
readonly enabled: import("typebox").TBoolean;
|
|
854
881
|
}>;
|
|
882
|
+
readonly set_permission_preset: import("typebox").TObject<{
|
|
883
|
+
id: import("typebox").TOptional<import("typebox").TString>;
|
|
884
|
+
admissionId: import("typebox").TOptional<import("typebox").TString>;
|
|
885
|
+
type: import("typebox").TLiteral<"set_permission_preset">;
|
|
886
|
+
} & {
|
|
887
|
+
readonly sessionId: import("typebox").TOptional<import("typebox").TString>;
|
|
888
|
+
} & {
|
|
889
|
+
readonly permissionPreset: import("typebox").TString;
|
|
890
|
+
}>;
|
|
855
891
|
readonly set_auto_retry: import("typebox").TObject<{
|
|
856
892
|
id: import("typebox").TOptional<import("typebox").TString>;
|
|
857
893
|
admissionId: import("typebox").TOptional<import("typebox").TString>;
|
|
@@ -140,10 +140,12 @@ export declare const RPC_METHOD_CLASS: {
|
|
|
140
140
|
readonly version: 1;
|
|
141
141
|
};
|
|
142
142
|
readonly set_auto_compaction: "drive";
|
|
143
|
+
readonly set_permission_preset: "device_admin";
|
|
143
144
|
readonly set_retry_fallback: "drive";
|
|
144
145
|
readonly pause_for_run: "drive";
|
|
145
146
|
readonly resume_for_run: "drive";
|
|
146
147
|
readonly wake: "drive";
|
|
148
|
+
readonly admit_external_message: "drive";
|
|
147
149
|
readonly release_tool_barrier: "drive";
|
|
148
150
|
readonly request_self_settle: "drive";
|
|
149
151
|
readonly "eval_cells.stop": "drive";
|
|
@@ -187,10 +187,14 @@ export const RPC_METHOD_CLASS = {
|
|
|
187
187
|
set_model: { classify: setModelClass, version: 1 },
|
|
188
188
|
// a session override; set_steering_mode, set_follow_up_mode and set_auto_retry write global settings (device_admin)
|
|
189
189
|
set_auto_compaction: "drive",
|
|
190
|
+
// like a preset-naming open_session: it changes what the agent may do without asking
|
|
191
|
+
set_permission_preset: "device_admin",
|
|
190
192
|
set_retry_fallback: "drive",
|
|
191
193
|
pause_for_run: "drive",
|
|
192
194
|
resume_for_run: "drive",
|
|
193
195
|
wake: "drive",
|
|
196
|
+
// the engine writes its own fixed delivery entry: no role=user, input event, command or template expansion (senpi#6233)
|
|
197
|
+
admit_external_message: "drive",
|
|
194
198
|
release_tool_barrier: "drive",
|
|
195
199
|
request_self_settle: "drive",
|
|
196
200
|
"eval_cells.stop": "drive",
|
|
@@ -13,6 +13,7 @@ import { answerDelegation, relayExecRefusal } from "./delegated-answer.js";
|
|
|
13
13
|
import { parseClientCapabilities } from "./custom-capability.js";
|
|
14
14
|
import { ClientOccupancy } from "./host-client-occupancy.js";
|
|
15
15
|
import { HostCoreGate } from "./host-core-gate.js";
|
|
16
|
+
import { bindRegisteredEndpoint } from "./host-bare-endpoint-registration.js";
|
|
16
17
|
import { createHostDaemonPaths } from "./host-daemon-paths.js";
|
|
17
18
|
import { ENDPOINT_OWNER_FENCE_CAPABILITY, GENERATION_HANDOFF_CAPABILITY } from "./host-decision.js";
|
|
18
19
|
import { HandoffAnnouncement } from "./host-handoff-announcement.js";
|
|
@@ -549,7 +550,11 @@ async function runSocketHost(options, socketPath) {
|
|
|
549
550
|
});
|
|
550
551
|
// Everything the internal listener needs is initialized: the runtime milestone of a coordinated start (senpi#4602).
|
|
551
552
|
reportStartupMilestone("host_runtime");
|
|
552
|
-
|
|
553
|
+
const bind = () => listen(server, socketPath, secret);
|
|
554
|
+
// A host binding its own public socket keeps its registry record; a supervised one's ensure keeps it.
|
|
555
|
+
boundIdentity = await (hostWatchdogBinding() === undefined
|
|
556
|
+
? bindRegisteredEndpoint({ agentDir: options.agentDir, socket: socketPath, log: hostLog }, bind)
|
|
557
|
+
: bind());
|
|
553
558
|
// A key record that cannot be published safely ends this host: held connections are refused, never served keyless.
|
|
554
559
|
await transport.publish(() => shutdown(1));
|
|
555
560
|
if (supervisorPublicOwnerFile) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AgentSessionRuntime } from "../../core/agent-session-runtime.ts";
|
|
2
|
+
import { type RpcCommand, type RpcResponse } from "./rpc-types.ts";
|
|
3
|
+
export declare function runSetPermissionPreset(runtime: Pick<AgentSessionRuntime, "session" | "setPermissionPreset">, command: Extract<RpcCommand, {
|
|
4
|
+
type: "set_permission_preset";
|
|
5
|
+
}>): RpcResponse;
|
|
6
|
+
//# sourceMappingURL=permission-preset-command.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { parsePermissionPresetName } from "../../core/extensions/builtin/permission-system/cli.js";
|
|
2
|
+
import { permissionModeOf, permissionModeReply } from "../../core/permission-mode.js";
|
|
3
|
+
import { RPC_ERROR_INVALID_LAUNCH_PROFILE } from "./rpc-types.js";
|
|
4
|
+
// The live setter a classic `--mode rpc` session has no other way to receive (it refuses `open_session`), and the
|
|
5
|
+
// path-free one for a session on another device. An unknown preset is refused before anything changes, so the
|
|
6
|
+
// session keeps the mode it had; a valid one is applied through the runtime the way an attach naming it applies it.
|
|
7
|
+
export function runSetPermissionPreset(runtime, command) {
|
|
8
|
+
if (parsePermissionPresetName(command.permissionPreset) === undefined) {
|
|
9
|
+
return {
|
|
10
|
+
id: command.id,
|
|
11
|
+
type: "response",
|
|
12
|
+
command: "set_permission_preset",
|
|
13
|
+
success: false,
|
|
14
|
+
error: `${RPC_ERROR_INVALID_LAUNCH_PROFILE}: unknown permissionPreset "${command.permissionPreset}"`,
|
|
15
|
+
errorCode: RPC_ERROR_INVALID_LAUNCH_PROFILE,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
runtime.setPermissionPreset(command.permissionPreset);
|
|
19
|
+
return {
|
|
20
|
+
id: command.id,
|
|
21
|
+
type: "response",
|
|
22
|
+
command: "set_permission_preset",
|
|
23
|
+
success: true,
|
|
24
|
+
data: permissionModeReply(permissionModeOf(runtime.session)),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=permission-preset-command.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isBrowserEngine } from "../../core/browser-engine.js";
|
|
2
2
|
import { clientMessageIdentitySchema } from "../../core/client-message-identity.js";
|
|
3
3
|
import { MAX_TOOL_BARRIER_ID_LENGTH, toolBarrierSpecError } from "../../core/tool-barrier.js";
|
|
4
|
+
import { admitExternalMessageFieldError } from "./admit-external-message-wire.js";
|
|
4
5
|
import { validatePauseCommand } from "./pause-command-validation.js";
|
|
5
6
|
export const MAX_RPC_MESSAGE_CHARACTERS = 1_000_000;
|
|
6
7
|
/**
|
|
@@ -141,9 +142,9 @@ export function rpcCommandPayloadError(command) {
|
|
|
141
142
|
!(typeof value.effectId === "string" && value.effectId.length > 0 && value.effectId.length <= 256)) {
|
|
142
143
|
return "effectId must be a non-empty string of at most 256 characters.";
|
|
143
144
|
}
|
|
144
|
-
const
|
|
145
|
-
if (
|
|
146
|
-
return
|
|
145
|
+
const fieldError = validatePauseCommand(value) ?? admitExternalMessageFieldError(value, MAX_RPC_MESSAGE_CHARACTERS);
|
|
146
|
+
if (fieldError !== undefined)
|
|
147
|
+
return fieldError;
|
|
147
148
|
if (value.type === "get_pending_inputs" && value.knownClientMessageIds !== undefined) {
|
|
148
149
|
const ids = value.knownClientMessageIds;
|
|
149
150
|
if (!Array.isArray(ids) ||
|
|
@@ -6,6 +6,7 @@ import type { ClientMessageIdentity } from "../../core/client-message-identity.t
|
|
|
6
6
|
import type { CompactionResult } from "../../core/compaction/index.ts";
|
|
7
7
|
import type { ServiceTier } from "../../core/extensions/builtin/service-tier.ts";
|
|
8
8
|
import type { SessionControlAdmission } from "../../core/extensions/types.ts";
|
|
9
|
+
import type { PermissionModeReply } from "../../core/permission-mode.ts";
|
|
9
10
|
import type { ApiKeyVerification } from "../../core/verify-api-key.ts";
|
|
10
11
|
import type { ClientMessageAdmission } from "./client-admission-record.ts";
|
|
11
12
|
import type { RpcProjectSettings, RpcProjectTrust } from "./project-workspace-commands.ts";
|
|
@@ -234,6 +235,12 @@ export type RpcMutationResponse = {
|
|
|
234
235
|
type: "response";
|
|
235
236
|
command: "set_auto_compaction";
|
|
236
237
|
success: true;
|
|
238
|
+
} | {
|
|
239
|
+
id?: string;
|
|
240
|
+
type: "response";
|
|
241
|
+
command: "set_permission_preset";
|
|
242
|
+
success: true;
|
|
243
|
+
data: PermissionModeReply;
|
|
237
244
|
} | {
|
|
238
245
|
id?: string;
|
|
239
246
|
type: "response";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RpcAdmitExternalMessageResponse } from "./admit-external-message-wire.ts";
|
|
1
2
|
import type { RpcAttachmentResponse } from "./attachment-types.ts";
|
|
2
3
|
import type { UnknownAdmissionResponse } from "./compact-admission-error.ts";
|
|
3
4
|
import type { RpcHostCommandResponse } from "./rpc-host-response-types.ts";
|
|
@@ -12,5 +13,5 @@ export type RpcResponse = {
|
|
|
12
13
|
data?: {
|
|
13
14
|
capabilities: readonly string[];
|
|
14
15
|
};
|
|
15
|
-
} | UnknownAdmissionResponse | RpcAttachmentResponse | RpcHostCommandResponse | RpcReadResponse | RpcMutationResponse | RpcPauseResponse;
|
|
16
|
+
} | UnknownAdmissionResponse | RpcAttachmentResponse | RpcHostCommandResponse | RpcReadResponse | RpcMutationResponse | RpcAdmitExternalMessageResponse | RpcPauseResponse;
|
|
16
17
|
//# sourceMappingURL=rpc-response-types.d.ts.map
|
|
@@ -5,6 +5,7 @@ import type { BashResult } from "../../core/bash-executor.ts";
|
|
|
5
5
|
import type { ClientMessageIdentity } from "../../core/client-message-identity.ts";
|
|
6
6
|
import type { SessionEntry } from "../../core/session-manager.ts";
|
|
7
7
|
import type { ToolBarrierSpec } from "../../core/tool-barrier.ts";
|
|
8
|
+
import type { RpcAdmitExternalMessageCommand } from "./admit-external-message-wire.ts";
|
|
8
9
|
import type { RpcRecoveryCommand } from "./rpc-recovery-command-types.ts";
|
|
9
10
|
import type { RpcRemoteOrigin } from "./remote-origin.ts";
|
|
10
11
|
import type { RpcSessionModelEntry } from "./rpc-session-state-types.ts";
|
|
@@ -196,7 +197,7 @@ export type RpcSessionCommand = {
|
|
|
196
197
|
id?: string;
|
|
197
198
|
type: "wake";
|
|
198
199
|
delivery_ids?: string[];
|
|
199
|
-
} | {
|
|
200
|
+
} | RpcAdmitExternalMessageCommand | {
|
|
200
201
|
id?: string;
|
|
201
202
|
type: "get_state";
|
|
202
203
|
} | {
|
|
@@ -293,6 +294,10 @@ export type RpcSessionCommand = {
|
|
|
293
294
|
id?: string;
|
|
294
295
|
type: "set_auto_compaction";
|
|
295
296
|
enabled: boolean;
|
|
297
|
+
} | {
|
|
298
|
+
id?: string;
|
|
299
|
+
type: "set_permission_preset";
|
|
300
|
+
permissionPreset: string;
|
|
296
301
|
} | {
|
|
297
302
|
id?: string;
|
|
298
303
|
type: "set_auto_retry";
|
|
@@ -109,8 +109,11 @@ export type RpcSessionParkedEvent = {
|
|
|
109
109
|
sessionId: string;
|
|
110
110
|
/** Session file to reopen this session by. */
|
|
111
111
|
sessionPath: string;
|
|
112
|
-
/**
|
|
113
|
-
|
|
112
|
+
/**
|
|
113
|
+
* `idle`: the idle sweep parked it; `unloaded`: `unload_session` did; `host_shutdown`: the host stopped with the session
|
|
114
|
+
* retained, and the next host on the endpoint reopens it. Absent from older hosts.
|
|
115
|
+
*/
|
|
116
|
+
reason?: "idle" | "unloaded" | "host_shutdown";
|
|
114
117
|
};
|
|
115
118
|
/**
|
|
116
119
|
* Sent only to the connections a headless engine's quiet takeover let go (senpi#5732): this connection no longer holds
|
|
@@ -3,6 +3,7 @@ import type { Model, ProviderDiagnostic, ThinkingSelection } from "@earendil-wor
|
|
|
3
3
|
import type { AgentAbortSource } from "../../core/agent-abort-provenance.ts";
|
|
4
4
|
import type { QueuedInput } from "../../core/agent-session.ts";
|
|
5
5
|
import type { HoldKind } from "../../core/engine-turn-hold.ts";
|
|
6
|
+
import type { PermissionMode } from "../../core/permission-mode.ts";
|
|
6
7
|
import type { ProviderOrigin } from "../../core/provider-origin.ts";
|
|
7
8
|
import type { ServiceTier } from "../../core/extensions/builtin/service-tier.ts";
|
|
8
9
|
import type { ContextUsage } from "../../core/extensions/types.ts";
|
|
@@ -105,7 +106,7 @@ export interface RpcSessionModelEntry {
|
|
|
105
106
|
thinkingSelection?: ThinkingSelection;
|
|
106
107
|
serviceTier?: ServiceTier;
|
|
107
108
|
}
|
|
108
|
-
export interface RpcSessionState {
|
|
109
|
+
export interface RpcSessionState extends Partial<PermissionMode> {
|
|
109
110
|
/** The running turn's id; absent when no turn is running. A steer or follow-up names it as `expectedTurnId` (senpi#5776). */
|
|
110
111
|
currentTurnId?: string;
|
|
111
112
|
/** Latest 64 UI-answer receipts in this session generation, oldest first. */
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { existsSync } from "node:fs";
|
|
6
6
|
import { sanitizeProviderDiagnostic } from "@earendil-works/pi-ai";
|
|
7
|
+
import { permissionModeOf } from "../../core/permission-mode.js";
|
|
7
8
|
import { ProjectTrustStore } from "../../core/trust-manager.js";
|
|
8
9
|
import { clientFacingIdentity } from "./client-admission-record.js";
|
|
9
10
|
import { sessionQuestionBridges } from "./connection-question-bridge.js";
|
|
@@ -38,6 +39,7 @@ export function buildRpcSessionState(session, lastAbortSource) {
|
|
|
38
39
|
lifecycle: observeLifecycle(session.lifecycle),
|
|
39
40
|
pendingQuestions: sessionQuestionBridges.get(session)?.pendingQuestions(),
|
|
40
41
|
pendingDialogs: sessionDialogRequests.get(session)?.snapshot() ?? [],
|
|
42
|
+
...permissionModeOf(session),
|
|
41
43
|
model: session.model,
|
|
42
44
|
pendingModelSwitch: session.pendingModelSwitch
|
|
43
45
|
? {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { takeOver } from "./attach-takeover.js";
|
|
2
2
|
import { compactOpen } from "./compact-open-admission.js";
|
|
3
|
-
import {
|
|
3
|
+
import { clearRetainedRecord } from "./session-router-residency.js";
|
|
4
4
|
import { hostInstanceId } from "./protocol-identity.js";
|
|
5
5
|
import { canonicalSessionPath } from "./session-path-key.js";
|
|
6
6
|
import { recordAttachment, releaseDisconnectAttachment, releaseOwnerAttachment } from "./session-router-attachments.js";
|
|
@@ -116,8 +116,8 @@ export async function reclaimSession(host, command) {
|
|
|
116
116
|
if (host.sessionsByConnection.get(owner)?.size === 0)
|
|
117
117
|
host.sessionsByConnection.delete(owner);
|
|
118
118
|
connectionLeft(host, row.sessionId, owner);
|
|
119
|
-
if (host.handoverParkedDir !== undefined
|
|
120
|
-
await
|
|
119
|
+
if (host.handoverParkedDir !== undefined)
|
|
120
|
+
await clearRetainedRecord(host, entry);
|
|
121
121
|
if (claim.finalizer) {
|
|
122
122
|
const binding = host.bindings.get(row.sessionId);
|
|
123
123
|
binding?.cancelPendingExtensionUiRequests?.();
|
|
@@ -23,6 +23,7 @@ export class SessionEventWriterConnections extends SessionEventWriterLanes {
|
|
|
23
23
|
record.type === "host_request" ||
|
|
24
24
|
record.type === "relocation_due" ||
|
|
25
25
|
(record.type === "extension_ui_request" &&
|
|
26
|
+
record.audience !== "session" &&
|
|
26
27
|
["select", "confirm", "input", "editor"].includes(String(record.method))));
|
|
27
28
|
}
|
|
28
29
|
isSessionSealed(sessionId) {
|
|
@@ -51,7 +51,7 @@ export declare class SessionEventWriter extends SessionEventWriterDestinations {
|
|
|
51
51
|
* session's reaches every connection. No client asked for this teardown, so there is
|
|
52
52
|
* no close response to answer.
|
|
53
53
|
*/
|
|
54
|
-
parkSession(sessionId: string, sessionPath: string, reason: "idle" | "unloaded"): void;
|
|
54
|
+
parkSession(sessionId: string, sessionPath: string, reason: "idle" | "unloaded" | "host_shutdown"): void;
|
|
55
55
|
/**
|
|
56
56
|
* Seal a session `release_session` handed to a runtime outside this host and publish
|
|
57
57
|
* `session_closed { reason: "released", sessionPath }`. Unlike a park the file must NOT be reopened
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Attach-on-open: a live session outlives individual client attachments, so a resume (or a second
|
|
3
|
-
* surface) for an already-hosted path joins the existing runtime instead of failing. An entry
|
|
4
|
-
* still opening holds the reservation, and an explicit open for that path waits on the entry's
|
|
5
|
-
* openCompletion (bounded on the waiter only, default 45s) and attaches once it opens; on that
|
|
6
|
-
* wait expiring, only the one waiting reopen fails with a retryable session_path_in_use
|
|
7
|
-
* {reason: "open_in_progress", retry_after_ms} naming an attached current owner, and the in-flight
|
|
8
|
-
* open keeps running untouched.
|
|
9
|
-
*/
|
|
10
1
|
import type { SessionPathReservations } from "./host-reservations.ts";
|
|
11
2
|
import { type OpenRpcSession, type RpcSessionEntry, type RpcSessionLaunchProfile, type RpcSessionOpenOptions } from "./session-registry-types.ts";
|
|
12
3
|
export declare function attachToOpenSession(entries: ReadonlyMap<string, RpcSessionEntry>, sessionPath: string, profile: RpcSessionLaunchProfile, options: RpcSessionOpenOptions | undefined, pathReservations: SessionPathReservations | undefined, now: number): Promise<OpenRpcSession>;
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attach-on-open: a live session outlives individual client attachments, so a resume (or a second
|
|
3
|
+
* surface) for an already-hosted path joins the existing runtime instead of failing. An entry
|
|
4
|
+
* still opening holds the reservation, and an explicit open for that path waits on the entry's
|
|
5
|
+
* openCompletion (bounded on the waiter only, default 45s) and attaches once it opens; on that
|
|
6
|
+
* wait expiring, only the one waiting reopen fails with a retryable session_path_in_use
|
|
7
|
+
* {reason: "open_in_progress", retry_after_ms} naming an attached current owner, and the in-flight
|
|
8
|
+
* open keeps running untouched.
|
|
9
|
+
*/
|
|
10
|
+
import { clientNamedPreset, withClientPreset } from "../../core/permission-mode.js";
|
|
1
11
|
import { hostInstanceId } from "./protocol-identity.js";
|
|
2
12
|
import { frozenProfile, RpcSessionRegistryError, } from "./session-registry-types.js";
|
|
3
13
|
/** How long ONE explicit reopen waits on an in-flight open before giving up (the open keeps going). */
|
|
@@ -104,9 +114,12 @@ export async function attachToOpenSession(entries, sessionPath, profile, options
|
|
|
104
114
|
}
|
|
105
115
|
// The preset is applied even when the record already names it: the record is not the live session,
|
|
106
116
|
// so a resent attach also repairs a session that drifted from it (senpi#2842).
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
// Only a preset the client named moves the session: an embedder's host default folded into a preset-less attach is
|
|
118
|
+
// not a choice, and applying it would turn the host default into a client-named mode (remote approval-mode rule).
|
|
119
|
+
const namedPreset = clientNamedPreset(profile);
|
|
120
|
+
if (namedPreset !== undefined) {
|
|
121
|
+
entry.profile = frozenProfile(withClientPreset(entry.profile, namedPreset));
|
|
122
|
+
entry.runtime?.setPermissionPreset(namedPreset);
|
|
110
123
|
}
|
|
111
124
|
entry.lastCommandAt = now;
|
|
112
125
|
if (wasParked) {
|
|
@@ -57,6 +57,8 @@ export interface RpcSessionEntry {
|
|
|
57
57
|
* Requested per `open_session`; an attach may turn it on, never off.
|
|
58
58
|
*/
|
|
59
59
|
retainOnDisconnect?: boolean;
|
|
60
|
+
/** The session path this host's handover-parked record entry is keyed by; it follows a transcript switch. */
|
|
61
|
+
recordedPath?: string;
|
|
60
62
|
/** Timestamp of the last routed command / observed activity; drives idle eviction. */
|
|
61
63
|
lastCommandAt: number;
|
|
62
64
|
/**
|
|
@@ -14,6 +14,7 @@ export declare class RpcSessionRegistry {
|
|
|
14
14
|
readonly closeGraceMs: number;
|
|
15
15
|
/** Present only when the runtime factory can build a session's services alone (`host-warm.ts`). */
|
|
16
16
|
readonly warm?: HostWarm;
|
|
17
|
+
private readonly warmsInFlight?;
|
|
17
18
|
/** The agent directory this host keeps its sessions (and session-move folders) under. */
|
|
18
19
|
get agentDir(): string;
|
|
19
20
|
constructor(options: RpcSessionRegistryOptions);
|
|
@@ -22,6 +23,7 @@ export declare class RpcSessionRegistry {
|
|
|
22
23
|
/** Daemon-family identities come from the endpoint's claims and generation registry. */
|
|
23
24
|
holderPids(observedStarts?: ReadonlyMap<number, number | undefined>): Promise<readonly number[]>;
|
|
24
25
|
openSession(requested: RpcSessionLaunchProfile, options?: RpcSessionOpenOptions): Promise<OpenRpcSession>;
|
|
26
|
+
private openNow;
|
|
25
27
|
/**
|
|
26
28
|
* Read-only lookup with no state transitions or attachment accounting.
|
|
27
29
|
* Exists so lifecycle decisions (e.g. deferring a dropped connection's
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isAbsolute } from "node:path";
|
|
2
2
|
import { assertValidSessionId } from "../../core/session-manager.js";
|
|
3
|
-
import { createRegistryWarm } from "./host-warm.js";
|
|
3
|
+
import { createRegistryWarm, waitForWarms } from "./host-warm.js";
|
|
4
4
|
import { refreshesSessionActivity } from "./session-command-activity.js";
|
|
5
5
|
import { publishedSessionContext } from "./session-context-patch.js";
|
|
6
6
|
import { attachLiveSession, markPathAttached } from "./session-live-attachment.js";
|
|
@@ -20,11 +20,14 @@ export class RpcSessionRegistry {
|
|
|
20
20
|
this.reservations = new Set();
|
|
21
21
|
this.pendingClaims = new Map();
|
|
22
22
|
this.nextHandle = 0;
|
|
23
|
-
if (options.createRuntime.prepare)
|
|
24
|
-
|
|
23
|
+
if (options.createRuntime.prepare) {
|
|
24
|
+
const warming = createRegistryWarm(options.createRuntime.prepare, {
|
|
25
25
|
agentDir: options.agentDir,
|
|
26
26
|
...(options.mcpRegistry !== undefined ? { mcpRegistry: options.mcpRegistry } : {}),
|
|
27
27
|
});
|
|
28
|
+
this.warm = warming.warm;
|
|
29
|
+
this.warmsInFlight = warming.inFlight;
|
|
30
|
+
}
|
|
28
31
|
this.options =
|
|
29
32
|
options.mcpRegistry === undefined
|
|
30
33
|
? options
|
|
@@ -70,6 +73,16 @@ export class RpcSessionRegistry {
|
|
|
70
73
|
return this.options.pathReservations?.holderPids?.(observedStarts) ?? Promise.resolve([]);
|
|
71
74
|
}
|
|
72
75
|
openSession(requested, options) {
|
|
76
|
+
// A warm in flight (the boot load of senpi#6147 included) loads on this loop and yields it between modules
|
|
77
|
+
// (senpi#6199): an open builds its runtime after the warms of ITS cwd that are loading when it arrives, so
|
|
78
|
+
// its factories never run beside that load. Other cwds and later warms are not waited on, and the wait is
|
|
79
|
+
// bounded by `closeGraceMs` like the closing-reservation wait.
|
|
80
|
+
const warming = this.warmsInFlight?.(requested.cwd);
|
|
81
|
+
if (warming === undefined)
|
|
82
|
+
return this.openNow(requested, options);
|
|
83
|
+
return waitForWarms(warming, this.closeGraceMs, requested.cwd).then(() => this.openNow(requested, options));
|
|
84
|
+
}
|
|
85
|
+
openNow(requested, options) {
|
|
73
86
|
return openRegistrySession({
|
|
74
87
|
entries: this.entries,
|
|
75
88
|
reservations: this.reservations,
|
|
@@ -1,8 +1,30 @@
|
|
|
1
|
-
import { clearHandoverParkedSession } from "./host-handover-parked.js";
|
|
2
1
|
import { RPC_ERROR_UNKNOWN_SESSION } from "./rpc-types.js";
|
|
3
2
|
import { forgetSessionOwnership, releaseOwnerAttachment } from "./session-router-attachments.js";
|
|
4
3
|
import { code, error } from "./session-router-errors.js";
|
|
5
4
|
import { stopSweep } from "./session-router-occupancy.js";
|
|
5
|
+
import { clearRetainedRecord, recordRetainedSession } from "./session-router-residency.js";
|
|
6
|
+
/** How long a stop lets a cut turn settle before its teardown proceeds anyway: the default close grace. */
|
|
7
|
+
const HOST_SHUTDOWN_ABORT_BOUND_MS = 10_000;
|
|
8
|
+
/** Ends the running turn as a host shutdown (senpi#6190), bounded so a run its abort cannot release never holds the stop. */
|
|
9
|
+
async function abortForHostShutdownWithin(sessionId, entry) {
|
|
10
|
+
// Async wrapper: a session that throws synchronously still only fails its own abort, never the whole stop.
|
|
11
|
+
const aborting = (async () => {
|
|
12
|
+
await entry?.runtime?.session.abortForHostShutdown();
|
|
13
|
+
})().catch((cause) => {
|
|
14
|
+
process.stderr.write(`senpi rpc host shutdown abort ${sessionId} failed: ${String(cause)}\n`);
|
|
15
|
+
});
|
|
16
|
+
let timer;
|
|
17
|
+
const bound = new Promise((resolve) => {
|
|
18
|
+
timer = setTimeout(resolve, HOST_SHUTDOWN_ABORT_BOUND_MS);
|
|
19
|
+
timer.unref?.();
|
|
20
|
+
});
|
|
21
|
+
try {
|
|
22
|
+
await Promise.race([aborting, bound]);
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
clearTimeout(timer);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
6
28
|
/**
|
|
7
29
|
* Releases one attachment (or every attachment when draining) and reports
|
|
8
30
|
* whether this caller became the finalizer. The join token is installed inside
|
|
@@ -66,10 +88,10 @@ export async function close(host, command) {
|
|
|
66
88
|
releaseOwnerAttachment(host, owner, command.sessionId);
|
|
67
89
|
if (claim.finalizer) {
|
|
68
90
|
// An explicit close ends the session for good: drop any handover-parked record entry, or
|
|
69
|
-
// the session would come back on the next host start (MEDIUM-1, senpi#3282 review).
|
|
70
|
-
|
|
71
|
-
if (host.handoverParkedDir !== undefined
|
|
72
|
-
await
|
|
91
|
+
// the session would come back on the next host start (MEDIUM-1, senpi#3282 review). Awaited only when a record
|
|
92
|
+
// exists, so a host without one starts the teardown in the same tick as the claim.
|
|
93
|
+
if (host.handoverParkedDir !== undefined)
|
|
94
|
+
await clearRetainedRecord(host, host.registry.peek(command.sessionId));
|
|
73
95
|
await finalizeClose(host, command.sessionId, host.bindings.get(command.sessionId), () => reply.complete(true, "client_close"));
|
|
74
96
|
}
|
|
75
97
|
else {
|
|
@@ -189,11 +211,26 @@ export async function dispose(host) {
|
|
|
189
211
|
if (host.admissions)
|
|
190
212
|
await host.admissions.dispose();
|
|
191
213
|
await Promise.all([...host.bindings.entries()].map(async ([sessionId, binding]) => {
|
|
214
|
+
const entry = host.registry.peek(sessionId);
|
|
215
|
+
// A retained session outlives this process: it parks under the transcript it is on now (its record stays
|
|
216
|
+
// for the next host on the endpoint, which reopens it) instead of closing, so attached clients do not read
|
|
217
|
+
// it as ended.
|
|
218
|
+
const parkedPath = host.handoverParkedDir !== undefined && entry?.retainOnDisconnect === true
|
|
219
|
+
? (entry.runtime?.session.sessionFile ?? entry.sessionPath)
|
|
220
|
+
: undefined;
|
|
221
|
+
// Claimed before any await, like close(): the stop fences the session in the tick it starts.
|
|
192
222
|
const claim = tryClaimClose(host, sessionId, { drainAttachments: true });
|
|
193
223
|
if (!claim)
|
|
194
224
|
return;
|
|
195
225
|
if (claim.finalizer) {
|
|
196
|
-
await
|
|
226
|
+
await abortForHostShutdownWithin(sessionId, entry);
|
|
227
|
+
if (entry !== undefined && parkedPath !== undefined)
|
|
228
|
+
await recordRetainedSession(host, entry, parkedPath, false).catch((cause) => {
|
|
229
|
+
process.stderr.write(`senpi rpc host shutdown park record ${sessionId} failed: ${String(cause)}\n`);
|
|
230
|
+
});
|
|
231
|
+
await finalizeClose(host, sessionId, binding, () => parkedPath !== undefined
|
|
232
|
+
? host.writer.parkSession(sessionId, parkedPath, "host_shutdown")
|
|
233
|
+
: host.writer.closeSession(sessionId, { type: "response", command: "close_session", success: true, data: {} }, "host_shutdown"));
|
|
197
234
|
}
|
|
198
235
|
else
|
|
199
236
|
await host.finalizations.get(sessionId)?.promise;
|