@cluesmith/codev 2.0.2 → 2.0.6

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 (312) hide show
  1. package/dashboard/dist/assets/index-B-s8BA2l.js +135 -0
  2. package/dashboard/dist/assets/index-B-s8BA2l.js.map +1 -0
  3. package/dashboard/dist/assets/index-DB2AxRP7.css +32 -0
  4. package/dashboard/dist/index.html +2 -2
  5. package/dist/agent-farm/cli.d.ts.map +1 -1
  6. package/dist/agent-farm/cli.js +32 -14
  7. package/dist/agent-farm/cli.js.map +1 -1
  8. package/dist/agent-farm/commands/architect.d.ts +1 -1
  9. package/dist/agent-farm/commands/architect.js +3 -3
  10. package/dist/agent-farm/commands/architect.js.map +1 -1
  11. package/dist/agent-farm/commands/attach.d.ts +19 -0
  12. package/dist/agent-farm/commands/attach.d.ts.map +1 -1
  13. package/dist/agent-farm/commands/attach.js +172 -12
  14. package/dist/agent-farm/commands/attach.js.map +1 -1
  15. package/dist/agent-farm/commands/cleanup.js +6 -6
  16. package/dist/agent-farm/commands/cleanup.js.map +1 -1
  17. package/dist/agent-farm/commands/open.js +5 -5
  18. package/dist/agent-farm/commands/open.js.map +1 -1
  19. package/dist/agent-farm/commands/send.d.ts +22 -2
  20. package/dist/agent-farm/commands/send.d.ts.map +1 -1
  21. package/dist/agent-farm/commands/send.js +100 -181
  22. package/dist/agent-farm/commands/send.js.map +1 -1
  23. package/dist/agent-farm/commands/shell.js +5 -5
  24. package/dist/agent-farm/commands/shell.js.map +1 -1
  25. package/dist/agent-farm/commands/spawn-roles.d.ts +3 -9
  26. package/dist/agent-farm/commands/spawn-roles.d.ts.map +1 -1
  27. package/dist/agent-farm/commands/spawn-roles.js +14 -53
  28. package/dist/agent-farm/commands/spawn-roles.js.map +1 -1
  29. package/dist/agent-farm/commands/spawn-worktree.d.ts +11 -17
  30. package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -1
  31. package/dist/agent-farm/commands/spawn-worktree.js +32 -13
  32. package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
  33. package/dist/agent-farm/commands/spawn.d.ts +8 -6
  34. package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
  35. package/dist/agent-farm/commands/spawn.js +183 -69
  36. package/dist/agent-farm/commands/spawn.js.map +1 -1
  37. package/dist/agent-farm/commands/start.d.ts +4 -4
  38. package/dist/agent-farm/commands/start.js +16 -16
  39. package/dist/agent-farm/commands/start.js.map +1 -1
  40. package/dist/agent-farm/commands/status.d.ts +1 -1
  41. package/dist/agent-farm/commands/status.d.ts.map +1 -1
  42. package/dist/agent-farm/commands/status.js +15 -26
  43. package/dist/agent-farm/commands/status.js.map +1 -1
  44. package/dist/agent-farm/commands/stop.d.ts +4 -4
  45. package/dist/agent-farm/commands/stop.js +9 -9
  46. package/dist/agent-farm/commands/stop.js.map +1 -1
  47. package/dist/agent-farm/db/index.d.ts.map +1 -1
  48. package/dist/agent-farm/db/index.js +82 -7
  49. package/dist/agent-farm/db/index.js.map +1 -1
  50. package/dist/agent-farm/db/schema.d.ts +2 -2
  51. package/dist/agent-farm/db/schema.d.ts.map +1 -1
  52. package/dist/agent-farm/db/schema.js +21 -4
  53. package/dist/agent-farm/db/schema.js.map +1 -1
  54. package/dist/agent-farm/lib/tower-client.d.ts +36 -26
  55. package/dist/agent-farm/lib/tower-client.d.ts.map +1 -1
  56. package/dist/agent-farm/lib/tower-client.js +50 -25
  57. package/dist/agent-farm/lib/tower-client.js.map +1 -1
  58. package/dist/agent-farm/lib/tunnel-client.d.ts +12 -2
  59. package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
  60. package/dist/agent-farm/lib/tunnel-client.js +59 -1
  61. package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
  62. package/dist/agent-farm/servers/overview.d.ts +111 -0
  63. package/dist/agent-farm/servers/overview.d.ts.map +1 -0
  64. package/dist/agent-farm/servers/overview.js +385 -0
  65. package/dist/agent-farm/servers/overview.js.map +1 -0
  66. package/dist/agent-farm/servers/tower-instances.d.ts +18 -20
  67. package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
  68. package/dist/agent-farm/servers/tower-instances.js +97 -100
  69. package/dist/agent-farm/servers/tower-instances.js.map +1 -1
  70. package/dist/agent-farm/servers/tower-messages.d.ts +87 -0
  71. package/dist/agent-farm/servers/tower-messages.d.ts.map +1 -0
  72. package/dist/agent-farm/servers/tower-messages.js +202 -0
  73. package/dist/agent-farm/servers/tower-messages.js.map +1 -0
  74. package/dist/agent-farm/servers/tower-routes.d.ts +1 -1
  75. package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
  76. package/dist/agent-farm/servers/tower-routes.js +343 -174
  77. package/dist/agent-farm/servers/tower-routes.js.map +1 -1
  78. package/dist/agent-farm/servers/tower-server.js +50 -21
  79. package/dist/agent-farm/servers/tower-server.js.map +1 -1
  80. package/dist/agent-farm/servers/tower-terminals.d.ts +35 -31
  81. package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
  82. package/dist/agent-farm/servers/tower-terminals.js +208 -184
  83. package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
  84. package/dist/agent-farm/servers/tower-tunnel.d.ts +2 -2
  85. package/dist/agent-farm/servers/tower-tunnel.d.ts.map +1 -1
  86. package/dist/agent-farm/servers/tower-tunnel.js +12 -12
  87. package/dist/agent-farm/servers/tower-tunnel.js.map +1 -1
  88. package/dist/agent-farm/servers/tower-types.d.ts +8 -12
  89. package/dist/agent-farm/servers/tower-types.d.ts.map +1 -1
  90. package/dist/agent-farm/servers/tower-utils.d.ts +9 -9
  91. package/dist/agent-farm/servers/tower-utils.d.ts.map +1 -1
  92. package/dist/agent-farm/servers/tower-utils.js +18 -18
  93. package/dist/agent-farm/servers/tower-utils.js.map +1 -1
  94. package/dist/agent-farm/servers/tower-websocket.d.ts +2 -2
  95. package/dist/agent-farm/servers/tower-websocket.d.ts.map +1 -1
  96. package/dist/agent-farm/servers/tower-websocket.js +39 -18
  97. package/dist/agent-farm/servers/tower-websocket.js.map +1 -1
  98. package/dist/agent-farm/types.d.ts +5 -6
  99. package/dist/agent-farm/types.d.ts.map +1 -1
  100. package/dist/agent-farm/utils/agent-names.d.ts +85 -0
  101. package/dist/agent-farm/utils/agent-names.d.ts.map +1 -0
  102. package/dist/agent-farm/utils/agent-names.js +140 -0
  103. package/dist/agent-farm/utils/agent-names.js.map +1 -0
  104. package/dist/agent-farm/utils/config.d.ts +1 -1
  105. package/dist/agent-farm/utils/config.d.ts.map +1 -1
  106. package/dist/agent-farm/utils/config.js +16 -16
  107. package/dist/agent-farm/utils/config.js.map +1 -1
  108. package/dist/agent-farm/utils/file-tabs.d.ts +3 -3
  109. package/dist/agent-farm/utils/file-tabs.d.ts.map +1 -1
  110. package/dist/agent-farm/utils/file-tabs.js +9 -9
  111. package/dist/agent-farm/utils/file-tabs.js.map +1 -1
  112. package/dist/agent-farm/utils/index.d.ts +0 -1
  113. package/dist/agent-farm/utils/index.d.ts.map +1 -1
  114. package/dist/agent-farm/utils/index.js +0 -1
  115. package/dist/agent-farm/utils/index.js.map +1 -1
  116. package/dist/agent-farm/utils/message-format.d.ts +17 -0
  117. package/dist/agent-farm/utils/message-format.d.ts.map +1 -0
  118. package/dist/agent-farm/utils/message-format.js +41 -0
  119. package/dist/agent-farm/utils/message-format.js.map +1 -0
  120. package/dist/agent-farm/utils/notifications.d.ts +4 -4
  121. package/dist/agent-farm/utils/notifications.d.ts.map +1 -1
  122. package/dist/agent-farm/utils/notifications.js +18 -18
  123. package/dist/agent-farm/utils/notifications.js.map +1 -1
  124. package/dist/cli.d.ts.map +1 -1
  125. package/dist/cli.js +26 -1
  126. package/dist/cli.js.map +1 -1
  127. package/dist/commands/adopt.d.ts +2 -2
  128. package/dist/commands/adopt.d.ts.map +1 -1
  129. package/dist/commands/adopt.js +13 -15
  130. package/dist/commands/adopt.js.map +1 -1
  131. package/dist/commands/consult/index.d.ts +26 -2
  132. package/dist/commands/consult/index.d.ts.map +1 -1
  133. package/dist/commands/consult/index.js +296 -83
  134. package/dist/commands/consult/index.js.map +1 -1
  135. package/dist/commands/consult/metrics.d.ts +90 -0
  136. package/dist/commands/consult/metrics.d.ts.map +1 -0
  137. package/dist/commands/consult/metrics.js +203 -0
  138. package/dist/commands/consult/metrics.js.map +1 -0
  139. package/dist/commands/consult/stats.d.ts +18 -0
  140. package/dist/commands/consult/stats.d.ts.map +1 -0
  141. package/dist/commands/consult/stats.js +150 -0
  142. package/dist/commands/consult/stats.js.map +1 -0
  143. package/dist/commands/consult/usage-extractor.d.ts +38 -0
  144. package/dist/commands/consult/usage-extractor.d.ts.map +1 -0
  145. package/dist/commands/consult/usage-extractor.js +99 -0
  146. package/dist/commands/consult/usage-extractor.js.map +1 -0
  147. package/dist/commands/doctor.d.ts.map +1 -1
  148. package/dist/commands/doctor.js +11 -9
  149. package/dist/commands/doctor.js.map +1 -1
  150. package/dist/commands/import.js +4 -4
  151. package/dist/commands/import.js.map +1 -1
  152. package/dist/commands/init.d.ts +2 -2
  153. package/dist/commands/init.d.ts.map +1 -1
  154. package/dist/commands/init.js +13 -15
  155. package/dist/commands/init.js.map +1 -1
  156. package/dist/commands/porch/index.d.ts +6 -6
  157. package/dist/commands/porch/index.d.ts.map +1 -1
  158. package/dist/commands/porch/index.js +37 -37
  159. package/dist/commands/porch/index.js.map +1 -1
  160. package/dist/commands/porch/next.d.ts +1 -1
  161. package/dist/commands/porch/next.d.ts.map +1 -1
  162. package/dist/commands/porch/next.js +86 -92
  163. package/dist/commands/porch/next.js.map +1 -1
  164. package/dist/commands/porch/notify.d.ts +11 -0
  165. package/dist/commands/porch/notify.d.ts.map +1 -0
  166. package/dist/commands/porch/notify.js +30 -0
  167. package/dist/commands/porch/notify.js.map +1 -0
  168. package/dist/commands/porch/plan.d.ts +1 -1
  169. package/dist/commands/porch/plan.d.ts.map +1 -1
  170. package/dist/commands/porch/plan.js +3 -3
  171. package/dist/commands/porch/plan.js.map +1 -1
  172. package/dist/commands/porch/prompts.d.ts +10 -1
  173. package/dist/commands/porch/prompts.d.ts.map +1 -1
  174. package/dist/commands/porch/prompts.js +59 -35
  175. package/dist/commands/porch/prompts.js.map +1 -1
  176. package/dist/commands/porch/protocol.d.ts +1 -1
  177. package/dist/commands/porch/protocol.d.ts.map +1 -1
  178. package/dist/commands/porch/protocol.js +8 -8
  179. package/dist/commands/porch/protocol.js.map +1 -1
  180. package/dist/commands/porch/state.d.ts +6 -6
  181. package/dist/commands/porch/state.d.ts.map +1 -1
  182. package/dist/commands/porch/state.js +14 -12
  183. package/dist/commands/porch/state.js.map +1 -1
  184. package/dist/commands/update.d.ts.map +1 -1
  185. package/dist/commands/update.js +10 -11
  186. package/dist/commands/update.js.map +1 -1
  187. package/dist/lib/github.d.ts +81 -0
  188. package/dist/lib/github.d.ts.map +1 -0
  189. package/dist/lib/github.js +141 -0
  190. package/dist/lib/github.js.map +1 -0
  191. package/dist/lib/scaffold.d.ts +13 -21
  192. package/dist/lib/scaffold.d.ts.map +1 -1
  193. package/dist/lib/scaffold.js +34 -57
  194. package/dist/lib/scaffold.js.map +1 -1
  195. package/dist/lib/skeleton.d.ts +7 -7
  196. package/dist/lib/skeleton.d.ts.map +1 -1
  197. package/dist/lib/skeleton.js +10 -10
  198. package/dist/lib/skeleton.js.map +1 -1
  199. package/dist/terminal/index.d.ts +14 -0
  200. package/dist/terminal/index.d.ts.map +1 -1
  201. package/dist/terminal/index.js +12 -0
  202. package/dist/terminal/index.js.map +1 -1
  203. package/dist/terminal/pty-manager.d.ts +1 -1
  204. package/dist/terminal/pty-manager.d.ts.map +1 -1
  205. package/dist/terminal/pty-manager.js +10 -7
  206. package/dist/terminal/pty-manager.js.map +1 -1
  207. package/dist/terminal/pty-session.js +3 -3
  208. package/dist/terminal/pty-session.js.map +1 -1
  209. package/dist/terminal/session-manager.d.ts +64 -0
  210. package/dist/terminal/session-manager.d.ts.map +1 -1
  211. package/dist/terminal/session-manager.js +299 -10
  212. package/dist/terminal/session-manager.js.map +1 -1
  213. package/dist/terminal/shellper-client.d.ts +2 -1
  214. package/dist/terminal/shellper-client.d.ts.map +1 -1
  215. package/dist/terminal/shellper-client.js +4 -2
  216. package/dist/terminal/shellper-client.js.map +1 -1
  217. package/dist/terminal/shellper-main.js +33 -4
  218. package/dist/terminal/shellper-main.js.map +1 -1
  219. package/dist/terminal/shellper-process.d.ts +24 -7
  220. package/dist/terminal/shellper-process.d.ts.map +1 -1
  221. package/dist/terminal/shellper-process.js +139 -36
  222. package/dist/terminal/shellper-process.js.map +1 -1
  223. package/dist/terminal/shellper-protocol.d.ts +1 -0
  224. package/dist/terminal/shellper-protocol.d.ts.map +1 -1
  225. package/dist/terminal/shellper-protocol.js.map +1 -1
  226. package/package.json +4 -1
  227. package/skeleton/.claude/skills/af/SKILL.md +7 -7
  228. package/skeleton/.claude/skills/consult/SKILL.md +1 -1
  229. package/skeleton/builders.md +2 -2
  230. package/skeleton/maintain/.gitkeep +1 -1
  231. package/skeleton/porch/prompts/specify.md +1 -1
  232. package/skeleton/protocols/bugfix/prompts/pr.md +15 -4
  233. package/skeleton/protocols/experiment/protocol.md +17 -17
  234. package/skeleton/protocols/maintain/prompts/audit.md +2 -2
  235. package/skeleton/protocols/maintain/prompts/sync.md +1 -1
  236. package/skeleton/protocols/maintain/prompts/verify.md +1 -1
  237. package/skeleton/protocols/maintain/protocol.md +8 -9
  238. package/skeleton/protocols/maintain/templates/maintenance-run.md +2 -2
  239. package/skeleton/protocols/spir/protocol.json +5 -5
  240. package/skeleton/protocols/spir/protocol.md +8 -8
  241. package/skeleton/protocols/tick/protocol.md +31 -31
  242. package/skeleton/resources/commands/agent-farm.md +14 -14
  243. package/skeleton/resources/commands/codev.md +0 -1
  244. package/skeleton/resources/commands/consult.md +3 -3
  245. package/skeleton/resources/spikes.md +3 -3
  246. package/skeleton/resources/workflow-reference.md +14 -14
  247. package/skeleton/roles/architect.md +25 -25
  248. package/skeleton/roles/builder.md +1 -1
  249. package/skeleton/roles/consultant.md +6 -0
  250. package/skeleton/templates/AGENTS.md +5 -5
  251. package/skeleton/templates/CLAUDE.md +5 -5
  252. package/skeleton/templates/lifecycle.md +9 -9
  253. package/templates/open.html +19 -16
  254. package/templates/tower.html +54 -94
  255. package/templates/vendor/marked.min.js +6 -0
  256. package/templates/vendor/prism-bash.min.js +1 -0
  257. package/templates/vendor/prism-css.min.js +1 -0
  258. package/templates/vendor/prism-javascript.min.js +1 -0
  259. package/templates/vendor/prism-json.min.js +1 -0
  260. package/templates/vendor/prism-markdown.min.js +1 -0
  261. package/templates/vendor/prism-markup.min.js +1 -0
  262. package/templates/vendor/prism-python.min.js +1 -0
  263. package/templates/vendor/prism-tomorrow.min.css +1 -0
  264. package/templates/vendor/prism-typescript.min.js +1 -0
  265. package/templates/vendor/prism-yaml.min.js +1 -0
  266. package/templates/vendor/prism.min.js +1 -0
  267. package/templates/vendor/purify.min.js +3 -0
  268. package/dashboard/dist/assets/index-4n9zpWLY.css +0 -32
  269. package/dashboard/dist/assets/index-b38SaXk5.js +0 -136
  270. package/dashboard/dist/assets/index-b38SaXk5.js.map +0 -1
  271. package/dist/agent-farm/hq-connector.d.ts +0 -19
  272. package/dist/agent-farm/hq-connector.d.ts.map +0 -1
  273. package/dist/agent-farm/hq-connector.js +0 -351
  274. package/dist/agent-farm/hq-connector.js.map +0 -1
  275. package/dist/agent-farm/utils/deps.d.ts +0 -51
  276. package/dist/agent-farm/utils/deps.d.ts.map +0 -1
  277. package/dist/agent-farm/utils/deps.js +0 -162
  278. package/dist/agent-farm/utils/deps.js.map +0 -1
  279. package/dist/agent-farm/utils/gate-status.d.ts +0 -16
  280. package/dist/agent-farm/utils/gate-status.d.ts.map +0 -1
  281. package/dist/agent-farm/utils/gate-status.js +0 -79
  282. package/dist/agent-farm/utils/gate-status.js.map +0 -1
  283. package/dist/agent-farm/utils/gate-watcher.d.ts +0 -38
  284. package/dist/agent-farm/utils/gate-watcher.d.ts.map +0 -1
  285. package/dist/agent-farm/utils/gate-watcher.js +0 -122
  286. package/dist/agent-farm/utils/gate-watcher.js.map +0 -1
  287. package/dist/agent-farm/utils/session.d.ts +0 -32
  288. package/dist/agent-farm/utils/session.d.ts.map +0 -1
  289. package/dist/agent-farm/utils/session.js +0 -57
  290. package/dist/agent-farm/utils/session.js.map +0 -1
  291. package/dist/lib/projectlist-parser.d.ts +0 -70
  292. package/dist/lib/projectlist-parser.d.ts.map +0 -1
  293. package/dist/lib/projectlist-parser.js +0 -200
  294. package/dist/lib/projectlist-parser.js.map +0 -1
  295. package/skeleton/templates/projectlist-archive.md +0 -21
  296. package/skeleton/templates/projectlist.md +0 -147
  297. package/templates/dashboard/css/dialogs.css +0 -149
  298. package/templates/dashboard/css/files.css +0 -558
  299. package/templates/dashboard/css/layout.css +0 -133
  300. package/templates/dashboard/css/projects.css +0 -501
  301. package/templates/dashboard/css/statusbar.css +0 -23
  302. package/templates/dashboard/css/tabs.css +0 -314
  303. package/templates/dashboard/css/utilities.css +0 -50
  304. package/templates/dashboard/css/variables.css +0 -45
  305. package/templates/dashboard/index.html +0 -149
  306. package/templates/dashboard/js/dialogs.js +0 -368
  307. package/templates/dashboard/js/files.js +0 -448
  308. package/templates/dashboard/js/main.js +0 -476
  309. package/templates/dashboard/js/projects.js +0 -544
  310. package/templates/dashboard/js/state.js +0 -91
  311. package/templates/dashboard/js/tabs.js +0 -518
  312. package/templates/dashboard/js/utils.js +0 -191
