@code-yeongyu/senpi 2026.11.10-1 → 2026.11.10-3
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 +42 -0
- package/dist/bundle/chunks/{args-77GYOPEO.js → args-HFYB6URH.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-YFZ734T3.js → azure-openai-responses-MNN2TINI.js} +1 -1
- package/dist/bundle/chunks/{chunk-ZUQCYIRY.js → chunk-2ODGHBUD.js} +1 -1
- package/dist/bundle/chunks/{chunk-YPAQXRP3.js → chunk-47T6YMI2.js} +2 -2
- package/dist/bundle/chunks/{chunk-I5ASHSLZ.js → chunk-4JMGWVRH.js} +1 -1
- package/dist/bundle/chunks/{chunk-MSDBBOB2.js → chunk-5H43O4MA.js} +1 -1
- package/dist/bundle/chunks/{chunk-3IYWH6RO.js → chunk-6Q7Y2G5A.js} +1 -1
- package/dist/bundle/chunks/{chunk-X4XWAB3J.js → chunk-AC6MDRAE.js} +81 -81
- package/dist/bundle/chunks/{chunk-33MZJTQ3.js → chunk-B4WD5XHP.js} +1 -1
- package/dist/bundle/chunks/{chunk-V5FSENW6.js → chunk-COKX65TE.js} +1 -1
- package/dist/bundle/chunks/{chunk-LHEP3ACI.js → chunk-DEQLHN2J.js} +2 -2
- package/dist/bundle/chunks/{chunk-EJB5E2JK.js → chunk-DHAAWL2H.js} +1 -1
- package/dist/bundle/chunks/{chunk-2EJ4BGBM.js → chunk-DHORIIVQ.js} +1 -1
- package/dist/bundle/chunks/{chunk-GPXZTSEX.js → chunk-DIHIEJFV.js} +3 -3
- package/dist/bundle/chunks/{chunk-NH7SYIGN.js → chunk-DLPV4B3R.js} +1 -1
- package/dist/bundle/chunks/{chunk-RCHIMH7N.js → chunk-DQY26AX3.js} +1 -1
- package/dist/bundle/chunks/{chunk-Y7Z7XPUF.js → chunk-DZQA5LVN.js} +1 -1
- package/dist/bundle/chunks/{chunk-2CNSCMYC.js → chunk-E5O4SP5I.js} +1 -1
- package/dist/bundle/chunks/{chunk-3Q5ZENSD.js → chunk-E6ZBTSC6.js} +1 -1
- package/dist/bundle/chunks/{chunk-HI5JSLG5.js → chunk-H3VJVKUK.js} +4 -4
- package/dist/bundle/chunks/{chunk-L6NRDUWJ.js → chunk-HZDKQOWB.js} +1 -1
- package/dist/bundle/chunks/chunk-IREUIMFE.js +11 -0
- package/dist/bundle/chunks/{chunk-FAFIGBUD.js → chunk-JSD6O3RJ.js} +2 -2
- package/dist/bundle/chunks/{chunk-BELNOPAI.js → chunk-L3KVP7VJ.js} +3 -3
- package/dist/bundle/chunks/{chunk-7MN7YNO5.js → chunk-L7DGTA3L.js} +1 -1
- package/dist/bundle/chunks/{chunk-J2NGJKXL.js → chunk-LXINMDMX.js} +1 -1
- package/dist/bundle/chunks/{chunk-H33A33M4.js → chunk-M2VJVJMK.js} +1 -1
- package/dist/bundle/chunks/{chunk-ARUV3US4.js → chunk-NN7NESW2.js} +1 -1
- package/dist/bundle/chunks/{chunk-2U6HXWXS.js → chunk-NNQ34ZDW.js} +1 -1
- package/dist/bundle/chunks/chunk-NQKCJQHB.js +2 -0
- package/dist/bundle/chunks/{chunk-TGW4R7SI.js → chunk-O5WJVIEU.js} +1 -1
- package/dist/bundle/chunks/{chunk-O3FG6HML.js → chunk-PJI5GT7U.js} +1 -1
- package/dist/bundle/chunks/{chunk-BPNSOZ2C.js → chunk-QUVSIW2R.js} +1 -1
- package/dist/bundle/chunks/{chunk-WXYMAUFX.js → chunk-QX7WD3IM.js} +1 -1
- package/dist/bundle/chunks/{chunk-Y4ONXQMR.js → chunk-RGHVPUUX.js} +1 -1
- package/dist/bundle/chunks/{chunk-RYPM5BZQ.js → chunk-S7NAJQB3.js} +1 -1
- package/dist/bundle/chunks/{chunk-LT353NSF.js → chunk-T4CUD7RF.js} +1 -1
- package/dist/bundle/chunks/{chunk-J7FW7MED.js → chunk-TCZORL3V.js} +1 -1
- package/dist/bundle/chunks/{chunk-KU72IKV5.js → chunk-VGSWOLIY.js} +1 -1
- package/dist/bundle/chunks/{chunk-DBQBJTMF.js → chunk-VUY4BZDI.js} +1 -1
- package/dist/bundle/chunks/chunk-XI6THO4F.js +2 -0
- package/dist/bundle/chunks/{chunk-THYEZBUG.js → chunk-Z2C5N2LM.js} +2 -2
- package/dist/bundle/chunks/{cli-main-VG3C2EXI.js → cli-main-ZTT3N4DO.js} +1 -1
- package/dist/bundle/chunks/{credential-accounts-LVVPKFEY.js → credential-accounts-5KHVGSCY.js} +1 -1
- package/dist/bundle/chunks/{dispatch-EP35KKJ3.js → dispatch-YUYZQXRP.js} +1 -1
- package/dist/bundle/chunks/{hand-entry-3LQKUTYS.js → hand-entry-UV5XPMBF.js} +3 -3
- package/dist/bundle/chunks/{headless-host-HKGNJGYT.js → headless-host-53UMJMM6.js} +1 -1
- package/dist/bundle/chunks/{health-write-FBF74QJ7.js → health-write-JLSF5EVV.js} +1 -1
- package/dist/bundle/chunks/{help-fast-path-5SCPY3OH.js → help-fast-path-552QLMWT.js} +1 -1
- package/dist/bundle/chunks/{host-command-CCASS7W4.js → host-command-BZN7WYYV.js} +1 -1
- package/dist/bundle/chunks/{host-lifecycle-WWC7HXQ6.js → host-lifecycle-TNHASSFJ.js} +1 -1
- package/dist/bundle/chunks/host-lifecycle.js +1 -1
- package/dist/bundle/chunks/{host-session-command-YJB2FLKU.js → host-session-command-O5WYHZXH.js} +1 -1
- package/dist/bundle/chunks/{host-socket-request-DMYXC56U.js → host-socket-request-QN4Q2P5E.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-CUN3WMUF.js → interactive-mode-OCU4NDPC.js} +1 -1
- package/dist/bundle/chunks/{login-health-EVXVLHB2.js → login-health-TOSQT5RG.js} +1 -1
- package/dist/bundle/chunks/{main-P7XRC2OI.js → main-CNDP6HCF.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-244X3P6L.js → multi-session-host-ODGJAGJP.js} +11 -8
- package/dist/bundle/chunks/openai-codex-responses-VRGOAFEG.js +10 -0
- package/dist/bundle/chunks/{openai-responses-NIVBWE2H.js → openai-responses-I7PXRWCM.js} +2 -2
- package/dist/bundle/chunks/{package-manager-cli-UVWJOQA3.js → package-manager-cli-HSPUG4RJ.js} +1 -1
- package/dist/bundle/chunks/{role-HQUN4XXK.js → role-AEOLJRTP.js} +1 -1
- package/dist/bundle/chunks/{rotation-stream-F3BEMXBE.js → rotation-stream-E3FJFHXJ.js} +1 -1
- package/dist/bundle/chunks/rpc-mode-KOZPXU3U.js +2 -0
- package/dist/bundle/chunks/{rpc-monitor-source-C6VQ3BC4.js → rpc-monitor-source-PGTDSGWP.js} +1 -1
- package/dist/bundle/chunks/{run-attached-tui-R3RB5P7G.js → run-attached-tui-4AENRP7P.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-5FG2OKSR.js → schedule-command-SG44FE23.js} +1 -1
- package/dist/bundle/chunks/session-control-endpoint-5A24JYPE.js +3 -0
- package/dist/bundle/chunks/{session-picker-2FZSNFS7.js → session-picker-73YRS3GE.js} +1 -1
- package/dist/bundle/chunks/{session-slot-CZGQQCOC.js → session-slot-RH7JLO3F.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +199 -196
- package/dist/bundle/chunks/{state-store-S7QAESIF.js → state-store-IECVTYXC.js} +1 -1
- package/dist/bundle/cli.js +2 -2
- package/dist/bundle/host-supervisor.js +1 -1
- 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 +5 -0
- package/dist/core/agent-session.d.ts +13 -3
- package/dist/core/agent-session.js +89 -18
- package/dist/core/assistant-error-redaction.d.ts +9 -0
- package/dist/core/assistant-error-redaction.js +27 -0
- package/dist/core/config-reference-redaction.js +90 -10
- package/dist/core/context-files.d.ts +10 -0
- package/dist/core/context-files.js +58 -12
- package/dist/core/egress/wire.d.ts +13 -0
- package/dist/core/extensions/builtin/config-reload/change-groups.js +6 -2
- package/dist/core/extensions/builtin/mcp/auth/catalog-identity.js +32 -8
- package/dist/core/extensions/builtin/mcp/auth/oauth-grant.d.ts +43 -0
- package/dist/core/extensions/builtin/mcp/auth/oauth-grant.js +196 -0
- package/dist/core/extensions/builtin/mcp/auth/oauth-provider.d.ts +4 -17
- package/dist/core/extensions/builtin/mcp/auth/oauth-provider.js +64 -75
- package/dist/core/extensions/builtin/mcp/auth/oauth-refresh.d.ts +1 -1
- package/dist/core/extensions/builtin/mcp/auth/oauth-refresh.js +25 -4
- package/dist/core/extensions/builtin/mcp/auth/oauth.js +10 -7
- package/dist/core/extensions/builtin/mcp/auth/token-store.d.ts +18 -0
- package/dist/core/extensions/builtin/mcp/auth/token-store.js +3 -0
- package/dist/core/extensions/builtin/mcp/catalog-cache.js +7 -6
- package/dist/core/extensions/builtin/mcp/catalog.js +3 -2
- package/dist/core/extensions/builtin/mcp/invocation.js +6 -0
- package/dist/core/extensions/builtin/mcp/service-register.js +16 -2
- package/dist/core/extensions/builtin/mcp/service-tools-changed.js +61 -54
- package/dist/core/extensions/builtin/mcp/startup-race.d.ts +2 -0
- package/dist/core/extensions/builtin/mcp/startup-race.js +25 -7
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-2.js +6 -6
- package/dist/core/extensions/loader.js +24 -4
- package/dist/core/extensions/runner.d.ts +9 -1
- package/dist/core/extensions/runner.js +9 -4
- package/dist/core/extensions/types.d.ts +17 -3
- package/dist/core/hand/hook-advertise.d.ts +41 -0
- package/dist/core/hand/hook-advertise.js +98 -0
- package/dist/core/hand/hook-contract.d.ts +66 -0
- package/dist/core/hand/hook-contract.js +138 -0
- package/dist/core/open-timing.d.ts +2 -0
- package/dist/core/open-timing.js +7 -1
- package/dist/core/resource-loader.js +2 -0
- package/dist/core/retry-fallback/log.d.ts +7 -1
- package/dist/core/retry-fallback/log.js +82 -5
- package/dist/core/retry-fallback/model-config-error.js +2 -1
- package/dist/core/session-manager.d.ts +2 -0
- package/dist/core/session-manager.js +15 -1
- package/dist/core/settings-manager.d.ts +6 -0
- package/dist/core/settings-manager.js +8 -0
- package/dist/core/turn-origin.d.ts +19 -13
- package/dist/core/turn-origin.js +34 -30
- package/dist/core/ultrafast-lanes.d.ts +1 -0
- package/dist/core/ultrafast-lanes.js +4 -2
- package/dist/modes/interactive/components/footer.d.ts +23 -5
- package/dist/modes/interactive/components/footer.js +45 -16
- package/dist/modes/interactive/interactive-mode.js +9 -1
- package/dist/modes/interactive/session-control-rpc-commands.d.ts +1 -1
- package/dist/modes/interactive/session-control-rpc-commands.js +5 -0
- package/dist/modes/rpc/admit-external-message-command.d.ts +2 -2
- package/dist/modes/rpc/admit-external-message-command.js +2 -10
- package/dist/modes/rpc/compact-admission-validation.js +4 -1
- package/dist/modes/rpc/connection-handler.d.ts +2 -0
- package/dist/modes/rpc/connection-handler.js +20 -8
- package/dist/modes/rpc/connection-roles.d.ts +2 -0
- package/dist/modes/rpc/connection-roles.js +4 -0
- package/dist/modes/rpc/custom-capability.d.ts +4 -0
- package/dist/modes/rpc/custom-capability.js +4 -0
- package/dist/modes/rpc/delegated-drive-origin.d.ts +6 -6
- package/dist/modes/rpc/delegated-drive-origin.js +7 -8
- package/dist/modes/rpc/delegation-declaration.d.ts +2 -0
- package/dist/modes/rpc/delegation-declaration.js +5 -1
- package/dist/modes/rpc/effect-commands.d.ts +21 -0
- package/dist/modes/rpc/host-capabilities.d.ts +1 -0
- package/dist/modes/rpc/host-capabilities.js +5 -1
- package/dist/modes/rpc/host-observe-request.d.ts +2 -0
- package/dist/modes/rpc/host-observe-request.js +6 -1
- package/dist/modes/rpc/host-park-ledger.d.ts +19 -0
- package/dist/modes/rpc/host-park-ledger.js +110 -0
- package/dist/modes/rpc/lifecycle-delivery.js +4 -1
- package/dist/modes/rpc/loopless-tool-handlers.d.ts +6 -0
- package/dist/modes/rpc/loopless-tool-handlers.js +14 -1
- package/dist/modes/rpc/media-placeholders.js +1 -0
- package/dist/modes/rpc/method-classes-schema-host.d.ts +42 -1
- package/dist/modes/rpc/method-classes-schema-host.js +24 -21
- package/dist/modes/rpc/method-classes-schema.d.ts +42 -1
- package/dist/modes/rpc/method-classes-schema.js +5 -2
- package/dist/modes/rpc/method-classes.d.ts +2 -0
- package/dist/modes/rpc/method-classes.js +3 -0
- package/dist/modes/rpc/multi-session-host.js +1 -1
- package/dist/modes/rpc/rpc-host-command-types.d.ts +14 -1
- package/dist/modes/rpc/rpc-host-response-types.d.ts +21 -0
- package/dist/modes/rpc/session-attachment-gate.js +2 -0
- package/dist/modes/rpc/session-binding.d.ts +1 -0
- package/dist/modes/rpc/session-binding.js +6 -1
- package/dist/modes/rpc/session-connection-context.d.ts +2 -0
- package/dist/modes/rpc/session-connection-context.js +4 -0
- package/dist/modes/rpc/session-registry-attach.d.ts +2 -0
- package/dist/modes/rpc/session-registry-attach.js +15 -11
- package/dist/modes/rpc/session-registry-claims.js +2 -0
- package/dist/modes/rpc/session-registry-open.js +13 -7
- package/dist/modes/rpc/session-registry-opening.js +2 -1
- package/dist/modes/rpc/session-registry-types.d.ts +4 -0
- package/dist/modes/rpc/session-registry.d.ts +3 -0
- package/dist/modes/rpc/session-registry.js +27 -3
- package/dist/modes/rpc/session-router-close.js +1 -0
- package/dist/modes/rpc/session-router-context.d.ts +4 -2
- package/dist/modes/rpc/session-router-context.js +3 -0
- package/dist/modes/rpc/session-router-host-reads.js +1 -0
- package/dist/modes/rpc/session-router-occupancy.js +10 -1
- package/dist/modes/rpc/session-router-open-result.d.ts +12 -0
- package/dist/modes/rpc/session-router-open-result.js +63 -0
- package/dist/modes/rpc/session-router-open.d.ts +3 -0
- package/dist/modes/rpc/session-router-open.js +15 -63
- package/dist/modes/rpc/session-router-park.d.ts +15 -0
- package/dist/modes/rpc/session-router-park.js +176 -0
- package/dist/modes/rpc/session-router-routing.d.ts +1 -1
- package/dist/modes/rpc/session-router-routing.js +7 -0
- package/dist/modes/rpc/session-status-source.js +2 -2
- package/docs/engine-socket/fixtures/admission-routes/h-legacy.json +1 -1
- package/docs/engine-socket/fixtures/rpc-inbound-samples.json +22 -2
- package/docs/extensions.md +10 -0
- package/docs/rpc.md +50 -0
- package/docs/settings.md +1 -0
- package/docs/usage.md +1 -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-436DNN4Z.js +0 -2
- package/dist/bundle/chunks/chunk-DLAY7CIU.js +0 -2
- package/dist/bundle/chunks/chunk-XH2MWTXA.js +0 -11
- package/dist/bundle/chunks/openai-codex-responses-ABB2J43U.js +0 -10
- package/dist/bundle/chunks/rpc-mode-G4I3HHPB.js +0 -2
- package/dist/bundle/chunks/session-control-endpoint-XWCFLJYC.js +0 -3
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { runWithProviderScope } from "@earendil-works/pi-ai/node/provider-scope";
|
|
2
|
+
import { withoutOpenTiming } from "../../core/open-timing.js";
|
|
3
|
+
import { outsideCommand } from "./command-authority.js";
|
|
4
|
+
import { runSetThinkingLevel } from "./effect-commands.js";
|
|
5
|
+
import { runSetModel } from "./handlers-model.js";
|
|
6
|
+
import { runSetPermissionPreset } from "./permission-preset-command.js";
|
|
7
|
+
import { applyAttachedProfile } from "./session-registry-attach.js";
|
|
8
|
+
import { releaseOwnedSession, releaseOwnerAttachment } from "./session-router-attachments.js";
|
|
9
|
+
import { finalizeClose, tryClaimClose } from "./session-router-close.js";
|
|
10
|
+
import { code, error } from "./session-router-errors.js";
|
|
11
|
+
import { open } from "./session-router-open.js";
|
|
12
|
+
import { validatedOpenProfile } from "./session-router-open-profile.js";
|
|
13
|
+
import { holdOpenConnection, ownOpen, publishOpen, replyOpen } from "./session-router-open-result.js";
|
|
14
|
+
import { syncRetainedRecord } from "./session-router-residency.js";
|
|
15
|
+
function profileKey(profile) {
|
|
16
|
+
return JSON.stringify([
|
|
17
|
+
profile.cwd,
|
|
18
|
+
profile.sessionKind ?? "interactive",
|
|
19
|
+
Object.entries(profile.sessionContext ?? {}).sort(([a], [b]) => a.localeCompare(b)),
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
/** Same open, host-context merge, kind, media and binding; no owner and no publication. */
|
|
23
|
+
async function buildPark(host, command) {
|
|
24
|
+
let opened;
|
|
25
|
+
const response = await outsideCommand(() => host.writer.connectionContext.outside(() => withoutOpenTiming(() => open(host, { ...command, type: "open_session" }, undefined, {
|
|
26
|
+
reply: false,
|
|
27
|
+
park: (result) => {
|
|
28
|
+
opened = result;
|
|
29
|
+
},
|
|
30
|
+
}))));
|
|
31
|
+
if (response && !response.success)
|
|
32
|
+
throw new Error(response.error);
|
|
33
|
+
if (!opened)
|
|
34
|
+
throw new Error("park_open_failed");
|
|
35
|
+
return opened;
|
|
36
|
+
}
|
|
37
|
+
/** Quiet teardown: speculation never owes a public terminal record or a handover park. */
|
|
38
|
+
export async function closePark(host, opened) {
|
|
39
|
+
const claim = tryClaimClose(host, opened.sessionId, { drainAttachments: true });
|
|
40
|
+
if (claim?.finalizer)
|
|
41
|
+
await finalizeClose(host, opened.sessionId, host.bindings.get(opened.sessionId));
|
|
42
|
+
else
|
|
43
|
+
await host.finalizations.get(opened.sessionId)?.promise;
|
|
44
|
+
host.writer.forgetSession(opened.sessionId);
|
|
45
|
+
}
|
|
46
|
+
export async function parkSession(host, command) {
|
|
47
|
+
if (!host.registry.supportsParkClaim)
|
|
48
|
+
return error(command.id, command.type, "park_claim_unsupported");
|
|
49
|
+
if (host.draining || host.drainExitRequested)
|
|
50
|
+
return error(command.id, command.type, "host_draining");
|
|
51
|
+
const profile = validatedOpenProfile(host, { ...command, type: "open_session" });
|
|
52
|
+
if ("type" in profile)
|
|
53
|
+
return { ...profile, command: command.type };
|
|
54
|
+
try {
|
|
55
|
+
const state = await host.parks.park(profileKey(profile), () => buildPark(host, command));
|
|
56
|
+
if (host.draining || host.drainExitRequested)
|
|
57
|
+
return error(command.id, command.type, "host_draining");
|
|
58
|
+
return { id: command.id, type: "response", command: command.type, success: true, data: { state } };
|
|
59
|
+
}
|
|
60
|
+
catch (cause) {
|
|
61
|
+
return error(command.id, command.type, code(cause));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export function claimSession(host, command) {
|
|
65
|
+
const owner = host.writer.currentConnection();
|
|
66
|
+
const release = owner === undefined ? undefined : holdOpenConnection(host, owner);
|
|
67
|
+
return claimReady(host, command, owner).finally(release);
|
|
68
|
+
}
|
|
69
|
+
async function claimReady(host, command, owner) {
|
|
70
|
+
if (!host.registry.supportsParkClaim || !host.registry.claimPark)
|
|
71
|
+
return error(command.id, command.type, "park_claim_unsupported");
|
|
72
|
+
if (host.draining || host.drainExitRequested)
|
|
73
|
+
return error(command.id, command.type, "host_draining");
|
|
74
|
+
const miss = () => ({
|
|
75
|
+
id: command.id,
|
|
76
|
+
type: "response",
|
|
77
|
+
command: "claim_session",
|
|
78
|
+
success: true,
|
|
79
|
+
data: { claimed: false },
|
|
80
|
+
});
|
|
81
|
+
// These require construction or a distinct admission contract. A miss leaves the park untouched.
|
|
82
|
+
if (command.sessionPath !== undefined ||
|
|
83
|
+
command.durableSessionId !== undefined ||
|
|
84
|
+
command.expectedHostInstance !== undefined ||
|
|
85
|
+
command.admissionId !== undefined ||
|
|
86
|
+
command.attended === false ||
|
|
87
|
+
command.retry !== undefined ||
|
|
88
|
+
(command.provider !== undefined) !== (command.modelId !== undefined) ||
|
|
89
|
+
command.spawnedBy !== undefined ||
|
|
90
|
+
command.env !== undefined ||
|
|
91
|
+
command.auto_title !== undefined ||
|
|
92
|
+
command.retryFallback !== undefined ||
|
|
93
|
+
(owner !== undefined && host.writer.compactSelection(owner)?.selected))
|
|
94
|
+
return miss();
|
|
95
|
+
const profile = validatedOpenProfile(host, { ...command, type: "open_session" });
|
|
96
|
+
if ("type" in profile)
|
|
97
|
+
return { ...profile, command: command.type };
|
|
98
|
+
const key = profileKey(profile);
|
|
99
|
+
const opened = host.parks.take(key);
|
|
100
|
+
if (!opened)
|
|
101
|
+
return miss();
|
|
102
|
+
let success = false;
|
|
103
|
+
try {
|
|
104
|
+
const entry = host.registry.peek(opened.sessionId);
|
|
105
|
+
if (entry?.state !== "open" || !entry.runtime)
|
|
106
|
+
return miss();
|
|
107
|
+
const runtime = entry.runtime;
|
|
108
|
+
const ctx = { session: runtime.session, sessionId: opened.sessionId, by: { connectionId: owner ?? "host" } };
|
|
109
|
+
await runWithProviderScope(entry.scope, async () => {
|
|
110
|
+
const responses = [];
|
|
111
|
+
if (command.provider !== undefined && command.modelId !== undefined)
|
|
112
|
+
responses.push(await runSetModel(ctx, {
|
|
113
|
+
type: "set_model",
|
|
114
|
+
provider: command.provider,
|
|
115
|
+
modelId: command.modelId,
|
|
116
|
+
scope: "session",
|
|
117
|
+
}));
|
|
118
|
+
if (command.thinkingLevel !== undefined)
|
|
119
|
+
responses.push(await runSetThinkingLevel(ctx, {
|
|
120
|
+
type: "set_thinking_level",
|
|
121
|
+
level: command.thinkingLevel,
|
|
122
|
+
scope: "turn",
|
|
123
|
+
}));
|
|
124
|
+
if (command.permissionPreset !== undefined)
|
|
125
|
+
responses.push(runSetPermissionPreset(runtime, {
|
|
126
|
+
type: "set_permission_preset",
|
|
127
|
+
permissionPreset: command.permissionPreset,
|
|
128
|
+
}));
|
|
129
|
+
const refused = responses.find((response) => !response.success);
|
|
130
|
+
if (refused && !refused.success)
|
|
131
|
+
throw new Error(refused.error);
|
|
132
|
+
applyAttachedProfile(entry, { ...profile, permissionPreset: undefined, permissionPresetSource: undefined });
|
|
133
|
+
if (runtime.launchProfile)
|
|
134
|
+
entry.profile = runtime.launchProfile;
|
|
135
|
+
});
|
|
136
|
+
if (host.draining || host.drainExitRequested || (owner !== undefined && host.releasedConnections.has(owner)))
|
|
137
|
+
return miss();
|
|
138
|
+
const claimed = await host.registry.claimPark(opened.sessionId, command.retain_on_disconnect === true);
|
|
139
|
+
if (host.draining || host.drainExitRequested)
|
|
140
|
+
return miss();
|
|
141
|
+
entry.acceptance?.applyTranscript(runtime.session.sessionManager.drainTranscript());
|
|
142
|
+
ownOpen(host, claimed, owner);
|
|
143
|
+
host.bindings
|
|
144
|
+
.get(claimed.sessionId)
|
|
145
|
+
?.setClientCapabilities?.((owner === undefined ? undefined : host.pendingCapabilities.get(owner)) ??
|
|
146
|
+
host.connectionOptions?.capabilities ??
|
|
147
|
+
[]);
|
|
148
|
+
publishOpen(host, claimed, entry);
|
|
149
|
+
await syncRetainedRecord(host, claimed.sessionId, undefined);
|
|
150
|
+
replyOpen(host, claimed, entry, command);
|
|
151
|
+
success = true;
|
|
152
|
+
if (owner !== undefined && host.releasedConnections.has(owner)) {
|
|
153
|
+
releaseOwnerAttachment(host, owner, claimed.sessionId);
|
|
154
|
+
await releaseOwnedSession(host, claimed.sessionId);
|
|
155
|
+
}
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
catch (cause) {
|
|
159
|
+
return error(command.id, command.type, code(cause));
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
if (!success)
|
|
163
|
+
await closePark(host, opened);
|
|
164
|
+
host.parks.finish(key);
|
|
165
|
+
if (success) {
|
|
166
|
+
const replacement = {
|
|
167
|
+
type: "park_session",
|
|
168
|
+
cwd: command.cwd,
|
|
169
|
+
kind: command.kind,
|
|
170
|
+
context: command.context,
|
|
171
|
+
};
|
|
172
|
+
host.parks.replace(key, () => buildPark(host, replacement));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=session-router-park.js.map
|
|
@@ -7,7 +7,7 @@ import type { RouterContext } from "./session-router-context.ts";
|
|
|
7
7
|
*/
|
|
8
8
|
export declare function handle(host: RouterContext, command: RpcCommand): Promise<RpcResponse | undefined>;
|
|
9
9
|
export declare function dispatch(host: RouterContext, command: Exclude<RpcCommand, {
|
|
10
|
-
type: "warm";
|
|
10
|
+
type: "warm" | "park_session";
|
|
11
11
|
}>): Promise<RpcResponse | undefined>;
|
|
12
12
|
/** Any attached connection may patch; a host with no per-connection identity (stdio) owns every session. */
|
|
13
13
|
export declare function setSessionContext(host: RouterContext, command: Extract<RpcCommand, {
|
|
@@ -24,6 +24,7 @@ import { answerListSessions, answerProtocolInfo, answerSubscriptionLimits } from
|
|
|
24
24
|
import { acknowledgePrompt, otherRequestsSettled } from "./session-router-observation.js";
|
|
25
25
|
import { sweepDrain } from "./session-router-occupancy.js";
|
|
26
26
|
import { openWithBarrier } from "./session-router-open.js";
|
|
27
|
+
import { claimSession, parkSession } from "./session-router-park.js";
|
|
27
28
|
import { syncRetainedRecord } from "./session-router-residency.js";
|
|
28
29
|
import { answerSetSessionContext, answerSubscribeSessions, answerUnsubscribeSessions, notAttachedRefusal, } from "./session-status-commands.js";
|
|
29
30
|
import { unloadSession } from "./session-unload.js";
|
|
@@ -42,6 +43,10 @@ export function handle(host, command) {
|
|
|
42
43
|
return ownership ? Promise.resolve(ownership) : admitted(host, command);
|
|
43
44
|
}
|
|
44
45
|
function admitted(host, command) {
|
|
46
|
+
if ("sessionId" in command && command.sessionId !== undefined && host.registry.peek(command.sessionId)?.speculative)
|
|
47
|
+
return Promise.resolve(error(command.id, command.type, "unknown_session"));
|
|
48
|
+
if (command.type === "park_session")
|
|
49
|
+
return parkSession(host, command);
|
|
45
50
|
const refusal = attachmentGate(host, command) ?? compactAdmissionGate(host, command);
|
|
46
51
|
if (refusal)
|
|
47
52
|
return Promise.resolve(refusal);
|
|
@@ -117,6 +122,8 @@ export async function dispatch(host, command) {
|
|
|
117
122
|
return detachConnection(command, host.writer.currentConnection(), (id) => releaseConnection(host, id));
|
|
118
123
|
if (command.type === "open_session")
|
|
119
124
|
return openWithBarrier(host, command);
|
|
125
|
+
if (command.type === "claim_session")
|
|
126
|
+
return claimSession(host, command);
|
|
120
127
|
if (command.type === "attach_session")
|
|
121
128
|
return attachSession(host, command);
|
|
122
129
|
if (command.type === "release_attachment")
|
|
@@ -63,11 +63,11 @@ export function registryStatusSource(registry) {
|
|
|
63
63
|
sessionIds: () => registry.list().map((row) => row.sessionId),
|
|
64
64
|
entryView: (sessionId) => {
|
|
65
65
|
const entry = registry.peek(sessionId);
|
|
66
|
-
return entry === undefined ? undefined : entryView(entry);
|
|
66
|
+
return entry === undefined || entry.speculative ? undefined : entryView(entry);
|
|
67
67
|
},
|
|
68
68
|
view: (sessionId) => {
|
|
69
69
|
const entry = registry.peek(sessionId);
|
|
70
|
-
if (entry === undefined)
|
|
70
|
+
if (entry === undefined || entry.speculative)
|
|
71
71
|
return undefined;
|
|
72
72
|
const runtime = runtimeView(entry);
|
|
73
73
|
return runtime === undefined ? { entry: entryView(entry) } : { entry: entryView(entry), runtime };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"rpcClientRequests": "{\"type\":\"get_protocol_info\",\"id\":\"rpc-auth-protocol\",\"observe\":true,\"auth\":{\"client_nonce\":\"<public-nonce>\"}}\n{\"type\":\"set_client_info\",\"width\":100,\"capabilities\":[],\"id\":\"req_1\"}\n{\"type\":\"open_session\",\"cwd\":\"<root>/cwd\",\"sessionPath\":\"<root>/cwd/session.jsonl\",\"id\":\"req_2\"}\n{\"type\":\"get_entries\",\"sessionId\":\"rpc-1\",\"id\":\"req_3\"}\n{\"type\":\"close_session\",\"sessionId\":\"rpc-1\",\"id\":\"req_4\"}\n",
|
|
3
|
-
"rpcClientFrames": "{\"id\":\"rpc-auth-protocol\",\"type\":\"response\",\"command\":\"get_protocol_info\",\"success\":true,\"data\":{\"protocolVersion\":1,\"serverVersion\":\"<server-version>\",\"capabilities\":[\"<capabilities>\"],\"mode\":\"multi\",\"instanceId\":\"<uuid-1>\",\"generation\":0,\"engineVersion\":\"<server-version>\",\"engineOrdinal\":\"<engine-ordinal>\",\"launch_profile\":{\"profile_id\":\"ca7a49435f02009fdda5dac49d29408dcfeb1ab5374353784c5a9def467f5be1\",\"core\":{\"extensions\":[],\"multi_session\":false,\"session_runtime\":\"worker\"}},\"agentDir\":\"<root>/agent\",\"method_classes\":{\"version\":1,\"digest\":\"62f1fd2318255fb0f1b7fad0141a9be6b8745542b36c6417c3a1777a7717f636\",\"classes\":{\"get_protocol_info\":\"observe\",\"get_subscription_limits\":\"observe\",\"list_sessions\":\"observe\",\"list_hands\":\"observe\",\"get_state\":\"observe\",\"get_snapshot\":\"observe\",\"get_entries\":\"observe\",\"get_messages\":\"observe\",\"get_tree\":\"observe\",\"get_fork_messages\":\"observe\",\"get_last_assistant_text\":\"observe\",\"get_session_stats\":\"observe\",\"get_effect_status\":\"dynamic\",\"get_pending_inputs\":\"observe\",\"get_follow_up_messages\":\"observe\",\"get_steering_messages\":\"observe\",\"get_commands\":\"observe\",\"get_loaded_surfaces\":\"observe\",\"get_project_trust\":\"observe\",\"get_available_models\":\"observe\",\"get_available_thinking_levels\":\"observe\",\"get_model_thinking_level\":\"observe\",\"get_fast_mode\":\"observe\",\"get_media\":\"observe\",\"memory_report\":\"observe\",\"eval_cells.list\":\"observe\",\"eval_cells.peek\":\"observe\",\"prompt\":\"dynamic\",\"steer\":\"dynamic\",\"follow_up\":\"dynamic\",\"abort\":\"drive\",\"interrupt\":\"drive\",\"abort_retry\":\"drive\",\"abort_compaction\":\"drive\",\"abort_branch_summary\":\"drive\",\"compact\":\"drive\",\"clear_queue\":\"drive\",\"dequeue_message\":\"drive\",\"edit_queued_message\":\"drive\",\"hold_input\":\"drive\",\"withdraw_held_input\":\"drive\",\"append_user_message\":\"drive\",\"edit_user_message\":\"drive\",\"continue_from_leaf\":\"drive\",\"navigate_tree\":\"drive\",\"set_label\":\"drive\",\"set_session_name\":\"drive\",\"set_thinking_level\":\"dynamic\",\"set_model\":\"dynamic\",\"set_auto_compaction\":\"drive\",\"set_permission_preset\":\"device_admin\",\"set_retry_fallback\":\"drive\",\"pause_for_run\":\"drive\",\"resume_for_run\":\"drive\",\"wake\":\"drive\",\"admit_external_message\":\"drive\",\"release_tool_barrier\":\"drive\",\"request_self_settle\":\"drive\",\"eval_cells.stop\":\"drive\",\"append_session_entry\":\"dynamic\",\"extension_ui_response\":\"answer\",\"extension_ui_progress\":\"answer\",\"new_session\":\"dynamic\",\"open_session\":\"dynamic\",\"resume_session\":\"thread\",\"fork\":\"thread\",\"clone\":\"thread\",\"close_session\":\"thread\",\"unload_session\":\"thread\",\"set_session_context\":\"thread\",\"attach_session\":\"thread\",\"select_hand\":\"device_admin\",\"bash\":\"device_admin\",\"abort_bash\":\"device_admin\",\"record_bash_result\":\"device_admin\",\"cleanup_bash_output\":\"device_admin\",\"extension_request\":\"device_admin\",\"reload\":\"device_admin\",\"check_reload_veto\":\"device_admin\",\"resolve_path\":\"device_admin\",\"login_start\":\"device_admin\",\"login_cancel\":\"device_admin\",\"login_api_key\":\"device_admin\",\"logout\":\"device_admin\",\"verify_api_key\":\"device_admin\",\"get_auth_providers\":\"device_admin\",\"get_provider_accounts\":\"device_admin\",\"account_order\":\"device_admin\",\"account_pin\":\"device_admin\",\"account_remove\":\"device_admin\",\"account_reset\":\"device_admin\",\"test_provider_account\":\"device_admin\",\"set_favorite_models\":\"device_admin\",\"set_scoped_models\":\"device_admin\",\"cycle_model\":\"device_admin\",\"cycle_thinking_level\":\"device_admin\",\"set_fast_mode\":\"device_admin\",\"set_steering_mode\":\"device_admin\",\"set_follow_up_mode\":\"device_admin\",\"set_auto_retry\":\"device_admin\",\"set_project_trust\":\"device_admin\",\"get_project_settings\":\"device_admin\",\"set_project_setting\":\"device_admin\",\"read_project_file\":\"device_admin\",\"write_project_file\":\"device_admin\",\"edit_assistant_message\":\"device_admin\",\"send_custom_message\":\"device_admin\",\"switch_session\":\"device_admin\",\"import_jsonl\":\"device_admin\",\"export_html\":\"device_admin\",\"export_jsonl\":\"device_admin\",\"set_client_info\":\"connection_local\",\"subscribe_sessions\":\"connection_local\",\"unsubscribe_sessions\":\"connection_local\",\"record_user_activity\":\"connection_local\",\"detach_connection\":\"connection_local\",\"release_session\":\"connection_local\",\"warm\":\"connection_local\",\"host_response\":\"connection_local\",\"release_attachment\":\"connection_local\",\"reclaim_session\":\"connection_local\",\"move_session\":\"connection_local\",\"get_recovery_page\":\"connection_local\",\"release_recovery\":\"connection_local\",\"cancel_attempt\":\"connection_local\",\"reset_stream\":\"connection_local\"},\"dynamic_versions\":{\"get_effect_status\":1,\"prompt\":1,\"steer\":1,\"follow_up\":1,\"set_thinking_level\":1,\"set_model\":1,\"append_session_entry\":1,\"new_session\":1,\"open_session\":2}},\"memory_pressure\":false,\"path_identity_resolver\":{\"state\":\"not_started\",\"detail\":null}}}\n{\"id\":\"req_1\",\"type\":\"response\",\"command\":\"set_client_info\",\"success\":true}\n{\"type\":\"queued\",\"for_request\":\"req_2\",\"position\":1,\"in_flight\":0}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-2>\",\"method\":\"setWidget\",\"widgetKey\":\"todo-sidebar\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-3>\",\"method\":\"setStatus\",\"statusKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-4>\",\"method\":\"setWidget\",\"widgetKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-5>\",\"method\":\"setStatus\",\"statusKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-6>\",\"method\":\"setWidget\",\"widgetKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-7>\",\"method\":\"setStatus\",\"statusKey\":\"monitors\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-8>\",\"method\":\"setStatus\",\"statusKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-9>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-10>\",\"method\":\"setStatus\",\"statusKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-11>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"entry_appended\",\"entry\":{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"},\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-12>\",\"method\":\"setStatus\",\"statusKey\":\"todo-waiting\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-13>\",\"method\":\"setStatus\",\"statusKey\":\"goal\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"session_opened\",\"sessionId\":\"rpc-1\",\"durableSessionId\":\"<uuid-14>\",\"sessionPath\":\"<root>/cwd/session.jsonl\",\"kind\":\"interactive\",\"cwd\":\"<root>/cwd\"}\n{\"id\":\"req_2\",\"type\":\"response\",\"command\":\"open_session\",\"success\":true,\"data\":{\"sessionId\":\"rpc-1\",\"state\":{\"answeredUiRequests\":[],\"paused\":false,\"pausedNoticeCount\":0,\"holds\":[],\"lifecycle\":{\"state\":\"done\",\"seq\":0,\"epoch\":0,\"epochOrigin\":\"automatic\",\"humanInputRevision\":0,\"selfSettleEligible\":true,\"restoring\":false,\"persisted\":false,\"runPaused\":false,\"since\":\"2026-10-29T00:00:00.000Z\",\"role\":\"root\",\"rootSessionId\":\"<uuid-14>\",\"activityRevision\":{\"instanceId\":\"<uuid-15>\",\"revision\":0},\"waitingOn\":{\"children\":0,\"background\":[],\"human\":[]},\"holds\":[],\"observedAt\":\"2026-10-29T00:00:00.000Z\"},\"pendingQuestions\":[],\"pendingDialogs\":[],\"permissionPreset\":\"full-access\",\"permissionPresetSource\":\"host_default\",\"permissionPresetStatus\":\"applied\",\"effectivePermissionPreset\":\"full-access\",\"model\":{\"id\":\"faux-a\",\"name\":\"faux-a\",\"api\":\"faux:fixture\",\"provider\":\"faux\",\"baseUrl\":\"http://localhost:0\",\"reasoning\":false,\"input\":[\"text\",\"image\"],\"cost\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0},\"contextWindow\":128000,\"maxTokens\":16384},\"pendingModelSwitch\":null,\"thinkingLevel\":\"off\",\"thinkingLevelSource\":\"default\",\"sessionModelThinkingLevels\":{\"faux/faux-a\":\"off\"},\"fastMode\":false,\"isStreaming\":false,\"pausedHeldInputCount\":0,\"runPaused\":false,\"pause\":{\"pauseSeq\":0,\"records\":[]},\"isCompacting\":false,\"retryAttempt\":0,\"isBashRunning\":false,\"steeringMode\":\"all\",\"followUpMode\":\"one-at-a-time\",\"sessionFile\":\"<root>/cwd/session.jsonl\",\"sessionId\":\"<uuid-14>\",\"cwd\":\"<root>/cwd\",\"projectTrusted\":false,\"entries\":[{\"type\":\"model_change\",\"id\":\"<entry-3>\",\"parentId\":null,\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"thinking_level_change\",\"id\":\"<entry-2>\",\"parentId\":\"<entry-3>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"thinkingLevel\":\"off\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"}],\"steering\":[],\"followUp\":[],\"ordered\":[],\"autoCompactionEnabled\":true,\"messageCount\":0,\"pendingMessageCount\":0,\"usageTotals\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0,\"cost\":0},\"contextUsage\":{\"tokens\":0,\"contextWindow\":128000,\"percent\":0},\"favoriteModels\":[],\"scopedModels\":[]},\"permissionPreset\":\"full-access\",\"permissionPresetSource\":\"host_default\",\"permissionPresetStatus\":\"applied\"},\"sessionId\":\"rpc-1\"}\n{\"id\":\"req_3\",\"type\":\"response\",\"command\":\"get_entries\",\"success\":true,\"data\":{\"entries\":[{\"type\":\"model_change\",\"id\":\"<entry-3>\",\"parentId\":null,\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"thinking_level_change\",\"id\":\"<entry-2>\",\"parentId\":\"<entry-3>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"thinkingLevel\":\"off\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"}],\"leafId\":\"<entry-1>\"},\"sessionId\":\"rpc-1\"}\n{\"type\":\"session_closed\",\"sessionId\":\"rpc-1\",\"reason\":\"client_close\"}\n{\"id\":\"req_4\",\"type\":\"response\",\"command\":\"close_session\",\"success\":true,\"data\":{},\"sessionId\":\"rpc-1\"}\n",
|
|
3
|
+
"rpcClientFrames": "{\"id\":\"rpc-auth-protocol\",\"type\":\"response\",\"command\":\"get_protocol_info\",\"success\":true,\"data\":{\"protocolVersion\":1,\"serverVersion\":\"<server-version>\",\"capabilities\":[\"<capabilities>\"],\"mode\":\"multi\",\"instanceId\":\"<uuid-1>\",\"generation\":0,\"engineVersion\":\"<server-version>\",\"engineOrdinal\":\"<engine-ordinal>\",\"launch_profile\":{\"profile_id\":\"ca7a49435f02009fdda5dac49d29408dcfeb1ab5374353784c5a9def467f5be1\",\"core\":{\"extensions\":[],\"multi_session\":false,\"session_runtime\":\"worker\"}},\"agentDir\":\"<root>/agent\",\"method_classes\":{\"version\":1,\"digest\":\"bca41dd6cac2eff3dc82c24d763e4143d90f44ee75920da9bca1c2c8a98c5156\",\"classes\":{\"get_protocol_info\":\"observe\",\"get_subscription_limits\":\"observe\",\"list_sessions\":\"observe\",\"list_hands\":\"observe\",\"get_state\":\"observe\",\"get_snapshot\":\"observe\",\"get_entries\":\"observe\",\"get_messages\":\"observe\",\"get_tree\":\"observe\",\"get_fork_messages\":\"observe\",\"get_last_assistant_text\":\"observe\",\"get_session_stats\":\"observe\",\"get_effect_status\":\"dynamic\",\"get_pending_inputs\":\"observe\",\"get_follow_up_messages\":\"observe\",\"get_steering_messages\":\"observe\",\"get_commands\":\"observe\",\"get_loaded_surfaces\":\"observe\",\"get_project_trust\":\"observe\",\"get_available_models\":\"observe\",\"get_available_thinking_levels\":\"observe\",\"get_model_thinking_level\":\"observe\",\"get_fast_mode\":\"observe\",\"get_media\":\"observe\",\"memory_report\":\"observe\",\"eval_cells.list\":\"observe\",\"eval_cells.peek\":\"observe\",\"prompt\":\"dynamic\",\"steer\":\"dynamic\",\"follow_up\":\"dynamic\",\"abort\":\"drive\",\"interrupt\":\"drive\",\"abort_retry\":\"drive\",\"abort_compaction\":\"drive\",\"abort_branch_summary\":\"drive\",\"compact\":\"drive\",\"clear_queue\":\"drive\",\"dequeue_message\":\"drive\",\"edit_queued_message\":\"drive\",\"hold_input\":\"drive\",\"withdraw_held_input\":\"drive\",\"append_user_message\":\"drive\",\"edit_user_message\":\"drive\",\"continue_from_leaf\":\"drive\",\"navigate_tree\":\"drive\",\"set_label\":\"drive\",\"set_session_name\":\"drive\",\"set_thinking_level\":\"dynamic\",\"set_model\":\"dynamic\",\"set_auto_compaction\":\"drive\",\"set_permission_preset\":\"device_admin\",\"set_retry_fallback\":\"drive\",\"pause_for_run\":\"drive\",\"resume_for_run\":\"drive\",\"wake\":\"drive\",\"admit_external_message\":\"drive\",\"release_tool_barrier\":\"drive\",\"request_self_settle\":\"drive\",\"eval_cells.stop\":\"drive\",\"append_session_entry\":\"dynamic\",\"extension_ui_response\":\"answer\",\"extension_ui_progress\":\"answer\",\"new_session\":\"dynamic\",\"open_session\":\"dynamic\",\"claim_session\":\"device_admin\",\"park_session\":\"device_admin\",\"resume_session\":\"thread\",\"fork\":\"thread\",\"clone\":\"thread\",\"close_session\":\"thread\",\"unload_session\":\"thread\",\"set_session_context\":\"thread\",\"attach_session\":\"thread\",\"select_hand\":\"device_admin\",\"bash\":\"device_admin\",\"abort_bash\":\"device_admin\",\"record_bash_result\":\"device_admin\",\"cleanup_bash_output\":\"device_admin\",\"extension_request\":\"device_admin\",\"reload\":\"device_admin\",\"check_reload_veto\":\"device_admin\",\"resolve_path\":\"device_admin\",\"login_start\":\"device_admin\",\"login_cancel\":\"device_admin\",\"login_api_key\":\"device_admin\",\"logout\":\"device_admin\",\"verify_api_key\":\"device_admin\",\"get_auth_providers\":\"device_admin\",\"get_provider_accounts\":\"device_admin\",\"account_order\":\"device_admin\",\"account_pin\":\"device_admin\",\"account_remove\":\"device_admin\",\"account_reset\":\"device_admin\",\"test_provider_account\":\"device_admin\",\"set_favorite_models\":\"device_admin\",\"set_scoped_models\":\"device_admin\",\"cycle_model\":\"device_admin\",\"cycle_thinking_level\":\"device_admin\",\"set_fast_mode\":\"device_admin\",\"set_steering_mode\":\"device_admin\",\"set_follow_up_mode\":\"device_admin\",\"set_auto_retry\":\"device_admin\",\"set_project_trust\":\"device_admin\",\"get_project_settings\":\"device_admin\",\"set_project_setting\":\"device_admin\",\"read_project_file\":\"device_admin\",\"write_project_file\":\"device_admin\",\"edit_assistant_message\":\"device_admin\",\"send_custom_message\":\"device_admin\",\"switch_session\":\"device_admin\",\"import_jsonl\":\"device_admin\",\"export_html\":\"device_admin\",\"export_jsonl\":\"device_admin\",\"set_client_info\":\"connection_local\",\"subscribe_sessions\":\"connection_local\",\"unsubscribe_sessions\":\"connection_local\",\"record_user_activity\":\"connection_local\",\"detach_connection\":\"connection_local\",\"release_session\":\"connection_local\",\"warm\":\"connection_local\",\"host_response\":\"connection_local\",\"release_attachment\":\"connection_local\",\"reclaim_session\":\"connection_local\",\"move_session\":\"connection_local\",\"get_recovery_page\":\"connection_local\",\"release_recovery\":\"connection_local\",\"cancel_attempt\":\"connection_local\",\"reset_stream\":\"connection_local\"},\"dynamic_versions\":{\"get_effect_status\":1,\"prompt\":1,\"steer\":1,\"follow_up\":1,\"set_thinking_level\":1,\"set_model\":1,\"append_session_entry\":1,\"new_session\":1,\"open_session\":2}},\"memory_pressure\":false,\"path_identity_resolver\":{\"state\":\"not_started\",\"detail\":null}}}\n{\"id\":\"req_1\",\"type\":\"response\",\"command\":\"set_client_info\",\"success\":true}\n{\"type\":\"queued\",\"for_request\":\"req_2\",\"position\":1,\"in_flight\":0}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-2>\",\"method\":\"setWidget\",\"widgetKey\":\"todo-sidebar\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-3>\",\"method\":\"setStatus\",\"statusKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-4>\",\"method\":\"setWidget\",\"widgetKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-5>\",\"method\":\"setStatus\",\"statusKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-6>\",\"method\":\"setWidget\",\"widgetKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-7>\",\"method\":\"setStatus\",\"statusKey\":\"monitors\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-8>\",\"method\":\"setStatus\",\"statusKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-9>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-10>\",\"method\":\"setStatus\",\"statusKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-11>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"entry_appended\",\"entry\":{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"},\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-12>\",\"method\":\"setStatus\",\"statusKey\":\"todo-waiting\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-13>\",\"method\":\"setStatus\",\"statusKey\":\"goal\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"session_opened\",\"sessionId\":\"rpc-1\",\"durableSessionId\":\"<uuid-14>\",\"sessionPath\":\"<root>/cwd/session.jsonl\",\"kind\":\"interactive\",\"cwd\":\"<root>/cwd\"}\n{\"id\":\"req_2\",\"type\":\"response\",\"command\":\"open_session\",\"success\":true,\"data\":{\"sessionId\":\"rpc-1\",\"state\":{\"answeredUiRequests\":[],\"paused\":false,\"pausedNoticeCount\":0,\"holds\":[],\"lifecycle\":{\"state\":\"done\",\"seq\":0,\"epoch\":0,\"epochOrigin\":\"automatic\",\"humanInputRevision\":0,\"selfSettleEligible\":true,\"restoring\":false,\"persisted\":false,\"runPaused\":false,\"since\":\"2026-10-29T00:00:00.000Z\",\"role\":\"root\",\"rootSessionId\":\"<uuid-14>\",\"activityRevision\":{\"instanceId\":\"<uuid-15>\",\"revision\":0},\"waitingOn\":{\"children\":0,\"background\":[],\"human\":[]},\"holds\":[],\"observedAt\":\"2026-10-29T00:00:00.000Z\"},\"pendingQuestions\":[],\"pendingDialogs\":[],\"permissionPreset\":\"full-access\",\"permissionPresetSource\":\"host_default\",\"permissionPresetStatus\":\"applied\",\"effectivePermissionPreset\":\"full-access\",\"model\":{\"id\":\"faux-a\",\"name\":\"faux-a\",\"api\":\"faux:fixture\",\"provider\":\"faux\",\"baseUrl\":\"http://localhost:0\",\"reasoning\":false,\"input\":[\"text\",\"image\"],\"cost\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0},\"contextWindow\":128000,\"maxTokens\":16384},\"pendingModelSwitch\":null,\"thinkingLevel\":\"off\",\"thinkingLevelSource\":\"default\",\"sessionModelThinkingLevels\":{\"faux/faux-a\":\"off\"},\"fastMode\":false,\"isStreaming\":false,\"pausedHeldInputCount\":0,\"runPaused\":false,\"pause\":{\"pauseSeq\":0,\"records\":[]},\"isCompacting\":false,\"retryAttempt\":0,\"isBashRunning\":false,\"steeringMode\":\"all\",\"followUpMode\":\"one-at-a-time\",\"sessionFile\":\"<root>/cwd/session.jsonl\",\"sessionId\":\"<uuid-14>\",\"cwd\":\"<root>/cwd\",\"projectTrusted\":false,\"entries\":[{\"type\":\"model_change\",\"id\":\"<entry-3>\",\"parentId\":null,\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"thinking_level_change\",\"id\":\"<entry-2>\",\"parentId\":\"<entry-3>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"thinkingLevel\":\"off\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"}],\"steering\":[],\"followUp\":[],\"ordered\":[],\"autoCompactionEnabled\":true,\"messageCount\":0,\"pendingMessageCount\":0,\"usageTotals\":{\"input\":0,\"output\":0,\"cacheRead\":0,\"cacheWrite\":0,\"cost\":0},\"contextUsage\":{\"tokens\":0,\"contextWindow\":128000,\"percent\":0},\"favoriteModels\":[],\"scopedModels\":[]},\"permissionPreset\":\"full-access\",\"permissionPresetSource\":\"host_default\",\"permissionPresetStatus\":\"applied\"},\"sessionId\":\"rpc-1\"}\n{\"id\":\"req_3\",\"type\":\"response\",\"command\":\"get_entries\",\"success\":true,\"data\":{\"entries\":[{\"type\":\"model_change\",\"id\":\"<entry-3>\",\"parentId\":null,\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"thinking_level_change\",\"id\":\"<entry-2>\",\"parentId\":\"<entry-3>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\",\"thinkingLevel\":\"off\",\"provider\":\"faux\",\"modelId\":\"faux-a\"},{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"}],\"leafId\":\"<entry-1>\"},\"sessionId\":\"rpc-1\"}\n{\"type\":\"session_closed\",\"sessionId\":\"rpc-1\",\"reason\":\"client_close\"}\n{\"id\":\"req_4\",\"type\":\"response\",\"command\":\"close_session\",\"success\":true,\"data\":{},\"sessionId\":\"rpc-1\"}\n",
|
|
4
4
|
"subscribeRequests": "{\"type\":\"subscribe_sessions\",\"mirror\":\"all\",\"id\":\"subscriber-1\"}\n{\"type\":\"unsubscribe_sessions\",\"subscriptionId\":\"sub-1\",\"id\":\"subscriber-2\"}\n",
|
|
5
5
|
"subscribeFrames": "{\"id\":\"subscriber-1\",\"type\":\"response\",\"command\":\"subscribe_sessions\",\"success\":true,\"data\":{\"subscriptionId\":\"sub-1\",\"snapshot\":[],\"seq\":0,\"hostGeneration\":\"0\",\"hostInstanceId\":\"<uuid-1>\"}}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-2>\",\"method\":\"setWidget\",\"widgetKey\":\"todo-sidebar\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-3>\",\"method\":\"setStatus\",\"statusKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-4>\",\"method\":\"setWidget\",\"widgetKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-5>\",\"method\":\"setStatus\",\"statusKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-6>\",\"method\":\"setWidget\",\"widgetKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-7>\",\"method\":\"setStatus\",\"statusKey\":\"monitors\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-8>\",\"method\":\"setStatus\",\"statusKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-9>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-10>\",\"method\":\"setStatus\",\"statusKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-11>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"entry_appended\",\"entry\":{\"type\":\"custom\",\"customType\":\"pi-rules.scan\",\"data\":{\"cwd\":\"<root>/cwd\",\"reason\":\"startup\"},\"startupBookkeeping\":true,\"id\":\"<entry-1>\",\"parentId\":\"<entry-2>\",\"timestamp\":\"2026-10-29T00:00:00.000Z\"},\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-12>\",\"method\":\"setStatus\",\"statusKey\":\"todo-waiting\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-13>\",\"method\":\"setStatus\",\"statusKey\":\"goal\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"session_opened\",\"sessionId\":\"rpc-1\",\"durableSessionId\":\"<uuid-14>\",\"sessionPath\":\"<root>/cwd/session.jsonl\",\"kind\":\"interactive\",\"cwd\":\"<root>/cwd\"}\n{\"type\":\"session_status\",\"subscriptionId\":\"sub-1\",\"seq\":1,\"sessionId\":\"rpc-1\",\"status\":\"idle\",\"kind\":\"interactive\",\"cwd\":\"<root>/cwd\",\"attachments\":1,\"durableSessionId\":\"<uuid-14>\",\"sessionPath\":\"<root>/cwd/session.jsonl\",\"model\":{\"provider\":\"faux\",\"id\":\"faux-a\"},\"thinkingLevel\":\"off\",\"pendingQueue\":{\"steering\":0,\"followUp\":0},\"lastChange\":{\"at\":\"2026-10-29T00:00:00.000Z\",\"cause\":\"open\",\"by\":\"client\"}}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-15>\",\"method\":\"setStatus\",\"statusKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-16>\",\"method\":\"setWidget\",\"widgetKey\":\"anthropic-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-17>\",\"method\":\"setStatus\",\"statusKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-18>\",\"method\":\"setWidget\",\"widgetKey\":\"openai-web-search\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-19>\",\"method\":\"setStatus\",\"statusKey\":\"monitors\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-20>\",\"method\":\"setStatus\",\"statusKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-21>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-websearch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-22>\",\"method\":\"setStatus\",\"statusKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-23>\",\"method\":\"setWidget\",\"widgetKey\":\"pi-webfetch\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<uuid-24>\",\"method\":\"setStatus\",\"statusKey\":\"loop\",\"sessionId\":\"rpc-1\"}\n{\"type\":\"session_closed\",\"sessionId\":\"rpc-1\",\"reason\":\"client_close\"}\n{\"type\":\"session_status\",\"subscriptionId\":\"sub-1\",\"seq\":2,\"sessionId\":\"rpc-1\",\"status\":\"closed\",\"reason\":\"client_close\",\"kind\":\"interactive\",\"cwd\":\"<root>/cwd\",\"attachments\":1,\"durableSessionId\":\"<uuid-14>\",\"sessionPath\":\"<root>/cwd/session.jsonl\",\"model\":{\"provider\":\"faux\",\"id\":\"faux-a\"},\"thinkingLevel\":\"off\",\"pendingQueue\":{\"steering\":0,\"followUp\":0},\"lastChange\":{\"at\":\"2026-10-29T00:00:00.000Z\",\"cause\":\"close\",\"by\":\"client\"}}\n{\"id\":\"subscriber-2\",\"type\":\"response\",\"command\":\"unsubscribe_sessions\",\"success\":true}\n"
|
|
6
6
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"methodClassesVersion": 1,
|
|
3
|
-
"methodClassesDigest": "
|
|
3
|
+
"methodClassesDigest": "bca41dd6cac2eff3dc82c24d763e4143d90f44ee75920da9bca1c2c8a98c5156",
|
|
4
4
|
"sampleId": "00000000-0000-7000-8000-000000000000",
|
|
5
5
|
"samplePathRoot": "/nonexistent/senpi-rpc-inbound-sample",
|
|
6
|
-
"methodCount":
|
|
6
|
+
"methodCount": 128,
|
|
7
7
|
"methods": [
|
|
8
8
|
{
|
|
9
9
|
"method": "abort",
|
|
@@ -182,6 +182,16 @@
|
|
|
182
182
|
"type": "check_reload_veto"
|
|
183
183
|
}
|
|
184
184
|
},
|
|
185
|
+
{
|
|
186
|
+
"method": "claim_session",
|
|
187
|
+
"class": "device_admin",
|
|
188
|
+
"sampleClass": "device_admin",
|
|
189
|
+
"connectionLocal": false,
|
|
190
|
+
"sample": {
|
|
191
|
+
"type": "claim_session",
|
|
192
|
+
"cwd": "/nonexistent/senpi-rpc-inbound-sample/cwd"
|
|
193
|
+
}
|
|
194
|
+
},
|
|
185
195
|
{
|
|
186
196
|
"method": "cleanup_bash_output",
|
|
187
197
|
"class": "device_admin",
|
|
@@ -807,6 +817,16 @@
|
|
|
807
817
|
"type": "open_session"
|
|
808
818
|
}
|
|
809
819
|
},
|
|
820
|
+
{
|
|
821
|
+
"method": "park_session",
|
|
822
|
+
"class": "device_admin",
|
|
823
|
+
"sampleClass": "device_admin",
|
|
824
|
+
"connectionLocal": false,
|
|
825
|
+
"sample": {
|
|
826
|
+
"type": "park_session",
|
|
827
|
+
"cwd": "/nonexistent/senpi-rpc-inbound-sample/cwd"
|
|
828
|
+
}
|
|
829
|
+
},
|
|
810
830
|
{
|
|
811
831
|
"method": "pause_for_run",
|
|
812
832
|
"class": "drive",
|
package/docs/extensions.md
CHANGED
|
@@ -1075,6 +1075,16 @@ pi.on("before_provider_request", (event, ctx) => {
|
|
|
1075
1075
|
|
|
1076
1076
|
This is mainly useful for debugging provider serialization and cache behavior.
|
|
1077
1077
|
|
|
1078
|
+
`before_provider_request`, `provider_stream_event` and `after_provider_response` handlers can declare the providers whose requests or streams they read or change:
|
|
1079
|
+
|
|
1080
|
+
```typescript
|
|
1081
|
+
pi.on("before_provider_request", (event) => ({ ...event.payload, metadata: { tag: "x" } }), {
|
|
1082
|
+
providers: ["anthropic"],
|
|
1083
|
+
});
|
|
1084
|
+
```
|
|
1085
|
+
|
|
1086
|
+
The declaration does not filter dispatch: the handler still receives every event. A device serving a hosted session advertises it, so the hosted side knows which providers' calls need that device's hooks. A handler without `providers` counts as touching every provider. The value must be a non-empty array of provider ids; anything else throws at registration, also for a handler whose `runs` side does not register it. Every other event ignores `providers`.
|
|
1087
|
+
|
|
1078
1088
|
#### after_provider_response
|
|
1079
1089
|
|
|
1080
1090
|
Fired after an HTTP response is received and before its stream body is consumed. Handlers run in extension load order.
|
package/docs/rpc.md
CHANGED
|
@@ -2758,6 +2758,56 @@ context - inside a provider scope of their own, then drops them.
|
|
|
2758
2758
|
Probe `warm` in `get_protocol_info` capabilities before sending it: an older host answers an unknown command with an
|
|
2759
2759
|
error.
|
|
2760
2760
|
|
|
2761
|
+
### Parking and claiming a built session (`park_claim`)
|
|
2762
|
+
|
|
2763
|
+
An in-process multi-session host advertises `park_claim`. A caller that knows the next session's profile can
|
|
2764
|
+
build it ahead of time:
|
|
2765
|
+
|
|
2766
|
+
```json
|
|
2767
|
+
{"id":"p1","type":"park_session","cwd":"/abs/project","kind":"worker","context":{"role":"child"}}
|
|
2768
|
+
{"id":"p1","type":"response","command":"park_session","success":true,"data":{"state":"parked"}}
|
|
2769
|
+
{"id":"c1","type":"claim_session","cwd":"/abs/project","kind":"worker","context":{"role":"child"},"retain_on_disconnect":true}
|
|
2770
|
+
```
|
|
2771
|
+
|
|
2772
|
+
A successful claim has exactly the `open_session` success payload (`sessionId`, `state`, permission-mode fields
|
|
2773
|
+
and, where available, `presence`), with `command: "claim_session"`. It takes the opener's normal connection
|
|
2774
|
+
capabilities, attachment, ownership and retention policy. No runtime is built in the claim request.
|
|
2775
|
+
When no ready park matches, or an option requires a fresh open, the response is:
|
|
2776
|
+
|
|
2777
|
+
```json
|
|
2778
|
+
{"id":"c1","type":"response","command":"claim_session","success":true,"data":{"claimed":false}}
|
|
2779
|
+
```
|
|
2780
|
+
|
|
2781
|
+
Send a normal `open_session` after that miss. A claim does not wait for an in-flight park. A ready park is consumed
|
|
2782
|
+
once; concurrent claims cannot receive the same session. After a successful claim, the host schedules a replacement
|
|
2783
|
+
for that profile in the background.
|
|
2784
|
+
|
|
2785
|
+
Both commands require an absolute `cwd`. `kind` defaults to `interactive`; `context` has the same validation and
|
|
2786
|
+
host-identity merge as `open_session`, and its key order does not affect matching. Repeated parks of the same profile
|
|
2787
|
+
share one build or answer `state: "already_parked"`. Each host holds at most four speculative profiles, including
|
|
2788
|
+
builds in flight and scheduled replacements; another profile answers `state: "full"`. This cap never limits ordinary opens. A ready park expires
|
|
2789
|
+
after 60 seconds; repeating `park_session` does not extend its lifetime.
|
|
2790
|
+
|
|
2791
|
+
Claim accepts the open options. `retain_on_disconnect`, model/provider, thinking level, permission preset,
|
|
2792
|
+
prompt surface and browser engine apply through the same live operations used by ordinary session commands or
|
|
2793
|
+
attach-on-open. A requested `sessionPath`, `durableSessionId`, `expectedHostInstance`, `spawnedBy`, `env`,
|
|
2794
|
+
`auto_title`, `retryFallback`, `attended: false`, or an unpaired provider/model choice returns `claimed: false`
|
|
2795
|
+
without consuming the park. Compact admissions (`admissionId`,
|
|
2796
|
+
`retry`, or a connection that selected compact transport) also miss, so the caller uses the existing `open_session`
|
|
2797
|
+
admission contract. Invalid applicable options receive their ordinary error response.
|
|
2798
|
+
|
|
2799
|
+
Parks run the existing open implementation without an owner or reply. They start attended, in memory, and acquire
|
|
2800
|
+
their persistent file and file hold only when claimed. Until then they appear in no session listing, status stream,
|
|
2801
|
+
`session_opened` event, session-list file, hosted export, durable-id collision check, attachment count or zero-session
|
|
2802
|
+
trim count. Build timing is dropped. `park_session` never makes its connection an idle-exit attachment; a claim does.
|
|
2803
|
+
Both methods are `device_admin` in the method-class table because they require a host cwd.
|
|
2804
|
+
|
|
2805
|
+
Expiry, drain, handoff and stop dispose parks without a public terminal record or a handover entry. Builds already
|
|
2806
|
+
in flight are closed when they finish; a stopped host never schedules replacements. Parks have no persistent
|
|
2807
|
+
transcript to survive a crash, and no successor reopens them. Worker-isolate hosts do not advertise `park_claim` and
|
|
2808
|
+
answer `park_claim_unsupported`; classic RPC and terminal single-session endpoints answer `multi_session_disabled`.
|
|
2809
|
+
Probe the capability before sending either command.
|
|
2810
|
+
|
|
2761
2811
|
### Delegated connections (`declare_delegation`)
|
|
2762
2812
|
|
|
2763
2813
|
A client that forwards records on behalf of someone else (a relay host forwarding a remote viewer) declares it, and
|
package/docs/settings.md
CHANGED
|
@@ -214,6 +214,7 @@ Set `PI_SKIP_VERSION_CHECK=1` to disable the senpi version update check. Use `--
|
|
|
214
214
|
|---------|------|---------|-------------|
|
|
215
215
|
| `contextFiles.maxBytesPerFile` | number | `65536` | Maximum UTF-8 bytes loaded from each AGENTS.md / CLAUDE.md, including the truncation note and any closing code fence |
|
|
216
216
|
| `contextFiles.maxTotalBytes` | number | `131072` | Maximum combined UTF-8 bytes of loaded context files, including truncation notes and closing code fences |
|
|
217
|
+
| `contextFiles.globalPath` | string | unset | Global (user-scope) context file to load instead of the agent-dir `AGENTS.md`, e.g. `~/.agents/AGENTS.md`. Read from `~/.senpi/agent/settings.json` only; a project's `.senpi/settings.json` cannot set it. A leading `~` is expanded, a relative path resolves against `~/.senpi/agent`, and a directory runs the same `AGENTS.override.md` / `AGENTS.md` / `CLAUDE.md` candidate probe as the agent dir. Unset or blank keeps the agent-dir file; a path that is set but missing, unreadable, or a directory with no candidate falls back to the agent-dir probe and shows one warning naming the path. The loaded file keeps the same size limits |
|
|
217
218
|
|
|
218
219
|
Files receive budget nearest-first: the current directory, its ancestors, then the global file. A cut prefers a newline in the last quarter of the available content budget; otherwise it uses a UTF-8 character boundary. An open backtick or tilde fence is closed with the same marker before the truncation note; the closing marker's bytes count against the budget. Files with less than 1024 bytes of budget left are skipped when they would need truncation, with a warning distinguishing an undersized per-file limit from budget used by nearer files. Both limits accept positive numbers (rounded down); invalid values use the defaults.
|
|
219
220
|
|
package/docs/usage.md
CHANGED
|
@@ -129,7 +129,7 @@ To see where a long session's memory goes, start senpi with `SENPI_MEMORY_REPORT
|
|
|
129
129
|
|
|
130
130
|
Senpi loads `AGENTS.md` or `CLAUDE.md` at startup from:
|
|
131
131
|
|
|
132
|
-
- `~/.senpi/agent/AGENTS.md` for global instructions
|
|
132
|
+
- `~/.senpi/agent/AGENTS.md` for global instructions (set `contextFiles.globalPath` in settings to load a different file or directory instead, e.g. `~/.agents/AGENTS.md`)
|
|
133
133
|
- parent directories, walking up from the current working directory
|
|
134
134
|
- the current directory
|
|
135
135
|
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/senpi",
|
|
3
|
-
"version": "2026.11.10-
|
|
3
|
+
"version": "2026.11.10-3",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"piConfig": {
|
|
@@ -92,9 +92,9 @@
|
|
|
92
92
|
},
|
|
93
93
|
"dependencies": {
|
|
94
94
|
"@earendil-works/chord": "0.99.1",
|
|
95
|
-
"@earendil-works/pi-agent-core": "npm:@code-yeongyu/senpi-agent-core@2026.11.10-
|
|
96
|
-
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.11.10-
|
|
97
|
-
"@earendil-works/pi-tui": "npm:@code-yeongyu/senpi-tui@2026.11.10-
|
|
95
|
+
"@earendil-works/pi-agent-core": "npm:@code-yeongyu/senpi-agent-core@2026.11.10-3",
|
|
96
|
+
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.11.10-3",
|
|
97
|
+
"@earendil-works/pi-tui": "npm:@code-yeongyu/senpi-tui@2026.11.10-3",
|
|
98
98
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
99
99
|
"ajv": "8.20.0",
|
|
100
100
|
"chalk": "6.0.0",
|
|
@@ -115,8 +115,8 @@
|
|
|
115
115
|
"yaml": "2.9.1",
|
|
116
116
|
"@anthropic-ai/claude-agent-sdk": "0.3.321",
|
|
117
117
|
"@anthropic-ai/sdk": "0.127.0",
|
|
118
|
-
"@code-yeongyu/senpi-codemode": "2026.11.10-
|
|
119
|
-
"@earendil-works/pi-pty": "npm:@code-yeongyu/senpi-pty@2026.11.10-
|
|
118
|
+
"@code-yeongyu/senpi-codemode": "2026.11.10-3",
|
|
119
|
+
"@earendil-works/pi-pty": "npm:@code-yeongyu/senpi-pty@2026.11.10-3",
|
|
120
120
|
"@modelcontextprotocol/sdk": "1.32.1",
|
|
121
121
|
"@mozilla/readability": "0.6.0",
|
|
122
122
|
"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{jsonNormalValue}from"./chunk-SF4MQDKZ.js";import{isBigIntObject,isBooleanObject,isNumberObject,isStringObject}from"node:util/types";function normalizeJsonValue(input){let ancestors=new Set,changed=!1,visit=(input2,key)=>{let value2=input2;if(typeof value2=="object"&&value2!==null||typeof value2=="function"||typeof value2=="bigint"){let toJSON=value2.toJSON;typeof toJSON=="function"&&(value2=toJSON.call(value2,key),changed=!0)}if(typeof value2=="object"&&value2!==null){if(isNumberObject(value2))value2=+value2,changed=!0;else if(isStringObject(value2))value2=String(value2),changed=!0;else if(isBooleanObject(value2))value2=Boolean.prototype.valueOf.call(value2),changed=!0;else if(isBigIntObject(value2))throw new TypeError("Do not know how to serialize a BigInt")}if(typeof value2=="bigint")throw new TypeError("Do not know how to serialize a BigInt");if(typeof value2=="number"){let normalized=Number.isFinite(value2)?Object.is(value2,-0)?0:value2:null;return Object.is(normalized,value2)||(changed=!0),normalized}if(typeof value2>"u"||typeof value2=="function"||typeof value2=="symbol"){changed=!0;return}if(typeof value2!="object"||value2===null)return value2;if(ancestors.has(value2))throw new TypeError("Converting circular structure to JSON");ancestors.add(value2);try{if("toJSON"in value2&&(changed=!0),Array.isArray(value2)){let array=[],length=value2.length;for(let index=0;index<length;index++){let descriptor=Object.getOwnPropertyDescriptor(value2,String(index));(!descriptor||descriptor.get)&&(changed=!0),array.push(visit(value2[index],String(index))??null)}return array}let result={},names=Object.keys(value2);(Object.getPrototypeOf(value2)!==Object.prototype||Reflect.ownKeys(value2).length!==names.length)&&(changed=!0);for(let name of names){Object.getOwnPropertyDescriptor(value2,name)?.get&&(changed=!0);let child=visit(value2[name],name);child!==void 0&&Object.defineProperty(result,name,{value:child,enumerable:!0,configurable:!0,writable:!0})}return result}finally{ancestors.delete(value2)}},value;try{value=visit(input,"")}catch(error){if(!(error instanceof RangeError))throw error;if(value=jsonNormalValue(input),value===void 0)throw new SyntaxError("JSON input has no representation");return{value,changed:!0}}if(value===void 0)throw new SyntaxError("JSON input has no representation");return{value,changed}}var MEDIA_BEARING_RECORD_TYPES=new Set(["tool_execution_end","message_start","message_end","turn_end","agent_end","entry_appended"]),MEDIA_BEARING_RESPONSE_COMMANDS=new Set(["get_messages","get_entries","get_tree","get_state","open_session"]);function base64ByteLength(data){let padding=data.endsWith("==")?2:data.endsWith("=")?1:0;return Math.max(0,Math.floor(data.length*3/4)-padding)}function isPlainObject(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isInlineImage(value){return isPlainObject(value)&&value.type==="image"&&typeof value.data=="string"}function omitContentImages(content,toolCallId,persist){let replaced;for(let index=0;index<content.length;index++){let block=content[index];if(!isInlineImage(block))continue;replaced??=[...content];let ref={toolCallId,contentIndex:index};replaced[index]={type:"image_ref",mimeType:typeof block.mimeType=="string"?block.mimeType:"application/octet-stream",byteLength:base64ByteLength(block.data),ref,...persist?.(ref,block)}}return replaced??content}function omitToolResultImages(message,persist){let content=message.content,toolCallId=typeof message.toolCallId=="string"?message.toolCallId:"";if(!Array.isArray(content))return message;let omitted=omitContentImages(content,toolCallId,persist);return omitted===content?message:{...message,content:omitted}}function enter(value,key,persist){if(Array.isArray(value))return{key,value,index:0};if(!isPlainObject(value))return;let scrubbed=value.role==="toolResult"?omitToolResultImages(value,persist):value,entries=Object.entries(scrubbed).filter(([name,child])=>(name!=="content"||scrubbed===value)&&(isPlainObject(child)||Array.isArray(child)));return scrubbed===value?{key,value,scrubbed,entries,index:0}:{key,value,scrubbed,entries,index:0,replaced:{...scrubbed}}}function walk(root,persist){let first=enter(root,0,persist);if(!first)return root;let stack=[first],ancestors=new Set([first.value]);for(;;){let top=stack[stack.length-1];if("entries"in top?top.index<top.entries.length:top.index<top.value.length){let[key,child]="entries"in top?top.entries[top.index]:[top.index,top.value[top.index]];top.index++;let frame=enter(child,key,persist);if(!frame)continue;if(ancestors.has(frame.value))throw new TypeError("Converting circular structure to JSON");ancestors.add(frame.value),stack.push(frame);continue}stack.pop(),ancestors.delete(top.value);let result=top.replaced??top.value,parent=stack[stack.length-1];if(!parent)return result;result!==top.value&&("entries"in parent?(parent.replaced??={...parent.scrubbed})[top.key]=result:(parent.replaced??=[...parent.value])[top.key]=result)}}function omitToolExecutionEndImages(record,persist){let result=record.result;if(!isPlainObject(result)||!Array.isArray(result.content))return record;let toolCallId=typeof record.toolCallId=="string"?record.toolCallId:"",omitted=omitContentImages(result.content,toolCallId,persist);return omitted===result.content?record:{...record,result:{...result,content:omitted}}}function carriesMedia(record){return typeof record.type!="string"?!1:MEDIA_BEARING_RECORD_TYPES.has(record.type)?!0:record.type==="response"&&typeof record.command=="string"?MEDIA_BEARING_RESPONSE_COMMANDS.has(record.command):!1}function omitNormalInlineMedia(record,persist){let typed=record;if(!carriesMedia(typed))return record;let scrubbed=typed.type==="tool_execution_end"?omitToolExecutionEndImages(typed,persist):typed,walked=walk(scrubbed,persist);return walked===typed?record:walked}export{normalizeJsonValue,base64ByteLength,carriesMedia,omitNormalInlineMedia};
|
|
@@ -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 resolvedValues=new Set,redactionForms;function rememberResolvedReferenceValue(value){value.length<4||resolvedValues.has(value)||(resolvedValues.add(value),redactionForms=void 0)}function encodings(value){let form=new URLSearchParams([["",value]]).toString().slice(1);return[value,JSON.stringify(value).slice(1,-1),encodeURIComponent(value),encodeURI(value),form]}function forms(){return redactionForms??=[...new Set([...resolvedValues].flatMap(encodings))].filter(form=>form.length>=4).sort((left,right)=>right.length-left.length),redactionForms}function redactResolvedReferenceValues(text,replacement="<redacted>"){let redacted=text;for(let form of forms())redacted.includes(form)&&(redacted=redacted.split(form).join(replacement));return redacted}var PROTOCOL_TYPES=new Set(["text","image","audio","resource","resource_link","object","array","string","number","integer","boolean","null"]),SCHEMA_FORMATS=new Set(["date-time","date","time","duration","email","idn-email","hostname","idn-hostname","ipv4","ipv6","uri","uri-reference","iri","iri-reference","uri-template","uuid","json-pointer","relative-json-pointer","regex","byte","binary","password"]),MEDIA_TYPES=new Set(["text/plain","text/markdown","text/html","text/css","text/csv","text/javascript","text/xml","text/x-python","text/x-typescript","application/json","application/xml","application/yaml","application/javascript","application/typescript","application/pdf","application/zip","application/gzip","application/octet-stream","application/x-ndjson","image/png","image/jpeg","image/gif","image/webp","image/svg+xml","image/bmp","image/avif","image/heic","image/tiff","audio/wav","audio/mpeg","audio/mp3","audio/ogg","audio/webm","audio/flac","audio/aac","video/mp4","video/webm"]),SCHEMA_URLS=new Set(["http://json-schema.org/draft-04/schema#","http://json-schema.org/draft-06/schema#","http://json-schema.org/draft-07/schema#","http://json-schema.org/schema#","https://json-schema.org/draft/2019-09/schema","https://json-schema.org/draft/2020-12/schema"]),PROTOCOL_VALUES={type:PROTOCOL_TYPES,mimeType:MEDIA_TYPES,format:SCHEMA_FORMATS,jsonrpc:new Set(["2.0"]),role:new Set(["user","assistant"]),$schema:SCHEMA_URLS};function isProtocolValue(key,value){return Object.hasOwn(PROTOCOL_VALUES,key)&&PROTOCOL_VALUES[key]?.has(value)===!0}function redactResolvedReferenceData(value){if(resolvedValues.size===0)return value;let copies=new WeakMap,pending=[],copy=input=>{let source=typeof input=="object"&&input!==null&&typeof Reflect.get(input,"toJSON")=="function"?Reflect.get(input,"toJSON").call(input):input;if(typeof source=="string")return redactResolvedReferenceValues(source);if(typeof source!="object"||source===null)return source;let existing=copies.get(source);if(existing!==void 0)return existing;let target=Array.isArray(source)?new Array(source.length):{};return copies.set(source,target),pending.push({source,target}),target},result=copy(value);for(let{source,target}of pending)for(let key of Object.keys(source)){let child=Reflect.get(source,key);Object.defineProperty(target,key,{value:typeof child=="string"&&isProtocolValue(key,child)?child:copy(child),enumerable:!0,writable:!0,configurable:!0})}return result}export{rememberResolvedReferenceValue,redactResolvedReferenceValues,redactResolvedReferenceData};
|