omnius 1.0.137 → 1.0.138

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
@@ -623811,214 +623811,29 @@ ${lines.join("\n")}`);
623811
623811
  const cardCount = (this.chatMemoryCards.get(sessionKey) ?? []).length;
623812
623812
  const memory = this.chatAssociativeMemory.get(sessionKey);
623813
623813
  const factCount = memory?.facts.length ?? 0;
623814
- const relationshipCount = memory?.relationships.length ?? 0;
623815
623814
  const userMemoryCount = memory ? Object.keys(memory.users).length : 0;
623816
623815
  const historyCount = (this.chatHistory.get(sessionKey) ?? []).length;
623817
- let sqliteCount = 0;
623818
- let episodeCount2 = 0;
623819
- try {
623820
- const db = this.telegramDb();
623821
- if (db) {
623822
- const row = db.prepare("SELECT COUNT(*) AS n FROM telegram_messages WHERE session_key = ?").get(sessionKey);
623823
- sqliteCount = Number(row?.n) || 0;
623824
- }
623825
- } catch {
623826
- }
623827
- if (this.repoRoot) {
623828
- try {
623829
- const paths = omniusMemoryDbPaths(this.repoRoot);
623830
- if (existsSync117(paths.episodes)) {
623831
- const graph = new TemporalGraph(paths.knowledge);
623832
- const store2 = new EpisodeStore(paths.episodes, graph);
623833
- try {
623834
- const sample = store2.search({ sessionId: sessionKey, limit: 1 }) ?? [];
623835
- if (sample.length > 0) {
623836
- const dbAny = store2.db;
623837
- if (dbAny && typeof dbAny.prepare === "function") {
623838
- const row = dbAny.prepare("SELECT COUNT(*) AS n FROM episodes WHERE session_id = ?").get(sessionKey);
623839
- episodeCount2 = Number(row?.n) || 0;
623840
- } else {
623841
- episodeCount2 = 1;
623842
- }
623843
- }
623844
- } finally {
623845
- try {
623846
- store2.close();
623847
- } catch {
623848
- }
623849
- try {
623850
- graph.close();
623851
- } catch {
623852
- }
623853
- }
623854
- }
623855
- } catch {
623856
- }
623857
- }
623858
623816
  const chatId = msg.chatId;
623859
- const topicFiles = [];
623817
+ let topicCount = 0;
623860
623818
  if (this.repoRoot && chatId !== void 0) {
623861
623819
  try {
623862
623820
  const memDir = resolve46(this.repoRoot, ".omnius", "memory");
623863
623821
  if (existsSync117(memDir)) {
623864
623822
  const prefix = this.telegramScopedMemoryPrefix(chatId);
623865
623823
  for (const file of readdirSync41(memDir)) {
623866
- if (!file.endsWith(".json") || !file.startsWith(prefix)) continue;
623867
- const topic = file.slice(prefix.length, -".json".length);
623868
- if (topic) topicFiles.push(topic);
623824
+ if (file.endsWith(".json") && file.startsWith(prefix)) topicCount++;
623869
623825
  }
623870
623826
  }
623871
623827
  } catch {
623872
623828
  }
623873
623829
  }
623874
- const anyMemory = cardCount + factCount + relationshipCount + userMemoryCount + sqliteCount + episodeCount2 + topicFiles.length > 0;
623875
- if (!anyMemory && historyCount === 0) return "";
623876
- const lines = [
623877
- "### Scoped Memory Substrate (this chat - always present)",
623878
- "Persistent memory is available for this chat. The current turn's lexical scorers may",
623879
- "have surfaced 0 matches above - that does not mean the substrate is empty. Counts:",
623880
- `- Memory cards: ${cardCount}`,
623881
- `- Associative facts: ${factCount}`,
623882
- `- Associative relationships: ${relationshipCount}`,
623883
- `- Per-user memories: ${userMemoryCount}`,
623884
- `- Rolling history entries retained: ${historyCount}`,
623885
- `- Addressable conversation history rows: ${Math.max(historyCount, sqliteCount)}`,
623886
- `- SQLite mirror rows: ${sqliteCount}`,
623887
- `- Episodes (durable, day+ scope): ${episodeCount2}`
623888
- ];
623889
- if (topicFiles.length > 0) {
623890
- lines.push("");
623891
- lines.push("Per-topic memory files (call memory_read with one of these `topic` values):");
623892
- for (const topic of topicFiles.slice(0, 80)) {
623893
- lines.push(` - ${topic}`);
623894
- }
623895
- }
623896
- const anchors = this.telegramHistoryAnchorsForSession(sessionKey, 3);
623897
- const fmtHistoryAnchor = (entry) => {
623898
- const when = entry.ts ? new Date(entry.ts).toISOString() : "(unknown ts)";
623899
- const speaker = telegramHistorySpeaker(entry);
623900
- const kind = entry.role === "assistant" || entry.isBot ? "bot" : "human";
623901
- const mode = entry.mode ? `/${entry.mode}` : "";
623902
- const messageId = entry.messageId ? ` msg:${entry.messageId}` : "";
623903
- return `${when} ${speaker} [${kind}]${mode}${messageId}: ${telegramContextJsonString(String(entry.text || ""), 320)}`;
623904
- };
623905
- const sameHistoryAnchor = (a2, b) => {
623906
- if (!a2 || !b) return false;
623907
- if (a2.messageId !== void 0 && b.messageId !== void 0) return a2.messageId === b.messageId && a2.role === b.role;
623908
- return a2.ts === b.ts && a2.role === b.role && a2.text === b.text;
623909
- };
623910
- if (anchors.earliest.length > 0 || anchors.latest) {
623911
- lines.push("");
623912
- lines.push("Chronological anchors - Telegram conversation history (SQLite mirror preferred; ground truth for 'oldest/newest memory' questions):");
623913
- if (anchors.earliest[0]) lines.push(` Earliest turn: ${fmtHistoryAnchor(anchors.earliest[0])}`);
623914
- if (anchors.latest && !sameHistoryAnchor(anchors.earliest[0], anchors.latest)) {
623915
- lines.push(` Latest turn: ${fmtHistoryAnchor(anchors.latest)}`);
623916
- }
623917
- if (anchors.earliest[1]) {
623918
- lines.push(` 2nd earliest: ${fmtHistoryAnchor(anchors.earliest[1])}`);
623919
- }
623920
- if (anchors.earliest[2]) {
623921
- lines.push(` 3rd earliest: ${fmtHistoryAnchor(anchors.earliest[2])}`);
623922
- }
623923
- }
623924
- const activityStats = this.telegramParticipantActivityStats(sessionKey, { limit: 8 });
623925
- if (activityStats.length > 0) {
623926
- lines.push("");
623927
- lines.push("Activity anchors - participant message counts from the durable mirror/merged history:");
623928
- for (const stat7 of activityStats) {
623929
- const first2 = stat7.firstTs ? new Date(stat7.firstTs).toISOString() : "?";
623930
- const last2 = stat7.lastTs ? new Date(stat7.lastTs).toISOString() : "?";
623931
- lines.push(` - ${stat7.speaker}: ${stat7.count} message${stat7.count === 1 ? "" : "s"} (first:${first2}, last:${last2})`);
623932
- }
623933
- }
623934
- if (this.repoRoot) {
623935
- try {
623936
- const paths = omniusMemoryDbPaths(this.repoRoot);
623937
- if (existsSync117(paths.episodes)) {
623938
- const graph = new TemporalGraph(paths.knowledge);
623939
- const store2 = new EpisodeStore(paths.episodes, graph);
623940
- try {
623941
- const dbAny = store2.db;
623942
- if (dbAny && typeof dbAny.prepare === "function") {
623943
- const earliest = dbAny.prepare(
623944
- "SELECT timestamp, modality, tool_name, content, gist FROM episodes WHERE session_id = ? ORDER BY timestamp ASC LIMIT 1"
623945
- ).get(sessionKey);
623946
- const latest = dbAny.prepare(
623947
- "SELECT timestamp, modality, tool_name, content, gist FROM episodes WHERE session_id = ? ORDER BY timestamp DESC LIMIT 1"
623948
- ).get(sessionKey);
623949
- if (earliest || latest) {
623950
- lines.push("");
623951
- lines.push("Chronological anchors - episodes.db (durable, may reach further back than rolling history):");
623952
- const fmtEp = (row) => {
623953
- const when = row.timestamp ? new Date(row.timestamp).toISOString() : "(unknown ts)";
623954
- const tag = `[${row.modality || "?"}${row.tool_name ? ":" + row.tool_name : ""}]`;
623955
- const text = (row.gist || row.content || "").split("\n").filter((ln) => !/^(Telegram|session:|chat:|message_id:|thread_id:|speaker:|mode:)/i.test(ln.trim())).join(" ").replace(/\s+/g, " ").trim();
623956
- return `${when} ${tag} ${telegramContextJsonString(text, 320)}`;
623957
- };
623958
- if (earliest) lines.push(` Earliest episode: ${fmtEp(earliest)}`);
623959
- if (latest && (!earliest || earliest.timestamp !== latest.timestamp)) lines.push(` Latest episode: ${fmtEp(latest)}`);
623960
- }
623961
- }
623962
- } finally {
623963
- try {
623964
- store2.close();
623965
- } catch {
623966
- }
623967
- try {
623968
- graph.close();
623969
- } catch {
623970
- }
623971
- }
623972
- }
623973
- } catch {
623974
- }
623975
- }
623976
- if (this.repoRoot && chatId !== void 0 && topicFiles.length > 0) {
623977
- try {
623978
- const memDir = resolve46(this.repoRoot, ".omnius", "memory");
623979
- const prefix = this.telegramScopedMemoryPrefix(chatId);
623980
- let earliestEntry = null;
623981
- let latestEntry = null;
623982
- for (const topic of topicFiles) {
623983
- const file = join131(memDir, `${prefix}${topic}.json`);
623984
- if (!existsSync117(file)) continue;
623985
- let parsed;
623986
- try {
623987
- parsed = JSON.parse(readFileSync96(file, "utf8"));
623988
- } catch {
623989
- continue;
623990
- }
623991
- for (const [key, entry] of Object.entries(parsed)) {
623992
- if (!entry || typeof entry !== "object") continue;
623993
- const rawTs = entry.timestamp;
623994
- const ts = typeof rawTs === "string" ? Date.parse(rawTs) : typeof rawTs === "number" ? rawTs : NaN;
623995
- if (!Number.isFinite(ts)) continue;
623996
- const value2 = String(entry.value ?? "");
623997
- if (!earliestEntry || ts < earliestEntry.ts) earliestEntry = { topic, key, value: value2, ts };
623998
- if (!latestEntry || ts > latestEntry.ts) latestEntry = { topic, key, value: value2, ts };
623999
- }
624000
- }
624001
- if (earliestEntry || latestEntry) {
624002
- lines.push("");
624003
- lines.push("Chronological anchors - memory_write entries (most-trusted, agent-asserted):");
624004
- const fmtMem = (e2) => {
624005
- const when = new Date(e2.ts).toISOString();
624006
- return `${when} topic="${e2.topic}" key="${e2.key}" → ${telegramContextJsonString(e2.value, 320)}`;
624007
- };
624008
- if (earliestEntry) lines.push(` Earliest memory_write: ${fmtMem(earliestEntry)}`);
624009
- if (latestEntry && (!earliestEntry || earliestEntry.ts !== latestEntry.ts)) lines.push(` Latest memory_write: ${fmtMem(latestEntry)}`);
624010
- }
624011
- } catch {
624012
- }
624013
- }
624014
- lines.push("");
624015
- lines.push("Rules:");
624016
- lines.push(" 1. Do not tell the user 'memory is empty' or 'nothing has been stored' for this chat without first calling memory_search and memory_read on a relevant topic from the list above.");
624017
- lines.push(" 2. If the structured sections (cards/facts/sqlite/episodes) above did not surface what the user asked about, that is a scoring miss, not absence. Call memory_search with broader tokens or pick a topic above with memory_read.");
624018
- lines.push(" 3. The rolling-history block is base context; the cards/facts/episodes are retrieval-augmented. Treat them as the same memory, surfaced different ways.");
624019
- lines.push(" 4. For 'what is your oldest/earliest memory' or 'most recent memory' questions: answer directly from the 'Chronological anchors' lines above. Quote the timestamp and content. Do not call tools first and do not report 'empty'.");
624020
- lines.push(" 5. memory_search accepts natural-language time phrases inside the `query` argument or explicit `since`/`until`/`bucket` args. Examples: query='what did manitcor say yesterday', query='last 3 hours', query='earlier today', query='2 days ago', query='since 2026-05-15', query='between 2026-05-15 and 2026-05-16', query='oldest memory about github', query='most recent flux discussion'. Use these for chronological/'how far back' style queries instead of guessing - the tool parses the phrase, filters by time, and returns the right window.");
624021
- return lines.join("\n");
623830
+ const hasMemory = cardCount + factCount + userMemoryCount + topicCount > 0 || historyCount > 0;
623831
+ if (!hasMemory) return "";
623832
+ return [
623833
+ "### Memory Substrate (this chat)",
623834
+ `Available: ${cardCount} cards, ${factCount} facts, ${userMemoryCount} per-user memories, ${historyCount} rolling-history msgs, ${topicCount} memory_read topics.`,
623835
+ "Recall via memory_search (semantic similarity / graph traversal / episodes). For exact reads: memory_read(topic, key). The substrate is associative — recall is by cue, not by date."
623836
+ ].join("\n");
624022
623837
  }
624023
623838
  buildTelegramConversationContextStream(sessionKey, msg, maxRecent = TELEGRAM_CONTEXT_RECENT_DEFAULT, salienceSignals = []) {
624024
623839
  this.ensureTelegramConversationLoaded(sessionKey);
@@ -625546,7 +625361,7 @@ ${list}` : "No shared group target is currently known for this sender. Ask in th
625546
625361
  return [
625547
625362
  "## Admin Telegram Omniscience (index only)",
625548
625363
  "One-way context for the authenticated admin private DM. Other Telegram sessions the bot has observed are listed below with one line each.",
625549
- "For details on a specific chat, use telegram_memory_search with the chat_id or topic — the always-loaded view is intentionally compact.",
625364
+ "For details on a specific chat, use memory_search (mode=episodes) with a topic keyword or chat_id — the always-loaded view is intentionally compact.",
625550
625365
  "Never inject admin/private DM content into public groups.",
625551
625366
  indexLines.join("\n")
625552
625367
  ].join("\n\n");
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.137",
3
+ "version": "1.0.138",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.137",
9
+ "version": "1.0.138",
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.137",
3
+ "version": "1.0.138",
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",