loop-task 1.4.3 → 1.4.4
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.
- package/dist/board/components/CreateForm.js +30 -13
- package/dist/board/components/HelpModal.js +8 -5
- package/dist/board/components/ProjectsPage.js +9 -1
- package/dist/board/components/TaskForm.js +15 -0
- package/dist/board/hooks/useBoardKeybindings.js +25 -13
- package/dist/board/hooks/useTaskKeybindings.js +24 -10
- package/dist/daemon/index.js +3 -1
- package/dist/daemon/manager.js +1 -4
- package/package.json +1 -1
|
@@ -92,6 +92,31 @@ export function CreateView(props) {
|
|
|
92
92
|
return 0;
|
|
93
93
|
return next;
|
|
94
94
|
});
|
|
95
|
+
key.preventDefault();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (key.name === "up" || key.name === "down") {
|
|
99
|
+
const field = filteredFields[focusIndex];
|
|
100
|
+
if (field === "project" && projectOptions.length > 1) {
|
|
101
|
+
const currentIdx = projectOptions.findIndex((p) => p.value === valuesRef.current.project);
|
|
102
|
+
const nextIdx = key.name === "down"
|
|
103
|
+
? (currentIdx + 1) % projectOptions.length
|
|
104
|
+
: (currentIdx - 1 + projectOptions.length) % projectOptions.length;
|
|
105
|
+
const next = projectOptions[nextIdx];
|
|
106
|
+
if (next)
|
|
107
|
+
updateValues({ ...valuesRef.current, project: next.value });
|
|
108
|
+
key.preventDefault();
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
setFocusIndex((i) => {
|
|
112
|
+
const next = key.name === "up" ? i - 1 : i + 1;
|
|
113
|
+
if (next < 0)
|
|
114
|
+
return cancelIndex;
|
|
115
|
+
if (next > cancelIndex)
|
|
116
|
+
return 0;
|
|
117
|
+
return next;
|
|
118
|
+
});
|
|
119
|
+
key.preventDefault();
|
|
95
120
|
return;
|
|
96
121
|
}
|
|
97
122
|
if (key.name === "return" || key.name === "enter" || key.name === " ") {
|
|
@@ -99,35 +124,27 @@ export function CreateView(props) {
|
|
|
99
124
|
if (field === "taskMode") {
|
|
100
125
|
const next = valuesRef.current.taskMode === TASK_MODE_INLINE ? TASK_MODE_EXISTING : TASK_MODE_INLINE;
|
|
101
126
|
updateValues({ ...valuesRef.current, taskMode: next });
|
|
127
|
+
key.preventDefault();
|
|
102
128
|
return;
|
|
103
129
|
}
|
|
104
130
|
if (field === "runNow") {
|
|
105
131
|
const next = valuesRef.current.runNow === "y" ? "n" : "y";
|
|
106
132
|
updateValues({ ...valuesRef.current, runNow: next });
|
|
133
|
+
key.preventDefault();
|
|
107
134
|
return;
|
|
108
135
|
}
|
|
109
136
|
if (focusIndex === chooseTaskIdx && !isInline) {
|
|
110
137
|
props.onChooseTask();
|
|
138
|
+
key.preventDefault();
|
|
111
139
|
return;
|
|
112
140
|
}
|
|
113
141
|
if (focusIndex === saveIndex) {
|
|
114
142
|
void submit(valuesRef.current);
|
|
143
|
+
key.preventDefault();
|
|
115
144
|
}
|
|
116
145
|
else if (focusIndex === cancelIndex) {
|
|
117
146
|
props.onCancel();
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
if (key.name === "up" || key.name === "down") {
|
|
121
|
-
const field = filteredFields[focusIndex];
|
|
122
|
-
if (field === "project" && projectOptions.length > 1) {
|
|
123
|
-
const currentIdx = projectOptions.findIndex((p) => p.value === valuesRef.current.project);
|
|
124
|
-
const nextIdx = key.name === "down"
|
|
125
|
-
? (currentIdx + 1) % projectOptions.length
|
|
126
|
-
: (currentIdx - 1 + projectOptions.length) % projectOptions.length;
|
|
127
|
-
const next = projectOptions[nextIdx];
|
|
128
|
-
if (next)
|
|
129
|
-
updateValues({ ...valuesRef.current, project: next.value });
|
|
130
|
-
return;
|
|
147
|
+
key.preventDefault();
|
|
131
148
|
}
|
|
132
149
|
}
|
|
133
150
|
});
|
|
@@ -5,40 +5,43 @@ export function HelpModal(props) {
|
|
|
5
5
|
const { view } = props;
|
|
6
6
|
const { width } = useTerminalDimensions();
|
|
7
7
|
const loopRows = [
|
|
8
|
+
["tab/←→", "switch panels"],
|
|
9
|
+
["↑/↓", "navigate list items"],
|
|
10
|
+
["enter", t("board.helpEdit")],
|
|
8
11
|
["e", "edit loop"],
|
|
9
12
|
["d/del", "delete loop"],
|
|
10
13
|
["c", "clone loop"],
|
|
11
14
|
["f", "force run"],
|
|
12
15
|
["p", "pause/play (contextual)"],
|
|
13
16
|
["s", "stop loop (resets schedule)"],
|
|
14
|
-
[t("board.helpKeyEnter"), t("board.helpEdit")],
|
|
15
17
|
["n", t("board.helpCreate")],
|
|
16
18
|
["t", t("board.helpCreateTask")],
|
|
17
19
|
["o", t("board.helpCycleSort")],
|
|
18
20
|
["x", "cycle status filter"],
|
|
19
21
|
["r", "project filter"],
|
|
20
|
-
["←/→", t("board.helpSwitchPanel")],
|
|
21
22
|
["/", t("board.helpSearch")],
|
|
22
23
|
["h", t("board.helpToggleHelp")],
|
|
23
24
|
["esc", t("board.helpQuit")],
|
|
24
25
|
];
|
|
25
26
|
const taskRows = [
|
|
27
|
+
["tab/←→", "switch panels"],
|
|
28
|
+
["↑/↓", "navigate tasks"],
|
|
29
|
+
["enter", "focus actions panel"],
|
|
26
30
|
["e", "edit task"],
|
|
27
31
|
["d/del", "delete task"],
|
|
28
32
|
["s", "select task (when creating/editing a loop)"],
|
|
29
|
-
["enter", "focus actions panel"],
|
|
30
33
|
["n", t("board.helpCreateTask")],
|
|
31
|
-
["←/→", t("board.helpSwitchPanel")],
|
|
32
34
|
["/", t("board.helpSearch")],
|
|
33
35
|
["h", t("board.helpToggleHelp")],
|
|
34
36
|
["esc", t("board.helpQuit")],
|
|
35
37
|
];
|
|
36
38
|
const projectRows = [
|
|
39
|
+
["tab/←→", "switch panel (list/actions)"],
|
|
40
|
+
["↑/↓", "navigate projects"],
|
|
37
41
|
["enter", "focus actions"],
|
|
38
42
|
["n", "new project"],
|
|
39
43
|
["e", "edit project"],
|
|
40
44
|
["d", "delete project"],
|
|
41
|
-
["←/→", "switch panel (list/actions)"],
|
|
42
45
|
["h", t("board.helpToggleHelp")],
|
|
43
46
|
["esc", t("board.helpQuit")],
|
|
44
47
|
];
|
|
@@ -41,6 +41,7 @@ export function ProjectsPage(props) {
|
|
|
41
41
|
setSelectedIndex((i) => Math.max(0, i - 1));
|
|
42
42
|
else
|
|
43
43
|
setSelectedAction((a) => Math.max(0, a - 1));
|
|
44
|
+
key.preventDefault();
|
|
44
45
|
return;
|
|
45
46
|
}
|
|
46
47
|
if (key.name === "down") {
|
|
@@ -48,10 +49,12 @@ export function ProjectsPage(props) {
|
|
|
48
49
|
setSelectedIndex((i) => Math.min(projects.length - 1, i + 1));
|
|
49
50
|
else
|
|
50
51
|
setSelectedAction((a) => Math.min(PROJECT_ACTION_COUNT - 1, a + 1));
|
|
52
|
+
key.preventDefault();
|
|
51
53
|
return;
|
|
52
54
|
}
|
|
53
|
-
if (key.name === "left" || key.name === "right") {
|
|
55
|
+
if (key.name === "left" || key.name === "right" || key.name === "tab") {
|
|
54
56
|
setFocusedPanel((p) => (p === "list" ? "actions" : "list"));
|
|
57
|
+
key.preventDefault();
|
|
55
58
|
return;
|
|
56
59
|
}
|
|
57
60
|
if (key.name === "return" || key.name === "enter") {
|
|
@@ -61,22 +64,27 @@ export function ProjectsPage(props) {
|
|
|
61
64
|
else {
|
|
62
65
|
runAction(selectedAction);
|
|
63
66
|
}
|
|
67
|
+
key.preventDefault();
|
|
64
68
|
return;
|
|
65
69
|
}
|
|
66
70
|
if (key.name === "n") {
|
|
67
71
|
setSubModal("create");
|
|
72
|
+
key.preventDefault();
|
|
68
73
|
return;
|
|
69
74
|
}
|
|
70
75
|
if (key.name === "e" && selectedProject && !selectedProject.isSystem) {
|
|
71
76
|
setSubModal("edit");
|
|
77
|
+
key.preventDefault();
|
|
72
78
|
return;
|
|
73
79
|
}
|
|
74
80
|
if (key.name === "d" && selectedProject && !selectedProject.isSystem) {
|
|
75
81
|
setSubModal("delete");
|
|
82
|
+
key.preventDefault();
|
|
76
83
|
return;
|
|
77
84
|
}
|
|
78
85
|
if (key.name === "escape") {
|
|
79
86
|
onClose();
|
|
87
|
+
key.preventDefault();
|
|
80
88
|
}
|
|
81
89
|
});
|
|
82
90
|
const actions = [
|
|
@@ -46,14 +46,29 @@ export function TaskForm(props) {
|
|
|
46
46
|
return 0;
|
|
47
47
|
return next;
|
|
48
48
|
});
|
|
49
|
+
key.preventDefault();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (key.name === "up" || key.name === "down") {
|
|
53
|
+
setFocusIndex((i) => {
|
|
54
|
+
const next = key.name === "up" ? i - 1 : i + 1;
|
|
55
|
+
if (next < 0)
|
|
56
|
+
return cancelIndex;
|
|
57
|
+
if (next > cancelIndex)
|
|
58
|
+
return 0;
|
|
59
|
+
return next;
|
|
60
|
+
});
|
|
61
|
+
key.preventDefault();
|
|
49
62
|
return;
|
|
50
63
|
}
|
|
51
64
|
if (key.name === "return" || key.name === "enter") {
|
|
52
65
|
if (focusIndex === saveIndex) {
|
|
53
66
|
void submit(valuesRef.current);
|
|
67
|
+
key.preventDefault();
|
|
54
68
|
}
|
|
55
69
|
else if (focusIndex === cancelIndex) {
|
|
56
70
|
props.onCancel();
|
|
71
|
+
key.preventDefault();
|
|
57
72
|
}
|
|
58
73
|
}
|
|
59
74
|
});
|
|
@@ -200,21 +200,25 @@ export function useBoardKeybindings(params) {
|
|
|
200
200
|
const name = key.name;
|
|
201
201
|
if (confirm) {
|
|
202
202
|
CONFIRM_KEYS[name]?.({ confirm, confirmChoice, setConfirm, setConfirmChoice });
|
|
203
|
+
key.preventDefault();
|
|
203
204
|
return;
|
|
204
205
|
}
|
|
205
206
|
if (logModalRun) {
|
|
206
207
|
if (name === "escape" || name === "q") {
|
|
207
208
|
OVERLAY_DISMISS.log({ setLogModalRun, setHelpOpen, setSearchActive, setFocusedPanel }, name);
|
|
209
|
+
key.preventDefault();
|
|
208
210
|
return;
|
|
209
211
|
}
|
|
210
212
|
if (key.ctrl && name === "c") {
|
|
211
213
|
copyToClipboard(logModalLines.join("\n"));
|
|
214
|
+
key.preventDefault();
|
|
212
215
|
return;
|
|
213
216
|
}
|
|
214
217
|
return;
|
|
215
218
|
}
|
|
216
219
|
if (helpOpen && (name === "h" || name === "escape")) {
|
|
217
220
|
OVERLAY_DISMISS.help({ setLogModalRun, setHelpOpen, setSearchActive, setFocusedPanel }, name);
|
|
221
|
+
key.preventDefault();
|
|
218
222
|
return;
|
|
219
223
|
}
|
|
220
224
|
if (helpOpen)
|
|
@@ -223,27 +227,36 @@ export function useBoardKeybindings(params) {
|
|
|
223
227
|
if (name === "escape") {
|
|
224
228
|
setSearchActive(false);
|
|
225
229
|
setFocusedPanel("loops");
|
|
230
|
+
key.preventDefault();
|
|
226
231
|
return;
|
|
227
232
|
}
|
|
228
233
|
return;
|
|
229
234
|
}
|
|
230
|
-
if (
|
|
231
|
-
|
|
235
|
+
if (view !== "board" && name === "escape") {
|
|
236
|
+
VIEW_ESCAPE[view]?.({ setEditTarget, setEditTask, onBack: pop });
|
|
237
|
+
key.preventDefault();
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (view !== "board")
|
|
241
|
+
return;
|
|
242
|
+
if (name === "left" || name === "right" || name === "tab") {
|
|
243
|
+
const direction = name === "left" || (name === "tab" && key.shift) ? "left" : "right";
|
|
244
|
+
if (focusedPanel === "actions" && name !== "tab") {
|
|
232
245
|
const actionCount = selected ? getActionCount(selected.status) : 0;
|
|
233
|
-
if (
|
|
246
|
+
if (direction === "left" && selectedAction === 0) {
|
|
234
247
|
setFocusedPanel((p) => nextPanel(p, "left"));
|
|
235
248
|
}
|
|
236
|
-
else if (
|
|
249
|
+
else if (direction === "right" && selectedAction === actionCount - 1) {
|
|
237
250
|
setFocusedPanel((p) => nextPanel(p, "right"));
|
|
238
251
|
}
|
|
239
252
|
else {
|
|
240
|
-
setSelectedAction((i) =>
|
|
253
|
+
setSelectedAction((i) => direction === "right"
|
|
241
254
|
? Math.min(actionCount - 1, i + 1)
|
|
242
255
|
: Math.max(0, i - 1));
|
|
243
256
|
}
|
|
244
257
|
}
|
|
245
258
|
else {
|
|
246
|
-
const next = nextPanel(focusedPanel,
|
|
259
|
+
const next = nextPanel(focusedPanel, direction);
|
|
247
260
|
if (next === "actions") {
|
|
248
261
|
setFocusedPanel("actions");
|
|
249
262
|
setSelectedAction(0);
|
|
@@ -252,17 +265,13 @@ export function useBoardKeybindings(params) {
|
|
|
252
265
|
setFocusedPanel(next);
|
|
253
266
|
}
|
|
254
267
|
}
|
|
268
|
+
key.preventDefault();
|
|
255
269
|
return;
|
|
256
270
|
}
|
|
257
|
-
if (view !== "board" && name === "escape") {
|
|
258
|
-
VIEW_ESCAPE[view]?.({ setEditTarget, setEditTask, onBack: pop });
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
if (view !== "board")
|
|
262
|
-
return;
|
|
263
271
|
const globalHandler = GLOBAL_KEYS[name];
|
|
264
272
|
if (globalHandler) {
|
|
265
273
|
globalHandler({ destroyLogSocket, onQuit, setHelpOpen, setEditTarget, setEditTask, push, onAction });
|
|
274
|
+
key.preventDefault();
|
|
266
275
|
return;
|
|
267
276
|
}
|
|
268
277
|
const panelHandler = panelHandlers[focusedPanel];
|
|
@@ -271,8 +280,10 @@ export function useBoardKeybindings(params) {
|
|
|
271
280
|
setSelectedIndex, setSelectedRunIndex, setFocusedPanel, selectedRunCount, selected,
|
|
272
281
|
selectedRunIndex, setSelectedAction, selectedAction, onAction, onOpenRunLog,
|
|
273
282
|
refreshTasks, onViewTasks, onViewProjects, onAddLoop,
|
|
274
|
-
}))
|
|
283
|
+
})) {
|
|
284
|
+
key.preventDefault();
|
|
275
285
|
return;
|
|
286
|
+
}
|
|
276
287
|
const shortcut = BOARD_SHORTCUTS[name];
|
|
277
288
|
if (shortcut) {
|
|
278
289
|
shortcut({
|
|
@@ -281,6 +292,7 @@ export function useBoardKeybindings(params) {
|
|
|
281
292
|
selectedRunIndex, setSelectedAction, selectedAction, onAction, onOpenRunLog,
|
|
282
293
|
onSelectProject,
|
|
283
294
|
});
|
|
295
|
+
key.preventDefault();
|
|
284
296
|
}
|
|
285
297
|
});
|
|
286
298
|
}
|
|
@@ -16,94 +16,108 @@ export function useTaskKeybindings(params) {
|
|
|
16
16
|
if (name === "escape") {
|
|
17
17
|
setTaskSearchActive(false);
|
|
18
18
|
setTaskFocusedPanel("tasks");
|
|
19
|
+
key.preventDefault();
|
|
19
20
|
return;
|
|
20
21
|
}
|
|
21
22
|
return;
|
|
22
23
|
}
|
|
23
24
|
if (name === "escape") {
|
|
24
25
|
onCancel();
|
|
26
|
+
key.preventDefault();
|
|
25
27
|
return;
|
|
26
28
|
}
|
|
27
29
|
if (name === "n") {
|
|
28
30
|
onCreateTask();
|
|
31
|
+
key.preventDefault();
|
|
29
32
|
return;
|
|
30
33
|
}
|
|
31
34
|
if (name === "/" && taskFocusedPanel === "tasks") {
|
|
32
35
|
setTaskSearchActive(true);
|
|
36
|
+
key.preventDefault();
|
|
33
37
|
return;
|
|
34
38
|
}
|
|
35
|
-
if (name === "tab") {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (name === "left" || name === "right") {
|
|
40
|
-
if (taskFocusedPanel === "actions") {
|
|
41
|
-
if (name === "left" && taskSelectedAction === 0) {
|
|
39
|
+
if (name === "tab" || name === "left" || name === "right") {
|
|
40
|
+
const direction = name === "left" || (name === "tab" && key.shift) ? "left" : "right";
|
|
41
|
+
if (taskFocusedPanel === "actions" && name !== "tab") {
|
|
42
|
+
if (direction === "left" && taskSelectedAction === 0) {
|
|
42
43
|
setTaskFocusedPanel((p) => nextTaskPanel(p, "left"));
|
|
43
44
|
}
|
|
44
|
-
else if (
|
|
45
|
+
else if (direction === "right" && taskSelectedAction === taskActionCount - 1) {
|
|
45
46
|
setTaskFocusedPanel((p) => nextTaskPanel(p, "right"));
|
|
46
47
|
}
|
|
47
48
|
else {
|
|
48
|
-
setTaskSelectedAction((i) =>
|
|
49
|
+
setTaskSelectedAction((i) => direction === "right"
|
|
49
50
|
? Math.min(taskActionCount - 1, i + 1)
|
|
50
51
|
: Math.max(0, i - 1));
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
else {
|
|
54
|
-
setTaskFocusedPanel((p) => nextTaskPanel(p,
|
|
55
|
+
setTaskFocusedPanel((p) => nextTaskPanel(p, direction));
|
|
55
56
|
}
|
|
57
|
+
key.preventDefault();
|
|
56
58
|
return;
|
|
57
59
|
}
|
|
58
60
|
if (taskFocusedPanel === "tasks") {
|
|
59
61
|
if (name === "up" || name === "k") {
|
|
60
62
|
setTaskSelectedIndex((i) => Math.max(0, i - 1));
|
|
63
|
+
key.preventDefault();
|
|
61
64
|
return;
|
|
62
65
|
}
|
|
63
66
|
if (name === "down" || name === "j") {
|
|
64
67
|
setTaskSelectedIndex((i) => Math.min(tasks.length - 1, i + 1));
|
|
68
|
+
key.preventDefault();
|
|
65
69
|
return;
|
|
66
70
|
}
|
|
67
71
|
if (name === "return" || name === "enter") {
|
|
68
72
|
setTaskFocusedPanel("actions");
|
|
73
|
+
key.preventDefault();
|
|
69
74
|
return;
|
|
70
75
|
}
|
|
71
76
|
if (name === "e" && tasks[taskSelectedIndex]) {
|
|
72
77
|
onTaskAction("edit");
|
|
78
|
+
key.preventDefault();
|
|
73
79
|
return;
|
|
74
80
|
}
|
|
75
81
|
if (name === "d" && tasks[taskSelectedIndex]) {
|
|
76
82
|
onTaskAction("delete");
|
|
83
|
+
key.preventDefault();
|
|
77
84
|
return;
|
|
78
85
|
}
|
|
79
86
|
if (name === "delete" && tasks[taskSelectedIndex]) {
|
|
80
87
|
onTaskAction("delete");
|
|
88
|
+
key.preventDefault();
|
|
81
89
|
return;
|
|
82
90
|
}
|
|
83
91
|
if (selectable && name === "s" && tasks[taskSelectedIndex]) {
|
|
84
92
|
onTaskAction("select");
|
|
93
|
+
key.preventDefault();
|
|
85
94
|
return;
|
|
86
95
|
}
|
|
87
96
|
}
|
|
88
97
|
if (taskFocusedPanel === "actions") {
|
|
89
98
|
if (name === "up" || name === "k") {
|
|
90
99
|
setTaskSelectedAction((i) => Math.max(0, i - 1));
|
|
100
|
+
key.preventDefault();
|
|
91
101
|
return;
|
|
92
102
|
}
|
|
93
103
|
if (name === "down" || name === "j") {
|
|
94
104
|
setTaskSelectedAction((i) => Math.min(taskActionCount - 1, i + 1));
|
|
105
|
+
key.preventDefault();
|
|
95
106
|
return;
|
|
96
107
|
}
|
|
97
108
|
if (name === "return" || name === "enter") {
|
|
98
109
|
onTaskAction(taskActions[taskSelectedAction] ?? "select");
|
|
110
|
+
key.preventDefault();
|
|
99
111
|
return;
|
|
100
112
|
}
|
|
101
113
|
if (name === "d") {
|
|
102
114
|
onTaskAction("delete");
|
|
115
|
+
key.preventDefault();
|
|
103
116
|
return;
|
|
104
117
|
}
|
|
105
118
|
if (selectable && name === "s") {
|
|
106
119
|
onTaskAction("select");
|
|
120
|
+
key.preventDefault();
|
|
107
121
|
return;
|
|
108
122
|
}
|
|
109
123
|
}
|
package/dist/daemon/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { LoopManager } from "./manager.js";
|
|
2
2
|
import { TaskManager } from "./task-manager.js";
|
|
3
3
|
import { IpcServer } from "./server.js";
|
|
4
|
-
import { writeDaemonPid, removeDaemonPid, writeDaemonSignature, removeDaemonSignature, computeCodeSignature, } from "./state.js";
|
|
4
|
+
import { writeDaemonPid, removeDaemonPid, writeDaemonSignature, removeDaemonSignature, computeCodeSignature, migrateTasksToJson, migrateLoopsToJson, } from "./state.js";
|
|
5
5
|
import { t } from "../i18n/index.js";
|
|
6
6
|
import { daemonLog } from "./daemon-log.js";
|
|
7
7
|
async function main() {
|
|
8
8
|
const taskManager = new TaskManager();
|
|
9
|
+
migrateLoopsToJson();
|
|
10
|
+
migrateTasksToJson();
|
|
9
11
|
taskManager.init();
|
|
10
12
|
const manager = new LoopManager(taskManager);
|
|
11
13
|
const server = new IpcServer(manager, taskManager);
|
package/dist/daemon/manager.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import { LoopController } from "../core/loop-controller.js";
|
|
3
3
|
import { ProjectManager } from "./projects.js";
|
|
4
|
-
import { saveLoop, loadAllLoops, deleteLoop as deleteLoopState, getLogPath,
|
|
4
|
+
import { saveLoop, loadAllLoops, deleteLoop as deleteLoopState, getLogPath, } from "./state.js";
|
|
5
5
|
import { daemonLog } from "./daemon-log.js";
|
|
6
6
|
export class LoopManager {
|
|
7
7
|
loops = new Map();
|
|
@@ -16,9 +16,6 @@ export class LoopManager {
|
|
|
16
16
|
init() {
|
|
17
17
|
// Initialize projects first
|
|
18
18
|
this.projectManager.init();
|
|
19
|
-
// Migrate from individual files to consolidated JSON
|
|
20
|
-
migrateLoopsToJson();
|
|
21
|
-
migrateTasksToJson();
|
|
22
19
|
const saved = loadAllLoops();
|
|
23
20
|
let restarted = 0;
|
|
24
21
|
let migrated = 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "loop-task",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.4",
|
|
4
4
|
"description": "Loop engineering toolkit. Run any command on a cadence, in the background, managed from a terminal board. Schedule tests, builds, syncs, or agent prompts.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|