agent-orcha 0.0.5 → 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 (264) hide show
  1. package/README.md +194 -1277
  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 +68 -52
  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 +180 -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/integrations/email.d.ts +38 -0
  22. package/dist/lib/integrations/email.d.ts.map +1 -0
  23. package/dist/lib/integrations/email.js +249 -0
  24. package/dist/lib/integrations/email.js.map +1 -0
  25. package/dist/lib/integrations/integration-manager.d.ts +5 -0
  26. package/dist/lib/integrations/integration-manager.d.ts.map +1 -1
  27. package/dist/lib/integrations/integration-manager.js +53 -3
  28. package/dist/lib/integrations/integration-manager.js.map +1 -1
  29. package/dist/lib/integrations/types.d.ts +187 -4
  30. package/dist/lib/integrations/types.d.ts.map +1 -1
  31. package/dist/lib/integrations/types.js +24 -1
  32. package/dist/lib/integrations/types.js.map +1 -1
  33. package/dist/lib/knowledge/knowledge-store.d.ts +6 -0
  34. package/dist/lib/knowledge/knowledge-store.d.ts.map +1 -1
  35. package/dist/lib/knowledge/knowledge-store.js +71 -4
  36. package/dist/lib/knowledge/knowledge-store.js.map +1 -1
  37. package/dist/lib/knowledge/loaders/file-loaders.d.ts +8 -2
  38. package/dist/lib/knowledge/loaders/file-loaders.d.ts.map +1 -1
  39. package/dist/lib/knowledge/loaders/file-loaders.js +89 -60
  40. package/dist/lib/knowledge/loaders/file-loaders.js.map +1 -1
  41. package/dist/lib/knowledge/loaders/web-loader.d.ts +12 -3
  42. package/dist/lib/knowledge/loaders/web-loader.d.ts.map +1 -1
  43. package/dist/lib/knowledge/loaders/web-loader.js +56 -22
  44. package/dist/lib/knowledge/loaders/web-loader.js.map +1 -1
  45. package/dist/lib/knowledge/types.d.ts +56 -20
  46. package/dist/lib/knowledge/types.d.ts.map +1 -1
  47. package/dist/lib/knowledge/types.js +18 -3
  48. package/dist/lib/knowledge/types.js.map +1 -1
  49. package/dist/lib/llm/llm-call-logger.d.ts +3 -1
  50. package/dist/lib/llm/llm-call-logger.d.ts.map +1 -1
  51. package/dist/lib/llm/llm-call-logger.js +31 -26
  52. package/dist/lib/llm/llm-call-logger.js.map +1 -1
  53. package/dist/lib/llm/llm-config.d.ts +8 -0
  54. package/dist/lib/llm/llm-config.d.ts.map +1 -1
  55. package/dist/lib/llm/llm-config.js +3 -1
  56. package/dist/lib/llm/llm-config.js.map +1 -1
  57. package/dist/lib/llm/llm-factory.d.ts.map +1 -1
  58. package/dist/lib/llm/llm-factory.js +3 -0
  59. package/dist/lib/llm/llm-factory.js.map +1 -1
  60. package/dist/lib/llm/providers/anthropic-chat-model.d.ts +5 -1
  61. package/dist/lib/llm/providers/anthropic-chat-model.d.ts.map +1 -1
  62. package/dist/lib/llm/providers/anthropic-chat-model.js +118 -42
  63. package/dist/lib/llm/providers/anthropic-chat-model.js.map +1 -1
  64. package/dist/lib/llm/providers/gemini-chat-model.d.ts +3 -2
  65. package/dist/lib/llm/providers/gemini-chat-model.d.ts.map +1 -1
  66. package/dist/lib/llm/providers/gemini-chat-model.js +83 -24
  67. package/dist/lib/llm/providers/gemini-chat-model.js.map +1 -1
  68. package/dist/lib/llm/providers/openai-chat-model.d.ts +10 -1
  69. package/dist/lib/llm/providers/openai-chat-model.d.ts.map +1 -1
  70. package/dist/lib/llm/providers/openai-chat-model.js +233 -32
  71. package/dist/lib/llm/providers/openai-chat-model.js.map +1 -1
  72. package/dist/lib/logger.d.ts.map +1 -1
  73. package/dist/lib/logger.js +0 -1
  74. package/dist/lib/logger.js.map +1 -1
  75. package/dist/lib/mcp/mcp-client.d.ts.map +1 -1
  76. package/dist/lib/mcp/mcp-client.js +5 -3
  77. package/dist/lib/mcp/mcp-client.js.map +1 -1
  78. package/dist/lib/mcp/types.d.ts +0 -9
  79. package/dist/lib/mcp/types.d.ts.map +1 -1
  80. package/dist/lib/mcp/types.js +1 -2
  81. package/dist/lib/mcp/types.js.map +1 -1
  82. package/dist/lib/memory/memory-manager.d.ts +1 -0
  83. package/dist/lib/memory/memory-manager.d.ts.map +1 -1
  84. package/dist/lib/memory/memory-manager.js +9 -0
  85. package/dist/lib/memory/memory-manager.js.map +1 -1
  86. package/dist/lib/orchestrator.d.ts +2 -8
  87. package/dist/lib/orchestrator.d.ts.map +1 -1
  88. package/dist/lib/orchestrator.js +96 -3
  89. package/dist/lib/orchestrator.js.map +1 -1
  90. package/dist/lib/sandbox/cdp-client.d.ts +14 -0
  91. package/dist/lib/sandbox/cdp-client.d.ts.map +1 -0
  92. package/dist/lib/sandbox/cdp-client.js +113 -0
  93. package/dist/lib/sandbox/cdp-client.js.map +1 -0
  94. package/dist/lib/sandbox/html-to-markdown.d.ts +9 -1
  95. package/dist/lib/sandbox/html-to-markdown.d.ts.map +1 -1
  96. package/dist/lib/sandbox/html-to-markdown.js +67 -10
  97. package/dist/lib/sandbox/html-to-markdown.js.map +1 -1
  98. package/dist/lib/sandbox/index.d.ts +5 -0
  99. package/dist/lib/sandbox/index.d.ts.map +1 -1
  100. package/dist/lib/sandbox/index.js +4 -0
  101. package/dist/lib/sandbox/index.js.map +1 -1
  102. package/dist/lib/sandbox/page-readiness.d.ts +37 -0
  103. package/dist/lib/sandbox/page-readiness.d.ts.map +1 -0
  104. package/dist/lib/sandbox/page-readiness.js +235 -0
  105. package/dist/lib/sandbox/page-readiness.js.map +1 -0
  106. package/dist/lib/sandbox/sandbox-browser.d.ts +4 -0
  107. package/dist/lib/sandbox/sandbox-browser.d.ts.map +1 -0
  108. package/dist/lib/sandbox/sandbox-browser.js +303 -0
  109. package/dist/lib/sandbox/sandbox-browser.js.map +1 -0
  110. package/dist/lib/sandbox/sandbox-file.d.ts +4 -0
  111. package/dist/lib/sandbox/sandbox-file.d.ts.map +1 -0
  112. package/dist/lib/sandbox/sandbox-file.js +168 -0
  113. package/dist/lib/sandbox/sandbox-file.js.map +1 -0
  114. package/dist/lib/sandbox/sandbox-shell.d.ts +4 -0
  115. package/dist/lib/sandbox/sandbox-shell.d.ts.map +1 -0
  116. package/dist/lib/sandbox/sandbox-shell.js +93 -0
  117. package/dist/lib/sandbox/sandbox-shell.js.map +1 -0
  118. package/dist/lib/sandbox/sandbox-web.d.ts.map +1 -1
  119. package/dist/lib/sandbox/sandbox-web.js +37 -22
  120. package/dist/lib/sandbox/sandbox-web.js.map +1 -1
  121. package/dist/lib/sandbox/types.d.ts +9 -0
  122. package/dist/lib/sandbox/types.d.ts.map +1 -1
  123. package/dist/lib/sandbox/types.js +1 -0
  124. package/dist/lib/sandbox/types.js.map +1 -1
  125. package/dist/lib/sandbox/vision-browser.d.ts +4 -0
  126. package/dist/lib/sandbox/vision-browser.d.ts.map +1 -0
  127. package/dist/lib/sandbox/vision-browser.js +289 -0
  128. package/dist/lib/sandbox/vision-browser.js.map +1 -0
  129. package/dist/lib/skills/skill-loader.d.ts +2 -0
  130. package/dist/lib/skills/skill-loader.d.ts.map +1 -1
  131. package/dist/lib/skills/skill-loader.js +12 -1
  132. package/dist/lib/skills/skill-loader.js.map +1 -1
  133. package/dist/lib/tasks/task-manager.d.ts +3 -1
  134. package/dist/lib/tasks/task-manager.d.ts.map +1 -1
  135. package/dist/lib/tasks/task-manager.js +11 -0
  136. package/dist/lib/tasks/task-manager.js.map +1 -1
  137. package/dist/lib/tasks/task-store.d.ts +1 -1
  138. package/dist/lib/tasks/task-store.d.ts.map +1 -1
  139. package/dist/lib/tasks/task-store.js.map +1 -1
  140. package/dist/lib/tasks/types.d.ts +18 -0
  141. package/dist/lib/tasks/types.d.ts.map +1 -1
  142. package/dist/lib/tools/built-in/integration-tools.d.ts +4 -0
  143. package/dist/lib/tools/built-in/integration-tools.d.ts.map +1 -0
  144. package/dist/lib/tools/built-in/integration-tools.js +47 -0
  145. package/dist/lib/tools/built-in/integration-tools.js.map +1 -0
  146. package/dist/lib/tools/built-in/knowledge-entity-lookup.tool.d.ts.map +1 -1
  147. package/dist/lib/tools/built-in/knowledge-entity-lookup.tool.js +12 -6
  148. package/dist/lib/tools/built-in/knowledge-entity-lookup.tool.js.map +1 -1
  149. package/dist/lib/tools/built-in/knowledge-sql.tool.d.ts.map +1 -1
  150. package/dist/lib/tools/built-in/knowledge-sql.tool.js +4 -3
  151. package/dist/lib/tools/built-in/knowledge-sql.tool.js.map +1 -1
  152. package/dist/lib/tools/built-in/query-validators.d.ts.map +1 -1
  153. package/dist/lib/tools/built-in/query-validators.js +4 -0
  154. package/dist/lib/tools/built-in/query-validators.js.map +1 -1
  155. package/dist/lib/tools/workspace/workspace-tools.d.ts +1 -0
  156. package/dist/lib/tools/workspace/workspace-tools.d.ts.map +1 -1
  157. package/dist/lib/tools/workspace/workspace-tools.js +39 -0
  158. package/dist/lib/tools/workspace/workspace-tools.js.map +1 -1
  159. package/dist/lib/triggers/cron-trigger.d.ts +1 -1
  160. package/dist/lib/triggers/cron-trigger.d.ts.map +1 -1
  161. package/dist/lib/triggers/cron-trigger.js.map +1 -1
  162. package/dist/lib/triggers/trigger-manager.d.ts +1 -0
  163. package/dist/lib/triggers/trigger-manager.d.ts.map +1 -1
  164. package/dist/lib/triggers/trigger-manager.js +26 -0
  165. package/dist/lib/triggers/trigger-manager.js.map +1 -1
  166. package/dist/lib/triggers/webhook-trigger.d.ts +1 -1
  167. package/dist/lib/triggers/webhook-trigger.d.ts.map +1 -1
  168. package/dist/lib/triggers/webhook-trigger.js.map +1 -1
  169. package/dist/lib/types/llm-types.d.ts +22 -4
  170. package/dist/lib/types/llm-types.d.ts.map +1 -1
  171. package/dist/lib/types/llm-types.js +50 -0
  172. package/dist/lib/types/llm-types.js.map +1 -1
  173. package/dist/lib/types/tool-factory.d.ts +2 -2
  174. package/dist/lib/types/tool-factory.d.ts.map +1 -1
  175. package/dist/lib/types/tool-factory.js.map +1 -1
  176. package/dist/lib/utils/env-substitution.d.ts +6 -0
  177. package/dist/lib/utils/env-substitution.d.ts.map +1 -0
  178. package/dist/lib/utils/env-substitution.js +15 -0
  179. package/dist/lib/utils/env-substitution.js.map +1 -0
  180. package/dist/lib/workflows/react-workflow-executor.js +3 -3
  181. package/dist/lib/workflows/react-workflow-executor.js.map +1 -1
  182. package/dist/lib/workflows/types.d.ts +10 -10
  183. package/dist/lib/workflows/workflow-loader.d.ts +3 -0
  184. package/dist/lib/workflows/workflow-loader.d.ts.map +1 -1
  185. package/dist/lib/workflows/workflow-loader.js +10 -1
  186. package/dist/lib/workflows/workflow-loader.js.map +1 -1
  187. package/dist/public/chat.html +114 -0
  188. package/dist/public/index.html +157 -0
  189. package/dist/public/src/components/AgentComposer.js +807 -0
  190. package/dist/public/src/components/AgentsView.js +740 -317
  191. package/dist/public/src/components/AppRoot.js +30 -5
  192. package/dist/public/src/components/GraphView.js +372 -288
  193. package/dist/public/src/components/IdeView.js +163 -7
  194. package/dist/public/src/components/MonitorView.js +139 -1
  195. package/dist/public/src/components/StandaloneChat.js +889 -0
  196. package/dist/public/src/components/WorkflowsView.js +180 -28
  197. package/dist/public/src/services/ApiService.js +7 -2
  198. package/dist/public/src/services/SessionStore.js +83 -0
  199. package/dist/public/src/store.js +0 -2
  200. package/dist/public/src/utils/markdown.js +13 -0
  201. package/dist/src/cli/index.js +7 -4
  202. package/dist/src/cli/index.js.map +1 -1
  203. package/dist/src/middleware/auth.d.ts.map +1 -1
  204. package/dist/src/middleware/auth.js +28 -6
  205. package/dist/src/middleware/auth.js.map +1 -1
  206. package/dist/src/middleware/rate-limit.d.ts +8 -0
  207. package/dist/src/middleware/rate-limit.d.ts.map +1 -0
  208. package/dist/src/middleware/rate-limit.js +21 -0
  209. package/dist/src/middleware/rate-limit.js.map +1 -0
  210. package/dist/src/routes/agents.route.d.ts.map +1 -1
  211. package/dist/src/routes/agents.route.js +136 -10
  212. package/dist/src/routes/agents.route.js.map +1 -1
  213. package/dist/src/routes/chat.route.d.ts +3 -0
  214. package/dist/src/routes/chat.route.d.ts.map +1 -0
  215. package/dist/src/routes/chat.route.js +155 -0
  216. package/dist/src/routes/chat.route.js.map +1 -0
  217. package/dist/src/routes/files.route.d.ts.map +1 -1
  218. package/dist/src/routes/files.route.js +37 -2
  219. package/dist/src/routes/files.route.js.map +1 -1
  220. package/dist/src/routes/llm.route.d.ts.map +1 -1
  221. package/dist/src/routes/llm.route.js +40 -5
  222. package/dist/src/routes/llm.route.js.map +1 -1
  223. package/dist/src/routes/tasks.route.d.ts.map +1 -1
  224. package/dist/src/routes/tasks.route.js +15 -1
  225. package/dist/src/routes/tasks.route.js.map +1 -1
  226. package/dist/src/routes/vnc.route.d.ts +3 -0
  227. package/dist/src/routes/vnc.route.d.ts.map +1 -0
  228. package/dist/src/routes/vnc.route.js +49 -0
  229. package/dist/src/routes/vnc.route.js.map +1 -0
  230. package/dist/src/server.d.ts.map +1 -1
  231. package/dist/src/server.js +5 -1
  232. package/dist/src/server.js.map +1 -1
  233. package/dist/templates/Demo.md +152 -0
  234. package/dist/templates/README.md +12 -3
  235. package/dist/templates/agents/architect.agent.yaml +20 -12
  236. package/dist/templates/agents/chatbot.agent.yaml +23 -26
  237. package/dist/templates/agents/corporate.agent.yaml +65 -0
  238. package/dist/templates/agents/investment-analyst.agent.yaml +80 -0
  239. package/dist/templates/agents/music-librarian.agent.yaml +70 -0
  240. package/dist/templates/agents/network-security.agent.yaml +82 -0
  241. package/dist/templates/agents/transport-security.agent.yaml +70 -0
  242. package/dist/templates/agents/web-engineer.agent.yaml +99 -0
  243. package/dist/templates/agents/web-pilot.agent.yaml +58 -0
  244. package/dist/templates/knowledge/music-store/LICENSE.md +11 -0
  245. package/dist/templates/knowledge/music-store/musicstore.sqlite +0 -0
  246. package/dist/templates/knowledge/music-store/tables.png +0 -0
  247. package/dist/templates/knowledge/music-store.knowledge.yaml +138 -0
  248. package/dist/templates/knowledge/org-chart/personnel.csv +21 -21
  249. package/dist/templates/knowledge/org-chart.knowledge.yaml +4 -0
  250. package/dist/templates/knowledge/pet-store.knowledge.yaml +3 -0
  251. package/dist/templates/knowledge/security-incidents/incidents.json +55935 -0
  252. package/dist/templates/knowledge/security-incidents.knowledge.yaml +46 -0
  253. package/dist/templates/knowledge/{example.knowledge.yaml → transcripts.knowledge.yaml} +9 -5
  254. package/dist/templates/knowledge/transport-ot/systems.csv +117 -0
  255. package/dist/templates/knowledge/transport-ot.knowledge.yaml +55 -0
  256. package/dist/templates/llm.json +7 -30
  257. package/dist/templates/mcp.json +7 -4
  258. package/dist/templates/skills/orcha-builder/SKILL.md +106 -226
  259. package/dist/templates/skills/pii-guard/SKILL.md +22 -0
  260. package/dist/templates/skills/sandbox/SKILL.md +25 -48
  261. package/dist/templates/skills/web-pilot/SKILL.md +51 -0
  262. package/package.json +8 -3
  263. package/dist/templates/agents/knowledge-broker.agent.yaml +0 -39
  264. package/dist/templates/agents/sandbox.agent.yaml +0 -56
