@taewooopark/agent-blackbox 0.43.0 → 0.45.0

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 +117 -12
  2. package/package.json +20 -7
package/dist/cli.js CHANGED
@@ -1107,8 +1107,9 @@ function removeManagedBlock(content) {
1107
1107
  // apps/daemon/dist/cli.js
1108
1108
  import { spawn as spawn2 } from "node:child_process";
1109
1109
  import { existsSync } from "node:fs";
1110
- import { fileURLToPath } from "node:url";
1111
- import { dirname as dirname3, resolve } from "node:path";
1110
+ import { homedir as homedir2 } from "node:os";
1111
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
1112
+ import { dirname as dirname5, join as join6, resolve } from "node:path";
1112
1113
 
1113
1114
  // apps/daemon/dist/dashboardServer.js
1114
1115
  import { createReadStream } from "node:fs";
@@ -1177,6 +1178,11 @@ async function startDashboardServer(options) {
1177
1178
  };
1178
1179
  }
1179
1180
 
1181
+ // apps/daemon/dist/index.js
1182
+ import { readFileSync } from "node:fs";
1183
+ import { dirname as dirname4, join as join5 } from "node:path";
1184
+ import { fileURLToPath } from "node:url";
1185
+
1180
1186
  // packages/storage/src/ndjson.ts
1181
1187
  import { appendFile, mkdir, readFile as readFile2 } from "node:fs/promises";
1182
1188
  import { dirname } from "node:path";
@@ -1912,10 +1918,39 @@ function isNodeError(error) {
1912
1918
  }
1913
1919
 
1914
1920
  // apps/daemon/dist/initOpenCode.js
