@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/update-recovery.js
CHANGED
|
@@ -9,19 +9,46 @@ import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
10
|
|
|
11
11
|
const SCHEMA = "a1-update-recovery-v1";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {object} Capsule
|
|
15
|
+
* @property {string} transactionId
|
|
16
|
+
* @property {string} packageName
|
|
17
|
+
* @property {string} targetVersion
|
|
18
|
+
* @property {string} packageRoot
|
|
19
|
+
* @property {string} globalRoot
|
|
20
|
+
* @property {string} launcherRoot
|
|
21
|
+
* @property {string[]} launchers
|
|
22
|
+
* @property {string} priorReleaseId
|
|
23
|
+
* @property {string} priorReleaseRoot
|
|
24
|
+
* @property {string} priorContentDigest
|
|
25
|
+
* @property {string} releaseManifestName
|
|
26
|
+
* @property {string} recoveryEntry
|
|
27
|
+
* @property {string} recoveryEntryDigest
|
|
28
|
+
* @property {string} nodeExecutable
|
|
29
|
+
* @property {string} npmCli
|
|
30
|
+
* @property {string[]} npmArguments
|
|
31
|
+
* @property {string} resultPath
|
|
32
|
+
* @property {string} cancellationPath
|
|
33
|
+
* @property {string} ownerPath
|
|
34
|
+
*/
|
|
35
|
+
|
|
12
36
|
const [, , mode, manifestPath, separator, ...forwarded] = process.argv;
|
|
13
37
|
|
|
14
38
|
if ((mode !== "--worker" && mode !== "--launch") || !manifestPath || (mode === "--launch" && separator !== "--")) {
|
|
15
39
|
throw new Error("invalid A1 update recovery invocation");
|
|
16
40
|
}
|
|
17
41
|
|
|
18
|
-
|
|
42
|
+
/** @type {string} */
|
|
43
|
+
const capsuleManifestPath = manifestPath;
|
|
44
|
+
const capsule = await readCapsule(capsuleManifestPath);
|
|
19
45
|
if (mode === "--worker") {
|
|
20
46
|
await runWorker(capsule);
|
|
21
47
|
} else {
|
|
22
48
|
process.exitCode = await runRecoveredCommand(capsule, forwarded);
|
|
23
49
|
}
|
|
24
50
|
|
|
51
|
+
/** @param {Capsule} value */
|
|
25
52
|
async function runWorker(value) {
|
|
26
53
|
await rm(value.resultPath, { force: true });
|
|
27
54
|
await writeJson(value.ownerPath, {
|
|
@@ -46,12 +73,15 @@ async function runWorker(value) {
|
|
|
46
73
|
windowsHide: true,
|
|
47
74
|
stdio: ["ignore", "pipe", "pipe"],
|
|
48
75
|
});
|
|
76
|
+
/** @type {Buffer[]} */
|
|
49
77
|
const stdout = [];
|
|
78
|
+
/** @type {Buffer[]} */
|
|
50
79
|
const stderr = [];
|
|
51
80
|
child.stdout?.on("data", chunk => stdout.push(Buffer.from(chunk)));
|
|
52
81
|
child.stderr?.on("data", chunk => stderr.push(Buffer.from(chunk)));
|
|
53
82
|
let cancelled = false;
|
|
54
83
|
let forced = false;
|
|
84
|
+
/** @type {ReturnType<typeof setTimeout> | null} */
|
|
55
85
|
let forceTimer = null;
|
|
56
86
|
const cancellationPoll = setInterval(async () => {
|
|
57
87
|
if (cancelled || !await exists(value.cancellationPath)) return;
|
|
@@ -104,20 +134,25 @@ async function runWorker(value) {
|
|
|
104
134
|
if (launcherDisposition === "unavailable") process.exitCode = 1;
|
|
105
135
|
}
|
|
106
136
|
|
|
137
|
+
/**
|
|
138
|
+
* @param {Capsule} value
|
|
139
|
+
* @param {string[]} arguments_
|
|
140
|
+
* @returns {Promise<number>}
|
|
141
|
+
*/
|
|
107
142
|
async function runRecoveredCommand(value, arguments_) {
|
|
108
143
|
let entry = await installedTargetEntry(value);
|
|
109
144
|
if (entry === null && arguments_[0] === "update") {
|
|
110
145
|
await rm(value.cancellationPath, { force: true });
|
|
111
146
|
await rm(value.resultPath, { force: true });
|
|
112
147
|
await rm(value.ownerPath, { force: true });
|
|
113
|
-
const worker = spawn(process.execPath, [fileURLToPath(import.meta.url), "--worker",
|
|
148
|
+
const worker = spawn(process.execPath, [fileURLToPath(import.meta.url), "--worker", capsuleManifestPath], {
|
|
114
149
|
detached: true,
|
|
115
150
|
windowsHide: true,
|
|
116
151
|
stdio: "ignore",
|
|
117
152
|
});
|
|
118
153
|
worker.unref();
|
|
119
154
|
const deadline = Date.now() + 15 * 60 * 1000;
|
|
120
|
-
const requestCancellation = signal => { void writeJson(value.cancellationPath, { schema: SCHEMA, transactionId: value.transactionId, signal, requestedAt: new Date().toISOString() }); };
|
|
155
|
+
const requestCancellation = (/** @type {string} */ signal) => { void writeJson(value.cancellationPath, { schema: SCHEMA, transactionId: value.transactionId, signal, requestedAt: new Date().toISOString() }); };
|
|
121
156
|
const onSigint = () => requestCancellation("SIGINT");
|
|
122
157
|
const onSigterm = () => requestCancellation("SIGTERM");
|
|
123
158
|
process.on("SIGINT", onSigint);
|
|
@@ -138,6 +173,10 @@ async function runRecoveredCommand(value, arguments_) {
|
|
|
138
173
|
});
|
|
139
174
|
}
|
|
140
175
|
|
|
176
|
+
/**
|
|
177
|
+
* @param {string} path
|
|
178
|
+
* @returns {Promise<Capsule>}
|
|
179
|
+
*/
|
|
141
180
|
async function readCapsule(path) {
|
|
142
181
|
const value = JSON.parse(await readFile(path, "utf8"));
|
|
143
182
|
if (value.launchContract !== "neutral-launch-v1") throw new Error("Unsupported private recovery contract; stop existing processes and install directly with npm. Preserve settings, sessions, and history.");
|
|
@@ -167,10 +206,10 @@ async function readCapsule(path) {
|
|
|
167
206
|
const expectedLaunchers = process.platform === "win32"
|
|
168
207
|
? [resolve(launcherRoot, "a1"), resolve(launcherRoot, "a1.cmd"), resolve(launcherRoot, "a1.ps1")]
|
|
169
208
|
: [resolve(launcherRoot, "a1")];
|
|
170
|
-
if (JSON.stringify(value.launchers.map(path => resolve(path))) !== JSON.stringify(expectedLaunchers)) throw new Error("A1 update recovery launcher set is invalid");
|
|
209
|
+
if (JSON.stringify(value.launchers.map((/** @type {string} */ path) => resolve(path))) !== JSON.stringify(expectedLaunchers)) throw new Error("A1 update recovery launcher set is invalid");
|
|
171
210
|
for (const launcher of value.launchers) assertDirectChild(launcherRoot, resolve(launcher));
|
|
172
211
|
const expectedSidecars = [resolve(lexicalCapsuleRoot, "cancel.json"), resolve(lexicalCapsuleRoot, "result.json"), resolve(lexicalCapsuleRoot, "owner.json")];
|
|
173
|
-
if (![value.cancellationPath, value.resultPath, value.ownerPath].every((candidate, index) => samePath(candidate, expectedSidecars[index]))) {
|
|
212
|
+
if (![value.cancellationPath, value.resultPath, value.ownerPath].every((candidate, index) => samePath(candidate, expectedSidecars[index] ?? ""))) {
|
|
174
213
|
throw new Error("A1 update recovery sidecar paths are invalid");
|
|
175
214
|
}
|
|
176
215
|
const dataDir = dirname(dirname(capsuleRoot));
|
|
@@ -188,6 +227,7 @@ async function readCapsule(path) {
|
|
|
188
227
|
return value;
|
|
189
228
|
}
|
|
190
229
|
|
|
230
|
+
/** @param {Capsule} value */
|
|
191
231
|
async function installedTargetEntry(value) {
|
|
192
232
|
try {
|
|
193
233
|
const manifest = JSON.parse(await readFile(resolve(value.packageRoot, "package.json"), "utf8"));
|
|
@@ -197,6 +237,7 @@ async function installedTargetEntry(value) {
|
|
|
197
237
|
} catch { return null; }
|
|
198
238
|
}
|
|
199
239
|
|
|
240
|
+
/** @param {Capsule} value */
|
|
200
241
|
async function installedTargetIsCallable(value) {
|
|
201
242
|
if (await installedTargetEntry(value) === null) return false;
|
|
202
243
|
const token = `node_modules/${value.packageName}/bin/cli.js`;
|
|
@@ -212,18 +253,20 @@ async function installedTargetIsCallable(value) {
|
|
|
212
253
|
return true;
|
|
213
254
|
}
|
|
214
255
|
|
|
256
|
+
/** @param {Capsule} value */
|
|
215
257
|
async function writeRecoveryLaunchers(value) {
|
|
216
258
|
const node = value.nodeExecutable ?? process.execPath;
|
|
217
259
|
const entry = value.recoveryEntry;
|
|
218
|
-
const manifest =
|
|
260
|
+
const manifest = capsuleManifestPath;
|
|
219
261
|
const shell = `#!/bin/sh\nexec ${shellQuote(node)} ${shellQuote(entry)} --launch ${shellQuote(manifest)} -- "$@"\n`;
|
|
220
262
|
const command = `@ECHO off\r\n"${node}" "${entry}" --launch "${manifest}" -- %*\r\n`;
|
|
221
263
|
const powershell = `& '${psQuote(node)}' '${psQuote(entry)}' --launch '${psQuote(manifest)}' -- $args\nexit $LASTEXITCODE\n`;
|
|
222
264
|
const content = process.platform === "win32" ? [shell, command, powershell] : [shell];
|
|
223
265
|
await mkdir(value.launcherRoot, { recursive: true });
|
|
224
|
-
for (let index = 0; index < value.launchers.length; index += 1) await atomicWrite(value.launchers[index], content[index], 0o755);
|
|
266
|
+
for (let index = 0; index < value.launchers.length; index += 1) await atomicWrite(value.launchers[index] ?? "", content[index] ?? "", 0o755);
|
|
225
267
|
}
|
|
226
268
|
|
|
269
|
+
/** @param {Capsule} value */
|
|
227
270
|
async function recoveryLaunchersAreCallable(value) {
|
|
228
271
|
for (const path of value.launchers) {
|
|
229
272
|
try {
|
|
@@ -236,6 +279,11 @@ async function recoveryLaunchersAreCallable(value) {
|
|
|
236
279
|
return true;
|
|
237
280
|
}
|
|
238
281
|
|
|
282
|
+
/**
|
|
283
|
+
* @param {string} path
|
|
284
|
+
* @param {string} content
|
|
285
|
+
* @param {number} mode
|
|
286
|
+
*/
|
|
239
287
|
async function atomicWrite(path, content, mode) {
|
|
240
288
|
const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
241
289
|
await writeFile(temporary, content, { mode });
|
|
@@ -244,6 +292,10 @@ async function atomicWrite(path, content, mode) {
|
|
|
244
292
|
await rename(temporary, path);
|
|
245
293
|
}
|
|
246
294
|
|
|
295
|
+
/**
|
|
296
|
+
* @param {string} path
|
|
297
|
+
* @param {unknown} value
|
|
298
|
+
*/
|
|
247
299
|
async function writeJson(path, value) {
|
|
248
300
|
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
249
301
|
const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
@@ -254,21 +306,38 @@ async function writeJson(path, value) {
|
|
|
254
306
|
await rename(temporary, path);
|
|
255
307
|
}
|
|
256
308
|
|
|
309
|
+
/**
|
|
310
|
+
* @param {string} left
|
|
311
|
+
* @param {string} right
|
|
312
|
+
*/
|
|
257
313
|
function samePath(left, right) {
|
|
258
314
|
return process.platform === "win32" ? resolve(left).toLowerCase() === resolve(right).toLowerCase() : resolve(left) === resolve(right);
|
|
259
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* @param {string} parent
|
|
318
|
+
* @param {string} child
|
|
319
|
+
*/
|
|
260
320
|
function containedBy(parent, child) {
|
|
261
321
|
const fromParent = relative(parent, child);
|
|
262
322
|
return fromParent.length > 0 && fromParent !== ".." && !fromParent.startsWith(`..${sep}`) && !isAbsolute(fromParent);
|
|
263
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* @param {string} parent
|
|
326
|
+
* @param {string} child
|
|
327
|
+
*/
|
|
264
328
|
function assertDirectChild(parent, child) {
|
|
265
329
|
const expectedParent = resolve(parent);
|
|
266
330
|
const actualParent = dirname(resolve(child));
|
|
267
331
|
const matches = process.platform === "win32" ? actualParent.toLowerCase() === expectedParent.toLowerCase() : actualParent === expectedParent;
|
|
268
332
|
if (!matches) throw new Error(`A1 update recovery path escapes its managed root: ${child}`);
|
|
269
333
|
}
|
|
334
|
+
/** @param {string} value */
|
|
270
335
|
function shellQuote(value) { return `'${String(value).replaceAll("'", `'"'"'`)}'`; }
|
|
336
|
+
/** @param {string} value */
|
|
271
337
|
function psQuote(value) { return String(value).replaceAll("'", "''"); }
|
|
338
|
+
/** @param {string} value */
|
|
272
339
|
function bounded(value) { return value.length <= 64 * 1024 ? value : value.slice(-64 * 1024); }
|
|
340
|
+
/** @param {string} path */
|
|
273
341
|
async function exists(path) { return await lstat(path).then(() => true).catch(() => false); }
|
|
342
|
+
/** @param {number} ms */
|
|
274
343
|
async function sleep(ms) { await new Promise(resolvePromise => setTimeout(resolvePromise, ms)); }
|
package/bin/warmup.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
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 }, { fileURLToPath: toPath }] = await Promise.all([import("./module-resolver.js"), import("node:url")]);
|
|
5
|
+
installPinnedPiTuiResolver(toPath(new URL("..", import.meta.url)));
|
|
3
6
|
const startup = await import("../dist/foundation/startup/startup-runtime.js");
|
|
4
7
|
startup.assertImmutableWarmupEnvironment(process.env);
|
|
5
8
|
startup.enableEnvironmentCompileCache(process.env);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PiTuiInputDiagnosticsEvent } from "
|
|
1
|
+
import type { PiTuiInputDiagnosticsEvent } from "../../integrations/pi/tui-runtime/contracts.js";
|
|
2
2
|
import type { ResponseCopyEvent } from "./response-copy-protocol.js";
|
|
3
3
|
import type { PasteEvent } from "./paste-protocol.js";
|
|
4
4
|
/** Opt-in scalar-only snapshots, bounded to 128 rows and one pending asynchronous write. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ImageAttachmentError, MAX_IMAGE_DATA_BYTES } from "
|
|
1
|
+
import { ImageAttachmentError, MAX_IMAGE_DATA_BYTES } from "../../contracts/owned-ui/index.js";
|
|
2
2
|
import { MAX_SOURCE_IMAGE_BYTES } from "./image-source.js";
|
|
3
3
|
const STANDARD_BASE64 = /^[A-Za-z0-9+/]*={0,2}$/u;
|
|
4
4
|
/**
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ChildProcess } from "node:child_process";
|
|
2
|
+
/** How long an unused spare helper may idle before it is stopped so a background session holds no extra process. */
|
|
3
|
+
export declare const HELPER_SPARE_IDLE_MS: number;
|
|
4
|
+
export interface SpareHelper {
|
|
5
|
+
readonly child: ChildProcess;
|
|
6
|
+
/** Whether the helper already announced itself; the taker must then send the first request itself. */
|
|
7
|
+
readonly ready: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface HelperPoolOptions {
|
|
10
|
+
readonly fork: () => ChildProcess;
|
|
11
|
+
/** Stops a spare that is no longer wanted; the paste helper needs its process group killed on POSIX. */
|
|
12
|
+
readonly stop: (child: ChildProcess) => void;
|
|
13
|
+
readonly idleMs?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Keeps one forked IPC helper ready so a request takes a live child instead of paying fork and module
|
|
17
|
+
* load on its own critical path. The spare stays idle on its channel until it is taken; a spare that
|
|
18
|
+
* exits or idles too long is dropped, and the next request forks cold and warms a replacement afterwards.
|
|
19
|
+
*/
|
|
20
|
+
export declare class HelperPool {
|
|
21
|
+
#private;
|
|
22
|
+
constructor(options: HelperPoolOptions);
|
|
23
|
+
/** Whether a spare is currently held (ready or still starting). */
|
|
24
|
+
get warmed(): boolean;
|
|
25
|
+
/** Opts the pool in and forks the first spare; from here on `replenish` keeps one ready after each request. */
|
|
26
|
+
warm(): void;
|
|
27
|
+
/** Forks the next spare after a request released its child; a no-op until the owner warmed the pool. A fork failure leaves the pool empty. */
|
|
28
|
+
replenish(): void;
|
|
29
|
+
/** Hands the spare to a request, with the pool's listeners removed; returns nothing when no live spare is held. */
|
|
30
|
+
take(): SpareHelper | undefined;
|
|
31
|
+
/** Stops the held spare and refuses further warming. */
|
|
32
|
+
dispose(): void;
|
|
33
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** How long an unused spare helper may idle before it is stopped so a background session holds no extra process. */
|
|
2
|
+
export const HELPER_SPARE_IDLE_MS = 5 * 60_000;
|
|
3
|
+
/**
|
|
4
|
+
* Keeps one forked IPC helper ready so a request takes a live child instead of paying fork and module
|
|
5
|
+
* load on its own critical path. The spare stays idle on its channel until it is taken; a spare that
|
|
6
|
+
* exits or idles too long is dropped, and the next request forks cold and warms a replacement afterwards.
|
|
7
|
+
*/
|
|
8
|
+
export class HelperPool {
|
|
9
|
+
#fork;
|
|
10
|
+
#stop;
|
|
11
|
+
#idleMs;
|
|
12
|
+
#spare;
|
|
13
|
+
#enabled = false;
|
|
14
|
+
#disposed = false;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.#fork = options.fork;
|
|
17
|
+
this.#stop = options.stop;
|
|
18
|
+
this.#idleMs = options.idleMs ?? HELPER_SPARE_IDLE_MS;
|
|
19
|
+
}
|
|
20
|
+
/** Whether a spare is currently held (ready or still starting). */
|
|
21
|
+
get warmed() { return this.#spare !== undefined; }
|
|
22
|
+
/** Opts the pool in and forks the first spare; from here on `replenish` keeps one ready after each request. */
|
|
23
|
+
warm() {
|
|
24
|
+
if (this.#disposed)
|
|
25
|
+
return;
|
|
26
|
+
this.#enabled = true;
|
|
27
|
+
this.replenish();
|
|
28
|
+
}
|
|
29
|
+
/** Forks the next spare after a request released its child; a no-op until the owner warmed the pool. A fork failure leaves the pool empty. */
|
|
30
|
+
replenish() {
|
|
31
|
+
if (!this.#enabled || this.#disposed || this.#spare !== undefined)
|
|
32
|
+
return;
|
|
33
|
+
let child;
|
|
34
|
+
try {
|
|
35
|
+
child = this.#fork();
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const onMessage = (value) => {
|
|
41
|
+
if (this.#spare?.child === child && value?.kind === "ready")
|
|
42
|
+
this.#spare.ready = true;
|
|
43
|
+
};
|
|
44
|
+
const onExit = () => { if (this.#spare?.child === child) {
|
|
45
|
+
this.#drop();
|
|
46
|
+
} };
|
|
47
|
+
const detach = () => {
|
|
48
|
+
child.off("message", onMessage);
|
|
49
|
+
child.off("exit", onExit);
|
|
50
|
+
child.off("close", onExit);
|
|
51
|
+
child.off("error", onExit);
|
|
52
|
+
};
|
|
53
|
+
// Performance: an idle spare must not keep a background session alive or hold a process forever.
|
|
54
|
+
const timer = setTimeout(() => { if (this.#spare?.child === child)
|
|
55
|
+
this.#discard(); }, this.#idleMs);
|
|
56
|
+
timer.unref();
|
|
57
|
+
child.on("message", onMessage);
|
|
58
|
+
child.once("exit", onExit);
|
|
59
|
+
child.once("close", onExit);
|
|
60
|
+
child.once("error", onExit);
|
|
61
|
+
// Invariant: an idle spare never keeps the owner's process alive; taking it refs it again.
|
|
62
|
+
child.unref();
|
|
63
|
+
child.channel?.unref();
|
|
64
|
+
this.#spare = { child, ready: false, timer, detach };
|
|
65
|
+
}
|
|
66
|
+
/** Hands the spare to a request, with the pool's listeners removed; returns nothing when no live spare is held. */
|
|
67
|
+
take() {
|
|
68
|
+
const spare = this.#spare;
|
|
69
|
+
if (spare === undefined)
|
|
70
|
+
return undefined;
|
|
71
|
+
this.#drop();
|
|
72
|
+
if (spare.child.exitCode !== null || spare.child.signalCode !== null || !spare.child.connected)
|
|
73
|
+
return undefined;
|
|
74
|
+
spare.child.ref();
|
|
75
|
+
spare.child.channel?.ref();
|
|
76
|
+
return { child: spare.child, ready: spare.ready };
|
|
77
|
+
}
|
|
78
|
+
/** Stops the held spare and refuses further warming. */
|
|
79
|
+
dispose() {
|
|
80
|
+
this.#disposed = true;
|
|
81
|
+
this.#discard();
|
|
82
|
+
}
|
|
83
|
+
#drop() {
|
|
84
|
+
const spare = this.#spare;
|
|
85
|
+
if (spare === undefined)
|
|
86
|
+
return;
|
|
87
|
+
this.#spare = undefined;
|
|
88
|
+
clearTimeout(spare.timer);
|
|
89
|
+
spare.detach();
|
|
90
|
+
}
|
|
91
|
+
#discard() {
|
|
92
|
+
const spare = this.#spare;
|
|
93
|
+
if (spare === undefined)
|
|
94
|
+
return;
|
|
95
|
+
this.#drop();
|
|
96
|
+
this.#stop(spare.child);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PiShellClipboardContent } from "
|
|
1
|
+
import type { PiShellClipboardContent } from "../../integrations/pi/components/index.js";
|
|
2
2
|
import type { ImagePreparationLimits, PreparedImage } from "./image-preparation.js";
|
|
3
3
|
import type { ImageWorkerRequest } from "./image-worker.js";
|
|
4
4
|
export type PreparedClipboardContent = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Worker } from "node:worker_threads";
|
|
2
|
-
import { ImageAttachmentError } from "
|
|
2
|
+
import { ImageAttachmentError } from "../../contracts/owned-ui/index.js";
|
|
3
3
|
import { IMAGE_PREPARATION_MS, MAX_SOURCE_IMAGE_BYTES } from "./image-source.js";
|
|
4
4
|
/** Owns bounded paste acquisition and one off-thread conversion, canceled on session disposal. */
|
|
5
5
|
export class ImagePreparationClient {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isMainThread } from "node:worker_threads";
|
|
2
|
-
import { ImageAttachmentError } from "
|
|
2
|
+
import { ImageAttachmentError } from "../../contracts/owned-ui/index.js";
|
|
3
3
|
import { canonicalizeClipboardImage } from "./clipboard-image.js";
|
|
4
4
|
import { sourceImageInfo } from "./image-source.js";
|
|
5
5
|
export const IMAGE_TARGET_BASE64_BYTES = 4.5 * 1024 * 1024;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ImageAttachmentError } from "
|
|
1
|
+
import { ImageAttachmentError } from "../../contracts/owned-ui/index.js";
|
|
2
2
|
export const MAX_SOURCE_IMAGE_BYTES = 20 * 1024 * 1024;
|
|
3
3
|
export const MAX_SOURCE_PIXELS = 40_000_000;
|
|
4
4
|
export const MAX_SOURCE_DIMENSION = 32_768;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parentPort, workerData } from "node:worker_threads";
|
|
2
|
-
import { ImageAttachmentError } from "
|
|
2
|
+
import { ImageAttachmentError } from "../../contracts/owned-ui/index.js";
|
|
3
3
|
import { prepareImage } from "./image-preparation.js";
|
|
4
4
|
import { canonicalizeClipboardImage } from "./clipboard-image.js";
|
|
5
5
|
import { readSystemClipboardContent } from "./system-clipboard.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { ClipboardDiagnosticCapture } from "./clipboard-diagnostics.js";
|
|
2
|
+
export { ContextualPromptSuggestionController, samePromptSuggestionIdentity } from "./prompt-suggestion-controller.js";
|
|
3
|
+
export type { ContextualPromptSuggestionControllerOptions, ContextualPromptSuggestionSurface } from "./prompt-suggestion-controller.js";
|
|
4
|
+
export { OwnedUiSessionShell, OwnedUiSessionShellRoot, formatSessionResumeCommand, quoteCommandArgument } from "./session-shell.js";
|
|
5
|
+
export type { OwnedUiSessionShellOptions, OwnedUiShellDiagnosticOptions, OwnedUiShellEngineOptions, OwnedUiShellHistoryOptions, OwnedUiShellPresentationOptions, OwnedUiShellSuggestionOptions, SessionResumeCommandMetadata, } from "./session-shell.js";
|
|
6
|
+
export { STREAM_PRESENTATION_INTERVAL_MS, StreamPresentationCoalescer } from "./stream-presentation-coalescer.js";
|
|
7
|
+
export type { StreamPresentationScheduler } from "./stream-presentation-coalescer.js";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { ClipboardDiagnosticCapture } from "./clipboard-diagnostics.js";
|
|
2
|
+
export { ContextualPromptSuggestionController, samePromptSuggestionIdentity } from "./prompt-suggestion-controller.js";
|
|
3
|
+
export { OwnedUiSessionShell, OwnedUiSessionShellRoot, formatSessionResumeCommand, quoteCommandArgument } from "./session-shell.js";
|
|
4
|
+
export { STREAM_PRESENTATION_INTERVAL_MS, StreamPresentationCoalescer } from "./stream-presentation-coalescer.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ChildProcess } from "node:child_process";
|
|
2
|
+
import type { PiShellClipboardContent } from "../../integrations/pi/components/shell-shared-facade.js";
|
|
3
|
+
import { type PreparedPaste, type PasteEvent } from "./paste-protocol.js";
|
|
4
|
+
import { HelperPool } from "./helper-pool.js";
|
|
5
|
+
export interface PasteExecutorJob {
|
|
6
|
+
readonly result: Promise<PreparedPaste>;
|
|
7
|
+
readonly stopped: Promise<void>;
|
|
8
|
+
cancel(): void;
|
|
9
|
+
}
|
|
10
|
+
export type PastePhase = (phase: PasteEvent["phase"], bytes?: number) => void;
|
|
11
|
+
/** Forks one paste helper: no inherited descriptors, JSON IPC only, and its own process group on POSIX. */
|
|
12
|
+
export declare function forkPasteHelper(helper?: URL): ChildProcess;
|
|
13
|
+
/** Kills a paste helper and everything it spawned, then lets the parent exit without waiting for it. */
|
|
14
|
+
export declare function stopPasteHelper(child: ChildProcess): void;
|
|
15
|
+
/** A spare-of-one pool of paste helpers; `startPasteExecutor` takes its child and warms the next one after each paste. */
|
|
16
|
+
export declare function createPasteHelperPool(helper?: URL, idleMs?: number): HelperPool;
|
|
17
|
+
/** Streams bounded fragments through a killable child; native/codec/filesystem work never runs on the UI thread. */
|
|
18
|
+
export declare function startPasteExecutor(content: PiShellClipboardContent | undefined, signal: AbortSignal, phase?: PastePhase, helper?: URL, pool?: HelperPool): PasteExecutorJob;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { fork } from "node:child_process";
|
|
2
|
-
import { ImageAttachmentError } from "
|
|
2
|
+
import { ImageAttachmentError } from "../../contracts/owned-ui/index.js";
|
|
3
3
|
import { MAX_SOURCE_IMAGE_BYTES } from "./image-source.js";
|
|
4
4
|
import { PASTE_CHUNK_UNITS, PASTE_REQUESTS, PASTE_STOP_MS, PASTE_TEXT_BYTES, pasteFragments } from "./paste-protocol.js";
|
|
5
|
+
import { HelperPool } from "./helper-pool.js";
|
|
5
6
|
const live = new Set();
|
|
6
7
|
const conversionQueue = [];
|
|
7
8
|
let converting;
|
|
@@ -18,14 +19,8 @@ function permitConversion() {
|
|
|
18
19
|
converting = child;
|
|
19
20
|
child.send({ kind: "convert" }, () => { });
|
|
20
21
|
}
|
|
21
|
-
/**
|
|
22
|
-
export function
|
|
23
|
-
const tooLarge = content?.kind === "text" && content.text.length > PASTE_TEXT_BYTES;
|
|
24
|
-
if (signal.aborted || live.size >= PASTE_REQUESTS || tooLarge) {
|
|
25
|
-
const result = Promise.reject(new ImageAttachmentError(signal.aborted ? "image-canceled" : tooLarge ? "paste-size" : "paste-busy"));
|
|
26
|
-
void result.catch(() => { });
|
|
27
|
-
return { result, stopped: Promise.resolve(), cancel() { } };
|
|
28
|
-
}
|
|
22
|
+
/** Forks one paste helper: no inherited descriptors, JSON IPC only, and its own process group on POSIX. */
|
|
23
|
+
export function forkPasteHelper(helper) {
|
|
29
24
|
const source = new URL(import.meta.url).pathname.endsWith(".ts");
|
|
30
25
|
const entry = helper ?? new URL(source ? "./paste-helper.ts" : "./paste-helper.js", import.meta.url);
|
|
31
26
|
const options = {
|
|
@@ -33,22 +28,40 @@ export function startPasteExecutor(content, signal, phase = () => { }, helper) {
|
|
|
33
28
|
stdio: ["ignore", "ignore", "ignore", "ipc"], serialization: "json", windowsHide: true,
|
|
34
29
|
detached: process.platform !== "win32",
|
|
35
30
|
};
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
child.kill("SIGKILL");
|
|
45
|
-
}
|
|
31
|
+
return fork(entry, [], options);
|
|
32
|
+
}
|
|
33
|
+
/** Kills a paste helper and everything it spawned, then lets the parent exit without waiting for it. */
|
|
34
|
+
export function stopPasteHelper(child) {
|
|
35
|
+
// Concurrency: POSIX command fallbacks share this isolated process group; kill descendants too.
|
|
36
|
+
if (process.platform !== "win32" && child.pid !== undefined) {
|
|
37
|
+
try {
|
|
38
|
+
process.kill(-child.pid, "SIGKILL");
|
|
46
39
|
}
|
|
47
|
-
|
|
40
|
+
catch {
|
|
48
41
|
child.kill("SIGKILL");
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else
|
|
45
|
+
child.kill("SIGKILL");
|
|
46
|
+
child.unref();
|
|
47
|
+
child.channel?.unref();
|
|
48
|
+
}
|
|
49
|
+
/** A spare-of-one pool of paste helpers; `startPasteExecutor` takes its child and warms the next one after each paste. */
|
|
50
|
+
export function createPasteHelperPool(helper, idleMs) {
|
|
51
|
+
return new HelperPool({ fork: () => forkPasteHelper(helper), stop: stopPasteHelper, ...(idleMs === undefined ? {} : { idleMs }) });
|
|
52
|
+
}
|
|
53
|
+
/** Streams bounded fragments through a killable child; native/codec/filesystem work never runs on the UI thread. */
|
|
54
|
+
export function startPasteExecutor(content, signal, phase = () => { }, helper, pool) {
|
|
55
|
+
const tooLarge = content?.kind === "text" && content.text.length > PASTE_TEXT_BYTES;
|
|
56
|
+
if (signal.aborted || live.size >= PASTE_REQUESTS || tooLarge) {
|
|
57
|
+
const result = Promise.reject(new ImageAttachmentError(signal.aborted ? "image-canceled" : tooLarge ? "paste-size" : "paste-busy"));
|
|
58
|
+
void result.catch(() => { });
|
|
59
|
+
return { result, stopped: Promise.resolve(), cancel() { } };
|
|
60
|
+
}
|
|
61
|
+
// Performance: a warm spare skips fork and module load on the paste's own critical path.
|
|
62
|
+
const spare = pool?.take();
|
|
63
|
+
const child = spare?.child ?? forkPasteHelper(helper);
|
|
64
|
+
const forceStop = () => stopPasteHelper(child);
|
|
52
65
|
live.add(child);
|
|
53
66
|
let input = sourceMessages(content);
|
|
54
67
|
let canceled = false, done = false;
|
|
@@ -84,6 +97,14 @@ export function startPasteExecutor(content, signal, phase = () => { }, helper) {
|
|
|
84
97
|
stopTimer.unref();
|
|
85
98
|
};
|
|
86
99
|
const fail = (code = "paste-unavailable") => { failure = new ImageAttachmentError(code); cancel(); };
|
|
100
|
+
const advance = () => {
|
|
101
|
+
const next = input?.next();
|
|
102
|
+
if (!next || next.done) {
|
|
103
|
+
fail();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
send(next.value);
|
|
107
|
+
};
|
|
87
108
|
signal.addEventListener("abort", cancel, { once: true });
|
|
88
109
|
child.on("message", value => {
|
|
89
110
|
if (canceled)
|
|
@@ -91,12 +112,7 @@ export function startPasteExecutor(content, signal, phase = () => { }, helper) {
|
|
|
91
112
|
const message = value;
|
|
92
113
|
try {
|
|
93
114
|
if (message?.kind === "ready") {
|
|
94
|
-
|
|
95
|
-
if (!next || next.done) {
|
|
96
|
-
fail();
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
send(next.value);
|
|
115
|
+
advance();
|
|
100
116
|
}
|
|
101
117
|
else if (message?.kind === "phase") {
|
|
102
118
|
if (!["acquired-text", "acquired-image", "classifying", "path-fallback", "prepared"].includes(message.phase) || phases.has(message.phase)) {
|
|
@@ -210,9 +226,14 @@ export function startPasteExecutor(content, signal, phase = () => { }, helper) {
|
|
|
210
226
|
phase("cleanup");
|
|
211
227
|
}
|
|
212
228
|
catch { /* Invariant: cleanup observation cannot retain an exited executor. */ }
|
|
229
|
+
// Performance: the next paste finds a spare that was forked while nothing waited on it.
|
|
230
|
+
pool?.replenish();
|
|
213
231
|
};
|
|
214
232
|
child.once("exit", cleanup);
|
|
215
233
|
child.once("close", cleanup);
|
|
234
|
+
// Protocol: a spare already announced itself while pooled, so its first request is sent now rather than on "ready".
|
|
235
|
+
if (spare?.ready)
|
|
236
|
+
advance();
|
|
216
237
|
void result.catch(() => { });
|
|
217
238
|
return { result, stopped: exit, cancel };
|
|
218
239
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Worker } from "node:worker_threads";
|
|
2
|
-
import { ImageAttachmentError } from "
|
|
2
|
+
import { ImageAttachmentError } from "../../contracts/owned-ui/index.js";
|
|
3
3
|
import { readSystemClipboardContent } from "./system-clipboard.js";
|
|
4
4
|
import { MAX_SOURCE_IMAGE_BYTES } from "./image-source.js";
|
|
5
5
|
import { preparePasteText } from "./paste-text-preparation.js";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { startPasteExecutor } from "./paste-executor.js";
|
|
2
|
+
import { type PasteEvent, type PasteSource, type PreparedPaste } from "./paste-protocol.js";
|
|
3
|
+
export interface PreparedPasteJob<T> {
|
|
4
|
+
readonly result: Promise<T>;
|
|
5
|
+
cancel(): void;
|
|
6
|
+
complete(): void;
|
|
7
|
+
isCurrent(): boolean;
|
|
8
|
+
}
|
|
9
|
+
/** Starts one isolated preparation; the production starter forks the paste helper, tests may prepare in process. */
|
|
10
|
+
export type PasteExecutorStarter = typeof startPasteExecutor;
|
|
11
|
+
export interface PastePreparationClientOptions {
|
|
12
|
+
readonly onEvent?: (event: PasteEvent) => void;
|
|
13
|
+
/** Test seam: replaces the forked helper entirely; no spare is kept when it is set. */
|
|
14
|
+
readonly execute?: PasteExecutorStarter;
|
|
15
|
+
/** Package/fault-test seam for the forked helper's entry. */
|
|
16
|
+
readonly helper?: URL;
|
|
17
|
+
/** Idle bound for the spare helper; production keeps the default. */
|
|
18
|
+
readonly spareIdleMs?: number;
|
|
19
|
+
}
|
|
20
|
+
/** Keeps eight distinct paste transactions alive through insertion; canceled executors retain capacity until fenced. */
|
|
21
|
+
export declare class PastePreparationClient {
|
|
22
|
+
#private;
|
|
23
|
+
constructor(options?: PastePreparationClientOptions);
|
|
24
|
+
/** Forks the spare helper now so the first paste takes a live child; later pastes rewarm it themselves. */
|
|
25
|
+
warm(): void;
|
|
26
|
+
/** Whether a spare helper is held; diagnostics and tests only. */
|
|
27
|
+
get warmed(): boolean;
|
|
28
|
+
start<T>(source: PasteSource, adopt: (value: PreparedPaste, signal: AbortSignal) => Promise<T> | T, onImage: () => void, onText?: () => void): PreparedPasteJob<T>;
|
|
29
|
+
reset(): void;
|
|
30
|
+
dispose(): Promise<void>;
|
|
31
|
+
}
|