@legioncodeinc/honeycomb 0.1.7 → 0.1.9
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/bundle/cli.js +581 -74
- package/daemon/dashboard-app.js +23 -23
- package/daemon/index.js +2860 -966
- package/daemon/restart-helper.js +41 -0
- package/embeddings/embed-daemon.js +1 -1
- package/harnesses/claude-code/.claude-plugin/plugin.json +1 -1
- package/harnesses/claude-code/bundle/capture.js +101 -34
- package/harnesses/claude-code/bundle/index.js +101 -34
- package/harnesses/claude-code/bundle/pre-tool-use.js +101 -34
- package/harnesses/claude-code/bundle/session-end.js +101 -34
- package/harnesses/claude-code/bundle/session-start.js +101 -34
- package/harnesses/codex/bundle/capture.js +67 -33
- package/harnesses/codex/bundle/index.js +67 -33
- package/harnesses/codex/bundle/pre-tool-use.js +67 -33
- package/harnesses/codex/bundle/session-start.js +67 -33
- package/harnesses/codex/package.json +1 -1
- package/harnesses/cursor/bundle/capture.js +67 -33
- package/harnesses/cursor/bundle/index.js +67 -33
- package/harnesses/cursor/bundle/pre-tool-use.js +67 -33
- package/harnesses/cursor/bundle/session-end.js +67 -33
- package/harnesses/cursor/bundle/session-start.js +67 -33
- 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
package/bundle/cli.js
CHANGED
|
@@ -6,38 +6,52 @@ var __export = (target, all) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// dist/src/commands/contracts.js
|
|
9
|
+
var VERB_GROUPS = Object.freeze([
|
|
10
|
+
{ key: "memory", label: "Memory & recall" },
|
|
11
|
+
{ key: "knowledge", label: "Knowledge & skills" },
|
|
12
|
+
{ key: "agents", label: "Agents, routing & config" },
|
|
13
|
+
{ key: "account", label: "Account & workspaces" },
|
|
14
|
+
{ key: "system", label: "Setup & system" }
|
|
15
|
+
]);
|
|
9
16
|
var VERB_TABLE = Object.freeze([
|
|
10
|
-
|
|
11
|
-
{ verb: "
|
|
12
|
-
{ verb: "
|
|
13
|
-
{ verb: "
|
|
14
|
-
{ verb: "
|
|
15
|
-
{ verb: "
|
|
16
|
-
{ verb: "
|
|
17
|
-
|
|
18
|
-
{ verb: "
|
|
19
|
-
{ verb: "
|
|
20
|
-
{ verb: "
|
|
21
|
-
{ verb: "
|
|
22
|
-
{ verb: "
|
|
23
|
-
{ verb: "
|
|
24
|
-
{ verb: "
|
|
25
|
-
|
|
26
|
-
{ verb: "
|
|
27
|
-
{ verb: "
|
|
28
|
-
{ verb: "
|
|
29
|
-
{ verb: "
|
|
30
|
-
|
|
31
|
-
{ verb: "
|
|
32
|
-
{ verb: "
|
|
33
|
-
{ verb: "whoami", cls: "auth", summary: "show the authenticated user, org, and workspace (GET /me)" },
|
|
34
|
-
{ verb: "org", cls: "auth", summary: "list/switch org (passthrough to the auth dispatcher)" },
|
|
35
|
-
{ verb: "workspace", cls: "auth", summary: "list/switch/use workspace (passthrough to the auth dispatcher)" },
|
|
36
|
-
{ verb: "workspaces", cls: "auth", summary: "list workspaces in the active org (alias of `workspace list`)" },
|
|
37
|
-
{ verb: "project", cls: "auth", summary: "list/bind/use projects + show the resolved per-folder scope (049d)" },
|
|
38
|
-
|
|
39
|
-
{ verb: "
|
|
40
|
-
{ verb: "
|
|
17
|
+
// Memory & recall — the product's core write/read/lifecycle surface.
|
|
18
|
+
{ verb: "remember", cls: "storage", group: "memory", summary: "write a memory through the daemon (--type fact|convention|preference|decision|gotcha|reference)" },
|
|
19
|
+
{ verb: "recall", cls: "storage", group: "memory", summary: "recall memories through the daemon" },
|
|
20
|
+
{ verb: "memory", cls: "storage", group: "memory", summary: "lifecycle: conflicts (list/resolve), stale-refs (list), inspect <id> --lifecycle (058d)" },
|
|
21
|
+
{ verb: "sessions", cls: "storage", group: "memory", summary: "list/prune captured sessions through the daemon" },
|
|
22
|
+
{ verb: "pollinate", cls: "storage", group: "memory", summary: "trigger a pollinating consolidation pass on the daemon (009/026)" },
|
|
23
|
+
{ verb: "maintenance", cls: "storage", group: "memory", summary: "run version-history compaction over version-bumped tables (030)" },
|
|
24
|
+
// Knowledge & skills — skills, assets, ontology, the codebase graph, and goals.
|
|
25
|
+
{ verb: "skill", cls: "storage", group: "knowledge", summary: "skillify scope/pull/unpull/force/promote through the daemon (promote = cross-project, 049c)" },
|
|
26
|
+
{ verb: "skillify", cls: "storage", group: "knowledge", summary: "pull team skills from the daemon (016c)" },
|
|
27
|
+
{ verb: "asset", cls: "storage", group: "knowledge", summary: "register/promote/demote/style skills+agents through the tier\xD7style lattice (033)" },
|
|
28
|
+
{ verb: "ontology", cls: "storage", group: "knowledge", summary: "inspect/propose ontology changes through the daemon" },
|
|
29
|
+
{ verb: "graph", cls: "storage", group: "knowledge", summary: "build/query the codebase graph through the daemon" },
|
|
30
|
+
{ verb: "sources", cls: "storage", group: "knowledge", summary: "connect/index/purge sources through the daemon" },
|
|
31
|
+
{ verb: "goal", cls: "storage", group: "knowledge", summary: "manage goals/KPIs through the daemon" },
|
|
32
|
+
// Agents, routing & config — agent turns, inference routes, secrets, and vault settings.
|
|
33
|
+
{ verb: "agent", cls: "storage", group: "agents", summary: "run an agent turn through the daemon" },
|
|
34
|
+
{ verb: "route", cls: "storage", group: "agents", summary: "manage inference routes through the daemon" },
|
|
35
|
+
{ verb: "secret", cls: "storage", group: "agents", summary: "manage named secrets through the daemon" },
|
|
36
|
+
{ verb: "settings", cls: "storage", group: "agents", summary: "get/set/list vault settings + provider\u2192model selector through the daemon" },
|
|
37
|
+
// Account & workspaces — auth, identity, and the org/workspace/project scope surface.
|
|
38
|
+
{ verb: "login", cls: "auth", group: "account", summary: "authenticate via device flow, or --token <key> for headless (023)" },
|
|
39
|
+
{ verb: "logout", cls: "auth", group: "account", summary: "remove the shared credentials and sign out (023)" },
|
|
40
|
+
{ verb: "whoami", cls: "auth", group: "account", summary: "show the authenticated user, org, and workspace (GET /me)" },
|
|
41
|
+
{ verb: "org", cls: "auth", group: "account", summary: "list/switch org (passthrough to the auth dispatcher)" },
|
|
42
|
+
{ verb: "workspace", cls: "auth", group: "account", summary: "list/switch/use workspace (passthrough to the auth dispatcher)" },
|
|
43
|
+
{ verb: "workspaces", cls: "auth", group: "account", summary: "list workspaces in the active org (alias of `workspace list`)" },
|
|
44
|
+
{ verb: "project", cls: "auth", group: "account", summary: "list/bind/use projects + show the resolved per-folder scope (049d)" },
|
|
45
|
+
// Setup & system — install/onboard, daemon lifecycle, dashboard, hooks, telemetry, update.
|
|
46
|
+
{ verb: "setup", cls: "local", group: "system", summary: "detect assistants, wire hooks, bring up the daemon" },
|
|
47
|
+
{ verb: "install", cls: "local", group: "system", summary: "bring up the daemon (health-gated) + open the dashboard (PRD-050a)" },
|
|
48
|
+
{ verb: "status", cls: "local", group: "system", summary: "daemon connectivity + login + D1\u2013D5 environment health" },
|
|
49
|
+
{ verb: "daemon", cls: "local", group: "system", summary: "start | stop | status the loopback daemon (3850)" },
|
|
50
|
+
{ verb: "dashboard", cls: "local", group: "system", summary: "launch the daemon-served dashboard (020b)" },
|
|
51
|
+
{ verb: "hook", cls: "local", group: "system", summary: "inspect/wire harness hooks" },
|
|
52
|
+
{ verb: "telemetry", cls: "local", group: "system", summary: "show exactly what adoption telemetry has been / would be sent (--show, PRD-050e)" },
|
|
53
|
+
{ verb: "update", cls: "local", group: "system", summary: "self-update the CLI, daemon, and bundles" },
|
|
54
|
+
{ verb: "uninstall", cls: "local", group: "system", summary: "reverse only Honeycomb's changes" }
|
|
41
55
|
]);
|
|
42
56
|
function lookupVerb(verb) {
|
|
43
57
|
return VERB_TABLE.find((v) => v.verb === verb);
|
|
@@ -514,6 +528,15 @@ var PROVIDER_CATALOG = Object.freeze([
|
|
|
514
528
|
// Suggestions only — OpenRouter accepts a free-form `vendor/model` id (passthrough).
|
|
515
529
|
models: Object.freeze(["anthropic/claude-sonnet-4.6", "openai/gpt-4o"]),
|
|
516
530
|
openEnded: true
|
|
531
|
+
}),
|
|
532
|
+
Object.freeze({
|
|
533
|
+
// PRD-063a: Portkey is a GATEWAY, not a model vendor — its `portkey.config` id is
|
|
534
|
+
// free-form (a config or virtual-key id copied from the Portkey dashboard), so it is
|
|
535
|
+
// `openEnded: true` like OpenRouter and carries NO curated model list of its own.
|
|
536
|
+
id: "portkey",
|
|
537
|
+
label: "Portkey",
|
|
538
|
+
models: Object.freeze([]),
|
|
539
|
+
openEnded: true
|
|
517
540
|
})
|
|
518
541
|
]);
|
|
519
542
|
function providerEntry(provider) {
|
|
@@ -16488,10 +16511,10 @@ function flagValue3(argv, flag) {
|
|
|
16488
16511
|
return v !== void 0 && !v.startsWith("--") ? v : void 0;
|
|
16489
16512
|
}
|
|
16490
16513
|
function parseSkillId(raw) {
|
|
16491
|
-
const
|
|
16492
|
-
if (
|
|
16514
|
+
const sep4 = raw.lastIndexOf("--");
|
|
16515
|
+
if (sep4 <= 0)
|
|
16493
16516
|
return { name: raw, author: "" };
|
|
16494
|
-
return { name: raw.slice(0,
|
|
16517
|
+
return { name: raw.slice(0, sep4), author: raw.slice(sep4 + 2) };
|
|
16495
16518
|
}
|
|
16496
16519
|
function buildSkillRequest(argv) {
|
|
16497
16520
|
const sub = subcommandOf(argv);
|
|
@@ -17235,7 +17258,7 @@ function buildAllowedProperties(input) {
|
|
|
17235
17258
|
}
|
|
17236
17259
|
var systemTelemetryClock = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
17237
17260
|
var DEFAULT_EMIT_TIMEOUT_MS = 2e3;
|
|
17238
|
-
var HONEYCOMB_VERSION = true ? "0.1.
|
|
17261
|
+
var HONEYCOMB_VERSION = true ? "0.1.9" : "0.0.0-dev";
|
|
17239
17262
|
async function emitTelemetry(event, opts, deps = {}) {
|
|
17240
17263
|
const env = deps.env ?? process.env;
|
|
17241
17264
|
const key = deps.posthogKey ?? POSTHOG_KEY;
|
|
@@ -17378,7 +17401,7 @@ function renderGlassBoxText(view) {
|
|
|
17378
17401
|
// dist/src/shared/constants.js
|
|
17379
17402
|
var DAEMON_PORT = 3850;
|
|
17380
17403
|
var DAEMON_HOST = "127.0.0.1";
|
|
17381
|
-
var HONEYCOMB_VERSION2 = true ? "0.1.
|
|
17404
|
+
var HONEYCOMB_VERSION2 = true ? "0.1.9" : "0.0.0-dev";
|
|
17382
17405
|
var PRODUCT_SLUG = "honeycomb";
|
|
17383
17406
|
|
|
17384
17407
|
// dist/src/commands/install.js
|
|
@@ -17461,6 +17484,19 @@ function openDashboardWithFallback(opener, out) {
|
|
|
17461
17484
|
const opened = opener(loopback);
|
|
17462
17485
|
out(opened ? `\u2192 opening dashboard at ${loopback}\u2026` : `\u2192 dashboard is ready at ${loopback} (open it in your browser).`);
|
|
17463
17486
|
}
|
|
17487
|
+
async function reportDaemonSupervision(deps, out) {
|
|
17488
|
+
if (deps.lifecycle === void 0)
|
|
17489
|
+
return;
|
|
17490
|
+
try {
|
|
17491
|
+
const status3 = await deps.lifecycle.status();
|
|
17492
|
+
if (status3.serviceManager !== void 0) {
|
|
17493
|
+
out(`\u2713 daemon registered as an OS service (${status3.serviceManager}): it restarts on crash and starts on boot.`);
|
|
17494
|
+
} else {
|
|
17495
|
+
out("note: daemon running as a detached process (OS service registration unavailable on this host).");
|
|
17496
|
+
}
|
|
17497
|
+
} catch {
|
|
17498
|
+
}
|
|
17499
|
+
}
|
|
17464
17500
|
async function runInstallCommand(argv, deps) {
|
|
17465
17501
|
const out = deps.out ?? ((line) => console.log(line));
|
|
17466
17502
|
const opener = deps.openDashboard ?? openLocalDashboardUrl;
|
|
@@ -17477,6 +17513,7 @@ async function runInstallCommand(argv, deps) {
|
|
|
17477
17513
|
return { exitCode: 1 };
|
|
17478
17514
|
}
|
|
17479
17515
|
out(`\u2713 daemon up on ${DAEMON_HOST}:${DAEMON_PORT}.`);
|
|
17516
|
+
await reportDaemonSupervision(deps, out);
|
|
17480
17517
|
const wrote = writeInstalledMarker(ref, deps.dir, out);
|
|
17481
17518
|
if (wrote)
|
|
17482
17519
|
out(`\u2713 onboarding marked installed (ref: ${ref}).`);
|
|
@@ -17535,12 +17572,26 @@ function parseInvocation(argv) {
|
|
|
17535
17572
|
const tail = verb === "" ? argv.slice(i) : argv.slice(i + 1);
|
|
17536
17573
|
return { verb, argv: tail, flags };
|
|
17537
17574
|
}
|
|
17575
|
+
var HONEYCOMB_BANNER = [
|
|
17576
|
+
" __ __ __",
|
|
17577
|
+
" / \\__/ \\__/ \\ H O N E Y C O M B",
|
|
17578
|
+
" \\__/ \\__/ \\__/",
|
|
17579
|
+
" / \\__/ \\__/ \\ shared agent memory for your coding tools",
|
|
17580
|
+
" \\__/ \\__/ \\__/"
|
|
17581
|
+
].join("\n");
|
|
17538
17582
|
function usageText() {
|
|
17539
|
-
const lines = [`${PRODUCT_SLUG} v${HONEYCOMB_VERSION2}`, "", "usage: honeycomb <command> [options]", ""
|
|
17540
|
-
|
|
17541
|
-
|
|
17583
|
+
const lines = [HONEYCOMB_BANNER, "", `${PRODUCT_SLUG} v${HONEYCOMB_VERSION2}`, "", "usage: honeycomb <command> [options]", ""];
|
|
17584
|
+
const pad = VERB_TABLE.reduce((w, s2) => Math.max(w, s2.verb.length), 0) + 2;
|
|
17585
|
+
for (const { key, label } of VERB_GROUPS) {
|
|
17586
|
+
const rows = VERB_TABLE.filter((s2) => s2.group === key);
|
|
17587
|
+
if (rows.length === 0)
|
|
17588
|
+
continue;
|
|
17589
|
+
lines.push(`${label}:`);
|
|
17590
|
+
for (const spec of rows)
|
|
17591
|
+
lines.push(` ${spec.verb.padEnd(pad)}${spec.summary}`);
|
|
17592
|
+
lines.push("");
|
|
17542
17593
|
}
|
|
17543
|
-
lines.push("
|
|
17594
|
+
lines.push("global flags: --help --version --json --dry-run");
|
|
17544
17595
|
return lines.join("\n");
|
|
17545
17596
|
}
|
|
17546
17597
|
function lifecycleOf(deps) {
|
|
@@ -17663,13 +17714,14 @@ function createDispatcher() {
|
|
|
17663
17714
|
|
|
17664
17715
|
// dist/src/cli/runtime.js
|
|
17665
17716
|
import { spawn } from "node:child_process";
|
|
17666
|
-
import {
|
|
17667
|
-
import {
|
|
17717
|
+
import { mkdirSync as mkdirSync8, mkdtempSync, rmSync as rmSync2 } from "node:fs";
|
|
17718
|
+
import { homedir as homedir13 } from "node:os";
|
|
17719
|
+
import { dirname as dirname8, join as join13, resolve as resolve8 } from "node:path";
|
|
17668
17720
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
17669
17721
|
|
|
17670
17722
|
// dist/src/daemon/runtime/auth/deeplake-issuer.js
|
|
17671
17723
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
17672
|
-
var realSleeper = (ms) => new Promise((
|
|
17724
|
+
var realSleeper = (ms) => new Promise((resolve9) => setTimeout(resolve9, ms));
|
|
17673
17725
|
var DEEPLAKE_CLIENT_HEADER = "X-Deeplake-Client";
|
|
17674
17726
|
var DEEPLAKE_ORG_HEADER = "X-Activeloop-Org-Id";
|
|
17675
17727
|
var DEEPLAKE_CLIENT_VALUE = "honeycomb";
|
|
@@ -18139,6 +18191,51 @@ var ROUTER_HISTORY_COLUMNS = Object.freeze([
|
|
|
18139
18191
|
{ name: "workspace_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18140
18192
|
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
18141
18193
|
]);
|
|
18194
|
+
var ROI_METRICS_COLUMNS = Object.freeze([
|
|
18195
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18196
|
+
{ name: "session_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18197
|
+
{ name: "org_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18198
|
+
{ name: "workspace_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18199
|
+
{ name: "agent_id", sql: "TEXT NOT NULL DEFAULT 'default'" },
|
|
18200
|
+
{ name: "project_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18201
|
+
{ name: "team_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18202
|
+
// GATED: '' until a verified backend-token claim populates it (f-AC-6/f-AC-7).
|
|
18203
|
+
{ name: "user_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18204
|
+
{ name: "input_tokens", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
18205
|
+
{ name: "output_tokens", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
18206
|
+
{ name: "cache_read_tokens", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
18207
|
+
{ name: "cache_creation_tokens", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
18208
|
+
// MEASURED / MODELED / GROSS / INFRA money — BIGINT integer cents, never FLOAT (f-AC-4).
|
|
18209
|
+
{ name: "measured_cache_savings_cents", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
18210
|
+
{ name: "modeled_savings_cents", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
18211
|
+
{ name: "modeled_assumption_ref", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18212
|
+
{ name: "gross_cost_cents", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
18213
|
+
{ name: "infra_cost_cents", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
18214
|
+
// cost_basis ∈ {measured, allocated, none}; allocation_method '' unless allocated (f-AC-5).
|
|
18215
|
+
{ name: "cost_basis", sql: "TEXT NOT NULL DEFAULT 'none'" },
|
|
18216
|
+
{ name: "allocation_method", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18217
|
+
{ name: "price_ref", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18218
|
+
{ name: "period_start", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18219
|
+
{ name: "period_end", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18220
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
18221
|
+
]);
|
|
18222
|
+
var ROI_COST_BASES = Object.freeze(["measured", "allocated", "none"]);
|
|
18223
|
+
var TEAMS_COLUMNS = Object.freeze([
|
|
18224
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18225
|
+
{ name: "team_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18226
|
+
{ name: "team_name", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18227
|
+
// 'agent' rows work today; 'user' rows inert until user_id verified.
|
|
18228
|
+
{ name: "member_type", sql: "TEXT NOT NULL DEFAULT 'agent'" },
|
|
18229
|
+
{ name: "member_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18230
|
+
{ name: "role", sql: "TEXT NOT NULL DEFAULT 'member'" },
|
|
18231
|
+
{ name: "active", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
18232
|
+
{ name: "org_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18233
|
+
{ name: "workspace_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18234
|
+
{ name: "version", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
18235
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
18236
|
+
{ name: "updated_at", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
18237
|
+
]);
|
|
18238
|
+
var TEAM_MEMBER_TYPES = Object.freeze(["agent", "user"]);
|
|
18142
18239
|
var TENANCY_TABLES = defineGroup([
|
|
18143
18240
|
{
|
|
18144
18241
|
name: "agents",
|
|
@@ -18177,6 +18274,25 @@ var TENANCY_TABLES = defineGroup([
|
|
|
18177
18274
|
pattern: "append-only",
|
|
18178
18275
|
embeddingColumns: [],
|
|
18179
18276
|
scope: "tenant"
|
|
18277
|
+
},
|
|
18278
|
+
{
|
|
18279
|
+
// PRD-060f (f-AC-1/f-AC-2): the shared spend ledger. APPEND-ONLY — one
|
|
18280
|
+
// immutable row per session, a re-price APPENDs a new row (new price_ref),
|
|
18281
|
+
// NEVER an in-place UPDATE; the canonical row is MAX(created_at) per session.
|
|
18282
|
+
name: "roi_metrics",
|
|
18283
|
+
columns: ROI_METRICS_COLUMNS,
|
|
18284
|
+
pattern: "append-only",
|
|
18285
|
+
embeddingColumns: [],
|
|
18286
|
+
scope: "tenant"
|
|
18287
|
+
},
|
|
18288
|
+
{
|
|
18289
|
+
// PRD-060f (f-AC-8): the roster. VERSION-BUMPED — one row per (team, member),
|
|
18290
|
+
// an edit APPENDs version N+1, read ORDER BY version DESC (same as api_keys).
|
|
18291
|
+
name: "teams",
|
|
18292
|
+
columns: TEAMS_COLUMNS,
|
|
18293
|
+
pattern: "version-bumped",
|
|
18294
|
+
embeddingColumns: [],
|
|
18295
|
+
scope: "tenant"
|
|
18180
18296
|
}
|
|
18181
18297
|
]);
|
|
18182
18298
|
var SCRYPT_PARAMS = Object.freeze({ N: 16384, r: 8, p: 1, keyLen: 32 });
|
|
@@ -19903,6 +20019,27 @@ var EMPTY_DASHBOARD_DATA = Object.freeze({
|
|
|
19903
20019
|
rules: { rules: [] },
|
|
19904
20020
|
skillSync: { skills: [] }
|
|
19905
20021
|
});
|
|
20022
|
+
var EMPTY_ROI_VIEW = Object.freeze({
|
|
20023
|
+
savings: {
|
|
20024
|
+
status: "absent",
|
|
20025
|
+
measuredCents: 0,
|
|
20026
|
+
modeledCents: 0,
|
|
20027
|
+
assumption: { kind: "", assumptionText: "", signedOff: false },
|
|
20028
|
+
blendedCentsPerMtok: null
|
|
20029
|
+
},
|
|
20030
|
+
infra: { status: "absent", cents: 0, costBasis: "none" },
|
|
20031
|
+
pollination: { status: "absent", cents: 0, lines: [] },
|
|
20032
|
+
net: { status: "absent", computed: false, netCents: 0, modeled: true, costBasis: "none" },
|
|
20033
|
+
rollups: [],
|
|
20034
|
+
perUserAvailable: false,
|
|
20035
|
+
scopedAcrossDevices: false,
|
|
20036
|
+
ratesAsOf: ""
|
|
20037
|
+
});
|
|
20038
|
+
var EMPTY_ROI_TREND = Object.freeze({
|
|
20039
|
+
status: "absent",
|
|
20040
|
+
series: [],
|
|
20041
|
+
startedAt: ""
|
|
20042
|
+
});
|
|
19906
20043
|
|
|
19907
20044
|
// dist/src/dashboard/views.js
|
|
19908
20045
|
var GRAPH_BUILD_PROMPT = "Run `honeycomb graph build` to build the codebase graph.";
|
|
@@ -20034,6 +20171,273 @@ async function launchDashboard(options = {}) {
|
|
|
20034
20171
|
return renderDashboard(source);
|
|
20035
20172
|
}
|
|
20036
20173
|
|
|
20174
|
+
// dist/src/cli/daemon-service.js
|
|
20175
|
+
import { createRequire } from "node:module";
|
|
20176
|
+
import { homedir as homedir12 } from "node:os";
|
|
20177
|
+
import { join as join12, normalize, resolve as resolve7, sep as sep3 } from "node:path";
|
|
20178
|
+
var SERVICE_LABEL = "ai.honeycomb.daemon";
|
|
20179
|
+
var SERVICE_TASK_NAME = "HoneycombDaemon";
|
|
20180
|
+
var SERVICE_MODE_ENV = "HONEYCOMB_DAEMON_SERVICE";
|
|
20181
|
+
function detectServiceManager(env = process.env, platform2 = process.platform) {
|
|
20182
|
+
if ((env[SERVICE_MODE_ENV] ?? "").trim().toLowerCase() === "spawn")
|
|
20183
|
+
return null;
|
|
20184
|
+
if (platform2 === "darwin")
|
|
20185
|
+
return "launchd";
|
|
20186
|
+
if (platform2 === "win32")
|
|
20187
|
+
return "schtasks";
|
|
20188
|
+
if (platform2 === "linux") {
|
|
20189
|
+
const xdg = (env.XDG_RUNTIME_DIR ?? "").trim();
|
|
20190
|
+
if (xdg.length > 0)
|
|
20191
|
+
return "systemd-user";
|
|
20192
|
+
return null;
|
|
20193
|
+
}
|
|
20194
|
+
return null;
|
|
20195
|
+
}
|
|
20196
|
+
function defaultServiceRunner() {
|
|
20197
|
+
const require2 = createRequire(import.meta.url);
|
|
20198
|
+
const cp = require2("node:child_process");
|
|
20199
|
+
const fs = require2("node:fs");
|
|
20200
|
+
return {
|
|
20201
|
+
run(cmd, args) {
|
|
20202
|
+
const out = cp.execFileSync(cmd, [...args], {
|
|
20203
|
+
encoding: "utf8",
|
|
20204
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
20205
|
+
timeout: 15e3,
|
|
20206
|
+
windowsHide: true
|
|
20207
|
+
});
|
|
20208
|
+
return typeof out === "string" ? out.trim() : "";
|
|
20209
|
+
},
|
|
20210
|
+
writeFile(path, contents) {
|
|
20211
|
+
fs.mkdirSync(join12(path, ".."), { recursive: true });
|
|
20212
|
+
fs.writeFileSync(path, contents, { encoding: "utf8" });
|
|
20213
|
+
},
|
|
20214
|
+
removeFile(path) {
|
|
20215
|
+
try {
|
|
20216
|
+
fs.rmSync(path, { force: true });
|
|
20217
|
+
} catch {
|
|
20218
|
+
}
|
|
20219
|
+
},
|
|
20220
|
+
fileExists(path) {
|
|
20221
|
+
try {
|
|
20222
|
+
return fs.existsSync(path);
|
|
20223
|
+
} catch {
|
|
20224
|
+
return false;
|
|
20225
|
+
}
|
|
20226
|
+
}
|
|
20227
|
+
};
|
|
20228
|
+
}
|
|
20229
|
+
function containedUnitPath(home, segments) {
|
|
20230
|
+
const resolvedHome = normalize(resolve7(home));
|
|
20231
|
+
const candidate = normalize(resolve7(resolvedHome, ...segments));
|
|
20232
|
+
const homeWithSep = resolvedHome.endsWith(sep3) ? resolvedHome : resolvedHome + sep3;
|
|
20233
|
+
if (candidate !== resolvedHome && !candidate.startsWith(homeWithSep)) {
|
|
20234
|
+
throw new Error("resolved service unit path escapes the home dir");
|
|
20235
|
+
}
|
|
20236
|
+
return candidate;
|
|
20237
|
+
}
|
|
20238
|
+
function launchdPlistPath(home) {
|
|
20239
|
+
return containedUnitPath(home, ["Library", "LaunchAgents", `${SERVICE_LABEL}.plist`]);
|
|
20240
|
+
}
|
|
20241
|
+
function systemdUnitPath(home) {
|
|
20242
|
+
return containedUnitPath(home, [".config", "systemd", "user", `${SERVICE_LABEL}.service`]);
|
|
20243
|
+
}
|
|
20244
|
+
function xmlEscape(value) {
|
|
20245
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
20246
|
+
}
|
|
20247
|
+
function renderLaunchdPlist(spec) {
|
|
20248
|
+
const argv = [spec.nodePath, ...spec.nodeFlags, spec.entry];
|
|
20249
|
+
const argvXml = argv.map((a) => ` <string>${xmlEscape(a)}</string>`).join("\n");
|
|
20250
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
20251
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
20252
|
+
<plist version="1.0">
|
|
20253
|
+
<dict>
|
|
20254
|
+
<key>Label</key>
|
|
20255
|
+
<string>${SERVICE_LABEL}</string>
|
|
20256
|
+
<key>ProgramArguments</key>
|
|
20257
|
+
<array>
|
|
20258
|
+
${argvXml}
|
|
20259
|
+
</array>
|
|
20260
|
+
<key>WorkingDirectory</key>
|
|
20261
|
+
<string>${xmlEscape(spec.workspace)}</string>
|
|
20262
|
+
<key>EnvironmentVariables</key>
|
|
20263
|
+
<dict>
|
|
20264
|
+
<key>HONEYCOMB_WORKSPACE</key>
|
|
20265
|
+
<string>${xmlEscape(spec.workspace)}</string>
|
|
20266
|
+
</dict>
|
|
20267
|
+
<key>RunAtLoad</key>
|
|
20268
|
+
<true/>
|
|
20269
|
+
<key>KeepAlive</key>
|
|
20270
|
+
<true/>
|
|
20271
|
+
<key>ProcessType</key>
|
|
20272
|
+
<string>Background</string>
|
|
20273
|
+
</dict>
|
|
20274
|
+
</plist>
|
|
20275
|
+
`;
|
|
20276
|
+
}
|
|
20277
|
+
function renderSystemdUnit(spec) {
|
|
20278
|
+
const execStart = [spec.nodePath, ...spec.nodeFlags, spec.entry].map((a) => `"${a}"`).join(" ");
|
|
20279
|
+
return `[Unit]
|
|
20280
|
+
Description=Honeycomb primary daemon (127.0.0.1:3850)
|
|
20281
|
+
After=network.target
|
|
20282
|
+
|
|
20283
|
+
[Service]
|
|
20284
|
+
Type=simple
|
|
20285
|
+
ExecStart=${execStart}
|
|
20286
|
+
WorkingDirectory=${spec.workspace}
|
|
20287
|
+
Environment=HONEYCOMB_WORKSPACE=${spec.workspace}
|
|
20288
|
+
Restart=always
|
|
20289
|
+
RestartSec=5
|
|
20290
|
+
|
|
20291
|
+
[Install]
|
|
20292
|
+
WantedBy=default.target
|
|
20293
|
+
`;
|
|
20294
|
+
}
|
|
20295
|
+
function assertCmdSafe(value) {
|
|
20296
|
+
if (/[&|<>^"%\r\n]/.test(value)) {
|
|
20297
|
+
throw new Error("unsafe character in service path; refusing to build schtasks /TR command");
|
|
20298
|
+
}
|
|
20299
|
+
}
|
|
20300
|
+
function buildSchtasksCreateArgs(spec) {
|
|
20301
|
+
assertCmdSafe(spec.workspace);
|
|
20302
|
+
assertCmdSafe(spec.nodePath);
|
|
20303
|
+
assertCmdSafe(spec.entry);
|
|
20304
|
+
const nodeFlags = spec.nodeFlags.length > 0 ? `${spec.nodeFlags.join(" ")} ` : "";
|
|
20305
|
+
const tr = `cmd /c "cd /d "${spec.workspace}" && set HONEYCOMB_WORKSPACE=${spec.workspace} && "${spec.nodePath}" ${nodeFlags}"${spec.entry}""`;
|
|
20306
|
+
return [
|
|
20307
|
+
"/Create",
|
|
20308
|
+
"/TN",
|
|
20309
|
+
SERVICE_TASK_NAME,
|
|
20310
|
+
"/TR",
|
|
20311
|
+
tr,
|
|
20312
|
+
"/SC",
|
|
20313
|
+
"ONLOGON",
|
|
20314
|
+
"/RL",
|
|
20315
|
+
"LIMITED",
|
|
20316
|
+
"/F"
|
|
20317
|
+
];
|
|
20318
|
+
}
|
|
20319
|
+
function specHome(spec) {
|
|
20320
|
+
return spec.home ?? homedir12();
|
|
20321
|
+
}
|
|
20322
|
+
function createDaemonServiceController(manager, runner = defaultServiceRunner()) {
|
|
20323
|
+
if (manager === "launchd")
|
|
20324
|
+
return launchdController(runner);
|
|
20325
|
+
if (manager === "systemd-user")
|
|
20326
|
+
return systemdController(runner);
|
|
20327
|
+
return schtasksController(runner);
|
|
20328
|
+
}
|
|
20329
|
+
function launchdController(runner) {
|
|
20330
|
+
function domain2() {
|
|
20331
|
+
return `gui/${process.getuid?.() ?? 501}`;
|
|
20332
|
+
}
|
|
20333
|
+
return {
|
|
20334
|
+
manager: "launchd",
|
|
20335
|
+
register(spec) {
|
|
20336
|
+
const path = launchdPlistPath(specHome(spec));
|
|
20337
|
+
runner.writeFile(path, renderLaunchdPlist(spec));
|
|
20338
|
+
runner.run("launchctl", ["bootstrap", domain2(), path]);
|
|
20339
|
+
return { ok: true, manager: "launchd" };
|
|
20340
|
+
},
|
|
20341
|
+
unregister(spec) {
|
|
20342
|
+
const path = launchdPlistPath(specHome(spec));
|
|
20343
|
+
try {
|
|
20344
|
+
runner.run("launchctl", ["bootout", `${domain2()}/${SERVICE_LABEL}`]);
|
|
20345
|
+
} catch {
|
|
20346
|
+
}
|
|
20347
|
+
runner.removeFile(path);
|
|
20348
|
+
return { ok: true, manager: "launchd" };
|
|
20349
|
+
},
|
|
20350
|
+
restart(_spec) {
|
|
20351
|
+
runner.run("launchctl", ["kickstart", "-k", `${domain2()}/${SERVICE_LABEL}`]);
|
|
20352
|
+
return { ok: true, manager: "launchd" };
|
|
20353
|
+
},
|
|
20354
|
+
stop(_spec) {
|
|
20355
|
+
runner.run("launchctl", ["kill", "SIGTERM", `${domain2()}/${SERVICE_LABEL}`]);
|
|
20356
|
+
return { ok: true, manager: "launchd" };
|
|
20357
|
+
},
|
|
20358
|
+
isRegistered(spec) {
|
|
20359
|
+
return runner.fileExists(launchdPlistPath(specHome(spec)));
|
|
20360
|
+
}
|
|
20361
|
+
};
|
|
20362
|
+
}
|
|
20363
|
+
function systemdController(runner) {
|
|
20364
|
+
const unit = `${SERVICE_LABEL}.service`;
|
|
20365
|
+
return {
|
|
20366
|
+
manager: "systemd-user",
|
|
20367
|
+
register(spec) {
|
|
20368
|
+
const path = systemdUnitPath(specHome(spec));
|
|
20369
|
+
runner.writeFile(path, renderSystemdUnit(spec));
|
|
20370
|
+
runner.run("systemctl", ["--user", "daemon-reload"]);
|
|
20371
|
+
runner.run("systemctl", ["--user", "enable", "--now", unit]);
|
|
20372
|
+
return { ok: true, manager: "systemd-user" };
|
|
20373
|
+
},
|
|
20374
|
+
unregister(spec) {
|
|
20375
|
+
try {
|
|
20376
|
+
runner.run("systemctl", ["--user", "disable", "--now", unit]);
|
|
20377
|
+
} catch {
|
|
20378
|
+
}
|
|
20379
|
+
runner.removeFile(systemdUnitPath(specHome(spec)));
|
|
20380
|
+
try {
|
|
20381
|
+
runner.run("systemctl", ["--user", "daemon-reload"]);
|
|
20382
|
+
} catch {
|
|
20383
|
+
}
|
|
20384
|
+
return { ok: true, manager: "systemd-user" };
|
|
20385
|
+
},
|
|
20386
|
+
restart(_spec) {
|
|
20387
|
+
runner.run("systemctl", ["--user", "restart", unit]);
|
|
20388
|
+
return { ok: true, manager: "systemd-user" };
|
|
20389
|
+
},
|
|
20390
|
+
stop(_spec) {
|
|
20391
|
+
runner.run("systemctl", ["--user", "stop", unit]);
|
|
20392
|
+
return { ok: true, manager: "systemd-user" };
|
|
20393
|
+
},
|
|
20394
|
+
isRegistered(spec) {
|
|
20395
|
+
return runner.fileExists(systemdUnitPath(specHome(spec)));
|
|
20396
|
+
}
|
|
20397
|
+
};
|
|
20398
|
+
}
|
|
20399
|
+
function schtasksController(runner) {
|
|
20400
|
+
return {
|
|
20401
|
+
manager: "schtasks",
|
|
20402
|
+
register(spec) {
|
|
20403
|
+
runner.run("schtasks", buildSchtasksCreateArgs(spec));
|
|
20404
|
+
runner.run("schtasks", ["/Run", "/TN", SERVICE_TASK_NAME]);
|
|
20405
|
+
return { ok: true, manager: "schtasks" };
|
|
20406
|
+
},
|
|
20407
|
+
unregister(_spec) {
|
|
20408
|
+
try {
|
|
20409
|
+
runner.run("schtasks", ["/End", "/TN", SERVICE_TASK_NAME]);
|
|
20410
|
+
} catch {
|
|
20411
|
+
}
|
|
20412
|
+
try {
|
|
20413
|
+
runner.run("schtasks", ["/Delete", "/TN", SERVICE_TASK_NAME, "/F"]);
|
|
20414
|
+
} catch {
|
|
20415
|
+
}
|
|
20416
|
+
return { ok: true, manager: "schtasks" };
|
|
20417
|
+
},
|
|
20418
|
+
restart(spec) {
|
|
20419
|
+
try {
|
|
20420
|
+
runner.run("schtasks", ["/End", "/TN", SERVICE_TASK_NAME]);
|
|
20421
|
+
} catch {
|
|
20422
|
+
}
|
|
20423
|
+
runner.run("schtasks", ["/Run", "/TN", SERVICE_TASK_NAME]);
|
|
20424
|
+
return { ok: true, manager: "schtasks" };
|
|
20425
|
+
},
|
|
20426
|
+
stop(_spec) {
|
|
20427
|
+
runner.run("schtasks", ["/End", "/TN", SERVICE_TASK_NAME]);
|
|
20428
|
+
return { ok: true, manager: "schtasks" };
|
|
20429
|
+
},
|
|
20430
|
+
isRegistered(_spec) {
|
|
20431
|
+
try {
|
|
20432
|
+
runner.run("schtasks", ["/Query", "/TN", SERVICE_TASK_NAME]);
|
|
20433
|
+
return true;
|
|
20434
|
+
} catch {
|
|
20435
|
+
return false;
|
|
20436
|
+
}
|
|
20437
|
+
}
|
|
20438
|
+
};
|
|
20439
|
+
}
|
|
20440
|
+
|
|
20037
20441
|
// dist/src/cli/runtime.js
|
|
20038
20442
|
function daemonBaseUrl2() {
|
|
20039
20443
|
return `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
@@ -20051,19 +20455,38 @@ function tenancyHeaders(creds) {
|
|
|
20051
20455
|
var DAEMON_NODE_FLAGS = ["--experimental-sqlite"];
|
|
20052
20456
|
function resolveDaemonEntry() {
|
|
20053
20457
|
const here = dirname8(fileURLToPath3(import.meta.url));
|
|
20054
|
-
const bundledSibling =
|
|
20055
|
-
const devSibling =
|
|
20458
|
+
const bundledSibling = resolve8(here, "..", "daemon", "index.js");
|
|
20459
|
+
const devSibling = resolve8(here, "..", "..", "..", "daemon", "index.js");
|
|
20056
20460
|
return process.env.HONEYCOMB_DAEMON_ENTRY ?? bundledSibling ?? devSibling;
|
|
20057
20461
|
}
|
|
20058
20462
|
var DEFAULT_START_TIMEOUT_MS = 45e3;
|
|
20059
20463
|
var START_POLL_INTERVAL_MS = 150;
|
|
20060
20464
|
function runtimeDir() {
|
|
20061
|
-
return
|
|
20465
|
+
return join13(homedir13(), ".honeycomb");
|
|
20466
|
+
}
|
|
20467
|
+
function resolveDaemonWorkspace() {
|
|
20468
|
+
const fromEnv = process.env.HONEYCOMB_WORKSPACE;
|
|
20469
|
+
const candidates = [fromEnv !== void 0 && fromEnv.length > 0 ? fromEnv : process.cwd(), runtimeDir()];
|
|
20470
|
+
for (const dir of candidates) {
|
|
20471
|
+
if (canWriteDir(dir))
|
|
20472
|
+
return dir;
|
|
20473
|
+
}
|
|
20474
|
+
return runtimeDir();
|
|
20475
|
+
}
|
|
20476
|
+
function canWriteDir(dir) {
|
|
20477
|
+
try {
|
|
20478
|
+
mkdirSync8(dir, { recursive: true });
|
|
20479
|
+
const probe = mkdtempSync(join13(dir, ".hc-spawn-probe-"));
|
|
20480
|
+
rmSync2(probe, { recursive: true, force: true });
|
|
20481
|
+
return true;
|
|
20482
|
+
} catch {
|
|
20483
|
+
return false;
|
|
20484
|
+
}
|
|
20062
20485
|
}
|
|
20063
20486
|
async function readDaemonPid() {
|
|
20064
20487
|
const { readFile: readFile2 } = await import("node:fs/promises");
|
|
20065
20488
|
try {
|
|
20066
|
-
const raw = (await readFile2(
|
|
20489
|
+
const raw = (await readFile2(join13(runtimeDir(), "daemon.pid"), "utf8")).trim();
|
|
20067
20490
|
const pid = Number.parseInt(raw, 10);
|
|
20068
20491
|
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
20069
20492
|
} catch {
|
|
@@ -20078,44 +20501,128 @@ function isPidAlive(pid) {
|
|
|
20078
20501
|
return err?.code === "EPERM";
|
|
20079
20502
|
}
|
|
20080
20503
|
}
|
|
20081
|
-
function
|
|
20504
|
+
function buildServiceSpec() {
|
|
20505
|
+
return {
|
|
20506
|
+
nodePath: process.execPath,
|
|
20507
|
+
entry: resolveDaemonEntry(),
|
|
20508
|
+
nodeFlags: DAEMON_NODE_FLAGS,
|
|
20509
|
+
workspace: resolveDaemonWorkspace()
|
|
20510
|
+
};
|
|
20511
|
+
}
|
|
20512
|
+
async function spawnDaemonAndWait(client) {
|
|
20513
|
+
const entry = resolveDaemonEntry();
|
|
20514
|
+
const workspace = resolveDaemonWorkspace();
|
|
20515
|
+
const child = spawn(process.execPath, [...DAEMON_NODE_FLAGS, entry], {
|
|
20516
|
+
detached: true,
|
|
20517
|
+
stdio: "ignore",
|
|
20518
|
+
cwd: workspace,
|
|
20519
|
+
env: { ...process.env, HONEYCOMB_WORKSPACE: workspace },
|
|
20520
|
+
// Hide the transient console window on Windows: a detached daemon spawn is never an
|
|
20521
|
+
// interactive terminal the user needs to see.
|
|
20522
|
+
windowsHide: true
|
|
20523
|
+
});
|
|
20524
|
+
child.unref();
|
|
20525
|
+
const deadline = Date.now() + DEFAULT_START_TIMEOUT_MS;
|
|
20526
|
+
while (Date.now() < deadline) {
|
|
20527
|
+
await new Promise((r) => setTimeout(r, START_POLL_INTERVAL_MS));
|
|
20528
|
+
if (await client.ping())
|
|
20529
|
+
return { started: true, alreadyRunning: false };
|
|
20530
|
+
}
|
|
20531
|
+
return { started: false, alreadyRunning: false };
|
|
20532
|
+
}
|
|
20533
|
+
async function waitForHealth(client) {
|
|
20534
|
+
const deadline = Date.now() + DEFAULT_START_TIMEOUT_MS;
|
|
20535
|
+
while (Date.now() < deadline) {
|
|
20536
|
+
if (await client.ping())
|
|
20537
|
+
return true;
|
|
20538
|
+
await new Promise((r) => setTimeout(r, START_POLL_INTERVAL_MS));
|
|
20539
|
+
}
|
|
20540
|
+
return false;
|
|
20541
|
+
}
|
|
20542
|
+
async function signalDaemonStop() {
|
|
20543
|
+
const pid = await readDaemonPid();
|
|
20544
|
+
if (pid === null || !isPidAlive(pid))
|
|
20545
|
+
return false;
|
|
20546
|
+
try {
|
|
20547
|
+
process.kill(pid, "SIGTERM");
|
|
20548
|
+
return true;
|
|
20549
|
+
} catch {
|
|
20550
|
+
return false;
|
|
20551
|
+
}
|
|
20552
|
+
}
|
|
20553
|
+
function buildDaemonLifecycle(client, options = {}) {
|
|
20554
|
+
const manager = options.serviceManager !== void 0 ? options.serviceManager : detectServiceManager();
|
|
20555
|
+
const controllerFor = options.controllerFor ?? ((m) => createDaemonServiceController(m));
|
|
20556
|
+
let controller = null;
|
|
20557
|
+
function serviceController() {
|
|
20558
|
+
if (manager === null)
|
|
20559
|
+
return null;
|
|
20560
|
+
if (controller === null) {
|
|
20561
|
+
try {
|
|
20562
|
+
controller = controllerFor(manager);
|
|
20563
|
+
} catch {
|
|
20564
|
+
return null;
|
|
20565
|
+
}
|
|
20566
|
+
}
|
|
20567
|
+
return controller;
|
|
20568
|
+
}
|
|
20082
20569
|
return {
|
|
20083
20570
|
async start() {
|
|
20084
20571
|
if (await client.ping())
|
|
20085
20572
|
return { started: false, alreadyRunning: true };
|
|
20086
|
-
const
|
|
20087
|
-
|
|
20088
|
-
|
|
20089
|
-
|
|
20090
|
-
|
|
20091
|
-
|
|
20092
|
-
|
|
20093
|
-
|
|
20094
|
-
|
|
20095
|
-
|
|
20096
|
-
|
|
20097
|
-
while (Date.now() < deadline) {
|
|
20098
|
-
await new Promise((r) => setTimeout(r, START_POLL_INTERVAL_MS));
|
|
20099
|
-
if (await client.ping())
|
|
20100
|
-
return { started: true, alreadyRunning: false };
|
|
20101
|
-
}
|
|
20102
|
-
return { started: false, alreadyRunning: false };
|
|
20573
|
+
const svc = serviceController();
|
|
20574
|
+
if (svc !== null) {
|
|
20575
|
+
try {
|
|
20576
|
+
svc.register(buildServiceSpec());
|
|
20577
|
+
if (await waitForHealth(client))
|
|
20578
|
+
return { started: true, alreadyRunning: false };
|
|
20579
|
+
return { started: false, alreadyRunning: false };
|
|
20580
|
+
} catch {
|
|
20581
|
+
}
|
|
20582
|
+
}
|
|
20583
|
+
return spawnDaemonAndWait(client);
|
|
20103
20584
|
},
|
|
20104
20585
|
async stop() {
|
|
20105
|
-
const
|
|
20106
|
-
if (
|
|
20107
|
-
|
|
20108
|
-
|
|
20109
|
-
|
|
20110
|
-
|
|
20111
|
-
|
|
20112
|
-
return { stopped: false };
|
|
20586
|
+
const svc = serviceController();
|
|
20587
|
+
if (svc !== null) {
|
|
20588
|
+
try {
|
|
20589
|
+
svc.stop(buildServiceSpec());
|
|
20590
|
+
return { stopped: true };
|
|
20591
|
+
} catch {
|
|
20592
|
+
}
|
|
20113
20593
|
}
|
|
20594
|
+
return { stopped: await signalDaemonStop() };
|
|
20114
20595
|
},
|
|
20115
20596
|
async status() {
|
|
20116
20597
|
const pid = await readDaemonPid();
|
|
20117
20598
|
const running = pid !== null && isPidAlive(pid);
|
|
20118
|
-
|
|
20599
|
+
const svc = serviceController();
|
|
20600
|
+
let serviceManager;
|
|
20601
|
+
if (svc !== null) {
|
|
20602
|
+
try {
|
|
20603
|
+
if (svc.isRegistered(buildServiceSpec()))
|
|
20604
|
+
serviceManager = svc.manager;
|
|
20605
|
+
} catch {
|
|
20606
|
+
}
|
|
20607
|
+
}
|
|
20608
|
+
if (running) {
|
|
20609
|
+
return serviceManager !== void 0 ? { running, pid, port: DAEMON_PORT, serviceManager } : { running, pid, port: DAEMON_PORT };
|
|
20610
|
+
}
|
|
20611
|
+
return serviceManager !== void 0 ? { running: false, port: DAEMON_PORT, serviceManager } : { running: false, port: DAEMON_PORT };
|
|
20612
|
+
},
|
|
20613
|
+
async restart() {
|
|
20614
|
+
const svc = serviceController();
|
|
20615
|
+
if (svc !== null && svc.isRegistered(buildServiceSpec())) {
|
|
20616
|
+
try {
|
|
20617
|
+
svc.restart(buildServiceSpec());
|
|
20618
|
+
const ok2 = await waitForHealth(client);
|
|
20619
|
+
return { restarted: ok2, viaService: true };
|
|
20620
|
+
} catch {
|
|
20621
|
+
}
|
|
20622
|
+
}
|
|
20623
|
+
await signalDaemonStop();
|
|
20624
|
+
const { started, alreadyRunning } = await spawnDaemonAndWait(client);
|
|
20625
|
+
return { restarted: started || alreadyRunning, viaService: false };
|
|
20119
20626
|
}
|
|
20120
20627
|
};
|
|
20121
20628
|
}
|