@code-yeongyu/senpi 2026.8.29 → 2026.8.30-3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +172 -0
- package/dist/core/agent-session.d.ts +47 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +406 -39
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +155 -37
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/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 +23 -9
- package/dist/core/credential-accounts.js.map +1 -1
- package/dist/core/credential-pool/env-slots.d.ts.map +1 -1
- package/dist/core/credential-pool/env-slots.js +2 -0
- package/dist/core/credential-pool/env-slots.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts +18 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.js +32 -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 +164 -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-retry.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/idle-retry.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/idle-retry.js +1 -1
- package/dist/core/extensions/builtin/compaction/idle-retry.js.map +1 -1
- 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 +148 -150
- 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/model-usability-budget.d.ts +30 -0
- package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/model-usability-budget.js +74 -0
- package/dist/core/extensions/builtin/compaction/model-usability-budget.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 +46 -0
- package/dist/core/extensions/builtin/compaction/orchestration.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/orchestration.js +103 -0
- package/dist/core/extensions/builtin/compaction/orchestration.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/policy.d.ts +12 -2
- package/dist/core/extensions/builtin/compaction/policy.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/policy.js +52 -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 +24 -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 +25 -0
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.d.ts +27 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.js +56 -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/permission-system/external-dir.d.ts.map +1 -1
- package/dist/core/extensions/builtin/permission-system/external-dir.js +15 -5
- package/dist/core/extensions/builtin/permission-system/external-dir.js.map +1 -1
- package/dist/core/extensions/builtin/permission-system/parsers.d.ts.map +1 -1
- package/dist/core/extensions/builtin/permission-system/parsers.js +16 -1
- package/dist/core/extensions/builtin/permission-system/parsers.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/manager.d.ts +5 -0
- package/dist/core/extensions/builtin/terminal/manager.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/manager.js +31 -3
- package/dist/core/extensions/builtin/terminal/manager.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-permission.d.ts +8 -0
- package/dist/core/extensions/builtin/terminal/monitor-permission.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-permission.js +16 -0
- package/dist/core/extensions/builtin/terminal/monitor-permission.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts +13 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-registry.js +403 -3
- package/dist/core/extensions/builtin/terminal/monitor-registry.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/runtime-session.d.ts +11 -0
- package/dist/core/extensions/builtin/terminal/runtime-session.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/runtime-session.js +18 -2
- package/dist/core/extensions/builtin/terminal/runtime-session.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/session-bundle.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/session-bundle.js +1 -0
- package/dist/core/extensions/builtin/terminal/session-bundle.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/kill-bash.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/kill-bash.js +5 -2
- package/dist/core/extensions/builtin/terminal/tools/kill-bash.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts +4 -0
- package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/monitor.js +40 -2
- package/dist/core/extensions/builtin/terminal/tools/monitor.js.map +1 -1
- package/dist/core/model-resolver.js +2 -2
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +5 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +10 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +17 -5
- package/dist/main.js.map +1 -1
- package/dist/modes/index.d.ts +1 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js +1 -1
- package/dist/modes/index.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 +132 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.js +633 -117
- package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +7 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +114 -2
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/connection-handler.d.ts +8 -1
- package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
- package/dist/modes/rpc/connection-handler.js +158 -49
- 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 +6 -4
- package/dist/modes/rpc/multi-session-host.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +20 -4
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +76 -17
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-input-validation.d.ts +1 -0
- package/dist/modes/rpc/rpc-input-validation.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-input-validation.js +66 -0
- package/dist/modes/rpc/rpc-input-validation.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +86 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-binding.d.ts +1 -0
- package/dist/modes/rpc/session-binding.d.ts.map +1 -1
- package/dist/modes/rpc/session-binding.js +21 -1
- package/dist/modes/rpc/session-binding.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +1 -0
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-event-writer.d.ts +2 -0
- package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-writer.js +54 -7
- package/dist/modes/rpc/session-event-writer.js.map +1 -1
- package/dist/modes/rpc/session-extension-ui-requests.d.ts +1 -0
- package/dist/modes/rpc/session-extension-ui-requests.d.ts.map +1 -1
- package/dist/modes/rpc/session-extension-ui-requests.js +5 -0
- package/dist/modes/rpc/session-extension-ui-requests.js.map +1 -1
- package/dist/modes/rpc/session-registry.d.ts +10 -2
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +58 -4
- package/dist/modes/rpc/session-registry.js.map +1 -1
- package/dist/modes/rpc/socket-event-fanout.d.ts +22 -0
- package/dist/modes/rpc/socket-event-fanout.d.ts.map +1 -0
- package/dist/modes/rpc/socket-event-fanout.js +84 -0
- package/dist/modes/rpc/socket-event-fanout.js.map +1 -0
- package/docs/rpc.md +22 -2
- package/docs/settings.md +34 -0
- package/docs/windows.md +2 -0
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +62 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-indirect-eval.js +139 -90
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +4 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js +40 -20
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts +3 -3
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.d.ts +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.js +28 -9
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +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/cloudflare-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts +42 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js +34 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js.map +1 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts +8 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-text.js +51 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-text.js.map +1 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts +45 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-pty/dist/screen.js +178 -55
- package/node_modules/@earendil-works/pi-pty/dist/screen.js.map +1 -1
- 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,38 +1,95 @@
|
|
|
1
1
|
import xterm from "@xterm/headless";
|
|
2
|
+
import { MAX_PENDING_WRITE_CHARS, settleOperation, sharedSettler, } from "./screen-operations.js";
|
|
3
|
+
import { decodeInput, normalizeDimension, normalizeReplayHistoryLength, normalizeScrollback, readLine, sanitizeString, } from "./screen-text.js";
|
|
2
4
|
const XtermTerminal = xterm.Terminal;
|
|
3
5
|
const DEFAULT_COLS = 80;
|
|
4
6
|
const DEFAULT_ROWS = 24;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Headless xterm screen model with serialized, flow-controlled writes.
|
|
9
|
+
*
|
|
10
|
+
* Every terminal mutation (feed, resize, backlog replay) runs through one
|
|
11
|
+
* FIFO queue that awaits xterm's parse callback before issuing the next
|
|
12
|
+
* write, so xterm's pending-write watermark can never be exceeded. When the
|
|
13
|
+
* queued backlog outgrows {@link MAX_PENDING_WRITE_CHARS}, the queued writes
|
|
14
|
+
* collapse into a single bounded history replay that reconstructs the same
|
|
15
|
+
* screen state. After {@link TerminalScreen.dispose}, queued and future
|
|
16
|
+
* operations settle as resolved no-ops; a terminal is never created after
|
|
17
|
+
* disposal.
|
|
18
|
+
*/
|
|
10
19
|
export class TerminalScreen {
|
|
11
20
|
constructor(options = {}) {
|
|
12
21
|
this.history = [];
|
|
13
22
|
this.historyLength = 0;
|
|
23
|
+
this.operations = [];
|
|
24
|
+
this.pendingChars = 0;
|
|
25
|
+
this.draining = false;
|
|
26
|
+
this.disposed = false;
|
|
27
|
+
this.notifyDisposed = () => undefined;
|
|
14
28
|
const cols = normalizeDimension(options.cols, DEFAULT_COLS);
|
|
15
29
|
const rows = normalizeDimension(options.rows, DEFAULT_ROWS);
|
|
16
30
|
this.scrollback = normalizeScrollback(options.scrollback);
|
|
17
31
|
this.maxReplayHistoryLength = normalizeReplayHistoryLength(cols, rows, this.scrollback);
|
|
32
|
+
this.whenDisposed = new Promise((resolve) => {
|
|
33
|
+
this.notifyDisposed = resolve;
|
|
34
|
+
});
|
|
18
35
|
this.terminal = this.createTerminal(cols, rows);
|
|
19
36
|
}
|
|
20
37
|
feed(data) {
|
|
38
|
+
if (this.disposed)
|
|
39
|
+
return Promise.resolve();
|
|
21
40
|
const payload = decodeInput(data);
|
|
22
41
|
const sanitizedPayload = sanitizeString(payload);
|
|
23
42
|
if (sanitizedPayload.length > 0)
|
|
24
43
|
this.appendHistory(sanitizedPayload);
|
|
25
|
-
|
|
44
|
+
if (this.pendingChars + payload.length > MAX_PENDING_WRITE_CHARS) {
|
|
45
|
+
return this.coalesceFeedIntoReplay(payload);
|
|
46
|
+
}
|
|
47
|
+
this.pendingChars += payload.length;
|
|
48
|
+
const operation = { kind: "write", payload, settled: null, settlers: [] };
|
|
49
|
+
return this.enqueue(operation, sharedSettler(operation));
|
|
26
50
|
}
|
|
27
51
|
resize(cols, rows) {
|
|
52
|
+
if (this.disposed)
|
|
53
|
+
return Promise.resolve();
|
|
28
54
|
const nextCols = normalizeDimension(cols, this.terminal.cols);
|
|
29
55
|
const nextRows = normalizeDimension(rows, this.terminal.rows);
|
|
30
|
-
this.
|
|
31
|
-
|
|
32
|
-
|
|
56
|
+
const snapshot = this.history.join("");
|
|
57
|
+
const tail = this.operations[this.operations.length - 1];
|
|
58
|
+
if (tail !== undefined && tail.kind === "resize") {
|
|
59
|
+
tail.cols = nextCols;
|
|
60
|
+
tail.rows = nextRows;
|
|
61
|
+
this.pendingChars += snapshot.length - tail.replay.length;
|
|
62
|
+
tail.replay = snapshot;
|
|
63
|
+
return sharedSettler(tail);
|
|
64
|
+
}
|
|
65
|
+
if (this.pendingChars + snapshot.length > MAX_PENDING_WRITE_CHARS) {
|
|
66
|
+
return this.coalesceQueueIntoResize(nextCols, nextRows, snapshot);
|
|
67
|
+
}
|
|
68
|
+
const operation = {
|
|
69
|
+
kind: "resize",
|
|
70
|
+
cols: nextCols,
|
|
71
|
+
rows: nextRows,
|
|
72
|
+
replay: snapshot,
|
|
73
|
+
settled: null,
|
|
74
|
+
settlers: [],
|
|
75
|
+
};
|
|
76
|
+
this.pendingChars += snapshot.length;
|
|
77
|
+
return this.enqueue(operation, sharedSettler(operation));
|
|
33
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Resolves once everything fed before this call has been parsed. Attaches
|
|
81
|
+
* to the queue tail instead of enqueueing a marker so a flush can never
|
|
82
|
+
* split a tail replay (which would let over-cap feeds mint unbounded new
|
|
83
|
+
* replay operations); only an empty queue enqueues a zero-length write.
|
|
84
|
+
*/
|
|
34
85
|
flush() {
|
|
35
|
-
|
|
86
|
+
if (this.disposed)
|
|
87
|
+
return Promise.resolve();
|
|
88
|
+
const tail = this.operations[this.operations.length - 1];
|
|
89
|
+
if (tail !== undefined)
|
|
90
|
+
return sharedSettler(tail);
|
|
91
|
+
const operation = { kind: "write", payload: "", settled: null, settlers: [] };
|
|
92
|
+
return this.enqueue(operation, sharedSettler(operation));
|
|
36
93
|
}
|
|
37
94
|
snapshot() {
|
|
38
95
|
const buffer = this.terminal.buffer.active;
|
|
@@ -58,6 +115,15 @@ export class TerminalScreen {
|
|
|
58
115
|
};
|
|
59
116
|
}
|
|
60
117
|
dispose() {
|
|
118
|
+
if (this.disposed)
|
|
119
|
+
return;
|
|
120
|
+
this.disposed = true;
|
|
121
|
+
this.notifyDisposed();
|
|
122
|
+
const pending = this.operations.splice(0, this.operations.length);
|
|
123
|
+
this.pendingChars = 0;
|
|
124
|
+
for (const operation of pending) {
|
|
125
|
+
settleOperation(operation.settlers, null);
|
|
126
|
+
}
|
|
61
127
|
this.terminal.dispose();
|
|
62
128
|
}
|
|
63
129
|
createTerminal(cols, rows) {
|
|
@@ -70,6 +136,108 @@ export class TerminalScreen {
|
|
|
70
136
|
logLevel: "off",
|
|
71
137
|
});
|
|
72
138
|
}
|
|
139
|
+
enqueue(operation, settled) {
|
|
140
|
+
this.operations.push(operation);
|
|
141
|
+
void this.drain();
|
|
142
|
+
return settled;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Route an over-cap feed to the queue's tail replay instead of enqueueing
|
|
146
|
+
* another write. Replay payloads are owned snapshot strings (immune to
|
|
147
|
+
* history trimming) bounded to the replay budget, and every coalesced feed
|
|
148
|
+
* shares the tail's memoized promise, so a flood cannot grow the queue,
|
|
149
|
+
* its payload memory, or its settler memory past the configured bounds.
|
|
150
|
+
*/
|
|
151
|
+
coalesceFeedIntoReplay(payload) {
|
|
152
|
+
const tail = this.operations[this.operations.length - 1];
|
|
153
|
+
if (tail !== undefined && tail.kind === "replay") {
|
|
154
|
+
const previousLength = tail.payload.length;
|
|
155
|
+
tail.payload = this.boundReplayPayload(tail.payload + payload);
|
|
156
|
+
this.pendingChars += tail.payload.length - previousLength;
|
|
157
|
+
return sharedSettler(tail);
|
|
158
|
+
}
|
|
159
|
+
const operation = {
|
|
160
|
+
kind: "replay",
|
|
161
|
+
payload: this.history.join(""),
|
|
162
|
+
settled: null,
|
|
163
|
+
settlers: [],
|
|
164
|
+
};
|
|
165
|
+
this.pendingChars += operation.payload.length;
|
|
166
|
+
return this.enqueue(operation, sharedSettler(operation));
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* A resize whose snapshot would push the queued payload past the cap
|
|
170
|
+
* collapses the whole queue into one resize at the latest dimensions:
|
|
171
|
+
* every dropped operation's payload is already covered by the bounded
|
|
172
|
+
* history snapshot, and their settlers settle with this operation.
|
|
173
|
+
*/
|
|
174
|
+
coalesceQueueIntoResize(cols, rows, snapshot) {
|
|
175
|
+
const operation = {
|
|
176
|
+
kind: "resize",
|
|
177
|
+
cols,
|
|
178
|
+
rows,
|
|
179
|
+
replay: snapshot,
|
|
180
|
+
settled: null,
|
|
181
|
+
settlers: [],
|
|
182
|
+
};
|
|
183
|
+
for (const queued of this.operations.splice(0, this.operations.length)) {
|
|
184
|
+
for (const settler of queued.settlers)
|
|
185
|
+
operation.settlers.push(settler);
|
|
186
|
+
queued.settlers.length = 0;
|
|
187
|
+
}
|
|
188
|
+
this.pendingChars = snapshot.length;
|
|
189
|
+
return this.enqueue(operation, sharedSettler(operation));
|
|
190
|
+
}
|
|
191
|
+
boundReplayPayload(payload) {
|
|
192
|
+
if (payload.length <= this.maxReplayHistoryLength)
|
|
193
|
+
return payload;
|
|
194
|
+
return sanitizeString(payload.slice(-this.maxReplayHistoryLength));
|
|
195
|
+
}
|
|
196
|
+
async drain() {
|
|
197
|
+
if (this.draining)
|
|
198
|
+
return;
|
|
199
|
+
this.draining = true;
|
|
200
|
+
try {
|
|
201
|
+
while (!this.disposed) {
|
|
202
|
+
const operation = this.operations.shift();
|
|
203
|
+
if (operation === undefined)
|
|
204
|
+
return;
|
|
205
|
+
this.pendingChars -= operation.kind === "resize" ? operation.replay.length : operation.payload.length;
|
|
206
|
+
try {
|
|
207
|
+
await this.run(operation);
|
|
208
|
+
settleOperation(operation.settlers, null);
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
settleOperation(operation.settlers, error instanceof Error ? error : new Error(String(error)));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
finally {
|
|
216
|
+
this.draining = false;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
async run(operation) {
|
|
220
|
+
if (this.disposed)
|
|
221
|
+
return;
|
|
222
|
+
switch (operation.kind) {
|
|
223
|
+
case "write":
|
|
224
|
+
await this.raceDisposal(this.write(operation.payload));
|
|
225
|
+
return;
|
|
226
|
+
case "replay":
|
|
227
|
+
this.terminal.reset();
|
|
228
|
+
await this.raceDisposal(this.write(operation.payload));
|
|
229
|
+
return;
|
|
230
|
+
case "resize":
|
|
231
|
+
this.terminal.dispose();
|
|
232
|
+
this.terminal = this.createTerminal(operation.cols, operation.rows);
|
|
233
|
+
await this.raceDisposal(this.write(operation.replay));
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/** A disposed terminal may never invoke its parse callback; do not hang. */
|
|
238
|
+
raceDisposal(written) {
|
|
239
|
+
return Promise.race([written, this.whenDisposed]);
|
|
240
|
+
}
|
|
73
241
|
write(payload) {
|
|
74
242
|
return new Promise((resolve, reject) => {
|
|
75
243
|
try {
|
|
@@ -107,49 +275,4 @@ export class TerminalScreen {
|
|
|
107
275
|
this.historyLength = trimmed.length;
|
|
108
276
|
}
|
|
109
277
|
}
|
|
110
|
-
function readLine(buffer, lineIndex) {
|
|
111
|
-
return buffer.getLine(lineIndex)?.translateToString(true) ?? "";
|
|
112
|
-
}
|
|
113
|
-
function normalizeDimension(value, fallback) {
|
|
114
|
-
if (value === undefined || !Number.isFinite(value))
|
|
115
|
-
return fallback;
|
|
116
|
-
return Math.min(MAX_SIZE, Math.max(MIN_SIZE, Math.trunc(value)));
|
|
117
|
-
}
|
|
118
|
-
function normalizeScrollback(value) {
|
|
119
|
-
if (value === undefined || !Number.isFinite(value))
|
|
120
|
-
return DEFAULT_SCROLLBACK;
|
|
121
|
-
return Math.max(0, Math.trunc(value));
|
|
122
|
-
}
|
|
123
|
-
function normalizeReplayHistoryLength(cols, rows, scrollback) {
|
|
124
|
-
const visibleCells = Math.max(MIN_SIZE, cols) * Math.max(MIN_SIZE, rows + scrollback + 1);
|
|
125
|
-
return Math.min(MAX_REPLAY_HISTORY_LENGTH, Math.max(MIN_REPLAY_HISTORY_LENGTH, visibleCells * 4));
|
|
126
|
-
}
|
|
127
|
-
function decodeInput(value) {
|
|
128
|
-
if (typeof value === "string")
|
|
129
|
-
return value;
|
|
130
|
-
return new TextDecoder("utf-8", { fatal: false }).decode(value);
|
|
131
|
-
}
|
|
132
|
-
function sanitizeString(value) {
|
|
133
|
-
let output = "";
|
|
134
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
135
|
-
const code = value.charCodeAt(index);
|
|
136
|
-
if (code >= 0xd800 && code <= 0xdbff) {
|
|
137
|
-
const next = value.charCodeAt(index + 1);
|
|
138
|
-
if (next >= 0xdc00 && next <= 0xdfff) {
|
|
139
|
-
output += value[index] + value[index + 1];
|
|
140
|
-
index += 1;
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
output += "\uFFFD";
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
else if (code >= 0xdc00 && code <= 0xdfff) {
|
|
147
|
-
output += "\uFFFD";
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
output += value[index];
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return output;
|
|
154
|
-
}
|
|
155
278
|
//# sourceMappingURL=screen.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen.js","sourceRoot":"","sources":["../src/screen.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Terminal as XtermTerminalType } from \"@xterm/headless\";\nimport xterm from \"@xterm/headless\";\n\nexport interface TerminalScreenOptions {\n\treadonly cols?: number;\n\treadonly rows?: number;\n\treadonly scrollback?: number;\n}\n\nexport interface TerminalScreenSnapshot {\n\treadonly cols: number;\n\treadonly rows: number;\n\treadonly visibleGrid: readonly string[];\n\treadonly scrollback: readonly string[];\n\treadonly cursor: {\n\t\treadonly x: number;\n\t\treadonly y: number;\n\t};\n}\n\nconst XtermTerminal = xterm.Terminal;\nconst DEFAULT_COLS = 80;\nconst DEFAULT_ROWS = 24;\nconst DEFAULT_SCROLLBACK = 1000;\nconst MIN_SIZE = 1;\nconst MAX_SIZE = 10000;\nconst MIN_REPLAY_HISTORY_LENGTH = 4096;\nconst MAX_REPLAY_HISTORY_LENGTH = 1_000_000;\n\nexport class TerminalScreen {\n\tprivate terminal: XtermTerminalType;\n\tprivate readonly history: string[] = [];\n\tprivate historyLength = 0;\n\tprivate readonly maxReplayHistoryLength: number;\n\tprivate readonly scrollback: number;\n\n\tconstructor(options: TerminalScreenOptions = {}) {\n\t\tconst cols = normalizeDimension(options.cols, DEFAULT_COLS);\n\t\tconst rows = normalizeDimension(options.rows, DEFAULT_ROWS);\n\t\tthis.scrollback = normalizeScrollback(options.scrollback);\n\t\tthis.maxReplayHistoryLength = normalizeReplayHistoryLength(cols, rows, this.scrollback);\n\t\tthis.terminal = this.createTerminal(cols, rows);\n\t}\n\n\tfeed(data: string | Uint8Array): Promise<void> {\n\t\tconst payload = decodeInput(data);\n\t\tconst sanitizedPayload = sanitizeString(payload);\n\t\tif (sanitizedPayload.length > 0) this.appendHistory(sanitizedPayload);\n\t\treturn this.write(payload);\n\t}\n\n\tresize(cols: number, rows: number): Promise<void> {\n\t\tconst nextCols = normalizeDimension(cols, this.terminal.cols);\n\t\tconst nextRows = normalizeDimension(rows, this.terminal.rows);\n\t\tthis.terminal.dispose();\n\t\tthis.terminal = this.createTerminal(nextCols, nextRows);\n\t\treturn this.write(this.history.join(\"\"));\n\t}\n\n\tflush(): Promise<void> {\n\t\treturn this.write(\"\");\n\t}\n\n\tsnapshot(): TerminalScreenSnapshot {\n\t\tconst buffer = this.terminal.buffer.active;\n\t\tconst viewportStart = buffer.viewportY;\n\t\tconst visibleGrid: string[] = [];\n\t\tconst scrollback: string[] = [];\n\t\tconst scrollbackStart = Math.max(0, viewportStart - this.scrollback);\n\n\t\tfor (let lineIndex = scrollbackStart; lineIndex < viewportStart; lineIndex += 1) {\n\t\t\tscrollback.push(readLine(buffer, lineIndex));\n\t\t}\n\t\tfor (let row = 0; row < this.terminal.rows; row += 1) {\n\t\t\tvisibleGrid.push(readLine(buffer, viewportStart + row));\n\t\t}\n\n\t\treturn {\n\t\t\tcols: this.terminal.cols,\n\t\t\trows: this.terminal.rows,\n\t\t\tvisibleGrid,\n\t\t\tscrollback,\n\t\t\tcursor: {\n\t\t\t\tx: buffer.cursorX,\n\t\t\t\ty: buffer.cursorY,\n\t\t\t},\n\t\t};\n\t}\n\n\tdispose(): void {\n\t\tthis.terminal.dispose();\n\t}\n\n\tprivate createTerminal(cols: number, rows: number): XtermTerminalType {\n\t\treturn new XtermTerminal({\n\t\t\tcols,\n\t\t\trows,\n\t\t\tscrollback: this.scrollback,\n\t\t\tdisableStdin: true,\n\t\t\tallowProposedApi: true,\n\t\t\tlogLevel: \"off\",\n\t\t});\n\t}\n\n\tprivate write(payload: string): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tthis.terminal.write(payload, resolve);\n\t\t\t} catch (error) {\n\t\t\t\tconst sanitizedPayload = sanitizeString(payload);\n\t\t\t\tif (sanitizedPayload === payload) {\n\t\t\t\t\treject(error instanceof Error ? error : new Error(String(error)));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.terminal.write(sanitizedPayload, resolve);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate appendHistory(payload: string): void {\n\t\tthis.history.push(payload);\n\t\tthis.historyLength += payload.length;\n\t\tthis.trimHistory();\n\t}\n\n\tprivate trimHistory(): void {\n\t\twhile (this.historyLength > this.maxReplayHistoryLength && this.history.length > 1) {\n\t\t\tconst removed = this.history.shift();\n\t\t\tif (removed === undefined) return;\n\t\t\tthis.historyLength -= removed.length;\n\t\t}\n\n\t\tif (this.historyLength <= this.maxReplayHistoryLength) return;\n\t\tconst [onlyChunk] = this.history;\n\t\tif (onlyChunk === undefined) return;\n\t\tconst trimmed = sanitizeString(onlyChunk.slice(-this.maxReplayHistoryLength));\n\t\tthis.history[0] = trimmed;\n\t\tthis.historyLength = trimmed.length;\n\t}\n}\n\nfunction readLine(buffer: XtermTerminalType[\"buffer\"][\"active\"], lineIndex: number): string {\n\treturn buffer.getLine(lineIndex)?.translateToString(true) ?? \"\";\n}\n\nfunction normalizeDimension(value: number | undefined, fallback: number): number {\n\tif (value === undefined || !Number.isFinite(value)) return fallback;\n\treturn Math.min(MAX_SIZE, Math.max(MIN_SIZE, Math.trunc(value)));\n}\n\nfunction normalizeScrollback(value: number | undefined): number {\n\tif (value === undefined || !Number.isFinite(value)) return DEFAULT_SCROLLBACK;\n\treturn Math.max(0, Math.trunc(value));\n}\n\nfunction normalizeReplayHistoryLength(cols: number, rows: number, scrollback: number): number {\n\tconst visibleCells = Math.max(MIN_SIZE, cols) * Math.max(MIN_SIZE, rows + scrollback + 1);\n\treturn Math.min(MAX_REPLAY_HISTORY_LENGTH, Math.max(MIN_REPLAY_HISTORY_LENGTH, visibleCells * 4));\n}\n\nfunction decodeInput(value: string | Uint8Array): string {\n\tif (typeof value === \"string\") return value;\n\treturn new TextDecoder(\"utf-8\", { fatal: false }).decode(value);\n}\n\nfunction sanitizeString(value: string): string {\n\tlet output = \"\";\n\tfor (let index = 0; index < value.length; index += 1) {\n\t\tconst code = value.charCodeAt(index);\n\t\tif (code >= 0xd800 && code <= 0xdbff) {\n\t\t\tconst next = value.charCodeAt(index + 1);\n\t\t\tif (next >= 0xdc00 && next <= 0xdfff) {\n\t\t\t\toutput += value[index] + value[index + 1];\n\t\t\t\tindex += 1;\n\t\t\t} else {\n\t\t\t\toutput += \"\\uFFFD\";\n\t\t\t}\n\t\t} else if (code >= 0xdc00 && code <= 0xdfff) {\n\t\t\toutput += \"\\uFFFD\";\n\t\t} else {\n\t\t\toutput += value[index];\n\t\t}\n\t}\n\treturn output;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"screen.js","sourceRoot":"","sources":["../src/screen.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Terminal as XtermTerminalType } from \"@xterm/headless\";\nimport xterm from \"@xterm/headless\";\nimport {\n\tMAX_PENDING_WRITE_CHARS,\n\ttype ReplayOperation,\n\ttype ResizeOperation,\n\ttype ScreenOperation,\n\tsettleOperation,\n\tsharedSettler,\n} from \"./screen-operations.ts\";\n\nimport {\n\tdecodeInput,\n\tnormalizeDimension,\n\tnormalizeReplayHistoryLength,\n\tnormalizeScrollback,\n\treadLine,\n\tsanitizeString,\n} from \"./screen-text.ts\";\n\nexport interface TerminalScreenOptions {\n\treadonly cols?: number;\n\treadonly rows?: number;\n\treadonly scrollback?: number;\n}\n\nexport interface TerminalScreenSnapshot {\n\treadonly cols: number;\n\treadonly rows: number;\n\treadonly visibleGrid: readonly string[];\n\treadonly scrollback: readonly string[];\n\treadonly cursor: {\n\t\treadonly x: number;\n\t\treadonly y: number;\n\t};\n}\n\nconst XtermTerminal = xterm.Terminal;\nconst DEFAULT_COLS = 80;\nconst DEFAULT_ROWS = 24;\n\n/**\n * Headless xterm screen model with serialized, flow-controlled writes.\n *\n * Every terminal mutation (feed, resize, backlog replay) runs through one\n * FIFO queue that awaits xterm's parse callback before issuing the next\n * write, so xterm's pending-write watermark can never be exceeded. When the\n * queued backlog outgrows {@link MAX_PENDING_WRITE_CHARS}, the queued writes\n * collapse into a single bounded history replay that reconstructs the same\n * screen state. After {@link TerminalScreen.dispose}, queued and future\n * operations settle as resolved no-ops; a terminal is never created after\n * disposal.\n */\nexport class TerminalScreen {\n\tprivate terminal: XtermTerminalType;\n\tprivate readonly history: string[] = [];\n\tprivate historyLength = 0;\n\tprivate readonly operations: ScreenOperation[] = [];\n\tprivate pendingChars = 0;\n\tprivate draining = false;\n\tprivate disposed = false;\n\tprivate notifyDisposed: () => void = () => undefined;\n\tprivate readonly whenDisposed: Promise<void>;\n\tprivate readonly maxReplayHistoryLength: number;\n\tprivate readonly scrollback: number;\n\n\tconstructor(options: TerminalScreenOptions = {}) {\n\t\tconst cols = normalizeDimension(options.cols, DEFAULT_COLS);\n\t\tconst rows = normalizeDimension(options.rows, DEFAULT_ROWS);\n\t\tthis.scrollback = normalizeScrollback(options.scrollback);\n\t\tthis.maxReplayHistoryLength = normalizeReplayHistoryLength(cols, rows, this.scrollback);\n\t\tthis.whenDisposed = new Promise((resolve) => {\n\t\t\tthis.notifyDisposed = resolve;\n\t\t});\n\t\tthis.terminal = this.createTerminal(cols, rows);\n\t}\n\n\tfeed(data: string | Uint8Array): Promise<void> {\n\t\tif (this.disposed) return Promise.resolve();\n\t\tconst payload = decodeInput(data);\n\t\tconst sanitizedPayload = sanitizeString(payload);\n\t\tif (sanitizedPayload.length > 0) this.appendHistory(sanitizedPayload);\n\t\tif (this.pendingChars + payload.length > MAX_PENDING_WRITE_CHARS) {\n\t\t\treturn this.coalesceFeedIntoReplay(payload);\n\t\t}\n\t\tthis.pendingChars += payload.length;\n\t\tconst operation: ScreenOperation = { kind: \"write\", payload, settled: null, settlers: [] };\n\t\treturn this.enqueue(operation, sharedSettler(operation));\n\t}\n\n\tresize(cols: number, rows: number): Promise<void> {\n\t\tif (this.disposed) return Promise.resolve();\n\t\tconst nextCols = normalizeDimension(cols, this.terminal.cols);\n\t\tconst nextRows = normalizeDimension(rows, this.terminal.rows);\n\t\tconst snapshot = this.history.join(\"\");\n\t\tconst tail = this.operations[this.operations.length - 1];\n\t\tif (tail !== undefined && tail.kind === \"resize\") {\n\t\t\ttail.cols = nextCols;\n\t\t\ttail.rows = nextRows;\n\t\t\tthis.pendingChars += snapshot.length - tail.replay.length;\n\t\t\ttail.replay = snapshot;\n\t\t\treturn sharedSettler(tail);\n\t\t}\n\t\tif (this.pendingChars + snapshot.length > MAX_PENDING_WRITE_CHARS) {\n\t\t\treturn this.coalesceQueueIntoResize(nextCols, nextRows, snapshot);\n\t\t}\n\t\tconst operation: ResizeOperation = {\n\t\t\tkind: \"resize\",\n\t\t\tcols: nextCols,\n\t\t\trows: nextRows,\n\t\t\treplay: snapshot,\n\t\t\tsettled: null,\n\t\t\tsettlers: [],\n\t\t};\n\t\tthis.pendingChars += snapshot.length;\n\t\treturn this.enqueue(operation, sharedSettler(operation));\n\t}\n\n\t/**\n\t * Resolves once everything fed before this call has been parsed. Attaches\n\t * to the queue tail instead of enqueueing a marker so a flush can never\n\t * split a tail replay (which would let over-cap feeds mint unbounded new\n\t * replay operations); only an empty queue enqueues a zero-length write.\n\t */\n\tflush(): Promise<void> {\n\t\tif (this.disposed) return Promise.resolve();\n\t\tconst tail = this.operations[this.operations.length - 1];\n\t\tif (tail !== undefined) return sharedSettler(tail);\n\t\tconst operation: ScreenOperation = { kind: \"write\", payload: \"\", settled: null, settlers: [] };\n\t\treturn this.enqueue(operation, sharedSettler(operation));\n\t}\n\n\tsnapshot(): TerminalScreenSnapshot {\n\t\tconst buffer = this.terminal.buffer.active;\n\t\tconst viewportStart = buffer.viewportY;\n\t\tconst visibleGrid: string[] = [];\n\t\tconst scrollback: string[] = [];\n\t\tconst scrollbackStart = Math.max(0, viewportStart - this.scrollback);\n\n\t\tfor (let lineIndex = scrollbackStart; lineIndex < viewportStart; lineIndex += 1) {\n\t\t\tscrollback.push(readLine(buffer, lineIndex));\n\t\t}\n\t\tfor (let row = 0; row < this.terminal.rows; row += 1) {\n\t\t\tvisibleGrid.push(readLine(buffer, viewportStart + row));\n\t\t}\n\n\t\treturn {\n\t\t\tcols: this.terminal.cols,\n\t\t\trows: this.terminal.rows,\n\t\t\tvisibleGrid,\n\t\t\tscrollback,\n\t\t\tcursor: {\n\t\t\t\tx: buffer.cursorX,\n\t\t\t\ty: buffer.cursorY,\n\t\t\t},\n\t\t};\n\t}\n\n\tdispose(): void {\n\t\tif (this.disposed) return;\n\t\tthis.disposed = true;\n\t\tthis.notifyDisposed();\n\t\tconst pending = this.operations.splice(0, this.operations.length);\n\t\tthis.pendingChars = 0;\n\t\tfor (const operation of pending) {\n\t\t\tsettleOperation(operation.settlers, null);\n\t\t}\n\t\tthis.terminal.dispose();\n\t}\n\n\tprivate createTerminal(cols: number, rows: number): XtermTerminalType {\n\t\treturn new XtermTerminal({\n\t\t\tcols,\n\t\t\trows,\n\t\t\tscrollback: this.scrollback,\n\t\t\tdisableStdin: true,\n\t\t\tallowProposedApi: true,\n\t\t\tlogLevel: \"off\",\n\t\t});\n\t}\n\n\tprivate enqueue(operation: ScreenOperation, settled: Promise<void>): Promise<void> {\n\t\tthis.operations.push(operation);\n\t\tvoid this.drain();\n\t\treturn settled;\n\t}\n\n\t/**\n\t * Route an over-cap feed to the queue's tail replay instead of enqueueing\n\t * another write. Replay payloads are owned snapshot strings (immune to\n\t * history trimming) bounded to the replay budget, and every coalesced feed\n\t * shares the tail's memoized promise, so a flood cannot grow the queue,\n\t * its payload memory, or its settler memory past the configured bounds.\n\t */\n\tprivate coalesceFeedIntoReplay(payload: string): Promise<void> {\n\t\tconst tail = this.operations[this.operations.length - 1];\n\t\tif (tail !== undefined && tail.kind === \"replay\") {\n\t\t\tconst previousLength = tail.payload.length;\n\t\t\ttail.payload = this.boundReplayPayload(tail.payload + payload);\n\t\t\tthis.pendingChars += tail.payload.length - previousLength;\n\t\t\treturn sharedSettler(tail);\n\t\t}\n\t\tconst operation: ReplayOperation = {\n\t\t\tkind: \"replay\",\n\t\t\tpayload: this.history.join(\"\"),\n\t\t\tsettled: null,\n\t\t\tsettlers: [],\n\t\t};\n\t\tthis.pendingChars += operation.payload.length;\n\t\treturn this.enqueue(operation, sharedSettler(operation));\n\t}\n\n\t/**\n\t * A resize whose snapshot would push the queued payload past the cap\n\t * collapses the whole queue into one resize at the latest dimensions:\n\t * every dropped operation's payload is already covered by the bounded\n\t * history snapshot, and their settlers settle with this operation.\n\t */\n\tprivate coalesceQueueIntoResize(cols: number, rows: number, snapshot: string): Promise<void> {\n\t\tconst operation: ResizeOperation = {\n\t\t\tkind: \"resize\",\n\t\t\tcols,\n\t\t\trows,\n\t\t\treplay: snapshot,\n\t\t\tsettled: null,\n\t\t\tsettlers: [],\n\t\t};\n\t\tfor (const queued of this.operations.splice(0, this.operations.length)) {\n\t\t\tfor (const settler of queued.settlers) operation.settlers.push(settler);\n\t\t\tqueued.settlers.length = 0;\n\t\t}\n\t\tthis.pendingChars = snapshot.length;\n\t\treturn this.enqueue(operation, sharedSettler(operation));\n\t}\n\n\tprivate boundReplayPayload(payload: string): string {\n\t\tif (payload.length <= this.maxReplayHistoryLength) return payload;\n\t\treturn sanitizeString(payload.slice(-this.maxReplayHistoryLength));\n\t}\n\n\tprivate async drain(): Promise<void> {\n\t\tif (this.draining) return;\n\t\tthis.draining = true;\n\t\ttry {\n\t\t\twhile (!this.disposed) {\n\t\t\t\tconst operation = this.operations.shift();\n\t\t\t\tif (operation === undefined) return;\n\t\t\t\tthis.pendingChars -= operation.kind === \"resize\" ? operation.replay.length : operation.payload.length;\n\t\t\t\ttry {\n\t\t\t\t\tawait this.run(operation);\n\t\t\t\t\tsettleOperation(operation.settlers, null);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tsettleOperation(operation.settlers, error instanceof Error ? error : new Error(String(error)));\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.draining = false;\n\t\t}\n\t}\n\n\tprivate async run(operation: ScreenOperation): Promise<void> {\n\t\tif (this.disposed) return;\n\t\tswitch (operation.kind) {\n\t\t\tcase \"write\":\n\t\t\t\tawait this.raceDisposal(this.write(operation.payload));\n\t\t\t\treturn;\n\t\t\tcase \"replay\":\n\t\t\t\tthis.terminal.reset();\n\t\t\t\tawait this.raceDisposal(this.write(operation.payload));\n\t\t\t\treturn;\n\t\t\tcase \"resize\":\n\t\t\t\tthis.terminal.dispose();\n\t\t\t\tthis.terminal = this.createTerminal(operation.cols, operation.rows);\n\t\t\t\tawait this.raceDisposal(this.write(operation.replay));\n\t\t\t\treturn;\n\t\t}\n\t}\n\n\t/** A disposed terminal may never invoke its parse callback; do not hang. */\n\tprivate raceDisposal(written: Promise<void>): Promise<void> {\n\t\treturn Promise.race([written, this.whenDisposed]);\n\t}\n\n\tprivate write(payload: string): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tthis.terminal.write(payload, resolve);\n\t\t\t} catch (error) {\n\t\t\t\tconst sanitizedPayload = sanitizeString(payload);\n\t\t\t\tif (sanitizedPayload === payload) {\n\t\t\t\t\treject(error instanceof Error ? error : new Error(String(error)));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.terminal.write(sanitizedPayload, resolve);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate appendHistory(payload: string): void {\n\t\tthis.history.push(payload);\n\t\tthis.historyLength += payload.length;\n\t\tthis.trimHistory();\n\t}\n\n\tprivate trimHistory(): void {\n\t\twhile (this.historyLength > this.maxReplayHistoryLength && this.history.length > 1) {\n\t\t\tconst removed = this.history.shift();\n\t\t\tif (removed === undefined) return;\n\t\t\tthis.historyLength -= removed.length;\n\t\t}\n\n\t\tif (this.historyLength <= this.maxReplayHistoryLength) return;\n\t\tconst [onlyChunk] = this.history;\n\t\tif (onlyChunk === undefined) return;\n\t\tconst trimmed = sanitizeString(onlyChunk.slice(-this.maxReplayHistoryLength));\n\t\tthis.history[0] = trimmed;\n\t\tthis.historyLength = trimmed.length;\n\t}\n}\n"]}
|
|
@@ -39,6 +39,10 @@ export interface EditorTheme {
|
|
|
39
39
|
export interface EditorOptions {
|
|
40
40
|
paddingX?: number;
|
|
41
41
|
autocompleteMaxVisible?: number;
|
|
42
|
+
/** Test seam for terminal-specific input normalization. */
|
|
43
|
+
terminalEnvironment?: NodeJS.ProcessEnv;
|
|
44
|
+
terminalPlatform?: NodeJS.Platform;
|
|
45
|
+
terminalSocketExists?: (socketPath: string) => boolean;
|
|
42
46
|
}
|
|
43
47
|
export declare class Editor implements Component, Focusable {
|
|
44
48
|
private state;
|
|
@@ -47,6 +51,9 @@ export declare class Editor implements Component, Focusable {
|
|
|
47
51
|
protected tui: TUI;
|
|
48
52
|
private theme;
|
|
49
53
|
private paddingX;
|
|
54
|
+
private terminalEnvironment?;
|
|
55
|
+
private terminalPlatform?;
|
|
56
|
+
private terminalSocketExists?;
|
|
50
57
|
private lastWidth;
|
|
51
58
|
private scrollOffset;
|
|
52
59
|
borderColor: (str: string) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/components/editor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAA2B,MAAM,oBAAoB,CAAC;AACxF,OAAO,EACN,KAAK,gBAAgB,EAOrB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EACN,KAAK,gBAAgB,EAKrB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/components/editor.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { getKeybindings } from "../keybindings.js";
|
|
|
3
3
|
import { decodePrintableKey, matchesKey } from "../keys.js";
|
|
4
4
|
import { KillRing } from "../kill-ring.js";
|
|
5
5
|
import { isPasteMarker, PasteMarkerRegistry, pasteMarkerId, segmentWithMarkers, } from "../paste-markers.js";
|
|
6
|
+
import { normalizeWarpWslShiftEnterInput } from "../terminal.js";
|
|
6
7
|
import { CURSOR_MARKER } from "../tui.js";
|
|
7
8
|
import { UndoStack } from "../undo-stack.js";
|
|
8
9
|
import { cjkBreakRegex, getGraphemeSegmenter, getWordSegmenter, isWhitespaceChar, sliceByColumn, visibleWidth, } from "../utils.js";
|
|
@@ -246,6 +247,9 @@ export class Editor {
|
|
|
246
247
|
this.borderColor = theme.borderColor;
|
|
247
248
|
const paddingX = options.paddingX ?? 0;
|
|
248
249
|
this.paddingX = Number.isFinite(paddingX) ? Math.max(0, Math.floor(paddingX)) : 0;
|
|
250
|
+
this.terminalEnvironment = options.terminalEnvironment;
|
|
251
|
+
this.terminalPlatform = options.terminalPlatform;
|
|
252
|
+
this.terminalSocketExists = options.terminalSocketExists;
|
|
249
253
|
const maxVisible = options.autocompleteMaxVisible ?? 5;
|
|
250
254
|
this.autocompleteMaxVisible = Number.isFinite(maxVisible) ? Math.max(3, Math.min(20, Math.floor(maxVisible))) : 5;
|
|
251
255
|
}
|
|
@@ -542,6 +546,7 @@ export class Editor {
|
|
|
542
546
|
return result;
|
|
543
547
|
}
|
|
544
548
|
handleInput(data) {
|
|
549
|
+
data = normalizeWarpWslShiftEnterInput(data, this.terminalEnvironment, this.terminalPlatform, this.terminalSocketExists);
|
|
545
550
|
const kb = getKeybindings();
|
|
546
551
|
// Handle character jump mode (awaiting next character to jump to)
|
|
547
552
|
if (this.jumpMode !== null) {
|