@gamflaz/opencode-todolist 0.0.0-stage → 1.0.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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +149 -2
  3. package/dist/icons/capabilities.d.ts +9 -0
  4. package/dist/icons/capabilities.js +16 -0
  5. package/dist/icons/capabilities.js.map +1 -0
  6. package/dist/icons/convert.d.ts +7 -0
  7. package/dist/icons/convert.js +75 -0
  8. package/dist/icons/convert.jsx +38 -0
  9. package/dist/icons/convert.jsx.map +1 -0
  10. package/dist/icons/icons.d.ts +4 -0
  11. package/dist/icons/icons.js +15 -0
  12. package/dist/icons/icons.js.map +1 -0
  13. package/dist/index.d.ts +12 -0
  14. package/dist/index.js +187 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/schema/status.schema.d.ts +16 -0
  17. package/dist/schema/status.schema.js +15 -0
  18. package/dist/schema/status.schema.js.map +1 -0
  19. package/dist/schema/store.schema.d.ts +19 -0
  20. package/dist/schema/store.schema.js +21 -0
  21. package/dist/schema/store.schema.js.map +1 -0
  22. package/dist/schema/todo.schema.d.ts +281 -0
  23. package/dist/schema/todo.schema.js +113 -0
  24. package/dist/schema/todo.schema.js.map +1 -0
  25. package/dist/skills/skill.d.ts +24 -0
  26. package/dist/skills/skill.js +154 -0
  27. package/dist/skills/skill.js.map +1 -0
  28. package/dist/store/errors.d.ts +3 -0
  29. package/dist/store/errors.js +7 -0
  30. package/dist/store/errors.js.map +1 -0
  31. package/dist/store/store.d.ts +145 -0
  32. package/dist/store/store.js +446 -0
  33. package/dist/store/store.js.map +1 -0
  34. package/dist/todo/display.d.ts +21 -0
  35. package/dist/todo/display.js +54 -0
  36. package/dist/todo/display.js.map +1 -0
  37. package/dist/todo/hint.d.ts +16 -0
  38. package/dist/todo/hint.js +188 -0
  39. package/dist/todo/hint.js.map +1 -0
  40. package/dist/todo/todo.d.ts +63 -0
  41. package/dist/todo/todo.js +189 -0
  42. package/dist/todo/todo.js.map +1 -0
  43. package/dist/todo/update.d.ts +35 -0
  44. package/dist/todo/update.js +141 -0
  45. package/dist/todo/update.js.map +1 -0
  46. package/dist/tui.d.ts +100 -0
  47. package/dist/tui.js +783 -0
  48. package/dist/tui.jsx +562 -0
  49. package/dist/tui.jsx.map +1 -0
  50. package/index.js +1 -0
  51. package/package.json +56 -4
  52. package/skills/continue-todolist/SKILL.md +94 -0
  53. package/skills/todolist/SKILL.md +220 -0
  54. package/tui.js +1 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gamflaz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,150 @@
