beeos-claw 0.6.75 → 0.6.77

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
@@ -227,6 +227,17 @@ command can contain multiple actions; unknown shell syntax falls back to
227
227
  `command` for the whole invocation. Standard `/bin`, `/usr/bin`, and
228
228
  `/usr/local/bin` executable paths use the same rules as bare names. Script
229
229
  execution shows the script basename without guessing what it produces.
230
+ Chinese font queries accept `fc-list :lang=zh` with optional `family`, `style`,
231
+ or `fullname` fields, followed by pure `sort -u` and `head -N` pipeline filters.
232
+ Unknown fields, extra file arguments, or other sort options fall back to `command`.
233
+ Directory listing accepts `ls` with `l`/`a`/`h` flags and at most one path.
234
+ `convert -version` and the complete fixed check
235
+ `python3 -c "import PIL; print(PIL.__version__)"` show `check_rendering`;
236
+ other inline Python remains `command`.
237
+ Headless `google-chrome` screenshots of local HTML or SVG to PNG use `generate_image`
238
+ with the output basename. Only known rendering flags are accepted; filenames
239
+ never imply `generate_poster`.
240
+ `identify` with one ordinary local PNG/JPEG/WebP/GIF path shows `read` and its basename.
230
241
  `write`/`edit` calls show `save` with the file basename. Unknown tools use `other`.
231
242
 
232
243
  `src/tool-activity.ts` reads actual tool names and arguments, including bounded
@@ -244,13 +255,19 @@ by their call ID. Background `pending`/`in_progress` updates keep the tool
244
255
  streaming; only `completed`/`failed` updates settle it. Late progress cannot
245
256
  replace a terminal result. Error information remains in the matching
246
257
  `tool_progress.data.is_error`, separate from activity.
258
+ Native hook results also read structured `isError` and `details` failure flags,
259
+ status, and timeout/error metadata. For `exec`/`exec_command`, a finite nonzero
260
+ numeric `details.exitCode` is a failure even when native status is `completed`.
261
+ Output text is never parsed for errors. `tool_use.state=done` means settled;
262
+ success or failure comes from the matching progress result.
247
263
 
248
264
  Acceptance coverage lives in `message-client-types.test.ts`,
249
- `runtime/im-reply-sink.test.ts`, and
265
+ `runtime/im-reply-sink.test.ts`, `runtime/tool-result-observation-router.test.ts`, and
250
266
  `runtime/message-service-run-output-channel.test.ts`: compound command actions,
251
267
  misleading titles and prompts, secret-bearing shell/URL arguments, wrapped
252
268
  calls, delayed anonymous approval errors, early results for a different ID,
253
- and approval waiting versus terminal updates.
269
+ approval waiting versus terminal updates, and structured native failures without
270
+ inferring errors from output text.
254
271
 
255
272
  MS transport lifecycle, PATCH retries, fallback writes, and stop reasons remain
256
273
  the SDK's responsibility. See the
