clawvault 3.0.0 → 3.1.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 (60) hide show
  1. package/README.md +156 -105
  2. package/bin/clawvault.js +0 -2
  3. package/bin/register-core-commands.js +20 -2
  4. package/dist/{chunk-3D6BCTP6.js → chunk-33UGEQRT.js} +70 -145
  5. package/dist/{chunk-ZVVFWOLW.js → chunk-3WRJEKN4.js} +1 -1
  6. package/dist/{chunk-DEFFDRVP.js → chunk-3ZIH425O.js} +3 -70
  7. package/dist/{chunk-K234IDRJ.js → chunk-D2H45LON.js} +1 -0
  8. package/dist/{chunk-YKTA5JOJ.js → chunk-H62BP7RI.js} +3 -3
  9. package/dist/{chunk-WGRQ6HDV.js → chunk-LI4O6NVK.js} +1 -1
  10. package/dist/{chunk-7R7O6STJ.js → chunk-OCGVIN3L.js} +1 -1
  11. package/dist/{chunk-GAJV4IGR.js → chunk-YCUNCH2I.js} +3 -7
  12. package/dist/cli/index.cjs +10 -1459
  13. package/dist/cli/index.js +5 -8
  14. package/dist/commands/compat.cjs +70 -145
  15. package/dist/commands/compat.js +1 -1
  16. package/dist/commands/context.cjs +1 -0
  17. package/dist/commands/context.js +3 -3
  18. package/dist/commands/doctor.cjs +68 -144
  19. package/dist/commands/doctor.js +4 -4
  20. package/dist/commands/embed.js +2 -2
  21. package/dist/commands/setup.cjs +2 -69
  22. package/dist/commands/setup.d.cts +0 -1
  23. package/dist/commands/setup.d.ts +0 -1
  24. package/dist/commands/setup.js +2 -2
  25. package/dist/commands/sleep.cjs +1 -0
  26. package/dist/commands/sleep.js +2 -2
  27. package/dist/commands/status.cjs +1 -0
  28. package/dist/commands/status.js +2 -2
  29. package/dist/commands/wake.cjs +1 -0
  30. package/dist/commands/wake.js +2 -2
  31. package/dist/index.cjs +447 -2600
  32. package/dist/index.d.cts +0 -4
  33. package/dist/index.d.ts +0 -4
  34. package/dist/index.js +8 -69
  35. package/dist/plugin/index.cjs +3 -3
  36. package/dist/plugin/index.js +10 -10
  37. package/package.json +11 -17
  38. package/bin/register-tailscale-commands.js +0 -106
  39. package/dist/chunk-IVRIKYFE.js +0 -520
  40. package/dist/chunk-THRJVD4L.js +0 -373
  41. package/dist/chunk-TIGW564L.js +0 -628
  42. package/dist/commands/tailscale.cjs +0 -1532
  43. package/dist/commands/tailscale.d.cts +0 -52
  44. package/dist/commands/tailscale.d.ts +0 -52
  45. package/dist/commands/tailscale.js +0 -26
  46. package/dist/lib/canvas-layout.cjs +0 -136
  47. package/dist/lib/canvas-layout.d.cts +0 -31
  48. package/dist/lib/canvas-layout.d.ts +0 -31
  49. package/dist/lib/canvas-layout.js +0 -92
  50. package/dist/lib/tailscale.cjs +0 -1183
  51. package/dist/lib/tailscale.d.cts +0 -225
  52. package/dist/lib/tailscale.d.ts +0 -225
  53. package/dist/lib/tailscale.js +0 -50
  54. package/dist/lib/webdav.cjs +0 -568
  55. package/dist/lib/webdav.d.cts +0 -109
  56. package/dist/lib/webdav.d.ts +0 -109
  57. package/dist/lib/webdav.js +0 -35
  58. package/hooks/clawvault/HOOK.md +0 -83
  59. package/hooks/clawvault/handler.js +0 -879
  60. package/hooks/clawvault/handler.test.js +0 -354
package/dist/cli/index.js CHANGED
@@ -1,9 +1,6 @@
1
1
  import {
2
2
  registerCliCommands
3
- } from "../chunk-GAJV4IGR.js";
4
- import "../chunk-THRJVD4L.js";
5
- import "../chunk-TIGW564L.js";
6
- import "../chunk-IVRIKYFE.js";
3
+ } from "../chunk-YCUNCH2I.js";
7
4
  import "../chunk-F2JEUD4J.js";
