@legioncodeinc/honeycomb 0.1.9 → 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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +18 -2
- package/bundle/cli.js +19 -3
- package/daemon/index.js +171 -31
- package/embeddings/embed-daemon.js +1 -1
- package/harnesses/claude-code/.claude-plugin/plugin.json +1 -1
- package/harnesses/claude-code/bundle/capture.js +132 -22
- package/harnesses/claude-code/bundle/index.js +132 -22
- package/harnesses/claude-code/bundle/pre-tool-use.js +132 -22
- package/harnesses/claude-code/bundle/session-end.js +132 -22
- package/harnesses/claude-code/bundle/session-start.js +132 -22
- package/harnesses/codex/bundle/capture.js +4 -2
- package/harnesses/codex/bundle/index.js +4 -2
- package/harnesses/codex/bundle/pre-tool-use.js +4 -2
- package/harnesses/codex/bundle/session-start.js +4 -2
- package/harnesses/codex/package.json +1 -1
- package/harnesses/cursor/bundle/capture.js +4 -2
- package/harnesses/cursor/bundle/index.js +4 -2
- package/harnesses/cursor/bundle/pre-tool-use.js +4 -2
- package/harnesses/cursor/bundle/session-end.js +4 -2
- package/harnesses/cursor/bundle/session-start.js +4 -2
- package/harnesses/openclaw/dist/index.js +1 -1
- package/harnesses/openclaw/openclaw.plugin.json +1 -1
- package/harnesses/openclaw/package.json +1 -1
- package/mcp/bundle/server.js +1 -1
- package/package.json +1 -1
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
},
|
|
6
6
|
"metadata": {
|
|
7
7
|
"description": "Honeycomb — persistent memory daemon and thin harness clients for AI coding assistants",
|
|
8
|
-
"version": "0.1.
|
|
8
|
+
"version": "0.1.10"
|
|
9
9
|
},
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "honeycomb",
|
|
13
13
|
"description": "Honeycomb Claude Code plugin — captures session activity and provides cross-session memory through the local daemon",
|
|
14
|
-
"version": "0.1.
|
|
14
|
+
"version": "0.1.10",
|
|
15
15
|
"source": "./harnesses/claude-code"
|
|
16
16
|
}
|
|
17
17
|
]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "honeycomb",
|
|
3
3
|
"description": "Honeycomb — a long-lived daemon plus thin clients for six coding harnesses, the unified honeycomb CLI, the MCP server, and the embed daemon",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.10",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Honeycomb"
|
|
7
7
|
},
|
package/README.md
CHANGED
|
@@ -30,7 +30,12 @@
|
|
|
30
30
|
</picture>
|
|
31
31
|
</a>
|
|
32
32
|
|
|
33
|
-
<a href="https://activeloop.ai"
|
|
33
|
+
<a href="https://activeloop.ai">
|
|
34
|
+
<picture>
|
|
35
|
+
<source media="(prefers-color-scheme: dark)" srcset="assets/logos/activeloop-full-mark-logo-on-dark.svg">
|
|
36
|
+
<img src="assets/logos/activeloop-full-mark-logo.svg" alt="Activeloop" height="26">
|
|
37
|
+
</picture>
|
|
38
|
+
</a>
|
|
34
39
|
</p>
|
|
35
40
|
|
|
36
41
|
<p align="center"><sub>A <a href="https://github.com/legioncodeinc"><strong>Legion Code</strong></a> × <a href="https://activeloop.ai"><strong>Activeloop</strong></a> collaboration · built on <a href="https://github.com/activeloopai/hivemind">Hivemind</a> & <a href="https://deeplake.ai">Deep Lake</a></sub></p>
|
|
@@ -88,7 +93,7 @@ curl -fsSL https://get.theapiary.sh | sh
|
|
|
88
93
|
irm https://get.theapiary.sh/install.ps1 | iex
|
|
89
94
|
```
|
|
90
95
|
|
|
91
|
-
That single line installs a current Node/npm if missing, installs **`@legioncodeinc/honeycomb`** globally, brings up the daemon on `127.0.0.1:3850`, and
|
|
96
|
+
That single line installs a current Node/npm if missing, installs **`@legioncodeinc/honeycomb`** globally, brings up the daemon on `127.0.0.1:3850`, opens the dashboard, and sets up **[HiveDoctor](#-hivedoctor-the-self-healing-watchdog)**, a tiny watchdog that keeps it all healthy (opt out with `--no-hivedoctor`). Then:
|
|
92
97
|
|
|
93
98
|
1. The dashboard loads in a **pre-auth setup state**. No token ever touches your shell.
|
|
94
99
|
2. Click **"First time setup."** Honeycomb runs the Deep Lake device-flow login *for* you, shows the code right on the page, and opens the verification tab.
|
|
@@ -210,6 +215,17 @@ Four ways to reach the same daemon and the same shared memory:
|
|
|
210
215
|
|
|
211
216
|
---
|
|
212
217
|
|
|
218
|
+
## 🩺 HiveDoctor: the self-healing watchdog
|
|
219
|
+
|
|
220
|
+
A daemon you cannot see is a daemon you cannot trust. **[HiveDoctor](https://www.npmjs.com/package/@legioncodeinc/hivedoctor)** is a separate, deliberately tiny package (zero runtime dependencies, Node built-ins only) that keeps your Honeycomb daemon healthy and reports home when it cannot. It is supervised by your OS (launchd / systemd / Windows Scheduled Task), so it survives crashes and reboots independently of the daemon it watches.
|
|
221
|
+
|
|
222
|
+
- **Watches and heals.** Probes the daemon's `/health` and runs an escalating repair ladder with exponential backoff: restart, then reinstall, then remove a conflicting Hivemind, then escalate. It goes quiet the moment the daemon is healthy, and it never touches your credentials.
|
|
223
|
+
- **Tells us when it cannot.** An unhealable install surfaces a local status page and, unless you opt out, sends a scrubbed diagnosis home, so problems get fixed proactively instead of becoming a support thread.
|
|
224
|
+
- **Keeps Honeycomb current.** Safely auto-updates the daemon behind a blessed-release gate, verifying health and rolling back on failure.
|
|
225
|
+
- **Honest by default.** Telemetry is opt-out (`DO_NOT_TRACK=1`, `HONEYCOMB_TELEMETRY=0`, or the dashboard) and never includes credentials, tokens, or your code. The one-command installer sets it up automatically; skip it with `--no-hivedoctor`. Full details in the [HiveDoctor README](hivedoctor/README.md).
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
213
229
|
## 📍 Status & roadmap
|
|
214
230
|
|
|
215
231
|
Honeycomb is **pre-release (v0.1.x)**. We document what's real and flag what's opt-in.
|
package/bundle/cli.js
CHANGED
|
@@ -5,6 +5,10 @@ var __export = (target, all) => {
|
|
|
5
5
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
+
// dist/src/cli/index.js
|
|
9
|
+
import { realpathSync } from "node:fs";
|
|
10
|
+
import { pathToFileURL } from "node:url";
|
|
11
|
+
|
|
8
12
|
// dist/src/commands/contracts.js
|
|
9
13
|
var VERB_GROUPS = Object.freeze([
|
|
10
14
|
{ key: "memory", label: "Memory & recall" },
|
|
@@ -17258,7 +17262,7 @@ function buildAllowedProperties(input) {
|
|
|
17258
17262
|
}
|
|
17259
17263
|
var systemTelemetryClock = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
17260
17264
|
var DEFAULT_EMIT_TIMEOUT_MS = 2e3;
|
|
17261
|
-
var HONEYCOMB_VERSION = true ? "0.1.
|
|
17265
|
+
var HONEYCOMB_VERSION = true ? "0.1.10" : "0.0.0-dev";
|
|
17262
17266
|
async function emitTelemetry(event, opts, deps = {}) {
|
|
17263
17267
|
const env = deps.env ?? process.env;
|
|
17264
17268
|
const key = deps.posthogKey ?? POSTHOG_KEY;
|
|
@@ -17401,7 +17405,7 @@ function renderGlassBoxText(view) {
|
|
|
17401
17405
|
// dist/src/shared/constants.js
|
|
17402
17406
|
var DAEMON_PORT = 3850;
|
|
17403
17407
|
var DAEMON_HOST = "127.0.0.1";
|
|
17404
|
-
var HONEYCOMB_VERSION2 = true ? "0.1.
|
|
17408
|
+
var HONEYCOMB_VERSION2 = true ? "0.1.10" : "0.0.0-dev";
|
|
17405
17409
|
var PRODUCT_SLUG = "honeycomb";
|
|
17406
17410
|
|
|
17407
17411
|
// dist/src/commands/install.js
|
|
@@ -20736,7 +20740,18 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
20736
20740
|
const result = await dispatcher.dispatch(inv, deps);
|
|
20737
20741
|
return result.exitCode;
|
|
20738
20742
|
}
|
|
20739
|
-
|
|
20743
|
+
function isCliEntry(importMetaUrl, argv1) {
|
|
20744
|
+
if (typeof argv1 !== "string" || argv1.length === 0)
|
|
20745
|
+
return false;
|
|
20746
|
+
try {
|
|
20747
|
+
if (importMetaUrl === pathToFileURL(argv1).href)
|
|
20748
|
+
return true;
|
|
20749
|
+
return importMetaUrl === pathToFileURL(realpathSync(argv1)).href;
|
|
20750
|
+
} catch {
|
|
20751
|
+
return false;
|
|
20752
|
+
}
|
|
20753
|
+
}
|
|
20754
|
+
if (isCliEntry(import.meta.url, process.argv[1])) {
|
|
20740
20755
|
main().then(async (code) => {
|
|
20741
20756
|
await finalizeCliExit();
|
|
20742
20757
|
process.exitCode = code;
|
|
@@ -20748,5 +20763,6 @@ if (import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith
|
|
|
20748
20763
|
});
|
|
20749
20764
|
}
|
|
20750
20765
|
export {
|
|
20766
|
+
isCliEntry,
|
|
20751
20767
|
main
|
|
20752
20768
|
};
|
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.
|
|
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 = {};
|
|
@@ -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
|
|
@@ -28182,7 +28190,7 @@ function coarsePipelineStatus(storage) {
|
|
|
28182
28190
|
}
|
|
28183
28191
|
|
|
28184
28192
|
// dist/src/daemon/runtime/assemble.js
|
|
28185
|
-
import { mkdirSync as mkdirSync20, mkdtempSync, readFileSync as
|
|
28193
|
+
import { mkdirSync as mkdirSync20, mkdtempSync, readFileSync as readFileSync23, rmSync as rmSync10, writeFileSync as writeFileSync17 } from "node:fs";
|
|
28186
28194
|
import { homedir as homedir25 } from "node:os";
|
|
28187
28195
|
import { join as join32 } from "node:path";
|
|
28188
28196
|
|
|
@@ -28610,7 +28618,7 @@ function buildAllowedProperties(input) {
|
|
|
28610
28618
|
}
|
|
28611
28619
|
var systemTelemetryClock = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
28612
28620
|
var DEFAULT_EMIT_TIMEOUT_MS = 2e3;
|
|
28613
|
-
var HONEYCOMB_VERSION2 = true ? "0.1.
|
|
28621
|
+
var HONEYCOMB_VERSION2 = true ? "0.1.10" : "0.0.0-dev";
|
|
28614
28622
|
async function emitTelemetry(event, opts, deps = {}) {
|
|
28615
28623
|
const env = deps.env ?? process.env;
|
|
28616
28624
|
const key = deps.posthogKey ?? POSTHOG_KEY;
|
|
@@ -31210,7 +31218,13 @@ var AssistantMessageEventSchema = external_exports.object({
|
|
|
31210
31218
|
kind: external_exports.literal("assistant_message"),
|
|
31211
31219
|
text: external_exports.string(),
|
|
31212
31220
|
/** PRD-060a: optional per-turn token + cache counts; absent when unavailable. */
|
|
31213
|
-
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)
|
|
31214
31228
|
});
|
|
31215
31229
|
var CaptureEventSchema = external_exports.discriminatedUnion("kind", [
|
|
31216
31230
|
UserMessageEventSchema,
|
|
@@ -31648,6 +31662,11 @@ var CaptureRouteHandler = class {
|
|
|
31648
31662
|
// canonical harness token the shim stamps (`claude-code` for the reference
|
|
31649
31663
|
// shim), so every Claude-Code-captured row carries `source_tool='claude-code'`.
|
|
31650
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))],
|
|
31651
31670
|
["creation_date", val.str(nowIso10)],
|
|
31652
31671
|
["last_update_date", val.str(nowIso10)]
|
|
31653
31672
|
];
|
|
@@ -31812,6 +31831,9 @@ function usageColumns(event) {
|
|
|
31812
31831
|
cols.push(["cache_creation_input_tokens", u.cacheCreation]);
|
|
31813
31832
|
return cols;
|
|
31814
31833
|
}
|
|
31834
|
+
function modelFor(event) {
|
|
31835
|
+
return event.kind === "assistant_message" && event.model !== void 0 ? event.model : "";
|
|
31836
|
+
}
|
|
31815
31837
|
function groupRowsByScope(batch) {
|
|
31816
31838
|
const byKey = /* @__PURE__ */ new Map();
|
|
31817
31839
|
for (const item of batch) {
|
|
@@ -36399,11 +36421,15 @@ function tokenCountOrNull(value) {
|
|
|
36399
36421
|
}
|
|
36400
36422
|
function rowToCapturedTurn(r) {
|
|
36401
36423
|
const sourceTool = toStr2(r.source_tool);
|
|
36424
|
+
const model = toStr2(r.model);
|
|
36425
|
+
const isAnthropic = sourceTool === "claude-code" || model.startsWith("claude-");
|
|
36402
36426
|
return {
|
|
36403
36427
|
input_tokens: tokenCountOrNull(r.input_tokens),
|
|
36404
36428
|
output_tokens: tokenCountOrNull(r.output_tokens),
|
|
36405
36429
|
cache_read_input_tokens: tokenCountOrNull(r.cache_read_input_tokens),
|
|
36406
36430
|
cache_creation_input_tokens: tokenCountOrNull(r.cache_creation_input_tokens),
|
|
36431
|
+
...model !== "" ? { model } : {},
|
|
36432
|
+
...model !== "" && isAnthropic ? { provider: "anthropic" } : {},
|
|
36407
36433
|
...sourceTool !== "" ? { sourceTool } : {}
|
|
36408
36434
|
};
|
|
36409
36435
|
}
|
|
@@ -36413,7 +36439,7 @@ async function readCapturedTurns(storage, scope, projectId) {
|
|
|
36413
36439
|
const dateCol = sqlIdent("creation_date");
|
|
36414
36440
|
const idCol = sqlIdent("id");
|
|
36415
36441
|
const projClause = projectWhereClause(projectId);
|
|
36416
|
-
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}`;
|
|
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}`;
|
|
36417
36443
|
const rows = await selectRows2(storage, sql, scope);
|
|
36418
36444
|
return rows.map(rowToCapturedTurn);
|
|
36419
36445
|
}
|
|
@@ -37502,12 +37528,14 @@ function nestedString(raw2, a, b) {
|
|
|
37502
37528
|
function userMessageData(text) {
|
|
37503
37529
|
return { kind: "user_message", text };
|
|
37504
37530
|
}
|
|
37505
|
-
function assistantMessageData(text, usage) {
|
|
37531
|
+
function assistantMessageData(text, usage, model) {
|
|
37506
37532
|
const normalized = usage !== void 0 ? compactUsage(usage) : void 0;
|
|
37533
|
+
const trimmedModel = typeof model === "string" ? model.trim() : "";
|
|
37507
37534
|
return {
|
|
37508
37535
|
kind: "assistant_message",
|
|
37509
37536
|
text,
|
|
37510
|
-
...normalized !== void 0 ? { usage: normalized } : {}
|
|
37537
|
+
...normalized !== void 0 ? { usage: normalized } : {},
|
|
37538
|
+
...trimmedModel !== "" ? { model: trimmedModel } : {}
|
|
37511
37539
|
};
|
|
37512
37540
|
}
|
|
37513
37541
|
function compactUsage(usage) {
|
|
@@ -37577,6 +37605,112 @@ function preToolData(tool, fields) {
|
|
|
37577
37605
|
};
|
|
37578
37606
|
}
|
|
37579
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
|
+
|
|
37580
37714
|
// dist/src/hooks/claude-code/shim.js
|
|
37581
37715
|
var CLAUDE_CODE_EVENT_MAP = {
|
|
37582
37716
|
SessionStart: "session-start",
|
|
@@ -37591,7 +37725,7 @@ var CLAUDE_CODE_CONTEXT_CHANNEL = "model-only";
|
|
|
37591
37725
|
var CLAUDE_CODE_RUNTIME_PATH = "legacy";
|
|
37592
37726
|
var CLAUDE_CODE_HOST_CLI = { bin: "claude", args: ["-p"] };
|
|
37593
37727
|
var CLAUDE_CODE_REFERENCES = "references/claude-code/";
|
|
37594
|
-
function claudeCodeExtractData(raw2, logical) {
|
|
37728
|
+
function claudeCodeExtractData(raw2, logical, meta3) {
|
|
37595
37729
|
switch (logical) {
|
|
37596
37730
|
case "session-start":
|
|
37597
37731
|
return sessionStartData(pickString(raw2, "source") || "startup");
|
|
@@ -37605,8 +37739,11 @@ function claudeCodeExtractData(raw2, logical) {
|
|
|
37605
37739
|
});
|
|
37606
37740
|
case "tool_call":
|
|
37607
37741
|
return toolCallData(pickString(raw2, "tool_name", "tool"), nested(raw2, "tool_input"), nested(raw2, "tool_response"));
|
|
37608
|
-
case "assistant_message":
|
|
37609
|
-
|
|
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
|
+
}
|
|
37610
37747
|
case "session-end":
|
|
37611
37748
|
return sessionEndData(pickString(raw2, "reason") || "Stop");
|
|
37612
37749
|
default:
|
|
@@ -37621,9 +37758,8 @@ function createClaudeCodeShim() {
|
|
|
37621
37758
|
hostCli: CLAUDE_CODE_HOST_CLI,
|
|
37622
37759
|
references: CLAUDE_CODE_REFERENCES,
|
|
37623
37760
|
eventMap: CLAUDE_CODE_EVENT_MAP,
|
|
37624
|
-
extractData(raw2, logical,
|
|
37625
|
-
|
|
37626
|
-
return claudeCodeExtractData(raw2, logical);
|
|
37761
|
+
extractData(raw2, logical, meta3) {
|
|
37762
|
+
return claudeCodeExtractData(raw2, logical, meta3);
|
|
37627
37763
|
}
|
|
37628
37764
|
});
|
|
37629
37765
|
}
|
|
@@ -38659,7 +38795,7 @@ async function tableAbsent(probe, table) {
|
|
|
38659
38795
|
}
|
|
38660
38796
|
|
|
38661
38797
|
// dist/src/daemon/runtime/dashboard/asset-install-target.js
|
|
38662
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync14, readFileSync as
|
|
38798
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync14, readFileSync as readFileSync17, rmSync as rmSync6, writeFileSync as writeFileSync12 } from "node:fs";
|
|
38663
38799
|
import { homedir as homedir17 } from "node:os";
|
|
38664
38800
|
import { join as join21 } from "node:path";
|
|
38665
38801
|
var SKILLS_SUBDIR = join21(".claude", "skills");
|
|
@@ -38695,7 +38831,7 @@ function createFsAssetInstallTarget(dirs = {}) {
|
|
|
38695
38831
|
const { file: file2 } = pathFor(assetType, install, name);
|
|
38696
38832
|
if (!existsSync13(file2))
|
|
38697
38833
|
return null;
|
|
38698
|
-
return
|
|
38834
|
+
return readFileSync17(file2, "utf-8");
|
|
38699
38835
|
} catch {
|
|
38700
38836
|
return null;
|
|
38701
38837
|
}
|
|
@@ -39098,7 +39234,7 @@ function pickAssetType(value) {
|
|
|
39098
39234
|
}
|
|
39099
39235
|
|
|
39100
39236
|
// dist/src/daemon/runtime/dashboard/web-assets.js
|
|
39101
|
-
import { existsSync as existsSync14, readFileSync as
|
|
39237
|
+
import { existsSync as existsSync14, readFileSync as readFileSync18 } from "node:fs";
|
|
39102
39238
|
import { dirname as dirname13, join as join22 } from "node:path";
|
|
39103
39239
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
39104
39240
|
var CSS_FILES = ["tokens/fonts.css", "tokens/colors.css", "tokens/typography.css", "tokens/spacing.css", "tokens/base.css"];
|
|
@@ -39148,7 +39284,7 @@ function resolveBundleDir(startUrl = import.meta.url) {
|
|
|
39148
39284
|
}
|
|
39149
39285
|
function readSoft(path4) {
|
|
39150
39286
|
try {
|
|
39151
|
-
return existsSync14(path4) ?
|
|
39287
|
+
return existsSync14(path4) ? readFileSync18(path4, "utf-8") : null;
|
|
39152
39288
|
} catch {
|
|
39153
39289
|
return null;
|
|
39154
39290
|
}
|
|
@@ -39157,7 +39293,7 @@ function readBinarySoft(path4) {
|
|
|
39157
39293
|
try {
|
|
39158
39294
|
if (!existsSync14(path4))
|
|
39159
39295
|
return null;
|
|
39160
|
-
const buf =
|
|
39296
|
+
const buf = readFileSync18(path4);
|
|
39161
39297
|
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
39162
39298
|
} catch {
|
|
39163
39299
|
return null;
|
|
@@ -48534,7 +48670,7 @@ function buildSourcesApiDeps(options) {
|
|
|
48534
48670
|
// dist/src/daemon/runtime/secrets/store.js
|
|
48535
48671
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
48536
48672
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
48537
|
-
import { appendFileSync, existsSync as existsSync18, mkdirSync as mkdirSync16, readdirSync as readdirSync4, readFileSync as
|
|
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";
|
|
48538
48674
|
import { homedir as homedir21 } from "node:os";
|
|
48539
48675
|
import { join as join27 } from "node:path";
|
|
48540
48676
|
|
|
@@ -49271,7 +49407,7 @@ function readOsMachineId() {
|
|
|
49271
49407
|
if (process.platform === "linux") {
|
|
49272
49408
|
for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
49273
49409
|
if (existsSync18(p)) {
|
|
49274
|
-
const id =
|
|
49410
|
+
const id = readFileSync19(p, "utf8").trim();
|
|
49275
49411
|
if (id.length > 0)
|
|
49276
49412
|
return id;
|
|
49277
49413
|
}
|
|
@@ -49306,7 +49442,7 @@ function readOrCreateFallbackKey(homeDir) {
|
|
|
49306
49442
|
const dir = join27(homeDir, MACHINE_KEY_DIR_NAME);
|
|
49307
49443
|
const file2 = machineKeyFilePath(homeDir);
|
|
49308
49444
|
if (existsSync18(file2)) {
|
|
49309
|
-
const hex4 =
|
|
49445
|
+
const hex4 = readFileSync19(file2, "utf8").trim();
|
|
49310
49446
|
if (hex4.length > 0)
|
|
49311
49447
|
return hex4;
|
|
49312
49448
|
}
|
|
@@ -49437,7 +49573,7 @@ var SecretsStore = class {
|
|
|
49437
49573
|
}
|
|
49438
49574
|
let record2;
|
|
49439
49575
|
try {
|
|
49440
|
-
const parsed = JSON.parse(
|
|
49576
|
+
const parsed = JSON.parse(readFileSync19(file2, "utf8"));
|
|
49441
49577
|
if (!isSecretRecord(parsed)) {
|
|
49442
49578
|
this.audit("resolved_for_exec", scope, "error", safe);
|
|
49443
49579
|
return { ok: false, reason: "io_error" };
|
|
@@ -49527,7 +49663,7 @@ function stripRefWrapper(ref) {
|
|
|
49527
49663
|
}
|
|
49528
49664
|
|
|
49529
49665
|
// dist/src/daemon/runtime/vault/store.js
|
|
49530
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync19, mkdirSync as mkdirSync17, readdirSync as readdirSync5, readFileSync as
|
|
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";
|
|
49531
49667
|
import { join as join28 } from "node:path";
|
|
49532
49668
|
var VAULT_DIR_NAME = ".vault";
|
|
49533
49669
|
var VAULT_AUDIT_FILE_NAME = "vault-audit.ndjson";
|
|
@@ -49729,7 +49865,7 @@ var VaultStore = class {
|
|
|
49729
49865
|
}
|
|
49730
49866
|
let record2;
|
|
49731
49867
|
try {
|
|
49732
|
-
const parsed = JSON.parse(
|
|
49868
|
+
const parsed = JSON.parse(readFileSync20(file2, "utf8"));
|
|
49733
49869
|
if (!isSecretRecord(parsed)) {
|
|
49734
49870
|
this.audit(klass, op, scope, "error", safe);
|
|
49735
49871
|
return { ok: false, reason: "io_error" };
|
|
@@ -52976,7 +53112,7 @@ import { homedir as homedir24 } from "node:os";
|
|
|
52976
53112
|
import { join as join31 } from "node:path";
|
|
52977
53113
|
|
|
52978
53114
|
// dist/src/daemon/runtime/skillify/install-target.js
|
|
52979
|
-
import { mkdirSync as mkdirSync18, readFileSync as
|
|
53115
|
+
import { mkdirSync as mkdirSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync15 } from "node:fs";
|
|
52980
53116
|
import { homedir as homedir22 } from "node:os";
|
|
52981
53117
|
import { join as join29 } from "node:path";
|
|
52982
53118
|
var SKILLS_SUBDIR2 = join29(".claude", "skills");
|
|
@@ -52995,7 +53131,7 @@ function createFsInstallTarget(dirs = {}) {
|
|
|
52995
53131
|
},
|
|
52996
53132
|
async read(install, name) {
|
|
52997
53133
|
try {
|
|
52998
|
-
return
|
|
53134
|
+
return readFileSync21(fileFor(install, name), "utf-8");
|
|
52999
53135
|
} catch {
|
|
53000
53136
|
return null;
|
|
53001
53137
|
}
|
|
@@ -53008,7 +53144,7 @@ function sanitizeSegment4(name) {
|
|
|
53008
53144
|
}
|
|
53009
53145
|
|
|
53010
53146
|
// dist/src/daemon/runtime/skillify/watermark.js
|
|
53011
|
-
import { mkdirSync as mkdirSync19, readFileSync as
|
|
53147
|
+
import { mkdirSync as mkdirSync19, readFileSync as readFileSync22, writeFileSync as writeFileSync16 } from "node:fs";
|
|
53012
53148
|
import { homedir as homedir23 } from "node:os";
|
|
53013
53149
|
import { dirname as dirname14, join as join30 } from "node:path";
|
|
53014
53150
|
function defaultWatermarkBaseDir() {
|
|
@@ -53018,7 +53154,7 @@ function createWatermarkStore(baseDir = defaultWatermarkBaseDir()) {
|
|
|
53018
53154
|
const fileFor = (projectKey) => join30(baseDir, sanitizeSegment5(projectKey), "watermark.json");
|
|
53019
53155
|
const read = (projectKey) => {
|
|
53020
53156
|
try {
|
|
53021
|
-
const raw2 =
|
|
53157
|
+
const raw2 = readFileSync22(fileFor(projectKey), "utf-8");
|
|
53022
53158
|
const parsed = JSON.parse(raw2);
|
|
53023
53159
|
return typeof parsed.watermark === "string" && parsed.watermark !== "" ? parsed.watermark : null;
|
|
53024
53160
|
} catch {
|
|
@@ -53075,18 +53211,22 @@ function tokenCountOrNull2(value) {
|
|
|
53075
53211
|
}
|
|
53076
53212
|
function rowToCapturedTurn2(r) {
|
|
53077
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;
|
|
53078
53216
|
return {
|
|
53079
53217
|
input_tokens: tokenCountOrNull2(r.input_tokens),
|
|
53080
53218
|
output_tokens: tokenCountOrNull2(r.output_tokens),
|
|
53081
53219
|
cache_read_input_tokens: tokenCountOrNull2(r.cache_read_input_tokens),
|
|
53082
53220
|
cache_creation_input_tokens: tokenCountOrNull2(r.cache_creation_input_tokens),
|
|
53083
|
-
...sourceTool !== "" ? { sourceTool } : {}
|
|
53221
|
+
...sourceTool !== "" ? { sourceTool } : {},
|
|
53222
|
+
...model !== "" ? { model } : {},
|
|
53223
|
+
...provider !== void 0 ? { provider } : {}
|
|
53084
53224
|
};
|
|
53085
53225
|
}
|
|
53086
53226
|
async function readSessionTurns(storage, scope, path4) {
|
|
53087
53227
|
const tbl = sqlIdent("sessions");
|
|
53088
53228
|
const pathCol = sqlIdent("path");
|
|
53089
|
-
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}`;
|
|
53090
53230
|
let result;
|
|
53091
53231
|
try {
|
|
53092
53232
|
result = await storage.query(sql, scope);
|
|
@@ -53863,7 +54003,7 @@ function acquireSingleInstanceLock(runtimeDir) {
|
|
|
53863
54003
|
}
|
|
53864
54004
|
function readPidFile(path4) {
|
|
53865
54005
|
try {
|
|
53866
|
-
const raw2 =
|
|
54006
|
+
const raw2 = readFileSync23(path4, "utf8").trim();
|
|
53867
54007
|
if (raw2.length === 0)
|
|
53868
54008
|
return null;
|
|
53869
54009
|
const pid = Number.parseInt(raw2, 10);
|