@yugenlab/vaayu 0.1.11 → 0.1.12

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.
Files changed (50) hide show
  1. package/chunks/{agentic-tool-loop-O3NUV7KG.js → agentic-tool-loop-NQESOBLC.js} +2 -2
  2. package/chunks/akasha-5C5Q6NMP.js +12 -0
  3. package/chunks/{chunk-7XV5ISV7.js → chunk-26K6DS6N.js} +2 -2
  4. package/chunks/chunk-5E3ZS5SW.js +529 -0
  5. package/chunks/{chunk-D46QTN3G.js → chunk-ARZCIITZ.js} +47 -18
  6. package/chunks/{chunk-ZYY6N3SP.js → chunk-FEDPZOZ5.js} +548 -389
  7. package/chunks/{chunk-3AYSJ7WB.js → chunk-GWYC7R2L.js} +13 -7
  8. package/chunks/chunk-H46F2Y6R.js +134 -0
  9. package/chunks/{chunk-QV4GPIPT.js → chunk-HXHDP2PZ.js} +8 -4
  10. package/chunks/chunk-KVQH4LE7.js +396 -0
  11. package/chunks/{chunk-Z576WVLG.js → chunk-LJCT7UYP.js} +17 -7
  12. package/chunks/{chunk-LJUEMPLG.js → chunk-M2RLX5LU.js} +32 -14
  13. package/chunks/{chunk-IGKYKEKT.js → chunk-NAQKA54E.js} +8 -2
  14. package/chunks/{chunk-F6RNEGFX.js → chunk-PZ4AQ22L.js} +78 -13
  15. package/chunks/{chunk-G2QREGXK.js → chunk-R273KC7J.js} +275 -2
  16. package/chunks/{chunk-A3HOZBC5.js → chunk-RVKTGKFD.js} +2 -2
  17. package/chunks/{chunk-VCUJES75.js → chunk-TSOQ2CT3.js} +763 -620
  18. package/chunks/{chunk-V2ZIKDN4.js → chunk-VEZ2DI2M.js} +16 -5
  19. package/chunks/{chunk-W4PVGBUH.js → chunk-XP3NIH5F.js} +7 -3
  20. package/chunks/{chunk-7AYYXHYZ.js → chunk-Y6IZH6FT.js} +19 -4
  21. package/chunks/{chunk-JZTFJE7M.js → chunk-YRTGGYJU.js} +14 -10
  22. package/chunks/{consolidation-indexer-VIWOP6VO.js → consolidation-indexer-KPXORCJ4.js} +9 -9
  23. package/chunks/database-BX3LVYXS.js +11 -0
  24. package/chunks/{day-consolidation-HMHSXIOM.js → day-consolidation-CR3TJFAL.js} +5 -5
  25. package/chunks/{dist-CY5NX2IK.js → dist-ESCM3CP5.js} +31 -21
  26. package/chunks/graphrag-73XA7LBX.js +14 -0
  27. package/chunks/hierarchical-temporal-search-GHKVKNZ6.js +8 -0
  28. package/chunks/hybrid-search-OD756RDV.js +20 -0
  29. package/chunks/{memory-store-LEERUQGL.js → memory-store-4GCBR2DZ.js} +4 -4
  30. package/chunks/periodic-consolidation-IINCHP6L.js +11 -0
  31. package/chunks/{postgres-7GZDDX77.js → postgres-YLCUNVPQ.js} +2 -2
  32. package/chunks/recall-64RROTUC.js +21 -0
  33. package/chunks/search-JVCDNTAJ.js +19 -0
  34. package/chunks/{session-store-O3TS7DUY.js → session-store-3EDQZEDS.js} +12 -6
  35. package/chunks/{sqlite-7BC4DJTN.js → sqlite-4N7YH2KK.js} +2 -2
  36. package/chunks/{src-6GVZTUH6.js → src-OPSDZEFI.js} +2 -2
  37. package/chunks/{suncalc-NOHGYHDU.js → suncalc-RM7URNUR.js} +2 -2
  38. package/chunks/{tree-RSHKDTCR.js → tree-FIUVGJ5J.js} +2 -2
  39. package/chunks/{vasana-engine-BJFHJVGM.js → vasana-engine-W4PYWT5H.js} +5 -5
  40. package/gateway.js +2358 -768
  41. package/package.json +1 -1
  42. package/pair-cli.js +2 -2
  43. package/chunks/chunk-2OBLQJYJ.js +0 -198
  44. package/chunks/chunk-67DXWEKG.js +0 -123
  45. package/chunks/graphrag-T2QWNX57.js +0 -14
  46. package/chunks/hierarchical-temporal-search-U6DG74IR.js +0 -8
  47. package/chunks/hybrid-search-BYTXCOXP.js +0 -20
  48. package/chunks/periodic-consolidation-D6SSKZ7H.js +0 -11
  49. package/chunks/recall-LNRQVATQ.js +0 -21
  50. package/chunks/search-BIODUW2P.js +0 -19