@@ -1,368 +0,0 @@
1
- // Dialog, Context Menu, and Tab Close Functions
2
-
3
- // Close tab
4
- async function closeTab(tabId, event) {
5
- const tab = tabs.find(t => t.id === tabId);
6
- if (!tab) return;
7
-
8
- // Shift+click bypasses confirmation
9
- if (event && event.shiftKey) {
10
- doCloseTab(tabId);
11
- return;
12
- }
13
-
14
- // Files don't need confirmation
15
- if (tab.type === 'file') {
16
- doCloseTab(tabId);
17
- return;
18
- }
19
-
20
- // Check if process is still running before showing confirmation (Bugfix #132)
21
- // If the shell/builder already exited, close immediately without confirmation
22
- try {
23
- const response = await fetch(apiUrl(`api/tabs/${encodeURIComponent(tabId)}/running`));
24
- if (response.ok) {
25
- const { running } = await response.json();
26
- if (!running) {
27
- // Process already exited, close without confirmation
28
- doCloseTab(tabId);
29
- return;
30
- }
31
- }
32
- } catch {
33
- // On error, fall through to show confirmation (safer default)
34
- }
35
-
36
- // Show confirmation for builders and shells with running processes
37
- pendingCloseTabId = tabId;
38
- const dialog = document.getElementById('close-dialog');
39
- const title = document.getElementById('close-dialog-title');
40
- const message = document.getElementById('close-dialog-message');
41
-
42
- if (tab.type === 'builder') {
43
- title.textContent = `Stop builder ${tab.name}?`;
44
- message.textContent = 'This will terminate the builder process.';
45
- } else {
46
- title.textContent = `Close shell ${tab.name}?`;
47
- message.textContent = 'This will terminate the shell process.';
48
- }
49
-
50
- dialog.classList.remove('hidden');
51
- }
52
-
53
- // Actually close the tab
54
- async function doCloseTab(tabId) {
55
- const tab = tabs.find(t => t.id === tabId);
56
- if (!tab) return;
57
-
58
- try {
59
- await fetch(apiUrl(`api/tabs/${encodeURIComponent(tabId)}`), { method: 'DELETE' });
60
-
61
- tabs = tabs.filter(t => t.id !== tabId);
62
-
63
- if (activeTabId === tabId) {
64
- activeTabId = tabs.length > 0 ? tabs[tabs.length - 1].id : null;
65
- }
66
-
67
- renderTabs();
68
- renderTabContent();
69
- showToast('Tab closed', 'success');
70
- } catch (err) {
71
- showToast('Failed to close tab: ' + err.message, 'error');
72
- }
73
- }
74
-
75
- // Confirm close from dialog
76
- function confirmClose() {
77
- if (pendingCloseTabId) {
78
- doCloseTab(pendingCloseTabId);
79
- hideCloseDialog();
80
- }
81
- }
82
-
83
- function hideCloseDialog() {
84
- document.getElementById('close-dialog').classList.add('hidden');
85
- pendingCloseTabId = null;
86
- }
87
-
88
- // Context menu
89
- function showContextMenu(event, tabId) {
90
- event.preventDefault();
91
- contextMenuTabId = tabId;
92
-
93
- const menu = document.getElementById('context-menu');
94
- menu.style.left = event.clientX + 'px';
95
- menu.style.top = event.clientY + 'px';
96
- menu.classList.remove('hidden');
97
-
98
- const tab = tabs.find(t => t.id === tabId);
99
- const reloadItem = document.getElementById('context-reload');
100
- if (reloadItem) {
101
- reloadItem.style.display = (tab && tab.type === 'file') ? 'block' : 'none';
102
- }
103
-
104
- const firstItem = menu.querySelector('.context-menu-item');
105
- if (firstItem) firstItem.focus();
106
-
107
- setTimeout(() => {
108
- document.addEventListener('click', hideContextMenu, { once: true });
109
- }, 0);
110
- }
111
-
112
- // Reload file tab content
113
- function reloadContextTab() {
114
- if (contextMenuTabId) {
115
- refreshFileTab(contextMenuTabId);
116
- showToast('Reloaded', 'success');
117
- }
118
- hideContextMenu();
119
- }
120
-
121
- function hideContextMenu() {
122
- document.getElementById('context-menu').classList.add('hidden');
123
- contextMenuTabId = null;
124
- }
125
-
126
- // Handle keyboard navigation in context menu
127
- // Uses shared handleMenuKeydown from utils.js (Maintenance Run 0004)
128
- function handleContextMenuKeydown(event) {
129
- handleMenuKeydown(event, 'context-menu', 'context-menu-item', hideContextMenu);
130
- }
131
-
132
- function closeActiveTab() {
133
- if (contextMenuTabId) {
134
- closeTab(contextMenuTabId);
135
- }
136
- hideContextMenu();
137
- }
138
-
139
- function closeOtherTabs() {
140
- if (contextMenuTabId) {
141
- const otherTabs = tabs.filter(t => t.id !== contextMenuTabId && t.closeable !== false);
142
- otherTabs.forEach(t => doCloseTab(t.id));
143
- }
144
- hideContextMenu();
145
- }
146
-
147
- function closeAllTabs() {
148
- tabs.filter(t => t.closeable !== false).forEach(t => doCloseTab(t.id));
149
- hideContextMenu();
150
- }
151
-
152
- // Open context menu tab in new tab
153
- function openContextTab() {
154
- if (contextMenuTabId) {
155
- openInNewTab(contextMenuTabId);
156
- }
157
- hideContextMenu();
158
- }
159
-
160
- // File dialog
161
- function showFileDialog() {
162
- document.getElementById('file-dialog').classList.remove('hidden');
163
- document.getElementById('file-path-input').focus();
164
- }
165
-
166
- function hideFileDialog() {
167
- document.getElementById('file-dialog').classList.add('hidden');
168
- document.getElementById('file-path-input').value = '';
169
- }
170
-
171
- function setFilePath(path) {
172
- document.getElementById('file-path-input').value = path;
173
- document.getElementById('file-path-input').focus();
174
- }
175
-
176
- // Uses shared openFileTab from utils.js (Maintenance Run 0004)
177
- async function openFile() {
178
- const path = document.getElementById('file-path-input').value.trim();
179
- if (!path) return;
180
- await openFileTab(path, { onSuccess: hideFileDialog });
181
- }
182
-
183
- // ========================================
184
- // Create File Dialog (Bugfix #131)
185
- // ========================================
186
-
187
- // Show create file dialog
188
- function showCreateFileDialog() {
189
- document.getElementById('create-file-dialog').classList.remove('hidden');
190
- const input = document.getElementById('create-file-path-input');
191
- input.value = '';
192
- input.focus();
193
- }
194
-
195
- // Hide create file dialog
196
- function hideCreateFileDialog() {
197
- document.getElementById('create-file-dialog').classList.add('hidden');
198
- document.getElementById('create-file-path-input').value = '';
199
- }
200
-
201
- // Set quick path for create file dialog
202
- function setCreateFilePath(path) {
203
- const input = document.getElementById('create-file-path-input');
204
- input.value = path;
205
- input.focus();
206
- // Move cursor to end
207
- input.setSelectionRange(path.length, path.length);
208
- }
209
-
210
- // Create a new file
211
- async function createFile() {
212
- const input = document.getElementById('create-file-path-input');
213
- const filePath = input.value.trim();
214
-
215
- if (!filePath) {
216
- showToast('Please enter a file path', 'error');
217
- return;
218
- }
219
-
220
- // Basic validation - prevent absolute paths and path traversal
221
- if (filePath.startsWith('/') || filePath.includes('..')) {
222
- showToast('Invalid file path', 'error');
223
- return;
224
- }
225
-
226
- try {
227
- const response = await fetch(apiUrl('api/files'), {
228
- method: 'POST',
229
- headers: { 'Content-Type': 'application/json' },
230
- body: JSON.stringify({ path: filePath, content: '' })
231
- });
232
-
233
- const result = await response.json();
234
-
235
- if (!response.ok) {
236
- showToast(result.error || 'Failed to create file', 'error');
237
- return;
238
- }
239
-
240
- hideCreateFileDialog();
241
- showToast(`Created ${filePath}`, 'success');
242
-
243
- // Refresh files tree and open the new file
244
- await refreshFilesTree();
245
- await openFileTab(filePath, { showSwitchToast: false });
246
- } catch (err) {
247
- showToast('Network error: ' + err.message, 'error');
248
- }
249
- }
250
-
251
- // Spawn worktree builder
252
- async function spawnBuilder() {
253
- try {
254
- const response = await fetch(apiUrl('api/tabs/builder'), {
255
- method: 'POST',
256
- headers: { 'Content-Type': 'application/json' },
257
- body: JSON.stringify({})
258
- });
259
-
260
- if (!response.ok) {
261
- throw new Error(await response.text());
262
- }
263
-
264
- const result = await response.json();
265
-
266
- const newTab = {
267
- id: `builder-${result.id}`,
268
- type: 'builder',
269
- name: result.name,
270
- projectId: result.id,
271
- port: result.port
272
- };
273
- tabs.push(newTab);
274
- activeTabId = newTab.id;
275
- renderTabs();
276
- renderTabContent();
277
- showToast(`Builder ${result.name} spawned`, 'success');
278
- } catch (err) {
279
- showToast('Failed to spawn builder: ' + err.message, 'error');
280
- }
281
- }
282
-
283
- // Spawn shell
284
- async function spawnShell() {
285
- try {
286
- const response = await fetch(apiUrl('api/tabs/shell'), {
287
- method: 'POST',
288
- headers: { 'Content-Type': 'application/json' },
289
- body: JSON.stringify({})
290
- });
291
-
292
- if (!response.ok) {
293
- throw new Error(await response.text());
294
- }
295
-
296
- const result = await response.json();
297
-
298
- const newTab = {
299
- id: `shell-${result.id}`,
300
- type: 'shell',
301
- name: result.name,
302
- port: result.port,
303
- utilId: result.id,
304
- pendingLoad: true
305
- };
306
- tabs.push(newTab);
307
- activeTabId = newTab.id;
308
- renderTabs();
309
-
310
- const content = document.getElementById('tab-content');
311
- content.innerHTML = '<div class="empty-state"><p>Starting shell...</p></div>';
312
-
313
- setTimeout(() => {
314
- delete newTab.pendingLoad;
315
- currentTabPort = null;
316
- renderTabContent();
317
- }, 800);
318
-
319
- showToast('Shell spawned', 'success');
320
- } catch (err) {
321
- showToast('Failed to spawn shell: ' + err.message, 'error');
322
- }
323
- }
324
-
325
- // Create new utility shell (quick action button)
326
- async function createNewShell() {
327
- try {
328
- const response = await fetch(apiUrl('api/tabs/shell'), { method: 'POST' });
329
- const data = await response.json();
330
- if (!data.success && data.error) {
331
- showToast(data.error || 'Failed to create shell', 'error');
332
- return;
333
- }
334
- await refresh();
335
- if (data.id) {
336
- selectTab(`shell-${data.id}`);
337
- }
338
- showToast('Shell created', 'success');
339
- } catch (err) {
340
- showToast('Network error: ' + err.message, 'error');
341
- }
342
- }
343
-
344
- // Create new worktree shell (quick action button)
345
- async function createNewWorktreeShell() {
346
- const branch = prompt('Branch name (leave empty for temp worktree):');
347
- if (branch === null) return;
348
-
349
- try {
350
- const response = await fetch(apiUrl('api/tabs/shell'), {
351
- method: 'POST',
352
- headers: { 'Content-Type': 'application/json' },
353
- body: JSON.stringify({ worktree: true, branch: branch || undefined })
354
- });
355
- const data = await response.json();
356
- if (!data.success && data.error) {
357
- showToast(data.error || 'Failed to create worktree shell', 'error');
358
- return;
359
- }
360
- await refresh();
361
- if (data.id) {
362
- selectTab(`shell-${data.id}`);
363
- }
364
- showToast('Worktree shell created', 'success');
365
- } catch (err) {
366
- showToast('Network error: ' + err.message, 'error');
367
- }
368
- }