@timurproko/a1 0.2.7-dev.1275 → 0.2.7-dev.1285

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 (220) hide show
  1. package/README.md +5 -1
  2. package/dist/app/session-shell/apps-dialog.d.ts +1 -1
  3. package/dist/app/session-shell/apps-dialog.js +2 -1
  4. package/dist/app/session-shell/dialog-coordinator.d.ts +4 -5
  5. package/dist/app/session-shell/dialog-coordinator.js +41 -12
  6. package/dist/app/session-shell/input-route.d.ts +23 -0
  7. package/dist/app/session-shell/input-route.js +59 -0
  8. package/dist/app/session-shell/session-selectors.d.ts +3 -3
  9. package/dist/app/session-shell/session-selectors.js +7 -2
  10. package/dist/app/session-shell/session-shell-root.d.ts +4 -68
  11. package/dist/app/session-shell/session-shell-root.js +6 -2
  12. package/dist/app/session-shell/session-shell.js +9 -13
  13. package/dist/app/session-shell/shell-host.js +2 -2
  14. package/dist/app/session-shell/shell-options.d.ts +65 -0
  15. package/dist/app/session-shell/shell-options.js +1 -0
  16. package/dist/app/session-shell/viewport-pointer.js +5 -1
  17. package/dist/app/session-shell/workflow-router.d.ts +4 -2
  18. package/dist/app/session-shell/workflow-router.js +12 -0
  19. package/dist/cli/dispatch.js +27 -1
  20. package/dist/cli/packages.js +18 -2
  21. package/dist/cli/session-context.js +6 -2
  22. package/dist/composition/owned-ui.js +20 -8
  23. package/dist/composition/session-naming.js +1 -1
  24. package/dist/composition/session-runtime-registry.d.ts +2 -0
  25. package/dist/composition/session-runtime-registry.js +49 -9
  26. package/dist/composition/settings-route-host.js +1 -0
  27. package/dist/contracts/agent-engine/package-ports.d.ts +10 -14
  28. package/dist/contracts/agent-engine/package-ports.js +5 -9
  29. package/dist/contracts/owned-ui/session-workflows.d.ts +6 -0
  30. package/dist/contracts/owned-ui/shell-components.d.ts +10 -0
  31. package/dist/contracts/presentation/component.d.ts +7 -0
  32. package/dist/contracts/presentation/index.d.ts +3 -0
  33. package/dist/contracts/presentation/index.js +4 -0
  34. package/dist/contracts/presentation/progress-palette.generated.d.ts +25 -1
  35. package/dist/contracts/presentation/progress-palette.generated.js +2 -135
  36. package/dist/contracts/presentation/progress-spinner.d.ts +7 -0
  37. package/dist/contracts/presentation/progress-spinner.js +1 -0
  38. package/dist/features/launch/session-context.d.ts +8 -0
  39. package/dist/features/launch/session-context.js +19 -10
  40. package/dist/features/owned-ui/project-trust-dialog.d.ts +1 -1
  41. package/dist/features/owned-ui/project-trust-dialog.js +5 -5
  42. package/dist/features/owned-ui/project-trust-prompt.js +2 -2
  43. package/dist/features/owned-ui/reference-screen-app.d.ts +2 -0
  44. package/dist/features/owned-ui/reference-screen-app.js +12 -5
  45. package/dist/features/owned-ui/session-fork-prompt.d.ts +2 -1
  46. package/dist/features/owned-ui/session-fork-prompt.js +11 -5
  47. package/dist/features/owned-ui/settings-app.d.ts +1 -1
  48. package/dist/features/owned-ui/settings-app.js +20 -13
  49. package/dist/features/owned-ui/settings-model-dialog.js +3 -3
  50. package/dist/features/owned-ui/settings-spinner-preview.d.ts +9 -0
  51. package/dist/features/owned-ui/settings-spinner-preview.js +29 -0
  52. package/dist/features/session-naming/context.d.ts +17 -0
  53. package/dist/features/session-naming/context.js +39 -0
  54. package/dist/features/session-naming/controller.d.ts +1 -5
  55. package/dist/features/session-naming/controller.js +7 -4
  56. package/dist/features/session-naming/generate.d.ts +2 -1
  57. package/dist/features/session-naming/generate.js +14 -10
  58. package/dist/features/session-naming/index.d.ts +1 -1
  59. package/dist/foundation/lifecycle/index.d.ts +3 -1
  60. package/dist/foundation/lifecycle/index.js +3 -1
  61. package/dist/foundation/lifecycle/session-claim-lock.d.ts +2 -2
  62. package/dist/foundation/lifecycle/session-claim-lock.js +36 -10
  63. package/dist/foundation/lifecycle/session-context-retry.d.ts +2 -0
  64. package/dist/foundation/lifecycle/session-context-retry.js +17 -0
  65. package/dist/foundation/lifecycle/session-repository-context.d.ts +7 -1
  66. package/dist/foundation/lifecycle/session-repository-context.js +105 -39
  67. package/dist/foundation/lifecycle/session-worktree-entry.d.ts +3 -0
  68. package/dist/foundation/lifecycle/session-worktree-entry.js +87 -0
  69. package/dist/foundation/release/automatic-update.js +2 -2
  70. package/dist/foundation/release/bootstrap.js +19 -3
  71. package/dist/foundation/release/release-gc.js +20 -5
  72. package/dist/foundation/release/release-state.d.ts +12 -3
  73. package/dist/foundation/release/release-state.js +55 -24
  74. package/dist/foundation/release/release-use.d.ts +10 -0
  75. package/dist/foundation/release/release-use.js +70 -0
  76. package/dist/foundation/release/update-activation.js +2 -2
  77. package/dist/foundation/release/update-recovery.js +2 -2
  78. package/dist/foundation/release/update.js +1 -1
  79. package/dist/foundation/release/warmup.js +8 -9
  80. package/dist/foundation/session-writer-lock/index.d.ts +2 -2
  81. package/dist/foundation/session-writer-lock/index.js +82 -12
  82. package/dist/foundation/startup/startup-descriptor.js +2 -2
  83. package/dist/foundation/terminal-cleanup/fatal-diagnostic.d.ts +2 -0
  84. package/dist/foundation/terminal-cleanup/fatal-diagnostic.js +59 -0
  85. package/dist/foundation/terminal-cleanup/fatal-exit.js +1 -29
  86. package/dist/integrations/pi/components/deferred-selector.d.ts +6 -0
  87. package/dist/integrations/pi/components/deferred-selector.js +40 -0
  88. package/dist/integrations/pi/components/login-dialog-loader.d.ts +3 -0
  89. package/dist/integrations/pi/components/login-dialog-loader.js +57 -0
  90. package/dist/integrations/pi/components/login-links.d.ts +6 -0
  91. package/dist/integrations/pi/components/login-links.js +31 -0
  92. package/dist/integrations/pi/components/login-text.d.ts +7 -0
  93. package/dist/integrations/pi/components/login-text.js +17 -0
  94. package/dist/integrations/pi/components/modal-frame.d.ts +5 -0
  95. package/dist/integrations/pi/components/modal-frame.js +30 -2
  96. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
  97. package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
  98. package/dist/integrations/pi/components/share-operation-dialog.d.ts +2 -1
  99. package/dist/integrations/pi/components/share-operation-dialog.js +13 -5
  100. package/dist/integrations/pi/components/shell-footer-status.d.ts +2 -1
  101. package/dist/integrations/pi/components/shell-footer-status.js +15 -8
  102. package/dist/integrations/pi/components/shell-selectors-dialogs.d.ts +11 -8
  103. package/dist/integrations/pi/components/shell-selectors-dialogs.js +36 -35
  104. package/dist/integrations/pi/components/shell-session-info-reference.d.ts +1 -1
  105. package/dist/integrations/pi/components/shell-session-info-reference.js +55 -49
  106. package/dist/integrations/pi/components/theme.d.ts +2 -0
  107. package/dist/integrations/pi/components/theme.js +4 -0
  108. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  109. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
  110. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  111. package/dist/integrations/pi/components/upstream/components/auth-url.d.ts +16 -0
  112. package/dist/integrations/pi/components/upstream/components/auth-url.js +49 -0
  113. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  114. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  115. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  116. package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
  117. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  118. package/dist/integrations/pi/components/upstream/components/extension-selector.d.ts +1 -0
  119. package/dist/integrations/pi/components/upstream/components/extension-selector.js +22 -11
  120. package/dist/integrations/pi/components/upstream/components/login-dialog.d.ts +3 -0
  121. package/dist/integrations/pi/components/upstream/components/login-dialog.js +216 -0
  122. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  123. package/dist/integrations/pi/components/upstream/components/oauth-selector.d.ts +19 -0
  124. package/dist/integrations/pi/components/upstream/components/oauth-selector.js +123 -0
  125. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
  126. package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
  127. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  128. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  129. package/dist/integrations/pi/components/upstream/components/session-footer.js +22 -13
  130. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  131. package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
  132. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  133. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  134. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
  135. package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
  136. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  137. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  138. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  139. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
  140. package/dist/integrations/pi/components/upstream/components/tool-execution.js +1 -1
  141. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
  142. package/dist/integrations/pi/components/upstream/components/tree-selector.js +1 -1
  143. package/dist/integrations/pi/components/upstream/components/trust-selector.d.ts +2 -0
  144. package/dist/integrations/pi/components/upstream/components/trust-selector.js +30 -13
  145. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  146. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +1 -1
  147. package/dist/integrations/pi/components/upstream/history/editor-core.js +1 -1
  148. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  149. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  150. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  151. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  152. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  153. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  154. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  155. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  156. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
  157. package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
  158. package/dist/integrations/pi/engine/adapter.d.ts +3 -1
  159. package/dist/integrations/pi/engine/adapter.js +24 -6
  160. package/dist/integrations/pi/engine/changelog.js +5 -2
  161. package/dist/integrations/pi/engine/delivery-retention.d.ts +7 -0
  162. package/dist/integrations/pi/engine/delivery-retention.js +66 -0
  163. package/dist/integrations/pi/engine/event-delivery.d.ts +17 -1
  164. package/dist/integrations/pi/engine/event-delivery.js +25 -3
  165. package/dist/integrations/pi/engine/extension-ui-binding.d.ts +2 -1
  166. package/dist/integrations/pi/engine/extension-ui-binding.js +45 -0
  167. package/dist/integrations/pi/engine/host-ports.d.ts +2 -0
  168. package/dist/integrations/pi/engine/host.d.ts +3 -0
  169. package/dist/integrations/pi/engine/host.js +2 -0
  170. package/dist/integrations/pi/engine/package-integration.js +19 -4
  171. package/dist/integrations/pi/engine/pending-delivery.d.ts +4 -1
  172. package/dist/integrations/pi/engine/pending-delivery.js +51 -18
  173. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  174. package/dist/integrations/pi/engine/runtime-integration.d.ts +8 -0
  175. package/dist/integrations/pi/engine/runtime-integration.js +58 -9
  176. package/dist/integrations/pi/engine/session-cwd-recovery.d.ts +11 -0
  177. package/dist/integrations/pi/engine/session-cwd-recovery.js +18 -0
  178. package/dist/integrations/pi/engine/session-runtime.d.ts +3 -0
  179. package/dist/integrations/pi/engine/session-runtime.js +2 -0
  180. package/dist/integrations/pi/engine/session-selection.d.ts +3 -2
  181. package/dist/integrations/pi/engine/session-selection.js +25 -5
  182. package/dist/integrations/pi/engine/transcript-image-assets.d.ts +3 -0
  183. package/dist/integrations/pi/engine/transcript-image-assets.js +65 -14
  184. package/dist/integrations/pi/engine/view-state.d.ts +14 -0
  185. package/dist/integrations/pi/engine/view-state.js +17 -0
  186. package/dist/integrations/pi/engine/workflow-runner.d.ts +2 -0
  187. package/dist/integrations/pi/engine/workflow-runner.js +47 -26
  188. package/dist/integrations/pi/engine/worktree-tools.d.ts +4 -0
  189. package/dist/integrations/pi/engine/worktree-tools.js +26 -0
  190. package/dist/integrations/pi/session-presenters/components.d.ts +2 -1
  191. package/dist/integrations/pi/session-presenters/components.js +12 -10
  192. package/dist/integrations/pi/session-presenters/presenters.d.ts +3 -1
  193. package/dist/integrations/pi/session-presenters/presenters.js +2 -2
  194. package/dist/integrations/pi/startup-public.d.ts +1 -1
  195. package/dist/integrations/pi/startup-public.js +16 -20
  196. package/dist/integrations/pi/startup-public.manifest.json +29 -29
  197. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  198. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
  199. package/dist/product-identity.json +1 -1
  200. package/dist/runtime-payload-inventory.json +5027 -5027
  201. package/dist/ui/components/index.d.ts +1 -1
  202. package/dist/ui/components/index.js +1 -1
  203. package/dist/ui/components/list-block.d.ts +2 -2
  204. package/dist/ui/components/list-block.js +4 -3
  205. package/dist/ui/components/progress-status.d.ts +7 -0
  206. package/dist/ui/components/progress-status.js +21 -0
  207. package/dist/ui/components/value-menu.d.ts +1 -1
  208. package/dist/ui/components/value-menu.js +4 -2
  209. package/dist/ui/settings/declarations.d.ts +16 -4
  210. package/dist/ui/settings/declarations.js +13 -4
  211. package/dist/ui/settings/early-accent.d.ts +24 -0
  212. package/docs/architecture/internal-naming.md +1 -1
  213. package/docs/architecture/project-structure.md +7 -11
  214. package/docs/features/session-exports.md +1 -1
  215. package/docs/features/session-naming.md +8 -6
  216. package/docs/features/worktrees.md +38 -0
  217. package/docs/local-worktree-cleanup.md +27 -4
  218. package/docs/openspec-archive-automation.md +30 -4
  219. package/docs/worktree-link-recovery.md +2 -2
  220. package/package.json +5 -5
