@opencode-trace/plugin 0.0.4 → 0.0.5

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 CHANGED
@@ -78,13 +78,14 @@ Trace data storage structure:
78
78
 
79
79
  ```
80
80
  ~/.opencode-trace/
81
+ ├── config.json # Global state (trace_enabled, current_session)
81
82
  ├── <session-id>/ # Session directory
82
83
  │ ├── 1.json # 1st request record
83
84
  │ ├── 1.sse # SSE stream data
85
+ │ ├── 1.parsed # Parsed conversation cache
84
86
  │ ├── 2.json # 2nd request record
85
- │ ├── metadata.json # Session metadata
86
- ├── state.db # SQLite state database
87
- ```
87
+ │ ├── timeline.ndjson # Summary index (fast viewer reads)
88
+ │ └── metadata.json # Session metadata
88
89
 
89
90
  ## Tools
90
91
 
@@ -111,14 +112,6 @@ AI: [calls trace_enable tool] Tracing enabled
111
112
  2. Confirm tracing enabled: run `opencode-trace status`
112
113
  3. Check directory permissions: ensure `~/.opencode-trace` is writable
113
114
 
114
- ### SQLite Corrupted
115
-
116
- Run repair command:
117
-
118
- ```bash
119
- opencode-trace sync --repair
120
- ```
121
-
122
115
  ## License
123
116
 
