opencode-debug-agent 0.1.0 → 0.1.1
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/dist/index.js +119 -64
- package/package.json +1 -1
- package/src/index.ts +125 -96
package/dist/index.js
CHANGED
|
@@ -10,9 +10,6 @@ var __export = (target, all) => {
|
|
|
10
10
|
});
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
// src/index.ts
|
|
14
|
-
import path from "path";
|
|
15
|
-
|
|
16
13
|
// node_modules/zod/v4/classic/external.js
|
|
17
14
|
var exports_external = {};
|
|
18
15
|
__export(exports_external, {
|
|
@@ -14176,60 +14173,124 @@ var debugStatus = tool({
|
|
|
14176
14173
|
});
|
|
14177
14174
|
|
|
14178
14175
|
// src/index.ts
|
|
14179
|
-
|
|
14180
|
-
|
|
14181
|
-
|
|
14182
|
-
|
|
14183
|
-
|
|
14184
|
-
|
|
14185
|
-
|
|
14186
|
-
|
|
14187
|
-
|
|
14188
|
-
|
|
14189
|
-
|
|
14190
|
-
|
|
14191
|
-
|
|
14192
|
-
|
|
14193
|
-
|
|
14194
|
-
|
|
14195
|
-
|
|
14196
|
-
|
|
14197
|
-
|
|
14198
|
-
|
|
14199
|
-
|
|
14200
|
-
|
|
14201
|
-
|
|
14202
|
-
|
|
14203
|
-
|
|
14204
|
-
|
|
14205
|
-
|
|
14206
|
-
|
|
14207
|
-
|
|
14208
|
-
|
|
14209
|
-
|
|
14210
|
-
|
|
14211
|
-
|
|
14212
|
-
|
|
14213
|
-
|
|
14214
|
-
|
|
14215
|
-
|
|
14216
|
-
|
|
14217
|
-
|
|
14218
|
-
|
|
14219
|
-
|
|
14220
|
-
|
|
14221
|
-
|
|
14222
|
-
|
|
14223
|
-
|
|
14224
|
-
|
|
14225
|
-
|
|
14226
|
-
|
|
14227
|
-
|
|
14228
|
-
}
|
|
14229
|
-
}
|
|
14176
|
+
var AGENT_PROMPT = `You are a debugging specialist. Your purpose is to help users debug runtime issues by capturing and analyzing execution data.
|
|
14177
|
+
|
|
14178
|
+
## IMPORTANT: Port Handling
|
|
14179
|
+
- \`debug_start\` returns a ready-to-use \`snippet\` with the correct port baked in
|
|
14180
|
+
- ALWAYS use the snippet from the tool response - never hardcode ports
|
|
14181
|
+
- If you need the current port later, call \`debug_status\`
|
|
14182
|
+
- The server remembers its port across sessions, so existing instrumentations keep working
|
|
14183
|
+
|
|
14184
|
+
## Workflow
|
|
14185
|
+
|
|
14186
|
+
1. Call \`debug_start\` to start the debug server
|
|
14187
|
+
2. Use the returned \`snippet\` to insert fetch() calls at strategic locations in the user's code
|
|
14188
|
+
- Replace \`LABEL_HERE\` with a descriptive label (e.g., "before-api-call", "user-input", "loop-iteration")
|
|
14189
|
+
- Replace \`YOUR_DATA\` with the variables you want to capture
|
|
14190
|
+
3. Ask user to reproduce the issue
|
|
14191
|
+
4. Call \`debug_read\` to analyze captured logs
|
|
14192
|
+
5. Identify the problem from the runtime data
|
|
14193
|
+
6. Call \`debug_stop\` when done
|
|
14194
|
+
7. Remove all fetch() instrumentation calls from the code
|
|
14195
|
+
|
|
14196
|
+
## If Instrumentations Already Exist
|
|
14197
|
+
- Call \`debug_status\` first to check for existing port
|
|
14198
|
+
- Use \`grep\` to find existing \`localhost:\\d+/log\` patterns in codebase
|
|
14199
|
+
- Start server on the same port to avoid breaking existing instrumentations
|
|
14200
|
+
|
|
14201
|
+
## Example Instrumentation
|
|
14202
|
+
|
|
14203
|
+
After calling \`debug_start\`, you'll get a snippet like:
|
|
14204
|
+
\`\`\`javascript
|
|
14205
|
+
fetch("http://localhost:54321/log", {
|
|
14206
|
+
method: "POST",
|
|
14207
|
+
headers: {"Content-Type": "application/json"},
|
|
14208
|
+
body: JSON.stringify({label: "LABEL_HERE", data: {YOUR_DATA}})
|
|
14209
|
+
})
|
|
14210
|
+
\`\`\`
|
|
14211
|
+
|
|
14212
|
+
Insert this at strategic points:
|
|
14213
|
+
\`\`\`javascript
|
|
14214
|
+
// Before an API call
|
|
14215
|
+
fetch("http://localhost:54321/log", {
|
|
14216
|
+
method: "POST",
|
|
14217
|
+
headers: {"Content-Type": "application/json"},
|
|
14218
|
+
body: JSON.stringify({label: "pre-api", data: {userId, requestBody}})
|
|
14219
|
+
})
|
|
14220
|
+
|
|
14221
|
+
// After receiving response
|
|
14222
|
+
fetch("http://localhost:54321/log", {
|
|
14223
|
+
method: "POST",
|
|
14224
|
+
headers: {"Content-Type": "application/json"},
|
|
14225
|
+
body: JSON.stringify({label: "post-api", data: {response, status}})
|
|
14226
|
+
})
|
|
14227
|
+
\`\`\`
|
|
14228
|
+
|
|
14229
|
+
## Tips
|
|
14230
|
+
- Use descriptive labels to make logs easy to understand
|
|
14231
|
+
- Capture relevant variables at each point
|
|
14232
|
+
- Add instrumentation around suspected problem areas
|
|
14233
|
+
- Compare expected vs actual values in the logs`;
|
|
14234
|
+
var DEBUG_SKILL = {
|
|
14235
|
+
name: "debug",
|
|
14236
|
+
description: "Runtime debugging - start a debug server, instrument code with fetch() calls, capture and analyze execution data",
|
|
14237
|
+
content: `## CRITICAL: Port Handling
|
|
14238
|
+
- \`debug_start\` returns a \`snippet\` with the correct port - ALWAYS use it
|
|
14239
|
+
- Never hardcode ports in fetch() calls
|
|
14240
|
+
- Call \`debug_status\` to get current port if needed later
|
|
14241
|
+
- Server persists port to \`.opencode/debug.port\` so existing instrumentations keep working
|
|
14242
|
+
|
|
14243
|
+
## Workflow
|
|
14244
|
+
|
|
14245
|
+
1. \`debug_start\` - Returns {port, url, snippet}
|
|
14246
|
+
2. Insert the returned \`snippet\` at strategic code locations:
|
|
14247
|
+
- Replace \`LABEL_HERE\` with descriptive label (e.g., "before-api", "after-parse")
|
|
14248
|
+
- Replace \`YOUR_DATA\` with variables to capture (e.g., \`{userId, response}\`)
|
|
14249
|
+
3. Ask user to reproduce the issue
|
|
14250
|
+
4. \`debug_read\` - Analyze captured logs (returns parsed JSON array)
|
|
14251
|
+
5. \`debug_stop\` - Stop server when done
|
|
14252
|
+
6. Remove all fetch() instrumentation calls from the code
|
|
14253
|
+
|
|
14254
|
+
## Before Starting - Check for Existing Instrumentations
|
|
14255
|
+
1. Call \`debug_status\` - check if server already running or port persisted
|
|
14256
|
+
2. Use grep to search for \`localhost:\\d+/log\` patterns in codebase
|
|
14257
|
+
3. If found, ensure server starts on same port to avoid breaking existing code
|
|
14258
|
+
|
|
14259
|
+
## Tools Reference
|
|
14260
|
+
|
|
14261
|
+
| Tool | Args | Returns |
|
|
14262
|
+
|------|------|---------|
|
|
14263
|
+
| \`debug_start\` | \`port?\` | \`{port, url, snippet, message}\` |
|
|
14264
|
+
| \`debug_stop\` | - | confirmation message |
|
|
14265
|
+
| \`debug_read\` | \`tail?\` | \`{entries: [{timestamp, label, data}, ...], count}\` |
|
|
14266
|
+
| \`debug_clear\` | - | confirmation message |
|
|
14267
|
+
| \`debug_status\` | - | \`{active, port?, url?, persistedPort?, hint?}\` |
|
|
14268
|
+
|
|
14269
|
+
## Example Session
|
|
14270
|
+
|
|
14271
|
+
\`\`\`
|
|
14272
|
+
> debug_start
|
|
14273
|
+
{port: 54321, url: "http://localhost:54321", snippet: "fetch(...)"}
|
|
14274
|
+
|
|
14275
|
+
> [Insert snippet at line 42 and 67 in user's code]
|
|
14276
|
+
|
|
14277
|
+
> [User reproduces the issue]
|
|
14278
|
+
|
|
14279
|
+
> debug_read
|
|
14280
|
+
{entries: [
|
|
14281
|
+
{timestamp: "...", label: "before-api", data: {userId: 123}},
|
|
14282
|
+
{timestamp: "...", label: "after-api", data: {error: "timeout"}}
|
|
14283
|
+
], count: 2}
|
|
14284
|
+
|
|
14285
|
+
> [Analyze: API call is timing out]
|
|
14286
|
+
|
|
14287
|
+
> debug_stop
|
|
14288
|
+
{message: "Debug server stopped."}
|
|
14289
|
+
|
|
14290
|
+
> [Remove instrumentation from lines 42 and 67]
|
|
14291
|
+
\`\`\``
|
|
14292
|
+
};
|
|
14230
14293
|
var DebugAgentPlugin = async () => {
|
|
14231
|
-
const skills = await loadSkills();
|
|
14232
|
-
const agentPrompt = await loadAgentPrompt();
|
|
14233
14294
|
return {
|
|
14234
14295
|
tool: {
|
|
14235
14296
|
debug_start: debugStart,
|
|
@@ -14243,17 +14304,11 @@ var DebugAgentPlugin = async () => {
|
|
|
14243
14304
|
config2.agent["debug"] = {
|
|
14244
14305
|
description: "Runtime debugging - capture and analyze execution data",
|
|
14245
14306
|
mode: "primary",
|
|
14246
|
-
prompt:
|
|
14307
|
+
prompt: AGENT_PROMPT
|
|
14247
14308
|
};
|
|
14248
14309
|
const configWithSkill = config2;
|
|
14249
14310
|
configWithSkill.skill = configWithSkill.skill ?? {};
|
|
14250
|
-
|
|
14251
|
-
configWithSkill.skill[skill.name] = {
|
|
14252
|
-
name: skill.name,
|
|
14253
|
-
description: skill.description,
|
|
14254
|
-
content: skill.content
|
|
14255
|
-
};
|
|
14256
|
-
}
|
|
14311
|
+
configWithSkill.skill[DEBUG_SKILL.name] = DEBUG_SKILL;
|
|
14257
14312
|
}
|
|
14258
14313
|
};
|
|
14259
14314
|
};
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -9,102 +9,137 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import type { Plugin } from '@opencode-ai/plugin';
|
|
12
|
-
import path from 'path';
|
|
13
12
|
import { debugStart, debugStop, debugRead, debugClear, debugStatus } from './tools';
|
|
14
13
|
|
|
15
14
|
// ============================================================
|
|
16
|
-
//
|
|
17
|
-
// Loads SKILL.md files from src/skill/ directory
|
|
15
|
+
// EMBEDDED CONTENT (to avoid file loading issues in npm packages)
|
|
18
16
|
// ============================================================
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
18
|
+
const AGENT_PROMPT = `You are a debugging specialist. Your purpose is to help users debug runtime issues by capturing and analyzing execution data.
|
|
19
|
+
|
|
20
|
+
## IMPORTANT: Port Handling
|
|
21
|
+
- \`debug_start\` returns a ready-to-use \`snippet\` with the correct port baked in
|
|
22
|
+
- ALWAYS use the snippet from the tool response - never hardcode ports
|
|
23
|
+
- If you need the current port later, call \`debug_status\`
|
|
24
|
+
- The server remembers its port across sessions, so existing instrumentations keep working
|
|
25
|
+
|
|
26
|
+
## Workflow
|
|
27
|
+
|
|
28
|
+
1. Call \`debug_start\` to start the debug server
|
|
29
|
+
2. Use the returned \`snippet\` to insert fetch() calls at strategic locations in the user's code
|
|
30
|
+
- Replace \`LABEL_HERE\` with a descriptive label (e.g., "before-api-call", "user-input", "loop-iteration")
|
|
31
|
+
- Replace \`YOUR_DATA\` with the variables you want to capture
|
|
32
|
+
3. Ask user to reproduce the issue
|
|
33
|
+
4. Call \`debug_read\` to analyze captured logs
|
|
34
|
+
5. Identify the problem from the runtime data
|
|
35
|
+
6. Call \`debug_stop\` when done
|
|
36
|
+
7. Remove all fetch() instrumentation calls from the code
|
|
37
|
+
|
|
38
|
+
## If Instrumentations Already Exist
|
|
39
|
+
- Call \`debug_status\` first to check for existing port
|
|
40
|
+
- Use \`grep\` to find existing \`localhost:\\d+/log\` patterns in codebase
|
|
41
|
+
- Start server on the same port to avoid breaking existing instrumentations
|
|
42
|
+
|
|
43
|
+
## Example Instrumentation
|
|
44
|
+
|
|
45
|
+
After calling \`debug_start\`, you'll get a snippet like:
|
|
46
|
+
\`\`\`javascript
|
|
47
|
+
fetch("http://localhost:54321/log", {
|
|
48
|
+
method: "POST",
|
|
49
|
+
headers: {"Content-Type": "application/json"},
|
|
50
|
+
body: JSON.stringify({label: "LABEL_HERE", data: {YOUR_DATA}})
|
|
51
|
+
})
|
|
52
|
+
\`\`\`
|
|
53
|
+
|
|
54
|
+
Insert this at strategic points:
|
|
55
|
+
\`\`\`javascript
|
|
56
|
+
// Before an API call
|
|
57
|
+
fetch("http://localhost:54321/log", {
|
|
58
|
+
method: "POST",
|
|
59
|
+
headers: {"Content-Type": "application/json"},
|
|
60
|
+
body: JSON.stringify({label: "pre-api", data: {userId, requestBody}})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
// After receiving response
|
|
64
|
+
fetch("http://localhost:54321/log", {
|
|
65
|
+
method: "POST",
|
|
66
|
+
headers: {"Content-Type": "application/json"},
|
|
67
|
+
body: JSON.stringify({label: "post-api", data: {response, status}})
|
|
68
|
+
})
|
|
69
|
+
\`\`\`
|
|
70
|
+
|
|
71
|
+
## Tips
|
|
72
|
+
- Use descriptive labels to make logs easy to understand
|
|
73
|
+
- Capture relevant variables at each point
|
|
74
|
+
- Add instrumentation around suspected problem areas
|
|
75
|
+
- Compare expected vs actual values in the logs`;
|
|
76
|
+
|
|
77
|
+
const DEBUG_SKILL = {
|
|
78
|
+
name: 'debug',
|
|
79
|
+
description:
|
|
80
|
+
'Runtime debugging - start a debug server, instrument code with fetch() calls, capture and analyze execution data',
|
|
81
|
+
content: `## CRITICAL: Port Handling
|
|
82
|
+
- \`debug_start\` returns a \`snippet\` with the correct port - ALWAYS use it
|
|
83
|
+
- Never hardcode ports in fetch() calls
|
|
84
|
+
- Call \`debug_status\` to get current port if needed later
|
|
85
|
+
- Server persists port to \`.opencode/debug.port\` so existing instrumentations keep working
|
|
86
|
+
|
|
87
|
+
## Workflow
|
|
88
|
+
|
|
89
|
+
1. \`debug_start\` - Returns {port, url, snippet}
|
|
90
|
+
2. Insert the returned \`snippet\` at strategic code locations:
|
|
91
|
+
- Replace \`LABEL_HERE\` with descriptive label (e.g., "before-api", "after-parse")
|
|
92
|
+
- Replace \`YOUR_DATA\` with variables to capture (e.g., \`{userId, response}\`)
|
|
93
|
+
3. Ask user to reproduce the issue
|
|
94
|
+
4. \`debug_read\` - Analyze captured logs (returns parsed JSON array)
|
|
95
|
+
5. \`debug_stop\` - Stop server when done
|
|
96
|
+
6. Remove all fetch() instrumentation calls from the code
|
|
97
|
+
|
|
98
|
+
## Before Starting - Check for Existing Instrumentations
|
|
99
|
+
1. Call \`debug_status\` - check if server already running or port persisted
|
|
100
|
+
2. Use grep to search for \`localhost:\\d+/log\` patterns in codebase
|
|
101
|
+
3. If found, ensure server starts on same port to avoid breaking existing code
|
|
102
|
+
|
|
103
|
+
## Tools Reference
|
|
104
|
+
|
|
105
|
+
| Tool | Args | Returns |
|
|
106
|
+
|------|------|---------|
|
|
107
|
+
| \`debug_start\` | \`port?\` | \`{port, url, snippet, message}\` |
|
|
108
|
+
| \`debug_stop\` | - | confirmation message |
|
|
109
|
+
| \`debug_read\` | \`tail?\` | \`{entries: [{timestamp, label, data}, ...], count}\` |
|
|
110
|
+
| \`debug_clear\` | - | confirmation message |
|
|
111
|
+
| \`debug_status\` | - | \`{active, port?, url?, persistedPort?, hint?}\` |
|
|
112
|
+
|
|
113
|
+
## Example Session
|
|
114
|
+
|
|
115
|
+
\`\`\`
|
|
116
|
+
> debug_start
|
|
117
|
+
{port: 54321, url: "http://localhost:54321", snippet: "fetch(...)"}
|
|
118
|
+
|
|
119
|
+
> [Insert snippet at line 42 and 67 in user's code]
|
|
120
|
+
|
|
121
|
+
> [User reproduces the issue]
|
|
122
|
+
|
|
123
|
+
> debug_read
|
|
124
|
+
{entries: [
|
|
125
|
+
{timestamp: "...", label: "before-api", data: {userId: 123}},
|
|
126
|
+
{timestamp: "...", label: "after-api", data: {error: "timeout"}}
|
|
127
|
+
], count: 2}
|
|
128
|
+
|
|
129
|
+
> [Analyze: API call is timing out]
|
|
130
|
+
|
|
131
|
+
> debug_stop
|
|
132
|
+
{message: "Debug server stopped."}
|
|
133
|
+
|
|
134
|
+
> [Remove instrumentation from lines 42 and 67]
|
|
135
|
+
\`\`\``,
|
|
136
|
+
};
|
|
86
137
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
async function loadAgentPrompt(): Promise<string> {
|
|
91
|
-
try {
|
|
92
|
-
const agentFile = path.join(import.meta.dir, 'agent', 'debug.md');
|
|
93
|
-
const content = await Bun.file(agentFile).text();
|
|
94
|
-
|
|
95
|
-
// Extract body after frontmatter
|
|
96
|
-
const match = content.match(/^---\n[\s\S]*?\n---\n([\s\S]*)$/);
|
|
97
|
-
return match ? match[1].trim() : content;
|
|
98
|
-
} catch {
|
|
99
|
-
return 'You are a debugging specialist.';
|
|
100
|
-
}
|
|
101
|
-
}
|
|
138
|
+
// ============================================================
|
|
139
|
+
// PLUGIN EXPORT
|
|
140
|
+
// ============================================================
|
|
102
141
|
|
|
103
142
|
export const DebugAgentPlugin: Plugin = async () => {
|
|
104
|
-
// Load skills at initialization
|
|
105
|
-
const skills = await loadSkills();
|
|
106
|
-
const agentPrompt = await loadAgentPrompt();
|
|
107
|
-
|
|
108
143
|
return {
|
|
109
144
|
// Register debug tools
|
|
110
145
|
tool: {
|
|
@@ -122,7 +157,7 @@ export const DebugAgentPlugin: Plugin = async () => {
|
|
|
122
157
|
config.agent['debug'] = {
|
|
123
158
|
description: 'Runtime debugging - capture and analyze execution data',
|
|
124
159
|
mode: 'primary',
|
|
125
|
-
prompt:
|
|
160
|
+
prompt: AGENT_PROMPT,
|
|
126
161
|
};
|
|
127
162
|
|
|
128
163
|
// Inject skills (using type assertion as skill may not be in Config type yet)
|
|
@@ -130,13 +165,7 @@ export const DebugAgentPlugin: Plugin = async () => {
|
|
|
130
165
|
skill?: Record<string, { name: string; description: string; content: string }>;
|
|
131
166
|
};
|
|
132
167
|
configWithSkill.skill = configWithSkill.skill ?? {};
|
|
133
|
-
|
|
134
|
-
configWithSkill.skill[skill.name] = {
|
|
135
|
-
name: skill.name,
|
|
136
|
-
description: skill.description,
|
|
137
|
-
content: skill.content,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
168
|
+
configWithSkill.skill[DEBUG_SKILL.name] = DEBUG_SKILL;
|
|
140
169
|
},
|
|
141
170
|
};
|
|
142
171
|
};
|