pi-agent-flow 1.8.39 → 2.0.0

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 (291) hide show
  1. package/README.md +33 -37
  2. package/agents/audit.md +18 -22
  3. package/agents/build.md +20 -22
  4. package/agents/craft.md +20 -27
  5. package/agents/debug.md +21 -28
  6. package/agents/ideas.md +18 -101
  7. package/agents/scout.md +15 -19
  8. package/dist/batch/batch-bash.d.ts +2 -2
  9. package/dist/batch/batch-bash.d.ts.map +1 -1
  10. package/dist/batch/batch-bash.js +3 -3
  11. package/dist/batch/batch-bash.js.map +1 -1
  12. package/dist/batch/constants.d.ts +19 -5
  13. package/dist/batch/constants.d.ts.map +1 -1
  14. package/dist/batch/constants.js +4 -3
  15. package/dist/batch/constants.js.map +1 -1
  16. package/dist/batch/execute.d.ts +0 -1
  17. package/dist/batch/execute.d.ts.map +1 -1
  18. package/dist/batch/execute.js +101 -10
  19. package/dist/batch/execute.js.map +1 -1
  20. package/dist/batch/fuzzy-edit.d.ts +0 -6
  21. package/dist/batch/fuzzy-edit.d.ts.map +1 -1
  22. package/dist/batch/fuzzy-edit.js +1 -1
  23. package/dist/batch/fuzzy-edit.js.map +1 -1
  24. package/dist/batch/index.d.ts.map +1 -1
  25. package/dist/batch/index.js +87 -16
  26. package/dist/batch/index.js.map +1 -1
  27. package/dist/batch/render.d.ts +0 -1
  28. package/dist/batch/render.d.ts.map +1 -1
  29. package/dist/batch/render.js +7 -101
  30. package/dist/batch/render.js.map +1 -1
  31. package/dist/batch/summary.d.ts +5 -0
  32. package/dist/batch/summary.d.ts.map +1 -0
  33. package/dist/batch/summary.js +101 -0
  34. package/dist/batch/summary.js.map +1 -0
  35. package/dist/{config.d.ts → config/config.d.ts} +34 -2
  36. package/dist/config/config.d.ts.map +1 -0
  37. package/dist/{config.js → config/config.js} +157 -9
  38. package/dist/config/config.js.map +1 -0
  39. package/dist/config/log.d.ts +27 -0
  40. package/dist/config/log.d.ts.map +1 -0
  41. package/dist/config/log.js +104 -0
  42. package/dist/config/log.js.map +1 -0
  43. package/dist/{settings-resolver.d.ts → config/settings-resolver.d.ts} +9 -2
  44. package/dist/config/settings-resolver.d.ts.map +1 -0
  45. package/dist/config/settings-resolver.js +275 -0
  46. package/dist/config/settings-resolver.js.map +1 -0
  47. package/dist/core/agents.d.ts.map +1 -0
  48. package/dist/{agents.js → core/agents.js} +11 -10
  49. package/dist/core/agents.js.map +1 -0
  50. package/dist/core/delegation.d.ts +24 -0
  51. package/dist/core/delegation.d.ts.map +1 -0
  52. package/dist/core/delegation.js +55 -0
  53. package/dist/core/delegation.js.map +1 -0
  54. package/dist/core/depth.d.ts.map +1 -0
  55. package/dist/{depth.js → core/depth.js} +9 -8
  56. package/dist/core/depth.js.map +1 -0
  57. package/dist/{executor.d.ts → core/executor.d.ts} +13 -3
  58. package/dist/core/executor.d.ts.map +1 -0
  59. package/dist/{executor.js → core/executor.js} +79 -15
  60. package/dist/core/executor.js.map +1 -0
  61. package/dist/{flow.d.ts → core/flow.d.ts} +4 -1
  62. package/dist/core/flow.d.ts.map +1 -0
  63. package/dist/{flow.js → core/flow.js} +179 -25
  64. package/dist/core/flow.js.map +1 -0
  65. package/dist/{session-mode.d.ts → core/session-mode.d.ts} +2 -1
  66. package/dist/core/session-mode.d.ts.map +1 -0
  67. package/dist/{session-mode.js → core/session-mode.js} +1 -1
  68. package/dist/core/session-mode.js.map +1 -0
  69. package/dist/core/session-registry.d.ts +16 -0
  70. package/dist/core/session-registry.d.ts.map +1 -0
  71. package/dist/core/session-registry.js +30 -0
  72. package/dist/core/session-registry.js.map +1 -0
  73. package/dist/core/transitions.d.ts.map +1 -0
  74. package/dist/{transitions.js → core/transitions.js} +1 -1
  75. package/dist/core/transitions.js.map +1 -0
  76. package/dist/flow/command.d.ts +8 -0
  77. package/dist/flow/command.d.ts.map +1 -0
  78. package/dist/flow/command.js +189 -0
  79. package/dist/flow/command.js.map +1 -0
  80. package/dist/flow/continuation.d.ts +16 -0
  81. package/dist/flow/continuation.d.ts.map +1 -0
  82. package/dist/flow/continuation.js +151 -0
  83. package/dist/flow/continuation.js.map +1 -0
  84. package/dist/flow/index.d.ts +15 -0
  85. package/dist/flow/index.d.ts.map +1 -0
  86. package/dist/flow/index.js +22 -0
  87. package/dist/flow/index.js.map +1 -0
  88. package/dist/flow/settings-command.d.ts +51 -0
  89. package/dist/flow/settings-command.d.ts.map +1 -0
  90. package/dist/flow/settings-command.js +851 -0
  91. package/dist/flow/settings-command.js.map +1 -0
  92. package/dist/flow/store.d.ts +26 -0
  93. package/dist/flow/store.d.ts.map +1 -0
  94. package/dist/flow/store.js +158 -0
  95. package/dist/flow/store.js.map +1 -0
  96. package/dist/flow/template-strings.d.ts +8 -0
  97. package/dist/flow/template-strings.d.ts.map +1 -0
  98. package/dist/flow/template-strings.js +39 -0
  99. package/dist/flow/template-strings.js.map +1 -0
  100. package/dist/flow/types.d.ts +55 -0
  101. package/dist/flow/types.d.ts.map +1 -0
  102. package/dist/flow/types.js +5 -0
  103. package/dist/flow/types.js.map +1 -0
  104. package/dist/flow/warp-command.d.ts +9 -0
  105. package/dist/flow/warp-command.d.ts.map +1 -0
  106. package/dist/flow/warp-command.js +405 -0
  107. package/dist/flow/warp-command.js.map +1 -0
  108. package/dist/index.d.ts +3 -1
  109. package/dist/index.d.ts.map +1 -1
  110. package/dist/index.js +115 -32
  111. package/dist/index.js.map +1 -1
  112. package/dist/{notify-state.d.ts → notify/notify-state.d.ts} +2 -1
  113. package/dist/notify/notify-state.d.ts.map +1 -0
  114. package/dist/notify/notify-state.js.map +1 -0
  115. package/dist/notify/notify.d.ts.map +1 -0
  116. package/dist/{notify.js → notify/notify.js} +3 -2
  117. package/dist/notify/notify.js.map +1 -0
  118. package/dist/{cli-args.d.ts → snapshot/cli-args.d.ts} +4 -2
  119. package/dist/snapshot/cli-args.d.ts.map +1 -0
  120. package/dist/{cli-args.js → snapshot/cli-args.js} +10 -1
  121. package/dist/snapshot/cli-args.js.map +1 -0
  122. package/dist/snapshot/index.d.ts +2 -0
  123. package/dist/snapshot/index.d.ts.map +1 -0
  124. package/dist/snapshot/index.js +2 -0
  125. package/dist/snapshot/index.js.map +1 -0
  126. package/dist/{reasoning-strip.d.ts → snapshot/reasoning-strip.d.ts} +0 -4
  127. package/dist/snapshot/reasoning-strip.d.ts.map +1 -0
  128. package/dist/{reasoning-strip.js → snapshot/reasoning-strip.js} +2 -2
  129. package/dist/snapshot/reasoning-strip.js.map +1 -0
  130. package/dist/{runner-events.d.ts → snapshot/runner-events.d.ts} +13 -1
  131. package/dist/snapshot/runner-events.d.ts.map +1 -0
  132. package/dist/{runner-events.js → snapshot/runner-events.js} +16 -4
  133. package/dist/snapshot/runner-events.js.map +1 -0
  134. package/dist/{snapshot.d.ts → snapshot/snapshot.d.ts} +29 -3
  135. package/dist/snapshot/snapshot.d.ts.map +1 -0
  136. package/dist/{snapshot.js → snapshot/snapshot.js} +347 -39
  137. package/dist/snapshot/snapshot.js.map +1 -0
  138. package/dist/{structured-output.d.ts → snapshot/structured-output.d.ts} +1 -1
  139. package/dist/snapshot/structured-output.d.ts.map +1 -0
  140. package/dist/{structured-output.js → snapshot/structured-output.js} +13 -0
  141. package/dist/snapshot/structured-output.js.map +1 -0
  142. package/dist/{flow-prompt.d.ts → steering/flow-prompt.d.ts} +2 -2
  143. package/dist/steering/flow-prompt.d.ts.map +1 -0
  144. package/dist/{flow-prompt.js → steering/flow-prompt.js} +3 -3
  145. package/dist/steering/flow-prompt.js.map +1 -0
  146. package/dist/{sliding-prompt.d.ts → steering/sliding-prompt.d.ts} +8 -7
  147. package/dist/steering/sliding-prompt.d.ts.map +1 -0
  148. package/dist/{sliding-prompt.js → steering/sliding-prompt.js} +15 -64
  149. package/dist/steering/sliding-prompt.js.map +1 -0
  150. package/dist/{tool-utils.d.ts → steering/tool-utils.d.ts} +1 -0
  151. package/dist/steering/tool-utils.d.ts.map +1 -0
  152. package/dist/{tool-utils.js → steering/tool-utils.js} +10 -3
  153. package/dist/steering/tool-utils.js.map +1 -0
  154. package/dist/{ask-user.d.ts → tools/ask-user.d.ts} +3 -15
  155. package/dist/tools/ask-user.d.ts.map +1 -0
  156. package/dist/tools/ask-user.js +778 -0
  157. package/dist/tools/ask-user.js.map +1 -0
  158. package/dist/{timed-bash.d.ts → tools/timed-bash.d.ts} +2 -7
  159. package/dist/tools/timed-bash.d.ts.map +1 -0
  160. package/dist/{timed-bash.js → tools/timed-bash.js} +2 -2
  161. package/dist/tools/timed-bash.js.map +1 -0
  162. package/dist/{web-tool.d.ts → tools/web-tool.d.ts} +1 -1
  163. package/dist/tools/web-tool.d.ts.map +1 -0
  164. package/dist/{web-tool.js → tools/web-tool.js} +8 -7
  165. package/dist/tools/web-tool.js.map +1 -0
  166. package/dist/tui/flow-colors.d.ts +55 -0
  167. package/dist/tui/flow-colors.d.ts.map +1 -0
  168. package/dist/tui/flow-colors.js +22 -0
  169. package/dist/tui/flow-colors.js.map +1 -0
  170. package/dist/{render-utils.d.ts → tui/render-utils.d.ts} +1 -1
  171. package/dist/tui/render-utils.d.ts.map +1 -0
  172. package/dist/{render-utils.js → tui/render-utils.js} +3 -3
  173. package/dist/tui/render-utils.js.map +1 -0
  174. package/dist/tui/render.d.ts +21 -0
  175. package/dist/tui/render.d.ts.map +1 -0
  176. package/dist/tui/render.js +813 -0
  177. package/dist/tui/render.js.map +1 -0
  178. package/dist/tui/scramble/algorithm.d.ts +7 -0
  179. package/dist/tui/scramble/algorithm.d.ts.map +1 -0
  180. package/dist/tui/scramble/algorithm.js +227 -0
  181. package/dist/tui/scramble/algorithm.js.map +1 -0
  182. package/dist/tui/scramble/constants.d.ts +99 -0
  183. package/dist/tui/scramble/constants.d.ts.map +1 -0
  184. package/dist/tui/scramble/constants.js +101 -0
  185. package/dist/tui/scramble/constants.js.map +1 -0
  186. package/dist/tui/scramble/index.d.ts +6 -0
  187. package/dist/tui/scramble/index.d.ts.map +1 -0
  188. package/dist/tui/scramble/index.js +6 -0
  189. package/dist/tui/scramble/index.js.map +1 -0
  190. package/dist/tui/scramble/manager.d.ts +48 -0
  191. package/dist/tui/scramble/manager.d.ts.map +1 -0
  192. package/dist/tui/scramble/manager.js +959 -0
  193. package/dist/tui/scramble/manager.js.map +1 -0
  194. package/dist/tui/scramble/utils.d.ts +18 -0
  195. package/dist/tui/scramble/utils.d.ts.map +1 -0
  196. package/dist/tui/scramble/utils.js +145 -0
  197. package/dist/tui/scramble/utils.js.map +1 -0
  198. package/dist/tui/single-select-layout.d.ts +17 -0
  199. package/dist/tui/single-select-layout.d.ts.map +1 -0
  200. package/dist/{single-select-layout.js → tui/single-select-layout.js} +8 -25
  201. package/dist/tui/single-select-layout.js.map +1 -0
  202. package/dist/types/flow.d.ts +110 -0
  203. package/dist/types/flow.d.ts.map +1 -0
  204. package/dist/{types.js → types/flow.js} +3 -54
  205. package/dist/types/flow.js.map +1 -0
  206. package/dist/types/index.d.ts +8 -0
  207. package/dist/types/index.d.ts.map +1 -0
  208. package/dist/types/index.js +7 -0
  209. package/dist/types/index.js.map +1 -0
  210. package/dist/types/output.d.ts +104 -0
  211. package/dist/types/output.d.ts.map +1 -0
  212. package/dist/types/output.js +5 -0
  213. package/dist/types/output.js.map +1 -0
  214. package/dist/types/ui.d.ts +24 -0
  215. package/dist/types/ui.d.ts.map +1 -0
  216. package/dist/types/ui.js +55 -0
  217. package/dist/types/ui.js.map +1 -0
  218. package/package.json +7 -4
  219. package/dist/agents.d.ts.map +0 -1
  220. package/dist/agents.js.map +0 -1
  221. package/dist/ask-user.d.ts.map +0 -1
  222. package/dist/ask-user.js +0 -1405
  223. package/dist/ask-user.js.map +0 -1
  224. package/dist/batch.d.ts +0 -12
  225. package/dist/batch.d.ts.map +0 -1
  226. package/dist/batch.js +0 -11
  227. package/dist/batch.js.map +0 -1
  228. package/dist/cli-args.d.ts.map +0 -1
  229. package/dist/cli-args.js.map +0 -1
  230. package/dist/config.d.ts.map +0 -1
  231. package/dist/config.js.map +0 -1
  232. package/dist/depth.d.ts.map +0 -1
  233. package/dist/depth.js.map +0 -1
  234. package/dist/executor.d.ts.map +0 -1
  235. package/dist/executor.js.map +0 -1
  236. package/dist/flow-prompt.d.ts.map +0 -1
  237. package/dist/flow-prompt.js.map +0 -1
  238. package/dist/flow.d.ts.map +0 -1
  239. package/dist/flow.js.map +0 -1
  240. package/dist/notify-state.d.ts.map +0 -1
  241. package/dist/notify-state.js.map +0 -1
  242. package/dist/notify.d.ts.map +0 -1
  243. package/dist/notify.js.map +0 -1
  244. package/dist/reasoning-strip.d.ts.map +0 -1
  245. package/dist/reasoning-strip.js.map +0 -1
  246. package/dist/render-utils.d.ts.map +0 -1
  247. package/dist/render-utils.js.map +0 -1
  248. package/dist/render.d.ts +0 -24
  249. package/dist/render.d.ts.map +0 -1
  250. package/dist/render.js +0 -592
  251. package/dist/render.js.map +0 -1
  252. package/dist/runner-events.d.ts.map +0 -1
  253. package/dist/runner-events.js.map +0 -1
  254. package/dist/scramble.d.ts +0 -171
  255. package/dist/scramble.d.ts.map +0 -1
  256. package/dist/scramble.js +0 -2261
  257. package/dist/scramble.js.map +0 -1
  258. package/dist/session-mode.d.ts.map +0 -1
  259. package/dist/session-mode.js.map +0 -1
  260. package/dist/settings-resolver.d.ts.map +0 -1
  261. package/dist/settings-resolver.js +0 -148
  262. package/dist/settings-resolver.js.map +0 -1
  263. package/dist/single-select-layout.d.ts +0 -20
  264. package/dist/single-select-layout.d.ts.map +0 -1
  265. package/dist/single-select-layout.js.map +0 -1
  266. package/dist/sliding-prompt.d.ts.map +0 -1
  267. package/dist/sliding-prompt.js.map +0 -1
  268. package/dist/snapshot.d.ts.map +0 -1
  269. package/dist/snapshot.js.map +0 -1
  270. package/dist/spec-mode.d.ts +0 -13
  271. package/dist/spec-mode.d.ts.map +0 -1
  272. package/dist/spec-mode.js +0 -90
  273. package/dist/spec-mode.js.map +0 -1
  274. package/dist/structured-output.d.ts.map +0 -1
  275. package/dist/structured-output.js.map +0 -1
  276. package/dist/timed-bash.d.ts.map +0 -1
  277. package/dist/timed-bash.js.map +0 -1
  278. package/dist/tool-utils.d.ts.map +0 -1
  279. package/dist/tool-utils.js.map +0 -1
  280. package/dist/transitions.d.ts.map +0 -1
  281. package/dist/transitions.js.map +0 -1
  282. package/dist/types.d.ts +0 -208
  283. package/dist/types.d.ts.map +0 -1
  284. package/dist/types.js.map +0 -1
  285. package/dist/web-tool.d.ts.map +0 -1
  286. package/dist/web-tool.js.map +0 -1
  287. /package/dist/{agents.d.ts → core/agents.d.ts} +0 -0
  288. /package/dist/{depth.d.ts → core/depth.d.ts} +0 -0
  289. /package/dist/{transitions.d.ts → core/transitions.d.ts} +0 -0
  290. /package/dist/{notify-state.js → notify/notify-state.js} +0 -0
  291. /package/dist/{notify.d.ts → notify/notify.d.ts} +0 -0
