pi-ui-extend 1.0.42 → 1.0.45

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 (233) hide show
  1. package/README.md +41 -12
  2. package/dist/app/app.d.ts +10 -0
  3. package/dist/app/app.js +132 -8
  4. package/dist/app/cli/install.js +2 -2
  5. package/dist/app/commands/command-controller.d.ts +4 -0
  6. package/dist/app/commands/command-controller.js +11 -0
  7. package/dist/app/commands/command-git-actions.d.ts +25 -0
  8. package/dist/app/commands/command-git-actions.js +381 -0
  9. package/dist/app/commands/command-host.d.ts +3 -0
  10. package/dist/app/commands/command-host.js +5 -2
  11. package/dist/app/commands/command-model-actions.d.ts +1 -0
  12. package/dist/app/commands/command-model-actions.js +51 -34
  13. package/dist/app/commands/command-navigation-actions.d.ts +1 -0
  14. package/dist/app/commands/command-navigation-actions.js +16 -3
  15. package/dist/app/commands/command-registry.d.ts +2 -0
  16. package/dist/app/commands/command-registry.js +14 -0
  17. package/dist/app/commands/reload-context-inventory.js +12 -1
  18. package/dist/app/input/autocomplete-controller.js +61 -34
  19. package/dist/app/input/input-action-controller.d.ts +2 -0
  20. package/dist/app/input/input-action-controller.js +8 -1
  21. package/dist/app/input/input-controller.d.ts +2 -1
  22. package/dist/app/input/input-controller.js +7 -2
  23. package/dist/app/input/prompt-enhancer-controller.js +53 -35
  24. package/dist/app/input/voice-controller.d.ts +41 -45
  25. package/dist/app/input/voice-controller.js +351 -419
  26. package/dist/app/model/model-usage-controller.js +17 -7
  27. package/dist/app/model/model-usage-status.d.ts +4 -1
  28. package/dist/app/model/model-usage-status.js +270 -46
  29. package/dist/app/popup/menu-items-controller.d.ts +13 -3
  30. package/dist/app/popup/menu-items-controller.js +37 -21
  31. package/dist/app/popup/popup-action-controller.d.ts +12 -2
  32. package/dist/app/popup/popup-action-controller.js +77 -24
  33. package/dist/app/popup/popup-menu-controller.d.ts +36 -14
  34. package/dist/app/popup/popup-menu-controller.js +239 -69
  35. package/dist/app/rendering/dcp-stats.d.ts +9 -4
  36. package/dist/app/rendering/dcp-stats.js +40 -425
  37. package/dist/app/rendering/popup-menu-renderer.d.ts +3 -5
  38. package/dist/app/rendering/popup-menu-renderer.js +42 -37
  39. package/dist/app/rendering/render-controller.js +23 -2
  40. package/dist/app/rendering/status-line-renderer.d.ts +5 -0
  41. package/dist/app/rendering/status-line-renderer.js +41 -5
  42. package/dist/app/rendering/tab-line-renderer.js +26 -20
  43. package/dist/app/runtime.d.ts +12 -1
  44. package/dist/app/runtime.js +120 -12
  45. package/dist/app/screen/mouse-controller.d.ts +2 -0
  46. package/dist/app/screen/mouse-controller.js +17 -7
  47. package/dist/app/screen/status-controller.d.ts +4 -0
  48. package/dist/app/screen/status-controller.js +5 -0
  49. package/dist/app/session/lazy-session-manager.js +34 -0
  50. package/dist/app/session/session-event-controller.d.ts +1 -0
  51. package/dist/app/session/session-event-controller.js +10 -1
  52. package/dist/app/session/session-history.d.ts +1 -0
  53. package/dist/app/session/session-history.js +12 -1
  54. package/dist/app/session/session-lifecycle-controller.d.ts +6 -1
  55. package/dist/app/session/session-lifecycle-controller.js +10 -1
  56. package/dist/app/session/tabs-controller.d.ts +25 -1
  57. package/dist/app/session/tabs-controller.js +442 -153
  58. package/dist/app/subagents/subagents-widget-controller.d.ts +1 -0
  59. package/dist/app/subagents/subagents-widget-controller.js +6 -0
  60. package/dist/app/types.d.ts +11 -1
  61. package/dist/app/workspace/workspace-actions-controller.js +10 -2
  62. package/dist/app/workspace/workspace-undo.d.ts +1 -0
  63. package/dist/app/workspace/workspace-undo.js +1 -0
  64. package/dist/bundled-extensions/question/index.js +9 -1
  65. package/dist/bundled-extensions/question/remote.d.ts +4 -0
  66. package/dist/bundled-extensions/question/remote.js +33 -0
  67. package/dist/bundled-extensions/telegram-connector/bot.d.ts +43 -0
  68. package/dist/bundled-extensions/telegram-connector/bot.js +166 -0
  69. package/dist/bundled-extensions/telegram-connector/config.d.ts +8 -0
  70. package/dist/bundled-extensions/telegram-connector/config.js +87 -0
  71. package/dist/bundled-extensions/telegram-connector/coordinator.d.ts +66 -0
  72. package/dist/bundled-extensions/telegram-connector/coordinator.js +413 -0
  73. package/dist/bundled-extensions/telegram-connector/index.d.ts +3 -0
  74. package/dist/bundled-extensions/telegram-connector/index.js +195 -0
  75. package/dist/bundled-extensions/terminal-bell/index.d.ts +0 -8
  76. package/dist/bundled-extensions/terminal-bell/index.js +0 -76
  77. package/dist/bundled-extensions/workspace-undo/index.d.ts +26 -0
  78. package/dist/bundled-extensions/workspace-undo/index.js +191 -0
  79. package/dist/config.d.ts +21 -2
  80. package/dist/config.js +159 -32
  81. package/dist/default-pix-config.js +20 -10
  82. package/dist/schemas/pi-tools-suite-schema.d.ts +8 -4
  83. package/dist/schemas/pi-tools-suite-schema.js +11 -5
  84. package/dist/schemas/pix-schema.d.ts +12 -2
  85. package/dist/schemas/pix-schema.js +37 -9
  86. package/dist/schemas/tasks-schema.js +1 -1
  87. package/docs/concurrency.md +3 -1
  88. package/docs/desktop-mvp.md +10 -5
  89. package/docs/desktop-task-manager.md +81 -28
  90. package/docs/release.md +30 -6
  91. package/external/pi-tools-suite/README.md +165 -39
  92. package/external/pi-tools-suite/docs/session-recovery.md +7 -0
  93. package/external/pi-tools-suite/docs/subagent-model-pools.md +12 -5
  94. package/external/pi-tools-suite/docs/ui-qa-subagent.md +440 -0
  95. package/external/pi-tools-suite/package.json +6 -1
  96. package/external/pi-tools-suite/src/antigravity-auth/auth-store.ts +2 -1
  97. package/external/pi-tools-suite/src/antigravity-auth/constants.ts +9 -3
  98. package/external/pi-tools-suite/src/antigravity-auth/headers.ts +41 -3
  99. package/external/pi-tools-suite/src/antigravity-auth/models.ts +94 -21
  100. package/external/pi-tools-suite/src/antigravity-auth/oauth.ts +5 -17
  101. package/external/pi-tools-suite/src/antigravity-auth/payload.ts +72 -7
  102. package/external/pi-tools-suite/src/antigravity-auth/stream.ts +13 -1
  103. package/external/pi-tools-suite/src/async-subagents/agents/implement.md +1 -1
  104. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/browser.mjs +346 -0
  105. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/desktop.mjs +1038 -0
  106. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/tui.mjs +759 -0
  107. package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/scripts/browser-qa-runner.mjs +32 -23
  108. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/chrome-devtools/chrome-devtools-provider.mjs +895 -0
  109. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/linux/linux-atspi.py +494 -0
  110. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/macos/macos-accessibility.swift +1085 -0
  111. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/native-terminal/bridge-client.mjs +50 -0
  112. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/native-terminal/native-terminal-host.mjs +501 -0
  113. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/windows/windows-uia.ps1 +454 -0
  114. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-auth.md +114 -0
  115. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-chrome-devtools.md +91 -0
  116. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-playwright.md +145 -0
  117. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser.md +82 -0
  118. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-linux.md +26 -0
  119. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-macos.md +29 -0
  120. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-windows.md +23 -0
  121. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop.md +54 -0
  122. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui-native-terminal.md +59 -0
  123. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui-pty.md +37 -0
  124. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui.md +60 -0
  125. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/scripts/ui-qa-runner.mjs +535 -0
  126. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa.md +75 -0
  127. package/external/pi-tools-suite/src/async-subagents/commands.ts +1 -1
  128. package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +1 -1
  129. package/external/pi-tools-suite/src/async-subagents/core/agents-dir.ts +0 -2
  130. package/external/pi-tools-suite/src/async-subagents/core/browser-qa.ts +16 -2
  131. package/external/pi-tools-suite/src/async-subagents/core/config.ts +40 -17
  132. package/external/pi-tools-suite/src/async-subagents/core/model-selection.ts +2 -1
  133. package/external/pi-tools-suite/src/async-subagents/core/registry.ts +158 -33
  134. package/external/pi-tools-suite/src/async-subagents/core/routing.ts +7 -4
  135. package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +34 -24
  136. package/external/pi-tools-suite/src/async-subagents/core/ultrawork-auto.ts +51 -45
  137. package/external/pi-tools-suite/src/async-subagents/lib.ts +9 -1
  138. package/external/pi-tools-suite/src/async-subagents/tools/spawn.ts +0 -1
  139. package/external/pi-tools-suite/src/async-subagents/tools/subagents.ts +2 -2
  140. package/external/pi-tools-suite/src/coding-discipline/index.ts +90 -59
  141. package/external/pi-tools-suite/src/config.ts +14 -0
  142. package/external/pi-tools-suite/src/context-gateway/accounting-log.ts +282 -0
  143. package/external/pi-tools-suite/src/context-gateway/config.ts +66 -1
  144. package/external/pi-tools-suite/src/context-gateway/efficiency.ts +414 -0
  145. package/external/pi-tools-suite/src/context-gateway/enforcement.ts +123 -3
  146. package/external/pi-tools-suite/src/context-gateway/index.ts +137 -4
  147. package/external/pi-tools-suite/src/context-gateway/storeless-capabilities.ts +5 -5
  148. package/external/pi-tools-suite/src/context-gateway/telemetry.ts +2 -2
  149. package/external/pi-tools-suite/src/context-gateway/types.ts +8 -1
  150. package/external/pi-tools-suite/src/dcp/auto-compress-budget.ts +39 -4
  151. package/external/pi-tools-suite/src/dcp/auto-compress.ts +41 -14
  152. package/external/pi-tools-suite/src/dcp/commands.ts +14 -156
  153. package/external/pi-tools-suite/src/dcp/compress-tool.ts +8 -2
  154. package/external/pi-tools-suite/src/dcp/compression-progress.ts +22 -0
  155. package/external/pi-tools-suite/src/dcp/config.ts +58 -4
  156. package/external/pi-tools-suite/src/dcp/conversation-index.ts +36 -9
  157. package/external/pi-tools-suite/src/dcp/diagnostics.ts +41 -0
  158. package/external/pi-tools-suite/src/dcp/fresh-tool-results.ts +38 -0
  159. package/external/pi-tools-suite/src/dcp/index.ts +338 -66
  160. package/external/pi-tools-suite/src/dcp/journal.ts +126 -4
  161. package/external/pi-tools-suite/src/dcp/progress-controller.ts +2 -1
  162. package/external/pi-tools-suite/src/dcp/pruner-candidates.ts +92 -2
  163. package/external/pi-tools-suite/src/dcp/pruner-nudge.ts +36 -33
  164. package/external/pi-tools-suite/src/dcp/pruner.ts +1 -0
  165. package/external/pi-tools-suite/src/dcp/routine-pressure.ts +86 -0
  166. package/external/pi-tools-suite/src/dcp/state.ts +9 -0
  167. package/external/pi-tools-suite/src/dcp/statistics.d.ts +8 -0
  168. package/external/pi-tools-suite/src/dcp/statistics.js +156 -0
  169. package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +68 -16
  170. package/external/pi-tools-suite/src/lib/project.ts +36 -1
  171. package/external/pi-tools-suite/src/model-tools/index.ts +10 -7
  172. package/external/pi-tools-suite/src/repo-discovery/index.ts +304 -4
  173. package/external/pi-tools-suite/src/resource-registry/index.ts +282 -21
  174. package/external/pi-tools-suite/src/session-recovery/index.ts +17 -0
  175. package/external/pi-tools-suite/src/todo/index.ts +21 -0
  176. package/external/pi-tools-suite/src/todo/todo.ts +19 -1
  177. package/external/pi-tools-suite/src/tool-descriptions.ts +44 -15
  178. package/package.json +7 -8
  179. package/schemas/pi-tools-suite.json +44 -12
  180. package/schemas/pix.json +109 -15
  181. package/schemas/tasks.json +1 -2
  182. package/skills/simplify/SKILL.md +33 -5
  183. package/external/pi-tools-suite/docs/browser-qa-subagent.md +0 -196
  184. package/external/pi-tools-suite/src/async-subagents/agents/browser-qa.md +0 -598
  185. package/skills/playwright-cli/SKILL.md +0 -420
  186. package/skills/playwright-cli/references/element-attributes.md +0 -23
  187. package/skills/playwright-cli/references/playwright-tests.md +0 -50
  188. package/skills/playwright-cli/references/request-mocking.md +0 -87
  189. package/skills/playwright-cli/references/running-code.md +0 -241
  190. package/skills/playwright-cli/references/session-management.md +0 -273
  191. package/skills/playwright-cli/references/spec-driven-testing.md +0 -311
  192. package/skills/playwright-cli/references/storage-state.md +0 -290
  193. package/skills/playwright-cli/references/test-generation.md +0 -142
  194. package/skills/playwright-cli/references/tracing.md +0 -154
  195. package/skills/playwright-cli/references/video-recording.md +0 -147
  196. package/skills/spec-wiki/SKILL.md +0 -55
  197. package/skills/spec-wiki/evals/evals.json +0 -132
  198. package/skills/spec-wiki/evals/files/bootstrap/architecture/rfc-007.md +0 -14
  199. package/skills/spec-wiki/evals/files/bootstrap/docs/how-to-pay.md +0 -4
  200. package/skills/spec-wiki/evals/files/bootstrap/docs/overview.md +0 -9
  201. package/skills/spec-wiki/evals/files/bootstrap/requirements/payment-behavior.md +0 -17
  202. package/skills/spec-wiki/evals/files/bootstrap/src/payments.ts +0 -12
  203. package/skills/spec-wiki/evals/files/bootstrap/tests/payments.test.ts +0 -11
  204. package/skills/spec-wiki/evals/files/focused/src/session.ts +0 -5
  205. package/skills/spec-wiki/evals/files/focused/tests/session.test.ts +0 -17
  206. package/skills/spec-wiki/evals/files/maintenance/low-signal/incoming/capture.txt +0 -2
  207. package/skills/spec-wiki/evals/files/maintenance/low-signal/src/capture.ts +0 -3
  208. package/skills/spec-wiki/evals/files/maintenance/move/docs/old-job-contract.md +0 -18
  209. package/skills/spec-wiki/evals/files/maintenance/move/src/job.ts +0 -5
  210. package/skills/spec-wiki/evals/files/maintenance/new-relation/docs/session-refresh.md +0 -24
  211. package/skills/spec-wiki/evals/files/maintenance/new-relation/incoming/refresh-worker.ts +0 -7
  212. package/skills/spec-wiki/evals/files/maintenance/new-relation/src/session.ts +0 -7
  213. package/skills/spec-wiki/evals/files/maintenance/no-impact/docs/auth-contract.md +0 -17
  214. package/skills/spec-wiki/evals/files/maintenance/no-impact/incoming/telemetry-format.ts +0 -3
  215. package/skills/spec-wiki/evals/files/maintenance/no-impact/src/auth.ts +0 -3
  216. package/skills/spec-wiki/evals/files/query/docs/how-to-run-jobs.md +0 -4
  217. package/skills/spec-wiki/evals/files/query/docs/spec-overview.md +0 -9
  218. package/skills/spec-wiki/evals/files/query/features/jobs/cancellation-contract.md +0 -15
  219. package/skills/spec-wiki/evals/files/query/features/jobs/retry-spec.md +0 -6
  220. package/skills/spec-wiki/evals/maintenance_regression.py +0 -311
  221. package/skills/spec-wiki/evals/retrieval-eval.md +0 -37
  222. package/skills/spec-wiki/evals/retrieval-evals.json +0 -37
  223. package/skills/spec-wiki/evals/trigger-evals.json +0 -94
  224. package/skills/spec-wiki/references/bootstrap.md +0 -100
  225. package/skills/spec-wiki/references/focused-spec.md +0 -117
  226. package/skills/spec-wiki/references/index-schema.md +0 -330
  227. package/skills/spec-wiki/references/maintenance.md +0 -134
  228. package/skills/spec-wiki/references/query.md +0 -74
  229. package/skills/spec-wiki/scripts/spec_wiki.py +0 -2076
  230. /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/examples/qa-auth.example.jsonc +0 -0
  231. /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/examples/qa-flow.example.jsonc +0 -0
  232. /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/vendor/fflate.LICENSE +0 -0
  233. /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/vendor/fflate.mjs +0 -0
