omnius 1.0.596 → 1.0.598

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.
@@ -1417,9 +1417,8 @@ var EpisodeStore = class {
1417
1417
  });
1418
1418
  scored.sort((a, b) => b.score - a.score);
1419
1419
  const topK = scored.slice(0, limit);
1420
- const updateStmt = this.db.prepare("UPDATE episodes SET strength = strength + 1, last_retrieved = ? WHERE id = ?");
1421
- for (const { episode } of topK) {
1422
- updateStmt.run(now, episode.id);
1420
+ if (opts.recordRetrieval !== false) {
1421
+ this.recordRetrieved(topK.map((item) => item.episode), now);
1423
1422
  }
1424
1423
  return topK.map((s) => s.episode);
1425
1424
  }
@@ -1427,30 +1426,105 @@ var EpisodeStore = class {
1427
1426
  * Falls back to standard search if graph is unavailable or no entities found.
1428
1427
  */
1429
1428
  searchWithPPR(query, opts = {}) {
1430
- const standardResults = this.search(query, opts);
1431
1429
  if (!this.graph || !query.query) {
1432
- return standardResults;
1430
+ return this.search(query, opts);
1433
1431
  }
1432
+ const standardResults = this.search(query, { ...opts, recordRetrieval: false });
1434
1433
  try {
1435
1434
  const pprResult = retrieveByPPR(query.query, this.graph, this, {
1436
1435
  damping: 0.5,
1437
1436
  maxIterations: 50,
1438
1437
  convergenceThreshold: 1e-6,
1439
- topK: query.limit ?? 20
1438
+ topK: query.limit ?? 20,
1439
+ currentEmotionalState: opts.currentEmotionalState,
1440
+ influenceFor: opts.influenceFor ? (episodeId) => {
1441
+ const episode = this.get(episodeId);
1442
+ return episode ? opts.influenceFor(episode) : null;
1443
+ } : void 0,
1444
+ engagementWeight: opts.engagementWeight
1440
1445
  });
1441
- const merged = [...standardResults];
1442
- const seenIds = new Set(merged.map((e) => e.id));
1443
- for (const { episode } of pprResult.episodes) {
1444
- if (!seenIds.has(episode.id)) {
1445
- merged.push(episode);
1446
- seenIds.add(episode.id);
1446
+ const candidates = /* @__PURE__ */ new Map();
1447
+ const addCandidate = (episode, rank, pprScore = 0) => {
1448
+ if (!this.matchesQueryFilters(episode, query))
1449
+ return;
1450
+ const contribution = 1 / (60 + rank + 1);
1451
+ const existing = candidates.get(episode.id);
1452
+ if (existing) {
1453
+ existing.score += contribution;
1454
+ existing.sourceCount += 1;
1455
+ existing.bestPprScore = Math.max(existing.bestPprScore, pprScore);
1456
+ } else {
1457
+ candidates.set(episode.id, {
1458
+ episode,
1459
+ score: contribution,
1460
+ sourceCount: 1,
1461
+ bestPprScore: pprScore
1462
+ });
1447
1463
  }
1448
- }
1449
- return merged.slice(0, query.limit ?? 20);
1464
+ };
1465
+ standardResults.forEach((episode, rank) => addCandidate(episode, rank));
1466
+ pprResult.episodes.forEach(({ episode, pprScore }, rank) => {
1467
+ addCandidate(episode, rank, pprScore);
1468
+ });
1469
+ const limit = query.limit ?? 20;
1470
+ const merged = [...candidates.values()].sort((a, b) => b.score - a.score || b.sourceCount - a.sourceCount || b.bestPprScore - a.bestPprScore || b.episode.timestamp - a.episode.timestamp || a.episode.id.localeCompare(b.episode.id)).slice(0, limit).map((candidate) => candidate.episode);
1471
+ if (opts.recordRetrieval !== false)
1472
+ this.recordRetrieved(merged, Date.now());
1473
+ return merged;
1450
1474
  } catch {
1475
+ if (opts.recordRetrieval !== false)
1476
+ this.recordRetrieved(standardResults, Date.now());
1451
1477
  return standardResults;
1452
1478
  }
1453
1479
  }
1480
+ /** Apply every non-text relevance constraint to a graph candidate. */
1481
+ matchesQueryFilters(episode, query) {
1482
+ if (query.sessionId && episode.sessionId !== query.sessionId)
1483
+ return false;
1484
+ if (query.taskId && episode.taskId !== query.taskId)
1485
+ return false;
1486
+ if (query.toolName && episode.toolName !== query.toolName)
1487
+ return false;
1488
+ if (query.modality && episode.modality !== query.modality)
1489
+ return false;
1490
+ if (query.since !== void 0 && episode.timestamp < query.since)
1491
+ return false;
1492
+ if (query.until !== void 0 && episode.timestamp > query.until)
1493
+ return false;
1494
+ if (query.minImportance !== void 0 && episode.importance < query.minImportance)
1495
+ return false;
1496
+ const metadata = episode.metadata;
1497
+ if (query.metadataFilter) {
1498
+ if (!metadata)
1499
+ return false;
1500
+ for (const [key, value] of Object.entries(query.metadataFilter)) {
1501
+ if (metadata[key] !== value)
1502
+ return false;
1503
+ }
1504
+ }
1505
+ if (query.soundClass && metadata?.["sound_class"] !== query.soundClass)
1506
+ return false;
1507
+ if (query.rmsRange) {
1508
+ const rms = metadata?.["rms_db"] ?? metadata?.["rmsDb"];
1509
+ if (typeof rms !== "number")
1510
+ return false;
1511
+ if (query.rmsRange.min !== void 0 && rms < query.rmsRange.min)
1512
+ return false;
1513
+ if (query.rmsRange.max !== void 0 && rms > query.rmsRange.max)
1514
+ return false;
1515
+ }
1516
+ return true;
1517
+ }
1518
+ recordRetrieved(episodes, timestamp) {
1519
+ if (episodes.length === 0)
1520
+ return;
1521
+ const updateStmt = this.db.prepare("UPDATE episodes SET strength = strength + 1, last_retrieved = ? WHERE id = ?");
1522
+ const updateAll = this.db.transaction(() => {
1523
+ for (const episode of episodes)
1524
+ updateStmt.run(timestamp, episode.id);
1525
+ });
1526
+ updateAll();
1527
+ }
1454
1528
  /** Get a single episode by ID. */
1455
1529
  get(id) {
1456
1530
  const row = this.db.prepare("SELECT * FROM episodes WHERE id = ?").get(id);
@@ -930,6 +930,11 @@ function main() {
930
930
  progress(4, INSTALL_STEPS, "Ensuring local REST key");
931
931
  ensureBootstrapApiKeyForUser(effectiveUser());
932
932
 
933
+ if (process.env.OMNIUS_UPDATE_COORDINATED === "1") {
934
+ log("Coordinated update owns daemon restart and exact-version verification.");
935
+ return safeExit(0);
936
+ }
937
+
933
938
  if (process.env.OMNIUS_SKIP_DAEMON_INSTALL === "1") {
934
939
  log("OMNIUS_SKIP_DAEMON_INSTALL=1 — skipping daemon service install.");
935
940
  return safeExit(0);
@@ -13,6 +13,14 @@
13
13
 
14
14
  "use strict";
15
15
 
16
+ // A coordinated self-update owns the exact PID/service lifecycle and verifies
17
+ // the replacement runtime afterward. The generic install hook must not race
18
+ // it by sweeping the configured port or killing an unattested process.
19
+ if (process.env.OMNIUS_UPDATE_COORDINATED === "1") {
20
+ process.stdout.write(" [preinstall] coordinated update owns daemon handoff\n");
21
+ process.exit(0);
22
+ }
23
+
16
24
  if (process.env.OMNIUS_SKIP_DAEMON_INSTALL === "1") {
17
25
  process.exit(0);
18
26
  }
@@ -7302,6 +7302,38 @@
7302
7302
  }
7303
7303
  ]
7304
7304
  },
7305
+ {
7306
+ "id": "command.indicator",
7307
+ "kind": "command",
7308
+ "title": "/indicator",
7309
+ "summary": "Report native system indicator readiness and daemon health",
7310
+ "aliases": [
7311
+ "/indicator",
7312
+ "indicator"
7313
+ ],
7314
+ "keywords": [
7315
+ "command",
7316
+ "tui",
7317
+ "indicator"
7318
+ ],
7319
+ "interfaces": [
7320
+ {
7321
+ "type": "tui",
7322
+ "target": "/indicator"
7323
+ },
7324
+ {
7325
+ "type": "rest",
7326
+ "target": "/v1/commands/indicator"
7327
+ }
7328
+ ],
7329
+ "references": [
7330
+ {
7331
+ "type": "source",
7332
+ "target": "packages/cli/src/tui/command-registry.ts",
7333
+ "relation": "registry"
7334
+ }
7335
+ ]
7336
+ },
7305
7337
  {
7306
7338
  "id": "command.ingest",
7307
7339
  "kind": "command",
@@ -9799,6 +9831,38 @@
9799
9831
  }
9800
9832
  ]
9801
9833
  },
