omnius 1.0.193 → 1.0.194

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/README.md CHANGED
@@ -158,8 +158,8 @@ pnpm -r build
158
158
  node scripts/build-publish.mjs
159
159
  cd publish
160
160
  mkdir -p .npm-cache
161
- NPM_CONFIG_CACHE=$(pwd)/.npm-cache npm pack
162
- NPM_CONFIG_CACHE=$(pwd)/.npm-cache npm publish --access public
161
+ NPM_CONFIG_CACHE=$(pwd)/.npm-cache npm pack --prefer-online --cache-min=0 --registry https://registry.npmjs.org/
162
+ NPM_CONFIG_CACHE=$(pwd)/.npm-cache npm publish --access public --prefer-online --cache-min=0 --registry https://registry.npmjs.org/
163
163
  ```
164
164
 
165
165
  Before publishing, verify `README.md`, `package.json`, `dist/index.js`, and `dist/launcher.cjs` are in the tarball, and that `package.json` includes `readmeFilename: "README.md"` plus a string `readme`.
package/dist/index.js CHANGED
@@ -23930,7 +23930,25 @@ function listMediaModelCatalog(modality) {
23930
23930
  function resolveMediaModel(id, modality) {
23931
23931
  const wanted = normalizeModality(modality);
23932
23932
  const normalized = normalizeRepoId(id);
23933
- return listMediaModelCatalog(wanted).find((entry) => entry.spec.id === normalized || entry.spec.repoId === normalized || mediaModelSlug(entry.spec.id) === mediaModelSlug(normalized));
23933
+ const normalizedLower = normalized.toLowerCase();
23934
+ const normalizedSlug = mediaModelSlug(normalized).toLowerCase();
23935
+ return listMediaModelCatalog(wanted).find((entry) => {
23936
+ const spec = entry.spec;
23937
+ const keys = [
23938
+ spec.id,
23939
+ spec.repoId,
23940
+ basename4(spec.repoId),
23941
+ spec.label,
23942
+ mediaModelSlug(spec.id),
23943
+ mediaModelSlug(spec.repoId),
23944
+ mediaModelSlug(basename4(spec.repoId)),
23945
+ mediaModelSlug(spec.label)
23946
+ ];
23947
+ return keys.some((key) => {
23948
+ const candidate = String(key ?? "").trim();
23949
+ return candidate.toLowerCase() === normalizedLower || mediaModelSlug(candidate).toLowerCase() === normalizedSlug;
23950
+ });
23951
+ });
23934
23952
  }
23935
23953
  function listRuntimeMediaModelSpecs(modality) {
23936
23954
  return listMediaModelCatalog(modality).map((entry) => entry.spec).filter((spec) => (spec.status === "active" || spec.status === "metadata-only") && mediaBackendCompatibleWithModality(spec.backend, modality));
@@ -267033,7 +267051,9 @@ ${llmAnnotation}` : result.llmContent;
267033
267051
  import { mkdir as mkdir15, stat as stat5, writeFile as writeFile20 } from "node:fs/promises";
267034
267052
  import { dirname as dirname9, extname as extname5, isAbsolute as isAbsolute2, join as join44, resolve as resolvePath } from "node:path";
267035
267053
  function builtInRuntimeFor(spec, kind) {
267036
- if (kind !== "cad" || spec.modality !== "cad")
267054
+ if (spec.modality !== "cad")
267055
+ return null;
267056
+ if (kind !== "cad" && !spec.modalities.includes("3d"))
267037
267057
  return null;
267038
267058
  const id = spec.id.toLowerCase();
267039
267059
  if (id === "campedersen/cad0" || id === "campedersen/cad0-mini")
@@ -267061,9 +267081,9 @@ function resolveModelOutputPath(cwd4, outputPath3, ext) {
267061
267081
  }
267062
267082
  return resolved;
267063
267083
  }
