beeos-claw 0.6.44-staging.1 → 0.6.44-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
import{toMessagePart}from"../message-client-types.js";import{extractUploadResourceLinks}from"../upload/extract-upload-uris.js";import{readLatestUploadToolResult,readUploadToolResult}from"../upload/result-cache.js";import{BEEOS_UPLOAD_TOOL_NAME}from"../upload/tool.js";import{resolveRuntimeToolArguments,resolveRuntimeToolCallId,resolveRuntimeToolName}from"./tool-envelope-metadata.js";const isNonEmptyString=e=>"string"==typeof e&&e.length>0,extractBodyUpdate=(e,t)=>{if(!isNonEmptyString(t))return{kind:"noop"};if(t===e.text)return{kind:"noop"};if(t.startsWith(e.text)){const r=t.slice(e.text.length);return e.text=t,{kind:"append",text:r}}return e.text.startsWith(t)?{kind:"noop"}:(e.text=t,{kind:"replace",text:t})};export function createImReplySink(e){const t={text:""};let r,n="",o="";const s=new Map,a=new Map,i=[],l=[];let d=0,u=0;const m=new Set,g=(t,r,n)=>{const o=u;return e.stream.appendToolUse(t,r,toMessagePart(n),"streaming"),u+=1,o},c=()=>(d+=1,`tool_${e.requestId}_${d}`),p=e=>{const t=i.indexOf(e);t>=0&&i.splice(t,1)},f=e=>{const t=e?i.filter(t=>s.get(t)?.name===e):i;return 1===t.length?t[0]:void 0},I=e=>{const t=l.map((e,t)=>({hint:e,index:t})).filter(({hint:t})=>!e||t.name===e);if(1!==t.length)return;const[{hint:r,index:n}]=t;return l.splice(n,1),r},h=(e,t)=>{a.set(e,t)},y=e=>a.get(e)??e,$=e=>null!=e&&("object"!=typeof e||(Array.isArray(e)?e.length>0:Object.keys(e).length>0)),v=(t,r,n,o)=>{const a=s.get(t);if(a){const s="tool"===a.name&&"tool"!==r?r:a.name,l=!$(a.arguments)&&$(n)?n:a.arguments;return s===a.name&&l===a.arguments||(e.stream.replacePart(a.partIndex,toMessagePart({type:"tool_use",id:a.id,name:s,arguments:l,state:a.state})),a.name=s,a.arguments=l),o&&!i.includes(t)&&"streaming"===a.state&&i.push(t),a}const l={id:t,name:r,arguments:n,partIndex:g(t,r,n),state:"streaming",itemEventObserved:!1,toolStartObserved:!1};return s.set(t,l),o&&i.push(t),l},b=t=>{"done"!==t.state&&(e.stream.replacePart(t.partIndex,toMessagePart({type:"tool_use",id:t.id,name:t.name,arguments:t.arguments,state:"done"})),t.state="done")},_=e=>{if(null===e||"object"!=typeof e)return JSON.stringify(e)??String(e);if(Array.isArray(e))return`[${e.map(_).join(",")}]`;return`{${Object.entries(e).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${JSON.stringify(e)}:${_(t)}`).join(",")}}`},k=(t,r,n)=>{const o=`${n?"1":"0"}:${_(r)}`;if(t.progressSignature===o)return;const s=toMessagePart({type:"custom",kind:"tool_progress",data:{tool_use_id:t.id,content:r,...n?{is_error:!0}:{}}});if(void 0===t.progressPartIndex){const r=u;return e.stream.addPart(s),t.progressPartIndex=r,t.progressSignature=o,void(u+=1)}e.stream.replacePart(t.progressPartIndex,s),t.progressSignature=o},x=e=>[e.mediaUrl,...e.mediaUrls??[]].filter(e=>isNonEmptyString(e)),S=(e,t=[])=>{const r=[...new Set([...x(e),...t])];return isNonEmptyString(e.text)&&r.length>0?{text:e.text,media_urls:r}:isNonEmptyString(e.text)?e.text:1===r.length?r[0]:r.length>1?{media_urls:r}:!0===e.isError?"Tool execution failed.":""},E=(t,r)=>{if(!(e=>{if(!e)return!1;if(e===BEEOS_UPLOAD_TOOL_NAME)return!0;const t=e.toLowerCase();return t.includes("beeos_upload")||t.includes("beeos upload file")||"beeos file upload"===t})(t.name))return;if(t.durableUploadFilesEmitted)return;e.logger.info?.(`[im-sink] schedule upload enrichment requestId=${e.requestId} toolUseId=${t.id} name=${t.name}`);const n=(async()=>{let n;try{n=await readUploadToolResult(t.id)}catch(r){const n=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] readUploadToolResult failed requestId=${e.requestId} toolUseId=${t.id} error=${n}`)}if(null==n)try{n=await readUploadToolResult("latest_beeos_upload_file"),null==n&&(n=await readLatestUploadToolResult(BEEOS_UPLOAD_TOOL_NAME)),null!=n&&e.logger.info?.(`[im-sink] upload cache recovered via latest-result fallback requestId=${e.requestId} toolUseId=${t.id}`)}catch(t){const r=t instanceof Error?t.message:String(t);e.logger.warn?.(`[im-sink] readLatestUploadToolResult failed requestId=${e.requestId} error=${r}`)}null==n&&e.logger.warn?.(`[im-sink] upload cache miss requestId=${e.requestId} toolUseId=${t.id} name=${t.name}`);let o=null!=n?extractUploadResourceLinks(n):[];0===o.length&&(o=x(r).map(e=>({uri:e,name:e.startsWith("beeos-file://")?e.slice(13):"file"}))),0!==o.length?await new Promise(n=>{e.callbackQueue.enqueueSync(()=>{try{if(e.abortSignal.aborted||e.stream.isTerminated)return;const n=o.map(e=>e.uri);k(t,S(r,n),!0===r.isError),((t,r,n)=>{if(0!==r.length&&!t.durableUploadFilesEmitted){t.durableUploadFilesEmitted=!0,e.stream.appendToolResult(t.id,r.map(e=>({type:"resource_link",uri:e.uri,name:e.name,...e.mimeType?{mimeType:e.mimeType}:{}})),n),u+=1;for(const t of r)e.stream.addPart(toMessagePart({type:"resource_link",uri:t.uri,name:t.name,...t.mimeType?{mimeType:t.mimeType}:{}})),u+=1}})(t,o,!0===r.isError)}catch(r){const n=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] upload enrichment apply failed requestId=${e.requestId} toolUseId=${t.id} error=${n}`)}finally{n()}})}):e.logger.warn?.(`[im-sink] upload enrichment found no links requestId=${e.requestId} toolUseId=${t.id}`)})().catch(r=>{const n=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] upload enrichment failed requestId=${e.requestId} toolUseId=${t.id} error=${n}`)});m.add(n),n.finally(()=>{m.delete(n)})},T=(e,t,r)=>{const n=a.get(e);if(n)return v(n,t??"tool",r??{},!1);if(s.has(e))return v(e,t??"tool",r??{},!1);const o=f(t);return o?(h(e,o),v(o,t??"tool",r??{},!1)):v(e,t??"tool",r??{},!1)},q=(e,t)=>{const r=a.get(e);if(r)return v(r,t,{},!1);if(s.has(e))return v(e,t,{},!1);const n=(e=>{const t=i.filter(t=>{const r=s.get(t);return!(void 0===r||e&&r.name!==e||r.itemEventObserved)});return 1===t.length?t[0]:void 0})(t);if(n)return h(e,n),v(n,t,{},!1);const o=I(t);return v(e,t,o?.arguments??{},!1)},R={tool:0,block:0,final:0};let w,U=!1;const O=(t,r)=>{e.callbackQueue.enqueueSync(()=>{if((t=>e.abortSignal.aborted?(e.logger.debug?.(`[im-sink] ${t} ignored after abort requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`),!1):e.stream.isTerminated?(e.logger.debug?.(`[im-sink] ${t} ignored after stream_terminated requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`),!1):!U||(e.logger.debug?.(`[im-sink] ${t} ignored after mark_complete requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`),!1))(t))try{r()}catch(r){const n=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] ${t} mapping failed requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId} error=${n}`)}})};return{dispatcher:{sendToolResult:t=>(O("tool_progress",()=>{const r=resolveRuntimeToolCallId(t),n=resolveRuntimeToolName(t),o=r?void 0:n?f(n):f(),a=r||o?void 0:I(n);if(!r&&!o&&!a)return void e.logger.debug?.(`[im-sink] ambiguous id-less tool progress ignored requestId=${e.requestId} channel=${e.channelId} tool=${n??"unknown"} pending=${i.length}`);const l=r?T(r,n,resolveRuntimeToolArguments(t)):v(o??c(),n??s.get(o??"")?.name??a.name,$(resolveRuntimeToolArguments(t))?resolveRuntimeToolArguments(t):a?.arguments??{},!1);R.tool+=1,k(l,S(t),!0===t.isError),b(l),p(l.id),E(l,t)}),!0),sendBlockReply:r=>(O("block_reply",()=>{R.block+=1,isNonEmptyString(r.text)&&(!0!==r.isError?(w=void 0,e.stream.setBody(r.text),t.text=r.text):w=r.text)}),!0),sendFinalReply:r=>(O("final_reply",()=>{R.final+=1,isNonEmptyString(r.text)&&(!0!==r.isError?(w=void 0,e.stream.setBody(r.text),t.text=r.text):w=r.text)}),!0),waitForIdle:async()=>{for(let t=0;t<16;t++){if(await e.callbackQueue.waitForIdle(),0===m.size)return;await Promise.allSettled([...m])}await e.callbackQueue.waitForIdle()},getQueuedCounts:()=>({...R}),getAccumulatedBody:()=>t.text,getTerminalErrorText:()=>w,markComplete:t=>{if(1===l.length){const e=l.shift();v(c(),e.name,e.arguments,!1)}for(const r of s.values())try{"success"===t&&b(r),p(r.id)}catch(t){const n=t instanceof Error?t.message:String(t);e.logger.warn?.(`[im-sink] tool finalization failed requestId=${e.requestId} toolUseId=${r.id} error=${n}`)}l.length=0,U=!0}},replyOptions:{...e.runId?{runId:e.runId}:{},abortSignal:e.abortSignal,onAgentRunStart:t=>{e.onAgentRunStart?.(t),e.logger.info?.(`[im-sink] run_start requestId=${e.requestId} runId=${t} channel=${e.channelId} in_reply_to=${e.inboundMessageId} origin=${e.origin??"im"}`)},onPartialReply:r=>{O("partial",()=>{const n=extractBodyUpdate(t,r.text);switch(n.kind){case"append":e.stream.appendBody(n.text);break;case"replace":e.stream.setBody(n.text)}})},onReasoningStream:t=>{O("reasoning",()=>{if(!isNonEmptyString(t.text))return;if(!r&&(r=e.openReasoningStream?.(),!r))return;const s=t.text;""===o&&""!==n&&(r.appendBody("\n"),n+="\n"),s!==o&&(s.startsWith(o)?(r.appendBody(s.slice(o.length)),o=s):o.startsWith(s)||(r.setBody(n+s),o=s))})},onReasoningEnd:()=>{O("reasoning_end",()=>{var t;""!==o&&(t=o,e.stream.appendThinking(t,"done"),u+=1,n+=o,o="")})},onAssistantMessageStart:()=>{e.logger.debug?.(`[im-sink] assistant_message_start requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`)},onToolStart:t=>{O("tool_start",()=>{const r="string"==typeof t.phase?t.phase:"start",n=resolveRuntimeToolName(t)??"tool",o=resolveRuntimeToolCallId(t);if("update"===r){if(o){const e=y(o);s.has(e)&&v(e,n,resolveRuntimeToolArguments(t),!0)}return}const a=resolveRuntimeToolArguments(t);if(o){const e=T(o,n,a);return e.toolStartObserved=!0,void(i.includes(e.id)||"streaming"!==e.state||i.push(e.id))}const d=(u=n,i.map(e=>s.get(e)).filter(e=>void 0!==e&&(!u||e.name===u)&&e.itemEventObserved));var u;if(1===d.length){return void(v(d[0].id,n,a,!0).toolStartObserved=!0)}d.length>1?e.logger.debug?.(`[im-sink] ambiguous id-less tool start ignored requestId=${e.requestId} channel=${e.channelId} tool=${n} candidates=${d.length}`):l.push({name:n,arguments:a})})},onItemEvent:e=>{O("item_event",()=>{const t="string"==typeof e.kind?e.kind.toLowerCase():"";if(t&&"tool"!==t)return;const r="string"==typeof e.phase?e.phase.toLowerCase():"update",n=resolveRuntimeToolCallId(e)??("string"==typeof e.itemId&&e.itemId.trim()?e.itemId.trim():void 0),o=resolveRuntimeToolName(e)??("string"==typeof e.title&&e.title.trim()?e.title.trim():void 0);if(!n||!o)return;if("update"===r){const e=y(n),t=s.get(e);return void(t&&(v(t.id,o,{},!0).itemEventObserved=!0))}const a=q(n,o);a.itemEventObserved=!0,i.includes(a.id)||"streaming"!==a.state||i.push(a.id)})}}}}
|
|
1
|
+
import{toMessagePart}from"../message-client-types.js";import{extractUploadResourceLinks}from"../upload/extract-upload-uris.js";import{resolveUploadToolResultForEnrichment}from"../upload/result-cache.js";import{BEEOS_UPLOAD_TOOL_NAME}from"../upload/tool.js";import{resolveRuntimeToolArguments,resolveRuntimeToolCallId,resolveRuntimeToolName}from"./tool-envelope-metadata.js";const isNonEmptyString=e=>"string"==typeof e&&e.length>0,extractBodyUpdate=(e,t)=>{if(!isNonEmptyString(t))return{kind:"noop"};if(t===e.text)return{kind:"noop"};if(t.startsWith(e.text)){const r=t.slice(e.text.length);return e.text=t,{kind:"append",text:r}}return e.text.startsWith(t)?{kind:"noop"}:(e.text=t,{kind:"replace",text:t})};export function createImReplySink(e){const t={text:""};let r,n="",o="";const s=new Map,i=new Map,a=[],l=[];let d=0,u=0;const m=new Set,g=(t,r,n)=>{const o=u;return e.stream.appendToolUse(t,r,toMessagePart(n),"streaming"),u+=1,o},c=()=>(d+=1,`tool_${e.requestId}_${d}`),p=e=>{const t=a.indexOf(e);t>=0&&a.splice(t,1)},f=e=>{const t=e?a.filter(t=>s.get(t)?.name===e):a;return 1===t.length?t[0]:void 0},h=e=>{const t=l.map((e,t)=>({hint:e,index:t})).filter(({hint:t})=>!e||t.name===e);if(1!==t.length)return;const[{hint:r,index:n}]=t;return l.splice(n,1),r},I=(e,t)=>{i.set(e,t)},y=e=>i.get(e)??e,$=e=>null!=e&&("object"!=typeof e||(Array.isArray(e)?e.length>0:Object.keys(e).length>0)),v=(t,r,n,o)=>{const i=s.get(t);if(i){const s="tool"===i.name&&"tool"!==r?r:i.name,l=!$(i.arguments)&&$(n)?n:i.arguments;return s===i.name&&l===i.arguments||(e.stream.replacePart(i.partIndex,toMessagePart({type:"tool_use",id:i.id,name:s,arguments:l,state:i.state})),i.name=s,i.arguments=l),o&&!a.includes(t)&&"streaming"===i.state&&a.push(t),i}const l={id:t,name:r,arguments:n,partIndex:g(t,r,n),state:"streaming",itemEventObserved:!1,toolStartObserved:!1};return s.set(t,l),o&&a.push(t),l},b=t=>{"done"!==t.state&&(e.stream.replacePart(t.partIndex,toMessagePart({type:"tool_use",id:t.id,name:t.name,arguments:t.arguments,state:"done"})),t.state="done")},x=e=>{if(null===e||"object"!=typeof e)return JSON.stringify(e)??String(e);if(Array.isArray(e))return`[${e.map(x).join(",")}]`;return`{${Object.entries(e).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${JSON.stringify(e)}:${x(t)}`).join(",")}}`},k=(t,r,n)=>{const o=`${n?"1":"0"}:${x(r)}`;if(t.progressSignature===o)return;const s=toMessagePart({type:"custom",kind:"tool_progress",data:{tool_use_id:t.id,content:r,...n?{is_error:!0}:{}}});if(void 0===t.progressPartIndex){const r=u;return e.stream.addPart(s),t.progressPartIndex=r,t.progressSignature=o,void(u+=1)}e.stream.replacePart(t.progressPartIndex,s),t.progressSignature=o},_=e=>[e.mediaUrl,...e.mediaUrls??[]].filter(e=>isNonEmptyString(e)),E=(e,t=[])=>{const r=[...new Set([..._(e),...t])];return isNonEmptyString(e.text)&&r.length>0?{text:e.text,media_urls:r}:isNonEmptyString(e.text)?e.text:1===r.length?r[0]:r.length>1?{media_urls:r}:!0===e.isError?"Tool execution failed.":""},S=(t,r)=>{if(!(e=>{if(!e)return!1;if(e===BEEOS_UPLOAD_TOOL_NAME)return!0;const t=e.toLowerCase();return t.includes("beeos_upload")||t.includes("beeos upload file")||"beeos file upload"===t})(t.name))return;if(t.durableUploadFilesEmitted)return;e.logger.info?.(`[im-sink] schedule upload enrichment requestId=${e.requestId} toolUseId=${t.id} name=${t.name}`);const n=(async()=>{let n;try{n=await resolveUploadToolResultForEnrichment(t.id,BEEOS_UPLOAD_TOOL_NAME),null!=n&&e.logger.info?.(`[im-sink] upload cache hit requestId=${e.requestId} toolUseId=${t.id}`)}catch(r){const n=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] resolveUploadToolResultForEnrichment failed requestId=${e.requestId} toolUseId=${t.id} error=${n}`)}null==n&&e.logger.warn?.(`[im-sink] upload cache miss requestId=${e.requestId} toolUseId=${t.id} name=${t.name}`);let o=null!=n?extractUploadResourceLinks(n):[];0===o.length&&(o=_(r).map(e=>({uri:e,name:e.startsWith("beeos-file://")?e.slice(13):"file"}))),0!==o.length?await new Promise(n=>{e.callbackQueue.enqueueSync(()=>{try{if(e.abortSignal.aborted||e.stream.isTerminated)return;const n=o.map(e=>e.uri);k(t,E(r,n),!0===r.isError),((t,r,n)=>{if(0!==r.length&&!t.durableUploadFilesEmitted){t.durableUploadFilesEmitted=!0,e.stream.appendToolResult(t.id,r.map(e=>({type:"resource_link",uri:e.uri,name:e.name,...e.mimeType?{mimeType:e.mimeType}:{}})),n),u+=1;for(const t of r)e.stream.addPart(toMessagePart({type:"resource_link",uri:t.uri,name:t.name,...t.mimeType?{mimeType:t.mimeType}:{}})),u+=1}})(t,o,!0===r.isError)}catch(r){const n=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] upload enrichment apply failed requestId=${e.requestId} toolUseId=${t.id} error=${n}`)}finally{n()}})}):e.logger.warn?.(`[im-sink] upload enrichment found no links requestId=${e.requestId} toolUseId=${t.id}`)})().catch(r=>{const n=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] upload enrichment failed requestId=${e.requestId} toolUseId=${t.id} error=${n}`)});m.add(n),n.finally(()=>{m.delete(n)})},T=(e,t,r)=>{const n=i.get(e);if(n)return v(n,t??"tool",r??{},!1);if(s.has(e))return v(e,t??"tool",r??{},!1);const o=f(t);return o?(I(e,o),v(o,t??"tool",r??{},!1)):v(e,t??"tool",r??{},!1)},q=(e,t)=>{const r=i.get(e);if(r)return v(r,t,{},!1);if(s.has(e))return v(e,t,{},!1);const n=(e=>{const t=a.filter(t=>{const r=s.get(t);return!(void 0===r||e&&r.name!==e||r.itemEventObserved)});return 1===t.length?t[0]:void 0})(t);if(n)return I(e,n),v(n,t,{},!1);const o=h(t);return v(e,t,o?.arguments??{},!1)},R={tool:0,block:0,final:0};let O,w=!1;const U=(t,r)=>{e.callbackQueue.enqueueSync(()=>{if((t=>e.abortSignal.aborted?(e.logger.debug?.(`[im-sink] ${t} ignored after abort requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`),!1):e.stream.isTerminated?(e.logger.debug?.(`[im-sink] ${t} ignored after stream_terminated requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`),!1):!w||(e.logger.debug?.(`[im-sink] ${t} ignored after mark_complete requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`),!1))(t))try{r()}catch(r){const n=r instanceof Error?r.message:String(r);e.logger.warn?.(`[im-sink] ${t} mapping failed requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId} error=${n}`)}})};return{dispatcher:{sendToolResult:t=>(U("tool_progress",()=>{const r=resolveRuntimeToolCallId(t),n=resolveRuntimeToolName(t),o=r?void 0:n?f(n):f(),i=r||o?void 0:h(n);if(!r&&!o&&!i)return void e.logger.debug?.(`[im-sink] ambiguous id-less tool progress ignored requestId=${e.requestId} channel=${e.channelId} tool=${n??"unknown"} pending=${a.length}`);const l=r?T(r,n,resolveRuntimeToolArguments(t)):v(o??c(),n??s.get(o??"")?.name??i.name,$(resolveRuntimeToolArguments(t))?resolveRuntimeToolArguments(t):i?.arguments??{},!1);R.tool+=1,k(l,E(t),!0===t.isError),b(l),p(l.id),S(l,t)}),!0),sendBlockReply:r=>(U("block_reply",()=>{R.block+=1,isNonEmptyString(r.text)&&(!0!==r.isError?(O=void 0,e.stream.setBody(r.text),t.text=r.text):O=r.text)}),!0),sendFinalReply:r=>(U("final_reply",()=>{R.final+=1,isNonEmptyString(r.text)&&(!0!==r.isError?(O=void 0,e.stream.setBody(r.text),t.text=r.text):O=r.text)}),!0),waitForIdle:async()=>{for(let t=0;t<16;t++){if(await e.callbackQueue.waitForIdle(),0===m.size)return;await Promise.allSettled([...m])}await e.callbackQueue.waitForIdle()},getQueuedCounts:()=>({...R}),getAccumulatedBody:()=>t.text,getTerminalErrorText:()=>O,markComplete:t=>{if(1===l.length){const e=l.shift();v(c(),e.name,e.arguments,!1)}for(const r of s.values())try{"success"===t&&b(r),p(r.id)}catch(t){const n=t instanceof Error?t.message:String(t);e.logger.warn?.(`[im-sink] tool finalization failed requestId=${e.requestId} toolUseId=${r.id} error=${n}`)}l.length=0,w=!0}},replyOptions:{...e.runId?{runId:e.runId}:{},abortSignal:e.abortSignal,onAgentRunStart:t=>{e.onAgentRunStart?.(t),e.logger.info?.(`[im-sink] run_start requestId=${e.requestId} runId=${t} channel=${e.channelId} in_reply_to=${e.inboundMessageId} origin=${e.origin??"im"}`)},onPartialReply:r=>{U("partial",()=>{const n=extractBodyUpdate(t,r.text);switch(n.kind){case"append":e.stream.appendBody(n.text);break;case"replace":e.stream.setBody(n.text)}})},onReasoningStream:t=>{U("reasoning",()=>{if(!isNonEmptyString(t.text))return;if(!r&&(r=e.openReasoningStream?.(),!r))return;const s=t.text;""===o&&""!==n&&(r.appendBody("\n"),n+="\n"),s!==o&&(s.startsWith(o)?(r.appendBody(s.slice(o.length)),o=s):o.startsWith(s)||(r.setBody(n+s),o=s))})},onReasoningEnd:()=>{U("reasoning_end",()=>{var t;""!==o&&(t=o,e.stream.appendThinking(t,"done"),u+=1,n+=o,o="")})},onAssistantMessageStart:()=>{e.logger.debug?.(`[im-sink] assistant_message_start requestId=${e.requestId} channel=${e.channelId} in_reply_to=${e.inboundMessageId}`)},onToolStart:t=>{U("tool_start",()=>{const r="string"==typeof t.phase?t.phase:"start",n=resolveRuntimeToolName(t)??"tool",o=resolveRuntimeToolCallId(t);if("update"===r){if(o){const e=y(o);s.has(e)&&v(e,n,resolveRuntimeToolArguments(t),!0)}return}const i=resolveRuntimeToolArguments(t);if(o){const e=T(o,n,i);return e.toolStartObserved=!0,void(a.includes(e.id)||"streaming"!==e.state||a.push(e.id))}const d=(u=n,a.map(e=>s.get(e)).filter(e=>void 0!==e&&(!u||e.name===u)&&e.itemEventObserved));var u;if(1===d.length){return void(v(d[0].id,n,i,!0).toolStartObserved=!0)}d.length>1?e.logger.debug?.(`[im-sink] ambiguous id-less tool start ignored requestId=${e.requestId} channel=${e.channelId} tool=${n} candidates=${d.length}`):l.push({name:n,arguments:i})})},onItemEvent:e=>{U("item_event",()=>{const t="string"==typeof e.kind?e.kind.toLowerCase():"";if(t&&"tool"!==t)return;const r="string"==typeof e.phase?e.phase.toLowerCase():"update",n=resolveRuntimeToolCallId(e)??("string"==typeof e.itemId&&e.itemId.trim()?e.itemId.trim():void 0),o=resolveRuntimeToolName(e)??("string"==typeof e.title&&e.title.trim()?e.title.trim():void 0);if(!n||!o)return;if("update"===r){const e=y(n),t=s.get(e);return void(t&&(v(t.id,o,{},!0).itemEventObserved=!0))}const i=q(n,o);i.itemEventObserved=!0,a.includes(i.id)||"streaming"!==i.state||a.push(i.id)})}}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID}from"node:crypto";import{mkdir,readFile,rename,stat,unlink,readdir}from"node:fs/promises";import{writeFile}from"node:fs/promises";import{homedir}from"node:os";import{join}from"node:path";const CACHE_TTL_MS=864e5,ENRICHMENT_CACHE_TTL_MS=2592e6,ENRICHMENT_PREFIX="enrich_",
|
|
1
|
+
import{randomUUID}from"node:crypto";import{mkdir,readFile,rename,stat,unlink,readdir}from"node:fs/promises";import{writeFile}from"node:fs/promises";import{homedir}from"node:os";import{join}from"node:path";const CACHE_TTL_MS=864e5,ENRICHMENT_CACHE_TTL_MS=2592e6,ENRICHMENT_PREFIX="enrich_",CACHE_VERSION=1;function cacheDir(){return join(process.env.OPENCLAW_HOME||join(homedir(),".openclaw"),"beeos-claw","upload_meta")}function safeToolCallId(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_")}function cachePath(e){return join(cacheDir(),`${safeToolCallId(e)}.json`)}async function safeUnlink(e){try{await unlink(e)}catch{}}export async function writeUploadToolResult(e,t,a){await mkdir(cacheDir(),{recursive:!0,mode:448});const n={version:1,createdAt:Date.now(),toolCallId:e,toolName:t,result:a},r=async e=>{const t=`${e}.${randomUUID()}.tmp`;await writeFile(t,JSON.stringify(n),{encoding:"utf8",mode:384}),await rename(t,e)};await r(cachePath(e)),"beeos_upload_file"===t&&await r(cachePath("latest_beeos_upload_file"))}export async function readUploadToolResult(e){const t=cachePath(e);let a,n,r;try{a=await stat(t)}catch{return}if(Date.now()-a.mtimeMs>=864e5)await safeUnlink(t);else{try{n=await readFile(t,"utf8")}catch{return}try{r=JSON.parse(n)}catch{return void await safeUnlink(t)}if(r&&1===r.version&&"number"==typeof r.createdAt&&!(Date.now()-r.createdAt>=864e5))return r.result;await safeUnlink(t)}}export function uploadCacheIdCandidates(e){const t=e.trim();if(!t)return[];const a=t.startsWith("tool:")?t.slice(5):t,n=[t,a,safeToolCallId(t),safeToolCallId(a)];return[...new Set(n.filter(e=>e.length>0))]}export async function resolveUploadToolResultForEnrichment(e,t="beeos_upload_file",a){const n=Math.max(1,a?.attempts??6),r=Math.max(0,a?.delayMs??40),o=uploadCacheIdCandidates(e);for(let e=0;e<n;e++){for(const e of o){const t=await readUploadToolResult(e);if(null!=t)return t}const a=await readUploadToolResult("latest_beeos_upload_file");if(null!=a)return a;const i=await readLatestUploadToolResult(t);if(null!=i)return i;e+1<n&&r>0&&await new Promise(t=>setTimeout(t,r*(e+1)))}}export async function readLatestUploadToolResult(e,t=12e4){let a;try{a=await readdir(cacheDir())}catch{return}const n=Date.now();let r;for(const o of a){if(!o.endsWith(".json")||o.startsWith("enrich_"))continue;const a=join(cacheDir(),o);let i,c;try{i=await readFile(a,"utf8")}catch{continue}try{c=JSON.parse(i)}catch{continue}!c||1!==c.version||c.toolName!==e||"number"!=typeof c.createdAt||n-c.createdAt>=t||n-c.createdAt>=864e5||(!r||c.createdAt>r.createdAt)&&(r={createdAt:c.createdAt,result:c.result})}return r?.result}function enrichmentCachePath(e){return join(cacheDir(),`enrich_${safeToolCallId(e)}.json`)}export async function writeEnrichmentCache(e,t){if(0===t.length)return;await mkdir(cacheDir(),{recursive:!0,mode:448});const a={version:1,createdAt:Date.now(),toolCallId:e,resourceLinks:t},n=enrichmentCachePath(e),r=`${n}.${randomUUID()}.tmp`;await writeFile(r,JSON.stringify(a),{encoding:"utf8",mode:384}),await rename(r,n)}export async function readEnrichmentCache(e){const t=enrichmentCachePath(e);let a,n,r;try{a=await stat(t)}catch{return}if(Date.now()-a.mtimeMs>=2592e6)await safeUnlink(t);else{try{n=await readFile(t,"utf8")}catch{return}try{r=JSON.parse(n)}catch{return void await safeUnlink(t)}if(r&&1===r.version&&"number"==typeof r.createdAt&&Array.isArray(r.resourceLinks)&&!(Date.now()-r.createdAt>=2592e6))return r.resourceLinks;await safeUnlink(t)}}export async function cleanupUploadToolResultCache(){let e;try{e=await readdir(cacheDir(),{withFileTypes:!0})}catch{return 0}const t=Date.now();let a=0;for(const n of e){if(!n.isFile())continue;if(!n.name.endsWith(".json")&&!n.name.endsWith(".tmp"))continue;const e=join(cacheDir(),n.name),r=n.name.startsWith("enrich_")?2592e6:864e5;try{t-(await stat(e)).mtimeMs>=r&&(await unlink(e),a++)}catch{}}return a}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "beeos-claw",
|
|
3
|
-
"version": "0.6.44-staging.
|
|
3
|
+
"version": "0.6.44-staging.2",
|
|
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>",
|