agent-orcha 0.0.5 → 0.0.8

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 (404) hide show
  1. package/README.md +250 -1275
  2. package/dist/lib/agents/agent-executor.d.ts +4 -2
  3. package/dist/lib/agents/agent-executor.d.ts.map +1 -1
  4. package/dist/lib/agents/agent-executor.js +85 -53
  5. package/dist/lib/agents/agent-executor.js.map +1 -1
  6. package/dist/lib/agents/agent-loader.d.ts +3 -0
  7. package/dist/lib/agents/agent-loader.d.ts.map +1 -1
  8. package/dist/lib/agents/agent-loader.js +10 -1
  9. package/dist/lib/agents/agent-loader.js.map +1 -1
  10. package/dist/lib/agents/react-loop.d.ts.map +1 -1
  11. package/dist/lib/agents/react-loop.js +207 -142
  12. package/dist/lib/agents/react-loop.js.map +1 -1
  13. package/dist/lib/agents/types.d.ts +181 -18
  14. package/dist/lib/agents/types.d.ts.map +1 -1
  15. package/dist/lib/agents/types.js +18 -2
  16. package/dist/lib/agents/types.js.map +1 -1
  17. package/dist/lib/functions/function-loader.d.ts +2 -0
  18. package/dist/lib/functions/function-loader.d.ts.map +1 -1
  19. package/dist/lib/functions/function-loader.js +10 -0
  20. package/dist/lib/functions/function-loader.js.map +1 -1
  21. package/dist/lib/functions/simple-function-wrapper.js +3 -3
  22. package/dist/lib/functions/simple-function-wrapper.js.map +1 -1
  23. package/dist/lib/integrations/email.d.ts +38 -0
  24. package/dist/lib/integrations/email.d.ts.map +1 -0
  25. package/dist/lib/integrations/email.js +249 -0
  26. package/dist/lib/integrations/email.js.map +1 -0
  27. package/dist/lib/integrations/integration-manager.d.ts +5 -0
  28. package/dist/lib/integrations/integration-manager.d.ts.map +1 -1
  29. package/dist/lib/integrations/integration-manager.js +53 -3
  30. package/dist/lib/integrations/integration-manager.js.map +1 -1
  31. package/dist/lib/integrations/types.d.ts +187 -4
  32. package/dist/lib/integrations/types.d.ts.map +1 -1
  33. package/dist/lib/integrations/types.js +24 -1
  34. package/dist/lib/integrations/types.js.map +1 -1
  35. package/dist/lib/knowledge/knowledge-store.d.ts +7 -1
  36. package/dist/lib/knowledge/knowledge-store.d.ts.map +1 -1
  37. package/dist/lib/knowledge/knowledge-store.js +96 -8
  38. package/dist/lib/knowledge/knowledge-store.js.map +1 -1
  39. package/dist/lib/knowledge/loaders/file-loaders.d.ts +8 -3
  40. package/dist/lib/knowledge/loaders/file-loaders.d.ts.map +1 -1
  41. package/dist/lib/knowledge/loaders/file-loaders.js +96 -75
  42. package/dist/lib/knowledge/loaders/file-loaders.js.map +1 -1
  43. package/dist/lib/knowledge/loaders/web-loader.d.ts +12 -3
  44. package/dist/lib/knowledge/loaders/web-loader.d.ts.map +1 -1
  45. package/dist/lib/knowledge/loaders/web-loader.js +56 -22
  46. package/dist/lib/knowledge/loaders/web-loader.js.map +1 -1
  47. package/dist/lib/knowledge/sqlite-store.d.ts.map +1 -1
  48. package/dist/lib/knowledge/sqlite-store.js +19 -10
  49. package/dist/lib/knowledge/sqlite-store.js.map +1 -1
  50. package/dist/lib/knowledge/types.d.ts +69 -33
  51. package/dist/lib/knowledge/types.d.ts.map +1 -1
  52. package/dist/lib/knowledge/types.js +18 -3
  53. package/dist/lib/knowledge/types.js.map +1 -1
  54. package/dist/lib/llm/index.d.ts +1 -1
  55. package/dist/lib/llm/index.d.ts.map +1 -1
  56. package/dist/lib/llm/index.js +1 -1
  57. package/dist/lib/llm/index.js.map +1 -1
  58. package/dist/lib/llm/llm-call-logger.d.ts +3 -1
  59. package/dist/lib/llm/llm-call-logger.d.ts.map +1 -1
  60. package/dist/lib/llm/llm-call-logger.js +31 -26
  61. package/dist/lib/llm/llm-call-logger.js.map +1 -1
  62. package/dist/lib/llm/llm-config.d.ts +59 -8
  63. package/dist/lib/llm/llm-config.d.ts.map +1 -1
  64. package/dist/lib/llm/llm-config.js +163 -17
  65. package/dist/lib/llm/llm-config.js.map +1 -1
  66. package/dist/lib/llm/llm-factory.d.ts +1 -2
  67. package/dist/lib/llm/llm-factory.d.ts.map +1 -1
  68. package/dist/lib/llm/llm-factory.js +44 -8
  69. package/dist/lib/llm/llm-factory.js.map +1 -1
  70. package/dist/lib/llm/providers/anthropic-chat-model.d.ts +5 -1
  71. package/dist/lib/llm/providers/anthropic-chat-model.d.ts.map +1 -1
  72. package/dist/lib/llm/providers/anthropic-chat-model.js +118 -42
  73. package/dist/lib/llm/providers/anthropic-chat-model.js.map +1 -1
  74. package/dist/lib/llm/providers/gemini-chat-model.d.ts +3 -2
  75. package/dist/lib/llm/providers/gemini-chat-model.d.ts.map +1 -1
  76. package/dist/lib/llm/providers/gemini-chat-model.js +83 -24
  77. package/dist/lib/llm/providers/gemini-chat-model.js.map +1 -1
  78. package/dist/lib/llm/providers/openai-chat-model.d.ts +20 -1
  79. package/dist/lib/llm/providers/openai-chat-model.d.ts.map +1 -1
  80. package/dist/lib/llm/providers/openai-chat-model.js +265 -32
  81. package/dist/lib/llm/providers/openai-chat-model.js.map +1 -1
  82. package/dist/lib/llm/providers/openai-embeddings.d.ts.map +1 -1
  83. package/dist/lib/llm/providers/openai-embeddings.js +41 -10
  84. package/dist/lib/llm/providers/openai-embeddings.js.map +1 -1
  85. package/dist/lib/local-llm/binary-manager.d.ts +66 -0
  86. package/dist/lib/local-llm/binary-manager.d.ts.map +1 -0
  87. package/dist/lib/local-llm/binary-manager.js +441 -0
  88. package/dist/lib/local-llm/binary-manager.js.map +1 -0
  89. package/dist/lib/local-llm/engine-interface.d.ts +47 -0
  90. package/dist/lib/local-llm/engine-interface.d.ts.map +1 -0
  91. package/dist/lib/local-llm/engine-interface.js +2 -0
  92. package/dist/lib/local-llm/engine-interface.js.map +1 -0
  93. package/dist/lib/local-llm/engine-registry.d.ts +20 -0
  94. package/dist/lib/local-llm/engine-registry.d.ts.map +1 -0
  95. package/dist/lib/local-llm/engine-registry.js +56 -0
  96. package/dist/lib/local-llm/engine-registry.js.map +1 -0
  97. package/dist/lib/local-llm/engines/llama-cpp-engine.d.ts +31 -0
  98. package/dist/lib/local-llm/engines/llama-cpp-engine.d.ts.map +1 -0
  99. package/dist/lib/local-llm/engines/llama-cpp-engine.js +164 -0
  100. package/dist/lib/local-llm/engines/llama-cpp-engine.js.map +1 -0
  101. package/dist/lib/local-llm/engines/mlx-serve-engine.d.ts +31 -0
  102. package/dist/lib/local-llm/engines/mlx-serve-engine.d.ts.map +1 -0
  103. package/dist/lib/local-llm/engines/mlx-serve-engine.js +161 -0
  104. package/dist/lib/local-llm/engines/mlx-serve-engine.js.map +1 -0
  105. package/dist/lib/local-llm/gguf-reader.d.ts +20 -0
  106. package/dist/lib/local-llm/gguf-reader.d.ts.map +1 -0
  107. package/dist/lib/local-llm/gguf-reader.js +190 -0
  108. package/dist/lib/local-llm/gguf-reader.js.map +1 -0
  109. package/dist/lib/local-llm/index.d.ts +9 -0
  110. package/dist/lib/local-llm/index.d.ts.map +1 -0
  111. package/dist/lib/local-llm/index.js +6 -0
  112. package/dist/lib/local-llm/index.js.map +1 -0
  113. package/dist/lib/local-llm/llama-server-process.d.ts +42 -0
  114. package/dist/lib/local-llm/llama-server-process.d.ts.map +1 -0
  115. package/dist/lib/local-llm/llama-server-process.js +237 -0
  116. package/dist/lib/local-llm/llama-server-process.js.map +1 -0
  117. package/dist/lib/local-llm/mlx-binary-manager.d.ts +33 -0
  118. package/dist/lib/local-llm/mlx-binary-manager.d.ts.map +1 -0
  119. package/dist/lib/local-llm/mlx-binary-manager.js +211 -0
  120. package/dist/lib/local-llm/mlx-binary-manager.js.map +1 -0
  121. package/dist/lib/local-llm/mlx-server-process.d.ts +26 -0
  122. package/dist/lib/local-llm/mlx-server-process.d.ts.map +1 -0
  123. package/dist/lib/local-llm/mlx-server-process.js +210 -0
  124. package/dist/lib/local-llm/mlx-server-process.js.map +1 -0
  125. package/dist/lib/local-llm/model-manager.d.ts +33 -0
  126. package/dist/lib/local-llm/model-manager.d.ts.map +1 -0
  127. package/dist/lib/local-llm/model-manager.js +591 -0
  128. package/dist/lib/local-llm/model-manager.js.map +1 -0
  129. package/dist/lib/local-llm/types.d.ts +51 -0
  130. package/dist/lib/local-llm/types.d.ts.map +1 -0
  131. package/dist/lib/local-llm/types.js +2 -0
  132. package/dist/lib/local-llm/types.js.map +1 -0
  133. package/dist/lib/logger.d.ts +2 -0
  134. package/dist/lib/logger.d.ts.map +1 -1
  135. package/dist/lib/logger.js +68 -6
  136. package/dist/lib/logger.js.map +1 -1
  137. package/dist/lib/mcp/mcp-client.d.ts.map +1 -1
  138. package/dist/lib/mcp/mcp-client.js +5 -3
  139. package/dist/lib/mcp/mcp-client.js.map +1 -1
  140. package/dist/lib/mcp/types.d.ts +0 -9
  141. package/dist/lib/mcp/types.d.ts.map +1 -1
  142. package/dist/lib/mcp/types.js +1 -2
  143. package/dist/lib/mcp/types.js.map +1 -1
  144. package/dist/lib/memory/memory-manager.d.ts +1 -0
  145. package/dist/lib/memory/memory-manager.d.ts.map +1 -1
  146. package/dist/lib/memory/memory-manager.js +9 -0
  147. package/dist/lib/memory/memory-manager.js.map +1 -1
  148. package/dist/lib/orchestrator.d.ts +11 -8
  149. package/dist/lib/orchestrator.d.ts.map +1 -1
  150. package/dist/lib/orchestrator.js +246 -5
  151. package/dist/lib/orchestrator.js.map +1 -1
  152. package/dist/lib/sandbox/cdp-client.d.ts +15 -0
  153. package/dist/lib/sandbox/cdp-client.d.ts.map +1 -0
  154. package/dist/lib/sandbox/cdp-client.js +139 -0
  155. package/dist/lib/sandbox/cdp-client.js.map +1 -0
  156. package/dist/lib/sandbox/html-to-markdown.d.ts +9 -1
  157. package/dist/lib/sandbox/html-to-markdown.d.ts.map +1 -1
  158. package/dist/lib/sandbox/html-to-markdown.js +67 -10
  159. package/dist/lib/sandbox/html-to-markdown.js.map +1 -1
  160. package/dist/lib/sandbox/index.d.ts +6 -0
  161. package/dist/lib/sandbox/index.d.ts.map +1 -1
  162. package/dist/lib/sandbox/index.js +5 -0
  163. package/dist/lib/sandbox/index.js.map +1 -1
  164. package/dist/lib/sandbox/page-readiness.d.ts +37 -0
  165. package/dist/lib/sandbox/page-readiness.d.ts.map +1 -0
  166. package/dist/lib/sandbox/page-readiness.js +268 -0
  167. package/dist/lib/sandbox/page-readiness.js.map +1 -0
  168. package/dist/lib/sandbox/sandbox-browser.d.ts +4 -0
  169. package/dist/lib/sandbox/sandbox-browser.d.ts.map +1 -0
  170. package/dist/lib/sandbox/sandbox-browser.js +316 -0
  171. package/dist/lib/sandbox/sandbox-browser.js.map +1 -0
  172. package/dist/lib/sandbox/sandbox-container.d.ts +39 -0
  173. package/dist/lib/sandbox/sandbox-container.d.ts.map +1 -0
  174. package/dist/lib/sandbox/sandbox-container.js +176 -0
  175. package/dist/lib/sandbox/sandbox-container.js.map +1 -0
  176. package/dist/lib/sandbox/sandbox-file.d.ts +4 -0
  177. package/dist/lib/sandbox/sandbox-file.d.ts.map +1 -0
  178. package/dist/lib/sandbox/sandbox-file.js +169 -0
  179. package/dist/lib/sandbox/sandbox-file.js.map +1 -0
  180. package/dist/lib/sandbox/sandbox-shell.d.ts +5 -0
  181. package/dist/lib/sandbox/sandbox-shell.d.ts.map +1 -0
  182. package/dist/lib/sandbox/sandbox-shell.js +111 -0
  183. package/dist/lib/sandbox/sandbox-shell.js.map +1 -0
  184. package/dist/lib/sandbox/sandbox-web.d.ts.map +1 -1
  185. package/dist/lib/sandbox/sandbox-web.js +64 -24
  186. package/dist/lib/sandbox/sandbox-web.js.map +1 -1
  187. package/dist/lib/sandbox/types.d.ts +9 -0
  188. package/dist/lib/sandbox/types.d.ts.map +1 -1
  189. package/dist/lib/sandbox/types.js +1 -0
  190. package/dist/lib/sandbox/types.js.map +1 -1
  191. package/dist/lib/sandbox/vision-browser.d.ts +4 -0
  192. package/dist/lib/sandbox/vision-browser.d.ts.map +1 -0
  193. package/dist/lib/sandbox/vision-browser.js +298 -0
  194. package/dist/lib/sandbox/vision-browser.js.map +1 -0
  195. package/dist/lib/sea/app-window.d.ts +7 -0
  196. package/dist/lib/sea/app-window.d.ts.map +1 -0
  197. package/dist/lib/sea/app-window.js +95 -0
  198. package/dist/lib/sea/app-window.js.map +1 -0
  199. package/dist/lib/sea/bootstrap.d.ts +18 -0
  200. package/dist/lib/sea/bootstrap.d.ts.map +1 -0
  201. package/dist/lib/sea/bootstrap.js +103 -0
  202. package/dist/lib/sea/bootstrap.js.map +1 -0
  203. package/dist/lib/sea/sqlite-vec-shim.d.ts +3 -0
  204. package/dist/lib/sea/sqlite-vec-shim.d.ts.map +1 -0
  205. package/dist/lib/sea/sqlite-vec-shim.js +10 -0
  206. package/dist/lib/sea/sqlite-vec-shim.js.map +1 -0
  207. package/dist/lib/skills/skill-loader.d.ts +2 -0
  208. package/dist/lib/skills/skill-loader.d.ts.map +1 -1
  209. package/dist/lib/skills/skill-loader.js +12 -1
  210. package/dist/lib/skills/skill-loader.js.map +1 -1
  211. package/dist/lib/tasks/task-manager.d.ts +3 -1
  212. package/dist/lib/tasks/task-manager.d.ts.map +1 -1
  213. package/dist/lib/tasks/task-manager.js +11 -0
  214. package/dist/lib/tasks/task-manager.js.map +1 -1
  215. package/dist/lib/tasks/task-store.d.ts +1 -1
  216. package/dist/lib/tasks/task-store.d.ts.map +1 -1
  217. package/dist/lib/tasks/task-store.js.map +1 -1
  218. package/dist/lib/tasks/types.d.ts +18 -0
  219. package/dist/lib/tasks/types.d.ts.map +1 -1
  220. package/dist/lib/tools/built-in/integration-tools.d.ts +4 -0
  221. package/dist/lib/tools/built-in/integration-tools.d.ts.map +1 -0
  222. package/dist/lib/tools/built-in/integration-tools.js +47 -0
  223. package/dist/lib/tools/built-in/integration-tools.js.map +1 -0
  224. package/dist/lib/tools/built-in/knowledge-entity-lookup.tool.d.ts +1 -2
  225. package/dist/lib/tools/built-in/knowledge-entity-lookup.tool.d.ts.map +1 -1
  226. package/dist/lib/tools/built-in/knowledge-entity-lookup.tool.js +17 -17
  227. package/dist/lib/tools/built-in/knowledge-entity-lookup.tool.js.map +1 -1
  228. package/dist/lib/tools/built-in/knowledge-graph-schema.tool.d.ts.map +1 -1
  229. package/dist/lib/tools/built-in/knowledge-graph-schema.tool.js +2 -4
  230. package/dist/lib/tools/built-in/knowledge-graph-schema.tool.js.map +1 -1
  231. package/dist/lib/tools/built-in/knowledge-search.tool.js +4 -4
  232. package/dist/lib/tools/built-in/knowledge-search.tool.js.map +1 -1
  233. package/dist/lib/tools/built-in/knowledge-sql.tool.d.ts.map +1 -1
  234. package/dist/lib/tools/built-in/knowledge-sql.tool.js +74 -40
  235. package/dist/lib/tools/built-in/knowledge-sql.tool.js.map +1 -1
  236. package/dist/lib/tools/built-in/knowledge-tools-factory.js +2 -2
  237. package/dist/lib/tools/built-in/knowledge-tools-factory.js.map +1 -1
  238. package/dist/lib/tools/built-in/knowledge-traverse.tool.d.ts +1 -2
  239. package/dist/lib/tools/built-in/knowledge-traverse.tool.d.ts.map +1 -1
  240. package/dist/lib/tools/built-in/knowledge-traverse.tool.js +5 -11
  241. package/dist/lib/tools/built-in/knowledge-traverse.tool.js.map +1 -1
  242. package/dist/lib/tools/built-in/query-validators.d.ts.map +1 -1
  243. package/dist/lib/tools/built-in/query-validators.js +4 -0
  244. package/dist/lib/tools/built-in/query-validators.js.map +1 -1
  245. package/dist/lib/tools/workspace/workspace-tools.d.ts +1 -0
  246. package/dist/lib/tools/workspace/workspace-tools.d.ts.map +1 -1
  247. package/dist/lib/tools/workspace/workspace-tools.js +44 -4
  248. package/dist/lib/tools/workspace/workspace-tools.js.map +1 -1
  249. package/dist/lib/triggers/cron-trigger.d.ts +1 -1
  250. package/dist/lib/triggers/cron-trigger.d.ts.map +1 -1
  251. package/dist/lib/triggers/cron-trigger.js.map +1 -1
  252. package/dist/lib/triggers/trigger-manager.d.ts +1 -0
  253. package/dist/lib/triggers/trigger-manager.d.ts.map +1 -1
  254. package/dist/lib/triggers/trigger-manager.js +26 -0
  255. package/dist/lib/triggers/trigger-manager.js.map +1 -1
  256. package/dist/lib/triggers/webhook-trigger.d.ts +1 -1
  257. package/dist/lib/triggers/webhook-trigger.d.ts.map +1 -1
  258. package/dist/lib/triggers/webhook-trigger.js.map +1 -1
  259. package/dist/lib/types/llm-types.d.ts +22 -4
  260. package/dist/lib/types/llm-types.d.ts.map +1 -1
  261. package/dist/lib/types/llm-types.js +50 -0
  262. package/dist/lib/types/llm-types.js.map +1 -1
  263. package/dist/lib/types/tool-factory.d.ts +2 -2
  264. package/dist/lib/types/tool-factory.d.ts.map +1 -1
  265. package/dist/lib/types/tool-factory.js +9 -2
  266. package/dist/lib/types/tool-factory.js.map +1 -1
  267. package/dist/lib/utils/document-extract.d.ts +10 -0
  268. package/dist/lib/utils/document-extract.d.ts.map +1 -0
  269. package/dist/lib/utils/document-extract.js +149 -0
  270. package/dist/lib/utils/document-extract.js.map +1 -0
  271. package/dist/lib/utils/env-substitution.d.ts +6 -0
  272. package/dist/lib/utils/env-substitution.d.ts.map +1 -0
  273. package/dist/lib/utils/env-substitution.js +15 -0
  274. package/dist/lib/utils/env-substitution.js.map +1 -0
  275. package/dist/lib/workflows/react-workflow-executor.d.ts.map +1 -1
  276. package/dist/lib/workflows/react-workflow-executor.js +23 -17
  277. package/dist/lib/workflows/react-workflow-executor.js.map +1 -1
  278. package/dist/lib/workflows/types.d.ts +81 -55
  279. package/dist/lib/workflows/types.d.ts.map +1 -1
  280. package/dist/lib/workflows/types.js +10 -0
  281. package/dist/lib/workflows/types.js.map +1 -1
  282. package/dist/lib/workflows/workflow-loader.d.ts +3 -0
  283. package/dist/lib/workflows/workflow-loader.d.ts.map +1 -1
  284. package/dist/lib/workflows/workflow-loader.js +10 -1
  285. package/dist/lib/workflows/workflow-loader.js.map +1 -1
  286. package/dist/public/assets/logo.png +0 -0
  287. package/dist/public/chat.html +39 -0
  288. package/dist/public/index.html +6 -176
  289. package/dist/public/src/components/AgentComposer.js +807 -0
  290. package/dist/public/src/components/AgentsView.js +1812 -508
  291. package/dist/public/src/components/AppRoot.js +125 -38
  292. package/dist/public/src/components/GraphView.js +382 -300
  293. package/dist/public/src/components/IdeView.js +277 -86
  294. package/dist/public/src/components/KnowledgeView.js +94 -130
  295. package/dist/public/src/components/LlmView.js +15 -19
  296. package/dist/public/src/components/LocalLlmView.js +2440 -0
  297. package/dist/public/src/components/LogViewer.js +155 -0
  298. package/dist/public/src/components/McpView.js +41 -49
  299. package/dist/public/src/components/MonitorView.js +174 -83
  300. package/dist/public/src/components/NavBar.js +16 -26
  301. package/dist/public/src/components/StandaloneChat.js +875 -0
  302. package/dist/public/src/services/ApiService.js +203 -4
  303. package/dist/public/src/services/SessionStore.js +86 -0
  304. package/dist/public/src/services/StreamManager.js +183 -0
  305. package/dist/public/src/store.js +1 -3
  306. package/dist/public/src/utils/card.js +21 -0
  307. package/dist/public/src/utils/markdown.js +7 -0
  308. package/dist/public/styles.css +2777 -0
  309. package/dist/src/cli/commands/init.d.ts.map +1 -1
  310. package/dist/src/cli/commands/init.js +7 -1
  311. package/dist/src/cli/commands/init.js.map +1 -1
  312. package/dist/src/cli/commands/start.d.ts.map +1 -1
  313. package/dist/src/cli/commands/start.js +28 -5
  314. package/dist/src/cli/commands/start.js.map +1 -1
  315. package/dist/src/cli/index.js +19 -5
  316. package/dist/src/cli/index.js.map +1 -1
  317. package/dist/src/index.js +7 -1
  318. package/dist/src/index.js.map +1 -1
  319. package/dist/src/middleware/auth.d.ts.map +1 -1
  320. package/dist/src/middleware/auth.js +28 -6
  321. package/dist/src/middleware/auth.js.map +1 -1
  322. package/dist/src/middleware/rate-limit.d.ts +8 -0
  323. package/dist/src/middleware/rate-limit.d.ts.map +1 -0
  324. package/dist/src/middleware/rate-limit.js +21 -0
  325. package/dist/src/middleware/rate-limit.js.map +1 -0
  326. package/dist/src/routes/agents.route.d.ts.map +1 -1
  327. package/dist/src/routes/agents.route.js +138 -10
  328. package/dist/src/routes/agents.route.js.map +1 -1
  329. package/dist/src/routes/chat.route.d.ts +3 -0
  330. package/dist/src/routes/chat.route.d.ts.map +1 -0
  331. package/dist/src/routes/chat.route.js +156 -0
  332. package/dist/src/routes/chat.route.js.map +1 -0
  333. package/dist/src/routes/files.route.d.ts.map +1 -1
  334. package/dist/src/routes/files.route.js +37 -2
  335. package/dist/src/routes/files.route.js.map +1 -1
  336. package/dist/src/routes/llm.route.d.ts.map +1 -1
  337. package/dist/src/routes/llm.route.js +263 -8
  338. package/dist/src/routes/llm.route.js.map +1 -1
  339. package/dist/src/routes/local-llm.route.d.ts +3 -0
  340. package/dist/src/routes/local-llm.route.d.ts.map +1 -0
  341. package/dist/src/routes/local-llm.route.js +688 -0
  342. package/dist/src/routes/local-llm.route.js.map +1 -0
  343. package/dist/src/routes/logs.route.d.ts +3 -0
  344. package/dist/src/routes/logs.route.d.ts.map +1 -0
  345. package/dist/src/routes/logs.route.js +24 -0
  346. package/dist/src/routes/logs.route.js.map +1 -0
  347. package/dist/src/routes/tasks.route.d.ts.map +1 -1
  348. package/dist/src/routes/tasks.route.js +15 -1
  349. package/dist/src/routes/tasks.route.js.map +1 -1
  350. package/dist/src/routes/vnc.route.d.ts +12 -0
  351. package/dist/src/routes/vnc.route.d.ts.map +1 -0
  352. package/dist/src/routes/vnc.route.js +74 -0
  353. package/dist/src/routes/vnc.route.js.map +1 -0
  354. package/dist/src/routes/workflows.route.d.ts.map +1 -1
  355. package/dist/src/routes/workflows.route.js +24 -0
  356. package/dist/src/routes/workflows.route.js.map +1 -1
  357. package/dist/src/server.d.ts.map +1 -1
  358. package/dist/src/server.js +29 -3
  359. package/dist/src/server.js.map +1 -1
  360. package/dist/templates/Demo.md +152 -0
  361. package/dist/templates/README.md +12 -3
  362. package/dist/templates/agents/actor.agent.yaml +34 -0
  363. package/dist/templates/agents/architect.agent.yaml +20 -13
  364. package/dist/templates/agents/chatbot.agent.yaml +23 -27
  365. package/dist/templates/agents/corporate.agent.yaml +64 -0
  366. package/dist/templates/agents/functions.agent.yaml +29 -0
  367. package/dist/templates/agents/investment-analyst.agent.yaml +79 -0
  368. package/dist/templates/agents/music-librarian.agent.yaml +46 -0
  369. package/dist/templates/agents/network-security.agent.yaml +81 -0
  370. package/dist/templates/agents/transport-security.agent.yaml +69 -0
  371. package/dist/templates/agents/web-engineer.agent.yaml +98 -0
  372. package/dist/templates/agents/web-pilot.agent.yaml +57 -0
  373. package/dist/templates/knowledge/music-store/LICENSE.md +11 -0
  374. package/dist/templates/knowledge/music-store/musicstore.sqlite +0 -0
  375. package/dist/templates/knowledge/music-store/tables.png +0 -0
  376. package/dist/templates/knowledge/music-store.knowledge.yaml +138 -0
  377. package/dist/templates/knowledge/org-chart/personnel.csv +21 -21
  378. package/dist/templates/knowledge/org-chart.knowledge.yaml +4 -0
  379. package/dist/templates/knowledge/patient-records.knowledge.yaml +20 -0
  380. package/dist/templates/knowledge/pdf-patients/PDF_Deid_Deidentification_0.pdf +0 -0
  381. package/dist/templates/knowledge/pdf-patients/PDF_Deid_Deidentification_1.pdf +0 -0
  382. package/dist/templates/knowledge/pdf-patients/PDF_Deid_Deidentification_10.pdf +0 -0
  383. package/dist/templates/knowledge/pdf-patients/PDF_Deid_Deidentification_11.pdf +0 -0
  384. package/dist/templates/knowledge/pet-store.knowledge.yaml +3 -0
  385. package/dist/templates/knowledge/security-incidents/incidents.json +55935 -0
  386. package/dist/templates/knowledge/security-incidents.knowledge.yaml +46 -0
  387. package/dist/templates/knowledge/{example.knowledge.yaml → transcripts.knowledge.yaml} +9 -5
  388. package/dist/templates/knowledge/transport-ot/systems.csv +117 -0
  389. package/dist/templates/knowledge/transport-ot.knowledge.yaml +55 -0
  390. package/dist/templates/knowledge/web-docs.knowledge.yaml +1 -1
  391. package/dist/templates/llm.json +62 -22
  392. package/dist/templates/mcp.json +7 -4
  393. package/dist/templates/skills/orcha-builder/SKILL.md +148 -215
  394. package/dist/templates/skills/pii-guard/SKILL.md +22 -0
  395. package/dist/templates/skills/sandbox/SKILL.md +25 -48
  396. package/dist/templates/skills/web-pilot/SKILL.md +51 -0
  397. package/dist/templates/workflows/example.workflow.yaml +27 -35
  398. package/dist/templates/workflows/react-example.workflow.yaml +14 -19
  399. package/dist/templates/workflows/team-chat.workflow.yaml +47 -0
  400. package/package.json +17 -4
  401. package/dist/public/src/components/SkillsView.js +0 -137
  402. package/dist/public/src/components/WorkflowsView.js +0 -416
  403. package/dist/templates/agents/knowledge-broker.agent.yaml +0 -39
  404. package/dist/templates/agents/sandbox.agent.yaml +0 -56