@@ -6,16 +6,19 @@ import {
6
6
  STOP_WORDS,
7
7
  cosineSimilarity,
8
8
  textMatchScore
9
- } from "./chunk-A3HOZBC5.js";
9
+ } from "./chunk-RVKTGKFD.js";
10
10
  import {
11
- initGraphSchema
12
- } from "./chunk-V2ZIKDN4.js";
11
+ initGraphSchema,
12
+ init_schema
13
+ } from "./chunk-VEZ2DI2M.js";
13
14
  import {
14
- DatabaseManager
15
- } from "./chunk-67DXWEKG.js";
15
+ DatabaseManager,
16
+ init_database
17
+ } from "./chunk-H46F2Y6R.js";
16
18
  import {
17
- getChitraguptaHome
18
- } from "./chunk-2OBLQJYJ.js";
19
+ getChitraguptaHome,
20
+ init_dist
21
+ } from "./chunk-KVQH4LE7.js";
19
22
 
20
23
  // ../chitragupta/packages/smriti/dist/graphrag-pagerank.js
21
24
  var PAGERANK_DAMPING = 0.85;
@@ -1492,6 +1495,9 @@ function findBridgeNodes(graph, result, minCommunities = 2) {
1492
1495
  }
1493
1496
 
1494
1497
  // ../chitragupta/packages/smriti/dist/graphrag-persistence.js
1498
+ init_dist();
1499
+ init_database();
1500
+ init_schema();
1495
1501
  import fs from "fs";
1496
1502
  import path from "path";
1497
1503
  function getGraphDir() {
@@ -1827,7 +1833,9 @@ var GraphRAGEngine = class {
1827
1833
  if (isAvailable) {
1828
1834
  try {
1829
1835
  baseEntities = await llmExtractEntities(text, this.config.endpoint, this.config.generationModel);
1830
- } catch {
1836
+ } catch (err) {
1837
+ process.stderr.write(`[smriti:graphrag] LLM entity extraction failed, falling back to keywords: ${err instanceof Error ? err.message : String(err)}
1838
+ `);
1831
1839
  baseEntities = keywordExtractEntities(text);
1832
1840
  }
1833
1841
  } else {
@@ -1860,7 +1868,9 @@ var GraphRAGEngine = class {
1860
1868
  seen.add(normalized);
1861
1869
  }
1862
1870
  }
1863
- } catch {
1871
+ } catch (err) {
1872
+ process.stderr.write(`[smriti:graphrag] NER extraction failed: ${err instanceof Error ? err.message : String(err)}
1873
+ `);
1864
1874
  }
1865
1875
  return baseEntities;
1866
1876
  }
@@ -2019,7 +2029,9 @@ var GraphRAGEngine = class {
2019
2029
  saveToSqlite(db, this.graph, this.pageRankScores, this.embeddingCache);
2020
2030
  return;
2021
2031
  }
2022
- } catch {
2032
+ } catch (err) {
2033
+ process.stderr.write(`[smriti:graphrag] SQLite save failed, falling back to JSON: ${err instanceof Error ? err.message : String(err)}
2034
+ `);
2023
2035
  }
2024
2036
  saveToJson(this.graph, this.pageRankScores, this.embeddingCache);
2025
2037
  }
@@ -2040,13 +2052,17 @@ var GraphRAGEngine = class {
2040
2052
  if (this.graph.nodes.length > 0) {
2041
2053
  try {
2042
2054
  migrateInMemoryToSqlite(db, this.graph, this.pageRankScores);
2043
- } catch {
2055
+ } catch (err) {
2056
+ process.stderr.write(`[smriti:graphrag] in-memory to SQLite migration failed: ${err instanceof Error ? err.message : String(err)}
2057
+ `);
2044
2058
  }
2045
2059
  }
2046
2060
  }
