@@ -3,6 +3,7 @@ import type { AnyAgentTool, OpenClawPluginApi } from "openclaw/plugin-sdk/plugin
33import { createTestPluginApi } from "openclaw/plugin-sdk/plugin-test-api" ;
44import { beforeEach , describe , expect , it , vi } from "vitest" ;
55import canvasPlugin from "./index.js" ;
6+ import { SHOW_WIDGET_REQUIRED_CLIENT_CAPS } from "./src/tool-schema.js" ;
67
78const mocks = vi . hoisted ( ( ) => {
89 const httpHandler = {
@@ -11,6 +12,7 @@ const mocks = vi.hoisted(() => {
1112 close : vi . fn ( async ( ) => { } ) ,
1213 } ;
1314 const toolExecute = vi . fn ( async ( ) => ( { content : [ { type : "text" , text : "ok" } ] } ) ) ;
15+ const widgetToolExecute = vi . fn ( async ( ) => ( { content : [ { type : "text" , text : "widget" } ] } ) ) ;
1416 return {
1517 httpHandler,
1618 createCanvasHttpRouteHandler : vi . fn ( ( ) => httpHandler ) ,
@@ -25,6 +27,14 @@ const mocks = vi.hoisted(() => {
2527 parameters : { } ,
2628 execute : toolExecute ,
2729 } ) ) ,
30+ widgetToolExecute,
31+ createShowWidgetTool : vi . fn ( ( ) => ( {
32+ label : "Show Widget" ,
33+ name : "show_widget" ,
34+ description : "Show Widget" ,
35+ parameters : { } ,
36+ execute : widgetToolExecute ,
37+ } ) ) ,
2838 } ;
2939} ) ;
3040
@@ -45,11 +55,18 @@ vi.mock("./src/tool.js", () => ({
4555 createCanvasTool : mocks . createCanvasTool ,
4656} ) ) ;
4757
58+ vi . mock ( "./src/widget-tool.js" , ( ) => ( {
59+ createShowWidgetTool : mocks . createShowWidgetTool ,
60+ } ) ) ;
61+
4862function registerCanvas ( ) {
4963 const routes : Array < Parameters < OpenClawPluginApi [ "registerHttpRoute" ] > [ 0 ] > = [ ] ;
5064 const services : Array < Parameters < OpenClawPluginApi [ "registerService" ] > [ 0 ] > = [ ] ;
5165 const resolvers : Array < Parameters < OpenClawPluginApi [ "registerHostedMediaResolver" ] > [ 0 ] > = [ ] ;
52- const tools : Array < Parameters < OpenClawPluginApi [ "registerTool" ] > [ 0 ] > = [ ] ;
66+ const tools : Array < {
67+ tool : Parameters < OpenClawPluginApi [ "registerTool" ] > [ 0 ] ;
68+ opts : Parameters < OpenClawPluginApi [ "registerTool" ] > [ 1 ] ;
69+ } > = [ ] ;
5370 const cliFeatures : Array < {
5471 registrar : Parameters < OpenClawPluginApi [ "registerNodeCliFeature" ] > [ 0 ] ;
5572 opts : Parameters < OpenClawPluginApi [ "registerNodeCliFeature" ] > [ 1 ] ;
@@ -62,7 +79,7 @@ function registerCanvas() {
6279 registerHttpRoute : ( route ) => routes . push ( route ) ,
6380 registerService : ( service ) => services . push ( service ) ,
6481 registerHostedMediaResolver : ( resolver ) => resolvers . push ( resolver ) ,
65- registerTool : ( tool ) => tools . push ( tool ) ,
82+ registerTool : ( tool , opts ) => tools . push ( { tool, opts } ) ,
6683 registerNodeCliFeature : ( registrar , opts ) => cliFeatures . push ( { registrar, opts } ) ,
6784 registerNodeInvokePolicy : vi . fn ( ) ,
6885 } ) ,
@@ -97,11 +114,13 @@ describe("Canvas plugin entry", () => {
97114 const { resolvers, tools, cliFeatures } = registerCanvas ( ) ;
98115
99116 expect ( resolvers ) . toHaveLength ( 1 ) ;
100- expect ( tools ) . toHaveLength ( 1 ) ;
117+ expect ( tools ) . toHaveLength ( 2 ) ;
118+ expect ( tools . map ( ( { opts } ) => opts ?. name ) ) . toEqual ( [ undefined , "show_widget" ] ) ;
101119 expect ( cliFeatures ) . toHaveLength ( 1 ) ;
102120 expect ( mocks . resolveCanvasHttpPathToLocalPath ) . not . toHaveBeenCalled ( ) ;
103121 expect ( mocks . createDefaultCanvasCliDependencies ) . not . toHaveBeenCalled ( ) ;
104122 expect ( mocks . createCanvasTool ) . not . toHaveBeenCalled ( ) ;
123+ expect ( mocks . createShowWidgetTool ) . not . toHaveBeenCalled ( ) ;
105124
106125 await expect ( resolvers [ 0 ] ?.( "/__openclaw__/canvas/documents/id/index.html" ) ) . resolves . toBe (
107126 "/tmp/canvas-asset" ,
@@ -118,21 +137,42 @@ describe("Canvas plugin entry", () => {
118137 expect ( mocks . createDefaultCanvasCliDependencies ) . toHaveBeenCalledTimes ( 1 ) ;
119138 expect ( mocks . registerNodesCanvasCommands ) . toHaveBeenCalledTimes ( 1 ) ;
120139
121- const toolFactory = tools [ 0 ] ;
122- expect ( typeof toolFactory ) . toBe ( "function" ) ;
123- const tool = ( toolFactory as Exclude < typeof toolFactory , AnyAgentTool > ) ( {
124- config : { } ,
125- workspaceDir : "/tmp/workspace" ,
140+ const registeredTools = tools . map ( ( { tool : toolFactory } ) => {
141+ expect ( typeof toolFactory ) . toBe ( "function" ) ;
142+ const tool = ( toolFactory as Exclude < typeof toolFactory , AnyAgentTool > ) ( {
143+ config : { } ,
144+ workspaceDir : "/tmp/workspace" ,
145+ sessionId : "session-1" ,
146+ agentId : "agent-1" ,
147+ } ) ;
148+ expect ( Array . isArray ( tool ) ) . toBe ( false ) ;
149+ return tool as AnyAgentTool ;
126150 } ) ;
127- expect ( Array . isArray ( tool ) ) . toBe ( false ) ;
128- expect ( ( tool as AnyAgentTool ) . name ) . toBe ( "canvas" ) ;
151+ expect ( registeredTools . map ( ( tool ) => tool . name ) ) . toEqual ( [ "canvas" , "show_widget" ] ) ;
152+ expect ( registeredTools [ 1 ] ?. requiredClientCaps ) . toEqual ( SHOW_WIDGET_REQUIRED_CLIENT_CAPS ) ;
129153 expect ( mocks . createCanvasTool ) . not . toHaveBeenCalled ( ) ;
154+ expect ( mocks . createShowWidgetTool ) . not . toHaveBeenCalled ( ) ;
130155
131- await ( tool as AnyAgentTool ) . execute ( "tool-call" , { action : "hide" } ) ;
156+ const [ canvasTool , showWidgetTool ] = registeredTools ;
157+ await canvasTool ?. execute ( "tool-call" , { action : "hide" } ) ;
132158 expect ( mocks . createCanvasTool ) . toHaveBeenCalledWith ( {
133159 config : { } ,
134160 workspaceDir : "/tmp/workspace" ,
135161 } ) ;
136162 expect ( mocks . toolExecute ) . toHaveBeenCalledWith ( "tool-call" , { action : "hide" } ) ;
163+
164+ await showWidgetTool ?. execute ( "widget-call" , {
165+ title : "Status" ,
166+ widget_code : "<p>ready</p>" ,
167+ } ) ;
168+ expect ( mocks . createShowWidgetTool ) . toHaveBeenCalledWith ( {
169+ config : { } ,
170+ sessionId : "session-1" ,
171+ agentId : "agent-1" ,
172+ } ) ;
173+ expect ( mocks . widgetToolExecute ) . toHaveBeenCalledWith ( "widget-call" , {
174+ title : "Status" ,
175+ widget_code : "<p>ready</p>" ,
176+ } ) ;
137177 } ) ;
138178} ) ;
0 commit comments