@timurproko/a1 0.2.7-dev.1255 → 0.2.7-dev.1264

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 (78) hide show
  1. package/dist/app/session-shell/prompt-submission.d.ts +1 -1
  2. package/dist/app/session-shell/prompt-submission.js +9 -9
  3. package/dist/app/session-shell/resource-labels.d.ts +2 -0
  4. package/dist/app/session-shell/resource-labels.js +158 -0
  5. package/dist/app/session-shell/session-prompt-history.d.ts +29 -0
  6. package/dist/app/session-shell/session-prompt-history.js +80 -0
  7. package/dist/app/session-shell/session-selectors.d.ts +46 -0
  8. package/dist/app/session-shell/session-selectors.js +269 -0
  9. package/dist/app/session-shell/session-shell-root.d.ts +6 -28
  10. package/dist/app/session-shell/session-shell-root.js +26 -220
  11. package/dist/app/session-shell/session-shell.d.ts +3 -23
  12. package/dist/app/session-shell/session-shell.js +54 -365
  13. package/dist/app/session-shell/session-viewport-controller.d.ts +2 -10
  14. package/dist/app/session-shell/session-viewport-controller.js +40 -318
  15. package/dist/app/session-shell/settings-bindings.d.ts +1 -1
  16. package/dist/app/session-shell/settings-bindings.js +2 -2
  17. package/dist/app/session-shell/viewport-pointer.d.ts +83 -0
  18. package/dist/app/session-shell/viewport-pointer.js +361 -0
  19. package/dist/composition/owned-ui.js +63 -59
  20. package/dist/contracts/owned-ui/index.d.ts +1 -1
  21. package/dist/contracts/owned-ui/index.js +1 -1
  22. package/dist/contracts/owned-ui/validation.d.ts +1 -11
  23. package/dist/contracts/owned-ui/validation.js +8 -104
  24. package/dist/contracts/presentation/index.d.ts +1 -1
  25. package/dist/contracts/presentation/terminal.d.ts +0 -6
  26. package/dist/features/owned-ui/settings-app.js +13 -208
  27. package/dist/features/owned-ui/settings-model-dialog.d.ts +41 -0
  28. package/dist/features/owned-ui/settings-model-dialog.js +194 -0
  29. package/dist/foundation/release/automatic-update.js +1 -8
  30. package/dist/foundation/release/dependency-layer.js +3 -3
  31. package/dist/foundation/release/latest-release.js +1 -1
  32. package/dist/foundation/release/managed-path.d.ts +10 -0
  33. package/dist/foundation/release/managed-path.js +26 -0
  34. package/dist/foundation/release/release-gc.js +6 -8
  35. package/dist/foundation/release/restart-certification.js +3 -4
  36. package/dist/foundation/release/update-activation.js +1 -1
  37. package/dist/foundation/release/update-execution-lease.js +1 -7
  38. package/dist/foundation/release/update-installer.d.ts +45 -0
  39. package/dist/foundation/release/update-installer.js +57 -0
  40. package/dist/foundation/release/update-recovery.js +2 -9
  41. package/dist/foundation/release/update.d.ts +4 -23
  42. package/dist/foundation/release/update.js +160 -179
  43. package/dist/integrations/pi/components/bracketed-paste.d.ts +33 -0
  44. package/dist/integrations/pi/components/bracketed-paste.js +123 -0
  45. package/dist/integrations/pi/components/owned-editor-ux.js +46 -140
  46. package/dist/integrations/pi/engine/adapter.d.ts +1 -8
  47. package/dist/integrations/pi/engine/adapter.js +6 -49
  48. package/dist/integrations/pi/engine/host.js +1 -1
  49. package/dist/integrations/pi/engine/repository-metadata.d.ts +49 -0
  50. package/dist/integrations/pi/engine/repository-metadata.js +189 -0
  51. package/dist/integrations/pi/engine/session-runtime.d.ts +6 -12
  52. package/dist/integrations/pi/engine/session-runtime.js +21 -178
  53. package/dist/integrations/pi/engine/view-state.d.ts +21 -2
  54. package/dist/integrations/pi/engine/view-state.js +129 -1
  55. package/dist/integrations/pi/engine/workflow-runner.d.ts +0 -1
  56. package/dist/integrations/pi/engine/workflow-runner.js +254 -365
  57. package/dist/integrations/pi/engine/workflow-share.d.ts +9 -0
  58. package/dist/integrations/pi/engine/workflow-share.js +168 -0
  59. package/dist/integrations/pi/engine/workflow-support.d.ts +0 -14
  60. package/dist/integrations/pi/engine/workflow-support.js +0 -47
  61. package/dist/integrations/pi/tui-runtime/adapter.d.ts +9 -19
  62. package/dist/integrations/pi/tui-runtime/adapter.js +35 -144
  63. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +4 -4
  64. package/dist/integrations/pi/tui-runtime/index.d.ts +0 -1
  65. package/dist/integrations/pi/tui-runtime/overlay-geometry.d.ts +2 -2
  66. package/dist/integrations/pi/tui-runtime/presentation-adapter.d.ts +2 -2
  67. package/dist/ui/components/transcript-viewport-frame.d.ts +120 -0
  68. package/dist/ui/components/transcript-viewport-frame.js +314 -0
  69. package/dist/ui/components/transcript-viewport-types.d.ts +147 -0
  70. package/dist/ui/components/transcript-viewport.d.ts +2 -147
  71. package/dist/ui/components/transcript-viewport.js +87 -315
  72. package/package.json +3 -3
  73. package/dist/integrations/pi/engine/diagnostics-state.d.ts +0 -9
  74. package/dist/integrations/pi/engine/diagnostics-state.js +0 -34
  75. package/dist/integrations/pi/engine/usage-view.d.ts +0 -4
  76. package/dist/integrations/pi/engine/usage-view.js +0 -56
  77. package/dist/integrations/pi/tui-runtime/contracts.d.ts +0 -22
  78. /package/dist/{integrations/pi/tui-runtime/contracts.js → ui/components/transcript-viewport-types.js} +0 -0
