@timurproko/a1 0.2.6-dev.717 → 0.2.6-dev.734

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 (213) hide show
  1. package/bin/cli.js +13 -2
  2. package/bin/ui.js +13 -0
  3. package/dist/app/session-shell/clipboard-services.d.ts +19 -0
  4. package/dist/app/session-shell/clipboard-services.js +7 -0
  5. package/dist/app/session-shell/exit-notice.d.ts +9 -5
  6. package/dist/app/session-shell/exit-notice.js +5 -5
  7. package/dist/app/session-shell/index.d.ts +3 -1
  8. package/dist/app/session-shell/index.js +1 -0
  9. package/dist/app/session-shell/paste-preparation-client.d.ts +3 -0
  10. package/dist/app/session-shell/paste-preparation-client.js +5 -2
  11. package/dist/app/session-shell/path-chip-presentation.d.ts +10 -3
  12. package/dist/app/session-shell/path-chip-presentation.js +48 -6
  13. package/dist/app/session-shell/prompt-chips.js +30 -4
  14. package/dist/app/session-shell/prompt-suggestion-controller.d.ts +5 -4
  15. package/dist/app/session-shell/prompt-suggestion-controller.js +148 -58
  16. package/dist/app/session-shell/quit-outro.d.ts +3 -1
  17. package/dist/app/session-shell/quit-outro.js +23 -8
  18. package/dist/app/session-shell/response-copy-transport.d.ts +6 -1
  19. package/dist/app/session-shell/response-copy-transport.js +8 -2
  20. package/dist/app/session-shell/session-shell-root.d.ts +22 -11
  21. package/dist/app/session-shell/session-shell-root.js +19 -12
  22. package/dist/app/session-shell/session-shell.d.ts +19 -21
  23. package/dist/app/session-shell/session-shell.js +678 -840
  24. package/dist/app/session-shell/session-viewport-controller.js +33 -21
  25. package/dist/cli/dispatch.js +5 -3
  26. package/dist/cli/session-context.d.ts +5 -1
  27. package/dist/cli/session-context.js +25 -8
  28. package/dist/composition/owned-ui.d.ts +23 -2
  29. package/dist/composition/owned-ui.js +124 -33
  30. package/dist/composition/session-info-reference.d.ts +2 -2
  31. package/dist/composition/session-info-reference.js +2 -2
  32. package/dist/composition/settings-route-host.js +2 -1
  33. package/dist/contracts/agent-engine/capability-ports.d.ts +1 -85
  34. package/dist/contracts/agent-engine/capability-ports.js +1 -35
  35. package/dist/contracts/agent-engine/index.d.ts +1 -7
  36. package/dist/contracts/agent-engine/index.js +0 -4
  37. package/dist/contracts/owned-ui/index.d.ts +9 -3
  38. package/dist/contracts/owned-ui/index.js +2 -1
  39. package/dist/contracts/owned-ui/model.d.ts +10 -0
  40. package/dist/contracts/owned-ui/session-backend.d.ts +119 -0
  41. package/dist/contracts/owned-ui/session-presenters.d.ts +55 -0
  42. package/dist/contracts/owned-ui/session-presenters.js +1 -0
  43. package/dist/contracts/owned-ui/session-workflows.d.ts +342 -0
  44. package/dist/contracts/owned-ui/session-workflows.js +30 -0
  45. package/dist/contracts/owned-ui/suggestion-diagnostics.d.ts +5 -1
  46. package/dist/contracts/owned-ui/suggestion-diagnostics.js +3 -1
  47. package/dist/contracts/owned-ui/validation.js +7 -0
  48. package/dist/features/launch/index.d.ts +1 -1
  49. package/dist/features/launch/session-context.d.ts +17 -2
  50. package/dist/features/launch/session-context.js +9 -5
  51. package/dist/features/owned-ui/settings-app.js +56 -54
  52. package/dist/features/prompt-suggestions/diagnostics.js +4 -1
  53. package/dist/foundation/lifecycle/index.d.ts +2 -2
  54. package/dist/foundation/lifecycle/index.js +1 -1
  55. package/dist/foundation/lifecycle/session-repository-context.d.ts +19 -2
  56. package/dist/foundation/lifecycle/session-repository-context.js +434 -66
  57. package/dist/foundation/process-containment/index.d.ts +1 -0
  58. package/dist/foundation/process-containment/index.js +1 -0
  59. package/dist/foundation/process-containment/native-process-inspector.d.ts +3 -0
  60. package/dist/foundation/process-containment/native-process-inspector.js +21 -0
  61. package/dist/foundation/release/bootstrap.js +1 -2
  62. package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
  63. package/dist/foundation/release/progress-palette.generated.js +2 -2
  64. package/dist/foundation/release/release-gc.js +1 -1
  65. package/dist/foundation/release/update.js +0 -4
  66. package/dist/foundation/startup/startup-descriptor.js +2 -2
  67. package/dist/foundation/storage/control-store.js +0 -12
  68. package/dist/integrations/pi/components/components.js +2 -18
  69. package/dist/integrations/pi/components/index.d.ts +4 -4
  70. package/dist/integrations/pi/components/index.js +2 -2
  71. package/dist/integrations/pi/components/modal-frame.js +3 -4
  72. package/dist/integrations/pi/components/models-dialog.js +6 -35
  73. package/dist/integrations/pi/components/prompt-input-port.d.ts +1 -0
  74. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
  75. package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
  76. package/dist/integrations/pi/components/share-operation-dialog.js +3 -3
  77. package/dist/integrations/pi/components/shell-editor-autocomplete.js +19 -16
  78. package/dist/integrations/pi/components/shell-extension-ui.d.ts +5 -3
  79. package/dist/integrations/pi/components/shell-extension-ui.js +26 -12
  80. package/dist/integrations/pi/components/shell-hotkey-sections.js +2 -2
  81. package/dist/integrations/pi/components/shell-presenters-info.js +10 -10
  82. package/dist/integrations/pi/components/shell-presenters-transcript.js +13 -13
  83. package/dist/integrations/pi/components/shell-selectors-dialogs.js +5 -6
  84. package/dist/integrations/pi/components/shell-shared-facade.d.ts +21 -1
  85. package/dist/integrations/pi/components/shell-shared-facade.js +19 -3
  86. package/dist/integrations/pi/components/skills-dialog.js +3 -3
  87. package/dist/integrations/pi/components/submitted-prompt-adapter.js +2 -3
  88. package/dist/integrations/pi/components/theme.d.ts +9 -0
  89. package/dist/integrations/pi/components/theme.js +30 -0
  90. package/dist/integrations/pi/components/tool-result-adapter.js +6 -1
  91. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  92. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
  93. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  94. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  95. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  96. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  97. package/dist/integrations/pi/components/upstream/components/extension-editor.js +6 -6
  98. package/dist/integrations/pi/components/upstream/components/extension-input.js +4 -4
  99. package/dist/integrations/pi/components/upstream/components/extension-selector.js +4 -4
  100. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  101. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +5 -5
  102. package/dist/integrations/pi/components/upstream/components/owned-editor.js +8 -5
  103. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  104. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  105. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +3 -3
  106. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  107. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  108. package/dist/integrations/pi/components/upstream/components/session-selector.js +9 -9
  109. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +3 -2
  110. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +6 -3
  111. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
  112. package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
  113. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  114. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  115. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  116. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +2 -2
  117. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +4 -0
  118. package/dist/integrations/pi/components/upstream/components/tool-execution.js +11 -1
  119. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +2 -2
  120. package/dist/integrations/pi/components/upstream/components/tree-selector.js +27 -18
  121. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  122. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  123. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +4 -4
  124. package/dist/integrations/pi/components/upstream/history/editor-core.js +11 -7
  125. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  126. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  127. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  128. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  129. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  130. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  131. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  132. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  133. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +31 -0
  134. package/dist/integrations/pi/components/upstream/program-status-reporter.js +89 -0
  135. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  136. package/dist/integrations/pi/components/upstream/theme/theme.d.ts +22 -1
  137. package/dist/integrations/pi/components/upstream/theme/theme.js +225 -10
  138. package/dist/integrations/pi/engine/adapter.d.ts +44 -24
  139. package/dist/integrations/pi/engine/adapter.js +130 -22
  140. package/dist/integrations/pi/engine/command-dispatch.d.ts +2 -5
  141. package/dist/integrations/pi/engine/extension-ui-binding.d.ts +2 -11
  142. package/dist/integrations/pi/engine/host-ports.d.ts +20 -0
  143. package/dist/integrations/pi/engine/host-ports.js +13 -0
  144. package/dist/integrations/pi/engine/host.d.ts +70 -0
  145. package/dist/integrations/pi/engine/host.js +147 -0
  146. package/dist/integrations/pi/engine/index.d.ts +8 -4
  147. package/dist/integrations/pi/engine/index.js +3 -1
  148. package/dist/integrations/pi/engine/pi-settings-metadata.json +1 -1
  149. package/dist/integrations/pi/engine/resource-catalog.d.ts +4 -23
  150. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  151. package/dist/integrations/pi/engine/runtime-integration.d.ts +8 -2
  152. package/dist/integrations/pi/engine/runtime-integration.js +12 -7
  153. package/dist/integrations/pi/engine/session-events.js +10 -2
  154. package/dist/integrations/pi/engine/session-integration.d.ts +3 -8
  155. package/dist/integrations/pi/engine/session-integration.js +0 -49
  156. package/dist/integrations/pi/engine/session-runtime.d.ts +18 -3
  157. package/dist/integrations/pi/engine/session-runtime.js +18 -7
  158. package/dist/integrations/pi/engine/settings-bridge.d.ts +2 -2
  159. package/dist/integrations/pi/engine/settings-bridge.js +0 -2
  160. package/dist/integrations/pi/engine/settings-port.d.ts +2 -0
  161. package/dist/integrations/pi/engine/settings-port.js +3 -5
  162. package/dist/integrations/pi/engine/transcript-projection.js +2 -1
  163. package/dist/integrations/pi/engine/workflows.d.ts +33 -260
  164. package/dist/integrations/pi/engine/workflows.js +6 -28
  165. package/dist/integrations/pi/session-presenters/index.d.ts +2 -0
  166. package/dist/integrations/pi/session-presenters/index.js +1 -0
  167. package/dist/integrations/pi/session-presenters/presenters.d.ts +16 -0
  168. package/dist/integrations/pi/session-presenters/presenters.js +341 -0
  169. package/dist/integrations/pi/startup-public.js +306 -290
  170. package/dist/integrations/pi/startup-public.manifest.json +289 -265
  171. package/dist/integrations/pi/tui-runtime/adapter.d.ts +2 -1
  172. package/dist/integrations/pi/tui-runtime/adapter.js +7 -2
  173. package/dist/integrations/pi/tui-runtime/contracts.d.ts +3 -1
  174. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +8 -1
  175. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +67 -2
  176. package/dist/integrations/pi/tui-runtime/index.d.ts +1 -1
  177. package/dist/integrations/pi/tui-runtime/index.js +1 -1
  178. package/dist/native/darwin-arm64/manifest.json +1 -1
  179. package/dist/native/linux-x64/manifest.json +1 -1
  180. package/dist/native/win32-x64/manifest.json +2 -2
  181. package/dist/native/win32-x64/process-guardian.exe +0 -0
  182. package/dist/product-identity.d.ts +2 -2
  183. package/dist/product-identity.js +2 -2
  184. package/dist/product-identity.json +3 -1
  185. package/dist/runtime-payload-inventory.json +3092 -2878
  186. package/dist/ui/components/prompt-input.d.ts +2 -0
  187. package/dist/ui/components/prompt-input.js +5 -1
  188. package/dist/ui/components/text-selection.d.ts +1 -1
  189. package/dist/ui/components/text-selection.js +3 -1
  190. package/dist/ui/components/theme.d.ts +2 -0
  191. package/dist/ui/components/transcript-viewport.d.ts +6 -4
  192. package/dist/ui/components/transcript-viewport.js +94 -16
  193. package/dist/ui/components/value-menu.d.ts +2 -0
  194. package/dist/ui/components/value-menu.js +13 -8
  195. package/dist/ui/settings/declarations.d.ts +38 -14
  196. package/dist/ui/settings/declarations.js +35 -11
  197. package/dist/ui/settings/migrations.js +23 -0
  198. package/docs/architecture/boundaries.md +9 -1
  199. package/docs/architecture/project-structure.md +7 -5
  200. package/docs/architecture/prompt-suggestions.md +14 -10
  201. package/docs/local-worktree-cleanup.md +11 -5
  202. package/docs/openspec-archive-automation.md +6 -5
  203. package/package.json +3 -3
  204. package/dist/contracts/agent-engine/model.d.ts +0 -78
  205. package/dist/contracts/agent-engine/model.js +0 -1
  206. package/dist/contracts/agent-engine/ports.d.ts +0 -18
  207. package/dist/contracts/agent-engine/serialization.d.ts +0 -7
  208. package/dist/contracts/agent-engine/serialization.js +0 -58
  209. package/dist/contracts/agent-engine/validation.d.ts +0 -5
  210. package/dist/contracts/agent-engine/validation.js +0 -128
  211. package/dist/integrations/pi/components/upstream/theme/system-theme.d.ts +0 -61
  212. package/dist/integrations/pi/components/upstream/theme/system-theme.js +0 -709
  213. /package/dist/contracts/{agent-engine/ports.js → owned-ui/session-backend.js} +0 -0
