omnius 1.0.95 → 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, HEADER_ACCENT_BLUE, 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;
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,9 +572519,9 @@ 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 ";
571864
- HEADER_ACCENT_BLUE = 147;
571865
- HEADER_ACCENT_BOLD_FG = `\x1B[1;38;5;${HEADER_ACCENT_BLUE}m`;
571866
- HEADER_BUTTON_BG = `\x1B[48;5;${HEADER_ACCENT_BLUE}m`;
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`;
571867
572525
  HEADER_BUTTON_FG = "\x1B[38;5;0m";
571868
572526
  BOX_TL3 = "╭";
571869
572527
  BOX_TR3 = "╮";
@@ -571980,6 +572638,9 @@ var init_status_bar = __esm({
571980
572638
  /** True while resize is in-flight (between first SIGWINCH and debounce settle).
571981
572639
  * Suppresses ALL footer renders to prevent separator debris at intermediate sizes. */
571982
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;
571983
572644
  /**
571984
572645
  * Depth-counted content write guard. Incremented by beginContentWrite(),
571985
572646
  * decremented by endContentWrite(). Footer is only redrawn and cursor
@@ -573768,7 +574429,12 @@ var init_status_bar = __esm({
573768
574429
  /** Handle terminal resize — debounced to prevent separator stacking during drag */
573769
574430
  handleResize() {
573770
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();
573771
574436
  this._resizing = true;
574437
+ this.renderFooterResizeFrame(prevRows, prevCols);
573772
574438
  if (this._resizeTimer) clearTimeout(this._resizeTimer);
573773
574439
  this._resizeTimer = setTimeout(() => {
573774
574440
  this._resizeTimer = null;
@@ -573797,15 +574463,20 @@ var init_status_bar = __esm({
573797
574463
  for (let row = clearStart; row <= rows; row++) {
573798
574464
  buf += `\x1B[${row};1H\x1B[2K`;
573799
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}`;
573800
574468
  for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
573801
- const row = pos.inputStartRow + i2;
574469
+ const row = pos.inputStartRow + 1 + i2;
573802
574470
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
573803
- 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}`;
573804
574475
  }
573805
- const boxInnerP = w - 2;
573806
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}`;
573807
- 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`;
573808
574478
  this.termWrite(buf);
574479
+ this.rememberFooterPaint(pos.inputStartRow);
573809
574480
  if (this._bannerRefresh) this._bannerRefresh();
573810
574481
  } else {
573811
574482
  this.applyScrollRegion(true);
@@ -573829,7 +574500,7 @@ var init_status_bar = __esm({
573829
574500
  if (this.writeDepth === 0) {
573830
574501
  this.parkCursorInInput();
573831
574502
  } else {
573832
- this.termWrite(`\x1B[${pos.inputStartRow};1H\x1B[?25l`);
574503
+ this.termWrite(`\x1B[${pos.inputStartRow + 1};1H\x1B[?25l`);
573833
574504
  }
573834
574505
  }
573835
574506
  /** Register a callback that fires AT THE END of _handleResizeImmediate.
@@ -573838,6 +574509,34 @@ var init_status_bar = __esm({
573838
574509
  setOnResizeFinalized(cb) {
573839
574510
  this._onResizeFinalized = cb;
573840
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
+ }
573841
574540
  /** Public cursor parking hook for command renderers and resize finalizers. */
573842
574541
  parkCursor() {
573843
574542
  this.parkCursorInInput();
@@ -575014,8 +575713,11 @@ ${CONTENT_BG_SEQ}`);
575014
575713
  * Does NOT set DECSTBM — the scroll region is maintained by
575015
575714
  * applyScrollRegion() and beginContentWrite().
575016
575715
  */
575017
- renderFooterAndPositionInput() {
575018
- 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;
575019
575721
  const rows = termRows();
575020
575722
  const w = getTermWidth();
575021
575723
  const oldFooterTop = Math.max(1, rows - this._currentFooterHeight + 1);
@@ -575073,6 +575775,7 @@ ${CONTENT_BG_SEQ}`);
575073
575775
  buf += `\x1B[${cursorTermRow};${inputWrap.cursorCol}H${CURSOR_BLINK_BLOCK}\x1B[?25h`;
575074
575776
  }
575075
575777
  this.termWrite(buf);
575778
+ this.rememberFooterPaint(pos.inputStartRow);
575076
575779
  }
575077
575780
  /**
575078
575781
  * Redraw footer while preserving the current cursor position.
@@ -575086,13 +575789,13 @@ ${CONTENT_BG_SEQ}`);
575086
575789
  * IMPORTANT: Does NOT set DECSTBM here — setting the scroll region between
575087
575790
  * cursor save/restore corrupts the restore position on many terminals.
575088
575791
  */
575089
- renderFooterPreserveCursor() {
575090
- if (!this.active || this._resizing) return;
575792
+ renderFooterPreserveCursor(force = false) {
575793
+ if (!this.active || this._resizing && !force) return;
575091
575794
  if (this.footerHeightChanged()) {
575092
575795
  if (this.writeDepth > 0) {
575093
- this.renderInputRowDuringStream();
575796
+ this.renderInputRowDuringStream(force);
575094
575797
  } else {
575095
- this.renderFooterAndPositionInput();
575798
+ this.renderFooterAndPositionInput(force);
575096
575799
  }
575097
575800
  return;
575098
575801
  }
@@ -575120,6 +575823,7 @@ ${CONTENT_BG_SEQ}`);
575120
575823
  buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}${PANEL_BG_SEQ}\x1B[?7h\x1B8` + // DEC restore cursor
575121
575824
  (this.writeDepth === 0 ? `${CURSOR_BLINK_BLOCK}\x1B[?25h` : "");
575122
575825
  this.termWrite(buf);
575826
+ this.rememberFooterPaint(pos.inputStartRow);
575123
575827
  if (pos.tabBarRow > 0) this.renderAgentTabs();
575124
575828
  }
575125
575829
  /**
@@ -575127,8 +575831,8 @@ ${CONTENT_BG_SEQ}`);
575127
575831
  * Uses DEC save/restore cursor so the streaming cursor position is preserved.
575128
575832
  * If footer height changed, also updates DECSTBM and redraws full footer.
575129
575833
  */
575130
- renderInputRowDuringStream() {
575131
- if (!this.active || this._resizing || !this.inputStateProvider) return;
575834
+ renderInputRowDuringStream(force = false) {
575835
+ if (!this.active || this._resizing && !force || !this.inputStateProvider) return;
575132
575836
  const rows = termRows();
575133
575837
  const w = getTermWidth();
575134
575838
  const oldFooterHeight = this._currentFooterHeight;
@@ -575193,6 +575897,7 @@ ${CONTENT_BG_SEQ}`);
575193
575897
  }
575194
575898
  const w1 = this._origWrite ?? this._trueStdoutWrite;
575195
575899
  w1.call(process.stdout, buf);
575900
+ this.rememberFooterPaint(pos.inputStartRow);
575196
575901
  if (heightDelta !== 0) this.refreshTasksPanelAfterLayoutChange();
575197
575902
  } else {
575198
575903
  let buf = "\x1B7\x1B[?25l\x1B[?7l";
@@ -575224,6 +575929,7 @@ ${CONTENT_BG_SEQ}`);
575224
575929
  buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}${PANEL_BG_SEQ}`;
575225
575930
  buf += "\x1B[?7h\x1B8\x1B[?25l";
575226
575931
  this.termWrite(buf);
575932
+ this.rememberFooterPaint(pos.inputStartRow);
575227
575933
  }
575228
575934
  }
575229
575935
  /**
@@ -580400,7 +581106,7 @@ var init_platforms = __esm({
580400
581106
 
580401
581107
  // packages/cli/src/tui/workspace-explorer.ts
580402
581108
  import { existsSync as existsSync93, readdirSync as readdirSync31, readFileSync as readFileSync75, statSync as statSync34 } from "node:fs";
580403
- 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";
580404
581110
  function exploreWorkspace(root, options2 = {}) {
580405
581111
  const query = (options2.query ?? "").trim().toLowerCase();
580406
581112
  const maxResults = options2.maxResults ?? 80;
@@ -580517,7 +581223,7 @@ function classifyWorkspaceFile(path12) {
580517
581223
  if (lower.includes(".test.") || lower.includes(".spec.") || lower.includes("/tests/")) return "test";
580518
581224
  if (SOURCE_EXT.has(ext)) return "source";
580519
581225
  if (DOC_EXT2.has(ext)) return "doc";
580520
- if (CONFIG_EXT.has(ext) || basename18(lower).startsWith("dockerfile")) return "config";
581226
+ if (CONFIG_EXT.has(ext) || basename19(lower).startsWith("dockerfile")) return "config";
580521
581227
  if (ASSET_EXT.has(ext)) return "asset";
580522
581228
  return "other";
580523
581229
  }
@@ -580529,7 +581235,7 @@ function scoreWorkspaceFile(entry, query) {
580529
581235
  if (entry.path.startsWith("packages/cli/src/")) score += 5;
580530
581236
  if (query) {
580531
581237
  const lower = entry.path.toLowerCase();
580532
- const name10 = basename18(lower);
581238
+ const name10 = basename19(lower);
580533
581239
  if (name10.startsWith(query)) score += 20;
580534
581240
  if (lower.includes(`/${query}`)) score += 12;
580535
581241
  if (lower.includes(query)) score += 8;
@@ -591984,6 +592690,9 @@ async function handleSlashCommand(input, ctx3) {
591984
592690
  case "parallel":
591985
592691
  await handleParallel(arg, ctx3);
591986
592692
  return "handled";
592693
+ case "ollama":
592694
+ await handleOllama(arg, ctx3);
592695
+ return "handled";
591987
592696
  case "mcp":
591988
592697
  case "mcps":
591989
592698
  await handleMcp(arg, ctx3);
@@ -598034,14 +598743,14 @@ async function handleVoiceMenu(ctx3, save2, hasLocal) {
598034
598743
  if (!jsonDrop.confirmed || !jsonDrop.path) {
598035
598744
  continue;
598036
598745
  }
598037
- const { basename: basename30, join: pathJoin } = await import("node:path");
598746
+ const { basename: basename31, join: pathJoin } = await import("node:path");
598038
598747
  const {
598039
598748
  copyFileSync: copyFileSync5,
598040
598749
  mkdirSync: mkdirSync81,
598041
598750
  existsSync: exists2
598042
598751
  } = await import("node:fs");
598043
598752
  const { homedir: homedir53 } = await import("node:os");
598044
- const modelName = basename30(onnxDrop.path, ".onnx").replace(
598753
+ const modelName = basename31(onnxDrop.path, ".onnx").replace(
598045
598754
  /[^a-zA-Z0-9_-]/g,
598046
598755
  "-"
598047
598756
  );
@@ -598428,7 +599137,7 @@ async function handleVoiceList(ctx3, focusFilename) {
598428
599137
  copyFileSync: cpf,
598429
599138
  mkdirSync: mkd
598430
599139
  } = __require("node:fs");
598431
- const { basename: basename30, join: pjoin } = __require("node:path");
599140
+ const { basename: basename31, join: pjoin } = __require("node:path");
598432
599141
  if (!fe(src2)) {
598433
599142
  renderError(`File not found: ${src2}`);
598434
599143
  helpers.render();
@@ -598441,7 +599150,7 @@ async function handleVoiceList(ctx3, focusFilename) {
598441
599150
  "clone-refs"
598442
599151
  );
598443
599152
  mkd(refsDir, { recursive: true });
598444
- const destName = basename30(src2);
599153
+ const destName = basename31(src2);
598445
599154
  const dest = pjoin(refsDir, destName);
598446
599155
  cpf(src2, dest);
598447
599156
  renderInfo(`Imported "${destName}" → ${dest}`);
@@ -599574,6 +600283,113 @@ ${escapedContent}EOF'`, {
599574
600283
  }
599575
600284
  }
599576
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
+ }
599577
600393
  async function handleMcp(subcommand, ctx3) {
599578
600394
  const manager = ctx3.getMcpManager?.();
599579
600395
  if (!manager) {
@@ -601767,7 +602583,7 @@ var init_commands = __esm({
601767
602583
 
601768
602584
  // packages/cli/src/tui/project-context.ts
601769
602585
  import { existsSync as existsSync102, readFileSync as readFileSync82, readdirSync as readdirSync34 } from "node:fs";
601770
- import { join as join115, basename as basename19 } from "node:path";
602586
+ import { join as join115, basename as basename20 } from "node:path";
601771
602587
  import { execSync as execSync53 } from "node:child_process";
601772
602588
  import { homedir as homedir39 } from "node:os";
601773
602589
  function getModelTier(modelName) {
@@ -601848,7 +602664,7 @@ function loadMemoryContext(repoRoot) {
601848
602664
  try {
601849
602665
  const raw = readFileSync82(join115(dir, file), "utf-8");
601850
602666
  const entries = JSON.parse(raw);
601851
- const topic = basename19(file, ".json");
602667
+ const topic = basename20(file, ".json");
601852
602668
  for (const [k, v] of Object.entries(entries)) {
601853
602669
  if (!v?.value) continue;
601854
602670
  all2.push({ topic, key: k, value: String(v.value), scope, ts: v.timestamp ?? "" });
@@ -602112,7 +602928,7 @@ __export(visual_identity_association_exports, {
602112
602928
  formatVisualIdentityAssociationContext: () => formatVisualIdentityAssociationContext,
602113
602929
  stageVisualIdentityAssertion: () => stageVisualIdentityAssertion
602114
602930
  });
602115
- import { basename as basename20 } from "node:path";
602931
+ import { basename as basename21 } from "node:path";
602116
602932
  function normalizePersonName(name10) {
602117
602933
  return name10.trim().toLowerCase().replace(/\s+/g, " ");
602118
602934
  }
@@ -602434,7 +603250,7 @@ async function associateVisualIdentityFromImage(options2) {
602434
603250
  relation: "same_person_candidate",
602435
603251
  confidence: match.confidence,
602436
603252
  assertedBy: { id: "visual_memory", displayName: "visual_memory", isBot: true },
602437
- note: `Prior enrolled visual-memory face match for ${basename20(options2.imagePath)}`
603253
+ note: `Prior enrolled visual-memory face match for ${basename21(options2.imagePath)}`
602438
603254
  }]
602439
603255
  });
602440
603256
  if (result2.episodeId) committedEpisodeIds.push(result2.episodeId);
@@ -602479,7 +603295,7 @@ async function associateVisualIdentityFromImage(options2) {
602479
603295
  relation: "depicts",
602480
603296
  confidence: item.confidence,
602481
603297
  assertedBy: item.sender || options2.sender,
602482
- 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)}`
602483
603299
  }]
602484
603300
  });
602485
603301
  if (result2.episodeId) committedEpisodeIds.push(result2.episodeId);
@@ -602537,7 +603353,7 @@ var init_visual_identity_association = __esm({
602537
603353
 
602538
603354
  // packages/cli/src/tui/identity-memory-tool.ts
602539
603355
  import { existsSync as existsSync103 } from "node:fs";
602540
- 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";
602541
603357
  function personKey2(name10) {
602542
603358
  return `person:${name10.trim().toLowerCase().replace(/\s+/g, " ")}`;
602543
603359
  }
@@ -602606,7 +603422,7 @@ async function resolveMediaFromArgs(args, opts) {
602606
603422
  path: path12,
602607
603423
  media,
602608
603424
  modality: inferModality(media),
602609
- label: basename21(path12)
603425
+ label: basename22(path12)
602610
603426
  };
602611
603427
  }
602612
603428
  function edgeDirection(edge, nodeId, otherText) {
@@ -602764,7 +603580,7 @@ var init_identity_memory_tool = __esm({
602764
603580
  } else if (shouldEnrollFace) {
602765
603581
  faceLine = "face enrollment: skipped because no resolved image path was available";
602766
603582
  }
602767
- 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";
602768
603584
  const output = [
602769
603585
  `Stored identity evidence for ${name10}.`,
602770
603586
  `relation: ${relation}`,
@@ -603705,7 +604521,7 @@ var init_banner = __esm({
603705
604521
 
603706
604522
  // packages/cli/src/tui/carousel-descriptors.ts
603707
604523
  import { existsSync as existsSync105, readFileSync as readFileSync84, writeFileSync as writeFileSync53, mkdirSync as mkdirSync59, readdirSync as readdirSync35 } from "node:fs";
603708
- import { join as join118, basename as basename22 } from "node:path";
604524
+ import { join as join118, basename as basename23 } from "node:path";
603709
604525
  function loadToolProfile(repoRoot) {
603710
604526
  const filePath = join118(repoRoot, OMNIUS_DIR, "context", TOOL_PROFILE_FILE);
603711
604527
  try {
@@ -603801,7 +604617,7 @@ function generateDescriptors(repoRoot) {
603801
604617
  extractFromSessions(repoRoot, tags);
603802
604618
  extractFromMemory(repoRoot, tags);
603803
604619
  extractFromToolProfile(profile, tags);
603804
- const repoName2 = basename22(repoRoot);
604620
+ const repoName2 = basename23(repoRoot);
603805
604621
  if (repoName2 && !tags.includes(repoName2)) {
603806
604622
  tags.push(repoName2);
603807
604623
  }
@@ -605011,7 +605827,7 @@ var init_promptLoader3 = __esm({
605011
605827
 
605012
605828
  // packages/cli/src/tui/dream-engine.ts
605013
605829
  import { mkdirSync as mkdirSync61, writeFileSync as writeFileSync54, readFileSync as readFileSync86, existsSync as existsSync107, readdirSync as readdirSync36 } from "node:fs";
605014
- import { join as join121, basename as basename23 } from "node:path";
605830
+ import { join as join121, basename as basename24 } from "node:path";
605015
605831
  import { execSync as execSync54 } from "node:child_process";
605016
605832
  function setDreamWriteContent(fn) {
605017
605833
  _dreamWriteContent = fn;
@@ -605224,7 +606040,7 @@ var init_dream_engine = __esm({
605224
606040
  const rawPath = String(args["path"] ?? "");
605225
606041
  const content = String(args["content"] ?? "");
605226
606042
  if (!rawPath) return { success: false, output: "", error: "path is required", durationMs: Date.now() - start2 };
605227
- 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);
605228
606044
  if (!targetPath.startsWith(this.autoresearchDir)) {
605229
606045
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .omnius/autoresearch/", durationMs: Date.now() - start2 };
605230
606046
  }
@@ -605259,7 +606075,7 @@ var init_dream_engine = __esm({
605259
606075
  const rawPath = String(args["path"] ?? "");
605260
606076
  const oldStr = String(args["old_string"] ?? "");
605261
606077
  const newStr = String(args["new_string"] ?? "");
605262
- 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);
605263
606079
  if (!targetPath.startsWith(this.autoresearchDir)) {
605264
606080
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .omnius/autoresearch/", durationMs: Date.now() - start2 };
605265
606081
  }
@@ -605312,7 +606128,7 @@ var init_dream_engine = __esm({
605312
606128
  const rawPath = String(args["path"] ?? "");
605313
606129
  const content = String(args["content"] ?? "");
605314
606130
  if (!rawPath) return { success: false, output: "", error: "path is required", durationMs: Date.now() - start2 };
605315
- 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);
605316
606132
  if (!targetPath.startsWith(this.dreamsDir)) {
605317
606133
  return { success: false, output: "", error: "Dream mode: writes are confined to .omnius/dreams/", durationMs: Date.now() - start2 };
605318
606134
  }
@@ -605347,7 +606163,7 @@ var init_dream_engine = __esm({
605347
606163
  const rawPath = String(args["path"] ?? "");
605348
606164
  const oldStr = String(args["old_string"] ?? "");
605349
606165
  const newStr = String(args["new_string"] ?? "");
605350
- 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);
605351
606167
  if (!targetPath.startsWith(this.dreamsDir)) {
605352
606168
  return { success: false, output: "", error: "Dream mode: edits are confined to .omnius/dreams/", durationMs: Date.now() - start2 };
605353
606169
  }
@@ -606944,7 +607760,7 @@ var init_bless_engine = __esm({
606944
607760
 
606945
607761
  // packages/cli/src/tui/dmn-engine.ts
606946
607762
  import { existsSync as existsSync108, readFileSync as readFileSync87, writeFileSync as writeFileSync55, mkdirSync as mkdirSync62, readdirSync as readdirSync37, unlinkSync as unlinkSync19 } from "node:fs";
606947
- import { join as join122, basename as basename24 } from "node:path";
607763
+ import { join as join122, basename as basename25 } from "node:path";
606948
607764
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
606949
607765
  const competenceReport = competence.length > 0 ? competence.map((c9) => {
606950
607766
  const rate = c9.attempts > 0 ? Math.round(c9.successes / c9.attempts * 100) : 0;
@@ -607489,9 +608305,9 @@ OUTPUT: Call task_complete with JSON:
607489
608305
  confidence: this.extractConfidence(gateResult)
607490
608306
  });
607491
608307
  workspace.evidenceAccumulated = this.extractConfidence(gateResult);
607492
- 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";
607493
608309
  const evScore = Math.round(workspace.evidenceAccumulated * 100);
607494
- 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.`;
607495
608311
  workspace.innerVoice.push(voiceFinal);
607496
608312
  onEvent?.({
607497
608313
  type: "status",
@@ -607695,7 +608511,7 @@ OUTPUT: Call task_complete with JSON:
607695
608511
  try {
607696
608512
  const files = readdirSync37(dir).filter((f2) => f2.endsWith(".json"));
607697
608513
  for (const f2 of files) {
607698
- const topic = basename24(f2, ".json");
608514
+ const topic = basename25(f2, ".json");
607699
608515
  if (!topics.includes(topic)) topics.push(topic);
607700
608516
  }
607701
608517
  } catch {
@@ -607749,7 +608565,7 @@ OUTPUT: Call task_complete with JSON:
607749
608565
 
607750
608566
  // packages/cli/src/tui/snr-engine.ts
607751
608567
  import { existsSync as existsSync109, readdirSync as readdirSync38, readFileSync as readFileSync88 } from "node:fs";
607752
- import { join as join123, basename as basename25 } from "node:path";
608568
+ import { join as join123, basename as basename26 } from "node:path";
607753
608569
  function computeDPrime(signalScores, noiseScores) {
607754
608570
  if (signalScores.length === 0 || noiseScores.length === 0) return 0;
607755
608571
  const mean = (arr) => arr.reduce((s2, v) => s2 + v, 0) / arr.length;
@@ -608043,7 +608859,7 @@ Call task_complete with the JSON array when done.`,
608043
608859
  try {
608044
608860
  const files = readdirSync38(dir).filter((f2) => f2.endsWith(".json"));
608045
608861
  for (const f2 of files) {
608046
- const topic = basename25(f2, ".json");
608862
+ const topic = basename26(f2, ".json");
608047
608863
  if (topics.length > 0 && !topics.includes(topic)) continue;
608048
608864
  try {
608049
608865
  const data = JSON.parse(readFileSync88(join123(dir, f2), "utf-8"));
@@ -609526,7 +610342,7 @@ import {
609526
610342
  } from "node:fs";
609527
610343
  import { mkdir as mkdir19 } from "node:fs/promises";
609528
610344
  import {
609529
- basename as basename26,
610345
+ basename as basename27,
609530
610346
  dirname as dirname34,
609531
610347
  extname as extname15,
609532
610348
  isAbsolute as isAbsolute7,
@@ -609760,7 +610576,7 @@ function guardPath(root, rawPath) {
609760
610576
  error: `Path escapes the public creative workspace. Use a relative path under ${rootAbs}.`
609761
610577
  };
609762
610578
  }
609763
- if (basename26(abs) === MANIFEST_FILE) {
610579
+ if (basename27(abs) === MANIFEST_FILE) {
609764
610580
  return { ok: false, error: "The creative workspace manifest is internal and cannot be edited." };
609765
610581
  }
609766
610582
  return { ok: true, path: { abs, rel } };
@@ -609852,7 +610668,7 @@ function rememberCreated(root, absPath) {
609852
610668
  manifest.objects[rel] = {
609853
610669
  logicalRel: rel,
609854
610670
  storedRel,
609855
- originalName: basename26(guarded.path.abs),
610671
+ originalName: basename27(guarded.path.abs),
609856
610672
  prefixBytes: prefix.length,
609857
610673
  encrypted: true,
609858
610674
  key: key.toString("base64"),
@@ -609903,7 +610719,7 @@ function materializeTelegramCreativeArtifactForSend(root, rawPath) {
609903
610719
  }
609904
610720
  const stageDir = join124(rootAbs, SEND_DIR, `${Date.now()}-${randomBytes21(8).toString("hex")}`);
609905
610721
  mkdirSync63(stageDir, { recursive: true });
609906
- const staged = join124(stageDir, object.originalName || basename26(rel));
610722
+ const staged = join124(stageDir, object.originalName || basename27(rel));
609907
610723
  writeFileSync56(staged, payload);
609908
610724
  return {
609909
610725
  ok: true,
@@ -610214,23 +611030,23 @@ var init_stimulation = __esm({
610214
611030
  context: this.formatContext(input.channelId)
610215
611031
  };
610216
611032
  }
610217
- applyAgentDecision(channelId, decision, nowMs = Date.now()) {
611033
+ applyAgentDecision(channelId, decision2, nowMs = Date.now()) {
610218
611034
  const state = this.stateFor(channelId, nowMs);
610219
- if (Number.isFinite(decision.attentionScore)) {
610220
- state.attention = clamp017(Number(decision.attentionScore));
610221
- } else if (Number.isFinite(decision.attentionDelta)) {
610222
- 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));
610223
611039
  } else {
610224
- state.attention = clamp017(state.attention + (decision.shouldReply ? 0.22 : -0.1));
611040
+ state.attention = clamp017(state.attention + (decision2.shouldReply ? 0.22 : -0.1));
610225
611041
  }
610226
- if (decision.phase) {
610227
- state.attention = Math.max(state.attention, PHASE_FLOORS[decision.phase]);
610228
- state.phase = decision.phase;
611042
+ if (decision2.phase) {
611043
+ state.attention = Math.max(state.attention, PHASE_FLOORS[decision2.phase]);
611044
+ state.phase = decision2.phase;
610229
611045
  } else {
610230
611046
  state.phase = phaseFromAttention(state.attention);
610231
611047
  }
610232
- state.consecutiveNoReply = decision.shouldReply ? 0 : state.consecutiveNoReply + 1;
610233
- 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;
610234
611050
  state.lastAnalysisAtMs = nowMs;
610235
611051
  state.messagesSinceAnalysis = 0;
610236
611052
  state.updatedAtMs = nowMs;
@@ -611316,7 +612132,7 @@ function buildTelegramReflectionExtractionPrompt(options2) {
611316
612132
  episodes || "none"
611317
612133
  ].join("\n");
611318
612134
  }
611319
- function parseJsonObject(raw) {
612135
+ function parseJsonObject2(raw) {
611320
612136
  const text = raw.trim();
611321
612137
  if (!text) return null;
611322
612138
  const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i)?.[1]?.trim();
@@ -611330,7 +612146,7 @@ function parseJsonObject(raw) {
611330
612146
  }
611331
612147
  }
611332
612148
  function parseTelegramReflectionExtraction(raw) {
611333
- const parsed = parseJsonObject(raw);
612149
+ const parsed = parseJsonObject2(raw);
611334
612150
  if (!parsed) return null;
611335
612151
  const tags = Array.isArray(parsed.tags) ? parsed.tags.map((item) => {
611336
612152
  const obj = item;
@@ -612368,7 +613184,7 @@ var init_vision_ingress = __esm({
612368
613184
 
612369
613185
  // packages/cli/src/tui/telegram-bridge.ts
612370
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";
612371
- 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";
612372
613188
  import { homedir as homedir40 } from "node:os";
612373
613189
  import { writeFile as writeFileAsync } from "node:fs/promises";
612374
613190
  import { createHash as createHash24, randomBytes as randomBytes22, randomInt } from "node:crypto";
@@ -614623,25 +615439,25 @@ External acquisition contract:
614623
615439
  this.subAgentViewCallbacks.onStatus(viewId, "running");
614624
615440
  return viewId;
614625
615441
  }
614626
- writeTelegramAttentionDecision(viewId, decision) {
614627
- const route = decision.shouldReply ? `reply via ${decision.route}` : "silent";
615442
+ writeTelegramAttentionDecision(viewId, decision2) {
615443
+ const route = decision2.shouldReply ? `reply via ${decision2.route}` : "silent";
614628
615444
  const attention = [
614629
- decision.attentionState ? `state=${decision.attentionState}` : "",
614630
- decision.attentionDelta !== void 0 ? `delta=${decision.attentionDelta.toFixed(2)}` : "",
614631
- 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)}` : ""
614632
615448
  ].filter(Boolean).join(", ");
614633
615449
  const cadence = [
614634
- decision.nextCheckAfterMessages !== void 0 ? `after ${decision.nextCheckAfterMessages} message(s)` : ""
615450
+ decision2.nextCheckAfterMessages !== void 0 ? `after ${decision2.nextCheckAfterMessages} message(s)` : ""
614635
615451
  ].filter(Boolean).join(" or ");
614636
615452
  const lines = [
614637
- `decision: ${route} (${decision.source}, confidence ${decision.confidence.toFixed(2)})`,
615453
+ `decision: ${route} (${decision2.source}, confidence ${decision2.confidence.toFixed(2)})`,
614638
615454
  attention ? `attention: ${attention}` : "",
614639
- `reason: ${decision.reason}`,
614640
- decision.diagnosticNote ? `router diagnostic: ${decision.diagnosticNote}` : "",
614641
- decision.silentDisposition ? `silent disposition: ${decision.silentDisposition}` : "",
614642
- decision.mentalNote ? `mental note: ${decision.mentalNote}` : "",
614643
- decision.memoryNote ? `memory note: ${decision.memoryNote}` : "",
614644
- 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}` : "",
614645
615461
  cadence ? `next attention sample: ${cadence}` : ""
614646
615462
  ].filter(Boolean);
614647
615463
  if (viewId && this.subAgentViewCallbacks) {
@@ -614650,15 +615466,15 @@ External acquisition contract:
614650
615466
  this.subAgentViewCallbacks.onComplete(viewId);
614651
615467
  }
614652
615468
  }
614653
- mirrorTelegramAttentionDecision(msg, decision) {
614654
- const route = decision.shouldReply ? `reply via ${decision.route}` : "silent";
614655
- 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}`;
614656
615472
  const notes2 = [
614657
- decision.diagnosticNote ? `router diagnostic: ${decision.diagnosticNote}` : "",
614658
- decision.silentDisposition ? `silent reflection: ${decision.silentDisposition}` : "",
614659
- decision.mentalNote ? `mental note: ${decision.mentalNote}` : "",
614660
- decision.memoryNote ? `memory note: ${decision.memoryNote}` : "",
614661
- 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}` : ""
614662
615478
  ].filter(Boolean);
614663
615479
  this.tuiWrite(() => {
614664
615480
  renderTelegramSubAgentEvent(msg.username, primary);
@@ -614667,17 +615483,17 @@ External acquisition contract:
614667
615483
  }
614668
615484
  });
614669
615485
  }
614670
- deliverTelegramAttentionDecision(sessionKey, msg, viewId, decision, salienceSignals, daydreamOpportunities = this.latestTelegramDaydreamOpportunityInputs(sessionKey)) {
614671
- this.writeTelegramAttentionDecision(viewId, decision);
614672
- 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);
614673
615489
  this.commitTelegramSocialDecision(
614674
615490
  sessionKey,
614675
615491
  msg,
614676
- decision,
615492
+ decision2,
614677
615493
  salienceSignals,
614678
615494
  daydreamOpportunities
614679
615495
  );
614680
- this.applyTelegramStimulationDecision(sessionKey, decision);
615496
+ this.applyTelegramStimulationDecision(sessionKey, decision2);
614681
615497
  }
614682
615498
  normalizeTelegramCommandText(input) {
614683
615499
  const trimmed = input.trim();
@@ -616024,40 +616840,40 @@ ${mediaContext}` : ""
616024
616840
  timeoutMs: Math.min(Math.max(this.agentConfig.timeoutMs ?? 3e4, 5e3), 2e4),
616025
616841
  think: false
616026
616842
  });
616027
- const decision = parseTelegramReflectionFollowupDecision(result.choices[0]?.message?.content ?? "");
616843
+ const decision2 = parseTelegramReflectionFollowupDecision(result.choices[0]?.message?.content ?? "");
616028
616844
  state.lastFollowupArtifactAt = artifact.generatedAt;
616029
- if (!decision) {
616845
+ if (!decision2) {
616030
616846
  this.saveTelegramConversationState(sessionKey);
616031
616847
  return { sent: false, reason: "model returned no usable follow-up decision" };
616032
616848
  }
616033
- if (!decision.shouldSend || !decision.text || decision.confidence < 0.66) {
616849
+ if (!decision2.shouldSend || !decision2.text || decision2.confidence < 0.66) {
616034
616850
  this.saveTelegramConversationState(sessionKey);
616035
- return { sent: false, reason: decision.reason || "model chose silence" };
616851
+ return { sent: false, reason: decision2.reason || "model chose silence" };
616036
616852
  }
616037
- 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;
616038
616854
  const chatId = this.telegramChatIdFromArtifact(artifact);
616039
616855
  const sentMessageId = await this.sendMessageHTML(
616040
616856
  chatId,
616041
- convertMarkdownToTelegramHTML(decision.text),
616857
+ convertMarkdownToTelegramHTML(decision2.text),
616042
616858
  replyTo
616043
616859
  );
616044
616860
  this.recordTelegramAssistantMessage({
616045
616861
  chatId,
616046
616862
  chatType: artifact.chatType,
616047
616863
  chatTitle: artifact.chatTitle,
616048
- text: decision.text,
616864
+ text: decision2.text,
616049
616865
  username: this.state.botUsername || "omnius",
616050
616866
  firstName: "Omnius",
616051
616867
  fromUserId: 0,
616052
616868
  messageId: sentMessageId ?? 0
616053
- }, decision.text, "chat", {
616869
+ }, decision2.text, "chat", {
616054
616870
  messageId: sentMessageId,
616055
616871
  replyToMessageId: replyTo
616056
616872
  });
616057
616873
  state.lastFollowupAt = now;
616058
616874
  this.saveTelegramConversationState(sessionKey);
616059
- this.tuiWrite(() => renderTelegramSubAgentEvent("reflection", `sent scoped Telegram follow-up (${decision.confidence.toFixed(2)}): ${decision.reason}`));
616060
- 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 };
616061
616877
  } catch (err) {
616062
616878
  state.lastFollowupArtifactAt = artifact.generatedAt;
616063
616879
  this.saveTelegramConversationState(sessionKey);
@@ -616107,7 +616923,7 @@ ${mediaContext}` : ""
616107
616923
  }
616108
616924
  return opportunities;
616109
616925
  }
616110
- commitTelegramSocialDecision(sessionKey, msg, decision, salienceSignals, daydreamOpportunities = this.latestTelegramDaydreamOpportunityInputs(sessionKey)) {
616926
+ commitTelegramSocialDecision(sessionKey, msg, decision2, salienceSignals, daydreamOpportunities = this.latestTelegramDaydreamOpportunityInputs(sessionKey)) {
616111
616927
  try {
616112
616928
  commitTelegramSocialDecision(this.telegramSocialStateForSession(sessionKey), {
616113
616929
  sessionKey,
@@ -616116,15 +616932,15 @@ ${mediaContext}` : ""
616116
616932
  messageThreadId: msg.messageThreadId,
616117
616933
  sender: this.telegramMessageSocialActorInput(msg),
616118
616934
  replyToMessageId: msg.replyToMessageId,
616119
- route: decision.route,
616120
- shouldReply: decision.shouldReply,
616121
- confidence: decision.confidence,
616122
- reason: decision.reason,
616123
- source: decision.source,
616124
- silentDisposition: decision.silentDisposition,
616125
- mentalNote: decision.mentalNote,
616126
- memoryNote: decision.memoryNote,
616127
- 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,
616128
616944
  salienceSignals,
616129
616945
  self: this.telegramSelfSocialActorInput(),
616130
616946
  daydreamOpportunities
@@ -616349,7 +617165,7 @@ ${mediaContext}` : ""
616349
617165
  }
616350
617166
  const matchingEntry = mediaEntries.find((entry) => {
616351
617167
  if (resolve43(entry.localPath) === resolve43(raw)) return true;
616352
- if (basename27(entry.localPath) === raw) return true;
617168
+ if (basename28(entry.localPath) === raw) return true;
616353
617169
  if (entry.fileUniqueId === raw || entry.fileId === raw) return true;
616354
617170
  if (entry.messageId && String(entry.messageId) === raw) return true;
616355
617171
  if (entry.messageId && `message_id:${entry.messageId}` === raw.toLowerCase()) return true;
@@ -616386,7 +617202,7 @@ ${mediaContext}` : ""
616386
617202
  }
616387
617203
  return entries.find((entry2) => {
616388
617204
  if (resolve43(entry2.localPath) === resolve43(ref)) return true;
616389
- if (basename27(entry2.localPath) === ref) return true;
617205
+ if (basename28(entry2.localPath) === ref) return true;
616390
617206
  if (entry2.fileUniqueId === ref || entry2.fileId === ref) return true;
616391
617207
  if (entry2.messageId && String(entry2.messageId) === ref) return true;
616392
617208
  return false;
@@ -616414,7 +617230,7 @@ ${mediaContext}` : ""
616414
617230
  caption: entry.caption
616415
617231
  },
616416
617232
  modality,
616417
- label: `Telegram message_id ${entry.messageId || "unknown"} ${basename27(entry.localPath)}`,
617233
+ label: `Telegram message_id ${entry.messageId || "unknown"} ${basename28(entry.localPath)}`,
616418
617234
  extractedContent: entry.extractedContent
616419
617235
  };
616420
617236
  }
@@ -617523,8 +618339,8 @@ ${cardLines.join("\n")}`);
617523
618339
  const caption = entry.caption ? ` caption=${telegramContextJsonString(entry.caption, 120)}` : "";
617524
618340
  const extracted = entry.extractedContent ? `
617525
618341
  extracted=${telegramContextJsonString(entry.extractedContent.replace(/\s+/g, " "), 220)}` : "";
617526
- const alias = entry.messageId ? `message_id:${entry.messageId}` : basename27(entry.localPath);
617527
- 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}`;
617528
618344
  });
617529
618345
  sections.push([
617530
618346
  "### Recent Chat Media",
@@ -617635,13 +618451,13 @@ ${lines.join("\n")}`);
617635
618451
  const resolvedReply = this.resolveTelegramReplyContext(this.sessionKeyForMessage(msg), msg);
617636
618452
  return Boolean(resolvedReply?.sender?.isSelf);
617637
618453
  }
617638
- applyTelegramStimulationDecision(sessionKey, decision) {
618454
+ applyTelegramStimulationDecision(sessionKey, decision2) {
617639
618455
  this.stimulation.applyAgentDecision(sessionKey, {
617640
- shouldReply: decision.shouldReply,
617641
- phase: decision.attentionState,
617642
- attentionDelta: decision.attentionDelta,
617643
- attentionScore: decision.attentionScore,
617644
- nextAnalysisAfterMessages: decision.nextCheckAfterMessages
618456
+ shouldReply: decision2.shouldReply,
618457
+ phase: decision2.attentionState,
618458
+ attentionDelta: decision2.attentionDelta,
618459
+ attentionScore: decision2.attentionScore,
618460
+ nextAnalysisAfterMessages: decision2.nextCheckAfterMessages
617645
618461
  });
617646
618462
  }
617647
618463
  async telegramRouterJsonCompletion(backend, request, diagnostics) {
@@ -618824,22 +619640,22 @@ Join: ${newUrl}`);
618824
619640
  const isGroup = msg.chatType !== "private";
618825
619641
  if (isGroup) {
618826
619642
  const attentionViewId2 = this.registerTelegramAttentionView(msg, existing.toolContext || toolContext, "active Telegram thread");
618827
- const decision2 = await this.inferTelegramInteractionDecision(msg, existing.toolContext || toolContext);
619643
+ const decision3 = await this.inferTelegramInteractionDecision(msg, existing.toolContext || toolContext);
618828
619644
  this.deliverTelegramAttentionDecision(
618829
619645
  sessionKey,
618830
619646
  msg,
618831
619647
  attentionViewId2,
618832
- decision2,
619648
+ decision3,
618833
619649
  this.telegramMessageIdentitySalienceSignals(msg),
618834
619650
  this.markLatestTelegramDaydreamOpportunitiesConsidered(sessionKey, msg)
618835
619651
  );
618836
- this.markLastTelegramUserMessageMode(msg, decision2.shouldReply ? "steering" : "ambient");
619652
+ this.markLastTelegramUserMessageMode(msg, decision3.shouldReply ? "steering" : "ambient");
618837
619653
  this.subAgentViewCallbacks?.onWrite(
618838
619654
  existing.viewId,
618839
- `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}`
618840
619656
  );
618841
- if (!decision2.shouldReply) {
618842
- this.maybeLogTelegramGroupSkip(msg, `live inference: no steering — ${decision2.reason}`);
619657
+ if (!decision3.shouldReply) {
619658
+ this.maybeLogTelegramGroupSkip(msg, `live inference: no steering — ${decision3.reason}`);
618843
619659
  return;
618844
619660
  }
618845
619661
  }
@@ -618868,25 +619684,25 @@ Join: ${newUrl}`);
618868
619684
  return;
618869
619685
  }
618870
619686
  const attentionViewId = this.registerTelegramAttentionView(msg, toolContext);
618871
- const decision = await this.inferTelegramInteractionDecision(msg, toolContext);
619687
+ const decision2 = await this.inferTelegramInteractionDecision(msg, toolContext);
618872
619688
  this.deliverTelegramAttentionDecision(
618873
619689
  sessionKey,
618874
619690
  msg,
618875
619691
  attentionViewId,
618876
- decision,
619692
+ decision2,
618877
619693
  this.telegramMessageIdentitySalienceSignals(msg),
618878
619694
  this.markLatestTelegramDaydreamOpportunitiesConsidered(sessionKey, msg)
618879
619695
  );
618880
- this.markLastTelegramUserMessageMode(msg, decision.shouldReply ? decision.route : "ambient");
619696
+ this.markLastTelegramUserMessageMode(msg, decision2.shouldReply ? decision2.route : "ambient");
618881
619697
  this.subAgentViewCallbacks?.onWrite(
618882
619698
  this.viewIdForMessage(msg),
618883
- `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}`
618884
619700
  );
618885
- if (!decision.shouldReply) {
618886
- this.maybeLogTelegramGroupSkip(msg, `live inference: no reply — ${decision.reason}`);
619701
+ if (!decision2.shouldReply) {
619702
+ this.maybeLogTelegramGroupSkip(msg, `live inference: no reply — ${decision2.reason}`);
618887
619703
  return;
618888
619704
  }
618889
- if (decision.route === "chat") {
619705
+ if (decision2.route === "chat") {
618890
619706
  await this.handleTelegramChatCompletion(msg, toolContext);
618891
619707
  return;
618892
619708
  }
@@ -621203,12 +622019,12 @@ Scoped workspace: ${scopedRoot}`,
621203
622019
  };
621204
622020
  });
621205
622021
  const dryRun = effective.dryRunByDefault === true;
621206
- const requireAdmin = effective.requireAdminForMutation !== false;
622022
+ const requireAdmin2 = effective.requireAdminForMutation !== false;
621207
622023
  const keyboard = [];
621208
622024
  for (let idx = 0; idx < rows.length; idx += 2) keyboard.push(rows.slice(idx, idx + 2));
621209
622025
  keyboard.push([
621210
622026
  { text: `${dryRun ? "[x]" : "[ ]"} Dry run`, callback_data: `omni:v1:tgtool:${state.nonce}:flag:dryrun` },
621211
- { 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` }
621212
622028
  ]);
621213
622029
  const scopeLabel = state.policyScope === "chat" ? `chat ${String(state.policyChatId)}` : "global";
621214
622030
  return {
@@ -621559,12 +622375,12 @@ Scoped workspace: ${scopedRoot}`,
621559
622375
  return { success: true, output: `No recent ${kind} media is available in this Telegram chat scope.`, durationMs: performance.now() - start2 };
621560
622376
  }
621561
622377
  const lines = entries.map((entry, index) => {
621562
- const pathAlias = entry.messageId ? `message_id:${entry.messageId}` : basename27(entry.localPath);
622378
+ const pathAlias = entry.messageId ? `message_id:${entry.messageId}` : basename28(entry.localPath);
621563
622379
  const parts = [
621564
622380
  `${index + 1}. message_id ${entry.messageId || "unknown"}`,
621565
622381
  currentMsg?.replyToMessageId === entry.messageId ? "replied-to" : "",
621566
622382
  telegramCachedMediaIsImage(entry) ? "image" : telegramCachedMediaIsPdf(entry) ? "pdf" : telegramCachedMediaIsAudio(entry) ? "audio" : telegramCachedMediaIsVideo(entry) ? "video" : entry.mediaType,
621567
- `file=${basename27(entry.localPath)}`,
622383
+ `file=${basename28(entry.localPath)}`,
621568
622384
  `path_alias=${pathAlias}`,
621569
622385
  entry.caption ? `caption=${telegramContextJsonString(entry.caption, 140)}` : ""
621570
622386
  ].filter(Boolean);
@@ -621691,8 +622507,8 @@ Scoped workspace: ${scopedRoot}`,
621691
622507
  if (bridge.telegramFileSendAlreadyDeliveredForMessage(currentMsg, sendFingerprint)) {
621692
622508
  return {
621693
622509
  success: true,
621694
- output: `Telegram file already sent in this turn: ${basename27(file.path)} as ${kind} to ${String(target.chatId)}`,
621695
- 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.`,
621696
622512
  durationMs: performance.now() - start2,
621697
622513
  mutated: false,
621698
622514
  mutatedFiles: []
@@ -621709,8 +622525,8 @@ Scoped workspace: ${scopedRoot}`,
621709
622525
  bridge.rememberTelegramDeliveredArtifactForMessage(currentMsg, ledgerPath);
621710
622526
  return {
621711
622527
  success: true,
621712
- output: `Sent Telegram file: ${basename27(file.path)} as ${kind} to ${String(target.chatId)}${messageId ? ` (message_id ${messageId})` : ""}`,
621713
- 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}.`,
621714
622530
  durationMs: performance.now() - start2,
621715
622531
  mutated: false,
621716
622532
  mutatedFiles: []
@@ -622164,7 +622980,7 @@ ${text}`.trim());
622164
622980
  if (!existsSync113(media.value)) throw new Error(`File does not exist: ${media.value}`);
622165
622981
  const buffer2 = readFileSync92(media.value);
622166
622982
  const boundary = `----omnius-media-${Date.now()}-${Math.random().toString(36).slice(2)}`;
622167
- const filename = basename27(media.value);
622983
+ const filename = basename28(media.value);
622168
622984
  const contentType = mimeForPath(media.value, media.kind);
622169
622985
  const parts = [];
622170
622986
  const addField = (name10, value2) => {
@@ -622404,7 +623220,7 @@ Content-Type: ${contentType}\r
622404
623220
  continue;
622405
623221
  }
622406
623222
  const buffer2 = readFileSync92(pathOrFileId);
622407
- const filename = basename27(pathOrFileId);
623223
+ const filename = basename28(pathOrFileId);
622408
623224
  parts.push(Buffer.from(`--${boundary}\r
622409
623225
  `));
622410
623226
  parts.push(Buffer.from(
@@ -623506,7 +624322,7 @@ __export(projects_exports, {
623506
624322
  });
623507
624323
  import { readFileSync as readFileSync94, writeFileSync as writeFileSync61, mkdirSync as mkdirSync67, existsSync as existsSync115, statSync as statSync40, renameSync as renameSync7 } from "node:fs";
623508
624324
  import { homedir as homedir42 } from "node:os";
623509
- 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";
623510
624326
  import { randomUUID as randomUUID14 } from "node:crypto";
623511
624327
  function readAll2() {
623512
624328
  try {
@@ -623554,7 +624370,7 @@ function registerProject(root, pid) {
623554
624370
  } else {
623555
624371
  entry = {
623556
624372
  root: canonical,
623557
- name: basename28(canonical) || canonical,
624373
+ name: basename29(canonical) || canonical,
623558
624374
  firstSeen: now,
623559
624375
  lastSeen: now,
623560
624376
  pid: pid ?? null,
@@ -626929,6 +627745,8 @@ async function tryRouteV1(ctx3) {
626929
627745
  if (pathname === "/v1/tor/status" && method === "GET") return handleTorStatus(ctx3);
626930
627746
  if (pathname === "/v1/tor/enable" && method === "POST") return handleTorEnable(ctx3);
626931
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);
626932
627750
  if (pathname === "/v1/tools" && method === "GET") {
626933
627751
  return handleListTools(ctx3);
626934
627752
  }
@@ -627274,6 +628092,109 @@ async function handleCallMcp(ctx3, name10) {
627274
628092
  return true;
627275
628093
  }
627276
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
+ }
627277
628198
  function memoryDbPaths2(baseDir = process.cwd()) {
627278
628199
  const dir = join136(baseDir, ".omnius");
627279
628200
  return {
@@ -638345,6 +639266,7 @@ function getOpenApiSpec() {
638345
639266
  { name: "Sessions", description: "Omnius task session archive" },
638346
639267
  { name: "Context", description: "Session context save/restore/compact" },
638347
639268
  { name: "Nexus", description: "P2P peer mesh and sponsor directory" },
639269
+ { name: "Ollama", description: "Local Ollama pool status and process hygiene" },
638348
639270
  { name: "Tools", description: "Agentic tool registry" },
638349
639271
  { name: "Engines", description: "Long-running TUI engines (dream, bless, call, listen, telegram, expose)" },
638350
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)." },
@@ -638507,6 +639429,23 @@ function getOpenApiSpec() {
638507
639429
  }
638508
639430
  },
638509
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
+ },
638510
639449
  // ───── PT-02: Skills ─────
638511
639450
  "/v1/skills": {
638512
639451
  get: {
@@ -639688,7 +640627,7 @@ __export(embedding_workers_exports, {
639688
640627
  startEmbeddingWorkers: () => startEmbeddingWorkers,
639689
640628
  stopEmbeddingWorkers: () => stopEmbeddingWorkers
639690
640629
  });
639691
- import { basename as basename29, join as join140 } from "node:path";
640630
+ import { basename as basename30, join as join140 } from "node:path";
639692
640631
  function startEmbeddingWorkers(opts) {
639693
640632
  if (_running) return;
639694
640633
  _running = true;
@@ -639754,7 +640693,7 @@ async function runEmbeddingTask(modality, episodeId, taskId, opts) {
639754
640693
  try {
639755
640694
  if (!_aligner) {
639756
640695
  const stateRoot = process.env.OMNIUS_DIR || process.cwd();
639757
- const omniusDir = basename29(stateRoot) === ".omnius" ? stateRoot : join140(stateRoot, ".omnius");
640696
+ const omniusDir = basename30(stateRoot) === ".omnius" ? stateRoot : join140(stateRoot, ".omnius");
639758
640697
  const memDir = join140(omniusDir, "memory");
639759
640698
  _aligner = new EmbeddingAligner(
639760
640699
  `${modality}-${emb.length}`,