9834
+ {
9835
+ "id": "command.tray",
9836
+ "kind": "command",
9837
+ "title": "/tray",
9838
+ "summary": "Alias for /indicator status",
9839
+ "aliases": [
9840
+ "/tray",
9841
+ "tray"
9842
+ ],
9843
+ "keywords": [
9844
+ "command",
9845
+ "tui",
9846
+ "tray"
9847
+ ],
9848
+ "interfaces": [
9849
+ {
9850
+ "type": "tui",
9851
+ "target": "/tray"
9852
+ },
9853
+ {
9854
+ "type": "rest",
9855
+ "target": "/v1/commands/tray"
9856
+ }
9857
+ ],
9858
+ "references": [
9859
+ {
9860
+ "type": "source",
9861
+ "target": "packages/cli/src/tui/command-registry.ts",
9862
+ "relation": "registry"
9863
+ }
9864
+ ]
9865
+ },
9802
9866
  {
9803
9867
  "id": "command.tree",
9804
9868
  "kind": "command",
package/docs/DISCOVERY.md CHANGED
@@ -232,6 +232,7 @@ Daemon equivalents are `GET /v1/discovery?q=<intent>` and `GET /v1/discovery/{id
232
232
  | `command.hf` | /hf | Cancel any pending HF token prompt and fall back immediately |
233
233
  | `command.host` | /host | Set bind host:port (OMNIUS_HOST) and restart daemon |
234
234
  | `command.image` | /image | List image models by category, quality, size, and hardware fit |
235
+ | `command.indicator` | /indicator | Report native system indicator readiness and daemon health |
235
236
  | `command.ingest` | /ingest | Ingest an audio, PDF, or text file into memory |
236
237
  | `command.init` | Initialize agent discovery guidance | Create or update managed Omnius discovery blocks in project guidance while preserving user content. |
237
238
  | `command.insights` | /insights | Show historical session insights |
@@ -310,6 +311,7 @@ Daemon equivalents are `GET /v1/discovery?q=<intent>` and `GET /v1/discovery/{id
310
311
  | `command.tools` | /tools | List agent-created custom tools |
311
312
  | `command.toolsets` | /toolsets | Show or select tool exposure sets |
312
313
  | `command.transcribe` | /transcribe | Alias for /ingest &lt;file&gt; |
314
+ | `command.tray` | /tray | Alias for /indicator status |
313
315
  | `command.tree` | /tree | Show, hide, or inspect the action-tree presentation |
314
316
  | `command.undo` | /undo | Undo the last queued or saved exchange when available |
315
317
  | `command.update` | /update | Run full non-interactive update: package, deps, rebuild, Python, cloudflared |
@@ -14,6 +14,17 @@ omnius tray stop # stop only the indicator
14
14
  omnius tray uninstall # stop it and remove login startup
15
15
  ```
16
16
 
17
+ From an active Omnius TUI, use the local slash command instead:
18
+
19
+ ```text
20
+ /indicator # start and report readiness
21
+ /indicator status # inspect without starting
22
+ ```
23
+
24
+ `/tray` is retained as an alias. Login registration and the full
25
+ start/stop/restart lifecycle remain available through the top-level
26
+ `omnius tray` command.
27
+
17
28
  The indicator polls the daemon's loopback-only `GET /health` route. It does not
18
29
  load a model or contact the configured inference backend. If the daemon uses a
19
30
  non-default port, Omnius discovers `OMNIUS_HOST`/`OMNIUS_PORT` from the current
@@ -82,4 +93,3 @@ tail -f ~/.local/state/omnius/tray.err.log # Linux default
82
93
  with `--endpoint`; avoid `0.0.0.0` in client URLs.
83
94
  - **No graphical session:** run `omnius tray start` from the logged-in desktop
84
95
  session so `DISPLAY`/`WAYLAND_DISPLAY` and the session D-Bus address exist.
85
-
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.596",
3
+ "version": "1.0.598",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.596",
9
+ "version": "1.0.598",
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.596",
3
+ "version": "1.0.598",
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/library.js",