@comfanion/usethis_todo 0.1.7-dev.0 → 0.1.7-dev.2

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 +78 -1
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -2,6 +2,12 @@ import type { Plugin } from "@opencode-ai/plugin"
2
2
 
3
3
  import { write, read, read_five, read_by_id, update } from "./tools"
4
4
 
5
+ interface TodoPruneState {
6
+ lastToolCallId: string | null
7
+ }
8
+
9
+ const pruneStates = new Map<string, TodoPruneState>()
10
+
5
11
  const UsethisTodoPlugin: Plugin = async ({ directory, client }) => {
6
12
  // Ensure storage directory exists on init
7
13
  try {
@@ -12,6 +18,69 @@ const UsethisTodoPlugin: Plugin = async ({ directory, client }) => {
12
18
  }
13
19
 
14
20
  return {
21
+ "experimental.chat.messages.transform": async (_input: unknown, output: { messages: any[] }) => {
22
+ const messages = output.messages || []
23
+ const sessionID = messages[0]?.info?.sessionID
24
+
25
+ if (!sessionID) return
26
+
27
+ const state = pruneStates.get(sessionID)
28
+ if (!state?.lastToolCallId) return
29
+
30
+ const prunedToolNames = new Set([
31
+ "usethis_todo_write",
32
+ "usethis_todo_update",
33
+ "usethis_todo_read",
34
+ "usethis_todo_read_five",
35
+ "usethis_todo_read_by_id",
36
+ "todowrite",
37
+ "todoread",
38
+ ])
39
+
40
+ // 1. Collect all "## TODO" user messages and all tool outputs
41
+ const todoTextParts: { part: any }[] = []
42
+ const todoToolParts: { part: any; isLast: boolean }[] = []
43
+
44
+ for (const msg of messages) {
45
+ const parts = Array.isArray(msg.parts) ? msg.parts : []
46
+ for (const part of parts) {
47
+ // Tool outputs
48
+ if (part.type === "tool" && prunedToolNames.has(part.tool) && part.state?.status === "completed") {
49
+ todoToolParts.push({ part, isLast: part.callID === state.lastToolCallId })
50
+ }
51
+ // User "## TODO" snapshots
52
+ if (part.type === "text" && typeof part.text === "string" && part.text.startsWith("## TODO")) {
53
+ todoTextParts.push({ part })
54
+ }
55
+ }
56
+ }
57
+
58
+ // 2. Check if all tasks are done by parsing the latest snapshot
59
+ const lastSnapshot = todoTextParts[todoTextParts.length - 1]?.part.text || ""
60
+ const doneMatch = lastSnapshot.match(/\[(\d+)\/(\d+) done/)
61
+ const allDone = doneMatch && doneMatch[1] === doneMatch[2] && parseInt(doneMatch[1]) > 0
62
+
63
+ // 3. Prune tool outputs
64
+ for (const { part, isLast } of todoToolParts) {
65
+ if (allDone || !isLast) {
66
+ part.state.output = "[TODO output pruned - see latest]"
67
+ }
68
+ }
69
+
70
+ // 4. Prune "## TODO" user messages
71
+ if (allDone) {
72
+ // All done → prune everything, no need to keep any snapshot
73
+ for (const { part } of todoTextParts) {
74
+ part.text = "[TODO completed - all tasks done]"
75
+ }
76
+ } else if (todoTextParts.length > 1) {
77
+ // Active tasks → keep only the last snapshot
78
+ for (let i = 0; i < todoTextParts.length - 1; i++) {
79
+ todoTextParts[i].part.text = "[TODO snapshot pruned - see latest]"
80
+ }
81
+ }
82
+ },
83
+
15
84
  tool: {
16
85
  usethis_todo_write: write,
17
86
  usethis_todo_read: read,
@@ -22,7 +91,15 @@ const UsethisTodoPlugin: Plugin = async ({ directory, client }) => {
22
91
 
23
92
  // UI niceties + publish snapshot into the chat
24
93
  "tool.execute.after": async (input, output) => {
25
- if (!input.tool.startsWith("usethis_todo_")) return
94
+ if (!input.tool.startsWith("usethis_todo_") && input.tool !== "todowrite" && input.tool !== "todoread") return
95
+
96
+ // Update prune state with latest call ID
97
+ const sessionID = input.sessionID
98
+ if (sessionID) {
99
+ const state = pruneStates.get(sessionID) || { lastToolCallId: null }
100
+ state.lastToolCallId = input.callID
101
+ pruneStates.set(sessionID, state)
102
+ }
26
103
 
27
104
  const out = output.output || ""
28
105
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comfanion/usethis_todo",
3
- "version": "0.1.7-dev.0",
3
+ "version": "0.1.7-dev.2",
4
4
  "description": "OpenCode plugin: enhanced TODO tools (dual storage + dependency graph)",
5
5
  "type": "module",
6
6
  "main": "./index.ts",