clawvault 3.0.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 (291) hide show
  1. package/README.md +352 -20
  2. package/bin/clawvault.js +8 -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 -10
  6. package/bin/register-maintenance-commands.js +39 -3
  7. package/bin/register-query-commands.js +58 -29
  8. package/bin/register-task-commands.js +18 -1
  9. package/bin/register-task-commands.test.js +16 -0
  10. package/bin/register-vault-operations-commands.js +29 -1
  11. package/bin/register-workgraph-commands.js +1368 -0
  12. package/dashboard/lib/graph-diff.js +104 -0
  13. package/dashboard/lib/graph-diff.test.js +75 -0
  14. package/dashboard/lib/vault-parser.js +556 -0
  15. package/dashboard/lib/vault-parser.test.js +254 -0
  16. package/dashboard/public/app.js +796 -0
  17. package/dashboard/public/index.html +52 -0
  18. package/dashboard/public/styles.css +221 -0
  19. package/dashboard/server.js +374 -0
  20. package/dist/{chunk-F2JEUD4J.js → chunk-23YDQ3QU.js} +6 -8
  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-2ZDO52B4.js +52 -0
  24. package/dist/{chunk-ZZA73MFY.js → chunk-33DOSHTA.js} +176 -36
  25. package/dist/chunk-33VSQP4J.js +37 -0
  26. package/dist/chunk-4BQTQMJP.js +93 -0
  27. package/dist/{chunk-GUKMRGM7.js → chunk-4OXMU5S2.js} +1 -1
  28. package/dist/{chunk-62YTUT6J.js → chunk-4PY655YM.js} +15 -3
  29. package/dist/chunk-6FH3IULF.js +352 -0
  30. package/dist/{chunk-3NSBOUT3.js → chunk-77Q5CSPJ.js} +404 -80
  31. package/dist/{chunk-4VQTUVH7.js → chunk-7YZWHM36.js} +52 -26
  32. package/dist/chunk-BSJ6RIT7.js +447 -0
  33. package/dist/chunk-BUEW6IIK.js +364 -0
  34. package/dist/{chunk-WGRQ6HDV.js → chunk-CLJTREDS.js} +74 -14
  35. package/dist/chunk-EK6S23ZB.js +469 -0
  36. package/dist/{chunk-LNJA2UGL.js → chunk-ESFLMDRB.js} +9 -86
  37. package/dist/{chunk-H34S76MB.js → chunk-ESVS6K2B.js} +6 -6
  38. package/dist/{chunk-WAZ3NLWL.js → chunk-F55HGNU4.js} +0 -47
  39. package/dist/{chunk-QK3UCXWL.js → chunk-FHFUXL6G.js} +2 -2
  40. package/dist/{chunk-YKTA5JOJ.js → chunk-GAOWA7GR.js} +212 -46
  41. package/dist/chunk-GGA32J2R.js +784 -0
  42. package/dist/chunk-GNJL4YGR.js +79 -0
  43. package/dist/chunk-MDIH26GC.js +183 -0
  44. package/dist/{chunk-LYHGEHXG.js → chunk-MFAWT5O5.js} +0 -1
  45. package/dist/chunk-MM6QGW3P.js +207 -0
  46. package/dist/{chunk-P5EPF6MB.js → chunk-MW5C6ZQA.js} +110 -13
  47. package/dist/chunk-NCKFNBHJ.js +257 -0
  48. package/dist/{chunk-QBLMXKF2.js → chunk-OIWVQYQF.js} +1 -1
  49. package/dist/{chunk-42MXU7A6.js → chunk-P62WHA27.js} +58 -47
  50. package/dist/chunk-PBACDKKP.js +66 -0
  51. package/dist/{chunk-VGLOTGAS.js → chunk-QSHD36LH.js} +2 -2
  52. package/dist/{chunk-OZ7RIXTO.js → chunk-QSRRMEYM.js} +2 -2
  53. package/dist/chunk-QVEERJSP.js +152 -0
  54. package/dist/{chunk-N2AXRYLC.js → chunk-QWQ3TIKS.js} +1 -1
  55. package/dist/{chunk-3DHXQHYG.js → chunk-R2MIW5G7.js} +1 -1
  56. package/dist/{chunk-SJSFRIYS.js → chunk-SLXOR3CC.js} +2 -2
  57. package/dist/chunk-SS4B7P7V.js +99 -0
  58. package/dist/{chunk-JY6FYXIT.js → chunk-STCQGCEQ.js} +6 -11
  59. package/dist/chunk-U4O6C46S.js +154 -0
  60. package/dist/{chunk-ITPEXLHA.js → chunk-URXDAUVH.js} +24 -5
  61. package/dist/chunk-VSL7KY3M.js +189 -0
  62. package/dist/{chunk-U55BGUAU.js → chunk-W4SPAEE7.js} +6 -6
  63. package/dist/chunk-WMGIIABP.js +15 -0
  64. package/dist/{chunk-3D6BCTP6.js → chunk-X3SPPUFG.js} +51 -39
  65. package/dist/{chunk-THRJVD4L.js → chunk-Y6VJKXGL.js} +1 -1
  66. package/dist/{chunk-ZVVFWOLW.js → chunk-ZN54U2OZ.js} +123 -10
  67. package/dist/cli/index.js +32 -25
  68. package/dist/commands/archive.js +3 -3
  69. package/dist/commands/backlog.js +3 -3
  70. package/dist/commands/blocked.js +3 -3
  71. package/dist/commands/canvas.d.ts +15 -0
  72. package/dist/commands/canvas.js +200 -0
  73. package/dist/commands/checkpoint.js +2 -2
  74. package/dist/commands/compat.js +2 -2
  75. package/dist/commands/context.js +8 -6
  76. package/dist/commands/doctor.d.ts +11 -7
  77. package/dist/commands/doctor.js +18 -16
  78. package/dist/commands/embed.js +5 -6
  79. package/dist/commands/entities.js +2 -2
  80. package/dist/commands/graph.js +4 -4
  81. package/dist/commands/inject.d.ts +1 -1
  82. package/dist/commands/inject.js +5 -6
  83. package/dist/commands/kanban.js +4 -4
  84. package/dist/commands/link.js +5 -5
  85. package/dist/commands/migrate-observations.js +4 -4
  86. package/dist/commands/observe.d.ts +0 -1
  87. package/dist/commands/observe.js +14 -13
  88. package/dist/commands/project.js +5 -5
  89. package/dist/commands/rebuild-embeddings.d.ts +21 -0
  90. package/dist/commands/rebuild-embeddings.js +91 -0
  91. package/dist/commands/rebuild.js +12 -11
  92. package/dist/commands/recover.js +3 -3
  93. package/dist/commands/reflect.js +6 -7
  94. package/dist/commands/repair-session.js +1 -1
  95. package/dist/commands/replay.js +14 -14
  96. package/dist/commands/session-recap.js +1 -1
  97. package/dist/commands/setup.d.ts +2 -90
  98. package/dist/commands/setup.js +3 -21
  99. package/dist/commands/shell-init.js +1 -1
  100. package/dist/commands/sleep.d.ts +1 -1
  101. package/dist/commands/sleep.js +20 -19
  102. package/dist/commands/status.d.ts +2 -0
  103. package/dist/commands/status.js +57 -35
  104. package/dist/commands/sync-bd.d.ts +10 -0
  105. package/dist/commands/sync-bd.js +10 -0
  106. package/dist/commands/tailscale.js +3 -3
  107. package/dist/commands/task.js +4 -4
  108. package/dist/commands/template.js +2 -2
  109. package/dist/commands/wake.d.ts +1 -1
  110. package/dist/commands/wake.js +11 -10
  111. package/dist/commands/workgraph.d.ts +124 -0
  112. package/dist/commands/workgraph.js +38 -0
  113. package/dist/index.d.ts +337 -191
  114. package/dist/index.js +387 -118
  115. package/dist/{inject-Bzi5E-By.d.cts → inject-DYUrDqQO.d.ts} +3 -3
  116. package/dist/ledger-B7g7jhqG.d.ts +44 -0
  117. package/dist/lib/auto-linker.js +2 -2
  118. package/dist/lib/canvas-layout.d.ts +100 -16
  119. package/dist/lib/canvas-layout.js +21 -78
  120. package/dist/lib/config.d.ts +27 -3
  121. package/dist/lib/config.js +4 -2
  122. package/dist/lib/entity-index.js +1 -1
  123. package/dist/lib/project-utils.js +4 -4
  124. package/dist/lib/session-repair.js +1 -1
  125. package/dist/lib/session-utils.js +1 -1
  126. package/dist/lib/tailscale.js +1 -1
  127. package/dist/lib/task-utils.js +3 -3
  128. package/dist/lib/template-engine.js +1 -1
  129. package/dist/lib/webdav.js +1 -1
  130. package/dist/onnxruntime_binding-5QEF3SUC.node +0 -0
  131. package/dist/onnxruntime_binding-BKPKNEGC.node +0 -0
  132. package/dist/onnxruntime_binding-FMOXGIUT.node +0 -0
  133. package/dist/onnxruntime_binding-OI2KMXC5.node +0 -0
  134. package/dist/onnxruntime_binding-UX44MLAZ.node +0 -0
  135. package/dist/onnxruntime_binding-Y2W7N7WY.node +0 -0
  136. package/dist/openclaw-plugin.d.ts +8 -0
  137. package/dist/openclaw-plugin.js +14 -0
  138. package/dist/registry-BR4326o0.d.ts +30 -0
  139. package/dist/store-CA-6sKCJ.d.ts +34 -0
  140. package/dist/thread-B9LhXNU0.d.ts +41 -0
  141. package/dist/transformers.node-A2ZRORSQ.js +46775 -0
  142. package/dist/{types-Y2_Um2Ls.d.cts → types-BbWJoC1c.d.ts} +1 -44
  143. package/dist/workgraph/index.d.ts +5 -0
  144. package/dist/workgraph/index.js +23 -0
  145. package/dist/workgraph/ledger.d.ts +2 -0
  146. package/dist/workgraph/ledger.js +25 -0
  147. package/dist/workgraph/registry.d.ts +2 -0
  148. package/dist/workgraph/registry.js +19 -0
  149. package/dist/workgraph/store.d.ts +2 -0
  150. package/dist/workgraph/store.js +25 -0
  151. package/dist/workgraph/thread.d.ts +2 -0
  152. package/dist/workgraph/thread.js +25 -0
  153. package/dist/workgraph/types.d.ts +54 -0
  154. package/dist/workgraph/types.js +7 -0
  155. package/hooks/clawvault/HOOK.md +34 -4
  156. package/hooks/clawvault/handler.js +760 -78
  157. package/hooks/clawvault/handler.test.js +235 -79
  158. package/hooks/clawvault/openclaw.plugin.json +72 -0
  159. package/openclaw.plugin.json +65 -38
  160. package/package.json +15 -18
  161. package/dist/chunk-3RG5ZIWI.js +0 -10
  162. package/dist/chunk-6U6MK36V.js +0 -205
  163. package/dist/chunk-7R7O6STJ.js +0 -88
  164. package/dist/chunk-CMB7UL7C.js +0 -327
  165. package/dist/chunk-DEFFDRVP.js +0 -938
  166. package/dist/chunk-E7MFQB6D.js +0 -163
  167. package/dist/chunk-GAJV4IGR.js +0 -82
  168. package/dist/chunk-GQSLDZTS.js +0 -560
  169. package/dist/chunk-K234IDRJ.js +0 -1073
  170. package/dist/chunk-MFM6K7PU.js +0 -374
  171. package/dist/chunk-MXSSG3QU.js +0 -42
  172. package/dist/chunk-PAH27GSN.js +0 -108
  173. package/dist/cli/index.cjs +0 -10033
  174. package/dist/cli/index.d.cts +0 -5
  175. package/dist/commands/archive.cjs +0 -287
  176. package/dist/commands/archive.d.cts +0 -11
  177. package/dist/commands/backlog.cjs +0 -721
  178. package/dist/commands/backlog.d.cts +0 -53
  179. package/dist/commands/blocked.cjs +0 -204
  180. package/dist/commands/blocked.d.cts +0 -26
  181. package/dist/commands/checkpoint.cjs +0 -244
  182. package/dist/commands/checkpoint.d.cts +0 -41
  183. package/dist/commands/compat.cjs +0 -369
  184. package/dist/commands/compat.d.cts +0 -28
  185. package/dist/commands/context.cjs +0 -2989
  186. package/dist/commands/context.d.cts +0 -2
  187. package/dist/commands/doctor.cjs +0 -3062
  188. package/dist/commands/doctor.d.cts +0 -21
  189. package/dist/commands/embed.cjs +0 -232
  190. package/dist/commands/embed.d.cts +0 -17
  191. package/dist/commands/entities.cjs +0 -141
  192. package/dist/commands/entities.d.cts +0 -7
  193. package/dist/commands/graph.cjs +0 -501
  194. package/dist/commands/graph.d.cts +0 -21
  195. package/dist/commands/inject.cjs +0 -1636
  196. package/dist/commands/inject.d.cts +0 -2
  197. package/dist/commands/kanban.cjs +0 -884
  198. package/dist/commands/kanban.d.cts +0 -63
  199. package/dist/commands/link.cjs +0 -965
  200. package/dist/commands/link.d.cts +0 -11
  201. package/dist/commands/migrate-observations.cjs +0 -362
  202. package/dist/commands/migrate-observations.d.cts +0 -19
  203. package/dist/commands/observe.cjs +0 -4099
  204. package/dist/commands/observe.d.cts +0 -23
  205. package/dist/commands/project.cjs +0 -1341
  206. package/dist/commands/project.d.cts +0 -85
  207. package/dist/commands/rebuild.cjs +0 -3136
  208. package/dist/commands/rebuild.d.cts +0 -11
  209. package/dist/commands/recover.cjs +0 -361
  210. package/dist/commands/recover.d.cts +0 -38
  211. package/dist/commands/reflect.cjs +0 -1008
  212. package/dist/commands/reflect.d.cts +0 -11
  213. package/dist/commands/repair-session.cjs +0 -457
  214. package/dist/commands/repair-session.d.cts +0 -38
  215. package/dist/commands/replay.cjs +0 -4103
  216. package/dist/commands/replay.d.cts +0 -16
  217. package/dist/commands/session-recap.cjs +0 -353
  218. package/dist/commands/session-recap.d.cts +0 -27
  219. package/dist/commands/setup.cjs +0 -1345
  220. package/dist/commands/setup.d.cts +0 -100
  221. package/dist/commands/shell-init.cjs +0 -75
  222. package/dist/commands/shell-init.d.cts +0 -7
  223. package/dist/commands/sleep.cjs +0 -6028
  224. package/dist/commands/sleep.d.cts +0 -36
  225. package/dist/commands/status.cjs +0 -2736
  226. package/dist/commands/status.d.cts +0 -52
  227. package/dist/commands/tailscale.cjs +0 -1532
  228. package/dist/commands/tailscale.d.cts +0 -52
  229. package/dist/commands/task.cjs +0 -1236
  230. package/dist/commands/task.d.cts +0 -97
  231. package/dist/commands/template.cjs +0 -457
  232. package/dist/commands/template.d.cts +0 -36
  233. package/dist/commands/wake.cjs +0 -2626
  234. package/dist/commands/wake.d.cts +0 -22
  235. package/dist/context-BUGaWpyL.d.cts +0 -46
  236. package/dist/index.cjs +0 -14526
  237. package/dist/index.d.cts +0 -858
  238. package/dist/inject-Bzi5E-By.d.ts +0 -137
  239. package/dist/lib/auto-linker.cjs +0 -176
  240. package/dist/lib/auto-linker.d.cts +0 -26
  241. package/dist/lib/canvas-layout.cjs +0 -136
  242. package/dist/lib/canvas-layout.d.cts +0 -31
  243. package/dist/lib/config.cjs +0 -78
  244. package/dist/lib/config.d.cts +0 -11
  245. package/dist/lib/entity-index.cjs +0 -84
  246. package/dist/lib/entity-index.d.cts +0 -26
  247. package/dist/lib/project-utils.cjs +0 -864
  248. package/dist/lib/project-utils.d.cts +0 -97
  249. package/dist/lib/session-repair.cjs +0 -239
  250. package/dist/lib/session-repair.d.cts +0 -110
  251. package/dist/lib/session-utils.cjs +0 -209
  252. package/dist/lib/session-utils.d.cts +0 -63
  253. package/dist/lib/tailscale.cjs +0 -1183
  254. package/dist/lib/tailscale.d.cts +0 -225
  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/lib/webdav.cjs +0 -568
  260. package/dist/lib/webdav.d.cts +0 -109
  261. package/dist/plugin/index.cjs +0 -1907
  262. package/dist/plugin/index.d.cts +0 -36
  263. package/dist/plugin/index.d.ts +0 -36
  264. package/dist/plugin/index.js +0 -572
  265. package/dist/plugin/inject.cjs +0 -356
  266. package/dist/plugin/inject.d.cts +0 -54
  267. package/dist/plugin/inject.d.ts +0 -54
  268. package/dist/plugin/inject.js +0 -17
  269. package/dist/plugin/observe.cjs +0 -631
  270. package/dist/plugin/observe.d.cts +0 -39
  271. package/dist/plugin/observe.d.ts +0 -39
  272. package/dist/plugin/observe.js +0 -18
  273. package/dist/plugin/templates.cjs +0 -593
  274. package/dist/plugin/templates.d.cts +0 -52
  275. package/dist/plugin/templates.d.ts +0 -52
  276. package/dist/plugin/templates.js +0 -25
  277. package/dist/plugin/types.cjs +0 -18
  278. package/dist/plugin/types.d.cts +0 -209
  279. package/dist/plugin/types.d.ts +0 -209
  280. package/dist/plugin/types.js +0 -0
  281. package/dist/plugin/vault.cjs +0 -927
  282. package/dist/plugin/vault.d.cts +0 -68
  283. package/dist/plugin/vault.d.ts +0 -68
  284. package/dist/plugin/vault.js +0 -22
  285. package/dist/types-Y2_Um2Ls.d.ts +0 -205
  286. package/templates/memory-event.md +0 -67
  287. package/templates/party.md +0 -63
  288. package/templates/primitive-registry.yaml +0 -551
  289. package/templates/run.md +0 -68
  290. package/templates/trigger.md +0 -68
  291. package/templates/workspace.md +0 -50
