@code-yeongyu/senpi 2026.9.15 → 2026.9.16-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +73 -0
- package/README.md +1 -1
- package/dist/core/agent-session.d.ts +28 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +111 -13
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +4 -2
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/stream-watchdog.d.ts +56 -2
- package/dist/core/compaction/stream-watchdog.d.ts.map +1 -1
- package/dist/core/compaction/stream-watchdog.js +93 -15
- package/dist/core/compaction/stream-watchdog.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.d.ts +6 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js +17 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts +4 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js +31 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts +2 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js +16 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.js +19 -8
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js +2 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +13 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +66 -2
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +16 -10
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative-summary.js +4 -2
- package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +8 -1
- package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.js +31 -7
- package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/transient-failure.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/transient-failure.js +6 -3
- package/dist/core/extensions/builtin/compaction/transient-failure.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/index.js +25 -8
- package/dist/core/extensions/builtin/config-reload/index.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-engine.d.ts +4 -5
- package/dist/core/extensions/builtin/config-reload/watch-engine.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-engine.js +14 -18
- package/dist/core/extensions/builtin/config-reload/watch-engine.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-event-source.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-event-source.js +32 -9
- package/dist/core/extensions/builtin/config-reload/watch-event-source.js.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/catalog-refresh.d.ts +23 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/catalog-refresh.d.ts.map +1 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/catalog-refresh.js +48 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/catalog-refresh.js.map +1 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/environment.d.ts +13 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/environment.d.ts.map +1 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/environment.js +24 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/environment.js.map +1 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/executable.d.ts +1 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/executable.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/executable.js +7 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/executable.js.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/index.d.ts +2 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/index.js +11 -9
- package/dist/core/extensions/builtin/cursor-cli-oauth/index.js.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/models-probe.d.ts +18 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/models-probe.d.ts.map +1 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/models-probe.js +61 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/models-probe.js.map +1 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/models.d.ts +4 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/models.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/models.js +1 -44
- package/dist/core/extensions/builtin/cursor-cli-oauth/models.js.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/oauth-login.d.ts +22 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/oauth-login.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/oauth-login.js +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/oauth-login.js.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/transport.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/transport.js +2 -13
- package/dist/core/extensions/builtin/cursor-cli-oauth/transport.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-file-digest.d.ts +3 -0
- package/dist/core/extensions/builtin/terminal/monitor-file-digest.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-file-digest.js +25 -0
- package/dist/core/extensions/builtin/terminal/monitor-file-digest.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-file-watch.d.ts +9 -0
- package/dist/core/extensions/builtin/terminal/monitor-file-watch.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-file-watch.js +33 -0
- package/dist/core/extensions/builtin/terminal/monitor-file-watch.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-line-buffer.d.ts +6 -0
- package/dist/core/extensions/builtin/terminal/monitor-line-buffer.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-line-buffer.js +22 -0
- package/dist/core/extensions/builtin/terminal/monitor-line-buffer.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-registry.js +14 -35
- package/dist/core/extensions/builtin/terminal/monitor-registry.js.map +1 -1
- package/dist/core/extensions/kernel-tools-context.d.ts +13 -0
- package/dist/core/extensions/kernel-tools-context.d.ts.map +1 -0
- package/dist/core/extensions/kernel-tools-context.js +3 -0
- package/dist/core/extensions/kernel-tools-context.js.map +1 -0
- package/dist/core/extensions/runner.d.ts +19 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +103 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +21 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybindings.d.ts +5 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +1 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +9 -17
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/retry-fallback/settings.d.ts +3 -0
- package/dist/core/retry-fallback/settings.d.ts.map +1 -1
- package/dist/core/retry-fallback/settings.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +30 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +92 -5
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-resident-store.d.ts +33 -7
- package/dist/core/session-resident-store.d.ts.map +1 -1
- package/dist/core/session-resident-store.js +163 -14
- package/dist/core/session-resident-store.js.map +1 -1
- package/dist/core/session-write-reservation.d.ts +6 -0
- package/dist/core/session-write-reservation.d.ts.map +1 -1
- package/dist/core/session-write-reservation.js +19 -0
- package/dist/core/session-write-reservation.js.map +1 -1
- package/dist/core/settings-manager.d.ts +35 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +62 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +2 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +4 -3
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/read.d.ts +3 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +16 -2
- package/dist/core/tools/read.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.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 +12 -5
- package/dist/modes/interactive/components/assistant-render-descriptors.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts +2 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +5 -0
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +19 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +69 -17
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tips/catalog/session-tips.js +1 -1
- package/dist/modes/interactive/tips/catalog/session-tips.js.map +1 -1
- package/dist/modes/interactive/working-status.d.ts +3 -2
- package/dist/modes/interactive/working-status.d.ts.map +1 -1
- package/dist/modes/interactive/working-status.js +17 -4
- package/dist/modes/interactive/working-status.js.map +1 -1
- package/dist/modes/print-mode.d.ts +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +5 -1
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
- package/dist/modes/rpc/host-watchdog.js +5 -24
- package/dist/modes/rpc/host-watchdog.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +3 -8
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +3 -0
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-worker-client.d.ts +3 -0
- package/dist/modes/rpc/session-worker-client.d.ts.map +1 -1
- package/dist/modes/rpc/session-worker-client.js +17 -6
- package/dist/modes/rpc/session-worker-client.js.map +1 -1
- package/dist/modes/rpc/shutdown.d.ts +3 -0
- package/dist/modes/rpc/shutdown.d.ts.map +1 -0
- package/dist/modes/rpc/shutdown.js +17 -0
- package/dist/modes/rpc/shutdown.js.map +1 -0
- package/docs/extensions.md +5 -2
- package/docs/keybindings.md +1 -0
- package/docs/session-format.md +1 -1
- package/docs/sessions.md +3 -3
- package/docs/settings.md +31 -1
- package/docs/usage.md +1 -1
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +50 -0
- package/node_modules/@code-yeongyu/senpi-codemode/README.md +24 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridge/http-server.ts +7 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridge/kernel-tools-protocol.ts +85 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridge/protocol.ts +6 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridges/agent-bridge.ts +30 -11
- package/node_modules/@code-yeongyu/senpi-codemode/src/extension/session-manager.ts +11 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +10 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/prelude.jl +46 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/runner.jl +1 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/context-manager.ts +58 -10
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-contract.ts +12 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-context.d.ts +13 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-context.js +7 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-define.d.ts +10 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-define.js +12 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-errors.js +22 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-errors.ts +26 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-host.ts +134 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-naming.js +28 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-parse.d.ts +5 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-parse.js +255 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-pump.js +105 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-registry.d.ts +27 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-registry.js +127 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-schema.js +69 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-types.ts +42 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/prelude.ts +2 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-core.js +26 -3
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-runtime.js +20 -8
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-slot.ts +6 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-startup.ts +9 -7
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/workpool.js +37 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/kernel-tools-unavailable.ts +5 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/kernel.ts +13 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/prelude.py +57 -3
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/prelude.rb +13 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/workpool.rb +38 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-kernel.ts +13 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-queue.ts +9 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt-template.ts +4 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/cell-handler.ts +31 -3
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-manager.ts +36 -71
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/image-resize.ts +52 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/image.ts +37 -72
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/managed-cell.ts +78 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +30 -5
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/run-eval-cell.ts +52 -30
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/terminal-snapshot-store.ts +35 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/tool-result-marshal.ts +23 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/types.ts +2 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +30 -3
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +5 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +2 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js +51 -12
- package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/read.d.ts +3 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/read.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/read.js +18 -3
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/read.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/brace-scanner.d.ts +4 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/brace-scanner.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/brace-scanner.js +268 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/brace-scanner.js.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/header-protection.d.ts +18 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/header-protection.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/header-protection.js +69 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/header-protection.js.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/index.d.ts +27 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/index.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/index.js +118 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/index.js.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-context.d.ts +21 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-context.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-context.js +24 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-context.js.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-spans.d.ts +12 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-spans.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-spans.js +92 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-spans.js.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/types.d.ts +47 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/types.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/types.js +8 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/types.js.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/segmented-read-view.d.ts +52 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/segmented-read-view.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/segmented-read-view.js +155 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/segmented-read-view.js.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts +4 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/index.js +3 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/stream-throughput-watchdog.d.ts +101 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/stream-throughput-watchdog.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/stream-throughput-watchdog.js +178 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/stream-throughput-watchdog.js.map +1 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +9 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- 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/alibaba-token-plan.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.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/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan.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/utils/empty-response-errors.d.ts +15 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/empty-response-errors.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/empty-response-errors.js +15 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/empty-response-errors.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts +24 -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 +92 -0
- 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
|
@@ -140,13 +140,22 @@ def __senpi_bridge_request(path, payload)
|
|
|
140
140
|
return body["value"] if body.is_a?(Hash) && body["ok"] == true
|
|
141
141
|
|
|
142
142
|
error = body.is_a?(Hash) ? body["error"] : body
|
|
143
|
-
raise(error.is_a?(Hash) ? error["message"].to_s : error.to_s)
|
|
143
|
+
raise SenpiBridgeError.new(error.is_a?(Hash) ? error["message"].to_s : error.to_s, error.is_a?(Hash) ? error["code"] : nil)
|
|
144
144
|
end
|
|
145
145
|
|
|
146
146
|
def __senpi_call_tool(name, args)
|
|
147
147
|
__senpi_bridge_request("/call", { "callId" => "rb-#{Process.pid}-#{rand(1_000_000)}", "toolName" => name, "args" => args })
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
+
class SenpiBridgeError < StandardError
|
|
151
|
+
attr_reader :code
|
|
152
|
+
|
|
153
|
+
def initialize(message, code = nil)
|
|
154
|
+
super(message)
|
|
155
|
+
@code = code
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
150
159
|
class SenpiToolCallable
|
|
151
160
|
def initialize(name)
|
|
152
161
|
@name = name
|
|
@@ -177,6 +186,8 @@ def tool
|
|
|
177
186
|
$__senpi_tool_proxy ||= SenpiToolProxy.new
|
|
178
187
|
end
|
|
179
188
|
|
|
189
|
+
require_relative "workpool"
|
|
190
|
+
|
|
180
191
|
def completion(prompt, model: "default", system: nil, schema: nil, **kwargs)
|
|
181
192
|
options = { "model" => model }.merge(kwargs.transform_keys(&:to_s))
|
|
182
193
|
options["system"] = system unless system.nil?
|
|
@@ -213,7 +224,7 @@ def agent(prompt, agent: "task", model: nil, label: nil, schema: nil, isolated:
|
|
|
213
224
|
text_value = record.fetch("text", response)
|
|
214
225
|
result = schema.nil? ? text_value : record.key?("data") ? record["data"] : JSON.parse(text_value.to_s)
|
|
215
226
|
return result unless handle
|
|
216
|
-
{ "text" => text_value, "output" => text_value, "handle" => record["handle"] || (record["id"] && "agent://#{record["id"]}"), "id" => record["id"], "agent" => record.fetch("agent", agent) }.tap do |node|
|
|
227
|
+
{ "text" => text_value, "output" => text_value, "handle" => record["handle"] || (record["id"] && "agent://#{record["id"]}"), "id" => record["id"], "run_epoch" => record["run_epoch"], "agent" => record.fetch("agent", agent) }.tap do |node|
|
|
217
228
|
node["data"] = result unless schema.nil?
|
|
218
229
|
end
|
|
219
230
|
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Only an opaque host identity is retained; all work remains engine-owned.
|
|
2
|
+
def __senpi_workpool_call(args)
|
|
3
|
+
tool.workpool(args)
|
|
4
|
+
rescue SenpiBridgeError => error
|
|
5
|
+
raise SenpiBridgeError.new("No active host workpool tool", "workpool_unavailable") if ["unknown_tool", "inactive_tool"].include?(error.code)
|
|
6
|
+
raise
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class SenpiWorkpool
|
|
10
|
+
attr_reader :pool_id
|
|
11
|
+
|
|
12
|
+
def initialize(pool_id)
|
|
13
|
+
@pool_id = pool_id
|
|
14
|
+
freeze
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def push(items)
|
|
18
|
+
__senpi_workpool_call({ "op" => "push", "pool_id" => @pool_id, "items" => items })
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
[:close, :inspect, :cancel].each do |op|
|
|
22
|
+
define_method(op) { __senpi_workpool_call({ "op" => op.to_s, "pool_id" => @pool_id }) }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def workpool(agent, name, mode: nil)
|
|
27
|
+
args = { "op" => "create", "agent" => agent, "name" => name }
|
|
28
|
+
args["mode"] = mode unless mode.nil?
|
|
29
|
+
result = __senpi_workpool_call(args)
|
|
30
|
+
details = result["details"]
|
|
31
|
+
if details.is_a?(Hash)
|
|
32
|
+
error = details["error"]
|
|
33
|
+
raise SenpiBridgeError.new(error["message"], error["code"]) if error.is_a?(Hash)
|
|
34
|
+
pool_id = details["pool_id"]
|
|
35
|
+
return SenpiWorkpool.new(pool_id) if !result["hasError"] && pool_id.is_a?(String) && /\Awp_[0-9a-f]{32}\z/.match?(pool_id)
|
|
36
|
+
end
|
|
37
|
+
raise SenpiBridgeError.new("Host did not return a workpool identity", "workpool_unavailable")
|
|
38
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { HostToKernelMessage, KernelToHostMessage } from "../../bridge/protocol.ts";
|
|
2
2
|
import { decodeBridgeFrame, encodeBridgeFrame, isKernelToHostMessage } from "../../bridge/protocol.ts";
|
|
3
3
|
import type { KernelInterruptHandle } from "../../tool/types.ts";
|
|
4
|
+
import { rejectKernelToolsUnavailable } from "../kernel-tools-unavailable.ts";
|
|
4
5
|
import { applySessionEnvironment } from "../session-env.ts";
|
|
5
6
|
import type { KernelResult, KernelRunInput, SubprocessKernelOptions, ToolCallMessage } from "./subprocess-contract.ts";
|
|
6
7
|
import { type SubprocessLike, SubprocessProcess, type SubprocessSpawn, spawnSubprocess } from "./subprocess-process.ts";
|
|
@@ -69,6 +70,18 @@ export class SubprocessKernel {
|
|
|
69
70
|
return { stateRetained: Promise.resolve(false) };
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
listKernelToolNames(): readonly string[] {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
describeKernelTools(_names: readonly string[]): Promise<never> {
|
|
78
|
+
return rejectKernelToolsUnavailable();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
invokeKernelTool(_request: unknown, _signal?: AbortSignal): Promise<never> {
|
|
82
|
+
return rejectKernelToolsUnavailable();
|
|
83
|
+
}
|
|
84
|
+
|
|
72
85
|
nextToolCall(): Promise<ToolCallMessage> {
|
|
73
86
|
return this.runs.nextToolCall();
|
|
74
87
|
}
|
|
@@ -2,6 +2,9 @@ import type { KernelToHostMessage } from "../../bridge/protocol.ts";
|
|
|
2
2
|
import type { KernelResult, KernelRunInput, ToolCallMessage } from "./subprocess-contract.ts";
|
|
3
3
|
import { createPendingRun, failureResult, type PendingRun, settlePendingRun } from "./subprocess-run.ts";
|
|
4
4
|
|
|
5
|
+
// Same bound as the JS kernel's pull-API fallback queue (context-manager.ts); clears happen at run teardown.
|
|
6
|
+
const MAX_PENDING_TOOL_CALLS = 256;
|
|
7
|
+
|
|
5
8
|
export class SubprocessRunQueue {
|
|
6
9
|
readonly #queue: PendingRun[] = [];
|
|
7
10
|
readonly #pendingCalls: ToolCallMessage[] = [];
|
|
@@ -59,7 +62,10 @@ export class SubprocessRunQueue {
|
|
|
59
62
|
pushToolCall(message: ToolCallMessage): void {
|
|
60
63
|
const waiter = this.#callWaiters.shift();
|
|
61
64
|
if (waiter) waiter(message);
|
|
62
|
-
else
|
|
65
|
+
else {
|
|
66
|
+
this.#pendingCalls.push(message);
|
|
67
|
+
if (this.#pendingCalls.length > MAX_PENDING_TOOL_CALLS) this.#pendingCalls.shift();
|
|
68
|
+
}
|
|
63
69
|
}
|
|
64
70
|
|
|
65
71
|
handleMessage(
|
|
@@ -90,6 +96,8 @@ export class SubprocessRunQueue {
|
|
|
90
96
|
case "ready":
|
|
91
97
|
case "init-failed":
|
|
92
98
|
case "closed":
|
|
99
|
+
case "kernel-tool-describe-reply":
|
|
100
|
+
case "kernel-tool-invoke-reply":
|
|
93
101
|
onMessage?.(message);
|
|
94
102
|
return false;
|
|
95
103
|
default: {
|
|
@@ -57,8 +57,10 @@ tool_schema(name?) → dict
|
|
|
57
57
|
completion(prompt, model?="default", system?=None, schema?=None) → str | dict
|
|
58
58
|
Oneshot, stateless. \`model\`: \`"smol"\` fast | \`"default"\` session | \`"slow"\` most capable. \`schema\` (JSON-Schema) → parsed structured output.
|
|
59
59
|
{{#if spawns}}agent(prompt, agent?="{{spawnDefaultAgent}}", model?=None, label?=None, schema?=None, handle?=False) → str | dict
|
|
60
|
-
Run a subagent → final output. \`agent\` picks a discovered agent. \`schema\` as in completion(). \`handle\` → workflow node { text, output, handle: \`agent://<id>\`, id, agent } (parsed under \`data\` with \`schema\`).
|
|
61
|
-
{{/if}}
|
|
60
|
+
Run a subagent → final output. \`agent\` picks a discovered agent. \`schema\` as in completion(). \`handle\` → workflow node { text, output, handle: \`agent://<id>\`, id, run_epoch, agent } (parsed under \`data\` with \`schema\`).
|
|
61
|
+
{{/if}}workpool(agent, name, mode?) → { pool_id, push(items), close(), inspect(), cancel() }
|
|
62
|
+
Thin host-tool adapter; agent is a plain-data spec. The host owns scheduling and keyed yields; explicitly close for automatic aggregate delivery. Requires the host workpool tool; omitted mode uses its default.
|
|
63
|
+
parallel(thunks) → list
|
|
62
64
|
Thunks through a bounded pool (as wide as a \`task\` batch), input order kept; a throwing thunk propagates.
|
|
63
65
|
pipeline(items, ...stages) → list
|
|
64
66
|
Map items through one-arg stages with a barrier between stages; each stage receives the previous stage's result.
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type AgentToolResult,
|
|
3
|
+
type ExtensionContext,
|
|
4
|
+
kernelToolsStorage,
|
|
5
|
+
sanitizeTerminalLabel,
|
|
6
|
+
} from "@code-yeongyu/senpi";
|
|
2
7
|
import type { KernelToHostMessage } from "../bridge/protocol.ts";
|
|
3
8
|
import { RESERVED_SCHEMA_TOOL } from "../bridge/reserved.ts";
|
|
4
9
|
import type { AgentExecuteTool } from "../bridges/agent-bridge.ts";
|
|
@@ -8,6 +13,7 @@ import { appendSchemaHint } from "../bridges/schema-hint.ts";
|
|
|
8
13
|
import type { CompletionRequest, CompletionResult } from "../completion/handler.ts";
|
|
9
14
|
import { handleCompletionToolCall } from "../completion/tool-bridge.ts";
|
|
10
15
|
import type { ResolvedCodemodeSettings } from "../config/settings.ts";
|
|
16
|
+
import type { KernelToolsCapability } from "../kernels/js/kernel-tools-types.ts";
|
|
11
17
|
import {
|
|
12
18
|
boundToolCallArgs,
|
|
13
19
|
capCodePoints,
|
|
@@ -39,6 +45,8 @@ export interface CellBridgeRuntime {
|
|
|
39
45
|
readonly ctx: ExtensionContext;
|
|
40
46
|
readonly artifactPath?: string;
|
|
41
47
|
readonly imageResizer?: EvalImageResizer;
|
|
48
|
+
/** This cell's live kernel-tool capability; only a JS kernel has one (#1754). */
|
|
49
|
+
readonly kernelTools?: KernelToolsCapability;
|
|
42
50
|
}
|
|
43
51
|
|
|
44
52
|
export class CellHandler {
|
|
@@ -81,7 +89,7 @@ export class CellHandler {
|
|
|
81
89
|
this.#resultBuilder.display(message);
|
|
82
90
|
return;
|
|
83
91
|
case "tool-call": {
|
|
84
|
-
const pending = this.#
|
|
92
|
+
const pending = this.#dispatchToolCall(message);
|
|
85
93
|
this.#state.pendingBridgeCalls.push(pending);
|
|
86
94
|
await pending;
|
|
87
95
|
return;
|
|
@@ -90,6 +98,8 @@ export class CellHandler {
|
|
|
90
98
|
case "init-failed":
|
|
91
99
|
case "result":
|
|
92
100
|
case "closed":
|
|
101
|
+
case "kernel-tool-describe-reply":
|
|
102
|
+
case "kernel-tool-invoke-reply":
|
|
93
103
|
return;
|
|
94
104
|
default:
|
|
95
105
|
throw new TypeError(`Unhandled kernel message: ${String(message)}`);
|
|
@@ -112,6 +122,19 @@ export class CellHandler {
|
|
|
112
122
|
return this.#resultBuilder.liveResult();
|
|
113
123
|
}
|
|
114
124
|
|
|
125
|
+
/**
|
|
126
|
+
* The worker's message loop fires outside the async context `run-eval-cell.ts` enters around the
|
|
127
|
+
* awaited run chain, so the capability has to be entered here — around the whole dispatch, including
|
|
128
|
+
* the reserved agent()/output() bridges where a host task tool resolves the parent's kernel tools —
|
|
129
|
+
* for exactly the duration of each host tool call this cell makes (#1754). Without a capability
|
|
130
|
+
* (py/rb/jl) the store stays empty and `ctx.kernelTools` remains undefined.
|
|
131
|
+
*/
|
|
132
|
+
async #dispatchToolCall(message: Extract<KernelToHostMessage, { type: "tool-call" }>): Promise<void> {
|
|
133
|
+
const kernelTools = this.#runtime.kernelTools;
|
|
134
|
+
if (kernelTools === undefined) return await this.#handleToolCall(message);
|
|
135
|
+
return await kernelToolsStorage.run(kernelTools, async () => await this.#handleToolCall(message));
|
|
136
|
+
}
|
|
137
|
+
|
|
115
138
|
async #handleToolCall(message: Extract<KernelToHostMessage, { type: "tool-call" }>): Promise<void> {
|
|
116
139
|
const startedAt = Date.now();
|
|
117
140
|
const metric = createToolCallMetric(message.toolName, startedAt);
|
|
@@ -223,7 +246,12 @@ export class CellHandler {
|
|
|
223
246
|
type: "tool-reply",
|
|
224
247
|
callId: message.callId,
|
|
225
248
|
ok: false,
|
|
226
|
-
error: {
|
|
249
|
+
error: {
|
|
250
|
+
message: text,
|
|
251
|
+
...(error instanceof Error && "code" in error && typeof error.code === "string"
|
|
252
|
+
? { code: error.code }
|
|
253
|
+
: {}),
|
|
254
|
+
},
|
|
227
255
|
});
|
|
228
256
|
}
|
|
229
257
|
this.#resultBuilder.emitUpdate(false);
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import type { AgentToolResult } from "@code-yeongyu/senpi";
|
|
2
2
|
import { DEFAULT_HARD_LIMIT_SECONDS, DEFAULT_RUN_BUDGET_SECONDS } from "../config/settings.ts";
|
|
3
3
|
import type { WakeSourceState } from "../extension/wake-source-state.ts";
|
|
4
|
-
import {
|
|
4
|
+
import type { CellDeadlineExpiry } from "./cell-deadlines.ts";
|
|
5
5
|
import type {
|
|
6
6
|
EvalDetachedCellManagerOptions,
|
|
7
7
|
EvalDetachedCellSnapshot,
|
|
8
|
-
EvalDetachedCellState,
|
|
9
8
|
EvalDetachedCellStatusEntry,
|
|
10
9
|
} from "./detached-cell-contract.ts";
|
|
11
|
-
import { detachedNotificationSpillPath } from "./detached-cell-notification.ts";
|
|
12
10
|
import { currentDetachedResult, detachedErrorResult, snapshotDetachedCell } from "./detached-cell-snapshot.ts";
|
|
13
11
|
import {
|
|
14
12
|
activeDetachedCellReuseError,
|
|
@@ -17,6 +15,8 @@ import {
|
|
|
17
15
|
} from "./detached-cell-state.ts";
|
|
18
16
|
import { detachedStatusEntries, detachedWakeSourceState } from "./detached-cell-status.ts";
|
|
19
17
|
import { DetachedNotificationQueue } from "./detached-notification-queue.ts";
|
|
18
|
+
import { createManagedCell, type LiveResultProvider, type ManagedCell } from "./managed-cell.ts";
|
|
19
|
+
import { TerminalSnapshotStore } from "./terminal-snapshot-store.ts";
|
|
20
20
|
import type { EvalKernel, EvalLanguage, EvalToolDetails, EvalToolInput } from "./types.ts";
|
|
21
21
|
|
|
22
22
|
export type {
|
|
@@ -28,40 +28,13 @@ export type {
|
|
|
28
28
|
EvalDetachedCellStatusEntry,
|
|
29
29
|
} from "./detached-cell-contract.ts";
|
|
30
30
|
|
|
31
|
-
type LiveResultProvider = () => AgentToolResult<EvalToolDetails>;
|
|
32
|
-
|
|
33
|
-
type ManagedCell = {
|
|
34
|
-
readonly cellId: string;
|
|
35
|
-
readonly input: EvalToolInput;
|
|
36
|
-
readonly spillPath: string | undefined;
|
|
37
|
-
readonly startedAtMs: number;
|
|
38
|
-
readonly terminal: PromiseWithResolvers<EvalDetachedCellSnapshot>;
|
|
39
|
-
state: EvalDetachedCellState;
|
|
40
|
-
canDetach: boolean;
|
|
41
|
-
wasDetached: boolean;
|
|
42
|
-
kernel: EvalKernel | undefined;
|
|
43
|
-
stateRetained: boolean | undefined;
|
|
44
|
-
interruptNote: string | undefined;
|
|
45
|
-
/** Holds the completion notification until the interrupt has reported whether kernel state survived. */
|
|
46
|
-
interruptOutcome: PromiseWithResolvers<void> | undefined;
|
|
47
|
-
liveResult: LiveResultProvider | undefined;
|
|
48
|
-
terminalResult: AgentToolResult<EvalToolDetails> | undefined;
|
|
49
|
-
notificationQueued: boolean;
|
|
50
|
-
readonly deadlines: CellDeadlines;
|
|
51
|
-
readonly hardLimitSeconds: number;
|
|
52
|
-
readonly runBudgetSeconds: number;
|
|
53
|
-
hardLimited: boolean;
|
|
54
|
-
runBudgetExhausted: boolean;
|
|
55
|
-
/** Foreground killer: the still-awaited CellExecution owns interrupting and rejecting its own call; bound from creation so a deadline firing during kernel boot still ends it. */
|
|
56
|
-
onKill: ((error: Error) => void) | undefined;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
31
|
export class EvalDetachedCellManager {
|
|
60
32
|
readonly #artifactsDir: string | undefined;
|
|
61
33
|
readonly #onStatusChange: ((entries: readonly EvalDetachedCellStatusEntry[]) => void) | undefined;
|
|
62
34
|
readonly #onWakeSourceState: ((state: WakeSourceState) => void) | undefined;
|
|
63
35
|
readonly #cells = new Map<string, ManagedCell>();
|
|
64
36
|
readonly #detachedByLanguage = new Map<EvalLanguage, ManagedCell>();
|
|
37
|
+
readonly #terminalSnapshots = new TerminalSnapshotStore();
|
|
65
38
|
readonly #notificationQueue: DetachedNotificationQueue;
|
|
66
39
|
readonly #now: () => number;
|
|
67
40
|
readonly #hardLimitSeconds: number;
|
|
@@ -83,40 +56,20 @@ export class EvalDetachedCellManager {
|
|
|
83
56
|
if (detachedCellIsActive(existing.state)) throw activeDetachedCellReuseError(existing);
|
|
84
57
|
this.#cells.delete(cellId);
|
|
85
58
|
}
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
const runBudgetSeconds = input.timeout ?? this.#runBudgetSeconds;
|
|
89
|
-
const cell: ManagedCell = {
|
|
59
|
+
this.#terminalSnapshots.delete(cellId);
|
|
60
|
+
const cell = createManagedCell({
|
|
90
61
|
cellId,
|
|
91
62
|
input,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
wasDetached: false,
|
|
97
|
-
kernel: undefined,
|
|
98
|
-
stateRetained: undefined,
|
|
99
|
-
interruptNote: undefined,
|
|
100
|
-
interruptOutcome: undefined,
|
|
101
|
-
liveResult: undefined,
|
|
102
|
-
terminalResult: undefined,
|
|
103
|
-
notificationQueued: false,
|
|
104
|
-
deadlines: new CellDeadlines({
|
|
105
|
-
cellId,
|
|
106
|
-
hardLimitSeconds,
|
|
107
|
-
runBudgetSeconds,
|
|
108
|
-
onExpire: (expiry) => {
|
|
109
|
-
const managed = this.#cells.get(cellId);
|
|
110
|
-
if (managed !== undefined) void this.#expireDeadline(managed, expiry);
|
|
111
|
-
},
|
|
112
|
-
}),
|
|
113
|
-
hardLimitSeconds,
|
|
114
|
-
runBudgetSeconds,
|
|
115
|
-
hardLimited: false,
|
|
116
|
-
runBudgetExhausted: false,
|
|
63
|
+
artifactsDir: this.#artifactsDir,
|
|
64
|
+
now: this.#now,
|
|
65
|
+
defaultHardLimitSeconds: this.#hardLimitSeconds,
|
|
66
|
+
defaultRunBudgetSeconds: this.#runBudgetSeconds,
|
|
117
67
|
onKill,
|
|
118
|
-
|
|
119
|
-
|
|
68
|
+
onExpire: (expiredId, expiry) => {
|
|
69
|
+
const managed = this.#cells.get(expiredId);
|
|
70
|
+
if (managed !== undefined) void this.#expireDeadline(managed, expiry);
|
|
71
|
+
},
|
|
72
|
+
});
|
|
120
73
|
this.#cells.set(cellId, cell);
|
|
121
74
|
return cell;
|
|
122
75
|
}
|
|
@@ -166,13 +119,15 @@ export class EvalDetachedCellManager {
|
|
|
166
119
|
}
|
|
167
120
|
|
|
168
121
|
async stop(cellId: string, reason = "Stopped detached eval cell"): Promise<EvalDetachedCellSnapshot> {
|
|
169
|
-
const
|
|
170
|
-
if (
|
|
171
|
-
|
|
122
|
+
const live = this.#cells.get(cellId);
|
|
123
|
+
if (live === undefined) return this.#terminal(cellId);
|
|
124
|
+
if (live.state === "detached") await this.#cancel(live, reason);
|
|
125
|
+
return this.#snapshot(live);
|
|
172
126
|
}
|
|
173
127
|
|
|
174
128
|
peek(cellId: string): EvalDetachedCellSnapshot {
|
|
175
|
-
|
|
129
|
+
const live = this.#cells.get(cellId);
|
|
130
|
+
return live === undefined ? this.#terminal(cellId) : this.#snapshot(live);
|
|
176
131
|
}
|
|
177
132
|
|
|
178
133
|
busyFor(language: EvalLanguage): EvalDetachedCellSnapshot | undefined {
|
|
@@ -181,7 +136,8 @@ export class EvalDetachedCellManager {
|
|
|
181
136
|
}
|
|
182
137
|
|
|
183
138
|
async waitForTerminal(cellId: string): Promise<EvalDetachedCellSnapshot> {
|
|
184
|
-
|
|
139
|
+
const live = this.#cells.get(cellId);
|
|
140
|
+
return live === undefined ? this.#terminal(cellId) : await live.terminal.promise;
|
|
185
141
|
}
|
|
186
142
|
|
|
187
143
|
async dispose(): Promise<void> {
|
|
@@ -191,6 +147,8 @@ export class EvalDetachedCellManager {
|
|
|
191
147
|
);
|
|
192
148
|
if (detached.length === 0) this.#emitWakeSourceState([]);
|
|
193
149
|
await this.#notificationQueue.flush();
|
|
150
|
+
this.#cells.clear();
|
|
151
|
+
this.#terminalSnapshots.clear();
|
|
194
152
|
}
|
|
195
153
|
|
|
196
154
|
async flushNotifications(): Promise<void> {
|
|
@@ -213,6 +171,8 @@ export class EvalDetachedCellManager {
|
|
|
213
171
|
cell.terminalResult = result;
|
|
214
172
|
cell.liveResult = undefined;
|
|
215
173
|
cell.terminal.resolve(this.#snapshot(cell));
|
|
174
|
+
this.#cells.delete(cell.cellId);
|
|
175
|
+
this.#refreshTerminalSnapshot(cell);
|
|
216
176
|
if (cell.wasDetached) {
|
|
217
177
|
if (this.#detachedByLanguage.get(cell.input.language) === cell)
|
|
218
178
|
this.#detachedByLanguage.delete(cell.input.language);
|
|
@@ -257,9 +217,14 @@ export class EvalDetachedCellManager {
|
|
|
257
217
|
cell.stateRetained = await handle.stateRetained;
|
|
258
218
|
} finally {
|
|
259
219
|
outcome.resolve();
|
|
220
|
+
this.#refreshTerminalSnapshot(cell);
|
|
260
221
|
}
|
|
261
222
|
}
|
|
262
223
|
|
|
224
|
+
#refreshTerminalSnapshot(cell: ManagedCell): void {
|
|
225
|
+
if (!this.#cells.has(cell.cellId)) this.#terminalSnapshots.remember(this.#snapshot(cell));
|
|
226
|
+
}
|
|
227
|
+
|
|
263
228
|
#emitStatus(): void {
|
|
264
229
|
const liveCells = [...this.#detachedByLanguage.values()];
|
|
265
230
|
this.#onStatusChange?.(detachedStatusEntries(liveCells));
|
|
@@ -274,9 +239,9 @@ export class EvalDetachedCellManager {
|
|
|
274
239
|
return snapshotDetachedCell(cell, this.#now());
|
|
275
240
|
}
|
|
276
241
|
|
|
277
|
-
#
|
|
278
|
-
const
|
|
279
|
-
if (
|
|
280
|
-
return
|
|
242
|
+
#terminal(cellId: string): EvalDetachedCellSnapshot {
|
|
243
|
+
const snapshot = this.#terminalSnapshots.get(cellId);
|
|
244
|
+
if (snapshot === undefined) throw new Error(`Unknown detached eval cell "${cellId}"`);
|
|
245
|
+
return snapshot;
|
|
281
246
|
}
|
|
282
247
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ExtensionContext } from "@code-yeongyu/senpi";
|
|
2
|
+
import { convertToPng, formatDimensionNote, resizeImage } from "@code-yeongyu/senpi";
|
|
3
|
+
|
|
4
|
+
export interface EvalImageContent {
|
|
5
|
+
readonly type: "image";
|
|
6
|
+
readonly data: string;
|
|
7
|
+
readonly mimeType: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface EvalImageResizeResult {
|
|
11
|
+
readonly image: EvalImageContent;
|
|
12
|
+
readonly dimensionNote?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type EvalImageResizer = (
|
|
16
|
+
image: EvalImageContent,
|
|
17
|
+
model: ExtensionContext["model"],
|
|
18
|
+
) => Promise<EvalImageResizeResult>;
|
|
19
|
+
|
|
20
|
+
type WebpModel = { readonly provider: string; readonly api: string } | undefined;
|
|
21
|
+
|
|
22
|
+
export function webpExclusionForModel(model: WebpModel): true | undefined {
|
|
23
|
+
if (model === undefined) return undefined;
|
|
24
|
+
return model.provider === "ollama" ||
|
|
25
|
+
model.provider === "ollama-cloud" ||
|
|
26
|
+
model.provider === "llama.cpp" ||
|
|
27
|
+
model.provider === "lm-studio" ||
|
|
28
|
+
model.provider === "local-server" ||
|
|
29
|
+
model.api === "ollama-chat"
|
|
30
|
+
? true
|
|
31
|
+
: undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const resizeEvalImage: EvalImageResizer = async (image, model) => {
|
|
35
|
+
const excludeWebP = webpExclusionForModel(model);
|
|
36
|
+
const forceWebpConversion = excludeWebP === true && image.mimeType === "image/webp";
|
|
37
|
+
const resized = await resizeImage(
|
|
38
|
+
Buffer.from(image.data, "base64"),
|
|
39
|
+
image.mimeType,
|
|
40
|
+
forceWebpConversion ? { maxBytes: Buffer.byteLength(image.data, "utf8") } : undefined,
|
|
41
|
+
);
|
|
42
|
+
let output: EvalImageContent =
|
|
43
|
+
resized === null ? image : { type: "image", data: resized.data, mimeType: resized.mimeType };
|
|
44
|
+
if (excludeWebP === true && output.mimeType === "image/webp") {
|
|
45
|
+
const converted = await convertToPng(output.data, output.mimeType);
|
|
46
|
+
if (converted === null)
|
|
47
|
+
throw new TypeError(`Unable to convert ${output.mimeType} display output for the active model`);
|
|
48
|
+
output = { type: "image", data: converted.data, mimeType: converted.mimeType };
|
|
49
|
+
}
|
|
50
|
+
const dimensionNote = resized === null ? undefined : formatDimensionNote(resized);
|
|
51
|
+
return { image: output, ...(dimensionNote === undefined ? {} : { dimensionNote }) };
|
|
52
|
+
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { writeFile } from "node:fs/promises";
|
|
2
|
-
import type {
|
|
3
|
-
import { convertToPng, formatDimensionNote, resizeImage } from "@code-yeongyu/senpi";
|
|
2
|
+
import type { ExtensionContext } from "@code-yeongyu/senpi";
|
|
4
3
|
import type { KernelToHostMessage } from "../bridge/protocol.ts";
|
|
5
4
|
import type { TruncationMeta } from "../output/output-meta.ts";
|
|
6
5
|
import {
|
|
@@ -12,24 +11,24 @@ import {
|
|
|
12
11
|
TailBuffer,
|
|
13
12
|
truncateTail,
|
|
14
13
|
} from "../output/streaming-output.ts";
|
|
14
|
+
import { type EvalImageContent, type EvalImageResizer, resizeEvalImage } from "./image-resize.ts";
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
16
|
+
export {
|
|
17
|
+
type EvalImageContent,
|
|
18
|
+
type EvalImageResizeResult,
|
|
19
|
+
type EvalImageResizer,
|
|
20
|
+
resizeEvalImage,
|
|
21
|
+
webpExclusionForModel,
|
|
22
|
+
} from "./image-resize.ts";
|
|
23
|
+
export { marshalToolResult, toolResultIsError } from "./tool-result-marshal.ts";
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
readonly image: EvalImageContent;
|
|
26
|
-
readonly dimensionNote?: string;
|
|
27
|
-
}
|
|
25
|
+
const MAX_DISPLAY_TEXT_BYTES = 8_000;
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
// Per-cell display caps: display payloads are retained for the whole result lifetime, so an unbounded
|
|
28
|
+
// burst pins base64 originals plus resized copies on the session heap (#1695).
|
|
29
|
+
const MAX_DISPLAY_IMAGES_PER_CELL = 8;
|
|
30
|
+
const MAX_DISPLAY_IMAGE_BYTES_PER_CELL = 24 * 1024 * 1024;
|
|
31
|
+
const MAX_JSON_OUTPUTS_PER_CELL = 64;
|
|
33
32
|
|
|
34
33
|
export interface EvalOutputOptions {
|
|
35
34
|
readonly artifactPath?: string;
|
|
@@ -51,7 +50,6 @@ export interface EvalOutputResult {
|
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
type DisplayMessage = Extract<KernelToHostMessage, { type: "display" }>;
|
|
54
|
-
type WebpModel = { readonly provider: string; readonly api: string } | undefined;
|
|
55
53
|
|
|
56
54
|
class DisplayPayloadError extends Error {
|
|
57
55
|
readonly name = "DisplayPayloadError";
|
|
@@ -69,6 +67,9 @@ export class EvalOutputCollector {
|
|
|
69
67
|
readonly #displayImages: EvalImageContent[] = [];
|
|
70
68
|
readonly #images: EvalImageContent[] = [];
|
|
71
69
|
readonly #jsonOutputs: unknown[] = [];
|
|
70
|
+
#displayImageBytes = 0;
|
|
71
|
+
#displayImagesElided = 0;
|
|
72
|
+
#jsonOutputsElided = 0;
|
|
72
73
|
#hasMarkdown = false;
|
|
73
74
|
#imagesProcessed = false;
|
|
74
75
|
|
|
@@ -92,11 +93,23 @@ export class EvalOutputCollector {
|
|
|
92
93
|
|
|
93
94
|
display(message: DisplayMessage): void {
|
|
94
95
|
if (message.mimeType.startsWith("image/")) {
|
|
96
|
+
if (
|
|
97
|
+
this.#displayImages.length >= MAX_DISPLAY_IMAGES_PER_CELL ||
|
|
98
|
+
this.#displayImageBytes + message.dataBase64.length > MAX_DISPLAY_IMAGE_BYTES_PER_CELL
|
|
99
|
+
) {
|
|
100
|
+
this.#displayImagesElided++;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
95
103
|
this.#displayImages.push({ type: "image", mimeType: message.mimeType, data: message.dataBase64 });
|
|
104
|
+
this.#displayImageBytes += message.dataBase64.length;
|
|
96
105
|
return;
|
|
97
106
|
}
|
|
98
107
|
const text = Buffer.from(message.dataBase64, "base64").toString("utf8");
|
|
99
108
|
if (message.mimeType === "application/json") {
|
|
109
|
+
if (this.#jsonOutputs.length >= MAX_JSON_OUTPUTS_PER_CELL) {
|
|
110
|
+
this.#jsonOutputsElided++;
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
100
113
|
let value: unknown;
|
|
101
114
|
try {
|
|
102
115
|
value = JSON.parse(text);
|
|
@@ -118,6 +131,12 @@ export class EvalOutputCollector {
|
|
|
118
131
|
|
|
119
132
|
async finish(): Promise<EvalOutputResult> {
|
|
120
133
|
await this.#processImages();
|
|
134
|
+
const elided = this.#displayImagesElided + this.#jsonOutputsElided;
|
|
135
|
+
if (elided > 0) {
|
|
136
|
+
this.#sink.push(
|
|
137
|
+
`[${this.#displayImagesElided} display image(s) and ${this.#jsonOutputsElided} JSON output(s) elided beyond per-cell caps]\n`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
121
140
|
const summary = await this.#finalSummary();
|
|
122
141
|
const meta = truncationMetaFromSummary(summary, this.#options.maxColumns);
|
|
123
142
|
const notice = summary.artifactId === undefined ? undefined : artifactNotice(summary.artifactId);
|
|
@@ -171,38 +190,6 @@ export class EvalOutputCollector {
|
|
|
171
190
|
}
|
|
172
191
|
}
|
|
173
192
|
|
|
174
|
-
export function webpExclusionForModel(model: WebpModel): true | undefined {
|
|
175
|
-
if (model === undefined) return undefined;
|
|
176
|
-
return model.provider === "ollama" ||
|
|
177
|
-
model.provider === "ollama-cloud" ||
|
|
178
|
-
model.provider === "llama.cpp" ||
|
|
179
|
-
model.provider === "lm-studio" ||
|
|
180
|
-
model.provider === "local-server" ||
|
|
181
|
-
model.api === "ollama-chat"
|
|
182
|
-
? true
|
|
183
|
-
: undefined;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export const resizeEvalImage: EvalImageResizer = async (image, model) => {
|
|
187
|
-
const excludeWebP = webpExclusionForModel(model);
|
|
188
|
-
const forceWebpConversion = excludeWebP === true && image.mimeType === "image/webp";
|
|
189
|
-
const resized = await resizeImage(
|
|
190
|
-
Buffer.from(image.data, "base64"),
|
|
191
|
-
image.mimeType,
|
|
192
|
-
forceWebpConversion ? { maxBytes: Buffer.byteLength(image.data, "utf8") } : undefined,
|
|
193
|
-
);
|
|
194
|
-
let output: EvalImageContent =
|
|
195
|
-
resized === null ? image : { type: "image", data: resized.data, mimeType: resized.mimeType };
|
|
196
|
-
if (excludeWebP === true && output.mimeType === "image/webp") {
|
|
197
|
-
const converted = await convertToPng(output.data, output.mimeType);
|
|
198
|
-
if (converted === null)
|
|
199
|
-
throw new TypeError(`Unable to convert ${output.mimeType} display output for the active model`);
|
|
200
|
-
output = { type: "image", data: converted.data, mimeType: converted.mimeType };
|
|
201
|
-
}
|
|
202
|
-
const dimensionNote = resized === null ? undefined : formatDimensionNote(resized);
|
|
203
|
-
return { image: output, ...(dimensionNote === undefined ? {} : { dimensionNote }) };
|
|
204
|
-
};
|
|
205
|
-
|
|
206
193
|
function formatDisplayJson(value: unknown): string {
|
|
207
194
|
let text: string;
|
|
208
195
|
try {
|
|
@@ -259,25 +246,3 @@ function truncationMetaFromSummary(summary: OutputSummary, maxColumns: number):
|
|
|
259
246
|
...artifact,
|
|
260
247
|
};
|
|
261
248
|
}
|
|
262
|
-
|
|
263
|
-
export function marshalToolResult(result: AgentToolResult<unknown>) {
|
|
264
|
-
const texts = result.content.filter((part) => part.type === "text").map((part) => part.text);
|
|
265
|
-
const images = result.content
|
|
266
|
-
.filter((part) => part.type === "image")
|
|
267
|
-
.map((part) => ({ mimeType: part.mimeType, dataBase64: part.data }));
|
|
268
|
-
const details =
|
|
269
|
-
typeof result.details === "object" &&
|
|
270
|
-
result.details !== null &&
|
|
271
|
-
!Array.isArray(result.details) &&
|
|
272
|
-
Object.keys(result.details).length === 0
|
|
273
|
-
? undefined
|
|
274
|
-
: result.details;
|
|
275
|
-
const hasError = toolResultIsError(result);
|
|
276
|
-
const text = texts.join("\n");
|
|
277
|
-
return images.length === 0 && details === undefined && !hasError ? { text } : { text, details, images, hasError };
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
export function toolResultIsError(result: AgentToolResult<unknown>): boolean {
|
|
281
|
-
const details = result.details;
|
|
282
|
-
return typeof details === "object" && details !== null && "isError" in details && details.isError === true;
|
|
283
|
-
}
|