synthos 0.7.1 → 0.8.0

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.
Files changed (263) hide show
  1. package/README.md +215 -65
  2. package/default-pages/application.json +1 -0
  3. package/default-pages/json_tools.json +1 -1
  4. package/default-pages/oregon_trail.html +321 -0
  5. package/default-pages/oregon_trail.json +12 -0
  6. package/default-pages/sidebar_page.json +1 -0
  7. package/default-pages/solar_explorer.html +10 -18
  8. package/default-pages/solar_explorer.json +2 -2
  9. package/default-pages/two-panel_page.json +1 -0
  10. package/default-pages/us_map.html +192 -0
  11. package/default-pages/us_map.json +12 -0
  12. package/default-pages/us_map_1850.html +325 -0
  13. package/default-pages/us_map_1850.json +12 -0
  14. package/default-pages/western_cities_1850.html +526 -0
  15. package/default-pages/western_cities_1850.json +12 -0
  16. package/default-themes/{nebula-dawn.css → nebula-dawn.v2.css} +24 -0
  17. package/default-themes/{nebula-dusk.css → nebula-dusk.v2.css} +24 -0
  18. package/dist/agents/a2a/a2aProvider.d.ts +3 -0
  19. package/dist/agents/a2a/a2aProvider.d.ts.map +1 -0
  20. package/dist/agents/a2a/a2aProvider.js +126 -0
  21. package/dist/agents/a2a/a2aProvider.js.map +1 -0
  22. package/dist/agents/discovery.d.ts +30 -0
  23. package/dist/agents/discovery.d.ts.map +1 -0
  24. package/dist/agents/discovery.js +52 -0
  25. package/dist/agents/discovery.js.map +1 -0
  26. package/dist/agents/index.d.ts +7 -0
  27. package/dist/agents/index.d.ts.map +1 -0
  28. package/dist/agents/index.js +19 -0
  29. package/dist/agents/index.js.map +1 -0
  30. package/dist/agents/openclaw/gatewayManager.d.ts +113 -0
  31. package/dist/agents/openclaw/gatewayManager.d.ts.map +1 -0
  32. package/dist/agents/openclaw/gatewayManager.js +470 -0
  33. package/dist/agents/openclaw/gatewayManager.js.map +1 -0
  34. package/dist/agents/openclaw/openclawProvider.d.ts +3 -0
  35. package/dist/agents/openclaw/openclawProvider.d.ts.map +1 -0
  36. package/dist/agents/openclaw/openclawProvider.js +239 -0
  37. package/dist/agents/openclaw/openclawProvider.js.map +1 -0
  38. package/dist/agents/openclaw/sshTunnelManager.d.ts +23 -0
  39. package/dist/agents/openclaw/sshTunnelManager.d.ts.map +1 -0
  40. package/dist/agents/openclaw/sshTunnelManager.js +340 -0
  41. package/dist/agents/openclaw/sshTunnelManager.js.map +1 -0
  42. package/dist/agents/types.d.ts +64 -0
  43. package/dist/agents/types.d.ts.map +1 -0
  44. package/dist/agents/types.js +6 -0
  45. package/dist/agents/types.js.map +1 -0
  46. package/dist/connectors/airtable/connector.json +27 -0
  47. package/dist/connectors/alpha-vantage/connector.json +26 -0
  48. package/dist/connectors/brave-search/connector.json +26 -0
  49. package/dist/connectors/cloudinary/connector.json +27 -0
  50. package/dist/connectors/deepl/connector.json +28 -0
  51. package/dist/connectors/elevenlabs/connector.json +30 -0
  52. package/dist/connectors/giphy/connector.json +27 -0
  53. package/dist/connectors/github/connector.json +29 -0
  54. package/dist/connectors/huggingface/connector.json +27 -0
  55. package/dist/connectors/imgur/connector.json +29 -0
  56. package/dist/connectors/index.d.ts +1 -1
  57. package/dist/connectors/index.d.ts.map +1 -1
  58. package/dist/connectors/instagram/connector.json +43 -0
  59. package/dist/connectors/jira/connector.json +28 -0
  60. package/dist/connectors/mapbox/connector.json +26 -0
  61. package/dist/connectors/nasa/connector.json +27 -0
  62. package/dist/connectors/newsapi/connector.json +27 -0
  63. package/dist/connectors/notion/connector.json +28 -0
  64. package/dist/connectors/open-exchange-rates/connector.json +27 -0
  65. package/dist/connectors/openweathermap/connector.json +26 -0
  66. package/dist/connectors/pexels/connector.json +27 -0
  67. package/dist/connectors/registry.d.ts.map +1 -1
  68. package/dist/connectors/registry.js +42 -96
  69. package/dist/connectors/registry.js.map +1 -1
  70. package/dist/connectors/resend/connector.json +29 -0
  71. package/dist/connectors/rss2json/connector.json +27 -0
  72. package/dist/connectors/sendgrid/connector.json +27 -0
  73. package/dist/connectors/spoonacular/connector.json +28 -0
  74. package/dist/connectors/stability-ai/connector.json +27 -0
  75. package/dist/connectors/twilio/connector.json +28 -0
  76. package/dist/connectors/types.d.ts +23 -0
  77. package/dist/connectors/types.d.ts.map +1 -1
  78. package/dist/connectors/unsplash/connector.json +27 -0
  79. package/dist/connectors/wolfram-alpha/connector.json +26 -0
  80. package/dist/connectors/youtube-data/connector.json +30 -0
  81. package/dist/files.d.ts +1 -0
  82. package/dist/files.d.ts.map +1 -1
  83. package/dist/files.js +16 -1
  84. package/dist/files.js.map +1 -1
  85. package/dist/init.d.ts.map +1 -1
  86. package/dist/init.js +28 -0
  87. package/dist/init.js.map +1 -1
  88. package/dist/migrations.d.ts +3 -2
  89. package/dist/migrations.d.ts.map +1 -1
  90. package/dist/migrations.js +122 -138
  91. package/dist/migrations.js.map +1 -1
  92. package/dist/models/anthropic.d.ts +22 -0
  93. package/dist/models/anthropic.d.ts.map +1 -0
  94. package/dist/models/anthropic.js +76 -0
  95. package/dist/models/anthropic.js.map +1 -0
  96. package/dist/models/chainOfThought.d.ts +12 -0
  97. package/dist/models/chainOfThought.d.ts.map +1 -0
  98. package/dist/models/chainOfThought.js +45 -0
  99. package/dist/models/chainOfThought.js.map +1 -0
  100. package/dist/models/fireworksai.d.ts +30 -0
  101. package/dist/models/fireworksai.d.ts.map +1 -0
  102. package/dist/models/fireworksai.js +133 -0
  103. package/dist/models/fireworksai.js.map +1 -0
  104. package/dist/models/index.d.ts +7 -1
  105. package/dist/models/index.d.ts.map +1 -1
  106. package/dist/models/index.js +19 -1
  107. package/dist/models/index.js.map +1 -1
  108. package/dist/models/logCompletePrompt.d.ts +3 -0
  109. package/dist/models/logCompletePrompt.d.ts.map +1 -0
  110. package/dist/models/logCompletePrompt.js +23 -0
  111. package/dist/models/logCompletePrompt.js.map +1 -0
  112. package/dist/models/openai.d.ts +24 -0
  113. package/dist/models/openai.d.ts.map +1 -0
  114. package/dist/models/openai.js +80 -0
  115. package/dist/models/openai.js.map +1 -0
  116. package/dist/models/providers.d.ts +1 -0
  117. package/dist/models/providers.d.ts.map +1 -1
  118. package/dist/models/providers.js +12 -4
  119. package/dist/models/providers.js.map +1 -1
  120. package/dist/models/types.d.ts +34 -2
  121. package/dist/models/types.d.ts.map +1 -1
  122. package/dist/models/types.js +16 -0
  123. package/dist/models/types.js.map +1 -1
  124. package/dist/models/utils.d.ts +6 -0
  125. package/dist/models/utils.d.ts.map +1 -0
  126. package/dist/models/utils.js +21 -0
  127. package/dist/models/utils.js.map +1 -0
  128. package/dist/scripts.d.ts +2 -1
  129. package/dist/scripts.d.ts.map +1 -1
  130. package/dist/scripts.js +4 -3
  131. package/dist/scripts.js.map +1 -1
  132. package/dist/service/createCompletePrompt.d.ts +1 -1
  133. package/dist/service/createCompletePrompt.d.ts.map +1 -1
  134. package/dist/service/createCompletePrompt.js +9 -6
  135. package/dist/service/createCompletePrompt.js.map +1 -1
  136. package/dist/service/generateImage.d.ts +1 -1
  137. package/dist/service/generateImage.d.ts.map +1 -1
  138. package/dist/service/generateImage.js +3 -3
  139. package/dist/service/generateImage.js.map +1 -1
  140. package/dist/service/server.d.ts.map +1 -1
  141. package/dist/service/server.js +3 -0
  142. package/dist/service/server.js.map +1 -1
  143. package/dist/service/transformPage.d.ts +4 -2
  144. package/dist/service/transformPage.d.ts.map +1 -1
  145. package/dist/service/transformPage.js +74 -6
  146. package/dist/service/transformPage.js.map +1 -1
  147. package/dist/service/useAgentRoutes.d.ts +4 -0
  148. package/dist/service/useAgentRoutes.d.ts.map +1 -0
  149. package/dist/service/useAgentRoutes.js +389 -0
  150. package/dist/service/useAgentRoutes.js.map +1 -0
  151. package/dist/service/useApiRoutes.d.ts.map +1 -1
  152. package/dist/service/useApiRoutes.js +157 -16
  153. package/dist/service/useApiRoutes.js.map +1 -1
  154. package/dist/service/useConnectorRoutes.d.ts.map +1 -1
  155. package/dist/service/useConnectorRoutes.js +14 -3
  156. package/dist/service/useConnectorRoutes.js.map +1 -1
  157. package/dist/service/useGatewayRoutes.d.ts +4 -0
  158. package/dist/service/useGatewayRoutes.d.ts.map +1 -0
  159. package/dist/service/useGatewayRoutes.js +168 -0
  160. package/dist/service/useGatewayRoutes.js.map +1 -0
  161. package/dist/service/usePageRoutes.d.ts.map +1 -1
  162. package/dist/service/usePageRoutes.js +16 -5
  163. package/dist/service/usePageRoutes.js.map +1 -1
  164. package/dist/settings.d.ts +2 -1
  165. package/dist/settings.d.ts.map +1 -1
  166. package/dist/settings.js +4 -8
  167. package/dist/settings.js.map +1 -1
  168. package/dist/themes.d.ts +14 -0
  169. package/dist/themes.d.ts.map +1 -1
  170. package/dist/themes.js +86 -13
  171. package/dist/themes.js.map +1 -1
  172. package/package.json +10 -5
  173. package/page-scripts/helpers-v2.js +222 -0
  174. package/page-scripts/page-v2.js +656 -0
  175. package/required-pages/builder.html +1 -27
  176. package/required-pages/pages.html +745 -22
  177. package/required-pages/settings.html +819 -21
  178. package/required-pages/synthos_apis.html +56 -1
  179. package/src/agents/a2a/a2aProvider.ts +110 -0
  180. package/src/agents/discovery.ts +74 -0
  181. package/src/agents/index.ts +6 -0
  182. package/src/agents/openclaw/gatewayManager.ts +559 -0
  183. package/src/agents/openclaw/openclawProvider.ts +261 -0
  184. package/src/agents/openclaw/sshTunnelManager.ts +385 -0
  185. package/src/agents/types.ts +82 -0
  186. package/src/connectors/airtable/connector.json +27 -0
  187. package/src/connectors/alpha-vantage/connector.json +26 -0
  188. package/src/connectors/brave-search/connector.json +26 -0
  189. package/src/connectors/cloudinary/connector.json +27 -0
  190. package/src/connectors/deepl/connector.json +28 -0
  191. package/src/connectors/elevenlabs/connector.json +30 -0
  192. package/src/connectors/giphy/connector.json +27 -0
  193. package/src/connectors/github/connector.json +29 -0
  194. package/src/connectors/huggingface/connector.json +27 -0
  195. package/src/connectors/imgur/connector.json +29 -0
  196. package/src/connectors/index.ts +2 -0
  197. package/src/connectors/instagram/connector.json +43 -0
  198. package/src/connectors/jira/connector.json +28 -0
  199. package/src/connectors/mapbox/connector.json +26 -0
  200. package/src/connectors/nasa/connector.json +27 -0
  201. package/src/connectors/newsapi/connector.json +27 -0
  202. package/src/connectors/notion/connector.json +28 -0
  203. package/src/connectors/open-exchange-rates/connector.json +27 -0
  204. package/src/connectors/openweathermap/connector.json +26 -0
  205. package/src/connectors/pexels/connector.json +27 -0
  206. package/src/connectors/registry.ts +21 -97
  207. package/src/connectors/resend/connector.json +29 -0
  208. package/src/connectors/rss2json/connector.json +27 -0
  209. package/src/connectors/sendgrid/connector.json +27 -0
  210. package/src/connectors/spoonacular/connector.json +28 -0
  211. package/src/connectors/stability-ai/connector.json +27 -0
  212. package/src/connectors/twilio/connector.json +28 -0
  213. package/src/connectors/types.ts +25 -0
  214. package/src/connectors/unsplash/connector.json +27 -0
  215. package/src/connectors/wolfram-alpha/connector.json +26 -0
  216. package/src/connectors/youtube-data/connector.json +30 -0
  217. package/src/files.ts +14 -0
  218. package/src/init.ts +27 -0
  219. package/src/migrations.ts +121 -138
  220. package/src/models/anthropic.ts +89 -0
  221. package/src/models/chainOfThought.ts +56 -0
  222. package/src/models/fireworksai.ts +136 -0
  223. package/src/models/index.ts +7 -1
  224. package/src/models/logCompletePrompt.ts +25 -0
  225. package/src/models/openai.ts +90 -0
  226. package/src/models/providers.ts +12 -3
  227. package/src/models/types.ts +67 -2
  228. package/src/models/utils.ts +16 -0
  229. package/src/scripts.ts +2 -2
  230. package/src/service/createCompletePrompt.ts +3 -1
  231. package/src/service/generateImage.ts +2 -2
  232. package/src/service/server.ts +4 -0
  233. package/src/service/transformPage.ts +81 -8
  234. package/src/service/useAgentRoutes.ts +423 -0
  235. package/src/service/useApiRoutes.ts +173 -18
  236. package/src/service/useConnectorRoutes.ts +14 -3
  237. package/src/service/usePageRoutes.ts +20 -6
  238. package/src/settings.ts +6 -10
  239. package/src/themes.ts +84 -12
  240. package/tests/README.md +12 -0
  241. package/tests/anthropic.spec.ts +84 -0
  242. package/tests/chainOfThought.spec.ts +108 -0
  243. package/tests/ensureScripts.spec.ts +82 -0
  244. package/tests/files.spec.ts +233 -0
  245. package/tests/fireworksai.spec.ts +92 -0
  246. package/tests/logCompletePrompt.spec.ts +74 -0
  247. package/tests/migrations.spec.ts +169 -0
  248. package/tests/openai.spec.ts +71 -0
  249. package/tests/pages.spec.ts +328 -0
  250. package/tests/providers.spec.ts +144 -0
  251. package/tests/scripts.spec.ts +209 -0
  252. package/tests/transformPage.spec.ts +931 -0
  253. package/tests/types.spec.ts +23 -0
  254. package/default-pages/app_builder.json +0 -1
  255. package/default-pages/sidebar_builder.json +0 -1
  256. package/default-pages/two-panel_builder.json +0 -1
  257. package/images/home.png +0 -0
  258. package/images/page-management.png +0 -0
  259. package/images/settings.png +0 -0
  260. package/images/synthos-square.png +0 -0
  261. /package/default-pages/{app_builder.html → application.html} +0 -0
  262. /package/default-pages/{sidebar_builder.html → sidebar_page.html} +0 -0
  263. /package/default-pages/{two-panel_builder.html → two-panel_page.html} +0 -0
