@timurproko/a1 0.2.7-dev.788 → 0.2.7-dev.792
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/dist/app/session-shell/session-shell-root.d.ts +0 -1
- package/dist/app/session-shell/session-shell-root.js +41 -15
- package/dist/app/session-shell/session-shell.js +5 -4
- package/dist/app/session-shell/session-viewport-controller.d.ts +2 -2
- package/dist/app/session-shell/session-viewport-controller.js +24 -12
- package/dist/composition/owned-ui.d.ts +1 -0
- package/dist/composition/owned-ui.js +27 -2
- package/dist/contracts/owned-ui/index.d.ts +1 -1
- package/dist/contracts/owned-ui/model.d.ts +3 -0
- package/dist/features/owned-ui/settings-app.js +9 -6
- package/dist/features/resident-tab/index.d.ts +3 -1
- package/dist/features/resident-tab/index.js +5 -1
- package/dist/features/resident-tab/shortcut-bindings-file.d.ts +8 -0
- package/dist/features/resident-tab/shortcut-bindings-file.js +40 -0
- package/dist/features/resident-tab/{shortcuts.d.ts → shortcut-declarations.d.ts} +5 -2
- package/dist/features/resident-tab/{shortcuts.js → shortcut-declarations.js} +5 -17
- package/dist/features/resident-tab/shortcut-projection.d.ts +29 -0
- package/dist/features/resident-tab/shortcut-projection.js +64 -0
- package/dist/foundation/release/bootstrap.js +1 -0
- package/dist/foundation/resident-tabs/bridge-client.d.ts +5 -0
- package/dist/foundation/resident-tabs/bridge-client.js +17 -1
- package/dist/foundation/resident-tabs/prompt-journal.d.ts +0 -2
- package/dist/foundation/resident-tabs/prompt-journal.js +0 -1
- package/dist/integrations/pi/components/owned-editor-ux.d.ts +2 -0
- package/dist/integrations/pi/components/owned-editor-ux.js +13 -0
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +1 -0
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +1 -0
- package/dist/integrations/pi/components/shell-presenters-info.js +10 -30
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +2 -0
- package/dist/native/darwin-arm64/a1_session_lock.node +0 -0
- package/dist/native/darwin-arm64/manifest.json +3 -2
- package/dist/native/darwin-arm64/terminal-host +0 -0
- package/dist/native/darwin-arm64/terminal-host.manifest.json +7 -6
- package/dist/native/darwin-x64/a1_session_lock.node +0 -0
- package/dist/native/darwin-x64/manifest.json +5 -4
- package/dist/native/darwin-x64/process-guardian +0 -0
- package/dist/native/darwin-x64/terminal-host +0 -0
- package/dist/native/darwin-x64/terminal-host.manifest.json +7 -6
- package/dist/native/linux-x64/a1_session_lock.node +0 -0
- package/dist/native/linux-x64/manifest.json +3 -2
- package/dist/native/linux-x64/terminal-host +0 -0
- package/dist/native/linux-x64/terminal-host.manifest.json +7 -6
- package/dist/native/win32-x64/a1_session_lock.node +0 -0
- package/dist/native/win32-x64/manifest.json +4 -3
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/native/win32-x64/terminal-host.exe +0 -0
- package/dist/native/win32-x64/terminal-host.manifest.json +6 -5
- package/dist/ui/components/index.d.ts +2 -2
- package/dist/ui/components/index.js +1 -1
- package/dist/ui/components/selection-copy.d.ts +2 -0
- package/dist/ui/components/selection-copy.js +13 -0
- package/dist/ui/components/submitted-prompt.d.ts +7 -4
- package/dist/ui/components/submitted-prompt.js +18 -10
- package/dist/ui/components/transcript-viewport.d.ts +10 -6
- package/dist/ui/components/transcript-viewport.js +28 -13
- package/dist/ui/settings/declarations.d.ts +13 -1
- package/dist/ui/settings/declarations.js +12 -1
- package/dist/ui/settings/migrations.js +7 -0
- package/docs/architecture/evidence/resident-tabs/macos-x64.md +1 -1
- package/docs/architecture/process-guardian-provenance.md +1 -1
- package/docs/architecture/project-structure.md +8 -0
- package/docs/architecture/resident-tabs.md +18 -2
- package/docs/architecture/terminal-host-provenance.md +1 -1
- package/docs/architecture/toolchain.md +1 -1
- package/docs/validation.md +3 -3
- package/package.json +1 -1
|
@@ -15,6 +15,9 @@ export type TabBridgeCommand = {
|
|
|
15
15
|
readonly type: "rename";
|
|
16
16
|
readonly name: string;
|
|
17
17
|
readonly nameSource: "default" | "user" | "auto";
|
|
18
|
+
} | {
|
|
19
|
+
readonly type: "route";
|
|
20
|
+
readonly route: "settings";
|
|
18
21
|
} | {
|
|
19
22
|
readonly type: "stop";
|
|
20
23
|
readonly deadlineMs: number;
|
|
@@ -48,6 +51,8 @@ export declare class TabBridgeClient {
|
|
|
48
51
|
accent(accent: string): void;
|
|
49
52
|
session(file: string | null, name: string | null, nameSource?: "default" | "user" | "auto"): void;
|
|
50
53
|
prompt(interrupted: boolean): void;
|
|
54
|
+
/** Publishes the effective tab shortcut assignments so the host dispatches and labels the same keys. */
|
|
55
|
+
shortcuts(assignments: Readonly<Record<string, string | null>>): void;
|
|
51
56
|
requestDetach(origin?: TabAttachment | null, timeoutMs?: number): Promise<boolean>;
|
|
52
57
|
requestRestart(origin?: TabAttachment | null, timeoutMs?: number): Promise<boolean>;
|
|
53
58
|
consumeControllerBoundaryInput(data: string): string;
|
|
@@ -15,6 +15,7 @@ export class TabBridgeClient {
|
|
|
15
15
|
#latestStatus = null;
|
|
16
16
|
#accent = null;
|
|
17
17
|
#latestSession = null;
|
|
18
|
+
#latestShortcuts = null;
|
|
18
19
|
#heartbeat = null;
|
|
19
20
|
#pending = new Map();
|
|
20
21
|
#startWaiter = null;
|
|
@@ -63,7 +64,7 @@ export class TabBridgeClient {
|
|
|
63
64
|
transport.once("connect", () => {
|
|
64
65
|
this.#send("hello", {
|
|
65
66
|
role: "bridge", generation: 1, build: this.#options.build ?? "a1",
|
|
66
|
-
features: ["bridge-status", "bridge-detach", "bridge-heartbeat", "bridge-restart", "bridge-visibility", "bridge-rename", "bridge-stop", "controller-boundary", "recovery-journal"],
|
|
67
|
+
features: ["bridge-status", "bridge-detach", "bridge-heartbeat", "bridge-restart", "bridge-visibility", "bridge-rename", "bridge-route", "bridge-stop", "bridge-shortcuts", "controller-boundary", "recovery-journal"],
|
|
67
68
|
token: [...Buffer.from(this.#options.credentials.token, "base64")], tabId: this.#options.credentials.tabId,
|
|
68
69
|
pid: this.#options.pid ?? process.pid, startIdentity: this.#options.startIdentity ?? `${process.pid}:node`,
|
|
69
70
|
}, ++this.#request);
|
|
@@ -102,6 +103,16 @@ export class TabBridgeClient {
|
|
|
102
103
|
prompt(interrupted) {
|
|
103
104
|
this.#send("bridge.prompt", { interrupted });
|
|
104
105
|
}
|
|
106
|
+
/** Publishes the effective tab shortcut assignments so the host dispatches and labels the same keys. */
|
|
107
|
+
shortcuts(assignments) {
|
|
108
|
+
this.#latestShortcuts = Object.entries(assignments).map(([action, key]) => [action, key]);
|
|
109
|
+
this.#sendShortcuts();
|
|
110
|
+
}
|
|
111
|
+
#sendShortcuts() {
|
|
112
|
+
if (this.#latestShortcuts === null || !this.#supports("bridge-shortcuts"))
|
|
113
|
+
return;
|
|
114
|
+
this.#send("bridge.shortcuts", { assignments: this.#latestShortcuts.map(([action, key]) => [action, key]) });
|
|
115
|
+
}
|
|
105
116
|
requestDetach(origin = this.captureAttachment(), timeoutMs = 1_000) {
|
|
106
117
|
return this.#requestAction("detach", origin, timeoutMs);
|
|
107
118
|
}
|
|
@@ -191,6 +202,7 @@ export class TabBridgeClient {
|
|
|
191
202
|
this.status(this.#latestStatus.state, this.#latestStatus.degraded, this.#latestStatus.pendingRequests, this.#latestStatus.queuedInput);
|
|
192
203
|
if (this.#latestSession !== null)
|
|
193
204
|
this.#send("bridge.session", this.#latestSession);
|
|
205
|
+
this.#sendShortcuts();
|
|
194
206
|
return;
|
|
195
207
|
}
|
|
196
208
|
if (message.type === "incompatible-generation") {
|
|
@@ -206,6 +218,10 @@ export class TabBridgeClient {
|
|
|
206
218
|
this.#emitCommand({ type: "rename", name: message.body["name"], nameSource: source === "auto" || source === "default" ? source : "user" });
|
|
207
219
|
return;
|
|
208
220
|
}
|
|
221
|
+
if (message.type === "bridge.route" && message.body["route"] === "settings") {
|
|
222
|
+
this.#emitCommand({ type: "route", route: "settings" });
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
209
225
|
if (message.type === "bridge.stop" && typeof message.body["deadlineMs"] === "number") {
|
|
210
226
|
this.#emitCommand({ type: "stop", deadlineMs: message.body["deadlineMs"] });
|
|
211
227
|
return;
|
|
@@ -8,7 +8,6 @@ export interface SubmittedPromptRecord {
|
|
|
8
8
|
readonly fileExisted: boolean;
|
|
9
9
|
readonly kind: "prompt" | "steer" | "follow-up";
|
|
10
10
|
readonly text: string;
|
|
11
|
-
readonly images?: readonly unknown[];
|
|
12
11
|
readonly at: string;
|
|
13
12
|
}
|
|
14
13
|
export interface CorrelatedPromptRecord {
|
|
@@ -33,7 +32,6 @@ export interface PromptSubmission {
|
|
|
33
32
|
readonly fileExisted: boolean;
|
|
34
33
|
readonly kind: SubmittedPromptRecord["kind"];
|
|
35
34
|
readonly text: string;
|
|
36
|
-
readonly images?: readonly unknown[];
|
|
37
35
|
}
|
|
38
36
|
export interface SessionJournalEntry {
|
|
39
37
|
readonly entryId: string;
|
|
@@ -30,7 +30,6 @@ export class PromptJournal {
|
|
|
30
30
|
type: "submitted",
|
|
31
31
|
id: randomUUID(),
|
|
32
32
|
...submission,
|
|
33
|
-
...(submission.images === undefined ? {} : { images: submission.images }),
|
|
34
33
|
at: new Date().toISOString(),
|
|
35
34
|
};
|
|
36
35
|
await this.#append(record, "journal-before-append", "journal-after-append", "journal-after-sync");
|
|
@@ -13,6 +13,7 @@ export interface OwnedEditorUxInterceptor {
|
|
|
13
13
|
reset(): void;
|
|
14
14
|
handlePointer?(event: OwnedEditorPointerEvent): boolean;
|
|
15
15
|
hasSelection?(): boolean;
|
|
16
|
+
selectedText?(): string | undefined;
|
|
16
17
|
ownsPointer?(): boolean;
|
|
17
18
|
pasteClipboard?(): boolean;
|
|
18
19
|
cancelPendingPastes?(): void;
|
|
@@ -40,6 +41,7 @@ export declare class OwnedEditorUxInterception {
|
|
|
40
41
|
cancelPendingPastes(): void;
|
|
41
42
|
handlePointer(event: OwnedEditorPointerEvent): boolean;
|
|
42
43
|
hasSelection(): boolean;
|
|
44
|
+
selectedText(): string | undefined;
|
|
43
45
|
ownsPointer(): boolean;
|
|
44
46
|
pasteClipboard(): boolean;
|
|
45
47
|
}
|
|
@@ -39,6 +39,14 @@ export class OwnedEditorUxInterception {
|
|
|
39
39
|
hasSelection() {
|
|
40
40
|
return this.interceptors.some(interceptor => interceptor.hasSelection?.() === true);
|
|
41
41
|
}
|
|
42
|
+
selectedText() {
|
|
43
|
+
for (const interceptor of this.interceptors) {
|
|
44
|
+
const selected = interceptor.selectedText?.();
|
|
45
|
+
if (selected !== undefined)
|
|
46
|
+
return selected;
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
42
50
|
ownsPointer() {
|
|
43
51
|
return this.interceptors.some(interceptor => interceptor.ownsPointer?.() === true);
|
|
44
52
|
}
|
|
@@ -281,6 +289,11 @@ class PromptSelectionInterceptor {
|
|
|
281
289
|
hasSelection() {
|
|
282
290
|
return this.#activeRange() !== undefined;
|
|
283
291
|
}
|
|
292
|
+
selectedText() {
|
|
293
|
+
return this.#activeRange() === undefined
|
|
294
|
+
? undefined
|
|
295
|
+
: this.options.expandCopiedText(this.#selectedText());
|
|
296
|
+
}
|
|
284
297
|
pasteClipboard() {
|
|
285
298
|
this.#pasteFromClipboard();
|
|
286
299
|
return true;
|
|
@@ -346,6 +346,7 @@ export function createPiShellEditor(options) {
|
|
|
346
346
|
return editor.canPresentPromptSuggestion() ? null : "prompt-mode";
|
|
347
347
|
},
|
|
348
348
|
hasSelection: () => editorUx?.hasSelection() ?? false,
|
|
349
|
+
selectedText: () => editorUx?.selectedText(),
|
|
349
350
|
ownsPointer: () => editorUx?.ownsPointer() ?? false,
|
|
350
351
|
handlePointer: event => editorUx?.handlePointer(event) ?? false,
|
|
351
352
|
pasteClipboard: () => editorUx?.pasteClipboard() ?? false,
|
|
@@ -73,6 +73,7 @@ export interface PiShellHotkeysPresentation {
|
|
|
73
73
|
export declare function createPiShellHotkeys(bindings?: KeybindingsConfig, getShortcuts?: NonNullable<PiShellExtensionRendererResolver["getShortcuts"]>, profile?: "pi" | "a1", residentTabs?: boolean): PiShellComponentPort;
|
|
74
74
|
/** The keyboard-shortcut document rows the feed presenter shows, without its spacer, borders, and heading. */
|
|
75
75
|
export declare function renderPiShellHotkeysLines(presentation: PiShellHotkeysPresentation, width: number): readonly string[];
|
|
76
|
+
/** The global tab declarations the hotkeys document lists, straight from the feature's declarations. */
|
|
76
77
|
export declare const TAB_HOTKEYS: readonly (readonly [string, string | null, string])[];
|
|
77
78
|
export declare function hotkeysMarkdown(bindings: KeybindingsConfig | undefined, getShortcuts: NonNullable<PiShellExtensionRendererResolver["getShortcuts"]>, profile: "pi" | "a1", residentTabs?: boolean): string;
|
|
78
79
|
/**
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DynamicBorder } from "../startup-public.js";
|
|
2
2
|
import { Container, getCapabilities, hyperlink, Markdown, Spacer, Text, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
3
|
import { PRODUCT_TEXT } from "../../../product-identity.js";
|
|
4
|
+
import { projectResidentTabShortcuts, RESIDENT_TAB_GLOBAL_SHORTCUTS } from "../../../features/resident-tab/index.js";
|
|
4
5
|
import { KeybindingsManager } from "./upstream/adjacent/core/keybindings.js";
|
|
5
6
|
import { getPiHotkeysMarkdownTheme, getPiMarkdownTheme, paintPiBorder, PINNED_PI_LAYOUT, piTheme } from "./theme.js";
|
|
6
7
|
import { componentPort, ensureTheme, formatSessionTokens } from "./shell-shared-facade.js";
|
|
@@ -167,14 +168,8 @@ export function renderPiShellHotkeysLines(presentation, width) {
|
|
|
167
168
|
function hotkeysMarkdownComponent(markdown) {
|
|
168
169
|
return new Markdown(markdown, 1, 1, getPiHotkeysMarkdownTheme());
|
|
169
170
|
}
|
|
170
|
-
|
|
171
|
-
export const TAB_HOTKEYS = [
|
|
172
|
-
["tabs.new", "alt+a", "New A1 tab"], ["tabs.close", "alt+w", "Close A1 tab"],
|
|
173
|
-
["tabs.rename", "f2", "Rename A1 tab"],
|
|
174
|
-
...Array.from({ length: 10 }, (_, index) => [`tabs.jump${index + 1}`, `alt+${(index + 1) % 10}`, `View A1 tab ${index + 1}`]),
|
|
175
|
-
["tabs.next", null, "View next A1 tab"], ["tabs.previous", null, "View previous A1 tab"],
|
|
176
|
-
["tabs.moveRight", null, "Move A1 tab right"], ["tabs.moveLeft", null, "Move A1 tab left"],
|
|
177
|
-
];
|
|
171
|
+
/** The global tab declarations the hotkeys document lists, straight from the feature's declarations. */
|
|
172
|
+
export const TAB_HOTKEYS = RESIDENT_TAB_GLOBAL_SHORTCUTS.map(shortcut => [shortcut.id, shortcut.defaultKey, shortcut.description]);
|
|
178
173
|
export function hotkeysMarkdown(bindings, getShortcuts, profile, residentTabs = false) {
|
|
179
174
|
const keys = profile === "a1" ? KeybindingsManager.fromOwnedBindings(bindings) : new KeybindingsManager(bindings);
|
|
180
175
|
// Compatibility: the owned viewport consumes these physical chords before editor actions.
|
|
@@ -189,29 +184,14 @@ export function hotkeysMarkdown(bindings, getShortcuts, profile, residentTabs =
|
|
|
189
184
|
}).join(" / ")} | ${description} |`;
|
|
190
185
|
let markdown = ["**Navigation**", "| Key | Action |", "|-----|--------|", row(["tui.editor.cursorUp", "tui.editor.cursorDown", "tui.editor.cursorLeft", "tui.editor.cursorRight"], "Move cursor / browse history"), row(["tui.editor.cursorWordLeft", "tui.editor.cursorWordRight"], "Move by word"), row(["tui.editor.cursorLineStart"], profile === "a1" ? "Start of prompt line" : "Start of line"), row(["tui.editor.cursorLineEnd"], profile === "a1" ? "End of prompt line" : "End of line"), ...(profile === "a1" ? ["| `Ctrl+Home` | Start of content |", "| `Ctrl+End` | End of content / follow output |"] : []), row(["tui.editor.jumpForward"], "Jump forward to character"), row(["tui.editor.jumpBackward"], "Jump backward to character"), row(["tui.editor.pageUp", "tui.editor.pageDown"], "Scroll by page"), "", "**Editing**", "| Key | Action |", "|-----|--------|", row(["tui.input.submit"], "Send message"), row(["tui.input.newLine"], `New line${process.platform === "win32" ? " (Ctrl+Enter on Windows Terminal)" : ""}`), row(["tui.editor.deleteWordBackward"], "Delete word backwards"), row(["tui.editor.deleteWordForward"], "Delete word forwards"), row(["tui.editor.deleteToLineStart"], "Delete to start of line"), row(["tui.editor.deleteToLineEnd"], "Delete to end of line"), row(["tui.editor.yank"], "Paste the most-recently-deleted text"), row(["tui.editor.yankPop"], "Cycle through the deleted text after pasting"), row(["tui.editor.undo"], "Undo"), "", "**Other**", "| Key | Action |", "|-----|--------|", row(["tui.input.tab"], "Path completion / accept autocomplete"), row(["app.interrupt"], "Cancel autocomplete / abort streaming"), row(["app.clear"], "Clear editor (first) / exit (second)"), row(["app.exit"], "Exit (when editor is empty)"), row(["app.suspend"], "Suspend to background"), row(["app.thinking.cycle"], "Cycle thinking level"), row(["app.model.cycleForward", "app.model.cycleBackward"], "Cycle models"), row(["app.model.select"], profile === "a1" ? "Open the Models dialog" : "Open model selector"), row(["app.tools.expand"], "Toggle tool output expansion"), row(["app.thinking.toggle"], "Toggle thinking block visibility"), row(["app.editor.external"], "Edit message in external editor"), row(["app.message.copy"], "Copy selection or last assistant message"), row(["app.message.followUp"], "Queue follow-up message"), row(["app.message.dequeue"], "Restore queued messages"), row(["app.clipboard.pasteImage"], profile === "a1" ? "Paste image or text from clipboard" : "Paste files on macOS, images, or text from clipboard"), "| `/` | Slash commands |", "| `!` | Run bash command |", "| `!!` | Run bash command (excluded from context) |", ...(profile === "a1" ? ["", "**Models dialog**", "| Key | Action |", "|-----|--------|", "| `Space` | Toggle the selected model in the cycling scope |", "| `Tab` | Switch the all/scoped filter |", row(["app.models.save"], "Save the scope to settings"), row(["app.models.enableAll"], "Scope every listed model"), row(["app.models.clearAll"], "Clear the listed models from the scope"), row(["app.models.toggleProvider"], "Toggle the selected model's provider"), row(["app.models.reorderUp", "app.models.reorderDown"], "Reorder the cycling scope")] : [])].join("\n");
|
|
191
186
|
if (profile === "a1" && residentTabs) {
|
|
192
|
-
|
|
187
|
+
// Invariant: the Tabs section shows the same projection the resident shell dispatches: the
|
|
188
|
+
// effective A1 declarations keep their keys and earlier tab declarations keep duplicates.
|
|
189
|
+
const projection = projectResidentTabShortcuts({ configured: bindings, reserved: keys.getEffectiveConfig() });
|
|
193
190
|
markdown += "\n\n**Tabs**\n| Key | Action |\n|-----|--------|\n";
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const keys = typeof value === "string" ? [value] : Array.isArray(value) ? value : [];
|
|
199
|
-
for (const key of keys)
|
|
200
|
-
if (typeof key === "string")
|
|
201
|
-
claimed.add(key.toLowerCase());
|
|
202
|
-
}
|
|
203
|
-
markdown += TAB_HOTKEYS.map(([id, defaultKey, description]) => {
|
|
204
|
-
const value = configured[id];
|
|
205
|
-
const assigned = (typeof value === "string" ? [value] : Array.isArray(value) ? value.filter((key) => typeof key === "string") : defaultKey === null ? [] : [defaultKey])
|
|
206
|
-
.filter(key => {
|
|
207
|
-
const normalized = key.toLowerCase();
|
|
208
|
-
if (claimed.has(normalized))
|
|
209
|
-
return false;
|
|
210
|
-
claimed.add(normalized);
|
|
211
|
-
return true;
|
|
212
|
-
});
|
|
213
|
-
const label = assigned.length === 0 ? "Unbound" : `\`${assigned.map(shortcutDisplay).join("/")}\``;
|
|
214
|
-
return `| ${label} | ${description} |`;
|
|
191
|
+
markdown += RESIDENT_TAB_GLOBAL_SHORTCUTS.map(shortcut => {
|
|
192
|
+
const assigned = projection.assignments[shortcut.id];
|
|
193
|
+
const label = assigned === null ? "Unbound" : `\`${shortcutDisplay(assigned)}\``;
|
|
194
|
+
return `| ${label} | ${shortcut.description} |`;
|
|
215
195
|
}).join("\n");
|
|
216
196
|
}
|
|
217
197
|
const shortcuts = getShortcuts(bindings ?? keys.getEffectiveConfig());
|
|
@@ -64,6 +64,8 @@ export interface PiShellEditorPort extends PiShellComponentPort {
|
|
|
64
64
|
canPresentPromptSuggestion(): boolean;
|
|
65
65
|
promptSuggestionBlockReason?(): SuggestionDecision;
|
|
66
66
|
hasSelection(): boolean;
|
|
67
|
+
/** Exact expanded semantic editor selection without mutating or collapsing it. */
|
|
68
|
+
selectedText?(): string | undefined;
|
|
67
69
|
ownsPointer(): boolean;
|
|
68
70
|
handlePointer(event: PiShellEditorPointerEvent): boolean;
|
|
69
71
|
pasteClipboard(): boolean;
|
|
Binary file
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"platform": "darwin",
|
|
6
6
|
"architecture": "arm64",
|
|
7
7
|
"capability": "supported",
|
|
8
|
-
"builtAt": "2026-10-
|
|
8
|
+
"builtAt": "2026-10-17T13:02:46.502Z",
|
|
9
9
|
"artifact": {
|
|
10
10
|
"filename": "process-guardian",
|
|
11
11
|
"sha256": "47e9052599983a6bb0078ce6203ba18d71bec0b7b94e6a49019d11d46c3fbeca",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"language": "Rust",
|
|
16
16
|
"cargoLock": "native/process-guardian/Cargo.lock",
|
|
17
17
|
"sourceRoot": "native/process-guardian",
|
|
18
|
-
"signatureStatus": "ci-attestation-required"
|
|
18
|
+
"signatureStatus": "ci-attestation-required",
|
|
19
|
+
"identityCheck": "executed"
|
|
19
20
|
}
|
|
20
21
|
}
|
|
Binary file
|
|
@@ -7,16 +7,16 @@
|
|
|
7
7
|
"architecture": "arm64",
|
|
8
8
|
"target": "aarch64-apple-darwin",
|
|
9
9
|
"capability": "supported",
|
|
10
|
-
"builtAt": "2026-10-
|
|
10
|
+
"builtAt": "2026-10-17T13:07:42.805Z",
|
|
11
11
|
"artifact": {
|
|
12
12
|
"filename": "terminal-host",
|
|
13
|
-
"sha256": "
|
|
14
|
-
"size":
|
|
13
|
+
"sha256": "da3e4930eb0249992da208ac2ab8f38f882388e810a7bcc0c48152f03b245129",
|
|
14
|
+
"size": 5337024
|
|
15
15
|
},
|
|
16
16
|
"sessionLock": {
|
|
17
17
|
"filename": "a1_session_lock.node",
|
|
18
|
-
"sha256": "
|
|
19
|
-
"size":
|
|
18
|
+
"sha256": "44682ec58d0de84a447535fa579fa847ffbc332a446cc60fd02e52b73716a03e",
|
|
19
|
+
"size": 577680
|
|
20
20
|
},
|
|
21
21
|
"notices": {
|
|
22
22
|
"filename": "terminal-host-THIRD-PARTY-NOTICES.txt",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"node-addon"
|
|
40
40
|
]
|
|
41
41
|
},
|
|
42
|
-
"signatureStatus": "ci-attestation-required"
|
|
42
|
+
"signatureStatus": "ci-attestation-required",
|
|
43
|
+
"identityCheck": "executed"
|
|
43
44
|
}
|
|
44
45
|
}
|
|
Binary file
|
|
@@ -5,16 +5,17 @@
|
|
|
5
5
|
"platform": "darwin",
|
|
6
6
|
"architecture": "x64",
|
|
7
7
|
"capability": "supported",
|
|
8
|
-
"builtAt": "2026-10-
|
|
8
|
+
"builtAt": "2026-10-17T13:02:52.732Z",
|
|
9
9
|
"artifact": {
|
|
10
10
|
"filename": "process-guardian",
|
|
11
|
-
"sha256": "
|
|
12
|
-
"size":
|
|
11
|
+
"sha256": "80ac279b688fe2642c43a40669ff35afc478fc5a8bda7f6cc2ac88a98431a4ce",
|
|
12
|
+
"size": 394768
|
|
13
13
|
},
|
|
14
14
|
"provenance": {
|
|
15
15
|
"language": "Rust",
|
|
16
16
|
"cargoLock": "native/process-guardian/Cargo.lock",
|
|
17
17
|
"sourceRoot": "native/process-guardian",
|
|
18
|
-
"signatureStatus": "ci-attestation-required"
|
|
18
|
+
"signatureStatus": "ci-attestation-required",
|
|
19
|
+
"identityCheck": "executed"
|
|
19
20
|
}
|
|
20
21
|
}
|
|
Binary file
|
|
Binary file
|
|
@@ -7,16 +7,16 @@
|
|
|
7
7
|
"architecture": "x64",
|
|
8
8
|
"target": "x86_64-apple-darwin",
|
|
9
9
|
"capability": "supported",
|
|
10
|
-
"builtAt": "2026-10-
|
|
10
|
+
"builtAt": "2026-10-17T13:11:38.751Z",
|
|
11
11
|
"artifact": {
|
|
12
12
|
"filename": "terminal-host",
|
|
13
|
-
"sha256": "
|
|
14
|
-
"size":
|
|
13
|
+
"sha256": "d1b524a5bd2da42a36e40f9b2e7c27b1d0143ecff88982fea9a20ac0367472e8",
|
|
14
|
+
"size": 5815872
|
|
15
15
|
},
|
|
16
16
|
"sessionLock": {
|
|
17
17
|
"filename": "a1_session_lock.node",
|
|
18
|
-
"sha256": "
|
|
19
|
-
"size":
|
|
18
|
+
"sha256": "d1418e81a3c8f48139b90aff322d2d860eab3e033cb8d25ff7760cc9e3331555",
|
|
19
|
+
"size": 516344
|
|
20
20
|
},
|
|
21
21
|
"notices": {
|
|
22
22
|
"filename": "terminal-host-THIRD-PARTY-NOTICES.txt",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"node-addon"
|
|
40
40
|
]
|
|
41
41
|
},
|
|
42
|
-
"signatureStatus": "ci-attestation-required"
|
|
42
|
+
"signatureStatus": "ci-attestation-required",
|
|
43
|
+
"identityCheck": "executed"
|
|
43
44
|
}
|
|
44
45
|
}
|
|
Binary file
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"platform": "linux",
|
|
6
6
|
"architecture": "x64",
|
|
7
7
|
"capability": "supported",
|
|
8
|
-
"builtAt": "2026-10-
|
|
8
|
+
"builtAt": "2026-10-17T13:02:43.567Z",
|
|
9
9
|
"artifact": {
|
|
10
10
|
"filename": "process-guardian",
|
|
11
11
|
"sha256": "94a96fa9d5178a1949d05c6d6cc9504f3030cd49a096cd9db20dd29860ea5884",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"language": "Rust",
|
|
16
16
|
"cargoLock": "native/process-guardian/Cargo.lock",
|
|
17
17
|
"sourceRoot": "native/process-guardian",
|
|
18
|
-
"signatureStatus": "ci-attestation-required"
|
|
18
|
+
"signatureStatus": "ci-attestation-required",
|
|
19
|
+
"identityCheck": "executed"
|
|
19
20
|
}
|
|
20
21
|
}
|
|
Binary file
|
|
@@ -7,16 +7,16 @@
|
|
|
7
7
|
"architecture": "x64",
|
|
8
8
|
"target": "x86_64-unknown-linux-gnu",
|
|
9
9
|
"capability": "supported",
|
|
10
|
-
"builtAt": "2026-10-
|
|
10
|
+
"builtAt": "2026-10-17T13:05:45.852Z",
|
|
11
11
|
"artifact": {
|
|
12
12
|
"filename": "terminal-host",
|
|
13
|
-
"sha256": "
|
|
14
|
-
"size":
|
|
13
|
+
"sha256": "9be29443a6ea4ce4718a93539adf9fb38dd6fdc0beb110485cd01a1fc93e5918",
|
|
14
|
+
"size": 6435192
|
|
15
15
|
},
|
|
16
16
|
"sessionLock": {
|
|
17
17
|
"filename": "a1_session_lock.node",
|
|
18
|
-
"sha256": "
|
|
19
|
-
"size":
|
|
18
|
+
"sha256": "bae1affd0d1ce906258afbc97f762796630c73ab314846d10b6a5bd0fe63f54f",
|
|
19
|
+
"size": 740560
|
|
20
20
|
},
|
|
21
21
|
"notices": {
|
|
22
22
|
"filename": "terminal-host-THIRD-PARTY-NOTICES.txt",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"node-addon"
|
|
40
40
|
]
|
|
41
41
|
},
|
|
42
|
-
"signatureStatus": "ci-attestation-required"
|
|
42
|
+
"signatureStatus": "ci-attestation-required",
|
|
43
|
+
"identityCheck": "executed"
|
|
43
44
|
}
|
|
44
45
|
}
|
|
Binary file
|
|
@@ -5,16 +5,17 @@
|
|
|
5
5
|
"platform": "win32",
|
|
6
6
|
"architecture": "x64",
|
|
7
7
|
"capability": "supported",
|
|
8
|
-
"builtAt": "2026-10-
|
|
8
|
+
"builtAt": "2026-10-17T13:03:20.189Z",
|
|
9
9
|
"artifact": {
|
|
10
10
|
"filename": "process-guardian.exe",
|
|
11
|
-
"sha256": "
|
|
11
|
+
"sha256": "231de38cbd11f08c493027290c523c589d8ffbfa61d9a8e6b55c2300ed50dbad",
|
|
12
12
|
"size": 288256
|
|
13
13
|
},
|
|
14
14
|
"provenance": {
|
|
15
15
|
"language": "Rust",
|
|
16
16
|
"cargoLock": "native/process-guardian/Cargo.lock",
|
|
17
17
|
"sourceRoot": "native/process-guardian",
|
|
18
|
-
"signatureStatus": "ci-attestation-required"
|
|
18
|
+
"signatureStatus": "ci-attestation-required",
|
|
19
|
+
"identityCheck": "executed"
|
|
19
20
|
}
|
|
20
21
|
}
|
|
Binary file
|
|
Binary file
|
|
@@ -7,15 +7,15 @@
|
|
|
7
7
|
"architecture": "x64",
|
|
8
8
|
"target": "x86_64-pc-windows-msvc",
|
|
9
9
|
"capability": "supported",
|
|
10
|
-
"builtAt": "2026-10-
|
|
10
|
+
"builtAt": "2026-10-17T13:09:09.866Z",
|
|
11
11
|
"artifact": {
|
|
12
12
|
"filename": "terminal-host.exe",
|
|
13
|
-
"sha256": "
|
|
14
|
-
"size":
|
|
13
|
+
"sha256": "0b6770b00388985dc7e65e6f8fffc93eec60f85621462e388c8b25d30a0bf3c8",
|
|
14
|
+
"size": 5740544
|
|
15
15
|
},
|
|
16
16
|
"sessionLock": {
|
|
17
17
|
"filename": "a1_session_lock.node",
|
|
18
|
-
"sha256": "
|
|
18
|
+
"sha256": "a4f2407b6166aa5e12b07548c286acf2e9a744a1f58fef2bfcab2cddbad1dca1",
|
|
19
19
|
"size": 1996288
|
|
20
20
|
},
|
|
21
21
|
"notices": {
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"node-addon"
|
|
40
40
|
]
|
|
41
41
|
},
|
|
42
|
-
"signatureStatus": "ci-attestation-required"
|
|
42
|
+
"signatureStatus": "ci-attestation-required",
|
|
43
|
+
"identityCheck": "executed"
|
|
43
44
|
}
|
|
44
45
|
}
|
|
@@ -32,8 +32,8 @@ export { readVisibleHyperlinks } from "./visible-hyperlinks.js";
|
|
|
32
32
|
export type { VisibleHyperlinkRange, VisibleHyperlinkRow } from "./visible-hyperlinks.js";
|
|
33
33
|
export { renderStatusLine, statusText } from "./status-line.js";
|
|
34
34
|
export type { StatusLineInput } from "./status-line.js";
|
|
35
|
-
export { SUBMITTED_PROMPT_PREFIX_WIDTH, composeSubmittedPromptRows, formatSubmittedPromptTime, submittedPromptLayout } from "./submitted-prompt.js";
|
|
36
|
-
export type { SubmittedPromptLayout, SubmittedPromptStyle } from "./submitted-prompt.js";
|
|
35
|
+
export { SUBMITTED_PROMPT_PREFIX_WIDTH, composeSubmittedPromptRows, formatLocalTime, formatSubmittedPromptTime, submittedPromptLayout } from "./submitted-prompt.js";
|
|
36
|
+
export type { SubmittedPromptLayout, SubmittedPromptStyle, UiTimeFormat } from "./submitted-prompt.js";
|
|
37
37
|
export { numericValues, steppedValue, stepperEnds } from "./stepper.js";
|
|
38
38
|
export type { NumericRange } from "./stepper.js";
|
|
39
39
|
export { TranscriptViewport, assertTranscriptViewportFrameDescriptor } from "./transcript-viewport.js";
|
|
@@ -16,7 +16,7 @@ export { GLOBAL_SCOPE, ShortcutRegistry, assembleShortcuts, assertNoShortcutConf
|
|
|
16
16
|
export { backgroundSgrSpan, heldNativeHyperlinkStyle, hyperlinkSgrSpan, hyperlinkTargetAtColumn, nativeHyperlinkStyle, overlaySpan } from "./spans.js";
|
|
17
17
|
export { readVisibleHyperlinks } from "./visible-hyperlinks.js";
|
|
18
18
|
export { renderStatusLine, statusText } from "./status-line.js";
|
|
19
|
-
export { SUBMITTED_PROMPT_PREFIX_WIDTH, composeSubmittedPromptRows, formatSubmittedPromptTime, submittedPromptLayout } from "./submitted-prompt.js";
|
|
19
|
+
export { SUBMITTED_PROMPT_PREFIX_WIDTH, composeSubmittedPromptRows, formatLocalTime, formatSubmittedPromptTime, submittedPromptLayout } from "./submitted-prompt.js";
|
|
20
20
|
export { numericValues, steppedValue, stepperEnds } from "./stepper.js";
|
|
21
21
|
export { TranscriptViewport, assertTranscriptViewportFrameDescriptor } from "./transcript-viewport.js";
|
|
22
22
|
export { RAIL_COLUMNS, renderEmptyState, withScrollbarRail } from "./surface.js";
|
|
@@ -20,5 +20,7 @@ export interface SelectionCopySnapshot {
|
|
|
20
20
|
}
|
|
21
21
|
/** Shares the viewport's semantic chrome exclusions with isolated copy preparation. */
|
|
22
22
|
export declare function selectionCopyLineContent(text: string, prompt: SelectionCopyPrompt): TextSelectionLineContent;
|
|
23
|
+
/** Builds an immutable exact-text snapshot without changing editor-owned selection state. */
|
|
24
|
+
export declare function literalSelectionCopySnapshot(text: string, revision?: number): SelectionCopySnapshot | null;
|
|
23
25
|
/** Extracts one snapshot row with the existing grapheme/newline policy; run expensive rows off-thread. */
|
|
24
26
|
export declare function selectionCopyRowText(snapshot: Pick<SelectionCopySnapshot, "selection" | "literal">, row: SelectionCopyRow, index: number): string;
|
|
@@ -19,6 +19,19 @@ export function selectionCopyLineContent(text, prompt) {
|
|
|
19
19
|
return { from, to: from + 1 };
|
|
20
20
|
return usefulTextLineContent(plain, from);
|
|
21
21
|
}
|
|
22
|
+
/** Builds an immutable exact-text snapshot without changing editor-owned selection state. */
|
|
23
|
+
export function literalSelectionCopySnapshot(text, revision = 0) {
|
|
24
|
+
if (text.trim().length === 0)
|
|
25
|
+
return null;
|
|
26
|
+
const selection = {
|
|
27
|
+
start: { line: 0, column: 0 },
|
|
28
|
+
end: { line: 0, column: Number.MAX_SAFE_INTEGER },
|
|
29
|
+
};
|
|
30
|
+
if (text.length > MAX_COPY_SOURCE_UNITS) {
|
|
31
|
+
return { literal: true, selection, revision, rows: [], sourceUnits: 0, rejected: "size" };
|
|
32
|
+
}
|
|
33
|
+
return { literal: true, selection, revision, rows: [{ text }], sourceUnits: text.length };
|
|
34
|
+
}
|
|
22
35
|
/** Extracts one snapshot row with the existing grapheme/newline policy; run expensive rows off-thread. */
|
|
23
36
|
export function selectionCopyRowText(snapshot, row, index) {
|
|
24
37
|
if (snapshot.literal)
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export type UiTimeFormat = "20:00" | "8:00 PM";
|
|
2
|
+
/** Deterministic local hour/minute presentation shared by A1-owned time labels. */
|
|
3
|
+
export declare function formatLocalTime(source: Date | number, format?: UiTimeFormat): string | null;
|
|
1
4
|
/** Visible width of the submitted-prompt prefix (`❯ `). */
|
|
2
5
|
export declare const SUBMITTED_PROMPT_PREFIX_WIDTH = 2;
|
|
3
6
|
export interface SubmittedPromptStyle {
|
|
@@ -8,16 +11,16 @@ export interface SubmittedPromptLayout {
|
|
|
8
11
|
readonly contentWidth: number;
|
|
9
12
|
readonly timestamp: string | null;
|
|
10
13
|
}
|
|
11
|
-
/** Formats transcript metadata, never render time,
|
|
12
|
-
export declare function formatSubmittedPromptTime(source: Date | number): string | null;
|
|
14
|
+
/** Formats transcript metadata, never render time, in the active A1 time format. */
|
|
15
|
+
export declare function formatSubmittedPromptTime(source: Date | number, format?: UiTimeFormat): string | null;
|
|
13
16
|
/**
|
|
14
17
|
* Computes the width at which the prompt's Markdown body must be rendered.
|
|
15
18
|
* The timestamp is omitted rather than allowing it to crowd useful content.
|
|
16
19
|
*/
|
|
17
|
-
export declare function submittedPromptLayout(width: number, source?: Date | number | null): SubmittedPromptLayout;
|
|
20
|
+
export declare function submittedPromptLayout(width: number, source?: Date | number | null, format?: UiTimeFormat): SubmittedPromptLayout;
|
|
18
21
|
/**
|
|
19
22
|
* Composes already-rendered prompt content into the compact submitted bar.
|
|
20
23
|
* Continuations align below the content, not below the prefix, and no row can
|
|
21
24
|
* exceed the supplied terminal width even when the content renderer misbehaves.
|
|
22
25
|
*/
|
|
23
|
-
export declare function composeSubmittedPromptRows(contentRows: readonly string[], width: number, source?: Date | number | null, style?: SubmittedPromptStyle): readonly string[];
|
|
26
|
+
export declare function composeSubmittedPromptRows(contentRows: readonly string[], width: number, source?: Date | number | null, style?: SubmittedPromptStyle, format?: UiTimeFormat): readonly string[];
|
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
import { displayWidth, truncateToWidth } from "./text.js";
|
|
2
|
+
/** Deterministic local hour/minute presentation shared by A1-owned time labels. */
|
|
3
|
+
export function formatLocalTime(source, format = "8:00 PM") {
|
|
4
|
+
const date = source instanceof Date ? source : new Date(source);
|
|
5
|
+
if (!Number.isFinite(date.getTime()))
|
|
6
|
+
return null;
|
|
7
|
+
const hour = date.getHours();
|
|
8
|
+
const minute = String(date.getMinutes()).padStart(2, "0");
|
|
9
|
+
if (format === "20:00")
|
|
10
|
+
return `${String(hour).padStart(2, "0")}:${minute}`;
|
|
11
|
+
return `${hour % 12 || 12}:${minute} ${hour < 12 ? "AM" : "PM"}`;
|
|
12
|
+
}
|
|
2
13
|
/** Visible width of the submitted-prompt prefix (`❯ `). */
|
|
3
14
|
export const SUBMITTED_PROMPT_PREFIX_WIDTH = 2;
|
|
4
15
|
const TIMESTAMP_MARGIN = 3;
|
|
5
16
|
const MIN_USEFUL_CONTENT_WIDTH = 8;
|
|
6
|
-
/** Formats transcript metadata, never render time,
|
|
7
|
-
export function formatSubmittedPromptTime(source) {
|
|
8
|
-
|
|
9
|
-
if (!Number.isFinite(date.getTime()))
|
|
10
|
-
return null;
|
|
11
|
-
return `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
|
|
17
|
+
/** Formats transcript metadata, never render time, in the active A1 time format. */
|
|
18
|
+
export function formatSubmittedPromptTime(source, format = "8:00 PM") {
|
|
19
|
+
return formatLocalTime(source, format);
|
|
12
20
|
}
|
|
13
21
|
/**
|
|
14
22
|
* Computes the width at which the prompt's Markdown body must be rendered.
|
|
15
23
|
* The timestamp is omitted rather than allowing it to crowd useful content.
|
|
16
24
|
*/
|
|
17
|
-
export function submittedPromptLayout(width, source) {
|
|
25
|
+
export function submittedPromptLayout(width, source, format = "8:00 PM") {
|
|
18
26
|
const boundedWidth = Math.max(1, width);
|
|
19
|
-
const timestamp = source === undefined || source === null ? null : formatSubmittedPromptTime(source);
|
|
27
|
+
const timestamp = source === undefined || source === null ? null : formatSubmittedPromptTime(source, format);
|
|
20
28
|
const timestampReserve = timestamp === null ? 0 : displayWidth(timestamp) + TIMESTAMP_MARGIN;
|
|
21
29
|
const canShowTimestamp = timestamp !== null
|
|
22
30
|
&& boundedWidth - SUBMITTED_PROMPT_PREFIX_WIDTH - timestampReserve >= MIN_USEFUL_CONTENT_WIDTH;
|
|
@@ -30,10 +38,10 @@ export function submittedPromptLayout(width, source) {
|
|
|
30
38
|
* Continuations align below the content, not below the prefix, and no row can
|
|
31
39
|
* exceed the supplied terminal width even when the content renderer misbehaves.
|
|
32
40
|
*/
|
|
33
|
-
export function composeSubmittedPromptRows(contentRows, width, source, style = {}) {
|
|
41
|
+
export function composeSubmittedPromptRows(contentRows, width, source, style = {}, format = "8:00 PM") {
|
|
34
42
|
if (width <= 0)
|
|
35
43
|
return [];
|
|
36
|
-
const layout = submittedPromptLayout(width, source);
|
|
44
|
+
const layout = submittedPromptLayout(width, source, format);
|
|
37
45
|
const prefix = (style.prefix ?? identity)("❯ ");
|
|
38
46
|
const rows = (contentRows.length === 0 ? [""] : contentRows).map((row, index) => {
|
|
39
47
|
const content = truncateToWidth(row, layout.contentWidth);
|