@timurproko/a1 0.2.7-dev.808 → 0.2.7-dev.810

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 (141) hide show
  1. package/README.md +4 -2
  2. package/dist/app/session-shell/dialog-coordinator.d.ts +42 -0
  3. package/dist/app/session-shell/dialog-coordinator.js +133 -0
  4. package/dist/app/session-shell/dock-chrome.d.ts +34 -0
  5. package/dist/app/session-shell/dock-chrome.js +109 -0
  6. package/dist/app/session-shell/exit-notice.d.ts +1 -1
  7. package/dist/app/session-shell/exit-notice.js +1 -1
  8. package/dist/app/session-shell/extension-surface.d.ts +30 -0
  9. package/dist/app/session-shell/extension-surface.js +105 -0
  10. package/dist/app/session-shell/input-surface-switch.d.ts +36 -0
  11. package/dist/app/session-shell/input-surface-switch.js +85 -0
  12. package/dist/app/session-shell/login-interaction.d.ts +27 -0
  13. package/dist/app/session-shell/login-interaction.js +91 -0
  14. package/dist/app/session-shell/prompt-submission.d.ts +48 -0
  15. package/dist/app/session-shell/prompt-submission.js +276 -0
  16. package/dist/app/session-shell/resident-tab-coordinator.d.ts +41 -0
  17. package/dist/app/session-shell/resident-tab-coordinator.js +120 -0
  18. package/dist/app/session-shell/response-copy-transport.d.ts +13 -0
  19. package/dist/app/session-shell/response-copy-transport.js +16 -7
  20. package/dist/app/session-shell/session-concern.d.ts +22 -0
  21. package/dist/app/session-shell/session-concern.js +29 -0
  22. package/dist/app/session-shell/session-lifecycle.d.ts +29 -0
  23. package/dist/app/session-shell/session-lifecycle.js +49 -0
  24. package/dist/app/session-shell/session-shell-root.d.ts +1 -1
  25. package/dist/app/session-shell/session-shell-root.js +182 -931
  26. package/dist/app/session-shell/session-shell.d.ts +2 -8
  27. package/dist/app/session-shell/session-shell.js +202 -901
  28. package/dist/app/session-shell/settings-bindings.d.ts +17 -0
  29. package/dist/app/session-shell/settings-bindings.js +91 -0
  30. package/dist/app/session-shell/shell-editor-factory.d.ts +27 -0
  31. package/dist/app/session-shell/shell-editor-factory.js +102 -0
  32. package/dist/app/session-shell/shell-host.d.ts +6 -0
  33. package/dist/app/session-shell/shell-host.js +8 -0
  34. package/dist/app/session-shell/shell-layout.d.ts +64 -0
  35. package/dist/app/session-shell/shell-layout.js +18 -0
  36. package/dist/app/session-shell/suggestion-surface.d.ts +25 -0
  37. package/dist/app/session-shell/suggestion-surface.js +63 -0
  38. package/dist/app/session-shell/transcript-document.d.ts +78 -0
  39. package/dist/app/session-shell/transcript-document.js +365 -0
  40. package/dist/app/session-shell/viewport-layout.d.ts +31 -0
  41. package/dist/app/session-shell/viewport-layout.js +160 -0
  42. package/dist/app/session-shell/workflow-output.d.ts +33 -0
  43. package/dist/app/session-shell/workflow-output.js +174 -0
  44. package/dist/app/session-shell/workflow-router.d.ts +25 -0
  45. package/dist/app/session-shell/workflow-router.js +39 -0
  46. package/dist/composition/owned-ui.d.ts +4 -25
  47. package/dist/composition/owned-ui.js +26 -270
  48. package/dist/composition/resident-tab-bridge.d.ts +16 -0
  49. package/dist/composition/resident-tab-bridge.js +159 -0
  50. package/dist/composition/session-backend.d.ts +19 -0
  51. package/dist/composition/session-backend.js +1 -0
  52. package/dist/composition/session-runtime-registry.d.ts +20 -0
  53. package/dist/composition/session-runtime-registry.js +85 -0
  54. package/dist/composition/startup-route.d.ts +32 -0
  55. package/dist/composition/startup-route.js +72 -0
  56. package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
  57. package/dist/foundation/release/progress-palette.generated.js +2 -2
  58. package/dist/foundation/startup/startup-descriptor.js +2 -2
  59. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
  60. package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
  61. package/dist/integrations/pi/components/shell-extension-ui.js +79 -60
  62. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  63. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
  64. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  65. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  66. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  67. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  68. package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
  69. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  70. package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
  71. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  72. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
  73. package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
  74. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  75. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  76. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  77. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  78. package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
  79. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  80. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  81. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
  82. package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
  83. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  84. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  85. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  86. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
  87. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +2 -4
  88. package/dist/integrations/pi/components/upstream/components/tool-execution.js +77 -98
  89. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
  90. package/dist/integrations/pi/components/upstream/components/tree-selector.js +1 -1
  91. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  92. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  93. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +1 -1
  94. package/dist/integrations/pi/components/upstream/history/editor-core.js +1 -1
  95. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  96. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  97. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  98. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  99. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  100. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  101. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  102. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  103. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
  104. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  105. package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
  106. package/dist/integrations/pi/engine/adapter.d.ts +4 -77
  107. package/dist/integrations/pi/engine/adapter.js +85 -393
  108. package/dist/integrations/pi/engine/command-dispatch.d.ts +13 -0
  109. package/dist/integrations/pi/engine/command-dispatch.js +57 -0
  110. package/dist/integrations/pi/engine/host.js +2 -2
  111. package/dist/integrations/pi/engine/ports.d.ts +56 -0
  112. package/dist/integrations/pi/engine/ports.js +89 -0
  113. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  114. package/dist/integrations/pi/engine/view-state.d.ts +42 -0
  115. package/dist/integrations/pi/engine/view-state.js +126 -0
  116. package/dist/integrations/pi/startup-public.js +164 -150
  117. package/dist/integrations/pi/startup-public.manifest.json +351 -310
  118. package/dist/integrations/pi/tui-runtime/adapter.js +4 -0
  119. package/dist/integrations/pi/tui-runtime/contracts.d.ts +5 -0
  120. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  121. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
  122. package/dist/native/darwin-arm64/manifest.json +1 -1
  123. package/dist/native/darwin-arm64/terminal-host.manifest.json +3 -3
  124. package/dist/native/darwin-arm64/terminal-host.node +0 -0
  125. package/dist/native/darwin-x64/manifest.json +1 -1
  126. package/dist/native/darwin-x64/terminal-host.manifest.json +3 -3
  127. package/dist/native/darwin-x64/terminal-host.node +0 -0
  128. package/dist/native/linux-x64/manifest.json +1 -1
  129. package/dist/native/linux-x64/terminal-host.manifest.json +3 -3
  130. package/dist/native/linux-x64/terminal-host.node +0 -0
  131. package/dist/native/win32-x64/manifest.json +2 -2
  132. package/dist/native/win32-x64/process-guardian.node +0 -0
  133. package/dist/native/win32-x64/terminal-host.manifest.json +3 -3
  134. package/dist/native/win32-x64/terminal-host.node +0 -0
  135. package/dist/runtime-payload-inventory.json +5181 -5369
  136. package/dist/ui/components/transcript-viewport.js +10 -19
  137. package/docs/architecture/boundaries.md +14 -0
  138. package/docs/architecture/resident-tabs.md +8 -8
  139. package/docs/architecture/response-copy-delivery.md +1 -1
  140. package/docs/architecture/toolchain.md +2 -2
  141. package/package.json +5 -5