@@ -261,12 +261,67 @@
261
261
  <div class="api-output"></div>
262
262
  </div>
263
263
  </div>
264
+ <div class="api-section">
265
+ <div class="api-header" onclick="toggleSection(this)">GET /api/agents</div>
266
+ <div class="api-content">
267
+ Lists configured agents (A2A and OpenClaw). Supports optional filters: enabled (boolean) and provider (a2a|openclaw). Returns id, name, description, url, enabled, provider, and capabilities for each agent.
268
+ <div class="api-input">
269
+ <select id="agentListEnabled">
270
+ <option value="">All</option>
271
+ <option value="true">Enabled only</option>
272
+ </select>
273
+ <select id="agentListProvider">
274
+ <option value="">All providers</option>
275
+ <option value="a2a">A2A</option>
276
+ <option value="openclaw">OpenClaw</option>
277
+ </select>
278
+ <button onclick="listAgents(event)">Submit</button>
279
+ </div>
280
+ <div class="api-output"></div>
281
+ </div>
282
+ </div>
283
+ <div class="api-section">
284
+ <div class="api-header" onclick="toggleSection(this)">POST /api/agents/:id/send</div>
285
+ <div class="api-content">
286
+ Sends a text message to an agent (works for both A2A and OpenClaw protocols). Returns a normalized response: { kind: 'message'|'task', text?: string, raw: object }. Optionally include an attachments array: [{ fileName: string, mimeType: string, content: string (base64 for binary) }].
287
+ <div class="api-input">
288
+ <input type="text" placeholder="Agent ID" id="agentSendId">
289
+ <textarea placeholder="Message" id="agentSendMessage"></textarea>
290
+ <button onclick="sendAgentMessage(event)">Send</button>
291
+ </div>
292
+ <div class="api-output"></div>
293
+ </div>
294
+ </div>
295
+ <div class="api-section">
296
+ <div class="api-header" onclick="toggleSection(this)">POST /api/agents/:id/stream</div>
297
+ <div class="api-content">
298
+ Sends a message and receives a streaming SSE response. Each event is JSON: { kind: 'text'|'status'|'artifact'|'done'|'error', data: any }. The stream ends with a [DONE] sentinel. Optionally include an attachments array: [{ fileName: string, mimeType: string, content: string (base64 for binary) }].
299
+ <div class="api-input">
300
+ <input type="text" placeholder="Agent ID" id="agentStreamId">
301
+ <textarea placeholder="Message" id="agentStreamMessage"></textarea>
302
+ <button onclick="streamAgentMessage(event)">Stream</button>
303
+ </div>
304
+ <div class="api-output"></div>
305
+ </div>
306
+ </div>
307
+ <div class="api-section">
308
+ <div class="api-header" onclick="toggleSection(this)">PATCH /api/agents/:id</div>
309
+ <div class="api-content">
310
+ Toggle an agent's enabled/disabled state or update its name and description. Send only the fields to change.
311
+ <div class="api-input">
312
+ <input type="text" placeholder="Agent ID" id="agentPatchId">
313
+ <textarea placeholder="{ &quot;enabled&quot;: true }" id="agentPatchBody"></textarea>
314
+ <button onclick="patchAgent(event)">Submit</button>
315
+ </div>
316
+ <div class="api-output"></div>
317
+ </div>
318
+ </div>
264
319
  </div>