@@ -1,864 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/lib/project-utils.ts
31
- var project_utils_exports = {};
32
- __export(project_utils_exports, {
33
- archiveProject: () => archiveProject,
34
- createProject: () => createProject,
35
- getProjectActivity: () => getProjectActivity,
36
- getProjectTasks: () => getProjectTasks,
37
- listProjects: () => listProjects,
38
- readProject: () => readProject,
39
- updateProject: () => updateProject
40
- });
41
- module.exports = __toCommonJS(project_utils_exports);
42
- var fs3 = __toESM(require("fs"), 1);
43
- var path3 = __toESM(require("path"), 1);
44
- var import_gray_matter3 = __toESM(require("gray-matter"), 1);
45
-
46
- // src/lib/task-utils.ts
47
- var fs2 = __toESM(require("fs"), 1);
48
- var path2 = __toESM(require("path"), 1);
49
- var import_gray_matter2 = __toESM(require("gray-matter"), 1);
50
-
51
- // src/lib/primitive-templates.ts
52
- var fs = __toESM(require("fs"), 1);
53
- var path = __toESM(require("path"), 1);
54
- var import_url = require("url");
55
- var import_gray_matter = __toESM(require("gray-matter"), 1);
56
-
57
- // src/lib/template-engine.ts
58
- function buildTemplateVariables(input = {}, now = /* @__PURE__ */ new Date()) {
59
- const datetime = input.datetime ?? now.toISOString();
60
- const date = input.date ?? datetime.split("T")[0];
61
- return {
62
- title: input.title ?? "",
63
- type: input.type ?? "",
64
- date,
65
- datetime
66
- };
67
- }
68
- function renderTemplate(template, variables) {
69
- return template.replace(/\{\{\s*([a-zA-Z0-9_-]+)\s*\}\}/g, (match, key) => {
70
- const value = variables[key];
71
- return value !== void 0 ? String(value) : match;
72
- });
73
- }
74
-
75
- // src/lib/primitive-templates.ts
76
- var import_meta = {};
77
- var TEMPLATE_EXTENSION = ".md";
78
- function isRecord(value) {
79
- return typeof value === "object" && value !== null && !Array.isArray(value);
80
- }
81
- function normalizeTemplateName(name) {
82
- const base = path.basename(name, path.extname(name));
83
- return base.trim();
84
- }
85
- function resolveBuiltinTemplatesDir(override) {
86
- if (override) {
87
- const resolved = path.resolve(override);
88
- return fs.existsSync(resolved) && fs.statSync(resolved).isDirectory() ? resolved : null;
89
- }
90
- const moduleDir = path.dirname((0, import_url.fileURLToPath)(import_meta.url));
91
- const candidates = [
92
- path.resolve(moduleDir, "../templates"),
93
- path.resolve(moduleDir, "../../templates")
94
- ];
95
- for (const candidate of candidates) {
96
- if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
97
- return candidate;
98
- }
99
- }
100
- return null;
101
- }
102
- function listTemplateFiles(dir, ignore) {
103
- const entries = /* @__PURE__ */ new Map();
104
- if (!fs.existsSync(dir)) return entries;
105
- for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
106
- if (!entry.isFile() || !entry.name.endsWith(TEMPLATE_EXTENSION)) continue;
107
- const name = normalizeTemplateName(entry.name);
108
- if (!name) continue;
109
- if (ignore?.has(name)) continue;
110
- entries.set(name, path.join(dir, entry.name));
111
- }
112
- return entries;
113
- }
114
- function buildTemplateIndex(options = {}) {
115
- const index = /* @__PURE__ */ new Map();
116
- const builtinDir = resolveBuiltinTemplatesDir(options.builtinDir);
117
- if (builtinDir) {
118
- for (const [name, filePath] of listTemplateFiles(builtinDir, options.ignoreBuiltinNames)) {
119
- index.set(name, filePath);
120
- }
121
- }
122
- if (options.vaultPath) {
123
- const vaultTemplatesDir = path.join(path.resolve(options.vaultPath), "templates");
124
- for (const [name, filePath] of listTemplateFiles(vaultTemplatesDir)) {
125
- index.set(name, filePath);
126
- }
127
- }
128
- return index;
129
- }
130
- function inferFieldType(defaultValue) {
131
- if (Array.isArray(defaultValue)) {
132
- const uniqueItemTypes = [...new Set(defaultValue.map((value) => typeof value))];
133
- if (uniqueItemTypes.length === 1 && uniqueItemTypes[0] === "string") {
134
- return "string[]";
135
- }
136
- return "array";
137
- }
138
- switch (typeof defaultValue) {
139
- case "string":
140
- return "string";
141
- case "number":
142
- return "number";
143
- case "boolean":
144
- return "boolean";
145
- case "object":
146
- if (defaultValue === null) return "string";
147
- return "object";
148
- default:
149
- return "string";
150
- }
151
- }
152
- function normalizeFieldDefinition(rawField) {
153
- if (!isRecord(rawField)) {
154
- return {
155
- type: inferFieldType(rawField),
156
- default: rawField
157
- };
158
- }
159
- const rawType = typeof rawField.type === "string" ? rawField.type.trim() : "";
160
- const normalized = {
161
- type: rawType || inferFieldType(rawField.default)
162
- };
163
- if (typeof rawField.description === "string" && rawField.description.trim()) {
164
- normalized.description = rawField.description.trim();
165
- }
166
- if (typeof rawField.required === "boolean") {
167
- normalized.required = rawField.required;
168
- }
169
- if (Object.prototype.hasOwnProperty.call(rawField, "default")) {
170
- normalized.default = rawField.default;
171
- }
172
- if (Array.isArray(rawField.enum)) {
173
- normalized.enum = rawField.enum;
174
- }
175
- return normalized;
176
- }
177
- function normalizeFieldDefinitions(rawFields) {
178
- const normalized = {};
179
- for (const [fieldName, rawField] of Object.entries(rawFields)) {
180
- const normalizedName = String(fieldName).trim();
181
- if (!normalizedName) continue;
182
- normalized[normalizedName] = normalizeFieldDefinition(rawField);
183
- }
184
- return normalized;
185
- }
186
- function extractSchemaDefinition(frontmatter) {
187
- const primitive = typeof frontmatter.primitive === "string" ? frontmatter.primitive.trim() : "";
188
- const description = typeof frontmatter.description === "string" ? frontmatter.description.trim() : void 0;
189
- if (primitive && isRecord(frontmatter.fields)) {
190
- return {
191
- primitive,
192
- description,
193
- fields: frontmatter.fields
194
- };
195
- }
196
- const containerCandidates = [frontmatter.schema, frontmatter.template];
197
- for (const candidate of containerCandidates) {
198
- if (!isRecord(candidate)) continue;
199
- const nestedPrimitive = typeof candidate.primitive === "string" ? candidate.primitive.trim() : primitive;
200
- if (!nestedPrimitive || !isRecord(candidate.fields)) continue;
201
- const nestedDescription = typeof candidate.description === "string" ? candidate.description.trim() : description;
202
- return {
203
- primitive: nestedPrimitive,
204
- description: nestedDescription,
205
- fields: candidate.fields
206
- };
207
- }
208
- return null;
209
- }
210
- function inferLegacyFieldDefinitions(frontmatter) {
211
- const normalized = {};
212
- const ignoredKeys = /* @__PURE__ */ new Set(["primitive", "fields", "schema", "template"]);
213
- for (const [key, value] of Object.entries(frontmatter)) {
214
- if (ignoredKeys.has(key)) continue;
215
- normalized[key] = {
216
- type: inferFieldType(value),
217
- default: value
218
- };
219
- }
220
- return normalized;
221
- }
222
- function parseTemplateDefinition(rawTemplate, templateName, sourcePath) {
223
- const normalizedName = normalizeTemplateName(templateName);
224
- const { data, content } = (0, import_gray_matter.default)(rawTemplate);
225
- const frontmatter = isRecord(data) ? data : {};
226
- const extractedSchema = extractSchemaDefinition(frontmatter);
227
- if (extractedSchema) {
228
- return {
229
- name: normalizedName,
230
- primitive: extractedSchema.primitive,
231
- description: extractedSchema.description,
232
- fields: normalizeFieldDefinitions(extractedSchema.fields),
233
- body: content,
234
- format: "schema",
235
- sourcePath
236
- };
237
- }
238
- return {
239
- name: normalizedName,
240
- primitive: normalizedName,
241
- description: typeof frontmatter.description === "string" ? frontmatter.description.trim() : void 0,
242
- fields: inferLegacyFieldDefinitions(frontmatter),
243
- body: content,
244
- format: "legacy",
245
- sourcePath
246
- };
247
- }
248
- function readTemplateDefinitionFromPath(filePath, templateName) {
249
- try {
250
- const raw = fs.readFileSync(filePath, "utf-8");
251
- return parseTemplateDefinition(raw, templateName, filePath);
252
- } catch {
253
- return null;
254
- }
255
- }
256
- function loadTemplateDefinition(templateName, options = {}) {
257
- const normalizedName = normalizeTemplateName(templateName);
258
- if (!normalizedName) return null;
259
- const index = buildTemplateIndex(options);
260
- const filePath = index.get(normalizedName);
261
- if (!filePath) return null;
262
- return readTemplateDefinitionFromPath(filePath, normalizedName);
263
- }
264
- function loadSchemaTemplateDefinition(templateName, options = {}) {
265
- const definition = loadTemplateDefinition(templateName, options);
266
- if (!definition || definition.format !== "schema") {
267
- return null;
268
- }
269
- return definition;
270
- }
271
- function resolveInterpolatedValue(value, variables) {
272
- if (typeof value === "string") {
273
- return renderTemplate(value, variables);
274
- }
275
- if (Array.isArray(value)) {
276
- return value.map((item) => resolveInterpolatedValue(item, variables));
277
- }
278
- if (isRecord(value)) {
279
- const resolved = {};
280
- for (const [key, nested] of Object.entries(value)) {
281
- resolved[key] = resolveInterpolatedValue(nested, variables);
282
- }
283
- return resolved;
284
- }
285
- return value;
286
- }
287
- function pruneFrontmatter(frontmatter, options) {
288
- const dropEmptyStrings = options.dropEmptyStrings ?? true;
289
- const dropEmptyArrays = options.dropEmptyArrays ?? true;
290
- const pruned = {};
291
- for (const [key, value] of Object.entries(frontmatter)) {
292
- if (value === void 0 || value === null) continue;
293
- if (dropEmptyStrings && typeof value === "string" && value.trim() === "") continue;
294
- if (dropEmptyArrays && Array.isArray(value) && value.length === 0) continue;
295
- pruned[key] = value;
296
- }
297
- return pruned;
298
- }
299
- function buildFrontmatterFromTemplate(definition, variables, overrides = {}, options = {}) {
300
- const frontmatter = {};
301
- for (const [fieldName, schema] of Object.entries(definition.fields)) {
302
- if (!Object.prototype.hasOwnProperty.call(schema, "default")) continue;
303
- frontmatter[fieldName] = resolveInterpolatedValue(schema.default, variables);
304
- }
305
- for (const [fieldName, value] of Object.entries(overrides)) {
306
- if (value === void 0) continue;
307
- if (value === null) {
308
- delete frontmatter[fieldName];
309
- continue;
310
- }
311
- frontmatter[fieldName] = value;
312
- }
313
- if (!options.pruneEmpty) {
314
- return frontmatter;
315
- }
316
- return pruneFrontmatter(frontmatter, options);
317
- }
318
- function renderDocumentFromTemplate(definition, options = {}) {
319
- const now = options.now ?? /* @__PURE__ */ new Date();
320
- const variables = {
321
- ...buildTemplateVariables(
322
- {
323
- title: options.title ?? "",
324
- type: options.type ?? definition.primitive
325
- },
326
- now
327
- ),
328
- ...options.variables ?? {}
329
- };
330
- const frontmatter = buildFrontmatterFromTemplate(
331
- definition,
332
- variables,
333
- options.overrides,
334
- options.frontmatter
335
- );
336
- const content = renderTemplate(definition.body, variables);
337
- const markdown = import_gray_matter.default.stringify(content, frontmatter);
338
- return {
339
- frontmatter,
340
- content,
341
- markdown,
342
- variables
343
- };
344
- }
345
-
346
- // src/lib/task-utils.ts
347
- function slugify(text) {
348
- return text.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "").trim();
349
- }
350
- function getTasksDir(vaultPath) {
351
- return path2.join(path2.resolve(vaultPath), "tasks");
352
- }
353
- function getTaskPath(vaultPath, slug) {
354
- return path2.join(getTasksDir(vaultPath), `${slug}.md`);
355
- }
356
- function extractTitle(content) {
357
- const match = content.match(/^#\s+(.+)$/m);
358
- return match ? match[1].trim() : "";
359
- }
360
- function parseDueDate(value) {
361
- if (!value) return null;
362
- const timestamp = Date.parse(value);
363
- if (Number.isNaN(timestamp)) return null;
364
- return timestamp;
365
- }
366
- function startOfToday() {
367
- const now = /* @__PURE__ */ new Date();
368
- return new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
369
- }
370
- function readTask(vaultPath, slug) {
371
- const taskPath = getTaskPath(vaultPath, slug);
372
- if (!fs2.existsSync(taskPath)) {
373
- return null;
374
- }
375
- try {
376
- const raw = fs2.readFileSync(taskPath, "utf-8");
377
- const { data, content } = (0, import_gray_matter2.default)(raw);
378
- const title = extractTitle(content) || slug;
379
- return {
380
- slug,
381
- title,
382
- content,
383
- frontmatter: data,
384
- path: taskPath
385
- };
386
- } catch {
387
- return null;
388
- }
389
- }
390
- function listTasks(vaultPath, filters) {
391
- const tasksDir = getTasksDir(vaultPath);
392
- if (!fs2.existsSync(tasksDir)) {
393
- return [];
394
- }
395
- const tasks = [];
396
- const entries = fs2.readdirSync(tasksDir, { withFileTypes: true });
397
- const today = startOfToday();
398
- for (const entry of entries) {
399
- if (!entry.isFile() || !entry.name.endsWith(".md")) {
400
- continue;
401
- }
402
- const slug = entry.name.replace(/\.md$/, "");
403
- const task = readTask(vaultPath, slug);
404
- if (!task) continue;
405
- if (filters) {
406
- if (filters.status && task.frontmatter.status !== filters.status) continue;
407
- if (filters.owner && task.frontmatter.owner !== filters.owner) continue;
408
- if (filters.project && task.frontmatter.project !== filters.project) continue;
409
- if (filters.priority && task.frontmatter.priority !== filters.priority) continue;
410
- if (filters.due && !task.frontmatter.due) continue;
411
- if (filters.tag) {
412
- const tags = task.frontmatter.tags || [];
413
- const hasTag = tags.some((tag) => tag.toLowerCase() === filters.tag?.toLowerCase());
414
- if (!hasTag) continue;
415
- }
416
- if (filters.overdue) {
417
- const dueTime = parseDueDate(task.frontmatter.due);
418
- if (task.frontmatter.status === "done" || dueTime === null || dueTime >= today) continue;
419
- }
420
- }
421
- tasks.push(task);
422
- }
423
- const priorityOrder = {
424
- critical: 0,
425
- high: 1,
426
- medium: 2,
427
- low: 3
428
- };
429
- if (filters?.due || filters?.overdue) {
430
- return tasks.sort((a, b) => {
431
- const aDue = parseDueDate(a.frontmatter.due);
432
- const bDue = parseDueDate(b.frontmatter.due);
433
- if (aDue !== null && bDue !== null && aDue !== bDue) {
434
- return aDue - bDue;
435
- }
436
- if (aDue !== null && bDue === null) return -1;
437
- if (aDue === null && bDue !== null) return 1;
438
- return new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime();
439
- });
440
- }
441
- return tasks.sort((a, b) => {
442
- const aPriority = priorityOrder[a.frontmatter.priority || "low"];
443
- const bPriority = priorityOrder[b.frontmatter.priority || "low"];
444
- if (aPriority !== bPriority) {
445
- return aPriority - bPriority;
446
- }
447
- return new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime();
448
- });
449
- }
450
-
451
- // src/lib/project-utils.ts
452
- function extractTitle2(content) {
453
- const match = content.match(/^#\s+(.+)$/m);
454
- return match ? match[1].trim() : "";
455
- }
456
- function isDateSlug(slug) {
457
- return /^\d{4}-\d{2}-\d{2}$/.test(slug);
458
- }
459
- function normalizeStringArray(value) {
460
- return value.map((item) => item.trim()).filter(Boolean);
461
- }
462
- function getProjectsDir(vaultPath) {
463
- return path3.join(path3.resolve(vaultPath), "projects");
464
- }
465
- function ensureProjectsDir(vaultPath) {
466
- const projectsDir = getProjectsDir(vaultPath);
467
- if (!fs3.existsSync(projectsDir)) {
468
- fs3.mkdirSync(projectsDir, { recursive: true });
469
- }
470
- }
471
- function getProjectPath(vaultPath, slug) {
472
- return path3.join(getProjectsDir(vaultPath), `${slug}.md`);
473
- }
474
- function parseProjectDateValue(filePath) {
475
- const filename = path3.basename(filePath, ".md");
476
- if (/^\d{4}-\d{2}-\d{2}$/.test(filename)) {
477
- const dateTs = Date.parse(`${filename}T00:00:00.000Z`);
478
- if (!Number.isNaN(dateTs)) {
479
- return dateTs;
480
- }
481
- }
482
- return fs3.statSync(filePath).mtime.getTime();
483
- }
484
- function parseSortableTimestamp(value) {
485
- if (!value) return 0;
486
- const timestamp = Date.parse(value);
487
- return Number.isNaN(timestamp) ? 0 : timestamp;
488
- }
489
- function normalizeProjectStatus(value) {
490
- if (value === "active" || value === "paused" || value === "completed" || value === "archived") {
491
- return value;
492
- }
493
- return "active";
494
- }
495
- function buildProjectFrontmatterFallback(now, options) {
496
- const frontmatter = {
497
- type: "project",
498
- status: options.status ?? "active",
499
- created: now,
500
- updated: now
501
- };
502
- if (options.owner) frontmatter.owner = options.owner;
503
- if (options.team && options.team.length > 0) {
504
- const team = normalizeStringArray(options.team);
505
- if (team.length > 0) frontmatter.team = team;
506
- }
507
- if (options.client) frontmatter.client = options.client;
508
- if (options.tags && options.tags.length > 0) {
509
- const tags = normalizeStringArray(options.tags);
510
- if (tags.length > 0) frontmatter.tags = tags;
511
- }
512
- if (options.description) frontmatter.description = options.description;
513
- if (options.started) frontmatter.started = options.started;
514
- if (options.deadline) frontmatter.deadline = options.deadline;
515
- if (options.repo) frontmatter.repo = options.repo;
516
- if (options.url) frontmatter.url = options.url;
517
- if (options.completed) frontmatter.completed = options.completed;
518
- if (options.reason) frontmatter.reason = options.reason;
519
- return frontmatter;
520
- }
521
- function buildProjectContentFallback(title, options) {
522
- let content = `# ${title}
523
- `;
524
- const wikiLinks = /* @__PURE__ */ new Set();
525
- if (options.owner) wikiLinks.add(options.owner);
526
- if (options.client) wikiLinks.add(options.client);
527
- for (const member of options.team || []) {
528
- const trimmed = member.trim();
529
- if (trimmed) wikiLinks.add(trimmed);
530
- }
531
- if (wikiLinks.size > 0) {
532
- content += `
533
- ${Array.from(wikiLinks).map((link) => `[[${link}]]`).join(" | ")}
534
- `;
535
- }
536
- if (options.content) {
537
- content += `
538
- ${options.content}
539
- `;
540
- }
541
- return content;
542
- }
543
- function buildProjectTemplateOverrides(options) {
544
- const overrides = {};
545
- if (options.status) overrides.status = options.status;
546
- if (options.owner) overrides.owner = options.owner;
547
- if (options.team && options.team.length > 0) {
548
- const team = normalizeStringArray(options.team);
549
- if (team.length > 0) overrides.team = team;
550
- }
551
- if (options.client) overrides.client = options.client;
552
- if (options.tags && options.tags.length > 0) {
553
- const tags = normalizeStringArray(options.tags);
554
- if (tags.length > 0) overrides.tags = tags;
555
- }
556
- if (options.description) overrides.description = options.description;
557
- if (options.started) overrides.started = options.started;
558
- if (options.deadline) overrides.deadline = options.deadline;
559
- if (options.repo) overrides.repo = options.repo;
560
- if (options.url) overrides.url = options.url;
561
- if (options.completed) overrides.completed = options.completed;
562
- if (options.reason) overrides.reason = options.reason;
563
- return overrides;
564
- }
565
- function buildProjectTemplateVariables(title, slug, options) {
566
- const ownerLink = options.owner ? `[[${options.owner}]]` : "";
567
- const clientLink = options.client ? `[[${options.client}]]` : "";
568
- const teamLinks = (options.team || []).map((member) => member.trim()).filter(Boolean).map((member) => `[[${member}]]`);
569
- const linksLine = [ownerLink, clientLink, ...teamLinks].filter(Boolean).join(" | ");
570
- return {
571
- title,
572
- slug,
573
- status: options.status ?? "",
574
- owner: options.owner ?? "",
575
- client: options.client ?? "",
576
- team_csv: (options.team || []).join(", "),
577
- tags_csv: (options.tags || []).join(", "),
578
- description: options.description ?? "",
579
- started: options.started ?? "",
580
- deadline: options.deadline ?? "",
581
- repo: options.repo ?? "",
582
- url: options.url ?? "",
583
- completed: options.completed ?? "",
584
- reason: options.reason ?? "",
585
- content: options.content ?? "",
586
- owner_link: ownerLink,
587
- client_link: clientLink,
588
- team_links_line: teamLinks.join(" | "),
589
- links_line: linksLine
590
- };
591
- }
592
- function normalizeProjectFrontmatter(frontmatter) {
593
- const normalizedCreated = typeof frontmatter.created === "string" && frontmatter.created ? frontmatter.created : (/* @__PURE__ */ new Date(0)).toISOString();
594
- const normalizedUpdated = typeof frontmatter.updated === "string" && frontmatter.updated ? frontmatter.updated : normalizedCreated;
595
- const normalized = {
596
- ...frontmatter,
597
- type: "project",
598
- status: normalizeProjectStatus(frontmatter.status),
599
- created: normalizedCreated,
600
- updated: normalizedUpdated
601
- };
602
- if (normalized.team) {
603
- const team = normalizeStringArray(normalized.team);
604
- if (team.length === 0) {
605
- delete normalized.team;
606
- } else {
607
- normalized.team = team;
608
- }
609
- }
610
- if (normalized.tags) {
611
- const tags = normalizeStringArray(normalized.tags);
612
- if (tags.length === 0) {
613
- delete normalized.tags;
614
- } else {
615
- normalized.tags = tags;
616
- }
617
- }
618
- return normalized;
619
- }
620
- function listProjects(vaultPath, filters) {
621
- const projectsDir = getProjectsDir(vaultPath);
622
- if (!fs3.existsSync(projectsDir)) {
623
- return [];
624
- }
625
- const projects = [];
626
- const entries = fs3.readdirSync(projectsDir, { withFileTypes: true });
627
- for (const entry of entries) {
628
- if (!entry.isFile() || !entry.name.endsWith(".md")) {
629
- continue;
630
- }
631
- const slug = entry.name.replace(/\.md$/, "");
632
- if (isDateSlug(slug)) {
633
- continue;
634
- }
635
- const project = readProject(vaultPath, slug);
636
- if (!project) continue;
637
- if (filters) {
638
- if (filters.status && project.frontmatter.status !== filters.status) continue;
639
- if (filters.owner && project.frontmatter.owner !== filters.owner) continue;
640
- if (filters.client && project.frontmatter.client !== filters.client) continue;
641
- if (filters.tag) {
642
- const tags = project.frontmatter.tags || [];
643
- const hasTag = tags.some((tag) => tag.toLowerCase() === filters.tag?.toLowerCase());
644
- if (!hasTag) continue;
645
- }
646
- }
647
- projects.push(project);
648
- }
649
- return projects.sort((left, right) => {
650
- const rightTime = parseSortableTimestamp(right.frontmatter.updated || right.frontmatter.created);
651
- const leftTime = parseSortableTimestamp(left.frontmatter.updated || left.frontmatter.created);
652
- return rightTime - leftTime;
653
- });
654
- }
655
- function readProject(vaultPath, slug) {
656
- if (!slug || isDateSlug(slug) || slug.includes(path3.sep)) {
657
- return null;
658
- }
659
- const projectPath = getProjectPath(vaultPath, slug);
660
- if (!fs3.existsSync(projectPath)) {
661
- return null;
662
- }
663
- try {
664
- const raw = fs3.readFileSync(projectPath, "utf-8");
665
- const { data, content } = (0, import_gray_matter3.default)(raw);
666
- if (data.type !== "project") {
667
- return null;
668
- }
669
- const frontmatter = normalizeProjectFrontmatter(data);
670
- const title = extractTitle2(content) || slug;
671
- return {
672
- slug,
673
- title,
674
- content,
675
- frontmatter
676
- };
677
- } catch {
678
- return null;
679
- }
680
- }
681
- function createProject(vaultPath, title, options = {}) {
682
- ensureProjectsDir(vaultPath);
683
- const slug = slugify(title);
684
- const projectPath = getProjectPath(vaultPath, slug);
685
- if (fs3.existsSync(projectPath)) {
686
- throw new Error(`Project already exists: ${slug}`);
687
- }
688
- const now = (/* @__PURE__ */ new Date()).toISOString();
689
- const template = loadSchemaTemplateDefinition("project", {
690
- vaultPath: path3.resolve(vaultPath)
691
- });
692
- let frontmatter;
693
- let content;
694
- if (template) {
695
- const rendered = renderDocumentFromTemplate(template, {
696
- title,
697
- type: "project",
698
- now: new Date(now),
699
- variables: buildProjectTemplateVariables(title, slug, options),
700
- overrides: buildProjectTemplateOverrides(options),
701
- frontmatter: { pruneEmpty: true }
702
- });
703
- const templateFrontmatter = rendered.frontmatter;
704
- frontmatter = normalizeProjectFrontmatter({
705
- ...templateFrontmatter,
706
- type: "project",
707
- status: normalizeProjectStatus(templateFrontmatter.status),
708
- created: typeof templateFrontmatter.created === "string" && templateFrontmatter.created ? templateFrontmatter.created : now,
709
- updated: typeof templateFrontmatter.updated === "string" && templateFrontmatter.updated ? templateFrontmatter.updated : now
710
- });
711
- content = rendered.content;
712
- } else {
713
- frontmatter = buildProjectFrontmatterFallback(now, options);
714
- content = buildProjectContentFallback(title, options);
715
- }
716
- const fileContent = import_gray_matter3.default.stringify(content, frontmatter);
717
- fs3.writeFileSync(projectPath, fileContent);
718
- return {
719
- slug,
720
- title,
721
- content,
722
- frontmatter
723
- };
724
- }
725
- function updateProject(vaultPath, slug, updates) {
726
- const project = readProject(vaultPath, slug);
727
- if (!project) {
728
- throw new Error(`Project not found: ${slug}`);
729
- }
730
- const now = (/* @__PURE__ */ new Date()).toISOString();
731
- const nextFrontmatter = {
732
- ...project.frontmatter,
733
- type: "project",
734
- updated: now
735
- };
736
- if (updates.status !== void 0) {
737
- nextFrontmatter.status = updates.status;
738
- if (updates.status === "completed" && !updates.completed && !nextFrontmatter.completed) {
739
- nextFrontmatter.completed = now;
740
- }
741
- }
742
- if (updates.owner !== void 0) {
743
- if (updates.owner === null || updates.owner.trim() === "") {
744
- delete nextFrontmatter.owner;
745
- } else {
746
- nextFrontmatter.owner = updates.owner;
747
- }
748
- }
749
- if (updates.team !== void 0) {
750
- if (updates.team === null) {
751
- delete nextFrontmatter.team;
752
- } else {
753
- const team = normalizeStringArray(updates.team);
754
- if (team.length === 0) {
755
- delete nextFrontmatter.team;
756
- } else {
757
- nextFrontmatter.team = team;
758
- }
759
- }
760
- }
761
- if (updates.client !== void 0) {
762
- if (updates.client === null || updates.client.trim() === "") {
763
- delete nextFrontmatter.client;
764
- } else {
765
- nextFrontmatter.client = updates.client;
766
- }
767
- }
768
- if (updates.tags !== void 0) {
769
- if (updates.tags === null) {
770
- delete nextFrontmatter.tags;
771
- } else {
772
- const tags = normalizeStringArray(updates.tags);
773
- if (tags.length === 0) {
774
- delete nextFrontmatter.tags;
775
- } else {
776
- nextFrontmatter.tags = tags;
777
- }
778
- }
779
- }
780
- if (updates.description !== void 0) {
781
- if (updates.description === null || updates.description.trim() === "") {
782
- delete nextFrontmatter.description;
783
- } else {
784
- nextFrontmatter.description = updates.description;
785
- }
786
- }
787
- if (updates.started !== void 0) {
788
- if (updates.started === null || updates.started.trim() === "") {
789
- delete nextFrontmatter.started;
790
- } else {
791
- nextFrontmatter.started = updates.started;
792
- }
793
- }
794
- if (updates.deadline !== void 0) {
795
- if (updates.deadline === null || updates.deadline.trim() === "") {
796
- delete nextFrontmatter.deadline;
797
- } else {
798
- nextFrontmatter.deadline = updates.deadline;
799
- }
800
- }
801
- if (updates.repo !== void 0) {
802
- if (updates.repo === null || updates.repo.trim() === "") {
803
- delete nextFrontmatter.repo;
804
- } else {
805
- nextFrontmatter.repo = updates.repo;
806
- }
807
- }
808
- if (updates.url !== void 0) {
809
- if (updates.url === null || updates.url.trim() === "") {
810
- delete nextFrontmatter.url;
811
- } else {
812
- nextFrontmatter.url = updates.url;
813
- }
814
- }
815
- if (updates.completed !== void 0) {
816
- if (updates.completed === null || updates.completed.trim() === "") {
817
- delete nextFrontmatter.completed;
818
- } else {
819
- nextFrontmatter.completed = updates.completed;
820
- }
821
- }
822
- if (updates.reason !== void 0) {
823
- if (updates.reason === null || updates.reason.trim() === "") {
824
- delete nextFrontmatter.reason;
825
- } else {
826
- nextFrontmatter.reason = updates.reason;
827
- }
828
- }
829
- const projectPath = getProjectPath(vaultPath, slug);
830
- fs3.writeFileSync(projectPath, import_gray_matter3.default.stringify(project.content, nextFrontmatter));
831
- return {
832
- ...project,
833
- frontmatter: nextFrontmatter
834
- };
835
- }
836
- function archiveProject(vaultPath, slug, reason) {
837
- return updateProject(vaultPath, slug, {
838
- status: "archived",
839
- reason: reason ?? null,
840
- completed: (/* @__PURE__ */ new Date()).toISOString()
841
- });
842
- }
843
- function getProjectTasks(vaultPath, slug) {
844
- return listTasks(vaultPath, { project: slug });
845
- }
846
- function getProjectActivity(vaultPath, slug) {
847
- const projectActivityDir = path3.join(getProjectsDir(vaultPath), slug);
848
- if (!fs3.existsSync(projectActivityDir) || !fs3.statSync(projectActivityDir).isDirectory()) {
849
- return [];
850
- }
851
- const entries = fs3.readdirSync(projectActivityDir, { withFileTypes: true });
852
- const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) => path3.join(projectActivityDir, entry.name));
853
- return files.sort((left, right) => parseProjectDateValue(right) - parseProjectDateValue(left));
854
- }
855
- // Annotate the CommonJS export names for ESM import in node:
856
- 0 && (module.exports = {
857
- archiveProject,
858
- createProject,
859
- getProjectActivity,
860
- getProjectTasks,
861
- listProjects,
862
- readProject,
863
- updateProject
864
- });