modelstat 0.1.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/dist/cli.mjs +231 -124
- package/dist/cli.mjs.map +1 -1
- package/package.json +6 -6
- package/scripts/postinstall.mjs +7 -7
- package/vendor/ModelstatTray.app/Contents/MacOS/modelstat-tray +0 -0
- package/vendor/tray-mac/Package.swift +1 -1
- package/vendor/tray-mac/Sources/ModelstatTray/main.swift +8 -8
package/dist/cli.mjs
CHANGED
|
@@ -137,6 +137,62 @@ var init_git = __esm({
|
|
|
137
137
|
}
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
+
// ../../packages/parsers/src/git-outcome.ts
|
|
141
|
+
import { execFile as execFile2 } from "child_process";
|
|
142
|
+
import { promisify as promisify2 } from "util";
|
|
143
|
+
function parseGitLog(stdout) {
|
|
144
|
+
const out = [];
|
|
145
|
+
for (const record of stdout.split(RS)) {
|
|
146
|
+
const rec = record.trim();
|
|
147
|
+
if (!rec) continue;
|
|
148
|
+
const [sha = "", committedAt = "", subject = "", ...rest] = rec.split(FS);
|
|
149
|
+
out.push({ sha, committedAt, subject, body: rest.join(FS) });
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
function findMergeCommitForPr(commits, prNumber) {
|
|
154
|
+
const re = new RegExp(`(^|\\D)#${prNumber}(\\D|$)`);
|
|
155
|
+
return commits.find((c) => re.test(c.subject)) ?? null;
|
|
156
|
+
}
|
|
157
|
+
function isReverted(commits, mergeSha) {
|
|
158
|
+
if (!mergeSha) return false;
|
|
159
|
+
const short = mergeSha.slice(0, 7);
|
|
160
|
+
return commits.some(
|
|
161
|
+
(c) => c.body.includes(`This reverts commit ${mergeSha}`) || c.body.includes(`This reverts commit ${short}`)
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
function outcomeFromCommits(commits, prNumber) {
|
|
165
|
+
const merge = findMergeCommitForPr(commits, prNumber);
|
|
166
|
+
if (!merge) return { merged: false, merged_at: null, reverted: false };
|
|
167
|
+
return {
|
|
168
|
+
merged: true,
|
|
169
|
+
merged_at: merge.committedAt || null,
|
|
170
|
+
reverted: isReverted(commits, merge.sha)
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
async function checkPullRequestOutcome(cwd, prNumber) {
|
|
174
|
+
try {
|
|
175
|
+
const { stdout } = await pexec2("git", ["log", "-n", "1000", `--format=${GIT_LOG_FORMAT}`], {
|
|
176
|
+
cwd,
|
|
177
|
+
timeout: 4e3,
|
|
178
|
+
maxBuffer: 16 * 1024 * 1024
|
|
179
|
+
});
|
|
180
|
+
return outcomeFromCommits(parseGitLog(stdout), prNumber);
|
|
181
|
+
} catch {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
var pexec2, FS, RS, GIT_LOG_FORMAT;
|
|
186
|
+
var init_git_outcome = __esm({
|
|
187
|
+
"../../packages/parsers/src/git-outcome.ts"() {
|
|
188
|
+
"use strict";
|
|
189
|
+
pexec2 = promisify2(execFile2);
|
|
190
|
+
FS = "";
|
|
191
|
+
RS = "";
|
|
192
|
+
GIT_LOG_FORMAT = `%H${FS}%cI${FS}%s${FS}%b${RS}`;
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
140
196
|
// ../../packages/core/src/billing.ts
|
|
141
197
|
var MILLION, FREE_INCLUDED_TOKENS, TEAM_INCLUDED_PER_SEAT;
|
|
142
198
|
var init_billing = __esm({
|
|
@@ -149,7 +205,7 @@ var init_billing = __esm({
|
|
|
149
205
|
});
|
|
150
206
|
|
|
151
207
|
// ../../packages/core/src/enums.ts
|
|
152
|
-
var AGENTS, PROVIDERS, IDENTITY_OWNER_SCOPES, INSTALL_METHODS, OS_FAMILIES, EVENT_KINDS, TOOL_CALL_STATUSES,
|
|
208
|
+
var AGENTS, PROVIDERS, IDENTITY_OWNER_SCOPES, INSTALL_METHODS, OS_FAMILIES, EVENT_KINDS, TOOL_CALL_STATUSES, DAEMON_PHASES, CLASSIFICATION_CONFIDENCE;
|
|
153
209
|
var init_enums = __esm({
|
|
154
210
|
"../../packages/core/src/enums.ts"() {
|
|
155
211
|
"use strict";
|
|
@@ -181,7 +237,7 @@ var init_enums = __esm({
|
|
|
181
237
|
"raw_sdk_anthropic",
|
|
182
238
|
"raw_sdk_openai",
|
|
183
239
|
"raw_sdk_google",
|
|
184
|
-
// Web chat UIs (Chrome-extension
|
|
240
|
+
// Web chat UIs (Chrome-extension daemon). Categorically distinct
|
|
185
241
|
// from *_cli / *_desktop agents — same provider, different surface.
|
|
186
242
|
"chatgpt_web",
|
|
187
243
|
"claude_web",
|
|
@@ -241,7 +297,7 @@ var init_enums = __esm({
|
|
|
241
297
|
"timeout",
|
|
242
298
|
"unknown"
|
|
243
299
|
];
|
|
244
|
-
|
|
300
|
+
DAEMON_PHASES = [
|
|
245
301
|
"starting",
|
|
246
302
|
"discovering",
|
|
247
303
|
"idle",
|
|
@@ -4540,7 +4596,7 @@ var init_redact_floor = __esm({
|
|
|
4540
4596
|
pattern: /(?:sk|pk|rk)_test_[A-Za-z0-9]{24,}/g,
|
|
4541
4597
|
replacement: "<REDACTED:stripe_test_key>"
|
|
4542
4598
|
},
|
|
4543
|
-
// Discord bot token (was
|
|
4599
|
+
// Discord bot token (was caught by only one redactor — the canonical drift example).
|
|
4544
4600
|
{
|
|
4545
4601
|
name: "discord_token",
|
|
4546
4602
|
pattern: /[MN][A-Za-z\d]{23}\.[\w-]{6}\.[\w-]{27}/g,
|
|
@@ -4938,7 +4994,16 @@ var init_session_metadata = __esm({
|
|
|
4938
4994
|
number: external_exports.number().int().positive(),
|
|
4939
4995
|
url: external_exports.string().max(400).nullable().default(null),
|
|
4940
4996
|
source: RefSource.default("content"),
|
|
4941
|
-
confidence: external_exports.number().min(0).max(1).default(0.9)
|
|
4997
|
+
confidence: external_exports.number().min(0).max(1).default(0.9),
|
|
4998
|
+
// On-device verified-outcome signals — filled by the parsers' local git-check
|
|
4999
|
+
// (`checkPullRequestOutcome`) when the PR's repo is on disk. `null` = unknown;
|
|
5000
|
+
// the server's CPVO engine classifies verified/failed from these. Mirrors
|
|
5001
|
+
// core's `PullRequestRef` field-for-field.
|
|
5002
|
+
merged: external_exports.boolean().nullable().optional(),
|
|
5003
|
+
merged_at: external_exports.string().max(40).nullable().optional(),
|
|
5004
|
+
reverted: external_exports.boolean().nullable().optional(),
|
|
5005
|
+
hotfixed: external_exports.boolean().nullable().optional(),
|
|
5006
|
+
reopened: external_exports.boolean().nullable().optional()
|
|
4942
5007
|
});
|
|
4943
5008
|
CommitRef = external_exports.object({
|
|
4944
5009
|
/** 7–40 char hex SHA. */
|
|
@@ -5045,7 +5110,7 @@ var init_schemas = __esm({
|
|
|
5045
5110
|
// available, the on-device Privacy Filter adapter.
|
|
5046
5111
|
// 3. Stripping code blocks and file-path noise.
|
|
5047
5112
|
// Optional — events without it fall back to metadata-only abstracts
|
|
5048
|
-
// (the historical behaviour). The
|
|
5113
|
+
// (the historical behaviour). The daemon-core pipeline runs
|
|
5049
5114
|
// redact() over it again as defence-in-depth before building the
|
|
5050
5115
|
// summarize prompt; it never gets stored long-term server-side, only
|
|
5051
5116
|
// used to construct the summarize input.
|
|
@@ -5076,7 +5141,7 @@ var init_schemas = __esm({
|
|
|
5076
5141
|
root_key: external_exports.string().max(60),
|
|
5077
5142
|
name: external_exports.string().max(120),
|
|
5078
5143
|
confidence: external_exports.number().min(0).max(1).default(0.7),
|
|
5079
|
-
/** Optional free-text reason the
|
|
5144
|
+
/** Optional free-text reason the daemon attached this tag — surfaces
|
|
5080
5145
|
* in the audit log so the user can see "why was this tagged X?" */
|
|
5081
5146
|
reason: external_exports.string().max(200).optional()
|
|
5082
5147
|
});
|
|
@@ -5099,7 +5164,7 @@ var init_schemas = __esm({
|
|
|
5099
5164
|
/** `source_event_id`s covered by this segment. Used for dedupe + replay. */
|
|
5100
5165
|
source_event_ids: external_exports.array(external_exports.string()).max(2e3),
|
|
5101
5166
|
/** Optional embedding of the abstract (BGE-small-en-v1.5, 384 dims).
|
|
5102
|
-
* Present when the
|
|
5167
|
+
* Present when the daemon has an Embedder adapter configured. */
|
|
5103
5168
|
abstract_embedding: external_exports.array(external_exports.number()).length(384).optional()
|
|
5104
5169
|
});
|
|
5105
5170
|
ToolAction = external_exports.object({
|
|
@@ -5115,7 +5180,7 @@ var init_schemas = __esm({
|
|
|
5115
5180
|
qualifiers: external_exports.array(external_exports.string().max(40)).max(8).default([]),
|
|
5116
5181
|
/** Value-masked argument skeleton (every value → `§`). Carried in full up
|
|
5117
5182
|
* to a malicious-size guard (mirrors backend `MAX_TOOL_ACTION_PARAM_SHAPE_CHARS`);
|
|
5118
|
-
* the
|
|
5183
|
+
* the daemon clamps rather than truncating semantically. (tier 1) */
|
|
5119
5184
|
param_shape: external_exports.string().max(16384).nullable().default(null),
|
|
5120
5185
|
/** Relevant non-sensitive keywords (e.g. ["rollout","restart","prod"]),
|
|
5121
5186
|
* OpenAI-redacted on-device. (tier 0) */
|
|
@@ -5147,7 +5212,7 @@ var init_schemas = __esm({
|
|
|
5147
5212
|
session_id: external_exports.string().max(120),
|
|
5148
5213
|
/** The RawEvent that contained the tool_use (dedupe/replay anchor). */
|
|
5149
5214
|
source_event_id: external_exports.string(),
|
|
5150
|
-
/** Segment containing source_event_id — filled by the
|
|
5215
|
+
/** Segment containing source_event_id — filled by the daemon at
|
|
5151
5216
|
* batch-build time when known, else null. */
|
|
5152
5217
|
segment_id: external_exports.string().max(64).nullable().default(null),
|
|
5153
5218
|
/** The agent that made the call (AGENTS enum). */
|
|
@@ -5185,7 +5250,7 @@ var init_schemas = __esm({
|
|
|
5185
5250
|
batch_id: external_exports.string(),
|
|
5186
5251
|
// ULID
|
|
5187
5252
|
device_id: external_exports.string(),
|
|
5188
|
-
|
|
5253
|
+
daemon_version: external_exports.string().max(40),
|
|
5189
5254
|
events: external_exports.array(RawEvent).max(1e4),
|
|
5190
5255
|
segments: external_exports.array(Segment).max(2e3).default([]),
|
|
5191
5256
|
/** Per-call tool invocations (additive — old agents omit it, old
|
|
@@ -5201,8 +5266,8 @@ var init_schemas = __esm({
|
|
|
5201
5266
|
})
|
|
5202
5267
|
).optional(),
|
|
5203
5268
|
/** Optional per-session titles — session_id → short redacted title
|
|
5204
|
-
* (≤120 chars) produced by the
|
|
5205
|
-
* session's segment abstracts.
|
|
5269
|
+
* (≤120 chars) produced by the daemon's local titler from the
|
|
5270
|
+
* session's segment abstracts. Daemons recompute it from the full
|
|
5206
5271
|
* session view on every upload, so the latest batch always carries the
|
|
5207
5272
|
* freshest title. Absent for runtimes without a titler (older agents,
|
|
5208
5273
|
* no-op browser summariser). */
|
|
@@ -5211,20 +5276,20 @@ var init_schemas = __esm({
|
|
|
5211
5276
|
* {@link SessionMetadata}: the repos, pull requests, commits, and issues the
|
|
5212
5277
|
* session touched, detected on-device across git context, tool calls,
|
|
5213
5278
|
* redacted content, and the local model (so it works for any provider).
|
|
5214
|
-
* Additive — old
|
|
5279
|
+
* Additive — old daemons omit it, old servers ignore it (the wire has no
|
|
5215
5280
|
* `deny_unknown_fields`). The join layer between AI spend and shipped work. */
|
|
5216
5281
|
session_metadata: external_exports.record(external_exports.string(), SessionMetadata).optional()
|
|
5217
5282
|
});
|
|
5218
5283
|
HeartbeatPayload = external_exports.object({
|
|
5219
5284
|
device_id: external_exports.string(),
|
|
5220
|
-
status: external_exports.enum(
|
|
5285
|
+
status: external_exports.enum(DAEMON_PHASES),
|
|
5221
5286
|
message: external_exports.string().max(240).nullable(),
|
|
5222
5287
|
progress_done: external_exports.number().int().nonnegative().default(0),
|
|
5223
5288
|
progress_total: external_exports.number().int().nonnegative().default(0),
|
|
5224
5289
|
queue_size: external_exports.number().int().nonnegative().default(0),
|
|
5225
5290
|
stats: external_exports.record(external_exports.string(), external_exports.unknown()).default({}),
|
|
5226
5291
|
last_event_at: external_exports.string().datetime({ offset: true }).nullable(),
|
|
5227
|
-
|
|
5292
|
+
daemon_version: external_exports.string().max(40)
|
|
5228
5293
|
});
|
|
5229
5294
|
DeviceEnrollment = external_exports.object({
|
|
5230
5295
|
machine_id: external_exports.string(),
|
|
@@ -5233,10 +5298,10 @@ var init_schemas = __esm({
|
|
|
5233
5298
|
os_family: external_exports.enum(OS_FAMILIES),
|
|
5234
5299
|
os_version: external_exports.string().max(60),
|
|
5235
5300
|
arch: external_exports.enum(["x86_64", "arm64", "other"]),
|
|
5236
|
-
|
|
5301
|
+
daemon_version: external_exports.string().max(40)
|
|
5237
5302
|
});
|
|
5238
5303
|
DeviceSelfRegister = external_exports.object({
|
|
5239
|
-
/**
|
|
5304
|
+
/** Daemon-generated UUIDv7 — must pass shape + recent-timestamp checks. */
|
|
5240
5305
|
device_uuid: external_exports.string(),
|
|
5241
5306
|
/** Base64-encoded ed25519 public key, exactly 32 raw bytes. Optional
|
|
5242
5307
|
* but recommended (used for sender-constrained tokens / DPoP later). */
|
|
@@ -5249,8 +5314,8 @@ var init_schemas = __esm({
|
|
|
5249
5314
|
os_family: external_exports.enum(OS_FAMILIES).optional(),
|
|
5250
5315
|
os_version: external_exports.string().max(60).optional(),
|
|
5251
5316
|
arch: external_exports.enum(["x86_64", "arm64", "other"]).optional(),
|
|
5252
|
-
|
|
5253
|
-
|
|
5317
|
+
daemon: external_exports.string().max(80).optional(),
|
|
5318
|
+
daemon_version: external_exports.string().max(40).optional()
|
|
5254
5319
|
// Allow extra fields for forward-compat without breaking old agents.
|
|
5255
5320
|
}).catchall(external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()])).default({})
|
|
5256
5321
|
});
|
|
@@ -8367,11 +8432,11 @@ var init_cursor = __esm({
|
|
|
8367
8432
|
});
|
|
8368
8433
|
|
|
8369
8434
|
// ../../packages/parsers/src/discovery/index.ts
|
|
8370
|
-
import { execFile as
|
|
8435
|
+
import { execFile as execFile3, execSync } from "child_process";
|
|
8371
8436
|
import { existsSync as existsSync3, statSync } from "fs";
|
|
8372
8437
|
import { homedir, platform } from "os";
|
|
8373
8438
|
import { join as join2, resolve as resolve2 } from "path";
|
|
8374
|
-
import { promisify as
|
|
8439
|
+
import { promisify as promisify3 } from "util";
|
|
8375
8440
|
async function discover(options = {}) {
|
|
8376
8441
|
const os2 = platform() === "darwin" ? "macos" : "linux";
|
|
8377
8442
|
const skip = new Set(options.skip ?? []);
|
|
@@ -8496,7 +8561,7 @@ function classifyInstallMethod(binPath, os2) {
|
|
|
8496
8561
|
}
|
|
8497
8562
|
async function safeVersionProbe(binPath) {
|
|
8498
8563
|
try {
|
|
8499
|
-
const { stdout } = await
|
|
8564
|
+
const { stdout } = await pexec3(binPath, ["--version"], { timeout: 1500 });
|
|
8500
8565
|
return stdout.trim().split(/\s+/).pop() ?? null;
|
|
8501
8566
|
} catch {
|
|
8502
8567
|
return null;
|
|
@@ -8701,11 +8766,11 @@ function dedupeIdentities(list) {
|
|
|
8701
8766
|
}
|
|
8702
8767
|
return Array.from(seen.values());
|
|
8703
8768
|
}
|
|
8704
|
-
var
|
|
8769
|
+
var pexec3, H, SOURCES;
|
|
8705
8770
|
var init_discovery = __esm({
|
|
8706
8771
|
"../../packages/parsers/src/discovery/index.ts"() {
|
|
8707
8772
|
"use strict";
|
|
8708
|
-
|
|
8773
|
+
pexec3 = promisify3(execFile3);
|
|
8709
8774
|
H = (p) => p.startsWith("~") ? p.replace("~", homedir()) : p;
|
|
8710
8775
|
SOURCES = [
|
|
8711
8776
|
{
|
|
@@ -8797,6 +8862,7 @@ var init_src2 = __esm({
|
|
|
8797
8862
|
"use strict";
|
|
8798
8863
|
init_types();
|
|
8799
8864
|
init_git();
|
|
8865
|
+
init_git_outcome();
|
|
8800
8866
|
init_tool_action();
|
|
8801
8867
|
init_claude_code();
|
|
8802
8868
|
init_codex();
|
|
@@ -21668,7 +21734,7 @@ var require_mock_interceptor = __commonJS({
|
|
|
21668
21734
|
var require_mock_client = __commonJS({
|
|
21669
21735
|
"../../node_modules/.pnpm/undici@7.25.0/node_modules/undici/lib/mock/mock-client.js"(exports, module) {
|
|
21670
21736
|
"use strict";
|
|
21671
|
-
var { promisify:
|
|
21737
|
+
var { promisify: promisify5 } = __require("util");
|
|
21672
21738
|
var Client = require_client();
|
|
21673
21739
|
var { buildMockDispatch } = require_mock_utils();
|
|
21674
21740
|
var {
|
|
@@ -21716,7 +21782,7 @@ var require_mock_client = __commonJS({
|
|
|
21716
21782
|
this[kDispatches] = [];
|
|
21717
21783
|
}
|
|
21718
21784
|
async [kClose]() {
|
|
21719
|
-
await
|
|
21785
|
+
await promisify5(this[kOriginalClose])();
|
|
21720
21786
|
this[kConnected] = 0;
|
|
21721
21787
|
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
|
21722
21788
|
}
|
|
@@ -21929,7 +21995,7 @@ var require_mock_call_history = __commonJS({
|
|
|
21929
21995
|
var require_mock_pool = __commonJS({
|
|
21930
21996
|
"../../node_modules/.pnpm/undici@7.25.0/node_modules/undici/lib/mock/mock-pool.js"(exports, module) {
|
|
21931
21997
|
"use strict";
|
|
21932
|
-
var { promisify:
|
|
21998
|
+
var { promisify: promisify5 } = __require("util");
|
|
21933
21999
|
var Pool = require_pool();
|
|
21934
22000
|
var { buildMockDispatch } = require_mock_utils();
|
|
21935
22001
|
var {
|
|
@@ -21977,7 +22043,7 @@ var require_mock_pool = __commonJS({
|
|
|
21977
22043
|
this[kDispatches] = [];
|
|
21978
22044
|
}
|
|
21979
22045
|
async [kClose]() {
|
|
21980
|
-
await
|
|
22046
|
+
await promisify5(this[kOriginalClose])();
|
|
21981
22047
|
this[kConnected] = 0;
|
|
21982
22048
|
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
|
21983
22049
|
}
|
|
@@ -33608,14 +33674,14 @@ ${captureLines}` : capture.stack;
|
|
|
33608
33674
|
}
|
|
33609
33675
|
});
|
|
33610
33676
|
|
|
33611
|
-
// ../../packages/
|
|
33677
|
+
// ../../packages/daemon-core/src/config/index.ts
|
|
33612
33678
|
function expBackoff(attempt) {
|
|
33613
33679
|
const i = Math.min(Math.max(attempt, 0), BACKOFF_MS.length - 1);
|
|
33614
33680
|
return BACKOFF_MS[i];
|
|
33615
33681
|
}
|
|
33616
33682
|
var INGEST_BATCH_MAX_EVENTS, BACKOFF_MS, BACKSTOP_SCAN_MS;
|
|
33617
33683
|
var init_config = __esm({
|
|
33618
|
-
"../../packages/
|
|
33684
|
+
"../../packages/daemon-core/src/config/index.ts"() {
|
|
33619
33685
|
"use strict";
|
|
33620
33686
|
INGEST_BATCH_MAX_EVENTS = 1e3;
|
|
33621
33687
|
BACKOFF_MS = [1e3, 2500, 5e3, 1e4, 2e4, 6e4];
|
|
@@ -33623,7 +33689,7 @@ var init_config = __esm({
|
|
|
33623
33689
|
}
|
|
33624
33690
|
});
|
|
33625
33691
|
|
|
33626
|
-
// ../../packages/
|
|
33692
|
+
// ../../packages/daemon-core/src/logger.ts
|
|
33627
33693
|
function defaultLevel() {
|
|
33628
33694
|
const env2 = globalThis.process?.env ?? {};
|
|
33629
33695
|
const raw = (env2.LOG_LEVEL ?? "").toLowerCase();
|
|
@@ -33676,7 +33742,7 @@ function describeErrorWithCause(err, depth = 4) {
|
|
|
33676
33742
|
}
|
|
33677
33743
|
var LEVEL_RANK;
|
|
33678
33744
|
var init_logger = __esm({
|
|
33679
|
-
"../../packages/
|
|
33745
|
+
"../../packages/daemon-core/src/logger.ts"() {
|
|
33680
33746
|
"use strict";
|
|
33681
33747
|
LEVEL_RANK = {
|
|
33682
33748
|
debug: 10,
|
|
@@ -33687,7 +33753,7 @@ var init_logger = __esm({
|
|
|
33687
33753
|
}
|
|
33688
33754
|
});
|
|
33689
33755
|
|
|
33690
|
-
// ../../packages/
|
|
33756
|
+
// ../../packages/daemon-core/src/http/index.ts
|
|
33691
33757
|
function classifyStatus(status2, attempt) {
|
|
33692
33758
|
if (status2 >= 200 && status2 < 300) return { type: "commit" };
|
|
33693
33759
|
if (status2 === 400 || status2 === 422) return { type: "drop", reason: `http_${status2}` };
|
|
@@ -33707,7 +33773,7 @@ function sleep(ms) {
|
|
|
33707
33773
|
}
|
|
33708
33774
|
var IngestClient;
|
|
33709
33775
|
var init_http = __esm({
|
|
33710
|
-
"../../packages/
|
|
33776
|
+
"../../packages/daemon-core/src/http/index.ts"() {
|
|
33711
33777
|
"use strict";
|
|
33712
33778
|
init_config();
|
|
33713
33779
|
init_logger();
|
|
@@ -34612,25 +34678,25 @@ var init_constants2 = __esm({
|
|
|
34612
34678
|
|
|
34613
34679
|
// ../../node_modules/.pnpm/stubborn-fs@2.0.0/node_modules/stubborn-fs/dist/index.js
|
|
34614
34680
|
import fs from "fs";
|
|
34615
|
-
import { promisify as
|
|
34616
|
-
var
|
|
34681
|
+
import { promisify as promisify4 } from "util";
|
|
34682
|
+
var FS2, dist_default;
|
|
34617
34683
|
var init_dist2 = __esm({
|
|
34618
34684
|
"../../node_modules/.pnpm/stubborn-fs@2.0.0/node_modules/stubborn-fs/dist/index.js"() {
|
|
34619
34685
|
"use strict";
|
|
34620
34686
|
init_dist();
|
|
34621
34687
|
init_dist();
|
|
34622
34688
|
init_constants2();
|
|
34623
|
-
|
|
34689
|
+
FS2 = {
|
|
34624
34690
|
attempt: {
|
|
34625
34691
|
/* ASYNC */
|
|
34626
|
-
chmod: attemptify_async_default(
|
|
34627
|
-
chown: attemptify_async_default(
|
|
34628
|
-
close: attemptify_async_default(
|
|
34629
|
-
fsync: attemptify_async_default(
|
|
34630
|
-
mkdir: attemptify_async_default(
|
|
34631
|
-
realpath: attemptify_async_default(
|
|
34632
|
-
stat: attemptify_async_default(
|
|
34633
|
-
unlink: attemptify_async_default(
|
|
34692
|
+
chmod: attemptify_async_default(promisify4(fs.chmod), ATTEMPTIFY_CHANGE_ERROR_OPTIONS),
|
|
34693
|
+
chown: attemptify_async_default(promisify4(fs.chown), ATTEMPTIFY_CHANGE_ERROR_OPTIONS),
|
|
34694
|
+
close: attemptify_async_default(promisify4(fs.close), ATTEMPTIFY_NOOP_OPTIONS),
|
|
34695
|
+
fsync: attemptify_async_default(promisify4(fs.fsync), ATTEMPTIFY_NOOP_OPTIONS),
|
|
34696
|
+
mkdir: attemptify_async_default(promisify4(fs.mkdir), ATTEMPTIFY_NOOP_OPTIONS),
|
|
34697
|
+
realpath: attemptify_async_default(promisify4(fs.realpath), ATTEMPTIFY_NOOP_OPTIONS),
|
|
34698
|
+
stat: attemptify_async_default(promisify4(fs.stat), ATTEMPTIFY_NOOP_OPTIONS),
|
|
34699
|
+
unlink: attemptify_async_default(promisify4(fs.unlink), ATTEMPTIFY_NOOP_OPTIONS),
|
|
34634
34700
|
/* SYNC */
|
|
34635
34701
|
chmodSync: attemptify_sync_default(fs.chmodSync, ATTEMPTIFY_CHANGE_ERROR_OPTIONS),
|
|
34636
34702
|
chownSync: attemptify_sync_default(fs.chownSync, ATTEMPTIFY_CHANGE_ERROR_OPTIONS),
|
|
@@ -34644,14 +34710,14 @@ var init_dist2 = __esm({
|
|
|
34644
34710
|
},
|
|
34645
34711
|
retry: {
|
|
34646
34712
|
/* ASYNC */
|
|
34647
|
-
close: retryify_async_default(
|
|
34648
|
-
fsync: retryify_async_default(
|
|
34649
|
-
open: retryify_async_default(
|
|
34650
|
-
readFile: retryify_async_default(
|
|
34651
|
-
rename: retryify_async_default(
|
|
34652
|
-
stat: retryify_async_default(
|
|
34653
|
-
write: retryify_async_default(
|
|
34654
|
-
writeFile: retryify_async_default(
|
|
34713
|
+
close: retryify_async_default(promisify4(fs.close), RETRYIFY_OPTIONS),
|
|
34714
|
+
fsync: retryify_async_default(promisify4(fs.fsync), RETRYIFY_OPTIONS),
|
|
34715
|
+
open: retryify_async_default(promisify4(fs.open), RETRYIFY_OPTIONS),
|
|
34716
|
+
readFile: retryify_async_default(promisify4(fs.readFile), RETRYIFY_OPTIONS),
|
|
34717
|
+
rename: retryify_async_default(promisify4(fs.rename), RETRYIFY_OPTIONS),
|
|
34718
|
+
stat: retryify_async_default(promisify4(fs.stat), RETRYIFY_OPTIONS),
|
|
34719
|
+
write: retryify_async_default(promisify4(fs.write), RETRYIFY_OPTIONS),
|
|
34720
|
+
writeFile: retryify_async_default(promisify4(fs.writeFile), RETRYIFY_OPTIONS),
|
|
34655
34721
|
/* SYNC */
|
|
34656
34722
|
closeSync: retryify_sync_default(fs.closeSync, RETRYIFY_OPTIONS),
|
|
34657
34723
|
fsyncSync: retryify_sync_default(fs.fsyncSync, RETRYIFY_OPTIONS),
|
|
@@ -34663,7 +34729,7 @@ var init_dist2 = __esm({
|
|
|
34663
34729
|
writeFileSync: retryify_sync_default(fs.writeFileSync, RETRYIFY_OPTIONS)
|
|
34664
34730
|
}
|
|
34665
34731
|
};
|
|
34666
|
-
dist_default =
|
|
34732
|
+
dist_default = FS2;
|
|
34667
34733
|
}
|
|
34668
34734
|
});
|
|
34669
34735
|
|
|
@@ -45249,7 +45315,7 @@ var init_config2 = __esm({
|
|
|
45249
45315
|
DEFAULT_API_URL = "https://modelstat.ai";
|
|
45250
45316
|
LEGACY_LOCALHOST_API = "http://localhost:3010";
|
|
45251
45317
|
store = new Conf({
|
|
45252
|
-
projectName: "modelstat-
|
|
45318
|
+
projectName: "modelstat-daemon",
|
|
45253
45319
|
defaults: {
|
|
45254
45320
|
// Intentionally empty — the apiUrl getter below computes this
|
|
45255
45321
|
// from env + stored value + DEFAULT_API_URL. Keeping the stored
|
|
@@ -45281,7 +45347,7 @@ var init_config2 = __esm({
|
|
|
45281
45347
|
* or paired pre-0.0.8) → production default. The legacy localhost
|
|
45282
45348
|
* value is ignored so upgrades from 0.0.7 self-heal. */
|
|
45283
45349
|
get apiUrl() {
|
|
45284
|
-
if (process.env.
|
|
45350
|
+
if (process.env.DAEMON_API_URL) return process.env.DAEMON_API_URL;
|
|
45285
45351
|
const stored = store.get("apiUrl");
|
|
45286
45352
|
if (stored && stored !== LEGACY_LOCALHOST_API) return stored;
|
|
45287
45353
|
return DEFAULT_API_URL;
|
|
@@ -45289,6 +45355,16 @@ var init_config2 = __esm({
|
|
|
45289
45355
|
setApiUrl(v) {
|
|
45290
45356
|
store.set("apiUrl", v);
|
|
45291
45357
|
},
|
|
45358
|
+
/** True when `apiUrl` resolves to the baked-in production default with no
|
|
45359
|
+
* explicit override (no `DAEMON_API_URL`, no operator-set stored URL). Used
|
|
45360
|
+
* to refuse silent prod self-register from CI/non-interactive environments
|
|
45361
|
+
* so ephemeral runners don't pile up unclaimed device rows. */
|
|
45362
|
+
get isProdDefaultApi() {
|
|
45363
|
+
if (process.env.DAEMON_API_URL) return false;
|
|
45364
|
+
const stored = store.get("apiUrl");
|
|
45365
|
+
if (stored && stored !== LEGACY_LOCALHOST_API) return false;
|
|
45366
|
+
return true;
|
|
45367
|
+
},
|
|
45292
45368
|
// ── Identity: backed by ~/.modelstat/identity.json ─────────────
|
|
45293
45369
|
/** Seed a fresh identity after a successful self-register. Writes
|
|
45294
45370
|
* the file atomically; use `state.backupAndReset()` first if
|
|
@@ -45427,7 +45503,7 @@ async function rotateDeviceSecret(currentSecret) {
|
|
|
45427
45503
|
}
|
|
45428
45504
|
async function reportDiscovery(report) {
|
|
45429
45505
|
const bearer = state.bearer;
|
|
45430
|
-
if (!bearer) throw new Error("
|
|
45506
|
+
if (!bearer) throw new Error("daemon not enrolled \u2014 run `register` first");
|
|
45431
45507
|
const res = await (0, import_undici.request)(`${state.apiUrl}/v1/devices/discovery`, {
|
|
45432
45508
|
method: "POST",
|
|
45433
45509
|
headers: { "content-type": "application/json", authorization: `Bearer ${bearer}` },
|
|
@@ -45472,7 +45548,7 @@ async function fetchDeviceViewLedgerByClaim(claimCode) {
|
|
|
45472
45548
|
}
|
|
45473
45549
|
function ingestClient() {
|
|
45474
45550
|
if (_ingest) return _ingest;
|
|
45475
|
-
const logger = createLogger("
|
|
45551
|
+
const logger = createLogger("daemon.ingest");
|
|
45476
45552
|
_ingest = new IngestClient({
|
|
45477
45553
|
apiUrl: state.apiUrl,
|
|
45478
45554
|
auth: {
|
|
@@ -45632,24 +45708,24 @@ var init_machine_key = __esm({
|
|
|
45632
45708
|
}
|
|
45633
45709
|
});
|
|
45634
45710
|
|
|
45635
|
-
// ../../packages/
|
|
45711
|
+
// ../../packages/daemon-core/src/contracts/index.ts
|
|
45636
45712
|
var init_contracts = __esm({
|
|
45637
|
-
"../../packages/
|
|
45713
|
+
"../../packages/daemon-core/src/contracts/index.ts"() {
|
|
45638
45714
|
"use strict";
|
|
45639
45715
|
init_schemas();
|
|
45640
45716
|
init_enums();
|
|
45641
45717
|
}
|
|
45642
45718
|
});
|
|
45643
45719
|
|
|
45644
|
-
// ../../packages/
|
|
45720
|
+
// ../../packages/daemon-core/src/ids.ts
|
|
45645
45721
|
var init_ids2 = __esm({
|
|
45646
|
-
"../../packages/
|
|
45722
|
+
"../../packages/daemon-core/src/ids.ts"() {
|
|
45647
45723
|
"use strict";
|
|
45648
45724
|
init_ids();
|
|
45649
45725
|
}
|
|
45650
45726
|
});
|
|
45651
45727
|
|
|
45652
|
-
// ../../packages/
|
|
45728
|
+
// ../../packages/daemon-core/src/queue/index.ts
|
|
45653
45729
|
function attachSegmentIdsByMap(calls, segmentByEvent) {
|
|
45654
45730
|
return calls.map((c) => ({
|
|
45655
45731
|
...c,
|
|
@@ -45657,14 +45733,14 @@ function attachSegmentIdsByMap(calls, segmentByEvent) {
|
|
|
45657
45733
|
}));
|
|
45658
45734
|
}
|
|
45659
45735
|
var init_queue = __esm({
|
|
45660
|
-
"../../packages/
|
|
45736
|
+
"../../packages/daemon-core/src/queue/index.ts"() {
|
|
45661
45737
|
"use strict";
|
|
45662
45738
|
init_config();
|
|
45663
45739
|
init_ids2();
|
|
45664
45740
|
}
|
|
45665
45741
|
});
|
|
45666
45742
|
|
|
45667
|
-
// ../../packages/
|
|
45743
|
+
// ../../packages/daemon-core/src/pipeline/cognition.ts
|
|
45668
45744
|
function buildCognitionUserPrompt(abstract) {
|
|
45669
45745
|
return `Summary: "${abstract.replace(/\s+/g, " ").trim().slice(0, 480)}"
|
|
45670
45746
|
|
|
@@ -45736,7 +45812,7 @@ function extractFirstJsonObject(s) {
|
|
|
45736
45812
|
}
|
|
45737
45813
|
var COGNITION_SYSTEM_PROMPT, MAX_COGNITION_TAGS_PER_FIELD, MAX_COGNITION_TAG_CHARS, COGNITION_MAX_TOKENS, COGNITION_TEMPERATURE;
|
|
45738
45814
|
var init_cognition = __esm({
|
|
45739
|
-
"../../packages/
|
|
45815
|
+
"../../packages/daemon-core/src/pipeline/cognition.ts"() {
|
|
45740
45816
|
"use strict";
|
|
45741
45817
|
COGNITION_SYSTEM_PROMPT = 'You read a one-sentence summary of an AI-coding work session and identify the user\'s emotional state and meta-cognitive state. Output JSON only \u2014 first character of reply is `{`. Schema: {"emotions":[],"meta":[]}. emotions: \u2264 3 short lowercase MOOD tags \u2014 how the user FEELS \u2014 such as frustrated, curious, excited, calm, confused, anxious, satisfied, proud, bored, energised, overwhelmed, confident. meta: \u2264 3 short lowercase MENTAL-MODE tags \u2014 HOW the user is THINKING, never what they are doing. Valid examples: focused, scattered, in-flow, deliberate, hurried, stuck, open, exploratory, methodical, distracted. DO NOT emit ACTIVITY verbs (debugging, refactoring, designing, reviewing, deploying, planning, documenting, implementing) under meta \u2014 those describe the WORK, not the MIND. If the only candidate tag would be an activity verb, return [] for meta instead. Each tag \u2264 24 chars, single word or hyphenated, no punctuation. Only emit a tag if the summary gives clear evidence \u2014 return [] for either field when unsure. Do not invent emotions or mental modes the user did not display. No prose, no markdown.';
|
|
45742
45818
|
MAX_COGNITION_TAGS_PER_FIELD = 3;
|
|
@@ -45746,10 +45822,10 @@ var init_cognition = __esm({
|
|
|
45746
45822
|
}
|
|
45747
45823
|
});
|
|
45748
45824
|
|
|
45749
|
-
// ../../packages/
|
|
45825
|
+
// ../../packages/daemon-core/src/pipeline/prompts.ts
|
|
45750
45826
|
var OLLAMA_CHAT_MODEL, OLLAMA_EMBED_MODEL, SUMMARISER_SYSTEM_PROMPT, SUMMARISER_MAX_TOKENS, SUMMARISER_TEMPERATURE, QWEN_CHARS_PER_TOKEN, ABSTRACT_OUTPUT_MAX_CHARS;
|
|
45751
45827
|
var init_prompts = __esm({
|
|
45752
|
-
"../../packages/
|
|
45828
|
+
"../../packages/daemon-core/src/pipeline/prompts.ts"() {
|
|
45753
45829
|
"use strict";
|
|
45754
45830
|
OLLAMA_CHAT_MODEL = "qwen3:4b";
|
|
45755
45831
|
OLLAMA_EMBED_MODEL = "bge-small-en-v1.5";
|
|
@@ -45761,7 +45837,7 @@ var init_prompts = __esm({
|
|
|
45761
45837
|
}
|
|
45762
45838
|
});
|
|
45763
45839
|
|
|
45764
|
-
// ../../packages/
|
|
45840
|
+
// ../../packages/daemon-core/src/pipeline/script-summary.ts
|
|
45765
45841
|
function buildScriptSummaryUserPrompt(input) {
|
|
45766
45842
|
const body = input.content.slice(0, SCRIPT_SUMMARY_INPUT_MAX_CHARS);
|
|
45767
45843
|
return [
|
|
@@ -45776,7 +45852,7 @@ function buildScriptSummaryUserPrompt(input) {
|
|
|
45776
45852
|
}
|
|
45777
45853
|
var SCRIPT_SUMMARY_OUTPUT_MAX_CHARS, SCRIPT_SUMMARY_TEMPERATURE, SCRIPT_SUMMARY_MAX_TOKENS, SCRIPT_SUMMARY_INPUT_MAX_CHARS, SCRIPT_SUMMARY_SYSTEM_PROMPT;
|
|
45778
45854
|
var init_script_summary = __esm({
|
|
45779
|
-
"../../packages/
|
|
45855
|
+
"../../packages/daemon-core/src/pipeline/script-summary.ts"() {
|
|
45780
45856
|
"use strict";
|
|
45781
45857
|
SCRIPT_SUMMARY_OUTPUT_MAX_CHARS = 200;
|
|
45782
45858
|
SCRIPT_SUMMARY_TEMPERATURE = 0.2;
|
|
@@ -45793,7 +45869,7 @@ Rules:
|
|
|
45793
45869
|
}
|
|
45794
45870
|
});
|
|
45795
45871
|
|
|
45796
|
-
// ../../packages/
|
|
45872
|
+
// ../../packages/daemon-core/src/pipeline/title.ts
|
|
45797
45873
|
function buildTitleUserPrompt(input) {
|
|
45798
45874
|
const lines = input.abstracts.map(
|
|
45799
45875
|
(a, i) => ` [part ${i + 1}] ${a.replace(/\s+/g, " ").trim().slice(0, TITLER_ABSTRACT_SLICE_CHARS)}`
|
|
@@ -45864,7 +45940,7 @@ async function buildSessionTitles(segments, entitle) {
|
|
|
45864
45940
|
}
|
|
45865
45941
|
var TITLER_SYSTEM_PROMPT, TITLE_MAX_CHARS, TITLER_MAX_TOKENS, TITLER_TEMPERATURE, TITLER_MAX_ABSTRACTS, TITLER_ABSTRACT_SLICE_CHARS;
|
|
45866
45942
|
var init_title = __esm({
|
|
45867
|
-
"../../packages/
|
|
45943
|
+
"../../packages/daemon-core/src/pipeline/title.ts"() {
|
|
45868
45944
|
"use strict";
|
|
45869
45945
|
init_redact();
|
|
45870
45946
|
TITLER_SYSTEM_PROMPT = "You write a short TITLE for an AI coding session, given one-sentence summaries of its parts in chronological order. The title names what the session was about at a high level, in 3-8 words. If the session clearly spans more than one theme, name the top themes (at most 3) separated by ' \xB7 '. Use concrete domain keywords (features, components, subsystems). No narration, no filler words like 'session' or 'work on', no quotes, no trailing period, no PII, no code literals, no file paths. Reply with only the title.";
|
|
@@ -45876,7 +45952,7 @@ var init_title = __esm({
|
|
|
45876
45952
|
}
|
|
45877
45953
|
});
|
|
45878
45954
|
|
|
45879
|
-
// ../../packages/
|
|
45955
|
+
// ../../packages/daemon-core/src/pipeline/session-metadata.ts
|
|
45880
45956
|
function buildLinkExtractUserPrompt(abstracts) {
|
|
45881
45957
|
const lines = abstracts.map((a, i) => ` [part ${i + 1}] ${a.replace(/\s+/g, " ").trim().slice(0, 240)}`).join("\n");
|
|
45882
45958
|
return `Summaries of the session's parts:
|
|
@@ -45904,6 +45980,7 @@ async function buildSessionMetadata(segments, events, opts = {}) {
|
|
|
45904
45980
|
const evs = eventsBySession.get(sessionId) ?? [];
|
|
45905
45981
|
const segs = segsBySession.get(sessionId) ?? [];
|
|
45906
45982
|
const parts = [];
|
|
45983
|
+
const slugToCwd = /* @__PURE__ */ new Map();
|
|
45907
45984
|
const cwds = /* @__PURE__ */ new Set();
|
|
45908
45985
|
for (const e of evs) {
|
|
45909
45986
|
if (e.cwd) cwds.add(e.cwd);
|
|
@@ -45938,6 +46015,7 @@ async function buildSessionMetadata(segments, events, opts = {}) {
|
|
|
45938
46015
|
g = null;
|
|
45939
46016
|
}
|
|
45940
46017
|
if (!g?.remote_slug) continue;
|
|
46018
|
+
slugToCwd.set(g.remote_slug.toLowerCase(), cwd);
|
|
45941
46019
|
const refs = emptyDetectedRefs();
|
|
45942
46020
|
refs.repos.push({
|
|
45943
46021
|
host: g.remote_host ?? null,
|
|
@@ -45967,6 +46045,21 @@ async function buildSessionMetadata(segments, events, opts = {}) {
|
|
|
45967
46045
|
}
|
|
45968
46046
|
}
|
|
45969
46047
|
const meta = dedupeSessionMetadata(parts);
|
|
46048
|
+
if (opts.checkPrOutcome && meta.pull_requests.length > 0) {
|
|
46049
|
+
for (const pr of meta.pull_requests) {
|
|
46050
|
+
const cwd = pr.slug ? slugToCwd.get(pr.slug.toLowerCase()) : void 0;
|
|
46051
|
+
if (!cwd) continue;
|
|
46052
|
+
try {
|
|
46053
|
+
const o = await opts.checkPrOutcome(cwd, pr.number);
|
|
46054
|
+
if (o) {
|
|
46055
|
+
pr.merged = o.merged;
|
|
46056
|
+
pr.merged_at = o.merged_at;
|
|
46057
|
+
pr.reverted = o.reverted;
|
|
46058
|
+
}
|
|
46059
|
+
} catch {
|
|
46060
|
+
}
|
|
46061
|
+
}
|
|
46062
|
+
}
|
|
45970
46063
|
if (!isEmptySessionMetadata(meta)) out[sessionId] = meta;
|
|
45971
46064
|
} catch {
|
|
45972
46065
|
}
|
|
@@ -45975,7 +46068,7 @@ async function buildSessionMetadata(segments, events, opts = {}) {
|
|
|
45975
46068
|
}
|
|
45976
46069
|
var LINK_EXTRACT_SYSTEM_PROMPT, LINK_EXTRACT_MAX_TOKENS, LINK_EXTRACT_TEMPERATURE, LINK_EXTRACT_MAX_ABSTRACTS;
|
|
45977
46070
|
var init_session_metadata2 = __esm({
|
|
45978
|
-
"../../packages/
|
|
46071
|
+
"../../packages/daemon-core/src/pipeline/session-metadata.ts"() {
|
|
45979
46072
|
"use strict";
|
|
45980
46073
|
init_session_metadata();
|
|
45981
46074
|
init_title();
|
|
@@ -45986,7 +46079,7 @@ var init_session_metadata2 = __esm({
|
|
|
45986
46079
|
}
|
|
45987
46080
|
});
|
|
45988
46081
|
|
|
45989
|
-
// ../../packages/
|
|
46082
|
+
// ../../packages/daemon-core/src/pipeline/index.ts
|
|
45990
46083
|
async function buildSegmentsForSession(events, adapters2, onProgress) {
|
|
45991
46084
|
if (events.length === 0) return [];
|
|
45992
46085
|
const bySession = /* @__PURE__ */ new Map();
|
|
@@ -46288,7 +46381,7 @@ function inferEnvironment(branch) {
|
|
|
46288
46381
|
}
|
|
46289
46382
|
var SEGMENT_TIME_GAP_MS, SEGMENT_TOPIC_THRESHOLD, SEGMENT_MAX_TURNS, SEGMENT_MAX_DURATION_MS, SEGMENT_MAX_CONTENT_CHARS, ABSTRACT_MAX_CHARS;
|
|
46290
46383
|
var init_pipeline = __esm({
|
|
46291
|
-
"../../packages/
|
|
46384
|
+
"../../packages/daemon-core/src/pipeline/index.ts"() {
|
|
46292
46385
|
"use strict";
|
|
46293
46386
|
init_ids();
|
|
46294
46387
|
init_redact();
|
|
@@ -46309,9 +46402,9 @@ var init_pipeline = __esm({
|
|
|
46309
46402
|
}
|
|
46310
46403
|
});
|
|
46311
46404
|
|
|
46312
|
-
// ../../packages/
|
|
46405
|
+
// ../../packages/daemon-core/src/index.ts
|
|
46313
46406
|
var init_src3 = __esm({
|
|
46314
|
-
"../../packages/
|
|
46407
|
+
"../../packages/daemon-core/src/index.ts"() {
|
|
46315
46408
|
"use strict";
|
|
46316
46409
|
init_contracts();
|
|
46317
46410
|
init_ids2();
|
|
@@ -46323,12 +46416,12 @@ var init_src3 = __esm({
|
|
|
46323
46416
|
}
|
|
46324
46417
|
});
|
|
46325
46418
|
|
|
46326
|
-
// ../../packages/
|
|
46419
|
+
// ../../packages/daemon-core/src/node/file-queue-store.ts
|
|
46327
46420
|
import { promises as fs3 } from "fs";
|
|
46328
46421
|
import { dirname as dirname4 } from "path";
|
|
46329
46422
|
var SENT_TTL_MS, FileQueueStore;
|
|
46330
46423
|
var init_file_queue_store = __esm({
|
|
46331
|
-
"../../packages/
|
|
46424
|
+
"../../packages/daemon-core/src/node/file-queue-store.ts"() {
|
|
46332
46425
|
"use strict";
|
|
46333
46426
|
SENT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
46334
46427
|
FileQueueStore = class {
|
|
@@ -46446,7 +46539,7 @@ var init_file_queue_store = __esm({
|
|
|
46446
46539
|
}
|
|
46447
46540
|
});
|
|
46448
46541
|
|
|
46449
|
-
// ../../packages/
|
|
46542
|
+
// ../../packages/daemon-core/src/node/llama.ts
|
|
46450
46543
|
import { existsSync as existsSync7 } from "fs";
|
|
46451
46544
|
import { mkdir } from "fs/promises";
|
|
46452
46545
|
import { homedir as homedir5 } from "os";
|
|
@@ -46742,7 +46835,7 @@ function llamaExtractLinks(cfg = defaultLlamaConfig()) {
|
|
|
46742
46835
|
}
|
|
46743
46836
|
var DEFAULT_LLAMA_MODEL_URL, LLAMA_MAX_TOKENS, loaded, loadPromise, inflight, llamaInstance;
|
|
46744
46837
|
var init_llama = __esm({
|
|
46745
|
-
"../../packages/
|
|
46838
|
+
"../../packages/daemon-core/src/node/llama.ts"() {
|
|
46746
46839
|
"use strict";
|
|
46747
46840
|
init_cognition();
|
|
46748
46841
|
init_prompts();
|
|
@@ -46758,7 +46851,7 @@ var init_llama = __esm({
|
|
|
46758
46851
|
}
|
|
46759
46852
|
});
|
|
46760
46853
|
|
|
46761
|
-
// ../../packages/
|
|
46854
|
+
// ../../packages/daemon-core/src/node/ollama.ts
|
|
46762
46855
|
function defaultOllamaConfig() {
|
|
46763
46856
|
const base = globalThis.process?.env ?? {};
|
|
46764
46857
|
return {
|
|
@@ -46861,14 +46954,14 @@ function ollamaCognize(cfg = defaultOllamaConfig()) {
|
|
|
46861
46954
|
};
|
|
46862
46955
|
}
|
|
46863
46956
|
var init_ollama = __esm({
|
|
46864
|
-
"../../packages/
|
|
46957
|
+
"../../packages/daemon-core/src/node/ollama.ts"() {
|
|
46865
46958
|
"use strict";
|
|
46866
46959
|
init_prompts();
|
|
46867
46960
|
init_cognition();
|
|
46868
46961
|
}
|
|
46869
46962
|
});
|
|
46870
46963
|
|
|
46871
|
-
// ../../packages/
|
|
46964
|
+
// ../../packages/daemon-core/src/optional-module.ts
|
|
46872
46965
|
function isMissingOptionalModuleError(err) {
|
|
46873
46966
|
const code = err?.code;
|
|
46874
46967
|
if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") return true;
|
|
@@ -46877,13 +46970,13 @@ function isMissingOptionalModuleError(err) {
|
|
|
46877
46970
|
}
|
|
46878
46971
|
var OPTIONAL_MODULE_MAX_LOAD_ATTEMPTS;
|
|
46879
46972
|
var init_optional_module = __esm({
|
|
46880
|
-
"../../packages/
|
|
46973
|
+
"../../packages/daemon-core/src/optional-module.ts"() {
|
|
46881
46974
|
"use strict";
|
|
46882
46975
|
OPTIONAL_MODULE_MAX_LOAD_ATTEMPTS = 3;
|
|
46883
46976
|
}
|
|
46884
46977
|
});
|
|
46885
46978
|
|
|
46886
|
-
// ../../packages/
|
|
46979
|
+
// ../../packages/daemon-core/src/node/transformersjs-embed.ts
|
|
46887
46980
|
async function loadPipeline(model) {
|
|
46888
46981
|
if (cached) return cached;
|
|
46889
46982
|
if (loadFailedPermanently) return null;
|
|
@@ -46937,7 +47030,7 @@ function createTransformersJsEmbedder(model = DEFAULT_MODEL) {
|
|
|
46937
47030
|
}
|
|
46938
47031
|
var cached, loadPromise2, loadFailedPermanently, loadAttempts, warnedUnavailable, warnedInferenceError, DEFAULT_MODEL, importModule;
|
|
46939
47032
|
var init_transformersjs_embed = __esm({
|
|
46940
|
-
"../../packages/
|
|
47033
|
+
"../../packages/daemon-core/src/node/transformersjs-embed.ts"() {
|
|
46941
47034
|
"use strict";
|
|
46942
47035
|
init_optional_module();
|
|
46943
47036
|
cached = null;
|
|
@@ -46954,7 +47047,7 @@ var init_transformersjs_embed = __esm({
|
|
|
46954
47047
|
}
|
|
46955
47048
|
});
|
|
46956
47049
|
|
|
46957
|
-
// ../../packages/
|
|
47050
|
+
// ../../packages/daemon-core/src/node/index.ts
|
|
46958
47051
|
var node_exports = {};
|
|
46959
47052
|
__export(node_exports, {
|
|
46960
47053
|
DEFAULT_LLAMA_MODEL_URL: () => DEFAULT_LLAMA_MODEL_URL,
|
|
@@ -46976,7 +47069,7 @@ __export(node_exports, {
|
|
|
46976
47069
|
ollamaTokenize: () => ollamaTokenize
|
|
46977
47070
|
});
|
|
46978
47071
|
var init_node2 = __esm({
|
|
46979
|
-
"../../packages/
|
|
47072
|
+
"../../packages/daemon-core/src/node/index.ts"() {
|
|
46980
47073
|
"use strict";
|
|
46981
47074
|
init_file_queue_store();
|
|
46982
47075
|
init_llama();
|
|
@@ -46985,7 +47078,7 @@ var init_node2 = __esm({
|
|
|
46985
47078
|
}
|
|
46986
47079
|
});
|
|
46987
47080
|
|
|
46988
|
-
// ../../packages/
|
|
47081
|
+
// ../../packages/daemon-core/src/redact/privacy-filter.ts
|
|
46989
47082
|
async function createPrivacyFilterRedactor(opts = {}) {
|
|
46990
47083
|
const isBrowser = typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined";
|
|
46991
47084
|
const device = opts.device ?? (isBrowser ? "webgpu" : "cpu");
|
|
@@ -47091,7 +47184,7 @@ async function createPrivacyFilterRedactor(opts = {}) {
|
|
|
47091
47184
|
};
|
|
47092
47185
|
}
|
|
47093
47186
|
var init_privacy_filter = __esm({
|
|
47094
|
-
"../../packages/
|
|
47187
|
+
"../../packages/daemon-core/src/redact/privacy-filter.ts"() {
|
|
47095
47188
|
"use strict";
|
|
47096
47189
|
init_optional_module();
|
|
47097
47190
|
}
|
|
@@ -47217,7 +47310,7 @@ async function getAdapters() {
|
|
|
47217
47310
|
await import("node-llama-cpp");
|
|
47218
47311
|
} catch (err) {
|
|
47219
47312
|
throw new Error(
|
|
47220
|
-
`modelstat
|
|
47313
|
+
`modelstat daemon can't start: the bundled summariser (node-llama-cpp) failed to load. Re-run \`modelstat connect\` (or \`npm i -g modelstat\`) so the native runtime is re-staged beside the bundle. Underlying error: ${err.message}`
|
|
47221
47314
|
);
|
|
47222
47315
|
}
|
|
47223
47316
|
console.log("[modelstat] using bundled local summariser (Qwen3.5-4B, runs on this machine)");
|
|
@@ -47235,7 +47328,8 @@ async function buildSessionMetadata2(segments, events) {
|
|
|
47235
47328
|
const a = await getAdapters();
|
|
47236
47329
|
return buildSessionMetadata(segments, events, {
|
|
47237
47330
|
resolveGit: resolveGitContext,
|
|
47238
|
-
extractLinks: a.extractLinks
|
|
47331
|
+
extractLinks: a.extractLinks,
|
|
47332
|
+
checkPrOutcome: checkPullRequestOutcome
|
|
47239
47333
|
});
|
|
47240
47334
|
}
|
|
47241
47335
|
async function enrichScripts(drafts, contexts = []) {
|
|
@@ -47288,7 +47382,7 @@ function withNonNullTokens(e) {
|
|
|
47288
47382
|
}
|
|
47289
47383
|
async function scanAll(cb = {}) {
|
|
47290
47384
|
const deviceId = state.deviceId;
|
|
47291
|
-
if (!deviceId) throw new Error("
|
|
47385
|
+
if (!deviceId) throw new Error("daemon not enrolled \u2014 run `register` first");
|
|
47292
47386
|
const jobs = [];
|
|
47293
47387
|
try {
|
|
47294
47388
|
const base = join6(homedir6(), ".claude/projects");
|
|
@@ -47393,7 +47487,7 @@ async function scanAll(cb = {}) {
|
|
|
47393
47487
|
const batch = {
|
|
47394
47488
|
batch_id: batchId(),
|
|
47395
47489
|
device_id: deviceId,
|
|
47396
|
-
|
|
47490
|
+
daemon_version: DAEMON_VERSION,
|
|
47397
47491
|
events,
|
|
47398
47492
|
segments,
|
|
47399
47493
|
tool_calls: attachSegmentIdsByMap(toolCallBuffer, callSegmentByEvent),
|
|
@@ -47468,7 +47562,7 @@ async function scanAll(cb = {}) {
|
|
|
47468
47562
|
morePending
|
|
47469
47563
|
};
|
|
47470
47564
|
}
|
|
47471
|
-
var
|
|
47565
|
+
var DAEMON_VERSION, BATCH_MAX_EVENTS, BATCH_MAX_TOOL_CALLS, BATCH_BUFFER_HARD_CAP, ZERO_TOKENS;
|
|
47472
47566
|
var init_scan = __esm({
|
|
47473
47567
|
"src/scan.ts"() {
|
|
47474
47568
|
"use strict";
|
|
@@ -47479,7 +47573,7 @@ var init_scan = __esm({
|
|
|
47479
47573
|
init_api();
|
|
47480
47574
|
init_config2();
|
|
47481
47575
|
init_pipeline2();
|
|
47482
|
-
|
|
47576
|
+
DAEMON_VERSION = true ? "daemon-0.3.0" : "daemon-dev";
|
|
47483
47577
|
BATCH_MAX_EVENTS = INGEST_BATCH_MAX_EVENTS;
|
|
47484
47578
|
BATCH_MAX_TOOL_CALLS = 2e4;
|
|
47485
47579
|
BATCH_BUFFER_HARD_CAP = BATCH_MAX_EVENTS * 2;
|
|
@@ -47526,7 +47620,7 @@ function readDaemonLock(lockFile = LOCK_FILE) {
|
|
|
47526
47620
|
return {
|
|
47527
47621
|
pid: obj.pid,
|
|
47528
47622
|
startedAt: obj.startedAt ?? "unknown",
|
|
47529
|
-
|
|
47623
|
+
daemonVersion: obj.daemonVersion ?? "unknown",
|
|
47530
47624
|
apiUrl: obj.apiUrl ?? "unknown"
|
|
47531
47625
|
};
|
|
47532
47626
|
} catch {
|
|
@@ -47568,7 +47662,7 @@ function acquireDaemonLock(opts) {
|
|
|
47568
47662
|
const meta = {
|
|
47569
47663
|
pid: process.pid,
|
|
47570
47664
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
47571
|
-
|
|
47665
|
+
daemonVersion: opts.daemonVersion,
|
|
47572
47666
|
apiUrl: opts.apiUrl
|
|
47573
47667
|
};
|
|
47574
47668
|
writeLockAtomic(meta);
|
|
@@ -47886,7 +47980,7 @@ var init_node3 = __esm({
|
|
|
47886
47980
|
}
|
|
47887
47981
|
});
|
|
47888
47982
|
|
|
47889
|
-
// ../../packages/
|
|
47983
|
+
// ../../packages/daemon-core/src/policies/index.ts
|
|
47890
47984
|
var policies_exports = {};
|
|
47891
47985
|
__export(policies_exports, {
|
|
47892
47986
|
createPolicyRefresher: () => createPolicyRefresher
|
|
@@ -47930,7 +48024,7 @@ function createPolicyRefresher(opts) {
|
|
|
47930
48024
|
}
|
|
47931
48025
|
var DEFAULT_REFRESH_MS, policiesKind;
|
|
47932
48026
|
var init_policies2 = __esm({
|
|
47933
|
-
"../../packages/
|
|
48027
|
+
"../../packages/daemon-core/src/policies/index.ts"() {
|
|
47934
48028
|
"use strict";
|
|
47935
48029
|
init_src();
|
|
47936
48030
|
init_src4();
|
|
@@ -49710,7 +49804,7 @@ function snapshotBody() {
|
|
|
49710
49804
|
queue_size: status.queueSize,
|
|
49711
49805
|
stats: status.stats,
|
|
49712
49806
|
last_event_at: status.lastEventAt,
|
|
49713
|
-
|
|
49807
|
+
daemon_version: DAEMON_VERSION2,
|
|
49714
49808
|
machine_id: machineKey()
|
|
49715
49809
|
};
|
|
49716
49810
|
}
|
|
@@ -49735,7 +49829,7 @@ async function sendHeartbeat() {
|
|
|
49735
49829
|
if (!bearer || !deviceId) return;
|
|
49736
49830
|
const body = { ...snapshotBody(), device_id: deviceId };
|
|
49737
49831
|
try {
|
|
49738
|
-
const res = await (0, import_undici2.request)(`${state.apiUrl}/v1/
|
|
49832
|
+
const res = await (0, import_undici2.request)(`${state.apiUrl}/v1/daemon/heartbeat`, {
|
|
49739
49833
|
method: "POST",
|
|
49740
49834
|
headers: { "content-type": "application/json", authorization: `Bearer ${bearer}` },
|
|
49741
49835
|
body: JSON.stringify(body)
|
|
@@ -49866,7 +49960,7 @@ async function runDaemon(opts = {}) {
|
|
|
49866
49960
|
throw new Error("not enrolled \u2014 run `npx modelstat@latest` first");
|
|
49867
49961
|
}
|
|
49868
49962
|
const lock = acquireDaemonLock({
|
|
49869
|
-
|
|
49963
|
+
daemonVersion: DAEMON_VERSION2,
|
|
49870
49964
|
apiUrl: state.apiUrl,
|
|
49871
49965
|
force: opts.force === true,
|
|
49872
49966
|
// If a racing daemon out-renamed us for the lock (see lock.ts
|
|
@@ -49884,7 +49978,7 @@ async function runDaemon(opts = {}) {
|
|
|
49884
49978
|
console.log(
|
|
49885
49979
|
`modelstat daemon is already running \u2014 PID ${lock.owner.pid}, started ${formatAge(
|
|
49886
49980
|
lock.ageSec
|
|
49887
|
-
)} ago,
|
|
49981
|
+
)} ago, daemon ${lock.owner.daemonVersion}.`
|
|
49888
49982
|
);
|
|
49889
49983
|
console.log(" \u2192 to stop it: kill " + lock.owner.pid);
|
|
49890
49984
|
console.log(" \u2192 to force-replace it: modelstat start --force");
|
|
@@ -49976,7 +50070,7 @@ async function runDaemon(opts = {}) {
|
|
|
49976
50070
|
await new Promise(() => {
|
|
49977
50071
|
});
|
|
49978
50072
|
}
|
|
49979
|
-
var import_undici2,
|
|
50073
|
+
var import_undici2, DAEMON_VERSION2, HEARTBEAT_INTERVAL_MS, SCAN_INTERVAL_MS, DISCOVERY_INTERVAL_MS, status, LOCAL_FLUSH_THROTTLE_MS, localFlushTimer, localFlushPending, LOG_MAX_BYTES, LOG_TAIL_KEEP_BYTES, lastStatusPath, scanRunner;
|
|
49980
50074
|
var init_daemon = __esm({
|
|
49981
50075
|
"src/daemon.ts"() {
|
|
49982
50076
|
"use strict";
|
|
@@ -49989,7 +50083,7 @@ var init_daemon = __esm({
|
|
|
49989
50083
|
init_machine_key();
|
|
49990
50084
|
init_scan();
|
|
49991
50085
|
init_single_flight();
|
|
49992
|
-
|
|
50086
|
+
DAEMON_VERSION2 = true ? "daemon-0.3.0" : "daemon-dev";
|
|
49993
50087
|
HEARTBEAT_INTERVAL_MS = 1e4;
|
|
49994
50088
|
SCAN_INTERVAL_MS = 5 * 60 * 1e3;
|
|
49995
50089
|
DISCOVERY_INTERVAL_MS = 6e4;
|
|
@@ -50134,7 +50228,7 @@ import { createRequire } from "module";
|
|
|
50134
50228
|
import { homedir as homedir7, platform as platform3, userInfo } from "os";
|
|
50135
50229
|
import { dirname as dirname6, join as join7 } from "path";
|
|
50136
50230
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
50137
|
-
var SERVICE_LABEL = "ai.modelstat.
|
|
50231
|
+
var SERVICE_LABEL = "ai.modelstat.daemon";
|
|
50138
50232
|
var SYSTEMD_UNIT = "modelstat";
|
|
50139
50233
|
function home() {
|
|
50140
50234
|
return homedir7();
|
|
@@ -50341,7 +50435,7 @@ function writeSystemdUnit(cliPath) {
|
|
|
50341
50435
|
const unitPath = systemdUnitPath();
|
|
50342
50436
|
mkdirSync3(dirname6(unitPath), { recursive: true });
|
|
50343
50437
|
const unit = `[Unit]
|
|
50344
|
-
Description=modelstat
|
|
50438
|
+
Description=modelstat daemon
|
|
50345
50439
|
Documentation=https://modelstat.ai
|
|
50346
50440
|
After=network-online.target
|
|
50347
50441
|
Wants=network-online.target
|
|
@@ -50408,7 +50502,7 @@ function installService() {
|
|
|
50408
50502
|
return { path: systemdUnitPath(), logs: logDir() };
|
|
50409
50503
|
}
|
|
50410
50504
|
throw new Error(
|
|
50411
|
-
`Service installation isn't supported on ${p}. Run 'modelstat start' manually to keep the
|
|
50505
|
+
`Service installation isn't supported on ${p}. Run 'modelstat start' manually to keep the daemon running.`
|
|
50412
50506
|
);
|
|
50413
50507
|
}
|
|
50414
50508
|
function uninstallService() {
|
|
@@ -50445,7 +50539,7 @@ async function bundledTrayAppPath(progress) {
|
|
|
50445
50539
|
const candidates = [
|
|
50446
50540
|
// Pre-built .app — CI with codesigning drops one here.
|
|
50447
50541
|
join7(here2, "..", "vendor", "ModelstatTray.app"),
|
|
50448
|
-
// Local dev layout: apps/
|
|
50542
|
+
// Local dev layout: apps/daemon/src/service.ts → ../../tray-mac/build/ModelstatTray.app
|
|
50449
50543
|
join7(here2, "..", "..", "tray-mac", "build", "ModelstatTray.app")
|
|
50450
50544
|
];
|
|
50451
50545
|
for (const c of candidates) {
|
|
@@ -50519,7 +50613,7 @@ function decideSupervision(input) {
|
|
|
50519
50613
|
const fresh = input.statusFreshMs ?? STATUS_FRESH_MS;
|
|
50520
50614
|
const grace = input.bootGraceMs ?? BOOT_GRACE_MS;
|
|
50521
50615
|
if (!input.lock || !input.ownerAlive) return "spawn";
|
|
50522
|
-
if (input.
|
|
50616
|
+
if (input.myDaemonVersion && input.lock.daemonVersion !== "unknown" && input.lock.daemonVersion !== input.myDaemonVersion) {
|
|
50523
50617
|
return "replace";
|
|
50524
50618
|
}
|
|
50525
50619
|
if (input.statusAgeMs !== null && input.statusAgeMs <= fresh) return "adopt";
|
|
@@ -50547,7 +50641,7 @@ function daemonHealth(opts = {}) {
|
|
|
50547
50641
|
ownerAlive,
|
|
50548
50642
|
lockAgeMs,
|
|
50549
50643
|
statusAgeMs,
|
|
50550
|
-
|
|
50644
|
+
myDaemonVersion: opts.myDaemonVersion
|
|
50551
50645
|
}),
|
|
50552
50646
|
lock,
|
|
50553
50647
|
ownerAlive,
|
|
@@ -50591,7 +50685,7 @@ function tryOpenBrowser(url) {
|
|
|
50591
50685
|
return false;
|
|
50592
50686
|
}
|
|
50593
50687
|
}
|
|
50594
|
-
var
|
|
50688
|
+
var DAEMON_VERSION3 = true ? "daemon-0.3.0" : "daemon-dev";
|
|
50595
50689
|
function osFamily() {
|
|
50596
50690
|
const p = platform5();
|
|
50597
50691
|
if (p === "darwin") return "macos";
|
|
@@ -50609,17 +50703,30 @@ function intendedDeviceUuid() {
|
|
|
50609
50703
|
const key = salt ? `${machineKey()}:${salt}` : machineKey();
|
|
50610
50704
|
return deviceUuidFromMachineKey(key);
|
|
50611
50705
|
}
|
|
50706
|
+
function isNonInteractive() {
|
|
50707
|
+
return Boolean(process.env.CI) || process.stdin.isTTY !== true;
|
|
50708
|
+
}
|
|
50709
|
+
function prodRegisterOptIn() {
|
|
50710
|
+
const v = process.env.MODELSTAT_ALLOW_PROD_REGISTER?.trim().toLowerCase();
|
|
50711
|
+
return v === "1" || v === "true" || v === "yes";
|
|
50712
|
+
}
|
|
50612
50713
|
async function cmdSelfRegister() {
|
|
50613
50714
|
const deviceUuid = state.deviceUuid ?? intendedDeviceUuid();
|
|
50614
50715
|
const derived = !state.deviceUuid;
|
|
50716
|
+
if (derived && state.isProdDefaultApi && isNonInteractive() && !prodRegisterOptIn()) {
|
|
50717
|
+
process.stderr.write(
|
|
50718
|
+
"modelstat: refusing to self-register a new device against production from a\nnon-interactive/CI environment (no claim is possible here anyway). Either:\n \u2022 point at your own backend: DAEMON_API_URL=https://your-host (CI/e2e)\n \u2022 explicitly opt in: MODELSTAT_ALLOW_PROD_REGISTER=1\n \u2022 or run it interactively: npx modelstat@latest\n"
|
|
50719
|
+
);
|
|
50720
|
+
process.exit(2);
|
|
50721
|
+
}
|
|
50615
50722
|
const mid = machineKey();
|
|
50616
50723
|
const fingerprint = {
|
|
50617
50724
|
hostname: hostname2(),
|
|
50618
50725
|
os_family: osFamily(),
|
|
50619
50726
|
os_version: release(),
|
|
50620
50727
|
arch: osArch(),
|
|
50621
|
-
|
|
50622
|
-
|
|
50728
|
+
daemon: "modelstat-daemon",
|
|
50729
|
+
daemon_version: DAEMON_VERSION3,
|
|
50623
50730
|
// Stable, install-method-independent machine key. The server
|
|
50624
50731
|
// dedupes self-register on this so the same physical machine can
|
|
50625
50732
|
// never become two device rows, even if the UUID somehow differs
|
|
@@ -50845,7 +50952,7 @@ async function cmdConnect(opts) {
|
|
|
50845
50952
|
warn(`couldn't prepare summariser model: ${e.message}`);
|
|
50846
50953
|
warn("the background service will retry the download on its first scan");
|
|
50847
50954
|
}
|
|
50848
|
-
step("Installing/refreshing background service so the
|
|
50955
|
+
step("Installing/refreshing background service so the daemon survives reboots");
|
|
50849
50956
|
let serviceOk = false;
|
|
50850
50957
|
try {
|
|
50851
50958
|
const svc = installService();
|
|
@@ -50859,7 +50966,7 @@ async function cmdConnect(opts) {
|
|
|
50859
50966
|
} catch (e) {
|
|
50860
50967
|
emitEvent(opts, "service_install_failed", { error: e.message });
|
|
50861
50968
|
warn(`couldn't install service: ${e.message}`);
|
|
50862
|
-
warn("the
|
|
50969
|
+
warn("the daemon will not run in the background \u2014 re-run after fixing the issue");
|
|
50863
50970
|
}
|
|
50864
50971
|
step("Detecting installed AI tools and signed-in accounts");
|
|
50865
50972
|
let discovered = null;
|
|
@@ -51081,7 +51188,7 @@ async function cmdStats(args) {
|
|
|
51081
51188
|
console.log(` ${dashboard}`);
|
|
51082
51189
|
if (local) {
|
|
51083
51190
|
console.log(
|
|
51084
|
-
`local
|
|
51191
|
+
`local daemon: ${local.status ?? "?"}${local.message ? ` \xB7 ${local.message}` : ""}`
|
|
51085
51192
|
);
|
|
51086
51193
|
const stats = local.stats ?? {};
|
|
51087
51194
|
for (const [k, v] of Object.entries(stats)) console.log(` ${k}: ${v}`);
|
|
@@ -51096,9 +51203,9 @@ async function cmdStats(args) {
|
|
|
51096
51203
|
}
|
|
51097
51204
|
console.log(`device: ${view.device.id}`);
|
|
51098
51205
|
console.log(`host: ${view.device.hostname ?? "(unknown)"} (${view.device.os_family ?? "?"})`);
|
|
51099
|
-
console.log(`
|
|
51206
|
+
console.log(`daemon: ${view.device.daemon_version ?? "(unknown)"}`);
|
|
51100
51207
|
console.log(
|
|
51101
|
-
`status: ${view.device.
|
|
51208
|
+
`status: ${view.device.daemon_status ?? "(unknown)"}${view.device.last_seen_at ? ` \xB7 last seen ${view.device.last_seen_at}` : ""}`
|
|
51102
51209
|
);
|
|
51103
51210
|
console.log(
|
|
51104
51211
|
`claim: ${view.status}${view.status === "unclaimed" ? ` (at ${view.claim_url})` : ""}`
|
|
@@ -51226,7 +51333,7 @@ async function main() {
|
|
|
51226
51333
|
}
|
|
51227
51334
|
case "_daemon-health": {
|
|
51228
51335
|
try {
|
|
51229
|
-
console.log(JSON.stringify(daemonHealth({
|
|
51336
|
+
console.log(JSON.stringify(daemonHealth({ myDaemonVersion: DAEMON_VERSION3 })));
|
|
51230
51337
|
} catch (e) {
|
|
51231
51338
|
console.log(JSON.stringify({ decision: "spawn", error: e.message }));
|
|
51232
51339
|
}
|