@legioncodeinc/honeycomb 0.1.8 → 0.1.10

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/daemon/index.js CHANGED
@@ -7369,7 +7369,7 @@ var require_dist = __commonJS({
7369
7369
  // dist/src/shared/constants.js
7370
7370
  var DAEMON_PORT = 3850;
7371
7371
  var DAEMON_HOST = "127.0.0.1";
7372
- var HONEYCOMB_VERSION = true ? "0.1.8" : "0.0.0-dev";
7372
+ var HONEYCOMB_VERSION = true ? "0.1.10" : "0.0.0-dev";
7373
7373
 
7374
7374
  // node_modules/zod/v4/classic/external.js
7375
7375
  var external_exports = {};
@@ -22440,7 +22440,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
22440
22440
  });
22441
22441
  if (!chunk) {
22442
22442
  if (i === 1) {
22443
- await new Promise((resolve6) => setTimeout(resolve6));
22443
+ await new Promise((resolve7) => setTimeout(resolve7));
22444
22444
  maxReadCount = 3;
22445
22445
  continue;
22446
22446
  }
@@ -22593,7 +22593,7 @@ async function startDaemon(daemon) {
22593
22593
  let server;
22594
22594
  let boundPort = daemon.config.port;
22595
22595
  try {
22596
- server = await new Promise((resolve6, reject) => {
22596
+ server = await new Promise((resolve7, reject) => {
22597
22597
  let handle;
22598
22598
  try {
22599
22599
  handle = serve({
@@ -22602,7 +22602,7 @@ async function startDaemon(daemon) {
22602
22602
  port: daemon.config.port
22603
22603
  }, (info) => {
22604
22604
  boundPort = info.port;
22605
- resolve6(handle);
22605
+ resolve7(handle);
22606
22606
  });
22607
22607
  handle.on?.("error", (err) => reject(err));
22608
22608
  } catch (err) {
@@ -22617,13 +22617,13 @@ async function startDaemon(daemon) {
22617
22617
  return {
22618
22618
  address: { host: daemon.config.host, port: boundPort },
22619
22619
  async close() {
22620
- await new Promise((resolve6, reject) => {
22620
+ await new Promise((resolve7, reject) => {
22621
22621
  server.close((err) => {
22622
22622
  if (err) {
22623
22623
  reject(err instanceof Error ? err : new Error(String(err)));
22624
22624
  return;
22625
22625
  }
22626
- resolve6();
22626
+ resolve7();
22627
22627
  });
22628
22628
  });
22629
22629
  await daemon.stopServices();
@@ -25690,6 +25690,14 @@ var SESSIONS_COLUMNS = Object.freeze([
25690
25690
  { name: "output_tokens", sql: "BIGINT" },
25691
25691
  { name: "cache_read_input_tokens", sql: "BIGINT" },
25692
25692
  { name: "cache_creation_input_tokens", sql: "BIGINT" },
25693
+ // ── PRD-060 ROI fix: the per-turn MODEL id ────────────────────────────────────
25694
+ // The model the turn ran on (e.g. `claude-opus-4-8`), read from the Claude Code
25695
+ // transcript so the ROI dashboard prices the turn at its REAL model's rate instead of
25696
+ // the Sonnet default (`rowToCapturedTurn` reads this; `resolveRate` does the rest).
25697
+ // Additive, healed in via the SAME `ALTER TABLE ADD COLUMN … DEFAULT ''` path as the
25698
+ // 060a columns. TEXT NOT NULL DEFAULT '' — heal-safe on a populated legacy table because
25699
+ // the empty string backfills, and `'' = "model unknown"` (the model-absent encoding).
25700
+ { name: "model", sql: "TEXT NOT NULL DEFAULT ''" },
25693
25701
  // The capture-source discriminant (a-AC-7): every Claude-Code row carries
25694
25702
  // `source_tool = 'claude-code'`, so 060b/060e can render a "Claude Code only"
25695
25703
  // partial state. NOT NULL DEFAULT '' (a discriminant always present; '' = unknown
@@ -27827,8 +27835,9 @@ function createEmbedSupervisor(deps = {}) {
27827
27835
  const cfg = resolveConfig2(deps.config);
27828
27836
  const spawnChild = deps.spawnChild ?? defaultSpawnChild(env);
27829
27837
  const probeHealth = deps.probeHealth ?? defaultProbeHealth(env);
27830
- const disabled = !resolveEmbedClientOptions(env).enabled;
27838
+ let enabled = deps.enabled ?? resolveEmbedClientOptions(env).enabled;
27831
27839
  let started = false;
27840
+ let lifecycleStarted = false;
27832
27841
  let stopping = false;
27833
27842
  let child = null;
27834
27843
  let live = false;
@@ -27899,7 +27908,7 @@ function createEmbedSupervisor(deps = {}) {
27899
27908
  return;
27900
27909
  await spawnAndWatch();
27901
27910
  }
27902
- return {
27911
+ const api = {
27903
27912
  get live() {
27904
27913
  return live;
27905
27914
  },
@@ -27907,16 +27916,17 @@ function createEmbedSupervisor(deps = {}) {
27907
27916
  return warm;
27908
27917
  },
27909
27918
  get disabled() {
27910
- return disabled;
27919
+ return !enabled;
27911
27920
  },
27912
27921
  get restarts() {
27913
27922
  return restarts;
27914
27923
  },
27915
27924
  async start() {
27925
+ lifecycleStarted = true;
27916
27926
  if (started)
27917
27927
  return;
27918
27928
  started = true;
27919
- if (disabled) {
27929
+ if (!enabled) {
27920
27930
  logger.event("embed.disabled");
27921
27931
  return;
27922
27932
  }
@@ -27958,12 +27968,29 @@ function createEmbedSupervisor(deps = {}) {
27958
27968
  live = false;
27959
27969
  warm = false;
27960
27970
  restarts = 0;
27961
- if (disabled || stopping)
27971
+ if (!enabled || stopping)
27962
27972
  return;
27963
27973
  logger.event("embed.manual_restart");
27964
27974
  await spawnAndWatch();
27975
+ },
27976
+ async setEnabled(want) {
27977
+ enabled = want;
27978
+ if (want) {
27979
+ logger.event("embed.enabled");
27980
+ if (!lifecycleStarted)
27981
+ return;
27982
+ if (child === null) {
27983
+ started = false;
27984
+ await api.start();
27985
+ }
27986
+ } else {
27987
+ logger.event("embed.disabled_live");
27988
+ if (child !== null)
27989
+ await api.stop();
27990
+ }
27965
27991
  }
27966
27992
  };
27993
+ return api;
27967
27994
  }
27968
27995
  var noopEmbedSupervisor = {
27969
27996
  live: false,
@@ -27975,6 +28002,8 @@ var noopEmbedSupervisor = {
27975
28002
  stop() {
27976
28003
  },
27977
28004
  async restart() {
28005
+ },
28006
+ async setEnabled() {
27978
28007
  }
27979
28008
  };
27980
28009
 
@@ -27983,7 +28012,9 @@ function buildHealthDetail(inputs) {
27983
28012
  const reasons = {
27984
28013
  storage: inputs.status === "ok" ? "reachable" : "unreachable",
27985
28014
  embeddings: inputs.embeddingsEnabled ? "on" : "off",
27986
- schema: inputs.schemaMissingTable === true ? "missing_table" : "ok"
28015
+ schema: inputs.schemaMissingTable === true ? "missing_table" : "ok",
28016
+ // PRD-063b / b-AC-7: read the supplied Portkey state verbatim (no probe). Omitted → `off`.
28017
+ portkey: inputs.portkey ?? "off"
27987
28018
  };
27988
28019
  return { status: inputs.status, reasons };
27989
28020
  }
@@ -28018,6 +28049,10 @@ var ROUTE_GROUPS = Object.freeze([
28018
28049
  { path: "/api/org", protect: true, session: false },
28019
28050
  { path: "/api/workspace", protect: true, session: false },
28020
28051
  { path: "/api/diagnostics", protect: true, session: false },
28052
+ // The dashboard imperative-actions surface (logout / embeddings / restart / uninstall). Protected
28053
+ // (inherits auth/RBAC) AND additionally local-mode + origin/CSRF gated inside the handlers
28054
+ // (`dashboard/actions-api.ts`), since these are credential/process/lifecycle actions.
28055
+ { path: "/api/actions", protect: true, session: false },
28021
28056
  { path: "/api/pipeline", protect: true, session: false },
28022
28057
  { path: "/api/repair", protect: true, session: false },
28023
28058
  { path: "/api/inference", protect: true, session: false },
@@ -28155,7 +28190,7 @@ function coarsePipelineStatus(storage) {
28155
28190
  }
28156
28191
 
28157
28192
  // dist/src/daemon/runtime/assemble.js
28158
- import { mkdirSync as mkdirSync20, readFileSync as readFileSync22, rmSync as rmSync9, writeFileSync as writeFileSync17 } from "node:fs";
28193
+ import { mkdirSync as mkdirSync20, mkdtempSync, readFileSync as readFileSync23, rmSync as rmSync10, writeFileSync as writeFileSync17 } from "node:fs";
28159
28194
  import { homedir as homedir25 } from "node:os";
28160
28195
  import { join as join32 } from "node:path";
28161
28196
 
@@ -28583,7 +28618,7 @@ function buildAllowedProperties(input) {
28583
28618
  }
28584
28619
  var systemTelemetryClock = () => (/* @__PURE__ */ new Date()).toISOString();
28585
28620
  var DEFAULT_EMIT_TIMEOUT_MS = 2e3;
28586
- var HONEYCOMB_VERSION2 = true ? "0.1.8" : "0.0.0-dev";
28621
+ var HONEYCOMB_VERSION2 = true ? "0.1.10" : "0.0.0-dev";
28587
28622
  async function emitTelemetry(event, opts, deps = {}) {
28588
28623
  const env = deps.env ?? process.env;
28589
28624
  const key = deps.posthogKey ?? POSTHOG_KEY;
@@ -28653,7 +28688,7 @@ async function postCapture(event, properties, distinctId, key, deps) {
28653
28688
  }
28654
28689
 
28655
28690
  // dist/src/daemon/runtime/auth/deeplake-issuer.js
28656
- var realSleeper = (ms) => new Promise((resolve6) => setTimeout(resolve6, ms));
28691
+ var realSleeper = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms));
28657
28692
  var DEEPLAKE_CLIENT_HEADER = "X-Deeplake-Client";
28658
28693
  var DEEPLAKE_ORG_HEADER = "X-Activeloop-Org-Id";
28659
28694
  var DEEPLAKE_CLIENT_VALUE = "honeycomb";
@@ -29181,7 +29216,7 @@ function resolveRequestScope(input) {
29181
29216
 
29182
29217
  // dist/src/daemon/runtime/auth/device-flow.js
29183
29218
  import { timingSafeEqual as timingSafeEqual2 } from "node:crypto";
29184
- var realSleeper2 = (ms) => new Promise((resolve6) => setTimeout(resolve6, ms));
29219
+ var realSleeper2 = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms));
29185
29220
  var DEFAULT_MAX_POLLS2 = 900;
29186
29221
  function reporterOf(deps) {
29187
29222
  return deps.reporter ?? { prompt: (line) => console.log(line) };
@@ -29963,7 +29998,7 @@ function recursEnough(pairs) {
29963
29998
  }
29964
29999
  var systemGateSpawner = {
29965
30000
  run(spec, prompt, timeoutMs) {
29966
- return new Promise((resolve6, reject) => {
30001
+ return new Promise((resolve7, reject) => {
29967
30002
  const child = spawn2(spec.command, [...spec.args], { shell: false, windowsHide: true });
29968
30003
  let stdout = "";
29969
30004
  let settled = false;
@@ -29987,7 +30022,7 @@ var systemGateSpawner = {
29987
30022
  child.on("error", (err) => finish(() => reject(err)));
29988
30023
  child.on("close", (code) => {
29989
30024
  if (code === 0)
29990
- finish(() => resolve6(stdout));
30025
+ finish(() => resolve7(stdout));
29991
30026
  else
29992
30027
  finish(() => reject(new Error(`skillify gate CLI exited with code ${code ?? "null"}`)));
29993
30028
  });
@@ -30091,7 +30126,7 @@ function uniqueSessionIds(pairs) {
30091
30126
  return out;
30092
30127
  }
30093
30128
  function withTimeout(promise2, timeoutMs, message) {
30094
- return new Promise((resolve6, reject) => {
30129
+ return new Promise((resolve7, reject) => {
30095
30130
  let settled = false;
30096
30131
  const timer = setTimeout(() => {
30097
30132
  if (settled)
@@ -30104,7 +30139,7 @@ function withTimeout(promise2, timeoutMs, message) {
30104
30139
  return;
30105
30140
  settled = true;
30106
30141
  clearTimeout(timer);
30107
- resolve6(v);
30142
+ resolve7(v);
30108
30143
  }, (e) => {
30109
30144
  if (settled)
30110
30145
  return;
@@ -30479,7 +30514,7 @@ function buildSummaryPrompt(session, events) {
30479
30514
  }
30480
30515
  var systemSummarySpawner = {
30481
30516
  run(spec, prompt, timeoutMs) {
30482
- return new Promise((resolve6, reject) => {
30517
+ return new Promise((resolve7, reject) => {
30483
30518
  const child = spawn3(spec.command, [...spec.args], {
30484
30519
  shell: false,
30485
30520
  windowsHide: true,
@@ -30515,7 +30550,7 @@ var systemSummarySpawner = {
30515
30550
  child.on("error", (err) => finish(() => reject(err)));
30516
30551
  child.on("close", (code) => {
30517
30552
  if (code === 0)
30518
- finish(() => resolve6(stdout));
30553
+ finish(() => resolve7(stdout));
30519
30554
  else
30520
30555
  finish(() => reject(new Error(`summary gate CLI exited with code ${code ?? "null"}`)));
30521
30556
  });
@@ -30536,7 +30571,7 @@ function createHostSummaryGenCli(spec, spawner = systemSummarySpawner, timeoutMs
30536
30571
  }
30537
30572
  var systemSleeper = {
30538
30573
  sleep(ms) {
30539
- return new Promise((resolve6) => setTimeout(resolve6, ms));
30574
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
30540
30575
  }
30541
30576
  };
30542
30577
  async function runSummaryWorker(trigger, session, deps) {
@@ -31183,7 +31218,13 @@ var AssistantMessageEventSchema = external_exports.object({
31183
31218
  kind: external_exports.literal("assistant_message"),
31184
31219
  text: external_exports.string(),
31185
31220
  /** PRD-060a: optional per-turn token + cache counts; absent when unavailable. */
31186
- usage: TurnUsageSchema
31221
+ usage: TurnUsageSchema,
31222
+ /**
31223
+ * PRD-060 ROI fix: the optional per-turn model id. A blank/whitespace value is treated as
31224
+ * ABSENT (transformed to `undefined`) so an empty string is never persisted — the column
31225
+ * stays `''` = "model unknown" rather than carrying a meaningless empty model.
31226
+ */
31227
+ model: external_exports.string().optional().transform((m) => m !== void 0 && m.trim() !== "" ? m.trim() : void 0)
31187
31228
  });
31188
31229
  var CaptureEventSchema = external_exports.discriminatedUnion("kind", [
31189
31230
  UserMessageEventSchema,
@@ -31621,6 +31662,11 @@ var CaptureRouteHandler = class {
31621
31662
  // canonical harness token the shim stamps (`claude-code` for the reference
31622
31663
  // shim), so every Claude-Code-captured row carries `source_tool='claude-code'`.
31623
31664
  ["source_tool", val.str(meta3.agent)],
31665
+ // PRD-060 ROI fix: the per-turn model id (e.g. `claude-opus-4-8`) read from the
31666
+ // transcript, so the dashboard prices the turn at its real model's rate. An absent
31667
+ // model writes `''` ("model unknown" — the column default); a present model writes the
31668
+ // id via the typed `val.str` SQL guard. Carried on the SAME append-only INSERT.
31669
+ ["model", val.str(modelFor(event))],
31624
31670
  ["creation_date", val.str(nowIso10)],
31625
31671
  ["last_update_date", val.str(nowIso10)]
31626
31672
  ];
@@ -31785,6 +31831,9 @@ function usageColumns(event) {
31785
31831
  cols.push(["cache_creation_input_tokens", u.cacheCreation]);
31786
31832
  return cols;
31787
31833
  }
31834
+ function modelFor(event) {
31835
+ return event.kind === "assistant_message" && event.model !== void 0 ? event.model : "";
31836
+ }
31788
31837
  function groupRowsByScope(batch) {
31789
31838
  const byKey = /* @__PURE__ */ new Map();
31790
31839
  for (const item of batch) {
@@ -33779,6 +33828,11 @@ async function runGraphBuild(identity, scope, options) {
33779
33828
  push: push.kind
33780
33829
  };
33781
33830
  }
33831
+ async function buildCodebaseGraphSnapshot(scope, options) {
33832
+ const workspaceDir = options.workspaceDir ?? process.cwd();
33833
+ const identity = options.identity ?? resolveSnapshotIdentity(workspaceDir, scope);
33834
+ return runGraphBuild(identity, scope, options);
33835
+ }
33782
33836
  function mountGraphApi(daemon, options) {
33783
33837
  const group = daemon.group(GRAPH_GROUP);
33784
33838
  if (group === void 0)
@@ -35696,7 +35750,7 @@ function modeledMemoryInjectionSavings(sessions, rate = resolveRate(void 0, void
35696
35750
  }
35697
35751
 
35698
35752
  // dist/src/daemon/runtime/dashboard/roi-billing.js
35699
- var realSleeper3 = (ms) => new Promise((resolve6) => setTimeout(resolve6, ms));
35753
+ var realSleeper3 = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms));
35700
35754
  var systemBillingClock = {
35701
35755
  now() {
35702
35756
  return Date.now();
@@ -36178,30 +36232,35 @@ async function selectRows2(storage, sql, scope) {
36178
36232
  return isOk(result) ? result.rows : [];
36179
36233
  }
36180
36234
  var CHARS_PER_TOKEN2 = 4;
36181
- async function fetchKpisView(storage, scope) {
36235
+ async function fetchKpiCounts(storage, scope, projectId) {
36182
36236
  const memTbl = sqlIdent("memories");
36183
36237
  const sessTbl = sqlIdent("sessions");
36184
- const [memRows, sessRows, savingsRows, teamSkillRows] = await Promise.all([
36185
- selectRows2(storage, `SELECT COUNT(*) AS n FROM "${memTbl}"`, scope),
36186
- selectRows2(storage, `SELECT COUNT(*) AS n FROM "${sessTbl}"`, scope),
36187
- selectRows2(storage, buildEstimatedSavingsSql(), scope),
36238
+ const projClause = projectWhereClause(projectId);
36239
+ const [memRows, sessRows, teamSkillRows] = await Promise.all([
36240
+ selectRows2(storage, `SELECT COUNT(*) AS n FROM "${memTbl}"${projClause}`, scope),
36241
+ selectRows2(storage, `SELECT COUNT(*) AS n FROM "${sessTbl}"${projClause}`, scope),
36188
36242
  selectRows2(storage, buildTeamSkillCountSql(), scope)
36189
36243
  ]);
36190
36244
  const sessionCount = toNum2(sessRows[0]?.n);
36191
- const estimatedSavings = Math.floor(toNum2(savingsRows[0]?.chars) / CHARS_PER_TOKEN2);
36192
36245
  return {
36193
36246
  memoryCount: toNum2(memRows[0]?.n),
36194
36247
  // 035a: same value, two names — `sessionCount` kept (additive), `turnCount` is what the UI reads.
36195
36248
  sessionCount,
36196
36249
  turnCount: sessionCount,
36197
- estimatedSavings,
36198
36250
  teamSkillCount: toNum2(teamSkillRows[0]?.n)
36199
36251
  };
36200
36252
  }
36201
- function buildEstimatedSavingsSql() {
36253
+ async function fetchEstimatedSavings(storage, scope, projectId) {
36254
+ const savingsRows = await selectRows2(storage, buildEstimatedSavingsSql(projectId), scope);
36255
+ return Math.floor(toNum2(savingsRows[0]?.chars) / CHARS_PER_TOKEN2);
36256
+ }
36257
+ function buildEstimatedSavingsSql(projectId) {
36202
36258
  const tbl = sqlIdent("memories");
36203
36259
  const col = sqlIdent("content");
36204
- return `SELECT SUM(LENGTH(${col})) AS chars FROM "${tbl}"`;
36260
+ return `SELECT SUM(LENGTH(${col})) AS chars FROM "${tbl}"${projectWhereClause(projectId)}`;
36261
+ }
36262
+ function projectWhereClause(projectId) {
36263
+ return projectId !== void 0 && projectId !== "" ? ` WHERE ${sqlIdent("project_id")} = ${sLiteral(projectId)}` : "";
36205
36264
  }
36206
36265
  function buildTeamSkillCountSql() {
36207
36266
  const tbl = sqlIdent(SYNCED_ASSETS_TABLE);
@@ -36362,11 +36421,15 @@ function tokenCountOrNull(value) {
36362
36421
  }
36363
36422
  function rowToCapturedTurn(r) {
36364
36423
  const sourceTool = toStr2(r.source_tool);
36424
+ const model = toStr2(r.model);
36425
+ const isAnthropic = sourceTool === "claude-code" || model.startsWith("claude-");
36365
36426
  return {
36366
36427
  input_tokens: tokenCountOrNull(r.input_tokens),
36367
36428
  output_tokens: tokenCountOrNull(r.output_tokens),
36368
36429
  cache_read_input_tokens: tokenCountOrNull(r.cache_read_input_tokens),
36369
36430
  cache_creation_input_tokens: tokenCountOrNull(r.cache_creation_input_tokens),
36431
+ ...model !== "" ? { model } : {},
36432
+ ...model !== "" && isAnthropic ? { provider: "anthropic" } : {},
36370
36433
  ...sourceTool !== "" ? { sourceTool } : {}
36371
36434
  };
36372
36435
  }
@@ -36375,8 +36438,8 @@ async function readCapturedTurns(storage, scope, projectId) {
36375
36438
  const tbl = sqlIdent("sessions");
36376
36439
  const dateCol = sqlIdent("creation_date");
36377
36440
  const idCol = sqlIdent("id");
36378
- const projClause = projectId !== void 0 && projectId !== "" ? ` WHERE ${sqlIdent("project_id")} = ${sLiteral(projectId)}` : "";
36379
- const sql = `SELECT ${sqlIdent("input_tokens")}, ${sqlIdent("output_tokens")}, ${sqlIdent("cache_read_input_tokens")}, ${sqlIdent("cache_creation_input_tokens")}, ${sqlIdent("source_tool")} FROM "${tbl}"${projClause} ORDER BY ${dateCol} DESC, ${idCol} DESC LIMIT ${ROI_SESSIONS_LIMIT}`;
36441
+ const projClause = projectWhereClause(projectId);
36442
+ const sql = `SELECT ${sqlIdent("input_tokens")}, ${sqlIdent("output_tokens")}, ${sqlIdent("cache_read_input_tokens")}, ${sqlIdent("cache_creation_input_tokens")}, ${sqlIdent("source_tool")}, ${sqlIdent("model")} FROM "${tbl}"${projClause} ORDER BY ${dateCol} DESC, ${idCol} DESC LIMIT ${ROI_SESSIONS_LIMIT}`;
36380
36443
  const rows = await selectRows2(storage, sql, scope);
36381
36444
  return rows.map(rowToCapturedTurn);
36382
36445
  }
@@ -36524,22 +36587,34 @@ function mountDashboardApi(daemon, options) {
36524
36587
  const resolveScope5 = (c) => resolveScopeOrLocalDefault(c, daemon.config.mode, options.defaultScope);
36525
36588
  const kpis = daemon.group(DASHBOARD_GROUPS.kpis);
36526
36589
  if (kpis !== void 0) {
36590
+ const countsCache = createTtlViewCache(DIAG_TTL_MS);
36591
+ const savingsCache = createTtlViewCache(SAVINGS_TTL_MS);
36527
36592
  kpis.get("/kpis", async (c) => {
36528
36593
  const scope = resolveScope5(c);
36529
36594
  if (scope === null)
36530
36595
  return c.json(NO_ORG_BODY4, 400);
36531
- return c.json(await fetchKpisView(storage, scope));
36596
+ const project = resolveRequestProject(c, scope);
36597
+ const projectId = project.degraded ? void 0 : project.projectId;
36598
+ const key = scopeCacheKey(scope, projectId);
36599
+ const [counts, estimatedSavings] = await Promise.all([
36600
+ countsCache(key, () => fetchKpiCounts(storage, scope, projectId)),
36601
+ savingsCache(key, () => fetchEstimatedSavings(storage, scope, projectId))
36602
+ ]);
36603
+ return c.json({ ...counts, estimatedSavings });
36532
36604
  });
36533
36605
  }
36534
36606
  const sessions = daemon.group(DASHBOARD_GROUPS.sessions);
36535
36607
  if (sessions !== void 0) {
36608
+ const sessionsCache = createTtlViewCache(DIAG_TTL_MS);
36536
36609
  sessions.get("/sessions", async (c) => {
36537
36610
  const scope = resolveScope5(c);
36538
36611
  if (scope === null)
36539
36612
  return c.json(NO_ORG_BODY4, 400);
36613
+ const cursorRaw = c.req.query("cursor");
36540
36614
  const limit = resolveSessionsLimit(c.req.query("limit"));
36541
- const before = decodeSessionsCursor(c.req.query("cursor"));
36542
- return c.json(await fetchSessionsView(storage, scope, before !== void 0 ? { limit, before } : { limit }));
36615
+ const before = decodeSessionsCursor(cursorRaw);
36616
+ const key = scopeCacheKey(scope, String(limit), cursorRaw);
36617
+ return c.json(await sessionsCache(key, () => fetchSessionsView(storage, scope, before !== void 0 ? { limit, before } : { limit })));
36543
36618
  });
36544
36619
  }
36545
36620
  const settings = daemon.group(DASHBOARD_GROUPS.settings);
@@ -36562,20 +36637,22 @@ function mountDashboardApi(daemon, options) {
36562
36637
  }
36563
36638
  const rules = daemon.group(DASHBOARD_GROUPS.rules);
36564
36639
  if (rules !== void 0) {
36640
+ const rulesCache = createTtlViewCache(DIAG_TTL_MS);
36565
36641
  rules.get("/rules", async (c) => {
36566
36642
  const scope = resolveScope5(c);
36567
36643
  if (scope === null)
36568
36644
  return c.json(NO_ORG_BODY4, 400);
36569
- return c.json(await fetchRulesView(storage, scope));
36645
+ return c.json(await rulesCache(scopeCacheKey(scope), () => fetchRulesView(storage, scope)));
36570
36646
  });
36571
36647
  }
36572
36648
  const skills = daemon.group(DASHBOARD_GROUPS.skills);
36573
36649
  if (skills !== void 0) {
36650
+ const skillsCache = createTtlViewCache(DIAG_TTL_MS);
36574
36651
  skills.get("/skills", async (c) => {
36575
36652
  const scope = resolveScope5(c);
36576
36653
  if (scope === null)
36577
36654
  return c.json(NO_ORG_BODY4, 400);
36578
- return c.json(await fetchSkillSyncView(storage, scope));
36655
+ return c.json(await skillsCache(scopeCacheKey(scope), () => fetchSkillSyncView(storage, scope)));
36579
36656
  });
36580
36657
  }
36581
36658
  const installedAssets = daemon.group(DASHBOARD_GROUPS.installedAssets);
@@ -36626,6 +36703,535 @@ function createInventoryCache() {
36626
36703
  return value;
36627
36704
  };
36628
36705
  }
36706
+ var DIAG_TTL_MS = 1e4;
36707
+ var SAVINGS_TTL_MS = 6e4;
36708
+ var CACHE_MAX_KEYS = 64;
36709
+ function scopeCacheKey(scope, ...extra) {
36710
+ return [scope.org, scope.workspace ?? "", ...extra.map((e) => e ?? "")].join("\0");
36711
+ }
36712
+ function createTtlViewCache(ttlMs) {
36713
+ const cache = /* @__PURE__ */ new Map();
36714
+ return async (key, compute) => {
36715
+ const now = Date.now();
36716
+ const hit = cache.get(key);
36717
+ if (hit !== void 0 && now - hit.at < ttlMs)
36718
+ return hit.value;
36719
+ const value = await compute();
36720
+ if (cache.size >= CACHE_MAX_KEYS && !cache.has(key))
36721
+ cache.clear();
36722
+ cache.set(key, { value, at: now });
36723
+ return value;
36724
+ };
36725
+ }
36726
+
36727
+ // dist/src/daemon/runtime/dashboard/actions-api.js
36728
+ import { spawn as spawn4 } from "node:child_process";
36729
+ import { rmSync as rmSync5 } from "node:fs";
36730
+ import { dirname as dirname12, resolve as resolve5 } from "node:path";
36731
+
36732
+ // dist/src/daemon/runtime/secrets/api.js
36733
+ function localDefaultScopeResolver(mode, defaultScope) {
36734
+ return {
36735
+ resolve(c) {
36736
+ const fromHeader = headerScopeResolver.resolve(c);
36737
+ if (fromHeader !== null)
36738
+ return fromHeader;
36739
+ if (mode === "local" && defaultScope !== void 0) {
36740
+ return { org: defaultScope.org, workspace: defaultScope.workspace ?? "default" };
36741
+ }
36742
+ return null;
36743
+ }
36744
+ };
36745
+ }
36746
+ var headerScopeResolver = {
36747
+ resolve(c) {
36748
+ const org = c.req.header("x-honeycomb-org");
36749
+ if (org === void 0 || org.length === 0)
36750
+ return null;
36751
+ const workspace = c.req.header("x-honeycomb-workspace");
36752
+ const agentId = c.req.header("x-honeycomb-agent");
36753
+ const ws = workspace !== void 0 && workspace.length > 0 ? workspace : "default";
36754
+ return agentId !== void 0 && agentId.length > 0 ? { org, workspace: ws, agentId } : { org, workspace: ws };
36755
+ }
36756
+ };
36757
+ function mountSecretsApi(group, deps) {
36758
+ const scope = deps.scope ?? headerScopeResolver;
36759
+ const store = deps.store;
36760
+ const runner = deps.execRunner;
36761
+ if (runner !== void 0) {
36762
+ group.post("/exec", async (c) => {
36763
+ const sc = scope.resolve(c);
36764
+ if (sc === null)
36765
+ return badTenancy(c);
36766
+ const request = await readExecRequest(c, sc);
36767
+ if (request === null) {
36768
+ return c.json({ error: "bad_request", reason: "exec body must carry a command" }, 400);
36769
+ }
36770
+ const res = runner.submit(request);
36771
+ if (!res.ok) {
36772
+ if (res.reason === "queue_full") {
36773
+ return c.json({ error: "queue_full", reason: "exec pool and queue are at capacity" }, 429);
36774
+ }
36775
+ return c.json({ error: "bad_request", reason: "invalid exec request" }, 400);
36776
+ }
36777
+ return c.json({ ok: true, jobId: res.jobId, status: "queued" }, 202);
36778
+ });
36779
+ group.get("/exec/:jobId", (c) => {
36780
+ const sc = scope.resolve(c);
36781
+ if (sc === null)
36782
+ return badTenancy(c);
36783
+ const jobId = c.req.param("jobId");
36784
+ const view = runner.getStatus(jobId, sc);
36785
+ if (view === null) {
36786
+ return c.json({ error: "not_found", reason: "no such exec job" }, 404);
36787
+ }
36788
+ return c.json(view);
36789
+ });
36790
+ group.all("/bitwarden/*", (c) => c.json({ error: "use_exec", reason: "reference a Bitwarden item via exec vaultRefs; values are never returned" }, 400));
36791
+ group.all("/1password/*", (c) => c.json({ error: "use_exec", reason: "reference a 1Password item via exec vaultRefs; values are never returned" }, 400));
36792
+ } else {
36793
+ group.post("/exec", (c) => notImplementedRoute(c, "POST /api/secrets/exec (secret_exec)"));
36794
+ group.get("/exec/:jobId", (c) => notImplementedRoute(c, "GET /api/secrets/exec/:jobId (exec status)"));
36795
+ group.all("/bitwarden/*", (c) => notImplementedRoute(c, "Bitwarden vault provider"));
36796
+ group.all("/1password/*", (c) => notImplementedRoute(c, "1Password vault provider"));
36797
+ }
36798
+ group.get("/", (c) => {
36799
+ const sc = scope.resolve(c);
36800
+ if (sc === null)
36801
+ return badTenancy(c);
36802
+ const names = store.listSecretNames(sc);
36803
+ return c.json({ names });
36804
+ });
36805
+ group.post("/:name", async (c) => {
36806
+ const sc = scope.resolve(c);
36807
+ if (sc === null)
36808
+ return badTenancy(c);
36809
+ const name = c.req.param("name");
36810
+ const value = await readValue(c);
36811
+ if (value === null) {
36812
+ return c.json({ error: "bad_request", reason: "request body must carry a string value" }, 400);
36813
+ }
36814
+ const res = await store.setSecret(name, value, sc);
36815
+ if (!res.ok) {
36816
+ if (res.reason === "invalid_name") {
36817
+ return c.json({ error: "bad_request", reason: "invalid secret name" }, 400);
36818
+ }
36819
+ return c.json({ error: "store_failed", reason: "could not store the secret" }, 502);
36820
+ }
36821
+ return c.json({ ok: true, name }, 201);
36822
+ });
36823
+ group.delete("/:name", (c) => {
36824
+ const sc = scope.resolve(c);
36825
+ if (sc === null)
36826
+ return badTenancy(c);
36827
+ const name = c.req.param("name");
36828
+ const res = store.deleteSecret(name, sc);
36829
+ if (!res.ok) {
36830
+ if (res.reason === "invalid_name") {
36831
+ return c.json({ error: "bad_request", reason: "invalid secret name" }, 400);
36832
+ }
36833
+ if (res.reason === "not_found") {
36834
+ return c.json({ error: "not_found", reason: "no such secret" }, 404);
36835
+ }
36836
+ return c.json({ error: "delete_failed", reason: "could not delete the secret" }, 502);
36837
+ }
36838
+ return c.json({ ok: true, name });
36839
+ });
36840
+ }
36841
+ function badTenancy(c) {
36842
+ return c.json({ error: "bad_request", reason: "x-honeycomb-org header is required" }, 400);
36843
+ }
36844
+ async function readValue(c) {
36845
+ const contentType = c.req.header("content-type") ?? "";
36846
+ if (contentType.includes("application/json")) {
36847
+ try {
36848
+ const body = await c.req.json();
36849
+ if (typeof body === "object" && body !== null) {
36850
+ const v = body.value;
36851
+ if (typeof v === "string" && v.length > 0)
36852
+ return v;
36853
+ }
36854
+ return null;
36855
+ } catch {
36856
+ return null;
36857
+ }
36858
+ }
36859
+ const text = await c.req.text();
36860
+ return text.length > 0 ? text : null;
36861
+ }
36862
+ function notImplementedRoute(c, what) {
36863
+ return c.json({ error: "not_implemented", reason: `${what} is implemented in PRD-012b` }, 501);
36864
+ }
36865
+ async function readExecRequest(c, scope) {
36866
+ let body;
36867
+ try {
36868
+ body = await c.req.json();
36869
+ } catch {
36870
+ return null;
36871
+ }
36872
+ if (typeof body !== "object" || body === null)
36873
+ return null;
36874
+ const b = body;
36875
+ const command = b.command;
36876
+ if (typeof command !== "string" || command.length === 0)
36877
+ return null;
36878
+ const args = Array.isArray(b.args) ? b.args.filter((a) => typeof a === "string") : [];
36879
+ const secretNames = Array.isArray(b.secretNames) ? b.secretNames.filter((n) => typeof n === "string") : [];
36880
+ const vaultRefs = {};
36881
+ if (typeof b.vaultRefs === "object" && b.vaultRefs !== null) {
36882
+ for (const [k, v] of Object.entries(b.vaultRefs)) {
36883
+ if (typeof v === "string")
36884
+ vaultRefs[k] = v;
36885
+ }
36886
+ }
36887
+ const timeoutMs = typeof b.timeoutMs === "number" ? b.timeoutMs : void 0;
36888
+ return { command, args, secretNames, vaultRefs, scope, timeoutMs };
36889
+ }
36890
+
36891
+ // dist/src/daemon/runtime/vault/catalog.js
36892
+ var PROVIDER_CATALOG = Object.freeze([
36893
+ Object.freeze({
36894
+ id: "anthropic",
36895
+ label: "Anthropic",
36896
+ models: Object.freeze(["claude-sonnet-4-6", "claude-opus-4-8"]),
36897
+ openEnded: false
36898
+ }),
36899
+ Object.freeze({
36900
+ id: "openai",
36901
+ label: "OpenAI",
36902
+ models: Object.freeze(["gpt-4o", "gpt-4o-mini", "gpt-4.1"]),
36903
+ openEnded: false
36904
+ }),
36905
+ Object.freeze({
36906
+ id: "openrouter",
36907
+ label: "OpenRouter",
36908
+ // Suggestions only — OpenRouter accepts a free-form `vendor/model` id (passthrough).
36909
+ models: Object.freeze(["anthropic/claude-sonnet-4.6", "openai/gpt-4o"]),
36910
+ openEnded: true
36911
+ }),
36912
+ Object.freeze({
36913
+ // PRD-063a: Portkey is a GATEWAY, not a model vendor — its `portkey.config` id is
36914
+ // free-form (a config or virtual-key id copied from the Portkey dashboard), so it is
36915
+ // `openEnded: true` like OpenRouter and carries NO curated model list of its own.
36916
+ id: "portkey",
36917
+ label: "Portkey",
36918
+ models: Object.freeze([]),
36919
+ openEnded: true
36920
+ })
36921
+ ]);
36922
+ function providerEntry(provider) {
36923
+ return PROVIDER_CATALOG.find((p) => p.id === provider);
36924
+ }
36925
+ function isValidProviderModel(provider, model) {
36926
+ const entry = providerEntry(provider);
36927
+ if (entry === void 0)
36928
+ return false;
36929
+ if (typeof model !== "string" || model.length === 0)
36930
+ return false;
36931
+ if (entry.openEnded)
36932
+ return true;
36933
+ return entry.models.includes(model);
36934
+ }
36935
+ function catalogView() {
36936
+ return PROVIDER_CATALOG;
36937
+ }
36938
+
36939
+ // dist/src/daemon/runtime/secrets/contracts.js
36940
+ import { homedir as homedir12, hostname as hostname3, userInfo } from "node:os";
36941
+ var SECRET_NAME_PATTERN = /^[A-Za-z0-9_.-]+$/;
36942
+ var MAX_SECRET_NAME_LENGTH = 128;
36943
+ function isValidSecretName(value) {
36944
+ if (typeof value !== "string")
36945
+ return false;
36946
+ if (value.length === 0 || value.length > MAX_SECRET_NAME_LENGTH)
36947
+ return false;
36948
+ if (value === "." || value === "..")
36949
+ return false;
36950
+ if (value.includes("/") || value.includes("\\") || value.includes("\0"))
36951
+ return false;
36952
+ return SECRET_NAME_PATTERN.test(value);
36953
+ }
36954
+ function asSecretName(value) {
36955
+ return isValidSecretName(value) ? value : null;
36956
+ }
36957
+ function isSecretRecord(value) {
36958
+ if (typeof value !== "object" || value === null)
36959
+ return false;
36960
+ const r = value;
36961
+ if (typeof r.nonce !== "string" || typeof r.ciphertext !== "string" || typeof r.createdAt !== "string") {
36962
+ return false;
36963
+ }
36964
+ const scope = r.scope;
36965
+ if (typeof scope !== "object" || scope === null)
36966
+ return false;
36967
+ const s = scope;
36968
+ if (typeof s.org !== "string" || typeof s.workspace !== "string")
36969
+ return false;
36970
+ if (s.agentId !== void 0 && typeof s.agentId !== "string")
36971
+ return false;
36972
+ return true;
36973
+ }
36974
+ var MACHINE_KEY_DIR_NAME = ".honeycomb";
36975
+ var MACHINE_KEY_FILE_NAME = ".machine-key";
36976
+ function hostnameUserFallbackId() {
36977
+ let user = "";
36978
+ try {
36979
+ user = userInfo().username;
36980
+ } catch {
36981
+ user = "";
36982
+ }
36983
+ return `host:${hostname3()}|user:${user}|home:${homedir12()}`;
36984
+ }
36985
+
36986
+ // dist/src/daemon/runtime/vault/contracts.js
36987
+ function asRecordClass(value) {
36988
+ return isValidSecretName(value) ? value : null;
36989
+ }
36990
+
36991
+ // dist/src/daemon/runtime/vault/registry.js
36992
+ var SECRET_CLASS = "secret";
36993
+ var SETTING_CLASS = "setting";
36994
+ var SecretValueSchema = external_exports.string().min(1);
36995
+ var SettingValueSchema = external_exports.union([external_exports.string(), external_exports.number().finite(), external_exports.boolean()]);
36996
+ var SECRET_DESCRIPTOR = Object.freeze({
36997
+ id: SECRET_CLASS,
36998
+ posture: "internal-only",
36999
+ schema: SecretValueSchema
37000
+ });
37001
+ var SETTING_DESCRIPTOR = Object.freeze({
37002
+ id: SETTING_CLASS,
37003
+ posture: "daemon-readable",
37004
+ schema: SettingValueSchema
37005
+ });
37006
+ var VaultRegistry = class {
37007
+ table;
37008
+ constructor(descriptors) {
37009
+ this.table = /* @__PURE__ */ new Map();
37010
+ for (const d of descriptors)
37011
+ this.table.set(d.id, d);
37012
+ }
37013
+ /**
37014
+ * Register a new record class (D-7). Validates the id is traversal-proof (a class is an
37015
+ * on-disk segment) and that the posture is one the store understands, then adds the
37016
+ * descriptor. Re-registering an existing id REPLACES it (so a test can swap a throwaway
37017
+ * class); registering the built-in `secret`/`setting` ids is allowed but discouraged —
37018
+ * their posture must not be loosened. Returns the registry for chaining.
37019
+ *
37020
+ * Throws on an invalid (traversal-unsafe) class id — that is a programming error, not a
37021
+ * runtime input, so it fails loud rather than silently dropping the class.
37022
+ */
37023
+ registerClass(descriptor) {
37024
+ const safe = asRecordClass(descriptor.id);
37025
+ if (safe === null) {
37026
+ throw new Error(`vault.registerClass: invalid (traversal-unsafe) class id`);
37027
+ }
37028
+ this.table.set(descriptor.id, descriptor);
37029
+ return this;
37030
+ }
37031
+ /** Whether a class id is registered. */
37032
+ has(klass) {
37033
+ return this.table.has(klass);
37034
+ }
37035
+ /** The registered class ids (sorted), for diagnostics — never values. */
37036
+ classIds() {
37037
+ return [...this.table.keys()].sort();
37038
+ }
37039
+ /**
37040
+ * Resolve a class's descriptor for a WRITE, validating the value against the class
37041
+ * schema (zod-at-boundary). Returns `unknown_class` for an unregistered class or
37042
+ * `invalid_value` when the value fails the schema — both fail-closed (nothing is
37043
+ * written). On success the descriptor (with the validated value available via the
37044
+ * caller's re-parse) is returned.
37045
+ */
37046
+ resolveForWrite(klass, value) {
37047
+ const descriptor = this.table.get(klass);
37048
+ if (descriptor === void 0)
37049
+ return { ok: false, reason: "unknown_class" };
37050
+ const parsed = descriptor.schema.safeParse(value);
37051
+ if (!parsed.success)
37052
+ return { ok: false, reason: "invalid_value" };
37053
+ return { ok: true, descriptor };
37054
+ }
37055
+ /**
37056
+ * The POSTURE GATE (a-AC-2). Resolve a class's descriptor for a READ that intends to
37057
+ * RETURN the value to a surface (the `getSetting` path). REJECTS a class whose posture
37058
+ * is `internal-only` with `not_readable` — so a `secret` can NEVER be read back through
37059
+ * the daemon-readable accessor. An unknown class is `unknown_class`. This is the single
37060
+ * point where the secret-vs-setting security boundary is enforced, as data.
37061
+ */
37062
+ assertReadable(klass) {
37063
+ const descriptor = this.table.get(klass);
37064
+ if (descriptor === void 0)
37065
+ return { ok: false, reason: "unknown_class" };
37066
+ if (descriptor.posture !== "daemon-readable")
37067
+ return { ok: false, reason: "not_readable" };
37068
+ return { ok: true, descriptor };
37069
+ }
37070
+ /** Resolve a descriptor with no value/posture check (internal callers that already gate). */
37071
+ descriptorOf(klass) {
37072
+ return this.table.get(klass);
37073
+ }
37074
+ };
37075
+ function createVaultRegistry(extra = []) {
37076
+ return new VaultRegistry([SECRET_DESCRIPTOR, SETTING_DESCRIPTOR, ...extra]);
37077
+ }
37078
+
37079
+ // dist/src/daemon/runtime/vault/api.js
37080
+ var SETTINGS_GROUP = "/api/settings";
37081
+ var EMBEDDINGS_ENABLED_KEY = "embeddings.enabled";
37082
+ var KNOWN_SETTING_KEYS = [
37083
+ "activeProvider",
37084
+ "activeModel",
37085
+ "pollinating.enabled",
37086
+ EMBEDDINGS_ENABLED_KEY,
37087
+ "recallMode",
37088
+ "portkey.enabled",
37089
+ "portkey.config",
37090
+ "portkey.fallbackToProvider"
37091
+ ];
37092
+ var RECALL_MODES = ["keyword", "semantic", "hybrid"];
37093
+ function isValidRecallMode(value) {
37094
+ return RECALL_MODES.includes(value);
37095
+ }
37096
+ var DASHBOARD_PREF_PREFIX = "dashboard.";
37097
+ function isKnownSettingKey(key) {
37098
+ if (KNOWN_SETTING_KEYS.includes(key))
37099
+ return true;
37100
+ return key.startsWith(DASHBOARD_PREF_PREFIX) && key.length > DASHBOARD_PREF_PREFIX.length;
37101
+ }
37102
+ function mountSettingsGroup(group, deps) {
37103
+ const scope = deps.scope ?? headerScopeResolver;
37104
+ const store = deps.store;
37105
+ group.get("/", async (c) => {
37106
+ const sc = scope.resolve(c);
37107
+ if (sc === null)
37108
+ return badTenancy2(c);
37109
+ const keys = store.listSettingKeys(sc);
37110
+ const settings = {};
37111
+ for (const key of keys) {
37112
+ const res = await store.getSetting(key, sc);
37113
+ if (res.ok)
37114
+ settings[key] = res.value;
37115
+ }
37116
+ return c.json({ settings, catalog: catalogView() });
37117
+ });
37118
+ group.get("/:key", async (c) => {
37119
+ const sc = scope.resolve(c);
37120
+ if (sc === null)
37121
+ return badTenancy2(c);
37122
+ const key = c.req.param("key");
37123
+ if (!isKnownSettingKey(key)) {
37124
+ return c.json({ error: "not_found", reason: "no such setting" }, 404);
37125
+ }
37126
+ const res = await store.getSetting(key, sc);
37127
+ if (!res.ok) {
37128
+ if (res.reason === "not_found")
37129
+ return c.json({ error: "not_found", reason: "no such setting" }, 404);
37130
+ if (res.reason === "not_readable")
37131
+ return c.json({ error: "not_found", reason: "no such setting" }, 404);
37132
+ return c.json({ error: "read_failed", reason: "could not read the setting" }, 502);
37133
+ }
37134
+ return c.json({ key, value: res.value });
37135
+ });
37136
+ group.post("/:key", async (c) => {
37137
+ const sc = scope.resolve(c);
37138
+ if (sc === null)
37139
+ return badTenancy2(c);
37140
+ const key = c.req.param("key");
37141
+ if (!isKnownSettingKey(key)) {
37142
+ return c.json({ error: "bad_request", reason: "unknown setting key" }, 400);
37143
+ }
37144
+ const value = await readSettingValue(c);
37145
+ if (value === null) {
37146
+ return c.json({ error: "bad_request", reason: "request body must carry a scalar value" }, 400);
37147
+ }
37148
+ const semanticError = await validateSettingSemantics(store, sc, key, value);
37149
+ if (semanticError !== null) {
37150
+ return c.json({ error: "bad_request", reason: semanticError }, 400);
37151
+ }
37152
+ const res = await store.setSetting(key, value, sc);
37153
+ if (!res.ok) {
37154
+ if (res.reason === "invalid_value") {
37155
+ return c.json({ error: "bad_request", reason: "invalid setting value" }, 400);
37156
+ }
37157
+ if (res.reason === "not_readable" || res.reason === "unknown_class") {
37158
+ return c.json({ error: "bad_request", reason: "setting class is not writable" }, 400);
37159
+ }
37160
+ return c.json({ error: "store_failed", reason: "could not store the setting" }, 502);
37161
+ }
37162
+ return c.json({ ok: true, key, value }, 201);
37163
+ });
37164
+ }
37165
+ function mountSettingsApi(daemon, deps) {
37166
+ const group = daemon.group(SETTINGS_GROUP);
37167
+ if (group === void 0)
37168
+ return;
37169
+ mountSettingsGroup(group, deps);
37170
+ }
37171
+ function badTenancy2(c) {
37172
+ return c.json({ error: "bad_request", reason: "x-honeycomb-org header is required" }, 400);
37173
+ }
37174
+ async function readSettingValue(c) {
37175
+ const contentType = c.req.header("content-type") ?? "";
37176
+ if (contentType.includes("application/json")) {
37177
+ try {
37178
+ const body = await c.req.json();
37179
+ if (typeof body === "object" && body !== null) {
37180
+ const v = body.value;
37181
+ const parsed = SettingValueSchema.safeParse(v);
37182
+ return parsed.success ? parsed.data : null;
37183
+ }
37184
+ return null;
37185
+ } catch {
37186
+ return null;
37187
+ }
37188
+ }
37189
+ const text = await c.req.text();
37190
+ return text.length > 0 ? text : null;
37191
+ }
37192
+ async function validateSettingSemantics(store, scope, key, value) {
37193
+ if (key === "activeProvider") {
37194
+ if (providerEntry(String(value)) === void 0)
37195
+ return "unknown provider";
37196
+ return null;
37197
+ }
37198
+ if (key === "activeModel") {
37199
+ const provRes = await store.getSetting("activeProvider", scope);
37200
+ const provider = provRes.ok ? String(provRes.value) : "";
37201
+ if (provider.length === 0)
37202
+ return "set activeProvider before activeModel";
37203
+ if (!isValidProviderModel(provider, String(value)))
37204
+ return "model not in provider catalog";
37205
+ return null;
37206
+ }
37207
+ if (key === "recallMode") {
37208
+ if (!isValidRecallMode(String(value)))
37209
+ return "recallMode must be keyword, semantic, or hybrid";
37210
+ return null;
37211
+ }
37212
+ if (key === "portkey.enabled" || key === "portkey.fallbackToProvider") {
37213
+ if (typeof value !== "boolean")
37214
+ return `${key} must be a boolean`;
37215
+ return null;
37216
+ }
37217
+ if (key === "portkey.config") {
37218
+ if (typeof value !== "string")
37219
+ return "portkey.config must be a string";
37220
+ if (/[\u0000-\u001F\u007F]/.test(value))
37221
+ return "portkey.config must not contain control characters";
37222
+ const enabledRes = await store.getSetting("portkey.enabled", scope);
37223
+ const enabled = enabledRes.ok && enabledRes.value === true;
37224
+ if (enabled && value.length === 0)
37225
+ return "portkey.config must be non-empty when portkey.enabled is true";
37226
+ return null;
37227
+ }
37228
+ return null;
37229
+ }
37230
+
37231
+ // dist/src/daemon/runtime/dashboard/harness-detect.js
37232
+ import { existsSync as existsSync12 } from "node:fs";
37233
+ import { homedir as homedir16 } from "node:os";
37234
+ import { join as join20 } from "node:path";
36629
37235
 
36630
37236
  // dist/src/hooks/shared/contracts.js
36631
37237
  var LOGICAL_EVENTS = [
@@ -36730,7 +37336,7 @@ var HEALTH_DIMENSION_WIRABLE = Object.freeze({
36730
37336
 
36731
37337
  // dist/src/notifications/state.js
36732
37338
  import { closeSync as closeSync3, existsSync as existsSync10, mkdirSync as mkdirSync11, openSync as openSync3, readFileSync as readFileSync13, renameSync as renameSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "node:fs";
36733
- import { homedir as homedir12 } from "node:os";
37339
+ import { homedir as homedir13 } from "node:os";
36734
37340
  import { join as join17 } from "node:path";
36735
37341
 
36736
37342
  // dist/src/daemon/runtime/assets/contracts.js
@@ -36754,7 +37360,7 @@ var audienceMatches = (asset, ctx) => {
36754
37360
 
36755
37361
  // dist/src/daemon-client/assets/install.js
36756
37362
  import { existsSync as existsSync11, mkdirSync as mkdirSync12, readFileSync as readFileSync14, renameSync as renameSync7, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "node:fs";
36757
- import { homedir as homedir13 } from "node:os";
37363
+ import { homedir as homedir14 } from "node:os";
36758
37364
  import { dirname as dirname10, join as join18, resolve as resolve4 } from "node:path";
36759
37365
  var HARNESS_SKILL_DIRS = Object.freeze({
36760
37366
  claude_code: join18(".claude", "skills"),
@@ -36774,38 +37380,52 @@ var HARNESS_AGENT_DIRS = Object.freeze({
36774
37380
  });
36775
37381
 
36776
37382
  // dist/src/commands/contracts.js
37383
+ var VERB_GROUPS = Object.freeze([
37384
+ { key: "memory", label: "Memory & recall" },
37385
+ { key: "knowledge", label: "Knowledge & skills" },
37386
+ { key: "agents", label: "Agents, routing & config" },
37387
+ { key: "account", label: "Account & workspaces" },
37388
+ { key: "system", label: "Setup & system" }
37389
+ ]);
36777
37390
  var VERB_TABLE = Object.freeze([
36778
- { verb: "setup", cls: "local", summary: "detect assistants, wire hooks, bring up the daemon" },
36779
- { verb: "install", cls: "local", summary: "bring up the daemon (health-gated) + open the dashboard (PRD-050a)" },
36780
- { verb: "status", cls: "local", summary: "daemon connectivity + login + D1\u2013D5 environment health" },
36781
- { verb: "daemon", cls: "local", summary: "start | stop | status the loopback daemon (3850)" },
36782
- { verb: "dashboard", cls: "local", summary: "launch the daemon-served dashboard (020b)" },
36783
- { verb: "telemetry", cls: "local", summary: "show exactly what adoption telemetry has been / would be sent (--show, PRD-050e)" },
36784
- { verb: "pollinate", cls: "storage", summary: "trigger a pollinating consolidation pass on the daemon (009/026)" },
36785
- { verb: "maintenance", cls: "storage", summary: "run version-history compaction over version-bumped tables (030)" },
36786
- { verb: "remember", cls: "storage", summary: "write a memory through the daemon (--type fact|convention|preference|decision|gotcha|reference)" },
36787
- { verb: "recall", cls: "storage", summary: "recall memories through the daemon" },
36788
- { verb: "memory", cls: "storage", summary: "lifecycle: conflicts (list/resolve), stale-refs (list), inspect <id> --lifecycle (058d)" },
36789
- { verb: "agent", cls: "storage", summary: "run an agent turn through the daemon" },
36790
- { verb: "ontology", cls: "storage", summary: "inspect/propose ontology changes through the daemon" },
36791
- { verb: "secret", cls: "storage", summary: "manage named secrets through the daemon" },
36792
- { verb: "settings", cls: "storage", summary: "get/set/list vault settings + provider\u2192model selector through the daemon" },
36793
- { verb: "asset", cls: "storage", summary: "register/promote/demote/style skills+agents through the tier\xD7style lattice (033)" },
36794
- { verb: "skill", cls: "storage", summary: "skillify scope/pull/unpull/force/promote through the daemon (promote = cross-project, 049c)" },
36795
- { verb: "skillify", cls: "storage", summary: "pull team skills from the daemon (016c)" },
36796
- { verb: "hook", cls: "local", summary: "inspect/wire harness hooks" },
36797
- { verb: "route", cls: "storage", summary: "manage inference routes through the daemon" },
36798
- { verb: "sources", cls: "storage", summary: "connect/index/purge sources through the daemon" },
36799
- { verb: "graph", cls: "storage", summary: "build/query the codebase graph through the daemon" },
36800
- { verb: "goal", cls: "storage", summary: "manage goals/KPIs through the daemon" },
36801
- { verb: "whoami", cls: "auth", summary: "show the authenticated user, org, and workspace (GET /me)" },
36802
- { verb: "org", cls: "auth", summary: "list/switch org (passthrough to the auth dispatcher)" },
36803
- { verb: "workspace", cls: "auth", summary: "list/switch/use workspace (passthrough to the auth dispatcher)" },
36804
- { verb: "workspaces", cls: "auth", summary: "list workspaces in the active org (alias of `workspace list`)" },
36805
- { verb: "project", cls: "auth", summary: "list/bind/use projects + show the resolved per-folder scope (049d)" },
36806
- { verb: "sessions", cls: "storage", summary: "list/prune captured sessions through the daemon" },
36807
- { verb: "uninstall", cls: "local", summary: "reverse only Honeycomb's changes" },
36808
- { verb: "update", cls: "local", summary: "self-update the CLI, daemon, and bundles" }
37391
+ // Memory & recall the product's core write/read/lifecycle surface.
37392
+ { verb: "remember", cls: "storage", group: "memory", summary: "write a memory through the daemon (--type fact|convention|preference|decision|gotcha|reference)" },
37393
+ { verb: "recall", cls: "storage", group: "memory", summary: "recall memories through the daemon" },
37394
+ { verb: "memory", cls: "storage", group: "memory", summary: "lifecycle: conflicts (list/resolve), stale-refs (list), inspect <id> --lifecycle (058d)" },
37395
+ { verb: "sessions", cls: "storage", group: "memory", summary: "list/prune captured sessions through the daemon" },
37396
+ { verb: "pollinate", cls: "storage", group: "memory", summary: "trigger a pollinating consolidation pass on the daemon (009/026)" },
37397
+ { verb: "maintenance", cls: "storage", group: "memory", summary: "run version-history compaction over version-bumped tables (030)" },
37398
+ // Knowledge & skills — skills, assets, ontology, the codebase graph, and goals.
37399
+ { verb: "skill", cls: "storage", group: "knowledge", summary: "skillify scope/pull/unpull/force/promote through the daemon (promote = cross-project, 049c)" },
37400
+ { verb: "skillify", cls: "storage", group: "knowledge", summary: "pull team skills from the daemon (016c)" },
37401
+ { verb: "asset", cls: "storage", group: "knowledge", summary: "register/promote/demote/style skills+agents through the tier\xD7style lattice (033)" },
37402
+ { verb: "ontology", cls: "storage", group: "knowledge", summary: "inspect/propose ontology changes through the daemon" },
37403
+ { verb: "graph", cls: "storage", group: "knowledge", summary: "build/query the codebase graph through the daemon" },
37404
+ { verb: "sources", cls: "storage", group: "knowledge", summary: "connect/index/purge sources through the daemon" },
37405
+ { verb: "goal", cls: "storage", group: "knowledge", summary: "manage goals/KPIs through the daemon" },
37406
+ // Agents, routing & config agent turns, inference routes, secrets, and vault settings.
37407
+ { verb: "agent", cls: "storage", group: "agents", summary: "run an agent turn through the daemon" },
37408
+ { verb: "route", cls: "storage", group: "agents", summary: "manage inference routes through the daemon" },
37409
+ { verb: "secret", cls: "storage", group: "agents", summary: "manage named secrets through the daemon" },
37410
+ { verb: "settings", cls: "storage", group: "agents", summary: "get/set/list vault settings + provider\u2192model selector through the daemon" },
37411
+ // Account & workspaces — auth, identity, and the org/workspace/project scope surface.
37412
+ { verb: "login", cls: "auth", group: "account", summary: "authenticate via device flow, or --token <key> for headless (023)" },
37413
+ { verb: "logout", cls: "auth", group: "account", summary: "remove the shared credentials and sign out (023)" },
37414
+ { verb: "whoami", cls: "auth", group: "account", summary: "show the authenticated user, org, and workspace (GET /me)" },
37415
+ { verb: "org", cls: "auth", group: "account", summary: "list/switch org (passthrough to the auth dispatcher)" },
37416
+ { verb: "workspace", cls: "auth", group: "account", summary: "list/switch/use workspace (passthrough to the auth dispatcher)" },
37417
+ { verb: "workspaces", cls: "auth", group: "account", summary: "list workspaces in the active org (alias of `workspace list`)" },
37418
+ { verb: "project", cls: "auth", group: "account", summary: "list/bind/use projects + show the resolved per-folder scope (049d)" },
37419
+ // Setup & system install/onboard, daemon lifecycle, dashboard, hooks, telemetry, update.
37420
+ { verb: "setup", cls: "local", group: "system", summary: "detect assistants, wire hooks, bring up the daemon" },
37421
+ { verb: "install", cls: "local", group: "system", summary: "bring up the daemon (health-gated) + open the dashboard (PRD-050a)" },
37422
+ { verb: "status", cls: "local", group: "system", summary: "daemon connectivity + login + D1\u2013D5 environment health" },
37423
+ { verb: "daemon", cls: "local", group: "system", summary: "start | stop | status the loopback daemon (3850)" },
37424
+ { verb: "dashboard", cls: "local", group: "system", summary: "launch the daemon-served dashboard (020b)" },
37425
+ { verb: "hook", cls: "local", group: "system", summary: "inspect/wire harness hooks" },
37426
+ { verb: "telemetry", cls: "local", group: "system", summary: "show exactly what adoption telemetry has been / would be sent (--show, PRD-050e)" },
37427
+ { verb: "update", cls: "local", group: "system", summary: "self-update the CLI, daemon, and bundles" },
37428
+ { verb: "uninstall", cls: "local", group: "system", summary: "reverse only Honeycomb's changes" }
36809
37429
  ]);
36810
37430
  var DEFAULT_GLOBAL_FLAGS = Object.freeze({
36811
37431
  help: false,
@@ -36817,7 +37437,7 @@ var DEFAULT_GLOBAL_FLAGS = Object.freeze({
36817
37437
  // dist/src/daemon/runtime/assets/device.js
36818
37438
  import { randomUUID as randomUUID2 } from "node:crypto";
36819
37439
  import { mkdirSync as mkdirSync13, readFileSync as readFileSync15, writeFileSync as writeFileSync11 } from "node:fs";
36820
- import { homedir as homedir14, hostname as hostname3 } from "node:os";
37440
+ import { homedir as homedir15, hostname as hostname4 } from "node:os";
36821
37441
  import { dirname as dirname11, join as join19 } from "node:path";
36822
37442
 
36823
37443
  // dist/src/hooks/normalize.js
@@ -36908,12 +37528,14 @@ function nestedString(raw2, a, b) {
36908
37528
  function userMessageData(text) {
36909
37529
  return { kind: "user_message", text };
36910
37530
  }
36911
- function assistantMessageData(text, usage) {
37531
+ function assistantMessageData(text, usage, model) {
36912
37532
  const normalized = usage !== void 0 ? compactUsage(usage) : void 0;
37533
+ const trimmedModel = typeof model === "string" ? model.trim() : "";
36913
37534
  return {
36914
37535
  kind: "assistant_message",
36915
37536
  text,
36916
- ...normalized !== void 0 ? { usage: normalized } : {}
37537
+ ...normalized !== void 0 ? { usage: normalized } : {},
37538
+ ...trimmedModel !== "" ? { model: trimmedModel } : {}
36917
37539
  };
36918
37540
  }
36919
37541
  function compactUsage(usage) {
@@ -36983,6 +37605,112 @@ function preToolData(tool, fields) {
36983
37605
  };
36984
37606
  }
36985
37607
 
37608
+ // dist/src/hooks/claude-code/transcript.js
37609
+ import { readFileSync as readFileSync16 } from "node:fs";
37610
+ function parseTurnUsage(jsonlText) {
37611
+ const entries = parseEntries(jsonlText);
37612
+ let lastUserIndex = -1;
37613
+ for (let i = 0; i < entries.length; i++) {
37614
+ if (entryType(entries[i]) === "user")
37615
+ lastUserIndex = i;
37616
+ }
37617
+ const totals = new TurnTotals();
37618
+ let lastModel;
37619
+ let sawAssistant = false;
37620
+ for (let i = lastUserIndex + 1; i < entries.length; i++) {
37621
+ const entry = entries[i];
37622
+ if (entryType(entry) !== "assistant")
37623
+ continue;
37624
+ sawAssistant = true;
37625
+ totals.add(messageOf(entry));
37626
+ const model = modelOf(entry);
37627
+ if (model !== void 0)
37628
+ lastModel = model;
37629
+ }
37630
+ if (!sawAssistant)
37631
+ return {};
37632
+ const usage = totals.toUsage();
37633
+ return {
37634
+ ...lastModel !== void 0 ? { model: lastModel } : {},
37635
+ ...usage !== void 0 ? { usage } : {}
37636
+ };
37637
+ }
37638
+ function readTranscriptTurnUsage(transcriptPath2) {
37639
+ if (transcriptPath2.length === 0)
37640
+ return {};
37641
+ let text;
37642
+ try {
37643
+ text = readFileSync16(transcriptPath2, "utf8");
37644
+ } catch {
37645
+ return {};
37646
+ }
37647
+ return parseTurnUsage(text);
37648
+ }
37649
+ function parseEntries(jsonlText) {
37650
+ const out = [];
37651
+ for (const line of jsonlText.split("\n")) {
37652
+ const trimmed = line.trim();
37653
+ if (trimmed.length === 0)
37654
+ continue;
37655
+ let parsed;
37656
+ try {
37657
+ parsed = JSON.parse(trimmed);
37658
+ } catch {
37659
+ continue;
37660
+ }
37661
+ if (parsed !== null && typeof parsed === "object")
37662
+ out.push(parsed);
37663
+ }
37664
+ return out;
37665
+ }
37666
+ function entryType(entry) {
37667
+ return typeof entry.type === "string" ? entry.type : "";
37668
+ }
37669
+ function messageOf(entry) {
37670
+ const message = entry.message;
37671
+ return message !== null && typeof message === "object" ? message : {};
37672
+ }
37673
+ function modelOf(entry) {
37674
+ const model = messageOf(entry).model;
37675
+ return typeof model === "string" && model.length > 0 ? model : void 0;
37676
+ }
37677
+ var TurnTotals = class {
37678
+ input;
37679
+ output;
37680
+ cacheRead;
37681
+ cacheCreation;
37682
+ /** Fold one assistant `message.usage` block's counts into the running totals (absent counts skipped). */
37683
+ add(message) {
37684
+ const usage = message.usage;
37685
+ const block = usage !== null && typeof usage === "object" ? usage : {};
37686
+ this.input = addCount(this.input, readCount2(block, "input_tokens"));
37687
+ this.output = addCount(this.output, readCount2(block, "output_tokens"));
37688
+ this.cacheRead = addCount(this.cacheRead, readCount2(block, "cache_read_input_tokens"));
37689
+ this.cacheCreation = addCount(this.cacheCreation, readCount2(block, "cache_creation_input_tokens"));
37690
+ }
37691
+ /** Compact the totals into a {@link NormalizedTurnUsage}, or `undefined` when every bucket stayed absent. */
37692
+ toUsage() {
37693
+ const usage = {
37694
+ ...this.input !== void 0 ? { input: this.input } : {},
37695
+ ...this.output !== void 0 ? { output: this.output } : {},
37696
+ ...this.cacheRead !== void 0 ? { cacheRead: this.cacheRead } : {},
37697
+ ...this.cacheCreation !== void 0 ? { cacheCreation: this.cacheCreation } : {}
37698
+ };
37699
+ return Object.keys(usage).length > 0 ? usage : void 0;
37700
+ }
37701
+ };
37702
+ function addCount(running, addend) {
37703
+ if (addend === void 0)
37704
+ return running;
37705
+ return (running ?? 0) + addend;
37706
+ }
37707
+ function readCount2(block, key) {
37708
+ const value = block[key];
37709
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 0)
37710
+ return void 0;
37711
+ return value;
37712
+ }
37713
+
36986
37714
  // dist/src/hooks/claude-code/shim.js
36987
37715
  var CLAUDE_CODE_EVENT_MAP = {
36988
37716
  SessionStart: "session-start",
@@ -36997,7 +37725,7 @@ var CLAUDE_CODE_CONTEXT_CHANNEL = "model-only";
36997
37725
  var CLAUDE_CODE_RUNTIME_PATH = "legacy";
36998
37726
  var CLAUDE_CODE_HOST_CLI = { bin: "claude", args: ["-p"] };
36999
37727
  var CLAUDE_CODE_REFERENCES = "references/claude-code/";
37000
- function claudeCodeExtractData(raw2, logical) {
37728
+ function claudeCodeExtractData(raw2, logical, meta3) {
37001
37729
  switch (logical) {
37002
37730
  case "session-start":
37003
37731
  return sessionStartData(pickString(raw2, "source") || "startup");
@@ -37011,8 +37739,11 @@ function claudeCodeExtractData(raw2, logical) {
37011
37739
  });
37012
37740
  case "tool_call":
37013
37741
  return toolCallData(pickString(raw2, "tool_name", "tool"), nested(raw2, "tool_input"), nested(raw2, "tool_response"));
37014
- case "assistant_message":
37015
- return assistantMessageData(pickString(raw2, "text", "message"), extractTurnUsage(raw2));
37742
+ case "assistant_message": {
37743
+ const fromTranscript = readTranscriptTurnUsage(meta3.path ?? "");
37744
+ const usage = fromTranscript.usage ?? extractTurnUsage(raw2);
37745
+ return assistantMessageData(pickString(raw2, "text", "message"), usage, fromTranscript.model);
37746
+ }
37016
37747
  case "session-end":
37017
37748
  return sessionEndData(pickString(raw2, "reason") || "Stop");
37018
37749
  default:
@@ -37027,9 +37758,8 @@ function createClaudeCodeShim() {
37027
37758
  hostCli: CLAUDE_CODE_HOST_CLI,
37028
37759
  references: CLAUDE_CODE_REFERENCES,
37029
37760
  eventMap: CLAUDE_CODE_EVENT_MAP,
37030
- extractData(raw2, logical, _meta) {
37031
- void _meta;
37032
- return claudeCodeExtractData(raw2, logical);
37761
+ extractData(raw2, logical, meta3) {
37762
+ return claudeCodeExtractData(raw2, logical, meta3);
37033
37763
  }
37034
37764
  });
37035
37765
  }
@@ -37342,6 +38072,200 @@ function capabilitiesFor(name) {
37342
38072
  return HARNESS_CAPABILITIES[name];
37343
38073
  }
37344
38074
 
38075
+ // dist/src/daemon/runtime/dashboard/harness-detect.js
38076
+ var HARNESS_MARKERS = [
38077
+ {
38078
+ name: "claude-code",
38079
+ // src/connectors/claude-code.ts: configPath() = ~/.claude/settings.json; pluginRoot = ~/.claude/plugins/honeycomb.
38080
+ paths: (h) => [join20(h, ".claude", "settings.json"), join20(h, ".claude", "plugins", "honeycomb")]
38081
+ },
38082
+ {
38083
+ name: "cursor",
38084
+ // src/connectors/cursor.ts: configPath() = ~/.cursor/hooks.json; pluginRoot = ~/.cursor/honeycomb.
38085
+ paths: (h) => [join20(h, ".cursor", "hooks.json"), join20(h, ".cursor", "honeycomb")]
38086
+ },
38087
+ {
38088
+ name: "codex",
38089
+ // hivemind-v1/src/cli/install-codex.ts: HOOKS_PATH = ~/.codex/hooks.json; PLUGIN_DIR = ~/.codex/hivemind.
38090
+ paths: (h) => [join20(h, ".codex", "hooks.json"), join20(h, ".codex", "hivemind")]
38091
+ },
38092
+ {
38093
+ name: "hermes",
38094
+ // hivemind-v1/src/cli/install-hermes.ts: CONFIG_PATH = ~/.hermes/config.yaml; HIVEMIND_DIR = ~/.hermes/hivemind.
38095
+ paths: (h) => [join20(h, ".hermes", "config.yaml"), join20(h, ".hermes", "hivemind")]
38096
+ },
38097
+ {
38098
+ name: "pi",
38099
+ // hivemind-v1/src/cli/install-pi.ts: AGENTS_MD = ~/.pi/agent/AGENTS.md; EXTENSION_PATH = ~/.pi/agent/extensions/hivemind.ts.
38100
+ paths: (h) => [
38101
+ join20(h, ".pi", "agent", "extensions", "hivemind.ts"),
38102
+ join20(h, ".pi", "agent", "AGENTS.md")
38103
+ ]
38104
+ },
38105
+ {
38106
+ name: "openclaw",
38107
+ // hivemind-v1/src/cli/install-openclaw.ts: PLUGIN_DIR = ~/.openclaw/extensions/hivemind.
38108
+ paths: (h) => [join20(h, ".openclaw", "extensions", "hivemind")]
38109
+ }
38110
+ ];
38111
+ function markerExists(path4) {
38112
+ try {
38113
+ return existsSync12(path4);
38114
+ } catch {
38115
+ return false;
38116
+ }
38117
+ }
38118
+ function detectInstalledHarnesses(homeDir = homedir16(), _cwd = process.cwd()) {
38119
+ const canonical = new Set(CANONICAL_HARNESS_IDS);
38120
+ const installed = /* @__PURE__ */ new Set();
38121
+ for (const marker of HARNESS_MARKERS) {
38122
+ if (!canonical.has(marker.name))
38123
+ continue;
38124
+ if (marker.paths(homeDir).some(markerExists))
38125
+ installed.add(marker.name);
38126
+ }
38127
+ return installed;
38128
+ }
38129
+
38130
+ // dist/src/daemon/runtime/dashboard/actions-api.js
38131
+ var ACTIONS_GROUP = "/api/actions";
38132
+ var RESTART_SHUTDOWN_DELAY_MS = 100;
38133
+ function isLoopbackOrigin(origin) {
38134
+ try {
38135
+ const host = new URL(origin).hostname;
38136
+ return host === "127.0.0.1" || host === "localhost" || host === "::1" || host === "[::1]";
38137
+ } catch {
38138
+ return false;
38139
+ }
38140
+ }
38141
+ function actionGuard(c, mode) {
38142
+ if (mode !== "local") {
38143
+ return c.json({ error: "forbidden", reason: "actions are available in local mode only" }, 403);
38144
+ }
38145
+ const site = c.req.header("sec-fetch-site");
38146
+ if (site === "cross-site" || site === "same-site") {
38147
+ return c.json({ error: "forbidden", reason: "cross-origin request rejected" }, 403);
38148
+ }
38149
+ const origin = c.req.header("origin");
38150
+ if (origin !== void 0 && origin !== "" && !isLoopbackOrigin(origin)) {
38151
+ return c.json({ error: "forbidden", reason: "untrusted origin" }, 403);
38152
+ }
38153
+ const session = c.req.header("x-honeycomb-session");
38154
+ if (session === void 0 || session.trim() === "") {
38155
+ return c.json({ error: "forbidden", reason: "missing dashboard session header" }, 403);
38156
+ }
38157
+ return null;
38158
+ }
38159
+ async function readEnabled(c) {
38160
+ try {
38161
+ const body = await c.req.json();
38162
+ if (typeof body === "object" && body !== null) {
38163
+ const v = body.enabled;
38164
+ if (typeof v === "boolean")
38165
+ return v;
38166
+ if (v === "true" || v === 1)
38167
+ return true;
38168
+ if (v === "false" || v === 0)
38169
+ return false;
38170
+ }
38171
+ return null;
38172
+ } catch {
38173
+ return null;
38174
+ }
38175
+ }
38176
+ function defaultRemoveCredentials() {
38177
+ for (const path4 of [credentialsPath(), legacyCredentialsPath()]) {
38178
+ try {
38179
+ rmSync5(path4, { force: true });
38180
+ } catch {
38181
+ }
38182
+ }
38183
+ }
38184
+ function defaultShutdown() {
38185
+ try {
38186
+ process.kill(process.pid, "SIGTERM");
38187
+ } catch {
38188
+ }
38189
+ }
38190
+ function defaultSpawnRestart() {
38191
+ const entry = process.argv[1];
38192
+ if (entry === void 0 || entry === "")
38193
+ return;
38194
+ const helper = resolve5(dirname12(entry), "restart-helper.js");
38195
+ const child = spawn4(process.execPath, [helper], {
38196
+ detached: true,
38197
+ stdio: "ignore",
38198
+ env: { ...process.env, HONEYCOMB_RESTART_ENTRY: entry, HONEYCOMB_RESTART_PORT: String(DAEMON_PORT) }
38199
+ });
38200
+ child.unref();
38201
+ }
38202
+ function defaultUninstall() {
38203
+ const harnesses = [...detectInstalledHarnesses()];
38204
+ return {
38205
+ ok: true,
38206
+ harnesses,
38207
+ removed: false,
38208
+ command: "honeycomb uninstall",
38209
+ note: "Run `honeycomb uninstall` in your terminal to remove Honeycomb's hooks from your coding assistants. It reverses only Honeycomb's changes; your DeepLake login is left intact (use Log out for that)."
38210
+ };
38211
+ }
38212
+ function mountActionsGroup(group, mode, options) {
38213
+ const embed = options.embed;
38214
+ const store = options.store;
38215
+ const removeCredentials = options.removeCredentials ?? defaultRemoveCredentials;
38216
+ const shutdown = options.shutdown ?? defaultShutdown;
38217
+ const spawnRestart = options.spawnRestart ?? defaultSpawnRestart;
38218
+ const uninstall = options.uninstall ?? defaultUninstall;
38219
+ const settingsScope = localDefaultScopeResolver(mode, options.defaultScope);
38220
+ group.post("/logout", (c) => {
38221
+ const denied = actionGuard(c, mode);
38222
+ if (denied)
38223
+ return denied;
38224
+ removeCredentials();
38225
+ return c.json({ ok: true });
38226
+ });
38227
+ group.post("/embeddings", async (c) => {
38228
+ const denied = actionGuard(c, mode);
38229
+ if (denied)
38230
+ return denied;
38231
+ const enabled = await readEnabled(c);
38232
+ if (enabled === null) {
38233
+ return c.json({ error: "bad_request", reason: "body must carry { enabled: boolean }" }, 400);
38234
+ }
38235
+ if (store !== void 0) {
38236
+ const sc = settingsScope.resolve(c);
38237
+ if (sc !== null) {
38238
+ try {
38239
+ await store.setSetting(EMBEDDINGS_ENABLED_KEY, enabled, sc);
38240
+ } catch {
38241
+ }
38242
+ }
38243
+ }
38244
+ await embed.setEnabled(enabled);
38245
+ return c.json({ ok: true, enabled });
38246
+ });
38247
+ group.post("/restart", (c) => {
38248
+ const denied = actionGuard(c, mode);
38249
+ if (denied)
38250
+ return denied;
38251
+ spawnRestart();
38252
+ setTimeout(() => shutdown(), RESTART_SHUTDOWN_DELAY_MS);
38253
+ return c.json({ ok: true, restarting: true });
38254
+ });
38255
+ group.post("/uninstall", (c) => {
38256
+ const denied = actionGuard(c, mode);
38257
+ if (denied)
38258
+ return denied;
38259
+ return c.json(uninstall());
38260
+ });
38261
+ }
38262
+ function mountActionsApi(daemon, options) {
38263
+ const group = daemon.group(ACTIONS_GROUP);
38264
+ if (group === void 0)
38265
+ return;
38266
+ mountActionsGroup(group, daemon.config.mode, options);
38267
+ }
38268
+
37345
38269
  // dist/src/daemon/runtime/dashboard/harness-api.js
37346
38270
  var HARNESS_GROUP = "/api/diagnostics";
37347
38271
  var HARNESS_PATH = "/harnesses";
@@ -37871,25 +38795,25 @@ async function tableAbsent(probe, table) {
37871
38795
  }
37872
38796
 
37873
38797
  // dist/src/daemon/runtime/dashboard/asset-install-target.js
37874
- import { existsSync as existsSync12, mkdirSync as mkdirSync14, readFileSync as readFileSync16, rmSync as rmSync5, writeFileSync as writeFileSync12 } from "node:fs";
37875
- import { homedir as homedir15 } from "node:os";
37876
- import { join as join20 } from "node:path";
37877
- var SKILLS_SUBDIR = join20(".claude", "skills");
37878
- var AGENTS_SUBDIR = join20(".claude", "agents");
38798
+ import { existsSync as existsSync13, mkdirSync as mkdirSync14, readFileSync as readFileSync17, rmSync as rmSync6, writeFileSync as writeFileSync12 } from "node:fs";
38799
+ import { homedir as homedir17 } from "node:os";
38800
+ import { join as join21 } from "node:path";
38801
+ var SKILLS_SUBDIR = join21(".claude", "skills");
38802
+ var AGENTS_SUBDIR = join21(".claude", "agents");
37879
38803
  var SKILL_FILE3 = "SKILL.md";
37880
38804
  function createFsAssetInstallTarget(dirs = {}) {
37881
38805
  const projectDir = dirs.projectDir ?? process.cwd();
37882
- const globalDir = dirs.globalDir ?? homedir15();
38806
+ const globalDir = dirs.globalDir ?? homedir17();
37883
38807
  const rootFor = (install) => install === "global" ? globalDir : projectDir;
37884
38808
  const pathFor = (assetType, install, name) => {
37885
38809
  const root = rootFor(install);
37886
38810
  const segment = sanitizeSegment3(name);
37887
38811
  if (assetType === "agent") {
37888
- const dir2 = join20(root, AGENTS_SUBDIR);
37889
- return { dir: dir2, file: join20(dir2, `${segment}.md`) };
38812
+ const dir2 = join21(root, AGENTS_SUBDIR);
38813
+ return { dir: dir2, file: join21(dir2, `${segment}.md`) };
37890
38814
  }
37891
- const dir = join20(root, SKILLS_SUBDIR, segment);
37892
- return { dir, file: join20(dir, SKILL_FILE3) };
38815
+ const dir = join21(root, SKILLS_SUBDIR, segment);
38816
+ return { dir, file: join21(dir, SKILL_FILE3) };
37893
38817
  };
37894
38818
  return {
37895
38819
  async write(assetType, install, name, body) {
@@ -37905,9 +38829,9 @@ function createFsAssetInstallTarget(dirs = {}) {
37905
38829
  async read(assetType, install, name) {
37906
38830
  try {
37907
38831
  const { file: file2 } = pathFor(assetType, install, name);
37908
- if (!existsSync12(file2))
38832
+ if (!existsSync13(file2))
37909
38833
  return null;
37910
- return readFileSync16(file2, "utf-8");
38834
+ return readFileSync17(file2, "utf-8");
37911
38835
  } catch {
37912
38836
  return null;
37913
38837
  }
@@ -37916,14 +38840,14 @@ function createFsAssetInstallTarget(dirs = {}) {
37916
38840
  try {
37917
38841
  const { dir, file: file2 } = pathFor(assetType, install, name);
37918
38842
  if (assetType === "agent") {
37919
- if (!existsSync12(file2))
38843
+ if (!existsSync13(file2))
37920
38844
  return false;
37921
- rmSync5(file2, { force: true });
38845
+ rmSync6(file2, { force: true });
37922
38846
  return true;
37923
38847
  }
37924
- if (!existsSync12(dir))
38848
+ if (!existsSync13(dir))
37925
38849
  return false;
37926
- rmSync5(dir, { recursive: true, force: true });
38850
+ rmSync6(dir, { recursive: true, force: true });
37927
38851
  return true;
37928
38852
  } catch {
37929
38853
  return false;
@@ -37931,7 +38855,7 @@ function createFsAssetInstallTarget(dirs = {}) {
37931
38855
  },
37932
38856
  exists(assetType, install, name) {
37933
38857
  try {
37934
- return existsSync12(pathFor(assetType, install, name).file);
38858
+ return existsSync13(pathFor(assetType, install, name).file);
37935
38859
  } catch {
37936
38860
  return false;
37937
38861
  }
@@ -38309,67 +39233,9 @@ function pickAssetType(value) {
38309
39233
  return typeof value === "string" && SYNCED_ASSET_TYPES.includes(value) ? value : null;
38310
39234
  }
38311
39235
 
38312
- // dist/src/daemon/runtime/dashboard/harness-detect.js
38313
- import { existsSync as existsSync13 } from "node:fs";
38314
- import { homedir as homedir16 } from "node:os";
38315
- import { join as join21 } from "node:path";
38316
- var HARNESS_MARKERS = [
38317
- {
38318
- name: "claude-code",
38319
- // src/connectors/claude-code.ts: configPath() = ~/.claude/settings.json; pluginRoot = ~/.claude/plugins/honeycomb.
38320
- paths: (h) => [join21(h, ".claude", "settings.json"), join21(h, ".claude", "plugins", "honeycomb")]
38321
- },
38322
- {
38323
- name: "cursor",
38324
- // src/connectors/cursor.ts: configPath() = ~/.cursor/hooks.json; pluginRoot = ~/.cursor/honeycomb.
38325
- paths: (h) => [join21(h, ".cursor", "hooks.json"), join21(h, ".cursor", "honeycomb")]
38326
- },
38327
- {
38328
- name: "codex",
38329
- // hivemind-v1/src/cli/install-codex.ts: HOOKS_PATH = ~/.codex/hooks.json; PLUGIN_DIR = ~/.codex/hivemind.
38330
- paths: (h) => [join21(h, ".codex", "hooks.json"), join21(h, ".codex", "hivemind")]
38331
- },
38332
- {
38333
- name: "hermes",
38334
- // hivemind-v1/src/cli/install-hermes.ts: CONFIG_PATH = ~/.hermes/config.yaml; HIVEMIND_DIR = ~/.hermes/hivemind.
38335
- paths: (h) => [join21(h, ".hermes", "config.yaml"), join21(h, ".hermes", "hivemind")]
38336
- },
38337
- {
38338
- name: "pi",
38339
- // hivemind-v1/src/cli/install-pi.ts: AGENTS_MD = ~/.pi/agent/AGENTS.md; EXTENSION_PATH = ~/.pi/agent/extensions/hivemind.ts.
38340
- paths: (h) => [
38341
- join21(h, ".pi", "agent", "extensions", "hivemind.ts"),
38342
- join21(h, ".pi", "agent", "AGENTS.md")
38343
- ]
38344
- },
38345
- {
38346
- name: "openclaw",
38347
- // hivemind-v1/src/cli/install-openclaw.ts: PLUGIN_DIR = ~/.openclaw/extensions/hivemind.
38348
- paths: (h) => [join21(h, ".openclaw", "extensions", "hivemind")]
38349
- }
38350
- ];
38351
- function markerExists(path4) {
38352
- try {
38353
- return existsSync13(path4);
38354
- } catch {
38355
- return false;
38356
- }
38357
- }
38358
- function detectInstalledHarnesses(homeDir = homedir16(), _cwd = process.cwd()) {
38359
- const canonical = new Set(CANONICAL_HARNESS_IDS);
38360
- const installed = /* @__PURE__ */ new Set();
38361
- for (const marker of HARNESS_MARKERS) {
38362
- if (!canonical.has(marker.name))
38363
- continue;
38364
- if (marker.paths(homeDir).some(markerExists))
38365
- installed.add(marker.name);
38366
- }
38367
- return installed;
38368
- }
38369
-
38370
39236
  // dist/src/daemon/runtime/dashboard/web-assets.js
38371
- import { existsSync as existsSync14, readFileSync as readFileSync17 } from "node:fs";
38372
- import { dirname as dirname12, join as join22 } from "node:path";
39237
+ import { existsSync as existsSync14, readFileSync as readFileSync18 } from "node:fs";
39238
+ import { dirname as dirname13, join as join22 } from "node:path";
38373
39239
  import { fileURLToPath as fileURLToPath2 } from "node:url";
38374
39240
  var CSS_FILES = ["tokens/fonts.css", "tokens/colors.css", "tokens/typography.css", "tokens/spacing.css", "tokens/base.css"];
38375
39241
  var LOGO_FILE = "logos/honeycomb-memory-cluster.svg";
@@ -38394,7 +39260,7 @@ var DASHBOARD_APP_BUNDLE = "dashboard-app.js";
38394
39260
  function resolveAssetsDir(startUrl = import.meta.url) {
38395
39261
  let dir;
38396
39262
  try {
38397
- dir = dirname12(fileURLToPath2(startUrl));
39263
+ dir = dirname13(fileURLToPath2(startUrl));
38398
39264
  } catch {
38399
39265
  return null;
38400
39266
  }
@@ -38402,7 +39268,7 @@ function resolveAssetsDir(startUrl = import.meta.url) {
38402
39268
  const candidate = join22(dir, "assets");
38403
39269
  if (existsSync14(join22(candidate, "styles.css")))
38404
39270
  return candidate;
38405
- const parent = dirname12(dir);
39271
+ const parent = dirname13(dir);
38406
39272
  if (parent === dir)
38407
39273
  break;
38408
39274
  dir = parent;
@@ -38411,14 +39277,14 @@ function resolveAssetsDir(startUrl = import.meta.url) {
38411
39277
  }
38412
39278
  function resolveBundleDir(startUrl = import.meta.url) {
38413
39279
  try {
38414
- return dirname12(fileURLToPath2(startUrl));
39280
+ return dirname13(fileURLToPath2(startUrl));
38415
39281
  } catch {
38416
39282
  return null;
38417
39283
  }
38418
39284
  }
38419
39285
  function readSoft(path4) {
38420
39286
  try {
38421
- return existsSync14(path4) ? readFileSync17(path4, "utf-8") : null;
39287
+ return existsSync14(path4) ? readFileSync18(path4, "utf-8") : null;
38422
39288
  } catch {
38423
39289
  return null;
38424
39290
  }
@@ -38427,7 +39293,7 @@ function readBinarySoft(path4) {
38427
39293
  try {
38428
39294
  if (!existsSync14(path4))
38429
39295
  return null;
38430
- const buf = readFileSync17(path4);
39296
+ const buf = readFileSync18(path4);
38431
39297
  return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
38432
39298
  } catch {
38433
39299
  return null;
@@ -38523,24 +39389,27 @@ function mountDashboardHost(daemon, options = {}) {
38523
39389
  if (root === void 0)
38524
39390
  return;
38525
39391
  const assets = options.assets ?? createWebAssets();
38526
- root.get(DASHBOARD_HOST_PATH, (c) => c.html(renderShell()));
39392
+ root.get(DASHBOARD_HOST_PATH, (c) => {
39393
+ c.header("cache-control", "no-cache");
39394
+ return c.html(renderShell());
39395
+ });
38527
39396
  root.get(DASHBOARD_APP_PATH, (c) => {
38528
39397
  const asset = assets.appJs();
38529
39398
  if (asset === null)
38530
39399
  return c.text("dashboard bundle not built", 404);
38531
- return c.body(asset.body, 200, { "content-type": asset.contentType });
39400
+ return c.body(asset.body, 200, { "content-type": asset.contentType, "cache-control": "no-cache" });
38532
39401
  });
38533
39402
  root.get(DASHBOARD_CSS_PATH, (c) => {
38534
39403
  const asset = assets.css();
38535
39404
  if (asset === null)
38536
39405
  return c.text("dashboard styles unavailable", 404);
38537
- return c.body(asset.body, 200, { "content-type": asset.contentType });
39406
+ return c.body(asset.body, 200, { "content-type": asset.contentType, "cache-control": "no-cache" });
38538
39407
  });
38539
39408
  root.get(DASHBOARD_LOGO_PATH, (c) => {
38540
39409
  const asset = assets.logo();
38541
39410
  if (asset === null)
38542
39411
  return c.text("dashboard logo unavailable", 404);
38543
- return c.body(asset.body, 200, { "content-type": asset.contentType });
39412
+ return c.body(asset.body, 200, { "content-type": asset.contentType, "cache-control": "no-cache" });
38544
39413
  });
38545
39414
  root.get(DASHBOARD_FONT_PATH, (c) => {
38546
39415
  const asset = assets.font(c.req.param("name"));
@@ -38589,8 +39458,8 @@ function mountSetupLogin(daemon, options = {}) {
38589
39458
  };
38590
39459
  let rejectGrant = () => {
38591
39460
  };
38592
- const grantReady = new Promise((resolve6, reject) => {
38593
- resolveGrant = resolve6;
39461
+ const grantReady = new Promise((resolve7, reject) => {
39462
+ resolveGrant = resolve7;
38594
39463
  rejectGrant = reject;
38595
39464
  });
38596
39465
  const deps = {
@@ -38621,7 +39490,7 @@ function mountSetupLogin(daemon, options = {}) {
38621
39490
 
38622
39491
  // dist/src/daemon/runtime/dashboard/setup-state.js
38623
39492
  import { existsSync as existsSync15 } from "node:fs";
38624
- import { homedir as homedir17 } from "node:os";
39493
+ import { homedir as homedir18 } from "node:os";
38625
39494
  import { join as join23 } from "node:path";
38626
39495
  var SETUP_STATE_PATH = "/setup/state";
38627
39496
  var SETUP_STATE_GROUP = "/";
@@ -38644,7 +39513,7 @@ function derivePriorTool(recorded, hivemindDirPresent) {
38644
39513
  return hivemindDirPresent ? { hivemind: "present" } : recorded;
38645
39514
  }
38646
39515
  function resolveSetupState(deps = {}) {
38647
- const home = deps.homeDir ?? homedir17();
39516
+ const home = deps.homeDir ?? homedir18();
38648
39517
  const env = deps.env ?? process.env;
38649
39518
  const onboarding = loadOnboarding(deps.onboardingDir);
38650
39519
  const legacyCredentialsDir = deps.legacyCredentialsDir ?? join23(home, LEGACY_CREDENTIALS_DIR_NAME);
@@ -38679,8 +39548,8 @@ function mountSetupStateApi(daemon, deps = {}) {
38679
39548
 
38680
39549
  // dist/src/daemon/runtime/onboarding/hivemind-uninstall.js
38681
39550
  import { execFileSync as execFileSync5 } from "node:child_process";
38682
- import { cpSync, existsSync as existsSync16, rmSync as rmSync6 } from "node:fs";
38683
- import { homedir as homedir18 } from "node:os";
39551
+ import { cpSync, existsSync as existsSync16, rmSync as rmSync7 } from "node:fs";
39552
+ import { homedir as homedir19 } from "node:os";
38684
39553
  import { join as join24 } from "node:path";
38685
39554
  var HIVEMIND_DIR_NAME2 = ".hivemind";
38686
39555
  var HIVEMIND_NPM_PACKAGE = "@deeplake/hivemind";
@@ -38702,7 +39571,7 @@ function hivemindBackupPath(home, iso) {
38702
39571
  return join24(home, `${HIVEMIND_BACKUP_PREFIX}${safe}`);
38703
39572
  }
38704
39573
  function backupAndUninstallHivemind(deps = {}) {
38705
- const home = deps.homeDir ?? homedir18();
39574
+ const home = deps.homeDir ?? homedir19();
38706
39575
  const npmRemove = deps.npmRemove ?? defaultNpmGlobalRemover;
38707
39576
  const dir = hivemindDirPath(home);
38708
39577
  let npmRemoved = false;
@@ -38718,7 +39587,7 @@ function backupAndUninstallHivemind(deps = {}) {
38718
39587
  const backupPath = hivemindBackupPath(home, iso);
38719
39588
  cpSync(dir, backupPath, { recursive: true });
38720
39589
  try {
38721
- rmSync6(dir, { recursive: true, force: true });
39590
+ rmSync7(dir, { recursive: true, force: true });
38722
39591
  return { removed: true, backupPath, npmRemoved };
38723
39592
  } catch {
38724
39593
  return { removed: false, backupPath, npmRemoved };
@@ -38727,9 +39596,9 @@ function backupAndUninstallHivemind(deps = {}) {
38727
39596
  function restoreHivemindBackup(backupPath, deps = {}) {
38728
39597
  if (backupPath.length === 0 || !existsSync16(backupPath))
38729
39598
  return false;
38730
- const home = deps.homeDir ?? homedir18();
39599
+ const home = deps.homeDir ?? homedir19();
38731
39600
  const dir = hivemindDirPath(home);
38732
- rmSync6(dir, { recursive: true, force: true });
39601
+ rmSync7(dir, { recursive: true, force: true });
38733
39602
  cpSync(backupPath, dir, { recursive: true });
38734
39603
  return true;
38735
39604
  }
@@ -39549,8 +40418,8 @@ function resolveProjectsScope(c, defaultScope) {
39549
40418
 
39550
40419
  // dist/src/daemon/runtime/projects/onboarding-api.js
39551
40420
  import { existsSync as existsSync17, readdirSync as readdirSync3, realpathSync, statSync as statSync2 } from "node:fs";
39552
- import { homedir as homedir19 } from "node:os";
39553
- import { isAbsolute as isAbsolute2, join as join25, resolve as resolve5, sep as sep3 } from "node:path";
40421
+ import { homedir as homedir20 } from "node:os";
40422
+ import { isAbsolute as isAbsolute2, join as join25, resolve as resolve6, sep as sep3 } from "node:path";
39554
40423
  var ONBOARDING_GROUP = "/api/diagnostics";
39555
40424
  var FS_BROWSE_PATH = "/fs/browse";
39556
40425
  var PROJECTS_BIND_PATH = "/projects/bind";
@@ -39578,19 +40447,19 @@ function suggestProjectId(absPath, readRemote) {
39578
40447
  return repo;
39579
40448
  }
39580
40449
  }
39581
- const segs = resolve5(absPath).split(sep3).filter((s) => s.length > 0);
40450
+ const segs = resolve6(absPath).split(sep3).filter((s) => s.length > 0);
39582
40451
  const base = segs[segs.length - 1];
39583
40452
  return base ?? "";
39584
40453
  }
39585
40454
  function canonicalize(absPath) {
39586
- let head = resolve5(absPath);
40455
+ let head = resolve6(absPath);
39587
40456
  const tail = [];
39588
40457
  for (; ; ) {
39589
40458
  try {
39590
40459
  const real = realpathSync(head);
39591
40460
  return stripTrailingSep(tail.length > 0 ? join25(real, ...tail.reverse()) : real);
39592
40461
  } catch {
39593
- const parent = resolve5(head, "..");
40462
+ const parent = resolve6(head, "..");
39594
40463
  if (parent === head)
39595
40464
  return stripTrailingSep(head);
39596
40465
  const segmentStart = parent.endsWith(sep3) ? parent.length : parent.length + sep3.length;
@@ -39617,7 +40486,7 @@ function parentWithinRoot(dir, root) {
39617
40486
  const normalizedRoot = root;
39618
40487
  if (dir === normalizedRoot)
39619
40488
  return null;
39620
- const parent = canonicalize(resolve5(dir, ".."));
40489
+ const parent = canonicalize(resolve6(dir, ".."));
39621
40490
  return parent === normalizedRoot || parent.startsWith(normalizedRoot + sep3) ? parent : normalizedRoot;
39622
40491
  }
39623
40492
  function listChildDirs(dir) {
@@ -39655,7 +40524,7 @@ function mountOnboardingApi(daemon, options) {
39655
40524
  if (group === void 0)
39656
40525
  return;
39657
40526
  const mode = daemon.config.mode;
39658
- const root = canonicalize(options.browseRoot ?? homedir19());
40527
+ const root = canonicalize(options.browseRoot ?? homedir20());
39659
40528
  const readRemote = options.readRemote ?? defaultGitRemoteReader;
39660
40529
  const notLocal = () => mode !== "local";
39661
40530
  group.get(FS_BROWSE_PATH, (c) => {
@@ -39747,7 +40616,7 @@ function resolveBindPath(path4) {
39747
40616
  const trimmed = path4.trim();
39748
40617
  if (trimmed.length === 0 || !isAbsolute2(trimmed))
39749
40618
  return null;
39750
- return resolve5(trimmed);
40619
+ return resolve6(trimmed);
39751
40620
  }
39752
40621
  function rejectBind(path4, reason) {
39753
40622
  return { bound: false, path: path4, projectId: "", error: reason };
@@ -39776,9 +40645,9 @@ function remoteFor(absPath, readRemote) {
39776
40645
  return raw2 !== null ? canonicalizeRemote(raw2) : "";
39777
40646
  }
39778
40647
  function removeBinding(absPath, options) {
39779
- const normalized = stripTrailingSep(resolve5(absPath));
40648
+ const normalized = stripTrailingSep(resolve6(absPath));
39780
40649
  const loaded = loadProjectsCache(options.projectsDir);
39781
- const kept = loaded.bindings.filter((b) => stripTrailingSep(resolve5(b.path)) !== normalized);
40650
+ const kept = loaded.bindings.filter((b) => stripTrailingSep(resolve6(b.path)) !== normalized);
39782
40651
  if (kept.length === loaded.bindings.length) {
39783
40652
  return { unbound: false, path: normalized };
39784
40653
  }
@@ -41384,7 +42253,7 @@ function recordKey(record2) {
41384
42253
  // dist/src/daemon/runtime/notifications/api.js
41385
42254
  var NOTIFICATIONS_GROUP = "/api/diagnostics";
41386
42255
  var NOTIFICATIONS_PATH = "/notifications";
41387
- var headerScopeResolver = {
42256
+ var headerScopeResolver2 = {
41388
42257
  resolve(c) {
41389
42258
  const org = c.req.header("x-honeycomb-org");
41390
42259
  if (org === void 0 || org.length === 0)
@@ -41428,7 +42297,7 @@ function mountNotificationsApi(daemon, options) {
41428
42297
  if (group === void 0)
41429
42298
  return;
41430
42299
  const table = options.table ?? "notifications";
41431
- const scopeResolver = options.scope ?? headerScopeResolver;
42300
+ const scopeResolver = options.scope ?? headerScopeResolver2;
41432
42301
  group.get(NOTIFICATIONS_PATH, async (c) => {
41433
42302
  const scope = scopeResolver.resolve(c);
41434
42303
  if (scope === null) {
@@ -41614,6 +42483,8 @@ var DEFAULT_TRAVERSAL_MIN_EDGE_WEIGHT = 0.3;
41614
42483
  var DEFAULT_TRAVERSAL_TIMEOUT_MS = 500;
41615
42484
  var DEFAULT_RERANKER = "none";
41616
42485
  var DEFAULT_RERANKER_TIMEOUT_MS = 300;
42486
+ var DEFAULT_RERANKER_PROVIDER_TIMEOUT_MS = 1e3;
42487
+ var DEFAULT_RERANKER_COHERE_MODEL = "rerank-v3.5";
41617
42488
  var DEFAULT_RERANKER_WINDOW = 50;
41618
42489
  var DEFAULT_DEDUP_ENABLED = true;
41619
42490
  var DEFAULT_DEDUP_SIMILARITY_THRESHOLD = 0.9;
@@ -41632,7 +42503,7 @@ var DEFAULT_RESOLUTION_BOOST = 1.25;
41632
42503
  var DEFAULT_REHEARSAL_BOOST = 1.1;
41633
42504
  var DEFAULT_REHEARSAL_WINDOW_MS = 7 * 24 * 60 * 60 * 1e3;
41634
42505
  var DEFAULT_MIN_INJECTION_SCORE = 0.6;
41635
- var RERANKER_STRATEGIES = Object.freeze(["embedding-cosine", "llm", "none"]);
42506
+ var RERANKER_STRATEGIES = Object.freeze(["embedding-cosine", "llm", "cohere", "none"]);
41636
42507
  var BoolFlag3 = external_exports.preprocess((raw2) => {
41637
42508
  if (typeof raw2 === "boolean")
41638
42509
  return raw2;
@@ -41687,12 +42558,26 @@ var TraversalConfigSchema = external_exports.object({
41687
42558
  timeoutMs: ClampedInt4(DEFAULT_TRAVERSAL_TIMEOUT_MS, 1).default(DEFAULT_TRAVERSAL_TIMEOUT_MS)
41688
42559
  });
41689
42560
  var RerankerConfigSchema = external_exports.object({
41690
- /** The reranker strategy (D-4). */
42561
+ /** The reranker strategy (D-4 + PRD-063c). */
41691
42562
  strategy: external_exports.enum(RERANKER_STRATEGIES).default(DEFAULT_RERANKER),
41692
- /** Reranker timeout in ms; on timeout keep the original order (d-AC-2 / b-AC-2). */
42563
+ /** Reranker timeout in ms; on timeout keep the original order (d-AC-2 / b-AC-2). LOCAL-cosine budget. */
41693
42564
  timeoutMs: ClampedInt4(DEFAULT_RERANKER_TIMEOUT_MS, 1).default(DEFAULT_RERANKER_TIMEOUT_MS),
42565
+ /**
42566
+ * The PROVIDER-rerank timeout in ms (PRD-063c / c-AC-3): the budget for the `cohere` outbound
42567
+ * Portkey round-trip, larger than the local-cosine {@link timeoutMs} because it crosses the
42568
+ * network. A `cohere` call that exceeds it FAILS SOFT to the RRF order. Defaults to
42569
+ * {@link DEFAULT_RERANKER_PROVIDER_TIMEOUT_MS} (1000ms); the local-cosine path never reads it.
42570
+ */
42571
+ providerTimeoutMs: ClampedInt4(DEFAULT_RERANKER_PROVIDER_TIMEOUT_MS, 1).default(DEFAULT_RERANKER_PROVIDER_TIMEOUT_MS),
41694
42572
  /** Rerank window N: how many fused top-N candidates to re-score (PRD-047b). */
41695
- window: ClampedInt4(DEFAULT_RERANKER_WINDOW, 1).default(DEFAULT_RERANKER_WINDOW)
42573
+ window: ClampedInt4(DEFAULT_RERANKER_WINDOW, 1).default(DEFAULT_RERANKER_WINDOW),
42574
+ /**
42575
+ * The Cohere rerank `model` id sent to Portkey when the strategy is `cohere` (PRD-063c / c-D-1).
42576
+ * Defaults to {@link DEFAULT_RERANKER_COHERE_MODEL}; the operator may override it (or configure
42577
+ * the model inside Portkey). A non-string env value falls back to the default. Only the `cohere`
42578
+ * strategy reads it.
42579
+ */
42580
+ cohereModel: external_exports.string().min(1).catch(DEFAULT_RERANKER_COHERE_MODEL).default(DEFAULT_RERANKER_COHERE_MODEL)
41696
42581
  });
41697
42582
  var DedupConfigSchema = external_exports.object({
41698
42583
  /** Whether semantic near-duplicate dedup runs; ON by default (PRD-047c / c-AC-3). */
@@ -41792,7 +42677,9 @@ function envRecallConfigProvider(env = process.env) {
41792
42677
  reranker: {
41793
42678
  strategy: env.HONEYCOMB_RECALL_RERANKER,
41794
42679
  timeoutMs: env.HONEYCOMB_RECALL_RERANKER_TIMEOUT_MS,
41795
- window: env.HONEYCOMB_RECALL_RERANKER_WINDOW
42680
+ providerTimeoutMs: env.HONEYCOMB_RECALL_RERANKER_PROVIDER_TIMEOUT_MS,
42681
+ window: env.HONEYCOMB_RECALL_RERANKER_WINDOW,
42682
+ cohereModel: env.HONEYCOMB_RECALL_RERANKER_COHERE_MODEL
41796
42683
  },
41797
42684
  dampening: {
41798
42685
  gravity: env.HONEYCOMB_RECALL_DAMPENING_GRAVITY,
@@ -41861,10 +42748,10 @@ var Semaphore = class {
41861
42748
  this.held += 1;
41862
42749
  return Promise.resolve();
41863
42750
  }
41864
- return new Promise((resolve6) => {
42751
+ return new Promise((resolve7) => {
41865
42752
  this.waiters.push(() => {
41866
42753
  this.held += 1;
41867
- resolve6();
42754
+ resolve7();
41868
42755
  });
41869
42756
  });
41870
42757
  }
@@ -42367,9 +43254,16 @@ async function fetchCandidateEmbeddings(candidates, request, deps) {
42367
43254
  }
42368
43255
  async function rerankHits(hits, queryVector, config2, request, deps) {
42369
43256
  const rrfOrder = [...hits];
43257
+ if (hits.length === 0)
43258
+ return rrfOrder;
43259
+ if (config2.strategy === "cohere") {
43260
+ if (deps.cohereRerank === void 0)
43261
+ return rrfOrder;
43262
+ return rerankWithCohere(rrfOrder, config2, request, deps, deps.cohereRerank);
43263
+ }
42370
43264
  if (config2.strategy !== "embedding-cosine")
42371
43265
  return rrfOrder;
42372
- if (hits.length === 0)
43266
+ if (queryVector === null)
42373
43267
  return rrfOrder;
42374
43268
  const now = deps.now ?? Date.now;
42375
43269
  const start = now();
@@ -42400,6 +43294,56 @@ async function rerankHits(hits, queryVector, config2, request, deps) {
42400
43294
  return rrfOrder;
42401
43295
  }
42402
43296
  }
43297
+ async function rerankWithCohere(rrfOrder, config2, request, deps, seam) {
43298
+ const baseOrder = [...rrfOrder];
43299
+ const now = deps.now ?? Date.now;
43300
+ const start = now();
43301
+ const window = Math.max(1, Math.trunc(config2.window));
43302
+ const head = baseOrder.slice(0, window);
43303
+ const tail = baseOrder.slice(window);
43304
+ const documents = head.map((h) => h.text);
43305
+ try {
43306
+ const timeoutMs = Math.max(1, Math.trunc(config2.providerTimeoutMs));
43307
+ const TIMED_OUT = /* @__PURE__ */ Symbol("rerank-timeout");
43308
+ let timer;
43309
+ const timeout = new Promise((resolve7) => {
43310
+ timer = setTimeout(() => resolve7(TIMED_OUT), timeoutMs);
43311
+ });
43312
+ let outcome;
43313
+ try {
43314
+ outcome = await Promise.race([seam.rerank(request.query, documents, head.length), timeout]);
43315
+ } finally {
43316
+ if (timer !== void 0)
43317
+ clearTimeout(timer);
43318
+ }
43319
+ if (outcome === TIMED_OUT || outcome.ok === false)
43320
+ return baseOrder;
43321
+ const scoreByIndex = /* @__PURE__ */ new Map();
43322
+ for (const r of outcome.results) {
43323
+ if (r.index >= 0 && r.index < head.length && !scoreByIndex.has(r.index)) {
43324
+ scoreByIndex.set(r.index, r.relevanceScore);
43325
+ }
43326
+ }
43327
+ const scoredSlots = [];
43328
+ for (let i = 0; i < head.length; i++) {
43329
+ if (scoreByIndex.has(i))
43330
+ scoredSlots.push(i);
43331
+ }
43332
+ const orderedByScore = scoredSlots.map((index) => ({ index, score: scoreByIndex.get(index) })).sort((a, b) => {
43333
+ if (b.score !== a.score)
43334
+ return b.score - a.score;
43335
+ return a.index - b.index;
43336
+ });
43337
+ const reorderedHead = head.slice();
43338
+ scoredSlots.forEach((slot, i) => {
43339
+ reorderedHead[slot] = head[orderedByScore[i].index];
43340
+ });
43341
+ void start;
43342
+ return [...reorderedHead, ...tail];
43343
+ } catch {
43344
+ return baseOrder;
43345
+ }
43346
+ }
42403
43347
  function provenanceRank(source) {
42404
43348
  if (source === "memories")
42405
43349
  return 0;
@@ -42739,11 +43683,15 @@ async function recallMemories(request, deps) {
42739
43683
  rowsToRankedArm(sessionsRows)
42740
43684
  ];
42741
43685
  const { hits, sources } = fuseHits(arms, limit);
42742
- const rerankerConfig = deps.reranker ?? { strategy: DEFAULT_RERANKER, timeoutMs: DEFAULT_RERANKER_TIMEOUT_MS, window: DEFAULT_RERANKER_WINDOW };
42743
- const ranked = semanticRun === null || rerankerConfig.strategy === "none" ? (
42744
- // No query vector to rerank against, or RRF-only requested → keep the fused order.
42745
- hits
42746
- ) : await rerankHits(hits, semanticRun.queryVector, rerankerConfig, request, deps);
43686
+ const rerankerConfig = deps.reranker ?? {
43687
+ strategy: DEFAULT_RERANKER,
43688
+ timeoutMs: DEFAULT_RERANKER_TIMEOUT_MS,
43689
+ providerTimeoutMs: DEFAULT_RERANKER_PROVIDER_TIMEOUT_MS,
43690
+ window: DEFAULT_RERANKER_WINDOW,
43691
+ cohereModel: DEFAULT_RERANKER_COHERE_MODEL
43692
+ };
43693
+ const skipRerank = rerankerConfig.strategy === "none" || rerankerConfig.strategy !== "cohere" && semanticRun === null;
43694
+ const ranked = skipRerank ? hits : await rerankHits(hits, semanticRun?.queryVector ?? null, rerankerConfig, request, deps);
42747
43695
  const dedupConfig = deps.dedup ?? { enabled: DEFAULT_DEDUP_ENABLED, similarityThreshold: DEFAULT_DEDUP_SIMILARITY_THRESHOLD };
42748
43696
  const deduped = await dedupHits(ranked, dedupConfig, request, deps);
42749
43697
  const dedupedSources = deduped.length === ranked.length ? sources : [...new Set(deduped.map((h) => h.source))];
@@ -42772,470 +43720,6 @@ async function recallMemories(request, deps) {
42772
43720
  }
42773
43721
  }
42774
43722
 
42775
- // dist/src/daemon/runtime/secrets/api.js
42776
- function localDefaultScopeResolver(mode, defaultScope) {
42777
- return {
42778
- resolve(c) {
42779
- const fromHeader = headerScopeResolver2.resolve(c);
42780
- if (fromHeader !== null)
42781
- return fromHeader;
42782
- if (mode === "local" && defaultScope !== void 0) {
42783
- return { org: defaultScope.org, workspace: defaultScope.workspace ?? "default" };
42784
- }
42785
- return null;
42786
- }
42787
- };
42788
- }
42789
- var headerScopeResolver2 = {
42790
- resolve(c) {
42791
- const org = c.req.header("x-honeycomb-org");
42792
- if (org === void 0 || org.length === 0)
42793
- return null;
42794
- const workspace = c.req.header("x-honeycomb-workspace");
42795
- const agentId = c.req.header("x-honeycomb-agent");
42796
- const ws = workspace !== void 0 && workspace.length > 0 ? workspace : "default";
42797
- return agentId !== void 0 && agentId.length > 0 ? { org, workspace: ws, agentId } : { org, workspace: ws };
42798
- }
42799
- };
42800
- function mountSecretsApi(group, deps) {
42801
- const scope = deps.scope ?? headerScopeResolver2;
42802
- const store = deps.store;
42803
- const runner = deps.execRunner;
42804
- if (runner !== void 0) {
42805
- group.post("/exec", async (c) => {
42806
- const sc = scope.resolve(c);
42807
- if (sc === null)
42808
- return badTenancy(c);
42809
- const request = await readExecRequest(c, sc);
42810
- if (request === null) {
42811
- return c.json({ error: "bad_request", reason: "exec body must carry a command" }, 400);
42812
- }
42813
- const res = runner.submit(request);
42814
- if (!res.ok) {
42815
- if (res.reason === "queue_full") {
42816
- return c.json({ error: "queue_full", reason: "exec pool and queue are at capacity" }, 429);
42817
- }
42818
- return c.json({ error: "bad_request", reason: "invalid exec request" }, 400);
42819
- }
42820
- return c.json({ ok: true, jobId: res.jobId, status: "queued" }, 202);
42821
- });
42822
- group.get("/exec/:jobId", (c) => {
42823
- const sc = scope.resolve(c);
42824
- if (sc === null)
42825
- return badTenancy(c);
42826
- const jobId = c.req.param("jobId");
42827
- const view = runner.getStatus(jobId, sc);
42828
- if (view === null) {
42829
- return c.json({ error: "not_found", reason: "no such exec job" }, 404);
42830
- }
42831
- return c.json(view);
42832
- });
42833
- group.all("/bitwarden/*", (c) => c.json({ error: "use_exec", reason: "reference a Bitwarden item via exec vaultRefs; values are never returned" }, 400));
42834
- group.all("/1password/*", (c) => c.json({ error: "use_exec", reason: "reference a 1Password item via exec vaultRefs; values are never returned" }, 400));
42835
- } else {
42836
- group.post("/exec", (c) => notImplementedRoute(c, "POST /api/secrets/exec (secret_exec)"));
42837
- group.get("/exec/:jobId", (c) => notImplementedRoute(c, "GET /api/secrets/exec/:jobId (exec status)"));
42838
- group.all("/bitwarden/*", (c) => notImplementedRoute(c, "Bitwarden vault provider"));
42839
- group.all("/1password/*", (c) => notImplementedRoute(c, "1Password vault provider"));
42840
- }
42841
- group.get("/", (c) => {
42842
- const sc = scope.resolve(c);
42843
- if (sc === null)
42844
- return badTenancy(c);
42845
- const names = store.listSecretNames(sc);
42846
- return c.json({ names });
42847
- });
42848
- group.post("/:name", async (c) => {
42849
- const sc = scope.resolve(c);
42850
- if (sc === null)
42851
- return badTenancy(c);
42852
- const name = c.req.param("name");
42853
- const value = await readValue(c);
42854
- if (value === null) {
42855
- return c.json({ error: "bad_request", reason: "request body must carry a string value" }, 400);
42856
- }
42857
- const res = await store.setSecret(name, value, sc);
42858
- if (!res.ok) {
42859
- if (res.reason === "invalid_name") {
42860
- return c.json({ error: "bad_request", reason: "invalid secret name" }, 400);
42861
- }
42862
- return c.json({ error: "store_failed", reason: "could not store the secret" }, 502);
42863
- }
42864
- return c.json({ ok: true, name }, 201);
42865
- });
42866
- group.delete("/:name", (c) => {
42867
- const sc = scope.resolve(c);
42868
- if (sc === null)
42869
- return badTenancy(c);
42870
- const name = c.req.param("name");
42871
- const res = store.deleteSecret(name, sc);
42872
- if (!res.ok) {
42873
- if (res.reason === "invalid_name") {
42874
- return c.json({ error: "bad_request", reason: "invalid secret name" }, 400);
42875
- }
42876
- if (res.reason === "not_found") {
42877
- return c.json({ error: "not_found", reason: "no such secret" }, 404);
42878
- }
42879
- return c.json({ error: "delete_failed", reason: "could not delete the secret" }, 502);
42880
- }
42881
- return c.json({ ok: true, name });
42882
- });
42883
- }
42884
- function badTenancy(c) {
42885
- return c.json({ error: "bad_request", reason: "x-honeycomb-org header is required" }, 400);
42886
- }
42887
- async function readValue(c) {
42888
- const contentType = c.req.header("content-type") ?? "";
42889
- if (contentType.includes("application/json")) {
42890
- try {
42891
- const body = await c.req.json();
42892
- if (typeof body === "object" && body !== null) {
42893
- const v = body.value;
42894
- if (typeof v === "string" && v.length > 0)
42895
- return v;
42896
- }
42897
- return null;
42898
- } catch {
42899
- return null;
42900
- }
42901
- }
42902
- const text = await c.req.text();
42903
- return text.length > 0 ? text : null;
42904
- }
42905
- function notImplementedRoute(c, what) {
42906
- return c.json({ error: "not_implemented", reason: `${what} is implemented in PRD-012b` }, 501);
42907
- }
42908
- async function readExecRequest(c, scope) {
42909
- let body;
42910
- try {
42911
- body = await c.req.json();
42912
- } catch {
42913
- return null;
42914
- }
42915
- if (typeof body !== "object" || body === null)
42916
- return null;
42917
- const b = body;
42918
- const command = b.command;
42919
- if (typeof command !== "string" || command.length === 0)
42920
- return null;
42921
- const args = Array.isArray(b.args) ? b.args.filter((a) => typeof a === "string") : [];
42922
- const secretNames = Array.isArray(b.secretNames) ? b.secretNames.filter((n) => typeof n === "string") : [];
42923
- const vaultRefs = {};
42924
- if (typeof b.vaultRefs === "object" && b.vaultRefs !== null) {
42925
- for (const [k, v] of Object.entries(b.vaultRefs)) {
42926
- if (typeof v === "string")
42927
- vaultRefs[k] = v;
42928
- }
42929
- }
42930
- const timeoutMs = typeof b.timeoutMs === "number" ? b.timeoutMs : void 0;
42931
- return { command, args, secretNames, vaultRefs, scope, timeoutMs };
42932
- }
42933
-
42934
- // dist/src/daemon/runtime/vault/catalog.js
42935
- var PROVIDER_CATALOG = Object.freeze([
42936
- Object.freeze({
42937
- id: "anthropic",
42938
- label: "Anthropic",
42939
- models: Object.freeze(["claude-sonnet-4-6", "claude-opus-4-8"]),
42940
- openEnded: false
42941
- }),
42942
- Object.freeze({
42943
- id: "openai",
42944
- label: "OpenAI",
42945
- models: Object.freeze(["gpt-4o", "gpt-4o-mini", "gpt-4.1"]),
42946
- openEnded: false
42947
- }),
42948
- Object.freeze({
42949
- id: "openrouter",
42950
- label: "OpenRouter",
42951
- // Suggestions only — OpenRouter accepts a free-form `vendor/model` id (passthrough).
42952
- models: Object.freeze(["anthropic/claude-sonnet-4.6", "openai/gpt-4o"]),
42953
- openEnded: true
42954
- })
42955
- ]);
42956
- function providerEntry(provider) {
42957
- return PROVIDER_CATALOG.find((p) => p.id === provider);
42958
- }
42959
- function isValidProviderModel(provider, model) {
42960
- const entry = providerEntry(provider);
42961
- if (entry === void 0)
42962
- return false;
42963
- if (typeof model !== "string" || model.length === 0)
42964
- return false;
42965
- if (entry.openEnded)
42966
- return true;
42967
- return entry.models.includes(model);
42968
- }
42969
- function catalogView() {
42970
- return PROVIDER_CATALOG;
42971
- }
42972
-
42973
- // dist/src/daemon/runtime/secrets/contracts.js
42974
- import { homedir as homedir20, hostname as hostname4, userInfo } from "node:os";
42975
- var SECRET_NAME_PATTERN = /^[A-Za-z0-9_.-]+$/;
42976
- var MAX_SECRET_NAME_LENGTH = 128;
42977
- function isValidSecretName(value) {
42978
- if (typeof value !== "string")
42979
- return false;
42980
- if (value.length === 0 || value.length > MAX_SECRET_NAME_LENGTH)
42981
- return false;
42982
- if (value === "." || value === "..")
42983
- return false;
42984
- if (value.includes("/") || value.includes("\\") || value.includes("\0"))
42985
- return false;
42986
- return SECRET_NAME_PATTERN.test(value);
42987
- }
42988
- function asSecretName(value) {
42989
- return isValidSecretName(value) ? value : null;
42990
- }
42991
- function isSecretRecord(value) {
42992
- if (typeof value !== "object" || value === null)
42993
- return false;
42994
- const r = value;
42995
- if (typeof r.nonce !== "string" || typeof r.ciphertext !== "string" || typeof r.createdAt !== "string") {
42996
- return false;
42997
- }
42998
- const scope = r.scope;
42999
- if (typeof scope !== "object" || scope === null)
43000
- return false;
43001
- const s = scope;
43002
- if (typeof s.org !== "string" || typeof s.workspace !== "string")
43003
- return false;
43004
- if (s.agentId !== void 0 && typeof s.agentId !== "string")
43005
- return false;
43006
- return true;
43007
- }
43008
- var MACHINE_KEY_DIR_NAME = ".honeycomb";
43009
- var MACHINE_KEY_FILE_NAME = ".machine-key";
43010
- function hostnameUserFallbackId() {
43011
- let user = "";
43012
- try {
43013
- user = userInfo().username;
43014
- } catch {
43015
- user = "";
43016
- }
43017
- return `host:${hostname4()}|user:${user}|home:${homedir20()}`;
43018
- }
43019
-
43020
- // dist/src/daemon/runtime/vault/contracts.js
43021
- function asRecordClass(value) {
43022
- return isValidSecretName(value) ? value : null;
43023
- }
43024
-
43025
- // dist/src/daemon/runtime/vault/registry.js
43026
- var SECRET_CLASS = "secret";
43027
- var SETTING_CLASS = "setting";
43028
- var SecretValueSchema = external_exports.string().min(1);
43029
- var SettingValueSchema = external_exports.union([external_exports.string(), external_exports.number().finite(), external_exports.boolean()]);
43030
- var SECRET_DESCRIPTOR = Object.freeze({
43031
- id: SECRET_CLASS,
43032
- posture: "internal-only",
43033
- schema: SecretValueSchema
43034
- });
43035
- var SETTING_DESCRIPTOR = Object.freeze({
43036
- id: SETTING_CLASS,
43037
- posture: "daemon-readable",
43038
- schema: SettingValueSchema
43039
- });
43040
- var VaultRegistry = class {
43041
- table;
43042
- constructor(descriptors) {
43043
- this.table = /* @__PURE__ */ new Map();
43044
- for (const d of descriptors)
43045
- this.table.set(d.id, d);
43046
- }
43047
- /**
43048
- * Register a new record class (D-7). Validates the id is traversal-proof (a class is an
43049
- * on-disk segment) and that the posture is one the store understands, then adds the
43050
- * descriptor. Re-registering an existing id REPLACES it (so a test can swap a throwaway
43051
- * class); registering the built-in `secret`/`setting` ids is allowed but discouraged —
43052
- * their posture must not be loosened. Returns the registry for chaining.
43053
- *
43054
- * Throws on an invalid (traversal-unsafe) class id — that is a programming error, not a
43055
- * runtime input, so it fails loud rather than silently dropping the class.
43056
- */
43057
- registerClass(descriptor) {
43058
- const safe = asRecordClass(descriptor.id);
43059
- if (safe === null) {
43060
- throw new Error(`vault.registerClass: invalid (traversal-unsafe) class id`);
43061
- }
43062
- this.table.set(descriptor.id, descriptor);
43063
- return this;
43064
- }
43065
- /** Whether a class id is registered. */
43066
- has(klass) {
43067
- return this.table.has(klass);
43068
- }
43069
- /** The registered class ids (sorted), for diagnostics — never values. */
43070
- classIds() {
43071
- return [...this.table.keys()].sort();
43072
- }
43073
- /**
43074
- * Resolve a class's descriptor for a WRITE, validating the value against the class
43075
- * schema (zod-at-boundary). Returns `unknown_class` for an unregistered class or
43076
- * `invalid_value` when the value fails the schema — both fail-closed (nothing is
43077
- * written). On success the descriptor (with the validated value available via the
43078
- * caller's re-parse) is returned.
43079
- */
43080
- resolveForWrite(klass, value) {
43081
- const descriptor = this.table.get(klass);
43082
- if (descriptor === void 0)
43083
- return { ok: false, reason: "unknown_class" };
43084
- const parsed = descriptor.schema.safeParse(value);
43085
- if (!parsed.success)
43086
- return { ok: false, reason: "invalid_value" };
43087
- return { ok: true, descriptor };
43088
- }
43089
- /**
43090
- * The POSTURE GATE (a-AC-2). Resolve a class's descriptor for a READ that intends to
43091
- * RETURN the value to a surface (the `getSetting` path). REJECTS a class whose posture
43092
- * is `internal-only` with `not_readable` — so a `secret` can NEVER be read back through
43093
- * the daemon-readable accessor. An unknown class is `unknown_class`. This is the single
43094
- * point where the secret-vs-setting security boundary is enforced, as data.
43095
- */
43096
- assertReadable(klass) {
43097
- const descriptor = this.table.get(klass);
43098
- if (descriptor === void 0)
43099
- return { ok: false, reason: "unknown_class" };
43100
- if (descriptor.posture !== "daemon-readable")
43101
- return { ok: false, reason: "not_readable" };
43102
- return { ok: true, descriptor };
43103
- }
43104
- /** Resolve a descriptor with no value/posture check (internal callers that already gate). */
43105
- descriptorOf(klass) {
43106
- return this.table.get(klass);
43107
- }
43108
- };
43109
- function createVaultRegistry(extra = []) {
43110
- return new VaultRegistry([SECRET_DESCRIPTOR, SETTING_DESCRIPTOR, ...extra]);
43111
- }
43112
-
43113
- // dist/src/daemon/runtime/vault/api.js
43114
- var SETTINGS_GROUP = "/api/settings";
43115
- var KNOWN_SETTING_KEYS = ["activeProvider", "activeModel", "pollinating.enabled", "recallMode"];
43116
- var RECALL_MODES = ["keyword", "semantic", "hybrid"];
43117
- function isValidRecallMode(value) {
43118
- return RECALL_MODES.includes(value);
43119
- }
43120
- var DASHBOARD_PREF_PREFIX = "dashboard.";
43121
- function isKnownSettingKey(key) {
43122
- if (KNOWN_SETTING_KEYS.includes(key))
43123
- return true;
43124
- return key.startsWith(DASHBOARD_PREF_PREFIX) && key.length > DASHBOARD_PREF_PREFIX.length;
43125
- }
43126
- function mountSettingsGroup(group, deps) {
43127
- const scope = deps.scope ?? headerScopeResolver2;
43128
- const store = deps.store;
43129
- group.get("/", async (c) => {
43130
- const sc = scope.resolve(c);
43131
- if (sc === null)
43132
- return badTenancy2(c);
43133
- const keys = store.listSettingKeys(sc);
43134
- const settings = {};
43135
- for (const key of keys) {
43136
- const res = await store.getSetting(key, sc);
43137
- if (res.ok)
43138
- settings[key] = res.value;
43139
- }
43140
- return c.json({ settings, catalog: catalogView() });
43141
- });
43142
- group.get("/:key", async (c) => {
43143
- const sc = scope.resolve(c);
43144
- if (sc === null)
43145
- return badTenancy2(c);
43146
- const key = c.req.param("key");
43147
- if (!isKnownSettingKey(key)) {
43148
- return c.json({ error: "not_found", reason: "no such setting" }, 404);
43149
- }
43150
- const res = await store.getSetting(key, sc);
43151
- if (!res.ok) {
43152
- if (res.reason === "not_found")
43153
- return c.json({ error: "not_found", reason: "no such setting" }, 404);
43154
- if (res.reason === "not_readable")
43155
- return c.json({ error: "not_found", reason: "no such setting" }, 404);
43156
- return c.json({ error: "read_failed", reason: "could not read the setting" }, 502);
43157
- }
43158
- return c.json({ key, value: res.value });
43159
- });
43160
- group.post("/:key", async (c) => {
43161
- const sc = scope.resolve(c);
43162
- if (sc === null)
43163
- return badTenancy2(c);
43164
- const key = c.req.param("key");
43165
- if (!isKnownSettingKey(key)) {
43166
- return c.json({ error: "bad_request", reason: "unknown setting key" }, 400);
43167
- }
43168
- const value = await readSettingValue(c);
43169
- if (value === null) {
43170
- return c.json({ error: "bad_request", reason: "request body must carry a scalar value" }, 400);
43171
- }
43172
- const semanticError = await validateSettingSemantics(store, sc, key, value);
43173
- if (semanticError !== null) {
43174
- return c.json({ error: "bad_request", reason: semanticError }, 400);
43175
- }
43176
- const res = await store.setSetting(key, value, sc);
43177
- if (!res.ok) {
43178
- if (res.reason === "invalid_value") {
43179
- return c.json({ error: "bad_request", reason: "invalid setting value" }, 400);
43180
- }
43181
- if (res.reason === "not_readable" || res.reason === "unknown_class") {
43182
- return c.json({ error: "bad_request", reason: "setting class is not writable" }, 400);
43183
- }
43184
- return c.json({ error: "store_failed", reason: "could not store the setting" }, 502);
43185
- }
43186
- return c.json({ ok: true, key, value }, 201);
43187
- });
43188
- }
43189
- function mountSettingsApi(daemon, deps) {
43190
- const group = daemon.group(SETTINGS_GROUP);
43191
- if (group === void 0)
43192
- return;
43193
- mountSettingsGroup(group, deps);
43194
- }
43195
- function badTenancy2(c) {
43196
- return c.json({ error: "bad_request", reason: "x-honeycomb-org header is required" }, 400);
43197
- }
43198
- async function readSettingValue(c) {
43199
- const contentType = c.req.header("content-type") ?? "";
43200
- if (contentType.includes("application/json")) {
43201
- try {
43202
- const body = await c.req.json();
43203
- if (typeof body === "object" && body !== null) {
43204
- const v = body.value;
43205
- const parsed = SettingValueSchema.safeParse(v);
43206
- return parsed.success ? parsed.data : null;
43207
- }
43208
- return null;
43209
- } catch {
43210
- return null;
43211
- }
43212
- }
43213
- const text = await c.req.text();
43214
- return text.length > 0 ? text : null;
43215
- }
43216
- async function validateSettingSemantics(store, scope, key, value) {
43217
- if (key === "activeProvider") {
43218
- if (providerEntry(String(value)) === void 0)
43219
- return "unknown provider";
43220
- return null;
43221
- }
43222
- if (key === "activeModel") {
43223
- const provRes = await store.getSetting("activeProvider", scope);
43224
- const provider = provRes.ok ? String(provRes.value) : "";
43225
- if (provider.length === 0)
43226
- return "set activeProvider before activeModel";
43227
- if (!isValidProviderModel(provider, String(value)))
43228
- return "model not in provider catalog";
43229
- return null;
43230
- }
43231
- if (key === "recallMode") {
43232
- if (!isValidRecallMode(String(value)))
43233
- return "recallMode must be keyword, semantic, or hybrid";
43234
- return null;
43235
- }
43236
- return null;
43237
- }
43238
-
43239
43723
  // dist/src/daemon/runtime/memories/calibration-store.js
43240
43724
  function coldStart(bins) {
43241
43725
  return {
@@ -44273,7 +44757,13 @@ function mountMemoriesApi(daemon, options) {
44273
44757
  // PRD-058a: the per-request recency override (per-class half-lives + activation exponent).
44274
44758
  ...recency !== void 0 ? { recency } : {},
44275
44759
  // PRD-058b: the κ gate's conflict-suppression seam (drops the κ = ρ open-conflict loser).
44276
- ...options.conflictSuppression !== void 0 ? { conflictSuppression: options.conflictSuppression } : {}
44760
+ ...options.conflictSuppression !== void 0 ? { conflictSuppression: options.conflictSuppression } : {},
44761
+ // PRD-063c: the operator-selected reranker config + the Cohere-via-Portkey seam. The
44762
+ // `cohere` strategy activates ONLY when BOTH are present (the strategy is `cohere` AND the
44763
+ // gateway-on seam is wired); otherwise the engine keeps the RRF order / runs the local
44764
+ // cosine path — byte-identical to today (c-AC-4).
44765
+ ...options.reranker !== void 0 ? { reranker: options.reranker } : {},
44766
+ ...options.cohereRerank !== void 0 ? { cohereRerank: options.cohereRerank } : {}
44277
44767
  });
44278
44768
  logDegradedRecall(options.logger, result);
44279
44769
  logProjectScopeDegraded(options.logger, project);
@@ -45741,7 +46231,7 @@ var DISCOVERY_POLLS = 20;
45741
46231
  var DISCOVERY_POLL_DELAY_MS = 400;
45742
46232
  var DISCOVERY_STABLE_BREAK = 4;
45743
46233
  function sleep(ms) {
45744
- return new Promise((resolve6) => setTimeout(resolve6, ms));
46234
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
45745
46235
  }
45746
46236
  function nowIso7() {
45747
46237
  return (/* @__PURE__ */ new Date()).toISOString();
@@ -46979,7 +47469,7 @@ function guardedLookup(allowLoopback) {
46979
47469
  }
46980
47470
  function requestOnce(url2, timeoutMs, maxBytes, allowLoopback) {
46981
47471
  const requestFn = url2.protocol === "https:" ? httpsRequest : httpRequest;
46982
- return new Promise((resolve6, reject) => {
47472
+ return new Promise((resolve7, reject) => {
46983
47473
  const req = requestFn(url2, {
46984
47474
  method: "GET",
46985
47475
  headers: { "user-agent": USER_AGENT, accept: "*/*" },
@@ -47006,7 +47496,7 @@ function requestOnce(url2, timeoutMs, maxBytes, allowLoopback) {
47006
47496
  if (aborted2)
47007
47497
  return;
47008
47498
  const location = res.headers.location;
47009
- resolve6({
47499
+ resolve7({
47010
47500
  status: res.statusCode ?? 0,
47011
47501
  location: typeof location === "string" ? location : void 0,
47012
47502
  contentType: typeof res.headers["content-type"] === "string" ? res.headers["content-type"] : "",
@@ -48180,7 +48670,7 @@ function buildSourcesApiDeps(options) {
48180
48670
  // dist/src/daemon/runtime/secrets/store.js
48181
48671
  import { execFileSync as execFileSync6 } from "node:child_process";
48182
48672
  import { randomBytes as randomBytes5 } from "node:crypto";
48183
- import { appendFileSync, existsSync as existsSync18, mkdirSync as mkdirSync16, readdirSync as readdirSync4, readFileSync as readFileSync18, rmSync as rmSync7, statSync as statSync3, writeFileSync as writeFileSync13 } from "node:fs";
48673
+ import { appendFileSync, existsSync as existsSync18, mkdirSync as mkdirSync16, readdirSync as readdirSync4, readFileSync as readFileSync19, rmSync as rmSync8, statSync as statSync3, writeFileSync as writeFileSync13 } from "node:fs";
48184
48674
  import { homedir as homedir21 } from "node:os";
48185
48675
  import { join as join27 } from "node:path";
48186
48676
 
@@ -48917,7 +49407,7 @@ function readOsMachineId() {
48917
49407
  if (process.platform === "linux") {
48918
49408
  for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
48919
49409
  if (existsSync18(p)) {
48920
- const id = readFileSync18(p, "utf8").trim();
49410
+ const id = readFileSync19(p, "utf8").trim();
48921
49411
  if (id.length > 0)
48922
49412
  return id;
48923
49413
  }
@@ -48952,7 +49442,7 @@ function readOrCreateFallbackKey(homeDir) {
48952
49442
  const dir = join27(homeDir, MACHINE_KEY_DIR_NAME);
48953
49443
  const file2 = machineKeyFilePath(homeDir);
48954
49444
  if (existsSync18(file2)) {
48955
- const hex4 = readFileSync18(file2, "utf8").trim();
49445
+ const hex4 = readFileSync19(file2, "utf8").trim();
48956
49446
  if (hex4.length > 0)
48957
49447
  return hex4;
48958
49448
  }
@@ -49052,7 +49542,7 @@ var SecretsStore = class {
49052
49542
  return { ok: false, reason: "not_found" };
49053
49543
  }
49054
49544
  try {
49055
- rmSync7(file2);
49545
+ rmSync8(file2);
49056
49546
  this.audit("deleted", scope, "ok", safe);
49057
49547
  return { ok: true };
49058
49548
  } catch {
@@ -49083,7 +49573,7 @@ var SecretsStore = class {
49083
49573
  }
49084
49574
  let record2;
49085
49575
  try {
49086
- const parsed = JSON.parse(readFileSync18(file2, "utf8"));
49576
+ const parsed = JSON.parse(readFileSync19(file2, "utf8"));
49087
49577
  if (!isSecretRecord(parsed)) {
49088
49578
  this.audit("resolved_for_exec", scope, "error", safe);
49089
49579
  return { ok: false, reason: "io_error" };
@@ -49173,7 +49663,7 @@ function stripRefWrapper(ref) {
49173
49663
  }
49174
49664
 
49175
49665
  // dist/src/daemon/runtime/vault/store.js
49176
- import { appendFileSync as appendFileSync2, existsSync as existsSync19, mkdirSync as mkdirSync17, readdirSync as readdirSync5, readFileSync as readFileSync19, rmSync as rmSync8, writeFileSync as writeFileSync14 } from "node:fs";
49666
+ import { appendFileSync as appendFileSync2, existsSync as existsSync19, mkdirSync as mkdirSync17, readdirSync as readdirSync5, readFileSync as readFileSync20, rmSync as rmSync9, writeFileSync as writeFileSync14 } from "node:fs";
49177
49667
  import { join as join28 } from "node:path";
49178
49668
  var VAULT_DIR_NAME = ".vault";
49179
49669
  var VAULT_AUDIT_FILE_NAME = "vault-audit.ndjson";
@@ -49347,7 +49837,7 @@ var VaultStore = class {
49347
49837
  return { ok: false, reason: "not_found" };
49348
49838
  }
49349
49839
  try {
49350
- rmSync8(file2);
49840
+ rmSync9(file2);
49351
49841
  this.audit(safeClass, "deleted", scope, "ok", safe);
49352
49842
  return { ok: true };
49353
49843
  } catch {
@@ -49375,7 +49865,7 @@ var VaultStore = class {
49375
49865
  }
49376
49866
  let record2;
49377
49867
  try {
49378
- const parsed = JSON.parse(readFileSync19(file2, "utf8"));
49868
+ const parsed = JSON.parse(readFileSync20(file2, "utf8"));
49379
49869
  if (!isSecretRecord(parsed)) {
49380
49870
  this.audit(klass, op, scope, "error", safe);
49381
49871
  return { ok: false, reason: "io_error" };
@@ -50286,94 +50776,7 @@ var noopUsageSink = {
50286
50776
  record() {
50287
50777
  }
50288
50778
  };
50289
- var AnthropicContentBlockSchema = external_exports.object({
50290
- type: external_exports.string(),
50291
- text: external_exports.string().optional()
50292
- });
50293
- var AnthropicUsageSchema = external_exports.object({
50294
- input_tokens: external_exports.number().int().nonnegative().catch(0).default(0),
50295
- output_tokens: external_exports.number().int().nonnegative().catch(0).default(0),
50296
- cache_read_input_tokens: external_exports.number().int().nonnegative().catch(0).default(0),
50297
- cache_creation_input_tokens: external_exports.number().int().nonnegative().catch(0).default(0)
50298
- });
50299
- var ZERO_USAGE = {
50300
- input_tokens: 0,
50301
- output_tokens: 0,
50302
- cache_read_input_tokens: 0,
50303
- cache_creation_input_tokens: 0
50304
- };
50305
- var AnthropicMessagesResponseSchema = external_exports.object({
50306
- content: external_exports.array(AnthropicContentBlockSchema).default([]),
50307
- // Finding (usage-failsoft): `.default(ZERO_USAGE)` only covers `usage === undefined`. A response with
50308
- // `usage: null` or a malformed `usage` object would FAIL the object parse and -- because this field is
50309
- // part of the whole-response schema -- bubble up to a 502 that DROPS an otherwise-valid completion.
50310
- // `.catch(ZERO_USAGE)` makes ANY invalid value (null, a string, a malformed object) fall back to
50311
- // zero-usage so a valid completion is NEVER dropped over its (side-channel) usage block.
50312
- usage: AnthropicUsageSchema.default(ZERO_USAGE).catch(ZERO_USAGE)
50313
- });
50314
- function toAnthropicBody(call, defaultMaxTokens) {
50315
- const systemParts = [];
50316
- const messages = [];
50317
- for (const m of call.request.messages) {
50318
- if (m.role === "system") {
50319
- systemParts.push(m.content);
50320
- continue;
50321
- }
50322
- const role = m.role === "assistant" ? "assistant" : "user";
50323
- messages.push({ role, content: m.content });
50324
- }
50325
- const maxTokens = call.request.maxTokens ?? defaultMaxTokens;
50326
- return {
50327
- model: call.target.model,
50328
- max_tokens: maxTokens,
50329
- ...systemParts.length > 0 ? { system: systemParts.join("\n\n") } : {},
50330
- messages
50331
- };
50332
- }
50333
- function joinContentText(content) {
50334
- return content.filter((b) => b.type === "text" && typeof b.text === "string").map((b) => b.text).join("");
50335
- }
50336
- function createAnthropicTransport(deps = {}) {
50337
- const doFetch = deps.fetch ?? globalThis.fetch;
50338
- const url2 = deps.baseUrl ?? ANTHROPIC_MESSAGES_URL;
50339
- const defaultMaxTokens = deps.defaultMaxTokens ?? DEFAULT_MAX_TOKENS;
50340
- const usageSink = deps.usageSink ?? noopUsageSink;
50341
- async function post(call) {
50342
- const body = toAnthropicBody(call, defaultMaxTokens);
50343
- let res;
50344
- try {
50345
- res = await doFetch(url2, {
50346
- method: "POST",
50347
- headers: {
50348
- "x-api-key": call.apiKey,
50349
- "anthropic-version": ANTHROPIC_VERSION,
50350
- "content-type": "application/json"
50351
- },
50352
- body: JSON.stringify(body)
50353
- });
50354
- } catch (err) {
50355
- const detail = err instanceof Error ? err.name : "network error";
50356
- throw new ProviderError(503, `anthropic transport: request failed (${detail})`);
50357
- }
50358
- if (!res.ok) {
50359
- throw new ProviderError(res.status, `anthropic transport: provider returned status ${res.status}`);
50360
- }
50361
- const raw2 = await res.text().then((t) => safeJson2(t));
50362
- const parsed = AnthropicMessagesResponseSchema.safeParse(raw2);
50363
- if (!parsed.success) {
50364
- throw new ProviderError(502, "anthropic transport: malformed provider response");
50365
- }
50366
- const u = parsed.data.usage;
50367
- const usage = {
50368
- model: call.target.model,
50369
- workload: call.request.workload,
50370
- inputTokens: u.input_tokens,
50371
- outputTokens: u.output_tokens,
50372
- cacheReadInputTokens: u.cache_read_input_tokens,
50373
- cacheCreationInputTokens: u.cache_creation_input_tokens
50374
- };
50375
- return { output: joinContentText(parsed.data.content), usage };
50376
- }
50779
+ function usageReportingTransport(post, usageSink) {
50377
50780
  function reportUsage(usage) {
50378
50781
  try {
50379
50782
  usageSink.record(usage);
@@ -50396,15 +50799,209 @@ function createAnthropicTransport(deps = {}) {
50396
50799
  }
50397
50800
  };
50398
50801
  }
50399
- function safeJson2(text) {
50802
+ function safeJsonParse(text) {
50400
50803
  try {
50401
50804
  return JSON.parse(text);
50402
50805
  } catch {
50403
50806
  return void 0;
50404
50807
  }
50405
50808
  }
50809
+ var AnthropicContentBlockSchema = external_exports.object({
50810
+ type: external_exports.string(),
50811
+ text: external_exports.string().optional()
50812
+ });
50813
+ var AnthropicUsageSchema = external_exports.object({
50814
+ input_tokens: external_exports.number().int().nonnegative().catch(0).default(0),
50815
+ output_tokens: external_exports.number().int().nonnegative().catch(0).default(0),
50816
+ cache_read_input_tokens: external_exports.number().int().nonnegative().catch(0).default(0),
50817
+ cache_creation_input_tokens: external_exports.number().int().nonnegative().catch(0).default(0)
50818
+ });
50819
+ var ZERO_USAGE = {
50820
+ input_tokens: 0,
50821
+ output_tokens: 0,
50822
+ cache_read_input_tokens: 0,
50823
+ cache_creation_input_tokens: 0
50824
+ };
50825
+ var AnthropicMessagesResponseSchema = external_exports.object({
50826
+ content: external_exports.array(AnthropicContentBlockSchema).default([]),
50827
+ // Finding (usage-failsoft): `.default(ZERO_USAGE)` only covers `usage === undefined`. A response with
50828
+ // `usage: null` or a malformed `usage` object would FAIL the object parse and -- because this field is
50829
+ // part of the whole-response schema -- bubble up to a 502 that DROPS an otherwise-valid completion.
50830
+ // `.catch(ZERO_USAGE)` makes ANY invalid value (null, a string, a malformed object) fall back to
50831
+ // zero-usage so a valid completion is NEVER dropped over its (side-channel) usage block.
50832
+ usage: AnthropicUsageSchema.default(ZERO_USAGE).catch(ZERO_USAGE)
50833
+ });
50834
+ function toAnthropicBody(call, defaultMaxTokens) {
50835
+ const systemParts = [];
50836
+ const messages = [];
50837
+ for (const m of call.request.messages) {
50838
+ if (m.role === "system") {
50839
+ systemParts.push(m.content);
50840
+ continue;
50841
+ }
50842
+ const role = m.role === "assistant" ? "assistant" : "user";
50843
+ messages.push({ role, content: m.content });
50844
+ }
50845
+ const maxTokens = call.request.maxTokens ?? defaultMaxTokens;
50846
+ return {
50847
+ model: call.target.model,
50848
+ max_tokens: maxTokens,
50849
+ ...systemParts.length > 0 ? { system: systemParts.join("\n\n") } : {},
50850
+ messages
50851
+ };
50852
+ }
50853
+ function joinContentText(content) {
50854
+ return content.filter((b) => b.type === "text" && typeof b.text === "string").map((b) => b.text).join("");
50855
+ }
50856
+ function createAnthropicTransport(deps = {}) {
50857
+ const doFetch = deps.fetch ?? globalThis.fetch;
50858
+ const url2 = deps.baseUrl ?? ANTHROPIC_MESSAGES_URL;
50859
+ const defaultMaxTokens = deps.defaultMaxTokens ?? DEFAULT_MAX_TOKENS;
50860
+ const usageSink = deps.usageSink ?? noopUsageSink;
50861
+ async function post(call) {
50862
+ const body = toAnthropicBody(call, defaultMaxTokens);
50863
+ let res;
50864
+ try {
50865
+ res = await doFetch(url2, {
50866
+ method: "POST",
50867
+ headers: {
50868
+ "x-api-key": call.apiKey,
50869
+ "anthropic-version": ANTHROPIC_VERSION,
50870
+ "content-type": "application/json"
50871
+ },
50872
+ body: JSON.stringify(body)
50873
+ });
50874
+ } catch (err) {
50875
+ const detail = err instanceof Error ? err.name : "network error";
50876
+ throw new ProviderError(503, `anthropic transport: request failed (${detail})`);
50877
+ }
50878
+ if (!res.ok) {
50879
+ throw new ProviderError(res.status, `anthropic transport: provider returned status ${res.status}`);
50880
+ }
50881
+ const raw2 = await res.text().then((t) => safeJsonParse(t));
50882
+ const parsed = AnthropicMessagesResponseSchema.safeParse(raw2);
50883
+ if (!parsed.success) {
50884
+ throw new ProviderError(502, "anthropic transport: malformed provider response");
50885
+ }
50886
+ const u = parsed.data.usage;
50887
+ const usage = {
50888
+ model: call.target.model,
50889
+ workload: call.request.workload,
50890
+ inputTokens: u.input_tokens,
50891
+ outputTokens: u.output_tokens,
50892
+ cacheReadInputTokens: u.cache_read_input_tokens,
50893
+ cacheCreationInputTokens: u.cache_creation_input_tokens
50894
+ };
50895
+ return { output: joinContentText(parsed.data.content), usage };
50896
+ }
50897
+ return usageReportingTransport(post, usageSink);
50898
+ }
50899
+
50900
+ // dist/src/daemon/runtime/inference/transport-portkey.js
50901
+ var PORTKEY_BASE_URL = "https://api.portkey.ai/v1";
50902
+ var PORTKEY_CHAT_COMPLETIONS_URL = `${PORTKEY_BASE_URL}/chat/completions`;
50903
+ var PORTKEY_RERANK_URL = `${PORTKEY_BASE_URL}/rerank`;
50904
+ var PORTKEY_API_KEY_HEADER = "x-portkey-api-key";
50905
+ var PORTKEY_CONFIG_HEADER = "x-portkey-config";
50906
+ function buildPortkeyHeaders(apiKey, configId) {
50907
+ return {
50908
+ [PORTKEY_API_KEY_HEADER]: apiKey,
50909
+ [PORTKEY_CONFIG_HEADER]: configId,
50910
+ "content-type": "application/json"
50911
+ };
50912
+ }
50913
+ var PORTKEY_DEFAULT_MAX_TOKENS = 4096;
50914
+ var PortkeyChoiceSchema = external_exports.object({
50915
+ message: external_exports.object({ content: external_exports.string().nullable().optional() }).optional()
50916
+ });
50917
+ var PortkeyUsageSchema = external_exports.object({
50918
+ prompt_tokens: external_exports.number().int().nonnegative().catch(0).default(0),
50919
+ completion_tokens: external_exports.number().int().nonnegative().catch(0).default(0),
50920
+ prompt_tokens_details: external_exports.object({ cached_tokens: external_exports.number().int().nonnegative().catch(0).default(0) }).partial().optional()
50921
+ });
50922
+ var ZERO_PORTKEY_USAGE = { prompt_tokens: 0, completion_tokens: 0 };
50923
+ var PortkeyChatResponseSchema = external_exports.object({
50924
+ choices: external_exports.array(PortkeyChoiceSchema).default([]),
50925
+ // As with the Anthropic transport's usage block: `.catch()` so ANY invalid `usage` value
50926
+ // (null, a string, a malformed object) falls back to zero-usage and a VALID completion is
50927
+ // never dropped over its (side-channel) usage block.
50928
+ usage: PortkeyUsageSchema.default(ZERO_PORTKEY_USAGE).catch(ZERO_PORTKEY_USAGE)
50929
+ });
50930
+ function toPortkeyBody(call, defaultMaxTokens) {
50931
+ return {
50932
+ model: call.target.model,
50933
+ max_tokens: call.request.maxTokens ?? defaultMaxTokens,
50934
+ messages: call.request.messages.map((m) => ({ role: m.role, content: m.content }))
50935
+ };
50936
+ }
50937
+ function joinChoiceText(choices) {
50938
+ return choices.map((c) => c.message?.content).filter((t) => typeof t === "string").join("");
50939
+ }
50940
+ function createPortkeyTransport(deps) {
50941
+ const doFetch = deps.fetch ?? globalThis.fetch;
50942
+ const url2 = deps.baseUrl ?? PORTKEY_CHAT_COMPLETIONS_URL;
50943
+ const defaultMaxTokens = deps.defaultMaxTokens ?? PORTKEY_DEFAULT_MAX_TOKENS;
50944
+ const usageSink = deps.usageSink ?? noopUsageSink;
50945
+ const configId = deps.config;
50946
+ const onTransportError = deps.onTransportError;
50947
+ function reportTransportError(statusCode) {
50948
+ if (onTransportError === void 0)
50949
+ return;
50950
+ try {
50951
+ onTransportError(statusCode);
50952
+ } catch {
50953
+ }
50954
+ }
50955
+ async function post(call) {
50956
+ const body = toPortkeyBody(call, defaultMaxTokens);
50957
+ let res;
50958
+ try {
50959
+ res = await doFetch(url2, {
50960
+ method: "POST",
50961
+ headers: buildPortkeyHeaders(call.apiKey, configId),
50962
+ body: JSON.stringify(body)
50963
+ });
50964
+ } catch (err) {
50965
+ reportTransportError(503);
50966
+ const detail = err instanceof Error ? err.name : "network error";
50967
+ throw new ProviderError(503, `portkey transport: request failed (${detail})`);
50968
+ }
50969
+ if (!res.ok) {
50970
+ reportTransportError(res.status);
50971
+ throw new ProviderError(res.status, `portkey transport: gateway returned status ${res.status}`);
50972
+ }
50973
+ const raw2 = await res.text().then((t) => safeJsonParse(t));
50974
+ const parsed = PortkeyChatResponseSchema.safeParse(raw2);
50975
+ if (!parsed.success) {
50976
+ throw new ProviderError(502, "portkey transport: malformed gateway response");
50977
+ }
50978
+ const u = parsed.data.usage;
50979
+ const usage = {
50980
+ model: call.target.model,
50981
+ workload: call.request.workload,
50982
+ inputTokens: u.prompt_tokens,
50983
+ outputTokens: u.completion_tokens,
50984
+ cacheReadInputTokens: u.prompt_tokens_details?.cached_tokens ?? 0,
50985
+ // Portkey's OpenAI-shaped usage has no cache-WRITE field; surface 0 (never fabricate).
50986
+ cacheCreationInputTokens: 0
50987
+ };
50988
+ return { output: joinChoiceText(parsed.data.choices), usage };
50989
+ }
50990
+ return usageReportingTransport(post, usageSink);
50991
+ }
50406
50992
 
50407
50993
  // dist/src/daemon/runtime/inference/model-client-factory.js
50994
+ var PORTKEY_API_KEY_REF = "${PORTKEY_API_KEY}";
50995
+ var PORTKEY_API_KEY_NAME = "PORTKEY_API_KEY";
50996
+ var PORTKEY_ACCOUNT_ID = "portkey-gateway";
50997
+ var PORTKEY_TARGET_ID = "portkey-target";
50998
+ var PORTKEY_POLICY_ID = "portkey-default";
50999
+ var PortkeyUnconfiguredError = class extends Error {
51000
+ constructor() {
51001
+ super("portkey: enabled but PORTKEY_API_KEY is not set (fail-closed; set the key or disable portkey.enabled)");
51002
+ this.name = "PortkeyUnconfiguredError";
51003
+ }
51004
+ };
50408
51005
  async function resolveConfig3(source) {
50409
51006
  if (typeof source === "string") {
50410
51007
  return loadInferenceConfigFromYaml(source);
@@ -50422,7 +51019,7 @@ function applyProviderModelOverride(config2, override) {
50422
51019
  workloads: config2.workloads
50423
51020
  };
50424
51021
  }
50425
- async function buildInferenceModelClient(deps) {
51022
+ async function buildProviderPathClient(deps) {
50426
51023
  let config2;
50427
51024
  try {
50428
51025
  config2 = await resolveConfig3(deps.config);
@@ -50443,6 +51040,161 @@ async function buildInferenceModelClient(deps) {
50443
51040
  });
50444
51041
  return new RouterModelClient(router);
50445
51042
  }
51043
+ async function buildInferenceModelClient(deps) {
51044
+ const { client } = await buildInferenceModelClientWithStatus(deps);
51045
+ return client;
51046
+ }
51047
+ async function buildInferenceModelClientWithStatus(deps) {
51048
+ const portkey = deps.portkey;
51049
+ if (portkey === void 0 || !portkey.enabled) {
51050
+ return { client: await buildProviderPathClient(deps), portkeyStatus: "off" };
51051
+ }
51052
+ try {
51053
+ const client = await resolvePortkeyClient(deps, portkey);
51054
+ return { client, portkeyStatus: "ok" };
51055
+ } catch (err) {
51056
+ if (err instanceof PortkeyUnconfiguredError) {
51057
+ return { client: noopModelClient, portkeyStatus: "unconfigured" };
51058
+ }
51059
+ return { client: noopModelClient, portkeyStatus: "unconfigured" };
51060
+ }
51061
+ }
51062
+ async function resolvePortkeyClient(deps, portkey) {
51063
+ const names = deps.secretsStore.listSecretNames(deps.scope);
51064
+ if (!names.includes(PORTKEY_API_KEY_NAME)) {
51065
+ throw new PortkeyUnconfiguredError();
51066
+ }
51067
+ const secrets = createSecretResolver(deps.secretsStore, deps.scope);
51068
+ const transport = createPortkeyTransport({
51069
+ config: portkey.config,
51070
+ ...deps.usageSink !== void 0 ? { usageSink: deps.usageSink } : {},
51071
+ ...deps.onPortkeyUnreachable !== void 0 ? { onTransportError: deps.onPortkeyUnreachable } : {}
51072
+ });
51073
+ const router = createInferenceRouter({
51074
+ config: buildPortkeyConfig(portkey.model),
51075
+ transport,
51076
+ secrets,
51077
+ history: deps.history ?? noopRoutingHistoryStore
51078
+ });
51079
+ const portkeyClient = new RouterModelClient(router);
51080
+ if (!portkey.fallbackToProvider) {
51081
+ return portkeyClient;
51082
+ }
51083
+ const providerClient = await buildProviderPathClient(deps);
51084
+ return new PortkeyFallbackModelClient(portkeyClient, providerClient);
51085
+ }
51086
+ function buildPortkeyConfig(model) {
51087
+ return {
51088
+ accounts: [{ id: PORTKEY_ACCOUNT_ID, provider: "portkey", apiKeyRef: PORTKEY_API_KEY_REF }],
51089
+ targets: [
51090
+ {
51091
+ id: PORTKEY_TARGET_ID,
51092
+ accountRef: PORTKEY_ACCOUNT_ID,
51093
+ model,
51094
+ privacyTier: "public",
51095
+ capabilities: ["chat"],
51096
+ contextWindow: 1e6
51097
+ }
51098
+ ],
51099
+ policies: [{ id: PORTKEY_POLICY_ID, mode: "strict", chain: [PORTKEY_TARGET_ID] }],
51100
+ workloads: [
51101
+ { name: "memory_extraction", policyRef: PORTKEY_POLICY_ID, requiredCapabilities: ["chat"], minPrivacyTier: "public" },
51102
+ { name: "memory_decision", policyRef: PORTKEY_POLICY_ID, requiredCapabilities: ["chat"], minPrivacyTier: "public" },
51103
+ { name: "memory_pollinating", policyRef: PORTKEY_POLICY_ID, requiredCapabilities: ["chat"], minPrivacyTier: "public" }
51104
+ ]
51105
+ };
51106
+ }
51107
+ var PortkeyFallbackModelClient = class {
51108
+ portkey;
51109
+ provider;
51110
+ constructor(portkey, provider) {
51111
+ this.portkey = portkey;
51112
+ this.provider = provider;
51113
+ }
51114
+ async complete(a, b) {
51115
+ try {
51116
+ return typeof a === "string" ? await this.portkey.complete(a, b) : await this.portkey.complete(a);
51117
+ } catch (err) {
51118
+ void err;
51119
+ return typeof a === "string" ? this.provider.complete(a, b) : this.provider.complete(a);
51120
+ }
51121
+ }
51122
+ };
51123
+
51124
+ // dist/src/daemon/runtime/recall/rerank-portkey.js
51125
+ var RERANK_FAILED = Object.freeze({ ok: false });
51126
+ var RerankResultSchema = external_exports.object({
51127
+ index: external_exports.number().int().nonnegative(),
51128
+ relevance_score: external_exports.number()
51129
+ });
51130
+ var RerankResponseSchema = external_exports.object({
51131
+ results: external_exports.array(RerankResultSchema)
51132
+ });
51133
+ function createPortkeyRerankClient(deps) {
51134
+ const doFetch = deps.fetch ?? globalThis.fetch;
51135
+ const url2 = deps.baseUrl ?? PORTKEY_RERANK_URL;
51136
+ const configId = deps.config;
51137
+ const onTransportError = deps.onTransportError;
51138
+ function reportTransportError(statusCode) {
51139
+ if (onTransportError === void 0)
51140
+ return;
51141
+ try {
51142
+ onTransportError(statusCode);
51143
+ } catch {
51144
+ }
51145
+ }
51146
+ return {
51147
+ async rerank(apiKey, request) {
51148
+ const body = {
51149
+ model: request.model,
51150
+ query: request.query,
51151
+ documents: request.documents,
51152
+ top_n: request.topN
51153
+ };
51154
+ let res;
51155
+ try {
51156
+ res = await doFetch(url2, {
51157
+ method: "POST",
51158
+ // SAME auth pair as the chat transport (c-D-2); the key lives only in the header (c-AC-2).
51159
+ headers: buildPortkeyHeaders(apiKey, configId),
51160
+ body: JSON.stringify(body)
51161
+ });
51162
+ } catch {
51163
+ reportTransportError(503);
51164
+ return RERANK_FAILED;
51165
+ }
51166
+ if (!res.ok) {
51167
+ reportTransportError(res.status);
51168
+ return RERANK_FAILED;
51169
+ }
51170
+ const text = await res.text().catch(() => "");
51171
+ const parsed = RerankResponseSchema.safeParse(safeJsonParse(text));
51172
+ if (!parsed.success) {
51173
+ process.stderr.write("honeycomb: portkey rerank returned an unusable 2xx body; failing soft to RRF order\n");
51174
+ return RERANK_FAILED;
51175
+ }
51176
+ const results = parsed.data.results.filter((r) => r.index < request.documents.length).map((r) => ({ index: r.index, relevanceScore: r.relevance_score }));
51177
+ return { ok: true, results };
51178
+ }
51179
+ };
51180
+ }
51181
+ function buildCohereRerankSeam(deps) {
51182
+ return {
51183
+ async rerank(query, documents, topN) {
51184
+ let apiKey;
51185
+ try {
51186
+ apiKey = await deps.secrets.resolve(deps.apiKeyRef);
51187
+ } catch {
51188
+ return { ok: false };
51189
+ }
51190
+ try {
51191
+ return await deps.client.rerank(apiKey, { model: deps.model, query, documents, topN });
51192
+ } catch {
51193
+ return RERANK_FAILED;
51194
+ }
51195
+ }
51196
+ };
51197
+ }
50446
51198
 
50447
51199
  // dist/src/daemon/runtime/services/poll-backoff.js
50448
51200
  var DEFAULT_POLL_BACKOFF_FLOOR_MS = 1e3;
@@ -52360,7 +53112,7 @@ import { homedir as homedir24 } from "node:os";
52360
53112
  import { join as join31 } from "node:path";
52361
53113
 
52362
53114
  // dist/src/daemon/runtime/skillify/install-target.js
52363
- import { mkdirSync as mkdirSync18, readFileSync as readFileSync20, writeFileSync as writeFileSync15 } from "node:fs";
53115
+ import { mkdirSync as mkdirSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync15 } from "node:fs";
52364
53116
  import { homedir as homedir22 } from "node:os";
52365
53117
  import { join as join29 } from "node:path";
52366
53118
  var SKILLS_SUBDIR2 = join29(".claude", "skills");
@@ -52379,7 +53131,7 @@ function createFsInstallTarget(dirs = {}) {
52379
53131
  },
52380
53132
  async read(install, name) {
52381
53133
  try {
52382
- return readFileSync20(fileFor(install, name), "utf-8");
53134
+ return readFileSync21(fileFor(install, name), "utf-8");
52383
53135
  } catch {
52384
53136
  return null;
52385
53137
  }
@@ -52392,9 +53144,9 @@ function sanitizeSegment4(name) {
52392
53144
  }
52393
53145
 
52394
53146
  // dist/src/daemon/runtime/skillify/watermark.js
52395
- import { mkdirSync as mkdirSync19, readFileSync as readFileSync21, writeFileSync as writeFileSync16 } from "node:fs";
53147
+ import { mkdirSync as mkdirSync19, readFileSync as readFileSync22, writeFileSync as writeFileSync16 } from "node:fs";
52396
53148
  import { homedir as homedir23 } from "node:os";
52397
- import { dirname as dirname13, join as join30 } from "node:path";
53149
+ import { dirname as dirname14, join as join30 } from "node:path";
52398
53150
  function defaultWatermarkBaseDir() {
52399
53151
  return join30(homedir23(), ".honeycomb", "state", "skillify");
52400
53152
  }
@@ -52402,7 +53154,7 @@ function createWatermarkStore(baseDir = defaultWatermarkBaseDir()) {
52402
53154
  const fileFor = (projectKey) => join30(baseDir, sanitizeSegment5(projectKey), "watermark.json");
52403
53155
  const read = (projectKey) => {
52404
53156
  try {
52405
- const raw2 = readFileSync21(fileFor(projectKey), "utf-8");
53157
+ const raw2 = readFileSync22(fileFor(projectKey), "utf-8");
52406
53158
  const parsed = JSON.parse(raw2);
52407
53159
  return typeof parsed.watermark === "string" && parsed.watermark !== "" ? parsed.watermark : null;
52408
53160
  } catch {
@@ -52420,7 +53172,7 @@ function createWatermarkStore(baseDir = defaultWatermarkBaseDir()) {
52420
53172
  const next = current === null ? oldest : earlier(current, oldest);
52421
53173
  const file2 = { watermark: next, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
52422
53174
  const path4 = fileFor(projectKey);
52423
- mkdirSync19(dirname13(path4), { recursive: true });
53175
+ mkdirSync19(dirname14(path4), { recursive: true });
52424
53176
  writeFileSync16(path4, JSON.stringify(file2, null, 2), "utf-8");
52425
53177
  return next;
52426
53178
  }
@@ -52459,18 +53211,22 @@ function tokenCountOrNull2(value) {
52459
53211
  }
52460
53212
  function rowToCapturedTurn2(r) {
52461
53213
  const sourceTool = typeof r.source_tool === "string" ? r.source_tool : "";
53214
+ const model = typeof r.model === "string" ? r.model : "";
53215
+ const provider = sourceTool === "claude-code" || model.startsWith("claude-") ? "anthropic" : void 0;
52462
53216
  return {
52463
53217
  input_tokens: tokenCountOrNull2(r.input_tokens),
52464
53218
  output_tokens: tokenCountOrNull2(r.output_tokens),
52465
53219
  cache_read_input_tokens: tokenCountOrNull2(r.cache_read_input_tokens),
52466
53220
  cache_creation_input_tokens: tokenCountOrNull2(r.cache_creation_input_tokens),
52467
- ...sourceTool !== "" ? { sourceTool } : {}
53221
+ ...sourceTool !== "" ? { sourceTool } : {},
53222
+ ...model !== "" ? { model } : {},
53223
+ ...provider !== void 0 ? { provider } : {}
52468
53224
  };
52469
53225
  }
52470
53226
  async function readSessionTurns(storage, scope, path4) {
52471
53227
  const tbl = sqlIdent("sessions");
52472
53228
  const pathCol = sqlIdent("path");
52473
- const sql = `SELECT ${sqlIdent("input_tokens")}, ${sqlIdent("output_tokens")}, ${sqlIdent("cache_read_input_tokens")}, ${sqlIdent("cache_creation_input_tokens")}, ${sqlIdent("source_tool")} FROM "${tbl}" WHERE ${pathCol} = ${sLiteral(path4)} LIMIT ${SESSION_TURNS_LIMIT}`;
53229
+ const sql = `SELECT ${sqlIdent("input_tokens")}, ${sqlIdent("output_tokens")}, ${sqlIdent("cache_read_input_tokens")}, ${sqlIdent("cache_creation_input_tokens")}, ${sqlIdent("source_tool")}, ${sqlIdent("model")} FROM "${tbl}" WHERE ${pathCol} = ${sLiteral(path4)} LIMIT ${SESSION_TURNS_LIMIT}`;
52474
53230
  let result;
52475
53231
  try {
52476
53232
  result = await storage.query(sql, scope);
@@ -53181,6 +53937,7 @@ var AGENT_CONFIG_FILE_NAME = "agent.yaml";
53181
53937
  var LOCK_FILE_NAME = "daemon.lock";
53182
53938
  var PID_FILE_NAME = "daemon.pid";
53183
53939
  var DEFAULT_HEALTH_PROBE_INTERVAL_MS = 15e3;
53940
+ var DEFAULT_GRAPH_BUILD_INTERVAL_MS = 60 * 60 * 1e3;
53184
53941
  var defaultSeamFns = {
53185
53942
  attachHooks: attachHooksHandlers,
53186
53943
  mountDashboard: mountDashboardApi,
@@ -53246,7 +54003,7 @@ function acquireSingleInstanceLock(runtimeDir) {
53246
54003
  }
53247
54004
  function readPidFile(path4) {
53248
54005
  try {
53249
- const raw2 = readFileSync22(path4, "utf8").trim();
54006
+ const raw2 = readFileSync23(path4, "utf8").trim();
53250
54007
  if (raw2.length === 0)
53251
54008
  return null;
53252
54009
  const pid = Number.parseInt(raw2, 10);
@@ -53258,7 +54015,7 @@ function readPidFile(path4) {
53258
54015
  function releaseSingleInstanceLock(runtimeDir) {
53259
54016
  for (const name of [LOCK_FILE_NAME, PID_FILE_NAME]) {
53260
54017
  try {
53261
- rmSync9(join32(runtimeDir, name), { force: true });
54018
+ rmSync10(join32(runtimeDir, name), { force: true });
53262
54019
  } catch {
53263
54020
  }
53264
54021
  }
@@ -53281,7 +54038,7 @@ function authForMode(mode, storage, scope) {
53281
54038
  }
53282
54039
  return { authenticator: composeAuthenticator(storage, scope), policy: defaultDenyPolicy };
53283
54040
  }
53284
- function assembleSeams(daemon, storage, defaultScope, orgName, embed, healthDetail, workspaceDir, installedHarnesses, logStore, seams = defaultSeamFns, vault) {
54041
+ function assembleSeams(daemon, storage, defaultScope, orgName, embed, healthDetail, workspaceDir, installedHarnesses, logStore, seams = defaultSeamFns, vault, rerankerDeps) {
53285
54042
  const captureHandler = seams.attachHooks(daemon, {
53286
54043
  storage,
53287
54044
  queue: daemon.services.queue,
@@ -53326,7 +54083,12 @@ function assembleSeams(daemon, storage, defaultScope, orgName, embed, healthDeta
53326
54083
  embed: embed.client,
53327
54084
  logger: daemon.logger,
53328
54085
  conflictSuppression,
53329
- ...vault !== void 0 ? { vault } : {}
54086
+ ...vault !== void 0 ? { vault } : {},
54087
+ // PRD-063c: the operator-selected reranker config + the late-bound Cohere-via-Portkey seam.
54088
+ // The `cohere` strategy only does anything when BOTH the strategy is `cohere` (env) AND the
54089
+ // gateway is ON (the seam's inner transport is wired in `start()`); otherwise RRF / local
54090
+ // cosine, byte-identical to today (c-AC-4). Absent rerankerDeps (a unit mount) → engine default.
54091
+ ...rerankerDeps !== void 0 ? { reranker: rerankerDeps.reranker, cohereRerank: rerankerDeps.cohereRerank } : {}
53330
54092
  });
53331
54093
  if (seams.mountConflicts !== void 0) {
53332
54094
  seams.mountConflicts(daemon, { storage, defaultScope });
@@ -53410,7 +54172,7 @@ function assembleSeams(daemon, storage, defaultScope, orgName, embed, healthDeta
53410
54172
  return captureHandler;
53411
54173
  }
53412
54174
  function resolveProductDataDeps(storage, defaultScope, queue, embed, mode) {
53413
- const baseDir = process.env.HONEYCOMB_WORKSPACE ?? process.cwd();
54175
+ const baseDir = resolveWorkspaceBaseDir();
53414
54176
  const secrets = {
53415
54177
  store: new SecretsStore({ baseDir, machineKey: createMachineKeyProvider() }),
53416
54178
  // PRD-022 local-mode default: the dashboard's `GET /api/secrets` (names-only) carries no
@@ -53434,8 +54196,35 @@ function resolveProductDataDeps(storage, defaultScope, queue, embed, mode) {
53434
54196
  defaultScope
53435
54197
  };
53436
54198
  }
54199
+ var workspaceBaseDirMemo;
53437
54200
  function resolveWorkspaceBaseDir() {
53438
- return process.env.HONEYCOMB_WORKSPACE ?? process.cwd();
54201
+ if (workspaceBaseDirMemo !== void 0)
54202
+ return workspaceBaseDirMemo;
54203
+ const fromEnv = process.env.HONEYCOMB_WORKSPACE;
54204
+ const candidate = fromEnv !== void 0 && fromEnv.length > 0 ? fromEnv : process.cwd();
54205
+ if (isWritableDir(candidate)) {
54206
+ workspaceBaseDirMemo = candidate;
54207
+ return candidate;
54208
+ }
54209
+ const fallback = join32(homedir25(), ".honeycomb");
54210
+ process.stderr.write(`honeycomb: workspace "${candidate}" is not writable; using "${fallback}" for filesystem state (secrets, logs, agent.yaml)
54211
+ `);
54212
+ try {
54213
+ mkdirSync20(fallback, { recursive: true, mode: DIR_MODE });
54214
+ } catch {
54215
+ }
54216
+ workspaceBaseDirMemo = fallback;
54217
+ return fallback;
54218
+ }
54219
+ function isWritableDir(dir) {
54220
+ try {
54221
+ mkdirSync20(dir, { recursive: true });
54222
+ const probe = mkdtempSync(join32(dir, ".honeycomb-write-test-"));
54223
+ rmSync10(probe, { recursive: true, force: true });
54224
+ return true;
54225
+ } catch {
54226
+ return false;
54227
+ }
53439
54228
  }
53440
54229
  function resolveAgentConfigPath(options) {
53441
54230
  return options.agentConfigPath ?? join32(resolveWorkspaceBaseDir(), AGENT_CONFIG_FILE_NAME);
@@ -53446,6 +54235,9 @@ function secretScopeFromQueryScope(scope) {
53446
54235
  var VAULT_PROVIDER_KEY = "activeProvider";
53447
54236
  var VAULT_MODEL_KEY = "activeModel";
53448
54237
  var VAULT_POLLINATING_ENABLED_KEY = "pollinating.enabled";
54238
+ var VAULT_PORTKEY_ENABLED_KEY = "portkey.enabled";
54239
+ var VAULT_PORTKEY_CONFIG_KEY = "portkey.config";
54240
+ var VAULT_PORTKEY_FALLBACK_KEY = "portkey.fallbackToProvider";
53449
54241
  function catalogTrustedTableProbe() {
53450
54242
  const names = CATALOG.map((t) => t.name);
53451
54243
  return { tables: () => Promise.resolve(names) };
@@ -53476,6 +54268,41 @@ async function readProviderModelOverride(vault, scope) {
53476
54268
  return void 0;
53477
54269
  }
53478
54270
  }
54271
+ async function readPortkeySelection(vault, scope) {
54272
+ if (vault === void 0)
54273
+ return void 0;
54274
+ try {
54275
+ const enabledRes = await vault.getSetting(VAULT_PORTKEY_ENABLED_KEY, scope);
54276
+ const enabled = enabledRes.ok && coerceSettingBool(enabledRes.value);
54277
+ if (!enabled)
54278
+ return void 0;
54279
+ const configRes = await vault.getSetting(VAULT_PORTKEY_CONFIG_KEY, scope);
54280
+ const config2 = configRes.ok ? String(configRes.value) : "";
54281
+ if (config2.length === 0)
54282
+ return void 0;
54283
+ const modelRes = await vault.getSetting(VAULT_MODEL_KEY, scope);
54284
+ const model = modelRes.ok ? String(modelRes.value) : "";
54285
+ const fallbackRes = await vault.getSetting(VAULT_PORTKEY_FALLBACK_KEY, scope);
54286
+ const fallbackToProvider = fallbackRes.ok && coerceSettingBool(fallbackRes.value);
54287
+ return { enabled: true, config: config2, model, fallbackToProvider };
54288
+ } catch {
54289
+ return void 0;
54290
+ }
54291
+ }
54292
+ async function resolvePortkeyAssemblyStatus(selection, scope) {
54293
+ if (selection === void 0 || !selection.enabled)
54294
+ return "off";
54295
+ try {
54296
+ const secretsStore = new SecretsStore({
54297
+ baseDir: resolveWorkspaceBaseDir(),
54298
+ machineKey: createMachineKeyProvider()
54299
+ });
54300
+ const names = secretsStore.listSecretNames(secretScopeFromQueryScope(scope));
54301
+ return names.includes(PORTKEY_API_KEY_NAME) ? "ok" : "unconfigured";
54302
+ } catch {
54303
+ return "unconfigured";
54304
+ }
54305
+ }
53479
54306
  async function readVaultPollinatingEnabled(vault, scope) {
53480
54307
  if (vault === void 0)
53481
54308
  return { decidedByVault: false, enabled: false };
@@ -53489,6 +54316,17 @@ async function readVaultPollinatingEnabled(vault, scope) {
53489
54316
  return { decidedByVault: false, enabled: false };
53490
54317
  }
53491
54318
  }
54319
+ async function readBootEmbeddingsEnabled(vault, scope) {
54320
+ if (vault !== void 0) {
54321
+ try {
54322
+ const res = await vault.getSetting(EMBEDDINGS_ENABLED_KEY, scope);
54323
+ if (res.ok)
54324
+ return coerceSettingBool(res.value);
54325
+ } catch {
54326
+ }
54327
+ }
54328
+ return resolveEmbedClientOptions().enabled;
54329
+ }
53492
54330
  function coerceSettingBool(value) {
53493
54331
  if (typeof value === "boolean")
53494
54332
  return value;
@@ -53498,7 +54336,7 @@ function coerceSettingBool(value) {
53498
54336
  return value === "true" || value === "1";
53499
54337
  return false;
53500
54338
  }
53501
- async function buildGatedPollinatingWorker(options, storage, scope, queue, vault, backoff) {
54339
+ async function buildGatedPollinatingWorker(options, storage, scope, queue, vault, backoff, portkeyDeps) {
53502
54340
  let config2;
53503
54341
  try {
53504
54342
  config2 = resolvePollinatingConfig(options.pollinatingConfigProvider);
@@ -53522,7 +54360,9 @@ async function buildGatedPollinatingWorker(options, storage, scope, queue, vault
53522
54360
  scope: secretScopeFromQueryScope(scope),
53523
54361
  secretsStore,
53524
54362
  config: resolveAgentConfigPath(options),
53525
- ...providerModelOverride !== void 0 ? { providerModelOverride } : {}
54363
+ ...providerModelOverride !== void 0 ? { providerModelOverride } : {},
54364
+ ...portkeyDeps?.selection !== void 0 ? { portkey: portkeyDeps.selection } : {},
54365
+ ...portkeyDeps !== void 0 ? { onPortkeyUnreachable: portkeyDeps.onUnreachable } : {}
53526
54366
  });
53527
54367
  const trigger = createPollinatingTrigger({ storage, scope, config: config2, enqueuer: queue });
53528
54368
  return createPollinatingWorker({ queue, storage, scope, config: config2, model, trigger, backoff });
@@ -53546,7 +54386,7 @@ function makePipelineEntryEnqueuer(queue) {
53546
54386
  });
53547
54387
  };
53548
54388
  }
53549
- async function buildPipelineWorker(options, storage, scope, queue, embed, backoff) {
54389
+ async function buildPipelineWorker(options, storage, scope, queue, embed, backoff, portkeyDeps) {
53550
54390
  let config2;
53551
54391
  try {
53552
54392
  config2 = resolvePipelineConfig();
@@ -53562,7 +54402,9 @@ async function buildPipelineWorker(options, storage, scope, queue, embed, backof
53562
54402
  model = await buildInferenceModelClient({
53563
54403
  scope: secretScopeFromQueryScope(scope),
53564
54404
  secretsStore,
53565
- config: resolveAgentConfigPath(options)
54405
+ config: resolveAgentConfigPath(options),
54406
+ ...portkeyDeps?.selection !== void 0 ? { portkey: portkeyDeps.selection } : {},
54407
+ ...portkeyDeps !== void 0 ? { onPortkeyUnreachable: portkeyDeps.onUnreachable } : {}
53566
54408
  });
53567
54409
  } catch {
53568
54410
  model = noopModelClient;
@@ -53597,6 +54439,7 @@ function assembleDaemon(options = {}) {
53597
54439
  const tenancy = resolveDaemonTenancy(provider);
53598
54440
  const scope = tenancy.scope;
53599
54441
  const daemonOrgName = tenancy.orgName;
54442
+ const vault = options.vault ?? (options.storage === void 0 ? buildVaultStore() : void 0);
53600
54443
  const services = {
53601
54444
  queue: createJobQueueService({ storage, scope }),
53602
54445
  watcher: createFileWatcherService({
@@ -53612,10 +54455,34 @@ function assembleDaemon(options = {}) {
53612
54455
  // fake supervisor so the hermetic assembly never spawns a real process.
53613
54456
  embed: options.embedSupervisor ?? createEmbedSupervisor()
53614
54457
  };
54458
+ const embedSupervisor = services.embed;
54459
+ if (embedSupervisor !== void 0 && vault !== void 0) {
54460
+ void readBootEmbeddingsEnabled(vault, secretScopeFromQueryScope(scope)).then(async (enabled) => {
54461
+ if (enabled !== !embedSupervisor.disabled)
54462
+ await embedSupervisor.setEnabled(enabled);
54463
+ }).catch((err) => {
54464
+ const reason = err instanceof Error ? err.message : String(err);
54465
+ process.stderr.write(`honeycomb: embeddings boot reconciliation failed (non-fatal): ${reason}
54466
+ `);
54467
+ });
54468
+ }
53615
54469
  let healthBit = "ok";
53616
54470
  const pipelineProbe = () => healthBit;
53617
- const embeddingsEnabled = options.embeddingsEnabled ?? (options.embed !== void 0 ? false : resolveEmbedClientOptions().enabled);
53618
- const healthDetail = () => buildHealthDetail({ status: healthBit, embeddingsEnabled });
54471
+ const embeddingsReason = () => options.embeddingsEnabled ?? (options.embed !== void 0 ? false : embedSupervisor !== void 0 ? !embedSupervisor.disabled : resolveEmbedClientOptions().enabled);
54472
+ let portkeyHealth = "off";
54473
+ const recordPortkeyUnreachable = (_statusCode) => {
54474
+ portkeyHealth = "unreachable";
54475
+ };
54476
+ const healthDetail = () => buildHealthDetail({ status: healthBit, embeddingsEnabled: embeddingsReason(), portkey: portkeyHealth });
54477
+ let cohereRerankInner;
54478
+ const cohereRerankSeam = {
54479
+ rerank(query, documents, topN) {
54480
+ const inner = cohereRerankInner;
54481
+ if (inner === void 0)
54482
+ return Promise.resolve({ ok: false });
54483
+ return inner.rerank(query, documents, topN);
54484
+ }
54485
+ };
53619
54486
  const { authenticator, policy } = authForMode(config2.mode, storage, scope);
53620
54487
  const createOptions = {
53621
54488
  config: config2,
@@ -53630,8 +54497,16 @@ function assembleDaemon(options = {}) {
53630
54497
  const daemon = createDaemon(createOptions);
53631
54498
  const embed = options.embed ?? createEmbedAttachment({ storage });
53632
54499
  const installedHarnesses = options.installedHarnesses ?? (options.harnessTargets !== void 0 && options.harnessTargets.length > 0 ? new Set(options.harnessTargets.map((t) => t.name)) : options.storage === void 0 ? detectInstalledHarnesses() : /* @__PURE__ */ new Set());
53633
- const vault = options.vault ?? (options.storage === void 0 ? buildVaultStore() : void 0);
53634
- const captureHandler = assembleSeams(daemon, storage, scope, daemonOrgName, embed, healthDetail, options.workspaceDir ?? process.cwd(), installedHarnesses, logStore, options.seams ?? defaultSeamFns, vault);
54500
+ let rerankerMountDeps;
54501
+ try {
54502
+ rerankerMountDeps = { reranker: resolveRecallConfig().reranker, cohereRerank: cohereRerankSeam };
54503
+ } catch {
54504
+ rerankerMountDeps = {
54505
+ reranker: RecallConfigSchema.parse({}).reranker,
54506
+ cohereRerank: cohereRerankSeam
54507
+ };
54508
+ }
54509
+ const captureHandler = assembleSeams(daemon, storage, scope, daemonOrgName, embed, healthDetail, options.workspaceDir ?? process.cwd(), installedHarnesses, logStore, options.seams ?? defaultSeamFns, vault, rerankerMountDeps);
53635
54510
  if (vault !== void 0 && vault instanceof VaultStore) {
53636
54511
  try {
53637
54512
  mountSettingsApi(daemon, { store: vault, scope: localDefaultScopeResolver(daemon.config.mode, scope) });
@@ -53646,6 +54521,17 @@ function assembleDaemon(options = {}) {
53646
54521
  } catch (err) {
53647
54522
  const reason = err instanceof Error ? err.message : String(err);
53648
54523
  process.stderr.write(`honeycomb: auth status API mount failed (non-fatal): ${reason}
54524
+ `);
54525
+ }
54526
+ try {
54527
+ mountActionsApi(daemon, {
54528
+ embed: daemon.services.embed,
54529
+ defaultScope: scope,
54530
+ ...vault instanceof VaultStore ? { store: vault } : {}
54531
+ });
54532
+ } catch (err) {
54533
+ const reason = err instanceof Error ? err.message : String(err);
54534
+ process.stderr.write(`honeycomb: actions API mount failed (non-fatal): ${reason}
53649
54535
  `);
53650
54536
  }
53651
54537
  try {
@@ -53696,6 +54582,27 @@ function assembleDaemon(options = {}) {
53696
54582
  healthBit = "degraded";
53697
54583
  }
53698
54584
  }
54585
+ const autoBuildGraph = options.storage === void 0 && config2.mode === "local";
54586
+ let graphBuildTimer = null;
54587
+ let graphBuildInFlight = false;
54588
+ async function rebuildCodebaseGraph() {
54589
+ if (graphBuildInFlight)
54590
+ return;
54591
+ graphBuildInFlight = true;
54592
+ try {
54593
+ await buildCodebaseGraphSnapshot(scope, {
54594
+ storage,
54595
+ defaultScope: scope,
54596
+ workspaceDir: options.workspaceDir ?? process.cwd()
54597
+ });
54598
+ } catch (err) {
54599
+ const reason = err instanceof Error ? err.message : String(err);
54600
+ process.stderr.write(`honeycomb: codebase graph auto-build failed (non-fatal): ${reason}
54601
+ `);
54602
+ } finally {
54603
+ graphBuildInFlight = false;
54604
+ }
54605
+ }
53699
54606
  let started = false;
53700
54607
  let locked = false;
53701
54608
  let pollinatingWorker = null;
@@ -53720,6 +54627,15 @@ function assembleDaemon(options = {}) {
53720
54627
  if (typeof probeTimer.unref === "function") {
53721
54628
  probeTimer.unref();
53722
54629
  }
54630
+ if (autoBuildGraph) {
54631
+ void rebuildCodebaseGraph();
54632
+ graphBuildTimer = setInterval(() => {
54633
+ void rebuildCodebaseGraph();
54634
+ }, DEFAULT_GRAPH_BUILD_INTERVAL_MS);
54635
+ if (typeof graphBuildTimer.unref === "function") {
54636
+ graphBuildTimer.unref();
54637
+ }
54638
+ }
53723
54639
  await daemon.startServices();
53724
54640
  let pollBackoff;
53725
54641
  try {
@@ -53733,6 +54649,33 @@ function assembleDaemon(options = {}) {
53733
54649
  } catch {
53734
54650
  consolidatePoll = false;
53735
54651
  }
54652
+ let portkeyWorkerDeps = { onUnreachable: recordPortkeyUnreachable };
54653
+ try {
54654
+ const portkeySelection = await readPortkeySelection(vault, secretScopeFromQueryScope(scope));
54655
+ portkeyHealth = await resolvePortkeyAssemblyStatus(portkeySelection, scope);
54656
+ portkeyWorkerDeps = {
54657
+ ...portkeySelection !== void 0 ? { selection: portkeySelection } : {},
54658
+ onUnreachable: recordPortkeyUnreachable
54659
+ };
54660
+ if (portkeySelection !== void 0) {
54661
+ const rerankSecrets = createSecretResolver(new SecretsStore({ baseDir: resolveWorkspaceBaseDir(), machineKey: createMachineKeyProvider() }), secretScopeFromQueryScope(scope));
54662
+ const rerankClient = createPortkeyRerankClient({
54663
+ config: portkeySelection.config,
54664
+ onTransportError: recordPortkeyUnreachable
54665
+ });
54666
+ cohereRerankInner = buildCohereRerankSeam({
54667
+ client: rerankClient,
54668
+ secrets: rerankSecrets,
54669
+ apiKeyRef: PORTKEY_API_KEY_REF,
54670
+ model: rerankerMountDeps.reranker.cohereModel
54671
+ });
54672
+ } else {
54673
+ cohereRerankInner = void 0;
54674
+ }
54675
+ } catch {
54676
+ portkeyHealth = "off";
54677
+ cohereRerankInner = void 0;
54678
+ }
53736
54679
  try {
53737
54680
  summaryWorker = buildSummaryWorker(storage, scope, daemon.services.queue, embed);
53738
54681
  summaryWorker.start();
@@ -53743,7 +54686,7 @@ function assembleDaemon(options = {}) {
53743
54686
  summaryWorker = null;
53744
54687
  }
53745
54688
  try {
53746
- pipelineWorker = await buildPipelineWorker(options, storage, scope, daemon.services.queue, embed, pollBackoff);
54689
+ pipelineWorker = await buildPipelineWorker(options, storage, scope, daemon.services.queue, embed, pollBackoff, portkeyWorkerDeps);
53747
54690
  if (!consolidatePoll)
53748
54691
  pipelineWorker.start();
53749
54692
  } catch (err) {
@@ -53775,7 +54718,7 @@ function assembleDaemon(options = {}) {
53775
54718
  }
53776
54719
  }
53777
54720
  try {
53778
- pollinatingWorker = await buildGatedPollinatingWorker(options, storage, scope, daemon.services.queue, vault, pollBackoff);
54721
+ pollinatingWorker = await buildGatedPollinatingWorker(options, storage, scope, daemon.services.queue, vault, pollBackoff, portkeyWorkerDeps);
53779
54722
  const pollinatingInjected = options.pollinatingWorker !== void 0;
53780
54723
  if (consolidatePoll && !pollinatingInjected) {
53781
54724
  const participants = [pipelineWorker, pollinatingWorker].filter((p) => p !== null);
@@ -53830,6 +54773,10 @@ function assembleDaemon(options = {}) {
53830
54773
  clearInterval(probeTimer);
53831
54774
  probeTimer = null;
53832
54775
  }
54776
+ if (graphBuildTimer !== null) {
54777
+ clearInterval(graphBuildTimer);
54778
+ graphBuildTimer = null;
54779
+ }
53833
54780
  if (started) {
53834
54781
  await daemon.stopServices();
53835
54782
  started = false;