omnius 1.0.384 → 1.0.385

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -8602,12 +8602,14 @@ __export(vision_exports, {
8602
8602
  MOONDREAM3_PREVIEW_HF_MODEL: () => MOONDREAM3_PREVIEW_HF_MODEL,
8603
8603
  VisionTool: () => VisionTool,
8604
8604
  analyzeImageWithVision: () => analyzeImageWithVision,
8605
+ callOllamaVision: () => callOllamaVision,
8605
8606
  formatVisionPointResult: () => formatVisionPointResult,
8606
8607
  getVisionPointDiagnostics: () => getVisionPointDiagnostics,
8607
8608
  locateImagePoints: () => locateImagePoints,
8608
8609
  normalizeVisionModelName: () => normalizeVisionModelName,
8609
8610
  resetMoondreamClient: () => resetMoondreamClient,
8610
8611
  resolveHuggingFaceVisionModelCandidates: () => resolveHuggingFaceVisionModelCandidates,
8612
+ resolveInstalledOllamaVisionModelAlias: () => resolveInstalledOllamaVisionModelAlias,
8611
8613
  resolveOllamaVisionModelCandidates: () => resolveOllamaVisionModelCandidates
8612
8614
  });
8613
8615
  import { mkdirSync as mkdirSync9, readFileSync as readFileSync12, existsSync as existsSync14, statSync as statSync7, unlinkSync as unlinkSync2, writeFileSync as writeFileSync10 } from "node:fs";
@@ -8940,7 +8942,8 @@ function resolveOllamaVisionModelCandidates(options2 = {}) {
8940
8942
  ollamaVisionModelName(options2.preferredModel || ""),
8941
8943
  process.env["OLLAMA_VISION_MODEL"] || "",
8942
8944
  options2.activeModelHasVision && options2.activeModel ? options2.activeModel : "",
8943
- DEFAULT_OLLAMA_VISION_MODEL
8945
+ DEFAULT_OLLAMA_VISION_MODEL,
8946
+ `${DEFAULT_OLLAMA_VISION_MODEL}:latest`
8944
8947
  ].map((entry) => entry.trim()).filter(Boolean);
8945
8948
  return [...new Set(candidates)];
8946
8949
  }
