grix-connector 4.0.2 → 4.2.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 (63) hide show
  1. package/dist/adapter/acp/acp-adapter.js +3 -3
  2. package/dist/adapter/acp/session-activity.js +1 -1
  3. package/dist/adapter/claude/claude-bridge-server.js +1 -0
  4. package/dist/adapter/claude/claude-tools.js +1 -0
  5. package/dist/adapter/claude/claude-worker-client.js +1 -0
  6. package/dist/adapter/claude/mcp-http-launcher.js +2 -0
  7. package/dist/adapter/claude/result-timeout.js +1 -0
  8. package/dist/adapter/deepseek/deepseek-adapter.js +6 -0
  9. package/dist/adapter/deepseek/index.js +1 -0
  10. package/dist/adapter/qwen/index.js +1 -0
  11. package/dist/adapter/qwen/qwen-adapter.js +4 -0
  12. package/dist/aibot/client.js +1 -0
  13. package/dist/aibot/index.js +1 -0
  14. package/dist/aibot/types.js +0 -0
  15. package/dist/assets/dsh-bridge/grix-dsh-bridge-4.2.0.tgz +0 -0
  16. package/dist/assets/dsh-bridge/manifest.json +5 -5
  17. package/dist/audit/adapters/agy/agy-audit-adapter.js +1 -1
  18. package/dist/audit/adapters/agy/agy-gen-metadata.js +1 -0
  19. package/dist/bridge/bridge.js +7 -7
  20. package/dist/bridge/lifecycle-barrier.js +1 -1
  21. package/dist/core/access/allowlist-gate.js +1 -0
  22. package/dist/core/access/allowlist-store.js +1 -0
  23. package/dist/core/access/index.js +1 -0
  24. package/dist/core/aibot/connection-manager.js +1 -1
  25. package/dist/core/config/agent-config-repository.js +2 -0
  26. package/dist/core/file-ops/handler.js +1 -0
  27. package/dist/core/file-ops/list-files.js +1 -0
  28. package/dist/core/file-ops/types.js +0 -0
  29. package/dist/core/installer/npm-registry.js +4 -4
  30. package/dist/core/runtime/health.js +1 -1
  31. package/dist/core/skill-sync/skill-syncer.js +1 -1
  32. package/dist/core/upgrade/npm-upgrader.js +2 -2
  33. package/dist/core/upgrade/upgrade-checker.js +1 -1
  34. package/dist/default-skills/grix-agent-dispatch/SKILL.md +9 -9
  35. package/dist/grix.js +7 -7
  36. package/dist/log.js +3 -0
  37. package/dist/main.js +31 -0
  38. package/dist/manager.js +1 -2
  39. package/dist/mcp/stream-http/config.js +1 -0
  40. package/dist/mcp/stream-http/connection-binding.js +1 -0
  41. package/dist/mcp/stream-http/event-tool-executor.js +1 -0
  42. package/dist/mcp/stream-http/gateway.js +1 -0
  43. package/dist/mcp/stream-http/index.js +1 -0
  44. package/dist/mcp/stream-http/security.js +1 -0
  45. package/dist/mcp/stream-http/session-manager.js +1 -0
  46. package/dist/mcp/stream-http/tool-executor.js +1 -0
  47. package/dist/mcp/stream-http/tool-registry.js +1 -0
  48. package/dist/mcp/stream-http/tool-schemas.js +1 -0
  49. package/dist/service/platform-adapter.js +25 -24
  50. package/dist/service/process-control.js +1 -1
  51. package/dist/service/service-manager.js +3 -3
  52. package/dist/service/service-paths.js +2 -2
  53. package/dist/service/windows-wrapper-migration.js +1 -0
  54. package/dist/session/index.js +1 -0
  55. package/dist/session/manager.js +1 -0
  56. package/dist/transport/index.js +1 -0
  57. package/dist/transport/json-rpc.js +3 -0
  58. package/openclaw-plugin/audit-recorder-worker.js +496 -54
  59. package/package.json +2 -1
  60. package/scripts/install-guardian.mjs +35 -19
  61. package/scripts/upgrade-guardian.mjs +1345 -0
  62. package/scripts/upgrade-guardian.sh +100 -75
  63. package/dist/assets/dsh-bridge/grix-dsh-bridge-4.0.2.tgz +0 -0
@@ -773,9 +773,9 @@ async function collectClaudeTranscript(boundary, includeSubagents) {
773
773
  }
774
774
  const subagentRoot = typeof boundary.subagentRoot === "string" ? boundary.subagentRoot : void 0;
775
775
  if (!includeSubagents || !subagentRoot) return evidence;
