omnius 1.0.94 → 1.0.96

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/index.js CHANGED
@@ -131793,16 +131793,16 @@ var require_cache2 = __commonJS({
131793
131793
  return dispatch(opts2, handler);
131794
131794
  }
131795
131795
  if (origins !== void 0) {
131796
- const requestOrigin = opts2.origin.toString().toLowerCase();
131796
+ const requestOrigin2 = opts2.origin.toString().toLowerCase();
131797
131797
  let isAllowed = false;
131798
131798
  for (let i2 = 0; i2 < origins.length; i2++) {
131799
131799
  const allowed = origins[i2];
131800
131800
  if (typeof allowed === "string") {
131801
- if (allowed.toLowerCase() === requestOrigin) {
131801
+ if (allowed.toLowerCase() === requestOrigin2) {
131802
131802
  isAllowed = true;
131803
131803
  break;
131804
131804
  }
131805
- } else if (allowed.test(requestOrigin)) {
131805
+ } else if (allowed.test(requestOrigin2)) {
131806
131806
  isAllowed = true;
131807
131807
  break;
131808
131808
  }
@@ -246345,8 +246345,8 @@ var require_pattern = __commonJS({
246345
246345
  }
246346
246346
  exports.endsWithSlashGlobStar = endsWithSlashGlobStar;
246347
246347
  function isAffectDepthOfReadingPattern(pattern) {
246348
- const basename30 = path12.basename(pattern);
246349
- return endsWithSlashGlobStar(pattern) || isStaticPattern(basename30);
246348
+ const basename31 = path12.basename(pattern);
246349
+ return endsWithSlashGlobStar(pattern) || isStaticPattern(basename31);
246350
246350
  }
246351
246351
  exports.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern;
246352
246352
  function expandPatternsWithBraceExpansion(patterns) {
@@ -246982,7 +246982,7 @@ var require_async3 = __commonJS({
246982
246982
  readdirWithFileTypes(directory, settings, callback);
246983
246983
  return;
246984
246984
  }
246985
- readdir6(directory, settings, callback);
246985
+ readdir7(directory, settings, callback);
246986
246986
  }
246987
246987
  exports.read = read3;
246988
246988
  function readdirWithFileTypes(directory, settings, callback) {
@@ -247031,7 +247031,7 @@ var require_async3 = __commonJS({
247031
247031
  });
247032
247032
  };
247033
247033
  }
247034
- function readdir6(directory, settings, callback) {
247034
+ function readdir7(directory, settings, callback) {
247035
247035
  settings.fs.readdir(directory, (readdirError, names) => {
247036
247036
  if (readdirError !== null) {
247037
247037
  callFailureCallback(callback, readdirError);
@@ -247066,7 +247066,7 @@ var require_async3 = __commonJS({
247066
247066
  });
247067
247067
  });
247068
247068
  }
247069
- exports.readdir = readdir6;
247069
+ exports.readdir = readdir7;
247070
247070
  function callFailureCallback(callback, error) {
247071
247071
  callback(error);
247072
247072
  }
@@ -247090,7 +247090,7 @@ var require_sync2 = __commonJS({
247090
247090
  if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) {
247091
247091
  return readdirWithFileTypes(directory, settings);
247092
247092
  }
247093
- return readdir6(directory, settings);
247093
+ return readdir7(directory, settings);
247094
247094
  }
247095
247095
  exports.read = read3;
247096
247096
  function readdirWithFileTypes(directory, settings) {
@@ -247115,7 +247115,7 @@ var require_sync2 = __commonJS({
247115
247115
  });
247116
247116
  }
247117
247117
  exports.readdirWithFileTypes = readdirWithFileTypes;
247118
- function readdir6(directory, settings) {
247118
+ function readdir7(directory, settings) {
247119
247119
  const names = settings.fs.readdirSync(directory);
247120
247120
  return names.map((name10) => {
247121
247121
  const entryPath = common.joinPathSegments(directory, name10, settings.pathSegmentSeparator);
@@ -247131,7 +247131,7 @@ var require_sync2 = __commonJS({
247131
247131
  return entry;
247132
247132
  });
247133
247133
  }
247134
- exports.readdir = readdir6;
247134
+ exports.readdir = readdir7;
247135
247135
  }
247136
247136
  });
247137
247137
 
@@ -406906,9 +406906,9 @@ ${lanes.join("\n")}
406906
406906
  /*ignoreCase*/
406907
406907
  false
406908
406908
  )) {
406909
- const basename30 = getBaseFileName(a2.fileName);
406910
- if (basename30 === "lib.d.ts" || basename30 === "lib.es6.d.ts") return 0;
406911
- const name10 = removeSuffix(removePrefix(basename30, "lib."), ".d.ts");
406909
+ const basename31 = getBaseFileName(a2.fileName);
406910
+ if (basename31 === "lib.d.ts" || basename31 === "lib.es6.d.ts") return 0;
406911
+ const name10 = removeSuffix(removePrefix(basename31, "lib."), ".d.ts");
406912
406912
  const index = libs.indexOf(name10);
406913
406913
  if (index !== -1) return index + 1;
406914
406914
  }
@@ -470834,8 +470834,8 @@ ${options2.prefix}` : "\n" : options2.prefix
470834
470834
  }
470835
470835
  };
470836
470836
  for (const file of files) {
470837
- const basename30 = getBaseFileName(file);
470838
- if (basename30 === "package.json" || basename30 === "bower.json") {
470837
+ const basename31 = getBaseFileName(file);
470838
+ if (basename31 === "package.json" || basename31 === "bower.json") {
470839
470839
  createProjectWatcher(
470840
470840
  file,
470841
470841
  "FileWatcher"
@@ -474519,8 +474519,8 @@ All files are: ${JSON.stringify(names)}`,
474519
474519
  var _a;
474520
474520
  const fileOrDirectoryPath = removeIgnoredPath(this.toPath(fileOrDirectory));
474521
474521
  if (!fileOrDirectoryPath) return;
474522
- const basename30 = getBaseFileName(fileOrDirectoryPath);
474523
- if (((_a = result.affectedModuleSpecifierCacheProjects) == null ? void 0 : _a.size) && (basename30 === "package.json" || basename30 === "node_modules")) {
474522
+ const basename31 = getBaseFileName(fileOrDirectoryPath);
474523
+ if (((_a = result.affectedModuleSpecifierCacheProjects) == null ? void 0 : _a.size) && (basename31 === "package.json" || basename31 === "node_modules")) {
474524
474524
  result.affectedModuleSpecifierCacheProjects.forEach((project) => {
474525
474525
  var _a2;
474526
474526
  (_a2 = project.getModuleSpecifierCache()) == null ? void 0 : _a2.clear();
@@ -483423,7 +483423,7 @@ var require_path_browserify = __commonJS({
483423
483423
  if (hasRoot && end === 1) return "//";
483424
483424
  return path12.slice(0, end);
483425
483425
  },
483426
- basename: function basename30(path12, ext) {
483426
+ basename: function basename31(path12, ext) {
483427
483427
  if (ext !== void 0 && typeof ext !== "string") throw new TypeError('"ext" argument must be a string');
483428
483428
  assertPath(path12);
483429
483429
  var start2 = 0;
@@ -524121,9 +524121,9 @@ var init_verifierRunner = __esm({
524121
524121
  async executeTests(patch, repoRoot) {
524122
524122
  if (patch.testsToRun.length === 0)
524123
524123
  return "(no tests specified)";
524124
- const { execFile: execFile7 } = await import("node:child_process");
524124
+ const { execFile: execFile8 } = await import("node:child_process");
524125
524125
  const { promisify: promisify7 } = await import("node:util");
524126
- const execFileAsync5 = promisify7(execFile7);
524126
+ const execFileAsync5 = promisify7(execFile8);
524127
524127
  const outputs = [];
524128
524128
  const workDir = this.options.workingDir || repoRoot;
524129
524129
  for (const cmd of patch.testsToRun.slice(0, 3)) {
@@ -524289,9 +524289,9 @@ var init_retryController = __esm({
524289
524289
  * Call after each verification to get the next action.
524290
524290
  * Also increments the internal attempt counter.
524291
524291
  */
524292
- evaluate(decision) {
524292
+ evaluate(decision2) {
524293
524293
  this.attemptCount += 1;
524294
- if (decision.status === "pass" && decision.nextAction === "finish") {
524294
+ if (decision2.status === "pass" && decision2.nextAction === "finish") {
524295
524295
  return {
524296
524296
  outcome: "accept",
524297
524297
  attemptNumber: this.attemptCount,
@@ -524299,7 +524299,7 @@ var init_retryController = __esm({
524299
524299
  repeatLoopDetected: false
524300
524300
  };
524301
524301
  }
524302
- if (decision.nextAction === "rollback") {
524302
+ if (decision2.nextAction === "rollback") {
524303
524303
  return {
524304
524304
  outcome: "rollback",
524305
524305
  attemptNumber: this.attemptCount,
@@ -524307,7 +524307,7 @@ var init_retryController = __esm({
524307
524307
  repeatLoopDetected: false
524308
524308
  };
524309
524309
  }
524310
- if (decision.nextAction === "inspect_more") {
524310
+ if (decision2.nextAction === "inspect_more") {
524311
524311
  if (this.attemptCount > this.maxRetries) {
524312
524312
  return {
524313
524313
  outcome: "give_up",
@@ -524323,7 +524323,7 @@ var init_retryController = __esm({
524323
524323
  repeatLoopDetected: false
524324
524324
  };
524325
524325
  }
524326
- const fingerprint = decision.failureFingerprint;
524326
+ const fingerprint = decision2.failureFingerprint;
524327
524327
  let repeatLoopDetected = false;
524328
524328
  if (fingerprint) {
524329
524329
  repeatLoopDetected = this.fingerprintHistory.includes(fingerprint);
@@ -524348,7 +524348,7 @@ var init_retryController = __esm({
524348
524348
  return {
524349
524349
  outcome: "retry",
524350
524350
  attemptNumber: this.attemptCount,
524351
- reason: `Verification ${decision.status}. Retrying (attempt ${this.attemptCount} of ${this.maxRetries}).`,
524351
+ reason: `Verification ${decision2.status}. Retrying (attempt ${this.attemptCount} of ${this.maxRetries}).`,
524352
524352
  repeatLoopDetected: false
524353
524353
  };
524354
524354
  }
@@ -524760,6 +524760,620 @@ var init_textSanitize = __esm({
524760
524760
  }
524761
524761
  });
524762
524762
 
524763
+ // packages/orchestrator/dist/ollama-pool-cleanup.js
524764
+ var ollama_pool_cleanup_exports = {};
524765
+ __export(ollama_pool_cleanup_exports, {
524766
+ classifyOllamaProcesses: () => classifyOllamaProcesses,
524767
+ cleanupStaleOllamaProcesses: () => cleanupStaleOllamaProcesses,
524768
+ scanOllamaProcesses: () => scanOllamaProcesses
524769
+ });
524770
+ import { execFile as execFile5 } from "node:child_process";
524771
+ import { readdir as readdir6, readFile as fsReadFile, readlink } from "node:fs/promises";
524772
+ import { basename as basename16 } from "node:path";
524773
+ async function scanOllamaProcesses(options2 = {}) {
524774
+ const system = makeSystem(options2.system);
524775
+ const config = resolveDefaultPoolConfig();
524776
+ const baseInstanceUrl = (options2.baseInstanceUrl ?? config.baseInstanceUrl).replace(/\/+$/, "");
524777
+ const basePort = portFromUrl(baseInstanceUrl) ?? DEFAULT_BASE_PORT;
524778
+ const poolPortStart = options2.poolPortStart ?? config.spawnPortStart ?? DEFAULT_POOL_PORT_START;
524779
+ const protectedPorts = uniqueNumbers([
524780
+ DEFAULT_BASE_PORT,
524781
+ basePort,
524782
+ ...options2.protectedPorts ?? []
524783
+ ]);
524784
+ const scannedAtMs = system.now();
524785
+ const [psRows, portMap, systemdOllamaMainPid, gpuMemoryByPid] = await Promise.all([
524786
+ readPsRows(system),
524787
+ readListeningPortMap(system),
524788
+ readSystemdOllamaMainPid(system),
524789
+ readGpuMemoryByPid(system)
524790
+ ]);
524791
+ const snapshots = [];
524792
+ for (const row of psRows) {
524793
+ if (!isOllamaServeCommand(row.command))
524794
+ continue;
524795
+ const env2 = await readProcEnv(system, row.pid);
524796
+ const ports = uniqueNumbers([
524797
+ ...portMap.get(row.pid) ?? [],
524798
+ ...portsFromEnv(env2.values)
524799
+ ]);
524800
+ const ollamaApiPorts = await probeOllamaPorts(system, ports);
524801
+ snapshots.push({
524802
+ pid: row.pid,
524803
+ ppid: row.ppid,
524804
+ command: row.command,
524805
+ cpuPct: row.cpuPct,
524806
+ memPct: row.memPct,
524807
+ elapsedMs: row.elapsedMs,
524808
+ ports,
524809
+ ollamaApiPorts,
524810
+ envReadable: env2.readable,
524811
+ env: env2.values,
524812
+ gpuMemoryMb: gpuMemoryByPid.get(row.pid) ?? null,
524813
+ isOllamaServe: true
524814
+ });
524815
+ }
524816
+ const decisions = classifyOllamaProcesses(snapshots, {
524817
+ baseInstanceUrl,
524818
+ protectedPorts,
524819
+ poolPortStart,
524820
+ poolPortEnd: options2.poolPortEnd,
524821
+ minAgeMs: options2.minAgeMs,
524822
+ cpuThresholdPct: options2.cpuThresholdPct,
524823
+ poolStatus: options2.poolStatus,
524824
+ systemdOllamaMainPid
524825
+ });
524826
+ return {
524827
+ scannedAtMs,
524828
+ baseInstanceUrl,
524829
+ protectedPorts,
524830
+ poolPortStart,
524831
+ systemdOllamaMainPid,
524832
+ processes: snapshots,
524833
+ decisions,
524834
+ provenance: {
524835
+ entity: `urn:omnius:ollama-pool-cleanup:${scannedAtMs}`,
524836
+ activity: "ollama-process-scan",
524837
+ agent: PROVENANCE_AGENT,
524838
+ timestampMs: scannedAtMs
524839
+ }
524840
+ };
524841
+ }
524842
+ async function cleanupStaleOllamaProcesses(options2 = {}) {
524843
+ const system = makeSystem(options2.system);
524844
+ const dryRun = options2.dryRun !== false;
524845
+ const scan = await scanOllamaProcesses({ ...options2, system });
524846
+ const inference = await maybeApplyInference(scan, options2, system);
524847
+ const decisions = inference.decisions;
524848
+ const report2 = {
524849
+ ...scan,
524850
+ decisions,
524851
+ dryRun,
524852
+ usedInference: inference.usedInference,
524853
+ inferenceFallbackReason: inference.fallbackReason,
524854
+ terminated: [],
524855
+ skipped: [],
524856
+ errors: [],
524857
+ provenance: {
524858
+ entity: scan.provenance.entity,
524859
+ activity: dryRun ? "ollama-process-cleanup-dry-run" : "ollama-process-cleanup",
524860
+ agent: PROVENANCE_AGENT,
524861
+ timestampMs: scan.scannedAtMs
524862
+ }
524863
+ };
524864
+ for (const decision2 of decisions) {
524865
+ const proc = scan.processes.find((p2) => p2.pid === decision2.pid);
524866
+ if (!proc)
524867
+ continue;
524868
+ if (decision2.action !== "terminate") {
524869
+ report2.skipped.push({ pid: decision2.pid, reason: decision2.reasons.join("; ") || "kept" });
524870
+ continue;
524871
+ }
524872
+ const recheck = classifyOllamaProcesses([proc], {
524873
+ baseInstanceUrl: scan.baseInstanceUrl,
524874
+ protectedPorts: scan.protectedPorts,
524875
+ poolPortStart: scan.poolPortStart,
524876
+ poolPortEnd: options2.poolPortEnd,
524877
+ minAgeMs: options2.minAgeMs,
524878
+ cpuThresholdPct: options2.cpuThresholdPct,
524879
+ poolStatus: options2.poolStatus,
524880
+ systemdOllamaMainPid: scan.systemdOllamaMainPid
524881
+ })[0];
524882
+ if (!recheck || recheck.action !== "terminate") {
524883
+ report2.skipped.push({ pid: decision2.pid, reason: "final safety recheck refused termination" });
524884
+ continue;
524885
+ }
524886
+ if (dryRun) {
524887
+ report2.terminated.push({ pid: proc.pid, ports: proc.ports, signal: "dry-run", verified: false });
524888
+ continue;
524889
+ }
524890
+ try {
524891
+ system.kill(proc.pid, "SIGTERM");
524892
+ await system.sleep(options2.graceMs ?? DEFAULT_GRACE_MS);
524893
+ let signal = "SIGTERM";
524894
+ if (system.isPidAlive(proc.pid)) {
524895
+ system.kill(proc.pid, "SIGKILL");
524896
+ signal = "SIGKILL";
524897
+ await system.sleep(250);
524898
+ }
524899
+ const verified = !system.isPidAlive(proc.pid) && await portsClosed(system, proc.ollamaApiPorts);
524900
+ report2.terminated.push({ pid: proc.pid, ports: proc.ports, signal, verified });
524901
+ } catch (err) {
524902
+ report2.errors.push({
524903
+ pid: proc.pid,
524904
+ error: err instanceof Error ? err.message : String(err)
524905
+ });
524906
+ }
524907
+ }
524908
+ return report2;
524909
+ }
524910
+ function classifyOllamaProcesses(processes, options2 = {}) {
524911
+ const config = resolveDefaultPoolConfig();
524912
+ const basePort = portFromUrl(options2.baseInstanceUrl ?? config.baseInstanceUrl) ?? DEFAULT_BASE_PORT;
524913
+ const protectedPorts = new Set(uniqueNumbers([
524914
+ DEFAULT_BASE_PORT,
524915
+ basePort,
524916
+ ...options2.protectedPorts ?? []
524917
+ ]));
524918
+ const poolPortStart = options2.poolPortStart ?? config.spawnPortStart ?? DEFAULT_POOL_PORT_START;
524919
+ const poolPortEnd = options2.poolPortEnd ?? poolPortStart + 128;
524920
+ const minAgeMs = options2.minAgeMs ?? DEFAULT_MIN_AGE_MS;
524921
+ const cpuThresholdPct = options2.cpuThresholdPct ?? DEFAULT_CPU_THRESHOLD_PCT;
524922
+ const activeRefs = activePoolRefs(options2.poolStatus ?? null);
524923
+ return processes.map((proc) => {
524924
+ const reasons = [];
524925
+ const hasProtectedPort = proc.ports.some((p2) => protectedPorts.has(p2));
524926
+ const isSystemdMain = options2.systemdOllamaMainPid !== null && options2.systemdOllamaMainPid !== void 0 && proc.pid === options2.systemdOllamaMainPid;
524927
+ const tracked = activeRefs.pids.has(proc.pid) || proc.ports.some((p2) => activeRefs.ports.has(p2));
524928
+ const inPoolPortRange = proc.ports.some((p2) => p2 >= poolPortStart && p2 <= poolPortEnd);
524929
+ const envPort = portsFromEnv(proc.env).some((p2) => proc.ports.includes(p2));
524930
+ const hasPortEvidence = proc.ports.length > 0 && proc.ollamaApiPorts.length > 0;
524931
+ const lowCpu = proc.cpuPct === null || proc.cpuPct <= cpuThresholdPct;
524932
+ const oldEnough = proc.elapsedMs === null || proc.elapsedMs >= minAgeMs;
524933
+ if (!proc.isOllamaServe) {
524934
+ return decision(proc, "keep", "unknown-ollama", false, false, "deterministic", ["not an ollama serve process"]);
524935
+ }
524936
+ if (isSystemdMain)
524937
+ reasons.push("systemd ollama.service main PID");
524938
+ if (hasProtectedPort)
524939
+ reasons.push(`owns protected port ${proc.ports.filter((p2) => protectedPorts.has(p2)).join(",")}`);
524940
+ if (isSystemdMain || hasProtectedPort) {
524941
+ return decision(proc, "keep", "base-service", true, false, "deterministic", reasons);
524942
+ }
524943
+ if (tracked) {
524944
+ return decision(proc, "keep", "active-pool-owned", true, false, "deterministic", ["tracked by live in-memory pool"]);
524945
+ }
524946
+ if (!hasPortEvidence)
524947
+ reasons.push("no verified Ollama API listening port for this PID");
524948
+ if (!inPoolPortRange && !envPort)
524949
+ reasons.push(`not in pool port range ${poolPortStart}-${poolPortEnd} and no OLLAMA_HOST evidence`);
524950
+ if (!lowCpu)
524951
+ reasons.push(`CPU ${proc.cpuPct?.toFixed(1)}% exceeds ${cpuThresholdPct}%`);
524952
+ if (!oldEnough)
524953
+ reasons.push(`age ${proc.elapsedMs}ms below ${minAgeMs}ms`);
524954
+ const eligible = hasPortEvidence && (inPoolPortRange || envPort) && lowCpu && oldEnough;
524955
+ if (!eligible) {
524956
+ return decision(proc, "keep", "unknown-ollama", false, false, "deterministic", reasons);
524957
+ }
524958
+ reasons.push("old low-utilization untracked pool-range Ollama runner");
524959
+ return decision(proc, "terminate", "stale-pool-runner", false, true, "deterministic", reasons);
524960
+ });
524961
+ }
524962
+ function decision(proc, action, classification, protectedProc, eligible, source, reasons) {
524963
+ return {
524964
+ pid: proc.pid,
524965
+ action,
524966
+ classification,
524967
+ confidence: eligible ? 0.92 : protectedProc ? 1 : 0.5,
524968
+ protected: protectedProc,
524969
+ eligible,
524970
+ source,
524971
+ reasons
524972
+ };
524973
+ }
524974
+ async function maybeApplyInference(scan, options2, system) {
524975
+ const mode = options2.useInference ?? "auto";
524976
+ if (mode === false || process.env["OMNIUS_OLLAMA_CLEANUP_INFERENCE"] === "0") {
524977
+ return { decisions: scan.decisions, usedInference: false, fallbackReason: null };
524978
+ }
524979
+ if (mode === "auto" || mode === true) {
524980
+ try {
524981
+ const inferenceUrl = (options2.inferenceUrl ?? process.env["OMNIUS_OLLAMA_CLEANUP_INFERENCE_URL"] ?? "http://127.0.0.1:11435").replace(/\/+$/, "");
524982
+ await system.fetchJson(`${inferenceUrl}/health`, 1500);
524983
+ const body = {
524984
+ model: options2.inferenceModel ?? process.env["OMNIUS_OLLAMA_CLEANUP_MODEL"] ?? process.env["OMNIUS_MODEL"] ?? "qwen3.5:4b",
524985
+ stream: false,
524986
+ messages: [
524987
+ {
524988
+ role: "system",
524989
+ content: [
524990
+ "You classify stale Ollama pool processes.",
524991
+ 'Return only compact JSON: {"decisions":[{"pid":123,"action":"keep|terminate","reason":"..."}]}',
524992
+ "Never terminate port 11434, the configured base port, systemd ollama.service, or a tracked active pool instance.",
524993
+ "Only choose terminate for processes already marked deterministic action terminate."
524994
+ ].join(" ")
524995
+ },
524996
+ {
524997
+ role: "user",
524998
+ content: JSON.stringify({
524999
+ protectedPorts: scan.protectedPorts,
525000
+ baseInstanceUrl: scan.baseInstanceUrl,
525001
+ processes: scan.processes.map((p2) => ({
525002
+ pid: p2.pid,
525003
+ ports: p2.ports,
525004
+ ollamaApiPorts: p2.ollamaApiPorts,
525005
+ cpuPct: p2.cpuPct,
525006
+ elapsedMs: p2.elapsedMs,
525007
+ gpuMemoryMb: p2.gpuMemoryMb,
525008
+ command: p2.command,
525009
+ deterministic: scan.decisions.find((d2) => d2.pid === p2.pid)
525010
+ }))
525011
+ })
525012
+ }
525013
+ ],
525014
+ temperature: 0
525015
+ };
525016
+ const resp = await system.fetchJson(`${inferenceUrl}/v1/chat/completions`, 15e3, body);
525017
+ const text = extractInferenceText(resp);
525018
+ const parsed = parseJsonObject(text);
525019
+ if (!Array.isArray(parsed.decisions))
525020
+ throw new Error("missing decisions array");
525021
+ const byPid = new Map(parsed.decisions.map((d2) => [Number(d2.pid), d2]));
525022
+ const decisions = scan.decisions.map((det) => {
525023
+ const inf = byPid.get(det.pid);
525024
+ if (!inf)
525025
+ return { ...det, source: "inference-fallback", reasons: [...det.reasons, "inference omitted PID"] };
525026
+ const requestedAction = inf.action === "terminate" ? "terminate" : "keep";
525027
+ if (requestedAction === "terminate" && det.action !== "terminate") {
525028
+ return {
525029
+ ...det,
525030
+ action: "keep",
525031
+ source: "inference-fallback",
525032
+ reasons: [...det.reasons, "inference requested termination but hard rules rejected it"]
525033
+ };
525034
+ }
525035
+ return {
525036
+ ...det,
525037
+ action: requestedAction,
525038
+ source: "inference",
525039
+ reasons: [...det.reasons, `inference: ${String(inf.reason ?? requestedAction).slice(0, 200)}`]
525040
+ };
525041
+ });
525042
+ return { decisions, usedInference: true, fallbackReason: null };
525043
+ } catch (err) {
525044
+ return {
525045
+ decisions: scan.decisions.map((d2) => ({ ...d2, source: "inference-fallback" })),
525046
+ usedInference: false,
525047
+ fallbackReason: err instanceof Error ? err.message : String(err)
525048
+ };
525049
+ }
525050
+ }
525051
+ return { decisions: scan.decisions, usedInference: false, fallbackReason: null };
525052
+ }
525053
+ function makeSystem(overrides) {
525054
+ const base3 = {
525055
+ runCommand: (command, args, timeoutMs) => new Promise((resolve52, reject) => {
525056
+ execFile5(command, args, { encoding: "utf8", timeout: timeoutMs }, (err, stdout) => {
525057
+ if (err)
525058
+ reject(err);
525059
+ else
525060
+ resolve52(stdout);
525061
+ });
525062
+ }),
525063
+ readFile: async (path12) => fsReadFile(path12, "utf8"),
525064
+ readDir: async (path12) => readdir6(path12),
525065
+ readLink: async (path12) => readlink(path12),
525066
+ fetchJson: async (url, timeoutMs, body) => {
525067
+ const resp = await fetch(url, {
525068
+ method: body === void 0 ? "GET" : "POST",
525069
+ headers: body === void 0 ? void 0 : { "content-type": "application/json" },
525070
+ body: body === void 0 ? void 0 : JSON.stringify(body),
525071
+ signal: AbortSignal.timeout(timeoutMs)
525072
+ });
525073
+ if (!resp.ok)
525074
+ throw new Error(`HTTP ${resp.status} from ${url}`);
525075
+ return resp.json();
525076
+ },
525077
+ kill: (pid, signal) => process.kill(pid, signal),
525078
+ isPidAlive: (pid) => {
525079
+ try {
525080
+ process.kill(pid, 0);
525081
+ return true;
525082
+ } catch {
525083
+ return false;
525084
+ }
525085
+ },
525086
+ sleep: (ms) => new Promise((resolve52) => setTimeout(resolve52, ms)),
525087
+ now: () => Date.now()
525088
+ };
525089
+ return { ...base3, ...overrides ?? {} };
525090
+ }
525091
+ async function readPsRows(system) {
525092
+ try {
525093
+ const out = await system.runCommand("ps", ["-eo", "pid=,ppid=,pcpu=,pmem=,etimes=,args="], 5e3);
525094
+ return out.split(/\r?\n/).map(parsePsRow).filter((r2) => r2 !== null);
525095
+ } catch {
525096
+ return [];
525097
+ }
525098
+ }
525099
+ function parsePsRow(line) {
525100
+ const trimmed = line.trim();
525101
+ if (!trimmed)
525102
+ return null;
525103
+ const parts = trimmed.split(/\s+/, 6);
525104
+ if (parts.length < 6)
525105
+ return null;
525106
+ const pid = Number(parts[0]);
525107
+ if (!Number.isFinite(pid))
525108
+ return null;
525109
+ const ppid = Number(parts[1]);
525110
+ const cpuPct = nullableNumber(parts[2]);
525111
+ const memPct = nullableNumber(parts[3]);
525112
+ const elapsedSec = nullableNumber(parts[4]);
525113
+ const commandStart = nthWhitespaceIndex(trimmed, 5);
525114
+ const command = commandStart >= 0 ? trimmed.slice(commandStart).trim() : parts[5] ?? "";
525115
+ return {
525116
+ pid,
525117
+ ppid: Number.isFinite(ppid) ? ppid : null,
525118
+ cpuPct,
525119
+ memPct,
525120
+ elapsedMs: elapsedSec === null ? null : elapsedSec * 1e3,
525121
+ command
525122
+ };
525123
+ }
525124
+ async function readListeningPortMap(system) {
525125
+ const map2 = /* @__PURE__ */ new Map();
525126
+ await readSsPorts(system, map2);
525127
+ await readLsofPorts(system, map2);
525128
+ await readProcNetPorts(system, map2);
525129
+ return map2;
525130
+ }
525131
+ async function readSsPorts(system, map2) {
525132
+ try {
525133
+ const out = await system.runCommand("ss", ["-ltnpH"], 5e3);
525134
+ for (const line of out.split(/\r?\n/)) {
525135
+ const pidMatch = line.match(/pid=(\d+)/);
525136
+ if (!pidMatch?.[1])
525137
+ continue;
525138
+ const parts = line.trim().split(/\s+/);
525139
+ const local = parts[3] ?? parts[2] ?? "";
525140
+ const port = parseEndpointPort(local);
525141
+ if (port === null)
525142
+ continue;
525143
+ addPort(map2, Number(pidMatch[1]), port);
525144
+ }
525145
+ } catch {
525146
+ }
525147
+ }
525148
+ async function readLsofPorts(system, map2) {
525149
+ try {
525150
+ const out = await system.runCommand("lsof", ["-nP", "-iTCP", "-sTCP:LISTEN"], 5e3);
525151
+ for (const line of out.split(/\r?\n/).slice(1)) {
525152
+ const parts = line.trim().split(/\s+/);
525153
+ const pid = Number(parts[1]);
525154
+ const name10 = parts[8] ?? "";
525155
+ const port = parseEndpointPort(name10);
525156
+ if (Number.isFinite(pid) && port !== null)
525157
+ addPort(map2, pid, port);
525158
+ }
525159
+ } catch {
525160
+ }
525161
+ }
525162
+ async function readProcNetPorts(system, map2) {
525163
+ if (process.platform !== "linux")
525164
+ return;
525165
+ try {
525166
+ const inodeToPort = /* @__PURE__ */ new Map();
525167
+ for (const file of ["/proc/net/tcp", "/proc/net/tcp6"]) {
525168
+ try {
525169
+ const text = await system.readFile(file);
525170
+ for (const line of text.split(/\r?\n/).slice(1)) {
525171
+ const parts = line.trim().split(/\s+/);
525172
+ if (parts.length < 10 || parts[3] !== "0A")
525173
+ continue;
525174
+ const local = parts[1] ?? "";
525175
+ const inode = parts[9] ?? "";
525176
+ const port = parseProcNetPort(local);
525177
+ if (port !== null && inode)
525178
+ inodeToPort.set(inode, port);
525179
+ }
525180
+ } catch {
525181
+ }
525182
+ }
525183
+ if (inodeToPort.size === 0)
525184
+ return;
525185
+ const procEntries = await system.readDir("/proc");
525186
+ await Promise.all(procEntries.filter((name10) => /^\d+$/.test(name10)).map(async (pidText) => {
525187
+ const pid = Number(pidText);
525188
+ try {
525189
+ const fdDir = `/proc/${pid}/fd`;
525190
+ const fds = await system.readDir(fdDir);
525191
+ for (const fd of fds) {
525192
+ try {
525193
+ const target = await system.readLink(`${fdDir}/${fd}`);
525194
+ const m2 = target.match(/^socket:\[(\d+)\]$/);
525195
+ const port = m2?.[1] ? inodeToPort.get(m2[1]) : void 0;
525196
+ if (port !== void 0)
525197
+ addPort(map2, pid, port);
525198
+ } catch {
525199
+ }
525200
+ }
525201
+ } catch {
525202
+ }
525203
+ }));
525204
+ } catch {
525205
+ }
525206
+ }
525207
+ async function readSystemdOllamaMainPid(system) {
525208
+ try {
525209
+ const out = await system.runCommand("systemctl", ["show", "ollama.service", "-p", "MainPID", "--value"], 3e3);
525210
+ const pid = Number(out.trim());
525211
+ return Number.isFinite(pid) && pid > 0 ? pid : null;
525212
+ } catch {
525213
+ return null;
525214
+ }
525215
+ }
525216
+ async function readGpuMemoryByPid(system) {
525217
+ const map2 = /* @__PURE__ */ new Map();
525218
+ try {
525219
+ const out = await system.runCommand("nvidia-smi", ["--query-compute-apps=pid,used_memory", "--format=csv,noheader,nounits"], 3e3);
525220
+ for (const line of out.split(/\r?\n/)) {
525221
+ const [pidText, memText] = line.split(",").map((s2) => s2?.trim());
525222
+ const pid = Number(pidText);
525223
+ const mem = Number(memText);
525224
+ if (Number.isFinite(pid) && Number.isFinite(mem))
525225
+ map2.set(pid, mem);
525226
+ }
525227
+ } catch {
525228
+ }
525229
+ return map2;
525230
+ }
525231
+ async function readProcEnv(system, pid) {
525232
+ try {
525233
+ const raw = await system.readFile(`/proc/${pid}/environ`);
525234
+ const values = {};
525235
+ for (const entry of raw.split("\0")) {
525236
+ const idx = entry.indexOf("=");
525237
+ if (idx <= 0)
525238
+ continue;
525239
+ const key = entry.slice(0, idx);
525240
+ if (!["OLLAMA_HOST", "OLLAMA_MODELS", "OLLAMA_NUM_PARALLEL", "CUDA_VISIBLE_DEVICES", "GPU_DEVICE_ORDINAL"].includes(key))
525241
+ continue;
525242
+ values[key] = entry.slice(idx + 1);
525243
+ }
525244
+ return { readable: true, values };
525245
+ } catch {
525246
+ return { readable: false, values: {} };
525247
+ }
525248
+ }
525249
+ async function probeOllamaPorts(system, ports) {
525250
+ const ok2 = [];
525251
+ await Promise.all(ports.map(async (port) => {
525252
+ try {
525253
+ const json = await system.fetchJson(`http://127.0.0.1:${port}/api/version`, 1e3);
525254
+ if (json && typeof json === "object" && "version" in json)
525255
+ ok2.push(port);
525256
+ } catch {
525257
+ }
525258
+ }));
525259
+ return ok2.sort((a2, b) => a2 - b);
525260
+ }
525261
+ async function portsClosed(system, ports) {
525262
+ for (const port of ports) {
525263
+ try {
525264
+ await system.fetchJson(`http://127.0.0.1:${port}/api/version`, 750);
525265
+ return false;
525266
+ } catch {
525267
+ }
525268
+ }
525269
+ return true;
525270
+ }
525271
+ function activePoolRefs(poolStatus) {
525272
+ const pids = /* @__PURE__ */ new Set();
525273
+ const ports = /* @__PURE__ */ new Set();
525274
+ for (const inst of poolStatus?.instances ?? []) {
525275
+ if (inst.poolOwned && inst.pid !== null)
525276
+ pids.add(inst.pid);
525277
+ const port = portFromUrl(inst.baseUrl);
525278
+ if (inst.poolOwned && port !== null)
525279
+ ports.add(port);
525280
+ }
525281
+ return { pids, ports };
525282
+ }
525283
+ function isOllamaServeCommand(command) {
525284
+ const [exe, subcommand] = command.trim().split(/\s+/);
525285
+ return basename16(exe ?? "") === "ollama" && subcommand === "serve";
525286
+ }
525287
+ function portsFromEnv(env2) {
525288
+ const host = env2["OLLAMA_HOST"];
525289
+ if (!host)
525290
+ return [];
525291
+ const port = portFromUrl(host.includes("://") ? host : `http://${host}`);
525292
+ return port === null ? [] : [port];
525293
+ }
525294
+ function addPort(map2, pid, port) {
525295
+ if (!Number.isFinite(pid) || !Number.isFinite(port))
525296
+ return;
525297
+ const list = map2.get(pid) ?? [];
525298
+ if (!list.includes(port))
525299
+ list.push(port);
525300
+ list.sort((a2, b) => a2 - b);
525301
+ map2.set(pid, list);
525302
+ }
525303
+ function portFromUrl(value2) {
525304
+ try {
525305
+ const normalized = /^[^:/]+:\d+$/.test(value2) ? `http://${value2}` : value2;
525306
+ const url = new URL(normalized);
525307
+ const port = url.port ? Number(url.port) : url.protocol === "https:" ? 443 : 80;
525308
+ return Number.isFinite(port) ? port : null;
525309
+ } catch {
525310
+ const match = value2.match(/:(\d+)(?:\/|$)/);
525311
+ return match?.[1] ? Number(match[1]) : null;
525312
+ }
525313
+ }
525314
+ function parseEndpointPort(endpoint) {
525315
+ const cleaned = endpoint.replace(/^\[/, "").replace(/\]$/, "");
525316
+ const colon = cleaned.match(/:(\d+)(?:\s|$|\)|->)?/);
525317
+ if (colon?.[1])
525318
+ return Number(colon[1]);
525319
+ const dot = cleaned.match(/\.(\d+)$/);
525320
+ return dot?.[1] ? Number(dot[1]) : null;
525321
+ }
525322
+ function parseProcNetPort(localAddress) {
525323
+ const parts = localAddress.split(":");
525324
+ const hex = parts[1];
525325
+ if (!hex)
525326
+ return null;
525327
+ const port = Number.parseInt(hex, 16);
525328
+ return Number.isFinite(port) ? port : null;
525329
+ }
525330
+ function nullableNumber(value2) {
525331
+ const n2 = Number(value2);
525332
+ return Number.isFinite(n2) ? n2 : null;
525333
+ }
525334
+ function nthWhitespaceIndex(value2, count) {
525335
+ let seen = 0;
525336
+ for (let i2 = 0; i2 < value2.length; i2++) {
525337
+ if (/\s/.test(value2[i2])) {
525338
+ while (i2 < value2.length && /\s/.test(value2[i2]))
525339
+ i2++;
525340
+ seen++;
525341
+ if (seen === count)
525342
+ return i2;
525343
+ }
525344
+ }
525345
+ return -1;
525346
+ }
525347
+ function uniqueNumbers(values) {
525348
+ return [...new Set(values.filter((v) => Number.isFinite(v)))].sort((a2, b) => a2 - b);
525349
+ }
525350
+ function extractInferenceText(resp) {
525351
+ const obj = resp;
525352
+ return String(obj?.choices?.[0]?.message?.content ?? obj?.message?.content ?? obj?.response ?? obj?.content ?? "");
525353
+ }
525354
+ function parseJsonObject(text) {
525355
+ const trimmed = text.trim();
525356
+ if (trimmed.startsWith("{"))
525357
+ return JSON.parse(trimmed);
525358
+ const match = trimmed.match(/\{[\s\S]*\}/);
525359
+ if (!match)
525360
+ throw new Error("model response did not contain JSON");
525361
+ return JSON.parse(match[0]);
525362
+ }
525363
+ var DEFAULT_BASE_PORT, DEFAULT_POOL_PORT_START, DEFAULT_MIN_AGE_MS, DEFAULT_CPU_THRESHOLD_PCT, DEFAULT_GRACE_MS, PROVENANCE_AGENT;
525364
+ var init_ollama_pool_cleanup = __esm({
525365
+ "packages/orchestrator/dist/ollama-pool-cleanup.js"() {
525366
+ "use strict";
525367
+ init_ollama_pool();
525368
+ DEFAULT_BASE_PORT = 11434;
525369
+ DEFAULT_POOL_PORT_START = 11435;
525370
+ DEFAULT_MIN_AGE_MS = 10 * 60 * 1e3;
525371
+ DEFAULT_CPU_THRESHOLD_PCT = 1;
525372
+ DEFAULT_GRACE_MS = 2e3;
525373
+ PROVENANCE_AGENT = "orchestrator.ollama-pool-cleanup";
525374
+ }
525375
+ });
525376
+
524763
525377
  // packages/orchestrator/dist/ollama-pool.js
524764
525378
  import { spawn as spawn21, exec } from "node:child_process";
524765
525379
  import { existsSync as existsSync60, readFileSync as readFileSync47, readdirSync as readdirSync20, statfsSync as statfsSync3, statSync as statSync22 } from "node:fs";
@@ -525213,6 +525827,7 @@ var init_ollama_pool = __esm({
525213
525827
  spawnedAtMs: Date.now()
525214
525828
  }, null));
525215
525829
  this.startReaper();
525830
+ this.scheduleStartupCleanupScan();
525216
525831
  }
525217
525832
  /**
525218
525833
  * Resolve the effective agent id for an acquire request. Explicit option
@@ -525625,6 +526240,40 @@ var init_ollama_pool = __esm({
525625
526240
  await inst.terminate();
525626
526241
  return true;
525627
526242
  }
526243
+ scheduleStartupCleanupScan() {
526244
+ if (process.env["NODE_ENV"] === "test" || process.env["VITEST"])
526245
+ return;
526246
+ if (process.env["OMNIUS_OLLAMA_CLEANUP_STARTUP_SCAN"] === "0")
526247
+ return;
526248
+ const handle2 = setTimeout(async () => {
526249
+ try {
526250
+ const cleanupOnStart = process.env["OMNIUS_OLLAMA_CLEANUP_ON_START"] === "1";
526251
+ const { cleanupStaleOllamaProcesses: cleanupStaleOllamaProcesses2 } = await Promise.resolve().then(() => (init_ollama_pool_cleanup(), ollama_pool_cleanup_exports));
526252
+ const report2 = await cleanupStaleOllamaProcesses2({
526253
+ dryRun: !cleanupOnStart,
526254
+ useInference: cleanupOnStart ? "auto" : false,
526255
+ baseInstanceUrl: this.config.baseInstanceUrl,
526256
+ poolPortStart: this.config.spawnPortStart,
526257
+ poolStatus: await this.status()
526258
+ });
526259
+ const stale = report2.decisions.filter((d2) => d2.action === "terminate");
526260
+ if (stale.length > 0) {
526261
+ this.emit(cleanupOnStart ? "stale-process-cleanup" : "stale-processes-found", {
526262
+ staleCount: stale.length,
526263
+ dryRun: report2.dryRun,
526264
+ terminated: report2.terminated,
526265
+ skipped: report2.skipped,
526266
+ errors: report2.errors,
526267
+ provenance: report2.provenance
526268
+ });
526269
+ }
526270
+ } catch (error) {
526271
+ this.emit("stale-process-scan-failed", { error });
526272
+ }
526273
+ }, 250);
526274
+ if (typeof handle2.unref === "function")
526275
+ handle2.unref();
526276
+ }
525628
526277
  portFromUrl(url) {
525629
526278
  const m2 = url.match(/:(\d+)(?:\/|$)/);
525630
526279
  if (m2?.[1])
@@ -526323,7 +526972,7 @@ var init_intervention_replay = __esm({
526323
526972
 
526324
526973
  // packages/orchestrator/dist/world-state-disk-scan.js
526325
526974
  import { existsSync as existsSync64, readFileSync as readFileSync50, readdirSync as readdirSync22, statSync as statSync24 } from "node:fs";
526326
- import { join as join77, relative as relative7, basename as basename16 } from "node:path";
526975
+ import { join as join77, relative as relative7, basename as basename17 } from "node:path";
526327
526976
  function loadIgnoreFile(path12) {
526328
526977
  if (!existsSync64(path12))
526329
526978
  return [];
@@ -526403,7 +527052,7 @@ function scanWorkspace(opts) {
526403
527052
  }
526404
527053
  const abs = join77(dir, entry);
526405
527054
  const rel = relative7(root, abs);
526406
- const base3 = basename16(abs);
527055
+ const base3 = basename17(abs);
526407
527056
  if (shouldIgnore(rel, base3, patterns))
526408
527057
  continue;
526409
527058
  let st;
@@ -537418,8 +538067,8 @@ function createAppState(opts) {
537418
538067
  expandedView: false
537419
538068
  };
537420
538069
  }
537421
- function recordToolDecision(state, decision) {
537422
- state.toolDecisions.push({ ...decision, timestamp: Date.now() });
538070
+ function recordToolDecision(state, decision2) {
538071
+ state.toolDecisions.push({ ...decision2, timestamp: Date.now() });
537423
538072
  if (state.toolDecisions.length > state.toolDecisionMaxHistory) {
537424
538073
  state.toolDecisions.splice(0, state.toolDecisions.length - state.toolDecisionMaxHistory);
537425
538074
  }
@@ -556083,8 +556732,10 @@ __export(dist_exports3, {
556083
556732
  checkMilestoneComplete: () => checkMilestoneComplete,
556084
556733
  claimAssertion: () => claimAssertion,
556085
556734
  classifyHandoff: () => classifyHandoff,
556735
+ classifyOllamaProcesses: () => classifyOllamaProcesses,
556086
556736
  cleanForStorage: () => cleanForStorage,
556087
556737
  cleanScaffolding: () => cleanScaffolding,
556738
+ cleanupStaleOllamaProcesses: () => cleanupStaleOllamaProcesses,
556088
556739
  clearTurnState: () => clearTurnState,
556089
556740
  combineValidatorResults: () => combineValidatorResults,
556090
556741
  compilePersonalityPrompt: () => compilePersonalityPrompt,
@@ -556162,6 +556813,7 @@ __export(dist_exports3, {
556162
556813
  resolveDefaultPoolConfig: () => resolveDefaultPoolConfig,
556163
556814
  resolveModelProfile: () => resolveModelProfile,
556164
556815
  restoreAgentTasks: () => restoreAgentTasks,
556816
+ scanOllamaProcesses: () => scanOllamaProcesses,
556165
556817
  scoreHandoff: () => scoreHandoff,
556166
556818
  sealMilestone: () => sealMilestone,
556167
556819
  sealMilestoneState: () => sealMilestoneState,
@@ -556196,6 +556848,7 @@ var init_dist8 = __esm({
556196
556848
  init_retryController();
556197
556849
  init_agenticRunner();
556198
556850
  init_ollama_pool();
556851
+ init_ollama_pool_cleanup();
556199
556852
  init_modelProfile();
556200
556853
  init_pressure_gate();
556201
556854
  init_constraint_learner();
@@ -557336,10 +557989,10 @@ transcribe-cli error: ${transcribeCliError}` : "";
557336
557989
  wordTimestamps: false
557337
557990
  });
557338
557991
  if (outputDir) {
557339
- const { basename: basename30 } = await import("node:path");
557992
+ const { basename: basename31 } = await import("node:path");
557340
557993
  const transcriptDir = join97(outputDir, ".omnius", "transcripts");
557341
557994
  mkdirSync45(transcriptDir, { recursive: true });
557342
- const outFile = join97(transcriptDir, `${basename30(filePath)}.txt`);
557995
+ const outFile = join97(transcriptDir, `${basename31(filePath)}.txt`);
557343
557996
  writeFileSync40(outFile, result.text, "utf-8");
557344
557997
  }
557345
557998
  return {
@@ -557355,10 +558008,10 @@ transcribe-cli error: ${transcribeCliError}` : "";
557355
558008
  const fb = await transcribeFileViaWhisper(filePath, this.config.model);
557356
558009
  if (fb) {
557357
558010
  if (outputDir) {
557358
- const { basename: basename30 } = await import("node:path");
558011
+ const { basename: basename31 } = await import("node:path");
557359
558012
  const transcriptDir = join97(outputDir, ".omnius", "transcripts");
557360
558013
  mkdirSync45(transcriptDir, { recursive: true });
557361
- const outFile = join97(transcriptDir, `${basename30(filePath)}.txt`);
558014
+ const outFile = join97(transcriptDir, `${basename31(filePath)}.txt`);
557362
558015
  writeFileSync40(outFile, fb.text, "utf-8");
557363
558016
  }
557364
558017
  return fb;
@@ -561531,6 +562184,8 @@ var init_command_registry = __esm({
561531
562184
  ["/wizard", "Alias for /setup"],
561532
562185
  ["/parallel", "Show current Ollama parallel inference slots"],
561533
562186
  ["/parallel <1-15>", "Set parallel slots (restarts Ollama, max 15)"],
562187
+ ["/ollama cleanup", "Dry-run stale Ollama pool process cleanup"],
562188
+ ["/ollama cleanup --execute", "Terminate guarded stale Ollama pool runners"],
561534
562189
  ["/mcp", "Show MCP server/tool status and controls"],
561535
562190
  ["/mcp reload", "Reload MCP servers and tools"],
561536
562191
  ["/update", "Check for updates and auto-install"],
@@ -561999,7 +562654,7 @@ var init_command_registry = __esm({
561999
562654
  "deny",
562000
562655
  "sethome"
562001
562656
  ]);
562002
- DESTRUCTIVE = /* @__PURE__ */ new Set(["destroy", "stop", "rollback", "update", "upgrade", "deny", "daemon"]);
562657
+ DESTRUCTIVE = /* @__PURE__ */ new Set(["destroy", "stop", "rollback", "update", "upgrade", "deny", "daemon", "ollama"]);
562003
562658
  NETWORKED = /* @__PURE__ */ new Set([
562004
562659
  "endpoint",
562005
562660
  "update",
@@ -562458,6 +563113,7 @@ var init_text_selection = __esm({
562458
563113
  // packages/cli/src/tui/task-complete-box.ts
562459
563114
  var task_complete_box_exports = {};
562460
563115
  __export(task_complete_box_exports, {
563116
+ TASK_COMPLETE_GREEN_256: () => TASK_COMPLETE_GREEN_256,
562461
563117
  buildBoxLines: () => buildBoxLines,
562462
563118
  buildSessionHistoryBoxLines: () => buildSessionHistoryBoxLines,
562463
563119
  deriveTitle: () => deriveTitle,
@@ -562468,7 +563124,8 @@ __export(task_complete_box_exports, {
562468
563124
  });
562469
563125
  function deriveTitle(task) {
562470
563126
  if (!task || !task.trim()) return "Task Complete";
562471
- const cleaned = task.replace(/```[\s\S]*?```/g, " ").replace(/`[^`]+`/g, " ").replace(/\([^)]*\)/g, " ").replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim();
563127
+ const source = task.replace(/^[\s\S]*?\n---\s*\n\s*NEW TASK:\s*/i, "").replace(/^NEW TASK:\s*/i, "").replace(/<task-handoff>[\s\S]*?<\/task-handoff>/gi, " ").replace(/<session-recap>[\s\S]*?<\/session-recap>/gi, " ").replace(/^\[task_(?:boundary|summary)\][\s\S]*?(?=\n\n|$)/gim, " ");
563128
+ const cleaned = source.replace(/```[\s\S]*?```/g, " ").replace(/`[^`]+`/g, " ").replace(/^#{1,6}\s*Previous Task:.*$/gim, " ").replace(/^Prior (?:goal|task):.*$/gim, " ").replace(/\([^)]*\)/g, " ").replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim();
562472
563129
  if (!cleaned) return "Task Complete";
562473
563130
  const firstSentence = cleaned.split(/(?<=[.!?:])\s/)[0] ?? cleaned;
562474
563131
  const words = firstSentence.split(/\s+/).filter((w) => w.length > 0);
@@ -562805,7 +563462,7 @@ function detectProvenanceAnchors(toolOutputs) {
562805
563462
  }
562806
563463
  return [...out].slice(0, 16);
562807
563464
  }
562808
- var BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, BOX_TJ_L, BOX_TJ_R, RESET, GREEN, FG_BORDER, FG_TITLE, FG_METRIC, FG_LABEL;
563465
+ var BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, BOX_TJ_L, BOX_TJ_R, RESET, TASK_COMPLETE_GREEN_256, GREEN, FG_BORDER, FG_TITLE, FG_METRIC, FG_LABEL;
562809
563466
  var init_task_complete_box = __esm({
562810
563467
  "packages/cli/src/tui/task-complete-box.ts"() {
562811
563468
  "use strict";
@@ -562819,9 +563476,10 @@ var init_task_complete_box = __esm({
562819
563476
  BOX_TJ_L = "├";
562820
563477
  BOX_TJ_R = "┤";
562821
563478
  RESET = "\x1B[0m";
562822
- GREEN = "\x1B[38;5;154m";
562823
- FG_BORDER = "\x1B[38;5;154m";
562824
- FG_TITLE = "\x1B[1;38;5;154m";
563479
+ TASK_COMPLETE_GREEN_256 = 154;
563480
+ GREEN = `\x1B[38;5;${TASK_COMPLETE_GREEN_256}m`;
563481
+ FG_BORDER = `\x1B[38;5;${TASK_COMPLETE_GREEN_256}m`;
563482
+ FG_TITLE = `\x1B[1;38;5;${TASK_COMPLETE_GREEN_256}m`;
562825
563483
  FG_METRIC = "\x1B[38;5;222m";
562826
563484
  FG_LABEL = "\x1B[38;5;147m";
562827
563485
  }
@@ -569232,7 +569890,7 @@ __export(omnius_directory_exports, {
569232
569890
  writeTaskHandoff: () => writeTaskHandoff2
569233
569891
  });
569234
569892
  import { appendFileSync as appendFileSync5, cpSync as cpSync2, existsSync as existsSync88, mkdirSync as mkdirSync50, readFileSync as readFileSync70, writeFileSync as writeFileSync45, readdirSync as readdirSync29, statSync as statSync32, unlinkSync as unlinkSync15, openSync as openSync2, closeSync as closeSync2, renameSync as renameSync4 } from "node:fs";
569235
- import { join as join104, relative as relative9, basename as basename17, dirname as dirname29 } from "node:path";
569893
+ import { join as join104, relative as relative9, basename as basename18, dirname as dirname29 } from "node:path";
569236
569894
  import { homedir as homedir31 } from "node:os";
569237
569895
  import { createHash as createHash20 } from "node:crypto";
569238
569896
  function findGitRoot(startDir) {
@@ -569428,7 +570086,7 @@ function writeIndexData(repoRoot, filename, data) {
569428
570086
  }
569429
570087
  function generateProjectMap(repoRoot) {
569430
570088
  const sections = [];
569431
- const repoName2 = basename17(repoRoot);
570089
+ const repoName2 = basename18(repoRoot);
569432
570090
  sections.push(`# Project Map: ${repoName2}
569433
570091
  `);
569434
570092
  sections.push(`> Auto-generated by omnius. Updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -570645,7 +571303,7 @@ var init_braille_spinner = __esm({
570645
571303
  });
570646
571304
 
570647
571305
  // packages/cli/src/tui/disk-monitor.ts
570648
- import { execFile as execFile5 } from "node:child_process";
571306
+ import { execFile as execFile6 } from "node:child_process";
570649
571307
  import { promisify as promisify5 } from "node:util";
570650
571308
  function unavailableDiskMetrics(path12 = process.cwd()) {
570651
571309
  return {
@@ -570694,7 +571352,7 @@ var execFileAsync4;
570694
571352
  var init_disk_monitor = __esm({
570695
571353
  "packages/cli/src/tui/disk-monitor.ts"() {
570696
571354
  "use strict";
570697
- execFileAsync4 = promisify5(execFile5);
571355
+ execFileAsync4 = promisify5(execFile6);
570698
571356
  }
570699
571357
  });
570700
571358
 
@@ -571682,7 +572340,7 @@ function setTerminalTitle(task, version4) {
571682
572340
  const title = task ? `${task.slice(0, 60)} · ${ver}` : ver;
571683
572341
  process.stdout.write(`\x1B]2;${title}\x07`);
571684
572342
  }
571685
- var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, NO_SUB_AGENTS_HEADER_LABEL, BOX_TL3, BOX_TR3, BOX_BL3, BOX_BR3, BOX_H3, BOX_V3, _globalFooterLock, RESET4, CURSOR_BLINK_BLOCK, _isWindows, StatusBar;
572343
+ var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, NO_SUB_AGENTS_HEADER_LABEL, HEADER_ACCENT_GREEN, HEADER_ACCENT_BOLD_FG, HEADER_BUTTON_BG, HEADER_BUTTON_FG, BOX_TL3, BOX_TR3, BOX_BL3, BOX_BR3, BOX_H3, BOX_V3, _globalFooterLock, RESET4, CURSOR_BLINK_BLOCK, _isWindows, StatusBar;
571686
572344
  var init_status_bar = __esm({
571687
572345
  "packages/cli/src/tui/status-bar.ts"() {
571688
572346
  "use strict";
@@ -571861,6 +572519,10 @@ var init_status_bar = __esm({
571861
572519
  TEXT_PRIMARY = tuiTextPrimary() < 0 ? 252 : tuiTextPrimary();
571862
572520
  TEXT_DIM = tuiTextDim();
571863
572521
  NO_SUB_AGENTS_HEADER_LABEL = " no sub-agents ";
572522
+ HEADER_ACCENT_GREEN = 154;
572523
+ HEADER_ACCENT_BOLD_FG = `\x1B[1;38;5;${HEADER_ACCENT_GREEN}m`;
572524
+ HEADER_BUTTON_BG = `\x1B[48;5;${HEADER_ACCENT_GREEN}m`;
572525
+ HEADER_BUTTON_FG = "\x1B[38;5;0m";
571864
572526
  BOX_TL3 = "╭";
571865
572527
  BOX_TR3 = "╮";
571866
572528
  BOX_BL3 = "╰";
@@ -571976,6 +572638,9 @@ var init_status_bar = __esm({
571976
572638
  /** True while resize is in-flight (between first SIGWINCH and debounce settle).
571977
572639
  * Suppresses ALL footer renders to prevent separator debris at intermediate sizes. */
571978
572640
  _resizing = false;
572641
+ /** Last absolute row where the footer box top was painted. Used to clear
572642
+ * stale footer chrome when the terminal grows and the footer moves down. */
572643
+ _lastFooterPaintTop = 0;
571979
572644
  /**
571980
572645
  * Depth-counted content write guard. Incremented by beginContentWrite(),
571981
572646
  * decremented by endContentWrite(). Footer is only redrawn and cursor
@@ -572217,7 +572882,7 @@ var init_status_bar = __esm({
572217
572882
  text += `${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
572218
572883
  width += 1;
572219
572884
  }
572220
- text += `\x1B[1;38;5;${TEXT_PRIMARY}m${PANEL_BG_SEQ}${segment}`;
572885
+ text += `${HEADER_ACCENT_BOLD_FG}${PANEL_BG_SEQ}${segment}`;
572221
572886
  width += segment.length;
572222
572887
  }
572223
572888
  return { text, width, separatorOffsets };
@@ -572283,22 +572948,10 @@ var init_status_bar = __esm({
572283
572948
  return fg2;
572284
572949
  };
572285
572950
  const decorateMenuButton = (cmd, label) => {
572286
- const isBranding = themeMode() === "branding";
572287
- if (isBranding) {
572288
- const BRAND_BG = 37;
572289
- const BRAND_FG = 0;
572290
- return linkify(
572291
- cmd,
572292
- `\x1B[38;5;${BRAND_FG}m\x1B[48;5;${BRAND_BG}m ${label} \x1B[0m${PANEL_BG_SEQ}`
572293
- );
572294
- } else {
572295
- const WHITE_BG = 15;
572296
- const BLACK_FG = 0;
572297
- return linkify(
572298
- cmd,
572299
- `\x1B[38;5;${BLACK_FG}m\x1B[48;5;${WHITE_BG}m ${label} \x1B[0m${PANEL_BG_SEQ}`
572300
- );
572301
- }
572951
+ return linkify(
572952
+ cmd,
572953
+ `${HEADER_BUTTON_FG}${HEADER_BUTTON_BG} ${label} \x1B[0m${PANEL_BG_SEQ}`
572954
+ );
572302
572955
  };
572303
572956
  const renderBtn = (cmd, label) => {
572304
572957
  const fg2 = buttonFg(cmd);
@@ -573776,7 +574429,12 @@ var init_status_bar = __esm({
573776
574429
  /** Handle terminal resize — debounced to prevent separator stacking during drag */
573777
574430
  handleResize() {
573778
574431
  if (!this.active) return;
574432
+ const prevRows = termRows();
574433
+ const prevCols = termCols();
574434
+ setTermSize(process.stdout.rows ?? 24, process.stdout.columns ?? 80);
574435
+ this._rebuildHeaderPanels();
573779
574436
  this._resizing = true;
574437
+ this.renderFooterResizeFrame(prevRows, prevCols);
573780
574438
  if (this._resizeTimer) clearTimeout(this._resizeTimer);
573781
574439
  this._resizeTimer = setTimeout(() => {
573782
574440
  this._resizeTimer = null;
@@ -573805,15 +574463,20 @@ var init_status_bar = __esm({
573805
574463
  for (let row = clearStart; row <= rows; row++) {
573806
574464
  buf += `\x1B[${row};1H\x1B[2K`;
573807
574465
  }
574466
+ const boxInnerP = w - 2;
574467
+ buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_TL3}${BOX_H3.repeat(Math.max(0, boxInnerP))}${BOX_TR3}${RESET4}${PANEL_BG_SEQ}`;
573808
574468
  for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
573809
- const row = pos.inputStartRow + i2;
574469
+ const row = pos.inputStartRow + 1 + i2;
573810
574470
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
573811
- buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${prefix}${inputWrap.lines[i2]}${RESET4}${PANEL_BG_SEQ}`;
574471
+ const lineContent = `${prefix}${inputWrap.lines[i2]}`;
574472
+ buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K`;
574473
+ buf += `${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
574474
+ buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
573812
574475
  }
573813
- const boxInnerP = w - 2;
573814
574476
  buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL3}${BOX_H3.repeat(Math.max(0, boxInnerP))}${BOX_BR3}${RESET4}${PANEL_BG_SEQ}`;
573815
- buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}${PANEL_BG_SEQ}\x1B[?7h\x1B[${pos.inputStartRow};1H`;
574477
+ buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}${PANEL_BG_SEQ}\x1B[?7h\x1B[${pos.inputStartRow + 1};1H`;
573816
574478
  this.termWrite(buf);
574479
+ this.rememberFooterPaint(pos.inputStartRow);
573817
574480
  if (this._bannerRefresh) this._bannerRefresh();
573818
574481
  } else {
573819
574482
  this.applyScrollRegion(true);
@@ -573837,7 +574500,7 @@ var init_status_bar = __esm({
573837
574500
  if (this.writeDepth === 0) {
573838
574501
  this.parkCursorInInput();
573839
574502
  } else {
573840
- this.termWrite(`\x1B[${pos.inputStartRow};1H\x1B[?25l`);
574503
+ this.termWrite(`\x1B[${pos.inputStartRow + 1};1H\x1B[?25l`);
573841
574504
  }
573842
574505
  }
573843
574506
  /** Register a callback that fires AT THE END of _handleResizeImmediate.
@@ -573846,6 +574509,34 @@ var init_status_bar = __esm({
573846
574509
  setOnResizeFinalized(cb) {
573847
574510
  this._onResizeFinalized = cb;
573848
574511
  }
574512
+ /**
574513
+ * Leading-edge resize paint used to keep the footer locked to the new
574514
+ * terminal geometry immediately, matching the header/banner path. The
574515
+ * debounced resize transaction still runs afterward to do the heavier
574516
+ * scrollback cleanup once dragging settles.
574517
+ */
574518
+ renderFooterResizeFrame(prevRows, prevCols) {
574519
+ if (!this.active) return;
574520
+ const rows = termRows();
574521
+ const w = getTermWidth();
574522
+ const previousRows = prevRows > 0 ? prevRows : rows;
574523
+ const widthChanged = prevCols > 0 && prevCols !== termCols();
574524
+ const oldFooterTop = this._lastFooterPaintTop > 0 ? this._lastFooterPaintTop : Math.max(1, previousRows - this._currentFooterHeight + 1);
574525
+ this.updateFooterHeight(w);
574526
+ const pos = this.rowPositions(rows);
574527
+ this.applyScrollRegion();
574528
+ if (widthChanged || oldFooterTop !== pos.inputStartRow) {
574529
+ this.clearFooterTransitionRows(oldFooterTop, pos.inputStartRow);
574530
+ }
574531
+ this.fillContentArea();
574532
+ this.repaintContent();
574533
+ this.refreshTasksPanelAfterLayoutChange();
574534
+ if (this.writeDepth > 0) {
574535
+ this.renderInputRowDuringStream(true);
574536
+ } else {
574537
+ this.renderFooterAndPositionInput(true);
574538
+ }
574539
+ }
573849
574540
  /** Public cursor parking hook for command renderers and resize finalizers. */
573850
574541
  parkCursor() {
573851
574542
  this.parkCursorInInput();
@@ -575022,8 +575713,11 @@ ${CONTENT_BG_SEQ}`);
575022
575713
  * Does NOT set DECSTBM — the scroll region is maintained by
575023
575714
  * applyScrollRegion() and beginContentWrite().
575024
575715
  */
575025
- renderFooterAndPositionInput() {
575026
- if (!this.active || this._resizing) return;
575716
+ rememberFooterPaint(top) {
575717
+ this._lastFooterPaintTop = top;
575718
+ }
575719
+ renderFooterAndPositionInput(force = false) {
575720
+ if (!this.active || this._resizing && !force) return;
575027
575721
  const rows = termRows();
575028
575722
  const w = getTermWidth();
575029
575723
  const oldFooterTop = Math.max(1, rows - this._currentFooterHeight + 1);
@@ -575081,6 +575775,7 @@ ${CONTENT_BG_SEQ}`);
575081
575775
  buf += `\x1B[${cursorTermRow};${inputWrap.cursorCol}H${CURSOR_BLINK_BLOCK}\x1B[?25h`;
575082
575776
  }
575083
575777
  this.termWrite(buf);
575778
+ this.rememberFooterPaint(pos.inputStartRow);
575084
575779
  }
575085
575780
  /**
575086
575781
  * Redraw footer while preserving the current cursor position.
@@ -575094,13 +575789,13 @@ ${CONTENT_BG_SEQ}`);
575094
575789
  * IMPORTANT: Does NOT set DECSTBM here — setting the scroll region between
575095
575790
  * cursor save/restore corrupts the restore position on many terminals.
575096
575791
  */
575097
- renderFooterPreserveCursor() {
575098
- if (!this.active || this._resizing) return;
575792
+ renderFooterPreserveCursor(force = false) {
575793
+ if (!this.active || this._resizing && !force) return;
575099
575794
  if (this.footerHeightChanged()) {
575100
575795
  if (this.writeDepth > 0) {
575101
- this.renderInputRowDuringStream();
575796
+ this.renderInputRowDuringStream(force);
575102
575797
  } else {
575103
- this.renderFooterAndPositionInput();
575798
+ this.renderFooterAndPositionInput(force);
575104
575799
  }
575105
575800
  return;
575106
575801
  }
@@ -575128,6 +575823,7 @@ ${CONTENT_BG_SEQ}`);
575128
575823
  buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}${PANEL_BG_SEQ}\x1B[?7h\x1B8` + // DEC restore cursor
575129
575824
  (this.writeDepth === 0 ? `${CURSOR_BLINK_BLOCK}\x1B[?25h` : "");
575130
575825
  this.termWrite(buf);
575826
+ this.rememberFooterPaint(pos.inputStartRow);
575131
575827
  if (pos.tabBarRow > 0) this.renderAgentTabs();
575132
575828
  }
575133
575829
  /**
@@ -575135,8 +575831,8 @@ ${CONTENT_BG_SEQ}`);
575135
575831
  * Uses DEC save/restore cursor so the streaming cursor position is preserved.
575136
575832
  * If footer height changed, also updates DECSTBM and redraws full footer.
575137
575833
  */
575138
- renderInputRowDuringStream() {
575139
- if (!this.active || this._resizing || !this.inputStateProvider) return;
575834
+ renderInputRowDuringStream(force = false) {
575835
+ if (!this.active || this._resizing && !force || !this.inputStateProvider) return;
575140
575836
  const rows = termRows();
575141
575837
  const w = getTermWidth();
575142
575838
  const oldFooterHeight = this._currentFooterHeight;
@@ -575201,6 +575897,7 @@ ${CONTENT_BG_SEQ}`);
575201
575897
  }
575202
575898
  const w1 = this._origWrite ?? this._trueStdoutWrite;
575203
575899
  w1.call(process.stdout, buf);
575900
+ this.rememberFooterPaint(pos.inputStartRow);
575204
575901
  if (heightDelta !== 0) this.refreshTasksPanelAfterLayoutChange();
575205
575902
  } else {
575206
575903
  let buf = "\x1B7\x1B[?25l\x1B[?7l";
@@ -575232,6 +575929,7 @@ ${CONTENT_BG_SEQ}`);
575232
575929
  buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}${PANEL_BG_SEQ}`;
575233
575930
  buf += "\x1B[?7h\x1B8\x1B[?25l";
575234
575931
  this.termWrite(buf);
575932
+ this.rememberFooterPaint(pos.inputStartRow);
575235
575933
  }
575236
575934
  }
575237
575935
  /**
@@ -580408,7 +581106,7 @@ var init_platforms = __esm({
580408
581106
 
580409
581107
  // packages/cli/src/tui/workspace-explorer.ts
580410
581108
  import { existsSync as existsSync93, readdirSync as readdirSync31, readFileSync as readFileSync75, statSync as statSync34 } from "node:fs";
580411
- import { basename as basename18, extname as extname12, join as join108, relative as relative10, resolve as resolve38 } from "node:path";
581109
+ import { basename as basename19, extname as extname12, join as join108, relative as relative10, resolve as resolve38 } from "node:path";
580412
581110
  function exploreWorkspace(root, options2 = {}) {
580413
581111
  const query = (options2.query ?? "").trim().toLowerCase();
580414
581112
  const maxResults = options2.maxResults ?? 80;
@@ -580525,7 +581223,7 @@ function classifyWorkspaceFile(path12) {
580525
581223
  if (lower.includes(".test.") || lower.includes(".spec.") || lower.includes("/tests/")) return "test";
580526
581224
  if (SOURCE_EXT.has(ext)) return "source";
580527
581225
  if (DOC_EXT2.has(ext)) return "doc";
580528
- if (CONFIG_EXT.has(ext) || basename18(lower).startsWith("dockerfile")) return "config";
581226
+ if (CONFIG_EXT.has(ext) || basename19(lower).startsWith("dockerfile")) return "config";
580529
581227
  if (ASSET_EXT.has(ext)) return "asset";
580530
581228
  return "other";
580531
581229
  }
@@ -580537,7 +581235,7 @@ function scoreWorkspaceFile(entry, query) {
580537
581235
  if (entry.path.startsWith("packages/cli/src/")) score += 5;
580538
581236
  if (query) {
580539
581237
  const lower = entry.path.toLowerCase();
580540
- const name10 = basename18(lower);
581238
+ const name10 = basename19(lower);
580541
581239
  if (name10.startsWith(query)) score += 20;
580542
581240
  if (lower.includes(`/${query}`)) score += 12;
580543
581241
  if (lower.includes(query)) score += 8;
@@ -591992,6 +592690,9 @@ async function handleSlashCommand(input, ctx3) {
591992
592690
  case "parallel":
591993
592691
  await handleParallel(arg, ctx3);
591994
592692
  return "handled";
592693
+ case "ollama":
592694
+ await handleOllama(arg, ctx3);
592695
+ return "handled";
591995
592696
  case "mcp":
591996
592697
  case "mcps":
591997
592698
  await handleMcp(arg, ctx3);
@@ -598042,14 +598743,14 @@ async function handleVoiceMenu(ctx3, save2, hasLocal) {
598042
598743
  if (!jsonDrop.confirmed || !jsonDrop.path) {
598043
598744
  continue;
598044
598745
  }
598045
- const { basename: basename30, join: pathJoin } = await import("node:path");
598746
+ const { basename: basename31, join: pathJoin } = await import("node:path");
598046
598747
  const {
598047
598748
  copyFileSync: copyFileSync5,
598048
598749
  mkdirSync: mkdirSync81,
598049
598750
  existsSync: exists2
598050
598751
  } = await import("node:fs");
598051
598752
  const { homedir: homedir53 } = await import("node:os");
598052
- const modelName = basename30(onnxDrop.path, ".onnx").replace(
598753
+ const modelName = basename31(onnxDrop.path, ".onnx").replace(
598053
598754
  /[^a-zA-Z0-9_-]/g,
598054
598755
  "-"
598055
598756
  );
@@ -598436,7 +599137,7 @@ async function handleVoiceList(ctx3, focusFilename) {
598436
599137
  copyFileSync: cpf,
598437
599138
  mkdirSync: mkd
598438
599139
  } = __require("node:fs");
598439
- const { basename: basename30, join: pjoin } = __require("node:path");
599140
+ const { basename: basename31, join: pjoin } = __require("node:path");
598440
599141
  if (!fe(src2)) {
598441
599142
  renderError(`File not found: ${src2}`);
598442
599143
  helpers.render();
@@ -598449,7 +599150,7 @@ async function handleVoiceList(ctx3, focusFilename) {
598449
599150
  "clone-refs"
598450
599151
  );
598451
599152
  mkd(refsDir, { recursive: true });
598452
- const destName = basename30(src2);
599153
+ const destName = basename31(src2);
598453
599154
  const dest = pjoin(refsDir, destName);
598454
599155
  cpf(src2, dest);
598455
599156
  renderInfo(`Imported "${destName}" → ${dest}`);
@@ -599582,6 +600283,113 @@ ${escapedContent}EOF'`, {
599582
600283
  }
599583
600284
  }
599584
600285
  }
600286
+ async function handleOllama(arg, ctx3) {
600287
+ const parts = arg.trim().split(/\s+/).filter(Boolean);
600288
+ const subcommand = parts[0] ?? "status";
600289
+ if (!["cleanup", "clean", "processes", "scan", "status"].includes(subcommand)) {
600290
+ renderInfo("Usage: /ollama cleanup [--dry-run|--execute] [--no-inference]");
600291
+ return;
600292
+ }
600293
+ const execute = parts.includes("--execute") || parts.includes("--yes") || parts.includes("--kill");
600294
+ const dryRun = parts.includes("--dry-run") || !execute;
600295
+ const useInference = parts.includes("--no-inference") ? false : "auto";
600296
+ const scanOnly = subcommand === "processes" || subcommand === "scan" || subcommand === "status";
600297
+ try {
600298
+ const orchestrator = await Promise.resolve().then(() => (init_dist8(), dist_exports3));
600299
+ const poolConfig = orchestrator.resolveDefaultPoolConfig();
600300
+ let poolStatus = null;
600301
+ try {
600302
+ if (orchestrator.shouldUseOllamaPoolForBaseUrl(poolConfig.baseInstanceUrl)) {
600303
+ poolStatus = await orchestrator.getOllamaPool({ baseInstanceUrl: poolConfig.baseInstanceUrl }).status();
600304
+ }
600305
+ } catch {
600306
+ poolStatus = null;
600307
+ }
600308
+ const report2 = scanOnly ? await orchestrator.scanOllamaProcesses({
600309
+ baseInstanceUrl: poolConfig.baseInstanceUrl,
600310
+ poolPortStart: poolConfig.spawnPortStart,
600311
+ poolStatus
600312
+ }) : await orchestrator.cleanupStaleOllamaProcesses({
600313
+ dryRun,
600314
+ useInference,
600315
+ baseInstanceUrl: poolConfig.baseInstanceUrl,
600316
+ poolPortStart: poolConfig.spawnPortStart,
600317
+ poolStatus
600318
+ });
600319
+ renderOllamaCleanupReport(report2, { scanOnly, dryRun });
600320
+ } catch (err) {
600321
+ renderError(`Ollama cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
600322
+ }
600323
+ }
600324
+ function renderOllamaCleanupReport(report2, opts) {
600325
+ const decisionByPid = new Map(report2.decisions.map((d2) => [d2.pid, d2]));
600326
+ safeLog("");
600327
+ safeLog(` ${c3.bold("Ollama Pool Process Hygiene")}`);
600328
+ safeLog(` ${c3.dim("Base:")} ${report2.baseInstanceUrl}`);
600329
+ safeLog(` ${c3.dim("Protected ports:")} ${report2.protectedPorts.join(", ")}`);
600330
+ safeLog(` ${c3.dim("Pool ports:")} ${report2.poolPortStart}+`);
600331
+ if (report2.systemdOllamaMainPid) {
600332
+ safeLog(` ${c3.dim("systemd ollama.service PID:")} ${report2.systemdOllamaMainPid}`);
600333
+ }
600334
+ if (typeof report2.usedInference === "boolean") {
600335
+ safeLog(` ${c3.dim("Inference:")} ${report2.usedInference ? c3.green("used") : c3.yellow("fallback/programmatic")}`);
600336
+ if (report2.inferenceFallbackReason) {
600337
+ safeLog(` ${c3.dim("Inference fallback:")} ${report2.inferenceFallbackReason}`);
600338
+ }
600339
+ }
600340
+ safeLog("");
600341
+ if (report2.processes.length === 0) {
600342
+ safeLog(` ${c3.green("No ollama serve processes found outside normal service discovery.")}`);
600343
+ } else {
600344
+ safeLog(` ${c3.dim("PID PORTS CPU AGE ACTION CLASSIFICATION")}`);
600345
+ safeLog(` ${c3.dim("-".repeat(78))}`);
600346
+ for (const proc of report2.processes) {
600347
+ const d2 = decisionByPid.get(proc.pid);
600348
+ const action = d2?.action === "terminate" ? c3.red(opts.scanOnly || opts.dryRun ? "would kill" : "kill") : c3.green("keep");
600349
+ const ports = proc.ports.length ? proc.ports.join(",") : "-";
600350
+ const cpu = proc.cpuPct === null ? "?" : proc.cpuPct.toFixed(1);
600351
+ const age = formatShortMs(proc.elapsedMs);
600352
+ safeLog(
600353
+ ` ${String(proc.pid).padEnd(8)} ${ports.padEnd(12)} ${cpu.padStart(5)} ${age.padEnd(9)} ${stripAnsiPad(action, 11)} ${d2?.classification ?? "unknown"}`
600354
+ );
600355
+ if (d2?.reasons?.length) {
600356
+ safeLog(` ${c3.dim(d2.reasons.join("; "))}`);
600357
+ }
600358
+ }
600359
+ }
600360
+ if (report2.terminated && report2.terminated.length > 0) {
600361
+ safeLog("");
600362
+ for (const item of report2.terminated) {
600363
+ const verb = item.signal === "dry-run" ? "Would terminate" : "Terminated";
600364
+ safeLog(` ${verb} PID ${item.pid} (${item.signal}${item.verified ? ", verified" : ""})`);
600365
+ }
600366
+ }
600367
+ if (report2.errors && report2.errors.length > 0) {
600368
+ safeLog("");
600369
+ for (const err of report2.errors) {
600370
+ safeLog(` ${c3.red(`PID ${err.pid}: ${err.error}`)}`);
600371
+ }
600372
+ }
600373
+ if (!opts.scanOnly && opts.dryRun) {
600374
+ safeLog("");
600375
+ safeLog(` ${c3.dim("Dry run only. Execute with:")} ${c3.cyan("/ollama cleanup --execute")}`);
600376
+ }
600377
+ safeLog("");
600378
+ }
600379
+ function formatShortMs(ms) {
600380
+ if (ms === null) return "?";
600381
+ const sec = Math.max(0, Math.floor(ms / 1e3));
600382
+ if (sec < 60) return `${sec}s`;
600383
+ const min = Math.floor(sec / 60);
600384
+ if (min < 60) return `${min}m`;
600385
+ const hr = Math.floor(min / 60);
600386
+ if (hr < 48) return `${hr}h`;
600387
+ return `${Math.floor(hr / 24)}d`;
600388
+ }
600389
+ function stripAnsiPad(value2, width) {
600390
+ const raw = value2.replace(/\x1b\[[0-9;]*m/g, "");
600391
+ return value2 + " ".repeat(Math.max(0, width - raw.length));
600392
+ }
599585
600393
  async function handleMcp(subcommand, ctx3) {
599586
600394
  const manager = ctx3.getMcpManager?.();
599587
600395
  if (!manager) {
@@ -601775,7 +602583,7 @@ var init_commands = __esm({
601775
602583
 
601776
602584
  // packages/cli/src/tui/project-context.ts
601777
602585
  import { existsSync as existsSync102, readFileSync as readFileSync82, readdirSync as readdirSync34 } from "node:fs";
601778
- import { join as join115, basename as basename19 } from "node:path";
602586
+ import { join as join115, basename as basename20 } from "node:path";
601779
602587
  import { execSync as execSync53 } from "node:child_process";
601780
602588
  import { homedir as homedir39 } from "node:os";
601781
602589
  function getModelTier(modelName) {
@@ -601856,7 +602664,7 @@ function loadMemoryContext(repoRoot) {
601856
602664
  try {
601857
602665
  const raw = readFileSync82(join115(dir, file), "utf-8");
601858
602666
  const entries = JSON.parse(raw);
601859
- const topic = basename19(file, ".json");
602667
+ const topic = basename20(file, ".json");
601860
602668
  for (const [k, v] of Object.entries(entries)) {
601861
602669
  if (!v?.value) continue;
601862
602670
  all2.push({ topic, key: k, value: String(v.value), scope, ts: v.timestamp ?? "" });
@@ -602120,7 +602928,7 @@ __export(visual_identity_association_exports, {
602120
602928
  formatVisualIdentityAssociationContext: () => formatVisualIdentityAssociationContext,
602121
602929
  stageVisualIdentityAssertion: () => stageVisualIdentityAssertion
602122
602930
  });
602123
- import { basename as basename20 } from "node:path";
602931
+ import { basename as basename21 } from "node:path";
602124
602932
  function normalizePersonName(name10) {
602125
602933
  return name10.trim().toLowerCase().replace(/\s+/g, " ");
602126
602934
  }
@@ -602442,7 +603250,7 @@ async function associateVisualIdentityFromImage(options2) {
602442
603250
  relation: "same_person_candidate",
602443
603251
  confidence: match.confidence,
602444
603252
  assertedBy: { id: "visual_memory", displayName: "visual_memory", isBot: true },
602445
- note: `Prior enrolled visual-memory face match for ${basename20(options2.imagePath)}`
603253
+ note: `Prior enrolled visual-memory face match for ${basename21(options2.imagePath)}`
602446
603254
  }]
602447
603255
  });
602448
603256
  if (result2.episodeId) committedEpisodeIds.push(result2.episodeId);
@@ -602487,7 +603295,7 @@ async function associateVisualIdentityFromImage(options2) {
602487
603295
  relation: "depicts",
602488
603296
  confidence: item.confidence,
602489
603297
  assertedBy: item.sender || options2.sender,
602490
- note: item.note || `Applied explicit pending identity assertion to ${basename20(options2.imagePath)}`
603298
+ note: item.note || `Applied explicit pending identity assertion to ${basename21(options2.imagePath)}`
602491
603299
  }]
602492
603300
  });
602493
603301
  if (result2.episodeId) committedEpisodeIds.push(result2.episodeId);
@@ -602545,7 +603353,7 @@ var init_visual_identity_association = __esm({
602545
603353
 
602546
603354
  // packages/cli/src/tui/identity-memory-tool.ts
602547
603355
  import { existsSync as existsSync103 } from "node:fs";
602548
- import { basename as basename21, extname as extname14, resolve as resolve41 } from "node:path";
603356
+ import { basename as basename22, extname as extname14, resolve as resolve41 } from "node:path";
602549
603357
  function personKey2(name10) {
602550
603358
  return `person:${name10.trim().toLowerCase().replace(/\s+/g, " ")}`;
602551
603359
  }
@@ -602614,7 +603422,7 @@ async function resolveMediaFromArgs(args, opts) {
602614
603422
  path: path12,
602615
603423
  media,
602616
603424
  modality: inferModality(media),
602617
- label: basename21(path12)
603425
+ label: basename22(path12)
602618
603426
  };
602619
603427
  }
602620
603428
  function edgeDirection(edge, nodeId, otherText) {
@@ -602772,7 +603580,7 @@ var init_identity_memory_tool = __esm({
602772
603580
  } else if (shouldEnrollFace) {
602773
603581
  faceLine = "face enrollment: skipped because no resolved image path was available";
602774
603582
  }
602775
- const mediaLine = resolvedMedia ? `media: ${resolvedMedia.label || basename21(resolvedMedia.path)} (${resolvedMedia.path})` : "media: none; stored as scoped textual identity evidence only";
603583
+ const mediaLine = resolvedMedia ? `media: ${resolvedMedia.label || basename22(resolvedMedia.path)} (${resolvedMedia.path})` : "media: none; stored as scoped textual identity evidence only";
602776
603584
  const output = [
602777
603585
  `Stored identity evidence for ${name10}.`,
602778
603586
  `relation: ${relation}`,
@@ -603713,7 +604521,7 @@ var init_banner = __esm({
603713
604521
 
603714
604522
  // packages/cli/src/tui/carousel-descriptors.ts
603715
604523
  import { existsSync as existsSync105, readFileSync as readFileSync84, writeFileSync as writeFileSync53, mkdirSync as mkdirSync59, readdirSync as readdirSync35 } from "node:fs";
603716
- import { join as join118, basename as basename22 } from "node:path";
604524
+ import { join as join118, basename as basename23 } from "node:path";
603717
604525
  function loadToolProfile(repoRoot) {
603718
604526
  const filePath = join118(repoRoot, OMNIUS_DIR, "context", TOOL_PROFILE_FILE);
603719
604527
  try {
@@ -603809,7 +604617,7 @@ function generateDescriptors(repoRoot) {
603809
604617
  extractFromSessions(repoRoot, tags);
603810
604618
  extractFromMemory(repoRoot, tags);
603811
604619
  extractFromToolProfile(profile, tags);
603812
- const repoName2 = basename22(repoRoot);
604620
+ const repoName2 = basename23(repoRoot);
603813
604621
  if (repoName2 && !tags.includes(repoName2)) {
603814
604622
  tags.push(repoName2);
603815
604623
  }
@@ -605019,7 +605827,7 @@ var init_promptLoader3 = __esm({
605019
605827
 
605020
605828
  // packages/cli/src/tui/dream-engine.ts
605021
605829
  import { mkdirSync as mkdirSync61, writeFileSync as writeFileSync54, readFileSync as readFileSync86, existsSync as existsSync107, readdirSync as readdirSync36 } from "node:fs";
605022
- import { join as join121, basename as basename23 } from "node:path";
605830
+ import { join as join121, basename as basename24 } from "node:path";
605023
605831
  import { execSync as execSync54 } from "node:child_process";
605024
605832
  function setDreamWriteContent(fn) {
605025
605833
  _dreamWriteContent = fn;
@@ -605232,7 +606040,7 @@ var init_dream_engine = __esm({
605232
606040
  const rawPath = String(args["path"] ?? "");
605233
606041
  const content = String(args["content"] ?? "");
605234
606042
  if (!rawPath) return { success: false, output: "", error: "path is required", durationMs: Date.now() - start2 };
605235
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/autoresearch") ? join121(this.autoresearchDir, basename23(rawPath)) : join121(this.autoresearchDir, rawPath);
606043
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/autoresearch") ? join121(this.autoresearchDir, basename24(rawPath)) : join121(this.autoresearchDir, rawPath);
605236
606044
  if (!targetPath.startsWith(this.autoresearchDir)) {
605237
606045
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .omnius/autoresearch/", durationMs: Date.now() - start2 };
605238
606046
  }
@@ -605267,7 +606075,7 @@ var init_dream_engine = __esm({
605267
606075
  const rawPath = String(args["path"] ?? "");
605268
606076
  const oldStr = String(args["old_string"] ?? "");
605269
606077
  const newStr = String(args["new_string"] ?? "");
605270
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/autoresearch") ? join121(this.autoresearchDir, basename23(rawPath)) : join121(this.autoresearchDir, rawPath);
606078
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/autoresearch") ? join121(this.autoresearchDir, basename24(rawPath)) : join121(this.autoresearchDir, rawPath);
605271
606079
  if (!targetPath.startsWith(this.autoresearchDir)) {
605272
606080
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .omnius/autoresearch/", durationMs: Date.now() - start2 };
605273
606081
  }
@@ -605320,7 +606128,7 @@ var init_dream_engine = __esm({
605320
606128
  const rawPath = String(args["path"] ?? "");
605321
606129
  const content = String(args["content"] ?? "");
605322
606130
  if (!rawPath) return { success: false, output: "", error: "path is required", durationMs: Date.now() - start2 };
605323
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/dreams") ? join121(this.dreamsDir, basename23(rawPath)) : join121(this.dreamsDir, rawPath);
606131
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/dreams") ? join121(this.dreamsDir, basename24(rawPath)) : join121(this.dreamsDir, rawPath);
605324
606132
  if (!targetPath.startsWith(this.dreamsDir)) {
605325
606133
  return { success: false, output: "", error: "Dream mode: writes are confined to .omnius/dreams/", durationMs: Date.now() - start2 };
605326
606134
  }
@@ -605355,7 +606163,7 @@ var init_dream_engine = __esm({
605355
606163
  const rawPath = String(args["path"] ?? "");
605356
606164
  const oldStr = String(args["old_string"] ?? "");
605357
606165
  const newStr = String(args["new_string"] ?? "");
605358
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/dreams") ? join121(this.dreamsDir, basename23(rawPath)) : join121(this.dreamsDir, rawPath);
606166
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".omnius/dreams") ? join121(this.dreamsDir, basename24(rawPath)) : join121(this.dreamsDir, rawPath);
605359
606167
  if (!targetPath.startsWith(this.dreamsDir)) {
605360
606168
  return { success: false, output: "", error: "Dream mode: edits are confined to .omnius/dreams/", durationMs: Date.now() - start2 };
605361
606169
  }
@@ -606952,7 +607760,7 @@ var init_bless_engine = __esm({
606952
607760
 
606953
607761
  // packages/cli/src/tui/dmn-engine.ts
606954
607762
  import { existsSync as existsSync108, readFileSync as readFileSync87, writeFileSync as writeFileSync55, mkdirSync as mkdirSync62, readdirSync as readdirSync37, unlinkSync as unlinkSync19 } from "node:fs";
606955
- import { join as join122, basename as basename24 } from "node:path";
607763
+ import { join as join122, basename as basename25 } from "node:path";
606956
607764
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
606957
607765
  const competenceReport = competence.length > 0 ? competence.map((c9) => {
606958
607766
  const rate = c9.attempts > 0 ? Math.round(c9.successes / c9.attempts * 100) : 0;
@@ -607497,9 +608305,9 @@ OUTPUT: Call task_complete with JSON:
607497
608305
  confidence: this.extractConfidence(gateResult)
607498
608306
  });
607499
608307
  workspace.evidenceAccumulated = this.extractConfidence(gateResult);
607500
- const decision = gateResult.includes('"GO"') || gateResult.toLowerCase().includes("decision.*go") ? "go" : "nogo";
608308
+ const decision2 = gateResult.includes('"GO"') || gateResult.toLowerCase().includes("decision.*go") ? "go" : "nogo";
607501
608309
  const evScore = Math.round(workspace.evidenceAccumulated * 100);
607502
- const voiceFinal = decision === "go" ? `Decision: GO (evidence ${evScore}%). I know what to do next. Let's move.` : `Decision: NOGO (evidence ${evScore}%). Not enough clarity to act. Better to rest and gather more information.`;
608310
+ const voiceFinal = decision2 === "go" ? `Decision: GO (evidence ${evScore}%). I know what to do next. Let's move.` : `Decision: NOGO (evidence ${evScore}%). Not enough clarity to act. Better to rest and gather more information.`;
607503
608311
  workspace.innerVoice.push(voiceFinal);
607504
608312
  onEvent?.({
607505
608313
  type: "status",
@@ -607703,7 +608511,7 @@ OUTPUT: Call task_complete with JSON:
607703
608511
  try {
607704
608512
  const files = readdirSync37(dir).filter((f2) => f2.endsWith(".json"));
607705
608513
  for (const f2 of files) {
607706
- const topic = basename24(f2, ".json");
608514
+ const topic = basename25(f2, ".json");
607707
608515
  if (!topics.includes(topic)) topics.push(topic);
607708
608516
  }
607709
608517
  } catch {
@@ -607757,7 +608565,7 @@ OUTPUT: Call task_complete with JSON:
607757
608565
 
607758
608566
  // packages/cli/src/tui/snr-engine.ts
607759
608567
  import { existsSync as existsSync109, readdirSync as readdirSync38, readFileSync as readFileSync88 } from "node:fs";
607760
- import { join as join123, basename as basename25 } from "node:path";
608568
+ import { join as join123, basename as basename26 } from "node:path";
607761
608569
  function computeDPrime(signalScores, noiseScores) {
607762
608570
  if (signalScores.length === 0 || noiseScores.length === 0) return 0;
607763
608571
  const mean = (arr) => arr.reduce((s2, v) => s2 + v, 0) / arr.length;
@@ -608051,7 +608859,7 @@ Call task_complete with the JSON array when done.`,
608051
608859
  try {
608052
608860
  const files = readdirSync38(dir).filter((f2) => f2.endsWith(".json"));
608053
608861
  for (const f2 of files) {
608054
- const topic = basename25(f2, ".json");
608862
+ const topic = basename26(f2, ".json");
608055
608863
  if (topics.length > 0 && !topics.includes(topic)) continue;
608056
608864
  try {
608057
608865
  const data = JSON.parse(readFileSync88(join123(dir, f2), "utf-8"));
@@ -609534,7 +610342,7 @@ import {
609534
610342
  } from "node:fs";
609535
610343
  import { mkdir as mkdir19 } from "node:fs/promises";
609536
610344
  import {
609537
- basename as basename26,
610345
+ basename as basename27,
609538
610346
  dirname as dirname34,
609539
610347
  extname as extname15,
609540
610348
  isAbsolute as isAbsolute7,
@@ -609768,7 +610576,7 @@ function guardPath(root, rawPath) {
609768
610576
  error: `Path escapes the public creative workspace. Use a relative path under ${rootAbs}.`
609769
610577
  };
609770
610578
  }
609771
- if (basename26(abs) === MANIFEST_FILE) {
610579
+ if (basename27(abs) === MANIFEST_FILE) {
609772
610580
  return { ok: false, error: "The creative workspace manifest is internal and cannot be edited." };
609773
610581
  }
609774
610582
  return { ok: true, path: { abs, rel } };
@@ -609860,7 +610668,7 @@ function rememberCreated(root, absPath) {
609860
610668
  manifest.objects[rel] = {
609861
610669
  logicalRel: rel,
609862
610670
  storedRel,
609863
- originalName: basename26(guarded.path.abs),
610671
+ originalName: basename27(guarded.path.abs),
609864
610672
  prefixBytes: prefix.length,
609865
610673
  encrypted: true,
609866
610674
  key: key.toString("base64"),
@@ -609911,7 +610719,7 @@ function materializeTelegramCreativeArtifactForSend(root, rawPath) {
609911
610719
  }
609912
610720
  const stageDir = join124(rootAbs, SEND_DIR, `${Date.now()}-${randomBytes21(8).toString("hex")}`);
609913
610721
  mkdirSync63(stageDir, { recursive: true });
609914
- const staged = join124(stageDir, object.originalName || basename26(rel));
610722
+ const staged = join124(stageDir, object.originalName || basename27(rel));
609915
610723
  writeFileSync56(staged, payload);
609916
610724
  return {
609917
610725
  ok: true,
@@ -610222,23 +611030,23 @@ var init_stimulation = __esm({
610222
611030
  context: this.formatContext(input.channelId)
610223
611031
  };
610224
611032
  }
610225
- applyAgentDecision(channelId, decision, nowMs = Date.now()) {
611033
+ applyAgentDecision(channelId, decision2, nowMs = Date.now()) {
610226
611034
  const state = this.stateFor(channelId, nowMs);
610227
- if (Number.isFinite(decision.attentionScore)) {
610228
- state.attention = clamp017(Number(decision.attentionScore));
610229
- } else if (Number.isFinite(decision.attentionDelta)) {
610230
- state.attention = clamp017(state.attention + Number(decision.attentionDelta));
611035
+ if (Number.isFinite(decision2.attentionScore)) {
611036
+ state.attention = clamp017(Number(decision2.attentionScore));
611037
+ } else if (Number.isFinite(decision2.attentionDelta)) {
611038
+ state.attention = clamp017(state.attention + Number(decision2.attentionDelta));
610231
611039
  } else {
610232
- state.attention = clamp017(state.attention + (decision.shouldReply ? 0.22 : -0.1));
611040
+ state.attention = clamp017(state.attention + (decision2.shouldReply ? 0.22 : -0.1));
610233
611041
  }
610234
- if (decision.phase) {
610235
- state.attention = Math.max(state.attention, PHASE_FLOORS[decision.phase]);
610236
- state.phase = decision.phase;
611042
+ if (decision2.phase) {
611043
+ state.attention = Math.max(state.attention, PHASE_FLOORS[decision2.phase]);
611044
+ state.phase = decision2.phase;
610237
611045
  } else {
610238
611046
  state.phase = phaseFromAttention(state.attention);
610239
611047
  }
610240
- state.consecutiveNoReply = decision.shouldReply ? 0 : state.consecutiveNoReply + 1;
610241
- state.nextAnalysisAfterMessages = Number.isFinite(decision.nextAnalysisAfterMessages) ? Math.max(1, Math.floor(Number(decision.nextAnalysisAfterMessages))) : void 0;
611048
+ state.consecutiveNoReply = decision2.shouldReply ? 0 : state.consecutiveNoReply + 1;
611049
+ state.nextAnalysisAfterMessages = Number.isFinite(decision2.nextAnalysisAfterMessages) ? Math.max(1, Math.floor(Number(decision2.nextAnalysisAfterMessages))) : void 0;
610242
611050
  state.lastAnalysisAtMs = nowMs;
610243
611051
  state.messagesSinceAnalysis = 0;
610244
611052
  state.updatedAtMs = nowMs;
@@ -611324,7 +612132,7 @@ function buildTelegramReflectionExtractionPrompt(options2) {
611324
612132
  episodes || "none"
611325
612133
  ].join("\n");
611326
612134
  }
611327
- function parseJsonObject(raw) {
612135
+ function parseJsonObject2(raw) {
611328
612136
  const text = raw.trim();
611329
612137
  if (!text) return null;
611330
612138
  const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i)?.[1]?.trim();
@@ -611338,7 +612146,7 @@ function parseJsonObject(raw) {
611338
612146
  }
611339
612147
  }
611340
612148
  function parseTelegramReflectionExtraction(raw) {
611341
- const parsed = parseJsonObject(raw);
612149
+ const parsed = parseJsonObject2(raw);
611342
612150
  if (!parsed) return null;
611343
612151
  const tags = Array.isArray(parsed.tags) ? parsed.tags.map((item) => {
611344
612152
  const obj = item;
@@ -612376,7 +613184,7 @@ var init_vision_ingress = __esm({
612376
613184
 
612377
613185
  // packages/cli/src/tui/telegram-bridge.ts
612378
613186
  import { mkdirSync as mkdirSync65, existsSync as existsSync113, unlinkSync as unlinkSync22, readdirSync as readdirSync40, statSync as statSync39, statfsSync as statfsSync5, readFileSync as readFileSync92, writeFileSync as writeFileSync59, appendFileSync as appendFileSync9 } from "node:fs";
612379
- import { join as join127, resolve as resolve43, basename as basename27, relative as relative13, isAbsolute as isAbsolute8, extname as extname16 } from "node:path";
613187
+ import { join as join127, resolve as resolve43, basename as basename28, relative as relative13, isAbsolute as isAbsolute8, extname as extname16 } from "node:path";
612380
613188
  import { homedir as homedir40 } from "node:os";
612381
613189
  import { writeFile as writeFileAsync } from "node:fs/promises";
612382
613190
  import { createHash as createHash24, randomBytes as randomBytes22, randomInt } from "node:crypto";
@@ -614631,25 +615439,25 @@ External acquisition contract:
614631
615439
  this.subAgentViewCallbacks.onStatus(viewId, "running");
614632
615440
  return viewId;
614633
615441
  }
614634
- writeTelegramAttentionDecision(viewId, decision) {
614635
- const route = decision.shouldReply ? `reply via ${decision.route}` : "silent";
615442
+ writeTelegramAttentionDecision(viewId, decision2) {
615443
+ const route = decision2.shouldReply ? `reply via ${decision2.route}` : "silent";
614636
615444
  const attention = [
614637
- decision.attentionState ? `state=${decision.attentionState}` : "",
614638
- decision.attentionDelta !== void 0 ? `delta=${decision.attentionDelta.toFixed(2)}` : "",
614639
- decision.attentionScore !== void 0 ? `score=${decision.attentionScore.toFixed(2)}` : ""
615445
+ decision2.attentionState ? `state=${decision2.attentionState}` : "",
615446
+ decision2.attentionDelta !== void 0 ? `delta=${decision2.attentionDelta.toFixed(2)}` : "",
615447
+ decision2.attentionScore !== void 0 ? `score=${decision2.attentionScore.toFixed(2)}` : ""
614640
615448
  ].filter(Boolean).join(", ");
614641
615449
  const cadence = [
614642
- decision.nextCheckAfterMessages !== void 0 ? `after ${decision.nextCheckAfterMessages} message(s)` : ""
615450
+ decision2.nextCheckAfterMessages !== void 0 ? `after ${decision2.nextCheckAfterMessages} message(s)` : ""
614643
615451
  ].filter(Boolean).join(" or ");
614644
615452
  const lines = [
614645
- `decision: ${route} (${decision.source}, confidence ${decision.confidence.toFixed(2)})`,
615453
+ `decision: ${route} (${decision2.source}, confidence ${decision2.confidence.toFixed(2)})`,
614646
615454
  attention ? `attention: ${attention}` : "",
614647
- `reason: ${decision.reason}`,
614648
- decision.diagnosticNote ? `router diagnostic: ${decision.diagnosticNote}` : "",
614649
- decision.silentDisposition ? `silent disposition: ${decision.silentDisposition}` : "",
614650
- decision.mentalNote ? `mental note: ${decision.mentalNote}` : "",
614651
- decision.memoryNote ? `memory note: ${decision.memoryNote}` : "",
614652
- decision.relationshipNote ? `relationship note: ${decision.relationshipNote}` : "",
615455
+ `reason: ${decision2.reason}`,
615456
+ decision2.diagnosticNote ? `router diagnostic: ${decision2.diagnosticNote}` : "",
615457
+ decision2.silentDisposition ? `silent disposition: ${decision2.silentDisposition}` : "",
615458
+ decision2.mentalNote ? `mental note: ${decision2.mentalNote}` : "",
615459
+ decision2.memoryNote ? `memory note: ${decision2.memoryNote}` : "",
615460
+ decision2.relationshipNote ? `relationship note: ${decision2.relationshipNote}` : "",
614653
615461
  cadence ? `next attention sample: ${cadence}` : ""
614654
615462
  ].filter(Boolean);
614655
615463
  if (viewId && this.subAgentViewCallbacks) {
@@ -614658,15 +615466,15 @@ External acquisition contract:
614658
615466
  this.subAgentViewCallbacks.onComplete(viewId);
614659
615467
  }
614660
615468
  }
614661
- mirrorTelegramAttentionDecision(msg, decision) {
614662
- const route = decision.shouldReply ? `reply via ${decision.route}` : "silent";
614663
- const primary = `attention decision: ${route} (${decision.source}, confidence ${decision.confidence.toFixed(2)}) - ${decision.reason}`;
615469
+ mirrorTelegramAttentionDecision(msg, decision2) {
615470
+ const route = decision2.shouldReply ? `reply via ${decision2.route}` : "silent";
615471
+ const primary = `attention decision: ${route} (${decision2.source}, confidence ${decision2.confidence.toFixed(2)}) - ${decision2.reason}`;
614664
615472
  const notes2 = [
614665
- decision.diagnosticNote ? `router diagnostic: ${decision.diagnosticNote}` : "",
614666
- decision.silentDisposition ? `silent reflection: ${decision.silentDisposition}` : "",
614667
- decision.mentalNote ? `mental note: ${decision.mentalNote}` : "",
614668
- decision.memoryNote ? `memory note: ${decision.memoryNote}` : "",
614669
- decision.relationshipNote ? `relationship note: ${decision.relationshipNote}` : ""
615473
+ decision2.diagnosticNote ? `router diagnostic: ${decision2.diagnosticNote}` : "",
615474
+ decision2.silentDisposition ? `silent reflection: ${decision2.silentDisposition}` : "",
615475
+ decision2.mentalNote ? `mental note: ${decision2.mentalNote}` : "",
615476
+ decision2.memoryNote ? `memory note: ${decision2.memoryNote}` : "",
615477
+ decision2.relationshipNote ? `relationship note: ${decision2.relationshipNote}` : ""
614670
615478
  ].filter(Boolean);
614671
615479
  this.tuiWrite(() => {
614672
615480
  renderTelegramSubAgentEvent(msg.username, primary);
@@ -614675,17 +615483,17 @@ External acquisition contract:
614675
615483
  }
614676
615484
  });
614677
615485
  }
614678
- deliverTelegramAttentionDecision(sessionKey, msg, viewId, decision, salienceSignals, daydreamOpportunities = this.latestTelegramDaydreamOpportunityInputs(sessionKey)) {
614679
- this.writeTelegramAttentionDecision(viewId, decision);
614680
- this.mirrorTelegramAttentionDecision(msg, decision);
615486
+ deliverTelegramAttentionDecision(sessionKey, msg, viewId, decision2, salienceSignals, daydreamOpportunities = this.latestTelegramDaydreamOpportunityInputs(sessionKey)) {
615487
+ this.writeTelegramAttentionDecision(viewId, decision2);
615488
+ this.mirrorTelegramAttentionDecision(msg, decision2);
614681
615489
  this.commitTelegramSocialDecision(
614682
615490
  sessionKey,
614683
615491
  msg,
614684
- decision,
615492
+ decision2,
614685
615493
  salienceSignals,
614686
615494
  daydreamOpportunities
614687
615495
  );
614688
- this.applyTelegramStimulationDecision(sessionKey, decision);
615496
+ this.applyTelegramStimulationDecision(sessionKey, decision2);
614689
615497
  }
614690
615498
  normalizeTelegramCommandText(input) {
614691
615499
  const trimmed = input.trim();
@@ -616032,40 +616840,40 @@ ${mediaContext}` : ""
616032
616840
  timeoutMs: Math.min(Math.max(this.agentConfig.timeoutMs ?? 3e4, 5e3), 2e4),
616033
616841
  think: false
616034
616842
  });
616035
- const decision = parseTelegramReflectionFollowupDecision(result.choices[0]?.message?.content ?? "");
616843
+ const decision2 = parseTelegramReflectionFollowupDecision(result.choices[0]?.message?.content ?? "");
616036
616844
  state.lastFollowupArtifactAt = artifact.generatedAt;
616037
- if (!decision) {
616845
+ if (!decision2) {
616038
616846
  this.saveTelegramConversationState(sessionKey);
616039
616847
  return { sent: false, reason: "model returned no usable follow-up decision" };
616040
616848
  }
616041
- if (!decision.shouldSend || !decision.text || decision.confidence < 0.66) {
616849
+ if (!decision2.shouldSend || !decision2.text || decision2.confidence < 0.66) {
616042
616850
  this.saveTelegramConversationState(sessionKey);
616043
- return { sent: false, reason: decision.reason || "model chose silence" };
616851
+ return { sent: false, reason: decision2.reason || "model chose silence" };
616044
616852
  }
616045
- const replyTo = decision.replyToMessageId && candidateMessageIds.includes(decision.replyToMessageId) ? decision.replyToMessageId : void 0;
616853
+ const replyTo = decision2.replyToMessageId && candidateMessageIds.includes(decision2.replyToMessageId) ? decision2.replyToMessageId : void 0;
616046
616854
  const chatId = this.telegramChatIdFromArtifact(artifact);
616047
616855
  const sentMessageId = await this.sendMessageHTML(
616048
616856
  chatId,
616049
- convertMarkdownToTelegramHTML(decision.text),
616857
+ convertMarkdownToTelegramHTML(decision2.text),
616050
616858
  replyTo
616051
616859
  );
616052
616860
  this.recordTelegramAssistantMessage({
616053
616861
  chatId,
616054
616862
  chatType: artifact.chatType,
616055
616863
  chatTitle: artifact.chatTitle,
616056
- text: decision.text,
616864
+ text: decision2.text,
616057
616865
  username: this.state.botUsername || "omnius",
616058
616866
  firstName: "Omnius",
616059
616867
  fromUserId: 0,
616060
616868
  messageId: sentMessageId ?? 0
616061
- }, decision.text, "chat", {
616869
+ }, decision2.text, "chat", {
616062
616870
  messageId: sentMessageId,
616063
616871
  replyToMessageId: replyTo
616064
616872
  });
616065
616873
  state.lastFollowupAt = now;
616066
616874
  this.saveTelegramConversationState(sessionKey);
616067
- this.tuiWrite(() => renderTelegramSubAgentEvent("reflection", `sent scoped Telegram follow-up (${decision.confidence.toFixed(2)}): ${decision.reason}`));
616068
- return { sent: true, reason: decision.reason };
616875
+ this.tuiWrite(() => renderTelegramSubAgentEvent("reflection", `sent scoped Telegram follow-up (${decision2.confidence.toFixed(2)}): ${decision2.reason}`));
616876
+ return { sent: true, reason: decision2.reason };
616069
616877
  } catch (err) {
616070
616878
  state.lastFollowupArtifactAt = artifact.generatedAt;
616071
616879
  this.saveTelegramConversationState(sessionKey);
@@ -616115,7 +616923,7 @@ ${mediaContext}` : ""
616115
616923
  }
616116
616924
  return opportunities;
616117
616925
  }
616118
- commitTelegramSocialDecision(sessionKey, msg, decision, salienceSignals, daydreamOpportunities = this.latestTelegramDaydreamOpportunityInputs(sessionKey)) {
616926
+ commitTelegramSocialDecision(sessionKey, msg, decision2, salienceSignals, daydreamOpportunities = this.latestTelegramDaydreamOpportunityInputs(sessionKey)) {
616119
616927
  try {
616120
616928
  commitTelegramSocialDecision(this.telegramSocialStateForSession(sessionKey), {
616121
616929
  sessionKey,
@@ -616124,15 +616932,15 @@ ${mediaContext}` : ""
616124
616932
  messageThreadId: msg.messageThreadId,
616125
616933
  sender: this.telegramMessageSocialActorInput(msg),
616126
616934
  replyToMessageId: msg.replyToMessageId,
616127
- route: decision.route,
616128
- shouldReply: decision.shouldReply,
616129
- confidence: decision.confidence,
616130
- reason: decision.reason,
616131
- source: decision.source,
616132
- silentDisposition: decision.silentDisposition,
616133
- mentalNote: decision.mentalNote,
616134
- memoryNote: decision.memoryNote,
616135
- relationshipNote: decision.relationshipNote,
616935
+ route: decision2.route,
616936
+ shouldReply: decision2.shouldReply,
616937
+ confidence: decision2.confidence,
616938
+ reason: decision2.reason,
616939
+ source: decision2.source,
616940
+ silentDisposition: decision2.silentDisposition,
616941
+ mentalNote: decision2.mentalNote,
616942
+ memoryNote: decision2.memoryNote,
616943
+ relationshipNote: decision2.relationshipNote,
616136
616944
  salienceSignals,
616137
616945
  self: this.telegramSelfSocialActorInput(),
616138
616946
  daydreamOpportunities
@@ -616357,7 +617165,7 @@ ${mediaContext}` : ""
616357
617165
  }
616358
617166
  const matchingEntry = mediaEntries.find((entry) => {
616359
617167
  if (resolve43(entry.localPath) === resolve43(raw)) return true;
616360
- if (basename27(entry.localPath) === raw) return true;
617168
+ if (basename28(entry.localPath) === raw) return true;
616361
617169
  if (entry.fileUniqueId === raw || entry.fileId === raw) return true;
616362
617170
  if (entry.messageId && String(entry.messageId) === raw) return true;
616363
617171
  if (entry.messageId && `message_id:${entry.messageId}` === raw.toLowerCase()) return true;
@@ -616394,7 +617202,7 @@ ${mediaContext}` : ""
616394
617202
  }
616395
617203
  return entries.find((entry2) => {
616396
617204
  if (resolve43(entry2.localPath) === resolve43(ref)) return true;
616397
- if (basename27(entry2.localPath) === ref) return true;
617205
+ if (basename28(entry2.localPath) === ref) return true;
616398
617206
  if (entry2.fileUniqueId === ref || entry2.fileId === ref) return true;
616399
617207
  if (entry2.messageId && String(entry2.messageId) === ref) return true;
616400
617208
  return false;
@@ -616422,7 +617230,7 @@ ${mediaContext}` : ""
616422
617230
  caption: entry.caption
616423
617231
  },
616424
617232
  modality,
616425
- label: `Telegram message_id ${entry.messageId || "unknown"} ${basename27(entry.localPath)}`,
617233
+ label: `Telegram message_id ${entry.messageId || "unknown"} ${basename28(entry.localPath)}`,
616426
617234
  extractedContent: entry.extractedContent
616427
617235
  };
616428
617236
  }
@@ -617531,8 +618339,8 @@ ${cardLines.join("\n")}`);
617531
618339
  const caption = entry.caption ? ` caption=${telegramContextJsonString(entry.caption, 120)}` : "";
617532
618340
  const extracted = entry.extractedContent ? `
617533
618341
  extracted=${telegramContextJsonString(entry.extractedContent.replace(/\s+/g, " "), 220)}` : "";
617534
- const alias = entry.messageId ? `message_id:${entry.messageId}` : basename27(entry.localPath);
617535
- return `- ${alias}${replyMark}: ${kind}; file ${basename27(entry.localPath)}${caption}${extracted}`;
618342
+ const alias = entry.messageId ? `message_id:${entry.messageId}` : basename28(entry.localPath);
618343
+ return `- ${alias}${replyMark}: ${kind}; file ${basename28(entry.localPath)}${caption}${extracted}`;
617536
618344
  });
617537
618345
  sections.push([
617538
618346
  "### Recent Chat Media",
@@ -617643,13 +618451,13 @@ ${lines.join("\n")}`);
617643
618451
  const resolvedReply = this.resolveTelegramReplyContext(this.sessionKeyForMessage(msg), msg);
617644
618452
  return Boolean(resolvedReply?.sender?.isSelf);
617645
618453
  }
617646
- applyTelegramStimulationDecision(sessionKey, decision) {
618454
+ applyTelegramStimulationDecision(sessionKey, decision2) {
617647
618455
  this.stimulation.applyAgentDecision(sessionKey, {
617648
- shouldReply: decision.shouldReply,
617649
- phase: decision.attentionState,
617650
- attentionDelta: decision.attentionDelta,
617651
- attentionScore: decision.attentionScore,
617652
- nextAnalysisAfterMessages: decision.nextCheckAfterMessages
618456
+ shouldReply: decision2.shouldReply,
618457
+ phase: decision2.attentionState,
618458
+ attentionDelta: decision2.attentionDelta,
618459
+ attentionScore: decision2.attentionScore,
618460
+ nextAnalysisAfterMessages: decision2.nextCheckAfterMessages
617653
618461
  });
617654
618462
  }
617655
618463
  async telegramRouterJsonCompletion(backend, request, diagnostics) {
@@ -618832,22 +619640,22 @@ Join: ${newUrl}`);
618832
619640
  const isGroup = msg.chatType !== "private";
618833
619641
  if (isGroup) {
618834
619642
  const attentionViewId2 = this.registerTelegramAttentionView(msg, existing.toolContext || toolContext, "active Telegram thread");
618835
- const decision2 = await this.inferTelegramInteractionDecision(msg, existing.toolContext || toolContext);
619643
+ const decision3 = await this.inferTelegramInteractionDecision(msg, existing.toolContext || toolContext);
618836
619644
  this.deliverTelegramAttentionDecision(
618837
619645
  sessionKey,
618838
619646
  msg,
618839
619647
  attentionViewId2,
618840
- decision2,
619648
+ decision3,
618841
619649
  this.telegramMessageIdentitySalienceSignals(msg),
618842
619650
  this.markLatestTelegramDaydreamOpportunitiesConsidered(sessionKey, msg)
618843
619651
  );
618844
- this.markLastTelegramUserMessageMode(msg, decision2.shouldReply ? "steering" : "ambient");
619652
+ this.markLastTelegramUserMessageMode(msg, decision3.shouldReply ? "steering" : "ambient");
618845
619653
  this.subAgentViewCallbacks?.onWrite(
618846
619654
  existing.viewId,
618847
- `live steering: ${decision2.shouldReply ? decision2.route : "no_reply"} (${decision2.source}, confidence ${decision2.confidence.toFixed(2)}): ${decision2.reason}`
619655
+ `live steering: ${decision3.shouldReply ? decision3.route : "no_reply"} (${decision3.source}, confidence ${decision3.confidence.toFixed(2)}): ${decision3.reason}`
618848
619656
  );
618849
- if (!decision2.shouldReply) {
618850
- this.maybeLogTelegramGroupSkip(msg, `live inference: no steering — ${decision2.reason}`);
619657
+ if (!decision3.shouldReply) {
619658
+ this.maybeLogTelegramGroupSkip(msg, `live inference: no steering — ${decision3.reason}`);
618851
619659
  return;
618852
619660
  }
618853
619661
  }
@@ -618876,25 +619684,25 @@ Join: ${newUrl}`);
618876
619684
  return;
618877
619685
  }
618878
619686
  const attentionViewId = this.registerTelegramAttentionView(msg, toolContext);
618879
- const decision = await this.inferTelegramInteractionDecision(msg, toolContext);
619687
+ const decision2 = await this.inferTelegramInteractionDecision(msg, toolContext);
618880
619688
  this.deliverTelegramAttentionDecision(
618881
619689
  sessionKey,
618882
619690
  msg,
618883
619691
  attentionViewId,
618884
- decision,
619692
+ decision2,
618885
619693
  this.telegramMessageIdentitySalienceSignals(msg),
618886
619694
  this.markLatestTelegramDaydreamOpportunitiesConsidered(sessionKey, msg)
618887
619695
  );
618888
- this.markLastTelegramUserMessageMode(msg, decision.shouldReply ? decision.route : "ambient");
619696
+ this.markLastTelegramUserMessageMode(msg, decision2.shouldReply ? decision2.route : "ambient");
618889
619697
  this.subAgentViewCallbacks?.onWrite(
618890
619698
  this.viewIdForMessage(msg),
618891
- `live route: ${decision.shouldReply ? decision.route : "no_reply"} (${decision.source}, confidence ${decision.confidence.toFixed(2)}): ${decision.reason}`
619699
+ `live route: ${decision2.shouldReply ? decision2.route : "no_reply"} (${decision2.source}, confidence ${decision2.confidence.toFixed(2)}): ${decision2.reason}`
618892
619700
  );
618893
- if (!decision.shouldReply) {
618894
- this.maybeLogTelegramGroupSkip(msg, `live inference: no reply — ${decision.reason}`);
619701
+ if (!decision2.shouldReply) {
619702
+ this.maybeLogTelegramGroupSkip(msg, `live inference: no reply — ${decision2.reason}`);
618895
619703
  return;
618896
619704
  }
618897
- if (decision.route === "chat") {
619705
+ if (decision2.route === "chat") {
618898
619706
  await this.handleTelegramChatCompletion(msg, toolContext);
618899
619707
  return;
618900
619708
  }
@@ -621211,12 +622019,12 @@ Scoped workspace: ${scopedRoot}`,
621211
622019
  };
621212
622020
  });
621213
622021
  const dryRun = effective.dryRunByDefault === true;
621214
- const requireAdmin = effective.requireAdminForMutation !== false;
622022
+ const requireAdmin2 = effective.requireAdminForMutation !== false;
621215
622023
  const keyboard = [];
621216
622024
  for (let idx = 0; idx < rows.length; idx += 2) keyboard.push(rows.slice(idx, idx + 2));
621217
622025
  keyboard.push([
621218
622026
  { text: `${dryRun ? "[x]" : "[ ]"} Dry run`, callback_data: `omni:v1:tgtool:${state.nonce}:flag:dryrun` },
621219
- { text: `${requireAdmin ? "[x]" : "[ ]"} Admin mutations`, callback_data: `omni:v1:tgtool:${state.nonce}:flag:admin` }
622027
+ { text: `${requireAdmin2 ? "[x]" : "[ ]"} Admin mutations`, callback_data: `omni:v1:tgtool:${state.nonce}:flag:admin` }
621220
622028
  ]);
621221
622029
  const scopeLabel = state.policyScope === "chat" ? `chat ${String(state.policyChatId)}` : "global";
621222
622030
  return {
@@ -621567,12 +622375,12 @@ Scoped workspace: ${scopedRoot}`,
621567
622375
  return { success: true, output: `No recent ${kind} media is available in this Telegram chat scope.`, durationMs: performance.now() - start2 };
621568
622376
  }
621569
622377
  const lines = entries.map((entry, index) => {
621570
- const pathAlias = entry.messageId ? `message_id:${entry.messageId}` : basename27(entry.localPath);
622378
+ const pathAlias = entry.messageId ? `message_id:${entry.messageId}` : basename28(entry.localPath);
621571
622379
  const parts = [
621572
622380
  `${index + 1}. message_id ${entry.messageId || "unknown"}`,
621573
622381
  currentMsg?.replyToMessageId === entry.messageId ? "replied-to" : "",
621574
622382
  telegramCachedMediaIsImage(entry) ? "image" : telegramCachedMediaIsPdf(entry) ? "pdf" : telegramCachedMediaIsAudio(entry) ? "audio" : telegramCachedMediaIsVideo(entry) ? "video" : entry.mediaType,
621575
- `file=${basename27(entry.localPath)}`,
622383
+ `file=${basename28(entry.localPath)}`,
621576
622384
  `path_alias=${pathAlias}`,
621577
622385
  entry.caption ? `caption=${telegramContextJsonString(entry.caption, 140)}` : ""
621578
622386
  ].filter(Boolean);
@@ -621699,8 +622507,8 @@ Scoped workspace: ${scopedRoot}`,
621699
622507
  if (bridge.telegramFileSendAlreadyDeliveredForMessage(currentMsg, sendFingerprint)) {
621700
622508
  return {
621701
622509
  success: true,
621702
- output: `Telegram file already sent in this turn: ${basename27(file.path)} as ${kind} to ${String(target.chatId)}`,
621703
- llmContent: `Already sent ${basename27(file.path)} to Telegram as ${kind}; do not send it again.`,
622510
+ output: `Telegram file already sent in this turn: ${basename28(file.path)} as ${kind} to ${String(target.chatId)}`,
622511
+ llmContent: `Already sent ${basename28(file.path)} to Telegram as ${kind}; do not send it again.`,
621704
622512
  durationMs: performance.now() - start2,
621705
622513
  mutated: false,
621706
622514
  mutatedFiles: []
@@ -621717,8 +622525,8 @@ Scoped workspace: ${scopedRoot}`,
621717
622525
  bridge.rememberTelegramDeliveredArtifactForMessage(currentMsg, ledgerPath);
621718
622526
  return {
621719
622527
  success: true,
621720
- output: `Sent Telegram file: ${basename27(file.path)} as ${kind} to ${String(target.chatId)}${messageId ? ` (message_id ${messageId})` : ""}`,
621721
- llmContent: `Sent ${basename27(file.path)} to Telegram as ${kind}.`,
622528
+ output: `Sent Telegram file: ${basename28(file.path)} as ${kind} to ${String(target.chatId)}${messageId ? ` (message_id ${messageId})` : ""}`,
622529
+ llmContent: `Sent ${basename28(file.path)} to Telegram as ${kind}.`,
621722
622530
  durationMs: performance.now() - start2,
621723
622531
  mutated: false,
621724
622532
  mutatedFiles: []
@@ -622172,7 +622980,7 @@ ${text}`.trim());
622172
622980
  if (!existsSync113(media.value)) throw new Error(`File does not exist: ${media.value}`);
622173
622981
  const buffer2 = readFileSync92(media.value);
622174
622982
  const boundary = `----omnius-media-${Date.now()}-${Math.random().toString(36).slice(2)}`;
622175
- const filename = basename27(media.value);
622983
+ const filename = basename28(media.value);
622176
622984
  const contentType = mimeForPath(media.value, media.kind);
622177
622985
  const parts = [];
622178
622986
  const addField = (name10, value2) => {
@@ -622412,7 +623220,7 @@ Content-Type: ${contentType}\r
622412
623220
  continue;
622413
623221
  }
622414
623222
  const buffer2 = readFileSync92(pathOrFileId);
622415
- const filename = basename27(pathOrFileId);
623223
+ const filename = basename28(pathOrFileId);
622416
623224
  parts.push(Buffer.from(`--${boundary}\r
622417
623225
  `));
622418
623226
  parts.push(Buffer.from(
@@ -623514,7 +624322,7 @@ __export(projects_exports, {
623514
624322
  });
623515
624323
  import { readFileSync as readFileSync94, writeFileSync as writeFileSync61, mkdirSync as mkdirSync67, existsSync as existsSync115, statSync as statSync40, renameSync as renameSync7 } from "node:fs";
623516
624324
  import { homedir as homedir42 } from "node:os";
623517
- import { basename as basename28, join as join129, resolve as resolve44 } from "node:path";
624325
+ import { basename as basename29, join as join129, resolve as resolve44 } from "node:path";
623518
624326
  import { randomUUID as randomUUID14 } from "node:crypto";
623519
624327
  function readAll2() {
623520
624328
  try {
@@ -623562,7 +624370,7 @@ function registerProject(root, pid) {
623562
624370
  } else {
623563
624371
  entry = {
623564
624372
  root: canonical,
623565
- name: basename28(canonical) || canonical,
624373
+ name: basename29(canonical) || canonical,
623566
624374
  firstSeen: now,
623567
624375
  lastSeen: now,
623568
624376
  pid: pid ?? null,
@@ -626937,6 +627745,8 @@ async function tryRouteV1(ctx3) {
626937
627745
  if (pathname === "/v1/tor/status" && method === "GET") return handleTorStatus(ctx3);
626938
627746
  if (pathname === "/v1/tor/enable" && method === "POST") return handleTorEnable(ctx3);
626939
627747
  if (pathname === "/v1/tor/disable" && method === "POST") return handleTorDisable(ctx3);
627748
+ if (pathname === "/v1/ollama/pool/processes" && method === "GET") return handleOllamaPoolProcesses(ctx3);
627749
+ if (pathname === "/v1/ollama/pool/cleanup" && method === "POST") return handleOllamaPoolCleanup(ctx3);
626940
627750
  if (pathname === "/v1/tools" && method === "GET") {
626941
627751
  return handleListTools(ctx3);
626942
627752
  }
@@ -627282,6 +628092,109 @@ async function handleCallMcp(ctx3, name10) {
627282
628092
  return true;
627283
628093
  }
627284
628094
  }
628095
+ function requestScope(ctx3) {
628096
+ const reqAuth = ctx3.req;
628097
+ return ctx3.scope ?? reqAuth._authScope ?? "read";
628098
+ }
628099
+ function requestOrigin(ctx3) {
628100
+ const remoteIp = (ctx3.req.socket?.remoteAddress || "").replace(/^::ffff:/, "");
628101
+ return /^(127\.\d+\.\d+\.\d+|::1|localhost)$/.test(remoteIp) ? "loopback" : "remote";
628102
+ }
628103
+ function requireAdmin(ctx3, detail) {
628104
+ if (requestScope(ctx3) === "admin") return true;
628105
+ sendProblem(ctx3.res, problemDetails({
628106
+ type: P.forbidden,
628107
+ status: 403,
628108
+ title: "Admin scope required",
628109
+ detail,
628110
+ instance: ctx3.requestId
628111
+ }));
628112
+ return false;
628113
+ }
628114
+ async function buildOllamaCleanupPoolStatus(mod2) {
628115
+ try {
628116
+ const poolConfig = mod2.resolveDefaultPoolConfig();
628117
+ if (!mod2.shouldUseOllamaPoolForBaseUrl(poolConfig.baseInstanceUrl)) return null;
628118
+ return await mod2.getOllamaPool({ baseInstanceUrl: poolConfig.baseInstanceUrl }).status();
628119
+ } catch {
628120
+ return null;
628121
+ }
628122
+ }
628123
+ async function handleOllamaPoolProcesses(ctx3) {
628124
+ if (!requireAdmin(ctx3, "Ollama process inventory exposes local PIDs and ports.")) return true;
628125
+ const { res, requestId } = ctx3;
628126
+ try {
628127
+ const mod2 = await Promise.resolve().then(() => (init_dist8(), dist_exports3));
628128
+ const poolConfig = mod2.resolveDefaultPoolConfig();
628129
+ const poolStatus = await buildOllamaCleanupPoolStatus(mod2);
628130
+ const report2 = await mod2.scanOllamaProcesses({
628131
+ baseInstanceUrl: poolConfig.baseInstanceUrl,
628132
+ poolPortStart: poolConfig.spawnPortStart,
628133
+ poolStatus
628134
+ });
628135
+ sendJson(res, 200, report2);
628136
+ return true;
628137
+ } catch (err) {
628138
+ sendProblem(res, problemDetails({
628139
+ type: P.internalError,
628140
+ status: 500,
628141
+ title: "Ollama process scan failed",
628142
+ detail: err instanceof Error ? err.message : String(err),
628143
+ instance: requestId
628144
+ }));
628145
+ return true;
628146
+ }
628147
+ }
628148
+ async function handleOllamaPoolCleanup(ctx3) {
628149
+ if (!requireAdmin(ctx3, "Cleaning stale Ollama processes requires admin scope.")) return true;
628150
+ if (requestOrigin(ctx3) !== "loopback") {
628151
+ sendProblem(ctx3.res, problemDetails({
628152
+ type: P.forbidden,
628153
+ status: 403,
628154
+ title: "Loopback required",
628155
+ detail: "Ollama process cleanup may only be requested from loopback.",
628156
+ instance: ctx3.requestId
628157
+ }));
628158
+ return true;
628159
+ }
628160
+ const { req: req2, res, requestId, user } = ctx3;
628161
+ try {
628162
+ const body = await parseJsonBodyStrict(req2).catch(() => ({}));
628163
+ const mod2 = await Promise.resolve().then(() => (init_dist8(), dist_exports3));
628164
+ const poolConfig = mod2.resolveDefaultPoolConfig();
628165
+ const poolStatus = await buildOllamaCleanupPoolStatus(mod2);
628166
+ const dryRun = body["dry_run"] === false ? false : true;
628167
+ const useInferenceRaw = body["use_inference"];
628168
+ const useInference = useInferenceRaw === false ? false : useInferenceRaw === true ? true : "auto";
628169
+ const report2 = await mod2.cleanupStaleOllamaProcesses({
628170
+ dryRun,
628171
+ useInference,
628172
+ baseInstanceUrl: poolConfig.baseInstanceUrl,
628173
+ poolPortStart: poolConfig.spawnPortStart,
628174
+ poolStatus
628175
+ });
628176
+ publishEvent("ollama.pool.cleanup", {
628177
+ dry_run: report2.dryRun,
628178
+ used_inference: report2.usedInference,
628179
+ terminated: report2.terminated.length,
628180
+ errors: report2.errors.length
628181
+ }, {
628182
+ subject: user ?? "anonymous",
628183
+ aimsControl: "A.6.2.6"
628184
+ });
628185
+ sendJson(res, 200, report2);
628186
+ return true;
628187
+ } catch (err) {
628188
+ sendProblem(res, problemDetails({
628189
+ type: P.internalError,
628190
+ status: 500,
628191
+ title: "Ollama process cleanup failed",
628192
+ detail: err instanceof Error ? err.message : String(err),
628193
+ instance: requestId
628194
+ }));
628195
+ return true;
628196
+ }
628197
+ }
627285
628198
  function memoryDbPaths2(baseDir = process.cwd()) {
627286
628199
  const dir = join136(baseDir, ".omnius");
627287
628200
  return {
@@ -638353,6 +639266,7 @@ function getOpenApiSpec() {
638353
639266
  { name: "Sessions", description: "Omnius task session archive" },
638354
639267
  { name: "Context", description: "Session context save/restore/compact" },
638355
639268
  { name: "Nexus", description: "P2P peer mesh and sponsor directory" },
639269
+ { name: "Ollama", description: "Local Ollama pool status and process hygiene" },
638356
639270
  { name: "Tools", description: "Agentic tool registry" },
638357
639271
  { name: "Engines", description: "Long-running TUI engines (dream, bless, call, listen, telegram, expose)" },
638358
639272
  { name: "Voice", description: "TTS / ASR / voice-clone pipeline. REST surface for synthesis (/v1/voice/tts) and transcription (/v1/voice/transcribe), full-duplex voicechat over WebSocket (/v1/voicechat/ws), and clone reference management (upload/from-URL/multipart/raw)." },
@@ -638515,6 +639429,23 @@ function getOpenApiSpec() {
638515
639429
  }
638516
639430
  },
638517
639431
  "/v1/system": { get: { summary: "System info + GPU/RAM/CPU", tags: ["Metering"], responses: { 200: { description: "System snapshot" } } } },
639432
+ "/v1/ollama/pool/processes": {
639433
+ get: {
639434
+ summary: "Scan local Ollama pool processes",
639435
+ tags: ["Ollama"],
639436
+ description: "Admin-scope inventory of local `ollama serve` PIDs, listening ports, protected base-service classification, and stale pool cleanup decisions. This endpoint does not terminate processes.",
639437
+ responses: { 200: { description: "Ollama process scan report" }, ...ErrorResponses }
639438
+ }
639439
+ },
639440
+ "/v1/ollama/pool/cleanup": {
639441
+ post: {
639442
+ summary: "Clean up stale Ollama pool processes",
639443
+ tags: ["Ollama"],
639444
+ description: "Loopback/admin-only guarded cleanup. Defaults to dry_run=true. Body: {dry_run?: boolean, use_inference?: boolean}. Hard rules always protect port 11434, the configured base port, systemd ollama.service, and live tracked pool runners.",
639445
+ requestBody: { required: false, content: { "application/json": { schema: { type: "object", properties: { dry_run: { type: "boolean", default: true }, use_inference: { type: "boolean", default: true } } } } } },
639446
+ responses: { 200: { description: "Cleanup report" }, ...ErrorResponses }
639447
+ }
639448
+ },
638518
639449
  // ───── PT-02: Skills ─────
638519
639450
  "/v1/skills": {
638520
639451
  get: {
@@ -639696,7 +640627,7 @@ __export(embedding_workers_exports, {
639696
640627
  startEmbeddingWorkers: () => startEmbeddingWorkers,
639697
640628
  stopEmbeddingWorkers: () => stopEmbeddingWorkers
639698
640629
  });
639699
- import { basename as basename29, join as join140 } from "node:path";
640630
+ import { basename as basename30, join as join140 } from "node:path";
639700
640631
  function startEmbeddingWorkers(opts) {
639701
640632
  if (_running) return;
639702
640633
  _running = true;
@@ -639762,7 +640693,7 @@ async function runEmbeddingTask(modality, episodeId, taskId, opts) {
639762
640693
  try {
639763
640694
  if (!_aligner) {
639764
640695
  const stateRoot = process.env.OMNIUS_DIR || process.cwd();
639765
- const omniusDir = basename29(stateRoot) === ".omnius" ? stateRoot : join140(stateRoot, ".omnius");
640696
+ const omniusDir = basename30(stateRoot) === ".omnius" ? stateRoot : join140(stateRoot, ".omnius");
639766
640697
  const memDir = join140(omniusDir, "memory");
639767
640698
  _aligner = new EmbeddingAligner(
639768
640699
  `${modality}-${emb.length}`,