@taewooopark/agent-blackbox 0.47.3 → 0.47.4

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.
Files changed (2) hide show
  1. package/dist/cli.js +69 -26
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -2048,7 +2048,7 @@ async function readTraceEvents(filePath) {
2048
2048
  }
2049
2049
 
2050
2050
  // apps/daemon/dist/server.js
2051
- import { readFile as readFile4 } from "node:fs/promises";
2051
+ import { open as open2, stat as stat3 } from "node:fs/promises";
2052
2052
  import { createServer as createServer2 } from "node:http";
2053
2053
  import { join as join4 } from "node:path";
2054
2054
  import { WebSocket, WebSocketServer } from "ws";
@@ -2642,24 +2642,67 @@ async function loadTraceEvents(eventsFile) {
2642
2642
  }
2643
2643
  }
2644
2644
  var SNAPSHOT_EVENT_CAP = 3e4;
2645
+ var eventCaches = /* @__PURE__ */ new Map();
2646
+ var cacheLocks = /* @__PURE__ */ new Map();
2647
+ function withCacheLock(key, run) {
2648
+ const prev = cacheLocks.get(key) ?? Promise.resolve();
2649
+ const result = prev.then(run, run);
2650
+ cacheLocks.set(key, result.then(() => void 0, () => void 0));
2651
+ return result;
2652
+ }
2645
2653
  async function loadRecentTraceEvents(eventsFile, cap = SNAPSHOT_EVENT_CAP) {
2646
- let text;
2647
- try {
2648
- text = await readFile4(eventsFile, "utf8");
2649
- } catch (error) {
2650
- if (isNodeError(error) && error.code === "ENOENT")
2651
- return [];
2652
- throw error;
2653
- }
2654
- const lines = text.split("\n");
2655
- let kept = 0;
2656
- let start = lines.length;
2657
- while (start > 0 && kept < cap) {
2658
- start -= 1;
2659
- if (lines[start].trim().length > 0)
2660
- kept += 1;
2661
- }
2662
- return parseTraceEvents(lines.slice(start).join("\n"));
2654
+ return withCacheLock(eventsFile, async () => {
2655
+ let cache = eventCaches.get(eventsFile);
2656
+ if (!cache) {
2657
+ cache = { offset: 0, buffer: "", events: [] };
2658
+ eventCaches.set(eventsFile, cache);
2659
+ }
2660
+ let size;
2661
+ try {
2662
+ size = (await stat3(eventsFile)).size;
2663
+ } catch (error) {
2664
+ if (isNodeError(error) && error.code === "ENOENT")
2665
+ return [];
2666
+ throw error;
2667
+ }
2668
+ if (size < cache.offset) {
2669
+ cache.offset = 0;
2670
+ cache.buffer = "";
2671
+ cache.events = [];
2672
+ }
2673
+ if (size > cache.offset) {
2674
+ const handle = await open2(eventsFile, "r");
2675
+ try {
2676
+ const length = size - cache.offset;
2677
+ const buf = Buffer.alloc(length);
2678
+ await handle.read(buf, 0, length, cache.offset);
2679
+ cache.offset = size;
2680
+ cache.buffer += buf.toString("utf8");
2681
+ } finally {
2682
+ await handle.close();
2683
+ }
2684
+ const lines = cache.buffer.split("\n");
2685
+ cache.buffer = lines.pop() ?? "";
2686
+ let from = 0;
2687
+ if (cache.events.length === 0 && lines.length > SNAPSHOT_EVENT_CAP) {
2688
+ let kept = 0;
2689
+ from = lines.length;
2690
+ while (from > 0 && kept < SNAPSHOT_EVENT_CAP) {
2691
+ from -= 1;
2692
+ if (lines[from].trim().length > 0)
2693
+ kept += 1;
2694
+ }
2695
+ }
2696
+ const fresh = parseTraceEvents(lines.slice(from).join("\n"));
2697
+ if (fresh.length > 0) {
2698
+ cache.events.push(...fresh);
2699
+ if (cache.events.length > SNAPSHOT_EVENT_CAP) {
2700
+ cache.events.splice(0, cache.events.length - SNAPSHOT_EVENT_CAP);
2701
+ }
2702
+ }
2703
+ }
2704
+ return cap >= cache.events.length ? cache.events.slice() : cache.events.slice(cache.events.length - cap);
2705
+ });
2663
2706
  }