@@ -1,139 +1,6 @@
1
1
  /**
2
2
  * Generated by scripts/pi/sync-progress-palette.ts from A1's named accent projection
3
- * over pinned Pi 1.5.1 (MIT), commit dd30101cfc5b0609411dd80b6f93adbc14db14cf. Do not edit directly.
3
+ * over pinned Pi 1.5.2 (MIT), commit b4afdddf44e059c67ccf5097e5317d913521b470. Do not edit directly.
4
4
  */
5
- export const SHARED_PROGRESS_PALETTE = Object.freeze({
6
- "blue": {
7
- "dark": {
8
- "truecolor": {
9
- "accent": "\u001b[38;2;130;160;241m",
10
- "border": "\u001b[38;2;116;102;197m"
11
- },
12
- "256color": {
13
- "accent": "\u001b[38;5;111m",
14
- "border": "\u001b[38;5;98m"
15
- }
16
- },
17
- "light": {
18
- "truecolor": {
19
- "accent": "\u001b[38;2;63;96;226m",
20
- "border": "\u001b[38;2;83;67;154m"
21
- },
22
- "256color": {
23
- "accent": "\u001b[38;5;62m",
24
- "border": "\u001b[38;5;60m"
25
- }
26
- }
27
- },
28
- "purple": {
29
- "dark": {
30
- "truecolor": {
31
- "accent": "\u001b[38;2;167;152;215m",
32
- "border": "\u001b[38;2;105;115;167m"
33
- },
34
- "256color": {
35
- "accent": "\u001b[38;5;140m",
36
- "border": "\u001b[38;5;61m"
37
- }
38
- },
39
- "light": {
40
- "truecolor": {
41
- "accent": "\u001b[38;2;116;89;180m",
42
- "border": "\u001b[38;2;68;77;130m"
43
- },
44
- "256color": {
45
- "accent": "\u001b[38;5;97m",
46
- "border": "\u001b[38;5;60m"
47
- }
48
- }
49
- },
50
- "cyan": {
51
- "dark": {
52
- "truecolor": {
53
- "accent": "\u001b[38;2;93;179;186m",
54
- "border": "\u001b[38;2;74;128;146m"
55
- },
56
- "256color": {
57
- "accent": "\u001b[38;5;73m",
58
- "border": "\u001b[38;5;66m"
59
- }
60
- },
61
- "light": {
62
- "truecolor": {
63
- "accent": "\u001b[38;2;40;122;129m",
64
- "border": "\u001b[38;2;40;89;106m"
65
- },
66
- "256color": {
67
- "accent": "\u001b[38;5;30m",
68
- "border": "\u001b[38;5;23m"
69
- }
70
- }
71
- },
72
- "green": {
73
- "dark": {
74
- "truecolor": {
75
- "accent": "\u001b[38;2;104;183;141m",
76
- "border": "\u001b[38;2;75;132;120m"
77
- },
78
- "256color": {
79
- "accent": "\u001b[38;5;72m",
80
- "border": "\u001b[38;5;66m"
81
- }
82
- },
83
- "light": {
84
- "truecolor": {
85
- "accent": "\u001b[38;2;51;126;88m",
86
- "border": "\u001b[38;2;41;93;82m"
87
- },
88
- "256color": {
89
- "accent": "\u001b[38;5;65m",
90
- "border": "\u001b[38;5;23m"
91
- }
92
- }
93
- },
94
- "orange": {
95
- "dark": {
96
- "truecolor": {
97
- "accent": "\u001b[38;2;231;135;83m",
98
- "border": "\u001b[38;2;178;89;79m"
99
- },
100
- "256color": {
101
- "accent": "\u001b[38;5;173m",
102
- "border": "\u001b[38;5;131m"
103
- }
104
- },
105
- "light": {
106
- "truecolor": {
107
- "accent": "\u001b[38;2;174;80;16m",
108
- "border": "\u001b[38;2;133;57;49m"
109
- },
110
- "256color": {
111
- "accent": "\u001b[38;5;130m",
112
- "border": "\u001b[38;5;95m"
113
- }
114
- }
115
- },
116
- "pink": {
117
- "dark": {
118
- "truecolor": {
119
- "accent": "\u001b[38;2;223;122;199m",
120
- "border": "\u001b[38;2;150;91;171m"
121
- },
122
- "256color": {
123
- "accent": "\u001b[38;5;176m",
124
- "border": "\u001b[38;5;97m"
125
- }
126
- },
127
- "light": {
128
- "truecolor": {
129
- "accent": "\u001b[38;2;178;56;153m",
130
- "border": "\u001b[38;2;114;61;131m"
131
- },
132
- "256color": {
133
- "accent": "\u001b[38;5;132m",
134
- "border": "\u001b[38;5;60m"
135
- }
136
- }
137
- }
138
- });
5
+ export const SHARED_PROGRESS_PALETTE = Object.freeze({ "blue": { "dark": { "truecolor": { "accent": "\u001b[38;2;130;160;241m", "border": "\u001b[38;2;116;102;197m", "selectedBg": "\u001b[48;2;52;57;69m" }, "256color": { "accent": "\u001b[38;5;111m", "border": "\u001b[38;5;98m", "selectedBg": "\u001b[48;5;59m" } }, "light": { "truecolor": { "accent": "\u001b[38;2;63;96;226m", "border": "\u001b[38;2;83;67;154m", "selectedBg": "\u001b[48;2;243;244;246m" }, "256color": { "accent": "\u001b[38;5;62m", "border": "\u001b[38;5;60m", "selectedBg": "\u001b[48;5;255m" } } }, "purple": { "dark": { "truecolor": { "accent": "\u001b[38;2;167;152;215m", "border": "\u001b[38;2;105;115;167m", "selectedBg": "\u001b[48;2;58;56;66m" }, "256color": { "accent": "\u001b[38;5;140m", "border": "\u001b[38;5;61m", "selectedBg": "\u001b[48;5;59m" } }, "light": { "truecolor": { "accent": "\u001b[38;2;116;89;180m", "border": "\u001b[38;2;68;77;130m", "selectedBg": "\u001b[48;2;243;243;245m" }, "256color": { "accent": "\u001b[38;5;97m", "border": "\u001b[38;5;60m", "selectedBg": "\u001b[48;5;255m" } } }, "cyan": { "dark": { "truecolor": { "accent": "\u001b[38;2;93;179;186m", "border": "\u001b[38;2;74;128;146m", "selectedBg": "\u001b[48;2;48;60;61m" }, "256color": { "accent": "\u001b[38;5;73m", "border": "\u001b[38;5;66m", "selectedBg": "\u001b[48;5;59m" } }, "light": { "truecolor": { "accent": "\u001b[38;2;40;122;129m", "border": "\u001b[38;2;40;89;106m", "selectedBg": "\u001b[48;2;241;244;244m" }, "256color": { "accent": "\u001b[38;5;30m", "border": "\u001b[38;5;23m", "selectedBg": "\u001b[48;5;255m" } } }, "green": { "dark": { "truecolor": { "accent": "\u001b[38;2;104;183;141m", "border": "\u001b[38;2;75;132;120m", "selectedBg": "\u001b[48;2;50;60;54m" }, "256color": { "accent": "\u001b[38;5;72m", "border": "\u001b[38;5;66m", "selectedBg": "\u001b[48;5;59m" } }, "light": { "truecolor": { "accent": "\u001b[38;2;51;126;88m", "border": "\u001b[38;2;41;93;82m", "selectedBg": "\u001b[48;2;242;244;243m" }, "256color": { "accent": "\u001b[38;5;65m", "border": "\u001b[38;5;23m", "selectedBg": "\u001b[48;5;255m" } } }, "orange": { "dark": { "truecolor": { "accent": "\u001b[38;2;231;135;83m", "border": "\u001b[38;2;178;89;79m", "selectedBg": "\u001b[48;2;67;54;48m" }, "256color": { "accent": "\u001b[38;5;173m", "border": "\u001b[38;5;131m", "selectedBg": "\u001b[48;5;59m" } }, "light": { "truecolor": { "accent": "\u001b[38;2;174;80;16m", "border": "\u001b[38;2;133;57;49m", "selectedBg": "\u001b[48;2;245;243;242m" }, "256color": { "accent": "\u001b[38;5;130m", "border": "\u001b[38;5;95m", "selectedBg": "\u001b[48;5;255m" } } }, "pink": { "dark": { "truecolor": { "accent": "\u001b[38;2;223;122;199m", "border": "\u001b[38;2;150;91;171m", "selectedBg": "\u001b[48;2;65;53;62m" }, "256color": { "accent": "\u001b[38;5;176m", "border": "\u001b[38;5;97m", "selectedBg": "\u001b[48;5;59m" } }, "light": { "truecolor": { "accent": "\u001b[38;2;178;56;153m", "border": "\u001b[38;2;114;61;131m", "selectedBg": "\u001b[48;2;245;243;245m" }, "256color": { "accent": "\u001b[38;5;132m", "border": "\u001b[38;5;60m", "selectedBg": "\u001b[48;5;255m" } } } });
139
6
  export const SHARED_PROGRESS_ACCENT_ANSI = SHARED_PROGRESS_PALETTE.blue.dark.truecolor.accent;