2047
2061
  loaded = true;
2048
2062
  }
2049
- } catch {
2063
+ } catch (err) {
2064
+ process.stderr.write(`[smriti:graphrag] SQLite load failed: ${err instanceof Error ? err.message : String(err)}
2065
+ `);
2050
2066
  }
2051
2067
  if (!loaded) {
2052
2068
  const jsonData = loadFromJson();
@@ -2073,7 +2089,9 @@ var GraphRAGEngine = class {
2073
2089
  const db = this.getGraphDbHandle();
2074
2090
  if (db)
2075
2091
  db.exec("DELETE FROM pagerank; DELETE FROM edges; DELETE FROM nodes;");
2076
- } catch {
2092
+ } catch (err) {
2093
+ process.stderr.write(`[smriti:graphrag] clear DB failed: ${err instanceof Error ? err.message : String(err)}
2094
+ `);
2077
2095
  }
2078
2096
  this.saveToDisk();
2079
2097
  }
@@ -2116,4 +2134,4 @@ export {
2116
2134
  migrateGraphJson,
2117
2135
  GraphRAGEngine
2118
2136
  };
2119
- //# sourceMappingURL=chunk-LJUEMPLG.js.map
2137
+ //# sourceMappingURL=chunk-M2RLX5LU.js.map
@@ -10,6 +10,9 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
10
10
  if (typeof require !== "undefined") return require.apply(this, arguments);
11
11
  throw Error('Dynamic require of "' + x + '" is not supported');
12
12
  });
13
+ var __esm = (fn, res) => function __init() {
14
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
15
+ };
13
16
  var __commonJS = (cb, mod) => function __require2() {
14
17
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
15
18
  };
@@ -33,11 +36,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
33
36
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
37
  mod
35
38
  ));
39
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
36
40
 
37
41
  export {
38
42
  __require,
43
+ __esm,
39
44
  __commonJS,
40
45
  __export,
41
- __toESM
46
+ __toESM,
47
+ __toCommonJS
42
48
  };
43
- //# sourceMappingURL=chunk-IGKYKEKT.js.map
49
+ //# sourceMappingURL=chunk-NAQKA54E.js.map
@@ -2,13 +2,15 @@ import {
2
2
  EmbeddingService,
3
3
  cosineSimilarity,
4
4
  fallbackEmbedding
5
- } from "./chunk-A3HOZBC5.js";
5
+ } from "./chunk-RVKTGKFD.js";
6
6
  import {
7
7
  SessionError,
8
- getChitraguptaHome
9
- } from "./chunk-2OBLQJYJ.js";
8
+ getChitraguptaHome,
9
+ init_dist
10
+ } from "./chunk-KVQH4LE7.js";
10
11
 
11
12
  // ../chitragupta/packages/smriti/dist/day-consolidation.js
13
+ init_dist();
12
14
  import fs2 from "fs";
13
15
  import path2 from "path";
14
16
 
@@ -558,6 +560,8 @@ var FactExtractor = class {
558
560
  * Uses pattern matching first, then vector similarity for misses.
559
561
  */
560
562
  async extract(text) {
563
+ if (!shouldAnalyzeForFacts(text))
564
+ return [];
561
565
  await this.ensureInitialized();
562
566
  const facts = [];
563
567
  if (text.length < 5 || text.length > 5e3)
@@ -580,7 +584,7 @@ var FactExtractor = class {
580
584
  }
581
585
  }
582
586
  }
