@timurproko/a1 0.2.7-dev.809 → 0.2.7-dev.820

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 (99) hide show
  1. package/README.md +4 -2
  2. package/dist/app/session-shell/resident-tab-coordinator.d.ts +6 -9
  3. package/dist/app/session-shell/resident-tab-coordinator.js +9 -52
  4. package/dist/app/session-shell/response-copy-transport.d.ts +13 -0
  5. package/dist/app/session-shell/response-copy-transport.js +16 -7
  6. package/dist/app/session-shell/session-shell-root.d.ts +1 -2
  7. package/dist/app/session-shell/session-shell.js +2 -2
  8. package/dist/app/session-shell/session-viewport-controller.js +6 -4
  9. package/dist/composition/owned-ui.js +1 -2
  10. package/dist/features/owned-ui/settings-app.js +1 -1
  11. package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
  12. package/dist/foundation/release/progress-palette.generated.js +2 -2
  13. package/dist/foundation/resident-tabs/bridge-client.d.ts +1 -1
  14. package/dist/foundation/resident-tabs/bridge-client.js +1 -1
  15. package/dist/foundation/resident-tabs/settings.d.ts +0 -1
  16. package/dist/foundation/resident-tabs/settings.js +0 -2
  17. package/dist/foundation/startup/startup-descriptor.js +2 -2
  18. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
  19. package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
  20. package/dist/integrations/pi/components/shell-extension-ui.js +79 -60
  21. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  22. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
  23. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  24. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  25. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  26. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  27. package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
  28. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  29. package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
  30. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  31. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
  32. package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
  33. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  34. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  35. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  36. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  37. package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
  38. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  39. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  40. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
  41. package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
  42. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  43. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  44. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  45. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
  46. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +2 -4
  47. package/dist/integrations/pi/components/upstream/components/tool-execution.js +77 -98
  48. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
  49. package/dist/integrations/pi/components/upstream/components/tree-selector.js +1 -1
  50. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  51. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  52. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +1 -1
  53. package/dist/integrations/pi/components/upstream/history/editor-core.js +1 -1
  54. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  55. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  56. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  57. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  58. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  59. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  60. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  61. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  62. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
  63. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  64. package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
  65. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  66. package/dist/integrations/pi/startup-public.js +164 -150
  67. package/dist/integrations/pi/startup-public.manifest.json +351 -310
  68. package/dist/integrations/pi/tui-runtime/adapter.js +4 -0
  69. package/dist/integrations/pi/tui-runtime/contracts.d.ts +5 -0
  70. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  71. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
  72. package/dist/native/darwin-arm64/manifest.json +1 -1
  73. package/dist/native/darwin-arm64/terminal-host.manifest.json +3 -3
  74. package/dist/native/darwin-arm64/terminal-host.node +0 -0
  75. package/dist/native/darwin-x64/manifest.json +1 -1
  76. package/dist/native/darwin-x64/terminal-host.manifest.json +3 -3
  77. package/dist/native/darwin-x64/terminal-host.node +0 -0
  78. package/dist/native/linux-x64/manifest.json +1 -1
  79. package/dist/native/linux-x64/terminal-host.manifest.json +3 -3
  80. package/dist/native/linux-x64/terminal-host.node +0 -0
  81. package/dist/native/win32-x64/manifest.json +2 -2
  82. package/dist/native/win32-x64/process-guardian.node +0 -0
  83. package/dist/native/win32-x64/terminal-host.manifest.json +3 -3
  84. package/dist/native/win32-x64/terminal-host.node +0 -0
  85. package/dist/runtime-payload-inventory.json +5181 -5369
  86. package/dist/ui/components/dialog-panel.js +1 -1
  87. package/dist/ui/components/prompt-input.d.ts +2 -2
  88. package/dist/ui/components/prompt-input.js +2 -2
  89. package/dist/ui/components/submitted-prompt.d.ts +2 -2
  90. package/dist/ui/components/submitted-prompt.js +3 -3
  91. package/dist/ui/components/transcript-viewport.d.ts +1 -1
  92. package/dist/ui/components/transcript-viewport.js +151 -43
  93. package/dist/ui/settings/declarations.d.ts +13 -9
  94. package/dist/ui/settings/declarations.js +10 -7
  95. package/dist/ui/settings/migrations.js +7 -0
  96. package/docs/architecture/resident-tabs.md +6 -6
  97. package/docs/architecture/response-copy-delivery.md +1 -1
  98. package/docs/architecture/toolchain.md +2 -2
  99. package/package.json +5 -5
