@timurproko/a1 0.2.7-dev.779 → 0.2.7-dev.792

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 (139) hide show
  1. package/dist/app/session-shell/session-shell-root.d.ts +0 -1
  2. package/dist/app/session-shell/session-shell-root.js +45 -18
  3. package/dist/app/session-shell/session-shell.js +10 -5
  4. package/dist/app/session-shell/session-viewport-controller.d.ts +2 -2
  5. package/dist/app/session-shell/session-viewport-controller.js +24 -12
  6. package/dist/app/session-shell/shell-host.d.ts +0 -2
  7. package/dist/app/session-shell/shell-host.js +3 -20
  8. package/dist/cli/tabs.js +15 -0
  9. package/dist/composition/owned-ui.d.ts +1 -1
  10. package/dist/composition/owned-ui.js +66 -32
  11. package/dist/contracts/owned-ui/index.d.ts +1 -1
  12. package/dist/contracts/owned-ui/model.d.ts +3 -0
  13. package/dist/contracts/owned-ui/session-workflows.d.ts +4 -1
  14. package/dist/features/owned-ui/settings-app.js +9 -6
  15. package/dist/features/resident-tab/auto-name.d.ts +2 -2
  16. package/dist/features/resident-tab/auto-name.js +7 -5
  17. package/dist/features/resident-tab/index.d.ts +4 -2
  18. package/dist/features/resident-tab/index.js +6 -2
  19. package/dist/features/resident-tab/shortcut-bindings-file.d.ts +8 -0
  20. package/dist/features/resident-tab/shortcut-bindings-file.js +40 -0
  21. package/dist/features/resident-tab/{shortcuts.d.ts → shortcut-declarations.d.ts} +5 -2
  22. package/dist/features/resident-tab/{shortcuts.js → shortcut-declarations.js} +5 -17
  23. package/dist/features/resident-tab/shortcut-projection.d.ts +29 -0
  24. package/dist/features/resident-tab/shortcut-projection.js +64 -0
  25. package/dist/foundation/release/bootstrap.js +1 -0
  26. package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
  27. package/dist/foundation/release/progress-palette.generated.js +2 -2
  28. package/dist/foundation/resident-tabs/bridge-client.d.ts +5 -0
  29. package/dist/foundation/resident-tabs/bridge-client.js +17 -1
  30. package/dist/foundation/resident-tabs/prompt-journal.d.ts +0 -2
  31. package/dist/foundation/resident-tabs/prompt-journal.js +0 -1
  32. package/dist/foundation/startup/startup-descriptor.js +2 -2
  33. package/dist/integrations/pi/components/owned-editor-ux.d.ts +2 -0
  34. package/dist/integrations/pi/components/owned-editor-ux.js +13 -0
  35. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
  36. package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
  37. package/dist/integrations/pi/components/share-operation-dialog.d.ts +2 -0
  38. package/dist/integrations/pi/components/share-operation-dialog.js +2 -1
  39. package/dist/integrations/pi/components/shell-editor-autocomplete.js +1 -0
  40. package/dist/integrations/pi/components/shell-presenters-info.d.ts +1 -0
  41. package/dist/integrations/pi/components/shell-presenters-info.js +10 -30
  42. package/dist/integrations/pi/components/shell-selectors-dialogs.js +1 -0
  43. package/dist/integrations/pi/components/shell-shared-facade.d.ts +2 -0
  44. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  45. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
  46. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  47. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  48. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  49. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  50. package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
  51. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  52. package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
  53. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  54. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
  55. package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
  56. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  57. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  58. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  59. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  60. package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
  61. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  62. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  63. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
  64. package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
  65. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  66. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  67. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  68. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
  69. package/dist/integrations/pi/components/upstream/components/tool-execution.js +1 -1
  70. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
  71. package/dist/integrations/pi/components/upstream/components/tree-selector.js +3 -11
  72. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  73. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  74. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +1 -1
  75. package/dist/integrations/pi/components/upstream/history/editor-core.js +1 -1
  76. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  77. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  78. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  79. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  80. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  81. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  82. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  83. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  84. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
  85. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  86. package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
  87. package/dist/integrations/pi/engine/pi-settings-metadata.json +12 -0
  88. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  89. package/dist/integrations/pi/engine/settings-bridge.js +2 -0
  90. package/dist/integrations/pi/engine/settings-port.js +10 -1
  91. package/dist/integrations/pi/engine/workflow-runner.js +64 -2
  92. package/dist/integrations/pi/engine/workflow-support.d.ts +12 -0
  93. package/dist/integrations/pi/engine/workflow-support.js +36 -0
  94. package/dist/integrations/pi/engine/workflows.d.ts +3 -1
  95. package/dist/integrations/pi/engine/workflows.js +1 -0
  96. package/dist/integrations/pi/startup-public.js +38 -35
  97. package/dist/integrations/pi/startup-public.manifest.json +110 -116
  98. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  99. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
  100. package/dist/native/darwin-arm64/a1_session_lock.node +0 -0
  101. package/dist/native/darwin-arm64/manifest.json +3 -2
  102. package/dist/native/darwin-arm64/terminal-host +0 -0
  103. package/dist/native/darwin-arm64/terminal-host.manifest.json +7 -6
  104. package/dist/native/darwin-x64/a1_session_lock.node +0 -0
  105. package/dist/native/darwin-x64/manifest.json +5 -4
  106. package/dist/native/darwin-x64/process-guardian +0 -0
  107. package/dist/native/darwin-x64/terminal-host +0 -0
  108. package/dist/native/darwin-x64/terminal-host.manifest.json +7 -6
  109. package/dist/native/linux-x64/a1_session_lock.node +0 -0
  110. package/dist/native/linux-x64/manifest.json +3 -2
  111. package/dist/native/linux-x64/terminal-host +0 -0
  112. package/dist/native/linux-x64/terminal-host.manifest.json +7 -6
  113. package/dist/native/win32-x64/a1_session_lock.node +0 -0
  114. package/dist/native/win32-x64/manifest.json +4 -3
  115. package/dist/native/win32-x64/process-guardian.exe +0 -0
  116. package/dist/native/win32-x64/terminal-host.exe +0 -0
  117. package/dist/native/win32-x64/terminal-host.manifest.json +6 -5
  118. package/dist/runtime-payload-inventory.json +4242 -3716
  119. package/dist/ui/components/index.d.ts +2 -2
  120. package/dist/ui/components/index.js +1 -1
  121. package/dist/ui/components/selection-copy.d.ts +2 -0
  122. package/dist/ui/components/selection-copy.js +13 -0
  123. package/dist/ui/components/submitted-prompt.d.ts +7 -4
  124. package/dist/ui/components/submitted-prompt.js +18 -10
  125. package/dist/ui/components/transcript-viewport.d.ts +10 -6
  126. package/dist/ui/components/transcript-viewport.js +28 -13
  127. package/dist/ui/settings/declarations.d.ts +13 -1
  128. package/dist/ui/settings/declarations.js +12 -1
  129. package/dist/ui/settings/migrations.js +7 -0
  130. package/docs/architecture/evidence/resident-tabs/macos-x64.md +1 -1
  131. package/docs/architecture/process-guardian-provenance.md +1 -1
  132. package/docs/architecture/project-structure.md +8 -0
  133. package/docs/architecture/resident-tabs.md +18 -2
  134. package/docs/architecture/terminal-host-provenance.md +1 -1
  135. package/docs/architecture/toolchain.md +2 -2
  136. package/docs/ci-release-runbook.md +2 -2
  137. package/docs/openspec-archive-automation.md +5 -5
  138. package/docs/validation.md +12 -4
  139. package/package.json +3 -3
