clawvault 3.1.0 → 3.2.1

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 (273) hide show
  1. package/README.md +422 -141
  2. package/bin/clawvault.js +10 -2
  3. package/bin/command-registration.test.js +3 -1
  4. package/bin/command-runtime.js +9 -1
  5. package/bin/register-core-commands.js +23 -28
  6. package/bin/register-maintenance-commands.js +39 -3
  7. package/bin/register-query-commands.js +58 -29
  8. package/bin/register-tailscale-commands.js +106 -0
  9. package/bin/register-task-commands.js +18 -1
  10. package/bin/register-task-commands.test.js +16 -0
  11. package/bin/register-vault-operations-commands.js +29 -1
  12. package/bin/register-workgraph-commands.js +451 -0
  13. package/dashboard/lib/graph-diff.js +104 -0
  14. package/dashboard/lib/graph-diff.test.js +75 -0
  15. package/dashboard/lib/vault-parser.js +556 -0
  16. package/dashboard/lib/vault-parser.test.js +254 -0
  17. package/dashboard/public/app.js +796 -0
  18. package/dashboard/public/index.html +52 -0
  19. package/dashboard/public/styles.css +221 -0
  20. package/dashboard/server.js +374 -0
  21. package/dist/{chunk-C7OK5WKP.js → chunk-2JQ3O2YL.js} +4 -4
  22. package/dist/{chunk-VR5NE7PZ.js → chunk-2RAZ4ZFE.js} +1 -1
  23. package/dist/{chunk-F2JEUD4J.js → chunk-4ITRXIVT.js} +5 -7
  24. package/dist/{chunk-GUKMRGM7.js → chunk-4OXMU5S2.js} +1 -1
  25. package/dist/chunk-5PJ4STIC.js +465 -0
  26. package/dist/{chunk-62YTUT6J.js → chunk-AZYOKJYC.js} +2 -2
  27. package/dist/chunk-BSJ6RIT7.js +447 -0
  28. package/dist/chunk-ECRZL5XR.js +50 -0
  29. package/dist/chunk-ERNE2FZ5.js +189 -0
  30. package/dist/{chunk-WAZ3NLWL.js → chunk-F55HGNU4.js} +0 -47
  31. package/dist/{chunk-VGLOTGAS.js → chunk-FAKNOB7Y.js} +2 -2
  32. package/dist/{chunk-QK3UCXWL.js → chunk-FHFUXL6G.js} +2 -2
  33. package/dist/chunk-GNJL4YGR.js +79 -0
  34. package/dist/chunk-HR4KN6S2.js +152 -0
  35. package/dist/{chunk-OZ7RIXTO.js → chunk-IIOU45CK.js} +1 -1
  36. package/dist/chunk-IJBFGPCS.js +33 -0
  37. package/dist/chunk-IVRIKYFE.js +520 -0
  38. package/dist/chunk-K7PNYS45.js +93 -0
  39. package/dist/chunk-MDIH26GC.js +183 -0
  40. package/dist/{chunk-LYHGEHXG.js → chunk-MFAWT5O5.js} +0 -1
  41. package/dist/{chunk-H34S76MB.js → chunk-MNPUYCHQ.js} +6 -6
  42. package/dist/chunk-NTOPJI7W.js +207 -0
  43. package/dist/{chunk-QBLMXKF2.js → chunk-OIWVQYQF.js} +1 -1
  44. package/dist/chunk-PG56HX5T.js +154 -0
  45. package/dist/{chunk-LNJA2UGL.js → chunk-PI4WMLMG.js} +7 -84
  46. package/dist/chunk-QMHPQYUV.js +363 -0
  47. package/dist/{chunk-H62BP7RI.js → chunk-QPDDIHXE.js} +209 -43
  48. package/dist/{chunk-N2AXRYLC.js → chunk-QWQ3TIKS.js} +1 -1
  49. package/dist/{chunk-3DHXQHYG.js → chunk-R2MIW5G7.js} +1 -1
  50. package/dist/{chunk-SJSFRIYS.js → chunk-S5OJEGFG.js} +2 -2
  51. package/dist/chunk-SS4B7P7V.js +99 -0
  52. package/dist/chunk-TIGW564L.js +628 -0
  53. package/dist/chunk-U67V476Y.js +35 -0
  54. package/dist/{chunk-JY6FYXIT.js → chunk-UCQAOZHW.js} +6 -11
  55. package/dist/{chunk-ITPEXLHA.js → chunk-URXDAUVH.js} +24 -5
  56. package/dist/chunk-WIOLLGAD.js +190 -0
  57. package/dist/{chunk-3WRJEKN4.js → chunk-WJVWINEM.js} +72 -8
  58. package/dist/chunk-WMGIIABP.js +15 -0
  59. package/dist/{chunk-33UGEQRT.js → chunk-X3SPPUFG.js} +151 -64
  60. package/dist/{chunk-3NSBOUT3.js → chunk-Y3TIJEBP.js} +314 -79
  61. package/dist/chunk-Y6VJKXGL.js +373 -0
  62. package/dist/{chunk-LI4O6NVK.js → chunk-YDWHS4LJ.js} +49 -9
  63. package/dist/{chunk-U55BGUAU.js → chunk-YNIPYN4F.js} +5 -5
  64. package/dist/chunk-YXQCA6B7.js +226 -0
  65. package/dist/cli/index.js +26 -22
  66. package/dist/commands/archive.js +3 -3
  67. package/dist/commands/backlog.js +3 -3
  68. package/dist/commands/blocked.js +3 -3
  69. package/dist/commands/canvas.d.ts +15 -0
  70. package/dist/commands/canvas.js +200 -0
  71. package/dist/commands/checkpoint.js +2 -2
  72. package/dist/commands/compat.js +2 -2
  73. package/dist/commands/context.js +7 -5
  74. package/dist/commands/doctor.d.ts +11 -7
  75. package/dist/commands/doctor.js +16 -14
  76. package/dist/commands/embed.js +5 -6
  77. package/dist/commands/entities.js +2 -2
  78. package/dist/commands/graph.js +3 -3
  79. package/dist/commands/inject.d.ts +1 -1
  80. package/dist/commands/inject.js +4 -5
  81. package/dist/commands/kanban.js +4 -4
  82. package/dist/commands/link.js +2 -2
  83. package/dist/commands/migrate-observations.js +4 -4
  84. package/dist/commands/observe.d.ts +0 -1
  85. package/dist/commands/observe.js +13 -12
  86. package/dist/commands/project.js +5 -5
  87. package/dist/commands/rebuild-embeddings.d.ts +21 -0
  88. package/dist/commands/rebuild-embeddings.js +91 -0
  89. package/dist/commands/rebuild.js +12 -11
  90. package/dist/commands/recover.js +3 -3
  91. package/dist/commands/reflect.js +6 -7
  92. package/dist/commands/repair-session.js +1 -1
  93. package/dist/commands/replay.js +14 -14
  94. package/dist/commands/session-recap.js +1 -1
  95. package/dist/commands/setup.d.ts +2 -89
  96. package/dist/commands/setup.js +3 -21
  97. package/dist/commands/shell-init.js +1 -1
  98. package/dist/commands/sleep.d.ts +1 -1
  99. package/dist/commands/sleep.js +18 -17
  100. package/dist/commands/status.d.ts +2 -0
  101. package/dist/commands/status.js +40 -30
  102. package/dist/commands/sync-bd.d.ts +10 -0
  103. package/dist/commands/sync-bd.js +10 -0
  104. package/dist/commands/tailscale.d.ts +52 -0
  105. package/dist/commands/tailscale.js +26 -0
  106. package/dist/commands/task.js +4 -4
  107. package/dist/commands/template.js +2 -2
  108. package/dist/commands/wake.d.ts +1 -1
  109. package/dist/commands/wake.js +11 -10
  110. package/dist/index.d.ts +334 -191
  111. package/dist/index.js +432 -108
  112. package/dist/{inject-Bzi5E-By.d.ts → inject-DYUrDqQO.d.ts} +3 -3
  113. package/dist/ledger-B7g7jhqG.d.ts +44 -0
  114. package/dist/lib/auto-linker.js +1 -1
  115. package/dist/lib/canvas-layout.d.ts +115 -0
  116. package/dist/lib/canvas-layout.js +35 -0
  117. package/dist/lib/config.d.ts +27 -3
  118. package/dist/lib/config.js +4 -2
  119. package/dist/lib/entity-index.js +1 -1
  120. package/dist/lib/project-utils.js +4 -4
  121. package/dist/lib/session-repair.js +1 -1
  122. package/dist/lib/session-utils.js +1 -1
  123. package/dist/lib/tailscale.d.ts +225 -0
  124. package/dist/lib/tailscale.js +50 -0
  125. package/dist/lib/task-utils.js +3 -3
  126. package/dist/lib/template-engine.js +1 -1
  127. package/dist/lib/webdav.d.ts +109 -0
  128. package/dist/lib/webdav.js +35 -0
  129. package/dist/plugin/index.d.ts +344 -28
  130. package/dist/plugin/index.js +3919 -227
  131. package/dist/registry-BR4326o0.d.ts +30 -0
  132. package/dist/store-CA-6sKCJ.d.ts +34 -0
  133. package/dist/thread-B9LhXNU0.d.ts +41 -0
  134. package/dist/{types-Y2_Um2Ls.d.ts → types-BbWJoC1c.d.ts} +1 -44
  135. package/dist/workgraph/index.d.ts +5 -0
  136. package/dist/workgraph/index.js +23 -0
  137. package/dist/workgraph/ledger.d.ts +2 -0
  138. package/dist/workgraph/ledger.js +25 -0
  139. package/dist/workgraph/registry.d.ts +2 -0
  140. package/dist/workgraph/registry.js +19 -0
  141. package/dist/workgraph/store.d.ts +2 -0
  142. package/dist/workgraph/store.js +25 -0
  143. package/dist/workgraph/thread.d.ts +2 -0
  144. package/dist/workgraph/thread.js +25 -0
  145. package/dist/workgraph/types.d.ts +54 -0
  146. package/dist/workgraph/types.js +7 -0
  147. package/hooks/clawvault/HOOK.md +113 -0
  148. package/hooks/clawvault/handler.js +1559 -0
  149. package/hooks/clawvault/handler.test.js +510 -0
  150. package/hooks/clawvault/openclaw.plugin.json +72 -0
  151. package/openclaw.plugin.json +235 -30
  152. package/package.json +20 -20
  153. package/dist/chunk-3RG5ZIWI.js +0 -10
  154. package/dist/chunk-3ZIH425O.js +0 -871
  155. package/dist/chunk-6U6MK36V.js +0 -205
  156. package/dist/chunk-CMB7UL7C.js +0 -327
  157. package/dist/chunk-D2H45LON.js +0 -1074
  158. package/dist/chunk-E7MFQB6D.js +0 -163
  159. package/dist/chunk-GQSLDZTS.js +0 -560
  160. package/dist/chunk-MFM6K7PU.js +0 -374
  161. package/dist/chunk-MXSSG3QU.js +0 -42
  162. package/dist/chunk-OCGVIN3L.js +0 -88
  163. package/dist/chunk-PAH27GSN.js +0 -108
  164. package/dist/chunk-YCUNCH2I.js +0 -78
  165. package/dist/cli/index.cjs +0 -8584
  166. package/dist/cli/index.d.cts +0 -5
  167. package/dist/commands/archive.cjs +0 -287
  168. package/dist/commands/archive.d.cts +0 -11
  169. package/dist/commands/backlog.cjs +0 -721
  170. package/dist/commands/backlog.d.cts +0 -53
  171. package/dist/commands/blocked.cjs +0 -204
  172. package/dist/commands/blocked.d.cts +0 -26
  173. package/dist/commands/checkpoint.cjs +0 -244
  174. package/dist/commands/checkpoint.d.cts +0 -41
  175. package/dist/commands/compat.cjs +0 -294
  176. package/dist/commands/compat.d.cts +0 -28
  177. package/dist/commands/context.cjs +0 -2990
  178. package/dist/commands/context.d.cts +0 -2
  179. package/dist/commands/doctor.cjs +0 -2986
  180. package/dist/commands/doctor.d.cts +0 -21
  181. package/dist/commands/embed.cjs +0 -232
  182. package/dist/commands/embed.d.cts +0 -17
  183. package/dist/commands/entities.cjs +0 -141
  184. package/dist/commands/entities.d.cts +0 -7
  185. package/dist/commands/graph.cjs +0 -501
  186. package/dist/commands/graph.d.cts +0 -21
  187. package/dist/commands/inject.cjs +0 -1636
  188. package/dist/commands/inject.d.cts +0 -2
  189. package/dist/commands/kanban.cjs +0 -884
  190. package/dist/commands/kanban.d.cts +0 -63
  191. package/dist/commands/link.cjs +0 -965
  192. package/dist/commands/link.d.cts +0 -11
  193. package/dist/commands/migrate-observations.cjs +0 -362
  194. package/dist/commands/migrate-observations.d.cts +0 -19
  195. package/dist/commands/observe.cjs +0 -4099
  196. package/dist/commands/observe.d.cts +0 -23
  197. package/dist/commands/project.cjs +0 -1341
  198. package/dist/commands/project.d.cts +0 -85
  199. package/dist/commands/rebuild.cjs +0 -3136
  200. package/dist/commands/rebuild.d.cts +0 -11
  201. package/dist/commands/recover.cjs +0 -361
  202. package/dist/commands/recover.d.cts +0 -38
  203. package/dist/commands/reflect.cjs +0 -1008
  204. package/dist/commands/reflect.d.cts +0 -11
  205. package/dist/commands/repair-session.cjs +0 -457
  206. package/dist/commands/repair-session.d.cts +0 -38
  207. package/dist/commands/replay.cjs +0 -4103
  208. package/dist/commands/replay.d.cts +0 -16
  209. package/dist/commands/session-recap.cjs +0 -353
  210. package/dist/commands/session-recap.d.cts +0 -27
  211. package/dist/commands/setup.cjs +0 -1278
  212. package/dist/commands/setup.d.cts +0 -99
  213. package/dist/commands/shell-init.cjs +0 -75
  214. package/dist/commands/shell-init.d.cts +0 -7
  215. package/dist/commands/sleep.cjs +0 -6029
  216. package/dist/commands/sleep.d.cts +0 -36
  217. package/dist/commands/status.cjs +0 -2737
  218. package/dist/commands/status.d.cts +0 -52
  219. package/dist/commands/task.cjs +0 -1236
  220. package/dist/commands/task.d.cts +0 -97
  221. package/dist/commands/template.cjs +0 -457
  222. package/dist/commands/template.d.cts +0 -36
  223. package/dist/commands/wake.cjs +0 -2627
  224. package/dist/commands/wake.d.cts +0 -22
  225. package/dist/context-BUGaWpyL.d.cts +0 -46
  226. package/dist/index.cjs +0 -12373
  227. package/dist/index.d.cts +0 -854
  228. package/dist/inject-Bzi5E-By.d.cts +0 -137
  229. package/dist/lib/auto-linker.cjs +0 -176
  230. package/dist/lib/auto-linker.d.cts +0 -26
  231. package/dist/lib/config.cjs +0 -78
  232. package/dist/lib/config.d.cts +0 -11
  233. package/dist/lib/entity-index.cjs +0 -84
  234. package/dist/lib/entity-index.d.cts +0 -26
  235. package/dist/lib/project-utils.cjs +0 -864
  236. package/dist/lib/project-utils.d.cts +0 -97
  237. package/dist/lib/session-repair.cjs +0 -239
  238. package/dist/lib/session-repair.d.cts +0 -110
  239. package/dist/lib/session-utils.cjs +0 -209
  240. package/dist/lib/session-utils.d.cts +0 -63
  241. package/dist/lib/task-utils.cjs +0 -1137
  242. package/dist/lib/task-utils.d.cts +0 -208
  243. package/dist/lib/template-engine.cjs +0 -47
  244. package/dist/lib/template-engine.d.cts +0 -11
  245. package/dist/plugin/index.cjs +0 -1907
  246. package/dist/plugin/index.d.cts +0 -36
  247. package/dist/plugin/inject.cjs +0 -356
  248. package/dist/plugin/inject.d.cts +0 -54
  249. package/dist/plugin/inject.d.ts +0 -54
  250. package/dist/plugin/inject.js +0 -17
  251. package/dist/plugin/observe.cjs +0 -631
  252. package/dist/plugin/observe.d.cts +0 -39
  253. package/dist/plugin/observe.d.ts +0 -39
  254. package/dist/plugin/observe.js +0 -18
  255. package/dist/plugin/templates.cjs +0 -593
  256. package/dist/plugin/templates.d.cts +0 -52
  257. package/dist/plugin/templates.d.ts +0 -52
  258. package/dist/plugin/templates.js +0 -25
  259. package/dist/plugin/types.cjs +0 -18
  260. package/dist/plugin/types.d.cts +0 -209
  261. package/dist/plugin/types.d.ts +0 -209
  262. package/dist/plugin/types.js +0 -0
  263. package/dist/plugin/vault.cjs +0 -927
  264. package/dist/plugin/vault.d.cts +0 -68
  265. package/dist/plugin/vault.d.ts +0 -68
  266. package/dist/plugin/vault.js +0 -22
  267. package/dist/types-Y2_Um2Ls.d.cts +0 -205
  268. package/templates/memory-event.md +0 -67
  269. package/templates/party.md +0 -63
  270. package/templates/primitive-registry.yaml +0 -551
  271. package/templates/run.md +0 -68
  272. package/templates/trigger.md +0 -68
  273. package/templates/workspace.md +0 -50
