agent-orcha 0.0.4 → 0.0.7

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