@compilr-dev/cli 0.4.0 → 0.5.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 (315) hide show
  1. package/README.md +30 -12
  2. package/dist/agent.d.ts +74 -1
  3. package/dist/agent.js +259 -76
  4. package/dist/anchors/index.d.ts +9 -0
  5. package/dist/anchors/index.js +9 -0
  6. package/dist/anchors/project-anchors.d.ts +79 -0
  7. package/dist/anchors/project-anchors.js +202 -0
  8. package/dist/commands/handler-types.d.ts +68 -0
  9. package/dist/commands/handler-types.js +8 -0
  10. package/dist/commands/handlers/agent-commands.d.ts +13 -0
  11. package/dist/commands/handlers/agent-commands.js +305 -0
  12. package/dist/commands/handlers/design-commands.d.ts +15 -0
  13. package/dist/commands/handlers/design-commands.js +334 -0
  14. package/dist/commands/handlers/index.d.ts +20 -0
  15. package/dist/commands/handlers/index.js +43 -0
  16. package/dist/commands/handlers/overlay-commands.d.ts +21 -0
  17. package/dist/commands/handlers/overlay-commands.js +287 -0
  18. package/dist/commands/handlers/project-commands.d.ts +11 -0
  19. package/dist/commands/handlers/project-commands.js +167 -0
  20. package/dist/commands/handlers/simple-commands.d.ts +19 -0
  21. package/dist/commands/handlers/simple-commands.js +144 -0
  22. package/dist/commands/index.d.ts +2 -1
  23. package/dist/commands/registry.d.ts +50 -0
  24. package/dist/commands/registry.js +75 -0
  25. package/dist/commands-v2/handlers/context.d.ts +13 -0
  26. package/dist/commands-v2/handlers/context.js +348 -0
  27. package/dist/commands-v2/handlers/core.d.ts +13 -0
  28. package/dist/commands-v2/handlers/core.js +165 -0
  29. package/dist/commands-v2/handlers/debug.d.ts +11 -0
  30. package/dist/commands-v2/handlers/debug.js +159 -0
  31. package/dist/commands-v2/handlers/index.d.ts +12 -0
  32. package/dist/commands-v2/handlers/index.js +24 -0
  33. package/dist/commands-v2/handlers/project.d.ts +22 -0
  34. package/dist/commands-v2/handlers/project.js +814 -0
  35. package/dist/commands-v2/handlers/settings.d.ts +15 -0
  36. package/dist/commands-v2/handlers/settings.js +235 -0
  37. package/dist/commands-v2/index.d.ts +13 -0
  38. package/dist/commands-v2/index.js +15 -0
  39. package/dist/commands-v2/registry.d.ts +37 -0
  40. package/dist/commands-v2/registry.js +80 -0
  41. package/dist/commands-v2/types.d.ts +75 -0
  42. package/dist/commands-v2/types.js +7 -0
  43. package/dist/commands.js +110 -7
  44. package/dist/index.js +288 -29
  45. package/dist/input-handlers/index.d.ts +7 -0
  46. package/dist/input-handlers/index.js +7 -0
  47. package/dist/input-handlers/memory-handler.d.ts +26 -0
  48. package/dist/input-handlers/memory-handler.js +68 -0
  49. package/dist/repl-helpers.d.ts +63 -0
  50. package/dist/repl-helpers.js +318 -0
  51. package/dist/repl-v2.d.ts +155 -0
  52. package/dist/repl-v2.js +774 -0
  53. package/dist/repl.d.ts +32 -4
  54. package/dist/repl.js +250 -977
  55. package/dist/settings/index.d.ts +23 -0
  56. package/dist/settings/index.js +48 -0
  57. package/dist/settings/paths.d.ts +110 -0
  58. package/dist/settings/paths.js +264 -0
  59. package/dist/templates/compilr-md.js +7 -4
  60. package/dist/templates/index.js +3 -4
  61. package/dist/themes/colors.js +3 -1
  62. package/dist/themes/registry.d.ts +5 -36
  63. package/dist/themes/registry.js +11 -95
  64. package/dist/themes/types.d.ts +3 -38
  65. package/dist/themes/types.js +2 -2
  66. package/dist/tools/anchor-tools.d.ts +31 -0
  67. package/dist/tools/anchor-tools.js +255 -0
  68. package/dist/tools/backlog-wrappers.d.ts +54 -0
  69. package/dist/tools/backlog-wrappers.js +338 -0
  70. package/dist/tools/backlog.js +1 -1
  71. package/dist/tools/db-tools.d.ts +65 -0
  72. package/dist/tools/db-tools.js +19 -0
  73. package/dist/tools/document-db.d.ts +43 -0
  74. package/dist/tools/document-db.js +220 -0
  75. package/dist/tools/project-db.d.ts +102 -0
  76. package/dist/tools/project-db.js +370 -0
  77. package/dist/tools/workitem-db.d.ts +103 -0
  78. package/dist/tools/workitem-db.js +549 -0
  79. package/dist/tools.js +13 -3
  80. package/dist/ui/agents-overlay-v2.d.ts +43 -0
  81. package/dist/ui/agents-overlay-v2.js +809 -0
  82. package/dist/ui/agents-overlay.d.ts +5 -5
  83. package/dist/ui/agents-overlay.js +782 -420
  84. package/dist/ui/anchors-overlay.d.ts +12 -0
  85. package/dist/ui/anchors-overlay.js +775 -0
  86. package/dist/ui/arch-type-overlay.d.ts +1 -6
  87. package/dist/ui/arch-type-overlay.js +175 -203
  88. package/dist/ui/ask-user-overlay-v2.d.ts +26 -0
  89. package/dist/ui/ask-user-overlay-v2.js +555 -0
  90. package/dist/ui/ask-user-overlay.d.ts +2 -2
  91. package/dist/ui/ask-user-overlay.js +443 -535
  92. package/dist/ui/ask-user-simple-overlay-v2.d.ts +25 -0
  93. package/dist/ui/ask-user-simple-overlay-v2.js +215 -0
  94. package/dist/ui/ask-user-simple-overlay.d.ts +2 -2
  95. package/dist/ui/ask-user-simple-overlay.js +182 -209
  96. package/dist/ui/backlog-overlay.d.ts +16 -1
  97. package/dist/ui/backlog-overlay.js +525 -659
  98. package/dist/ui/base/index.d.ts +26 -0
  99. package/dist/ui/base/index.js +33 -0
  100. package/dist/ui/base/inline-overlay-utils.d.ts +217 -0
  101. package/dist/ui/base/inline-overlay-utils.js +320 -0
  102. package/dist/ui/base/inline-overlay.d.ts +159 -0
  103. package/dist/ui/base/inline-overlay.js +257 -0
  104. package/dist/ui/base/key-utils.d.ts +15 -0
  105. package/dist/ui/base/key-utils.js +30 -0
  106. package/dist/ui/base/overlay-base-v2.d.ts +193 -0
  107. package/dist/ui/base/overlay-base-v2.js +246 -0
  108. package/dist/ui/base/overlay-base.d.ts +156 -0
  109. package/dist/ui/base/overlay-base.js +238 -0
  110. package/dist/ui/base/overlay-lifecycle.d.ts +65 -0
  111. package/dist/ui/base/overlay-lifecycle.js +159 -0
  112. package/dist/ui/base/overlay-types.d.ts +185 -0
  113. package/dist/ui/base/overlay-types.js +7 -0
  114. package/dist/ui/base/render-utils.d.ts +8 -0
  115. package/dist/ui/base/render-utils.js +11 -0
  116. package/dist/ui/base/screen-stack.d.ts +148 -0
  117. package/dist/ui/base/screen-stack.js +184 -0
  118. package/dist/ui/base/tabbed-list-overlay-v2.d.ts +103 -0
  119. package/dist/ui/base/tabbed-list-overlay-v2.js +317 -0
  120. package/dist/ui/base/tabbed-list-overlay.d.ts +153 -0
  121. package/dist/ui/base/tabbed-list-overlay.js +369 -0
  122. package/dist/ui/commands-overlay-v2.d.ts +33 -0
  123. package/dist/ui/commands-overlay-v2.js +441 -0
  124. package/dist/ui/commands-overlay.d.ts +7 -2
  125. package/dist/ui/commands-overlay.js +384 -355
  126. package/dist/ui/config-overlay.d.ts +5 -4
  127. package/dist/ui/config-overlay.js +243 -513
  128. package/dist/ui/conversation.d.ts +75 -4
  129. package/dist/ui/conversation.js +374 -161
  130. package/dist/ui/docs-overlay.d.ts +17 -0
  131. package/dist/ui/docs-overlay.js +303 -0
  132. package/dist/ui/ephemeral.d.ts +1 -1
  133. package/dist/ui/ephemeral.js +1 -1
  134. package/dist/ui/features/index.d.ts +34 -0
  135. package/dist/ui/features/index.js +34 -0
  136. package/dist/ui/features/input-feature.d.ts +85 -0
  137. package/dist/ui/features/input-feature.js +238 -0
  138. package/dist/ui/features/list-feature.d.ts +155 -0
  139. package/dist/ui/features/list-feature.js +244 -0
  140. package/dist/ui/features/pagination-feature.d.ts +154 -0
  141. package/dist/ui/features/pagination-feature.js +238 -0
  142. package/dist/ui/features/search-feature.d.ts +148 -0
  143. package/dist/ui/features/search-feature.js +185 -0
  144. package/dist/ui/features/tab-feature.d.ts +194 -0
  145. package/dist/ui/features/tab-feature.js +307 -0
  146. package/dist/ui/footer-v2.d.ts +222 -0
  147. package/dist/ui/footer-v2.js +1349 -0
  148. package/dist/ui/footer.d.ts +107 -0
  149. package/dist/ui/footer.js +359 -67
  150. package/dist/ui/guardrail-overlay.d.ts +29 -0
  151. package/dist/ui/guardrail-overlay.js +145 -0
  152. package/dist/ui/help-overlay-v2.d.ts +34 -0
  153. package/dist/ui/help-overlay-v2.js +309 -0
  154. package/dist/ui/help-overlay.d.ts +16 -0
  155. package/dist/ui/help-overlay.js +316 -0
  156. package/dist/ui/index.d.ts +1 -1
  157. package/dist/ui/index.js +1 -3
  158. package/dist/ui/init-overlay-v2.d.ts +34 -0
  159. package/dist/ui/init-overlay-v2.js +600 -0
  160. package/dist/ui/init-overlay.d.ts +12 -2
  161. package/dist/ui/init-overlay.js +349 -270
  162. package/dist/ui/input-prompt-v2.d.ts +1 -0
  163. package/dist/ui/input-prompt-v2.js +14 -6
  164. package/dist/ui/input-prompt.d.ts +116 -33
  165. package/dist/ui/input-prompt.js +536 -337
  166. package/dist/ui/iteration-limit-overlay-v2.d.ts +21 -0
  167. package/dist/ui/iteration-limit-overlay-v2.js +114 -0
  168. package/dist/ui/iteration-limit-overlay.d.ts +2 -2
  169. package/dist/ui/iteration-limit-overlay.js +92 -128
  170. package/dist/ui/keys-overlay-v2.d.ts +41 -0
  171. package/dist/ui/keys-overlay-v2.js +248 -0
  172. package/dist/ui/keys-overlay.d.ts +1 -0
  173. package/dist/ui/keys-overlay.js +203 -141
  174. package/dist/ui/line-utils.d.ts +88 -0
  175. package/dist/ui/line-utils.js +150 -0
  176. package/dist/ui/live-region.d.ts +161 -0
  177. package/dist/ui/live-region.js +387 -0
  178. package/dist/ui/mascot/expressions.d.ts +32 -0
  179. package/dist/ui/mascot/expressions.js +213 -0
  180. package/dist/ui/mascot/index.d.ts +8 -0
  181. package/dist/ui/mascot/index.js +8 -0
  182. package/dist/ui/mascot/renderer.d.ts +19 -0
  183. package/dist/ui/mascot/renderer.js +97 -0
  184. package/dist/ui/mascot-overlay-v2.d.ts +41 -0
  185. package/dist/ui/mascot-overlay-v2.js +138 -0
  186. package/dist/ui/mascot-overlay.d.ts +21 -0
  187. package/dist/ui/mascot-overlay.js +146 -0
  188. package/dist/ui/model-overlay-v2.d.ts +49 -0
  189. package/dist/ui/model-overlay-v2.js +118 -0
  190. package/dist/ui/model-overlay.d.ts +27 -0
  191. package/dist/ui/model-overlay.js +221 -0
  192. package/dist/ui/model-warning-overlay.js +3 -5
  193. package/dist/ui/new-overlay.d.ts +34 -0
  194. package/dist/ui/new-overlay.js +604 -0
  195. package/dist/ui/overlay/impl/agents-overlay-v2.d.ts +45 -0
  196. package/dist/ui/overlay/impl/agents-overlay-v2.js +825 -0
  197. package/dist/ui/overlay/impl/anchors-overlay-v2.d.ts +47 -0
  198. package/dist/ui/overlay/impl/anchors-overlay-v2.js +783 -0
  199. package/dist/ui/overlay/impl/arch-type-overlay-v2.d.ts +37 -0
  200. package/dist/ui/overlay/impl/arch-type-overlay-v2.js +240 -0
  201. package/dist/ui/overlay/impl/ask-user-overlay-v2.d.ts +72 -0
  202. package/dist/ui/overlay/impl/ask-user-overlay-v2.js +584 -0
  203. package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.d.ts +46 -0
  204. package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.js +204 -0
  205. package/dist/ui/overlay/impl/backlog-overlay-v2.d.ts +49 -0
  206. package/dist/ui/overlay/impl/backlog-overlay-v2.js +642 -0
  207. package/dist/ui/overlay/impl/commands-overlay-v2.d.ts +33 -0
  208. package/dist/ui/overlay/impl/commands-overlay-v2.js +441 -0
  209. package/dist/ui/overlay/impl/config-overlay-v2.d.ts +100 -0
  210. package/dist/ui/overlay/impl/config-overlay-v2.js +654 -0
  211. package/dist/ui/overlay/impl/dashboard-overlay-v2.d.ts +55 -0
  212. package/dist/ui/overlay/impl/dashboard-overlay-v2.js +359 -0
  213. package/dist/ui/overlay/impl/docs-overlay-v2.d.ts +45 -0
  214. package/dist/ui/overlay/impl/docs-overlay-v2.js +114 -0
  215. package/dist/ui/overlay/impl/document-detail-overlay-v2.d.ts +77 -0
  216. package/dist/ui/overlay/impl/document-detail-overlay-v2.js +1071 -0
  217. package/dist/ui/overlay/impl/guardrail-overlay-v2.d.ts +43 -0
  218. package/dist/ui/overlay/impl/guardrail-overlay-v2.js +114 -0
  219. package/dist/ui/overlay/impl/help-overlay-v2.d.ts +34 -0
  220. package/dist/ui/overlay/impl/help-overlay-v2.js +309 -0
  221. package/dist/ui/overlay/impl/init-overlay-v2.d.ts +77 -0
  222. package/dist/ui/overlay/impl/init-overlay-v2.js +593 -0
  223. package/dist/ui/overlay/impl/init-setup-overlay-v2.d.ts +25 -0
  224. package/dist/ui/overlay/impl/init-setup-overlay-v2.js +97 -0
  225. package/dist/ui/overlay/impl/iteration-limit-overlay-v2.d.ts +35 -0
  226. package/dist/ui/overlay/impl/iteration-limit-overlay-v2.js +105 -0
  227. package/dist/ui/overlay/impl/keys-overlay-v2.d.ts +41 -0
  228. package/dist/ui/overlay/impl/keys-overlay-v2.js +248 -0
  229. package/dist/ui/overlay/impl/mascot-overlay-v2.d.ts +41 -0
  230. package/dist/ui/overlay/impl/mascot-overlay-v2.js +138 -0
  231. package/dist/ui/overlay/impl/model-overlay-v2.d.ts +49 -0
  232. package/dist/ui/overlay/impl/model-overlay-v2.js +118 -0
  233. package/dist/ui/overlay/impl/model-warning-overlay-v2.d.ts +46 -0
  234. package/dist/ui/overlay/impl/model-warning-overlay-v2.js +132 -0
  235. package/dist/ui/overlay/impl/new-overlay-v2.d.ts +77 -0
  236. package/dist/ui/overlay/impl/new-overlay-v2.js +593 -0
  237. package/dist/ui/overlay/impl/permission-overlay-v2.d.ts +36 -0
  238. package/dist/ui/overlay/impl/permission-overlay-v2.js +380 -0
  239. package/dist/ui/overlay/impl/projects-overlay-v2.d.ts +36 -0
  240. package/dist/ui/overlay/impl/projects-overlay-v2.js +499 -0
  241. package/dist/ui/overlay/impl/theme-overlay-v2.d.ts +42 -0
  242. package/dist/ui/overlay/impl/theme-overlay-v2.js +135 -0
  243. package/dist/ui/overlay/impl/tools-overlay-v2.d.ts +47 -0
  244. package/dist/ui/overlay/impl/tools-overlay-v2.js +218 -0
  245. package/dist/ui/overlay/impl/tutorial-overlay-v2.d.ts +31 -0
  246. package/dist/ui/overlay/impl/tutorial-overlay-v2.js +1035 -0
  247. package/dist/ui/overlay/impl/workflow-overlay-v2.d.ts +80 -0
  248. package/dist/ui/overlay/impl/workflow-overlay-v2.js +637 -0
  249. package/dist/ui/overlay/index.d.ts +33 -0
  250. package/dist/ui/overlay/index.js +35 -0
  251. package/dist/ui/overlay/key-utils.d.ts +6 -0
  252. package/dist/ui/overlay/key-utils.js +6 -0
  253. package/dist/ui/overlay/overlay-types.d.ts +128 -0
  254. package/dist/ui/overlay/overlay-types.js +22 -0
  255. package/dist/ui/overlay/types.d.ts +135 -0
  256. package/dist/ui/overlay/types.js +22 -0
  257. package/dist/ui/overlays/help-overlay-v2.d.ts +28 -0
  258. package/dist/ui/overlays/help-overlay-v2.js +198 -0
  259. package/dist/ui/overlays/index.d.ts +11 -0
  260. package/dist/ui/overlays/index.js +11 -0
  261. package/dist/ui/overlays.d.ts +0 -4
  262. package/dist/ui/overlays.js +0 -444
  263. package/dist/ui/permission-overlay-v2.d.ts +36 -0
  264. package/dist/ui/permission-overlay-v2.js +380 -0
  265. package/dist/ui/permission-overlay.d.ts +1 -1
  266. package/dist/ui/permission-overlay.js +186 -298
  267. package/dist/ui/projects-overlay.d.ts +19 -0
  268. package/dist/ui/projects-overlay.js +484 -0
  269. package/dist/ui/providers/types.d.ts +178 -0
  270. package/dist/ui/providers/types.js +9 -0
  271. package/dist/ui/render-modes.d.ts +36 -0
  272. package/dist/ui/render-modes.js +44 -0
  273. package/dist/ui/startup-menu.d.ts +36 -0
  274. package/dist/ui/startup-menu.js +236 -0
  275. package/dist/ui/subagent-renderer.d.ts +117 -0
  276. package/dist/ui/subagent-renderer.js +334 -0
  277. package/dist/ui/terminal-codes.d.ts +94 -0
  278. package/dist/ui/terminal-codes.js +124 -0
  279. package/dist/ui/terminal-renderer.d.ts +221 -0
  280. package/dist/ui/terminal-renderer.js +751 -0
  281. package/dist/ui/terminal-ui.d.ts +463 -0
  282. package/dist/ui/terminal-ui.js +2296 -0
  283. package/dist/ui/terminal.d.ts +20 -0
  284. package/dist/ui/terminal.js +72 -0
  285. package/dist/ui/theme-overlay-v2.d.ts +42 -0
  286. package/dist/ui/theme-overlay-v2.js +135 -0
  287. package/dist/ui/theme-overlay.d.ts +24 -0
  288. package/dist/ui/theme-overlay.js +127 -0
  289. package/dist/ui/todo-zone.js +53 -25
  290. package/dist/ui/tool-formatters.d.ts +16 -0
  291. package/dist/ui/tool-formatters.js +516 -0
  292. package/dist/ui/tools-overlay-v2.d.ts +47 -0
  293. package/dist/ui/tools-overlay-v2.js +218 -0
  294. package/dist/ui/tools-overlay.d.ts +10 -2
  295. package/dist/ui/tools-overlay.js +172 -220
  296. package/dist/ui/tutorial-overlay-v2.d.ts +31 -0
  297. package/dist/ui/tutorial-overlay-v2.js +1035 -0
  298. package/dist/ui/tutorial-overlay.d.ts +1 -0
  299. package/dist/ui/tutorial-overlay.js +400 -302
  300. package/dist/ui/workflow-overlay.d.ts +22 -0
  301. package/dist/ui/workflow-overlay.js +636 -0
  302. package/dist/utils/debug-log.d.ts +28 -0
  303. package/dist/utils/debug-log.js +57 -0
  304. package/dist/utils/model-tiers.js +1 -1
  305. package/dist/utils/path-safety.d.ts +56 -0
  306. package/dist/utils/path-safety.js +239 -0
  307. package/dist/workflow/guided-mode-injector.d.ts +42 -0
  308. package/dist/workflow/guided-mode-injector.js +191 -0
  309. package/dist/workflow/index.d.ts +8 -0
  310. package/dist/workflow/index.js +8 -0
  311. package/dist/workflow/step-criteria.d.ts +62 -0
  312. package/dist/workflow/step-criteria.js +150 -0
  313. package/dist/workflow/step-tracker.d.ts +92 -0
  314. package/dist/workflow/step-tracker.js +141 -0
  315. package/package.json +12 -5
