opencode-debug-agent 0.1.1 → 0.1.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/dist/index.js CHANGED
@@ -13967,7 +13967,7 @@ class DebugServer {
13967
13967
  };
13968
13968
  await this.appendLog(entry);
13969
13969
  return c.json({ success: true });
13970
- } catch (error45) {
13970
+ } catch {
13971
13971
  return c.json({ error: "Invalid JSON" }, 400);
13972
13972
  }
13973
13973
  });
@@ -14290,7 +14290,7 @@ var DEBUG_SKILL = {
14290
14290
  > [Remove instrumentation from lines 42 and 67]
14291
14291
  \`\`\``
14292
14292
  };
14293
- var DebugAgentPlugin = async () => {
14293
+ var DebugAgentPlugin = async (ctx) => {
14294
14294
  return {
14295
14295
  tool: {
14296
14296
  debug_start: debugStart,
@@ -14314,6 +14314,5 @@ var DebugAgentPlugin = async () => {
14314
14314
  };
14315
14315
  var src_default = DebugAgentPlugin;
14316
14316
  export {
14317
- src_default as default,
14318
- DebugAgentPlugin
14317
+ src_default as default
14319
14318
  };
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "opencode-debug-agent",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "OpenCode plugin for runtime debugging - capture and analyze execution data",
5
5
  "author": {
6
6
  "name": "anis00723",
7
7
  "email": "anis00723@gmail.com"
8
8
  },
9
9
  "type": "module",
10
+ "main": "dist/index.js",
11
+ "types": "dist/index.d.ts",
10
12
  "exports": {
11
13
  ".": {
12
14
  "types": "./dist/index.d.ts",
@@ -15,34 +17,35 @@
15
17
  },
16
18
  "repository": {
17
19
  "type": "git",
18
- "url": "https://github.com/anis-dr/opencode-debug-agent.git"
20
+ "url": "git+https://github.com/anis-dr/opencode-debug-agent.git"
19
21
  },
20
22
  "publishConfig": {
21
23
  "access": "public"
22
24
  },
23
25
  "files": [
24
- "dist",
25
- "src"
26
+ "dist"
26
27
  ],
27
28
  "scripts": {
28
- "build": "bun build ./src/index.ts --outdir dist --target bun",
29
+ "build": "bun build ./src/index.ts --outdir dist --target bun --format esm",
29
30
  "prepublishOnly": "bun run build"
30
31
  },
32
+ "opencode": {
33
+ "type": "plugin"
34
+ },
35
+ "keywords": [
36
+ "opencode",
37
+ "opencode-plugin",
38
+ "debug",
39
+ "debugging",
40
+ "runtime"
41
+ ],
42
+ "license": "MIT",
31
43
  "dependencies": {
32
- "@opencode-ai/plugin": "1.0.85",
44
+ "@opencode-ai/plugin": "^1.0.162",
33
45
  "hono": "^4"
34
46
  },
35
47
  "devDependencies": {
36
- "@eslint/js": "^9.39.1",
37
- "@types/node": "^20.11.5",
38
- "@typescript-eslint/eslint-plugin": "8.47.0",
39
- "@typescript-eslint/parser": "8.47.0",
40
- "bun-types": "latest",
41
- "eslint": "^9.39.1",
42
- "eslint-config-prettier": "10.1.8",
43
- "eslint-plugin-prettier": "^5.1.3",
44
- "prettier": "^3.2.4",
45
- "typescript-eslint": "^8.47.0",
46
- "vitest": "^3.2.4"
48
+ "@types/bun": "latest",
49
+ "typescript": "^5"
47
50
  }
48
51
  }
@@ -1,74 +0,0 @@
1
- ---
2
- description: Runtime debugging - capture and analyze execution data
3
- mode: primary
4
- tools:
5
- debug_start: true
6
- debug_stop: true
7
- debug_read: true
8
- debug_clear: true
9
- debug_status: true
10
- read: true
11
- edit: true
12
- bash: true
13
- glob: true
14
- grep: true
15
- ---
16
-
17
- You are a debugging specialist. Your purpose is to help users debug runtime issues by capturing and analyzing execution data.
18
-
19
- ## IMPORTANT: Port Handling
20
- - `debug_start` returns a ready-to-use `snippet` with the correct port baked in
21
- - ALWAYS use the snippet from the tool response - never hardcode ports
22
- - If you need the current port later, call `debug_status`
23
- - The server remembers its port across sessions, so existing instrumentations keep working
24
-
25
- ## Workflow
26
-
27
- 1. Call `debug_start` to start the debug server
28
- 2. Use the returned `snippet` to insert fetch() calls at strategic locations in the user's code
29
- - Replace `LABEL_HERE` with a descriptive label (e.g., "before-api-call", "user-input", "loop-iteration")
30
- - Replace `YOUR_DATA` with the variables you want to capture
31
- 3. Ask user to reproduce the issue
32
- 4. Call `debug_read` to analyze captured logs
33
- 5. Identify the problem from the runtime data
34
- 6. Call `debug_stop` when done
35
- 7. Remove all fetch() instrumentation calls from the code
36
-
37
- ## If Instrumentations Already Exist
38
- - Call `debug_status` first to check for existing port
39
- - Use `grep` to find existing `localhost:\d+/log` patterns in codebase
40
- - Start server on the same port to avoid breaking existing instrumentations
41
-
42
- ## Example Instrumentation
43
-
44
- After calling `debug_start`, you'll get a snippet like:
45
- ```javascript
46
- fetch("http://localhost:54321/log", {
47
- method: "POST",
48
- headers: {"Content-Type": "application/json"},
49
- body: JSON.stringify({label: "LABEL_HERE", data: {YOUR_DATA}})
50
- })
51
- ```
52
-
53
- Insert this at strategic points:
54
- ```javascript
55
- // Before an API call
56
- fetch("http://localhost:54321/log", {
57
- method: "POST",
58
- headers: {"Content-Type": "application/json"},
59
- body: JSON.stringify({label: "pre-api", data: {userId, requestBody}})
60
- })
61
-
62
- // After receiving response
63
- fetch("http://localhost:54321/log", {
64
- method: "POST",
65
- headers: {"Content-Type": "application/json"},
66
- body: JSON.stringify({label: "post-api", data: {response, status}})
67
- })
68
- ```
69
-
70
- ## Tips
71
- - Use descriptive labels to make logs easy to understand
72
- - Capture relevant variables at each point
73
- - Add instrumentation around suspected problem areas
74
- - Compare expected vs actual values in the logs
@@ -1,10 +0,0 @@
1
- ---
2
- description: Explain the current file or selection
3
- model: anthropic/claude-sonnet-4-20250514
4
- ---
5
-
6
- Explain the code in the current context:
7
-
8
- - What does it do?
9
- - How does it work?
10
- - Any notable patterns or techniques used?
@@ -1,6 +0,0 @@
1
- ---
2
- description: Check code formatting without blocking
3
- subtask: true
4
- ---
5
-
6
- Run the formatter check and report any files that need formatting.
@@ -1,5 +0,0 @@
1
- ---
2
- description: A friendly greeting command
3
- ---
4
-
5
- Say hello to the user in a friendly and creative way.
@@ -1,12 +0,0 @@
1
- ---
2
- description: Quick code review of staged changes
3
- agent: plan
4
- ---
5
-
6
- Review the staged git changes and provide:
7
-
8
- 1. A brief summary of what changed
9
- 2. Any potential issues or improvements
10
- 3. Overall assessment (good to merge / needs work)
11
-
12
- Be concise and actionable.
package/src/index.ts DELETED
@@ -1,174 +0,0 @@
1
- /**
2
- * OpenCode Debug Agent Plugin
3
- *
4
- * Provides runtime debugging capabilities:
5
- * - Debug HTTP server for capturing execution data
6
- * - 5 tools: debug_start, debug_stop, debug_read, debug_clear, debug_status
7
- * - Debug agent (primary) for dedicated debugging sessions
8
- * - Debug skill for use with any agent
9
- */
10
-
11
- import type { Plugin } from '@opencode-ai/plugin';
12
- import { debugStart, debugStop, debugRead, debugClear, debugStatus } from './tools';
13
-
14
- // ============================================================
15
- // EMBEDDED CONTENT (to avoid file loading issues in npm packages)
16
- // ============================================================
17
-
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
- };
137
-
138
- // ============================================================
139
- // PLUGIN EXPORT
140
- // ============================================================
141
-
142
- export const DebugAgentPlugin: Plugin = async () => {
143
- return {
144
- // Register debug tools
145
- tool: {
146
- debug_start: debugStart,
147
- debug_stop: debugStop,
148
- debug_read: debugRead,
149
- debug_clear: debugClear,
150
- debug_status: debugStatus,
151
- },
152
-
153
- // Config hook to inject agent and skills
154
- async config(config) {
155
- // Inject debug agent
156
- config.agent = config.agent ?? {};
157
- config.agent['debug'] = {
158
- description: 'Runtime debugging - capture and analyze execution data',
159
- mode: 'primary',
160
- prompt: AGENT_PROMPT,
161
- };
162
-
163
- // Inject skills (using type assertion as skill may not be in Config type yet)
164
- const configWithSkill = config as typeof config & {
165
- skill?: Record<string, { name: string; description: string; content: string }>;
166
- };
167
- configWithSkill.skill = configWithSkill.skill ?? {};
168
- configWithSkill.skill[DEBUG_SKILL.name] = DEBUG_SKILL;
169
- },
170
- };
171
- };
172
-
173
- // Default export for compatibility
174
- export default DebugAgentPlugin;
package/src/server.ts DELETED
@@ -1,267 +0,0 @@
1
- /**
2
- * Debug Server - Hono-based HTTP server for capturing runtime debug data
3
- *
4
- * Features:
5
- * - CORS enabled for browser instrumentation
6
- * - Port persistence across sessions
7
- * - NDJSON log format
8
- * - Auto-flush with configurable interval
9
- */
10
-
11
- import { Hono } from 'hono';
12
- import { cors } from 'hono/cors';
13
- import { mkdir } from 'node:fs/promises';
14
- import { dirname } from 'node:path';
15
-
16
- interface LogEntry {
17
- timestamp: string;
18
- label: string;
19
- data: unknown;
20
- }
21
-
22
- interface StartResult {
23
- port: number;
24
- url: string;
25
- }
26
-
27
- interface ServerInfo {
28
- active: boolean;
29
- port?: number;
30
- url?: string;
31
- }
32
-
33
- class DebugServer {
34
- private server: ReturnType<typeof Bun.serve> | null = null;
35
- private writer: ReturnType<(typeof Bun.file)['prototype']['writer']> | null = null;
36
- private flushInterval: ReturnType<typeof setInterval> | null = null;
37
-
38
- private portFile = '.opencode/debug.port';
39
- private logFile = '.opencode/debug.log';
40
-
41
- /**
42
- * Start the debug server
43
- * Port priority: 1) User-specified → 2) Persisted port → 3) Auto-select
44
- */
45
- async start(port?: number): Promise<StartResult> {
46
- // If already running, return existing info
47
- if (this.server) {
48
- const existingPort = this.server.port ?? 0;
49
- return {
50
- port: existingPort,
51
- url: `http://localhost:${existingPort}`,
52
- };
53
- }
54
-
55
- // Determine target port
56
- const targetPort = port ?? (await this.loadPersistedPort()) ?? 0;
57
-
58
- // Create Hono app
59
- const app = new Hono();
60
-
61
- // Enable CORS for browser instrumentation
62
- app.use(
63
- '/*',
64
- cors({
65
- origin: '*',
66
- allowMethods: ['POST', 'GET', 'OPTIONS'],
67
- allowHeaders: ['Content-Type'],
68
- })
69
- );
70
-
71
- // POST /log - receive debug data
72
- app.post('/log', async (c) => {
73
- try {
74
- const body = await c.req.json();
75
- const entry: LogEntry = {
76
- timestamp: new Date().toISOString(),
77
- label: body.label ?? 'unknown',
78
- data: body.data ?? body,
79
- };
80
- await this.appendLog(entry);
81
- return c.json({ success: true });
82
- } catch (error) {
83
- return c.json({ error: 'Invalid JSON' }, 400);
84
- }
85
- });
86
-
87
- // GET /health - health check
88
- app.get('/health', (c) => c.text('OK'));
89
-
90
- // Ensure .opencode directory exists
91
- await mkdir(dirname(this.logFile), { recursive: true });
92
-
93
- // Initialize log file writer
94
- const file = Bun.file(this.logFile);
95
- this.writer = file.writer({ highWaterMark: 1024 * 8 });
96
-
97
- // Start server
98
- this.server = Bun.serve({
99
- fetch: app.fetch,
100
- port: targetPort,
101
- });
102
-
103
- // Get the actual port (Bun may have assigned one if we requested 0)
104
- const actualPort = this.server.port ?? 0;
105
-
106
- // Persist the port for future sessions
107
- await this.persistPort(actualPort);
108
-
109
- // Auto-flush every 5 seconds
110
- this.flushInterval = setInterval(() => {
111
- this.writer?.flush();
112
- }, 5000);
113
-
114
- return {
115
- port: actualPort,
116
- url: `http://localhost:${actualPort}`,
117
- };
118
- }
119
-
120
- /**
121
- * Stop the debug server
122
- */
123
- async stop(): Promise<void> {
124
- if (this.flushInterval) {
125
- clearInterval(this.flushInterval);
126
- this.flushInterval = null;
127
- }
128
-
129
- if (this.writer) {
130
- await this.writer.flush();
131
- await this.writer.end();
132
- this.writer = null;
133
- }
134
-
135
- if (this.server) {
136
- this.server.stop();
137
- this.server = null;
138
- }
139
- }
140
-
141
- /**
142
- * Check if server is running
143
- */
144
- isRunning(): boolean {
145
- return this.server !== null;
146
- }
147
-
148
- /**
149
- * Get current server info
150
- */
151
- getInfo(): ServerInfo {
152
- if (!this.server) {
153
- return { active: false };
154
- }
155
- return {
156
- active: true,
157
- port: this.server.port,
158
- url: `http://localhost:${this.server.port}`,
159
- };
160
- }
161
-
162
- /**
163
- * Get persisted port (for when server is not running)
164
- */
165
- async getPersistedPort(): Promise<number | null> {
166
- return this.loadPersistedPort();
167
- }
168
-
169
- /**
170
- * Read log entries
171
- */
172
- async readLogs(tail?: number): Promise<LogEntry[]> {
173
- try {
174
- // Flush before reading to ensure all data is written
175
- await this.writer?.flush();
176
-
177
- const file = Bun.file(this.logFile);
178
- if (!(await file.exists())) {
179
- return [];
180
- }
181
-
182
- const content = await file.text();
183
- const lines = content.trim().split('\n').filter(Boolean);
184
-
185
- const entries: LogEntry[] = [];
186
- for (const line of lines) {
187
- try {
188
- entries.push(JSON.parse(line));
189
- } catch {
190
- // Skip malformed lines
191
- }
192
- }
193
-
194
- if (tail && tail > 0) {
195
- return entries.slice(-tail);
196
- }
197
-
198
- return entries;
199
- } catch {
200
- return [];
201
- }
202
- }
203
-
204
- /**
205
- * Clear log file
206
- */
207
- async clearLogs(): Promise<void> {
208
- // Stop current writer if exists
209
- if (this.writer) {
210
- await this.writer.flush();
211
- await this.writer.end();
212
- }
213
-
214
- // Truncate the file
215
- await Bun.write(this.logFile, '');
216
-
217
- // Restart writer if server is running
218
- if (this.server) {
219
- const file = Bun.file(this.logFile);
220
- this.writer = file.writer({ highWaterMark: 1024 * 8 });
221
- }
222
- }
223
-
224
- /**
225
- * Append a log entry
226
- */
227
- private async appendLog(entry: LogEntry): Promise<void> {
228
- if (!this.writer) {
229
- // Server not running, append directly to file
230
- await mkdir(dirname(this.logFile), { recursive: true });
231
- const file = Bun.file(this.logFile);
232
- const existing = (await file.exists()) ? await file.text() : '';
233
- await Bun.write(this.logFile, existing + JSON.stringify(entry) + '\n');
234
- return;
235
- }
236
-
237
- this.writer.write(JSON.stringify(entry) + '\n');
238
- }
239
-
240
- /**
241
- * Load persisted port from file
242
- */
243
- private async loadPersistedPort(): Promise<number | null> {
244
- try {
245
- const file = Bun.file(this.portFile);
246
- if (!(await file.exists())) {
247
- return null;
248
- }
249
- const content = await file.text();
250
- const port = parseInt(content.trim(), 10);
251
- return isNaN(port) ? null : port;
252
- } catch {
253
- return null;
254
- }
255
- }
256
-
257
- /**
258
- * Persist port to file
259
- */
260
- private async persistPort(port: number): Promise<void> {
261
- await mkdir(dirname(this.portFile), { recursive: true });
262
- await Bun.write(this.portFile, String(port));
263
- }
264
- }
265
-
266
- // Singleton instance
267
- export const debugServer = new DebugServer();
@@ -1,60 +0,0 @@
1
- ---
2
- name: debug
3
- description: Runtime debugging - start a debug server, instrument code with fetch() calls, capture and analyze execution data
4
- ---
5
-
6
- ## CRITICAL: Port Handling
7
- - `debug_start` returns a `snippet` with the correct port - ALWAYS use it
8
- - Never hardcode ports in fetch() calls
9
- - Call `debug_status` to get current port if needed later
10
- - Server persists port to `.opencode/debug.port` so existing instrumentations keep working
11
-
12
- ## Workflow
13
-
14
- 1. `debug_start` - Returns {port, url, snippet}
15
- 2. Insert the returned `snippet` at strategic code locations:
16
- - Replace `LABEL_HERE` with descriptive label (e.g., "before-api", "after-parse")
17
- - Replace `YOUR_DATA` with variables to capture (e.g., `{userId, response}`)
18
- 3. Ask user to reproduce the issue
19
- 4. `debug_read` - Analyze captured logs (returns parsed JSON array)
20
- 5. `debug_stop` - Stop server when done
21
- 6. Remove all fetch() instrumentation calls from the code
22
-
23
- ## Before Starting - Check for Existing Instrumentations
24
- 1. Call `debug_status` - check if server already running or port persisted
25
- 2. Use grep to search for `localhost:\d+/log` patterns in codebase
26
- 3. If found, ensure server starts on same port to avoid breaking existing code
27
-
28
- ## Tools Reference
29
-
30
- | Tool | Args | Returns |
31
- |------|------|---------|
32
- | `debug_start` | `port?` | `{port, url, snippet, message}` |
33
- | `debug_stop` | - | confirmation message |
34
- | `debug_read` | `tail?` | `{entries: [{timestamp, label, data}, ...], count}` |
35
- | `debug_clear` | - | confirmation message |
36
- | `debug_status` | - | `{active, port?, url?, persistedPort?, hint?}` |
37
-
38
- ## Example Session
39
-
40
- ```
41
- > debug_start
42
- {port: 54321, url: "http://localhost:54321", snippet: "fetch(...)"}
43
-
44
- > [Insert snippet at line 42 and 67 in user's code]
45
-
46
- > [User reproduces the issue]
47
-
48
- > debug_read
49
- {entries: [
50
- {timestamp: "...", label: "before-api", data: {userId: 123}},
51
- {timestamp: "...", label: "after-api", data: {error: "timeout"}}
52
- ], count: 2}
53
-
54
- > [Analyze: API call is timing out]
55
-
56
- > debug_stop
57
- {message: "Debug server stopped."}
58
-
59
- > [Remove instrumentation from lines 42 and 67]
60
- ```
package/src/tools.ts DELETED
@@ -1,131 +0,0 @@
1
- /**
2
- * Debug Tools - OpenCode tools for runtime debugging workflow
3
- */
4
-
5
- import { tool } from '@opencode-ai/plugin';
6
- import { debugServer } from './server';
7
-
8
- /**
9
- * Generate the instrumentation snippet with the given URL
10
- */
11
- function generateSnippet(url: string): string {
12
- return `fetch("${url}/log", {
13
- method: "POST",
14
- headers: {"Content-Type": "application/json"},
15
- body: JSON.stringify({label: "LABEL_HERE", data: {YOUR_DATA}})
16
- })`;
17
- }
18
-
19
- /**
20
- * Start debug server to capture runtime data
21
- * Returns port, URL, and ready-to-use code snippet
22
- */
23
- export const debugStart = tool({
24
- description:
25
- 'Start debug server to capture runtime data. Returns port, URL, and ready-to-use code snippet for instrumentation.',
26
- args: {
27
- port: tool.schema
28
- .number()
29
- .optional()
30
- .describe(
31
- 'Specific port to use (optional). If not provided, reuses previous port or auto-selects.'
32
- ),
33
- },
34
- async execute(args) {
35
- const result = await debugServer.start(args.port);
36
- return JSON.stringify({
37
- port: result.port,
38
- url: result.url,
39
- snippet: generateSnippet(result.url),
40
- message: `Debug server running on port ${result.port}. Use the snippet to instrument code.`,
41
- });
42
- },
43
- });
44
-
45
- /**
46
- * Stop the debug server and flush remaining logs
47
- */
48
- export const debugStop = tool({
49
- description: 'Stop the debug server and flush remaining logs to disk.',
50
- args: {},
51
- async execute() {
52
- if (!debugServer.isRunning()) {
53
- return JSON.stringify({ message: 'Debug server is not running.' });
54
- }
55
- await debugServer.stop();
56
- return JSON.stringify({
57
- message: 'Debug server stopped. Logs preserved in .opencode/debug.log',
58
- });
59
- },
60
- });
61
-
62
- /**
63
- * Read captured debug logs
64
- */
65
- export const debugRead = tool({
66
- description: 'Read captured debug logs. Returns parsed JSON array of log entries.',
67
- args: {
68
- tail: tool.schema
69
- .number()
70
- .optional()
71
- .describe('Return only the last N entries. If not provided, returns all entries.'),
72
- },
73
- async execute(args) {
74
- const entries = await debugServer.readLogs(args.tail);
75
- if (entries.length === 0) {
76
- return JSON.stringify({
77
- entries: [],
78
- message:
79
- 'No log entries found. Make sure the debug server is running and code is instrumented.',
80
- });
81
- }
82
- return JSON.stringify({
83
- entries,
84
- count: entries.length,
85
- });
86
- },
87
- });
88
-
89
- /**
90
- * Clear the debug log file
91
- */
92
- export const debugClear = tool({
93
- description: 'Clear the debug log file.',
94
- args: {},
95
- async execute() {
96
- await debugServer.clearLogs();
97
- return JSON.stringify({ message: 'Debug log cleared.' });
98
- },
99
- });
100
-
101
- /**
102
- * Check debug server status and get current port/URL
103
- */
104
- export const debugStatus = tool({
105
- description:
106
- 'Check if debug server is running and get current port/URL. Also shows persisted port from previous sessions.',
107
- args: {},
108
- async execute() {
109
- const info = debugServer.getInfo();
110
-
111
- if (info.active && info.url) {
112
- return JSON.stringify({
113
- active: true,
114
- port: info.port,
115
- url: info.url,
116
- snippet: generateSnippet(info.url),
117
- });
118
- }
119
-
120
- // Server not running - check for persisted port
121
- const persistedPort = await debugServer.getPersistedPort();
122
-
123
- return JSON.stringify({
124
- active: false,
125
- persistedPort,
126
- hint: persistedPort
127
- ? `Previous session used port ${persistedPort}. Call debug_start to reuse it.`
128
- : 'No debug server configured. Call debug_start to begin.',
129
- });
130
- },
131
- });