776
- let paths;
776
+ let paths2;
777
777
  try {
778
- paths = await findSubagentFiles(subagentRoot);
778
+ paths2 = await findSubagentFiles(subagentRoot);
779
779
  } catch (error) {
780
780
  evidence.anomalies.push({
781
781
  code: "claude_subagent_root_unreadable",
@@ -789,7 +789,7 @@ async function collectClaudeTranscript(boundary, includeSubagents) {
789
789
  return evidence;
790
790
  }
791
791
  const offsets = isRecord(boundary.subagentOffsets) ? boundary.subagentOffsets : {};
792
- for (const path of paths) {
792
+ for (const path of paths2) {
793
793
  const fileBoundary = subagentBoundary(offsets[path] ?? offsets[basename(path)]);
794
794
  const result = await readJsonlRange(
795
795
  path,
@@ -1291,7 +1291,7 @@ function groupMessages(job, evidence, anomalies) {
1291
1291
  });
1292
1292
  continue;
1293
1293
  }
1294
- const timestamp5 = asTimestamp(line.record.timestamp, job.startedAt);
1294
+ const timestamp6 = asTimestamp(line.record.timestamp, job.startedAt);
1295
1295
  let group = groups.get(messageId);
1296
1296
  if (!group) {
1297
1297
  group = {
@@ -1301,14 +1301,14 @@ function groupMessages(job, evidence, anomalies) {
1301
1301
  sourcePath: line.sourcePath,
1302
1302
  isSubagent: line.isSubagent,
1303
1303
  promptId: targetPromptId,
1304
- startedAt: timestamp5,
1305
- endedAt: timestamp5,
1304
+ startedAt: timestamp6,
1305
+ endedAt: timestamp6,
1306
1306
  samples: [],
1307
1307
  blocks: []
1308
1308
  };
1309
1309
  groups.set(messageId, group);
1310
1310
  } else {
1311
- group.endedAt = timestamp5;
1311
+ group.endedAt = timestamp6;
1312
1312
  if (typeof line.record.requestId === "string") {
1313
1313
  group.requestId = line.record.requestId;
1314
1314
  }
@@ -2299,9 +2299,9 @@ function stableHash(value) {
2299
2299
  return (hash >>> 0).toString(16).padStart(8, "0");
2300
2300
  }
2301
2301
  function observedAt(value) {
2302
- const timestamp5 = stringValue2(value);
2303
- if (!timestamp5 || Number.isNaN(Date.parse(timestamp5))) return void 0;
2304
- return timestamp5;
2302
+ const timestamp6 = stringValue2(value);
2303
+ if (!timestamp6 || Number.isNaN(Date.parse(timestamp6))) return void 0;
2304
+ return timestamp6;
2305
2305
  }
2306
2306
  function captureOptions2(job) {
2307
2307
  return job.options?.enabled === true ? job.options.capture : DEFAULT_CAPTURE2;
@@ -2816,7 +2816,7 @@ function toSpan(job, candidate, modelId) {
2816
2816
  if (candidate.snapshotKey) {
2817
2817
  nativeIds2.usageSnapshotId = stableHash(candidate.snapshotKey);
2818
2818
  }
2819
- const timestamp5 = candidate.observedAt ?? job.startedAt;
2819
+ const timestamp6 = candidate.observedAt ?? job.startedAt;
2820
2820
  return {
2821
2821
  spanId: `codex-llm-${stableHash(`${job.traceId}|${nativeRequestId}`)}`,
2822
2822
  traceId: job.traceId,
@@ -2827,8 +2827,8 @@ function toSpan(job, candidate, modelId) {
2827
2827
  name: "codex response",
2828
2828
  sequence: candidate.sequence,
2829
2829
  status: "completed",
2830
- startedAt: timestamp5,
2831
- endedAt: timestamp5,
2830
+ startedAt: timestamp6,
2831
+ endedAt: timestamp6,
2832
2832
  ...modelId ? { modelId } : {},
2833
2833
  inputRefs: [],
2834
2834
  outputRefs: [],
@@ -4378,9 +4378,9 @@ function eventTime(value) {
4378
4378
  }
4379
4379
  return void 0;
4380
4380
  }
4381
- function withinTurn(timestamp5, job) {
4382
- if (!timestamp5) return false;
4383
- const at = Date.parse(timestamp5);
4381
+ function withinTurn(timestamp6, job) {
4382
+ if (!timestamp6) return false;
4383
+ const at = Date.parse(timestamp6);
4384
4384
  return at >= Date.parse(job.startedAt) - 5e3 && at <= Date.parse(job.endedAt) + 3e4;
4385
4385
  }
4386
4386
  function contentText2(value) {
@@ -5023,8 +5023,8 @@ function lineEvent(line) {
5023
5023
  return line.record.type === "context.append_loop_event" && isRecord7(line.record.event) ? line.record.event : void 0;
5024
5024
  }
5025
5025
  function withinTurn2(value, job) {
5026
- const timestamp5 = Date.parse(isoTime(value, ""));
5027
- return Number.isFinite(timestamp5) && timestamp5 >= Date.parse(job.startedAt) - 5e3 && timestamp5 <= Date.parse(job.endedAt) + 3e4;
5026
+ const timestamp6 = Date.parse(isoTime(value, ""));
5027
+ return Number.isFinite(timestamp6) && timestamp6 >= Date.parse(job.startedAt) - 5e3 && timestamp6 <= Date.parse(job.endedAt) + 3e4;
5028
5028
  }
5029
5029
  async function readJsonl2(sourcePath) {
5030
5030
  const raw = await readFile4(sourcePath, "utf8");
@@ -8059,7 +8059,7 @@ var DeepSeekHarnessAuditAdapter = class {
8059
8059
  const mapped = mapDshSessionEvent(event);
8060
8060
  const eventSessionId = String(event.sessionId ?? "");
8061
8061
  const isChild = !!eventSessionId && !!rootSessionId && eventSessionId !== rootSessionId;
8062
- const timestamp5 = iso(record4.at, job.startedAt);
8062
+ const timestamp6 = iso(record4.at, job.startedAt);
8063
8063
  if (mapped.kind === "thinking") {
8064
8064
  if (capture.thinking && mapped.text) {
8065
8065
  addContent10(contents, { role: "thinking", format: "text", value: mapped.text, captureLevel: "runtime_exact" });
@@ -8134,9 +8134,9 @@ var DeepSeekHarnessAuditAdapter = class {
8134
8134
  continue;
8135
8135
  }
8136
8136
  tool.span.status = mapped.isError ? "failed" : "completed";
8137
- tool.span.endedAt = timestamp5;
8137
+ tool.span.endedAt = timestamp6;
8138
8138
  const startMs = Date.parse(tool.span.startedAt);
8139
- const endMs = Date.parse(timestamp5);
8139
+ const endMs = Date.parse(timestamp6);
8140
8140
  if (Number.isFinite(startMs) && Number.isFinite(endMs)) {
8141
8141
  tool.span.durationMs = Math.max(0, endMs - startMs);
8142
8142
  }
@@ -8234,7 +8234,7 @@ function turnSpan(job, spanId) {
8234
8234
  };
8235
8235
  }
8236
8236
  function simpleSpan(job, parentSpanId, sequence, kind, name, at, nativeIds2) {
8237
- const timestamp5 = iso(at, job.startedAt);
8237
+ const timestamp6 = iso(at, job.startedAt);
8238
8238
  return {
8239
8239
  spanId: `deepseek-harness:${job.turnId}:${sequence}`,
8240
8240
  traceId: job.traceId,
@@ -8245,8 +8245,8 @@ function simpleSpan(job, parentSpanId, sequence, kind, name, at, nativeIds2) {
8245
8245
  name,
8246
8246
  sequence,
8247
8247
  status: "completed",
8248
- startedAt: timestamp5,
8249
- endedAt: timestamp5,
8248
+ startedAt: timestamp6,
8249
+ endedAt: timestamp6,
8250
8250
  inputRefs: [],
8251
8251
  outputRefs: [],
8252
8252
  provider: { provider: "deepseek-harness", nativeEventType: name, nativeIds: nativeIds2 },
@@ -8306,6 +8306,387 @@ function usageSpan(job, parentSpanId, sequence, at, raw, requestId2, modelId, pr
8306
8306
 
8307
8307
  // src/audit/adapters/agy/agy-audit-adapter.ts
8308
8308
  import { readFile as readFile5 } from "node:fs/promises";
8309
+
8310
+ // src/audit/adapters/agy/agy-gen-metadata.ts
8311
+ import { homedir as homedir4 } from "node:os";
8312
+ import { join as join6 } from "node:path";
8313
+
8314
+ // src/core/util/sqlite-reader.ts
8315
+ import { createRequire } from "node:module";
8316
+
8317
+ // src/core/log/logger.ts
8318
+ import { createWriteStream, mkdirSync, existsSync, readdirSync, statSync, unlinkSync } from "node:fs";
8319
+ import { join as join5 } from "node:path";
8320
+
8321
+ // src/core/config/paths.ts
8322
+ import { join as join4 } from "node:path";
8323
+ import { homedir as homedir3 } from "node:os";
8324
+ var GRIX_HOME_ENV = "GRIX_CONNECTOR_HOME";
8325
+ var DEFAULT_GRIX_HOME = join4(homedir3(), ".grix");
8326
+ function resolveRuntimePaths(runtimeDir) {
8327
+ const rootDir = runtimeDir ? runtimeDir : process.env[GRIX_HOME_ENV] ? process.env[GRIX_HOME_ENV] : DEFAULT_GRIX_HOME;
8328
+ return {
8329
+ rootDir,
8330
+ configDir: join4(rootDir, "config"),
8331
+ logDir: join4(rootDir, "log"),
8332
+ dataDir: join4(rootDir, "data"),
8333
+ serviceDir: join4(rootDir, "service"),
8334
+ skillsDir: join4(rootDir, "skills"),
8335
+ stateFile: join4(rootDir, "service.json"),
8336
+ pidFile: join4(rootDir, "grix-connector.pid"),
8337
+ daemonLockFile: join4(rootDir, "daemon.lock.json"),
8338
+ daemonStatusFile: join4(rootDir, "daemon-status.json"),
8339
+ stdoutLogFile: join4(rootDir, "service", "daemon.out.log"),
8340
+ stderrLogFile: join4(rootDir, "service", "daemon.err.log"),
8341
+ contextsDir: join4(rootDir, "data", "session-contexts"),
8342
+ hookSignalsPath: join4(rootDir, "data", "hook-signals.json"),
8343
+ hookSignalsLogPath: join4(rootDir, "log", "hook-signals.log"),
8344
+ elicitationRequestsDir: join4(rootDir, "data", "elicitation-requests"),
8345
+ eventStatesDir: join4(rootDir, "data", "event-states"),
8346
+ questionRequestsDir: join4(rootDir, "data", "question-requests"),
8347
+ permissionRequestsDir: join4(rootDir, "data", "permission-requests"),
8348
+ agentGlobalConfigsFile: join4(rootDir, "data", "agent-global-configs.json")
8349
+ };
8350
+ }
8351
+
8352
+ // src/core/log/logger.ts
8353
+ var paths = resolveRuntimePaths();
8354
+ var GRIX_PATHS = {
8355
+ base: paths.rootDir,
8356
+ config: paths.configDir,
8357
+ log: paths.logDir,
8358
+ data: paths.dataDir,
8359
+ skills: paths.skillsDir
8360
+ };
8361
+ var LEVEL_PRIORITY = {
8362
+ trace: 0,
8363
+ debug: 1,
8364
+ info: 2,
8365
+ warn: 3,
8366
+ error: 4
8367
+ };
8368
+ function parseLevel(raw, fallback) {
8369
+ if (!raw) return fallback;
8370
+ const lower = raw.trim().toLowerCase();
8371
+ return lower in LEVEL_PRIORITY ? lower : fallback;
8372
+ }
8373
+ function parseTagOverrides(env) {
8374
+ const map = /* @__PURE__ */ new Map();
8375
+ if (!env) return map;
8376
+ for (const pair of env.split(",")) {
8377
+ const eq = pair.indexOf("=");
8378
+ if (eq < 0) continue;
8379
+ const tag = pair.slice(0, eq).trim();
8380
+ const level = parseLevel(pair.slice(eq + 1), "info");
8381
+ if (tag) map.set(tag, level);
8382
+ }
8383
+ return map;
8384
+ }
8385
+ var globalLevel = parseLevel(process.env.GRIX_CONNECTOR_LOG_LEVEL, "info");
8386
+ var tagOverrides = parseTagOverrides(process.env.GRIX_CONNECTOR_LOG_TAG_LEVELS);
8387
+ function effectiveLevel(tag) {
8388
+ return tagOverrides.get(tag) ?? globalLevel;
8389
+ }
8390
+ function shouldLog(tag, level) {
8391
+ return LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[effectiveLevel(tag)];
8392
+ }
8393
+ var logStream = null;
8394
+ var currentLogDate = "";
8395
+ var LOG_RETENTION_DAYS_ENV = "GRIX_CONNECTOR_LOG_RETENTION_DAYS";
8396
+ var DEFAULT_LOG_RETENTION_DAYS = 14;
8397
+ function resolveRetentionDays() {
8398
+ const raw = process.env[LOG_RETENTION_DAYS_ENV];
8399
+ const n2 = raw ? Number.parseInt(raw, 10) : Number.NaN;
8400
+ return Number.isFinite(n2) && n2 > 0 ? n2 : DEFAULT_LOG_RETENTION_DAYS;
8401
+ }
8402
+ function currentDate() {
8403
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8404
+ }
8405
+ function cleanupOldLogs() {
8406
+ const cutoff = Date.now() - resolveRetentionDays() * 24 * 60 * 60 * 1e3;
8407
+ let entries;
8408
+ try {
8409
+ entries = readdirSync(GRIX_PATHS.log);
8410
+ } catch {
8411
+ return;
8412
+ }
8413
+ for (const name of entries) {
8414
+ if (!name.startsWith("grix-connector-") || !name.includes(".log")) continue;
8415
+ const full = join5(GRIX_PATHS.log, name);
8416
+ try {
8417
+ if (statSync(full).mtimeMs < cutoff) unlinkSync(full);
8418
+ } catch {
8419
+ }
8420
+ }
8421
+ }
8422
+ function openLogStream(date) {
8423
+ try {
8424
+ logStream?.end();
8425
+ } catch {
8426
+ }
8427
+ const logFile = join5(GRIX_PATHS.log, `grix-connector-${date}.log`);
8428
+ logStream = createWriteStream(logFile, { flags: "a" });
8429
+ currentLogDate = date;
8430
+ cleanupOldLogs();
8431
+ }
8432
+ function timestamp4() {
8433
+ return (/* @__PURE__ */ new Date()).toISOString().slice(11, 19);
8434
+ }
8435
+ var consoleEnabled = true;
8436
+ function emitConsole(level, line) {
8437
+ if (!consoleEnabled) return;
8438
+ if (level === "warn") console.warn(line);
8439
+ else if (level === "error") console.error(line);
8440
+ else console.log(line);
8441
+ }
8442
+ function safeWrite(line) {
8443
+ try {
8444
+ const date = currentDate();
8445
+ if (date !== currentLogDate) openLogStream(date);
8446
+ logStream?.write(line);
8447
+ } catch {
8448
+ }
8449
+ }
8450
+ function formatLine(level, tag, msg, args) {
8451
+ const levelStr = level === "info" ? "" : `${level.toUpperCase()} `;
8452
+ return `${timestamp4()} [${tag}] ${levelStr}${msg}${args.length ? " " + args.map(String).join(" ") : ""}`;
8453
+ }
8454
+ var log = {
8455
+ trace(tag, msg, ...args) {
8456
+ if (!shouldLog(tag, "trace")) return;
8457
+ const line = formatLine("trace", tag, msg, args);
8458
+ emitConsole("trace", line);
8459
+ safeWrite(line + "\n");
8460
+ },
8461
+ debug(tag, msg, ...args) {
8462
+ if (!shouldLog(tag, "debug")) return;
8463
+ const line = formatLine("debug", tag, msg, args);
8464
+ emitConsole("debug", line);
8465
+ safeWrite(line + "\n");
8466
+ },
8467
+ info(tag, msg, ...args) {
8468
+ if (!shouldLog(tag, "info")) return;
8469
+ const line = formatLine("info", tag, msg, args);
8470
+ emitConsole("info", line);
8471
+ safeWrite(line + "\n");
8472
+ },
8473
+ warn(tag, msg, ...args) {
8474
+ if (!shouldLog(tag, "warn")) return;
8475
+ const line = formatLine("warn", tag, msg, args);
8476
+ emitConsole("warn", line);
8477
+ safeWrite(line + "\n");
8478
+ },
8479
+ error(tag, msg, ...args) {
8480
+ if (!shouldLog(tag, "error")) return;
8481
+ const line = formatLine("error", tag, msg, args);
8482
+ emitConsole("error", line);
8483
+ safeWrite(line + "\n");
8484
+ }
8485
+ };
8486
+
8487
+ // src/core/log/rotation.ts
8488
+ var DEFAULT_LOG_MAX_BYTES = 10 * 1024 * 1024;
8489
+
8490
+ // src/core/log/packet-log.ts
8491
+ var DEFAULT_MAX_BYTES = 128 * 1024 * 1024;
8492
+
8493
+ // src/core/util/sqlite-reader.ts
8494
+ var cachedCtor;
8495
+ function loadDatabaseSync() {
8496
+ if (cachedCtor !== void 0) return cachedCtor;
8497
+ try {
8498
+ const require2 = createRequire(import.meta.url);
8499
+ cachedCtor = require2("node:sqlite").DatabaseSync;
8500
+ } catch {
8501
+ cachedCtor = null;
8502
+ log.warn(
8503
+ "sqlite-reader",
8504
+ `node:sqlite unavailable on Node ${process.version}; sessions stored in sqlite (cursor/opencode) will not be listed`
8505
+ );
8506
+ }
8507
+ return cachedCtor;
8508
+ }
8509
+ function openReadOnlyDatabase(dbPath) {
8510
+ const DatabaseSync = loadDatabaseSync();
8511
+ if (!DatabaseSync) return null;
8512
+ try {
8513
+ const db = new DatabaseSync(dbPath, { readOnly: true });
8514
+ return {
8515
+ all(sql, ...params) {
8516
+ return db.prepare(sql).all(...params);
8517
+ },
8518
+ close() {
8519
+ try {
8520
+ db.close();
8521
+ } catch {
8522
+ }
8523
+ }
8524
+ };
8525
+ } catch {
8526
+ return null;
8527
+ }
8528
+ }
8529
+
8530
+ // src/audit/adapters/agy/agy-gen-metadata.ts
8531
+ function resolveAgyAntigravityHome() {
8532
+ return process.env.GRIX_AGY_ANTIGRAVITY_HOME ?? join6(homedir4(), ".gemini", "antigravity-cli");
8533
+ }
8534
+ function extractAgyResponseIds(logExcerpt) {
8535
+ const ids = [];
8536
+ const seen = /* @__PURE__ */ new Set();
8537
+ for (const line of logExcerpt.split(/\r?\n/)) {
8538
+ if (!line.includes("streamGenerateContent")) continue;
8539
+ const match = /ResponseID: (\S+)/.exec(line);
8540
+ if (!match) continue;
8541
+ const id = match[1];
8542
+ if (!seen.has(id)) {
8543
+ seen.add(id);
8544
+ ids.push(id);
8545
+ }
8546
+ }
8547
+ return ids;
8548
+ }
8549
+ function readVarint(buf, pos) {
8550
+ let value = 0n;
8551
+ let shift = 0n;
8552
+ let cursor = pos;
8553
+ for (; ; ) {
8554
+ if (cursor >= buf.length || shift > 63n) throw new Error("bad varint");
8555
+ const byte = buf[cursor];
8556
+ value |= BigInt(byte & 127) << shift;
8557
+ cursor += 1;
8558
+ if ((byte & 128) === 0) return { value, next: cursor };
8559
+ shift += 7n;
8560
+ }
8561
+ }
8562
+ function parseProtoFields(buf) {
8563
+ const fields = [];
8564
+ let pos = 0;
8565
+ while (pos < buf.length) {
8566
+ const tag = readVarint(buf, pos);
8567
+ pos = tag.next;
8568
+ const field2 = Number(tag.value >> 3n);
8569
+ const wire = Number(tag.value & 0x7n);
8570
+ if (field2 <= 0) throw new Error("bad field number");
8571
+ if (wire === 0) {
8572
+ const v = readVarint(buf, pos);
8573
+ pos = v.next;
8574
+ fields.push({ field: field2, wire, varint: v.value });
8575
+ } else if (wire === 2) {
8576
+ const len = readVarint(buf, pos);
8577
+ pos = len.next;
8578
+ const end = pos + Number(len.value);
8579
+ if (end > buf.length) throw new Error("bad length");
8580
+ fields.push({ field: field2, wire, bytes: buf.subarray(pos, end) });
8581
+ pos = end;
8582
+ } else if (wire === 5) {
8583
+ pos += 4;
8584
+ if (pos > buf.length) throw new Error("bad fixed32");
8585
+ } else if (wire === 1) {
8586
+ pos += 8;
8587
+ if (pos > buf.length) throw new Error("bad fixed64");
8588
+ } else {
8589
+ throw new Error(`unsupported wire type ${wire}`);
8590
+ }
8591
+ }
8592
+ return fields;
8593
+ }
8594
+ function firstMessage(fields, fieldNumber) {
8595
+ const field2 = fields.find((item) => item.field === fieldNumber && item.wire === 2);
8596
+ if (!field2?.bytes) return void 0;
8597
+ try {
8598
+ return parseProtoFields(field2.bytes);
8599
+ } catch {
8600
+ return void 0;
8601
+ }
8602
+ }
8603
+ function firstVarint(fields, fieldNumber) {
8604
+ const field2 = fields.find((item) => item.field === fieldNumber && item.wire === 0);
8605
+ if (field2?.varint === void 0) return void 0;
8606
+ if (field2.varint < 0n || field2.varint > 0xffffffffn) return void 0;
8607
+ return Number(field2.varint);
8608
+ }
8609
+ var RESPONSE_ID_PATTERN = /^[\x21-\x7e]{8,64}$/;
8610
+ function tryDecodeUtf8(bytes) {
8611
+ try {
8612
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
8613
+ } catch {
8614
+ return void 0;
8615
+ }
8616
+ }
8617
+ function firstString(fields, fieldNumber, pattern) {
8618
+ const field2 = fields.find((item) => item.field === fieldNumber && item.wire === 2);
8619
+ if (!field2?.bytes) return void 0;
8620
+ const value = tryDecodeUtf8(field2.bytes);
8621
+ if (value === void 0) return void 0;
8622
+ if (pattern && !pattern.test(value)) return void 0;
8623
+ return value;
8624
+ }
8625
+ function decodeAgyGenMetadata(data) {
8626
+ try {
8627
+ const top = parseProtoFields(data);
8628
+ const record4 = firstMessage(top, 1);
8629
+ if (!record4) return void 0;
8630
+ const usage = firstMessage(record4, 4);
8631
+ if (!usage) return void 0;
8632
+ const responseId = firstString(usage, 11, RESPONSE_ID_PATTERN);
8633
+ if (!responseId) return void 0;
8634
+ return {
8635
+ responseId,
8636
+ inputTokens: firstVarint(usage, 2),
8637
+ outputTokens: firstVarint(usage, 3),
8638
+ model: firstString(record4, 19)
8639
+ };
8640
+ } catch {
8641
+ return void 0;
8642
+ }
8643
+ }
8644
+ var SAFE_CONVERSATION_ID = /^[a-zA-Z0-9._-]+$/;
8645
+ function readAgyTurnUsage(conversationId, responseIds) {
8646
+ if (!SAFE_CONVERSATION_ID.test(conversationId) || responseIds.length === 0) {
8647
+ return null;
8648
+ }
8649
+ const dbPath = join6(
8650
+ resolveAgyAntigravityHome(),
8651
+ "conversations",
8652
+ `${conversationId}.db`
8653
+ );
8654
+ const db = openReadOnlyDatabase(dbPath);
8655
+ if (!db) return null;
8656
+ try {
8657
+ const wanted = new Set(responseIds);
8658
+ const rows = db.all(
8659
+ "SELECT idx, data FROM gen_metadata"
8660
+ );
8661
+ const byResponseId = /* @__PURE__ */ new Map();
8662
+ let model;
8663
+ for (const row of rows) {
8664
+ if (!(row.data instanceof Uint8Array)) continue;
8665
+ const decoded = decodeAgyGenMetadata(row.data);
8666
+ if (!decoded || !wanted.has(decoded.responseId)) continue;
8667
+ const existing = byResponseId.get(decoded.responseId);
8668
+ if (existing && existing.idx >= row.idx) continue;
8669
+ byResponseId.set(decoded.responseId, {
8670
+ idx: row.idx,
8671
+ responseId: decoded.responseId,
8672
+ inputTokens: decoded.inputTokens ?? null,
8673
+ outputTokens: decoded.outputTokens ?? null
8674
+ });
8675
+ model ??= decoded.model;
8676
+ }
8677
+ if (byResponseId.size === 0) return null;
8678
+ const records = Array.from(byResponseId.values()).sort(
8679
+ (left, right) => left.idx - right.idx
8680
+ );
8681
+ return { records, ...model ? { model } : {} };
8682
+ } catch {
8683
+ return null;
8684
+ } finally {
8685
+ db.close();
8686
+ }
8687
+ }
8688
+
8689
+ // src/audit/adapters/agy/agy-audit-adapter.ts
8309
8690
  var DEFAULT_CAPTURE11 = Object.freeze({
8310
8691
  inputOutput: true,
8311
8692
  tools: true,
@@ -8339,7 +8720,7 @@ function append5(target, reference) {
8339
8720
  target.push(reference);
8340
8721
  }
8341
8722
  }
8342
- function timestamp4(value, fallback) {
8723
+ function timestamp5(value, fallback) {
8343
8724
  return typeof value === "string" && Number.isFinite(Date.parse(value)) ? value : fallback;
8344
8725
  }
8345
8726
  function makeSpan8(input) {
@@ -8392,6 +8773,51 @@ function parseToolInvocation(value) {
8392
8773
  ...typeof value.completedAt === "string" ? { completedAt: value.completedAt } : {}
8393
8774
  };
8394
8775
  }
8776
+ function agyUsage(evidence) {
8777
+ const records = evidence.usageRecords;
8778
+ if (!records || records.length === 0) return void 0;
8779
+ let input = 0;
8780
+ let output = 0;
8781
+ for (const record4 of records) {
8782
+ input += record4.inputTokens ?? 0;
8783
+ output += record4.outputTokens ?? 0;
8784
+ }
8785
+ const hasNullTokenRecord = records.some(
8786
+ (record4) => record4.inputTokens === null && record4.outputTokens === null
8787
+ );
8788
+ const complete = evidence.usageExpectedCount !== void 0 && records.length === evidence.usageExpectedCount && !hasNullTokenRecord;
8789
+ return {
8790
+ input: {
8791
+ total: input,
8792
+ uncached: null,
8793
+ cacheRead: null,
8794
+ cacheWrite: null,
8795
+ other: null
8796
+ },
8797
+ output: {
8798
+ total: output,
8799
+ reasoning: null,
8800
+ visible: null
8801
+ },
8802
+ totalProcessed: input + output,
8803
+ requestCount: records.length,
8804
+ accuracy: "provider_reported",
8805
+ completeness: complete ? "complete" : "partial",
8806
+ provider: "agy",
8807
+ providerUsageRaw: records,
8808
+ normalization: {
8809
+ adapter: "agy-gen-metadata",
8810
+ version: 1,
8811
+ formula: "sum of per-generation input_tokens/output_tokens from the agy conversation sqlite gen_metadata table, matched to this turn by streamGenerateContent ResponseID"
8812
+ }
8813
+ };
8814
+ }
8815
+ function agyUsageGapDetail(evidence) {
8816
+ if (evidence.usageExpectedCount === void 0) {
8817
+ return "agy gen_metadata extraction skipped: conversation id or streamGenerateContent log excerpt unavailable";
8818
+ }
8819
+ return `agy gen_metadata extraction found no matching rows for ${evidence.usageExpectedCount} ResponseID(s)`;
8820
+ }
8395
8821
  var AgyAuditAdapter = class {
8396
8822
  provider = "agy";
8397
8823
  async collect(job) {
@@ -8465,6 +8891,16 @@ var AgyAuditAdapter = class {
8465
8891
  });
8466
8892
  }
8467
8893
  }
8894
+ const conversationId = stringValue10(job.boundary.providerSessionId);
8895
+ const responseIds = evidence.logExcerpt ? extractAgyResponseIds(evidence.logExcerpt) : [];
8896
+ if (conversationId && responseIds.length > 0) {
8897
+ evidence.usageExpectedCount = responseIds.length;
8898
+ const usage = readAgyTurnUsage(conversationId, responseIds);
8899
+ if (usage) {
8900
+ evidence.usageRecords = usage.records;
8901
+ if (usage.model) evidence.usageModel = usage.model;
8902
+ }
8903
+ }
8468
8904
  return evidence;
8469
8905
  }
8470
8906
  async normalize(job, rawEvidence) {
@@ -8558,8 +8994,8 @@ var AgyAuditAdapter = class {
8558
8994
  name: invocation.action,
8559
8995
  sequence: sequence++,
8560
8996
  status: invocation.error ? "failed" : invocation.completedAt ? "completed" : "running",
8561
- startedAt: timestamp4(invocation.observedAt, job.startedAt),
8562
- endedAt: timestamp4(invocation.completedAt, job.endedAt),
8997
+ startedAt: timestamp5(invocation.observedAt, job.startedAt),
8998
+ endedAt: timestamp5(invocation.completedAt, job.endedAt),
8563
8999
  nativeEventType: "grix_tool_invoke",
8564
9000
  nativeIds: { toolSequence: String(invocation.sequence) },
8565
9001
  rawAttributes: { toolInvocation: invocation }
@@ -8584,11 +9020,17 @@ var AgyAuditAdapter = class {
8584
9020
  spans.push(tool);
8585
9021
  }
8586
9022
  }
8587
- collection.gaps.push({
8588
- category: "provider_usage",
8589
- reason: "provider_usage_missing",
8590
- detail: "agy print mode does not report token usage"
8591
- });
9023
+ const usage = agyUsage(collection);
9024
+ if (usage) {
9025
+ request.usage = usage;
9026
+ if (collection.usageModel) request.modelId = collection.usageModel;
9027
+ } else {
9028
+ collection.gaps.push({
9029
+ category: "provider_usage",
9030
+ reason: "provider_usage_missing",
9031
+ detail: agyUsageGapDetail(collection)
9032
+ });
9033
+ }
8592
9034
  return {
8593
9035
  spans,
8594
9036
  contents,
@@ -8609,7 +9051,7 @@ var AgyAuditAdapter = class {
8609
9051
  const inputComplete = !evidence.capture.inputOutput || job.input !== void 0 || evidence.collection.prompt !== void 0;
8610
9052
  const outputComplete = !evidence.capture.inputOutput || job.finalOutput !== void 0 || requests.some((request) => request.outputRefs.length > 0);
8611
9053
  const toolCallsComplete = !evidence.capture.tools || tools.every((tool) => tool.status !== "running");
8612
- const usageComplete = false;
9054
+ const usageComplete = requests.length > 0 && requests.every((request) => request.usage?.completeness === "complete");
8613
9055
  const gaps = [...evidence.collection.gaps];
8614
9056
  if (evidence.capture.rawProviderBody) {
8615
9057
  gaps.push({
@@ -8634,7 +9076,7 @@ var AgyAuditAdapter = class {
8634
9076
 
8635
9077
  // src/audit/adapters/openclaw/openclaw-audit-adapter.ts
8636
9078
  import { readFile as readFile6, readdir as readdir4, stat as stat7 } from "node:fs/promises";
8637
- import { basename as basename6, dirname as dirname2, join as join4 } from "node:path";
9079
+ import { basename as basename6, dirname as dirname2, join as join7 } from "node:path";
8638
9080
  function isRecord15(value) {
8639
9081
  return typeof value === "object" && value !== null && !Array.isArray(value);
8640
9082
  }
@@ -8661,7 +9103,7 @@ async function resolveResetTranscriptPath(transcriptPath, expectedIdentity) {
8661
9103
  const prefix = `${basename6(transcriptPath)}.reset`;
8662
9104
  const candidates = (await readdir4(directory)).filter((entry) => entry.startsWith(prefix)).sort().reverse();
8663
9105
  for (const entry of candidates) {
8664
- const candidate = join4(directory, entry);
9106
+ const candidate = join7(directory, entry);
8665
9107
  if (await fileIdentity(candidate) === expectedIdentity) return candidate;
8666
9108
  }
8667
9109
  } catch {
@@ -8676,7 +9118,7 @@ async function resolveCurrentTranscriptPath(boundary) {
8676
9118
  const parsed = JSON.parse(await readFile6(storePath, "utf8"));
8677
9119
  if (!isRecord15(parsed) || !isRecord15(parsed[sessionKey])) return void 0;
8678
9120
  const session = parsed[sessionKey];
8679
- return typeof session.sessionFile === "string" ? session.sessionFile : typeof session.sessionId === "string" ? join4(dirname2(storePath), `${session.sessionId}.jsonl`) : void 0;
9121
+ return typeof session.sessionFile === "string" ? session.sessionFile : typeof session.sessionId === "string" ? join7(dirname2(storePath), `${session.sessionId}.jsonl`) : void 0;
8680
9122
  } catch {
8681
9123
  return void 0;
8682
9124
  }
@@ -8784,7 +9226,7 @@ import {
8784
9226
  rm,
8785
9227
  writeFile
8786
9228
  } from "node:fs/promises";
8787
- import { basename as basename7, dirname as dirname3, join as join5, relative, resolve as resolve3, sep as sep3 } from "node:path";
9229
+ import { basename as basename7, dirname as dirname3, join as join8, relative, resolve as resolve3, sep as sep3 } from "node:path";
8788
9230
  var SHA256_PATTERN = /^[a-f0-9]{64}$/;
8789
9231
  var NO_CAPTURE = Object.freeze({
8790
9232
  inputOutput: false,
@@ -8877,7 +9319,7 @@ var FileAuditReplayStore = class {
8877
9319
  const replaySha256 = sha256(replayBytes);
8878
9320
  const auditKey = idKey(replay.auditId);
8879
9321
  const turnKey = idKey(replay.turnId);
8880
- const replayPath = join5(
9322
+ const replayPath = join8(
8881
9323
  this.rootDir,
8882
9324
  "replays",
8883
9325
  auditKey,
@@ -8943,7 +9385,7 @@ var FileAuditReplayStore = class {
8943
9385
  return this.readReplay(manifest);
8944
9386
  }
8945
9387
  async findByAuditId(auditId) {
8946
- const directory = join5(
9388
+ const directory = join8(
8947
9389
  this.rootDir,
8948
9390
  "manifests",
8949
9391
  "by-audit",
@@ -8952,7 +9394,7 @@ var FileAuditReplayStore = class {
8952
9394
  const names = await readDirectory(directory);
8953
9395
  const replays = [];
8954
9396
  for (const name of names.filter((item) => item.endsWith(".json")).sort()) {
8955
- const manifest = await this.readManifest(join5(directory, name));
9397
+ const manifest = await this.readManifest(join8(directory, name));
8956
9398
  if (!manifest || manifest.auditId !== auditId || manifestExpired(manifest)) {
8957
9399
  continue;
8958
9400
  }
@@ -8961,7 +9403,7 @@ var FileAuditReplayStore = class {
8961
9403
  return sortReplays(replays);
8962
9404
  }
8963
9405
  async findByTurnId(turnId) {
8964
- const directory = join5(
9406
+ const directory = join8(
8965
9407
  this.rootDir,
8966
9408
  "indexes",
8967
9409
  "by-turn",
@@ -8970,7 +9412,7 @@ var FileAuditReplayStore = class {
8970
9412
  const names = await readDirectory(directory);
8971
9413
  const replays = [];
8972
9414
  for (const name of names.filter((item) => item.endsWith(".json")).sort()) {
8973
- const entry = await this.readIndex(join5(directory, name));
9415
+ const entry = await this.readIndex(join8(directory, name));
8974
9416
  if (!entry || entry.turnId !== turnId) continue;
8975
9417
  const manifestPath = this.resolveStoredPath(entry.manifestPath);
8976
9418
  const manifest = await this.readManifest(manifestPath);
@@ -9083,13 +9525,13 @@ var FileAuditReplayStore = class {
9083
9525
  await mkdir(this.rootDir, { recursive: true, mode: 448 });
9084
9526
  }
9085
9527
  async currentManifests() {
9086
- const root = join5(this.rootDir, "manifests", "by-audit");
9528
+ const root = join8(this.rootDir, "manifests", "by-audit");
9087
9529
  const manifests = [];
9088
9530
  for (const auditKey of await readDirectory(root)) {
9089
- const directory = join5(root, auditKey);
9531
+ const directory = join8(root, auditKey);
9090
9532
  for (const name of await readDirectory(directory)) {
9091
9533
  if (!name.endsWith(".json")) continue;
9092
- const path = join5(directory, name);
9534
+ const path = join8(directory, name);
9093
9535
  const manifest = await this.readManifest(path);
9094
9536
  if (manifest) manifests.push({ path, manifest });
9095
9537
  }
@@ -9097,7 +9539,7 @@ var FileAuditReplayStore = class {
9097
9539
  return manifests;
9098
9540
  }
9099
9541
  async revisionManifests(manifest) {
9100
- const directory = join5(
9542
+ const directory = join8(
9101
9543
  this.rootDir,
9102
9544
  "manifests",
9103
9545
  "revisions",
@@ -9107,7 +9549,7 @@ var FileAuditReplayStore = class {
9107
9549
  const revisions = [];
9108
9550
  for (const name of await readDirectory(directory)) {
9109
9551
  if (!name.endsWith(".json")) continue;
9110
- const revision = await this.readManifest(join5(directory, name));
9552
+ const revision = await this.readManifest(join8(directory, name));
9111
9553
  if (revision) revisions.push(revision);
9112
9554
  }
9113
9555
  return revisions;
@@ -9119,14 +9561,14 @@ var FileAuditReplayStore = class {
9119
9561
  rm(this.manifestPath(manifest.auditId, manifest.turnId), {
9120
9562
  force: true
9121
9563
  }),
9122
- rm(join5(
9564
+ rm(join8(
9123
9565
  this.rootDir,
9124
9566
  "manifests",
9125
9567
  "revisions",
9126
9568
  auditKey,
9127
9569
  turnKey
9128
9570
  ), { recursive: true, force: true }),
9129
- rm(join5(this.rootDir, "replays", auditKey, turnKey), {
9571
+ rm(join8(this.rootDir, "replays", auditKey, turnKey), {
9130
9572
  recursive: true,
9131
9573
  force: true
9132
9574
  }),
@@ -9180,7 +9622,7 @@ var FileAuditReplayStore = class {
9180
9622
  async atomicWrite(path, body) {
9181
9623
  const directory = dirname3(path);
9182
9624
  await mkdir(directory, { recursive: true, mode: 448 });
9183
- const temporary = join5(
9625
+ const temporary = join8(
9184
9626
  directory,
9185
9627
  `.${basename7(path)}.${process.pid}.${randomUUID()}.tmp`
9186
9628
  );
@@ -9192,7 +9634,7 @@ var FileAuditReplayStore = class {
9192
9634
  }
9193
9635
  }
9194
9636
  manifestPath(auditId, turnId) {
9195
- return join5(
9637
+ return join8(
9196
9638
  this.rootDir,
9197
9639
  "manifests",
9198
9640
  "by-audit",
@@ -9201,7 +9643,7 @@ var FileAuditReplayStore = class {
9201
9643
  );
9202
9644
  }
9203
9645
  revisionManifestPath(auditId, turnId, revision) {
9204
- return join5(
9646
+ return join8(
9205
9647
  this.rootDir,
9206
9648
  "manifests",
9207
9649
  "revisions",
@@ -9211,7 +9653,7 @@ var FileAuditReplayStore = class {
9211
9653
  );
9212
9654
  }
9213
9655
  turnIndexPath(turnId, auditId) {
9214
- return join5(
9656
+ return join8(
9215
9657
  this.rootDir,
9216
9658
  "indexes",
9217
9659
  "by-turn",
@@ -9220,7 +9662,7 @@ var FileAuditReplayStore = class {
9220
9662
  );
9221
9663
  }
9222
9664
  blobPath(contentId) {
9223
- return join5(
9665
+ return join8(
9224
9666
  this.rootDir,
9225
9667
  "blobs",
9226
9668
  "sha256",