@code-yeongyu/senpi 2026.8.28 → 2026.8.30-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 +196 -0
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +4 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +2 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +50 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +330 -29
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +1 -0
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +3 -0
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +155 -37
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/compaction-execution.d.ts +14 -0
- package/dist/core/compaction/compaction-execution.d.ts.map +1 -0
- package/dist/core/compaction/compaction-execution.js +121 -0
- package/dist/core/compaction/compaction-execution.js.map +1 -0
- package/dist/core/compaction/compaction-settings.d.ts +17 -0
- package/dist/core/compaction/compaction-settings.d.ts.map +1 -0
- package/dist/core/compaction/compaction-settings.js +17 -0
- package/dist/core/compaction/compaction-settings.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +13 -26
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +7 -136
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/ideal-compaction-settings.d.ts +9 -0
- package/dist/core/compaction/ideal-compaction-settings.d.ts.map +1 -0
- package/dist/core/compaction/ideal-compaction-settings.js +7 -0
- package/dist/core/compaction/ideal-compaction-settings.js.map +1 -0
- package/dist/core/compaction-settings-access.d.ts +19 -0
- package/dist/core/compaction-settings-access.d.ts.map +1 -0
- package/dist/core/compaction-settings-access.js +10 -0
- package/dist/core/compaction-settings-access.js.map +1 -0
- package/dist/core/compaction-settings-resolver.d.ts +22 -0
- package/dist/core/compaction-settings-resolver.d.ts.map +1 -0
- package/dist/core/compaction-settings-resolver.js +46 -0
- package/dist/core/compaction-settings-resolver.js.map +1 -0
- package/dist/core/credential-accounts.d.ts.map +1 -1
- package/dist/core/credential-accounts.js +45 -21
- package/dist/core/credential-accounts.js.map +1 -1
- package/dist/core/credential-pool/classify.d.ts +6 -1
- package/dist/core/credential-pool/classify.d.ts.map +1 -1
- package/dist/core/credential-pool/classify.js +22 -5
- package/dist/core/credential-pool/classify.js.map +1 -1
- package/dist/core/credential-pool/env-slots.d.ts.map +1 -1
- package/dist/core/credential-pool/env-slots.js +2 -0
- package/dist/core/credential-pool/env-slots.js.map +1 -1
- package/dist/core/credential-pool/failover.d.ts +8 -0
- package/dist/core/credential-pool/failover.d.ts.map +1 -1
- package/dist/core/credential-pool/failover.js +24 -6
- package/dist/core/credential-pool/failover.js.map +1 -1
- package/dist/core/credential-pool/rotation-stream.d.ts +13 -2
- package/dist/core/credential-pool/rotation-stream.d.ts.map +1 -1
- package/dist/core/credential-pool/rotation-stream.js +97 -10
- package/dist/core/credential-pool/rotation-stream.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts +17 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.js +28 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +8 -2
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +163 -48
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts +17 -0
- package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/emergency-prune.js +64 -0
- package/dist/core/extensions/builtin/compaction/emergency-prune.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts +27 -0
- package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/extension-wiring.js +84 -0
- package/dist/core/extensions/builtin/compaction/extension-wiring.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/idle.d.ts +1 -0
- package/dist/core/extensions/builtin/compaction/idle.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/idle.js +13 -2
- package/dist/core/extensions/builtin/compaction/idle.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +121 -147
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.js +2 -0
- package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/model-selection.d.ts +14 -0
- package/dist/core/extensions/builtin/compaction/model-selection.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/model-selection.js +37 -0
- package/dist/core/extensions/builtin/compaction/model-selection.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts +9 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js +2 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +3 -6
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/orchestration.d.ts +56 -0
- package/dist/core/extensions/builtin/compaction/orchestration.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/orchestration.js +136 -0
- package/dist/core/extensions/builtin/compaction/orchestration.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/policy.d.ts +5 -2
- package/dist/core/extensions/builtin/compaction/policy.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/policy.js +43 -26
- package/dist/core/extensions/builtin/compaction/policy.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/retained-message-safety.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/retained-message-safety.js +31 -8
- package/dist/core/extensions/builtin/compaction/retained-message-safety.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts +8 -0
- package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculation-lead.js +17 -0
- package/dist/core/extensions/builtin/compaction/speculation-lead.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative-job.d.ts +22 -0
- package/dist/core/extensions/builtin/compaction/speculative-job.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative-job.js +16 -0
- package/dist/core/extensions/builtin/compaction/speculative-job.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts +22 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.js +131 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +8 -13
- package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.js +7 -196
- package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts +18 -0
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.js +18 -0
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.d.ts +36 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.js +92 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.js.map +1 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/stream.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/stream.js +8 -28
- package/dist/core/extensions/builtin/cursor-cli-oauth/stream.js.map +1 -1
- package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/index.js +7 -0
- package/dist/core/extensions/builtin/goal/index.js.map +1 -1
- package/dist/core/extensions/builtin/permission-system/external-dir.d.ts.map +1 -1
- package/dist/core/extensions/builtin/permission-system/external-dir.js +15 -5
- package/dist/core/extensions/builtin/permission-system/external-dir.js.map +1 -1
- package/dist/core/extensions/builtin/permission-system/parsers.d.ts.map +1 -1
- package/dist/core/extensions/builtin/permission-system/parsers.js +16 -1
- package/dist/core/extensions/builtin/permission-system/parsers.js.map +1 -1
- package/dist/core/extensions/builtin/service-tier.d.ts.map +1 -1
- package/dist/core/extensions/builtin/service-tier.js +13 -0
- package/dist/core/extensions/builtin/service-tier.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/extension.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/extension.js +4 -2
- package/dist/core/extensions/builtin/terminal/extension.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/manager.d.ts +5 -0
- package/dist/core/extensions/builtin/terminal/manager.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/manager.js +31 -3
- package/dist/core/extensions/builtin/terminal/manager.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-permission.d.ts +8 -0
- package/dist/core/extensions/builtin/terminal/monitor-permission.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-permission.js +16 -0
- package/dist/core/extensions/builtin/terminal/monitor-permission.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts +13 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-registry.js +403 -3
- package/dist/core/extensions/builtin/terminal/monitor-registry.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/session-bundle.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/session-bundle.js +1 -0
- package/dist/core/extensions/builtin/terminal/session-bundle.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/kill-bash.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/kill-bash.js +5 -2
- package/dist/core/extensions/builtin/terminal/tools/kill-bash.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts +4 -0
- package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/monitor.js +40 -2
- package/dist/core/extensions/builtin/terminal/tools/monitor.js.map +1 -1
- package/dist/core/model-config-schema.d.ts +4 -4
- package/dist/core/model-resolver.js +2 -2
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +2 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +74 -37
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/retry-fallback/chains.d.ts +23 -1
- package/dist/core/retry-fallback/chains.d.ts.map +1 -1
- package/dist/core/retry-fallback/chains.js +59 -3
- package/dist/core/retry-fallback/chains.js.map +1 -1
- package/dist/core/retry-fallback/controller.d.ts.map +1 -1
- package/dist/core/retry-fallback/controller.js +9 -2
- package/dist/core/retry-fallback/controller.js.map +1 -1
- package/dist/core/retry-fallback/settings.d.ts.map +1 -1
- package/dist/core/retry-fallback/settings.js +9 -0
- package/dist/core/retry-fallback/settings.js.map +1 -1
- package/dist/core/retry-fallback/validate.js +1 -1
- package/dist/core/retry-fallback/validate.js.map +1 -1
- package/dist/core/sdk.js +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +9 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +40 -0
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +15 -85
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +15 -17
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-public-types.d.ts +11 -0
- package/dist/core/settings-public-types.d.ts.map +1 -0
- package/dist/core/settings-public-types.js +2 -0
- package/dist/core/settings-public-types.js.map +1 -0
- package/dist/core/settings-shapes.d.ts +36 -0
- package/dist/core/settings-shapes.d.ts.map +1 -0
- package/dist/core/settings-shapes.js +2 -0
- package/dist/core/settings-shapes.js.map +1 -0
- package/dist/core/shared-host-policy.d.ts +6 -0
- package/dist/core/shared-host-policy.d.ts.map +1 -0
- package/dist/core/shared-host-policy.js +7 -0
- package/dist/core/shared-host-policy.js.map +1 -0
- package/dist/core/terminal-settings.d.ts +22 -0
- package/dist/core/terminal-settings.d.ts.map +1 -0
- package/dist/core/terminal-settings.js +2 -0
- package/dist/core/terminal-settings.js.map +1 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +97 -15
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -0
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +8 -0
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +76 -34
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/main.d.ts +7 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +27 -6
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/favorite-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/favorite-models-selector.js +2 -2
- package/dist/modes/interactive/components/favorite-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +7 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +34 -8
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/grok/chrome.d.ts +2 -0
- package/dist/modes/interactive/grok/chrome.d.ts.map +1 -1
- package/dist/modes/interactive/grok/chrome.js.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts +121 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.js +606 -45
- package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +7 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +390 -239
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/connection-handler.d.ts +8 -1
- package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
- package/dist/modes/rpc/connection-handler.js +268 -63
- package/dist/modes/rpc/connection-handler.js.map +1 -1
- package/dist/modes/rpc/host-ensure.d.ts +19 -0
- package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
- package/dist/modes/rpc/host-ensure.js +79 -15
- package/dist/modes/rpc/host-ensure.js.map +1 -1
- package/dist/modes/rpc/host-lifecycle.d.ts +29 -0
- package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
- package/dist/modes/rpc/host-lifecycle.js +96 -25
- package/dist/modes/rpc/host-lifecycle.js.map +1 -1
- package/dist/modes/rpc/host-watchdog.d.ts +2 -0
- package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
- package/dist/modes/rpc/host-watchdog.js +23 -12
- package/dist/modes/rpc/host-watchdog.js.map +1 -1
- package/dist/modes/rpc/multi-session-host.js +20 -8
- package/dist/modes/rpc/multi-session-host.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +91 -16
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +131 -37
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-input-validation.d.ts +1 -0
- package/dist/modes/rpc/rpc-input-validation.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-input-validation.js +66 -0
- package/dist/modes/rpc/rpc-input-validation.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +3 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +3 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +248 -3
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-binding.d.ts +1 -0
- package/dist/modes/rpc/session-binding.d.ts.map +1 -1
- package/dist/modes/rpc/session-binding.js +21 -1
- package/dist/modes/rpc/session-binding.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts +22 -0
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +148 -16
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-event-writer.d.ts +4 -0
- package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-writer.js +58 -7
- package/dist/modes/rpc/session-event-writer.js.map +1 -1
- package/dist/modes/rpc/session-extension-ui-requests.d.ts +1 -0
- package/dist/modes/rpc/session-extension-ui-requests.d.ts.map +1 -1
- package/dist/modes/rpc/session-extension-ui-requests.js +5 -0
- package/dist/modes/rpc/session-extension-ui-requests.js.map +1 -1
- package/dist/modes/rpc/session-registry.d.ts +17 -2
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +67 -4
- package/dist/modes/rpc/session-registry.js.map +1 -1
- package/dist/modes/rpc/socket-event-fanout.d.ts +22 -0
- package/dist/modes/rpc/socket-event-fanout.d.ts.map +1 -0
- package/dist/modes/rpc/socket-event-fanout.js +84 -0
- package/dist/modes/rpc/socket-event-fanout.js.map +1 -0
- package/docs/rpc.md +55 -2
- package/docs/settings.md +34 -0
- package/docs/windows.md +2 -0
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +74 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-indirect-eval.js +139 -90
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +4 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +6 -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/harness/env/nodejs.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js +40 -20
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts +3 -3
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.d.ts +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.js +28 -9
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +67 -38
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.d.ts +20 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js +443 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts +7 -0
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +5 -0
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/mux.d.ts +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/mux.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/mux.js +2 -2
- package/node_modules/@earendil-works/pi-tui/dist/mux.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js +19 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { rm } from "node:fs/promises";
|
|
3
|
+
import { executeBashWithOperations } from "../../core/bash-executor.js";
|
|
4
|
+
import { SessionManager } from "../../core/session-manager.js";
|
|
5
|
+
import { SettingsManager } from "../../core/settings-manager.js";
|
|
1
6
|
import { ensureHost } from "../rpc/host-ensure.js";
|
|
2
7
|
import { RpcClient } from "../rpc/rpc-client.js";
|
|
3
8
|
export const INTERACTIVE_HOST_FALLBACK_WARNING = "Warning: shared interactive host unavailable; continuing locally";
|
|
@@ -23,7 +28,15 @@ export async function createInteractiveHostRuntime(localRuntime, options) {
|
|
|
23
28
|
modelId: localRuntime.session.model?.id,
|
|
24
29
|
thinkingLevel: localRuntime.session.thinkingLevel,
|
|
25
30
|
});
|
|
26
|
-
const remoteSession = createRemoteSessionProxy(localRuntime.session, client, opened.state, options.onWarning);
|
|
31
|
+
const remoteSession = createRemoteSessionProxy(localRuntime.session, localRuntime.services.agentDir, client, opened.state, options.onWarning);
|
|
32
|
+
if (opened.state.isBashRunning && !opened.attached) {
|
|
33
|
+
// Only a newly opened session can have an execution orphaned by a
|
|
34
|
+
// previous connection. An attach is an observer of the same live runtime;
|
|
35
|
+
// aborting it would cancel work owned by the surviving attachment.
|
|
36
|
+
await client.abortBash().catch(() => { });
|
|
37
|
+
}
|
|
38
|
+
if (opened.attached)
|
|
39
|
+
await remoteSession.refresh();
|
|
27
40
|
return new RemoteInteractiveRuntime(localRuntime, remoteSession, client);
|
|
28
41
|
}
|
|
29
42
|
catch (cause) {
|
|
@@ -36,25 +49,25 @@ export async function createInteractiveHostRuntime(localRuntime, options) {
|
|
|
36
49
|
return localRuntime;
|
|
37
50
|
}
|
|
38
51
|
}
|
|
39
|
-
class RemoteInteractiveRuntime {
|
|
52
|
+
export class RemoteInteractiveRuntime {
|
|
40
53
|
#local;
|
|
41
|
-
#
|
|
54
|
+
#remoteSession;
|
|
42
55
|
#client;
|
|
43
56
|
#rebindSession;
|
|
44
57
|
#beforeSessionInvalidate;
|
|
45
|
-
constructor(local,
|
|
58
|
+
constructor(local, remoteSession, client) {
|
|
46
59
|
this.#local = local;
|
|
47
|
-
this.#
|
|
60
|
+
this.#remoteSession = remoteSession;
|
|
48
61
|
this.#client = client;
|
|
49
62
|
}
|
|
50
63
|
get session() {
|
|
51
|
-
return this.#session;
|
|
64
|
+
return this.#remoteSession.session;
|
|
52
65
|
}
|
|
53
66
|
get services() {
|
|
54
67
|
return this.#local.services;
|
|
55
68
|
}
|
|
56
69
|
get cwd() {
|
|
57
|
-
return this.#
|
|
70
|
+
return this.#remoteSession.session.sessionManager.getCwd();
|
|
58
71
|
}
|
|
59
72
|
get diagnostics() {
|
|
60
73
|
return this.#local.diagnostics;
|
|
@@ -71,37 +84,104 @@ class RemoteInteractiveRuntime {
|
|
|
71
84
|
setRebindSession(callback) {
|
|
72
85
|
this.#rebindSession = callback;
|
|
73
86
|
}
|
|
87
|
+
setHostUiHandler(callback) {
|
|
88
|
+
this.#remoteSession.setHostUiHandler(callback);
|
|
89
|
+
}
|
|
74
90
|
async dispose() {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
91
|
+
const errors = [];
|
|
92
|
+
for (const cleanup of [
|
|
93
|
+
() => this.#remoteSession.abortLocalBash(),
|
|
94
|
+
() => this.#client.closeSession(),
|
|
95
|
+
() => this.#client.stop(),
|
|
96
|
+
() => this.#local.dispose(),
|
|
97
|
+
]) {
|
|
98
|
+
try {
|
|
99
|
+
await cleanup();
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
errors.push(error);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (errors.length > 0)
|
|
106
|
+
throw errors[0];
|
|
78
107
|
}
|
|
79
|
-
async newSession() {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return
|
|
108
|
+
async newSession(options) {
|
|
109
|
+
// Suppresses for the ENTIRE command, not just the refresh tail: a
|
|
110
|
+
// multi-session host emits session_replaced while completing it, so the echo
|
|
111
|
+
// can arrive before the refresh/rebind sequence below starts and race it -
|
|
112
|
+
// newSession transports setup entries between two refreshes.
|
|
113
|
+
return this.#remoteSession.aroundLocalReplacement(async () => {
|
|
114
|
+
const result = await this.#client.newSession(options?.parentSession);
|
|
115
|
+
if (!result.cancelled) {
|
|
116
|
+
this.#beforeSessionInvalidate?.();
|
|
117
|
+
this.#remoteSession.abortLocalBash();
|
|
118
|
+
await this.#remoteSession.refresh();
|
|
119
|
+
if (options?.setup) {
|
|
120
|
+
const capture = SessionManager.inMemory(this.#remoteSession.session.sessionManager.getCwd());
|
|
121
|
+
await options.setup(capture);
|
|
122
|
+
for (const entry of capture.getEntries())
|
|
123
|
+
await this.#client.appendSessionEntry(entry);
|
|
124
|
+
await this.#remoteSession.refresh();
|
|
125
|
+
}
|
|
126
|
+
await this.#rebindSession?.();
|
|
127
|
+
if (options?.withSession)
|
|
128
|
+
await options.withSession(this.#remoteSession.createReplacedSessionContext());
|
|
129
|
+
}
|
|
130
|
+
return result;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
async switchSession(sessionPath, options) {
|
|
134
|
+
// See newSession: the suppression must cover the command itself, since the
|
|
135
|
+
// host emits session_replaced while completing it.
|
|
136
|
+
return this.#remoteSession.aroundLocalReplacement(async () => {
|
|
137
|
+
const result = await this.#client.switchSession(sessionPath, options?.cwdOverride === undefined ? undefined : { cwdOverride: options.cwdOverride });
|
|
138
|
+
if (!result.cancelled) {
|
|
139
|
+
this.#beforeSessionInvalidate?.();
|
|
140
|
+
this.#remoteSession.abortLocalBash();
|
|
141
|
+
await this.#remoteSession.refresh();
|
|
142
|
+
await this.#rebindSession?.();
|
|
143
|
+
// The shared host already resolved trust; this callback is retained for
|
|
144
|
+
// compatibility, but its result cannot override host-authoritative state.
|
|
145
|
+
options?.projectTrustContextFactory?.(this.#remoteSession.session.sessionManager.getCwd());
|
|
146
|
+
if (options?.withSession)
|
|
147
|
+
await options.withSession(this.#remoteSession.createReplacedSessionContext());
|
|
148
|
+
}
|
|
149
|
+
return result;
|
|
150
|
+
});
|
|
85
151
|
}
|
|
86
|
-
async
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
152
|
+
async fork(entryId, options) {
|
|
153
|
+
// See newSession: the suppression must cover the command itself.
|
|
154
|
+
return this.#remoteSession.aroundLocalReplacement(async () => {
|
|
155
|
+
const result = await this.#client.fork(entryId, options);
|
|
156
|
+
if (!result.cancelled) {
|
|
157
|
+
this.#beforeSessionInvalidate?.();
|
|
158
|
+
this.#remoteSession.abortLocalBash();
|
|
159
|
+
await this.#refreshAndRebind();
|
|
160
|
+
if (options?.withSession)
|
|
161
|
+
await options.withSession(this.#remoteSession.createReplacedSessionContext());
|
|
162
|
+
}
|
|
163
|
+
return { cancelled: result.cancelled, selectedText: result.text };
|
|
164
|
+
});
|
|
92
165
|
}
|
|
93
|
-
async
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
166
|
+
async importFromJsonl(inputPath, cwdOverride) {
|
|
167
|
+
// See newSession: the suppression must cover the command itself.
|
|
168
|
+
return this.#remoteSession.aroundLocalReplacement(async () => {
|
|
169
|
+
const result = await this.#client.importJsonl(inputPath, cwdOverride);
|
|
170
|
+
if (!result.cancelled) {
|
|
171
|
+
this.#beforeSessionInvalidate?.();
|
|
172
|
+
this.#remoteSession.abortLocalBash();
|
|
173
|
+
await this.#refreshAndRebind();
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
176
|
+
});
|
|
99
177
|
}
|
|
100
|
-
async
|
|
101
|
-
|
|
178
|
+
async #refreshAndRebind() {
|
|
179
|
+
await this.#remoteSession.refresh();
|
|
180
|
+
await this.#rebindSession?.();
|
|
102
181
|
}
|
|
103
182
|
}
|
|
104
|
-
|
|
183
|
+
/** Exported for direct coverage of the wire-event handling below. */
|
|
184
|
+
export function createRemoteSessionProxy(local, agentDir, client, initialState, onWarning) {
|
|
105
185
|
// Fire-and-forget setters keep the sync AgentSession signature, but their RPC
|
|
106
186
|
// failures must not vanish: the matching *_changed wire event confirms success,
|
|
107
187
|
// and a rejection here is the only signal of failure.
|
|
@@ -112,36 +192,296 @@ function createRemoteSessionProxy(local, client, initialState, onWarning) {
|
|
|
112
192
|
cause: error,
|
|
113
193
|
});
|
|
114
194
|
};
|
|
115
|
-
let state = initialState;
|
|
195
|
+
let state = { ...initialState };
|
|
196
|
+
const waitForBashCallbacks = async (promises, allowAbandonment) => {
|
|
197
|
+
if (promises.size === 0)
|
|
198
|
+
return true;
|
|
199
|
+
const settled = Promise.allSettled([...promises]).then(() => true);
|
|
200
|
+
let timeout;
|
|
201
|
+
const bounded = new Promise((resolve) => {
|
|
202
|
+
timeout = setTimeout(resolve, allowAbandonment ? 100 : 5_000, false);
|
|
203
|
+
timeout.unref?.();
|
|
204
|
+
});
|
|
205
|
+
try {
|
|
206
|
+
return await Promise.race([settled, bounded]);
|
|
207
|
+
}
|
|
208
|
+
finally {
|
|
209
|
+
if (timeout)
|
|
210
|
+
clearTimeout(timeout);
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
const executionNamespace = randomUUID();
|
|
214
|
+
const cleanupRemoteBashOutput = async (path) => {
|
|
215
|
+
let cleanupTimeout;
|
|
216
|
+
try {
|
|
217
|
+
await Promise.race([
|
|
218
|
+
client.cleanupBashOutput(path),
|
|
219
|
+
new Promise((_, reject) => {
|
|
220
|
+
cleanupTimeout = setTimeout(() => reject(new Error("RPC cleanup timed out")), 1_000);
|
|
221
|
+
}),
|
|
222
|
+
]);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
catch (transportError) {
|
|
226
|
+
// Spill paths are shared host filesystem paths. If the RPC transport is
|
|
227
|
+
// already unavailable, remove locally as a bounded best-effort fallback;
|
|
228
|
+
// a later reconnect is not required to prevent this callback failure from
|
|
229
|
+
// permanently leaking the host-owned artifact.
|
|
230
|
+
try {
|
|
231
|
+
await rm(path, { force: true });
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
catch (localError) {
|
|
235
|
+
onWarning?.({
|
|
236
|
+
type: "interactive_host_action_failed",
|
|
237
|
+
message: `Warning: failed to clean up shared bash output spill: ${localError instanceof Error ? localError.message : String(localError)}`,
|
|
238
|
+
cause: new AggregateError([transportError, localError]),
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
finally {
|
|
243
|
+
if (cleanupTimeout)
|
|
244
|
+
clearTimeout(cleanupTimeout);
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
let nextBashExecutionId = 0;
|
|
248
|
+
const bashExecutions = new Map();
|
|
249
|
+
let hostUiHandler;
|
|
250
|
+
const pendingUiRequests = [];
|
|
251
|
+
let localBashAbortController;
|
|
252
|
+
let localBashRunning = false;
|
|
253
|
+
let hostBashRunning = initialState.isBashRunning;
|
|
254
|
+
let nextQueuedInputOrder = Math.max(0, ...initialState.ordered.map((item) => item.enqueueOrder));
|
|
255
|
+
let sessionManager = local.sessionManager;
|
|
256
|
+
let settingsManager = SettingsManager.create(initialState.cwd, agentDir, {
|
|
257
|
+
projectTrusted: initialState.projectTrusted,
|
|
258
|
+
});
|
|
259
|
+
const updateBashState = () => {
|
|
260
|
+
state = { ...state, isBashRunning: localBashRunning || hostBashRunning };
|
|
261
|
+
};
|
|
262
|
+
const remoteSessionManager = new Proxy({}, {
|
|
263
|
+
get(_target, property, _receiver) {
|
|
264
|
+
if (property === "appendLabelChange") {
|
|
265
|
+
return (entryId, label) => void client.setLabel(entryId, label);
|
|
266
|
+
}
|
|
267
|
+
if (property === "getCwd")
|
|
268
|
+
return () => state.cwd;
|
|
269
|
+
if (property === "getSessionName")
|
|
270
|
+
return () => state.sessionName;
|
|
271
|
+
if (property === "getUsageTotals")
|
|
272
|
+
return () => state.usageTotals;
|
|
273
|
+
const value = Reflect.get(sessionManager, property, sessionManager);
|
|
274
|
+
return typeof value === "function" ? value.bind(sessionManager) : value;
|
|
275
|
+
},
|
|
276
|
+
});
|
|
116
277
|
let streamingAssistant;
|
|
278
|
+
let mirroredCurrentAssistantUsage = false;
|
|
279
|
+
/** Non-zero while this runtime is driving its own replacement sequence. */
|
|
280
|
+
let localReplacementDepth = 0;
|
|
117
281
|
const listeners = new Set();
|
|
118
282
|
client.onEvent((wireEvent) => {
|
|
283
|
+
if (wireEvent.type === "extension_ui_request") {
|
|
284
|
+
const request = wireEvent;
|
|
285
|
+
if (hostUiHandler)
|
|
286
|
+
void Promise.resolve(hostUiHandler(request)).then((response) => response && client.sendExtensionUIResponse(response));
|
|
287
|
+
else
|
|
288
|
+
pendingUiRequests.push(request);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (wireEvent.type === "session_replaced") {
|
|
292
|
+
// The host swapped the live session behind this connection - another
|
|
293
|
+
// attached client issued the replacement, or an extension drove one that no
|
|
294
|
+
// client issued. Nothing else re-reads the binding, so without this the
|
|
295
|
+
// proxy keeps serving the previous session's manager, settings and message
|
|
296
|
+
// mirror while the host has already moved on. The command response carries
|
|
297
|
+
// only `{ cancelled }`, so this event is the only signal available here.
|
|
298
|
+
//
|
|
299
|
+
// A multi-session host broadcasts the event to every connection including
|
|
300
|
+
// the one that issued the replacement, and this runtime's own replacement
|
|
301
|
+
// methods already run an ordered refresh/rebind - newSession additionally
|
|
302
|
+
// transports setup entries between two refreshes. Refreshing again from
|
|
303
|
+
// here would race that sequence, so self-driven replacements are skipped.
|
|
304
|
+
if (localReplacementDepth === 0) {
|
|
305
|
+
void refresh().catch(reportActionFailure("session refresh after replacement"));
|
|
306
|
+
}
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
119
309
|
if (wireEvent.type === "agent_settled")
|
|
120
|
-
state = { ...state, isStreaming: false };
|
|
310
|
+
state = { ...state, isStreaming: false, retryAttempt: 0 };
|
|
311
|
+
if (wireEvent.type === "bash_start") {
|
|
312
|
+
hostBashRunning = true;
|
|
313
|
+
updateBashState();
|
|
314
|
+
}
|
|
315
|
+
if (wireEvent.type === "bash_end") {
|
|
316
|
+
hostBashRunning = false;
|
|
317
|
+
updateBashState();
|
|
318
|
+
}
|
|
319
|
+
if (wireEvent.type === "bash_execution_update" && wireEvent.id) {
|
|
320
|
+
const execution = bashExecutions.get(wireEvent.id);
|
|
321
|
+
if (execution?.chunk && !execution.hasError) {
|
|
322
|
+
try {
|
|
323
|
+
const callbackPromise = Promise.resolve(execution.chunk(wireEvent.delta)).catch((error) => {
|
|
324
|
+
if (!execution.hasError) {
|
|
325
|
+
execution.error = error;
|
|
326
|
+
execution.hasError = true;
|
|
327
|
+
void client.abortBash().catch(() => { });
|
|
328
|
+
}
|
|
329
|
+
throw error;
|
|
330
|
+
});
|
|
331
|
+
execution.promises.add(callbackPromise);
|
|
332
|
+
void callbackPromise.catch(() => { }).finally(() => execution.promises.delete(callbackPromise));
|
|
333
|
+
}
|
|
334
|
+
catch (error) {
|
|
335
|
+
if (!execution.hasError) {
|
|
336
|
+
execution.error = error;
|
|
337
|
+
execution.hasError = true;
|
|
338
|
+
void client.abortBash().catch(() => { });
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
121
343
|
if (wireEvent.type === "agent_start")
|
|
122
344
|
state = { ...state, isStreaming: true };
|
|
345
|
+
if (wireEvent.type === "compaction_start")
|
|
346
|
+
state = { ...state, isCompacting: true };
|
|
347
|
+
if (wireEvent.type === "compaction_end")
|
|
348
|
+
state = { ...state, isCompacting: false };
|
|
349
|
+
if (wireEvent.type === "auto_retry_start")
|
|
350
|
+
state = { ...state, retryAttempt: wireEvent.attempt };
|
|
351
|
+
if (wireEvent.type === "auto_retry_end")
|
|
352
|
+
state = { ...state, retryAttempt: 0 };
|
|
353
|
+
if (wireEvent.type === "queue_update") {
|
|
354
|
+
nextQueuedInputOrder = Math.max(nextQueuedInputOrder, ...wireEvent.ordered.map((item) => item.enqueueOrder));
|
|
355
|
+
state = {
|
|
356
|
+
...state,
|
|
357
|
+
steering: [...wireEvent.steering],
|
|
358
|
+
followUp: [...wireEvent.followUp],
|
|
359
|
+
ordered: [...wireEvent.ordered],
|
|
360
|
+
pendingMessageCount: wireEvent.steering.length + wireEvent.followUp.length,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
123
363
|
if (wireEvent.type === "model_changed") {
|
|
124
364
|
state = { ...state, model: wireEvent.model, thinkingLevel: wireEvent.thinkingLevel };
|
|
125
365
|
}
|
|
126
366
|
if (wireEvent.type === "thinking_level_changed")
|
|
127
367
|
state = { ...state, thinkingLevel: wireEvent.level };
|
|
368
|
+
if (wireEvent.type === "service_tier_changed") {
|
|
369
|
+
state = { ...state, serviceTier: wireEvent.tier, fastMode: wireEvent.fastMode };
|
|
370
|
+
}
|
|
371
|
+
if (wireEvent.type === "session_settings_changed") {
|
|
372
|
+
state = {
|
|
373
|
+
...state,
|
|
374
|
+
steeringMode: wireEvent.steeringMode,
|
|
375
|
+
followUpMode: wireEvent.followUpMode,
|
|
376
|
+
autoCompactionEnabled: wireEvent.autoCompactionEnabled,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
if (wireEvent.type === "entry_appended") {
|
|
380
|
+
try {
|
|
381
|
+
sessionManager.appendEntry(wireEvent.entry);
|
|
382
|
+
local.agent.state.messages = sessionManager.buildSessionContext().messages;
|
|
383
|
+
}
|
|
384
|
+
catch {
|
|
385
|
+
// Non-fatal if the local snapshot cannot accept a concurrent entry.
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (wireEvent.type === "session_info_changed")
|
|
389
|
+
state = { ...state, sessionName: wireEvent.name };
|
|
128
390
|
if (wireEvent.type === "message_start") {
|
|
129
|
-
if (wireEvent.message.role === "assistant")
|
|
391
|
+
if (wireEvent.message.role === "assistant") {
|
|
130
392
|
streamingAssistant = structuredClone(wireEvent.message);
|
|
393
|
+
mirroredCurrentAssistantUsage = false;
|
|
394
|
+
}
|
|
131
395
|
local.agent.state.messages.push(structuredClone(wireEvent.message));
|
|
132
396
|
}
|
|
133
397
|
if (wireEvent.type === "message_end") {
|
|
134
|
-
if (wireEvent.message.role === "assistant")
|
|
398
|
+
if (wireEvent.message.role === "assistant") {
|
|
135
399
|
streamingAssistant = structuredClone(wireEvent.message);
|
|
400
|
+
const usage = wireEvent.message.usage;
|
|
401
|
+
if (usage && !mirroredCurrentAssistantUsage) {
|
|
402
|
+
mirroredCurrentAssistantUsage = true;
|
|
403
|
+
const latestPromptTokens = usage.input + usage.cacheRead + usage.cacheWrite;
|
|
404
|
+
const contextWindow = state.model?.contextWindow ?? 0;
|
|
405
|
+
const contextTokens = usage.input + usage.cacheRead + usage.cacheWrite;
|
|
406
|
+
state = {
|
|
407
|
+
...state,
|
|
408
|
+
contextUsage: contextWindow > 0
|
|
409
|
+
? { tokens: contextTokens, contextWindow, percent: (contextTokens / contextWindow) * 100 }
|
|
410
|
+
: undefined,
|
|
411
|
+
usageTotals: {
|
|
412
|
+
...state.usageTotals,
|
|
413
|
+
input: state.usageTotals.input + usage.input,
|
|
414
|
+
output: state.usageTotals.output + usage.output,
|
|
415
|
+
cacheRead: state.usageTotals.cacheRead + usage.cacheRead,
|
|
416
|
+
cacheWrite: state.usageTotals.cacheWrite + usage.cacheWrite,
|
|
417
|
+
cost: state.usageTotals.cost + (usage.cost?.total ?? 0),
|
|
418
|
+
latestCacheHitRate: latestPromptTokens > 0 ? (usage.cacheRead / latestPromptTokens) * 100 : undefined,
|
|
419
|
+
},
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
}
|
|
136
423
|
const messages = local.agent.state.messages;
|
|
137
424
|
const previous = messages.at(-1);
|
|
138
425
|
if (previous?.role === wireEvent.message.role)
|
|
139
426
|
messages[messages.length - 1] = structuredClone(wireEvent.message);
|
|
140
427
|
}
|
|
428
|
+
if (wireEvent.type === "compaction_end" && wireEvent.accepted && !wireEvent.aborted) {
|
|
429
|
+
try {
|
|
430
|
+
local.sessionManager.reloadFromDisk?.();
|
|
431
|
+
if (sessionManager !== local.sessionManager)
|
|
432
|
+
sessionManager.reloadFromDisk?.();
|
|
433
|
+
local.agent.state.messages = sessionManager.buildSessionContext().messages;
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
// Non-fatal if session file is transiently locked or unavailable
|
|
437
|
+
}
|
|
438
|
+
}
|
|
141
439
|
const event = hydrateMessageUpdate(wireEvent, streamingAssistant);
|
|
142
440
|
for (const listener of listeners)
|
|
143
441
|
listener(event);
|
|
144
442
|
});
|
|
443
|
+
const performRefresh = async () => {
|
|
444
|
+
const nextState = await client.getState();
|
|
445
|
+
state = { ...stateFromRpc(nextState) };
|
|
446
|
+
nextQueuedInputOrder = Math.max(0, ...nextState.ordered.map((item) => item.enqueueOrder));
|
|
447
|
+
let messages;
|
|
448
|
+
settingsManager = SettingsManager.create(nextState.cwd, agentDir, {
|
|
449
|
+
projectTrusted: nextState.projectTrusted,
|
|
450
|
+
});
|
|
451
|
+
if (nextState.sessionFile) {
|
|
452
|
+
// Keep the caller-owned manager identity when refreshing the same session.
|
|
453
|
+
// Navigation and host-side mutations must update every existing mirror, not
|
|
454
|
+
// leave the interactive runtime holding the pre-refresh snapshot.
|
|
455
|
+
if (sessionManager.getSessionFile() === nextState.sessionFile) {
|
|
456
|
+
sessionManager.reloadFromDisk?.();
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
// SessionManager.open retains the explicit path even when the host has
|
|
460
|
+
// deferred creating the file for a setup-only session.
|
|
461
|
+
sessionManager = SessionManager.open(nextState.sessionFile, undefined, nextState.cwd);
|
|
462
|
+
}
|
|
463
|
+
if (nextState.entries?.length && !sessionManager.getEntries().length) {
|
|
464
|
+
for (const entry of nextState.entries)
|
|
465
|
+
sessionManager.appendEntry(entry);
|
|
466
|
+
}
|
|
467
|
+
messages = sessionManager.buildSessionContext().messages;
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
messages = await client.getMessages();
|
|
471
|
+
}
|
|
472
|
+
local.agent.state.messages.splice(0, local.agent.state.messages.length, ...structuredClone(messages));
|
|
473
|
+
streamingAssistant = undefined;
|
|
474
|
+
};
|
|
475
|
+
// Refreshes must not interleave: each one reassigns sessionManager,
|
|
476
|
+
// settingsManager and the mirrored message list, so two in flight can commit a
|
|
477
|
+
// mixed snapshot of two different sessions. A replacement-driven refresh races
|
|
478
|
+
// exactly that way against a caller-driven one, so run them in order.
|
|
479
|
+
let refreshChain = Promise.resolve();
|
|
480
|
+
const refresh = () => {
|
|
481
|
+
const next = refreshChain.then(performRefresh, performRefresh);
|
|
482
|
+
refreshChain = next.then(() => { }, () => { });
|
|
483
|
+
return next;
|
|
484
|
+
};
|
|
145
485
|
const session = new Proxy(local, {
|
|
146
486
|
get(target, property, receiver) {
|
|
147
487
|
if (property === "prompt")
|
|
@@ -149,25 +489,74 @@ function createRemoteSessionProxy(local, client, initialState, onWarning) {
|
|
|
149
489
|
...(options?.images ? { images: options.images } : {}),
|
|
150
490
|
...(options?.streamingBehavior ? { streamingBehavior: options.streamingBehavior } : {}),
|
|
151
491
|
...(options?.thinkingLevel ? { thinkingLevel: options.thinkingLevel } : {}),
|
|
492
|
+
...(options?.sessionTitlePrompt !== undefined
|
|
493
|
+
? { sessionTitlePrompt: options.sessionTitlePrompt }
|
|
494
|
+
: {}),
|
|
495
|
+
...(options?.expandPromptTemplates !== undefined
|
|
496
|
+
? { expandPromptTemplates: options.expandPromptTemplates }
|
|
497
|
+
: {}),
|
|
152
498
|
...(options?.promptDisposition ? { promptDisposition: options.promptDisposition } : {}),
|
|
153
499
|
...(options?.preflightResult ? { preflightResult: options.preflightResult } : {}),
|
|
154
500
|
});
|
|
155
501
|
if (property === "abort")
|
|
156
502
|
return () => client.abort();
|
|
503
|
+
if (property === "abortCompaction")
|
|
504
|
+
return () => void client.abortCompaction();
|
|
157
505
|
if (property === "steer")
|
|
158
|
-
return (message, images) =>
|
|
506
|
+
return (message, images, recovery) => {
|
|
507
|
+
const enqueueOrder = recovery?.enqueueOrder ?? Math.max(0, ...state.ordered.map((item) => item.enqueueOrder)) + 1;
|
|
508
|
+
state = {
|
|
509
|
+
...state,
|
|
510
|
+
steering: [...state.steering, message],
|
|
511
|
+
ordered: [...state.ordered, { text: message, mode: "steer", enqueueOrder }],
|
|
512
|
+
pendingMessageCount: state.pendingMessageCount + 1,
|
|
513
|
+
};
|
|
514
|
+
return client.steer(message, images, { ...recovery, enqueueOrder });
|
|
515
|
+
};
|
|
159
516
|
if (property === "followUp")
|
|
160
|
-
return (message, images) =>
|
|
517
|
+
return (message, images, recovery) => {
|
|
518
|
+
const enqueueOrder = recovery?.enqueueOrder ?? Math.max(0, ...state.ordered.map((item) => item.enqueueOrder)) + 1;
|
|
519
|
+
state = {
|
|
520
|
+
...state,
|
|
521
|
+
followUp: [...state.followUp, message],
|
|
522
|
+
ordered: [...state.ordered, { text: message, mode: "followUp", enqueueOrder }],
|
|
523
|
+
pendingMessageCount: state.pendingMessageCount + 1,
|
|
524
|
+
};
|
|
525
|
+
return client.followUp(message, images, { ...recovery, enqueueOrder });
|
|
526
|
+
};
|
|
161
527
|
if (property === "waitForIdle")
|
|
162
528
|
return () => client.waitForIdle();
|
|
163
529
|
if (property === "getLastAssistantText")
|
|
164
530
|
return () => target.getLastAssistantText();
|
|
165
|
-
if (property === "setModel")
|
|
531
|
+
if (property === "setModel" || property === "setSessionModel")
|
|
166
532
|
return async (model) => {
|
|
167
|
-
await client.setModel(model.provider, model.id);
|
|
533
|
+
const next = await client.setModel(model.provider, model.id);
|
|
534
|
+
return { systemPromptName: next.systemPromptName, model: next };
|
|
535
|
+
};
|
|
536
|
+
if (property === "setSessionThinkingLevel")
|
|
537
|
+
return (level) => void client
|
|
538
|
+
.setThinkingLevel(level, { scope: "turn" })
|
|
539
|
+
.catch(reportActionFailure("setSessionThinkingLevel"));
|
|
540
|
+
if (property === "setSessionFastMode")
|
|
541
|
+
return (enabled) => void client.setFastMode(enabled).catch(reportActionFailure("setSessionFastMode"));
|
|
542
|
+
if (property === "abortRetry")
|
|
543
|
+
return () => void client.abortRetry().catch(reportActionFailure("abortRetry"));
|
|
544
|
+
if (property === "setAutoRetryEnabled")
|
|
545
|
+
return (enabled) => void client.setAutoRetry(enabled).catch(reportActionFailure("setAutoRetryEnabled"));
|
|
546
|
+
if (property === "reserveQueuedInputOrder")
|
|
547
|
+
return () => ++nextQueuedInputOrder;
|
|
548
|
+
if (property === "setFavoriteModels")
|
|
549
|
+
return (models) => {
|
|
550
|
+
state = { ...state, favoriteModels: [...models] };
|
|
551
|
+
void client.setFavoriteModels(models).catch(reportActionFailure("setFavoriteModels"));
|
|
552
|
+
};
|
|
553
|
+
if (property === "setScopedModels")
|
|
554
|
+
return (models) => {
|
|
555
|
+
state = { ...state, scopedModels: [...models] };
|
|
556
|
+
void client.setScopedModels(models).catch(reportActionFailure("setScopedModels"));
|
|
168
557
|
};
|
|
169
558
|
if (property === "cycleModel")
|
|
170
|
-
return () => client.cycleModel();
|
|
559
|
+
return (direction) => client.cycleModel(direction);
|
|
171
560
|
if (property === "setThinkingLevel")
|
|
172
561
|
return (level) => void client.setThinkingLevel(level).catch(reportActionFailure("setThinkingLevel"));
|
|
173
562
|
if (property === "cycleThinkingLevel")
|
|
@@ -183,15 +572,81 @@ function createRemoteSessionProxy(local, client, initialState, onWarning) {
|
|
|
183
572
|
if (property === "setAutoCompactionEnabled")
|
|
184
573
|
return (enabled) => void client.setAutoCompaction(enabled).catch(reportActionFailure("setAutoCompaction"));
|
|
185
574
|
if (property === "executeBash")
|
|
186
|
-
return (command) =>
|
|
575
|
+
return async (command, onChunk, options) => {
|
|
576
|
+
if (options?.operations && typeof options.operations.exec === "function") {
|
|
577
|
+
const abortController = new AbortController();
|
|
578
|
+
localBashAbortController = abortController;
|
|
579
|
+
localBashRunning = true;
|
|
580
|
+
updateBashState();
|
|
581
|
+
const sessionAtStart = state.sessionId;
|
|
582
|
+
const prefix = settingsManager.getShellCommandPrefix();
|
|
583
|
+
const resolvedCommand = prefix ? `${prefix}\n${command}` : command;
|
|
584
|
+
try {
|
|
585
|
+
const result = await executeBashWithOperations(resolvedCommand, state.cwd, options.operations, { onChunk, signal: abortController.signal });
|
|
586
|
+
if (state.sessionId === sessionAtStart) {
|
|
587
|
+
await client.recordBashResult(command, result, options.excludeFromContext);
|
|
588
|
+
}
|
|
589
|
+
return result;
|
|
590
|
+
}
|
|
591
|
+
finally {
|
|
592
|
+
localBashAbortController = undefined;
|
|
593
|
+
localBashRunning = false;
|
|
594
|
+
updateBashState();
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
const executionId = `bash-${executionNamespace}-${++nextBashExecutionId}`;
|
|
598
|
+
const execution = {
|
|
599
|
+
chunk: onChunk,
|
|
600
|
+
promises: new Set(),
|
|
601
|
+
error: undefined,
|
|
602
|
+
hasError: false,
|
|
603
|
+
};
|
|
604
|
+
bashExecutions.set(executionId, execution);
|
|
605
|
+
try {
|
|
606
|
+
const result = await client.bash(command, {
|
|
607
|
+
excludeFromContext: options?.excludeFromContext,
|
|
608
|
+
executionId,
|
|
609
|
+
operations: options?.operations,
|
|
610
|
+
});
|
|
611
|
+
const callbacksSettled = await waitForBashCallbacks(execution.promises, false);
|
|
612
|
+
if (!callbacksSettled) {
|
|
613
|
+
if (result.fullOutputPath)
|
|
614
|
+
await cleanupRemoteBashOutput(result.fullOutputPath);
|
|
615
|
+
throw new Error("Bash output callback did not settle within 5000ms");
|
|
616
|
+
}
|
|
617
|
+
if (execution.hasError) {
|
|
618
|
+
if (result.fullOutputPath)
|
|
619
|
+
await cleanupRemoteBashOutput(result.fullOutputPath);
|
|
620
|
+
throw execution.error;
|
|
621
|
+
}
|
|
622
|
+
return result;
|
|
623
|
+
}
|
|
624
|
+
finally {
|
|
625
|
+
bashExecutions.delete(executionId);
|
|
626
|
+
}
|
|
627
|
+
};
|
|
187
628
|
if (property === "abortBash")
|
|
188
|
-
return () =>
|
|
629
|
+
return () => {
|
|
630
|
+
if (localBashAbortController)
|
|
631
|
+
localBashAbortController.abort();
|
|
632
|
+
else
|
|
633
|
+
void client.abortBash().catch(reportActionFailure("abortBash"));
|
|
634
|
+
};
|
|
635
|
+
if (property === "getContextUsage")
|
|
636
|
+
return () => state.contextUsage;
|
|
189
637
|
if (property === "getSessionStats")
|
|
190
638
|
return () => client.getSessionStats();
|
|
191
639
|
if (property === "exportToHtml")
|
|
192
|
-
return (outputPath) => client.exportHtml(outputPath).then((result) => result.path);
|
|
640
|
+
return (outputPath, options) => client.exportHtml(outputPath, options?.themeName).then((result) => result.path);
|
|
193
641
|
if (property === "setSessionName")
|
|
194
|
-
return (name) =>
|
|
642
|
+
return (name) => client.setSessionName(name).catch(reportActionFailure("setSessionName"));
|
|
643
|
+
if (property === "navigateTree")
|
|
644
|
+
return async (targetId, options) => {
|
|
645
|
+
const result = await client.navigateTree(targetId, options);
|
|
646
|
+
if (!result.cancelled)
|
|
647
|
+
await refresh();
|
|
648
|
+
return result;
|
|
649
|
+
};
|
|
195
650
|
if (property === "getUserMessagesForForking")
|
|
196
651
|
return () => client.getForkMessages();
|
|
197
652
|
if (property === "subscribe")
|
|
@@ -205,6 +660,45 @@ function createRemoteSessionProxy(local, client, initialState, onWarning) {
|
|
|
205
660
|
};
|
|
206
661
|
if (property === "isStreaming")
|
|
207
662
|
return state.isStreaming;
|
|
663
|
+
if (property === "isIdle")
|
|
664
|
+
return !state.isStreaming;
|
|
665
|
+
if (property === "isCompacting")
|
|
666
|
+
return state.isCompacting;
|
|
667
|
+
if (property === "pendingMessageCount")
|
|
668
|
+
return state.pendingMessageCount;
|
|
669
|
+
if (property === "getSteeringMessages")
|
|
670
|
+
return () => state.steering;
|
|
671
|
+
if (property === "getFollowUpMessages")
|
|
672
|
+
return () => state.followUp;
|
|
673
|
+
if (property === "clearQueue")
|
|
674
|
+
return (options) => {
|
|
675
|
+
const result = {
|
|
676
|
+
steering: [...state.steering],
|
|
677
|
+
followUp: [...state.followUp],
|
|
678
|
+
ordered: [...state.ordered],
|
|
679
|
+
};
|
|
680
|
+
Object.defineProperty(result, "ordered", { value: result.ordered, enumerable: false });
|
|
681
|
+
void client.clearQueue(options).catch(reportActionFailure("clearQueue"));
|
|
682
|
+
return result;
|
|
683
|
+
};
|
|
684
|
+
if (property === "abortBranchSummary")
|
|
685
|
+
return () => void client.abortBranchSummary().catch(reportActionFailure("abortBranchSummary"));
|
|
686
|
+
if (property === "recordBashResult")
|
|
687
|
+
return (command, result, options) => void client
|
|
688
|
+
.recordBashResult(command, result, options?.excludeFromContext)
|
|
689
|
+
.catch(reportActionFailure("recordBashResult"));
|
|
690
|
+
if (property === "set_label")
|
|
691
|
+
return undefined;
|
|
692
|
+
if (property === "retryAttempt")
|
|
693
|
+
return state.retryAttempt;
|
|
694
|
+
if (property === "isBashRunning")
|
|
695
|
+
return state.isBashRunning;
|
|
696
|
+
if (property === "reload")
|
|
697
|
+
return (_options) => client.reload();
|
|
698
|
+
if (property === "checkReloadVeto")
|
|
699
|
+
return () => client.checkReloadVeto();
|
|
700
|
+
if (property === "exportToJsonl")
|
|
701
|
+
return (outputPath) => client.exportJsonl(outputPath).then((result) => result.path);
|
|
208
702
|
// The footer and other renderers read session.state.*; surface the
|
|
209
703
|
// host-authoritative fields there too, not only via the direct getters.
|
|
210
704
|
if (property === "state") {
|
|
@@ -214,14 +708,35 @@ function createRemoteSessionProxy(local, client, initialState, onWarning) {
|
|
|
214
708
|
model: state.model ?? localState.model,
|
|
215
709
|
thinkingLevel: state.thinkingLevel,
|
|
216
710
|
isStreaming: state.isStreaming,
|
|
711
|
+
isCompacting: state.isCompacting,
|
|
217
712
|
};
|
|
218
713
|
}
|
|
219
714
|
if (property === "sessionFile")
|
|
220
715
|
return state.sessionFile;
|
|
221
716
|
if (property === "sessionId")
|
|
222
717
|
return state.sessionId;
|
|
718
|
+
if (property === "sessionName")
|
|
719
|
+
return state.sessionName;
|
|
720
|
+
if (property === "serviceTier")
|
|
721
|
+
return state.serviceTier;
|
|
722
|
+
if (property === "steeringMode")
|
|
723
|
+
return state.steeringMode;
|
|
724
|
+
if (property === "followUpMode")
|
|
725
|
+
return state.followUpMode;
|
|
726
|
+
if (property === "autoCompactionEnabled")
|
|
727
|
+
return state.autoCompactionEnabled;
|
|
728
|
+
if (property === "isFastModeActive")
|
|
729
|
+
return () => state.fastMode;
|
|
730
|
+
if (property === "sessionManager")
|
|
731
|
+
return remoteSessionManager;
|
|
732
|
+
if (property === "settingsManager")
|
|
733
|
+
return settingsManager;
|
|
223
734
|
if (property === "messages")
|
|
224
735
|
return target.messages;
|
|
736
|
+
if (property === "favoriteModels")
|
|
737
|
+
return state.favoriteModels;
|
|
738
|
+
if (property === "scopedModels")
|
|
739
|
+
return state.scopedModels;
|
|
225
740
|
if (property === "model")
|
|
226
741
|
return state.model ?? target.model;
|
|
227
742
|
if (property === "thinkingLevel")
|
|
@@ -229,7 +744,53 @@ function createRemoteSessionProxy(local, client, initialState, onWarning) {
|
|
|
229
744
|
return Reflect.get(target, property, receiver);
|
|
230
745
|
},
|
|
231
746
|
});
|
|
232
|
-
return
|
|
747
|
+
return {
|
|
748
|
+
session,
|
|
749
|
+
setHostUiHandler: (callback) => {
|
|
750
|
+
hostUiHandler = callback;
|
|
751
|
+
if (callback)
|
|
752
|
+
for (const request of pendingUiRequests.splice(0))
|
|
753
|
+
void Promise.resolve(callback(request)).then((response) => response && client.sendExtensionUIResponse(response));
|
|
754
|
+
},
|
|
755
|
+
refresh,
|
|
756
|
+
aroundLocalReplacement: async (body) => {
|
|
757
|
+
localReplacementDepth++;
|
|
758
|
+
try {
|
|
759
|
+
return await body();
|
|
760
|
+
}
|
|
761
|
+
finally {
|
|
762
|
+
localReplacementDepth--;
|
|
763
|
+
}
|
|
764
|
+
},
|
|
765
|
+
abortLocalBash: () => localBashAbortController?.abort(),
|
|
766
|
+
createReplacedSessionContext: () => {
|
|
767
|
+
const context = local.createReplacedSessionContext();
|
|
768
|
+
Object.defineProperty(context, "cwd", { value: state.cwd });
|
|
769
|
+
Object.defineProperty(context, "sessionManager", { value: remoteSessionManager });
|
|
770
|
+
context.sendMessage = (message, options) => client.sendCustomMessage(message, {
|
|
771
|
+
triggerTurn: options?.triggerTurn,
|
|
772
|
+
deliverAs: options?.deliverAs,
|
|
773
|
+
});
|
|
774
|
+
context.sendUserMessage = (content, options) => {
|
|
775
|
+
if (typeof content === "string")
|
|
776
|
+
return client.prompt(content, {
|
|
777
|
+
streamingBehavior: options?.deliverAs,
|
|
778
|
+
expandPromptTemplates: options?.expandPromptTemplates,
|
|
779
|
+
});
|
|
780
|
+
const text = content
|
|
781
|
+
.filter((part) => part.type === "text")
|
|
782
|
+
.map((part) => part.text)
|
|
783
|
+
.join("\n");
|
|
784
|
+
const images = content.filter((part) => part.type === "image");
|
|
785
|
+
return client.prompt(text, {
|
|
786
|
+
images,
|
|
787
|
+
streamingBehavior: options?.deliverAs,
|
|
788
|
+
expandPromptTemplates: options?.expandPromptTemplates,
|
|
789
|
+
});
|
|
790
|
+
};
|
|
791
|
+
return context;
|
|
792
|
+
},
|
|
793
|
+
};
|
|
233
794
|
}
|
|
234
795
|
function hydrateMessageUpdate(event, streamingAssistant) {
|
|
235
796
|
if (event.type !== "message_update" || !streamingAssistant)
|