@getrift/rift 0.1.0-beta.1 → 0.1.0-beta.11

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 (207) hide show
  1. package/README.md +154 -0
  2. package/dist/src/auth/keychain.d.ts +9 -0
  3. package/dist/src/auth/keychain.d.ts.map +1 -1
  4. package/dist/src/auth/keychain.js +37 -0
  5. package/dist/src/auth/keychain.js.map +1 -1
  6. package/dist/src/capture/recover-quarantine.d.ts +221 -0
  7. package/dist/src/capture/recover-quarantine.d.ts.map +1 -0
  8. package/dist/src/capture/recover-quarantine.js +453 -0
  9. package/dist/src/capture/recover-quarantine.js.map +1 -0
  10. package/dist/src/cli/commands/backfill.d.ts.map +1 -1
  11. package/dist/src/cli/commands/backfill.js +5 -2
  12. package/dist/src/cli/commands/backfill.js.map +1 -1
  13. package/dist/src/cli/commands/capture-recover.d.ts +12 -0
  14. package/dist/src/cli/commands/capture-recover.d.ts.map +1 -0
  15. package/dist/src/cli/commands/capture-recover.js +120 -0
  16. package/dist/src/cli/commands/capture-recover.js.map +1 -0
  17. package/dist/src/cli/commands/capture.d.ts.map +1 -1
  18. package/dist/src/cli/commands/capture.js +10 -4
  19. package/dist/src/cli/commands/capture.js.map +1 -1
  20. package/dist/src/cli/commands/feedback.d.ts.map +1 -1
  21. package/dist/src/cli/commands/feedback.js +6 -2
  22. package/dist/src/cli/commands/feedback.js.map +1 -1
  23. package/dist/src/cli/commands/mcp-install.js +5 -2
  24. package/dist/src/cli/commands/mcp-install.js.map +1 -1
  25. package/dist/src/cli/commands/onboard.d.ts +24 -0
  26. package/dist/src/cli/commands/onboard.d.ts.map +1 -1
  27. package/dist/src/cli/commands/onboard.js +119 -21
  28. package/dist/src/cli/commands/onboard.js.map +1 -1
  29. package/dist/src/cli/commands/rebuild.d.ts.map +1 -1
  30. package/dist/src/cli/commands/rebuild.js +6 -3
  31. package/dist/src/cli/commands/rebuild.js.map +1 -1
  32. package/dist/src/cli/commands/review.d.ts.map +1 -1
  33. package/dist/src/cli/commands/review.js +22 -7
  34. package/dist/src/cli/commands/review.js.map +1 -1
  35. package/dist/src/cli/commands/search.d.ts.map +1 -1
  36. package/dist/src/cli/commands/search.js +28 -4
  37. package/dist/src/cli/commands/search.js.map +1 -1
  38. package/dist/src/cli/commands/status.d.ts.map +1 -1
  39. package/dist/src/cli/commands/status.js +48 -2
  40. package/dist/src/cli/commands/status.js.map +1 -1
  41. package/dist/src/cli/commands/token-issue.d.ts.map +1 -1
  42. package/dist/src/cli/commands/token-issue.js +9 -1
  43. package/dist/src/cli/commands/token-issue.js.map +1 -1
  44. package/dist/src/cli/commands/triage.d.ts.map +1 -1
  45. package/dist/src/cli/commands/triage.js +7 -5
  46. package/dist/src/cli/commands/triage.js.map +1 -1
  47. package/dist/src/cli/commands/update.d.ts +26 -0
  48. package/dist/src/cli/commands/update.d.ts.map +1 -0
  49. package/dist/src/cli/commands/update.js +130 -0
  50. package/dist/src/cli/commands/update.js.map +1 -0
  51. package/dist/src/cli/default-config-path.d.ts +15 -0
  52. package/dist/src/cli/default-config-path.d.ts.map +1 -0
  53. package/dist/src/cli/default-config-path.js +27 -0
  54. package/dist/src/cli/default-config-path.js.map +1 -0
  55. package/dist/src/cli/http-client.d.ts +56 -1
  56. package/dist/src/cli/http-client.d.ts.map +1 -1
  57. package/dist/src/cli/http-client.js +161 -6
  58. package/dist/src/cli/http-client.js.map +1 -1
  59. package/dist/src/cli/index.d.ts.map +1 -1
  60. package/dist/src/cli/index.js +25 -6
  61. package/dist/src/cli/index.js.map +1 -1
  62. package/dist/src/cli/status/friend-header.d.ts.map +1 -1
  63. package/dist/src/cli/status/friend-header.js +117 -7
  64. package/dist/src/cli/status/friend-header.js.map +1 -1
  65. package/dist/src/ingestion/inbox-core/conversation-fingerprint.d.ts +2 -0
  66. package/dist/src/ingestion/inbox-core/conversation-fingerprint.d.ts.map +1 -0
  67. package/dist/src/ingestion/inbox-core/conversation-fingerprint.js +27 -0
  68. package/dist/src/ingestion/inbox-core/conversation-fingerprint.js.map +1 -0
  69. package/dist/src/ingestion/inbox-core/conversation-key.d.ts +2 -0
  70. package/dist/src/ingestion/inbox-core/conversation-key.d.ts.map +1 -0
  71. package/dist/src/ingestion/inbox-core/conversation-key.js +31 -0
  72. package/dist/src/ingestion/inbox-core/conversation-key.js.map +1 -0
  73. package/dist/src/ingestion/inbox-core/extensions.d.ts +3 -0
  74. package/dist/src/ingestion/inbox-core/extensions.d.ts.map +1 -0
  75. package/dist/src/ingestion/inbox-core/extensions.js +16 -0
  76. package/dist/src/ingestion/inbox-core/extensions.js.map +1 -0
  77. package/dist/src/ingestion/inbox-core/idempotency.d.ts +2 -0
  78. package/dist/src/ingestion/inbox-core/idempotency.d.ts.map +1 -0
  79. package/dist/src/ingestion/inbox-core/idempotency.js +22 -0
  80. package/dist/src/ingestion/inbox-core/idempotency.js.map +1 -0
  81. package/dist/src/ingestion/inbox-core/index.d.ts +20 -0
  82. package/dist/src/ingestion/inbox-core/index.d.ts.map +1 -0
  83. package/dist/src/ingestion/inbox-core/index.js +20 -0
  84. package/dist/src/ingestion/inbox-core/index.js.map +1 -0
  85. package/dist/src/ingestion/inbox-core/source-detection.d.ts +2 -0
  86. package/dist/src/ingestion/inbox-core/source-detection.d.ts.map +1 -0
  87. package/dist/src/ingestion/inbox-core/source-detection.js +23 -0
  88. package/dist/src/ingestion/inbox-core/source-detection.js.map +1 -0
  89. package/dist/src/ingestion/inbox-core/source-sniffer.d.ts +11 -0
  90. package/dist/src/ingestion/inbox-core/source-sniffer.d.ts.map +1 -0
  91. package/dist/src/ingestion/inbox-core/source-sniffer.js +69 -0
  92. package/dist/src/ingestion/inbox-core/source-sniffer.js.map +1 -0
  93. package/dist/src/ingestion/inbox-core/zip-sniffer.d.ts +70 -0
  94. package/dist/src/ingestion/inbox-core/zip-sniffer.d.ts.map +1 -0
  95. package/dist/src/ingestion/inbox-core/zip-sniffer.js +161 -0
  96. package/dist/src/ingestion/inbox-core/zip-sniffer.js.map +1 -0
  97. package/dist/src/ingestion/inbox-watcher.d.ts.map +1 -1
  98. package/dist/src/ingestion/inbox-watcher.js +34 -50
  99. package/dist/src/ingestion/inbox-watcher.js.map +1 -1
  100. package/dist/src/ingestion/indexer.d.ts +7 -0
  101. package/dist/src/ingestion/indexer.d.ts.map +1 -1
  102. package/dist/src/ingestion/indexer.js +36 -2
  103. package/dist/src/ingestion/indexer.js.map +1 -1
  104. package/dist/src/ingestion/metadata-extraction.d.ts +8 -5
  105. package/dist/src/ingestion/metadata-extraction.d.ts.map +1 -1
  106. package/dist/src/ingestion/metadata-extraction.js +24 -5
  107. package/dist/src/ingestion/metadata-extraction.js.map +1 -1
  108. package/dist/src/ingestion/skip-quarantine.d.ts +10 -0
  109. package/dist/src/ingestion/skip-quarantine.d.ts.map +1 -0
  110. package/dist/src/ingestion/skip-quarantine.js +35 -0
  111. package/dist/src/ingestion/skip-quarantine.js.map +1 -0
  112. package/dist/src/jobs/handlers/compact.d.ts.map +1 -1
  113. package/dist/src/jobs/handlers/compact.js +25 -4
  114. package/dist/src/jobs/handlers/compact.js.map +1 -1
  115. package/dist/src/jobs/handlers/ingest.d.ts.map +1 -1
  116. package/dist/src/jobs/handlers/ingest.js +214 -36
  117. package/dist/src/jobs/handlers/ingest.js.map +1 -1
  118. package/dist/src/jobs/handlers/reconcile.d.ts.map +1 -1
  119. package/dist/src/jobs/handlers/reconcile.js +30 -8
  120. package/dist/src/jobs/handlers/reconcile.js.map +1 -1
  121. package/dist/src/jobs/handlers/reindex.d.ts.map +1 -1
  122. package/dist/src/jobs/handlers/reindex.js +12 -2
  123. package/dist/src/jobs/handlers/reindex.js.map +1 -1
  124. package/dist/src/jobs/handlers/save.d.ts.map +1 -1
  125. package/dist/src/jobs/handlers/save.js +9 -2
  126. package/dist/src/jobs/handlers/save.js.map +1 -1
  127. package/dist/src/jobs/queue.d.ts +11 -0
  128. package/dist/src/jobs/queue.d.ts.map +1 -1
  129. package/dist/src/jobs/queue.js +18 -0
  130. package/dist/src/jobs/queue.js.map +1 -1
  131. package/dist/src/jobs/worker-entry.d.ts.map +1 -1
  132. package/dist/src/jobs/worker-entry.js +2 -0
  133. package/dist/src/jobs/worker-entry.js.map +1 -1
  134. package/dist/src/main.js +36 -4
  135. package/dist/src/main.js.map +1 -1
  136. package/dist/src/mcp/errors.d.ts.map +1 -1
  137. package/dist/src/mcp/errors.js +20 -1
  138. package/dist/src/mcp/errors.js.map +1 -1
  139. package/dist/src/mcp/tools/context-pack.d.ts.map +1 -1
  140. package/dist/src/mcp/tools/context-pack.js +5 -2
  141. package/dist/src/mcp/tools/context-pack.js.map +1 -1
  142. package/dist/src/mcp/tools/search.d.ts +6 -2
  143. package/dist/src/mcp/tools/search.d.ts.map +1 -1
  144. package/dist/src/mcp/tools/search.js +34 -4
  145. package/dist/src/mcp/tools/search.js.map +1 -1
  146. package/dist/src/observability/embedding-events.d.ts +52 -0
  147. package/dist/src/observability/embedding-events.d.ts.map +1 -0
  148. package/dist/src/observability/embedding-events.js +149 -0
  149. package/dist/src/observability/embedding-events.js.map +1 -0
  150. package/dist/src/observability/index-events.d.ts +70 -0
  151. package/dist/src/observability/index-events.d.ts.map +1 -0
  152. package/dist/src/observability/index-events.js +148 -0
  153. package/dist/src/observability/index-events.js.map +1 -0
  154. package/dist/src/observability/tool-usage-stats.d.ts +69 -4
  155. package/dist/src/observability/tool-usage-stats.d.ts.map +1 -1
  156. package/dist/src/observability/tool-usage-stats.js +88 -31
  157. package/dist/src/observability/tool-usage-stats.js.map +1 -1
  158. package/dist/src/observability/tool-usage.d.ts +100 -7
  159. package/dist/src/observability/tool-usage.d.ts.map +1 -1
  160. package/dist/src/observability/tool-usage.js +196 -33
  161. package/dist/src/observability/tool-usage.js.map +1 -1
  162. package/dist/src/observability/version-check.d.ts +70 -0
  163. package/dist/src/observability/version-check.d.ts.map +1 -0
  164. package/dist/src/observability/version-check.js +197 -0
  165. package/dist/src/observability/version-check.js.map +1 -0
  166. package/dist/src/providers/ollama-embed.d.ts +2 -1
  167. package/dist/src/providers/ollama-embed.d.ts.map +1 -1
  168. package/dist/src/providers/ollama-embed.js +1 -0
  169. package/dist/src/providers/ollama-embed.js.map +1 -1
  170. package/dist/src/providers/openai-metadata-extraction.d.ts +3 -3
  171. package/dist/src/providers/openai-metadata-extraction.d.ts.map +1 -1
  172. package/dist/src/providers/openai-metadata-extraction.js +18 -3
  173. package/dist/src/providers/openai-metadata-extraction.js.map +1 -1
  174. package/dist/src/providers/stub.d.ts +2 -0
  175. package/dist/src/providers/stub.d.ts.map +1 -1
  176. package/dist/src/providers/stub.js +2 -0
  177. package/dist/src/providers/stub.js.map +1 -1
  178. package/dist/src/providers/types.d.ts +11 -0
  179. package/dist/src/providers/types.d.ts.map +1 -1
  180. package/dist/src/providers/voyage.d.ts +2 -1
  181. package/dist/src/providers/voyage.d.ts.map +1 -1
  182. package/dist/src/providers/voyage.js +1 -0
  183. package/dist/src/providers/voyage.js.map +1 -1
  184. package/dist/src/retrieval/compact.d.ts +115 -2
  185. package/dist/src/retrieval/compact.d.ts.map +1 -1
  186. package/dist/src/retrieval/compact.js +154 -5
  187. package/dist/src/retrieval/compact.js.map +1 -1
  188. package/dist/src/retrieval/context-pack.d.ts +8 -0
  189. package/dist/src/retrieval/context-pack.d.ts.map +1 -1
  190. package/dist/src/retrieval/context-pack.js +17 -2
  191. package/dist/src/retrieval/context-pack.js.map +1 -1
  192. package/dist/src/server/app.d.ts.map +1 -1
  193. package/dist/src/server/app.js +67 -1
  194. package/dist/src/server/app.js.map +1 -1
  195. package/dist/src/server/routes/friend-status.d.ts +202 -3
  196. package/dist/src/server/routes/friend-status.d.ts.map +1 -1
  197. package/dist/src/server/routes/friend-status.js +290 -7
  198. package/dist/src/server/routes/friend-status.js.map +1 -1
  199. package/dist/src/server/routes/mcp-usage.d.ts +4 -4
  200. package/dist/src/server/routes/search.d.ts.map +1 -1
  201. package/dist/src/server/routes/search.js +144 -24
  202. package/dist/src/server/routes/search.js.map +1 -1
  203. package/dist/src/storage/rebuild.d.ts +14 -1
  204. package/dist/src/storage/rebuild.d.ts.map +1 -1
  205. package/dist/src/storage/rebuild.js +160 -34
  206. package/dist/src/storage/rebuild.js.map +1 -1
  207. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","sourceRoot":"","sources":["../../../../src/mcp/tools/search.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EACL,qBAAqB,GAEtB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC;IACjD,KAAK,EAAE,CAAC;SACL,IAAI,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;SAClE,QAAQ,EAAE;SACV,QAAQ,CAAC,gCAAgC,CAAC;IAC7C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;IAC1E,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,2DAA2D,CAAC;IACxE,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,QAAQ,EAAE;SACV,QAAQ,CAAC,yCAAyC,CAAC;IACtD,GAAG,EAAE,CAAC;SACH,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,yEAAyE,CAC1E;IACH,MAAM,EAAE,CAAC;SACN,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;SACzB,QAAQ,EAAE;SACV,QAAQ,CACP,qGAAqG,CACtG;IACH,EAAE,EAAE,CAAC;SACF,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,gDAAgD,CAAC;CAC9D,CAAC;AAUF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAA6B,EAC7B,MAAkB;IAElB,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,IAA6B,CAAC;QAC3C,MAAM,IAAI,GAAG,qBAAqB,CAAC,IAAI,CAAC,OAAO,EAAE;YAC/C,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1E,CAAC,CAAC;QACH,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;YAC1C,iBAAiB,EAAE,IAA0C;SAC9D,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../../../src/mcp/tools/search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { EmbeddingProvider } from "../providers/types.js";
