clawvault 2.6.0 → 3.0.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 (232) hide show
  1. package/bin/command-registration.test.js +1 -3
  2. package/bin/register-core-commands.js +10 -23
  3. package/bin/register-maintenance-commands.js +3 -20
  4. package/bin/register-query-commands.js +23 -0
  5. package/bin/register-task-commands.js +1 -18
  6. package/bin/register-task-commands.test.js +0 -16
  7. package/bin/register-vault-operations-commands.js +1 -29
  8. package/dist/{chunk-QVMXF7FY.js → chunk-3D6BCTP6.js} +39 -1
  9. package/dist/{chunk-R2MIW5G7.js → chunk-3DHXQHYG.js} +1 -1
  10. package/dist/{chunk-Q2J5YTUF.js → chunk-3NSBOUT3.js} +73 -36
  11. package/dist/chunk-3RG5ZIWI.js +10 -0
  12. package/dist/{chunk-AZYOKJYC.js → chunk-62YTUT6J.js} +2 -2
  13. package/dist/chunk-6U6MK36V.js +205 -0
  14. package/dist/{chunk-4QYGFWRM.js → chunk-7R7O6STJ.js} +4 -4
  15. package/dist/{chunk-VXEOHTSL.js → chunk-C7OK5WKP.js} +4 -4
  16. package/dist/chunk-CMB7UL7C.js +327 -0
  17. package/dist/chunk-DEFFDRVP.js +938 -0
  18. package/dist/{chunk-K3CDT7IH.js → chunk-E7MFQB6D.js} +61 -20
  19. package/dist/{chunk-ME37YNW3.js → chunk-F2JEUD4J.js} +6 -4
  20. package/dist/chunk-GAJV4IGR.js +82 -0
  21. package/dist/chunk-GQSLDZTS.js +560 -0
  22. package/dist/{chunk-4OXMU5S2.js → chunk-GUKMRGM7.js} +1 -1
  23. package/dist/{chunk-YOSEUUNB.js → chunk-H34S76MB.js} +6 -6
  24. package/dist/{chunk-4TE4JMLA.js → chunk-JY6FYXIT.js} +10 -5
  25. package/dist/chunk-K234IDRJ.js +1073 -0
  26. package/dist/{chunk-IEVLHNLU.js → chunk-LNJA2UGL.js} +86 -9
  27. package/dist/{chunk-MFAWT5O5.js → chunk-LYHGEHXG.js} +1 -0
  28. package/dist/chunk-MFM6K7PU.js +374 -0
  29. package/dist/{chunk-QWQ3TIKS.js → chunk-N2AXRYLC.js} +1 -1
  30. package/dist/chunk-PAH27GSN.js +108 -0
  31. package/dist/{chunk-OIWVQYQF.js → chunk-QBLMXKF2.js} +1 -1
  32. package/dist/{chunk-FHFUXL6G.js → chunk-QK3UCXWL.js} +2 -2
  33. package/dist/{chunk-2YDBJS7M.js → chunk-SJSFRIYS.js} +1 -1
  34. package/dist/{chunk-GSD4ALSI.js → chunk-U55BGUAU.js} +2 -2
  35. package/dist/{chunk-PBEE567J.js → chunk-VGLOTGAS.js} +1 -1
  36. package/dist/{chunk-F55HGNU4.js → chunk-WAZ3NLWL.js} +47 -0
  37. package/dist/{chunk-KL4NAOMO.js → chunk-WGRQ6HDV.js} +1 -1
  38. package/dist/{chunk-UEOUADMO.js → chunk-YKTA5JOJ.js} +13 -10
  39. package/dist/{chunk-XAVB4GB4.js → chunk-ZVVFWOLW.js} +4 -4
  40. package/dist/cli/index.cjs +10033 -0
  41. package/dist/cli/index.d.cts +5 -0
  42. package/dist/cli/index.js +20 -18
  43. package/dist/commands/archive.cjs +287 -0
  44. package/dist/commands/archive.d.cts +11 -0
  45. package/dist/commands/archive.js +1 -0
  46. package/dist/commands/backlog.cjs +721 -0
  47. package/dist/commands/backlog.d.cts +53 -0
  48. package/dist/commands/backlog.js +3 -2
  49. package/dist/commands/blocked.cjs +204 -0
  50. package/dist/commands/blocked.d.cts +26 -0
  51. package/dist/commands/blocked.js +3 -2
  52. package/dist/commands/checkpoint.cjs +244 -0
  53. package/dist/commands/checkpoint.d.cts +41 -0
  54. package/dist/commands/checkpoint.js +2 -1
  55. package/dist/commands/compat.cjs +369 -0
  56. package/dist/commands/compat.d.cts +28 -0
  57. package/dist/commands/compat.js +2 -1
  58. package/dist/commands/context.cjs +2989 -0
  59. package/dist/commands/context.d.cts +2 -0
  60. package/dist/commands/context.js +5 -4
  61. package/dist/commands/doctor.cjs +3062 -0
  62. package/dist/commands/doctor.d.cts +21 -0
  63. package/dist/commands/doctor.d.ts +6 -1
  64. package/dist/commands/doctor.js +13 -11
  65. package/dist/commands/embed.cjs +232 -0
  66. package/dist/commands/embed.d.cts +17 -0
  67. package/dist/commands/embed.js +5 -2
  68. package/dist/commands/entities.cjs +141 -0
  69. package/dist/commands/entities.d.cts +7 -0
  70. package/dist/commands/entities.js +1 -0
  71. package/dist/commands/graph.cjs +501 -0
  72. package/dist/commands/graph.d.cts +21 -0
  73. package/dist/commands/graph.js +1 -0
  74. package/dist/commands/inject.cjs +1636 -0
  75. package/dist/commands/inject.d.cts +2 -0
  76. package/dist/commands/inject.d.ts +1 -1
  77. package/dist/commands/inject.js +4 -2
  78. package/dist/commands/kanban.cjs +884 -0
  79. package/dist/commands/kanban.d.cts +63 -0
  80. package/dist/commands/kanban.js +4 -3
  81. package/dist/commands/link.cjs +965 -0
  82. package/dist/commands/link.d.cts +11 -0
  83. package/dist/commands/link.js +1 -0
  84. package/dist/commands/migrate-observations.cjs +362 -0
  85. package/dist/commands/migrate-observations.d.cts +19 -0
  86. package/dist/commands/migrate-observations.js +3 -2
  87. package/dist/commands/observe.cjs +4099 -0
  88. package/dist/commands/observe.d.cts +23 -0
  89. package/dist/commands/observe.d.ts +1 -0
  90. package/dist/commands/observe.js +11 -9
  91. package/dist/commands/project.cjs +1341 -0
  92. package/dist/commands/project.d.cts +85 -0
  93. package/dist/commands/project.js +5 -4
  94. package/dist/commands/rebuild.cjs +3136 -0
  95. package/dist/commands/rebuild.d.cts +11 -0
  96. package/dist/commands/rebuild.js +10 -8
  97. package/dist/commands/recover.cjs +361 -0
  98. package/dist/commands/recover.d.cts +38 -0
  99. package/dist/commands/recover.js +3 -2
  100. package/dist/commands/reflect.cjs +1008 -0
  101. package/dist/commands/reflect.d.cts +11 -0
  102. package/dist/commands/reflect.js +6 -4
  103. package/dist/commands/repair-session.cjs +457 -0
  104. package/dist/commands/repair-session.d.cts +38 -0
  105. package/dist/commands/repair-session.js +1 -0
  106. package/dist/commands/replay.cjs +4103 -0
  107. package/dist/commands/replay.d.cts +16 -0
  108. package/dist/commands/replay.js +12 -10
  109. package/dist/commands/session-recap.cjs +353 -0
  110. package/dist/commands/session-recap.d.cts +27 -0
  111. package/dist/commands/session-recap.js +1 -0
  112. package/dist/commands/setup.cjs +1345 -0
  113. package/dist/commands/setup.d.cts +100 -0
  114. package/dist/commands/setup.d.ts +90 -2
  115. package/dist/commands/setup.js +21 -2
  116. package/dist/commands/shell-init.cjs +75 -0
  117. package/dist/commands/shell-init.d.cts +7 -0
  118. package/dist/commands/shell-init.js +2 -0
  119. package/dist/commands/sleep.cjs +6028 -0
  120. package/dist/commands/sleep.d.cts +36 -0
  121. package/dist/commands/sleep.d.ts +1 -1
  122. package/dist/commands/sleep.js +17 -15
  123. package/dist/commands/status.cjs +2736 -0
  124. package/dist/commands/status.d.cts +52 -0
  125. package/dist/commands/status.js +12 -10
  126. package/dist/commands/tailscale.cjs +1532 -0
  127. package/dist/commands/tailscale.d.cts +52 -0
  128. package/dist/commands/tailscale.js +1 -0
  129. package/dist/commands/task.cjs +1236 -0
  130. package/dist/commands/task.d.cts +97 -0
  131. package/dist/commands/task.js +4 -3
  132. package/dist/commands/template.cjs +457 -0
  133. package/dist/commands/template.d.cts +36 -0
  134. package/dist/commands/template.js +2 -1
  135. package/dist/commands/wake.cjs +2626 -0
  136. package/dist/commands/wake.d.cts +22 -0
  137. package/dist/commands/wake.d.ts +1 -1
  138. package/dist/commands/wake.js +12 -11
  139. package/dist/context-BUGaWpyL.d.cts +46 -0
  140. package/dist/index.cjs +14526 -0
  141. package/dist/index.d.cts +858 -0
  142. package/dist/index.d.ts +192 -7
  143. package/dist/index.js +101 -75
  144. package/dist/{inject-x65KXWPk.d.ts → inject-Bzi5E-By.d.cts} +1 -1
  145. package/dist/inject-Bzi5E-By.d.ts +137 -0
  146. package/dist/lib/auto-linker.cjs +176 -0
  147. package/dist/lib/auto-linker.d.cts +26 -0
  148. package/dist/lib/auto-linker.js +1 -0
  149. package/dist/lib/canvas-layout.cjs +136 -0
  150. package/dist/lib/canvas-layout.d.cts +31 -0
  151. package/dist/lib/canvas-layout.d.ts +16 -100
  152. package/dist/lib/canvas-layout.js +78 -20
  153. package/dist/lib/config.cjs +78 -0
  154. package/dist/lib/config.d.cts +11 -0
  155. package/dist/lib/config.js +1 -0
  156. package/dist/lib/entity-index.cjs +84 -0
  157. package/dist/lib/entity-index.d.cts +26 -0
  158. package/dist/lib/entity-index.js +1 -0
  159. package/dist/lib/project-utils.cjs +864 -0
  160. package/dist/lib/project-utils.d.cts +97 -0
  161. package/dist/lib/project-utils.js +4 -3
  162. package/dist/lib/session-repair.cjs +239 -0
  163. package/dist/lib/session-repair.d.cts +110 -0
  164. package/dist/lib/session-repair.js +1 -0
  165. package/dist/lib/session-utils.cjs +209 -0
  166. package/dist/lib/session-utils.d.cts +63 -0
  167. package/dist/lib/session-utils.js +1 -0
  168. package/dist/lib/tailscale.cjs +1183 -0
  169. package/dist/lib/tailscale.d.cts +225 -0
  170. package/dist/lib/tailscale.js +1 -0
  171. package/dist/lib/task-utils.cjs +1137 -0
  172. package/dist/lib/task-utils.d.cts +208 -0
  173. package/dist/lib/task-utils.js +3 -2
  174. package/dist/lib/template-engine.cjs +47 -0
  175. package/dist/lib/template-engine.d.cts +11 -0
  176. package/dist/lib/template-engine.js +1 -0
  177. package/dist/lib/webdav.cjs +568 -0
  178. package/dist/lib/webdav.d.cts +109 -0
  179. package/dist/lib/webdav.js +1 -0
  180. package/dist/plugin/index.cjs +1907 -0
  181. package/dist/plugin/index.d.cts +36 -0
  182. package/dist/plugin/index.d.ts +36 -0
  183. package/dist/plugin/index.js +572 -0
  184. package/dist/plugin/inject.cjs +356 -0
  185. package/dist/plugin/inject.d.cts +54 -0
  186. package/dist/plugin/inject.d.ts +54 -0
  187. package/dist/plugin/inject.js +17 -0
  188. package/dist/plugin/observe.cjs +631 -0
  189. package/dist/plugin/observe.d.cts +39 -0
  190. package/dist/plugin/observe.d.ts +39 -0
  191. package/dist/plugin/observe.js +18 -0
  192. package/dist/plugin/templates.cjs +593 -0
  193. package/dist/plugin/templates.d.cts +52 -0
  194. package/dist/plugin/templates.d.ts +52 -0
  195. package/dist/plugin/templates.js +25 -0
  196. package/dist/plugin/types.cjs +18 -0
  197. package/dist/plugin/types.d.cts +209 -0
  198. package/dist/plugin/types.d.ts +209 -0
  199. package/dist/plugin/types.js +0 -0
  200. package/dist/plugin/vault.cjs +927 -0
  201. package/dist/plugin/vault.d.cts +68 -0
  202. package/dist/plugin/vault.d.ts +68 -0
  203. package/dist/plugin/vault.js +22 -0
  204. package/dist/{types-C74wgGL1.d.ts → types-Y2_Um2Ls.d.cts} +44 -1
  205. package/dist/types-Y2_Um2Ls.d.ts +205 -0
  206. package/hooks/clawvault/handler.js +70 -7
  207. package/hooks/clawvault/handler.test.js +91 -0
  208. package/openclaw.plugin.json +56 -0
  209. package/package.json +17 -7
  210. package/templates/memory-event.md +67 -0
  211. package/templates/party.md +63 -0
  212. package/templates/primitive-registry.yaml +551 -0
  213. package/templates/run.md +68 -0
  214. package/templates/trigger.md +68 -0
  215. package/templates/workspace.md +50 -0
  216. package/dashboard/lib/graph-diff.js +0 -104
  217. package/dashboard/lib/graph-diff.test.js +0 -75
  218. package/dashboard/lib/vault-parser.js +0 -556
  219. package/dashboard/lib/vault-parser.test.js +0 -254
  220. package/dashboard/public/app.js +0 -796
  221. package/dashboard/public/index.html +0 -52
  222. package/dashboard/public/styles.css +0 -221
  223. package/dashboard/server.js +0 -374
  224. package/dist/chunk-HA5M6KJB.js +0 -33
  225. package/dist/chunk-MAKNAHAW.js +0 -375
  226. package/dist/chunk-MDIH26GC.js +0 -183
  227. package/dist/chunk-MGDEINGP.js +0 -99
  228. package/dist/chunk-RVYA52PY.js +0 -363
  229. package/dist/commands/canvas.d.ts +0 -15
  230. package/dist/commands/canvas.js +0 -199
  231. package/dist/commands/sync-bd.d.ts +0 -10
  232. package/dist/commands/sync-bd.js +0 -9
