@timurproko/a1 0.1.8-dev.472 → 0.1.8-dev.508
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/bin/cli.js +4 -5
- package/bin/guardian.js +5 -1
- package/bin/module-identity.js +53 -98
- package/bin/module-resolver.js +138 -0
- package/bin/pinned-pi-public.js +25 -6
- package/bin/ui.js +7 -2
- package/bin/update-recovery.js +76 -7
- package/bin/warmup.js +3 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/clipboard-diagnostics.d.ts +1 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/clipboard-image.js +1 -1
- package/dist/app/session-shell/helper-pool.d.ts +33 -0
- package/dist/app/session-shell/helper-pool.js +98 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/image-preparation-client.d.ts +1 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/image-preparation-client.js +1 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/image-preparation.js +1 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/image-source.js +1 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/image-worker.js +1 -1
- package/dist/app/session-shell/index.d.ts +7 -0
- package/dist/app/session-shell/index.js +4 -0
- package/dist/app/session-shell/paste-executor.d.ts +18 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/paste-executor.js +50 -29
- package/dist/{integrations/pi/session-ui → app/session-shell}/paste-helper.js +1 -1
- package/dist/app/session-shell/paste-preparation-client.d.ts +31 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/paste-preparation-client.js +19 -8
- package/dist/{integrations/pi/session-ui → app/session-shell}/paste-protocol.d.ts +1 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/paste-protocol.js +1 -1
- package/dist/app/session-shell/paste-text-preparation.d.ts +6 -0
- package/dist/{integrations/pi/session-ui/paste-text-preparation.d.ts → app/session-shell/paste-types.d.ts} +1 -4
- package/dist/{integrations/pi/session-ui → app/session-shell}/path-chip-presentation.d.ts +1 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/prompt-chips.d.ts +5 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/prompt-chips.js +6 -2
- package/dist/{integrations/pi/session-ui → app/session-shell}/prompt-history-controller.d.ts +2 -2
- package/dist/{integrations/pi/session-ui → app/session-shell}/prompt-history-controller.js +2 -2
- package/dist/{integrations/pi/session-ui → app/session-shell}/prompt-suggestion-controller.d.ts +1 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/prompt-suggestion-controller.js +2 -2
- package/dist/{integrations/pi/session-ui → app/session-shell}/quit-outro.js +1 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/response-copy-coordinator.d.ts +1 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/response-copy-coordinator.js +3 -5
- package/dist/{integrations/pi/session-ui → app/session-shell}/response-copy-helper.js +1 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/response-copy-protocol.d.ts +1 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/response-copy-transport.d.ts +10 -2
- package/dist/{integrations/pi/session-ui → app/session-shell}/response-copy-transport.js +45 -19
- package/dist/{integrations/pi/session-ui → app/session-shell}/session-shell-root.d.ts +75 -53
- package/dist/{integrations/pi/session-ui → app/session-shell}/session-shell-root.js +30 -20
- package/dist/{integrations/pi/session-ui → app/session-shell}/session-shell.d.ts +9 -8
- package/dist/{integrations/pi/session-ui → app/session-shell}/session-shell.js +108 -67
- package/dist/{integrations/pi/session-ui → app/session-shell}/session-viewport-controller.d.ts +5 -5
- package/dist/{integrations/pi/session-ui → app/session-shell}/session-viewport-controller.js +5 -5
- package/dist/{integrations/pi/session-ui → app/session-shell}/system-clipboard.d.ts +1 -1
- package/dist/{integrations/pi/session-ui → app/session-shell}/system-clipboard.js +1 -1
- package/dist/cli/index.d.ts +8 -5
- package/dist/cli/index.js +4 -5
- package/dist/composition/index.d.ts +0 -1
- package/dist/composition/index.js +0 -1
- package/dist/composition/owned-ui.d.ts +2 -2
- package/dist/composition/owned-ui.js +35 -36
- package/dist/composition/settings-route-host.d.ts +2 -2
- package/dist/contracts/agent-engine/domain.d.ts +6 -1
- package/dist/contracts/agent-engine/index.d.ts +11 -8
- package/dist/contracts/agent-engine/index.js +6 -8
- package/dist/contracts/owned-ui/extension-ui.d.ts +8 -0
- package/dist/contracts/owned-ui/index.d.ts +12 -8
- package/dist/contracts/owned-ui/index.js +8 -8
- package/dist/features/launch/index.d.ts +12 -6
- package/dist/features/launch/index.js +6 -6
- package/dist/features/launch/intent.d.ts +5 -5
- package/dist/features/launch/intent.js +2 -2
- package/dist/features/owned-ui/index.d.ts +6 -6
- package/dist/features/owned-ui/index.js +4 -6
- package/dist/features/owned-ui/run.d.ts +2 -2
- package/dist/features/owned-ui/settings-app.d.ts +2 -2
- package/dist/features/owned-ui/settings-app.js +18 -5
- package/dist/features/prompt-history/service.d.ts +1 -1
- package/dist/features/prompt-history/service.js +1 -1
- package/dist/features/prompt-history/store.js +3 -7
- package/dist/features/prompt-suggestions/diagnostics.js +1 -1
- package/dist/features/prompt-suggestions/index.d.ts +2 -1
- package/dist/features/prompt-suggestions/index.js +1 -1
- package/dist/foundation/launch-guardian/index.d.ts +2 -1
- package/dist/foundation/launch-guardian/index.js +1 -1
- package/dist/foundation/lifecycle/index.d.ts +11 -6
- package/dist/foundation/lifecycle/index.js +5 -6
- package/dist/foundation/process-containment/index.d.ts +8 -6
- package/dist/foundation/process-containment/index.js +6 -6
- package/dist/foundation/process-containment/native-guardian-containment.js +3 -3
- package/dist/foundation/protocol/index.d.ts +3 -2
- package/dist/foundation/protocol/index.js +2 -2
- package/dist/foundation/release/bootstrap.d.ts +0 -4
- package/dist/foundation/release/bootstrap.js +1 -82
- package/dist/foundation/release/dependency-layer.d.ts +2 -5
- package/dist/foundation/release/endpoints.d.ts +4 -0
- package/dist/foundation/release/endpoints.js +86 -2
- package/dist/foundation/release/index.d.ts +30 -16
- package/dist/foundation/release/index.js +16 -16
- package/dist/foundation/release/release.d.ts +1 -1
- package/dist/foundation/release/types.d.ts +11 -0
- package/dist/foundation/release/types.js +1 -0
- package/dist/foundation/release/update-transaction.d.ts +1 -1
- package/dist/foundation/release/update.d.ts +2 -1
- package/dist/foundation/release/update.js +3 -18
- package/dist/foundation/startup/index.d.ts +4 -2
- package/dist/foundation/startup/index.js +2 -2
- package/dist/foundation/startup/startup-descriptor.js +2 -2
- package/dist/foundation/storage/control-store.d.ts +1 -45
- package/dist/foundation/storage/control-store.js +54 -277
- package/dist/foundation/storage/index.d.ts +1 -1
- package/dist/foundation/storage/index.js +1 -1
- package/dist/foundation/supervision/index.d.ts +2 -2
- package/dist/foundation/supervision/index.js +2 -2
- package/dist/foundation/supervision/server.d.ts +5 -10
- package/dist/foundation/supervision/server.js +7 -7
- package/dist/foundation/terminal-cleanup/index.d.ts +3 -2
- package/dist/foundation/terminal-cleanup/index.js +2 -2
- package/dist/integrations/pi/components/editor-interaction.d.ts +1 -1
- package/dist/integrations/pi/components/history-editor-loader.d.ts +1 -1
- package/dist/integrations/pi/components/index.d.ts +20 -13
- package/dist/integrations/pi/components/index.js +12 -13
- package/dist/integrations/pi/components/owned-editor-ux.js +5 -8
- package/dist/integrations/pi/components/resources/builtin-themes.d.ts +7 -5
- package/dist/integrations/pi/components/resources/builtin-themes.js +7 -5
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +1 -1
- package/dist/integrations/pi/components/shell-extension-ui.js +2 -1
- package/dist/integrations/pi/components/shell-footer-status.js +1 -1
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +1 -1
- package/dist/integrations/pi/components/shell-presenters-info.js +1 -1
- package/dist/integrations/pi/components/shell-presenters-transcript.js +1 -1
- package/dist/integrations/pi/components/shell-selectors-dialogs.d.ts +9 -3
- package/dist/integrations/pi/components/shell-selectors-dialogs.js +9 -6
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +3 -1
- package/dist/integrations/pi/components/shell-shared-facade.js +4 -2
- package/dist/integrations/pi/components/submitted-prompt-adapter.d.ts +1 -1
- package/dist/integrations/pi/components/submitted-prompt-adapter.js +1 -1
- package/dist/integrations/pi/components/tool-image-presentation.d.ts +1 -1
- package/dist/integrations/pi/components/tool-image-presentation.js +4 -7
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +36 -22
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +43 -7
- package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
- package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +6 -3
- package/dist/integrations/pi/components/upstream/components/daxnuts.d.ts +8 -1
- package/dist/integrations/pi/components/upstream/components/daxnuts.js +7 -3
- package/dist/integrations/pi/components/upstream/components/earendil-announcement.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +10 -4
- package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +7 -4
- package/dist/integrations/pi/components/upstream/components/extension-editor.js +7 -4
- package/dist/integrations/pi/components/upstream/components/mermaid.js +8 -4
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +9 -5
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +10 -6
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +8 -4
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +27 -25
- package/dist/integrations/pi/components/upstream/components/session-footer.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/session-footer.js +8 -10
- package/dist/integrations/pi/components/upstream/components/session-selector-search.js +6 -4
- package/dist/integrations/pi/components/upstream/components/session-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector.js +8 -4
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +7 -5
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +8 -6
- package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +9 -4
- package/dist/integrations/pi/components/upstream/components/status-indicator.js +15 -5
- package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +8 -2
- package/dist/integrations/pi/components/upstream/components/tool-execution.js +58 -37
- package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +7 -4
- package/dist/integrations/pi/components/upstream/components/tree-selector.js +7 -4
- package/dist/integrations/pi/components/upstream/components/trust-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/trust-selector.js +10 -5
- package/dist/integrations/pi/components/upstream/external-editor.js +8 -4
- package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +13 -4
- package/dist/integrations/pi/components/upstream/history/editor-core.js +112 -30
- package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +6 -3
- package/dist/integrations/pi/components/upstream/history/kill-ring.js +6 -3
- package/dist/integrations/pi/components/upstream/history/printable-key.js +7 -4
- package/dist/integrations/pi/components/upstream/history/text-helpers.js +6 -3
- package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +6 -3
- package/dist/integrations/pi/components/upstream/history/undo-stack.js +6 -3
- package/dist/integrations/pi/components/upstream/history/word-navigation.js +6 -3
- package/dist/integrations/pi/components/upstream/model-search.d.ts +5 -2
- package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +8 -0
- package/dist/integrations/pi/components/upstream/theme/theme-controller.js +0 -3
- package/dist/integrations/pi/components/upstream/theme/theme.d.ts +2 -2
- package/dist/integrations/pi/components/upstream/theme/theme.js +17 -6
- package/dist/integrations/pi/engine/adapter.d.ts +39 -138
- package/dist/integrations/pi/engine/adapter.js +338 -3226
- package/dist/integrations/pi/engine/command-dispatch.d.ts +41 -0
- package/dist/integrations/pi/engine/command-dispatch.js +125 -0
- package/dist/integrations/pi/engine/event-delivery.d.ts +100 -0
- package/dist/integrations/pi/engine/event-delivery.js +184 -0
- package/dist/integrations/pi/engine/extension-ui-binding.d.ts +35 -0
- package/dist/integrations/pi/engine/extension-ui-binding.js +81 -0
- package/dist/integrations/pi/engine/index.d.ts +18 -14
- package/dist/integrations/pi/engine/index.js +10 -14
- package/dist/integrations/pi/engine/message-values.d.ts +29 -0
- package/dist/integrations/pi/engine/message-values.js +168 -0
- package/dist/integrations/pi/engine/pending-delivery.d.ts +2 -2
- package/dist/integrations/pi/engine/pending-delivery.js +2 -4
- package/dist/integrations/pi/engine/pi-settings-metadata.json +382 -371
- package/dist/integrations/pi/engine/prompt-suggestions.d.ts +30 -0
- package/dist/integrations/pi/engine/prompt-suggestions.js +102 -0
- package/dist/integrations/pi/engine/provider-authentication.d.ts +34 -0
- package/dist/integrations/pi/engine/provider-authentication.js +209 -0
- package/dist/integrations/pi/engine/resource-catalog.d.ts +49 -0
- package/dist/integrations/pi/engine/resource-catalog.js +289 -0
- package/dist/integrations/pi/engine/resources/changelog.json +4 -4
- package/dist/integrations/pi/engine/session-events.d.ts +48 -0
- package/dist/integrations/pi/engine/session-events.js +223 -0
- package/dist/integrations/pi/engine/session-integration.js +2 -4
- package/dist/integrations/pi/engine/session-runtime.d.ts +84 -0
- package/dist/integrations/pi/engine/session-runtime.js +249 -0
- package/dist/integrations/pi/engine/{settings-effects.d.ts → settings-bridge.d.ts} +57 -2
- package/dist/integrations/pi/engine/settings-bridge.js +514 -0
- package/dist/integrations/pi/engine/settings-metadata.d.ts +31 -0
- package/dist/integrations/pi/engine/settings-metadata.js +67 -0
- package/dist/integrations/pi/engine/settings-port.d.ts +42 -0
- package/dist/integrations/pi/engine/settings-port.js +353 -0
- package/dist/integrations/pi/engine/transcript-projection.d.ts +39 -0
- package/dist/integrations/pi/engine/transcript-projection.js +405 -0
- package/dist/integrations/pi/engine/usage-view.d.ts +4 -0
- package/dist/integrations/pi/engine/usage-view.js +56 -0
- package/dist/integrations/pi/engine/workflow-contexts.d.ts +59 -0
- package/dist/integrations/pi/engine/workflow-contexts.js +316 -0
- package/dist/integrations/pi/engine/workflow-runner.d.ts +60 -0
- package/dist/integrations/pi/engine/workflow-runner.js +509 -0
- package/dist/integrations/pi/engine/workflow-support.d.ts +33 -0
- package/dist/integrations/pi/engine/workflow-support.js +352 -0
- package/dist/integrations/pi/engine/workflows.d.ts +63 -2
- package/dist/integrations/pi/engine/workflows.js +5 -2
- package/dist/integrations/pi/startup-public.js +576 -554
- package/dist/integrations/pi/startup-public.manifest.json +1730 -984
- package/dist/integrations/pi/tui-runtime/adapter.js +10 -13
- package/dist/integrations/pi/tui-runtime/contracts.d.ts +11 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +4 -7
- package/dist/integrations/pi/tui-runtime/index.d.ts +8 -6
- package/dist/integrations/pi/tui-runtime/index.js +4 -6
- package/dist/integrations/pi/tui-runtime/mouse-report-input.js +2 -4
- package/dist/integrations/pi/tui-runtime/overlay-geometry.d.ts +2 -2
- package/dist/integrations/pi/tui-runtime/overlay-geometry.js +4 -5
- package/dist/integrations/pi/tui-runtime/presentation-adapter.js +1 -1
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/runtime-payload-inventory.json +51320 -46509
- package/dist/ui/apps/index.d.ts +5 -3
- package/dist/ui/apps/index.js +3 -3
- package/dist/ui/components/index.d.ts +47 -25
- package/dist/ui/components/index.js +25 -25
- package/dist/ui/components/prompt-input.js +1 -4
- package/dist/ui/settings/declarations.d.ts +119 -0
- package/dist/ui/settings/declarations.js +20 -11
- package/dist/ui/settings/index.d.ts +10 -6
- package/dist/ui/settings/index.js +5 -6
- package/dist/ui/settings/manager.d.ts +54 -0
- package/dist/ui/settings/{session.js → manager.js} +101 -9
- package/dist/ui/settings/sections.d.ts +2 -7
- package/docs/architecture/boundaries.md +4 -4
- package/docs/architecture/history-editor-provenance.md +1 -1
- package/docs/architecture/project-structure.md +6 -6
- package/docs/architecture/prompt-suggestions.md +1 -1
- package/docs/architecture/terminal-host-proof-gate.md +1 -1
- package/docs/architecture/terminal-host-spike-evidence.md +1 -1
- package/docs/architecture/toolchain.md +8 -0
- package/docs/architecture/ui-reference-provenance.md +4 -4
- package/docs/ci-release-runbook.md +7 -1
- package/docs/features/modal-content-interaction.md +2 -2
- package/docs/local-worktree-cleanup.md +4 -2
- package/docs/validation.md +6 -4
- package/package.json +7 -11
- package/bin/pi-tui.d.ts +0 -6
- package/bin/pi-tui.js +0 -28
- package/bin/sync-pi-tui-proxy.js +0 -97
- package/dist/cli/version.d.ts +0 -2
- package/dist/cli/version.js +0 -23
- package/dist/composition/agent-engine-bridge.d.ts +0 -3
- package/dist/composition/agent-engine-bridge.js +0 -108
- package/dist/composition/process.d.ts +0 -16
- package/dist/composition/process.js +0 -45
- package/dist/contracts/workspace/index.d.ts +0 -2
- package/dist/contracts/workspace/index.js +0 -2
- package/dist/contracts/workspace/model.d.ts +0 -248
- package/dist/contracts/workspace/model.js +0 -2
- package/dist/contracts/workspace/validation.d.ts +0 -13
- package/dist/contracts/workspace/validation.js +0 -335
- package/dist/features/owned-ui/customization.d.ts +0 -40
- package/dist/features/owned-ui/customization.js +0 -110
- package/dist/features/owned-ui/diagnostics.d.ts +0 -34
- package/dist/features/owned-ui/diagnostics.js +0 -95
- package/dist/features/workspace/capabilities.d.ts +0 -31
- package/dist/features/workspace/capabilities.js +0 -75
- package/dist/features/workspace/index.d.ts +0 -6
- package/dist/features/workspace/index.js +0 -6
- package/dist/features/workspace/presentation.d.ts +0 -30
- package/dist/features/workspace/presentation.js +0 -70
- package/dist/features/workspace/reconciliation.d.ts +0 -15
- package/dist/features/workspace/reconciliation.js +0 -82
- package/dist/features/workspace/reducer.d.ts +0 -43
- package/dist/features/workspace/reducer.js +0 -214
- package/dist/features/workspace/router.d.ts +0 -32
- package/dist/features/workspace/router.js +0 -125
- package/dist/features/workspace/store.d.ts +0 -18
- package/dist/features/workspace/store.js +0 -55
- package/dist/foundation/native-host-protocol/codec.d.ts +0 -13
- package/dist/foundation/native-host-protocol/codec.js +0 -58
- package/dist/foundation/native-host-protocol/evidence.d.ts +0 -67
- package/dist/foundation/native-host-protocol/evidence.js +0 -141
- package/dist/foundation/native-host-protocol/index.d.ts +0 -4
- package/dist/foundation/native-host-protocol/index.js +0 -4
- package/dist/foundation/native-host-protocol/messages.d.ts +0 -56
- package/dist/foundation/native-host-protocol/messages.js +0 -149
- package/dist/foundation/native-host-protocol/proof-gate.d.ts +0 -13
- package/dist/foundation/native-host-protocol/proof-gate.js +0 -33
- package/dist/foundation/structured-agent-runtime/backpressure.d.ts +0 -47
- package/dist/foundation/structured-agent-runtime/backpressure.js +0 -119
- package/dist/foundation/structured-agent-runtime/commands.d.ts +0 -53
- package/dist/foundation/structured-agent-runtime/commands.js +0 -165
- package/dist/foundation/structured-agent-runtime/handshake.d.ts +0 -41
- package/dist/foundation/structured-agent-runtime/handshake.js +0 -151
- package/dist/foundation/structured-agent-runtime/index.d.ts +0 -5
- package/dist/foundation/structured-agent-runtime/index.js +0 -5
- package/dist/foundation/structured-agent-runtime/reconnection.d.ts +0 -38
- package/dist/foundation/structured-agent-runtime/reconnection.js +0 -130
- package/dist/foundation/structured-agent-runtime/state.d.ts +0 -57
- package/dist/foundation/structured-agent-runtime/state.js +0 -119
- package/dist/integrations/pi/components/upstream/components/custom-entry.d.ts +0 -17
- package/dist/integrations/pi/components/upstream/components/custom-entry.js +0 -51
- package/dist/integrations/pi/components/upstream/components/first-time-setup.d.ts +0 -24
- package/dist/integrations/pi/components/upstream/components/first-time-setup.js +0 -105
- package/dist/integrations/pi/components/upstream/components/markdown-transform.d.ts +0 -2
- package/dist/integrations/pi/components/upstream/components/markdown-transform.js +0 -18
- package/dist/integrations/pi/engine/model-auth-integration.d.ts +0 -31
- package/dist/integrations/pi/engine/model-auth-integration.js +0 -62
- package/dist/integrations/pi/engine/resource-extension-integration.d.ts +0 -32
- package/dist/integrations/pi/engine/resource-extension-integration.js +0 -81
- package/dist/integrations/pi/engine/settings-effects.js +0 -249
- package/dist/integrations/pi/engine/settings-integration.d.ts +0 -43
- package/dist/integrations/pi/engine/settings-integration.js +0 -227
- package/dist/integrations/pi/engine/workflow-controllers.d.ts +0 -21
- package/dist/integrations/pi/engine/workflow-controllers.js +0 -49
- package/dist/integrations/pi/session-ui/index.d.ts +0 -5
- package/dist/integrations/pi/session-ui/index.js +0 -5
- package/dist/integrations/pi/session-ui/paste-executor.d.ts +0 -10
- package/dist/integrations/pi/session-ui/paste-preparation-client.d.ts +0 -16
- package/dist/integrations/pi/session-ui/route-host.d.ts +0 -5
- package/dist/integrations/pi/tui-runtime/conformance.d.ts +0 -18
- package/dist/integrations/pi/tui-runtime/conformance.js +0 -145
- package/dist/ui/components/prompt-row.d.ts +0 -14
- package/dist/ui/components/prompt-row.js +0 -20
- package/dist/ui/settings/session.d.ts +0 -36
- package/dist/ui/settings/store.d.ts +0 -29
- package/dist/ui/settings/store.js +0 -91
- package/dist/{integrations/pi/session-ui → app/session-shell}/clipboard-diagnostics.js +2 -2
- package/dist/{integrations/pi/session-ui → app/session-shell}/clipboard-image.d.ts +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/editor-hyperlink-budget.d.ts +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/editor-hyperlink-budget.js +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/image-preparation.d.ts +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/image-source.d.ts +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/image-worker.d.ts +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/paste-helper.d.ts +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/paste-text-preparation.js +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/paste-text-worker.d.ts +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/paste-text-worker.js +0 -0
- package/dist/{integrations/pi/session-ui/response-copy-helper.d.ts → app/session-shell/paste-types.js} +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/path-chip-presentation.js +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/quit-outro-effects.d.ts +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/quit-outro-effects.js +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/quit-outro.d.ts +0 -0
- package/dist/{integrations/pi/session-ui/route-host.js → app/session-shell/response-copy-helper.d.ts} +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/response-copy-protocol.js +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/stream-presentation-coalescer.d.ts +0 -0
- package/dist/{integrations/pi/session-ui → app/session-shell}/stream-presentation-coalescer.js +3 -3
- /package/dist/{integrations/pi/session-ui → app/session-shell}/text-paste.d.ts +0 -0
- /package/dist/{integrations/pi/session-ui → app/session-shell}/text-paste.js +0 -0
package/bin/cli.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const commandStartedAtMs = performance.timeOrigin + performance.now();
|
|
4
4
|
const packageRoot = new URL("..", import.meta.url);
|
|
5
|
+
// Invariant: one terminal module identity per process, decided before any A1 or Pi module loads.
|
|
6
|
+
const [{ installPinnedPiTuiResolver }, { fileURLToPath: toPath }] = await Promise.all([import("./module-resolver.js"), import("node:url")]);
|
|
7
|
+
installPinnedPiTuiResolver(toPath(packageRoot));
|
|
5
8
|
const startup = await import("../dist/foundation/startup/startup-runtime.js");
|
|
6
9
|
const startupProfile = process.argv[2] === "pi" ? "pi" : "a1";
|
|
7
10
|
startup.initializeStartupTrace(process.env, startupProfile, commandStartedAtMs);
|
|
@@ -20,16 +23,12 @@ const capabilities = cliCapabilities(JSON.parse(await readFile(new URL("package.
|
|
|
20
23
|
|
|
21
24
|
process.exitCode = await dispatchCli(process.argv.slice(2), {
|
|
22
25
|
launch: async intent => {
|
|
23
|
-
const [{ prepareInteractiveLaunch }, { runBootstrap }, {
|
|
26
|
+
const [{ prepareInteractiveLaunch }, { runBootstrap }, { releaseCopyIsLaunchable }] = await Promise.all([
|
|
24
27
|
import("../dist/features/launch/prepare-launch.js"),
|
|
25
28
|
import("../dist/foundation/release/bootstrap.js"),
|
|
26
29
|
import("./module-identity.js"),
|
|
27
30
|
]);
|
|
28
|
-
// Compatibility: self-heal the installed tree before the release store copies it: npm 12
|
|
29
|
-
// blocks install scripts by default, so the postinstall that normally
|
|
30
|
-
// repairs module identity may never have run (see bin/module-identity.js).
|
|
31
31
|
const packageRootPath = fileURLToPath(packageRoot);
|
|
32
|
-
await healModuleIdentityAtLaunch(packageRootPath, message => process.stderr.write(message));
|
|
33
32
|
const prepared = await prepareInteractiveLaunch(intent);
|
|
34
33
|
return await runBootstrap({
|
|
35
34
|
packageRoot: packageRootPath,
|
package/bin/guardian.js
CHANGED
|
@@ -11,9 +11,13 @@ const { readLaunchContext } = await import("../dist/foundation/launch-context/in
|
|
|
11
11
|
const launchContext = readLaunchContext(process.env, "release");
|
|
12
12
|
const releaseRoot = launchContext.releaseRoot;
|
|
13
13
|
const profileId = readLaunchContext(process.env, "profile").launchProfile;
|
|
14
|
+
// Invariant: the "release" and "profile" requirements above already refused an environment without
|
|
15
|
+
// these values; the checks give the type checker the same certainty.
|
|
16
|
+
if (releaseRoot === undefined || profileId === undefined) throw new Error("A1 launch context is incomplete");
|
|
14
17
|
|
|
18
|
+
const sessionSelection = parseSessionSelection(process.argv.slice(2));
|
|
15
19
|
Promise.resolve().then(() => runLaunchGuardian({
|
|
16
|
-
sessionSelection:
|
|
20
|
+
...(sessionSelection === undefined ? {} : { sessionSelection }),
|
|
17
21
|
profileId,
|
|
18
22
|
releaseRoot,
|
|
19
23
|
uiEntry: resolve(releaseRoot, "bin", "ui.js"),
|
package/bin/module-identity.js
CHANGED
|
@@ -1,101 +1,58 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* One pi-tui module identity per process.
|
|
2
|
+
* One pi-tui module identity per process: the check that the resolver hook worked.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* bin/module-resolver.js decides identity at the loader by rewriting every pi-tui module
|
|
5
|
+
* URL to the copy pinned Pi resolves. What remains here is the assertion, made by asking
|
|
6
|
+
* Node itself: with the hook installed, resolving `@earendil-works/pi-tui` from A1's own
|
|
7
|
+
* package root must answer with the same real path pinned Pi answers with. When it does not,
|
|
8
|
+
* launch says so loudly and once, instead of leaving a user to discover it as missing
|
|
9
|
+
* extension UI.
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* resolves from its own directory — so an extension's `instanceof` check and
|
|
13
|
-
* its prototype patches land on classes A1's renderer never uses. Extension
|
|
14
|
-
* chrome silently disappears and routed input dead-ends, with no error.
|
|
15
|
-
*
|
|
16
|
-
* A1 therefore does not import the specifier at all. Its package declares the
|
|
17
|
-
* subpath import `#pi-tui`, resolving to bin/pi-tui.js — a proxy that
|
|
18
|
-
* re-exports pinned Pi's nested copy. The hop through the proxy is load-bearing:
|
|
19
|
-
* Node rejects package-imports targets containing a `node_modules` path segment
|
|
20
|
-
* (Invalid Package Target) and silently falls through to any fallback, which is
|
|
21
|
-
* exactly how an earlier alias that named the nested path directly reintroduced
|
|
22
|
-
* the split while appearing to declare the opposite. A plain import specifier
|
|
23
|
-
* inside a module carries no such restriction.
|
|
24
|
-
*
|
|
25
|
-
* What remains here is the check that it worked. The alias is resolved by
|
|
26
|
-
* asking Node itself — never by reimplementing resolution, which is how the
|
|
27
|
-
* earlier check reported "unified" for a target Node had rejected — and the
|
|
28
|
-
* proxy hop is followed to the module it re-exports. When that disagrees with
|
|
29
|
-
* what pinned Pi resolves, launch says so, loudly and once, instead of leaving
|
|
30
|
-
* a user to discover it as missing extension UI.
|
|
31
|
-
*
|
|
32
|
-
* This lives in bin/ (shipped, plain JS) because it inspects dependency
|
|
33
|
-
* resolution, which the Pi API boundary policy rightly forbids ordinary
|
|
34
|
-
* production code from touching.
|
|
11
|
+
* This lives in bin/ (shipped, plain JS) because it inspects dependency resolution, which
|
|
12
|
+
* the Pi API boundary policy rightly forbids ordinary production code from touching.
|
|
35
13
|
*/
|
|
36
14
|
import { createRequire } from "node:module";
|
|
37
15
|
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
38
16
|
import { dirname, join } from "node:path";
|
|
39
|
-
import { pathToFileURL } from "node:url";
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
18
|
+
import { pinnedPiTuiPackageRoot } from "./module-resolver.js";
|
|
40
19
|
|
|
41
20
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* Node answers for the alias itself (require.resolve honors package imports for
|
|
45
|
-
* the package the parent belongs to). When the answer is A1's proxy file, the
|
|
46
|
-
* module it re-exports is what A1 actually renders with, so the proxy's one
|
|
47
|
-
* static `export * from` specifier is followed to its target.
|
|
21
|
+
* @typedef {{ kind: "unified"; path: string } | { kind: "split"; own: string; pinned: string } | { kind: "unresolved"; side: "a1" | "pi"; message: string }} ModuleIdentityOutcome
|
|
48
22
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
try {
|
|
53
|
-
resolved = requireFromRoot.resolve("#pi-tui");
|
|
54
|
-
} catch (error) {
|
|
55
|
-
throw new Error(`#pi-tui does not resolve: ${message(error)}`);
|
|
56
|
-
}
|
|
57
|
-
return canonical(followProxyReExport(resolved));
|
|
58
|
-
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
const OWN_PACKAGE_ROOT = canonical(fileURLToPath(new URL("..", import.meta.url)));
|
|
59
26
|
|
|
60
27
|
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
28
|
+
* What A1's own modules resolve `@earendil-works/pi-tui` to, as a real path.
|
|
29
|
+
*
|
|
30
|
+
* Compatibility: the resolver hook governs ESM loading, and on Node 22 CommonJS resolution does
|
|
31
|
+
* not consult synchronous hooks at all, so the process's own package is measured through the ESM
|
|
32
|
+
* resolver from this file, which sits in that package. Any other root is measured by plain
|
|
33
|
+
* resolution, which is what its own entries would see before installing the hook. A test
|
|
34
|
+
* transformer that offers no `import.meta.resolve` falls back to plain resolution too.
|
|
35
|
+
* @param {string} packageRoot
|
|
64
36
|
*/
|
|
65
|
-
function
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
source = readFileSync(resolvedPath, "utf8");
|
|
69
|
-
} catch {
|
|
70
|
-
return resolvedPath;
|
|
71
|
-
}
|
|
72
|
-
const reExport = source.match(/^export \* from "(\.\.?\/[^"]+)";?$/m);
|
|
73
|
-
if (!reExport) return resolvedPath;
|
|
74
|
-
const target = join(dirname(resolvedPath), reExport[1]);
|
|
75
|
-
if (!existsSync(target)) {
|
|
76
|
-
throw new Error(`#pi-tui proxy ${resolvedPath} re-exports a missing file: ${target}`);
|
|
37
|
+
function resolveOwnPiTui(packageRoot) {
|
|
38
|
+
if (canonical(packageRoot) === OWN_PACKAGE_ROOT && typeof import.meta.resolve === "function") {
|
|
39
|
+
return canonical(fileURLToPath(import.meta.resolve("@earendil-works/pi-tui")));
|
|
77
40
|
}
|
|
78
|
-
|
|
41
|
+
const requireFromRoot = createRequire(pathToFileURL(join(packageRoot, "package.json")).href);
|
|
42
|
+
return canonical(requireFromRoot.resolve("@earendil-works/pi-tui"));
|
|
79
43
|
}
|
|
80
44
|
|
|
81
45
|
/**
|
|
82
|
-
* What pinned Pi resolves
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* Pi's directory is located by walking node_modules outward, the way Node
|
|
86
|
-
* itself would, rather than by resolving Pi's entry: its `exports` map offers
|
|
87
|
-
* no CommonJS condition, so an ordinary require cannot name it. From there a
|
|
88
|
-
* require resolves pi-tui, which publishes no `exports` map at all.
|
|
46
|
+
* What pinned Pi resolves `@earendil-works/pi-tui` to, as a real path.
|
|
47
|
+
* @param {string} packageRoot
|
|
89
48
|
*/
|
|
90
49
|
export function resolvePinnedPiTui(packageRoot) {
|
|
91
|
-
|
|
92
|
-
return canonical(createRequire(pathToFileURL(join(pinnedRoot, "package.json")).href).resolve("@earendil-works/pi-tui"));
|
|
50
|
+
return canonical(join(pinnedPiTuiPackageRoot(packageRoot), "dist", "index.js"));
|
|
93
51
|
}
|
|
94
52
|
|
|
95
53
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* which would make Pi read A1's package metadata and themes.
|
|
54
|
+
* @param {string} packageRoot
|
|
55
|
+
* @param {NodeJS.ProcessEnv} [environment]
|
|
99
56
|
*/
|
|
100
57
|
export function configurePinnedPiPublicPackage(packageRoot, environment = process.env) {
|
|
101
58
|
const pinnedRoot = resolvePinnedPiRoot(packageRoot);
|
|
@@ -107,6 +64,7 @@ export function configurePinnedPiPublicPackage(packageRoot, environment = proces
|
|
|
107
64
|
return { root: pinnedRoot, version: manifest.version };
|
|
108
65
|
}
|
|
109
66
|
|
|
67
|
+
/** @param {string} packageRoot */
|
|
110
68
|
function resolvePinnedPiRoot(packageRoot) {
|
|
111
69
|
let directory = packageRoot;
|
|
112
70
|
while (true) {
|
|
@@ -118,6 +76,7 @@ function resolvePinnedPiRoot(packageRoot) {
|
|
|
118
76
|
}
|
|
119
77
|
}
|
|
120
78
|
|
|
79
|
+
/** @param {string} path */
|
|
121
80
|
function canonical(path) {
|
|
122
81
|
try {
|
|
123
82
|
return realpathSync.native(path);
|
|
@@ -127,8 +86,10 @@ function canonical(path) {
|
|
|
127
86
|
}
|
|
128
87
|
|
|
129
88
|
/**
|
|
130
|
-
*
|
|
131
|
-
*
|
|
89
|
+
* Compare what A1 and pinned Pi resolve. With the resolver hook installed in this process the
|
|
90
|
+
* two agree whatever layout npm built; without it they agree only when npm hoisted one copy.
|
|
91
|
+
* @param {string} packageRoot
|
|
92
|
+
* @returns {ModuleIdentityOutcome}
|
|
132
93
|
*/
|
|
133
94
|
export function inspectPiTuiModuleIdentity(packageRoot) {
|
|
134
95
|
let own;
|
|
@@ -146,38 +107,32 @@ export function inspectPiTuiModuleIdentity(packageRoot) {
|
|
|
146
107
|
return own === pinned ? { kind: "unified", path: own } : { kind: "split", own, pinned };
|
|
147
108
|
}
|
|
148
109
|
|
|
110
|
+
/** @param {unknown} error */
|
|
149
111
|
function message(error) {
|
|
150
112
|
return error instanceof Error ? error.message : String(error);
|
|
151
113
|
}
|
|
152
114
|
|
|
153
115
|
/**
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
* this tree. npm 12 blocks install scripts unless allowScripts covers the
|
|
157
|
-
* package, so the postinstall that normally rewrites the proxy may never
|
|
158
|
-
* have run and the installed tree may still carry the published placeholder
|
|
159
|
-
* path. Named neutrally so the launch entries that call it stay free of
|
|
160
|
-
* terminal implementation identifiers, as the bootstrap boundary requires.
|
|
116
|
+
* A release copy is launchable when pinned Pi inside it resolves its terminal package.
|
|
117
|
+
* @param {string} releaseRoot
|
|
161
118
|
*/
|
|
162
|
-
export async function healModuleIdentityAtLaunch(packageRoot, warn) {
|
|
163
|
-
if (inspectPiTuiModuleIdentity(packageRoot).kind === "unified") return;
|
|
164
|
-
const { syncPiTuiProxy } = await import("./sync-pi-tui-proxy.js");
|
|
165
|
-
const outcome = syncPiTuiProxy(packageRoot);
|
|
166
|
-
if (outcome.kind === "unresolved") {
|
|
167
|
-
warn(`a1: could not point the terminal module proxy at pinned Pi's copy (${outcome.message}); extension UI may not render.\n`);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/** Whether a materialized release copy resolves one terminal module for both A1 and Pi. */
|
|
172
119
|
export function releaseCopyIsLaunchable(releaseRoot) {
|
|
173
|
-
|
|
120
|
+
try {
|
|
121
|
+
resolvePinnedPiTui(releaseRoot);
|
|
122
|
+
return true;
|
|
123
|
+
} catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
174
126
|
}
|
|
175
127
|
|
|
176
|
-
/**
|
|
128
|
+
/**
|
|
129
|
+
* @param {string} packageRoot
|
|
130
|
+
* @param {(message: string) => void} warn
|
|
131
|
+
*/
|
|
177
132
|
export function assertSinglePiTuiModuleAtLaunch(packageRoot, warn) {
|
|
178
133
|
const outcome = inspectPiTuiModuleIdentity(packageRoot);
|
|
179
134
|
if (outcome.kind === "split") {
|
|
180
|
-
warn(`a1: pi-tui resolves to two different copies (${outcome.own} for a1, ${outcome.pinned} for Pi); extension UI may not render. The
|
|
135
|
+
warn(`a1: pi-tui resolves to two different copies (${outcome.own} for a1, ${outcome.pinned} for Pi); extension UI may not render. The pinned pi-tui resolver hook is not active in this process.\n`);
|
|
181
136
|
} else if (outcome.kind === "unresolved") {
|
|
182
137
|
warn(`a1: could not resolve pi-tui from ${outcome.side === "a1" ? "a1" : "pinned Pi"} (${outcome.message}); extension UI may not render.\n`);
|
|
183
138
|
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One pi-tui module identity per process, decided at the loader.
|
|
3
|
+
*
|
|
4
|
+
* npm may materialize @earendil-works/pi-tui twice under A1's package root: as A1's own
|
|
5
|
+
* dependency at the node_modules root and nested inside @earendil-works/pi-coding-agent,
|
|
6
|
+
* whose shrinkwrap pins its own copy. Two copies means two of every TUI class: pinned Pi
|
|
7
|
+
* hands extensions the copy it resolves itself, so an extension's `instanceof` check and
|
|
8
|
+
* prototype patches would land on classes A1's renderer never uses, and extension chrome
|
|
9
|
+
* would silently vanish.
|
|
10
|
+
*
|
|
11
|
+
* Rather than repairing the layout after the fact, this module asks Node which copy pinned
|
|
12
|
+
* Pi resolves and installs a synchronous resolve hook that rewrites every pi-tui module URL,
|
|
13
|
+
* from any importer and in any form (bare specifier, subpath, or an absolute path into the
|
|
14
|
+
* other copy), to that one copy. When npm hoisted a single copy the two answers coincide and
|
|
15
|
+
* the hook changes nothing. The hook is registered by the bin/ entries before any A1 module
|
|
16
|
+
* loads, so the composition, the bundled Pi public artifact, and Pi's own extension loader
|
|
17
|
+
* all share one module. bin/module-identity.js keeps the launch-time assertion that it
|
|
18
|
+
* worked.
|
|
19
|
+
*
|
|
20
|
+
* This lives in bin/ (shipped, plain JS) because it inspects dependency resolution, which
|
|
21
|
+
* the Pi API boundary policy rightly forbids ordinary production code from touching.
|
|
22
|
+
*/
|
|
23
|
+
import { createRequire, registerHooks } from "node:module";
|
|
24
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
25
|
+
import { dirname, isAbsolute, join, relative } from "node:path";
|
|
26
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
27
|
+
|
|
28
|
+
const PACKAGE = "@earendil-works/pi-tui";
|
|
29
|
+
const SEGMENT = `/node_modules/${PACKAGE}/`;
|
|
30
|
+
|
|
31
|
+
/** @type {string | null} */
|
|
32
|
+
let installed = null;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The package root pinned Pi resolves `@earendil-works/pi-tui` to, as a real path.
|
|
36
|
+
* @param {string} packageRoot
|
|
37
|
+
* @returns {string}
|
|
38
|
+
*/
|
|
39
|
+
export function pinnedPiTuiPackageRoot(packageRoot) {
|
|
40
|
+
return pinnedPiTuiLayout(packageRoot).pinnedRoot;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Where pinned Pi lives and which pi-tui copy it resolves. The installation root is the directory
|
|
45
|
+
* whose node_modules holds pinned Pi; the hook rewrites only modules beneath it, so fixture trees
|
|
46
|
+
* and other release copies inspected from this process keep their own resolution.
|
|
47
|
+
* @param {string} packageRoot
|
|
48
|
+
* @returns {{ installationRoot: string; pinnedRoot: string }}
|
|
49
|
+
*/
|
|
50
|
+
export function pinnedPiTuiLayout(packageRoot) {
|
|
51
|
+
const piRoot = pinnedPiRoot(packageRoot);
|
|
52
|
+
const requireFromPi = createRequire(pathToFileURL(join(piRoot, "package.json")).href);
|
|
53
|
+
return {
|
|
54
|
+
installationRoot: dirname(dirname(dirname(piRoot))),
|
|
55
|
+
pinnedRoot: packageRootOf(canonical(requireFromPi.resolve(PACKAGE))),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Rationale: pinned Pi exports no `./package.json` subpath, so its directory is found by walking
|
|
60
|
+
// up from the package root the way Node itself would, never by reimplementing export resolution.
|
|
61
|
+
/** @param {string} packageRoot */
|
|
62
|
+
function pinnedPiRoot(packageRoot) {
|
|
63
|
+
let directory = packageRoot;
|
|
64
|
+
while (true) {
|
|
65
|
+
const candidate = join(directory, "node_modules", "@earendil-works", "pi-coding-agent");
|
|
66
|
+
if (existsSync(join(candidate, "package.json"))) return canonical(candidate);
|
|
67
|
+
const parent = dirname(directory);
|
|
68
|
+
if (parent === directory) throw new Error("pinned Pi is not installed beneath this package root");
|
|
69
|
+
directory = parent;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Install the resolve hook once per process. Returns the pinned package root URL. Idempotent:
|
|
75
|
+
* every bin/ entry calls it and only the first call registers.
|
|
76
|
+
* @param {string} packageRoot
|
|
77
|
+
* @returns {string}
|
|
78
|
+
*/
|
|
79
|
+
export function installPinnedPiTuiResolver(packageRoot) {
|
|
80
|
+
if (installed !== null) return installed;
|
|
81
|
+
const layout = pinnedPiTuiLayout(packageRoot);
|
|
82
|
+
registerHooks({
|
|
83
|
+
resolve(specifier, context, nextResolve) {
|
|
84
|
+
const result = nextResolve(specifier, context);
|
|
85
|
+
const rewritten = redirectToPinned(result.url, layout);
|
|
86
|
+
return rewritten === result.url ? result : { ...result, url: rewritten };
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
installed = pathToFileURL(layout.pinnedRoot).href.replace(/\/$/, "");
|
|
90
|
+
return installed;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Rewrite a resolved pi-tui module URL beneath the installation root to the pinned copy; any
|
|
95
|
+
* other URL is returned unchanged. Paths are compared as canonical real paths, never as URL
|
|
96
|
+
* strings: a temp directory reached by its short 8.3 name or a different drive-letter case is
|
|
97
|
+
* still the same installation.
|
|
98
|
+
* @param {string} url
|
|
99
|
+
* @param {{ installationRoot: string; pinnedRoot: string }} layout
|
|
100
|
+
* @returns {string}
|
|
101
|
+
*/
|
|
102
|
+
export function redirectToPinned(url, layout) {
|
|
103
|
+
if (!url.startsWith("file:")) return url;
|
|
104
|
+
const index = url.lastIndexOf(SEGMENT);
|
|
105
|
+
if (index < 0) return url;
|
|
106
|
+
const packagePath = canonical(fileURLToPath(url.slice(0, index + SEGMENT.length - 1)));
|
|
107
|
+
if (packagePath === layout.pinnedRoot || !isWithin(layout.installationRoot, packagePath)) return url;
|
|
108
|
+
return `${pathToFileURL(layout.pinnedRoot).href.replace(/\/$/, "")}${url.slice(index + SEGMENT.length - 1)}`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @param {string} root
|
|
113
|
+
* @param {string} path
|
|
114
|
+
*/
|
|
115
|
+
function isWithin(root, path) {
|
|
116
|
+
const relativePath = relative(root, path);
|
|
117
|
+
return relativePath !== "" && !relativePath.startsWith("..") && !isAbsolute(relativePath);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** @param {string} path */
|
|
121
|
+
function canonical(path) {
|
|
122
|
+
try {
|
|
123
|
+
return realpathSync.native(path);
|
|
124
|
+
} catch {
|
|
125
|
+
return path;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** @param {string} modulePath */
|
|
130
|
+
function packageRootOf(modulePath) {
|
|
131
|
+
let directory = dirname(modulePath);
|
|
132
|
+
while (!directory.endsWith(join("node_modules", "@earendil-works", "pi-tui"))) {
|
|
133
|
+
const parent = dirname(directory);
|
|
134
|
+
if (parent === directory) throw new Error(`${modulePath} is not inside a ${PACKAGE} package`);
|
|
135
|
+
directory = parent;
|
|
136
|
+
}
|
|
137
|
+
return directory;
|
|
138
|
+
}
|
package/bin/pinned-pi-public.js
CHANGED
|
@@ -2,7 +2,10 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
2
2
|
import { dirname, posix, resolve, sep } from "node:path";
|
|
3
3
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
4
|
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Bind the generated facade to the package reached through Pi's public entry.
|
|
7
|
+
* @param {string | URL} entryUrl
|
|
8
|
+
*/
|
|
6
9
|
export function configurePinnedPiPublicPackageEntry(entryUrl) {
|
|
7
10
|
const root = dirname(dirname(fileURLToPath(entryUrl)));
|
|
8
11
|
const manifest = JSON.parse(readFileSync(resolve(root, "package.json"), "utf8"));
|
|
@@ -13,7 +16,10 @@ export function configurePinnedPiPublicPackageEntry(entryUrl) {
|
|
|
13
16
|
return { root, version: manifest.version };
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Preserve one bundled Pi module's original public-package URL semantics.
|
|
21
|
+
* @param {string} relativeModule
|
|
22
|
+
*/
|
|
17
23
|
export function pinnedPiModuleUrl(relativeModule) {
|
|
18
24
|
if (typeof relativeModule !== "string" || relativeModule.includes("\\") || relativeModule.startsWith("/")
|
|
19
25
|
|| posix.normalize(relativeModule).startsWith("../") || !relativeModule.endsWith(".js")) {
|
|
@@ -22,7 +28,10 @@ export function pinnedPiModuleUrl(relativeModule) {
|
|
|
22
28
|
return pathToFileURL(resolve(pinnedRoot(), "dist", relativeModule)).href;
|
|
23
29
|
}
|
|
24
30
|
|
|
25
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Resolve documented Pi dependency exports from the pinned public package tree.
|
|
33
|
+
* @param {string} specifier
|
|
34
|
+
*/
|
|
26
35
|
export function resolvePinnedPiImport(specifier) {
|
|
27
36
|
if (typeof specifier !== "string" || specifier.includes("\\") || specifier.includes("\0")) {
|
|
28
37
|
throw new Error("pinned Pi import specifier is invalid");
|
|
@@ -31,7 +40,7 @@ export function resolvePinnedPiImport(specifier) {
|
|
|
31
40
|
if (specifier === "@earendil-works/pi-coding-agent") return pathToFileURL(resolve(root, "dist", "index.js")).href;
|
|
32
41
|
const match = /^(@[^/]+\/[^/]+|[^/]+)(\/.*)?$/.exec(specifier);
|
|
33
42
|
if (match === null) throw new Error(`pinned Pi import is invalid: ${specifier}`);
|
|
34
|
-
const packageName = match[1];
|
|
43
|
+
const packageName = match[1] ?? "";
|
|
35
44
|
const subpath = match[2]?.slice(1) ?? "";
|
|
36
45
|
const packageRoot = resolve(root, "node_modules", ...packageName.split("/"));
|
|
37
46
|
const manifestPath = resolve(packageRoot, "package.json");
|
|
@@ -51,11 +60,16 @@ function pinnedRoot() {
|
|
|
51
60
|
return resolve(root);
|
|
52
61
|
}
|
|
53
62
|
|
|
63
|
+
/**
|
|
64
|
+
* @param {unknown} exports
|
|
65
|
+
* @param {string} subpath
|
|
66
|
+
* @returns {string | undefined}
|
|
67
|
+
*/
|
|
54
68
|
function exportedTarget(exports, subpath) {
|
|
55
69
|
const key = subpath.length === 0 ? "." : `./${subpath}`;
|
|
56
70
|
if (typeof exports === "string") return subpath.length === 0 ? exports : undefined;
|
|
57
71
|
if (!exports || typeof exports !== "object") return undefined;
|
|
58
|
-
const exact = exports[key];
|
|
72
|
+
const exact = /** @type {Record<string, unknown>} */ (exports)[key];
|
|
59
73
|
if (exact !== undefined) return importCondition(exact);
|
|
60
74
|
for (const [pattern, value] of Object.entries(exports)) {
|
|
61
75
|
const star = pattern.indexOf("*");
|
|
@@ -67,8 +81,13 @@ function exportedTarget(exports, subpath) {
|
|
|
67
81
|
return undefined;
|
|
68
82
|
}
|
|
69
83
|
|
|
84
|
+
/**
|
|
85
|
+
* @param {unknown} value
|
|
86
|
+
* @returns {string | undefined}
|
|
87
|
+
*/
|
|
70
88
|
function importCondition(value) {
|
|
71
89
|
if (typeof value === "string") return value;
|
|
72
90
|
if (!value || typeof value !== "object") return undefined;
|
|
73
|
-
|
|
91
|
+
const conditions = /** @type {{ import?: unknown; default?: unknown }} */ (value);
|
|
92
|
+
return importCondition(conditions.import ?? conditions.default);
|
|
74
93
|
}
|
package/bin/ui.js
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// Invariant: one terminal module identity per process, decided before any A1 or Pi module loads.
|
|
4
|
+
const { installPinnedPiTuiResolver } = await import("./module-resolver.js");
|
|
5
|
+
installPinnedPiTuiResolver(new URL("..", import.meta.url).pathname.replace(/^\/(.:)/, "$1").replace(/\/$/, ""));
|
|
3
6
|
const startup = await import("../dist/foundation/startup/startup-runtime.js");
|
|
4
7
|
startup.enableEnvironmentCompileCache(process.env);
|
|
5
8
|
const { readLaunchContext } = await import("../dist/foundation/launch-context/index.js");
|
|
6
9
|
const launchContext = readLaunchContext(process.env, "profile");
|
|
7
10
|
const profile = launchContext.launchProfile;
|
|
11
|
+
if (profile === undefined) throw new Error("A1 launch profile is missing");
|
|
8
12
|
const { installFatalExit } = await import("../dist/foundation/terminal-cleanup/fatal-exit.js");
|
|
9
13
|
const { resolveProductPaths } = await import("../dist/foundation/lifecycle/paths.js");
|
|
10
14
|
const { join } = await import("node:path");
|
|
15
|
+
/** @type {{ dispose(): void | Promise<unknown> } | undefined} */
|
|
11
16
|
let runningApplication;
|
|
12
17
|
const fatal = profile === "a1" ? installFatalExit({
|
|
13
18
|
directory: join(resolveProductPaths().runtimeDir, "crashes"),
|
|
14
|
-
releaseId: launchContext.releaseId,
|
|
19
|
+
...(launchContext.releaseId === undefined ? {} : { releaseId: launchContext.releaseId }),
|
|
15
20
|
dispose: () => runningApplication?.dispose(),
|
|
16
21
|
}) : undefined;
|
|
17
22
|
const [{ fileURLToPath }, identity, descriptor] = await Promise.all([
|
|
@@ -36,7 +41,7 @@ const [
|
|
|
36
41
|
|
|
37
42
|
// Compatibility: before the composition uses pinned Pi's terminal stack: confirm A1 and Pi
|
|
38
43
|
// resolve it to the same copy, so extensions and the owned UI share one module identity.
|
|
39
|
-
identity.assertSinglePiTuiModuleAtLaunch(packageRootPath, message => process.stderr.write(message));
|
|
44
|
+
identity.assertSinglePiTuiModuleAtLaunch(packageRootPath, (/** @type {string} */ message) => process.stderr.write(message));
|
|
40
45
|
await startup.markStartupPhase(process.env, "ui-modules-loaded");
|
|
41
46
|
|
|
42
47
|
const sessionSelection = parseSessionSelection(process.argv.slice(2));
|