@opencode-trace/plugin 0.0.4 → 0.0.6

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.
@@ -1,13 +1,26 @@
1
- import { describe, test, expect, beforeEach, afterEach } from "vitest";
1
+ import { describe, test, expect, beforeEach, afterEach, vi } from "vitest";
2
2
  import { TracePlugin } from "./plugin-instance.js";
3
- import { mkdtempSync, rmSync, readdirSync, readFileSync, existsSync } from "node:fs";
3
+ import entrypoint, { _resetForTesting } from "./trace.js";
4
+ import { mkdtempSync, rmSync, readdirSync, readFileSync, writeFileSync, existsSync, promises as fs, } from "node:fs";
4
5
  import { tmpdir } from "node:os";
5
6
  import { join } from "node:path";
7
+ vi.mock("node:os", async (importOriginal) => {
8
+ const original = await importOriginal();
9
+ return {
10
+ ...original,
11
+ homedir: () => {
12
+ const testDir = process.env._INTEGRATION_TEST_DIR_;
13
+ if (testDir)
14
+ return testDir;
15
+ return original.homedir();
16
+ },
17
+ };
18
+ });
6
19
  async function waitForFiles(dir, count, timeoutMs = 5000) {
7
20
  const startTime = Date.now();
8
21
  while (true) {
9
22
  if (existsSync(dir)) {
10
- const files = readdirSync(dir).filter(f => f.endsWith(".json"));
23
+ const files = readdirSync(dir).filter((f) => /^\d+\.json$/.test(f));
11
24
  if (files.length >= count) {
12
25
  let allValid = true;
13
26
  for (const file of files) {
@@ -31,7 +44,26 @@ async function waitForFiles(dir, count, timeoutMs = 5000) {
31
44
  if (Date.now() - startTime > timeoutMs) {
32
45
  throw new Error(`Timeout waiting for ${count} valid files in ${dir} after ${timeoutMs}ms`);
33
46
  }
34
- await new Promise(r => setTimeout(r, 10));
47
+ await new Promise((r) => setTimeout(r, 10));
48
+ }
49
+ }
50
+ async function waitForFile(filePath, timeoutMs = 5000) {
51
+ const startTime = Date.now();
52
+ while (true) {
53
+ if (existsSync(filePath)) {
54
+ try {
55
+ const content = readFileSync(filePath, "utf-8");
56
+ if (content && content.length > 0) {
57
+ JSON.parse(content);
58
+ return;
59
+ }
60
+ }
61
+ catch { }
62
+ }
63
+ if (Date.now() - startTime > timeoutMs) {
64
+ throw new Error(`Timeout waiting for valid file ${filePath} after ${timeoutMs}ms`);
65
+ }
66
+ await new Promise((r) => setTimeout(r, 10));
35
67
  }
36
68
  }
37
69
  describe("Integration: TracePlugin full flow", () => {
@@ -39,7 +71,7 @@ describe("Integration: TracePlugin full flow", () => {
39
71
  let plugin;
40
72
  beforeEach(async () => {
41
73
  tempDir = mkdtempSync(join(tmpdir(), "integration-test-"));
42
- plugin = new TracePlugin(tempDir, tempDir);
74
+ plugin = new TracePlugin({ globalDir: tempDir, localDir: tempDir });
43
75
  });
44
76
  afterEach(() => {
45
77
  plugin.uninstallInterceptor();
@@ -49,22 +81,24 @@ describe("Integration: TracePlugin full flow", () => {
49
81
  const originalFetch = globalThis.fetch;
50
82
  globalThis.fetch = async (input) => {
51
83
  const req = new Request(input);
52
- await new Promise(resolve => setTimeout(resolve, 50));
84
+ await new Promise((resolve) => setTimeout(resolve, 50));
53
85
  return new Response(JSON.stringify({ url: req.url }), { status: 200 });
54
86
  };
55
87
  plugin.installInterceptor();
56
88
  await plugin.initStateManager();
57
89
  const sessionId = "concurrent-test";
58
- plugin["stateManager"].startSession(sessionId);
90
+ plugin.getStateManager().startSession(sessionId);
59
91
  const requests = Array.from({ length: 5 }, (_, i) => plugin.tracedFetch(`https://example.com/${i}`, {
60
92
  method: "GET",
61
- headers: { "x-opencode-session": sessionId }
93
+ headers: { "x-opencode-session": sessionId },
62
94
  }));
63
95
  const responses = await Promise.all(requests);
64
- expect(responses.every(r => r.status === 200)).toBe(true);
96
+ expect(responses.every((r) => r.status === 200)).toBe(true);
97
+ await plugin.flush();
65
98
  const sessionDir = join(tempDir, sessionId);
66
- await waitForFiles(sessionDir, 5);
67
- const files = readdirSync(sessionDir).filter(f => f.endsWith(".json")).sort();
99
+ const files = readdirSync(sessionDir)
100
+ .filter((f) => /^\d+\.json$/.test(f))
101
+ .sort();
68
102
  expect(files.length).toBe(5);
69
103
  for (let i = 0; i < 5; i++) {
70
104
  const content = JSON.parse(readFileSync(join(sessionDir, files[i]), "utf-8"));
@@ -73,4 +107,467 @@ describe("Integration: TracePlugin full flow", () => {
73
107
  globalThis.fetch = originalFetch;
74
108
  });
75
109
  });
110
+ // =============================================================================
111
+ // ST1: Real plugin SDK hooks lifecycle via entrypoint(input)
112
+ // =============================================================================
113
+ // Constructs the plugin through the real SDK entrypoint with a mocked
114
+ // PluginInput, then exercises the actually-wired hooks (`event`,
115
+ // `tool.execute.after`, `config`, `tool.trace_on/trace_off/trace_status`).
116
+ // Verifies real side effects on disk: session dir, metadata.json, config.json,
117
+ // subSessions array, and effective enabled state.
118
+ //
119
+ // The plugin DOES wire `chat.message`, `chat.params`, and `tool.execute.before`
120
+ // (they just `logger.info` and return — they do not change the existing flow).
121
+ // =============================================================================
122
+ describe("ST1: real plugin SDK hooks lifecycle (entrypoint + PluginInput)", () => {
123
+ let tempDir;
124
+ beforeEach(() => {
125
+ tempDir = mkdtempSync(join(tmpdir(), "integration-st1-"));
126
+ process.env._INTEGRATION_TEST_DIR_ = tempDir;
127
+ _resetForTesting();
128
+ });
129
+ afterEach(() => {
130
+ _resetForTesting();
131
+ delete process.env._INTEGRATION_TEST_DIR_;
132
+ rmSync(tempDir, { recursive: true, force: true });
133
+ });
134
+ test("entrypoint.server returns wired hooks, and the wired hooks have real side effects", async () => {
135
+ const hooks = await entrypoint.server({
136
+ client: {},
137
+ project: {},
138
+ directory: tempDir,
139
+ worktree: tempDir,
140
+ experimental_workspace: { register: vi.fn() },
141
+ serverUrl: new URL("http://localhost"),
142
+ $: {},
143
+ });
144
+ // Wired hooks per trace.ts
145
+ expect(hooks.event).toBeDefined();
146
+ expect(hooks["tool.execute.after"]).toBeDefined();
147
+ expect(hooks.config).toBeDefined();
148
+ expect(hooks["command.execute.before"]).toBeDefined();
149
+ expect(hooks.tool).toBeDefined();
150
+ expect(hooks.tool.trace_on).toBeDefined();
151
+ expect(hooks.tool.trace_off).toBeDefined();
152
+ expect(hooks.tool.trace_status).toBeDefined();
153
+ // Wired: chat.message / chat.params / tool.execute.before (logger.info only,
154
+ // no state change). Assert they exist and are functions.
155
+ expect(typeof hooks["chat.message"]).toBe("function");
156
+ expect(typeof hooks["chat.params"]).toBe("function");
157
+ expect(typeof hooks["tool.execute.before"]).toBe("function");
158
+ // Step 1: `event` hook with session.created creates the session dir and metadata.
159
+ const parentId = "st1-parent-session";
160
+ await hooks.event({
161
+ event: {
162
+ type: "session.created",
163
+ properties: {
164
+ info: {
165
+ id: parentId,
166
+ projectID: "p",
167
+ directory: tempDir,
168
+ title: "ST1 Parent",
169
+ version: "1.0",
170
+ time: { created: Date.now(), updated: Date.now() },
171
+ },
172
+ },
173
+ },
174
+ });
175
+ const globalTraceDir = join(tempDir, ".opencode-trace");
176
+ const parentSessionDir = join(globalTraceDir, parentId);
177
+ expect(existsSync(parentSessionDir)).toBe(true);
178
+ const parentMetaPath = join(parentSessionDir, "metadata.json");
179
+ expect(existsSync(parentMetaPath)).toBe(true);
180
+ const parentMeta = JSON.parse(readFileSync(parentMetaPath, "utf-8"));
181
+ expect(parentMeta.title).toBe("ST1 Parent");
182
+ expect(parentMeta.folderPath).toBe(tempDir);
183
+ // global config.json is initialized by initStateManager()
184
+ expect(existsSync(join(globalTraceDir, "config.json"))).toBe(true);
185
+ // Step 2: `config` hook registers the /trace command
186
+ const cfgIn = {};
187
+ await hooks.config(cfgIn);
188
+ expect(cfgIn.command?.trace?.description).toMatch(/Control trace recording/);
189
+ // Step 3: tool.trace_on enables session
190
+ const onResult = await hooks.tool.trace_on.execute({}, { sessionID: parentId });
191
+ expect(String(onResult)).toContain("Trace enabled for session");
192
+ // Step 4: tool.trace_status reflects new effective state for session
193
+ const statusResult = await hooks.tool.trace_status.execute({}, { sessionID: parentId });
194
+ expect(String(statusResult)).toContain("Trace Status");
195
+ expect(String(statusResult)).toContain("Session : ON");
196
+ expect(String(statusResult)).toMatch(/Effective: (RECORDING|PAUSED)/);
197
+ // Step 5: tool.trace_off disables the session again
198
+ const offResult = await hooks.tool.trace_off.execute({}, { sessionID: parentId });
199
+ expect(String(offResult)).toContain("Trace disabled for session");
200
+ });
201
+ });
202
+ // =============================================================================
203
+ // ST2: SSE (text/event-stream) roundtrip
204
+ // =============================================================================
205
+ // Mocks fetch to return a `ReadableStream` of SSE chunks, calls tracedFetch
206
+ // with `stream: true` body, and verifies:
207
+ // - Response stream is still drainable by the caller and yields the same chunks
208
+ // - __latencyMeta is attached to the wrapped Response
209
+ // - firstTokenAt/lastTokenAt become populated as chunks flow through
210
+ // - Persisted {seq}.json record carries those latency fields
211
+ //
212
+ // NOTE: The plugin does NOT currently write a raw `1.sse` file even though the
213
+ // README documents one — only `{seq}.json` and `{seq}.parsed` are emitted.
214
+ // =============================================================================
215
+ describe("ST2: SSE stream roundtrip", () => {
216
+ let tempDir;
217
+ let plugin;
218
+ let originalFetch;
219
+ beforeEach(async () => {
220
+ tempDir = mkdtempSync(join(tmpdir(), "integration-st2-"));
221
+ plugin = new TracePlugin({ globalDir: tempDir, localDir: tempDir });
222
+ await plugin.initStateManager();
223
+ originalFetch = globalThis.fetch;
224
+ });
225
+ afterEach(() => {
226
+ plugin.uninstallInterceptor();
227
+ globalThis.fetch = originalFetch;
228
+ rmSync(tempDir, { recursive: true, force: true });
229
+ });
230
+ test("stream body is drained by caller and latency fields land in {seq}.json", async () => {
231
+ const encoder = new TextEncoder();
232
+ const sseChunks = [
233
+ 'data: {"delta":"Hello"}\n\n',
234
+ 'data: {"delta":" world"}\n\n',
235
+ "data: [DONE]\n\n",
236
+ ];
237
+ const mockFetch = vi.fn(async () => {
238
+ const stream = new ReadableStream({
239
+ start(controller) {
240
+ for (const c of sseChunks)
241
+ controller.enqueue(encoder.encode(c));
242
+ controller.close();
243
+ },
244
+ });
245
+ return new Response(stream, {
246
+ status: 200,
247
+ headers: { "content-type": "text/event-stream" },
248
+ });
249
+ });
250
+ globalThis.fetch = mockFetch;
251
+ plugin.installInterceptor();
252
+ const sessionId = "st2-sse";
253
+ plugin.getStateManager().startSession(sessionId);
254
+ const res = await plugin.tracedFetch("https://api.example.com/v1/messages", {
255
+ method: "POST",
256
+ headers: {
257
+ "content-type": "application/json",
258
+ "x-opencode-session": sessionId,
259
+ },
260
+ body: JSON.stringify({
261
+ stream: true,
262
+ messages: [{ role: "user", content: "hi" }],
263
+ }),
264
+ });
265
+ expect(res.status).toBe(200);
266
+ expect(res.headers.get("content-type")).toBe("text/event-stream");
267
+ // __latencyMeta should be present BEFORE consumption
268
+ const latencyBefore = res.__latencyMeta;
269
+ expect(latencyBefore).toBeDefined();
270
+ expect(typeof latencyBefore.requestSentAt).toBe("number");
271
+ expect(latencyBefore.firstTokenAt).toBeNull();
272
+ expect(latencyBefore.lastTokenAt).toBeNull();
273
+ // Drain the body as a downstream caller would
274
+ const reader = res.body.getReader();
275
+ const received = [];
276
+ while (true) {
277
+ const { done, value } = await reader.read();
278
+ if (done)
279
+ break;
280
+ received.push(value);
281
+ }
282
+ // Caller received the same chunks the mock emitted
283
+ expect(received.length).toBe(sseChunks.length);
284
+ const decoder = new TextDecoder();
285
+ const reassembled = received.map((c) => decoder.decode(c)).join("");
286
+ expect(reassembled).toBe(sseChunks.join(""));
287
+ // After draining, latency fields should be populated
288
+ const latencyAfter = res.__latencyMeta;
289
+ expect(latencyAfter.firstTokenAt).not.toBeNull();
290
+ expect(latencyAfter.lastTokenAt).not.toBeNull();
291
+ expect(latencyAfter.lastTokenAt).toBeGreaterThanOrEqual(latencyAfter.firstTokenAt);
292
+ await plugin.flush();
293
+ const sessionDir = join(tempDir, sessionId);
294
+ await waitForFiles(sessionDir, 1);
295
+ const recordPath = join(sessionDir, "1.json");
296
+ const record = JSON.parse(readFileSync(recordPath, "utf-8"));
297
+ expect(record.id).toBe(1);
298
+ expect(record.requestSentAt).toBeDefined();
299
+ expect(typeof record.firstTokenAt).toBe("number");
300
+ expect(typeof record.lastTokenAt).toBe("number");
301
+ expect(record.lastTokenAt).toBeGreaterThanOrEqual(record.firstTokenAt);
302
+ });
303
+ });
304
+ // =============================================================================
305
+ // ST3: parentID / subSessions chain from tool.execute.after
306
+ // =============================================================================
307
+ // Verifies what the `tool.execute.after` hook actually does for the "task" tool:
308
+ // it appends the child session id to the PARENT's metadata.json `subSessions`
309
+ // array, AND eagerly writes the child's metadata.json with `parentID` set so
310
+ // the child is linked immediately, regardless of whether `session.created`
311
+ // arrives for it later. We assert both behaviors so the contract is locked in.
312
+ // =============================================================================
313
+ describe("ST3: subSessions chain from tool.execute.after", () => {
314
+ let tempDir;
315
+ beforeEach(() => {
316
+ tempDir = mkdtempSync(join(tmpdir(), "integration-st3-"));
317
+ process.env._INTEGRATION_TEST_DIR_ = tempDir;
318
+ _resetForTesting();
319
+ });
320
+ afterEach(() => {
321
+ _resetForTesting();
322
+ delete process.env._INTEGRATION_TEST_DIR_;
323
+ rmSync(tempDir, { recursive: true, force: true });
324
+ });
325
+ test("tool.execute.after task appends to parent.subSessions AND eagerly sets child.parentID", async () => {
326
+ const hooks = await entrypoint.server({
327
+ client: {},
328
+ project: {},
329
+ directory: tempDir,
330
+ worktree: tempDir,
331
+ experimental_workspace: { register: vi.fn() },
332
+ serverUrl: new URL("http://localhost"),
333
+ $: {},
334
+ });
335
+ const parentId = "st3-parent";
336
+ const childId = "st3-child";
337
+ // Create the parent session via the event hook
338
+ await hooks.event({
339
+ event: {
340
+ type: "session.created",
341
+ properties: {
342
+ info: {
343
+ id: parentId,
344
+ projectID: "p",
345
+ directory: tempDir,
346
+ title: "Parent",
347
+ version: "1.0",
348
+ time: { created: Date.now(), updated: Date.now() },
349
+ },
350
+ },
351
+ },
352
+ });
353
+ // Simulate a Task tool returning a child sessionID in its metadata
354
+ await hooks["tool.execute.after"]({
355
+ tool: "task",
356
+ sessionID: parentId,
357
+ callID: "call-1",
358
+ args: { description: "spawn child", prompt: "go" },
359
+ }, {
360
+ title: "Task done",
361
+ output: "ok",
362
+ metadata: { session_id: childId },
363
+ });
364
+ const globalTraceDir = join(tempDir, ".opencode-trace");
365
+ const parentMetaPath = join(globalTraceDir, parentId, "metadata.json");
366
+ await waitForFile(parentMetaPath);
367
+ const parentMeta = JSON.parse(readFileSync(parentMetaPath, "utf-8"));
368
+ expect(Array.isArray(parentMeta.subSessions)).toBe(true);
369
+ expect(parentMeta.subSessions).toContain(childId);
370
+ // The child's metadata.json IS eagerly created by tool.execute.after with
371
+ // parentID set, so the link is race-free and survives missing session.created.
372
+ const childMetaPath = join(globalTraceDir, childId, "metadata.json");
373
+ expect(existsSync(childMetaPath)).toBe(true);
374
+ const eagerChildMeta = JSON.parse(readFileSync(childMetaPath, "utf-8"));
375
+ expect(eagerChildMeta.parentID).toBe(parentId);
376
+ // Now simulate the child's own session.created event carrying parentID.
377
+ // This is idempotent: parentID is already correct, and addSubSession
378
+ // dedupes so the parent's subSessions array still has the child exactly once.
379
+ const childEvent = {
380
+ type: "session.created",
381
+ properties: {
382
+ info: {
383
+ id: childId,
384
+ projectID: "p",
385
+ directory: tempDir,
386
+ title: "Child",
387
+ parentID: parentId,
388
+ version: "1.0",
389
+ time: { created: Date.now(), updated: Date.now() },
390
+ },
391
+ },
392
+ };
393
+ await hooks.event({ event: childEvent });
394
+ const childMeta = JSON.parse(readFileSync(childMetaPath, "utf-8"));
395
+ expect(childMeta.parentID).toBe(parentId);
396
+ expect(childMeta.title).toBe("Child");
397
+ // The parent still has the child listed exactly once (idempotent).
398
+ const parentMeta2 = JSON.parse(readFileSync(parentMetaPath, "utf-8"));
399
+ expect(parentMeta2.subSessions.filter((s) => s === childId).length).toBe(1);
400
+ // Sanity: non-"task" tool with metadata.session_id does NOTHING.
401
+ const noopChildId = "st3-noop-child";
402
+ await hooks["tool.execute.after"]({
403
+ tool: "bash",
404
+ sessionID: parentId,
405
+ callID: "call-2",
406
+ args: { command: "ls" },
407
+ }, {
408
+ title: "Ran bash",
409
+ output: "",
410
+ metadata: { session_id: noopChildId },
411
+ });
412
+ const parentMeta3 = JSON.parse(readFileSync(parentMetaPath, "utf-8"));
413
+ expect(parentMeta3.subSessions).not.toContain(noopChildId);
414
+ const noopChildPath = join(globalTraceDir, noopChildId, "metadata.json");
415
+ expect(existsSync(noopChildPath)).toBe(false);
416
+ });
417
+ });
418
+ // =============================================================================
419
+ // ST4: corrupted {seq}.json record on disk does not crash later requests
420
+ // =============================================================================
421
+ // The plugin keeps `seq` in memory (this.ids Map), not on disk, so a corrupted
422
+ // file should not affect new writes. We do one successful request (seq=1),
423
+ // corrupt 1.json in-place, then trigger another request and verify seq=2 is
424
+ // written cleanly and the plugin process survives.
425
+ // =============================================================================
426
+ describe("ST4: corrupted record recovery", () => {
427
+ let tempDir;
428
+ let plugin;
429
+ let originalFetch;
430
+ beforeEach(async () => {
431
+ tempDir = mkdtempSync(join(tmpdir(), "integration-st4-"));
432
+ plugin = new TracePlugin({ globalDir: tempDir, localDir: tempDir });
433
+ await plugin.initStateManager();
434
+ originalFetch = globalThis.fetch;
435
+ });
436
+ afterEach(() => {
437
+ plugin.uninstallInterceptor();
438
+ globalThis.fetch = originalFetch;
439
+ rmSync(tempDir, { recursive: true, force: true });
440
+ });
441
+ test("a corrupted prior record does not break subsequent writes", async () => {
442
+ let callCount = 0;
443
+ globalThis.fetch = (async () => {
444
+ callCount++;
445
+ return new Response(JSON.stringify({ ok: true, call: callCount }), {
446
+ status: 200,
447
+ headers: { "content-type": "application/json" },
448
+ });
449
+ });
450
+ plugin.installInterceptor();
451
+ const sessionId = "st4-corrupt";
452
+ plugin.getStateManager().startSession(sessionId);
453
+ // First request — should land as 1.json with valid JSON
454
+ const r1 = await plugin.tracedFetch("https://example.com/a", {
455
+ method: "GET",
456
+ headers: { "x-opencode-session": sessionId },
457
+ });
458
+ expect(r1.status).toBe(200);
459
+ await plugin.flush();
460
+ const sessionDir = join(tempDir, sessionId);
461
+ await waitForFiles(sessionDir, 1);
462
+ const file1 = join(sessionDir, "1.json");
463
+ expect(existsSync(file1)).toBe(true);
464
+ // Corrupt the existing 1.json
465
+ writeFileSync(file1, "not valid json {{{ definitely broken", "utf-8");
466
+ expect(() => JSON.parse(readFileSync(file1, "utf-8"))).toThrow();
467
+ // Second request should produce 2.json cleanly without throwing
468
+ const r2 = await plugin.tracedFetch("https://example.com/b", {
469
+ method: "GET",
470
+ headers: { "x-opencode-session": sessionId },
471
+ });
472
+ expect(r2.status).toBe(200);
473
+ await plugin.flush();
474
+ // Don't use waitForFiles here: 1.json is now corrupted, so the
475
+ // "all files valid" precondition would never hold. Wait specifically
476
+ // for 2.json instead.
477
+ const file2 = join(sessionDir, "2.json");
478
+ await waitForFile(file2);
479
+ expect(existsSync(file2)).toBe(true);
480
+ const record2 = JSON.parse(readFileSync(file2, "utf-8"));
481
+ expect(record2.id).toBe(2);
482
+ expect(record2.response.status).toBe(200);
483
+ expect(record2.request.url).toBe("https://example.com/b");
484
+ // The corrupted 1.json is left untouched — plugin never re-reads it
485
+ const stillCorrupt = readFileSync(file1, "utf-8");
486
+ expect(stillCorrupt).toBe("not valid json {{{ definitely broken");
487
+ // No fallback dir created because no rename actually failed
488
+ expect(existsSync(join(tempDir, "fallback"))).toBe(false);
489
+ });
490
+ });
491
+ // =============================================================================
492
+ // ST5: Windows-style transient rename failure is retried by safeRename
493
+ // =============================================================================
494
+ // Spies on fs.promises.rename and throws an EPERM-like error on the first call,
495
+ // then lets the real rename through on subsequent calls. Verifies:
496
+ // - The .tmp file ends up renamed to the final {seq}.json
497
+ // - No .tmp leftover
498
+ // - No fallback file (because retry succeeded)
499
+ //
500
+ // NOTE: safeRename currently retries SILENTLY — it does not call logger.warn
501
+ // on each retry. The task description anticipates a warn log; we assert the
502
+ // observed behavior and surface this gap in the report.
503
+ // =============================================================================
504
+ describe("ST5: Windows rename retry", () => {
505
+ let tempDir;
506
+ let plugin;
507
+ let originalFetch;
508
+ let renameSpy = null;
509
+ beforeEach(async () => {
510
+ tempDir = mkdtempSync(join(tmpdir(), "integration-st5-"));
511
+ plugin = new TracePlugin({ globalDir: tempDir, localDir: tempDir });
512
+ await plugin.initStateManager();
513
+ originalFetch = globalThis.fetch;
514
+ });
515
+ afterEach(() => {
516
+ plugin.uninstallInterceptor();
517
+ globalThis.fetch = originalFetch;
518
+ if (renameSpy) {
519
+ renameSpy.mockRestore();
520
+ renameSpy = null;
521
+ }
522
+ rmSync(tempDir, { recursive: true, force: true });
523
+ });
524
+ test("fs.rename throwing EPERM once is recovered transparently by safeRename", async () => {
525
+ globalThis.fetch = (async () => new Response(JSON.stringify({ ok: true }), {
526
+ status: 200,
527
+ headers: { "content-type": "application/json" },
528
+ }));
529
+ // Spy on the real fs.promises.rename. Throw EPERM the first time it is
530
+ // called for OUR session dir, then call through on every subsequent
531
+ // invocation. Tests for OTHER sessions in parallel files share the same
532
+ // singleton — so we scope by destination path.
533
+ const realRename = fs.rename.bind(fs);
534
+ const sessionId = "st5-rename-retry";
535
+ const sessionDir = join(tempDir, sessionId);
536
+ let throwsRemaining = 1;
537
+ renameSpy = vi
538
+ .spyOn(fs, "rename")
539
+ .mockImplementation(async (src, dest) => {
540
+ const destStr = String(dest);
541
+ if (throwsRemaining > 0 && destStr.startsWith(sessionDir)) {
542
+ throwsRemaining--;
543
+ const err = new Error("EPERM: simulated transient lock");
544
+ err.code = "EPERM";
545
+ throw err;
546
+ }
547
+ return realRename(src, dest);
548
+ });
549
+ plugin.installInterceptor();
550
+ plugin.getStateManager().startSession(sessionId);
551
+ const res = await plugin.tracedFetch("https://example.com/x", {
552
+ method: "GET",
553
+ headers: { "x-opencode-session": sessionId },
554
+ });
555
+ expect(res.status).toBe(200);
556
+ await plugin.flush();
557
+ // Give safeRename's 50ms backoff a window plus a bit
558
+ await new Promise((r) => setTimeout(r, 200));
559
+ await waitForFiles(sessionDir, 1);
560
+ // The first rename for our session was thrown
561
+ const renameCalls = renameSpy.mock.calls.filter((c) => String(c[1]).startsWith(sessionDir));
562
+ expect(renameCalls.length).toBeGreaterThanOrEqual(2);
563
+ // Final {seq}.json exists and parses; no .tmp leftover
564
+ const finalPath = join(sessionDir, "1.json");
565
+ expect(existsSync(finalPath)).toBe(true);
566
+ const rec = JSON.parse(readFileSync(finalPath, "utf-8"));
567
+ expect(rec.id).toBe(1);
568
+ expect(existsSync(join(sessionDir, "1.json.tmp"))).toBe(false);
569
+ // Retry succeeded → no fallback file should have been emitted
570
+ expect(existsSync(join(tempDir, "fallback"))).toBe(false);
571
+ });
572
+ });
76
573
  //# sourceMappingURL=integration.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../src/integration.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../src/integration.test.ts"],"names":[],"mappings":"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"}