@timurproko/a1 0.2.6-dev.717 → 0.2.6-dev.734
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 +13 -2
- package/bin/ui.js +13 -0
- package/dist/app/session-shell/clipboard-services.d.ts +19 -0
- package/dist/app/session-shell/clipboard-services.js +7 -0
- package/dist/app/session-shell/exit-notice.d.ts +9 -5
- package/dist/app/session-shell/exit-notice.js +5 -5
- package/dist/app/session-shell/index.d.ts +3 -1
- package/dist/app/session-shell/index.js +1 -0
- package/dist/app/session-shell/paste-preparation-client.d.ts +3 -0
- package/dist/app/session-shell/paste-preparation-client.js +5 -2
- package/dist/app/session-shell/path-chip-presentation.d.ts +10 -3
- package/dist/app/session-shell/path-chip-presentation.js +48 -6
- package/dist/app/session-shell/prompt-chips.js +30 -4
- package/dist/app/session-shell/prompt-suggestion-controller.d.ts +5 -4
- package/dist/app/session-shell/prompt-suggestion-controller.js +148 -58
- package/dist/app/session-shell/quit-outro.d.ts +3 -1
- package/dist/app/session-shell/quit-outro.js +23 -8
- package/dist/app/session-shell/response-copy-transport.d.ts +6 -1
- package/dist/app/session-shell/response-copy-transport.js +8 -2
- package/dist/app/session-shell/session-shell-root.d.ts +22 -11
- package/dist/app/session-shell/session-shell-root.js +19 -12
- package/dist/app/session-shell/session-shell.d.ts +19 -21
- package/dist/app/session-shell/session-shell.js +678 -840
- package/dist/app/session-shell/session-viewport-controller.js +33 -21
- package/dist/cli/dispatch.js +5 -3
- package/dist/cli/session-context.d.ts +5 -1
- package/dist/cli/session-context.js +25 -8
- package/dist/composition/owned-ui.d.ts +23 -2
- package/dist/composition/owned-ui.js +124 -33
- package/dist/composition/session-info-reference.d.ts +2 -2
- package/dist/composition/session-info-reference.js +2 -2
- package/dist/composition/settings-route-host.js +2 -1
- package/dist/contracts/agent-engine/capability-ports.d.ts +1 -85
- package/dist/contracts/agent-engine/capability-ports.js +1 -35
- package/dist/contracts/agent-engine/index.d.ts +1 -7
- package/dist/contracts/agent-engine/index.js +0 -4
- package/dist/contracts/owned-ui/index.d.ts +9 -3
- package/dist/contracts/owned-ui/index.js +2 -1
- package/dist/contracts/owned-ui/model.d.ts +10 -0
- package/dist/contracts/owned-ui/session-backend.d.ts +119 -0
- package/dist/contracts/owned-ui/session-presenters.d.ts +55 -0
- package/dist/contracts/owned-ui/session-presenters.js +1 -0
- package/dist/contracts/owned-ui/session-workflows.d.ts +342 -0
- package/dist/contracts/owned-ui/session-workflows.js +30 -0
- package/dist/contracts/owned-ui/suggestion-diagnostics.d.ts +5 -1
- package/dist/contracts/owned-ui/suggestion-diagnostics.js +3 -1
- package/dist/contracts/owned-ui/validation.js +7 -0
- package/dist/features/launch/index.d.ts +1 -1
- package/dist/features/launch/session-context.d.ts +17 -2
- package/dist/features/launch/session-context.js +9 -5
- package/dist/features/owned-ui/settings-app.js +56 -54
- package/dist/features/prompt-suggestions/diagnostics.js +4 -1
- package/dist/foundation/lifecycle/index.d.ts +2 -2
- package/dist/foundation/lifecycle/index.js +1 -1
- package/dist/foundation/lifecycle/session-repository-context.d.ts +19 -2
- package/dist/foundation/lifecycle/session-repository-context.js +434 -66
- package/dist/foundation/process-containment/index.d.ts +1 -0
- package/dist/foundation/process-containment/index.js +1 -0
- package/dist/foundation/process-containment/native-process-inspector.d.ts +3 -0
- package/dist/foundation/process-containment/native-process-inspector.js +21 -0
- package/dist/foundation/release/bootstrap.js +1 -2
- package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
- package/dist/foundation/release/progress-palette.generated.js +2 -2
- package/dist/foundation/release/release-gc.js +1 -1
- package/dist/foundation/release/update.js +0 -4
- package/dist/foundation/startup/startup-descriptor.js +2 -2
- package/dist/foundation/storage/control-store.js +0 -12
- package/dist/integrations/pi/components/components.js +2 -18
- package/dist/integrations/pi/components/index.d.ts +4 -4
- package/dist/integrations/pi/components/index.js +2 -2
- package/dist/integrations/pi/components/modal-frame.js +3 -4
- package/dist/integrations/pi/components/models-dialog.js +6 -35
- package/dist/integrations/pi/components/prompt-input-port.d.ts +1 -0
- package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
- package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
- package/dist/integrations/pi/components/share-operation-dialog.js +3 -3
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +19 -16
- package/dist/integrations/pi/components/shell-extension-ui.d.ts +5 -3
- package/dist/integrations/pi/components/shell-extension-ui.js +26 -12
- package/dist/integrations/pi/components/shell-hotkey-sections.js +2 -2
- package/dist/integrations/pi/components/shell-presenters-info.js +10 -10
- package/dist/integrations/pi/components/shell-presenters-transcript.js +13 -13
- package/dist/integrations/pi/components/shell-selectors-dialogs.js +5 -6
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +21 -1
- package/dist/integrations/pi/components/shell-shared-facade.js +19 -3
- package/dist/integrations/pi/components/skills-dialog.js +3 -3
- package/dist/integrations/pi/components/submitted-prompt-adapter.js +2 -3
- package/dist/integrations/pi/components/theme.d.ts +9 -0
- package/dist/integrations/pi/components/theme.js +30 -0
- package/dist/integrations/pi/components/tool-result-adapter.js +6 -1
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
- package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
- package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.js +6 -6
- package/dist/integrations/pi/components/upstream/components/extension-input.js +4 -4
- package/dist/integrations/pi/components/upstream/components/extension-selector.js +4 -4
- package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +5 -5
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +8 -5
- package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +3 -3
- package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector.js +9 -9
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +3 -2
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +6 -3
- package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.js +2 -2
- package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +4 -0
- package/dist/integrations/pi/components/upstream/components/tool-execution.js +11 -1
- package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +2 -2
- package/dist/integrations/pi/components/upstream/components/tree-selector.js +27 -18
- package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +4 -4
- package/dist/integrations/pi/components/upstream/history/editor-core.js +11 -7
- package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
- package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
- package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
- package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
- package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +31 -0
- package/dist/integrations/pi/components/upstream/program-status-reporter.js +89 -0
- package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme.d.ts +22 -1
- package/dist/integrations/pi/components/upstream/theme/theme.js +225 -10
- package/dist/integrations/pi/engine/adapter.d.ts +44 -24
- package/dist/integrations/pi/engine/adapter.js +130 -22
- package/dist/integrations/pi/engine/command-dispatch.d.ts +2 -5
- package/dist/integrations/pi/engine/extension-ui-binding.d.ts +2 -11
- package/dist/integrations/pi/engine/host-ports.d.ts +20 -0
- package/dist/integrations/pi/engine/host-ports.js +13 -0
- package/dist/integrations/pi/engine/host.d.ts +70 -0
- package/dist/integrations/pi/engine/host.js +147 -0
- package/dist/integrations/pi/engine/index.d.ts +8 -4
- package/dist/integrations/pi/engine/index.js +3 -1
- package/dist/integrations/pi/engine/pi-settings-metadata.json +1 -1
- package/dist/integrations/pi/engine/resource-catalog.d.ts +4 -23
- package/dist/integrations/pi/engine/resources/changelog.json +4 -4
- package/dist/integrations/pi/engine/runtime-integration.d.ts +8 -2
- package/dist/integrations/pi/engine/runtime-integration.js +12 -7
- package/dist/integrations/pi/engine/session-events.js +10 -2
- package/dist/integrations/pi/engine/session-integration.d.ts +3 -8
- package/dist/integrations/pi/engine/session-integration.js +0 -49
- package/dist/integrations/pi/engine/session-runtime.d.ts +18 -3
- package/dist/integrations/pi/engine/session-runtime.js +18 -7
- package/dist/integrations/pi/engine/settings-bridge.d.ts +2 -2
- package/dist/integrations/pi/engine/settings-bridge.js +0 -2
- package/dist/integrations/pi/engine/settings-port.d.ts +2 -0
- package/dist/integrations/pi/engine/settings-port.js +3 -5
- package/dist/integrations/pi/engine/transcript-projection.js +2 -1
- package/dist/integrations/pi/engine/workflows.d.ts +33 -260
- package/dist/integrations/pi/engine/workflows.js +6 -28
- package/dist/integrations/pi/session-presenters/index.d.ts +2 -0
- package/dist/integrations/pi/session-presenters/index.js +1 -0
- package/dist/integrations/pi/session-presenters/presenters.d.ts +16 -0
- package/dist/integrations/pi/session-presenters/presenters.js +341 -0
- package/dist/integrations/pi/startup-public.js +306 -290
- package/dist/integrations/pi/startup-public.manifest.json +289 -265
- package/dist/integrations/pi/tui-runtime/adapter.d.ts +2 -1
- package/dist/integrations/pi/tui-runtime/adapter.js +7 -2
- package/dist/integrations/pi/tui-runtime/contracts.d.ts +3 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +8 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +67 -2
- package/dist/integrations/pi/tui-runtime/index.d.ts +1 -1
- package/dist/integrations/pi/tui-runtime/index.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/product-identity.d.ts +2 -2
- package/dist/product-identity.js +2 -2
- package/dist/product-identity.json +3 -1
- package/dist/runtime-payload-inventory.json +3092 -2878
- package/dist/ui/components/prompt-input.d.ts +2 -0
- package/dist/ui/components/prompt-input.js +5 -1
- package/dist/ui/components/text-selection.d.ts +1 -1
- package/dist/ui/components/text-selection.js +3 -1
- package/dist/ui/components/theme.d.ts +2 -0
- package/dist/ui/components/transcript-viewport.d.ts +6 -4
- package/dist/ui/components/transcript-viewport.js +94 -16
- package/dist/ui/components/value-menu.d.ts +2 -0
- package/dist/ui/components/value-menu.js +13 -8
- package/dist/ui/settings/declarations.d.ts +38 -14
- package/dist/ui/settings/declarations.js +35 -11
- package/dist/ui/settings/migrations.js +23 -0
- package/docs/architecture/boundaries.md +9 -1
- package/docs/architecture/project-structure.md +7 -5
- package/docs/architecture/prompt-suggestions.md +14 -10
- package/docs/local-worktree-cleanup.md +11 -5
- package/docs/openspec-archive-automation.md +6 -5
- package/package.json +3 -3
- package/dist/contracts/agent-engine/model.d.ts +0 -78
- package/dist/contracts/agent-engine/model.js +0 -1
- package/dist/contracts/agent-engine/ports.d.ts +0 -18
- package/dist/contracts/agent-engine/serialization.d.ts +0 -7
- package/dist/contracts/agent-engine/serialization.js +0 -58
- package/dist/contracts/agent-engine/validation.d.ts +0 -5
- package/dist/contracts/agent-engine/validation.js +0 -128
- package/dist/integrations/pi/components/upstream/theme/system-theme.d.ts +0 -61
- package/dist/integrations/pi/components/upstream/theme/system-theme.js +0 -709
- /package/dist/contracts/{agent-engine/ports.js → owned-ui/session-backend.js} +0 -0
|
@@ -306,14 +306,14 @@ export class SessionViewportController {
|
|
|
306
306
|
if (this.#viewport.clearSelection())
|
|
307
307
|
this.#requestRender();
|
|
308
308
|
}
|
|
309
|
-
else {
|
|
309
|
+
else if (this.#viewport.hasSelection) {
|
|
310
310
|
const copySelection = this.#viewport.captureSelectedText();
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
311
|
+
this.#viewport.clearSelection();
|
|
312
|
+
this.#stopSelectionAutoScroll();
|
|
313
|
+
this.#requestRender();
|
|
314
|
+
return copySelection === null
|
|
315
|
+
? { data: "", consumed: true }
|
|
316
|
+
: { data: "", consumed: true, copySelection };
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
319
|
const previousPrompt = SHIFT_UP_INPUTS.has(data) || this.#editor.matchesTerminalKey(data, "alt+home");
|
|
@@ -412,12 +412,19 @@ export class SessionViewportController {
|
|
|
412
412
|
}
|
|
413
413
|
if (this.#dockPointerSuppressed || this.#tailPointerSuppressed)
|
|
414
414
|
return true;
|
|
415
|
+
const pendingEditorClick = this.#pendingEditorClick;
|
|
416
|
+
if (pendingEditorClick !== undefined) {
|
|
417
|
+
if (event.column === pendingEditorClick.column && event.row === pendingEditorClick.row)
|
|
418
|
+
return true;
|
|
419
|
+
this.#pendingEditorClick = undefined;
|
|
420
|
+
this.#viewport.pressSelection(pendingEditorClick.column, pendingEditorClick.row, now, { continueMultiClick: false });
|
|
421
|
+
this.#viewport.extendSelection(event.column, event.row, now, false);
|
|
422
|
+
this.#updateSelectionAutoScroll(event.column, event.row, hits.viewportHeight, frame.rows.length);
|
|
423
|
+
activity = true;
|
|
424
|
+
return true;
|
|
425
|
+
}
|
|
415
426
|
if (this.#viewport.selectionActive) {
|
|
416
427
|
this.#viewport.extendSelection(event.column, event.row, now, false);
|
|
417
|
-
if (this.#pendingEditorClick !== undefined
|
|
418
|
-
&& (event.column !== this.#pendingEditorClick.column || event.row !== this.#pendingEditorClick.row)) {
|
|
419
|
-
this.#pendingEditorClick = undefined;
|
|
420
|
-
}
|
|
421
428
|
this.#updateSelectionAutoScroll(event.column, event.row, hits.viewportHeight, frame.rows.length);
|
|
422
429
|
activity = true;
|
|
423
430
|
return true;
|
|
@@ -500,11 +507,13 @@ export class SessionViewportController {
|
|
|
500
507
|
}
|
|
501
508
|
if (event.row >= 1 && event.row <= frame.rows.length && event.column <= frame.descriptor.width) {
|
|
502
509
|
if (editorFrame !== undefined && event.row >= editorFrame.rowStart && event.row <= editorFrame.rowEnd) {
|
|
510
|
+
// Invariant: no-drag prompt clicks remain visually editor-owned. Distinct
|
|
511
|
+
// motion promotes from this exact origin into complete-frame selection.
|
|
503
512
|
this.#pendingEditorClick = { column: event.column, row: event.row };
|
|
504
513
|
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
514
|
+
else {
|
|
515
|
+
this.#viewport.pressSelection(event.column, event.row, now);
|
|
516
|
+
}
|
|
508
517
|
repaint = true;
|
|
509
518
|
return true;
|
|
510
519
|
}
|
|
@@ -525,19 +534,22 @@ export class SessionViewportController {
|
|
|
525
534
|
repaint = true;
|
|
526
535
|
return true;
|
|
527
536
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
const pendingEditorClick = this.#pendingEditorClick;
|
|
537
|
+
const pendingEditorClick = this.#pendingEditorClick;
|
|
538
|
+
if (pendingEditorClick !== undefined) {
|
|
531
539
|
this.#pendingEditorClick = undefined;
|
|
532
|
-
if (
|
|
533
|
-
this.#viewport.clearSelection();
|
|
540
|
+
if (this.#editorPointerFrame !== undefined) {
|
|
534
541
|
const editorRow = pendingEditorClick.row - this.#editorPointerFrame.rowStart + 1;
|
|
535
542
|
this.#editor.handlePointer({ kind: "press", button: 0, column: pendingEditorClick.column, row: editorRow });
|
|
536
543
|
this.#editor.handlePointer({ kind: "release", button: 0, column: pendingEditorClick.column, row: editorRow });
|
|
537
544
|
}
|
|
538
|
-
|
|
545
|
+
forceRepaint = true;
|
|
546
|
+
repaint = true;
|
|
547
|
+
return true;
|
|
548
|
+
}
|
|
549
|
+
if (this.#viewport.releaseSelection()) {
|
|
550
|
+
this.#stopSelectionAutoScroll();
|
|
551
|
+
if (this.#copyOnSelect)
|
|
539
552
|
completedCopy = this.#viewport.captureSelectedText() ?? undefined;
|
|
540
|
-
}
|
|
541
553
|
// Platform: restore OSC 8 links only after the held-button selection paint has
|
|
542
554
|
// ended, then overwrite any terminal-cached hover cells immediately.
|
|
543
555
|
forceRepaint = true;
|
package/dist/cli/dispatch.js
CHANGED
|
@@ -18,6 +18,7 @@ export function cliUsage(capabilities) {
|
|
|
18
18
|
"remove <source>",
|
|
19
19
|
"uninstall <source>",
|
|
20
20
|
"list",
|
|
21
|
+
"session worktrees",
|
|
21
22
|
"session link-worktree <path>",
|
|
22
23
|
"session unlink-worktree",
|
|
23
24
|
]);
|
|
@@ -47,6 +48,7 @@ export function cliHelp(capabilities) {
|
|
|
47
48
|
` ${command} list`,
|
|
48
49
|
"",
|
|
49
50
|
"Session context:",
|
|
51
|
+
` ${command} session worktrees`,
|
|
50
52
|
` ${command} session link-worktree <path>`,
|
|
51
53
|
` ${command} session unlink-worktree`,
|
|
52
54
|
"",
|
|
@@ -127,12 +129,12 @@ function parseSessionContext(rest) {
|
|
|
127
129
|
return { kind: "error", message: PRODUCT_TEXT.diagnostic("session link-worktree accepts one path.") };
|
|
128
130
|
return { kind: "session-context", request: { action, path: value } };
|
|
129
131
|
}
|
|
130
|
-
if (action === "unlink-worktree") {
|
|
132
|
+
if (action === "unlink-worktree" || action === "worktrees") {
|
|
131
133
|
if (value !== undefined)
|
|
132
|
-
return { kind: "error", message: PRODUCT_TEXT.diagnostic(
|
|
134
|
+
return { kind: "error", message: PRODUCT_TEXT.diagnostic(`session ${action} does not accept arguments.`) };
|
|
133
135
|
return { kind: "session-context", request: { action } };
|
|
134
136
|
}
|
|
135
|
-
return { kind: "error", message: PRODUCT_TEXT.diagnostic("session accepts link-worktree <path
|
|
137
|
+
return { kind: "error", message: PRODUCT_TEXT.diagnostic("session accepts worktrees, link-worktree <path>, or unlink-worktree.") };
|
|
136
138
|
}
|
|
137
139
|
/**
|
|
138
140
|
* Stable update is the empty form. `--develop` selects the moving development
|
|
@@ -2,8 +2,12 @@ import { type SessionContextRequest } from "../features/launch/index.js";
|
|
|
2
2
|
export type { SessionContextRequest } from "../features/launch/index.js";
|
|
3
3
|
export interface SessionContextCommandOptions {
|
|
4
4
|
readonly environment?: NodeJS.ProcessEnv;
|
|
5
|
+
readonly inspectProcess?: (pid: number) => Promise<{
|
|
6
|
+
readonly pid: number;
|
|
7
|
+
readonly startIdentity: string;
|
|
8
|
+
} | null>;
|
|
5
9
|
readonly stdout?: (message: string) => void;
|
|
6
10
|
readonly stderr?: (message: string) => void;
|
|
7
11
|
}
|
|
8
|
-
/** Apply repository
|
|
12
|
+
/** Apply repository context only when invoked by an exact live A1 shell-tool runtime. */
|
|
9
13
|
export declare function runSessionContextCommand(request: SessionContextRequest, options?: SessionContextCommandOptions): Promise<number>;
|
|
@@ -1,29 +1,46 @@
|
|
|
1
1
|
import { updateSessionRepositoryContext, } from "../features/launch/index.js";
|
|
2
|
-
import { PRODUCT_TEXT } from "../product-identity.js";
|
|
3
|
-
/** Apply repository
|
|
2
|
+
import { PRODUCT_IDENTITY, PRODUCT_TEXT } from "../product-identity.js";
|
|
3
|
+
/** Apply repository context only when invoked by an exact live A1 shell-tool runtime. */
|
|
4
4
|
export async function runSessionContextCommand(request, options = {}) {
|
|
5
5
|
const environment = options.environment ?? process.env;
|
|
6
6
|
const stdout = options.stdout ?? (message => process.stdout.write(message));
|
|
7
7
|
const stderr = options.stderr ?? (message => process.stderr.write(message));
|
|
8
8
|
const identity = readIdentity(environment);
|
|
9
9
|
if (identity === null) {
|
|
10
|
-
stderr(`${PRODUCT_TEXT.diagnostic("session context requires an active A1 shell-tool session.")}\n`);
|
|
10
|
+
stderr(`${PRODUCT_TEXT.diagnostic("session context requires an active A1 shell-tool session runtime.")}\n`);
|
|
11
11
|
return 2;
|
|
12
12
|
}
|
|
13
13
|
try {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
if (options.inspectProcess === undefined)
|
|
15
|
+
throw Object.assign(new Error("native process identity inspection is unavailable"), { code: "process-inspection-unavailable" });
|
|
16
|
+
const outcome = await updateSessionRepositoryContext({ sessionId: identity.sessionId, sessionFile: identity.sessionFile }, request, { runtimeId: identity.runtimeId, inspectProcess: options.inspectProcess });
|
|
17
|
+
if (outcome.kind === "unlinked")
|
|
18
|
+
stdout("Session worktree context cleared.\n");
|
|
19
|
+
if (outcome.kind === "linked")
|
|
20
|
+
stdout(`Session worktree context linked: ${outcome.cwd}\n`);
|
|
21
|
+
if (outcome.kind === "worktrees") {
|
|
22
|
+
for (const entry of outcome.entries)
|
|
23
|
+
stdout(`${entry.status}: ${entry.cwd} (${entry.branch})\n`);
|
|
24
|
+
}
|
|
16
25
|
return 0;
|
|
17
26
|
}
|
|
18
27
|
catch (error) {
|
|
19
|
-
|
|
28
|
+
const code = errorCode(error);
|
|
29
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
30
|
+
stderr(`${PRODUCT_TEXT.diagnostic(`could not update session context${code === null ? "" : ` (${code})`}: ${detail}`)}\n`);
|
|
20
31
|
return 1;
|
|
21
32
|
}
|
|
22
33
|
}
|
|
23
34
|
function readIdentity(environment) {
|
|
24
35
|
const sessionId = environment.PI_SESSION_ID;
|
|
25
36
|
const sessionFile = environment.PI_SESSION_FILE;
|
|
26
|
-
|
|
37
|
+
const runtimeId = environment[PRODUCT_IDENTITY.environment.sessionRuntimeId];
|
|
38
|
+
if (!sessionId || !sessionFile || !runtimeId)
|
|
27
39
|
return null;
|
|
28
|
-
return { sessionId, sessionFile };
|
|
40
|
+
return { sessionId, sessionFile, runtimeId };
|
|
41
|
+
}
|
|
42
|
+
function errorCode(error) {
|
|
43
|
+
if (error instanceof Error && "code" in error && typeof error.code === "string")
|
|
44
|
+
return error.code;
|
|
45
|
+
return null;
|
|
29
46
|
}
|
|
@@ -1,15 +1,34 @@
|
|
|
1
1
|
import type { AvailableRelease, StartupReleaseCheckOptions } from "../foundation/release/latest-release.js";
|
|
2
|
+
import type { NativeProcessIdentity } from "../foundation/lifecycle/model.js";
|
|
2
3
|
import type { SessionSelection } from "../foundation/lifecycle/session-selection.js";
|
|
3
|
-
import type
|
|
4
|
+
import { type PiEngineHostOptions, type PiEngineSessionRequest } from "../integrations/pi/engine/host.js";
|
|
5
|
+
import { type PiSessionPresenterBackend } from "../integrations/pi/session-presenters/index.js";
|
|
4
6
|
import type { PiProjectTrustPreflightPrompt } from "../integrations/pi/engine/project-trust-preflight.js";
|
|
5
7
|
import type { PiSessionForkPrompt } from "../integrations/pi/engine/session-selection.js";
|
|
6
8
|
import { OwnedSettingsManager } from "../ui/settings/manager.js";
|
|
7
9
|
import type { OwnedUiApplicationPort, PresentationTerminalPort } from "../contracts/presentation/index.js";
|
|
10
|
+
import type { AgentSettingsPort } from "../contracts/agent-engine/index.js";
|
|
11
|
+
import type { OwnedUiPromptSuggestionGeneratorPort, UiAccentColor } from "../contracts/owned-ui/index.js";
|
|
8
12
|
import type { ReleaseNoteCatalog } from "../features/owned-ui/release-notes.js";
|
|
13
|
+
/**
|
|
14
|
+
* The session backend composition wires: the owned-UI port, the prompt-suggestion generator, and
|
|
15
|
+
* the agent settings port. `settingsPort` stays outside the owned-UI contract because its type
|
|
16
|
+
* belongs to the agent-engine contracts, which the owned-UI contract may not import.
|
|
17
|
+
*/
|
|
18
|
+
export interface ComposedSessionBackend extends PiSessionPresenterBackend, OwnedUiPromptSuggestionGeneratorPort {
|
|
19
|
+
settingsPort(): AgentSettingsPort | null;
|
|
20
|
+
}
|
|
21
|
+
/** The process-level engine host as composition drives it: sessions, the live accent, and disposal. */
|
|
22
|
+
export interface ComposedEngineHost {
|
|
23
|
+
create(request: PiEngineSessionRequest): Promise<ComposedSessionBackend>;
|
|
24
|
+
setAccentColor(color: UiAccentColor): void;
|
|
25
|
+
dispose(): Promise<void>;
|
|
26
|
+
}
|
|
9
27
|
export interface OwnedUiCompositionOptions {
|
|
10
28
|
readonly cwd?: string;
|
|
11
29
|
readonly terminal?: PresentationTerminalPort;
|
|
12
|
-
|
|
30
|
+
/** Test seam standing in for the Pi engine host; receives the options composition resolved. */
|
|
31
|
+
readonly createEngineHost?: (options: PiEngineHostOptions) => Promise<ComposedEngineHost>;
|
|
13
32
|
/** Explicit file selection retained for SDK callers. Public CLI uses sessionSelection. */
|
|
14
33
|
readonly sessionPath?: string;
|
|
15
34
|
readonly sessionSelection?: SessionSelection;
|
|
@@ -34,6 +53,8 @@ export interface OwnedUiCompositionOptions {
|
|
|
34
53
|
readonly releaseNotes?: ReleaseNoteCatalog;
|
|
35
54
|
/** Startup release-availability seam; defaults to the throttled registry check. */
|
|
36
55
|
readonly checkForNewerRelease?: (options: StartupReleaseCheckOptions) => Promise<AvailableRelease | null>;
|
|
56
|
+
/** Exact native process inspection injected by the shipped entry; absent SDK seams do not publish claims. */
|
|
57
|
+
readonly inspectProcess?: (pid: number) => Promise<NativeProcessIdentity | null>;
|
|
37
58
|
}
|
|
38
59
|
export interface OwnedUiComposition {
|
|
39
60
|
readonly application: OwnedUiApplicationPort;
|
|
@@ -6,47 +6,108 @@ import { PromptImageSidecar } from "../features/prompt-history/image-sidecar.js"
|
|
|
6
6
|
import { resolvePromptHistoryPath } from "../features/prompt-history/paths.js";
|
|
7
7
|
import { resolvePromptHistoryDataDir } from "../features/launch/profile-paths.js";
|
|
8
8
|
import { resolveProductPaths } from "../foundation/lifecycle/paths.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { applyConfiguredPiTheme, getAvailablePiThemes, setPiAccentColor, setPiPackageBorderProjectionEnabled } from "../integrations/pi/components/upstream/theme/theme.js";
|
|
10
|
+
import { createPiEngineHost } from "../integrations/pi/engine/host.js";
|
|
11
|
+
import { createPiSessionPresenters } from "../integrations/pi/session-presenters/index.js";
|
|
12
12
|
import { ClipboardDiagnosticCapture } from "../app/session-shell/clipboard-diagnostics.js";
|
|
13
|
+
import { createOwnedUiClipboardServices } from "../app/session-shell/clipboard-services.js";
|
|
14
|
+
import { createPiKeybindingsHost } from "../integrations/pi/components/shell-shared-facade.js";
|
|
13
15
|
import { OwnedUiSessionShell } from "../app/session-shell/session-shell.js";
|
|
14
16
|
import { OwnedSettingsManager } from "../ui/settings/manager.js";
|
|
15
17
|
import { createPiTerminalBridge } from "../integrations/pi/tui-runtime/presentation-adapter.js";
|
|
16
18
|
import { createOwnedRouteHost } from "./settings-route-host.js";
|
|
17
19
|
import { renderPiShellChangelogLines } from "../integrations/pi/components/shell-presenters-info.js";
|
|
18
20
|
import { nativeHyperlinkStyle } from "../ui/components/spans.js";
|
|
21
|
+
const SESSION_RUNTIME_REFRESH_MS = 30_000;
|
|
19
22
|
export async function composeOwnedUiApplication(options = {}) {
|
|
20
23
|
return (await composeOwnedUi(options)).application;
|
|
21
24
|
}
|
|
22
25
|
export async function composeOwnedUi(options = {}) {
|
|
23
26
|
const cwd = options.cwd ?? process.cwd();
|
|
24
27
|
const ownedSurfaces = options.ownedSurfaces !== "off";
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
const sessionRuntimeId = ownedSurfaces ? process.env[PRODUCT_IDENTITY.environment.sessionRuntimeId] : undefined;
|
|
29
|
+
const inspectSessionProcess = options.inspectProcess;
|
|
30
|
+
let sessionRuntimeIdentity = null;
|
|
31
|
+
let activeSessionIdentity = null;
|
|
32
|
+
let sessionRuntimeRefreshTimer = null;
|
|
33
|
+
let sessionRuntimeRefresh = Promise.resolve();
|
|
34
|
+
let sessionRuntimeDisposed = false;
|
|
35
|
+
const runtimeIdentity = async () => {
|
|
36
|
+
if (sessionRuntimeId === undefined || inspectSessionProcess === undefined)
|
|
37
|
+
return null;
|
|
38
|
+
sessionRuntimeIdentity ??= inspectSessionProcess(process.pid).catch(() => null);
|
|
39
|
+
return await sessionRuntimeIdentity;
|
|
40
|
+
};
|
|
41
|
+
const queueSessionRuntimeRefresh = () => {
|
|
42
|
+
if (sessionRuntimeDisposed || activeSessionIdentity === null || sessionRuntimeId === undefined || inspectSessionProcess === undefined)
|
|
43
|
+
return;
|
|
44
|
+
sessionRuntimeRefresh = sessionRuntimeRefresh.then(async () => {
|
|
45
|
+
const identity = activeSessionIdentity;
|
|
46
|
+
if (sessionRuntimeDisposed || identity === null)
|
|
47
|
+
return;
|
|
48
|
+
const owner = await runtimeIdentity();
|
|
49
|
+
if (owner === null)
|
|
50
|
+
return;
|
|
51
|
+
const { registerSessionRepositoryRuntime } = await import("../foundation/lifecycle/session-repository-context.js");
|
|
52
|
+
await registerSessionRepositoryRuntime(identity, sessionRuntimeId, owner, { inspectProcess: inspectSessionProcess });
|
|
53
|
+
}).catch(() => undefined);
|
|
54
|
+
};
|
|
55
|
+
const armSessionRuntimeRefresh = () => {
|
|
56
|
+
if (sessionRuntimeRefreshTimer !== null)
|
|
57
|
+
return;
|
|
58
|
+
sessionRuntimeRefreshTimer = setInterval(queueSessionRuntimeRefresh, SESSION_RUNTIME_REFRESH_MS);
|
|
59
|
+
sessionRuntimeRefreshTimer.unref();
|
|
60
|
+
};
|
|
40
61
|
const productPaths = resolveProductPaths();
|
|
62
|
+
// Rationale: the manager reads the engine's settings port lazily, after the session exists.
|
|
63
|
+
let backend;
|
|
41
64
|
const settings = options.profileId === undefined
|
|
42
65
|
? null
|
|
43
66
|
: new OwnedSettingsManager({
|
|
44
67
|
configDir: resolveProductPaths().configDir,
|
|
45
68
|
profileId: options.profileId,
|
|
46
|
-
agentProvider: () =>
|
|
69
|
+
agentProvider: () => backend.settingsPort(),
|
|
47
70
|
hiddenAgentSettingIds: ["fullscreenWheelScrollLines"],
|
|
48
71
|
agentSettingLabelOverrides: { fullscreenCopyOnSelect: "Copy on select" },
|
|
49
72
|
});
|
|
73
|
+
// Invariant: process-wide engine state has one owner. The host installs the HTTP dispatcher, applies
|
|
74
|
+
// the theme singletons, and announces startup notices once; every session is created through it.
|
|
75
|
+
const host = await (options.createEngineHost ?? (async (hostOptions) => createPiEngineHost(hostOptions)))({
|
|
76
|
+
productMode: ownedSurfaces ? "bare" : "comparison",
|
|
77
|
+
availableThemes: () => getAvailablePiThemes().map(theme => theme.name),
|
|
78
|
+
announceStartupChangelog: !ownedSurfaces,
|
|
79
|
+
theme: {
|
|
80
|
+
base: ownedSurfaces ? "dark" : "engine-configured",
|
|
81
|
+
accentColor: settings !== null && ownedSurfaces ? settings.value("accentColor") : "purple",
|
|
82
|
+
packageBorderProjection: ownedSurfaces,
|
|
83
|
+
apply: { base: applyConfiguredPiTheme, accentColor: setPiAccentColor, packageBorderProjection: setPiPackageBorderProjectionEnabled },
|
|
84
|
+
},
|
|
85
|
+
...(options.projectTrustPrompt === undefined ? {} : { projectTrustPrompt: options.projectTrustPrompt }),
|
|
86
|
+
});
|
|
87
|
+
try {
|
|
88
|
+
backend = await host.create({
|
|
89
|
+
cwd,
|
|
90
|
+
...(ownedSurfaces ? {
|
|
91
|
+
repositoryContextReader: async (sessionId, sessionFile, signal) => {
|
|
92
|
+
const owner = await runtimeIdentity();
|
|
93
|
+
if (owner === null || sessionRuntimeId === undefined || inspectSessionProcess === undefined)
|
|
94
|
+
return null;
|
|
95
|
+
activeSessionIdentity = { sessionId, sessionFile };
|
|
96
|
+
const { activateSessionRepositoryContext } = await import("../foundation/lifecycle/session-repository-context.js");
|
|
97
|
+
const context = await activateSessionRepositoryContext(activeSessionIdentity, sessionRuntimeId, owner, { signal, inspectProcess: inspectSessionProcess });
|
|
98
|
+
armSessionRuntimeRefresh();
|
|
99
|
+
return context;
|
|
100
|
+
},
|
|
101
|
+
} : {}),
|
|
102
|
+
...(options.sessionPath === undefined ? {} : { sessionPath: options.sessionPath }),
|
|
103
|
+
...(options.sessionSelection === undefined ? {} : { sessionSelection: options.sessionSelection }),
|
|
104
|
+
...(options.sessionForkPrompt === undefined ? {} : { sessionForkPrompt: options.sessionForkPrompt }),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
await host.dispose();
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
50
111
|
let releaseNotes = null;
|
|
51
112
|
let releaseNotesFailure;
|
|
52
113
|
if (ownedSurfaces) {
|
|
@@ -67,10 +128,9 @@ export async function composeOwnedUi(options = {}) {
|
|
|
67
128
|
: await import("../features/owned-ui/release-note-state.js").then(module => module.claimReleaseNote({
|
|
68
129
|
configDir: productPaths.configDir, profileId: options.profileId, version: currentReleaseNote.version,
|
|
69
130
|
}));
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
applyConfiguredPiTheme(ownedSurfaces ? "dark" : adapter.configuredTheme());
|
|
131
|
+
const unsubscribeAccent = settings === null || !ownedSurfaces
|
|
132
|
+
? () => { }
|
|
133
|
+
: settings.onChange(current => host.setAccentColor(current.value("accentColor")));
|
|
74
134
|
// Rationale: Routes open only after shell construction.
|
|
75
135
|
const references = {
|
|
76
136
|
changelog: async (input) => {
|
|
@@ -84,19 +144,24 @@ export async function composeOwnedUi(options = {}) {
|
|
|
84
144
|
const { renderPiShellHotkeySections } = await import("../integrations/pi/components/shell-hotkey-sections.js");
|
|
85
145
|
return { sections: width => renderPiShellHotkeySections(presentation, width) };
|
|
86
146
|
},
|
|
87
|
-
session: () => import("./session-info-reference.js").then(m => m.loadSessionInfoReference(
|
|
147
|
+
session: () => import("./session-info-reference.js").then(m => m.loadSessionInfoReference(backend)),
|
|
88
148
|
};
|
|
89
149
|
const routeHost = settings === null || !ownedSurfaces ? null : createOwnedRouteHost(settings, references);
|
|
90
150
|
const viewportSettings = settings === null || !ownedSurfaces ? null : {
|
|
91
151
|
snapshot: () => viewportSettingsSnapshot(settings),
|
|
92
152
|
onChange: listener => settings.onChange(() => listener(viewportSettingsSnapshot(settings))),
|
|
93
153
|
};
|
|
154
|
+
const backgroundSettings = settings === null || !ownedSurfaces ? null : {
|
|
155
|
+
snapshot: () => settings.value("backgroundStyle"),
|
|
156
|
+
// Rationale: one manager notification also recomputes an accent-derived canvas after accentColor changes.
|
|
157
|
+
onChange: listener => settings.onChange(current => listener(current.value("backgroundStyle"))),
|
|
158
|
+
};
|
|
94
159
|
const diagnosticDestination = options.suggestionDiagnosticsPath ?? process.env[PRODUCT_IDENTITY.environment.suggestionDiagnostics];
|
|
95
160
|
const suggestionDiagnostics = settings !== null && ownedSurfaces && diagnosticDestination?.trim()
|
|
96
161
|
? new SuggestionDiagnosticCapture({ enabled: true, destination: diagnosticDestination }) : null;
|
|
97
162
|
const promptSuggestions = settings === null || !ownedSurfaces ? null : {
|
|
98
163
|
...(suggestionDiagnostics === null ? {} : { diagnostics: suggestionDiagnostics }),
|
|
99
|
-
generator:
|
|
164
|
+
generator: backend,
|
|
100
165
|
enabled: () => settings.value("promptSuggestions"),
|
|
101
166
|
onChange: (listener) => settings.onChange(() => listener(settings.value("promptSuggestions"))),
|
|
102
167
|
};
|
|
@@ -112,12 +177,12 @@ export async function composeOwnedUi(options = {}) {
|
|
|
112
177
|
const historyLimit = settings?.value("promptHistoryMaxItems");
|
|
113
178
|
const historyProfileLocation = settings === null || !ownedSurfaces || !settings.value("promptHistoryEnabled")
|
|
114
179
|
? null
|
|
115
|
-
: resolvePromptHistoryPath(resolvePromptHistoryDataDir(),
|
|
180
|
+
: resolvePromptHistoryPath(resolvePromptHistoryDataDir(), backend.identity.agentDir);
|
|
116
181
|
const promptHistory = historyProfileLocation === null ? null : {
|
|
117
182
|
limit: typeof historyLimit === "number" ? historyLimit : 100,
|
|
118
183
|
store: new PromptHistoryService({
|
|
119
184
|
dataDir: resolvePromptHistoryDataDir(),
|
|
120
|
-
profileRoot:
|
|
185
|
+
profileRoot: backend.identity.agentDir,
|
|
121
186
|
limit: typeof historyLimit === "number" ? historyLimit : 100,
|
|
122
187
|
}),
|
|
123
188
|
imageSidecar: new PromptImageSidecar(historyProfileLocation.imagesDir),
|
|
@@ -125,13 +190,18 @@ export async function composeOwnedUi(options = {}) {
|
|
|
125
190
|
const clipboardDestination = options.clipboardDiagnosticsPath ?? process.env[PRODUCT_IDENTITY.environment.clipboardDiagnostics];
|
|
126
191
|
const clipboardDiagnostics = settings !== null && ownedSurfaces && clipboardDestination?.trim()
|
|
127
192
|
? new ClipboardDiagnosticCapture(clipboardDestination) : null;
|
|
193
|
+
// Invariant: process-wide services are created once here and borrowed by every session shell. The
|
|
194
|
+
// keybinding registry is applied before any presenter is built, so none of them reads Pi's defaults.
|
|
195
|
+
const keybindings = createPiKeybindingsHost({ profile: ownedSurfaces ? "a1" : "pi", agentDir: backend.identity.agentDir });
|
|
196
|
+
const clipboardServices = ownedSurfaces ? createOwnedUiClipboardServices() : null;
|
|
128
197
|
let shell;
|
|
129
198
|
let releaseNoteAcknowledgement = null;
|
|
130
199
|
try {
|
|
131
200
|
shell = new OwnedUiSessionShell({
|
|
201
|
+
presenters: createPiSessionPresenters(backend),
|
|
132
202
|
engine: {
|
|
133
|
-
backend
|
|
134
|
-
cwd:
|
|
203
|
+
backend,
|
|
204
|
+
cwd: backend.identity.cwd,
|
|
135
205
|
...(routeHost === null ? {} : { routeHost }),
|
|
136
206
|
...(currentReleaseNote === null || releaseNoteClaim === null ? {} : {
|
|
137
207
|
startupRoute: {
|
|
@@ -149,6 +219,7 @@ export async function composeOwnedUi(options = {}) {
|
|
|
149
219
|
...(options.terminal === undefined ? {} : { terminal: createPiTerminalBridge(options.terminal) }),
|
|
150
220
|
...(clipboardDiagnostics === null ? {} : { input: { onEvent: event => clipboardDiagnostics.runtime(event) } }),
|
|
151
221
|
...(viewportSettings === null ? {} : { viewportSettings }),
|
|
222
|
+
...(backgroundSettings === null ? {} : { backgroundSettings }),
|
|
152
223
|
...(settings === null || !ownedSurfaces ? {} : {
|
|
153
224
|
quitOutro: { snapshot: () => quitOutroSettingsSnapshot(settings), interactive: process.stdout.isTTY === true },
|
|
154
225
|
}),
|
|
@@ -160,6 +231,7 @@ export async function composeOwnedUi(options = {}) {
|
|
|
160
231
|
...(promptSuggestions === null ? {} : { suggestions: promptSuggestions }),
|
|
161
232
|
...(promptImages === null ? {} : { promptImages }),
|
|
162
233
|
...(skills === null ? {} : { skills }),
|
|
234
|
+
shared: { keybindings, ...(clipboardServices === null ? {} : { clipboard: clipboardServices }) },
|
|
163
235
|
...(promptHistory === null ? {} : { history: {
|
|
164
236
|
...promptHistory,
|
|
165
237
|
editor: await import("../integrations/pi/components/history-editor-loader.js").then(module => module.loadHistoryEditor()),
|
|
@@ -167,9 +239,12 @@ export async function composeOwnedUi(options = {}) {
|
|
|
167
239
|
});
|
|
168
240
|
}
|
|
169
241
|
catch (error) {
|
|
242
|
+
unsubscribeAccent();
|
|
170
243
|
await releaseNoteClaim?.release();
|
|
171
244
|
clipboardDiagnostics?.dispose();
|
|
172
245
|
suggestionDiagnostics?.dispose();
|
|
246
|
+
clipboardServices?.dispose();
|
|
247
|
+
await host.dispose();
|
|
173
248
|
throw error;
|
|
174
249
|
}
|
|
175
250
|
// Rationale: pinned Pi's version check is unreachable because the owned shell never runs its
|
|
@@ -185,23 +260,23 @@ export async function composeOwnedUi(options = {}) {
|
|
|
185
260
|
...(settings === null || !ownedSurfaces ? {} : { settingEnabled: settings.value("updateCheck") }),
|
|
186
261
|
});
|
|
187
262
|
if (release !== null)
|
|
188
|
-
|
|
263
|
+
backend.extensions.announceReleaseUpdate(release);
|
|
189
264
|
};
|
|
190
265
|
const exitNoticePath = process.env[PRODUCT_IDENTITY.environment.exitNoticePath];
|
|
191
266
|
// Security: tools the agent runs must never see, or rewrite, this instance's notice.
|
|
192
267
|
delete process.env[PRODUCT_IDENTITY.environment.exitNoticePath];
|
|
193
268
|
let exitNotice = Promise.resolve(null);
|
|
194
269
|
const application = {
|
|
195
|
-
get disposed() { return
|
|
270
|
+
get disposed() { return backend.identity.disposed; },
|
|
196
271
|
start: () => {
|
|
197
272
|
// Performance: the guardian notice loads beside first paint, never on the startup path.
|
|
198
273
|
if (exitNoticePath)
|
|
199
274
|
exitNotice = import("../app/session-shell/exit-notice.js")
|
|
200
|
-
.then(module => module.armExitNotice(
|
|
275
|
+
.then(module => module.armExitNotice(backend, exitNoticePath), () => null);
|
|
201
276
|
shell.start();
|
|
202
277
|
void announceNewerRelease().catch(() => undefined);
|
|
203
278
|
},
|
|
204
|
-
flush: () =>
|
|
279
|
+
flush: () => backend.session.flushEvents(),
|
|
205
280
|
waitUntilStopped: () => shell.waitUntilStopped(),
|
|
206
281
|
dispose: async () => {
|
|
207
282
|
try {
|
|
@@ -211,9 +286,25 @@ export async function composeOwnedUi(options = {}) {
|
|
|
211
286
|
await releaseNoteAcknowledgement?.catch(() => undefined);
|
|
212
287
|
}
|
|
213
288
|
finally {
|
|
289
|
+
// Invariant: the shared spares outlive every shell and stop only after the last one is disposed.
|
|
290
|
+
clipboardServices?.dispose();
|
|
291
|
+
unsubscribeAccent();
|
|
292
|
+
sessionRuntimeDisposed = true;
|
|
293
|
+
if (sessionRuntimeRefreshTimer !== null)
|
|
294
|
+
clearInterval(sessionRuntimeRefreshTimer);
|
|
295
|
+
sessionRuntimeRefreshTimer = null;
|
|
296
|
+
await sessionRuntimeRefresh;
|
|
297
|
+
const owner = await runtimeIdentity();
|
|
298
|
+
if (sessionRuntimeId !== undefined && owner !== null) {
|
|
299
|
+
await import("../foundation/lifecycle/session-repository-context.js")
|
|
300
|
+
.then(module => module.releaseSessionRepositoryRuntime(sessionRuntimeId, owner))
|
|
301
|
+
.catch(() => undefined);
|
|
302
|
+
}
|
|
214
303
|
await releaseNoteClaim?.release();
|
|
215
304
|
suggestionDiagnostics?.dispose();
|
|
216
305
|
clipboardDiagnostics?.dispose();
|
|
306
|
+
// Invariant: the host outlives the application; disposing it cancels host-level probes last.
|
|
307
|
+
await host.dispose();
|
|
217
308
|
}
|
|
218
309
|
},
|
|
219
310
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ReferenceDocumentProvider } from "../features/owned-ui/reference-screen-app.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { OwnedUiSessionBackend } from "../contracts/owned-ui/index.js";
|
|
3
3
|
/** Captures one current session snapshot and adapts it to the neutral reference document. */
|
|
4
|
-
export declare function loadSessionInfoReference(
|
|
4
|
+
export declare function loadSessionInfoReference(backend: OwnedUiSessionBackend): Promise<ReferenceDocumentProvider>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { renderPiShellSessionInfoReferenceDocument } from "../integrations/pi/components/shell-session-info-reference.js";
|
|
2
2
|
/** Captures one current session snapshot and adapts it to the neutral reference document. */
|
|
3
|
-
export async function loadSessionInfoReference(
|
|
4
|
-
const result = await
|
|
3
|
+
export async function loadSessionInfoReference(backend) {
|
|
4
|
+
const result = await backend.workflows.executeWorkflow({ command: "session", argument: "" });
|
|
5
5
|
if (result.outcome !== "completed")
|
|
6
6
|
throw new Error(result.message);
|
|
7
7
|
if (result.presentation?.kind !== "session-info")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CHANGELOG_ROUTE, HOTKEYS_ROUTE, HOTKEYS_TITLE } from "../features/owned-ui/reference-routes.js";
|
|
2
2
|
import { SETTINGS_APP_ID, SETTINGS_ROUTE } from "../features/owned-ui/settings-route.js";
|
|
3
|
-
import { piTheme } from "../integrations/pi/components/upstream/theme/theme.js";
|
|
3
|
+
import { piTheme, renderPiAccentPreview } from "../integrations/pi/components/upstream/theme/theme.js";
|
|
4
4
|
import { faint } from "../ui/components/text.js";
|
|
5
5
|
/** Declares settings and lazy document routes. */
|
|
6
6
|
export function createOwnedRouteHost(settings, references) {
|
|
@@ -130,6 +130,7 @@ function pinnedTheme() {
|
|
|
130
130
|
fg: (token, text) => piTheme().fg(token, text),
|
|
131
131
|
bold: (text) => piTheme().bold(text),
|
|
132
132
|
plain: (text) => text,
|
|
133
|
+
accentPreview: (color, text) => renderPiAccentPreview(color, text),
|
|
133
134
|
disabled: (text) => faint(piTheme().fg("dim", text)),
|
|
134
135
|
highlight: (text) => piTheme().bg("selectedBg", text),
|
|
135
136
|
panel: (text) => `\u001b[48;2;55;55;55m${text}\u001b[49m`,
|