265
320
  <div id="loadingOverlay" class="loading-overlay"><div class="spinner"></div></div>
266
321
  </div>
267
322
  <div id="instructions" style="display: none;" data-locked="true"></div>
268
323
  <div id="thoughts" style="display: none;" data-locked="true"></div>
269
- <script id="api-explorer">function toggleSection(header){const content=header.nextElementSibling;content.style.display="block"===content.style.display?"none":"block"}function callApi(event,method,endpoint){event.preventDefault();const button=event.target;button.disabled=!0;const inputs=event.target.parentElement.querySelectorAll("input, textarea");let url=endpoint,data={};inputs.forEach(input=>{"Page Name"===input.placeholder?url+=input.value:"Table Name"===input.placeholder||"ID"===input.placeholder?url+="/"+input.value:"JSON Data"===input.placeholder&&(data=JSON.parse(input.value))}),fetch(url,{method:method,headers:{"Content-Type":"application/json"},body:"POST"===method?JSON.stringify(data):null}).then(response=>response.json()).then(data=>{console.log("Success:",data),event.target.parentElement.nextElementSibling.textContent=JSON.stringify(data,null,2)}).catch(error=>{console.error("Error:",error),alert("API call failed! Check console for details.")}).finally(()=>{button.disabled=!1})}function callPaginatedApi(event){event.preventDefault();const button=event.target;button.disabled=!0;const inputs=event.target.parentElement.querySelectorAll("input");let page="",table="",limit="",offset="";inputs.forEach(input=>{"Page Name"===input.placeholder?page=input.value:"Table Name"===input.placeholder?table=input.value:"Limit"===input.placeholder?limit=input.value:"Offset (optional)"===input.placeholder&&(offset=input.value)});let url="/api/data/"+encodeURIComponent(page)+"/"+encodeURIComponent(table)+"?limit="+encodeURIComponent(limit);offset&&(url+="&offset="+encodeURIComponent(offset)),fetch(url).then(response=>response.json()).then(data=>{event.target.parentElement.nextElementSibling.textContent=JSON.stringify(data,null,2)}).catch(error=>{console.error("Error:",error),alert("API call failed! Check console for details.")}).finally(()=>{button.disabled=!1})}function callPageApi(event,method,suffix){event.preventDefault();const button=event.target;button.disabled=!0;const inputs=event.target.parentElement.querySelectorAll("input, textarea");let pageName="",data=null;inputs.forEach(input=>{"Page Name"===input.placeholder?pageName=input.value:"TEXTAREA"===input.tagName&&(data=JSON.parse(input.value))});const url="/api/pages/"+encodeURIComponent(pageName)+(suffix||"");fetch(url,{method:method,headers:{"Content-Type":"application/json"},body:"POST"===method?JSON.stringify(data):null}).then(response=>response.json()).then(data=>{event.target.parentElement.nextElementSibling.textContent=JSON.stringify(data,null,2)}).catch(error=>{console.error("Error:",error),alert("API call failed! Check console for details.")}).finally(()=>{button.disabled=!1})}function generateImage(event){event.preventDefault();const button=event.target;button.disabled=!0;const prompt=document.getElementById("imagePrompt").value,shape=document.getElementById("imageShape").value,style=document.getElementById("imageStyle").value,outputBox=event.target.parentElement.nextElementSibling;fetch("/api/generate/image",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({prompt:prompt,shape:shape,style:style})}).then(response=>response.json()).then(data=>{if(console.log("Success:",data),outputBox.textContent=JSON.stringify(data,null,2),data.url){const img=document.createElement("img");img.src=data.url,img.alt="Generated Image",img.className="generated-image",outputBox.appendChild(img)}}).catch(error=>{console.error("Error:",error),alert("Image generation failed! Check console for details.")}).finally(()=>{button.disabled=!1})}function generateCompletion(event){event.preventDefault();const button=event.target;button.disabled=!0;const prompt=document.getElementById("completionPrompt").value,temperature=document.getElementById("completionTemperature").value,outputBox=event.target.parentElement.nextElementSibling;fetch("/api/generate/completion",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({prompt:prompt,temperature:parseFloat(temperature)||void 0})}).then(response=>response.json()).then(data=>{console.log("Success:",data),outputBox.textContent=JSON.stringify(data,null,2)}).catch(error=>{console.error("Error:",error),alert("Completion generation failed! Check console for details.")}).finally(()=>{button.disabled=!1})}function webSearch(event){event.preventDefault();var button=event.target;button.disabled=!0;var query=document.getElementById("webSearchQuery").value,count=document.getElementById("webSearchCount").value,outputBox=event.target.parentElement.nextElementSibling,body={query:query};count&&(body.count=parseInt(count,10)),fetch("/api/search/web",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)}).then(function(response){return response.json()}).then(function(data){outputBox.textContent=JSON.stringify(data,null,2)}).catch(function(error){console.error("Error:",error),alert("Web search failed! Check console for details.")}).finally(function(){button.disabled=!1})}function executeScript(event){event.preventDefault();const button=event.target;button.disabled=!0;const scriptId=document.getElementById("scriptId").value,variables=JSON.parse(document.getElementById("scriptVariables").value),outputBox=event.target.parentElement.nextElementSibling;fetch(`/api/scripts/${scriptId}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(variables)}).then(response=>response.json()).then(data=>{console.log("Success:",data),outputBox.textContent=JSON.stringify(data,null,2)}).catch(error=>{console.error("Error:",error),alert("Script execution failed! Check console for details.")}).finally(()=>{button.disabled=!1})}function listConnectors(event){event.preventDefault();var button=event.target;button.disabled=!0;var category=document.getElementById("connectorListCategory").value;var url="/api/connectors";if(category)url+="?category="+encodeURIComponent(category);var outputBox=event.target.parentElement.nextElementSibling;fetch(url).then(function(r){return r.json()}).then(function(data){outputBox.textContent=JSON.stringify(data,null,2)}).catch(function(err){console.error("Error:",err);alert("Failed! Check console.")}).finally(function(){button.disabled=!1})}function getConnectorDetail(event){event.preventDefault();var button=event.target;button.disabled=!0;var id=document.getElementById("connectorDetailId").value;var outputBox=event.target.parentElement.nextElementSibling;fetch("/api/connectors/"+encodeURIComponent(id)).then(function(r){return r.json()}).then(function(data){outputBox.textContent=JSON.stringify(data,null,2)}).catch(function(err){console.error("Error:",err);alert("Failed! Check console.")}).finally(function(){button.disabled=!1})}function callConnector(event){event.preventDefault();var button=event.target;button.disabled=!0;var body={connector:document.getElementById("connectorCallId").value,method:document.getElementById("connectorCallMethod").value,path:document.getElementById("connectorCallPath").value};var queryVal=document.getElementById("connectorCallQuery").value;if(queryVal)try{body.query=JSON.parse(queryVal)}catch(e){}var bodyVal=document.getElementById("connectorCallBody").value;if(bodyVal)try{body.body=JSON.parse(bodyVal)}catch(e){}var outputBox=event.target.parentElement.nextElementSibling;fetch("/api/connectors",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)}).then(function(r){return r.json()}).then(function(data){outputBox.textContent=JSON.stringify(data,null,2)}).catch(function(err){console.error("Error:",err);alert("Failed! Check console.")}).finally(function(){button.disabled=!1})}</script>
324
+ <script id="api-explorer">function toggleSection(header){const content=header.nextElementSibling;content.style.display="block"===content.style.display?"none":"block"}function callApi(event,method,endpoint){event.preventDefault();const button=event.target;button.disabled=!0;const inputs=event.target.parentElement.querySelectorAll("input, textarea");let url=endpoint,data={};inputs.forEach(input=>{"Page Name"===input.placeholder?url+=input.value:"Table Name"===input.placeholder||"ID"===input.placeholder?url+="/"+input.value:"JSON Data"===input.placeholder&&(data=JSON.parse(input.value))}),fetch(url,{method:method,headers:{"Content-Type":"application/json"},body:"POST"===method?JSON.stringify(data):null}).then(response=>response.json()).then(data=>{console.log("Success:",data),event.target.parentElement.nextElementSibling.textContent=JSON.stringify(data,null,2)}).catch(error=>{console.error("Error:",error),alert("API call failed! Check console for details.")}).finally(()=>{button.disabled=!1})}function callPaginatedApi(event){event.preventDefault();const button=event.target;button.disabled=!0;const inputs=event.target.parentElement.querySelectorAll("input");let page="",table="",limit="",offset="";inputs.forEach(input=>{"Page Name"===input.placeholder?page=input.value:"Table Name"===input.placeholder?table=input.value:"Limit"===input.placeholder?limit=input.value:"Offset (optional)"===input.placeholder&&(offset=input.value)});let url="/api/data/"+encodeURIComponent(page)+"/"+encodeURIComponent(table)+"?limit="+encodeURIComponent(limit);offset&&(url+="&offset="+encodeURIComponent(offset)),fetch(url).then(response=>response.json()).then(data=>{event.target.parentElement.nextElementSibling.textContent=JSON.stringify(data,null,2)}).catch(error=>{console.error("Error:",error),alert("API call failed! Check console for details.")}).finally(()=>{button.disabled=!1})}function callPageApi(event,method,suffix){event.preventDefault();const button=event.target;button.disabled=!0;const inputs=event.target.parentElement.querySelectorAll("input, textarea");let pageName="",data=null;inputs.forEach(input=>{"Page Name"===input.placeholder?pageName=input.value:"TEXTAREA"===input.tagName&&(data=JSON.parse(input.value))});const url="/api/pages/"+encodeURIComponent(pageName)+(suffix||"");fetch(url,{method:method,headers:{"Content-Type":"application/json"},body:"POST"===method?JSON.stringify(data):null}).then(response=>response.json()).then(data=>{event.target.parentElement.nextElementSibling.textContent=JSON.stringify(data,null,2)}).catch(error=>{console.error("Error:",error),alert("API call failed! Check console for details.")}).finally(()=>{button.disabled=!1})}function generateImage(event){event.preventDefault();const button=event.target;button.disabled=!0;const prompt=document.getElementById("imagePrompt").value,shape=document.getElementById("imageShape").value,style=document.getElementById("imageStyle").value,outputBox=event.target.parentElement.nextElementSibling;fetch("/api/generate/image",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({prompt:prompt,shape:shape,style:style})}).then(response=>response.json()).then(data=>{if(console.log("Success:",data),outputBox.textContent=JSON.stringify(data,null,2),data.url){const img=document.createElement("img");img.src=data.url,img.alt="Generated Image",img.className="generated-image",outputBox.appendChild(img)}}).catch(error=>{console.error("Error:",error),alert("Image generation failed! Check console for details.")}).finally(()=>{button.disabled=!1})}function generateCompletion(event){event.preventDefault();const button=event.target;button.disabled=!0;const prompt=document.getElementById("completionPrompt").value,temperature=document.getElementById("completionTemperature").value,outputBox=event.target.parentElement.nextElementSibling;fetch("/api/generate/completion",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({prompt:prompt,temperature:parseFloat(temperature)||void 0})}).then(response=>response.json()).then(data=>{console.log("Success:",data),outputBox.textContent=JSON.stringify(data,null,2)}).catch(error=>{console.error("Error:",error),alert("Completion generation failed! Check console for details.")}).finally(()=>{button.disabled=!1})}function webSearch(event){event.preventDefault();var button=event.target;button.disabled=!0;var query=document.getElementById("webSearchQuery").value,count=document.getElementById("webSearchCount").value,outputBox=event.target.parentElement.nextElementSibling,body={query:query};count&&(body.count=parseInt(count,10)),fetch("/api/search/web",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)}).then(function(response){return response.json()}).then(function(data){outputBox.textContent=JSON.stringify(data,null,2)}).catch(function(error){console.error("Error:",error),alert("Web search failed! Check console for details.")}).finally(function(){button.disabled=!1})}function executeScript(event){event.preventDefault();const button=event.target;button.disabled=!0;const scriptId=document.getElementById("scriptId").value,variables=JSON.parse(document.getElementById("scriptVariables").value),outputBox=event.target.parentElement.nextElementSibling;fetch(`/api/scripts/${scriptId}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(variables)}).then(response=>response.json()).then(data=>{console.log("Success:",data),outputBox.textContent=JSON.stringify(data,null,2)}).catch(error=>{console.error("Error:",error),alert("Script execution failed! Check console for details.")}).finally(()=>{button.disabled=!1})}function listConnectors(event){event.preventDefault();var button=event.target;button.disabled=!0;var category=document.getElementById("connectorListCategory").value;var url="/api/connectors";if(category)url+="?category="+encodeURIComponent(category);var outputBox=event.target.parentElement.nextElementSibling;fetch(url).then(function(r){return r.json()}).then(function(data){outputBox.textContent=JSON.stringify(data,null,2)}).catch(function(err){console.error("Error:",err);alert("Failed! Check console.")}).finally(function(){button.disabled=!1})}function getConnectorDetail(event){event.preventDefault();var button=event.target;button.disabled=!0;var id=document.getElementById("connectorDetailId").value;var outputBox=event.target.parentElement.nextElementSibling;fetch("/api/connectors/"+encodeURIComponent(id)).then(function(r){return r.json()}).then(function(data){outputBox.textContent=JSON.stringify(data,null,2)}).catch(function(err){console.error("Error:",err);alert("Failed! Check console.")}).finally(function(){button.disabled=!1})}function callConnector(event){event.preventDefault();var button=event.target;button.disabled=!0;var body={connector:document.getElementById("connectorCallId").value,method:document.getElementById("connectorCallMethod").value,path:document.getElementById("connectorCallPath").value};var queryVal=document.getElementById("connectorCallQuery").value;if(queryVal)try{body.query=JSON.parse(queryVal)}catch(e){}var bodyVal=document.getElementById("connectorCallBody").value;if(bodyVal)try{body.body=JSON.parse(bodyVal)}catch(e){}var outputBox=event.target.parentElement.nextElementSibling;fetch("/api/connectors",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)}).then(function(r){return r.json()}).then(function(data){outputBox.textContent=JSON.stringify(data,null,2)}).catch(function(err){console.error("Error:",err);alert("Failed! Check console.")}).finally(function(){button.disabled=!1})}function listAgents(event){event.preventDefault();var button=event.target;button.disabled=!0;var enabled=document.getElementById("agentListEnabled").value;var provider=document.getElementById("agentListProvider").value;var url="/api/agents";var params=[];if(enabled)params.push("enabled="+enabled);if(provider)params.push("provider="+encodeURIComponent(provider));if(params.length)url+="?"+params.join("&");var outputBox=event.target.parentElement.nextElementSibling;fetch(url).then(function(r){return r.json()}).then(function(data){outputBox.textContent=JSON.stringify(data,null,2)}).catch(function(err){console.error("Error:",err);alert("Failed! Check console.")}).finally(function(){button.disabled=!1})}function sendAgentMessage(event){event.preventDefault();var button=event.target;button.disabled=!0;var id=document.getElementById("agentSendId").value;var message=document.getElementById("agentSendMessage").value;var outputBox=event.target.parentElement.nextElementSibling;fetch("/api/agents/"+encodeURIComponent(id)+"/send",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:message})}).then(function(r){return r.json()}).then(function(data){outputBox.textContent=JSON.stringify(data,null,2)}).catch(function(err){console.error("Error:",err);alert("Failed! Check console.")}).finally(function(){button.disabled=!1})}function streamAgentMessage(event){event.preventDefault();var button=event.target;button.disabled=!0;var id=document.getElementById("agentStreamId").value;var message=document.getElementById("agentStreamMessage").value;var outputBox=event.target.parentElement.nextElementSibling;outputBox.textContent="Streaming...\n";fetch("/api/agents/"+encodeURIComponent(id)+"/stream",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:message})}).then(function(res){var reader=res.body.getReader();var decoder=new TextDecoder();var buffer="";function pump(){return reader.read().then(function(result){if(result.done){button.disabled=!1;return}buffer+=decoder.decode(result.value,{stream:!0});var lines=buffer.split("\n");buffer=lines.pop()||"";for(var i=0;i<lines.length;i++){var line=lines[i];if(line.indexOf("data: ")===0){var data=line.substring(6);if(data==="[DONE]"){outputBox.textContent+="\n[DONE]";button.disabled=!1;return}try{var event=JSON.parse(data);outputBox.textContent+=JSON.stringify(event)+"\n"}catch(e){}}}return pump()})}return pump()}).catch(function(err){console.error("Error:",err);outputBox.textContent+="Error: "+err.message;button.disabled=!1})}function patchAgent(event){event.preventDefault();var button=event.target;button.disabled=!0;var id=document.getElementById("agentPatchId").value;var body;try{body=JSON.parse(document.getElementById("agentPatchBody").value)}catch(e){alert("Invalid JSON");button.disabled=!1;return}var outputBox=event.target.parentElement.nextElementSibling;fetch("/api/agents/"+encodeURIComponent(id),{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)}).then(function(r){return r.json()}).then(function(data){outputBox.textContent=JSON.stringify(data,null,2)}).catch(function(err){console.error("Error:",err);alert("Failed! Check console.")}).finally(function(){button.disabled=!1})}</script>
270
325
  <script id="page-helpers" src="/api/page-helpers.js?v=2" data-locked="true"></script>
