@comfanion/usethis_todo 0.1.15-dev.6 → 0.1.15-dev.8

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 (2) hide show
  1. package/index.ts +14 -69
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import type { Plugin } from "@opencode-ai/plugin"
2
+ import path from "path"
3
+ import fs from "fs/promises"
2
4
 
3
5
  import { write, read, read_five, read_by_id, update } from "./tools"
4
6
 
@@ -8,7 +10,7 @@ interface TodoPruneState {
8
10
 
9
11
  const pruneStates = new Map<string, TodoPruneState>()
10
12
 
11
- const UsethisTodoPlugin: Plugin = async ({ directory, client }) => {
13
+ const UsethisTodoPlugin: Plugin = async ({ directory }) => {
12
14
  // Ensure storage directory exists on init
13
15
  try {
14
16
  const todoDir = path.join(directory, ".opencode", "session-todo")
@@ -37,56 +39,26 @@ const UsethisTodoPlugin: Plugin = async ({ directory, client }) => {
37
39
  "todoread",
38
40
  ])
39
41
 
40
- // 1. Collect all TODO-related parts
42
+ // Collect all TODO-related tool parts
41
43
  const toolParts: { part: any; isLast: boolean }[] = []
42
- const snapshotParts = new Set<any>()
43
- let lastSnapshotPart: any = null
44
44
 
45
45
  for (const msg of messages) {
46
46
  for (const part of (msg.parts || [])) {
47
- // Tool parts (contain both state.input and state.output)
48
47
  if (part.type === "tool" && prunedToolNames.has(part.tool) && part.state?.status === "completed") {
49
48
  toolParts.push({ part, isLast: part.callID === state.lastToolCallId })
50
49
  }
51
- // User "## TODO" snapshot text parts
52
- if (part.type === "text" && typeof part.text === "string" && part.text.startsWith("## TODO")) {
53
- snapshotParts.add(part)
54
- lastSnapshotPart = part
55
- }
56
50
  }
57
51
  }
58
52
 
59
- if (toolParts.length === 0 && snapshotParts.size === 0) return
60
-
61
- // 2. Check if all tasks are done by parsing the latest snapshot
62
- const lastSnapshotText = lastSnapshotPart?.text || ""
63
- const doneMatch = lastSnapshotText.match(/\[(\d+)\/(\d+) done/)
64
- const allDone = doneMatch && doneMatch[1] === doneMatch[2] && parseInt(doneMatch[1]) > 0
53
+ if (toolParts.length === 0) return
65
54
 
66
- // 3. Prune old tool parts — clear BOTH input and output
55
+ // Prune old tool parts — clear BOTH input and output, keep only last
67
56
  for (const { part, isLast } of toolParts) {
68
- if (allDone || !isLast) {
57
+ if (!isLast) {
69
58
  part.state.output = "[TODO pruned]"
70
59
  if (part.state.input) part.state.input = {}
71
60
  }
72
61
  }
73
-
74
- // 4. Remove old "## TODO" snapshot parts entirely from messages
75
- // Keep only the last snapshot (or none if allDone)
76
- const snapshotsToRemove = new Set(snapshotParts)
77
- if (!allDone && lastSnapshotPart) {
78
- snapshotsToRemove.delete(lastSnapshotPart)
79
- }
80
-
81
- if (snapshotsToRemove.size > 0) {
82
- for (const msg of messages) {
83
- if (!Array.isArray(msg.parts)) continue
84
- msg.parts = msg.parts.filter((p: any) => !snapshotsToRemove.has(p))
85
- }
86
- }
87
-
88
- // 5. Remove messages that became empty after part removal
89
- output.messages = messages.filter((msg: any) => (msg.parts || []).length > 0)
90
62
  },
91
63
 
92
64
  tool: {
@@ -96,12 +68,12 @@ const UsethisTodoPlugin: Plugin = async ({ directory, client }) => {
96
68
  usethis_todo_read_five: read_five,
97
69
  usethis_todo_read_by_id: read_by_id,
98
70
  usethis_todo_update: update,
99
- // Override native tools — server may emit todo.updated for these names
71
+ // Override native tools — same implementation, native names
100
72
  todowrite: write,
101
73
  todoread: read,
102
74
  },
103
75
 
104
- // UI niceties + publish snapshot into the chat
76
+ // Set nicer titles in TUI + track prune state
105
77
  "tool.execute.after": async (input, output) => {
106
78
  if (!input.tool.startsWith("usethis_todo_") && input.tool !== "todowrite" && input.tool !== "todoread") return
107
79
 
@@ -118,44 +90,17 @@ const UsethisTodoPlugin: Plugin = async ({ directory, client }) => {
118
90
  // Set a nicer title in TUI
119
91
  if (input.tool === "usethis_todo_write" || input.tool === "todowrite") {
120
92
  const match = out.match(/\[(\d+)\/(\d+) done/)
121
- output.title = match ? `📋 TODO: ${match[2]} tasks` : "📋 TODO updated"
93
+ output.title = match ? `TODO: ${match[2]} tasks` : "TODO updated"
122
94
  } else if (input.tool === "usethis_todo_update") {
123
95
  const match = out.match(/^✅ (.+)$/m)
124
- output.title = match ? `📝 ${match[1]}` : "📝 Task updated"
96
+ output.title = match ? match[1] : "Task updated"
125
97
  } else if (input.tool === "usethis_todo_read" || input.tool === "todoread") {
126
98
  const match = out.match(/\[(\d+)\/(\d+) done, (\d+) in progress\]/)
127
- output.title = match ? `📋 TODO [${match[1]}/${match[2]} done]` : "📋 TODO list"
99
+ output.title = match ? `TODO [${match[1]}/${match[2]} done]` : "TODO list"
128
100
  } else if (input.tool === "usethis_todo_read_five") {
129
- output.title = "📋 Next 5 tasks"
101
+ output.title = "Next 5 tasks"
130
102
  } else if (input.tool === "usethis_todo_read_by_id") {
131
- output.title = "📋 Task details"
132
- }
133
-
134
- // Publish snapshot into chat (sidebar doesn't refresh from plugin writes)
135
- const publishTools = new Set([
136
- "usethis_todo_write",
137
- "usethis_todo_update",
138
- "usethis_todo_read",
139
- "usethis_todo_read_five",
140
- "usethis_todo_read_by_id",
141
- "todowrite",
142
- "todoread",
143
- ])
144
-
145
- if (!publishTools.has(input.tool)) return
146
-
147
- const text = ["## TODO", "", out].join("\n")
148
-
149
- try {
150
- await client?.session?.prompt?.({
151
- path: { id: input.sessionID },
152
- body: {
153
- noReply: true,
154
- parts: [{ type: "text", text }],
155
- },
156
- })
157
- } catch {
158
- // non-fatal
103
+ output.title = "Task details"
159
104
  }
160
105
  },
161
106
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comfanion/usethis_todo",
3
- "version": "0.1.15-dev.6",
3
+ "version": "0.1.15-dev.8",
4
4
  "description": "OpenCode plugin: enhanced TODO tools (dual storage + dependency graph)",
5
5
  "type": "module",
6
6
  "main": "./index.ts",