@@ -9191,6 +9194,26 @@ async function callOllamaVision(ollamaHost, model, prompt, imageBase64, timeoutM
9191
9194
  if (!res.ok && shouldAutoPullOllamaVisionModel(model)) {
9192
9195
  const errText = await res.text().catch(() => "");
9193
9196
  if (res.status === 404 || /not found|does not exist/i.test(errText)) {
9197
+ const installedAlias = await resolveInstalledOllamaVisionModelAlias(ollamaHost, model, timeoutMs);
9198
+ if (installedAlias && installedAlias !== model) {
9199
+ res = await fetch(`${ollamaHost}/api/generate`, {
9200
+ method: "POST",
9201
+ headers: { "Content-Type": "application/json" },
9202
+ body: JSON.stringify({
9203
+ model: installedAlias,
9204
+ prompt,
9205
+ images: [imageBase64],
9206
+ stream: false,
9207
+ think: false,
9208
+ options: { temperature: 0 }
9209
+ }),
9210
+ signal: AbortSignal.timeout(timeoutMs)
9211
+ });
9212
+ if (res.ok) {
9213
+ const data2 = await res.json();
9214
+ return typeof data2.response === "string" && data2.response.trim() ? data2.response : null;
9215
+ }
9216
+ }
9194
9217
  try {
9195
9218
  ensureDiskSpaceForOllamaVisionModel(model);
9196
9219
  pullOllamaVisionModel(model);
@@ -9217,6 +9240,33 @@ async function callOllamaVision(ollamaHost, model, prompt, imageBase64, timeoutM
9217
9240
  const data = await res.json();
9218
9241
  return typeof data.response === "string" && data.response.trim() ? data.response : null;
9219
9242
  }
9243
+ async function resolveInstalledOllamaVisionModelAlias(ollamaHost, model, timeoutMs = 5e3) {
9244
+ const requested = model.trim();
9245
+ if (!requested)
9246
+ return null;
9247
+ try {
9248
+ const res = await fetch(`${ollamaHost}/api/tags`, {
9249
+ signal: AbortSignal.timeout(Math.min(Math.max(timeoutMs, 1e3), 5e3))
9250
+ });
9251
+ if (!res.ok)
9252
+ return null;
9253
+ const data = await res.json();
9254
+ const names = (Array.isArray(data.models) ? data.models : []).map((entry) => typeof entry.name === "string" ? entry.name.trim() : "").filter(Boolean);
9255
+ if (names.includes(requested))
9256
+ return requested;
9257
+ if (!requested.includes(":")) {
9258
+ const latest = `${requested}:latest`;
9259
+ if (names.includes(latest))
9260
+ return latest;
9261
+ const prefixMatch = names.find((name10) => name10.startsWith(`${requested}:`));
9262
+ if (prefixMatch)
9263
+ return prefixMatch;
9264
+ }
9265
+ } catch {
9266
+ return null;
9267
+ }
9268
+ return null;
9269
+ }
9220
9270
  function shouldAutoPullOllamaVisionModel(model) {
9221
9271
  if (!envFlag2(process.env["OMNIUS_OLLAMA_VISION_AUTO_PULL"], true))
9222
9272
  return false;
@@ -295276,6 +295326,21 @@ function getTodoSessionId() {
295276
295326
  return envSession;
295277
295327
  return "default";
295278
295328
  }
295329
+ function validateLargeTaskDecomposition(todos) {
295330
+ if (todos.length < 20)
295331
+ return null;
295332
+ const ids = new Set(todos.map((todo) => todo.id).filter((id) => typeof id === "string" && id.trim().length > 0));
295333
+ const childTodos = todos.filter((todo) => typeof todo.parentId === "string" && todo.parentId.trim().length > 0);
295334
+ const parentIds = new Set(childTodos.map((todo) => todo.parentId.trim()));
295335
+ const hasValidParent = [...parentIds].some((parentId) => ids.has(parentId));
295336
+ if (childTodos.length > 0 && hasValidParent)
295337
+ return null;
295338
+ return [
295339
+ "Large todo lists (20+ items) must be decomposed into a nested tree with stable ids and parentId links.",
295340
+ "Create parent objectives and child leaf tasks instead of a flat checklist.",
295341
+ 'Canonical shape: todo_write({"todos":[{"id":"group-1","content":"Steps 01-08","status":"in_progress"},{"id":"step-01","parentId":"group-1","content":"Complete step 01 and verify evidence","status":"in_progress"}]})'
295342
+ ].join(" ");
295343
+ }
295279
295344
  function normalizeIncomingTodos(args) {
295280
295345
  const repairNotes = [];
295281
295346
  const record = args;
@@ -295462,6 +295527,15 @@ Mark tasks complete IMMEDIATELY after finishing — don't batch. Never mark comp
295462
295527
  declaredArtifacts: Array.isArray(entry["declaredArtifacts"]) ? entry["declaredArtifacts"].filter((x) => typeof x === "string") : void 0
295463
295528
  });
295464
295529
  }
295530
+ const decompositionError = validateLargeTaskDecomposition(incoming);
295531
+ if (decompositionError) {
295532
+ return {
295533
+ success: false,
295534
+ output: "",
295535
+ error: decompositionError,
295536
+ durationMs: performance.now() - start2
295537
+ };
295538
+ }
295465
295539
  const sessionId = typeof args["session_id"] === "string" && args["session_id"].trim() ? args["session_id"].trim() : typeof args["sessionId"] === "string" && args["sessionId"].trim() ? args["sessionId"].trim() : getTodoSessionId();
295466
295540
  const oldTodos = readTodos(sessionId);
295467
295541
  const canonicalize2 = (todos) => JSON.stringify(todos.map((t2) => ({
@@ -547133,6 +547207,23 @@ function summarizeProcessFailure(stdout, stderr) {
547133
547207
  }
547134
547208
  return parts.join("\n").slice(0, 2200);
547135
547209
  }
547210
+ function formatObjectRecognitionResult(result) {
547211
+ const matches = (Array.isArray(result.matches) ? result.matches : []).filter((m2) => m2.recognized);
547212
+ const matchLines = matches.map((m2) => ` ${m2.label}: ${(m2.blended_score * 100).toFixed(0)}% (image=${(m2.image_similarity * 100).toFixed(0)}%, text=${(m2.text_similarity * 100).toFixed(0)}%)`);
547213
+ const extraLabels = Array.isArray(result.extra_labels) ? result.extra_labels : null;
547214
+ if (extraLabels && extraLabels.length > 0) {
547215
+ const extraLines = extraLabels.map((s2) => ` ${s2.label}: ${(s2.score * 100).toFixed(0)}%`);
547216
+ const sections = [`CLIP candidate label scores:
547217
+ ${extraLines.join("\n")}`];
547218
+ if (matches.length > 0) {
547219
+ sections.push(`Persistent visual memory matches above threshold:
547220
+ ${matchLines.join("\n")}`);
547221
+ }
547222
+ return sections.join("\n\n");
547223
+ }
547224
+ return matches.length > 0 ? `Recognized ${result.recognized_count} object(s):
547225
+ ${matchLines.join("\n")}` : "No taught objects recognized in this image.";
547226
+ }
547136
547227
  var VMEM_DIR, VENV_DIR2, VENV_PY, VENV_PIP2, VISUAL_MEMORY_ACTIONS, VisualMemoryTool;
547137
547228
  var init_visual_memory = __esm({
547138
547229
  "packages/execution/dist/tools/visual-memory.js"() {
@@ -547668,18 +547759,7 @@ print(json.dumps({
547668
547759
  const payload = JSON.stringify(result);
547669
547760
  return { success: true, output: payload, llmContent: payload, durationMs: performance.now() - start2 };
547670
547761
  }
547671
- const matches = (result.matches || []).filter((m2) => m2.recognized);
547672
- const lines = matches.map((m2) => ` ${m2.label}: ${(m2.blended_score * 100).toFixed(0)}% (image=${(m2.image_similarity * 100).toFixed(0)}%, text=${(m2.text_similarity * 100).toFixed(0)}%)`);
547673
- let output = matches.length > 0 ? `Recognized ${result.recognized_count} object(s):
547674
- ${lines.join("\n")}` : "No taught objects recognized in this image.";
547675
- if (result.extra_labels) {
547676
- const extraLines = result.extra_labels.map((s2) => ` ${s2.label}: ${(s2.score * 100).toFixed(0)}%`);
547677
- output += `
547678
-
547679
- CLIP label scores:
547680
- ${extraLines.join("\n")}`;
547681
- }
547682
- return { success: true, output, durationMs: performance.now() - start2 };
547762
+ return { success: true, output: formatObjectRecognitionResult(result), durationMs: performance.now() - start2 };
547683
547763
  }
547684
547764
  // =========================================================================
547685
547765
  // Memory Management
@@ -728690,11 +728770,17 @@ var init_serve2 = __esm({
728690
728770
  // packages/cli/src/commands/eval.ts
728691
728771
  var eval_exports = {};
728692
728772
  __export(eval_exports, {
728693
- evalCommand: () => evalCommand
728773
+ createTempEvalRepo: () => createTempEvalRepo,
728774
+ evalCommand: () => evalCommand,
728775
+ expectedStatusesForEvalTask: () => expectedStatusesForEvalTask
728694
728776
  });
728695
728777
  import { tmpdir as tmpdir23 } from "node:os";
728696
728778
  import { mkdirSync as mkdirSync106, writeFileSync as writeFileSync90 } from "node:fs";
728697
728779
  import { join as join178 } from "node:path";
728780
+ function expectedStatusesForEvalTask(task, live) {
728781
+ if (!live) return task.expectedStatuses;
728782
+ return task.liveExpectedStatuses ?? task.expectedStatuses.filter((status) => status !== "needs_human_decision");
728783
+ }
728698
728784
  async function evalCommand(opts, config) {
728699
728785
  const suiteName = opts.suite ?? "basic";
728700
728786
  const suite = SUITES[suiteName];
@@ -728708,6 +728794,10 @@ async function evalCommand(opts, config) {
728708
728794
  printKeyValue("Suite", suiteName, 2);
728709
728795
  printKeyValue("Tasks", String(suite.length), 2);
728710
728796
  printKeyValue("Mode", modeLabel, 2);
728797
+ if (useLive) {
728798
+ printKeyValue("Live pass statuses", "success, partial_success", 2);
728799
+ printInfo("Live eval treats needs_human_decision as a failure for concrete coding tasks.");
728800
+ }
728711
728801
  const evalRepoRoot = opts.repoPath ?? createTempEvalRepo();
728712
728802
  let rawBackend;
728713
728803
  if (useLive) {
@@ -728766,22 +728856,27 @@ async function evalCommand(opts, config) {
728766
728856
  let result;
728767
728857
  try {
728768
728858
  const report2 = await loop.run(task.request, evalRepoRoot);
728769
- const passed2 = task.expectedStatuses.includes(report2.status);
728859
+ const expectedStatuses = expectedStatusesForEvalTask(task, useLive);
728860
+ const passed2 = expectedStatuses.includes(report2.status);
728770
728861
  result = {
728771
728862
  task,
728772
728863
  status: report2.status,
728864
+ expectedStatuses,
728773
728865
  passed: passed2,
728774
728866
  durationMs: Date.now() - start2
728775
728867
  };
728776
728868
  if (passed2) {
728777
728869
  spinner.succeed(`[${task.id}] PASS (${report2.status})`);
728778
728870
  } else {
728779
- spinner.fail(`[${task.id}] FAIL (got: ${report2.status})`);
728871
+ spinner.fail(
728872
+ `[${task.id}] FAIL (got: ${report2.status}; expected: ${expectedStatuses.join(", ")})`
728873
+ );
728780
728874
  }
728781
728875
  } catch (err) {
728782
728876
  result = {
728783
728877
  task,
728784
728878
  status: "error",
728879
+ expectedStatuses: expectedStatusesForEvalTask(task, useLive),
728785
728880
  passed: false,
728786
728881
  durationMs: Date.now() - start2,
728787
728882
  error: err instanceof Error ? err.message : String(err)
@@ -728807,7 +728902,7 @@ async function evalCommand(opts, config) {
728807
728902
  const icon = r2.passed ? "PASS" : "FAIL";
728808
728903
  printKeyValue(
728809
728904
  `${r2.task.id} [${icon}]`,
728810
- `${r2.status} (${formatDuration(r2.durationMs)})`,
728905
+ `${r2.status} (${formatDuration(r2.durationMs)}; expected ${r2.expectedStatuses.join(", ")})`,
728811
728906
  2
728812
728907
  );
728813
728908
  if (r2.error) {
@@ -728825,13 +728920,79 @@ async function evalCommand(opts, config) {
728825
728920
  function createTempEvalRepo() {
728826
728921
  const dir = join178(tmpdir23(), `omnius-eval-${Date.now()}`);
728827
728922
  mkdirSync106(dir, { recursive: true });
728828
- writeFileSync90(
728829
- join178(dir, "package.json"),
728830
- JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n",
728831
- "utf8"
728832
- );
728923
+ mkdirSync106(join178(dir, "src"), { recursive: true });
728924
+ mkdirSync106(join178(dir, "tests"), { recursive: true });
728925
+ writeEvalFile(dir, "package.json", JSON.stringify({
728926
+ name: "eval-repo",
728927
+ version: "0.0.0",
728928
+ type: "module",
728929
+ scripts: { test: "node tests/auth.test.js && node tests/users.test.js && node tests/db.test.js && node tests/payment.test.js" }
728930
+ }, null, 2));
728931
+ writeEvalFile(dir, "src/auth.js", [
728932
+ "export function authenticateUser(user) {",
728933
+ " return user.active;",
728934
+ "}"
728935
+ ].join("\n"));
728936
+ writeEvalFile(dir, "src/users.js", [
728937
+ "export function listUsers(users) {",
728938
+ " return users.slice();",
728939
+ "}"
728940
+ ].join("\n"));
728941
+ writeEvalFile(dir, "src/db.js", [
728942
+ "export function getConnection() {",
728943
+ ' return Promise.resolve({ id: "primary", open: true });',
728944
+ "}"
728945
+ ].join("\n"));
728946
+ writeEvalFile(dir, "src/payment.js", [
728947
+ "export function applyDiscount(amount, percent) {",
728948
+ " return amount - amount * (percent / 100);",
728949
+ "}",
728950
+ "",
728951
+ "export function addTax(amount, taxRate) {",
728952
+ " return amount + amount * taxRate;",
728953
+ "}"
728954
+ ].join("\n"));
728955
+ writeEvalFile(dir, "src/api.js", [
728956
+ "export function health() {",
728957
+ " return { ok: true };",
728958
+ "}",
728959
+ "",
728960
+ "export function version() {",
728961
+ ' return "0.0.0";',
728962
+ "}"
728963
+ ].join("\n"));
728964
+ writeEvalFile(dir, "tests/auth.test.js", [
728965
+ "import assert from 'node:assert/strict';",
728966
+ "import { authenticateUser } from '../src/auth.js';",
728967
+ "assert.equal(authenticateUser({ id: 'u1', active: true }), true);",
728968
+ "assert.equal(authenticateUser({ id: 'u2', active: false }), false);",
728969
+ "assert.equal(authenticateUser(null), false);",
728970
+ "assert.equal(authenticateUser(undefined), false);"
728971
+ ].join("\n"));
728972
+ writeEvalFile(dir, "tests/users.test.js", [
728973
+ "import assert from 'node:assert/strict';",
728974
+ "import { paginateUsers } from '../src/users.js';",
728975
+ "const users = ['a', 'b', 'c', 'd', 'e'];",
728976
+ "assert.deepEqual(paginateUsers(users, 1, 2), { items: ['a', 'b'], page: 1, pageSize: 2, totalPages: 3, totalItems: 5 });",
728977
+ "assert.deepEqual(paginateUsers(users, 3, 2).items, ['e']);"
728978
+ ].join("\n"));
728979
+ writeEvalFile(dir, "tests/db.test.js", [
728980
+ "import assert from 'node:assert/strict';",
728981
+ "import { getConnection } from '../src/db.js';",
728982
+ "const conn = await getConnection();",
728983
+ "assert.deepEqual(conn, { id: 'primary', open: true });"
728984
+ ].join("\n"));
728985
+ writeEvalFile(dir, "tests/payment.test.js", [
728986
+ "import assert from 'node:assert/strict';",
728987
+ "import { applyDiscount, addTax } from '../src/payment.js';",
728988
+ "assert.equal(applyDiscount(100, 15), 85);",
728989
+ "assert.equal(addTax(100, 0.0825), 108.25);"
728990
+ ].join("\n"));
728833
728991
  return dir;
728834
728992
  }
728993
+ function writeEvalFile(root, relativePath, content) {
728994
+ writeFileSync90(join178(root, relativePath), content.trimEnd() + "\n", "utf8");
728995
+ }
728835
728996
  var BASIC_SUITE, FULL_SUITE, SUITES;
728836
728997
  var init_eval = __esm({
728837
728998
  "packages/cli/src/commands/eval.ts"() {
@@ -728843,21 +729004,24 @@ var init_eval = __esm({
728843
729004
  BASIC_SUITE = [
728844
729005
  {
728845
729006
  id: "eval-001",
728846
- description: "Simple fix request",
728847
- request: "Fix the null pointer dereference in the auth module",
728848
- expectedStatuses: ["success", "partial_success", "needs_human_decision"]
729007
+ description: "Boundary bug fix",
729008
+ request: "In src/auth.js, fix authenticateUser so null or undefined users return false instead of throwing. Use tests/auth.test.js as the acceptance evidence.",
729009
+ expectedStatuses: ["success", "partial_success", "needs_human_decision"],
729010
+ liveExpectedStatuses: ["success", "partial_success"]
728849
729011
  },
728850
729012
  {
728851
729013
  id: "eval-002",
728852
729014
  description: "Feature addition request",
728853
- request: "Add pagination support to the user list endpoint",
728854
- expectedStatuses: ["success", "partial_success", "needs_human_decision"]
729015
+ request: "In src/users.js, add paginateUsers(users, page, pageSize) with 1-based page indexing, stable slicing, and totalPages metadata. Use tests/users.test.js as the acceptance evidence.",
729016
+ expectedStatuses: ["success", "partial_success", "needs_human_decision"],
729017
+ liveExpectedStatuses: ["success", "partial_success"]
728855
729018
  },
728856
729019
  {
728857
729020
  id: "eval-003",
728858
729021
  description: "Refactor request",
728859
- request: "Refactor the database connection pool to use async/await",
728860
- expectedStatuses: ["success", "partial_success", "needs_human_decision"]
729022
+ request: "In src/db.js, refactor getConnection to async/await while preserving the exported API behavior covered by tests/db.test.js.",
729023
+ expectedStatuses: ["success", "partial_success", "needs_human_decision"],
729024
+ liveExpectedStatuses: ["success", "partial_success"]
728861
729025
  }
728862
729026
  ];
728863
729027
  FULL_SUITE = [
@@ -728865,14 +729029,16 @@ var init_eval = __esm({
728865
729029
  {
728866
729030
  id: "eval-004",
728867
729031
  description: "Test generation request",
728868
- request: "Write unit tests for the payment processing module",
728869
- expectedStatuses: ["success", "partial_success", "needs_human_decision"]
729032
+ request: "Add missing unit coverage for src/payment.js discount and tax behavior in tests/payment.test.js without changing production semantics.",
729033
+ expectedStatuses: ["success", "partial_success", "needs_human_decision"],
729034
+ liveExpectedStatuses: ["success", "partial_success"]
728870
729035
  },
728871
729036
  {
728872
729037
  id: "eval-005",
728873
729038
  description: "Documentation request",
728874
- request: "Add JSDoc comments to all exported functions in the API layer",
728875
- expectedStatuses: ["success", "partial_success", "needs_human_decision"]
729039
+ request: "Add concise JSDoc comments to the exported functions in src/api.js while preserving behavior.",
729040
+ expectedStatuses: ["success", "partial_success", "needs_human_decision"],
729041
+ liveExpectedStatuses: ["success", "partial_success"]
728876
729042
  }
728877
729043
  ];
728878
729044
  SUITES = {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.384",
3
+ "version": "1.0.385",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.384",
9
+ "version": "1.0.385",
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.384",
3
+ "version": "1.0.385",
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",