clawvault 3.1.0 → 3.2.0

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 (289) 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 +1368 -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-F2JEUD4J.js → chunk-23YDQ3QU.js} +6 -8
  22. package/dist/{chunk-C7OK5WKP.js → chunk-2JQ3O2YL.js} +4 -4
  23. package/dist/{chunk-VR5NE7PZ.js → chunk-2RAZ4ZFE.js} +1 -1
  24. package/dist/chunk-2ZDO52B4.js +52 -0
  25. package/dist/{chunk-ZZA73MFY.js → chunk-33DOSHTA.js} +176 -36
  26. package/dist/chunk-33VSQP4J.js +37 -0
  27. package/dist/chunk-4BQTQMJP.js +93 -0
  28. package/dist/{chunk-GUKMRGM7.js → chunk-4OXMU5S2.js} +1 -1
  29. package/dist/{chunk-62YTUT6J.js → chunk-4PY655YM.js} +15 -3
  30. package/dist/chunk-6FH3IULF.js +352 -0
  31. package/dist/{chunk-3NSBOUT3.js → chunk-77Q5CSPJ.js} +404 -80
  32. package/dist/{chunk-4VQTUVH7.js → chunk-7YZWHM36.js} +52 -26
  33. package/dist/chunk-BSJ6RIT7.js +447 -0
  34. package/dist/chunk-BUEW6IIK.js +364 -0
  35. package/dist/{chunk-LI4O6NVK.js → chunk-CLJTREDS.js} +74 -14
  36. package/dist/chunk-EK6S23ZB.js +469 -0
  37. package/dist/{chunk-LNJA2UGL.js → chunk-ESFLMDRB.js} +9 -86
  38. package/dist/{chunk-H34S76MB.js → chunk-ESVS6K2B.js} +6 -6
  39. package/dist/{chunk-WAZ3NLWL.js → chunk-F55HGNU4.js} +0 -47
  40. package/dist/{chunk-QK3UCXWL.js → chunk-FHFUXL6G.js} +2 -2
  41. package/dist/{chunk-H62BP7RI.js → chunk-GAOWA7GR.js} +212 -46
  42. package/dist/chunk-GGA32J2R.js +784 -0
  43. package/dist/chunk-GNJL4YGR.js +79 -0
  44. package/dist/chunk-IVRIKYFE.js +520 -0
  45. package/dist/chunk-MDIH26GC.js +183 -0
  46. package/dist/{chunk-LYHGEHXG.js → chunk-MFAWT5O5.js} +0 -1
  47. package/dist/chunk-MM6QGW3P.js +207 -0
  48. package/dist/{chunk-P5EPF6MB.js → chunk-MW5C6ZQA.js} +110 -13
  49. package/dist/chunk-NCKFNBHJ.js +257 -0
  50. package/dist/{chunk-QBLMXKF2.js → chunk-OIWVQYQF.js} +1 -1
  51. package/dist/{chunk-42MXU7A6.js → chunk-P62WHA27.js} +58 -47
  52. package/dist/chunk-PBACDKKP.js +66 -0
  53. package/dist/{chunk-VGLOTGAS.js → chunk-QSHD36LH.js} +2 -2
  54. package/dist/{chunk-OZ7RIXTO.js → chunk-QSRRMEYM.js} +2 -2
  55. package/dist/chunk-QVEERJSP.js +152 -0
  56. package/dist/{chunk-N2AXRYLC.js → chunk-QWQ3TIKS.js} +1 -1
  57. package/dist/{chunk-3DHXQHYG.js → chunk-R2MIW5G7.js} +1 -1
  58. package/dist/{chunk-SJSFRIYS.js → chunk-SLXOR3CC.js} +2 -2
  59. package/dist/chunk-SS4B7P7V.js +99 -0
  60. package/dist/{chunk-JY6FYXIT.js → chunk-STCQGCEQ.js} +6 -11
  61. package/dist/chunk-TIGW564L.js +628 -0
  62. package/dist/chunk-U4O6C46S.js +154 -0
  63. package/dist/{chunk-ITPEXLHA.js → chunk-URXDAUVH.js} +24 -5
  64. package/dist/chunk-VSL7KY3M.js +189 -0
  65. package/dist/{chunk-U55BGUAU.js → chunk-W4SPAEE7.js} +6 -6
  66. package/dist/chunk-WMGIIABP.js +15 -0
  67. package/dist/{chunk-33UGEQRT.js → chunk-X3SPPUFG.js} +151 -64
  68. package/dist/chunk-Y6VJKXGL.js +373 -0
  69. package/dist/{chunk-3WRJEKN4.js → chunk-ZN54U2OZ.js} +123 -10
  70. package/dist/cli/index.js +34 -24
  71. package/dist/commands/archive.js +3 -3
  72. package/dist/commands/backlog.js +3 -3
  73. package/dist/commands/blocked.js +3 -3
  74. package/dist/commands/canvas.d.ts +15 -0
  75. package/dist/commands/canvas.js +200 -0
  76. package/dist/commands/checkpoint.js +2 -2
  77. package/dist/commands/compat.js +2 -2
  78. package/dist/commands/context.js +8 -6
  79. package/dist/commands/doctor.d.ts +11 -7
  80. package/dist/commands/doctor.js +18 -16
  81. package/dist/commands/embed.js +5 -6
  82. package/dist/commands/entities.js +2 -2
  83. package/dist/commands/graph.js +4 -4
  84. package/dist/commands/inject.d.ts +1 -1
  85. package/dist/commands/inject.js +5 -6
  86. package/dist/commands/kanban.js +4 -4
  87. package/dist/commands/link.js +5 -5
  88. package/dist/commands/migrate-observations.js +4 -4
  89. package/dist/commands/observe.d.ts +0 -1
  90. package/dist/commands/observe.js +14 -13
  91. package/dist/commands/project.js +5 -5
  92. package/dist/commands/rebuild-embeddings.d.ts +21 -0
  93. package/dist/commands/rebuild-embeddings.js +91 -0
  94. package/dist/commands/rebuild.js +12 -11
  95. package/dist/commands/recover.js +3 -3
  96. package/dist/commands/reflect.js +6 -7
  97. package/dist/commands/repair-session.js +1 -1
  98. package/dist/commands/replay.js +14 -14
  99. package/dist/commands/session-recap.js +1 -1
  100. package/dist/commands/setup.d.ts +2 -89
  101. package/dist/commands/setup.js +3 -21
  102. package/dist/commands/shell-init.js +1 -1
  103. package/dist/commands/sleep.d.ts +1 -1
  104. package/dist/commands/sleep.js +20 -19
  105. package/dist/commands/status.d.ts +2 -0
  106. package/dist/commands/status.js +57 -35
  107. package/dist/commands/sync-bd.d.ts +10 -0
  108. package/dist/commands/sync-bd.js +10 -0
  109. package/dist/commands/tailscale.d.ts +52 -0
  110. package/dist/commands/tailscale.js +26 -0
  111. package/dist/commands/task.js +4 -4
  112. package/dist/commands/template.js +2 -2
  113. package/dist/commands/wake.d.ts +1 -1
  114. package/dist/commands/wake.js +11 -10
  115. package/dist/commands/workgraph.d.ts +124 -0
  116. package/dist/commands/workgraph.js +38 -0
  117. package/dist/index.d.ts +341 -191
  118. package/dist/index.js +446 -116
  119. package/dist/{inject-Bzi5E-By.d.ts → inject-DYUrDqQO.d.ts} +3 -3
  120. package/dist/ledger-B7g7jhqG.d.ts +44 -0
  121. package/dist/lib/auto-linker.js +2 -2
  122. package/dist/lib/canvas-layout.d.ts +115 -0
  123. package/dist/lib/canvas-layout.js +35 -0
  124. package/dist/lib/config.d.ts +27 -3
  125. package/dist/lib/config.js +4 -2
  126. package/dist/lib/entity-index.js +1 -1
  127. package/dist/lib/project-utils.js +4 -4
  128. package/dist/lib/session-repair.js +1 -1
  129. package/dist/lib/session-utils.js +1 -1
  130. package/dist/lib/tailscale.d.ts +225 -0
  131. package/dist/lib/tailscale.js +50 -0
  132. package/dist/lib/task-utils.js +3 -3
  133. package/dist/lib/template-engine.js +1 -1
  134. package/dist/lib/webdav.d.ts +109 -0
  135. package/dist/lib/webdav.js +35 -0
  136. package/dist/onnxruntime_binding-5QEF3SUC.node +0 -0
  137. package/dist/onnxruntime_binding-BKPKNEGC.node +0 -0
  138. package/dist/onnxruntime_binding-FMOXGIUT.node +0 -0
  139. package/dist/onnxruntime_binding-OI2KMXC5.node +0 -0
  140. package/dist/onnxruntime_binding-UX44MLAZ.node +0 -0
  141. package/dist/onnxruntime_binding-Y2W7N7WY.node +0 -0
  142. package/dist/openclaw-plugin.d.ts +8 -0
  143. package/dist/openclaw-plugin.js +14 -0
  144. package/dist/registry-BR4326o0.d.ts +30 -0
  145. package/dist/store-CA-6sKCJ.d.ts +34 -0
  146. package/dist/thread-B9LhXNU0.d.ts +41 -0
  147. package/dist/transformers.node-A2ZRORSQ.js +46775 -0
  148. package/dist/{types-Y2_Um2Ls.d.ts → types-BbWJoC1c.d.ts} +1 -44
  149. package/dist/workgraph/index.d.ts +5 -0
  150. package/dist/workgraph/index.js +23 -0
  151. package/dist/workgraph/ledger.d.ts +2 -0
  152. package/dist/workgraph/ledger.js +25 -0
  153. package/dist/workgraph/registry.d.ts +2 -0
  154. package/dist/workgraph/registry.js +19 -0
  155. package/dist/workgraph/store.d.ts +2 -0
  156. package/dist/workgraph/store.js +25 -0
  157. package/dist/workgraph/thread.d.ts +2 -0
  158. package/dist/workgraph/thread.js +25 -0
  159. package/dist/workgraph/types.d.ts +54 -0
  160. package/dist/workgraph/types.js +7 -0
  161. package/hooks/clawvault/HOOK.md +113 -0
  162. package/hooks/clawvault/handler.js +1561 -0
  163. package/hooks/clawvault/handler.test.js +510 -0
  164. package/hooks/clawvault/openclaw.plugin.json +72 -0
  165. package/openclaw.plugin.json +65 -38
  166. package/package.json +25 -22
  167. package/dist/chunk-3RG5ZIWI.js +0 -10
  168. package/dist/chunk-3ZIH425O.js +0 -871
  169. package/dist/chunk-6U6MK36V.js +0 -205
  170. package/dist/chunk-CMB7UL7C.js +0 -327
  171. package/dist/chunk-D2H45LON.js +0 -1074
  172. package/dist/chunk-E7MFQB6D.js +0 -163
  173. package/dist/chunk-GQSLDZTS.js +0 -560
  174. package/dist/chunk-MFM6K7PU.js +0 -374
  175. package/dist/chunk-MXSSG3QU.js +0 -42
  176. package/dist/chunk-OCGVIN3L.js +0 -88
  177. package/dist/chunk-PAH27GSN.js +0 -108
  178. package/dist/chunk-YCUNCH2I.js +0 -78
  179. package/dist/cli/index.cjs +0 -8584
  180. package/dist/cli/index.d.cts +0 -5
  181. package/dist/commands/archive.cjs +0 -287
  182. package/dist/commands/archive.d.cts +0 -11
  183. package/dist/commands/backlog.cjs +0 -721
  184. package/dist/commands/backlog.d.cts +0 -53
  185. package/dist/commands/blocked.cjs +0 -204
  186. package/dist/commands/blocked.d.cts +0 -26
  187. package/dist/commands/checkpoint.cjs +0 -244
  188. package/dist/commands/checkpoint.d.cts +0 -41
  189. package/dist/commands/compat.cjs +0 -294
  190. package/dist/commands/compat.d.cts +0 -28
  191. package/dist/commands/context.cjs +0 -2990
  192. package/dist/commands/context.d.cts +0 -2
  193. package/dist/commands/doctor.cjs +0 -2986
  194. package/dist/commands/doctor.d.cts +0 -21
  195. package/dist/commands/embed.cjs +0 -232
  196. package/dist/commands/embed.d.cts +0 -17
  197. package/dist/commands/entities.cjs +0 -141
  198. package/dist/commands/entities.d.cts +0 -7
  199. package/dist/commands/graph.cjs +0 -501
  200. package/dist/commands/graph.d.cts +0 -21
  201. package/dist/commands/inject.cjs +0 -1636
  202. package/dist/commands/inject.d.cts +0 -2
  203. package/dist/commands/kanban.cjs +0 -884
  204. package/dist/commands/kanban.d.cts +0 -63
  205. package/dist/commands/link.cjs +0 -965
  206. package/dist/commands/link.d.cts +0 -11
  207. package/dist/commands/migrate-observations.cjs +0 -362
  208. package/dist/commands/migrate-observations.d.cts +0 -19
  209. package/dist/commands/observe.cjs +0 -4099
  210. package/dist/commands/observe.d.cts +0 -23
  211. package/dist/commands/project.cjs +0 -1341
  212. package/dist/commands/project.d.cts +0 -85
  213. package/dist/commands/rebuild.cjs +0 -3136
  214. package/dist/commands/rebuild.d.cts +0 -11
  215. package/dist/commands/recover.cjs +0 -361
  216. package/dist/commands/recover.d.cts +0 -38
  217. package/dist/commands/reflect.cjs +0 -1008
  218. package/dist/commands/reflect.d.cts +0 -11
  219. package/dist/commands/repair-session.cjs +0 -457
  220. package/dist/commands/repair-session.d.cts +0 -38
  221. package/dist/commands/replay.cjs +0 -4103
  222. package/dist/commands/replay.d.cts +0 -16
  223. package/dist/commands/session-recap.cjs +0 -353
  224. package/dist/commands/session-recap.d.cts +0 -27
  225. package/dist/commands/setup.cjs +0 -1278
  226. package/dist/commands/setup.d.cts +0 -99
  227. package/dist/commands/shell-init.cjs +0 -75
  228. package/dist/commands/shell-init.d.cts +0 -7
  229. package/dist/commands/sleep.cjs +0 -6029
  230. package/dist/commands/sleep.d.cts +0 -36
  231. package/dist/commands/status.cjs +0 -2737
  232. package/dist/commands/status.d.cts +0 -52
  233. package/dist/commands/task.cjs +0 -1236
  234. package/dist/commands/task.d.cts +0 -97
  235. package/dist/commands/template.cjs +0 -457
  236. package/dist/commands/template.d.cts +0 -36
  237. package/dist/commands/wake.cjs +0 -2627
  238. package/dist/commands/wake.d.cts +0 -22
  239. package/dist/context-BUGaWpyL.d.cts +0 -46
  240. package/dist/index.cjs +0 -12373
  241. package/dist/index.d.cts +0 -854
  242. package/dist/inject-Bzi5E-By.d.cts +0 -137
  243. package/dist/lib/auto-linker.cjs +0 -176
  244. package/dist/lib/auto-linker.d.cts +0 -26
  245. package/dist/lib/config.cjs +0 -78
  246. package/dist/lib/config.d.cts +0 -11
  247. package/dist/lib/entity-index.cjs +0 -84
  248. package/dist/lib/entity-index.d.cts +0 -26
  249. package/dist/lib/project-utils.cjs +0 -864
  250. package/dist/lib/project-utils.d.cts +0 -97
  251. package/dist/lib/session-repair.cjs +0 -239
  252. package/dist/lib/session-repair.d.cts +0 -110
  253. package/dist/lib/session-utils.cjs +0 -209
  254. package/dist/lib/session-utils.d.cts +0 -63
  255. package/dist/lib/task-utils.cjs +0 -1137
  256. package/dist/lib/task-utils.d.cts +0 -208
  257. package/dist/lib/template-engine.cjs +0 -47
  258. package/dist/lib/template-engine.d.cts +0 -11
  259. package/dist/plugin/index.cjs +0 -1907
  260. package/dist/plugin/index.d.cts +0 -36
  261. package/dist/plugin/index.d.ts +0 -36
  262. package/dist/plugin/index.js +0 -572
  263. package/dist/plugin/inject.cjs +0 -356
  264. package/dist/plugin/inject.d.cts +0 -54
  265. package/dist/plugin/inject.d.ts +0 -54
  266. package/dist/plugin/inject.js +0 -17
  267. package/dist/plugin/observe.cjs +0 -631
  268. package/dist/plugin/observe.d.cts +0 -39
  269. package/dist/plugin/observe.d.ts +0 -39
  270. package/dist/plugin/observe.js +0 -18
  271. package/dist/plugin/templates.cjs +0 -593
  272. package/dist/plugin/templates.d.cts +0 -52
  273. package/dist/plugin/templates.d.ts +0 -52
  274. package/dist/plugin/templates.js +0 -25
  275. package/dist/plugin/types.cjs +0 -18
  276. package/dist/plugin/types.d.cts +0 -209
  277. package/dist/plugin/types.d.ts +0 -209
  278. package/dist/plugin/types.js +0 -0
  279. package/dist/plugin/vault.cjs +0 -927
  280. package/dist/plugin/vault.d.cts +0 -68
  281. package/dist/plugin/vault.d.ts +0 -68
  282. package/dist/plugin/vault.js +0 -22
  283. package/dist/types-Y2_Um2Ls.d.cts +0 -205
  284. package/templates/memory-event.md +0 -67
  285. package/templates/party.md +0 -63
  286. package/templates/primitive-registry.yaml +0 -551
  287. package/templates/run.md +0 -68
  288. package/templates/trigger.md +0 -68
  289. package/templates/workspace.md +0 -50
