@code-yeongyu/senpi 2026.9.21-2 → 2026.9.22
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 +21 -0
- package/dist/bundle/chunks/{anthropic-messages-C3ZY2ANT.js → anthropic-messages-2P7APOOQ.js} +1 -1
- package/dist/bundle/chunks/{app-server-command-HSX5RFAP.js → app-server-command-DLBXJ5K5.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-7TAGS2VU.js → azure-openai-responses-3AH7MJWF.js} +1 -1
- package/dist/bundle/chunks/{chunk-3SLCHXZO.js → chunk-4AXZDO3E.js} +2 -2
- package/dist/bundle/chunks/{chunk-Z3KQB2R3.js → chunk-7ICH7UFW.js} +12 -12
- package/dist/bundle/chunks/{chunk-KNM6SRPE.js → chunk-AAVNXTGQ.js} +1 -1
- package/dist/bundle/chunks/{chunk-IDTLJYJ5.js → chunk-AY37SZJZ.js} +4 -4
- package/dist/bundle/chunks/{chunk-XHMOFY4T.js → chunk-BUPX33Q4.js} +3 -3
- package/dist/bundle/chunks/{chunk-GLKVDRNP.js → chunk-CWCY7LXK.js} +1 -1
- package/dist/bundle/chunks/{chunk-POMPEGWQ.js → chunk-F3DXL5MX.js} +1 -1
- package/dist/bundle/chunks/{chunk-GVI2HP7N.js → chunk-I2HIIJPI.js} +1 -1
- package/dist/bundle/chunks/{chunk-T6XA2IZR.js → chunk-JR4X6ECO.js} +1 -1
- package/dist/bundle/chunks/{chunk-M2XAY6I7.js → chunk-M2HSO7MH.js} +1 -1
- package/dist/bundle/chunks/{chunk-MIVOQT3Q.js → chunk-N5AQJAQ2.js} +1 -1
- package/dist/bundle/chunks/{chunk-UYVPLEOL.js → chunk-NK2RNX25.js} +1 -1
- package/dist/bundle/chunks/chunk-NMB4C6ZZ.js +2 -0
- package/dist/bundle/chunks/{chunk-B7W62BM7.js → chunk-P4OHEJ7P.js} +1 -1
- package/dist/bundle/chunks/{chunk-I425CMTO.js → chunk-VBNHBSBD.js} +1 -1
- package/dist/bundle/chunks/{chunk-B2IM56LB.js → chunk-VYIJQQ5I.js} +1 -1
- package/dist/bundle/chunks/chunk-XRHUMMIW.js +8 -0
- package/dist/bundle/chunks/{chunk-47GF6XYZ.js → chunk-YT2ZSZOY.js} +1 -1
- package/dist/bundle/chunks/{chunk-OSDJ2SYO.js → chunk-ZCBX2K34.js} +1 -1
- package/dist/bundle/chunks/{chunk-D5CL7PPD.js → chunk-ZMVXBX33.js} +2 -2
- package/dist/bundle/chunks/{cli-main-GQTEEZ2V.js → cli-main-D2VPNIQ3.js} +1 -1
- package/dist/bundle/chunks/{google-generative-ai-JWIH75VF.js → google-generative-ai-Y2IYMUVC.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-IRGAY5XR.js → google-vertex-TKBBMPHV.js} +1 -1
- package/dist/bundle/chunks/{host-command-KOEKIHIZ.js → host-command-IFIIOX5S.js} +1 -1
- package/dist/bundle/chunks/host-lifecycle-3OJZA4QQ.js +3 -0
- package/dist/bundle/chunks/host-lifecycle.js +3 -3
- package/dist/bundle/chunks/{interactive-host-runtime-2KTFEW7O.js → interactive-host-runtime-V7PBDIOJ.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-I3ILWXQB.js → interactive-mode-RFMMGQCT.js} +1 -1
- package/dist/bundle/chunks/kimi-coding.js +2 -2
- package/dist/bundle/chunks/{mistral-conversations-VOBYATVJ.js → mistral-conversations-ZYDVFRYF.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-S5FWCIWE.js → multi-session-host-45YMCQIH.js} +8 -7
- package/dist/bundle/chunks/openai-codex-responses-MEIUNROM.js +10 -0
- package/dist/bundle/chunks/{openai-completions-YK6QTYOH.js → openai-completions-4V76L5ZJ.js} +1 -1
- package/dist/bundle/chunks/openai-responses-YR7WRBG3.js +2 -0
- package/dist/bundle/chunks/{package-manager-cli-HOL6CAI6.js → package-manager-cli-7DQKRSI5.js} +1 -1
- package/dist/bundle/chunks/rotation-stream-YPZP3VJS.js +2 -0
- package/dist/bundle/chunks/{rpc-mode-L3DSGTVM.js → rpc-mode-4GWZCJKI.js} +1 -1
- package/dist/bundle/chunks/{session-picker-L3FYEQBL.js → session-picker-ZKRYWZGC.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +38 -37
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/agent-session.d.ts +6 -4
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +9 -7
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/credential-pool/classify.d.ts.map +1 -1
- package/dist/core/credential-pool/classify.js +12 -0
- package/dist/core/credential-pool/classify.js.map +1 -1
- package/dist/core/credential-pool/failover.d.ts +37 -5
- package/dist/core/credential-pool/failover.d.ts.map +1 -1
- package/dist/core/credential-pool/failover.js +60 -24
- package/dist/core/credential-pool/failover.js.map +1 -1
- package/dist/core/credential-pool/rotation-events.d.ts +5 -0
- package/dist/core/credential-pool/rotation-events.d.ts.map +1 -0
- package/dist/core/credential-pool/rotation-events.js +25 -0
- package/dist/core/credential-pool/rotation-events.js.map +1 -0
- package/dist/core/credential-pool/rotation-stream.d.ts +4 -3
- package/dist/core/credential-pool/rotation-stream.d.ts.map +1 -1
- package/dist/core/credential-pool/rotation-stream.js +8 -11
- package/dist/core/credential-pool/rotation-stream.js.map +1 -1
- package/dist/core/extensions/builtin/ask-user/schema.d.ts +2 -25
- package/dist/core/extensions/builtin/ask-user/schema.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ask-user/schema.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +2 -7
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +2 -8
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/naming.d.ts +0 -1
- package/dist/core/extensions/builtin/mcp/expose/naming.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/naming.js +0 -3
- package/dist/core/extensions/builtin/mcp/expose/naming.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/register.d.ts +1 -2
- package/dist/core/extensions/builtin/mcp/expose/register.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/register.js +0 -21
- package/dist/core/extensions/builtin/mcp/expose/register.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/schema-compat.d.ts +2 -2
- package/dist/core/extensions/builtin/mcp/expose/schema-compat.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/expose/schema-compat.js +2 -2
- package/dist/core/extensions/builtin/mcp/expose/schema-compat.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts +29 -0
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +30 -3
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/modes/interactive/components/assistant-render-descriptors.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-render-descriptors.js +8 -7
- package/dist/modes/interactive/components/assistant-render-descriptors.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +7 -5
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/handoff-activity.d.ts +4 -0
- package/dist/modes/rpc/handoff-activity.d.ts.map +1 -0
- package/dist/modes/rpc/handoff-activity.js +6 -0
- package/dist/modes/rpc/handoff-activity.js.map +1 -0
- package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
- package/dist/modes/rpc/host-ensure.js +60 -17
- package/dist/modes/rpc/host-ensure.js.map +1 -1
- package/dist/modes/rpc/host-lifecycle.d.ts +3 -0
- package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
- package/dist/modes/rpc/host-lifecycle.js +25 -5
- package/dist/modes/rpc/host-lifecycle.js.map +1 -1
- package/dist/modes/rpc/multi-session-host.d.ts +1 -0
- package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
- package/dist/modes/rpc/multi-session-host.js +40 -7
- package/dist/modes/rpc/multi-session-host.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +13 -0
- 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-command-router.d.ts +10 -4
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +90 -18
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-event-writer.d.ts +5 -3
- package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-writer.js +21 -2
- package/dist/modes/rpc/session-event-writer.js.map +1 -1
- package/dist/modes/rpc/session-worker-client.d.ts +1 -0
- package/dist/modes/rpc/session-worker-client.d.ts.map +1 -1
- package/dist/modes/rpc/session-worker-client.js +3 -0
- package/dist/modes/rpc/session-worker-client.js.map +1 -1
- package/dist/modes/rpc/session-worker-protocol.d.ts +3 -1
- package/dist/modes/rpc/session-worker-protocol.d.ts.map +1 -1
- package/dist/modes/rpc/session-worker-protocol.js.map +1 -1
- package/dist/modes/rpc/session-worker.js +7 -1
- package/dist/modes/rpc/session-worker.js.map +1 -1
- package/docs/providers.md +9 -1
- package/docs/rpc.md +58 -8
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +15 -0
- package/node_modules/@code-yeongyu/senpi-codemode/README.md +51 -13
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridges/agent-bridge.ts +53 -9
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridges/reserved-dispatch.ts +1 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/config/settings.ts +18 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/extension/eval-status.ts +9 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +3 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/AGENTS.md +2 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/prelude.jl +10 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/context-manager.ts +18 -6
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-contract.ts +2 -6
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/prelude.ts +1 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/run-queue.ts +17 -7
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-runtime.js +6 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/kernel-contract.ts +2 -5
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/kernel.ts +37 -5
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/prelude.py +11 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/prelude.rb +6 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-contract.ts +2 -5
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-kernel.ts +14 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-queue.ts +18 -5
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt-template.ts +3 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +4 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/timeouts/idle-timeout.ts +9 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/AGENTS.md +2 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/cell-execution.ts +19 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/cell-runtime.ts +11 -3
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-contract.ts +6 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-manager.ts +72 -20
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-snapshot.ts +28 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-state.ts +5 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-status.ts +5 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-eval-result.ts +76 -25
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-execution-event.ts +4 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-kernel-reset-refused-error.ts +12 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-request.ts +2 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool-options.ts +3 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +58 -37
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/managed-cell.ts +15 -8
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +20 -6
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/run-eval-cell.ts +89 -25
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/terminal-snapshot-store.ts +4 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/types.ts +51 -10
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/README.md +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +14 -56
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +18 -27
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/websocket-transport-failure.d.ts +40 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/websocket-transport-failure.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/websocket-transport-failure.js +102 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/websocket-transport-failure.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.d.ts +4 -3
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js +28 -14
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-region.d.ts +44 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-region.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-region.js +120 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-region.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.d.ts +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.js +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/failover.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js +21 -15
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.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/huggingface.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/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding-auth.d.ts +9 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding-auth.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding-auth.js +43 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding-auth.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.js +3 -2
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/provider-failure-description.d.ts +19 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/provider-failure-description.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/provider-failure-description.js +63 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/provider-failure-description.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +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/package.json +1 -1
- package/package.json +7 -7
- package/dist/bundle/chunks/chunk-5J5R5AMP.js +0 -8
- package/dist/bundle/chunks/chunk-I3F6VZZF.js +0 -2
- package/dist/bundle/chunks/host-lifecycle-DGZJTBDJ.js +0 -3
- package/dist/bundle/chunks/openai-codex-responses-L2PO2D6F.js +0 -10
- package/dist/bundle/chunks/openai-responses-YDUBVF4S.js +0 -2
- package/dist/bundle/chunks/rotation-stream-Y4YU6HV4.js +0 -2
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import type { ToolDefinition } from "@code-yeongyu/senpi";
|
|
2
|
-
import {
|
|
1
|
+
import type { AgentToolResult, ToolDefinition } from "@code-yeongyu/senpi";
|
|
2
|
+
import type { TUnsafe } from "typebox";
|
|
3
|
+
import {
|
|
4
|
+
DEFAULT_FOREGROUND_WINDOW_SECONDS,
|
|
5
|
+
defaultCodemodeSettings,
|
|
6
|
+
resolveMaxDetachedCells,
|
|
7
|
+
} from "../config/settings.ts";
|
|
3
8
|
import { buildEvalPrompt } from "../prompt/eval-prompt.ts";
|
|
4
9
|
import { EvalDetachedCellManager } from "./detached-cell-manager.ts";
|
|
5
|
-
import {
|
|
10
|
+
import { executeEvalControl } from "./detached-eval-result.ts";
|
|
6
11
|
import { clampEvalSummary, isEvalControlRequest, parseEvalRequest } from "./eval-request.ts";
|
|
7
12
|
import type { CreateEvalToolOptions } from "./eval-tool-options.ts";
|
|
8
13
|
import { runEvalCell } from "./run-eval-cell.ts";
|
|
@@ -10,6 +15,9 @@ import {
|
|
|
10
15
|
createEvalInputSchema,
|
|
11
16
|
defaultEvalDeadlineSeconds,
|
|
12
17
|
type EvalInputSchema,
|
|
18
|
+
type EvalListDetails,
|
|
19
|
+
type EvalListInput,
|
|
20
|
+
type EvalResultDetails,
|
|
13
21
|
type EvalToolDetails,
|
|
14
22
|
type EvalToolRequest,
|
|
15
23
|
enabledLanguageList,
|
|
@@ -19,8 +27,16 @@ export type { EvalTimeoutFactory } from "./cell-execution.ts";
|
|
|
19
27
|
export type { CreateEvalToolOptions } from "./eval-tool-options.ts";
|
|
20
28
|
export type { EnabledEvalLanguages, EvalKernel, EvalKernelManager } from "./types.ts";
|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
type EvalExecuteArgs<Request extends EvalToolRequest> = Parameters<
|
|
31
|
+
ToolDefinition<TUnsafe<Request>, EvalToolDetails>["execute"]
|
|
32
|
+
>;
|
|
33
|
+
|
|
34
|
+
export function createEvalTool(options: CreateEvalToolOptions) {
|
|
23
35
|
const foregroundWindowSeconds = options.foregroundWindowSeconds ?? DEFAULT_FOREGROUND_WINDOW_SECONDS;
|
|
36
|
+
const maxDetachedCells =
|
|
37
|
+
options.cellManager?.maxDetachedCells ??
|
|
38
|
+
options.maxDetachedCells ??
|
|
39
|
+
resolveMaxDetachedCells(options.settings ?? defaultCodemodeSettings);
|
|
24
40
|
const deadlines = {
|
|
25
41
|
runBudgetSeconds: options.runBudgetSeconds ?? defaultEvalDeadlineSeconds.runBudgetSeconds,
|
|
26
42
|
detachAfterSeconds: Math.min(options.cellTimeoutSeconds, foregroundWindowSeconds),
|
|
@@ -31,6 +47,7 @@ export function createEvalTool(options: CreateEvalToolOptions): ToolDefinition<E
|
|
|
31
47
|
const prompt = buildEvalPrompt(options.enabledLanguages, {
|
|
32
48
|
spawns: options.spawns ?? false,
|
|
33
49
|
monitor: options.monitor,
|
|
50
|
+
maxDetachedCells,
|
|
34
51
|
runBudgetSeconds: deadlines.runBudgetSeconds,
|
|
35
52
|
...(options.spawnDefaultAgent === undefined ? {} : { spawnDefaultAgent: options.spawnDefaultAgent }),
|
|
36
53
|
...(options.modelId === undefined ? {} : { modelId: options.modelId }),
|
|
@@ -42,10 +59,43 @@ export function createEvalTool(options: CreateEvalToolOptions): ToolDefinition<E
|
|
|
42
59
|
const cellManager =
|
|
43
60
|
options.cellManager ??
|
|
44
61
|
new EvalDetachedCellManager({
|
|
62
|
+
maxDetachedCells,
|
|
45
63
|
...(options.artifactsDir === undefined ? {} : { artifactsDir: options.artifactsDir }),
|
|
46
64
|
...(options.hardLimitSeconds === undefined ? {} : { hardLimitSeconds: options.hardLimitSeconds }),
|
|
47
65
|
...(options.runBudgetSeconds === undefined ? {} : { runBudgetSeconds: options.runBudgetSeconds }),
|
|
48
66
|
});
|
|
67
|
+
// Keep run/peek/stop results typed as execution details; list has no single language or output cell.
|
|
68
|
+
function execute(
|
|
69
|
+
...args: EvalExecuteArgs<Exclude<EvalToolRequest, EvalListInput>>
|
|
70
|
+
): Promise<AgentToolResult<EvalToolDetails>>;
|
|
71
|
+
function execute(...args: EvalExecuteArgs<EvalListInput>): Promise<AgentToolResult<EvalListDetails>>;
|
|
72
|
+
function execute(...args: EvalExecuteArgs<EvalToolRequest>): Promise<AgentToolResult<EvalResultDetails>>;
|
|
73
|
+
async function execute(
|
|
74
|
+
...[toolCallId, params, signal, onUpdate, ctx]: EvalExecuteArgs<EvalToolRequest>
|
|
75
|
+
): Promise<AgentToolResult<EvalResultDetails>> {
|
|
76
|
+
const request = parseEvalRequest(params);
|
|
77
|
+
if (isEvalControlRequest(request)) return await executeEvalControl(cellManager, request);
|
|
78
|
+
if (options.proxyExecutor) return await options.proxyExecutor(request, signal);
|
|
79
|
+
if (!languages.includes(request.language))
|
|
80
|
+
throw new RangeError(
|
|
81
|
+
`Unsupported eval language "${request.language}". Enabled languages: ${languages.join(", ")}`,
|
|
82
|
+
);
|
|
83
|
+
options.executionTracker?.assertEvalExecutionAllowed();
|
|
84
|
+
const lifecycleController = new AbortController();
|
|
85
|
+
const combinedSignal = signal
|
|
86
|
+
? AbortSignal.any([signal, lifecycleController.signal])
|
|
87
|
+
: lifecycleController.signal;
|
|
88
|
+
const execution = runEvalCell(options, cellManager, {
|
|
89
|
+
cellId: toolCallId,
|
|
90
|
+
input: request,
|
|
91
|
+
signal: combinedSignal,
|
|
92
|
+
onUpdate,
|
|
93
|
+
ctx,
|
|
94
|
+
});
|
|
95
|
+
return options.executionTracker
|
|
96
|
+
? await options.executionTracker.trackEvalExecution(execution, lifecycleController)
|
|
97
|
+
: await execution;
|
|
98
|
+
}
|
|
49
99
|
return {
|
|
50
100
|
name: "eval",
|
|
51
101
|
label: "Eval",
|
|
@@ -57,7 +107,8 @@ export function createEvalTool(options: CreateEvalToolOptions): ToolDefinition<E
|
|
|
57
107
|
prepareArguments: (args) => {
|
|
58
108
|
if (typeof args !== "object" || args === null) return args as EvalToolRequest;
|
|
59
109
|
const record = args as Record<string, unknown>;
|
|
60
|
-
if (record.action === "peek" || record.action === "stop"
|
|
110
|
+
if (record.action === "peek" || record.action === "stop" || record.action === "list")
|
|
111
|
+
return args as EvalToolRequest;
|
|
61
112
|
const summary = clampEvalSummary(record.summary);
|
|
62
113
|
if (summary === undefined) delete record.summary;
|
|
63
114
|
else record.summary = summary;
|
|
@@ -65,36 +116,6 @@ export function createEvalTool(options: CreateEvalToolOptions): ToolDefinition<E
|
|
|
65
116
|
},
|
|
66
117
|
...(options.renderers?.renderCall === undefined ? {} : { renderCall: options.renderers.renderCall }),
|
|
67
118
|
...(options.renderers?.renderResult === undefined ? {} : { renderResult: options.renderers.renderResult }),
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (isEvalControlRequest(request)) return await executeEvalControl(cellManager, request);
|
|
71
|
-
if (options.proxyExecutor) return await options.proxyExecutor(request, signal);
|
|
72
|
-
if (!languages.includes(request.language))
|
|
73
|
-
throw new RangeError(
|
|
74
|
-
`Unsupported eval language "${request.language}". Enabled languages: ${languages.join(", ")}`,
|
|
75
|
-
);
|
|
76
|
-
const busy = cellManager.busyFor(request.language);
|
|
77
|
-
if (busy !== undefined) {
|
|
78
|
-
const idleLanguages = languages.filter(
|
|
79
|
-
(language) => language !== request.language && cellManager.busyFor(language) === undefined,
|
|
80
|
-
);
|
|
81
|
-
throw detachedKernelBusyError(busy, idleLanguages);
|
|
82
|
-
}
|
|
83
|
-
options.executionTracker?.assertEvalExecutionAllowed();
|
|
84
|
-
const lifecycleController = new AbortController();
|
|
85
|
-
const combinedSignal = signal
|
|
86
|
-
? AbortSignal.any([signal, lifecycleController.signal])
|
|
87
|
-
: lifecycleController.signal;
|
|
88
|
-
const execution = runEvalCell(options, cellManager, {
|
|
89
|
-
cellId: toolCallId,
|
|
90
|
-
input: request,
|
|
91
|
-
signal: combinedSignal,
|
|
92
|
-
onUpdate,
|
|
93
|
-
ctx,
|
|
94
|
-
});
|
|
95
|
-
return options.executionTracker
|
|
96
|
-
? await options.executionTracker.trackEvalExecution(execution, lifecycleController)
|
|
97
|
-
: await execution;
|
|
98
|
-
},
|
|
99
|
-
};
|
|
119
|
+
execute,
|
|
120
|
+
} satisfies ToolDefinition<EvalInputSchema, EvalResultDetails>;
|
|
100
121
|
}
|
|
@@ -12,7 +12,9 @@ export type ManagedCell = {
|
|
|
12
12
|
readonly spillPath: string | undefined;
|
|
13
13
|
readonly startedAtMs: number;
|
|
14
14
|
readonly terminal: PromiseWithResolvers<EvalDetachedCellSnapshot>;
|
|
15
|
-
state: EvalDetachedCellState
|
|
15
|
+
state: Exclude<EvalDetachedCellState, "detached">;
|
|
16
|
+
runStartedAtMs: number | undefined;
|
|
17
|
+
detached: boolean;
|
|
16
18
|
canDetach: boolean;
|
|
17
19
|
wasDetached: boolean;
|
|
18
20
|
kernel: EvalKernel | undefined;
|
|
@@ -47,12 +49,22 @@ export function createManagedCell(init: ManagedCellInit): ManagedCell {
|
|
|
47
49
|
// An explicit longer per-call timeout raises the deadline, mirroring bash keeping explicit timeouts.
|
|
48
50
|
const hardLimitSeconds = Math.max(init.defaultHardLimitSeconds, init.input.timeout ?? 0);
|
|
49
51
|
const runBudgetSeconds = init.input.timeout ?? init.defaultRunBudgetSeconds;
|
|
52
|
+
const deadlines = new CellDeadlines({
|
|
53
|
+
cellId: init.cellId,
|
|
54
|
+
hardLimitSeconds,
|
|
55
|
+
runBudgetSeconds,
|
|
56
|
+
onExpire: (expiry) => init.onExpire(init.cellId, expiry),
|
|
57
|
+
});
|
|
58
|
+
// Queue time never consumes execution budget; the submission-time hard limit remains armed.
|
|
59
|
+
deadlines.pause();
|
|
50
60
|
return {
|
|
51
61
|
cellId: init.cellId,
|
|
52
62
|
input: init.input,
|
|
53
63
|
spillPath: detachedNotificationSpillPath(init.artifactsDir, init.cellId),
|
|
54
64
|
startedAtMs: init.now(),
|
|
55
|
-
state: "
|
|
65
|
+
state: "queued",
|
|
66
|
+
runStartedAtMs: undefined,
|
|
67
|
+
detached: false,
|
|
56
68
|
canDetach: false,
|
|
57
69
|
wasDetached: false,
|
|
58
70
|
kernel: undefined,
|
|
@@ -62,12 +74,7 @@ export function createManagedCell(init: ManagedCellInit): ManagedCell {
|
|
|
62
74
|
liveResult: undefined,
|
|
63
75
|
terminalResult: undefined,
|
|
64
76
|
notificationQueued: false,
|
|
65
|
-
deadlines
|
|
66
|
-
cellId: init.cellId,
|
|
67
|
-
hardLimitSeconds,
|
|
68
|
-
runBudgetSeconds,
|
|
69
|
-
onExpire: (expiry) => init.onExpire(init.cellId, expiry),
|
|
70
|
-
}),
|
|
77
|
+
deadlines,
|
|
71
78
|
hardLimitSeconds,
|
|
72
79
|
runBudgetSeconds,
|
|
73
80
|
hardLimited: false,
|
|
@@ -25,13 +25,14 @@ import type {
|
|
|
25
25
|
EvalCellResult,
|
|
26
26
|
EvalInputSchema,
|
|
27
27
|
EvalLanguage,
|
|
28
|
+
EvalResultDetails,
|
|
28
29
|
EvalStatusEvent,
|
|
29
30
|
EvalToolDetails,
|
|
30
31
|
EvalToolInput,
|
|
31
32
|
EvalToolRequest,
|
|
32
33
|
} from "./types.ts";
|
|
33
34
|
|
|
34
|
-
type EvalToolDefinition = ToolDefinition<EvalInputSchema,
|
|
35
|
+
type EvalToolDefinition = ToolDefinition<EvalInputSchema, EvalResultDetails>;
|
|
35
36
|
type RenderContext = Parameters<NonNullable<EvalToolDefinition["renderCall"]>>[2];
|
|
36
37
|
type ResultRenderContext = Parameters<NonNullable<EvalToolDefinition["renderResult"]>>[3];
|
|
37
38
|
type CollapsibleKind = "code" | "output";
|
|
@@ -301,6 +302,8 @@ function cellPresentation(status: CellStatus, spinnerFrame: number | undefined):
|
|
|
301
302
|
switch (status) {
|
|
302
303
|
case "pending":
|
|
303
304
|
return { label: "pending", icon: "○", color: "muted" };
|
|
305
|
+
case "queued":
|
|
306
|
+
return { label: "queued", icon: "○", color: "muted" };
|
|
304
307
|
case "running":
|
|
305
308
|
return { label: "running", icon: spinner(spinnerFrame), color: "warning" };
|
|
306
309
|
case "detached":
|
|
@@ -337,6 +340,8 @@ function cellHeader(cell: EvalCellResult, environment: RenderEnvironment, badges
|
|
|
337
340
|
const presentation = cellPresentation(cell.status, environment.spinnerFrame);
|
|
338
341
|
const runtimeBadge = cell.runtime === undefined ? "" : ` (${formatRuntimeBadge(cell.language, cell.runtime)})`;
|
|
339
342
|
let header = `eval ${cell.language}${runtimeBadge} ${presentation.label} ${presentation.icon}`;
|
|
343
|
+
if (cell.queuedBehind !== undefined && cell.queuedBehind.length > 0)
|
|
344
|
+
header += ` · queued behind ${cell.queuedBehind.map(sanitizeTerminalLabel).join(", ")}`;
|
|
340
345
|
const throughputBadge = badges.throughput === undefined ? undefined : formatThroughputBadge(badges.throughput);
|
|
341
346
|
if (throughputBadge !== undefined) header += ` · ${throughputBadge}`;
|
|
342
347
|
const elapsedMs = badges.throughput?.wallDurationMs ?? cellElapsedMs(cell, environment);
|
|
@@ -706,7 +711,7 @@ function renderJsonOutputs(values: readonly unknown[], environment: RenderEnviro
|
|
|
706
711
|
|
|
707
712
|
function renderDetailedLines(
|
|
708
713
|
details: EvalToolDetails,
|
|
709
|
-
result: AgentToolResult<
|
|
714
|
+
result: AgentToolResult<EvalResultDetails>,
|
|
710
715
|
context: DetailedRenderContext,
|
|
711
716
|
): string[] {
|
|
712
717
|
const lines: string[] = [];
|
|
@@ -765,7 +770,7 @@ function renderDetailedLines(
|
|
|
765
770
|
return lines;
|
|
766
771
|
}
|
|
767
772
|
|
|
768
|
-
function textOutput(result: AgentToolResult<
|
|
773
|
+
function textOutput(result: AgentToolResult<EvalResultDetails>, showImageFallback: boolean): string {
|
|
769
774
|
const lines: string[] = [];
|
|
770
775
|
for (const part of result.content) {
|
|
771
776
|
if (part.type === "text") lines.push(part.text);
|
|
@@ -777,7 +782,7 @@ function textOutput(result: AgentToolResult<EvalToolDetails>, showImageFallback:
|
|
|
777
782
|
}
|
|
778
783
|
|
|
779
784
|
function isEvalRunInput(args: EvalToolRequest): args is EvalToolInput {
|
|
780
|
-
return args.action
|
|
785
|
+
return args.action === undefined || args.action === "run";
|
|
781
786
|
}
|
|
782
787
|
|
|
783
788
|
function toolCallRows(details: EvalToolDetails | undefined): ToolCallRow[] {
|
|
@@ -891,7 +896,8 @@ export function renderEvalCall(
|
|
|
891
896
|
return component;
|
|
892
897
|
}
|
|
893
898
|
if (!isEvalRunInput(args)) {
|
|
894
|
-
|
|
899
|
+
const title = args.action === "list" ? "eval list" : `eval ${args.action} ${args.cell_id}`;
|
|
900
|
+
component.setBlocks([{ kind: "text", text: style(theme, "toolTitle", title) }]);
|
|
895
901
|
return component;
|
|
896
902
|
}
|
|
897
903
|
if (theme === undefined && context.spinnerFrame === undefined) {
|
|
@@ -942,13 +948,21 @@ export function renderEvalCall(
|
|
|
942
948
|
}
|
|
943
949
|
|
|
944
950
|
export function renderEvalResult(
|
|
945
|
-
result: AgentToolResult<
|
|
951
|
+
result: AgentToolResult<EvalResultDetails>,
|
|
946
952
|
options: ToolRenderResultOptions,
|
|
947
953
|
theme: Theme | undefined,
|
|
948
954
|
context: ResultRenderContext,
|
|
949
955
|
): EvalRenderComponent {
|
|
950
956
|
const component = componentFor(context);
|
|
951
957
|
const details = result.details;
|
|
958
|
+
if (details && "action" in details) {
|
|
959
|
+
component.syncLiveTicker(false, context.invalidate);
|
|
960
|
+
component.setBlocks([
|
|
961
|
+
{ kind: "text", text: style(theme, "toolTitle", "eval list") },
|
|
962
|
+
{ kind: "text", text: style(theme, "toolOutput", textOutput(result, false)) },
|
|
963
|
+
]);
|
|
964
|
+
return component;
|
|
965
|
+
}
|
|
952
966
|
const expanded = options.expanded || context.expanded;
|
|
953
967
|
const imageProtocol = context.imageProtocol ?? null;
|
|
954
968
|
component.syncLiveTicker(hasLiveCell(details), context.invalidate);
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
type ExtensionKernelTools,
|
|
7
7
|
kernelToolsStorage,
|
|
8
8
|
} from "@code-yeongyu/senpi";
|
|
9
|
+
import type { KernelToHostMessage } from "../bridge/protocol.ts";
|
|
9
10
|
import { DEFAULT_FOREGROUND_WINDOW_SECONDS, defaultCodemodeSettings } from "../config/settings.ts";
|
|
10
11
|
import {
|
|
11
12
|
KERNEL_TOOLS_CAPABILITIES,
|
|
@@ -16,8 +17,9 @@ import { TIMEOUT_PAUSE_OP, TIMEOUT_RESUME_OP } from "../timeouts/bridge-timeout.
|
|
|
16
17
|
import { abortError, CellExecution, defaultTimeoutFactory } from "./cell-execution.ts";
|
|
17
18
|
import { CellHandler, type CellState } from "./cell-handler.ts";
|
|
18
19
|
import type { EvalDetachedCellManager } from "./detached-cell-manager.ts";
|
|
19
|
-
import { resultAfterDetach } from "./detached-eval-result.ts";
|
|
20
|
+
import { EvalBackgroundCapacityError, resultAfterDetach, resultForDetachedState } from "./detached-eval-result.ts";
|
|
20
21
|
import { buildEvalExecutionEventPayload, type EvalExecutionSettleOutcome } from "./eval-execution-event.ts";
|
|
22
|
+
import { EvalKernelResetRefusedError } from "./eval-kernel-reset-refused-error.ts";
|
|
21
23
|
import { evalTimeoutBehavior } from "./eval-request.ts";
|
|
22
24
|
import type { CreateEvalToolOptions, EvalCellInvocation } from "./eval-tool-options.ts";
|
|
23
25
|
import { describeTimeoutState } from "./interrupt-note.ts";
|
|
@@ -54,7 +56,7 @@ export async function runEvalCell(
|
|
|
54
56
|
phase: undefined,
|
|
55
57
|
error: undefined,
|
|
56
58
|
durationMs: 0,
|
|
57
|
-
status: "
|
|
59
|
+
status: "queued",
|
|
58
60
|
};
|
|
59
61
|
let detached = false;
|
|
60
62
|
let execution: CellExecution;
|
|
@@ -65,6 +67,24 @@ export async function runEvalCell(
|
|
|
65
67
|
execution.detach();
|
|
66
68
|
return true;
|
|
67
69
|
};
|
|
70
|
+
const cancelAtCapacity = (idleError: Error): void => {
|
|
71
|
+
const liveCells = cellManager.liveCells(undefined, { except: invocation.cellId });
|
|
72
|
+
if (
|
|
73
|
+
!cell.canDetach &&
|
|
74
|
+
liveCells.filter((live) => live.state === "detached").length < cellManager.maxDetachedCells
|
|
75
|
+
) {
|
|
76
|
+
execution.cancel(idleError);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
execution.cancel(
|
|
80
|
+
new EvalBackgroundCapacityError(
|
|
81
|
+
cellManager.maxDetachedCells,
|
|
82
|
+
invocation.cellId,
|
|
83
|
+
Date.now() - state.startedAt,
|
|
84
|
+
liveCells.map((live) => live.cellId),
|
|
85
|
+
),
|
|
86
|
+
);
|
|
87
|
+
};
|
|
68
88
|
execution = new CellExecution({
|
|
69
89
|
callerSignal: invocation.signal,
|
|
70
90
|
cellId: invocation.cellId,
|
|
@@ -74,7 +94,13 @@ export async function runEvalCell(
|
|
|
74
94
|
timeoutMs: detachAfterMs,
|
|
75
95
|
maxPauseGraceMs: foregroundWindowMs,
|
|
76
96
|
onTimeout: (error: Error) => {
|
|
77
|
-
if (
|
|
97
|
+
if (detach()) return;
|
|
98
|
+
const remainingMs = foregroundWindowMs - (Date.now() - state.startedAt);
|
|
99
|
+
if (remainingMs <= 0) cancelAtCapacity(error);
|
|
100
|
+
else
|
|
101
|
+
execution.rearmIdle(remainingMs, () => {
|
|
102
|
+
if (!detach()) cancelAtCapacity(error);
|
|
103
|
+
});
|
|
78
104
|
},
|
|
79
105
|
},
|
|
80
106
|
}
|
|
@@ -116,6 +142,7 @@ export async function runEvalCell(
|
|
|
116
142
|
state,
|
|
117
143
|
outcome,
|
|
118
144
|
completedAt: Date.now(),
|
|
145
|
+
queuedMs: Math.max(0, (cell.runStartedAtMs ?? Date.now()) - cell.startedAtMs),
|
|
119
146
|
detached,
|
|
120
147
|
}),
|
|
121
148
|
);
|
|
@@ -137,7 +164,12 @@ export async function runEvalCell(
|
|
|
137
164
|
finalized.then((result) => ({ kind: "result" as const, result })),
|
|
138
165
|
execution.detached.then(() => ({ kind: "detached" as const })),
|
|
139
166
|
]);
|
|
140
|
-
if (outcome.kind === "detached")
|
|
167
|
+
if (outcome.kind === "detached")
|
|
168
|
+
return resultAfterDetach(
|
|
169
|
+
cellManager.peek(invocation.cellId),
|
|
170
|
+
invocation.input,
|
|
171
|
+
cellManager.liveCells(undefined, { except: invocation.cellId }).length,
|
|
172
|
+
);
|
|
141
173
|
return outcome.result;
|
|
142
174
|
} finally {
|
|
143
175
|
steeringSignal?.removeEventListener("abort", onSteering);
|
|
@@ -157,30 +189,30 @@ async function executeCell(
|
|
|
157
189
|
): Promise<AgentToolResult<EvalToolDetails>> {
|
|
158
190
|
let handler: CellHandler | undefined;
|
|
159
191
|
try {
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (message.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
if (message.event.op === TIMEOUT_RESUME_OP) {
|
|
170
|
-
execution.resume();
|
|
171
|
-
cellManager.resume(cell);
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
192
|
+
const onMessage = (message: KernelToHostMessage): void => {
|
|
193
|
+
if (!state.active || handler === undefined) return;
|
|
194
|
+
if (message.type === "status") {
|
|
195
|
+
if (message.event.op === TIMEOUT_PAUSE_OP) {
|
|
196
|
+
execution.pause();
|
|
197
|
+
cellManager.pause(cell);
|
|
198
|
+
return;
|
|
174
199
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
200
|
+
if (message.event.op === TIMEOUT_RESUME_OP) {
|
|
201
|
+
execution.resume();
|
|
202
|
+
cellManager.resume(cell);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const pending = handler.handle(message);
|
|
207
|
+
void pending.catch((error: unknown) => execution.cancel(error));
|
|
208
|
+
};
|
|
209
|
+
const kernel = await execution.wait(options.kernelManager.getKernel(invocation.input.language, onMessage));
|
|
179
210
|
// Computed before the handler so the cell's capability can be entered per host tool call from the
|
|
180
211
|
// worker's message loop, which runs outside the `kernelToolsStorage.run` context below (#1754).
|
|
181
212
|
const kernelTools = jsKernelTools(kernel, invocation.input.language);
|
|
182
213
|
const runBound = async (): Promise<AgentToolResult<EvalToolDetails>> => {
|
|
183
|
-
|
|
214
|
+
const queue = kernel.queueSnapshot();
|
|
215
|
+
state.queuedBehind = [...(queue.activeCellId === null ? [] : [queue.activeCellId]), ...queue.queuedCellIds];
|
|
184
216
|
const activeHandler = new CellHandler(kernel, state, {
|
|
185
217
|
executeTool: options.executeTool,
|
|
186
218
|
...(options.listTools === undefined ? {} : { listTools: options.listTools }),
|
|
@@ -194,25 +226,57 @@ async function executeCell(
|
|
|
194
226
|
...(kernelTools === undefined ? {} : { kernelTools }),
|
|
195
227
|
});
|
|
196
228
|
handler = activeHandler;
|
|
197
|
-
cellManager.
|
|
229
|
+
cellManager.bindKernel(
|
|
198
230
|
cell,
|
|
199
231
|
kernel,
|
|
200
232
|
() => activeHandler.liveResult(),
|
|
201
233
|
(error) => execution.cancel(error),
|
|
202
234
|
);
|
|
235
|
+
if (invocation.input.reset) {
|
|
236
|
+
const liveCells = cellManager.liveCells(invocation.input.language, { except: invocation.cellId });
|
|
237
|
+
if (liveCells.length > 0)
|
|
238
|
+
throw new EvalKernelResetRefusedError(
|
|
239
|
+
invocation.input.language,
|
|
240
|
+
liveCells.map((live) => live.cellId),
|
|
241
|
+
);
|
|
242
|
+
}
|
|
203
243
|
// Includes a steer already queued at execute start or received while acquiring the kernel.
|
|
204
244
|
onReady();
|
|
205
245
|
if ("setContext" in options.kernelManager && typeof options.kernelManager.setContext === "function") {
|
|
206
246
|
options.kernelManager.setContext(bridgeContext);
|
|
207
247
|
}
|
|
208
248
|
if (invocation.input.reset) await execution.wait(kernel.reset());
|
|
209
|
-
|
|
249
|
+
execution.setKernel(kernel);
|
|
250
|
+
const result = await execution.wait(
|
|
251
|
+
kernel.run({
|
|
252
|
+
cellId: invocation.cellId,
|
|
253
|
+
code: invocation.input.code,
|
|
254
|
+
onMessage,
|
|
255
|
+
onStarted: () => {
|
|
256
|
+
cellManager.markRunning(cell);
|
|
257
|
+
state.runStartedAt = cell.runStartedAtMs;
|
|
258
|
+
state.status = "running";
|
|
259
|
+
state.queuedBehind = undefined;
|
|
260
|
+
state.onUpdate?.(activeHandler.liveResult());
|
|
261
|
+
},
|
|
262
|
+
}),
|
|
263
|
+
);
|
|
210
264
|
if (result.ok && state.pendingBridgeCalls.length > 0)
|
|
211
265
|
await execution.wait(Promise.all(state.pendingBridgeCalls));
|
|
212
266
|
return await handler.finalize(result);
|
|
213
267
|
};
|
|
214
268
|
return kernelTools ? await kernelToolsStorage.run(kernelTools, runBound) : await runBound();
|
|
215
269
|
} catch (error) {
|
|
270
|
+
if (error instanceof EvalBackgroundCapacityError) {
|
|
271
|
+
const final = handler
|
|
272
|
+
? await handler.finalizeCancellation(error)
|
|
273
|
+
: {
|
|
274
|
+
content: [{ type: "text" as const, text: error.message }],
|
|
275
|
+
details: cellManager.peek(invocation.cellId).result.details,
|
|
276
|
+
};
|
|
277
|
+
const result = resultForDetachedState(final, "cancelled", state.durationMs);
|
|
278
|
+
return { ...result, details: { ...result.details, isError: true, code: error.code } };
|
|
279
|
+
}
|
|
216
280
|
if (handler && error instanceof Error && error.name === "CodemodeSessionDisposedError")
|
|
217
281
|
return await handler.finalizeCancellation(error);
|
|
218
282
|
if (error instanceof Error && error.name === "TimeoutError") throw await describeTimeoutState(error, execution);
|
|
@@ -54,18 +54,25 @@ export interface EvalToolInput {
|
|
|
54
54
|
readonly reset?: boolean;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
export interface
|
|
58
|
-
readonly action: "
|
|
59
|
-
readonly cell_id: string;
|
|
57
|
+
export interface EvalListInput {
|
|
58
|
+
readonly action: "list";
|
|
60
59
|
}
|
|
61
60
|
|
|
61
|
+
export type EvalControlInput =
|
|
62
|
+
| EvalListInput
|
|
63
|
+
| {
|
|
64
|
+
readonly action: "peek" | "stop";
|
|
65
|
+
readonly cell_id: string;
|
|
66
|
+
};
|
|
67
|
+
|
|
62
68
|
export type EvalToolRequest = EvalToolInput | EvalControlInput;
|
|
63
69
|
|
|
64
70
|
function evalInputProperties<Language extends TSchema>(languageSchema: Language, deadlines: EvalDeadlineSeconds) {
|
|
65
71
|
return {
|
|
66
72
|
action: Type.Optional(
|
|
67
|
-
Type.Union([Type.Literal("run"), Type.Literal("peek"), Type.Literal("stop")], {
|
|
68
|
-
description:
|
|
73
|
+
Type.Union([Type.Literal("run"), Type.Literal("peek"), Type.Literal("stop"), Type.Literal("list")], {
|
|
74
|
+
description:
|
|
75
|
+
"Defaults to run. peek and stop require cell_id. list: live and recently settled cells across languages.",
|
|
69
76
|
}),
|
|
70
77
|
),
|
|
71
78
|
language: Type.Optional(languageSchema),
|
|
@@ -83,8 +90,12 @@ function evalInputProperties<Language extends TSchema>(languageSchema: Language,
|
|
|
83
90
|
description: onTimeoutFieldDescription(deadlines),
|
|
84
91
|
}),
|
|
85
92
|
),
|
|
86
|
-
reset: Type.Optional(
|
|
87
|
-
|
|
93
|
+
reset: Type.Optional(
|
|
94
|
+
Type.Boolean({
|
|
95
|
+
description: "Reset this language kernel before running; refused while that language has live cells.",
|
|
96
|
+
}),
|
|
97
|
+
),
|
|
98
|
+
cell_id: Type.Optional(Type.String({ minLength: 1, description: "Eval cell id for peek or stop." })),
|
|
88
99
|
};
|
|
89
100
|
}
|
|
90
101
|
|
|
@@ -108,7 +119,14 @@ export function createEvalInputSchema(
|
|
|
108
119
|
languages.length === 1
|
|
109
120
|
? Type.Union([Type.Literal(languages[0])])
|
|
110
121
|
: Type.Union(languages.map((item) => Type.Literal(item)));
|
|
111
|
-
return Type.Unsafe<EvalToolRequest>(
|
|
122
|
+
return Type.Unsafe<EvalToolRequest>(
|
|
123
|
+
Type.Object(evalInputProperties(languageSchema, deadlines), {
|
|
124
|
+
anyOf: [
|
|
125
|
+
{ properties: { action: { enum: ["run", "list"] } } },
|
|
126
|
+
{ properties: { action: { enum: ["peek", "stop"] } }, required: ["action", "cell_id"] },
|
|
127
|
+
],
|
|
128
|
+
}),
|
|
129
|
+
) as EvalInputSchema;
|
|
112
130
|
}
|
|
113
131
|
export type EvalKernelResult = Extract<KernelToHostMessage, { type: "result" }>;
|
|
114
132
|
export type EvalToolCallMessage = Extract<KernelToHostMessage, { type: "tool-call" }>;
|
|
@@ -117,6 +135,8 @@ export interface EvalKernelRunInput {
|
|
|
117
135
|
readonly cellId: string;
|
|
118
136
|
readonly code: string;
|
|
119
137
|
readonly timeoutMs?: number;
|
|
138
|
+
readonly onStarted?: () => void;
|
|
139
|
+
readonly onMessage?: (message: KernelToHostMessage) => void;
|
|
120
140
|
}
|
|
121
141
|
|
|
122
142
|
export interface KernelInterruptHandle {
|
|
@@ -128,7 +148,9 @@ export interface KernelInterruptHandle {
|
|
|
128
148
|
|
|
129
149
|
export interface EvalKernel {
|
|
130
150
|
run(input: EvalKernelRunInput): Promise<EvalKernelResult>;
|
|
131
|
-
|
|
151
|
+
cancelQueued(cellId: string, reason: string): boolean;
|
|
152
|
+
interrupt(reason?: string, cellId?: string): Promise<KernelInterruptHandle>;
|
|
153
|
+
queueSnapshot(): { activeCellId: string | null; queuedCellIds: readonly string[] };
|
|
132
154
|
deliverToolReply(message: Extract<HostToKernelMessage, { type: "tool-reply" }>): void;
|
|
133
155
|
reset(): Promise<void>;
|
|
134
156
|
close(): Promise<void>;
|
|
@@ -182,7 +204,8 @@ export type EvalCellResult = {
|
|
|
182
204
|
readonly language: EvalLanguage;
|
|
183
205
|
readonly output: string;
|
|
184
206
|
readonly runtime?: EvalRuntimeInfo;
|
|
185
|
-
readonly status: "pending" | "running" | "detached" | "complete" | "error" | "cancelled";
|
|
207
|
+
readonly status: "pending" | "queued" | "running" | "detached" | "complete" | "error" | "cancelled";
|
|
208
|
+
readonly queuedBehind?: readonly string[];
|
|
186
209
|
readonly exitCode?: number;
|
|
187
210
|
readonly durationMs?: number;
|
|
188
211
|
/** Epoch ms when the cell started; lets renderers tick elapsed time between update events. */
|
|
@@ -191,6 +214,22 @@ export type EvalCellResult = {
|
|
|
191
214
|
readonly hasMarkdown?: boolean;
|
|
192
215
|
};
|
|
193
216
|
|
|
217
|
+
export interface EvalListedCell {
|
|
218
|
+
readonly cellId: string;
|
|
219
|
+
readonly language: EvalLanguage;
|
|
220
|
+
readonly state: "queued" | "running" | "detached" | "completed" | "failed" | "cancelled";
|
|
221
|
+
readonly startedAtMs: number;
|
|
222
|
+
readonly queuedBehind?: readonly string[];
|
|
223
|
+
readonly summary?: string;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export interface EvalListDetails {
|
|
227
|
+
readonly action: "list";
|
|
228
|
+
readonly cells: readonly EvalListedCell[];
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export type EvalResultDetails = EvalToolDetails | EvalListDetails;
|
|
232
|
+
|
|
194
233
|
export interface EvalToolDetails {
|
|
195
234
|
readonly language: EvalLanguage;
|
|
196
235
|
readonly languages?: readonly EvalLanguage[];
|
|
@@ -204,6 +243,8 @@ export interface EvalToolDetails {
|
|
|
204
243
|
readonly toolCalls: readonly EvalToolCallSummary[];
|
|
205
244
|
readonly truncated: boolean;
|
|
206
245
|
readonly isError?: boolean;
|
|
246
|
+
/** Machine-readable reason for a tool-boundary cancellation. */
|
|
247
|
+
readonly code?: string;
|
|
207
248
|
readonly phase?: string;
|
|
208
249
|
readonly cells?: readonly EvalCellResult[];
|
|
209
250
|
readonly statusEvents?: readonly EvalStatusEvent[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@earendil-works/pi-agent-core",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.22",
|
|
4
4
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@earendil-works/chord": "0.85.1",
|
|
60
|
-
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.
|
|
61
|
-
"@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.9.
|
|
60
|
+
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.22",
|
|
61
|
+
"@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.9.22",
|
|
62
62
|
"diff": "9.0.0",
|
|
63
63
|
"ignore": "7.0.9",
|
|
64
64
|
"typebox": "1.3.34",
|
|
@@ -458,7 +458,7 @@ Built-in providers resolve these env vars (Node.js; in browsers pass `apiKey` ex
|
|
|
458
458
|
| Moonshot AI / Moonshot AI (China) | `MOONSHOT_API_KEY` |
|
|
459
459
|
| Hugging Face | `HF_TOKEN` |
|
|
460
460
|
| OpenCode Zen / OpenCode Go | `OPENCODE_API_KEY` |
|
|
461
|
-
| Kimi For Coding | `KIMI_API_KEY` |
|
|
461
|
+
| Kimi For Coding | `KIMI_API_KEY` (+ `KIMI_CODE_REGION`) |
|
|
462
462
|
| Qwen Token Plan (existing catalog) | `QWEN_TOKEN_PLAN_API_KEY` |
|
|
463
463
|
| Qwen Token Plan (Individual) | `QWEN_TOKEN_PLAN_API_KEY` |
|
|
464
464
|
| Qwen Token Plan (China) | `QWEN_TOKEN_PLAN_CN_API_KEY` |
|