@@ -0,0 +1,380 @@
1
+ /**
2
+ * Permission Overlay V2
3
+ *
4
+ * Modal overlay for tool permission requests.
5
+ * Uses BaseOverlayV2 for the new TerminalUI-based REPL.
6
+ */
7
+ import chalk from 'chalk';
8
+ import { getStyles } from '../themes/index.js';
9
+ import { BaseOverlayV2 } from './base/index.js';
10
+ import * as terminal from './terminal.js';
11
+ // =============================================================================
12
+ // Helpers
13
+ // =============================================================================
14
+ /**
15
+ * Format a value for display, handling nested structures
16
+ * Replaces newlines with ↵ symbol to prevent multi-line rendering
17
+ */
18
+ function formatValue(value, maxLen) {
19
+ if (typeof value === 'string') {
20
+ const singleLine = value.replace(/\r?\n|\r/g, '↵');
21
+ return singleLine.length > maxLen ? singleLine.slice(0, maxLen) + '...' : singleLine;
22
+ }
23
+ if (typeof value === 'boolean' || typeof value === 'number') {
24
+ return String(value);
25
+ }
26
+ if (Array.isArray(value)) {
27
+ if (value.length === 0)
28
+ return '[]';
29
+ const items = value.slice(0, 3).map((item) => {
30
+ if (typeof item === 'object' && item !== null) {
31
+ const obj = item;
32
+ const keys = Object.keys(obj);
33
+ if (keys.length === 0)
34
+ return '{}';
35
+ const preview = keys
36
+ .slice(0, 2)
37
+ .map((k) => {
38
+ const v = obj[k];
39
+ return `${k}: ${formatValue(v, 20)}`;
40
+ })
41
+ .join(', ');
42
+ return `{${preview}${keys.length > 2 ? ', ...' : ''}}`;
43
+ }
44
+ return formatValue(item, 20);
45
+ });
46
+ const remaining = value.length - 3;
47
+ const suffix = remaining > 0 ? `, ... (+${String(remaining)} more)` : '';
48
+ return `[${items.join(', ')}${suffix}]`;
49
+ }
50
+ if (typeof value === 'object' && value !== null) {
51
+ const obj = value;
52
+ const keys = Object.keys(obj);
53
+ if (keys.length === 0)
54
+ return '{}';
55
+ const preview = keys
56
+ .slice(0, 3)
57
+ .map((k) => `${k}: ${formatValue(obj[k], 15)}`)
58
+ .join(', ');
59
+ return keys.length > 3 ? `{${preview}, ...}` : `{${preview}}`;
60
+ }
61
+ return String(value);
62
+ }
63
+ /**
64
+ * Format tool args for display.
65
+ */
66
+ function formatArgs(toolName, args, maxWidth) {
67
+ const lines = [];
68
+ // Special handling for bash commands
69
+ if (toolName === 'bash' && typeof args.command === 'string') {
70
+ const cmd = args.command;
71
+ const prefix = 'Command: ';
72
+ const availableWidth = maxWidth - prefix.length - 4;
73
+ if (cmd.length <= availableWidth) {
74
+ lines.push(prefix + cmd);
75
+ }
76
+ else {
77
+ lines.push(prefix);
78
+ const maxCmdLength = availableWidth * 3;
79
+ const truncatedCmd = cmd.length > maxCmdLength ? cmd.slice(0, maxCmdLength) + '...' : cmd;
80
+ lines.push(' ' + truncatedCmd);
81
+ }
82
+ return lines;
83
+ }
84
+ // Special handling for edit tool
85
+ if (toolName === 'edit') {
86
+ const path = args.path ?? args.file_path ?? args.filePath;
87
+ if (typeof path === 'string') {
88
+ const maxPathLen = maxWidth - 10;
89
+ const truncPath = path.length > maxPathLen ? '...' + path.slice(-(maxPathLen - 3)) : path;
90
+ lines.push(`File: ${truncPath}`);
91
+ }
92
+ // Diff is shown separately, don't show old/new text here
93
+ return lines;
94
+ }
95
+ // Special handling for write_file
96
+ if (toolName === 'write_file') {
97
+ const path = args.path ?? args.file_path ?? args.filePath;
98
+ if (typeof path === 'string') {
99
+ const maxPathLen = maxWidth - 10;
100
+ const truncPath = path.length > maxPathLen ? '...' + path.slice(-(maxPathLen - 3)) : path;
101
+ lines.push(`File: ${truncPath}`);
102
+ }
103
+ const content = args.content;
104
+ if (typeof content === 'string') {
105
+ const contentLines = content.split('\n').length;
106
+ lines.push(`Content: ${String(contentLines)} lines`);
107
+ }
108
+ return lines;
109
+ }
110
+ // For file operations, show path prominently
111
+ const path = args.path ?? args.file_path ?? args.filePath;
112
+ if (typeof path === 'string') {
113
+ const maxPathLen = maxWidth - 10;
114
+ const truncPath = path.length > maxPathLen ? '...' + path.slice(-(maxPathLen - 3)) : path;
115
+ lines.push('Path: ' + truncPath);
116
+ }
117
+ // Show other args (limit to 3)
118
+ const skipKeys = ['path', 'file_path', 'filePath', 'command', 'old_string', 'new_string', 'oldString', 'newString', 'content'];
119
+ let shown = 0;
120
+ for (const [key, value] of Object.entries(args)) {
121
+ if (skipKeys.includes(key))
122
+ continue;
123
+ if (shown >= 3) {
124
+ lines.push(`... +${String(Object.keys(args).length - shown - skipKeys.length)} more`);
125
+ break;
126
+ }
127
+ const valueStr = formatValue(value, maxWidth - key.length - 6);
128
+ lines.push(`${key}: ${valueStr}`);
129
+ shown++;
130
+ }
131
+ return lines;
132
+ }
133
+ /**
134
+ * Format args for detail view (no truncation, proper word wrapping)
135
+ */
136
+ function formatArgsForDetail(toolName, args, maxWidth) {
137
+ const lines = [];
138
+ lines.push(`Tool: ${toolName}`);
139
+ lines.push('');
140
+ for (const [key, value] of Object.entries(args)) {
141
+ if (typeof value === 'string') {
142
+ lines.push(`${key}:`);
143
+ const valueLines = value.split(/\r?\n/);
144
+ for (const valueLine of valueLines) {
145
+ if (valueLine.length <= maxWidth - 4) {
146
+ lines.push(` ${valueLine}`);
147
+ }
148
+ else {
149
+ let remaining = valueLine;
150
+ while (remaining.length > 0) {
151
+ const chunk = remaining.slice(0, maxWidth - 4);
152
+ lines.push(` ${chunk}`);
153
+ remaining = remaining.slice(maxWidth - 4);
154
+ }
155
+ }
156
+ }
157
+ lines.push('');
158
+ }
159
+ else if (Array.isArray(value)) {
160
+ lines.push(`${key}: [${String(value.length)} items]`);
161
+ for (let i = 0; i < Math.min(value.length, 10); i++) {
162
+ const item = value[i];
163
+ if (typeof item === 'object' && item !== null) {
164
+ lines.push(` [${String(i)}]:`);
165
+ const itemObj = item;
166
+ for (const [k, v] of Object.entries(itemObj)) {
167
+ const vStr = typeof v === 'string' ? v : JSON.stringify(v);
168
+ lines.push(` ${k}: ${vStr.slice(0, maxWidth - 10)}`);
169
+ }
170
+ }
171
+ else {
172
+ lines.push(` [${String(i)}]: ${String(item)}`);
173
+ }
174
+ }
175
+ if (value.length > 10) {
176
+ lines.push(` ... +${String(value.length - 10)} more items`);
177
+ }
178
+ lines.push('');
179
+ }
180
+ else if (typeof value === 'object' && value !== null) {
181
+ lines.push(`${key}:`);
182
+ for (const [k, v] of Object.entries(value)) {
183
+ const vStr = typeof v === 'string' ? v : JSON.stringify(v);
184
+ lines.push(` ${k}: ${vStr.slice(0, maxWidth - 6)}`);
185
+ }
186
+ lines.push('');
187
+ }
188
+ else {
189
+ lines.push(`${key}: ${String(value)}`);
190
+ }
191
+ }
192
+ return lines;
193
+ }
194
+ // Fixed height for detail view
195
+ const DETAIL_VIEW_CONTENT_LINES = 15;
196
+ // =============================================================================
197
+ // Permission Overlay V2 Class
198
+ // =============================================================================
199
+ export class PermissionOverlayV2 extends BaseOverlayV2 {
200
+ type = 'inline';
201
+ id = 'permission-overlay-v2';
202
+ options;
203
+ constructor(options) {
204
+ // Initialize state before super call
205
+ const initialState = {
206
+ selectedIndex: 0, // Default to "Yes"
207
+ showingDetail: false,
208
+ detailScrollOffset: 0,
209
+ detailContentLines: [],
210
+ };
211
+ super(initialState);
212
+ this.options = options;
213
+ // Set minimum height for stable rendering
214
+ const diffLineCount = options.diffLines?.length ?? 0;
215
+ this.minHeight = 15 + diffLineCount;
216
+ }
217
+ renderContent(context) {
218
+ if (this.state.showingDetail) {
219
+ return this.renderDetailView(context);
220
+ }
221
+ return this.renderMainView(context);
222
+ }
223
+ renderMainView(context) {
224
+ const s = context.styles;
225
+ const lines = [];
226
+ const cols = terminal.getTerminalWidth();
227
+ const border = s.muted('─'.repeat(Math.max(1, cols - 1)));
228
+ // If there are diff lines, show them first
229
+ if (this.options.diffLines && this.options.diffLines.length > 0) {
230
+ for (const diffLine of this.options.diffLines) {
231
+ lines.push(diffLine);
232
+ }
233
+ lines.push('');
234
+ }
235
+ // Header
236
+ lines.push(border);
237
+ lines.push(' ' + s.warning('⚠') + ' ' + chalk.bold('Permission Required'));
238
+ lines.push('');
239
+ // Tool info
240
+ lines.push(' Tool: ' + s.primary(this.options.toolName));
241
+ // Format and display args
242
+ const maxArgWidth = cols - 6;
243
+ const argLines = formatArgs(this.options.toolName, this.options.args, maxArgWidth);
244
+ for (const argLine of argLines) {
245
+ const safeArg = argLine.length > maxArgWidth ? argLine.slice(0, maxArgWidth - 3) + '...' : argLine;
246
+ lines.push(' ' + s.muted(safeArg));
247
+ }
248
+ lines.push('');
249
+ // Options
250
+ const optionLabels = ['Yes, allow this', 'No, deny', 'Always allow this tool'];
251
+ const optionKeys = ['y', 'n', 'a'];
252
+ for (let i = 0; i < optionLabels.length; i++) {
253
+ const isCursor = this.state.selectedIndex === i;
254
+ const prefix = isCursor ? ' ❯ ' : ' ';
255
+ const key = `[${optionKeys[i]}] `;
256
+ if (isCursor) {
257
+ lines.push(s.primary(prefix + key + optionLabels[i]));
258
+ }
259
+ else {
260
+ lines.push(s.muted(prefix + key + optionLabels[i]));
261
+ }
262
+ }
263
+ // Footer
264
+ lines.push('');
265
+ lines.push(s.muted(' ↑↓ Navigate · Enter Select · y/n/a Quick select · ') + s.primary('d') + s.muted(' Details'));
266
+ lines.push(border);
267
+ return lines;
268
+ }
269
+ renderDetailView(context) {
270
+ const s = context.styles;
271
+ const cols = terminal.getTerminalWidth();
272
+ const lines = [];
273
+ const border = s.muted('─'.repeat(Math.max(1, cols - 1)));
274
+ // Header
275
+ lines.push(border);
276
+ lines.push(' ' + s.warning('⚠') + ' ' + chalk.bold('Permission Details') + s.muted(` (${this.options.toolName})`));
277
+ lines.push(border);
278
+ lines.push('');
279
+ // Content with scroll
280
+ const contentLines = this.state.detailContentLines;
281
+ const visibleLines = DETAIL_VIEW_CONTENT_LINES;
282
+ const endLine = Math.min(this.state.detailScrollOffset + visibleLines, contentLines.length);
283
+ for (let i = this.state.detailScrollOffset; i < endLine; i++) {
284
+ const line = contentLines[i];
285
+ const safeLine = line.length > cols - 4 ? line.slice(0, cols - 7) + '...' : line;
286
+ lines.push(' ' + safeLine);
287
+ }
288
+ // Pad to fixed height
289
+ const renderedLines = endLine - this.state.detailScrollOffset;
290
+ for (let i = renderedLines; i < DETAIL_VIEW_CONTENT_LINES; i++) {
291
+ lines.push('');
292
+ }
293
+ // Footer with scroll indicator
294
+ lines.push('');
295
+ const scrollInfo = contentLines.length > visibleLines
296
+ ? s.muted(` [${String(this.state.detailScrollOffset + 1)}-${String(endLine)}/${String(contentLines.length)}]`)
297
+ : '';
298
+ lines.push(border);
299
+ lines.push(s.muted(' ↑↓/PgUp/PgDn Scroll · q/Esc Back') + scrollInfo);
300
+ return lines;
301
+ }
302
+ handleKey(key) {
303
+ if (this.state.showingDetail) {
304
+ return this.handleDetailKey(key);
305
+ }
306
+ return this.handleMainKey(key);
307
+ }
308
+ handleMainKey(key) {
309
+ // Escape or Ctrl+C = deny
310
+ if (key.name === 'escape' || (key.ctrl && key.name === 'c')) {
311
+ return this.close('deny');
312
+ }
313
+ // Quick keys - use char for single letter presses
314
+ const keyStr = key.char?.toLowerCase() ?? '';
315
+ if (keyStr === 'y') {
316
+ return this.close('allow');
317
+ }
318
+ if (keyStr === 'n') {
319
+ return this.close('deny');
320
+ }
321
+ if (keyStr === 'a') {
322
+ return this.close('allow-always');
323
+ }
324
+ if (keyStr === 'd') {
325
+ // Switch to detail view
326
+ const cols = terminal.getTerminalWidth();
327
+ this.state.showingDetail = true;
328
+ this.state.detailScrollOffset = 0;
329
+ this.state.detailContentLines = formatArgsForDetail(this.options.toolName, this.options.args, cols - 4);
330
+ return this.rerender();
331
+ }
332
+ // Arrow navigation
333
+ if (key.name === 'up') {
334
+ this.state.selectedIndex = Math.max(0, this.state.selectedIndex - 1);
335
+ return this.rerender();
336
+ }
337
+ if (key.name === 'down') {
338
+ this.state.selectedIndex = Math.min(2, this.state.selectedIndex + 1);
339
+ return this.rerender();
340
+ }
341
+ if (key.name === 'return') {
342
+ const results = ['allow', 'deny', 'allow-always'];
343
+ return this.close(results[this.state.selectedIndex]);
344
+ }
345
+ return this.rerender();
346
+ }
347
+ handleDetailKey(key) {
348
+ // q or Escape = go back to main view
349
+ const keyStr = key.char?.toLowerCase() ?? '';
350
+ if (keyStr === 'q' || key.name === 'escape') {
351
+ this.state.showingDetail = false;
352
+ return this.rerender();
353
+ }
354
+ // Scroll
355
+ const visibleLines = DETAIL_VIEW_CONTENT_LINES;
356
+ const maxOffset = Math.max(0, this.state.detailContentLines.length - visibleLines);
357
+ if (key.name === 'up') {
358
+ this.state.detailScrollOffset = Math.max(0, this.state.detailScrollOffset - 1);
359
+ }
360
+ else if (key.name === 'pageup') {
361
+ this.state.detailScrollOffset = Math.max(0, this.state.detailScrollOffset - visibleLines);
362
+ }
363
+ else if (key.name === 'down') {
364
+ this.state.detailScrollOffset = Math.min(maxOffset, this.state.detailScrollOffset + 1);
365
+ }
366
+ else if (key.name === 'pagedown') {
367
+ this.state.detailScrollOffset = Math.min(maxOffset, this.state.detailScrollOffset + visibleLines);
368
+ }
369
+ return this.rerender();
370
+ }
371
+ getCloseSummary(result) {
372
+ const s = getStyles();
373
+ const resultText = result === 'allow'
374
+ ? s.success('Allowed')
375
+ : result === 'allow-always'
376
+ ? s.primary('Always allowed')
377
+ : s.error('Denied');
378
+ return s.muted(`Permission: ${resultText}`);
379
+ }
380
+ }
@@ -2,7 +2,7 @@
2
2
  * Permission Overlay
3
3
  *
4
4
  * Modal overlay for tool permission requests.
5
- * Uses the same pattern as ask-user-simple-overlay for consistent behavior.
5
+ * Renders inline above the footer using InlineOverlay base class.
6
6
  */
7
7
  export type PermissionResult = 'allow' | 'deny' | 'allow-always';
8
8
  export interface PermissionOverlayOptions {