@@ -1,6 +1,7 @@
1
1
 
2
2
  import { Component } from '../utils/Component.js';
3
3
  import { api } from '../services/ApiService.js';
4
+ import './AgentComposer.js';
4
5
 
5
6
  const FILE_ICONS = {
6
7
  yaml: { icon: 'fa-file-code', color: 'text-orange-400' },
@@ -66,6 +67,10 @@ function getExtension(filename) {
66
67
  return parts.length > 1 ? parts.pop().toLowerCase() : '';
67
68
  }
68
69
 
70
+ function isAgentFile(path) {
71
+ return path && path.endsWith('.agent.yaml');
72
+ }
73
+
69
74
  export class IdeView extends Component {
70
75
  constructor() {
71
76
  super();
@@ -75,6 +80,7 @@ export class IdeView extends Component {
75
80
  this.treeData = [];
76
81
  this.expandedDirs = new Set();
77
82
  this._renamingPath = null;
83
+ this._viewMode = 'source'; // 'source' | 'visual'
78
84
  this._handleKeyDown = this._handleKeyDown.bind(this);
79
85
  this._handleDocClick = this._handleDocClick.bind(this);
80
86
  }
@@ -86,6 +92,7 @@ export class IdeView extends Component {
86
92
  this.editor.destroy();
87
93
  this.editor = null;
88
94
  }
95
+ this._viewMode = 'source';
89
96
  }
90
97
 
91
98
  async postRender() {
@@ -105,6 +112,7 @@ export class IdeView extends Component {
105
112
  });
106
113
  }
107
114
 
115
+ this._attachModeToggle();
108
116
  await this._loadTree();
109
117
  }
