beeos-claw 0.5.34 → 0.5.35

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{findLocalHistoryEntryByMessageId}from"./local-session-history.js";import{buildToolCallPayload}from"./tool-call-payload-builder.js";import{emitNormalizedToolResultForTurn}from"./tool-result-emitter.js";import{stripTransportMetadata}from"../message-filter.js";export function reconcileMissingArtifacts(t,e){const{session:s,turnId:n,messageId:o,runId:i}=e;s.agentId&&(s.hasAgentAssistantStream&&s.hasAgentThinkingStream&&s.hasAgentToolStartStream&&s.hasAgentToolResultStream||setImmediate(()=>{(async()=>{if(t.isSessionAlive(s.sessionId))try{const e=t.localHistory.readEntries({agentId:s.agentId,sessionKey:s.gatewaySessionKey,sessionId:s.sessionId}),r=findLocalHistoryEntryByMessageId(e,o);if(!r)return;const a=Array.isArray(r.content)?r.content:[];if(0===a.length)return;const l="number"==typeof r.timestamp?new Date(r.timestamp).toISOString():"string"==typeof r.timestamp?r.timestamp:void 0;let c=0;const d=e=>{void 0===e._turnId&&(e._turnId=n),t.transport.sendSessionUpdate(s.sessionId,e,{turnId:n})&&(c+=1)};for(const e of a){if(!isRecord(e))continue;const o=asString(e.type);if(o){if("text"===o&&!s.hasAgentAssistantStream){const t=asString(e.text);if(!t)continue;const s=stripTransportMetadata(t);if(!s)continue;d({sessionUpdate:"agent_message_chunk",content:{type:"text",text:s},...l?{timestamp:l}:{}});continue}if("thinking"===o&&!s.hasAgentThinkingStream){const t=asString(e.thinking)??asString(e.text);if(!t)continue;d({sessionUpdate:"agent_thought_chunk",content:{type:"text",text:t},...l?{timestamp:l}:{}});continue}if("toolCall"===o&&!s.hasAgentToolStartStream){const t=resolveToolCallId(e),s=asString(e.name)??asString(e.toolName)??asString(e.tool_name)??"tool",n=resolveToolArgs(e);d(buildToolCallPayload({toolCallId:t,toolName:s,args:n,timestamp:l}));continue}if("toolResult"===o&&!s.hasAgentToolResultStream){const o=resolveToolCallId(e),i=asString(e.name)??asString(e.toolName)??asString(e.tool_name)??"tool",r=e.result,a=asString(e.text)??asString(e.result)??(isRecord(r)||Array.isArray(r)?JSON.stringify(r,null,2):void 0);if(!a)continue;await emitNormalizedToolResultForTurn({session:s,envelope:{toolCallId:o,toolName:i,rawText:a,rawResult:r,...l?{timestamp:l}:{}},turnId:n,config:t.config,logger:t.logger,writeObs:t.writeObs,getCanvasState:t.getCanvasState,sendUpdate:t=>(d(t),!0)});continue}}}c>0&&(t.logger.info?.(`[missing-artifacts] reconciled ${c} block(s) sessionId=${s.sessionId} runId=${i??"n/a"} messageId=${o}`),t.writeObs({component:"bridge-core",domain:"lifecycle",name:"reconcile.missing_artifacts.emitted",severity:"info",payload:{sessionId:s.sessionId,runId:i,messageId:o,emitted:c}}))}catch(e){t.logger.warn?.(`[missing-artifacts] reconcile failed sessionId=${s.sessionId} messageId=${o}: ${e instanceof Error?e.message:String(e)}`),t.writeObs({component:"bridge-core",domain:"lifecycle",name:"reconcile.missing_artifacts.failed",severity:"warn",payload:{sessionId:s.sessionId,messageId:o,error:e instanceof Error?e.message:String(e)}})}else t.writeObs({component:"bridge-core",domain:"lifecycle",name:"reconcile.missing_artifacts.skipped_stale",severity:"debug",payload:{sessionId:s.sessionId,messageId:o,runId:i}})})()}))}function isRecord(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function asString(t){if("string"==typeof t&&t.length>0)return t}function resolveToolCallId(t){const e=asString(t.toolCallId)??asString(t.tool_call_id)??asString(t.id);return e||`reconcile_${hashStable(JSON.stringify(t))}`}function resolveToolArgs(t){const e=[t.arguments,t.args,t.input];for(const t of e){if(isRecord(t))return t;if("string"==typeof t)try{const e=JSON.parse(t);if(isRecord(e))return e}catch{}}return{}}function hashStable(t){let e=5381;for(let s=0;s<t.length;s++)e=(e<<5)+e+t.charCodeAt(s)|0;return(e>>>0).toString(16)}
1
+ import{findLocalHistoryEntryByMessageId}from"./local-session-history.js";import{recordToolCallTurnForUpdate}from"./gateway-events.js";import{buildToolCallPayload}from"./tool-call-payload-builder.js";import{emitNormalizedToolResultForTurn}from"./tool-result-emitter.js";import{extractPersistedToolResultEnvelope}from"./persisted-tool-result-envelope.js";import{stripTransportMetadata}from"../message-filter.js";export function reconcileMissingArtifacts(t,e){const{session:o,turnId:s,messageId:n,runId:r}=e;if(!o.agentId)return;const i=(o.toolCallTurns?.size??0)>0;o.hasAgentAssistantStream&&o.hasAgentThinkingStream&&o.hasAgentToolStartStream&&o.hasAgentToolResultStream&&!i||setImmediate(()=>{(async()=>{if(t.isSessionAlive(o.sessionId))try{const e=t.localHistory.readEntries({agentId:o.agentId,sessionKey:o.gatewaySessionKey,sessionId:o.sessionId}),i=findLocalHistoryEntryByMessageId(e,n);if(!i)return;const a=findLocalHistoryEntryIndexByMessageId(e,n),l=Array.isArray(i.content)?i.content:[];if(0===l.length)return;const c="number"==typeof i.timestamp?new Date(i.timestamp).toISOString():"string"==typeof i.timestamp?i.timestamp:void 0;let d=0;const m=e=>{void 0===e._turnId&&(e._turnId=s),t.transport.sendSessionUpdate(o.sessionId,e,{turnId:s})&&(d+=1)};for(const e of l){if(!isRecord(e))continue;const n=asString(e.type);if(n){if("text"===n&&!o.hasAgentAssistantStream){const t=asString(e.text);if(!t)continue;const o=stripTransportMetadata(t);if(!o)continue;m({sessionUpdate:"agent_message_chunk",content:{type:"text",text:o},...c?{timestamp:c}:{}});continue}if("thinking"===n&&!o.hasAgentThinkingStream){const t=asString(e.thinking)??asString(e.text);if(!t)continue;m({sessionUpdate:"agent_thought_chunk",content:{type:"text",text:t},...c?{timestamp:c}:{}});continue}if("toolCall"===n&&!o.hasAgentToolStartStream){const t=resolveToolCallId(e),n=asString(e.name)??asString(e.toolName)??asString(e.tool_name)??"tool",r=resolveToolArgs(e),i=buildToolCallPayload({toolCallId:t,toolName:n,args:r,timestamp:c});recordToolCallTurnForUpdate(o,i,s),m(i);continue}if("toolResult"===n&&!o.hasAgentToolResultStream){const n=resolveToolCallId(e),r=asString(e.name)??asString(e.toolName)??asString(e.tool_name)??"tool",i=e.result,a=asString(e.text)??asString(e.result)??(isRecord(i)||Array.isArray(i)?JSON.stringify(i,null,2):void 0);if(!a)continue;await emitNormalizedToolResultForTurn({session:o,envelope:{toolCallId:n,toolName:r,rawText:a,rawResult:i,...c?{timestamp:c}:{}},turnId:s,config:t.config,logger:t.logger,writeObs:t.writeObs,getCanvasState:t.getCanvasState,sendUpdate:t=>(m(t),!0)});continue}}}await reconcilePersistedToolResultsInTurn({deps:t,session:o,turnId:s,entries:e,currentIndex:a,timestamp:c,emit:m}),d>0&&(t.logger.info?.(`[missing-artifacts] reconciled ${d} block(s) sessionId=${o.sessionId} runId=${r??"n/a"} messageId=${n}`),t.writeObs({component:"bridge-core",domain:"lifecycle",name:"reconcile.missing_artifacts.emitted",severity:"info",payload:{sessionId:o.sessionId,runId:r,messageId:n,emitted:d}}))}catch(e){t.logger.warn?.(`[missing-artifacts] reconcile failed sessionId=${o.sessionId} messageId=${n}: ${e instanceof Error?e.message:String(e)}`),t.writeObs({component:"bridge-core",domain:"lifecycle",name:"reconcile.missing_artifacts.failed",severity:"warn",payload:{sessionId:o.sessionId,messageId:n,error:e instanceof Error?e.message:String(e)}})}else t.writeObs({component:"bridge-core",domain:"lifecycle",name:"reconcile.missing_artifacts.skipped_stale",severity:"debug",payload:{sessionId:o.sessionId,messageId:n,runId:r}})})()})}async function reconcilePersistedToolResultsInTurn(t){const{deps:e,session:o,turnId:s,entries:n,currentIndex:r,timestamp:i,emit:a}=t;if(r<0)return 0;const l=findCurrentUserTurnStart(n,r),c=n.slice(l,r+1);recordToolCallsFromTurnWindow(o,s,c);let d=0;for(const t of c){const n=t.role;if("toolResult"!==n&&"tool"!==n)continue;const r=extractPersistedToolResultEnvelope(t);if(!r?.toolCallId)continue;const l=o.toolCallTurns?.get(r.toolCallId);if(l?.turnId!==s)continue;const c=d;await emitNormalizedToolResultForTurn({session:o,envelope:{toolCallId:r.toolCallId,toolName:r.toolName||l.toolName||"tool",...r.rawText?{rawText:r.rawText}:{},...r.rawResult?{rawResult:r.rawResult}:{},...r.timestamp??i?{timestamp:r.timestamp??i}:{}},turnId:s,config:e.config,logger:e.logger,writeObs:e.writeObs,getCanvasState:e.getCanvasState,sendUpdate:t=>(a(t),d+=1,!0)}),d>c&&e.writeObs({component:"bridge-core",domain:"lifecycle",name:"reconcile.persisted_tool_result.emitted",severity:"info",payload:{sessionId:o.sessionId,toolCallId:r.toolCallId,toolName:r.toolName,emitted:d-c}})}return d}function findCurrentUserTurnStart(t,e){for(let o=e;o>=0;o--){const e=t[o]?.role;if("user"===e)return o+1}return 0}function recordToolCallsFromTurnWindow(t,e,o){for(const s of o){if("assistant"!==s.role)continue;const o=Array.isArray(s.content)?s.content:[];for(const s of o){if(!isRecord(s))continue;if("toolCall"!==asString(s.type))continue;const o=resolveToolCallId(s),n=asString(s.name)??asString(s.toolName)??asString(s.tool_name)??"tool";t.toolCallTurns??=new Map,t.toolCallTurns.has(o)||t.toolCallTurns.set(o,{turnId:e,toolName:n})}}}function findLocalHistoryEntryIndexByMessageId(t,e){for(let o=t.length-1;o>=0;o--){const s=t[o];if(!s)continue;const n=s.__openclaw;if(isRecord(n)&&n.id===e)return o;if(s.id===e)return o}return-1}function isRecord(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function asString(t){if("string"==typeof t&&t.length>0)return t}function resolveToolCallId(t){const e=asString(t.toolCallId)??asString(t.tool_call_id)??asString(t.id);return e||`reconcile_${hashStable(JSON.stringify(t))}`}function resolveToolArgs(t){const e=[t.arguments,t.args,t.input];for(const t of e){if(isRecord(t))return t;if("string"==typeof t)try{const e=JSON.parse(t);if(isRecord(e))return e}catch{}}return{}}function hashStable(t){let e=5381;for(let o=0;o<t.length;o++)e=(e<<5)+e+t.charCodeAt(o)|0;return(e>>>0).toString(16)}
@@ -1 +1 @@
1
- import{describe,it,expect,vi}from"vitest";import{reconcileMissingArtifacts}from"./missing-artifacts-reconciler.js";function makeLogger(){return{info:vi.fn(),warn:vi.fn(),debug:vi.fn(),error:vi.fn()}}describe("reconcileMissingArtifacts — stale guard",()=>{it("skips dispatch when isSessionAlive returns false",async()=>{const e=vi.fn(),t=vi.fn(),n=vi.fn(),s=makeLogger(),i={sessionId:"s-stale",gatewaySessionKey:"agent:main:s1",agentId:"main",createdAt:Date.now(),chatReplayDedupKeys:new Set};reconcileMissingArtifacts({localHistory:{readEntries:e},transport:{sendSessionUpdate:t},config:{},logger:s,writeObs:n,isSessionAlive:()=>!1},{session:i,turnId:"turn-1",messageId:"msg-1",runId:"run-1"}),await new Promise(e=>setImmediate(e)),expect(t).not.toHaveBeenCalled(),expect(e).not.toHaveBeenCalled(),expect(n).toHaveBeenCalledWith(expect.objectContaining({name:"reconcile.missing_artifacts.skipped_stale",payload:expect.objectContaining({sessionId:"s-stale",messageId:"msg-1",runId:"run-1"})}))}),it("fast-paths (no setImmediate) when every stream flag is set",async()=>{const e=vi.fn(()=>!0),t=vi.fn(),n=vi.fn(),s=vi.fn(),i={sessionId:"s-fast",gatewaySessionKey:"agent:main:s1",agentId:"main",createdAt:Date.now(),chatReplayDedupKeys:new Set,hasAgentAssistantStream:!0,hasAgentThinkingStream:!0,hasAgentToolStartStream:!0,hasAgentToolResultStream:!0};reconcileMissingArtifacts({localHistory:{readEntries:t},transport:{sendSessionUpdate:n},config:{},logger:makeLogger(),writeObs:s,isSessionAlive:e},{session:i,turnId:"turn-1",messageId:"msg-1",runId:"run-1"}),await new Promise(e=>setImmediate(e)),expect(e).not.toHaveBeenCalled(),expect(t).not.toHaveBeenCalled(),expect(n).not.toHaveBeenCalled(),expect(s).not.toHaveBeenCalled()}),it("bails out synchronously when agentId is missing",async()=>{const e=vi.fn(()=>!0),t=vi.fn(),n=vi.fn(),s=vi.fn(),i={sessionId:"s-no-agent",gatewaySessionKey:"agent:main:s1",agentId:"",createdAt:Date.now(),chatReplayDedupKeys:new Set};reconcileMissingArtifacts({localHistory:{readEntries:t},transport:{sendSessionUpdate:n},config:{},logger:makeLogger(),writeObs:s,isSessionAlive:e},{session:i,turnId:"turn-1",messageId:"msg-1",runId:"run-1"}),await new Promise(e=>setImmediate(e)),expect(e).not.toHaveBeenCalled(),expect(t).not.toHaveBeenCalled(),expect(n).not.toHaveBeenCalled()}),it("reconciles persisted tool result resource links through the shared normalizer",async()=>{const e=vi.fn().mockReturnValue([{__openclaw:{id:"msg-1"},timestamp:"2026-07-02T14:15:22.658Z",content:[{type:"toolResult",id:"tc-1",name:"beeos_get_task",text:JSON.stringify({content:JSON.stringify({status:"completed",result:"beeos-file://file-1",files:[{uri:"beeos-file://file-1",name:"screenshot.jpeg",mimeType:"image/jpeg"}]})})}]}]),t=vi.fn().mockReturnValue(!0),n=vi.fn(),s={sessionId:"s-artifact",gatewaySessionKey:"agent:main:s1",agentId:"main",createdAt:Date.now(),chatReplayDedupKeys:new Set};reconcileMissingArtifacts({localHistory:{readEntries:e},transport:{sendSessionUpdate:t},config:{},logger:makeLogger(),writeObs:n,isSessionAlive:()=>!0},{session:s,turnId:"turn-1",messageId:"msg-1",runId:"run-1"}),await new Promise(e=>setImmediate(e)),await Promise.resolve();const i=t.mock.calls.map(e=>e[1]);expect(i).toContainEqual(expect.objectContaining({sessionUpdate:"tool_call_update",toolCallId:"tc-1",name:"beeos_get_task",content:expect.arrayContaining([{type:"content",content:{type:"resource_link",uri:"beeos-file://file-1",name:"screenshot.jpeg",mimeType:"image/jpeg"}}])})),expect(n).toHaveBeenCalledWith(expect.objectContaining({name:"reconcile.missing_artifacts.emitted",payload:expect.objectContaining({emitted:2})}))})});
1
+ import{describe,it,expect,vi}from"vitest";import{reconcileMissingArtifacts}from"./missing-artifacts-reconciler.js";function makeLogger(){return{info:vi.fn(),warn:vi.fn(),debug:vi.fn(),error:vi.fn()}}async function flushReconciler(){await new Promise(e=>setImmediate(e)),await Promise.resolve(),await Promise.resolve()}describe("reconcileMissingArtifacts — stale guard",()=>{it("skips dispatch when isSessionAlive returns false",async()=>{const e=vi.fn(),t=vi.fn(),s=vi.fn(),n=makeLogger(),a={sessionId:"s-stale",gatewaySessionKey:"agent:main:s1",agentId:"main",createdAt:Date.now(),chatReplayDedupKeys:new Set};reconcileMissingArtifacts({localHistory:{readEntries:e},transport:{sendSessionUpdate:t},config:{},logger:n,writeObs:s,isSessionAlive:()=>!1},{session:a,turnId:"turn-1",messageId:"msg-1",runId:"run-1"}),await flushReconciler(),expect(t).not.toHaveBeenCalled(),expect(e).not.toHaveBeenCalled(),expect(s).toHaveBeenCalledWith(expect.objectContaining({name:"reconcile.missing_artifacts.skipped_stale",payload:expect.objectContaining({sessionId:"s-stale",messageId:"msg-1",runId:"run-1"})}))}),it("fast-paths (no setImmediate) when every stream flag is set",async()=>{const e=vi.fn(()=>!0),t=vi.fn(),s=vi.fn(),n=vi.fn(),a={sessionId:"s-fast",gatewaySessionKey:"agent:main:s1",agentId:"main",createdAt:Date.now(),chatReplayDedupKeys:new Set,hasAgentAssistantStream:!0,hasAgentThinkingStream:!0,hasAgentToolStartStream:!0,hasAgentToolResultStream:!0};reconcileMissingArtifacts({localHistory:{readEntries:t},transport:{sendSessionUpdate:s},config:{},logger:makeLogger(),writeObs:n,isSessionAlive:e},{session:a,turnId:"turn-1",messageId:"msg-1",runId:"run-1"}),await flushReconciler(),expect(e).not.toHaveBeenCalled(),expect(t).not.toHaveBeenCalled(),expect(s).not.toHaveBeenCalled(),expect(n).not.toHaveBeenCalled()}),it("bails out synchronously when agentId is missing",async()=>{const e=vi.fn(()=>!0),t=vi.fn(),s=vi.fn(),n=vi.fn(),a={sessionId:"s-no-agent",gatewaySessionKey:"agent:main:s1",agentId:"",createdAt:Date.now(),chatReplayDedupKeys:new Set};reconcileMissingArtifacts({localHistory:{readEntries:t},transport:{sendSessionUpdate:s},config:{},logger:makeLogger(),writeObs:n,isSessionAlive:e},{session:a,turnId:"turn-1",messageId:"msg-1",runId:"run-1"}),await flushReconciler(),expect(e).not.toHaveBeenCalled(),expect(t).not.toHaveBeenCalled(),expect(s).not.toHaveBeenCalled()}),it("reconciles persisted tool result resource links through the shared normalizer",async()=>{const e=vi.fn().mockReturnValue([{__openclaw:{id:"msg-1"},timestamp:"2026-07-02T14:15:22.658Z",content:[{type:"toolResult",id:"tc-1",name:"beeos_get_task",text:JSON.stringify({content:JSON.stringify({status:"completed",result:"beeos-file://file-1",files:[{uri:"beeos-file://file-1",name:"screenshot.jpeg",mimeType:"image/jpeg"}]})})}]}]),t=vi.fn().mockReturnValue(!0),s=vi.fn(),n={sessionId:"s-artifact",gatewaySessionKey:"agent:main:s1",agentId:"main",createdAt:Date.now(),chatReplayDedupKeys:new Set};reconcileMissingArtifacts({localHistory:{readEntries:e},transport:{sendSessionUpdate:t},config:{},logger:makeLogger(),writeObs:s,isSessionAlive:()=>!0},{session:n,turnId:"turn-1",messageId:"msg-1",runId:"run-1"}),await flushReconciler();const a=t.mock.calls.map(e=>e[1]);expect(a).toContainEqual(expect.objectContaining({sessionUpdate:"tool_call_update",toolCallId:"tc-1",name:"beeos_get_task",content:expect.arrayContaining([{type:"content",content:{type:"resource_link",uri:"beeos-file://file-1",name:"screenshot.jpeg",mimeType:"image/jpeg"}}])})),expect(s).toHaveBeenCalledWith(expect.objectContaining({name:"reconcile.missing_artifacts.emitted",payload:expect.objectContaining({emitted:2})}))}),it("reconciles production persisted role=toolResult files from the current turn window",async()=>{const e={status:"completed",is_terminal:!0,task_id:"task-1",result:"beeos-file://file-1",files:[{uri:"beeos-file://file-1",name:"device-screenshots/screenshot.jpeg",mimeType:"image/jpeg"}]},t=vi.fn().mockReturnValue([{__openclaw:{id:"user-1"},role:"user",timestamp:"2026-07-02T18:02:44.475Z",content:[{type:"text",text:"@device /screenshot"}]},{__openclaw:{id:"assistant-call-agent"},role:"assistant",timestamp:"2026-07-02T18:02:50.607Z",content:[{type:"toolCall",id:"tc-call-agent",name:"beeos_call_agent",arguments:{agentId:"device",message:"/screenshot"}}]},{__openclaw:{id:"tool-result-call-agent"},role:"toolResult",timestamp:"2026-07-02T18:02:51.036Z",toolCallId:"tc-call-agent",toolName:"beeos_call_agent",content:[{type:"text",text:JSON.stringify({content:JSON.stringify({status:"working",task_id:"task-1"})})}],details:{content:JSON.stringify({status:"working",task_id:"task-1"})}},{__openclaw:{id:"assistant-get-task"},role:"assistant",timestamp:"2026-07-02T18:02:56.660Z",content:[{type:"toolCall",id:"tc-get-task",name:"beeos_get_task",arguments:{taskId:"task-1",agentId:"device"}}]},{__openclaw:{id:"tool-result-get-task"},role:"toolResult",timestamp:"2026-07-02T18:02:57.046Z",toolCallId:"tc-get-task",toolName:"beeos_get_task",content:[{type:"text",text:JSON.stringify({content:JSON.stringify(e)})}],details:{content:JSON.stringify(e)}},{__openclaw:{id:"assistant-final"},role:"assistant",timestamp:"2026-07-02T18:03:01.926Z",content:[{type:"text",text:"Done! Screenshot captured."}]}]),s=vi.fn().mockReturnValue(!0),n=vi.fn(),a={sessionId:"s-production",gatewaySessionKey:"agent:main:s1",agentId:"main",createdAt:Date.now(),chatReplayDedupKeys:new Set};reconcileMissingArtifacts({localHistory:{readEntries:t},transport:{sendSessionUpdate:s},config:{},logger:makeLogger(),writeObs:n,isSessionAlive:()=>!0},{session:a,turnId:"turn-1",messageId:"assistant-final",runId:"run-1"}),await flushReconciler(),expect(a.toolCallTurns?.get("tc-get-task")).toEqual({turnId:"turn-1",toolName:"beeos_get_task"});const i=s.mock.calls.map(e=>e[1]);expect(i).toContainEqual(expect.objectContaining({sessionUpdate:"tool_call_update",toolCallId:"tc-get-task",name:"beeos_get_task",content:expect.arrayContaining([{type:"content",content:{type:"resource_link",uri:"beeos-file://file-1",name:"device-screenshots/screenshot.jpeg",mimeType:"image/jpeg"}}])})),expect(i).toContainEqual(expect.objectContaining({sessionUpdate:"agent_message_chunk",content:{type:"resource_link",uri:"beeos-file://file-1",name:"device-screenshots/screenshot.jpeg",mimeType:"image/jpeg"}})),expect(n).toHaveBeenCalledWith(expect.objectContaining({name:"reconcile.persisted_tool_result.emitted",payload:expect.objectContaining({sessionId:"s-production",toolCallId:"tc-get-task",toolName:"beeos_get_task"})}))}),it("does not infer a persisted text-only beeos-file URI as a resource link",async()=>{const e=vi.fn().mockReturnValue([{__openclaw:{id:"user-1"},role:"user",content:[{type:"text",text:"@device /screenshot"}]},{__openclaw:{id:"assistant-get-task"},role:"assistant",content:[{type:"toolCall",id:"tc-get-task",name:"beeos_get_task",arguments:{taskId:"task-1",agentId:"device"}}]},{__openclaw:{id:"tool-result-get-task"},role:"toolResult",toolCallId:"tc-get-task",toolName:"beeos_get_task",content:[{type:"text",text:"beeos-file://file-1"}],details:{content:"beeos-file://file-1"}},{__openclaw:{id:"assistant-final"},role:"assistant",content:[{type:"text",text:"Done."}]}]),t=vi.fn().mockReturnValue(!0),s={sessionId:"s-text-only",gatewaySessionKey:"agent:main:s1",agentId:"main",createdAt:Date.now(),chatReplayDedupKeys:new Set};reconcileMissingArtifacts({localHistory:{readEntries:e},transport:{sendSessionUpdate:t},config:{},logger:makeLogger(),writeObs:vi.fn(),isSessionAlive:()=>!0},{session:s,turnId:"turn-1",messageId:"assistant-final",runId:"run-1"}),await flushReconciler();const n=t.mock.calls.map(e=>e[1]).filter(e=>{const t=e.content;return JSON.stringify(t).includes('"resource_link"')});expect(n).toEqual([])})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beeos-claw",
3
- "version": "0.5.34",
3
+ "version": "0.5.35",
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>",