brainfile 0.18.1 → 0.20.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 (275) hide show
  1. package/README.md +18 -24
  2. package/dist/__tests__/helpers/mcp-wire.d.ts +45 -0
  3. package/dist/__tests__/helpers/mcp-wire.d.ts.map +1 -0
  4. package/dist/__tests__/helpers/mcp-wire.js +133 -0
  5. package/dist/__tests__/helpers/mcp-wire.js.map +1 -0
  6. package/dist/__tests__/helpers/mcp.d.ts +34 -0
  7. package/dist/__tests__/helpers/mcp.d.ts.map +1 -0
  8. package/dist/__tests__/helpers/mcp.js +37 -0
  9. package/dist/__tests__/helpers/mcp.js.map +1 -0
  10. package/dist/chunk-I5SJHUZK.mjs +52 -0
  11. package/dist/chunk-UOCQBEEW.mjs +12583 -0
  12. package/dist/cli.js +8 -479
  13. package/dist/cli.mjs +41334 -0
  14. package/dist/commands/add.d.ts.map +1 -1
  15. package/dist/commands/add.js +28 -37
  16. package/dist/commands/add.js.map +1 -1
  17. package/dist/commands/adr.d.ts +1 -9
  18. package/dist/commands/adr.d.ts.map +1 -1
  19. package/dist/commands/adr.js +11 -88
  20. package/dist/commands/adr.js.map +1 -1
  21. package/dist/commands/archive.d.ts +2 -4
  22. package/dist/commands/archive.d.ts.map +1 -1
  23. package/dist/commands/archive.js +55 -212
  24. package/dist/commands/archive.js.map +1 -1
  25. package/dist/commands/brief.d.ts +31 -0
  26. package/dist/commands/brief.d.ts.map +1 -0
  27. package/dist/commands/brief.js +151 -0
  28. package/dist/commands/brief.js.map +1 -0
  29. package/dist/commands/complete.d.ts +0 -4
  30. package/dist/commands/complete.d.ts.map +1 -1
  31. package/dist/commands/complete.js +14 -168
  32. package/dist/commands/complete.js.map +1 -1
  33. package/dist/commands/contract.d.ts.map +1 -1
  34. package/dist/commands/contract.js +66 -331
  35. package/dist/commands/contract.js.map +1 -1
  36. package/dist/commands/delete.d.ts.map +1 -1
  37. package/dist/commands/delete.js +13 -55
  38. package/dist/commands/delete.js.map +1 -1
  39. package/dist/commands/init.d.ts.map +1 -1
  40. package/dist/commands/init.js +3 -2
  41. package/dist/commands/init.js.map +1 -1
  42. package/dist/commands/list.d.ts.map +1 -1
  43. package/dist/commands/list.js +3 -54
  44. package/dist/commands/list.js.map +1 -1
  45. package/dist/commands/log.js +33 -26
  46. package/dist/commands/log.js.map +1 -1
  47. package/dist/commands/mcp.d.ts +9 -0
  48. package/dist/commands/mcp.d.ts.map +1 -1
  49. package/dist/commands/mcp.js +34 -18
  50. package/dist/commands/mcp.js.map +1 -1
  51. package/dist/commands/migrate.d.ts.map +1 -1
  52. package/dist/commands/migrate.js +14 -15
  53. package/dist/commands/migrate.js.map +1 -1
  54. package/dist/commands/move.d.ts.map +1 -1
  55. package/dist/commands/move.js +31 -126
  56. package/dist/commands/move.js.map +1 -1
  57. package/dist/commands/patch.d.ts.map +1 -1
  58. package/dist/commands/patch.js +22 -92
  59. package/dist/commands/patch.js.map +1 -1
  60. package/dist/commands/plan.d.ts +61 -0
  61. package/dist/commands/plan.d.ts.map +1 -0
  62. package/dist/commands/plan.js +205 -0
  63. package/dist/commands/plan.js.map +1 -0
  64. package/dist/commands/search.d.ts.map +1 -1
  65. package/dist/commands/search.js +20 -146
  66. package/dist/commands/search.js.map +1 -1
  67. package/dist/commands/show.d.ts.map +1 -1
  68. package/dist/commands/show.js +5 -126
  69. package/dist/commands/show.js.map +1 -1
  70. package/dist/commands/subtask.d.ts.map +1 -1
  71. package/dist/commands/subtask.js +19 -135
  72. package/dist/commands/subtask.js.map +1 -1
  73. package/dist/commands/types.d.ts +2 -2
  74. package/dist/commands/types.d.ts.map +1 -1
  75. package/dist/commands/types.js +8 -30
  76. package/dist/commands/types.js.map +1 -1
  77. package/dist/devtools-NE5M3KPM.mjs +92 -0
  78. package/dist/lib/contractRunner.d.ts.map +1 -1
  79. package/dist/lib/contractRunner.js +19 -205
  80. package/dist/lib/contractRunner.js.map +1 -1
  81. package/dist/mcp/helpers.d.ts +11 -16
  82. package/dist/mcp/helpers.d.ts.map +1 -1
  83. package/dist/mcp/helpers.js +9 -46
  84. package/dist/mcp/helpers.js.map +1 -1
  85. package/dist/mcp/schemas.d.ts +297 -0
  86. package/dist/mcp/schemas.d.ts.map +1 -0
  87. package/dist/mcp/schemas.js +328 -0
  88. package/dist/mcp/schemas.js.map +1 -0
  89. package/dist/mcp/tools/brief_tool.d.ts +14 -0
  90. package/dist/mcp/tools/brief_tool.d.ts.map +1 -0
  91. package/dist/mcp/tools/brief_tool.js +58 -0
  92. package/dist/mcp/tools/brief_tool.js.map +1 -0
  93. package/dist/mcp/tools/contract_tool.d.ts +1 -1
  94. package/dist/mcp/tools/contract_tool.d.ts.map +1 -1
  95. package/dist/mcp/tools/contract_tool.js +58 -186
  96. package/dist/mcp/tools/contract_tool.js.map +1 -1
  97. package/dist/mcp/tools/get_task_tool.d.ts +1 -1
  98. package/dist/mcp/tools/get_task_tool.d.ts.map +1 -1
  99. package/dist/mcp/tools/get_task_tool.js +18 -32
  100. package/dist/mcp/tools/get_task_tool.js.map +1 -1
  101. package/dist/mcp/tools/list_tasks_tool.d.ts +1 -1
  102. package/dist/mcp/tools/list_tasks_tool.d.ts.map +1 -1
  103. package/dist/mcp/tools/list_tasks_tool.js +14 -45
  104. package/dist/mcp/tools/list_tasks_tool.js.map +1 -1
  105. package/dist/mcp/tools/search_tool.d.ts +1 -1
  106. package/dist/mcp/tools/search_tool.d.ts.map +1 -1
  107. package/dist/mcp/tools/search_tool.js +33 -101
  108. package/dist/mcp/tools/search_tool.js.map +1 -1
  109. package/dist/mcp/tools/subtask_tool.d.ts +1 -1
  110. package/dist/mcp/tools/subtask_tool.d.ts.map +1 -1
  111. package/dist/mcp/tools/subtask_tool.js +95 -236
  112. package/dist/mcp/tools/subtask_tool.js.map +1 -1
  113. package/dist/mcp/tools/task_add_tool.d.ts +1 -1
  114. package/dist/mcp/tools/task_add_tool.d.ts.map +1 -1
  115. package/dist/mcp/tools/task_add_tool.js +63 -154
  116. package/dist/mcp/tools/task_add_tool.js.map +1 -1
  117. package/dist/mcp/tools/task_complete_tool.d.ts +1 -1
  118. package/dist/mcp/tools/task_complete_tool.d.ts.map +1 -1
  119. package/dist/mcp/tools/task_complete_tool.js +59 -127
  120. package/dist/mcp/tools/task_complete_tool.js.map +1 -1
  121. package/dist/mcp/tools/task_delete_tool.d.ts +1 -1
  122. package/dist/mcp/tools/task_delete_tool.d.ts.map +1 -1
  123. package/dist/mcp/tools/task_delete_tool.js +19 -33
  124. package/dist/mcp/tools/task_delete_tool.js.map +1 -1
  125. package/dist/mcp/tools/task_move_tool.d.ts +1 -1
  126. package/dist/mcp/tools/task_move_tool.d.ts.map +1 -1
  127. package/dist/mcp/tools/task_move_tool.js +53 -150
  128. package/dist/mcp/tools/task_move_tool.js.map +1 -1
  129. package/dist/mcp/tools/task_patch_tool.d.ts +1 -1
  130. package/dist/mcp/tools/task_patch_tool.d.ts.map +1 -1
  131. package/dist/mcp/tools/task_patch_tool.js +49 -113
  132. package/dist/mcp/tools/task_patch_tool.js.map +1 -1
  133. package/dist/open-ZGSQIGEH.mjs +542 -0
  134. package/dist/schemas/board.json +1 -1
  135. package/dist/tui/theme.d.ts +74 -95
  136. package/dist/tui/theme.d.ts.map +1 -1
  137. package/dist/tui/theme.js +113 -110
  138. package/dist/tui/theme.js.map +1 -1
  139. package/dist/tui-H3RI22S4.mjs +23374 -0
  140. package/dist/utils/cli-error.d.ts +20 -0
  141. package/dist/utils/cli-error.d.ts.map +1 -1
  142. package/dist/utils/cli-error.js +36 -0
  143. package/dist/utils/cli-error.js.map +1 -1
  144. package/dist/utils/dot-brainfile.d.ts +0 -4
  145. package/dist/utils/dot-brainfile.d.ts.map +1 -1
  146. package/dist/utils/dot-brainfile.js +0 -17
  147. package/dist/utils/dot-brainfile.js.map +1 -1
  148. package/dist/utils/errorHandler.d.ts +7 -11
  149. package/dist/utils/errorHandler.d.ts.map +1 -1
  150. package/dist/utils/errorHandler.js +8 -19
  151. package/dist/utils/errorHandler.js.map +1 -1
  152. package/package.json +24 -16
  153. package/dist/cli.d.ts +0 -3
  154. package/dist/cli.d.ts.map +0 -1
  155. package/dist/cli.js.map +0 -1
  156. package/dist/commands/rules.d.ts +0 -68
  157. package/dist/commands/rules.d.ts.map +0 -1
  158. package/dist/commands/rules.js +0 -322
  159. package/dist/commands/rules.js.map +0 -1
  160. package/dist/commands/tui.d.ts +0 -6
  161. package/dist/commands/tui.d.ts.map +0 -1
  162. package/dist/commands/tui.js +0 -79
  163. package/dist/commands/tui.js.map +0 -1
  164. package/dist/tui/BrainfileTUI.d.ts +0 -4
  165. package/dist/tui/BrainfileTUI.d.ts.map +0 -1
  166. package/dist/tui/BrainfileTUI.js +0 -272
  167. package/dist/tui/BrainfileTUI.js.map +0 -1
  168. package/dist/tui/actions.d.ts +0 -84
  169. package/dist/tui/actions.d.ts.map +0 -1
  170. package/dist/tui/actions.js +0 -1251
  171. package/dist/tui/actions.js.map +0 -1
  172. package/dist/tui/components/ColumnTabs.d.ts +0 -9
  173. package/dist/tui/components/ColumnTabs.d.ts.map +0 -1
  174. package/dist/tui/components/ColumnTabs.js +0 -34
  175. package/dist/tui/components/ColumnTabs.js.map +0 -1
  176. package/dist/tui/components/Header.d.ts +0 -15
  177. package/dist/tui/components/Header.d.ts.map +0 -1
  178. package/dist/tui/components/Header.js +0 -48
  179. package/dist/tui/components/Header.js.map +0 -1
  180. package/dist/tui/components/HelpOverlay.d.ts +0 -9
  181. package/dist/tui/components/HelpOverlay.d.ts.map +0 -1
  182. package/dist/tui/components/HelpOverlay.js +0 -116
  183. package/dist/tui/components/HelpOverlay.js.map +0 -1
  184. package/dist/tui/components/LogsPanel.d.ts +0 -16
  185. package/dist/tui/components/LogsPanel.d.ts.map +0 -1
  186. package/dist/tui/components/LogsPanel.js +0 -115
  187. package/dist/tui/components/LogsPanel.js.map +0 -1
  188. package/dist/tui/components/MainPanelTabs.d.ts +0 -10
  189. package/dist/tui/components/MainPanelTabs.d.ts.map +0 -1
  190. package/dist/tui/components/MainPanelTabs.js +0 -56
  191. package/dist/tui/components/MainPanelTabs.js.map +0 -1
  192. package/dist/tui/components/ManualBorder.d.ts +0 -42
  193. package/dist/tui/components/ManualBorder.d.ts.map +0 -1
  194. package/dist/tui/components/ManualBorder.js +0 -56
  195. package/dist/tui/components/ManualBorder.js.map +0 -1
  196. package/dist/tui/components/Overlays.d.ts +0 -41
  197. package/dist/tui/components/Overlays.d.ts.map +0 -1
  198. package/dist/tui/components/Overlays.js +0 -127
  199. package/dist/tui/components/Overlays.js.map +0 -1
  200. package/dist/tui/components/ProgressBar.d.ts +0 -8
  201. package/dist/tui/components/ProgressBar.d.ts.map +0 -1
  202. package/dist/tui/components/ProgressBar.js +0 -35
  203. package/dist/tui/components/ProgressBar.js.map +0 -1
  204. package/dist/tui/components/RulesPanel.d.ts +0 -25
  205. package/dist/tui/components/RulesPanel.d.ts.map +0 -1
  206. package/dist/tui/components/RulesPanel.js +0 -139
  207. package/dist/tui/components/RulesPanel.js.map +0 -1
  208. package/dist/tui/components/SearchBar.d.ts +0 -8
  209. package/dist/tui/components/SearchBar.d.ts.map +0 -1
  210. package/dist/tui/components/SearchBar.js +0 -38
  211. package/dist/tui/components/SearchBar.js.map +0 -1
  212. package/dist/tui/components/StackedTaskList.d.ts +0 -27
  213. package/dist/tui/components/StackedTaskList.d.ts.map +0 -1
  214. package/dist/tui/components/StackedTaskList.js +0 -120
  215. package/dist/tui/components/StackedTaskList.js.map +0 -1
  216. package/dist/tui/components/StatusBar.d.ts +0 -14
  217. package/dist/tui/components/StatusBar.d.ts.map +0 -1
  218. package/dist/tui/components/StatusBar.js +0 -42
  219. package/dist/tui/components/StatusBar.js.map +0 -1
  220. package/dist/tui/components/TaskCard.d.ts +0 -25
  221. package/dist/tui/components/TaskCard.d.ts.map +0 -1
  222. package/dist/tui/components/TaskCard.js +0 -221
  223. package/dist/tui/components/TaskCard.js.map +0 -1
  224. package/dist/tui/components/TaskCardMeasure.d.ts +0 -31
  225. package/dist/tui/components/TaskCardMeasure.d.ts.map +0 -1
  226. package/dist/tui/components/TaskCardMeasure.js +0 -133
  227. package/dist/tui/components/TaskCardMeasure.js.map +0 -1
  228. package/dist/tui/components/TaskDetail.d.ts +0 -13
  229. package/dist/tui/components/TaskDetail.d.ts.map +0 -1
  230. package/dist/tui/components/TaskDetail.js +0 -64
  231. package/dist/tui/components/TaskDetail.js.map +0 -1
  232. package/dist/tui/components/TaskList.d.ts +0 -12
  233. package/dist/tui/components/TaskList.d.ts.map +0 -1
  234. package/dist/tui/components/TaskList.js +0 -75
  235. package/dist/tui/components/TaskList.js.map +0 -1
  236. package/dist/tui/components/index.d.ts +0 -31
  237. package/dist/tui/components/index.d.ts.map +0 -1
  238. package/dist/tui/components/index.js +0 -43
  239. package/dist/tui/components/index.js.map +0 -1
  240. package/dist/tui/hooks/index.d.ts +0 -3
  241. package/dist/tui/hooks/index.d.ts.map +0 -1
  242. package/dist/tui/hooks/index.js +0 -8
  243. package/dist/tui/hooks/index.js.map +0 -1
  244. package/dist/tui/hooks/useBrainfileLoader.d.ts +0 -5
  245. package/dist/tui/hooks/useBrainfileLoader.d.ts.map +0 -1
  246. package/dist/tui/hooks/useBrainfileLoader.js +0 -237
  247. package/dist/tui/hooks/useBrainfileLoader.js.map +0 -1
  248. package/dist/tui/hooks/useKeyboardNavigation.d.ts +0 -20
  249. package/dist/tui/hooks/useKeyboardNavigation.d.ts.map +0 -1
  250. package/dist/tui/hooks/useKeyboardNavigation.js +0 -806
  251. package/dist/tui/hooks/useKeyboardNavigation.js.map +0 -1
  252. package/dist/tui/index.d.ts +0 -10
  253. package/dist/tui/index.d.ts.map +0 -1
  254. package/dist/tui/index.js +0 -38
  255. package/dist/tui/index.js.map +0 -1
  256. package/dist/tui/types.d.ts +0 -53
  257. package/dist/tui/types.d.ts.map +0 -1
  258. package/dist/tui/types.js +0 -12
  259. package/dist/tui/types.js.map +0 -1
  260. package/dist/tui/utils.d.ts +0 -24
  261. package/dist/tui/utils.d.ts.map +0 -1
  262. package/dist/tui/utils.js +0 -161
  263. package/dist/tui/utils.js.map +0 -1
  264. package/dist/utils/board-types.d.ts +0 -13
  265. package/dist/utils/board-types.d.ts.map +0 -1
  266. package/dist/utils/board-types.js +0 -7
  267. package/dist/utils/board-types.js.map +0 -1
  268. package/dist/utils/contractSpec.d.ts +0 -13
  269. package/dist/utils/contractSpec.d.ts.map +0 -1
  270. package/dist/utils/contractSpec.js +0 -61
  271. package/dist/utils/contractSpec.js.map +0 -1
  272. package/dist/utils/strict-validation.d.ts +0 -8
  273. package/dist/utils/strict-validation.d.ts.map +0 -1
  274. package/dist/utils/strict-validation.js +0 -41
  275. package/dist/utils/strict-validation.js.map +0 -1