110
118
 
@@ -395,7 +403,9 @@ export class IdeView extends Component {
395
403
  if (this.currentFile && this.currentFile.path === filePath) {
396
404
  this.currentFile = null;
397
405
  this.isDirty = false;
406
+ this._viewMode = 'source';
398
407
  this._renderEditor();
408
+ this._updateModeToggle();
399
409
  }
400
410
 
401
411
  await this._loadTree();
@@ -604,8 +614,10 @@ export class IdeView extends Component {
604
614
  const data = await api.readFile(filePath);
605
615
  this.currentFile = { path: data.path, content: data.content };
606
616
  this.isDirty = false;
617
+ this._viewMode = 'source';
607
618
  this._renderEditor();
608
619
  this._renderTree();
620
+ this._updateModeToggle();
609
621
  } catch (err) {
610
622
  console.error('Failed to read file:', err);
611
623
  }
@@ -613,19 +625,18 @@ export class IdeView extends Component {
613
625
 
614
626
  _renderEditor() {
615
627
  const editorContainer = this.querySelector('#editorContainer');
628
+ const composerContainer = this.querySelector('#composerContainer');
616
629
  const welcomePanel = this.querySelector('#welcomePanel');
617
630
  const breadcrumb = this.querySelector('#breadcrumb');
618
- const saveBtn = this.querySelector('#saveBtn');
619
- const dirtyIndicator = this.querySelector('#dirtyIndicator');
620
631
 
621
632
  if (!this.currentFile) {
622
633
  if (welcomePanel) welcomePanel.classList.remove('hidden');
623
634
  if (editorContainer) editorContainer.classList.add('hidden');
635
+ if (composerContainer) composerContainer.classList.add('hidden');
624
636
  return;
625
637
  }
626
638
 
627
639
  if (welcomePanel) welcomePanel.classList.add('hidden');
628
- if (editorContainer) editorContainer.classList.remove('hidden');
629
640
 
630
641
  // Update breadcrumb
631
642
  if (breadcrumb) {
@@ -636,6 +647,16 @@ export class IdeView extends Component {
636
647
  // Update dirty state
637
648
  this._updateDirtyState();
638
649
 
650
+ if (this._viewMode === 'visual') {
651
+ if (editorContainer) editorContainer.classList.add('hidden');
652
+ if (composerContainer) composerContainer.classList.remove('hidden');
653
+ return;
654
+ }
655
+
656
+ // Source mode
657
+ if (composerContainer) composerContainer.classList.add('hidden');
658
+ if (editorContainer) editorContainer.classList.remove('hidden');
659
+
639
660
  // Initialize or update Ace
640
661
  const aceEl = this.querySelector('#aceEditor');
641
662
  if (!aceEl) return;
@@ -690,9 +711,18 @@ export class IdeView extends Component {
690
711
  }
691
712
 
692
713
  async _saveFile() {
693
- if (!this.currentFile || !this.isDirty || !this.editor) return;
694
-
695
- const content = this.editor.getValue();
714
+ if (!this.currentFile || !this.isDirty) return;
715
+
716
+ let content;
717
+ if (this._viewMode === 'visual') {
718
+ const composer = this.querySelector('agent-composer');
719
+ if (!composer) return;
720
+ const data = composer.getData();
721
+ content = jsyaml.dump(data, { indent: 2, lineWidth: -1, noRefs: true, sortKeys: false });
722
+ } else {
723
+ if (!this.editor) return;
724
+ content = this.editor.getValue();
725
+ }
696
726
 
697
727
  try {
698
728
  const result = await api.writeFile(this.currentFile.path, content);
@@ -726,6 +756,122 @@ export class IdeView extends Component {
726
756
  }
727
757
  }
728
758
 
759
+ // ── Mode Toggle ──
760
+
761
+ _attachModeToggle() {
762
+ this.querySelectorAll('.mode-toggle-btn').forEach(btn => {
763
+ btn.addEventListener('click', () => {
764
+ const mode = btn.dataset.mode;
765
+ if (mode === this._viewMode) return;
766
+ if (mode === 'visual') this._switchToVisual();
767
+ else this._switchToSource();
768
+ });
769
+ });
770
+ }
771
+
772
+ _updateModeToggle() {
773
+ const toggle = this.querySelector('#modeToggle');
774
+ if (!toggle) return;
775
+
776
+ const show = this.currentFile && isAgentFile(this.currentFile.path);
777
+ toggle.classList.toggle('hidden', !show);
778
+
779
+ toggle.querySelectorAll('.mode-toggle-btn').forEach(btn => {
780
+ const active = btn.dataset.mode === this._viewMode;
781
+ btn.classList.toggle('bg-dark-hover', active);
782
+ btn.classList.toggle('text-white', active);
783
+ btn.classList.toggle('text-gray-500', !active);
784
+ });
785
+ }
786
+
787
+ _switchToVisual() {
788
+ if (!this.currentFile) return;
789
+
790
+ // Get current Ace content and parse
791
+ const content = this.editor ? this.editor.getValue() : this.currentFile.content;
792
+ let parsed;
793
+ try {
794
+ parsed = jsyaml.load(content);
795
+ } catch (err) {
796
+ this._showToast(`Invalid YAML: ${err.message}`, 'error');
797
+ return;
798
+ }
799
+
800
+ if (!parsed || typeof parsed !== 'object') {
801
+ this._showToast('YAML must be an object', 'error');
802
+ return;
803
+ }
804
+
805
+ this._viewMode = 'visual';
806
+ this._updateModeToggle();
807
+
808
+ // Hide Ace, show composer
809
+ const editorContainer = this.querySelector('#editorContainer');
810
+ const composerContainer = this.querySelector('#composerContainer');
811
+ if (editorContainer) editorContainer.classList.add('hidden');
812
+ if (composerContainer) composerContainer.classList.remove('hidden');
813
+
814
+ // Create or get the composer element
815
+ let composer = composerContainer.querySelector('agent-composer');
816
+ if (!composer) {
817
+ composer = document.createElement('agent-composer');
818
+ composer.classList.add('block', 'h-full');
819
+ composerContainer.appendChild(composer);
820
+ }
821
+
822
+ composer.data = parsed;
823
+
824
+ // Listen for changes
825
+ composer.addEventListener('composer:change', () => {
826
+ if (!this.isDirty) {
827
+ this.isDirty = true;
828
+ this._updateDirtyState();
829
+ }
830
+ });
831
+ }
832
+
833
+ _switchToSource() {
834
+ if (!this.currentFile) return;
835
+
836
+ const composer = this.querySelector('agent-composer');
837
+ if (composer && this._viewMode === 'visual') {
838
+ const data = composer.getData();
839
+ const yaml = jsyaml.dump(data, { indent: 2, lineWidth: -1, noRefs: true, sortKeys: false });
840
+
841
+ // Update Ace content
842
+ if (this.editor) {
843
+ this.editor.setValue(yaml, -1);
844
+ }
845
+ this.currentFile.content = yaml;
846
+ }
847
+
848
+ this._viewMode = 'source';
849
+ this._updateModeToggle();
850
+
851
+ const editorContainer = this.querySelector('#editorContainer');
852
+ const composerContainer = this.querySelector('#composerContainer');
853
+ if (composerContainer) composerContainer.classList.add('hidden');
854
+ if (editorContainer) editorContainer.classList.remove('hidden');
855
+
856
+ if (this.editor) {
857
+ this.editor.resize();
858
+ this.editor.focus();
859
+ }
860
+ }
861
+
862
+ _showToast(message, type = 'info') {
863
+ const existing = document.querySelector('#ideToast');
864
+ if (existing) existing.remove();
865
+
866
+ const toast = document.createElement('div');
867
+ toast.id = 'ideToast';
868
+ const color = type === 'error' ? 'bg-red-600' : 'bg-blue-600';
869
+ toast.className = `fixed bottom-4 right-4 z-50 ${color} text-white text-sm px-4 py-2 rounded-lg shadow-lg`;
870
+ toast.textContent = message;
871
+ document.body.appendChild(toast);
872
+ setTimeout(() => toast.remove(), 4000);
873
+ }
874
+
729
875
  template() {
730
876
  return `
731
877
  <div class="flex flex-col h-full">
@@ -736,6 +882,15 @@ export class IdeView extends Component {
736
882
  <span id="breadcrumb">Select a file to edit</span>
737
883
  </div>
738
884
  <div class="flex items-center gap-3">
885
+ <!-- Mode toggle (only for .agent.yaml files) -->
886
+ <div id="modeToggle" class="hidden flex items-center bg-dark-bg rounded border border-dark-border overflow-hidden">
887
+ <button class="mode-toggle-btn px-2.5 py-1 text-xs transition-colors text-white bg-dark-hover" data-mode="source">
888
+ <i class="fas fa-code mr-1"></i>Source
889
+ </button>
890
+ <button class="mode-toggle-btn px-2.5 py-1 text-xs transition-colors text-gray-500" data-mode="visual">
891
+ <i class="fas fa-palette mr-1"></i>Visual
892
+ </button>
893
+ </div>
739
894
  <span id="dirtyIndicator" class="hidden text-yellow-400 text-xs flex items-center gap-1">
740
895
  <i class="fas fa-circle text-[6px]"></i> Unsaved
741
896
  </span>
@@ -763,7 +918,7 @@ export class IdeView extends Component {
763
918
  </div>
764
919
  </div>
765
920
 
766
- <!-- Editor / Welcome -->
921
+ <!-- Editor / Composer / Welcome -->
767
922
  <div class="flex-1 min-w-0 relative">
768
923
  <div id="welcomePanel" class="flex items-center justify-center h-full text-gray-500">
769
924
  <div class="text-center">
@@ -775,6 +930,7 @@ export class IdeView extends Component {
775
930
  <div id="editorContainer" class="hidden h-full">
776
931
  <div id="aceEditor" class="h-full w-full"></div>
777
932
  </div>
933
+ <div id="composerContainer" class="hidden h-full overflow-hidden"></div>
778
934
  </div>
779
935
  </div>
780
936
  </div>
@@ -55,6 +55,13 @@ export class MonitorView extends Component {
55
55
  if (this.selectedTask) {
56
56
  const updated = tasks.find(t => t.id === this.selectedTask.id);
57
57
  if (updated) {
58
+ // Preserve events and metrics from SSE — list API doesn't include them
59
+ if (this.selectedTask.events?.length && !updated.events?.length) {
60
+ updated.events = this.selectedTask.events;
61
+ }
62
+ if (this.selectedTask.metrics && !updated.metrics) {
63
+ updated.metrics = this.selectedTask.metrics;
64
+ }
58
65
  this.selectedTask = updated;
59
66
  this.renderDetailPanel();
60
67
  }
@@ -114,13 +121,19 @@ export class MonitorView extends Component {
114
121
  });
115
122
  }
116
123
 
117
- selectTask(taskId) {
124
+ async selectTask(taskId) {
118
125
  const task = this.tasks.find(t => t.id === taskId);
119
126
  if (!task) return;
120
127
 
121
128
  this.selectedTask = task;
122
129
  this.renderTaskList();
123
130
 
131
+ // Fetch full task with events
132
+ try {
133
+ const full = await api.getTask(taskId);
134
+ this.selectedTask = full;
135
+ } catch { /* fall back to list data */ }
136
+
124
137
  const detailArea = this.querySelector('#taskDetailArea');
125
138
  detailArea.classList.remove('hidden');
126
139
  this.renderDetailPanel();
@@ -170,6 +183,47 @@ export class MonitorView extends Component {
170
183
  </div>
171
184
  </div>`;
172
185
 
186
+ // Metrics section (react-loop telemetry)
187
+ const metricsContainer = this.querySelector('#detailMetrics');
188
+ if (task.metrics) {
189
+ const m = task.metrics;
190
+ metricsContainer.innerHTML = `
191
+ <div class="bg-dark-surface/50 border border-dark-border rounded-lg p-4">
192
+ <div class="flex items-center gap-2 mb-3">
193
+ <i class="fas fa-chart-line text-indigo-400 text-sm"></i>
194
+ <span class="text-sm font-medium text-gray-400">React-Loop Metrics</span>
195
+ </div>
196
+ <div class="grid grid-cols-3 md:grid-cols-6 gap-4 text-sm">
197
+ <div>
198
+ <span class="text-gray-500 block text-xs">Iteration</span>
199
+ <span class="text-gray-200 font-mono">${m.iteration}</span>
200
+ </div>
201
+ <div>
202
+ <span class="text-gray-500 block text-xs">Messages</span>
203
+ <span class="text-gray-200 font-mono">${m.messageCount}</span>
204
+ </div>
205
+ <div>
206
+ <span class="text-gray-500 block text-xs">Images</span>
207
+ <span class="text-gray-200 font-mono">${m.imageCount}</span>
208
+ </div>
209
+ <div>
210
+ <span class="text-gray-500 block text-xs">Context Size</span>
211
+ <span class="text-gray-200 font-mono">${formatContextSize(m.contextChars)}</span>
212
+ </div>
213
+ <div>
214
+ <span class="text-gray-500 block text-xs">Input Tokens</span>
215
+ <span class="text-gray-200 font-mono">${m.inputTokens ? m.inputTokens.toLocaleString() : '-'}</span>
216
+ </div>
217
+ <div>
218
+ <span class="text-gray-500 block text-xs">Output Tokens</span>
219
+ <span class="text-gray-200 font-mono">${m.outputTokens ? m.outputTokens.toLocaleString() : '-'}</span>
220
+ </div>
221
+ </div>
222
+ </div>`;
223
+ } else {
224
+ metricsContainer.innerHTML = '';
225
+ }
226
+
173
227
  // Input section
174
228
  this.querySelector('#detailInput').innerHTML = `
175
229
  <details class="group">
@@ -239,6 +293,73 @@ export class MonitorView extends Component {
239
293
  } else {
240
294
  actionsContainer.innerHTML = '';
241
295
  }
296
+
297
+ // Activity feed (events + LLM output)
298
+ this.renderActivityFeed();
299
+ }
300
+
301
+ renderActivityFeed() {
302
+ const container = this.querySelector('#detailActivity');
303
+ const events = this.selectedTask?.events;
304
+ if (!events?.length) {
305
+ container.innerHTML = '';
306
+ return;
307
+ }
308
+
309
+ const rows = events.map(evt => {
310
+ const time = new Date(evt.timestamp).toLocaleTimeString();
311
+ if (evt.type === 'tool_start') {
312
+ const inputStr = typeof evt.input === 'string' ? evt.input : JSON.stringify(evt.input ?? {});
313
+ const truncInput = inputStr.length > 120 ? inputStr.slice(0, 120) + '...' : inputStr;
314
+ return `<div class="flex gap-2 py-1.5 border-b border-dark-border/50">
315
+ <span class="text-gray-600 text-xs font-mono flex-shrink-0 w-16">${time}</span>
316
+ <span class="text-xs"><i class="fas fa-play text-blue-400 mr-1"></i><span class="text-blue-300 font-medium">${escapeHtml(evt.tool)}</span> <span class="text-gray-500">${escapeHtml(truncInput)}</span></span>
317
+ </div>`;
318
+ }
319
+ if (evt.type === 'tool_end') {
320
+ let outputStr = '';
321
+ if (Array.isArray(evt.output)) {
322
+ outputStr = evt.output.map(p => p.type === 'image' ? `[image ${formatContextSize(p.bytes)}]` : p.text || '').join(' ');
323
+ } else if (typeof evt.output === 'string') {
324
+ outputStr = evt.output;
325
+ }
326
+ const truncOutput = outputStr.length > 200 ? outputStr.slice(0, 200) + '...' : outputStr;
327
+ return `<div class="flex gap-2 py-1.5 border-b border-dark-border/50">
328
+ <span class="text-gray-600 text-xs font-mono flex-shrink-0 w-16">${time}</span>
329
+ <span class="text-xs"><i class="fas fa-check text-green-400 mr-1"></i><span class="text-green-300 font-medium">${escapeHtml(evt.tool)}</span> <span class="text-gray-400">${escapeHtml(truncOutput)}</span></span>
330
+ </div>`;
331
+ }
332
+ if (evt.type === 'thinking') {
333
+ const truncContent = (evt.content || '').length > 200 ? evt.content.slice(0, 200) + '...' : evt.content;
334
+ return `<div class="flex gap-2 py-1.5 border-b border-dark-border/50">
335
+ <span class="text-gray-600 text-xs font-mono flex-shrink-0 w-16">${time}</span>
336
+ <span class="text-xs"><i class="fas fa-brain text-purple-400 mr-1"></i><span class="text-purple-300">${escapeHtml(truncContent)}</span></span>
337
+ </div>`;
338
+ }
339
+ if (evt.type === 'content') {
340
+ const truncContent = (evt.content || '').length > 300 ? evt.content.slice(0, 300) + '...' : evt.content;
341
+ return `<div class="flex gap-2 py-1.5 border-b border-dark-border/50">
342
+ <span class="text-gray-600 text-xs font-mono flex-shrink-0 w-16">${time}</span>
343
+ <span class="text-xs"><i class="fas fa-comment text-gray-400 mr-1"></i><span class="text-gray-300">${escapeHtml(truncContent)}</span></span>
344
+ </div>`;
345
+ }
346
+ return '';
347
+ }).join('');
348
+
349
+ container.innerHTML = `
350
+ <details open class="group">
351
+ <summary class="cursor-pointer text-sm font-medium text-gray-400 hover:text-gray-300 transition-colors">
352
+ <i class="fas fa-chevron-right text-xs mr-1 group-open:rotate-90 transition-transform inline-block"></i>
353
+ Activity (${events.length} events)
354
+ </summary>
355
+ <div class="mt-2 bg-dark-bg border border-dark-border rounded-lg p-3 max-h-96 overflow-y-auto custom-scrollbar">
356
+ ${rows}
357
+ </div>
358
+ </details>`;
359
+
360
+ // Auto-scroll to bottom
361
+ const feed = container.querySelector('.overflow-y-auto');
362
+ if (feed) feed.scrollTop = feed.scrollHeight;
242
363
  }
243
364
 
244
365
  async handleCancel() {
@@ -275,6 +396,15 @@ export class MonitorView extends Component {
275
396
  if (data.type === 'status' && this.selectedTask?.id === taskId) {
276
397
  this.loadTasks();
277
398
  }
399
+ if (data.type === 'metrics' && this.selectedTask?.id === taskId) {
400
+ this.selectedTask.metrics = data.metrics;
401
+ this.renderDetailPanel();
402
+ }
403
+ if (data.type === 'events' && this.selectedTask?.id === taskId) {
404
+ if (!this.selectedTask.events) this.selectedTask.events = [];
405
+ this.selectedTask.events.push(...data.events);
406
+ this.renderActivityFeed();
407
+ }
278
408
  if (data.type === 'done') {
279
409
  this.closeEventSource();
280
410
  }
@@ -360,9 +490,11 @@ export class MonitorView extends Component {
360
490
  </div>
361
491
 
362
492
  <div id="detailMeta" class="bg-dark-surface/50 border border-dark-border rounded-lg p-4"></div>
493
+ <div id="detailMetrics"></div>
363
494
  <div id="detailInputRequest"></div>
364
495
  <div id="detailInput"></div>
365
496
  <div id="detailResult"></div>
497
+ <div id="detailActivity"></div>
366
498
  <div id="detailActions"></div>
367
499
  </div>
368
500
  </div>
@@ -385,4 +517,10 @@ function kindBadgeClass(kind) {
385
517
  return map[kind] || 'bg-gray-500/20 text-gray-400';
386
518
  }
387
519
 
520
+ function formatContextSize(chars) {
521
+ if (chars >= 1_000_000) return `${(chars / 1_000_000).toFixed(1)}M`;
522
+ if (chars >= 1_000) return `${(chars / 1_000).toFixed(1)}K`;
523
+ return `${chars}`;
524
+ }
525
+
388
526
  customElements.define('monitor-view', MonitorView);