@@ -0,0 +1,7 @@
1
+ /** Owned indeterminate-progress styles; Current delegates to the pinned loader's dot frames. */
2
+ export type ProgressSpinnerStyle = "none" | "current" | "circle" | "diamond" | "square";
3
+ /** Profile-scoped live spinner choice, borrowed by owned status and operation components. */
4
+ export interface ProgressSpinnerSource {
5
+ readonly snapshot: () => ProgressSpinnerStyle;
6
+ readonly onChange: (listener: () => void) => () => void;
7
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -3,6 +3,10 @@ export { PRIMARY_SESSION_AGENT_ID } from "../../foundation/lifecycle/index.js";
3
3
  export type SessionContextRequest = {
4
4
  readonly action: "link-worktree";
5
5
  readonly path: string;
6
+ } | {
7
+ readonly action: "enter-worktree";
8
+ readonly branch: string;
9
+ readonly base?: string;
6
10
  } | {
7
11
  readonly action: "unlink-worktree";
8
12
  } | {
@@ -11,6 +15,7 @@ export type SessionContextRequest = {
11
15
  export type SessionContextOutcome = {
12
16
  readonly kind: "linked";
13
17
  readonly cwd: string;
18
+ readonly branch: string;
14
19
  } | {
15
20
  readonly kind: "unlinked";
16
21
  } | {
@@ -20,5 +25,8 @@ export type SessionContextOutcome = {
20
25
  export interface SessionContextRuntime {
21
26
  readonly runtimeId: string;
22
27
  readonly inspectProcess: (pid: number) => Promise<ProcessIdentity | null>;
28
+ readonly dataDir?: string;
29
+ readonly signal?: AbortSignal;
30
+ readonly retryBudgetMs?: number;
23
31
  }
24
32
  export declare function updateSessionRepositoryContext(identity: SessionRepositoryIdentity, request: SessionContextRequest, runtime: SessionContextRuntime): Promise<SessionContextOutcome>;
@@ -1,13 +1,22 @@
1
- import { clearSessionRepositoryContext, listSessionRepositoryWorktrees, setSessionRepositoryContext, } from "../../foundation/lifecycle/index.js";
1
+ import { clearSessionRepositoryContext, enterSessionRepositoryWorktree, listSessionRepositoryWorktrees, retrySessionCoordination, setSessionRepositoryContext, } from "../../foundation/lifecycle/index.js";
2
2
  export { PRIMARY_SESSION_AGENT_ID } from "../../foundation/lifecycle/index.js";
3
3
  export async function updateSessionRepositoryContext(identity, request, runtime) {
4
- const options = { runtimeId: runtime.runtimeId, inspectProcess: runtime.inspectProcess };
5
- if (request.action === "unlink-worktree") {
6
- await clearSessionRepositoryContext(identity, options);
7
- return { kind: "unlinked" };
8
- }
9
- if (request.action === "worktrees") {
10
- return { kind: "worktrees", entries: await listSessionRepositoryWorktrees(identity, options) };
11
- }
12
- return { kind: "linked", cwd: (await setSessionRepositoryContext(identity, request.path, options)).cwd };
4
+ const options = {
5
+ runtimeId: runtime.runtimeId, inspectProcess: runtime.inspectProcess,
6
+ ...(runtime.dataDir === undefined ? {} : { dataDir: runtime.dataDir }),
7
+ ...(runtime.signal === undefined ? {} : { signal: runtime.signal }),
8
+ };
9
+ return await retrySessionCoordination(async () => {
10
+ if (request.action === "enter-worktree") {
11
+ return { kind: "linked", ...await enterSessionRepositoryWorktree(identity, request.branch, request.base, options) };
12
+ }
13
+ if (request.action === "unlink-worktree") {
14
+ await clearSessionRepositoryContext(identity, options);
15
+ return { kind: "unlinked" };
16
+ }
17
+ if (request.action === "worktrees") {
18
+ return { kind: "worktrees", entries: await listSessionRepositoryWorktrees(identity, options) };
19
+ }
20
+ return { kind: "linked", ...await setSessionRepositoryContext(identity, request.path, options) };
21
+ }, runtime.retryBudgetMs ?? 8_000, runtime.signal);
13
22
  }
@@ -1,2 +1,2 @@
1
1
  /** Fixed startup-safe rendering only; project-derived presentation is forbidden before trust resolves. */
2
- export declare function renderProjectTrustDialog(cwd: string, options: readonly string[], selected: number, terminalWidth: number, terminalRows: number, accent: string, border: string): readonly string[];
2
+ export declare function renderProjectTrustDialog(cwd: string, options: readonly string[], selected: number, terminalWidth: number, terminalRows: number, accent: string, border: string, selectedBg: string): readonly string[];
@@ -6,12 +6,12 @@ const BOLD = "\u001b[1m";
6
6
  const RESET_BOLD = "\u001b[22m";
7
7
  const EXPLANATION = "This allows to load project settings and resources, install missing project packages, and execute project extensions.";
8
8
  /** Fixed startup-safe rendering only; project-derived presentation is forbidden before trust resolves. */
9
- export function renderProjectTrustDialog(cwd, options, selected, terminalWidth, terminalRows, accent, border) {
9
+ export function renderProjectTrustDialog(cwd, options, selected, terminalWidth, terminalRows, accent, border, selectedBg) {
10
10
  const width = Math.max(1, terminalWidth);
11
11
  const rule = `${border}${"─".repeat(width)}${RESET_FG}`;
12
- const title = ` ${BOLD}${accent}Trust project folder?${RESET_FG}${RESET_BOLD}`;
12
+ const title = ` ${BOLD}${accent}Trust Project Folder?${RESET_FG}${RESET_BOLD}`;
13
13
  const path = ` ${MUTED}${sanitize(cwd)}${RESET_FG}`;
14
- const choices = options.map((label, index) => choice(label, selected === index, accent));
14
+ const choices = options.map((label, index) => choice(label, selected === index, accent, selectedBg));
15
15
  const closeKey = displayShortcutKeyLabel(DIALOG_CLOSE_SHORTCUT_HINT.key);
16
16
  const hint = ` ${DIM}↑↓${MUTED} navigate ${DIM}Enter${MUTED} select ${DIM}${closeKey}${MUTED} ${DIALOG_CLOSE_SHORTCUT_HINT.action}${RESET_FG}`;
17
17
  const explanation = wrap(EXPLANATION, Math.max(1, width - 2)).map(line => ` ${line}`);
@@ -33,8 +33,8 @@ export function renderProjectTrustDialog(cwd, options, selected, terminalWidth,
33
33
  return choiceWindow(choices, selected, 2);
34
34
  return [choices[selected] ?? choices[0] ?? ""];
35
35
  }
36
- function choice(label, selected, accent) {
37
- return selected ? ` ${accent}→ ${label}${RESET_FG}` : ` ${label}`;
36
+ function choice(label, selected, accent, selectedBg) {
37
+ return selected ? ` ${selectedBg}${accent}→ ${RESET_FG}${label}\u001b[49m` : ` ${label}`;
38
38
  }
39
39
  function choiceWindow(choices, selected, capacity) {
40
40
  const start = Math.min(Math.max(0, selected - Math.floor(capacity / 2)), Math.max(0, choices.length - capacity));
@@ -67,7 +67,7 @@ export function createConsoleProjectTrustPrompt(options = {}) {
67
67
  const render = () => {
68
68
  const width = Math.max(renderBareDialog ? 1 : 20, output.columns ?? 80);
69
69
  const rows = Math.max(1, output.rows ?? 24);
70
- const lines = (renderBareDialog?.(cwd, choices.map(choice => choice.label), selected, width, rows, palette.accent, palette.border) ?? [
70
+ const lines = (renderBareDialog?.(cwd, choices.map(choice => choice.label), selected, width, rows, palette.accent, palette.border, palette.selectedBg) ?? [
71
71
  `${BOLD}${ACCENT}Trust project folder?${RESET_FG}${RESET_BOLD}`,
72
72
  cwd,
73
73
  "",
@@ -205,5 +205,5 @@ function clipAnsiSafe(line, width) {
205
205
  index += 1;
206
206
  visible += 1;
207
207
  }
208
- return `${output}${RESET_FG}${RESET_BOLD}`;
208
+ return `${output}${RESET_FG}${RESET_BOLD}${line.includes("\u001b[48;") ? "\u001b[49m" : ""}`;
209
209
  }
@@ -23,6 +23,8 @@ export interface ReferenceScreenOptions {
23
23
  readonly id: string;
24
24
  readonly title: string;
25
25
  readonly document: ReferenceDocumentProvider;
26
+ /** In-place documents put their shortcut row inside the bottom rule like other dock dialogs. */
27
+ readonly presentation?: "screen" | "dialog";
26
28
  /** The reader's scroll settings, read on every frame so a live change is honored. */
27
29
  readonly scrollSettings: () => OwnedUiViewportSettings;
28
30
  /** Enables owned text selection for document routes that explicitly opt in. */
@@ -4,12 +4,16 @@ import { GLOBAL_SCOPE, PLAIN_THEME, RAIL_COLUMNS, ShortcutRegistry, ScrollbarRai
4
4
  const SCOPE = "reference-screen";
5
5
  /** Rows above the document: the top rule. */
6
6
  const HEADER_ROWS = 1;
7
- /** Rows below the document: the bottom rule and the hint line. */
7
+ /** Base rows below the document: the bottom rule and the hint line. */
8
8
  const FOOTER_ROWS = 2;
9
9
  // Compatibility: the transcript rail stays lit this long after a scroll, and repaints just after.
10
10
  const SCROLL_LINGER_MS = 900;
11
11
  const SCROLL_LINGER_REPAINT_MS = 925;
12
12
  const LOADING_NOTICE = "Loading…";
13
+ /** Keeps document rendering and paging on the same height after reserving dialog footer spacing. */
14
+ function referenceBodyHeight(height, dialog) {
15
+ return Math.max(0, height - HEADER_ROWS - FOOTER_ROWS - (dialog ? 1 : 0));
16
+ }
13
17
  export const REFERENCE_SCREEN_SHORTCUTS = new ShortcutRegistry();
14
18
  REFERENCE_SCREEN_SHORTCUTS.declare({ key: "up", scope: SCOPE, description: "Scroll up", section: "Navigate", hint: { keys: "↑↓", does: "scroll" } }, "up");
15
19
  REFERENCE_SCREEN_SHORTCUTS.declare({ key: "down", scope: SCOPE, description: "Scroll down", section: "Navigate", hint: { keys: "↑↓", does: "scroll" } }, "down");
@@ -47,6 +51,7 @@ const KEYS = {
47
51
  export class ReferenceScreenApp {
48
52
  id;
49
53
  #title;
54
+ #dialog;
50
55
  #document;
51
56
  #scrollSettings;
52
57
  #selection;
@@ -66,6 +71,7 @@ export class ReferenceScreenApp {
66
71
  constructor(options) {
67
72
  this.id = options.id;
68
73
  this.#title = options.title;
74
+ this.#dialog = options.presentation === "dialog";
69
75
  this.#document = options.document;
70
76
  this.#scrollSettings = options.scrollSettings;
71
77
  this.#selection = options.selection === undefined ? undefined : new ReferenceDocumentSelection(options.selection);
@@ -93,7 +99,7 @@ export class ReferenceScreenApp {
93
99
  const settings = this.#scrollSettings();
94
100
  const reservesRail = settings.scrollbarAppearance !== "hidden";
95
101
  const contentWidth = reservesRail ? Math.max(0, rect.width - RAIL_COLUMNS) : rect.width;
96
- const bodyHeight = Math.max(0, rect.height - HEADER_ROWS - FOOTER_ROWS);
102
+ const bodyHeight = referenceBodyHeight(rect.height, this.#dialog);
97
103
  const content = this.#content(contentWidth, theme);
98
104
  const body = [];
99
105
  const visibleDocumentRows = [];
@@ -158,7 +164,8 @@ export class ReferenceScreenApp {
158
164
  // Compatibility: the v2 reference screen frames its document between two border-coloured rules.
159
165
  const rule = theme.fg("border", "─".repeat(rect.width));
160
166
  // Invariant: dialog chrome shares the title's one-cell inset; document content keeps its own layout.
161
- const frame = [rule, ...withRail, rule, padToWidth(hint, rect.width)];
167
+ const footer = padToWidth(hint, rect.width);
168
+ const frame = this.#dialog ? [rule, ...withRail, "", footer, rule] : [rule, ...withRail, rule, footer];
162
169
  // Invariant: a rectangle too small for the chrome still gets exactly its rows, top first.
163
170
  return frame.slice(0, rect.height).concat(Array(Math.max(0, rect.height - frame.length)).fill(""));
164
171
  }
@@ -185,10 +192,10 @@ export class ReferenceScreenApp {
185
192
  this.#scrollBy(1);
186
193
  return { consumed: true };
187
194
  case "page-up":
188
- this.#scrollBy(-Math.max(1, host.getSize().height - HEADER_ROWS - FOOTER_ROWS));
195
+ this.#scrollBy(-Math.max(1, referenceBodyHeight(host.getSize().height, this.#dialog)));
189
196
  return { consumed: true };
190
197
  case "page-down":
191
- this.#scrollBy(Math.max(1, host.getSize().height - HEADER_ROWS - FOOTER_ROWS));
198
+ this.#scrollBy(Math.max(1, referenceBodyHeight(host.getSize().height, this.#dialog)));
192
199
  return { consumed: true };
193
200
  case "first":
194
201
  this.#scroll = 0;
@@ -5,4 +5,5 @@ export declare function createConsoleSessionForkPrompt(options?: {
5
5
  readonly output?: Writable;
6
6
  }): (request: {
7
7
  readonly sourceCwd: string;
8
- }) => Promise<boolean>;
8
+ readonly fallbackCwd?: string;
9
+ }) => Promise<boolean | "continue" | "fork" | "cancel">;
@@ -3,14 +3,17 @@ import { createInterface } from "node:readline";
3
3
  export function createConsoleSessionForkPrompt(options = {}) {
4
4
  const input = options.input ?? process.stdin;
5
5
  const output = options.output ?? process.stdout;
6
- return async ({ sourceCwd }) => {
7
- output.write(`Session found in different project: ${sourceCwd}\n`);
6
+ return async ({ sourceCwd, fallbackCwd }) => {
7
+ const recovering = fallbackCwd !== undefined;
8
+ output.write(recovering
9
+ ? `Session cwd does not exist: ${sourceCwd}\n1. Continue in ${fallbackCwd} (asks again next time)\n2. Fork into ${fallbackCwd} (new session ID, original kept)\n3. Cancel\n`
10
+ : `Session found in different project: ${sourceCwd}\n`);
8
11
  const wasFlowing = input.readableFlowing;
9
12
  const readline = createInterface({ input, output });
10
13
  try {
11
14
  return await new Promise((resolve, reject) => {
12
15
  const finish = (accepted) => { cleanup(); resolve(accepted); };
13
- const cancel = () => finish(false);
16
+ const cancel = () => finish(recovering ? "cancel" : false);
14
17
  const fail = (error) => { cleanup(); reject(error); };
15
18
  const cleanup = () => {
16
19
  readline.off("close", cancel);
@@ -20,8 +23,11 @@ export function createConsoleSessionForkPrompt(options = {}) {
20
23
  readline.once("close", cancel);
21
24
  readline.once("SIGINT", cancel);
22
25
  input.once("error", fail);
23
- readline.question("Fork this session into current directory? [y/N] ", answer => {
24
- finish(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
26
+ readline.question(recovering ? "Choose Continue, Fork, or Cancel [1/2/3]: " : "Fork this session into current directory? [y/N] ", answer => {
27
+ const choice = answer.trim().toLowerCase();
28
+ finish(recovering
29
+ ? choice === "1" || choice === "continue" ? "continue" : choice === "2" || choice === "fork" ? "fork" : "cancel"
30
+ : choice === "y" || choice === "yes");
25
31
  });
26
32
  });
27
33
  }
@@ -22,5 +22,5 @@ export declare class SettingsApp implements UiApp {
22
22
  onClose(_host: AppHostServices): void;
23
23
  render(rect: PaneRect, host: AppHostServices): readonly string[];
24
24
  onInput(data: string, host: AppHostServices): PaneInputResult;
25
- onMouse(event: PaneMouseEvent, _host: AppHostServices): PaneInputResult;
25
+ onMouse(event: PaneMouseEvent, host: AppHostServices): PaneInputResult;
26
26
  }
@@ -1,6 +1,7 @@
1
- import { DIALOG_CLOSE_SHORTCUT_HINT } from "../../contracts/presentation/index.js";
1
+ import { DIALOG_CLOSE_SHORTCUT_HINT, wrapChoiceIndex } from "../../contracts/presentation/index.js";
2
2
  import { GLOBAL_SCOPE, LineInput, PLAIN_THEME, ShortcutRegistry, assertNoShortcutConflicts, blockJumpTarget, configureDialogChoiceCapacity, configureDialogTextRows, configureDialogWidth, numericValues, RAIL_COLUMNS, renderCenteredDialogOverlay, renderDialogPanel, renderEmptyState, renderGroupHeader, renderListRow, renderNote, renderShortcutHintsWithClose, menuRowAt, regionAt, renderValueMenu, withScrollbarRail, stepperEnds, steppedValue, truncateToWidth, valueColumnFor, valueMenuFrame, blockRowSpan, displayWidth, humanizeLabel, humanizeTitle, indexOfKey, layoutList, moveSelection, rowKey, scrollForSelection, scrollbarGeometry, scrollbarWheelRows, selectableIndexes, } from "../../ui/components/index.js";
3
3
  import { SettingsScrollRail } from "./settings-scroll-rail.js";
4
+ import { SettingsSpinnerPreview } from "./settings-spinner-preview.js";
4
5
  import { SettingsEdits, replaceRecord, sameRecord } from "./settings-edits.js";
5
6
  import { SETTINGS_APP_ID } from "./settings-route.js";
6
7
  import { dialogWindow, modelDialogKey, modelDialogLines } from "./settings-model-dialog.js";
@@ -111,6 +112,8 @@ export class SettingsApp {
111
112
  void this.#session.load().then(() => host.requestRender());
112
113
  }
113
114
  onClose(_host) {
115
+ this.#menu?.preview?.dispose();
116
+ this.#menu = null;
114
117
  this.#edits.close();
115
118
  this.#search.input?.setFocused(false);
116
119
  this.#search.input = null;
@@ -235,12 +238,12 @@ export class SettingsApp {
235
238
  else if (row?.kind === "element" && typeof this.#edits.shown(row.value) === "number")
236
239
  this.#cycle(rows, selected, 1);
237
240
  else
238
- this.#openMenu(rows, selected, true);
241
+ this.#openMenu(rows, selected, host, true);
239
242
  return { consumed: true };
240
243
  }
241
244
  case "move-up":
242
245
  case "move-down":
243
- this.#select(rows, moveSelection(rows, selected, action === "move-down" ? 1 : -1));
246
+ this.#select(rows, moveSelection(rows, selected, action === "move-down" ? 1 : -1, true));
244
247
  return { consumed: true };
245
248
  case "page-up":
246
249
  case "page-down":
@@ -276,7 +279,7 @@ export class SettingsApp {
276
279
  return { consumed: false };
277
280
  }
278
281
  }
279
- onMouse(event, _host) {
282
+ onMouse(event, host) {
280
283
  const searchPointer = handleSettingsSearchPointer(this.#search, event, this.#panelTopForFrame);
281
284
  if (searchPointer !== null)
282
285
  return searchPointer;
@@ -367,14 +370,14 @@ export class SettingsApp {
367
370
  else if (this.#hoverRegion === "plus")
368
371
  this.#cycle(rows, index, 1);
369
372
  else if (this.#hoverRegion === "value")
370
- this.#openMenu(rows, index);
373
+ this.#openMenu(rows, index, host);
371
374
  }
372
375
  return { consumed: true };
373
376
  }
374
377
  const changed = previousKey !== this.#hoverKey || previousRegion !== this.#hoverRegion || rail.changed;
375
378
  return { consumed: event.kind !== "motion", render: changed };
376
379
  }
377
- #openMenu(rows, selected, selectCurrent = false) {
380
+ #openMenu(rows, selected, host, selectCurrent = false) {
378
381
  const row = rows[selected];
379
382
  if (row === undefined || row.kind !== "element")
380
383
  return;
@@ -406,10 +409,12 @@ export class SettingsApp {
406
409
  anchorKey,
407
410
  choices: entry.choices,
408
411
  keyboardOpened: selectCurrent,
412
+ preview: entry.backend === "a1" && entry.id === "spinnerStyle" ? new SettingsSpinnerPreview(() => host.requestRender()) : null,
409
413
  index: current,
410
414
  };
411
415
  }
412
416
  #closeMenu(menu) {
417
+ menu.preview?.dispose();
413
418
  this.#menu = null;
414
419
  if (!menu.keyboardOpened || this.#hoverKey !== menu.anchorKey)
415
420
  return;
@@ -472,10 +477,10 @@ export class SettingsApp {
472
477
  this.#structured = null;
473
478
  return { consumed: true };
474
479
  case "part-previous":
475
- open.index = Math.max(0, open.index - 1);
480
+ open.index = wrapChoiceIndex(open.index, -1, open.flags.length);
476
481
  return { consumed: true };
477
482
  case "part-next":
478
- open.index = Math.min(open.flags.length - 1, open.index + 1);
483
+ open.index = wrapChoiceIndex(open.index, 1, open.flags.length);
479
484
  return { consumed: true };
480
485
  case "part-change":
481
486
  this.#toggleFlag(open.index);
@@ -529,7 +534,7 @@ export class SettingsApp {
529
534
  // Compatibility: the keyboard starts from the value in effect rather than from the top.
530
535
  menu.index = menu.index < 0
531
536
  ? menu.current
532
- : Math.min(menu.choices.length - 1, Math.max(0, menu.index + (key === "down" ? 1 : -1)));
537
+ : wrapChoiceIndex(menu.index, key === "down" ? 1 : -1, menu.choices.length);
533
538
  }
534
539
  else if (key === "enter") {
535
540
  const value = menu.choices[menu.index];
@@ -577,7 +582,7 @@ export class SettingsApp {
577
582
  this.#jump(rows, target);
578
583
  return { consumed: true };
579
584
  }
580
- this.#select(rows, moveSelection(rows, selected, forward ? 1 : -1));
585
+ this.#select(rows, moveSelection(rows, selected, forward ? 1 : -1, true));
581
586
  return { consumed: true };
582
587
  }
583
588
  const before = input.getText();
@@ -720,14 +725,16 @@ export class SettingsApp {
720
725
  const menu = this.#menu;
721
726
  const anchor = menu === null ? undefined : this.#frameRows.find(candidate => candidate.key === menu.anchorKey);
722
727
  if (menu === null || anchor === undefined) {
728
+ menu?.preview?.dispose();
723
729
  this.#menuFrame = null;
724
730
  return lines;
725
731
  }
726
732
  const state = {
727
733
  choices: menu.choices.map(choice => displaySettingValue(menu.entry, choice)),
728
- ...(menu.entry.id === "accentColor" ? {
729
- previews: menu.choices.map(choice => theme.accentPreview?.(String(choice), "■") ?? ""),
730
- } : {}),
734
+ ...(menu.preview !== null ? { previews: menu.preview.frames(menu.choices, menu.index, theme) }
735
+ : menu.entry.id === "accentColor" ? {
736
+ previews: menu.choices.map(choice => theme.accentPreview?.(String(choice), "■") ?? ""),
737
+ } : {}),
731
738
  current: this.#edits.shown(menu.entry) === null ? null : displaySettingValue(menu.entry, this.#edits.shown(menu.entry)),
732
739
  index: menu.index,
733
740
  };
@@ -1,4 +1,4 @@
1
- import { DIALOG_BACK_SHORTCUT_HINT, DIALOG_CLOSE_SHORTCUT_HINT } from "../../contracts/presentation/index.js";
1
+ import { DIALOG_BACK_SHORTCUT_HINT, DIALOG_CLOSE_SHORTCUT_HINT, wrapChoiceIndex } from "../../contracts/presentation/index.js";
2
2
  import { LineInput, ShortcutRegistry, assertNoShortcutConflicts, configureDialogChoiceCapacity, configureDialogTextRows, handleLineInputKey, humanizeLabel, renderSteppedDialogPanel, } from "../../ui/components/index.js";
3
3
  import { changeFailure, structuredValue } from "./settings-edits.js";
4
4
  import { SETTINGS_APP_ID } from "./settings-route.js";
@@ -28,7 +28,7 @@ export function modelDialogKey(open, data, key, actions) {
28
28
  return { consumed: true };
29
29
  }
30
30
  if (action === "previous" || action === "next") {
31
- open.index = Math.min(Math.max(0, flags.length - 1), Math.max(0, open.index + (action === "next" ? 1 : -1)));
31
+ open.index = wrapChoiceIndex(open.index, action === "next" ? 1 : -1, flags.length);
32
32
  return { consumed: true };
33
33
  }
34
34
  if (action === "select") {
@@ -61,7 +61,7 @@ export function modelDialogKey(open, data, key, actions) {
61
61
  return { consumed: true };
62
62
  }
63
63
  if (action === "previous" || action === "next") {
64
- open.index = Math.min(Math.max(0, choices.length - 1), Math.max(0, open.index + (action === "next" ? 1 : -1)));
64
+ open.index = wrapChoiceIndex(open.index, action === "next" ? 1 : -1, choices.length);
65
65
  return { consumed: true };
66
66
  }
67
67
  if (action === "select") {
@@ -0,0 +1,9 @@
1
+ import type { UiTheme } from "../../ui/components/index.js";
2
+ import type { OwnedUiSettingValue } from "../../ui/settings/index.js";
3
+ /** One dropdown's focused spinner animation; unselected choices keep their representative frame. */
4
+ export declare class SettingsSpinnerPreview {
5
+ #private;
6
+ constructor(requestRender: () => void);
7
+ frames(choices: readonly OwnedUiSettingValue[], selected: number, theme: UiTheme): readonly string[];
8
+ dispose(): void;
9
+ }
@@ -0,0 +1,29 @@
1
+ import { isProgressSpinnerStyle, progressSpinnerFrame, PROGRESS_SPINNER_INTERVAL_MS, } from "../../ui/components/index.js";
2
+ /** One dropdown's focused spinner animation; unselected choices keep their representative frame. */
3
+ export class SettingsSpinnerPreview {
4
+ #requestRender;
5
+ #phase = 0;
6
+ #timer;
7
+ constructor(requestRender) {
8
+ this.#requestRender = requestRender;
9
+ }
10
+ frames(choices, selected, theme) {
11
+ const focused = choices[selected];
12
+ const animated = isProgressSpinnerStyle(focused) && focused !== "none";
13
+ if (animated && this.#timer === undefined) {
14
+ this.#timer = setInterval(() => { this.#phase += 1; this.#requestRender(); }, PROGRESS_SPINNER_INTERVAL_MS);
15
+ this.#timer.unref?.();
16
+ }
17
+ else if (!animated)
18
+ this.dispose();
19
+ return choices.map((choice, index) => {
20
+ const frame = isProgressSpinnerStyle(choice) ? progressSpinnerFrame(choice, index === selected ? this.#phase : 0) : "";
21
+ return frame === "" ? "" : theme.fg("accent", frame);
22
+ });
23
+ }
24
+ dispose() {
25
+ if (this.#timer !== undefined)
26
+ clearInterval(this.#timer);
27
+ this.#timer = undefined;
28
+ }
29
+ }
@@ -0,0 +1,17 @@
1
+ import type { OwnedUiTranscriptBlock } from "../../contracts/owned-ui/index.js";
2
+ export interface SessionNamingContext {
3
+ readonly cwd: string;
4
+ readonly branch: string | null;
5
+ readonly revision: string;
6
+ }
7
+ export declare function isGenericSessionName(value: string): boolean;
8
+ export interface SessionNamingTask {
9
+ readonly prompt: string;
10
+ readonly hints: string;
11
+ readonly discussion: readonly {
12
+ readonly role: "user" | "assistant";
13
+ readonly text: string;
14
+ }[];
15
+ readonly fallback: string;
16
+ }
17
+ export declare function sessionNamingTask(prompt: string, promptId: string, context: SessionNamingContext, transcript: readonly OwnedUiTranscriptBlock[], allowUnanchored: boolean): SessionNamingTask;