@@ -1 +1 @@
1
- export class ToolResultObservationRouter{targets=new Map;register(t,e){const r=this.targets.get(t);if(r&&r!==e)throw new Error(`tool result observation target already registered for ${t}`);return this.targets.set(t,e),()=>{this.targets.get(t)===e&&this.targets.delete(t)}}route(t,e){const r=this.targets.get(t);return!!r&&(r.observeToolResult(e),!0)}size(){return this.targets.size}}
1
+ function structuredResultFailed(e){const t=e.rawResult;if(!t||"object"!=typeof t||Array.isArray(t))return!1;const r=t;if(!0===r.isError)return!0;if(!r.details||"object"!=typeof r.details||Array.isArray(r.details))return!1;const s=r.details;if(!1===s.ok||!1===s.success||!0===s.timedOut||Boolean(s.error))return!0;const i="string"==typeof s.status?s.status.trim().toLowerCase():"";return!!["error","failed","failure","timeout","timed_out","blocked","denied","forbidden","unavailable","approval-unavailable","disabled","aborted","cancelled","canceled","killed","invalid"].includes(i)||["exec","exec_command"].includes(e.toolName)&&"number"==typeof s.exitCode&&Number.isFinite(s.exitCode)&&0!==s.exitCode}export class ToolResultObservationRouter{targets=new Map;register(e,t){const r=this.targets.get(e);if(r&&r!==t)throw new Error(`tool result observation target already registered for ${e}`);return this.targets.set(e,t),()=>{this.targets.get(e)===t&&this.targets.delete(e)}}route(e,t){const r=this.targets.get(e);return!!r&&(r.observeToolResult({...t,isError:t.isError||structuredResultFailed(t)}),!0)}size(){return this.targets.size}}
@@ -1 +1 @@
1
- const record=e=>{if("string"==typeof e&&e.length<=65536)try{e=JSON.parse(e)}catch{return{}}return null===e||"object"!=typeof e||Array.isArray(e)?{}:e},text=e=>"string"==typeof e?e:"",short=e=>{const t=e.replace(/[\u0000-\u001f\u007f]/g," ").trim(),n=Array.from(t);return n.length<=180?t:`${n.slice(0,180).join("")}…`},action=(e,t="")=>{const n=short(t);return n?{kind:e,subject:n}:{kind:e}},filename=e=>text(e).replaceAll("\\","/").split("/").at(-1)??"",toolName=e=>text(e).split(":").at(-1)??"";export function toolActivity(e,t){let n,s=toolName(e),r=record(t);for(let e=0;e<3&&"tool_call"===s;e++)s=toolName(r.id??r.name),r=record(r.args??r.arguments??r.input);switch(s){case"exec":case"exec_command":n=commandActions(text(r.command??r.cmd));break;case"beeos_search":case"web_search":case"search_web":n=[action("search",text(r.query))];break;case"beeos_fetch":case"web_fetch":{let e="";try{const t=new URL(text(r.url));"https:"!==t.protocol&&"http:"!==t.protocol||(e=t.hostname)}catch{}n=[action("page",e)];break}case"read":case"read_file":n=[action("read",filename(r.fileName??r.file_path??r.path))];break;case"write":case"edit":case"write_file":case"edit_file":case"beeos_upload_file":n=Array.isArray(r.paths)&&r.paths.length>0?r.paths.slice(0,5).map(e=>action("save",filename(e))):[action("save",filename(r.fileName??r.file_path??r.path))];break;case"tool_search":{const e=Array.isArray(r.queries)?r.queries:[],t=e.length>0&&e.every(e=>{const t=text(record(e).query).toLowerCase();return/\b(image|poster|graphic)\b/.test(t)&&/\b(generate|create|design)\b/.test(t)&&!/\b(not|never|without)\b/.test(t)});n=[action(t?"find_design_tools":"find_tools")];break}case"image_generate":{const e=text(r.prompt).trim(),t=/^(?:制作|生成|设计)[^不无非。!?\n]{0,60}海报[。!!]?$/i.test(e)||/^(?:create|generate|design) (?:a |an )?poster[.!]?$/i.test(e);n=[action(t?"generate_poster":"generate_image")];break}default:n=[action("other")]}return{schema_version:1,source:"tool_arguments",actions:n}}function commandActions(e){const t=[action("command")];if(!e||e.length>8192||/[$`\\(){}<>]/.test(e))return t;const n=/"[^"\n]*"|'[^'\n]*'|&&|\|\||[;|\n]|[^\s"';|&]+/g,s=[],r=[];let a=[],i=0,c="";for(const o of e.matchAll(n)){const n=e.slice(i,o.index);if(n.trim())return t;const l=o[0],h=[";","|","&&","||","\n"].includes(l);if(!h&&a.length>0&&0===n.length)return t;if(i=o.index+l.length,h){if(!a.length)return t;s.push(a),r.push(c),a=[],c=l}else a.push(l.startsWith('"')||l.startsWith("'")?l.slice(1,-1):l)}if(e.slice(i).trim()||!a.length&&["&&","||","|"].includes(c))return t;a.length&&(s.push(a),r.push(c));const o=[],l=new Set(["rsvg-convert","inkscape","chromium","chromium-browser","google-chrome","convert","magick","python3"]);for(const[e,n]of s.entries()){const[s,...a]=n,i=s.replace(/^\/(?:usr\/(?:local\/)?)?bin\/([A-Za-z0-9_.-]+)$/,"$1");let c;if("echo"!==i||1!==a.length||!["---","DONE"].includes(a[0])){if("which"===i&&a.length>0&&a.every(e=>l.has(e))||"command"===i&&2===a.length&&"-v"===a[0]&&l.has(a[1]))c=action("check_rendering");else if("fc-list"===i&&(0===a.length||1===a.length&&":lang=zh"===a[0]))c=action(0===a.length?"list_fonts":"list_chinese_fonts");else if("ls"!==i||0!==a.length&&(1!==a.length||a[0].startsWith("-"))){if("head"===i&&1===a.length&&/^-\d+$/.test(a[0])&&o.length>0&&"|"===r[e])continue;{const e="python3"===i&&"-m"===a[0]&&"pip"===a[1]?["pip",...a.slice(2)]:"uv"===i&&"pip"===a[0]?a:[i,...a];if("pip"!==e[0]&&"pip3"!==e[0]||"install"!==e[1]){if(!["python","python3","node"].includes(i)||1!==a.length||!/^(?:[A-Za-z0-9_./-]+\/)?[A-Za-z0-9_-][A-Za-z0-9_.-]*\.(?:py|js|mjs)$/.test(a[0]))return t;c=action("run_script",filename(a[0]))}else{const n=e.slice(2).filter(e=>!["--quiet","-q","--upgrade","-U","--user","--no-cache-dir"].includes(e));if(!n.length||n.length>6||n.some(e=>!/^[A-Za-z0-9][A-Za-z0-9_.-]{0,79}(?:==[A-Za-z0-9_.-]{1,40})?$/.test(e)))return t;c=action("install",n.join(", "))}}}else c=action("list_files");o.some(e=>e.kind===c.kind&&e.subject===c.subject)||o.push(c)}}return o.length?o:t}
1
+ const record=e=>{if("string"==typeof e&&e.length<=65536)try{e=JSON.parse(e)}catch{return{}}return null===e||"object"!=typeof e||Array.isArray(e)?{}:e},text=e=>"string"==typeof e?e:"",short=e=>{const t=e.replace(/[\u0000-\u001f\u007f]/g," ").trim(),n=Array.from(t);return n.length<=180?t:`${n.slice(0,180).join("")}…`},action=(e,t="")=>{const n=short(t);return n?{kind:e,subject:n}:{kind:e}},filename=e=>text(e).replaceAll("\\","/").split("/").at(-1)??"",toolName=e=>text(e).split(":").at(-1)??"";export function toolActivity(e,t){let n,s=toolName(e),i=record(t);for(let e=0;e<3&&"tool_call"===s;e++)s=toolName(i.id??i.name),i=record(i.args??i.arguments??i.input);switch(s){case"exec":case"exec_command":n=commandActions(text(i.command??i.cmd));break;case"beeos_search":case"web_search":case"search_web":n=[action("search",text(i.query))];break;case"beeos_fetch":case"web_fetch":{let e="";try{const t=new URL(text(i.url));"https:"!==t.protocol&&"http:"!==t.protocol||(e=t.hostname)}catch{}n=[action("page",e)];break}case"read":case"read_file":n=[action("read",filename(i.fileName??i.file_path??i.path))];break;case"write":case"edit":case"write_file":case"edit_file":case"beeos_upload_file":n=Array.isArray(i.paths)&&i.paths.length>0?i.paths.slice(0,5).map(e=>action("save",filename(e))):[action("save",filename(i.fileName??i.file_path??i.path))];break;case"tool_search":{const e=Array.isArray(i.queries)?i.queries:[],t=e.length>0&&e.every(e=>{const t=text(record(e).query).toLowerCase();return/\b(image|poster|graphic)\b/.test(t)&&/\b(generate|create|design)\b/.test(t)&&!/\b(not|never|without)\b/.test(t)});n=[action(t?"find_design_tools":"find_tools")];break}case"image_generate":{const e=text(i.prompt).trim(),t=/^(?:制作|生成|设计)[^不无非。!?\n]{0,60}海报[。!!]?$/i.test(e)||/^(?:create|generate|design) (?:a |an )?poster[.!]?$/i.test(e);n=[action(t?"generate_poster":"generate_image")];break}default:n=[action("other")]}return{schema_version:1,source:"tool_arguments",actions:n}}function commandActions(e){const t=[action("command")];if(!e||e.length>8192)return t;if(/^(?:\/(?:usr\/(?:local\/)?)?bin\/)?python3[ \t]+-c[ \t]+(["'])import PIL; print\(PIL\.__version__\)\1$/.test(e.trim()))return[action("check_rendering")];if(/[$`\\(){}<>]/.test(e))return t;const n=/"[^"\n]*"|'[^'\n]*'|&&|\|\||[;|\n]|[^\s"';|&]+/g,s=[],i=[];let r=[],a=0,c="";for(const o of e.matchAll(n)){const n=e.slice(a,o.index);if(n.trim())return t;const l=o[0],h=[";","|","&&","||","\n"].includes(l);if(!h&&r.length>0&&0===n.length)return t;if(a=o.index+l.length,h){if(!r.length)return t;s.push(r),i.push(c),r=[],c=l}else r.push(l.startsWith('"')||l.startsWith("'")?l.slice(1,-1):l)}if(e.slice(a).trim()||!r.length&&["&&","||","|"].includes(c))return t;r.length&&(s.push(r),i.push(c));const o=[],l=new Set(["rsvg-convert","inkscape","chromium","chromium-browser","google-chrome","convert","magick","python3"]);let h=!1;for(const[e,n]of s.entries()){const s=h&&"|"===i[e];h=!1;const[r,...a]=n,c=r.replace(/^\/(?:usr\/(?:local\/)?)?bin\/([A-Za-z0-9_.-]+)$/,"$1");let u;if("echo"!==c||1!==a.length||!["---","DONE"].includes(a[0])){if("which"===c&&a.length>0&&a.every(e=>l.has(e))||"command"===c&&2===a.length&&"-v"===a[0]&&l.has(a[1])||"convert"===c&&1===a.length&&"-version"===a[0])u=action("check_rendering");else if("google-chrome"===c&&chromeScreenshot(a))u=action("generate_image",filename(a.find(e=>e.startsWith("--screenshot=")).slice(13)));else if("identify"===c&&1===a.length&&/^(?:[A-Za-z0-9_./-]+\/)?[A-Za-z0-9_-][A-Za-z0-9_.-]*\.(?:png|jpe?g|webp|gif)$/.test(a[0]))u=action("read",filename(a[0]));else if("fc-list"===c&&(0===a.length||":lang=zh"===a[0]&&a.slice(1).every(e=>["family","style","fullname"].includes(e))))u=action(0===a.length?"list_fonts":"list_chinese_fonts"),h=!0;else{if("sort"===c&&s&&1===a.length&&"-u"===a[0]){h=!0;continue}if("ls"===c&&a.filter(e=>!e.startsWith("-")).length<=1&&a.every(e=>!e.startsWith("-")||/^-[lah]+$/.test(e)))u=action("list_files");else{if("head"===c&&1===a.length&&/^-\d+$/.test(a[0])&&o.length>0&&"|"===i[e]){h=s;continue}{const e="python3"===c&&"-m"===a[0]&&"pip"===a[1]?["pip",...a.slice(2)]:"uv"===c&&"pip"===a[0]?a:[c,...a];if("pip"!==e[0]&&"pip3"!==e[0]||"install"!==e[1]){if(!["python","python3","node"].includes(c)||1!==a.length||!/^(?:[A-Za-z0-9_./-]+\/)?[A-Za-z0-9_-][A-Za-z0-9_.-]*\.(?:py|js|mjs)$/.test(a[0]))return t;u=action("run_script",filename(a[0]))}else{const n=e.slice(2).filter(e=>!["--quiet","-q","--upgrade","-U","--user","--no-cache-dir"].includes(e));if(!n.length||n.length>6||n.some(e=>!/^[A-Za-z0-9][A-Za-z0-9_.-]{0,79}(?:==[A-Za-z0-9_.-]{1,40})?$/.test(e)))return t;u=action("install",n.join(", "))}}}}o.some(e=>e.kind===u.kind&&e.subject===u.subject)||o.push(u)}}return o.length?o:t}function chromeScreenshot(e){const t=e.map(e=>e.startsWith("--")?e.split("=",1)[0]:"input");return new Set(t).size===t.length&&e.includes("--headless=new")&&t.includes("--screenshot")&&t.includes("input")&&e.every(e=>["--headless=new","--no-sandbox","--disable-gpu","--hide-scrollbars"].includes(e)||/^--force-device-scale-factor=[1-4]$/.test(e)||/^--window-size=[1-9]\d{0,3},[1-9]\d{0,3}$/.test(e)||/^--screenshot=(?:[A-Za-z0-9_./-]+\/)?[A-Za-z0-9_-][A-Za-z0-9_.-]*\.png$/.test(e)||/^file:\/\/\/[A-Za-z0-9_./-]+\.(?:html?|svg)$/.test(e))}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beeos-claw",
3
- "version": "0.6.75",
3
+ "version": "0.6.77",
4
4
  "description": "OpenClaw plugin that bridges the BeeOS platform with the local OpenClaw Gateway, providing file transfer, ACP bridge, and observability.",
5
5
  "license": "MIT",
6
6
  "author": "BeeOS <dev@beeos.ai>",
@@ -90,5 +90,5 @@
90
90
  "brace-expansion": ">=5.0.9",
91
91
  "@beeos-ai/beeos-types": "$@beeos-ai/beeos-types"
92
92
  },
93
- "gitHead": "8a30ad4aa510b0ed608942881b4a9c3cd5ed2285"
93
+ "gitHead": "45758143fa5519799914af01e95fe2566727e3ca"
94
94
  }