1
- # Temporary Holding Version
1
+ # OpenCode Todo List Plugin
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A local OpenCode plugin for hierarchical todo tracking: a `manage_todo_list` tool
4
+ plus a TUI widget above the composer that shows progress in real time.
5
+
6
+ ## Features
7
+
8
+ - Hierarchical tasks: any number of root tasks, each with up to 9 subtasks.
9
+ - Numeric IDs only: root `1`, `2`, … and subtasks `1.1`, `1.2`, … (`1.9` max).
10
+ - Small partial updates: change one item without resending the whole list.
11
+ - Strict forward-only progress with enforced order between root tasks.
12
+ - Real-time TUI widget with collapse, scroll, `↻ Continue`, and clear controls.
13
+ - Bundled skills that teach the agent how to drive the tool.
14
+
15
+ ## Installation
16
+
17
+ Requires [Bun](https://bun.sh/) and OpenCode V2.
18
+
19
+ ```bash
20
+ git clone https://github.com/MomoPi-Dark/opencode-todolist.git \
21
+ ~/.config/opencode/plugins/todolist
22
+ cd ~/.config/opencode/plugins/todolist
23
+ bun install
24
+ bun run build
25
+ ```
26
+
27
+ OpenCode loads local plugins from the plugins directory, but it does not install
28
+ their dependencies, so `bun install` is required before use.
29
+
30
+ ## Tool: `manage_todo_list`
31
+
32
+ ### Read
33
+
34
+ ```json
35
+ { "operation": "read" }
36
+ ```
37
+
38
+ Returns the current list as a progress tree:
39
+
40
+ ```text
41
+ [~] 1. Design architecture (1/2)
42
+ ↳ note: Keep the hierarchy shallow
43
+ [x] 1.1 Database schema
44
+ [~] 1.2 API endpoints
45
+ [ ] 2. Write tests
46
+ ```
47
+
48
+ Markers: `[ ]` pending, `[~]` in progress, `[x]` completed, `[-]` cancelled,
49
+ `[!]` error. Notes render under their item as `↳ note: …`.
50
+
51
+ ### Write
52
+
53
+ `write` initializes a session or clears it. A non-empty list is only accepted
54
+ while the session has no todos yet.
55
+
56
+ ```json
57
+ {
58
+ "operation": "write",
59
+ "todos": [
60
+ {
61
+ "id": 1,
62
+ "content": "Add auth endpoint",
63
+ "status": "in_progress",
64
+ "note": "Return 401 on bad token",
65
+ "children": [
66
+ { "id": 1.1, "content": "Write handler", "status": "pending" }
67
+ ]
68
+ },
69
+ { "id": 2, "content": "Update docs", "status": "pending" }
70
+ ]
71
+ }
72
+ ```
73
+
74
+ Clear the current list:
75
+
76
+ ```json
77
+ { "operation": "write", "todos": [] }
78
+ ```
79
+
80
+ ### Update
81
+
82
+ `update` changes one existing root or subtask. Send only the fields that change;
83
+ `status` is required.
84
+
85
+ ```json
86
+ {
87
+ "operation": "update",
88
+ "id": 1.1,
89
+ "status": "completed",
90
+ "note": "Tests passing"
91
+ }
92
+ ```
93
+
94
+ Field values:
95
+
96
+ | Field | Required | Notes |
97
+ | ---------- | -------- | ------------------------------------------------------------ |
98
+ | `id` | Yes | Root number or subtask number (`1`, `1.1`). |
99
+ | `status` | Yes | `pending`, `in_progress`, `completed`, `cancelled`, `error`. |
100
+ | `content` | No | One-line summary shown in the widget. |
101
+ | `note` | No | Technical context or evidence. Pass `null` to remove. |
102
+ | `priority` | No | `high`, `medium`, or `low`. Pass `null` to remove. |
103
+
104
+ ## Rules
105
+
106
+ 1. **One root at a time, in order.** Root `2` cannot start while root `1` is
107
+ still open. Finish or cancel root `1` first.
108
+ 2. **One active subtask per root.** Starting a second `in_progress` subtask is
109
+ rejected until the first one finishes or is cancelled.
110
+ 3. **Forward-only progress.** `in_progress` never returns to `pending`, and
111
+ `completed` or `cancelled` items are locked.
112
+ 4. **Error exception.** A root that reports `error` may be fixed early, but only
113
+ that root and its own subtasks; every other root still waits its turn.
114
+ 5. **Evidence in `note`.** Record what was verified before marking an item
115
+ `completed`.
116
+
117
+ Every response reports progress, the next step, and any status transitions, for
118
+ example:
119
+
120
+ ```text
121
+ Todos (2/4) updated. Next: 2 "Write tests". Continue immediately.
122
+ ```
123
+
124
+ ## TUI widget
125
+
126
+ The widget sits above the session composer:
127
+
128
+ - Collapsed view shows the progress count and the active item.
129
+ - Expand it to see every task; long lists scroll.
130
+ - `↻ Continue` asks the session to resume the next open item with a short
131
+ summary of what remains.
132
+ - `✕` clears the list.
133
+
134
+ ## Skills
135
+
136
+ `skills/todolist` and `skills/continue-todolist` ship with the plugin and are
137
+ registered automatically. They explain how to use the tool and how to resume
138
+ tracked work.
139
+
140
+ ## Development
141
+
142
+ ```bash
143
+ bun install
144
+ bun run check # typecheck + tests
145
+ bun run build # compile the plugin entrypoints
146
+ ```
147
+
148
+ ## Publishing notes
149
+
150
+ Do not commit environment files, local dependencies, or generated build output.
@@ -0,0 +1,9 @@
1
+ import { type TerminalCapabilities } from "@opentui/core";
2
+ /** Minimal capability view needed to decide between image and text icons. */
3
+ export type ImageCapabilitySnapshot = Pick<TerminalCapabilities, "kitty_graphics" | "sixel"> & Partial<Pick<TerminalCapabilities, "image_protocol" | "multiplexer">>;
4
+ /**
5
+ * Whether the terminal can render raster icons. Terminals without Kitty or
6
+ * Sixel support (and any host that still reports unknown capabilities) must
7
+ * fall back to the direct text glyph.
8
+ */
9
+ export declare function supportsImageRendering(capabilities: ImageCapabilitySnapshot | null | undefined): boolean;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Whether the terminal can render raster icons. Terminals without Kitty or
3
+ * Sixel support (and any host that still reports unknown capabilities) must
4
+ * fall back to the direct text glyph.
5
+ */
6
+ export function supportsImageRendering(capabilities) {
7
+ if (!capabilities || capabilities.image_protocol === "blocks")
8
+ return false;
9
+ if (capabilities.multiplexer === "tmux" &&
10
+ capabilities.image_protocol !== "kitty" &&
11
+ capabilities.image_protocol !== "sixel") {
12
+ return false;
13
+ }
14
+ return capabilities.kitty_graphics || capabilities.sixel;
15
+ }
16
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/icons/capabilities.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,YAAwD;IAExD,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,cAAc,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5E,IACE,YAAY,CAAC,WAAW,KAAK,MAAM;QACnC,YAAY,CAAC,cAAc,KAAK,OAAO;QACvC,YAAY,CAAC,cAAc,KAAK,OAAO,EACvC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,YAAY,CAAC,cAAc,IAAI,YAAY,CAAC,KAAK,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { RGBA } from "@opentui/core";
2
+ import { type ImageProps } from "@opentui/solid";
3
+ export declare function SvgIcon(props: ImageProps & {
4
+ source: string;
5
+ color?: RGBA | string;
6
+ fallback: string;
7
+ }): import("solid-js").JSX.Element;
@@ -0,0 +1,75 @@
1
+ import { setProp as _$setProp } from "@opentui/solid";
2
+ import { effect as _$effect } from "@opentui/solid";
3
+ import { insertNode as _$insertNode } from "@opentui/solid";
4
+ import { insert as _$insert } from "@opentui/solid";
5
+ import { createComponent as _$createComponent } from "@opentui/solid";
6
+ import { spread as _$spread } from "@opentui/solid";
7
+ import { mergeProps as _$mergeProps } from "@opentui/solid";
8
+ import { memo as _$memo } from "@opentui/solid";
9
+ import { createElement as _$createElement } from "@opentui/solid";
10
+ import { usePlugin } from "@opencode/plugin/tui";
11
+ import { rgbToHex } from "@opentui/core";
12
+ import { Resvg } from "@resvg/resvg-js";
13
+ import { createMemo, createSignal, onCleanup, Show } from "solid-js";
14
+ import { supportsImageRendering } from "./capabilities";
15
+ export function SvgIcon(props) {
16
+ const {
17
+ source: _,
18
+ color: __,
19
+ fallback,
20
+ ...prop
21
+ } = props;
22
+ const context = usePlugin();
23
+ const [imageSupported, setImageSupported] = createSignal(supportsImageRendering(context.renderer.capabilities));
24
+ const updateImageSupport = capabilities => {
25
+ setImageSupported(supportsImageRendering(capabilities));
26
+ };
27
+ context.renderer.on("capabilities", updateImageSupport);
28
+ onCleanup(() => context.renderer.off("capabilities", updateImageSupport));
29
+ const iconColor = () => props.color ? typeof props.color === "string" ? props.color : rgbToHex(props.color) : "currentColor";
30
+ const pngBuffer = createMemo(() => {
31
+ const bgToken = context.theme.background.base;
32
+ const bg = rgbToHex(bgToken);
33
+ let svg = props.source.replace(/stroke="[^"]*"/g, `stroke="${iconColor()}"`).replace(/color="[^"]*"/g, `color="${iconColor()}"`);
34
+ const resvg = new Resvg(svg, {
35
+ fitTo: {
36
+ mode: "width",
37
+ value: 64
38
+ },
39
+ background: bg
40
+ });
41
+ return resvg.render().asPng();
42
+ });
43
+ return _$createComponent(Show, {
44
+ get when() {
45
+ return imageSupported();
46
+ },
47
+ get fallback() {
48
+ return (() => {
49
+ var _el$2 = _$createElement("text"),
50
+ _el$3 = _$createElement("span");
51
+ _$insertNode(_el$2, _el$3);
52
+ _$insert(_el$3, fallback);
53
+ _$effect(_$p => _$setProp(_el$3, "style", {
54
+ fg: iconColor()
55
+ }, _$p));
56
+ return _el$2;
57
+ })();
58
+ },
59
+ get children() {
60
+ var _el$ = _$createElement("image");
61
+ _$spread(_el$, _$mergeProps({
62
+ get source() {
63
+ return pngBuffer();
64
+ },
65
+ get width() {
66
+ return props.width ?? 2;
67
+ },
68
+ get height() {
69
+ return props.height ?? 1;
70
+ }
71
+ }, prop), false);
72
+ return _el$;
73
+ }
74
+ });
75
+ }
@@ -0,0 +1,38 @@
1
+ import { usePlugin } from "@opencode/plugin/tui";
2
+ import { rgbToHex } from "@opentui/core";
3
+ import { Resvg } from "@resvg/resvg-js";
4
+ import { createMemo, createSignal, onCleanup, Show } from "solid-js";
5
+ import { supportsImageRendering } from "./capabilities";
6
+ export function SvgIcon(props) {
7
+ const { source: _, color: __, fallback, ...prop } = props;
8
+ const context = usePlugin();
9
+ const [imageSupported, setImageSupported] = createSignal(supportsImageRendering(context.renderer.capabilities));
10
+ const updateImageSupport = (capabilities) => {
11
+ setImageSupported(supportsImageRendering(capabilities));
12
+ };
13
+ context.renderer.on("capabilities", updateImageSupport);
14
+ onCleanup(() => context.renderer.off("capabilities", updateImageSupport));
15
+ const iconColor = () => props.color
16
+ ? typeof props.color === "string"
17
+ ? props.color
18
+ : rgbToHex(props.color)
19
+ : "currentColor";
20
+ const pngBuffer = createMemo(() => {
21
+ const bgToken = context.theme.background.base;
22
+ const bg = rgbToHex(bgToken);
23
+ let svg = props.source
24
+ .replace(/stroke="[^"]*"/g, `stroke="${iconColor()}"`)
25
+ .replace(/color="[^"]*"/g, `color="${iconColor()}"`);
26
+ const resvg = new Resvg(svg, {
27
+ fitTo: { mode: "width", value: 64 },
28
+ background: bg,
29
+ });
30
+ return resvg.render().asPng();
31
+ });
32
+ return (<Show when={imageSupported()} fallback={<text>
33
+ <span style={{ fg: iconColor() }}>{fallback}</span>
34
+ </text>}>
35
+ <image source={pngBuffer()} width={props.width ?? 2} height={props.height ?? 1} {...prop}/>
36
+ </Show>);
37
+ }
38
+ //# sourceMappingURL=convert.jsx.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert.jsx","sourceRoot":"","sources":["../../src/icons/convert.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAQ,QAAQ,EAA6B,MAAM,eAAe,CAAC;AAE1E,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAExD,MAAM,UAAU,OAAO,CACrB,KAIC;IAED,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IAC1D,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAC5B,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,YAAY,CACtD,sBAAsB,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CACtD,CAAC;IACF,MAAM,kBAAkB,GAAG,CAAC,YAAkC,EAAE,EAAE;QAChE,iBAAiB,CAAC,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC;IAEF,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;IACxD,SAAS,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAE1E,MAAM,SAAS,GAAG,GAAG,EAAE,CACrB,KAAK,CAAC,KAAK;QACT,CAAC,CAAC,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;YAC/B,CAAC,CAAC,KAAK,CAAC,KAAK;YACb,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;QACzB,CAAC,CAAC,cAAc,CAAC;IAErB,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;QAChC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;QAC9C,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAE7B,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM;aACnB,OAAO,CAAC,iBAAiB,EAAE,WAAW,SAAS,EAAE,GAAG,CAAC;aACrD,OAAO,CAAC,gBAAgB,EAAE,UAAU,SAAS,EAAE,GAAG,CAAC,CAAC;QAEvD,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,EAAE;YAC3B,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;YACnC,UAAU,EAAE,EAAE;SACf,CAAC,CAAC;QACH,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,OAAO,CACL,CAAC,IAAI,CACH,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC,CACvB,QAAQ,CAAC,CACP,CAAC,IAAI,CACH;UAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAI,CACpD;QAAA,EAAE,IAAI,CACR,CAAC,CAED;MAAA,CAAC,KAAK,CACJ,MAAM,CAAC,CAAC,SAAS,EAAE,CAAC,CACpB,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CACxB,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,CAC1B,IAAI,IAAI,CAAC,EAEb;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const removeSvgIcon = "\n<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-mop-sparkles preview-icon\"><path d=\"M10 22a3 3 0 01-3-3\"/><path d=\"M10 22c2.761 0 5-1.79 5-4-4.42 0-4.08-5-8.5-5a4.501 4.501 0 000 9z\"/><path d=\"M10 3H8\"/><path d=\"M12.5 11.5 22 2\"/><path d=\"M20 13v4\"/><path d=\"M22 15h-4\"/><path d=\"M4 5v4\"/><path d=\"M6 7H2\"/><path d=\"m6.98 13.02 2.665-2.664a1.21 1.21 0 011.71 0l2.29 2.288a1.21 1.21 0 010 1.712l-2.088 2.087\"/><path d=\"M9 2v2\"/></svg>\n";
2
+ export declare const arrowDownSvgIcon = "\n<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"m6 9 6 6 6-6\"/>\n</svg>\n";
3
+ export declare const arrowRightSvgIcon = "\n<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"m9 18 6-6-6-6\"/>\n</svg>\n";
4
+ export declare const continuePromptSvgIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-rotate-cw preview-icon\"><path d=\"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\"/><path d=\"M21 3v5h-5\"/></svg>";
@@ -0,0 +1,15 @@
1
+ export const removeSvgIcon = `
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mop-sparkles preview-icon"><path d="M10 22a3 3 0 01-3-3"/><path d="M10 22c2.761 0 5-1.79 5-4-4.42 0-4.08-5-8.5-5a4.501 4.501 0 000 9z"/><path d="M10 3H8"/><path d="M12.5 11.5 22 2"/><path d="M20 13v4"/><path d="M22 15h-4"/><path d="M4 5v4"/><path d="M6 7H2"/><path d="m6.98 13.02 2.665-2.664a1.21 1.21 0 011.71 0l2.29 2.288a1.21 1.21 0 010 1.712l-2.088 2.087"/><path d="M9 2v2"/></svg>
3
+ `;
4
+ export const arrowDownSvgIcon = `
5
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
6
+ <path d="m6 9 6 6 6-6"/>
7
+ </svg>
8
+ `;
9
+ export const arrowRightSvgIcon = `
10
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
11
+ <path d="m9 18 6-6-6-6"/>
12
+ </svg>
13
+ `;
14
+ export const continuePromptSvgIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-rotate-cw preview-icon"><path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/></svg>`;
15
+ //# sourceMappingURL=icons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icons.js","sourceRoot":"","sources":["../../src/icons/icons.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,aAAa,GAAG;;CAE5B,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;CAI/B,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;CAIhC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,6TAA6T,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { Plugin } from "@opencode/plugin";
2
+ import { type TodoRootItem } from "./schema/todo.schema";
3
+ export declare function formatReadOutput(todos: readonly TodoRootItem[]): string;
4
+ export declare function formatTransitionLines(before: readonly TodoRootItem[], after: readonly TodoRootItem[]): string[];
5
+ export declare function formatWriteOutput(todos: readonly TodoRootItem[], before?: readonly TodoRootItem[]): string;
6
+ export declare function assertWriteIsInitialization(existing: readonly TodoRootItem[], incoming: readonly TodoRootItem[]): void;
7
+ /** Update response: progress, next step, and transition lines without resending the list. */
8
+ export declare function formatUpdateOutput(todos: readonly TodoRootItem[], before?: readonly TodoRootItem[]): string;
9
+ export declare function registerTodoTools(ctx: Plugin.Context): Promise<void>;
10
+ export declare function registerTodoPromptHook(ctx: Plugin.Context): Promise<void>;
11
+ declare const _default: Plugin.Plugin;
12
+ export default _default;
package/dist/index.js ADDED
@@ -0,0 +1,187 @@
1
+ import { Plugin } from "@opencode/plugin";
2
+ import { TodoInputToolSchema, TodoOutputToolSchema, } from "./schema/todo.schema";
3
+ import { registerTodoSkills } from "./skills/skill";
4
+ import { readTodoData, readTodos, updateTodos } from "./store/store";
5
+ import { buildTodoHint, consumeTodoHint, findNextTodo, findStuckParent, flattenLeaves, isAnyTodoActive, } from "./todo/hint";
6
+ import { TodoTree } from "./todo/todo";
7
+ import { updateTodoById } from "./todo/update";
8
+ export function formatReadOutput(todos) {
9
+ if (todos.length === 0)
10
+ return "No todos recorded.";
11
+ const tree = new TodoTree(todos).render();
12
+ const check = new TodoTree(todos).validateAndNormalize();
13
+ if (check.valid)
14
+ return tree;
15
+ return `Warning: the stored list needs fixing — ${check.error}\n${tree}`;
16
+ }
17
+ export function formatTransitionLines(before, after) {
18
+ const previous = new Map(flattenLeaves(before).map((leaf) => [leaf.id, leaf.status]));
19
+ const leaves = flattenLeaves(after);
20
+ const total = leaves.length;
21
+ const completed = [];
22
+ const started = [];
23
+ const failed = [];
24
+ leaves.forEach((leaf, index) => {
25
+ const was = previous.get(leaf.id);
26
+ const label = `(${index + 1}/${total}): ${leaf.content}`;
27
+ if (leaf.status === "completed" &&
28
+ was !== undefined &&
29
+ was !== "completed") {
30
+ completed.push(`✓\uFE0E Completed ${label}`);
31
+ }
32
+ else if (leaf.status === "in_progress" && was !== "in_progress") {
33
+ started.push(`▶\uFE0E Starting ${label}`);
34
+ }
35
+ else if (leaf.status === "error" &&
36
+ was !== undefined &&
37
+ was !== "error") {
38
+ failed.push(`✗\uFE0E Error ${label}${leaf.note ? ` — ${leaf.note}` : ""}`);
39
+ }
40
+ });
41
+ return [...completed, ...started, ...failed];
42
+ }
43
+ export function formatWriteOutput(todos, before = []) {
44
+ const stats = new TodoTree(todos).calculateStats();
45
+ const base = `Todos (${stats.completedSubTasks}/${stats.totalSubTasks}) updated.`;
46
+ const next = findNextTodo(todos);
47
+ const stuck = findStuckParent(todos);
48
+ const head = next
49
+ ? `${base} Next: ${next.id} "${next.content}". Continue immediately.`
50
+ : stuck
51
+ ? `${base} All children of ${stuck.id} "${stuck.content}" are done. Set ${stuck.id} to completed (or cancelled) to finish it.`
52
+ : isAnyTodoActive(todos)
53
+ ? `${base} Open items remain. Call manage_todo_list [read] and resolve them.`
54
+ : `${base} All todos finished.`;
55
+ const lines = formatTransitionLines(before, todos);
56
+ if (lines.length === 0)
57
+ return head;
58
+ return `${head}\nPrint these lines to chat verbatim, then continue:\n${lines.join("\n")}`;
59
+ }
60
+ export function assertWriteIsInitialization(existing, incoming) {
61
+ if (existing.length > 0 && incoming.length > 0) {
62
+ const messages = [
63
+ '[manage_todo_list] Invalid operation: "write".',
64
+ "",
65
+ 'The "write" operation is only allowed during initialization.',
66
+ 'Use "update" to modify an existing todo list.',
67
+ 'To replace the entire list, use "write" with "todos:[]".',
68
+ ];
69
+ throw new Error(messages.join("\n"));
70
+ }
71
+ }
72
+ /** Update response: progress, next step, and transition lines without resending the list. */
73
+ export function formatUpdateOutput(todos, before = []) {
74
+ const stats = new TodoTree(todos).calculateStats();
75
+ const progress = `Todos (${stats.completedSubTasks}/${stats.totalSubTasks}).`;
76
+ return formatWriteOutput(todos, before).replace(/^Todos \(\d+\/\d+\) updated\./, progress.slice(0, -1));
77
+ }
78
+ export async function registerTodoTools(ctx) {
79
+ await ctx.tool.transform((tools) => {
80
+ tools.add({
81
+ name: "manage_todo_list",
82
+ description: "Manage the todo list for multi-step tasks. Use non-empty 'write' only to initialize; use 'write' with [] to clear; use 'update' for existing items. " +
83
+ "Rules enforced: one root at a time in order — root 2 cannot start while root 1 is still open; only a root in 'error' may be fixed early, and only inside that root. " +
84
+ "Only one task/subtask may be 'in_progress'; progress never moves backward and finished items are locked. " +
85
+ "Mark items completed right after they are verified. " +
86
+ "Keep working through open items without asking permission to continue. " +
87
+ "Call 'read' first if unsure of current state, as tasks can be cleared by user via UI.",
88
+ input: TodoInputToolSchema,
89
+ output: TodoOutputToolSchema,
90
+ options: { codemode: false },
91
+ execute: async (input, toolContext) => {
92
+ const parsed = TodoInputToolSchema.safeParse(input);
93
+ if (!parsed.success) {
94
+ throw new Error(`[manage_todo_list validation failed] ${parsed.error.issues
95
+ .map((i) => `${i.path.join(".") || "input"}: ${i.message}`)
96
+ .join(", ")}`);
97
+ }
98
+ if (parsed.data.operation === "read") {
99
+ const todos = await readTodos(toolContext.sessionID);
100
+ return { output: { todos }, content: formatReadOutput(todos) };
101
+ }
102
+ if (parsed.data.operation === "update") {
103
+ const updateInput = parsed.data;
104
+ let updated;
105
+ let before = [];
106
+ const todos = await updateTodos(toolContext.sessionID, (current) => {
107
+ before = current;
108
+ const result = updateTodoById(current, updateInput);
109
+ updated = result.updated;
110
+ return result.todos;
111
+ });
112
+ return {
113
+ output: { todos },
114
+ content: `Updated ${updated.scope} todo ${updated.id}. ${formatUpdateOutput(todos, before)}`,
115
+ };
116
+ }
117
+ const rawTodos = parsed.data.todos;
118
+ assertWriteIsInitialization(readTodoData(toolContext.sessionID)?.todos ?? [], rawTodos);
119
+ if (rawTodos.length === 0) {
120
+ await updateTodos(toolContext.sessionID, () => []);
121
+ return { output: { todos: [] }, content: "Cleared all todos." };
122
+ }
123
+ let before = [];
124
+ const todos = await updateTodos(toolContext.sessionID, (current) => {
125
+ before = current;
126
+ return rawTodos;
127
+ });
128
+ return { output: { todos }, content: formatWriteOutput(todos, before) };
129
+ },
130
+ });
131
+ });
132
+ await registerTodoSkills(ctx);
133
+ await registerTodoPromptHook(ctx);
134
+ }
135
+ export async function registerTodoPromptHook(ctx) {
136
+ if (typeof ctx.session?.hook !== "function")
137
+ return;
138
+ const debug = process.env.TODO_HINT_DEBUG === "1";
139
+ try {
140
+ await ctx.session.hook("context", async (sessionContext) => {
141
+ try {
142
+ const system = sessionContext.system;
143
+ if (!Array.isArray(system)) {
144
+ if (debug)
145
+ console.error("[todo] system is not an array");
146
+ return;
147
+ }
148
+ const hint = buildTodoHint(sessionContext.sessionID);
149
+ if (!hint)
150
+ return;
151
+ system.push({ type: "text", text: hint });
152
+ if (debug)
153
+ console.error("[todo] hint injected", sessionContext.sessionID);
154
+ }
155
+ catch {
156
+ // Fail-safe
157
+ }
158
+ });
159
+ return;
160
+ }
161
+ catch {
162
+ // Fallback
163
+ }
164
+ try {
165
+ await ctx.session.hook("prompt", async (sessionPrompt) => {
166
+ try {
167
+ if (!sessionPrompt.prompt?.text?.trim())
168
+ return;
169
+ const hint = consumeTodoHint(sessionPrompt.sessionID);
170
+ if (hint) {
171
+ sessionPrompt.prompt.text = `${sessionPrompt.prompt.text}\n\n${hint}`;
172
+ }
173
+ }
174
+ catch {
175
+ // Fail-safe
176
+ }
177
+ });
178
+ }
179
+ catch {
180
+ // Graceful degradation
181
+ }
182
+ }
183
+ export default Plugin.define({
184
+ id: "opencode.todolist.tool",
185
+ setup: registerTodoTools,
186
+ });
187
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { z } from "zod";
2
+ export declare const TodoStatusSchema: z.ZodEnum<{
3
+ cancelled: "cancelled";
4
+ completed: "completed";
5
+ error: "error";
6
+ in_progress: "in_progress";
7
+ pending: "pending";
8
+ }>;
9
+ export type TodoStatus = z.infer<typeof TodoStatusSchema>;
10
+ export declare const PrioritySchema: z.ZodEnum<{
11
+ high: "high";
12
+ low: "low";
13
+ medium: "medium";
14
+ }>;
15
+ export type Priority = z.infer<typeof PrioritySchema>;
16
+ export declare const OPEN_STATUSES: readonly TodoStatus[];
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ export const TodoStatusSchema = z.enum([
3
+ "pending",
4
+ "in_progress",
5
+ "completed",
6
+ "cancelled",
7
+ "error",
8
+ ]);
9
+ export const PrioritySchema = z.enum(["high", "medium", "low"]);
10
+ export const OPEN_STATUSES = [
11
+ "pending",
12
+ "in_progress",
13
+ "error",
14
+ ];
15
+ //# sourceMappingURL=status.schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.schema.js","sourceRoot":"","sources":["../../src/schema/status.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC;IACrC,SAAS;IACT,aAAa;IACb,WAAW;IACX,WAAW;IACX,OAAO;CACR,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;AAGhE,MAAM,CAAC,MAAM,aAAa,GAA0B;IAClD,SAAS;IACT,aAAa;IACb,OAAO;CACR,CAAC"}
@@ -0,0 +1,19 @@
1
+ import z from "zod";
2
+ export declare const PlatformContextSchema: z.ZodObject<{
3
+ platform: z.ZodOptional<z.ZodEnum<{
4
+ aix: "aix";
5
+ android: "android";
6
+ cygwin: "cygwin";
7
+ darwin: "darwin";
8
+ freebsd: "freebsd";
9
+ haiku: "haiku";
10
+ linux: "linux";
11
+ netbsd: "netbsd";
12
+ openbsd: "openbsd";
13
+ sunos: "sunos";
14
+ win32: "win32";
15
+ }>>;
16
+ env: z.ZodOptional<z.ZodDefault<z.ZodObject<{}, z.core.$strip>>>;
17
+ home: z.ZodOptional<z.ZodString>;
18
+ }, z.core.$strip>;
19
+ export type PlatformContext = z.infer<typeof PlatformContextSchema>;