2
+ export declare const EMBEDDING_PIPELINES: readonly ["watcher", "scheduled_scan", "reconcile", "ingest_job", "compact", "backfill", "capture", "reindex"];
3
+ export type EmbeddingPipeline = (typeof EMBEDDING_PIPELINES)[number];
4
+ export type EmbeddingOutcome = "success" | "error";
5
+ export interface EmbeddingEvent {
6
+ ts: string;
7
+ provider: string;
8
+ model: string;
9
+ pipeline: EmbeddingPipeline;
10
+ /**
11
+ * Free-form caller label (e.g. "document_embedding", "conversation",
12
+ * "digest", "reindex_conversation"). Helps debug "which write path"
13
+ * when scanning the log; does not gate any status logic today.
14
+ */
15
+ operation: string;
16
+ outcome: EmbeddingOutcome;
17
+ input_count: number;
18
+ ms: number;
19
+ /** Compact error class (e.g. "provider_400"). Present when outcome === "error". */
20
+ error_class?: string;
21
+ /** Truncated error message (≤ 512 chars). Present when outcome === "error". */
22
+ error_message?: string;
23
+ }
24
+ export interface EmbedContext {
25
+ pipeline: EmbeddingPipeline;
26
+ operation: string;
27
+ /** Number of inputs in this call (1 for embed, N for embedBatch). */
28
+ input_count: number;
29
+ }
30
+ export declare function eventsFilePath(dataDir: string): string;
31
+ /**
32
+ * Append a single event to the lane. Never throws — telemetry must not
33
+ * break embedding. On filesystem error, writes a single stderr line so
34
+ * the failure is at least visible to operators tailing logs.
35
+ */
36
+ export declare function appendEmbeddingEvent(dataDir: string, event: EmbeddingEvent): void;
37
+ /**
38
+ * Run an embedding call and record one event. Re-throws errors so the
39
+ * caller's existing failure-handling path is unchanged; logging is a
40
+ * pure side effect.
41
+ *
42
+ * Use this at every ingest call site. Do NOT use it for search-time
43
+ * embedding — keeping search out of the lane is what makes
44
+ * `last_embed_at` meaningful.
45
+ */
46
+ export declare function recordEmbed<T>(dataDir: string, provider: EmbeddingProvider, ctx: EmbedContext, fn: () => Promise<T>): Promise<T>;
47
+ /**
48
+ * Tolerant reader. One bad JSON line is skipped; the rest are returned.
49
+ * Returns [] if the file is missing.
50
+ */
51
+ export declare function readEmbeddingEvents(dataDir: string): EmbeddingEvent[];
52
+ //# sourceMappingURL=embedding-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding-events.d.ts","sourceRoot":"","sources":["../../../src/observability/embedding-events.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,eAAO,MAAM,mBAAmB,gHAStB,CAAC;AACX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAErE,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,iBAAiB,CAAC;IAC5B;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAID,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,cAAc,GACpB,IAAI,CAUN;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,CAAC,EACjC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,iBAAiB,EAC3B,GAAG,EAAE,YAAY,EACjB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CA+BZ;AAkBD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAoBrE"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Embedding-events lane — append-only JSONL.
3
+ *
4
+ * One row per call to an embedding provider on an *ingest* code path
5
+ * (watcher / scheduled-scan / reconcile / ingest-job / compact / backfill).
6
+ * Search-time embedding calls (search routes, hybrid retrieval) are
7
+ * deliberately NOT logged here — otherwise a user search would refresh
8
+ * `voyage.last_embed_at` and mask an ingestion outage.
9
+ *
10
+ * Provider-agnostic on purpose: `provider` and `model` are payload
11
+ * fields, not the file name, so a future Ollama/local-embedding swap
12
+ * shares the same lane and the same `/status/friend` consumer.
13
+ *
14
+ * Failure mode: writes are best-effort and never throw — embedding must
15
+ * not be observably blocked by telemetry. Reads are tolerant of bad
16
+ * lines so one corrupt row doesn't blank the status dashboard.
17
+ */
18
+ import fs from "node:fs";
19
+ import path from "node:path";
20
+ export const EMBEDDING_PIPELINES = [
21
+ "watcher",
22
+ "scheduled_scan",
23
+ "reconcile",
24
+ "ingest_job",
25
+ "compact",
26
+ "backfill",
27
+ "capture",
28
+ "reindex",
29
+ ];
30
+ const MAX_ERROR_MESSAGE_LEN = 512;
31
+ export function eventsFilePath(dataDir) {
32
+ return path.join(dataDir, "observability", "embedding-events.jsonl");
33
+ }
34
+ /**
35
+ * Append a single event to the lane. Never throws — telemetry must not
36
+ * break embedding. On filesystem error, writes a single stderr line so
37
+ * the failure is at least visible to operators tailing logs.
38
+ */
39
+ export function appendEmbeddingEvent(dataDir, event) {
40
+ const filePath = eventsFilePath(dataDir);
41
+ try {
42
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
43
+ fs.appendFileSync(filePath, JSON.stringify(event) + "\n");
44
+ }
45
+ catch (err) {
46
+ process.stderr.write(`[embedding-events] write failed: ${err instanceof Error ? err.message : String(err)}\n`);
47
+ }
48
+ }
49
+ /**
50
+ * Run an embedding call and record one event. Re-throws errors so the
51
+ * caller's existing failure-handling path is unchanged; logging is a
52
+ * pure side effect.
53
+ *
54
+ * Use this at every ingest call site. Do NOT use it for search-time
55
+ * embedding — keeping search out of the lane is what makes
56
+ * `last_embed_at` meaningful.
57
+ */
58
+ export async function recordEmbed(dataDir, provider, ctx, fn) {
59
+ const start = Date.now();
60
+ try {
61
+ const result = await fn();
62
+ appendEmbeddingEvent(dataDir, {
63
+ ts: new Date().toISOString(),
64
+ provider: provider.name,
65
+ model: provider.model,
66
+ pipeline: ctx.pipeline,
67
+ operation: ctx.operation,
68
+ outcome: "success",
69
+ input_count: ctx.input_count,
70
+ ms: Date.now() - start,
71
+ });
72
+ return result;
73
+ }
74
+ catch (err) {
75
+ const message = err instanceof Error ? err.message : String(err);
76
+ appendEmbeddingEvent(dataDir, {
77
+ ts: new Date().toISOString(),
78
+ provider: provider.name,
79
+ model: provider.model,
80
+ pipeline: ctx.pipeline,
81
+ operation: ctx.operation,
82
+ outcome: "error",
83
+ input_count: ctx.input_count,
84
+ ms: Date.now() - start,
85
+ error_class: classifyError(err),
86
+ error_message: message.slice(0, MAX_ERROR_MESSAGE_LEN),
87
+ });
88
+ throw err;
89
+ }
90
+ }
91
+ /**
92
+ * Best-effort classification for the `error_class` field.
93
+ * Voyage / Ollama errors carry `Voyage API <code>: ...` /
94
+ * `Ollama embed API <code>: ...` shapes — extract the status code so
95
+ * status views can group by class without parsing free-text.
96
+ */
97
+ function classifyError(err) {
98
+ const msg = err instanceof Error ? err.message : String(err);
99
+ const httpMatch = msg.match(/\b(\d{3})\b/);
100
+ if (httpMatch && msg.toLowerCase().includes("api")) {
101
+ return `provider_${httpMatch[1]}`;
102
+ }
103
+ if (err instanceof TypeError)
104
+ return "network";
105
+ return "unknown";
106
+ }
107
+ /**
108
+ * Tolerant reader. One bad JSON line is skipped; the rest are returned.
109
+ * Returns [] if the file is missing.
110
+ */
111
+ export function readEmbeddingEvents(dataDir) {
112
+ let raw;
113
+ try {
114
+ raw = fs.readFileSync(eventsFilePath(dataDir), "utf-8");
115
+ }
116
+ catch {
117
+ return [];
118
+ }
119
+ const out = [];
120
+ for (const line of raw.split("\n")) {
121
+ if (!line)
122
+ continue;
123
+ let parsed;
124
+ try {
125
+ parsed = JSON.parse(line);
126
+ }
127
+ catch {
128
+ continue;
129
+ }
130
+ if (!isEmbeddingEvent(parsed))
131
+ continue;
132
+ out.push(parsed);
133
+ }
134
+ return out;
135
+ }
136
+ function isEmbeddingEvent(value) {
137
+ if (value === null || typeof value !== "object")
138
+ return false;
139
+ const v = value;
140
+ return (typeof v["ts"] === "string" &&
141
+ typeof v["provider"] === "string" &&
142
+ typeof v["model"] === "string" &&
143
+ typeof v["pipeline"] === "string" &&
144
+ typeof v["operation"] === "string" &&
145
+ (v["outcome"] === "success" || v["outcome"] === "error") &&
146
+ typeof v["input_count"] === "number" &&
147
+ typeof v["ms"] === "number");
148
+ }
149
+ //# sourceMappingURL=embedding-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding-events.js","sourceRoot":"","sources":["../../../src/observability/embedding-events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import type { EmbeddingPipeline } from "./embedding-events.js";
2
+ export type IndexOutcome = "success" | "error";
3
+ export interface IndexEvent {
4
+ ts: string;
5
+ /**
6
+ * Target LanceDB table. Free-form string (not `TableName`) so shadow
7
+ * writes can record their target without coupling to the live table
8
+ * name set.
9
+ */
10
+ table: string;
11
+ pipeline: EmbeddingPipeline;
12
+ /**
13
+ * Free-form caller label (e.g. "structured_doc_upsert",
14
+ * "conversation_upsert", "digest_upsert"). Helps debug "which write
15
+ * path"; does not gate any status logic today.
16
+ */
17
+ operation: string;
18
+ outcome: IndexOutcome;
19
+ /** Number of rows in this `table.add(...)` call (or rollback batch). */
20
+ row_count: number;
21
+ ms: number;
22
+ /**
23
+ * Lifecycle phase.
24
+ * - "live" (default when omitted) — the row is now searchable.
25
+ * Direct writes are always "live"; shadow rebuilds emit a single
26
+ * "live" event per table after `commitAllSwaps` succeeds.
27
+ * - "shadow" — the row was written to a pre-commit shadow table. If
28
+ * the subsequent swap fails the row is NOT searchable, so
29
+ * `computeIndexHealth` does NOT credit `last_update_at` from
30
+ * shadow successes. Shadow errors still surface as `last_error_at`
31
+ * because they represent real LanceDB write failures regardless of
32
+ * the eventual swap outcome.
33
+ */
34
+ phase?: "live" | "shadow";
35
+ /** Compact error class. Present when outcome === "error". */
36
+ error_class?: string;
37
+ /** Truncated error message (≤ 512 chars). Present when outcome === "error". */
38
+ error_message?: string;
39
+ }
40
+ export interface IndexWriteContext {
41
+ table: string;
42
+ pipeline: EmbeddingPipeline;
43
+ operation: string;
44
+ row_count: number;
45
+ /** Defaults to "live". Set "shadow" for pre-commit shadow-table writes. */
46
+ phase?: "live" | "shadow";
47
+ }
48
+ export declare function indexEventsFilePath(dataDir: string): string;
49
+ /**
50
+ * Append a single event to the lane. Never throws — telemetry must not
51
+ * break indexing. On filesystem error, writes a single stderr line so
52
+ * the failure is at least visible to operators tailing logs.
53
+ */
54
+ export declare function appendIndexEvent(dataDir: string, event: IndexEvent): void;
55
+ /**
56
+ * Run a LanceDB write and record one event. Re-throws errors so the
57
+ * caller's existing failure-handling path is unchanged; logging is a
58
+ * pure side effect.
59
+ *
60
+ * Use this only at write boundaries (`table.add(...)`). Do NOT use it
61
+ * for reads, queries, or deletes — keeping the lane write-only is what
62
+ * makes `last_update_at` meaningful.
63
+ */
64
+ export declare function recordIndexWrite<T>(dataDir: string, ctx: IndexWriteContext, fn: () => Promise<T>): Promise<T>;
65
+ /**
66
+ * Tolerant reader. One bad JSON line is skipped; the rest are returned.
67
+ * Returns [] if the file is missing.
68
+ */
69
+ export declare function readIndexEvents(dataDir: string): IndexEvent[];
70
+ //# sourceMappingURL=index-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-events.d.ts","sourceRoot":"","sources":["../../../src/observability/index-events.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;AAE/C,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,iBAAiB,CAAC;IAC5B;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAID,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CAC3B;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,UAAU,GAChB,IAAI,CAUN;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,iBAAiB,EACtB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAgCZ;AAmBD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,CAoB7D"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Index-events lane — append-only JSONL.
3
+ *
4
+ * One row per write boundary against LanceDB (`table.add(...)`). This
5
+ * complements `embedding-events.jsonl`: the embedding lane proves the
6
+ * vector was produced, this lane proves the row was actually persisted
7
+ * to LanceDB and is searchable. Without it, `/status/friend` cannot
8
+ * distinguish "embedded but not indexed yet" from "fully searchable".
9
+ *
10
+ * Provider-agnostic and table-agnostic: `table` and `pipeline` are
11
+ * payload fields. Reads / search queries are deliberately NOT wrapped —
12
+ * they're not write events and would muddy `index.last_update_at`.
13
+ *
14
+ * Failure mode: writes are best-effort and never throw — observability
15
+ * must not break indexing. The reader is tolerant of bad lines so one
16
+ * corrupt row doesn't blank the status dashboard.
17
+ */
18
+ import fs from "node:fs";
19
+ import path from "node:path";
20
+ const MAX_ERROR_MESSAGE_LEN = 512;
21
+ export function indexEventsFilePath(dataDir) {
22
+ return path.join(dataDir, "observability", "index-events.jsonl");
23
+ }
24
+ /**
25
+ * Append a single event to the lane. Never throws — telemetry must not
26
+ * break indexing. On filesystem error, writes a single stderr line so
27
+ * the failure is at least visible to operators tailing logs.
28
+ */
29
+ export function appendIndexEvent(dataDir, event) {
30
+ const filePath = indexEventsFilePath(dataDir);
31
+ try {
32
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
33
+ fs.appendFileSync(filePath, JSON.stringify(event) + "\n");
34
+ }
35
+ catch (err) {
36
+ process.stderr.write(`[index-events] write failed: ${err instanceof Error ? err.message : String(err)}\n`);
37
+ }
38
+ }
39
+ /**
40
+ * Run a LanceDB write and record one event. Re-throws errors so the
41
+ * caller's existing failure-handling path is unchanged; logging is a
42
+ * pure side effect.
43
+ *
44
+ * Use this only at write boundaries (`table.add(...)`). Do NOT use it
45
+ * for reads, queries, or deletes — keeping the lane write-only is what
46
+ * makes `last_update_at` meaningful.
47
+ */
48
+ export async function recordIndexWrite(dataDir, ctx, fn) {
49
+ const start = Date.now();
50
+ const phase = ctx.phase ?? "live";
51
+ try {
52
+ const result = await fn();
53
+ appendIndexEvent(dataDir, {
54
+ ts: new Date().toISOString(),
55
+ table: ctx.table,
56
+ pipeline: ctx.pipeline,
57
+ operation: ctx.operation,
58
+ outcome: "success",
59
+ row_count: ctx.row_count,
60
+ ms: Date.now() - start,
61
+ phase,
62
+ });
63
+ return result;
64
+ }
65
+ catch (err) {
66
+ const message = err instanceof Error ? err.message : String(err);
67
+ appendIndexEvent(dataDir, {
68
+ ts: new Date().toISOString(),
69
+ table: ctx.table,
70
+ pipeline: ctx.pipeline,
71
+ operation: ctx.operation,
72
+ outcome: "error",
73
+ row_count: ctx.row_count,
74
+ ms: Date.now() - start,
75
+ phase,
76
+ error_class: classifyError(err),
77
+ error_message: message.slice(0, MAX_ERROR_MESSAGE_LEN),
78
+ });
79
+ throw err;
80
+ }
81
+ }
82
+ /**
83
+ * Best-effort classification for the `error_class` field. LanceDB
84
+ * surfaces schema mismatches, IO errors, and lock contention with
85
+ * different shapes — pick a coarse class so dashboards can group.
86
+ */
87
+ function classifyError(err) {
88
+ const msg = err instanceof Error ? err.message : String(err);
89
+ const lower = msg.toLowerCase();
90
+ if (lower.includes("schema"))
91
+ return "schema_mismatch";
92
+ if (lower.includes("lock") || lower.includes("conflict"))
93
+ return "lock_conflict";
94
+ if (lower.includes("enoent") || lower.includes("eacces") || lower.includes("eio")) {
95
+ return "io";
96
+ }
97
+ if (err instanceof TypeError)
98
+ return "type";
99
+ return "unknown";
100
+ }
101
+ /**
102
+ * Tolerant reader. One bad JSON line is skipped; the rest are returned.
103
+ * Returns [] if the file is missing.
104
+ */
105
+ export function readIndexEvents(dataDir) {
106
+ let raw;
107
+ try {
108
+ raw = fs.readFileSync(indexEventsFilePath(dataDir), "utf-8");
109
+ }
110
+ catch {
111
+ return [];
112
+ }
113
+ const out = [];
114
+ for (const line of raw.split("\n")) {
115
+ if (!line)
116
+ continue;
117
+ let parsed;
118
+ try {
119
+ parsed = JSON.parse(line);
120
+ }
121
+ catch {
122
+ continue;
123
+ }
124
+ if (!isIndexEvent(parsed))
125
+ continue;
126
+ out.push(parsed);
127
+ }
128
+ return out;
129
+ }
130
+ function isIndexEvent(value) {
131
+ if (value === null || typeof value !== "object")
132
+ return false;
133
+ const v = value;
134
+ if (!(typeof v["ts"] === "string" &&
135
+ typeof v["table"] === "string" &&
136
+ typeof v["pipeline"] === "string" &&
137
+ typeof v["operation"] === "string" &&
138
+ (v["outcome"] === "success" || v["outcome"] === "error") &&
139
+ typeof v["row_count"] === "number" &&
140
+ typeof v["ms"] === "number")) {
141
+ return false;
142
+ }
143
+ const phase = v["phase"];
144
+ if (phase !== undefined && phase !== "live" && phase !== "shadow")
145
+ return false;
146
+ return true;
147
+ }
148
+ //# sourceMappingURL=index-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-events.js","sourceRoot":"","sources":["../../../src/observability/index-events.ts"],"names":[],"mappings":"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"}
@@ -3,14 +3,78 @@
3
3
  *