@@ -1,14 +1,14 @@
1
- import type { OwnedUiShellComponents, OwnedUiShellHotkeysPresentation, OwnedUiShellClipboardContent, OwnedUiShellComponentPort, OwnedUiShellEditorPort, OwnedUiShellHeaderOptions, OwnedUiShellHeaderPort, OwnedUiShellHistoryEditor, OwnedUiShellImageAssetResolver, OwnedUiShellKeybindingsHost, OwnedUiShellLoadedResourcesPort, OwnedUiShellResourceEntry } from "../../contracts/owned-ui/index.js";
2
- import type { TerminalComponentPort, TerminalInputCoordinationScheduler, TerminalInputDiagnosticsEvent, TerminalInputSurfaceKind, TerminalLayoutNode, TerminalPointerSurface, TerminalPort } from "../../contracts/presentation/index.js";
1
+ import type { OwnedUiShellComponents, OwnedUiShellHotkeysPresentation, OwnedUiShellClipboardContent, OwnedUiShellComponentPort, OwnedUiShellEditorPort, OwnedUiShellHeaderOptions, OwnedUiShellHeaderPort, OwnedUiShellHistoryEditor, OwnedUiShellImageAssetResolver, OwnedUiShellKeybindingsHost, OwnedUiShellLoadedResourcesPort } from "../../contracts/owned-ui/index.js";
2
+ import type { TerminalComponentPort, TerminalInputCoordinationScheduler, TerminalInputDiagnosticsEvent, TerminalInputSurfaceKind, TerminalLayoutNode, TerminalPort } from "../../contracts/presentation/index.js";
3
3
  import type { ShellPresentationPorts, ThemeSource } from "../../contracts/presentation/index.js";
4
4
  import type { OwnedUiBackgroundSettingsPort, OwnedUiPromptSuggestionGeneratorPort, OwnedUiSessionBackend, OwnedUiSessionPresenters, OwnedUiSessionViewModel, OwnedUiTranscriptRendererPort, OwnedUiViewportSettings, OwnedUiViewportSettingsPort, OwnedUiQuitOutroSettingsPort, SuggestionDecision, SuggestionDiagnosticObserver } from "../../contracts/owned-ui/index.js";
5
5
  import type { UiRouteHost, UiRouteInput } from "../../ui/apps/contracts.js";
6
6
  import type { TranscriptViewportFrame, TranscriptViewportFrameDescriptor } from "../../ui/components/transcript-viewport.js";
7
- import { type PreparedPrompt } from "./prompt-chips.js";
7
+ import { PromptChipStore, type PreparedPrompt } from "./prompt-chips.js";
8
8
  import type { PastePreparationClientOptions } from "./paste-preparation-client.js";
9
9
  import type { OwnedUiClipboardServices } from "./clipboard-services.js";
10
10
  import type { OwnedUiClipboardPort } from "./shell-clipboard.js";
11
- import { type SessionViewportInputResult } from "./session-viewport-controller.js";
11
+ import { SessionViewportController, type SessionViewportInputResult } from "./session-viewport-controller.js";
12
12
  import type { ResponseCopyExecutor } from "./response-copy-transport.js";
13
13
  import type { ResponseCopyEvent } from "./response-copy-protocol.js";
14
14
  import type { PasteEvent, PasteSource } from "./paste-protocol.js";
