@timurproko/a1 0.2.6 → 0.2.7-dev.1222
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 +41 -3
- package/bin/automatic-update.js +7 -0
- package/bin/cli.js +4 -0
- package/bin/guardian.js +5 -0
- package/bin/tab-launch-context.d.ts +27 -0
- package/bin/tab-launch-context.js +94 -0
- package/bin/ui.js +107 -59
- package/dist/app/session-shell/clipboard-diagnostics.js +1 -1
- package/dist/app/session-shell/dialog-coordinator.d.ts +42 -0
- package/dist/app/session-shell/dialog-coordinator.js +133 -0
- package/dist/app/session-shell/dock-chrome.d.ts +34 -0
- package/dist/app/session-shell/dock-chrome.js +109 -0
- package/dist/app/session-shell/exit-notice.d.ts +1 -1
- package/dist/app/session-shell/exit-notice.js +1 -1
- package/dist/app/session-shell/extension-surface.d.ts +30 -0
- package/dist/app/session-shell/extension-surface.js +105 -0
- package/dist/app/session-shell/helper-pool.d.ts +3 -5
- package/dist/app/session-shell/helper-pool.js +3 -5
- package/dist/app/session-shell/input-surface-switch.d.ts +36 -0
- package/dist/app/session-shell/input-surface-switch.js +85 -0
- package/dist/app/session-shell/login-interaction.d.ts +27 -0
- package/dist/app/session-shell/login-interaction.js +91 -0
- package/dist/app/session-shell/prompt-submission.d.ts +48 -0
- package/dist/app/session-shell/prompt-submission.js +276 -0
- package/dist/app/session-shell/resident-tab-coordinator.d.ts +38 -0
- package/dist/app/session-shell/resident-tab-coordinator.js +77 -0
- package/dist/app/session-shell/response-copy-helper.js +21 -6
- package/dist/app/session-shell/response-copy-protocol.d.ts +1 -1
- package/dist/app/session-shell/response-copy-transport.d.ts +16 -6
- package/dist/app/session-shell/response-copy-transport.js +69 -17
- package/dist/app/session-shell/session-concern.d.ts +22 -0
- package/dist/app/session-shell/session-concern.js +29 -0
- package/dist/app/session-shell/session-lifecycle.d.ts +29 -0
- package/dist/app/session-shell/session-lifecycle.js +49 -0
- package/dist/app/session-shell/session-shell-root.d.ts +42 -6
- package/dist/app/session-shell/session-shell-root.js +197 -908
- package/dist/app/session-shell/session-shell.d.ts +3 -8
- package/dist/app/session-shell/session-shell.js +327 -835
- package/dist/app/session-shell/session-viewport-controller.d.ts +2 -1
- package/dist/app/session-shell/session-viewport-controller.js +41 -38
- package/dist/app/session-shell/settings-bindings.d.ts +17 -0
- package/dist/app/session-shell/settings-bindings.js +91 -0
- package/dist/app/session-shell/shell-editor-factory.d.ts +27 -0
- package/dist/app/session-shell/shell-editor-factory.js +105 -0
- package/dist/app/session-shell/shell-host.d.ts +6 -0
- package/dist/app/session-shell/shell-host.js +34 -7
- package/dist/app/session-shell/shell-layout.d.ts +64 -0
- package/dist/app/session-shell/shell-layout.js +18 -0
- package/dist/app/session-shell/suggestion-surface.d.ts +25 -0
- package/dist/app/session-shell/suggestion-surface.js +63 -0
- package/dist/app/session-shell/transcript-document.d.ts +78 -0
- package/dist/app/session-shell/transcript-document.js +365 -0
- package/dist/app/session-shell/viewport-layout.d.ts +31 -0
- package/dist/app/session-shell/viewport-layout.js +160 -0
- package/dist/app/session-shell/workflow-output.d.ts +33 -0
- package/dist/app/session-shell/workflow-output.js +174 -0
- package/dist/app/session-shell/workflow-router.d.ts +25 -0
- package/dist/app/session-shell/workflow-router.js +39 -0
- package/dist/cli/dispatch.d.ts +11 -1
- package/dist/cli/dispatch.js +79 -5
- package/dist/cli/tabs-request.d.ts +7 -0
- package/dist/cli/tabs-request.js +1 -0
- package/dist/cli/tabs.d.ts +14 -0
- package/dist/cli/tabs.js +151 -0
- package/dist/cli/version-stats.js +38 -3
- package/dist/composition/owned-settings.d.ts +12 -0
- package/dist/composition/owned-settings.js +36 -0
- package/dist/composition/owned-ui.d.ts +27 -28
- package/dist/composition/owned-ui.js +207 -153
- package/dist/composition/reference-selection-options.d.ts +3 -0
- package/dist/composition/reference-selection-options.js +16 -0
- package/dist/composition/resident-tab-bridge.d.ts +25 -0
- package/dist/composition/resident-tab-bridge.js +180 -0
- package/dist/composition/session-backend.d.ts +19 -0
- package/dist/composition/session-backend.js +1 -0
- package/dist/composition/session-runtime-registry.d.ts +20 -0
- package/dist/composition/session-runtime-registry.js +85 -0
- package/dist/composition/settings-route-host.d.ts +16 -2
- package/dist/composition/settings-route-host.js +42 -17
- package/dist/composition/settings-search-input.d.ts +9 -0
- package/dist/composition/settings-search-input.js +61 -0
- package/dist/composition/startup-route.d.ts +32 -0
- package/dist/composition/startup-route.js +72 -0
- package/dist/composition/utility-tab.d.ts +28 -0
- package/dist/composition/utility-tab.js +244 -0
- package/dist/contracts/owned-ui/index.d.ts +1 -1
- package/dist/contracts/owned-ui/model.d.ts +3 -0
- package/dist/contracts/owned-ui/session-backend.d.ts +3 -0
- package/dist/contracts/owned-ui/session-workflows.d.ts +11 -4
- package/dist/contracts/presentation/index.d.ts +11 -0
- package/dist/contracts/presentation/index.js +12 -0
- package/dist/features/launch/development-launch.js +6 -0
- package/dist/features/launch/index.d.ts +1 -1
- package/dist/features/launch/intent.d.ts +3 -1
- package/dist/features/launch/intent.js +7 -4
- package/dist/features/launch/profile-paths.js +4 -0
- package/dist/features/owned-ui/plus-menu-dialog.d.ts +22 -0
- package/dist/features/owned-ui/plus-menu-dialog.js +84 -0
- package/dist/features/owned-ui/project-trust-dialog.d.ts +1 -1
- package/dist/features/owned-ui/project-trust-dialog.js +6 -8
- package/dist/features/owned-ui/project-trust-prompt.d.ts +1 -0
- package/dist/features/owned-ui/project-trust-prompt.js +7 -3
- package/dist/features/owned-ui/reference-document-selection.d.ts +30 -0
- package/dist/features/owned-ui/reference-document-selection.js +179 -0
- package/dist/features/owned-ui/reference-screen-app.d.ts +6 -1
- package/dist/features/owned-ui/reference-screen-app.js +51 -10
- package/dist/features/owned-ui/settings-app.d.ts +13 -2
- package/dist/features/owned-ui/settings-app.js +136 -97
- package/dist/features/owned-ui/settings-search-input.d.ts +29 -0
- package/dist/features/owned-ui/settings-search-input.js +1 -0
- package/dist/features/prompt-history/index.d.ts +1 -1
- package/dist/features/prompt-history/paths.d.ts +2 -1
- package/dist/features/prompt-history/paths.js +10 -2
- package/dist/features/prompt-history/service.d.ts +5 -0
- package/dist/features/prompt-history/service.js +1 -1
- package/dist/features/resident-tab/auto-name.d.ts +11 -0
- package/dist/features/resident-tab/auto-name.js +44 -0
- package/dist/features/resident-tab/index.d.ts +5 -0
- package/dist/features/resident-tab/index.js +7 -0
- package/dist/features/resident-tab/shortcut-bindings-file.d.ts +8 -0
- package/dist/features/resident-tab/shortcut-bindings-file.js +40 -0
- package/dist/features/resident-tab/shortcut-declarations.d.ts +13 -0
- package/dist/features/resident-tab/shortcut-declarations.js +26 -0
- package/dist/features/resident-tab/shortcut-projection.d.ts +29 -0
- package/dist/features/resident-tab/shortcut-projection.js +64 -0
- package/dist/features/resident-tab/status-deriver.d.ts +10 -0
- package/dist/features/resident-tab/status-deriver.js +12 -0
- package/dist/foundation/launch-context/index.d.ts +12 -0
- package/dist/foundation/launch-context/index.js +26 -0
- package/dist/foundation/launch-guardian/exit-watcher.d.ts +14 -0
- package/dist/foundation/launch-guardian/exit-watcher.js +94 -0
- package/dist/foundation/launch-guardian/main.d.ts +7 -1
- package/dist/foundation/launch-guardian/main.js +60 -7
- package/dist/foundation/lifecycle/session-repository-context.js +16 -2
- package/dist/foundation/process-containment/{native-guardian-containment.d.ts → addon-containment.d.ts} +7 -5
- package/dist/foundation/process-containment/addon-containment.js +139 -0
- package/dist/foundation/process-containment/addon-process-inspector.d.ts +11 -0
- package/dist/foundation/process-containment/addon-process-inspector.js +36 -0
- package/dist/foundation/process-containment/addon.d.ts +42 -0
- package/dist/foundation/process-containment/addon.js +57 -0
- package/dist/foundation/process-containment/artifact.d.ts +1 -1
- package/dist/foundation/process-containment/artifact.js +6 -5
- package/dist/foundation/process-containment/contracts.d.ts +2 -0
- package/dist/foundation/process-containment/index.d.ts +4 -4
- package/dist/foundation/process-containment/index.js +3 -3
- package/dist/foundation/process-containment/native-process-inspector.d.ts +2 -1
- package/dist/foundation/process-containment/native-process-inspector.js +10 -10
- package/dist/foundation/release/automatic-update.d.ts +37 -0
- package/dist/foundation/release/automatic-update.js +265 -0
- package/dist/foundation/release/bootstrap.d.ts +7 -9
- package/dist/foundation/release/bootstrap.js +107 -24
- package/dist/foundation/release/cohort-state.d.ts +1 -1
- package/dist/foundation/release/cohort-state.js +1 -1
- package/dist/foundation/release/dependency-certification.js +54 -19
- package/dist/foundation/release/early-accent.d.ts +12 -0
- package/dist/foundation/release/early-accent.js +59 -0
- package/dist/foundation/release/index.d.ts +2 -2
- package/dist/foundation/release/index.js +2 -2
- package/dist/foundation/release/latest-release.d.ts +24 -2
- package/dist/foundation/release/latest-release.js +51 -1
- package/dist/foundation/release/progress-palette.generated.d.ts +137 -3
- package/dist/foundation/release/progress-palette.generated.js +137 -3
- package/dist/foundation/release/release-gc.d.ts +3 -0
- package/dist/foundation/release/release-gc.js +59 -8
- package/dist/foundation/release/release-store.d.ts +12 -0
- package/dist/foundation/release/release-store.js +124 -2
- package/dist/foundation/release/update-execution-lease.d.ts +48 -0
- package/dist/foundation/release/update-execution-lease.js +161 -0
- package/dist/foundation/release/update.d.ts +12 -7
- package/dist/foundation/release/update.js +281 -196
- package/dist/foundation/resident-tabs/bounded-host-command.d.ts +18 -0
- package/dist/foundation/resident-tabs/bounded-host-command.js +39 -0
- package/dist/foundation/resident-tabs/bridge-client.d.ts +70 -0
- package/dist/foundation/resident-tabs/bridge-client.js +321 -0
- package/dist/foundation/resident-tabs/doctor.d.ts +28 -0
- package/dist/foundation/resident-tabs/doctor.js +166 -0
- package/dist/foundation/resident-tabs/draft-checkpoint.d.ts +27 -0
- package/dist/foundation/resident-tabs/draft-checkpoint.js +145 -0
- package/dist/foundation/resident-tabs/ensure-terminal-host.d.ts +36 -0
- package/dist/foundation/resident-tabs/ensure-terminal-host.js +151 -0
- package/dist/foundation/resident-tabs/fault-injection.d.ts +8 -0
- package/dist/foundation/resident-tabs/fault-injection.js +26 -0
- package/dist/foundation/resident-tabs/fixture-control.d.ts +7 -0
- package/dist/foundation/resident-tabs/fixture-control.js +35 -0
- package/dist/foundation/resident-tabs/host-entry.d.ts +1 -0
- package/dist/foundation/resident-tabs/host-entry.js +17 -0
- package/dist/foundation/resident-tabs/index.d.ts +12 -0
- package/dist/foundation/resident-tabs/index.js +6 -0
- package/dist/foundation/resident-tabs/maintenance.d.ts +39 -0
- package/dist/foundation/resident-tabs/maintenance.js +75 -0
- package/dist/foundation/resident-tabs/progress-observation-schema.d.ts +34 -0
- package/dist/foundation/resident-tabs/progress-observation-schema.js +1 -0
- package/dist/foundation/resident-tabs/progress-observation.d.ts +4 -0
- package/dist/foundation/resident-tabs/progress-observation.js +150 -0
- package/dist/foundation/resident-tabs/prompt-journal.d.ts +63 -0
- package/dist/foundation/resident-tabs/prompt-journal.js +213 -0
- package/dist/foundation/resident-tabs/protocol.d.ts +12 -0
- package/dist/foundation/resident-tabs/protocol.js +195 -0
- package/dist/foundation/resident-tabs/recovery.d.ts +26 -0
- package/dist/foundation/resident-tabs/recovery.js +205 -0
- package/dist/foundation/resident-tabs/release-holds.d.ts +28 -0
- package/dist/foundation/resident-tabs/release-holds.js +75 -0
- package/dist/foundation/resident-tabs/routes.d.ts +5 -0
- package/dist/foundation/resident-tabs/routes.js +5 -0
- package/dist/foundation/resident-tabs/routing.d.ts +11 -0
- package/dist/foundation/resident-tabs/routing.js +10 -0
- package/dist/foundation/resident-tabs/session-sync.d.ts +14 -0
- package/dist/foundation/resident-tabs/session-sync.js +37 -0
- package/dist/foundation/resident-tabs/settings.d.ts +12 -0
- package/dist/foundation/resident-tabs/settings.js +58 -0
- package/dist/foundation/resident-tabs/terminal-host-artifact.d.ts +14 -0
- package/dist/foundation/resident-tabs/terminal-host-artifact.js +78 -0
- package/dist/foundation/resident-tabs/zip-archive.d.ts +9 -0
- package/dist/foundation/resident-tabs/zip-archive.js +56 -0
- package/dist/foundation/session-writer-lock/index.d.ts +30 -0
- package/dist/foundation/session-writer-lock/index.js +203 -0
- package/dist/foundation/startup/startup-descriptor.js +2 -2
- package/dist/foundation/terminal-cleanup/index.d.ts +1 -1
- package/dist/foundation/terminal-cleanup/index.js +1 -1
- package/dist/foundation/terminal-cleanup/terminal-reset.d.ts +6 -0
- package/dist/foundation/terminal-cleanup/terminal-reset.js +6 -0
- package/dist/integrations/pi/components/editor-interaction.d.ts +2 -0
- package/dist/integrations/pi/components/modal-frame.d.ts +17 -1
- package/dist/integrations/pi/components/modal-frame.js +48 -9
- package/dist/integrations/pi/components/models-dialog.js +4 -52
- package/dist/integrations/pi/components/owned-editor-ux.d.ts +6 -1
- package/dist/integrations/pi/components/owned-editor-ux.js +138 -11
- package/dist/integrations/pi/components/resources/builtin-themes.d.ts +4 -4
- package/dist/integrations/pi/components/resources/builtin-themes.js +4 -4
- package/dist/integrations/pi/components/share-operation-dialog.d.ts +2 -0
- package/dist/integrations/pi/components/share-operation-dialog.js +2 -1
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +58 -36
- package/dist/integrations/pi/components/shell-extension-ui.js +79 -60
- package/dist/integrations/pi/components/shell-footer-status.d.ts +1 -1
- package/dist/integrations/pi/components/shell-footer-status.js +21 -5
- package/dist/integrations/pi/components/shell-hotkey-sections.js +1 -1
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +5 -2
- package/dist/integrations/pi/components/shell-presenters-info.js +18 -4
- package/dist/integrations/pi/components/shell-presenters-transcript.js +4 -1
- package/dist/integrations/pi/components/shell-selectors-dialogs.js +5 -1
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +12 -1
- package/dist/integrations/pi/components/skills-dialog.js +2 -2
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +17 -4
- package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
- package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +8 -6
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +16 -9
- package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +4 -4
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +2 -2
- package/dist/integrations/pi/components/upstream/components/session-footer.d.ts +2 -1
- package/dist/integrations/pi/components/upstream/components/session-footer.js +31 -25
- package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector.js +8 -7
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
- package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +2 -2
- package/dist/integrations/pi/components/upstream/components/status-indicator.js +3 -3
- package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +8 -7
- package/dist/integrations/pi/components/upstream/components/thinking-selector.js +10 -9
- package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +2 -6
- package/dist/integrations/pi/components/upstream/components/tool-execution.js +103 -101
- package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +9 -9
- package/dist/integrations/pi/components/upstream/components/tree-selector.js +13 -21
- package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +2 -2
- package/dist/integrations/pi/components/upstream/history/editor-core.js +7 -5
- package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
- package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
- package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
- package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
- package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme.d.ts +5 -0
- package/dist/integrations/pi/components/upstream/theme/theme.js +29 -2
- package/dist/integrations/pi/engine/adapter.d.ts +5 -77
- package/dist/integrations/pi/engine/adapter.js +95 -394
- package/dist/integrations/pi/engine/command-dispatch.d.ts +13 -0
- package/dist/integrations/pi/engine/command-dispatch.js +57 -0
- package/dist/integrations/pi/engine/host.js +2 -2
- package/dist/integrations/pi/engine/offline-settings-port.d.ts +23 -0
- package/dist/integrations/pi/engine/offline-settings-port.js +53 -0
- package/dist/integrations/pi/engine/pi-settings-metadata.json +14 -2
- package/dist/integrations/pi/engine/ports.d.ts +56 -0
- package/dist/integrations/pi/engine/ports.js +93 -0
- package/dist/integrations/pi/engine/prompt-suggestions.d.ts +1 -0
- package/dist/integrations/pi/engine/prompt-suggestions.js +40 -0
- package/dist/integrations/pi/engine/resources/changelog.json +4 -4
- package/dist/integrations/pi/engine/runtime-integration.js +102 -29
- package/dist/integrations/pi/engine/session-runtime.d.ts +0 -6
- package/dist/integrations/pi/engine/session-runtime.js +13 -5
- package/dist/integrations/pi/engine/session-selection.d.ts +3 -0
- package/dist/integrations/pi/engine/session-selection.js +45 -9
- package/dist/integrations/pi/engine/settings-bridge.d.ts +5 -0
- package/dist/integrations/pi/engine/settings-bridge.js +15 -0
- package/dist/integrations/pi/engine/settings-port.js +11 -15
- package/dist/integrations/pi/engine/view-state.d.ts +42 -0
- package/dist/integrations/pi/engine/view-state.js +126 -0
- package/dist/integrations/pi/engine/workflow-contexts.js +10 -1
- package/dist/integrations/pi/engine/workflow-runner.js +74 -5
- package/dist/integrations/pi/engine/workflow-support.d.ts +12 -0
- package/dist/integrations/pi/engine/workflow-support.js +36 -0
- package/dist/integrations/pi/engine/workflows.d.ts +3 -1
- package/dist/integrations/pi/engine/workflows.js +1 -0
- package/dist/integrations/pi/startup-public.js +257 -310
- package/dist/integrations/pi/startup-public.manifest.json +564 -440
- package/dist/integrations/pi/tui-runtime/adapter.d.ts +6 -0
- package/dist/integrations/pi/tui-runtime/adapter.js +32 -1
- package/dist/integrations/pi/tui-runtime/contracts.d.ts +5 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +12 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +31 -2
- package/dist/native/darwin-arm64/manifest.json +10 -7
- package/dist/native/darwin-arm64/process-guardian.node +0 -0
- package/dist/native/darwin-arm64/terminal-host-THIRD-PARTY-NOTICES.txt +10500 -0
- package/dist/native/darwin-arm64/terminal-host.manifest.json +46 -0
- package/dist/native/darwin-arm64/terminal-host.node +0 -0
- package/dist/native/darwin-x64/manifest.json +23 -0
- package/dist/native/darwin-x64/process-guardian.node +0 -0
- package/dist/native/darwin-x64/terminal-host-THIRD-PARTY-NOTICES.txt +10737 -0
- package/dist/native/darwin-x64/terminal-host.manifest.json +46 -0
- package/dist/native/darwin-x64/terminal-host.node +0 -0
- package/dist/native/linux-x64/manifest.json +10 -7
- package/dist/native/linux-x64/process-guardian.node +0 -0
- package/dist/native/linux-x64/terminal-host-THIRD-PARTY-NOTICES.txt +11226 -0
- package/dist/native/linux-x64/terminal-host.manifest.json +46 -0
- package/dist/native/linux-x64/terminal-host.node +0 -0
- package/dist/native/win32-x64/manifest.json +10 -7
- package/dist/native/win32-x64/process-guardian.node +0 -0
- package/dist/native/win32-x64/terminal-host-THIRD-PARTY-NOTICES.txt +10757 -0
- package/dist/native/win32-x64/terminal-host.manifest.json +46 -0
- package/dist/native/win32-x64/terminal-host.node +0 -0
- package/dist/product-identity.d.ts +3 -3
- package/dist/product-identity.js +4 -4
- package/dist/product-identity.json +16 -2
- package/dist/runtime-payload-inventory.json +6330 -6677
- package/dist/ui/apps/host.d.ts +2 -0
- package/dist/ui/apps/host.js +7 -1
- package/dist/ui/components/dialog-panel.d.ts +17 -8
- package/dist/ui/components/dialog-panel.js +117 -41
- package/dist/ui/components/index.d.ts +5 -5
- package/dist/ui/components/index.js +4 -4
- package/dist/ui/components/line-input.d.ts +4 -1
- package/dist/ui/components/line-input.js +3 -1
- package/dist/ui/components/prompt-input.d.ts +11 -8
- package/dist/ui/components/prompt-input.js +15 -13
- package/dist/ui/components/scrollbar.d.ts +1 -1
- package/dist/ui/components/scrollbar.js +1 -1
- package/dist/ui/components/selection-copy.d.ts +3 -3
- package/dist/ui/components/selection-copy.js +16 -1
- package/dist/ui/components/spans.js +2 -2
- package/dist/ui/components/submitted-prompt.d.ts +9 -6
- package/dist/ui/components/submitted-prompt.js +20 -12
- package/dist/ui/components/surface.js +4 -2
- package/dist/ui/components/text-selection.d.ts +1 -2
- package/dist/ui/components/text-selection.js +5 -2
- package/dist/ui/components/text.d.ts +3 -6
- package/dist/ui/components/text.js +6 -8
- package/dist/ui/components/transcript-viewport.d.ts +9 -2
- package/dist/ui/components/transcript-viewport.js +179 -58
- package/dist/ui/settings/declarations.d.ts +90 -16
- package/dist/ui/settings/declarations.js +67 -14
- package/dist/ui/settings/early-accent.d.ts +81 -0
- package/dist/ui/settings/early-accent.js +50 -0
- package/dist/ui/settings/index.d.ts +4 -2
- package/dist/ui/settings/index.js +2 -1
- package/dist/ui/settings/manager.d.ts +16 -3
- package/dist/ui/settings/manager.js +122 -33
- package/dist/ui/settings/migrations.d.ts +6 -0
- package/dist/ui/settings/migrations.js +73 -0
- package/dist/ui/settings/profile-document.d.ts +26 -0
- package/dist/ui/settings/profile-document.js +164 -0
- package/dist/ui/settings/progress-palette.generated.d.ts +139 -0
- package/dist/ui/settings/progress-palette.generated.js +139 -0
- package/dist/ui/settings/sections.d.ts +4 -0
- package/dist/ui/settings/sections.js +9 -3
- package/docs/architecture/boundaries.md +24 -9
- package/docs/architecture/evidence/resident-tabs/linux-x64.md +37 -0
- package/docs/architecture/evidence/resident-tabs/macos-arm64.md +36 -0
- package/docs/architecture/evidence/resident-tabs/macos-x64.md +35 -0
- package/docs/architecture/evidence/resident-tabs/windows-x64.md +36 -0
- package/docs/architecture/internal-naming.md +3 -1
- package/docs/architecture/process-guardian-provenance.md +18 -10
- package/docs/architecture/project-structure.md +8 -0
- package/docs/architecture/resident-tabs-requirements.md +18 -0
- package/docs/architecture/resident-tabs.md +649 -0
- package/docs/architecture/response-copy-delivery.md +1 -1
- package/docs/architecture/terminal-host-proof-gate.md +2 -0
- package/docs/architecture/terminal-host-provenance.md +16 -4
- package/docs/architecture/tool-image-presentation.md +2 -1
- package/docs/architecture/toolchain.md +11 -9
- package/docs/ci-release-runbook.md +14 -7
- package/docs/features/launch-profiles.md +11 -8
- package/docs/features/prompt-history.md +41 -20
- package/docs/manual-resident-tabs-acceptance.md +51 -0
- package/docs/openspec-archive-automation.md +49 -22
- package/docs/validation.md +49 -9
- package/package.json +19 -6
- package/dist/foundation/process-containment/darwin-process-inspector.d.ts +0 -5
- package/dist/foundation/process-containment/darwin-process-inspector.js +0 -7
- package/dist/foundation/process-containment/native-guardian-containment.js +0 -152
- package/dist/foundation/process-containment/windows-process-inspector.d.ts +0 -19
- package/dist/foundation/process-containment/windows-process-inspector.js +0 -56
- package/dist/native/darwin-arm64/process-guardian +0 -0
- package/dist/native/linux-x64/process-guardian +0 -0
- package/dist/native/win32-x64/process-guardian.exe +0 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { chmod, mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
import { ResidentTabFaultInjection } from "./fault-injection.js";
|
|
5
|
+
/** Periodic rather than inactivity-debounced: continuous input still checkpoints every interval. */
|
|
6
|
+
export class DraftCheckpointer {
|
|
7
|
+
path;
|
|
8
|
+
#intervalMs;
|
|
9
|
+
#maximumDirtyMs;
|
|
10
|
+
#faults;
|
|
11
|
+
#now;
|
|
12
|
+
#onDegraded;
|
|
13
|
+
#write;
|
|
14
|
+
#move;
|
|
15
|
+
#scheduleTimer;
|
|
16
|
+
#cancelTimer;
|
|
17
|
+
#text = "";
|
|
18
|
+
#dirtySince = null;
|
|
19
|
+
#timer = null;
|
|
20
|
+
#degradedTimer = null;
|
|
21
|
+
#writing = null;
|
|
22
|
+
#closed = false;
|
|
23
|
+
#degraded = false;
|
|
24
|
+
constructor(path, options = {}) {
|
|
25
|
+
this.path = path;
|
|
26
|
+
this.#intervalMs = options.intervalMs ?? 500;
|
|
27
|
+
this.#maximumDirtyMs = options.maximumDirtyMs ?? 1_000;
|
|
28
|
+
this.#faults = options.faults ?? new ResidentTabFaultInjection();
|
|
29
|
+
this.#now = options.now ?? Date.now;
|
|
30
|
+
this.#onDegraded = options.onDegraded ?? (() => { });
|
|
31
|
+
this.#write = options.write ?? (async (target, text) => writeFile(target, text, { encoding: "utf8", mode: 0o600, flag: "wx" }));
|
|
32
|
+
this.#move = options.move ?? rename;
|
|
33
|
+
this.#scheduleTimer = options.schedule ?? ((callback, delayMs) => setTimeout(callback, delayMs));
|
|
34
|
+
this.#cancelTimer = options.cancel ?? (timer => clearTimeout(timer));
|
|
35
|
+
}
|
|
36
|
+
get degraded() { return this.#degraded; }
|
|
37
|
+
change(text) {
|
|
38
|
+
if (this.#closed)
|
|
39
|
+
return;
|
|
40
|
+
this.#text = text;
|
|
41
|
+
this.#dirtySince ??= this.#now();
|
|
42
|
+
this.#schedule();
|
|
43
|
+
this.#armDegradedDeadline();
|
|
44
|
+
}
|
|
45
|
+
async restore() {
|
|
46
|
+
try {
|
|
47
|
+
const value = JSON.parse(await readFile(this.path, "utf8"));
|
|
48
|
+
if (typeof value !== "object" || value === null || typeof value.text !== "string"
|
|
49
|
+
|| typeof value.savedAt !== "string")
|
|
50
|
+
return null;
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error.code === "ENOENT" || error instanceof SyntaxError)
|
|
55
|
+
return null;
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async flush() {
|
|
60
|
+
if (this.#timer !== null) {
|
|
61
|
+
this.#cancelTimer(this.#timer);
|
|
62
|
+
this.#timer = null;
|
|
63
|
+
}
|
|
64
|
+
await this.#writing;
|
|
65
|
+
if (this.#dirtySince !== null)
|
|
66
|
+
await this.#checkpoint();
|
|
67
|
+
}
|
|
68
|
+
async close() {
|
|
69
|
+
await this.flush();
|
|
70
|
+
this.#closed = true;
|
|
71
|
+
}
|
|
72
|
+
#armDegradedDeadline() {
|
|
73
|
+
if (this.#degradedTimer !== null || this.#dirtySince === null || this.#closed)
|
|
74
|
+
return;
|
|
75
|
+
const delay = Math.max(0, this.#maximumDirtyMs - (this.#now() - this.#dirtySince));
|
|
76
|
+
this.#degradedTimer = this.#scheduleTimer(() => {
|
|
77
|
+
this.#degradedTimer = null;
|
|
78
|
+
if (this.#dirtySince !== null && this.#now() - this.#dirtySince >= this.#maximumDirtyMs) {
|
|
79
|
+
this.#setDegraded(true);
|
|
80
|
+
}
|
|
81
|
+
else if (this.#dirtySince !== null) {
|
|
82
|
+
this.#armDegradedDeadline();
|
|
83
|
+
}
|
|
84
|
+
}, delay);
|
|
85
|
+
}
|
|
86
|
+
#clearDegradedDeadline() {
|
|
87
|
+
if (this.#degradedTimer !== null)
|
|
88
|
+
this.#cancelTimer(this.#degradedTimer);
|
|
89
|
+
this.#degradedTimer = null;
|
|
90
|
+
}
|
|
91
|
+
#schedule() {
|
|
92
|
+
if (this.#timer !== null || this.#writing !== null || this.#closed)
|
|
93
|
+
return;
|
|
94
|
+
const age = this.#dirtySince === null ? 0 : this.#now() - this.#dirtySince;
|
|
95
|
+
if (age > this.#maximumDirtyMs)
|
|
96
|
+
this.#setDegraded(true);
|
|
97
|
+
this.#timer = this.#scheduleTimer(async () => {
|
|
98
|
+
this.#timer = null;
|
|
99
|
+
this.#writing = this.#checkpoint().finally(() => {
|
|
100
|
+
this.#writing = null;
|
|
101
|
+
if (this.#dirtySince !== null)
|
|
102
|
+
this.#schedule();
|
|
103
|
+
});
|
|
104
|
+
await this.#writing.catch(() => undefined);
|
|
105
|
+
}, this.#intervalMs);
|
|
106
|
+
}
|
|
107
|
+
async #checkpoint() {
|
|
108
|
+
if (this.#dirtySince === null)
|
|
109
|
+
return;
|
|
110
|
+
const snapshot = this.#text;
|
|
111
|
+
const temporary = `${this.path}.tmp-${process.pid}-${randomUUID()}`;
|
|
112
|
+
try {
|
|
113
|
+
await mkdir(dirname(this.path), { recursive: true, mode: 0o700 });
|
|
114
|
+
if (process.platform !== "win32")
|
|
115
|
+
await chmod(dirname(this.path), 0o700);
|
|
116
|
+
this.#faults.at("draft-during-temp-write");
|
|
117
|
+
await this.#write(temporary, `${JSON.stringify({ text: snapshot, savedAt: new Date(this.#now()).toISOString() })}\n`);
|
|
118
|
+
this.#faults.at("draft-before-rename");
|
|
119
|
+
await this.#move(temporary, this.path);
|
|
120
|
+
this.#faults.at("draft-after-rename");
|
|
121
|
+
if (process.platform !== "win32")
|
|
122
|
+
await chmod(this.path, 0o600);
|
|
123
|
+
if (this.#text === snapshot)
|
|
124
|
+
this.#dirtySince = null;
|
|
125
|
+
else
|
|
126
|
+
this.#dirtySince = this.#now();
|
|
127
|
+
this.#clearDegradedDeadline();
|
|
128
|
+
if (this.#dirtySince !== null)
|
|
129
|
+
this.#armDegradedDeadline();
|
|
130
|
+
this.#setDegraded(false);
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
await unlink(temporary).catch(() => undefined);
|
|
134
|
+
this.#clearDegradedDeadline();
|
|
135
|
+
this.#setDegraded(true);
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
#setDegraded(value) {
|
|
140
|
+
if (this.#degraded === value)
|
|
141
|
+
return;
|
|
142
|
+
this.#degraded = value;
|
|
143
|
+
this.#onDegraded(value);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type TerminalHostFallbackReason = "unsupported platform" | "no interactive terminal" | "terminal host not installed" | "terminal host not verified" | "host probe failed" | "incompatible generation" | "registry unreadable" | "recovery blocked" | "launch not verified" | "host startup timed out";
|
|
2
|
+
export interface TerminalHostCommand {
|
|
3
|
+
readonly executable: string;
|
|
4
|
+
readonly entry: string;
|
|
5
|
+
}
|
|
6
|
+
export type EnsureTerminalHostResult = {
|
|
7
|
+
readonly status: "ready";
|
|
8
|
+
readonly executable: TerminalHostCommand;
|
|
9
|
+
readonly endpoint: string;
|
|
10
|
+
} | {
|
|
11
|
+
readonly status: "fallback";
|
|
12
|
+
readonly reason: TerminalHostFallbackReason;
|
|
13
|
+
};
|
|
14
|
+
interface HostCommandResult {
|
|
15
|
+
readonly code: number;
|
|
16
|
+
readonly stdout: string;
|
|
17
|
+
readonly stderr: string;
|
|
18
|
+
}
|
|
19
|
+
export interface EnsureTerminalHostOptions {
|
|
20
|
+
readonly releaseRoot: string;
|
|
21
|
+
readonly profileRoot: string;
|
|
22
|
+
readonly dataDir: string;
|
|
23
|
+
readonly runtimeDir: string;
|
|
24
|
+
readonly environment: NodeJS.ProcessEnv;
|
|
25
|
+
readonly platform?: NodeJS.Platform;
|
|
26
|
+
readonly architecture?: string;
|
|
27
|
+
readonly timeoutMs?: number;
|
|
28
|
+
readonly maxConcurrentStarts?: number;
|
|
29
|
+
readonly unresponsiveRestartSeconds?: number;
|
|
30
|
+
readonly run?: (executable: string, arguments_: readonly string[], environment: NodeJS.ProcessEnv, timeoutMs: number) => Promise<HostCommandResult>;
|
|
31
|
+
readonly verify?: (addon: string, platform: NodeJS.Platform, architecture: string) => Promise<unknown>;
|
|
32
|
+
}
|
|
33
|
+
export declare function resolveTerminalHostPath(releaseRoot: string, environment?: NodeJS.ProcessEnv, platform?: NodeJS.Platform, architecture?: string): string;
|
|
34
|
+
export declare function resolveTerminalHostEntryPath(releaseRoot: string): string;
|
|
35
|
+
export declare function ensureTerminalHost(options: EnsureTerminalHostOptions): Promise<EnsureTerminalHostResult>;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { access } from "node:fs/promises";
|
|
3
|
+
import { constants } from "node:fs";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
6
|
+
import { TerminalHostArtifactError, verifyTerminalHostArtifact } from "./terminal-host-artifact.js";
|
|
7
|
+
export function resolveTerminalHostPath(releaseRoot, environment = process.env, platform = process.platform, architecture = process.arch) {
|
|
8
|
+
const override = developmentOverride(environment);
|
|
9
|
+
if (override)
|
|
10
|
+
return resolve(override);
|
|
11
|
+
return resolve(releaseRoot, "dist", "native", `${platform}-${architecture}`, `${PRODUCT_IDENTITY.artifacts.terminalHostAddon}.node`);
|
|
12
|
+
}
|
|
13
|
+
export function resolveTerminalHostEntryPath(releaseRoot) {
|
|
14
|
+
return resolve(releaseRoot, "dist", "foundation", "resident-tabs", `${PRODUCT_IDENTITY.artifacts.terminalHostEntry}.js`);
|
|
15
|
+
}
|
|
16
|
+
/** The terminal-host override is a development aid; installed releases always run their own verified artifact. */
|
|
17
|
+
function developmentOverride(environment) {
|
|
18
|
+
if (!environment[PRODUCT_IDENTITY.environment.developmentInstanceId])
|
|
19
|
+
return undefined;
|
|
20
|
+
return environment[PRODUCT_IDENTITY.environment.terminalHostPath]?.trim() || undefined;
|
|
21
|
+
}
|
|
22
|
+
export async function ensureTerminalHost(options) {
|
|
23
|
+
const platform = options.platform ?? process.platform;
|
|
24
|
+
const architecture = options.architecture ?? process.arch;
|
|
25
|
+
if (!supported(platform, architecture))
|
|
26
|
+
return { status: "fallback", reason: "unsupported platform" };
|
|
27
|
+
const addon = resolveTerminalHostPath(options.releaseRoot, options.environment, platform, architecture);
|
|
28
|
+
const command = { executable: process.execPath, entry: resolveTerminalHostEntryPath(options.releaseRoot) };
|
|
29
|
+
if (developmentOverride(options.environment)) {
|
|
30
|
+
try {
|
|
31
|
+
await Promise.all([access(addon, constants.R_OK), access(command.entry, constants.R_OK)]);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return { status: "fallback", reason: "terminal host not installed" };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
try {
|
|
39
|
+
await (options.verify ?? verifyTerminalHostArtifact)(addon, platform, architecture);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
return { status: "fallback", reason: verificationReason(error) };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const run = options.run ?? runHostCommand;
|
|
46
|
+
const timeoutMs = options.timeoutMs ?? 8_000;
|
|
47
|
+
const common = ["--profile", options.profileRoot, "--data-dir", options.dataDir, "--runtime-dir", options.runtimeDir];
|
|
48
|
+
const environment = { ...options.environment };
|
|
49
|
+
const invoke = async (arguments_, commandTimeoutMs) => await run(command.executable, [command.entry, ...arguments_], environment, commandTimeoutMs);
|
|
50
|
+
try {
|
|
51
|
+
const probe = await invoke(["probe", ...common], Math.min(4_000, timeoutMs));
|
|
52
|
+
const existing = parseResult(probe.stdout);
|
|
53
|
+
if (probe.code === 0) {
|
|
54
|
+
if (existing?.generation === 1 && typeof existing.endpoint === "string") {
|
|
55
|
+
return { status: "ready", executable: command, endpoint: existing.endpoint };
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
status: "fallback",
|
|
59
|
+
reason: typeof existing?.generation === "number" ? "incompatible generation" : "host probe failed",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (probe.code === 4 || existing?.outcome === "incompatible-generation")
|
|
63
|
+
return { status: "fallback", reason: "incompatible generation" };
|
|
64
|
+
if (existing?.outcome !== "not-running" && probe.code !== 3)
|
|
65
|
+
return { status: "fallback", reason: classifiedReason(existing?.reason, "host probe failed") };
|
|
66
|
+
const maximum = Math.max(1, Math.min(8, Math.trunc(options.maxConcurrentStarts ?? 2)));
|
|
67
|
+
const unresponsiveRestartSeconds = Math.max(30, Math.min(600, Math.trunc(options.unresponsiveRestartSeconds ?? 120)));
|
|
68
|
+
const start = await invoke([
|
|
69
|
+
"server", "--detach", ...common,
|
|
70
|
+
"--max-concurrent-starts", String(maximum),
|
|
71
|
+
"--unresponsive-restart-seconds", String(unresponsiveRestartSeconds),
|
|
72
|
+
], timeoutMs);
|
|
73
|
+
const started = parseResult(start.stdout);
|
|
74
|
+
if (start.code !== 0)
|
|
75
|
+
return { status: "fallback", reason: classifiedReason(started?.reason, "launch not verified") };
|
|
76
|
+
if (started?.verified !== true || typeof started.endpoint !== "string")
|
|
77
|
+
return { status: "fallback", reason: "launch not verified" };
|
|
78
|
+
const deadline = Date.now() + timeoutMs;
|
|
79
|
+
while (Date.now() < deadline) {
|
|
80
|
+
const result = await invoke(["probe", ...common], Math.min(1_000, Math.max(1, deadline - Date.now())));
|
|
81
|
+
const ready = parseResult(result.stdout);
|
|
82
|
+
if (result.code === 0) {
|
|
83
|
+
if (ready?.generation === 1 && typeof ready.endpoint === "string") {
|
|
84
|
+
return { status: "ready", executable: command, endpoint: ready.endpoint };
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
status: "fallback",
|
|
88
|
+
reason: typeof ready?.generation === "number" ? "incompatible generation" : "host probe failed",
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (result.code === 4 || ready?.outcome === "incompatible-generation")
|
|
92
|
+
return { status: "fallback", reason: "incompatible generation" };
|
|
93
|
+
await new Promise(resolvePromise => setTimeout(resolvePromise, 40));
|
|
94
|
+
}
|
|
95
|
+
return { status: "fallback", reason: "host startup timed out" };
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
return { status: "fallback", reason: isTimeout(error) ? "host startup timed out" : "host probe failed" };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function supported(platform, architecture) {
|
|
102
|
+
return (platform === "win32" || platform === "linux") && architecture === "x64"
|
|
103
|
+
|| platform === "darwin" && (architecture === "arm64" || architecture === "x64");
|
|
104
|
+
}
|
|
105
|
+
function verificationReason(error) {
|
|
106
|
+
if (!(error instanceof TerminalHostArtifactError))
|
|
107
|
+
return "terminal host not verified";
|
|
108
|
+
if (error.code === "TERMINAL_HOST_ARTIFACT_MISSING")
|
|
109
|
+
return "terminal host not installed";
|
|
110
|
+
if (error.code === "TERMINAL_HOST_ARTIFACT_UNSUPPORTED")
|
|
111
|
+
return "unsupported platform";
|
|
112
|
+
return "terminal host not verified";
|
|
113
|
+
}
|
|
114
|
+
function parseResult(output) {
|
|
115
|
+
const line = output.trim().split(/\r?\n/).filter(Boolean).at(-1);
|
|
116
|
+
if (!line)
|
|
117
|
+
return null;
|
|
118
|
+
try {
|
|
119
|
+
const parsed = JSON.parse(line);
|
|
120
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : null;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function classifiedReason(value, fallback) {
|
|
127
|
+
if (value === "registry-unreadable")
|
|
128
|
+
return "registry unreadable";
|
|
129
|
+
if (value === "blocked")
|
|
130
|
+
return "recovery blocked";
|
|
131
|
+
if (value === "incompatible-generation")
|
|
132
|
+
return "incompatible generation";
|
|
133
|
+
return fallback;
|
|
134
|
+
}
|
|
135
|
+
function isTimeout(error) { return error instanceof Error && "code" in error && error.code === "ETIMEDOUT"; }
|
|
136
|
+
async function runHostCommand(executable, arguments_, environment, timeoutMs) {
|
|
137
|
+
return await new Promise((resolvePromise, rejectPromise) => {
|
|
138
|
+
const child = spawn(executable, [...arguments_], { env: environment, windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
|
|
139
|
+
const stdout = [];
|
|
140
|
+
const stderr = [];
|
|
141
|
+
child.stdout.on("data", chunk => stdout.push(Buffer.from(chunk)));
|
|
142
|
+
child.stderr.on("data", chunk => stderr.push(Buffer.from(chunk)));
|
|
143
|
+
child.once("error", rejectPromise);
|
|
144
|
+
child.once("close", code => { clearTimeout(timer); resolvePromise({ code: code ?? 1, stdout: Buffer.concat(stdout).toString("utf8"), stderr: Buffer.concat(stderr).toString("utf8") }); });
|
|
145
|
+
const timer = setTimeout(() => {
|
|
146
|
+
child.kill("SIGKILL");
|
|
147
|
+
rejectPromise(Object.assign(new Error("terminal host command timed out"), { code: "ETIMEDOUT" }));
|
|
148
|
+
}, timeoutMs);
|
|
149
|
+
timer.unref();
|
|
150
|
+
});
|
|
151
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const RESIDENT_TAB_FAULT_ENVIRONMENT: readonly ["A1_TABS_FAULT_CRASH_POINT", "A1_TABS_HERMETIC_TEST"];
|
|
2
|
+
export declare function residentTabFaultEnvironment(point: string, hermetic?: boolean): NodeJS.ProcessEnv;
|
|
3
|
+
/** Test-only crash points are inert unless the caller explicitly marks a hermetic process. */
|
|
4
|
+
export declare class ResidentTabFaultInjection {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(environment?: NodeJS.ProcessEnv, crash?: (point: string) => never);
|
|
7
|
+
at(point: string): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const CRASH_POINT = "A1_TABS_FAULT_CRASH_POINT";
|
|
2
|
+
const HERMETIC = "A1_TABS_HERMETIC_TEST";
|
|
3
|
+
export const RESIDENT_TAB_FAULT_ENVIRONMENT = Object.freeze([CRASH_POINT, HERMETIC]);
|
|
4
|
+
export function residentTabFaultEnvironment(point, hermetic = true) {
|
|
5
|
+
return Object.fromEntries(hermetic ? [[CRASH_POINT, point], [HERMETIC, "1"]] : [[CRASH_POINT, point]]);
|
|
6
|
+
}
|
|
7
|
+
/** Test-only crash points are inert unless the caller explicitly marks a hermetic process. */
|
|
8
|
+
export class ResidentTabFaultInjection {
|
|
9
|
+
#point;
|
|
10
|
+
#crash;
|
|
11
|
+
constructor(environment = process.env, crash = point => {
|
|
12
|
+
process.stderr.write(`resident tab injected crash: ${point}\n`);
|
|
13
|
+
process.abort();
|
|
14
|
+
}) {
|
|
15
|
+
const point = environment[CRASH_POINT];
|
|
16
|
+
if (point !== undefined && environment[HERMETIC] !== "1") {
|
|
17
|
+
throw new Error(`${CRASH_POINT} is available only in a hermetic resident-tab test`);
|
|
18
|
+
}
|
|
19
|
+
this.#point = point;
|
|
20
|
+
this.#crash = crash;
|
|
21
|
+
}
|
|
22
|
+
at(point) {
|
|
23
|
+
if (this.#point === point)
|
|
24
|
+
this.#crash(point);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type ResidentFixtureStoppedStage = "child-render-write";
|
|
2
|
+
export interface ResidentFixtureControlPort {
|
|
3
|
+
stopped(stage: ResidentFixtureStoppedStage): boolean;
|
|
4
|
+
fragmentChildWrite(data: string): readonly string[];
|
|
5
|
+
}
|
|
6
|
+
/** Returns the exact-artifact fixture control, or null for every ordinary resident child. */
|
|
7
|
+
export declare function residentFixtureControl(environment?: NodeJS.ProcessEnv): ResidentFixtureControlPort | null;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
4
|
+
import { residentProgressObserver } from "./progress-observation.js";
|
|
5
|
+
/** Returns the exact-artifact fixture control, or null for every ordinary resident child. */
|
|
6
|
+
export function residentFixtureControl(environment = process.env) {
|
|
7
|
+
const directory = environment[PRODUCT_IDENTITY.environment.residentFixtureControlDir];
|
|
8
|
+
if (environment === process.env)
|
|
9
|
+
delete process.env[PRODUCT_IDENTITY.environment.residentFixtureControlDir];
|
|
10
|
+
// Invariant: launch erases the bridge tab identity; the observer retains the observed one.
|
|
11
|
+
const tabId = residentProgressObserver(environment)?.tabId;
|
|
12
|
+
if (!directory || !tabId || !/^[a-z0-9-]{1,128}$/iu.test(tabId))
|
|
13
|
+
return null;
|
|
14
|
+
return {
|
|
15
|
+
stopped: stage => existsSync(join(directory, `${tabId}.${stage}.stop`)),
|
|
16
|
+
fragmentChildWrite: data => existsSync(join(directory, `${tabId}.child-render-fragments.enable`))
|
|
17
|
+
? boundedFragments(data)
|
|
18
|
+
: [data],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function boundedFragments(data) {
|
|
22
|
+
const points = [...data];
|
|
23
|
+
if (points.length <= 1)
|
|
24
|
+
return [data];
|
|
25
|
+
if (points.length <= 16)
|
|
26
|
+
return points;
|
|
27
|
+
const fragments = points.slice(0, 8);
|
|
28
|
+
const middle = points.slice(8, -8);
|
|
29
|
+
const chunkSize = Math.max(1, Math.ceil(middle.length / 48));
|
|
30
|
+
for (let index = 0; index < middle.length; index += chunkSize) {
|
|
31
|
+
fragments.push(middle.slice(index, index + chunkSize).join(""));
|
|
32
|
+
}
|
|
33
|
+
fragments.push(...points.slice(-8));
|
|
34
|
+
return fragments;
|
|
35
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
5
|
+
const filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const target = `${process.platform}-${process.arch}`;
|
|
7
|
+
const development = process.env[PRODUCT_IDENTITY.environment.developmentInstanceId]?.trim();
|
|
8
|
+
const override = development ? process.env[PRODUCT_IDENTITY.environment.terminalHostPath]?.trim() : undefined;
|
|
9
|
+
const addonPath = resolve(override || resolve(dirname(filename), "../../native", target, `${PRODUCT_IDENTITY.artifacts.terminalHostAddon}.node`));
|
|
10
|
+
const addon = createRequire(import.meta.url)(addonPath);
|
|
11
|
+
if (typeof addon.runRole !== "function")
|
|
12
|
+
throw new Error("terminal host addon exports are incompatible");
|
|
13
|
+
// Invariant: runRole blocks Node's main thread, so this entry must not register JavaScript signal
|
|
14
|
+
// listeners whose callbacks cannot run until the native role has already returned. Default process
|
|
15
|
+
// signal handling keeps attach clients and identity-verified resident roles externally stoppable.
|
|
16
|
+
process.env[PRODUCT_IDENTITY.environment.terminalHostPath] = addonPath;
|
|
17
|
+
process.exitCode = addon.runRole(process.argv.slice(2), { executable: process.execPath, entry: filename, artifact: addonPath });
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { ensureTerminalHost, resolveTerminalHostEntryPath, resolveTerminalHostPath } from "./ensure-terminal-host.js";
|
|
2
|
+
export type { EnsureTerminalHostOptions, EnsureTerminalHostResult, TerminalHostCommand, TerminalHostFallbackReason } from "./ensure-terminal-host.js";
|
|
3
|
+
export { readResidentTabLaunchSettings } from "./settings.js";
|
|
4
|
+
export type { ResidentTabLaunchSettings } from "./settings.js";
|
|
5
|
+
export { selectResidentHost } from "./routing.js";
|
|
6
|
+
export type { ResidentHostSelectionOptions } from "./routing.js";
|
|
7
|
+
export { readResidentReleaseHolds } from "./release-holds.js";
|
|
8
|
+
export type { ResidentReleaseHoldReport } from "./release-holds.js";
|
|
9
|
+
export { runTerminalHostMaintenance } from "./maintenance.js";
|
|
10
|
+
export type { MaintenanceAction, MaintenanceHostState, MaintenanceOptions, MaintenanceReport } from "./maintenance.js";
|
|
11
|
+
export { DOCTOR_MAX_BYTES, writeDoctorBundle } from "./doctor.js";
|
|
12
|
+
export type { DoctorBundle, DoctorOptions } from "./doctor.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { ensureTerminalHost, resolveTerminalHostEntryPath, resolveTerminalHostPath } from "./ensure-terminal-host.js";
|
|
2
|
+
export { readResidentTabLaunchSettings } from "./settings.js";
|
|
3
|
+
export { selectResidentHost } from "./routing.js";
|
|
4
|
+
export { readResidentReleaseHolds } from "./release-holds.js";
|
|
5
|
+
export { runTerminalHostMaintenance } from "./maintenance.js";
|
|
6
|
+
export { DOCTOR_MAX_BYTES, writeDoctorBundle } from "./doctor.js";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type TerminalHostCommand } from "./ensure-terminal-host.js";
|
|
2
|
+
export type MaintenanceAction = "list" | "stop" | "stop-all" | "host-status" | "host-stop";
|
|
3
|
+
export type MaintenanceHostState = "none" | "running" | "stopped" | "unresponsive" | "incompatible" | "refused" | "unverifiable" | "unavailable";
|
|
4
|
+
/** The versioned `a1 tabs` report: `a1-tabs-maintenance-v1`, as printed by the terminal host. */
|
|
5
|
+
export interface MaintenanceReport {
|
|
6
|
+
readonly schema: "a1-tabs-maintenance-v1";
|
|
7
|
+
readonly command: string;
|
|
8
|
+
readonly host: MaintenanceHostState;
|
|
9
|
+
readonly stateDir?: string;
|
|
10
|
+
readonly result?: Record<string, unknown>;
|
|
11
|
+
readonly pid?: number;
|
|
12
|
+
readonly message?: string;
|
|
13
|
+
readonly releaseRoot?: string | null;
|
|
14
|
+
readonly terminatedUnresponsive?: number;
|
|
15
|
+
/** The terminal host's exit status: 0 success, 3 refused or failed, 4 another generation. */
|
|
16
|
+
readonly exitCode: number;
|
|
17
|
+
}
|
|
18
|
+
export interface MaintenanceOptions {
|
|
19
|
+
readonly action: MaintenanceAction;
|
|
20
|
+
readonly tabId?: string;
|
|
21
|
+
readonly profileRoot: string;
|
|
22
|
+
readonly dataDir: string;
|
|
23
|
+
readonly runtimeDir: string;
|
|
24
|
+
/** The first root is the invoking release; other roots never substitute for it. */
|
|
25
|
+
readonly releaseRoots: readonly string[];
|
|
26
|
+
readonly environment: NodeJS.ProcessEnv;
|
|
27
|
+
readonly platform?: NodeJS.Platform;
|
|
28
|
+
readonly architecture?: string;
|
|
29
|
+
readonly timeoutMs?: number;
|
|
30
|
+
readonly verify?: (addon: string, platform: NodeJS.Platform, architecture: string) => Promise<unknown>;
|
|
31
|
+
readonly run?: (command: TerminalHostCommand, arguments_: readonly string[], timeoutMs: number) => Promise<{
|
|
32
|
+
readonly code: number;
|
|
33
|
+
readonly stdout: string;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
/** Runs maintenance only through the invoking release; another cohort is never a retry target. */
|
|
37
|
+
export declare function runTerminalHostMaintenance(options: MaintenanceOptions): Promise<MaintenanceReport>;
|
|
38
|
+
/** The largest maintenance report accepted from the terminal host. */
|
|
39
|
+
export declare const MAX_MAINTENANCE_REPORT_BYTES: number;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { access } from "node:fs/promises";
|
|
3
|
+
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
4
|
+
import { runBoundedHostCommand } from "./bounded-host-command.js";
|
|
5
|
+
import { resolveTerminalHostEntryPath, resolveTerminalHostPath } from "./ensure-terminal-host.js";
|
|
6
|
+
import { verifyTerminalHostArtifact } from "./terminal-host-artifact.js";
|
|
7
|
+
/** Runs maintenance only through the invoking release; another cohort is never a retry target. */
|
|
8
|
+
export async function runTerminalHostMaintenance(options) {
|
|
9
|
+
const platform = options.platform ?? process.platform;
|
|
10
|
+
const architecture = options.architecture ?? process.arch;
|
|
11
|
+
const command = await firstVerifiedHost(options, options.releaseRoots.slice(0, 1), platform, architecture);
|
|
12
|
+
if (command === undefined)
|
|
13
|
+
return unavailable(options.action, "the invoking release has no verified terminal host");
|
|
14
|
+
return await invoke(options, command);
|
|
15
|
+
}
|
|
16
|
+
function arguments_(options) {
|
|
17
|
+
const command = options.action === "stop" ? ["stop", options.tabId ?? ""] : [options.action];
|
|
18
|
+
return ["tabs", ...command, "--profile", options.profileRoot, "--data-dir", options.dataDir, "--runtime-dir", options.runtimeDir];
|
|
19
|
+
}
|
|
20
|
+
async function invoke(options, command) {
|
|
21
|
+
const timeoutMs = options.timeoutMs ?? 120_000;
|
|
22
|
+
try {
|
|
23
|
+
const run = options.run ?? ((host, argumentsValue, limit) => runHost(host, argumentsValue, limit, options.environment));
|
|
24
|
+
const result = await run(command, arguments_(options), timeoutMs);
|
|
25
|
+
const line = result.stdout.trim().split(/\r?\n/u).at(-1) ?? "";
|
|
26
|
+
const parsed = JSON.parse(line);
|
|
27
|
+
if (parsed.schema !== "a1-tabs-maintenance-v1" || typeof parsed.host !== "string")
|
|
28
|
+
throw new Error("malformed maintenance report");
|
|
29
|
+
return { ...parsed, exitCode: result.code };
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
return unavailable(options.action, `terminal host maintenance failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function firstVerifiedHost(options, roots, platform, architecture) {
|
|
36
|
+
const override = options.environment[PRODUCT_IDENTITY.environment.developmentInstanceId]
|
|
37
|
+
? options.environment[PRODUCT_IDENTITY.environment.terminalHostPath]?.trim()
|
|
38
|
+
: undefined;
|
|
39
|
+
if (override) {
|
|
40
|
+
const entry = roots[0] === undefined ? undefined : resolveTerminalHostEntryPath(roots[0]);
|
|
41
|
+
if (entry === undefined)
|
|
42
|
+
return undefined;
|
|
43
|
+
try {
|
|
44
|
+
await Promise.all([access(override, constants.R_OK), access(entry, constants.R_OK)]);
|
|
45
|
+
return { executable: process.execPath, entry };
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
for (const root of roots) {
|
|
52
|
+
const addon = resolveTerminalHostPath(root, {}, platform, architecture);
|
|
53
|
+
try {
|
|
54
|
+
await (options.verify ?? verifyTerminalHostArtifact)(addon, platform, architecture);
|
|
55
|
+
return { executable: process.execPath, entry: resolveTerminalHostEntryPath(root) };
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Invariant: a missing or altered invoking artifact fails closed.
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
function unavailable(action, message) {
|
|
64
|
+
return { schema: "a1-tabs-maintenance-v1", command: action, host: "unavailable", message, exitCode: 3 };
|
|
65
|
+
}
|
|
66
|
+
/** The largest maintenance report accepted from the terminal host. */
|
|
67
|
+
export const MAX_MAINTENANCE_REPORT_BYTES = 4 * 1024 * 1024;
|
|
68
|
+
async function runHost(command, arguments_, timeoutMs, environment) {
|
|
69
|
+
return await runBoundedHostCommand(command, arguments_, {
|
|
70
|
+
environment,
|
|
71
|
+
maxStdoutBytes: MAX_MAINTENANCE_REPORT_BYTES,
|
|
72
|
+
timeoutMs,
|
|
73
|
+
label: "terminal host maintenance",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Payload-free fixture schema; type-only imports keep it outside the evaluated startup graph. */
|
|
2
|
+
export type ResidentInputPhase = "receipt" | "semantic-start" | "semantic-end" | "composition-start" | "composition-end" | "write-start" | "write-end";
|
|
3
|
+
export interface ProgressFields {
|
|
4
|
+
readonly eventSequence?: number;
|
|
5
|
+
readonly revision?: number;
|
|
6
|
+
readonly geometryGeneration?: number;
|
|
7
|
+
readonly bytes?: number;
|
|
8
|
+
readonly count?: number;
|
|
9
|
+
readonly eventKind?: string;
|
|
10
|
+
readonly frameId?: number;
|
|
11
|
+
readonly renderCause?: string;
|
|
12
|
+
readonly fragmentCount?: number;
|
|
13
|
+
readonly transactionKind?: "synchronized-output" | "ordinary";
|
|
14
|
+
}
|
|
15
|
+
export interface ProgressRecord extends ProgressFields {
|
|
16
|
+
readonly schema: "a1-resident-progress-observation-v1";
|
|
17
|
+
readonly runId: string;
|
|
18
|
+
readonly role: "child";
|
|
19
|
+
readonly stage: "engine-delivery" | "child-render-write" | "child-input-phase";
|
|
20
|
+
readonly pid: number;
|
|
21
|
+
readonly processInstance: string;
|
|
22
|
+
readonly timestampUnixUs: number;
|
|
23
|
+
readonly clockErrorUs: number;
|
|
24
|
+
readonly sequence: number;
|
|
25
|
+
readonly tabId: string;
|
|
26
|
+
readonly incarnation: number;
|
|
27
|
+
readonly lostBefore: number;
|
|
28
|
+
}
|
|
29
|
+
export interface ResidentProgressObserverPort {
|
|
30
|
+
readonly tabId: string;
|
|
31
|
+
engineDelivery(event: unknown): void;
|
|
32
|
+
inputPhase?(phase: ResidentInputPhase, revision: number): void;
|
|
33
|
+
childRenderWrite(bytes: number, fragments: number, transaction: "synchronized-output" | "ordinary", frameId?: number, renderCause?: string): void;
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ResidentProgressObserverPort } from "./progress-observation-schema.js";
|
|
2
|
+
export type { ResidentProgressObserverPort } from "./progress-observation-schema.js";
|
|
3
|
+
/** Opt-in payload-free child observer; ordinary launches return null. */
|
|
4
|
+
export declare function residentProgressObserver(environment?: NodeJS.ProcessEnv): ResidentProgressObserverPort | null;
|