8
5
  import "../chunk-P5EPF6MB.js";
9
6
  import "../chunk-SJSFRIYS.js";
@@ -12,7 +9,7 @@ import "../chunk-LNJA2UGL.js";
12
9
  import "../chunk-3NSBOUT3.js";
13
10
  import "../chunk-62YTUT6J.js";
14
11
  import "../chunk-HRLWZGMA.js";
15
- import "../chunk-7R7O6STJ.js";
12
+ import "../chunk-OCGVIN3L.js";
16
13
  import "../chunk-U55BGUAU.js";
17
14
  import "../chunk-E7MFQB6D.js";
18
15
  import "../chunk-ITPEXLHA.js";
@@ -22,9 +19,9 @@ import "../chunk-MXSSG3QU.js";
22
19
  import "../chunk-N2AXRYLC.js";
23
20
  import "../chunk-LYHGEHXG.js";
24
21
  import "../chunk-7766SIJP.js";
25
- import "../chunk-ZVVFWOLW.js";
26
- import "../chunk-WGRQ6HDV.js";
27
- import "../chunk-K234IDRJ.js";
22
+ import "../chunk-3WRJEKN4.js";
23
+ import "../chunk-LI4O6NVK.js";
24
+ import "../chunk-D2H45LON.js";
28
25
  import "../chunk-2CDEETQN.js";
29
26
  import "../chunk-ZZA73MFY.js";
30
27
  import "../chunk-QK3UCXWL.js";
@@ -41,8 +41,6 @@ var import_gray_matter = __toESM(require("gray-matter"), 1);
41
41
  var import_child_process = require("child_process");
42
42
  var import_url = require("url");
43
43
  var import_meta = {};
