@comfanion/usethis_todo 0.1.15-dev.0 → 0.1.15-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.
- package/index.ts +48 -15
- package/package.json +1 -1
- package/tools.ts +7 -12
package/index.ts
CHANGED
|
@@ -11,19 +11,7 @@ interface TodoPruneState {
|
|
|
11
11
|
const pruneStates = new Map<string, TodoPruneState>()
|
|
12
12
|
|
|
13
13
|
const UsethisTodoPlugin: Plugin = async ({ directory, client }) => {
|
|
14
|
-
//
|
|
15
|
-
// Must NOT await — server may block until plugin init completes → deadlock.
|
|
16
|
-
// Wrapped in try-catch because client.path may not exist (sync TypeError).
|
|
17
|
-
try {
|
|
18
|
-
client?.path?.get()?.then((pathInfo: any) => {
|
|
19
|
-
const state = pathInfo?.data?.state
|
|
20
|
-
if (state) setNativeStorageBase(state)
|
|
21
|
-
}).catch(() => {})
|
|
22
|
-
} catch {
|
|
23
|
-
// client.path not available in this SDK version — fall back to guessed paths
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Ensure enhanced storage directory exists on init
|
|
14
|
+
// Ensure storage directory exists on init
|
|
27
15
|
try {
|
|
28
16
|
const todoDir = path.join(directory, ".opencode", "session-todo")
|
|
29
17
|
await fs.mkdir(todoDir, { recursive: true })
|
|
@@ -31,6 +19,18 @@ const UsethisTodoPlugin: Plugin = async ({ directory, client }) => {
|
|
|
31
19
|
// ignore
|
|
32
20
|
}
|
|
33
21
|
|
|
22
|
+
// Resolve native storage path (non-blocking — MUST NOT await in init)
|
|
23
|
+
client.path.get().then((res) => {
|
|
24
|
+
try {
|
|
25
|
+
const state = (res as any)?.data?.state
|
|
26
|
+
if (state && typeof state === "string") {
|
|
27
|
+
setNativeStorageBase(state)
|
|
28
|
+
}
|
|
29
|
+
} catch {
|
|
30
|
+
// ignore
|
|
31
|
+
}
|
|
32
|
+
}).catch(() => {})
|
|
33
|
+
|
|
34
34
|
return {
|
|
35
35
|
"experimental.chat.messages.transform": async (_input: unknown, output: { messages: any[] }) => {
|
|
36
36
|
const messages = output.messages || []
|
|
@@ -141,8 +141,41 @@ const UsethisTodoPlugin: Plugin = async ({ directory, client }) => {
|
|
|
141
141
|
output.title = "📋 Task details"
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
//
|
|
145
|
-
|
|
144
|
+
// Only publish for our write/update tools
|
|
145
|
+
const writeTools = new Set([
|
|
146
|
+
"usethis_todo_write",
|
|
147
|
+
"usethis_todo_update",
|
|
148
|
+
])
|
|
149
|
+
|
|
150
|
+
if (!writeTools.has(input.tool)) return
|
|
151
|
+
|
|
152
|
+
// Attempt sidebar refresh via tui.command.execute hack
|
|
153
|
+
// The server may recognize a command that forces re-read of todo storage
|
|
154
|
+
try {
|
|
155
|
+
await (client as any)?.tui?.publish?.({
|
|
156
|
+
body: {
|
|
157
|
+
type: "tui.command.execute",
|
|
158
|
+
properties: { command: "session.todo.refresh" },
|
|
159
|
+
},
|
|
160
|
+
})
|
|
161
|
+
} catch {
|
|
162
|
+
// ignore — experimental
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Fallback: publish snapshot into chat (helps when sidebar doesn't refresh)
|
|
166
|
+
const text = ["## TODO", "", out].join("\n")
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
await client?.session?.prompt?.({
|
|
170
|
+
path: { id: input.sessionID },
|
|
171
|
+
body: {
|
|
172
|
+
noReply: true,
|
|
173
|
+
parts: [{ type: "text", text }],
|
|
174
|
+
},
|
|
175
|
+
})
|
|
176
|
+
} catch {
|
|
177
|
+
// non-fatal
|
|
178
|
+
}
|
|
146
179
|
},
|
|
147
180
|
}
|
|
148
181
|
}
|
package/package.json
CHANGED
package/tools.ts
CHANGED
|
@@ -111,16 +111,11 @@ interface TodoGraph {
|
|
|
111
111
|
// Storage — dual write
|
|
112
112
|
// ============================================================================
|
|
113
113
|
|
|
114
|
-
// Native storage base path (
|
|
115
|
-
let
|
|
114
|
+
// Native storage base path (resolved from client.path.get() at runtime)
|
|
115
|
+
let nativeStorageBase: string | null = null
|
|
116
116
|
|
|
117
|
-
/**
|
|
118
|
-
* Set the native storage base path (OpenCode's state directory).
|
|
119
|
-
* Called once during plugin initialization with the result of client.path.get().
|
|
120
|
-
* This ensures we write to the exact path OpenCode reads from for the sidebar.
|
|
121
|
-
*/
|
|
122
117
|
export function setNativeStorageBase(statePath: string): void {
|
|
123
|
-
|
|
118
|
+
nativeStorageBase = statePath
|
|
124
119
|
}
|
|
125
120
|
|
|
126
121
|
// Resolve project directory (context.directory may be undefined via MCP)
|
|
@@ -171,12 +166,12 @@ async function getNativeDataDirs(): Promise<string[]> {
|
|
|
171
166
|
async function getNativePaths(sid: string): Promise<string[]> {
|
|
172
167
|
const file = `${sid || "current"}.json`
|
|
173
168
|
|
|
174
|
-
// Prefer
|
|
175
|
-
if (
|
|
176
|
-
return [path.join(
|
|
169
|
+
// Prefer resolved path from client.path.get()
|
|
170
|
+
if (nativeStorageBase) {
|
|
171
|
+
return [path.join(nativeStorageBase, "storage", "todo", file)]
|
|
177
172
|
}
|
|
178
173
|
|
|
179
|
-
// Fallback
|
|
174
|
+
// Fallback to guessed paths
|
|
180
175
|
const baseDirs = await getNativeDataDirs()
|
|
181
176
|
return baseDirs.map((base) => path.join(base, "opencode", "storage", "todo", file))
|
|
182
177
|
}
|