@@ -0,0 +1,85 @@
1
+ const SESSION_RUNTIME_REFRESH_MS = 30_000;
2
+ /**
3
+ * The live worktree claims this runtime's agents hold: each agent's session identity, the heartbeat
4
+ * that keeps the claims fresh, and their release when the runtime is disposed.
5
+ */
6
+ export class SessionRuntimeRegistry {
7
+ #options;
8
+ // Invariant: one entry per agent of this runtime; each agent holds its own claim, and the runtime's exit releases all.
9
+ #identities = new Map();
10
+ #owner = null;
11
+ #timer = null;
12
+ #refresh = Promise.resolve();
13
+ #disposed = false;
14
+ constructor(options) {
15
+ this.#options = options;
16
+ }
17
+ /** The repository context reader for one agent; undefined names the primary agent. */
18
+ readerFor(agentId) {
19
+ return async (sessionId, sessionFile, signal) => {
20
+ const { runtimeId, inspectProcess } = this.#options;
21
+ const owner = await this.#ownerIdentity();
22
+ if (owner === null || runtimeId === undefined || inspectProcess === undefined)
23
+ return null;
24
+ const identity = { sessionId, sessionFile };
25
+ this.#identities.set(agentId, identity);
26
+ const { activateSessionRepositoryContext } = await import("../foundation/lifecycle/session-repository-context.js");
27
+ const context = await activateSessionRepositoryContext(identity, runtimeId, owner, {
28
+ signal,
29
+ inspectProcess,
30
+ ...(agentId === undefined ? {} : { agentId }),
31
+ });
32
+ this.#arm();
33
+ return context;
34
+ };
35
+ }
36
+ /** Stops the heartbeat, waits for an in-flight refresh, and releases every claim this runtime holds. */
37
+ async dispose() {
38
+ this.#disposed = true;
39
+ if (this.#timer !== null)
40
+ clearInterval(this.#timer);
41
+ this.#timer = null;
42
+ await this.#refresh;
43
+ const { runtimeId } = this.#options;
44
+ const owner = await this.#ownerIdentity();
45
+ if (runtimeId === undefined || owner === null)
46
+ return;
47
+ await import("../foundation/lifecycle/session-repository-context.js")
48
+ .then(module => module.releaseSessionRepositoryRuntime(runtimeId, owner))
49
+ .catch(() => undefined);
50
+ }
51
+ async #ownerIdentity() {
52
+ const { runtimeId, inspectProcess } = this.#options;
53
+ if (runtimeId === undefined || inspectProcess === undefined)
54
+ return null;
55
+ this.#owner ??= inspectProcess(process.pid).catch(() => null);
56
+ return await this.#owner;
57
+ }
58
+ #arm() {
59
+ if (this.#timer !== null)
60
+ return;
61
+ this.#timer = setInterval(() => this.#queueRefresh(), this.#options.refreshMs ?? SESSION_RUNTIME_REFRESH_MS);
62
+ this.#timer.unref();
63
+ }
64
+ #queueRefresh() {
65
+ const { runtimeId, inspectProcess } = this.#options;
66
+ if (this.#disposed || this.#identities.size === 0 || runtimeId === undefined || inspectProcess === undefined)
67
+ return;
68
+ this.#refresh = this.#refresh.then(async () => {
69
+ if (this.#disposed)
70
+ return;
71
+ const owner = await this.#ownerIdentity();
72
+ if (owner === null)
73
+ return;
74
+ const { registerSessionRepositoryRuntime } = await import("../foundation/lifecycle/session-repository-context.js");
75
+ for (const [agentId, identity] of this.#identities) {
76
+ if (this.#disposed)
77
+ return;
78
+ await registerSessionRepositoryRuntime(identity, runtimeId, owner, {
79
+ inspectProcess,
80
+ ...(agentId === undefined ? {} : { agentId }),
81
+ }).catch(() => undefined);
82
+ }
83
+ }).catch(() => undefined);
84
+ }
85
+ }
@@ -0,0 +1,32 @@
1
+ import type { OwnedUiShellEngineOptions } from "../app/session-shell/index.js";
2
+ import type { ReleaseNoteCatalog } from "../features/owned-ui/release-notes.js";
3
+ type StartupRoute = NonNullable<OwnedUiShellEngineOptions["startupRoute"]>;
4
+ export interface StartupReleaseNoteOptions {
5
+ readonly ownedSurfaces: boolean;
6
+ /** Deterministic catalog and version seams for composition tests. */
7
+ readonly releaseNotes?: ReleaseNoteCatalog;
8
+ readonly packageVersion?: string;
9
+ /** Without a profile there is nowhere to remember the note as seen, so it is never shown on startup. */
10
+ readonly profileId?: string;
11
+ readonly configDir: string;
12
+ }
13
+ export declare function readPackageVersion(): Promise<string>;
14
+ /**
15
+ * The release notes bare A1 ships and the one note this version shows once per profile on startup:
16
+ * the packaged catalog (or why it could not be read), the running version, and the claim that
17
+ * marks the note seen after its route closes.
18
+ */
19
+ export declare class StartupReleaseNote {
20
+ #private;
21
+ readonly catalog: ReleaseNoteCatalog | null;
22
+ readonly failure: unknown;
23
+ readonly packageVersion: string | null;
24
+ static load(options: StartupReleaseNoteOptions): Promise<StartupReleaseNote>;
25
+ private constructor();
26
+ /** The changelog route to present after the first frame, or undefined when there is no unseen note to show. */
27
+ get startupRoute(): StartupRoute | undefined;
28
+ /** Waits for a pending acknowledgement; a failed one stays unseen and is never reported. */
29
+ settleAcknowledgement(): Promise<void>;
30
+ releaseClaim(): Promise<void>;
31
+ }
32
+ export {};
@@ -0,0 +1,72 @@
1
+ import { readFile } from "node:fs/promises";
2
+ export async function readPackageVersion() {
3
+ const manifest = JSON.parse(await readFile(new URL("../../package.json", import.meta.url), "utf8"));
4
+ const version = manifest?.version;
5
+ if (typeof version !== "string")
6
+ throw new Error("A1 package version is unavailable");
7
+ return version;
8
+ }
9
+ /**
10
+ * The release notes bare A1 ships and the one note this version shows once per profile on startup:
11
+ * the packaged catalog (or why it could not be read), the running version, and the claim that
12
+ * marks the note seen after its route closes.
13
+ */
14
+ export class StartupReleaseNote {
15
+ catalog;
16
+ failure;
17
+ packageVersion;
18
+ #current;
19
+ #claim;
20
+ #acknowledgement = null;
21
+ static async load(options) {
22
+ let catalog = null;
23
+ let failure;
24
+ if (options.ownedSurfaces) {
25
+ try {
26
+ catalog = options.releaseNotes
27
+ ?? await import("../features/owned-ui/release-notes.js").then(module => module.readPackagedReleaseNotes());
28
+ }
29
+ catch (error) {
30
+ failure = error;
31
+ }
32
+ }
33
+ const packageVersion = options.ownedSurfaces ? options.packageVersion ?? await readPackageVersion() : null;
34
+ const current = packageVersion === null ? null : catalog?.current(packageVersion) ?? null;
35
+ const profileId = options.profileId;
36
+ const claim = current === null || profileId === undefined
37
+ ? null
38
+ : await import("../features/owned-ui/release-note-state.js").then(module => module.claimReleaseNote({
39
+ configDir: options.configDir, profileId, version: current.version,
40
+ }));
41
+ return new StartupReleaseNote(catalog, failure, packageVersion, current, claim);
42
+ }
43
+ constructor(catalog, failure, packageVersion, current, claim) {
44
+ this.catalog = catalog;
45
+ this.failure = failure;
46
+ this.packageVersion = packageVersion;
47
+ this.#current = current;
48
+ this.#claim = claim;
49
+ }
50
+ /** The changelog route to present after the first frame, or undefined when there is no unseen note to show. */
51
+ get startupRoute() {
52
+ const current = this.#current;
53
+ const claim = this.#claim;
54
+ if (current === null || claim === null)
55
+ return undefined;
56
+ return {
57
+ route: "changelog",
58
+ input: { document: current.markdown },
59
+ onClosed: () => {
60
+ this.#acknowledgement ??= claim.acknowledge();
61
+ return this.#acknowledgement;
62
+ },
63
+ };
64
+ }
65
+ /** Waits for a pending acknowledgement; a failed one stays unseen and is never reported. */
66
+ async settleAcknowledgement() {
67
+ await this.#acknowledgement?.catch(() => undefined);
68
+ }
69
+ async releaseClaim() {
70
+ await this.#claim?.release();
71
+ }
72
+ }
@@ -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";
@@ -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,
@@ -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,
@@ -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-input.ts.
4
4
  * Modifications: Mechanical port: remap public imports, use ECMAScript private fields, and route the
5
5
  * bare-A1 instruction row and chrome through the shared semantic shortcut and compact padded
@@ -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-selector.ts.
4
4
  * Modifications: Mechanical port: remap public imports, use ECMAScript private fields, and route the
5
5
  * bare-A1 instruction row and chrome through the shared semantic shortcut and compact padded
@@ -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/mermaid.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; behavior remains acceptance-tested.
@@ -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/custom-editor.ts.
4
4
  * Modifications: A1-owned class name and synchronized A1 keybinding contract replace the nominal
5
5
  * private upstream keybinding constructor dependency; bare A1 injects the shared Settings/agent input
@@ -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/custom-editor.ts.
4
4
  * Modifications: A1-owned class name and synchronized A1 keybinding contract replace the nominal
5
5
  * private upstream keybinding constructor dependency; bare A1 injects the shared Settings/agent input
@@ -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/pi-logo.ts.
4
4
  * Modifications: Remapped the private theme import to A1's public-backed adapter and composed the
5
5
  * fixed-color logo into the owned startup header.
@@ -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/scoped-models-selector.ts.
4
4
  * Modifications: Source-synchronized scoped-model selector port: preserve session-only toggles,
5
5
  * search, bulk/provider/reorder actions, dirty state, Ctrl+S persistence, refresh status,
@@ -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/footer.ts.
4
4
  * Modifications: Consumes neutral owned-UI view data instead of a fabricated concrete AgentSession;
5
5
  * preserves the latest physical route for virtual models; an explicit bare-A1 profile colors the
@@ -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/session-selector-search.ts.
4
4
  * Modifications: Source-synchronized session search port with only the public SessionInfo type import
5
5
  * remapped.
@@ -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/session-selector.ts.
4
4
  * Modifications: Source-synchronized session selector port: preserve threaded/current/all scope,
5
5
  * search, sort, named/path filters, rename, delete confirmation, active-session protection,
@@ -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/skill-invocation-message.ts.
4
4
  * Modifications: Mechanical port uses A1's public pi-tui instance, owned theme boundary, and
5
5
  * root-instance keybinding registry because the public coding-agent component closes over a second
@@ -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/skill-invocation-message.ts.
4
4
  * Modifications: Mechanical port uses A1's public pi-tui instance, owned theme boundary, and
5
5
  * root-instance keybinding registry because the public coding-agent component closes over a second
@@ -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/status-indicator.ts.
4
4
  * Modifications: Mechanical source port with public package-root keybinding, Loader, and owned
5
5
  * theme/countdown imports plus ECMAScript private fields.
@@ -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/status-indicator.ts.
4
4
  * Modifications: Mechanical source port with public package-root keybinding, Loader, and owned
5
5
  * theme/countdown imports plus ECMAScript private fields.
@@ -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/themed-text.ts.
4
4
  * Modifications: Integrated invalidation-aware text into A1's owned startup header and notices;
5
5
  * repository formatting only.