clawchef 0.1.9 → 0.1.10

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.
@@ -76,6 +76,9 @@ function isHttpUrl(value) {
76
76
  return false;
77
77
  }
78
78
  }
79
+ function isNotFoundError(err) {
80
+ return typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT";
81
+ }
79
82
  function resolveFileRef(recipeOrigin, reference) {
80
83
  if (isHttpUrl(reference)) {
81
84
  return { kind: "url", value: reference };
@@ -195,20 +198,31 @@ export async function runRecipe(recipe, recipeOrigin, options, logger) {
195
198
  assetDirStat = await stat(resolvedAssets.value);
196
199
  }
197
200
  catch (err) {
198
- const message = err instanceof Error ? err.message : String(err);
199
- throw new ClawChefError(`openclaw.root.assets path is not accessible: ${resolvedAssets.value} (${message})`);
201
+ if (isNotFoundError(err)) {
202
+ logger.warn(`Skipping missing openclaw.root.assets directory: ${resolvedAssets.value}`);
203
+ assetDirStat = undefined;
204
+ }
205
+ else {
206
+ const message = err instanceof Error ? err.message : String(err);
207
+ throw new ClawChefError(`openclaw.root.assets path is not accessible: ${resolvedAssets.value} (${message})`);
208
+ }
200
209
  }
201
- if (!assetDirStat.isDirectory()) {
210
+ if (!assetDirStat) {
211
+ // missing assets path is non-fatal by design
212
+ }
213
+ else if (!assetDirStat.isDirectory()) {
202
214
  throw new ClawChefError(`openclaw.root.assets must be a directory: ${resolvedAssets.value}`);
203
215
  }
204
- const assetFiles = await collectLocalAssetFiles(resolvedAssets.value);
205
- for (const assetFile of assetFiles) {
206
- const target = path.resolve(openclawRootPath, assetFile.relativePath);
207
- if (!options.dryRun) {
208
- await mkdir(path.dirname(target), { recursive: true });
209
- await copyFile(assetFile.absolutePath, target);
216
+ else {
217
+ const assetFiles = await collectLocalAssetFiles(resolvedAssets.value);
218
+ for (const assetFile of assetFiles) {
219
+ const target = path.resolve(openclawRootPath, assetFile.relativePath);
220
+ if (!options.dryRun) {
221
+ await mkdir(path.dirname(target), { recursive: true });
222
+ await copyFile(assetFile.absolutePath, target);
223
+ }
224
+ logger.info(`OpenClaw root asset copied: ${assetFile.relativePath}`);
210
225
  }
211
- logger.info(`OpenClaw root asset copied: ${assetFile.relativePath}`);
212
226
  }
213
227
  }
214
228
  for (const file of root.files ?? []) {
@@ -262,6 +276,10 @@ export async function runRecipe(recipe, recipeOrigin, options, logger) {
262
276
  assetDirStat = await stat(resolvedAssets.value);
263
277
  }
264
278
  catch (err) {
279
+ if (isNotFoundError(err)) {
280
+ logger.warn(`Skipping missing workspace assets directory: ${resolvedAssets.value}`);
281
+ continue;
282
+ }
265
283
  const message = err instanceof Error ? err.message : String(err);
266
284
  throw new ClawChefError(`Workspace assets path is not accessible: ${resolvedAssets.value} (${message})`);
267
285
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawchef",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Recipe-driven OpenClaw environment orchestrator",
5
5
  "homepage": "https://renorzr.github.io/clawchef",
6
6
  "repository": {
@@ -84,6 +84,10 @@ function isHttpUrl(value: string): boolean {
84
84
  }
85
85
  }
86
86
 
87
+ function isNotFoundError(err: unknown): boolean {
88
+ return typeof err === "object" && err !== null && "code" in err && (err as { code?: string }).code === "ENOENT";
89
+ }
90
+
87
91
  function resolveFileRef(recipeOrigin: RecipeOrigin, reference: string): { kind: "local" | "url"; value: string } {
88
92
  if (isHttpUrl(reference)) {
89
93
  return { kind: "url", value: reference };
@@ -233,21 +237,28 @@ export async function runRecipe(
233
237
  try {
234
238
  assetDirStat = await stat(resolvedAssets.value);
235
239
  } catch (err) {
236
- const message = err instanceof Error ? err.message : String(err);
237
- throw new ClawChefError(`openclaw.root.assets path is not accessible: ${resolvedAssets.value} (${message})`);
240
+ if (isNotFoundError(err)) {
241
+ logger.warn(`Skipping missing openclaw.root.assets directory: ${resolvedAssets.value}`);
242
+ assetDirStat = undefined;
243
+ } else {
244
+ const message = err instanceof Error ? err.message : String(err);
245
+ throw new ClawChefError(`openclaw.root.assets path is not accessible: ${resolvedAssets.value} (${message})`);
246
+ }
238
247
  }
239
- if (!assetDirStat.isDirectory()) {
248
+ if (!assetDirStat) {
249
+ // missing assets path is non-fatal by design
250
+ } else if (!assetDirStat.isDirectory()) {
240
251
  throw new ClawChefError(`openclaw.root.assets must be a directory: ${resolvedAssets.value}`);
241
- }
242
-
243
- const assetFiles = await collectLocalAssetFiles(resolvedAssets.value);
244
- for (const assetFile of assetFiles) {
245
- const target = path.resolve(openclawRootPath, assetFile.relativePath);
246
- if (!options.dryRun) {
247
- await mkdir(path.dirname(target), { recursive: true });
248
- await copyFile(assetFile.absolutePath, target);
252
+ } else {
253
+ const assetFiles = await collectLocalAssetFiles(resolvedAssets.value);
254
+ for (const assetFile of assetFiles) {
255
+ const target = path.resolve(openclawRootPath, assetFile.relativePath);
256
+ if (!options.dryRun) {
257
+ await mkdir(path.dirname(target), { recursive: true });
258
+ await copyFile(assetFile.absolutePath, target);
259
+ }
260
+ logger.info(`OpenClaw root asset copied: ${assetFile.relativePath}`);
249
261
  }
250
- logger.info(`OpenClaw root asset copied: ${assetFile.relativePath}`);
251
262
  }
252
263
  }
253
264
 
@@ -304,6 +315,10 @@ export async function runRecipe(
304
315
  try {
305
316
  assetDirStat = await stat(resolvedAssets.value);
306
317
  } catch (err) {
318
+ if (isNotFoundError(err)) {
319
+ logger.warn(`Skipping missing workspace assets directory: ${resolvedAssets.value}`);
320
+ continue;
321
+ }
307
322
  const message = err instanceof Error ? err.message : String(err);
308
323
  throw new ClawChefError(`Workspace assets path is not accessible: ${resolvedAssets.value} (${message})`);
309
324
  }