267064
- function formatCadSuccessOutput(args) {
267084
+ function formatCadSuccessOutput(args, warnings = []) {
267065
267085
  const prompt = args.prompt.length > 140 ? args.prompt.slice(0, 137) + "..." : args.prompt;
267066
- return [
267086
+ const lines = [
267067
267087
  `CAD generated: ${args.filepath}`,
267068
267088
  ` Model: ${args.model}`,
267069
267089
  ` Backend: ${args.backend}`,
@@ -267072,7 +267092,13 @@ function formatCadSuccessOutput(args) {
267072
267092
  ` Prompt: "${prompt}"`,
267073
267093
  " Compact IR:",
267074
267094
  ...args.compactIr.split("\n").map((line) => ` ${line}`)
267075
- ].join("\n");
267095
+ ];
267096
+ if (warnings.length > 0) {
267097
+ lines.push(" Notes:");
267098
+ for (const warning of warnings)
267099
+ lines.push(` - ${warning}`);
267100
+ }
267101
+ return lines.join("\n");
267076
267102
  }
267077
267103
  function buildCadScadArtifact(prompt, modelId) {
267078
267104
  const profile = inferCadProfile(prompt);
@@ -267104,7 +267130,7 @@ function inferCadProfile(prompt) {
267104
267130
  const lower = prompt.toLowerCase();
267105
267131
  const dims = inferDimensions(prompt);
267106
267132
  const holeCount = inferHoleCount(lower);
267107
- const family = /gear|tooth|teeth|cog/.test(lower) ? "gear" : /flange|bolt circle|bcd/.test(lower) ? "flange" : /standoff|spacer|bushing|sleeve/.test(lower) ? "standoff" : /enclosure|box|case|shell/.test(lower) ? "enclosure" : /l-bracket|bracket|angle/.test(lower) ? "bracket" : "plate";
267133
+ const family = /sphere|ball|orb|globe|planet/.test(lower) ? "sphere" : /cone|conical/.test(lower) ? "cone" : /cylinder|tube|pipe|rod/.test(lower) ? "cylinder" : /cube|boxy block|block/.test(lower) && !/enclosure|case|shell/.test(lower) ? "cube" : /gear|tooth|teeth|cog/.test(lower) ? "gear" : /flange|bolt circle|bcd/.test(lower) ? "flange" : /standoff|spacer|bushing|sleeve/.test(lower) ? "standoff" : /enclosure|box|case|shell/.test(lower) ? "enclosure" : /l-bracket|bracket|angle/.test(lower) ? "bracket" : "plate";
267108
267134
  const holeRadius = inferHoleRadius(lower);
267109
267135
  return {
267110
267136
  family,
@@ -267201,7 +267227,11 @@ function holePositions(count, width, depth) {
267201
267227
  }
267202
267228
  function compactIrForProfile(profile) {
267203
267229
  const lines = [];
267204
- if (profile.family === "standoff" || profile.family === "flange" || profile.family === "gear") {
267230
+ if (profile.family === "sphere") {
267231
+ lines.push(`S ${num(profile.width / 2)}`);
267232
+ } else if (profile.family === "cone") {
267233
+ lines.push(`CN ${num(profile.width / 2)} 0 ${num(profile.height)}`);
267234
+ } else if (profile.family === "standoff" || profile.family === "flange" || profile.family === "gear" || profile.family === "cylinder") {
267205
267235
  lines.push(`Y ${num(profile.width / 2)} ${num(profile.height)}`);
267206
267236
  } else {
267207
267237
  lines.push(`C ${num(profile.width)} ${num(profile.depth)} ${num(profile.height)}`);
@@ -267223,6 +267253,38 @@ function compactIrForProfile(profile) {
267223
267253
  return lines.join("\n");
267224
267254
  }
267225
267255
  function scadBodyForProfile(profile) {
267256
+ if (profile.family === "sphere") {
267257
+ return [
267258
+ "difference() {",
267259
+ " sphere(r = width / 2);",
267260
+ " for (p = hole_positions) translate([p[0], p[1], -width / 2 - 0.2]) cylinder(h = width + 0.4, r = hole_r);",
267261
+ "}"
267262
+ ].join("\n");
267263
+ }
267264
+ if (profile.family === "cube") {
267265
+ return [
267266
+ "difference() {",
267267
+ " translate([-width / 2, -width / 2, -width / 2]) cube([width, width, width]);",
267268
+ " for (p = hole_positions) translate([p[0], p[1], -width / 2 - 0.2]) cylinder(h = width + 0.4, r = hole_r);",
267269
+ "}"
267270
+ ].join("\n");
267271
+ }
267272
+ if (profile.family === "cylinder") {
267273
+ return [
267274
+ "difference() {",
267275
+ " cylinder(h = height, r = width / 2);",
267276
+ " for (p = hole_positions) translate([p[0], p[1], -0.2]) cylinder(h = height + 0.4, r = hole_r);",
267277
+ "}"
267278
+ ].join("\n");
267279
+ }
267280
+ if (profile.family === "cone") {
267281
+ return [
267282
+ "difference() {",
267283
+ " cylinder(h = height, r1 = width / 2, r2 = 0);",
267284
+ " for (p = hole_positions) translate([p[0], p[1], -0.2]) cylinder(h = height + 0.4, r = hole_r);",
267285
+ "}"
267286
+ ].join("\n");
267287
+ }
267226
267288
  if (profile.family === "standoff") {
267227
267289
  return [
267228
267290
  "difference() {",
@@ -267333,10 +267395,62 @@ function statusRank(status) {
267333
267395
  return 2;
267334
267396
  return 3;
267335
267397
  }
267398
+ function isGenericModelSelector(value2, kind) {
267399
+ const raw = value2.trim().toLowerCase();
267400
+ if (!raw)
267401
+ return true;
267402
+ if (raw === "auto" || raw === "default" || raw === "best" || raw === "smallest" || raw === "recommended")
267403
+ return true;
267404
+ if (kind === "3d") {
267405
+ return /^(3d|3d model|3d-model|model|mesh|asset|object|world|glb|obj|stl|ply)$/.test(raw);
267406
+ }
267407
+ return /^(cad|cad model|text-to-cad|parametric cad|scad|step|openscad)$/.test(raw);
267408
+ }
267409
+ function looksLikeExplicitModelAdapter(value2) {
267410
+ const raw = value2.trim();
267411
+ if (!raw)
267412
+ return false;
267413
+ if (/^https?:\/\/huggingface\.co\//i.test(raw))
267414
+ return true;
267415
+ if (/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+(?:\/.*)?$/.test(raw))
267416
+ return true;
267417
+ if (/^(hf|huggingface):/i.test(raw))
267418
+ return true;
267419
+ return false;
267420
+ }
267421
+ function shouldUseTextCadFallbackFor3d(kind, prompt, input, args) {
267422
+ if (kind !== "3d")
267423
+ return false;
267424
+ if (!prompt || input)
267425
+ return false;
267426
+ const outputFormat = String(args["output_format"] ?? "").trim().toLowerCase().replace(/^\./, "");
267427
+ if (outputFormat && outputFormat !== "scad" && outputFormat !== "step")
267428
+ return false;
267429
+ const outputPath3 = String(args["output_path"] ?? "").trim().toLowerCase();
267430
+ if (/\.(glb|obj|stl|ply|png|json)$/.test(outputPath3))
267431
+ return false;
267432
+ return true;
267433
+ }
267434
+ function renderSelectionError(kind, selection) {
267435
+ const label = adapterLabel(kind);
267436
+ const available = selection.available.slice(0, 8).map((entry) => entry.spec.id);
267437
+ if (selection.missingRequested) {
267438
+ return [
267439
+ `Requested ${label} "${selection.missingRequested}" was not found in the /models catalog.`,
267440
+ available.length > 0 ? `Available ${label}s include: ${available.join(", ")}.` : `No ${label}s are currently available.`,
267441
+ `Call generate_model with action='list_models' and kind='${kind}' to inspect selectable adapters.`
267442
+ ].join("\n");
267443
+ }
267444
+ return [
267445
+ `No ${label} is available in the /models catalog.`,
267446
+ "Built-in CAD/3D adapters may be disabled by OMNIUS_MEDIA_MODEL_DISABLE_BUILTINS=1.",
267447
+ "Use hf_model_discover or hf_model_intake to add a Hugging Face media model adapter."
267448
+ ].join("\n");
267449
+ }
267336
267450
  function renderCatalogForKind(kind, entries) {
267337
267451
  if (entries.length === 0)
267338
- return `No ${kindLabel(kind)} model adapters are available.`;
267339
- const lines = [`Available ${kindLabel(kind)} model adapters:`];
267452
+ return `No ${adapterLabel(kind)}s are available.`;
267453
+ const lines = [`Available ${adapterLabel(kind)}s:`];
267340
267454
  for (const entry of entries) {
267341
267455
  const spec = entry.spec;
267342
267456
  const resources = resourceSummary(spec);
@@ -267474,6 +267588,9 @@ function resourceSummary(spec) {
267474
267588
  function kindLabel(kind) {
267475
267589
  return kind === "cad" ? "CAD" : "3D model";
267476
267590
  }
267591
+ function adapterLabel(kind) {
267592
+ return kind === "cad" ? "CAD model adapter" : "3D model adapter";
267593
+ }
267477
267594
  var RUNTIME_BLOCKER, ModelGenerateTool;
267478
267595
  var init_model_generate = __esm({
267479
267596
  "packages/execution/dist/tools/model-generate.js"() {
@@ -267557,18 +267674,28 @@ var init_model_generate = __esm({
267557
267674
  durationMs: performance.now() - start2
267558
267675
  };
267559
267676
  }
267560
- const selected = this.selectModel(kind, args);
267561
- if (!selected) {
267677
+ const selection = this.selectModel(kind, args);
267678
+ if (!selection.entry) {
267679
+ const error = renderSelectionError(kind, selection);
267562
267680
  return {
267563
267681
  success: false,
267564
- output: "",
267565
- error: `No ${kindLabel(kind)} model adapter is available. Use hf_model_discover or hf_model_intake to add one.`,
267682
+ output: error,
267683
+ error,
267684
+ llmContent: JSON.stringify({
267685
+ kind,
267686
+ created: false,
267687
+ reason: selection.missingRequested ? "model_adapter_not_found" : "no_model_adapters",
267688
+ requestedModel: selection.missingRequested,
267689
+ available: selection.available.map((entry) => modelSummary(entry))
267690
+ }, null, 2),
267566
267691
  durationMs: performance.now() - start2
267567
267692
  };
267568
267693
  }
267694
+ const selected = selection.entry;
267569
267695
  const spec = selected.spec;
267570
267696
  this.emit(start2, "setup", `Selected ${spec.id} (${spec.modality}/${spec.backend})`, 10);
267571
267697
  const readiness = await this.checkReadiness(spec, kind);
267698
+ readiness.warnings.unshift(...selection.warnings);
267572
267699
  const body = renderReadiness(kind, spec, readiness);
267573
267700
  if (action === "check") {
267574
267701
  return {
@@ -267590,7 +267717,7 @@ No artifact created: ${readiness.blockers[0] ?? `${kindLabel(kind)} generation i
267590
267717
  durationMs: performance.now() - start2
267591
267718
  };
267592
267719
  }
267593
- const prompt = String(args["prompt"] ?? "").trim();
267720
+ const prompt = String(args["prompt"] ?? "").trim() || selection.promptFromModelValue || "";
267594
267721
  const input = String(args["input_image"] ?? args["input"] ?? "").trim();
267595
267722
  if (!prompt && !input) {
267596
267723
  return {
@@ -267667,21 +267794,46 @@ No artifact created: provide prompt and/or input_image for ${kindLabel(kind)} ge
267667
267794
  return "3d";
267668
267795
  }
267669
267796
  selectModel(kind, args) {
267797
+ const warnings = [];
267798
+ const entries = rankCatalogEntries(kind);
267670
267799
  const requested = String(args["model"] ?? "").trim();
267671
267800
  const configured = kind === "cad" ? this.defaults.cadModel : this.defaults.model3dModel;
267672
- const model = requested || configured || "";
267673
- if (model)
267674
- return resolveMediaModel(model, kind);
267801
+ let promptFromModelValue;
267802
+ if (requested && !isGenericModelSelector(requested, kind)) {
267803
+ const resolved = resolveMediaModel(requested, kind);
267804
+ if (resolved)
267805
+ return { entry: resolved, available: entries, warnings };
267806
+ if (looksLikeExplicitModelAdapter(requested)) {
267807
+ return { available: entries, warnings, missingRequested: requested };
267808
+ }
267809
+ promptFromModelValue = requested;
267810
+ warnings.push(`Treating model="${requested}" as the requested object description, not a /models adapter id; using automatic selection.`);
267811
+ }
267812
+ if (configured && !isGenericModelSelector(configured, kind)) {
267813
+ const resolved = resolveMediaModel(configured, kind);
267814
+ if (resolved)
267815
+ return { entry: resolved, available: entries, warnings };
267816
+ warnings.push(`Configured /models ${kind} adapter "${configured}" is not available; falling back to automatic selection.`);
267817
+ }
267675
267818
  const requestedBackend = String(args["backend"] ?? "").trim();
267676
267819
  const backend = requestedBackend || (kind === "cad" ? this.defaults.cadBackend : this.defaults.model3dBackend);
267677
- const entries = rankCatalogEntries(kind);
267678
267820
  if (backend && backend !== "auto") {
267679
267821
  const wantedBackend = backend.toLowerCase();
267680
267822
  const matching = entries.find((entry) => entry.spec.backend === wantedBackend);
267681
267823
  if (matching)
267682
- return matching;
267824
+ return { entry: matching, available: entries, warnings, promptFromModelValue };
267825
+ warnings.push(`Requested ${kindLabel(kind)} backend "${backend}" is not available; falling back to automatic selection.`);
267683
267826
  }
267684
- return entries[0];
267827
+ const prompt = String(args["prompt"] ?? "").trim() || promptFromModelValue || "";
267828
+ const input = String(args["input_image"] ?? args["input"] ?? "").trim();
267829
+ if (shouldUseTextCadFallbackFor3d(kind, prompt, input, args)) {
267830
+ const cadFallback = rankCatalogEntries("cad").find((entry) => builtInRuntimeFor(entry.spec, "cad") === "cad0-scad");
267831
+ if (cadFallback) {
267832
+ warnings.push("Text-only 3D generation has no wired mesh runtime yet; using the built-in CAD/SCAD adapter to create a real 3D artifact.");
267833
+ return { entry: cadFallback, available: entries, warnings, promptFromModelValue };
267834
+ }
267835
+ }
267836
+ return { entry: entries[0], available: entries, warnings, promptFromModelValue };
267685
267837
  }
267686
267838
  async checkReadiness(spec, kind) {
267687
267839
  const blockers = [];
@@ -267789,7 +267941,7 @@ No artifact created: ${msg}`,
267789
267941
  prompt: args.prompt,
267790
267942
  sizeKB: Math.max(1, Math.round(info.size / 1024)),
267791
267943
  compactIr: artifact.compactIr
267792
- });
267944
+ }, args.readiness.warnings);
267793
267945
  return {
267794
267946
  success: true,
267795
267947
  output,
@@ -564537,6 +564689,8 @@ Example: ${tool.name}(${JSON.stringify(meta.examples[0].args ?? {})})` : "";
564537
564689
  "batch_edit"
564538
564690
  ]);
564539
564691
  const taskText = (this._taskState.originalGoal || this._taskState.goal || "").toLowerCase();
564692
+ const wants3dModelGeneration = /\b(?:make|create|generate|build|produce|render|give)\b/.test(taskText) && /\b(?:3d|three[-\s]?d|mesh|glb|obj|stl|ply|cad|scad|step|printable|model)\b/.test(taskText) && !/\b(?:image|picture|photo|rendering|screenshot)\b/.test(taskText);
564693
+ const wantsModelCatalogManagement = /\b(?:discover|search|find|add|install|intake|inspect|validate|save|catalog|adapter|hugging\s*face|hf)\b/.test(taskText) && /\b(?:model|adapter|hugging\s*face|hf)\b/.test(taskText);
564540
564694
  const taskWords = new Set(taskText.split(/\s+/).filter((w) => w.length > 2));
564541
564695
  const scored = [];
564542
564696
  for (const tool of allTools) {
@@ -564557,6 +564711,15 @@ Example: ${tool.name}(${JSON.stringify(meta.examples[0].args ?? {})})` : "";
564557
564711
  if (taskText.includes(tool.name.replace(/_/g, " ")) || taskText.includes(tool.name)) {
564558
564712
  score += customMeta ? 16 : 10;
564559
564713
  }
564714
+ if (wants3dModelGeneration) {
564715
+ if (tool.name === "generate_model")
564716
+ score += 40;
564717
+ if (tool.name === "generate_image")
564718
+ score -= 12;
564719
+ if ((tool.name === "hf_model_discover" || tool.name === "hf_model_intake") && !wantsModelCatalogManagement) {
564720
+ score -= 18;
564721
+ }
564722
+ }
564560
564723
  if (customMeta) {
564561
564724
  const lastStatus = customMeta.qualityGate?.lastTest?.status;
564562
564725
  if (lastStatus === "passed")
@@ -633935,6 +634098,9 @@ file access, and code analysis. Respond thoroughly and helpfully.
633935
634098
  When asked to send a generated or existing file to Telegram, call telegram_send_file with
633936
634099
  path and target. Do not search for Telegram bot tokens, environment secrets, or Bot API
633937
634100
  credentials; upload authorization is encapsulated by telegram_send_file.
634101
+ For admin-DM artifact generation requests, send the generated file with
634102
+ telegram_send_file after the generation tool succeeds unless the admin
634103
+ explicitly asked only for a local path.
633938
634104
 
633939
634105
  When asked to generate speech, narration, or TTS, use generate_tts or audio_playback.
633940
634106
  Those tools handle first-use backend setup where supported. Do not fall back to shell
@@ -633943,6 +634109,9 @@ commands or generic audio generation for speech synthesis while those tools are
633943
634109
  When asked to generate a 3D asset, mesh, printable model, or CAD part, use
633944
634110
  generate_model. Use hf_model_discover or hf_model_intake only when the admin is
633945
634111
  asking to add, inspect, validate, or save model adapters.
634112
+ For text-only 3D requests, pass the requested object in prompt and do not put
634113
+ the object name in model; model is only for exact /models adapter ids. Do not
634114
+ use generate_image as a substitute for a 3D/CAD artifact.
633946
634115
 
633947
634116
  Keep responses concise for Telegram but don't withhold information from the admin.
633948
634117
  `.trim();
@@ -642044,7 +642213,7 @@ ${currentTelegramPrompt}`;
642044
642213
  "If the user asks you to create an image, audio file, video, 3D/CAD model, or document artifact, create it with the scoped creative tools. Freshly generated artifacts are recorded and automatically attached to this Telegram chat when the turn completes, so do not call telegram_send_file for those same artifacts unless the user asked for a specific caption, existing/unrecorded file, or non-default target.",
642045
642214
  "For image generation requests, decide from the conversation whether generate_image is appropriate; do not ask the user to use a hardcoded shortcut when the request is clear.",
642046
642215
  "For video generation requests, decide whether generate_video is appropriate. Use mode='i2v' (image-to-video) when the user references an attached or already-generated image; otherwise mode='t2v'. Warn the user up front that video generation typically takes 2-10 minutes on consumer GPUs, and that the public Telegram video-generation quota is tight (2/hour/user).",
642047
- "For 3D asset, mesh, printable model, or CAD generation requests, use generate_model. Use kind='cad' for parametric/mechanical parts and kind='3d' for mesh/asset/world requests. If the tool reports a catalog/runtime blocker, explain that blocker plainly.",
642216
+ "For 3D asset, mesh, printable model, or CAD generation requests, use generate_model. Use kind='cad' for parametric/mechanical parts and kind='3d' for mesh/asset/world requests. For text-only 3D requests, put the object description in prompt and omit model unless selecting an exact /models adapter id. Do not use generate_image as a substitute for a 3D/CAD artifact. If the tool reports a catalog/runtime blocker, explain that blocker plainly.",
642048
642217
  creativeWorkspace
642049
642218
  ].filter(Boolean).join("\n\n");
642050
642219
  userPrompt = `${systemPrompt}${discretionPrompt}
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.193",
3
+ "version": "1.0.194",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.193",
9
+ "version": "1.0.194",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.193",
3
+ "version": "1.0.194",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -142,5 +142,5 @@
142
142
  "transcribe-cli": "^2.0.1",
143
143
  "viem": "2.47.4"
144
144
  },
145
- "readme": "# Omnius\n\nOmnius is a local-first agentic coding runtime: terminal UI, autonomous coding loop, REST daemon, model router, memory layer, media tools, Telegram bridge, and peer-to-peer inference mesh in one CLI.\n\nIt is designed for open-weight and user-controlled models first, while still routing cleanly through Ollama, vLLM, OpenAI-compatible endpoints, OpenRouter, Groq, Chutes, sponsor peers, COHERE peers, and other configured providers.\n\n[![npm](https://img.shields.io/npm/v/omnius.svg)](https://www.npmjs.com/package/omnius)\n[![Node](https://img.shields.io/badge/node-%3E%3D22-brightgreen.svg)](https://nodejs.org/)\n[![License](https://img.shields.io/badge/license-CC--BY--NC--4.0-blue.svg)](LICENSE)\n\n## Install\n\n```bash\nnpm install -g omnius\nomnius\n```\n\nRequirements:\n\n- Node.js 22 or newer\n- npm 10 or newer for published CLI use\n- pnpm 9 or newer for workspace development\n- A local model or configured remote endpoint\n\nStart the REST daemon:\n\n```bash\nomnius serve\n```\n\nThe daemon defaults to `http://127.0.0.1:11435`. Open the interactive API docs at `http://127.0.0.1:11435/docs`.\n\n## What Omnius Does\n\n- Runs autonomous coding tasks, edits files, executes tools, tests changes, and iterates on failures.\n- Provides a dense terminal UI for model selection, endpoint routing, task control, shell output, voice, sponsors, Telegram, and system telemetry.\n- Exposes a REST daemon with OpenAI/Ollama-compatible inference, agentic task execution, memory, skills, tools, MCP, events, voice, projects, and governance endpoints.\n- Routes models through local, cloud, sponsor, and peer-to-peer endpoints without assuming local Ollama is the only source.\n- Supports realtime spoken conversation for ASR/TTS clients through `/realtime` and REST `realtime: true`.\n- Supports image, video, sound, music, TTS, ASR, voice clone references, Telegram media workflows, and sponsor-provided media generation.\n- Keeps project runtime state in `.omnius/`, which is intentionally ignored by git.\n\n## Common Workflows\n\n```bash\nomnius \"inspect this repo and summarize the main entrypoints\"\nomnius serve\n```\n\n```text\n/help command help\n/model select or inspect the active model\n/endpoint select or configure local, cloud, sponsor, or peer endpoints\n/realtime toggle short ASR/TTS-oriented conversation mode\n/broker inspect model broker, RAM/VRAM thresholds, and loaded models\n/sponsor expose local or upstream capacity to peers\n/cohere participate in distributed COHERE inference\n/telegram configure or toggle the Telegram bridge\n/skills list explorable skills and docs memories\n/pause pause after the current turn boundary\n/stop interrupt the active run\n/resume resume saved state\n```\n\n## Current Feature Areas\n\n| Area | What to read |\n| --- | --- |\n| Install and setup | [Install](docs/getting-started/install.md), [First run](docs/getting-started/first-run.md), [Model providers](docs/getting-started/model-providers.md) |\n| Terminal workflows | [TUI workflows](docs/guides/tui-workflows.md), [Slash commands](docs/reference/slash-commands.md) |\n| REST daemon | [REST reference](docs/reference/rest-api.md), [REST quickref](docs/rest/QUICKREF.md), [OpenAPI source](docs/rest/openapi-source.md) |\n| Realtime voice chat | [Realtime guide](docs/guides/realtime.md) |\n| Sponsor and COHERE mesh | [Sponsor and COHERE guide](docs/guides/sponsor-and-cohere.md) |\n| Telegram bridge | [Telegram guide](docs/guides/telegram.md) |\n| Media generation | [Media guide](docs/guides/media-generation.md) |\n| Operations | [Runtime hygiene](docs/operations/runtime-hygiene.md), [Security and remote access](docs/operations/security-and-remote-access.md) |\n| Architecture | [Architecture overview](docs/architecture/overview.md) |\n| Agent-explorable docs | [Agent memory docs index](docs/agent-memory/INDEX.md) |\n\n## Recent Highlights\n\n- `/realtime` and REST `realtime: true` provide short, natural, SOUL.md-aware conversation for ASR/TTS clients.\n- Endpoint setup and sponsor setup aggregate models from all enabled endpoints, including external OpenAI-compatible routers.\n- `/sponsor` can expose text inference and media generation for image, video, sound, and music with per-modality limits.\n- Sponsor and COHERE status surfaces now use shared telemetry concepts: concurrency, request rate, daily tokens, peer usage, model usage, and remote system metrics.\n- The TUI reports token production rate as `t/s`, supports Shift+Enter multiline input, and renders dynamic shell output inside bounded Unicode cards.\n- Telegram state is scoped by user and group, supports durable reply preferences, and feeds raw platform/tool failures back into the agent loop.\n- Ollama pool cleanup now accounts for process groups and orphan runner processes that can keep VRAM pinned.\n- REST documentation is available both as human docs and as Omnius-discoverable docs skills.\n\n## REST API\n\nStart:\n\n```bash\nomnius serve\n```\n\nUseful entrypoints:\n\n```text\nGET /docs\nGET /openapi.json\nPOST /v1/chat\nPOST /v1/chat/completions\nPOST /v1/run\nGET /v1/events\nGET /v1/skills\nPOST /v1/tools/{name}/call\nWS /v1/voicechat/ws\n```\n\nFor shared deployments, use bearer keys:\n\n```bash\nOMNIUS_API_KEYS=\"read-key:read:grafana,run-key:run:ci:60:100000:3,admin-key:admin:ops\" omnius serve\n```\n\nSee [docs/reference/rest-api.md](docs/reference/rest-api.md) for the maintained endpoint inventory. The canonical machine contract is generated from [packages/cli/src/api/openapi.ts](packages/cli/src/api/openapi.ts).\n\n## Agent-Explorable Documentation\n\nOmnius discovers project-local docs skills from `.aiwg/addons/*/skills`. The docs bundles in this repo expose high-signal entrypoints for agents:\n\n```text\n/skills omnius docs\nskill_execute name=\"omnius-docs\"\nskill_execute name=\"omnius-rest-docs\"\nskill_extract name=\"omnius-realtime-docs\" query=\"How does realtime REST mode work?\"\n```\n\nThe intended pattern is index first, targeted document second, not loading the whole manual into the active context.\n\n## Development\n\n```bash\npnpm install\npnpm -r build\npnpm docs:check\n```\n\nFocused checks used for the docs skill surface:\n\n```bash\npnpm --filter @omnius/execution exec vitest run tests/skill-discovery.test.ts\npnpm --filter omnius exec vitest run tests/realtime-mode.test.ts tests/command-registry.test.ts\n```\n\n## Publishing\n\nPublish only from `publish/`.\n\n```bash\ncd omnius\npnpm -r clean || true\nfind . -name 'tsconfig.tsbuildinfo' -not -path '*/node_modules/*' -delete\npnpm -r build\nnode scripts/build-publish.mjs\ncd publish\nmkdir -p .npm-cache\nNPM_CONFIG_CACHE=$(pwd)/.npm-cache npm pack\nNPM_CONFIG_CACHE=$(pwd)/.npm-cache npm publish --access public\n```\n\nBefore publishing, verify `README.md`, `package.json`, `dist/index.js`, and `dist/launcher.cjs` are in the tarball, and that `package.json` includes `readmeFilename: \"README.md\"` plus a string `readme`.\n\n## License\n\nOmnius is released under [CC-BY-NC-4.0](LICENSE) for non-commercial use. Commercial use, redistribution, hosted services, and enterprise deployment require a commercial license.\n"
145
+ "readme": "# Omnius\n\nOmnius is a local-first agentic coding runtime: terminal UI, autonomous coding loop, REST daemon, model router, memory layer, media tools, Telegram bridge, and peer-to-peer inference mesh in one CLI.\n\nIt is designed for open-weight and user-controlled models first, while still routing cleanly through Ollama, vLLM, OpenAI-compatible endpoints, OpenRouter, Groq, Chutes, sponsor peers, COHERE peers, and other configured providers.\n\n[![npm](https://img.shields.io/npm/v/omnius.svg)](https://www.npmjs.com/package/omnius)\n[![Node](https://img.shields.io/badge/node-%3E%3D22-brightgreen.svg)](https://nodejs.org/)\n[![License](https://img.shields.io/badge/license-CC--BY--NC--4.0-blue.svg)](LICENSE)\n\n## Install\n\n```bash\nnpm install -g omnius\nomnius\n```\n\nRequirements:\n\n- Node.js 22 or newer\n- npm 10 or newer for published CLI use\n- pnpm 9 or newer for workspace development\n- A local model or configured remote endpoint\n\nStart the REST daemon:\n\n```bash\nomnius serve\n```\n\nThe daemon defaults to `http://127.0.0.1:11435`. Open the interactive API docs at `http://127.0.0.1:11435/docs`.\n\n## What Omnius Does\n\n- Runs autonomous coding tasks, edits files, executes tools, tests changes, and iterates on failures.\n- Provides a dense terminal UI for model selection, endpoint routing, task control, shell output, voice, sponsors, Telegram, and system telemetry.\n- Exposes a REST daemon with OpenAI/Ollama-compatible inference, agentic task execution, memory, skills, tools, MCP, events, voice, projects, and governance endpoints.\n- Routes models through local, cloud, sponsor, and peer-to-peer endpoints without assuming local Ollama is the only source.\n- Supports realtime spoken conversation for ASR/TTS clients through `/realtime` and REST `realtime: true`.\n- Supports image, video, sound, music, TTS, ASR, voice clone references, Telegram media workflows, and sponsor-provided media generation.\n- Keeps project runtime state in `.omnius/`, which is intentionally ignored by git.\n\n## Common Workflows\n\n```bash\nomnius \"inspect this repo and summarize the main entrypoints\"\nomnius serve\n```\n\n```text\n/help command help\n/model select or inspect the active model\n/endpoint select or configure local, cloud, sponsor, or peer endpoints\n/realtime toggle short ASR/TTS-oriented conversation mode\n/broker inspect model broker, RAM/VRAM thresholds, and loaded models\n/sponsor expose local or upstream capacity to peers\n/cohere participate in distributed COHERE inference\n/telegram configure or toggle the Telegram bridge\n/skills list explorable skills and docs memories\n/pause pause after the current turn boundary\n/stop interrupt the active run\n/resume resume saved state\n```\n\n## Current Feature Areas\n\n| Area | What to read |\n| --- | --- |\n| Install and setup | [Install](docs/getting-started/install.md), [First run](docs/getting-started/first-run.md), [Model providers](docs/getting-started/model-providers.md) |\n| Terminal workflows | [TUI workflows](docs/guides/tui-workflows.md), [Slash commands](docs/reference/slash-commands.md) |\n| REST daemon | [REST reference](docs/reference/rest-api.md), [REST quickref](docs/rest/QUICKREF.md), [OpenAPI source](docs/rest/openapi-source.md) |\n| Realtime voice chat | [Realtime guide](docs/guides/realtime.md) |\n| Sponsor and COHERE mesh | [Sponsor and COHERE guide](docs/guides/sponsor-and-cohere.md) |\n| Telegram bridge | [Telegram guide](docs/guides/telegram.md) |\n| Media generation | [Media guide](docs/guides/media-generation.md) |\n| Operations | [Runtime hygiene](docs/operations/runtime-hygiene.md), [Security and remote access](docs/operations/security-and-remote-access.md) |\n| Architecture | [Architecture overview](docs/architecture/overview.md) |\n| Agent-explorable docs | [Agent memory docs index](docs/agent-memory/INDEX.md) |\n\n## Recent Highlights\n\n- `/realtime` and REST `realtime: true` provide short, natural, SOUL.md-aware conversation for ASR/TTS clients.\n- Endpoint setup and sponsor setup aggregate models from all enabled endpoints, including external OpenAI-compatible routers.\n- `/sponsor` can expose text inference and media generation for image, video, sound, and music with per-modality limits.\n- Sponsor and COHERE status surfaces now use shared telemetry concepts: concurrency, request rate, daily tokens, peer usage, model usage, and remote system metrics.\n- The TUI reports token production rate as `t/s`, supports Shift+Enter multiline input, and renders dynamic shell output inside bounded Unicode cards.\n- Telegram state is scoped by user and group, supports durable reply preferences, and feeds raw platform/tool failures back into the agent loop.\n- Ollama pool cleanup now accounts for process groups and orphan runner processes that can keep VRAM pinned.\n- REST documentation is available both as human docs and as Omnius-discoverable docs skills.\n\n## REST API\n\nStart:\n\n```bash\nomnius serve\n```\n\nUseful entrypoints:\n\n```text\nGET /docs\nGET /openapi.json\nPOST /v1/chat\nPOST /v1/chat/completions\nPOST /v1/run\nGET /v1/events\nGET /v1/skills\nPOST /v1/tools/{name}/call\nWS /v1/voicechat/ws\n```\n\nFor shared deployments, use bearer keys:\n\n```bash\nOMNIUS_API_KEYS=\"read-key:read:grafana,run-key:run:ci:60:100000:3,admin-key:admin:ops\" omnius serve\n```\n\nSee [docs/reference/rest-api.md](docs/reference/rest-api.md) for the maintained endpoint inventory. The canonical machine contract is generated from [packages/cli/src/api/openapi.ts](packages/cli/src/api/openapi.ts).\n\n## Agent-Explorable Documentation\n\nOmnius discovers project-local docs skills from `.aiwg/addons/*/skills`. The docs bundles in this repo expose high-signal entrypoints for agents:\n\n```text\n/skills omnius docs\nskill_execute name=\"omnius-docs\"\nskill_execute name=\"omnius-rest-docs\"\nskill_extract name=\"omnius-realtime-docs\" query=\"How does realtime REST mode work?\"\n```\n\nThe intended pattern is index first, targeted document second, not loading the whole manual into the active context.\n\n## Development\n\n```bash\npnpm install\npnpm -r build\npnpm docs:check\n```\n\nFocused checks used for the docs skill surface:\n\n```bash\npnpm --filter @omnius/execution exec vitest run tests/skill-discovery.test.ts\npnpm --filter omnius exec vitest run tests/realtime-mode.test.ts tests/command-registry.test.ts\n```\n\n## Publishing\n\nPublish only from `publish/`.\n\n```bash\ncd omnius\npnpm -r clean || true\nfind . -name 'tsconfig.tsbuildinfo' -not -path '*/node_modules/*' -delete\npnpm -r build\nnode scripts/build-publish.mjs\ncd publish\nmkdir -p .npm-cache\nNPM_CONFIG_CACHE=$(pwd)/.npm-cache npm pack --prefer-online --cache-min=0 --registry https://registry.npmjs.org/\nNPM_CONFIG_CACHE=$(pwd)/.npm-cache npm publish --access public --prefer-online --cache-min=0 --registry https://registry.npmjs.org/\n```\n\nBefore publishing, verify `README.md`, `package.json`, `dist/index.js`, and `dist/launcher.cjs` are in the tarball, and that `package.json` includes `readmeFilename: \"README.md\"` plus a string `readme`.\n\n## License\n\nOmnius is released under [CC-BY-NC-4.0](LICENSE) for non-commercial use. Commercial use, redistribution, hosted services, and enterprise deployment require a commercial license.\n"
146
146
  }