44
- var REQUIRED_HOOK_EVENTS = ["gateway:startup", "command:new", "session:start"];
45
- var REQUIRED_HOOK_BIN = "clawvault";
46
44
  function readOptionalFile(filePath) {
47
45
  try {
48
46
  if (!fs.existsSync(filePath)) return null;
@@ -61,19 +59,6 @@ function findPackageRoot() {
61
59
  }
62
60
  return path.dirname((0, import_url.fileURLToPath)(import_meta.url));
63
61
  }
64
- function resolveOpenClawHooksDir() {
65
- const candidates = [
66
- path.join(process.env.HOME || "", ".openclaw", "hooks", "clawvault"),
67
- path.join(process.env.OPENCLAW_HOME || "", "hooks", "clawvault"),
68
- path.join(process.env.OPENCLAW_STATE_DIR || "", "hooks", "clawvault")
69
- ].filter((p) => p && !p.startsWith(path.sep + "hooks"));
70
- for (const candidate of candidates) {
71
- if (fs.existsSync(candidate)) {
72
- return candidate;
73
- }
74
- }
75
- return null;
76
- }
77
62
  function resolveProjectFile(relativePath, baseDir) {
78
63
  if (baseDir) {
79
64
  return path.resolve(baseDir, relativePath);
@@ -82,20 +67,6 @@ function resolveProjectFile(relativePath, baseDir) {
82
67
  if (fs.existsSync(fromCwd)) {
83
68
  return fromCwd;
84
69
  }
85
- if (relativePath.startsWith("hooks/clawvault/")) {
86
- const hooksDir = resolveOpenClawHooksDir();
87
- if (hooksDir) {
88
- const hookRelative = relativePath.replace("hooks/clawvault/", "");
89
- const fromHooks = path.resolve(hooksDir, hookRelative);
90
- if (fs.existsSync(fromHooks)) {
91
- return fromHooks;
92
- }
93
- const fromNestedHooks = path.resolve(hooksDir, "hooks", "clawvault", hookRelative);
94
- if (fs.existsSync(fromNestedHooks)) {
95
- return fromNestedHooks;
96
- }
97
- }
98
- }
99
70
  return path.resolve(findPackageRoot(), relativePath);
100
71
  }
101
72
  function checkOpenClawCli() {
@@ -105,7 +76,7 @@ function checkOpenClawCli() {
105
76
  label: "openclaw CLI available",
106
77
  status: "warn",
107
78
  detail: "openclaw binary not found",
108
- hint: "Install OpenClaw CLI to enable hook runtime validation."
79
+ hint: "Install OpenClaw CLI to enable plugin runtime validation."
109
80
  };
110
81
  }
111
82
  if (typeof result.status === "number" && result.status !== 0) {
@@ -126,152 +97,106 @@ function checkOpenClawCli() {
126
97
  }
127
98
  return { label: "openclaw CLI available", status: "ok" };
128
99
  }
129
- function checkPackageHookRegistration(options) {
130
- let packageRaw = readOptionalFile(resolveProjectFile("package.json", options.baseDir));
131
- if (packageRaw && !options.baseDir) {
132
- try {
133
- const parsed = JSON.parse(packageRaw);
134
- if (!parsed.openclaw?.hooks) {
135
- const fallbackPath = path.resolve(findPackageRoot(), "package.json");
136
- const fallbackRaw = readOptionalFile(fallbackPath);
137
- if (fallbackRaw) packageRaw = fallbackRaw;
138
- }
139
- } catch {
140
- }
141
- }
142
- if (!packageRaw) {
100
+ function checkPluginManifest(options) {
101
+ const manifestRaw = readOptionalFile(
102
+ resolveProjectFile("openclaw.plugin.json", options.baseDir)
103
+ );
104
+ if (!manifestRaw) {
143
105
  return {
144
- label: "package hook registration",
106
+ label: "plugin manifest",
145
107
  status: "error",
146
- detail: "package.json not found"
108
+ detail: "openclaw.plugin.json not found",
109
+ hint: "Create openclaw.plugin.json with id, kind, and configSchema fields."
147
110
  };
148
111
  }
149
112
  try {
150
- const parsed = JSON.parse(packageRaw);
151
- const registeredHooks = parsed.openclaw?.hooks ?? [];
152
- if (registeredHooks.includes("./hooks/clawvault")) {
113
+ const manifest = JSON.parse(manifestRaw);
114
+ const issues = [];
115
+ if (!manifest.id) issues.push("missing id");
116
+ if (!manifest.kind) issues.push("missing kind");
117
+ if (!manifest.configSchema) issues.push("missing configSchema");
118
+ if (issues.length > 0) {
153
119
  return {
154
- label: "package hook registration",
155
- status: "ok",
156
- detail: "./hooks/clawvault"
120
+ label: "plugin manifest",
121
+ status: "error",
122
+ detail: issues.join(", ")
157
123
  };
158
124
  }
159
125
  return {
160
- label: "package hook registration",
161
- status: "error",
162
- detail: "Missing ./hooks/clawvault in package openclaw.hooks"
126
+ label: "plugin manifest",
127
+ status: "ok",
128
+ detail: `id=${manifest.id} kind=${manifest.kind}`
163
129
  };
164
130
  } catch (err) {
165
131
  return {
166
- label: "package hook registration",
132
+ label: "plugin manifest",
167
133
  status: "error",
168
- detail: err?.message || "Unable to parse package.json"
134
+ detail: err?.message || "Unable to parse openclaw.plugin.json"
169
135
  };
170
136
  }
171
137
  }
172
- function checkHookManifest(options) {
173
- const hookRaw = readOptionalFile(resolveProjectFile("hooks/clawvault/HOOK.md", options.baseDir));
174
- if (!hookRaw) {
138
+ function checkPluginExtensions(options) {
139
+ let packageRaw = readOptionalFile(
140
+ resolveProjectFile("package.json", options.baseDir)
141
+ );
142
+ if (packageRaw && !options.baseDir) {
143
+ try {
144
+ const parsed = JSON.parse(packageRaw);
145
+ if (!parsed.openclaw?.extensions) {
146
+ const fallbackPath = path.resolve(findPackageRoot(), "package.json");
147
+ const fallbackRaw = readOptionalFile(fallbackPath);
148
+ if (fallbackRaw) packageRaw = fallbackRaw;
149
+ }
150
+ } catch {
151
+ }
152
+ }
153
+ if (!packageRaw) {
175
154
  return {
176
- label: "hook manifest",
155
+ label: "plugin extensions registration",
177
156
  status: "error",
178
- detail: "HOOK.md not found"
157
+ detail: "package.json not found"
179
158
  };
180
159
  }
181
160
  try {
182
- const parsed = (0, import_gray_matter.default)(hookRaw);
183
- const openclaw = parsed.data?.metadata?.openclaw;
184
- const events = Array.isArray(openclaw?.events) ? openclaw?.events ?? [] : [];
185
- const missingEvents = REQUIRED_HOOK_EVENTS.filter((event) => !events.includes(event));
186
- if (missingEvents.length === 0) {
161
+ const parsed = JSON.parse(packageRaw);
162
+ const extensions = parsed.openclaw?.extensions ?? [];
163
+ if (extensions.length === 0) {
187
164
  return {
188
- label: "hook manifest events",
189
- status: "ok",
190
- detail: events.join(", ")
165
+ label: "plugin extensions registration",
166
+ status: "error",
167
+ detail: "Missing openclaw.extensions in package.json",
168
+ hint: 'Add openclaw.extensions: ["./dist/plugin/index.js"] to package.json.'
191
169
  };
192
170
  }
193
- return {
194
- label: "hook manifest events",
195
- status: "error",
196
- detail: `Missing events: ${missingEvents.join(", ")}`
197
- };
198
- } catch (err) {
199
- return {
200
- label: "hook manifest events",
201
- status: "error",
202
- detail: err?.message || "Unable to parse HOOK.md frontmatter"
203
- };
204
- }
205
- }
206
- function checkHookManifestRequirements(options) {
207
- const hookRaw = readOptionalFile(resolveProjectFile("hooks/clawvault/HOOK.md", options.baseDir));
208
- if (!hookRaw) {
209
- return {
210
- label: "hook manifest requirements",
211
- status: "error",
212
- detail: "HOOK.md not found"
213
- };
214
- }
215
- try {
216
- const parsed = (0, import_gray_matter.default)(hookRaw);
217
- const requiresBins = parsed.data?.metadata?.openclaw?.requires?.bins;
218
- const bins = Array.isArray(requiresBins) ? requiresBins : [];
219
- if (bins.includes(REQUIRED_HOOK_BIN)) {
171
+ const baseDir = options.baseDir || findPackageRoot();
172
+ const missing = extensions.filter(
173
+ (ext) => !fs.existsSync(path.resolve(baseDir, ext))
174
+ );
175
+ if (missing.length > 0) {
220
176
  return {
221
- label: "hook manifest requirements",
222
- status: "ok",
223
- detail: `bins: ${bins.join(", ")}`
177
+ label: "plugin extensions registration",
178
+ status: "error",
179
+ detail: `Entry file(s) not found: ${missing.join(", ")}`,
180
+ hint: "Run npm run build to generate dist files."
224
181
  };
225
182
  }
226
183
  return {
227
- label: "hook manifest requirements",
228
- status: "warn",
229
- detail: `Missing required hook bin "${REQUIRED_HOOK_BIN}"`,
230
- hint: 'Add metadata.openclaw.requires.bins: ["clawvault"] to hooks/clawvault/HOOK.md.'
184
+ label: "plugin extensions registration",
185
+ status: "ok",
186
+ detail: extensions.join(", ")
231
187
  };
232
188
  } catch (err) {
233
189
  return {
234
- label: "hook manifest requirements",
235
- status: "error",
236
- detail: err?.message || "Unable to parse HOOK.md frontmatter"
237
- };
238
- }
239
- }
240
- function checkHookHandlerSafety(options) {
241
- const handlerRaw = readOptionalFile(resolveProjectFile("hooks/clawvault/handler.js", options.baseDir));
242
- if (!handlerRaw) {
243
- return {
244
- label: "hook handler script",
190
+ label: "plugin extensions registration",
245
191
  status: "error",
246
- detail: "handler.js not found"
247
- };
248
- }
249
- const usesExecFileSync = handlerRaw.includes("execFileSync");
250
- const usesExecSync = /\bexecSync\b/.test(handlerRaw);
251
- const enablesShell = /\bshell\s*:\s*true\b/.test(handlerRaw);
252
- const delegatesAutoProfile = /['"]--profile['"]\s*,\s*['"]auto['"]/.test(handlerRaw);
253
- const violations = [];
254
- if (!usesExecFileSync || usesExecSync) {
255
- violations.push("execFileSync-only execution path");
256
- }
257
- if (enablesShell) {
258
- violations.push("shell:false execution option");
259
- }
260
- if (!delegatesAutoProfile) {
261
- violations.push("shared context profile delegation (--profile auto)");
262
- }
263
- if (violations.length > 0) {
264
- return {
265
- label: "hook handler safety",
266
- status: "warn",
267
- detail: `Missing conventions: ${violations.join(", ")}`,
268
- hint: "Use execFileSync (no shell), avoid execSync, and delegate profile inference via --profile auto."
192
+ detail: err?.message || "Unable to parse package.json"
269
193
  };
270
194
  }
271
- return { label: "hook handler safety", status: "ok" };
272
195
  }
273
196
  function checkSkillMetadata(options) {
274
- const skillRaw = readOptionalFile(resolveProjectFile("SKILL.md", options.baseDir));
197
+ const skillRaw = readOptionalFile(
198
+ resolveProjectFile("SKILL.md", options.baseDir)
199
+ );
275
200
  if (!skillRaw) {
276
201
  return {
277
202
  label: "skill metadata",
@@ -310,10 +235,8 @@ function checkSkillMetadata(options) {
310
235
  function checkOpenClawCompatibility(options = {}) {
311
236
  const checks = [
312
237
  checkOpenClawCli(),
313
- checkPackageHookRegistration(options),
314
- checkHookManifest(options),
315
- checkHookManifestRequirements(options),
316
- checkHookHandlerSafety(options),
238
+ checkPluginManifest(options),
239
+ checkPluginExtensions(options),
317
240
  checkSkillMetadata(options)
318
241
  ];
319
242
  const warnings = checks.filter((check) => check.status === "warn").length;
@@ -333,7 +256,9 @@ function formatCompatibilityReport(report) {
333
256
  lines.push("");
334
257
  for (const check of report.checks) {
335
258
  const prefix = check.status === "ok" ? "\u2713" : check.status === "warn" ? "\u26A0" : "\u2717";
336
- lines.push(`${prefix} ${check.label}${check.detail ? ` \u2014 ${check.detail}` : ""}`);
259
+ lines.push(
260
+ `${prefix} ${check.label}${check.detail ? ` \u2014 ${check.detail}` : ""}`
261
+ );
337
262
  if (check.hint) {
338
263
  lines.push(` ${check.hint}`);
339
264
  }
@@ -2,7 +2,7 @@ import {
2
2
  checkOpenClawCompatibility,
3
3
  compatCommand,
4
4
  compatibilityExitCode
5
- } from "../chunk-3D6BCTP6.js";
5
+ } from "../chunk-33UGEQRT.js";
6
6
  import "../chunk-3RG5ZIWI.js";
7
7
  export {
8
8
  checkOpenClawCompatibility,
@@ -354,6 +354,7 @@ function stripQmdNoise(raw) {
354
354
  function parseQmdOutput(raw) {
355
355
  const trimmed = stripQmdNoise(raw).trim();
356
356
  if (!trimmed) return [];
357
+ if (trimmed.startsWith("No results") || trimmed.startsWith("No matches")) return [];
357
358
  const direct = tryParseJson(trimmed);
358
359
  const extracted = direct ? null : extractJsonPayload(trimmed);
359
360
  const parsed = direct ?? (extracted ? tryParseJson(extracted) : null);
@@ -3,9 +3,9 @@ import {
3
3
  contextCommand,
4
4
  formatContextMarkdown,
5
5
  registerContextCommand
6
- } from "../chunk-ZVVFWOLW.js";
7
- import "../chunk-WGRQ6HDV.js";
8
- import "../chunk-K234IDRJ.js";
6
+ } from "../chunk-3WRJEKN4.js";
7
+ import "../chunk-LI4O6NVK.js";
8
+ import "../chunk-D2H45LON.js";
9
9
  import "../chunk-2CDEETQN.js";
10
10
  import "../chunk-ZZA73MFY.js";
11
11
  import "../chunk-QK3UCXWL.js";
@@ -145,6 +145,7 @@ function stripQmdNoise(raw) {
145
145
  function parseQmdOutput(raw) {
146
146
  const trimmed = stripQmdNoise(raw).trim();
147
147
  if (!trimmed) return [];
148
+ if (trimmed.startsWith("No results") || trimmed.startsWith("No matches")) return [];
148
149
  const direct = tryParseJson(trimmed);
149
150
  const extracted = direct ? null : extractJsonPayload(trimmed);
150
151
  const parsed = direct ?? (extracted ? tryParseJson(extracted) : null);
@@ -2466,8 +2467,6 @@ var import_gray_matter7 = __toESM(require("gray-matter"), 1);
2466
2467
  var import_child_process2 = require("child_process");
2467
2468
  var import_url2 = require("url");
2468
2469
  var import_meta2 = {};
2469
- var REQUIRED_HOOK_EVENTS = ["gateway:startup", "command:new", "session:start"];
2470
- var REQUIRED_HOOK_BIN = "clawvault";
2471
2470
  function readOptionalFile(filePath) {
2472
2471
  try {
2473
2472
  if (!fs7.existsSync(filePath)) return null;
@@ -2486,19 +2485,6 @@ function findPackageRoot() {
2486
2485
  }
2487
2486
  return path8.dirname((0, import_url2.fileURLToPath)(import_meta2.url));
2488
2487
  }
2489
- function resolveOpenClawHooksDir() {
2490
- const candidates = [
2491
- path8.join(process.env.HOME || "", ".openclaw", "hooks", "clawvault"),
2492
- path8.join(process.env.OPENCLAW_HOME || "", "hooks", "clawvault"),
2493
- path8.join(process.env.OPENCLAW_STATE_DIR || "", "hooks", "clawvault")
2494
- ].filter((p) => p && !p.startsWith(path8.sep + "hooks"));
2495
- for (const candidate of candidates) {
2496
- if (fs7.existsSync(candidate)) {
2497
- return candidate;
2498
- }
2499
- }
2500
- return null;
2501
- }
2502
2488
  function resolveProjectFile(relativePath, baseDir) {
2503
2489
  if (baseDir) {
2504
2490
  return path8.resolve(baseDir, relativePath);
@@ -2507,20 +2493,6 @@ function resolveProjectFile(relativePath, baseDir) {
2507
2493
  if (fs7.existsSync(fromCwd)) {
2508
2494
  return fromCwd;
2509
2495
  }
2510
- if (relativePath.startsWith("hooks/clawvault/")) {
2511
- const hooksDir = resolveOpenClawHooksDir();
2512
- if (hooksDir) {
2513
- const hookRelative = relativePath.replace("hooks/clawvault/", "");
2514
- const fromHooks = path8.resolve(hooksDir, hookRelative);
2515
- if (fs7.existsSync(fromHooks)) {
2516
- return fromHooks;
2517
- }
2518
- const fromNestedHooks = path8.resolve(hooksDir, "hooks", "clawvault", hookRelative);
2519
- if (fs7.existsSync(fromNestedHooks)) {
2520
- return fromNestedHooks;
2521
- }
2522
- }
2523
- }
2524
2496
  return path8.resolve(findPackageRoot(), relativePath);
2525
2497
  }
2526
2498
  function checkOpenClawCli() {
@@ -2530,7 +2502,7 @@ function checkOpenClawCli() {
2530
2502
  label: "openclaw CLI available",
2531
2503
  status: "warn",
2532
2504
  detail: "openclaw binary not found",
2533
- hint: "Install OpenClaw CLI to enable hook runtime validation."
2505
+ hint: "Install OpenClaw CLI to enable plugin runtime validation."
2534
2506
  };
2535
2507
  }
2536
2508
  if (typeof result.status === "number" && result.status !== 0) {
@@ -2551,152 +2523,106 @@ function checkOpenClawCli() {
2551
2523
  }
2552
2524
  return { label: "openclaw CLI available", status: "ok" };
2553
2525
  }
2554
- function checkPackageHookRegistration(options) {
2555
- let packageRaw = readOptionalFile(resolveProjectFile("package.json", options.baseDir));
2556
- if (packageRaw && !options.baseDir) {
2557
- try {
2558
- const parsed = JSON.parse(packageRaw);
2559
- if (!parsed.openclaw?.hooks) {
2560
- const fallbackPath = path8.resolve(findPackageRoot(), "package.json");
2561
- const fallbackRaw = readOptionalFile(fallbackPath);
2562
- if (fallbackRaw) packageRaw = fallbackRaw;
2563
- }
2564
- } catch {
2565
- }
2566
- }
2567
- if (!packageRaw) {
2526
+ function checkPluginManifest(options) {
2527
+ const manifestRaw = readOptionalFile(
2528
+ resolveProjectFile("openclaw.plugin.json", options.baseDir)
2529
+ );
2530
+ if (!manifestRaw) {
2568
2531
  return {
2569
- label: "package hook registration",
2532
+ label: "plugin manifest",
2570
2533
  status: "error",
2571
- detail: "package.json not found"
2534
+ detail: "openclaw.plugin.json not found",
2535
+ hint: "Create openclaw.plugin.json with id, kind, and configSchema fields."
2572
2536
  };
2573
2537
  }
2574
2538
  try {
2575
- const parsed = JSON.parse(packageRaw);
2576
- const registeredHooks = parsed.openclaw?.hooks ?? [];
2577
- if (registeredHooks.includes("./hooks/clawvault")) {
2539
+ const manifest = JSON.parse(manifestRaw);
2540
+ const issues = [];
2541
+ if (!manifest.id) issues.push("missing id");
2542
+ if (!manifest.kind) issues.push("missing kind");
2543
+ if (!manifest.configSchema) issues.push("missing configSchema");
2544
+ if (issues.length > 0) {
2578
2545
  return {
2579
- label: "package hook registration",
2580
- status: "ok",
2581
- detail: "./hooks/clawvault"
2546
+ label: "plugin manifest",
2547
+ status: "error",
2548
+ detail: issues.join(", ")
2582
2549
  };
2583
2550
  }
2584
2551
  return {
2585
- label: "package hook registration",
2586
- status: "error",
2587
- detail: "Missing ./hooks/clawvault in package openclaw.hooks"
2552
+ label: "plugin manifest",
2553
+ status: "ok",
2554
+ detail: `id=${manifest.id} kind=${manifest.kind}`
2588
2555
  };
2589
2556
  } catch (err) {
2590
2557
  return {
2591
- label: "package hook registration",
2558
+ label: "plugin manifest",
2592
2559
  status: "error",
2593
- detail: err?.message || "Unable to parse package.json"
2560
+ detail: err?.message || "Unable to parse openclaw.plugin.json"
2594
2561
  };
2595
2562
  }
2596
2563
  }
2597
- function checkHookManifest(options) {
2598
- const hookRaw = readOptionalFile(resolveProjectFile("hooks/clawvault/HOOK.md", options.baseDir));
2599
- if (!hookRaw) {
2564
+ function checkPluginExtensions(options) {
2565
+ let packageRaw = readOptionalFile(
2566
+ resolveProjectFile("package.json", options.baseDir)
2567
+ );
2568
+ if (packageRaw && !options.baseDir) {
2569
+ try {
2570
+ const parsed = JSON.parse(packageRaw);
2571
+ if (!parsed.openclaw?.extensions) {
2572
+ const fallbackPath = path8.resolve(findPackageRoot(), "package.json");
2573
+ const fallbackRaw = readOptionalFile(fallbackPath);
2574
+ if (fallbackRaw) packageRaw = fallbackRaw;
2575
+ }
2576
+ } catch {
2577
+ }
2578
+ }
2579
+ if (!packageRaw) {
2600
2580
  return {
2601
- label: "hook manifest",
2581
+ label: "plugin extensions registration",
2602
2582
  status: "error",
2603
- detail: "HOOK.md not found"
2583
+ detail: "package.json not found"
2604
2584
  };
2605
2585
  }
2606
2586
  try {
2607
- const parsed = (0, import_gray_matter7.default)(hookRaw);
2608
- const openclaw = parsed.data?.metadata?.openclaw;
2609
- const events = Array.isArray(openclaw?.events) ? openclaw?.events ?? [] : [];
2610
- const missingEvents = REQUIRED_HOOK_EVENTS.filter((event) => !events.includes(event));
2611
- if (missingEvents.length === 0) {
2587
+ const parsed = JSON.parse(packageRaw);
2588
+ const extensions = parsed.openclaw?.extensions ?? [];
2589
+ if (extensions.length === 0) {
2612
2590
  return {
2613
- label: "hook manifest events",
2614
- status: "ok",
2615
- detail: events.join(", ")
2591
+ label: "plugin extensions registration",
2592
+ status: "error",
2593
+ detail: "Missing openclaw.extensions in package.json",
2594
+ hint: 'Add openclaw.extensions: ["./dist/plugin/index.js"] to package.json.'
2616
2595
  };
2617
2596
  }
2618
- return {
2619
- label: "hook manifest events",
2620
- status: "error",
2621
- detail: `Missing events: ${missingEvents.join(", ")}`
2622
- };
2623
- } catch (err) {
2624
- return {
2625
- label: "hook manifest events",
2626
- status: "error",
2627
- detail: err?.message || "Unable to parse HOOK.md frontmatter"
2628
- };
2629
- }
2630
- }
2631
- function checkHookManifestRequirements(options) {
2632
- const hookRaw = readOptionalFile(resolveProjectFile("hooks/clawvault/HOOK.md", options.baseDir));
2633
- if (!hookRaw) {
2634
- return {
2635
- label: "hook manifest requirements",
2636
- status: "error",
2637
- detail: "HOOK.md not found"
2638
- };
2639
- }
2640
- try {
2641
- const parsed = (0, import_gray_matter7.default)(hookRaw);
2642
- const requiresBins = parsed.data?.metadata?.openclaw?.requires?.bins;
2643
- const bins = Array.isArray(requiresBins) ? requiresBins : [];
2644
- if (bins.includes(REQUIRED_HOOK_BIN)) {
2597
+ const baseDir = options.baseDir || findPackageRoot();
2598
+ const missing = extensions.filter(
2599
+ (ext) => !fs7.existsSync(path8.resolve(baseDir, ext))
2600
+ );
2601
+ if (missing.length > 0) {
2645
2602
  return {
2646
- label: "hook manifest requirements",
2647
- status: "ok",
2648
- detail: `bins: ${bins.join(", ")}`
2603
+ label: "plugin extensions registration",
2604
+ status: "error",
2605
+ detail: `Entry file(s) not found: ${missing.join(", ")}`,
2606
+ hint: "Run npm run build to generate dist files."
2649
2607
  };
2650
2608
  }
2651
2609
  return {
2652
- label: "hook manifest requirements",
2653
- status: "warn",
2654
- detail: `Missing required hook bin "${REQUIRED_HOOK_BIN}"`,
2655
- hint: 'Add metadata.openclaw.requires.bins: ["clawvault"] to hooks/clawvault/HOOK.md.'
2610
+ label: "plugin extensions registration",
2611
+ status: "ok",
2612
+ detail: extensions.join(", ")
2656
2613
  };
2657
2614
  } catch (err) {
2658
2615
  return {
2659
- label: "hook manifest requirements",
2660
- status: "error",
2661
- detail: err?.message || "Unable to parse HOOK.md frontmatter"
2662
- };
2663
- }
2664
- }
2665
- function checkHookHandlerSafety(options) {
2666
- const handlerRaw = readOptionalFile(resolveProjectFile("hooks/clawvault/handler.js", options.baseDir));
2667
- if (!handlerRaw) {
2668
- return {
2669
- label: "hook handler script",
2616
+ label: "plugin extensions registration",
2670
2617
  status: "error",
2671
- detail: "handler.js not found"
2672
- };
2673
- }
2674
- const usesExecFileSync = handlerRaw.includes("execFileSync");
2675
- const usesExecSync = /\bexecSync\b/.test(handlerRaw);
2676
- const enablesShell = /\bshell\s*:\s*true\b/.test(handlerRaw);
2677
- const delegatesAutoProfile = /['"]--profile['"]\s*,\s*['"]auto['"]/.test(handlerRaw);
2678
- const violations = [];
2679
- if (!usesExecFileSync || usesExecSync) {
2680
- violations.push("execFileSync-only execution path");
2681
- }
2682
- if (enablesShell) {
2683
- violations.push("shell:false execution option");
2684
- }
2685
- if (!delegatesAutoProfile) {
2686
- violations.push("shared context profile delegation (--profile auto)");
2687
- }
2688
- if (violations.length > 0) {
2689
- return {
2690
- label: "hook handler safety",
2691
- status: "warn",
2692
- detail: `Missing conventions: ${violations.join(", ")}`,
2693
- hint: "Use execFileSync (no shell), avoid execSync, and delegate profile inference via --profile auto."
2618
+ detail: err?.message || "Unable to parse package.json"
2694
2619
  };
2695
2620
  }
2696
- return { label: "hook handler safety", status: "ok" };
2697
2621
  }
2698
2622
  function checkSkillMetadata(options) {
2699
- const skillRaw = readOptionalFile(resolveProjectFile("SKILL.md", options.baseDir));
2623
+ const skillRaw = readOptionalFile(
2624
+ resolveProjectFile("SKILL.md", options.baseDir)
2625
+ );
2700
2626
  if (!skillRaw) {
2701
2627
  return {
2702
2628
  label: "skill metadata",
@@ -2735,10 +2661,8 @@ function checkSkillMetadata(options) {
2735
2661
  function checkOpenClawCompatibility(options = {}) {
2736
2662
  const checks = [
2737
2663
  checkOpenClawCli(),
2738
- checkPackageHookRegistration(options),
2739
- checkHookManifest(options),
2740
- checkHookManifestRequirements(options),
2741
- checkHookHandlerSafety(options),
2664
+ checkPluginManifest(options),
2665
+ checkPluginExtensions(options),
2742
2666
  checkSkillMetadata(options)
2743
2667
  ];
2744
2668
  const warnings = checks.filter((check) => check.status === "warn").length;