@timurproko/a1 0.2.6-dev.736 → 0.2.7-dev.1221
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 +196 -908
- package/dist/app/session-shell/session-shell.d.ts +3 -8
- package/dist/app/session-shell/session-shell.js +324 -835
- package/dist/app/session-shell/session-viewport-controller.d.ts +2 -2
- package/dist/app/session-shell/session-viewport-controller.js +29 -15
- 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 +102 -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 +205 -153
- 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 -1
- package/dist/composition/settings-route-host.js +29 -10
- package/dist/composition/settings-search-input.d.ts +9 -0
- package/dist/composition/settings-search-input.js +58 -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 +242 -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 +76 -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-screen-app.d.ts +2 -0
- package/dist/features/owned-ui/reference-screen-app.js +12 -2
- package/dist/features/owned-ui/resources/release-notes.json +4 -0
- package/dist/features/owned-ui/settings-app.d.ts +12 -2
- package/dist/features/owned-ui/settings-app.js +119 -84
- 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 +6 -3
- 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 +90 -6
- 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 +73 -4
- 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.js +35 -30
- package/dist/ui/components/index.d.ts +2 -2
- package/dist/ui/components/index.js +1 -1
- 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/selection-copy.d.ts +2 -0
- package/dist/ui/components/selection-copy.js +13 -0
- 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.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 +176 -55
- package/dist/ui/components/value-menu.d.ts +6 -3
- package/dist/ui/components/value-menu.js +6 -5
- 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 +25 -10
- 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/evidence/terminal-host-spike/manual-one-pane-terminal-host.md +70 -0
- package/docs/architecture/evidence/terminal-host-spike/manual-two-by-two-basic-terminal-host.md +32 -0
- package/docs/architecture/evidence/terminal-host-spike/milestone-baseline.json +115 -0
- package/docs/architecture/evidence/terminal-host-spike/owned-ui-foundation-prerequisite.json +48 -0
- package/docs/architecture/evidence/terminal-host-spike/terminal-host-provenance.json +125 -0
- package/docs/architecture/evidence/terminal-host-spike/terminal-host-task-5-1.json +56 -0
- package/docs/architecture/evidence/terminal-host-spike/terminal-host-task-5-3.json +174 -0
- package/docs/architecture/evidence/terminal-host-spike/terminal-spike-acceptance-record.json +18 -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 +648 -0
- package/docs/architecture/response-copy-delivery.md +1 -1
- package/docs/architecture/terminal-host-proof-gate.md +3 -1
- package/docs/architecture/terminal-host-provenance.md +16 -4
- package/docs/architecture/terminal-host-spike-evidence.md +1 -1
- 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/releases/0.2.6.md +44 -0
- 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,265 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { mkdir, open, readFile, rename, rm } from "node:fs/promises";
|
|
4
|
+
import { dirname, resolve } from "node:path";
|
|
5
|
+
import { valid as validSemver } from "semver";
|
|
6
|
+
import { readLaunchContext } from "../launch-context/index.js";
|
|
7
|
+
import { resolveProductPaths } from "../lifecycle/index.js";
|
|
8
|
+
import { CohortStateStore } from "./cohort-state.js";
|
|
9
|
+
import { processIsAlive } from "./process-cleanup.js";
|
|
10
|
+
import { isNewerRelease, releaseChannelOf } from "./latest-release.js";
|
|
11
|
+
import { readCertifiedReleaseManifest, resolveReleaseEntryPoint } from "./release-store.js";
|
|
12
|
+
import { readUpdateExecutionOwner } from "./update-execution-lease.js";
|
|
13
|
+
import { runSelfUpdate, UPDATE_ALREADY_RUNNING_EXIT_CODE } from "./update.js";
|
|
14
|
+
export const AUTOMATIC_UPDATE_STATE_SCHEMA = 1;
|
|
15
|
+
export const AUTOMATIC_UPDATE_RETRY_MS = 24 * 60 * 60_000;
|
|
16
|
+
const AUTOMATIC_UPDATE_STATE_FILENAME = "automatic-update.json";
|
|
17
|
+
const MAX_STATE_BYTES = 16_384;
|
|
18
|
+
const OBSERVER_POLL_MS = 250;
|
|
19
|
+
const WORKER_START_GRACE_MS = 5_000;
|
|
20
|
+
export class AutomaticUpdateStateStore {
|
|
21
|
+
path;
|
|
22
|
+
constructor(dataDir) { this.path = resolve(dataDir, AUTOMATIC_UPDATE_STATE_FILENAME); }
|
|
23
|
+
async read() {
|
|
24
|
+
let source;
|
|
25
|
+
try {
|
|
26
|
+
source = await readFile(this.path, "utf8");
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (hasCode(error, "ENOENT"))
|
|
30
|
+
return null;
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
if (Buffer.byteLength(source, "utf8") > MAX_STATE_BYTES)
|
|
34
|
+
throw new Error("automatic update state is oversized");
|
|
35
|
+
const value = JSON.parse(source);
|
|
36
|
+
validateState(value);
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
async write(value) {
|
|
40
|
+
validateState(value);
|
|
41
|
+
await mkdir(dirname(this.path), { recursive: true, mode: 0o700 });
|
|
42
|
+
const temporary = `${this.path}.${process.pid}.${randomUUID()}.tmp`;
|
|
43
|
+
const file = await open(temporary, "wx", 0o600);
|
|
44
|
+
try {
|
|
45
|
+
await file.writeFile(`${JSON.stringify(value)}\n`);
|
|
46
|
+
await file.sync();
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
await file.close();
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
await rename(temporary, this.path);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
await rm(temporary, { force: true });
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Start or observe one silent update and resolve with the active newer version once restart is useful. */
|
|
61
|
+
export async function requestAutomaticUpdate(options) {
|
|
62
|
+
if (options.signal?.aborted)
|
|
63
|
+
return null;
|
|
64
|
+
const environment = options.environment ?? process.env;
|
|
65
|
+
const paths = resolveProductPaths(environment);
|
|
66
|
+
const now = options.now ?? Date.now;
|
|
67
|
+
const store = new AutomaticUpdateStateStore(paths.dataDir);
|
|
68
|
+
let existing;
|
|
69
|
+
try {
|
|
70
|
+
existing = await store.read();
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
const readActiveVersion = options.activeVersion ?? (async () => await activeNewerVersion(paths.dataDir, options.runningVersion));
|
|
76
|
+
const active = await readActiveVersion();
|
|
77
|
+
if (active !== null)
|
|
78
|
+
return active;
|
|
79
|
+
if (existing?.status === "failed" && existing.channel === options.release.channel && now() - existing.attemptedAt >= 0
|
|
80
|
+
&& now() - existing.attemptedAt < AUTOMATIC_UPDATE_RETRY_MS
|
|
81
|
+
&& !isNewerRelease(options.release.version, existing.targetVersion))
|
|
82
|
+
return null;
|
|
83
|
+
let worker = options.worker;
|
|
84
|
+
if (worker === undefined) {
|
|
85
|
+
const launch = readLaunchContext(environment, "release");
|
|
86
|
+
const cohort = await new CohortStateStore(paths.dataDir).read();
|
|
87
|
+
const record = launch.releaseId === undefined ? undefined : cohort.releases[launch.releaseId];
|
|
88
|
+
if (!record || record.approval !== "approved" || record.releaseRoot !== launch.releaseRoot
|
|
89
|
+
|| record.contentDigest !== launch.releaseDigest)
|
|
90
|
+
return null;
|
|
91
|
+
const selected = await readCertifiedReleaseManifest(record, resolve(paths.dataDir, "releases"));
|
|
92
|
+
worker = {
|
|
93
|
+
entry: await resolveReleaseEntryPoint(selected, "bin/automatic-update.js"),
|
|
94
|
+
packageRoot: selected.packageRoot,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const arguments_ = [
|
|
98
|
+
"--package-root", worker.packageRoot,
|
|
99
|
+
"--channel", options.release.channel,
|
|
100
|
+
"--target-version", options.release.version,
|
|
101
|
+
"--data-dir", paths.dataDir,
|
|
102
|
+
];
|
|
103
|
+
let owner;
|
|
104
|
+
try {
|
|
105
|
+
owner = await readUpdateExecutionOwner(paths.dataDir);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
if (owner === null || !processIsAlive(owner.pid)) {
|
|
111
|
+
await (options.spawnWorker ?? spawnAutomaticUpdateWorker)(worker.entry, arguments_, environment).catch(() => undefined);
|
|
112
|
+
}
|
|
113
|
+
const startedAt = now();
|
|
114
|
+
const sleep = options.sleep ?? (async (durationMs) => await new Promise(resolvePromise => {
|
|
115
|
+
const timer = setTimeout(resolvePromise, durationMs);
|
|
116
|
+
timer.unref?.();
|
|
117
|
+
}));
|
|
118
|
+
while (!options.signal?.aborted) {
|
|
119
|
+
const installed = await readActiveVersion();
|
|
120
|
+
if (installed !== null)
|
|
121
|
+
return installed;
|
|
122
|
+
const state = await store.read().catch(() => null);
|
|
123
|
+
if (state?.targetVersion === options.release.version && state.status === "failed" && state.attemptedAt >= startedAt)
|
|
124
|
+
return null;
|
|
125
|
+
const owner = await readUpdateExecutionOwner(paths.dataDir).catch(() => null);
|
|
126
|
+
if ((owner === null || !processIsAlive(owner.pid)) && now() - startedAt >= WORKER_START_GRACE_MS)
|
|
127
|
+
return null;
|
|
128
|
+
await sleep(OBSERVER_POLL_MS);
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
export async function runAutomaticUpdateWorker(argv, environment = process.env) {
|
|
133
|
+
const parsed = parseWorkerArguments(argv);
|
|
134
|
+
const paths = resolveProductPaths(environment);
|
|
135
|
+
if (!samePath(parsed.dataDir, paths.dataDir))
|
|
136
|
+
return 1;
|
|
137
|
+
const launch = readLaunchContext(environment, "release");
|
|
138
|
+
const cohort = await new CohortStateStore(paths.dataDir).read();
|
|
139
|
+
const record = launch.releaseId === undefined ? undefined : cohort.releases[launch.releaseId];
|
|
140
|
+
if (!record || record.approval !== "approved" || !samePath(record.releaseRoot, launch.releaseRoot ?? "")
|
|
141
|
+
|| record.contentDigest !== launch.releaseDigest)
|
|
142
|
+
return 1;
|
|
143
|
+
const selected = await readCertifiedReleaseManifest(record, resolve(paths.dataDir, "releases"));
|
|
144
|
+
if (!samePath(selected.packageRoot, parsed.packageRoot))
|
|
145
|
+
return 1;
|
|
146
|
+
const store = new AutomaticUpdateStateStore(paths.dataDir);
|
|
147
|
+
const attemptedAt = Date.now();
|
|
148
|
+
const output = { stdout() { }, stderr() { } };
|
|
149
|
+
let acquired = false;
|
|
150
|
+
let runningWrite = Promise.resolve();
|
|
151
|
+
try {
|
|
152
|
+
const code = await runSelfUpdate({
|
|
153
|
+
packageRoot: parsed.packageRoot,
|
|
154
|
+
channel: parsed.channel === "stable" ? "stable" : "next",
|
|
155
|
+
resolvedTarget: parsed.targetVersion,
|
|
156
|
+
mode: "automatic",
|
|
157
|
+
environment,
|
|
158
|
+
output,
|
|
159
|
+
progress: false,
|
|
160
|
+
onLeaseAcquired: () => {
|
|
161
|
+
acquired = true;
|
|
162
|
+
runningWrite = store.write(state(parsed, "running", attemptedAt, null, null));
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
if (code === UPDATE_ALREADY_RUNNING_EXIT_CODE)
|
|
166
|
+
return 0;
|
|
167
|
+
if (code !== 0) {
|
|
168
|
+
await runningWrite;
|
|
169
|
+
await store.write(state(parsed, "failed", attemptedAt, null, `exit-${code}`));
|
|
170
|
+
return code;
|
|
171
|
+
}
|
|
172
|
+
const active = await activeRelease(paths.dataDir);
|
|
173
|
+
if (active === null || releaseChannelOf(active.packageVersion) !== parsed.channel
|
|
174
|
+
|| (active.packageVersion !== parsed.targetVersion && !isNewerRelease(active.packageVersion, parsed.targetVersion))) {
|
|
175
|
+
if (acquired) {
|
|
176
|
+
await runningWrite;
|
|
177
|
+
await store.write(state(parsed, "failed", attemptedAt, null, "target-not-active"));
|
|
178
|
+
}
|
|
179
|
+
return 1;
|
|
180
|
+
}
|
|
181
|
+
await runningWrite;
|
|
182
|
+
await store.write(state(parsed, "installed", attemptedAt, active.packageVersion, null));
|
|
183
|
+
return 0;
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
await runningWrite.catch(() => undefined);
|
|
187
|
+
await store.write(state(parsed, "failed", attemptedAt, null, errorMessage(error).slice(0, 512))).catch(() => undefined);
|
|
188
|
+
return 1;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async function spawnAutomaticUpdateWorker(entry, arguments_, environment) {
|
|
192
|
+
const child = spawn(process.execPath, [entry, ...arguments_], {
|
|
193
|
+
detached: true,
|
|
194
|
+
env: environment,
|
|
195
|
+
stdio: "ignore",
|
|
196
|
+
windowsHide: true,
|
|
197
|
+
});
|
|
198
|
+
await new Promise((resolvePromise, rejectPromise) => {
|
|
199
|
+
child.once("spawn", resolvePromise);
|
|
200
|
+
child.once("error", rejectPromise);
|
|
201
|
+
});
|
|
202
|
+
child.unref();
|
|
203
|
+
}
|
|
204
|
+
async function activeNewerVersion(dataDir, runningVersion) {
|
|
205
|
+
const active = await activeRelease(dataDir);
|
|
206
|
+
return active !== null && isNewerRelease(active.packageVersion, runningVersion) ? active.packageVersion : null;
|
|
207
|
+
}
|
|
208
|
+
async function activeRelease(dataDir) {
|
|
209
|
+
const cohort = await new CohortStateStore(dataDir).read();
|
|
210
|
+
const activeId = cohort.references.active;
|
|
211
|
+
if (activeId === null)
|
|
212
|
+
return null;
|
|
213
|
+
const active = cohort.releases[activeId];
|
|
214
|
+
return active?.approval === "approved" ? active : null;
|
|
215
|
+
}
|
|
216
|
+
function state(parsed, status, attemptedAt, installedVersion, failure) {
|
|
217
|
+
return {
|
|
218
|
+
schema: AUTOMATIC_UPDATE_STATE_SCHEMA,
|
|
219
|
+
channel: parsed.channel,
|
|
220
|
+
targetVersion: parsed.targetVersion,
|
|
221
|
+
status,
|
|
222
|
+
attemptedAt,
|
|
223
|
+
updatedAt: Date.now(),
|
|
224
|
+
installedVersion,
|
|
225
|
+
failure,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function parseWorkerArguments(argv) {
|
|
229
|
+
const values = new Map();
|
|
230
|
+
for (let index = 0; index < argv.length; index += 2) {
|
|
231
|
+
const key = argv[index];
|
|
232
|
+
const value = argv[index + 1];
|
|
233
|
+
if (!key?.startsWith("--") || value === undefined || values.has(key))
|
|
234
|
+
throw new Error("invalid automatic update worker arguments");
|
|
235
|
+
values.set(key, value);
|
|
236
|
+
}
|
|
237
|
+
const packageRoot = values.get("--package-root");
|
|
238
|
+
const channel = values.get("--channel");
|
|
239
|
+
const targetVersion = values.get("--target-version");
|
|
240
|
+
const dataDir = values.get("--data-dir");
|
|
241
|
+
if (!packageRoot || (channel !== "stable" && channel !== "development") || !targetVersion || !dataDir
|
|
242
|
+
|| validSemver(targetVersion) === null)
|
|
243
|
+
throw new Error("incomplete automatic update worker arguments");
|
|
244
|
+
return { packageRoot, channel, targetVersion, dataDir };
|
|
245
|
+
}
|
|
246
|
+
function validateState(value) {
|
|
247
|
+
if (value.schema !== AUTOMATIC_UPDATE_STATE_SCHEMA || (value.channel !== "stable" && value.channel !== "development")
|
|
248
|
+
|| validSemver(value.targetVersion) === null || !["running", "installed", "failed"].includes(value.status)
|
|
249
|
+
|| !Number.isFinite(value.attemptedAt) || !Number.isFinite(value.updatedAt)
|
|
250
|
+
|| (value.installedVersion !== null && validSemver(value.installedVersion) === null)
|
|
251
|
+
|| (value.failure !== null && (typeof value.failure !== "string" || value.failure.length > 512))) {
|
|
252
|
+
throw new Error("invalid automatic update state");
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function samePath(left, right) {
|
|
256
|
+
const canonicalLeft = resolve(left);
|
|
257
|
+
const canonicalRight = resolve(right);
|
|
258
|
+
return process.platform === "win32"
|
|
259
|
+
? canonicalLeft.toLowerCase() === canonicalRight.toLowerCase()
|
|
260
|
+
: canonicalLeft === canonicalRight;
|
|
261
|
+
}
|
|
262
|
+
function hasCode(error, code) {
|
|
263
|
+
return error instanceof Error && "code" in error && error.code === code;
|
|
264
|
+
}
|
|
265
|
+
function errorMessage(error) { return error instanceof Error ? error.message : String(error); }
|
|
@@ -2,27 +2,25 @@ import { type SupervisorEndpointMetadata } from "./cohort-state.js";
|
|
|
2
2
|
import { resolveProductPaths, type SessionSelection, type LaunchProfileId, type SupervisorStartupAttemptIdentity } from "../lifecycle/index.js";
|
|
3
3
|
import { cleanupProvenIdleOwner } from "./process-cleanup.js";
|
|
4
4
|
import { type MaterializedRelease, type VerifyMaterializedReleaseOptions } from "./release-store.js";
|
|
5
|
+
import { type EnsureTerminalHostOptions, type EnsureTerminalHostResult } from "../resident-tabs/index.js";
|
|
5
6
|
export interface BootstrapOptions {
|
|
6
7
|
readonly packageRoot: string;
|
|
7
8
|
readonly launchIntent?: {
|
|
8
9
|
readonly kind: "interactive";
|
|
9
10
|
readonly profileId: LaunchProfileId;
|
|
11
|
+
readonly launchMode: "tabs" | "solo";
|
|
10
12
|
readonly sessionSelection?: SessionSelection;
|
|
11
13
|
};
|
|
12
14
|
readonly environment?: NodeJS.ProcessEnv;
|
|
13
15
|
readonly output?: Pick<NodeJS.WriteStream, "write">;
|
|
14
|
-
/**
|
|
15
|
-
* Whether a materialized release copy is fit to launch. The active release
|
|
16
|
-
* is normally reused while its version matches the installation, but a copy
|
|
17
|
-
* can be broken in ways a version cannot see — materialized from a tree a
|
|
18
|
-
* blocked postinstall never finished repairing. The probe is injected from
|
|
19
|
-
* the bin entry because deciding it requires inspecting dependency
|
|
20
|
-
* resolution, which stays out of production code. Absent means every
|
|
21
|
-
* release is fit.
|
|
22
|
-
*/
|
|
16
|
+
/** Optional package-resolution probe that excludes a damaged retained release. */
|
|
23
17
|
readonly releaseIsLaunchable?: (releaseRoot: string) => boolean;
|
|
24
18
|
/** Test seam for bounded maintenance scheduled after stale endpoint sweeping. */
|
|
25
19
|
readonly scheduleMaintenance?: (dataDir: string, paths: ReturnType<typeof resolveProductPaths>) => Promise<void>;
|
|
20
|
+
/** Test seam for resident launch routing before the guardian starts. */
|
|
21
|
+
readonly ensureTerminalHost?: (options: EnsureTerminalHostOptions) => Promise<EnsureTerminalHostResult>;
|
|
22
|
+
/** Test seam for whether this process's standard input and output are terminals; absent reads them. */
|
|
23
|
+
readonly interactiveTerminal?: boolean;
|
|
26
24
|
}
|
|
27
25
|
export declare function runBootstrap(options: BootstrapOptions): Promise<number>;
|
|
28
26
|
export declare function certifyMaterializedRelease(release: MaterializedRelease, dataDir: string, verification?: VerifyMaterializedReleaseOptions): Promise<string>;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
-
import { restoreAfterOwnedExit } from "../terminal-cleanup/index.js";
|
|
2
|
+
import { RESIDENT_DETACH_INTERVAL_MS, restoreAfterOwnedExit } from "../terminal-cleanup/index.js";
|
|
3
3
|
import { chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
4
|
import { connect } from "node:net";
|
|
5
5
|
import { resolve } from "node:path";
|
|
6
6
|
import { selectCohortLaunch } from "./cohort-selection.js";
|
|
7
7
|
import { selectOrdinaryLaunchReleaseId } from "./ordinary-launch-selection.js";
|
|
8
|
+
import { releaseChannelOf } from "./latest-release.js";
|
|
8
9
|
import { CohortStateStore } from "./cohort-state.js";
|
|
9
10
|
import { assertLaunchProfileId, createSupervisorStartupAttempt, readSupervisorStartupResult, resolveCohortEndpoint, resolveProductPaths, sessionSelectionArguments } from "../lifecycle/index.js";
|
|
10
11
|
import { encodeFrame, LineFrameDecoder } from "../protocol/index.js";
|
|
@@ -12,29 +13,67 @@ import { cleanupProvenIdleOwner, processIsAlive } from "./process-cleanup.js";
|
|
|
12
13
|
import { probeOwnership, readEndpointMetadata, removeEndpointArtifacts, sweepDeadEndpoints } from "./endpoints.js";
|
|
13
14
|
import { UpdateTransactionStore } from "./update-transaction.js";
|
|
14
15
|
import { selectUpdateLaunchRelease } from "./update-launch.js";
|
|
15
|
-
import { consumeMaterializationProof, materializeRelease, readCertifiedReleaseManifest, readMaterializedRelease, resolveReleaseEntryPoint, verifyMaterializedRelease } from "./release-store.js";
|
|
16
|
+
import { assertCertifiedFilesPresent, consumeMaterializationProof, materializeRelease, readCertifiedReleaseManifest, readMaterializedRelease, repairMaterializedRelease, resolveReleaseEntryPoint, verifyMaterializedRelease } from "./release-store.js";
|
|
16
17
|
import { scheduleReleaseCleanup } from "./release-gc.js";
|
|
17
18
|
import { createRestartSeal, readRestartCertifiedRelease, releaseCertificationDocument } from "./restart-certification.js";
|
|
18
|
-
import { PRODUCT_TEXT } from "../../product-identity.js";
|
|
19
|
+
import { PRODUCT_IDENTITY, PRODUCT_TEXT } from "../../product-identity.js";
|
|
19
20
|
import { markStartupPhase } from "../startup/index.js";
|
|
20
|
-
import { launchContractTarget, readLaunchContext, withLaunchContext } from "../launch-context/index.js";
|
|
21
|
+
import { PRIVATE_ENVIRONMENT, isCurrentLaunchContract, launchContractTarget, readLaunchContext, withLaunchContext } from "../launch-context/index.js";
|
|
22
|
+
import { ensureTerminalHost, readResidentTabLaunchSettings, selectResidentHost } from "../resident-tabs/index.js";
|
|
21
23
|
const RELEASE_RESELECTION_MESSAGE = "a1-release-reselection";
|
|
22
24
|
export async function runBootstrap(options) {
|
|
23
25
|
return await runBootstrapAttempt(options, 1);
|
|
24
26
|
}
|
|
25
27
|
async function runBootstrapAttempt(options, retriesRemaining) {
|
|
26
|
-
const environment = withLaunchContext(options.environment ?? process.env, { launchProfile: options.launchIntent?.profileId ?? "a1" });
|
|
27
|
-
await markStartupPhase(environment, "bootstrap-start");
|
|
28
28
|
const launchProfileId = options.launchIntent?.profileId ?? "a1";
|
|
29
|
+
const launchMode = options.launchIntent?.launchMode ?? (launchProfileId === "a1" ? "tabs" : "solo");
|
|
30
|
+
const environment = withLaunchContext(options.environment ?? process.env, { launchProfile: launchProfileId, launchMode });
|
|
31
|
+
await markStartupPhase(environment, "bootstrap-start");
|
|
29
32
|
assertLaunchProfileId(launchProfileId);
|
|
30
33
|
const sessionArgs = sessionSelectionArguments(options.launchIntent?.sessionSelection);
|
|
31
|
-
if (sessionArgs.length > 0 && launchProfileId !== "a1")
|
|
32
|
-
throw new Error("session selection requires the normal A1
|
|
34
|
+
if (sessionArgs.length > 0 && (launchProfileId !== "a1" || launchMode === "solo")) {
|
|
35
|
+
throw new Error("session selection requires the normal tabbed A1 launch");
|
|
36
|
+
}
|
|
33
37
|
const output = options.output ?? process.stderr;
|
|
34
38
|
const paths = resolveProductPaths(environment);
|
|
35
39
|
await mkdir(paths.runtimeDir, { recursive: true, mode: 0o700 });
|
|
36
40
|
const launchSelected = async (release) => {
|
|
37
|
-
|
|
41
|
+
let residentContext = {};
|
|
42
|
+
// Compatibility: public launch preparation supplies PI_CODING_AGENT_DIR; the fallback keeps
|
|
43
|
+
// direct SDK/bootstrap callers hermetic while retaining their former config-root read.
|
|
44
|
+
const agentProfileDir = environment.PI_CODING_AGENT_DIR ?? paths.configDir;
|
|
45
|
+
const residentLaunchSettings = launchProfileId === "a1"
|
|
46
|
+
? readResidentTabLaunchSettings(agentProfileDir, PRODUCT_IDENTITY.commandName, paths.configDir, launchProfileId)
|
|
47
|
+
: null;
|
|
48
|
+
const resident = await selectResidentHost({
|
|
49
|
+
profileId: launchProfileId,
|
|
50
|
+
currentLaunchContract: isCurrentLaunchContract(release),
|
|
51
|
+
solo: launchMode === "solo",
|
|
52
|
+
interactive: options.interactiveTerminal ?? (process.stdin.isTTY === true && process.stdout.isTTY === true),
|
|
53
|
+
ensureHost: async () => (options.ensureTerminalHost ?? ensureTerminalHost)({
|
|
54
|
+
releaseRoot: release.releaseRoot,
|
|
55
|
+
profileRoot: environment[PRODUCT_IDENTITY.environment.profileHome] ?? paths.configDir,
|
|
56
|
+
dataDir: paths.dataDir,
|
|
57
|
+
runtimeDir: paths.runtimeDir,
|
|
58
|
+
environment,
|
|
59
|
+
maxConcurrentStarts: (await residentLaunchSettings).maxConcurrentStarts,
|
|
60
|
+
unresponsiveRestartSeconds: (await residentLaunchSettings).unresponsiveRestartSeconds,
|
|
61
|
+
}),
|
|
62
|
+
});
|
|
63
|
+
if (resident !== null) {
|
|
64
|
+
residentContext = resident.status === "ready" ? {
|
|
65
|
+
residentRootExecutable: resident.executable.executable,
|
|
66
|
+
residentRootArguments: JSON.stringify([
|
|
67
|
+
resident.executable.entry,
|
|
68
|
+
"attach", "--endpoint", resident.endpoint, "--cwd", process.cwd(), "--clear-exit-ms", String(RESIDENT_DETACH_INTERVAL_MS),
|
|
69
|
+
"--profile", environment[PRODUCT_IDENTITY.environment.profileHome] ?? paths.configDir,
|
|
70
|
+
"--settings-file", resolve(agentProfileDir, "settings.json"),
|
|
71
|
+
"--data-dir", paths.dataDir, "--runtime-dir", paths.runtimeDir,
|
|
72
|
+
"--release-root", release.releaseRoot, "--node-executable", process.execPath,
|
|
73
|
+
]),
|
|
74
|
+
} : { residentFallback: resident.reason };
|
|
75
|
+
}
|
|
76
|
+
const result = await launchUi(release, environment, sessionArgs, residentContext);
|
|
38
77
|
if (!result.releaseSuperseded)
|
|
39
78
|
return result.code;
|
|
40
79
|
if (retriesRemaining > 0)
|
|
@@ -86,9 +125,27 @@ async function runBootstrapAttempt(options, retriesRemaining) {
|
|
|
86
125
|
}
|
|
87
126
|
let probe = endpoint ? await probeOwnership(endpoint) : "dead";
|
|
88
127
|
const installedVersion = await readInstalledVersion(options.packageRoot);
|
|
128
|
+
if (releaseChannelOf(installedVersion) !== null)
|
|
129
|
+
environment[PRIVATE_ENVIRONMENT.updateVersion] = installedVersion;
|
|
89
130
|
const activeId = state.references.active;
|
|
90
131
|
const active = activeId === null ? undefined : state.releases[activeId];
|
|
91
|
-
|
|
132
|
+
let activeIsLaunchable = active === undefined || (options.releaseIsLaunchable?.(active.releaseRoot) ?? true);
|
|
133
|
+
let excludedRetainedReleaseId;
|
|
134
|
+
if (activeIsLaunchable && active?.approval === "approved" && active.packageVersion === installedVersion) {
|
|
135
|
+
try {
|
|
136
|
+
await assertCertifiedFilesPresent(active.releaseRoot);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
try {
|
|
140
|
+
await repairApprovedRelease(options.packageRoot, active, paths.dataDir);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// Security: a damaged certified release is no longer a fallback when package bytes cannot restore it.
|
|
144
|
+
activeIsLaunchable = false;
|
|
145
|
+
excludedRetainedReleaseId = active.releaseId;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
92
149
|
if (activeIsLaunchable && active?.approval === "approved" && active.packageVersion === installedVersion) {
|
|
93
150
|
const endpointMatches = endpoint?.releaseId === active.releaseId
|
|
94
151
|
&& endpoint.releaseRoot === active.releaseRoot
|
|
@@ -102,18 +159,27 @@ async function runBootstrapAttempt(options, retriesRemaining) {
|
|
|
102
159
|
await removeEndpointArtifacts(endpointPaths.endpointMetadataPath, endpointPaths.endpoint);
|
|
103
160
|
await markStartupPhase(environment, "durable-validation-start");
|
|
104
161
|
const retained = await readRestartCertifiedRelease(active, paths.dataDir).catch(async () => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
162
|
+
let verified;
|
|
163
|
+
try {
|
|
164
|
+
verified = await readMaterializedRelease(active.releaseRoot, resolve(paths.dataDir, "releases"));
|
|
108
165
|
}
|
|
166
|
+
catch {
|
|
167
|
+
verified = await repairApprovedRelease(options.packageRoot, active, paths.dataDir);
|
|
168
|
+
return verified;
|
|
169
|
+
}
|
|
170
|
+
assertApprovedReleaseMatches(verified, active);
|
|
109
171
|
await certifyMaterializedRelease(verified, paths.dataDir);
|
|
110
172
|
return verified;
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
173
|
+
}).catch(() => null);
|
|
174
|
+
if (retained !== null) {
|
|
175
|
+
await markStartupPhase(environment, "durable-validation-complete");
|
|
176
|
+
await markStartupPhase(environment, "replacement-supervisor-start");
|
|
177
|
+
await ensureSupervisor(retained, environment);
|
|
178
|
+
await markStartupPhase(environment, "replacement-supervisor-ready");
|
|
179
|
+
return await launchSelected(retained);
|
|
180
|
+
}
|
|
181
|
+
activeIsLaunchable = false;
|
|
182
|
+
excludedRetainedReleaseId = active.releaseId;
|
|
117
183
|
}
|
|
118
184
|
}
|
|
119
185
|
// Concurrency: an installation being replaced is not a reason to refuse a launch. While
|
|
@@ -125,7 +191,7 @@ async function runBootstrapAttempt(options, retriesRemaining) {
|
|
|
125
191
|
candidate = await materializeRelease(options.packageRoot, paths.dataDir);
|
|
126
192
|
}
|
|
127
193
|
catch (error) {
|
|
128
|
-
const fallback = await launchRetainedActive(state, paths, environment, launchSelected);
|
|
194
|
+
const fallback = await launchRetainedActive(state, paths, environment, launchSelected, excludedRetainedReleaseId);
|
|
129
195
|
if (fallback === null)
|
|
130
196
|
throw error;
|
|
131
197
|
return fallback;
|
|
@@ -252,10 +318,10 @@ async function runBootstrapAttempt(options, retriesRemaining) {
|
|
|
252
318
|
* certifying anything new, and reports no selection when there is nothing safe
|
|
253
319
|
* to fall back to.
|
|
254
320
|
*/
|
|
255
|
-
async function launchRetainedActive(state, paths, environment, launch) {
|
|
321
|
+
async function launchRetainedActive(state, paths, environment, launch, excludedReleaseId) {
|
|
256
322
|
const activeId = state.references.active;
|
|
257
323
|
const active = activeId === null ? undefined : state.releases[activeId];
|
|
258
|
-
if (!active || active.approval !== "approved")
|
|
324
|
+
if (!active || active.approval !== "approved" || active.releaseId === excludedReleaseId)
|
|
259
325
|
return null;
|
|
260
326
|
try {
|
|
261
327
|
const retained = await readCertifiedReleaseManifest(active, resolve(paths.dataDir, "releases"));
|
|
@@ -266,6 +332,18 @@ async function launchRetainedActive(state, paths, environment, launch) {
|
|
|
266
332
|
return null;
|
|
267
333
|
}
|
|
268
334
|
}
|
|
335
|
+
async function repairApprovedRelease(packageRoot, active, dataDir) {
|
|
336
|
+
const repaired = await repairMaterializedRelease(packageRoot, active.releaseRoot);
|
|
337
|
+
assertApprovedReleaseMatches(repaired, active);
|
|
338
|
+
await recordParentCertifiedRelease(repaired, dataDir);
|
|
339
|
+
return repaired;
|
|
340
|
+
}
|
|
341
|
+
function assertApprovedReleaseMatches(release, active) {
|
|
342
|
+
if (release.releaseId !== active.releaseId || release.contentDigest !== active.contentDigest
|
|
343
|
+
|| (active.packageVersion !== undefined && release.packageVersion !== active.packageVersion)) {
|
|
344
|
+
throw new Error("completely verified release differs from the approved active record");
|
|
345
|
+
}
|
|
346
|
+
}
|
|
269
347
|
async function readInstalledVersion(packageRoot) {
|
|
270
348
|
const manifest = JSON.parse(await readFile(resolve(packageRoot, "package.json"), "utf8"));
|
|
271
349
|
if (typeof manifest.version !== "string" || manifest.version.length === 0) {
|
|
@@ -327,13 +405,15 @@ export async function startSupervisor(release, environment) {
|
|
|
327
405
|
child.unref();
|
|
328
406
|
return { ...attempt, childOutcome };
|
|
329
407
|
}
|
|
330
|
-
async function launchUi(release, environment, sessionArgs) {
|
|
408
|
+
async function launchUi(release, environment, sessionArgs, residentContext = {}) {
|
|
331
409
|
await markStartupPhase(environment, "bootstrap-selected");
|
|
332
410
|
const entry = await resolveReleaseEntryPoint(release, "bin/guardian.js");
|
|
333
411
|
return await new Promise((resolvePromise, rejectPromise) => {
|
|
334
412
|
let releaseSuperseded = false;
|
|
413
|
+
const releaseEnv = releaseEnvironment(environment, release, readLaunchContext(environment, "profile").launchProfile);
|
|
414
|
+
const launchEnvironment = Object.keys(residentContext).length === 0 ? releaseEnv : withLaunchContext(releaseEnv, { ...readLaunchContext(releaseEnv), ...residentContext }, process.platform, launchContractTarget(release));
|
|
335
415
|
const child = spawn(process.execPath, [entry, ...sessionArgs], {
|
|
336
|
-
env:
|
|
416
|
+
env: launchEnvironment,
|
|
337
417
|
stdio: ["inherit", "inherit", "inherit", "ipc"],
|
|
338
418
|
windowsHide: false,
|
|
339
419
|
});
|
|
@@ -357,12 +437,15 @@ async function launchUi(release, environment, sessionArgs) {
|
|
|
357
437
|
* version instead of failing while an installation is being replaced.
|
|
358
438
|
*/
|
|
359
439
|
export function releaseEnvironment(environment, release, profile) {
|
|
440
|
+
const context = readLaunchContext(environment);
|
|
360
441
|
return withLaunchContext(environment, {
|
|
361
442
|
releaseId: release.releaseId,
|
|
362
443
|
releaseLayers: (release.dependencyLayers ?? []).map(layer => layer.layerId).join(","),
|
|
363
444
|
releaseRoot: release.releaseRoot,
|
|
364
445
|
releaseDigest: release.contentDigest,
|
|
365
446
|
...(profile === undefined ? {} : { launchProfile: profile }),
|
|
447
|
+
...(context.launchMode === undefined ? {} : { launchMode: context.launchMode }),
|
|
448
|
+
...(context.updateVersion === undefined ? {} : { updateVersion: context.updateVersion }),
|
|
366
449
|
}, process.platform, launchContractTarget(release));
|
|
367
450
|
}
|
|
368
451
|
export async function waitForVerifiedEndpoint(path, release, timeoutMs, startup) {
|
|
@@ -19,7 +19,7 @@ export interface ReleaseReferences {
|
|
|
19
19
|
readonly rollback: string | null;
|
|
20
20
|
readonly retention: readonly string[];
|
|
21
21
|
}
|
|
22
|
-
export type ExternalReleaseHoldAuthority = "agent" | "migration";
|
|
22
|
+
export type ExternalReleaseHoldAuthority = "agent" | "migration" | "resident";
|
|
23
23
|
/** A current hold supplied by an authority that must participate in every reconciliation. */
|
|
24
24
|
export interface ExternalReleaseHold {
|
|
25
25
|
readonly authority: ExternalReleaseHoldAuthority;
|
|
@@ -12,7 +12,7 @@ const RELEASE_ID_PATTERN = /^[0-9A-Za-z.+_-]+-[a-f0-9]{20}$/;
|
|
|
12
12
|
export function planProtectedReleases(state, inputs = {}) {
|
|
13
13
|
const holds = inputs.externalHolds ?? [];
|
|
14
14
|
for (const hold of holds) {
|
|
15
|
-
if (hold.authority !== "agent" && hold.authority !== "migration")
|
|
15
|
+
if (hold.authority !== "agent" && hold.authority !== "migration" && hold.authority !== "resident")
|
|
16
16
|
throw new Error(`unknown release hold authority: ${String(hold.authority)}`);
|
|
17
17
|
if (!state.releases[hold.releaseId] && !state.cleanup.pending[hold.releaseId]) {
|
|
18
18
|
throw new Error(`external ${hold.authority} hold names unknown release ${hold.releaseId}`);
|
|
@@ -402,9 +402,12 @@ async function acquireLock(path) {
|
|
|
402
402
|
return lock;
|
|
403
403
|
}
|
|
404
404
|
catch (error) {
|
|
405
|
-
|
|
405
|
+
const code = error instanceof Error && "code" in error ? error.code : undefined;
|
|
406
|
+
// Platform: Windows reports a lock file another holder is still deleting as EPERM or EACCES.
|
|
407
|
+
const releasing = process.platform === "win32" && (code === "EPERM" || code === "EACCES");
|
|
408
|
+
if (code !== "EEXIST" && !releasing)
|
|
406
409
|
throw error;
|
|
407
|
-
if (await reclaimAbandonedLock(path))
|
|
410
|
+
if (code === "EEXIST" && await reclaimAbandonedLock(path))
|
|
408
411
|
continue;
|
|
409
412
|
if (Date.now() >= deadline)
|
|
410
413
|
throw error;
|