271
326
  <script id="page-script" src="/api/page-script.js?v=2" data-locked="true"></script>
272
327
  </body></html>
@@ -0,0 +1,110 @@
1
+ import { v4 as uuidv4 } from 'uuid';
2
+ import { AgentConfig, AgentResponse, AgentEvent, AgentProvider, Attachment } from '../types';
3
+
4
+ /**
5
+ * Extract readable text from an A2A response (Message or Task object).
6
+ */
7
+ function extractText(raw: unknown): string | undefined {
8
+ if (!raw || typeof raw !== 'object') return undefined;
9
+ const obj = raw as Record<string, unknown>;
10
+
11
+ // A2A Message shape: { kind: 'message', parts: [{ kind: 'text', text: '...' }] }
12
+ if (obj.kind === 'message' && Array.isArray(obj.parts)) {
13
+ const texts = (obj.parts as Array<Record<string, unknown>>)
14
+ .filter(p => p.kind === 'text' && typeof p.text === 'string')
15
+ .map(p => p.text as string);
16
+ if (texts.length > 0) return texts.join('\n');
17
+ }
18
+
19
+ // A2A Task shape: { kind: 'task', status: { message: { parts: [...] } } }
20
+ if (obj.kind === 'task' && obj.status && typeof obj.status === 'object') {
21
+ const status = obj.status as Record<string, unknown>;
22
+ if (status.message) {
23
+ return extractText(status.message);
24
+ }
25
+ }
26
+
27
+ // Fallback: look for a result.message in the response
28
+ if (obj.result && typeof obj.result === 'object') {
29
+ return extractText(obj.result);
30
+ }
31
+
32
+ return undefined;
33
+ }
34
+
35
+ export const a2aProvider: AgentProvider = {
36
+ async send(agent: AgentConfig, message: string, _attachments?: Attachment[]): Promise<AgentResponse> {
37
+ const { A2AClient } = await import('@a2a-js/sdk/client');
38
+ const cardUrl = agent.url.replace(/\/+$/, '') + '/.well-known/agent-card.json';
39
+ const client = new A2AClient(cardUrl);
40
+
41
+ const sendResult = await client.sendMessage({
42
+ message: {
43
+ kind: 'message' as const,
44
+ role: 'user' as const,
45
+ messageId: uuidv4(),
46
+ parts: [{ kind: 'text' as const, text: message }]
47
+ }
48
+ });
49
+
50
+ const raw = sendResult as unknown;
51
+ const rawObj = raw as Record<string, unknown>;
52
+ const kind = rawObj.kind === 'task' ? 'task' : 'message';
53
+
54
+ return {
55
+ kind,
56
+ text: extractText(raw),
57
+ raw,
58
+ taskId: kind === 'task' ? (rawObj.id as string | undefined) : undefined,
59
+ status: kind === 'task' ? ((rawObj.status as Record<string, unknown>)?.state as string | undefined) : undefined,
60
+ };
61
+ },
62
+
63
+ async *sendStream(agent: AgentConfig, message: string, _attachments?: Attachment[]): AsyncIterable<AgentEvent> {
64
+ // If the agent supports streaming, use SSE-based streaming via A2A SDK
65
+ if (!agent.capabilities?.streaming) {
66
+ // Fallback: send a regular message and yield the result as a single event
67
+ const response = await a2aProvider.send(agent, message);
68
+ if (response.text) {
69
+ yield { kind: 'text', data: response.text };
70
+ }
71
+ yield { kind: 'done', data: response.raw };
72
+ return;
73
+ }
74
+
75
+ // A2A streaming via sendSubscribe (if available in the SDK)
76
+ try {
77
+ const { A2AClient } = await import('@a2a-js/sdk/client');
78
+ const cardUrl = agent.url.replace(/\/+$/, '') + '/.well-known/agent-card.json';
79
+ const client = new A2AClient(cardUrl);
80
+
81
+ const stream = client.sendMessageStream({
82
+ message: {
83
+ kind: 'message' as const,
84
+ role: 'user' as const,
85
+ messageId: uuidv4(),
86
+ parts: [{ kind: 'text' as const, text: message }]
87
+ }
88
+ });
89
+
90
+ for await (const event of stream) {
91
+ const eventObj = event as unknown as Record<string, unknown>;
92
+ if (eventObj.kind === 'status-update') {
93
+ yield { kind: 'status', data: eventObj };
94
+ } else if (eventObj.kind === 'artifact-update') {
95
+ yield { kind: 'artifact', data: eventObj };
96
+ } else {
97
+ yield { kind: 'text', data: eventObj };
98
+ }
99
+ }
100
+
101
+ yield { kind: 'done', data: null };
102
+ } catch (err) {
103
+ yield { kind: 'error', data: err instanceof Error ? err.message : String(err) };
104
+ }
105
+ },
106
+
107
+ supportsStreaming(agent: AgentConfig): boolean {
108
+ return agent.capabilities?.streaming === true;
109
+ }
110
+ };
@@ -0,0 +1,74 @@
1
+ import { httpBaseUrl } from './openclaw/gatewayManager';
2
+
3
+ // ---------------------------------------------------------------------------
4
+ // A2A Discovery
5
+ // ---------------------------------------------------------------------------
6
+
7
+ export interface A2ADiscoveryResult {
8
+ name: string;
9
+ description: string;
10
+ url: string;
11
+ iconUrl?: string;
12
+ capabilities?: { streaming?: boolean; pushNotifications?: boolean };
13
+ skills?: { id: string; name: string; description: string; tags: string[] }[];
14
+ }
15
+
16
+ /**
17
+ * Discover an A2A agent by fetching its agent card from /.well-known/agent-card.json.
18
+ */
19
+ export async function discoverA2AAgent(url: string): Promise<A2ADiscoveryResult> {
20
+ const cardUrl = url.replace(/\/+$/, '') + '/.well-known/agent-card.json';
21
+ const res = await fetch(cardUrl);
22
+ if (!res.ok) {
23
+ throw new Error(`Failed to fetch agent card: ${res.status} ${res.statusText}`);
24
+ }
25
+
26
+ const card = await res.json() as Record<string, unknown>;
27
+ return {
28
+ name: (card.name as string) ?? '',
29
+ description: (card.description as string) ?? '',
30
+ url: (card.url as string) ?? url,
31
+ iconUrl: (card as Record<string, string>).iconUrl ?? undefined,
32
+ capabilities: (card.capabilities as A2ADiscoveryResult['capabilities']) ?? {},
33
+ skills: (card.skills as A2ADiscoveryResult['skills']) ?? [],
34
+ };
35
+ }
36
+
37
+ // ---------------------------------------------------------------------------
38
+ // OpenClaw Discovery
39
+ // ---------------------------------------------------------------------------
40
+
41
+ export interface OpenClawDiscoveryResult {
42
+ name: string;
43
+ verified: boolean;
44
+ }
45
+
46
+ /**
47
+ * Verify an OpenClaw gateway is reachable and authenticated by probing
48
+ * the HTTP API (GET /v1/models with Bearer token).
49
+ */
50
+ export async function discoverOpenClawAgent(url: string, token: string): Promise<OpenClawDiscoveryResult> {
51
+ const baseUrl = httpBaseUrl({ url });
52
+
53
+ const res = await fetch(`${baseUrl}/v1/models`, {
54
+ headers: { 'Authorization': `Bearer ${token}` },
55
+ });
56
+
57
+ if (!res.ok) {
58
+ throw new Error(`OpenClaw probe failed (${res.status}): ${await res.text()}`);
59
+ }
60
+
61
+ // Try to extract a name from the models response
62
+ let name = 'OpenClaw Agent';
63
+ try {
64
+ const data = await res.json() as Record<string, unknown>;
65
+ const models = (data.data ?? data.models) as Array<Record<string, unknown>> | undefined;
66
+ if (Array.isArray(models) && models.length > 0) {
67
+ name = (models[0].id as string) ?? name;
68
+ }
69
+ } catch {
70
+ // Response parsed but no useful data — that's fine
71
+ }
72
+
73
+ return { name, verified: true };
74
+ }
@@ -0,0 +1,6 @@
1
+ export { AgentConfig, AgentResponse, AgentEvent, AgentProvider, Attachment, ChatMessage } from './types';
2
+ export { a2aProvider } from './a2a/a2aProvider';
3
+ export { openclawProvider } from './openclaw/openclawProvider';
4
+ export { connectAgent, disconnectAgent, getAgentStatus } from './openclaw/gatewayManager';
5
+ export { startTunnel, stopTunnel, getTunnelStatus } from './openclaw/sshTunnelManager';
6
+ export { discoverA2AAgent, discoverOpenClawAgent } from './discovery';