@hacky.software/opencode-todo-supervisor 0.3.8 → 0.3.9
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/README.md +6 -5
- package/package.json +1 -1
- package/src/panel.test.ts +7 -7
- package/src/panel.ts +10 -10
- package/src/tui.tsx +8 -2
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ Tested against OpenCode `2.0.24`.
|
|
|
23
23
|
## Install
|
|
24
24
|
|
|
25
25
|
```sh
|
|
26
|
-
opencode plugin add @hacky.software/opencode-todo-supervisor@0.3.
|
|
26
|
+
opencode plugin add @hacky.software/opencode-todo-supervisor@0.3.9
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
This also loads the bundled TUI entry. To pass options, use the object form:
|
|
@@ -198,9 +198,10 @@ effective set is `config.markdownFiles ∪ stored files − removed` per session
|
|
|
198
198
|
without waiting for an event.
|
|
199
199
|
- **Side panel** (palette "Todo: open side panel"): the same list docked to
|
|
200
200
|
`session.panel` (`todo.todos`), with `f` for fullscreen. Its keys are live only
|
|
201
|
-
while the panel is focused *and* no overlay is up (dialog, menu,
|
|
202
|
-
|
|
203
|
-
command palette or the prompt's completions.
|
|
201
|
+
while the panel is focused *and* no overlay is up (dialog, menu, completions,
|
|
202
|
+
composer), so a docked panel never steals the arrow keys from the model picker,
|
|
203
|
+
command palette or the prompt's completions. The gate is applied per key at
|
|
204
|
+
dispatch, not on the layer: the host ignores a layer-level `enabled`.
|
|
204
205
|
- `/todos add <path>` and `/todos remove <path>` manage subscriptions from the
|
|
205
206
|
prompt.
|
|
206
207
|
- **Toasts** on `nudged` (idle vs stalled wording) and on the all-done transition.
|
|
@@ -383,7 +384,7 @@ There is no filesystem watcher. Instead:
|
|
|
383
384
|
(source edits and config content changes; `touch` alone does not).
|
|
384
385
|
- `opencode2 reload` forces reconciliation; `opencode2 service restart` only as a
|
|
385
386
|
last resort (it interrupts sessions).
|
|
386
|
-
- Tests: `bun test` (
|
|
387
|
+
- Tests: `bun test` (123 tests across parser, storage, tools, RPC, state machine,
|
|
387
388
|
panel helpers).
|
|
388
389
|
- Watch logs: `tail -f ~/.local/share/opencode/log/todo-supervisor.log`.
|
|
389
390
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hacky.software/opencode-todo-supervisor",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
4
4
|
"description": "OpenCode V2 plugin that gives every session a todo list (todo_write/todo_read), supervises idle sessions until the list is done, and can drive checklists in markdown files from a TUI panel.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/panel.test.ts
CHANGED
|
@@ -206,20 +206,20 @@ describe("panel cursor", () => {
|
|
|
206
206
|
// Normal session view: live while focused.
|
|
207
207
|
expect(panelKeys(true, "base")).toBe(true)
|
|
208
208
|
expect(panelKeys(false, "base")).toBe(false)
|
|
209
|
-
// The model picker,
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
//
|
|
214
|
-
expect(panelKeys(true, "
|
|
209
|
+
// The model picker, dialogs, menus and completions all take the keyboard.
|
|
210
|
+
for (const mode of ["modal", "menu", "autocomplete", "composer"]) {
|
|
211
|
+
expect(panelKeys(true, mode)).toBe(false)
|
|
212
|
+
}
|
|
213
|
+
// Any other mode (including the plain session view) keeps the panel live.
|
|
214
|
+
expect(panelKeys(true, "base")).toBe(true)
|
|
215
215
|
})
|
|
216
216
|
|
|
217
217
|
test("the popover keeps the keyboard in its own dialog", () => {
|
|
218
218
|
expect(popoverKeys("modal")).toBe(true)
|
|
219
219
|
expect(popoverKeys("base")).toBe(true)
|
|
220
|
-
expect(popoverKeys("composer")).toBe(true)
|
|
221
220
|
expect(popoverKeys("menu")).toBe(false)
|
|
222
221
|
expect(popoverKeys("autocomplete")).toBe(false)
|
|
222
|
+
expect(popoverKeys("composer")).toBe(false)
|
|
223
223
|
})
|
|
224
224
|
|
|
225
225
|
test("id and priority tags and their column widths", () => {
|
package/src/panel.ts
CHANGED
|
@@ -325,16 +325,17 @@ export function dialogWidth(size: DialogSizeName, viewportWidth: number): number
|
|
|
325
325
|
|
|
326
326
|
/**
|
|
327
327
|
* Keymap modes that own the keyboard while they are up: `modal` (dialogs, the
|
|
328
|
-
* model picker, confirmations), `menu` (the command/palette menus)
|
|
329
|
-
* `autocomplete` (the prompt's completion list)
|
|
330
|
-
* the arrow keys.
|
|
328
|
+
* model picker, confirmations), `menu` (the command/palette menus),
|
|
329
|
+
* `autocomplete` (the prompt's completion list) and `composer` (composer
|
|
330
|
+
* overlays). They all drive themselves with the arrow keys.
|
|
331
331
|
*/
|
|
332
|
-
const OVERLAY_MODES: ReadonlySet<string> = new Set(["modal", "menu", "autocomplete"])
|
|
332
|
+
const OVERLAY_MODES: ReadonlySet<string> = new Set(["modal", "menu", "autocomplete", "composer"])
|
|
333
333
|
|
|
334
334
|
/**
|
|
335
|
-
* Whether the side panel's keys should be live.
|
|
336
|
-
*
|
|
337
|
-
*
|
|
335
|
+
* Whether the side panel's keys should be live. Only the overlay modes take the
|
|
336
|
+
* keyboard away; any other mode (the plain session view included) keeps the
|
|
337
|
+
* panel live while it is focused. Without this a focused docked panel swallows
|
|
338
|
+
* the model picker's up/down.
|
|
338
339
|
*/
|
|
339
340
|
export function panelKeys(focused: boolean, mode: string): boolean {
|
|
340
341
|
return focused && !OVERLAY_MODES.has(mode)
|
|
@@ -342,9 +343,8 @@ export function panelKeys(focused: boolean, mode: string): boolean {
|
|
|
342
343
|
|
|
343
344
|
/**
|
|
344
345
|
* Whether the popover's keys should be live. The popover *is* a dialog, so
|
|
345
|
-
* `modal` is ours;
|
|
346
|
-
* the keyboard away from it.
|
|
346
|
+
* `modal` is ours; any other overlay takes the keyboard away from it.
|
|
347
347
|
*/
|
|
348
348
|
export function popoverKeys(mode: string): boolean {
|
|
349
|
-
return mode
|
|
349
|
+
return mode === "modal" || !OVERLAY_MODES.has(mode)
|
|
350
350
|
}
|
package/src/tui.tsx
CHANGED
|
@@ -411,8 +411,9 @@ export default Plugin.define({
|
|
|
411
411
|
})
|
|
412
412
|
|
|
413
413
|
context.keymap.layer(() => ({
|
|
414
|
+
// "global" keeps the layer mode-agnostic; the actual gating is done
|
|
415
|
+
// per command below.
|
|
414
416
|
mode: "global",
|
|
415
|
-
enabled: () => props.active(),
|
|
416
417
|
priority: 10,
|
|
417
418
|
commands: [
|
|
418
419
|
{ title: "Todo: select next", bind: "down", run: () => move(1) },
|
|
@@ -493,7 +494,12 @@ export default Plugin.define({
|
|
|
493
494
|
}),
|
|
494
495
|
},
|
|
495
496
|
{ title: "Todo: close", bind: "escape", run: () => props.close() },
|
|
496
|
-
|
|
497
|
+
// The host drops a *layer*-level `enabled`; the *command*-level one
|
|
498
|
+
// is consulted on every dispatch. Gate each key here so it yields —
|
|
499
|
+
// and falls through — the moment an overlay (model picker, palette,
|
|
500
|
+
// completion list, composer) owns the keyboard while a todo surface
|
|
501
|
+
// happens to still be focused.
|
|
502
|
+
].map((command) => ({ ...command, enabled: () => props.active() })),
|
|
497
503
|
}))
|
|
498
504
|
|
|
499
505
|
const totals = () => {
|