@timurproko/a1 0.2.6 → 0.2.7-dev.746
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/guardian.js +5 -0
- package/bin/tab-launch-context.d.ts +18 -0
- package/bin/tab-launch-context.js +36 -0
- package/bin/ui.js +14 -3
- package/dist/app/session-shell/helper-pool.d.ts +3 -5
- package/dist/app/session-shell/helper-pool.js +3 -5
- package/dist/app/session-shell/session-shell-root.d.ts +6 -1
- package/dist/app/session-shell/session-shell-root.js +3 -2
- package/dist/app/session-shell/session-shell.js +41 -24
- package/dist/app/session-shell/session-viewport-controller.d.ts +1 -1
- package/dist/app/session-shell/session-viewport-controller.js +3 -3
- package/dist/composition/owned-ui.d.ts +17 -0
- package/dist/composition/owned-ui.js +28 -1
- package/dist/foundation/launch-context/index.d.ts +6 -0
- package/dist/foundation/launch-context/index.js +15 -0
- package/dist/foundation/launch-guardian/main.d.ts +5 -0
- package/dist/foundation/launch-guardian/main.js +2 -1
- package/dist/foundation/release/bootstrap.d.ts +4 -0
- package/dist/foundation/release/bootstrap.js +33 -6
- package/dist/foundation/resident-tabs/bridge-client.d.ts +36 -0
- package/dist/foundation/resident-tabs/bridge-client.js +157 -0
- package/dist/foundation/resident-tabs/ensure-terminal-host.d.ts +28 -0
- package/dist/foundation/resident-tabs/ensure-terminal-host.js +115 -0
- package/dist/foundation/resident-tabs/index.d.ts +5 -0
- package/dist/foundation/resident-tabs/index.js +3 -0
- package/dist/foundation/resident-tabs/protocol.d.ts +12 -0
- package/dist/foundation/resident-tabs/protocol.js +195 -0
- package/dist/foundation/resident-tabs/routing.d.ts +10 -0
- package/dist/foundation/resident-tabs/routing.js +8 -0
- package/dist/foundation/resident-tabs/settings.d.ts +2 -0
- package/dist/foundation/resident-tabs/settings.js +17 -0
- package/dist/foundation/terminal-cleanup/index.d.ts +1 -1
- package/dist/foundation/terminal-cleanup/index.js +1 -1
- package/dist/foundation/terminal-cleanup/terminal-reset.d.ts +1 -0
- package/dist/foundation/terminal-cleanup/terminal-reset.js +1 -0
- package/dist/integrations/pi/components/owned-editor-ux.d.ts +1 -1
- package/dist/integrations/pi/components/owned-editor-ux.js +2 -2
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +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 +1 -1
- package/dist/product-identity.js +1 -1
- package/dist/product-identity.json +5 -0
- package/dist/ui/components/transcript-viewport.d.ts +6 -3
- package/dist/ui/components/transcript-viewport.js +13 -15
- package/dist/ui/settings/declarations.d.ts +13 -1
- package/dist/ui/settings/declarations.js +10 -1
- package/dist/ui/settings/index.d.ts +1 -1
- package/dist/ui/settings/index.js +1 -1
- package/dist/ui/settings/migrations.js +7 -0
- package/dist/ui/settings/resolution.d.ts +2 -0
- package/dist/ui/settings/resolution.js +13 -1
- package/docs/architecture/internal-naming.md +1 -1
- package/docs/architecture/resident-tabs-requirements.md +813 -0
- package/docs/architecture/resident-tabs.md +502 -0
- package/docs/architecture/terminal-host-proof-gate.md +2 -0
- package/docs/openspec-archive-automation.md +12 -11
- package/docs/validation.md +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { parseOwnedUiSettingsDocument, resolveResidentTabsSetting } from "../../ui/settings/index.js";
|
|
4
|
+
const MAX_SETTINGS_BYTES = 256 * 1024;
|
|
5
|
+
/** Read only the routing flag before any UI or extension module is loaded. */
|
|
6
|
+
export async function readResidentTabsSetting(configDir, profileId = "a1") {
|
|
7
|
+
const file = resolve(configDir, "settings", `${profileId}.json`);
|
|
8
|
+
try {
|
|
9
|
+
const raw = await readFile(file, "utf8");
|
|
10
|
+
if (Buffer.byteLength(raw, "utf8") > MAX_SETTINGS_BYTES)
|
|
11
|
+
return false;
|
|
12
|
+
return resolveResidentTabsSetting(parseOwnedUiSettingsDocument(raw));
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { EMERGENCY_TERMINAL_RESET, boundedCleanup, restoreAfterOwnedExit, restoreProcessTerminal } from "./terminal-reset.js";
|
|
1
|
+
export { CLEAR_EXIT_INTERVAL_MS, EMERGENCY_TERMINAL_RESET, boundedCleanup, restoreAfterOwnedExit, restoreProcessTerminal } from "./terminal-reset.js";
|
|
2
2
|
export { installFatalExit, writeFatalDiagnostic } from "./fatal-exit.js";
|
|
3
3
|
export type { FatalExitOptions } from "./fatal-exit.js";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { EMERGENCY_TERMINAL_RESET, boundedCleanup, restoreAfterOwnedExit, restoreProcessTerminal } from "./terminal-reset.js";
|
|
1
|
+
export { CLEAR_EXIT_INTERVAL_MS, EMERGENCY_TERMINAL_RESET, boundedCleanup, restoreAfterOwnedExit, restoreProcessTerminal } from "./terminal-reset.js";
|
|
2
2
|
export { installFatalExit, writeFatalDiagnostic } from "./fatal-exit.js";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const CLEAR_EXIT_INTERVAL_MS = 500;
|
|
1
2
|
export declare const EMERGENCY_TERMINAL_RESET: string;
|
|
2
3
|
export declare function restoreProcessTerminal(): void;
|
|
3
4
|
export declare function restoreAfterOwnedExit(ownsTerminal: boolean, code: number | null, signal: string | null, restore?: () => void): number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { writeSync } from "node:fs";
|
|
2
|
+
export const CLEAR_EXIT_INTERVAL_MS = 500;
|
|
2
3
|
// Protocol: reset modes on both screens; setting keyboard flags to zero is idempotent,
|
|
3
4
|
// unlike repeatedly popping a keyboard-protocol stack owned by a parent application.
|
|
4
5
|
// Resetting parent-screen margins homes the cursor, so preserve its restored position.
|
|
@@ -44,7 +44,7 @@ export declare class OwnedEditorUxInterception {
|
|
|
44
44
|
pasteClipboard(): boolean;
|
|
45
45
|
}
|
|
46
46
|
export interface PromptSelectionUxOptions {
|
|
47
|
-
readonly copyText: (text: string) => void;
|
|
47
|
+
readonly copyText: (text: string, cut: boolean) => void;
|
|
48
48
|
readonly readClipboardContent: () => Promise<PiShellClipboardContent | null>;
|
|
49
49
|
readonly beginClipboardPaste?: () => PiShellPasteReservation;
|
|
50
50
|
readonly beginTextPaste?: (text: string) => PiShellPasteReservation;
|
|
@@ -88,12 +88,12 @@ class PromptSelectionInterceptor {
|
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
90
|
if (this.keybindings.matches(data, "tui.input.copy") && this.hasSelection()) {
|
|
91
|
-
this.options.copyText(this.options.expandCopiedText(this.#selectedText()));
|
|
91
|
+
this.options.copyText(this.options.expandCopiedText(this.#selectedText()), false);
|
|
92
92
|
this.#collapseCopiedSelection();
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
95
|
if (this.keybindings.matches(data, "owned.editor.cut") && this.hasSelection()) {
|
|
96
|
-
this.options.copyText(this.options.expandCopiedText(this.#selectedText()));
|
|
96
|
+
this.options.copyText(this.options.expandCopiedText(this.#selectedText()), true);
|
|
97
97
|
if (!this.#deleteSelection())
|
|
98
98
|
this.#deleteAtomicFocus();
|
|
99
99
|
return;
|
|
@@ -185,7 +185,7 @@ export interface PiShellEditorOptions {
|
|
|
185
185
|
readonly onFollowUp?: (() => void) | undefined;
|
|
186
186
|
readonly onDequeue?: (() => void) | undefined;
|
|
187
187
|
readonly onPromptSuggestionAccepted?: (text: string) => void;
|
|
188
|
-
readonly onCopyText?: (text: string) => void;
|
|
188
|
+
readonly onCopyText?: (text: string, cut: boolean) => void;
|
|
189
189
|
readonly readClipboardContent?: (signal?: AbortSignal) => Promise<PiShellClipboardContent | null>;
|
|
190
190
|
readonly beginClipboardPaste?: () => PiShellPasteReservation;
|
|
191
191
|
readonly beginTextPaste?: (text: string) => PiShellPasteReservation;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"platform": "darwin",
|
|
6
6
|
"architecture": "arm64",
|
|
7
7
|
"capability": "supported",
|
|
8
|
-
"builtAt": "2026-10-
|
|
8
|
+
"builtAt": "2026-10-12T06:07:21.173Z",
|
|
9
9
|
"artifact": {
|
|
10
10
|
"filename": "process-guardian",
|
|
11
11
|
"sha256": "51b0b2dc1c9ae577f2586c4217066929278726c2c15308d9144eb6f538e118ff",
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"platform": "linux",
|
|
6
6
|
"architecture": "x64",
|
|
7
7
|
"capability": "supported",
|
|
8
|
-
"builtAt": "2026-10-
|
|
8
|
+
"builtAt": "2026-10-12T06:06:54.072Z",
|
|
9
9
|
"artifact": {
|
|
10
10
|
"filename": "process-guardian",
|
|
11
11
|
"sha256": "ef62679e83bc1fad3d38f9f21675d9256f08d20e67fd4791571032115ca1b0e9",
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
"platform": "win32",
|
|
6
6
|
"architecture": "x64",
|
|
7
7
|
"capability": "supported",
|
|
8
|
-
"builtAt": "2026-10-
|
|
8
|
+
"builtAt": "2026-10-12T06:07:34.911Z",
|
|
9
9
|
"artifact": {
|
|
10
10
|
"filename": "process-guardian.exe",
|
|
11
|
-
"sha256": "
|
|
11
|
+
"sha256": "3f4e2d9c37a775b8a12f15539af5421e64f11149293ab2adc1bf3b06ce85b66d",
|
|
12
12
|
"size": 288256
|
|
13
13
|
},
|
|
14
14
|
"provenance": {
|
|
Binary file
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const ENVIRONMENT_KEYS: readonly ["clipboardDiagnostics", "configDir", "dataDir", "databasePath", "developmentInstanceId", "developmentRoot", "endpoint", "exitNoticePath", "paneId", "probeTrace", "processGuardianPath", "prFooterPreview", "profileHome", "runtimeDir", "sessionRuntimeId", "skipVersionCheck", "startupTrace", "suggestionDiagnostics", "terminalSessionId"];
|
|
1
|
+
declare const ENVIRONMENT_KEYS: readonly ["clipboardDiagnostics", "configDir", "dataDir", "databasePath", "developmentInstanceId", "developmentRoot", "endpoint", "exitNoticePath", "paneId", "probeTrace", "processGuardianPath", "prFooterPreview", "profileHome", "runtimeDir", "sessionRuntimeId", "skipVersionCheck", "startupTrace", "suggestionDiagnostics", "tabEndpoint", "tabId", "tabToken", "tabsEndpoint", "terminalHostPath", "terminalSessionId"];
|
|
2
2
|
declare const FILESYSTEM_KEYS: readonly ["slug", "windowsDirectory", "unixDirectory", "temporaryPrefix"];
|
|
3
3
|
declare const STATE_KEYS: readonly ["windowsControlDirectory", "unixControlDirectory", "developmentDirectory", "piAgentProfile", "piVanillaProfile", "sessionRepositoryDirectory", "sessionWorktreeClaimDirectory"];
|
|
4
4
|
declare const ENDPOINT_KEYS: readonly ["windowsPipeStem", "unixSocketFilename", "metadataFilename", "supervisorLogFilename", "databaseFilename"];
|
package/dist/product-identity.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import rawIdentity from "./product-identity.json" with { type: "json" };
|
|
2
2
|
const ENVIRONMENT_KEYS = [
|
|
3
3
|
"clipboardDiagnostics", "configDir", "dataDir", "databasePath", "developmentInstanceId", "developmentRoot", "endpoint", "exitNoticePath",
|
|
4
|
-
"paneId", "probeTrace", "processGuardianPath", "prFooterPreview", "profileHome", "runtimeDir", "sessionRuntimeId", "skipVersionCheck", "startupTrace", "suggestionDiagnostics", "terminalSessionId",
|
|
4
|
+
"paneId", "probeTrace", "processGuardianPath", "prFooterPreview", "profileHome", "runtimeDir", "sessionRuntimeId", "skipVersionCheck", "startupTrace", "suggestionDiagnostics", "tabEndpoint", "tabId", "tabToken", "tabsEndpoint", "terminalHostPath", "terminalSessionId",
|
|
5
5
|
];
|
|
6
6
|
const FILESYSTEM_KEYS = ["slug", "windowsDirectory", "unixDirectory", "temporaryPrefix"];
|
|
7
7
|
const STATE_KEYS = ["windowsControlDirectory", "unixControlDirectory", "developmentDirectory", "piAgentProfile", "piVanillaProfile", "sessionRepositoryDirectory", "sessionWorktreeClaimDirectory"];
|
|
@@ -28,6 +28,11 @@
|
|
|
28
28
|
"skipVersionCheck": "A1_SKIP_VERSION_CHECK",
|
|
29
29
|
"startupTrace": "A1_STARTUP_TRACE",
|
|
30
30
|
"suggestionDiagnostics": "A1_SUGGESTION_DIAGNOSTICS",
|
|
31
|
+
"tabEndpoint": "A1_TAB_ENDPOINT",
|
|
32
|
+
"tabId": "A1_TAB_ID",
|
|
33
|
+
"tabToken": "A1_TAB_TOKEN",
|
|
34
|
+
"tabsEndpoint": "A1_TABS_ENDPOINT",
|
|
35
|
+
"terminalHostPath": "A1_TERMINAL_HOST_PATH",
|
|
31
36
|
"terminalSessionId": "A1_TERMINAL_SESSION_ID"
|
|
32
37
|
},
|
|
33
38
|
"state": {
|
|
@@ -36,6 +36,7 @@ export interface TranscriptViewportFrameInput {
|
|
|
36
36
|
/** Final transient rows to bottom-align with unused viewport space while content fits. */
|
|
37
37
|
readonly bottomAlignedTailRowCount?: number;
|
|
38
38
|
readonly dockRows: readonly string[];
|
|
39
|
+
readonly explicitCopyDockRows?: number;
|
|
39
40
|
readonly promptAnchors: readonly TranscriptPromptAnchor[];
|
|
40
41
|
readonly width: number;
|
|
41
42
|
readonly height: number;
|
|
@@ -141,6 +142,7 @@ export interface TranscriptViewportFrame {
|
|
|
141
142
|
readonly cacheEntries: number;
|
|
142
143
|
};
|
|
143
144
|
}
|
|
145
|
+
type SelectionCopyIntent = "automatic" | "explicit";
|
|
144
146
|
/**
|
|
145
147
|
* A1-owned viewport state. It knows only rows and semantic prompt anchors; Pi
|
|
146
148
|
* components and transcript payloads remain outside this neutral boundary.
|
|
@@ -170,9 +172,9 @@ export declare class TranscriptViewport {
|
|
|
170
172
|
extendSelection(column: number, frameRow: number, now?: number, autoScroll?: boolean): boolean;
|
|
171
173
|
releaseSelection(): boolean;
|
|
172
174
|
clearSelection(): boolean;
|
|
173
|
-
selectedText(): string | null;
|
|
175
|
+
selectedText(intent?: SelectionCopyIntent): string | null;
|
|
174
176
|
/** Captures visible selected text, not off-screen history. */
|
|
175
|
-
captureSelectedText(): SelectionCopySnapshot | null;
|
|
177
|
+
captureSelectedText(intent?: SelectionCopyIntent): SelectionCopySnapshot | null;
|
|
176
178
|
scrollBy(lines: number, now?: number): boolean;
|
|
177
179
|
scrollTo(position: number, now?: number): boolean;
|
|
178
180
|
scrollToEnd(now?: number): boolean;
|
|
@@ -184,6 +186,7 @@ export declare class TranscriptViewport {
|
|
|
184
186
|
clearTransient(): void;
|
|
185
187
|
compose(input: TranscriptViewportFrameInput): TranscriptViewportFrame;
|
|
186
188
|
/** Reuses an established transcript frame when only same-height dock rows changed. */
|
|
187
|
-
composeDockOnly(dockRows: readonly string[], width: number, height: number): TranscriptViewportFrame | null;
|
|
189
|
+
composeDockOnly(dockRows: readonly string[], width: number, height: number, explicitCopyDockRows?: number): TranscriptViewportFrame | null;
|
|
188
190
|
}
|
|
189
191
|
export declare function assertTranscriptViewportFrameDescriptor(descriptor: TranscriptViewportFrameDescriptor): void;
|
|
192
|
+
export {};
|
|
@@ -63,6 +63,7 @@ export class TranscriptViewport {
|
|
|
63
63
|
#contentWidth = 0;
|
|
64
64
|
#selectionWidth = 0;
|
|
65
65
|
#viewportHeight = 0;
|
|
66
|
+
#explicitCopyDockRows = 0;
|
|
66
67
|
#firstSelectableRow = 0;
|
|
67
68
|
#selectionRowAnchors = [];
|
|
68
69
|
#frameId = 0;
|
|
@@ -178,22 +179,19 @@ export class TranscriptViewport {
|
|
|
178
179
|
this.#selectionRevision += 1;
|
|
179
180
|
return true;
|
|
180
181
|
}
|
|
181
|
-
selectedText() {
|
|
182
|
+
selectedText(intent = "automatic") {
|
|
182
183
|
const selection = this.#visibleSelection();
|
|
183
184
|
if (selection === undefined)
|
|
184
185
|
return null;
|
|
185
|
-
// Invariant: the blue range spans the complete frame, but automatic and Ctrl+C frame copy
|
|
186
|
-
// admit only persistent transcript rows. Transient status, suggestions, input, and footer
|
|
187
|
-
// chrome remain visually selectable without becoming clipboard payload.
|
|
188
186
|
const copiedLines = Array.from({ length: Math.max(0, selection.end.line - selection.start.line + 1) }, (_value, index) => selection.start.line + index).filter(line => {
|
|
189
187
|
const anchor = this.#selectionRowAnchors[line];
|
|
190
|
-
return anchor?.kind === "document" && anchor.row < this.#selectableDocumentRowCount
|
|
188
|
+
return anchor?.kind === "document" && anchor.row < this.#selectableDocumentRowCount
|
|
189
|
+
|| intent === "explicit" && anchor?.kind === "dock" && anchor.fromBottom < this.#explicitCopyDockRows;
|
|
191
190
|
});
|
|
192
191
|
if (copiedLines.length === 0)
|
|
193
192
|
return null;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const prompt = this.#promptAnchors.find(candidate => copiedLines.every(line => {
|
|
193
|
+
const transcriptLines = copiedLines.filter(line => this.#selectionRowAnchors[line]?.kind === "document");
|
|
194
|
+
const prompt = transcriptLines.length === 0 ? undefined : this.#promptAnchors.find(candidate => transcriptLines.every(line => {
|
|
197
195
|
const anchor = this.#selectionRowAnchors[line];
|
|
198
196
|
return anchor?.kind === "document" && anchor.row >= candidate.firstRow && anchor.row <= candidate.lastRow;
|
|
199
197
|
}));
|
|
@@ -208,11 +206,11 @@ export class TranscriptViewport {
|
|
|
208
206
|
return text.length === 0 ? null : text;
|
|
209
207
|
}
|
|
210
208
|
/** Captures visible selected text, not off-screen history. */
|
|
211
|
-
captureSelectedText() {
|
|
212
|
-
if (!this.#copyableSelection)
|
|
209
|
+
captureSelectedText(intent = "automatic") {
|
|
210
|
+
if (intent === "automatic" && !this.#copyableSelection)
|
|
213
211
|
return null;
|
|
214
212
|
const started = performance.now();
|
|
215
|
-
let text = this.selectedText();
|
|
213
|
+
let text = this.selectedText(intent);
|
|
216
214
|
if (text === null)
|
|
217
215
|
return null;
|
|
218
216
|
text = text.trim();
|
|
@@ -315,6 +313,7 @@ export class TranscriptViewport {
|
|
|
315
313
|
this.#contentWidth = 0;
|
|
316
314
|
this.#selectionWidth = 0;
|
|
317
315
|
this.#viewportHeight = 0;
|
|
316
|
+
this.#explicitCopyDockRows = 0;
|
|
318
317
|
this.clearTransient();
|
|
319
318
|
this.#frame = null;
|
|
320
319
|
}
|
|
@@ -330,6 +329,7 @@ export class TranscriptViewport {
|
|
|
330
329
|
const theme = input.theme ?? PLAIN_THEME;
|
|
331
330
|
const previousDescriptor = this.#frame?.descriptor ?? null;
|
|
332
331
|
const dock = input.dockRows.length > height ? input.dockRows.slice(-height) : [...input.dockRows];
|
|
332
|
+
this.#explicitCopyDockRows = clamp(input.explicitCopyDockRows ?? 0, 0, dock.length);
|
|
333
333
|
const viewportHeight = Math.max(0, height - dock.length);
|
|
334
334
|
const bottomAlignedTailRowCount = clamp(input.bottomAlignedTailRowCount ?? 0, 0, input.documentRows.length);
|
|
335
335
|
const transientAlignmentGapRows = bottomAlignedTailRowCount > 0
|
|
@@ -414,8 +414,6 @@ export class TranscriptViewport {
|
|
|
414
414
|
visible[0] = quiet && !this.#stickyHovered ? theme.quietSticky(sticky) : sticky;
|
|
415
415
|
visibleSource[0] = sourceRow;
|
|
416
416
|
}
|
|
417
|
-
// Invariant: selection uses exact visible source rows within the rendered
|
|
418
|
-
// content boundary; paint-only guards and the rail gutter stay presentation-only.
|
|
419
417
|
this.#selectionRows = [
|
|
420
418
|
...visibleSource.map(row => truncateToWidth(row, contentWidth)),
|
|
421
419
|
...dock,
|
|
@@ -426,7 +424,6 @@ export class TranscriptViewport {
|
|
|
426
424
|
? viewportSelectionAnchor(documentRow, documentRows[documentRow] ?? "", this.#selectableDocumentRowCount, documentRows.length)
|
|
427
425
|
: { kind: "screen", row, source: this.#selectionRows[row] ?? "" };
|
|
428
426
|
});
|
|
429
|
-
// Invariant: a pinned prompt is chrome over its hidden source row, which clips like off-screen rows.
|
|
430
427
|
this.#firstSelectableRow = stickyActive && viewportHeight > 0 ? 1 : 0;
|
|
431
428
|
this.#selectionRowAnchors = [
|
|
432
429
|
...visibleAnchors,
|
|
@@ -609,7 +606,7 @@ export class TranscriptViewport {
|
|
|
609
606
|
return frame;
|
|
610
607
|
}
|
|
611
608
|
/** Reuses an established transcript frame when only same-height dock rows changed. */
|
|
612
|
-
composeDockOnly(dockRows, width, height) {
|
|
609
|
+
composeDockOnly(dockRows, width, height, explicitCopyDockRows = 0) {
|
|
613
610
|
const previous = this.#frame;
|
|
614
611
|
const boundedWidth = Math.max(1, width);
|
|
615
612
|
const boundedHeight = Math.max(0, height);
|
|
@@ -645,6 +642,7 @@ export class TranscriptViewport {
|
|
|
645
642
|
};
|
|
646
643
|
assertTranscriptViewportFrameDescriptor(descriptor);
|
|
647
644
|
this.#selectionRows = [...this.#selectionRows.slice(0, viewportHeight), ...dock].slice(0, boundedHeight);
|
|
645
|
+
this.#explicitCopyDockRows = clamp(explicitCopyDockRows, 0, dock.length);
|
|
648
646
|
const frame = {
|
|
649
647
|
rows: [...previous.rows.slice(0, viewportHeight), ...dock].slice(0, boundedHeight),
|
|
650
648
|
contentWidth: previous.contentWidth,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const OWNED_UI_SETTINGS_VERSION =
|
|
1
|
+
export declare const OWNED_UI_SETTINGS_VERSION = 14;
|
|
2
2
|
export type OwnedUiSettingValue = string | number | boolean;
|
|
3
3
|
export type OwnedUiSettingApplication = "live" | "restart";
|
|
4
4
|
export interface OwnedUiSettingDeclaration {
|
|
@@ -164,6 +164,18 @@ export declare const OWNED_SETTING_DECLARATIONS: Readonly<{
|
|
|
164
164
|
defaultValue: 8;
|
|
165
165
|
allowedValues: readonly [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
|
|
166
166
|
}>;
|
|
167
|
+
readonly residentTabs: Readonly<{
|
|
168
|
+
id: "residentTabs";
|
|
169
|
+
label: "Resident tabs";
|
|
170
|
+
section: Readonly<{
|
|
171
|
+
id: "generic";
|
|
172
|
+
title: "Generic";
|
|
173
|
+
}>;
|
|
174
|
+
description: "Keep bare A1 running when its terminal closes and reattach on the next launch. Resident tabs have no stop command yet; turning this off prevents new resident launches but does not stop an existing tab.";
|
|
175
|
+
application: "restart";
|
|
176
|
+
defaultValue: false;
|
|
177
|
+
allowedValues: readonly [true, false];
|
|
178
|
+
}>;
|
|
167
179
|
}>;
|
|
168
180
|
export type OwnedSettingId = keyof typeof OWNED_SETTING_DECLARATIONS;
|
|
169
181
|
/** The value type a setting's declaration allows: a literal union for a choice, `number` for a stepped range. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const OWNED_UI_SETTINGS_VERSION =
|
|
1
|
+
export const OWNED_UI_SETTINGS_VERSION = 14;
|
|
2
2
|
const UI_ACCENT_COLOR_CHOICES = Object.freeze([
|
|
3
3
|
"purple", "blue", "cyan", "green", "orange", "pink",
|
|
4
4
|
]);
|
|
@@ -124,6 +124,15 @@ export const OWNED_SETTING_DECLARATIONS = Object.freeze({
|
|
|
124
124
|
defaultValue: 8,
|
|
125
125
|
allowedValues: Object.freeze([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
|
|
126
126
|
}),
|
|
127
|
+
residentTabs: Object.freeze({
|
|
128
|
+
id: "residentTabs",
|
|
129
|
+
label: "Resident tabs",
|
|
130
|
+
section: GENERIC_SECTION,
|
|
131
|
+
description: "Keep bare A1 running when its terminal closes and reattach on the next launch. Resident tabs have no stop command yet; turning this off prevents new resident launches but does not stop an existing tab.",
|
|
132
|
+
application: "restart",
|
|
133
|
+
defaultValue: false,
|
|
134
|
+
allowedValues: Object.freeze([true, false]),
|
|
135
|
+
}),
|
|
127
136
|
});
|
|
128
137
|
/** The declarations in declaration order, for resolution, persistence, and the settings screen. */
|
|
129
138
|
export const OWNED_UI_SETTING_DECLARATIONS = Object.freeze(Object.values(OWNED_SETTING_DECLARATIONS));
|
|
@@ -2,7 +2,7 @@ export { OWNED_SETTING_DECLARATIONS, OWNED_UI_SETTINGS_VERSION, OWNED_UI_SETTING
|
|
|
2
2
|
export type { OwnedSettingId, OwnedSettingValueOf, OwnedUiSettingApplication, OwnedUiSettingDeclaration, OwnedUiSettingValue } from "./declarations.js";
|
|
3
3
|
export { OWNED_UI_SETTINGS_MIGRATIONS, assertOwnedUiSettingsMigrations, migrationsFrom } from "./migrations.js";
|
|
4
4
|
export type { OwnedUiSettingsMigration } from "./migrations.js";
|
|
5
|
-
export { documentFrom, parseOwnedUiSettingsDocument, resolveOwnedUiSettings, settingValue } from "./resolution.js";
|
|
5
|
+
export { documentFrom, parseOwnedUiSettingsDocument, resolveOwnedUiSettings, resolveResidentTabsSetting, settingValue } from "./resolution.js";
|
|
6
6
|
export type { OwnedUiResolvedSetting, OwnedUiSettingSource, OwnedUiSettingsDocument, OwnedUiSettingsNotice, OwnedUiSettingsNoticeCode, OwnedUiSettingsResolution, ResolveOwnedUiSettingsInput, } from "./resolution.js";
|
|
7
7
|
export { AGENT_SECTION_ID, buildOwnedUiSettingsSections, findOwnedUiSettingsEntry } from "./sections.js";
|
|
8
8
|
export type { AgentSettingsSnapshot, BuildOwnedUiSettingsSectionsInput, OwnedUiSettingsBackend, OwnedUiSettingsEntry, OwnedUiSettingsSection, } from "./sections.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { OWNED_SETTING_DECLARATIONS, OWNED_UI_SETTINGS_VERSION, OWNED_UI_SETTING_DECLARATIONS, assertOwnedUiSettingDeclarations, findOwnedUiSettingDeclaration, isOwnedSettingId, } from "./declarations.js";
|
|
2
2
|
export { OWNED_UI_SETTINGS_MIGRATIONS, assertOwnedUiSettingsMigrations, migrationsFrom } from "./migrations.js";
|
|
3
|
-
export { documentFrom, parseOwnedUiSettingsDocument, resolveOwnedUiSettings, settingValue } from "./resolution.js";
|
|
3
|
+
export { documentFrom, parseOwnedUiSettingsDocument, resolveOwnedUiSettings, resolveResidentTabsSetting, settingValue } from "./resolution.js";
|
|
4
4
|
export { AGENT_SECTION_ID, buildOwnedUiSettingsSections, findOwnedUiSettingsEntry } from "./sections.js";
|
|
5
5
|
export { OwnedSettingsManager } from "./manager.js";
|
|
@@ -104,6 +104,13 @@ export const OWNED_UI_SETTINGS_MIGRATIONS = Object.freeze([
|
|
|
104
104
|
return { ...values };
|
|
105
105
|
},
|
|
106
106
|
}),
|
|
107
|
+
Object.freeze({
|
|
108
|
+
to: 14,
|
|
109
|
+
description: "Introduce the opt-in resident tabs preview with a disabled default.",
|
|
110
|
+
migrate(values) {
|
|
111
|
+
return { ...values };
|
|
112
|
+
},
|
|
113
|
+
}),
|
|
107
114
|
]);
|
|
108
115
|
export function assertOwnedUiSettingsMigrations(migrations, currentVersion = OWNED_UI_SETTINGS_VERSION) {
|
|
109
116
|
const firstProduced = currentVersion - migrations.length + 1;
|
|
@@ -42,4 +42,6 @@ export interface ResolveOwnedUiSettingsInput {
|
|
|
42
42
|
*/
|
|
43
43
|
export declare function resolveOwnedUiSettings(input: ResolveOwnedUiSettingsInput): OwnedUiSettingsResolution;
|
|
44
44
|
export declare function settingValue(resolution: OwnedUiSettingsResolution, id: string): OwnedUiSettingValue | null;
|
|
45
|
+
/** Resolve the launch-routing flag without constructing the UI settings manager. */
|
|
46
|
+
export declare function resolveResidentTabsSetting(document: OwnedUiSettingsDocument | null): boolean;
|
|
45
47
|
export declare function documentFrom(resolution: OwnedUiSettingsResolution): OwnedUiSettingsDocument;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OWNED_UI_SETTINGS_VERSION, findOwnedUiSettingDeclaration, } from "./declarations.js";
|
|
1
|
+
import { OWNED_SETTING_DECLARATIONS, OWNED_UI_SETTINGS_VERSION, findOwnedUiSettingDeclaration, } from "./declarations.js";
|
|
2
2
|
import { migrationsFrom } from "./migrations.js";
|
|
3
3
|
export function parseOwnedUiSettingsDocument(raw) {
|
|
4
4
|
let parsed;
|
|
@@ -122,6 +122,18 @@ export function resolveOwnedUiSettings(input) {
|
|
|
122
122
|
export function settingValue(resolution, id) {
|
|
123
123
|
return resolution.settings.find(setting => setting.declaration.id === id)?.value ?? null;
|
|
124
124
|
}
|
|
125
|
+
/** Resolve the launch-routing flag without constructing the UI settings manager. */
|
|
126
|
+
export function resolveResidentTabsSetting(document) {
|
|
127
|
+
if (document === null || document.version !== OWNED_UI_SETTINGS_VERSION)
|
|
128
|
+
return false;
|
|
129
|
+
const resolution = resolveOwnedUiSettings({
|
|
130
|
+
declarations: [OWNED_SETTING_DECLARATIONS.residentTabs],
|
|
131
|
+
migrations: [],
|
|
132
|
+
document,
|
|
133
|
+
currentVersion: OWNED_UI_SETTINGS_VERSION,
|
|
134
|
+
});
|
|
135
|
+
return settingValue(resolution, "residentTabs") === true;
|
|
136
|
+
}
|
|
125
137
|
export function documentFrom(resolution) {
|
|
126
138
|
const values = { ...resolution.preserved };
|
|
127
139
|
for (const setting of resolution.settings) {
|
|
@@ -31,7 +31,7 @@ The exact externally branded key/member authority is `config/internal-naming-pol
|
|
|
31
31
|
| `A1_PROCESS_GUARDIAN_PATH` | Explicit executable override in `src/foundation/process-containment/native-guardian-containment.ts`, also configured by CI; exact existing exposure-review entry. |
|
|
32
32
|
| `A1_PROBE_TRACE` | Opt-in diagnostics read by native terminal-host code; exact existing exposure-review entry. |
|
|
33
33
|
| `A1_BUILD_VERBOSE`, `A1_DEV_SHELL` | Developer invocation controls in the build helper and development launcher; exact existing exposure-review entries. |
|
|
34
|
-
| `A1_PANE_ID`, `A1_TERMINAL_SESSION_ID` |
|
|
34
|
+
| `A1_PANE_ID`, `A1_TERMINAL_SESSION_ID` | Reserved compatibility identities retained in the product identity manifest; the resident host does not currently emit them. |
|
|
35
35
|
|
|
36
36
|
Pending review preserves a possible external interface, not an obsolete private alias. Once a setting is established as private, it cannot keep its branded spelling through that category.
|
|
37
37
|
|