4
4
  * No filesystem reads, no parsing — callers pass an already-decoded
5
5
  * `ToolUsageEntry[]` (typically via `readToolUsageEntriesTolerant`).
6
- * Buckets calls into today/week/month/all-time and applies a fixed
7
- * per-tool tokens-saved heuristic so historical entries (which were
8
- * never instrumented for size) yield a usable estimate.
6
+ * Buckets calls into today/week/month/all-time. The headline retrieval
7
+ * metric is `context_tokens_delivered_estimate` the measured size of
8
+ * the text channel actually returned on context hits, divided by 4 for
9
+ * a rough tokens estimate.
9
10
  */
10
11
  import type { ToolUsageEntry } from "./tool-usage.js";
11
12
  export interface UsageWindow {
12
13
  calls: number;
13
- tokens_saved: number;
14
+ /**
15
+ * Successful retrieval calls that returned at least one item and were not
16
+ * marked `degraded`. Captures rift_search, rift_conversations_search, and
17
+ * rift_context_pack — the tools whose job is to surface relevant context.
18
+ * Non-retrieval calls (rift_save, rift_status) are excluded.
19
+ */
20
+ context_hits: number;
21
+ /**
22
+ * Cheap tokens estimate (`ceil(bytes / 4)`) over the MCP text channel of
23
+ * every call that counts toward `context_hits`. Measured from the response
24
+ * we actually returned — not a per-tool flat constant. Empty results,
25
+ * degraded retrievals, failures, and non-retrieval tools contribute 0.
26
+ * Legacy log rows written before response size was recorded contribute 0
27
+ * (no fabricated number) and naturally age out as fresh rows accumulate.
28
+ */
29
+ context_tokens_delivered_estimate: number;
30
+ }
31
+ /**
32
+ * Precise-lookup health: aggregates over rift_search calls whose
33
+ * `search_mode` was recorded as `"exact_id"`. Surfaces the leading
34
+ * indicators that the strict direct-lookup gate on `/search` is or
35
+ * isn't earning agent trust — high success ratio + rare typed failures
36
+ * is healthy; rising `typed_failures` (`id_not_found`/`ambiguous_id`)
37
+ * or large `max_content_tokens_estimate` paired with low success is
38
+ * the shape of a flow where an agent may stop trusting Rift for precise
39
+ * lookup. Trust risk is named precisely:
40
+ * we cannot tell from Rift alone that the agent went on to read JSONL
41
+ * from disk, only that the lookup it asked for here failed.
42
+ */
43
+ export interface PreciseLookupStats {
44
+ /** Total rift_search calls with search_mode = exact_id (success or not). */
45
+ total: number;
46
+ /** Subset of `total` where success = true. */
47
+ successes: number;
48
+ /**
49
+ * Failures bucketed by the typed `error` field parsed from the response
50
+ * body (e.g. `id_not_found`, `ambiguous_id`). Transport / untyped
51
+ * failures do not appear here — they only count toward `total - successes`.
52
+ */
53
+ typed_failures: Record<string, number>;
54
+ /**
55
+ * Detail-level split among exact-id calls. `summary` is impossible by
56
+ * definition (exact-id requires middle|full), so only `middle` and
57
+ * `full` appear. Useful for seeing whether agents prefer the bounded
58
+ * middle path or still default to full-body expansion.
59
+ */
60
+ by_detail: {
61
+ middle: number;
62
+ full: number;
63
+ };
64
+ /**
65
+ * Count of successful exact-id calls that returned at least one hit
66
+ * with `content_truncated === true` — a leading indicator that the
67
+ * agent received a bounded excerpt and may decide to escalate to
68
+ * `detail=full`. Bounded to successful calls because truncation only
69
+ * makes sense for returned content.
70
+ */
71
+ truncated_count: number;
72
+ /**
73
+ * Maximum `content_tokens_estimate` observed across all exact-id
74
+ * calls (successful or not, when the field was present). Captures the
75
+ * worst-case "this row would blow context if expanded" signal.
76
+ */
77
+ max_content_tokens_estimate: number;
14
78
  }