@@ -53,7 +53,6 @@ export interface OwnedUiShellEngineOptions {
53
53
  readonly sessionFile: string | null;
54
54
  readonly kind: "prompt" | "steer" | "follow-up";
55
55
  readonly text: string;
56
- readonly images?: readonly unknown[];
57
56
  }): Promise<{
58
57
  readonly id: string;
59
58
  }>;
@@ -96,9 +96,8 @@ export class OwnedUiSessionShellRoot {
96
96
  ...(handlers.promptImageLimit === undefined ? {} : { imageLimit: handlers.promptImageLimit }) });
97
97
  this.#submittedPromptComposer = this.#customViewport
98
98
  ? {
99
- layout: submittedPromptLayout,
100
- compose: (rows, width, source, style) => composeSubmittedPromptRows(rows, width, source, { ...style, prefix: text => promptArrow(text, piTheme()) })
101
- .map(row => nativeHyperlinkStyle(row, nativeTranscriptLinkColor)),
99
+ layout: (width, source) => submittedPromptLayout(width, source, this.#viewportController.config.timeFormat ?? "8:00 PM"),
100
+ compose: (rows, width, source, style) => composeSubmittedPromptRows(rows, width, source, { ...style, prefix: text => promptArrow(text, piTheme()) }, this.#viewportController.config.timeFormat ?? "8:00 PM").map(row => nativeHyperlinkStyle(row, nativeTranscriptLinkColor)),
102
101
  }
103
102
  : undefined;
104
103
  this.#cwd = cwd;
@@ -430,6 +429,23 @@ export class OwnedUiSessionShellRoot {
430
429
  const selectableDocumentRowCount = document.rows.length;
431
430
  const dockStartRow = height - dockRows.length + 1;
432
431
  const editorOffset = dock.editorOffset;
432
+ // Rationale: rendered chip tags are lossy presentation (truncated labels), so a frame drag over
433
+ // a draft holding chips stays visual-only; editor-owned word/line selection still copies the
434
+ // expanded chip text through its semantic route.
435
+ const draft = this.usesDefaultInputSurface() ? this.editor.getText() : "";
436
+ const promptCopyRows = draft.length > 0
437
+ && !draft.split("\n").some(line => this.#promptChips.atomicRanges(line).length > 0)
438
+ ? Math.max(0, dock.inputRows - 2)
439
+ : 0;
440
+ const copyableDockRows = [
441
+ ...Array.from({ length: promptCopyRows }, (_value, index) => ({
442
+ row: editorOffset + index + 1,
443
+ prompt: index === 0 ? "first" : "continuation",
444
+ })),
445
+ ...Array.from({ length: dock.footerRows }, (_value, index) => ({
446
+ row: dockRows.length - dock.footerRows + index,
447
+ })),
448
+ ];
433
449
  this.#viewportController.setInputSurfaceFrame(this.usesDefaultInputSurface() ? undefined : {
434
450
  component: this.#inputSurface,
435
451
  columnStart: 1,
@@ -458,7 +474,7 @@ export class OwnedUiSessionShellRoot {
458
474
  && snapshot.inputSurface === inputSurface
459
475
  && snapshot.viewportRevision === viewportRevision
460
476
  && snapshot.selectionRevision === selectionRevision
461
- ? this.#viewportController.composeDockOnly(dockRows, width, height, dock.footerRows)
477
+ ? this.#viewportController.composeDockOnly(dockRows, width, height, copyableDockRows)
462
478
  : null;
463
479
  if (frame === null) {
464
480
  frame = this.#viewportController.compose({
@@ -474,7 +490,7 @@ export class OwnedUiSessionShellRoot {
474
490
  ...(document.liveTailStartRow === undefined ? {} : { liveTailStartRow: document.liveTailStartRow }),
475
491
  bottomAlignedTailRowCount: steeringRows.length + statusRows.length,
476
492
  dockRows,
477
- explicitCopyDockRows: dock.footerRows,
493
+ copyableDockRows,
478
494
  promptAnchors: document.promptAnchors,
479
495
  width,
480
496
  height,
@@ -541,8 +557,11 @@ export class OwnedUiSessionShellRoot {
541
557
  return this.#viewportController.hasSelection || this.editor.hasSelection();
542
558
  }
543
559
  setViewportConfig(config) {
544
- if (this.#viewportController.setConfig(config))
560
+ if (this.#viewportController.setConfig(config)) {
561
+ this.#renderedRows.clear();
545
562
  this.#documentLayouts.clear();
563
+ this.#visibleViewportSnapshot = undefined;
564
+ }
546
565
  }
547
566
  setFullscreenCopyOnSelect(enabled) {
548
567
  this.#viewportController.setCopyOnSelect(enabled);
@@ -751,11 +770,13 @@ export class OwnedUiSessionShellRoot {
751
770
  }
752
771
  rows.push(...blockRows);
753
772
  if (promptLike && blockRows[0] !== undefined) {
773
+ const source = pinnedPromptSource(block, blockRows[0], blockWidth, this.#viewportController.config.timeFormat);
754
774
  promptAnchors.push({
755
775
  id: block.id,
756
776
  firstRow,
757
777
  lastRow: Math.max(firstRow, rows.length - 1),
758
- sourceRow: pinnedPromptSourceRow(block, blockRows[0], blockWidth),
778
+ sourceRow: source.row,
779
+ copySuffixWidth: source.copySuffixWidth,
759
780
  prominentSourceRow: blockRows[0],
760
781
  });
761
782
  }
@@ -960,9 +981,10 @@ export class OwnedUiSessionShellRoot {
960
981
  return;
961
982
  }
962
983
  // Rationale: the pinned engine links both share URLs; the workflow result carries the plain URLs.
963
- const message = result.command === "share" && result.detail
964
- ? `${linkShareUrl(result.message)}\nGist: ${piShellHyperlink(result.detail)}`
965
- : result.message;
984
+ const message = result.command !== "share" ? result.message
985
+ : result.detail ? `${linkShareUrl(result.message)}\nGist: ${piShellHyperlink(result.detail)}`
986
+ // Protocol: Radius shares carry only the artifact URL.
987
+ : linkShareUrl(result.message);
966
988
  this.appendWorkflowStatus(message);
967
989
  }
968
990
  toggleThinkingVisibility() {
@@ -1321,20 +1343,25 @@ function withoutTerminalBackground(text) {
1321
1343
  return text.replace(TERMINAL_BACKGROUND, "");
1322
1344
  }
1323
1345
  /** Preserve the stable metadata-grey foreground for every pinned timestamp state. */
1324
- function pinnedPromptSourceRow(block, sourceRow, width) {
1346
+ function pinnedPromptSource(block, sourceRow, width, timeFormat) {
1347
+ const unchanged = { row: sourceRow, copySuffixWidth: 0 };
1325
1348
  if (typeof block.payload !== "object" || block.payload === null)
1326
- return sourceRow;
1349
+ return unchanged;
1327
1350
  const value = block.payload.timestamp;
1328
1351
  if (typeof value !== "number" || !Number.isFinite(value))
1329
- return sourceRow;
1330
- const timestamp = formatSubmittedPromptTime(value);
1331
- if (timestamp === null || submittedPromptLayout(width, value).timestamp === null)
1332
- return sourceRow;
1352
+ return unchanged;
1353
+ const format = timeFormat ?? "8:00 PM";
1354
+ const timestamp = formatSubmittedPromptTime(value, format);
1355
+ if (timestamp === null || submittedPromptLayout(width, value, format).timestamp === null)
1356
+ return unchanged;
1333
1357
  const rowWidth = displayWidth(sourceRow);
1334
1358
  const timestampWidth = displayWidth(timestamp);
1335
1359
  if (rowWidth < timestampWidth)
1336
- return sourceRow;
1337
- return overlaySpan(sourceRow, rowWidth - timestampWidth, rowWidth, paintPiSubmittedPromptTimestamp(timestamp));
1360
+ return unchanged;
1361
+ return {
1362
+ row: overlaySpan(sourceRow, rowWidth - timestampWidth, rowWidth, paintPiSubmittedPromptTimestamp(timestamp)),
1363
+ copySuffixWidth: timestampWidth,
1364
+ };
1338
1365
  }
1339
1366
  /**
1340
1367
  * The pinned-profile screen: a followed transcript scroll above the dock. The runtime mounts one such layout,
@@ -270,7 +270,7 @@ export class OwnedUiSessionPresenter {
270
270
  // Invariant: the presenter owns its root (theme subscription and helper clients) and disposes it once the
271
271
  // terminal no longer renders it.
272
272
  constructed.push(() => this.root.dispose());
273
- this.#restoreResidentInput();
273
+ this.#restoreResidentInput(options.history?.imageSidecar);
274
274
  const initialPiSettings = this.backend.settings.snapshot();
275
275
  this.#programStatus = new ProgramStatusReporter(status => this.#terminal.setProgramStatus(status), () => this.view().status.footer?.sessionName ?? undefined);
276
276
  this.#reloadPresentation = reloadPresentation;
@@ -802,7 +802,6 @@ export class OwnedUiSessionPresenter {
802
802
  sessionFile: this.#currentSessionFile(),
803
803
  kind: type,
804
804
  text: input,
805
- ...(prepared.images.length === 0 ? {} : { images: prepared.images }),
806
805
  });
807
806
  }
808
807
  catch {
@@ -1213,11 +1212,13 @@ export class OwnedUiSessionPresenter {
1213
1212
  this.#resolveStoppedLifecycle();
1214
1213
  }
1215
1214
  }
1216
- #restoreResidentInput() {
1215
+ #restoreResidentInput(imageSidecar) {
1217
1216
  const recovered = this.#residentTabOptions?.recovered;
1218
1217
  if (recovered === undefined)
1219
1218
  return;
1220
- const prompts = recovered.prompts.map(prompt => prompt.text).filter(Boolean);
1219
+ const prompts = recovered.prompts
1220
+ .map(prompt => this.root.rehydrateHistoryText(prompt.text, id => imageSidecar?.readAttachment(id) ?? null))
1221
+ .filter(Boolean);
1221
1222
  if (prompts.length > 0) {
1222
1223
  this.root.editor.setText(prompts[0]);
1223
1224
  if (recovered.draft)
@@ -1391,7 +1392,11 @@ export class OwnedUiSessionPresenter {
1391
1392
  }
1392
1393
  let result;
1393
1394
  try {
1394
- result = await this.backend.workflows.executeWorkflow(shareSurface === undefined ? request : { ...request, signal: shareSurface.signal });
1395
+ result = await this.backend.workflows.executeWorkflow(shareSurface === undefined ? request : {
1396
+ ...request,
1397
+ signal: shareSurface.signal,
1398
+ onProgress: message => { shareSurface.setMessage?.(message); this.#terminal.requestRender(); },
1399
+ });
1395
1400
  }
1396
1401
  finally {
1397
1402
  if (operationSurface) {
@@ -1,7 +1,7 @@
1
1
  import type { PiTuiPointerSurface } from "../../integrations/pi/tui-runtime/contracts.js";
2
2
  import type { OwnedUiViewportSettings } from "../../contracts/owned-ui/index.js";
3
3
  import { type TranscriptViewportFrame, type TranscriptViewportFrameInput } from "../../ui/components/transcript-viewport.js";
4
- import type { SelectionCopySnapshot } from "../../ui/components/selection-copy.js";
4
+ import { type SelectionCopySnapshot } from "../../ui/components/selection-copy.js";
5
5
  import type { PiShellEditorPort } from "../../integrations/pi/components/shell-shared-facade.js";
6
6
  import type { PasteEvent } from "./paste-protocol.js";
7
7
  export interface SessionViewportControllerOptions {
@@ -64,7 +64,7 @@ export declare class SessionViewportController {
64
64
  setOverlaySurfaces(surfaces: readonly PiTuiPointerSurface[] | null): void;
65
65
  get inputGeometryReady(): boolean;
66
66
  compose(input: Omit<TranscriptViewportFrameInput, "pointerPosition">): TranscriptViewportFrame;
67
- composeDockOnly(dockRows: readonly string[], width: number, height: number, explicitCopyDockRows?: number): TranscriptViewportFrame | null;
67
+ composeDockOnly(dockRows: readonly string[], width: number, height: number, copyableDockRows?: TranscriptViewportFrameInput["copyableDockRows"]): TranscriptViewportFrame | null;
68
68
  /** Returns true when document wrapping may have changed. */
69
69
  setConfig(config: OwnedUiViewportSettings): boolean;
70
70
  resumeFollowing(): void;
@@ -3,6 +3,7 @@ import { TranscriptViewport } from "../../ui/components/transcript-viewport.js";
3
3
  import { readVisibleHyperlinks } from "../../ui/components/visible-hyperlinks.js";
4
4
  import { routeMouseInput } from "../../ui/components/mouse.js";
5
5
  import { scrollForTrackPage, scrollForThumbRow, scrollbarSelectionRows, scrollbarWheelRows } from "../../ui/components/scrollbar.js";
6
+ import { literalSelectionCopySnapshot } from "../../ui/components/selection-copy.js";
6
7
  function withinTailControl(region, column, row) {
7
8
  return row >= region.rowStart && row <= region.rowEnd && column >= region.columnStart && column <= region.columnEnd;
8
9
  }
@@ -22,6 +23,7 @@ export class SessionViewportController {
22
23
  #pasteDiagnosticRequest = 0;
23
24
  #viewport = new TranscriptViewport();
24
25
  #config = {
26
+ timeFormat: "8:00 PM",
25
27
  scrollbarAppearance: "auto",
26
28
  scrollbarStyle: "thin",
27
29
  scrollbarSpeed: "normal",
@@ -165,16 +167,18 @@ export class SessionViewportController {
165
167
  }
166
168
  return frame;
167
169
  }
168
- composeDockOnly(dockRows, width, height, explicitCopyDockRows = 0) {
169
- return this.#viewport.composeDockOnly(dockRows, width, height, explicitCopyDockRows);
170
+ composeDockOnly(dockRows, width, height, copyableDockRows = []) {
171
+ return this.#viewport.composeDockOnly(dockRows, width, height, copyableDockRows);
170
172
  }
171
173
  /** Returns true when document wrapping may have changed. */
172
174
  setConfig(config) {
173
- const appearanceChanged = config.scrollbarAppearance !== this.#config.scrollbarAppearance;
174
- this.#config = config;
175
- this.#viewport.setConfig(config);
175
+ const normalized = { ...config, timeFormat: config.timeFormat ?? "8:00 PM" };
176
+ const layoutChanged = normalized.scrollbarAppearance !== this.#config.scrollbarAppearance
177
+ || normalized.timeFormat !== this.#config.timeFormat;
178
+ this.#config = normalized;
179
+ this.#viewport.setConfig(normalized);
176
180
  this.#requestRender();
177
- return appearanceChanged;
181
+ return layoutChanged;
178
182
  }
179
183
  resumeFollowing() {
180
184
  if (!this.#enabled)
@@ -302,12 +306,10 @@ export class SessionViewportController {
302
306
  });
303
307
  }
304
308
  if (data === "\u0003") {
305
- if (editorActive && this.#editor.hasSelection()) {
306
- if (this.#viewport.clearSelection())
307
- this.#requestRender();
308
- }
309
- else if (this.#viewport.hasSelection) {
310
- const copySelection = this.#viewport.captureSelectedText("explicit");
309
+ // Invariant: the newest complete-frame gesture owns explicit copy even if an
310
+ // older editor word/line selection remains painted beneath it.
311
+ if (this.#viewport.hasSelection) {
312
+ const copySelection = this.#viewport.captureSelectedText();
311
313
  this.#viewport.clearSelection();
312
314
  this.#stopSelectionAutoScroll();
313
315
  this.#requestRender();
@@ -315,6 +317,10 @@ export class SessionViewportController {
315
317
  ? { data: "", consumed: true }
316
318
  : { data: "", consumed: true, copySelection };
317
319
  }
320
+ if (editorActive && this.#editor.hasSelection()) {
321
+ if (this.#viewport.clearSelection())
322
+ this.#requestRender();
323
+ }
318
324
  }
319
325
  const previousPrompt = SHIFT_UP_INPUTS.has(data) || this.#editor.matchesTerminalKey(data, "alt+home");
320
326
  if (editorActive && allowWheel && (previousPrompt || SHIFT_DOWN_INPUTS.has(data))) {
@@ -541,6 +547,12 @@ export class SessionViewportController {
541
547
  const editorRow = pendingEditorClick.row - this.#editorPointerFrame.rowStart + 1;
542
548
  this.#editor.handlePointer({ kind: "press", button: 0, column: pendingEditorClick.column, row: editorRow });
543
549
  this.#editor.handlePointer({ kind: "release", button: 0, column: pendingEditorClick.column, row: editorRow });
550
+ if (this.#copyOnSelect) {
551
+ const selected = this.#editor.selectedText?.();
552
+ if (selected !== undefined) {
553
+ completedCopy = literalSelectionCopySnapshot(selected, this.#viewport.selectionRevision) ?? undefined;
554
+ }
555
+ }
544
556
  }
545
557
  forceRepaint = true;
546
558
  repaint = true;
@@ -98,8 +98,6 @@ export declare class OwnedUiTerminalHost implements OwnedUiTerminalHostContract<
98
98
  active(): OwnedUiHostedPresenter | null;
99
99
  requestRender(from: OwnedUiHostedPresenter, force?: boolean): void;
100
100
  start(): void;
101
- /** Hidden resident tabs retain engine/status work but stop producing terminal animation frames. */
102
- setPresentationVisible(visible: boolean): void;
103
101
  /** Closes one presenter. Closing the last one ends the terminal. */
104
102
  close(presenter: OwnedUiHostedPresenter): Promise<void>;
105
103
  dispose(): Promise<void>;
@@ -42,8 +42,6 @@ export class OwnedUiTerminalHost {
42
42
  #focused = false;
43
43
  #pointerReporting = false;
44
44
  #started = false;
45
- #presentationVisible = true;
46
- #releaseVisibilityHold;
47
45
  #ending;
48
46
  constructor(options) {
49
47
  this.#customViewport = options.layout === "custom-viewport";
@@ -148,8 +146,10 @@ export class OwnedUiTerminalHost {
148
146
  active() {
149
147
  return this.#active;
150
148
  }
149
+ // Invariant: resident tab visibility never gates rendering here; a hidden tab keeps painting into its
150
+ // resident terminal, and the native holder alone withholds inactive surfaces from attach clients.
151
151
  requestRender(from, force = false) {
152
- if (this.#presentationVisible && from === this.#active)
152
+ if (from === this.#active)
153
153
  this.runtime.requestRender(force);
154
154
  }
155
155
  start() {
@@ -157,26 +157,9 @@ export class OwnedUiTerminalHost {
157
157
  return;
158
158
  this.#started = true;
159
159
  this.runtime.start();
160
- if (!this.#presentationVisible)
161
- this.#releaseVisibilityHold = this.runtime.beginPresentationHold();
162
160
  if (this.#customViewport)
163
161
  this.#setPointerReporting(true);
164
162
  }
165
- /** Hidden resident tabs retain engine/status work but stop producing terminal animation frames. */
166
- setPresentationVisible(visible) {
167
- if (this.#presentationVisible === visible)
168
- return;
169
- this.#presentationVisible = visible;
170
- if (!this.#started || this.#ending !== undefined)
171
- return;
172
- if (visible) {
173
- this.#releaseVisibilityHold?.();
174
- this.#releaseVisibilityHold = undefined;
175
- }
176
- else if (this.#releaseVisibilityHold === undefined) {
177
- this.#releaseVisibilityHold = this.runtime.beginPresentationHold();
178
- }
179
- }
180
163
  /** Closes one presenter. Closing the last one ends the terminal. */
181
164
  close(presenter) {
182
165
  if (this.#ending !== undefined || !this.#presenters.has(presenter))
package/dist/cli/tabs.js CHANGED
@@ -132,9 +132,24 @@ function status(result) {
132
132
  `detachment: ${String(result.detachmentMode ?? "unknown")}${result.detachmentVerified === false ? " (not verified)" : ""}`,
133
133
  `tabs: ${String(result.tabs ?? 0)}${Object.keys(byStatus).length > 0 ? ` (${Object.entries(byStatus).map(([key, value]) => `${key} ${String(value)}`).join(", ")})` : ""}`,
134
134
  `clients: ${String(result.clients ?? 0)}`,
135
+ ...startsAndLifecycle(result),
135
136
  `limits: ${Object.entries(limits).map(([key, value]) => `${key} ${String(value)}`).join(", ")}`,
136
137
  `counters: ${Object.entries(counters).map(([key, value]) => `${key} ${String(value)}`).join(", ")}`,
137
138
  ...(Array.isArray(result.logs) ? result.logs.map(path => `log: ${String(path)}`) : []),
138
139
  ];
139
140
  return `${lines.join("\n")}\n`;
140
141
  }
142
+ /** Lifecycle work running this long means a terminal's tab requests are stuck. */
143
+ const LIFECYCLE_STALL_MS = 10_000;
144
+ function startsAndLifecycle(result) {
145
+ const lines = [];
146
+ const starts = result.starts;
147
+ if (starts)
148
+ lines.push(`starts: active ${String(starts.active ?? 0)}, waiting ${String(starts.interactiveWaiting ?? 0)}, recovering ${String(starts.recoverySlots ?? 0)}`);
149
+ const lifecycle = result.lifecycle;
150
+ if (lifecycle) {
151
+ const oldest = typeof lifecycle.oldestMs === "number" ? lifecycle.oldestMs : 0;
152
+ lines.push(`lifecycle: pending ${String(lifecycle.pending ?? 0)}, oldest ${oldest}ms${oldest > LIFECYCLE_STALL_MS ? " (stalled)" : ""}`);
153
+ }
154
+ return lines;
155
+ }
@@ -87,5 +87,5 @@ export declare function composeOwnedUiApplication(options?: OwnedUiCompositionOp
87
87
  export declare function composeOwnedUi(options?: OwnedUiCompositionOptions): Promise<OwnedUiComposition>;
88
88
  export declare function bindResidentTabBridge(tabBridge: TabBridgeClient, backend: Pick<ComposedSessionBackend, "identity" | "session" | "workflows" | "generateResidentTabName">, recovery?: Pick<ResidentTabRecovery, "settled"> | null, options?: {
89
89
  readonly autoName?: boolean;
90
- readonly onVisibility?: (visible: boolean) => void;
91
90
  }): Promise<() => void>;
91
+ export declare function correlateResidentTabSubmission(recovery: Pick<ResidentTabRecovery, "correlated" | "settled">, backend: Pick<ComposedSessionBackend, "identity" | "session">, submissionId: string, entryId: string): Promise<void>;
@@ -12,6 +12,8 @@ import { createPiSessionPresenters } from "../integrations/pi/session-presenters
12
12
  import { ClipboardDiagnosticCapture } from "../app/session-shell/clipboard-diagnostics.js";
13
13
  import { createOwnedUiClipboardServices } from "../app/session-shell/clipboard-services.js";
14
14
  import { createPiKeybindingsHost } from "../integrations/pi/components/shell-shared-facade.js";
15
+ import { projectResidentTabShortcuts } from "../features/resident-tab/shortcut-projection.js";
16
+ import { readShortcutBindingsFile } from "../features/resident-tab/shortcut-bindings-file.js";
15
17
  import { OwnedUiSessionPresenter, OwnedUiTerminalHost, sessionTerminalHostOptions, } from "../app/session-shell/session-shell.js";
16
18
  import { OwnedSettingsManager } from "../ui/settings/manager.js";
17
19
  import { createPiTerminalBridge } from "../integrations/pi/tui-runtime/presentation-adapter.js";
@@ -164,13 +166,8 @@ export async function composeOwnedUi(options = {}) {
164
166
  const recoveredTabInput = await tabRecovery?.initialize(currentBackendSessionFile(backend), backend.identity.sessionId);
165
167
  if (tabBridge !== null && settings !== null && ownedSurfaces)
166
168
  tabBridge.accent(settings.value("accentColor"));
167
- let residentTabVisible = true;
168
- let applyResidentTabVisibility = () => { };
169
169
  let removeControllerBoundaryInput = () => { };
170
- const unsubscribeTabBridge = tabBridge === null ? () => { } : await bindResidentTabBridge(tabBridge, backend, tabRecovery, {
171
- autoName: settings?.value("tabsAutoName") ?? true,
172
- onVisibility: visible => { residentTabVisible = visible; applyResidentTabVisibility(); },
173
- });
170
+ const unsubscribeTabBridge = tabBridge === null ? () => { } : await bindResidentTabBridge(tabBridge, backend, tabRecovery, { autoName: settings?.value("tabsAutoName") ?? true });
174
171
  let releaseNotes = null;
175
172
  let releaseNotesFailure;
176
173
  if (ownedSurfaces) {
@@ -259,7 +256,18 @@ export async function composeOwnedUi(options = {}) {
259
256
  ? new ClipboardDiagnosticCapture(clipboardDestination) : null;
260
257
  // Invariant: process-wide services are created once here and borrowed by every session shell. The
261
258
  // keybinding registry is applied before any presenter is built, so none of them reads Pi's defaults.
262
- const keybindings = createPiKeybindingsHost({ profile: ownedSurfaces ? "a1" : "pi", agentDir: backend.identity.agentDir });
259
+ const keybindingsHost = createPiKeybindingsHost({ profile: ownedSurfaces ? "a1" : "pi", agentDir: backend.identity.agentDir });
260
+ // Invariant: the resident host dispatches and labels the tab shortcuts this child projects
261
+ // from its effective declarations, so a customization reload republishes the projection.
262
+ const publishTabShortcuts = () => tabBridge?.shortcuts(projectResidentTabShortcuts({
263
+ configured: readShortcutBindingsFile(backend.identity.agentDir),
264
+ reserved: keybindingsHost.manager.getEffectiveConfig(),
265
+ }).assignments);
266
+ const keybindings = tabBridge === null ? keybindingsHost : {
267
+ ...keybindingsHost,
268
+ reload: () => { keybindingsHost.reload(); publishTabShortcuts(); },
269
+ };
270
+ publishTabShortcuts();
263
271
  const clipboardServices = ownedSurfaces ? createOwnedUiClipboardServices() : null;
264
272
  let createdTerminalHost;
265
273
  let terminalHost;
@@ -289,7 +297,7 @@ export async function composeOwnedUi(options = {}) {
289
297
  stallNoticeSeconds: 300,
290
298
  admit: input => tabRecovery.admit({ ...input, incarnation: options.tab.incarnation }),
291
299
  dispatched: () => tabRecovery.dispatched(),
292
- correlated: (submissionId, entryId) => tabRecovery.correlated(submissionId, entryId),
300
+ correlated: (submissionId, entryId) => correlateResidentTabSubmission(tabRecovery, backend, submissionId, entryId),
293
301
  checkpoint: text => tabRecovery.checkpoint(text),
294
302
  gracefulStop: sessionFile => tabRecovery.gracefulStop(sessionFile),
295
303
  ...(recoveredTabInput === undefined ? {} : { recovered: recoveredTabInput }),
@@ -322,7 +330,6 @@ export async function composeOwnedUi(options = {}) {
322
330
  // the host and paints once attached.
323
331
  terminalHost = createdTerminalHost = new OwnedUiTerminalHost(sessionTerminalHostOptions(presenterOptions));
324
332
  if (tabBridge !== null) {
325
- applyResidentTabVisibility = () => terminalHost.setPresentationVisible(residentTabVisible);
326
333
  removeControllerBoundaryInput = terminalHost.runtime.addPreInputListener(data => ({
327
334
  data: tabBridge.consumeControllerBoundaryInput(data),
328
335
  }));
@@ -375,7 +382,6 @@ export async function composeOwnedUi(options = {}) {
375
382
  exitNotice = import("../app/session-shell/exit-notice.js")
376
383
  .then(module => module.armExitNotice(backend, exitNoticePath), () => null);
377
384
  presenter.start();
378
- applyResidentTabVisibility();
379
385
  void announceNewerRelease().catch(() => undefined);
380
386
  },
381
387
  flush: () => backend.session.flushEvents(),
@@ -420,14 +426,38 @@ export async function bindResidentTabBridge(tabBridge, backend, recovery = null,
420
426
  tabBridge.status("starting");
421
427
  const currentSessionFile = () => currentBackendSessionFile(backend);
422
428
  let pendingAutoName = null;
429
+ const isDefaultName = (name) => name == null || /^agent(?: \d+)?$/i.test(name);
430
+ const currentSessionName = () => backend.session.view().status.footer?.sessionName ?? null;
423
431
  const announceSession = () => {
424
- const name = backend.session.view().status.footer?.sessionName ?? null;
425
- const nameSource = name === pendingAutoName ? "auto" : name === null || /^agent(?: \d+)?$/i.test(name) ? "default" : "user";
432
+ const name = currentSessionName();
433
+ const nameSource = name === pendingAutoName ? "auto" : isDefaultName(name) ? "default" : "user";
426
434
  tabBridge.session(currentSessionFile(), name, nameSource);
427
435
  };
428
436
  let working = false;
429
437
  let lastTurnFailed = false;
430
438
  let autoNameAttempted = false;
439
+ let autoNameArmed = false;
440
+ // Invariant: naming launches once per tab during an agent run, as soon as its prompt is projected,
441
+ // and runs beside the turn instead of waiting for it to settle.
442
+ const launchAutoName = () => {
443
+ if (!autoNameArmed || autoNameAttempted || options.autoName !== true || !isDefaultName(currentSessionName()))
444
+ return;
445
+ const prompt = backend.session.view().transcript.find(block => block.kind === "user")?.text.trim();
446
+ if (!prompt)
447
+ return;
448
+ autoNameAttempted = true;
449
+ void import("../features/resident-tab/index.js").then(({ generateAutoName }) => generateAutoName(prompt, request => backend.generateResidentTabName(request.prompt, request.maxTokens, request.signal))).then(async (name) => {
450
+ // Invariant: a manual rename made while generation was pending owns both the session and the tab.
451
+ if (!isDefaultName(currentSessionName()))
452
+ return;
453
+ pendingAutoName = name;
454
+ const result = await backend.workflows.executeWorkflow({ command: "name", argument: name });
455
+ if (result.outcome === "completed")
456
+ tabBridge.session(currentSessionFile(), name, "auto");
457
+ else if (pendingAutoName === name)
458
+ pendingAutoName = null;
459
+ }).catch(() => { pendingAutoName = null; });
460
+ };
431
461
  const reportStatus = (lifecycle) => {
432
462
  const view = backend.session.view();
433
463
  const pendingRequests = view.dialog == null ? 0 : 1;
@@ -441,12 +471,14 @@ export async function bindResidentTabBridge(tabBridge, backend, recovery = null,
441
471
  };
442
472
  announceSession();
443
473
  const unsubscribeCommands = typeof tabBridge.onCommand === "function" ? tabBridge.onCommand(command => {
444
- if (command.type === "visibility") {
445
- options.onVisibility?.(command.visible);
446
- }
447
- else if (command.type === "rename") {
474
+ // Invariant: visibility stays decoded for generation-1 peers but never pauses rendering; a hidden tab
475
+ // keeps its resident terminal current while the holder withholds only its client surfaces.
476
+ if (command.type === "rename") {
448
477
  void backend.workflows.executeWorkflow({ command: "name", argument: command.name }).catch(() => { });
449
478
  }
479
+ else if (command.type === "route") {
480
+ void backend.workflows.executeWorkflow({ command: command.route, argument: "" }).catch(() => { });
481
+ }
450
482
  else if (command.type === "stop") {
451
483
  void backend.session.dispose().catch(() => { });
452
484
  }
@@ -461,24 +493,17 @@ export async function bindResidentTabBridge(tabBridge, backend, recovery = null,
461
493
  if (wasWorking && !working && recovery !== null) {
462
494
  void recovery.settled(currentSessionFile()).catch(() => tabBridge.degraded(true));
463
495
  }
464
- if (wasWorking && !working && options.autoName === true && !autoNameAttempted) {
465
- autoNameAttempted = true;
466
- const view = backend.session.view();
467
- const currentName = view.status.footer?.sessionName;
468
- const prompt = view.transcript.find(block => block.kind === "user")?.text.trim();
469
- if (prompt && (currentName == null || /^agent(?: \d+)?$/i.test(currentName))) {
470
- void import("../features/resident-tab/index.js").then(({ generateAutoName }) => generateAutoName(prompt, request => backend.generateResidentTabName(request.prompt, request.maxTokens, request.signal))).then(async (name) => {
471
- pendingAutoName = name;
472
- const result = await backend.workflows.executeWorkflow({ command: "name", argument: name });
473
- if (result.outcome === "completed")
474
- tabBridge.session(currentSessionFile(), name, "auto");
475
- else if (pendingAutoName === name)
476
- pendingAutoName = null;
477
- }).catch(() => { pendingAutoName = null; });
478
- }
479
- }
480
496
  }
497
+ if (event.type === "agent-run-started") {
498
+ autoNameArmed = true;
499
+ launchAutoName();
500
+ }
501
+ // Rationale: Pi starts the run before it projects the user message, so the prompt may arrive later.
502
+ if (event.type === "transcript-block" || event.type === "session-view")
503
+ launchAutoName();
481
504
  if (event.type === "agent-run-settled") {
505
+ launchAutoName();
506
+ autoNameArmed = false;
482
507
  lastTurnFailed = !event.successful && !event.aborted;
483
508
  tabBridge.prompt(event.aborted);
484
509
  reportStatus();
@@ -493,6 +518,14 @@ export async function bindResidentTabBridge(tabBridge, backend, recovery = null,
493
518
  unsubscribeEvents();
494
519
  };
495
520
  }
521
+ export async function correlateResidentTabSubmission(recovery, backend, submissionId, entryId) {
522
+ await recovery.correlated(submissionId, entryId);
523
+ // Concurrency: a normal prompt command can resolve after the ready transition already fired.
524
+ // Re-read lifecycle only after correlation is active; a concurrent ready observer and this path
525
+ // safely race because recovery consumes the active entry once and retirement is idempotent.
526
+ if (backend.session.view().lifecycle !== "busy")
527
+ await recovery.settled(currentBackendSessionFile(backend));
528
+ }
496
529
  function currentBackendSessionFile(backend) {
497
530
  const direct = backend.identity.currentSessionFile?.();
498
531
  if (direct !== undefined && direct !== null)
@@ -514,6 +547,7 @@ function quitOutroSettingsSnapshot(settings) {
514
547
  }
515
548
  function viewportSettingsSnapshot(settings) {
516
549
  return {
550
+ timeFormat: settings.value("timeFormat"),
517
551
  scrollbarAppearance: settings.value("scrollbarAppearance"),
518
552
  scrollbarStyle: settings.value("scrollbarStyle"),
519
553
  scrollbarSpeed: settings.value("scrollbarSpeed"),
@@ -3,7 +3,7 @@ export type UiAccentColor = "purple" | "blue" | "cyan" | "green" | "orange" | "p
3
3
  export { OWNED_UI_EXTENSION_CONTRACT_VERSION, OWNED_UI_EXTENSION_RENDER_CALLBACKS, OWNED_UI_EXTENSION_UI_CALLBACKS, OWNED_UI_EXTENSION_UI_PROPERTIES, assertOwnedUiExtensionUiPort, } from "./extension-ui.js";
4
4
  export type { OwnedUiExtensionAutocompleteItem, OwnedUiExtensionAutocompleteProvider, OwnedUiExtensionAutocompleteProviderFactory, OwnedUiExtensionAutocompleteSuggestions, OwnedUiExtensionComponent, OwnedUiExtensionComponentFactory, OwnedUiExtensionComponentFactoryContext, OwnedUiExtensionCustomFactory, OwnedUiExtensionCustomOptions, OwnedUiExtensionDialogOptions, OwnedUiExtensionEditorComponent, OwnedUiExtensionEditorFactory, OwnedUiExtensionEditorThemePort, OwnedUiExtensionEntryRenderInput, OwnedUiExtensionFooterDataPort, OwnedUiExtensionFooterFactory, OwnedUiExtensionInputListener, OwnedUiExtensionKeybindingsPort, OwnedUiExtensionMessageRenderInput, OwnedUiExtensionNotificationSeverity, OwnedUiExtensionOverlayAnchor, OwnedUiExtensionOverlayHandle, OwnedUiExtensionOverlayMargin, OwnedUiExtensionOverlayOptions, OwnedUiExtensionRenderCallback, OwnedUiExtensionRendererPort, OwnedUiExtensionRuntimePort, OwnedUiExtensionSelectListThemePort, OwnedUiExtensionSizeValue, OwnedUiExtensionTerminalPort, OwnedUiExtensionThemeBackground, OwnedUiExtensionThemeColor, OwnedUiExtensionThemeInfo, OwnedUiExtensionThemePort, OwnedUiExtensionToolRenderContext, OwnedUiExtensionUiCallback, OwnedUiExtensionUiPort, OwnedUiExtensionUiProperty, OwnedUiExtensionWidgetOptions, OwnedUiExtensionWidgetPlacement, OwnedUiExtensionWorkingIndicatorOptions, } from "./extension-ui.js";
5
5
  export { OWNED_UI_CONTRACT_VERSION } from "./model.js";
6
- export type { OwnedUiBackgroundSettingsPort, OwnedUiBackgroundStyle, OwnedUiBlockStatus, OwnedUiCommand, OwnedUiCommandOutcome, OwnedUiCorrelationId, OwnedUiCustomization, OwnedUiDiagnostics, OwnedUiDialog, OwnedUiEditorState, OwnedUiEntityId, OwnedUiEvent, OwnedUiFooterView, OwnedUiImageAttachment, OwnedUiLifecycle, OwnedUiModelInfo, OwnedUiOverlay, OwnedUiPromptSuggestionGeneratorPort, OwnedUiPromptSuggestionIdentity, OwnedUiPromptSuggestionReasoning, OwnedUiPromptSuggestionRequest, OwnedUiPromptSuggestionResult, OwnedUiPromptSuggestionState, OwnedUiQuitOutroSettings, OwnedUiQuitOutroSettingsPort, OwnedUiSessionId, OwnedUiSessionViewModel, OwnedUiSeverity, OwnedUiSlotId, OwnedUiSnapshot, OwnedUiStatusView, OwnedUiTerminalSurface, OwnedUiThinkingLevel, OwnedUiToolRendering, OwnedUiToolResultPart, OwnedUiToolState, OwnedUiTranscriptBlock, OwnedUiTranscriptBlockKind, OwnedUiTranscriptImageReference, OwnedUiUsageView, OwnedUiViewportSettings, OwnedUiViewportSettingsPort, } from "./model.js";
6
+ export type { OwnedUiBackgroundSettingsPort, OwnedUiBackgroundStyle, OwnedUiBlockStatus, OwnedUiCommand, OwnedUiCommandOutcome, OwnedUiCorrelationId, OwnedUiCustomization, OwnedUiDiagnostics, OwnedUiDialog, OwnedUiEditorState, OwnedUiEntityId, OwnedUiEvent, OwnedUiFooterView, OwnedUiImageAttachment, OwnedUiLifecycle, OwnedUiModelInfo, OwnedUiOverlay, OwnedUiPromptSuggestionGeneratorPort, OwnedUiPromptSuggestionIdentity, OwnedUiPromptSuggestionReasoning, OwnedUiPromptSuggestionRequest, OwnedUiPromptSuggestionResult, OwnedUiPromptSuggestionState, OwnedUiQuitOutroSettings, OwnedUiQuitOutroSettingsPort, OwnedUiSessionId, OwnedUiSessionViewModel, OwnedUiSeverity, OwnedUiSlotId, OwnedUiSnapshot, OwnedUiStatusView, OwnedUiTerminalSurface, OwnedUiThinkingLevel, OwnedUiTimeFormat, OwnedUiToolRendering, OwnedUiToolResultPart, OwnedUiToolState, OwnedUiTranscriptBlock, OwnedUiTranscriptBlockKind, OwnedUiTranscriptImageReference, OwnedUiUsageView, OwnedUiViewportSettings, OwnedUiViewportSettingsPort, } from "./model.js";
7
7
  export type { OwnedUiExtensionPort, OwnedUiSessionBackend, OwnedUiSessionCatalogPort, OwnedUiSessionFactory, OwnedUiSessionIdentityPort, OwnedUiSessionPort, OwnedUiSessionRequest, OwnedUiSessionSettingsPort, OwnedUiWorkflowPort, } from "./session-backend.js";
8
8
  export type { OwnedUiDialogHost, OwnedUiInputSurface, OwnedUiPresenterHost, OwnedUiSessionPresenter, OwnedUiSessionPresenters, OwnedUiShortcutDescription, OwnedUiTerminalHost, OwnedUiTranscriptRendererPort, } from "./session-presenters.js";
9
9
  export { OWNED_UI_HIDDEN_COMMAND_NAMES, OWNED_UI_MODELS_COMMAND_NAME, OWNED_UI_WORKFLOW_COMMAND_NAMES, } from "./session-workflows.js";
@@ -53,7 +53,10 @@ export interface OwnedUiPromptSuggestionGeneratorPort {
53
53
  generate(request: OwnedUiPromptSuggestionRequest): Promise<OwnedUiPromptSuggestionResult>;
54
54
  }
55
55
  export type OwnedUiThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
56
+ export type OwnedUiTimeFormat = "20:00" | "8:00 PM";
56
57
  export interface OwnedUiViewportSettings {
58
+ /** Omitted by older SDK callers; bare A1 composition always supplies the owned default. */
59
+ readonly timeFormat?: OwnedUiTimeFormat;
57
60
  readonly scrollbarAppearance: "auto" | "always" | "hidden";
58
61
  readonly scrollbarStyle: "thin" | "thick";
59
62
  /** normal is baseline; fast is 2x normal; high is normal plus fast. */
@@ -49,6 +49,8 @@ export interface OwnedUiWorkflowRequest {
49
49
  readonly cwdOverride?: string;
50
50
  /** Cancellation for an owned operation surface such as `/share`. */
51
51
  readonly signal?: AbortSignal;
52
+ /** Progress label for that operation surface, e.g. when `/share` picks its upload destination. */
53
+ readonly onProgress?: (message: string) => void;
52
54
  readonly treeSummary?: {
53
55
  readonly summarize: boolean;
54
56
  readonly customInstructions?: string;
@@ -272,6 +274,7 @@ export interface OwnedUiSessionSettingsSnapshot {
272
274
  readonly autocompleteMaxVisible: number;
273
275
  readonly quietStartup: boolean | "header";
274
276
  readonly defaultProjectTrust: "ask" | "always" | "never";
277
+ readonly sessionShareDestination: "auto" | "gist" | "radius";
275
278
  readonly clearOnShrink: boolean;
276
279
  readonly showTerminalProgress: boolean;
277
280
  readonly tuiMode: "regular" | "fullscreen";
@@ -289,7 +292,7 @@ export type OwnedUiJsonValue = null | boolean | number | string | readonly Owned
289
292
  /** The layer that installs a setting's live effect. */
290
293
  export type OwnedUiSettingOwner = "agent" | "shell" | "terminal" | "startup" | "shutdown" | "installation";
291
294
  /** Engine settings whose live effect an owner may bind. */
292
- export type OwnedUiSessionSettingKey = "autoCompact" | "showImages" | "imageWidthCells" | "autoResizeImages" | "blockImages" | "enableSkillCommands" | "steeringMode" | "followUpMode" | "transport" | "httpIdleTimeoutMs" | "cacheWarmingMode" | "modelThinkingLevels" | "theme" | "hideThinkingBlock" | "mermaidRenderingMode" | "showCacheMissNotices" | "collapseChangelog" | "enableInstallTelemetry" | "quietStartup" | "defaultProjectTrust" | "doubleEscapeAction" | "treeFilterMode" | "showHardwareCursor" | "editorPaddingX" | "outputPad" | "autocompleteMaxVisible" | "clearOnShrink" | "showTerminalProgress" | "tuiMode" | "fullscreenExitOutput" | "fullscreenScrollbar" | "fullscreenCopyOnSelect" | "fullscreenWheelScrollLines" | "warnings";
295
+ export type OwnedUiSessionSettingKey = "autoCompact" | "showImages" | "imageWidthCells" | "autoResizeImages" | "blockImages" | "enableSkillCommands" | "steeringMode" | "followUpMode" | "transport" | "httpIdleTimeoutMs" | "cacheWarmingMode" | "modelThinkingLevels" | "theme" | "hideThinkingBlock" | "mermaidRenderingMode" | "showCacheMissNotices" | "collapseChangelog" | "enableInstallTelemetry" | "quietStartup" | "defaultProjectTrust" | "sessionShareDestination" | "doubleEscapeAction" | "treeFilterMode" | "showHardwareCursor" | "editorPaddingX" | "outputPad" | "autocompleteMaxVisible" | "clearOnShrink" | "showTerminalProgress" | "tuiMode" | "fullscreenExitOutput" | "fullscreenScrollbar" | "fullscreenCopyOnSelect" | "fullscreenWheelScrollLines" | "warnings";
293
296
  export interface OwnedUiSettingEffectHandler {
294
297
  /** Install one value in the active owner. Handlers must be idempotent and reversible. */
295
298
  apply(value: OwnedUiJsonValue): void | Promise<void>;