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 +1131 -192
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
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
|
|
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() ===
|
|
131801
|
+
if (allowed.toLowerCase() === requestOrigin2) {
|
|
131802
131802
|
isAllowed = true;
|
|
131803
131803
|
break;
|
|
131804
131804
|
}
|
|
131805
|
-
} else if (allowed.test(
|
|
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
|
|
246349
|
-
return endsWithSlashGlobStar(pattern) || isStaticPattern(
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
406910
|
-
if (
|
|
406911
|
-
const name10 = removeSuffix(removePrefix(
|
|
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
|
|
470838
|
-
if (
|
|
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
|
|
474523
|
-
if (((_a = result.affectedModuleSpecifierCacheProjects) == null ? void 0 : _a.size) && (
|
|
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
|
|
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:
|
|
524124
|
+
const { execFile: execFile8 } = await import("node:child_process");
|
|
524125
524125
|
const { promisify: promisify7 } = await import("node:util");
|
|
524126
|
-
const execFileAsync5 = promisify7(
|
|
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(
|
|
524292
|
+
evaluate(decision2) {
|
|
524293
524293
|
this.attemptCount += 1;
|
|
524294
|
-
if (
|
|
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 (
|
|
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 (
|
|
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 =
|
|
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 ${
|
|
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
|
|
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 =
|
|
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,
|
|
537422
|
-
state.toolDecisions.push({ ...
|
|
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:
|
|
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, `${
|
|
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:
|
|
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, `${
|
|
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
|
|
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
|
-
|
|
562823
|
-
|
|
562824
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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(
|
|
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,
|
|
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
|
-
|
|
571865
|
-
HEADER_ACCENT_BOLD_FG = `\x1B[1;38;5;${
|
|
571866
|
-
HEADER_BUTTON_BG = `\x1B[48;5;${
|
|
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
|
-
|
|
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
|
-
|
|
575018
|
-
|
|
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
|
|
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) ||
|
|
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 =
|
|
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:
|
|
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 =
|
|
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:
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 ${
|
|
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 ${
|
|
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
|
|
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:
|
|
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 ||
|
|
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
|
|
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 =
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 (
|
|
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:
|
|
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 ||
|
|
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,
|
|
611033
|
+
applyAgentDecision(channelId, decision2, nowMs = Date.now()) {
|
|
610218
611034
|
const state = this.stateFor(channelId, nowMs);
|
|
610219
|
-
if (Number.isFinite(
|
|
610220
|
-
state.attention = clamp017(Number(
|
|
610221
|
-
} else if (Number.isFinite(
|
|
610222
|
-
state.attention = clamp017(state.attention + Number(
|
|
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 + (
|
|
611040
|
+
state.attention = clamp017(state.attention + (decision2.shouldReply ? 0.22 : -0.1));
|
|
610225
611041
|
}
|
|
610226
|
-
if (
|
|
610227
|
-
state.attention = Math.max(state.attention, PHASE_FLOORS[
|
|
610228
|
-
state.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 =
|
|
610233
|
-
state.nextAnalysisAfterMessages = Number.isFinite(
|
|
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
|
|
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 =
|
|
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
|
|
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,
|
|
614627
|
-
const route =
|
|
615442
|
+
writeTelegramAttentionDecision(viewId, decision2) {
|
|
615443
|
+
const route = decision2.shouldReply ? `reply via ${decision2.route}` : "silent";
|
|
614628
615444
|
const attention = [
|
|
614629
|
-
|
|
614630
|
-
|
|
614631
|
-
|
|
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
|
-
|
|
615450
|
+
decision2.nextCheckAfterMessages !== void 0 ? `after ${decision2.nextCheckAfterMessages} message(s)` : ""
|
|
614635
615451
|
].filter(Boolean).join(" or ");
|
|
614636
615452
|
const lines = [
|
|
614637
|
-
`decision: ${route} (${
|
|
615453
|
+
`decision: ${route} (${decision2.source}, confidence ${decision2.confidence.toFixed(2)})`,
|
|
614638
615454
|
attention ? `attention: ${attention}` : "",
|
|
614639
|
-
`reason: ${
|
|
614640
|
-
|
|
614641
|
-
|
|
614642
|
-
|
|
614643
|
-
|
|
614644
|
-
|
|
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,
|
|
614654
|
-
const route =
|
|
614655
|
-
const primary = `attention decision: ${route} (${
|
|
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
|
-
|
|
614658
|
-
|
|
614659
|
-
|
|
614660
|
-
|
|
614661
|
-
|
|
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,
|
|
614671
|
-
this.writeTelegramAttentionDecision(viewId,
|
|
614672
|
-
this.mirrorTelegramAttentionDecision(msg,
|
|
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
|
-
|
|
615492
|
+
decision2,
|
|
614677
615493
|
salienceSignals,
|
|
614678
615494
|
daydreamOpportunities
|
|
614679
615495
|
);
|
|
614680
|
-
this.applyTelegramStimulationDecision(sessionKey,
|
|
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
|
|
616843
|
+
const decision2 = parseTelegramReflectionFollowupDecision(result.choices[0]?.message?.content ?? "");
|
|
616028
616844
|
state.lastFollowupArtifactAt = artifact.generatedAt;
|
|
616029
|
-
if (!
|
|
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 (!
|
|
616849
|
+
if (!decision2.shouldSend || !decision2.text || decision2.confidence < 0.66) {
|
|
616034
616850
|
this.saveTelegramConversationState(sessionKey);
|
|
616035
|
-
return { sent: false, reason:
|
|
616851
|
+
return { sent: false, reason: decision2.reason || "model chose silence" };
|
|
616036
616852
|
}
|
|
616037
|
-
const replyTo =
|
|
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(
|
|
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:
|
|
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
|
-
},
|
|
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 (${
|
|
616060
|
-
return { sent: true, 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,
|
|
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:
|
|
616120
|
-
shouldReply:
|
|
616121
|
-
confidence:
|
|
616122
|
-
reason:
|
|
616123
|
-
source:
|
|
616124
|
-
silentDisposition:
|
|
616125
|
-
mentalNote:
|
|
616126
|
-
memoryNote:
|
|
616127
|
-
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 (
|
|
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 (
|
|
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"} ${
|
|
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}` :
|
|
617527
|
-
return `- ${alias}${replyMark}: ${kind}; file ${
|
|
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,
|
|
618454
|
+
applyTelegramStimulationDecision(sessionKey, decision2) {
|
|
617639
618455
|
this.stimulation.applyAgentDecision(sessionKey, {
|
|
617640
|
-
shouldReply:
|
|
617641
|
-
phase:
|
|
617642
|
-
attentionDelta:
|
|
617643
|
-
attentionScore:
|
|
617644
|
-
nextAnalysisAfterMessages:
|
|
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
|
|
619643
|
+
const decision3 = await this.inferTelegramInteractionDecision(msg, existing.toolContext || toolContext);
|
|
618828
619644
|
this.deliverTelegramAttentionDecision(
|
|
618829
619645
|
sessionKey,
|
|
618830
619646
|
msg,
|
|
618831
619647
|
attentionViewId2,
|
|
618832
|
-
|
|
619648
|
+
decision3,
|
|
618833
619649
|
this.telegramMessageIdentitySalienceSignals(msg),
|
|
618834
619650
|
this.markLatestTelegramDaydreamOpportunitiesConsidered(sessionKey, msg)
|
|
618835
619651
|
);
|
|
618836
|
-
this.markLastTelegramUserMessageMode(msg,
|
|
619652
|
+
this.markLastTelegramUserMessageMode(msg, decision3.shouldReply ? "steering" : "ambient");
|
|
618837
619653
|
this.subAgentViewCallbacks?.onWrite(
|
|
618838
619654
|
existing.viewId,
|
|
618839
|
-
`live steering: ${
|
|
619655
|
+
`live steering: ${decision3.shouldReply ? decision3.route : "no_reply"} (${decision3.source}, confidence ${decision3.confidence.toFixed(2)}): ${decision3.reason}`
|
|
618840
619656
|
);
|
|
618841
|
-
if (!
|
|
618842
|
-
this.maybeLogTelegramGroupSkip(msg, `live inference: no steering — ${
|
|
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
|
|
619687
|
+
const decision2 = await this.inferTelegramInteractionDecision(msg, toolContext);
|
|
618872
619688
|
this.deliverTelegramAttentionDecision(
|
|
618873
619689
|
sessionKey,
|
|
618874
619690
|
msg,
|
|
618875
619691
|
attentionViewId,
|
|
618876
|
-
|
|
619692
|
+
decision2,
|
|
618877
619693
|
this.telegramMessageIdentitySalienceSignals(msg),
|
|
618878
619694
|
this.markLatestTelegramDaydreamOpportunitiesConsidered(sessionKey, msg)
|
|
618879
619695
|
);
|
|
618880
|
-
this.markLastTelegramUserMessageMode(msg,
|
|
619696
|
+
this.markLastTelegramUserMessageMode(msg, decision2.shouldReply ? decision2.route : "ambient");
|
|
618881
619697
|
this.subAgentViewCallbacks?.onWrite(
|
|
618882
619698
|
this.viewIdForMessage(msg),
|
|
618883
|
-
`live route: ${
|
|
619699
|
+
`live route: ${decision2.shouldReply ? decision2.route : "no_reply"} (${decision2.source}, confidence ${decision2.confidence.toFixed(2)}): ${decision2.reason}`
|
|
618884
619700
|
);
|
|
618885
|
-
if (!
|
|
618886
|
-
this.maybeLogTelegramGroupSkip(msg, `live inference: no reply — ${
|
|
619701
|
+
if (!decision2.shouldReply) {
|
|
619702
|
+
this.maybeLogTelegramGroupSkip(msg, `live inference: no reply — ${decision2.reason}`);
|
|
618887
619703
|
return;
|
|
618888
619704
|
}
|
|
618889
|
-
if (
|
|
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
|
|
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: `${
|
|
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}` :
|
|
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=${
|
|
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: ${
|
|
621695
|
-
llmContent: `Already sent ${
|
|
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: ${
|
|
621713
|
-
llmContent: `Sent ${
|
|
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 =
|
|
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 =
|
|
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
|
|
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:
|
|
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
|
|
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 =
|
|
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}`,
|