@@ -0,0 +1,721 @@
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/commands/backlog.ts
31
+ var backlog_exports = {};
32
+ __export(backlog_exports, {
33
+ backlogAdd: () => backlogAdd,
34
+ backlogCommand: () => backlogCommand,
35
+ backlogList: () => backlogList,
36
+ backlogPromote: () => backlogPromote,
37
+ formatBacklogDetails: () => formatBacklogDetails,
38
+ formatBacklogList: () => formatBacklogList
39
+ });
40
+ module.exports = __toCommonJS(backlog_exports);
41
+
42
+ // src/lib/task-utils.ts
43
+ var fs2 = __toESM(require("fs"), 1);
44
+ var path2 = __toESM(require("path"), 1);
45
+ var import_gray_matter2 = __toESM(require("gray-matter"), 1);
46
+
47
+ // src/lib/primitive-templates.ts
48
+ var fs = __toESM(require("fs"), 1);
49
+ var path = __toESM(require("path"), 1);
50
+ var import_url = require("url");
51
+ var import_gray_matter = __toESM(require("gray-matter"), 1);
52
+
53
+ // src/lib/template-engine.ts
54
+ function buildTemplateVariables(input = {}, now = /* @__PURE__ */ new Date()) {
55
+ const datetime = input.datetime ?? now.toISOString();
56
+ const date = input.date ?? datetime.split("T")[0];
57
+ return {
58
+ title: input.title ?? "",
59
+ type: input.type ?? "",
60
+ date,
61
+ datetime
62
+ };
63
+ }
64
+ function renderTemplate(template, variables) {
65
+ return template.replace(/\{\{\s*([a-zA-Z0-9_-]+)\s*\}\}/g, (match, key) => {
66
+ const value = variables[key];
67
+ return value !== void 0 ? String(value) : match;
68
+ });
69
+ }
70
+
71
+ // src/lib/primitive-templates.ts
72
+ var import_meta = {};
73
+ var TEMPLATE_EXTENSION = ".md";
74
+ function isRecord(value) {
75
+ return typeof value === "object" && value !== null && !Array.isArray(value);
76
+ }
77
+ function normalizeTemplateName(name) {
78
+ const base = path.basename(name, path.extname(name));
79
+ return base.trim();
80
+ }
81
+ function resolveBuiltinTemplatesDir(override) {
82
+ if (override) {
83
+ const resolved = path.resolve(override);
84
+ return fs.existsSync(resolved) && fs.statSync(resolved).isDirectory() ? resolved : null;
85
+ }
86
+ const moduleDir = path.dirname((0, import_url.fileURLToPath)(import_meta.url));
87
+ const candidates = [
88
+ path.resolve(moduleDir, "../templates"),
89
+ path.resolve(moduleDir, "../../templates")
90
+ ];
91
+ for (const candidate of candidates) {
92
+ if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
93
+ return candidate;
94
+ }
95
+ }
96
+ return null;
97
+ }
98
+ function listTemplateFiles(dir, ignore) {
99
+ const entries = /* @__PURE__ */ new Map();
100
+ if (!fs.existsSync(dir)) return entries;
101
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
102
+ if (!entry.isFile() || !entry.name.endsWith(TEMPLATE_EXTENSION)) continue;
103
+ const name = normalizeTemplateName(entry.name);
104
+ if (!name) continue;
105
+ if (ignore?.has(name)) continue;
106
+ entries.set(name, path.join(dir, entry.name));
107
+ }
108
+ return entries;
109
+ }
110
+ function buildTemplateIndex(options = {}) {
111
+ const index = /* @__PURE__ */ new Map();
112
+ const builtinDir = resolveBuiltinTemplatesDir(options.builtinDir);
113
+ if (builtinDir) {
114
+ for (const [name, filePath] of listTemplateFiles(builtinDir, options.ignoreBuiltinNames)) {
115
+ index.set(name, filePath);
116
+ }
117
+ }
118
+ if (options.vaultPath) {
119
+ const vaultTemplatesDir = path.join(path.resolve(options.vaultPath), "templates");
120
+ for (const [name, filePath] of listTemplateFiles(vaultTemplatesDir)) {
121
+ index.set(name, filePath);
122
+ }
123
+ }
124
+ return index;
125
+ }
126
+ function inferFieldType(defaultValue) {
127
+ if (Array.isArray(defaultValue)) {
128
+ const uniqueItemTypes = [...new Set(defaultValue.map((value) => typeof value))];
129
+ if (uniqueItemTypes.length === 1 && uniqueItemTypes[0] === "string") {
130
+ return "string[]";
131
+ }
132
+ return "array";
133
+ }
134
+ switch (typeof defaultValue) {
135
+ case "string":
136
+ return "string";
137
+ case "number":
138
+ return "number";
139
+ case "boolean":
140
+ return "boolean";
141
+ case "object":
142
+ if (defaultValue === null) return "string";
143
+ return "object";
144
+ default:
145
+ return "string";
146
+ }
147
+ }
148
+ function normalizeFieldDefinition(rawField) {
149
+ if (!isRecord(rawField)) {
150
+ return {
151
+ type: inferFieldType(rawField),
152
+ default: rawField
153
+ };
154
+ }
155
+ const rawType = typeof rawField.type === "string" ? rawField.type.trim() : "";
156
+ const normalized = {
157
+ type: rawType || inferFieldType(rawField.default)
158
+ };
159
+ if (typeof rawField.description === "string" && rawField.description.trim()) {
160
+ normalized.description = rawField.description.trim();
161
+ }
162
+ if (typeof rawField.required === "boolean") {
163
+ normalized.required = rawField.required;
164
+ }
165
+ if (Object.prototype.hasOwnProperty.call(rawField, "default")) {
166
+ normalized.default = rawField.default;
167
+ }
168
+ if (Array.isArray(rawField.enum)) {
169
+ normalized.enum = rawField.enum;
170
+ }
171
+ return normalized;
172
+ }
173
+ function normalizeFieldDefinitions(rawFields) {
174
+ const normalized = {};
175
+ for (const [fieldName, rawField] of Object.entries(rawFields)) {
176
+ const normalizedName = String(fieldName).trim();
177
+ if (!normalizedName) continue;
178
+ normalized[normalizedName] = normalizeFieldDefinition(rawField);
179
+ }
180
+ return normalized;
181
+ }
182
+ function extractSchemaDefinition(frontmatter) {
183
+ const primitive = typeof frontmatter.primitive === "string" ? frontmatter.primitive.trim() : "";
184
+ const description = typeof frontmatter.description === "string" ? frontmatter.description.trim() : void 0;
185
+ if (primitive && isRecord(frontmatter.fields)) {
186
+ return {
187
+ primitive,
188
+ description,
189
+ fields: frontmatter.fields
190
+ };
191
+ }
192
+ const containerCandidates = [frontmatter.schema, frontmatter.template];
193
+ for (const candidate of containerCandidates) {
194
+ if (!isRecord(candidate)) continue;
195
+ const nestedPrimitive = typeof candidate.primitive === "string" ? candidate.primitive.trim() : primitive;
196
+ if (!nestedPrimitive || !isRecord(candidate.fields)) continue;
197
+ const nestedDescription = typeof candidate.description === "string" ? candidate.description.trim() : description;
198
+ return {
199
+ primitive: nestedPrimitive,
200
+ description: nestedDescription,
201
+ fields: candidate.fields
202
+ };
203
+ }
204
+ return null;
205
+ }
206
+ function inferLegacyFieldDefinitions(frontmatter) {
207
+ const normalized = {};
208
+ const ignoredKeys = /* @__PURE__ */ new Set(["primitive", "fields", "schema", "template"]);
209
+ for (const [key, value] of Object.entries(frontmatter)) {
210
+ if (ignoredKeys.has(key)) continue;
211
+ normalized[key] = {
212
+ type: inferFieldType(value),
213
+ default: value
214
+ };
215
+ }
216
+ return normalized;
217
+ }
218
+ function parseTemplateDefinition(rawTemplate, templateName, sourcePath) {
219
+ const normalizedName = normalizeTemplateName(templateName);
220
+ const { data, content } = (0, import_gray_matter.default)(rawTemplate);
221
+ const frontmatter = isRecord(data) ? data : {};
222
+ const extractedSchema = extractSchemaDefinition(frontmatter);
223
+ if (extractedSchema) {
224
+ return {
225
+ name: normalizedName,
226
+ primitive: extractedSchema.primitive,
227
+ description: extractedSchema.description,
228
+ fields: normalizeFieldDefinitions(extractedSchema.fields),
229
+ body: content,
230
+ format: "schema",
231
+ sourcePath
232
+ };
233
+ }
234
+ return {
235
+ name: normalizedName,
236
+ primitive: normalizedName,
237
+ description: typeof frontmatter.description === "string" ? frontmatter.description.trim() : void 0,
238
+ fields: inferLegacyFieldDefinitions(frontmatter),
239
+ body: content,
240
+ format: "legacy",
241
+ sourcePath
242
+ };
243
+ }
244
+ function readTemplateDefinitionFromPath(filePath, templateName) {
245
+ try {
246
+ const raw = fs.readFileSync(filePath, "utf-8");
247
+ return parseTemplateDefinition(raw, templateName, filePath);
248
+ } catch {
249
+ return null;
250
+ }
251
+ }
252
+ function loadTemplateDefinition(templateName, options = {}) {
253
+ const normalizedName = normalizeTemplateName(templateName);
254
+ if (!normalizedName) return null;
255
+ const index = buildTemplateIndex(options);
256
+ const filePath = index.get(normalizedName);
257
+ if (!filePath) return null;
258
+ return readTemplateDefinitionFromPath(filePath, normalizedName);
259
+ }
260
+ function loadSchemaTemplateDefinition(templateName, options = {}) {
261
+ const definition = loadTemplateDefinition(templateName, options);
262
+ if (!definition || definition.format !== "schema") {
263
+ return null;
264
+ }
265
+ return definition;
266
+ }
267
+ function resolveInterpolatedValue(value, variables) {
268
+ if (typeof value === "string") {
269
+ return renderTemplate(value, variables);
270
+ }
271
+ if (Array.isArray(value)) {
272
+ return value.map((item) => resolveInterpolatedValue(item, variables));
273
+ }
274
+ if (isRecord(value)) {
275
+ const resolved = {};
276
+ for (const [key, nested] of Object.entries(value)) {
277
+ resolved[key] = resolveInterpolatedValue(nested, variables);
278
+ }
279
+ return resolved;
280
+ }
281
+ return value;
282
+ }
283
+ function pruneFrontmatter(frontmatter, options) {
284
+ const dropEmptyStrings = options.dropEmptyStrings ?? true;
285
+ const dropEmptyArrays = options.dropEmptyArrays ?? true;
286
+ const pruned = {};
287
+ for (const [key, value] of Object.entries(frontmatter)) {
288
+ if (value === void 0 || value === null) continue;
289
+ if (dropEmptyStrings && typeof value === "string" && value.trim() === "") continue;
290
+ if (dropEmptyArrays && Array.isArray(value) && value.length === 0) continue;
291
+ pruned[key] = value;
292
+ }
293
+ return pruned;
294
+ }
295
+ function buildFrontmatterFromTemplate(definition, variables, overrides = {}, options = {}) {
296
+ const frontmatter = {};
297
+ for (const [fieldName, schema] of Object.entries(definition.fields)) {
298
+ if (!Object.prototype.hasOwnProperty.call(schema, "default")) continue;
299
+ frontmatter[fieldName] = resolveInterpolatedValue(schema.default, variables);
300
+ }
301
+ for (const [fieldName, value] of Object.entries(overrides)) {
302
+ if (value === void 0) continue;
303
+ if (value === null) {
304
+ delete frontmatter[fieldName];
305
+ continue;
306
+ }
307
+ frontmatter[fieldName] = value;
308
+ }
309
+ if (!options.pruneEmpty) {
310
+ return frontmatter;
311
+ }
312
+ return pruneFrontmatter(frontmatter, options);
313
+ }
314
+ function renderDocumentFromTemplate(definition, options = {}) {
315
+ const now = options.now ?? /* @__PURE__ */ new Date();
316
+ const variables = {
317
+ ...buildTemplateVariables(
318
+ {
319
+ title: options.title ?? "",
320
+ type: options.type ?? definition.primitive
321
+ },
322
+ now
323
+ ),
324
+ ...options.variables ?? {}
325
+ };
326
+ const frontmatter = buildFrontmatterFromTemplate(
327
+ definition,
328
+ variables,
329
+ options.overrides,
330
+ options.frontmatter
331
+ );
332
+ const content = renderTemplate(definition.body, variables);
333
+ const markdown = import_gray_matter.default.stringify(content, frontmatter);
334
+ return {
335
+ frontmatter,
336
+ content,
337
+ markdown,
338
+ variables
339
+ };
340
+ }
341
+
342
+ // src/lib/task-utils.ts
343
+ function slugify(text) {
344
+ return text.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "").trim();
345
+ }
346
+ function getTasksDir(vaultPath) {
347
+ return path2.join(path2.resolve(vaultPath), "tasks");
348
+ }
349
+ function getBacklogDir(vaultPath) {
350
+ return path2.join(path2.resolve(vaultPath), "backlog");
351
+ }
352
+ function ensureTasksDir(vaultPath) {
353
+ const tasksDir = getTasksDir(vaultPath);
354
+ if (!fs2.existsSync(tasksDir)) {
355
+ fs2.mkdirSync(tasksDir, { recursive: true });
356
+ }
357
+ }
358
+ function ensureBacklogDir(vaultPath) {
359
+ const backlogDir = getBacklogDir(vaultPath);
360
+ if (!fs2.existsSync(backlogDir)) {
361
+ fs2.mkdirSync(backlogDir, { recursive: true });
362
+ }
363
+ }
364
+ function getTaskPath(vaultPath, slug) {
365
+ return path2.join(getTasksDir(vaultPath), `${slug}.md`);
366
+ }
367
+ function getBacklogPath(vaultPath, slug) {
368
+ return path2.join(getBacklogDir(vaultPath), `${slug}.md`);
369
+ }
370
+ function extractTitle(content) {
371
+ const match = content.match(/^#\s+(.+)$/m);
372
+ return match ? match[1].trim() : "";
373
+ }
374
+ function buildTaskFrontmatterFallback(now, options) {
375
+ const frontmatter = {
376
+ status: "open",
377
+ created: now,
378
+ updated: now
379
+ };
380
+ if (options.source) frontmatter.source = options.source;
381
+ if (options.owner) frontmatter.owner = options.owner;
382
+ if (options.project) frontmatter.project = options.project;
383
+ if (options.priority) frontmatter.priority = options.priority;
384
+ if (options.due) frontmatter.due = options.due;
385
+ if (options.tags && options.tags.length > 0) frontmatter.tags = options.tags;
386
+ if (options.description) frontmatter.description = options.description;
387
+ if (options.estimate) frontmatter.estimate = options.estimate;
388
+ if (options.parent) frontmatter.parent = options.parent;
389
+ if (options.depends_on && options.depends_on.length > 0) frontmatter.depends_on = options.depends_on;
390
+ return frontmatter;
391
+ }
392
+ function buildTaskContentFallback(title, options) {
393
+ let content = `# ${title}
394
+ `;
395
+ const links = [];
396
+ if (options.owner) links.push(`[[${options.owner}]]`);
397
+ if (options.project) links.push(`[[${options.project}]]`);
398
+ if (links.length > 0) {
399
+ content += `
400
+ ${links.join(" | ")}
401
+ `;
402
+ }
403
+ if (options.content) {
404
+ content += `
405
+ ${options.content}
406
+ `;
407
+ }
408
+ return content;
409
+ }
410
+ function buildTaskTemplateOverrides(options) {
411
+ const overrides = {};
412
+ if (options.source) overrides.source = options.source;
413
+ if (options.owner) overrides.owner = options.owner;
414
+ if (options.project) overrides.project = options.project;
415
+ if (options.priority) overrides.priority = options.priority;
416
+ if (options.due) overrides.due = options.due;
417
+ if (options.tags && options.tags.length > 0) overrides.tags = options.tags;
418
+ if (options.description) overrides.description = options.description;
419
+ if (options.estimate) overrides.estimate = options.estimate;
420
+ if (options.parent) overrides.parent = options.parent;
421
+ if (options.depends_on && options.depends_on.length > 0) overrides.depends_on = options.depends_on;
422
+ return overrides;
423
+ }
424
+ function buildTaskTemplateVariables(title, slug, options) {
425
+ const ownerLink = options.owner ? `[[${options.owner}]]` : "";
426
+ const projectLink = options.project ? `[[${options.project}]]` : "";
427
+ const linksLine = [ownerLink, projectLink].filter(Boolean).join(" | ");
428
+ return {
429
+ title,
430
+ slug,
431
+ source: options.source ?? "",
432
+ owner: options.owner ?? "",
433
+ project: options.project ?? "",
434
+ priority: options.priority ?? "",
435
+ due: options.due ?? "",
436
+ tags_csv: (options.tags || []).join(", "),
437
+ description: options.description ?? "",
438
+ estimate: options.estimate ?? "",
439
+ parent: options.parent ?? "",
440
+ depends_on_csv: (options.depends_on || []).join(", "),
441
+ content: options.content ?? "",
442
+ owner_link: ownerLink,
443
+ project_link: projectLink,
444
+ links_line: linksLine
445
+ };
446
+ }
447
+ var VALID_TASK_STATUSES = /* @__PURE__ */ new Set([
448
+ "open",
449
+ "in-progress",
450
+ "blocked",
451
+ "done"
452
+ ]);
453
+ function isTaskStatus(value) {
454
+ return typeof value === "string" && VALID_TASK_STATUSES.has(value);
455
+ }
456
+ function readBacklogItem(vaultPath, slug) {
457
+ const backlogPath = getBacklogPath(vaultPath, slug);
458
+ if (!fs2.existsSync(backlogPath)) {
459
+ return null;
460
+ }
461
+ try {
462
+ const raw = fs2.readFileSync(backlogPath, "utf-8");
463
+ const { data, content } = (0, import_gray_matter2.default)(raw);
464
+ const title = extractTitle(content) || slug;
465
+ return {
466
+ slug,
467
+ title,
468
+ content,
469
+ frontmatter: data,
470
+ path: backlogPath
471
+ };
472
+ } catch {
473
+ return null;
474
+ }
475
+ }
476
+ function listBacklogItems(vaultPath, filters) {
477
+ const backlogDir = getBacklogDir(vaultPath);
478
+ if (!fs2.existsSync(backlogDir)) {
479
+ return [];
480
+ }
481
+ const items = [];
482
+ const entries = fs2.readdirSync(backlogDir, { withFileTypes: true });
483
+ for (const entry of entries) {
484
+ if (!entry.isFile() || !entry.name.endsWith(".md")) {
485
+ continue;
486
+ }
487
+ const slug = entry.name.replace(/\.md$/, "");
488
+ const item = readBacklogItem(vaultPath, slug);
489
+ if (!item) continue;
490
+ if (filters) {
491
+ if (filters.project && item.frontmatter.project !== filters.project) continue;
492
+ if (filters.source && item.frontmatter.source !== filters.source) continue;
493
+ }
494
+ items.push(item);
495
+ }
496
+ return items.sort((a, b) => {
497
+ return new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime();
498
+ });
499
+ }
500
+ function createTask(vaultPath, title, options = {}) {
501
+ ensureTasksDir(vaultPath);
502
+ const slug = slugify(title);
503
+ const taskPath = getTaskPath(vaultPath, slug);
504
+ if (fs2.existsSync(taskPath)) {
505
+ throw new Error(`Task already exists: ${slug}`);
506
+ }
507
+ const now = (/* @__PURE__ */ new Date()).toISOString();
508
+ const template = loadSchemaTemplateDefinition("task", {
509
+ vaultPath: path2.resolve(vaultPath)
510
+ });
511
+ let frontmatter;
512
+ let content;
513
+ if (template) {
514
+ const rendered = renderDocumentFromTemplate(template, {
515
+ title,
516
+ type: "task",
517
+ now: new Date(now),
518
+ variables: buildTaskTemplateVariables(title, slug, options),
519
+ overrides: buildTaskTemplateOverrides(options),
520
+ frontmatter: { pruneEmpty: true }
521
+ });
522
+ const templateFrontmatter = rendered.frontmatter;
523
+ frontmatter = {
524
+ ...templateFrontmatter,
525
+ status: isTaskStatus(templateFrontmatter.status) ? templateFrontmatter.status : "open",
526
+ created: typeof templateFrontmatter.created === "string" && templateFrontmatter.created ? templateFrontmatter.created : now,
527
+ updated: typeof templateFrontmatter.updated === "string" && templateFrontmatter.updated ? templateFrontmatter.updated : now
528
+ };
529
+ content = rendered.content;
530
+ } else {
531
+ frontmatter = buildTaskFrontmatterFallback(now, options);
532
+ content = buildTaskContentFallback(title, options);
533
+ }
534
+ const fileContent = import_gray_matter2.default.stringify(content, frontmatter);
535
+ fs2.writeFileSync(taskPath, fileContent);
536
+ return {
537
+ slug,
538
+ title,
539
+ content,
540
+ frontmatter,
541
+ path: taskPath
542
+ };
543
+ }
544
+ function createBacklogItem(vaultPath, title, options = {}) {
545
+ ensureBacklogDir(vaultPath);
546
+ const slug = slugify(title);
547
+ const backlogPath = getBacklogPath(vaultPath, slug);
548
+ if (fs2.existsSync(backlogPath)) {
549
+ throw new Error(`Backlog item already exists: ${slug}`);
550
+ }
551
+ const now = (/* @__PURE__ */ new Date()).toISOString();
552
+ const frontmatter = {
553
+ created: now
554
+ };
555
+ if (options.source) frontmatter.source = options.source;
556
+ if (options.project) frontmatter.project = options.project;
557
+ if (options.tags && options.tags.length > 0) frontmatter.tags = options.tags;
558
+ let content = `# ${title}
559
+ `;
560
+ const links = [];
561
+ if (options.source) links.push(`[[${options.source}]]`);
562
+ if (options.project) links.push(`[[${options.project}]]`);
563
+ if (links.length > 0) {
564
+ content += `
565
+ ${links.join(" | ")}
566
+ `;
567
+ }
568
+ if (options.content) {
569
+ content += `
570
+ ${options.content}
571
+ `;
572
+ }
573
+ const fileContent = import_gray_matter2.default.stringify(content, frontmatter);
574
+ fs2.writeFileSync(backlogPath, fileContent);
575
+ return {
576
+ slug,
577
+ title,
578
+ content,
579
+ frontmatter,
580
+ path: backlogPath
581
+ };
582
+ }
583
+ function promoteBacklogItem(vaultPath, slug, options = {}) {
584
+ const backlogItem = readBacklogItem(vaultPath, slug);
585
+ if (!backlogItem) {
586
+ throw new Error(`Backlog item not found: ${slug}`);
587
+ }
588
+ const task = createTask(vaultPath, backlogItem.title, {
589
+ owner: options.owner,
590
+ project: backlogItem.frontmatter.project,
591
+ priority: options.priority,
592
+ due: options.due,
593
+ content: backlogItem.content.replace(/^#\s+.+\n/, "").trim(),
594
+ // Remove title from content
595
+ tags: backlogItem.frontmatter.tags
596
+ });
597
+ fs2.unlinkSync(backlogItem.path);
598
+ return task;
599
+ }
600
+
601
+ // src/commands/backlog.ts
602
+ function toDateStr(val) {
603
+ if (!val) return "unknown";
604
+ if (val instanceof Date) return val.toISOString().split("T")[0];
605
+ const s = String(val);
606
+ if (s.includes("T")) return s.split("T")[0];
607
+ return s;
608
+ }
609
+ function backlogAdd(vaultPath, title, options = {}) {
610
+ return createBacklogItem(vaultPath, title, {
611
+ source: options.source,
612
+ project: options.project,
613
+ content: options.content,
614
+ tags: options.tags
615
+ });
616
+ }
617
+ function backlogList(vaultPath, options = {}) {
618
+ const filters = {};
619
+ if (options.project) filters.project = options.project;
620
+ return listBacklogItems(vaultPath, filters);
621
+ }
622
+ function backlogPromote(vaultPath, slug, options = {}) {
623
+ return promoteBacklogItem(vaultPath, slug, {
624
+ owner: options.owner,
625
+ priority: options.priority,
626
+ due: options.due
627
+ });
628
+ }
629
+ function formatBacklogList(items) {
630
+ if (items.length === 0) {
631
+ return "No backlog items found.\n";
632
+ }
633
+ const headers = ["SOURCE", "PROJECT", "CREATED", "TITLE"];
634
+ const widths = [12, 16, 12, 40];
635
+ let output = headers.map((h, i) => h.padEnd(widths[i])).join(" ") + "\n";
636
+ for (const item of items) {
637
+ const source = item.frontmatter.source || "-";
638
+ const project = item.frontmatter.project || "-";
639
+ const created = toDateStr(item.frontmatter.created);
640
+ const title = item.title.length > widths[3] ? item.title.slice(0, widths[3] - 3) + "..." : item.title;
641
+ const row = [
642
+ source.padEnd(widths[0]),
643
+ project.padEnd(widths[1]),
644
+ created.padEnd(widths[2]),
645
+ title
646
+ ];
647
+ output += row.join(" ") + "\n";
648
+ }
649
+ return output;
650
+ }
651
+ function formatBacklogDetails(item) {
652
+ let output = "";
653
+ output += `# ${item.title}
654
+ `;
655
+ output += "-".repeat(40) + "\n";
656
+ if (item.frontmatter.source) {
657
+ output += `Source: ${item.frontmatter.source}
658
+ `;
659
+ }
660
+ if (item.frontmatter.project) {
661
+ output += `Project: ${item.frontmatter.project}
662
+ `;
663
+ }
664
+ if (item.frontmatter.tags && item.frontmatter.tags.length > 0) {
665
+ output += `Tags: ${item.frontmatter.tags.join(", ")}
666
+ `;
667
+ }
668
+ output += `Created: ${item.frontmatter.created}
669
+ `;
670
+ output += `File: ${item.path}
671
+ `;
672
+ output += "-".repeat(40) + "\n";
673
+ const contentWithoutTitle = item.content.replace(/^#\s+.+\n/, "").trim();
674
+ if (contentWithoutTitle) {
675
+ output += "\n" + contentWithoutTitle + "\n";
676
+ }
677
+ return output;
678
+ }
679
+ async function backlogCommand(vaultPath, action, args) {
680
+ const options = args.options || {};
681
+ switch (action) {
682
+ case "add": {
683
+ if (!args.title) {
684
+ throw new Error("Title is required for backlog add");
685
+ }
686
+ const item = backlogAdd(vaultPath, args.title, options);
687
+ console.log(`\u2713 Added to backlog: ${item.slug}`);
688
+ console.log(` Path: ${item.path}`);
689
+ break;
690
+ }
691
+ case "list": {
692
+ const items = backlogList(vaultPath, options);
693
+ if (options.json) {
694
+ console.log(JSON.stringify(items, null, 2));
695
+ } else {
696
+ console.log(formatBacklogList(items));
697
+ }
698
+ break;
699
+ }
700
+ case "promote": {
701
+ if (!args.slug) {
702
+ throw new Error("Backlog item slug is required for promote");
703
+ }
704
+ const task = backlogPromote(vaultPath, args.slug, options);
705
+ console.log(`\u2713 Promoted to task: ${task.slug}`);
706
+ console.log(` Path: ${task.path}`);
707
+ break;
708
+ }
709
+ default:
710
+ throw new Error(`Unknown backlog action: ${action}`);
711
+ }
712
+ }
713
+ // Annotate the CommonJS export names for ESM import in node:
714
+ 0 && (module.exports = {
715
+ backlogAdd,
716
+ backlogCommand,
717
+ backlogList,
718
+ backlogPromote,
719
+ formatBacklogDetails,
720
+ formatBacklogList
721
+ });