beeos-claw 0.5.22 → 0.5.23

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.
@@ -1 +1 @@
1
- import AdmZip from"adm-zip";export const MAX_ZIP_BYTES=20971520;export const MAX_DECOMPRESSED_BYTES=104857600;export const MAX_FILE_BYTES=5242880;export const MAX_ENTRIES=2e3;const MANIFEST_NAME="manifest.json",WORKSPACE_PREFIX="workspace/",SKILLS_PREFIX="workspace/skills/",ROOT_SKILLS_PREFIX="skills/",ALLOWED_BOOTSTRAP_FILES=new Set(["SOUL.md","USER.md","AGENTS.md","TOOLS.md","HEARTBEAT.md","BOOTSTRAP.md","MEMORY.md"]),SLUG_PATTERN=/^[a-z0-9][a-z0-9-]{1,63}$/,VERSION_PATTERN=/^[0-9]+(\.[0-9]+){0,2}([.-][0-9A-Za-z.-]+)?$/;export class TemplatePackageError extends Error{constructor(e){super(e),this.name="TemplatePackageError"}}function normalizeEntryName(e){return e.replace(/\\/g,"/")}function isIgnored(e){if("__MACOSX"===e||e.startsWith("__MACOSX/"))return!0;return".DS_Store"===(e.replace(/\/$/,"").split("/").pop()??"")}function isSymlink(e){return 40960===((e.header.attr??0)>>>16&61440)}function detectFlattenPrefix(e){let t="",r=!0;for(const n of e){const e=normalizeEntryName(n.entryName);if(""===e||isIgnored(e))continue;const a=e.indexOf("/");if(a<0)return"";const o=e.slice(0,a);if(r)t=o,r=!1;else if(o!==t)return""}return""===t?"":t+"/"}function cleanRelPath(e){if(e.startsWith("/")||/^[a-zA-Z]:/.test(e))throw new TemplatePackageError(`path traversal detected: ${e}`);const t=[];for(const r of e.split("/"))if(""!==r&&"."!==r){if(".."===r)throw new TemplatePackageError(`path traversal detected: ${e}`);t.push(r)}return t.join("/")}function stripPrefixSafe(e,t){let r=e;if(""!==t){if(!e.startsWith(t))throw new TemplatePackageError(`entry escapes package root: ${e}`);r=e.slice(t.length)}if(""===r)return"";const n=r.endsWith("/"),a=cleanRelPath(r);return""===a?"":n?a+"/":a}function skillSlugFromPath(e,t){const r=e.slice(t.length);if(""===r)return"";const n=(r.indexOf("/")>=0?r.slice(0,r.indexOf("/")):r).toLowerCase();return SLUG_PATTERN.test(n)?n:""}function parseManifest(e){let t;try{t=JSON.parse(e.toString("utf8"))}catch(e){throw new TemplatePackageError(`invalid manifest.json: ${e instanceof Error?e.message:String(e)}`)}if("object"!=typeof t||null===t)throw new TemplatePackageError("invalid manifest.json: not an object");const r=t;if(1!==r.schema_version)throw new TemplatePackageError(`unsupported manifest schema_version: ${String(r.schema_version)} (expected 1)`);const n=String(r.slug??"").trim().toLowerCase();if(""!==n&&!SLUG_PATTERN.test(n))throw new TemplatePackageError(`manifest slug "${n}" must match ${SLUG_PATTERN}`);const a=String(r.display_name??"").trim();if(""===a)throw new TemplatePackageError("manifest display_name is required");const o=String(r.version??"").trim();if(""!==o&&!VERSION_PATTERN.test(o))throw new TemplatePackageError(`manifest version "${o}" is not a valid version`);const i=t;return i.slug=n,i.display_name=a,i.version=o,i}export function parseAndValidateTemplatePackage(e){if(0===e.length)throw new TemplatePackageError("package is empty");if(e.length>20971520)throw new TemplatePackageError(`package too large: ${e.length} bytes (max 20971520)`);let t;try{t=new AdmZip(e)}catch(e){throw new TemplatePackageError(`not a valid zip archive: ${e instanceof Error?e.message:String(e)}`)}const r=t.getEntries();if(r.length>2e3)throw new TemplatePackageError(`too many entries: ${r.length} (max 2000)`);const n=detectFlattenPrefix(r),a=new Map;let o=null,i=0;for(const e of r){const t=normalizeEntryName(e.entryName);if(""===t||isIgnored(t))continue;if(isSymlink(e))throw new TemplatePackageError(`symlinks are not allowed: ${e.entryName}`);const r=stripPrefixSafe(t,n);if(""===r||r.endsWith("/"))continue;const s=e.header.size??0;if(s>5242880)throw new TemplatePackageError(`file too large: ${r} is ${s} bytes (max 5242880)`);const l=r;if(l===MANIFEST_NAME){if(o=e.getData(),i+=o.length,i>104857600)throw new TemplatePackageError("package decompresses to more than 104857600 bytes");continue}if("IDENTITY.md"===l)continue;if("workspace/IDENTITY.md"===l)continue;if(l.startsWith(SKILLS_PREFIX)){if(""===skillSlugFromPath(l,SKILLS_PREFIX))throw new TemplatePackageError(`invalid skill path: ${r}`)}else if(l.startsWith("skills/")){if(""===skillSlugFromPath(l,"skills/"))throw new TemplatePackageError(`invalid skill path: ${r}`)}else if(l.startsWith("workspace/")){const e=l.slice(10);if(e.includes("/"))continue;if(!ALLOWED_BOOTSTRAP_FILES.has(e))continue}else if(!ALLOWED_BOOTSTRAP_FILES.has(l))continue;const c=e.getData();if(c.length>5242880)throw new TemplatePackageError(`file too large: ${r} is ${c.length} bytes (max 5242880)`);if(i+=c.length,i>104857600)throw new TemplatePackageError("package decompresses to more than 104857600 bytes");const m=l.startsWith("workspace/")?l.slice(10):l;a.set(m,c)}return{manifest:null!==o?parseManifest(o):null,workspaceFiles:a,flattenPrefix:n}}
1
+ import AdmZip from"adm-zip";export const MAX_ZIP_BYTES=268435456;export const MAX_DECOMPRESSED_BYTES=536870912;export const MAX_FILE_BYTES=268435456;export const MAX_ENTRIES=5e4;const MANIFEST_NAME="manifest.json",IDENTITY_NAME="IDENTITY.md",SKILLS_DIR="skills/",SLUG_PATTERN=/^[a-z0-9][a-z0-9-]{1,63}$/,VERSION_PATTERN=/^[0-9]+(\.[0-9]+){0,2}([.-][0-9A-Za-z.-]+)?$/;export class TemplatePackageError extends Error{constructor(e){super(e),this.name="TemplatePackageError"}}function normalizeEntryName(e){return e.replace(/\\/g,"/")}function isIgnored(e){if("__MACOSX"===e||e.startsWith("__MACOSX/"))return!0;return".DS_Store"===(e.replace(/\/$/,"").split("/").pop()??"")}function isSymlink(e){return 40960===((e.header.attr??0)>>>16&61440)}function baseName(e){return e.replace(/\/$/,"").split("/").pop()??""}function hasUnsafePath(e){return!!e.startsWith("/")||(e.length>=2&&":"===e[1]||e.split("/").some(e=>".."===e))}function findManifestIndex(e){let t=-1,r=0;for(let n=0;n<e.length;n++){const a=normalizeEntryName(e[n].entryName);if(""===a||isIgnored(a)||baseName(a)!==MANIFEST_NAME)continue;const o=(a.match(/\//g)??[]).length;(-1===t||o<r)&&(t=n,r=o)}return t}function detectFlattenPrefix(e,t){let r="";for(;;){let n="",a=!0,o=!1;for(let i=0;i<e.length;i++){if(i===t)continue;const s=normalizeEntryName(e[i].entryName);if(""===s||isIgnored(s)||!s.startsWith(r))continue;const l=s.slice(r.length);if(""===l)continue;o=!0;const c=l.indexOf("/");if(c<0)return r;const f=l.slice(0,c);if(a)n=f,a=!1;else if(f!==n)return r}if(!o||""===n||n+"/"=="skills/")return r;r+=n+"/"}}function cleanRelPath(e){if(e.startsWith("/")||/^[a-zA-Z]:/.test(e))throw new TemplatePackageError(`path traversal detected: ${e}`);const t=[];for(const r of e.split("/"))if(""!==r&&"."!==r){if(".."===r)throw new TemplatePackageError(`path traversal detected: ${e}`);t.push(r)}return t.join("/")}function stripPrefixSafe(e,t){let r=e;if(""!==t){if(!e.startsWith(t))throw new TemplatePackageError(`entry escapes package root: ${e}`);r=e.slice(t.length)}if(""===r)return"";const n=r.endsWith("/"),a=cleanRelPath(r);return""===a?"":n?a+"/":a}function parseManifest(e){let t;try{t=JSON.parse(e.toString("utf8"))}catch(e){throw new TemplatePackageError(`invalid manifest.json: ${e instanceof Error?e.message:String(e)}`)}if("object"!=typeof t||null===t)throw new TemplatePackageError("invalid manifest.json: not an object");const r=t;if(1!==r.schema_version)throw new TemplatePackageError(`unsupported manifest schema_version: ${String(r.schema_version)} (expected 1)`);const n=String(r.slug??"").trim().toLowerCase();if(""!==n&&!SLUG_PATTERN.test(n))throw new TemplatePackageError(`manifest slug "${n}" must match ${SLUG_PATTERN}`);const a=String(r.display_name??"").trim();if(""===a)throw new TemplatePackageError("manifest display_name is required");const o=String(r.version??"").trim();if(""!==o&&!VERSION_PATTERN.test(o))throw new TemplatePackageError(`manifest version "${o}" is not a valid version`);const i=t;return i.slug=n,i.display_name=a,i.version=o,i}export function parseAndValidateTemplatePackage(e){if(0===e.length)throw new TemplatePackageError("package is empty");if(e.length>268435456)throw new TemplatePackageError(`package too large: ${e.length} bytes (max 268435456)`);let t;try{t=new AdmZip(e)}catch(e){throw new TemplatePackageError(`not a valid zip archive: ${e instanceof Error?e.message:String(e)}`)}const r=t.getEntries();if(r.length>5e4)throw new TemplatePackageError(`too many entries: ${r.length} (max 50000)`);for(const e of r){const t=normalizeEntryName(e.entryName);if(""!==t&&!isIgnored(t)&&hasUnsafePath(t))throw new TemplatePackageError(`path traversal detected: ${e.entryName}`)}const n=findManifestIndex(r),a=detectFlattenPrefix(r,n),o=new Map;let i=null,s=0;const l=e=>{if(s+=e,s>536870912)throw new TemplatePackageError("package decompresses to more than 536870912 bytes")};if(n>=0){const e=r[n];if((e.header.size??0)>268435456)throw new TemplatePackageError(`file too large: ${MANIFEST_NAME} (max 268435456)`);if(i=e.getData(),i.length>268435456)throw new TemplatePackageError(`file too large: ${MANIFEST_NAME} (max 268435456)`);l(i.length)}for(let e=0;e<r.length;e++){if(e===n)continue;const t=r[e],i=normalizeEntryName(t.entryName);if(""===i||isIgnored(i))continue;if(i.endsWith("/"))continue;if(isSymlink(t))throw new TemplatePackageError(`symlinks are not allowed: ${t.entryName}`);const s=stripPrefixSafe(i,a);if(""===s||s.endsWith("/"))continue;const c=t.header.size??0;if(c>268435456)throw new TemplatePackageError(`file too large: ${s} is ${c} bytes (max 268435456)`);if("IDENTITY.md"===s)continue;const f=t.getData();if(f.length>268435456)throw new TemplatePackageError(`file too large: ${s} is ${f.length} bytes (max 268435456)`);l(f.length),o.set(s,f)}return{manifest:null!==i?parseManifest(i):null,workspaceFiles:o,flattenPrefix:a}}
@@ -1 +1 @@
1
- import{describe,it,expect}from"vitest";import AdmZip from"adm-zip";import{parseAndValidateTemplatePackage,TemplatePackageError}from"./agent-template-package.js";const validManifest=JSON.stringify({schema_version:1,slug:"demo-expert",display_name:"Demo Expert",version:"1.0.0"});function buildZip(e){const a=new AdmZip;for(const[t,s]of Object.entries(e))a.addFile(t,Buffer.from(s,"utf8"));return a.toBuffer()}describe("parseAndValidateTemplatePackage",()=>{it("parses a BeeOS root-level package and returns workspace files",()=>{const e=buildZip({"manifest.json":validManifest,"workspace/SOUL.md":"you are a demo","workspace/skills/foo/SKILL.md":"skill foo"}),a=parseAndValidateTemplatePackage(e);expect(a.manifest?.slug).toBe("demo-expert"),expect(a.flattenPrefix).toBe(""),expect(a.workspaceFiles.get("SOUL.md")?.toString()).toBe("you are a demo"),expect(a.workspaceFiles.get("skills/foo/SKILL.md")?.toString()).toBe("skill foo"),expect(a.workspaceFiles.has("manifest.json")).toBe(!1)}),it("flattens a single wrapping top-level directory (QClaw-style)",()=>{const e=buildZip({"expert-pkg/manifest.json":validManifest,"expert-pkg/workspace/SOUL.md":"soul"}),a=parseAndValidateTemplatePackage(e);expect(a.flattenPrefix).toBe("expert-pkg/"),expect(a.workspaceFiles.get("SOUL.md")?.toString()).toBe("soul")}),it("ignores __MACOSX and .DS_Store noise",()=>{const e=buildZip({"manifest.json":validManifest,"workspace/SOUL.md":"soul","__MACOSX/workspace/._SOUL.md":"junk","workspace/.DS_Store":"junk"}),a=parseAndValidateTemplatePackage(e);expect(a.workspaceFiles.has("SOUL.md")).toBe(!0),expect(a.workspaceFiles.size).toBe(1)}),it("allows workspace/IDENTITY.md without error",()=>{const e=buildZip({"manifest.json":validManifest,"workspace/IDENTITY.md":"name: hacked"}),a=parseAndValidateTemplatePackage(e);expect(a.workspaceFiles.has("IDENTITY.md")).toBe(!1)}),it("silently skips unknown workspace files",()=>{const e=buildZip({"manifest.json":validManifest,"workspace/secrets.env":"TOKEN=1"}),a=parseAndValidateTemplatePackage(e);expect(a.workspaceFiles.has("secrets.env")).toBe(!1)}),it("accepts a QClaw native layout (root-level files, no manifest)",()=>{const e=buildZip({"IDENTITY.md":"- Name: Car Agent\n- Vibe: helpful","SOUL.md":"you are a car agent","AGENTS.md":"agents","skills/car-mgr/SKILL.md":"skill","skills/car-mgr/scripts/main.py":"code","skills/car-mgr/_meta.json":'{"name":"car-mgr"}',"memory/notes.jsonl":"{}"}),a=parseAndValidateTemplatePackage(e);expect(a.manifest).toBeNull(),expect(a.workspaceFiles.get("SOUL.md")?.toString()).toBe("you are a car agent"),expect(a.workspaceFiles.get("AGENTS.md")?.toString()).toBe("agents"),expect(a.workspaceFiles.get("skills/car-mgr/SKILL.md")?.toString()).toBe("skill"),expect(a.workspaceFiles.has("IDENTITY.md")).toBe(!1),expect(a.workspaceFiles.has("memory/notes.jsonl")).toBe(!1)}),it("accepts a wrapped QClaw export (single top-level dir, no manifest)",()=>{const e=buildZip({"car-mgr/SOUL.md":"soul","car-mgr/IDENTITY.md":"- Name: Car\n","car-mgr/skills/car-mgr/SKILL.md":"skill"}),a=parseAndValidateTemplatePackage(e);expect(a.flattenPrefix).toBe("car-mgr/"),expect(a.manifest).toBeNull(),expect(a.workspaceFiles.get("SOUL.md")?.toString()).toBe("soul"),expect(a.workspaceFiles.has("IDENTITY.md")).toBe(!1)}),it("silently skips paths that AdmZip normalises outside workspace",()=>{const e=buildZip({"manifest.json":validManifest,"workspace/../../etc/passwd":"root"}),a=parseAndValidateTemplatePackage(e);expect(a.workspaceFiles.has("etc/passwd")).toBe(!1),expect(a.workspaceFiles.has("../etc/passwd")).toBe(!1)}),it("rejects an unsupported schema_version",()=>{const e=buildZip({"manifest.json":JSON.stringify({schema_version:2,slug:"x",display_name:"X",version:"1.0.0"}),"workspace/SOUL.md":"soul"});expect(()=>parseAndValidateTemplatePackage(e)).toThrow(/schema_version/)}),it("rejects an invalid slug in manifest",()=>{const e=buildZip({"manifest.json":JSON.stringify({schema_version:1,slug:"Bad Slug!",display_name:"X",version:"1.0.0"}),"workspace/SOUL.md":"soul"});expect(()=>parseAndValidateTemplatePackage(e)).toThrow(/slug/)}),it("rejects a non-zip buffer",()=>{expect(()=>parseAndValidateTemplatePackage(Buffer.from("not a zip"))).toThrow(TemplatePackageError)}),it("rejects an empty buffer",()=>{expect(()=>parseAndValidateTemplatePackage(Buffer.alloc(0))).toThrow(/empty/)})});
1
+ import{describe,it,expect}from"vitest";import AdmZip from"adm-zip";import{parseAndValidateTemplatePackage,TemplatePackageError}from"./agent-template-package.js";const validManifest=JSON.stringify({schema_version:1,slug:"demo-expert",display_name:"Demo Expert",version:"1.0.0"});function buildZip(e){const t=new AdmZip;for(const[a,s]of Object.entries(e))t.addFile(a,Buffer.from(s,"utf8"));return t.toBuffer()}describe("parseAndValidateTemplatePackage",()=>{it("parses a BeeOS package and flattens the workspace/ subdir",()=>{const e=buildZip({"manifest.json":validManifest,"workspace/SOUL.md":"you are a demo","workspace/skills/foo/SKILL.md":"skill foo"}),t=parseAndValidateTemplatePackage(e);expect(t.manifest?.slug).toBe("demo-expert"),expect(t.flattenPrefix).toBe("workspace/"),expect(t.workspaceFiles.get("SOUL.md")?.toString()).toBe("you are a demo"),expect(t.workspaceFiles.get("skills/foo/SKILL.md")?.toString()).toBe("skill foo"),expect(t.workspaceFiles.has("manifest.json")).toBe(!1)}),it("peels both an outer wrapper and the workspace/ subdir",()=>{const e=buildZip({"expert-pkg/manifest.json":validManifest,"expert-pkg/workspace/SOUL.md":"soul"}),t=parseAndValidateTemplatePackage(e);expect(t.flattenPrefix).toBe("expert-pkg/workspace/"),expect(t.workspaceFiles.get("SOUL.md")?.toString()).toBe("soul")}),it("ignores __MACOSX and .DS_Store noise",()=>{const e=buildZip({"manifest.json":validManifest,"workspace/SOUL.md":"soul","__MACOSX/workspace/._SOUL.md":"junk","workspace/.DS_Store":"junk"}),t=parseAndValidateTemplatePackage(e);expect(t.workspaceFiles.has("SOUL.md")).toBe(!0),expect(t.workspaceFiles.size).toBe(1)}),it("never writes IDENTITY.md",()=>{const e=buildZip({"manifest.json":validManifest,"workspace/IDENTITY.md":"name: hacked","workspace/SOUL.md":"soul"}),t=parseAndValidateTemplatePackage(e);expect(t.workspaceFiles.has("IDENTITY.md")).toBe(!1),expect(t.workspaceFiles.has("SOUL.md")).toBe(!0)}),it("carries arbitrary non-bootstrap files verbatim",()=>{const e=buildZip({"SOUL.md":"soul","NOTES.md":"notes","data/config.json":"{}","secrets.env":"TOKEN=1"}),t=parseAndValidateTemplatePackage(e);expect(t.workspaceFiles.get("NOTES.md")?.toString()).toBe("notes"),expect(t.workspaceFiles.get("data/config.json")?.toString()).toBe("{}"),expect(t.workspaceFiles.get("secrets.env")?.toString()).toBe("TOKEN=1")}),it("accepts a QClaw native layout and carries unknown files",()=>{const e=buildZip({"IDENTITY.md":"- Name: Car Agent\n- Vibe: helpful","SOUL.md":"you are a car agent","AGENTS.md":"agents","skills/car-mgr/SKILL.md":"skill","skills/car-mgr/scripts/main.py":"code","skills/car-mgr/_meta.json":'{"name":"car-mgr"}',"memory/notes.jsonl":"{}"}),t=parseAndValidateTemplatePackage(e);expect(t.manifest).toBeNull(),expect(t.flattenPrefix).toBe(""),expect(t.workspaceFiles.get("SOUL.md")?.toString()).toBe("you are a car agent"),expect(t.workspaceFiles.get("AGENTS.md")?.toString()).toBe("agents"),expect(t.workspaceFiles.get("skills/car-mgr/SKILL.md")?.toString()).toBe("skill"),expect(t.workspaceFiles.has("skills/car-mgr/_meta.json")).toBe(!0),expect(t.workspaceFiles.has("memory/notes.jsonl")).toBe(!0),expect(t.workspaceFiles.has("IDENTITY.md")).toBe(!1)}),it("accepts a wrapped QClaw export (single top-level dir, no manifest)",()=>{const e=buildZip({"car-mgr/SOUL.md":"soul","car-mgr/IDENTITY.md":"- Name: Car\n","car-mgr/skills/car-mgr/SKILL.md":"skill"}),t=parseAndValidateTemplatePackage(e);expect(t.flattenPrefix).toBe("car-mgr/"),expect(t.manifest).toBeNull(),expect(t.workspaceFiles.get("SOUL.md")?.toString()).toBe("soul"),expect(t.workspaceFiles.has("IDENTITY.md")).toBe(!1)}),it("skips explicit directory entries (real zip tooling)",()=>{const e=new AdmZip;e.addFile("pkg/",Buffer.alloc(0)),e.addFile("pkg/manifest.json",Buffer.from(validManifest,"utf8")),e.addFile("pkg/workspace/",Buffer.alloc(0)),e.addFile("pkg/workspace/SOUL.md",Buffer.from("soul","utf8")),e.addFile("pkg/workspace/skills/",Buffer.alloc(0)),e.addFile("pkg/workspace/skills/x/",Buffer.alloc(0)),e.addFile("pkg/workspace/skills/x/SKILL.md",Buffer.from("skill","utf8"));const t=parseAndValidateTemplatePackage(e.toBuffer());expect(t.flattenPrefix).toBe("pkg/workspace/"),expect(t.manifest?.slug).toBe("demo-expert"),expect(t.workspaceFiles.get("SOUL.md")?.toString()).toBe("soul"),expect(t.workspaceFiles.get("skills/x/SKILL.md")?.toString()).toBe("skill"),expect(t.workspaceFiles.has("pkg/")).toBe(!1)}),it("recognises an OpenClaw workspace-<profile> wrapper",()=>{const e=buildZip({"workspace-acme/SOUL.md":"soul","workspace-acme/skills/foo/SKILL.md":"skill"}),t=parseAndValidateTemplatePackage(e);expect(t.flattenPrefix).toBe("workspace-acme/"),expect(t.workspaceFiles.get("SOUL.md")?.toString()).toBe("soul"),expect(t.workspaceFiles.get("skills/foo/SKILL.md")?.toString()).toBe("skill")}),it("keeps a skills-only package's skills/ directory intact",()=>{const e=buildZip({"skills/foo/SKILL.md":"skill"}),t=parseAndValidateTemplatePackage(e);expect(t.flattenPrefix).toBe(""),expect(t.workspaceFiles.get("skills/foo/SKILL.md")?.toString()).toBe("skill")}),it("never writes outside the workspace on traversal input",()=>{const e=buildZip({"manifest.json":validManifest,"workspace/SOUL.md":"soul","workspace/../../etc/passwd":"root"});let t;try{t=parseAndValidateTemplatePackage(e)}catch(e){return void expect(e).toBeInstanceOf(TemplatePackageError)}for(const e of t.workspaceFiles.keys())expect(e.startsWith("..")).toBe(!1),expect(e.startsWith("/")).toBe(!1),expect(e.includes("/../")).toBe(!1)}),it("rejects an unsupported schema_version",()=>{const e=buildZip({"manifest.json":JSON.stringify({schema_version:2,slug:"x",display_name:"X",version:"1.0.0"}),"workspace/SOUL.md":"soul"});expect(()=>parseAndValidateTemplatePackage(e)).toThrow(/schema_version/)}),it("rejects an invalid slug in manifest",()=>{const e=buildZip({"manifest.json":JSON.stringify({schema_version:1,slug:"Bad Slug!",display_name:"X",version:"1.0.0"}),"workspace/SOUL.md":"soul"});expect(()=>parseAndValidateTemplatePackage(e)).toThrow(/slug/)}),it("rejects a non-zip buffer",()=>{expect(()=>parseAndValidateTemplatePackage(Buffer.from("not a zip"))).toThrow(TemplatePackageError)}),it("rejects an empty buffer",()=>{expect(()=>parseAndValidateTemplatePackage(Buffer.alloc(0))).toThrow(/empty/)})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beeos-claw",
3
- "version": "0.5.22",
3
+ "version": "0.5.23",
4
4
  "description": "OpenClaw plugin that bridges the BeeOS platform with the local OpenClaw Gateway, providing file transfer, ACP bridge, and observability.",
5
5
  "license": "MIT",
6
6
  "author": "BeeOS <dev@beeos.ai>",