omnius 1.0.63 → 1.0.65

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
@@ -613237,6 +613237,108 @@ ${lines.join("\n")}`);
613237
613237
  return `- ${when} ${speaker}${mode}${messageId}: ${telegramContextJsonString(text, maxText)}`;
613238
613238
  }).join("\n");
613239
613239
  }
613240
+ /**
613241
+ * Build an always-on "memory substrate census" injected into every Telegram
613242
+ * prompt. Anchors the agent against false-empty responses: lists counts for
613243
+ * each store + the chat-scoped memory_read topic filenames that exist on disk.
613244
+ *
613245
+ * Without this, when the lexical scorers (cards/facts/episodes) score zero
613246
+ * for the current query, NO section about those stores reaches the prompt,
613247
+ * and the bot will report "memory empty" in good faith. This section keeps
613248
+ * the substrate visible regardless of per-turn scoring.
613249
+ */
613250
+ buildTelegramMemorySubstrateCensus(sessionKey, msg) {
613251
+ const cardCount = (this.chatMemoryCards.get(sessionKey) ?? []).length;
613252
+ const memory = this.chatAssociativeMemory.get(sessionKey);
613253
+ const factCount = memory?.facts.length ?? 0;
613254
+ const relationshipCount = memory?.relationships.length ?? 0;
613255
+ const userMemoryCount = memory ? Object.keys(memory.users).length : 0;
613256
+ const historyCount = (this.chatHistory.get(sessionKey) ?? []).length;
613257
+ let sqliteCount = 0;
613258
+ let episodeCount2 = 0;
613259
+ try {
613260
+ const db = this.telegramDb();
613261
+ if (db) {
613262
+ const row = db.prepare("SELECT COUNT(*) AS n FROM telegram_messages WHERE session_key = ?").get(sessionKey);
613263
+ sqliteCount = Number(row?.n) || 0;
613264
+ }
613265
+ } catch {
613266
+ }
613267
+ if (this.repoRoot) {
613268
+ try {
613269
+ const paths = omniusMemoryDbPaths(this.repoRoot);
613270
+ if (existsSync113(paths.episodes)) {
613271
+ const graph = new TemporalGraph(paths.knowledge);
613272
+ const store2 = new EpisodeStore(paths.episodes, graph);
613273
+ try {
613274
+ const sample = store2.search({ sessionId: sessionKey, limit: 1 }) ?? [];
613275
+ if (sample.length > 0) {
613276
+ const dbAny = store2.db;
613277
+ if (dbAny && typeof dbAny.prepare === "function") {
613278
+ const row = dbAny.prepare("SELECT COUNT(*) AS n FROM episodes WHERE session_id = ?").get(sessionKey);
613279
+ episodeCount2 = Number(row?.n) || 0;
613280
+ } else {
613281
+ episodeCount2 = 1;
613282
+ }
613283
+ }
613284
+ } finally {
613285
+ try {
613286
+ store2.close();
613287
+ } catch {
613288
+ }
613289
+ try {
613290
+ graph.close();
613291
+ } catch {
613292
+ }
613293
+ }
613294
+ }
613295
+ } catch {
613296
+ }
613297
+ }
613298
+ const chatId = msg.chatId;
613299
+ const topicFiles = [];
613300
+ if (this.repoRoot && chatId !== void 0) {
613301
+ try {
613302
+ const memDir = resolve43(this.repoRoot, ".omnius", "memory");
613303
+ if (existsSync113(memDir)) {
613304
+ const prefix = this.telegramScopedMemoryPrefix(chatId);
613305
+ for (const file of readdirSync40(memDir)) {
613306
+ if (!file.endsWith(".json") || !file.startsWith(prefix)) continue;
613307
+ const topic = file.slice(prefix.length, -".json".length);
613308
+ if (topic) topicFiles.push(topic);
613309
+ }
613310
+ }
613311
+ } catch {
613312
+ }
613313
+ }
613314
+ const anyMemory = cardCount + factCount + relationshipCount + userMemoryCount + sqliteCount + episodeCount2 + topicFiles.length > 0;
613315
+ if (!anyMemory && historyCount === 0) return "";
613316
+ const lines = [
613317
+ "### Scoped Memory Substrate (this chat — ALWAYS PRESENT)",
613318
+ "Persistent memory IS available for this chat. The current turn's lexical scorers may",
613319
+ "have surfaced 0 matches above — that does NOT mean the substrate is empty. Counts:",
613320
+ `- Memory cards: ${cardCount}`,
613321
+ `- Associative facts: ${factCount}`,
613322
+ `- Associative relationships: ${relationshipCount}`,
613323
+ `- Per-user memories: ${userMemoryCount}`,
613324
+ `- Rolling history entries retained: ${historyCount}`,
613325
+ `- SQLite mirror rows: ${sqliteCount}`,
613326
+ `- Episodes (durable, day+ scope): ${episodeCount2}`
613327
+ ];
613328
+ if (topicFiles.length > 0) {
613329
+ lines.push("");
613330
+ lines.push("Per-topic memory files (call memory_read with one of these `topic` values):");
613331
+ for (const topic of topicFiles.slice(0, 80)) {
613332
+ lines.push(` - ${topic}`);
613333
+ }
613334
+ }
613335
+ lines.push("");
613336
+ lines.push("RULES:");
613337
+ lines.push(" 1. NEVER 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.");
613338
+ 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.");
613339
+ 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.");
613340
+ return lines.join("\n");
613341
+ }
613240
613342
  buildTelegramConversationContextStream(sessionKey, msg, maxRecent = TELEGRAM_CONTEXT_RECENT_DEFAULT) {
613241
613343
  this.ensureTelegramConversationLoaded(sessionKey);
613242
613344
  const history = this.chatHistory.get(sessionKey) ?? [];
@@ -613260,6 +613362,11 @@ ${lines.join("\n")}`);
613260
613362
  if (currentReplyContext) {
613261
613363
  sections.push(currentReplyContext);
613262
613364
  }
613365
+ try {
613366
+ const substrateCensus = this.buildTelegramMemorySubstrateCensus(sessionKey, msg);
613367
+ if (substrateCensus) sections.push(substrateCensus);
613368
+ } catch {
613369
+ }
613263
613370
  const scopedPersonality = this.renderTelegramScopedPersonality(sessionKey, msg);
613264
613371
  if (scopedPersonality) {
613265
613372
  sections.push(scopedPersonality);
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.63",
3
+ "version": "1.0.65",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.63",
9
+ "version": "1.0.65",
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.63",
3
+ "version": "1.0.65",
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",