2664
2707
  async function buildReplaySummary(eventsFile) {
2665
2708
  const events = await loadTraceEvents(eventsFile);
@@ -2921,7 +2964,7 @@ function isNodeError(error) {
2921
2964
  }
2922
2965
 
2923
2966
  // apps/daemon/dist/initOpenCode.js
2924
- import { mkdir as mkdir3, readFile as readFile5, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
2967
+ import { mkdir as mkdir3, readFile as readFile4, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
2925
2968
  import { homedir as homedir2 } from "node:os";
2926
2969
  import { dirname as dirname3, join as join5 } from "node:path";
2927
2970
  var defaultAdapterPackage = "@agent-blackbox/opencode-adapter";
@@ -2938,7 +2981,7 @@ async function installGlobalRecorder(options) {
2938
2981
  throw new Error("Self-contained recorder bundle not found. Use the published npx package, or build it from source with `npm run build:cli`.");
2939
2982
  }
2940
2983
  const pluginPath = globalRecorderPath();
2941
- const bundle = (await readFile5(options.pluginBundlePath, "utf8")).replaceAll("__ABB_DAEMON_URL__", options.daemonUrl);
2984
+ const bundle = (await readFile4(options.pluginBundlePath, "utf8")).replaceAll("__ABB_DAEMON_URL__", options.daemonUrl);
2942
2985
  await mkdir3(dirname3(pluginPath), { recursive: true });
2943
2986
  await writeFile2(pluginPath, bundle, "utf8");
2944
2987
  return { pluginPath };
@@ -2967,7 +3010,7 @@ async function initOpenCodeProject(options) {
2967
3010
  throw new Error(`${pluginPath} already exists. Re-run with --force to overwrite it.`);
2968
3011
  }
2969
3012
  if (options.pluginBundlePath && await pathExists(options.pluginBundlePath)) {
2970
- const bundle = await readFile5(options.pluginBundlePath, "utf8");
3013
+ const bundle = await readFile4(options.pluginBundlePath, "utf8");
2971
3014
  const inlined = bundle.replaceAll("__ABB_DAEMON_URL__", daemonUrl);
2972
3015
  await writeFile2(pluginPath, inlined, "utf8");
2973
3016
  return { pluginPath, packageJsonPath, adapterPackage, adapterImport };
@@ -3006,7 +3049,7 @@ function inferAdapterImport(adapterPackage) {
3006
3049
  }
3007
3050
  async function readPackageJson(packageJsonPath) {
3008
3051
  try {
3009
- return JSON.parse(await readFile5(packageJsonPath, "utf8"));
3052
+ return JSON.parse(await readFile4(packageJsonPath, "utf8"));
3010
3053
  } catch (error) {
3011
3054
  if (isNodeError2(error) && error.code === "ENOENT") {
3012
3055
  return {};
@@ -3016,7 +3059,7 @@ async function readPackageJson(packageJsonPath) {
3016
3059
  }
3017
3060
  async function pathExists(path) {
3018
3061
  try {
3019
- await readFile5(path, "utf8");
3062
+ await readFile4(path, "utf8");
3020
3063
  return true;
3021
3064
  } catch (error) {
3022
3065
  if (isNodeError2(error) && error.code === "ENOENT") {
@@ -3052,7 +3095,7 @@ function describeDaemon() {
3052
3095
  }
3053
3096
 
3054
3097
  // apps/daemon/dist/initClaudeHooks.js
3055
- import { mkdir as mkdir4, readFile as readFile6, writeFile as writeFile3 } from "node:fs/promises";
3098
+ import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile3 } from "node:fs/promises";
3056
3099
  import { homedir as homedir3 } from "node:os";
3057
3100
  import { dirname as dirname5, join as join7 } from "node:path";
3058
3101
  function globalClaudeDir() {
@@ -3075,7 +3118,7 @@ async function uninstallClaudeCodeHooks() {
3075
3118
  const settingsPath = claudeSettingsPath();
3076
3119
  let settings;
3077
3120
  try {
3078
- settings = JSON.parse(await readFile6(settingsPath, "utf8"));
3121
+ settings = JSON.parse(await readFile5(settingsPath, "utf8"));
3079
3122
  } catch (error) {
3080
3123
  if (isNotFound(error))
3081
3124
  return { settingsPath, removed: false };
@@ -3089,7 +3132,7 @@ async function uninstallClaudeCodeHooks() {
3089
3132
  }
3090
3133
  async function readSettings(path) {
3091
3134
  try {
3092
- return JSON.parse(await readFile6(path, "utf8"));
3135
+ return JSON.parse(await readFile5(path, "utf8"));
3093
3136
  } catch (error) {
3094
3137
  if (isNotFound(error))
3095
3138
  return {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taewooopark/agent-blackbox",
3
- "version": "0.47.3",
3
+ "version": "0.47.4",
4
4
  "description": "Local-first flight recorder + context-efficiency profiler for coding agents — records Claude Code and OpenCode. Run with npx.",
5
5
  "keywords": [
6
6
  "claude-code",