@opencode-trace/plugin 0.0.3
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/README.md +124 -0
- package/dist/integration.test.d.ts +2 -0
- package/dist/integration.test.d.ts.map +1 -0
- package/dist/integration.test.js +76 -0
- package/dist/integration.test.js.map +1 -0
- package/dist/plugin-instance.d.ts +29 -0
- package/dist/plugin-instance.d.ts.map +1 -0
- package/dist/plugin-instance.js +219 -0
- package/dist/plugin-instance.js.map +1 -0
- package/dist/plugin-instance.test.d.ts +2 -0
- package/dist/plugin-instance.test.d.ts.map +1 -0
- package/dist/plugin-instance.test.js +135 -0
- package/dist/plugin-instance.test.js.map +1 -0
- package/dist/redact.d.ts +2 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +40 -0
- package/dist/redact.js.map +1 -0
- package/dist/redact.test.d.ts +2 -0
- package/dist/redact.test.d.ts.map +1 -0
- package/dist/redact.test.js +77 -0
- package/dist/redact.test.js.map +1 -0
- package/dist/state-queue.d.ts +14 -0
- package/dist/state-queue.d.ts.map +1 -0
- package/dist/state-queue.js +44 -0
- package/dist/state-queue.js.map +1 -0
- package/dist/state-queue.test.d.ts +2 -0
- package/dist/state-queue.test.d.ts.map +1 -0
- package/dist/state-queue.test.js +99 -0
- package/dist/state-queue.test.js.map +1 -0
- package/dist/trace.d.ts +32 -0
- package/dist/trace.d.ts.map +1 -0
- package/dist/trace.js +100 -0
- package/dist/trace.js.map +1 -0
- package/dist/trace.test.d.ts +2 -0
- package/dist/trace.test.d.ts.map +1 -0
- package/dist/trace.test.js +359 -0
- package/dist/trace.test.js.map +1 -0
- package/dist/write-queue.d.ts +14 -0
- package/dist/write-queue.d.ts.map +1 -0
- package/dist/write-queue.js +62 -0
- package/dist/write-queue.js.map +1 -0
- package/dist/write-queue.test.d.ts +2 -0
- package/dist/write-queue.test.d.ts.map +1 -0
- package/dist/write-queue.test.js +92 -0
- package/dist/write-queue.test.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import { describe, test, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync, existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import entrypoint, { _resetForTesting } from "./trace.js";
|
|
6
|
+
async function waitForFile(filePath, timeoutMs = 5000) {
|
|
7
|
+
const startTime = Date.now();
|
|
8
|
+
while (true) {
|
|
9
|
+
if (existsSync(filePath)) {
|
|
10
|
+
try {
|
|
11
|
+
const content = readFileSync(filePath, "utf-8");
|
|
12
|
+
if (content && content.length > 0) {
|
|
13
|
+
JSON.parse(content);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (Date.now() - startTime > timeoutMs) {
|
|
21
|
+
throw new Error(`Timeout waiting for valid file ${filePath} after ${timeoutMs}ms`);
|
|
22
|
+
}
|
|
23
|
+
await new Promise(r => setTimeout(r, 10));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
let testDir;
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
testDir = mkdtempSync(join(tmpdir(), "plugin-test-"));
|
|
29
|
+
vi.stubEnv("HOME", testDir);
|
|
30
|
+
});
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
33
|
+
vi.unstubAllEnvs();
|
|
34
|
+
});
|
|
35
|
+
describe("Plugin - Hooks 返回值", () => {
|
|
36
|
+
test("plugin 返回包含 event hook", async () => {
|
|
37
|
+
const hooks = await entrypoint.server({
|
|
38
|
+
client: {},
|
|
39
|
+
project: {},
|
|
40
|
+
directory: testDir,
|
|
41
|
+
worktree: testDir,
|
|
42
|
+
experimental_workspace: { register: vi.fn() },
|
|
43
|
+
serverUrl: new URL("http://localhost"),
|
|
44
|
+
$: {},
|
|
45
|
+
});
|
|
46
|
+
expect(hooks.event).toBeDefined();
|
|
47
|
+
});
|
|
48
|
+
test("plugin 返回包含 tool.execute.after hook", async () => {
|
|
49
|
+
const hooks = await entrypoint.server({
|
|
50
|
+
client: {},
|
|
51
|
+
project: {},
|
|
52
|
+
directory: testDir,
|
|
53
|
+
worktree: testDir,
|
|
54
|
+
experimental_workspace: { register: vi.fn() },
|
|
55
|
+
serverUrl: new URL("http://localhost"),
|
|
56
|
+
$: {},
|
|
57
|
+
});
|
|
58
|
+
expect(hooks["tool.execute.after"]).toBeDefined();
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe("Plugin - event hook 处理 session.created", () => {
|
|
62
|
+
test("event hook 处理 session.created 更新元数据", async () => {
|
|
63
|
+
const hooks = await entrypoint.server({
|
|
64
|
+
client: {},
|
|
65
|
+
project: {},
|
|
66
|
+
directory: testDir,
|
|
67
|
+
worktree: testDir,
|
|
68
|
+
experimental_workspace: { register: vi.fn() },
|
|
69
|
+
serverUrl: new URL("http://localhost"),
|
|
70
|
+
$: {},
|
|
71
|
+
});
|
|
72
|
+
const sessionId = "test-session-123";
|
|
73
|
+
await hooks.event({
|
|
74
|
+
event: {
|
|
75
|
+
type: "session.created",
|
|
76
|
+
properties: {
|
|
77
|
+
info: {
|
|
78
|
+
id: sessionId,
|
|
79
|
+
projectID: "test-project",
|
|
80
|
+
directory: testDir,
|
|
81
|
+
title: "Test Session Title",
|
|
82
|
+
version: "1.0",
|
|
83
|
+
time: { created: Date.now(), updated: Date.now() },
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
const traceDir = join(testDir, ".opencode-trace");
|
|
89
|
+
const sessionDir = join(traceDir, sessionId);
|
|
90
|
+
expect(existsSync(sessionDir)).toBe(true);
|
|
91
|
+
const dbPath = join(traceDir, "state.db");
|
|
92
|
+
expect(existsSync(dbPath)).toBe(true);
|
|
93
|
+
const metaPath = join(sessionDir, "metadata.json");
|
|
94
|
+
expect(existsSync(metaPath)).toBe(true);
|
|
95
|
+
const meta = JSON.parse(readFileSync(metaPath, "utf-8"));
|
|
96
|
+
expect(meta.folderPath).toBe(testDir);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
describe("Stream request detection", () => {
|
|
100
|
+
test("should detect stream request from body", () => {
|
|
101
|
+
const init = {
|
|
102
|
+
body: JSON.stringify({ stream: true, messages: [] }),
|
|
103
|
+
};
|
|
104
|
+
const isStream = JSON.parse(init.body ?? "{}").stream === true;
|
|
105
|
+
expect(isStream).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
test("should detect non-stream request", () => {
|
|
108
|
+
const init = {
|
|
109
|
+
body: JSON.stringify({ stream: false, messages: [] }),
|
|
110
|
+
};
|
|
111
|
+
const isStream = JSON.parse(init.body ?? "{}").stream === true;
|
|
112
|
+
expect(isStream).toBe(false);
|
|
113
|
+
});
|
|
114
|
+
test("should handle missing stream field", () => {
|
|
115
|
+
const init = {
|
|
116
|
+
body: JSON.stringify({ messages: [] }),
|
|
117
|
+
};
|
|
118
|
+
const isStream = JSON.parse(init.body ?? "{}").stream === true;
|
|
119
|
+
expect(isStream).toBe(false);
|
|
120
|
+
});
|
|
121
|
+
test("should handle invalid JSON body", () => {
|
|
122
|
+
const init = {
|
|
123
|
+
body: "not valid json",
|
|
124
|
+
};
|
|
125
|
+
let isStream = false;
|
|
126
|
+
try {
|
|
127
|
+
isStream = JSON.parse(init.body ?? "{}")?.stream === true;
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
isStream = false;
|
|
131
|
+
}
|
|
132
|
+
expect(isStream).toBe(false);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
describe("Latency metadata in TraceRecord", () => {
|
|
136
|
+
test("TraceRecord interface should have latency fields", () => {
|
|
137
|
+
const record = {
|
|
138
|
+
requestSentAt: 1234567.89,
|
|
139
|
+
firstTokenAt: 1234570.12,
|
|
140
|
+
lastTokenAt: 1234590.34,
|
|
141
|
+
};
|
|
142
|
+
expect(record.requestSentAt).toBe(1234567.89);
|
|
143
|
+
expect(record.firstTokenAt).toBe(1234570.12);
|
|
144
|
+
expect(record.lastTokenAt).toBe(1234590.34);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
describe("tracedFetch stream integration", () => {
|
|
148
|
+
test("should apply TransformStream wrapper and record latency metadata", async () => {
|
|
149
|
+
_resetForTesting();
|
|
150
|
+
const mockFetch = vi.fn();
|
|
151
|
+
const originalFetch = globalThis.fetch;
|
|
152
|
+
globalThis.fetch = mockFetch;
|
|
153
|
+
const chunks = ["data: {\"content\": \"Hello\"}\n", "data: {\"content\": \"World\"}\n", "data: [DONE]\n"];
|
|
154
|
+
const encoder = new TextEncoder();
|
|
155
|
+
const streamChunks = chunks.map(c => encoder.encode(c));
|
|
156
|
+
const mockStream = new ReadableStream({
|
|
157
|
+
start(controller) {
|
|
158
|
+
for (const chunk of streamChunks) {
|
|
159
|
+
controller.enqueue(chunk);
|
|
160
|
+
}
|
|
161
|
+
controller.close();
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
mockFetch.mockResolvedValueOnce(new Response(mockStream, {
|
|
165
|
+
status: 200,
|
|
166
|
+
headers: { "content-type": "text/event-stream" },
|
|
167
|
+
}));
|
|
168
|
+
const hooks = await entrypoint.server({
|
|
169
|
+
client: {},
|
|
170
|
+
project: {},
|
|
171
|
+
directory: testDir,
|
|
172
|
+
worktree: testDir,
|
|
173
|
+
experimental_workspace: { register: vi.fn() },
|
|
174
|
+
serverUrl: new URL("http://localhost"),
|
|
175
|
+
$: {},
|
|
176
|
+
});
|
|
177
|
+
const sessionId = "stream-test-session";
|
|
178
|
+
await hooks.event({
|
|
179
|
+
event: {
|
|
180
|
+
type: "session.created",
|
|
181
|
+
properties: {
|
|
182
|
+
info: {
|
|
183
|
+
id: sessionId,
|
|
184
|
+
projectID: "test-project",
|
|
185
|
+
directory: testDir,
|
|
186
|
+
title: "Stream Test Session",
|
|
187
|
+
version: "1.0",
|
|
188
|
+
time: { created: Date.now(), updated: Date.now() },
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
const streamRequest = new Request("https://api.example.com/v1/chat/completions", {
|
|
194
|
+
method: "POST",
|
|
195
|
+
headers: {
|
|
196
|
+
"content-type": "application/json",
|
|
197
|
+
"x-opencode-session": sessionId,
|
|
198
|
+
},
|
|
199
|
+
body: JSON.stringify({ stream: true, messages: [{ role: "user", content: "test" }] }),
|
|
200
|
+
});
|
|
201
|
+
const response = await globalThis.fetch(streamRequest);
|
|
202
|
+
expect(response.__latencyMeta).toBeDefined();
|
|
203
|
+
expect(response.__latencyMeta.requestSentAt).toBeDefined();
|
|
204
|
+
expect(response.__latencyMeta.firstTokenAt).toBeNull();
|
|
205
|
+
expect(response.__latencyMeta.lastTokenAt).toBeNull();
|
|
206
|
+
const reader = response.body.getReader();
|
|
207
|
+
const receivedChunks = [];
|
|
208
|
+
while (true) {
|
|
209
|
+
const { done, value } = await reader.read();
|
|
210
|
+
if (done)
|
|
211
|
+
break;
|
|
212
|
+
receivedChunks.push(value);
|
|
213
|
+
}
|
|
214
|
+
expect(receivedChunks.length).toBe(3);
|
|
215
|
+
expect(response.__latencyMeta.firstTokenAt).not.toBeNull();
|
|
216
|
+
expect(response.__latencyMeta.lastTokenAt).not.toBeNull();
|
|
217
|
+
const traceDir = join(testDir, ".opencode-trace");
|
|
218
|
+
const sessionDir = join(traceDir, sessionId);
|
|
219
|
+
const recordFile = join(sessionDir, "1.json");
|
|
220
|
+
await waitForFile(recordFile, 5000);
|
|
221
|
+
if (existsSync(recordFile)) {
|
|
222
|
+
const record = JSON.parse(readFileSync(recordFile, "utf-8"));
|
|
223
|
+
expect(record.requestSentAt).toBeDefined();
|
|
224
|
+
expect(record.firstTokenAt).toBeDefined();
|
|
225
|
+
expect(record.lastTokenAt).toBeDefined();
|
|
226
|
+
}
|
|
227
|
+
globalThis.fetch = originalFetch;
|
|
228
|
+
});
|
|
229
|
+
test("should not wrap non-stream responses", async () => {
|
|
230
|
+
_resetForTesting();
|
|
231
|
+
const mockFetch = vi.fn();
|
|
232
|
+
const originalFetch = globalThis.fetch;
|
|
233
|
+
globalThis.fetch = mockFetch;
|
|
234
|
+
mockFetch.mockResolvedValueOnce(new Response(JSON.stringify({ result: "ok" }), {
|
|
235
|
+
status: 200,
|
|
236
|
+
headers: { "content-type": "application/json" },
|
|
237
|
+
}));
|
|
238
|
+
const hooks = await entrypoint.server({
|
|
239
|
+
client: {},
|
|
240
|
+
project: {},
|
|
241
|
+
directory: testDir,
|
|
242
|
+
worktree: testDir,
|
|
243
|
+
experimental_workspace: { register: vi.fn() },
|
|
244
|
+
serverUrl: new URL("http://localhost"),
|
|
245
|
+
$: {},
|
|
246
|
+
});
|
|
247
|
+
const sessionId = "non-stream-test-session";
|
|
248
|
+
await hooks.event({
|
|
249
|
+
event: {
|
|
250
|
+
type: "session.created",
|
|
251
|
+
properties: {
|
|
252
|
+
info: {
|
|
253
|
+
id: sessionId,
|
|
254
|
+
projectID: "test-project",
|
|
255
|
+
directory: testDir,
|
|
256
|
+
title: "Non-Stream Test",
|
|
257
|
+
version: "1.0",
|
|
258
|
+
time: { created: Date.now(), updated: Date.now() },
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
const request = new Request("https://api.example.com/v1/chat/completions", {
|
|
264
|
+
method: "POST",
|
|
265
|
+
headers: {
|
|
266
|
+
"content-type": "application/json",
|
|
267
|
+
"x-opencode-session": sessionId,
|
|
268
|
+
},
|
|
269
|
+
body: JSON.stringify({ stream: false, messages: [{ role: "user", content: "test" }] }),
|
|
270
|
+
});
|
|
271
|
+
const response = await globalThis.fetch(request);
|
|
272
|
+
expect(response.__latencyMeta).toBeUndefined();
|
|
273
|
+
globalThis.fetch = originalFetch;
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
describe("Plugin - tool.execute.after hook 处理 Task 工具", () => {
|
|
277
|
+
test("tool.execute.after hook 处理 Task 工具记录 sub session", async () => {
|
|
278
|
+
const hooks = await entrypoint.server({
|
|
279
|
+
client: {},
|
|
280
|
+
project: {},
|
|
281
|
+
directory: testDir,
|
|
282
|
+
worktree: testDir,
|
|
283
|
+
experimental_workspace: { register: vi.fn() },
|
|
284
|
+
serverUrl: new URL("http://localhost"),
|
|
285
|
+
$: {},
|
|
286
|
+
});
|
|
287
|
+
const parentSessionId = "parent-session-123";
|
|
288
|
+
const subSessionId = "sub-session-456";
|
|
289
|
+
await hooks.event({
|
|
290
|
+
event: {
|
|
291
|
+
type: "session.created",
|
|
292
|
+
properties: {
|
|
293
|
+
info: {
|
|
294
|
+
id: parentSessionId,
|
|
295
|
+
projectID: "test-project",
|
|
296
|
+
directory: testDir,
|
|
297
|
+
title: "Parent Session",
|
|
298
|
+
version: "1.0",
|
|
299
|
+
time: { created: Date.now(), updated: Date.now() },
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
await hooks["tool.execute.after"]({
|
|
305
|
+
tool: "task",
|
|
306
|
+
sessionID: parentSessionId,
|
|
307
|
+
callID: "call-123",
|
|
308
|
+
args: { description: "test", prompt: "test" },
|
|
309
|
+
}, {
|
|
310
|
+
title: "Task completed",
|
|
311
|
+
output: "success",
|
|
312
|
+
metadata: { session_id: subSessionId },
|
|
313
|
+
});
|
|
314
|
+
const traceDir = join(testDir, ".opencode-trace");
|
|
315
|
+
const dbPath = join(traceDir, "state.db");
|
|
316
|
+
expect(existsSync(dbPath)).toBe(true);
|
|
317
|
+
});
|
|
318
|
+
test("tool.execute.after hook 对非 Task 工具不记录 sub session", async () => {
|
|
319
|
+
const hooks = await entrypoint.server({
|
|
320
|
+
client: {},
|
|
321
|
+
project: {},
|
|
322
|
+
directory: testDir,
|
|
323
|
+
worktree: testDir,
|
|
324
|
+
experimental_workspace: { register: vi.fn() },
|
|
325
|
+
serverUrl: new URL("http://localhost"),
|
|
326
|
+
$: {},
|
|
327
|
+
});
|
|
328
|
+
const sessionId = "test-session-123";
|
|
329
|
+
await hooks.event({
|
|
330
|
+
event: {
|
|
331
|
+
type: "session.created",
|
|
332
|
+
properties: {
|
|
333
|
+
info: {
|
|
334
|
+
id: sessionId,
|
|
335
|
+
projectID: "test-project",
|
|
336
|
+
directory: testDir,
|
|
337
|
+
title: "Test Session",
|
|
338
|
+
version: "1.0",
|
|
339
|
+
time: { created: Date.now(), updated: Date.now() },
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
await hooks["tool.execute.after"]({
|
|
345
|
+
tool: "bash",
|
|
346
|
+
sessionID: sessionId,
|
|
347
|
+
callID: "call-123",
|
|
348
|
+
args: { command: "ls" },
|
|
349
|
+
}, {
|
|
350
|
+
title: "Command executed",
|
|
351
|
+
output: "file1.txt\nfile2.txt",
|
|
352
|
+
metadata: {},
|
|
353
|
+
});
|
|
354
|
+
const traceDir = join(testDir, ".opencode-trace");
|
|
355
|
+
const dbPath = join(traceDir, "state.db");
|
|
356
|
+
expect(existsSync(dbPath)).toBe(true);
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
//# sourceMappingURL=trace.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace.test.js","sourceRoot":"","sources":["../src/trace.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TraceRecord } from "./trace.js";
|
|
2
|
+
export declare class AsyncWriteQueue {
|
|
3
|
+
private queue;
|
|
4
|
+
private writing;
|
|
5
|
+
private traceDir;
|
|
6
|
+
private batchSize;
|
|
7
|
+
constructor(traceDir: string, batchSize?: number);
|
|
8
|
+
enqueue(session: string, seq: number, record: TraceRecord): void;
|
|
9
|
+
private processQueue;
|
|
10
|
+
flush(): Promise<void>;
|
|
11
|
+
private writeBatch;
|
|
12
|
+
private writeFallback;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=write-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-queue.d.ts","sourceRoot":"","sources":["../src/write-queue.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAoE;IACjF,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;gBAEd,QAAQ,EAAE,MAAM,EAAE,SAAS,GAAE,MAAW;IAKpD,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI;YAOlD,YAAY;IAapB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAMd,UAAU;YAYV,aAAa;CAiB5B"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { logger } from "@opencode-trace/core";
|
|
4
|
+
export class AsyncWriteQueue {
|
|
5
|
+
queue = [];
|
|
6
|
+
writing = false;
|
|
7
|
+
traceDir;
|
|
8
|
+
batchSize;
|
|
9
|
+
constructor(traceDir, batchSize = 10) {
|
|
10
|
+
this.traceDir = traceDir;
|
|
11
|
+
this.batchSize = batchSize;
|
|
12
|
+
}
|
|
13
|
+
enqueue(session, seq, record) {
|
|
14
|
+
this.queue.push({ session, seq, record });
|
|
15
|
+
if (!this.writing) {
|
|
16
|
+
this.processQueue();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async processQueue() {
|
|
20
|
+
this.writing = true;
|
|
21
|
+
while (this.queue.length > 0) {
|
|
22
|
+
const batch = this.queue.splice(0, this.batchSize);
|
|
23
|
+
await this.writeBatch(batch);
|
|
24
|
+
}
|
|
25
|
+
this.writing = false;
|
|
26
|
+
if (this.queue.length > 0 && !this.writing) {
|
|
27
|
+
this.processQueue();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async flush() {
|
|
31
|
+
while (this.writing || this.queue.length > 0) {
|
|
32
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async writeBatch(items) {
|
|
36
|
+
for (const { session, seq, record } of items) {
|
|
37
|
+
try {
|
|
38
|
+
const sessionDir = join(this.traceDir, session);
|
|
39
|
+
await fs.mkdir(sessionDir, { recursive: true });
|
|
40
|
+
await fs.writeFile(join(sessionDir, `${seq}.json`), JSON.stringify(record, null, 2));
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
await this.writeFallback(session, seq, record, err);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async writeFallback(session, seq, record, err) {
|
|
48
|
+
const fallbackDir = join(this.traceDir, "fallback");
|
|
49
|
+
await fs.mkdir(fallbackDir, { recursive: true });
|
|
50
|
+
const filename = `${session}-${seq}-${Date.now()}.json`;
|
|
51
|
+
await fs.writeFile(join(fallbackDir, filename), JSON.stringify({
|
|
52
|
+
record,
|
|
53
|
+
error: {
|
|
54
|
+
name: err.name,
|
|
55
|
+
message: err.message,
|
|
56
|
+
stack: err.stack
|
|
57
|
+
}
|
|
58
|
+
}, null, 2));
|
|
59
|
+
logger.error("Write failed, saved to fallback", { filename, error: err.message });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=write-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-queue.js","sourceRoot":"","sources":["../src/write-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-queue.test.d.ts","sourceRoot":"","sources":["../src/write-queue.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { AsyncWriteQueue } from "./write-queue.js";
|
|
3
|
+
import { mkdtempSync, rmSync, existsSync, readFileSync, promises as fs } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
describe("AsyncWriteQueue", () => {
|
|
7
|
+
let tempDir;
|
|
8
|
+
let queue;
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
tempDir = mkdtempSync(join(tmpdir(), "write-queue-test-"));
|
|
11
|
+
queue = new AsyncWriteQueue(tempDir);
|
|
12
|
+
});
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
15
|
+
});
|
|
16
|
+
test("enqueue writes JSON file to session directory", async () => {
|
|
17
|
+
const record = {
|
|
18
|
+
id: 1,
|
|
19
|
+
purpose: "test",
|
|
20
|
+
requestAt: "2026-05-07T00:00:00Z",
|
|
21
|
+
responseAt: "2026-05-07T00:00:01Z",
|
|
22
|
+
request: { method: "GET", url: "https://example.com", headers: {}, body: null },
|
|
23
|
+
response: { status: 200, statusText: "OK", headers: {}, body: null },
|
|
24
|
+
error: null,
|
|
25
|
+
};
|
|
26
|
+
queue.enqueue("session-1", 1, record);
|
|
27
|
+
await queue.flush();
|
|
28
|
+
const filePath = join(tempDir, "session-1", "1.json");
|
|
29
|
+
expect(existsSync(filePath)).toBe(true);
|
|
30
|
+
const content = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
31
|
+
expect(content).toEqual(record);
|
|
32
|
+
});
|
|
33
|
+
test("enqueue processes items in batches of 10", async () => {
|
|
34
|
+
const records = Array.from({ length: 25 }, (_, i) => ({
|
|
35
|
+
id: i + 1,
|
|
36
|
+
purpose: `test-${i}`,
|
|
37
|
+
requestAt: `2026-05-07T00:00:${i.toString().padStart(2, "0")}Z`,
|
|
38
|
+
responseAt: `2026-05-07T00:00:${(i + 1).toString().padStart(2, "0")}Z`,
|
|
39
|
+
request: { method: "GET", url: `https://example.com/${i}`, headers: {}, body: null },
|
|
40
|
+
response: { status: 200, statusText: "OK", headers: {}, body: null },
|
|
41
|
+
error: null,
|
|
42
|
+
}));
|
|
43
|
+
for (let i = 0; i < 25; i++) {
|
|
44
|
+
queue.enqueue("batch-test", i + 1, records[i]);
|
|
45
|
+
}
|
|
46
|
+
await queue.flush();
|
|
47
|
+
for (let i = 1; i <= 25; i++) {
|
|
48
|
+
const filePath = join(tempDir, "batch-test", `${i}.json`);
|
|
49
|
+
expect(existsSync(filePath)).toBe(true);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
test.skipIf(process.platform === "win32")("enqueue writes to fallback directory when primary write fails", async () => {
|
|
53
|
+
const record = {
|
|
54
|
+
id: 1,
|
|
55
|
+
purpose: "fallback-test",
|
|
56
|
+
requestAt: "2026-05-07T00:00:00Z",
|
|
57
|
+
responseAt: "2026-05-07T00:00:01Z",
|
|
58
|
+
request: { method: "GET", url: "https://example.com", headers: {}, body: null },
|
|
59
|
+
response: { status: 200, statusText: "OK", headers: {}, body: null },
|
|
60
|
+
error: null,
|
|
61
|
+
};
|
|
62
|
+
const sessionDir = join(tempDir, "readonly-session");
|
|
63
|
+
await fs.mkdir(sessionDir, { recursive: true });
|
|
64
|
+
await fs.chmod(sessionDir, 0o000);
|
|
65
|
+
queue.enqueue("readonly-session", 1, record);
|
|
66
|
+
await queue.flush();
|
|
67
|
+
await fs.chmod(sessionDir, 0o755);
|
|
68
|
+
const fallbackDir = join(tempDir, "fallback");
|
|
69
|
+
const files = await fs.readdir(fallbackDir);
|
|
70
|
+
expect(files.length).toBeGreaterThan(0);
|
|
71
|
+
});
|
|
72
|
+
test("flush waits for queue to drain", async () => {
|
|
73
|
+
const records = Array.from({ length: 15 }, (_, i) => ({
|
|
74
|
+
id: i + 1,
|
|
75
|
+
purpose: `flush-test-${i}`,
|
|
76
|
+
requestAt: "2026-05-07T00:00:00Z",
|
|
77
|
+
responseAt: "2026-05-07T00:00:01Z",
|
|
78
|
+
request: { method: "GET", url: "https://example.com", headers: {}, body: null },
|
|
79
|
+
response: { status: 200, statusText: "OK", headers: {}, body: null },
|
|
80
|
+
error: null,
|
|
81
|
+
}));
|
|
82
|
+
for (let i = 0; i < 15; i++) {
|
|
83
|
+
queue.enqueue("flush-test", i + 1, records[i]);
|
|
84
|
+
}
|
|
85
|
+
await queue.flush();
|
|
86
|
+
for (let i = 1; i <= 15; i++) {
|
|
87
|
+
const filePath = join(tempDir, "flush-test", `${i}.json`);
|
|
88
|
+
expect(existsSync(filePath)).toBe(true);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
//# sourceMappingURL=write-queue.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-queue.test.js","sourceRoot":"","sources":["../src/write-queue.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@opencode-trace/plugin",
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "OpenCode plugin for trace recording",
|
|
6
|
+
"main": "./dist/trace.js",
|
|
7
|
+
"types": "./dist/trace.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/trace.js",
|
|
11
|
+
"types": "./dist/trace.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest watch",
|
|
22
|
+
"clean": "node ../../scripts/clean.mjs"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@opencode-trace/core": "0.0.3",
|
|
26
|
+
"@opencode-ai/plugin": "^1.14.22",
|
|
27
|
+
"@opencode-ai/sdk": "^1.14.41"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"typescript": "^5.3.0",
|
|
31
|
+
"vitest": "^4.1.5"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public",
|
|
35
|
+
"registry": "https://registry.npmjs.org/"
|
|
36
|
+
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/aixmoyu/opencode-trace.git",
|
|
40
|
+
"directory": "packages/plugin"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"opencode",
|
|
44
|
+
"trace",
|
|
45
|
+
"plugin"
|
|
46
|
+
],
|
|
47
|
+
"license": "MIT"
|
|
48
|
+
}
|