@timurproko/a1 0.2.7-dev.779 → 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.
Files changed (139) hide show
  1. package/dist/app/session-shell/session-shell-root.d.ts +0 -1
  2. package/dist/app/session-shell/session-shell-root.js +45 -18
  3. package/dist/app/session-shell/session-shell.js +10 -5
  4. package/dist/app/session-shell/session-viewport-controller.d.ts +2 -2
  5. package/dist/app/session-shell/session-viewport-controller.js +24 -12
  6. package/dist/app/session-shell/shell-host.d.ts +0 -2
  7. package/dist/app/session-shell/shell-host.js +3 -20
  8. package/dist/cli/tabs.js +15 -0
  9. package/dist/composition/owned-ui.d.ts +1 -1
  10. package/dist/composition/owned-ui.js +66 -32
  11. package/dist/contracts/owned-ui/index.d.ts +1 -1
  12. package/dist/contracts/owned-ui/model.d.ts +3 -0
  13. package/dist/contracts/owned-ui/session-workflows.d.ts +4 -1
  14. package/dist/features/owned-ui/settings-app.js +9 -6
  15. package/dist/features/resident-tab/auto-name.d.ts +2 -2
  16. package/dist/features/resident-tab/auto-name.js +7 -5
  17. package/dist/features/resident-tab/index.d.ts +4 -2
  18. package/dist/features/resident-tab/index.js +6 -2
  19. package/dist/features/resident-tab/shortcut-bindings-file.d.ts +8 -0
  20. package/dist/features/resident-tab/shortcut-bindings-file.js +40 -0
  21. package/dist/features/resident-tab/{shortcuts.d.ts → shortcut-declarations.d.ts} +5 -2
  22. package/dist/features/resident-tab/{shortcuts.js → shortcut-declarations.js} +5 -17
  23. package/dist/features/resident-tab/shortcut-projection.d.ts +29 -0
  24. package/dist/features/resident-tab/shortcut-projection.js +64 -0
  25. package/dist/foundation/release/bootstrap.js +1 -0
  26. package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
  27. package/dist/foundation/release/progress-palette.generated.js +2 -2
  28. package/dist/foundation/resident-tabs/bridge-client.d.ts +5 -0
  29. package/dist/foundation/resident-tabs/bridge-client.js +17 -1
  30. package/dist/foundation/resident-tabs/prompt-journal.d.ts +0 -2
  31. package/dist/foundation/resident-tabs/prompt-journal.js +0 -1
  32. package/dist/foundation/startup/startup-descriptor.js +2 -2
  33. package/dist/integrations/pi/components/owned-editor-ux.d.ts +2 -0
  34. package/dist/integrations/pi/components/owned-editor-ux.js +13 -0
  35. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
  36. package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
  37. package/dist/integrations/pi/components/share-operation-dialog.d.ts +2 -0
  38. package/dist/integrations/pi/components/share-operation-dialog.js +2 -1
  39. package/dist/integrations/pi/components/shell-editor-autocomplete.js +1 -0
  40. package/dist/integrations/pi/components/shell-presenters-info.d.ts +1 -0
  41. package/dist/integrations/pi/components/shell-presenters-info.js +10 -30
  42. package/dist/integrations/pi/components/shell-selectors-dialogs.js +1 -0
  43. package/dist/integrations/pi/components/shell-shared-facade.d.ts +2 -0
  44. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  45. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
  46. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  47. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  48. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  49. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  50. package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
  51. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  52. package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
  53. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  54. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
  55. package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
  56. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  57. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  58. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  59. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  60. package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
  61. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  62. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  63. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
  64. package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
  65. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  66. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  67. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  68. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
  69. package/dist/integrations/pi/components/upstream/components/tool-execution.js +1 -1
  70. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
  71. package/dist/integrations/pi/components/upstream/components/tree-selector.js +3 -11
  72. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  73. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  74. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +1 -1
  75. package/dist/integrations/pi/components/upstream/history/editor-core.js +1 -1
  76. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  77. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  78. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  79. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  80. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  81. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  82. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  83. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  84. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
  85. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  86. package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
  87. package/dist/integrations/pi/engine/pi-settings-metadata.json +12 -0
  88. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  89. package/dist/integrations/pi/engine/settings-bridge.js +2 -0
  90. package/dist/integrations/pi/engine/settings-port.js +10 -1
  91. package/dist/integrations/pi/engine/workflow-runner.js +64 -2
  92. package/dist/integrations/pi/engine/workflow-support.d.ts +12 -0
  93. package/dist/integrations/pi/engine/workflow-support.js +36 -0
  94. package/dist/integrations/pi/engine/workflows.d.ts +3 -1
  95. package/dist/integrations/pi/engine/workflows.js +1 -0
  96. package/dist/integrations/pi/startup-public.js +38 -35
  97. package/dist/integrations/pi/startup-public.manifest.json +110 -116
  98. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  99. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
  100. package/dist/native/darwin-arm64/a1_session_lock.node +0 -0
  101. package/dist/native/darwin-arm64/manifest.json +3 -2
  102. package/dist/native/darwin-arm64/terminal-host +0 -0
  103. package/dist/native/darwin-arm64/terminal-host.manifest.json +7 -6
  104. package/dist/native/darwin-x64/a1_session_lock.node +0 -0
  105. package/dist/native/darwin-x64/manifest.json +5 -4
  106. package/dist/native/darwin-x64/process-guardian +0 -0
  107. package/dist/native/darwin-x64/terminal-host +0 -0
  108. package/dist/native/darwin-x64/terminal-host.manifest.json +7 -6
  109. package/dist/native/linux-x64/a1_session_lock.node +0 -0
  110. package/dist/native/linux-x64/manifest.json +3 -2
  111. package/dist/native/linux-x64/terminal-host +0 -0
  112. package/dist/native/linux-x64/terminal-host.manifest.json +7 -6
  113. package/dist/native/win32-x64/a1_session_lock.node +0 -0
  114. package/dist/native/win32-x64/manifest.json +4 -3
  115. package/dist/native/win32-x64/process-guardian.exe +0 -0
  116. package/dist/native/win32-x64/terminal-host.exe +0 -0
  117. package/dist/native/win32-x64/terminal-host.manifest.json +6 -5
  118. package/dist/runtime-payload-inventory.json +4242 -3716
  119. package/dist/ui/components/index.d.ts +2 -2
  120. package/dist/ui/components/index.js +1 -1
  121. package/dist/ui/components/selection-copy.d.ts +2 -0
  122. package/dist/ui/components/selection-copy.js +13 -0
  123. package/dist/ui/components/submitted-prompt.d.ts +7 -4
  124. package/dist/ui/components/submitted-prompt.js +18 -10
  125. package/dist/ui/components/transcript-viewport.d.ts +10 -6
  126. package/dist/ui/components/transcript-viewport.js +28 -13
  127. package/dist/ui/settings/declarations.d.ts +13 -1
  128. package/dist/ui/settings/declarations.js +12 -1
  129. package/dist/ui/settings/migrations.js +7 -0
  130. package/docs/architecture/evidence/resident-tabs/macos-x64.md +1 -1
  131. package/docs/architecture/process-guardian-provenance.md +1 -1
  132. package/docs/architecture/project-structure.md +8 -0
  133. package/docs/architecture/resident-tabs.md +18 -2
  134. package/docs/architecture/terminal-host-provenance.md +1 -1
  135. package/docs/architecture/toolchain.md +2 -2
  136. package/docs/ci-release-runbook.md +2 -2
  137. package/docs/openspec-archive-automation.md +5 -5
  138. package/docs/validation.md +12 -4
  139. package/package.json +3 -3
