@lark-tns/openclaw-guardian-plugin 2026.4.19 → 2026.5.19

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.
package/README.md CHANGED
@@ -1,61 +1,3 @@
1
1
  # OpenClaw Guardian Plugin
2
2
 
3
- This plugin uses the new OpenClaw SDK entry style and reports trust-layer payloads for the active hook points below:
4
-
5
- - logs the payload to the official plugin logger
6
- - pulls runtime toggles from `http://localhost:8001/open-apis/security_plugin/v1/openclaw_plugin/config`
7
- - forwards detect requests to `http://localhost:8001/open-apis/security_plugin/v1/openclaw_plugin/detect`
8
-
9
- - `llm_input`
10
- - `llm_output`
11
- - `before_tool_call`
12
- - `after_tool_call`
13
-
14
- The runtime config polling is managed by `api.registerService(...)`. The service initializes remote config on startup, keeps an in-memory snapshot for hook handlers, and disposes the refresh timer on shutdown.
15
-
16
- ## Files
17
-
18
- - `openclaw.plugin.json`: native plugin manifest
19
- - `src/index.ts`: plugin entry registered with `definePluginEntry`, hook registration, and `api.registerService(...)` wiring
20
- - `src/runtime-config.ts`: remote config store plus polling service, typed against `OpenClawPluginApi` / `api.registerService(...)`
21
- - `src/hook-payloads.ts`: hook-specific payload builders required by the trust-layer API
22
- - `src/logger.ts`: safe payload formatter and logger helper
23
- - `src/http-client.ts`: request body builder and detect/config service client
24
- - `src/fetch-interceptor.ts`: optional `before_llm_fetch` / `after_llm_fetch` request-response interceptor, currently not enabled in `src/index.ts`
25
- - `src/tool-effects.ts`: effect parser and hook-specific deny/rewrite handling
26
-
27
- ## Install
28
-
29
- Link-install the plugin from this directory:
30
-
31
- ```bash
32
- openclaw plugins install -l .
33
- ```
34
-
35
- Then enable it in your OpenClaw config if needed:
36
-
37
- ```json5
38
- {
39
- plugins: {
40
- entries: {
41
- "openclaw-guardian-plugin": {
42
- enabled: true
43
- }
44
- }
45
- }
46
- }
47
- ```
48
-
49
- Restart the Gateway after config changes.
50
-
51
- ## Notes
52
-
53
- - The plugin logs via `api.logger.info(...)`.
54
- - The plugin registers a background service via `api.registerService(...)`; the service typing is derived from `OpenClawPluginApi`, GETs remote runtime config on startup, retries up to 3 times, defaults to all hooks disabled on first-start failure, and refreshes the config every 60 seconds.
55
- - The plugin POSTs `{ hook_name, payload }` to `http://localhost:8001/open-apis/security_plugin/v1/openclaw_plugin/detect`.
56
- - Hook handlers read the latest in-memory runtime-config snapshot instead of fetching `/config` inline on every hook invocation.
57
- - Hook payloads are sent as the trust-layer contract requires, such as tool/session fields for tool hooks and `domain` / `path` / `origin_req` or `origin_resp` for LLM fetch hooks.
58
- - `llm_input` and `llm_output` are report-only hooks; deny/rewrite responses are logged but not applied.
59
- - `after_tool_call` is also observe-only in runtime; detect decisions are logged but do not rewrite the actual hook return value.
60
- - Payloads are serialized defensively so circular references and `Error` objects do not break logging.
61
- - `before_llm_fetch` / `after_llm_fetch` support remains in `src/fetch-interceptor.ts`, but those hooks are not active until `installFetchInterceptor(api, configStore)` is enabled in `src/index.ts`.
3
+ OpenClaw 安全治理插件,用于拦截 LLM 请求与工具调用,检测 SKILL 安全性问题
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import{createRequire as e}from"node:module";import{definePluginEntry as t}from"openclaw/plugin-sdk/plugin-entry";import{basename as n,dirname as r,join as i,relative as a,resolve as o}from"node:path";import{homedir as s,hostname as c}from"node:os";import{lstat as l,mkdir as u,readFile as d,readdir as f,rename as p,stat as m,unlink as h,writeFile as g}from"node:fs/promises";import{createHash as _}from"node:crypto";import{existsSync as v}from"node:fs";var y=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),b=e(import.meta.url);const ee=2e4;function x(e){return`[openclaw-guardian-plugin] ${e}`}function S(){let e=new WeakSet;return(t,n)=>{if(n instanceof Error)return{name:n.name,message:n.message,stack:n.stack};if(typeof n==`bigint`)return n.toString();if(typeof n==`object`&&n){if(e.has(n))return`[Circular]`;e.add(n)}return n}}function C(e){let t=JSON.stringify(e,S(),2)??`null`;return t.length<=ee?t:`${t.slice(0,ee)}\n...<truncated>`}function w(e,t){return t===`online`?`[payload omitted in online]`:C(e)}function T(e,t,n,r){e.logger.info(x(`[${t}] ${w(n,r)}`))}function te(e){return typeof e==`string`?e:typeof e==`number`||typeof e==`boolean`||typeof e==`bigint`?String(e):JSON.stringify(e,S(),2)??`null`}function E(e){let t=e?.pluginConfig?.env;return t===`boe`||t===`dev`||t===`pre`?t:`online`}let D=null,O=null;function k(e,t){if(typeof e!=`string`||!e)throw Error(`missing or invalid ${t}`);return e}function A(...e){for(let t of e)if(typeof t==`string`&&t)return t;return null}function j(e){return!e||typeof e!=`object`||Array.isArray(e)?null:e}function M(e){let t=A(e?.pluginConfig?.appId),n=A(e?.pluginConfig?.appSecret),r=t&&n?{appId:t,appSecret:n}:null,i=j(j(j(e?.config)?.channels)?.feishu),a=A(i?.appId,i?.app_id),o=A(i?.appSecret,i?.app_secret),s=a&&o?{appId:a,appSecret:o}:null,c=E(e);return c===`online`||c===`pre`?s??r??null:r??s??null}function N(e){return!!M(e)}function P(e){let t=e?.pluginConfig?.x_tt_env;return typeof t==`string`&&t?t:E(e)===`boe`?`boe_tns_api`:null}function F(e){let t=E(e);return t===`online`?`https://open.feishu.cn`:t===`pre`?`https://open.feishu-pre.cn`:`https://open.feishu-boe.cn`}function ne(e){if(!e||typeof e!=`object`||Array.isArray(e))return null;let t=e;return{code:typeof t.code==`number`?t.code:NaN,msg:typeof t.msg==`string`?t.msg:``,tenant_access_token:typeof t.tenant_access_token==`string`?t.tenant_access_token:void 0,expire:typeof t.expire==`number`?t.expire:void 0}}async function I(e){let t=Date.now();return D&&D.expiresAtMs-t>18e5?D.token:O||(O=(async()=>{let t=M(e);if(!t)throw Error(`missing Feishu appId/appSecret from api.config.channels.feishu or pluginConfig`);let n=k(t.appId,`appId`),r=k(t.appSecret,`appSecret`),i=`${F(e)}/open-apis/auth/v3/tenant_access_token/internal`,a={"content-type":`application/json`},o=P(e);o&&(a[`x-tt-env`]=o),e.logger.debug?.(x(`[auth] requesting tenant_access_token`));let{signal:s,clear:c}=ie(U),l;try{l=await fetch(i,{method:`POST`,headers:a,body:JSON.stringify({app_id:n,app_secret:r}),signal:s})}catch(e){throw c(),e instanceof Error&&e.name===`AbortError`?new z(i,U):new B(i,e)}finally{c()}let u=await l.text();if(!l.ok)throw Error(`[auth] tenant_access_token request failed status=${l.status} body=${u||`<empty>`}`);let d=null;try{d=u?JSON.parse(u):null}catch{d=null}let f=ne(d);if(!f||!Number.isFinite(f.code))throw Error(`[auth] tenant_access_token response parse failed`);if(f.code!==0)throw Error(`[auth] tenant_access_token request failed code=${f.code}${f.msg?` msg=${f.msg}`:``}`);let p=k(f.tenant_access_token,`tenant_access_token`),m=typeof f.expire==`number`&&f.expire>0?f.expire:7200;return D={token:p,expiresAtMs:Date.now()+m*1e3},e.logger.debug?.(x(`[auth] tenant_access_token updated`)),p})().finally(()=>{O=null}),O)}async function L(e){if(E(e)===`dev`)return{};let t={},n=P(e);return n&&(t[`x-tt-env`]=n),t.authorization=`Bearer ${await I(e)}`,t}async function R(e,t={}){let n=await L(e),r=new Headers(t.headers??{});for(let[e,t]of Object.entries(n))r.set(e,t);return{...t,headers:r}}var z=class extends Error{code=`TIMEOUT`;constructor(e,t){super(`Request to ${e} timed out after ${t}ms`),this.name=`RequestTimeoutError`}},B=class extends Error{code=`NETWORK`;constructor(e,t){super(`Network error requesting ${e}: ${t instanceof Error?t.message:String(t)}`),this.name=`NetworkError`}},re=class extends Error{code=`SERVER`;statusCode;constructor(e,t,n){super(`Server error ${t} from ${e}${n?`: ${n}`:``}`),this.name=`ServerError`,this.statusCode=t}};function V(e){return e instanceof z?`TIMEOUT`:e instanceof B?`NETWORK`:e instanceof re?`SERVER`:e instanceof Error&&e.name===`AbortError`?`TIMEOUT`:`UNKNOWN`}const H=3e4,U=3e4;function ie(e){let t=new AbortController,n=setTimeout(()=>t.abort(),e);return typeof n==`object`&&`unref`in n&&n.unref(),{signal:t.signal,clear:()=>clearTimeout(n)}}function ae(e,t){if(!e)return t;let n=new AbortController,r=()=>n.abort();return e.addEventListener(`abort`,r,{once:!0}),t.addEventListener(`abort`,r,{once:!0}),n.signal}const oe={dev:`http://localhost:8001`,online:`https://open.feishu.cn`,boe:`https://open.feishu-boe.cn`,pre:`https://open.feishu-pre.cn`};function W(e){return`${oe[E(e)]}/open-apis/security_plugin/v1/openclaw_plugin`}function se(e){return`${W(e)}/config`}function ce(e){return`${W(e)}/detect`}function le(e){return`${W(e)}/batch_check_skill_detection`}function ue(e){return`${W(e)}/skill_detect`}function de(e={}){let t={};for(let[n,r]of Object.entries(e??{}))t[n]=te(r);return t}function fe(e,t,n=``){return{hook_name:e,payload:de(t),source:n}}function pe(e){if(!e)return null;try{let t=JSON.parse(e);return t&&typeof t==`object`&&!Array.isArray(t)?t:null}catch{return null}}function me(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return typeof t.code==`number`&&Number.isFinite(t.code)&&typeof t.msg==`string`}async function he(e,t,n){let r=await n.text();if(e.logger.debug?.(x(`[${t}] response: ${r}`)),!n.ok)throw Error(`${t} request failed: status=${n.status} body=${r||`<empty>`}`);let i=pe(r);if(!me(i))throw Error(`${t} response parse failed: missing or invalid code/msg fields`);if(i.code!==0)throw Error(`${t} request failed: code=${i.code}${i.msg?` msg=${i.msg}`:``}`);return i.data??null}async function G(e,t,n,r,i=H){let a=await R(e,r),{signal:o,clear:s}=ie(i),c=ae(a.signal,o),l,u=Date.now();try{l=await fetch(n,{...a,signal:c});let r=Date.now()-u;e.logger.info(x(`[${t}] http_elapsed=${r}ms status=${l.status} url=${n}`))}catch(r){let a=Date.now()-u;throw e.logger.info(x(`[${t}] http_elapsed=${a}ms error=${r instanceof Error?r.message:String(r)} url=${n}`)),s(),r instanceof Error&&r.name===`AbortError`?new z(n,i):new B(n,r)}finally{s()}return he(e,t,l)}let ge=null;function _e(){return ge||=c(),ge}function ve(){return{hostname:_e()}}function ye(e){if(!e||typeof e!=`object`||Array.isArray(e))return e;let t=e;return Object.prototype.hasOwnProperty.call(t,`hostname`)?e:{...t,...ve()}}async function K(e,t,n){let r=fe(t,ye(n),`miaoda`);return G(e,t,ce(e),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(r)},H)}function q(...e){return e.find(e=>e!=null)}function J(e){return e==null?``:typeof e==`string`?e:String(e)}function be(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:{}}function Y(e){return Array.isArray(e)?e:[]}function xe(e){try{let t=new URL(e);return{domain:t.host,path:t.pathname||`/`}}catch{return{domain:``,path:``}}}function Se(e){let{domain:t,path:n}=xe(J(e?.url));return{request_id:J(e?.request_id),domain:t,path:n,origin_req:q(e?.jsonBody,e?.rawBody,``)}}function Ce(e){let{domain:t,path:n}=xe(J(e?.url));return{request_id:J(e?.request_id),domain:t,path:n,is_sse:e?.isSse?`true`:`false`,chunks:Y(e?.chunks),origin_resp:e?.isSse?``:J(q(e?.originResp,``))}}function we(e,t){return{agent_name:J(t?.agentId),session_id:J(t?.sessionId),session_key:J(t?.sessionKey),channel_id:J(t?.channelId),message_provider:J(t?.messageProvider),trigger:J(t?.trigger),model:J(e?.model),provider:J(e?.provider),run_id:J(e?.runId)}}function Te(e,t){return{...we(e,t),prompt:J(e?.prompt),system_prompt:J(e?.systemPrompt),history_messages:Y(e?.historyMessages)}}function Ee(e,t){return{...we(e,t),assistant_texts:Y(e?.assistantTexts),last_assistant:J(JSON.stringify(e?.lastAssistant))}}function De(e,t){return{agent_name:J(t?.agentId),session_id:J(t?.sessionId),session_key:J(t?.sessionKey),tool_call_id:J(e?.toolCallId),tool_name:J(e?.toolName),tool_args:q(e?.params,{}),run_id:J(e?.runId)}}function Oe(e,t){return De(e,t)}function ke(e,t){return{...De(e,t),tool_output:q(e?.result,``),tool_error:q(e?.error,``),tool_duration_ms:J(q(e?.durationMs,``))}}function X(e,t,n,r){let i=t,a=t,o=n;switch(e){case`before_tool_call`:return Oe(i,o);case`after_tool_call`:return ke(i,o);case`before_llm_fetch`:return Se(r);case`after_llm_fetch`:return Ce(r);case`llm_input`:return Te(a,o);case`llm_output`:return Ee(a,o);default:return be(r)}}function Ae(e){return i(e??i(s(),`.openclaw`,`workspace`),`.openclaw-guardian`,`skill-detect-state.json`)}const je=Ae();function Me(e){if(!e||typeof e!=`object`||!(`code`in e))return;let{code:t}=e;return typeof t==`string`?t:void 0}function Ne(e,t){return e.is_detected?typeof e.last_detect_ts==`number`?(t??Date.now())-e.last_detect_ts>864e5:!0:!1}function Pe(e){return!e.skill_hash}let Fe=Promise.resolve();function Ie(e){let t=Fe.then(e,e);return Fe=t.catch(()=>void 0),t}async function Le(e){try{await h(e)}catch{}}async function Re(e,t){return Ie(async()=>{let n=t??je;e.logger.info(x(`[skill-storage] loading state from: ${n}`));try{let t=await d(n,`utf-8`),r=JSON.parse(t);return!r||typeof r!=`object`||Array.isArray(r)?(e.logger.warn(x(`[skill-storage] corrupted state file (invalid format), deleting and starting fresh`)),await Le(n),{}):(e.logger.info(x(`[skill-storage] loaded ${Object.keys(r).length} skill(s) from state`)),r)}catch(t){return Me(t)===`ENOENT`?(e.logger.info(x(`[skill-storage] no existing state file, starting fresh`)),{}):t instanceof SyntaxError?(e.logger.warn(x(`[skill-storage] corrupted state file (invalid JSON), deleting and starting fresh`)),await Le(n),{}):(e.logger.warn(x(`[skill-storage] failed to load state: ${t instanceof Error?t.message:String(t)}`)),{})}})}async function ze(e,t,n){return Ie(async()=>{let i=n??je,a=`${i}.tmp`;e.logger.info(x(`[skill-storage] saving state (${Object.keys(t).length} skill(s)) to: ${i}`));try{await u(r(i),{recursive:!0}),await g(a,JSON.stringify(t,null,2),`utf-8`),await p(a,i),e.logger.info(x(`[skill-storage] state saved successfully`))}catch(t){e.logger.error(x(`[skill-storage] failed to save state: ${t instanceof Error?t.message:String(t)}`)),await Le(a)}})}function Be(e,t,n){let r={...e},i=n??Date.now();for(let e of t){let t=r[e.dirName];t&&t.skill_hash===e.skillHash?Ne(t,i)?r[e.dirName]={...t,skill_name:e.skillName,is_detected:!1}:r[e.dirName]={...t,skill_name:e.skillName}:r[e.dirName]={skill_name:e.skillName,skill_hash:e.skillHash,is_detected:!1,last_detect_ts:null}}let a=new Set(t.map(e=>e.dirName));for(let e of Object.keys(r))a.has(e)||delete r[e];return r}var Ve=y(((e,t)=>{function n(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,`default`)?e.default:e}let r=new Int32Array([0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117]);function i(e){if(Buffer.isBuffer(e))return e;if(typeof e==`number`)return Buffer.alloc(e);if(typeof e==`string`)return Buffer.from(e);throw Error(`input must be buffer, number, or string, received `+typeof e)}function a(e){let t=i(4);return t.writeInt32BE(e,0),t}function o(e,t){e=i(e),Buffer.isBuffer(t)&&(t=t.readUInt32BE(0));let n=~~t^-1;for(var a=0;a<e.length;a++)n=r[(n^e[a])&255]^n>>>8;return n^-1}function s(){return a(o.apply(null,arguments))}s.signed=function(){return o.apply(null,arguments)},s.unsigned=function(){return o.apply(null,arguments)>>>0},t.exports=n(s)})),He=y((e=>{var t=b(`fs`),n=b(`stream`).Transform,r=b(`stream`).PassThrough,i=b(`zlib`),a=b(`util`),o=b(`events`).EventEmitter,s=b(`events`).errorMonitor,c=Ve();e.ZipFile=l,a.inherits(l,o);function l(){this.outputStream=new r,this.entries=[],this.outputStreamCursor=0,this.ended=!1,this.allDone=!1,this.forceZip64Eocd=!1,this.errored=!1,this.on(s,function(){this.errored=!0})}l.prototype.addFile=function(e,n,r){var i=this;if(n=x(n,!1),r??={},!g(i)){var a=new C(n,!1,r);i.entries.push(a),t.stat(e,function(n,o){if(n)return i.emit(`error`,n);if(!o.isFile())return i.emit(`error`,Error(`not a file: `+e));a.uncompressedSize=o.size,r.mtime??a.setLastModDate(o.mtime),r.mode??a.setFileAttributesMode(o.mode),a.setFileDataPumpFunction(function(){var n=t.createReadStream(e);a.state=C.FILE_DATA_IN_PROGRESS,n.on(`error`,function(e){i.emit(`error`,e)}),f(i,a,n)}),m(i)})}},l.prototype.addReadStream=function(e,t,n){this.addReadStreamLazy(t,n,function(t){t(null,e)})},l.prototype.addReadStreamLazy=function(e,t,n){var r=this;if(typeof t==`function`&&(n=t,t=null),t??={},e=x(e,!1),!g(r)){var i=new C(e,!1,t);r.entries.push(i),i.setFileDataPumpFunction(function(){i.state=C.FILE_DATA_IN_PROGRESS,n(function(e,t){if(e)return r.emit(`error`,e);f(r,i,t)})}),m(r)}},l.prototype.addBuffer=function(e,t,n){var r=this;if(t=x(t,!1),e.length>1073741823)throw Error(`buffer too large: `+e.length+` > 1073741823`);if(n??={},n.size!=null)throw Error(`options.size not allowed`);if(g(r))return;var a=new C(t,!1,n);a.uncompressedSize=e.length,a.crc32=c.unsigned(e),a.crcAndFileSizeKnown=!0,r.entries.push(a),a.compressionLevel===0?o(e):i.deflateRaw(e,{level:a.compressionLevel},function(e,t){o(t)});function o(e){a.compressedSize=e.length,a.setFileDataPumpFunction(function(){d(r,e),d(r,a.getDataDescriptor()),a.state=C.FILE_DATA_DONE,setImmediate(function(){m(r)})}),m(r)}},l.prototype.addEmptyDirectory=function(e,t){var n=this;if(e=x(e,!0),t??={},t.size!=null)throw Error(`options.size not allowed`);if(t.compress!=null)throw Error(`options.compress not allowed`);if(t.compressionLevel!=null)throw Error(`options.compressionLevel not allowed`);if(!g(n)){var r=new C(e,!0,t);n.entries.push(r),r.setFileDataPumpFunction(function(){d(n,r.getDataDescriptor()),r.state=C.FILE_DATA_DONE,m(n)}),m(n)}};var u=H([80,75,5,6]);l.prototype.end=function(e,t){if(typeof e==`function`&&(t=e,e=null),e??={},!this.ended&&(this.ended=!0,!this.errored)){if(this.calculatedTotalSizeCallback=t,this.forceZip64Eocd=!!e.forceZip64Format,e.comment){if(typeof e.comment==`string`?this.comment=re(e.comment):this.comment=e.comment,this.comment.length>65535)throw Error(`comment is too large`);if(U(this.comment,u))throw Error(`comment contains end of central directory record signature`)}else this.comment=S;m(this)}};function d(e,t){e.outputStream.write(t),e.outputStreamCursor+=t.length}function f(e,t,n){var a=new R,o=new L,s=t.compressionLevel===0?new r:new i.DeflateRaw({level:t.compressionLevel}),c=new L;n.pipe(a).pipe(o).pipe(s).pipe(c).pipe(e.outputStream,{end:!1}),c.on(`end`,function(){if(t.crc32=a.crc32,t.uncompressedSize==null)t.uncompressedSize=o.byteCount;else if(t.uncompressedSize!==o.byteCount)return e.emit(`error`,Error(`file data stream has unexpected number of bytes`));t.compressedSize=c.byteCount,e.outputStreamCursor+=t.compressedSize,d(e,t.getDataDescriptor()),t.state=C.FILE_DATA_DONE,m(e)})}function p(e){if(e.compress!=null&&e.compressionLevel!=null&&!!e.compress!=!!e.compressionLevel)throw Error(`conflicting settings for compress and compressionLevel`);return e.compressionLevel==null?e.compress===!1?0:6:e.compressionLevel}function m(e){if(e.allDone||e.errored)return;if(e.ended&&e.calculatedTotalSizeCallback!=null){var t=h(e);t!=null&&(e.calculatedTotalSizeCallback(t),e.calculatedTotalSizeCallback=null)}var n=r();function r(){for(var t=0;t<e.entries.length;t++){var n=e.entries[t];if(n.state<C.FILE_DATA_DONE)return n}return null}if(n!=null){if(n.state<C.READY_TO_PUMP_FILE_DATA||n.state===C.FILE_DATA_IN_PROGRESS)return;n.relativeOffsetOfLocalHeader=e.outputStreamCursor,d(e,n.getLocalFileHeader()),n.doFileDataPump()}else e.ended&&(e.offsetOfStartOfCentralDirectory=e.outputStreamCursor,e.entries.forEach(function(t){d(e,t.getCentralDirectoryRecord())}),d(e,ee(e)),e.outputStream.end(),e.allDone=!0)}function h(e){for(var t=0,n=0,r=0;r<e.entries.length;r++){var i=e.entries[r];if(i.compressionLevel!==0)return-1;if(i.state>=C.READY_TO_PUMP_FILE_DATA){if(i.uncompressedSize==null)return-1}else if(i.uncompressedSize==null)return null;i.relativeOffsetOfLocalHeader=t;var a=i.useZip64Format();t+=w+i.utf8FileName.length,t+=i.uncompressedSize,i.crcAndFileSizeKnown||(a?t+=A:t+=k),n+=j+i.utf8FileName.length+i.fileComment.length,i.forceDosTimestamp||(n+=M),a&&(n+=N)}var o=0;return(e.forceZip64Eocd||e.entries.length>=65535||n>=65535||t>=4294967295)&&(o+=_+v),o+=y+e.comment.length,t+n+o}function g(e){if(e.ended)throw Error(`cannot add entries after calling end()`);return!!e.errored}var _=56,v=20,y=22;function ee(e,t){var n=!1,r=e.entries.length;(e.forceZip64Eocd||e.entries.length>=65535)&&(r=65535,n=!0);var i=e.outputStreamCursor-e.offsetOfStartOfCentralDirectory,a=i;(e.forceZip64Eocd||i>=4294967295)&&(a=4294967295,n=!0);var o=e.offsetOfStartOfCentralDirectory;if((e.forceZip64Eocd||e.offsetOfStartOfCentralDirectory>=4294967295)&&(o=4294967295,n=!0),t)return n?_+v+y:y;var s=V(y+e.comment.length);if(s.writeUInt32LE(101010256,0),s.writeUInt16LE(0,4),s.writeUInt16LE(0,6),s.writeUInt16LE(r,8),s.writeUInt16LE(r,10),s.writeUInt32LE(a,12),s.writeUInt32LE(o,16),s.writeUInt16LE(e.comment.length,20),e.comment.copy(s,22),!n)return s;var c=V(_);c.writeUInt32LE(101075792,0),I(c,_-12,4),c.writeUInt16LE(E,12),c.writeUInt16LE(te,14),c.writeUInt32LE(0,16),c.writeUInt32LE(0,20),I(c,e.entries.length,24),I(c,e.entries.length,32),I(c,i,40),I(c,e.offsetOfStartOfCentralDirectory,48);var l=V(v);return l.writeUInt32LE(117853008,0),l.writeUInt32LE(0,4),I(l,e.outputStreamCursor,8),l.writeUInt32LE(1,16),Buffer.concat([c,l,s])}function x(e,t){if(e===``)throw Error(`empty metadataPath`);if(e=e.replace(/\\/g,`/`),/^[a-zA-Z]:/.test(e)||/^\//.test(e))throw Error(`absolute path: `+e);if(e.split(`/`).indexOf(`..`)!==-1)throw Error(`invalid relative path: `+e);var n=/\/$/.test(e);if(t)n||(e+=`/`);else if(n)throw Error(`file path cannot end with '/': `+e);return e}var S=V(0);function C(e,t,n){if(this.utf8FileName=H(e),this.utf8FileName.length>65535)throw Error(`utf8 file name too long. `+utf8FileName.length+` > 65535`);if(this.isDirectory=t,this.state=C.WAITING_FOR_METADATA,this.setLastModDate(n.mtime==null?new Date:n.mtime),this.forceDosTimestamp=!!n.forceDosTimestamp,n.mode==null?this.setFileAttributesMode(t?16893:33204):this.setFileAttributesMode(n.mode),t?(this.crcAndFileSizeKnown=!0,this.crc32=0,this.uncompressedSize=0,this.compressedSize=0):(this.crcAndFileSizeKnown=!1,this.crc32=null,this.uncompressedSize=null,this.compressedSize=null,n.size!=null&&(this.uncompressedSize=n.size)),t?this.compressionLevel=0:this.compressionLevel=p(n),this.forceZip64Format=!!n.forceZip64Format,n.fileComment){if(typeof n.fileComment==`string`?this.fileComment=H(n.fileComment,`utf-8`):this.fileComment=n.fileComment,this.fileComment.length>65535)throw Error(`fileComment is too large`)}else this.fileComment=S}C.WAITING_FOR_METADATA=0,C.READY_TO_PUMP_FILE_DATA=1,C.FILE_DATA_IN_PROGRESS=2,C.FILE_DATA_DONE=3,C.prototype.setLastModDate=function(e){this.mtime=e;var t=ne(e);this.lastModFileTime=t.time,this.lastModFileDate=t.date},C.prototype.setFileAttributesMode=function(e){if((e&65535)!==e)throw Error(`invalid mode. expected: 0 <= `+e+` <= 65535`);this.externalFileAttributes=e<<16>>>0},C.prototype.setFileDataPumpFunction=function(e){this.doFileDataPump=e,this.state=C.READY_TO_PUMP_FILE_DATA},C.prototype.useZip64Format=function(){return this.forceZip64Format||this.uncompressedSize!=null&&this.uncompressedSize>4294967294||this.compressedSize!=null&&this.compressedSize>4294967294||this.relativeOffsetOfLocalHeader!=null&&this.relativeOffsetOfLocalHeader>4294967294};var w=30,T=20,te=45,E=831,D=2048,O=8;C.prototype.getLocalFileHeader=function(){var e=0,t=0,n=0;this.crcAndFileSizeKnown&&(e=this.crc32,t=this.compressedSize,n=this.uncompressedSize);var r=V(w),i=D;return this.crcAndFileSizeKnown||(i|=O),r.writeUInt32LE(67324752,0),r.writeUInt16LE(T,4),r.writeUInt16LE(i,6),r.writeUInt16LE(this.getCompressionMethod(),8),r.writeUInt16LE(this.lastModFileTime,10),r.writeUInt16LE(this.lastModFileDate,12),r.writeUInt32LE(e,14),r.writeUInt32LE(t,18),r.writeUInt32LE(n,22),r.writeUInt16LE(this.utf8FileName.length,26),r.writeUInt16LE(0,28),Buffer.concat([r,this.utf8FileName])};var k=16,A=24;C.prototype.getDataDescriptor=function(){if(this.crcAndFileSizeKnown)return S;if(this.useZip64Format()){var e=V(A);return e.writeUInt32LE(134695760,0),e.writeUInt32LE(this.crc32,4),I(e,this.compressedSize,8),I(e,this.uncompressedSize,16),e}else{var e=V(k);return e.writeUInt32LE(134695760,0),e.writeUInt32LE(this.crc32,4),e.writeUInt32LE(this.compressedSize,8),e.writeUInt32LE(this.uncompressedSize,12),e}};var j=46,M=9,N=28;C.prototype.getCentralDirectoryRecord=function(){var e=V(j),t=D;this.crcAndFileSizeKnown||(t|=O);var n=S;if(!this.forceDosTimestamp){n=V(M),n.writeUInt16LE(21589,0),n.writeUInt16LE(M-4,2),n.writeUInt8(3,4);var r=Math.floor(this.mtime.getTime()/1e3);r<-2147483648&&(r=-2147483648),r>2147483647&&(r=2147483647),n.writeUInt32LE(r,5)}var i=this.compressedSize,a=this.uncompressedSize,o=this.relativeOffsetOfLocalHeader,s=T,c=S;return this.useZip64Format()&&(i=4294967295,a=4294967295,o=4294967295,s=te,c=V(N),c.writeUInt16LE(1,0),c.writeUInt16LE(N-4,2),I(c,this.uncompressedSize,4),I(c,this.compressedSize,12),I(c,this.relativeOffsetOfLocalHeader,20)),e.writeUInt32LE(33639248,0),e.writeUInt16LE(E,4),e.writeUInt16LE(s,6),e.writeUInt16LE(t,8),e.writeUInt16LE(this.getCompressionMethod(),10),e.writeUInt16LE(this.lastModFileTime,12),e.writeUInt16LE(this.lastModFileDate,14),e.writeUInt32LE(this.crc32,16),e.writeUInt32LE(i,20),e.writeUInt32LE(a,24),e.writeUInt16LE(this.utf8FileName.length,28),e.writeUInt16LE(n.length+c.length,30),e.writeUInt16LE(this.fileComment.length,32),e.writeUInt16LE(0,34),e.writeUInt16LE(0,36),e.writeUInt32LE(this.externalFileAttributes,38),e.writeUInt32LE(o,42),Buffer.concat([e,this.utf8FileName,n,c,this.fileComment])},C.prototype.getCompressionMethod=function(){return this.compressionLevel===0?0:8};var P=new Date(1980,0,1),F=new Date(2107,11,31,23,59,58);function ne(e){e<P?e=P:e>F&&(e=F);var t=0;t|=e.getDate()&31,t|=(e.getMonth()+1&15)<<5,t|=(e.getFullYear()-1980&127)<<9;var n=0;return n|=Math.floor(e.getSeconds()/2),n|=(e.getMinutes()&63)<<5,n|=(e.getHours()&31)<<11,{date:t,time:n}}function I(e,t,n){var r=Math.floor(t/4294967296),i=t%4294967296;e.writeUInt32LE(i,n),e.writeUInt32LE(r,n+4)}a.inherits(L,n);function L(e){n.call(this,e),this.byteCount=0}L.prototype._transform=function(e,t,n){this.byteCount+=e.length,n(null,e)},a.inherits(R,n);function R(e){n.call(this,e),this.crc32=0}R.prototype._transform=function(e,t,n){this.crc32=c.unsigned(e,this.crc32),n(null,e)};var z=`\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■\xA0`;if(z.length!==256)throw Error(`assertion failure`);var B=null;function re(e){if(/^[\x20-\x7e]*$/.test(e))return H(e,`utf-8`);if(B==null){B={};for(var t=0;t<z.length;t++)B[z[t]]=t}for(var n=V(e.length),t=0;t<e.length;t++){var r=B[e[t]];if(r==null)throw Error(`character not encodable in CP437: `+JSON.stringify(e[t]));n[t]=r}return n}function V(e){V=t;try{return V(e)}catch{return V=n,V(e)}function t(e){return Buffer.allocUnsafe(e)}function n(e){return new Buffer(e)}}function H(e,t){H=n;try{return H(e,t)}catch{return H=r,H(e,t)}function n(e,t){return Buffer.from(e,t)}function r(e,t){return new Buffer(e,t)}}function U(e,t){U=n;try{return U(e,t)}catch{return U=r,U(e,t)}function n(e,t){return e.includes(t)}function r(e,t){for(var n=0;n<=e.length-t.length;n++)for(var r=0;;r++){if(r===t.length)return!0;if(e[n+r]!==t[r])break}return!1}}}))();function Z(e){return`v1:${e}`}function Ue(e){if(!e||typeof e!=`object`||Array.isArray(e))return{};let t={};for(let[n,r]of Object.entries(e))t[n]=r===!0;return t}function We(e){return{skills:Object.values(e).map(e=>({skill_name:e.skill_name,skill_hash:Z(e.skill_hash)}))}}async function Ge(e,t){let n=le(e),r=We(t),i=await G(e,`batch_check_detection`,n,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(r)},H);return i&&typeof i==`object`&&!Array.isArray(i)&&`result`in i?Ue(i.result):Ue(i)}const Ke=10*1024*1024;async function qe(e){let t=await f(e),n=[];for(let r of t){let t=i(e,r),a=await l(t);a.isSymbolicLink()||(a.isDirectory()?n.push(...await qe(t)):a.isFile()&&n.push(t))}return n}async function Je(e){let t=await m(e).catch(()=>null);if(!t||!t.isDirectory())throw Error(`zipDirectory: path does not exist or is not a directory: ${e}`);let n=await qe(e);return n.sort((t,n)=>{let r=a(e,t),i=a(e,n);return r<i?-1:+(r>i)}),new Promise((t,r)=>{let i=new He.ZipFile,o=[],s=0,c=!1,l=e=>{c||(c=!0,r(e))};i.outputStream.on(`data`,t=>{if(!c){if(s+=t.length,s>Ke){l(Error(`zipDirectory: zip exceeds ${Ke} bytes limit for ${e} (${s} bytes)`));return}o.push(t)}}),i.outputStream.on(`end`,()=>{c||(c=!0,t(Buffer.concat(o)))}),i.outputStream.on(`error`,l);for(let t of n)i.addFile(t,a(e,t));i.end()})}async function Ye(e,t,n){let r=ue(e),i=`skill_detect:${n.skill_name}`;e.logger.info(x(`[skill-detect] detect: sending skill=${n.skill_name} hash=${n.skill_hash.slice(0,12)}... dir=${t}`));let a=await Je(t);e.logger.info(x(`[skill-detect] zipped ${t} (${a.length} bytes)`));let o=new FormData,s=new Blob([new Uint8Array(a)],{type:`application/zip`});return o.append(`file`,s,n.skill_name),o.append(`skill`,JSON.stringify({skill_name:n.skill_name,skill_hash:Z(n.skill_hash)})),o.append(`payload`,JSON.stringify(ve())),await G(e,i,r,{method:`POST`,body:o},6e5),e.logger.info(x(`[skill-detect] skill ${n.skill_name} detected successfully`)),!0}function Xe(e){if(e.tool_name!==`read`)return null;let t=e.tool_args;return!t||typeof t!=`object`||Array.isArray(t)?null:Object.values(t).find(e=>typeof e==`string`&&e.endsWith(`SKILL.md`))??null}async function Ze(e,t,i){let a=n(r(t));try{let t;i&&(t=Ae(e.runtime.agent.resolveAgentWorkspaceDir(e.config,i)));let n=(await Re(e,t))[a];return!n||!n.skill_hash?null:{skill_name:n.skill_name,skill_hash:Z(n.skill_hash)}}catch{return null}}function Qe(...e){return e.find(e=>typeof e==`string`)??``}function $e(e){return typeof e==`string`?e.toUpperCase():`PERMIT`}function et(e){if(!(typeof e!=`string`||e.length===0))try{let t=JSON.parse(e);return t&&typeof t==`object`&&!Array.isArray(t)?t:void 0}catch{return}}function tt(e){return{effect:$e(e?.effect),denyOutput:Qe(e?.deny_output),rewriteOutput:Qe(e?.rewrite_output)}}function nt(e){let t=$e(e.effect);if(t===`DENY`)return e.denyOutput?{action:`deny`,output:e.denyOutput,returnValue:{block:!0,blockReason:e.denyOutput||`Tool call blocked by detect service`}}:{action:`permit`,returnValue:void 0};if(t===`REWRITE`){if(!e.rewriteOutput)return{action:`permit`,returnValue:void 0};let t=et(e.rewriteOutput);return t?{action:`rewrite`,returnValue:{params:t}}:{action:`rewrite_invalid`,returnValue:void 0}}return{action:`permit`,returnValue:void 0}}async function rt(e,t,n,r,i){if(!await t.isHookEnabled(n)){e.logger.info(x(`[${n}] detect skipped: hook disabled by runtime config`));return}let a=Date.now(),o=X(n,r,i);T(e,n,o,E(e));try{let t=tt(await K(e,n,o));e.logger.info(x(`[${n}] detect effect observed: effect=${t.effect} (report-only hook)`))}catch(t){e.logger.error(x(`[${n}] detect request failed: ${t instanceof Error?t.message:String(t)}`))}finally{let t=Date.now()-a;e.logger.info(x(`[${n}] total_elapsed=${t}ms`))}}async function it(e,t,n,r){let i=Date.now();if(!await t.isHookEnabled(`before_tool_call`)){e.logger.info(x(`[before_tool_call] detect skipped: hook disabled by runtime config`));return}let a=X(`before_tool_call`,n,r),o=Xe(a),s=a;if(o){let t=await Ze(e,o,r.agentId);t&&(s={...s,...t},e.logger.info(x(`[before_tool_call] skill read detected: skill=${t.skill_name} hash=${t.skill_hash.slice(0,12)}...`)))}T(e,`before_tool_call`,s,E(e));let c;try{let t=nt(tt(await K(e,`before_tool_call`,s)));e.logger.info(x(`[before_tool_call] detect effect applied: ${JSON.stringify(t.returnValue)}`)),c=t.returnValue}catch(t){e.logger.error(x(`[before_tool_call] detect request failed: ${t instanceof Error?t.message:String(t)}`))}let l=Date.now()-i;return e.logger.info(x(`[before_tool_call] total_elapsed=${l}ms`)),c}function at(e,t){e.on(`llm_input`,async(n,r)=>{await rt(e,t,`llm_input`,n,r)}),e.on(`llm_output`,async(n,r)=>{await rt(e,t,`llm_output`,n,r)}),e.on(`after_tool_call`,async(n,r)=>{await rt(e,t,`after_tool_call`,n,r)}),e.on(`before_tool_call`,async(n,r)=>it(e,t,n,r))}function Q(e){return typeof e==`object`&&!!e}function ot(e,t){if(!Q(e))return null;let n=e[t];return Q(n)?n:null}function st(e){let t=ot(ot(e,`models`),`providers`);return t?Object.entries(t).map(([e,t])=>{if(!Q(t))return null;let n=t.baseUrl??t.baseURL;return typeof n==`string`&&n?{providerId:e,baseUrl:n}:null}).filter(e=>e!==null):[]}function ct(e,t){for(let n of t)if(e.startsWith(n.baseUrl))return n;return null}function lt(e){return typeof e==`string`?e:e instanceof URLSearchParams?e.toString():e instanceof Uint8Array?new TextDecoder().decode(e):ArrayBuffer.isView(e)?new TextDecoder().decode(new Uint8Array(e.buffer,e.byteOffset,e.byteLength)):e instanceof ArrayBuffer?new TextDecoder().decode(new Uint8Array(e)):null}function ut(e){let t=lt(e);if(!t)return null;try{let e=JSON.parse(t);return Q(e)?e:null}catch{return null}}function dt(e){return Q(e)?Array.isArray(e.messages)||typeof e.prompt==`string`||typeof e.input==`string`:!1}function ft(e){return typeof e==`string`&&e.includes(`/open-apis/security_plugin/v1/openclaw_plugin`)}function pt(e){return typeof e==`string`&&e.includes(`text/event-stream`)}function mt(e,t){let n=e.split(/\r?\n/).filter(e=>e.startsWith(`data:`)).map(e=>e.slice(5).trim()).filter(e=>e.length>0&&e!==`[DONE]`),r=Math.max(1,Number(t)||1);if(r===1)return n;let i=[];for(let e=0;e<n.length;e+=r)i.push(n.slice(e,e+r).join(`
2
- `));return i}function ht(e,t){return t?`${String(e).split(/\r?\n/).map(e=>`data: ${e}`).join(`
3
- `)}\n\n`:e}function gt(e,t,n){let r=new Headers(e.headers);return r.delete(`content-length`),n?r.set(`content-type`,`text/event-stream; charset=utf-8`):r.get(`content-type`)||r.set(`content-type`,`text/plain; charset=utf-8`),new Response(ht(t,n),{status:e.status,statusText:e.statusText,headers:r})}async function _t(e,t,n){let r=await t.clone().text(),i=pt(t.headers.get(`content-type`)??``);return{url:e,isSse:i,chunks:i?mt(r,n):[],originResp:i?``:r}}function vt(...e){return e.find(e=>typeof e==`string`)??``}function yt(e){return typeof e==`string`?e.toUpperCase():`PERMIT`}function bt(e){return{effect:yt(e?.effect),denyOutput:vt(e?.deny_output),rewriteOutput:vt(e?.rewrite_output)}}function xt(e){let t=yt(e.effect);return t===`DENY`&&e.denyOutput?{action:`deny`,output:e.denyOutput,effect:t}:t===`REWRITE`&&e.rewriteOutput?{action:`rewrite`,output:e.rewriteOutput,effect:t}:{action:`permit`,output:``,effect:t}}function St(e){let t=yt(e.effect);return t===`DENY`&&e.denyOutput?{action:`deny`,output:e.denyOutput,effect:t}:t===`REWRITE`&&e.rewriteOutput?{action:`rewrite`,output:e.rewriteOutput,effect:t}:{action:`permit`,output:``,effect:t}}function Ct(e,t,n){e.logger.info(x(`[${t}] ${w(n,E(e))}`))}function wt(){let e=globalThis.crypto;return e?.randomUUID?e.randomUUID():`${Date.now()}-${Math.random().toString(16).slice(2)}`}function Tt(e){let t=String(e);function n(e){if(typeof e!=`string`)return JSON.stringify(e);try{let t=JSON.parse(e);return typeof t==`string`?t:JSON.stringify(t)}catch{return e}}try{let e=JSON.parse(t);if(Array.isArray(e))return e.map(e=>n(e))}catch{}return t.split(/\r?\n/)}function Et(e,t){let n=new Headers(e.headers);n.delete(`content-length`),n.set(`content-type`,`text/event-stream; charset=utf-8`);let r=`${Tt(t).map(e=>`data: ${e}\n\n`).join(``)}`;return new Response(r,{status:e.status,statusText:e.statusText,headers:n})}function Dt(e){return(e.headers.get(`content-type`)??``).includes(`text/event-stream`)}async function Ot(e,t,n,r,i,a){let o=r.body;if(!o)return r;let s=Math.max(1,Number(await i.getSseChunkSize())||1),c=o.getReader(),l=new TextDecoder,u=new TextEncoder,d=``,f=[],p=[];async function m(r){let i=X(`after_llm_fetch`,null,null,{request_id:n,url:t,isSse:!0,chunks:r,originResp:``});return Ct(e,`after_llm_fetch`,i),St(bt(await K(e,`after_llm_fetch`,i)))}function h(e){f.length!==0&&(e.enqueue(u.encode(f.join(``))),f=[])}let g=new ReadableStream({async start(t){try{for(;;){let{value:i,done:o}=await c.read();if(o)break;for(d+=l.decode(i,{stream:!0});;){let i=d.indexOf(`
1
+ import{createRequire as e}from"node:module";import{definePluginEntry as t}from"openclaw/plugin-sdk/plugin-entry";import{basename as n,dirname as r,join as i,relative as a,resolve as o}from"node:path";import{homedir as s,hostname as c}from"node:os";import{lstat as l,mkdir as u,readFile as d,readdir as f,rename as p,stat as m,unlink as h,writeFile as g}from"node:fs/promises";import{createHash as _}from"node:crypto";import{existsSync as v}from"node:fs";var y=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),b=e(import.meta.url);function x(e){return`[openclaw-guardian-plugin] ${e}`}function S(){let e=new WeakSet;return(t,n)=>{if(n instanceof Error)return{name:n.name,message:n.message,stack:n.stack};if(typeof n==`bigint`)return n.toString();if(typeof n==`object`&&n){if(e.has(n))return`[Circular]`;e.add(n)}return n}}function C(e){return typeof e==`string`?e:typeof e==`number`||typeof e==`boolean`||typeof e==`bigint`?String(e):JSON.stringify(e,S(),2)??`null`}function w(e){let t=e?.pluginConfig?.env;return t===`boe`||t===`dev`||t===`pre`?t:`online`}let T=null,E=null;function D(e,t){if(typeof e!=`string`||!e)throw Error(`missing or invalid ${t}`);return e}function O(...e){for(let t of e)if(typeof t==`string`&&t)return t;return null}function k(e){return!e||typeof e!=`object`||Array.isArray(e)?null:e}function A(e){let t=O(e?.pluginConfig?.appId),n=O(e?.pluginConfig?.appSecret),r=t&&n?{appId:t,appSecret:n}:null,i=k(k(k(e?.config)?.channels)?.feishu),a=O(i?.appId,i?.app_id),o=O(i?.appSecret,i?.app_secret),s=a&&o?{appId:a,appSecret:o}:null,c=w(e);return c===`online`||c===`pre`?s??r??null:r??s??null}function ee(e){return!!A(e)}function j(e){let t=e?.pluginConfig?.x_tt_env;return typeof t==`string`&&t?t:w(e)===`boe`?`boe_tns_api`:null}function te(e){let t=w(e);return t===`online`?`https://open.feishu.cn`:t===`pre`?`https://open.feishu-pre.cn`:`https://open.feishu-boe.cn`}function M(e){if(!e||typeof e!=`object`||Array.isArray(e))return null;let t=e;return{code:typeof t.code==`number`?t.code:NaN,msg:typeof t.msg==`string`?t.msg:``,tenant_access_token:typeof t.tenant_access_token==`string`?t.tenant_access_token:void 0,expire:typeof t.expire==`number`?t.expire:void 0}}async function N(e){let t=Date.now();return T&&T.expiresAtMs-t>18e5?T.token:E||(E=(async()=>{let t=A(e);if(!t)throw Error(`missing Feishu appId/appSecret from api.config.channels.feishu or pluginConfig`);let n=D(t.appId,`appId`),r=D(t.appSecret,`appSecret`),i=`${te(e)}/open-apis/auth/v3/tenant_access_token/internal`,a={"content-type":`application/json`},o=j(e);o&&(a[`x-tt-env`]=o),e.logger.debug?.(x(`[auth] requesting tenant_access_token`));let{signal:s,clear:c}=ie(z),l;try{l=await fetch(i,{method:`POST`,headers:a,body:JSON.stringify({app_id:n,app_secret:r}),signal:s})}catch(e){throw c(),e instanceof Error&&e.name===`AbortError`?new P(i,z):new F(i,e)}finally{c()}let u=await l.text();if(!l.ok)throw Error(`[auth] tenant_access_token request failed status=${l.status} body=${u||`<empty>`}`);let d=null;try{d=u?JSON.parse(u):null}catch{d=null}let f=M(d);if(!f||!Number.isFinite(f.code))throw Error(`[auth] tenant_access_token response parse failed`);if(f.code!==0)throw Error(`[auth] tenant_access_token request failed code=${f.code}${f.msg?` msg=${f.msg}`:``}`);let p=D(f.tenant_access_token,`tenant_access_token`),m=typeof f.expire==`number`&&f.expire>0?f.expire:7200;return T={token:p,expiresAtMs:Date.now()+m*1e3},e.logger.info(x(`[auth] tenant_access_token updated`)),p})().finally(()=>{E=null}),E)}async function ne(e){if(w(e)===`dev`)return{};let t={},n=j(e);return n&&(t[`x-tt-env`]=n),t.authorization=`Bearer ${await N(e)}`,t}async function re(e,t={}){let n=await ne(e),r=new Headers(t.headers??{});for(let[e,t]of Object.entries(n))r.set(e,t);return{...t,headers:r}}var P=class extends Error{code=`TIMEOUT`;constructor(e,t){super(`Request to ${e} timed out after ${t}ms`),this.name=`RequestTimeoutError`}},F=class extends Error{code=`NETWORK`;constructor(e,t){super(`Network error requesting ${e}: ${t instanceof Error?t.message:String(t)}`),this.name=`NetworkError`}},I=class extends Error{code=`SERVER`;statusCode;constructor(e,t,n){super(`Server error ${t} from ${e}${n?`: ${n}`:``}`),this.name=`ServerError`,this.statusCode=t}};function L(e){return e instanceof P?`TIMEOUT`:e instanceof F?`NETWORK`:e instanceof I?`SERVER`:e instanceof Error&&e.name===`AbortError`?`TIMEOUT`:`UNKNOWN`}const R=5e3,z=5e3;function ie(e){let t=new AbortController,n=setTimeout(()=>t.abort(),e);return typeof n==`object`&&`unref`in n&&n.unref(),{signal:t.signal,clear:()=>clearTimeout(n)}}function B(e,t){if(!e)return t;let n=new AbortController,r=()=>n.abort();return e.addEventListener(`abort`,r,{once:!0}),t.addEventListener(`abort`,r,{once:!0}),n.signal}const V={dev:`http://localhost:8001`,online:`https://open.feishu.cn`,boe:`https://open.feishu-boe.cn`,pre:`https://open.feishu-pre.cn`};function H(e){return`${V[w(e)]}/open-apis/security_plugin/v1/openclaw_plugin`}function ae(e){return`${H(e)}/config`}function oe(e){return`${H(e)}/detect`}function se(e){return`${H(e)}/batch_check_skill_detection`}function ce(e){return`${H(e)}/skill_detect`}function le(e){return`${H(e)}/tracking_openclaw_plugin`}function ue(e={}){let t={};for(let[n,r]of Object.entries(e??{}))t[n]=C(r);return t}function de(e,t,n=``){return{hook_name:e,payload:ue(t),source:n}}function fe(e){if(!e)return null;try{let t=JSON.parse(e);return t&&typeof t==`object`&&!Array.isArray(t)?t:null}catch{return null}}function pe(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return typeof t.code==`number`&&Number.isFinite(t.code)&&typeof t.msg==`string`}async function me(e,t){let n=await t.text();if(!t.ok)throw Error(`${e} request failed: status=${t.status}`);let r=fe(n);if(!pe(r))throw Error(`${e} response parse failed: missing or invalid code/msg fields`);if(r.code!==0)throw Error(`${e} request failed: code=${r.code}${r.msg?` msg=${r.msg}`:``}`);return r.data??null}async function U(e,t,n,r,i=R){let a=await re(e,r),{signal:o,clear:s}=ie(i),c=B(a.signal,o),l,u=Date.now();try{l=await fetch(n,{...a,signal:c});let r=Date.now()-u;e.logger.info(x(`[${t}] http_elapsed=${r}ms status=${l.status} url=${n}`))}catch(r){let a=Date.now()-u;throw e.logger.info(x(`[${t}] http_elapsed=${a}ms error=${r instanceof Error?r.message:String(r)} url=${n}`)),s(),r instanceof Error&&r.name===`AbortError`?new P(n,i):new F(n,r)}finally{s()}return me(t,l)}let he=null;function ge(){return he||=c(),he}function _e(){return{hostname:ge()}}function ve(e){if(!e||typeof e!=`object`||Array.isArray(e))return e;let t=e;return Object.prototype.hasOwnProperty.call(t,`hostname`)?e:{...t,..._e()}}const ye=`llm_req_async_detect_result`;async function W(e,t,n,r=R){let i=de(t,ve(n),`miaoda`);return U(e,t,oe(e),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(i)},r)}async function be(e,t){let n={name:ye,tag_kv:{request_id:t.requestId,source:`miaoda`,need_block:String(t.needBlock),out_token_cnt:String(Math.max(0,Math.floor(t.outTokenCnt))),detect_duration_ms:String(Math.max(0,Math.floor(t.detectDurationMs)))}};await U(e,ye,le(e),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(n)},R)}function G(...e){return e.find(e=>e!=null)}function K(e){return e==null?``:typeof e==`string`?e:String(e)}function xe(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:{}}function Se(e){return Array.isArray(e)?e:[]}function Ce(e){try{let t=new URL(e);return{domain:t.host,path:t.pathname||`/`}}catch{return{domain:``,path:``}}}function we(e){let{domain:t,path:n}=Ce(K(e?.url));return{request_id:K(e?.request_id),domain:t,path:n,llm_req_detect_type:K(e?.llmReqDetectType),origin_req:G(e?.jsonBody,e?.rawBody,``)}}function Te(e){let{domain:t,path:n}=Ce(K(e?.url));return{request_id:K(e?.request_id),domain:t,path:n,is_sse:e?.isSse?`true`:`false`,llm_detect_time_ms:K(e?.llm_detect_time_ms),chunks:Se(e?.chunks),origin_resp:e?.isSse?``:K(G(e?.originResp,``))}}function Ee(e){return{request_id:K(e?.request_id),domain:K(e?.domain),path:K(e?.path),llm_detect_time_ms:K(e?.llm_detect_time_ms),api_type:`openai-completions`}}function De(e,t){return{agent_name:K(t?.agentId),session_id:K(t?.sessionId),session_key:K(t?.sessionKey),channel_id:K(t?.channelId),message_provider:K(t?.messageProvider),trigger:K(t?.trigger),model:K(e?.model),provider:K(e?.provider),run_id:K(e?.runId)}}function Oe(e,t){return{...De(e,t),prompt:K(e?.prompt),system_prompt:K(e?.systemPrompt),history_messages:Se(e?.historyMessages)}}function ke(e,t){return{...De(e,t),assistant_texts:Se(e?.assistantTexts),last_assistant:K(JSON.stringify(e?.lastAssistant))}}function Ae(e,t){return{agent_name:K(t?.agentId),session_id:K(t?.sessionId),session_key:K(t?.sessionKey),tool_call_id:K(e?.toolCallId),tool_name:K(e?.toolName),tool_args:G(e?.params,{}),run_id:K(e?.runId)}}function je(e,t){return Ae(e,t)}function Me(e,t){return{...Ae(e,t),tool_output:G(e?.result,``),tool_error:G(e?.error,``),tool_duration_ms:K(G(e?.durationMs,``))}}function q(e,t,n,r){let i=t,a=t,o=n;switch(e){case`before_tool_call`:return je(i,o);case`after_tool_call`:return Me(i,o);case`before_llm_fetch`:return we(r);case`after_llm_fetch`:case`after_llm_fetch_v2`:return Te(r);case`llm_req_async_detect`:return Ee(r??{});case`llm_input`:return Oe(a,o);case`llm_output`:return ke(a,o);default:return xe(r)}}function Ne(e){return i(e??i(s(),`.openclaw`,`workspace`),`.openclaw-guardian`,`skill-detect-state.json`)}const Pe=Ne();function Fe(e){if(!e||typeof e!=`object`||!(`code`in e))return;let{code:t}=e;return typeof t==`string`?t:void 0}function Ie(e,t){return e.is_detected?typeof e.last_detect_ts==`number`?(t??Date.now())-e.last_detect_ts>864e5:!0:!1}function Le(e){return!e.skill_hash}let Re=Promise.resolve();function ze(e){let t=Re.then(e,e);return Re=t.catch(()=>void 0),t}async function Be(e){try{await h(e)}catch{}}async function Ve(e,t){return ze(async()=>{let n=t??Pe;e.logger.info(x(`[skill-storage] loading state from: ${n}`));try{let t=await d(n,`utf-8`),r=JSON.parse(t);return!r||typeof r!=`object`||Array.isArray(r)?(e.logger.warn(x(`[skill-storage] corrupted state file (invalid format), deleting and starting fresh`)),await Be(n),{}):(e.logger.info(x(`[skill-storage] loaded ${Object.keys(r).length} skill(s) from state`)),r)}catch(t){return Fe(t)===`ENOENT`?(e.logger.info(x(`[skill-storage] no existing state file, starting fresh`)),{}):t instanceof SyntaxError?(e.logger.warn(x(`[skill-storage] corrupted state file (invalid JSON), deleting and starting fresh`)),await Be(n),{}):(e.logger.warn(x(`[skill-storage] failed to load state: ${t instanceof Error?t.message:String(t)}`)),{})}})}async function He(e,t,n){return ze(async()=>{let i=n??Pe,a=`${i}.tmp`;e.logger.info(x(`[skill-storage] saving state (${Object.keys(t).length} skill(s)) to: ${i}`));try{await u(r(i),{recursive:!0}),await g(a,JSON.stringify(t,null,2),`utf-8`),await p(a,i),e.logger.info(x(`[skill-storage] state saved successfully`))}catch(t){e.logger.error(x(`[skill-storage] failed to save state: ${t instanceof Error?t.message:String(t)}`)),await Be(a)}})}function Ue(e,t,n){let r={...e},i=n??Date.now();for(let e of t){let t=r[e.dirName];t&&t.skill_hash===e.skillHash?Ie(t,i)?r[e.dirName]={...t,skill_name:e.skillName,is_detected:!1}:r[e.dirName]={...t,skill_name:e.skillName}:r[e.dirName]={skill_name:e.skillName,skill_hash:e.skillHash,is_detected:!1,last_detect_ts:null}}let a=new Set(t.map(e=>e.dirName));for(let e of Object.keys(r))a.has(e)||delete r[e];return r}var We=y(((e,t)=>{function n(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,`default`)?e.default:e}let r=new Int32Array([0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117]);function i(e){if(Buffer.isBuffer(e))return e;if(typeof e==`number`)return Buffer.alloc(e);if(typeof e==`string`)return Buffer.from(e);throw Error(`input must be buffer, number, or string, received `+typeof e)}function a(e){let t=i(4);return t.writeInt32BE(e,0),t}function o(e,t){e=i(e),Buffer.isBuffer(t)&&(t=t.readUInt32BE(0));let n=~~t^-1;for(var a=0;a<e.length;a++)n=r[(n^e[a])&255]^n>>>8;return n^-1}function s(){return a(o.apply(null,arguments))}s.signed=function(){return o.apply(null,arguments)},s.unsigned=function(){return o.apply(null,arguments)>>>0},t.exports=n(s)})),Ge=y((e=>{var t=b(`fs`),n=b(`stream`).Transform,r=b(`stream`).PassThrough,i=b(`zlib`),a=b(`util`),o=b(`events`).EventEmitter,s=b(`events`).errorMonitor,c=We();e.ZipFile=l,a.inherits(l,o);function l(){this.outputStream=new r,this.entries=[],this.outputStreamCursor=0,this.ended=!1,this.allDone=!1,this.forceZip64Eocd=!1,this.errored=!1,this.on(s,function(){this.errored=!0})}l.prototype.addFile=function(e,n,r){var i=this;if(n=S(n,!1),r??={},!g(i)){var a=new w(n,!1,r);i.entries.push(a),t.stat(e,function(n,o){if(n)return i.emit(`error`,n);if(!o.isFile())return i.emit(`error`,Error(`not a file: `+e));a.uncompressedSize=o.size,r.mtime??a.setLastModDate(o.mtime),r.mode??a.setFileAttributesMode(o.mode),a.setFileDataPumpFunction(function(){var n=t.createReadStream(e);a.state=w.FILE_DATA_IN_PROGRESS,n.on(`error`,function(e){i.emit(`error`,e)}),f(i,a,n)}),m(i)})}},l.prototype.addReadStream=function(e,t,n){this.addReadStreamLazy(t,n,function(t){t(null,e)})},l.prototype.addReadStreamLazy=function(e,t,n){var r=this;if(typeof t==`function`&&(n=t,t=null),t??={},e=S(e,!1),!g(r)){var i=new w(e,!1,t);r.entries.push(i),i.setFileDataPumpFunction(function(){i.state=w.FILE_DATA_IN_PROGRESS,n(function(e,t){if(e)return r.emit(`error`,e);f(r,i,t)})}),m(r)}},l.prototype.addBuffer=function(e,t,n){var r=this;if(t=S(t,!1),e.length>1073741823)throw Error(`buffer too large: `+e.length+` > 1073741823`);if(n??={},n.size!=null)throw Error(`options.size not allowed`);if(g(r))return;var a=new w(t,!1,n);a.uncompressedSize=e.length,a.crc32=c.unsigned(e),a.crcAndFileSizeKnown=!0,r.entries.push(a),a.compressionLevel===0?o(e):i.deflateRaw(e,{level:a.compressionLevel},function(e,t){o(t)});function o(e){a.compressedSize=e.length,a.setFileDataPumpFunction(function(){d(r,e),d(r,a.getDataDescriptor()),a.state=w.FILE_DATA_DONE,setImmediate(function(){m(r)})}),m(r)}},l.prototype.addEmptyDirectory=function(e,t){var n=this;if(e=S(e,!0),t??={},t.size!=null)throw Error(`options.size not allowed`);if(t.compress!=null)throw Error(`options.compress not allowed`);if(t.compressionLevel!=null)throw Error(`options.compressionLevel not allowed`);if(!g(n)){var r=new w(e,!0,t);n.entries.push(r),r.setFileDataPumpFunction(function(){d(n,r.getDataDescriptor()),r.state=w.FILE_DATA_DONE,m(n)}),m(n)}};var u=V([80,75,5,6]);l.prototype.end=function(e,t){if(typeof e==`function`&&(t=e,e=null),e??={},!this.ended&&(this.ended=!0,!this.errored)){if(this.calculatedTotalSizeCallback=t,this.forceZip64Eocd=!!e.forceZip64Format,e.comment){if(typeof e.comment==`string`?this.comment=ie(e.comment):this.comment=e.comment,this.comment.length>65535)throw Error(`comment is too large`);if(H(this.comment,u))throw Error(`comment contains end of central directory record signature`)}else this.comment=C;m(this)}};function d(e,t){e.outputStream.write(t),e.outputStreamCursor+=t.length}function f(e,t,n){var a=new L,o=new I,s=t.compressionLevel===0?new r:new i.DeflateRaw({level:t.compressionLevel}),c=new I;n.pipe(a).pipe(o).pipe(s).pipe(c).pipe(e.outputStream,{end:!1}),c.on(`end`,function(){if(t.crc32=a.crc32,t.uncompressedSize==null)t.uncompressedSize=o.byteCount;else if(t.uncompressedSize!==o.byteCount)return e.emit(`error`,Error(`file data stream has unexpected number of bytes`));t.compressedSize=c.byteCount,e.outputStreamCursor+=t.compressedSize,d(e,t.getDataDescriptor()),t.state=w.FILE_DATA_DONE,m(e)})}function p(e){if(e.compress!=null&&e.compressionLevel!=null&&!!e.compress!=!!e.compressionLevel)throw Error(`conflicting settings for compress and compressionLevel`);return e.compressionLevel==null?e.compress===!1?0:6:e.compressionLevel}function m(e){if(e.allDone||e.errored)return;if(e.ended&&e.calculatedTotalSizeCallback!=null){var t=h(e);t!=null&&(e.calculatedTotalSizeCallback(t),e.calculatedTotalSizeCallback=null)}var n=r();function r(){for(var t=0;t<e.entries.length;t++){var n=e.entries[t];if(n.state<w.FILE_DATA_DONE)return n}return null}if(n!=null){if(n.state<w.READY_TO_PUMP_FILE_DATA||n.state===w.FILE_DATA_IN_PROGRESS)return;n.relativeOffsetOfLocalHeader=e.outputStreamCursor,d(e,n.getLocalFileHeader()),n.doFileDataPump()}else e.ended&&(e.offsetOfStartOfCentralDirectory=e.outputStreamCursor,e.entries.forEach(function(t){d(e,t.getCentralDirectoryRecord())}),d(e,x(e)),e.outputStream.end(),e.allDone=!0)}function h(e){for(var t=0,n=0,r=0;r<e.entries.length;r++){var i=e.entries[r];if(i.compressionLevel!==0)return-1;if(i.state>=w.READY_TO_PUMP_FILE_DATA){if(i.uncompressedSize==null)return-1}else if(i.uncompressedSize==null)return null;i.relativeOffsetOfLocalHeader=t;var a=i.useZip64Format();t+=T+i.utf8FileName.length,t+=i.uncompressedSize,i.crcAndFileSizeKnown||(a?t+=j:t+=ee),n+=te+i.utf8FileName.length+i.fileComment.length,i.forceDosTimestamp||(n+=M),a&&(n+=N)}var o=0;return(e.forceZip64Eocd||e.entries.length>=65535||n>=65535||t>=4294967295)&&(o+=_+v),o+=y+e.comment.length,t+n+o}function g(e){if(e.ended)throw Error(`cannot add entries after calling end()`);return!!e.errored}var _=56,v=20,y=22;function x(e,t){var n=!1,r=e.entries.length;(e.forceZip64Eocd||e.entries.length>=65535)&&(r=65535,n=!0);var i=e.outputStreamCursor-e.offsetOfStartOfCentralDirectory,a=i;(e.forceZip64Eocd||i>=4294967295)&&(a=4294967295,n=!0);var o=e.offsetOfStartOfCentralDirectory;if((e.forceZip64Eocd||e.offsetOfStartOfCentralDirectory>=4294967295)&&(o=4294967295,n=!0),t)return n?_+v+y:y;var s=B(y+e.comment.length);if(s.writeUInt32LE(101010256,0),s.writeUInt16LE(0,4),s.writeUInt16LE(0,6),s.writeUInt16LE(r,8),s.writeUInt16LE(r,10),s.writeUInt32LE(a,12),s.writeUInt32LE(o,16),s.writeUInt16LE(e.comment.length,20),e.comment.copy(s,22),!n)return s;var c=B(_);c.writeUInt32LE(101075792,0),F(c,_-12,4),c.writeUInt16LE(O,12),c.writeUInt16LE(D,14),c.writeUInt32LE(0,16),c.writeUInt32LE(0,20),F(c,e.entries.length,24),F(c,e.entries.length,32),F(c,i,40),F(c,e.offsetOfStartOfCentralDirectory,48);var l=B(v);return l.writeUInt32LE(117853008,0),l.writeUInt32LE(0,4),F(l,e.outputStreamCursor,8),l.writeUInt32LE(1,16),Buffer.concat([c,l,s])}function S(e,t){if(e===``)throw Error(`empty metadataPath`);if(e=e.replace(/\\/g,`/`),/^[a-zA-Z]:/.test(e)||/^\//.test(e))throw Error(`absolute path: `+e);if(e.split(`/`).indexOf(`..`)!==-1)throw Error(`invalid relative path: `+e);var n=/\/$/.test(e);if(t)n||(e+=`/`);else if(n)throw Error(`file path cannot end with '/': `+e);return e}var C=B(0);function w(e,t,n){if(this.utf8FileName=V(e),this.utf8FileName.length>65535)throw Error(`utf8 file name too long. `+utf8FileName.length+` > 65535`);if(this.isDirectory=t,this.state=w.WAITING_FOR_METADATA,this.setLastModDate(n.mtime==null?new Date:n.mtime),this.forceDosTimestamp=!!n.forceDosTimestamp,n.mode==null?this.setFileAttributesMode(t?16893:33204):this.setFileAttributesMode(n.mode),t?(this.crcAndFileSizeKnown=!0,this.crc32=0,this.uncompressedSize=0,this.compressedSize=0):(this.crcAndFileSizeKnown=!1,this.crc32=null,this.uncompressedSize=null,this.compressedSize=null,n.size!=null&&(this.uncompressedSize=n.size)),t?this.compressionLevel=0:this.compressionLevel=p(n),this.forceZip64Format=!!n.forceZip64Format,n.fileComment){if(typeof n.fileComment==`string`?this.fileComment=V(n.fileComment,`utf-8`):this.fileComment=n.fileComment,this.fileComment.length>65535)throw Error(`fileComment is too large`)}else this.fileComment=C}w.WAITING_FOR_METADATA=0,w.READY_TO_PUMP_FILE_DATA=1,w.FILE_DATA_IN_PROGRESS=2,w.FILE_DATA_DONE=3,w.prototype.setLastModDate=function(e){this.mtime=e;var t=P(e);this.lastModFileTime=t.time,this.lastModFileDate=t.date},w.prototype.setFileAttributesMode=function(e){if((e&65535)!==e)throw Error(`invalid mode. expected: 0 <= `+e+` <= 65535`);this.externalFileAttributes=e<<16>>>0},w.prototype.setFileDataPumpFunction=function(e){this.doFileDataPump=e,this.state=w.READY_TO_PUMP_FILE_DATA},w.prototype.useZip64Format=function(){return this.forceZip64Format||this.uncompressedSize!=null&&this.uncompressedSize>4294967294||this.compressedSize!=null&&this.compressedSize>4294967294||this.relativeOffsetOfLocalHeader!=null&&this.relativeOffsetOfLocalHeader>4294967294};var T=30,E=20,D=45,O=831,k=2048,A=8;w.prototype.getLocalFileHeader=function(){var e=0,t=0,n=0;this.crcAndFileSizeKnown&&(e=this.crc32,t=this.compressedSize,n=this.uncompressedSize);var r=B(T),i=k;return this.crcAndFileSizeKnown||(i|=A),r.writeUInt32LE(67324752,0),r.writeUInt16LE(E,4),r.writeUInt16LE(i,6),r.writeUInt16LE(this.getCompressionMethod(),8),r.writeUInt16LE(this.lastModFileTime,10),r.writeUInt16LE(this.lastModFileDate,12),r.writeUInt32LE(e,14),r.writeUInt32LE(t,18),r.writeUInt32LE(n,22),r.writeUInt16LE(this.utf8FileName.length,26),r.writeUInt16LE(0,28),Buffer.concat([r,this.utf8FileName])};var ee=16,j=24;w.prototype.getDataDescriptor=function(){if(this.crcAndFileSizeKnown)return C;if(this.useZip64Format()){var e=B(j);return e.writeUInt32LE(134695760,0),e.writeUInt32LE(this.crc32,4),F(e,this.compressedSize,8),F(e,this.uncompressedSize,16),e}else{var e=B(ee);return e.writeUInt32LE(134695760,0),e.writeUInt32LE(this.crc32,4),e.writeUInt32LE(this.compressedSize,8),e.writeUInt32LE(this.uncompressedSize,12),e}};var te=46,M=9,N=28;w.prototype.getCentralDirectoryRecord=function(){var e=B(te),t=k;this.crcAndFileSizeKnown||(t|=A);var n=C;if(!this.forceDosTimestamp){n=B(M),n.writeUInt16LE(21589,0),n.writeUInt16LE(M-4,2),n.writeUInt8(3,4);var r=Math.floor(this.mtime.getTime()/1e3);r<-2147483648&&(r=-2147483648),r>2147483647&&(r=2147483647),n.writeUInt32LE(r,5)}var i=this.compressedSize,a=this.uncompressedSize,o=this.relativeOffsetOfLocalHeader,s=E,c=C;return this.useZip64Format()&&(i=4294967295,a=4294967295,o=4294967295,s=D,c=B(N),c.writeUInt16LE(1,0),c.writeUInt16LE(N-4,2),F(c,this.uncompressedSize,4),F(c,this.compressedSize,12),F(c,this.relativeOffsetOfLocalHeader,20)),e.writeUInt32LE(33639248,0),e.writeUInt16LE(O,4),e.writeUInt16LE(s,6),e.writeUInt16LE(t,8),e.writeUInt16LE(this.getCompressionMethod(),10),e.writeUInt16LE(this.lastModFileTime,12),e.writeUInt16LE(this.lastModFileDate,14),e.writeUInt32LE(this.crc32,16),e.writeUInt32LE(i,20),e.writeUInt32LE(a,24),e.writeUInt16LE(this.utf8FileName.length,28),e.writeUInt16LE(n.length+c.length,30),e.writeUInt16LE(this.fileComment.length,32),e.writeUInt16LE(0,34),e.writeUInt16LE(0,36),e.writeUInt32LE(this.externalFileAttributes,38),e.writeUInt32LE(o,42),Buffer.concat([e,this.utf8FileName,n,c,this.fileComment])},w.prototype.getCompressionMethod=function(){return this.compressionLevel===0?0:8};var ne=new Date(1980,0,1),re=new Date(2107,11,31,23,59,58);function P(e){e<ne?e=ne:e>re&&(e=re);var t=0;t|=e.getDate()&31,t|=(e.getMonth()+1&15)<<5,t|=(e.getFullYear()-1980&127)<<9;var n=0;return n|=Math.floor(e.getSeconds()/2),n|=(e.getMinutes()&63)<<5,n|=(e.getHours()&31)<<11,{date:t,time:n}}function F(e,t,n){var r=Math.floor(t/4294967296),i=t%4294967296;e.writeUInt32LE(i,n),e.writeUInt32LE(r,n+4)}a.inherits(I,n);function I(e){n.call(this,e),this.byteCount=0}I.prototype._transform=function(e,t,n){this.byteCount+=e.length,n(null,e)},a.inherits(L,n);function L(e){n.call(this,e),this.crc32=0}L.prototype._transform=function(e,t,n){this.crc32=c.unsigned(e,this.crc32),n(null,e)};var R=`\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■\xA0`;if(R.length!==256)throw Error(`assertion failure`);var z=null;function ie(e){if(/^[\x20-\x7e]*$/.test(e))return V(e,`utf-8`);if(z==null){z={};for(var t=0;t<R.length;t++)z[R[t]]=t}for(var n=B(e.length),t=0;t<e.length;t++){var r=z[e[t]];if(r==null)throw Error(`character not encodable in CP437: `+JSON.stringify(e[t]));n[t]=r}return n}function B(e){B=t;try{return B(e)}catch{return B=n,B(e)}function t(e){return Buffer.allocUnsafe(e)}function n(e){return new Buffer(e)}}function V(e,t){V=n;try{return V(e,t)}catch{return V=r,V(e,t)}function n(e,t){return Buffer.from(e,t)}function r(e,t){return new Buffer(e,t)}}function H(e,t){H=n;try{return H(e,t)}catch{return H=r,H(e,t)}function n(e,t){return e.includes(t)}function r(e,t){for(var n=0;n<=e.length-t.length;n++)for(var r=0;;r++){if(r===t.length)return!0;if(e[n+r]!==t[r])break}return!1}}}))();function J(e){return`v1:${e}`}function Ke(e){if(!e||typeof e!=`object`||Array.isArray(e))return{};let t={};for(let[n,r]of Object.entries(e))t[n]=r===!0;return t}function qe(e){return{skills:Object.values(e).map(e=>({skill_name:e.skill_name,skill_hash:J(e.skill_hash)}))}}async function Je(e,t){let n=se(e),r=qe(t),i=await U(e,`batch_check_detection`,n,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(r)},R);return i&&typeof i==`object`&&!Array.isArray(i)&&`result`in i?Ke(i.result):Ke(i)}const Ye=10*1024*1024;async function Xe(e){let t=await f(e),n=[];for(let r of t){let t=i(e,r),a=await l(t);a.isSymbolicLink()||(a.isDirectory()?n.push(...await Xe(t)):a.isFile()&&n.push(t))}return n}async function Ze(e){let t=await m(e).catch(()=>null);if(!t||!t.isDirectory())throw Error(`zipDirectory: path does not exist or is not a directory: ${e}`);let n=await Xe(e);return n.sort((t,n)=>{let r=a(e,t),i=a(e,n);return r<i?-1:+(r>i)}),new Promise((t,r)=>{let i=new Ge.ZipFile,o=[],s=0,c=!1,l=e=>{c||(c=!0,r(e))};i.outputStream.on(`data`,t=>{if(!c){if(s+=t.length,s>Ye){l(Error(`zipDirectory: zip exceeds ${Ye} bytes limit for ${e} (${s} bytes)`));return}o.push(t)}}),i.outputStream.on(`end`,()=>{c||(c=!0,t(Buffer.concat(o)))}),i.outputStream.on(`error`,l);for(let t of n)i.addFile(t,a(e,t));i.end()})}async function Qe(e,t,n){let r=ce(e),i=`skill_detect:${n.skill_name}`;e.logger.info(x(`[skill-detect] detect: sending skill=${n.skill_name} hash=${n.skill_hash.slice(0,12)}... dir=${t}`));let a=await Ze(t);e.logger.info(x(`[skill-detect] zipped ${t} (${a.length} bytes)`));let o=new FormData,s=new Blob([new Uint8Array(a)],{type:`application/zip`});return o.append(`file`,s,n.skill_name),o.append(`skill`,JSON.stringify({skill_name:n.skill_name,skill_hash:J(n.skill_hash)})),o.append(`payload`,JSON.stringify(_e())),await U(e,i,r,{method:`POST`,body:o},6e5),e.logger.info(x(`[skill-detect] skill ${n.skill_name} detected successfully`)),!0}function $e(e){if(e.tool_name!==`read`)return null;let t=e.tool_args;return!t||typeof t!=`object`||Array.isArray(t)?null:Object.values(t).find(e=>typeof e==`string`&&e.endsWith(`SKILL.md`))??null}async function et(e,t,i){let a=n(r(t));try{let t;i&&(t=Ne(e.runtime.agent.resolveAgentWorkspaceDir(e.config,i)));let n=(await Ve(e,t))[a];return!n||!n.skill_hash?null:{skill_name:n.skill_name,skill_hash:J(n.skill_hash)}}catch{return null}}function tt(...e){return e.find(e=>typeof e==`string`)??``}function nt(e){return typeof e==`string`?e.toUpperCase():`PERMIT`}function rt(e){if(!(typeof e!=`string`||e.length===0))try{let t=JSON.parse(e);return t&&typeof t==`object`&&!Array.isArray(t)?t:void 0}catch{return}}function it(e){return{effect:nt(e?.effect),denyOutput:tt(e?.deny_output),rewriteOutput:tt(e?.rewrite_output)}}function at(e){let t=nt(e.effect);if(t===`DENY`)return e.denyOutput?{action:`deny`,output:e.denyOutput,returnValue:{block:!0,blockReason:e.denyOutput||`Tool call blocked by detect service`}}:{action:`permit`,returnValue:void 0};if(t===`REWRITE`){if(!e.rewriteOutput)return{action:`permit`,returnValue:void 0};let t=rt(e.rewriteOutput);return t?{action:`rewrite`,returnValue:{params:t}}:{action:`rewrite_invalid`,returnValue:void 0}}return{action:`permit`,returnValue:void 0}}async function ot(e,t,n,r,i){if(!await t.isHookEnabled(n)){e.logger.info(x(`[${n}] detect skipped: hook disabled by runtime config`));return}let a=Date.now(),o=q(n,r,i);try{let t=it(await W(e,n,o));e.logger.info(x(`[${n}] detect effect observed: effect=${t.effect} (report-only hook)`))}catch(t){e.logger.error(x(`[${n}] detect request failed: ${t instanceof Error?t.message:String(t)}`))}finally{let t=Date.now()-a;e.logger.info(x(`[${n}] total_elapsed=${t}ms`))}}async function st(e,t,n,r){let i=Date.now();if(!await t.isHookEnabled(`before_tool_call`)){e.logger.info(x(`[before_tool_call] detect skipped: hook disabled by runtime config`));return}let a=q(`before_tool_call`,n,r),o=$e(a),s=a;if(o){let t=await et(e,o,r.agentId);t&&(s={...s,...t},e.logger.info(x(`[before_tool_call] skill read detected: skill=${t.skill_name} hash=${t.skill_hash.slice(0,12)}...`)))}let c;try{let t=it(await W(e,`before_tool_call`,s)),n=at(t);e.logger.info(x(`[before_tool_call] detect effect applied: effect=${t.effect} has_return_value=${n.returnValue!==void 0}`)),c=n.returnValue}catch(t){e.logger.error(x(`[before_tool_call] detect request failed: ${t instanceof Error?t.message:String(t)}`))}let l=Date.now()-i;return e.logger.info(x(`[before_tool_call] total_elapsed=${l}ms`)),c}function ct(e,t){e.on(`llm_input`,async(n,r)=>{await ot(e,t,`llm_input`,n,r)}),e.on(`llm_output`,async(n,r)=>{await ot(e,t,`llm_output`,n,r)}),e.on(`after_tool_call`,async(n,r)=>{await ot(e,t,`after_tool_call`,n,r)}),e.on(`before_tool_call`,async(n,r)=>st(e,t,n,r))}const lt=[`taken_over`,`completed`,`failed_open`];function Y(e){return lt.includes(e)}function X(e,t){return Y(e.state)?!1:(e.state=t,!0)}function ut(...e){return e.find(e=>typeof e==`string`)??``}function dt(e){return typeof e==`string`?e.toUpperCase():`PERMIT`}function Z(e){return{effect:dt(e?.effect),denyOutput:ut(e?.deny_output),rewriteOutput:ut(e?.rewrite_output)}}function ft(e){let t=e.effect;return!!(t===`DENY`&&e.denyOutput||t===`REWRITE`&&e.rewriteOutput)}function pt(e){return typeof e==`string`?e.toUpperCase():``}function mt(e){return e===`PERMIT`||e===`DENY`||e===`REWRITE`}function ht(e){return typeof e==`number`&&Number.isFinite(e)&&e>0?Math.floor(e):1e3}function gt(e,t,n,r={}){let i=r.decisionMode??`takeover`,a=n&&typeof n==`object`?n:null,o={request_id:t,domain:typeof a?.domain==`string`?a.domain:``,path:typeof a?.path==`string`?a.path:``},s=r.initialDetectPromise,c=typeof r.detectStartTimeMs==`number`&&Number.isFinite(r.detectStartTimeMs)?Math.floor(r.detectStartTimeMs):Date.now(),l=ht(r.pollIntervalMs),u=typeof r.maxPollWaitMs==`number`&&Number.isFinite(r.maxPollWaitMs)&&r.maxPollWaitMs>0?Math.floor(r.maxPollWaitMs):3e4,d=null,f=!1,p=Date.now(),m,h=new Promise(e=>{m=e}),g={requestId:t,startedAtMs:Date.now(),state:`pending`,hasOriginalOutput:!1,originalOutputChunks:0,originalOutputBytes:0,flushPendingOutputStats:()=>{},cancelReader:null,takeoverPromise:h,stopPolling:()=>{f=!0,d&&=(clearTimeout(d),null)},cleanup:()=>{if(g.stopPolling(),g.flushPendingOutputStats(),g.cancelReader)try{g.cancelReader()}catch{}}};if(e.logger.info(x(`[before_llm_fetch] async_detect_started request_id=${t}`)),s)return s.then(()=>{Y(g.state)||_(g,e,u)}).catch(n=>{e.logger.error(x(`[before_llm_fetch] async_detect_failed request_id=${t} error=${n instanceof Error?n.message:String(n)}`)),X(g,`failed_open`)&&g.stopPolling()}),g;W(e,`before_llm_fetch`,n).then(n=>{if(Y(g.state))return;let r=n;if(!r){e.logger.info(x(`[before_llm_fetch] async_detect_init request_id=${t} effect=empty`)),_(g,e,u);return}let i=pt(r.effect);if(e.logger.info(x(`[before_llm_fetch] async_detect_init request_id=${t} effect=${i||`<empty>`}`)),mt(i)){y(g,Z(r),e);return}if(i&&i!==`PENDING`){e.logger.warn(x(`[before_llm_fetch] async_detect_init_invalid request_id=${t} effect=${i}`)),X(g,`failed_open`)&&g.stopPolling();return}_(g,e,u)}).catch(n=>{e.logger.error(x(`[before_llm_fetch] async_detect_failed request_id=${t} error=${n instanceof Error?n.message:String(n)}`)),X(g,`failed_open`)&&g.stopPolling()});function _(e,t,n){p=Date.now(),v(e,t,n)}function v(e,t,n){if(!(f||Y(e.state))){if(Date.now()-p>n){t.logger.info(x(`[llm_req_async_detect] async_detect_poll_timeout request_id=${e.requestId}`)),X(e,`failed_open`)&&e.stopPolling();return}d=setTimeout(async()=>{if(!(f||Y(e.state)))try{let r=await W(t,`llm_req_async_detect`,q(`llm_req_async_detect`,null,null,{...o,llm_detect_time_ms:c}));if(Y(e.state))return;if(!r){t.logger.info(x(`[llm_req_async_detect] async_detect_poll request_id=${e.requestId} effect=empty`)),v(e,t,n);return}let i=pt(r.effect);if(t.logger.info(x(`[llm_req_async_detect] async_detect_poll request_id=${e.requestId} effect=${i||`<empty>`}`)),i===`PENDING`){v(e,t,n);return}if(mt(i)){y(e,Z(r),t);return}if(!i){let n=typeof r.status==`string`?r.status:``;t.logger.warn(x(`[llm_req_async_detect] async_detect_poll_invalid request_id=${e.requestId} effect=<empty>${n?` legacy_status=${n}`:``}`)),X(e,`failed_open`)&&e.stopPolling();return}t.logger.warn(x(`[llm_req_async_detect] async_detect_poll_invalid request_id=${e.requestId} effect=${i}`)),X(e,`failed_open`)&&e.stopPolling()}catch(n){t.logger.error(x(`[llm_req_async_detect] async_detect_failed request_id=${e.requestId} error=${n instanceof Error?n.message:String(n)}`)),X(e,`failed_open`)&&e.stopPolling()}},l),typeof d==`object`&&d&&`unref`in d&&d.unref()}}function y(e,t,n){if(n.logger.info(x(`[before_llm_fetch] async_detect_decision request_id=${e.requestId} effect=${t.effect}`)),e.flushPendingOutputStats(),t.effect===`PERMIT`){e.stopPolling();return}if(ft(t)){if(i===`observe`){e.stopPolling(),n.logger.info(x(`[before_llm_fetch] async_detect_ignored request_id=${e.requestId} effect=${t.effect}`));return}if(e.decision=t,Y(e.state))return;if((e.state===`pending`||e.state===`response_ready`||e.state===`outputting`)&&X(e,`taken_over`)){if(e.stopPolling(),e.flushPendingOutputStats(),e.cancelReader)try{e.cancelReader()}catch{}m(),n.logger.info(x(`[before_llm_fetch] takeover request_id=${e.requestId} phase=${e.state===`pending`?`before_response`:`sse_streaming`} effect=${t.effect} original_chunks=${e.originalOutputChunks} original_bytes=${e.originalOutputBytes}`))}}}return g}function _t(e){let t=new Promise(()=>{});return{requestId:e,startedAtMs:Date.now(),state:`pending`,hasOriginalOutput:!1,originalOutputChunks:0,originalOutputBytes:0,flushPendingOutputStats:()=>{},cancelReader:null,takeoverPromise:t,stopPolling:()=>{},cleanup:()=>{}}}function Q(e){return typeof e==`object`&&!!e}function vt(e,t){if(!Q(e))return null;let n=e[t];return Q(n)?n:null}function yt(e){let t=vt(vt(e,`models`),`providers`);return t?Object.entries(t).map(([e,t])=>{if(!Q(t))return null;let n=t.baseUrl??t.baseURL;return typeof n==`string`&&n?{providerId:e,baseUrl:n}:null}).filter(e=>e!==null):[]}function bt(e,t){for(let n of t)if(e.startsWith(n.baseUrl))return n;return null}function xt(e){return typeof e==`string`?e:e instanceof URLSearchParams?e.toString():e instanceof Uint8Array?new TextDecoder().decode(e):ArrayBuffer.isView(e)?new TextDecoder().decode(new Uint8Array(e.buffer,e.byteOffset,e.byteLength)):e instanceof ArrayBuffer?new TextDecoder().decode(new Uint8Array(e)):null}function St(e){let t=xt(e);if(!t)return null;try{let e=JSON.parse(t);return Q(e)?e:null}catch{return null}}function Ct(e){return Q(e)?Array.isArray(e.messages)||typeof e.prompt==`string`||typeof e.input==`string`:!1}function wt(e){return typeof e==`string`&&e.includes(`/open-apis/security_plugin/v1/openclaw_plugin`)}function Tt(e){let t=e.split(`
2
+ `),n=[];for(let e of t)if(e.startsWith(`data:`)){let t=e.slice(5).trim();t&&t!==`[DONE]`&&n.push(t)}if(n.length===0)return 0;let r=n.join(`
3
+ `);try{let e=JSON.parse(r),t=Array.isArray(e?.choices)?e.choices:[],n=0;for(let e of t){let t=e?.delta?.content;typeof t==`string`&&(n+=t.length)}return n}catch{}return 0}function Et(){let e=globalThis.crypto;return e?.randomUUID?e.randomUUID():`${Date.now()}-${Math.random().toString(16).slice(2)}`}async function Dt(e,t){let n=typeof t==`number`&&Number.isFinite(t)&&t>0?Math.floor(t):R,r=null;try{return await Promise.race([e.then(e=>({timedOut:!1,value:e})),new Promise(e=>{r=setTimeout(()=>e({timedOut:!0}),n),typeof r.unref==`function`&&r.unref()})])}finally{r&&clearTimeout(r)}}function Ot(e){let t=String(e);function n(e){if(typeof e!=`string`)return JSON.stringify(e);try{let t=JSON.parse(e);return typeof t==`string`?t:JSON.stringify(t)}catch{return e}}function r(e){if(!e||e===`[DONE]`)return!0;try{return JSON.parse(e),!0}catch{return!1}}try{let e=JSON.parse(t);if(Array.isArray(e))return e.map(e=>n(e))}catch{}let i=t.split(/\r?\n\r?\n/).map(e=>e.trim()).filter(e=>e.length>0);if(i.some(e=>e.includes(`data:`))){let e=i.flatMap(e=>e.split(/\r?\n/).filter(e=>e.startsWith(`data:`)).map(e=>e.slice(5).trim())).filter(e=>e.length>0);if(e.length>0)return e.map(e=>n(e))}if(i.length>1)return i.map(e=>n(e));let a=t.split(/\r?\n/).map(e=>e.trim()).filter(e=>e.length>0);return a.length>1&&a.every(e=>r(e))?a.map(e=>n(e)):[t]}function kt(e){let t=Ot(e).filter(e=>e.length>0);return(t.at(-1)===`[DONE]`?t:[...t,`[DONE]`]).map(e=>`data: ${e}\n\n`)}function At(e){return(e.headers.get(`content-type`)??``).includes(`text/event-stream`)}function jt(e){return e.effect===`DENY`?e.denyOutput||null:e.effect===`REWRITE`&&e.rewriteOutput||null}function Mt(e,t,n){let r=jt(e)??``,i=new Headers;if(i.set(`content-type`,t?`text/event-stream; charset=utf-8`:`application/json; charset=utf-8`),!t)return new Response(r,{status:200,statusText:`OK`,headers:i});let a=new TextEncoder,o=kt(r),s=new ReadableStream({async start(e){try{for(let t=0;t<o.length;t+=1){let n=o[t];e.enqueue(a.encode(n)),t===0&&o.length>1&&await Nt()}}finally{try{e.close()}catch{}n?.()}}});return new Response(s,{status:200,statusText:`OK`,headers:i})}function Nt(){return new Promise(e=>{let t=setTimeout(e,0);typeof t.unref==`function`&&t.unref()})}function Pt(e,t,n,r,i){be(e,{requestId:t,needBlock:r,outTokenCnt:i,detectDurationMs:Math.max(0,Date.now()-n)}).catch(n=>{e.logger.error(x(`[llm_fetch] stream_tracking_failed request_id=${t} error=${n instanceof Error?n.message:String(n)}`))})}function Ft(e,t,n){n.then(async n=>{try{await n.body?.cancel()}catch(n){e.logger.debug?.(x(`[llm_fetch] background_response_cancel_failed request_id=${t} error=${n instanceof Error?n.message:String(n)}`))}}).catch(n=>{e.logger.debug?.(x(`[llm_fetch] background_fetch_ignored request_id=${t} error=${n instanceof Error?n.message:String(n)}`))})}async function It(e,t){let n=e.read().then(e=>({value:e.value,done:e.done,takeover:!1})),r=t.then(()=>({value:void 0,done:!1,takeover:!0}));return Promise.race([n,r])}async function Lt(e,t,n,r,i,a,o){let s=r.body;if(!s)return r;let c=s.getReader(),l=new TextDecoder,u=new TextEncoder,d=``,f=[],p=[],m=[],h=null,g=[],_=new Set,v=await a.isHookEnabled(`after_llm_fetch_v2`),y=Math.max(1,Number(await a.getSseChunkSize())||1),b=!1;i.cancelReader=()=>{try{c.cancel()}catch{}};function S(){if(h&&=(clearTimeout(h),null),m.length===0)return;let e=m;m=[];for(let t of e)i.originalOutputBytes+=Tt(t)}function C(){h||(h=setTimeout(()=>{h=null,S()},0),typeof h.unref==`function`&&h.unref())}i.flushPendingOutputStats=S;function w(t){b||(b=!0,i.flushPendingOutputStats(),Pt(e,n,o,t,i.originalOutputBytes))}function T(e){if(f.length!==0){if(i.state===`taken_over`&&i.decision){f=[],p=[];return}e.enqueue(u.encode(f.join(``))),i.originalOutputChunks+=p.length,p.length>0&&(i.hasOriginalOutput=!0,m.push(...p),C()),f=[],p=[]}}async function E(e){if(!i.decision)return;let t=kt(i.decision.effect===`DENY`?i.decision.denyOutput:i.decision.rewriteOutput);for(let n=0;n<t.length;n+=1){let r=t[n];e.enqueue(u.encode(r)),n===0&&t.length>1&&await Nt()}e.close()}async function D(t){f=[],await E(t),w(!0);try{await c.cancel()}catch{}e.logger.info(x(`[llm_fetch] total_elapsed=${Date.now()-o}ms request_id=${n}`))}function O(r){if(!v||r.length===0)return;let a=q(`after_llm_fetch_v2`,null,null,{request_id:n,url:t,isSse:!0,llm_detect_time_ms:o,chunks:r,originResp:``}),s=(async()=>{try{let t=await W(e,`after_llm_fetch_v2`,a);if(i.state===`taken_over`||i.state===`completed`||i.state===`failed_open`)return;let r=Z(t);if(!ft(r))return;if(i.decision=r,i.flushPendingOutputStats(),X(i,`taken_over`)){if(i.stopPolling(),i.cancelReader)try{i.cancelReader()}catch{}e.logger.info(x(`[after_llm_fetch_v2] takeover request_id=${n} effect=${r.effect} original_chunks=${i.originalOutputChunks} original_bytes=${i.originalOutputBytes}`))}}catch(t){e.logger.error(x(`[after_llm_fetch_v2] detect failed request_id=${n} error=${t instanceof Error?t.message:String(t)}`))}})();_.add(s),s.finally(()=>{_.delete(s)})}let k=new ReadableStream({async start(t){try{for(;;){if(i.state===`taken_over`&&i.decision){await D(t);return}let e=await It(c,i.takeoverPromise);if(e.takeover&&i.state===`taken_over`&&i.decision||i.state===`taken_over`&&i.decision){await D(t);return}if(e.done)break;let n=e.value,r=l.decode(n,{stream:!0});for(d+=r;;){let e=d.indexOf(`
4
4
 
5
- `),o=2;if(i<0&&(i=d.indexOf(`\r
5
+ `),n=2;if(e<0&&(e=d.indexOf(`\r
6
6
  \r
7
- `),o=4),i<0)break;let l=d.slice(0,i);d=d.slice(i+o);let g=`${l}\n\n`;f.push(g);let _=l.split(/\r?\n/);for(let e of _){if(!e.startsWith(`data:`))continue;let t=e.slice(5).trim();!t||t===`[DONE]`||p.push(t)}if(p.length>=s){try{let i=await m(p);if((i.action===`deny`||i.action===`rewrite`)&&i.output){f=[],p=[];let o=await Et(r,i.output).text();t.enqueue(u.encode(o));try{await c.cancel()}catch{}t.close(),e.logger.info(x(`[llm_fetch] total_elapsed=${Date.now()-a}ms request_id=${n}`));return}}catch(t){e.logger.error(x(`[after_llm_fetch] detect failed; passthrough buffered events: ${t instanceof Error?t.message:String(t)}`))}h(t),p=[]}}}if(d&&=(f.push(d),``),p.length>0)try{let i=await m(p);if((i.action===`deny`||i.action===`rewrite`)&&i.output){f=[],p=[];let o=await Et(r,i.output).text();t.enqueue(u.encode(o));try{await c.cancel()}catch{}t.close(),e.logger.info(x(`[llm_fetch] total_elapsed=${Date.now()-a}ms request_id=${n}`));return}}catch(t){e.logger.error(x(`[after_llm_fetch] detect failed; passthrough buffered events: ${t instanceof Error?t.message:String(t)}`))}h(t),t.close(),e.logger.info(x(`[llm_fetch] total_elapsed=${Date.now()-a}ms request_id=${n}`))}catch(e){try{await c.cancel()}catch{}t.error(e)}}}),_=new Headers(r.headers);return _.delete(`content-length`),_.set(`content-type`,`text/event-stream; charset=utf-8`),new Response(g,{status:r.status,statusText:r.statusText,headers:_})}function kt(e,t){let n=globalThis.fetch;if(typeof n!=`function`){e.logger.warn(x(`[before_llm_fetch] global.fetch is unavailable; skipping interceptor`));return}globalThis.__openclawGuardianOriginalFetch||(globalThis.__openclawGuardianOriginalFetch=n,globalThis.fetch=async function(r,i){let a=[r,i],o=r?.toString?.()??``,s=i??{},c=()=>n.call(globalThis,a[0],a[1]);if(a[1]||=s,ft(o))return c();let l,u=null;try{let r=ct(o,st(e.config));if(!r)return e.logger.info(x(`[before_llm_fetch] pass-through: no provider baseUrl match for url=${o}`)),c();e.logger.info(x(`[before_llm_fetch] matched provider=${r.providerId} baseUrl=${r.baseUrl} url=${o}`));let i=ut(s.body);if(!dt(i))return e.logger.info(x(`[before_llm_fetch] pass-through: matched provider=${r.providerId} but request body is not a supported LLM payload shape`)),c();let d={request_id:wt(),url:o,rawBody:lt(s.body)??``,jsonBody:i},f=String(d.request_id);if(u=Date.now(),await t.isHookEnabled(`before_llm_fetch`)){let t=X(`before_llm_fetch`,null,null,d);Ct(e,`before_llm_fetch`,t);let n=bt(await K(e,`before_llm_fetch`,t)),i=xt(n);(i.action===`deny`||i.action===`rewrite`)&&i.output?(s.body=String(i.output),a[1]=s,e.logger.info(x(`[before_llm_fetch] detect effect applied: ${i.action} (use output as new body) provider=${r.providerId}`))):e.logger.info(x(`[before_llm_fetch] detect effect passthrough: effect=${n.effect} provider=${r.providerId}`))}else e.logger.info(x(`[before_llm_fetch] detect skipped: hook disabled by runtime config`));if(l=await n.apply(this,a),!await t.isHookEnabled(`after_llm_fetch`))return u!==null&&e.logger.info(x(`[llm_fetch] total_elapsed=${Date.now()-u}ms request_id=${f}`)),l;if(Dt(l))return await Ot(e,o,f,l,t,u??Date.now());let p=await _t(o,l,await t.getSseChunkSize()),m=X(`after_llm_fetch`,null,null,{...p,request_id:f});Ct(e,`after_llm_fetch`,m);let h=bt(await K(e,`after_llm_fetch`,m)),g=St(h);return(g.action===`deny`||g.action===`rewrite`)&&g.output?(e.logger.info(x(`[after_llm_fetch] detect effect applied: ${g.action} provider=${r.providerId}`)),u!==null&&e.logger.info(x(`[llm_fetch] total_elapsed=${Date.now()-u}ms url=${o}`)),gt(l,g.output,p.isSse)):(e.logger.info(x(`[after_llm_fetch] detect effect passthrough: effect=${h.effect} provider=${r.providerId}`)),u!==null&&e.logger.info(x(`[llm_fetch] total_elapsed=${Date.now()-u}ms request_id=${f}`)),l)}catch(t){return e.logger.error(x(`[llm_fetch] detect request failed, allowing original fetch flow: ${t instanceof Error?t.message:String(t)}`)),l?(u!==null&&e.logger.info(x(`[llm_fetch] total_elapsed=${Date.now()-u}ms request_id=<unknown>`)),l):c()}})}function $(e){return e.replace(/\0/g,``)}function At(e,t){let n=s(),r=new Set,a=e.config??{},c=a?.skills?.load?.extraDirs;if(Array.isArray(c))for(let e of c)typeof e==`string`&&e.trim()&&r.add(o($(e.trim())));r.add(i(n,`.openclaw`,`skills`)),r.add(i(n,`.agents`,`skills`));let l=new Set,u=a?.agents?.defaults?.workspace;if(typeof u==`string`&&u.trim()&&l.add(o($(u.trim()))),Array.isArray(a?.agents?.list))for(let e of a.agents.list)typeof e?.workspace==`string`&&e.workspace.trim()&&l.add(o($(e.workspace.trim())));for(let e of l)r.add(i(e,`skills`)),r.add(i(e,`.agents`,`skills`));let d,f=e.pluginConfig;if(typeof f?.openClawDir==`string`&&f.openClawDir.trim())d=o($(f.openClawDir.trim()));else try{let t=e.runtime?.state?.resolveStateDir?.();typeof t==`string`&&t.trim()&&(d=t)}catch{}d&&(r.add(i(d,`skills`)),r.add(i(d,`.agents`,`skills`)));let p=a?.plugins;if(p?.installs&&typeof p.installs==`object`){for(let e of Object.values(p.installs))if(typeof e?.installPath==`string`&&e.installPath.trim()){let t=i($(e.installPath.trim()),`skills`);r.add(o(t))}}let m=t??i(n,`.openclaw`,`workspace`);r.add(i(m,`.agents`,`skills`)),r.add(i(m,`skills`));let h=Array.from(r),g=h.filter(e=>v(e));return e.logger.info(x(`[skill-scan] resolved ${h.length} skill path(s), ${g.length} exist`)),g}async function jt(e){let t;try{t=await f(e)}catch{return[]}let n=[];for(let r of t){let t=i(e,r),a=await l(t);a.isSymbolicLink()||(a.isDirectory()?n.push(...await jt(t)):a.isFile()&&n.push(t))}return n}const Mt=10*1024*1024;async function Nt(e){let t=await jt(e);if(t.length===0)return _(`sha256`).update(`empty-skill-dir`).digest(`hex`);let r=[],i=0;for(let a of t){let t=await d(a);if(i+=t.length,i>Mt)throw Error(`computeCanonicalHash: skill directory exceeds ${Mt} byte limit: ${e}`);let o=n(a),s=_(`sha256`).update(t).digest(`hex`);r.push(`${o}:${s}`)}return r.sort(),_(`sha256`).update(r.join(`
8
- `)).digest(`hex`)}function Pt(e){let t=/^name:\s*(.+)$/m.exec(e);return t?t[1].trim():null}function Ft(e){let t=/^---\n([\s\S]*?)\n---/.exec(e);return t?t[1]:``}async function It(e,t){let n;try{n=await f(t,{withFileTypes:!0,encoding:`utf8`})}catch{return[]}let r=[];for(let a of n){if(!a.isDirectory())continue;let n=i(t,a.name),o=i(n,`SKILL.md`);try{let e=Pt(Ft(await d(o,`utf-8`)))||a.name,t=await Nt(n);r.push({dirName:a.name,dirPath:n,filePath:o,skillName:e,skillHash:t})}catch(t){t instanceof Error&&t.message.includes(`byte limit`)&&e.logger.warn(x(`[skill-scan] skipping skill '${a.name}': ${t.message}`))}}return r}async function Lt(e,t){let n=At(e,t);e.logger.info(x(`[skill-scan] scanning ${n.length} skill location(s)`));let r=new Map;for(let t of n){let n=await It(e,t);n.length>0&&e.logger.info(x(`[skill-scan] ${t}: ${n.length} skill(s)`));for(let e of n)r.set(e.skillName,e)}let i=Array.from(r.values());return e.logger.info(x(`[skill-scan] scan complete: ${i.length} unique skill(s) across all locations`)),i}function Rt(e,t,n,r,i){e[t]={...n,skill_name:r.skill_name,skill_hash:r.skill_hash,is_detected:i,last_detect_ts:Date.now()}}async function zt(e,t){e.logger.info(x(`[skill-scan] starting skill scan`));let n=Date.now(),r=Ae(t),i=await Lt(e,t);if(i.length===0){e.logger.info(x(`[skill-scan] no skills found, skipping detection`));return}let a=Be(await Re(e,r),i);e.logger.info(x(`[skill-scan] merged state: ${Object.keys(a).length} skill(s)`));let o=new Map(i.map(e=>[e.dirName,e])),s=[];for(let[t,n]of Object.entries(a))if(o.get(t)){if(Pe(n)){e.logger.warn(x(`[skill-scan] ${n.skill_name}: skill_hash missing, skipping`));continue}n.is_detected||(e.logger.info(x(`[skill-scan] ${n.skill_name}: not detected, queuing`)),s.push({dirName:t,entry:n,entity:{skill_name:n.skill_name,skill_hash:n.skill_hash}}))}if(e.logger.info(x(`[skill-scan] ${s.length} skill(s) need detection`)),s.length===0){await ze(e,a,r),e.logger.info(x(`[skill-scan] skill scan complete (nothing to detect) total_elapsed=${Date.now()-n}ms scanned=${i.length}`));return}let c={};for(let{dirName:e}of s)c[e]=a[e];let l={},u=!1;try{l=await Ge(e,c),e.logger.info(x(`[skill-scan] batch_check result: ${JSON.stringify(l)}`))}catch(t){e.logger.error(x(`[skill-scan] batch_check_detection failed: ${t instanceof Error?t.message:String(t)}`)),u=!0}for(let{dirName:t,entry:n,entity:r}of s)l[Z(r.skill_hash)]===!0&&(Rt(a,t,n,r,!0),e.logger.info(x(`[skill-scan] ${r.skill_name}: already known by server (batch_check)`)));if(u){e.logger.warn(x(`[skill-scan] skipping individual detect calls: batch_check_detection was unreachable`)),await ze(e,a,r),e.logger.info(x(`[skill-scan] skill scan complete (partial — batch_check failed) total_elapsed=${Date.now()-n}ms scanned=${i.length}`));return}for(let{dirName:t,entry:n,entity:r}of s){if(l[r.skill_hash]===!0)continue;let n=o.get(t);if(n)try{let i=await Ye(e,n.dirPath,r);Rt(a,t,a[t],r,i),e.logger.info(x(`[skill-scan] detect result for ${r.skill_name}: is_detected=${i}`))}catch(n){e.logger.error(x(`[skill-scan] detect failed for ${r.skill_name}: ${n instanceof Error?n.message:String(n)}`)),Rt(a,t,a[t],r,!1)}}await ze(e,a,r),e.logger.info(x(`[skill-scan] skill scan complete total_elapsed=${Date.now()-n}ms scanned=${i.length} to_detect=${s.length}`))}async function Bt(e,t,n,r){e.logger.info(x(`[gateway_start] gateway ready on port=${n.port} ctx=${JSON.stringify(r)}`))}function Vt(e,t){let n=null,r=!1,i=!1,a;async function o(){if(i)return;let s=await t.getSkillScanIntervalMs();e.logger.info(x(`[skill-scan-service] next scan in ${s/1e3}s`)),n=setTimeout(async()=>{if(!i){if(!await t.isSkillDetectEnabled()){e.logger.info(x(`[skill-scan-service] periodic scan skipped: skill_detect disabled`)),await o();return}if(r){e.logger.info(x(`[skill-scan-service] periodic scan skipped: previous scan still running`)),await o();return}e.logger.info(x(`[skill-scan-service] periodic scan triggered`)),r=!0,zt(e,a).catch(t=>{e.logger.error(x(`[skill-scan-service] periodic scan failed: ${t instanceof Error?t.message:String(t)}`))}).finally(()=>{r=!1,o()})}},s),n.unref()}return{id:`openclaw-guardian-skill-scan`,async start(n){a=n.workspaceDir,e.logger.info(x(`[skill-scan-service] starting with workspaceDir=${a??`(default)`}`)),i=!1,await t.isSkillDetectEnabled()&&(e.logger.info(x(`[skill-scan-service] running initial skill scan`)),r=!0,zt(e,a).catch(t=>{e.logger.error(x(`[skill-scan-service] initial scan failed: ${t instanceof Error?t.message:String(t)}`))}).finally(()=>{r=!1})),await o()},async stop(t){i=!0,n&&=(clearTimeout(n),null),e.logger.info(x(`[skill-scan-service] stopped`))}}}function Ht(e,t){e.on(`gateway_start`,async(n,r)=>{await Bt(e,t,n,r)}),e.registerService(Vt(e,t))}const Ut=[...[`before_tool_call`,`after_tool_call`,`before_llm_fetch`,`after_llm_fetch`,`llm_input`,`llm_output`],`skill_detect`];function Wt(){return Object.fromEntries(Ut.map(e=>[e,!1]))}function Gt(e){let t=Wt(),n=e&&typeof e==`object`?e:{};for(let e of Ut)t[e]=!!n[e];return t}function Kt(e){return typeof e==`number`&&Number.isFinite(e)&&e>0?Math.floor(e):1}function qt(e){return typeof e==`number`&&Number.isFinite(e)&&e>0?Math.floor(e):600}function Jt(e){return typeof e==`number`&&Number.isFinite(e)&&e>0?Math.floor(e):900}function Yt(e){return{enabled:!1,hook_toggles:Wt(),sse_chunk_size:1,skill_scan_duration_second:900,query_duration_second:600,reason:e}}function Xt(e){let t=e&&typeof e==`object`?e:{},n=t.enabled===void 0?!0:!!t.enabled;return{enabled:n,hook_toggles:n?Gt(t.hook_toggles):Wt(),sse_chunk_size:Kt(t.sse_chunk_size),skill_scan_duration_second:Jt(t.skill_scan_duration_second),query_duration_second:qt(t.query_duration_second),reason:n?`remote`:`remote_disabled`}}function Zt(e){return st(e.config).map(e=>e.baseUrl)}async function Qt(e){let t={source:`miaoda`,base_url_list:Zt(e)};return Xt(await G(e,`runtime_config`,se(e),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(t)},H))}function $t(e){let t=Yt(`not_initialized`),n=!1,r=null,i=null;async function a(){let r=null;for(let i=1;i<=3;i+=1)try{let r=await Qt(e);return t=r,n=!0,e.logger.debug?.(x(`[runtime_config] initial config loaded on attempt=${i} enabled_hooks=${JSON.stringify(r.hook_toggles)}`)),t}catch(t){r=t;let n=V(t);if(e.logger.error(x(`[runtime_config] initial config load failed attempt=${i} errorCode=${n}: ${t instanceof Error?t.message:String(t)}`)),n===`SERVER`||n===`PARSE`)break}return t=Yt(`initial_fetch_failed`),e.logger.warn(x(`[runtime_config] initial config unavailable after 3 attempts; detection disabled by default${r?`: ${r instanceof Error?r.message:String(r)}`:``}`)),t}async function o(){try{let r=await Qt(e);return t=r,n=!0,e.logger.debug?.(x(`[runtime_config] config refreshed enabled_hooks=${JSON.stringify(r.hook_toggles)} sse_chunk_size=${r.sse_chunk_size}`)),t}catch(r){let i=V(r);return n?(e.logger.error(x(`[runtime_config] refresh failed (errorCode=${i}); keeping previous config: ${r instanceof Error?r.message:String(r)}`)),t):(e.logger.error(x(`[runtime_config] refresh failed before first successful load (errorCode=${i}): ${r instanceof Error?r.message:String(r)}`)),t=Yt(`refresh_failed_${i}`),t)}}function s(){r&&clearTimeout(r);let n=t.query_duration_second*1e3;e.logger.debug?.(x(`[runtime_config] next config refresh in ${t.query_duration_second}s`)),r=setTimeout(()=>{e.logger.debug?.(x(`[runtime_config] refresh loop fired`)),o().catch(t=>{e.logger.error(x(`[runtime_config] refresh loop failed: ${t instanceof Error?t.message:String(t)}`))}).finally(()=>{s()})},n),r.unref()}function c(){return i||=a().catch(n=>(e.logger.error(x(`[runtime_config] initialize failed: ${n instanceof Error?n.message:String(n)}`)),t)).finally(()=>{s()}),i}return{async isHookEnabled(e){return await c(),!!(t?.enabled&&t?.hook_toggles?.[e])},async isSkillDetectEnabled(){return await c(),!!(t?.enabled&&t?.hook_toggles?.skill_detect)},async getSseChunkSize(){return await c(),Kt(t?.sse_chunk_size)},async getSkillScanIntervalMs(){return await c(),Jt(t?.skill_scan_duration_second)*1e3}}}var en=t({id:`openclaw-guardian-plugin`,name:`OpenClaw Guardian Plugin`,description:`Reports OpenClaw hook payloads to the trust_layer detect service with remote hook toggles.`,register(e){if(!N(e)){e.logger.debug?.(x(`[plugin] missing Feishu appId/appSecret from api.config.channels.feishu or pluginConfig; skip all hooks and reporting`));return}let t=$t(e);kt(e,t),at(e,t),Ht(e,t)}});export{en as default};
7
+ `),n=4),e<0)break;let r=d.slice(0,e);if(d=d.slice(e+n),i.state===`taken_over`&&i.decision){d=``,await D(t);return}let a=`${r}\n\n`;f.push(a),p.push(r);let o=r.split(/\r?\n/);for(let e of o){if(!e.startsWith(`data:`))continue;let t=e.slice(5).trim();!t||t===`[DONE]`||g.push(t)}if(g.length>=y){let e=g.slice(0,y);g=g.slice(y),O(e)}X(i,`outputting`)}T(t)}d&&=(f.push(d),``),g.length>0&&(O([...g]),g=[]),T(t),!i.decision&&i.state!==`failed_open`&&i.state!==`taken_over`&&i.state!==`completed`&&e.logger.info(x(`[before_llm_fetch] async_detect_stopped_on_sse_end request_id=${n} state=${i.state} original_chunks=${i.originalOutputChunks} original_bytes=${i.originalOutputBytes}`)),X(i,`completed`)&&i.stopPolling(),t.close(),w(!1),e.logger.info(x(`[llm_fetch] total_elapsed=${Date.now()-o}ms request_id=${n}`))}catch(e){if(i.state===`taken_over`&&i.decision){await D(t);return}i.state!==`taken_over`&&(X(i,`completed`),i.stopPolling()),w(!1);try{await c.cancel()}catch{}t.error(e)}}}),A=new Headers(r.headers);return A.delete(`content-length`),A.set(`content-type`,`text/event-stream; charset=utf-8`),new Response(k,{status:r.status,statusText:r.statusText,headers:A})}function Rt(e,t){let n=globalThis.fetch;if(typeof n!=`function`){e.logger.warn(x(`[before_llm_fetch] global.fetch is unavailable; skipping interceptor`));return}globalThis.__openclawGuardianOriginalFetch||(globalThis.__openclawGuardianOriginalFetch=n,globalThis.fetch=async function(r,i){let a=[r,i],o=r?.toString?.()??``,s=i??{},c=()=>n.call(globalThis,a[0],a[1]);if(a[1]||=s,wt(o))return c();let l,u=null,d=null;try{let r=bt(o,yt(e.config));if(!r)return c();let i=St(s.body);if(!Ct(i))return c();let f=!!i.stream,p={request_id:Et(),url:o,rawBody:xt(s.body)??``,jsonBody:i},m=String(p.request_id);if(u=Date.now(),await t.isHookEnabled(`before_llm_fetch`)){let[n,i,o,c]=await Promise.all([t.isLlmReqSyncDetectEnabled(),t.getLlmReqSyncDetectTimeoutMs(),t.isLlmReqAsyncDetectEnabled(),t.getLlmAsyncDetectLoopQueryMs()]),l=n?`sync`:`async`,u=q(`before_llm_fetch`,null,null,{...p,llmReqDetectType:l}),f=Date.now(),h=W(e,`before_llm_fetch`,u,n&&o?Math.max(i,R):n?i:R);if(n)try{let t=await Dt(h,i);if(!(`value`in t))e.logger.warn(x(`[before_llm_fetch] sync detect timed out locally request_id=${m} timeout_ms=${i}`));else{let n=t.value,i=typeof n?.status==`string`?n.status:`done`;if(i!==`done`)e.logger.warn(x(`[before_llm_fetch] sync detect returned unexpected status=${i} request_id=${m}; ignoring and continuing original flow`));else{let t=Z(n);if(ft(t)){let n=jt(t);n?(s={...s,body:n},a[1]={...a[1],body:n},e.logger.info(x(`[before_llm_fetch] detect effect applied: ${t.effect} (sync request rewritten before fetch) provider=${r.providerId}`))):e.logger.warn(x(`[before_llm_fetch] sync detect returned effect=${t.effect} without replacement request body; continuing original request`))}e.logger.info(x(`[before_llm_fetch] sync detect completed with effect=${t.effect} request_id=${m}`))}}}catch(t){e.logger.error(x(`[before_llm_fetch] sync detect failed request_id=${m} timeout_ms=${i} error=${t instanceof Error?t.message:String(t)}`))}o?d=gt(e,m,u,{initialDetectPromise:h,pollIntervalMs:c,decisionMode:`takeover`,detectStartTimeMs:f}):n||(h.catch(t=>{e.logger.error(x(`[before_llm_fetch] async detect failed request_id=${m} error=${t instanceof Error?t.message:String(t)}`))}),e.logger.info(x(`[before_llm_fetch] sync wait disabled and async poll disabled; initial detect result will be ignored`)))}else e.logger.info(x(`[before_llm_fetch] detect skipped: hook disabled by runtime config`));let h=n.apply(this,a);if(d){let t=await Promise.race([h.then(e=>({type:`response`,response:e})),d.takeoverPromise.then(()=>({type:`takeover`}))]);if(t.type===`takeover`&&d.state===`taken_over`&&d.decision)return Ft(e,m,h),e.logger.info(x(`[before_llm_fetch] takeover request_id=${m} phase=before_response effect=${d.decision.effect} original_chunks=${d.originalOutputChunks} original_bytes=${d.originalOutputBytes}`)),u!==null&&e.logger.info(x(`[llm_fetch] total_elapsed=${Date.now()-u}ms request_id=${m}`)),Mt(d.decision,f,f?()=>Pt(e,m,u??Date.now(),!0,d.originalOutputBytes):void 0);if(t.type===`response`)l=t.response;else throw Error(`unexpected before_llm_fetch takeover state`)}else l=await h;return At(l)?(d??=_t(m),X(d,`response_ready`),await Lt(e,o,m,l,d,t,u??Date.now())):(d&&(X(d,`completed`),d.stopPolling(),e.logger.info(x(`[before_llm_fetch] non-sse response returned; stopping async detect request_id=${m}`))),u!==null&&e.logger.info(x(`[llm_fetch] total_elapsed=${Date.now()-u}ms request_id=${m}`)),l)}catch(t){return e.logger.error(x(`[llm_fetch] detect request failed, allowing original fetch flow: ${t instanceof Error?t.message:String(t)}`)),l?(u!==null&&e.logger.info(x(`[llm_fetch] total_elapsed=${Date.now()-u}ms request_id=<unknown>`)),l):c()}})}function $(e){return e.replace(/\0/g,``)}function zt(e,t){let n=s(),r=new Set,a=e.config??{},c=a?.skills?.load?.extraDirs;if(Array.isArray(c))for(let e of c)typeof e==`string`&&e.trim()&&r.add(o($(e.trim())));r.add(i(n,`.openclaw`,`skills`)),r.add(i(n,`.agents`,`skills`));let l=new Set,u=a?.agents?.defaults?.workspace;if(typeof u==`string`&&u.trim()&&l.add(o($(u.trim()))),Array.isArray(a?.agents?.list))for(let e of a.agents.list)typeof e?.workspace==`string`&&e.workspace.trim()&&l.add(o($(e.workspace.trim())));for(let e of l)r.add(i(e,`skills`)),r.add(i(e,`.agents`,`skills`));let d,f=e.pluginConfig;if(typeof f?.openClawDir==`string`&&f.openClawDir.trim())d=o($(f.openClawDir.trim()));else try{let t=e.runtime?.state?.resolveStateDir?.();typeof t==`string`&&t.trim()&&(d=t)}catch{}d&&(r.add(i(d,`skills`)),r.add(i(d,`.agents`,`skills`)));let p=a?.plugins;if(p?.installs&&typeof p.installs==`object`){for(let e of Object.values(p.installs))if(typeof e?.installPath==`string`&&e.installPath.trim()){let t=i($(e.installPath.trim()),`skills`);r.add(o(t))}}let m=t??i(n,`.openclaw`,`workspace`);r.add(i(m,`.agents`,`skills`)),r.add(i(m,`skills`));let h=Array.from(r),g=h.filter(e=>v(e));return e.logger.info(x(`[skill-scan] resolved ${h.length} skill path(s), ${g.length} exist`)),g}async function Bt(e){let t;try{t=await f(e)}catch{return[]}let n=[];for(let r of t){let t=i(e,r),a=await l(t);a.isSymbolicLink()||(a.isDirectory()?n.push(...await Bt(t)):a.isFile()&&n.push(t))}return n}const Vt=10*1024*1024;async function Ht(e){let t=await Bt(e);if(t.length===0)return _(`sha256`).update(`empty-skill-dir`).digest(`hex`);let r=[],i=0;for(let a of t){let t=await d(a);if(i+=t.length,i>Vt)throw Error(`computeCanonicalHash: skill directory exceeds ${Vt} byte limit: ${e}`);let o=n(a),s=_(`sha256`).update(t).digest(`hex`);r.push(`${o}:${s}`)}return r.sort(),_(`sha256`).update(r.join(`
8
+ `)).digest(`hex`)}function Ut(e){let t=/^name:\s*(.+)$/m.exec(e);return t?t[1].trim():null}function Wt(e){let t=/^---\n([\s\S]*?)\n---/.exec(e);return t?t[1]:``}async function Gt(e,t){let n;try{n=await f(t,{withFileTypes:!0,encoding:`utf8`})}catch{return[]}let r=[];for(let a of n){if(!a.isDirectory())continue;let n=i(t,a.name),o=i(n,`SKILL.md`);try{let e=Ut(Wt(await d(o,`utf-8`)))||a.name,t=await Ht(n);r.push({dirName:a.name,dirPath:n,filePath:o,skillName:e,skillHash:t})}catch(t){t instanceof Error&&t.message.includes(`byte limit`)&&e.logger.warn(x(`[skill-scan] skipping skill '${a.name}': ${t.message}`))}}return r}async function Kt(e,t){let n=zt(e,t);e.logger.info(x(`[skill-scan] scanning ${n.length} skill location(s)`));let r=new Map;for(let t of n){let n=await Gt(e,t);n.length>0&&e.logger.info(x(`[skill-scan] ${t}: ${n.length} skill(s)`));for(let e of n)r.set(e.skillName,e)}let i=Array.from(r.values());return e.logger.info(x(`[skill-scan] scan complete: ${i.length} unique skill(s) across all locations`)),i}function qt(e,t,n,r,i){e[t]={...n,skill_name:r.skill_name,skill_hash:r.skill_hash,is_detected:i,last_detect_ts:Date.now()}}async function Jt(e,t){e.logger.info(x(`[skill-scan] starting skill scan`));let n=Date.now(),r=Ne(t),i=await Kt(e,t);if(i.length===0){e.logger.info(x(`[skill-scan] no skills found, skipping detection`));return}let a=Ue(await Ve(e,r),i);e.logger.info(x(`[skill-scan] merged state: ${Object.keys(a).length} skill(s)`));let o=new Map(i.map(e=>[e.dirName,e])),s=[];for(let[t,n]of Object.entries(a))if(o.get(t)){if(Le(n)){e.logger.warn(x(`[skill-scan] ${n.skill_name}: skill_hash missing, skipping`));continue}n.is_detected||(e.logger.info(x(`[skill-scan] ${n.skill_name}: not detected, queuing`)),s.push({dirName:t,entry:n,entity:{skill_name:n.skill_name,skill_hash:n.skill_hash}}))}if(e.logger.info(x(`[skill-scan] ${s.length} skill(s) need detection`)),s.length===0){await He(e,a,r),e.logger.info(x(`[skill-scan] skill scan complete (nothing to detect) total_elapsed=${Date.now()-n}ms scanned=${i.length}`));return}let c={};for(let{dirName:e}of s)c[e]=a[e];let l={},u=!1;try{l=await Je(e,c),e.logger.info(x(`[skill-scan] batch_check result: ${JSON.stringify(l)}`))}catch(t){e.logger.error(x(`[skill-scan] batch_check_detection failed: ${t instanceof Error?t.message:String(t)}`)),u=!0}for(let{dirName:t,entry:n,entity:r}of s)l[J(r.skill_hash)]===!0&&(qt(a,t,n,r,!0),e.logger.info(x(`[skill-scan] ${r.skill_name}: already known by server (batch_check)`)));if(u){e.logger.warn(x(`[skill-scan] skipping individual detect calls: batch_check_detection was unreachable`)),await He(e,a,r),e.logger.info(x(`[skill-scan] skill scan complete (partial — batch_check failed) total_elapsed=${Date.now()-n}ms scanned=${i.length}`));return}for(let{dirName:t,entry:n,entity:r}of s){if(l[r.skill_hash]===!0)continue;let n=o.get(t);if(n)try{let i=await Qe(e,n.dirPath,r);qt(a,t,a[t],r,i),e.logger.info(x(`[skill-scan] detect result for ${r.skill_name}: is_detected=${i}`))}catch(n){e.logger.error(x(`[skill-scan] detect failed for ${r.skill_name}: ${n instanceof Error?n.message:String(n)}`)),qt(a,t,a[t],r,!1)}}await He(e,a,r),e.logger.info(x(`[skill-scan] skill scan complete total_elapsed=${Date.now()-n}ms scanned=${i.length} to_detect=${s.length}`))}async function Yt(e,t,n,r){e.logger.info(x(`[gateway_start] gateway ready on port=${n.port} ctx=${JSON.stringify(r)}`))}function Xt(e,t){let n=null,r=!1,i=!1,a;async function o(){if(i)return;let s=await t.getSkillScanIntervalMs();e.logger.info(x(`[skill-scan-service] next scan in ${s/1e3}s`)),n=setTimeout(async()=>{if(!i){if(!await t.isSkillDetectEnabled()){e.logger.info(x(`[skill-scan-service] periodic scan skipped: skill_detect disabled`)),await o();return}if(r){e.logger.info(x(`[skill-scan-service] periodic scan skipped: previous scan still running`)),await o();return}e.logger.info(x(`[skill-scan-service] periodic scan triggered`)),r=!0,Jt(e,a).catch(t=>{e.logger.error(x(`[skill-scan-service] periodic scan failed: ${t instanceof Error?t.message:String(t)}`))}).finally(()=>{r=!1,o()})}},s),n.unref()}return{id:`openclaw-guardian-skill-scan`,async start(n){a=n.workspaceDir,e.logger.info(x(`[skill-scan-service] starting with workspaceDir=${a??`(default)`}`)),i=!1,await t.isSkillDetectEnabled()&&(e.logger.info(x(`[skill-scan-service] running initial skill scan`)),r=!0,Jt(e,a).catch(t=>{e.logger.error(x(`[skill-scan-service] initial scan failed: ${t instanceof Error?t.message:String(t)}`))}).finally(()=>{r=!1})),await o()},async stop(t){i=!0,n&&=(clearTimeout(n),null),e.logger.info(x(`[skill-scan-service] stopped`))}}}function Zt(e,t){e.on(`gateway_start`,async(n,r)=>{await Yt(e,t,n,r)}),e.registerService(Xt(e,t))}const Qt=[`before_tool_call`,`after_tool_call`,`before_llm_fetch`,`after_llm_fetch_v2`,`llm_input`,`llm_output`,`skill_detect`];function $t(){return Object.fromEntries(Qt.map(e=>[e,!1]))}function en(e){let t=$t(),n=e&&typeof e==`object`?e:{};for(let e of Qt)t[e]=!!n[e];return t}function tn(e){return typeof e==`number`&&Number.isFinite(e)&&e>0?Math.floor(e):1}function nn(e){return typeof e==`number`&&Number.isFinite(e)&&e>0?Math.floor(e):600}const rn=1e3,an=1e3;function on(e,t){return typeof e==`number`&&Number.isFinite(e)&&e>0?Math.floor(e):t}function sn(e){return typeof e==`number`&&Number.isFinite(e)&&e>0?Math.floor(e):900}function cn(e){return{enabled:!1,hook_toggles:$t(),sse_chunk_size:1,skill_scan_duration_second:900,query_duration_second:600,enable_llm_req_sync_detect:!1,llm_req_sync_detect_timeout_ms:rn,enable_llm_req_async_detect:!1,llm_async_detect_loop_query_ms:an,reason:e}}function ln(e){let t=e&&typeof e==`object`?e:{},n=t.enabled===void 0?!0:!!t.enabled;return{enabled:n,hook_toggles:n?en(t.hook_toggles):$t(),sse_chunk_size:tn(t.sse_chunk_size),skill_scan_duration_second:sn(t.skill_scan_duration_second),query_duration_second:nn(t.query_duration_second),enable_llm_req_sync_detect:n?!!t.enable_llm_req_sync_detect:!1,llm_req_sync_detect_timeout_ms:on(t.llm_req_sync_detect_timeout_ms,rn),enable_llm_req_async_detect:n?!!t.enable_llm_req_async_detect:!1,llm_async_detect_loop_query_ms:on(t.llm_async_detect_loop_query_ms,an),reason:n?`remote`:`remote_disabled`}}function un(e){return yt(e.config).map(e=>e.baseUrl)}async function dn(e){let t={source:`miaoda`,base_url_list:un(e)};return ln(await U(e,`runtime_config`,ae(e),{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(t)},R))}function fn(e){let t=cn(`not_initialized`),n=!1,r=null,i=null;async function a(){let r=null;for(let i=1;i<=3;i+=1)try{let r=await dn(e);return t=r,n=!0,e.logger.info(x(`[runtime_config] initial config loaded on attempt=${i} enabled_hooks=${JSON.stringify(r.hook_toggles)} sync_detect=${r.enable_llm_req_sync_detect} async_detect=${r.enable_llm_req_async_detect}`)),t}catch(t){r=t;let n=L(t);if(e.logger.error(x(`[runtime_config] initial config load failed attempt=${i} errorCode=${n}: ${t instanceof Error?t.message:String(t)}`)),n===`SERVER`||n===`PARSE`)break}return t=cn(`initial_fetch_failed`),e.logger.warn(x(`[runtime_config] initial config unavailable after 3 attempts; detection disabled by default${r?`: ${r instanceof Error?r.message:String(r)}`:``}`)),t}async function o(){try{let r=await dn(e);return t=r,n=!0,e.logger.info(x(`[runtime_config] config refreshed enabled_hooks=${JSON.stringify(r.hook_toggles)} sse_chunk_size=${r.sse_chunk_size} sync_detect=${r.enable_llm_req_sync_detect} async_detect=${r.enable_llm_req_async_detect}`)),t}catch(r){let i=L(r);return n?(e.logger.error(x(`[runtime_config] refresh failed (errorCode=${i}); keeping previous config: ${r instanceof Error?r.message:String(r)}`)),t):(e.logger.error(x(`[runtime_config] refresh failed before first successful load (errorCode=${i}): ${r instanceof Error?r.message:String(r)}`)),t=cn(`refresh_failed_${i}`),t)}}function s(){r&&clearTimeout(r);let n=t.query_duration_second*1e3;e.logger.info(x(`[runtime_config] next config refresh in ${t.query_duration_second}s`)),r=setTimeout(()=>{e.logger.info(x(`[runtime_config] refresh loop fired`)),o().catch(t=>{e.logger.error(x(`[runtime_config] refresh loop failed: ${t instanceof Error?t.message:String(t)}`))}).finally(()=>{s()})},n),r.unref()}function c(){return i||=a().catch(n=>(e.logger.error(x(`[runtime_config] initialize failed: ${n instanceof Error?n.message:String(n)}`)),t)).finally(()=>{s()}),i}return{async isHookEnabled(e){return await c(),!!(t?.enabled&&t?.hook_toggles?.[e])},async isSkillDetectEnabled(){return await c(),!!(t?.enabled&&t?.hook_toggles?.skill_detect)},async getSseChunkSize(){return await c(),tn(t?.sse_chunk_size)},async getSkillScanIntervalMs(){return await c(),sn(t?.skill_scan_duration_second)*1e3},async isLlmReqSyncDetectEnabled(){return await c(),!!(t?.enabled&&t?.hook_toggles?.before_llm_fetch&&t?.enable_llm_req_sync_detect)},async getLlmReqSyncDetectTimeoutMs(){return await c(),on(t?.llm_req_sync_detect_timeout_ms,rn)},async isLlmReqAsyncDetectEnabled(){return await c(),!!(t?.enabled&&t?.hook_toggles?.before_llm_fetch&&t?.enable_llm_req_async_detect)},async getLlmAsyncDetectLoopQueryMs(){return await c(),on(t?.llm_async_detect_loop_query_ms,an)}}}var pn=t({id:`openclaw-guardian-plugin`,name:`OpenClaw Guardian Plugin`,description:`Reports OpenClaw hook payloads to the trust_layer detect service with remote hook toggles.`,register(e){if(!ee(e)){e.logger.debug?.(x(`[plugin] missing Feishu appId/appSecret from api.config.channels.feishu or pluginConfig; skip all hooks and reporting`));return}let t=fn(e);Rt(e,t),ct(e,t),Zt(e,t)}});export{pn as default};
@@ -2,7 +2,7 @@
2
2
  "id": "openclaw-guardian-plugin",
3
3
  "name": "OpenClaw Guardian Plugin",
4
4
  "description": "Reports OpenClaw hook payloads to security_plugin config and detect endpoints.",
5
- "version": "2026.4.19",
5
+ "version": "2026.5.19",
6
6
  "uiHints": {
7
7
  "appId": {
8
8
  "label": "Feishu App ID",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-tns/openclaw-guardian-plugin",
3
- "version": "2026.4.19",
3
+ "version": "2026.5.19",
4
4
  "type": "module",
5
5
  "description": "OpenClaw plugin that reports hook payloads to the security_plugin detect service with remote hook toggles.",
6
6
  "keywords": ["openclaw", "plugin", "security", "guardian"],