omnius 1.0.330 → 1.0.331

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
@@ -279078,7 +279078,7 @@ if __name__ == "__main__":
279078
279078
  });
279079
279079
 
279080
279080
  // packages/execution/dist/tools/media-store-migrate.js
279081
- import { existsSync as existsSync41, readdirSync as readdirSync16, readFileSync as readFileSync30, statSync as statSync16, mkdirSync as mkdirSync22, copyFileSync, rmSync as rmSync5, statfsSync as statfsSync2 } from "node:fs";
279081
+ import { existsSync as existsSync41, readdirSync as readdirSync16, readFileSync as readFileSync30, statSync as statSync16, lstatSync, readlinkSync as readlinkSync2, symlinkSync, mkdirSync as mkdirSync22, copyFileSync, rmSync as rmSync5, statfsSync as statfsSync2 } from "node:fs";
279082
279082
  import { join as join50, dirname as dirname13, extname as extname6, resolve as resolvePath } from "node:path";
279083
279083
  function approxDirBytes(dir, budget = { nodes: 2e5 }) {
279084
279084
  let total = 0;
@@ -279209,19 +279209,41 @@ function freeBytesAt(path12) {
279209
279209
  return Number.MAX_SAFE_INTEGER;
279210
279210
  }
279211
279211
  }
