diff --git a/hooks/capture.ts b/hooks/capture.ts index 5f4b28b..d13df06 100644 --- a/hooks/capture.ts +++ b/hooks/capture.ts @@ -64,9 +64,16 @@ export function buildCaptureHandler( const captured = cfg.captureMode === "all" - ? texts.filter( - (t) => t.length >= 10 && !t.includes(""), - ) + ? texts + .map((t) => + t + .replace( + /[\s\S]*?<\/supermemory-context>\s*/g, + "", + ) + .trim(), + ) + .filter((t) => t.length >= 10) : texts if (captured.length === 0) return diff --git a/lib/validate.js b/lib/validate.js index dd937dc..ac2e25b 100644 --- a/lib/validate.js +++ b/lib/validate.js @@ -1 +1 @@ -import{createHash as o,createHmac as l}from"node:crypto";function b(e){return!e||typeof e!="string"?{valid:!1,reason:"key is empty or not a string"}:e.startsWith("sm_")?e.length<20?{valid:!1,reason:"key is too short"}:/\s/.test(e)?{valid:!1,reason:"key contains whitespace"}:{valid:!0}:{valid:!1,reason:"key must start with sm_ prefix"}}function v(e){return!e||typeof e!="string"?{valid:!1,reason:"tag is empty"}:e.length>100?{valid:!1,reason:"tag exceeds 100 characters"}:/^[a-zA-Z0-9_-]+$/.test(e)?/^[-_]|[-_]$/.test(e)?{valid:!1,reason:"tag must not start or end with - or _"}:{valid:!0}:{valid:!1,reason:"tag contains invalid characters (only alphanumeric, underscore, hyphen allowed)"}}var u=[/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g,/\uFEFF/g,/[\uFFF0-\uFFFF]/g];function m(e,n=1e5){if(!e||typeof e!="string")return"";let t=e;for(let r of u)t=t.replace(r,"");return t.length>n&&(t=t.slice(0,n)),t}function A(e,n=1,t=1e5){return e.lengtht?{valid:!1,reason:`content exceeds maximum length (${t})`}:{valid:!0}}var f=50,c=128,g=1024;function x(e){let n={},t=0;for(let[r,i]of Object.entries(e)){if(t>=f)break;r.length>c||/[^\w.-]/.test(r)||(typeof i=="string"?(n[r]=i.slice(0,g),t++):(typeof i=="number"&&Number.isFinite(i)||typeof i=="boolean")&&(n[r]=i,t++))}return n}function E(e,n){let t=[];return(!Number.isInteger(e)||e<1||e>20)&&t.push("maxRecallResults must be an integer between 1 and 20"),(!Number.isInteger(n)||n<1||n>500)&&t.push("profileFrequency must be an integer between 1 and 500"),t}function s(e){return o("sha256").update(e).digest("hex").slice(0,16)}var a=1,d="7f2a9c4b8e1d6f3a5c0b9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e9f8a";function h(e,n){let t=Math.floor(Date.now()/864e5),r=[s(e),s(n),t.toString(36),a].join(":");return l("sha256",d).update(r).digest("base64url")}function F(e,n){let t=s(n),r=h(e,n);return{"X-Content-Hash":t,"X-Request-Integrity":[`v${a}`,r].join(".")}}export{F as getRequestIntegrity,m as sanitizeContent,x as sanitizeMetadata,b as validateApiKeyFormat,v as validateContainerTag,A as validateContentLength,E as validateRecallConfig}; +import{createHash as o,createHmac as l}from"node:crypto";function h(e){return!e||typeof e!="string"?{valid:!1,reason:"key is empty or not a string"}:e.startsWith("sm_")?e.length<20?{valid:!1,reason:"key is too short"}:/\s/.test(e)?{valid:!1,reason:"key contains whitespace"}:{valid:!0}:{valid:!1,reason:"key must start with sm_ prefix"}}function v(e){return!e||typeof e!="string"?{valid:!1,reason:"tag is empty"}:e.length>100?{valid:!1,reason:"tag exceeds 100 characters"}:/^[a-zA-Z0-9_-]+$/.test(e)?/^[-_]|[-_]$/.test(e)?{valid:!1,reason:"tag must not start or end with - or _"}:{valid:!0}:{valid:!1,reason:"tag contains invalid characters (only alphanumeric, underscore, hyphen allowed)"}}var u=[/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g,/\uFEFF/g,/[\uFFF0-\uFFFF]/g];function m(e,n=1e5){if(!e||typeof e!="string")return"";let t=e;for(let r of u)t=t.replace(r,"");return t.length>n&&(t=t.slice(0,n)),t}function A(e,n=1,t=1e5){return e.lengtht?{valid:!1,reason:`content exceeds maximum length (${t})`}:{valid:!0}}var f=50,g=128,c=1024;function x(e){let n={},t=0;for(let[r,i]of Object.entries(e)){if(t>=f)break;r.length>g||/[^\w.-]/.test(r)||(typeof i=="string"?(n[r]=i.slice(0,c),t++):(typeof i=="number"&&Number.isFinite(i)||typeof i=="boolean")&&(n[r]=i,t++))}return n}function E(e,n){let t=[];return(!Number.isInteger(e)||e<1||e>20)&&t.push("maxRecallResults must be an integer between 1 and 20"),(!Number.isInteger(n)||n<1||n>500)&&t.push("profileFrequency must be an integer between 1 and 500"),t}function s(e){return o("sha256").update(e).digest("hex")}var a=1,d="7f2a9c4b8e1d6f3a5c0b9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e9f8a";function p(e,n){let t=[s(e),s(n),a].join(":");return l("sha256",d).update(t).digest("base64url")}function F(e,n){let t=s(n),r=p(e,n);return{"X-Content-Hash":t,"X-Request-Integrity":[`v${a}`,r].join(".")}}export{F as getRequestIntegrity,m as sanitizeContent,x as sanitizeMetadata,h as validateApiKeyFormat,v as validateContainerTag,A as validateContentLength,E as validateRecallConfig}; diff --git a/package.json b/package.json index df2deaf..c995f31 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@supermemory/clawdbot-supermemory", "version": "1.0.0", "type": "module", - "description": "Supermemory memory plugin for Clawdbot", + "description": "Clawdbot Supermemory memory plugin", "license": "MIT", "dependencies": { "supermemory": "^4.0.0", @@ -10,6 +10,8 @@ }, "scripts": { "check-types": "tsc --noEmit", + "lint": "bunx @biomejs/biome ci .", + "lint:fix": "bunx @biomejs/biome check --write .", "build:lib": "esbuild lib/validate.ts --bundle --minify --format=esm --platform=node --target=es2022 --external:node:crypto --outfile=lib/validate.js" }, "peerDependencies": {