package/README.md CHANGED
@@ -185,13 +185,15 @@ a1 update npm:pi-mcp-adapter
185
185
 
186
186
  ## Develop
187
187
 
188
+ A source build needs Node.js, npm, git, and Rustup. Windows additionally needs Visual Studio or Visual Studio Build Tools with the **Desktop development with C++** workload, MSVC x64/x86 tools, and a Windows SDK; Visual Studio Code is not required. A1 discovers installed Rustup and Visual Studio tools and initializes them for build children, so Git Bash and ordinary PowerShell do not need manual `PATH` or developer-shell setup. It never installs these tools or accepts their licenses automatically.
189
+
188
190
  Install exact locked dependencies:
189
191
 
190
192
  ```text
191
193
  npm ci
192
194
  ```
193
195
 
194
- Compile TypeScript and the process guardian into `dist`:
196
+ Compile TypeScript and the native addons into `dist`:
195
197
 
196
198
  ```text
197
199
  npm run build
@@ -221,7 +223,7 @@ Complete non-physical suite:
221
223
  npm run test:full
222
224
  ```
223
225
 
224
- Report Node, npm, git, Rust, and dependency readiness:
226
+ Report Node, npm, git, Rust, dependency, and Windows C++ readiness. Missing Windows tools are listed in setup order; after installing them, rerun the same build command:
225
227
 
