@zergai/ztc 0.4.0-beta.1 → 0.5.0-beta.1
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/README.md +398 -45
- package/RUST_THIRD_PARTY_LICENSES.txt +1080 -822
- package/THIRD_PARTY_NOTICES.md +273 -12
- package/bin/zmux-darwin-arm64 +0 -0
- package/bin/ztc-audio-darwin-arm64 +0 -0
- package/bin/ztc-capture-darwin-arm64 +0 -0
- package/bin/ztc-computer-darwin-arm64 +0 -0
- package/bin/ztc-llm-darwin-arm64 +0 -0
- package/bin/ztc-tts-darwin-arm64 +0 -0
- package/bin/ztc-tui-darwin-arm64 +0 -0
- package/bin/ztc-zlicky-overlay-darwin-arm64 +0 -0
- package/bin/zterm-darwin-arm64 +0 -0
- package/dist/App.js +1206 -209
- package/dist/agent/agent.d.ts +74 -8
- package/dist/agent/agent.js +1073 -184
- package/dist/agent/backends/account_rotation.d.ts +4 -0
- package/dist/agent/backends/account_rotation.js +8 -2
- package/dist/agent/backends/anthropic.d.ts +13 -0
- package/dist/agent/backends/anthropic.js +169 -28
- package/dist/agent/backends/claude_cli.js +18 -8
- package/dist/agent/backends/codex_app_server.d.ts +1 -0
- package/dist/agent/backends/codex_app_server.js +55 -3
- package/dist/agent/backends/codex_auth.d.ts +1 -0
- package/dist/agent/backends/codex_auth.js +67 -13
- package/dist/agent/backends/codex_buffered_recovery.d.ts +27 -0
- package/dist/agent/backends/codex_buffered_recovery.js +293 -0
- package/dist/agent/backends/gemini.js +3 -1
- package/dist/agent/backends/http_error.d.ts +26 -0
- package/dist/agent/backends/http_error.js +221 -0
- package/dist/agent/backends/index.d.ts +9 -2
- package/dist/agent/backends/index.js +22 -2
- package/dist/agent/backends/openai.d.ts +0 -6
- package/dist/agent/backends/openai.js +5 -2
- package/dist/agent/backends/openai_compatible.d.ts +5 -4
- package/dist/agent/backends/openai_compatible.js +26 -19
- package/dist/agent/backends/openai_responses.d.ts +8 -3
- package/dist/agent/backends/openai_responses.js +77 -33
- package/dist/agent/backends/provider_ids.d.ts +1 -0
- package/dist/agent/backends/provider_ids.js +4 -0
- package/dist/agent/backends/request_metrics.js +12 -2
- package/dist/agent/backends/types.d.ts +109 -6
- package/dist/agent/backends/types.js +5 -1
- package/dist/agent/backends/zrouter_stream.d.ts +6 -1
- package/dist/agent/backends/zrouter_stream.js +160 -42
- package/dist/agent/background_registry.d.ts +2 -0
- package/dist/agent/background_registry.js +1 -0
- package/dist/agent/claim_observation.d.ts +6 -0
- package/dist/agent/claim_observation.js +54 -0
- package/dist/agent/commands/accounts.js +46 -177
- package/dist/agent/commands/attention.d.ts +2 -0
- package/dist/agent/commands/attention.js +67 -0
- package/dist/agent/commands/auth.js +18 -2
- package/dist/agent/commands/board.d.ts +2 -0
- package/dist/agent/commands/board.js +169 -0
- package/dist/agent/commands/clipboard.js +50 -1
- package/dist/agent/commands/compact.js +21 -13
- package/dist/agent/commands/config.js +4 -1
- package/dist/agent/commands/context.js +6 -1
- package/dist/agent/commands/desktop.d.ts +2 -0
- package/dist/agent/commands/desktop.js +29 -0
- package/dist/agent/commands/effort.js +14 -6
- package/dist/agent/commands/environment.d.ts +3 -0
- package/dist/agent/commands/environment.js +109 -0
- package/dist/agent/commands/evidence.d.ts +2 -0
- package/dist/agent/commands/evidence.js +9 -0
- package/dist/agent/commands/fork.js +4 -3
- package/dist/agent/commands/goal.d.ts +33 -1
- package/dist/agent/commands/goal.js +174 -14
- package/dist/agent/commands/goal_exit.d.ts +36 -0
- package/dist/agent/commands/goal_exit.js +120 -0
- package/dist/agent/commands/help.js +3 -1
- package/dist/agent/commands/history.js +3 -1
- package/dist/agent/commands/inbox.d.ts +2 -0
- package/dist/agent/commands/inbox.js +148 -0
- package/dist/agent/commands/index.js +16 -1
- package/dist/agent/commands/input_mode.js +8 -6
- package/dist/agent/commands/job.d.ts +2 -0
- package/dist/agent/commands/job.js +93 -0
- package/dist/agent/commands/keybindings.js +4 -1
- package/dist/agent/commands/label.d.ts +2 -0
- package/dist/agent/commands/label.js +77 -0
- package/dist/agent/commands/layout.d.ts +2 -0
- package/dist/agent/commands/layout.js +20 -0
- package/dist/agent/commands/mirror.js +16 -1
- package/dist/agent/commands/model.js +12 -2
- package/dist/agent/commands/permissions.d.ts +3 -1
- package/dist/agent/commands/permissions.js +79 -89
- package/dist/agent/commands/plan.js +5 -15
- package/dist/agent/commands/profile.js +21 -2
- package/dist/agent/commands/provider_selection.js +20 -1
- package/dist/agent/commands/rename.js +1 -1
- package/dist/agent/commands/resources.d.ts +2 -0
- package/dist/agent/commands/resources.js +67 -0
- package/dist/agent/commands/rewind.d.ts +3 -0
- package/dist/agent/commands/rewind.js +16 -0
- package/dist/agent/commands/runbooks.d.ts +2 -0
- package/dist/agent/commands/runbooks.js +73 -0
- package/dist/agent/commands/runbooks_lazy.d.ts +2 -0
- package/dist/agent/commands/runbooks_lazy.js +8 -0
- package/dist/agent/commands/sessions.d.ts +1 -1
- package/dist/agent/commands/sessions.js +33 -5
- package/dist/agent/commands/settings.js +185 -39
- package/dist/agent/commands/setup.d.ts +2 -0
- package/dist/agent/commands/setup.js +78 -0
- package/dist/agent/commands/share.d.ts +2 -0
- package/dist/agent/commands/share.js +64 -0
- package/dist/agent/commands/status.js +14 -2
- package/dist/agent/commands/types.d.ts +99 -6
- package/dist/agent/commands/update.js +8 -0
- package/dist/agent/commands/usage.d.ts +2 -0
- package/dist/agent/commands/usage.js +8 -0
- package/dist/agent/factory.d.ts +11 -0
- package/dist/agent/factory.js +113 -88
- package/dist/agent/loop_policy.d.ts +6 -3
- package/dist/agent/loop_policy.js +12 -3
- package/dist/agent/measurement_guidance.d.ts +2 -0
- package/dist/agent/measurement_guidance.js +5 -0
- package/dist/agent/request_encoder.d.ts +8 -1
- package/dist/agent/request_encoder.js +95 -23
- package/dist/agent/runtime/benchmark_comparison.d.ts +30 -0
- package/dist/agent/runtime/benchmark_comparison.js +94 -0
- package/dist/agent/runtime/benchmark_contract.d.ts +48 -0
- package/dist/agent/runtime/benchmark_contract.js +90 -0
- package/dist/agent/runtime/checked_commands.d.ts +32 -0
- package/dist/agent/runtime/checked_commands.js +119 -0
- package/dist/agent/runtime/command_execution_policy.d.ts +26 -0
- package/dist/agent/runtime/command_execution_policy.js +91 -0
- package/dist/agent/runtime/command_jobs.d.ts +36 -18
- package/dist/agent/runtime/command_jobs.js +151 -13
- package/dist/agent/runtime/command_panes.d.ts +59 -0
- package/dist/agent/runtime/command_panes.js +398 -0
- package/dist/agent/runtime/command_wait.d.ts +19 -0
- package/dist/agent/runtime/command_wait.js +167 -0
- package/dist/agent/runtime/cpu_benchmark.d.ts +30 -0
- package/dist/agent/runtime/cpu_benchmark.js +126 -0
- package/dist/agent/runtime/delegated_evidence.d.ts +26 -0
- package/dist/agent/runtime/delegated_evidence.js +80 -0
- package/dist/agent/runtime/evidence.d.ts +127 -0
- package/dist/agent/runtime/evidence.js +468 -0
- package/dist/agent/runtime/execution_context.d.ts +7 -0
- package/dist/agent/runtime/execution_context.js +39 -3
- package/dist/agent/runtime/json_verifier_recipe.d.ts +8 -0
- package/dist/agent/runtime/json_verifier_recipe.js +66 -0
- package/dist/agent/runtime/measurements.d.ts +110 -0
- package/dist/agent/runtime/measurements.js +317 -0
- package/dist/agent/runtime/policy.d.ts +4 -0
- package/dist/agent/runtime/policy.js +31 -20
- package/dist/agent/runtime/provider_native_evidence.d.ts +20 -0
- package/dist/agent/runtime/provider_native_evidence.js +86 -0
- package/dist/agent/runtime/recovery.d.ts +2 -0
- package/dist/agent/runtime/recovery.js +45 -2
- package/dist/agent/runtime/remote_broker_transport.d.ts +10 -0
- package/dist/agent/runtime/remote_broker_transport.js +84 -0
- package/dist/agent/runtime/remote_deletion_receipts.d.ts +3 -0
- package/dist/agent/runtime/remote_deletion_receipts.js +43 -0
- package/dist/agent/runtime/remote_journal_replay.d.ts +13 -0
- package/dist/agent/runtime/remote_journal_replay.js +233 -0
- package/dist/agent/runtime/remote_mutation_journal.d.ts +25 -0
- package/dist/agent/runtime/remote_mutation_journal.js +208 -0
- package/dist/agent/runtime/remote_resource_endpoint.d.ts +7 -0
- package/dist/agent/runtime/remote_resource_endpoint.js +6 -0
- package/dist/agent/runtime/remote_resource_errors.d.ts +5 -0
- package/dist/agent/runtime/remote_resource_errors.js +9 -0
- package/dist/agent/runtime/remote_resource_script.d.ts +2 -0
- package/dist/agent/runtime/remote_resource_script.js +1009 -0
- package/dist/agent/runtime/remote_resources.d.ts +29 -0
- package/dist/agent/runtime/remote_resources.js +160 -0
- package/dist/agent/runtime/source_verification.d.ts +12 -0
- package/dist/agent/runtime/source_verification.js +210 -0
- package/dist/agent/runtime/source_verification_contract.d.ts +75 -0
- package/dist/agent/runtime/source_verification_contract.js +203 -0
- package/dist/agent/runtime/tool_checkpoints.d.ts +11 -0
- package/dist/agent/runtime/tool_checkpoints.js +26 -0
- package/dist/agent/runtime/tool_effects.d.ts +5 -0
- package/dist/agent/runtime/tool_progress.d.ts +12 -0
- package/dist/agent/runtime/tool_progress.js +76 -0
- package/dist/agent/runtime/tool_runtime.d.ts +16 -1
- package/dist/agent/runtime/tool_runtime.js +204 -10
- package/dist/agent/runtime/tracing.d.ts +1 -1
- package/dist/agent/runtime/verifier_capture.d.ts +9 -0
- package/dist/agent/runtime/verifier_capture.js +100 -0
- package/dist/agent/runtime/verifier_contract.d.ts +24 -0
- package/dist/agent/runtime/verifier_contract.js +41 -0
- package/dist/agent/subagent.d.ts +20 -10
- package/dist/agent/subagent.js +266 -29
- package/dist/agent/tool_response_directory.d.ts +24 -0
- package/dist/agent/tool_response_directory.js +61 -0
- package/dist/agent/tool_response_source.d.ts +8 -0
- package/dist/agent/tool_response_source.js +49 -0
- package/dist/agent/tool_response_store.d.ts +75 -4
- package/dist/agent/tool_response_store.js +583 -64
- package/dist/agent/tools/ask_user.d.ts +3 -1
- package/dist/agent/tools/ask_user.js +30 -11
- package/dist/agent/tools/background.js +1 -0
- package/dist/agent/tools/benchmark_cpu.d.ts +2 -0
- package/dist/agent/tools/benchmark_cpu.js +102 -0
- package/dist/agent/tools/compare_benchmarks.d.ts +2 -0
- package/dist/agent/tools/compare_benchmarks.js +53 -0
- package/dist/agent/tools/deferred.js +1 -0
- package/dist/agent/tools/delegate.js +18 -2
- package/dist/agent/tools/helper_requirements.d.ts +7 -0
- package/dist/agent/tools/helper_requirements.js +19 -0
- package/dist/agent/tools/index.d.ts +1 -0
- package/dist/agent/tools/index.js +3 -0
- package/dist/agent/tools/measurement_report.d.ts +22 -0
- package/dist/agent/tools/measurement_report.js +190 -0
- package/dist/agent/tools/pane.d.ts +0 -7
- package/dist/agent/tools/pane.js +5 -4
- package/dist/agent/tools/project_context.d.ts +3 -0
- package/dist/agent/tools/project_context.js +45 -0
- package/dist/agent/tools/recall_tool_response.d.ts +3 -5
- package/dist/agent/tools/recall_tool_response.js +19 -29
- package/dist/agent/tools/registry.d.ts +1 -0
- package/dist/agent/tools/registry.js +23 -0
- package/dist/agent/tools/related_sessions.d.ts +2 -0
- package/dist/agent/tools/related_sessions.js +156 -0
- package/dist/agent/tools/routine.js +13 -3
- package/dist/agent/tools/session_evidence.d.ts +3 -0
- package/dist/agent/tools/session_evidence.js +72 -0
- package/dist/agent/tools/shell.d.ts +4 -3
- package/dist/agent/tools/shell.js +174 -47
- package/dist/agent/tools/tool_search.js +3 -2
- package/dist/agent/tools/types.d.ts +28 -0
- package/dist/agent/tools/verify_artifact.d.ts +2 -0
- package/dist/agent/tools/verify_artifact.js +60 -0
- package/dist/agent/tools/workflow.js +1 -0
- package/dist/app/activity.d.ts +6 -1
- package/dist/app/activity.js +81 -12
- package/dist/app/agent_runner.d.ts +6 -1
- package/dist/app/agent_runner.js +34 -19
- package/dist/app/command_context.js +106 -10
- package/dist/app/controller.d.ts +15 -4
- package/dist/app/controller.js +29 -3
- package/dist/app/escape_stop.d.ts +11 -0
- package/dist/app/escape_stop.js +15 -0
- package/dist/app/liveness.d.ts +6 -4
- package/dist/app/liveness.js +13 -3
- package/dist/app/model_catalog_cache.d.ts +5 -0
- package/dist/app/model_catalog_cache.js +138 -0
- package/dist/app/ordered_transcript.js +43 -4
- package/dist/app/prompt_turn.d.ts +14 -0
- package/dist/app/prompt_turn.js +53 -0
- package/dist/app/recap.d.ts +3 -0
- package/dist/app/recap.js +9 -3
- package/dist/app/restart.d.ts +3 -2
- package/dist/app/restart.js +22 -7
- package/dist/app/rewind.d.ts +3 -3
- package/dist/app/rewind.js +3 -3
- package/dist/app/selection_completion.d.ts +17 -2
- package/dist/app/selection_completion.js +84 -9
- package/dist/app/session_manager.d.ts +38 -6
- package/dist/app/session_manager.js +263 -60
- package/dist/app/session_messages.d.ts +3 -0
- package/dist/app/session_messages.js +60 -0
- package/dist/app/task_scope_router.d.ts +20 -0
- package/dist/app/task_scope_router.js +173 -0
- package/dist/app/transcript_window.d.ts +2 -0
- package/dist/app/transcript_window.js +4 -0
- package/dist/app/workspace_admission_details.d.ts +3 -0
- package/dist/app/workspace_admission_details.js +26 -0
- package/dist/app/workspace_layout_controller.d.ts +11 -0
- package/dist/app/workspace_layout_controller.js +88 -0
- package/dist/app/workspace_monitor.d.ts +1 -0
- package/dist/app/workspace_monitor.js +216 -0
- package/dist/app/workspace_presets.d.ts +29 -0
- package/dist/app/workspace_presets.js +192 -0
- package/dist/attention/queue.d.ts +37 -0
- package/dist/attention/queue.js +183 -0
- package/dist/bench/rf_shared.d.ts +2 -0
- package/dist/board/binding.d.ts +42 -0
- package/dist/board/binding.js +38 -0
- package/dist/board/client.d.ts +42 -0
- package/dist/board/client.js +60 -0
- package/dist/cli.js +1 -1
- package/dist/cli_args.js +19 -17
- package/dist/cli_main.js +110 -13
- package/dist/cli_ratatui.d.ts +183 -16
- package/dist/cli_ratatui.js +3989 -1255
- package/dist/components/ActivityLine.d.ts +3 -2
- package/dist/components/ActivityLine.js +2 -2
- package/dist/components/InputArea.d.ts +19 -1
- package/dist/components/InputArea.js +264 -190
- package/dist/components/MessageList.d.ts +2 -0
- package/dist/components/MessageList.js +3 -1
- package/dist/components/SingleMessage.d.ts +2 -0
- package/dist/components/SingleMessage.js +4 -2
- package/dist/components/StatusBar.d.ts +4 -2
- package/dist/components/StatusBar.js +3 -1
- package/dist/conductor_branch.js +3 -0
- package/dist/config/api_retry.d.ts +6 -1
- package/dist/config/api_retry.js +19 -1
- package/dist/config/defaults.d.ts +2 -1
- package/dist/config/defaults.js +9 -2
- package/dist/config/message_display.d.ts +1 -0
- package/dist/config/message_display.js +17 -2
- package/dist/config/permissions.d.ts +21 -0
- package/dist/config/permissions.js +89 -0
- package/dist/config/resolved.d.ts +2 -2
- package/dist/config/types.d.ts +32 -5
- package/dist/config.d.ts +38 -4
- package/dist/config.js +290 -42
- package/dist/context/project_intelligence.d.ts +44 -0
- package/dist/context/project_intelligence.js +246 -0
- package/dist/desktop/cli_launch.d.ts +8 -0
- package/dist/desktop/cli_launch.js +6 -0
- package/dist/desktop/cli_shim.d.ts +8 -0
- package/dist/desktop/cli_shim.js +120 -0
- package/dist/desktop/runtime.d.ts +16 -0
- package/dist/desktop/runtime.js +161 -0
- package/dist/desktop/worker_launch.d.ts +7 -0
- package/dist/desktop/worker_launch.js +7 -0
- package/dist/diagnostics/cargo_mutants_selection.d.ts +27 -0
- package/dist/diagnostics/cargo_mutants_selection.js +48 -0
- package/dist/diagnostics/native_terminal_benchmark.d.ts +58 -0
- package/dist/diagnostics/native_terminal_benchmark.js +1247 -0
- package/dist/diagnostics/session_evidence_package.d.ts +40 -0
- package/dist/diagnostics/session_evidence_package.js +234 -0
- package/dist/diagnostics/session_export.d.ts +93 -0
- package/dist/diagnostics/session_export.js +634 -0
- package/dist/emulation/tool_adapters.js +48 -18
- package/dist/emulation/ztc_addendum.d.ts +1 -0
- package/dist/emulation/ztc_addendum.js +13 -12
- package/dist/environment/service_runner.d.ts +1 -0
- package/dist/environment/service_runner.js +68 -0
- package/dist/environment/store.d.ts +120 -0
- package/dist/environment/store.js +387 -0
- package/dist/events.d.ts +40 -1
- package/dist/events.js +10 -17
- package/dist/goal_contract.d.ts +25 -0
- package/dist/goal_contract.js +44 -0
- package/dist/headless.d.ts +31 -0
- package/dist/headless.js +578 -70
- package/dist/headless_cli.js +8 -0
- package/dist/headless_cli_args.d.ts +1 -0
- package/dist/headless_cli_args.js +1 -0
- package/dist/intake/cli.d.ts +1 -0
- package/dist/intake/cli.js +33 -0
- package/dist/intake/format.d.ts +2 -0
- package/dist/intake/format.js +14 -0
- package/dist/intake/notifications.d.ts +16 -0
- package/dist/intake/notifications.js +132 -0
- package/dist/intake/store.d.ts +56 -0
- package/dist/intake/store.js +238 -0
- package/dist/library.d.ts +8 -0
- package/dist/library.js +19 -10
- package/dist/mcp/client.d.ts +1 -0
- package/dist/mcp/client.js +20 -0
- package/dist/modes/builtin/plan.yaml +2 -2
- package/dist/modes/handlers.js +1 -1
- package/dist/onboarding/first_run.d.ts +3 -0
- package/dist/onboarding/first_run.js +33 -25
- package/dist/onboarding/setup.d.ts +32 -0
- package/dist/onboarding/setup.js +133 -0
- package/dist/onboarding/setup_agent_health.d.ts +17 -0
- package/dist/onboarding/setup_agent_health.js +79 -0
- package/dist/onboarding/setup_environment.d.ts +66 -0
- package/dist/onboarding/setup_environment.js +219 -0
- package/dist/onboarding/setup_workspace.d.ts +17 -0
- package/dist/onboarding/setup_workspace.js +129 -0
- package/dist/optimize/adapters/index.d.ts +4 -1
- package/dist/optimize/adapters/index.js +7 -0
- package/dist/optimize/adapters/kernelbench.js +14 -5
- package/dist/optimize/adapters/popcorn.js +3 -2
- package/dist/optimize/adapters/profile_benchmark.js +13 -7
- package/dist/optimize/adapters/rfbench.js +25 -14
- package/dist/optimize/adapters/types.d.ts +3 -0
- package/dist/optimize/adapters/zergpod.js +5 -2
- package/dist/optimize/baseline.js +10 -21
- package/dist/optimize/branch.js +9 -12
- package/dist/optimize/combine.js +2 -3
- package/dist/optimize/executor.js +34 -48
- package/dist/optimize/measurements.d.ts +55 -0
- package/dist/optimize/measurements.js +173 -0
- package/dist/optimize/results.d.ts +1 -0
- package/dist/optimize/results.js +11 -33
- package/dist/optimize/tge.js +2 -1
- package/dist/panes/initial_input.d.ts +19 -0
- package/dist/panes/initial_input.js +206 -0
- package/dist/panes/labels.d.ts +16 -0
- package/dist/panes/labels.js +42 -0
- package/dist/panes/model_catalog.d.ts +3 -3
- package/dist/panes/model_catalog.js +28 -4
- package/dist/panes/pane_registry.js +6 -2
- package/dist/panes/types.d.ts +3 -0
- package/dist/panes/ztc_launch.js +19 -0
- package/dist/plugin/optimization.d.ts +2 -0
- package/dist/plugin/optimization.js +1 -0
- package/dist/plugin/runtime.d.ts +2 -0
- package/dist/plugin/simulation.d.ts +6 -1
- package/dist/plugin/simulation_contract.d.ts +836 -1
- package/dist/plugin/simulation_documents.d.ts +22 -0
- package/dist/plugin/simulation_documents.js +1 -0
- package/dist/plugin/simulation_interventions.d.ts +103 -0
- package/dist/plugin/simulation_interventions.js +1 -0
- package/dist/plugin/simulation_living.d.ts +1 -0
- package/dist/plugin/simulation_living.js +3 -0
- package/dist/plugin/simulation_meetings.d.ts +121 -0
- package/dist/plugin/simulation_meetings.js +1 -0
- package/dist/plugin/simulation_story_review.d.ts +111 -0
- package/dist/plugin/simulation_story_review.js +1 -0
- package/dist/plugin/simulation_storyteller.d.ts +91 -0
- package/dist/plugin/simulation_storyteller.js +1 -0
- package/dist/plugin/simulation_structured.d.ts +2 -0
- package/dist/plugin/simulation_structured.js +2 -0
- package/dist/plugin/simulation_toolkit.d.ts +21 -0
- package/dist/plugin/simulation_toolkit.js +24 -0
- package/dist/prompts/tool_delegate_task.j2 +1 -1
- package/dist/remote-broker/Dockerfile +10 -0
- package/dist/remote-broker/archive.py +1227 -0
- package/dist/remote-broker/cutover.py +761 -0
- package/dist/remote-broker/requirements.txt +5 -0
- package/dist/remote-broker/resources.json +6 -0
- package/dist/remote-broker/resources.write-staging.example.json +18 -0
- package/dist/remote-broker/retained.py +686 -0
- package/dist/remote-broker/retained_cleanup.py +550 -0
- package/dist/remote-broker/server.py +648 -0
- package/dist/remote-broker/worker.py +1007 -0
- package/dist/router_auth.d.ts +31 -0
- package/dist/router_auth.js +155 -9
- package/dist/runbooks/catalog.d.ts +3 -0
- package/dist/runbooks/catalog.js +26 -0
- package/dist/runbooks/library.d.ts +11 -0
- package/dist/runbooks/library.js +95 -0
- package/dist/runbooks/package.d.ts +43 -0
- package/dist/runbooks/package.js +102 -0
- package/dist/session.d.ts +65 -13
- package/dist/session.js +548 -43
- package/dist/session_handoff.d.ts +25 -0
- package/dist/session_handoff.js +322 -0
- package/dist/session_handoff_contract.d.ts +89 -0
- package/dist/session_handoff_contract.js +179 -0
- package/dist/session_media.d.ts +41 -0
- package/dist/session_media.js +357 -0
- package/dist/session_ownership.d.ts +16 -0
- package/dist/session_ownership.js +221 -0
- package/dist/session_public.d.ts +10 -2
- package/dist/session_public.js +6 -1
- package/dist/simulation/dynamic_history.d.ts +42 -0
- package/dist/simulation/dynamic_history.js +173 -0
- package/dist/simulation/engines/swarm/pane_manager.js +7 -6
- package/dist/simulation/inference.d.ts +3 -1
- package/dist/simulation/inference.js +19 -1
- package/dist/simulation/intervention_generation.d.ts +27 -0
- package/dist/simulation/intervention_generation.js +246 -0
- package/dist/simulation/intervention_material.d.ts +4 -0
- package/dist/simulation/intervention_material.js +81 -0
- package/dist/simulation/living/context.d.ts +3130 -0
- package/dist/simulation/living/context.js +944 -0
- package/dist/simulation/living/definer.d.ts +12 -0
- package/dist/simulation/living/definer.js +223 -0
- package/dist/simulation/living/definition.d.ts +257 -0
- package/dist/simulation/living/definition.js +341 -0
- package/dist/simulation/living/frame.d.ts +259 -0
- package/dist/simulation/living/frame.js +223 -0
- package/dist/simulation/living/identifiers.d.ts +2 -0
- package/dist/simulation/living/identifiers.js +12 -0
- package/dist/simulation/living/index.d.ts +15 -0
- package/dist/simulation/living/index.js +15 -0
- package/dist/simulation/living/inference.d.ts +219 -0
- package/dist/simulation/living/inference.js +576 -0
- package/dist/simulation/living/mechanics.d.ts +54 -0
- package/dist/simulation/living/mechanics.js +588 -0
- package/dist/simulation/living/model-input.d.ts +25 -0
- package/dist/simulation/living/model-input.js +215 -0
- package/dist/simulation/living/open-world.d.ts +257 -0
- package/dist/simulation/living/open-world.js +102 -0
- package/dist/simulation/living/projection.d.ts +7 -0
- package/dist/simulation/living/projection.js +31 -0
- package/dist/simulation/living/recall.d.ts +17 -0
- package/dist/simulation/living/recall.js +25 -0
- package/dist/simulation/living/reduce.d.ts +15 -0
- package/dist/simulation/living/reduce.js +1853 -0
- package/dist/simulation/living/replay.d.ts +6 -0
- package/dist/simulation/living/replay.js +22 -0
- package/dist/simulation/living/runtime.d.ts +140 -0
- package/dist/simulation/living/runtime.js +3020 -0
- package/dist/simulation/living/shared-kinds.d.ts +24 -0
- package/dist/simulation/living/shared-kinds.js +96 -0
- package/dist/simulation/living/types.d.ts +2785 -0
- package/dist/simulation/living/types.js +669 -0
- package/dist/simulation/llm.d.ts +3 -1
- package/dist/simulation/llm.js +90 -30
- package/dist/simulation/memory/embedding.d.ts +1 -1
- package/dist/simulation/memory/embedding.js +9 -3
- package/dist/simulation/memory/filesystem.d.ts +2 -0
- package/dist/simulation/memory/filesystem.js +5 -1
- package/dist/simulation/memory/filesystem_file_tree.d.ts +4 -1
- package/dist/simulation/memory/filesystem_file_tree.js +41 -10
- package/dist/simulation/memory/filesystem_invariants.js +1 -2
- package/dist/simulation/memory/filesystem_types.d.ts +1 -0
- package/dist/simulation/memory/memory.d.ts +2 -0
- package/dist/simulation/memory/memory.js +5 -1
- package/dist/simulation/orchestration/intent.js +0 -2
- package/dist/simulation/orchestration/lifecycle.js +0 -2
- package/dist/simulation/plugin_host.d.ts +25 -1
- package/dist/simulation/plugin_host.js +334 -17
- package/dist/simulation/session_documents.d.ts +20 -0
- package/dist/simulation/session_documents.js +62 -0
- package/dist/simulation/session_input_validation.d.ts +43 -0
- package/dist/simulation/session_input_validation.js +364 -0
- package/dist/simulation/session_inputs.d.ts +32 -0
- package/dist/simulation/session_inputs.js +154 -0
- package/dist/simulation/telemetry.d.ts +11 -14
- package/dist/simulation/telemetry.js +177 -54
- package/dist/simulation/toolkit/bounded_turns.d.ts +13 -0
- package/dist/simulation/toolkit/bounded_turns.js +80 -0
- package/dist/simulation/toolkit/dynamic_agents.d.ts +25 -0
- package/dist/simulation/toolkit/dynamic_agents.js +218 -0
- package/dist/simulation/toolkit/dynamic_digest.d.ts +1 -0
- package/dist/simulation/toolkit/dynamic_digest.js +8 -0
- package/dist/simulation/toolkit/dynamic_documents.d.ts +7 -0
- package/dist/simulation/toolkit/dynamic_documents.js +71 -0
- package/dist/simulation/toolkit/dynamic_driver.d.ts +8 -0
- package/dist/simulation/toolkit/dynamic_driver.js +269 -0
- package/dist/simulation/toolkit/dynamic_game.d.ts +53 -0
- package/dist/simulation/toolkit/dynamic_game.js +805 -0
- package/dist/simulation/toolkit/dynamic_knowledge.d.ts +15 -0
- package/dist/simulation/toolkit/dynamic_knowledge.js +91 -0
- package/dist/simulation/toolkit/dynamic_mechanics.d.ts +22 -0
- package/dist/simulation/toolkit/dynamic_mechanics.js +910 -0
- package/dist/simulation/toolkit/dynamic_meetings.d.ts +239 -0
- package/dist/simulation/toolkit/dynamic_meetings.js +350 -0
- package/dist/simulation/toolkit/dynamic_progress.d.ts +131 -0
- package/dist/simulation/toolkit/dynamic_progress.js +214 -0
- package/dist/simulation/toolkit/dynamic_projection.d.ts +9 -0
- package/dist/simulation/toolkit/dynamic_projection.js +219 -0
- package/dist/simulation/toolkit/dynamic_runtime.d.ts +412 -0
- package/dist/simulation/toolkit/dynamic_runtime.js +6536 -0
- package/dist/simulation/toolkit/dynamic_state.d.ts +111 -0
- package/dist/simulation/toolkit/dynamic_state.js +1967 -0
- package/dist/simulation/toolkit/dynamic_story_review.d.ts +508 -0
- package/dist/simulation/toolkit/dynamic_story_review.js +333 -0
- package/dist/simulation/toolkit/dynamic_storyteller.d.ts +77 -0
- package/dist/simulation/toolkit/dynamic_storyteller.js +114 -0
- package/dist/simulation/toolkit/dynamic_storyteller_runtime.d.ts +26 -0
- package/dist/simulation/toolkit/dynamic_storyteller_runtime.js +126 -0
- package/dist/simulation/toolkit/dynamic_world.d.ts +22 -0
- package/dist/simulation/toolkit/dynamic_world.js +377 -0
- package/dist/simulation/toolkit/structured_output.d.ts +5 -0
- package/dist/simulation/toolkit/structured_output.js +321 -0
- package/dist/simulation/types/world.d.ts +2 -0
- package/dist/simulation/world/artifact_store.js +1 -1
- package/dist/simulation/world/memory_manager.d.ts +5 -0
- package/dist/simulation/world/memory_manager.js +17 -2
- package/dist/simulation/world/state.d.ts +3 -2
- package/dist/simulation/world/state.js +15 -5
- package/dist/skills/bundled/measurement-validation/SKILL.md +144 -0
- package/dist/terminal_attach.d.ts +1 -0
- package/dist/terminal_attach.js +113 -0
- package/dist/tool_progress.d.ts +3 -0
- package/dist/tool_progress.js +27 -0
- package/dist/types.d.ts +145 -10
- package/dist/types.js +3 -0
- package/dist/ui/core/input.d.ts +3 -0
- package/dist/ui/core/input_segments.d.ts +18 -1
- package/dist/ui/core/input_segments.js +131 -47
- package/dist/ui/core/input_state.d.ts +12 -0
- package/dist/ui/core/layout_yoga.d.ts +1 -1
- package/dist/ui/core/turn_metadata.d.ts +5 -0
- package/dist/ui/core/turn_metadata.js +22 -0
- package/dist/ui/ink/render.d.ts +2 -1
- package/dist/ui/ink/render.js +6 -5
- package/dist/ui/ratatui/headless_pane_manager.d.ts +14 -1
- package/dist/ui/ratatui/headless_pane_manager.js +293 -104
- package/dist/ui/ratatui/index.d.ts +1 -0
- package/dist/ui/ratatui/input.d.ts +4 -0
- package/dist/ui/ratatui/input.js +15 -0
- package/dist/ui/ratatui/ipc_path.d.ts +2 -0
- package/dist/ui/ratatui/ipc_path.js +29 -1
- package/dist/ui/ratatui/mux_persistence.d.ts +3 -1
- package/dist/ui/ratatui/mux_persistence.js +139 -1
- package/dist/ui/ratatui/pane_relay.d.ts +1 -1
- package/dist/ui/ratatui/pane_relay.js +55 -27
- package/dist/ui/ratatui/process.d.ts +17 -1
- package/dist/ui/ratatui/process.js +80 -7
- package/dist/ui/ratatui/protocol.d.ts +236 -1
- package/dist/ui/ratatui/protocol.js +90 -0
- package/dist/ui/scrollback.d.ts +2 -1
- package/dist/ui/scrollback.js +9 -4
- package/dist/ui/stream_typewriter.d.ts +8 -3
- package/dist/ui/stream_typewriter.js +30 -1
- package/dist/ui/streaming_scrollback.d.ts +1 -0
- package/dist/ui/streaming_scrollback.js +1 -1
- package/dist/ui/transcript_render_cache.js +10 -0
- package/dist/ui/views/activity_line.d.ts +5 -3
- package/dist/ui/views/activity_line.js +65 -7
- package/dist/ui/views/app.d.ts +6 -3
- package/dist/ui/views/app.js +17 -6
- package/dist/ui/views/completion_menu.js +10 -5
- package/dist/ui/views/input_area.d.ts +7 -3
- package/dist/ui/views/input_area.js +15 -9
- package/dist/ui/views/message_list.d.ts +4 -1
- package/dist/ui/views/message_list.js +89 -19
- package/dist/ui/views/queue_panel.d.ts +3 -1
- package/dist/ui/views/queue_panel.js +9 -2
- package/dist/ui/views/status_bar.d.ts +4 -2
- package/dist/ui/views/status_bar.js +28 -13
- package/dist/ui/views/theme.d.ts +2 -0
- package/dist/ui/views/theme.js +2 -0
- package/dist/ui/widgets/color_panel.js +18 -0
- package/dist/ui/widgets/form.js +8 -0
- package/dist/ui/widgets/log_view.js +7 -0
- package/dist/ui/widgets/navigator_panel.js +8 -0
- package/dist/ui/widgets/prompt_viewer.js +2 -0
- package/dist/ui/widgets/questionnaire.d.ts +2 -0
- package/dist/ui/widgets/questionnaire.js +79 -16
- package/dist/ui/widgets/resume_panel.d.ts +2 -0
- package/dist/ui/widgets/resume_panel.js +26 -15
- package/dist/ui/widgets/rewind_panel.d.ts +2 -2
- package/dist/ui/widgets/rewind_panel.js +4 -2
- package/dist/ui/widgets/select.js +16 -27
- package/dist/ui/widgets/settings_panel.js +16 -0
- package/dist/ui/widgets/status_line_panel.d.ts +1 -0
- package/dist/ui/widgets/status_line_panel.js +30 -4
- package/dist/ui/widgets/text_input.d.ts +2 -0
- package/dist/ui/widgets/text_input.js +15 -1
- package/dist/ui/widgets/types.d.ts +2 -0
- package/dist/usage_projection.d.ts +24 -0
- package/dist/usage_projection.js +130 -0
- package/dist/usage_snapshot.d.ts +36 -0
- package/dist/usage_snapshot.js +131 -0
- package/dist/utils/assistant_message.d.ts +2 -0
- package/dist/utils/assistant_message.js +5 -0
- package/dist/utils/atomic_write.d.ts +6 -2
- package/dist/utils/atomic_write.js +29 -4
- package/dist/utils/checked_shell.d.ts +25 -0
- package/dist/utils/checked_shell.js +107 -0
- package/dist/utils/compaction.d.ts +4 -1
- package/dist/utils/compaction.js +31 -7
- package/dist/utils/context.d.ts +4 -4
- package/dist/utils/context.js +14 -12
- package/dist/utils/deepseek.d.ts +2 -2
- package/dist/utils/deepseek.js +13 -5
- package/dist/utils/ephemeral.js +4 -0
- package/dist/utils/ephemeral_tools.d.ts +18 -0
- package/dist/utils/ephemeral_tools.js +97 -0
- package/dist/utils/jev_client.d.ts +4 -0
- package/dist/utils/jev_client.js +15 -0
- package/dist/utils/model_cache.d.ts +15 -0
- package/dist/utils/model_cache.js +143 -0
- package/dist/utils/models.d.ts +4 -2
- package/dist/utils/models.js +12 -16
- package/dist/utils/reasoning.d.ts +8 -1
- package/dist/utils/reasoning.js +31 -11
- package/dist/utils/router_catalog.d.ts +49 -0
- package/dist/utils/router_catalog.js +271 -0
- package/dist/utils/sandbox.d.ts +9 -0
- package/dist/utils/sandbox.js +118 -15
- package/dist/utils/shell.d.ts +7 -0
- package/dist/utils/shell.js +98 -34
- package/dist/utils/subprocess_env.d.ts +3 -0
- package/dist/utils/subprocess_env.js +27 -1
- package/dist/web/accounts_mirror.d.ts +3 -1
- package/dist/web/accounts_mirror.js +13 -9
- package/dist/web/child_publication.d.ts +17 -0
- package/dist/web/child_publication.js +45 -0
- package/dist/web/mirror_authenticator.d.ts +31 -11
- package/dist/web/mirror_authenticator.js +67 -17
- package/dist/web/mirror_client.d.ts +31 -4
- package/dist/web/mirror_client.js +189 -23
- package/dist/web/mirror_stream.d.ts +84 -22
- package/dist/web/mirror_stream.js +676 -95
- package/dist/web/observer_query_redaction.d.ts +6 -0
- package/dist/web/observer_query_redaction.js +58 -0
- package/dist/web/pane_registry.d.ts +2 -0
- package/dist/web/pane_registry.js +86 -22
- package/dist/web/tool_image.d.ts +6 -0
- package/dist/web/tool_image.js +17 -0
- package/dist/web/view_plugin.d.ts +14 -0
- package/dist/web/view_plugin.js +23 -1
- package/dist/worker/executor.js +31 -12
- package/dist/worker/index.d.ts +1 -0
- package/dist/worker/toolsets.js +3 -1
- package/dist/worker/types.d.ts +12 -1
- package/dist/workflows/registry.js +1 -0
- package/dist/workflows/registry_handle.d.ts +2 -0
- package/dist/workflows/runtime.d.ts +2 -0
- package/dist/workflows/runtime.js +1 -0
- package/dist/workspace_agent.d.ts +7 -0
- package/dist/workspace_agent.js +36 -0
- package/dist/workspace_collision.d.ts +76 -0
- package/dist/workspace_collision.js +688 -0
- package/dist/workspace_layout.d.ts +18 -0
- package/dist/workspace_layout.js +121 -0
- package/dist/workspace_runtime.d.ts +44 -0
- package/dist/workspace_runtime.js +82 -0
- package/dist/workspace_session_context.d.ts +62 -0
- package/dist/workspace_session_context.js +160 -0
- package/dist/zlm-embed.mjs +32518 -9615
- package/dist/zlm.js +1 -0
- package/node_modules/@zerg/model-contracts/LICENSE.md +375 -0
- package/node_modules/@zerg/model-contracts/README.md +90 -0
- package/node_modules/@zerg/model-contracts/index.d.ts +20 -0
- package/node_modules/@zerg/model-contracts/index.js +223 -0
- package/node_modules/@zerg/model-contracts/package.json +8 -0
- package/node_modules/glob/node_modules/brace-expansion/index.js +78 -22
- package/node_modules/glob/node_modules/brace-expansion/package.json +1 -1
- package/node_modules/readdir-glob/node_modules/brace-expansion/index.js +78 -22
- package/node_modules/readdir-glob/node_modules/brace-expansion/package.json +1 -1
- package/package.json +45 -24
- package/packages/model-contracts/LICENSE.md +375 -0
- package/packages/model-contracts/README.md +90 -0
- package/packages/model-contracts/index.d.ts +20 -0
- package/packages/model-contracts/index.js +223 -0
- package/packages/model-contracts/package.json +8 -0
- package/remote-broker/Dockerfile +10 -0
- package/remote-broker/README.md +308 -0
- package/remote-broker/archive.py +1227 -0
- package/remote-broker/cutover.py +761 -0
- package/remote-broker/requirements.txt +5 -0
- package/remote-broker/resources.example.json +6 -0
- package/remote-broker/resources.write-staging.example.json +18 -0
- package/remote-broker/retained.py +686 -0
- package/remote-broker/retained_cleanup.py +550 -0
- package/remote-broker/server.py +648 -0
- package/scripts/build-remote-broker.mjs +13 -0
- package/scripts/ensure-local-packages.mjs +6 -0
- package/scripts/node-pty-helpers.mjs +103 -0
|
@@ -10,6 +10,7 @@ export type { RatatuiRendererOptions } from './adapter.js';
|
|
|
10
10
|
export { TuiProcess, NullTuiProcess, getTuiProcess, getNullTuiProcess, isTTY, isZmuxAvailable, isZtermAvailable, launchZtermDesktop, isRatatuiBinaryAvailable } from './process.js';
|
|
11
11
|
export type { TuiEventHandler } from './process.js';
|
|
12
12
|
export type { RustCommand, RustEvent } from './protocol.js';
|
|
13
|
+
export type { DesktopTaskControlState, DesktopTaskControlEntry, DesktopTaskControlAttachment, DesktopTaskAction, DesktopTaskActionResult } from './protocol.js';
|
|
13
14
|
export { PaneRelayServer, PaneRelayClient, generateRelaySocketPath } from './pane_relay.js';
|
|
14
15
|
export type { PaneCommandTransport } from './pane_relay.js';
|
|
15
16
|
export { HeadlessPaneManager, encodeZtcPaneInput, decodeZtcPaneInput } from './headless_pane_manager.js';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type InputKey } from '../core/input.js';
|
|
2
|
+
export type ClipboardPastePreference = 'text' | 'image' | 'image-only';
|
|
3
|
+
/** Identify a clipboard gesture while keeping terminal paste payloads literal. */
|
|
4
|
+
export declare function clipboardPastePreference(input: string, key: InputKey, paste?: boolean): ClipboardPastePreference | null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isControlKey } from '../core/input.js';
|
|
2
|
+
/** Identify a clipboard gesture while keeping terminal paste payloads literal. */
|
|
3
|
+
export function clipboardPastePreference(input, key, paste = false) {
|
|
4
|
+
if (paste)
|
|
5
|
+
return null;
|
|
6
|
+
const command = key.super === true || (key.meta === true && key.alt !== true);
|
|
7
|
+
const isV = input.toLowerCase() === 'v';
|
|
8
|
+
if (isV && (command || (key.ctrl && key.shift)))
|
|
9
|
+
return 'text';
|
|
10
|
+
if (isV && key.ctrl)
|
|
11
|
+
return 'image';
|
|
12
|
+
if (isControlKey(input, key, 'i'))
|
|
13
|
+
return 'image-only';
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
* than only whichever one the host happens to run.
|
|
15
15
|
*/
|
|
16
16
|
export declare function generateIpcPath(prefix: string, platformName?: string): string;
|
|
17
|
+
/** Retire only directories allocated by this host, without recursive removal. */
|
|
18
|
+
export declare function removeOwnedIpcPath(endpoint: string): void;
|
|
17
19
|
/**
|
|
18
20
|
* True when the path names a Windows pipe rather than a filesystem entry.
|
|
19
21
|
*
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
* `\\.\pipe\<name>` form: libuv maps a bare path into the pipe namespace itself,
|
|
8
8
|
* so a filesystem-style path can never reach an AF_UNIX socket there.
|
|
9
9
|
*/
|
|
10
|
+
import { chmodSync, mkdtempSync, rmdirSync } from 'fs';
|
|
10
11
|
import { tmpdir } from 'os';
|
|
11
12
|
import { join } from 'path';
|
|
13
|
+
const ownedEndpoints = new Map();
|
|
12
14
|
/**
|
|
13
15
|
* Build a unique IPC endpoint name for the current process.
|
|
14
16
|
*
|
|
@@ -20,7 +22,33 @@ export function generateIpcPath(prefix, platformName = process.platform) {
|
|
|
20
22
|
if (platformName === 'win32') {
|
|
21
23
|
return `\\\\.\\pipe\\${prefix}-${unique}`;
|
|
22
24
|
}
|
|
23
|
-
|
|
25
|
+
const requested = join(tmpdir(), `${prefix}-${unique}.sock`);
|
|
26
|
+
// Darwin reserves one of its 104 address bytes for NUL. A long TMPDIR
|
|
27
|
+
// must not truncate distinct endpoints onto the same kernel address.
|
|
28
|
+
if (Buffer.byteLength(requested, 'utf8') <= 103)
|
|
29
|
+
return requested;
|
|
30
|
+
const channel = prefix.replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 16) || 'ztc-ipc';
|
|
31
|
+
const directory = mkdtempSync(join('/tmp', `${channel}-`));
|
|
32
|
+
chmodSync(directory, 0o700);
|
|
33
|
+
const endpoint = join(directory, 'socket');
|
|
34
|
+
ownedEndpoints.set(endpoint, directory);
|
|
35
|
+
return endpoint;
|
|
36
|
+
}
|
|
37
|
+
/** Retire only directories allocated by this host, without recursive removal. */
|
|
38
|
+
export function removeOwnedIpcPath(endpoint) {
|
|
39
|
+
const directory = ownedEndpoints.get(endpoint);
|
|
40
|
+
if (!directory)
|
|
41
|
+
return;
|
|
42
|
+
// The listener retires its endpoint first. Never delete anything a failed
|
|
43
|
+
// bind might have found in the allocated directory.
|
|
44
|
+
try {
|
|
45
|
+
rmdirSync(directory);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (error.code !== 'ENOENT')
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
ownedEndpoints.delete(endpoint);
|
|
24
52
|
}
|
|
25
53
|
/**
|
|
26
54
|
* True when the path names a Windows pipe rather than a filesystem entry.
|
|
@@ -4,5 +4,7 @@ export interface MuxPersistenceOptions {
|
|
|
4
4
|
}
|
|
5
5
|
export declare function resolveMuxPersistenceOptions(env?: NodeJS.ProcessEnv): MuxPersistenceOptions;
|
|
6
6
|
export declare function shouldPersistMuxPaneType(paneType: string, options: MuxPersistenceOptions): boolean;
|
|
7
|
-
export declare function isMuxPaneRestorable(pane: Pick<MuxPaneState, 'id' | 'pane_type'>, options: MuxPersistenceOptions): boolean;
|
|
7
|
+
export declare function isMuxPaneRestorable(pane: Pick<MuxPaneState, 'id' | 'pane_type' | 'agent_session'>, options: MuxPersistenceOptions): boolean;
|
|
8
8
|
export declare function sanitizeMuxSessionState(state: MuxSessionState, options: MuxPersistenceOptions): MuxSessionState;
|
|
9
|
+
/** Decode/admit a bounded checkpoint before traversing it or changing live panes. */
|
|
10
|
+
export declare function validateWorkspaceState(value: unknown): asserts value is MuxSessionState;
|
|
@@ -16,6 +16,9 @@ export function isMuxPaneRestorable(pane, options) {
|
|
|
16
16
|
if (pane.id === 0) {
|
|
17
17
|
return false;
|
|
18
18
|
}
|
|
19
|
+
// A canonical session link is descriptive; restoration never launches its saved argv.
|
|
20
|
+
if (pane.pane_type === 'ztc' && pane.agent_session)
|
|
21
|
+
return true;
|
|
19
22
|
return shouldPersistMuxPaneType(pane.pane_type, options);
|
|
20
23
|
}
|
|
21
24
|
function pruneMuxLayoutNode(node, allowedPaneIds) {
|
|
@@ -30,13 +33,14 @@ function pruneMuxLayoutNode(node, allowedPaneIds) {
|
|
|
30
33
|
return first || second;
|
|
31
34
|
}
|
|
32
35
|
export function sanitizeMuxSessionState(state, options) {
|
|
36
|
+
validateWorkspaceState(state);
|
|
33
37
|
const panes = state.panes.filter((pane) => isMuxPaneRestorable(pane, options));
|
|
34
38
|
const allowedPaneIds = new Set([0, ...panes.map((pane) => pane.id)]);
|
|
35
39
|
const layout = pruneMuxLayoutNode(state.layout, allowedPaneIds) || { type: 'leaf', pane_id: 0 };
|
|
36
40
|
const layoutPaneIds = new Set(collectMuxLayoutPaneIds(layout));
|
|
37
41
|
const focused_pane_id = layoutPaneIds.has(state.focused_pane_id)
|
|
38
42
|
? state.focused_pane_id
|
|
39
|
-
: 0;
|
|
43
|
+
: collectMuxLayoutPaneIds(layout)[0];
|
|
40
44
|
const zoomed_pane_id = state.zoomed_pane_id !== undefined
|
|
41
45
|
&& layoutPaneIds.has(state.zoomed_pane_id)
|
|
42
46
|
? state.zoomed_pane_id
|
|
@@ -47,8 +51,142 @@ export function sanitizeMuxSessionState(state, options) {
|
|
|
47
51
|
zoomed_pane_id,
|
|
48
52
|
layout,
|
|
49
53
|
panes,
|
|
54
|
+
...(state.windows ? { windows: state.windows.map(window => {
|
|
55
|
+
const windowLayout = pruneMuxLayoutNode(window.layout, allowedPaneIds) || { type: 'leaf', pane_id: 0 };
|
|
56
|
+
const ids = new Set(collectMuxLayoutPaneIds(windowLayout));
|
|
57
|
+
return { ...window, layout: windowLayout,
|
|
58
|
+
focused_pane_id: ids.has(window.focused_pane_id) ? window.focused_pane_id : collectMuxLayoutPaneIds(windowLayout)[0],
|
|
59
|
+
zoomed_pane_id: window.zoomed_pane_id !== undefined && ids.has(window.zoomed_pane_id) ? window.zoomed_pane_id : undefined };
|
|
60
|
+
}) } : {}),
|
|
50
61
|
};
|
|
51
62
|
}
|
|
63
|
+
/** Decode/admit a bounded checkpoint before traversing it or changing live panes. */
|
|
64
|
+
export function validateWorkspaceState(value) {
|
|
65
|
+
const object = (v) => {
|
|
66
|
+
if (!v || typeof v !== 'object' || Array.isArray(v))
|
|
67
|
+
throw new Error('Workspace requires an object');
|
|
68
|
+
return v;
|
|
69
|
+
};
|
|
70
|
+
const id = (v) => {
|
|
71
|
+
if (typeof v !== 'number' || !Number.isInteger(v) || v < 0 || v > 0xffffffff)
|
|
72
|
+
throw new Error('Workspace identity must be an unsigned integer');
|
|
73
|
+
return v;
|
|
74
|
+
};
|
|
75
|
+
const text = (v, max) => {
|
|
76
|
+
if (typeof v !== 'string' || Buffer.byteLength(v) > max)
|
|
77
|
+
throw new Error('Workspace metadata exceeds its bounds');
|
|
78
|
+
};
|
|
79
|
+
const saved = object(value);
|
|
80
|
+
if (saved.schema_version !== undefined && saved.schema_version !== 1)
|
|
81
|
+
throw new Error(`Unsupported workspace schema version ${String(saved.schema_version)}`);
|
|
82
|
+
if (!Array.isArray(saved.panes) || saved.panes.length > 256)
|
|
83
|
+
throw new Error('Workspace requires at most 256 panes');
|
|
84
|
+
const paneIds = new Set();
|
|
85
|
+
for (const entry of saved.panes) {
|
|
86
|
+
const pane = object(entry);
|
|
87
|
+
const paneId = id(pane.id);
|
|
88
|
+
if (paneIds.has(paneId))
|
|
89
|
+
throw new Error(`Duplicate workspace pane ID ${paneId}`);
|
|
90
|
+
paneIds.add(paneId);
|
|
91
|
+
text(pane.title, 4096);
|
|
92
|
+
text(pane.pane_type, 64);
|
|
93
|
+
for (const key of ['command', 'cwd'])
|
|
94
|
+
if (pane[key] !== undefined && pane[key] !== null)
|
|
95
|
+
text(pane[key], 65536);
|
|
96
|
+
if (pane.content !== undefined && pane.content !== null)
|
|
97
|
+
text(pane.content, 4 * 1024 * 1024);
|
|
98
|
+
if (pane.args !== undefined) {
|
|
99
|
+
if (!Array.isArray(pane.args) || pane.args.length > 256)
|
|
100
|
+
throw new Error('Workspace arguments exceed their bounds');
|
|
101
|
+
pane.args.forEach(arg => text(arg, 65536));
|
|
102
|
+
}
|
|
103
|
+
if (pane.agent_session !== undefined && pane.agent_session !== null) {
|
|
104
|
+
const ref = object(pane.agent_session);
|
|
105
|
+
text(ref.session_id, 256);
|
|
106
|
+
text(ref.project_path, 65536);
|
|
107
|
+
if (!ref.session_id || !ref.project_path)
|
|
108
|
+
throw new Error('Workspace agent session requires a bounded session ID and project path');
|
|
109
|
+
}
|
|
110
|
+
if (pane.restoration_status !== undefined && pane.restoration_status !== null
|
|
111
|
+
&& (typeof pane.restoration_status !== 'string' || !['not_started', 'missing_command', 'missing_directory', 'session_missing', 'session_active_elsewhere', 'session_unreadable'].includes(pane.restoration_status)))
|
|
112
|
+
throw new Error('Unknown workspace restoration status');
|
|
113
|
+
}
|
|
114
|
+
paneIds.add(0);
|
|
115
|
+
const layout = (v, depth = 0) => {
|
|
116
|
+
if (depth > 64)
|
|
117
|
+
throw new Error('Workspace layout exceeds depth 64');
|
|
118
|
+
const node = object(v);
|
|
119
|
+
if (node.type === 'leaf') {
|
|
120
|
+
const paneId = id(node.pane_id);
|
|
121
|
+
if (!paneIds.has(paneId))
|
|
122
|
+
throw new Error(`Workspace layout names missing pane ${paneId}`);
|
|
123
|
+
return new Set([paneId]);
|
|
124
|
+
}
|
|
125
|
+
if (node.type !== 'split' || typeof node.direction !== 'string' || !['horizontal', 'vertical'].includes(node.direction))
|
|
126
|
+
throw new Error('Workspace requires a valid layout node');
|
|
127
|
+
if (typeof node.ratio !== 'number' || !Number.isFinite(node.ratio) || node.ratio <= 0 || node.ratio >= 1)
|
|
128
|
+
throw new Error('Workspace split ratio must be between 0 and 1');
|
|
129
|
+
const ids = layout(node.first, depth + 1);
|
|
130
|
+
for (const second of layout(node.second, depth + 1)) {
|
|
131
|
+
if (ids.has(second))
|
|
132
|
+
throw new Error(`Duplicate workspace layout pane ID ${second}`);
|
|
133
|
+
ids.add(second);
|
|
134
|
+
}
|
|
135
|
+
return ids;
|
|
136
|
+
};
|
|
137
|
+
layout(saved.layout);
|
|
138
|
+
if (!paneIds.has(id(saved.focused_pane_id)) || (saved.zoomed_pane_id !== undefined && saved.zoomed_pane_id !== null && !paneIds.has(id(saved.zoomed_pane_id))))
|
|
139
|
+
throw new Error('Workspace focus names a missing pane');
|
|
140
|
+
const windows = saved.windows ?? [];
|
|
141
|
+
if (!Array.isArray(windows) || windows.length > 64)
|
|
142
|
+
throw new Error('Workspace requires at most 64 windows');
|
|
143
|
+
const windowIds = new Set();
|
|
144
|
+
const paneWindows = new Map();
|
|
145
|
+
for (const entry of windows) {
|
|
146
|
+
const window = object(entry);
|
|
147
|
+
const windowId = id(window.id);
|
|
148
|
+
if (windowIds.has(windowId))
|
|
149
|
+
throw new Error(`Duplicate workspace window ID ${windowId}`);
|
|
150
|
+
windowIds.add(windowId);
|
|
151
|
+
text(window.title, 4096);
|
|
152
|
+
for (const key of ['color', 'pattern'])
|
|
153
|
+
if (window[key] !== undefined && window[key] !== null)
|
|
154
|
+
text(window[key], 64);
|
|
155
|
+
const ids = layout(window.layout);
|
|
156
|
+
for (const paneId of ids) {
|
|
157
|
+
if (paneId === 0)
|
|
158
|
+
continue;
|
|
159
|
+
if (paneWindows.has(paneId))
|
|
160
|
+
throw new Error(`Workspace pane ${paneId} appears in multiple windows`);
|
|
161
|
+
paneWindows.set(paneId, windowId);
|
|
162
|
+
}
|
|
163
|
+
if (!ids.has(id(window.focused_pane_id)) || (window.zoomed_pane_id !== undefined && window.zoomed_pane_id !== null && !ids.has(id(window.zoomed_pane_id))))
|
|
164
|
+
throw new Error('Workspace window focus names a missing pane');
|
|
165
|
+
}
|
|
166
|
+
if (windows.length) {
|
|
167
|
+
for (const entry of saved.panes) {
|
|
168
|
+
const pane = object(entry);
|
|
169
|
+
const paneId = id(pane.id);
|
|
170
|
+
if (paneId !== 0 && pane.window_id !== undefined && pane.window_id !== null
|
|
171
|
+
&& paneWindows.has(paneId) && paneWindows.get(paneId) !== id(pane.window_id))
|
|
172
|
+
throw new Error(`Workspace pane ${paneId} window assignment contradicts its layout`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (windows.length && ((saved.active_window_id !== undefined && saved.active_window_id !== null && !windowIds.has(id(saved.active_window_id)))
|
|
176
|
+
|| saved.panes.some(entry => { const pane = object(entry); return pane.window_id !== undefined && pane.window_id !== null && !windowIds.has(id(pane.window_id)); })))
|
|
177
|
+
throw new Error('Workspace names a missing window');
|
|
178
|
+
if (saved.geometry !== undefined && saved.geometry !== null) {
|
|
179
|
+
const geometry = object(saved.geometry);
|
|
180
|
+
for (const key of ['cols', 'rows', 'pixel_width', 'pixel_height']) {
|
|
181
|
+
const v = geometry[key];
|
|
182
|
+
if (v === undefined || v === null)
|
|
183
|
+
continue;
|
|
184
|
+
const cells = key === 'cols' || key === 'rows';
|
|
185
|
+
if (typeof v !== 'number' || !Number.isFinite(v) || v <= 0 || v > (cells ? 10000 : 32768) || (cells && !Number.isInteger(v)))
|
|
186
|
+
throw new Error('Workspace geometry must be positive and bounded');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
52
190
|
function collectMuxLayoutPaneIds(node) {
|
|
53
191
|
if (node.type === 'leaf') {
|
|
54
192
|
return [node.pane_id];
|
|
@@ -25,7 +25,7 @@ export declare class PaneRelayServer {
|
|
|
25
25
|
private tuiUnsubscribe;
|
|
26
26
|
constructor(transport: PaneCommandTransport, socketPath: string);
|
|
27
27
|
/** Start listening for child connections */
|
|
28
|
-
start(): void
|
|
28
|
+
start(): Promise<void>;
|
|
29
29
|
/** Broadcast a pane event to all connected children */
|
|
30
30
|
private broadcast;
|
|
31
31
|
/** Stop the relay server and clean up */
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { createServer, createConnection } from 'net';
|
|
13
13
|
import { createInterface } from 'readline';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { generateIpcPath,
|
|
14
|
+
import { serializeCommand, parseEvent, CAPABILITY_PANE_DELIVERY_ACK, CAPABILITY_DESKTOP_TASK_CONTROLS, CAPABILITY_DESKTOP_RUNTIME_CONTROLS, CAPABILITY_DESKTOP_SESSION_SHARE } from './protocol.js';
|
|
15
|
+
import { runtimeDiag } from '../../utils/debug_log.js';
|
|
16
|
+
import { generateIpcPath, removeOwnedIpcPath } from './ipc_path.js';
|
|
17
17
|
// ============================================================================
|
|
18
18
|
// PaneRelayServer — runs in parent ZTC (--mux mode)
|
|
19
19
|
// ============================================================================
|
|
@@ -27,6 +27,9 @@ const PANE_EVENT_TYPES = new Set([
|
|
|
27
27
|
'pane_state',
|
|
28
28
|
'pane_output',
|
|
29
29
|
'error',
|
|
30
|
+
'desktop_task_action',
|
|
31
|
+
'desktop_runtime_action',
|
|
32
|
+
'desktop_session_share_action',
|
|
30
33
|
]);
|
|
31
34
|
export class PaneRelayServer {
|
|
32
35
|
transport;
|
|
@@ -39,7 +42,9 @@ export class PaneRelayServer {
|
|
|
39
42
|
this.socketPath = socketPath;
|
|
40
43
|
}
|
|
41
44
|
/** Start listening for child connections */
|
|
42
|
-
start() {
|
|
45
|
+
async start() {
|
|
46
|
+
if (this.server !== null)
|
|
47
|
+
throw new Error('Pane relay is already started.');
|
|
43
48
|
// Subscribe to pane events from the parent's TuiProcess
|
|
44
49
|
this.tuiUnsubscribe = this.transport.on((event) => {
|
|
45
50
|
if (PANE_EVENT_TYPES.has(event.type)) {
|
|
@@ -49,9 +54,15 @@ export class PaneRelayServer {
|
|
|
49
54
|
this.server = createServer((client) => {
|
|
50
55
|
this.clients.add(client);
|
|
51
56
|
client.write(JSON.stringify({ type: 'ready', version: 'pane-relay', cols: 0, rows: 0,
|
|
52
|
-
capabilities:
|
|
57
|
+
capabilities: [CAPABILITY_PANE_DELIVERY_ACK, 'pane_labels_v1', CAPABILITY_DESKTOP_TASK_CONTROLS, CAPABILITY_DESKTOP_RUNTIME_CONTROLS, CAPABILITY_DESKTOP_SESSION_SHARE]
|
|
58
|
+
.filter(capability => this.transport.hasCapability?.(capability)),
|
|
53
59
|
}) + '\n');
|
|
54
60
|
const rl = createInterface({ input: client, crlfDelay: Infinity });
|
|
61
|
+
// Readline re-emits input errors; one failed peer must not terminate its parent.
|
|
62
|
+
rl.on('error', () => {
|
|
63
|
+
this.clients.delete(client);
|
|
64
|
+
client.destroy();
|
|
65
|
+
});
|
|
55
66
|
rl.on('line', (line) => {
|
|
56
67
|
const parsed = parseEvent(line);
|
|
57
68
|
if (!parsed)
|
|
@@ -68,21 +79,29 @@ export class PaneRelayServer {
|
|
|
68
79
|
rl.close();
|
|
69
80
|
});
|
|
70
81
|
});
|
|
71
|
-
this.server
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
const server = this.server;
|
|
83
|
+
try {
|
|
84
|
+
await new Promise((resolve, reject) => {
|
|
85
|
+
const failed = (error) => reject(error);
|
|
86
|
+
server.once('error', failed);
|
|
87
|
+
server.once('listening', () => {
|
|
88
|
+
server.off('error', failed);
|
|
89
|
+
server.on('error', error => {
|
|
90
|
+
runtimeDiag('error', `Pane relay stopped: ${error.message}`);
|
|
91
|
+
this.stop();
|
|
92
|
+
});
|
|
93
|
+
resolve();
|
|
94
|
+
});
|
|
95
|
+
server.listen(this.socketPath);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
// An occupied address is not proof that its owner crashed. Never unlink
|
|
100
|
+
// another listener or spin in a repeated listen/error retry cycle.
|
|
101
|
+
this.stop();
|
|
102
|
+
const cause = error instanceof Error ? error : new Error(String(error));
|
|
103
|
+
throw new Error(`Pane relay could not listen: ${cause.message}`, { cause });
|
|
104
|
+
}
|
|
86
105
|
}
|
|
87
106
|
/** Broadcast a pane event to all connected children */
|
|
88
107
|
broadcast(event) {
|
|
@@ -110,15 +129,18 @@ export class PaneRelayServer {
|
|
|
110
129
|
}
|
|
111
130
|
this.clients.clear();
|
|
112
131
|
if (this.server) {
|
|
113
|
-
this.server.close()
|
|
132
|
+
this.server.close(() => {
|
|
133
|
+
try {
|
|
134
|
+
removeOwnedIpcPath(this.socketPath);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
runtimeDiag('error', `Pane relay IPC cleanup failed: ${String(error)}`);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
114
140
|
this.server = null;
|
|
115
141
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
unlinkSync(this.socketPath);
|
|
119
|
-
}
|
|
120
|
-
catch { /* ignore */ }
|
|
121
|
-
}
|
|
142
|
+
// Node closes its own bound endpoint. A failed bind never owns a path
|
|
143
|
+
// and must not unlink a file belonging to an existing listener.
|
|
122
144
|
}
|
|
123
145
|
}
|
|
124
146
|
// ============================================================================
|
|
@@ -194,6 +216,12 @@ export class PaneRelayClient {
|
|
|
194
216
|
this.ready = false;
|
|
195
217
|
this.cleanup();
|
|
196
218
|
});
|
|
219
|
+
// readline forwards input errors independently of the socket listener.
|
|
220
|
+
// A stale write after the parent closes must retire this transport too.
|
|
221
|
+
this.readline.on('error', () => {
|
|
222
|
+
this.ready = false;
|
|
223
|
+
this.cleanup();
|
|
224
|
+
});
|
|
197
225
|
this.socket.on('error', () => {
|
|
198
226
|
this.ready = false;
|
|
199
227
|
this.cleanup();
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* a fullscreen multiplexer with split panes (alternate screen mode).
|
|
10
10
|
*/
|
|
11
11
|
import type { RustCommand, RustEvent } from './protocol.js';
|
|
12
|
+
import { type DesktopRuntime } from '../../desktop/runtime.js';
|
|
12
13
|
export type TuiEventHandler = (event: RustEvent) => void;
|
|
13
14
|
/**
|
|
14
15
|
* Get the path to the zmux binary
|
|
@@ -32,7 +33,7 @@ export declare function isZmuxAvailable(): boolean;
|
|
|
32
33
|
* Check if zterm is available. Unlike zmux, zterm is a desktop process and
|
|
33
34
|
* does not require the current process to have a TTY.
|
|
34
35
|
*/
|
|
35
|
-
export declare function isZtermAvailable(): boolean;
|
|
36
|
+
export declare function isZtermAvailable(admission?: DesktopRuntime | null): boolean;
|
|
36
37
|
/**
|
|
37
38
|
* Launch the native zterm desktop binary and resolve with its exit code.
|
|
38
39
|
*/
|
|
@@ -83,6 +84,11 @@ export declare function isTransientSocketConnectError(code: string | undefined):
|
|
|
83
84
|
* Manages the Rust TUI process with Unix socket communication
|
|
84
85
|
*/
|
|
85
86
|
export declare class TuiProcess {
|
|
87
|
+
private readonly options;
|
|
88
|
+
/** Host-selected unmanaged renderer; validated bundle admission takes precedence. */
|
|
89
|
+
constructor(options?: {
|
|
90
|
+
desktopBinaryPath?: string;
|
|
91
|
+
});
|
|
86
92
|
private process;
|
|
87
93
|
private socket;
|
|
88
94
|
private readline;
|
|
@@ -98,6 +104,9 @@ export declare class TuiProcess {
|
|
|
98
104
|
private _muxMode;
|
|
99
105
|
/** Whether zterm is being used as the native desktop renderer */
|
|
100
106
|
private _desktopMode;
|
|
107
|
+
private desktopCompatibility;
|
|
108
|
+
/** Retained across socket cleanup so an admitted renderer can request owner exit. */
|
|
109
|
+
private desktopStartupAdmitted;
|
|
101
110
|
private stopping;
|
|
102
111
|
/** Whether zmux was detected from the ready event version string */
|
|
103
112
|
private _isZmux;
|
|
@@ -123,6 +132,7 @@ export declare class TuiProcess {
|
|
|
123
132
|
*/
|
|
124
133
|
private clipboardRequests;
|
|
125
134
|
private clipboardRequestSeq;
|
|
135
|
+
private clipboardTextRequests;
|
|
126
136
|
/**
|
|
127
137
|
* Subscribe to zmux's mirror-socket path. The callback runs exactly once:
|
|
128
138
|
* synchronously if the path is already known, otherwise as soon as zmux
|
|
@@ -151,6 +161,9 @@ export declare class TuiProcess {
|
|
|
151
161
|
*/
|
|
152
162
|
readClipboardImage(timeoutMs?: number): Promise<Buffer | null>;
|
|
153
163
|
private settleClipboardRequest;
|
|
164
|
+
/** Read exact text through the renderer; null means unavailable, '' means empty. */
|
|
165
|
+
readClipboardText(timeoutMs?: number): Promise<string | null>;
|
|
166
|
+
private settleClipboardTextRequest;
|
|
154
167
|
/**
|
|
155
168
|
* Mirror socket path this zmux is exposing, or null if unavailable
|
|
156
169
|
* (non-zmux mode, bind failed, or announcement not received yet).
|
|
@@ -167,6 +180,8 @@ export declare class TuiProcess {
|
|
|
167
180
|
mux?: boolean;
|
|
168
181
|
headless?: boolean;
|
|
169
182
|
desktop?: boolean;
|
|
183
|
+
/** Admission from this host's CLI bootstrap, never an environment cache. */
|
|
184
|
+
desktopRuntime?: DesktopRuntime | null;
|
|
170
185
|
desktopUpdateRelaunch?: string;
|
|
171
186
|
/** Extra environment for the renderer process (e.g. the zmux keymap). */
|
|
172
187
|
env?: Record<string, string>;
|
|
@@ -218,6 +233,7 @@ export declare class NullTuiProcess {
|
|
|
218
233
|
get zmuxMirrorSocketPath(): string | null;
|
|
219
234
|
hasCapability(_name: string): boolean;
|
|
220
235
|
readClipboardImage(): Promise<Buffer | null>;
|
|
236
|
+
readClipboardText(): Promise<string | null>;
|
|
221
237
|
/** NullTuiProcess never has a mirror socket; callback never fires. */
|
|
222
238
|
onZmuxMirrorSocketReady(_cb: (path: string) => void): () => void;
|
|
223
239
|
on(handler: TuiEventHandler): () => void;
|
|
@@ -15,8 +15,9 @@ import { join, dirname, resolve } from 'path';
|
|
|
15
15
|
import { homedir, platform, arch, tmpdir } from 'os';
|
|
16
16
|
import { fileURLToPath } from 'url';
|
|
17
17
|
import { createConnection } from 'net';
|
|
18
|
-
import { serializeCommand, parseEvent, CAPABILITY_CLIPBOARD_IMAGE } from './protocol.js';
|
|
19
|
-
import { generateIpcPath } from './ipc_path.js';
|
|
18
|
+
import { serializeCommand, parseEvent, CAPABILITY_CLIPBOARD_IMAGE, CAPABILITY_CLIPBOARD_TEXT } from './protocol.js';
|
|
19
|
+
import { generateIpcPath, removeOwnedIpcPath } from './ipc_path.js';
|
|
20
|
+
import { loadDesktopRuntime, validateDesktopRendererReady } from '../../desktop/runtime.js';
|
|
20
21
|
// Debug log file - use a file to avoid interfering with TUI
|
|
21
22
|
const DEBUG_LOG_FILE = join(tmpdir(), `ztc-debug-${process.pid}.log`);
|
|
22
23
|
function debugLog(message) {
|
|
@@ -203,7 +204,10 @@ export function resolveZtermBinaryPath(dependencies) {
|
|
|
203
204
|
return dependencies.resolveFallback();
|
|
204
205
|
}
|
|
205
206
|
/** Get the path to the zterm desktop binary. */
|
|
206
|
-
function getZtermBinaryPath() {
|
|
207
|
+
function getZtermBinaryPath(admission) {
|
|
208
|
+
const runtime = admission === undefined ? loadDesktopRuntime() : admission;
|
|
209
|
+
if (runtime)
|
|
210
|
+
return runtime.rendererPath;
|
|
207
211
|
const binaryName = getZtermBinaryName();
|
|
208
212
|
return resolveZtermBinaryPath({
|
|
209
213
|
operatingSystem: platform(),
|
|
@@ -222,8 +226,8 @@ export function isZmuxAvailable() {
|
|
|
222
226
|
* Check if zterm is available. Unlike zmux, zterm is a desktop process and
|
|
223
227
|
* does not require the current process to have a TTY.
|
|
224
228
|
*/
|
|
225
|
-
export function isZtermAvailable() {
|
|
226
|
-
return getZtermBinaryPath() !== null;
|
|
229
|
+
export function isZtermAvailable(admission) {
|
|
230
|
+
return getZtermBinaryPath(admission) !== null;
|
|
227
231
|
}
|
|
228
232
|
/**
|
|
229
233
|
* Launch the native zterm desktop binary and resolve with its exit code.
|
|
@@ -314,6 +318,11 @@ export function isTransientSocketConnectError(code) {
|
|
|
314
318
|
* Manages the Rust TUI process with Unix socket communication
|
|
315
319
|
*/
|
|
316
320
|
export class TuiProcess {
|
|
321
|
+
options;
|
|
322
|
+
/** Host-selected unmanaged renderer; validated bundle admission takes precedence. */
|
|
323
|
+
constructor(options = {}) {
|
|
324
|
+
this.options = options;
|
|
325
|
+
}
|
|
317
326
|
process = null;
|
|
318
327
|
socket = null;
|
|
319
328
|
readline = null;
|
|
@@ -329,6 +338,9 @@ export class TuiProcess {
|
|
|
329
338
|
_muxMode = false;
|
|
330
339
|
/** Whether zterm is being used as the native desktop renderer */
|
|
331
340
|
_desktopMode = false;
|
|
341
|
+
desktopCompatibility = null;
|
|
342
|
+
/** Retained across socket cleanup so an admitted renderer can request owner exit. */
|
|
343
|
+
desktopStartupAdmitted = false;
|
|
332
344
|
stopping = false;
|
|
333
345
|
/** Whether zmux was detected from the ready event version string */
|
|
334
346
|
_isZmux = false;
|
|
@@ -354,6 +366,7 @@ export class TuiProcess {
|
|
|
354
366
|
*/
|
|
355
367
|
clipboardRequests = new Map();
|
|
356
368
|
clipboardRequestSeq = 0;
|
|
369
|
+
clipboardTextRequests = new Map();
|
|
357
370
|
/**
|
|
358
371
|
* Subscribe to zmux's mirror-socket path. The callback runs exactly once:
|
|
359
372
|
* synchronously if the path is already known, otherwise as soon as zmux
|
|
@@ -436,6 +449,26 @@ export class TuiProcess {
|
|
|
436
449
|
this.clipboardRequests.delete(requestId);
|
|
437
450
|
pending.resolve(png);
|
|
438
451
|
}
|
|
452
|
+
/** Read exact text through the renderer; null means unavailable, '' means empty. */
|
|
453
|
+
readClipboardText(timeoutMs = 4000) {
|
|
454
|
+
if (!this.hasCapability(CAPABILITY_CLIPBOARD_TEXT))
|
|
455
|
+
return Promise.resolve(null);
|
|
456
|
+
const requestId = `clip-text-${++this.clipboardRequestSeq}-${Date.now().toString(36)}`;
|
|
457
|
+
return new Promise((resolve) => {
|
|
458
|
+
const timer = setTimeout(() => this.settleClipboardTextRequest(requestId, null), timeoutMs);
|
|
459
|
+
this.clipboardTextRequests.set(requestId, { resolve, timer });
|
|
460
|
+
if (!this.send({ type: 'read_clipboard_text', request_id: requestId }))
|
|
461
|
+
this.settleClipboardTextRequest(requestId, null);
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
settleClipboardTextRequest(requestId, text) {
|
|
465
|
+
const pending = this.clipboardTextRequests.get(requestId);
|
|
466
|
+
if (!pending)
|
|
467
|
+
return;
|
|
468
|
+
clearTimeout(pending.timer);
|
|
469
|
+
this.clipboardTextRequests.delete(requestId);
|
|
470
|
+
pending.resolve(text);
|
|
471
|
+
}
|
|
439
472
|
/**
|
|
440
473
|
* Mirror socket path this zmux is exposing, or null if unavailable
|
|
441
474
|
* (non-zmux mode, bind failed, or announcement not received yet).
|
|
@@ -456,12 +489,21 @@ export class TuiProcess {
|
|
|
456
489
|
}
|
|
457
490
|
this._muxMode = options?.mux ?? false;
|
|
458
491
|
this._desktopMode = options?.desktop ?? false;
|
|
492
|
+
this.desktopCompatibility = null;
|
|
493
|
+
this.desktopStartupAdmitted = false;
|
|
494
|
+
this._capabilities.clear();
|
|
495
|
+
this.stopping = false;
|
|
459
496
|
let binaryPath;
|
|
460
497
|
if (this._desktopMode) {
|
|
461
|
-
|
|
498
|
+
const runtime = options?.desktopRuntime === undefined ? loadDesktopRuntime() : options.desktopRuntime;
|
|
499
|
+
binaryPath = runtime?.rendererPath ?? this.options.desktopBinaryPath ?? getZtermBinaryPath(runtime);
|
|
462
500
|
if (!binaryPath) {
|
|
463
501
|
throw new Error('zterm binary not found. Build with: cd packages/zterm && cargo build --release');
|
|
464
502
|
}
|
|
503
|
+
if (runtime)
|
|
504
|
+
this.desktopCompatibility = { version: runtime.rendererVersion, requiredCapabilities: runtime.requiredCapabilities };
|
|
505
|
+
else if (binaryPath === resolveInstalledZtermExecutable())
|
|
506
|
+
this.desktopCompatibility = {};
|
|
465
507
|
}
|
|
466
508
|
else if (this._muxMode) {
|
|
467
509
|
binaryPath = getZmuxBinaryPath();
|
|
@@ -576,7 +618,7 @@ export class TuiProcess {
|
|
|
576
618
|
this.process.on('close', (code, signal) => {
|
|
577
619
|
debugLog(`[TuiProcess] Process closed: code=${code}, signal=${signal}`);
|
|
578
620
|
debugLog(`[TuiProcess] stderr buffer at close: ${stderrBuffer || '(empty)'}`);
|
|
579
|
-
const shouldExitOwner = this._desktopMode && this.
|
|
621
|
+
const shouldExitOwner = this._desktopMode && this.desktopStartupAdmitted && !this.stopping;
|
|
580
622
|
this.cleanup();
|
|
581
623
|
if (shouldExitOwner) {
|
|
582
624
|
this.emit({ type: 'quit_requested' });
|
|
@@ -734,7 +776,24 @@ export class TuiProcess {
|
|
|
734
776
|
this.settleClipboardRequest(event.request_id, event.png_base64 ? Buffer.from(event.png_base64, 'base64') : null);
|
|
735
777
|
return;
|
|
736
778
|
}
|
|
779
|
+
if (event.type === 'clipboard_text') {
|
|
780
|
+
this.settleClipboardTextRequest(event.request_id, !event.error && typeof event.text === 'string' ? event.text : null);
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
737
783
|
if (event.type === 'ready' && this.readyResolve) {
|
|
784
|
+
if (this.desktopCompatibility) {
|
|
785
|
+
try {
|
|
786
|
+
validateDesktopRendererReady(event, this.desktopCompatibility.version, this.desktopCompatibility.requiredCapabilities);
|
|
787
|
+
}
|
|
788
|
+
catch (error) {
|
|
789
|
+
this.readyReject?.(error);
|
|
790
|
+
this.readyResolve = null;
|
|
791
|
+
this.readyReject = null;
|
|
792
|
+
this.cleanup();
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
this.desktopStartupAdmitted = this._desktopMode;
|
|
738
797
|
this.ready = true;
|
|
739
798
|
this._isZmux = event.version.startsWith('zmux-') || event.version.startsWith('zterm-');
|
|
740
799
|
if (event.capabilities) {
|
|
@@ -783,6 +842,11 @@ export class TuiProcess {
|
|
|
783
842
|
pending.resolve(null);
|
|
784
843
|
}
|
|
785
844
|
this.clipboardRequests.clear();
|
|
845
|
+
for (const pending of this.clipboardTextRequests.values()) {
|
|
846
|
+
clearTimeout(pending.timer);
|
|
847
|
+
pending.resolve(null);
|
|
848
|
+
}
|
|
849
|
+
this.clipboardTextRequests.clear();
|
|
786
850
|
if (this.connectRetryTimer) {
|
|
787
851
|
clearTimeout(this.connectRetryTimer);
|
|
788
852
|
this.connectRetryTimer = null;
|
|
@@ -802,6 +866,12 @@ export class TuiProcess {
|
|
|
802
866
|
catch {
|
|
803
867
|
// Ignore
|
|
804
868
|
}
|
|
869
|
+
try {
|
|
870
|
+
removeOwnedIpcPath(this.socketPath);
|
|
871
|
+
}
|
|
872
|
+
catch (error) {
|
|
873
|
+
debugLog(`[TuiProcess] IPC directory cleanup failed: ${String(error)}`);
|
|
874
|
+
}
|
|
805
875
|
this.socketPath = null;
|
|
806
876
|
}
|
|
807
877
|
// Tearing down without signalling a still-running child orphans the native
|
|
@@ -884,6 +954,9 @@ export class NullTuiProcess {
|
|
|
884
954
|
readClipboardImage() {
|
|
885
955
|
return Promise.resolve(null);
|
|
886
956
|
}
|
|
957
|
+
readClipboardText() {
|
|
958
|
+
return Promise.resolve(null);
|
|
959
|
+
}
|
|
887
960
|
/** NullTuiProcess never has a mirror socket; callback never fires. */
|
|
888
961
|
onZmuxMirrorSocketReady(_cb) {
|
|
889
962
|
return () => { };
|