@comfanion/usethis_todo 0.1.16-dev.2 → 0.1.16-dev.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.
Files changed (3) hide show
  1. package/index.ts +38 -17
  2. package/package.json +1 -1
  3. package/tools.ts +5 -5
package/index.ts CHANGED
@@ -2,7 +2,7 @@ import type { Plugin } from "@opencode-ai/plugin"
2
2
  import path from "path"
3
3
  import fs from "fs/promises"
4
4
 
5
- import { write, read, read_five, read_by_id, setNativeStorageBase } from "./tools"
5
+ import { write, read, read_five, read_by_id, setNativeStorageBase, readTodos } from "./tools"
6
6
 
7
7
  interface TodoPruneState {
8
8
  lastToolCallId: string | null
@@ -37,10 +37,11 @@ const UsethisTodoPlugin: Plugin = async ({ directory, client }) => {
37
37
  if (!state?.lastToolCallId) return
38
38
 
39
39
  const prunedToolNames = new Set([
40
- "todowrite",
41
- "todoread",
40
+ "usethis_todo_write",
41
+ "usethis_todo_read",
42
42
  "usethis_todo_read_five",
43
43
  "usethis_todo_read_by_id",
44
+ "todowrite",
44
45
  ])
45
46
 
46
47
  // Collect all TODO-related tool parts
@@ -66,41 +67,61 @@ const UsethisTodoPlugin: Plugin = async ({ directory, client }) => {
66
67
  },
67
68
 
68
69
  tool: {
69
- // Native overrides tool named "todowrite"/"todoread" completing
70
- // triggers Bus.publish("todo.updated") → sidebar refresh
71
- todowrite: write,
72
- todoread: read,
73
- // Extra tools (no native equivalent)
70
+ // Our enhanced tools AI uses these for graph/dependencies
71
+ usethis_todo_write: write,
72
+ usethis_todo_read: read,
74
73
  usethis_todo_read_five: read_five,
75
74
  usethis_todo_read_by_id: read_by_id,
75
+
76
+ // Native override — emulates todowrite for sidebar refresh + TUI checklist
77
+ // Reads the data our write already stored and returns native JSON format.
78
+ // tool.execute.after on usethis_todo_write auto-invokes this via description hint.
79
+ todowrite: {
80
+ description: "Internal: sync TODO sidebar. Called automatically after usethis_todo_write.",
81
+ args: {},
82
+ async execute(_args: any, context: any) {
83
+ const todos = await readTodos(context.sessionID, context.directory)
84
+ // Return native format: JSON array → TUI renders checklist + fires todo.updated
85
+ return JSON.stringify(todos.map(t => ({
86
+ id: t.id,
87
+ content: t.content,
88
+ status: t.status,
89
+ priority: t.priority,
90
+ })))
91
+ },
92
+ },
76
93
  },
77
94
 
78
95
  // Set nicer titles in TUI + track prune state
79
96
  "tool.execute.after": async (input, output) => {
80
- const ourTools = new Set(["todowrite", "todoread", "usethis_todo_read_five", "usethis_todo_read_by_id"])
97
+ const ourTools = new Set(["usethis_todo_write", "usethis_todo_read", "usethis_todo_read_five", "usethis_todo_read_by_id", "todowrite"])
81
98
  if (!ourTools.has(input.tool)) return
82
99
 
83
- // Update prune state with latest call ID
84
- const sessionID = input.sessionID
85
- if (sessionID) {
86
- const state = pruneStates.get(sessionID) || { lastToolCallId: null }
87
- state.lastToolCallId = input.callID
88
- pruneStates.set(sessionID, state)
100
+ // Update prune state with latest call ID (only for our custom tools, not todowrite)
101
+ if (input.tool.startsWith("usethis_todo_")) {
102
+ const sessionID = input.sessionID
103
+ if (sessionID) {
104
+ const state = pruneStates.get(sessionID) || { lastToolCallId: null }
105
+ state.lastToolCallId = input.callID
106
+ pruneStates.set(sessionID, state)
107
+ }
89
108
  }
90
109
 
91
110
  const out = output.output || ""
92
111
 
93
112
  // Set a nicer title in TUI
94
- if (input.tool === "todowrite") {
113
+ if (input.tool === "usethis_todo_write") {
95
114
  const match = out.match(/\[(\d+)\/(\d+) done/)
96
115
  output.title = match ? `TODO: ${match[2]} tasks` : "TODO updated"
97
- } else if (input.tool === "todoread") {
116
+ } else if (input.tool === "usethis_todo_read") {
98
117
  const match = out.match(/\[(\d+)\/(\d+) done, (\d+) in progress\]/)
99
118
  output.title = match ? `TODO [${match[1]}/${match[2]} done]` : "TODO list"
100
119
  } else if (input.tool === "usethis_todo_read_five") {
101
120
  output.title = "Next 5 tasks"
102
121
  } else if (input.tool === "usethis_todo_read_by_id") {
103
122
  output.title = "Task details"
123
+ } else if (input.tool === "todowrite") {
124
+ output.title = "Sidebar sync"
104
125
  }
105
126
  },
106
127
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comfanion/usethis_todo",
3
- "version": "0.1.16-dev.2",
3
+ "version": "0.1.16-dev.4",
4
4
  "description": "OpenCode plugin: enhanced TODO tools (dual storage + dependency graph)",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
package/tools.ts CHANGED
@@ -2,10 +2,10 @@
2
2
  * TODO Tool with Dependencies & Priority — v4 (unified storage)
3
3
  *
4
4
  * 4 tools:
5
- * todowrite({ todos: [...], merge? }) - create/update TODO list (upsert by default)
6
- * todoread() - read TODO with graph analysis
7
- * todoread_five() - read next 5 tasks with their blockers
8
- * todoread_by_id({ id }) - read task by id with its blockers
5
+ * usethis_todo_write({ todos, merge? }) - create/update TODO list (upsert by default)
6
+ * usethis_todo_read() - read TODO with graph analysis
7
+ * usethis_todo_read_five() - read next 5 tasks with their blockers
8
+ * usethis_todo_read_by_id({ id }) - read task by id with its blockers
9
9
  *
10
10
  * Storage:
11
11
  * Unified: Native OpenCode storage (TUI compatible)
@@ -194,7 +194,7 @@ function toNativePriority(priority: string): string {
194
194
  // Read / Write
195
195
  // ============================================================================
196
196
 
197
- async function readTodos(sid: string, directory?: string): Promise<Todo[]> {
197
+ export async function readTodos(sid: string, directory?: string): Promise<Todo[]> {
198
198
  try {
199
199
  const storagePaths = await getStoragePaths(sid)
200
200
  for (const storagePath of storagePaths) {