@@ -1,9 +1,17 @@
1
1
  import { assertOwnedUiPromptSuggestionResult, normalizePromptSuggestionCandidate, } from "../../contracts/owned-ui/index.js";
2
- /** Prefetches one inert candidate; owns retirement even when a provider ignores abort. */
2
+ const TRANSIENT_PRESENTATION_REASONS = new Set([
3
+ "not-ready", "not-focused", "autocomplete", "prompt-mode",
4
+ ]);
5
+ const RETRYABLE_OUTCOMES = new Set([
6
+ "empty", "rejected", "provider-failure", "unavailable", "timeout",
7
+ ]);
8
+ /** Prefetches one inert candidate and owns one bounded settlement/retry recovery lifecycle. */
3
9
  export class ContextualPromptSuggestionController {
4
10
  #state = { status: "idle" };
11
+ #lifecycle = null;
5
12
  #request = null;
6
13
  #lastConsidered = "";
14
+ #retiredIdentity = "";
7
15
  #enabled;
8
16
  #disposed = false;
9
17
  #sessionKey = "";
@@ -27,6 +35,7 @@ export class ContextualPromptSuggestionController {
27
35
  }
28
36
  skip(identity, reason) {
29
37
  this.invalidate();
38
+ this.#lastConsidered = decisionIdentityKey(identity);
30
39
  this.#emit(this.#metadata(identity), "skipped", reason);
31
40
  }
32
41
  consider(identity, decision) {
@@ -34,51 +43,43 @@ export class ContextualPromptSuggestionController {
34
43
  if (key === this.#lastConsidered)
35
44
  return;
36
45
  this.#lastConsidered = key;
37
- this.invalidate();
38
- const reason = this.#disposed ? "disposed" : !this.#enabled ? "disabled"
39
- : decision === false ? "ineligible" : decision === true ? null : decision;
46
+ this.#reset(true, true);
47
+ const reason = this.#decisionReason(decision);
40
48
  if (reason !== null) {
41
49
  this.#emit(this.#metadata(identity), "skipped", reason);
42
50
  return;
43
51
  }
44
- let reasoning = "unavailable";
45
- try {
46
- reasoning = this.options.generator.suggestionReasoningPolicy?.() ?? "unavailable";
47
- }
48
- catch { /* Security: isolate diagnostic metadata failure. */ }
49
- const request = {
50
- identity,
51
- metadata: { ...this.#metadata(identity), request: ++this.#requestSequence, reasoning },
52
- abort: new AbortController(), startedAt: this.#now(), terminal: false,
53
- };
54
- this.#request = request;
55
- this.#state = { status: "generating", identity, settled: false };
56
- this.#emit(request.metadata, "started");
57
- request.timer = setTimeout(() => {
58
- if (this.#request !== request || this.#state.status !== "generating")
59
- return;
60
- this.#finish(request, "timeout");
61
- this.#state = { status: "idle" };
62
- this.#request = null;
63
- request.abort.abort();
64
- }, this.#timeoutMs);
65
- request.timer.unref?.();
66
- try {
67
- void this.options.generator.generate({ identity, signal: request.abort.signal })
68
- .then(result => this.#receive(request, result), () => this.#failed(request))
69
- .finally(() => clearTimeout(request.timer));
70
- }
71
- catch {
72
- this.#failed(request);
73
- }
52
+ this.#retiredIdentity = "";
53
+ this.#lifecycle = { identity, settled: false, attempts: 0, retryPending: false, presentationDeferred: false };
54
+ this.#startAttempt("prefetch");
74
55
  }
75
- settle(identity) {
76
- if (this.#disposed || !this.#enabled || this.#state.status === "idle")
56
+ /** Settles an existing prefetch or starts the first request when that eligible prefetch was missed. */
57
+ settle(identity, decision = null) {
58
+ if (this.#disposed || !this.#enabled || identityKey(identity) === this.#retiredIdentity)
77
59
  return;
78
- if (!samePromptSuggestionIdentity(this.#state.identity, identity)) {
60
+ const reason = this.#decisionReason(decision);
61
+ const lifecycle = this.#lifecycle;
62
+ if (lifecycle !== null && !samePromptSuggestionIdentity(lifecycle.identity, identity)) {
79
63
  if (this.#request)
80
64
  this.#finish(this.#request, "stale-result", "stale-identity");
81
- this.invalidate();
65
+ this.#reset(true, true);
66
+ }
67
+ if (reason !== null) {
68
+ if (this.#lifecycle !== null)
69
+ this.#reset(true, true);
70
+ else
71
+ this.#emit(this.#metadata(identity), "skipped", reason);
72
+ return;
73
+ }
74
+ if (this.#lifecycle === null) {
75
+ this.#retiredIdentity = "";
76
+ this.#lifecycle = { identity, settled: true, attempts: 0, retryPending: false, presentationDeferred: false };
77
+ this.#startAttempt("settlement");
78
+ return;
79
+ }
80
+ this.#lifecycle.settled = true;
81
+ if (this.#lifecycle.retryPending) {
82
+ this.#startAttempt("retry");
82
83
  return;
83
84
  }
84
85
  if (this.#state.status === "generating")
@@ -86,23 +87,23 @@ export class ContextualPromptSuggestionController {
86
87
  else if (this.#state.status === "prepared" && this.#request)
87
88
  this.#show(this.#request, this.#state.text);
88
89
  }
89
- accept() { this.#invalidate(false); }
90
- invalidate() { this.#invalidate(true); }
91
- /** Retires only a generating request; a prepared or available suggestion survives the draft edit. */
90
+ accept() { this.#reset(false, true); }
91
+ invalidate() { this.#reset(true, true); }
92
+ /** Retires generating or scheduled recovery; a prepared or available suggestion survives a draft edit. */
92
93
  abortPending() {
93
- if (this.#state.status !== "generating")
94
- return;
95
- const request = this.#request;
96
- this.#request = null;
97
- this.#state = { status: "idle" };
98
- if (request === null)
94
+ if (this.#state.status !== "generating" && !(this.#state.status === "idle" && this.#lifecycle?.retryPending))
99
95
  return;
100
- this.#finish(request, "cancelled");
101
- request.abort.abort();
96
+ this.#reset(false, true);
102
97
  }
103
- /** Reasserts retained ghost text after an editor mutation makes the prompt eligible again. */
98
+ /** Reasserts retained ghost text or retries a deferred presentation when the editor is eligible. */
104
99
  restoreAvailable() {
105
- if (this.#disposed || !this.#enabled || this.#state.status !== "available")
100
+ if (this.#disposed || !this.#enabled)
101
+ return;
102
+ if (this.#state.status === "prepared" && this.#lifecycle?.settled && this.#request) {
103
+ this.#show(this.#request, this.#state.text);
104
+ return;
105
+ }
106
+ if (this.#state.status !== "available")
106
107
  return;
107
108
  const reason = this.options.surface.presentationBlockReason?.(this.#state.identity)
108
109
  ?? (this.options.surface.canPresent(this.#state.identity) ? null : "presentation-unavailable");
@@ -114,16 +115,64 @@ export class ContextualPromptSuggestionController {
114
115
  this.#disposed = true;
115
116
  this.invalidate();
116
117
  this.#lastConsidered = "";
118
+ this.#retiredIdentity = "";
117
119
  this.#sessionKey = "";
118
120
  }
119
- #invalidate(clearSurface) {
121
+ #decisionReason(decision) {
122
+ return this.#disposed ? "disposed" : !this.#enabled ? "disabled"
123
+ : decision === false ? "ineligible" : decision === true ? null : decision;
124
+ }
125
+ #startAttempt(trigger) {
126
+ const lifecycle = this.#lifecycle;
127
+ if (lifecycle === null || this.#request !== null || lifecycle.attempts >= 2)
128
+ return;
129
+ lifecycle.retryPending = false;
130
+ lifecycle.presentationDeferred = false;
131
+ const attempt = ++lifecycle.attempts;
132
+ let reasoning = "unavailable";
133
+ try {
134
+ reasoning = this.options.generator.suggestionReasoningPolicy?.() ?? "unavailable";
135
+ }
136
+ catch { /* Security: isolate diagnostic metadata failure. */ }
137
+ const request = {
138
+ identity: lifecycle.identity,
139
+ metadata: { ...this.#metadata(lifecycle.identity), request: ++this.#requestSequence, reasoning, attempt, trigger },
140
+ abort: new AbortController(), startedAt: this.#now(), terminal: false,
141
+ };
142
+ this.#request = request;
143
+ this.#state = { status: "generating", identity: lifecycle.identity, settled: lifecycle.settled };
144
+ this.#emit(request.metadata, "started");
145
+ request.timer = setTimeout(() => {
146
+ if (this.#request !== request || this.#state.status !== "generating")
147
+ return;
148
+ this.#finish(request, "timeout");
149
+ this.#request = null;
150
+ this.#state = { status: "idle" };
151
+ request.abort.abort();
152
+ this.#completeNoCandidate(request, "timeout");
153
+ }, this.#timeoutMs);
154
+ request.timer.unref?.();
155
+ try {
156
+ void this.options.generator.generate({ identity: lifecycle.identity, signal: request.abort.signal })
157
+ .then(result => this.#receive(request, result), () => this.#failed(request))
158
+ .finally(() => clearTimeout(request.timer));
159
+ }
160
+ catch {
161
+ this.#failed(request);
162
+ }
163
+ }
164
+ #reset(clearSurface, retire) {
120
165
  const hadVisibleSuggestion = this.#state.status === "available";
166
+ const identity = this.#lifecycle?.identity ?? (this.#state.status === "idle" ? null : this.#state.identity);
121
167
  const request = this.#request;
122
168
  if (request)
123
169
  this.#finish(request, "cancelled");
124
170
  this.#request = null;
171
+ this.#lifecycle = null;
125
172
  this.#state = { status: "idle" };
126
173
  request?.abort.abort();
174
+ if (retire && identity !== null)
175
+ this.#retiredIdentity = identityKey(identity);
127
176
  if (clearSurface && hadVisibleSuggestion) {
128
177
  this.options.surface.clear();
129
178
  this.options.surface.requestRender();
@@ -137,6 +186,7 @@ export class ContextualPromptSuggestionController {
137
186
  this.#finish(request, "provider-failure");
138
187
  this.#request = null;
139
188
  this.#state = { status: "idle" };
189
+ this.#completeNoCandidate(request, "provider-failure");
140
190
  }
141
191
  #receive(request, result) {
142
192
  if (this.#disposed || this.#request !== request || request.terminal || this.#state.status !== "generating") {
@@ -148,41 +198,76 @@ export class ContextualPromptSuggestionController {
148
198
  }
149
199
  catch {
150
200
  this.#finish(request, "rejected");
151
- this.invalidate();
201
+ this.#request = null;
202
+ this.#state = { status: "idle" };
203
+ this.#completeNoCandidate(request, "rejected");
152
204
  return;
153
205
  }
154
206
  if (!samePromptSuggestionIdentity(request.identity, result.identity)) {
155
207
  this.#finish(request, "stale-result", "stale-identity");
156
- this.invalidate();
208
+ this.#reset(true, true);
157
209
  return;
158
210
  }
159
211
  if (result.outcome !== "candidate") {
160
212
  this.#finish(request, result.outcome);
161
- this.invalidate();
213
+ this.#request = null;
214
+ this.#state = { status: "idle" };
215
+ if (RETRYABLE_OUTCOMES.has(result.outcome))
216
+ this.#completeNoCandidate(request, result.outcome);
217
+ else {
218
+ this.#retiredIdentity = identityKey(request.identity);
219
+ this.#lifecycle = null;
220
+ }
162
221
  return;
163
222
  }
164
223
  const text = normalizePromptSuggestionCandidate(result.text);
165
224
  if (text === null) {
166
225
  this.#finish(request, "rejected");
167
- this.invalidate();
226
+ this.#request = null;
227
+ this.#state = { status: "idle" };
228
+ this.#completeNoCandidate(request, "rejected");
168
229
  return;
169
230
  }
170
231
  clearTimeout(request.timer);
171
- if (this.#state.settled)
232
+ if (this.#lifecycle?.settled)
172
233
  this.#show(request, text);
173
234
  else
174
235
  this.#state = { status: "prepared", identity: request.identity, text };
175
236
  }
237
+ #completeNoCandidate(request, outcome) {
238
+ const lifecycle = this.#lifecycle;
239
+ if (lifecycle === null || !samePromptSuggestionIdentity(lifecycle.identity, request.identity))
240
+ return;
241
+ if (lifecycle.attempts >= 2 || !RETRYABLE_OUTCOMES.has(outcome)) {
242
+ this.#emit({ ...request.metadata, elapsedMs: Math.max(0, this.#now() - request.startedAt) }, "retry-exhausted");
243
+ this.#retiredIdentity = identityKey(request.identity);
244
+ this.#lifecycle = null;
245
+ return;
246
+ }
247
+ lifecycle.retryPending = true;
248
+ if (lifecycle.settled)
249
+ this.#startAttempt("retry");
250
+ }
176
251
  #show(request, text) {
177
252
  const reason = this.options.surface.presentationBlockReason?.(request.identity)
178
253
  ?? (this.options.surface.canPresent(request.identity) ? null : "presentation-unavailable");
254
+ if (reason !== null && TRANSIENT_PRESENTATION_REASONS.has(reason)) {
255
+ this.#state = { status: "prepared", identity: request.identity, text };
256
+ if (this.#lifecycle !== null && !this.#lifecycle.presentationDeferred) {
257
+ this.#lifecycle.presentationDeferred = true;
258
+ this.#emit({ ...request.metadata, elapsedMs: Math.max(0, this.#now() - request.startedAt) }, "presentation-deferred", reason);
259
+ }
260
+ return;
261
+ }
179
262
  if (reason !== null || !this.options.surface.present(text)) {
180
263
  this.#finish(request, "presentation-blocked", reason ?? "presentation-unavailable");
181
- this.invalidate();
264
+ this.#reset(true, true);
182
265
  return;
183
266
  }
184
267
  this.#state = { status: "available", identity: request.identity, text };
185
268
  this.#finish(request, "displayed");
269
+ if (this.#lifecycle !== null)
270
+ this.#lifecycle.presentationDeferred = false;
186
271
  this.options.surface.requestRender();
187
272
  }
188
273
  #finish(request, event, reason) {
@@ -227,3 +312,8 @@ export function samePromptSuggestionIdentity(left, right) {
227
312
  function identityKey(identity) {
228
313
  return `${identity.sessionId}\0${identity.sessionGeneration}\0${identity.runSequence}\0${identity.responseSequence}\0${identity.model.providerId}\0${identity.model.modelId}`;
229
314
  }
315
+ function decisionIdentityKey(identity) {
316
+ return identity.model === null
317
+ ? `${identity.sessionId}\0${identity.sessionGeneration}\0${identity.runSequence}\0${identity.responseSequence}\0\0`
318
+ : identityKey(identity);
319
+ }
@@ -15,6 +15,8 @@ export interface QuitOutroPlayback {
15
15
  sleep?(ms: number): Promise<void>;
16
16
  /** Plan seed; defaults to a time- and geometry-derived value. */
17
17
  readonly seed?: number;
18
+ /** Active bare-A1 canvas; omitted preserves transparent playback bytes. */
19
+ readonly canvasBackgroundAnsi?: string;
18
20
  }
19
21
  export declare const QUIT_OUTRO_MIN_MS = 300;
20
22
  export declare const QUIT_OUTRO_MAX_MS = 2000;
@@ -29,7 +31,7 @@ export declare function clampQuitOutroDuration(durationMs: number): number;
29
31
  */
30
32
  export declare function captureQuitOutroFrame(presented: readonly string[], columns: number, rows: number): QuitOutroFrame | null;
31
33
  /** The clear-and-repaint block that seeds the animation surface with the captured frame. */
32
- export declare function createQuitOutroSurfaceFrame(frame: QuitOutroFrame): string;
34
+ export declare function createQuitOutroSurfaceFrame(frame: QuitOutroFrame, canvasBackgroundAnsi?: string): string;
33
35
  /**
34
36
  * Plays the effect over the frame. Resolves true when the plan was played to
35
37
  * completion or abandoned at its guard, false when there was nothing to play.
@@ -6,6 +6,7 @@
6
6
  * terminal cannot delay restoration past the configured clamp.
7
7
  */
8
8
  import { displayWidth, truncateToWidth } from "../../ui/components/index.js";
9
+ import { rebaseTerminalDefaultBackground } from "../../integrations/pi/tui-runtime/index.js";
9
10
  import { createQuitOutroPlan } from "./quit-outro-effects.js";
10
11
  export const QUIT_OUTRO_MIN_MS = 300;
11
12
  export const QUIT_OUTRO_MAX_MS = 2000;
@@ -44,14 +45,25 @@ export function captureQuitOutroFrame(presented, columns, rows) {
44
45
  return { lines, columns: width, rows: height, rowWidths };
45
46
  }
46
47
  /** The clear-and-repaint block that seeds the animation surface with the captured frame. */
47
- export function createQuitOutroSurfaceFrame(frame) {
48
- let output = `${SYNC_BEGIN}${HIDE_CURSOR}${CLEAR_SCREEN}${HOME}${RESET}`;
48
+ export function createQuitOutroSurfaceFrame(frame, canvasBackgroundAnsi) {
49
+ if (canvasBackgroundAnsi === undefined) {
50
+ let output = `${SYNC_BEGIN}${HIDE_CURSOR}${CLEAR_SCREEN}${HOME}${RESET}`;
51
+ for (let row = 0; row < frame.rows; row++) {
52
+ const line = frame.lines[row] ?? "";
53
+ if (frame.rowWidths[row] > 0)
54
+ output += `${cursorAt(row, 0)}${line}${RESET}`;
55
+ }
56
+ return `${output}${SYNC_END}`;
57
+ }
58
+ let output = `${SYNC_BEGIN}${HIDE_CURSOR}${RESET}${canvasBackgroundAnsi}${CLEAR_SCREEN}${HOME}`;
49
59
  for (let row = 0; row < frame.rows; row++) {
50
60
  const line = frame.lines[row] ?? "";
51
- if (frame.rowWidths[row] > 0)
52
- output += `${cursorAt(row, 0)}${line}${RESET}`;
61
+ if (frame.rowWidths[row] > 0) {
62
+ output += `${cursorAt(row, 0)}${canvasBackgroundAnsi}`
63
+ + `${rebaseTerminalDefaultBackground(line, canvasBackgroundAnsi)}${RESET}${canvasBackgroundAnsi}`;
64
+ }
53
65
  }
54
- return `${output}${SYNC_END}`;
66
+ return `${output}${RESET}${SYNC_END}`;
55
67
  }
56
68
  /**
57
69
  * Plays the effect over the frame. Resolves true when the plan was played to
@@ -69,20 +81,23 @@ export async function playQuitOutro(frame, effect, durationMs, playback) {
69
81
  let sparkleIndex = 0;
70
82
  let clearIndex = 0;
71
83
  let ticks = 0;
72
- playback.write(createQuitOutroSurfaceFrame(frame));
84
+ const canvas = playback.canvasBackgroundAnsi;
85
+ playback.write(createQuitOutroSurfaceFrame(frame, canvas));
73
86
  const startedAt = now();
74
87
  for (;;) {
75
88
  ticks += 1;
76
89
  const elapsed = now() - startedAt;
77
90
  const progress = Math.min(1, elapsed / duration);
78
- let output = `${SYNC_BEGIN}${RESET}`;
91
+ let output = canvas === undefined ? `${SYNC_BEGIN}${RESET}` : `${SYNC_BEGIN}${RESET}${canvas}`;
79
92
  while (sparkleIndex < plan.sparkles.length && plan.sparkles[sparkleIndex].start <= progress) {
80
93
  const cell = plan.sparkles[sparkleIndex++];
81
94
  output += `${cursorAt(cell.row, cell.col)}${cell.color}${cell.glyph}`;
82
95
  }
83
96
  while (clearIndex < plan.clears.length && plan.clears[clearIndex].end <= progress) {
84
97
  const cell = plan.clears[clearIndex++];
85
- output += `${cursorAt(cell.row, cell.col)}${RESET} `;
98
+ output += canvas === undefined
99
+ ? `${cursorAt(cell.row, cell.col)}${RESET} `
100
+ : `${cursorAt(cell.row, cell.col)}${RESET}${canvas} `;
86
101
  }
87
102
  const finished = clearIndex >= plan.clears.length || progress >= 1
88
103
  || elapsed > duration + QUIT_OUTRO_GUARD_MS || ticks >= QUIT_OUTRO_MAX_TICKS;
@@ -1,3 +1,4 @@
1
+ import { HelperPool } from "./helper-pool.js";
1
2
  import type { SelectionCopySnapshot } from "../../ui/components/selection-copy.js";
2
3
  import { type CopyResult } from "./response-copy-protocol.js";
3
4
  export interface ResponseCopyJob {
@@ -8,7 +9,7 @@ export interface ResponseCopyJob {
8
9
  }
9
10
  export type CopyPhaseObserver = (phase: "extracted" | "encoded" | "submitting", bytes: number, transport: "native" | "terminal" | "injected") => void;
10
11
  export type ResponseCopyExecutor = (snapshot: SelectionCopySnapshot, phase: CopyPhaseObserver) => ResponseCopyJob;
11
- /** The production executor also owns a spare helper; the owner warms it at start and disposes it at shutdown. */
12
+ /** The production executor also holds a spare helper; the owner warms it at start and disposes it at shutdown unless the pool is shared. */
12
13
  export interface OwnedResponseCopyExecutor extends ResponseCopyExecutor {
13
14
  warm(): void;
14
15
  dispose(): void;
@@ -36,4 +37,8 @@ export declare function createResponseCopyExecutor(options?: {
36
37
  readonly helper?: URL;
37
38
  /** Idle bound for the spare helper; production keeps the default. */
38
39
  readonly spareIdleMs?: number;
40
+ /** Process-wide spare pool shared across sessions; the executor warms it but never disposes it. */
41
+ readonly pool?: HelperPool;
39
42
  }): OwnedResponseCopyExecutor;
43
+ /** A spare-of-one pool of copy helpers; `createResponseCopyExecutor` takes its child and warms the next one after each copy. */
44
+ export declare function createCopyHelperPool(helper?: URL, idleMs?: number): HelperPool;
@@ -23,7 +23,8 @@ export function hasAsyncClipboardOutput(platform = process.platform, stdout = pr
23
23
  }
24
24
  /** Isolates preparation and native clipboard access; only the owner may submit terminal controls. */
25
25
  export function createResponseCopyExecutor(options = {}) {
26
- const pool = new HelperPool({ fork: () => forkCopyHelper(options.helper), stop: stopCopyHelper, ...(options.spareIdleMs === undefined ? {} : { idleMs: options.spareIdleMs }) });
26
+ const pool = options.pool ?? createCopyHelperPool(options.helper, options.spareIdleMs);
27
+ const ownsPool = options.pool === undefined;
27
28
  const execute = (snapshot, phase) => {
28
29
  const controller = new AbortController();
29
30
  let active;
@@ -70,10 +71,15 @@ export function createResponseCopyExecutor(options = {}) {
70
71
  // Rationale: `Object.assign` would copy the getter's value once; the accessor must read the pool each time.
71
72
  return Object.defineProperties(execute, {
72
73
  warm: { value: () => pool.warm() },
73
- dispose: { value: () => pool.dispose() },
74
+ dispose: { value: () => { if (ownsPool)
75
+ pool.dispose(); } },
74
76
  warmed: { get: () => pool.warmed },
75
77
  });
76
78
  }
79
+ /** A spare-of-one pool of copy helpers; `createResponseCopyExecutor` takes its child and warms the next one after each copy. */
80
+ export function createCopyHelperPool(helper, idleMs) {
81
+ return new HelperPool({ fork: () => forkCopyHelper(helper), stop: stopCopyHelper, ...(idleMs === undefined ? {} : { idleMs }) });
82
+ }
77
83
  /** Forks one copy helper: bounded IPC only, no clipboard payload in argv or temp files, no inherited terminal descriptors. */
78
84
  function forkCopyHelper(helper) {
79
85
  const source = new URL(import.meta.url).pathname.endsWith(".ts");
@@ -1,23 +1,21 @@
1
1
  import { ImageAttachmentError } from "../../contracts/owned-ui/index.js";
2
- import type { OwnedUiPromptSuggestionGeneratorPort, OwnedUiSessionViewModel, OwnedUiViewportSettings, OwnedUiViewportSettingsPort, OwnedUiQuitOutroSettingsPort, SuggestionDecision, SuggestionDiagnosticObserver } from "../../contracts/owned-ui/index.js";
2
+ import type { OwnedUiBackgroundSettingsPort, OwnedUiPromptSuggestionGeneratorPort, OwnedUiSessionBackend, OwnedUiSessionPresenters, OwnedUiSessionViewModel, OwnedUiTranscriptRendererPort, OwnedUiWorkflowMessage, OwnedUiWorkflowResult, OwnedUiViewportSettings, OwnedUiViewportSettingsPort, OwnedUiQuitOutroSettingsPort, SuggestionDecision, SuggestionDiagnosticObserver } from "../../contracts/owned-ui/index.js";
3
3
  import type { PiTuiPointerSurface } from "../../integrations/pi/tui-runtime/contracts.js";
4
4
  import type { UiRouteHost, UiRouteInput } from "../../ui/apps/contracts.js";
5
5
  import type { TranscriptViewportFrame, TranscriptViewportFrameDescriptor } from "../../ui/components/transcript-viewport.js";
6
- import type { PiEngineAdapter } from "../../integrations/pi/engine/adapter.js";
7
- import type { PiWorkflowMessage, PiWorkflowResult } from "../../integrations/pi/engine/workflows.js";
8
6
  import type { PiShellLazySelectorLoader } from "../../integrations/pi/components/lazy-selectors.js";
9
7
  import { type PiShellHotkeysPresentation } from "../../integrations/pi/components/shell-presenters-info.js";
10
- import { type PiShellClipboardContent, type PiShellComponentPort, type PiShellEditorPort, type PiShellExtensionRendererResolver, type PiShellHeaderOptions, type PiShellHeaderPort, type PiShellImageAssetResolver, type PiShellLoadedResourcesPort, type PiShellResourceEntry, type PiShellTranscriptComponentPort } from "../../integrations/pi/components/shell-shared-facade.js";
8
+ import { type PiShellClipboardContent, type PiShellComponentPort, type PiKeybindingsHost, type PiShellEditorPort, type PiShellHeaderOptions, type PiShellHeaderPort, type PiShellImageAssetResolver, type PiShellLoadedResourcesPort, type PiShellResourceEntry, type PiShellTranscriptComponentPort } from "../../integrations/pi/components/shell-shared-facade.js";
11
9
  import { type PiTuiInputCoordinationScheduler, type PiTuiInputSurfaceKind } from "../../integrations/pi/tui-runtime/input-presentation-coordinator.js";
12
10
  import type { PiTuiComponentPort, PiTuiInputDiagnosticsEvent, PiTuiLayoutNode, PiTuiTerminalPort } from "../../integrations/pi/tui-runtime/contracts.js";
13
11
  import { type PreparedPrompt } from "./prompt-chips.js";
14
12
  import type { PastePreparationClientOptions } from "./paste-preparation-client.js";
13
+ import type { OwnedUiClipboardServices } from "./clipboard-services.js";
15
14
  import { type SessionViewportInputResult } from "./session-viewport-controller.js";
16
15
  import type { ResponseCopyExecutor } from "./response-copy-transport.js";
17
16
  import type { ResponseCopyEvent } from "./response-copy-protocol.js";
18
17
  import type { PasteEvent, PasteSource } from "./paste-protocol.js";
19
18
  import type { StreamPresentationScheduler } from "./stream-presentation-coalescer.js";
20
- export type OwnedUiBackendPort = PiEngineAdapter;
21
19
  export type OwnedUiTerminalPort = PiTuiTerminalPort;
22
20
  type OwnedUiStartupOptions = PiShellHeaderOptions;
23
21
  export interface OwnedUiClipboardPort {
@@ -30,7 +28,7 @@ export interface OwnedUiClipboardPort {
30
28
  }
31
29
  /** The engine session the shell presents and the composition's decisions about it. */
32
30
  export interface OwnedUiShellEngineOptions {
33
- readonly backend: OwnedUiBackendPort;
31
+ readonly backend: OwnedUiSessionBackend;
34
32
  readonly cwd: string;
35
33
  /**
36
34
  * Declared A1-owned routes. A route this host claims resolves to its app;
@@ -52,6 +50,8 @@ export interface OwnedUiShellPresentationOptions {
52
50
  readonly startup?: OwnedUiStartupOptions;
53
51
  /** Live profile-local settings, supplied only to the bare-A1 composition. */
54
52
  readonly viewportSettings?: OwnedUiViewportSettingsPort;
53
+ /** Live fullscreen canvas choice, supplied only to the bare-A1 composition. */
54
+ readonly backgroundSettings?: OwnedUiBackgroundSettingsPort;
55
55
  /** Deterministic scheduling seam for presentation-cadence tests. */
56
56
  readonly stream?: {
57
57
  readonly intervalMs?: number;
@@ -130,9 +130,17 @@ export interface OwnedUiShellSkillsOptions {
130
130
  readonly presentation: () => "collapse" | "expand";
131
131
  readonly onChange: (listener: () => void) => () => void;
132
132
  }
133
+ /** Process-wide services composition creates once and every session shell borrows; absent, a shell keeps private ones. */
134
+ export interface OwnedUiShellSharedServices {
135
+ readonly clipboard?: OwnedUiClipboardServices;
136
+ /** Must match the shell's layout: the owned-input profile for the custom viewport, Pi's otherwise. */
137
+ readonly keybindings?: PiKeybindingsHost;
138
+ }
133
139
  /** What composes an owned session shell, grouped by the collaborator that provides each part. */
134
140
  export interface OwnedUiSessionShellOptions {
135
141
  readonly engine: OwnedUiShellEngineOptions;
142
+ /** Opens the selectors and resolves the transcript renderers whose inputs are engine objects. */
143
+ readonly presenters: OwnedUiSessionPresenters;
136
144
  readonly presentation?: OwnedUiShellPresentationOptions;
137
145
  readonly history?: OwnedUiShellHistoryOptions;
138
146
  readonly suggestions?: OwnedUiShellSuggestionOptions;
@@ -141,6 +149,7 @@ export interface OwnedUiSessionShellOptions {
141
149
  /** Supplied only to the bare-A1 composition; absent keeps the pinned per-skill command list. */
142
150
  readonly skills?: OwnedUiShellSkillsOptions;
143
151
  readonly diagnostics?: OwnedUiShellDiagnosticOptions;
152
+ readonly shared?: OwnedUiShellSharedServices;
144
153
  }
145
154
  /** Composes backend session state into the owned transcript, viewport, editor, and dock presentation. */
146
155
  export declare class OwnedUiSessionShellRoot implements PiTuiComponentPort {
@@ -172,14 +181,16 @@ export declare class OwnedUiSessionShellRoot implements PiTuiComponentPort {
172
181
  readonly onEditorChange?: (text: string) => void;
173
182
  readonly onPromptSuggestionAccepted?: (text: string) => void;
174
183
  readonly onInputSurfaceChanged?: () => void;
184
+ readonly onPromptSuggestionEligibilityChanged?: () => void;
175
185
  readonly onCopyText?: (text: string) => void;
176
186
  readonly readClipboardContent?: (signal?: AbortSignal) => Promise<PiShellClipboardContent | null>;
177
187
  readonly captureClipboardPaste?: () => PasteSource;
178
188
  readonly pasteDiagnostics?: (event: PasteEvent) => void;
179
189
  readonly pastePreparation?: Omit<PastePreparationClientOptions, "onEvent">;
190
+ readonly keybindings?: PiKeybindingsHost;
180
191
  readonly promptImageLimit?: () => number;
181
192
  readonly skillsPresentation?: () => "collapse" | "expand";
182
- }, startup?: PiShellHeaderOptions, agentDir?: string, extensionRenderers?: PiShellExtensionRendererResolver, sessionLayout?: "pinned" | "custom-viewport", imageAssets?: PiShellImageAssetResolver);
193
+ }, startup?: PiShellHeaderOptions, agentDir?: string, extensionRenderers?: OwnedUiTranscriptRendererPort, sessionLayout?: "pinned" | "custom-viewport", imageAssets?: PiShellImageAssetResolver);
183
194
  setEditorPaddingX(padding: number): void;
184
195
  setAutocompleteMaxVisible(maxVisible: number): void;
185
196
  setOutputPad(padding: 0 | 1): void;
@@ -245,7 +256,7 @@ export declare class OwnedUiSessionShellRoot implements PiTuiComponentPort {
245
256
  maxScroll: number;
246
257
  cause: "initial" | "steady" | "dock-input" | "follow-shift" | "detached" | "geometry-change" | null;
247
258
  };
248
- /** Visible non-selectable Steering, alignment, and Working rows, for rendering evidence. */
259
+ /** Visible non-persistent Steering, alignment, and Working rows, for rendering evidence. */
249
260
  viewportTransientTailRowCount(): number;
250
261
  hasActiveSelection(): boolean;
251
262
  setViewportConfig(config: OwnedUiViewportSettings): void;
@@ -265,8 +276,8 @@ export declare class OwnedUiSessionShellRoot implements PiTuiComponentPort {
265
276
  transcriptComponent(id: string): PiShellTranscriptComponentPort | undefined;
266
277
  exitTranscript(width: number): string;
267
278
  appendWorkflowStatus(message: string): void;
268
- appendWorkflowMessage(message: PiWorkflowMessage, errorCode?: ImageAttachmentError["code"]): void;
269
- appendWorkflowResult(result: PiWorkflowResult, errorCode?: ImageAttachmentError["code"]): void;
279
+ appendWorkflowMessage(message: OwnedUiWorkflowMessage, errorCode?: ImageAttachmentError["code"]): void;
280
+ appendWorkflowResult(result: OwnedUiWorkflowResult, errorCode?: ImageAttachmentError["code"]): void;
270
281
  toggleThinkingVisibility(): void;
271
282
  get toolsExpanded(): boolean;
272
283
  setToolsExpanded(expanded: boolean): void;
@@ -295,5 +306,5 @@ export declare class OwnedUiSessionShellRoot implements PiTuiComponentPort {
295
306
  setFocused(focused: boolean): void;
296
307
  dispose(): void;
297
308
  }
298
- export declare function shellResourceEntries(backend: OwnedUiBackendPort): readonly PiShellResourceEntry[];
309
+ export declare function shellResourceEntries(backend: OwnedUiSessionBackend): readonly PiShellResourceEntry[];
299
310
  export {};