@@ -1,5 +1,5 @@
1
1
  import { DIALOG_BACK_SHORTCUT_HINT, DIALOG_CLOSE_SHORTCUT_HINT } from "../../contracts/presentation/index.js";
2
- import { GLOBAL_SCOPE, LineInput, PLAIN_THEME, ShortcutRegistry, assertNoShortcutConflicts, blockJumpTarget, numericValues, RAIL_COLUMNS, renderDialogPanel, renderSteppedDialogPanel, renderEmptyState, renderGroupHeader, renderInputRow, renderListRow, renderNote, renderShortcutHintsWithClose, menuRowAt, regionAt, renderValueMenu, withScrollbarRail, stepperEnds, steppedValue, truncateToWidth, valueColumnFor, valueMenuFrame, blockRowSpan, displayWidth, handleLineInputKey, humanizeLabel, humanizeTitle, indexOfKey, layoutList, moveSelection, rowKey, scrollForSelection, scrollForTrackPage, scrollbarGeometry, scrollbarPresentation, ScrollbarRails, scrollbarWheelRows, selectableIndexes, } from "../../ui/components/index.js";
2
+ import { GLOBAL_SCOPE, LineInput, PLAIN_THEME, ShortcutRegistry, assertNoShortcutConflicts, blockJumpTarget, numericValues, RAIL_COLUMNS, renderDialogPanel, renderSteppedDialogPanel, renderEmptyState, renderGroupHeader, renderInputRow, renderListRow, renderNote, renderShortcutHintsWithClose, menuRowAt, regionAt, renderValueMenu, withScrollbarRail, stepperEnds, steppedValue, truncateToWidth, valueColumnFor, valueMenuFrame, blockRowSpan, displayWidth, formatLocalTime, handleLineInputKey, humanizeLabel, humanizeTitle, indexOfKey, layoutList, moveSelection, rowKey, scrollForSelection, scrollForTrackPage, scrollbarGeometry, scrollbarPresentation, ScrollbarRails, scrollbarWheelRows, selectableIndexes, } from "../../ui/components/index.js";
3
3
  import { SETTINGS_APP_ID } from "./settings-route.js";