@@ -0,0 +1,875 @@
1
+ class StandaloneChat extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ this.agentName = '';
5
+ this.agentConfig = null;
6
+ this.isLoading = false;
7
+ this.currentAbortController = null;
8
+ this.streamStartTime = null;
9
+ this.streamTimerInterval = null;
10
+ this.streamUsageData = null;
11
+ this.pendingAttachments = [];
12
+ }
13
+
14
+ connectedCallback() {
15
+ // Extract agent name from URL: /chat/:agentName
16
+ const parts = window.location.pathname.split('/');
17
+ this.agentName = parts[parts.length - 1] || '';
18
+
19
+ if (!this.agentName) {
20
+ this.innerHTML = '<div class="auth-overlay"><span class="text-secondary">Invalid agent URL</span></div>';
21
+ return;
22
+ }
23
+
24
+ this.sessionId = sessionStorage.getItem(`chat-session-${this.agentName}`) || this.generateSessionId();
25
+ sessionStorage.setItem(`chat-session-${this.agentName}`, this.sessionId);
26
+
27
+ this.loadConfig();
28
+ }
29
+
30
+ generateSessionId() {
31
+ return 'chat-' + Date.now() + '-' + Math.random().toString(36).slice(2, 8);
32
+ }
33
+
34
+ getToken() {
35
+ return sessionStorage.getItem(`chat-token-${this.agentName}`);
36
+ }
37
+
38
+ setToken(token) {
39
+ sessionStorage.setItem(`chat-token-${this.agentName}`, token);
40
+ }
41
+
42
+ async loadConfig() {
43
+ try {
44
+ const res = await fetch(`/api/chat/${this.agentName}/config`);
45
+ if (!res.ok) {
46
+ this.innerHTML = '<div class="auth-overlay"><span class="text-secondary">Agent not found or not published</span></div>';
47
+ return;
48
+ }
49
+ this.agentConfig = await res.json();
50
+ document.title = `${this.agentConfig.name} — Agent Orcha`;
51
+
52
+ if (this.agentConfig.requiresPassword && !this.getToken()) {
53
+ this.renderPasswordOverlay();
54
+ } else {
55
+ this.renderChat();
56
+ }
57
+ } catch {
58
+ this.innerHTML = '<div class="auth-overlay"><span class="text-secondary">Failed to load agent</span></div>';
59
+ }
60
+ }
61
+
62
+ // --- Password overlay ---
63
+
64
+ renderPasswordOverlay() {
65
+ this.innerHTML = `
66
+ <div class="auth-overlay">
67
+ <div class="auth-card">
68
+ <div class="text-center mb-6">
69
+ <i class="fas fa-lock text-2xl text-muted mb-3"></i>
70
+ <h2 class="text-lg font-semibold text-primary">${this.escapeHtml(this.agentConfig.name)}</h2>
71
+ <p class="text-sm text-secondary mt-1">This agent requires a password</p>
72
+ </div>
73
+ <div id="authError" class="hidden text-sm text-red text-center mb-3"></div>
74
+ <div class="relative">
75
+ <input id="passwordInput" type="password" class="input w-full"
76
+ placeholder="Enter password">
77
+ </div>
78
+ <button id="authBtn" class="btn btn-accent w-full mt-4">
79
+ Continue
80
+ </button>
81
+ </div>
82
+ </div>
83
+ `;
84
+
85
+ const passwordInput = this.querySelector('#passwordInput');
86
+ const authBtn = this.querySelector('#authBtn');
87
+
88
+ authBtn.addEventListener('click', () => this.authenticate());
89
+ passwordInput.addEventListener('keydown', (e) => {
90
+ if (e.key === 'Enter') this.authenticate();
91
+ });
92
+ passwordInput.focus();
93
+ }
94
+
95
+ async authenticate() {
96
+ const passwordInput = this.querySelector('#passwordInput');
97
+ const authError = this.querySelector('#authError');
98
+ const password = passwordInput.value;
99
+
100
+ if (!password) return;
101
+
102
+ try {
103
+ const res = await fetch(`/api/chat/${this.agentName}/auth`, {
104
+ method: 'POST',
105
+ headers: { 'Content-Type': 'application/json' },
106
+ body: JSON.stringify({ password }),
107
+ });
108
+
109
+ if (!res.ok) {
110
+ authError.textContent = 'Invalid password';
111
+ authError.classList.remove('hidden');
112
+ passwordInput.value = '';
113
+ passwordInput.focus();
114
+ return;
115
+ }
116
+
117
+ const { token } = await res.json();
118
+ this.setToken(token);
119
+ this.renderChat();
120
+ } catch {
121
+ authError.textContent = 'Authentication failed';
122
+ authError.classList.remove('hidden');
123
+ }
124
+ }
125
+
126
+ // --- Chat UI ---
127
+
128
+ renderChat() {
129
+ const desc = this.agentConfig.description
130
+ ? `<p class="text-xs text-muted truncate">${this.escapeHtml(this.agentConfig.description)}</p>`
131
+ : '';
132
+
133
+ this.innerHTML = `
134
+ <div class="standalone-shell">
135
+ <!-- Header -->
136
+ <div class="standalone-header">
137
+ <i class="fas fa-robot text-accent"></i>
138
+ <div class="min-w-0">
139
+ <h1 class="text-sm font-semibold text-primary">${this.escapeHtml(this.agentConfig.name)}</h1>
140
+ ${desc}
141
+ </div>
142
+ </div>
143
+
144
+ <!-- Messages -->
145
+ <div id="chatMessages" class="chat-messages custom-scrollbar">
146
+ ${this.renderSampleQuestions()}
147
+ </div>
148
+
149
+ <!-- Input -->
150
+ <div class="chat-input-area">
151
+ <div id="attachmentPreview" class="attachment-preview"></div>
152
+ <div class="chat-input-wrap">
153
+ <input type="file" id="fileInput" multiple accept="image/*,.pdf,.doc,.docx,.xls,.xlsx,.pptx,.txt,.md,.csv,.json,.yaml,.yml,.xml,.html,.css,.js,.ts,.py,.java,.c,.cpp,.go,.rs,.rb,.php,.sql,.sh,.log,.ini,.toml,.env" class="hidden">
154
+ <textarea id="chatInput" rows="1"
155
+ placeholder="Type a message..."></textarea>
156
+ <div class="chat-input-actions left">
157
+ <button id="attachBtn" type="button" class="attach-btn" title="Attach files">
158
+ <i class="fas fa-plus text-sm"></i>
159
+ </button>
160
+ </div>
161
+ <div class="chat-input-actions right">
162
+ <button id="sendBtn" class="send-btn">
163
+ <i class="fas fa-paper-plane text-sm"></i>
164
+ </button>
165
+ </div>
166
+ </div>
167
+ </div>
168
+ </div>
169
+ `;
170
+
171
+ this.bindChatEvents();
172
+ }
173
+
174
+ renderSampleQuestions() {
175
+ const questions = this.agentConfig.sampleQuestions;
176
+ if (!questions || questions.length === 0) return '';
177
+
178
+ const chips = questions.map(q =>
179
+ `<button class="sample-question-chip">${this.escapeHtml(q)}</button>`
180
+ ).join('');
181
+
182
+ return `
183
+ <div id="sampleQuestions" class="welcome-container">
184
+ <p class="text-muted text-sm">Try asking</p>
185
+ <div class="sample-questions-wrap">${chips}</div>
186
+ </div>
187
+ `;
188
+ }
189
+
190
+ bindChatEvents() {
191
+ const input = this.querySelector('#chatInput');
192
+ const sendBtn = this.querySelector('#sendBtn');
193
+
194
+ input.addEventListener('input', () => {
195
+ input.style.height = 'auto';
196
+ input.style.height = Math.min(input.scrollHeight, 200) + 'px';
197
+ });
198
+
199
+ input.addEventListener('keydown', (e) => {
200
+ if (e.key === 'Enter' && !e.shiftKey) {
201
+ e.preventDefault();
202
+ this.sendMessage();
203
+ }
204
+ });
205
+
206
+ sendBtn.addEventListener('click', () => this.sendMessage());
207
+
208
+ this.querySelector('#attachBtn').addEventListener('click', () => this.querySelector('#fileInput').click());
209
+ this.querySelector('#fileInput').addEventListener('change', (e) => this.handleFileSelect(e));
210
+
211
+ this.querySelectorAll('.sample-question-chip').forEach(chip => {
212
+ chip.addEventListener('click', () => {
213
+ input.value = chip.textContent;
214
+ input.focus();
215
+ });
216
+ });
217
+
218
+ input.focus();
219
+ }
220
+
221
+ // --- File Attachments ---
222
+
223
+ handleFileSelect(e) {
224
+ const files = Array.from(e.target.files);
225
+ e.target.value = '';
226
+ const needsConversion = ['image/webp', 'image/bmp', 'image/tiff'];
227
+
228
+ for (const file of files) {
229
+ if (needsConversion.includes(file.type)) {
230
+ this.convertImageToJpeg(file);
231
+ } else {
232
+ const reader = new FileReader();
233
+ reader.onload = () => {
234
+ const dataUrl = reader.result;
235
+ const base64 = dataUrl.slice(dataUrl.indexOf(',') + 1);
236
+ this.pendingAttachments.push({ data: base64, mediaType: file.type || 'application/octet-stream', name: file.name });
237
+ this.renderAttachmentPreview();
238
+ };
239
+ reader.readAsDataURL(file);
240
+ }
241
+ }
242
+ }
243
+
244
+ convertImageToJpeg(file) {
245
+ const img = new Image();
246
+ const url = URL.createObjectURL(file);
247
+ img.onload = () => {
248
+ const canvas = document.createElement('canvas');
249
+ canvas.width = img.naturalWidth;
250
+ canvas.height = img.naturalHeight;
251
+ canvas.getContext('2d').drawImage(img, 0, 0);
252
+ URL.revokeObjectURL(url);
253
+ const dataUrl = canvas.toDataURL('image/jpeg', 0.92);
254
+ this.pendingAttachments.push({ data: dataUrl.split(',')[1], mediaType: 'image/jpeg', name: file.name });
255
+ this.renderAttachmentPreview();
256
+ };
257
+ img.src = url;
258
+ }
259
+
260
+ renderAttachmentPreview() {
261
+ const preview = this.querySelector('#attachmentPreview');
262
+ if (!preview) return;
263
+
264
+ if (this.pendingAttachments.length === 0) {
265
+ preview.classList.remove('visible');
266
+ preview.innerHTML = '';
267
+ return;
268
+ }
269
+
270
+ preview.classList.add('visible');
271
+ preview.innerHTML = this.pendingAttachments.map((att, i) => {
272
+ const isImage = att.mediaType.startsWith('image/');
273
+ const thumb = isImage
274
+ ? `<img src="data:${att.mediaType};base64,${att.data}">`
275
+ : `<i class="fas fa-file text-secondary text-lg"></i>`;
276
+ return `
277
+ <div class="attachment-pill">
278
+ ${thumb}
279
+ <span class="truncate attachment-name">${this.escapeHtml(att.name)}</span>
280
+ <button class="attachment-remove" data-index="${i}">
281
+ <i class="fas fa-xmark text-xs"></i>
282
+ </button>
283
+ </div>
284
+ `;
285
+ }).join('');
286
+
287
+ preview.querySelectorAll('.attachment-remove').forEach(btn => {
288
+ btn.addEventListener('click', (e) => {
289
+ this.pendingAttachments.splice(parseInt(e.currentTarget.dataset.index, 10), 1);
290
+ this.renderAttachmentPreview();
291
+ });
292
+ });
293
+ }
294
+
295
+ // --- Messaging ---
296
+
297
+ async sendMessage() {
298
+ const input = this.querySelector('#chatInput');
299
+ const message = input.value.trim();
300
+ const hasAttachments = this.pendingAttachments.length > 0;
301
+
302
+ if ((!message && !hasAttachments) || this.isLoading) return;
303
+
304
+ const attachments = hasAttachments ? [...this.pendingAttachments] : null;
305
+
306
+ const sampleQDiv = this.querySelector('#sampleQuestions');
307
+ if (sampleQDiv) sampleQDiv.remove();
308
+
309
+ this.appendUserMessage(message || '(attached files)', attachments);
310
+ input.value = '';
311
+ input.style.height = 'auto';
312
+ this.pendingAttachments = [];
313
+ this.renderAttachmentPreview();
314
+
315
+ this.isLoading = true;
316
+ this.updateUiState();
317
+
318
+ const responseId = 'response-' + Date.now();
319
+ this.createResponseBubble(responseId);
320
+
321
+ this.currentAbortController = new AbortController();
322
+ this.streamUsageData = null;
323
+ this.startStreamTimer(responseId);
324
+
325
+ let finalContent = '';
326
+ let wasCancelled = false;
327
+
328
+ try {
329
+ finalContent = await this.streamAgent(message, responseId, attachments);
330
+ } catch (e) {
331
+ if (e.name === 'AbortError') {
332
+ wasCancelled = true;
333
+ } else {
334
+ this.updateResponseError(responseId, `Error: ${e.message}`);
335
+ }
336
+ } finally {
337
+ this.stopStreamTimer(responseId, message, finalContent, wasCancelled);
338
+ this.currentAbortController = null;
339
+ this.isLoading = false;
340
+ this.updateUiState();
341
+ input.focus();
342
+ }
343
+ }
344
+
345
+ async streamAgent(message, responseId, attachments) {
346
+ const inputVars = this.agentConfig.inputVariables || ['message'];
347
+ const inputObj = {};
348
+ inputObj[inputVars[0] || 'message'] = message;
349
+ if (attachments) inputObj.attachments = attachments;
350
+
351
+ const headers = { 'Content-Type': 'application/json' };
352
+ const token = this.getToken();
353
+ if (token) headers['X-Chat-Token'] = token;
354
+
355
+ const res = await fetch(`/api/chat/${this.agentName}/stream`, {
356
+ method: 'POST',
357
+ headers,
358
+ body: JSON.stringify({ input: inputObj, sessionId: this.sessionId }),
359
+ signal: this.currentAbortController?.signal,
360
+ });
361
+
362
+ if (!res.ok) {
363
+ const err = await res.json().catch(() => ({ error: 'Request failed' }));
364
+ throw new Error(err.error || `HTTP ${res.status}`);
365
+ }
366
+
367
+ const reader = res.body.getReader();
368
+ const decoder = new TextDecoder();
369
+
370
+ const bubble = this.querySelector(`#${responseId}`);
371
+ const contentDiv = bubble.querySelector('.response-content');
372
+ const container = this.querySelector('#chatMessages');
373
+ const thinkingState = { inThinking: false, thinkingSections: [], currentSection: null, thinkingContent: '', thinkingPill: null };
374
+
375
+ let currentContent = '';
376
+ let buffer = '';
377
+ let hasToolCalls = false;
378
+
379
+ while (true) {
380
+ const { done, value } = await reader.read();
381
+ if (done) break;
382
+
383
+ buffer += decoder.decode(value, { stream: true });
384
+ const lines = buffer.split('\n');
385
+ buffer = lines.pop() || '';
386
+
387
+ for (const line of lines) {
388
+ if (line.trim() === '') continue;
389
+ if (!line.startsWith('data: ')) continue;
390
+
391
+ const data = line.slice(6);
392
+ if (data === '[DONE]') continue;
393
+
394
+ try {
395
+ const event = JSON.parse(data);
396
+
397
+ if (event.error) {
398
+ this.updateResponseError(responseId, `Error: ${event.error}`);
399
+ return currentContent;
400
+ }
401
+
402
+ if (event.type === 'content') currentContent += event.content;
403
+ if (event.type === 'tool_start' || event.type === 'tool_end') hasToolCalls = true;
404
+
405
+ this.handleStreamEvent(event, responseId, currentContent, thinkingState);
406
+ } catch (e) {
407
+ console.error('Error parsing stream event', e, data);
408
+ }
409
+ }
410
+ }
411
+
412
+ // Finalize any remaining thinking pill
413
+ const toolsDiv = bubble.querySelector('.tool-invocations');
414
+ this.finalizeThinkingPill(toolsDiv, thinkingState);
415
+
416
+ // If tools were called but no text content, clear loading state
417
+ if (hasToolCalls && !currentContent.trim()) {
418
+ const loadingDots = contentDiv.querySelector('.loading-dots');
419
+ if (loadingDots) {
420
+ loadingDots.remove();
421
+ bubble.querySelector('.response-bubble-inner').classList.remove('loading');
422
+ contentDiv.classList.remove('flex', 'items-center', 'whitespace-pre-wrap');
423
+ contentDiv.innerHTML = '';
424
+ }
425
+ }
426
+
427
+ return currentContent;
428
+ }
429
+
430
+ // --- Stream event handling ---
431
+
432
+ handleStreamEvent(event, responseId, currentContent, thinkingState) {
433
+ const bubble = this.querySelector(`#${responseId}`);
434
+ if (!bubble) return;
435
+
436
+ const contentDiv = bubble.querySelector('.response-content');
437
+ const toolsDiv = bubble.querySelector('.tool-invocations');
438
+ const loadingDots = contentDiv.querySelector('.loading-dots');
439
+ const container = this.querySelector('#chatMessages');
440
+
441
+ if (event.type === 'thinking') {
442
+ this.handleThinkingEvent(event, toolsDiv, thinkingState, container);
443
+ } else if (event.type === 'content') {
444
+ this.finalizeThinkingPill(toolsDiv, thinkingState);
445
+ if (loadingDots) {
446
+ loadingDots.remove();
447
+ bubble.querySelector('.response-bubble-inner').classList.remove('loading');
448
+ contentDiv.classList.remove('flex', 'items-center', 'whitespace-pre-wrap');
449
+ contentDiv.innerHTML = '';
450
+ }
451
+ this.renderContentStreaming(contentDiv, currentContent, responseId, thinkingState);
452
+ container.scrollTop = container.scrollHeight;
453
+ } else if (event.type === 'tool_start') {
454
+ this.finalizeThinkingPill(toolsDiv, thinkingState);
455
+ const toolId = `tool-${event.runId}`;
456
+ const toolEl = document.createElement('div');
457
+ toolEl.id = toolId;
458
+ toolEl.className = 'tool-pill';
459
+ toolEl.dataset.toolInput = typeof event.input === 'string' ? event.input : JSON.stringify(event.input, null, 2);
460
+ toolEl.innerHTML = `
461
+ <i class="fas fa-circle-notch animate-spin text-blue text-2xs"></i>
462
+ <span>${this.escapeHtml(event.tool)}</span>
463
+ `;
464
+ toolsDiv.appendChild(toolEl);
465
+ container.scrollTop = container.scrollHeight;
466
+ } else if (event.type === 'tool_end') {
467
+ const toolId = `tool-${event.runId}`;
468
+ const toolEl = toolsDiv.querySelector(`#${toolId}`);
469
+ if (toolEl) {
470
+ const toolInput = toolEl.dataset.toolInput || '';
471
+ const toolOutput = typeof event.output === 'string' ? event.output : JSON.stringify(event.output, null, 2);
472
+
473
+ toolEl.className = 'tool-pill done';
474
+ toolEl.innerHTML = '';
475
+
476
+ const pillContent = document.createElement('span');
477
+ pillContent.className = 'inline-flex items-center gap-1';
478
+ pillContent.innerHTML = `
479
+ <i class="fas fa-check text-green text-2xs"></i>
480
+ <span>${this.escapeHtml(event.tool)}</span>
481
+ `;
482
+ toolEl.appendChild(pillContent);
483
+
484
+ const details = document.createElement('div');
485
+ details.className = 'tool-invocation-details';
486
+
487
+ if (toolInput) {
488
+ const inputSection = document.createElement('div');
489
+ inputSection.className = 'tool-detail-section';
490
+ inputSection.innerHTML = '<h4>Input</h4>';
491
+ const inputPre = document.createElement('pre');
492
+ inputPre.className = 'tool-detail-pre custom-scrollbar';
493
+ inputPre.textContent = toolInput;
494
+ inputSection.appendChild(inputPre);
495
+ details.appendChild(inputSection);
496
+ }
497
+
498
+ const outputSection = document.createElement('div');
499
+ outputSection.className = 'tool-detail-section';
500
+ outputSection.innerHTML = '<h4>Output</h4>';
501
+ const outputPre = document.createElement('pre');
502
+ outputPre.className = 'tool-detail-pre custom-scrollbar';
503
+ outputPre.textContent = toolOutput;
504
+ outputSection.appendChild(outputPre);
505
+ details.appendChild(outputSection);
506
+
507
+ toolEl.appendChild(details);
508
+
509
+ this._attachClickDetails(toolEl, details, toolsDiv, container);
510
+ container.scrollTop = container.scrollHeight;
511
+ }
512
+ } else if (event.type === 'result') {
513
+ if (loadingDots) {
514
+ loadingDots.remove();
515
+ bubble.querySelector('.response-bubble-inner').classList.remove('loading');
516
+ contentDiv.classList.remove('flex', 'items-center', 'whitespace-pre-wrap');
517
+ contentDiv.innerHTML = '';
518
+ }
519
+ const resultContainer = document.createElement('div');
520
+ resultContainer.className = 'panel';
521
+ const resultPre = document.createElement('pre');
522
+ resultPre.className = 'text-sm text-primary font-mono whitespace-pre-wrap overflow-x-auto';
523
+ resultPre.textContent = JSON.stringify(event.output, null, 2);
524
+ resultContainer.appendChild(resultPre);
525
+ contentDiv.appendChild(resultContainer);
526
+ container.scrollTop = container.scrollHeight;
527
+ } else if (event.type === 'error') {
528
+ if (loadingDots) {
529
+ loadingDots.remove();
530
+ bubble.querySelector('.response-bubble-inner').classList.remove('loading');
531
+ contentDiv.classList.remove('flex', 'items-center', 'whitespace-pre-wrap');
532
+ }
533
+ const errorDiv = document.createElement('div');
534
+ errorDiv.className = 'text-red text-sm';
535
+ errorDiv.textContent = `Error: ${event.error}`;
536
+ contentDiv.appendChild(errorDiv);
537
+ container.scrollTop = container.scrollHeight;
538
+ } else if (event.type === 'warning') {
539
+ const warningDiv = document.createElement('div');
540
+ warningDiv.className = 'text-yellow text-sm';
541
+ warningDiv.textContent = event.message;
542
+ contentDiv.appendChild(warningDiv);
543
+ container.scrollTop = container.scrollHeight;
544
+ } else if (event.type === 'usage') {
545
+ this.streamUsageData = {
546
+ input_tokens: event.input_tokens || 0,
547
+ output_tokens: event.output_tokens || 0,
548
+ total_tokens: event.total_tokens || 0,
549
+ };
550
+ } else if (event.type === 'react_iteration') {
551
+ const wrapper = bubble.closest('.response-wrapper');
552
+ const statusText = wrapper?.querySelector('.stream-status-text');
553
+ if (statusText) {
554
+ const contextKB = (event.contextChars / 1024).toFixed(1);
555
+ statusText.textContent = `Iteration ${event.iteration} · ${contextKB} KB context`;
556
+ }
557
+ }
558
+ }
559
+
560
+ // --- Markdown streaming renderer ---
561
+
562
+ renderContentStreaming(contentDiv, fullContent, responseId, state) {
563
+ const existing = contentDiv.querySelector('.content-text');
564
+ if (existing) {
565
+ existing.innerHTML = this.renderMarkdown(fullContent);
566
+ this.highlightCode(existing);
567
+ } else {
568
+ const div = document.createElement('div');
569
+ div.className = 'content-text markdown-content';
570
+ div.innerHTML = this.renderMarkdown(fullContent);
571
+ this.highlightCode(div);
572
+ contentDiv.appendChild(div);
573
+ }
574
+ }
575
+
576
+ handleThinkingEvent(event, toolsDiv, thinkingState, container) {
577
+ if (!thinkingState.thinkingContent) {
578
+ thinkingState.thinkingContent = '';
579
+ }
580
+ thinkingState.thinkingContent += event.content;
581
+
582
+ if (!thinkingState.thinkingPill) {
583
+ const pill = document.createElement('div');
584
+ pill.className = 'tool-pill thinking';
585
+ pill.innerHTML = `
586
+ <i class="fas fa-brain animate-pulse text-2xs"></i>
587
+ <span>Thinking...</span>
588
+ `;
589
+ toolsDiv.appendChild(pill);
590
+ thinkingState.thinkingPill = pill;
591
+ container.scrollTop = container.scrollHeight;
592
+ }
593
+ }
594
+
595
+ _attachClickDetails(pillEl, detailsEl, toolsDiv, container) {
596
+ pillEl.addEventListener('click', (e) => {
597
+ if (detailsEl.contains(e.target)) return;
598
+ e.preventDefault();
599
+ e.stopPropagation();
600
+ toolsDiv.querySelectorAll('.tool-invocation-details.visible').forEach(d => {
601
+ if (d !== detailsEl) d.classList.remove('visible');
602
+ });
603
+ const wasHidden = !detailsEl.classList.contains('visible');
604
+ detailsEl.classList.toggle('visible');
605
+ if (wasHidden && container) {
606
+ const pillRect = pillEl.getBoundingClientRect();
607
+ const containerRect = container.getBoundingClientRect();
608
+ const spaceRight = containerRect.right - pillRect.left;
609
+ if (spaceRight < 420) {
610
+ detailsEl.style.right = '0';
611
+ detailsEl.style.left = 'auto';
612
+ } else {
613
+ detailsEl.style.left = '0';
614
+ detailsEl.style.right = 'auto';
615
+ }
616
+ }
617
+ });
618
+ document.addEventListener('click', (e) => {
619
+ if (!pillEl.contains(e.target)) detailsEl.classList.remove('visible');
620
+ }, { capture: true });
621
+ }
622
+
623
+ finalizeThinkingPill(toolsDiv, thinkingState) {
624
+ const container = this.querySelector('#chatMessages');
625
+ const pill = thinkingState.thinkingPill;
626
+ if (!pill) return;
627
+
628
+ const content = thinkingState.thinkingContent || '';
629
+ thinkingState.thinkingPill = null;
630
+ thinkingState.thinkingContent = '';
631
+
632
+ pill.className = 'tool-pill done thinking';
633
+ pill.innerHTML = '';
634
+
635
+ const pillContent = document.createElement('span');
636
+ pillContent.className = 'inline-flex items-center gap-1';
637
+ pillContent.innerHTML = '<i class="fas fa-brain text-purple text-2xs"></i><span>Thinking</span>';
638
+ pill.appendChild(pillContent);
639
+
640
+ const details = document.createElement('div');
641
+ details.className = 'tool-invocation-details';
642
+
643
+ const section = document.createElement('div');
644
+ section.className = 'tool-detail-section';
645
+ const pre = document.createElement('div');
646
+ pre.className = 'tool-detail-pre markdown-content custom-scrollbar';
647
+ pre.innerHTML = this.renderMarkdown(content);
648
+ this.highlightCode(pre);
649
+ section.appendChild(pre);
650
+ details.appendChild(section);
651
+ pill.appendChild(details);
652
+
653
+ this._attachClickDetails(pill, details, toolsDiv, container);
654
+ }
655
+
656
+ // --- Bubble rendering ---
657
+
658
+ appendUserMessage(content, attachments) {
659
+ const container = this.querySelector('#chatMessages');
660
+ const div = document.createElement('div');
661
+ div.className = 'flex justify-end';
662
+
663
+ let attachmentHtml = '';
664
+ if (attachments && attachments.length > 0) {
665
+ const thumbs = attachments.map(att => {
666
+ if (att.mediaType.startsWith('image/')) {
667
+ return `<img src="data:${att.mediaType};base64,${att.data}" class="attachment-thumb">`;
668
+ }
669
+ return `<div class="attachment-pill">
670
+ <i class="fas fa-file"></i>
671
+ <span class="truncate attachment-name">${this.escapeHtml(att.name)}</span>
672
+ </div>`;
673
+ }).join('');
674
+ attachmentHtml = `<div class="flex flex-wrap gap-2 mb-2">${thumbs}</div>`;
675
+ }
676
+
677
+ div.innerHTML = `
678
+ <div class="user-bubble">
679
+ ${attachmentHtml}
680
+ <div class="whitespace-pre-wrap">${this.escapeHtml(content)}</div>
681
+ </div>
682
+ `;
683
+
684
+ container.appendChild(div);
685
+ container.scrollTop = container.scrollHeight;
686
+ }
687
+
688
+ createResponseBubble(id) {
689
+ const container = this.querySelector('#chatMessages');
690
+ const wrapper = document.createElement('div');
691
+ wrapper.className = 'response-wrapper';
692
+
693
+ const div = document.createElement('div');
694
+ div.id = id;
695
+ div.className = 'flex justify-start';
696
+ div.innerHTML = `
697
+ <div class="response-bubble-inner loading group">
698
+ <div class="response-content whitespace-pre-wrap flex items-center">
699
+ <div class="loading-dots">
700
+ <div></div>
701
+ <div></div>
702
+ <div></div>
703
+ </div>
704
+ </div>
705
+ <div class="tool-invocations"></div>
706
+ </div>
707
+ `;
708
+
709
+ wrapper.appendChild(div);
710
+
711
+ const statusBar = document.createElement('div');
712
+ statusBar.className = 'stream-status-bar';
713
+ statusBar.innerHTML = `
714
+ <div class="status-dot-pulse"></div>
715
+ <span class="stream-status-text">Generating...</span>
716
+ <span class="stream-elapsed text-muted">0.0s</span>
717
+ <button class="stream-cancel-btn">Stop</button>
718
+ `;
719
+ wrapper.appendChild(statusBar);
720
+
721
+ statusBar.querySelector('.stream-cancel-btn').addEventListener('click', () => {
722
+ if (this.currentAbortController) this.currentAbortController.abort();
723
+ });
724
+
725
+ const statsBar = document.createElement('div');
726
+ statsBar.className = 'stream-stats-bar';
727
+ statsBar.innerHTML = `
728
+ <span class="flex items-center gap-1"><i class="far fa-clock"></i><span class="stats-elapsed"></span></span>
729
+ <span class="divider">|</span>
730
+ <span class="flex items-center gap-1"><i class="fas fa-arrow-up text-2xs"></i><span class="stats-input-tokens"></span></span>
731
+ <span class="divider">|</span>
732
+ <span class="flex items-center gap-1"><i class="fas fa-arrow-down text-2xs"></i><span class="stats-output-tokens"></span></span>
733
+ <span class="divider">|</span>
734
+ <span class="flex items-center gap-1"><i class="fas fa-bolt text-2xs"></i><span class="stats-tps"></span></span>
735
+ `;
736
+ wrapper.appendChild(statsBar);
737
+
738
+ container.appendChild(wrapper);
739
+ container.scrollTop = container.scrollHeight;
740
+ }
741
+
742
+ updateResponseError(id, errorMsg) {
743
+ const bubble = this.querySelector(`#${id}`);
744
+ if (bubble) {
745
+ bubble.querySelector('.response-content').innerHTML = `<span class="text-red">${this.escapeHtml(errorMsg)}</span>`;
746
+ }
747
+ }
748
+
749
+ // --- Timer & stats ---
750
+
751
+ formatElapsedTime(ms) {
752
+ if (ms < 1000) return `${ms}ms`;
753
+ const seconds = ms / 1000;
754
+ if (seconds < 60) return `${seconds.toFixed(1)}s`;
755
+ const minutes = Math.floor(seconds / 60);
756
+ const remainingSeconds = (seconds % 60).toFixed(0);
757
+ return `${minutes}m ${remainingSeconds}s`;
758
+ }
759
+
760
+ estimateTokens(text) {
761
+ return Math.round((text || '').length / 4);
762
+ }
763
+
764
+ startStreamTimer(responseId) {
765
+ this.streamStartTime = Date.now();
766
+ this.streamTimerInterval = setInterval(() => {
767
+ const elapsed = Date.now() - this.streamStartTime;
768
+ const bubble = this.querySelector(`#${responseId}`);
769
+ if (!bubble) return;
770
+ const timerEl = bubble.parentElement.querySelector('.stream-elapsed');
771
+ if (timerEl) timerEl.textContent = this.formatElapsedTime(elapsed);
772
+ }, 100);
773
+ }
774
+
775
+ stopStreamTimer(responseId, inputMessage, finalContent, wasCancelled) {
776
+ if (this.streamTimerInterval) {
777
+ clearInterval(this.streamTimerInterval);
778
+ this.streamTimerInterval = null;
779
+ }
780
+
781
+ const elapsed = this.streamStartTime ? Date.now() - this.streamStartTime : 0;
782
+ this.streamStartTime = null;
783
+
784
+ const bubble = this.querySelector(`#${responseId}`);
785
+ if (!bubble) return;
786
+
787
+ const wrapper = bubble.parentElement;
788
+ const statusBar = wrapper.querySelector('.stream-status-bar');
789
+ const statsBar = wrapper.querySelector('.stream-stats-bar');
790
+
791
+ if (statusBar) statusBar.remove();
792
+
793
+ if (statsBar) {
794
+ const elapsedEl = statsBar.querySelector('.stats-elapsed');
795
+ const inputTokensEl = statsBar.querySelector('.stats-input-tokens');
796
+ const outputTokensEl = statsBar.querySelector('.stats-output-tokens');
797
+ const tpsEl = statsBar.querySelector('.stats-tps');
798
+
799
+ const usage = this.streamUsageData;
800
+ const hasRealUsage = usage && (usage.input_tokens > 0 || usage.output_tokens > 0);
801
+ const inputTokens = hasRealUsage ? usage.input_tokens : this.estimateTokens(inputMessage);
802
+ const outputTokens = hasRealUsage ? usage.output_tokens : this.estimateTokens(finalContent);
803
+ const prefix = hasRealUsage ? '' : '~';
804
+
805
+ if (elapsedEl) elapsedEl.textContent = this.formatElapsedTime(elapsed);
806
+ if (inputTokensEl) inputTokensEl.textContent = `${prefix}${inputTokens} input`;
807
+ if (outputTokensEl) outputTokensEl.textContent = `${prefix}${outputTokens} output`;
808
+ if (tpsEl) {
809
+ const seconds = elapsed / 1000;
810
+ const tps = seconds > 0 ? (outputTokens / seconds).toFixed(1) : 0;
811
+ tpsEl.textContent = `${prefix}${tps} tok/s`;
812
+ }
813
+
814
+ this.streamUsageData = null;
815
+
816
+ if (wasCancelled) {
817
+ const badge = document.createElement('span');
818
+ badge.className = 'badge badge-amber';
819
+ badge.textContent = 'Cancelled';
820
+ statsBar.appendChild(badge);
821
+ }
822
+
823
+ statsBar.classList.add('visible');
824
+ }
825
+ }
826
+
827
+ // --- UI state ---
828
+
829
+ updateUiState() {
830
+ const btn = this.querySelector('#sendBtn');
831
+ const input = this.querySelector('#chatInput');
832
+ if (btn) btn.disabled = this.isLoading;
833
+ if (input) input.disabled = this.isLoading;
834
+ }
835
+
836
+ // --- Markdown helpers ---
837
+
838
+ renderMarkdown(text) {
839
+ if (!text) return '';
840
+ try {
841
+ const rawHtml = marked.parse(text);
842
+ return DOMPurify.sanitize(rawHtml, {
843
+ ALLOWED_TAGS: [
844
+ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
845
+ 'p', 'br', 'strong', 'em', 'u', 's', 'del',
846
+ 'ul', 'ol', 'li',
847
+ 'a', 'code', 'pre',
848
+ 'blockquote', 'hr',
849
+ 'table', 'thead', 'tbody', 'tr', 'th', 'td',
850
+ 'span', 'div'
851
+ ],
852
+ ALLOWED_ATTR: ['href', 'class', 'id', 'target', 'rel'],
853
+ ALLOW_DATA_ATTR: false,
854
+ });
855
+ } catch {
856
+ return this.escapeHtml(text);
857
+ }
858
+ }
859
+
860
+ highlightCode(element) {
861
+ if (typeof hljs === 'undefined') return;
862
+ element.querySelectorAll('pre code').forEach(block => {
863
+ block.removeAttribute('data-highlighted');
864
+ hljs.highlightElement(block);
865
+ });
866
+ }
867
+
868
+ escapeHtml(text) {
869
+ const div = document.createElement('div');
870
+ div.textContent = text;
871
+ return div.innerHTML;
872
+ }
873
+ }
874
+
875
+ customElements.define('standalone-chat', StandaloneChat);