583
- if (this.config.useVectors && facts.length === 0) {
587
+ if (this.config.useVectors && facts.length === 0 && shouldUseVectorFallback(text)) {
584
588
  const inputEmbedding = fallbackEmbedding(text.toLowerCase().slice(0, 200));
585
589
  let bestScore = 0;
586
590
  let bestTemplate = null;
@@ -623,20 +627,22 @@ var FactExtractor = class {
623
627
  const facts = await this.extract(text);
624
628
  if (facts.length === 0)
625
629
  return [];
626
- const { appendMemory, getMemory } = await import("./memory-store-LEERUQGL.js");
630
+ const { appendMemory, getMemory } = await import("./memory-store-4GCBR2DZ.js");
627
631
  const globalScope = scope ?? { type: "global" };
628
632
  const existingMemory = getMemory(globalScope).toLowerCase();
633
+ const projectMemory = projectScope && projectScope.type !== "session" ? getMemory(projectScope).toLowerCase() : "";
629
634
  for (const fact of facts) {
630
635
  const dedupeKey = `${fact.category}:${fact.fact.toLowerCase().slice(0, 50)}`;
631
636
  if (this.recentFacts.has(dedupeKey))
632
637
  continue;
633
- if (existingMemory.includes(fact.fact.toLowerCase().slice(0, 30)))
638
+ const memoryNeedle = fact.fact.toLowerCase().slice(0, 40);
639
+ if (existingMemory.includes(memoryNeedle) || projectMemory.includes(memoryNeedle))
634
640
  continue;
635
641
  const entry = `[${fact.category}] ${fact.fact}`;
636
642
  if (fact.category === "preference" && projectScope) {
637
- await appendMemory(projectScope, entry);
643
+ await appendMemory(projectScope, entry, { dedupe: true });
638
644
  } else {
639
- await appendMemory(globalScope, entry);
645
+ await appendMemory(globalScope, entry, { dedupe: true });
640
646
  }
641
647
  this.recentFacts.add(dedupeKey);
642
648
  }
@@ -652,10 +658,43 @@ var FactExtractor = class {
652
658
  }
653
659
  }
654
660
  };
661
+ var MIN_WORDS = {
662
+ identity: 1,
663
+ location: 1,
664
+ work: 1,
665
+ preference: 1,
666
+ relationship: 1,
667
+ instruction: 3,
668
+ personal: 1
669
+ };
670
+ var MIN_LENGTH = {
671
+ identity: 2,
672
+ location: 2,
673
+ work: 2,
674
+ preference: 3,
675
+ relationship: 2,
676
+ instruction: 10,
677
+ personal: 2
678
+ };
679
+ var NOISE_PATTERNS = [
680
+ /^(?:this|that|it|the|a|an|some|any|all)$/i,
681
+ /^(?:circular deps?|deps?|fix|bug|error|issue|test|build|run|check)$/i,
682
+ /^(?:file|folder|dir|path|module|package|import|export)$/i,
683
+ /^[a-z]$/i
684
+ ];
655
685
  function normalizeFact(category, raw) {
656
686
  const cleaned = raw.replace(/[.!?,;:]+$/, "").trim();
657
- if (cleaned.length < 2)
687
+ if (cleaned.length < MIN_LENGTH[category])
688
+ return null;
689
+ const wordCount = cleaned.split(/\s+/).filter((w) => w.length > 0).length;
690
+ if (wordCount < MIN_WORDS[category])
658
691
  return null;
692
+ if (wordCount <= 2) {
693
+ for (const noise of NOISE_PATTERNS) {
694
+ if (noise.test(cleaned))
695
+ return null;
696
+ }
697
+ }
659
698
  switch (category) {
660
699
  case "identity":
661
700
  return `Name: ${capitalize(cleaned)}`;
@@ -678,6 +717,32 @@ function normalizeFact(category, raw) {
678
717
  function capitalize(s) {
679
718
  return s.charAt(0).toUpperCase() + s.slice(1);
680
719
  }
720
+ function shouldAnalyzeForFacts(text) {
721
+ const trimmed = text.trim();
722
+ if (trimmed.length < 8 || trimmed.length > 5e3)
723
+ return false;
724
+ const lower = trimmed.toLowerCase();
725
+ if (/^\/[a-z0-9_-]+/i.test(lower))
726
+ return false;
727
+ if (/^(hi|hii|hello|hey|yo|thanks|thank you|ok|okay|cool|fine|namaste|namaskaram)\b/.test(lower) && trimmed.length < 64) {
728
+ return false;
729
+ }
730
+ const hasMemorySignal = /\b(remember|don't forget|note this|save this|from now on|always|call me|my name is|i am|i'm|i live|i work|i prefer|we use|our stack)\b/i.test(lower);
731
+ const hasFirstPerson = /\b(i|i'm|i am|my|we|our)\b/i.test(lower);
732
+ const hasPatternCue = /\b(based in|living in|located in|never use|don't use|avoid|keep in mind|note that|remember that)\b/i.test(lower);
733
+ const isQuestion = /\?\s*$/.test(lower);
734
+ if (isQuestion && !hasMemorySignal)
735
+ return false;
736
+ return hasMemorySignal || hasFirstPerson || hasPatternCue;
737
+ }
738
+ function shouldUseVectorFallback(text) {
739
+ const lower = text.toLowerCase();
740
+ if (!shouldAnalyzeForFacts(text))
741
+ return false;
742
+ if (/^\s*(which|what|when|where|why|how)\b/.test(lower) && /\?\s*$/.test(lower))
743
+ return false;
744
+ return true;
745
+ }
681
746
  var _instance = null;
682
747
  function getFactExtractor(config) {
683
748
  if (!_instance) {
@@ -873,7 +938,7 @@ function isDayConsolidated(date) {
873
938
  return fs.existsSync(getDayFilePath(date));
874
939
  }
875
940
  async function getUnconsolidatedDates(limit) {
876
- const { listSessionDates } = await import("./session-store-O3TS7DUY.js");
941
+ const { listSessionDates } = await import("./session-store-3EDQZEDS.js");
877
942
  const sessionDates = listSessionDates();
878
943
  const unconsolidated = [];
879
944
  for (const date of sessionDates) {
@@ -916,7 +981,7 @@ async function consolidateDay(date, options) {
916
981
  if (options?.loadSessions) {
917
982
  sessions = await options.loadSessions(date);
918
983
  } else {
919
- const { listSessionsByDate, listTurnsWithTimestamps, loadSession } = await import("./session-store-O3TS7DUY.js");
984
+ const { listSessionsByDate, listTurnsWithTimestamps, loadSession } = await import("./session-store-3EDQZEDS.js");
920
985
  const metas = listSessionsByDate(date);
921
986
  sessions = metas.map((meta) => {
922
987
  try {
@@ -992,7 +1057,7 @@ async function consolidateDay(date, options) {
992
1057
  fs2.mkdirSync(dir, { recursive: true });
993
1058
  fs2.writeFileSync(dayPath, markdown, "utf-8");
994
1059
  try {
995
- const { indexConsolidationSummary } = await import("./consolidation-indexer-VIWOP6VO.js");
1060
+ const { indexConsolidationSummary } = await import("./consolidation-indexer-KPXORCJ4.js");
996
1061
  await indexConsolidationSummary("daily", date, markdown);
997
1062
  } catch {
998
1063
  }
@@ -1074,4 +1139,4 @@ export {
1074
1139
  getDayFilePath,
1075
1140
  consolidateDay
1076
1141
  };
1077
- //# sourceMappingURL=chunk-F6RNEGFX.js.map
1142
+ //# sourceMappingURL=chunk-PZ4AQ22L.js.map
@@ -2,7 +2,7 @@ import {
2
2
  __commonJS,
3
3
  __require,
4
4
  __toESM
5
- } from "./chunk-IGKYKEKT.js";
5
+ } from "./chunk-NAQKA54E.js";
6
6
 
7
7
  // ../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/can-promise.js
8
8
  var require_can_promise = __commonJS({
@@ -5802,15 +5802,288 @@ var TwitterAdapter = class {
5802
5802
  }
5803
5803
  };
5804
5804
 
5805
+ // packages/channels/src/tring.ts
5806
+ import { execSync } from "node:child_process";
5807
+ import { randomUUID } from "node:crypto";
5808
+ var TRING_PLATFORM_ALIASES = {
5809
+ whispr: "signal"
5810
+ };
5811
+ var normalizeTringPlatform = (value) => {
5812
+ const normalized = value.trim().toLowerCase();
5813
+ if (normalized in TRING_PLATFORM_ALIASES) return TRING_PLATFORM_ALIASES[normalized];
5814
+ if (normalized === "whatsapp" || normalized === "telegram" || normalized === "signal") {
5815
+ return normalized;
5816
+ }
5817
+ return void 0;
5818
+ };
5819
+ var TringAdapter = class _TringAdapter {
5820
+ id = "tring";
5821
+ options;
5822
+ onMessage;
5823
+ timer;
5824
+ isPolling = false;
5825
+ unsupportedPollPlatforms = /* @__PURE__ */ new Set();
5826
+ /** Per-platform cursor token returned by Tring message list/poll. */
5827
+ lastCursor = /* @__PURE__ */ new Map();
5828
+ /** Per-platform fallback lower bound in unix seconds when cursor is unavailable. */
5829
+ lastSince = /* @__PURE__ */ new Map();
5830
+ /** Recent message identities for local de-duplication when daemon lacks `since`. */
5831
+ recentMessageKeys = /* @__PURE__ */ new Map();
5832
+ constructor(options, onMessage) {
5833
+ const normalizedPlatforms = options.platforms.map((platform) => normalizeTringPlatform(platform)).filter((platform) => Boolean(platform)).filter((platform, index, list) => list.indexOf(platform) === index);
5834
+ this.options = {
5835
+ ...options,
5836
+ platforms: normalizedPlatforms
5837
+ };
5838
+ this.onMessage = onMessage;
5839
+ }
5840
+ /** Start the adapter: verify daemon health, optionally spawn it, begin polling. */
5841
+ async start() {
5842
+ if (this.timer) return;
5843
+ const healthy = await this.health();
5844
+ if (!healthy && this.options.autoStartDaemon) {
5845
+ const bin = this.options.tringBin ?? _TringAdapter.detectTringBin();
5846
+ if (bin) {
5847
+ try {
5848
+ execSync(`${bin} daemon start`, { stdio: "ignore", timeout: 5e3 });
5849
+ } catch {
5850
+ }
5851
+ }
5852
+ }
5853
+ this.timer = setInterval(() => {
5854
+ void this.pollOnce();
5855
+ }, this.options.pollIntervalMs);
5856
+ }
5857
+ /** Stop polling. Does NOT kill the daemon. */
5858
+ stop() {
5859
+ if (this.timer) {
5860
+ clearInterval(this.timer);
5861
+ this.timer = void 0;
5862
+ }
5863
+ }
5864
+ /**
5865
+ * Send a text message through the Tring daemon.
5866
+ * @param platform Target platform (whatsapp, telegram, signal).
5867
+ * @param chatId Destination chat identifier.
5868
+ * @param text Message body.
5869
+ */
5870
+ async sendMessage(platform, chatId, text) {
5871
+ const canonical = normalizeTringPlatform(platform);
5872
+ if (!canonical) {
5873
+ throw new Error(`unsupported tring platform: ${platform}`);
5874
+ }
5875
+ await this.rpc("message.send", { platform: canonical, chat_id: chatId, text });
5876
+ }
5877
+ /** Check daemon health. Returns `true` if the daemon is reachable and healthy. */
5878
+ async health() {
5879
+ try {
5880
+ const res = await this.rpc("platform.health", {});
5881
+ return res?.ok === true;
5882
+ } catch {
5883
+ return false;
5884
+ }
5885
+ }
5886
+ /**
5887
+ * Auto-detect the tring CLI binary on the local system.
5888
+ * Searches common install paths.
5889
+ */
5890
+ static detectTringBin() {
5891
+ const paths = [
5892
+ "tring",
5893
+ `${process.env["HOME"] ?? ""}/.local/bin/tring`,
5894
+ "/usr/local/bin/tring"
5895
+ ];
5896
+ for (const p of paths) {
5897
+ try {
5898
+ execSync(`which ${p}`, { stdio: "ignore" });
5899
+ return p;
5900
+ } catch {
5901
+ }
5902
+ }
5903
+ return void 0;
5904
+ }
5905
+ // ── Private ──────────────────────────────────────────────────────────
5906
+ /** Poll all configured platforms once for new messages. */
5907
+ async pollOnce() {
5908
+ if (this.isPolling) return;
5909
+ this.isPolling = true;
5910
+ try {
5911
+ for (const platform of this.options.platforms) {
5912
+ const params = {
5913
+ platform,
5914
+ direction: "incoming"
5915
+ };
5916
+ const cursor = this.lastCursor.get(platform);
5917
+ const since = this.lastSince.get(platform);
5918
+ if (cursor) {
5919
+ params["cursor"] = cursor;
5920
+ } else if (since && since > 0) {
5921
+ params["since"] = since;
5922
+ }
5923
+ let res;
5924
+ if (this.unsupportedPollPlatforms.has(platform)) {
5925
+ res = await this.rpc("message.list", params);
5926
+ } else {
5927
+ const pollRes = await this.rpc("message.poll", params);
5928
+ if (pollRes.ok) {
5929
+ res = pollRes;
5930
+ } else if (this.shouldFallbackToList(pollRes.error)) {
5931
+ this.unsupportedPollPlatforms.add(platform);
5932
+ res = await this.rpc("message.list", params);
5933
+ } else {
5934
+ res = pollRes;
5935
+ }
5936
+ }
5937
+ const { messages, cursor: nextCursor } = this.extractMessages(res?.data);
5938
+ if (nextCursor) this.lastCursor.set(platform, nextCursor);
5939
+ this.pruneRecentMessageKeys();
5940
+ let maxSeenSince = since ?? 0;
5941
+ for (const raw of messages) {
5942
+ if (this.isDuplicate(platform, raw)) continue;
5943
+ if (this.options.allowedChats?.length) {
5944
+ if (!this.options.allowedChats.includes(raw.chat_id)) continue;
5945
+ }
5946
+ const normalized = this.normalize(platform, raw);
5947
+ if (normalized) {
5948
+ await this.onMessage(normalized);
5949
+ }
5950
+ const ts = this.toUnixSeconds(raw.timestamp);
5951
+ if (ts > maxSeenSince) maxSeenSince = ts;
5952
+ }
5953
+ if (maxSeenSince > 0) this.lastSince.set(platform, maxSeenSince);
5954
+ }
5955
+ } finally {
5956
+ this.isPolling = false;
5957
+ }
5958
+ }
5959
+ /** Normalize a Tring raw message into a NormalizedMessage. */
5960
+ normalize(platform, raw) {
5961
+ const normalizedPlatform = normalizeTringPlatform(raw.platform ?? platform);
5962
+ if (!normalizedPlatform) return null;
5963
+ const body = raw.body_text ?? raw.body;
5964
+ if (!body) return null;
5965
+ const userId = raw.user_id ?? raw.sender_id ?? raw.chat_id;
5966
+ const channel = normalizedPlatform;
5967
+ return {
5968
+ channel,
5969
+ chatId: raw.chat_id,
5970
+ userId,
5971
+ chatType: raw.chat_type ?? "dm",
5972
+ threadId: raw.thread_id,
5973
+ text: body,
5974
+ time: this.toIsoTimestamp(raw.timestamp),
5975
+ raw
5976
+ };
5977
+ }
5978
+ /** Extract messages/cursor from both legacy (`data: []`) and current payloads. */
5979
+ extractMessages(data) {
5980
+ if (Array.isArray(data)) return { messages: data };
5981
+ if (!data) return { messages: [] };
5982
+ return {
5983
+ messages: Array.isArray(data.messages) ? data.messages : [],
5984
+ cursor: typeof data.cursor === "string" && data.cursor.length > 0 ? data.cursor : void 0
5985
+ };
5986
+ }
5987
+ /** Convert epoch seconds/milliseconds into ISO timestamp. */
5988
+ toIsoTimestamp(value) {
5989
+ const millis = value > 1e10 ? value : value * 1e3;
5990
+ return new Date(millis).toISOString();
5991
+ }
5992
+ /** Convert epoch seconds/milliseconds to unix seconds. */
5993
+ toUnixSeconds(value) {
5994
+ return value > 1e10 ? Math.floor(value / 1e3) : value;
5995
+ }
5996
+ /** Prune dedupe cache to avoid unbounded growth. */
5997
+ pruneRecentMessageKeys() {
5998
+ const cutoff = Date.now() - 10 * 6e4;
5999
+ for (const [key, seenAt] of this.recentMessageKeys.entries()) {
6000
+ if (seenAt < cutoff) this.recentMessageKeys.delete(key);
6001
+ }
6002
+ }
6003
+ /** Return true when this inbound record was already observed in recent polls. */
6004
+ isDuplicate(platform, raw) {
6005
+ const identity = raw.platform_message_id || raw.id || `${raw.chat_id}:${raw.sender_id ?? raw.user_id ?? ""}:${raw.timestamp}:${raw.body ?? ""}`;
6006
+ const key = `${platform}:${identity}`;
6007
+ const now = Date.now();
6008
+ if (this.recentMessageKeys.has(key)) return true;
6009
+ this.recentMessageKeys.set(key, now);
6010
+ return false;
6011
+ }
6012
+ shouldFallbackToList(error) {
6013
+ if (!error) return false;
6014
+ const code = this.extractErrorCode(error);
6015
+ if (!code) return false;
6016
+ return code.includes("PLATFORM_FEATURE_UNSUPPORTED") || code.includes("METHOD_NOT_FOUND") || code.includes("INVALID_ARGUMENT") || code.includes("NOT_FOUND");
6017
+ }
6018
+ extractErrorCode(error) {
6019
+ if (typeof error === "string") return error;
6020
+ return error.code;
6021
+ }
6022
+ /**
6023
+ * Inline JSON-RPC client. Posts a command to the Tring daemon.
6024
+ * Retries once on connection failure after a 1 second delay.
6025
+ */
6026
+ async rpc(command, params) {
6027
+ const url = `${this.options.daemonUrl}/rpc`;
6028
+ const body = JSON.stringify({
6029
+ request_id: randomUUID(),
6030
+ command,
6031
+ params
6032
+ });
6033
+ const headers = { "content-type": "application/json" };
6034
+ const attempt = async () => {
6035
+ const res = await fetch(url, { method: "POST", headers, body });
6036
+ const contentType = res.headers.get("content-type")?.toLowerCase() ?? "";
6037
+ const payloadText = await res.text();
6038
+ const preview = payloadText.length > 512 ? `${payloadText.slice(0, 512)}...` : payloadText;
6039
+ if (!res.ok) {
6040
+ return {
6041
+ ok: false,
6042
+ error: `http_${res.status}_${res.statusText}: ${preview}`
6043
+ };
6044
+ }
6045
+ if (!contentType.includes("application/json")) {
6046
+ return {
6047
+ ok: false,
6048
+ error: `non_json_response_${contentType || "unknown"}: ${preview}`
6049
+ };
6050
+ }
6051
+ try {
6052
+ return JSON.parse(payloadText);
6053
+ } catch (parseError) {
6054
+ return {
6055
+ ok: false,
6056
+ error: `json_parse_failed_${parseError instanceof Error ? parseError.message : String(parseError)}: ${preview}`
6057
+ };
6058
+ }
6059
+ };
6060
+ try {
6061
+ return await attempt();
6062
+ } catch (firstError) {
6063
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
6064
+ try {
6065
+ return await attempt();
6066
+ } catch (retryError) {
6067
+ console.warn("[vaayu] tring rpc failed", {
6068
+ command,
6069
+ message: retryError instanceof Error ? retryError.message : String(retryError)
6070
+ });
6071
+ return { ok: false, error: "connection_failed" };
6072
+ }
6073
+ }
6074
+ }
6075
+ };
6076
+
5805
6077
  export {
5806
6078
  require_lib,
5807
6079
  TelegramAdapter,
5808
6080
  WhatsAppAdapter,
5809
6081
  IMessageAdapter,
5810
6082
  TwitterAdapter,
6083
+ TringAdapter,
5811
6084
  generateMantra,
5812
6085
  validateMantra,
5813
6086
  renderPairDisplay,
5814
6087
  renderPairStatus
5815
6088
  };
5816
- //# sourceMappingURL=chunk-G2QREGXK.js.map
6089
+ //# sourceMappingURL=chunk-R273KC7J.js.map
@@ -55,7 +55,7 @@ function cosineSimilarity(a, b) {
55
55
  return dotProduct / denominator;
56
56
  }
57
57
  function estimateTokens(text) {
58
- return Math.ceil(text.length / 4);
58
+ return Math.ceil(text.length / 3.7);
59
59
  }
60
60
  function tokenize(text) {
61
61
  return text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((t) => t.length >= 2 && !STOP_WORDS.has(t));
@@ -209,4 +209,4 @@ export {
209
209
  fallbackEmbedding,
210
210
  EmbeddingService
211
211
  };
212
- //# sourceMappingURL=chunk-A3HOZBC5.js.map
212
+ //# sourceMappingURL=chunk-RVKTGKFD.js.map