@@ -0,0 +1,257 @@
1
+ // src/lib/llm-provider.ts
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import * as os from "os";
5
+ var DEFAULT_MODELS = {
6
+ anthropic: "claude-3-5-haiku-latest",
7
+ openai: "gpt-4o-mini",
8
+ gemini: "gemini-2.0-flash",
9
+ xai: "grok-2-latest",
10
+ openclaw: "gpt-4o-mini"
11
+ };
12
+ var XAI_BASE_URL = "https://api.x.ai/v1";
13
+ function resolveOpenClawHome() {
14
+ return process.env.OPENCLAW_HOME?.trim() || path.join(os.homedir(), ".openclaw");
15
+ }
16
+ function resolveOpenClawGatewayProvider() {
17
+ try {
18
+ const configPath = path.join(resolveOpenClawHome(), "openclaw.json");
19
+ if (!fs.existsSync(configPath)) {
20
+ return null;
21
+ }
22
+ const raw = JSON.parse(fs.readFileSync(configPath, "utf-8"));
23
+ const enabled = raw.gateway?.http?.endpoints?.chatCompletions?.enabled === true;
24
+ const apiKey = raw.gateway?.auth?.token?.trim();
25
+ const port = raw.gateway?.port;
26
+ if (!enabled || !apiKey || typeof port !== "number" || !Number.isFinite(port) || port <= 0) {
27
+ return null;
28
+ }
29
+ const defaultModel = raw.agents?.defaults?.model?.trim() || DEFAULT_MODELS.openclaw;
30
+ const host = raw.gateway?.bind === "loopback" ? "127.0.0.1" : "127.0.0.1";
31
+ return {
32
+ baseUrl: `http://${host}:${port}/v1`,
33
+ apiKey,
34
+ api: "openai-completions",
35
+ defaultModel
36
+ };
37
+ } catch {
38
+ return null;
39
+ }
40
+ }
41
+ function resolveOpenClawProvider() {
42
+ const gatewayProvider = resolveOpenClawGatewayProvider();
43
+ if (gatewayProvider) {
44
+ return gatewayProvider;
45
+ }
46
+ try {
47
+ const modelsPath = path.join(resolveOpenClawHome(), "agents", "main", "agent", "models.json");
48
+ if (!fs.existsSync(modelsPath)) {
49
+ return null;
50
+ }
51
+ const raw = JSON.parse(fs.readFileSync(modelsPath, "utf-8"));
52
+ if (!raw.providers || typeof raw.providers !== "object") {
53
+ return null;
54
+ }
55
+ for (const [, provider] of Object.entries(raw.providers)) {
56
+ if (provider.baseUrl && provider.apiKey) {
57
+ const defaultModel = provider.models?.[0]?.id ?? "gpt-4o-mini";
58
+ return {
59
+ baseUrl: provider.baseUrl.replace(/\/+$/, ""),
60
+ apiKey: provider.apiKey,
61
+ api: provider.api ?? "openai-completions",
62
+ defaultModel
63
+ };
64
+ }
65
+ }
66
+ } catch {
67
+ }
68
+ return null;
69
+ }
70
+ function resolveLlmProvider() {
71
+ if (process.env.CLAWVAULT_NO_LLM) {
72
+ return null;
73
+ }
74
+ if (resolveOpenClawProvider()) {
75
+ return "openclaw";
76
+ }
77
+ if (process.env.ANTHROPIC_API_KEY) {
78
+ return "anthropic";
79
+ }
80
+ if (process.env.OPENAI_API_KEY) {
81
+ return "openai";
82
+ }
83
+ if (process.env.GEMINI_API_KEY) {
84
+ return "gemini";
85
+ }
86
+ if (process.env.XAI_API_KEY) {
87
+ return "xai";
88
+ }
89
+ return null;
90
+ }
91
+ async function requestLlmCompletion(options) {
92
+ const provider = options.provider ?? resolveLlmProvider();
93
+ if (!provider) {
94
+ return "";
95
+ }
96
+ if (provider === "openclaw") {
97
+ return callOpenClaw(options);
98
+ }
99
+ if (provider === "anthropic") {
100
+ return callAnthropic(options, provider);
101
+ }
102
+ if (provider === "gemini") {
103
+ return callGemini(options, provider);
104
+ }
105
+ if (provider === "xai") {
106
+ return callXAI(options, provider);
107
+ }
108
+ return callOpenAI(options, provider);
109
+ }
110
+ async function callAnthropic(options, provider) {
111
+ const apiKey = process.env.ANTHROPIC_API_KEY;
112
+ if (!apiKey) {
113
+ return "";
114
+ }
115
+ const fetchImpl = options.fetchImpl ?? fetch;
116
+ const response = await fetchImpl("https://api.anthropic.com/v1/messages", {
117
+ method: "POST",
118
+ headers: {
119
+ "content-type": "application/json",
120
+ "x-api-key": apiKey,
121
+ "anthropic-version": "2023-06-01"
122
+ },
123
+ body: JSON.stringify({
124
+ model: options.model ?? DEFAULT_MODELS[provider],
125
+ temperature: options.temperature ?? 0.1,
126
+ max_tokens: options.maxTokens ?? 1200,
127
+ messages: [{ role: "user", content: options.prompt }]
128
+ })
129
+ });
130
+ if (!response.ok) {
131
+ throw new Error(`Anthropic request failed (${response.status})`);
132
+ }
133
+ const payload = await response.json();
134
+ return payload.content?.filter((entry) => entry.type === "text" && entry.text).map((entry) => entry.text).join("\n").trim() ?? "";
135
+ }
136
+ async function callOpenAI(options, provider) {
137
+ const apiKey = process.env.OPENAI_API_KEY;
138
+ if (!apiKey) {
139
+ return "";
140
+ }
141
+ const fetchImpl = options.fetchImpl ?? fetch;
142
+ const messages = [];
143
+ if (options.systemPrompt?.trim()) {
144
+ messages.push({ role: "system", content: options.systemPrompt.trim() });
145
+ }
146
+ messages.push({ role: "user", content: options.prompt });
147
+ const response = await fetchImpl("https://api.openai.com/v1/chat/completions", {
148
+ method: "POST",
149
+ headers: {
150
+ "content-type": "application/json",
151
+ authorization: `Bearer ${apiKey}`
152
+ },
153
+ body: JSON.stringify({
154
+ model: options.model ?? DEFAULT_MODELS[provider],
155
+ temperature: options.temperature ?? 0.1,
156
+ max_tokens: options.maxTokens ?? 1200,
157
+ messages
158
+ })
159
+ });
160
+ if (!response.ok) {
161
+ throw new Error(`OpenAI request failed (${response.status})`);
162
+ }
163
+ const payload = await response.json();
164
+ return payload.choices?.[0]?.message?.content?.trim() ?? "";
165
+ }
166
+ async function callXAI(options, provider) {
167
+ const apiKey = process.env.XAI_API_KEY;
168
+ if (!apiKey) {
169
+ return "";
170
+ }
171
+ const fetchImpl = options.fetchImpl ?? fetch;
172
+ const messages = [];
173
+ if (options.systemPrompt?.trim()) {
174
+ messages.push({ role: "system", content: options.systemPrompt.trim() });
175
+ }
176
+ messages.push({ role: "user", content: options.prompt });
177
+ const response = await fetchImpl(`${XAI_BASE_URL}/chat/completions`, {
178
+ method: "POST",
179
+ headers: {
180
+ "content-type": "application/json",
181
+ authorization: `Bearer ${apiKey}`
182
+ },
183
+ body: JSON.stringify({
184
+ model: options.model ?? DEFAULT_MODELS[provider],
185
+ temperature: options.temperature ?? 0.1,
186
+ max_tokens: options.maxTokens ?? 1200,
187
+ messages
188
+ })
189
+ });
190
+ if (!response.ok) {
191
+ throw new Error(`xAI request failed (${response.status})`);
192
+ }
193
+ const payload = await response.json();
194
+ return payload.choices?.[0]?.message?.content?.trim() ?? "";
195
+ }
196
+ async function callGemini(options, provider) {
197
+ const apiKey = process.env.GEMINI_API_KEY;
198
+ if (!apiKey) {
199
+ return "";
200
+ }
201
+ const fetchImpl = options.fetchImpl ?? fetch;
202
+ const model = options.model ?? DEFAULT_MODELS[provider];
203
+ const response = await fetchImpl(
204
+ `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent`,
205
+ {
206
+ method: "POST",
207
+ headers: { "content-type": "application/json", "x-goog-api-key": apiKey },
208
+ body: JSON.stringify({
209
+ contents: [{ parts: [{ text: options.prompt }] }],
210
+ generationConfig: {
211
+ temperature: options.temperature ?? 0.1,
212
+ maxOutputTokens: options.maxTokens ?? 1200
213
+ }
214
+ })
215
+ }
216
+ );
217
+ if (!response.ok) {
218
+ throw new Error(`Gemini request failed (${response.status})`);
219
+ }
220
+ const payload = await response.json();
221
+ return payload.candidates?.[0]?.content?.parts?.[0]?.text?.trim() ?? "";
222
+ }
223
+ async function callOpenClaw(options) {
224
+ const config = resolveOpenClawProvider();
225
+ if (!config) {
226
+ return "";
227
+ }
228
+ const fetchImpl = options.fetchImpl ?? fetch;
229
+ const messages = [];
230
+ if (options.systemPrompt?.trim()) {
231
+ messages.push({ role: "system", content: options.systemPrompt.trim() });
232
+ }
233
+ messages.push({ role: "user", content: options.prompt });
234
+ const response = await fetchImpl(`${config.baseUrl}/chat/completions`, {
235
+ method: "POST",
236
+ headers: {
237
+ "content-type": "application/json",
238
+ authorization: `Bearer ${config.apiKey}`
239
+ },
240
+ body: JSON.stringify({
241
+ model: options.model ?? config.defaultModel,
242
+ temperature: options.temperature ?? 0.1,
243
+ max_tokens: options.maxTokens ?? 1200,
244
+ messages
245
+ })
246
+ });
247
+ if (!response.ok) {
248
+ throw new Error(`OpenClaw provider request failed (${response.status})`);
249
+ }
250
+ const payload = await response.json();
251
+ return payload.choices?.[0]?.message?.content?.trim() ?? "";
252
+ }
253
+
254
+ export {
255
+ resolveLlmProvider,
256
+ requestLlmCompletion
257
+ };
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  checkDirtyDeath,
6
6
  clearDirtyFlag