@@ -1,21 +1,11 @@
1
1
  import {
2
2
  listProjects
3
- } from "./chunk-62YTUT6J.js";
3
+ } from "./chunk-AZYOKJYC.js";
4
4
  import {
5
- listConfig,
6
- listRouteRules,
7
- matchRouteRule
8
- } from "./chunk-ITPEXLHA.js";
9
- import {
10
- resolveClaudeOAuthToken
11
- } from "./chunk-PAH27GSN.js";
12
- import {
13
- createBacklogItem,
14
- listBacklogItems,
15
- listTasks,
16
- updateBacklogItem,
17
- updateTask
18
- } from "./chunk-N2AXRYLC.js";
5
+ FactStore,
6
+ extractFactsLlm,
7
+ extractFactsRuleBased
8
+ } from "./chunk-BSJ6RIT7.js";
19
9
  import {
20
10
  DATE_HEADING_RE,
21
11
  inferObservationType,
@@ -24,7 +14,16 @@ import {
24
14
  parseObservationMarkdown,
25
15
  renderObservationMarkdown,
26
16
  renderScoredObservationLine
27
- } from "./chunk-QK3UCXWL.js";
17
+ } from "./chunk-FHFUXL6G.js";
18
+ import {
19
+ listConfig,
20
+ listRouteRules,
21
+ matchRouteRule
22
+ } from "./chunk-URXDAUVH.js";
23
+ import {
24
+ requestLlmCompletion,
25
+ resolveLlmProvider
26
+ } from "./chunk-YXQCA6B7.js";
28
27
  import {
29
28
  ensureLedgerStructure,
30
29
  ensureParentDir,
@@ -33,16 +32,27 @@ import {
33
32
  getRawTranscriptPath,
34
33
  toDateKey
35
34
  } from "./chunk-Z2XBWN7A.js";
35
+ import {
36
+ createBacklogItem,
37
+ listBacklogItems,
38
+ listTasks,
39
+ updateBacklogItem,
40
+ updateTask
41
+ } from "./chunk-QWQ3TIKS.js";
36
42
 
37
43
  // src/observer/compressor.ts
38
44
  var OPENAI_BASE_URL = "https://api.openai.com/v1";
45
+ var XAI_BASE_URL = "https://api.x.ai/v1";
39
46
  var OLLAMA_BASE_URL = "http://localhost:11434/v1";
40
47
  var DEFAULT_PROVIDER_MODELS = {
41
- anthropic: "claude-haiku-4-5",
48
+ anthropic: "claude-3-5-haiku-latest",
42
49
  openai: "gpt-4o-mini",
43
50
  gemini: "gemini-2.0-flash",
51
+ xai: "grok-2-latest",
44
52
  "openai-compatible": "gpt-4o-mini",
45
- ollama: "llama3.2"
53
+ ollama: "llama3.2",
54
+ minimax: "MiniMax-M2.1",
55
+ zai: "glm-4.5-air"
46
56
  };
47
57
  var CRITICAL_RE = /(?:\b(?:decision|decided|chose|chosen|selected|picked|opted|switched to)\s*:?|\bdecid(?:e|ed|ing|ion)\b|\berror\b|\bfail(?:ed|ure|ing)?\b|\bblock(?:ed|er)?\b|\bbreaking(?:\s+change)?s?\b|\bcritical\b|\b\w+\s+chosen\s+(?:for|over|as)\b|\bpublish(?:ed)?\b.*@?\d+\.\d+|\bmerge[d]?\s+(?:PR|pull\s+request)\b|\bshipped\b|\breleased?\b.*v?\d+\.\d+|\bsigned\b.*\b(?:contract|agreement|deal)\b|\bpricing\b.*\$|\bdemo\b.*\b(?:completed?|done|finished)\b|\bmeeting\b.*\b(?:completed?|done|finished)\b|\bstrategy\b.*\b(?:pivot|change|shift)\b)/i;
48
58
  var DEADLINE_WITH_DATE_RE = /(?:(?:\bdeadline\b|\bdue(?:\s+date)?\b|\bcutoff\b).*(?:\d{4}-\d{2}-\d{2}|\d{1,2}\/\d{1,2}(?:\/\d{2,4})?|(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\s+\d{1,2})|(?:\d{4}-\d{2}-\d{2}|\d{1,2}\/\d{1,2}(?:\/\d{2,4})?|(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\s+\d{1,2}).*(?:\bdeadline\b|\bdue(?:\s+date)?\b|\bcutoff\b))/i;
@@ -72,10 +82,10 @@ var Compressor = class {
72
82
  return existingObservations.trim();
73
83
  }
74
84
  const prompt = this.buildPrompt(cleanedMessages, existingObservations);
75
- const backend = await this.resolveProvider();
85
+ const backend = this.resolveProvider();
76
86
  if (backend) {
77
87
  try {
78
- const llmOutput = backend.provider === "anthropic" ? await this.callAnthropic(prompt, backend) : backend.provider === "gemini" ? await this.callGemini(prompt, backend) : backend.provider === "openai" ? await this.callOpenAI(prompt, backend) : await this.callOpenAICompatible(prompt, backend);
88
+ const llmOutput = backend.provider === "anthropic" ? await this.callAnthropic(prompt, backend) : backend.provider === "gemini" ? await this.callGemini(prompt, backend) : backend.provider === "openai" ? await this.callOpenAI(prompt, backend) : backend.provider === "xai" ? await this.callXAI(prompt, backend) : await this.callOpenAICompatible(prompt, backend);
79
89
  const normalized = this.normalizeLlmOutput(llmOutput);
80
90
  if (normalized) {
81
91
  return this.mergeObservations(existingObservations, normalized);
@@ -86,16 +96,16 @@ var Compressor = class {
86
96
  const fallback = this.fallbackCompression(cleanedMessages);
87
97
  return this.mergeObservations(existingObservations, fallback);
88
98
  }
89
- async resolveProvider() {
99
+ resolveProvider() {
90
100
  if (process.env.CLAWVAULT_NO_LLM) return null;
91
101
  if (this.provider) {
92
102
  const configured = this.resolveConfiguredProvider(this.provider);
93
103
  if (configured) {
94
104
  return configured;
95
105
  }
96
- return await this.resolveProviderFromEnv(false);
106
+ return this.resolveProviderFromEnv(false);
97
107
  }
98
- return await this.resolveProviderFromEnv(true);
108
+ return this.resolveProviderFromEnv(true);
99
109
  }
100
110
  resolveConfiguredProvider(provider) {
101
111
  const model = this.resolveModel(provider);
@@ -133,6 +143,18 @@ var Compressor = class {
133
143
  baseUrl: this.resolveBaseUrl(provider)
134
144
  };
135
145
  }
146
+ if (provider === "xai") {
147
+ const apiKey2 = this.resolveApiKey(provider);
148
+ if (!apiKey2) {
149
+ return null;
150
+ }
151
+ return {
152
+ provider,
153
+ model,
154
+ apiKey: apiKey2,
155
+ baseUrl: XAI_BASE_URL
156
+ };
157
+ }
136
158
  const apiKey = this.resolveApiKey(provider) ?? void 0;
137
159
  return {
138
160
  provider,
@@ -141,21 +163,14 @@ var Compressor = class {
141
163
  baseUrl: this.resolveBaseUrl(provider)
142
164
  };
143
165
  }
144
- async resolveProviderFromEnv(allowConfiguredModel) {
145
- const anthropicModel = allowConfiguredModel ? this.resolveModel("anthropic") : DEFAULT_PROVIDER_MODELS.anthropic;
146
- const oauthEnvToken = this.readEnvValue("ANTHROPIC_OAUTH_TOKEN");
147
- if (oauthEnvToken) {
148
- return { provider: "anthropic", model: anthropicModel, apiKey: oauthEnvToken, isOAuth: true };
149
- }
166
+ resolveProviderFromEnv(allowConfiguredModel) {
150
167
  const anthropicApiKey = this.readEnvValue("ANTHROPIC_API_KEY");
151
168
  if (anthropicApiKey) {
152
- return { provider: "anthropic", model: anthropicModel, apiKey: anthropicApiKey };
153
- }
154
- if (this.readEnvValue("CLAWVAULT_CLAUDE_AUTH")) {
155
- const oauthToken = await resolveClaudeOAuthToken();
156
- if (oauthToken) {
157
- return { provider: "anthropic", model: anthropicModel, apiKey: oauthToken, isOAuth: true };
158
- }
169
+ return {
170
+ provider: "anthropic",
171
+ model: allowConfiguredModel ? this.resolveModel("anthropic") : DEFAULT_PROVIDER_MODELS.anthropic,
172
+ apiKey: anthropicApiKey
173
+ };
159
174
  }
160
175
  const openAiApiKey = this.readEnvValue("OPENAI_API_KEY");
161
176
  if (openAiApiKey) {
@@ -174,6 +189,15 @@ var Compressor = class {
174
189
  apiKey: geminiApiKey
175
190
  };
176
191
  }
192
+ const xaiApiKey = this.readEnvValue("XAI_API_KEY");
193
+ if (xaiApiKey) {
194
+ return {
195
+ provider: "xai",
196
+ model: allowConfiguredModel ? this.resolveModel("xai") : DEFAULT_PROVIDER_MODELS.xai,
197
+ apiKey: xaiApiKey,
198
+ baseUrl: XAI_BASE_URL
199
+ };
200
+ }
177
201
  return null;
178
202
  }
179
203
  resolveModel(provider) {
@@ -194,6 +218,9 @@ var Compressor = class {
194
218
  if (provider === "gemini") {
195
219
  return this.readEnvValue("GEMINI_API_KEY");
196
220
  }
221
+ if (provider === "xai") {
222
+ return this.readEnvValue("XAI_API_KEY");
223
+ }
197
224
  return this.readEnvValue("OPENAI_API_KEY");
198
225
  }
199
226
  resolveBaseUrl(provider) {
@@ -225,17 +252,6 @@ var Compressor = class {
225
252
  "- Confidence c reflects extraction certainty, not importance.",
226
253
  "- Preserve source tags when present (e.g., [main], [telegram-dm], [discord], [telegram-group]).",
227
254
  "",
228
- "PREFERENCE & PERSONAL CONTEXT EXTRACTION (critical for personalization):",
229
- "- Emit [preference] for ANY personal detail that reveals tastes, habits, equipment, or context:",
230
- ' * Explicit: "I prefer X", "I like Y", "I always use Z"',
231
- ' * Ownership: "my Sony A7R IV", "I have a...", "I use...", "I own..."',
232
- ' * Habits/routines: "I usually...", "every morning I...", "I tend to..."',
233
- " * Interests: topics the user is enthusiastic about, hobbies mentioned in passing",
234
- " * Constraints: dietary restrictions, allergies, phobias, limitations",
235
- ` * Goals: "I'm trying to...", "I want to learn..."`,
236
- "- These are HIGH VALUE observations (i >= 0.60) \u2014 they enable personalized responses.",
237
- "- When in doubt between [preference] and [task], choose [preference] if it describes a lasting trait.",
238
- "",
239
255
  "TASK EXTRACTION (required):",
240
256
  `- Emit [todo] for explicit TODO phrasing: "TODO:", "we need to", "don't forget", "remember to", "make sure to".`,
241
257
  `- Emit [task] for commitments/action intent: "I'll", "I will", "let me", "going to", "plan to", "should".`,
@@ -314,35 +330,19 @@ var Compressor = class {
314
330
  if (!backend.apiKey) {
315
331
  return "";
316
332
  }
317
- const isOAuth = backend.isOAuth || backend.apiKey.includes("sk-ant-oat");
318
- const headers = isOAuth ? {
319
- "content-type": "application/json",
320
- "authorization": `Bearer ${backend.apiKey}`,
321
- "anthropic-version": "2023-06-01",
322
- "anthropic-beta": "claude-code-20250219,oauth-2025-04-20",
323
- "x-app": "cli",
324
- "user-agent": "claude-cli/1.0.0 (external, cli)"
325
- } : {
326
- "content-type": "application/json",
327
- "x-api-key": backend.apiKey,
328
- "anthropic-version": "2023-06-01"
329
- };
330
- const body = isOAuth ? {
331
- model: backend.model,
332
- temperature: 0.1,
333
- max_tokens: 1400,
334
- system: [{ type: "text", text: "You are Claude Code, Anthropic's official CLI for Claude." }],
335
- messages: [{ role: "user", content: prompt }]
336
- } : {
337
- model: backend.model,
338
- temperature: 0.1,
339
- max_tokens: 1400,
340
- messages: [{ role: "user", content: prompt }]
341
- };
342
333
  const response = await this.fetchImpl("https://api.anthropic.com/v1/messages", {
343
334
  method: "POST",
344
- headers,
345
- body: JSON.stringify(body)
335
+ headers: {
336
+ "content-type": "application/json",
337
+ "x-api-key": backend.apiKey,
338
+ "anthropic-version": "2023-06-01"
339
+ },
340
+ body: JSON.stringify({
341
+ model: backend.model,
342
+ temperature: 0.1,
343
+ max_tokens: 1400,
344
+ messages: [{ role: "user", content: prompt }]
345
+ })
346
346
  });
347
347
  if (!response.ok) {
348
348
  throw new Error(`Anthropic request failed (${response.status})`);
@@ -353,6 +353,9 @@ var Compressor = class {
353
353
  async callOpenAI(prompt, backend) {
354
354
  return this.callOpenAICompatible(prompt, backend);
355
355
  }
356
+ async callXAI(prompt, backend) {
357
+ return this.callOpenAICompatible(prompt, backend);
358
+ }
356
359
  async callOpenAICompatible(prompt, backend) {
357
360
  const baseUrl = backend.baseUrl ?? this.resolveBaseUrl(backend.provider);
358
361
  const response = await this.fetchImpl(this.buildOpenAICompatibleUrl(baseUrl), {
@@ -728,6 +731,125 @@ var Reflector = class {
728
731
  }
729
732
  };
730
733
 
734
+ // src/lib/llm-adapter.ts
735
+ var GEMINI_FLASH_MODEL = "gemini-2.0-flash";
736
+ var OLLAMA_DEFAULT_MODEL = "llama3.1:8b";
737
+ var OLLAMA_BASE_URL2 = "http://127.0.0.1:11434";
738
+ function createGeminiFlashAdapter(options = {}) {
739
+ const apiKey = process.env.GEMINI_API_KEY;
740
+ return {
741
+ async call(prompt) {
742
+ if (!apiKey) {
743
+ return "";
744
+ }
745
+ return requestLlmCompletion({
746
+ prompt,
747
+ provider: "gemini",
748
+ model: options.model ?? GEMINI_FLASH_MODEL,
749
+ temperature: options.temperature ?? 0.1,
750
+ maxTokens: options.maxTokens ?? 2e3,
751
+ fetchImpl: options.fetchImpl
752
+ });
753
+ },
754
+ isAvailable() {
755
+ return Boolean(apiKey);
756
+ },
757
+ getProvider() {
758
+ return apiKey ? "gemini" : null;
759
+ }
760
+ };
761
+ }
762
+ function createOllamaAdapter(options = {}) {
763
+ let _available = null;
764
+ const fetchFn = options.fetchImpl ?? globalThis.fetch;
765
+ return {
766
+ async call(prompt) {
767
+ const resp = await fetchFn(`${OLLAMA_BASE_URL2}/api/generate`, {
768
+ method: "POST",
769
+ headers: { "Content-Type": "application/json" },
770
+ body: JSON.stringify({
771
+ model: options.model ?? OLLAMA_DEFAULT_MODEL,
772
+ prompt,
773
+ stream: false,
774
+ options: {
775
+ temperature: options.temperature ?? 0.1,
776
+ num_predict: options.maxTokens ?? 2e3
777
+ }
778
+ })
779
+ });
780
+ if (!resp.ok) return "";
781
+ const data = await resp.json();
782
+ return data.response ?? "";
783
+ },
784
+ isAvailable() {
785
+ if (_available !== null) return _available;
786
+ _available = true;
787
+ return true;
788
+ },
789
+ getProvider() {
790
+ return null;
791
+ }
792
+ };
793
+ }
794
+ function createDefaultAdapter(options = {}) {
795
+ const resolvedProvider = options.provider !== void 0 ? options.provider : resolveLlmProvider();
796
+ return {
797
+ async call(prompt) {
798
+ if (!resolvedProvider) {
799
+ return "";
800
+ }
801
+ return requestLlmCompletion({
802
+ prompt,
803
+ provider: resolvedProvider,
804
+ model: options.model,
805
+ temperature: options.temperature ?? 0.1,
806
+ maxTokens: options.maxTokens ?? 2e3,
807
+ fetchImpl: options.fetchImpl
808
+ });
809
+ },
810
+ isAvailable() {
811
+ return resolvedProvider !== null;
812
+ },
813
+ getProvider() {
814
+ return resolvedProvider;
815
+ }
816
+ };
817
+ }
818
+ function createFactExtractionAdapter(options = {}) {
819
+ if (options.provider) {
820
+ return createDefaultAdapter(options);
821
+ }
822
+ const geminiAdapter = createGeminiFlashAdapter(options);
823
+ if (geminiAdapter.isAvailable()) {
824
+ return geminiAdapter;
825
+ }
826
+ const ollamaAdapter = createOllamaAdapter(options);
827
+ if (ollamaAdapter.isAvailable()) {
828
+ return ollamaAdapter;
829
+ }
830
+ return createDefaultAdapter(options);
831
+ }
832
+ function createLlmFunction(adapter) {
833
+ if (!adapter.isAvailable()) {
834
+ return void 0;
835
+ }
836
+ return (prompt) => adapter.call(prompt);
837
+ }
838
+ function resolveFactExtractionMode(configuredMode, adapter) {
839
+ const mode = configuredMode ?? "llm";
840
+ if (mode === "off") {
841
+ return { mode: "off", useLlm: false };
842
+ }
843
+ if (mode === "rule") {
844
+ return { mode: "rule", useLlm: false };
845
+ }
846
+ const llmAvailable = adapter?.isAvailable() ?? resolveLlmProvider() !== null;
847
+ if (mode === "llm" || mode === "hybrid") {
848
+ return { mode, useLlm: llmAvailable };
849
+ }
850
+ return { mode: "rule", useLlm: false };
851
+ }
852
+
731
853
  // src/observer/observer.ts
732
854
  import * as fs2 from "fs";
733
855
  import * as path2 from "path";
@@ -801,17 +923,41 @@ var FUTURE_TASK_HINT_RE = /\b(need to|should|todo|must|plan to)\b/i;
801
923
  var Router = class {
802
924
  vaultPath;
803
925
  extractTasks;
926
+ extractFacts;
927
+ factExtractionMode;
928
+ llmAdapter;
929
+ factStore;
804
930
  now;
805
931
  customRoutes;
806
932
  constructor(vaultPath, options = {}) {
807
933
  this.vaultPath = path.resolve(vaultPath);
808
934
  this.extractTasks = options.extractTasks ?? true;
935
+ this.extractFacts = options.extractFacts ?? true;
936
+ this.factExtractionMode = options.factExtractionMode ?? this.loadFactExtractionMode();
937
+ this.llmAdapter = options.llmAdapter ?? createFactExtractionAdapter();
938
+ this.factStore = new FactStore(this.vaultPath);
809
939
  this.now = options.now ?? (() => /* @__PURE__ */ new Date());
810
940
  this.customRoutes = this.loadCustomRoutes();
941
+ if (this.extractFacts && this.factExtractionMode !== "off") {
942
+ this.factStore.load();
943
+ }
944
+ }
945
+ loadFactExtractionMode() {
946
+ try {
947
+ const config = listConfig(this.vaultPath);
948
+ const observer = config.observer;
949
+ const mode = observer?.factExtractionMode;
950
+ if (mode === "off" || mode === "rule" || mode === "llm" || mode === "hybrid") {
951
+ return mode;
952
+ }
953
+ } catch {
954
+ }
955
+ return "llm";
811
956
  }
812
957
  /**
813
958
  * Takes observation markdown and routes items to appropriate vault categories.
814
959
  * Routes only items with importance >= 0.4.
960
+ * Also extracts structured facts from observations when fact extraction is enabled.
815
961
  * Returns a summary of what was routed where.
816
962
  */
817
963
  route(observationMarkdown, context = {}) {
@@ -821,6 +967,7 @@ var Router = class {
821
967
  const knownWorkItems = this.extractTasks ? this.loadExistingWorkItems() : [];
822
968
  const knownProjectDefinitions = this.loadKnownProjectDefinitions();
823
969
  let dedupHits = 0;
970
+ let factsExtracted = 0;
824
971
  for (const item of items) {
825
972
  if (item.importance < 0.4) continue;
826
973
  if (this.extractTasks && this.isTaskObservation(item.type)) {
@@ -847,8 +994,81 @@ var Router = class {
847
994
  routed.push(routedItem);
848
995
  this.appendToCategory(category, routedItem, knownProjectDefinitions);
849
996
  }
850
- const summary = this.buildSummary(routed, dedupHits);
851
- return { routed, summary };
997
+ if (this.extractFacts && this.factExtractionMode !== "off") {
998
+ const extractedCount = this.extractAndStoreFacts(observationMarkdown, context);
999
+ factsExtracted = extractedCount;
1000
+ }
1001
+ const summary = this.buildSummary(routed, dedupHits, factsExtracted);
1002
+ return { routed, summary, factsExtracted };
1003
+ }
1004
+ /**
1005
+ * Extract facts from observation markdown and store them in the fact store.
1006
+ * Uses the configured extraction mode (rule-based, LLM, or hybrid).
1007
+ */
1008
+ extractAndStoreFacts(observationMarkdown, context) {
1009
+ const { mode, useLlm } = resolveFactExtractionMode(this.factExtractionMode, this.llmAdapter);
1010
+ if (mode === "off") {
1011
+ return 0;
1012
+ }
1013
+ const source = context.source ?? "observer";
1014
+ const timestamp = context.timestamp?.toISOString() ?? this.now().toISOString();
1015
+ let facts = [];
1016
+ if (mode === "rule" || !useLlm) {
1017
+ facts = extractFactsRuleBased(observationMarkdown, source, timestamp);
1018
+ } else if (mode === "llm") {
1019
+ const llmFn = createLlmFunction(this.llmAdapter);
1020
+ extractFactsLlm(observationMarkdown, source, timestamp, llmFn).then((llmFacts) => {
1021
+ if (llmFacts.length > 0) {
1022
+ this.factStore.addFacts(llmFacts);
1023
+ this.factStore.save();
1024
+ }
1025
+ }).catch(() => {
1026
+ const ruleFacts = extractFactsRuleBased(observationMarkdown, source, timestamp);
1027
+ if (ruleFacts.length > 0) {
1028
+ this.factStore.addFacts(ruleFacts);
1029
+ this.factStore.save();
1030
+ }
1031
+ });
1032
+ return 0;
1033
+ } else if (mode === "hybrid") {
1034
+ facts = extractFactsRuleBased(observationMarkdown, source, timestamp);
1035
+ const llmFn = createLlmFunction(this.llmAdapter);
1036
+ extractFactsLlm(observationMarkdown, source, timestamp, llmFn).then((llmFacts) => {
1037
+ const merged = this.mergeFacts(facts, llmFacts);
1038
+ if (merged.length > facts.length) {
1039
+ this.factStore.addFacts(merged.slice(facts.length));
1040
+ this.factStore.save();
1041
+ }
1042
+ }).catch(() => {
1043
+ });
1044
+ }
1045
+ if (facts.length > 0) {
1046
+ this.factStore.addFacts(facts);
1047
+ this.factStore.save();
1048
+ }
1049
+ return facts.length;
1050
+ }
1051
+ /**
1052
+ * Merge facts from rule-based and LLM extraction, deduplicating by entity+relation.
1053
+ */
1054
+ mergeFacts(ruleFacts, llmFacts) {
1055
+ const seen = /* @__PURE__ */ new Set();
1056
+ const merged = [];
1057
+ for (const fact of ruleFacts) {
1058
+ const key = `${fact.entityNorm}::${fact.relation}`;
1059
+ if (!seen.has(key)) {
1060
+ seen.add(key);
1061
+ merged.push(fact);
1062
+ }
1063
+ }
1064
+ for (const fact of llmFacts) {
1065
+ const key = `${fact.entityNorm}::${fact.relation}`;
1066
+ if (!seen.has(key)) {
1067
+ seen.add(key);
1068
+ merged.push(fact);
1069
+ }
1070
+ }
1071
+ return merged;
852
1072
  }
853
1073
  isTaskObservation(type) {
854
1074
  return type === "task" || type === "todo" || type === "commitment-unresolved";
@@ -1436,8 +1656,8 @@ ${entry}
1436
1656
  for (const bg of setA) if (setB.has(bg)) intersection++;
1437
1657
  return intersection / (setA.size + setB.size - intersection);
1438
1658
  }
1439
- buildSummary(routed, dedupHits) {
1440
- if (routed.length === 0) {
1659
+ buildSummary(routed, dedupHits, factsExtracted = 0) {
1660
+ if (routed.length === 0 && factsExtracted === 0) {
1441
1661
  if (dedupHits > 0) {
1442
1662
  return `No items routed to vault categories (dedup hits: ${dedupHits}).`;
1443
1663
  }
@@ -1448,7 +1668,17 @@ ${entry}
1448
1668
  byCat.set(item.category, (byCat.get(item.category) ?? 0) + 1);
1449
1669
  }
1450
1670
  const parts = [...byCat.entries()].map(([cat, count]) => `${cat}: ${count}`);
1451
- const suffix = dedupHits > 0 ? ` (dedup hits: ${dedupHits})` : "";
1671
+ const suffixParts = [];
1672
+ if (dedupHits > 0) {
1673
+ suffixParts.push(`dedup hits: ${dedupHits}`);
1674
+ }
1675
+ if (factsExtracted > 0) {
1676
+ suffixParts.push(`facts: ${factsExtracted}`);
1677
+ }
1678
+ const suffix = suffixParts.length > 0 ? ` (${suffixParts.join(", ")})` : "";
1679
+ if (routed.length === 0 && factsExtracted > 0) {
1680
+ return `Extracted ${factsExtracted} facts${suffix}`;
1681
+ }
1452
1682
  return `Routed ${routed.length} observations \u2192 ${parts.join(", ")}${suffix}`;
1453
1683
  }
1454
1684
  };
@@ -1698,5 +1928,10 @@ var Observer = class {
1698
1928
  export {
1699
1929
  Compressor,
1700
1930
  Reflector,
1931
+ createGeminiFlashAdapter,
1932
+ createDefaultAdapter,
1933
+ createFactExtractionAdapter,
1934
+ createLlmFunction,
1935
+ resolveFactExtractionMode,
1701
1936
  Observer
1702
1937
  };