@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
|
@@ -5,8 +5,9 @@ import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
|
5
5
|
import crossSpawn from "cross-spawn";
|
|
6
6
|
import { valid as validSemver } from "semver";
|
|
7
7
|
import { PRODUCT_IDENTITY, PRODUCT_TEXT } from "../../product-identity.js";
|
|
8
|
+
import { earlyAccentPalette, earlyTerminalAppearance, earlyTerminalColorMode, resolveEarlyAccentColor } from "./early-accent.js";
|
|
8
9
|
import { SHARED_PROGRESS_ACCENT_ANSI } from "./progress-palette.generated.js";
|
|
9
|
-
import { isNewerRelease, releaseChannelOf } from "./latest-release.js";
|
|
10
|
+
import { createRegistryFetcher, invalidateReleaseCheckCache, isNewerRelease, queryPublishedVersions, releaseChannelOf, } from "./latest-release.js";
|
|
10
11
|
import { certifyMaterializedRelease, ensureSupervisor, waitForProcessExit, } from "./bootstrap.js";
|
|
11
12
|
import { probeOwnership, readEndpointMetadata, removeEndpointArtifacts } from "./endpoints.js";
|
|
12
13
|
import { resolveCohortEndpoint, resolveProductPaths } from "../lifecycle/index.js";
|
|
@@ -17,6 +18,7 @@ import { materializeRelease, readMaterializedRelease } from "./release-store.js"
|
|
|
17
18
|
import { scheduleReleaseCleanup } from "./release-gc.js";
|
|
18
19
|
import { UPDATE_ACTIVATION_CONTRACT, activateInstalledRelease, delegateActivation, readActivationContracts, } from "./update-activation.js";
|
|
19
20
|
import { UpdateTransactionStore } from "./update-transaction.js";
|
|
21
|
+
import { acquireUpdateExecutionLease, reclaimDeadLease } from "./update-execution-lease.js";
|
|
20
22
|
import { npmPrefixForGlobalRoot, removeUpdateRecoveryCapsule, resolveNpmCli, runProtectedPackageReplacement, updateLauncherPaths, updateNpmInstallArguments, } from "./update-recovery.js";
|
|
21
23
|
export const PRODUCT_PACKAGE = PRODUCT_TEXT.packageName;
|
|
22
24
|
const UPDATE_DIST_TAGS = { stable: "latest", next: "next" };
|
|
@@ -34,6 +36,9 @@ const defaultFileSystem = {
|
|
|
34
36
|
* The update therefore keeps checking for this long before it calls the package locked.
|
|
35
37
|
*/
|
|
36
38
|
export const PACKAGE_UNLOCK_PATIENCE_MS = 15_000;
|
|
39
|
+
export const UPDATE_ALREADY_RUNNING_EXIT_CODE = 75;
|
|
40
|
+
/** A named preview reads the registry's whole package document, which is larger than a dist-tag lookup. */
|
|
41
|
+
const PREVIEW_LOOKUP_TIMEOUT_MS = 30_000;
|
|
37
42
|
const PACKAGE_UNLOCK_INITIAL_DELAY_MS = 100;
|
|
38
43
|
const PACKAGE_UNLOCK_MAX_DELAY_MS = 1_000;
|
|
39
44
|
// Platform: Windows reports a held directory as EPERM or EBUSY; EACCES and ENOTEMPTY are the other
|
|
@@ -85,6 +90,21 @@ export function createNpmProcessRunner(platform = process.platform) {
|
|
|
85
90
|
* its own endpoint. A cohort running from the mutable installation is the one exception,
|
|
86
91
|
* because that installation is exactly what is about to be replaced under it.
|
|
87
92
|
*/
|
|
93
|
+
async function verifyAutomaticUpdateSafety(paths, stateStore, environment) {
|
|
94
|
+
const state = await stateStore.read();
|
|
95
|
+
const owner = await readActiveEndpoint(paths, state.references.active, environment);
|
|
96
|
+
if (!owner)
|
|
97
|
+
return;
|
|
98
|
+
const ownership = await probeOwnership(owner.metadata);
|
|
99
|
+
if (ownership === "dead")
|
|
100
|
+
return;
|
|
101
|
+
if (ownership !== "live-verified") {
|
|
102
|
+
throw new UpdateAutomaticDeferred(PRODUCT_TEXT.diagnostic(`automatic update deferred because supervisor ownership is ${ownership}`));
|
|
103
|
+
}
|
|
104
|
+
if (!await canonicalImmutableRoot(paths.dataDir, owner.metadata.releaseRoot)) {
|
|
105
|
+
throw new UpdateAutomaticDeferred(PRODUCT_TEXT.diagnostic("automatic update deferred because the running session is not using a retained immutable release; run the update command manually"));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
88
108
|
export function planUpdateOwnership(ownership, runsFromRetainedRelease) {
|
|
89
109
|
if (ownership === "dead")
|
|
90
110
|
return "clean-dead-record";
|
|
@@ -111,13 +131,13 @@ export function createUpdateLifecycleCoordinator(environment = process.env, file
|
|
|
111
131
|
const stateStore = new CohortStateStore(paths.dataDir);
|
|
112
132
|
return {
|
|
113
133
|
async targetIsActive(targetVersion) {
|
|
114
|
-
const state = await stateStore.read();
|
|
115
|
-
const activeId = state.references.active;
|
|
134
|
+
const state = await stateStore.read(), activeId = state.references.active;
|
|
116
135
|
if (!activeId || state.releases[activeId]?.packageVersion !== targetVersion)
|
|
117
136
|
return false;
|
|
118
137
|
const endpoint = await readActiveEndpoint(paths, activeId, environment);
|
|
119
138
|
return endpoint?.metadata.releaseId === activeId && await probeOwnership(endpoint.metadata) === "live-verified";
|
|
120
139
|
},
|
|
140
|
+
async verifyAutomaticSafety() { await verifyAutomaticUpdateSafety(paths, stateStore, environment); },
|
|
121
141
|
async shutdownVerifiedOwners(targetVersion) {
|
|
122
142
|
const state = await stateStore.read();
|
|
123
143
|
const activeId = state.references.active;
|
|
@@ -233,16 +253,19 @@ const ACTIVATION_PROGRESS = {
|
|
|
233
253
|
"active-reference-committed": { at: 96, creepTo: 99 },
|
|
234
254
|
};
|
|
235
255
|
/** Renders the terminal-only update meter; the visual preview shares this exact frame. */
|
|
236
|
-
export function renderUpdateProgressBar(percent) {
|
|
256
|
+
export function renderUpdateProgressBar(percent, accent = SHARED_PROGRESS_ACCENT_ANSI) {
|
|
237
257
|
const bounded = Math.min(100, Math.max(0, Math.round(percent)));
|
|
238
258
|
const filled = Math.round((bounded / 100) * PROGRESS_BAR_WIDTH);
|
|
239
|
-
// Rationale: the completed run follows the
|
|
240
|
-
//
|
|
259
|
+
// Rationale: the completed run follows the A1 profile accent; the track and
|
|
260
|
+
// percentage retain the update meter's neutral treatment.
|
|
241
261
|
const gray = "\u001b[38;2;128;128;128m";
|
|
242
262
|
const track = "\u001b[38;2;102;102;102m";
|
|
243
|
-
return `${
|
|
263
|
+
return `${accent}${"━".repeat(filled)}${track}${"─".repeat(PROGRESS_BAR_WIDTH - filled)}${gray} ${bounded}%\u001b[39m`;
|
|
264
|
+
}
|
|
265
|
+
function updateProgressAccent(environment) {
|
|
266
|
+
return earlyAccentPalette(resolveEarlyAccentColor(environment), earlyTerminalAppearance(environment), earlyTerminalColorMode(environment)).accent;
|
|
244
267
|
}
|
|
245
|
-
function createUpdateProgress(output, enabled) {
|
|
268
|
+
function createUpdateProgress(output, enabled, accent = SHARED_PROGRESS_ACCENT_ANSI) {
|
|
246
269
|
let visible = false;
|
|
247
270
|
let current = 0;
|
|
248
271
|
let shown = -1;
|
|
@@ -253,7 +276,7 @@ function createUpdateProgress(output, enabled) {
|
|
|
253
276
|
return;
|
|
254
277
|
shown = rounded;
|
|
255
278
|
visible = true;
|
|
256
|
-
output.stdout(`\r${renderUpdateProgressBar(rounded)}`);
|
|
279
|
+
output.stdout(`\r${renderUpdateProgressBar(rounded, accent)}`);
|
|
257
280
|
};
|
|
258
281
|
const stopCreep = () => {
|
|
259
282
|
if (timer !== null) {
|
|
@@ -320,35 +343,28 @@ async function resolveChannelHead(runner, distTag, output) {
|
|
|
320
343
|
/**
|
|
321
344
|
* Resolve a preview the caller named.
|
|
322
345
|
*
|
|
323
|
-
* A
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
* installed package's base version.
|
|
346
|
+
* A decimal names the pull request a published preview records in its manifest, or the trailing
|
|
347
|
+
* number of a preview published as `<version>-dev.<pull-request>` before pull requests were
|
|
348
|
+
* recorded; a full version is accepted too. The registry's published manifests remain
|
|
349
|
+
* authoritative: nothing is constructed from the installed package's base version.
|
|
327
350
|
*/
|
|
328
|
-
async function resolveRequestedPreview(
|
|
329
|
-
const
|
|
330
|
-
if (
|
|
331
|
-
|
|
332
|
-
let published;
|
|
333
|
-
try {
|
|
334
|
-
published = JSON.parse(lookup.result.stdout.trim() || "[]");
|
|
335
|
-
}
|
|
336
|
-
catch {
|
|
337
|
-
output.stderr(`${PRODUCT_TEXT.diagnostic(`received a malformed version list from npm: ${JSON.stringify(lookup.result.stdout.trim())}.`)}\n`);
|
|
351
|
+
async function resolveRequestedPreview(fetcher, registry, requested, output) {
|
|
352
|
+
const published = await queryPublishedVersions(fetcher, registry);
|
|
353
|
+
if (published.error !== null) {
|
|
354
|
+
output.stderr(`${PRODUCT_TEXT.diagnostic(`could not list the published versions: ${published.error}.`)}\n`);
|
|
338
355
|
return { version: null, exitCode: 1 };
|
|
339
356
|
}
|
|
340
|
-
const
|
|
341
|
-
const exact = versions.find(version => version === requested);
|
|
357
|
+
const exact = published.versions.find(entry => entry.version === requested);
|
|
342
358
|
if (exact !== undefined) {
|
|
343
359
|
// Rationale: naming a release here would install it through the preview path, which is a
|
|
344
360
|
// different command with a different meaning.
|
|
345
|
-
if (!exact.includes("-dev.")) {
|
|
346
|
-
output.stderr(`${PRODUCT_TEXT.diagnostic(`${exact} is a release, not a preview; run ${PRODUCT_TEXT.commandName} update to move to the current release.`)}\n`);
|
|
361
|
+
if (!exact.version.includes("-dev.")) {
|
|
362
|
+
output.stderr(`${PRODUCT_TEXT.diagnostic(`${exact.version} is a release, not a preview; run ${PRODUCT_TEXT.commandName} update to move to the current release.`)}\n`);
|
|
347
363
|
return { version: null, exitCode: 1 };
|
|
348
364
|
}
|
|
349
|
-
return { version: exact, exitCode: 0 };
|
|
365
|
+
return { version: exact.version, exitCode: 0 };
|
|
350
366
|
}
|
|
351
|
-
const matches = versions
|
|
367
|
+
const matches = previewsNumbered(published.versions, requested);
|
|
352
368
|
if (matches.length === 1)
|
|
353
369
|
return { version: matches[0], exitCode: 0 };
|
|
354
370
|
if (matches.length > 1) {
|
|
@@ -358,6 +374,13 @@ async function resolveRequestedPreview(runner, requested, output) {
|
|
|
358
374
|
output.stderr(`${PRODUCT_TEXT.diagnostic(`published no preview for ${requested}.`)}\n`);
|
|
359
375
|
return { version: null, exitCode: 1 };
|
|
360
376
|
}
|
|
377
|
+
/** The published versions a preview number names: by recorded pull request, or by trailing identifier. */
|
|
378
|
+
function previewsNumbered(versions, requested) {
|
|
379
|
+
const number = Number(requested);
|
|
380
|
+
return versions
|
|
381
|
+
.filter(entry => entry.pullRequest === number || entry.version.endsWith(`-dev.${requested}`))
|
|
382
|
+
.map(entry => entry.version);
|
|
383
|
+
}
|
|
361
384
|
async function resolveManagedNpmInstallation(requestedPackageRoot, fileSystem, runner, output) {
|
|
362
385
|
const rootLookup = await runNpm(runner, ["root", "--global"], true, output, "resolve npm's global package root");
|
|
363
386
|
if (rootLookup.result === null)
|
|
@@ -455,9 +478,72 @@ async function launchersOwnPackage(globalRoot, fileSystem) {
|
|
|
455
478
|
return false;
|
|
456
479
|
}
|
|
457
480
|
}
|
|
481
|
+
async function resolveSelfUpdateTarget(input) {
|
|
482
|
+
if (input.exactTarget !== undefined && input.exactTarget.length > 0) {
|
|
483
|
+
return resolveExactAutomaticTarget(input.exactTarget, input.channel, input.output);
|
|
484
|
+
}
|
|
485
|
+
return input.requested === undefined || input.requested.length === 0
|
|
486
|
+
? await resolveChannelHead(input.runner, input.distTag, input.output)
|
|
487
|
+
: await resolveRequestedPreview(input.fetcher ?? createRegistryFetcher(PREVIEW_LOOKUP_TIMEOUT_MS), input.registry?.trim() || undefined, input.requested, input.output);
|
|
488
|
+
}
|
|
489
|
+
function resolveExactAutomaticTarget(target, channel, output) {
|
|
490
|
+
const version = validSemver(target);
|
|
491
|
+
const expected = channel === "stable" ? "stable" : "development";
|
|
492
|
+
if (version === null || releaseChannelOf(version) !== expected) {
|
|
493
|
+
output.stderr(`${PRODUCT_TEXT.diagnostic(`refused invalid automatic ${expected} update target ${JSON.stringify(target)}`)}\n`);
|
|
494
|
+
return { version: null, exitCode: 1 };
|
|
495
|
+
}
|
|
496
|
+
return { version, exitCode: 0 };
|
|
497
|
+
}
|
|
458
498
|
function reportUnmanagedInstallation(output, packageRoot, activeGlobalRoot) {
|
|
459
499
|
output.stderr(`${PRODUCT_TEXT.diagnostic(`refused to update automatically because ${packageRoot} could not be verified as an npm-managed ${PRODUCT_PACKAGE} installation; npm's active global package root is ${activeGlobalRoot}. Run npm install --global ${PRODUCT_PACKAGE} to install it manually.`)}\n`);
|
|
460
500
|
}
|
|
501
|
+
async function withUpdateExecutionLease(input, options, output, operation) {
|
|
502
|
+
let lease = await acquireUpdateExecutionLease(input);
|
|
503
|
+
if (lease.status === "interrupted") {
|
|
504
|
+
// Rationale: the owner that targeted another version is gone. Its durable transaction is rolled
|
|
505
|
+
// back to the cohort that ran before it, so this request proceeds as an ordinary update of its
|
|
506
|
+
// own target instead of reporting a dead attempt as in progress.
|
|
507
|
+
const interrupted = lease.owner.targetVersion;
|
|
508
|
+
const rollback = await rollbackPriorCohort(input.dataDir, options.environment ?? process.env, lease.transaction.priorActiveReleaseId)
|
|
509
|
+
.catch(error => `rollback failed: ${errorMessage(error)}`);
|
|
510
|
+
const store = new UpdateTransactionStore(input.dataDir);
|
|
511
|
+
await store.finish("rolled-back", `interrupted ${interrupted} update settled by ${input.targetVersion}; ${rollback}`);
|
|
512
|
+
await store.clearCompleted().catch(() => undefined);
|
|
513
|
+
await reclaimDeadLease(input.dataDir, lease.owner);
|
|
514
|
+
output.stdout(`${PRODUCT_TEXT.commandName} rolled back the interrupted ${interrupted} update: ${rollback}\n`);
|
|
515
|
+
lease = await acquireUpdateExecutionLease(input);
|
|
516
|
+
}
|
|
517
|
+
if (lease.status !== "acquired") {
|
|
518
|
+
options.onLeaseBusy?.(lease.owner);
|
|
519
|
+
if ((options.mode ?? "manual") === "manual") {
|
|
520
|
+
output.stderr(`${PRODUCT_TEXT.diagnostic(`update already in progress for ${lease.owner.targetVersion}`)}\n`);
|
|
521
|
+
}
|
|
522
|
+
return UPDATE_ALREADY_RUNNING_EXIT_CODE;
|
|
523
|
+
}
|
|
524
|
+
try {
|
|
525
|
+
options.onLeaseAcquired?.(lease.owner);
|
|
526
|
+
return await operation();
|
|
527
|
+
}
|
|
528
|
+
finally {
|
|
529
|
+
await lease.release();
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
async function readRunningPackageVersion(packageRoot, fileSystem, output) {
|
|
533
|
+
try {
|
|
534
|
+
const packageJson = JSON.parse(await fileSystem.readFile(resolve(packageRoot, "package.json")));
|
|
535
|
+
const version = typeof packageJson.version === "string" ? validSemver(packageJson.version) : null;
|
|
536
|
+
if (packageJson.name !== PRODUCT_PACKAGE)
|
|
537
|
+
throw new Error(`package.json does not identify ${PRODUCT_PACKAGE}`);
|
|
538
|
+
if (version === null)
|
|
539
|
+
throw new Error("package.json does not contain a valid semantic version");
|
|
540
|
+
return version;
|
|
541
|
+
}
|
|
542
|
+
catch (error) {
|
|
543
|
+
output.stderr(`${PRODUCT_TEXT.diagnostic(`could not read its running package version: ${errorMessage(error)}`)}\n`);
|
|
544
|
+
return null;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
461
547
|
export async function runSelfUpdate(options) {
|
|
462
548
|
const fileSystem = options.fileSystem ?? defaultFileSystem;
|
|
463
549
|
const output = options.output ?? defaultOutput;
|
|
@@ -474,24 +560,15 @@ export async function runSelfUpdate(options) {
|
|
|
474
560
|
options.onPhaseTiming?.({ phase, durationMs: Math.max(0, now() - startedAt) });
|
|
475
561
|
}
|
|
476
562
|
};
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
const packageJson = JSON.parse(await measure("package-version", async () => await fileSystem.readFile(resolve(options.packageRoot, "package.json"))));
|
|
480
|
-
const parsedVersion = typeof packageJson.version === "string" ? validSemver(packageJson.version) : null;
|
|
481
|
-
if (packageJson.name !== PRODUCT_PACKAGE)
|
|
482
|
-
throw new Error(`package.json does not identify ${PRODUCT_PACKAGE}`);
|
|
483
|
-
if (parsedVersion === null)
|
|
484
|
-
throw new Error("package.json does not contain a valid semantic version");
|
|
485
|
-
runningVersion = parsedVersion;
|
|
486
|
-
}
|
|
487
|
-
catch (error) {
|
|
488
|
-
output.stderr(`${PRODUCT_TEXT.diagnostic(`could not read its running package version: ${errorMessage(error)}`)}\n`);
|
|
563
|
+
const runningVersion = await measure("package-version", async () => await readRunningPackageVersion(options.packageRoot, fileSystem, output));
|
|
564
|
+
if (runningVersion === null)
|
|
489
565
|
return 1;
|
|
490
|
-
}
|
|
491
566
|
const requested = options.target?.trim();
|
|
492
|
-
const
|
|
493
|
-
|
|
494
|
-
|
|
567
|
+
const exactTarget = options.resolvedTarget?.trim();
|
|
568
|
+
const environment = options.environment ?? process.env;
|
|
569
|
+
const resolved = await measure("target-resolution", async () => await resolveSelfUpdateTarget({
|
|
570
|
+
runner, output, channel, distTag, requested, exactTarget, fetcher: options.fetcher, registry: environment.npm_config_registry,
|
|
571
|
+
}));
|
|
495
572
|
if (resolved.version === null)
|
|
496
573
|
return resolved.exitCode;
|
|
497
574
|
const targetVersion = resolved.version;
|
|
@@ -506,178 +583,184 @@ export async function runSelfUpdate(options) {
|
|
|
506
583
|
// Rationale: no full stop after a version: it already ends in a dot-separated identifier,
|
|
507
584
|
// and a trailing one reads as part of the version rather than as punctuation.
|
|
508
585
|
output.stdout(`${PRODUCT_TEXT.commandName} update: ${runningVersion} → ${targetVersion}\n`);
|
|
509
|
-
const progress = createUpdateProgress(output, options.progress ?? (options.output === undefined && process.stdout.isTTY === true));
|
|
586
|
+
const progress = createUpdateProgress(output, options.progress ?? (options.output === undefined && process.stdout.isTTY === true), updateProgressAccent(environment));
|
|
510
587
|
const managed = await measure("global-root", async () => await resolveManagedNpmInstallation(options.packageRoot, fileSystem, runner, output));
|
|
511
588
|
if (managed.installation === null)
|
|
512
589
|
return managed.exitCode;
|
|
513
590
|
const { packageRoot, globalRoot, npmCliRoot } = managed.installation;
|
|
514
|
-
const environment = options.environment ?? process.env;
|
|
515
591
|
const paths = resolveProductPaths(environment);
|
|
516
592
|
const lifecycle = options.lifecycle ?? createUpdateLifecycleCoordinator(environment, fileSystem, output);
|
|
517
593
|
const transactionStore = options.transactionStore ?? new UpdateTransactionStore(paths.dataDir);
|
|
594
|
+
const mode = options.mode ?? "manual";
|
|
518
595
|
const maintenance = options.maintenance ?? (options.lifecycle
|
|
519
596
|
? async () => { }
|
|
520
597
|
: async () => await scheduleReleaseCleanup(paths.dataDir, paths));
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
if (preflightRequired) {
|
|
533
|
-
try {
|
|
534
|
-
npmCli = await (options.npmCliResolver ?? resolveNpmCli)(npmCliRoot, environment);
|
|
598
|
+
return await withUpdateExecutionLease({ dataDir: paths.dataDir, packageRoot, channel, targetVersion, mode }, options, output, async () => {
|
|
599
|
+
let transaction = await transactionStore.read();
|
|
600
|
+
let npmCli;
|
|
601
|
+
try {
|
|
602
|
+
if (mode === "automatic")
|
|
603
|
+
await lifecycle.verifyAutomaticSafety?.();
|
|
604
|
+
if ((!transaction || transaction.status === "completed") && await lifecycle.targetIsActive(targetVersion)) {
|
|
605
|
+
await maintenance();
|
|
606
|
+
await transactionStore.clearCompleted();
|
|
607
|
+
output.stdout(`${PRODUCT_TEXT.commandName} is up to date — no update needed.\n`);
|
|
608
|
+
return 0;
|
|
535
609
|
}
|
|
536
|
-
|
|
537
|
-
|
|
610
|
+
const preflightRequired = options.npmCliResolver !== undefined
|
|
611
|
+
|| options.packageReplacement === undefined && options.runner === undefined;
|
|
612
|
+
if (preflightRequired) {
|
|
613
|
+
try {
|
|
614
|
+
npmCli = await (options.npmCliResolver ?? resolveNpmCli)(npmCliRoot, environment);
|
|
615
|
+
}
|
|
616
|
+
catch (error) {
|
|
617
|
+
throw new UpdatePreflightFailure(errorMessage(error));
|
|
618
|
+
}
|
|
538
619
|
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
priorActiveReleaseId,
|
|
560
|
-
});
|
|
561
|
-
if (phaseBefore(transaction.phase, "ownership-released")) {
|
|
562
|
-
await measure("ownership-release", async () => {
|
|
563
|
-
await lifecycle.shutdownVerifiedOwners(targetVersion);
|
|
564
|
-
await lifecycle.verifyPackageUnlocked(packageRoot);
|
|
620
|
+
// Rationale: the bar first appears only after every non-mutating replacement prerequisite passes.
|
|
621
|
+
progress.set(3, 15);
|
|
622
|
+
const cohortStore = new CohortStateStore(paths.dataDir);
|
|
623
|
+
let cohortState = await cohortStore.read();
|
|
624
|
+
let priorActiveReleaseId = cohortState.references.active;
|
|
625
|
+
if (options.runner === undefined && (priorActiveReleaseId === null || cohortState.releases[priorActiveReleaseId]?.approval !== "approved")) {
|
|
626
|
+
// Invariant: protected replacement needs an immutable launch authority that npm cannot rename.
|
|
627
|
+
const recoveryRelease = await materializeRelease(packageRoot, paths.dataDir);
|
|
628
|
+
await cohortStore.recordCandidate(recoveryRelease);
|
|
629
|
+
const diagnostics = await certifyMaterializedRelease(recoveryRelease, paths.dataDir);
|
|
630
|
+
await cohortStore.approve(recoveryRelease.releaseId, diagnostics);
|
|
631
|
+
await cohortStore.activate(recoveryRelease.releaseId);
|
|
632
|
+
cohortState = await cohortStore.read();
|
|
633
|
+
priorActiveReleaseId = recoveryRelease.releaseId;
|
|
634
|
+
}
|
|
635
|
+
transaction = await transactionStore.begin({
|
|
636
|
+
channel,
|
|
637
|
+
targetVersion,
|
|
638
|
+
packageRoot,
|
|
639
|
+
priorActiveReleaseId,
|
|
565
640
|
});
|
|
566
|
-
transaction
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
641
|
+
if (phaseBefore(transaction.phase, "ownership-released")) {
|
|
642
|
+
await measure("ownership-release", async () => {
|
|
643
|
+
await lifecycle.shutdownVerifiedOwners(targetVersion);
|
|
644
|
+
await lifecycle.verifyPackageUnlocked(packageRoot);
|
|
645
|
+
});
|
|
646
|
+
transaction = await transactionStore.advance("ownership-released");
|
|
647
|
+
}
|
|
648
|
+
progress.set(15, 70);
|
|
649
|
+
if (phaseBefore(transaction.phase, "package-installed")) {
|
|
650
|
+
if (options.packageReplacement || options.runner === undefined) {
|
|
651
|
+
const priorReleaseId = transaction.priorActiveReleaseId ?? priorActiveReleaseId;
|
|
652
|
+
const recordedPrior = priorReleaseId === null ? undefined : cohortState.releases[priorReleaseId];
|
|
653
|
+
if ((!recordedPrior || recordedPrior.approval !== "approved") && !options.packageReplacement) {
|
|
654
|
+
throw new Error(PRODUCT_TEXT.diagnostic("cannot protect package replacement because no approved prior release is available"));
|
|
655
|
+
}
|
|
656
|
+
const priorRelease = recordedPrior ?? {
|
|
657
|
+
releaseId: priorReleaseId ?? "injected-prior-release",
|
|
658
|
+
releaseRoot: packageRoot,
|
|
659
|
+
contentDigest: "0".repeat(64),
|
|
660
|
+
};
|
|
661
|
+
const replacementTransaction = transaction;
|
|
662
|
+
const replacement = await measure("npm-install", async () => await (options.packageReplacement ?? runProtectedPackageReplacement)({
|
|
663
|
+
dataDir: paths.dataDir,
|
|
664
|
+
globalRoot,
|
|
665
|
+
npmCliRoot,
|
|
666
|
+
...(npmCli === undefined ? {} : { npmCli }),
|
|
667
|
+
packageRoot,
|
|
668
|
+
transaction: replacementTransaction,
|
|
669
|
+
priorRelease,
|
|
670
|
+
output,
|
|
671
|
+
environment,
|
|
672
|
+
onRecoveryState: async (recovery) => {
|
|
673
|
+
if (transactionStore.setRecovery)
|
|
674
|
+
transaction = await transactionStore.setRecovery(recovery) ?? transaction;
|
|
675
|
+
},
|
|
676
|
+
}));
|
|
677
|
+
// Rationale: npm's own text explains a failed replacement and says nothing about a
|
|
678
|
+
// successful one, so it reaches the terminal only when the installation did not happen.
|
|
679
|
+
if (replacement.outcome !== "installed")
|
|
680
|
+
reportChildDiagnostics(output, replacement);
|
|
681
|
+
if (replacement.outcome === "installed")
|
|
682
|
+
transaction = await transactionStore.advance("package-installed");
|
|
683
|
+
if (replacement.cancelled) {
|
|
684
|
+
progress.clear();
|
|
685
|
+
output.stderr(`${PRODUCT_TEXT.diagnostic("update cancelled safely; the launcher is available and the transaction can be resumed.")}\n`);
|
|
686
|
+
return 130;
|
|
687
|
+
}
|
|
688
|
+
if (replacement.outcome !== "installed") {
|
|
689
|
+
throw new UpdateFailure(unsuccessfulCode(replacement.npmExitCode), `npm exited with status ${formatExitCode(replacement.npmExitCode)}`);
|
|
690
|
+
}
|
|
575
691
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
globalRoot,
|
|
585
|
-
npmCliRoot,
|
|
586
|
-
...(npmCli === undefined ? {} : { npmCli }),
|
|
587
|
-
packageRoot,
|
|
588
|
-
transaction: replacementTransaction,
|
|
589
|
-
priorRelease,
|
|
590
|
-
output,
|
|
591
|
-
environment,
|
|
592
|
-
onRecoveryState: async (recovery) => {
|
|
593
|
-
if (transactionStore.setRecovery)
|
|
594
|
-
transaction = await transactionStore.setRecovery(recovery) ?? transaction;
|
|
595
|
-
},
|
|
596
|
-
}));
|
|
597
|
-
// Rationale: npm's own text explains a failed replacement and says nothing about a
|
|
598
|
-
// successful one, so it reaches the terminal only when the installation did not happen.
|
|
599
|
-
if (replacement.outcome !== "installed")
|
|
600
|
-
reportChildDiagnostics(output, replacement);
|
|
601
|
-
if (replacement.outcome === "installed")
|
|
692
|
+
else {
|
|
693
|
+
const installation = await measure("npm-install", async () => await runNpm(runner, updateNpmInstallArguments(globalRoot, targetVersion), true, output, "start the global npm installation", false));
|
|
694
|
+
if (installation.result === null)
|
|
695
|
+
throw new UpdateFailure(installation.exitCode, "npm process failed");
|
|
696
|
+
if (installation.result.code !== 0) {
|
|
697
|
+
reportChildDiagnostics(output, installation.result);
|
|
698
|
+
throw new UpdateFailure(unsuccessfulCode(installation.result.code), `npm exited with status ${formatExitCode(installation.result.code)}`);
|
|
699
|
+
}
|
|
602
700
|
transaction = await transactionStore.advance("package-installed");
|
|
603
|
-
if (replacement.cancelled) {
|
|
604
|
-
progress.clear();
|
|
605
|
-
output.stderr(`${PRODUCT_TEXT.diagnostic("update cancelled safely; the launcher is available and the transaction can be resumed.")}\n`);
|
|
606
|
-
return 130;
|
|
607
|
-
}
|
|
608
|
-
if (replacement.outcome !== "installed") {
|
|
609
|
-
throw new UpdateFailure(unsuccessfulCode(replacement.npmExitCode), `npm exited with status ${formatExitCode(replacement.npmExitCode)}`);
|
|
610
701
|
}
|
|
611
702
|
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
703
|
+
progress.set(70, 75);
|
|
704
|
+
// Concurrency: ownership can be reacquired after an interrupted installation (for
|
|
705
|
+
// example, if bare A1 is launched before the update is resumed). Recheck
|
|
706
|
+
// immediately before activation so recovery cannot start a second cohort.
|
|
707
|
+
await measure("ownership-release", async () => { await lifecycle.shutdownVerifiedOwners(targetVersion); });
|
|
708
|
+
progress.set(75, MATERIALIZE_PROGRESS.from);
|
|
709
|
+
let activationPhaseStartedAt = now();
|
|
710
|
+
await lifecycle.activateInstalled(packageRoot, targetVersion, async (phase) => {
|
|
711
|
+
options.onPhaseTiming?.({ phase, durationMs: Math.max(0, now() - activationPhaseStartedAt) });
|
|
712
|
+
transaction = await transactionStore.advance(phase);
|
|
713
|
+
progress.set(ACTIVATION_PROGRESS[phase].at, ACTIVATION_PROGRESS[phase].creepTo);
|
|
714
|
+
activationPhaseStartedAt = now();
|
|
715
|
+
}, ({ completed, total }) => {
|
|
716
|
+
const span = MATERIALIZE_PROGRESS.to - MATERIALIZE_PROGRESS.from;
|
|
717
|
+
const done = total > 0 ? Math.min(1, completed / total) : 0;
|
|
718
|
+
progress.set(MATERIALIZE_PROGRESS.from + span * done);
|
|
719
|
+
}, state => {
|
|
720
|
+
if (state === "started") {
|
|
721
|
+
activationPhaseStartedAt = now();
|
|
722
|
+
progress.set(98, 99);
|
|
619
723
|
}
|
|
620
|
-
|
|
621
|
-
|
|
724
|
+
else {
|
|
725
|
+
options.onPhaseTiming?.({ phase: "warmup", durationMs: Math.max(0, now() - activationPhaseStartedAt) });
|
|
726
|
+
activationPhaseStartedAt = now();
|
|
727
|
+
progress.set(99);
|
|
728
|
+
}
|
|
729
|
+
});
|
|
730
|
+
options.onPhaseTiming?.({ phase: "supervisor-verified", durationMs: Math.max(0, now() - activationPhaseStartedAt) });
|
|
731
|
+
const transactionStartedAt = now();
|
|
732
|
+
await transactionStore.advance("supervisor-verified");
|
|
733
|
+
if (transaction.recovery?.capsulePath)
|
|
734
|
+
await removeUpdateRecoveryCapsule(paths.dataDir, transaction.transactionId);
|
|
735
|
+
// Invariant: successful output follows the durable cleanup disposition. Slow recursive
|
|
736
|
+
// removal belongs to the detached worker started by this maintenance coordinator.
|
|
737
|
+
await maintenance();
|
|
738
|
+
// Concurrency: this is the launch cutover. No failure-prone update work follows success.
|
|
739
|
+
await transactionStore.finish("completed");
|
|
740
|
+
await Promise.all([transactionStore.clearCompleted(), invalidateReleaseCheckCache(paths.configDir)]).catch(() => undefined);
|
|
741
|
+
options.onPhaseTiming?.({ phase: "transaction-complete", durationMs: Math.max(0, now() - transactionStartedAt) });
|
|
742
|
+
progress.finish();
|
|
743
|
+
output.stdout(`${PRODUCT_TEXT.commandName} updated successfully to ${targetVersion}\n`);
|
|
744
|
+
return 0;
|
|
622
745
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
options.onPhaseTiming?.({ phase, durationMs: Math.max(0, now() - activationPhaseStartedAt) });
|
|
632
|
-
transaction = await transactionStore.advance(phase);
|
|
633
|
-
progress.set(ACTIVATION_PROGRESS[phase].at, ACTIVATION_PROGRESS[phase].creepTo);
|
|
634
|
-
activationPhaseStartedAt = now();
|
|
635
|
-
}, ({ completed, total }) => {
|
|
636
|
-
const span = MATERIALIZE_PROGRESS.to - MATERIALIZE_PROGRESS.from;
|
|
637
|
-
const done = total > 0 ? Math.min(1, completed / total) : 0;
|
|
638
|
-
progress.set(MATERIALIZE_PROGRESS.from + span * done);
|
|
639
|
-
}, state => {
|
|
640
|
-
if (state === "started") {
|
|
641
|
-
activationPhaseStartedAt = now();
|
|
642
|
-
progress.set(98, 99);
|
|
643
|
-
}
|
|
644
|
-
else {
|
|
645
|
-
options.onPhaseTiming?.({ phase: "warmup", durationMs: Math.max(0, now() - activationPhaseStartedAt) });
|
|
646
|
-
activationPhaseStartedAt = now();
|
|
647
|
-
progress.set(99);
|
|
746
|
+
catch (error) {
|
|
747
|
+
progress.clear();
|
|
748
|
+
const message = errorMessage(error);
|
|
749
|
+
if (error instanceof UpdateAutomaticDeferred)
|
|
750
|
+
return 1;
|
|
751
|
+
if (error instanceof UpdatePreflightFailure) {
|
|
752
|
+
output.stderr(`${PRODUCT_TEXT.diagnostic(`update could not start safely: ${message}. Nothing was changed. Retry with npm x -y -- ${PRODUCT_PACKAGE}-install`)}\n`);
|
|
753
|
+
return 1;
|
|
648
754
|
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
// removal belongs to the detached worker started by this maintenance coordinator.
|
|
657
|
-
await maintenance();
|
|
658
|
-
// Concurrency: this is the launch cutover. No failure-prone update work follows success.
|
|
659
|
-
await transactionStore.finish("completed");
|
|
660
|
-
await transactionStore.clearCompleted().catch(() => undefined);
|
|
661
|
-
options.onPhaseTiming?.({ phase: "transaction-complete", durationMs: Math.max(0, now() - transactionStartedAt) });
|
|
662
|
-
progress.finish();
|
|
663
|
-
output.stdout(`${PRODUCT_TEXT.commandName} updated successfully to ${targetVersion}\n`);
|
|
664
|
-
return 0;
|
|
665
|
-
}
|
|
666
|
-
catch (error) {
|
|
667
|
-
progress.clear();
|
|
668
|
-
const message = errorMessage(error);
|
|
669
|
-
if (error instanceof UpdatePreflightFailure) {
|
|
670
|
-
output.stderr(`${PRODUCT_TEXT.diagnostic(`update could not start safely: ${message}. Nothing was changed. Retry with npm x -y -- ${PRODUCT_PACKAGE}-install`)}\n`);
|
|
671
|
-
return 1;
|
|
755
|
+
const rollback = options.lifecycle
|
|
756
|
+
? "previous test lifecycle retained"
|
|
757
|
+
: await rollbackPriorCohort(paths.dataDir, environment, transaction?.priorActiveReleaseId ?? null).catch(rollbackError => `rollback failed: ${errorMessage(rollbackError)}`);
|
|
758
|
+
if (transaction)
|
|
759
|
+
await transactionStore.finish(rollback === "rolled back" ? "rolled-back" : "failed", `${message}; ${rollback}`);
|
|
760
|
+
output.stderr(`${PRODUCT_TEXT.diagnostic(`update failed: ${message}. ${rollback}. Diagnostics: ${transactionStore.path}`)}\n`);
|
|
761
|
+
return error instanceof UpdateFailure ? error.exitCode : 1;
|
|
672
762
|
}
|
|
673
|
-
|
|
674
|
-
? "previous test lifecycle retained"
|
|
675
|
-
: await rollbackPriorCohort(paths.dataDir, environment, transaction?.priorActiveReleaseId ?? null).catch(rollbackError => `rollback failed: ${errorMessage(rollbackError)}`);
|
|
676
|
-
if (transaction)
|
|
677
|
-
await transactionStore.finish(rollback === "rolled back" ? "rolled-back" : "failed", `${message}; ${rollback}`);
|
|
678
|
-
output.stderr(`${PRODUCT_TEXT.diagnostic(`update failed: ${message}. ${rollback}. Diagnostics: ${transactionStore.path}`)}\n`);
|
|
679
|
-
return error instanceof UpdateFailure ? error.exitCode : 1;
|
|
680
|
-
}
|
|
763
|
+
});
|
|
681
764
|
}
|
|
682
765
|
export function assertUpdatePerformanceBudget(evidence, maximumPostNpmDurationMs = 30_000) {
|
|
683
766
|
const failures = [];
|
|
@@ -777,6 +860,8 @@ class UpdateFailure extends Error {
|
|
|
777
860
|
}
|
|
778
861
|
class UpdatePreflightFailure extends Error {
|
|
779
862
|
}
|
|
863
|
+
class UpdateAutomaticDeferred extends Error {
|
|
864
|
+
}
|
|
780
865
|
async function canonicalImmutableRoot(dataDir, releaseRoot) {
|
|
781
866
|
try {
|
|
782
867
|
const [store, selected] = await Promise.all([realpath(resolve(dataDir, "releases")), realpath(releaseRoot)]);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TerminalHostCommand } from "./ensure-terminal-host.js";
|
|
2
|
+
export interface BoundedHostCommandResult {
|
|
3
|
+
readonly code: number;
|
|
4
|
+
readonly stdout: string;
|
|
5
|
+
}
|
|
6
|
+
export interface BoundedHostCommandLimits {
|
|
7
|
+
/** Output beyond this many bytes fails the exchange instead of being parsed. */
|
|
8
|
+
readonly maxStdoutBytes: number;
|
|
9
|
+
readonly timeoutMs: number;
|
|
10
|
+
/** Names the exchange in the timeout error. */
|
|
11
|
+
readonly label: string;
|
|
12
|
+
readonly environment?: NodeJS.ProcessEnv;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Runs one terminal-host command whose report is small. An oversized report kills the command and
|
|
16
|
+
* reports a failed exchange; a command that outlives its deadline is killed and rejected.
|
|
17
|
+
*/
|
|
18
|
+
export declare function runBoundedHostCommand(command: TerminalHostCommand, arguments_: readonly string[], limits: BoundedHostCommandLimits): Promise<BoundedHostCommandResult>;
|