1915
- import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile2 } from "node:fs/promises";
1916
- import { join as join4 } from "node:path";
1921
+ import { mkdir as mkdir3, readFile as readFile4, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
1922
+ import { homedir } from "node:os";
1923
+ import { dirname as dirname3, join as join4 } from "node:path";
1917
1924
  var defaultAdapterPackage = "@agent-blackbox/opencode-adapter";
1918
1925
  var defaultDaemonUrl = "http://127.0.0.1:47831";
1926
+ function globalOpenCodeDir() {
1927
+ const xdg = process.env.XDG_CONFIG_HOME;
1928
+ return xdg && xdg.length > 0 ? join4(xdg, "opencode") : join4(homedir(), ".config", "opencode");
1929
+ }
1930
+ function globalRecorderPath() {
1931
+ return join4(globalOpenCodeDir(), "plugins", "agent-blackbox.js");
1932
+ }
1933
+ async function installGlobalRecorder(options) {
1934
+ if (!await pathExists(options.pluginBundlePath)) {
1935
+ throw new Error("Self-contained recorder bundle not found. Use the published npx package, or build it from source with `npm run build:cli`.");
1936
+ }
1937
+ const pluginPath = globalRecorderPath();
1938
+ const bundle = (await readFile4(options.pluginBundlePath, "utf8")).replaceAll("__ABB_DAEMON_URL__", options.daemonUrl);
1939
+ await mkdir3(dirname3(pluginPath), { recursive: true });
1940
+ await writeFile2(pluginPath, bundle, "utf8");
1941
+ return { pluginPath };
1942
+ }
1943
+ async function uninstallGlobalRecorder() {
1944
+ const pluginPath = globalRecorderPath();
1945
+ try {
1946
+ await rm2(pluginPath);
1947
+ return { pluginPath, removed: true };
1948
+ } catch (error) {
1949
+ if (isNodeError2(error) && error.code === "ENOENT")
1950
+ return { pluginPath, removed: false };
1951
+ throw error;
1952
+ }
1953
+ }
1919
1954
  async function initOpenCodeProject(options) {
1920
1955
  const adapterPackage = options.adapterPackage ?? defaultAdapterPackage;
1921
1956
  const adapterImport = inferAdapterImport(adapterPackage);
@@ -1992,18 +2027,38 @@ function isNodeError2(error) {
1992
2027
  }
1993
2028
 
1994
2029
  // apps/daemon/dist/index.js
1995
- var AGENT_BLACKBOX_DAEMON_VERSION = "0.1.0";
2030
+ function resolvePackageVersion() {
2031
+ let dir = dirname4(fileURLToPath(import.meta.url));
2032
+ for (let i = 0; i < 6; i += 1) {
2033
+ try {
2034
+ const pkg = JSON.parse(readFileSync(join5(dir, "package.json"), "utf8"));
2035
+ if (typeof pkg.version === "string" && pkg.version.length > 0)
2036
+ return pkg.version;
2037
+ } catch {
2038
+ }
2039
+ const parent = dirname4(dir);
2040
+ if (parent === dir)
2041
+ break;
2042
+ dir = parent;
2043
+ }
2044
+ return "0.0.0";
2045
+ }
2046
+ var AGENT_BLACKBOX_DAEMON_VERSION = resolvePackageVersion();
1996
2047
  function describeDaemon() {
1997
2048
  return "Agent-Blackbox daemon: local ingest, replay, and dashboard bridge.";
1998
2049
  }
1999
2050
 
2000
2051
  // apps/daemon/dist/cli.js
2001
2052
  var args = process.argv.slice(2);
2002
- var cliDir = dirname3(fileURLToPath(import.meta.url));
2053
+ var cliDir = dirname5(fileURLToPath2(import.meta.url));
2003
2054
  var repoRoot = resolve(cliDir, "../../..");
2004
2055
  var firstExisting = (paths) => paths.find((p) => existsSync(p));
2005
2056
  var dashboardDistDir = firstExisting([resolve(cliDir, "dashboard"), resolve(repoRoot, "apps/dashboard/dist")]) ?? resolve(repoRoot, "apps/dashboard/dist");
2006
2057
  var pluginBundlePath = firstExisting([resolve(cliDir, "agent-blackbox.plugin.mjs")]);
2058
+ function globalDataDir() {
2059
+ const xdg = process.env.XDG_DATA_HOME;
2060
+ return xdg && xdg.length > 0 ? join6(xdg, "agent-blackbox") : join6(homedir2(), ".local", "share", "agent-blackbox");
2061
+ }
2007
2062
  void main(args);
2008
2063
  async function main(argv) {
2009
2064
  if (argv.includes("--version") || argv.includes("-v")) {
@@ -2020,12 +2075,41 @@ async function main(argv) {
2020
2075
  return;
2021
2076
  }
2022
2077
  if (command === "up") {
2023
- const projectDir = resolve(readFlag(argv, "--project") ?? process.cwd());
2078
+ const projectFlag = readFlag(argv, "--project");
2079
+ const global = projectFlag === void 0;
2024
2080
  const port = Number(readFlag(argv, "--port") ?? "47831");
2025
2081
  const uiPort = Number(readFlag(argv, "--ui-port") ?? "5173");
2026
2082
  const daemonUrl = `http://127.0.0.1:${port}`;
2027
- const adapterPackage = readFlag(argv, "--adapter-package") ?? `file:${resolve(repoRoot, "packages/opencode-adapter")}`;
2028
2083
  const suggest = readSuggestConfig(argv);
2084
+ let daemon;
2085
+ if (global) {
2086
+ if (!pluginBundlePath) {
2087
+ throw new Error("Global install needs the self-contained recorder bundle. Use the published npx package, or `npm run build:cli` then `node packages/cli/dist/cli.js up`.\n(Or scope to one project with: agent-blackbox up --project <dir>.)");
2088
+ }
2089
+ const { pluginPath } = await installGlobalRecorder({ daemonUrl, pluginBundlePath });
2090
+ const dataDir = globalDataDir();
2091
+ const eventsFile = join6(dataDir, "events.ndjson");
2092
+ daemon = await startTraceDaemon({ projectDir: dataDir, port, eventsFile, suggest });
2093
+ const ui2 = await startDashboardServer({ distDir: dashboardDistDir, port: uiPort, daemonUrl });
2094
+ const dashboardUrl2 = `http://127.0.0.1:${ui2.port}`;
2095
+ console.log(`\u2713 Global OpenCode recorder installed: ${pluginPath}`);
2096
+ console.log(`\u2713 Agent-Blackbox is up (recording all OpenCode sessions)`);
2097
+ console.log(` Dashboard: ${dashboardUrl2}`);
2098
+ console.log(` Daemon API: ${daemonUrl} (trace: ${daemon.eventsFile})`);
2099
+ console.log(` Suggestions: ${suggest.mode}${suggest.model ? ` (${suggest.model})` : ""}`);
2100
+ console.log("");
2101
+ if (!argv.includes("--no-open"))
2102
+ openInBrowser(dashboardUrl2);
2103
+ console.log("Now use OpenCode however you already do \u2014 the dashboard fills in live:");
2104
+ console.log(" opencode # in any folder (terminal), or");
2105
+ console.log(" the OpenCode desktop app # open any project");
2106
+ console.log("");
2107
+ console.log("Stop recording any time with: agent-blackbox uninstall");
2108
+ console.log("Press Ctrl+C to stop the daemon + dashboard.");
2109
+ return;
2110
+ }
2111
+ const projectDir = resolve(projectFlag);
2112
+ const adapterPackage = readFlag(argv, "--adapter-package") ?? `file:${resolve(repoRoot, "packages/opencode-adapter")}`;
2029
2113
  try {
2030
2114
  const result = await initOpenCodeProject({
2031
2115
  projectDir,
@@ -2043,7 +2127,7 @@ async function main(argv) {
2043
2127
  throw error;
2044
2128
  }
2045
2129
  }
2046
- const daemon = await startTraceDaemon({ projectDir, port, suggest });
2130
+ daemon = await startTraceDaemon({ projectDir, port, suggest });
2047
2131
  const ui = await startDashboardServer({ distDir: dashboardDistDir, port: uiPort, daemonUrl });
2048
2132
  const dashboardUrl = `http://127.0.0.1:${ui.port}`;
2049
2133
  console.log("");
@@ -2055,11 +2139,29 @@ async function main(argv) {
2055
2139
  if (!argv.includes("--no-open"))
2056
2140
  openInBrowser(dashboardUrl);
2057
2141
  console.log("Now run your agent in that project, e.g.:");
2058
- console.log(` AGENT_BLACKBOX_DAEMON_URL=${daemonUrl} opencode run --dir ${projectDir} "Read the code, run tests, summarize."`);
2142
+ console.log(` opencode # in ${projectDir} (the project-local recorder streams here)`);
2059
2143
  console.log("");
2060
2144
  console.log("Press Ctrl+C to stop.");
2061
2145
  return;
2062
2146
  }
2147
+ if (command === "install") {
2148
+ const port = Number(readFlag(argv, "--port") ?? "47831");
2149
+ const daemonUrl = `http://127.0.0.1:${port}`;
2150
+ if (!pluginBundlePath) {
2151
+ throw new Error("Global install needs the self-contained recorder bundle. Use the published npx package, or `npm run build:cli` first.");
2152
+ }
2153
+ const { pluginPath } = await installGlobalRecorder({ daemonUrl, pluginBundlePath });
2154
+ console.log(`\u2713 Global OpenCode recorder installed: ${pluginPath}`);
2155
+ console.log(` Every OpenCode session (any folder, terminal, or the app) now streams to ${daemonUrl}.`);
2156
+ console.log(` Start the dashboard with: agent-blackbox up`);
2157
+ console.log(` Remove with: agent-blackbox uninstall`);
2158
+ return;
2159
+ }
2160
+ if (command === "uninstall") {
2161
+ const { pluginPath, removed } = await uninstallGlobalRecorder();
2162
+ console.log(removed ? `\u2713 Removed global OpenCode recorder: ${pluginPath}` : `Nothing to remove \u2014 ${pluginPath} is not present.`);
2163
+ return;
2164
+ }
2063
2165
  if (command === "replay") {
2064
2166
  const eventsFile = argv[1];
2065
2167
  if (!eventsFile) {
@@ -2117,8 +2219,11 @@ function printHelp() {
2117
2219
  console.log(describeDaemon());
2118
2220
  console.log("");
2119
2221
  console.log("Usage:");
2120
- console.log(" agent-blackbox up [--project <dir>] [--port <port>] [--ui-port <port>] # plugin + daemon + dashboard, one command");
2121
- console.log(" [--suggest auto|free|off|ollama|opencode|openai-compat] [--suggest-model <id>] [--suggest-base-url <url>] [--optimize] [--no-open]");
2222
+ console.log(" agent-blackbox up # GLOBAL: record every OpenCode session (any folder / the app) + daemon + dashboard");
2223
+ console.log(" agent-blackbox up --project <dir> # scope the recorder to one project instead");
2224
+ console.log(" [--port <port>] [--ui-port <port>] [--suggest auto|free|off|ollama|opencode|openai-compat] [--suggest-model <id>] [--optimize] [--no-open]");
2225
+ console.log(" agent-blackbox install [--port <port>] # install the global recorder only (no daemon)");
2226
+ console.log(" agent-blackbox uninstall # remove the global recorder");
2122
2227
  console.log(" agent-blackbox daemon [--project <dir>] [--port <port>]");
2123
2228
  console.log(" agent-blackbox init-opencode [--project <dir>] [--daemon-url <url>] [--adapter-package <specifier>] [--force] [--optimize]");
2124
2229
  console.log(" agent-blackbox optimize [--project <dir>] [--apply | --check | --revert] # write/measure/rollback AGENTS.md efficiency memory");
package/package.json CHANGED
@@ -1,13 +1,26 @@
1
1
  {
2
2
  "name": "@taewooopark/agent-blackbox",
3
- "version": "0.43.0",
3
+ "version": "0.45.0",
4
4
  "description": "Local-first flight recorder + context-efficiency profiler for coding agents (OpenCode). Run with npx.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
- "repository": { "type": "git", "url": "git+https://github.com/TaewoooPark/Agent-Blackbox.git" },
8
- "bin": { "agent-blackbox": "dist/cli.js" },
9
- "files": ["dist"],
10
- "engines": { "node": ">=20" },
11
- "dependencies": { "ws": "^8.21.0" },
12
- "scripts": { "bundle": "node build.mjs" }
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/TaewoooPark/Agent-Blackbox.git"
10
+ },
11
+ "bin": {
12
+ "agent-blackbox": "dist/cli.js"
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "engines": {
18
+ "node": ">=20"
19
+ },
20
+ "dependencies": {
21
+ "ws": "^8.21.0"
22
+ },
23
+ "scripts": {
24
+ "bundle": "node build.mjs"
25
+ }
13
26
  }