279212
+ function treeSizeNoFollow(dir) {
279213
+ let entries;
279214
+ try {
279215
+ entries = readdirSync16(dir, { withFileTypes: true });
279216
+ } catch {
279217
+ return 0;
279218
+ }
279219
+ let total = 0;
279220
+ for (const ent of entries) {
279221
+ const p2 = join50(dir, ent.name);
279222
+ try {
279223
+ if (ent.isSymbolicLink())
279224
+ total += lstatSync(p2).size;
279225
+ else if (ent.isDirectory())
279226
+ total += treeSizeNoFollow(p2);
279227
+ else if (ent.isFile())
279228
+ total += statSync16(p2).size;
279229
+ } catch {
279230
+ }
279231
+ }
279232
+ return total;
279233
+ }
279212
279234
  function copyDirWithProgress(src2, dst, onFile) {
279213
279235
  mkdirSync22(dst, { recursive: true });
279214
279236
  for (const ent of readdirSync16(src2, { withFileTypes: true })) {
279215
279237
  const s2 = join50(src2, ent.name);
279216
279238
  const d2 = join50(dst, ent.name);
279217
- if (ent.isDirectory()) {
279218
- copyDirWithProgress(s2, d2, onFile);
279219
- } else if (ent.isSymbolicLink()) {
279239
+ if (ent.isSymbolicLink()) {
279220
279240
  try {
279221
- copyFileSync(s2, d2);
279222
- onFile(statSync16(d2).size, s2);
279241
+ symlinkSync(readlinkSync2(s2), d2);
279242
+ onFile(lstatSync(d2).size, s2);
279223
279243
  } catch {
279224
279244
  }
279245
+ } else if (ent.isDirectory()) {
279246
+ copyDirWithProgress(s2, d2, onFile);
279225
279247
  } else if (ent.isFile()) {
279226
279248
  copyFileSync(s2, d2);
279227
279249
  let size = 0;
@@ -279257,7 +279279,7 @@ function relocateMediaStore(args) {
279257
279279
  if (!dryRun && existsSync41(dst) && readdirSync16(dst).length > 0) {
279258
279280
  throw new Error(`Destination already has a non-empty "${name10}" folder: ${dst}. Choose an empty/new folder.`);
279259
279281
  }
279260
- const bytes = dirSizeBytes(src2);
279282
+ const bytes = treeSizeNoFollow(src2);
279261
279283
  present.push({ name: name10, src: src2, dst, bytes });
279262
279284
  bytesTotal += bytes;
279263
279285
  }
@@ -279289,8 +279311,8 @@ function relocateMediaStore(args) {
279289
279311
  emit2({ stage: "copy", bytesDone, bytesTotal, currentPath });
279290
279312
  });
279291
279313
  emit2({ stage: "verify", bytesDone, bytesTotal, message: `Verifying ${sub2.name}…` });
279292
- const copied = dirSizeBytes(sub2.dst);
279293
- if (copied < sub2.bytes * 0.99) {
279314
+ const copied = treeSizeNoFollow(sub2.dst);
279315
+ if (copied < sub2.bytes * 0.95) {
279294
279316
  throw new Error(`Verification failed for "${sub2.name}" (${formatBytes3(copied)} of ${formatBytes3(sub2.bytes)} copied). Source left intact at ${sub2.src}.`);
279295
279317
  }
279296
279318
  }
@@ -279320,9 +279342,15 @@ async function copyDirWithProgressAsync(src2, dst, onFile) {
279320
279342
  for (const ent of entries) {
279321
279343
  const s2 = join50(src2, ent.name);
279322
279344
  const d2 = join50(dst, ent.name);
279323
- if (ent.isDirectory()) {
279345
+ if (ent.isSymbolicLink()) {
279346
+ try {
279347
+ await fsp2.symlink(await fsp2.readlink(s2), d2);
279348
+ onFile((await fsp2.lstat(d2)).size, s2);
279349
+ } catch {
279350
+ }
279351
+ } else if (ent.isDirectory()) {
279324
279352
  await copyDirWithProgressAsync(s2, d2, onFile);
279325
- } else if (ent.isFile() || ent.isSymbolicLink()) {
279353
+ } else if (ent.isFile()) {
279326
279354
  try {
279327
279355
  await fsp2.copyFile(s2, d2);
279328
279356
  let size = 0;
@@ -279364,7 +279392,7 @@ async function relocateMediaStoreAsync(args) {
279364
279392
  if (!dryRun && existsSync41(dst) && readdirSync16(dst).length > 0) {
279365
279393
  throw new Error(`Destination already has a non-empty "${name10}" folder: ${dst}. Choose an empty/new folder.`);
279366
279394
  }
279367
- const bytes = dirSizeBytes(src2);
279395
+ const bytes = treeSizeNoFollow(src2);
279368
279396
  present.push({ name: name10, src: src2, dst, bytes });
279369
279397
  bytesTotal += bytes;
279370
279398
  }
@@ -279389,7 +279417,7 @@ async function relocateMediaStoreAsync(args) {
279389
279417
  emit2({ stage: "copy", bytesDone, bytesTotal, currentPath });
279390
279418
  });
279391
279419
  emit2({ stage: "verify", bytesDone, bytesTotal, message: `Verifying ${sub2.name}…` });
279392
- if (dirSizeBytes(sub2.dst) < sub2.bytes * 0.99) {
279420
+ if (treeSizeNoFollow(sub2.dst) < sub2.bytes * 0.95) {
279393
279421
  throw new Error(`Verification failed for "${sub2.name}". Source left intact at ${sub2.src}.`);
279394
279422
  }
279395
279423
  }
@@ -630946,7 +630974,7 @@ import {
630946
630974
  writeFileSync as writeFileSync66,
630947
630975
  mkdirSync as mkdirSync76,
630948
630976
  readdirSync as readdirSync44,
630949
- lstatSync,
630977
+ lstatSync as lstatSync2,
630950
630978
  statSync as statSync48,
630951
630979
  rmSync as rmSync10,
630952
630980
  appendFileSync as appendFileSync12,
@@ -639402,7 +639430,7 @@ function cacheCandidatePaths(root, model) {
639402
639430
  }
639403
639431
  function directorySizeBytes2(path12, seen = /* @__PURE__ */ new Set()) {
639404
639432
  try {
639405
- const stat8 = lstatSync(path12);
639433
+ const stat8 = lstatSync2(path12);
639406
639434
  if (stat8.isSymbolicLink()) return 0;
639407
639435
  if (stat8.isFile()) return stat8.size;
639408
639436
  if (!stat8.isDirectory()) return 0;
@@ -681018,6 +681046,54 @@ function handleRelocateStatus(ctx3) {
681018
681046
  });
681019
681047
  return true;
681020
681048
  }
681049
+ async function handleAvAnalyze(ctx3) {
681050
+ if (!requireRunScope(ctx3, "AV analysis")) return true;
681051
+ const body = await parseJsonBodyStrict(ctx3.req).catch(() => null);
681052
+ const raw = body?.path || body?.mediaUri;
681053
+ if (!raw) {
681054
+ sendProblem(ctx3.res, problemDetails({ type: P.invalidRequest, status: 400, title: "Missing media path", detail: "POST body must include {path} or {mediaUri}", instance: ctx3.requestId }));
681055
+ return true;
681056
+ }
681057
+ const filePath = raw.startsWith("file://") ? raw.slice(7) : raw;
681058
+ if (!existsSync149(filePath)) {
681059
+ sendProblem(ctx3.res, problemDetails({ type: P.notFound, status: 404, title: "Media not found", detail: filePath, instance: ctx3.requestId }));
681060
+ return true;
681061
+ }
681062
+ try {
681063
+ const registry4 = buildRegistry();
681064
+ const adapterStatus = {};
681065
+ let anyLive = false;
681066
+ for (const role of AV_ROLES) {
681067
+ const a2 = await registry4.selectForRole(role);
681068
+ adapterStatus[role] = a2 && !a2.meta.isMock ? "live" : "mock";
681069
+ if (adapterStatus[role] === "live") anyLive = true;
681070
+ }
681071
+ const episodeId = `rest-${basename37(filePath)}-${Date.now().toString(36)}`;
681072
+ const ingest = await ingestMedia(episodeId, `file://${filePath}`);
681073
+ const store2 = await analyzeEpisode({ episodeId, mediaUri: `file://${filePath}`, durationSec: ingest.source.durationSec, registry: registry4, windows: ingest.shots, roles: AV_ROLES });
681074
+ const world = store2.snapshot();
681075
+ const answer = composeAnswer(world, body?.question ?? "");
681076
+ const cap = getMediaCapability();
681077
+ sendJson2(ctx3.res, 200, {
681078
+ data: {
681079
+ episodeId,
681080
+ source: ingest.source,
681081
+ shots: ingest.shots,
681082
+ stack: cap.stack,
681083
+ adapters: adapterStatus,
681084
+ modelsLive: anyLive,
681085
+ note: anyLive ? void 0 : "No live AV models loaded yet — entity/event results are scaffold placeholders from mock adapters. They become real once the sidecar models finish downloading.",
681086
+ entities: world.entities,
681087
+ events: world.events,
681088
+ relations: world.relations,
681089
+ answer
681090
+ }
681091
+ });
681092
+ } catch (err) {
681093
+ sendProblem(ctx3.res, problemDetails({ type: P.internalError, status: 500, title: "AV analysis error", detail: err instanceof Error ? err.message : String(err), instance: ctx3.requestId }));
681094
+ }
681095
+ return true;
681096
+ }
681021
681097
  async function runGeneration(ctx3, kind, buildTool, buildArgs) {
681022
681098
  if (!requireRunScope(ctx3, `${kind} generation`)) return true;
681023
681099
  const body = await parseJsonBodyStrict(ctx3.req).catch(() => null);
@@ -681187,6 +681263,7 @@ async function tryRouteMedia(ctx3) {
681187
681263
  if (!pathname.startsWith("/v1/media")) return false;
681188
681264
  if (pathname === "/v1/media/models" && method === "GET") return handleListModels(ctx3);
681189
681265
  if (pathname === "/v1/media/store" && method === "GET") return handleStoreInfo(ctx3);
681266
+ if (pathname === "/v1/media/av/analyze" && method === "POST") return handleAvAnalyze(ctx3);
681190
681267
  if (pathname === "/v1/media/migrate" && method === "POST") return handleMigrate(ctx3);
681191
681268
  if (pathname === "/v1/media/relocate" && method === "POST") return handleRelocate(ctx3);
681192
681269
  if (pathname === "/v1/media/relocate/status" && method === "GET") return handleRelocateStatus(ctx3);
@@ -681265,7 +681342,7 @@ async function tryRouteMedia(ctx3) {
681265
681342
  }
681266
681343
  return false;
681267
681344
  }
681268
- var PROBLEM_BASE, P, MIME_BY_EXT, _relocateJob;
681345
+ var PROBLEM_BASE, P, MIME_BY_EXT, _relocateJob, AV_ROLES;
681269
681346
  var init_routes_media = __esm({
681270
681347
  "packages/cli/src/api/routes-media.ts"() {
681271
681348
  "use strict";
@@ -681296,6 +681373,7 @@ var init_routes_media = __esm({
681296
681373
  ".m4a": "audio/mp4"
681297
681374
  };
681298
681375
  _relocateJob = null;
681376
+ AV_ROLES = ["video_temporal", "grounding", "tracking", "audio_event", "cross_modal"];
681299
681377
  }
681300
681378
  });
681301
681379
 
@@ -696502,6 +696580,7 @@ function getOpenApiSpec() {
696502
696580
  "/v1/media/migrate": { post: { summary: "Dedup + migrate legacy per-group media caches into the unified store — body {dryRun?, roots?, maxDepth?}", tags: ["Media"], responses: { 200: { description: "Migration report (bytes reclaimed/migrated)" }, 403: { description: "Insufficient scope" } } } },
696503
696581
  "/v1/media/relocate": { post: { summary: "Relocate the whole media store (weights/venvs/gallery) to a chosen folder — body {newRoot, dryRun?}; streams media.relocate_progress and returns 202 + job_id", tags: ["Media"], responses: { 200: { description: "Dry-run plan" }, 202: { description: "Relocation started" }, 400: { description: "Missing newRoot" }, 409: { description: "Relocation already running" } } } },
696504
696582
  "/v1/media/relocate/status": { get: { summary: "Status of the in-flight (or last) media-store relocation job", tags: ["Media"], responses: { 200: { description: "Relocation job status + progress" } } } },
696583
+ "/v1/media/av/analyze": { post: { summary: "Analyze a media file into a grounded entity/event/evidence answer (AV entity-comprehension) — body {path|mediaUri, question?}; reports per-role live-vs-mock adapter status", tags: ["Media"], responses: { 200: { description: "Grounded answer + entity/event graph" }, 400: { description: "Missing media path" }, 404: { description: "Media not found" } } } },
696505
696584
  "/v1/media/image": { post: { summary: "Generate an image — body {prompt, model?, backend?, width?, height?, steps?, guidance?, seed?, aspect_ratio?}", tags: ["Media"], responses: { 200: { description: "Generated image path + gallery URL" }, 400: { description: "Missing prompt" }, 403: { description: "Insufficient scope" }, 502: { description: "Generation failed" } } } },
696506
696585
  "/v1/media/video": { post: { summary: "Generate a video — body {prompt, model?, backend?, num_frames?, fps?, width?, height?, steps?, guidance?, seed?}", tags: ["Media"], responses: { 200: { description: "Generated video path + gallery URL" }, 400: { description: "Missing prompt" }, 403: { description: "Insufficient scope" }, 502: { description: "Generation failed" } } } },
696507
696586
  "/v1/media/audio": { post: { summary: "Generate a sound effect — body {prompt, model?, backend?, duration?, seed?}", tags: ["Media"], responses: { 200: { description: "Generated audio path + gallery URL" }, 400: { description: "Missing prompt" }, 403: { description: "Insufficient scope" }, 502: { description: "Generation failed" } } } },
@@ -201,6 +201,7 @@ All generation is backed by the unified `~/.omnius` model store and shared venvs
201
201
  | `POST` | `/v1/media/migrate` | Dedup + migrate legacy per-group caches into the unified store |
202
202
  | `POST` | `/v1/media/relocate` | Relocate the whole media store (weights/venvs/gallery) to a chosen folder |
203
203
  | `GET` | `/v1/media/relocate/status` | Status + progress of the media-store relocation job |
204
+ | `POST` | `/v1/media/av/analyze` | Analyze a media file into a grounded entity/event answer (AV comprehension) |
204
205
  | `POST` | `/v1/media/image` | Generate an image |
205
206
  | `POST` | `/v1/media/video` | Generate a video |
206
207
  | `POST` | `/v1/media/audio` | Generate a sound effect |
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.330",
3
+ "version": "1.0.331",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.330",
9
+ "version": "1.0.331",
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.330",
3
+ "version": "1.0.331",
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",