15
79
  export interface UsageSummary {
16
80
  today: UsageWindow;
@@ -18,6 +82,7 @@ export interface UsageSummary {
18
82
  month: UsageWindow;
19
83
  all_time: UsageWindow;
20
84
  by_tool: Record<string, number>;
85
+ precise_lookup: PreciseLookupStats;
21
86
  }
22
87
  export declare function aggregateUsage(entries: ToolUsageEntry[], now?: Date): UsageSummary;
23
88
  //# sourceMappingURL=tool-usage-stats.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool-usage-stats.d.ts","sourceRoot":"","sources":["../../../src/observability/tool-usage-stats.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAyCtD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,WAAW,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAkBD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,cAAc,EAAE,EACzB,GAAG,GAAE,IAAiB,GACrB,YAAY,CA4Cd"}
1
+ {"version":3,"file":"tool-usage-stats.d.ts","sourceRoot":"","sources":["../../../src/observability/tool-usage-stats.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAsBtD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,iCAAiC,EAAE,MAAM,CAAC;CAC3C;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAkB;IACjC,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC;;;;;OAKG;IACH,SAAS,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C;;;;;;OAMG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,2BAA2B,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,WAAW,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,cAAc,EAAE,kBAAkB,CAAC;CACpC;AA+DD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,cAAc,EAAE,EACzB,GAAG,GAAE,IAAiB,GACrB,YAAY,CAiFd"}