@@ -193,6 +193,8 @@ export declare class OwnedUiSessionShellRoot implements TerminalComponentPort {
193
193
  readonly resources: OwnedUiShellLoadedResourcesPort;
194
194
  /** The transcript's semantic rows, caches, and engine-backed block renderers. */
195
195
  readonly transcript: TranscriptDocument;
196
+ readonly promptChips: PromptChipStore;
197
+ readonly viewport: SessionViewportController;
196
198
  /** Workflow results, messages, and status lines appended to the transcript. */
197
199
  readonly workflow: WorkflowOutput;
198
200
  /** The dock's notices, copy acknowledgement, and release banner. */
@@ -204,28 +206,11 @@ export declare class OwnedUiSessionShellRoot implements TerminalComponentPort {
204
206
  setHideThinkingBlock(hidden: boolean): void;
205
207
  setMermaidRenderingMode(mode: "off" | "final" | "streaming"): void;
206
208
  setImagePresentation(showImages: boolean, imageWidthCells: number): void;
207
- prepareHistoryText(text: string): string;
208
- omitUnsentPromptImages(text: string): string;
209
- rehydrateHistoryText(text: string, resolveImage: (id: string) => import("../../contracts/owned-ui/index.js").PromptHistoryImageSidecarAttachment | null): string;
210
- imageChipAttachmentsFromEditor(text: string): {
211
- readonly id: string;
212
- readonly tag: string;
213
- readonly image: {
214
- readonly type: "image";
215
- readonly data: string;
216
- readonly mimeType: string;
217
- };
218
- }[];
219
- preparePromptSubmission(text: string): PreparedPrompt;
220
209
  reconcilePromptImageLimitNotice(text?: string): boolean;
221
- hasPendingPastes(text: string): boolean;
222
210
  waitForPromptPastes(text: string, signal: AbortSignal): Promise<PreparedPrompt>;
223
211
  resetPendingPastes(): void;
224
- /** Forks the spare paste helper so the first paste of the session takes a live child. */
225
- warmPastePreparation(): void;
226
212
  disposePendingPastes(): Promise<void>;
227
213
  promptSuggestionPrepareBlockReason(): SuggestionDecision;
228
- canPreparePromptSuggestion(): boolean;
229
214
  promptSuggestionPresentationBlockReason(): SuggestionDecision;
230
215
  canPresentPromptSuggestion(): boolean;
231
216
  setPromptSuggestion(text: string | null): void;
@@ -261,12 +246,6 @@ export declare class OwnedUiSessionShellRoot implements TerminalComponentPort {
261
246
  viewportTransientTailRowCount(): number;
262
247
  hasActiveSelection(): boolean;
263
248
  setViewportConfig(config: OwnedUiViewportSettings): void;
264
- setFullscreenCopyOnSelect(enabled: boolean): void;
265
- resumeViewportFollowing(): void;
266
- noteCompletedAssistantMessage(): void;
267
- resetViewport(): void;
268
- clearViewportPointerState(): void;
269
- setViewportOverlaySurfaces(surfaces: readonly TerminalPointerSurface[] | null): void;
270
249
  viewportInputGeometryReady(width: number, height: number): boolean;
271
250
  handleViewportPreInput(data: string, allowWheel?: boolean, now?: number, editorActive?: boolean): SessionViewportInputResult;
272
251
  /** The pinned-profile layout regions of this session; the terminal host arranges them with `pinnedLayoutRoot`. */
@@ -306,5 +285,4 @@ export type PinnedLayoutParts = Readonly<Record<PinnedLayoutPart, TerminalCompon
306
285
  * so its single `transcript` scroll view is shared by whichever session the parts currently resolve to.
307
286
  */
308
287
  export declare function pinnedLayoutRoot(parts: PinnedLayoutParts, theme: ThemeSource): TerminalLayoutNode;
309
- export declare function shellResourceEntries(backend: OwnedUiSessionBackend): readonly OwnedUiShellResourceEntry[];
310
288
  export {};
@@ -28,11 +28,11 @@ export class OwnedUiSessionShellRoot {
28
28
  #queued;
29
29
  #extensionRenderers;
30
30
  #imageAssets;
31
- #promptChips;
31
+ promptChips;
32
32
  #pasteDiagnosticId = 0;
33
33
  #customViewport;
34
34
  #submittedPromptComposer;
35
- #viewportController;
35
+ viewport;
36
36
  #onPromptSuggestionEligibilityChanged;
37
37
  #componentRuntime;
38
38
  #toolsExpanded = false;
@@ -57,7 +57,7 @@ export class OwnedUiSessionShellRoot {
57
57
  }, sessionLayout = "pinned", imageAssets) {
58
58
  this.#view = view;
59
59
  this.#customViewport = sessionLayout === "custom-viewport";
60
- this.#promptChips = new PromptChipStore({ isolated: this.#customViewport,
60
+ this.promptChips = new PromptChipStore({ isolated: this.#customViewport,
61
61
  ...(handlers.pasteDiagnostics === undefined ? {} : { onEvent: handlers.pasteDiagnostics }),
62
62
  ...(handlers.pastePreparation === undefined ? {} : { preparation: handlers.pastePreparation }),
63
63
  ...(handlers.promptImageLimit === undefined ? {} : { imageLimit: handlers.promptImageLimit }) });
@@ -84,25 +84,25 @@ export class OwnedUiSessionShellRoot {
84
84
  customViewport: this.#customViewport,
85
85
  cwd,
86
86
  ...(agentDir === undefined ? {} : { agentDir }),
87
- promptChips: this.#promptChips,
88
- editorPointerSelecting: () => this.#viewportController.editorPointerSelecting,
87
+ promptChips: this.promptChips,
88
+ editorPointerSelecting: () => this.viewport.editorPointerSelecting,
89
89
  nextPasteDiagnosticRequest: () => --this.#pasteDiagnosticId,
90
90
  toggleToolsExpanded: () => this.#setToolsExpanded(!this.#toolsExpanded),
91
91
  });
92
92
  this.#queued = handlers.components.chrome.queuedInput(view.editor.queuedSubmissions, this.#customViewport ? "custom-viewport" : "pinned", this.#customViewport ? () => this.editor.keybindingConfig() : undefined);
93
- this.#viewportController = new SessionViewportController({
93
+ this.viewport = new SessionViewportController({
94
94
  enabled: this.#customViewport,
95
95
  editor: this.editor,
96
96
  requestRender: force => this.#componentRuntime.requestRender(force),
97
97
  requestHyperlinkCleanup: rows => handlers.requestHyperlinkCleanup?.(rows),
98
- hasEditorLinks: () => this.#promptChips.hyperlinkRanges(this.editor.getText()).length > 0,
98
+ hasEditorLinks: () => this.promptChips.hyperlinkRanges(this.editor.getText()).length > 0,
99
99
  ...(handlers.pasteDiagnostics === undefined ? {} : { pasteDiagnostics: handlers.pasteDiagnostics }),
100
100
  nextPasteDiagnosticRequest: () => --this.#pasteDiagnosticId,
101
101
  });
102
102
  this.chrome = new DockChrome({ theme: handlers.presentation.theme, outputPad: handlers.presentation.pinnedOutputPad, components: handlers.components,
103
103
  invalidateChrome: () => this.#invalidateChrome(),
104
104
  requestRender: () => this.#componentRuntime.requestRender(),
105
- viewport: this.#viewportController,
105
+ viewport: this.viewport,
106
106
  });
107
107
  this.workflow = new WorkflowOutput({
108
108
  customViewport: this.#customViewport, components: handlers.components,
@@ -117,7 +117,7 @@ export class OwnedUiSessionShellRoot {
117
117
  this.editor.setThinkingLevel(view.thinkingLevel);
118
118
  this.#input = new InputSurfaceSwitch(this.editor, {
119
119
  dockInputReuse: this.#customViewport && (handlers.enableDockInputReuse ?? true), classifyInput: handlers.presentation.terminalRuntime.classifyInput,
120
- viewport: this.#viewportController,
120
+ viewport: this.viewport,
121
121
  ...(handlers.onInputSurfaceChanged === undefined ? {} : { onChanged: handlers.onInputSurfaceChanged }),
122
122
  });
123
123
  this.#layout = this.#createLayout(handlers.onViewportFrame, createViewportTheme(handlers.presentation.theme));
@@ -153,10 +153,10 @@ export class OwnedUiSessionShellRoot {
153
153
  // Invariant: one layout per root; the render path never consults the layout mode again.
154
154
  #createLayout(onFrame, theme) {
155
155
  const ports = {
156
- viewport: this.#viewportController,
156
+ viewport: this.viewport,
157
157
  input: this.#input,
158
158
  editor: this.editor,
159
- promptChips: this.#promptChips,
159
+ promptChips: this.promptChips,
160
160
  dockChrome: this.chrome,
161
161
  theme,
162
162
  ...(onFrame === undefined ? {} : { onFrame }),
@@ -217,40 +217,22 @@ export class OwnedUiSessionShellRoot {
217
217
  component.setImagePresentation(showImages, imageWidthCells);
218
218
  this.#invalidateTranscriptPresentation();
219
219
  }
220
- prepareHistoryText(text) {
221
- return this.#promptChips.prepareHistoryText(text);
222
- }
223
- omitUnsentPromptImages(text) {
224
- return this.#promptChips.omitUnsentImages(text);
225
- }
226
- rehydrateHistoryText(text, resolveImage) {
227
- return this.#promptChips.rehydrateHistoryText(text, resolveImage);
228
- }
229
- imageChipAttachmentsFromEditor(text) {
230
- return this.#promptChips.imageChipAttachments(text);
231
- }
232
- preparePromptSubmission(text) {
233
- return this.#promptChips.prepareSubmission(text);
234
- }
235
220
  reconcilePromptImageLimitNotice(text = this.editor.getText()) {
236
- if (this.chrome.notice?.errorCode !== "image-count" || !this.#promptChips.imageLimitState(text).corrected)
221
+ if (this.chrome.notice?.errorCode !== "image-count" || !this.promptChips.imageLimitState(text).corrected)
237
222
  return false;
238
223
  this.chrome.dismissNotice();
239
224
  return true;
240
225
  }
241
- hasPendingPastes(text) { return this.#promptChips.hasPending(text); }
242
226
  waitForPromptPastes(text, signal) {
243
- return this.#promptChips.waitForPastes(text, signal, () => this.editor.getText());
227
+ return this.promptChips.waitForPastes(text, signal, () => this.editor.getText());
244
228
  }
245
229
  resetPendingPastes() {
246
230
  this.editor.cancelPendingPastes?.();
247
- this.editor.setText(this.#promptChips.resetPastes(this.editor.getText()));
231
+ this.editor.setText(this.promptChips.resetPastes(this.editor.getText()));
248
232
  }
249
- /** Forks the spare paste helper so the first paste of the session takes a live child. */
250
- warmPastePreparation() { this.#promptChips.warm(); }
251
233
  disposePendingPastes() {
252
234
  this.resetPendingPastes();
253
- return this.#promptChips.dispose();
235
+ return this.promptChips.dispose();
254
236
  }
255
237
  promptSuggestionPrepareBlockReason() {
256
238
  if (!this.usesDefaultInputSurface())
@@ -261,7 +243,6 @@ export class OwnedUiSessionShellRoot {
261
243
  return "draft";
262
244
  return null;
263
245
  }
264
- canPreparePromptSuggestion() { return this.promptSuggestionPrepareBlockReason() === null; }
265
246
  promptSuggestionPresentationBlockReason() {
266
247
  const reason = this.promptSuggestionPrepareBlockReason();
267
248
  if (reason !== null)
@@ -322,18 +303,18 @@ export class OwnedUiSessionShellRoot {
322
303
  return this.#layout.render(width);
323
304
  }
324
305
  viewportFrameDescriptor() {
325
- return this.#viewportController.frame?.descriptor ?? null;
306
+ return this.viewport.frame?.descriptor ?? null;
326
307
  }
327
308
  /** Read-only, payload-free evidence; observing a pending frame must never render or repair it. */
328
309
  viewportPresentationEvidence() {
329
- const frame = this.#viewportController.frame;
310
+ const frame = this.viewport.frame;
330
311
  const snapshot = this.#layout.composed();
331
312
  return {
332
313
  candidate: this.#input.dockInputCandidate,
333
314
  candidateRevision: this.#input.dockInputCandidate ? this.#input.dockInputRevision ?? null : null,
334
- currentRevision: this.#viewportController.presentationRevision,
315
+ currentRevision: this.viewport.presentationRevision,
335
316
  composedRevision: snapshot?.viewportRevision ?? null,
336
- currentPointer: this.#viewportController.pointerPosition ?? null,
317
+ currentPointer: this.viewport.pointerPosition ?? null,
337
318
  composedPointer: snapshot?.pointerPosition ?? null,
338
319
  frameId: frame?.descriptor.frameId ?? null,
339
320
  bottom: frame?.hits.bottom ?? null,
@@ -345,41 +326,23 @@ export class OwnedUiSessionShellRoot {
345
326
  }
346
327
  /** Visible non-persistent Steering, alignment, and Working rows, for rendering evidence. */
347
328
  viewportTransientTailRowCount() {
348
- return this.#viewportController.frame?.hits.transientTail.length ?? 0;
329
+ return this.viewport.frame?.hits.transientTail.length ?? 0;
349
330
  }
350
331
  hasActiveSelection() {
351
- return this.#viewportController.hasSelection || this.editor.hasSelection();
332
+ return this.viewport.hasSelection || this.editor.hasSelection();
352
333
  }
353
334
  setViewportConfig(config) {
354
- if (this.#viewportController.setConfig(config)) {
335
+ if (this.viewport.setConfig(config)) {
355
336
  this.transcript.invalidate("viewport-config");
356
337
  this.#layout.invalidate();
357
338
  }
358
339
  }
359
- setFullscreenCopyOnSelect(enabled) {
360
- this.#viewportController.setCopyOnSelect(enabled);
361
- }
362
- resumeViewportFollowing() {
363
- this.#viewportController.resumeFollowing();
364
- }
365
- noteCompletedAssistantMessage() {
366
- this.#viewportController.noteCompletedAssistantMessage();
367
- }
368
- resetViewport() {
369
- this.#viewportController.reset();
370
- }
371
- clearViewportPointerState() {
372
- this.#viewportController.clearPointerState();
373
- }
374
- setViewportOverlaySurfaces(surfaces) {
375
- this.#viewportController.setOverlaySurfaces(surfaces);
376
- }
377
340
  viewportInputGeometryReady(width, height) {
378
- const frame = this.#viewportController.frame;
379
- return this.#viewportController.inputGeometryReady && frame?.descriptor.width === width && frame.descriptor.height === height;
341
+ const frame = this.viewport.frame;
342
+ return this.viewport.inputGeometryReady && frame?.descriptor.width === width && frame.descriptor.height === height;
380
343
  }
381
344
  handleViewportPreInput(data, allowWheel = true, now = Date.now(), editorActive = this.usesDefaultInputSurface()) {
382
- return this.#viewportController.handlePreInput(data, allowWheel, now, editorActive);
345
+ return this.viewport.handlePreInput(data, allowWheel, now, editorActive);
383
346
  }
384
347
  #renderDockLayout(width) {
385
348
  const queued = this.#customViewport ? [] : this.#renderQueued(width);
@@ -552,7 +515,7 @@ export class OwnedUiSessionShellRoot {
552
515
  }
553
516
  dispose() {
554
517
  this.chrome.clearCopyAcknowledgement(false);
555
- this.clearViewportPointerState();
518
+ this.viewport.clearPointerState();
556
519
  this.#themeUnsubscribe();
557
520
  this.header.dispose?.();
558
521
  this.resources.dispose?.();
@@ -650,163 +613,6 @@ function layoutPort(render, invalidate, handleInput) {
650
613
  ...(handleInput === undefined ? {} : { handleInput }),
651
614
  };
652
615
  }
653
- export function shellResourceEntries(backend) {
654
- const resources = backend.extensions.nonVisualResources().map(resource => ({
655
- section: resource.kind === "skill"
656
- ? "Skills"
657
- : resource.kind === "prompt-template"
658
- ? "Prompts"
659
- : resource.kind === "theme"
660
- ? "Themes"
661
- : "Context",
662
- label: resource.kind === "prompt-template"
663
- ? `/${resource.label}`
664
- : resource.kind === "agent-context" || resource.kind === "system-prompt"
665
- ? compactResourceLabel(resource.sourcePath ?? resource.label)
666
- : resource.label,
667
- sourcePath: resource.sourcePath,
668
- diagnostic: resource.diagnostic,
669
- }));
670
- const extensions = backend.extensions.extensionResources().filter(extension => !extension.hidden);
671
- const loadedExtensions = extensions.filter(extension => extension.diagnostic === null);
672
- const extensionLabels = compactExtensionLabels(loadedExtensions);
673
- for (const extension of extensions) {
674
- const labelIndex = loadedExtensions.indexOf(extension);
675
- resources.push({
676
- section: "Extensions",
677
- label: extensionLabels[labelIndex] ?? compactResourceLabel(extension.sourcePath ?? extension.resolvedPath ?? "extension"),
678
- sourcePath: extension.sourcePath ?? extension.resolvedPath,
679
- diagnostic: extension.diagnostic,
680
- });
681
- }
682
- return resources;
683
- }
684
- function compactResourceLabel(path) {
685
- const segments = compactPathSegments(path);
686
- const leaf = segments.at(-1) ?? path;
687
- if ((leaf === "index.ts" || leaf === "index.js") && segments.length > 1)
688
- return segments.at(-2) ?? leaf;
689
- return leaf;
690
- }
691
- /**
692
- * Pinned from InteractiveMode's compact extension-label helpers at Pi commit
693
- * 914cf1472e715297caa30db4b9535d534a9eb718. The source metadata crosses an
694
- * A1-owned boundary first; the owned shell never inspects Pi's private root.
695
- */
696
- function compactExtensionLabels(extensions) {
697
- const localExtensions = extensions
698
- .filter(extension => !isPackageExtensionSource(extension.sourceInfo))
699
- .map(extension => {
700
- const path = extension.sourcePath ?? extension.resolvedPath ?? "extension";
701
- const segments = compactPathSegments(path);
702
- if (segments.length > 1 && (segments.at(-1) === "index.ts" || segments.at(-1) === "index.js"))
703
- segments.pop();
704
- return { extension, segments };
705
- });
706
- return extensions.map(extension => {
707
- const resourcePath = extension.sourcePath ?? extension.resolvedPath ?? "extension";
708
- if (isPackageExtensionSource(extension.sourceInfo)) {
709
- return compactPackageExtensionLabel(resourcePath, extension.sourceInfo);
710
- }
711
- const localIndex = localExtensions.findIndex(item => item.extension === extension);
712
- const segments = localExtensions[localIndex]?.segments;
713
- if (!segments || segments.length === 0)
714
- return compactResourceLabel(resourcePath);
715
- for (let count = 1; count <= segments.length; count += 1) {
716
- const candidate = segments.slice(-count).join("/");
717
- if (localExtensions.every((item, itemIndex) => itemIndex === localIndex || item.segments.slice(-count).join("/") !== candidate)) {
718
- return candidate;
719
- }
720
- }
721
- return segments.join("/");
722
- });
723
- }
724
- function compactPackageExtensionLabel(resourcePath, sourceInfo) {
725
- const sourceLabel = compactPackageSourceLabel(sourceInfo.source);
726
- if (!sourceLabel)
727
- return compactResourceLabel(resourcePath);
728
- const shortPath = shortPackagePath(resourcePath, sourceInfo).replaceAll("\\", "/");
729
- const packagePath = shortPath.startsWith("extensions/") ? shortPath.slice("extensions/".length) : shortPath;
730
- const slash = packagePath.lastIndexOf("/");
731
- const fileName = slash < 0 ? packagePath : packagePath.slice(slash + 1);
732
- const directory = slash < 0 ? "" : packagePath.slice(0, slash);
733
- const extension = fileName.lastIndexOf(".");
734
- const name = extension <= 0 ? fileName : fileName.slice(0, extension);
735
- if (name === "index")
736
- return !directory || directory === "." ? sourceLabel : `${sourceLabel}:${directory}`;
737
- return `${sourceLabel}:${packagePath}`;
738
- }
739
- function compactPackageSourceLabel(source) {
740
- if (source.startsWith("npm:"))
741
- return source.slice("npm:".length) || source;
742
- if (!source.startsWith("git:"))
743
- return source;
744
- const gitSource = source.slice("git:".length).trim();
745
- let repositoryPath;
746
- const scpLike = gitSource.match(/^git@[^:]+:(.+)$/);
747
- if (scpLike?.[1]) {
748
- repositoryPath = scpLike[1];
749
- }
750
- else if (/^[a-z]+:\/\//i.test(gitSource)) {
751
- try {
752
- repositoryPath = new URL(gitSource).pathname.replace(/^\/+/, "");
753
- }
754
- catch {
755
- return source;
756
- }
757
- }
758
- else {
759
- const slash = gitSource.indexOf("/");
760
- if (slash >= 0)
761
- repositoryPath = gitSource.slice(slash + 1);
762
- }
763
- if (!repositoryPath)
764
- return source;
765
- const ref = repositoryPath.indexOf("@");
766
- const withoutRef = ref < 0 ? repositoryPath : repositoryPath.slice(0, ref);
767
- return withoutRef.replace(/\.git$/, "") || source;
768
- }
769
- function shortPackagePath(resourcePath, sourceInfo) {
770
- const fullPath = normalizeResourcePath(resourcePath);
771
- const baseDir = sourceInfo.baseDir === null ? undefined : normalizeResourcePath(sourceInfo.baseDir).replace(/\/$/, "");
772
- if (baseDir) {
773
- const npmRoot = baseDir.match(/^(.*\/node_modules)\/(@?[^/]+(?:\/[^/]+)?)$/);
774
- if (npmRoot?.[1] && fullPath.startsWith(`${npmRoot[1]}/`))
775
- return relativeResourcePath(baseDir, fullPath);
776
- if (fullPath === baseDir)
777
- return ".";
778
- if (fullPath.startsWith(`${baseDir}/`))
779
- return fullPath.slice(baseDir.length + 1);
780
- }
781
- const npmMatch = fullPath.match(/node_modules\/(@?[^/]+(?:\/[^/]+)?)\/(.*)/);
782
- if (npmMatch?.[2] && sourceInfo.source.startsWith("npm:"))
783
- return npmMatch[2];
784
- const gitMatch = fullPath.match(/git\/[^/]+\/[^/]+\/(.*)/);
785
- if (gitMatch?.[1] && sourceInfo.source.startsWith("git:"))
786
- return gitMatch[1];
787
- return resourcePath;
788
- }
789
- function relativeResourcePath(from, to) {
790
- const fromSegments = from.split("/").filter(Boolean);
791
- const toSegments = to.split("/").filter(Boolean);
792
- let common = 0;
793
- while (common < fromSegments.length && common < toSegments.length
794
- && fromSegments[common]?.toLowerCase() === toSegments[common]?.toLowerCase())
795
- common += 1;
796
- return [...fromSegments.slice(common).map(() => ".."), ...toSegments.slice(common)].join("/") || ".";
797
- }
798
- function compactPathSegments(path) {
799
- return normalizeResourcePath(path).split("/").filter(segment => segment.length > 0 && segment !== "~");
800
- }
801
- function normalizeResourcePath(path) {
802
- return path.replaceAll("\\", "/");
803
- }
804
- function isPackageExtensionSource(sourceInfo) {
805
- const source = sourceInfo?.source ?? "";
806
- return source.startsWith("npm:") || source.startsWith("git:");
807
- }
808
- // Performance: one painter set per root keeps identities stable, so the neutral viewport retains row-level
809
- // selection variants while each callback still resolves the live theme.
810
616
  function createViewportTheme(source) {
811
617
  return {
812
618
  track: text => `${SCROLLBAR_CELL_RESET}${source.current().fg("dim", text)}`,
@@ -1,7 +1,8 @@
1
1
  import type { OwnedUiShellSelectorOption } from "../../contracts/owned-ui/index.js";
2
2
  import type { TerminalComponentPort, TerminalInputListenerResult, TerminalInputSurfaceKind, TerminalOverlayHandle, TerminalPointerSurface } from "../../contracts/presentation/index.js";
3
+ import { SessionSelectors } from "./session-selectors.js";
3
4
  import type { OwnedUiCommandResult, OwnedUiSessionBackend, OwnedUiSessionViewModel, OwnedUiThinkingLevel, OwnedUiWorkflowRequest } from "../../contracts/owned-ui/index.js";
4
- import type { OwnedUiShellHotkeysPresentation, OwnedUiShellSkillSummary } from "../../contracts/owned-ui/index.js";
5
+ import type { OwnedUiShellHotkeysPresentation } from "../../contracts/owned-ui/index.js";
5
6
  import type { TerminalDamageDecision, TerminalRuntimePort } from "../../contracts/presentation/index.js";
6
7
  import { OwnedUiTerminalHost, type OwnedUiHostedPresenter, type OwnedUiPresenterRelease } from "./shell-host.js";
7
8
  import { OwnedUiSessionShellRoot, type OwnedUiSessionShellOptions, type PinnedLayoutPart } from "./session-shell-root.js";
@@ -15,6 +16,7 @@ export { formatSessionResumeCommand, quoteCommandArgument, type SessionResumeCom
15
16
  export declare class OwnedUiSessionPresenter implements OwnedUiHostedPresenter {
16
17
  #private;
17
18
  readonly backend: OwnedUiSessionBackend;
19
+ readonly selectors: SessionSelectors;
18
20
  readonly root: OwnedUiSessionShellRoot;
19
21
  constructor(host: OwnedUiTerminalHost, options: OwnedUiSessionShellOptions);
20
22
  view(): OwnedUiSessionViewModel;
@@ -30,41 +32,19 @@ export declare class OwnedUiSessionPresenter implements OwnedUiHostedPresenter {
30
32
  activated(): void;
31
33
  handleViewportInput(data: string): TerminalInputListenerResult | undefined;
32
34
  start(): void;
33
- onView(listener: (view: OwnedUiSessionViewModel) => void): () => void;
34
35
  waitUntilStopped(): Promise<void>;
35
36
  submit(text: string): Promise<OwnedUiCommandResult>;
36
37
  clearOrExit(now?: number): Promise<OwnedUiCommandResult>;
37
38
  interrupt(now?: number): Promise<OwnedUiCommandResult>;
38
39
  abort(): Promise<OwnedUiCommandResult>;
39
- retry(): Promise<OwnedUiCommandResult>;
40
- compact(): Promise<OwnedUiCommandResult>;
41
- newSession(): Promise<OwnedUiCommandResult>;
42
- resumeSession(sessionPath: string): Promise<OwnedUiCommandResult>;
43
- setModel(providerId: string, modelId: string): Promise<OwnedUiCommandResult>;
44
40
  setThinkingLevel(thinkingLevel: OwnedUiThinkingLevel): Promise<OwnedUiCommandResult>;
45
41
  cycleThinkingLevel(): Promise<OwnedUiCommandResult>;
46
42
  cycleModel(direction: "forward" | "backward"): Promise<OwnedUiCommandResult>;
47
43
  queueFollowUp(): Promise<OwnedUiCommandResult>;
48
44
  restoreQueuedInput(): void;
49
45
  showSelector(title: string, options: readonly OwnedUiShellSelectorOption[], onSelect: (id: string) => void, onCancel?: () => void): TerminalOverlayHandle;
50
- showThinkingSelector(): Promise<void>;
51
- /** The Skills dialog: a replacement input like the model selector, applying the chosen skill through the prompt path. */
52
- showSkillsSelector(skills?: readonly OwnedUiShellSkillSummary[]): void;
53
- showModelSelector(initialSearchInput?: string): void;
54
- showForkSelector(): void;
55
- showLogoutSelector(): Promise<void>;
56
- showLoginMethodSelector(providerReference: string): void;
57
- showTreeSelector(initialSelectedId?: string): Promise<void>;
58
- showLoginAuthTypeSelector(): void;
59
- showLoginProviderSelector(authType?: "oauth" | "api_key", initialSearchInput?: string): void;
60
- showSessionSelector(): Promise<void>;
61
- showSettingsSelector(): void;
62
46
  shutdown(): Promise<OwnedUiCommandResult>;
63
47
  runWorkflow(request: OwnedUiWorkflowRequest): Promise<OwnedUiCommandResult>;
64
- showTrustSelector(): void;
65
- showScopedModelsSelector(): void;
66
- /** The bare-A1 unified Models dialog: switch on Enter, scope on Space, persist on Ctrl+S, all through the engine. */
67
- showModelsDialog(initialQuery?: string): void;
68
48
  dispose(): Promise<void>;
69
49
  release(terminal: {
70
50
  readonly mode: "regular" | "fullscreen";