124
117
  MIT
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tracer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracer.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/tracer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,276 @@
1
+ import { describe, test, expect, beforeEach, afterEach } from "vitest";
2
+ import { createTracer } from "../tracer.js";
3
+ import { TracePlugin } from "../plugin-instance.js";
4
+ import { mkdtempSync, rmSync, existsSync, readFileSync, } from "node:fs";
5
+ import { tmpdir } from "node:os";
6
+ import { join } from "node:path";
7
+ async function waitForFile(filePath, timeoutMs = 5000) {
8
+ const startTime = Date.now();
9
+ while (true) {
10
+ if (existsSync(filePath)) {
11
+ try {
12
+ const content = readFileSync(filePath, "utf-8");
13
+ if (content && content.length > 0) {
14
+ JSON.parse(content);
15
+ return;
16
+ }
17
+ }
18
+ catch { /* still being written */ }
19
+ }
20
+ if (Date.now() - startTime > timeoutMs) {
21
+ throw new Error(`Timeout waiting for valid file ${filePath} after ${timeoutMs}ms`);
22
+ }
23
+ const { promise, resolve } = Promise.withResolvers();
24
+ setTimeout(resolve, 10);
25
+ await promise;
26
+ }
27
+ }
28
+ describe("./tracer exports", () => {
29
+ test("TC-001: exports createTracer function and TracerConfig type", () => {
30
+ expect(createTracer).toBeDefined();
31
+ expect(typeof createTracer).toBe("function");
32
+ });
33
+ test("wrap(fetch) returns a wrapper function without auto-patching", () => {
34
+ const originalFetch = globalThis.fetch;
35
+ const t = createTracer({ localDir: "/tmp/test" });
36
+ const wrapper = t.wrap(originalFetch);
37
+ expect(typeof wrapper).toBe("function");
38
+ // globalThis.fetch must NOT be patched
39
+ expect(globalThis.fetch).toBe(originalFetch);
40
+ });
41
+ test("TC-003: createTracer with only localDir succeeds", () => {
42
+ const t = createTracer({ localDir: "/tmp/test-trace" });
43
+ expect(t).toBeDefined();
44
+ expect(typeof t.wrap).toBe("function");
45
+ });
46
+ test("TC-003: createTracer with custom globalDir and localDir", () => {
47
+ const t = createTracer({
48
+ globalDir: "/custom/global",
49
+ localDir: "/tmp/test-trace",
50
+ });
51
+ expect(t).toBeDefined();
52
+ expect(typeof t.wrap).toBe("function");
53
+ });
54
+ test("TC-007: createTracer without localDir throws TypeError", () => {
55
+ expect(() => createTracer({})).toThrow(/localDir/);
56
+ });
57
+ test("TC-007: error message mentions required", () => {
58
+ expect(() => createTracer({})).toThrow(/required/);
59
+ });
60
+ });
61
+ describe("Tracer interception", () => {
62
+ let tempDir;
63
+ beforeEach(() => {
64
+ tempDir = mkdtempSync(join(tmpdir(), "tracer-test-"));
65
+ });
66
+ afterEach(() => {
67
+ rmSync(tempDir, { recursive: true, force: true });
68
+ });
69
+ test("TC-004: nested monkeypatch records to both paths", async () => {
70
+ const tempDirA = mkdtempSync(join(tmpdir(), "tracer-a-"));
71
+ const tempDirB = mkdtempSync(join(tmpdir(), "tracer-b-"));
72
+ try {
73
+ const tracerA = createTracer({
74
+ globalDir: tempDirA,
75
+ localDir: tempDirA,
76
+ });
77
+ const tracerB = createTracer({
78
+ globalDir: tempDirB,
79
+ localDir: tempDirB,
80
+ });
81
+ const originalFetch = globalThis.fetch;
82
+ globalThis.fetch = async () => new Response(JSON.stringify({ ok: true }), {
83
+ status: 200,
84
+ headers: { "content-type": "application/json" },
85
+ });
86
+ try {
87
+ globalThis.fetch = tracerA.wrap(globalThis.fetch);
88
+ globalThis.fetch = tracerB.wrap(globalThis.fetch);
89
+ const response = await globalThis.fetch("https://example.com/api", {
90
+ method: "GET",
91
+ headers: { "x-opencode-session": "test-nested" },
92
+ });
93
+ expect(response.status).toBe(200);
94
+ const fileA = join(tempDirA, "test-nested", "1.json");
95
+ const fileB = join(tempDirB, "test-nested", "1.json");
96
+ await waitForFile(fileA);
97
+ await waitForFile(fileB);
98
+ const recordA = JSON.parse(readFileSync(fileA, "utf-8"));
99
+ const recordB = JSON.parse(readFileSync(fileB, "utf-8"));
100
+ expect(recordA.request).toEqual(recordB.request);
101
+ }
102
+ finally {
103
+ globalThis.fetch = originalFetch;
104
+ }
105
+ }
106
+ finally {
107
+ rmSync(tempDirA, { recursive: true, force: true });
108
+ rmSync(tempDirB, { recursive: true, force: true });
109
+ }
110
+ });
111
+ test("TC-005: redaction is inherited", async () => {
112
+ const t = createTracer({ globalDir: tempDir, localDir: tempDir });
113
+ const originalFetch = globalThis.fetch;
114
+ globalThis.fetch = async () => new Response(JSON.stringify({ ok: true }), {
115
+ status: 200,
116
+ headers: { "content-type": "application/json" },
117
+ });
118
+ try {
119
+ globalThis.fetch = t.wrap(globalThis.fetch);
120
+ const response = await globalThis.fetch("https://example.com/api", {
121
+ method: "POST",
122
+ headers: {
123
+ "x-opencode-session": "test-redact",
124
+ authorization: "Bearer secret-token-123",
125
+ "content-type": "application/json",
126
+ },
127
+ body: JSON.stringify({ test: true }),
128
+ });
129
+ expect(response.status).toBe(200);
130
+ const filePath = join(tempDir, "test-redact", "1.json");
131
+ await waitForFile(filePath);
132
+ const record = JSON.parse(readFileSync(filePath, "utf-8"));
133
+ const request = record.request;
134
+ const requestHeaders = request.headers;
135
+ expect(requestHeaders.authorization).toBe("Bearer [REDACTED]");
136
+ expect(requestHeaders["content-type"]).toBe("application/json");
137
+ }
138
+ finally {
139
+ globalThis.fetch = originalFetch;
140
+ }
141
+ });
142
+ test("TC-009: invalid localDir does not throw on construction", () => {
143
+ const t = createTracer({
144
+ globalDir: tempDir,
145
+ localDir: "/nonexistent/path/.opencode-trace",
146
+ });
147
+ expect(t).toBeDefined();
148
+ });
149
+ test("installInterceptor auto-patches and is idempotent", () => {
150
+ const t = createTracer({ globalDir: tempDir, localDir: tempDir });
151
+ const originalFetch = globalThis.fetch;
152
+ const mockFetch = async () => new Response(null, { status: 200 });
153
+ try {
154
+ globalThis.fetch = mockFetch;
155
+ t.installInterceptor();
156
+ const firstInterceptor = globalThis.fetch;
157
+ t.installInterceptor();
158
+ expect(globalThis.fetch).toBe(firstInterceptor);
159
+ }
160
+ finally {
161
+ globalThis.fetch = originalFetch;
162
+ }
163
+ });
164
+ });
165
+ describe("getInterceptor", () => {
166
+ let tempDir;
167
+ beforeEach(() => {
168
+ tempDir = mkdtempSync(join(tmpdir(), "tracer-getinterceptor-"));
169
+ });
170
+ afterEach(() => {
171
+ rmSync(tempDir, { recursive: true, force: true });
172
+ });
173
+ test("getInterceptor returns a function and does not auto-patch globalThis.fetch", () => {
174
+ const originalFetch = globalThis.fetch;
175
+ const t = createTracer({ globalDir: tempDir, localDir: tempDir });
176
+ const interceptor = t.getInterceptor();
177
+ expect(typeof interceptor).toBe("function");
178
+ // getInterceptor must NOT auto-patch — same contract as wrap()
179
+ expect(globalThis.fetch).toBe(originalFetch);
180
+ });
181
+ test("getInterceptor returns a fresh wrapper on each call", () => {
182
+ const t = createTracer({ globalDir: tempDir, localDir: tempDir });
183
+ const a = t.getInterceptor();
184
+ const b = t.getInterceptor();
185
+ expect(typeof a).toBe("function");
186
+ expect(typeof b).toBe("function");
187
+ // Each call returns a distinct arrow function instance
188
+ expect(a).not.toBe(b);
189
+ });
190
+ test("getInterceptor wrapper records a traced fetch call to disk", async () => {
191
+ const originalFetch = globalThis.fetch;
192
+ // origFetch is captured at tracer-construction time, so install the mock first
193
+ globalThis.fetch = async () => new Response(JSON.stringify({ ok: true }), {
194
+ status: 200,
195
+ headers: { "content-type": "application/json" },
196
+ });
197
+ const t = createTracer({ globalDir: tempDir, localDir: tempDir });
198
+ try {
199
+ const interceptor = t.getInterceptor();
200
+ const response = await interceptor("https://example.com/api", {
201
+ method: "GET",
202
+ headers: { "x-opencode-session": "test-getinterceptor" },
203
+ });
204
+ expect(response.status).toBe(200);
205
+ const filePath = join(tempDir, "test-getinterceptor", "1.json");
206
+ await waitForFile(filePath);
207
+ const record = JSON.parse(readFileSync(filePath, "utf-8"));
208
+ const request = record.request;
209
+ expect(request.url).toBe("https://example.com/api");
210
+ expect(request.method).toBe("GET");
211
+ }
212
+ finally {
213
+ globalThis.fetch = originalFetch;
214
+ }
215
+ });
216
+ });
217
+ describe("wrapStreamResponse raw SSE file write", () => {
218
+ test("writes raw SSE chunks to {seq}.sse in the traceDir", async () => {
219
+ const sseChunks = [
220
+ new TextEncoder().encode('data: {"id":"1"}\n\n'),
221
+ new TextEncoder().encode('data: {"id":"2"}\n\n'),
222
+ new TextEncoder().encode("data: [DONE]\n\n"),
223
+ ];
224
+ const stream = new ReadableStream({
225
+ start(controller) {
226
+ for (const c of sseChunks)
227
+ controller.enqueue(c);
228
+ controller.close();
229
+ },
230
+ });
231
+ const orig = new Response(stream, {
232
+ status: 200,
233
+ headers: { "Content-Type": "text/event-stream" },
234
+ });
235
+ const traceDir = mkdtempSync(join(tmpdir(), "sse-test-"));
236
+ const plugin = new TracePlugin({ localDir: traceDir, globalDir: traceDir });
237
+ const wrapped = await plugin.wrapStreamResponse(orig, performance.now(), "sess-1", 7, traceDir);
238
+ // Drain the wrapped body — this drives the transform's flush to completion
239
+ const reader = wrapped.body.getReader();
240
+ const received = [];
241
+ while (true) {
242
+ const { done, value } = await reader.read();
243
+ if (done)
244
+ break;
245
+ received.push(value);
246
+ }
247
+ const ssePath = join(traceDir, "sess-1", "7.sse");
248
+ expect(existsSync(ssePath)).toBe(true);
249
+ const written = readFileSync(ssePath, "utf8");
250
+ expect(written).toBe(sseChunks.map((c) => new TextDecoder().decode(c)).join(""));
251
+ const meta = wrapped.__latencyMeta;
252
+ expect(meta.firstTokenAt).not.toBeNull();
253
+ expect(meta.lastTokenAt).not.toBeNull();
254
+ rmSync(traceDir, { recursive: true, force: true });
255
+ });
256
+ test("does not create {seq}.sse or {seq}.sse.tmp when no chunks are written (empty stream)", async () => {
257
+ const stream = new ReadableStream({
258
+ start(c) {
259
+ c.close();
260
+ },
261
+ });
262
+ const orig = new Response(stream, { status: 200 });
263
+ const traceDir = mkdtempSync(join(tmpdir(), "sse-empty-"));
264
+ const plugin = new TracePlugin({ localDir: traceDir, globalDir: traceDir });
265
+ const wrapped = await plugin.wrapStreamResponse(orig, performance.now(), "sess-1", 8, traceDir);
266
+ const reader = wrapped.body.getReader();
267
+ while (!(await reader.read()).done) {
268
+ /* drain */
269
+ }
270
+ const sessionDir = join(traceDir, "sess-1");
271
+ expect(existsSync(join(sessionDir, "8.sse"))).toBe(false);
272
+ expect(existsSync(join(sessionDir, "8.sse.tmp"))).toBe(false);
273
+ rmSync(traceDir, { recursive: true, force: true });
274
+ });
275
+ });
276
+ //# sourceMappingURL=tracer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracer.test.js","sourceRoot":"","sources":["../../src/__tests__/tracer.test.ts"],"names":[],"mappings":"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"}