@@ -0,0 +1,851 @@
1
+ /**
2
+ * /flow:settings slash command registration.
3
+ *
4
+ * Subcommands: steering, strategic-hint, animation, glitch,
5
+ * tool-optimize, structured-output, session-mode, max-concurrency, reset
6
+ *
7
+ * When called with no arguments, opens an interactive TUI overlay.
8
+ */
9
+ import { DynamicBorder } from "@mariozechner/pi-coding-agent";
10
+ import { loadFlowSettings, writeFlowSetting, loadFlowModelConfigs, writeGlobalFlowMode, writeFlowModelConfig } from "../config/config.js";
11
+ import { configureSteering } from "../steering/sliding-prompt.js";
12
+ import { configureStrategicHint } from "../steering/tool-utils.js";
13
+ import { scrambleManager } from "../tui/scramble/index.js";
14
+ import { Container, Input, matchesKey, SelectList, Key, Spacer, Text, truncateToWidth, visibleWidth, wrapTextWithAnsi, } from "@mariozechner/pi-tui";
15
+ // Module-level refs for submenu builders (set during handler call)
16
+ let _modelRegistry = null;
17
+ let _theme = null;
18
+ let _keybindings = null;
19
+ export class SettingsList {
20
+ items;
21
+ theme;
22
+ selectedIndex = 0;
23
+ maxVisible;
24
+ onChange;
25
+ onCancel;
26
+ keybindings;
27
+ submenuComponent = null;
28
+ submenuItemIndex = null;
29
+ constructor(items, maxVisible, theme, keybindings, onChange, onCancel) {
30
+ this.items = items;
31
+ this.maxVisible = maxVisible;
32
+ this.theme = theme;
33
+ this.keybindings = keybindings;
34
+ this.onChange = onChange;
35
+ this.onCancel = onCancel;
36
+ }
37
+ updateValue(id, newValue) {
38
+ const item = this.items.find((i) => i.id === id);
39
+ if (item) {
40
+ item.currentValue = newValue;
41
+ }
42
+ }
43
+ invalidate() {
44
+ this.submenuComponent?.invalidate?.();
45
+ }
46
+ render(width) {
47
+ if (this.submenuComponent) {
48
+ return this.submenuComponent.render(width);
49
+ }
50
+ return this.renderMainList(width);
51
+ }
52
+ renderMainList(width) {
53
+ const lines = [];
54
+ if (this.items.length === 0) {
55
+ lines.push(this.theme.hint(" No settings available"));
56
+ this.addHintLine(lines);
57
+ return lines;
58
+ }
59
+ const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.items.length - this.maxVisible));
60
+ const endIndex = Math.min(startIndex + this.maxVisible, this.items.length);
61
+ const maxLabelWidth = Math.min(30, Math.max(...this.items.map((item) => visibleWidth(item.label))));
62
+ for (let i = startIndex; i < endIndex; i++) {
63
+ const item = this.items[i];
64
+ if (!item)
65
+ continue;
66
+ const isSelected = i === this.selectedIndex;
67
+ const prefix = isSelected ? this.theme.cursor : " ";
68
+ const prefixWidth = visibleWidth(prefix);
69
+ const labelPadded = item.label + " ".repeat(Math.max(0, maxLabelWidth - visibleWidth(item.label)));
70
+ const labelText = this.theme.label(labelPadded, isSelected);
71
+ const separator = " ";
72
+ const usedWidth = prefixWidth + maxLabelWidth + visibleWidth(separator);
73
+ const valueMaxWidth = Math.max(1, width - usedWidth - 2);
74
+ const optionLines = isSelected && item.values && item.values.length > 0
75
+ ? wrapTextWithAnsi(this.formatOptionsInline(item, item.values), valueMaxWidth)
76
+ : null;
77
+ const valueText = optionLines
78
+ ? optionLines[0] ?? ""
79
+ : this.theme.value(truncateToWidth(item.currentValue, valueMaxWidth, ""), isSelected);
80
+ const line = prefix + labelText + separator + valueText;
81
+ lines.push(truncateToWidth(line, width, ""));
82
+ if (optionLines && optionLines.length > 1) {
83
+ const indent = " ".repeat(prefixWidth + maxLabelWidth + visibleWidth(separator));
84
+ for (const continuation of optionLines.slice(1)) {
85
+ lines.push(truncateToWidth(indent + continuation, width, ""));
86
+ }
87
+ }
88
+ }
89
+ if (startIndex > 0 || endIndex < this.items.length) {
90
+ const scrollText = ` (${this.selectedIndex + 1}/${this.items.length})`;
91
+ lines.push(this.theme.hint(truncateToWidth(scrollText, width - 2, "")));
92
+ }
93
+ const selectedItem = this.items[this.selectedIndex];
94
+ if (selectedItem?.description) {
95
+ lines.push("");
96
+ const wrapWidth = Math.max(1, width - 4);
97
+ const wrappedDesc = wrapTextWithAnsi(selectedItem.description, wrapWidth);
98
+ for (const line of wrappedDesc) {
99
+ const prefixed = ` ${line}`;
100
+ lines.push(this.theme.description(truncateToWidth(prefixed, width, "")));
101
+ }
102
+ }
103
+ this.addHintLine(lines);
104
+ return lines;
105
+ }
106
+ handleInput(data) {
107
+ if (this.submenuComponent) {
108
+ this.submenuComponent.handleInput?.(data);
109
+ return;
110
+ }
111
+ if (this.keybindings.matches(data, "tui.select.up") || matchesKey(data, Key.ctrl("k"))) {
112
+ if (this.items.length === 0)
113
+ return;
114
+ this.selectedIndex = this.selectedIndex === 0 ? this.items.length - 1 : this.selectedIndex - 1;
115
+ }
116
+ else if (this.keybindings.matches(data, "tui.select.down") || matchesKey(data, Key.ctrl("j"))) {
117
+ if (this.items.length === 0)
118
+ return;
119
+ this.selectedIndex = this.selectedIndex === this.items.length - 1 ? 0 : this.selectedIndex + 1;
120
+ }
121
+ else if (this.keybindings.matches(data, "tui.editor.cursorLeft") || data === "\u001b[D") {
122
+ this.stepValue(-1);
123
+ }
124
+ else if (this.keybindings.matches(data, "tui.editor.cursorRight") || data === "\u001b[C") {
125
+ this.stepValue(1);
126
+ }
127
+ else if (this.keybindings.matches(data, "tui.select.confirm") ||
128
+ data === "\r" ||
129
+ data === "\n" ||
130
+ data === " ") {
131
+ this.activateItem();
132
+ }
133
+ else if (this.keybindings.matches(data, "tui.select.cancel") || matchesKey(data, Key.escape)) {
134
+ this.onCancel();
135
+ }
136
+ }
137
+ stepValue(direction) {
138
+ const item = this.items[this.selectedIndex];
139
+ if (!item || !item.values || item.values.length === 0)
140
+ return;
141
+ const values = item.values;
142
+ let currentIndex = values.indexOf(item.currentValue);
143
+ if (currentIndex === -1) {
144
+ currentIndex = direction > 0 ? 0 : values.length - 1;
145
+ }
146
+ const nextIndex = (currentIndex + direction + values.length) % values.length;
147
+ const newValue = values[nextIndex];
148
+ item.currentValue = newValue;
149
+ this.onChange(item.id, newValue);
150
+ }
151
+ activateItem() {
152
+ const item = this.items[this.selectedIndex];
153
+ if (!item)
154
+ return;
155
+ if (item.submenu) {
156
+ this.openSubmenu(item);
157
+ }
158
+ }
159
+ closeSubmenu() {
160
+ this.submenuComponent = null;
161
+ if (this.submenuItemIndex !== null) {
162
+ this.selectedIndex = this.submenuItemIndex;
163
+ this.submenuItemIndex = null;
164
+ }
165
+ }
166
+ formatOptionsInline(item, values) {
167
+ const separator = this.theme.description(" • ");
168
+ return values
169
+ .map((value) => {
170
+ const selected = value === item.currentValue;
171
+ return this.theme.value(value, selected);
172
+ })
173
+ .join(separator);
174
+ }
175
+ openSubmenu(item) {
176
+ if (!item.submenu)
177
+ return;
178
+ this.submenuItemIndex = this.selectedIndex;
179
+ this.submenuComponent = item.submenu(item.currentValue, (selectedValue) => {
180
+ if (selectedValue !== undefined) {
181
+ item.currentValue = selectedValue;
182
+ this.onChange(item.id, selectedValue);
183
+ }
184
+ this.closeSubmenu();
185
+ });
186
+ }
187
+ addHintLine(lines) {
188
+ lines.push("");
189
+ lines.push(this.theme.hint(" ←/→ change • Enter/Space edit custom • Esc to cancel"));
190
+ }
191
+ }
192
+ function getMainMenuItems(settings, cwd) {
193
+ const steeringEnabled = settings.steering?.enabled ?? true;
194
+ const animationEnabled = settings.animation?.enabled ?? true;
195
+ const toolOptimize = settings.toolOptimize ?? true;
196
+ const structuredOutput = settings.structuredOutput ?? true;
197
+ const sessionMode = settings.sessionMode ?? "default";
198
+ const askUserEnabled = settings.askUser?.enabled ?? false;
199
+ const askUserTimeout = settings.askUser?.timeout ?? 300;
200
+ const loaded = loadFlowModelConfigs(cwd);
201
+ const strategyName = loaded.selectedName;
202
+ const litePrimary = loaded.strategy.lite?.primary ?? "(default)";
203
+ const primaryModelShort = litePrimary.includes("/") ? litePrimary.split("/").pop() : litePrimary;
204
+ return [
205
+ {
206
+ value: "steering",
207
+ label: "Steering Settings",
208
+ description: steeringEnabled ? "enabled" : "disabled",
209
+ tooltip: "Configure orchestrator steering and strategic hints",
210
+ },
211
+ {
212
+ value: "animation",
213
+ label: "Animation Settings",
214
+ description: animationEnabled ? "enabled" : "disabled",
215
+ tooltip: "Toggle animation effects and glitch/scramble",
216
+ },
217
+ {
218
+ value: "tools",
219
+ label: "Tool Settings",
220
+ description: `tool-optimize: ${toolOptimize ? "on" : "off"}, structured-output: ${structuredOutput ? "on" : "off"}`,
221
+ tooltip: "Configure tool optimization and structured output",
222
+ },
223
+ {
224
+ value: "session",
225
+ label: "Session Settings",
226
+ description: `mode: ${sessionMode}`,
227
+ tooltip: "Set default session mode and concurrency",
228
+ },
229
+ {
230
+ value: "ask-user",
231
+ label: "Ask User Settings",
232
+ description: `enabled: ${askUserEnabled ? "on" : "off"}, timeout: ${askUserTimeout}s`,
233
+ tooltip: "Configure ask_user timeout and countdown",
234
+ },
235
+ {
236
+ value: "model-config",
237
+ label: "Model Config",
238
+ description: `${strategyName} ▸ lite: ${primaryModelShort}`,
239
+ tooltip: "Configure LLM models for lite, flash, and full flow tiers",
240
+ },
241
+ {
242
+ value: "reset",
243
+ label: "Reset to Defaults",
244
+ description: "restore all settings",
245
+ tooltip: "Restore all flow settings to their default values",
246
+ },
247
+ ];
248
+ }
249
+ function getSteeringItems(settings) {
250
+ const steering = settings.steering ?? {};
251
+ return [
252
+ {
253
+ id: "steering.enabled",
254
+ label: "enabled",
255
+ description: "Toggle steering injection",
256
+ currentValue: (steering.enabled ?? true) ? "on" : "off",
257
+ values: ["on", "off"],
258
+ },
259
+ {
260
+ id: "steering.strategicHint",
261
+ label: "strategic-hint",
262
+ description: "Toggle [Hint: Plan next step...]",
263
+ currentValue: (steering.strategicHint ?? true) ? "on" : "off",
264
+ values: ["on", "off"],
265
+ },
266
+ {
267
+ id: "steering.customPrompt",
268
+ label: "custom-prompt",
269
+ description: "Enter custom steering prompt or type 'default' to reset",
270
+ currentValue: steering.customPrompt ?? "(default)",
271
+ submenu: buildInputSubmenu("Custom prompt (or 'default')", (v) => {
272
+ const trimmed = v.trim();
273
+ if (!trimmed || trimmed.toLowerCase() === "default")
274
+ return "(default)";
275
+ return trimmed;
276
+ }),
277
+ },
278
+ ];
279
+ }
280
+ function getAnimationItems(settings) {
281
+ const animation = settings.animation ?? {};
282
+ return [
283
+ {
284
+ id: "animation.enabled",
285
+ label: "enabled",
286
+ description: "Master animation switch",
287
+ currentValue: (animation.enabled ?? true) ? "on" : "off",
288
+ values: ["on", "off"],
289
+ },
290
+ {
291
+ id: "animation.glitch",
292
+ label: "glitch",
293
+ description: "Glitch/scramble effect",
294
+ currentValue: (animation.glitch ?? true) ? "on" : "off",
295
+ values: ["on", "off"],
296
+ },
297
+ ];
298
+ }
299
+ function getToolItems(settings) {
300
+ return [
301
+ {
302
+ id: "toolOptimize",
303
+ label: "tool-optimize",
304
+ description: "Unified batch tool vs separate tools",
305
+ currentValue: (settings.toolOptimize ?? true) ? "on" : "off",
306
+ values: ["on", "off"],
307
+ },
308
+ {
309
+ id: "structuredOutput",
310
+ label: "structured-output",
311
+ description: "Structured JSON output from flows",
312
+ currentValue: (settings.structuredOutput ?? true) ? "on" : "off",
313
+ values: ["on", "off"],
314
+ },
315
+ ];
316
+ }
317
+ function getSessionItems(settings) {
318
+ return [
319
+ {
320
+ id: "sessionMode",
321
+ label: "session-mode",
322
+ description: "Session safety mode",
323
+ currentValue: settings.sessionMode ?? "default",
324
+ values: ["fast", "default", "long", "extreme_long"],
325
+ },
326
+ {
327
+ id: "maxConcurrency",
328
+ label: "max-concurrency",
329
+ description: "Maximum concurrent flows",
330
+ currentValue: String(settings.maxConcurrency ?? 4),
331
+ values: ["1", "2", "3", "4", "5", "6", "7", "8"],
332
+ submenu: buildInputSubmenu("Max concurrency (1-20)", (v) => {
333
+ const n = Number(v.trim());
334
+ if (!Number.isSafeInteger(n) || n < 1 || n > 20)
335
+ return null;
336
+ return String(n);
337
+ }),
338
+ },
339
+ ];
340
+ }
341
+ function getAskUserItems(settings) {
342
+ const askUser = settings.askUser ?? {};
343
+ return [
344
+ {
345
+ id: "askUser.enabled",
346
+ label: "enabled",
347
+ description: "Show countdown timer in ask_user prompt",
348
+ currentValue: (askUser.enabled ?? false) ? "on" : "off",
349
+ values: ["on", "off"],
350
+ },
351
+ {
352
+ id: "askUser.timeout",
353
+ label: "timeout",
354
+ description: "Auto-dismiss timeout in seconds",
355
+ currentValue: String(askUser.timeout ?? 300),
356
+ values: ["30", "60", "120", "300", "600"],
357
+ submenu: buildInputSubmenu("Timeout in seconds (10-3600)", (v) => {
358
+ const n = Number(v.trim());
359
+ if (!Number.isSafeInteger(n) || n < 10 || n > 3600)
360
+ return null;
361
+ return String(n);
362
+ }),
363
+ },
364
+ ];
365
+ }
366
+ function getModelConfigItems(settings, cwd) {
367
+ const loaded = loadFlowModelConfigs(cwd);
368
+ const strategyName = loaded.selectedName;
369
+ const strategy = loaded.strategy;
370
+ const items = [
371
+ {
372
+ id: "modelConfig.strategy",
373
+ label: "strategy",
374
+ description: "Active model strategy",
375
+ currentValue: strategyName,
376
+ values: Object.keys(loaded.configs).sort(),
377
+ },
378
+ ];
379
+ for (const tier of ["lite", "flash", "full"]) {
380
+ const tierConfig = strategy[tier];
381
+ const primary = tierConfig?.primary ?? "(default)";
382
+ const failover = tierConfig?.failover?.join(", ") ?? "(none)";
383
+ items.push({
384
+ id: `modelConfig.${tier}.primary`,
385
+ label: `${tier}: primary`,
386
+ description: `Primary model for ${tier} tier`,
387
+ currentValue: primary,
388
+ submenu: buildModelPickerSubmenu(primary, tier, "primary"),
389
+ });
390
+ items.push({
391
+ id: `modelConfig.${tier}.failover`,
392
+ label: `${tier}: failover`,
393
+ description: `Failover models for ${tier} tier`,
394
+ currentValue: failover,
395
+ submenu: buildModelPickerSubmenu(failover, tier, "failover"),
396
+ });
397
+ }
398
+ return items;
399
+ }
400
+ // ---------------------------------------------------------------------------
401
+ // Submenu helpers
402
+ // ---------------------------------------------------------------------------
403
+ function buildInputSubmenu(label, parseValue) {
404
+ return (currentValue, done) => {
405
+ const input = new Input();
406
+ input.focused = true;
407
+ input.setValue(currentValue);
408
+ input.onSubmit = (value) => {
409
+ const parsed = parseValue(value);
410
+ if (parsed === null)
411
+ return;
412
+ done(parsed);
413
+ };
414
+ input.onEscape = () => {
415
+ done();
416
+ };
417
+ const container = new Container();
418
+ container.addChild(new Text(label, 1, 0));
419
+ container.addChild(new Spacer(1));
420
+ container.addChild(input);
421
+ return {
422
+ render: (width) => container.render(width),
423
+ invalidate: () => container.invalidate(),
424
+ handleInput: (data) => input.handleInput(data),
425
+ };
426
+ };
427
+ }
428
+ function buildModelPickerSubmenu(currentValue, tier, slot) {
429
+ return (_currentValue, done) => {
430
+ const models = _modelRegistry?.getAvailable() ?? [];
431
+ const items = models.map((m) => ({
432
+ value: `${m.provider}/${m.id}`,
433
+ label: `${m.provider}/${m.id}`,
434
+ description: m.name ?? "",
435
+ }));
436
+ items.unshift({ value: "(default)", label: "(default)", description: "Use the default model" });
437
+ const selectList = new SelectList(items, 15, {
438
+ selectedPrefix: (t) => _theme?.fg("accent", t) ?? t,
439
+ selectedText: (t) => _theme?.fg("accent", t) ?? t,
440
+ description: (t) => _theme?.fg("muted", t) ?? t,
441
+ scrollInfo: (t) => _theme?.fg("dim", t) ?? t,
442
+ noMatch: (t) => _theme?.fg("warning", t) ?? t,
443
+ });
444
+ selectList.onSelect = (item) => {
445
+ done(item.value);
446
+ };
447
+ selectList.onCancel = () => {
448
+ done();
449
+ };
450
+ return {
451
+ render(width) {
452
+ return selectList.render(width);
453
+ },
454
+ invalidate() {
455
+ selectList.invalidate?.();
456
+ },
457
+ handleInput(data) {
458
+ selectList.handleInput(data);
459
+ },
460
+ };
461
+ };
462
+ }
463
+ // ---------------------------------------------------------------------------
464
+ // Command registration
465
+ // ---------------------------------------------------------------------------
466
+ export function setupSettingsCommand(pi) {
467
+ pi.registerCommand("flow:settings", {
468
+ description: "Manage flow settings. Subcommands: steering <on|off>, strategic-hint <on|off>, animation <on|off>, glitch <on|off>, tool-optimize <on|off>, structured-output <on|off>, session-mode <mode>, max-concurrency <n>, ask-user {enabled <on|off> | timeout <seconds>}, reset. Call with no args for interactive TUI.",
469
+ handler: async (args, ctx) => {
470
+ const cwd = ctx.cwd;
471
+ const trimmed = args.trim().toLowerCase();
472
+ const parts = trimmed.split(/\s+/);
473
+ const sub = parts[0] ?? "";
474
+ const value = parts[1] ?? "";
475
+ if (!sub) {
476
+ const settings = loadFlowSettings(cwd);
477
+ _modelRegistry = ctx.modelRegistry;
478
+ await ctx.ui.custom((tui, theme, keybindings, done) => {
479
+ _theme = theme;
480
+ _keybindings = keybindings;
481
+ let currentCategory = "main";
482
+ let container = new Container();
483
+ let activeList = null;
484
+ function rebuild() {
485
+ container = new Container();
486
+ activeList = null;
487
+ // Header
488
+ container.addChild(new DynamicBorder());
489
+ container.addChild(new Text(theme.fg("accent", theme.bold("Flow Settings")), 1, 0));
490
+ container.addChild(new Spacer(1));
491
+ const currentSettings = loadFlowSettings(cwd);
492
+ if (currentCategory === "main") {
493
+ const items = getMainMenuItems(currentSettings, cwd);
494
+ const selectList = new SelectList(items, Math.min(items.length, 10), {
495
+ selectedPrefix: (t) => theme.fg("accent", t),
496
+ selectedText: (t) => theme.fg("accent", t),
497
+ description: (t) => theme.fg("muted", t),
498
+ scrollInfo: (t) => theme.fg("dim", t),
499
+ noMatch: (t) => theme.fg("warning", t),
500
+ });
501
+ selectList.onSelect = (item) => {
502
+ if (item.value === "reset") {
503
+ writeFlowSetting(cwd, "", {});
504
+ configureSteering({ enabled: true, customPrompt: undefined });
505
+ configureStrategicHint(true);
506
+ scrambleManager.setAnimationConfig({ enabled: true, glitch: true });
507
+ ctx.ui.notify?.("Flow settings reset to defaults", "info");
508
+ rebuild();
509
+ tui.requestRender();
510
+ }
511
+ else {
512
+ currentCategory = item.value;
513
+ rebuild();
514
+ tui.requestRender();
515
+ }
516
+ };
517
+ selectList.onCancel = () => {
518
+ done(loadFlowSettings(cwd));
519
+ };
520
+ activeList = selectList;
521
+ container.addChild(selectList);
522
+ const tooltipText = new Text("", 1, 0);
523
+ selectList.onSelectionChange = (item) => {
524
+ tooltipText.setText(theme.fg("dim", item.tooltip ?? ""));
525
+ };
526
+ const initialItem = selectList.getSelectedItem();
527
+ if (initialItem) {
528
+ tooltipText.setText(theme.fg("dim", initialItem.tooltip ?? ""));
529
+ }
530
+ container.addChild(new Spacer(1));
531
+ container.addChild(tooltipText);
532
+ container.addChild(new Spacer(1));
533
+ container.addChild(new Text(theme.fg("dim", "▲▼ navigate • Enter/Space select • Esc back"), 1, 0));
534
+ container.addChild(new DynamicBorder());
535
+ }
536
+ else {
537
+ let items;
538
+ let handleChange;
539
+ const backCategory = "main";
540
+ if (currentCategory === "steering") {
541
+ items = getSteeringItems(currentSettings);
542
+ handleChange = (id, value) => {
543
+ if (id === "steering.enabled") {
544
+ const boolValue = value === "on";
545
+ writeFlowSetting(cwd, "steering.enabled", boolValue);
546
+ configureSteering({
547
+ enabled: boolValue,
548
+ customPrompt: currentSettings.steering?.customPrompt,
549
+ });
550
+ }
551
+ else if (id === "steering.strategicHint") {
552
+ const boolValue = value === "on";
553
+ writeFlowSetting(cwd, "steering.strategicHint", boolValue);
554
+ configureStrategicHint(boolValue);
555
+ }
556
+ else if (id === "steering.customPrompt") {
557
+ if (value === "(default)") {
558
+ writeFlowSetting(cwd, "steering.customPrompt", undefined);
559
+ configureSteering({
560
+ enabled: currentSettings.steering?.enabled ?? true,
561
+ customPrompt: undefined,
562
+ });
563
+ }
564
+ else {
565
+ writeFlowSetting(cwd, "steering.customPrompt", value);
566
+ configureSteering({
567
+ enabled: currentSettings.steering?.enabled ?? true,
568
+ customPrompt: value,
569
+ });
570
+ }
571
+ }
572
+ rebuild();
573
+ tui.requestRender();
574
+ };
575
+ }
576
+ else if (currentCategory === "animation") {
577
+ items = getAnimationItems(currentSettings);
578
+ handleChange = (id, value) => {
579
+ if (id === "animation.enabled") {
580
+ const boolValue = value === "on";
581
+ writeFlowSetting(cwd, "animation.enabled", boolValue);
582
+ scrambleManager.setAnimationConfig({
583
+ enabled: boolValue,
584
+ glitch: currentSettings.animation?.glitch ?? true,
585
+ });
586
+ }
587
+ else if (id === "animation.glitch") {
588
+ const boolValue = value === "on";
589
+ writeFlowSetting(cwd, "animation.glitch", boolValue);
590
+ scrambleManager.setAnimationConfig({
591
+ enabled: currentSettings.animation?.enabled ?? true,
592
+ glitch: boolValue,
593
+ });
594
+ }
595
+ rebuild();
596
+ tui.requestRender();
597
+ };
598
+ }
599
+ else if (currentCategory === "tools") {
600
+ items = getToolItems(currentSettings);
601
+ handleChange = (id, value) => {
602
+ if (id === "toolOptimize") {
603
+ writeFlowSetting(cwd, "toolOptimize", value === "on");
604
+ }
605
+ else if (id === "structuredOutput") {
606
+ writeFlowSetting(cwd, "structuredOutput", value === "on");
607
+ }
608
+ rebuild();
609
+ tui.requestRender();
610
+ };
611
+ }
612
+ else if (currentCategory === "session") {
613
+ items = getSessionItems(currentSettings);
614
+ handleChange = (id, value) => {
615
+ if (id === "sessionMode") {
616
+ writeFlowSetting(cwd, "sessionMode", value);
617
+ }
618
+ else if (id === "maxConcurrency") {
619
+ writeFlowSetting(cwd, "maxConcurrency", Number(value));
620
+ }
621
+ rebuild();
622
+ tui.requestRender();
623
+ };
624
+ }
625
+ else if (currentCategory === "ask-user") {
626
+ items = getAskUserItems(currentSettings);
627
+ handleChange = (id, value) => {
628
+ if (id === "askUser.enabled") {
629
+ writeFlowSetting(cwd, "askUser.enabled", value === "on");
630
+ }
631
+ else if (id === "askUser.timeout") {
632
+ writeFlowSetting(cwd, "askUser.timeout", Number(value));
633
+ }
634
+ rebuild();
635
+ tui.requestRender();
636
+ };
637
+ }
638
+ else if (currentCategory === "model-config") {
639
+ items = getModelConfigItems(currentSettings, cwd);
640
+ handleChange = (id, value) => {
641
+ if (id === "modelConfig.strategy") {
642
+ try {
643
+ writeGlobalFlowMode(value);
644
+ }
645
+ catch (e) {
646
+ /* ignore */
647
+ }
648
+ }
649
+ else if (id.startsWith("modelConfig.")) {
650
+ const match = id.match(/^modelConfig\.(lite|flash|full)\.(primary|failover)$/);
651
+ if (match) {
652
+ const tier = match[1];
653
+ const slot = match[2];
654
+ const loaded = loadFlowModelConfigs(cwd);
655
+ const strategyName = loaded.selectedName;
656
+ if (slot === "primary") {
657
+ if (value === "(default)") {
658
+ writeFlowModelConfig(cwd, strategyName, tier, { primary: null, failover: null });
659
+ }
660
+ else {
661
+ writeFlowModelConfig(cwd, strategyName, tier, { primary: value });
662
+ }
663
+ }
664
+ else {
665
+ if (value === "(default)") {
666
+ writeFlowModelConfig(cwd, strategyName, tier, { failover: [] });
667
+ }
668
+ else {
669
+ writeFlowModelConfig(cwd, strategyName, tier, { failover: [value] });
670
+ }
671
+ }
672
+ }
673
+ }
674
+ rebuild();
675
+ tui.requestRender();
676
+ };
677
+ }
678
+ else {
679
+ items = [];
680
+ handleChange = () => { };
681
+ }
682
+ const settingsTheme = {
683
+ label: (text, selected) => selected ? theme.fg("accent", theme.bold(text)) : theme.fg("text", text),
684
+ value: (text, selected) => selected ? theme.fg("accent", text) : theme.fg("muted", text),
685
+ description: (text) => theme.fg("muted", text),
686
+ cursor: theme.fg("accent", "▶ "),
687
+ hint: (text) => theme.fg("dim", text),
688
+ };
689
+ const settingsList = new SettingsList(items, Math.min(items.length + 2, 15), settingsTheme, keybindings, handleChange, () => {
690
+ currentCategory = backCategory;
691
+ rebuild();
692
+ tui.requestRender();
693
+ });
694
+ activeList = settingsList;
695
+ container.addChild(settingsList);
696
+ container.addChild(new DynamicBorder());
697
+ }
698
+ }
699
+ rebuild();
700
+ return {
701
+ render(width) {
702
+ return container.render(width);
703
+ },
704
+ invalidate() {
705
+ container.invalidate();
706
+ },
707
+ handleInput(data) {
708
+ if (activeList?.handleInput) {
709
+ activeList.handleInput(data);
710
+ }
711
+ tui.requestRender();
712
+ },
713
+ };
714
+ });
715
+ return;
716
+ }
717
+ // -----------------------------------------------------------------
718
+ // Text-based fallback for subcommands with arguments
719
+ // -----------------------------------------------------------------
720
+ const parseOnOff = (v) => {
721
+ if (v === "on" || v === "true" || v === "1")
722
+ return true;
723
+ if (v === "off" || v === "false" || v === "0")
724
+ return false;
725
+ return null;
726
+ };
727
+ switch (sub) {
728
+ case "steering": {
729
+ const parsed = parseOnOff(value);
730
+ if (parsed === null) {
731
+ ctx.ui.notify?.("Usage: /flow:settings steering <on|off>", "error");
732
+ return;
733
+ }
734
+ writeFlowSetting(cwd, "steering.enabled", parsed);
735
+ configureSteering({ enabled: parsed, customPrompt: undefined });
736
+ ctx.ui.notify?.(`steering.enabled = ${parsed}`, "info");
737
+ break;
738
+ }
739
+ case "strategic-hint": {
740
+ const parsed = parseOnOff(value);
741
+ if (parsed === null) {
742
+ ctx.ui.notify?.("Usage: /flow:settings strategic-hint <on|off>", "error");
743
+ return;
744
+ }
745
+ writeFlowSetting(cwd, "steering.strategicHint", parsed);
746
+ configureStrategicHint(parsed);
747
+ ctx.ui.notify?.(`steering.strategicHint = ${parsed}`, "info");
748
+ break;
749
+ }
750
+ case "animation": {
751
+ const parsed = parseOnOff(value);
752
+ if (parsed === null) {
753
+ ctx.ui.notify?.("Usage: /flow:settings animation <on|off>", "error");
754
+ return;
755
+ }
756
+ writeFlowSetting(cwd, "animation.enabled", parsed);
757
+ scrambleManager.setAnimationConfig({ enabled: parsed, glitch: true });
758
+ ctx.ui.notify?.(`animation.enabled = ${parsed}`, "info");
759
+ break;
760
+ }
761
+ case "glitch": {
762
+ const parsed = parseOnOff(value);
763
+ if (parsed === null) {
764
+ ctx.ui.notify?.("Usage: /flow:settings glitch <on|off>", "error");
765
+ return;
766
+ }
767
+ writeFlowSetting(cwd, "animation.glitch", parsed);
768
+ scrambleManager.setAnimationConfig({ enabled: true, glitch: parsed });
769
+ ctx.ui.notify?.(`animation.glitch = ${parsed}`, "info");
770
+ break;
771
+ }
772
+ case "tool-optimize": {
773
+ const parsed = parseOnOff(value);
774
+ if (parsed === null) {
775
+ ctx.ui.notify?.("Usage: /flow:settings tool-optimize <on|off>", "error");
776
+ return;
777
+ }
778
+ writeFlowSetting(cwd, "toolOptimize", parsed);
779
+ ctx.ui.notify?.(`toolOptimize = ${parsed}`, "info");
780
+ break;
781
+ }
782
+ case "structured-output": {
783
+ const parsed = parseOnOff(value);
784
+ if (parsed === null) {
785
+ ctx.ui.notify?.("Usage: /flow:settings structured-output <on|off>", "error");
786
+ return;
787
+ }
788
+ writeFlowSetting(cwd, "structuredOutput", parsed);
789
+ ctx.ui.notify?.(`structuredOutput = ${parsed}`, "info");
790
+ break;
791
+ }
792
+ case "session-mode": {
793
+ const validModes = ["fast", "default", "long", "extreme_long"];
794
+ if (!validModes.includes(value)) {
795
+ ctx.ui.notify?.("Usage: /flow:settings session-mode <fast|default|long|extreme_long>", "error");
796
+ return;
797
+ }
798
+ writeFlowSetting(cwd, "sessionMode", value);
799
+ ctx.ui.notify?.(`sessionMode = ${value}`, "info");
800
+ break;
801
+ }
802
+ case "max-concurrency": {
803
+ const n = Number(value);
804
+ if (!Number.isSafeInteger(n) || n < 1) {
805
+ ctx.ui.notify?.("Usage: /flow:settings max-concurrency <n>", "error");
806
+ return;
807
+ }
808
+ writeFlowSetting(cwd, "maxConcurrency", n);
809
+ ctx.ui.notify?.(`maxConcurrency = ${n}`, "info");
810
+ break;
811
+ }
812
+ case "ask-user": {
813
+ const askParts = trimmed.split(/\s+/);
814
+ const askSub = askParts[1] ?? "";
815
+ const askValue = askParts[2] ?? "";
816
+ if (askSub === "enabled") {
817
+ const parsed = parseOnOff(askValue);
818
+ if (parsed === null) {
819
+ ctx.ui.notify?.("Usage: /flow:settings ask-user enabled <on|off>", "error");
820
+ return;
821
+ }
822
+ writeFlowSetting(cwd, "askUser.enabled", parsed);
823
+ ctx.ui.notify?.(`askUser.enabled = ${parsed}`, "info");
824
+ }
825
+ else if (askSub === "timeout") {
826
+ const n = Number(askValue);
827
+ if (!Number.isSafeInteger(n) || n < 10) {
828
+ ctx.ui.notify?.("Usage: /flow:settings ask-user timeout <seconds>", "error");
829
+ return;
830
+ }
831
+ writeFlowSetting(cwd, "askUser.timeout", n);
832
+ ctx.ui.notify?.(`askUser.timeout = ${n}`, "info");
833
+ }
834
+ else {
835
+ ctx.ui.notify?.("Usage: /flow:settings ask-user {enabled <on|off> | timeout <seconds>}", "error");
836
+ }
837
+ break;
838
+ }
839
+ case "reset": {
840
+ writeFlowSetting(cwd, "", {});
841
+ ctx.ui.notify?.("Flow settings reset to defaults", "info");
842
+ break;
843
+ }
844
+ default: {
845
+ ctx.ui.notify?.("Unknown subcommand. Usage: /flow:settings {steering|strategic-hint|animation|glitch|tool-optimize|structured-output|session-mode|max-concurrency|ask-user|reset}", "error");
846
+ }
847
+ }
848
+ },
849
+ });
850
+ }
851
+ //# sourceMappingURL=settings-command.js.map