226
228
  ```text
227
229
  npm run doctor
@@ -1,18 +1,15 @@
1
1
  import type { OwnedUiEvent, PromptHistoryImageSidecarPort } from "../../contracts/owned-ui/index.js";
2
2
  import type { SessionConcern } from "./session-concern.js";
3
3
  import type { OwnedUiShellEngineOptions, OwnedUiSessionShellRoot } from "./session-shell-root.js";
4
- import type { OwnedUiPresenterTerminal } from "./shell-host.js";
5
4
  export type ResidentTabOptions = NonNullable<OwnedUiShellEngineOptions["residentTab"]>;
6
5
  export interface ResidentTabCoordinatorPorts {
7
6
  readonly root: Pick<OwnedUiSessionShellRoot, "appendWorkflowStatus" | "rehydrateHistoryText" | "editor">;
8
- readonly terminal: Pick<OwnedUiPresenterTerminal, "requestRender">;
9
- readonly disposed: () => boolean;
10
7
  }
11
8
  /**
12
- * The session presenter's side of a resident tab: recovered input, the progress and stall status
13
- * it reports to the strip, prompt admission and correlation through the recovery journal, draft
14
- * checkpoints, detach on quit, and the graceful stop when the presenter is released. Outside a
15
- * resident tab every operation is a no-op.
9
+ * The session presenter's side of a resident tab: recovered input, the idle status it reports to
10
+ * the strip, prompt admission and correlation through the recovery journal, draft checkpoints,
11
+ * detach on quit, and the graceful stop when the presenter is released. Outside a resident tab
12
+ * every operation is a no-op.
16
13
  */
17
14
  export declare class ResidentTabCoordinator implements SessionConcern {
18
15
  #private;
@@ -23,8 +20,8 @@ export declare class ResidentTabCoordinator implements SessionConcern {
23
20
  closeOwnedRoute(route: string): void;
24
21
  /** Puts the prompts and draft a previous tab process left unfinished back into the editor. */
25
22
  restoreInput(imageSidecar?: PromptHistoryImageSidecarPort): void;
26
- /** Tracks working, idle, and stalled status from session events and arms the stall notice. */
27
- observeProgress(event: OwnedUiEvent): void;
23
+ /** Reports idle to the strip whenever the session leaves its busy lifecycle. */
24
+ observeLifecycle(event: OwnedUiEvent): void;
28
25
  /** Journals a prompt before it is sent; undefined outside a resident tab. Rejects when the journal cannot sync. */
29
26
  admit(input: Parameters<NonNullable<ResidentTabOptions["admit"]>>[0]): Promise<{
30
27
  readonly id: string;
@@ -1,18 +1,12 @@
1
- const PROGRESS_EVENTS = new Set([
2
- "transcript-block", "session-view", "assistant-message-completed", "agent-run-started",
3
- ]);
4
1
  /**
5
- * The session presenter's side of a resident tab: recovered input, the progress and stall status
6
- * it reports to the strip, prompt admission and correlation through the recovery journal, draft
7
- * checkpoints, detach on quit, and the graceful stop when the presenter is released. Outside a
8
- * resident tab every operation is a no-op.
2
+ * The session presenter's side of a resident tab: recovered input, the idle status it reports to
3
+ * the strip, prompt admission and correlation through the recovery journal, draft checkpoints,
4
+ * detach on quit, and the graceful stop when the presenter is released. Outside a resident tab
5
+ * every operation is a no-op.
9
6
  */
10
7
  export class ResidentTabCoordinator {
11
8
  #options;
12
9
  #ports;
13
- #progressTimer;
14
- #working = false;
15
- #stalled = false;
16
10
  constructor(options, ports) {
17
11
  this.#options = options;
18
12
  this.#ports = ports;
@@ -51,40 +45,10 @@ export class ResidentTabCoordinator {
51
45
  root.appendWorkflowStatus("Recovered the editor draft from the previous tab process.");
52
46
  }
53
47
  }
54
- /** Tracks working, idle, and stalled status from session events and arms the stall notice. */
55
- observeProgress(event) {
56
- const resident = this.#options;
57
- const seconds = resident?.stallNoticeSeconds;
58
- if (resident === undefined || seconds === undefined)
59
- return;
60
- if (event.type === "session-lifecycle") {
61
- this.#working = event.lifecycle === "busy";
62
- if (!this.#working) {
63
- this.#clearTimer();
64
- this.#stalled = false;
65
- resident.reportStatus?.("idle");
66
- return;
67
- }
68
- }
69
- else if (!this.#working || !PROGRESS_EVENTS.has(event.type)) {
70
- return;
71
- }
72
- if (this.#stalled) {
73
- this.#stalled = false;
74
- resident.reportStatus?.("working");
75
- }
76
- this.#clearTimer();
77
- this.#progressTimer = setTimeout(() => {
78
- this.#progressTimer = undefined;
79
- if (this.#ports.disposed() || !this.#working)
80
- return;
81
- this.#stalled = true;
82
- resident.reportStatus?.("stalled");
83
- const minutes = Math.max(1, Math.round(seconds / 60));
84
- this.#ports.root.appendWorkflowStatus(`No progress for ${minutes} min — Esc interrupts · use the tab restart action to restart`);
85
- this.#ports.terminal.requestRender();
86
- }, seconds * 1_000);
87
- this.#progressTimer.unref?.();
48
+ /** Reports idle to the strip whenever the session leaves its busy lifecycle. */
49
+ observeLifecycle(event) {
50
+ if (event.type === "session-lifecycle" && event.lifecycle !== "busy")
51
+ this.#options?.reportStatus?.("idle");
88
52
  }
89
53
  /** Journals a prompt before it is sent; undefined outside a resident tab. Rejects when the journal cannot sync. */
90
54
  admit(input) {
@@ -109,12 +73,5 @@ export class ResidentTabCoordinator {
109
73
  gracefulStop(sessionFile) {
110
74
  return this.#options?.gracefulStop?.(sessionFile) ?? Promise.resolve();
111
75
  }
112
- dispose() {
113
- this.#clearTimer();
114
- }
115
- #clearTimer() {
116
- if (this.#progressTimer !== undefined)
117
- clearTimeout(this.#progressTimer);
118
- this.#progressTimer = undefined;
119
- }
76
+ dispose() { }
120
77
  }
@@ -22,6 +22,19 @@ export interface ResponseCopyTerminal {
22
22
  }
23
23
  /** Never substitute a remote host's native clipboard for the terminal user's clipboard. */
24
24
  export declare function responseCopyDestination(env: NodeJS.ProcessEnv): "native" | "terminal";
25
+ /**
26
+ * Spawn options for one operating-system clipboard writer.
27
+ * Platform: on POSIX the writer is detached into its own process group, as pinned Pi 1.4 does, so a writer
28
+ * that daemonizes to keep serving the clipboard is not stopped when Ctrl+Z sends SIGTSTP to the shell's group.
29
+ */
30
+ export declare function platformClipboardWriteOptions(signal: AbortSignal, platform?: NodeJS.Platform): {
31
+ signal: AbortSignal;
32
+ windowsHide: boolean;
33
+ timeout: number;
34
+ killSignal: "SIGKILL";
35
+ maxBuffer: number;
36
+ detached: boolean;
37
+ };
25
38
  /** Isolates preparation and native clipboard access; only the owner may submit terminal controls. */
26
39
  export declare function createResponseCopyExecutor(options?: {
27
40
  readonly terminal?: ResponseCopyTerminal;
@@ -21,6 +21,21 @@ function platformClipboardCommands() {
21
21
  { command: "xclip", args: ["-selection", "clipboard", "-in"] },
22
22
  ];
23
23
  }
24
+ /**
25
+ * Spawn options for one operating-system clipboard writer.
26
+ * Platform: on POSIX the writer is detached into its own process group, as pinned Pi 1.4 does, so a writer
27
+ * that daemonizes to keep serving the clipboard is not stopped when Ctrl+Z sends SIGTSTP to the shell's group.
28
+ */
29
+ export function platformClipboardWriteOptions(signal, platform = process.platform) {
30
+ return {
31
+ signal,
32
+ windowsHide: true,
33
+ timeout: PLATFORM_WRITE_TIMEOUT_MS,
34
+ killSignal: "SIGKILL",
35
+ maxBuffer: 1_024,
36
+ detached: platform !== "win32",
37
+ };
38
+ }
24
39
  async function writePlatformClipboardText(text, signal) {
25
40
  for (const route of platformClipboardCommands()) {
26
41
  if (signal.aborted)
@@ -33,13 +48,7 @@ async function writePlatformClipboardText(text, signal) {
33
48
  settled = true;
34
49
  resolve(value);
35
50
  };
36
- const child = execFile(route.command, [...route.args], {
37
- signal,
38
- windowsHide: true,
39
- timeout: PLATFORM_WRITE_TIMEOUT_MS,
40
- killSignal: "SIGKILL",
41
- maxBuffer: 1_024,
42
- }, error => done(error === null));
51
+ const child = execFile(route.command, [...route.args], platformClipboardWriteOptions(signal), error => done(error === null));
43
52
  child.once("error", () => done(false));
44
53
  if (child.stdin === null) {
45
54
  child.kill("SIGKILL");
@@ -47,8 +47,7 @@ export interface OwnedUiShellEngineOptions {
47
47
  readonly residentTab?: {
48
48
  requestDetach(): Promise<boolean>;
49
49
  closeOwnedRoute?(route: string): void;
50
- reportStatus?(status: "working" | "idle" | "stalled"): void;
51
- readonly stallNoticeSeconds?: number;
50
+ reportStatus?(status: "working" | "idle"): void;
52
51
  admit?(input: {
53
52
  readonly sessionId: string;
54
53
  readonly sessionFile: string | null;
@@ -251,7 +251,7 @@ export class OwnedUiSessionPresenter {
251
251
  // Invariant: the presenter owns its root (theme subscription and helper clients) and disposes it once the
252
252
  // terminal no longer renders it.
253
253
  constructed.push(() => this.root.dispose());
254
- this.#resident = new ResidentTabCoordinator(options.engine.residentTab, { root: this.root, terminal: this.#terminal, disposed: () => this.#disposed });
254
+ this.#resident = new ResidentTabCoordinator(options.engine.residentTab, { root: this.root });
255
255
  constructed.push(() => this.#resident.dispose());
256
256
  const startupRoute = options.engine.startupRoute;
257
257
  this.#dialogs = new SessionDialogCoordinator({
@@ -366,7 +366,7 @@ export class OwnedUiSessionPresenter {
366
366
  this.#stop.settleAfter(() => this.dispose());
367
367
  return;
368
368
  }
369
- this.#resident.observeProgress(event);
369
+ this.#resident.observeLifecycle(event);
370
370
  // Performance: a streamed chunk names one block, and touching only that block is what keeps the
371
371
  // cost of a chunk the same in a long session as in a new one. Everything else
372
372
  // resynchronizes the view, which is cheap next to re-reading the transcript.
@@ -322,8 +322,8 @@ export class SessionViewportController {
322
322
  this.#requestRender();
323
323
  }
324
324
  }
325
- const previousPrompt = SHIFT_UP_INPUTS.has(data) || this.#editor.matchesTerminalKey(data, "alt+home");
326
- if (editorActive && allowWheel && (previousPrompt || SHIFT_DOWN_INPUTS.has(data))) {
325
+ const previousPrompt = PROMPT_UP_INPUTS.has(data) || this.#editor.matchesTerminalKey(data, "alt+home");
326
+ if (editorActive && allowWheel && (previousPrompt || PROMPT_DOWN_INPUTS.has(data))) {
327
327
  const scrolled = previousPrompt
328
328
  ? this.#viewport.scrollToPreviousPrompt(now)
329
329
  : this.#viewport.scrollToNextPrompt(now);
@@ -670,5 +670,7 @@ export class SessionViewportController {
670
670
  }
671
671
  const SELECTION_AUTO_SCROLL_INTERVAL_MS = 30;
672
672
  const EDITOR_LINK_DELETION_INPUTS = new Set(["\b", "\u007f", "\u001b[3~"]);
673
- const SHIFT_UP_INPUTS = new Set(["\u001b[1;2A"]);
674
- const SHIFT_DOWN_INPUTS = new Set(["\u001b[1;2B"]);
673
+ // Platform: Windows Terminal may consume Shift+Arrow for native selection. Ctrl+Arrow matches
674
+ // solo A1's Windows binding while retaining Shift+Arrow whenever the terminal delivers it.
675
+ const PROMPT_UP_INPUTS = new Set(["\u001b[1;2A", "\u001b[1;5A"]);
676
+ const PROMPT_DOWN_INPUTS = new Set(["\u001b[1;2B", "\u001b[1;5B"]);
@@ -50,7 +50,7 @@ export async function composeOwnedUi(options = {}) {
50
50
  namespace: PRODUCT_IDENTITY.commandName,
51
51
  legacyConfigDir: productPaths.configDir,
52
52
  agentProvider: () => backend.settingsPort(),
53
- ...(options.hideTabSettings ? { hiddenOwnedSettingIds: ["tabsAutoName"] } : {}),
53
+ ...(options.hideTabSettings ? { hiddenOwnedSettingIds: ["tabsAutoName", "tabsPosition"] } : {}),
54
54
  hiddenAgentSettingIds: ["fullscreenWheelScrollLines"],
55
55
  agentSettingLabelOverrides: { fullscreenCopyOnSelect: "Copy on select" },
56
56
  });
@@ -221,7 +221,6 @@ export async function composeOwnedUi(options = {}) {
221
221
  void tabBridge.requestClose();
222
222
  },
223
223
  reportStatus: status => tabBridge.status(status),
224
- stallNoticeSeconds: 300,
225
224
  admit: input => tabRecovery.admit({ ...input, incarnation: options.tab.incarnation }),
226
225
  dispatched: () => tabRecovery.dispatched(),
227
226
  correlated: (submissionId, entryId) => correlateResidentTabSubmission(tabRecovery, backend, submissionId, entryId),
@@ -1026,7 +1026,7 @@ export class SettingsApp {
1026
1026
  const input = this.#filter;
1027
1027
  if (input === null)
1028
1028
  return [status];
1029
- return [...renderInputRow(input, width, { placeholder: SEARCH_PLACEHOLDER, theme }).lines, status];
1029
+ return [...renderInputRow(input, width, { placeholder: SEARCH_PLACEHOLDER, promptGlyph: "", theme }).lines, status];
1030
1030
  }
1031
1031
  }
1032
1032
  function modelLabelParts(label) {
@@ -1,5 +1,5 @@
1
1
  /**
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.
2
+ * Generated by scripts/pi/sync-progress-palette.ts from @earendil-works/pi-coding-agent 1.4.0
3
+ * (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0. 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.3.0
3
- * (MIT), commit 71023aec1546d6d677a65669c5665c0927ce0dd0. Do not edit directly.
2
+ * Generated by scripts/pi/sync-progress-palette.ts from @earendil-works/pi-coding-agent 1.4.0
3
+ * (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0. Do not edit directly.
4
4
  */
5
5
  export const SHARED_PROGRESS_ACCENT_ANSI = "\u001b[38;2;167;152;215m";
@@ -1,4 +1,4 @@
1
- export type ResidentTabStatus = "starting" | "working" | "needs-input" | "done-unseen" | "done" | "aborted" | "error" | "idle" | "unresponsive" | "stalled" | "crashed" | "restarting" | "failed";
1
+ export type ResidentTabStatus = "starting" | "working" | "needs-input" | "done-unseen" | "done" | "aborted" | "error" | "idle" | "unresponsive" | "crashed" | "restarting" | "failed";
2
2
  export interface TabBridgeCredentials {
3
3
  readonly tabId: string;
4
4
  readonly token: string;
@@ -80,7 +80,7 @@ export class TabBridgeClient {
80
80
  }
81
81
  status(state, degraded = false, pendingRequests = 0, queuedInput = 0) {
82
82
  this.#latestStatus = { state, degraded, accent: this.#accent, pendingRequests, queuedInput };
83
- const recoveryState = state === "unresponsive" || state === "stalled" || state === "crashed" || state === "restarting" || state === "failed";
83
+ const recoveryState = state === "unresponsive" || state === "crashed" || state === "restarting" || state === "failed";
84
84
  if (recoveryState && !this.#supports("recovery-status"))
85
85
  return;
86
86
  this.#send("bridge.status", {
@@ -7,7 +7,6 @@ export interface ResidentTabLaunchSettings {
7
7
  readonly maxConcurrentStarts: number;
8
8
  readonly prewarmCount: number;
9
9
  readonly unresponsiveRestartSeconds: number;
10
- readonly stallNoticeSeconds: number;
11
10
  }
12
11
  /** Read only resident-launch values before any UI or extension module is loaded. */
13
12
  export declare function readResidentTabLaunchSettings(profileDir: string, namespace?: string, legacyConfigDir?: string, profileId?: string): Promise<ResidentTabLaunchSettings>;
@@ -11,7 +11,6 @@ const DEFAULTS = Object.freeze({
11
11
  maxConcurrentStarts: RESIDENT_TABS_MAX_CONCURRENT_STARTS,
12
12
  prewarmCount: RESIDENT_TABS_PREWARM_COUNT,
13
13
  unresponsiveRestartSeconds: 120,
14
- stallNoticeSeconds: 300,
15
14
  });
16
15
  /** Read only resident-launch values before any UI or extension module is loaded. */
17
16
  export async function readResidentTabLaunchSettings(profileDir, namespace = "a1", legacyConfigDir, profileId = namespace) {
@@ -55,6 +54,5 @@ function resolveLaunchValues(document, migrations) {
55
54
  maxConcurrentStarts: RESIDENT_TABS_MAX_CONCURRENT_STARTS,
56
55
  prewarmCount: RESIDENT_TABS_PREWARM_COUNT,
57
56
  unresponsiveRestartSeconds: DEFAULTS.unresponsiveRestartSeconds,
58
- stallNoticeSeconds: DEFAULTS.stallNoticeSeconds,
59
57
  };
60
58
  }
@@ -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": "bca69314139a5503ccfc0678ffc86f3b7160f57a6ca55c86239b6587d3f627a3"
13
+ "sha256": "e065933fe374d7953c5aac0ff1735fa47d119ab97551e955c2a65e8c2df667eb"
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": "163053e701440c93391663404f0d4ae96c74f66773fa0ca99f98c39b68a5d37b"
22
+ "identity": "5c1afab4657c251b840e042279290bd1fa03ce608bc81bc6e7eaf8d332486eef"
23
23
  });
24
24
 
25
25
  export function loadDeclaredStartupGraph() {
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.3.0 (MIT),
3
- * commit 71023aec1546d6d677a65669c5665c0927ce0dd0.
2
+ * Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.4.0 (MIT),
3
+ * commit 4a080252f06caf63a525d7873c5d94d3c23887e0.
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.3.0 (MIT),
3
- * commit 71023aec1546d6d677a65669c5665c0927ce0dd0.
2
+ * Attributed owned theme resources adapted from @earendil-works/pi-coding-agent 1.4.0 (MIT),
3
+ * commit 4a080252f06caf63a525d7873c5d94d3c23887e0.
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.
@@ -15,22 +15,8 @@ export function createPiExtensionUiBridge(host) {
15
15
  const keybindings = KeybindingsManager.create(host.agentDir);
16
16
  const disposers = new Set();
17
17
  let customEditorFactory;
18
- let activeSurface;
19
- let activeCancel;
20
- const closeSurface = (surface) => {
21
- if (surface !== undefined && activeSurface !== surface)
22
- return;
23
- activeSurface = undefined;
24
- host.setInputSurface(null);
25
- host.runtime.requestRender();
26
- };
27
- const mountSurface = (surface) => {
28
- if (activeSurface !== undefined && activeSurface !== surface)
29
- activeSurface.dispose?.();
30
- activeSurface = surface;
31
- host.setInputSurface(surface);
32
- host.runtime.requestRender();
33
- };
18
+ const dialogs = createExtensionDialogStack(host);
19
+ const overlayCancels = new Set();
34
20
  const trackAbort = (signal, cancel) => {
35
21
  if (signal === undefined)
36
22
  return () => { };
@@ -54,26 +40,24 @@ export function createPiExtensionUiBridge(host) {
54
40
  if (settled)
55
41
  return;
56
42
  settled = true;
57
- if (activeCancel === cancel)
58
- activeCancel = undefined;
59
43
  untrack();
60
- const ownedSurface = activeSurface === surface;
61
- if (retainSurfaceOnSettle && ownedSurface)
62
- activeSurface = undefined;
63
- else
64
- closeSurface(surface);
65
- if (ownedSurface)
66
- host.setProgramStatusBlocked(undefined);
44
+ if (surface !== undefined) {
45
+ const retained = retainSurfaceOnSettle && dialogs.isOnly(surface);
46
+ // Rationale: like pinned Pi, a settled dialog is disposed so its countdown stops, unless it stays painted.
47
+ if (!retained)
48
+ surface.dispose?.();
49
+ dialogs.remove(surface, retained);
50
+ }
67
51
  resolve(value);
68
52
  };
69
53
  const cancel = () => finish(undefined);
70
- surface = create(finish, cancel);
54
+ const created = create(finish, cancel);
55
+ surface = created;
71
56
  untrack = trackAbort(options?.signal, cancel);
72
- if (!settled) {
73
- activeCancel = cancel;
74
- mountSurface(surface);
75
- host.setProgramStatusBlocked(blocked);
76
- }
57
+ if (!settled)
58
+ dialogs.push({ surface: created, blocked, cancel });
59
+ else
60
+ created.dispose?.();
77
61
  });
78
62
  const createFactoryComponent = (factory, ...arguments_) => {
79
63
  if (typeof factory !== "function")
@@ -148,28 +132,26 @@ export function createPiExtensionUiBridge(host) {
148
132
  let settled = false;
149
133
  let surface;
150
134
  let overlay;
151
- const done = (value) => {
152
- if (settled)
153
- return;
154
- settled = true;
155
- if (activeCancel === cancelCustom)
156
- activeCancel = undefined;
157
- overlay?.hide();
158
- if (surface !== undefined)
159
- closeSurface(surface);
160
- resolve(value);
161
- };
162
- const cancelCustom = () => {
135
+ const close = (settle) => {
163
136
  if (settled)
164
137
  return;
165
138
  settled = true;
166
- if (activeCancel === cancelCustom)
167
- activeCancel = undefined;
168
- overlay?.hide();
169
- if (surface !== undefined)
170
- closeSurface(surface);
171
- Reflect.apply(resolve, undefined, []);
139
+ overlayCancels.delete(cancelCustom);
140
+ // Invariant: remove this dialog or overlay, not the topmost one; another may have opened above it.
141
+ if (overlay !== undefined)
142
+ overlay.hide();
143
+ else if (surface !== undefined)
144
+ dialogs.remove(surface);
145
+ settle();
146
+ if (overlay === undefined) {
147
+ try {
148
+ surface?.dispose?.();
149
+ }
150
+ catch { /* Rationale: a settled dialog's dispose failure must not leak. */ }
151
+ }
172
152
  };
153
+ const done = (value) => close(() => resolve(value));
154
+ const cancelCustom = () => close(() => Reflect.apply(resolve, undefined, []));
173
155
  let created;
174
156
  try {
175
157
  created = Reflect.apply(factory, undefined, [tui, piTheme(), keybindings, done]);
@@ -187,19 +169,18 @@ export function createPiExtensionUiBridge(host) {
187
169
  return;
188
170
  }
189
171
  surface = withPiDialogCancel(componentPort(component), cancelCustom);
190
- activeCancel = cancelCustom;
191
172
  if (options?.overlay) {
192
173
  const overlayOptions = typeof options.overlayOptions === "function" ? options.overlayOptions() : options.overlayOptions;
174
+ overlayCancels.add(cancelCustom);
193
175
  overlay = host.showOverlay(surface, overlayOptions);
194
176
  options.onHandle?.(publicOverlayHandle(overlay));
195
177
  }
196
178
  else
197
- mountSurface(surface);
179
+ dialogs.push({ surface, blocked: undefined, cancel: cancelCustom });
198
180
  }).catch(error => {
199
- if (activeCancel === cancelCustom)
200
- activeCancel = undefined;
201
- if (surface !== undefined)
202
- closeSurface(surface);
181
+ overlayCancels.delete(cancelCustom);
182
+ if (surface !== undefined && overlay === undefined)
183
+ dialogs.remove(surface);
203
184
  reject(error);
204
185
  });
205
186
  }),
@@ -251,11 +232,9 @@ export function createPiExtensionUiBridge(host) {
251
232
  setToolsExpanded: expanded => host.setToolsExpanded(expanded),
252
233
  };
253
234
  const reset = () => {
254
- const cancel = activeCancel;
255
- activeCancel = undefined;
256
- cancel?.();
257
- activeSurface?.dispose?.();
258
- activeSurface = undefined;
235
+ dialogs.cancelAll();
236
+ for (const cancel of [...overlayCancels])
237
+ cancel();
259
238
  host.setInputSurface(null);
260
239
  host.setProgramStatusBlocked(undefined);
261
240
  };
@@ -276,6 +255,46 @@ export function createPiExtensionUiBridge(host) {
276
255
  },
277
256
  };
278
257
  }
258
+ /**
259
+ * Pinned Pi's extension dialog stack over the shell's single input slot. The last entry is visible; closing it shows
260
+ * the previous one with its program status, and a covered dialog stays answerable, so no dialog promise is left pending.
261
+ */
262
+ function createExtensionDialogStack(host) {
263
+ const dialogs = [];
264
+ const showTop = () => {
265
+ const top = dialogs.at(-1);
266
+ host.setInputSurface(top?.surface ?? null);
267
+ host.setProgramStatusBlocked(top?.blocked);
268
+ host.runtime.requestRender();
269
+ };
270
+ return {
271
+ push(dialog) {
272
+ dialogs.push(dialog);
273
+ showTop();
274
+ },
275
+ /** Only removing the visible dialog changes the slot; a retained last surface stays painted without its status. */
276
+ remove(surface, retainSurface = false) {
277
+ const index = dialogs.findIndex(dialog => dialog.surface === surface);
278
+ if (index === -1)
279
+ return;
280
+ dialogs.splice(index, 1);
281
+ if (index !== dialogs.length)
282
+ return;
283
+ if (!retainSurface || dialogs.length > 0)
284
+ return showTop();
285
+ host.setProgramStatusBlocked(undefined);
286
+ host.runtime.requestRender();
287
+ },
288
+ isOnly: (surface) => dialogs.length === 1 && dialogs[0].surface === surface,
289
+ /** Rationale: unlike pinned Pi, which drops stacked dialogs unresolved, A1 settles each as cancelled, top first. */
290
+ cancelAll() {
291
+ for (const dialog of [...dialogs].reverse())
292
+ dialog.cancel();
293
+ for (const dialog of dialogs.splice(0))
294
+ dialog.surface.dispose?.();
295
+ },
296
+ };
297
+ }
279
298
  function extensionError(surface, error) {
280
299
  return `Extension ${surface} failed: ${error instanceof Error ? error.message : String(error)}`;
281
300
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.3.0 (MIT), commit 71023aec1546d6d677a65669c5665c0927ce0dd0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
3
3
  * packages/coding-agent/src/core/keybindings.ts.
4
4
  * Modifications: Mechanical source port with Node import prefixes, public package-root agent-directory
5
5
  * resolution, and an opt-in bare-A1 input profile including Ctrl+L level cycling, unbound model
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.3.0 (MIT), commit 71023aec1546d6d677a65669c5665c0927ce0dd0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
3
3
  * packages/coding-agent/src/core/keybindings.ts.
4
4
  * Modifications: Mechanical source port with Node import prefixes, public package-root agent-directory
5
5
  * resolution, and an opt-in bare-A1 input profile including Ctrl+L level cycling, unbound model
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "sourcePackage": "@earendil-works/pi-coding-agent",
3
- "sourceVersion": "1.3.0",
3
+ "sourceVersion": "1.4.0",
4
4
  "upstreamRepository": "https://github.com/earendil-works/pi.git",
5
- "upstreamCommit": "71023aec1546d6d677a65669c5665c0927ce0dd0",
5
+ "upstreamCommit": "4a080252f06caf63a525d7873c5d94d3c23887e0",
6
6
  "sourcePath": "dist/modes/interactive/assets/clankolas.png",
7
7
  "sourceSha256": "169acd0dfe6fbb8d8742ed24a3fc654fd0b2e2d4223c733249c5493723f1b72d",
8
8
  "license": "MIT",
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.3.0 (MIT), commit 71023aec1546d6d677a65669c5665c0927ce0dd0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
3
3
  * packages/coding-agent/src/modes/interactive/components/countdown-timer.ts.
4
4
  * Modifications: Mechanical source port with ECMAScript private fields; imports remain on the public
5
5
  * Pi TUI package root.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.3.0 (MIT), commit 71023aec1546d6d677a65669c5665c0927ce0dd0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
3
3
  * packages/coding-agent/src/modes/interactive/components/earendil-announcement.ts.
4
4
  * Modifications: Mechanical pinned source port with private imports remapped to public package-root
5
5
  * types/APIs and A1-owned theme boundaries. The unchanged image is loaded lazily from its attributed,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Provenance: @earendil-works/pi-coding-agent 1.3.0 (MIT), commit 71023aec1546d6d677a65669c5665c0927ce0dd0,
2
+ * Provenance: @earendil-works/pi-coding-agent 1.4.0 (MIT), commit 4a080252f06caf63a525d7873c5d94d3c23887e0,
3
3
  * packages/coding-agent/src/modes/interactive/components/extension-editor.ts.
4
4
  * Modifications: Mechanical port: remap pi-tui to the root public singleton, use owned
5
5
  * keybindings/theme and external-editor seams, preserve editor layout, hints, focus, submission,