modelstat 0.8.3 → 0.10.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/dist/cli.mjs CHANGED
@@ -34556,7 +34556,9 @@ function load() {
34556
34556
  cursor: obj.cursor ?? {},
34557
34557
  segmentsSent: obj.segmentsSent ?? 0,
34558
34558
  processingVersion: obj.processingVersion ?? null,
34559
- reconcileCache: obj.reconcileCache ?? {}
34559
+ reconcileCache: obj.reconcileCache ?? {},
34560
+ summariserDegraded: obj.summariserDegraded ?? false,
34561
+ summariserRecoveryAt: obj.summariserRecoveryAt ?? 0
34560
34562
  };
34561
34563
  } catch {
34562
34564
  cache2 = { ...DEFAULTS, cursor: {} };
@@ -34579,7 +34581,9 @@ var init_runtime_state = __esm({
34579
34581
  cursor: {},
34580
34582
  segmentsSent: 0,
34581
34583
  processingVersion: null,
34582
- reconcileCache: {}
34584
+ reconcileCache: {},
34585
+ summariserDegraded: false,
34586
+ summariserRecoveryAt: 0
34583
34587
  };
34584
34588
  cache2 = null;
34585
34589
  runtimeState = {
@@ -34646,6 +34650,25 @@ var init_runtime_state = __esm({
34646
34650
  s.processingVersion = v;
34647
34651
  persist(s);
34648
34652
  },
34653
+ /** Whether the last run shipped extractive (LLM-unavailable) abstracts. */
34654
+ getSummariserDegraded() {
34655
+ return load().summariserDegraded;
34656
+ },
34657
+ setSummariserDegraded(v) {
34658
+ const s = load();
34659
+ if (s.summariserDegraded === v) return;
34660
+ s.summariserDegraded = v;
34661
+ persist(s);
34662
+ },
34663
+ /** ms-epoch of the last degradation-recovery re-scan (0 = never). */
34664
+ getSummariserRecoveryAt() {
34665
+ return load().summariserRecoveryAt;
34666
+ },
34667
+ setSummariserRecoveryAt(ms) {
34668
+ const s = load();
34669
+ s.summariserRecoveryAt = ms;
34670
+ persist(s);
34671
+ },
34649
34672
  /** Self-healing reconcile cache (see {@link RuntimeState.reconcileCache}). */
34650
34673
  getReconcileCache() {
34651
34674
  return load().reconcileCache;
@@ -35289,6 +35312,61 @@ var init_prompts = __esm({
35289
35312
  }
35290
35313
  });
35291
35314
 
35315
+ // ../../packages/daemon-core/src/pipeline/heuristic-summary.ts
35316
+ function parsePromptExcerpts(prompt) {
35317
+ const out = [];
35318
+ const re = /\[turn \d+\]\s*"([^"]*)"/g;
35319
+ let m = re.exec(prompt);
35320
+ while (m) {
35321
+ if (m[1]) out.push(m[1]);
35322
+ m = re.exec(prompt);
35323
+ }
35324
+ return out;
35325
+ }
35326
+ function parsePromptFacts(prompt) {
35327
+ const m = /Session context:\s*(.+?)\.\s*(?:\n|$)/.exec(prompt);
35328
+ return m?.[1]?.trim() ?? "";
35329
+ }
35330
+ function pickIntent(lines) {
35331
+ const early = lines.slice(0, 5);
35332
+ const substantive = early.filter((l) => l.length >= 16 && !GREETING.test(l));
35333
+ if (substantive.length > 0) return substantive[0];
35334
+ const byLen = [...early].sort((a, b) => b.length - a.length);
35335
+ return byLen[0] ?? lines.find((l) => l.length > 0) ?? null;
35336
+ }
35337
+ function cleanLead(s) {
35338
+ let t = s.replace(GREETING, "").trim();
35339
+ t = t.replace(LEAD_FILLER, "").trim();
35340
+ if (!t) t = s.trim();
35341
+ return t.charAt(0).toUpperCase() + t.slice(1);
35342
+ }
35343
+ function clamp(s, max) {
35344
+ const t = s.replace(/\s+/g, " ").trim();
35345
+ if (t.length <= max) return t;
35346
+ const cut = t.slice(0, max - 1);
35347
+ const sp = cut.lastIndexOf(" ");
35348
+ return `${(sp > max * 0.6 ? cut.slice(0, sp) : cut).trimEnd()}\u2026`;
35349
+ }
35350
+ function heuristicSummarize() {
35351
+ return async ({ prompt, excerpts, facts }) => {
35352
+ const lines = (excerpts && excerpts.length > 0 ? excerpts : parsePromptExcerpts(prompt)).map((s) => s.replace(/\s+/g, " ").trim()).filter((s) => s.length > 0);
35353
+ const factText = (facts?.trim() || parsePromptFacts(prompt)).replace(/\s+/g, " ").trim();
35354
+ const intent = pickIntent(lines);
35355
+ const lead = intent ? cleanLead(intent) : "AI coding session";
35356
+ const body = factText ? `${lead} [${factText}]` : lead;
35357
+ return clamp(body, ABSTRACT_OUTPUT_MAX_CHARS);
35358
+ };
35359
+ }
35360
+ var GREETING, LEAD_FILLER;
35361
+ var init_heuristic_summary = __esm({
35362
+ "../../packages/daemon-core/src/pipeline/heuristic-summary.ts"() {
35363
+ "use strict";
35364
+ init_prompts();
35365
+ GREETING = /^(hi|hey|hello|thanks?|thank you|ok(ay)?|yes|no|sure|please|cool|great|nice)\b[\s!.,]*/i;
35366
+ LEAD_FILLER = /^(can you|could you|could we|can we|please|i(?:'d| would)? (?:like|want)(?: you)? to|i need(?: you)? to|let'?s|help me|i'?m trying to|i am trying to|now|so|ok(?:ay)?)\s+/i;
35367
+ }
35368
+ });
35369
+
35292
35370
  // ../../packages/daemon-core/src/pipeline/script-summary.ts
35293
35371
  function buildScriptSummaryUserPrompt(input) {
35294
35372
  const body = input.content.slice(0, SCRIPT_SUMMARY_INPUT_MAX_CHARS);
@@ -35755,7 +35833,11 @@ ${excerptBlock}
35755
35833
  Write the SHORTEST keyword-dense paragraph (1-3 sentences, \u2264${ABSTRACT_OUTPUT_MAX_CHARS} chars) naming exactly what was achieved. Lead with an outcome verb. Pack with concrete domain keywords (frameworks, features, components, decisions). Skip narration and filler.`;
35756
35834
  const rawAbstract = await adapters2.summarize({
35757
35835
  prompt,
35758
- maxTokens: SUMMARISER_MAX_TOKENS
35836
+ maxTokens: SUMMARISER_MAX_TOKENS,
35837
+ // Structured inputs for the dependency-free fallback summariser (used when
35838
+ // the bundled LLM can't load); the LLM path ignores these and uses `prompt`.
35839
+ excerpts,
35840
+ facts: promptFacts
35759
35841
  });
35760
35842
  if (!rawAbstract || rawAbstract.trim().length === 0) {
35761
35843
  throw new Error(
@@ -35916,6 +35998,7 @@ var init_pipeline = __esm({
35916
35998
  init_redact();
35917
35999
  init_cognition();
35918
36000
  init_prompts();
36001
+ init_heuristic_summary();
35919
36002
  init_redact();
35920
36003
  init_cognition();
35921
36004
  init_prompts();
@@ -36873,10 +36956,41 @@ __export(pipeline_exports, {
36873
36956
  buildSessionMetadata: () => buildSessionMetadata2,
36874
36957
  buildSessionTitles: () => buildSessionTitles2,
36875
36958
  enrichScripts: () => enrichScripts,
36876
- preflightSummariser: () => preflightSummariser
36959
+ preflightSummariser: () => preflightSummariser,
36960
+ summariserDegradedThisProcess: () => summariserDegradedThisProcess
36877
36961
  });
36878
36962
  import { existsSync as existsSync8 } from "fs";
36879
36963
  import { readFile as fsReadFile } from "fs/promises";
36964
+ function summariserDegradedThisProcess() {
36965
+ return degradedThisProcess;
36966
+ }
36967
+ function markDegraded(reason) {
36968
+ if (!degradedThisProcess) {
36969
+ degradedThisProcess = true;
36970
+ console.warn(
36971
+ `[modelstat] \u26A0 summariser DEGRADED \u2014 bundled LLM unavailable (${reason}); shipping extractive fallback abstracts so ingest continues. They re-summarise at model quality automatically once the LLM is healthy again.`
36972
+ );
36973
+ }
36974
+ runtimeState.setSummariserDegraded(true);
36975
+ }
36976
+ function resilientSummarize(llamaCfg) {
36977
+ const llm = llamaSummarize(llamaCfg);
36978
+ const heuristic = heuristicSummarize();
36979
+ return async (input) => {
36980
+ if (Date.now() >= llmRetryAfter) {
36981
+ try {
36982
+ const out = await llm(input);
36983
+ if (out && out.trim().length > 0) return out;
36984
+ } catch (err) {
36985
+ llmRetryAfter = Date.now() + LLM_RETRY_COOLDOWN_MS;
36986
+ markDegraded(err.message);
36987
+ }
36988
+ } else {
36989
+ markDegraded("LLM in post-failure cooldown");
36990
+ }
36991
+ return heuristic(input);
36992
+ };
36993
+ }
36880
36994
  async function bundledAdapters() {
36881
36995
  const llamaCfg = defaultLlamaConfig();
36882
36996
  return {
@@ -36886,7 +37000,7 @@ async function bundledAdapters() {
36886
37000
  // vector-less with empty arrays; hooking embeddings here attaches a
36887
37001
  // real abstract embedding to each segment.)
36888
37002
  embed: createTransformersJsEmbedder(),
36889
- summarize: llamaSummarize(llamaCfg),
37003
+ summarize: resilientSummarize(llamaCfg),
36890
37004
  tokenize: (text) => Math.max(1, Math.ceil(text.length / 4)),
36891
37005
  cognize: llamaCognize(llamaCfg),
36892
37006
  // Session-title pass — same bundled model, third chat session with
@@ -36919,14 +37033,15 @@ async function bundledAdapters() {
36919
37033
  }
36920
37034
  async function getAdapters() {
36921
37035
  if (adapters) return adapters;
37036
+ let llmReady = true;
36922
37037
  try {
36923
37038
  await import("node-llama-cpp");
36924
- } catch (err) {
36925
- throw new Error(
36926
- `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}`
36927
- );
37039
+ } catch {
37040
+ llmReady = false;
36928
37041
  }
36929
- console.log("[modelstat] using bundled local summariser (Qwen3.5-4B, runs on this machine)");
37042
+ console.log(
37043
+ llmReady ? "[modelstat] using bundled local summariser (Qwen3.5-4B, runs on this machine)" : "[modelstat] bundled summariser runtime not loadable \u2014 using extractive fallback (degraded) until it is"
37044
+ );
36930
37045
  adapters = await bundledAdapters();
36931
37046
  return adapters;
36932
37047
  }
@@ -36965,16 +37080,19 @@ async function preflightSummariser() {
36965
37080
  const a = await getAdapters();
36966
37081
  const out = await a.summarize({
36967
37082
  prompt: 'Session context: smoke test. Sampled excerpts:\n [turn 1] "hello world"\nWrite ONE sentence (\u2264240 chars) describing what the human was doing.',
36968
- maxTokens: 32
37083
+ maxTokens: 32,
37084
+ excerpts: ["smoke test \u2014 verifying the summariser is alive"],
37085
+ facts: "preflight smoke test"
36969
37086
  });
37087
+ const degraded = summariserDegradedThisProcess();
36970
37088
  if (!out || out.trim().length === 0) {
36971
- throw new Error(
36972
- "summariser preflight returned empty output \u2014 the configured summariser is reachable but produced no text. Check the model is loaded."
36973
- );
37089
+ return { label: "summariser produced no output", degraded: true };
36974
37090
  }
36975
- return out.length > 60 ? `${out.slice(0, 57)}\u2026` : out;
37091
+ const sample = out.length > 60 ? `${out.slice(0, 57)}\u2026` : out;
37092
+ const engine = degraded ? "extractive fallback (LLM unavailable)" : "Qwen3.5-4B";
37093
+ return { label: `${engine} \u2014 "${sample}"`, degraded };
36976
37094
  }
36977
- var adapters, MAX_SCRIPT_READ_BYTES, scriptSummarizer;
37095
+ var adapters, degradedThisProcess, LLM_RETRY_COOLDOWN_MS, llmRetryAfter, MAX_SCRIPT_READ_BYTES, scriptSummarizer;
36978
37096
  var init_pipeline2 = __esm({
36979
37097
  "src/pipeline.ts"() {
36980
37098
  "use strict";
@@ -36983,7 +37101,11 @@ var init_pipeline2 = __esm({
36983
37101
  init_privacy_filter();
36984
37102
  init_src2();
36985
37103
  init_enrich_scripts();
37104
+ init_runtime_state();
36986
37105
  adapters = null;
37106
+ degradedThisProcess = false;
37107
+ LLM_RETRY_COOLDOWN_MS = 10 * 6e4;
37108
+ llmRetryAfter = 0;
36987
37109
  MAX_SCRIPT_READ_BYTES = 64 * 1024;
36988
37110
  scriptSummarizer = null;
36989
37111
  }
@@ -37193,7 +37315,7 @@ var init_scan = __esm({
37193
37315
  init_api();
37194
37316
  init_config2();
37195
37317
  init_pipeline2();
37196
- DAEMON_VERSION = true ? "daemon-0.8.3" : "daemon-dev";
37318
+ DAEMON_VERSION = true ? "daemon-0.10.0" : "daemon-dev";
37197
37319
  BATCH_MAX_EVENTS = INGEST_BATCH_MAX_EVENTS;
37198
37320
  BATCH_MAX_TOOL_CALLS = 2e4;
37199
37321
  BATCH_BUFFER_HARD_CAP = BATCH_MAX_EVENTS * 2;
@@ -37760,7 +37882,7 @@ var PROCESSING_VERSION;
37760
37882
  var init_processing_version = __esm({
37761
37883
  "src/processing-version.ts"() {
37762
37884
  "use strict";
37763
- PROCESSING_VERSION = 7;
37885
+ PROCESSING_VERSION = 8;
37764
37886
  }
37765
37887
  });
37766
37888
 
@@ -39996,14 +40118,33 @@ async function runDaemon(opts = {}) {
39996
40118
  const hb = setInterval(() => void sendHeartbeat(), HEARTBEAT_INTERVAL_MS);
39997
40119
  hb.unref();
39998
40120
  void sendHeartbeat();
40121
+ const wasDegraded = runtimeState.getSummariserDegraded();
39999
40122
  try {
40000
40123
  setPhase("starting", "Preflight: summariser");
40001
40124
  const { preflightSummariser: preflightSummariser2 } = await Promise.resolve().then(() => (init_pipeline2(), pipeline_exports));
40002
- const sample = await preflightSummariser2();
40003
- console.log(`[modelstat] summariser preflight ok: "${sample}"`);
40125
+ const { label, degraded } = await preflightSummariser2();
40126
+ if (degraded) {
40127
+ console.warn(`[modelstat] \u26A0 summariser preflight DEGRADED \u2014 ${label}`);
40128
+ setMessage(
40129
+ "summariser degraded: extractive fallback (LLM unavailable) \u2014 ingest continues, self-heals when the model loads"
40130
+ );
40131
+ } else {
40132
+ console.log(`[modelstat] summariser preflight ok: ${label}`);
40133
+ if (wasDegraded) {
40134
+ const since = Date.now() - runtimeState.getSummariserRecoveryAt();
40135
+ if (since > SUMMARISER_RECOVERY_MIN_INTERVAL_MS) {
40136
+ runtimeState.wipeCursors();
40137
+ runtimeState.setSummariserRecoveryAt(Date.now());
40138
+ console.log(
40139
+ "[modelstat] summariser recovered \u2014 re-scanning so extractive fallback abstracts upgrade to model quality"
40140
+ );
40141
+ }
40142
+ }
40143
+ runtimeState.setSummariserDegraded(false);
40144
+ }
40004
40145
  } catch (err) {
40005
- setPhase("error", `summariser preflight failed: ${err.message}`);
40006
- throw err;
40146
+ console.warn(`[modelstat] summariser preflight error (continuing): ${err.message}`);
40147
+ setMessage(`summariser preflight error (continuing): ${err.message}`);
40007
40148
  }
40008
40149
  const localIngest = await startLocalIngestReceiver();
40009
40150
  const LOCAL_DRAIN_INTERVAL_MS = 5e3;
@@ -40104,7 +40245,7 @@ async function runDaemon(opts = {}) {
40104
40245
  await new Promise(() => {
40105
40246
  });
40106
40247
  }
40107
- var import_undici2, DAEMON_VERSION2, HEARTBEAT_INTERVAL_MS, SCAN_INTERVAL_MS, DISCOVERY_INTERVAL_MS, status, LOCAL_FLUSH_THROTTLE_MS, localFlushTimer, localFlushPending, lastVerdict, LOG_MAX_BYTES, LOG_TAIL_KEEP_BYTES, lastStatusPath, scanRunner;
40248
+ var import_undici2, DAEMON_VERSION2, HEARTBEAT_INTERVAL_MS, SCAN_INTERVAL_MS, DISCOVERY_INTERVAL_MS, SUMMARISER_RECOVERY_MIN_INTERVAL_MS, status, LOCAL_FLUSH_THROTTLE_MS, localFlushTimer, localFlushPending, lastVerdict, LOG_MAX_BYTES, LOG_TAIL_KEEP_BYTES, lastStatusPath, scanRunner;
40108
40249
  var init_daemon = __esm({
40109
40250
  "src/daemon.ts"() {
40110
40251
  "use strict";
@@ -40117,13 +40258,15 @@ var init_daemon = __esm({
40117
40258
  init_machine_key();
40118
40259
  init_receiver();
40119
40260
  init_reconcile();
40261
+ init_runtime_state();
40120
40262
  init_scan();
40121
40263
  init_single_flight();
40122
40264
  init_update();
40123
- DAEMON_VERSION2 = true ? "daemon-0.8.3" : "daemon-dev";
40265
+ DAEMON_VERSION2 = true ? "daemon-0.10.0" : "daemon-dev";
40124
40266
  HEARTBEAT_INTERVAL_MS = 1e4;
40125
40267
  SCAN_INTERVAL_MS = 5 * 60 * 1e3;
40126
40268
  DISCOVERY_INTERVAL_MS = 6e4;
40269
+ SUMMARISER_RECOVERY_MIN_INTERVAL_MS = 6 * 60 * 6e4;
40127
40270
  status = {
40128
40271
  phase: "starting",
40129
40272
  message: null,
@@ -40305,15 +40448,16 @@ function setupRuntime() {
40305
40448
  return installBundle();
40306
40449
  }
40307
40450
  var NODE_LLAMA_CPP_FALLBACK_VERSION = "3.18.1";
40308
- function sourceLlamaVersion(sourceCli) {
40451
+ var HF_TRANSFORMERS_FALLBACK_VERSION = "3.8.1";
40452
+ function sourcePkgVersion(sourceCli, pkgName) {
40309
40453
  try {
40310
40454
  const req = createRequire(sourceCli);
40311
- let d = dirname6(realpathSync(req.resolve("node-llama-cpp")));
40455
+ let d = dirname6(realpathSync(req.resolve(pkgName)));
40312
40456
  for (let i = 0; i < 10; i++) {
40313
40457
  const pj = join8(d, "package.json");
40314
40458
  if (existsSync9(pj)) {
40315
40459
  const p = JSON.parse(readFileSync5(pj, "utf8"));
40316
- if (p.name === "node-llama-cpp" && p.version) return p.version;
40460
+ if (p.name === pkgName && p.version) return p.version;
40317
40461
  }
40318
40462
  const up = dirname6(d);
40319
40463
  if (up === d) break;
@@ -40323,21 +40467,21 @@ function sourceLlamaVersion(sourceCli) {
40323
40467
  }
40324
40468
  return null;
40325
40469
  }
40326
- function installNativeRuntime(sourceCli) {
40327
- const version = sourceLlamaVersion(sourceCli) ?? NODE_LLAMA_CPP_FALLBACK_VERSION;
40470
+ function stageNativePkg(sourceCli, pkgName, fallbackVersion, critical) {
40471
+ const version = sourcePkgVersion(sourceCli, pkgName) ?? fallbackVersion;
40328
40472
  const dest = binDir();
40473
+ const pkgJson = join8(dest, "node_modules", ...pkgName.split("/"), "package.json");
40329
40474
  try {
40330
- const have = JSON.parse(
40331
- readFileSync5(join8(dest, "node_modules", "node-llama-cpp", "package.json"), "utf8")
40332
- );
40333
- if (have.version === version) return [`node-llama-cpp@${version} (cached)`];
40475
+ const have = JSON.parse(readFileSync5(pkgJson, "utf8"));
40476
+ if (have.version === version) return [`${pkgName}@${version} (cached)`];
40334
40477
  } catch {
40335
40478
  }
40336
40479
  mkdirSync4(dest, { recursive: true });
40337
40480
  const childEnv = { ...process.env };
40338
40481
  delete childEnv.npm_config_global;
40339
40482
  delete childEnv.npm_config_prefix;
40340
- process.stderr.write(` \xB7 staging summariser runtime (node-llama-cpp@${version})\u2026
40483
+ const label = critical ? "summariser runtime" : "on-device embedder + PII/NER redactor";
40484
+ process.stderr.write(` \xB7 staging ${label} (${pkgName}@${version})\u2026
40341
40485
  `);
40342
40486
  const r = spawnSync2(
40343
40487
  "npm",
@@ -40350,27 +40494,38 @@ function installNativeRuntime(sourceCli) {
40350
40494
  "--omit=dev",
40351
40495
  "--no-audit",
40352
40496
  "--no-fund",
40353
- // Prefer the npm cache the current install already populated (node-llama-cpp
40354
- // is a direct dep, so the platform prebuilt is cached) an offline ~3s copy
40355
- // instead of a redundant network re-fetch. Only a genuine cache miss touches
40356
- // the network, and a capped per-request timeout makes that fail fast (the
40357
- // daemon's summariser preflight re-stages) rather than hang indefinitely.
40497
+ // Prefer the npm cache the current install already populated — an offline
40498
+ // ~3s copy instead of a redundant network re-fetch. Only a genuine cache
40499
+ // miss touches the network, and a capped per-request timeout makes that
40500
+ // fail fast (the daemon re-stages on its next preflight) rather than hang.
40358
40501
  "--prefer-offline",
40359
40502
  "--fetch-timeout=60000",
40360
40503
  "--loglevel=error",
40361
- `node-llama-cpp@${version}`
40504
+ `${pkgName}@${version}`
40362
40505
  ],
40363
40506
  { encoding: "utf8", stdio: "pipe", env: childEnv }
40364
40507
  );
40365
40508
  if (r.status !== 0) {
40366
40509
  process.stderr.write(
40367
- `[modelstat] couldn't stage the bundled summariser runtime via npm (node-llama-cpp@${version}); the daemon's summariser preflight will fail until this is resolved.
40510
+ critical ? `[modelstat] couldn't stage the bundled summariser runtime via npm (${pkgName}@${version}); the daemon's summariser preflight will fail until this is resolved.
40368
40511
  ${(r.stderr || r.stdout || "").trim()}
40512
+ ` : `[modelstat] couldn't stage the on-device embedder/redactor (${pkgName}@${version}); the daemon falls back to server-side embedding + regex/LLM redaction (non-fatal).
40369
40513
  `
40370
40514
  );
40371
40515
  return [];
40372
40516
  }
40373
- return [`node-llama-cpp@${version}`];
40517
+ return [`${pkgName}@${version}`];
40518
+ }
40519
+ function installNativeRuntime(sourceCli) {
40520
+ return [
40521
+ ...stageNativePkg(sourceCli, "node-llama-cpp", NODE_LLAMA_CPP_FALLBACK_VERSION, true),
40522
+ ...stageNativePkg(
40523
+ sourceCli,
40524
+ "@huggingface/transformers",
40525
+ HF_TRANSFORMERS_FALLBACK_VERSION,
40526
+ false
40527
+ )
40528
+ ];
40374
40529
  }
40375
40530
  function nodeBinary() {
40376
40531
  return process.execPath;
@@ -40724,7 +40879,7 @@ function tryOpenBrowser(url) {
40724
40879
  return false;
40725
40880
  }
40726
40881
  }
40727
- var DAEMON_VERSION3 = true ? "daemon-0.8.3" : "daemon-dev";
40882
+ var DAEMON_VERSION3 = true ? "daemon-0.10.0" : "daemon-dev";
40728
40883
  function osFamily() {
40729
40884
  const p = platform6();
40730
40885
  if (p === "darwin") return "macos";
@@ -41097,8 +41252,10 @@ async function cmdDiscover() {
41097
41252
  }
41098
41253
  async function cmdScan() {
41099
41254
  const { preflightSummariser: preflightSummariser2 } = await Promise.resolve().then(() => (init_pipeline2(), pipeline_exports));
41100
- const sample = await preflightSummariser2();
41101
- console.log(`[modelstat] summariser preflight ok: "${sample}"`);
41255
+ const { label, degraded } = await preflightSummariser2();
41256
+ console.log(
41257
+ degraded ? `[modelstat] \u26A0 summariser DEGRADED \u2014 ${label}; extractive fallback, ingest continues` : `[modelstat] summariser preflight ok: ${label}`
41258
+ );
41102
41259
  const { reconcileProcessingVersion: reconcileProcessingVersion2 } = await Promise.resolve().then(() => (init_processing_version(), processing_version_exports));
41103
41260
  const pv = reconcileProcessingVersion2(state);
41104
41261
  if (pv.changed) {