@code-yeongyu/senpi 2026.8.29 → 2026.8.30
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 +66 -0
- package/dist/core/agent-session.d.ts +45 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +312 -25
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +155 -37
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/credential-accounts.d.ts.map +1 -1
- package/dist/core/credential-accounts.js +23 -9
- package/dist/core/credential-accounts.js.map +1 -1
- package/dist/core/credential-pool/env-slots.d.ts.map +1 -1
- package/dist/core/credential-pool/env-slots.js +2 -0
- package/dist/core/credential-pool/env-slots.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +8 -2
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +160 -47
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/retained-message-safety.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/retained-message-safety.js +31 -8
- package/dist/core/extensions/builtin/compaction/retained-message-safety.js.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/stream.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/stream.js +8 -28
- package/dist/core/extensions/builtin/cursor-cli-oauth/stream.js.map +1 -1
- package/dist/core/extensions/builtin/permission-system/external-dir.d.ts.map +1 -1
- package/dist/core/extensions/builtin/permission-system/external-dir.js +15 -5
- package/dist/core/extensions/builtin/permission-system/external-dir.js.map +1 -1
- package/dist/core/extensions/builtin/permission-system/parsers.d.ts.map +1 -1
- package/dist/core/extensions/builtin/permission-system/parsers.js +16 -1
- package/dist/core/extensions/builtin/permission-system/parsers.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/manager.d.ts +5 -0
- package/dist/core/extensions/builtin/terminal/manager.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/manager.js +31 -3
- package/dist/core/extensions/builtin/terminal/manager.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-permission.d.ts +8 -0
- package/dist/core/extensions/builtin/terminal/monitor-permission.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-permission.js +16 -0
- package/dist/core/extensions/builtin/terminal/monitor-permission.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts +13 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-registry.js +403 -3
- package/dist/core/extensions/builtin/terminal/monitor-registry.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/session-bundle.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/session-bundle.js +1 -0
- package/dist/core/extensions/builtin/terminal/session-bundle.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/kill-bash.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/kill-bash.js +5 -2
- package/dist/core/extensions/builtin/terminal/tools/kill-bash.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts +4 -0
- package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/monitor.js +40 -2
- package/dist/core/extensions/builtin/terminal/tools/monitor.js.map +1 -1
- package/dist/core/model-resolver.js +2 -2
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +10 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +7 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +6 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +97 -15
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -0
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +8 -0
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +76 -34
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +7 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +34 -8
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/grok/chrome.d.ts +2 -0
- package/dist/modes/interactive/grok/chrome.d.ts.map +1 -1
- package/dist/modes/interactive/grok/chrome.js.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts +51 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.js +235 -20
- package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +7 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +114 -2
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/connection-handler.d.ts +8 -1
- package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
- package/dist/modes/rpc/connection-handler.js +145 -49
- package/dist/modes/rpc/connection-handler.js.map +1 -1
- package/dist/modes/rpc/host-ensure.d.ts +2 -0
- package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
- package/dist/modes/rpc/host-ensure.js +15 -2
- package/dist/modes/rpc/host-ensure.js.map +1 -1
- package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
- package/dist/modes/rpc/host-lifecycle.js +31 -12
- package/dist/modes/rpc/host-lifecycle.js.map +1 -1
- package/dist/modes/rpc/host-watchdog.d.ts +2 -0
- package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
- package/dist/modes/rpc/host-watchdog.js +23 -12
- package/dist/modes/rpc/host-watchdog.js.map +1 -1
- package/dist/modes/rpc/multi-session-host.js +6 -4
- package/dist/modes/rpc/multi-session-host.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +10 -4
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +45 -10
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-input-validation.d.ts +1 -0
- package/dist/modes/rpc/rpc-input-validation.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-input-validation.js +66 -0
- package/dist/modes/rpc/rpc-input-validation.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +79 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-binding.d.ts +1 -0
- package/dist/modes/rpc/session-binding.d.ts.map +1 -1
- package/dist/modes/rpc/session-binding.js +21 -1
- package/dist/modes/rpc/session-binding.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +1 -0
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-event-writer.d.ts +2 -0
- package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-writer.js +54 -7
- package/dist/modes/rpc/session-event-writer.js.map +1 -1
- package/dist/modes/rpc/session-extension-ui-requests.d.ts +1 -0
- package/dist/modes/rpc/session-extension-ui-requests.d.ts.map +1 -1
- package/dist/modes/rpc/session-extension-ui-requests.js +5 -0
- package/dist/modes/rpc/session-extension-ui-requests.js.map +1 -1
- package/dist/modes/rpc/session-registry.d.ts +10 -2
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +58 -4
- package/dist/modes/rpc/session-registry.js.map +1 -1
- package/dist/modes/rpc/socket-event-fanout.d.ts +22 -0
- package/dist/modes/rpc/socket-event-fanout.d.ts.map +1 -0
- package/dist/modes/rpc/socket-event-fanout.js +84 -0
- package/dist/modes/rpc/socket-event-fanout.js.map +1 -0
- package/docs/rpc.md +3 -1
- package/docs/settings.md +34 -0
- package/docs/windows.md +2 -0
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +38 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-indirect-eval.js +139 -90
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +4 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js +40 -20
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts +3 -3
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.d.ts +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.js +28 -9
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +58 -31
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.d.ts +20 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js +443 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts +7 -0
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +5 -0
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/mux.d.ts +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/mux.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/mux.js +2 -2
- package/node_modules/@earendil-works/pi-tui/dist/mux.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js +19 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* go to `sink.writeRaw` instead of `writeRawStdout`, and the caller decides how
|
|
15
15
|
* (and whether) to end the process.
|
|
16
16
|
*/
|
|
17
|
+
import type { AgentAbortSource } from "../../core/agent-abort-provenance.ts";
|
|
17
18
|
import type { AgentSession } from "../../core/agent-session.ts";
|
|
18
19
|
import type { AgentSessionRuntime } from "../../core/agent-session-runtime.ts";
|
|
19
20
|
import type { RpcSessionState } from "./rpc-types.ts";
|
|
@@ -50,6 +51,8 @@ export interface RpcConnectionHandler {
|
|
|
50
51
|
* host polls this after each command and decides how to tear down.
|
|
51
52
|
*/
|
|
52
53
|
isShutdownRequested(): boolean;
|
|
54
|
+
/** Cancel UI requests that can no longer be answered by this connection. */
|
|
55
|
+
cancelPendingExtensionUiRequests(): void;
|
|
53
56
|
/** Tear down subscriptions and dispose the runtime. Never calls process.exit. */
|
|
54
57
|
dispose(): Promise<void>;
|
|
55
58
|
}
|
|
@@ -59,8 +62,12 @@ export interface RpcConnectionHandler {
|
|
|
59
62
|
* Shared with `open_session` (session-command-router) so both surfaces answer with the SAME
|
|
60
63
|
* fields: a second hand-rolled literal silently drifts, which is how `serviceTier`/`fastMode`
|
|
61
64
|
* would otherwise be missing from an opened session's initial state.
|
|
65
|
+
*
|
|
66
|
+
* `lastAbortSource` is passed in rather than read from the session: `session.currentAbortSource`
|
|
67
|
+
* is cleared once the turn settles, so only the caller that observed `agent_end` still knows
|
|
68
|
+
* who owned the abort.
|
|
62
69
|
*/
|
|
63
|
-
export declare function buildRpcSessionState(session: AgentSession): RpcSessionState;
|
|
70
|
+
export declare function buildRpcSessionState(session: AgentSession, lastAbortSource?: AgentAbortSource): RpcSessionState;
|
|
64
71
|
/**
|
|
65
72
|
* Create a per-connection RPC handler bound to one runtime host and one sink.
|
|
66
73
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-handler.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/connection-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAqB,MAAM,6BAA6B,CAAC;AACnF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"connection-handler.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/connection-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAqB,MAAM,6BAA6B,CAAC;AACnF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAyC/E,OAAO,KAAK,EAYX,eAAe,EAEf,MAAM,gBAAgB,CAAC;AAGxB,kFAAkF;AAClF,MAAM,WAAW,oBAAoB;IACpC,mFAAmF;IACnF,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,iFAAiF;IACjF,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,0DAA0D;IAC1D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,sEAAsE;IACtE,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C;;;OAGG;IACH,mBAAmB,IAAI,OAAO,CAAC;IAC/B,4EAA4E;IAC5E,gCAAgC,IAAI,IAAI,CAAC;IACzC,iFAAiF;IACjF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AA4BD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,eAAe,CAAC,EAAE,gBAAgB,GAAG,eAAe,CAkD/G;AA4BD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACzC,WAAW,EAAE,mBAAmB,EAChC,IAAI,EAAE,iBAAiB,EACvB,OAAO,GAAE,oBAAyB,GAChC,oBAAoB,CA4uCtB"}
|
|
@@ -25,11 +25,12 @@ import { CLAUDE_SDK_OAUTH_PROVIDER_ID } from "../../core/extensions/builtin/clau
|
|
|
25
25
|
import { isMcpControlInventoryChanged, MCP_CONTROL_INVENTORY_CHANGED_EVENT, MCP_CONTROL_INVENTORY_REQUEST_EVENT, } from "../../core/extensions/builtin/mcp/control-inventory.js";
|
|
26
26
|
import { applyFastMode, resolveServiceTierMemoryModel, } from "../../core/extensions/builtin/service-tier.js";
|
|
27
27
|
import { getSupportedThinkingLevels } from "../../core/thinking-levels.js";
|
|
28
|
+
import { ProjectTrustStore } from "../../core/trust-manager.js";
|
|
28
29
|
import { theme } from "../interactive/theme/theme.js";
|
|
29
30
|
import { buildCustomUnsupportedRequest, DEFAULT_CUSTOM_EXTENSION_LABEL, EXTENSION_EVENTS_CAPABILITY, } from "./custom-capability.js";
|
|
30
31
|
import { createRpcEventOutputBuffer } from "./event-output-buffer.js";
|
|
31
32
|
import { buildRpcCommandsForSession, createCommandsChangedEvent, rpcCommandListDigest } from "./rpc-command-surface.js";
|
|
32
|
-
import { rpcCommandShapeError, rpcMessageLengthError } from "./rpc-input-validation.js";
|
|
33
|
+
import { rpcCommandPayloadError, rpcCommandShapeError, rpcMessageLengthError } from "./rpc-input-validation.js";
|
|
33
34
|
import { SessionExtensionUiRequests } from "./session-extension-ui-requests.js";
|
|
34
35
|
function loadedExtensionName(path) {
|
|
35
36
|
const synthetic = /^<(?:builtin|inline):([^>]+)>$/.exec(path);
|
|
@@ -65,11 +66,24 @@ function loadedMcpStatus(server) {
|
|
|
65
66
|
* Shared with `open_session` (session-command-router) so both surfaces answer with the SAME
|
|
66
67
|
* fields: a second hand-rolled literal silently drifts, which is how `serviceTier`/`fastMode`
|
|
67
68
|
* would otherwise be missing from an opened session's initial state.
|
|
69
|
+
*
|
|
70
|
+
* `lastAbortSource` is passed in rather than read from the session: `session.currentAbortSource`
|
|
71
|
+
* is cleared once the turn settles, so only the caller that observed `agent_end` still knows
|
|
72
|
+
* who owned the abort.
|
|
68
73
|
*/
|
|
69
|
-
export function buildRpcSessionState(session) {
|
|
74
|
+
export function buildRpcSessionState(session, lastAbortSource) {
|
|
75
|
+
const cwd = session.sessionManager.getCwd();
|
|
76
|
+
// Trust gates project-source settings (shell prefixes, project resources), so an
|
|
77
|
+
// unverifiable verdict must fail closed: no agentDir means no authoritative store to
|
|
78
|
+
// consult, and the session's own manager only counts when it says trusted outright.
|
|
79
|
+
const projectTrusted = session.agentDir
|
|
80
|
+
? new ProjectTrustStore(session.agentDir).get(cwd) === true
|
|
81
|
+
: session.settingsManager?.isProjectTrusted?.() === true;
|
|
70
82
|
return {
|
|
71
83
|
model: session.model,
|
|
72
84
|
thinkingLevel: session.thinkingLevel,
|
|
85
|
+
...(session.thinkingSelection ? { thinkingSelection: session.thinkingSelection } : {}),
|
|
86
|
+
...(lastAbortSource ? { lastAbortSource } : {}),
|
|
73
87
|
serviceTier: session.effectiveServiceTier,
|
|
74
88
|
fastMode: session.isFastModeActive(),
|
|
75
89
|
isStreaming: session.isStreaming,
|
|
@@ -81,8 +95,8 @@ export function buildRpcSessionState(session) {
|
|
|
81
95
|
sessionFile: session.sessionFile,
|
|
82
96
|
sessionId: session.sessionId,
|
|
83
97
|
sessionName: session.sessionName,
|
|
84
|
-
cwd
|
|
85
|
-
projectTrusted
|
|
98
|
+
cwd,
|
|
99
|
+
projectTrusted,
|
|
86
100
|
...(session.sessionFile &&
|
|
87
101
|
!existsSync(session.sessionFile) &&
|
|
88
102
|
session.sessionManager
|
|
@@ -99,6 +113,9 @@ export function buildRpcSessionState(session) {
|
|
|
99
113
|
messageCount: session.messages.length,
|
|
100
114
|
pendingMessageCount: session.pendingMessageCount,
|
|
101
115
|
usageTotals: session.sessionManager.getUsageTotals(),
|
|
116
|
+
contextUsage: typeof session.getContextUsage === "function" ? session.getContextUsage() : undefined,
|
|
117
|
+
favoriteModels: session.favoriteModels?.map((entry) => ({ ...entry })) ?? [],
|
|
118
|
+
scopedModels: session.scopedModels?.map((entry) => ({ ...entry })) ?? [],
|
|
102
119
|
};
|
|
103
120
|
}
|
|
104
121
|
function loadedMcpServers(snapshot) {
|
|
@@ -131,12 +148,17 @@ function loadedSurfacesFingerprint(session, extensions, mcpServers) {
|
|
|
131
148
|
export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
132
149
|
const clientCapabilities = options.capabilities;
|
|
133
150
|
const routingSessionId = options.sessionId;
|
|
151
|
+
// True only while THIS connection's own command drives a replacement; the issuer
|
|
152
|
+
// already learns the new identity from its command response.
|
|
153
|
+
let replacementIssuedHere = false;
|
|
134
154
|
let session = runtimeHost.session;
|
|
135
155
|
let unsubscribe;
|
|
136
156
|
let unsubscribeBackpressure;
|
|
137
157
|
let unsubscribeLoadedSurfaces;
|
|
138
158
|
let unsubscribeExtensionEvents;
|
|
139
159
|
let mcpWireStatus = { servers: [] };
|
|
160
|
+
/** Abort owner of the last settled turn; `session.currentAbortSource` clears on settle. */
|
|
161
|
+
let lastAbortSource;
|
|
140
162
|
let loadedSurfacesDigest;
|
|
141
163
|
let rpcCommandsDigest;
|
|
142
164
|
let suppressLoadedSurfaceEvents = false;
|
|
@@ -306,7 +328,6 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
306
328
|
// Hidden thinking label not supported in RPC mode - requires TUI message rendering access
|
|
307
329
|
},
|
|
308
330
|
setWidget(key, content, options) {
|
|
309
|
-
// Only support string arrays in RPC mode - factory functions are ignored
|
|
310
331
|
if (content === undefined || Array.isArray(content)) {
|
|
311
332
|
output({
|
|
312
333
|
type: "extension_ui_request",
|
|
@@ -316,8 +337,14 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
316
337
|
widgetLines: content,
|
|
317
338
|
widgetPlacement: options?.placement,
|
|
318
339
|
});
|
|
340
|
+
return;
|
|
319
341
|
}
|
|
320
|
-
//
|
|
342
|
+
// A component factory closes over live TUI/theme state and cannot cross
|
|
343
|
+
// the RPC boundary. Never drop it silently: an opted-in client can show
|
|
344
|
+
// the same explicit degradation notice used by ctx.ui.custom.
|
|
345
|
+
const request = buildCustomUnsupportedRequest(clientCapabilities, "widget component");
|
|
346
|
+
if (request)
|
|
347
|
+
output(request);
|
|
321
348
|
},
|
|
322
349
|
setFooter(_factory) {
|
|
323
350
|
// Custom footer not supported in RPC mode - requires TUI access
|
|
@@ -443,19 +470,49 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
443
470
|
}
|
|
444
471
|
};
|
|
445
472
|
runtimeHost.setRebindSession(async () => {
|
|
446
|
-
|
|
473
|
+
// AgentSessionRuntime invokes this callback while completing a replacement.
|
|
474
|
+
// Do not await extension binding here: extensions may wait for session work
|
|
475
|
+
// that the replacement still owns. The command response must acknowledge the
|
|
476
|
+
// committed replacement; derived surfaces refresh out of band afterwards.
|
|
477
|
+
await rebindSession(true);
|
|
447
478
|
});
|
|
448
|
-
const
|
|
479
|
+
const rebindAfterLocalReplacement = async () => {
|
|
480
|
+
replacementIssuedHere = true;
|
|
481
|
+
try {
|
|
482
|
+
await rebindSession();
|
|
483
|
+
}
|
|
484
|
+
finally {
|
|
485
|
+
replacementIssuedHere = false;
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
const rebindSession = async (deferRefresh = false) => {
|
|
449
489
|
unsubscribeLoadedSurfaces?.();
|
|
450
490
|
unsubscribeExtensionEvents?.();
|
|
491
|
+
const replacedSession = session !== runtimeHost.session;
|
|
451
492
|
session = runtimeHost.session;
|
|
493
|
+
if (replacedSession) {
|
|
494
|
+
lastAbortSource = undefined;
|
|
495
|
+
if (routingSessionId !== undefined || !replacementIssuedHere) {
|
|
496
|
+
// A replacement can be driven by ANY attached client, so every connection must be
|
|
497
|
+
// told the live binding moved and given the new authoritative identity. Emitted
|
|
498
|
+
// before the derived-surface refresh so a client cannot act on the old identity in
|
|
499
|
+
// the window the refresh takes.
|
|
500
|
+
outputEvent({
|
|
501
|
+
type: "session_replaced",
|
|
502
|
+
sessionId: session.sessionId,
|
|
503
|
+
sessionFile: session.sessionFile,
|
|
504
|
+
cwd: session.sessionManager.getCwd(),
|
|
505
|
+
sessionName: session.sessionName,
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
}
|
|
452
509
|
unsubscribeExtensionEvents = clientCapabilities?.includes(EXTENSION_EVENTS_CAPABILITY)
|
|
453
510
|
? session.extensionRunner.onRpcEvent(({ name, data }) => {
|
|
454
511
|
outputEvent({ type: "extension_event", name, data });
|
|
455
512
|
})
|
|
456
513
|
: undefined;
|
|
457
514
|
subscribeLoadedSurfaceEvents();
|
|
458
|
-
|
|
515
|
+
const refresh = refreshLoadedSurfacesAfter(() => session.bindExtensions({
|
|
459
516
|
uiContext: createExtensionUIContext(),
|
|
460
517
|
mode: "rpc",
|
|
461
518
|
commandContextActions: {
|
|
@@ -500,22 +557,50 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
500
557
|
});
|
|
501
558
|
},
|
|
502
559
|
}), true);
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
560
|
+
const installSessionSubscriptions = () => {
|
|
561
|
+
unsubscribe?.();
|
|
562
|
+
unsubscribeBackpressure?.();
|
|
563
|
+
unsubscribe = session.subscribe((event) => {
|
|
564
|
+
if (event.type === "skill_invocation") {
|
|
565
|
+
outputEvent(event);
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
if (event.type === "command_invocation") {
|
|
569
|
+
outputEvent(event);
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
if (event.type === "thinking_level_changed" || event.type === "model_changed") {
|
|
573
|
+
// Core emits the effective level only; the selection provenance lives beside it
|
|
574
|
+
// on the session and is what distinguishes an explicit choice from a default.
|
|
575
|
+
const thinkingSelection = session.thinkingSelection;
|
|
576
|
+
outputEvent(thinkingSelection === undefined ? event : { ...event, thinkingSelection });
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
if (event.type === "agent_end") {
|
|
580
|
+
// The subscribe-path `agent_end` carries only { type, messages, willRetry };
|
|
581
|
+
// the abort provenance the extension hook receives is stripped from it. Read
|
|
582
|
+
// it from the session, which still reports the owner at this point, and retain
|
|
583
|
+
// it for `get_state` because the getter clears once the turn settles.
|
|
584
|
+
const abortSource = session.currentAbortSource;
|
|
585
|
+
if (abortSource !== undefined)
|
|
586
|
+
lastAbortSource = abortSource;
|
|
587
|
+
outputEvent(abortSource === undefined ? event : { ...event, aborted: true, abortSource });
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
511
590
|
outputEvent(event);
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
591
|
+
});
|
|
592
|
+
unsubscribeBackpressure = session.agent.subscribe(async () => {
|
|
593
|
+
await waitForRpcBackpressure();
|
|
594
|
+
});
|
|
595
|
+
};
|
|
596
|
+
if (deferRefresh) {
|
|
597
|
+
void refresh.then(installSessionSubscriptions, (cause) => {
|
|
598
|
+
outputEvent({ type: "rpc_error", error: String(cause) });
|
|
599
|
+
});
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
await refresh;
|
|
603
|
+
installSessionSubscriptions();
|
|
519
604
|
};
|
|
520
605
|
/**
|
|
521
606
|
* Drive an OAuth login for one provider as fire-command-then-subscribe.
|
|
@@ -623,6 +708,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
623
708
|
images: command.images,
|
|
624
709
|
streamingBehavior: command.streamingBehavior,
|
|
625
710
|
thinkingLevel: command.thinkingLevel,
|
|
711
|
+
sessionTitlePrompt: command.sessionTitlePrompt,
|
|
626
712
|
expandPromptTemplates: command.expandPromptTemplates,
|
|
627
713
|
source: "rpc",
|
|
628
714
|
promptDisposition: (nextDisposition) => {
|
|
@@ -648,13 +734,11 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
648
734
|
? { role: "user", content, timestamp: Date.now() }
|
|
649
735
|
: { role: "user", content, timestamp: Date.now() };
|
|
650
736
|
session.sessionManager.appendMessage(message);
|
|
651
|
-
session.messages.
|
|
737
|
+
session.agent.state.messages = session.sessionManager.buildSessionContext().messages;
|
|
652
738
|
return success(id, "append_user_message");
|
|
653
739
|
}
|
|
654
740
|
case "append_session_entry": {
|
|
655
|
-
session.
|
|
656
|
-
if (command.entry.type === "message")
|
|
657
|
-
session.messages.push(command.entry.message);
|
|
741
|
+
session.appendSessionEntry(command.entry);
|
|
658
742
|
return success(id, "append_session_entry");
|
|
659
743
|
}
|
|
660
744
|
case "send_custom_message": {
|
|
@@ -707,16 +791,15 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
707
791
|
case "new_session": {
|
|
708
792
|
const options = command.parentSession ? { parentSession: command.parentSession } : undefined;
|
|
709
793
|
const result = await runtimeHost.newSession(options);
|
|
710
|
-
if (!result.cancelled)
|
|
711
|
-
await
|
|
712
|
-
}
|
|
794
|
+
if (routingSessionId === undefined && !result.cancelled && session !== runtimeHost.session)
|
|
795
|
+
await rebindAfterLocalReplacement();
|
|
713
796
|
return success(id, "new_session", result);
|
|
714
797
|
}
|
|
715
798
|
// =================================================================
|
|
716
799
|
// State
|
|
717
800
|
// =================================================================
|
|
718
801
|
case "get_state":
|
|
719
|
-
return success(id, "get_state", buildRpcSessionState(session));
|
|
802
|
+
return success(id, "get_state", buildRpcSessionState(session, lastAbortSource));
|
|
720
803
|
// =================================================================
|
|
721
804
|
// Model
|
|
722
805
|
// =================================================================
|
|
@@ -729,8 +812,14 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
729
812
|
const systemPromptChange = await session.setModel(model);
|
|
730
813
|
return success(id, "set_model", { ...model, systemPromptName: systemPromptChange?.systemPromptName });
|
|
731
814
|
}
|
|
815
|
+
case "set_favorite_models":
|
|
816
|
+
session.setFavoriteModels(command.models);
|
|
817
|
+
return success(id, "set_favorite_models");
|
|
818
|
+
case "set_scoped_models":
|
|
819
|
+
session.setScopedModels(command.models);
|
|
820
|
+
return success(id, "set_scoped_models");
|
|
732
821
|
case "cycle_model": {
|
|
733
|
-
const result = await session.cycleModel();
|
|
822
|
+
const result = await session.cycleModel(command.direction);
|
|
734
823
|
if (!result) {
|
|
735
824
|
return success(id, "cycle_model", null);
|
|
736
825
|
}
|
|
@@ -861,7 +950,8 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
861
950
|
session.sessionManager.appendLabelChange(command.entryId, command.label);
|
|
862
951
|
return success(id, "set_label");
|
|
863
952
|
case "bash": {
|
|
864
|
-
|
|
953
|
+
if (routingSessionId !== undefined)
|
|
954
|
+
outputEvent({ type: "bash_start" });
|
|
865
955
|
try {
|
|
866
956
|
const eventResult = await session.extensionRunner.emitUserBash({
|
|
867
957
|
type: "user_bash",
|
|
@@ -877,6 +967,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
877
967
|
}
|
|
878
968
|
const result = await session.executeBash(command.command, undefined, {
|
|
879
969
|
excludeFromContext: command.excludeFromContext,
|
|
970
|
+
id: command.executionId,
|
|
880
971
|
// Functions cannot cross JSONL. Host extensions may still provide the
|
|
881
972
|
// executable operations object; client-supplied data is only a wire-safe hint.
|
|
882
973
|
operations: eventResult?.operations,
|
|
@@ -884,13 +975,17 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
884
975
|
return success(id, "bash", result);
|
|
885
976
|
}
|
|
886
977
|
finally {
|
|
887
|
-
|
|
978
|
+
if (routingSessionId !== undefined)
|
|
979
|
+
outputEvent({ type: "bash_end" });
|
|
888
980
|
}
|
|
889
981
|
}
|
|
890
982
|
case "abort_bash": {
|
|
891
983
|
session.abortBash();
|
|
892
984
|
return success(id, "abort_bash");
|
|
893
985
|
}
|
|
986
|
+
case "cleanup_bash_output":
|
|
987
|
+
await session.cleanupBashOutput(command.path);
|
|
988
|
+
return success(id, "cleanup_bash_output");
|
|
894
989
|
// =================================================================
|
|
895
990
|
// Session
|
|
896
991
|
// =================================================================
|
|
@@ -899,7 +994,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
899
994
|
return success(id, "get_session_stats", stats);
|
|
900
995
|
}
|
|
901
996
|
case "export_html": {
|
|
902
|
-
const path = await session.exportToHtml(command.outputPath);
|
|
997
|
+
const path = await session.exportToHtml(command.outputPath, { themeName: command.themeName });
|
|
903
998
|
return success(id, "export_html", { path });
|
|
904
999
|
}
|
|
905
1000
|
case "export_jsonl": {
|
|
@@ -907,16 +1002,14 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
907
1002
|
}
|
|
908
1003
|
case "switch_session": {
|
|
909
1004
|
const result = await runtimeHost.switchSession(command.sessionPath, { cwdOverride: command.cwdOverride });
|
|
910
|
-
if (!result.cancelled)
|
|
911
|
-
await
|
|
912
|
-
}
|
|
1005
|
+
if (routingSessionId === undefined && !result.cancelled && session !== runtimeHost.session)
|
|
1006
|
+
await rebindAfterLocalReplacement();
|
|
913
1007
|
return success(id, "switch_session", result);
|
|
914
1008
|
}
|
|
915
1009
|
case "fork": {
|
|
916
1010
|
const result = await runtimeHost.fork(command.entryId, { position: command.position });
|
|
917
|
-
if (!result.cancelled)
|
|
918
|
-
await
|
|
919
|
-
}
|
|
1011
|
+
if (routingSessionId === undefined && !result.cancelled && session !== runtimeHost.session)
|
|
1012
|
+
await rebindAfterLocalReplacement();
|
|
920
1013
|
return success(id, "fork", { text: result.selectedText, cancelled: result.cancelled });
|
|
921
1014
|
}
|
|
922
1015
|
case "clone": {
|
|
@@ -925,9 +1018,8 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
925
1018
|
return error(id, "clone", "Cannot clone session: no current entry selected");
|
|
926
1019
|
}
|
|
927
1020
|
const result = await runtimeHost.fork(leafId, { position: "at" });
|
|
928
|
-
if (!result.cancelled)
|
|
929
|
-
await
|
|
930
|
-
}
|
|
1021
|
+
if (routingSessionId === undefined && !result.cancelled && session !== runtimeHost.session)
|
|
1022
|
+
await rebindAfterLocalReplacement();
|
|
931
1023
|
return success(id, "clone", { cancelled: result.cancelled });
|
|
932
1024
|
}
|
|
933
1025
|
case "get_fork_messages": {
|
|
@@ -956,8 +1048,8 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
956
1048
|
}
|
|
957
1049
|
case "import_jsonl": {
|
|
958
1050
|
const result = await runtimeHost.importFromJsonl(command.inputPath, command.cwdOverride);
|
|
959
|
-
if (!result.cancelled)
|
|
960
|
-
await
|
|
1051
|
+
if (routingSessionId === undefined && !result.cancelled && session !== runtimeHost.session)
|
|
1052
|
+
await rebindAfterLocalReplacement();
|
|
961
1053
|
return success(id, "import_jsonl", result);
|
|
962
1054
|
}
|
|
963
1055
|
case "set_session_name": {
|
|
@@ -1079,9 +1171,10 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
1079
1171
|
return;
|
|
1080
1172
|
}
|
|
1081
1173
|
const command = parsed;
|
|
1174
|
+
const payloadError = rpcCommandPayloadError(command);
|
|
1082
1175
|
const messageLengthError = rpcMessageLengthError(command);
|
|
1083
|
-
if (messageLengthError) {
|
|
1084
|
-
output(error(command.id, command.type, messageLengthError));
|
|
1176
|
+
if (payloadError || messageLengthError) {
|
|
1177
|
+
output(error(command.id, command.type, payloadError ?? messageLengthError));
|
|
1085
1178
|
await waitForRpcBackpressure();
|
|
1086
1179
|
return;
|
|
1087
1180
|
}
|
|
@@ -1125,6 +1218,9 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
|
|
|
1125
1218
|
isShutdownRequested() {
|
|
1126
1219
|
return shutdownRequested;
|
|
1127
1220
|
},
|
|
1221
|
+
cancelPendingExtensionUiRequests() {
|
|
1222
|
+
pendingExtensionRequests.cancelAll();
|
|
1223
|
+
},
|
|
1128
1224
|
async dispose() {
|
|
1129
1225
|
await ready;
|
|
1130
1226
|
await dispose();
|