@@ -1,806 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useKeyboardNavigation = useKeyboardNavigation;
4
- const ink_1 = require("ink");
5
- const actions_js_1 = require("../actions.js");
6
- const RULE_TYPES = ['always', 'never', 'prefer', 'context'];
7
- // Helper to show status message
8
- function showStatus(setState, text, type) {
9
- const timestamp = Date.now();
10
- setState(prev => ({
11
- ...prev,
12
- statusMessage: { text, type, timestamp },
13
- }));
14
- // Clear message after 3 seconds
15
- setTimeout(() => {
16
- setState(prev => {
17
- // Only clear if it's the same message
18
- if (prev.statusMessage?.timestamp === timestamp) {
19
- return { ...prev, statusMessage: null };
20
- }
21
- return prev;
22
- });
23
- }, 3000);
24
- }
25
- function useKeyboardNavigation({ state, setState, currentTasks, maxTaskIndex, filteredColumnsLength, viewportHeight, loadBrainfile, filePath, allColumns, layoutMode, flatTasks, maxGlobalIndex, }) {
26
- const { exit } = (0, ink_1.useApp)();
27
- // Get current task based on layout mode
28
- const currentTask = layoutMode === 'wide'
29
- ? currentTasks[state.selectedTaskIndex]
30
- : flatTasks[state.selectedGlobalIndex]?.task;
31
- (0, ink_1.useInput)((input, key) => {
32
- // Help mode - any key closes
33
- if (state.mode === 'help') {
34
- setState(prev => ({ ...prev, mode: 'browse' }));
35
- return;
36
- }
37
- // Delete confirmation mode
38
- if (state.mode === 'delete-confirm') {
39
- if (input === 'y' || input === 'Y') {
40
- if (currentTask) {
41
- const result = (0, actions_js_1.deleteTaskAction)(filePath, currentTask.id);
42
- if (result.success) {
43
- showStatus(setState, `Deleted ${currentTask.id}`, 'success');
44
- loadBrainfile(true);
45
- }
46
- else {
47
- showStatus(setState, result.error || 'Failed to delete', 'error');
48
- }
49
- }
50
- setState(prev => ({ ...prev, mode: 'browse' }));
51
- return;
52
- }
53
- if (input === 'n' || input === 'N' || key.escape) {
54
- setState(prev => ({ ...prev, mode: 'browse' }));
55
- showStatus(setState, 'Delete cancelled', 'info');
56
- return;
57
- }
58
- return;
59
- }
60
- // Move mode - column picker
61
- if (state.mode === 'move') {
62
- if (key.escape) {
63
- setState(prev => ({ ...prev, mode: 'browse' }));
64
- return;
65
- }
66
- if (key.leftArrow || input === 'h') {
67
- setState(prev => ({
68
- ...prev,
69
- moveTargetIndex: Math.max(0, prev.moveTargetIndex - 1),
70
- }));
71
- return;
72
- }
73
- if (key.rightArrow || input === 'l') {
74
- setState(prev => ({
75
- ...prev,
76
- moveTargetIndex: Math.min(allColumns.length - 1, prev.moveTargetIndex + 1),
77
- }));
78
- return;
79
- }
80
- if (key.return) {
81
- if (currentTask) {
82
- const targetColumn = allColumns[state.moveTargetIndex];
83
- if (targetColumn) {
84
- const result = (0, actions_js_1.moveTaskAction)(filePath, currentTask.id, targetColumn.id);
85
- if (result.success) {
86
- showStatus(setState, result.message || `Moved to ${targetColumn.title}`, 'success');
87
- loadBrainfile(true);
88
- }
89
- else {
90
- showStatus(setState, result.error || 'Failed to move', 'error');
91
- }
92
- }
93
- }
94
- setState(prev => ({ ...prev, mode: 'browse' }));
95
- return;
96
- }
97
- // Number keys 1-9 to jump to column
98
- const num = parseInt(input, 10);
99
- if (num >= 1 && num <= allColumns.length) {
100
- setState(prev => ({ ...prev, moveTargetIndex: num - 1 }));
101
- return;
102
- }
103
- return;
104
- }
105
- // Subtask mode - toggle subtasks
106
- if (state.mode === 'subtask') {
107
- const subtasks = currentTask?.subtasks || [];
108
- if (key.escape) {
109
- setState(prev => ({ ...prev, mode: 'browse' }));
110
- return;
111
- }
112
- if (key.upArrow || input === 'k') {
113
- setState(prev => ({
114
- ...prev,
115
- selectedSubtaskIndex: Math.max(0, prev.selectedSubtaskIndex - 1),
116
- }));
117
- return;
118
- }
119
- if (key.downArrow || input === 'j') {
120
- setState(prev => ({
121
- ...prev,
122
- selectedSubtaskIndex: Math.min(subtasks.length - 1, prev.selectedSubtaskIndex + 1),
123
- }));
124
- return;
125
- }
126
- if (key.return || input === ' ') {
127
- const subtask = subtasks[state.selectedSubtaskIndex];
128
- if (currentTask && subtask) {
129
- const result = (0, actions_js_1.toggleSubtaskAction)(filePath, currentTask.id, subtask.id);
130
- if (result.success) {
131
- showStatus(setState, `Toggled ${subtask.id}`, 'success');
132
- loadBrainfile(true);
133
- }
134
- else {
135
- showStatus(setState, result.error || 'Failed to toggle', 'error');
136
- }
137
- }
138
- return;
139
- }
140
- return;
141
- }
142
- // New task mode - inline title input
143
- if (state.mode === 'new-task') {
144
- if (key.escape) {
145
- setState(prev => ({ ...prev, mode: 'browse', newTaskTitle: '' }));
146
- return;
147
- }
148
- if (key.return) {
149
- const title = state.newTaskTitle.trim();
150
- if (title) {
151
- const currentCol = allColumns[state.activeColumnIndex];
152
- if (currentCol) {
153
- const result = (0, actions_js_1.addTaskAction)(filePath, currentCol.id, { title });
154
- if (result.success) {
155
- showStatus(setState, result.message || 'Task added', 'success');
156
- loadBrainfile(true);
157
- }
158
- else {
159
- showStatus(setState, result.error || 'Failed to add task', 'error');
160
- }
161
- }
162
- }
163
- else {
164
- showStatus(setState, 'Title required', 'error');
165
- }
166
- setState(prev => ({ ...prev, mode: 'browse', newTaskTitle: '' }));
167
- return;
168
- }
169
- if (key.backspace || key.delete) {
170
- setState(prev => ({ ...prev, newTaskTitle: prev.newTaskTitle.slice(0, -1) }));
171
- return;
172
- }
173
- if (input && !key.ctrl && !key.meta) {
174
- setState(prev => ({ ...prev, newTaskTitle: prev.newTaskTitle + input }));
175
- return;
176
- }
177
- return;
178
- }
179
- // Search mode handling (Tasks panel)
180
- if (state.mode === 'search') {
181
- if (key.escape) {
182
- setState(prev => ({ ...prev, mode: 'browse', searchQuery: '' }));
183
- return;
184
- }
185
- if (key.return) {
186
- setState(prev => ({ ...prev, mode: 'browse' }));
187
- return;
188
- }
189
- if (key.backspace || key.delete) {
190
- setState(prev => ({ ...prev, searchQuery: prev.searchQuery.slice(0, -1) }));
191
- return;
192
- }
193
- if (input && !key.ctrl && !key.meta) {
194
- setState(prev => ({ ...prev, searchQuery: prev.searchQuery + input }));
195
- return;
196
- }
197
- return;
198
- }
199
- // Rule add/edit mode
200
- if (state.mode === 'rule-add' || state.mode === 'rule-edit') {
201
- if (key.escape) {
202
- setState(prev => ({ ...prev, mode: 'browse', ruleEditText: '', ruleEditId: null }));
203
- return;
204
- }
205
- if (key.return) {
206
- const text = state.ruleEditText.trim();
207
- if (!text) {
208
- showStatus(setState, 'Rule text required', 'error');
209
- return;
210
- }
211
- if (state.mode === 'rule-add') {
212
- const result = (0, actions_js_1.addRuleAction)(filePath, state.activeRuleType, text);
213
- if (result.success) {
214
- showStatus(setState, result.message || 'Rule added', 'success');
215
- loadBrainfile(true);
216
- }
217
- else {
218
- showStatus(setState, result.error || 'Failed to add rule', 'error');
219
- }
220
- }
221
- else if (state.ruleEditId !== null) {
222
- const result = (0, actions_js_1.updateRuleAction)(filePath, state.activeRuleType, state.ruleEditId, text);
223
- if (result.success) {
224
- showStatus(setState, result.message || 'Rule updated', 'success');
225
- loadBrainfile(true);
226
- }
227
- else {
228
- showStatus(setState, result.error || 'Failed to update rule', 'error');
229
- }
230
- }
231
- setState(prev => ({ ...prev, mode: 'browse', ruleEditText: '', ruleEditId: null }));
232
- return;
233
- }
234
- if (key.backspace || key.delete) {
235
- setState(prev => ({ ...prev, ruleEditText: prev.ruleEditText.slice(0, -1) }));
236
- return;
237
- }
238
- if (input && !key.ctrl && !key.meta) {
239
- setState(prev => ({ ...prev, ruleEditText: prev.ruleEditText + input }));
240
- return;
241
- }
242
- return;
243
- }
244
- // Rule delete confirmation
245
- if (state.mode === 'rule-delete-confirm') {
246
- const rules = state.board?.rules?.[state.activeRuleType] || [];
247
- const rule = rules[state.selectedRuleIndex];
248
- if (input === 'y' || input === 'Y') {
249
- if (rule) {
250
- const result = (0, actions_js_1.deleteRuleAction)(filePath, state.activeRuleType, rule.id);
251
- if (result.success) {
252
- showStatus(setState, result.message || 'Rule deleted', 'success');
253
- loadBrainfile(true);
254
- // Adjust selection if needed
255
- setState(prev => ({
256
- ...prev,
257
- mode: 'browse',
258
- selectedRuleIndex: Math.max(0, prev.selectedRuleIndex - 1),
259
- }));
260
- }
261
- else {
262
- showStatus(setState, result.error || 'Failed to delete rule', 'error');
263
- setState(prev => ({ ...prev, mode: 'browse' }));
264
- }
265
- }
266
- return;
267
- }
268
- if (input === 'n' || input === 'N' || key.escape) {
269
- setState(prev => ({ ...prev, mode: 'browse' }));
270
- showStatus(setState, 'Delete cancelled', 'info');
271
- return;
272
- }
273
- return;
274
- }
275
- // Logs restore mode - column picker
276
- if (state.mode === 'logs-restore') {
277
- if (key.escape) {
278
- setState(prev => ({ ...prev, mode: 'browse' }));
279
- return;
280
- }
281
- if (key.downArrow || input === 'j') {
282
- setState(prev => ({
283
- ...prev,
284
- logRestoreColumnIndex: Math.min(prev.logRestoreColumnIndex + 1, allColumns.length - 1),
285
- }));
286
- return;
287
- }
288
- if (key.upArrow || input === 'k') {
289
- setState(prev => ({
290
- ...prev,
291
- logRestoreColumnIndex: Math.max(prev.logRestoreColumnIndex - 1, 0),
292
- }));
293
- return;
294
- }
295
- if (key.return) {
296
- const task = state.logs[state.selectedLogIndex];
297
- const column = allColumns[state.logRestoreColumnIndex];
298
- if (task && column) {
299
- const result = (0, actions_js_1.restoreTaskAction)(filePath, task.id, column.id);
300
- if (result.success) {
301
- showStatus(setState, result.message || 'Task restored', 'success');
302
- loadBrainfile(true);
303
- // Reload logs
304
- const logResult = (0, actions_js_1.loadLogs)(filePath);
305
- setState(prev => ({
306
- ...prev,
307
- mode: 'browse',
308
- logs: logResult.logs,
309
- selectedLogIndex: Math.max(0, prev.selectedLogIndex - 1),
310
- }));
311
- }
312
- else {
313
- showStatus(setState, result.error || 'Failed to restore task', 'error');
314
- setState(prev => ({ ...prev, mode: 'browse' }));
315
- }
316
- }
317
- return;
318
- }
319
- return;
320
- }
321
- // Logs delete confirmation
322
- if (state.mode === 'logs-delete-confirm') {
323
- const task = state.logs[state.selectedLogIndex];
324
- if (input === 'y' || input === 'Y') {
325
- if (task) {
326
- const result = (0, actions_js_1.deleteArchivedTaskAction)(filePath, task.id);
327
- if (result.success) {
328
- showStatus(setState, result.message || 'Task permanently deleted', 'success');
329
- // Reload logs
330
- const logResult = (0, actions_js_1.loadLogs)(filePath);
331
- setState(prev => ({
332
- ...prev,
333
- mode: 'browse',
334
- logs: logResult.logs,
335
- selectedLogIndex: Math.max(0, prev.selectedLogIndex - 1),
336
- }));
337
- }
338
- else {
339
- showStatus(setState, result.error || 'Failed to delete task', 'error');
340
- setState(prev => ({ ...prev, mode: 'browse' }));
341
- }
342
- }
343
- return;
344
- }
345
- if (input === 'n' || input === 'N' || key.escape) {
346
- setState(prev => ({ ...prev, mode: 'browse' }));
347
- showStatus(setState, 'Delete cancelled', 'info');
348
- return;
349
- }
350
- return;
351
- }
352
- // ============================================================
353
- // GLOBAL KEYS (work in browse mode across all panels)
354
- // ============================================================
355
- if (input === 'q' || (key.ctrl && input === 'c')) {
356
- exit();
357
- return;
358
- }
359
- if (input === '?') {
360
- setState(prev => ({ ...prev, mode: 'help' }));
361
- return;
362
- }
363
- // Panel switching: 1/2/3
364
- if (input === '1') {
365
- setState(prev => ({ ...prev, activePanel: 'tasks', mode: 'browse' }));
366
- return;
367
- }
368
- if (input === '2') {
369
- setState(prev => ({ ...prev, activePanel: 'rules', mode: 'browse' }));
370
- return;
371
- }
372
- if (input === '3') {
373
- setState(prev => ({ ...prev, activePanel: 'logs', mode: 'browse' }));
374
- // Logs are loaded via useEffect in BrainfileTUI
375
- return;
376
- }
377
- // Refresh (force refresh bypasses hash check)
378
- if (input === 'r' && state.activePanel !== 'logs') {
379
- loadBrainfile(true);
380
- showStatus(setState, 'Refreshed', 'info');
381
- return;
382
- }
383
- // ============================================================
384
- // TASKS PANEL - Browse mode
385
- // ============================================================
386
- if (state.activePanel === 'tasks') {
387
- if (input === '/') {
388
- setState(prev => ({ ...prev, mode: 'search', searchQuery: '' }));
389
- return;
390
- }
391
- // 'e' - Edit task in $EDITOR
392
- if (input === 'e') {
393
- if (!currentTask) {
394
- showStatus(setState, 'No task selected', 'error');
395
- return;
396
- }
397
- const result = (0, actions_js_1.editTaskInEditor)(filePath, currentTask.id);
398
- if (result.success) {
399
- showStatus(setState, result.message || 'Task updated', 'success');
400
- loadBrainfile(true);
401
- }
402
- else {
403
- showStatus(setState, result.error || 'Edit failed', 'error');
404
- }
405
- return;
406
- }
407
- // 'm' - Move task
408
- if (input === 'm') {
409
- if (!currentTask) {
410
- showStatus(setState, 'No task selected', 'error');
411
- return;
412
- }
413
- setState(prev => ({ ...prev, mode: 'move', moveTargetIndex: prev.activeColumnIndex }));
414
- return;
415
- }
416
- // 'd' - Delete task
417
- if (input === 'd') {
418
- if (!currentTask) {
419
- showStatus(setState, 'No task selected', 'error');
420
- return;
421
- }
422
- setState(prev => ({ ...prev, mode: 'delete-confirm' }));
423
- return;
424
- }
425
- // 'A' - Move task to logs (supports external destinations)
426
- if (input === 'A') {
427
- if (!currentTask) {
428
- showStatus(setState, 'No task selected', 'error');
429
- return;
430
- }
431
- // Show status while async operation runs
432
- showStatus(setState, 'Moving to logs...', 'info');
433
- // Call async archive function (supports GitHub/Linear destinations)
434
- (0, actions_js_1.archiveTaskActionAsync)(filePath, currentTask.id).then((result) => {
435
- if (result.success) {
436
- showStatus(setState, result.message || 'Task moved to logs', 'success');
437
- loadBrainfile(true);
438
- }
439
- else {
440
- showStatus(setState, result.error || 'Move to logs failed', 'error');
441
- }
442
- }).catch((err) => {
443
- showStatus(setState, `Move to logs failed: ${err}`, 'error');
444
- });
445
- return;
446
- }
447
- // 'p' - Cycle priority
448
- if (input === 'p') {
449
- if (!currentTask) {
450
- showStatus(setState, 'No task selected', 'error');
451
- return;
452
- }
453
- const result = (0, actions_js_1.cyclePriorityAction)(filePath, currentTask.id);
454
- if (result.success) {
455
- showStatus(setState, result.message || 'Priority updated', 'success');
456
- loadBrainfile(true);
457
- }
458
- else {
459
- showStatus(setState, result.error || 'Failed to update priority', 'error');
460
- }
461
- return;
462
- }
463
- // 't' - Toggle subtask
464
- if (input === 't') {
465
- if (!currentTask) {
466
- showStatus(setState, 'No task selected', 'error');
467
- return;
468
- }
469
- if (!currentTask.subtasks || currentTask.subtasks.length === 0) {
470
- showStatus(setState, 'No subtasks', 'info');
471
- return;
472
- }
473
- setState(prev => ({ ...prev, mode: 'subtask', selectedSubtaskIndex: 0 }));
474
- return;
475
- }
476
- // 'y' - Copy task ID
477
- if (input === 'y') {
478
- if (!currentTask) {
479
- showStatus(setState, 'No task selected', 'error');
480
- return;
481
- }
482
- const result = (0, actions_js_1.copyToClipboard)(currentTask.id);
483
- if (result.success) {
484
- showStatus(setState, `Copied ${currentTask.id}`, 'success');
485
- }
486
- else {
487
- showStatus(setState, result.error || 'Copy failed', 'error');
488
- }
489
- return;
490
- }
491
- // 'n' - New task (quick)
492
- if (input === 'n') {
493
- setState(prev => ({ ...prev, mode: 'new-task', newTaskTitle: '' }));
494
- return;
495
- }
496
- // 'N' - New task (editor)
497
- if (input === 'N') {
498
- const currentCol = allColumns[state.activeColumnIndex];
499
- if (currentCol) {
500
- const result = (0, actions_js_1.newTaskInEditor)(filePath, currentCol.id);
501
- if (result.success) {
502
- showStatus(setState, result.message || 'Task created', 'success');
503
- loadBrainfile(true);
504
- }
505
- else {
506
- showStatus(setState, result.error || 'Failed to create task', 'error');
507
- }
508
- }
509
- return;
510
- }
511
- // Navigation: up/down
512
- if (key.downArrow || input === 'j') {
513
- if (layoutMode === 'narrow') {
514
- setState(prev => ({
515
- ...prev,
516
- selectedGlobalIndex: Math.min(prev.selectedGlobalIndex + 1, maxGlobalIndex),
517
- }));
518
- }
519
- else {
520
- setState(prev => ({
521
- ...prev,
522
- selectedTaskIndex: Math.min(prev.selectedTaskIndex + 1, maxTaskIndex),
523
- }));
524
- }
525
- return;
526
- }
527
- if (key.upArrow || input === 'k') {
528
- if (layoutMode === 'narrow') {
529
- setState(prev => ({
530
- ...prev,
531
- selectedGlobalIndex: Math.max(prev.selectedGlobalIndex - 1, 0),
532
- }));
533
- }
534
- else {
535
- setState(prev => ({
536
- ...prev,
537
- selectedTaskIndex: Math.max(prev.selectedTaskIndex - 1, 0),
538
- }));
539
- }
540
- return;
541
- }
542
- // Page scrolling
543
- if (key.ctrl && input === 'd') {
544
- if (layoutMode === 'narrow') {
545
- setState(prev => ({
546
- ...prev,
547
- selectedGlobalIndex: Math.min(prev.selectedGlobalIndex + Math.floor(viewportHeight / 2), maxGlobalIndex),
548
- }));
549
- }
550
- else {
551
- setState(prev => ({
552
- ...prev,
553
- selectedTaskIndex: Math.min(prev.selectedTaskIndex + Math.floor(viewportHeight / 2), maxTaskIndex),
554
- }));
555
- }
556
- return;
557
- }
558
- if (key.ctrl && input === 'u') {
559
- if (layoutMode === 'narrow') {
560
- setState(prev => ({
561
- ...prev,
562
- selectedGlobalIndex: Math.max(prev.selectedGlobalIndex - Math.floor(viewportHeight / 2), 0),
563
- }));
564
- }
565
- else {
566
- setState(prev => ({
567
- ...prev,
568
- selectedTaskIndex: Math.max(prev.selectedTaskIndex - Math.floor(viewportHeight / 2), 0),
569
- }));
570
- }
571
- return;
572
- }
573
- // Column switching (wide mode only - narrow mode navigates all tasks with j/k)
574
- if (layoutMode === 'wide') {
575
- if (key.tab || key.rightArrow || input === 'l') {
576
- setState(prev => ({
577
- ...prev,
578
- activeColumnIndex: (prev.activeColumnIndex + 1) % filteredColumnsLength,
579
- selectedTaskIndex: 0,
580
- }));
581
- return;
582
- }
583
- if ((key.shift && key.tab) || key.leftArrow || input === 'h') {
584
- setState(prev => ({
585
- ...prev,
586
- activeColumnIndex: prev.activeColumnIndex === 0
587
- ? filteredColumnsLength - 1
588
- : prev.activeColumnIndex - 1,
589
- selectedTaskIndex: 0,
590
- }));
591
- return;
592
- }
593
- }
594
- // Home/End
595
- if (input === 'g') {
596
- if (layoutMode === 'narrow') {
597
- setState(prev => ({ ...prev, selectedGlobalIndex: 0 }));
598
- }
599
- else {
600
- setState(prev => ({ ...prev, selectedTaskIndex: 0 }));
601
- }
602
- return;
603
- }
604
- if (input === 'G') {
605
- if (layoutMode === 'narrow') {
606
- setState(prev => ({ ...prev, selectedGlobalIndex: maxGlobalIndex }));
607
- }
608
- else {
609
- setState(prev => ({ ...prev, selectedTaskIndex: maxTaskIndex }));
610
- }
611
- return;
612
- }
613
- // Expand/collapse task
614
- if (key.return) {
615
- const task = layoutMode === 'wide'
616
- ? currentTasks[state.selectedTaskIndex]
617
- : flatTasks[state.selectedGlobalIndex]?.task;
618
- if (task) {
619
- setState(prev => {
620
- const newExpanded = new Set(prev.expandedTaskIds);
621
- if (newExpanded.has(task.id)) {
622
- newExpanded.delete(task.id);
623
- }
624
- else {
625
- newExpanded.add(task.id);
626
- }
627
- return { ...prev, expandedTaskIds: newExpanded };
628
- });
629
- }
630
- return;
631
- }
632
- // Escape: collapse all or clear search
633
- if (key.escape) {
634
- setState(prev => ({
635
- ...prev,
636
- expandedTaskIds: new Set(),
637
- searchQuery: '',
638
- }));
639
- return;
640
- }
641
- }
642
- // ============================================================
643
- // RULES PANEL - Browse mode
644
- // ============================================================
645
- if (state.activePanel === 'rules') {
646
- const rules = state.board?.rules?.[state.activeRuleType] || [];
647
- const maxRuleIndex = Math.max(0, rules.length - 1);
648
- // h/l or left/right or Shift+TAB to switch rule type left
649
- if (key.leftArrow || input === 'h' || (key.shift && key.tab)) {
650
- const currentIdx = RULE_TYPES.indexOf(state.activeRuleType);
651
- const newIdx = currentIdx === 0 ? RULE_TYPES.length - 1 : currentIdx - 1;
652
- setState(prev => ({ ...prev, activeRuleType: RULE_TYPES[newIdx], selectedRuleIndex: 0 }));
653
- return;
654
- }
655
- // TAB or l or right to switch rule type right
656
- if (key.tab || key.rightArrow || input === 'l') {
657
- const currentIdx = RULE_TYPES.indexOf(state.activeRuleType);
658
- const newIdx = (currentIdx + 1) % RULE_TYPES.length;
659
- setState(prev => ({ ...prev, activeRuleType: RULE_TYPES[newIdx], selectedRuleIndex: 0 }));
660
- return;
661
- }
662
- // j/k to navigate rules
663
- if (key.downArrow || input === 'j') {
664
- setState(prev => ({
665
- ...prev,
666
- selectedRuleIndex: Math.min(prev.selectedRuleIndex + 1, maxRuleIndex),
667
- }));
668
- return;
669
- }
670
- if (key.upArrow || input === 'k') {
671
- setState(prev => ({
672
- ...prev,
673
- selectedRuleIndex: Math.max(prev.selectedRuleIndex - 1, 0),
674
- }));
675
- return;
676
- }
677
- // n - New rule
678
- if (input === 'n') {
679
- setState(prev => ({ ...prev, mode: 'rule-add', ruleEditText: '', ruleEditId: null }));
680
- return;
681
- }
682
- // e - Edit rule
683
- if (input === 'e') {
684
- const rule = rules[state.selectedRuleIndex];
685
- if (rule) {
686
- setState(prev => ({
687
- ...prev,
688
- mode: 'rule-edit',
689
- ruleEditText: rule.rule,
690
- ruleEditId: rule.id,
691
- }));
692
- }
693
- else {
694
- showStatus(setState, 'No rule selected', 'error');
695
- }
696
- return;
697
- }
698
- // d - Delete rule
699
- if (input === 'd') {
700
- const rule = rules[state.selectedRuleIndex];
701
- if (rule) {
702
- setState(prev => ({ ...prev, mode: 'rule-delete-confirm' }));
703
- }
704
- else {
705
- showStatus(setState, 'No rule selected', 'error');
706
- }
707
- return;
708
- }
709
- // Home/End
710
- if (input === 'g') {
711
- setState(prev => ({ ...prev, selectedRuleIndex: 0 }));
712
- return;
713
- }
714
- if (input === 'G') {
715
- setState(prev => ({ ...prev, selectedRuleIndex: maxRuleIndex }));
716
- return;
717
- }
718
- // Escape
719
- if (key.escape) {
720
- setState(prev => ({ ...prev, selectedRuleIndex: 0 }));
721
- return;
722
- }
723
- }
724
- // ============================================================
725
- // LOGS PANEL - Browse mode
726
- // ============================================================
727
- if (state.activePanel === 'logs') {
728
- const maxArchiveIndex = Math.max(0, state.logs.length - 1);
729
- // r - Refresh logs
730
- if (input === 'r') {
731
- const result = (0, actions_js_1.loadLogs)(filePath);
732
- setState(prev => ({ ...prev, logs: result.logs }));
733
- showStatus(setState, 'Logs refreshed', 'info');
734
- return;
735
- }
736
- // j/k navigation
737
- if (key.downArrow || input === 'j') {
738
- setState(prev => ({
739
- ...prev,
740
- selectedLogIndex: Math.min(prev.selectedLogIndex + 1, maxArchiveIndex),
741
- }));
742
- return;
743
- }
744
- if (key.upArrow || input === 'k') {
745
- setState(prev => ({
746
- ...prev,
747
- selectedLogIndex: Math.max(prev.selectedLogIndex - 1, 0),
748
- }));
749
- return;
750
- }
751
- // Enter - Expand/collapse
752
- if (key.return) {
753
- const task = state.logs[state.selectedLogIndex];
754
- if (task) {
755
- setState(prev => {
756
- const newExpanded = new Set(prev.expandedLogIds);
757
- if (newExpanded.has(task.id)) {
758
- newExpanded.delete(task.id);
759
- }
760
- else {
761
- newExpanded.add(task.id);
762
- }
763
- return { ...prev, expandedLogIds: newExpanded };
764
- });
765
- }
766
- return;
767
- }
768
- // r key for restore (use 'R' to avoid conflict with refresh)
769
- if (input === 'R') {
770
- if (state.logs.length === 0) {
771
- showStatus(setState, 'No logged tasks', 'error');
772
- return;
773
- }
774
- setState(prev => ({ ...prev, mode: 'logs-restore', logRestoreColumnIndex: 0 }));
775
- return;
776
- }
777
- // d - Delete permanently
778
- if (input === 'd') {
779
- if (state.logs.length === 0) {
780
- showStatus(setState, 'No logged tasks', 'error');
781
- return;
782
- }
783
- setState(prev => ({ ...prev, mode: 'logs-delete-confirm' }));
784
- return;
785
- }
786
- // Home/End
787
- if (input === 'g') {
788
- setState(prev => ({ ...prev, selectedLogIndex: 0 }));
789
- return;
790
- }
791
- if (input === 'G') {
792
- setState(prev => ({ ...prev, selectedLogIndex: maxArchiveIndex }));
793
- return;
794
- }
795
- // Escape - collapse all expanded
796
- if (key.escape) {
797
- setState(prev => ({
798
- ...prev,
799
- expandedLogIds: new Set(),
800
- }));
801
- return;
802
- }
803
- }
804
- });
805
- }
806
- //# sourceMappingURL=useKeyboardNavigation.js.map