4
4
  export { SETTINGS_APP_ID, SETTINGS_ROUTE } from "./settings-route.js";
5
5
  const SCOPE = SETTINGS_APP_ID;
@@ -921,7 +921,7 @@ export class SettingsApp {
921
921
  ? CONFIGURE
922
922
  : shown === null
923
923
  ? describeRaw(entry.rawValue)
924
- : displayValue(shown);
924
+ : displaySettingValue(entry, shown);
925
925
  const range = rangeOf(entry);
926
926
  return {
927
927
  key,
@@ -938,11 +938,11 @@ export class SettingsApp {
938
938
  return lines;
939
939
  }
940
940
  const state = {
941
- choices: menu.choices.map(choice => displayValue(choice)),
941
+ choices: menu.choices.map(choice => displaySettingValue(menu.entry, choice)),
942
942
  ...(menu.entry.id === "accentColor" ? {
943
943
  previews: menu.choices.map(choice => theme.accentPreview?.(String(choice), "■") ?? ""),
944
944
  } : {}),
945
- current: this.#shownValue(menu.entry) === null ? null : displayValue(this.#shownValue(menu.entry)),
945
+ current: this.#shownValue(menu.entry) === null ? null : displaySettingValue(menu.entry, this.#shownValue(menu.entry)),
946
946
  index: menu.index,
947
947
  };
948
948
  const frame = valueMenuFrame(state, {
@@ -1084,8 +1084,11 @@ function labelOf(entry) {
1084
1084
  function rangeOf(entry) {
1085
1085
  return { minimum: entry.minimum, maximum: entry.maximum, values: numericValues(entry.choices) };
1086
1086
  }
1087
- /** Booleans read as yes and no; everything else prints as itself. */
1088
- function displayValue(value) {
1087
+ /** Booleans read as yes and no; time-format choices preview the current local time. */
1088
+ function displaySettingValue(entry, value) {
1089
+ if (entry.backend === "a1" && entry.id === "timeFormat" && (value === "20:00" || value === "8:00 PM")) {
1090
+ return formatLocalTime(new Date(), value) ?? value;
1091
+ }
1089
1092
  if (typeof value === "boolean")
1090
1093
  return value ? "yes" : "no";
1091
1094
  return String(value);
@@ -1,6 +1,6 @@
1
1
  export declare const AUTO_NAME_MAX_LENGTH = 16;
2
- export declare const AUTO_NAME_TIMEOUT_MS = 10000;
3
- export declare const AUTO_NAME_MAX_TOKENS = 64;
2
+ export declare const AUTO_NAME_TIMEOUT_MS = 30000;
3
+ export declare const AUTO_NAME_TOKEN_BUDGETS: readonly [4096, 32768];
4
4
  export declare function normalizeAutoName(value: string): string | null;
5
5
  export declare function fallbackAutoName(prompt: string): string;
6
6
  export interface AutoNameCompletion {
@@ -1,6 +1,8 @@
1
1
  export const AUTO_NAME_MAX_LENGTH = 16;
2
- export const AUTO_NAME_TIMEOUT_MS = 10_000;
3
- export const AUTO_NAME_MAX_TOKENS = 64;
2
+ export const AUTO_NAME_TIMEOUT_MS = 30_000;
3
+ // Rationale: reasoning models can spend a small ceiling on hidden thinking and emit no title, so an
4
+ // answerless attempt retries with a larger bound; budgets stay strictly increasing, as in v2.
5
+ export const AUTO_NAME_TOKEN_BUDGETS = [4_096, 32_768];
4
6
  export function normalizeAutoName(value) {
5
7
  const normalized = value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-");
6
8
  if (!normalized)
@@ -17,14 +19,14 @@ export function fallbackAutoName(prompt) {
17
19
  return normalizeAutoName(words.slice(0, 3).join("-")) ?? "new-task";
18
20
  }
19
21
  export async function generateAutoName(firstPrompt, complete, timeoutMs = AUTO_NAME_TIMEOUT_MS) {
20
- for (let attempt = 0; attempt < 2; attempt++) {
22
+ for (const maxTokens of AUTO_NAME_TOKEN_BUDGETS) {
21
23
  const controller = new AbortController();
22
24
  const timer = setTimeout(() => controller.abort(), timeoutMs);
23
25
  timer.unref?.();
24
26
  try {
25
27
  const response = await complete({
26
28
  prompt: `Name this coding task with a lowercase hyphenated title of at most ${AUTO_NAME_MAX_LENGTH} characters. Reply only with the title.\n\n${firstPrompt.slice(0, 500)}`,
27
- maxTokens: AUTO_NAME_MAX_TOKENS,
29
+ maxTokens,
28
30
  signal: controller.signal,
29
31
  });
30
32
  const name = response === null ? null : normalizeAutoName(response);
@@ -32,7 +34,7 @@ export async function generateAutoName(firstPrompt, complete, timeoutMs = AUTO_N
32
34
  return name;
33
35
  }
34
36
  catch {
35
- // Rationale: naming is best effort; one retry precedes the deterministic fallback.
37
+ // Rationale: naming is best effort; the larger bounded attempt precedes the deterministic fallback.
36
38
  }
37
39
  finally {
38
40
  clearTimeout(timer);
@@ -1,3 +1,5 @@
1
- export { AUTO_NAME_MAX_LENGTH, AUTO_NAME_MAX_TOKENS, AUTO_NAME_TIMEOUT_MS, fallbackAutoName, generateAutoName, normalizeAutoName, type AutoNameCompletion, } from "./auto-name.js";
2
- export { RESIDENT_TAB_SHORTCUTS, residentTabShortcutRegistry, type ResidentTabAction, type ResidentTabShortcut, } from "./shortcuts.js";
1
+ export { AUTO_NAME_MAX_LENGTH, AUTO_NAME_TIMEOUT_MS, AUTO_NAME_TOKEN_BUDGETS, fallbackAutoName, generateAutoName, normalizeAutoName, type AutoNameCompletion, } from "./auto-name.js";
2
+ export { RESIDENT_TAB_SHORTCUTS, type ResidentTabAction, type ResidentTabShortcut, } from "./shortcut-declarations.js";
3
+ export { projectResidentTabShortcuts, RESIDENT_TAB_GLOBAL_SHORTCUTS, type ResidentTabGlobalAction, type ResidentTabShortcutConflict, type ResidentTabShortcutProjection, type ShortcutBindings, } from "./shortcut-projection.js";
4
+ export { readShortcutBindingsFile } from "./shortcut-bindings-file.js";
3
5
  export { deriveResidentTabStatus, type ResidentTabDerivedStatus, type ResidentTabFacts, } from "./status-deriver.js";
@@ -1,3 +1,7 @@
1
- export { AUTO_NAME_MAX_LENGTH, AUTO_NAME_MAX_TOKENS, AUTO_NAME_TIMEOUT_MS, fallbackAutoName, generateAutoName, normalizeAutoName, } from "./auto-name.js";
2
- export { RESIDENT_TAB_SHORTCUTS, residentTabShortcutRegistry, } from "./shortcuts.js";
1
+ export { AUTO_NAME_MAX_LENGTH, AUTO_NAME_TIMEOUT_MS, AUTO_NAME_TOKEN_BUDGETS, fallbackAutoName, generateAutoName, normalizeAutoName, } from "./auto-name.js";
2
+ // Performance: the registry builder lives in `shortcuts.ts`, outside this barrel, so startup
3
+ // presentation can read the declarations without loading the component registry.
4
+ export { RESIDENT_TAB_SHORTCUTS, } from "./shortcut-declarations.js";
5
+ export { projectResidentTabShortcuts, RESIDENT_TAB_GLOBAL_SHORTCUTS, } from "./shortcut-projection.js";
6
+ export { readShortcutBindingsFile } from "./shortcut-bindings-file.js";
3
7
  export { deriveResidentTabStatus, } from "./status-deriver.js";
@@ -0,0 +1,8 @@
1
+ import type { ShortcutBindings } from "./shortcut-projection.js";
2
+ /** Largest `keybindings.json` the projection reads; a larger file counts as absent. */
3
+ export declare const MAX_SHORTCUT_BINDINGS_BYTES: number;
4
+ /**
5
+ * Reads the user's `keybindings.json` as shortcut bindings, keeping `null` entries so an
6
+ * explicit unbind survives, and treating any unreadable or malformed file as empty.
7
+ */
8
+ export declare function readShortcutBindingsFile(agentDir: string): ShortcutBindings;
@@ -0,0 +1,40 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ /** Largest `keybindings.json` the projection reads; a larger file counts as absent. */
4
+ export const MAX_SHORTCUT_BINDINGS_BYTES = 256 * 1024;
5
+ /**
6
+ * Reads the user's `keybindings.json` as shortcut bindings, keeping `null` entries so an
7
+ * explicit unbind survives, and treating any unreadable or malformed file as empty.
8
+ */
9
+ export function readShortcutBindingsFile(agentDir) {
10
+ let text;
11
+ try {
12
+ text = readFileSync(join(agentDir, "keybindings.json"), "utf8");
13
+ }
14
+ catch {
15
+ return {};
16
+ }
17
+ if (text.length > MAX_SHORTCUT_BINDINGS_BYTES)
18
+ return {};
19
+ let parsed;
20
+ try {
21
+ parsed = JSON.parse(text.replace(/^/u, ""));
22
+ }
23
+ catch {
24
+ return {};
25
+ }
26
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
27
+ return {};
28
+ const bindings = {};
29
+ for (const [action, value] of Object.entries(parsed)) {
30
+ if (action === "$schema")
31
+ continue;
32
+ if (value === null || typeof value === "string") {
33
+ bindings[action] = value;
34
+ continue;
35
+ }
36
+ if (Array.isArray(value))
37
+ bindings[action] = value.filter((key) => typeof key === "string");
38
+ }
39
+ return bindings;
40
+ }
@@ -1,4 +1,3 @@
1
- import { ShortcutRegistry } from "../../ui/components/index.js";
2
1
  export type ResidentTabAction = "tabs.new" | "tabs.close" | "tabs.rename" | "tabs.retry" | "tabs.fresh" | "tabs.next" | "tabs.previous" | "tabs.moveRight" | "tabs.moveLeft" | `tabs.jump${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10}`;
3
2
  export interface ResidentTabShortcut {
4
3
  readonly id: ResidentTabAction;
@@ -6,5 +5,9 @@ export interface ResidentTabShortcut {
6
5
  readonly scope: "global" | "failed-banner";
7
6
  readonly description: string;
8
7
  }
8
+ /**
9
+ * The tab shortcut declarations, in the order that decides which action keeps a duplicated key.
10
+ * This module stays dependency-free so startup presentation and the resident projection can
11
+ * read it without loading the component registry.
12
+ */
9
13
  export declare const RESIDENT_TAB_SHORTCUTS: readonly ResidentTabShortcut[];
10
- export declare function residentTabShortcutRegistry(assignments?: Readonly<Partial<Record<ResidentTabAction, string | null>>>): ShortcutRegistry<ResidentTabAction>;
@@ -1,10 +1,14 @@
1
- import { GLOBAL_SCOPE, ShortcutRegistry } from "../../ui/components/index.js";
2
1
  const jumps = Array.from({ length: 10 }, (_, index) => ({
3
2
  id: `tabs.jump${index + 1}`,
4
3
  defaultKey: `alt+${(index + 1) % 10}`,
5
4
  scope: "global",
6
5
  description: `View A1 tab ${index + 1}`,
7
6
  }));
7
+ /**
8
+ * The tab shortcut declarations, in the order that decides which action keeps a duplicated key.
9
+ * This module stays dependency-free so startup presentation and the resident projection can
10
+ * read it without loading the component registry.
11
+ */
8
12
  export const RESIDENT_TAB_SHORTCUTS = Object.freeze([
9
13
  { id: "tabs.new", defaultKey: "alt+a", scope: "global", description: "New A1 tab" },
10
14
  { id: "tabs.close", defaultKey: "alt+w", scope: "global", description: "Close A1 tab" },
@@ -17,19 +21,3 @@ export const RESIDENT_TAB_SHORTCUTS = Object.freeze([
17
21
  { id: "tabs.retry", defaultKey: "r", scope: "failed-banner", description: "Retry failed A1 tab" },
18
22
  { id: "tabs.fresh", defaultKey: "f", scope: "failed-banner", description: "Start failed A1 tab fresh" },
19
23
  ]);
20
- export function residentTabShortcutRegistry(assignments = {}) {
21
- const registry = new ShortcutRegistry();
22
- for (const shortcut of RESIDENT_TAB_SHORTCUTS) {
23
- const key = assignments[shortcut.id] === undefined ? shortcut.defaultKey : assignments[shortcut.id];
24
- if (!key)
25
- continue;
26
- const declaration = {
27
- key,
28
- scope: shortcut.scope === "global" ? GLOBAL_SCOPE : shortcut.scope,
29
- section: "Tabs",
30
- description: shortcut.description,
31
- };
32
- registry.declare(declaration, shortcut.id);
33
- }
34
- return registry;
35
- }
@@ -0,0 +1,29 @@
1
+ import { type ResidentTabAction } from "./shortcut-declarations.js";
2
+ /** Key assignments as `keybindings.json` and the keybinding manager express them. */
3
+ export type ShortcutBindings = Readonly<Record<string, string | readonly string[] | null | undefined>>;
4
+ export type ResidentTabGlobalAction = Exclude<ResidentTabAction, "tabs.retry" | "tabs.fresh">;
5
+ export interface ResidentTabShortcutConflict {
6
+ readonly id: ResidentTabGlobalAction;
7
+ readonly key: string;
8
+ /** `reserved` keys belong to an A1 action; `duplicate` keys were claimed by an earlier tab action. */
9
+ readonly reason: "reserved" | "duplicate";
10
+ }
11
+ /** The effective tab shortcuts the resident shell dispatches and every presentation shows. */
12
+ export interface ResidentTabShortcutProjection {
13
+ readonly assignments: Readonly<Record<ResidentTabGlobalAction, string | null>>;
14
+ readonly conflicts: readonly ResidentTabShortcutConflict[];
15
+ }
16
+ export interface ResidentTabShortcutInput {
17
+ /** The user's `keybindings.json`, including any `tabs.*` entries; `null` unbinds an action. */
18
+ readonly configured?: ShortcutBindings | undefined;
19
+ /** The effective A1 declarations (defaults plus customization) whose keys tab actions may not take. */
20
+ readonly reserved?: ShortcutBindings | undefined;
21
+ }
22
+ /** The declarations the projection covers, in the order that decides duplicate claims. */
23
+ export declare const RESIDENT_TAB_GLOBAL_SHORTCUTS: import("./shortcut-declarations.js").ResidentTabShortcut[];
24
+ /**
25
+ * Projects the effective A1 declarations and the user's customization into one tab shortcut
26
+ * assignment per action. A key an A1 action holds after customization never becomes a tab
27
+ * shortcut; between tab actions the earlier declaration keeps a duplicated key.
28
+ */
29
+ export declare function projectResidentTabShortcuts(input?: ResidentTabShortcutInput): ResidentTabShortcutProjection;
@@ -0,0 +1,64 @@
1
+ import { RESIDENT_TAB_SHORTCUTS } from "./shortcut-declarations.js";
2
+ /** The declarations the projection covers, in the order that decides duplicate claims. */
3
+ export const RESIDENT_TAB_GLOBAL_SHORTCUTS = RESIDENT_TAB_SHORTCUTS.filter(shortcut => shortcut.scope === "global");
4
+ function normalizeKey(key) {
5
+ return key.trim().toLowerCase();
6
+ }
7
+ function keysOf(value) {
8
+ if (value === null || value === undefined)
9
+ return value;
10
+ if (typeof value === "string")
11
+ return [value];
12
+ return value.filter((key) => typeof key === "string");
13
+ }
14
+ /**
15
+ * Projects the effective A1 declarations and the user's customization into one tab shortcut
16
+ * assignment per action. A key an A1 action holds after customization never becomes a tab
17
+ * shortcut; between tab actions the earlier declaration keeps a duplicated key.
18
+ */
19
+ export function projectResidentTabShortcuts(input = {}) {
20
+ const configured = input.configured ?? {};
21
+ const claimedByOwnedActions = new Map();
22
+ for (const [action, value] of Object.entries(input.reserved ?? {})) {
23
+ if (action.startsWith("tabs."))
24
+ continue;
25
+ claimedByOwnedActions.set(action, keysOf(value) ?? []);
26
+ }
27
+ for (const [action, value] of Object.entries(configured)) {
28
+ if (action.startsWith("tabs.") || action === "$schema")
29
+ continue;
30
+ claimedByOwnedActions.set(action, keysOf(value) ?? []);
31
+ }
32
+ const reserved = new Set();
33
+ for (const keys of claimedByOwnedActions.values())
34
+ for (const key of keys)
35
+ reserved.add(normalizeKey(key));
36
+ const claimed = new Set();
37
+ const conflicts = [];
38
+ const assignments = {};
39
+ for (const shortcut of RESIDENT_TAB_GLOBAL_SHORTCUTS) {
40
+ const id = shortcut.id;
41
+ const custom = configured[id];
42
+ const candidates = custom === undefined
43
+ ? (shortcut.defaultKey === null ? [] : [shortcut.defaultKey])
44
+ : (keysOf(custom) ?? []);
45
+ let assigned = null;
46
+ for (const candidate of candidates.map(normalizeKey)) {
47
+ if (candidate.length === 0)
48
+ continue;
49
+ if (reserved.has(candidate)) {
50
+ conflicts.push({ id, key: candidate, reason: "reserved" });
51
+ continue;
52
+ }
53
+ if (claimed.has(candidate)) {
54
+ conflicts.push({ id, key: candidate, reason: "duplicate" });
55
+ continue;
56
+ }
57
+ assigned = candidate;
58
+ claimed.add(candidate);
59
+ break;
60
+ }
61
+ assignments[id] = assigned;
62
+ }
63
+ return { assignments, conflicts };
64
+ }
@@ -66,6 +66,7 @@ async function runBootstrapAttempt(options, retriesRemaining) {
66
66
  "attach", "--endpoint", resident.endpoint, "--cwd", process.cwd(), "--clear-exit-ms", String(CLEAR_EXIT_INTERVAL_MS),
67
67
  "--tabs-max", String((await residentLaunchSettings).tabsMax),
68
68
  "--profile", environment[PRODUCT_IDENTITY.environment.profileHome] ?? paths.configDir,
69
+ "--settings-file", resolve(agentProfileDir, "settings.json"),
69
70
  "--data-dir", paths.dataDir, "--runtime-dir", paths.runtimeDir,
70
71
  "--release-root", release.releaseRoot, "--node-executable", process.execPath,
71
72
  ]),
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Generated by scripts/pi/sync-progress-palette.ts from @earendil-works/pi-coding-agent 1.2.0
3
- * (MIT), commit 06a466935536f8c9bcacb2d5efc0fc021be1bdff. Do not edit directly.
2
+ * Generated by scripts/pi/sync-progress-palette.ts from @earendil-works/pi-coding-agent 1.3.0
3
+ * (MIT), commit 71023aec1546d6d677a65669c5665c0927ce0dd0. Do not edit directly.
4
4
  */
5
5
  export declare const SHARED_PROGRESS_ACCENT_ANSI = "\u001B[38;2;167;152;215m";
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Generated by scripts/pi/sync-progress-palette.ts from @earendil-works/pi-coding-agent 1.2.0
3
- * (MIT), commit 06a466935536f8c9bcacb2d5efc0fc021be1bdff. Do not edit directly.
2
+ * Generated by scripts/pi/sync-progress-palette.ts from @earendil-works/pi-coding-agent 1.3.0
3
+ * (MIT), commit 71023aec1546d6d677a65669c5665c0927ce0dd0. Do not edit directly.
4
4
  */
5
5
  export const SHARED_PROGRESS_ACCENT_ANSI = "\u001b[38;2;167;152;215m";
@@ -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");
@@ -10,7 +10,7 @@ export const STARTUP_DESCRIPTOR = Object.freeze({
10
10
  ],
11
11
  "generatedArtifact": {
12
12
  "path": "dist/integrations/pi/startup-public.js",
13
- "sha256": "2e5c23263868c689b0b76648a7565fe4384f8144f4c11b64569a08fc4d3502c2"
13
+ "sha256": "bca69314139a5503ccfc0678ffc86f3b7160f57a6ca55c86239b6587d3f627a3"
14
14
  },
15
15
  "dependencyLayerIdentity": {
16
16
  "source": "A1_RELEASE_LAYERS",
@@ -19,7 +19,7 @@ export const STARTUP_DESCRIPTOR = Object.freeze({
19
19
  "compileCacheNamespace": {
20
20
  "strategy": "node-abi-version-and-ordered-layer-sha256-v1"
21
21
  },
22
- "identity": "5d1fea810b3c76b1560dd3a743dd4db0b8d03935d9f5079fd4b2da55d4f1084a"
22
+ "identity": "163053e701440c93391663404f0d4ae96c74f66773fa0ca99f98c39b68a5d37b"
23
23
  });
24
24
 
25
25
  export function loadDeclaredStartupGraph() {
@@ -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;
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.2.0 (MIT),
3
- * commit 06a466935536f8c9bcacb2d5efc0fc021be1bdff.
2
+ * Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.3.0 (MIT),
3
+ * commit 71023aec1546d6d677a65669c5665c0927ce0dd0.
4
4
  * Upstream dark.json SHA-256: e1f96982f8cb7d2a48eca7db03c9cb282cb1e14a243680cd855638ecd6a251b6
5
5
  * Upstream light.json SHA-256: 2dee6a4be7f765e7fd7728166b7ebf8c29e4ce313f8ec6b38ae50699e3abc2f3
6
6
  * Modifications: removed upstream schema/export metadata; runtime color data is unchanged.
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.2.0 (MIT),
3
- * commit 06a466935536f8c9bcacb2d5efc0fc021be1bdff.
2
+ * Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.3.0 (MIT),
3
+ * commit 71023aec1546d6d677a65669c5665c0927ce0dd0.
4
4
  * Upstream dark.json SHA-256: e1f96982f8cb7d2a48eca7db03c9cb282cb1e14a243680cd855638ecd6a251b6
5
5
  * Upstream light.json SHA-256: 2dee6a4be7f765e7fd7728166b7ebf8c29e4ce313f8ec6b38ae50699e3abc2f3
6
6
  * Modifications: removed upstream schema/export metadata; runtime color data is unchanged.
@@ -1,6 +1,8 @@
1
1
  import { type PiShellComponentPort, type PiShellEditorOptions } from "./shell-shared-facade.js";
2
2
  export interface PiShellOperationLoaderPort extends PiShellComponentPort {
3
3
  readonly signal: AbortSignal;
4
+ /** Relabels the running operation; the pinned comparison loader keeps its first label. */
5
+ readonly setMessage?: (message: string) => void;
4
6
  }
5
7
  export declare function createPiShellShareOperationDialog(runtime: Pick<PiShellEditorOptions, "getColumns" | "getRows" | "requestRender">, message: string): PiShellOperationLoaderPort;
6
8
  export declare function createPiShellOperationLoader(runtime: Pick<PiShellEditorOptions, "getColumns" | "getRows" | "requestRender">, message: string): PiShellOperationLoaderPort;
@@ -18,6 +18,7 @@ class ShareOperationDialog {
18
18
  ], new DynamicBorder(paintPiBorder));
19
19
  }
20
20
  get signal() { return this.#loader.signal; }
21
+ setMessage(message) { this.#loader.setMessage(message); }
21
22
  invalidate() { this.#frame.invalidate(); }
22
23
  render(width) { return this.#frame.render(width); }
23
24
  handleInput(data) { this.#loader.handleInput(data); }
@@ -26,7 +27,7 @@ class ShareOperationDialog {
26
27
  export function createPiShellShareOperationDialog(runtime, message) {
27
28
  ensureTheme();
28
29
  const dialog = new ShareOperationDialog(runtime, message);
29
- return { ...componentPort(dialog), signal: dialog.signal };
30
+ return { ...componentPort(dialog), signal: dialog.signal, setMessage: message => dialog.setMessage(message) };
30
31
  }
31
32
  export function createPiShellOperationLoader(runtime, message) {
32
33
  ensureTheme();
@@ -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
  /**