@@ -22,6 +22,7 @@ class LazySessionManager {
22
22
  labelsById = new Map();
23
23
  leafId = null;
24
24
  hydrated;
25
+ contextManager;
25
26
  tailEntryCount;
26
27
  tailStartOffset = 0;
27
28
  constructor(sessionPath, options = {}) {
@@ -74,6 +75,7 @@ class LazySessionManager {
74
75
  this.byId.clear();
75
76
  this.labelsById.clear();
76
77
  this.leafId = null;
78
+ this.contextManager = undefined;
77
79
  mkdirSync(this.sessionDirPath, { recursive: true });
78
80
  this.sessionFilePath = join(this.sessionDirPath, `${timestamp.replace(/[:.]/g, "-")}_${sessionId}.jsonl`);
79
81
  writeFileSync(this.sessionFilePath, `${JSON.stringify(header)}\n`, "utf8");
@@ -103,6 +105,11 @@ class LazySessionManager {
103
105
  getEntries() {
104
106
  return this.hydrated?.getEntries() ?? [...this.entries];
105
107
  }
108
+ // Before hydration this is a presentation/file tail, NOT selected ancestry:
109
+ // it can omit old ancestors and contain abandoned side-branch entries.
110
+ // Lineage-sensitive callers must use readFullBranchEntries(); retry proofs
111
+ // must follow parentId, never compare positions in this cache. See
112
+ // specs/dcp-statistics.md#lazy-tail-retry-invariant and its regression tests.
106
113
  getBranch(fromId) {
107
114
  if (this.hydrated)
108
115
  return this.hydrated.getBranch(fromId);
@@ -161,6 +168,8 @@ class LazySessionManager {
161
168
  buildContextEntries() {
162
169
  if (this.hydrated)
163
170
  return this.hydrated.buildContextEntries();
171
+ if (this.tailStartOffset > 0)
172
+ return this.completeContextManager().buildContextEntries();
164
173
  const entries = this.contextEntries();
165
174
  const byId = new Map(entries.map((entry) => [entry.id, entry]));
166
175
  return buildSdkContextEntries(entries, entries.at(-1)?.id ?? null, byId);
@@ -168,6 +177,8 @@ class LazySessionManager {
168
177
  buildSessionContext() {
169
178
  if (this.hydrated)
170
179
  return this.hydrated.buildSessionContext();
180
+ if (this.tailStartOffset > 0)
181
+ return this.completeContextManager().buildSessionContext();
171
182
  const entries = this.contextEntries();
172
183
  const byId = new Map(entries.map((entry) => [entry.id, entry]));
173
184
  return buildSessionContext(entries, entries.at(-1)?.id ?? null, byId);
@@ -212,6 +223,7 @@ class LazySessionManager {
212
223
  return;
213
224
  }
214
225
  this.leafId = branchFromId;
226
+ this.contextManager = undefined;
215
227
  }
216
228
  resetLeaf() {
217
229
  if (this.hydrated) {
@@ -219,6 +231,7 @@ class LazySessionManager {
219
231
  return;
220
232
  }
221
233
  this.leafId = null;
234
+ this.contextManager = undefined;
222
235
  }
223
236
  createBranchedSession(leafId) {
224
237
  return this.hydrate().createBranchedSession(leafId);
@@ -292,9 +305,29 @@ class LazySessionManager {
292
305
  hydrate() {
293
306
  if (!this.hydrated) {
294
307
  this.hydrated = SessionManager.open(this.sessionFilePath, this.sessionDirPath, this.cwdPath);
308
+ this.contextManager = undefined;
295
309
  }
296
310
  return this.hydrated;
297
311
  }
312
+ /**
313
+ * The tail cache is a presentation/history optimisation, not a valid model
314
+ * context boundary. If older entries exist, reconstruct provider context from
315
+ * the complete persisted session while leaving the facade itself lazy so the
316
+ * UI can continue paging old history on demand.
317
+ */
318
+ completeContextManager() {
319
+ if (!this.contextManager) {
320
+ const manager = SessionManager.open(this.sessionFilePath, this.sessionDirPath, this.cwdPath);
321
+ if (this.leafId === null) {
322
+ manager.resetLeaf();
323
+ }
324
+ else if (manager.getLeafId() !== this.leafId && manager.getEntry(this.leafId)) {
325
+ manager.branch(this.leafId);
326
+ }
327
+ this.contextManager = manager;
328
+ }
329
+ return this.contextManager;
330
+ }
298
331
  async loadHeaderAsync(cwdOverride) {
299
332
  const existingHeader = await readSessionHeaderFast(this.sessionFilePath);
300
333
  if (existingHeader)
@@ -335,6 +368,7 @@ class LazySessionManager {
335
368
  this.entries.push(entry);
336
369
  this.byId.set(entry.id, entry);
337
370
  this.leafId = entry.id;
371
+ this.contextManager = undefined;
338
372
  return entry.id;
339
373
  }
340
374
  newEntry(type, payload) {
@@ -91,6 +91,7 @@ export declare class AppSessionEventController {
91
91
  private currentThinkingEntryStartedAt;
92
92
  private thinkingElapsedRenderTimer;
93
93
  private assistantMessageClosed;
94
+ private currentAssistantTerminalErrorRendered;
94
95
  private assistantTextBuffer;
95
96
  constructor(host: AppSessionEventControllerHost);
96
97
  snapshotState(): AppSessionEventControllerState;
@@ -1,7 +1,7 @@
1
1
  import { isRetryableAssistantError } from "@earendil-works/pi-ai";
2
2
  import { createId } from "../id.js";
3
3
  import { extractImageContents, renderContent, renderUserMessageContent, stringifyUnknown } from "../rendering/message-content.js";
4
- import { customMessageEntry, extensionSessionEntry, loadSessionHistoryEntries, loadSessionHistoryEntriesAsync } from "./session-history.js";
4
+ import { assistantTerminalErrorText, customMessageEntry, extensionSessionEntry, loadSessionHistoryEntries, loadSessionHistoryEntriesAsync } from "./session-history.js";
5
5
  import { sessionHistoryDisplayMessages, sessionHistoryDisplayMessagesFromEntries, sessionHistoryFullBranchEntries, sessionHistoryOlderMessagesReader } from "./pix-system-message.js";
6
6
  import { THINKING_TOOL_NAME } from "../constants.js";
7
7
  import { isRecord } from "../guards.js";
@@ -34,6 +34,7 @@ export class AppSessionEventController {
34
34
  currentThinkingEntryStartedAt;
35
35
  thinkingElapsedRenderTimer;
36
36
  assistantMessageClosed = false;
37
+ currentAssistantTerminalErrorRendered = false;
37
38
  assistantTextBuffer = "";
38
39
  constructor(host) {
39
40
  this.host = host;
@@ -586,6 +587,7 @@ export class AppSessionEventController {
586
587
  }
587
588
  if (isRecord(message) && message.role === "assistant") {
588
589
  this.assistantMessageClosed = false;
590
+ this.currentAssistantTerminalErrorRendered = false;
589
591
  this.clearCurrentAssistantState();
590
592
  }
591
593
  }
@@ -601,6 +603,12 @@ export class AppSessionEventController {
601
603
  this.renderAssistantToolCallsFromMessage(message);
602
604
  this.finishCurrentThinkingEntry();
603
605
  this.flushAssistantTextBuffer(true);
606
+ const terminalError = assistantTerminalErrorText(message);
607
+ if (terminalError && !this.currentAssistantTerminalErrorRendered) {
608
+ this.addEntry({ id: createId("error"), kind: "error", text: terminalError });
609
+ this.currentAssistantTerminalErrorRendered = true;
610
+ this.showManualRetryOnTerminalError(message);
611
+ }
604
612
  this.clearCurrentAssistantState();
605
613
  this.assistantMessageClosed = true;
606
614
  }
@@ -726,6 +734,7 @@ export class AppSessionEventController {
726
734
  this.host.setSessionActivity(this.host.runtime()?.session.isStreaming ? "running" : "idle");
727
735
  const errorText = assistantEvent.error.errorMessage ?? assistantEvent.reason;
728
736
  this.addEntry({ id: createId("error"), kind: "error", text: errorText });
737
+ this.currentAssistantTerminalErrorRendered = true;
729
738
  this.showManualRetryOnTerminalError(assistantEvent.error);
730
739
  break;
731
740
  }
@@ -41,4 +41,5 @@ export declare function customMessageEntry(message: Record<string, unknown>): En
41
41
  export declare function extensionSessionEntry(value: unknown): Extract<Entry, {
42
42
  kind: "extension-entry";
43
43
  }> | undefined;
44
+ export declare function assistantTerminalErrorText(message: Record<string, unknown>): string | undefined;
44
45
  export {};
@@ -4,6 +4,7 @@ import { isOnlyHiddenMetadata } from "../../markdown-format.js";
4
4
  import { extractImageContents, renderContent, renderUserMessageContent, stringifyUnknown } from "../rendering/message-content.js";
5
5
  import { THINKING_TOOL_NAME } from "../constants.js";
6
6
  import { PIX_EXTENSION_ENTRY_ROLE, PIX_SESSION_ENTRY_ID_FIELD, PIX_SYSTEM_DISPLAY_ENTRY_CUSTOM_TYPE, PIX_SYSTEM_MESSAGE_CUSTOM_TYPE, PIX_THINKING_LEVEL_FIELD } from "./pix-system-message.js";
7
+ import { WORKSPACE_MUTATION_ENTRY_TYPE } from "../workspace/workspace-undo.js";
7
8
  const HISTORICAL_SUBAGENTS_OBSERVATION = { showSnapshot: false };
8
9
  const DEFAULT_HISTORY_CHUNK_SIZE = 50;
9
10
  const DEFAULT_HISTORY_TAIL_MESSAGE_COUNT = 80;
@@ -189,7 +190,7 @@ export function customMessageEntry(message) {
189
190
  export function extensionSessionEntry(value) {
190
191
  if (!isRecord(value) || value.type !== "custom" || typeof value.id !== "string" || typeof value.customType !== "string")
191
192
  return undefined;
192
- if (value.customType === PIX_SYSTEM_DISPLAY_ENTRY_CUSTOM_TYPE)
193
+ if (value.customType === PIX_SYSTEM_DISPLAY_ENTRY_CUSTOM_TYPE || value.customType === WORKSPACE_MUTATION_ENTRY_TYPE)
193
194
  return undefined;
194
195
  return {
195
196
  id: `extension-entry-${value.id}`,
@@ -198,6 +199,12 @@ export function extensionSessionEntry(value) {
198
199
  expanded: false,
199
200
  };
200
201
  }
202
+ export function assistantTerminalErrorText(message) {
203
+ if (message.stopReason !== "error")
204
+ return undefined;
205
+ const errorMessage = typeof message.errorMessage === "string" ? message.errorMessage.trim() : "";
206
+ return errorMessage || "Request failed before the assistant produced a response.";
207
+ }
201
208
  function renderAssistantHistoryMessage(message, toolResults, options) {
202
209
  const content = message.content;
203
210
  if (!Array.isArray(content))
@@ -273,4 +280,8 @@ function renderAssistantHistoryMessage(message, toolResults, options) {
273
280
  if (assistantText && !isOnlyHiddenMetadata(assistantText)) {
274
281
  options.addEntry({ id: createId("assistant"), kind: "assistant", text: assistantText });
275
282
  }
283
+ const terminalError = assistantTerminalErrorText(message);
284
+ if (terminalError) {
285
+ options.addEntry({ id: createId("error"), kind: "error", text: terminalError });
286
+ }
276
287
  }
@@ -3,7 +3,12 @@ import type { InputEditor } from "../../input-editor.js";
3
3
  import type { AppOptions, Entry, PixExtensionUIContext, SessionActivity } from "../types.js";
4
4
  export type AppSessionLifecycleHost = {
5
5
  options: AppOptions;
6
- createRuntime(): Promise<AgentSessionRuntime>;
6
+ prepareStartupRuntime?(): Promise<{
7
+ sessionPath?: string;
8
+ } | null>;
9
+ createRuntime(options?: {
10
+ sessionPath?: string;
11
+ }): Promise<AgentSessionRuntime>;
7
12
  entries: Entry[];
8
13
  runtime(): AgentSessionRuntime | undefined;
9
14
  setRuntime(runtime: AgentSessionRuntime | undefined): void;
@@ -32,7 +32,16 @@ export class AppSessionLifecycleController {
32
32
  });
33
33
  try {
34
34
  await this.host.loadStartupConfig();
35
- const runtime = await this.host.createRuntime();
35
+ const startupRuntime = await this.host.prepareStartupRuntime?.();
36
+ if (startupRuntime === null) {
37
+ this.host.setRuntime(undefined);
38
+ this.host.setSessionStatus(undefined);
39
+ this.host.setSessionActivity("idle");
40
+ await this.host.restoreTabsAfterStartup();
41
+ this.host.render();
42
+ return;
43
+ }
44
+ const runtime = await this.host.createRuntime(startupRuntime ?? undefined);
36
45
  if (!this.host.isRunning()) {
37
46
  await this.host.disposeRuntimeForQuit(runtime);
38
47
  return;
@@ -16,8 +16,11 @@ export type AppTabsControllerHost = {
16
16
  readonly maxProjectSessions?: number | (() => number | undefined);
17
17
  readonly blinkController: AppBlinkController;
18
18
  runtime(): AgentSessionRuntime | undefined;
19
- createRuntimeForNewSession(): Promise<AgentSessionRuntime>;
19
+ createRuntimeForNewSession(modelRef?: string): Promise<AgentSessionRuntime>;
20
20
  createRuntimeForSession(sessionPath: string): Promise<AgentSessionRuntime>;
21
+ draftModelOverrideRef?(): string | undefined;
22
+ resetDraftModelSelection?(): void;
23
+ deactivateRuntimeForDraft?(): void;
21
24
  awaitCurrentSessionExtensions?(runtime?: AgentSessionRuntime): Promise<void>;
22
25
  activateRuntime(runtime: AgentSessionRuntime, options?: BindCurrentSessionOptions): Promise<void>;
23
26
  disposeRuntime(runtime: AgentSessionRuntime): Promise<void>;
@@ -43,6 +46,8 @@ export type AppTabsControllerHost = {
43
46
  restoreAutoUserMessages?(messages: readonly SubmittedUserMessage[]): void;
44
47
  captureDeferredUserMessages?(): readonly SubmittedUserMessage[];
45
48
  restoreDeferredUserMessages?(messages: readonly SubmittedUserMessage[]): void;
49
+ openDraftSessionSelector?(): void;
50
+ closeDraftSessionSelector?(): void;
46
51
  contextInventoryText?(runtime: AgentSessionRuntime, heading: string): string;
47
52
  addEntry(entry: Entry): void;
48
53
  showToast(message: string, kind: "success" | "error" | "warning" | "info"): void;
@@ -64,6 +69,7 @@ export declare class AppTabsController {
64
69
  private readonly tabIdsNeedingHistoryReload;
65
70
  private readonly historyInvalidationGenerationByTabId;
66
71
  private readonly runtimeOwnershipGenerationByTabId;
72
+ private readonly touchedDraftTabIds;
67
73
  private readonly orphanRuntimeDisposals;
68
74
  private readonly lifecycleMutationQueue;
69
75
  private activeTabId;
@@ -74,6 +80,9 @@ export declare class AppTabsController {
74
80
  private lifecycleGeneration;
75
81
  private lifecycleMutationRunning;
76
82
  private saveTabsWriteTail;
83
+ private startupSavedTabs;
84
+ private startupPrepared;
85
+ private startupRuntimePlan;
77
86
  private restored;
78
87
  private retentionCleanupRunning;
79
88
  private retentionCleanupScheduled;
@@ -88,6 +97,9 @@ export declare class AppTabsController {
88
97
  markTerminalBellAttention(sessionPath: string | undefined): void;
89
98
  tabPanelRows(terminalRows: number): number;
90
99
  activeInputTabId(): string | undefined;
100
+ isDraftTabActive(): boolean;
101
+ openSessionPaths(): readonly string[];
102
+ noteActiveDraftInputChanged(): void;
91
103
  inputStateForTab(tabId: string | undefined): TabInputState | undefined;
92
104
  setInputStateForTab(tabId: string | undefined, state: TabInputState): Promise<void>;
93
105
  disposeInactiveRuntimes(disposeRuntime?: (runtime: AgentSessionRuntime) => Promise<void>): Promise<void>;
@@ -99,18 +111,28 @@ export declare class AppTabsController {
99
111
  save?: boolean;
100
112
  force?: boolean;
101
113
  }): void;
114
+ prepareStartupRuntime(): Promise<{
115
+ sessionPath?: string;
116
+ } | null>;
102
117
  restoreAfterStartup(): Promise<void>;
103
118
  private restoreAfterStartupMutation;
104
119
  openNewTab(): Promise<void>;
105
120
  private openNewTabMutation;
121
+ materializeActiveDraftTab(): Promise<AgentSessionRuntime | undefined>;
122
+ private materializeActiveDraftTabMutation;
123
+ openSessionInActiveDraftTab(sessionPath: string): Promise<boolean>;
124
+ private openSessionInActiveDraftTabMutation;
125
+ private ownsDraftLifecycle;
106
126
  openSessionInNewTab(sessionPath: string): Promise<boolean>;
107
127
  private openSessionInNewTabMutation;
108
128
  forkSessionEntryInNewTab(entryId: string): Promise<boolean>;
109
129
  private forkSessionEntryInNewTabMutation;
110
130
  switchToTab(tabId: string): Promise<void>;
111
131
  private switchToTabMutation;
132
+ private switchDraftToPersistedTab;
112
133
  closeTab(tabId: string): Promise<void>;
113
134
  private closeTabMutation;
135
+ private closeDraftTabMutation;
114
136
  private replaceLastTabWithNewSession;
115
137
  private loadActiveSessionHistory;
116
138
  private cancelHistoryLoad;
@@ -118,6 +140,8 @@ export declare class AppTabsController {
118
140
  private runtimeForCommand;
119
141
  private idleRuntime;
120
142
  private activeTab;
143
+ private createDraftTab;
144
+ private activateDraftTab;
121
145
  private clearStartupTabPlaceholders;
122
146
  private storeActiveRuntime;
123
147
  private storeActiveSessionView;