omnius 1.0.3 → 1.0.4
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 +295 -130
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7852,7 +7852,6 @@ var init_nexus = __esm({
|
|
|
7852
7852
|
* Usage: node nexus-daemon.mjs <nexus-dir> <agent-name> [agent-type]
|
|
7853
7853
|
*/
|
|
7854
7854
|
|
|
7855
|
-
import { NexusClient } from 'open-agents-nexus';
|
|
7856
7855
|
import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync, readdirSync, appendFileSync, watch as fsWatch } from 'node:fs';
|
|
7857
7856
|
import { join } from 'node:path';
|
|
7858
7857
|
import { homedir, hostname } from 'node:os';
|
|
@@ -7930,6 +7929,40 @@ const globalKeyDir = join(homedir(), '.omnius');
|
|
|
7930
7929
|
const globalKeyPath = join(globalKeyDir, 'identity.key');
|
|
7931
7930
|
const projectKeyPath = join(nexusDir, 'identity.key');
|
|
7932
7931
|
const keyPath = existsSync(globalKeyPath) ? globalKeyPath : projectKeyPath;
|
|
7932
|
+
|
|
7933
|
+
function formatStartupError(err) {
|
|
7934
|
+
if (!err) return 'Unknown startup error';
|
|
7935
|
+
var msg = err && err.stack ? String(err.stack) : String(err && err.message ? err.message : err);
|
|
7936
|
+
return msg.replace(/\\x1B\\[[0-?]*[ -/]*[@-~]/g, '').slice(0, 4000);
|
|
7937
|
+
}
|
|
7938
|
+
|
|
7939
|
+
async function loadNexusClientClass() {
|
|
7940
|
+
try {
|
|
7941
|
+
var mod = await import('open-agents-nexus');
|
|
7942
|
+
if (!mod || !mod.NexusClient) throw new Error('open-agents-nexus did not export NexusClient');
|
|
7943
|
+
return mod.NexusClient;
|
|
7944
|
+
} catch (err) {
|
|
7945
|
+
var msg = 'Failed to load open-agents-nexus: ' + formatStartupError(err);
|
|
7946
|
+
try { appendFileSync(join(nexusDir, 'daemon.err'), 'Nexus daemon dependency load failed: ' + msg + '\\n'); } catch {}
|
|
7947
|
+
try {
|
|
7948
|
+
writeFileSync(statusFile, JSON.stringify({
|
|
7949
|
+
pid: process.pid,
|
|
7950
|
+
connected: false,
|
|
7951
|
+
peerId: null,
|
|
7952
|
+
agentName: agentName,
|
|
7953
|
+
agentType: agentType,
|
|
7954
|
+
rooms: [],
|
|
7955
|
+
capabilities: [],
|
|
7956
|
+
blockedPeers: [],
|
|
7957
|
+
connectedAt: null,
|
|
7958
|
+
error: msg,
|
|
7959
|
+
}, null, 2));
|
|
7960
|
+
} catch {}
|
|
7961
|
+
process.exit(1);
|
|
7962
|
+
}
|
|
7963
|
+
}
|
|
7964
|
+
|
|
7965
|
+
const NexusClient = await loadNexusClientClass();
|
|
7933
7966
|
var nexusOpts = {
|
|
7934
7967
|
keyStorePath: keyPath,
|
|
7935
7968
|
agentName,
|
|
@@ -13188,6 +13221,21 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13188
13221
|
res((stdout || "").trim());
|
|
13189
13222
|
});
|
|
13190
13223
|
});
|
|
13224
|
+
const isNativeDataChannelError = (text) => /node-datachannel|node_datachannel\.node|datachannel\/dist/i.test(text);
|
|
13225
|
+
const tryRepairNodeDataChannel = async () => {
|
|
13226
|
+
const cmds = existsSync17(join21(this.repoRoot, "pnpm-lock.yaml")) ? ["pnpm rebuild node-datachannel 2>&1", "npm rebuild node-datachannel 2>&1"] : ["npm rebuild node-datachannel 2>&1", "pnpm rebuild node-datachannel 2>&1"];
|
|
13227
|
+
const failures = [];
|
|
13228
|
+
for (const cmd of cmds) {
|
|
13229
|
+
try {
|
|
13230
|
+
await execAsync3(cmd, { cwd: this.repoRoot, timeout: 18e4 });
|
|
13231
|
+
return `Repaired node-datachannel native addon with: ${cmd.replace(" 2>&1", "")}`;
|
|
13232
|
+
} catch (err) {
|
|
13233
|
+
failures.push(`${cmd.replace(" 2>&1", "")}: ${err?.message ?? String(err)}`.slice(0, 500));
|
|
13234
|
+
}
|
|
13235
|
+
}
|
|
13236
|
+
return `node-datachannel native addon repair failed:
|
|
13237
|
+
${failures.join("\n")}`;
|
|
13238
|
+
};
|
|
13191
13239
|
try {
|
|
13192
13240
|
const nexusPkg = join21(nodeModulesDir, "open-agents-nexus", "package.json");
|
|
13193
13241
|
if (existsSync17(nexusPkg)) {
|
|
@@ -13294,7 +13342,17 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13294
13342
|
errTail = (await readFile9(daemonErrPath, "utf8")).slice(-300);
|
|
13295
13343
|
} catch {
|
|
13296
13344
|
}
|
|
13297
|
-
|
|
13345
|
+
const statusError = String(status.error ?? "");
|
|
13346
|
+
if (!args.__native_repair_attempted && isNativeDataChannelError(`${statusError}
|
|
13347
|
+
${errTail}`)) {
|
|
13348
|
+
const repair = await tryRepairNodeDataChannel();
|
|
13349
|
+
if (/^Repaired /.test(repair)) {
|
|
13350
|
+
return this.doConnect({ ...args, __native_repair_attempted: true });
|
|
13351
|
+
}
|
|
13352
|
+
return `Nexus daemon failed to connect: ${statusError}
|
|
13353
|
+
${repair}${errTail ? "\n" + errTail : ""}`;
|
|
13354
|
+
}
|
|
13355
|
+
return `Nexus daemon failed to connect: ${statusError}${errTail ? "\n" + errTail : ""}`;
|
|
13298
13356
|
}
|
|
13299
13357
|
if (status.connected && status.peerId) {
|
|
13300
13358
|
return [
|
|
@@ -13320,6 +13378,17 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13320
13378
|
try {
|
|
13321
13379
|
earlyOutput = (await readFile9(daemonLogPath, "utf8")).slice(-500);
|
|
13322
13380
|
} catch {
|
|
13381
|
+
}
|
|
13382
|
+
const earlyCombined = `${earlyError}
|
|
13383
|
+
${earlyOutput}`;
|
|
13384
|
+
if (!args.__native_repair_attempted && isNativeDataChannelError(earlyCombined)) {
|
|
13385
|
+
const repair = await tryRepairNodeDataChannel();
|
|
13386
|
+
if (/^Repaired /.test(repair)) {
|
|
13387
|
+
return this.doConnect({ ...args, __native_repair_attempted: true });
|
|
13388
|
+
}
|
|
13389
|
+
return `Daemon failed to start.
|
|
13390
|
+
${repair}
|
|
13391
|
+
${earlyError ? "\n" + earlyError : ""}${earlyOutput ? "\n" + earlyOutput : ""}`;
|
|
13323
13392
|
}
|
|
13324
13393
|
if (pid) {
|
|
13325
13394
|
return `Daemon spawned (pid: ${pid}) but still connecting. Check status in a moment.${earlyError ? "\nStderr: " + earlyError.slice(0, 200) : ""}`;
|
|
@@ -549721,27 +549790,27 @@ var init_theme = __esm({
|
|
|
549721
549790
|
},
|
|
549722
549791
|
branding: {
|
|
549723
549792
|
mode: "branding",
|
|
549724
|
-
bg:
|
|
549725
|
-
//
|
|
549726
|
-
accent:
|
|
549727
|
-
//
|
|
549728
|
-
textPrimary:
|
|
549729
|
-
//
|
|
549793
|
+
bg: -1,
|
|
549794
|
+
// terminal default background
|
|
549795
|
+
accent: 37,
|
|
549796
|
+
// teal
|
|
549797
|
+
textPrimary: 37,
|
|
549798
|
+
// teal
|
|
549730
549799
|
textDim: 240,
|
|
549731
549800
|
// grey
|
|
549732
|
-
boxColor:
|
|
549733
|
-
//
|
|
549801
|
+
boxColor: 37
|
|
549802
|
+
// teal
|
|
549734
549803
|
},
|
|
549735
549804
|
custom: {
|
|
549736
549805
|
mode: "custom",
|
|
549737
|
-
bg:
|
|
549738
|
-
accent:
|
|
549806
|
+
bg: -1,
|
|
549807
|
+
accent: 37,
|
|
549739
549808
|
textPrimary: 252,
|
|
549740
549809
|
textDim: 245,
|
|
549741
549810
|
boxColor: 252
|
|
549742
549811
|
}
|
|
549743
549812
|
};
|
|
549744
|
-
_config2 = { ...PRESETS.
|
|
549813
|
+
_config2 = { ...PRESETS.system };
|
|
549745
549814
|
}
|
|
549746
549815
|
});
|
|
549747
549816
|
|
|
@@ -551291,10 +551360,10 @@ var init_render = __esm({
|
|
|
551291
551360
|
warn: (t2) => fg256(214, t2),
|
|
551292
551361
|
/** Success text — green for confirmations */
|
|
551293
551362
|
ok: (t2) => fg256(78, t2),
|
|
551294
|
-
/** Accent —
|
|
551295
|
-
accent: (t2) => fg256(
|
|
551296
|
-
/** Muted accent — dim
|
|
551297
|
-
accentDim: (t2) => fg256(
|
|
551363
|
+
/** Accent — teal matching header/banner */
|
|
551364
|
+
accent: (t2) => fg256(37, t2),
|
|
551365
|
+
/** Muted accent — dim teal for secondary accent */
|
|
551366
|
+
accentDim: (t2) => fg256(30, t2)
|
|
551298
551367
|
};
|
|
551299
551368
|
pastel = {
|
|
551300
551369
|
pink: (t2) => fg256(218, t2),
|
|
@@ -551402,11 +551471,11 @@ var init_render = __esm({
|
|
|
551402
551471
|
// User interaction
|
|
551403
551472
|
ask_user: "Ask user"
|
|
551404
551473
|
};
|
|
551405
|
-
accent = (t2) => fg256(
|
|
551406
|
-
accentBright = (t2) => fg256(
|
|
551407
|
-
accentDim = (t2) => fg256(
|
|
551408
|
-
accentWarm = (t2) => fg256(
|
|
551409
|
-
accentSoft = (t2) => fg256(
|
|
551474
|
+
accent = (t2) => fg256(37, t2);
|
|
551475
|
+
accentBright = (t2) => fg256(44, t2);
|
|
551476
|
+
accentDim = (t2) => fg256(30, t2);
|
|
551477
|
+
accentWarm = (t2) => fg256(43, t2);
|
|
551478
|
+
accentSoft = (t2) => fg256(80, t2);
|
|
551410
551479
|
TOOL_COLORS = {
|
|
551411
551480
|
file_read: accentSoft,
|
|
551412
551481
|
file_write: accentWarm,
|
|
@@ -557646,8 +557715,8 @@ var init_braille_spinner = __esm({
|
|
|
557646
557715
|
return (x * x * 31 + x * 17 + 59) % 97 / 97;
|
|
557647
557716
|
};
|
|
557648
557717
|
MOOD_RAMPS = {
|
|
557649
|
-
neutral: [237,
|
|
557650
|
-
// default
|
|
557718
|
+
neutral: [237, 24, 30, 36, 37, 43, 44, 50, 51],
|
|
557719
|
+
// default teal/cyan
|
|
557651
557720
|
success: [237, 22, 28, 34, 40, 46, 47, 48, 49],
|
|
557652
557721
|
// green pulse
|
|
557653
557722
|
error: [237, 52, 88, 124, 160, 196, 197, 203, 209],
|
|
@@ -557658,8 +557727,8 @@ var init_braille_spinner = __esm({
|
|
|
557658
557727
|
// purple contemplation
|
|
557659
557728
|
};
|
|
557660
557729
|
THEME_DEFAULT = {
|
|
557661
|
-
ramp: [237,
|
|
557662
|
-
// grey
|
|
557730
|
+
ramp: [237, 24, 30, 36, 37, 43, 44, 50, 51],
|
|
557731
|
+
// grey -> teal/cyan
|
|
557663
557732
|
speed: 2
|
|
557664
557733
|
};
|
|
557665
557734
|
THEME_FILE = {
|
|
@@ -557679,7 +557748,7 @@ var init_braille_spinner = __esm({
|
|
|
557679
557748
|
speed: 4
|
|
557680
557749
|
};
|
|
557681
557750
|
THEME_MEMORY = {
|
|
557682
|
-
ramp: [237,
|
|
557751
|
+
ramp: [237, 23, 29, 35, 36, 37, 43, 44, 50],
|
|
557683
557752
|
speed: 1
|
|
557684
557753
|
};
|
|
557685
557754
|
THEME_SKILL = {
|
|
@@ -557691,7 +557760,7 @@ var init_braille_spinner = __esm({
|
|
|
557691
557760
|
speed: 2
|
|
557692
557761
|
};
|
|
557693
557762
|
THEME_DREAM = {
|
|
557694
|
-
ramp: [237,
|
|
557763
|
+
ramp: [237, 24, 30, 36, 37, 43, 44, 50, 51],
|
|
557695
557764
|
speed: 1
|
|
557696
557765
|
};
|
|
557697
557766
|
DEFAULT_METRICS = {
|
|
@@ -558303,7 +558372,7 @@ var init_text_selection = __esm({
|
|
|
558303
558372
|
"packages/cli/src/tui/text-selection.ts"() {
|
|
558304
558373
|
"use strict";
|
|
558305
558374
|
init_layout2();
|
|
558306
|
-
SEL_BG =
|
|
558375
|
+
SEL_BG = 37;
|
|
558307
558376
|
SEL_FG = 30;
|
|
558308
558377
|
SEL_START = `\x1B[${SEL_FG}m\x1B[48;5;${SEL_BG}m`;
|
|
558309
558378
|
SEL_END = `\x1B[0m`;
|
|
@@ -559594,8 +559663,8 @@ var init_status_bar = __esm({
|
|
|
559594
559663
|
const decorateMenuButton = (cmd, label) => {
|
|
559595
559664
|
const isBranding = themeMode() === "branding";
|
|
559596
559665
|
if (isBranding) {
|
|
559597
|
-
const BRAND_BG =
|
|
559598
|
-
const BRAND_FG =
|
|
559666
|
+
const BRAND_BG = 37;
|
|
559667
|
+
const BRAND_FG = 0;
|
|
559599
559668
|
return linkify(
|
|
559600
559669
|
cmd,
|
|
559601
559670
|
`\x1B[38;5;${BRAND_FG}m\x1B[48;5;${BRAND_BG}m ${label} \x1B[0m${PANEL_BG_SEQ}`
|
|
@@ -561516,7 +561585,7 @@ ${CONTENT_BG_SEQ}`);
|
|
|
561516
561585
|
if (this._contentScrollOffset > 0) {
|
|
561517
561586
|
const label = " ↓ scroll to bottom ";
|
|
561518
561587
|
const startCol = 3;
|
|
561519
|
-
buf += `\x1B[${spacerRow};${startCol}H\x1B[
|
|
561588
|
+
buf += `\x1B[${spacerRow};${startCol}H\x1B[38;5;37m${label}\x1B[0m${CONTENT_BG_SEQ}`;
|
|
561520
561589
|
this._scrollBtnRegion = {
|
|
561521
561590
|
row: spacerRow,
|
|
561522
561591
|
start: startCol,
|
|
@@ -564239,6 +564308,23 @@ import { promisify as promisify5 } from "node:util";
|
|
|
564239
564308
|
import { existsSync as existsSync85, writeFileSync as writeFileSync46, readFileSync as readFileSync71, appendFileSync as appendFileSync4, mkdirSync as mkdirSync49 } from "node:fs";
|
|
564240
564309
|
import { join as join102 } from "node:path";
|
|
564241
564310
|
import { homedir as homedir30, platform as platform4 } from "node:os";
|
|
564311
|
+
function wrapText(value2, width) {
|
|
564312
|
+
const words = value2.split(/\s+/).filter(Boolean);
|
|
564313
|
+
const lines = [];
|
|
564314
|
+
let line = "";
|
|
564315
|
+
for (const word2 of words) {
|
|
564316
|
+
if (!line) {
|
|
564317
|
+
line = word2;
|
|
564318
|
+
} else if (Array.from(line).length + 1 + Array.from(word2).length <= width) {
|
|
564319
|
+
line += " " + word2;
|
|
564320
|
+
} else {
|
|
564321
|
+
lines.push(line);
|
|
564322
|
+
line = word2;
|
|
564323
|
+
}
|
|
564324
|
+
}
|
|
564325
|
+
if (line) lines.push(line);
|
|
564326
|
+
return lines.length > 0 ? lines : [""];
|
|
564327
|
+
}
|
|
564242
564328
|
async function checkToolSupport(modelName, backendUrl = "http://localhost:11434") {
|
|
564243
564329
|
if (_toolSupportCache.has(modelName)) return _toolSupportCache.get(modelName);
|
|
564244
564330
|
try {
|
|
@@ -564459,7 +564545,7 @@ function ensureCurl() {
|
|
|
564459
564545
|
if (hasCmd("curl")) return true;
|
|
564460
564546
|
const plat = platform4();
|
|
564461
564547
|
if (plat === "win32") {
|
|
564462
|
-
process.stdout.write(` ${c3.
|
|
564548
|
+
process.stdout.write(` ${c3.cyan("⚠")} curl not found on Windows — install it manually.
|
|
564463
564549
|
`);
|
|
564464
564550
|
return false;
|
|
564465
564551
|
}
|
|
@@ -564483,7 +564569,7 @@ function ensureCurl() {
|
|
|
564483
564569
|
return true;
|
|
564484
564570
|
}
|
|
564485
564571
|
} catch {
|
|
564486
|
-
process.stdout.write(` ${c3.
|
|
564572
|
+
process.stdout.write(` ${c3.cyan("⚠")} ${s2.label} install failed, trying next...
|
|
564487
564573
|
`);
|
|
564488
564574
|
}
|
|
564489
564575
|
}
|
|
@@ -564520,7 +564606,7 @@ function ensureZstd() {
|
|
|
564520
564606
|
else if (hasCmd("apk")) installCmd = "apk add --no-cache zstd";
|
|
564521
564607
|
if (!installCmd) {
|
|
564522
564608
|
process.stdout.write(`
|
|
564523
|
-
${c3.
|
|
564609
|
+
${c3.cyan("⚠")} Could not detect package manager to install zstd.
|
|
564524
564610
|
`);
|
|
564525
564611
|
return false;
|
|
564526
564612
|
}
|
|
@@ -564689,7 +564775,7 @@ function runElevatedCommand(command, opts = {}) {
|
|
|
564689
564775
|
function runOllamaInstallScript() {
|
|
564690
564776
|
const zstdReady = ensureZstd();
|
|
564691
564777
|
if (!zstdReady) {
|
|
564692
|
-
process.stdout.write(` ${c3.
|
|
564778
|
+
process.stdout.write(` ${c3.cyan("⚠")} Proceeding without zstd — install may fail if the script requires it.
|
|
564693
564779
|
`);
|
|
564694
564780
|
}
|
|
564695
564781
|
const elevated = buildElevatedInstall();
|
|
@@ -564700,9 +564786,9 @@ function runOllamaInstallScript() {
|
|
|
564700
564786
|
process.stdout.write(` ${c3.cyan("●")} Elevation: SUDO_ASKPASS (GUI password modal)
|
|
564701
564787
|
`);
|
|
564702
564788
|
} else {
|
|
564703
|
-
process.stdout.write(` ${c3.
|
|
564789
|
+
process.stdout.write(` ${c3.cyan("⚠")} No GUI password helper available — install may stall waiting for sudo.
|
|
564704
564790
|
`);
|
|
564705
|
-
process.stdout.write(` ${c3.
|
|
564791
|
+
process.stdout.write(` ${c3.cyan("⚠")} Install one of: pkexec / zenity / kdialog / yad / ssh-askpass
|
|
564706
564792
|
`);
|
|
564707
564793
|
}
|
|
564708
564794
|
const runOnce = () => {
|
|
@@ -564722,7 +564808,7 @@ function runOllamaInstallScript() {
|
|
|
564722
564808
|
const combined = stderr + "\n" + message2;
|
|
564723
564809
|
if (combined.includes("requires zstd") || combined.includes("install zstd")) {
|
|
564724
564810
|
process.stdout.write(`
|
|
564725
|
-
${c3.
|
|
564811
|
+
${c3.cyan("⚠")} Ollama install script requires zstd. Attempting to install it...
|
|
564726
564812
|
`);
|
|
564727
564813
|
if (ensureZstd()) {
|
|
564728
564814
|
runOnce();
|
|
@@ -564747,7 +564833,7 @@ async function autoInstallOllama(rl) {
|
|
|
564747
564833
|
} else if (plat === "win32") {
|
|
564748
564834
|
return installOllamaWindows();
|
|
564749
564835
|
}
|
|
564750
|
-
process.stdout.write(` ${c3.
|
|
564836
|
+
process.stdout.write(` ${c3.cyan("⚠")} Unsupported platform: ${plat}
|
|
564751
564837
|
`);
|
|
564752
564838
|
process.stdout.write(` ${c3.dim("Visit https://ollama.com to install manually.")}
|
|
564753
564839
|
|
|
@@ -564768,7 +564854,7 @@ function installOllamaLinux() {
|
|
|
564768
564854
|
return true;
|
|
564769
564855
|
}
|
|
564770
564856
|
process.stdout.write(`
|
|
564771
|
-
${c3.
|
|
564857
|
+
${c3.cyan("⚠")} Install script ran but ollama not found on PATH.
|
|
564772
564858
|
`);
|
|
564773
564859
|
return false;
|
|
564774
564860
|
} catch (err) {
|
|
@@ -564802,7 +564888,7 @@ async function installOllamaMac(_rl) {
|
|
|
564802
564888
|
`);
|
|
564803
564889
|
} else {
|
|
564804
564890
|
process.stdout.write(`
|
|
564805
|
-
${c3.
|
|
564891
|
+
${c3.cyan("⚠")} Homebrew install completed but brew not found on PATH.
|
|
564806
564892
|
`);
|
|
564807
564893
|
process.stdout.write(` ${c3.dim('Try: eval "$(/opt/homebrew/bin/brew shellenv)"')}
|
|
564808
564894
|
|
|
@@ -564832,7 +564918,7 @@ async function installOllamaMac(_rl) {
|
|
|
564832
564918
|
return true;
|
|
564833
564919
|
}
|
|
564834
564920
|
process.stdout.write(`
|
|
564835
|
-
${c3.
|
|
564921
|
+
${c3.cyan("⚠")} brew install completed but ollama not found on PATH.
|
|
564836
564922
|
`);
|
|
564837
564923
|
return false;
|
|
564838
564924
|
} catch (err) {
|
|
@@ -564859,7 +564945,7 @@ function installOllamaWindows() {
|
|
|
564859
564945
|
return true;
|
|
564860
564946
|
}
|
|
564861
564947
|
process.stdout.write(`
|
|
564862
|
-
${c3.
|
|
564948
|
+
${c3.cyan("⚠")} Install script ran but ollama not found on PATH.
|
|
564863
564949
|
`);
|
|
564864
564950
|
return false;
|
|
564865
564951
|
} catch (err) {
|
|
@@ -564874,7 +564960,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
|
|
|
564874
564960
|
if (!ollamaInstalled) {
|
|
564875
564961
|
if (rl) {
|
|
564876
564962
|
process.stdout.write(`
|
|
564877
|
-
${c3.
|
|
564963
|
+
${c3.cyan("⚠")} Ollama is not installed on this system.
|
|
564878
564964
|
`);
|
|
564879
564965
|
const answer = await ask(rl, ` ${c3.bold("Install Ollama now?")} (Y/n) `);
|
|
564880
564966
|
if (answer.toLowerCase() === "n") {
|
|
@@ -564901,7 +564987,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
|
|
|
564901
564987
|
const child = spawn24("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
564902
564988
|
child.unref();
|
|
564903
564989
|
} catch {
|
|
564904
|
-
process.stdout.write(` ${c3.
|
|
564990
|
+
process.stdout.write(` ${c3.cyan("⚠")} Could not start ollama serve.
|
|
564905
564991
|
|
|
564906
564992
|
`);
|
|
564907
564993
|
return false;
|
|
@@ -564921,7 +565007,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
|
|
|
564921
565007
|
} catch {
|
|
564922
565008
|
}
|
|
564923
565009
|
}
|
|
564924
|
-
process.stdout.write(` ${c3.
|
|
565010
|
+
process.stdout.write(` ${c3.cyan("⚠")} Ollama started but not responding. Try ${c3.bold("ollama serve")} manually.
|
|
564925
565011
|
|
|
564926
565012
|
`);
|
|
564927
565013
|
return false;
|
|
@@ -564996,7 +565082,7 @@ function pullModelWithAutoUpdate(tag) {
|
|
|
564996
565082
|
const combined = errMsg + "\n" + stderr;
|
|
564997
565083
|
if (combined.includes("412") || combined.includes("newer version") || combined.includes("requires a newer version")) {
|
|
564998
565084
|
process.stdout.write(`
|
|
564999
|
-
${c3.
|
|
565085
|
+
${c3.cyan("⚠")} Ollama needs to be updated for this model.
|
|
565000
565086
|
`);
|
|
565001
565087
|
if (!ensureCurl()) {
|
|
565002
565088
|
throw new Error("curl is required to update Ollama but could not be installed.");
|
|
@@ -565124,7 +565210,7 @@ function ensurePython3() {
|
|
|
565124
565210
|
}
|
|
565125
565211
|
}
|
|
565126
565212
|
}
|
|
565127
|
-
process.stdout.write(` ${c3.
|
|
565213
|
+
process.stdout.write(` ${c3.cyan("⚠")} Could not install Python3 automatically. Install manually.
|
|
565128
565214
|
|
|
565129
565215
|
`);
|
|
565130
565216
|
}
|
|
@@ -565163,7 +565249,7 @@ function ensurePythonVenv() {
|
|
|
565163
565249
|
}
|
|
565164
565250
|
}
|
|
565165
565251
|
}
|
|
565166
|
-
process.stdout.write(` ${c3.
|
|
565252
|
+
process.stdout.write(` ${c3.cyan("⚠")} Could not install python3-venv. Install manually: sudo apt install python3-venv
|
|
565167
565253
|
|
|
565168
565254
|
`);
|
|
565169
565255
|
}
|
|
@@ -565249,12 +565335,12 @@ async function promptForCustomEndpoint(config, rl) {
|
|
|
565249
565335
|
}
|
|
565250
565336
|
}
|
|
565251
565337
|
if (!testOk) {
|
|
565252
|
-
process.stdout.write(` ${c3.
|
|
565338
|
+
process.stdout.write(` ${c3.cyan("⚠")} Endpoint returned HTTP ${resp.status}
|
|
565253
565339
|
`);
|
|
565254
565340
|
}
|
|
565255
565341
|
}
|
|
565256
565342
|
} catch (err) {
|
|
565257
|
-
process.stdout.write(` ${c3.
|
|
565343
|
+
process.stdout.write(` ${c3.cyan("⚠")} Could not reach endpoint: ${err instanceof Error ? err.message : String(err)}
|
|
565258
565344
|
`);
|
|
565259
565345
|
}
|
|
565260
565346
|
if (!testOk) {
|
|
@@ -565292,7 +565378,7 @@ async function promptForCustomEndpoint(config, rl) {
|
|
|
565292
565378
|
}
|
|
565293
565379
|
async function doSetup(config, rl) {
|
|
565294
565380
|
process.stdout.write(`
|
|
565295
|
-
|
|
565381
|
+
${c3.cyan(OMNIUS_FIRST_RUN_BANNER)}
|
|
565296
565382
|
`);
|
|
565297
565383
|
process.stdout.write(` ${c3.dim("─".repeat(60))}
|
|
565298
565384
|
`);
|
|
@@ -565329,36 +565415,43 @@ async function doSetup(config, rl) {
|
|
|
565329
565415
|
const bw = 30;
|
|
565330
565416
|
const sw = 24;
|
|
565331
565417
|
const boxW = 52;
|
|
565332
|
-
const boxLine = (content
|
|
565418
|
+
const boxLine = (content) => {
|
|
565419
|
+
const visLen = visibleLen(content);
|
|
565333
565420
|
const pad = Math.max(0, boxW - visLen);
|
|
565334
565421
|
return ` ${c3.dim("│")}${content}${" ".repeat(pad)}${c3.dim("│")}
|
|
565335
565422
|
`;
|
|
565336
565423
|
};
|
|
565424
|
+
const boxWrappedDimLine = (content, indent = " ") => {
|
|
565425
|
+
const lines = wrapText(content, Math.max(1, boxW - visibleLen(indent)));
|
|
565426
|
+
for (const line of lines) {
|
|
565427
|
+
process.stdout.write(boxLine(`${indent}${c3.dim(line)}`));
|
|
565428
|
+
}
|
|
565429
|
+
};
|
|
565337
565430
|
const hLine = (ch) => ` ${c3.dim(ch + "─".repeat(boxW) + (ch === "┌" ? "┐" : ch === "├" ? "┤" : "┘"))}
|
|
565338
565431
|
`;
|
|
565339
565432
|
process.stdout.write("\n");
|
|
565340
565433
|
process.stdout.write(hLine("┌"));
|
|
565341
|
-
process.stdout.write(boxLine(` ${c3.bold("Inference Capability")}
|
|
565434
|
+
process.stdout.write(boxLine(` ${c3.bold("Inference Capability")}`));
|
|
565342
565435
|
process.stdout.write(hLine("├"));
|
|
565343
|
-
process.stdout.write(boxLine(` ${c3.bold("Overall")}
|
|
565436
|
+
process.stdout.write(boxLine(` ${c3.bold("Overall")}`));
|
|
565344
565437
|
const overallBar = renderScoreBar(score.overall, bw);
|
|
565345
565438
|
const overallLabel = `${String(score.overall).padStart(3)}/100`;
|
|
565346
|
-
process.stdout.write(boxLine(` ${overallBar} ${c3.bold(overallLabel)}
|
|
565347
|
-
|
|
565439
|
+
process.stdout.write(boxLine(` ${overallBar} ${c3.bold(overallLabel)}`));
|
|
565440
|
+
boxWrappedDimLine(score.summary);
|
|
565348
565441
|
process.stdout.write(hLine("├"));
|
|
565349
565442
|
const memLabel = `${specs.totalRamGB.toFixed(0)} GB RAM` + (specs.gpuVramGB > 0 ? ` + ${specs.gpuVramGB.toFixed(0)} GB VRAM` : "");
|
|
565350
|
-
process.stdout.write(boxLine(` ${c3.bold("Memory")} ${c3.dim(memLabel)}
|
|
565351
|
-
process.stdout.write(boxLine(` ${renderScoreBar(score.memory, sw)} ${String(score.memory).padStart(3)}
|
|
565352
|
-
process.stdout.write(boxLine(""
|
|
565443
|
+
process.stdout.write(boxLine(` ${c3.bold("Memory")} ${c3.dim(memLabel)}`));
|
|
565444
|
+
process.stdout.write(boxLine(` ${renderScoreBar(score.memory, sw)} ${String(score.memory).padStart(3)}`));
|
|
565445
|
+
process.stdout.write(boxLine(""));
|
|
565353
565446
|
const gpuLabel = specs.gpuVramGB > 0 ? specs.gpuName || "NVIDIA GPU" : "CPU only";
|
|
565354
|
-
process.stdout.write(boxLine(` ${c3.bold("Compute")} ${c3.dim(gpuLabel)}
|
|
565355
|
-
process.stdout.write(boxLine(` ${renderScoreBar(score.compute, sw)} ${String(score.compute).padStart(3)}
|
|
565356
|
-
process.stdout.write(boxLine(""
|
|
565447
|
+
process.stdout.write(boxLine(` ${c3.bold("Compute")} ${c3.dim(gpuLabel)}`));
|
|
565448
|
+
process.stdout.write(boxLine(` ${renderScoreBar(score.compute, sw)} ${String(score.compute).padStart(3)}`));
|
|
565449
|
+
process.stdout.write(boxLine(""));
|
|
565357
565450
|
const speedLabel = specs.gpuVramGB > 0 ? "GPU accelerated" : "CPU inference";
|
|
565358
|
-
process.stdout.write(boxLine(` ${c3.bold("Speed")} ${c3.dim(speedLabel)}
|
|
565359
|
-
process.stdout.write(boxLine(` ${renderScoreBar(score.speed, sw)} ${String(score.speed).padStart(3)}
|
|
565451
|
+
process.stdout.write(boxLine(` ${c3.bold("Speed")} ${c3.dim(speedLabel)}`));
|
|
565452
|
+
process.stdout.write(boxLine(` ${renderScoreBar(score.speed, sw)} ${String(score.speed).padStart(3)}`));
|
|
565360
565453
|
process.stdout.write(hLine("├"));
|
|
565361
|
-
process.stdout.write(boxLine(` ${c3.bold("Model Compatibility")}
|
|
565454
|
+
process.stdout.write(boxLine(` ${c3.bold("Model Compatibility")}`));
|
|
565362
565455
|
for (const compat of score.modelCompat) {
|
|
565363
565456
|
const icon = compat.fits ? c3.green("✔") : c3.red("✖");
|
|
565364
565457
|
const tag = compat.fits ? compat.tag : c3.dim(compat.tag);
|
|
@@ -565372,7 +565465,7 @@ async function doSetup(config, rl) {
|
|
|
565372
565465
|
process.stdout.write("\n");
|
|
565373
565466
|
let hasPython = hasCmd("python3") || hasCmd("python");
|
|
565374
565467
|
if (!hasPython) {
|
|
565375
|
-
process.stdout.write(` ${c3.
|
|
565468
|
+
process.stdout.write(` ${c3.cyan("⚠")} Python3 not found (needed for vision, OCR, browser automation).
|
|
565376
565469
|
`);
|
|
565377
565470
|
const installPy = await ask(rl, ` ${c3.bold("Install Python3?")} (Y/n) `);
|
|
565378
565471
|
if (installPy.toLowerCase() !== "n") {
|
|
@@ -565383,7 +565476,7 @@ async function doSetup(config, rl) {
|
|
|
565383
565476
|
if (hasPython) {
|
|
565384
565477
|
const hasVenv = checkPythonVenv();
|
|
565385
565478
|
if (!hasVenv) {
|
|
565386
|
-
process.stdout.write(` ${c3.
|
|
565479
|
+
process.stdout.write(` ${c3.cyan("⚠")} Python3 venv module not found (needed for Moondream, OCR, browser automation).
|
|
565387
565480
|
`);
|
|
565388
565481
|
const installVenv = await ask(rl, ` ${c3.bold("Install python3-venv?")} (Y/n) `);
|
|
565389
565482
|
if (installVenv.toLowerCase() !== "n") {
|
|
@@ -565396,7 +565489,7 @@ async function doSetup(config, rl) {
|
|
|
565396
565489
|
try {
|
|
565397
565490
|
models = await fetchOllamaModels(config.backendUrl);
|
|
565398
565491
|
} catch {
|
|
565399
|
-
process.stdout.write(` ${c3.
|
|
565492
|
+
process.stdout.write(` ${c3.cyan("⚠")} Cannot reach Ollama at ${c3.bold(config.backendUrl)}
|
|
565400
565493
|
|
|
565401
565494
|
`);
|
|
565402
565495
|
const useCustom = await ask(rl, ` ${c3.bold("Use a custom inference endpoint instead?")} (Y/n) `);
|
|
@@ -565422,12 +565515,12 @@ async function doSetup(config, rl) {
|
|
|
565422
565515
|
|
|
565423
565516
|
`);
|
|
565424
565517
|
} catch {
|
|
565425
|
-
process.stdout.write(` ${c3.
|
|
565518
|
+
process.stdout.write(` ${c3.cyan("⚠")} Ollama started but not responding yet. It may need a moment.
|
|
565426
565519
|
|
|
565427
565520
|
`);
|
|
565428
565521
|
}
|
|
565429
565522
|
} catch {
|
|
565430
|
-
process.stdout.write(` ${c3.
|
|
565523
|
+
process.stdout.write(` ${c3.cyan("⚠")} Could not start Ollama. Try running ${c3.bold("ollama serve")} manually.
|
|
565431
565524
|
|
|
565432
565525
|
`);
|
|
565433
565526
|
}
|
|
@@ -565450,12 +565543,12 @@ async function doSetup(config, rl) {
|
|
|
565450
565543
|
|
|
565451
565544
|
`);
|
|
565452
565545
|
} catch {
|
|
565453
|
-
process.stdout.write(` ${c3.
|
|
565546
|
+
process.stdout.write(` ${c3.cyan("⚠")} Ollama installed but not responding yet. Try ${c3.bold("ollama serve")} manually.
|
|
565454
565547
|
|
|
565455
565548
|
`);
|
|
565456
565549
|
}
|
|
565457
565550
|
} catch {
|
|
565458
|
-
process.stdout.write(` ${c3.
|
|
565551
|
+
process.stdout.write(` ${c3.cyan("⚠")} Ollama installed. Start it with: ${c3.bold("ollama serve")}
|
|
565459
565552
|
|
|
565460
565553
|
`);
|
|
565461
565554
|
}
|
|
@@ -565482,7 +565575,7 @@ async function doSetup(config, rl) {
|
|
|
565482
565575
|
`);
|
|
565483
565576
|
return currentModel.name;
|
|
565484
565577
|
}
|
|
565485
|
-
process.stdout.write(` ${c3.
|
|
565578
|
+
process.stdout.write(` ${c3.cyan("⚠")} Default model ${c3.bold(config.model)} is not available.
|
|
565486
565579
|
|
|
565487
565580
|
`);
|
|
565488
565581
|
if (models.length > 0) {
|
|
@@ -565514,7 +565607,7 @@ async function doSetup(config, rl) {
|
|
|
565514
565607
|
return selected.name;
|
|
565515
565608
|
}
|
|
565516
565609
|
} else {
|
|
565517
|
-
process.stdout.write(` ${c3.
|
|
565610
|
+
process.stdout.write(` ${c3.cyan("⚠")} No models found on this system.
|
|
565518
565611
|
|
|
565519
565612
|
`);
|
|
565520
565613
|
}
|
|
@@ -566584,7 +566677,7 @@ export PATH="${binDir}:$PATH" # Added by omnius for nvim
|
|
|
566584
566677
|
} catch {
|
|
566585
566678
|
}
|
|
566586
566679
|
}
|
|
566587
|
-
var execAsync2, QWEN_VARIANTS, _toolSupportCache, _cloudflaredInstallPromise;
|
|
566680
|
+
var execAsync2, OMNIUS_FIRST_RUN_BANNER, ANSI_RE, visibleLen, QWEN_VARIANTS, _toolSupportCache, _cloudflaredInstallPromise;
|
|
566588
566681
|
var init_setup = __esm({
|
|
566589
566682
|
"packages/cli/src/tui/setup.ts"() {
|
|
566590
566683
|
"use strict";
|
|
@@ -566594,6 +566687,17 @@ var init_setup = __esm({
|
|
|
566594
566687
|
init_dist();
|
|
566595
566688
|
init_tui_select();
|
|
566596
566689
|
execAsync2 = promisify5(exec4);
|
|
566690
|
+
OMNIUS_FIRST_RUN_BANNER = [
|
|
566691
|
+
" ░▒▓██████▓▒░░▒▓██████████████▓▒░░▒▓███████▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓███████▓▒░ ",
|
|
566692
|
+
"░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ",
|
|
566693
|
+
"░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ",
|
|
566694
|
+
"░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓██████▓▒░ ",
|
|
566695
|
+
"░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ",
|
|
566696
|
+
"░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ",
|
|
566697
|
+
" ░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓██████▓▒░░▒▓███████▓▒░ "
|
|
566698
|
+
].join("\n");
|
|
566699
|
+
ANSI_RE = /\x1B\[[0-?]*[ -/]*[@-~]/g;
|
|
566700
|
+
visibleLen = (value2) => Array.from(value2.replace(ANSI_RE, "")).length;
|
|
566597
566701
|
QWEN_VARIANTS = [
|
|
566598
566702
|
{ tag: "qwen3.5:0.8b", sizeGB: 1, label: "0.8B params (1.0 GB)", cloud: false },
|
|
566599
566703
|
{ tag: "qwen3.5:2b", sizeGB: 2.7, label: "2B params (2.7 GB)", cloud: false },
|
|
@@ -581466,7 +581570,7 @@ async function showColorMenu(ctx3) {
|
|
|
581466
581570
|
{
|
|
581467
581571
|
key: "branding",
|
|
581468
581572
|
label: `Omnius Branding${currentConfig.mode === "branding" ? " (active)" : ""}`,
|
|
581469
|
-
detail: "
|
|
581573
|
+
detail: "Teal accent on terminal background"
|
|
581470
581574
|
},
|
|
581471
581575
|
{
|
|
581472
581576
|
key: "custom",
|
|
@@ -587626,30 +587730,30 @@ function getNodeMnemonic() {
|
|
|
587626
587730
|
function createDefaultBanner(version4 = "0.120.0") {
|
|
587627
587731
|
const width = termCols();
|
|
587628
587732
|
const rows = headerHeight();
|
|
587629
|
-
const
|
|
587733
|
+
const accent2 = tuiAccent() < 0 ? -1 : tuiAccent();
|
|
587630
587734
|
const bgBlack = tuiBg() < 0 ? -1 : tuiBg();
|
|
587631
587735
|
const grid = [];
|
|
587632
587736
|
const innerW = width - 2;
|
|
587633
587737
|
const topRow = [];
|
|
587634
|
-
topRow.push({ char: "╭", fg:
|
|
587738
|
+
topRow.push({ char: "╭", fg: accent2, bg: bgBlack, bold: false });
|
|
587635
587739
|
for (let c9 = 0; c9 < innerW; c9++) {
|
|
587636
|
-
topRow.push({ char: "─", fg:
|
|
587740
|
+
topRow.push({ char: "─", fg: accent2, bg: bgBlack, bold: false });
|
|
587637
587741
|
}
|
|
587638
|
-
topRow.push({ char: "╮", fg:
|
|
587742
|
+
topRow.push({ char: "╮", fg: accent2, bg: bgBlack, bold: false });
|
|
587639
587743
|
grid.push(topRow);
|
|
587640
587744
|
const midRow = [];
|
|
587641
|
-
midRow.push({ char: "│", fg:
|
|
587745
|
+
midRow.push({ char: "│", fg: accent2, bg: bgBlack, bold: false });
|
|
587642
587746
|
for (let c9 = 0; c9 < innerW; c9++) {
|
|
587643
587747
|
midRow.push({ char: " ", fg: 0, bg: bgBlack, bold: false });
|
|
587644
587748
|
}
|
|
587645
|
-
midRow.push({ char: "│", fg:
|
|
587749
|
+
midRow.push({ char: "│", fg: accent2, bg: bgBlack, bold: false });
|
|
587646
587750
|
grid.push(midRow);
|
|
587647
587751
|
const botRow = [];
|
|
587648
|
-
botRow.push({ char: "╰", fg:
|
|
587752
|
+
botRow.push({ char: "╰", fg: accent2, bg: bgBlack, bold: false });
|
|
587649
587753
|
for (let c9 = 0; c9 < innerW; c9++) {
|
|
587650
|
-
botRow.push({ char: "─", fg:
|
|
587754
|
+
botRow.push({ char: "─", fg: accent2, bg: bgBlack, bold: false });
|
|
587651
587755
|
}
|
|
587652
|
-
botRow.push({ char: "╯", fg:
|
|
587756
|
+
botRow.push({ char: "╯", fg: accent2, bg: bgBlack, bold: false });
|
|
587653
587757
|
grid.push(botRow);
|
|
587654
587758
|
return {
|
|
587655
587759
|
id: "default-header",
|
|
@@ -588330,7 +588434,7 @@ var init_carousel_descriptors = __esm({
|
|
|
588330
588434
|
},
|
|
588331
588435
|
{
|
|
588332
588436
|
name: "memory",
|
|
588333
|
-
colors: [
|
|
588437
|
+
colors: [23, 29, 35, 36, 37, 43, 44, 50],
|
|
588334
588438
|
tools: ["memory_read", "memory_write"]
|
|
588335
588439
|
},
|
|
588336
588440
|
{
|
|
@@ -593226,7 +593330,7 @@ import { mkdirSync as mkdirSync60, existsSync as existsSync105, unlinkSync as un
|
|
|
593226
593330
|
import { join as join120, resolve as resolve39, basename as basename22 } from "node:path";
|
|
593227
593331
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
593228
593332
|
import { createHash as createHash19, randomInt } from "node:crypto";
|
|
593229
|
-
function parseTelegramInteractionDecision(text, forcedRoute) {
|
|
593333
|
+
function parseTelegramInteractionDecision(text, forcedRoute, options2 = {}) {
|
|
593230
593334
|
const cleaned = stripTelegramHiddenThinking(text).replace(/```(?:json)?/gi, "").replace(/```/g, "").trim();
|
|
593231
593335
|
const jsonText = cleaned.startsWith("{") ? cleaned : cleaned.match(/\{[\s\S]*\}/)?.[0] ?? "";
|
|
593232
593336
|
if (!jsonText) return null;
|
|
@@ -593236,7 +593340,7 @@ function parseTelegramInteractionDecision(text, forcedRoute) {
|
|
|
593236
593340
|
const route = forcedRoute ?? parsedRoute;
|
|
593237
593341
|
if (!route) return null;
|
|
593238
593342
|
const shouldReplyRaw = parsed["should_reply"] ?? parsed["shouldReply"];
|
|
593239
|
-
const shouldReply = typeof shouldReplyRaw === "boolean" ? shouldReplyRaw : true;
|
|
593343
|
+
const shouldReply = typeof shouldReplyRaw === "boolean" ? shouldReplyRaw : options2.defaultShouldReply ?? true;
|
|
593240
593344
|
const confidenceRaw = Number(parsed["confidence"]);
|
|
593241
593345
|
const confidence = Number.isFinite(confidenceRaw) ? Math.max(0, Math.min(1, confidenceRaw)) : 0;
|
|
593242
593346
|
const reason = String(parsed["reason"] ?? "live inference decision").slice(0, 240);
|
|
@@ -593299,6 +593403,41 @@ function sanitizeTelegramProgressText(text, maxLength) {
|
|
|
593299
593403
|
const compact = stripTelegramHiddenThinking(text).replace(/\s+/g, " ").trim();
|
|
593300
593404
|
return compact.length > maxLength ? compact.slice(0, Math.max(0, maxLength - 3)) + "..." : compact;
|
|
593301
593405
|
}
|
|
593406
|
+
function compactTelegramVisibleText(text) {
|
|
593407
|
+
return stripTelegramHiddenThinking(text).replace(/\s+/g, " ").trim();
|
|
593408
|
+
}
|
|
593409
|
+
function isTelegramPotentialNoReplyPrefix(text) {
|
|
593410
|
+
const lower = compactTelegramVisibleText(text).toLowerCase();
|
|
593411
|
+
return Boolean(lower) && "no_reply".startsWith(lower);
|
|
593412
|
+
}
|
|
593413
|
+
function isTelegramNoReplySentinel(text) {
|
|
593414
|
+
const lower = compactTelegramVisibleText(text).toLowerCase();
|
|
593415
|
+
return lower === "no_reply" || lower.startsWith("no_reply");
|
|
593416
|
+
}
|
|
593417
|
+
function isTelegramInternalStatusText(text) {
|
|
593418
|
+
const compact = compactTelegramVisibleText(text);
|
|
593419
|
+
if (!compact) return false;
|
|
593420
|
+
const lower = compact.toLowerCase();
|
|
593421
|
+
if (isTelegramNoReplySentinel(compact)) return true;
|
|
593422
|
+
if (lower === "complete" || lower === "completed") return true;
|
|
593423
|
+
if (/^memory stage:/i.test(compact)) return true;
|
|
593424
|
+
if (/^\[ppr[-_\s]?skip\]/i.test(compact)) return true;
|
|
593425
|
+
if (/^(casual|ambient|group)\b.{0,180}\b(skipping|skipped|not directed|no action needed|no reply)\b/i.test(compact)) return true;
|
|
593426
|
+
if (/^no further action needed\b/i.test(compact)) return true;
|
|
593427
|
+
if (/^no action needed\b.{0,120}\b(task|complete|completed|done)\b/i.test(compact)) return true;
|
|
593428
|
+
if (/^(there'?s|there is) no active task\b/i.test(compact)) return true;
|
|
593429
|
+
if (/^everything'?s (done|complete|completed|wrapped up)\b/i.test(compact)) return true;
|
|
593430
|
+
if (/\balready (been )?(provided|answered|handled|delivered) above\b/i.test(compact)) return true;
|
|
593431
|
+
if (/\b(no remaining work|nothing left to do|task is complete|task has been completed)\b/i.test(compact)) return true;
|
|
593432
|
+
return false;
|
|
593433
|
+
}
|
|
593434
|
+
function cleanTelegramVisibleReply(text, options2 = {}) {
|
|
593435
|
+
const clean3 = stripTelegramHiddenThinking(text).trim();
|
|
593436
|
+
if (!clean3) return "";
|
|
593437
|
+
if (options2.suppressPotentialNoReplyPrefix && isTelegramPotentialNoReplyPrefix(clean3)) return "";
|
|
593438
|
+
if (isTelegramInternalStatusText(clean3)) return "";
|
|
593439
|
+
return clean3;
|
|
593440
|
+
}
|
|
593302
593441
|
function truncateTelegramContext(text, maxLength) {
|
|
593303
593442
|
const trimmed = text.trim();
|
|
593304
593443
|
if (trimmed.length <= maxLength) return trimmed;
|
|
@@ -593419,13 +593558,13 @@ function selectTelegramFinalResponse(args) {
|
|
|
593419
593558
|
args.streamText,
|
|
593420
593559
|
args.accumulated,
|
|
593421
593560
|
args.assistantText
|
|
593422
|
-
].map((candidate) =>
|
|
593561
|
+
].map((candidate) => cleanTelegramVisibleReply(candidate || "")).filter(Boolean);
|
|
593423
593562
|
if (visibleCandidates.length > 0) {
|
|
593424
593563
|
return visibleCandidates.reduce(
|
|
593425
593564
|
(best, current) => current.length > best.length ? current : best
|
|
593426
593565
|
);
|
|
593427
593566
|
}
|
|
593428
|
-
return
|
|
593567
|
+
return cleanTelegramVisibleReply(args.summary || "");
|
|
593429
593568
|
}
|
|
593430
593569
|
function formatTelegramProgressEvent(event) {
|
|
593431
593570
|
if (event.type === "tool_call" && event.toolName === "task_complete") return null;
|
|
@@ -593435,23 +593574,25 @@ function formatTelegramProgressEvent(event) {
|
|
|
593435
593574
|
}
|
|
593436
593575
|
if (event.type === "tool_result") {
|
|
593437
593576
|
const preview = sanitizeTelegramProgressText(event.content || "", 80);
|
|
593577
|
+
if (isTelegramInternalStatusText(preview)) return null;
|
|
593438
593578
|
const toolName = escapeTelegramHTML(event.toolName || "tool");
|
|
593439
593579
|
if (preview) return `${toolName}: ${escapeTelegramHTML(preview)}`;
|
|
593440
593580
|
return event.success ? `${toolName} completed` : `${toolName} failed`;
|
|
593441
593581
|
}
|
|
593442
593582
|
if (event.type === "status") {
|
|
593443
593583
|
const content = sanitizeTelegramProgressText(event.content || "", 120);
|
|
593584
|
+
if (isTelegramInternalStatusText(content)) return null;
|
|
593444
593585
|
return content ? escapeTelegramHTML(content) : null;
|
|
593445
593586
|
}
|
|
593446
593587
|
return null;
|
|
593447
593588
|
}
|
|
593448
593589
|
function renderTelegramLiveProgressHTML(progressLines, accumulated) {
|
|
593449
|
-
const draft =
|
|
593590
|
+
const draft = cleanTelegramVisibleReply(accumulated, { suppressPotentialNoReplyPrefix: true });
|
|
593450
593591
|
if (draft) {
|
|
593451
593592
|
const clipped = draft.length > 2e3 ? `${draft.slice(0, 1997).trimEnd()}...` : draft;
|
|
593452
593593
|
return convertMarkdownToTelegramHTML(clipped);
|
|
593453
593594
|
}
|
|
593454
|
-
return progressLines.slice(-6).map((line) => line.trim()).filter(Boolean).join("\n");
|
|
593595
|
+
return progressLines.slice(-6).map((line) => line.trim()).filter((line) => !isTelegramInternalStatusText(line)).filter(Boolean).join("\n");
|
|
593455
593596
|
}
|
|
593456
593597
|
function telegramSyntheticHelpSignatures() {
|
|
593457
593598
|
return [
|
|
@@ -593935,14 +594076,17 @@ RULES FOR GROUP CONTEXT:
|
|
|
593935
594076
|
6. You may share general knowledge and helpful guidance
|
|
593936
594077
|
`.trim();
|
|
593937
594078
|
GROUP_REPLY_DISCRETION_PROMPT = `
|
|
593938
|
-
REPLY DISCRETION: You are in a group chat.
|
|
593939
|
-
|
|
593940
|
-
|
|
593941
|
-
|
|
593942
|
-
|
|
593943
|
-
|
|
593944
|
-
|
|
593945
|
-
|
|
594079
|
+
REPLY DISCRETION: You are in a group chat. The live router has already filtered
|
|
594080
|
+
most ambient chatter. Continue to be selective:
|
|
594081
|
+
1. Respond when someone directly addresses the bot, replies to the bot, or keeps
|
|
594082
|
+
an active bot-involved task moving.
|
|
594083
|
+
2. Stay silent for conversation between other people, third-person commentary
|
|
594084
|
+
about the bot, status chatter, or questions clearly meant for someone else.
|
|
594085
|
+
3. Do not reply just because you know an answer or could add color.
|
|
594086
|
+
|
|
594087
|
+
If you determine no visible reply should be sent, call task_complete with summary
|
|
594088
|
+
"no_reply". Never write "no_reply", "skipping", "no action needed", or a status
|
|
594089
|
+
explanation as assistant text.
|
|
593946
594090
|
`.trim();
|
|
593947
594091
|
TELEGRAM_CHAT_MODE_PROMPT = `
|
|
593948
594092
|
You are Omnius replying in Telegram quick-chat mode.
|
|
@@ -593956,6 +594100,7 @@ Rules:
|
|
|
593956
594100
|
6. Use the Telegram conversation context stream as the source of truth for who said what, recent group dynamics, and retained earlier context.
|
|
593957
594101
|
7. Do not claim older chat is unavailable when the context stream contains it. If asked what you see, summarize the supplied transcript, speakers, and relationship/tone signals.
|
|
593958
594102
|
8. Mirror the current sender's tone and directness while staying safe and clear.
|
|
594103
|
+
9. Never send router decisions, skip explanations, memory-stage notes, task-complete summaries, or "no_reply" as chat text.
|
|
593959
594104
|
`.trim();
|
|
593960
594105
|
ADMIN_CHAT_PROFILE_PROMPT = `
|
|
593961
594106
|
You are replying to the authenticated Telegram admin in a private DM.
|
|
@@ -593972,6 +594117,7 @@ Capabilities:
|
|
|
593972
594117
|
Telegram response contract:
|
|
593973
594118
|
- Write the actual Telegram reply as normal assistant text before completion.
|
|
593974
594119
|
- task_complete is only an internal completion signal; do not put status reports, wrap-up notes, or meta-commentary there.
|
|
594120
|
+
- "no_reply" is an internal silent-skip sentinel only; never emit it or explain it in assistant text.
|
|
593975
594121
|
- Do not summarize the fact that you answered; the visible assistant text must be the answer itself.
|
|
593976
594122
|
- If you delegated long-running work, include the sub-agent id/status and what the admin should expect next.
|
|
593977
594123
|
`.trim();
|
|
@@ -594637,17 +594783,17 @@ ${lines.join("\n")}`);
|
|
|
594637
594783
|
async inferTelegramInteractionDecision(msg, toolContext) {
|
|
594638
594784
|
const config = this.agentConfig;
|
|
594639
594785
|
const forcedRoute = this.interactionMode === "chat" || this.interactionMode === "action" ? this.interactionMode : null;
|
|
594786
|
+
const isGroup = msg.chatType !== "private";
|
|
594640
594787
|
if (!config) {
|
|
594641
594788
|
return {
|
|
594642
594789
|
route: forcedRoute ?? "action",
|
|
594643
|
-
shouldReply:
|
|
594790
|
+
shouldReply: !isGroup,
|
|
594644
594791
|
confidence: 0,
|
|
594645
|
-
reason: "router inference unavailable;
|
|
594792
|
+
reason: isGroup ? "router inference unavailable; public group fails closed without keyword heuristics" : "router inference unavailable; private chat defaults to reply",
|
|
594646
594793
|
source: "inference-unavailable"
|
|
594647
594794
|
};
|
|
594648
594795
|
}
|
|
594649
594796
|
const sessionKey = this.sessionKeyForMessage(msg);
|
|
594650
|
-
const isGroup = msg.chatType !== "private";
|
|
594651
594797
|
const backend = new OllamaAgenticBackend(
|
|
594652
594798
|
config.backendUrl,
|
|
594653
594799
|
config.model,
|
|
@@ -594665,7 +594811,9 @@ ${lines.join("\n")}`);
|
|
|
594665
594811
|
`- chat: a short conversational answer can be produced without tools.`,
|
|
594666
594812
|
`- action: tools, workspace context, media processing, web lookup, delegation, or a multi-step agent loop may be needed.`,
|
|
594667
594813
|
``,
|
|
594668
|
-
`Reply discretion: infer from the live thread, speaker relationships, direct mentions, replies, tone, and current message. Do not use static keyword rules
|
|
594814
|
+
`Reply discretion: infer from the live thread, speaker relationships, direct mentions, replies, tone, and current message. Do not use static keyword rules.`,
|
|
594815
|
+
`Private chats: should_reply is normally true.`,
|
|
594816
|
+
`Group/public chats: default should_reply to false unless the current message clearly addresses the bot, replies to the bot, continues an active bot-involved exchange, assigns the bot work, or asks for the bot's view. Ambient chatter, third-person discussion about the bot, commands meant for a human, or questions among other people are false. Do not set true just because the bot could help.`,
|
|
594669
594817
|
forcedLine,
|
|
594670
594818
|
``,
|
|
594671
594819
|
`Tool context: ${toolContext}`,
|
|
@@ -594696,15 +594844,17 @@ ${msg.text}`
|
|
|
594696
594844
|
think: false
|
|
594697
594845
|
});
|
|
594698
594846
|
const text = result.choices[0]?.message?.content ?? "";
|
|
594699
|
-
const parsed = parseTelegramInteractionDecision(text, forcedRoute
|
|
594847
|
+
const parsed = parseTelegramInteractionDecision(text, forcedRoute, {
|
|
594848
|
+
defaultShouldReply: !isGroup
|
|
594849
|
+
});
|
|
594700
594850
|
if (parsed) return parsed;
|
|
594701
594851
|
} catch {
|
|
594702
594852
|
}
|
|
594703
594853
|
return {
|
|
594704
594854
|
route: forcedRoute ?? "action",
|
|
594705
|
-
shouldReply:
|
|
594855
|
+
shouldReply: !isGroup,
|
|
594706
594856
|
confidence: 0,
|
|
594707
|
-
reason: "router inference failed;
|
|
594857
|
+
reason: isGroup ? "router inference failed; public group fails closed without keyword heuristics" : "router inference failed; private chat defaults to reply",
|
|
594708
594858
|
source: "inference-unavailable"
|
|
594709
594859
|
};
|
|
594710
594860
|
}
|
|
@@ -595096,6 +595246,20 @@ Join: ${newUrl}`);
|
|
|
595096
595246
|
}
|
|
595097
595247
|
const existing = this.subAgents.get(sessionKey);
|
|
595098
595248
|
if (existing && !existing.aborted) {
|
|
595249
|
+
const isGroup = msg.chatType !== "private";
|
|
595250
|
+
if (isGroup) {
|
|
595251
|
+
this.recordTelegramUserMessage(msg, "ambient");
|
|
595252
|
+
const decision2 = await this.inferTelegramInteractionDecision(msg, existing.toolContext || toolContext);
|
|
595253
|
+
this.markLastTelegramUserMessageMode(msg, decision2.shouldReply ? "steering" : "ambient");
|
|
595254
|
+
this.subAgentViewCallbacks?.onWrite(
|
|
595255
|
+
existing.viewId,
|
|
595256
|
+
`live steering: ${decision2.shouldReply ? decision2.route : "no_reply"} (${decision2.source}, confidence ${decision2.confidence.toFixed(2)}): ${decision2.reason}`
|
|
595257
|
+
);
|
|
595258
|
+
if (!decision2.shouldReply) {
|
|
595259
|
+
this.maybeLogTelegramGroupSkip(msg, `live inference: no steering — ${decision2.reason}`);
|
|
595260
|
+
return;
|
|
595261
|
+
}
|
|
595262
|
+
}
|
|
595099
595263
|
let steeringText = msg.text;
|
|
595100
595264
|
if (msg.media) {
|
|
595101
595265
|
const mediaContext = await this.processMedia(msg);
|
|
@@ -595106,7 +595270,11 @@ Join: ${newUrl}`);
|
|
|
595106
595270
|
${mediaContext}`;
|
|
595107
595271
|
}
|
|
595108
595272
|
}
|
|
595109
|
-
|
|
595273
|
+
if (isGroup) {
|
|
595274
|
+
this.markLastTelegramUserMessageMode(msg, "steering");
|
|
595275
|
+
} else {
|
|
595276
|
+
this.recordTelegramUserMessage(msg, "steering", steeringText);
|
|
595277
|
+
}
|
|
595110
595278
|
if (existing.runner) {
|
|
595111
595279
|
existing.runner.injectUserMessage(steeringText);
|
|
595112
595280
|
this.tuiWrite(() => renderTelegramSubAgentEvent(msg.username, "mid-conversation steering injected"));
|
|
@@ -595172,7 +595340,8 @@ ${mediaContext}`;
|
|
|
595172
595340
|
clearInterval(subAgent.typingInterval);
|
|
595173
595341
|
subAgent.typingInterval = null;
|
|
595174
595342
|
}
|
|
595175
|
-
|
|
595343
|
+
const finalText = cleanTelegramVisibleReply(result || "");
|
|
595344
|
+
if (!finalText) {
|
|
595176
595345
|
if (msg.chatType !== "private") {
|
|
595177
595346
|
this.maybeLogTelegramGroupSkip(msg, "discretion: skipped reply");
|
|
595178
595347
|
} else {
|
|
@@ -595186,20 +595355,10 @@ ${mediaContext}`;
|
|
|
595186
595355
|
}
|
|
595187
595356
|
return;
|
|
595188
595357
|
}
|
|
595189
|
-
const finalText = stripTelegramHiddenThinking(result || "").trim();
|
|
595190
595358
|
if (subAgent.liveMessagePromise) {
|
|
595191
595359
|
await subAgent.liveMessagePromise.catch(() => {
|
|
595192
595360
|
});
|
|
595193
595361
|
}
|
|
595194
|
-
if (!finalText) {
|
|
595195
|
-
if (subAgent.liveMessageId && !msg.guestQueryId) {
|
|
595196
|
-
await this.deleteLiveMessage(msg.chatId, subAgent.liveMessageId).catch(() => {
|
|
595197
|
-
});
|
|
595198
|
-
}
|
|
595199
|
-
this.subAgentViewCallbacks?.onWrite(subAgent.viewId, "completed: no model reply");
|
|
595200
|
-
this.subAgentViewCallbacks?.onStatus(subAgent.viewId, "completed");
|
|
595201
|
-
return;
|
|
595202
|
-
}
|
|
595203
595362
|
this.recordTelegramAssistantMessage(msg, finalText, "action");
|
|
595204
595363
|
const finalHtml = convertMarkdownToTelegramHTML(finalText);
|
|
595205
595364
|
await this.sendOrEditFinalTelegramHTML(msg, finalHtml, subAgent.liveMessageId);
|
|
@@ -595280,7 +595439,7 @@ ${mediaContext}`;
|
|
|
595280
595439
|
clearInterval(subAgent.typingInterval);
|
|
595281
595440
|
subAgent.typingInterval = null;
|
|
595282
595441
|
}
|
|
595283
|
-
const finalText =
|
|
595442
|
+
const finalText = cleanTelegramVisibleReply(result || "");
|
|
595284
595443
|
if (subAgent.liveMessagePromise) {
|
|
595285
595444
|
await subAgent.liveMessagePromise.catch(() => {
|
|
595286
595445
|
});
|
|
@@ -595370,10 +595529,12 @@ ${mediaContext}`;
|
|
|
595370
595529
|
}
|
|
595371
595530
|
if (liveMessageId && !msg.guestQueryId && now - lastEditMs > 900) {
|
|
595372
595531
|
lastEditMs = now;
|
|
595532
|
+
const html = renderTelegramLiveProgressHTML(progressLines, accumulated);
|
|
595533
|
+
if (!html.trim()) return;
|
|
595373
595534
|
await this.editLiveMessage(
|
|
595374
595535
|
msg.chatId,
|
|
595375
595536
|
liveMessageId,
|
|
595376
|
-
|
|
595537
|
+
html
|
|
595377
595538
|
).catch(() => {
|
|
595378
595539
|
});
|
|
595379
595540
|
} else if (!liveMessageId && !liveMessagePromise && !msg.guestQueryId) {
|
|
@@ -595399,7 +595560,7 @@ ${mediaContext}`;
|
|
|
595399
595560
|
clearInterval(typingInterval);
|
|
595400
595561
|
typingInterval = null;
|
|
595401
595562
|
}
|
|
595402
|
-
const cleaned =
|
|
595563
|
+
const cleaned = cleanTelegramVisibleReply(finalText || accumulated);
|
|
595403
595564
|
const pendingLiveMessage = liveMessagePromise;
|
|
595404
595565
|
if (pendingLiveMessage) {
|
|
595405
595566
|
await pendingLiveMessage.catch(() => {
|
|
@@ -595452,7 +595613,7 @@ ${mediaContext}`;
|
|
|
595452
595613
|
isGroup ? 44 : 24
|
|
595453
595614
|
);
|
|
595454
595615
|
const safety = isAdminDM ? "Admin private DM. The user is trusted, but quick-chat mode still has no tool access." : isAdminGroup ? ADMIN_GROUP_PROMPT : TELEGRAM_SAFETY_PROMPT;
|
|
595455
|
-
const groupHint = isGroup ? `Telegram group: ${msg.chatTitle || "unknown"}.
|
|
595616
|
+
const groupHint = isGroup ? `Telegram group: ${msg.chatTitle || "unknown"}. The live router selected this turn as reply-worthy; keep the reply short and relevant. Never output a skip decision, no_reply marker, memory-stage note, or completion status.` : "Telegram private chat.";
|
|
595456
595617
|
const runtime = buildTelegramRuntimeContext(/* @__PURE__ */ new Date());
|
|
595457
595618
|
const messages2 = [
|
|
595458
595619
|
{
|
|
@@ -595642,7 +595803,7 @@ ${toolHint}
|
|
|
595642
595803
|
Telegram message from @${msg.username}${chatLabel}:
|
|
595643
595804
|
${msg.text}
|
|
595644
595805
|
|
|
595645
|
-
Respond concisely and safely.`;
|
|
595806
|
+
Respond concisely and safely. Send the actual chat reply, not router/status/completion commentary.`;
|
|
595646
595807
|
}
|
|
595647
595808
|
if (mediaContext) {
|
|
595648
595809
|
userPrompt += `
|
|
@@ -595671,11 +595832,11 @@ ${creativeWorkspace}` : ""}`;
|
|
|
595671
595832
|
buildSubAgentTools(context2, repoRoot, chatId, todoSessionId) {
|
|
595672
595833
|
const taskComplete = {
|
|
595673
595834
|
name: "task_complete",
|
|
595674
|
-
description: "Internal completion signal for Telegram runs. Put the actual user-facing reply in assistant text before calling this. Use summary 'no_reply' only to silently skip responding.",
|
|
595835
|
+
description: "Internal completion signal for Telegram runs. Put the actual user-facing reply in assistant text before calling this. Use summary 'no_reply' only to silently skip responding; never write that sentinel as assistant text.",
|
|
595675
595836
|
parameters: {
|
|
595676
595837
|
type: "object",
|
|
595677
595838
|
properties: {
|
|
595678
|
-
summary: { type: "string", description: "Internal completion note, or 'no_reply' to skip when no assistant reply should be sent" }
|
|
595839
|
+
summary: { type: "string", description: "Internal completion note, or 'no_reply' to skip when no assistant reply should be sent. This is never shown directly to Telegram." }
|
|
595679
595840
|
},
|
|
595680
595841
|
required: ["summary"]
|
|
595681
595842
|
},
|
|
@@ -624977,8 +625138,12 @@ This is an independent background session started from /background.`
|
|
|
624977
625138
|
await new Promise((r3) => setTimeout(r3, 5e3));
|
|
624978
625139
|
return _tryNexusConnect(attempt + 1);
|
|
624979
625140
|
}
|
|
625141
|
+
const nexusLogPath = join136(repoRoot, ".omnius", "nexus", "daemon.err");
|
|
625142
|
+
const visibleOut = out.length > 1200 ? `${out.slice(0, 1200)}...` : out;
|
|
624980
625143
|
writeContent(
|
|
624981
|
-
() => renderWarning(`Nexus auto-connect failed:
|
|
625144
|
+
() => renderWarning(`Nexus auto-connect failed:
|
|
625145
|
+
${visibleOut}
|
|
625146
|
+
Log: ${nexusLogPath}`)
|
|
624982
625147
|
);
|
|
624983
625148
|
} else if (out.includes("still connecting") || out.includes("spawned")) {
|
|
624984
625149
|
for (let i2 = 0; i2 < 30; i2++) {
|
|
@@ -626728,7 +626893,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
626728
626893
|
},
|
|
626729
626894
|
onAgentSpeech(text) {
|
|
626730
626895
|
writeContent(
|
|
626731
|
-
() => renderInfo(`\x1B[38;5;
|
|
626896
|
+
() => renderInfo(`\x1B[38;5;37m[agent]\x1B[0m ${text.slice(0, 120)}`)
|
|
626732
626897
|
);
|
|
626733
626898
|
},
|
|
626734
626899
|
// Keep state changes silent
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnius",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "omnius",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.4",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "CC-BY-NC-4.0",
|
|
12
12
|
"dependencies": {
|
package/package.json
CHANGED