@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
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const MAX_PLAN_BYTES = 16 * 1024;
|
|
2
|
+
const MAX_STEPS = 8;
|
|
3
|
+
const MAX_STAGES = 8;
|
|
4
|
+
const utf8 = new TextEncoder();
|
|
5
|
+
const stepId = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/;
|
|
6
|
+
function object(value) {
|
|
7
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
8
|
+
return false;
|
|
9
|
+
const prototype = Object.getPrototypeOf(value);
|
|
10
|
+
return prototype === Object.prototype || prototype === null;
|
|
11
|
+
}
|
|
12
|
+
function keys(value, required, optional = []) {
|
|
13
|
+
return required.every(key => Object.hasOwn(value, key))
|
|
14
|
+
&& Object.keys(value).every(key => required.includes(key) || optional.includes(key));
|
|
15
|
+
}
|
|
16
|
+
function string(value, maxBytes, allowEmpty = false) {
|
|
17
|
+
return typeof value === 'string' && (allowEmpty || value.length > 0)
|
|
18
|
+
&& !value.includes('\0') && utf8.encode(value).byteLength <= maxBytes;
|
|
19
|
+
}
|
|
20
|
+
function jsonBytes(value) {
|
|
21
|
+
try {
|
|
22
|
+
const encoded = JSON.stringify(value);
|
|
23
|
+
return encoded === undefined ? Infinity : utf8.encode(encoded).byteLength;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return Infinity;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function exitCode(value) {
|
|
30
|
+
return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 && value <= 255;
|
|
31
|
+
}
|
|
32
|
+
function codes(value) {
|
|
33
|
+
if (!Array.isArray(value) || value.length < 1 || value.length > 8
|
|
34
|
+
|| ![...value].every(exitCode) || new Set(value).size !== value.length)
|
|
35
|
+
return null;
|
|
36
|
+
return [...value];
|
|
37
|
+
}
|
|
38
|
+
/** Parse a bounded literal process plan; shell text is never inferred from its arguments. */
|
|
39
|
+
export function parseCheckedCommandPlan(value) {
|
|
40
|
+
if (jsonBytes(value) > MAX_PLAN_BYTES || !object(value) || !keys(value, ['steps'])
|
|
41
|
+
|| !Array.isArray(value.steps) || value.steps.length < 1 || value.steps.length > MAX_STEPS)
|
|
42
|
+
return null;
|
|
43
|
+
const steps = [];
|
|
44
|
+
const ids = new Set();
|
|
45
|
+
for (const rawStep of value.steps) {
|
|
46
|
+
if (!object(rawStep) || !keys(rawStep, ['id', 'pipeline']) || typeof rawStep.id !== 'string'
|
|
47
|
+
|| !stepId.test(rawStep.id) || ids.has(rawStep.id) || !Array.isArray(rawStep.pipeline)
|
|
48
|
+
|| rawStep.pipeline.length < 1 || rawStep.pipeline.length > MAX_STAGES)
|
|
49
|
+
return null;
|
|
50
|
+
const pipeline = [];
|
|
51
|
+
for (const rawStage of rawStep.pipeline) {
|
|
52
|
+
if (!object(rawStage) || !keys(rawStage, ['executable', 'args'], ['acceptable_exit_codes'])
|
|
53
|
+
|| !string(rawStage.executable, 512) || !Array.isArray(rawStage.args) || rawStage.args.length > 64
|
|
54
|
+
|| ![...rawStage.args].every(arg => string(arg, 4096, true)))
|
|
55
|
+
return null;
|
|
56
|
+
const accepted = Object.hasOwn(rawStage, 'acceptable_exit_codes') ? codes(rawStage.acceptable_exit_codes) : [0];
|
|
57
|
+
if (!accepted)
|
|
58
|
+
return null;
|
|
59
|
+
pipeline.push({ executable: rawStage.executable, args: [...rawStage.args], acceptable_exit_codes: accepted });
|
|
60
|
+
}
|
|
61
|
+
ids.add(rawStep.id);
|
|
62
|
+
steps.push({ id: rawStep.id, pipeline });
|
|
63
|
+
}
|
|
64
|
+
const parsed = { steps };
|
|
65
|
+
return jsonBytes(parsed) <= MAX_PLAN_BYTES ? parsed : null;
|
|
66
|
+
}
|
|
67
|
+
/** Parse declared process outcomes without turning them into source or build qualification. */
|
|
68
|
+
export function parseCheckedCommandResult(value) {
|
|
69
|
+
if (!object(value) || !keys(value, ['schema_version', 'status', 'verification', 'plan_sha256', 'steps'], ['reason'])
|
|
70
|
+
|| value.schema_version !== 1 || value.verification !== 'unknown'
|
|
71
|
+
|| (value.status !== 'passed' && value.status !== 'failed' && value.status !== 'incomplete'
|
|
72
|
+
&& value.status !== 'timed_out' && value.status !== 'cancelled')
|
|
73
|
+
|| typeof value.plan_sha256 !== 'string' || !/^[a-f0-9]{64}$/.test(value.plan_sha256)
|
|
74
|
+
|| (Object.hasOwn(value, 'reason') && !string(value.reason, 256, true))
|
|
75
|
+
|| !Array.isArray(value.steps) || value.steps.length < 1 || value.steps.length > MAX_STEPS)
|
|
76
|
+
return null;
|
|
77
|
+
const steps = [];
|
|
78
|
+
const ids = new Set();
|
|
79
|
+
let predecessorUnaccepted = false;
|
|
80
|
+
let observedFailure = false;
|
|
81
|
+
for (const rawStep of value.steps) {
|
|
82
|
+
if (!object(rawStep) || !keys(rawStep, ['id', 'status', 'stages']) || typeof rawStep.id !== 'string'
|
|
83
|
+
|| !stepId.test(rawStep.id) || ids.has(rawStep.id)
|
|
84
|
+
|| (rawStep.status !== 'passed' && rawStep.status !== 'failed' && rawStep.status !== 'skipped' && rawStep.status !== 'unknown')
|
|
85
|
+
|| !Array.isArray(rawStep.stages) || rawStep.stages.length < 1 || rawStep.stages.length > MAX_STAGES)
|
|
86
|
+
return null;
|
|
87
|
+
const stages = [];
|
|
88
|
+
for (const rawStage of rawStep.stages) {
|
|
89
|
+
if (!object(rawStage) || !keys(rawStage, ['exit_code', 'acceptable_exit_codes', 'accepted']))
|
|
90
|
+
return null;
|
|
91
|
+
const acceptedCodes = codes(rawStage.acceptable_exit_codes);
|
|
92
|
+
if (!acceptedCodes || (rawStage.exit_code !== null && !exitCode(rawStage.exit_code)))
|
|
93
|
+
return null;
|
|
94
|
+
const accepted = rawStage.exit_code === null ? null : acceptedCodes.includes(rawStage.exit_code);
|
|
95
|
+
if (rawStage.accepted !== accepted)
|
|
96
|
+
return null;
|
|
97
|
+
stages.push({ exit_code: rawStage.exit_code, acceptable_exit_codes: acceptedCodes, accepted });
|
|
98
|
+
}
|
|
99
|
+
const allKnown = stages.every(stage => stage.exit_code !== null);
|
|
100
|
+
const anyKnown = stages.some(stage => stage.exit_code !== null);
|
|
101
|
+
const failed = stages.some(stage => stage.accepted === false);
|
|
102
|
+
if ((rawStep.status === 'passed' && (!allKnown || failed))
|
|
103
|
+
|| (rawStep.status === 'failed' && (!allKnown || !failed))
|
|
104
|
+
|| (rawStep.status === 'unknown' && allKnown)
|
|
105
|
+
|| (rawStep.status === 'skipped' && anyKnown)
|
|
106
|
+
|| (predecessorUnaccepted && anyKnown))
|
|
107
|
+
return null;
|
|
108
|
+
if (rawStep.status !== 'passed')
|
|
109
|
+
predecessorUnaccepted = true;
|
|
110
|
+
observedFailure ||= failed;
|
|
111
|
+
ids.add(rawStep.id);
|
|
112
|
+
steps.push({ id: rawStep.id, status: rawStep.status, stages });
|
|
113
|
+
}
|
|
114
|
+
if ((value.status === 'passed' && !steps.every(step => step.status === 'passed'))
|
|
115
|
+
|| (value.status === 'failed' && !observedFailure))
|
|
116
|
+
return null;
|
|
117
|
+
return { schema_version: 1, status: value.status, verification: 'unknown', plan_sha256: value.plan_sha256, steps,
|
|
118
|
+
...(typeof value.reason === 'string' ? { reason: value.reason } : {}) };
|
|
119
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Declared execution limits and cleanup policy, never evidence that cleanup succeeded. */
|
|
2
|
+
export interface CommandExecutionPolicy {
|
|
3
|
+
schema_version: 1;
|
|
4
|
+
mode: 'foreground' | 'background';
|
|
5
|
+
timeout_ms: number | null;
|
|
6
|
+
timeout_source: 'default' | 'explicit' | 'unlimited';
|
|
7
|
+
started_at: string;
|
|
8
|
+
deadline_at: string | null;
|
|
9
|
+
cleanup: {
|
|
10
|
+
scope: 'local_process_group' | 'local_process';
|
|
11
|
+
term_grace_ms: 250;
|
|
12
|
+
turn_interrupt: 'cancel' | 'preserve' | 'unknown';
|
|
13
|
+
host_shutdown: 'cancel';
|
|
14
|
+
remote: 'unknown';
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** A host observation of elapsed execution time, independent of wall-clock drift. */
|
|
18
|
+
export interface CommandExecutionObservation {
|
|
19
|
+
observed_at: string;
|
|
20
|
+
elapsed_ms: number;
|
|
21
|
+
}
|
|
22
|
+
export declare const COMMAND_EXECUTION_POLICY_MAX_BYTES = 2048;
|
|
23
|
+
/** Validate a bounded, detached execution policy for runtime and browser consumers. */
|
|
24
|
+
export declare function parseCommandExecutionPolicy(value: unknown): CommandExecutionPolicy | null;
|
|
25
|
+
/** Validate an observation without inferring elapsed time from its wall-clock timestamp. */
|
|
26
|
+
export declare function parseCommandExecutionObservation(value: unknown, startedAt: string): CommandExecutionObservation | null;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export const COMMAND_EXECUTION_POLICY_MAX_BYTES = 2048;
|
|
2
|
+
const encoder = new TextEncoder();
|
|
3
|
+
function record(value, fields) {
|
|
4
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
5
|
+
return null;
|
|
6
|
+
const prototype = Object.getPrototypeOf(value);
|
|
7
|
+
if (prototype !== Object.prototype && prototype !== null)
|
|
8
|
+
return null;
|
|
9
|
+
const keys = Reflect.ownKeys(value);
|
|
10
|
+
if (keys.length !== fields.length || keys.some(key => typeof key !== 'string' || !fields.includes(key)))
|
|
11
|
+
return null;
|
|
12
|
+
if (keys.some(key => !Object.hasOwn(Object.getOwnPropertyDescriptor(value, key), 'value')))
|
|
13
|
+
return null;
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function instant(value) {
|
|
17
|
+
if (typeof value !== 'string')
|
|
18
|
+
return null;
|
|
19
|
+
const milliseconds = Date.parse(value);
|
|
20
|
+
return Number.isFinite(milliseconds) && new Date(milliseconds).toISOString() === value ? milliseconds : null;
|
|
21
|
+
}
|
|
22
|
+
function member(value, choices) {
|
|
23
|
+
return typeof value === 'string' && choices.includes(value);
|
|
24
|
+
}
|
|
25
|
+
function bounded(value) {
|
|
26
|
+
return encoder.encode(JSON.stringify(value)).byteLength <= COMMAND_EXECUTION_POLICY_MAX_BYTES;
|
|
27
|
+
}
|
|
28
|
+
/** Validate a bounded, detached execution policy for runtime and browser consumers. */
|
|
29
|
+
export function parseCommandExecutionPolicy(value) {
|
|
30
|
+
try {
|
|
31
|
+
const row = record(value, ['schema_version', 'mode', 'timeout_ms', 'timeout_source', 'started_at', 'deadline_at', 'cleanup']);
|
|
32
|
+
if (!row || row.schema_version !== 1 || !member(row.mode, ['foreground', 'background'])
|
|
33
|
+
|| !member(row.timeout_source, ['default', 'explicit', 'unlimited']))
|
|
34
|
+
return null;
|
|
35
|
+
const cleanup = record(row.cleanup, ['scope', 'term_grace_ms', 'turn_interrupt', 'host_shutdown', 'remote']);
|
|
36
|
+
if (!cleanup || !member(cleanup.scope, ['local_process_group', 'local_process'])
|
|
37
|
+
|| cleanup.term_grace_ms !== 250 || !member(cleanup.turn_interrupt, ['cancel', 'preserve', 'unknown'])
|
|
38
|
+
|| cleanup.host_shutdown !== 'cancel' || cleanup.remote !== 'unknown')
|
|
39
|
+
return null;
|
|
40
|
+
const started = instant(row.started_at);
|
|
41
|
+
if (started === null)
|
|
42
|
+
return null;
|
|
43
|
+
let timeout;
|
|
44
|
+
let deadline;
|
|
45
|
+
if (row.timeout_source === 'unlimited') {
|
|
46
|
+
if (row.timeout_ms !== null || row.deadline_at !== null)
|
|
47
|
+
return null;
|
|
48
|
+
timeout = null;
|
|
49
|
+
deadline = null;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
if (typeof row.timeout_ms !== 'number' || !Number.isSafeInteger(row.timeout_ms)
|
|
53
|
+
|| row.timeout_ms < 1 || row.timeout_ms > 86400000)
|
|
54
|
+
return null;
|
|
55
|
+
if (row.timeout_source === 'default' && row.timeout_ms !== 30000 && row.timeout_ms !== 120000)
|
|
56
|
+
return null;
|
|
57
|
+
const end = instant(row.deadline_at);
|
|
58
|
+
if (end === null || end !== started + row.timeout_ms)
|
|
59
|
+
return null;
|
|
60
|
+
timeout = row.timeout_ms;
|
|
61
|
+
deadline = row.deadline_at;
|
|
62
|
+
}
|
|
63
|
+
if (!bounded(row))
|
|
64
|
+
return null;
|
|
65
|
+
return {
|
|
66
|
+
schema_version: 1, mode: row.mode, timeout_ms: timeout, timeout_source: row.timeout_source,
|
|
67
|
+
started_at: row.started_at, deadline_at: deadline,
|
|
68
|
+
cleanup: { scope: cleanup.scope, term_grace_ms: 250, turn_interrupt: cleanup.turn_interrupt,
|
|
69
|
+
host_shutdown: 'cancel', remote: 'unknown' },
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** Validate an observation without inferring elapsed time from its wall-clock timestamp. */
|
|
77
|
+
export function parseCommandExecutionObservation(value, startedAt) {
|
|
78
|
+
try {
|
|
79
|
+
const row = record(value, ['observed_at', 'elapsed_ms']);
|
|
80
|
+
if (!row || typeof row.elapsed_ms !== 'number' || !Number.isSafeInteger(row.elapsed_ms) || row.elapsed_ms < 0)
|
|
81
|
+
return null;
|
|
82
|
+
const started = instant(startedAt);
|
|
83
|
+
const observed = instant(row.observed_at);
|
|
84
|
+
if (started === null || observed === null || observed < started || !bounded(row))
|
|
85
|
+
return null;
|
|
86
|
+
return { observed_at: row.observed_at, elapsed_ms: row.elapsed_ms };
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { type RunShellCommandOptions } from '../../utils/shell.js';
|
|
2
|
+
import type { CheckedCommandResult } from './checked_commands.js';
|
|
3
|
+
import type { CommandVerificationReceipt, CurrentVerificationProjection } from './source_verification_contract.js';
|
|
4
|
+
import { type SourceInspectionGate } from './source_verification.js';
|
|
5
|
+
import { type CommandExecutionPolicy } from './command_execution_policy.js';
|
|
2
6
|
export type CommandStatus = 'running' | 'completed' | 'failed' | 'cancelled' | 'timed_out' | 'interrupted';
|
|
3
7
|
export interface CommandReceipt {
|
|
4
8
|
job_id: string;
|
|
@@ -13,6 +17,28 @@ export interface CommandReceipt {
|
|
|
13
17
|
owner_pid?: number;
|
|
14
18
|
output_truncated?: boolean;
|
|
15
19
|
dropped_bytes?: number;
|
|
20
|
+
checked?: CheckedCommandResult;
|
|
21
|
+
verification?: CommandVerificationReceipt;
|
|
22
|
+
verification_current?: CurrentVerificationProjection;
|
|
23
|
+
execution_policy?: CommandExecutionPolicy;
|
|
24
|
+
/** Host observation time; a terminal duration stays fixed after process completion. */
|
|
25
|
+
observed_at?: string;
|
|
26
|
+
elapsed_ms?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface CommandReadResult extends CommandReceipt {
|
|
29
|
+
output: string;
|
|
30
|
+
cursor: number;
|
|
31
|
+
has_more: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface ManagedCommandObservation {
|
|
34
|
+
sessionId: string;
|
|
35
|
+
result: CommandReadResult;
|
|
36
|
+
requestedWaitMs: number;
|
|
37
|
+
kind: 'read' | 'launch';
|
|
38
|
+
}
|
|
39
|
+
export interface CommandProgressResult {
|
|
40
|
+
reason: 'output' | 'terminal' | 'deadline';
|
|
41
|
+
result: CommandReadResult;
|
|
16
42
|
}
|
|
17
43
|
export declare function subscribeCommandJobs(sessionId: string, listener: (jobs: CommandReceipt[]) => void): () => void;
|
|
18
44
|
export declare function listCommandJobs(sessionId: string): CommandReceipt[];
|
|
@@ -24,24 +50,16 @@ export declare function startCommandJob(options: {
|
|
|
24
50
|
shell: RunShellCommandOptions;
|
|
25
51
|
maxJobs: number;
|
|
26
52
|
signal?: AbortSignal;
|
|
53
|
+
verification?: CommandVerificationReceipt;
|
|
54
|
+
canInspectVerificationSource?: SourceInspectionGate;
|
|
27
55
|
}): Promise<CommandReceipt>;
|
|
28
|
-
export declare function readCommandJob(sessionId: string, jobId: string, cursor?: number, waitMs?: number, signal?: AbortSignal): Promise<
|
|
29
|
-
|
|
30
|
-
cursor
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
started_at: string;
|
|
37
|
-
ended_at?: string;
|
|
38
|
-
exit_code?: number;
|
|
39
|
-
error?: string;
|
|
40
|
-
log_path: string;
|
|
41
|
-
owner_pid?: number;
|
|
42
|
-
output_truncated?: boolean;
|
|
43
|
-
dropped_bytes?: number;
|
|
44
|
-
}>;
|
|
45
|
-
export declare function stopCommandJob(sessionId: string, jobId: string): Promise<CommandReceipt>;
|
|
56
|
+
export declare function readCommandJob(sessionId: string, jobId: string, cursor?: number, waitMs?: number, signal?: AbortSignal, canInspectSource?: SourceInspectionGate): Promise<CommandReadResult>;
|
|
57
|
+
export declare function waitForCommandProgress(sessionId: string, jobId: string, options: {
|
|
58
|
+
cursor?: number;
|
|
59
|
+
maxWaitMs: number;
|
|
60
|
+
signal?: AbortSignal;
|
|
61
|
+
canInspectVerificationSource?: SourceInspectionGate;
|
|
62
|
+
}): Promise<CommandProgressResult>;
|
|
63
|
+
export declare function stopCommandJob(sessionId: string, jobId: string, canInspectSource?: SourceInspectionGate): Promise<CommandReceipt>;
|
|
46
64
|
export declare function shutdownCommandJobs(sessionId?: string): Promise<void>;
|
|
47
65
|
export declare function interruptCommandJobs(sessionId: string): Promise<void>;
|
|
@@ -3,6 +3,9 @@ import { appendFileSync, closeSync, mkdirSync, openSync, readFileSync, readSync,
|
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { runShellCommand } from '../../utils/shell.js';
|
|
6
|
+
import { finishCommandVerification, projectCurrentVerification } from './source_verification.js';
|
|
7
|
+
import { parseCommandExecutionPolicy } from './command_execution_policy.js';
|
|
8
|
+
import { writeFileAtomicSync } from '../../utils/atomic_write.js';
|
|
6
9
|
const MAX_LOG_BYTES = 16 * 1024 * 1024;
|
|
7
10
|
const MAX_RETAINED_JOBS = 64;
|
|
8
11
|
const RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
|
|
@@ -27,6 +30,10 @@ function publish(sessionId) {
|
|
|
27
30
|
catch { /* a view cannot change command lifecycle */ }
|
|
28
31
|
}
|
|
29
32
|
}
|
|
33
|
+
function notifyActivity(job) {
|
|
34
|
+
for (const listener of job.activity)
|
|
35
|
+
listener();
|
|
36
|
+
}
|
|
30
37
|
/** Bound completed logs across all sessions; active processes keep their logs. */
|
|
31
38
|
function pruneCommandLogs() {
|
|
32
39
|
const root = join(process.env.ZTC_CONFIG_DIR || join(homedir(), '.ztc'), 'command-jobs');
|
|
@@ -100,12 +107,14 @@ function appendCommandOutput(sessionId, job, text) {
|
|
|
100
107
|
if (first)
|
|
101
108
|
save(sessionId, job.receipt);
|
|
102
109
|
}
|
|
110
|
+
if (count > 0 || count < bytes.length)
|
|
111
|
+
notifyActivity(job);
|
|
103
112
|
}
|
|
104
113
|
function directory(sessionId) {
|
|
105
114
|
return join(process.env.ZTC_CONFIG_DIR || join(homedir(), '.ztc'), 'command-jobs', createHash('sha256').update(sessionId).digest('hex').slice(0, 32));
|
|
106
115
|
}
|
|
107
116
|
function save(sessionId, receipt) {
|
|
108
|
-
|
|
117
|
+
writeFileAtomicSync(join(directory(sessionId), `${receipt.job_id}.json`), JSON.stringify(receipt), { mode: 0o600 });
|
|
109
118
|
}
|
|
110
119
|
function resolveJob(sessionId, jobId) {
|
|
111
120
|
if (!/^[0-9a-f-]{36}$/.test(jobId))
|
|
@@ -120,15 +129,43 @@ function resolveJob(sessionId, jobId) {
|
|
|
120
129
|
catch {
|
|
121
130
|
throw new Error('Command job not found in this session');
|
|
122
131
|
}
|
|
132
|
+
const policy = parseCommandExecutionPolicy(receipt.execution_policy);
|
|
133
|
+
if (policy && policy.started_at === receipt.started_at)
|
|
134
|
+
receipt.execution_policy = policy;
|
|
135
|
+
else
|
|
136
|
+
delete receipt.execution_policy;
|
|
123
137
|
if (receipt.status === 'running') {
|
|
124
|
-
receipt = { ...receipt, status: 'interrupted',
|
|
138
|
+
receipt = { ...receipt, status: 'interrupted', error: 'Owning ZTC process ended; inspect output before retrying.',
|
|
139
|
+
...(receipt.verification?.process_outcome === 'running' ? { verification: { ...receipt.verification,
|
|
140
|
+
process_outcome: 'interrupted', source_binding: 'unknown' } } : {}) };
|
|
141
|
+
// Recovery observes missing ownership, not the original process's end time.
|
|
142
|
+
delete receipt.ended_at;
|
|
143
|
+
delete receipt.observed_at;
|
|
144
|
+
delete receipt.elapsed_ms;
|
|
125
145
|
save(sessionId, receipt);
|
|
126
146
|
}
|
|
127
|
-
return { receipt, controller: new AbortController(), done: Promise.resolve(), loggedBytes: statSync(receipt.log_path).size
|
|
147
|
+
return { receipt, controller: new AbortController(), done: Promise.resolve(), loggedBytes: statSync(receipt.log_path).size, activity: new Set(),
|
|
148
|
+
canInspectVerificationSource: () => false };
|
|
128
149
|
}
|
|
129
150
|
export function listCommandJobs(sessionId) {
|
|
130
151
|
const jobs = [...(sessions.get(sessionId)?.values() ?? [])];
|
|
131
|
-
return [...jobs.filter(job => job.receipt.status === 'running'), ...jobs.filter(job => job.receipt.status !== 'running').slice(-28)].map(job => (
|
|
152
|
+
return [...jobs.filter(job => job.receipt.status === 'running'), ...jobs.filter(job => job.receipt.status !== 'running').slice(-28)].map(job => observeReceipt(job.receipt));
|
|
153
|
+
}
|
|
154
|
+
function observeReceipt(receipt) {
|
|
155
|
+
const result = structuredClone(receipt);
|
|
156
|
+
const now = Date.now();
|
|
157
|
+
const started = Date.parse(receipt.started_at);
|
|
158
|
+
const ended = receipt.status === 'running' ? now : Date.parse(receipt.ended_at ?? '');
|
|
159
|
+
const elapsed = ended - started;
|
|
160
|
+
if (Number.isSafeInteger(elapsed) && elapsed >= 0 && now >= started) {
|
|
161
|
+
result.observed_at = new Date(now).toISOString();
|
|
162
|
+
result.elapsed_ms = elapsed;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
delete result.observed_at;
|
|
166
|
+
delete result.elapsed_ms;
|
|
167
|
+
}
|
|
168
|
+
return result;
|
|
132
169
|
}
|
|
133
170
|
export async function startCommandJob(options) {
|
|
134
171
|
const { sessionId } = options;
|
|
@@ -148,9 +185,11 @@ export async function startCommandJob(options) {
|
|
|
148
185
|
const logPath = join(directory(sessionId), `${jobId}.log`);
|
|
149
186
|
writeFileSync(logPath, '', { mode: 0o600 });
|
|
150
187
|
const controller = new AbortController();
|
|
151
|
-
const job = { controller, done: Promise.resolve(), loggedBytes: 0,
|
|
188
|
+
const job = { controller, done: Promise.resolve(), loggedBytes: 0, activity: new Set(),
|
|
189
|
+
canInspectVerificationSource: options.canInspectVerificationSource ?? (() => true), receipt: {
|
|
152
190
|
job_id: jobId, status: 'running', command: options.command, cwd: options.cwd,
|
|
153
191
|
started_at: new Date().toISOString(), log_path: logPath, owner_pid: process.pid,
|
|
192
|
+
...(options.verification ? { verification: structuredClone(options.verification) } : {}),
|
|
154
193
|
} };
|
|
155
194
|
save(sessionId, job.receipt);
|
|
156
195
|
registry.set(jobId, job);
|
|
@@ -159,19 +198,40 @@ export async function startCommandJob(options) {
|
|
|
159
198
|
options.signal?.addEventListener('abort', abort, { once: true });
|
|
160
199
|
job.done = runShellCommand(options.command, options.cwd, controller.signal, options.timeoutMs, {
|
|
161
200
|
...options.shell, noTimeout: options.timeoutMs === undefined,
|
|
201
|
+
executionMode: 'background', turnInterruptPolicy: options.signal ? 'cancel' : 'preserve',
|
|
202
|
+
onExecutionPolicy: policy => {
|
|
203
|
+
job.receipt.execution_policy = structuredClone(policy);
|
|
204
|
+
job.receipt.started_at = policy.started_at;
|
|
205
|
+
options.shell.onExecutionPolicy?.(structuredClone(policy));
|
|
206
|
+
save(sessionId, job.receipt);
|
|
207
|
+
publish(sessionId);
|
|
208
|
+
},
|
|
162
209
|
onOutput: (_stream, text) => appendCommandOutput(sessionId, job, text),
|
|
210
|
+
onCheckedProgress: checked => { job.receipt.checked = structuredClone(checked); save(sessionId, job.receipt); publish(sessionId); },
|
|
163
211
|
}).then(result => {
|
|
164
212
|
job.receipt.exit_code = result.exitCode;
|
|
165
|
-
|
|
213
|
+
if (result.checked)
|
|
214
|
+
job.receipt.checked = structuredClone(result.checked);
|
|
215
|
+
if (job.receipt.status !== 'interrupted')
|
|
216
|
+
job.receipt.status = result.checked
|
|
217
|
+
? result.checked.status === 'passed' ? 'completed' : result.checked.status === 'timed_out' ? 'timed_out'
|
|
218
|
+
: result.checked.status === 'cancelled' ? 'cancelled' : 'failed'
|
|
219
|
+
: result.timedOut === true ? 'timed_out' : result.exitCode === 0 ? 'completed' : 'failed';
|
|
166
220
|
if (result.exitCode !== 0)
|
|
167
221
|
job.receipt.error = result.stderr.slice(-4096) || `Command exited with code ${result.exitCode}`;
|
|
222
|
+
job.receipt.ended_at = new Date().toISOString();
|
|
168
223
|
}, error => {
|
|
169
224
|
if (job.receipt.status !== 'interrupted')
|
|
170
225
|
job.receipt.status = controller.signal.aborted ? 'cancelled' : 'failed';
|
|
171
226
|
job.receipt.error = error.message;
|
|
172
|
-
}).finally(() => {
|
|
173
|
-
options.signal?.removeEventListener('abort', abort);
|
|
174
227
|
job.receipt.ended_at = new Date().toISOString();
|
|
228
|
+
}).finally(async () => {
|
|
229
|
+
options.signal?.removeEventListener('abort', abort);
|
|
230
|
+
if (job.receipt.verification) {
|
|
231
|
+
const outcome = job.receipt.status === 'completed' ? 'passed' : job.receipt.status === 'running' ? 'unknown' : job.receipt.status;
|
|
232
|
+
job.receipt.verification = await finishCommandVerification(job.receipt.verification, outcome, job.canInspectVerificationSource);
|
|
233
|
+
job.receipt.verification_current = await projectCurrentVerification(job.receipt.verification, job.canInspectVerificationSource);
|
|
234
|
+
}
|
|
175
235
|
try {
|
|
176
236
|
save(sessionId, job.receipt);
|
|
177
237
|
}
|
|
@@ -184,16 +244,19 @@ export async function startCommandJob(options) {
|
|
|
184
244
|
const terminal = [...registry.entries()].filter(([, entry]) => entry.receipt.status !== 'running');
|
|
185
245
|
for (const [id] of terminal.slice(0, Math.max(0, terminal.length - 64)))
|
|
186
246
|
registry.delete(id);
|
|
247
|
+
notifyActivity(job);
|
|
187
248
|
publish(sessionId);
|
|
188
249
|
});
|
|
189
|
-
return
|
|
250
|
+
return observeReceipt(job.receipt);
|
|
190
251
|
}
|
|
191
|
-
export async function readCommandJob(sessionId, jobId, cursor = 0, waitMs = 0, signal) {
|
|
252
|
+
export async function readCommandJob(sessionId, jobId, cursor = 0, waitMs = 0, signal, canInspectSource) {
|
|
192
253
|
if (!Number.isSafeInteger(cursor) || cursor < 0)
|
|
193
254
|
throw new Error('cursor must be a non-negative byte offset');
|
|
194
255
|
if (!Number.isSafeInteger(waitMs) || waitMs < 0 || waitMs > 60000)
|
|
195
256
|
throw new Error('wait_ms must be an integer between 0 and 60000');
|
|
196
257
|
const job = resolveJob(sessionId, jobId);
|
|
258
|
+
if (canInspectSource)
|
|
259
|
+
job.canInspectVerificationSource = canInspectSource;
|
|
197
260
|
const cancelled = () => new Error(`Command read cancelled; inspect job ${jobId} before retrying. The job may still be running.`);
|
|
198
261
|
if (signal?.aborted)
|
|
199
262
|
throw cancelled();
|
|
@@ -214,6 +277,19 @@ export async function readCommandJob(sessionId, jobId, cursor = 0, waitMs = 0, s
|
|
|
214
277
|
signal?.removeEventListener('abort', onAbort);
|
|
215
278
|
}
|
|
216
279
|
}
|
|
280
|
+
const result = await refreshReadVerification(job, readOutput(job, cursor), canInspectSource);
|
|
281
|
+
return observeReceipt(result);
|
|
282
|
+
}
|
|
283
|
+
async function refreshReadVerification(job, result, canInspectSource) {
|
|
284
|
+
if (!result.verification)
|
|
285
|
+
return result;
|
|
286
|
+
const original = job.receipt.verification;
|
|
287
|
+
const current = await projectCurrentVerification(result.verification, canInspectSource ?? job.canInspectVerificationSource);
|
|
288
|
+
if (job.receipt.verification === original)
|
|
289
|
+
job.receipt.verification_current = structuredClone(current);
|
|
290
|
+
return { ...result, verification_current: current };
|
|
291
|
+
}
|
|
292
|
+
function readOutput(job, cursor) {
|
|
217
293
|
const size = statSync(job.receipt.log_path).size;
|
|
218
294
|
if (cursor > size)
|
|
219
295
|
throw new Error('cursor is beyond the command output');
|
|
@@ -240,15 +316,77 @@ export async function readCommandJob(sessionId, jobId, cursor = 0, waitMs = 0, s
|
|
|
240
316
|
throw new Error('cursor must be at a UTF-8 character boundary');
|
|
241
317
|
}
|
|
242
318
|
}
|
|
243
|
-
return { ...job.receipt, output, cursor: cursor + count, has_more: cursor + count < size };
|
|
319
|
+
return { ...observeReceipt(job.receipt), output, cursor: cursor + count, has_more: cursor + count < size };
|
|
320
|
+
}
|
|
321
|
+
export async function waitForCommandProgress(sessionId, jobId, options) {
|
|
322
|
+
const cursor = options.cursor ?? 0;
|
|
323
|
+
if (!Number.isSafeInteger(cursor) || cursor < 0)
|
|
324
|
+
throw new Error('cursor must be a non-negative byte offset');
|
|
325
|
+
if (!Number.isSafeInteger(options.maxWaitMs) || options.maxWaitMs < 0 || options.maxWaitMs > 60000) {
|
|
326
|
+
throw new Error('maxWaitMs must be an integer between 0 and 60000');
|
|
327
|
+
}
|
|
328
|
+
const job = resolveJob(sessionId, jobId);
|
|
329
|
+
if (options.canInspectVerificationSource)
|
|
330
|
+
job.canInspectVerificationSource = options.canInspectVerificationSource;
|
|
331
|
+
const cancelled = () => new Error(`Command read cancelled; inspect job ${jobId} before retrying. The job may still be running.`);
|
|
332
|
+
if (options.signal?.aborted)
|
|
333
|
+
throw cancelled();
|
|
334
|
+
const progress = await new Promise((resolve, reject) => {
|
|
335
|
+
let settled = false;
|
|
336
|
+
let timer;
|
|
337
|
+
const cleanup = () => {
|
|
338
|
+
settled = true;
|
|
339
|
+
job.activity.delete(onActivity);
|
|
340
|
+
if (timer !== undefined)
|
|
341
|
+
clearTimeout(timer);
|
|
342
|
+
options.signal?.removeEventListener('abort', onAbort);
|
|
343
|
+
};
|
|
344
|
+
const onAbort = () => { if (!settled) {
|
|
345
|
+
cleanup();
|
|
346
|
+
reject(cancelled());
|
|
347
|
+
} };
|
|
348
|
+
const inspect = (deadline) => {
|
|
349
|
+
if (settled)
|
|
350
|
+
return;
|
|
351
|
+
if (options.signal?.aborted) {
|
|
352
|
+
onAbort();
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
try {
|
|
356
|
+
const result = readOutput(job, cursor);
|
|
357
|
+
const reason = result.status !== 'running' ? 'terminal' : result.output.length > 0 ? 'output' : deadline ? 'deadline' : null;
|
|
358
|
+
if (reason !== null) {
|
|
359
|
+
cleanup();
|
|
360
|
+
resolve({ reason, result });
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
cleanup();
|
|
365
|
+
reject(error);
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
const onActivity = () => inspect(false);
|
|
369
|
+
// Register before checking bytes/status so output or completion cannot be lost.
|
|
370
|
+
job.activity.add(onActivity);
|
|
371
|
+
options.signal?.addEventListener('abort', onAbort, { once: true });
|
|
372
|
+
if (options.maxWaitMs > 0)
|
|
373
|
+
timer = setTimeout(() => inspect(true), options.maxWaitMs);
|
|
374
|
+
inspect(options.maxWaitMs === 0);
|
|
375
|
+
});
|
|
376
|
+
const result = await refreshReadVerification(job, progress.result, options.canInspectVerificationSource);
|
|
377
|
+
return { reason: progress.reason, result: observeReceipt(result) };
|
|
244
378
|
}
|
|
245
|
-
export async function stopCommandJob(sessionId, jobId) {
|
|
379
|
+
export async function stopCommandJob(sessionId, jobId, canInspectSource) {
|
|
246
380
|
const job = resolveJob(sessionId, jobId);
|
|
381
|
+
if (canInspectSource)
|
|
382
|
+
job.canInspectVerificationSource = canInspectSource;
|
|
247
383
|
if (job.receipt.status === 'running') {
|
|
248
384
|
job.controller.abort();
|
|
249
385
|
await job.done;
|
|
250
386
|
}
|
|
251
|
-
|
|
387
|
+
if (job.receipt.verification)
|
|
388
|
+
job.receipt.verification_current = await projectCurrentVerification(job.receipt.verification, job.canInspectVerificationSource);
|
|
389
|
+
return observeReceipt(job.receipt);
|
|
252
390
|
}
|
|
253
391
|
export async function shutdownCommandJobs(sessionId) {
|
|
254
392
|
const registries = sessionId ? [sessions.get(sessionId)] : [...sessions.values()];
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { RunShellCommandOptions } from '../../utils/shell.js';
|
|
2
|
+
export type CommandPaneState = 'suspended' | 'running' | 'completed' | 'failed' | 'unknown';
|
|
3
|
+
export interface CommandPaneView {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
command: string;
|
|
7
|
+
cwd: string;
|
|
8
|
+
environmentKeys: string[];
|
|
9
|
+
state: CommandPaneState;
|
|
10
|
+
attempt: string;
|
|
11
|
+
exitCode?: number;
|
|
12
|
+
error?: string;
|
|
13
|
+
output: string;
|
|
14
|
+
evidence?: {
|
|
15
|
+
path: string;
|
|
16
|
+
sha256: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/** Durable definitions and command receipts are authoritative; panes are projections. */
|
|
20
|
+
export declare class CommandPaneManager {
|
|
21
|
+
private readonly sessionId;
|
|
22
|
+
private readonly shellOptions;
|
|
23
|
+
private readonly file;
|
|
24
|
+
private readonly sessionDirectory;
|
|
25
|
+
private readonly listeners;
|
|
26
|
+
private readonly localJobs;
|
|
27
|
+
private readonly admittedJobs;
|
|
28
|
+
private timer?;
|
|
29
|
+
private refreshTask?;
|
|
30
|
+
private closed;
|
|
31
|
+
private lastPublished?;
|
|
32
|
+
constructor(sessionId: string, sessionCwd: string, shellOptions: () => RunShellCommandOptions);
|
|
33
|
+
private read;
|
|
34
|
+
private mutate;
|
|
35
|
+
private find;
|
|
36
|
+
pin(options: {
|
|
37
|
+
name: string;
|
|
38
|
+
command: string;
|
|
39
|
+
cwd: string;
|
|
40
|
+
env?: Record<string, string>;
|
|
41
|
+
suspended?: boolean;
|
|
42
|
+
}): Promise<CommandPaneView>;
|
|
43
|
+
/** expectedAttempt binds an action to the snapshot it was offered on. */
|
|
44
|
+
run(name: string, expectedAttempt: string): Promise<CommandPaneView>;
|
|
45
|
+
stop(name: string, expectedAttempt: string): Promise<void>;
|
|
46
|
+
unpin(name: string): Promise<void>;
|
|
47
|
+
private output;
|
|
48
|
+
list(): Promise<CommandPaneView[]>;
|
|
49
|
+
attachEvidence(name: string, expectedAttempt: string): Promise<{
|
|
50
|
+
path: string;
|
|
51
|
+
sha256: string;
|
|
52
|
+
}>;
|
|
53
|
+
subscribe(listener: (commands: CommandPaneView[]) => void): () => void;
|
|
54
|
+
private watch;
|
|
55
|
+
refresh(): Promise<void>;
|
|
56
|
+
private publish;
|
|
57
|
+
dispose(): Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
export declare function commandPaneText(command: CommandPaneView): string;
|