@getpaseo/server 0.1.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/.env.example +20 -0
- package/README.md +107 -0
- package/agent-prompt.md +339 -0
- package/dist/scripts/daemon-runner.js +32 -0
- package/dist/scripts/daemon-runner.js.map +1 -0
- package/dist/scripts/dev-runner.js +19 -0
- package/dist/scripts/dev-runner.js.map +1 -0
- package/dist/scripts/mcp-stdio-socket-bridge-cli.mjs +62 -0
- package/dist/scripts/supervisor.js +95 -0
- package/dist/scripts/supervisor.js.map +1 -0
- package/dist/server/client/daemon-client.d.ts +383 -0
- package/dist/server/client/daemon-client.d.ts.map +1 -0
- package/dist/server/client/daemon-client.js +2443 -0
- package/dist/server/client/daemon-client.js.map +1 -0
- package/dist/server/server/agent/activity-curator.d.ts +8 -0
- package/dist/server/server/agent/activity-curator.d.ts.map +1 -0
- package/dist/server/server/agent/activity-curator.js +228 -0
- package/dist/server/server/agent/activity-curator.js.map +1 -0
- package/dist/server/server/agent/agent-management-mcp.d.ts +34 -0
- package/dist/server/server/agent/agent-management-mcp.d.ts.map +1 -0
- package/dist/server/server/agent/agent-management-mcp.js +619 -0
- package/dist/server/server/agent/agent-management-mcp.js.map +1 -0
- package/dist/server/server/agent/agent-manager.d.ts +182 -0
- package/dist/server/server/agent/agent-manager.d.ts.map +1 -0
- package/dist/server/server/agent/agent-manager.js +1066 -0
- package/dist/server/server/agent/agent-manager.js.map +1 -0
- package/dist/server/server/agent/agent-metadata-generator.d.ts +29 -0
- package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -0
- package/dist/server/server/agent/agent-metadata-generator.js +157 -0
- package/dist/server/server/agent/agent-metadata-generator.js.map +1 -0
- package/dist/server/server/agent/agent-projections.d.ts +12 -0
- package/dist/server/server/agent/agent-projections.d.ts.map +1 -0
- package/dist/server/server/agent/agent-projections.js +238 -0
- package/dist/server/server/agent/agent-projections.js.map +1 -0
- package/dist/server/server/agent/agent-response-loop.d.ts +32 -0
- package/dist/server/server/agent/agent-response-loop.d.ts.map +1 -0
- package/dist/server/server/agent/agent-response-loop.js +224 -0
- package/dist/server/server/agent/agent-response-loop.js.map +1 -0
- package/dist/server/server/agent/agent-sdk-types.d.ts +360 -0
- package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -0
- package/dist/server/server/agent/agent-sdk-types.js +2 -0
- package/dist/server/server/agent/agent-sdk-types.js.map +1 -0
- package/dist/server/server/agent/agent-storage.d.ts +187 -0
- package/dist/server/server/agent/agent-storage.d.ts.map +1 -0
- package/dist/server/server/agent/agent-storage.js +328 -0
- package/dist/server/server/agent/agent-storage.js.map +1 -0
- package/dist/server/server/agent/audio-utils.d.ts +3 -0
- package/dist/server/server/agent/audio-utils.d.ts.map +1 -0
- package/dist/server/server/agent/audio-utils.js +19 -0
- package/dist/server/server/agent/audio-utils.js.map +1 -0
- package/dist/server/server/agent/dictation-debug.d.ts +13 -0
- package/dist/server/server/agent/dictation-debug.d.ts.map +1 -0
- package/dist/server/server/agent/dictation-debug.js +50 -0
- package/dist/server/server/agent/dictation-debug.js.map +1 -0
- package/dist/server/server/agent/llm-openai.d.ts +7 -0
- package/dist/server/server/agent/llm-openai.d.ts.map +1 -0
- package/dist/server/server/agent/llm-openai.js +8 -0
- package/dist/server/server/agent/llm-openai.js.map +1 -0
- package/dist/server/server/agent/mcp-server.d.ts +26 -0
- package/dist/server/server/agent/mcp-server.d.ts.map +1 -0
- package/dist/server/server/agent/mcp-server.js +762 -0
- package/dist/server/server/agent/mcp-server.js.map +1 -0
- package/dist/server/server/agent/model-resolver.d.ts +11 -0
- package/dist/server/server/agent/model-resolver.d.ts.map +1 -0
- package/dist/server/server/agent/model-resolver.js +21 -0
- package/dist/server/server/agent/model-resolver.js.map +1 -0
- package/dist/server/server/agent/orchestrator-instructions.d.ts +7 -0
- package/dist/server/server/agent/orchestrator-instructions.d.ts.map +1 -0
- package/dist/server/server/agent/orchestrator-instructions.js +51 -0
- package/dist/server/server/agent/orchestrator-instructions.js.map +1 -0
- package/dist/server/server/agent/orchestrator.d.ts +12 -0
- package/dist/server/server/agent/orchestrator.d.ts.map +1 -0
- package/dist/server/server/agent/orchestrator.js +12 -0
- package/dist/server/server/agent/orchestrator.js.map +1 -0
- package/dist/server/server/agent/pcm16-resampler.d.ts +14 -0
- package/dist/server/server/agent/pcm16-resampler.d.ts.map +1 -0
- package/dist/server/server/agent/pcm16-resampler.js +63 -0
- package/dist/server/server/agent/pcm16-resampler.js.map +1 -0
- package/dist/server/server/agent/provider-launch-config.d.ts +139 -0
- package/dist/server/server/agent/provider-launch-config.d.ts.map +1 -0
- package/dist/server/server/agent/provider-launch-config.js +83 -0
- package/dist/server/server/agent/provider-launch-config.js.map +1 -0
- package/dist/server/server/agent/provider-manifest.d.ts +20 -0
- package/dist/server/server/agent/provider-manifest.d.ts.map +1 -0
- package/dist/server/server/agent/provider-manifest.js +97 -0
- package/dist/server/server/agent/provider-manifest.js.map +1 -0
- package/dist/server/server/agent/provider-registry.d.ts +18 -0
- package/dist/server/server/agent/provider-registry.d.ts.map +1 -0
- package/dist/server/server/agent/provider-registry.js +45 -0
- package/dist/server/server/agent/provider-registry.js.map +1 -0
- package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts +3 -0
- package/dist/server/server/agent/providers/claude/tool-call-detail-parser.d.ts.map +1 -0
- package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js +42 -0
- package/dist/server/server/agent/providers/claude/tool-call-detail-parser.js.map +1 -0
- package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts +16 -0
- package/dist/server/server/agent/providers/claude/tool-call-mapper.d.ts.map +1 -0
- package/dist/server/server/agent/providers/claude/tool-call-mapper.js +73 -0
- package/dist/server/server/agent/providers/claude/tool-call-mapper.js.map +1 -0
- package/dist/server/server/agent/providers/claude-agent.d.ts +35 -0
- package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -0
- package/dist/server/server/agent/providers/claude-agent.js +2056 -0
- package/dist/server/server/agent/providers/claude-agent.js.map +1 -0
- package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts +13 -0
- package/dist/server/server/agent/providers/codex/tool-call-detail-parser.d.ts.map +1 -0
- package/dist/server/server/agent/providers/codex/tool-call-detail-parser.js +67 -0
- package/dist/server/server/agent/providers/codex/tool-call-detail-parser.js.map +1 -0
- package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts +15 -0
- package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts.map +1 -0
- package/dist/server/server/agent/providers/codex/tool-call-mapper.js +640 -0
- package/dist/server/server/agent/providers/codex/tool-call-mapper.js.map +1 -0
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +34 -0
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -0
- package/dist/server/server/agent/providers/codex-app-server-agent.js +2476 -0
- package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -0
- package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts +9 -0
- package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts.map +1 -0
- package/dist/server/server/agent/providers/codex-rollout-timeline.js +486 -0
- package/dist/server/server/agent/providers/codex-rollout-timeline.js.map +1 -0
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts +3 -0
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts.map +1 -0
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +33 -0
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js.map +1 -0
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts +13 -0
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.d.ts.map +1 -0
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.js +75 -0
- package/dist/server/server/agent/providers/opencode/tool-call-mapper.js.map +1 -0
- package/dist/server/server/agent/providers/opencode-agent.d.ts +37 -0
- package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -0
- package/dist/server/server/agent/providers/opencode-agent.js +822 -0
- package/dist/server/server/agent/providers/opencode-agent.js.map +1 -0
- package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +1363 -0
- package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts.map +1 -0
- package/dist/server/server/agent/providers/tool-call-detail-primitives.js +534 -0
- package/dist/server/server/agent/providers/tool-call-detail-primitives.js.map +1 -0
- package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +18 -0
- package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts.map +1 -0
- package/dist/server/server/agent/providers/tool-call-mapper-utils.js +119 -0
- package/dist/server/server/agent/providers/tool-call-mapper-utils.js.map +1 -0
- package/dist/server/server/agent/recordings-debug.d.ts +3 -0
- package/dist/server/server/agent/recordings-debug.d.ts.map +1 -0
- package/dist/server/server/agent/recordings-debug.js +19 -0
- package/dist/server/server/agent/recordings-debug.js.map +1 -0
- package/dist/server/server/agent/stt-debug.d.ts +10 -0
- package/dist/server/server/agent/stt-debug.d.ts.map +1 -0
- package/dist/server/server/agent/stt-debug.js +33 -0
- package/dist/server/server/agent/stt-debug.js.map +1 -0
- package/dist/server/server/agent/stt-manager.d.ts +32 -0
- package/dist/server/server/agent/stt-manager.d.ts.map +1 -0
- package/dist/server/server/agent/stt-manager.js +231 -0
- package/dist/server/server/agent/stt-manager.js.map +1 -0
- package/dist/server/server/agent/system-prompt.d.ts +3 -0
- package/dist/server/server/agent/system-prompt.d.ts.map +1 -0
- package/dist/server/server/agent/system-prompt.js +19 -0
- package/dist/server/server/agent/system-prompt.js.map +1 -0
- package/dist/server/server/agent/tool-name-normalization.d.ts +7 -0
- package/dist/server/server/agent/tool-name-normalization.d.ts.map +1 -0
- package/dist/server/server/agent/tool-name-normalization.js +45 -0
- package/dist/server/server/agent/tool-name-normalization.js.map +1 -0
- package/dist/server/server/agent/tts-debug.d.ts +8 -0
- package/dist/server/server/agent/tts-debug.d.ts.map +1 -0
- package/dist/server/server/agent/tts-debug.js +24 -0
- package/dist/server/server/agent/tts-debug.js.map +1 -0
- package/dist/server/server/agent/tts-manager.d.ts +33 -0
- package/dist/server/server/agent/tts-manager.d.ts.map +1 -0
- package/dist/server/server/agent/tts-manager.js +261 -0
- package/dist/server/server/agent/tts-manager.js.map +1 -0
- package/dist/server/server/agent/wait-for-agent-tracker.d.ts +15 -0
- package/dist/server/server/agent/wait-for-agent-tracker.d.ts.map +1 -0
- package/dist/server/server/agent/wait-for-agent-tracker.js +53 -0
- package/dist/server/server/agent/wait-for-agent-tracker.js.map +1 -0
- package/dist/server/server/allowed-hosts.d.ts +13 -0
- package/dist/server/server/allowed-hosts.d.ts.map +1 -0
- package/dist/server/server/allowed-hosts.js +94 -0
- package/dist/server/server/allowed-hosts.js.map +1 -0
- package/dist/server/server/bootstrap.d.ts +49 -0
- package/dist/server/server/bootstrap.d.ts.map +1 -0
- package/dist/server/server/bootstrap.js +483 -0
- package/dist/server/server/bootstrap.js.map +1 -0
- package/dist/server/server/config.d.ts +13 -0
- package/dist/server/server/config.d.ts.map +1 -0
- package/dist/server/server/config.js +84 -0
- package/dist/server/server/config.js.map +1 -0
- package/dist/server/server/connection-offer.d.ts +19 -0
- package/dist/server/server/connection-offer.d.ts.map +1 -0
- package/dist/server/server/connection-offer.js +60 -0
- package/dist/server/server/connection-offer.js.map +1 -0
- package/dist/server/server/daemon-keypair.d.ts +8 -0
- package/dist/server/server/daemon-keypair.d.ts.map +1 -0
- package/dist/server/server/daemon-keypair.js +40 -0
- package/dist/server/server/daemon-keypair.js.map +1 -0
- package/dist/server/server/dictation/dictation-stream-manager.d.ts +76 -0
- package/dist/server/server/dictation/dictation-stream-manager.d.ts.map +1 -0
- package/dist/server/server/dictation/dictation-stream-manager.js +481 -0
- package/dist/server/server/dictation/dictation-stream-manager.js.map +1 -0
- package/dist/server/server/exports.d.ts +11 -0
- package/dist/server/server/exports.d.ts.map +1 -0
- package/dist/server/server/exports.js +11 -0
- package/dist/server/server/exports.js.map +1 -0
- package/dist/server/server/file-download/token-store.d.ts +25 -0
- package/dist/server/server/file-download/token-store.d.ts.map +1 -0
- package/dist/server/server/file-download/token-store.js +40 -0
- package/dist/server/server/file-download/token-store.js.map +1 -0
- package/dist/server/server/file-explorer/service.d.ts +41 -0
- package/dist/server/server/file-explorer/service.d.ts.map +1 -0
- package/dist/server/server/file-explorer/service.js +163 -0
- package/dist/server/server/file-explorer/service.js.map +1 -0
- package/dist/server/server/index.d.ts +2 -0
- package/dist/server/server/index.d.ts.map +1 -0
- package/dist/server/server/index.js +90 -0
- package/dist/server/server/index.js.map +1 -0
- package/dist/server/server/json-utils.d.ts +11 -0
- package/dist/server/server/json-utils.d.ts.map +1 -0
- package/dist/server/server/json-utils.js +45 -0
- package/dist/server/server/json-utils.js.map +1 -0
- package/dist/server/server/logger.d.ts +12 -0
- package/dist/server/server/logger.d.ts.map +1 -0
- package/dist/server/server/logger.js +29 -0
- package/dist/server/server/logger.js.map +1 -0
- package/dist/server/server/messages.d.ts +9 -0
- package/dist/server/server/messages.d.ts.map +1 -0
- package/dist/server/server/messages.js +29 -0
- package/dist/server/server/messages.js.map +1 -0
- package/dist/server/server/pairing-offer.d.ts +16 -0
- package/dist/server/server/pairing-offer.d.ts.map +1 -0
- package/dist/server/server/pairing-offer.js +45 -0
- package/dist/server/server/pairing-offer.js.map +1 -0
- package/dist/server/server/pairing-qr.d.ts +7 -0
- package/dist/server/server/pairing-qr.d.ts.map +1 -0
- package/dist/server/server/pairing-qr.js +45 -0
- package/dist/server/server/pairing-qr.js.map +1 -0
- package/dist/server/server/paseo-home.d.ts +2 -0
- package/dist/server/server/paseo-home.d.ts.map +1 -0
- package/dist/server/server/paseo-home.js +19 -0
- package/dist/server/server/paseo-home.js.map +1 -0
- package/dist/server/server/path-utils.d.ts +3 -0
- package/dist/server/server/path-utils.d.ts.map +1 -0
- package/dist/server/server/path-utils.js +20 -0
- package/dist/server/server/path-utils.js.map +1 -0
- package/dist/server/server/persisted-config.d.ts +500 -0
- package/dist/server/server/persisted-config.d.ts.map +1 -0
- package/dist/server/server/persisted-config.js +212 -0
- package/dist/server/server/persisted-config.js.map +1 -0
- package/dist/server/server/persistence-hooks.d.ts +24 -0
- package/dist/server/server/persistence-hooks.d.ts.map +1 -0
- package/dist/server/server/persistence-hooks.js +60 -0
- package/dist/server/server/persistence-hooks.js.map +1 -0
- package/dist/server/server/pid-lock.d.ts +19 -0
- package/dist/server/server/pid-lock.d.ts.map +1 -0
- package/dist/server/server/pid-lock.js +115 -0
- package/dist/server/server/pid-lock.js.map +1 -0
- package/dist/server/server/push/push-service.d.ts +21 -0
- package/dist/server/server/push/push-service.d.ts.map +1 -0
- package/dist/server/server/push/push-service.js +68 -0
- package/dist/server/server/push/push-service.js.map +1 -0
- package/dist/server/server/push/token-store.d.ts +18 -0
- package/dist/server/server/push/token-store.d.ts.map +1 -0
- package/dist/server/server/push/token-store.js +70 -0
- package/dist/server/server/push/token-store.js.map +1 -0
- package/dist/server/server/relay-transport.d.ts +22 -0
- package/dist/server/server/relay-transport.d.ts.map +1 -0
- package/dist/server/server/relay-transport.js +374 -0
- package/dist/server/server/relay-transport.js.map +1 -0
- package/dist/server/server/server-id.d.ts +17 -0
- package/dist/server/server/server-id.d.ts.map +1 -0
- package/dist/server/server/server-id.js +63 -0
- package/dist/server/server/server-id.js.map +1 -0
- package/dist/server/server/session.d.ts +360 -0
- package/dist/server/server/session.d.ts.map +1 -0
- package/dist/server/server/session.js +4615 -0
- package/dist/server/server/session.js.map +1 -0
- package/dist/server/server/speech/audio.d.ts +10 -0
- package/dist/server/server/speech/audio.d.ts.map +1 -0
- package/dist/server/server/speech/audio.js +101 -0
- package/dist/server/server/speech/audio.js.map +1 -0
- package/dist/server/server/speech/providers/local/config.d.ts +26 -0
- package/dist/server/server/speech/providers/local/config.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/config.js +93 -0
- package/dist/server/server/speech/providers/local/config.js.map +1 -0
- package/dist/server/server/speech/providers/local/models.d.ts +12 -0
- package/dist/server/server/speech/providers/local/models.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/models.js +18 -0
- package/dist/server/server/speech/providers/local/models.js.map +1 -0
- package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.d.ts +24 -0
- package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.js +422 -0
- package/dist/server/server/speech/providers/local/pocket/pocket-tts-onnx.js.map +1 -0
- package/dist/server/server/speech/providers/local/runtime.d.ts +30 -0
- package/dist/server/server/speech/providers/local/runtime.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/runtime.js +254 -0
- package/dist/server/server/speech/providers/local/runtime.js.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts +117 -0
- package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/model-catalog.js +166 -0
- package/dist/server/server/speech/providers/local/sherpa/model-catalog.js.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts +17 -0
- package/dist/server/server/speech/providers/local/sherpa/model-downloader.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/model-downloader.js +151 -0
- package/dist/server/server/speech/providers/local/sherpa/model-downloader.js.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts +28 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js +68 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-offline-recognizer.js.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.d.ts +37 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.js +79 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-online-recognizer.js.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.d.ts +7 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.js +11 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-loader.js.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts +7 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js +44 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.js.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.d.ts +28 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js +131 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-realtime-session.js.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts +21 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js +132 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-parakeet-stt.js.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.d.ts +23 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.js +112 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-realtime-session.js.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.d.ts +23 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.js +140 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-stt.js.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts +21 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.d.ts.map +1 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js +95 -0
- package/dist/server/server/speech/providers/local/sherpa/sherpa-tts.js.map +1 -0
- package/dist/server/server/speech/providers/openai/config.d.ts +22 -0
- package/dist/server/server/speech/providers/openai/config.d.ts.map +1 -0
- package/dist/server/server/speech/providers/openai/config.js +94 -0
- package/dist/server/server/speech/providers/openai/config.js.map +1 -0
- package/dist/server/server/speech/providers/openai/realtime-transcription-session.d.ts +42 -0
- package/dist/server/server/speech/providers/openai/realtime-transcription-session.d.ts.map +1 -0
- package/dist/server/server/speech/providers/openai/realtime-transcription-session.js +165 -0
- package/dist/server/server/speech/providers/openai/realtime-transcription-session.js.map +1 -0
- package/dist/server/server/speech/providers/openai/runtime.d.ts +27 -0
- package/dist/server/server/speech/providers/openai/runtime.d.ts.map +1 -0
- package/dist/server/server/speech/providers/openai/runtime.js +103 -0
- package/dist/server/server/speech/providers/openai/runtime.js.map +1 -0
- package/dist/server/server/speech/providers/openai/stt.d.ts +22 -0
- package/dist/server/server/speech/providers/openai/stt.d.ts.map +1 -0
- package/dist/server/server/speech/providers/openai/stt.js +208 -0
- package/dist/server/server/speech/providers/openai/stt.js.map +1 -0
- package/dist/server/server/speech/providers/openai/tts.d.ts +18 -0
- package/dist/server/server/speech/providers/openai/tts.d.ts.map +1 -0
- package/dist/server/server/speech/providers/openai/tts.js +46 -0
- package/dist/server/server/speech/providers/openai/tts.js.map +1 -0
- package/dist/server/server/speech/speech-config-resolver.d.ts +11 -0
- package/dist/server/server/speech/speech-config-resolver.d.ts.map +1 -0
- package/dist/server/server/speech/speech-config-resolver.js +64 -0
- package/dist/server/server/speech/speech-config-resolver.js.map +1 -0
- package/dist/server/server/speech/speech-provider.d.ts +59 -0
- package/dist/server/server/speech/speech-provider.d.ts.map +1 -0
- package/dist/server/server/speech/speech-provider.js +2 -0
- package/dist/server/server/speech/speech-provider.js.map +1 -0
- package/dist/server/server/speech/speech-runtime.d.ts +20 -0
- package/dist/server/server/speech/speech-runtime.d.ts.map +1 -0
- package/dist/server/server/speech/speech-runtime.js +119 -0
- package/dist/server/server/speech/speech-runtime.js.map +1 -0
- package/dist/server/server/speech/speech-types.d.ts +20 -0
- package/dist/server/server/speech/speech-types.d.ts.map +1 -0
- package/dist/server/server/speech/speech-types.js +7 -0
- package/dist/server/server/speech/speech-types.js.map +1 -0
- package/dist/server/server/terminal-mcp/index.d.ts +4 -0
- package/dist/server/server/terminal-mcp/index.d.ts.map +1 -0
- package/dist/server/server/terminal-mcp/index.js +3 -0
- package/dist/server/server/terminal-mcp/index.js.map +1 -0
- package/dist/server/server/terminal-mcp/server.d.ts +10 -0
- package/dist/server/server/terminal-mcp/server.d.ts.map +1 -0
- package/dist/server/server/terminal-mcp/server.js +217 -0
- package/dist/server/server/terminal-mcp/server.js.map +1 -0
- package/dist/server/server/terminal-mcp/terminal-manager.d.ts +123 -0
- package/dist/server/server/terminal-mcp/terminal-manager.d.ts.map +1 -0
- package/dist/server/server/terminal-mcp/terminal-manager.js +351 -0
- package/dist/server/server/terminal-mcp/terminal-manager.js.map +1 -0
- package/dist/server/server/terminal-mcp/tmux.d.ts +207 -0
- package/dist/server/server/terminal-mcp/tmux.d.ts.map +1 -0
- package/dist/server/server/terminal-mcp/tmux.js +924 -0
- package/dist/server/server/terminal-mcp/tmux.js.map +1 -0
- package/dist/server/server/types.d.ts +5 -0
- package/dist/server/server/types.d.ts.map +1 -0
- package/dist/server/server/types.js +3 -0
- package/dist/server/server/types.js.map +1 -0
- package/dist/server/server/utils/diff-highlighter.d.ts +52 -0
- package/dist/server/server/utils/diff-highlighter.d.ts.map +1 -0
- package/dist/server/server/utils/diff-highlighter.js +244 -0
- package/dist/server/server/utils/diff-highlighter.js.map +1 -0
- package/dist/server/server/utils/syntax-highlighter.d.ts +10 -0
- package/dist/server/server/utils/syntax-highlighter.d.ts.map +1 -0
- package/dist/server/server/utils/syntax-highlighter.js +141 -0
- package/dist/server/server/utils/syntax-highlighter.js.map +1 -0
- package/dist/server/server/voice-config.d.ts +14 -0
- package/dist/server/server/voice-config.d.ts.map +1 -0
- package/dist/server/server/voice-config.js +51 -0
- package/dist/server/server/voice-config.js.map +1 -0
- package/dist/server/server/voice-mcp-bridge-command.d.ts +17 -0
- package/dist/server/server/voice-mcp-bridge-command.d.ts.map +1 -0
- package/dist/server/server/voice-mcp-bridge-command.js +31 -0
- package/dist/server/server/voice-mcp-bridge-command.js.map +1 -0
- package/dist/server/server/voice-mcp-bridge.d.ts +18 -0
- package/dist/server/server/voice-mcp-bridge.d.ts.map +1 -0
- package/dist/server/server/voice-mcp-bridge.js +109 -0
- package/dist/server/server/voice-mcp-bridge.js.map +1 -0
- package/dist/server/server/voice-permission-policy.d.ts +4 -0
- package/dist/server/server/voice-permission-policy.d.ts.map +1 -0
- package/dist/server/server/voice-permission-policy.js +13 -0
- package/dist/server/server/voice-permission-policy.js.map +1 -0
- package/dist/server/server/voice-types.d.ts +17 -0
- package/dist/server/server/voice-types.d.ts.map +1 -0
- package/dist/server/server/voice-types.js +2 -0
- package/dist/server/server/voice-types.js.map +1 -0
- package/dist/server/server/websocket-server.d.ts +80 -0
- package/dist/server/server/websocket-server.d.ts.map +1 -0
- package/dist/server/server/websocket-server.js +447 -0
- package/dist/server/server/websocket-server.js.map +1 -0
- package/dist/server/shared/agent-lifecycle.d.ts +3 -0
- package/dist/server/shared/agent-lifecycle.d.ts.map +1 -0
- package/dist/server/shared/agent-lifecycle.js +8 -0
- package/dist/server/shared/agent-lifecycle.js.map +1 -0
- package/dist/server/shared/connection-offer.d.ts +62 -0
- package/dist/server/shared/connection-offer.d.ts.map +1 -0
- package/dist/server/shared/connection-offer.js +17 -0
- package/dist/server/shared/connection-offer.js.map +1 -0
- package/dist/server/shared/daemon-endpoints.d.ts +19 -0
- package/dist/server/shared/daemon-endpoints.d.ts.map +1 -0
- package/dist/server/shared/daemon-endpoints.js +98 -0
- package/dist/server/shared/daemon-endpoints.js.map +1 -0
- package/dist/server/shared/messages.d.ts +36729 -0
- package/dist/server/shared/messages.d.ts.map +1 -0
- package/dist/server/shared/messages.js +1666 -0
- package/dist/server/shared/messages.js.map +1 -0
- package/dist/server/shared/path-utils.d.ts +2 -0
- package/dist/server/shared/path-utils.d.ts.map +1 -0
- package/dist/server/shared/path-utils.js +16 -0
- package/dist/server/shared/path-utils.js.map +1 -0
- package/dist/server/shared/tool-call-display.d.ts +11 -0
- package/dist/server/shared/tool-call-display.d.ts.map +1 -0
- package/dist/server/shared/tool-call-display.js +82 -0
- package/dist/server/shared/tool-call-display.js.map +1 -0
- package/dist/server/terminal/terminal-manager.d.ts +14 -0
- package/dist/server/terminal/terminal-manager.d.ts.map +1 -0
- package/dist/server/terminal/terminal-manager.js +67 -0
- package/dist/server/terminal/terminal-manager.js.map +1 -0
- package/dist/server/terminal/terminal.d.ts +67 -0
- package/dist/server/terminal/terminal.d.ts.map +1 -0
- package/dist/server/terminal/terminal.js +190 -0
- package/dist/server/terminal/terminal.js.map +1 -0
- package/dist/server/utils/checkout-git.d.ts +138 -0
- package/dist/server/utils/checkout-git.d.ts.map +1 -0
- package/dist/server/utils/checkout-git.js +1079 -0
- package/dist/server/utils/checkout-git.js.map +1 -0
- package/dist/server/utils/path.d.ts +5 -0
- package/dist/server/utils/path.d.ts.map +1 -0
- package/dist/server/utils/path.js +15 -0
- package/dist/server/utils/path.js.map +1 -0
- package/dist/server/utils/project-icon.d.ts +39 -0
- package/dist/server/utils/project-icon.d.ts.map +1 -0
- package/dist/server/utils/project-icon.js +391 -0
- package/dist/server/utils/project-icon.js.map +1 -0
- package/dist/server/utils/worktree-metadata.d.ts +21 -0
- package/dist/server/utils/worktree-metadata.d.ts.map +1 -0
- package/dist/server/utils/worktree-metadata.js +74 -0
- package/dist/server/utils/worktree-metadata.js.map +1 -0
- package/dist/server/utils/worktree.d.ts +95 -0
- package/dist/server/utils/worktree.d.ts.map +1 -0
- package/dist/server/utils/worktree.js +568 -0
- package/dist/server/utils/worktree.js.map +1 -0
- package/package.json +108 -0
|
@@ -0,0 +1,924 @@
|
|
|
1
|
+
import { exec as execCallback, execFile as execFileCallback, } from "child_process";
|
|
2
|
+
import { promisify } from "util";
|
|
3
|
+
import { v4 as uuidv4 } from "uuid";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
const exec = promisify(execCallback);
|
|
6
|
+
const execFile = promisify(execFileCallback);
|
|
7
|
+
let shellConfig = { type: "bash" };
|
|
8
|
+
const ANSI_ESCAPE_REGEX = /\u001B[\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
|
|
9
|
+
const EXIT_CODE_MARKER = "__PASEO_EXIT_CODE__:";
|
|
10
|
+
function stripAnsiSequences(value) {
|
|
11
|
+
if (!value) {
|
|
12
|
+
return "";
|
|
13
|
+
}
|
|
14
|
+
return value.replace(ANSI_ESCAPE_REGEX, "");
|
|
15
|
+
}
|
|
16
|
+
export function extractExitCodeMarkerFromOutput(output) {
|
|
17
|
+
if (!output) {
|
|
18
|
+
return { exitCode: null, output };
|
|
19
|
+
}
|
|
20
|
+
let exitCode = null;
|
|
21
|
+
const kept = [];
|
|
22
|
+
for (const line of output.split("\n")) {
|
|
23
|
+
const trimmed = line.trim();
|
|
24
|
+
if (trimmed.startsWith(EXIT_CODE_MARKER)) {
|
|
25
|
+
const codeStr = trimmed.slice(EXIT_CODE_MARKER.length).trim();
|
|
26
|
+
const parsed = parseInt(codeStr, 10);
|
|
27
|
+
if (Number.isFinite(parsed)) {
|
|
28
|
+
exitCode = parsed;
|
|
29
|
+
}
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
kept.push(line);
|
|
33
|
+
}
|
|
34
|
+
return { exitCode, output: kept.join("\n").trimEnd() };
|
|
35
|
+
}
|
|
36
|
+
export function setShellConfig(config) {
|
|
37
|
+
// Validate shell type
|
|
38
|
+
const validShells = ["bash", "zsh", "fish"];
|
|
39
|
+
if (validShells.includes(config.type)) {
|
|
40
|
+
shellConfig = { type: config.type };
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
shellConfig = { type: "bash" };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Execute a tmux command and return the result
|
|
48
|
+
* Uses execFile to avoid shell interpretation of special characters
|
|
49
|
+
*/
|
|
50
|
+
export async function executeTmux(args) {
|
|
51
|
+
try {
|
|
52
|
+
const { stdout } = await execFile("tmux", args);
|
|
53
|
+
return stdout.trim();
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
throw new Error(`Failed to execute tmux command: ${error.message}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Check if tmux server is running
|
|
61
|
+
*/
|
|
62
|
+
export async function isTmuxRunning() {
|
|
63
|
+
try {
|
|
64
|
+
await executeTmux(["list-sessions", "-F", "#{session_name}"]);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* List all tmux sessions
|
|
73
|
+
*/
|
|
74
|
+
export async function listSessions() {
|
|
75
|
+
const format = "#{session_id}:#{session_name}:#{?session_attached,1,0}:#{session_windows}";
|
|
76
|
+
const output = await executeTmux(["list-sessions", "-F", format]);
|
|
77
|
+
if (!output)
|
|
78
|
+
return [];
|
|
79
|
+
return output.split("\n").map((line) => {
|
|
80
|
+
const [id, name, attached, windows] = line.split(":");
|
|
81
|
+
return {
|
|
82
|
+
id,
|
|
83
|
+
name,
|
|
84
|
+
attached: attached === "1",
|
|
85
|
+
windows: parseInt(windows, 10),
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Find a session by name
|
|
91
|
+
*/
|
|
92
|
+
export async function findSessionByName(name) {
|
|
93
|
+
try {
|
|
94
|
+
const sessions = await listSessions();
|
|
95
|
+
return sessions.find((session) => session.name === name) || null;
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Find a window by name in a session
|
|
103
|
+
*/
|
|
104
|
+
export async function findWindowByName(sessionId, name) {
|
|
105
|
+
try {
|
|
106
|
+
const windows = await listWindows(sessionId);
|
|
107
|
+
return windows.find((window) => window.name === name) || null;
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Check if a window name is unique in a session
|
|
115
|
+
*/
|
|
116
|
+
export async function isWindowNameUnique(sessionId, name) {
|
|
117
|
+
const window = await findWindowByName(sessionId, name);
|
|
118
|
+
return window === null;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* List windows in a session
|
|
122
|
+
*/
|
|
123
|
+
export async function listWindows(sessionId) {
|
|
124
|
+
const format = "#{window_id}:#{window_name}:#{?window_active,1,0}";
|
|
125
|
+
const output = await executeTmux([
|
|
126
|
+
"list-windows",
|
|
127
|
+
"-t",
|
|
128
|
+
sessionId,
|
|
129
|
+
"-F",
|
|
130
|
+
format,
|
|
131
|
+
]);
|
|
132
|
+
if (!output)
|
|
133
|
+
return [];
|
|
134
|
+
return output.split("\n").map((line) => {
|
|
135
|
+
const [id, name, active] = line.split(":");
|
|
136
|
+
return {
|
|
137
|
+
id,
|
|
138
|
+
name,
|
|
139
|
+
active: active === "1",
|
|
140
|
+
sessionId,
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* List panes in a window
|
|
146
|
+
*/
|
|
147
|
+
export async function listPanes(windowId) {
|
|
148
|
+
const format = "#{pane_id}:#{pane_title}:#{?pane_active,1,0}";
|
|
149
|
+
const output = await executeTmux([
|
|
150
|
+
"list-panes",
|
|
151
|
+
"-t",
|
|
152
|
+
windowId,
|
|
153
|
+
"-F",
|
|
154
|
+
format,
|
|
155
|
+
]);
|
|
156
|
+
if (!output)
|
|
157
|
+
return [];
|
|
158
|
+
return output.split("\n").map((line) => {
|
|
159
|
+
const [id, title, active] = line.split(":");
|
|
160
|
+
return {
|
|
161
|
+
id,
|
|
162
|
+
windowId,
|
|
163
|
+
title: title,
|
|
164
|
+
active: active === "1",
|
|
165
|
+
};
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Capture content from a specific pane, by default the latest 200 lines.
|
|
170
|
+
*/
|
|
171
|
+
export async function capturePaneContent(paneId, lines = 200, includeColors = false) {
|
|
172
|
+
// Capture a large range to ensure we have enough content
|
|
173
|
+
const captureLines = Math.max(lines, 1000);
|
|
174
|
+
const args = ["capture-pane", "-p"];
|
|
175
|
+
if (includeColors) {
|
|
176
|
+
args.push("-e");
|
|
177
|
+
}
|
|
178
|
+
args.push("-t", paneId, "-S", `-${captureLines}`, "-E", "-");
|
|
179
|
+
const output = await executeTmux(args);
|
|
180
|
+
// Trim trailing whitespace, split by lines, take last N lines, rejoin
|
|
181
|
+
const trimmed = output.trimEnd();
|
|
182
|
+
const allLines = trimmed.split("\n");
|
|
183
|
+
const lastLines = allLines.slice(-lines);
|
|
184
|
+
const joined = lastLines.join("\n");
|
|
185
|
+
return includeColors ? joined : stripAnsiSequences(joined);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get the current working directory of a pane
|
|
189
|
+
*/
|
|
190
|
+
export async function getCurrentWorkingDirectory(paneId) {
|
|
191
|
+
try {
|
|
192
|
+
const tmuxPath = await executeTmux([
|
|
193
|
+
"display-message",
|
|
194
|
+
"-p",
|
|
195
|
+
"-t",
|
|
196
|
+
paneId,
|
|
197
|
+
"#{pane_current_path}",
|
|
198
|
+
]);
|
|
199
|
+
// If tmux returns a valid path, use it
|
|
200
|
+
if (tmuxPath && tmuxPath.trim()) {
|
|
201
|
+
return tmuxPath;
|
|
202
|
+
}
|
|
203
|
+
// Fallback: get the PID and use lsof to find the actual CWD
|
|
204
|
+
const shellPid = await executeTmux([
|
|
205
|
+
"display-message",
|
|
206
|
+
"-p",
|
|
207
|
+
"-t",
|
|
208
|
+
paneId,
|
|
209
|
+
"#{pane_pid}",
|
|
210
|
+
]);
|
|
211
|
+
const { stdout } = await exec(`lsof -a -p ${shellPid.trim()} -d cwd -Fn | grep '^n' | cut -c2-`);
|
|
212
|
+
return stdout.trim() || tmuxPath;
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
// If all else fails, return empty string
|
|
216
|
+
return "";
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Get stored working directory from window user option (for dead panes)
|
|
221
|
+
* Falls back to current working directory if not stored
|
|
222
|
+
*/
|
|
223
|
+
export async function getStoredWorkingDirectory(windowId, paneId) {
|
|
224
|
+
try {
|
|
225
|
+
const stored = await executeTmux([
|
|
226
|
+
"show-window-options",
|
|
227
|
+
"-t",
|
|
228
|
+
windowId,
|
|
229
|
+
"-v",
|
|
230
|
+
"@working_directory",
|
|
231
|
+
]);
|
|
232
|
+
if (stored && stored.trim()) {
|
|
233
|
+
return stored.trim();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
// Option not set, fall back to current
|
|
238
|
+
}
|
|
239
|
+
return getCurrentWorkingDirectory(paneId);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Get the current command running in a pane (full command line with arguments)
|
|
243
|
+
* Gets the immediate child process of the shell, not the shell itself
|
|
244
|
+
*/
|
|
245
|
+
export async function getCurrentCommand(paneId) {
|
|
246
|
+
try {
|
|
247
|
+
// Get the shell PID (the pane's main process)
|
|
248
|
+
const shellPid = await executeTmux([
|
|
249
|
+
"display-message",
|
|
250
|
+
"-p",
|
|
251
|
+
"-t",
|
|
252
|
+
paneId,
|
|
253
|
+
"#{pane_pid}",
|
|
254
|
+
]);
|
|
255
|
+
// First, check if there's a child process using comm= (works for all programs including top)
|
|
256
|
+
// Use 'ax' flags to see all processes
|
|
257
|
+
const { stdout: childPid } = await exec(`ps ax -o pid=,ppid=,comm= | awk '$2 == ${shellPid.trim()} { print $1; exit }'`);
|
|
258
|
+
if (childPid.trim()) {
|
|
259
|
+
// Found a child process, get its full command with args
|
|
260
|
+
const { stdout: fullCmd } = await exec(`ps -p ${childPid.trim()} -o args= | sed 's/\\\\012.*//'`);
|
|
261
|
+
const command = fullCmd.trim();
|
|
262
|
+
if (command) {
|
|
263
|
+
return command;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// No child process, just return the shell name
|
|
267
|
+
const { stdout: shellCmd } = await exec(`ps -p ${shellPid} -o comm=`);
|
|
268
|
+
return shellCmd.trim();
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
// Fallback to just the command name if ps fails
|
|
272
|
+
return executeTmux([
|
|
273
|
+
"display-message",
|
|
274
|
+
"-p",
|
|
275
|
+
"-t",
|
|
276
|
+
paneId,
|
|
277
|
+
"#{pane_current_command}",
|
|
278
|
+
]);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Get stored command from window user option (for dead panes)
|
|
283
|
+
* Falls back to current command if not stored
|
|
284
|
+
*/
|
|
285
|
+
export async function getStoredCommand(windowId, paneId) {
|
|
286
|
+
try {
|
|
287
|
+
const stored = await executeTmux([
|
|
288
|
+
"show-window-options",
|
|
289
|
+
"-t",
|
|
290
|
+
windowId,
|
|
291
|
+
"-v",
|
|
292
|
+
"@command",
|
|
293
|
+
]);
|
|
294
|
+
if (stored && stored.trim()) {
|
|
295
|
+
return stored.trim();
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
// Option not set, fall back to current
|
|
300
|
+
}
|
|
301
|
+
return getCurrentCommand(paneId);
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Create a new tmux session with a default window named "default" in home directory
|
|
305
|
+
*/
|
|
306
|
+
export async function createSession(name) {
|
|
307
|
+
const homeDir = process.env.HOME || "~";
|
|
308
|
+
await executeTmux([
|
|
309
|
+
"new-session",
|
|
310
|
+
"-d",
|
|
311
|
+
"-s",
|
|
312
|
+
name,
|
|
313
|
+
"-n",
|
|
314
|
+
"default",
|
|
315
|
+
"-c",
|
|
316
|
+
homeDir,
|
|
317
|
+
]);
|
|
318
|
+
const session = await findSessionByName(name);
|
|
319
|
+
if (!session) {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
// Disable automatic window renaming for all windows in the session (session target works; ':0' does not)
|
|
323
|
+
await executeTmux([
|
|
324
|
+
"set-window-option",
|
|
325
|
+
"-t",
|
|
326
|
+
session.id,
|
|
327
|
+
"automatic-rename",
|
|
328
|
+
"off",
|
|
329
|
+
]);
|
|
330
|
+
return session;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Expand tilde in path to home directory
|
|
334
|
+
*/
|
|
335
|
+
export function expandTilde(path) {
|
|
336
|
+
if (path.startsWith("~/")) {
|
|
337
|
+
const homeDir = process.env.HOME || os.homedir();
|
|
338
|
+
return path.replace("~", homeDir);
|
|
339
|
+
}
|
|
340
|
+
if (path === "~") {
|
|
341
|
+
return process.env.HOME || os.homedir();
|
|
342
|
+
}
|
|
343
|
+
return path;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Create a new window in a session with optional working directory and initial command
|
|
347
|
+
*/
|
|
348
|
+
export async function createWindow(sessionId, name, options) {
|
|
349
|
+
// Validate name uniqueness
|
|
350
|
+
const isUnique = await isWindowNameUnique(sessionId, name);
|
|
351
|
+
if (!isUnique) {
|
|
352
|
+
throw new Error(`Terminal with name '${name}' already exists. Please choose a unique name.`);
|
|
353
|
+
}
|
|
354
|
+
// Build new-window command with optional working directory
|
|
355
|
+
const args = ["new-window", "-t", sessionId, "-n", name];
|
|
356
|
+
if (options?.workingDirectory) {
|
|
357
|
+
// Expand tilde to home directory before passing to tmux
|
|
358
|
+
const expandedPath = expandTilde(options.workingDirectory);
|
|
359
|
+
args.push("-c", expandedPath);
|
|
360
|
+
}
|
|
361
|
+
await executeTmux(args);
|
|
362
|
+
const windows = await listWindows(sessionId);
|
|
363
|
+
const window = windows.find((window) => window.name === name);
|
|
364
|
+
if (!window)
|
|
365
|
+
return null;
|
|
366
|
+
// Disable automatic window renaming
|
|
367
|
+
await executeTmux([
|
|
368
|
+
"set-window-option",
|
|
369
|
+
"-t",
|
|
370
|
+
window.id,
|
|
371
|
+
"automatic-rename",
|
|
372
|
+
"off",
|
|
373
|
+
]);
|
|
374
|
+
// Get the default pane created with the window
|
|
375
|
+
const panes = await listPanes(window.id);
|
|
376
|
+
const defaultPane = panes[0];
|
|
377
|
+
let commandOutput = null;
|
|
378
|
+
// If command is provided, execute it in the new pane
|
|
379
|
+
if (options?.command && defaultPane) {
|
|
380
|
+
commandOutput = (await sendText({
|
|
381
|
+
paneId: defaultPane.id,
|
|
382
|
+
text: options.command,
|
|
383
|
+
pressEnter: true,
|
|
384
|
+
return_output: {
|
|
385
|
+
waitForSettled: true,
|
|
386
|
+
maxWait: 120000,
|
|
387
|
+
},
|
|
388
|
+
}));
|
|
389
|
+
}
|
|
390
|
+
return {
|
|
391
|
+
...window,
|
|
392
|
+
paneId: defaultPane?.id || "",
|
|
393
|
+
output: commandOutput,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Execute a command in a new window with remain-on-exit enabled
|
|
398
|
+
* This allows capturing output and exit code even after the command finishes
|
|
399
|
+
*
|
|
400
|
+
* @param sessionId - The tmux session ID
|
|
401
|
+
* @param command - The command to execute (will be wrapped in bash -c)
|
|
402
|
+
* @param workingDirectory - Directory to execute command in
|
|
403
|
+
* @param maxWait - Maximum milliseconds to wait for command completion or stability
|
|
404
|
+
* @returns Window ID, output, exit code (if finished), and whether process is still running
|
|
405
|
+
*/
|
|
406
|
+
export async function executeCommand({ sessionId, command, workingDirectory, maxWait = 120000, }) {
|
|
407
|
+
// Generate unique window name using timestamp
|
|
408
|
+
const windowName = `cmd-${Date.now()}`;
|
|
409
|
+
const expandedPath = expandTilde(workingDirectory);
|
|
410
|
+
// Create window
|
|
411
|
+
const args = ["new-window", "-t", sessionId, "-n", windowName, "-c", expandedPath];
|
|
412
|
+
await executeTmux(args);
|
|
413
|
+
const windows = await listWindows(sessionId);
|
|
414
|
+
const window = windows.find((w) => w.name === windowName);
|
|
415
|
+
if (!window) {
|
|
416
|
+
throw new Error("Failed to create window for command execution");
|
|
417
|
+
}
|
|
418
|
+
// Enable remain-on-exit to keep window after command finishes
|
|
419
|
+
await executeTmux([
|
|
420
|
+
"set-window-option",
|
|
421
|
+
"-t",
|
|
422
|
+
window.id,
|
|
423
|
+
"remain-on-exit",
|
|
424
|
+
"on",
|
|
425
|
+
]);
|
|
426
|
+
// Disable automatic window renaming
|
|
427
|
+
await executeTmux([
|
|
428
|
+
"set-window-option",
|
|
429
|
+
"-t",
|
|
430
|
+
window.id,
|
|
431
|
+
"automatic-rename",
|
|
432
|
+
"off",
|
|
433
|
+
]);
|
|
434
|
+
// Store command and working directory as window options for later retrieval
|
|
435
|
+
await executeTmux([
|
|
436
|
+
"set-window-option",
|
|
437
|
+
"-t",
|
|
438
|
+
window.id,
|
|
439
|
+
"@command",
|
|
440
|
+
command,
|
|
441
|
+
]);
|
|
442
|
+
await executeTmux([
|
|
443
|
+
"set-window-option",
|
|
444
|
+
"-t",
|
|
445
|
+
window.id,
|
|
446
|
+
"@working_directory",
|
|
447
|
+
expandedPath,
|
|
448
|
+
]);
|
|
449
|
+
// Get the pane
|
|
450
|
+
const panes = await listPanes(window.id);
|
|
451
|
+
const pane = panes[0];
|
|
452
|
+
if (!pane) {
|
|
453
|
+
throw new Error("No pane found in created window");
|
|
454
|
+
}
|
|
455
|
+
// Execute command via respawn-pane with bash -c wrapper
|
|
456
|
+
// This ensures all bash features work (pipes, operators, etc.)
|
|
457
|
+
const wrappedCommand = `bash -c 'cd "${expandedPath}" && ${command.replace(/'/g, "'\\''")} 2>&1; code=$?; echo ${EXIT_CODE_MARKER}$code; exit $code'`;
|
|
458
|
+
await executeTmux(["respawn-pane", "-t", pane.id, "-k", wrappedCommand]);
|
|
459
|
+
// Wait for command to finish or reach stability
|
|
460
|
+
const startTime = Date.now();
|
|
461
|
+
let output = "";
|
|
462
|
+
let isDead = false;
|
|
463
|
+
let exitCode = null;
|
|
464
|
+
const emptyOutputGraceMs = Math.min(maxWait, 2000);
|
|
465
|
+
while (Date.now() - startTime < maxWait) {
|
|
466
|
+
// Check if pane is dead (command exited)
|
|
467
|
+
const deadStatus = await executeTmux([
|
|
468
|
+
"display-message",
|
|
469
|
+
"-p",
|
|
470
|
+
"-t",
|
|
471
|
+
pane.id,
|
|
472
|
+
"#{pane_dead}",
|
|
473
|
+
]);
|
|
474
|
+
isDead = deadStatus === "1";
|
|
475
|
+
if (isDead) {
|
|
476
|
+
// Command finished - capture output and exit code
|
|
477
|
+
output = await capturePaneContent(pane.id, 1000, false);
|
|
478
|
+
const extracted = extractExitCodeMarkerFromOutput(output);
|
|
479
|
+
output = extracted.output;
|
|
480
|
+
const exitCodeStr = await executeTmux([
|
|
481
|
+
"display-message",
|
|
482
|
+
"-p",
|
|
483
|
+
"-t",
|
|
484
|
+
pane.id,
|
|
485
|
+
"#{pane_dead_status}",
|
|
486
|
+
]);
|
|
487
|
+
const parsed = parseInt(exitCodeStr, 10);
|
|
488
|
+
exitCode = Number.isFinite(parsed) ? parsed : extracted.exitCode;
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
// Check for stability (output hasn't changed)
|
|
492
|
+
const currentOutput = await capturePaneContent(pane.id, 1000, false);
|
|
493
|
+
if (currentOutput === output) {
|
|
494
|
+
// Wait a bit more to confirm stability
|
|
495
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
496
|
+
const confirmedOutput = await capturePaneContent(pane.id, 1000, false);
|
|
497
|
+
if (confirmedOutput === currentOutput) {
|
|
498
|
+
const elapsed = Date.now() - startTime;
|
|
499
|
+
if (!confirmedOutput && elapsed < emptyOutputGraceMs) {
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
// Stable - command is likely waiting for input or running steadily
|
|
503
|
+
output = confirmedOutput;
|
|
504
|
+
break;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
output = currentOutput;
|
|
508
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
509
|
+
}
|
|
510
|
+
// Final capture if we hit timeout
|
|
511
|
+
if (!isDead && !output) {
|
|
512
|
+
output = await capturePaneContent(pane.id, 1000, false);
|
|
513
|
+
}
|
|
514
|
+
return {
|
|
515
|
+
windowId: window.id,
|
|
516
|
+
paneId: pane.id,
|
|
517
|
+
output,
|
|
518
|
+
exitCode,
|
|
519
|
+
isDead,
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Kill a tmux session by ID
|
|
524
|
+
*/
|
|
525
|
+
export async function killSession(sessionId) {
|
|
526
|
+
await executeTmux(["kill-session", "-t", sessionId]);
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Kill a tmux window by ID
|
|
530
|
+
*/
|
|
531
|
+
export async function killWindow(windowId) {
|
|
532
|
+
await executeTmux(["kill-window", "-t", windowId]);
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Kill a tmux pane by ID
|
|
536
|
+
*/
|
|
537
|
+
export async function killPane(paneId) {
|
|
538
|
+
await executeTmux(["kill-pane", "-t", paneId]);
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Rename a tmux window by name or ID
|
|
542
|
+
*/
|
|
543
|
+
export async function renameWindow(sessionId, windowNameOrId, newName) {
|
|
544
|
+
// Validate new name is unique
|
|
545
|
+
const isUnique = await isWindowNameUnique(sessionId, newName);
|
|
546
|
+
if (!isUnique) {
|
|
547
|
+
throw new Error(`Terminal with name '${newName}' already exists. Please choose a unique name.`);
|
|
548
|
+
}
|
|
549
|
+
// Check if windowNameOrId is a window ID (starts with @) or a name
|
|
550
|
+
let windowId;
|
|
551
|
+
if (windowNameOrId.startsWith("@")) {
|
|
552
|
+
windowId = windowNameOrId;
|
|
553
|
+
}
|
|
554
|
+
else {
|
|
555
|
+
// Resolve name to ID
|
|
556
|
+
const window = await findWindowByName(sessionId, windowNameOrId);
|
|
557
|
+
if (!window) {
|
|
558
|
+
throw new Error(`Terminal '${windowNameOrId}' not found.`);
|
|
559
|
+
}
|
|
560
|
+
windowId = window.id;
|
|
561
|
+
}
|
|
562
|
+
await executeTmux(["rename-window", "-t", windowId, newName]);
|
|
563
|
+
// Disable automatic renaming to preserve the manual name
|
|
564
|
+
await executeTmux([
|
|
565
|
+
"set-window-option",
|
|
566
|
+
"-t",
|
|
567
|
+
windowId,
|
|
568
|
+
"automatic-rename",
|
|
569
|
+
"off",
|
|
570
|
+
]);
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Split a tmux pane horizontally or vertically
|
|
574
|
+
*/
|
|
575
|
+
export async function splitPane(targetPaneId, direction = "vertical", size) {
|
|
576
|
+
// Build the split-window command args
|
|
577
|
+
const args = ["split-window"];
|
|
578
|
+
// Add direction flag (-h for horizontal, -v for vertical)
|
|
579
|
+
if (direction === "horizontal") {
|
|
580
|
+
args.push("-h");
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
args.push("-v");
|
|
584
|
+
}
|
|
585
|
+
// Add target pane
|
|
586
|
+
args.push("-t", targetPaneId);
|
|
587
|
+
// Add size if specified (as percentage)
|
|
588
|
+
if (size !== undefined && size > 0 && size < 100) {
|
|
589
|
+
args.push("-p", size.toString());
|
|
590
|
+
}
|
|
591
|
+
// Execute the split command
|
|
592
|
+
await executeTmux(args);
|
|
593
|
+
// Get the window ID from the target pane to list all panes
|
|
594
|
+
const windowInfo = await executeTmux([
|
|
595
|
+
"display-message",
|
|
596
|
+
"-p",
|
|
597
|
+
"-t",
|
|
598
|
+
targetPaneId,
|
|
599
|
+
"#{window_id}",
|
|
600
|
+
]);
|
|
601
|
+
// List all panes in the window to find the newly created one
|
|
602
|
+
const panes = await listPanes(windowInfo);
|
|
603
|
+
// The newest pane is typically the last one in the list
|
|
604
|
+
return panes.length > 0 ? panes[panes.length - 1] : null;
|
|
605
|
+
}
|
|
606
|
+
// Map to track ongoing command executions
|
|
607
|
+
const activeCommands = new Map();
|
|
608
|
+
const startMarkerText = "TMUX_MCP_START";
|
|
609
|
+
const endMarkerPrefix = "TMUX_MCP_DONE_";
|
|
610
|
+
// Execute a command in a tmux pane and track its execution (OLD - for backward compat)
|
|
611
|
+
export async function executeCommandLegacy(paneId, command, rawMode, noEnter) {
|
|
612
|
+
// Generate unique ID for this command execution
|
|
613
|
+
const commandId = uuidv4();
|
|
614
|
+
let fullCommand;
|
|
615
|
+
if (rawMode || noEnter) {
|
|
616
|
+
fullCommand = command;
|
|
617
|
+
}
|
|
618
|
+
else {
|
|
619
|
+
const endMarkerText = getEndMarkerText();
|
|
620
|
+
fullCommand = `echo "${startMarkerText}"; ${command}; echo "${endMarkerText}"`;
|
|
621
|
+
}
|
|
622
|
+
// Store command in tracking map
|
|
623
|
+
activeCommands.set(commandId, {
|
|
624
|
+
id: commandId,
|
|
625
|
+
paneId,
|
|
626
|
+
command,
|
|
627
|
+
status: "pending",
|
|
628
|
+
startTime: new Date(),
|
|
629
|
+
rawMode: rawMode || noEnter,
|
|
630
|
+
});
|
|
631
|
+
// Send the command to the tmux pane
|
|
632
|
+
if (noEnter) {
|
|
633
|
+
// Check if this is a special key or key combination
|
|
634
|
+
// Special keys in tmux are typically capitalized or have special names
|
|
635
|
+
const specialKeys = [
|
|
636
|
+
"Up",
|
|
637
|
+
"Down",
|
|
638
|
+
"Left",
|
|
639
|
+
"Right",
|
|
640
|
+
"Escape",
|
|
641
|
+
"Tab",
|
|
642
|
+
"Enter",
|
|
643
|
+
"Space",
|
|
644
|
+
"BSpace",
|
|
645
|
+
"Delete",
|
|
646
|
+
"Home",
|
|
647
|
+
"End",
|
|
648
|
+
"PageUp",
|
|
649
|
+
"PageDown",
|
|
650
|
+
"F1",
|
|
651
|
+
"F2",
|
|
652
|
+
"F3",
|
|
653
|
+
"F4",
|
|
654
|
+
"F5",
|
|
655
|
+
"F6",
|
|
656
|
+
"F7",
|
|
657
|
+
"F8",
|
|
658
|
+
"F9",
|
|
659
|
+
"F10",
|
|
660
|
+
"F11",
|
|
661
|
+
"F12",
|
|
662
|
+
"BTab",
|
|
663
|
+
];
|
|
664
|
+
// Split the command into parts to handle combinations like "C-b" or "M-x"
|
|
665
|
+
const parts = fullCommand.split("-");
|
|
666
|
+
const isSpecialKey = parts.length === 1 && specialKeys.includes(parts[0]);
|
|
667
|
+
const isKeyCombo = parts.length > 1 &&
|
|
668
|
+
(parts[0] === "C" || // Control
|
|
669
|
+
parts[0] === "M" || // Meta/Alt
|
|
670
|
+
parts[0] === "S"); // Shift
|
|
671
|
+
if (isSpecialKey || isKeyCombo) {
|
|
672
|
+
// Send special key or key combination as-is
|
|
673
|
+
const args = ["send-keys", "-t", paneId];
|
|
674
|
+
args.push(...fullCommand.split(" "));
|
|
675
|
+
await executeTmux(args);
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
// For regular text, send each character individually to ensure proper processing
|
|
679
|
+
// This handles both single characters (like 'q', 'f') and strings (like 'beam')
|
|
680
|
+
for (const char of fullCommand) {
|
|
681
|
+
await executeTmux(["send-keys", "-t", paneId, char]);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
await executeTmux(["send-keys", "-t", paneId, fullCommand, "Enter"]);
|
|
687
|
+
}
|
|
688
|
+
return commandId;
|
|
689
|
+
}
|
|
690
|
+
export async function checkCommandStatus(commandId) {
|
|
691
|
+
const command = activeCommands.get(commandId);
|
|
692
|
+
if (!command)
|
|
693
|
+
return null;
|
|
694
|
+
if (command.status !== "pending")
|
|
695
|
+
return command;
|
|
696
|
+
const content = await capturePaneContent(command.paneId, 1000);
|
|
697
|
+
if (command.rawMode) {
|
|
698
|
+
command.result =
|
|
699
|
+
"Status tracking unavailable for rawMode commands. Use capture-pane to monitor interactive apps instead.";
|
|
700
|
+
return command;
|
|
701
|
+
}
|
|
702
|
+
// Find the last occurrence of the markers
|
|
703
|
+
const startIndex = content.lastIndexOf(startMarkerText);
|
|
704
|
+
const endIndex = content.lastIndexOf(endMarkerPrefix);
|
|
705
|
+
if (startIndex === -1 || endIndex === -1 || endIndex <= startIndex) {
|
|
706
|
+
command.result = "Command output could not be captured properly";
|
|
707
|
+
return command;
|
|
708
|
+
}
|
|
709
|
+
// Extract exit code from the end marker line
|
|
710
|
+
const endLine = content.substring(endIndex).split("\n")[0];
|
|
711
|
+
const endMarkerRegex = new RegExp(`${endMarkerPrefix}(\\d+)`);
|
|
712
|
+
const exitCodeMatch = endLine.match(endMarkerRegex);
|
|
713
|
+
if (exitCodeMatch) {
|
|
714
|
+
const exitCode = parseInt(exitCodeMatch[1], 10);
|
|
715
|
+
command.status = exitCode === 0 ? "completed" : "error";
|
|
716
|
+
command.exitCode = exitCode;
|
|
717
|
+
// Extract output between the start and end markers
|
|
718
|
+
const outputStart = startIndex + startMarkerText.length;
|
|
719
|
+
const outputContent = content.substring(outputStart, endIndex).trim();
|
|
720
|
+
command.result = outputContent
|
|
721
|
+
.substring(outputContent.indexOf("\n") + 1)
|
|
722
|
+
.trim();
|
|
723
|
+
// Update in map
|
|
724
|
+
activeCommands.set(commandId, command);
|
|
725
|
+
}
|
|
726
|
+
return command;
|
|
727
|
+
}
|
|
728
|
+
// Get command by ID
|
|
729
|
+
export function getCommand(commandId) {
|
|
730
|
+
return activeCommands.get(commandId) || null;
|
|
731
|
+
}
|
|
732
|
+
// Get all active command IDs
|
|
733
|
+
export function getActiveCommandIds() {
|
|
734
|
+
return Array.from(activeCommands.keys());
|
|
735
|
+
}
|
|
736
|
+
// Clean up completed commands older than a certain time
|
|
737
|
+
export function cleanupOldCommands(maxAgeMinutes = 60) {
|
|
738
|
+
const now = new Date();
|
|
739
|
+
for (const [id, command] of activeCommands.entries()) {
|
|
740
|
+
const ageMinutes = (now.getTime() - command.startTime.getTime()) / (1000 * 60);
|
|
741
|
+
if (command.status !== "pending" && ageMinutes > maxAgeMinutes) {
|
|
742
|
+
activeCommands.delete(id);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
function getEndMarkerText() {
|
|
747
|
+
return shellConfig.type === "fish"
|
|
748
|
+
? `${endMarkerPrefix}$status`
|
|
749
|
+
: `${endMarkerPrefix}$?`;
|
|
750
|
+
}
|
|
751
|
+
export async function list({ scope, target, }) {
|
|
752
|
+
if (scope === "all") {
|
|
753
|
+
const sessions = await listSessions();
|
|
754
|
+
const sessionsWithDetails = [];
|
|
755
|
+
for (const session of sessions) {
|
|
756
|
+
const windows = await listWindows(session.id);
|
|
757
|
+
const windowsWithPanes = [];
|
|
758
|
+
for (const window of windows) {
|
|
759
|
+
const panes = await listPanes(window.id);
|
|
760
|
+
windowsWithPanes.push({
|
|
761
|
+
...window,
|
|
762
|
+
paneDetails: panes,
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
sessionsWithDetails.push({
|
|
766
|
+
...session,
|
|
767
|
+
windowDetails: windowsWithPanes,
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
return sessionsWithDetails;
|
|
771
|
+
}
|
|
772
|
+
if (scope === "sessions") {
|
|
773
|
+
return listSessions();
|
|
774
|
+
}
|
|
775
|
+
if (scope === "session") {
|
|
776
|
+
if (!target) {
|
|
777
|
+
throw new Error("target is required for scope 'session'");
|
|
778
|
+
}
|
|
779
|
+
return listWindows(target);
|
|
780
|
+
}
|
|
781
|
+
if (scope === "window") {
|
|
782
|
+
if (!target) {
|
|
783
|
+
throw new Error("target is required for scope 'window'");
|
|
784
|
+
}
|
|
785
|
+
return listPanes(target);
|
|
786
|
+
}
|
|
787
|
+
if (scope === "pane") {
|
|
788
|
+
if (!target) {
|
|
789
|
+
throw new Error("target is required for scope 'pane'");
|
|
790
|
+
}
|
|
791
|
+
const windowId = await executeTmux([
|
|
792
|
+
"display-message",
|
|
793
|
+
"-p",
|
|
794
|
+
"-t",
|
|
795
|
+
target,
|
|
796
|
+
"#{window_id}",
|
|
797
|
+
]);
|
|
798
|
+
const panes = await listPanes(windowId);
|
|
799
|
+
const pane = panes.find((p) => p.id === target);
|
|
800
|
+
if (!pane) {
|
|
801
|
+
throw new Error(`Pane not found: ${target}`);
|
|
802
|
+
}
|
|
803
|
+
return pane;
|
|
804
|
+
}
|
|
805
|
+
throw new Error(`Invalid scope: ${scope}`);
|
|
806
|
+
}
|
|
807
|
+
export async function kill({ scope, target, }) {
|
|
808
|
+
if (scope === "session") {
|
|
809
|
+
return killSession(target);
|
|
810
|
+
}
|
|
811
|
+
if (scope === "window") {
|
|
812
|
+
return killWindow(target);
|
|
813
|
+
}
|
|
814
|
+
if (scope === "pane") {
|
|
815
|
+
return killPane(target);
|
|
816
|
+
}
|
|
817
|
+
throw new Error(`Invalid scope: ${scope}`);
|
|
818
|
+
}
|
|
819
|
+
export async function executeShellCommand({ paneId, command, timeout = 30000, }) {
|
|
820
|
+
const commandId = uuidv4();
|
|
821
|
+
const endMarkerText = getEndMarkerText();
|
|
822
|
+
const fullCommand = `echo "${startMarkerText}"; ${command}; echo "${endMarkerText}"`;
|
|
823
|
+
activeCommands.set(commandId, {
|
|
824
|
+
id: commandId,
|
|
825
|
+
paneId,
|
|
826
|
+
command,
|
|
827
|
+
status: "pending",
|
|
828
|
+
startTime: new Date(),
|
|
829
|
+
rawMode: false,
|
|
830
|
+
});
|
|
831
|
+
await executeTmux(["send-keys", "-t", paneId, fullCommand, "Enter"]);
|
|
832
|
+
// Poll for completion
|
|
833
|
+
const startTime = Date.now();
|
|
834
|
+
const pollInterval = 100;
|
|
835
|
+
while (Date.now() - startTime < timeout) {
|
|
836
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
837
|
+
const result = await checkCommandStatus(commandId);
|
|
838
|
+
if (result && result.status !== "pending") {
|
|
839
|
+
// Cleanup
|
|
840
|
+
activeCommands.delete(commandId);
|
|
841
|
+
return {
|
|
842
|
+
command: result.command,
|
|
843
|
+
status: result.status,
|
|
844
|
+
exitCode: result.exitCode,
|
|
845
|
+
output: result.result || "",
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
// Timeout
|
|
850
|
+
activeCommands.delete(commandId);
|
|
851
|
+
throw new Error(`Command timed out after ${timeout}ms. Use capture-pane to check pane state.`);
|
|
852
|
+
}
|
|
853
|
+
export async function sendKeys({ paneId, keys, repeat = 1, return_output, }) {
|
|
854
|
+
// Repeat the key press the specified number of times
|
|
855
|
+
for (let i = 0; i < repeat; i++) {
|
|
856
|
+
// Raw pass-through, no validation or processing
|
|
857
|
+
const args = ["send-keys", "-t", paneId];
|
|
858
|
+
args.push(...keys.split(" "));
|
|
859
|
+
await executeTmux(args);
|
|
860
|
+
}
|
|
861
|
+
// If return_output is requested, wait and capture pane content
|
|
862
|
+
if (return_output) {
|
|
863
|
+
const lines = return_output.lines || 200;
|
|
864
|
+
const waitForSettled = return_output.waitForSettled ?? true;
|
|
865
|
+
const maxWait = return_output.maxWait ?? 120000; // 2 minutes default
|
|
866
|
+
if (waitForSettled) {
|
|
867
|
+
return waitForPaneActivityToSettle(paneId, maxWait, lines);
|
|
868
|
+
}
|
|
869
|
+
else {
|
|
870
|
+
return capturePaneContent(paneId, lines, false);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
return null;
|
|
874
|
+
}
|
|
875
|
+
export async function waitForPaneActivityToSettle(paneId, maxWait, lines) {
|
|
876
|
+
const settleTime = 1000; // Hardcoded debounce
|
|
877
|
+
const pollInterval = 100; // Poll every 100ms
|
|
878
|
+
let lastContent = "";
|
|
879
|
+
let lastChangeTime = Date.now();
|
|
880
|
+
const startTime = Date.now();
|
|
881
|
+
while (true) {
|
|
882
|
+
const elapsed = Date.now() - startTime;
|
|
883
|
+
if (elapsed >= maxWait) {
|
|
884
|
+
// Timeout - return what we have
|
|
885
|
+
return lastContent;
|
|
886
|
+
}
|
|
887
|
+
const content = await capturePaneContent(paneId, lines, false);
|
|
888
|
+
if (content !== lastContent) {
|
|
889
|
+
// Activity detected - reset settle timer
|
|
890
|
+
lastContent = content;
|
|
891
|
+
lastChangeTime = Date.now();
|
|
892
|
+
}
|
|
893
|
+
else if (Date.now() - lastChangeTime >= settleTime) {
|
|
894
|
+
// No changes for settleTime ms - settled!
|
|
895
|
+
return content;
|
|
896
|
+
}
|
|
897
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
export async function sendText({ paneId, text, pressEnter = false, return_output, }) {
|
|
901
|
+
// Send each character with -l flag for literal interpretation
|
|
902
|
+
// Using execFile avoids shell interpretation of special characters like ; | & $
|
|
903
|
+
for (const char of text) {
|
|
904
|
+
await executeTmux(["send-keys", "-l", "-t", paneId, char]);
|
|
905
|
+
}
|
|
906
|
+
if (pressEnter) {
|
|
907
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
908
|
+
await executeTmux(["send-keys", "-t", paneId, "Enter"]);
|
|
909
|
+
}
|
|
910
|
+
// If return_output is requested, wait and capture pane content
|
|
911
|
+
if (return_output) {
|
|
912
|
+
const lines = return_output.lines || 200;
|
|
913
|
+
const waitForSettled = return_output.waitForSettled ?? true;
|
|
914
|
+
const maxWait = return_output.maxWait ?? 120000; // 2 minutes default
|
|
915
|
+
if (waitForSettled) {
|
|
916
|
+
return waitForPaneActivityToSettle(paneId, maxWait, lines);
|
|
917
|
+
}
|
|
918
|
+
else {
|
|
919
|
+
return capturePaneContent(paneId, lines, false);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
return null;
|
|
923
|
+
}
|
|
924
|
+
//# sourceMappingURL=tmux.js.map
|