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,51 +1,87 @@
1
-
2
- import { Component } from '../utils/Component.js';
3
- import { api } from '../services/ApiService.js';
1
+ import { Component } from "../utils/Component.js";
2
+ import { api } from "../services/ApiService.js";
4
3
 
5
4
  const TYPE_COLORS = [
6
- '#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6',
7
- '#ec4899', '#06b6d4', '#f97316', '#14b8a6', '#a855f7',
8
- '#84cc16', '#e11d48', '#0ea5e9', '#d946ef', '#22c55e',
5
+ "#3b82f6",
6
+ "#10b981",
7
+ "#f59e0b",
8
+ "#ef4444",
9
+ "#8b5cf6",
10
+ "#ec4899",
11
+ "#06b6d4",
12
+ "#f97316",
13
+ "#14b8a6",
14
+ "#a855f7",
15
+ "#84cc16",
16
+ "#e11d48",
17
+ "#0ea5e9",
18
+ "#d946ef",
19
+ "#22c55e",
9
20
  ];
10
21
 
22
+ const SESSION_KEY = "graphView:positions";
23
+
11
24
  export class GraphView extends Component {
12
- constructor() {
13
- super();
14
- this.network = null;
15
- this.nodes = null; // vis.DataSet
16
- this.edges = null; // vis.DataSet
17
- this.selectedNodeId = null;
18
- this.typeColorMap = new Map();
19
- this.colorIndex = 0;
20
- this.expandedNodes = new Set();
25
+ constructor() {
26
+ super();
27
+ this.network = null;
28
+ this.nodes = null; // vis.DataSet
29
+ this.edges = null; // vis.DataSet
30
+ this.selectedNodeId = null;
31
+ this.typeColorMap = new Map();
32
+ this.colorIndex = 0;
33
+ this.expandedNodes = new Set();
34
+ }
35
+
36
+ async connectedCallback() {
37
+ super.connectedCallback();
38
+ await this.checkGraphConnection();
39
+ }
40
+
41
+ disconnectedCallback() {
42
+ this.savePositions();
43
+ if (this.network) {
44
+ this.network.destroy();
45
+ this.network = null;
21
46
  }
22
-
23
- async connectedCallback() {
24
- super.connectedCallback();
25
- await this.checkGraphConnection();
47
+ }
48
+
49
+ savePositions() {
50
+ if (!this.network || !this.nodes) return;
51
+ const positions = this.network.getPositions();
52
+ sessionStorage.setItem(SESSION_KEY, JSON.stringify(positions));
53
+ }
54
+
55
+ loadPositions() {
56
+ try {
57
+ const raw = sessionStorage.getItem(SESSION_KEY);
58
+ return raw ? JSON.parse(raw) : null;
59
+ } catch {
60
+ return null;
26
61
  }
27
-
28
- getColorForType(type) {
29
- if (this.typeColorMap.has(type)) return this.typeColorMap.get(type);
30
- const color = TYPE_COLORS[this.colorIndex % TYPE_COLORS.length];
31
- this.colorIndex++;
32
- this.typeColorMap.set(type, color);
33
- return color;
62
+ }
63
+
64
+ getColorForType(type) {
65
+ if (this.typeColorMap.has(type)) return this.typeColorMap.get(type);
66
+ const color = TYPE_COLORS[this.colorIndex % TYPE_COLORS.length];
67
+ this.colorIndex++;
68
+ this.typeColorMap.set(type, color);
69
+ return color;
70
+ }
71
+
72
+ async checkGraphConnection() {
73
+ try {
74
+ await api.getGraphConfig();
75
+ await this.loadFullGraph();
76
+ } catch (e) {
77
+ console.error("Failed to check graph config:", e);
78
+ this.renderError("Failed to connect to server");
34
79
  }
80
+ }
35
81
 
36
- async checkGraphConnection() {
37
- try {
38
- await api.getGraphConfig();
39
- await this.loadFullGraph();
40
- } catch (e) {
41
- console.error('Failed to check graph config:', e);
42
- this.renderError('Failed to connect to server');
43
- }
44
- }
45
-
46
- renderError(message) {
47
- const main = this.querySelector('#graphContainer');
48
- main.innerHTML = `
82
+ renderError(message) {
83
+ const main = this.querySelector("#graphContainer");
84
+ main.innerHTML = `
49
85
  <div class="flex items-center justify-center h-full">
50
86
  <div class="text-center p-8">
51
87
  <i class="fas fa-exclamation-circle text-4xl text-red-400 mb-4"></i>
@@ -53,274 +89,322 @@ export class GraphView extends Component {
53
89
  </div>
54
90
  </div>
55
91
  `;
92
+ }
93
+
94
+ async loadFullGraph() {
95
+ try {
96
+ const data = await api.getGraphFull(300);
97
+ if (this.network) {
98
+ this.mergeData(data);
99
+ } else {
100
+ this.initGraph(data);
101
+ }
102
+ } catch (e) {
103
+ console.error("Failed to load full graph:", e);
104
+ this.renderError("Failed to load graph data: " + e.message);
56
105
  }
57
-
58
- async loadFullGraph() {
59
- try {
60
- const data = await api.getGraphFull(300);
61
- if (this.network) {
62
- this.mergeData(data);
63
- } else {
64
- this.initGraph(data);
65
- }
66
- } catch (e) {
67
- console.error('Failed to load full graph:', e);
68
- this.renderError('Failed to load graph data: ' + e.message);
69
- }
106
+ }
107
+
108
+ async expandNode(nodeId) {
109
+ if (!nodeId) return;
110
+ try {
111
+ const beforeCount = this.nodes.length;
112
+ const data = await api.getGraphNeighbors(nodeId);
113
+ if (this.network) {
114
+ this.mergeData(data);
115
+ }
116
+
117
+ if (this.nodes.length > beforeCount) {
118
+ this.expandedNodes.add(nodeId);
119
+ }
120
+ } catch (e) {
121
+ console.error("Failed to expand node:", e);
70
122
  }
71
-
72
- async expandNode(nodeId) {
73
- if (!nodeId) return;
74
- try {
75
- const beforeCount = this.nodes.length;
76
- const data = await api.getGraphNeighbors(nodeId);
77
- if (this.network) {
78
- this.mergeData(data);
79
- }
80
-
81
- if (this.nodes.length > beforeCount) {
82
- this.expandedNodes.add(nodeId);
83
- }
84
- } catch (e) {
85
- console.error('Failed to expand node:', e);
86
- }
123
+ }
124
+
125
+ collapseNode(nodeId) {
126
+ // Remove from expanded FIRST to prevent infinite recursion
127
+ // (child neighbors that are also expanded won't recurse back here)
128
+ this.expandedNodes.delete(nodeId);
129
+
130
+ const neighborIds = this.edges
131
+ .get()
132
+ .filter((e) => e.from === nodeId || e.to === nodeId)
133
+ .map((e) => (e.from === nodeId ? e.to : e.from));
134
+
135
+ // Recursively collapse expanded children first
136
+ for (const nid of neighborIds) {
137
+ if (this.expandedNodes.has(nid)) {
138
+ this.collapseNode(nid);
139
+ }
87
140
  }
88
141
 
89
- collapseNode(nodeId) {
90
- // Remove from expanded FIRST to prevent infinite recursion
91
- // (child neighbors that are also expanded won't recurse back here)
92
- this.expandedNodes.delete(nodeId);
93
-
94
- const neighborIds = this.edges.get()
95
- .filter((e) => e.from === nodeId || e.to === nodeId)
96
- .map((e) => (e.from === nodeId ? e.to : e.from));
97
-
98
- // Recursively collapse expanded children first
99
- for (const nid of neighborIds) {
100
- if (this.expandedNodes.has(nid)) {
101
- this.collapseNode(nid);
102
- }
103
- }
104
-
105
- // Re-query neighbors after recursive collapses may have changed the graph
106
- const currentNeighborIds = this.edges.get()
107
- .filter((e) => e.from === nodeId || e.to === nodeId)
108
- .map((e) => (e.from === nodeId ? e.to : e.from));
109
-
110
- const removableNodes = currentNeighborIds.filter((nid) => {
111
- if (this.expandedNodes.has(nid)) return false;
112
- const allEdges = this.edges.get().filter(
113
- (e) => e.from === nid || e.to === nid
114
- );
115
- return allEdges.every(
116
- (e) => e.from === nodeId || e.to === nodeId
117
- );
118
- });
119
-
120
- if (removableNodes.length > 0) {
121
- const removeSet = new Set(removableNodes);
122
- const edgesToRemove = this.edges.get().filter(
123
- (e) => removeSet.has(e.from) || removeSet.has(e.to)
124
- );
125
- this.edges.remove(edgesToRemove.map((e) => e.id));
126
- this.nodes.remove(removableNodes);
127
- }
128
- }
129
-
130
- /**
131
- * Convert API nodes to vis.js node format.
132
- */
133
- toVisNodes(apiNodes) {
134
- return (apiNodes || []).map((n) => {
135
- if (n.type === 'KnowledgeBase') {
136
- return {
137
- id: n.id,
138
- label: n.name || n.id,
139
- title: n.description || n.name,
140
- shape: 'dot',
141
- size: 30,
142
- color: { background: '#3b82f6', border: '#60a5fa', highlight: { background: '#60a5fa', border: '#93c5fd' }, hover: { background: '#60a5fa', border: '#93c5fd' } },
143
- borderWidth: 3,
144
- font: { color: '#e2e8f0', size: 16, bold: { color: '#e2e8f0' } },
145
- _type: n.type,
146
- _name: n.name,
147
- _description: n.description,
148
- _properties: n.properties || {},
149
- };
150
- }
151
-
152
- const color = this.getColorForType(n.type);
153
- return {
154
- id: n.id,
155
- label: this.truncate(n.name || n.id, 20),
156
- title: n.description || n.name,
157
- shape: 'dot',
158
- size: 12,
159
- color: { background: color, border: color, highlight: { background: color, border: '#e2e8f0' }, hover: { background: color, border: '#e2e8f0' } },
160
- font: { color: '#e2e8f0', size: 12 },
161
- _type: n.type,
162
- _name: n.name,
163
- _description: n.description,
164
- _properties: n.properties || {},
165
- };
166
- });
167
- }
168
-
169
- /**
170
- * Convert API edges to vis.js edge format.
171
- */
172
- toVisEdges(apiEdges) {
173
- return (apiEdges || []).map((e) => ({
174
- id: e.id,
175
- from: e.source,
176
- to: e.target,
177
- label: e.type,
178
- title: e.description || e.type,
179
- arrows: 'to',
180
- color: { color: '#475569', highlight: '#60a5fa', hover: '#64748b' },
181
- font: { color: '#64748b', size: 9, strokeWidth: 0 },
182
- smooth: { type: 'continuous' },
183
- width: 1.5,
184
- // Store original data
185
- _type: e.type,
186
- _description: e.description,
187
- }));
188
- }
189
-
190
- initGraph(data) {
191
- const container = this.querySelector('#graphContainer');
192
- if (!container) return;
193
-
194
- const visNodes = this.toVisNodes(data.nodes);
195
- const visEdges = this.toVisEdges(data.edges);
196
- this.nodes = new vis.DataSet([...new Map(visNodes.map(n => [n.id, n])).values()]);
197
- this.edges = new vis.DataSet([...new Map(visEdges.map(e => [e.id, e])).values()]);
198
-
199
- this.network = new vis.Network(container, { nodes: this.nodes, edges: this.edges }, {
200
- physics: {
201
- stabilization: false,
202
- barnesHut: {
203
- gravitationalConstant: -4000,
204
- springLength: 250,
205
- springConstant: 0.02,
206
- damping: 0.3,
207
- avoidOverlap: 0.8,
208
- },
209
- },
210
- interaction: {
211
- hover: true,
212
- tooltipDelay: 200,
213
- navigationButtons: false,
214
- keyboard: false,
215
- },
216
- edges: {
217
- smooth: { type: 'continuous' },
218
- },
219
- });
220
-
221
- this.network.on('click', (params) => {
222
- if (params.nodes.length > 0) {
223
- this.onNodeClicked(params.nodes[0]);
224
- } else {
225
- this.querySelector('#sidebar')?.classList.add('hidden');
226
- this.selectedNodeId = null;
227
- }
228
- });
229
-
230
- this.network.on('doubleClick', (params) => {
231
- if (params.nodes.length > 0) {
232
- const nodeId = params.nodes[0];
233
- if (this.expandedNodes.has(nodeId)) {
234
- this.collapseNode(nodeId);
235
- } else {
236
- this.expandNode(nodeId);
237
- }
238
- }
239
- });
240
-
142
+ // Re-query neighbors after recursive collapses may have changed the graph
143
+ const currentNeighborIds = this.edges
144
+ .get()
145
+ .filter((e) => e.from === nodeId || e.to === nodeId)
146
+ .map((e) => (e.from === nodeId ? e.to : e.from));
147
+
148
+ const removableNodes = currentNeighborIds.filter((nid) => {
149
+ if (this.expandedNodes.has(nid)) return false;
150
+ const allEdges = this.edges
151
+ .get()
152
+ .filter((e) => e.from === nid || e.to === nid);
153
+ return allEdges.every((e) => e.from === nodeId || e.to === nodeId);
154
+ });
155
+
156
+ if (removableNodes.length > 0) {
157
+ const removeSet = new Set(removableNodes);
158
+ const edgesToRemove = this.edges
159
+ .get()
160
+ .filter((e) => removeSet.has(e.from) || removeSet.has(e.to));
161
+ this.edges.remove(edgesToRemove.map((e) => e.id));
162
+ this.nodes.remove(removableNodes);
241
163
  }
242
-
243
- /**
244
- * Merge new data into existing graph. vis.js DataSet handles dedup by id.
245
- * Physics smoothly repositions existing nodes no full re-render.
246
- */
247
- mergeData(data) {
248
- const newNodes = this.toVisNodes(data.nodes).filter((n) => !this.nodes.get(n.id));
249
- const newEdges = this.toVisEdges(data.edges).filter((e) => !this.edges.get(e.id));
250
-
251
- if (newNodes.length > 0) this.nodes.add(newNodes);
252
- if (newEdges.length > 0) this.edges.add(newEdges);
253
-
254
- }
255
-
256
- onNodeClicked(nodeId) {
257
- this.selectedNodeId = nodeId;
258
- this.showSidebar(nodeId);
164
+ }
165
+
166
+ /**
167
+ * Convert API nodes to vis.js node format.
168
+ */
169
+ toVisNodes(apiNodes) {
170
+ return (apiNodes || []).map((n) => {
171
+ if (n.type === "KnowledgeBase") {
172
+ return {
173
+ id: n.id,
174
+ label: n.name || n.id,
175
+ title: n.description || n.name,
176
+ shape: "dot",
177
+ size: 30,
178
+ color: {
179
+ background: "#3b82f6",
180
+ border: "#60a5fa",
181
+ highlight: { background: "#60a5fa", border: "#93c5fd" },
182
+ hover: { background: "#60a5fa", border: "#93c5fd" },
183
+ },
184
+ borderWidth: 3,
185
+ font: { color: "#e2e8f0", size: 16, bold: { color: "#e2e8f0" } },
186
+ _type: n.type,
187
+ _name: n.name,
188
+ _description: n.description,
189
+ _properties: n.properties || {},
190
+ };
191
+ }
192
+
193
+ const color = this.getColorForType(n.type);
194
+ return {
195
+ id: n.id,
196
+ label: this.truncate(n.name || n.id, 20),
197
+ title: n.description || n.name,
198
+ shape: "dot",
199
+ size: 12,
200
+ color: {
201
+ background: color,
202
+ border: color,
203
+ highlight: { background: color, border: "#e2e8f0" },
204
+ hover: { background: color, border: "#e2e8f0" },
205
+ },
206
+ font: { color: "#e2e8f0", size: 12 },
207
+ _type: n.type,
208
+ _name: n.name,
209
+ _description: n.description,
210
+ _properties: n.properties || {},
211
+ };
212
+ });
213
+ }
214
+
215
+ /**
216
+ * Convert API edges to vis.js edge format.
217
+ */
218
+ toVisEdges(apiEdges) {
219
+ return (apiEdges || []).map((e) => ({
220
+ id: e.id,
221
+ from: e.source,
222
+ to: e.target,
223
+ label: e.type,
224
+ title: e.description || e.type,
225
+ arrows: "to",
226
+ color: { color: "#475569", highlight: "#60a5fa", hover: "#64748b" },
227
+ font: { color: "#64748b", size: 9, strokeWidth: 0 },
228
+ smooth: { type: "continuous" },
229
+ width: 1.5,
230
+ // Store original data
231
+ _type: e.type,
232
+ _description: e.description,
233
+ }));
234
+ }
235
+
236
+ initGraph(data) {
237
+ const container = this.querySelector("#graphContainer");
238
+ if (!container) return;
239
+
240
+ const saved = this.loadPositions();
241
+ const visNodes = this.toVisNodes(data.nodes);
242
+ const visEdges = this.toVisEdges(data.edges);
243
+
244
+ // Restore saved positions so nodes don't all start from center
245
+ if (saved) {
246
+ for (const node of visNodes) {
247
+ if (saved[node.id]) {
248
+ node.x = saved[node.id].x;
249
+ node.y = saved[node.id].y;
250
+ }
251
+ }
259
252
  }
260
253
 
261
- showSidebar(nodeId) {
262
- const sidebar = this.querySelector('#sidebar');
263
- const sidebarContent = this.querySelector('#sidebarContent');
264
- sidebar.classList.remove('hidden');
265
-
266
- const nodeData = this.nodes.get(nodeId);
267
- if (!nodeData) return;
268
-
269
- const type = nodeData._type || 'Unknown';
270
- const props = nodeData._properties || {};
271
- const propKeys = Object.keys(props);
272
-
273
- const coreProps = [
274
- { key: 'name', val: nodeData._name },
275
- { key: 'description', val: nodeData._description },
276
- ].filter((p) => p.val);
277
-
278
- sidebarContent.innerHTML = `
254
+ this.nodes = new vis.DataSet([
255
+ ...new Map(visNodes.map((n) => [n.id, n])).values(),
256
+ ]);
257
+ this.edges = new vis.DataSet([
258
+ ...new Map(visEdges.map((e) => [e.id, e])).values(),
259
+ ]);
260
+
261
+ const hasPositions = saved && visNodes.some((n) => n.x !== undefined);
262
+
263
+ this.network = new vis.Network(
264
+ container,
265
+ { nodes: this.nodes, edges: this.edges },
266
+ {
267
+ physics: {
268
+ stabilization: false,
269
+ barnesHut: {
270
+ gravitationalConstant: -10000,
271
+ centralGravity: 1.5,
272
+ springLength: 340,
273
+ springConstant: 0.02,
274
+ damping: 0.3,
275
+ avoidOverlap: 0.8,
276
+ },
277
+ },
278
+ interaction: {
279
+ hover: true,
280
+ tooltipDelay: 200,
281
+ navigationButtons: false,
282
+ keyboard: false,
283
+ },
284
+ edges: {
285
+ smooth: { type: "continuous" },
286
+ },
287
+ },
288
+ );
289
+
290
+ // Save positions periodically as physics settles
291
+ //this.network.on('stabilized', () => this.savePositions());
292
+ //this.network.on('dragEnd', () => this.savePositions());
293
+
294
+ this.network.on("click", (params) => {
295
+ if (params.nodes.length > 0) {
296
+ this.onNodeClicked(params.nodes[0]);
297
+ } else {
298
+ this.querySelector("#sidebar")?.classList.add("hidden");
299
+ this.selectedNodeId = null;
300
+ }
301
+ });
302
+
303
+ this.network.on("doubleClick", (params) => {
304
+ if (params.nodes.length > 0) {
305
+ const nodeId = params.nodes[0];
306
+ if (this.expandedNodes.has(nodeId)) {
307
+ this.collapseNode(nodeId);
308
+ } else {
309
+ this.expandNode(nodeId);
310
+ }
311
+ }
312
+ });
313
+ }
314
+
315
+ /**
316
+ * Merge new data into existing graph. vis.js DataSet handles dedup by id.
317
+ * Physics smoothly repositions existing nodes — no full re-render.
318
+ */
319
+ mergeData(data) {
320
+ const newNodes = this.toVisNodes(data.nodes).filter(
321
+ (n) => !this.nodes.get(n.id),
322
+ );
323
+ const newEdges = this.toVisEdges(data.edges).filter(
324
+ (e) => !this.edges.get(e.id),
325
+ );
326
+
327
+ if (newNodes.length > 0) this.nodes.add(newNodes);
328
+ if (newEdges.length > 0) this.edges.add(newEdges);
329
+ }
330
+
331
+ onNodeClicked(nodeId) {
332
+ this.selectedNodeId = nodeId;
333
+ this.showSidebar(nodeId);
334
+ }
335
+
336
+ showSidebar(nodeId) {
337
+ const sidebar = this.querySelector("#sidebar");
338
+ const sidebarContent = this.querySelector("#sidebarContent");
339
+ sidebar.classList.remove("hidden");
340
+
341
+ const nodeData = this.nodes.get(nodeId);
342
+ if (!nodeData) return;
343
+
344
+ const type = nodeData._type || "Unknown";
345
+ const props = nodeData._properties || {};
346
+ const propKeys = Object.keys(props);
347
+
348
+ const coreProps = [
349
+ { key: "name", val: nodeData._name },
350
+ { key: "description", val: nodeData._description },
351
+ ].filter((p) => p.val);
352
+
353
+ sidebarContent.innerHTML = `
279
354
  <div class="mb-2">
280
355
  <h3 class="text-sm font-bold text-white">${this.escapeHtml(type)}</h3>
281
356
  <span class="text-xs text-gray-500 font-mono">${this.escapeHtml(nodeId)}</span>
282
357
  </div>
283
358
  <div class="space-y-1">
284
- ${[...coreProps.map((p) => this.renderProperty(p.key, p.val)),
285
- ...propKeys.map((key) => this.renderProperty(key, props[key]))
286
- ].join('')}
287
- ${coreProps.length === 0 && propKeys.length === 0
359
+ ${[
360
+ ...coreProps.map((p) => this.renderProperty(p.key, p.val)),
361
+ ...propKeys.map((key) =>
362
+ this.renderProperty(key, props[key]),
363
+ ),
364
+ ].join("")}
365
+ ${
366
+ coreProps.length === 0 && propKeys.length === 0
288
367
  ? '<p class="text-xs text-gray-500 italic">No properties</p>'
289
- : ''
368
+ : ""
290
369
  }
291
370
  </div>
292
371
  `;
293
- }
294
-
295
- renderProperty(key, val) {
296
- const displayVal = typeof val === 'string'
297
- ? (val.length > 120 ? val.substring(0, 120) + '...' : val)
298
- : JSON.stringify(val);
299
- return `
372
+ }
373
+
374
+ renderProperty(key, val) {
375
+ const displayVal =
376
+ typeof val === "string"
377
+ ? val.length > 120
378
+ ? val.substring(0, 120) + "..."
379
+ : val
380
+ : JSON.stringify(val);
381
+ return `
300
382
  <div class="bg-dark-bg rounded px-2 py-1 border border-dark-border">
301
383
  <span class="text-xs text-gray-500">${this.escapeHtml(key)}: </span>
302
384
  <span class="text-xs text-gray-200 break-words">${this.escapeHtml(displayVal)}</span>
303
385
  </div>
304
386
  `;
305
- }
306
-
307
-
308
- truncate(text, max) {
309
- if (!text) return '';
310
- return text.length > max ? text.substring(0, max) + '..' : text;
311
- }
312
-
313
- escapeHtml(text) {
314
- if (text === null || text === undefined) return '';
315
- return String(text).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
316
- }
317
-
318
- postRender() {
319
- // Graph initialized in checkGraphConnection on connectedCallback
320
- }
321
-
322
- template() {
323
- return `
387
+ }
388
+
389
+ truncate(text, max) {
390
+ if (!text) return "";
391
+ return text.length > max ? text.substring(0, max) + ".." : text;
392
+ }
393
+
394
+ escapeHtml(text) {
395
+ if (text === null || text === undefined) return "";
396
+ return String(text)
397
+ .replace(/&/g, "&amp;")
398
+ .replace(/</g, "&lt;")
399
+ .replace(/>/g, "&gt;");
400
+ }
401
+
402
+ postRender() {
403
+ // Graph initialized in checkGraphConnection on connectedCallback
404
+ }
405
+
406
+ template() {
407
+ return `
324
408
  <div class="h-full flex flex-col">
325
409
  <div class="flex-1 min-h-0 relative">
326
410
  <div id="graphContainer" class="h-full w-full rounded-lg graph-canvas"></div>
@@ -330,7 +414,7 @@ export class GraphView extends Component {
330
414
  </div>
331
415
  </div>
332
416
  `;
333
- }
417
+ }
334
418
  }
335
419
 
336
- customElements.define('graph-view', GraphView);
420
+ customElements.define("graph-view", GraphView);