7
- } from "./chunk-WAZ3NLWL.js";
7
+ } from "./chunk-F55HGNU4.js";
8
8
 
9
9
  // src/commands/recover.ts
10
10
  import * as fs from "fs";
@@ -14,7 +14,7 @@ function findProtectedRanges(content) {
14
14
  while ((match = codeBlockRegex.exec(content)) !== null) {
15
15
  ranges.push({ start: match.index, end: match.index + match[0].length });
16
16
  }
17
- const inlineCodeRegex = /`[^`]+`/g;
17
+ const inlineCodeRegex = /(?<!`)`[^`\n]+`(?!`)/g;
18
18
  while ((match = inlineCodeRegex.exec(content)) !== null) {
19
19
  ranges.push({ start: match.index, end: match.index + match[0].length });
20
20
  }
@@ -26,10 +26,51 @@ function findProtectedRanges(content) {
26
26
  while ((match = urlRegex.exec(content)) !== null) {
27
27
  ranges.push({ start: match.index, end: match.index + match[0].length });
28
28
  }
29
+ const filePathRegex = /(?:^|[\s([{"'])((?:~|\/)[^\s`<>\])}"']+|[A-Za-z]:\\[^\s`<>\])}"']+)/g;
30
+ while ((match = filePathRegex.exec(content)) !== null) {
31
+ const fullMatch = match[0];
32
+ const pathValue = match[1];
33
+ const start = match.index + fullMatch.indexOf(pathValue);
34
+ ranges.push({ start, end: start + pathValue.length });
35
+ }
29
36
  return ranges;
30
37
  }
31
- function isProtected(pos, ranges) {
32
- return ranges.some((r) => pos >= r.start && pos < r.end);
38
+ function isProtectedRange(start, end, ranges) {
39
+ return ranges.some((range) => start < range.end && end > range.start);
40
+ }
41
+ function createAliasRegex(alias) {
42
+ const escapedAlias = alias.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
43
+ return new RegExp(`\\b${escapedAlias}\\b`, "gi");
44
+ }
45
+ function formatWikiLink(path, originalText) {
46
+ return originalText.toLowerCase() === path.split("/").pop()?.toLowerCase() ? `[[${path}]]` : `[[${path}|${originalText}]]`;
47
+ }
48
+ function planLinks(content, index, protectedRanges) {
49
+ const sortedAliases = getSortedAliases(index);
50
+ const linkedEntities = /* @__PURE__ */ new Set();
51
+ const claimedRanges = [];
52
+ const plannedLinks = [];
53
+ for (const { alias, path } of sortedAliases) {
54
+ if (linkedEntities.has(path)) continue;
55
+ const regex = createAliasRegex(alias);
56
+ let match;
57
+ while ((match = regex.exec(content)) !== null) {
58
+ const start = match.index;
59
+ const end = start + match[0].length;
60
+ if (isProtectedRange(start, end, protectedRanges)) continue;
61
+ if (isProtectedRange(start, end, claimedRanges)) continue;
62
+ plannedLinks.push({
63
+ start,
64
+ end,
65
+ originalText: match[0],
66
+ path
67
+ });
68
+ claimedRanges.push({ start, end });
69
+ linkedEntities.add(path);
70
+ break;
71
+ }
72
+ }
73
+ return plannedLinks;
33
74
  }
34
75
  function createLineLookup(content) {
35
76
  const lines = content.split("\n");
@@ -48,56 +89,24 @@ function createLineLookup(content) {
48
89
  }
49
90
  function autoLink(content, index) {
50
91
  const protectedRanges = findProtectedRanges(content);
51
- const sortedAliases = getSortedAliases(index);
52
- const linkedEntities = /* @__PURE__ */ new Set();
92
+ const plannedLinks = planLinks(content, index, protectedRanges);
53
93
  let result = content;
54
- let offset = 0;
55
- for (const { alias, path } of sortedAliases) {
56
- if (linkedEntities.has(path)) continue;
57
- const escapedAlias = alias.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
58
- const regex = new RegExp(`\\b${escapedAlias}\\b`, "gi");
59
- let match;
60
- while ((match = regex.exec(content)) !== null) {
61
- const originalPos = match.index;
62
- const adjustedPos = originalPos + offset;
63
- if (isProtected(originalPos, protectedRanges)) continue;
64
- const beforeMatch = result.substring(0, adjustedPos);
65
- const openBrackets = (beforeMatch.match(/\[\[/g) || []).length;
66
- const closeBrackets = (beforeMatch.match(/\]\]/g) || []).length;
67
- if (openBrackets > closeBrackets) continue;
68
- const originalText = match[0];
69
- const replacement = originalText.toLowerCase() === path.split("/").pop()?.toLowerCase() ? `[[${path}]]` : `[[${path}|${originalText}]]`;
70
- result = result.substring(0, adjustedPos) + replacement + result.substring(adjustedPos + originalText.length);
71
- offset += replacement.length - originalText.length;
72
- linkedEntities.add(path);
73
- break;
74
- }
94
+ const sortedByPosition = plannedLinks.slice().sort((a, b) => b.start - a.start);
95
+ for (const planned of sortedByPosition) {
96
+ const replacement = formatWikiLink(planned.path, planned.originalText);
97
+ result = result.substring(0, planned.start) + replacement + result.substring(planned.end);
75
98
  }
76
99
  return result;
77
100
  }
78
101
  function dryRunLink(content, index) {
79
102
  const protectedRanges = findProtectedRanges(content);
80
- const sortedAliases = getSortedAliases(index);
81
- const linkedEntities = /* @__PURE__ */ new Set();
82
- const matches = [];
103
+ const plannedLinks = planLinks(content, index, protectedRanges);
83
104
  const getLineNumber = createLineLookup(content);
84
- for (const { alias, path } of sortedAliases) {
85
- if (linkedEntities.has(path)) continue;
86
- const escapedAlias = alias.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
87
- const regex = new RegExp(`\\b${escapedAlias}\\b`, "gi");
88
- let match;
89
- while ((match = regex.exec(content)) !== null) {
90
- if (isProtected(match.index, protectedRanges)) continue;
91
- matches.push({
92
- alias: match[0],
93
- path,
94
- line: getLineNumber(match.index)
95
- });
96
- linkedEntities.add(path);
97
- break;
98
- }
99
- }
100
- return matches;
105
+ return plannedLinks.map((planned) => ({
106
+ alias: planned.originalText,
107
+ path: planned.path,
108
+ line: getLineNumber(planned.start)
109
+ }));
101
110
  }
102
111
  function findUnlinkedMentions(content, index) {
103
112
  const protectedRanges = findProtectedRanges(content);
@@ -111,7 +120,9 @@ function findUnlinkedMentions(content, index) {
111
120
  const regex = new RegExp(`\\b${escapedAlias}\\b`, "gi");
112
121
  let match;
113
122
  while ((match = regex.exec(content)) !== null) {
114
- if (isProtected(match.index, protectedRanges)) continue;
123
+ const start = match.index;
124
+ const end = start + match[0].length;
125
+ if (isProtectedRange(start, end, protectedRanges)) continue;
115
126
  matches.push({
116
127
  alias: match[0],
117
128
  path,
@@ -0,0 +1,66 @@
1
+ import {
2
+ loadVaultQmdConfig,
3
+ recoverQmdEmbeddingIfNeeded,
4
+ runCrashSafeQmdEmbed
5
+ } from "./chunk-6FH3IULF.js";
6
+ import {
7
+ QmdUnavailableError,
8
+ hasQmd
9
+ } from "./chunk-EK6S23ZB.js";
10
+ import {
11
+ resolveVaultPath
12
+ } from "./chunk-GNJL4YGR.js";
13
+
14
+ // src/commands/embed.ts
15
+ async function embedCommand(options = {}) {
16
+ if (!hasQmd()) {
17
+ throw new QmdUnavailableError();
18
+ }
19
+ const vaultPath = resolveVaultPath({ explicitPath: options.vaultPath });
20
+ const qmdConfig = loadVaultQmdConfig(vaultPath);
21
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
22
+ const recovery = recoverQmdEmbeddingIfNeeded({
23
+ vaultPath,
24
+ collection: qmdConfig.qmdCollection,
25
+ rootPath: qmdConfig.qmdRoot,
26
+ mode: "marker-or-empty",
27
+ onLog: options.quiet ? void 0 : (message) => console.log(message)
28
+ });
29
+ if (!options.quiet && recovery.recovered) {
30
+ const reasonLabel = recovery.reason === "interrupted_wal" ? "interrupted run" : "empty vector state";
31
+ console.log(`\u2713 Automatic qmd recovery completed (${reasonLabel}).`);
32
+ }
33
+ if (!options.quiet) {
34
+ console.log(
35
+ `Embedding pending documents for collection "${qmdConfig.qmdCollection}" (root: ${qmdConfig.qmdRoot})...`
36
+ );
37
+ }
38
+ runCrashSafeQmdEmbed({
39
+ vaultPath,
40
+ collection: qmdConfig.qmdCollection,
41
+ rootPath: qmdConfig.qmdRoot
42
+ });
43
+ const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
44
+ if (!options.quiet) {
45
+ console.log(`\u2713 Embedding complete for "${qmdConfig.qmdCollection}"`);
46
+ }
47
+ return {
48
+ vaultPath,
49
+ qmdCollection: qmdConfig.qmdCollection,
50
+ qmdRoot: qmdConfig.qmdRoot,
51
+ startedAt,
52
+ finishedAt
53
+ };
54
+ }
55
+ function registerEmbedCommand(program) {
56
+ program.command("embed").description("Run qmd embedding for pending vault documents").option("-v, --vault <path>", "Vault path").action(async (rawOptions) => {
57
+ await embedCommand({
58
+ vaultPath: rawOptions.vault
59
+ });
60
+ });
61
+ }
62
+
63
+ export {
64
+ embedCommand,
65
+ registerEmbedCommand
66
+ };
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  Observer
3
- } from "./chunk-3NSBOUT3.js";
3
+ } from "./chunk-77Q5CSPJ.js";
4
4
  import {
5
5
  resolveVaultPath
6
- } from "./chunk-MXSSG3QU.js";
6
+ } from "./chunk-GNJL4YGR.js";
7
7
  import {
8
8
  getLegacyObservationPath,
9
9
  getObservationPath,
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  resolveVaultPath
3
- } from "./chunk-MXSSG3QU.js";
3
+ } from "./chunk-GNJL4YGR.js";
4
4
  import {
5
5
  buildOrUpdateMemoryGraphIndex,
6
6
  loadMemoryGraphIndex
7
- } from "./chunk-ZZA73MFY.js";
7
+ } from "./chunk-33DOSHTA.js";
8
8
 
9
9
  // src/commands/graph.ts
10
10
  function formatGraphSummary(summary) {
@@ -0,0 +1,152 @@
1
+ import {
2
+ append
3
+ } from "./chunk-4BQTQMJP.js";
4
+ import {
5
+ getType,
6
+ loadRegistry
7
+ } from "./chunk-MM6QGW3P.js";
8
+ import {
9
+ __export
10
+ } from "./chunk-2ZDO52B4.js";
11
+
12
+ // src/workgraph/store.ts
13
+ var store_exports = {};
14
+ __export(store_exports, {
15
+ activeThreads: () => activeThreads,
16
+ blockedThreads: () => blockedThreads,
17
+ create: () => create,
18
+ findByField: () => findByField,
19
+ list: () => list,
20
+ openThreads: () => openThreads,
21
+ read: () => read,
22
+ remove: () => remove,
23
+ update: () => update
24
+ });
25
+ import fs from "fs";
26
+ import path from "path";
27
+ import matter from "gray-matter";
28
+ function create(vaultPath, typeName, fields, body, actor) {
29
+ const typeDef = getType(vaultPath, typeName);
30
+ if (!typeDef) {
31
+ throw new Error(`Unknown primitive type "${typeName}". Run \`clawvault primitive list\` to see available types, or \`clawvault primitive define\` to create one.`);
32
+ }
33
+ const now = (/* @__PURE__ */ new Date()).toISOString();
34
+ const merged = applyDefaults(typeDef, {
35
+ ...fields,
36
+ created: fields.created ?? now,
37
+ updated: now
38
+ });
39
+ const slug = slugify(String(merged.title ?? merged.name ?? typeName));
40
+ const relDir = typeDef.directory;
41
+ const relPath = `${relDir}/${slug}.md`;
42
+ const absDir = path.join(vaultPath, relDir);
43
+ const absPath = path.join(vaultPath, relPath);
44
+ if (!fs.existsSync(absDir)) fs.mkdirSync(absDir, { recursive: true });
45
+ if (fs.existsSync(absPath)) {
46
+ throw new Error(`File already exists: ${relPath}. Use update instead.`);
47
+ }
48
+ const content = matter.stringify(body, stripUndefined(merged));
49
+ fs.writeFileSync(absPath, content, "utf-8");
50
+ append(vaultPath, actor, "create", relPath, typeName, {
51
+ title: merged.title ?? slug
52
+ });
53
+ return { path: relPath, type: typeName, fields: merged, body };
54
+ }
55
+ function read(vaultPath, relPath) {
56
+ const absPath = path.join(vaultPath, relPath);
57
+ if (!fs.existsSync(absPath)) return null;
58
+ const raw = fs.readFileSync(absPath, "utf-8");
59
+ const { data, content } = matter(raw);
60
+ const typeName = inferType(vaultPath, relPath);
61
+ return { path: relPath, type: typeName, fields: data, body: content.trim() };
62
+ }
63
+ function list(vaultPath, typeName) {
64
+ const typeDef = getType(vaultPath, typeName);
65
+ if (!typeDef) return [];
66
+ const dir = path.join(vaultPath, typeDef.directory);
67
+ if (!fs.existsSync(dir)) return [];
68
+ const files = fs.readdirSync(dir).filter((f) => f.endsWith(".md"));
69
+ const instances = [];
70
+ for (const file of files) {
71
+ const relPath = `${typeDef.directory}/${file}`;
72
+ const inst = read(vaultPath, relPath);
73
+ if (inst) instances.push(inst);
74
+ }
75
+ return instances;
76
+ }
77
+ function update(vaultPath, relPath, fieldUpdates, bodyUpdate, actor) {
78
+ const existing = read(vaultPath, relPath);
79
+ if (!existing) throw new Error(`Not found: ${relPath}`);
80
+ const now = (/* @__PURE__ */ new Date()).toISOString();
81
+ const newFields = { ...existing.fields, ...fieldUpdates, updated: now };
82
+ const newBody = bodyUpdate ?? existing.body;
83
+ const absPath = path.join(vaultPath, relPath);
84
+ const content = matter.stringify(newBody, stripUndefined(newFields));
85
+ fs.writeFileSync(absPath, content, "utf-8");
86
+ append(vaultPath, actor, "update", relPath, existing.type, {
87
+ changed: Object.keys(fieldUpdates)
88
+ });
89
+ return { path: relPath, type: existing.type, fields: newFields, body: newBody };
90
+ }
91
+ function remove(vaultPath, relPath, actor) {
92
+ const absPath = path.join(vaultPath, relPath);
93
+ if (!fs.existsSync(absPath)) throw new Error(`Not found: ${relPath}`);
94
+ const archiveDir = path.join(vaultPath, ".clawvault", "archive");
95
+ if (!fs.existsSync(archiveDir)) fs.mkdirSync(archiveDir, { recursive: true });
96
+ const archivePath = path.join(archiveDir, path.basename(relPath));
97
+ fs.renameSync(absPath, archivePath);
98
+ const typeName = inferType(vaultPath, relPath);
99
+ append(vaultPath, actor, "delete", relPath, typeName);
100
+ }
101
+ function findByField(vaultPath, typeName, field, value) {
102
+ return list(vaultPath, typeName).filter((inst) => inst.fields[field] === value);
103
+ }
104
+ function openThreads(vaultPath) {
105
+ return findByField(vaultPath, "thread", "status", "open");
106
+ }
107
+ function activeThreads(vaultPath) {
108
+ return findByField(vaultPath, "thread", "status", "active");
109
+ }
110
+ function blockedThreads(vaultPath) {
111
+ return findByField(vaultPath, "thread", "status", "blocked");
112
+ }
113
+ function slugify(text) {
114
+ return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 80);
115
+ }
116
+ function applyDefaults(typeDef, fields) {
117
+ const result = { ...fields };
118
+ for (const [key, def] of Object.entries(typeDef.fields)) {
119
+ if (result[key] === void 0 && def.default !== void 0) {
120
+ result[key] = def.default;
121
+ }
122
+ }
123
+ return result;
124
+ }
125
+ function stripUndefined(obj) {
126
+ const result = {};
127
+ for (const [k, v] of Object.entries(obj)) {
128
+ if (v !== void 0) result[k] = v;
129
+ }
130
+ return result;
131
+ }
132
+ function inferType(vaultPath, relPath) {
133
+ const registry = loadRegistry(vaultPath);
134
+ const dir = relPath.split("/")[0];
135
+ for (const typeDef of Object.values(registry.types)) {
136
+ if (typeDef.directory === dir) return typeDef.name;
137
+ }
138
+ return "unknown";
139
+ }
140
+
141
+ export {
142
+ create,
143
+ read,
144
+ list,
145
+ update,
146
+ remove,
147
+ findByField,
148
+ openThreads,
149
+ activeThreads,
150
+ blockedThreads,
151
+ store_exports
152
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  loadSchemaTemplateDefinition,
3
3
  renderDocumentFromTemplate
4
- } from "./chunk-LYHGEHXG.js";
4
+ } from "./chunk-MFAWT5O5.js";
5
5
 
6
6
  // src/lib/task-utils.ts
7
7
  import * as fs2 from "fs";
@@ -8,7 +8,7 @@ import {
8
8
  queryTransitions,
9
9
  readTask,
10
10
  updateTask
11
- } from "./chunk-N2AXRYLC.js";
11
+ } from "./chunk-QWQ3TIKS.js";
12
12
 
13
13
  // src/commands/task.ts
14
14
  function taskAdd(vaultPath, title, options = {}) {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  runReflection
3
- } from "./chunk-H34S76MB.js";
3
+ } from "./chunk-ESVS6K2B.js";
4
4
  import {
5
5
  resolveVaultPath
6
- } from "./chunk-MXSSG3QU.js";
6
+ } from "./chunk-GNJL4YGR.js";
7
7
 
8
8
  // src/commands/reflect.ts
9
9
  function parsePositiveInteger(raw, label) {