@praveencs/agent 0.9.29 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/README.md +55 -9
  2. package/ROADMAP.md +42 -50
  3. package/agent-skills/README.md +192 -0
  4. package/agent-skills/plugins/aws/plugin.json +22 -0
  5. package/agent-skills/plugins/aws/skills/aws-manager.md +17 -0
  6. package/agent-skills/plugins/aws/tools/aws.js +152 -0
  7. package/agent-skills/plugins/discord/plugin.json +22 -0
  8. package/agent-skills/plugins/discord/skills/discord-manager.md +15 -0
  9. package/agent-skills/plugins/discord/tools/discord.js +150 -0
  10. package/agent-skills/plugins/docker/plugin.json +21 -0
  11. package/agent-skills/plugins/docker/skills/docker-manager.md +15 -0
  12. package/agent-skills/plugins/docker/tools/docker.js +135 -0
  13. package/agent-skills/plugins/firebase/plugin.json +22 -0
  14. package/agent-skills/plugins/firebase/skills/firebase-manager.md +14 -0
  15. package/agent-skills/plugins/firebase/tools/firebase.js +157 -0
  16. package/agent-skills/plugins/github/plugin.json +23 -0
  17. package/agent-skills/plugins/github/skills/github-manager.md +15 -0
  18. package/agent-skills/plugins/github/tools/github.js +133 -0
  19. package/agent-skills/plugins/huggingface/plugin.json +22 -0
  20. package/agent-skills/plugins/huggingface/skills/huggingface-manager.md +16 -0
  21. package/agent-skills/plugins/huggingface/tools/huggingface.js +149 -0
  22. package/agent-skills/plugins/linear/plugin.json +22 -0
  23. package/agent-skills/plugins/linear/skills/linear-manager.md +16 -0
  24. package/agent-skills/plugins/linear/tools/linear.js +199 -0
  25. package/agent-skills/plugins/mongodb/plugin.json +21 -0
  26. package/agent-skills/plugins/mongodb/skills/mongodb-manager.md +14 -0
  27. package/agent-skills/plugins/mongodb/tools/mongodb.js +123 -0
  28. package/agent-skills/plugins/notion/plugin.json +22 -0
  29. package/agent-skills/plugins/notion/skills/notion-manager.md +16 -0
  30. package/agent-skills/plugins/notion/tools/notion.js +158 -0
  31. package/agent-skills/plugins/openai/plugin.json +23 -0
  32. package/agent-skills/plugins/openai/skills/openai-manager.md +15 -0
  33. package/agent-skills/plugins/openai/tools/openai.js +137 -0
  34. package/agent-skills/plugins/resend/plugin.json +21 -0
  35. package/agent-skills/plugins/resend/skills/resend-manager.md +15 -0
  36. package/agent-skills/plugins/resend/tools/resend.js +102 -0
  37. package/agent-skills/plugins/slack/plugin.json +22 -0
  38. package/agent-skills/plugins/slack/skills/slack-manager.md +15 -0
  39. package/agent-skills/plugins/slack/tools/slack.js +168 -0
  40. package/agent-skills/plugins/stripe/plugin.json +22 -0
  41. package/agent-skills/plugins/stripe/skills/stripe-manager.md +16 -0
  42. package/agent-skills/plugins/stripe/tools/stripe.js +174 -0
  43. package/agent-skills/plugins/supabase/plugin.json +22 -0
  44. package/agent-skills/plugins/supabase/skills/supabase-manager.md +16 -0
  45. package/agent-skills/plugins/supabase/tools/supabase.js +153 -0
  46. package/agent-skills/plugins/telegram/plugin.json +21 -0
  47. package/agent-skills/plugins/telegram/skills/telegram-manager.md +14 -0
  48. package/agent-skills/plugins/telegram/tools/telegram.js +131 -0
  49. package/agent-skills/plugins/vercel/plugin.json +22 -0
  50. package/agent-skills/plugins/vercel/skills/vercel-manager.md +15 -0
  51. package/agent-skills/plugins/vercel/tools/vercel.js +145 -0
  52. package/agent-skills/registry.json +675 -0
  53. package/agent-skills/skills/api-tester/prompt.md +27 -0
  54. package/agent-skills/skills/api-tester/skill.json +16 -0
  55. package/agent-skills/skills/backup/prompt.md +12 -0
  56. package/agent-skills/skills/backup/skill.json +1 -0
  57. package/agent-skills/skills/code-review/prompt.md +29 -0
  58. package/agent-skills/skills/code-review/skill.json +18 -0
  59. package/agent-skills/skills/create-note/prompt.md +21 -0
  60. package/agent-skills/skills/create-note/skill.json +15 -0
  61. package/agent-skills/skills/cron-scheduler/prompt.md +25 -0
  62. package/agent-skills/skills/cron-scheduler/skill.json +1 -0
  63. package/agent-skills/skills/db-query/prompt.md +12 -0
  64. package/agent-skills/skills/db-query/skill.json +1 -0
  65. package/agent-skills/skills/docker-deploy/prompt.md +21 -0
  66. package/agent-skills/skills/docker-deploy/skill.json +16 -0
  67. package/agent-skills/skills/file-organizer/prompt.md +32 -0
  68. package/agent-skills/skills/file-organizer/skill.json +19 -0
  69. package/agent-skills/skills/git-commit/prompt.md +21 -0
  70. package/agent-skills/skills/git-commit/skill.json +17 -0
  71. package/agent-skills/skills/log-analyzer/prompt.md +16 -0
  72. package/agent-skills/skills/log-analyzer/skill.json +1 -0
  73. package/agent-skills/skills/npm-publish/prompt.md +24 -0
  74. package/agent-skills/skills/npm-publish/skill.json +20 -0
  75. package/agent-skills/skills/open-vscode/prompt.md +8 -0
  76. package/agent-skills/skills/open-vscode/skill.json +15 -0
  77. package/agent-skills/skills/project-scaffold/prompt.md +43 -0
  78. package/agent-skills/skills/project-scaffold/skill.json +17 -0
  79. package/agent-skills/skills/send-email/prompt.md +19 -0
  80. package/agent-skills/skills/send-email/send.js +60 -0
  81. package/agent-skills/skills/send-email/skill.json +16 -0
  82. package/agent-skills/skills/system-monitor/prompt.md +27 -0
  83. package/agent-skills/skills/system-monitor/skill.json +15 -0
  84. package/agent-skills/skills/web-search/prompt.md +26 -0
  85. package/agent-skills/skills/web-search/skill.json +16 -0
  86. package/dist/src/cli/commands/desktop.d.ts +3 -0
  87. package/dist/src/cli/commands/desktop.d.ts.map +1 -0
  88. package/dist/src/cli/commands/desktop.js +80 -0
  89. package/dist/src/cli/commands/desktop.js.map +1 -0
  90. package/dist/src/cli/commands/multimodal.d.ts +3 -0
  91. package/dist/src/cli/commands/multimodal.d.ts.map +1 -0
  92. package/dist/src/cli/commands/multimodal.js +78 -0
  93. package/dist/src/cli/commands/multimodal.js.map +1 -0
  94. package/dist/src/cli/commands/plugins.d.ts.map +1 -1
  95. package/dist/src/cli/commands/plugins.js +63 -12
  96. package/dist/src/cli/commands/plugins.js.map +1 -1
  97. package/dist/src/cli/commands/sandbox.d.ts +3 -0
  98. package/dist/src/cli/commands/sandbox.d.ts.map +1 -0
  99. package/dist/src/cli/commands/sandbox.js +89 -0
  100. package/dist/src/cli/commands/sandbox.js.map +1 -0
  101. package/dist/src/cli/commands/skills.d.ts.map +1 -1
  102. package/dist/src/cli/commands/skills.js +52 -121
  103. package/dist/src/cli/commands/skills.js.map +1 -1
  104. package/dist/src/cli/commands/swarm.d.ts +3 -0
  105. package/dist/src/cli/commands/swarm.d.ts.map +1 -0
  106. package/dist/src/cli/commands/swarm.js +120 -0
  107. package/dist/src/cli/commands/swarm.js.map +1 -0
  108. package/dist/src/cli/index.d.ts.map +1 -1
  109. package/dist/src/cli/index.js +8 -0
  110. package/dist/src/cli/index.js.map +1 -1
  111. package/dist/src/config/defaults.d.ts.map +1 -1
  112. package/dist/src/config/defaults.js +42 -0
  113. package/dist/src/config/defaults.js.map +1 -1
  114. package/dist/src/config/loader.d.ts +4 -0
  115. package/dist/src/config/loader.d.ts.map +1 -1
  116. package/dist/src/config/loader.js +27 -6
  117. package/dist/src/config/loader.js.map +1 -1
  118. package/dist/src/config/schema.d.ts +261 -0
  119. package/dist/src/config/schema.d.ts.map +1 -1
  120. package/dist/src/config/schema.js +58 -0
  121. package/dist/src/config/schema.js.map +1 -1
  122. package/dist/src/desktop/engine.d.ts +42 -0
  123. package/dist/src/desktop/engine.d.ts.map +1 -0
  124. package/dist/src/desktop/engine.js +77 -0
  125. package/dist/src/desktop/engine.js.map +1 -0
  126. package/dist/src/desktop/index.d.ts +6 -0
  127. package/dist/src/desktop/index.d.ts.map +1 -0
  128. package/dist/src/desktop/index.js +6 -0
  129. package/dist/src/desktop/index.js.map +1 -0
  130. package/dist/src/desktop/input.d.ts +20 -0
  131. package/dist/src/desktop/input.d.ts.map +1 -0
  132. package/dist/src/desktop/input.js +160 -0
  133. package/dist/src/desktop/input.js.map +1 -0
  134. package/dist/src/desktop/screen.d.ts +17 -0
  135. package/dist/src/desktop/screen.d.ts.map +1 -0
  136. package/dist/src/desktop/screen.js +120 -0
  137. package/dist/src/desktop/screen.js.map +1 -0
  138. package/dist/src/desktop/types.d.ts +50 -0
  139. package/dist/src/desktop/types.d.ts.map +1 -0
  140. package/dist/src/desktop/types.js +10 -0
  141. package/dist/src/desktop/types.js.map +1 -0
  142. package/dist/src/hub/lockfile.d.ts +29 -0
  143. package/dist/src/hub/lockfile.d.ts.map +1 -0
  144. package/dist/src/hub/lockfile.js +72 -0
  145. package/dist/src/hub/lockfile.js.map +1 -0
  146. package/dist/src/hub/publisher.d.ts +13 -0
  147. package/dist/src/hub/publisher.d.ts.map +1 -0
  148. package/dist/src/hub/publisher.js +159 -0
  149. package/dist/src/hub/publisher.js.map +1 -0
  150. package/dist/src/hub/registry.d.ts +40 -0
  151. package/dist/src/hub/registry.d.ts.map +1 -0
  152. package/dist/src/hub/registry.js +123 -0
  153. package/dist/src/hub/registry.js.map +1 -0
  154. package/dist/src/multimodal/engine.d.ts +33 -0
  155. package/dist/src/multimodal/engine.d.ts.map +1 -0
  156. package/dist/src/multimodal/engine.js +63 -0
  157. package/dist/src/multimodal/engine.js.map +1 -0
  158. package/dist/src/multimodal/index.d.ts +7 -0
  159. package/dist/src/multimodal/index.d.ts.map +1 -0
  160. package/dist/src/multimodal/index.js +7 -0
  161. package/dist/src/multimodal/index.js.map +1 -0
  162. package/dist/src/multimodal/tts.d.ts +11 -0
  163. package/dist/src/multimodal/tts.d.ts.map +1 -0
  164. package/dist/src/multimodal/tts.js +48 -0
  165. package/dist/src/multimodal/tts.js.map +1 -0
  166. package/dist/src/multimodal/types.d.ts +55 -0
  167. package/dist/src/multimodal/types.d.ts.map +1 -0
  168. package/dist/src/multimodal/types.js +20 -0
  169. package/dist/src/multimodal/types.js.map +1 -0
  170. package/dist/src/multimodal/vision.d.ts +15 -0
  171. package/dist/src/multimodal/vision.d.ts.map +1 -0
  172. package/dist/src/multimodal/vision.js +98 -0
  173. package/dist/src/multimodal/vision.js.map +1 -0
  174. package/dist/src/multimodal/voice.d.ts +11 -0
  175. package/dist/src/multimodal/voice.d.ts.map +1 -0
  176. package/dist/src/multimodal/voice.js +43 -0
  177. package/dist/src/multimodal/voice.js.map +1 -0
  178. package/dist/src/plans/types.d.ts +18 -18
  179. package/dist/src/plugins/loader.d.ts.map +1 -1
  180. package/dist/src/plugins/loader.js +10 -0
  181. package/dist/src/plugins/loader.js.map +1 -1
  182. package/dist/src/sandbox/docker.d.ts +42 -0
  183. package/dist/src/sandbox/docker.d.ts.map +1 -0
  184. package/dist/src/sandbox/docker.js +131 -0
  185. package/dist/src/sandbox/docker.js.map +1 -0
  186. package/dist/src/sandbox/engine.d.ts +50 -0
  187. package/dist/src/sandbox/engine.d.ts.map +1 -0
  188. package/dist/src/sandbox/engine.js +133 -0
  189. package/dist/src/sandbox/engine.js.map +1 -0
  190. package/dist/src/sandbox/index.d.ts +5 -0
  191. package/dist/src/sandbox/index.d.ts.map +1 -0
  192. package/dist/src/sandbox/index.js +5 -0
  193. package/dist/src/sandbox/index.js.map +1 -0
  194. package/dist/src/sandbox/types.d.ts +41 -0
  195. package/dist/src/sandbox/types.d.ts.map +1 -0
  196. package/dist/src/sandbox/types.js +12 -0
  197. package/dist/src/sandbox/types.js.map +1 -0
  198. package/dist/src/scripts/types.d.ts +2 -2
  199. package/dist/src/server/app.d.ts.map +1 -1
  200. package/dist/src/server/app.js +133 -0
  201. package/dist/src/server/app.js.map +1 -1
  202. package/dist/src/skills/loader.d.ts.map +1 -1
  203. package/dist/src/skills/loader.js +10 -0
  204. package/dist/src/skills/loader.js.map +1 -1
  205. package/dist/src/swarm/bus.d.ts +27 -0
  206. package/dist/src/swarm/bus.d.ts.map +1 -0
  207. package/dist/src/swarm/bus.js +64 -0
  208. package/dist/src/swarm/bus.js.map +1 -0
  209. package/dist/src/swarm/index.d.ts +6 -0
  210. package/dist/src/swarm/index.d.ts.map +1 -0
  211. package/dist/src/swarm/index.js +6 -0
  212. package/dist/src/swarm/index.js.map +1 -0
  213. package/dist/src/swarm/orchestrator.d.ts +79 -0
  214. package/dist/src/swarm/orchestrator.d.ts.map +1 -0
  215. package/dist/src/swarm/orchestrator.js +271 -0
  216. package/dist/src/swarm/orchestrator.js.map +1 -0
  217. package/dist/src/swarm/roles.d.ts +18 -0
  218. package/dist/src/swarm/roles.d.ts.map +1 -0
  219. package/dist/src/swarm/roles.js +83 -0
  220. package/dist/src/swarm/roles.js.map +1 -0
  221. package/dist/src/swarm/types.d.ts +58 -0
  222. package/dist/src/swarm/types.d.ts.map +1 -0
  223. package/dist/src/swarm/types.js +10 -0
  224. package/dist/src/swarm/types.js.map +1 -0
  225. package/dist/src/tools/core/cmd.d.ts.map +1 -1
  226. package/dist/src/tools/core/cmd.js +28 -0
  227. package/dist/src/tools/core/cmd.js.map +1 -1
  228. package/dist/src/utils/paths.d.ts +4 -4
  229. package/dist/src/utils/paths.d.ts.map +1 -1
  230. package/dist/src/utils/paths.js +8 -8
  231. package/dist/src/utils/paths.js.map +1 -1
  232. package/docs/DOCUMENTATION.md +137 -0
  233. package/package.json +4 -2
  234. package/studio/README.md +73 -0
  235. package/studio/eslint.config.js +23 -0
  236. package/studio/index.html +13 -0
  237. package/studio/package-lock.json +4350 -0
  238. package/studio/package.json +44 -0
  239. package/studio/postcss.config.js +6 -0
  240. package/studio/public/vite.svg +1 -0
  241. package/studio/src/App.tsx +243 -0
  242. package/studio/src/assets/react.svg +1 -0
  243. package/studio/src/components/Capabilities.tsx +80 -0
  244. package/studio/src/components/CommandsManager.tsx +94 -0
  245. package/studio/src/components/CostDashboard.tsx +182 -0
  246. package/studio/src/components/CredentialCapture.tsx +196 -0
  247. package/studio/src/components/CredentialsManager.tsx +257 -0
  248. package/studio/src/components/DaemonPanel.tsx +91 -0
  249. package/studio/src/components/DesktopPanel.tsx +118 -0
  250. package/studio/src/components/GoalTemplates.tsx +190 -0
  251. package/studio/src/components/GoalsPanel.tsx +235 -0
  252. package/studio/src/components/MemoryExplorer.tsx +152 -0
  253. package/studio/src/components/MultimodalPanel.tsx +150 -0
  254. package/studio/src/components/NotificationsPanel.tsx +175 -0
  255. package/studio/src/components/PluginsManager.tsx +60 -0
  256. package/studio/src/components/SandboxPanel.tsx +118 -0
  257. package/studio/src/components/ScriptsManager.tsx +269 -0
  258. package/studio/src/components/SkillsManager.tsx +123 -0
  259. package/studio/src/components/SwarmPanel.tsx +149 -0
  260. package/studio/src/components/TaskStreaming.tsx +189 -0
  261. package/studio/src/components/Terminal.tsx +200 -0
  262. package/studio/src/index.css +51 -0
  263. package/studio/src/main.tsx +13 -0
  264. package/studio/tailwind.config.js +47 -0
  265. package/studio/tsconfig.app.json +28 -0
  266. package/studio/tsconfig.json +7 -0
  267. package/studio/tsconfig.node.json +26 -0
  268. package/studio/vite.config.ts +7 -0
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "studio",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc -b && vite build",
9
+ "lint": "eslint .",
10
+ "preview": "vite preview"
11
+ },
12
+ "dependencies": {
13
+ "clsx": "^2.1.1",
14
+ "date-fns": "^4.1.0",
15
+ "lucide-react": "^0.575.0",
16
+ "react": "^19.2.4",
17
+ "react-dom": "^19.2.4",
18
+ "react-router-dom": "^7.13.1",
19
+ "socket.io-client": "^4.8.3",
20
+ "tailwind-merge": "^3.5.0"
21
+ },
22
+ "devDependencies": {
23
+ "@eslint/js": "^9.39.1",
24
+ "@types/node": "^24.10.1",
25
+ "@types/react": "^19.2.14",
26
+ "@types/react-dom": "^19.2.3",
27
+ "@vitejs/plugin-react": "^5.1.4",
28
+ "autoprefixer": "^10.4.27",
29
+ "eslint": "^9.39.1",
30
+ "eslint-plugin-react-hooks": "^7.0.1",
31
+ "eslint-plugin-react-refresh": "^0.4.24",
32
+ "globals": "^16.5.0",
33
+ "postcss": "^8.5.6",
34
+ "tailwindcss": "^3.4.19",
35
+ "typescript": "~5.9.3",
36
+ "typescript-eslint": "^8.48.0",
37
+ "vite": "^7.3.1"
38
+ },
39
+ "description": "This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.",
40
+ "main": "eslint.config.js",
41
+ "keywords": [],
42
+ "author": "",
43
+ "license": "ISC"
44
+ }
@@ -0,0 +1,6 @@
1
+ export default {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
@@ -0,0 +1,243 @@
1
+ import { useState, useEffect } from 'react';
2
+ import { Routes, Route, Link, useNavigate, useParams } from 'react-router-dom';
3
+ import {
4
+ Terminal, Activity, Workflow, Server, ArrowLeft, Zap, Target,
5
+ Wrench, Code, FileCode, Package, Brain, Sparkles, KeyRound, DollarSign, Bell,
6
+ Container, Users, Monitor, Mic
7
+ } from 'lucide-react';
8
+ import { Terminal as TerminalComponent } from './components/Terminal';
9
+ import { Capabilities } from './components/Capabilities';
10
+ import { GoalsPanel } from './components/GoalsPanel';
11
+ import { SkillsManager } from './components/SkillsManager';
12
+ import { CommandsManager } from './components/CommandsManager';
13
+ import { ScriptsManager } from './components/ScriptsManager';
14
+ import { PluginsManager } from './components/PluginsManager';
15
+ import { DaemonPanel } from './components/DaemonPanel';
16
+ import { MemoryExplorer } from './components/MemoryExplorer';
17
+ import { GoalTemplates } from './components/GoalTemplates';
18
+ import CredentialsManager from './components/CredentialsManager';
19
+ import TaskStreaming from './components/TaskStreaming';
20
+ import CredentialCapture from './components/CredentialCapture';
21
+ import CostDashboard from './components/CostDashboard';
22
+ import NotificationsPanel from './components/NotificationsPanel';
23
+ import SandboxPanel from './components/SandboxPanel';
24
+ import SwarmPanel from './components/SwarmPanel';
25
+ import DesktopPanel from './components/DesktopPanel';
26
+ import MultimodalPanel from './components/MultimodalPanel';
27
+
28
+ export default function App() {
29
+ return (
30
+ <div className="min-h-screen bg-neutral-950 text-neutral-200 flex flex-col font-sans">
31
+ <Routes>
32
+ <Route path="/" element={<Dashboard />} />
33
+ <Route path="/instance/:id/*" element={<InstanceView />} />
34
+ </Routes>
35
+ </div>
36
+ );
37
+ }
38
+
39
+ function Dashboard() {
40
+ const [instances, setInstances] = useState<any[]>([]);
41
+ const [loading, setLoading] = useState(true);
42
+ const navigate = useNavigate();
43
+
44
+ useEffect(() => {
45
+ fetchInstances();
46
+ const interval = setInterval(fetchInstances, 5000);
47
+ return () => clearInterval(interval);
48
+ }, []);
49
+
50
+ const fetchInstances = async () => {
51
+ try {
52
+ const res = await fetch('http://localhost:3333/api/instances');
53
+ const data = await res.json();
54
+ setInstances(data);
55
+ } catch (err) {
56
+ console.error("Failed to fetch instances", err);
57
+ } finally {
58
+ setLoading(false);
59
+ }
60
+ };
61
+
62
+ return (
63
+ <>
64
+ {/* Top Navbar */}
65
+ <header className="h-14 border-b border-white/10 flex items-center px-6 shrink-0 bg-neutral-900/50 backdrop-blur-md sticky top-0 z-10">
66
+ <div className="flex items-center gap-3">
67
+ <div className="h-8 w-8 rounded-lg bg-indigo-500/20 flex items-center justify-center border border-indigo-500/30 text-indigo-400">
68
+ <Workflow size={18} />
69
+ </div>
70
+ <h1 className="font-semibold text-lg tracking-tight">Agent Studio</h1>
71
+ </div>
72
+ <div className="ml-auto flex items-center gap-4 text-sm text-neutral-400">
73
+ <div className="flex items-center gap-2">
74
+ <span className="relative flex h-2.5 w-2.5">
75
+ <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
76
+ <span className="relative inline-flex rounded-full h-2.5 w-2.5 bg-emerald-500"></span>
77
+ </span>
78
+ {instances.length} Active System{instances.length === 1 ? '' : 's'}
79
+ </div>
80
+ </div>
81
+ </header>
82
+
83
+ {/* Main Content Area */}
84
+ <main className="flex-1 p-8 max-w-7xl mx-auto w-full">
85
+ <div className="mb-8 flex items-center justify-between">
86
+ <div>
87
+ <h2 className="text-2xl font-semibold mb-1">Local Instances</h2>
88
+ <p className="text-neutral-500 text-sm">Monitor and control your active autonomous agent environments.</p>
89
+ </div>
90
+ </div>
91
+
92
+ {loading ? (
93
+ <div className="flex items-center justify-center p-20 text-neutral-500">
94
+ <Activity className="animate-spin mr-3" size={20} /> Loading nodes...
95
+ </div>
96
+ ) : instances.length === 0 ? (
97
+ <div className="border border-white/10 border-dashed rounded-xl p-16 text-center bg-neutral-900/20">
98
+ <Terminal className="mx-auto mb-4 text-neutral-600" size={32} />
99
+ <h3 className="text-lg font-medium mb-2">No Active Agents</h3>
100
+ <p className="text-neutral-500 max-w-sm mx-auto mb-6 text-sm">
101
+ Start an agent in any project directory using <code className="bg-neutral-800 px-1 py-0.5 rounded text-neutral-300">agent</code> or <code className="bg-neutral-800 px-1 py-0.5 rounded text-neutral-300">agent daemon start</code>, and it will appear here automatically.
102
+ </p>
103
+ </div>
104
+ ) : (
105
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
106
+ {instances.map((instance) => {
107
+ const isDaemon = instance.id.startsWith('daemon');
108
+ return (
109
+ <div key={instance.id} className="group border border-white/10 bg-neutral-900/40 rounded-xl p-5 hover:bg-neutral-900/80 hover:border-white/20 transition-all cursor-pointer relative overflow-hidden flex flex-col">
110
+ <div className="absolute top-0 inset-x-0 h-1/2 bg-gradient-to-b from-white/[0.03] to-transparent pointer-events-none" />
111
+
112
+ <div className="flex justify-between items-start mb-4 relative z-10">
113
+ <div className="flex items-center gap-3">
114
+ <div className={`p-2 rounded-lg border flex-shrink-0 ${isDaemon ? 'bg-amber-500/10 border-amber-500/20 text-amber-500' : 'bg-blue-500/10 border-blue-500/20 text-blue-400'}`}>
115
+ {isDaemon ? <Server size={18} /> : <Terminal size={18} />}
116
+ </div>
117
+ <div>
118
+ <h3 className="font-medium text-neutral-100 leading-tight">
119
+ {instance.project || 'Agent Workspace'}
120
+ </h3>
121
+ <span className="text-xs font-mono text-neutral-500 break-all line-clamp-1 mt-0.5">
122
+ PID: {instance.pid}
123
+ </span>
124
+ </div>
125
+ </div>
126
+
127
+ <div className="flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 text-xs font-medium">
128
+ <div className="h-1.5 w-1.5 rounded-full bg-emerald-400" />
129
+ Active
130
+ </div>
131
+ </div>
132
+
133
+ <div className="mt-auto space-y-3 relative z-10">
134
+ <div className="flex items-center text-neutral-400 bg-black/20 p-2.5 rounded-md font-mono text-xs overflow-hidden text-ellipsis whitespace-nowrap border border-white/5">
135
+ {instance.cwd}
136
+ </div>
137
+
138
+ <div className="grid grid-cols-2 gap-2 mt-4">
139
+ <button
140
+ onClick={() => navigate(`/instance/${instance.id}/console`)}
141
+ className="text-xs font-medium py-1.5 border border-white/10 rounded-md bg-white/5 hover:bg-white/10 text-neutral-300 transition-colors"
142
+ >
143
+ View Console
144
+ </button>
145
+ <button
146
+ onClick={() => navigate(`/instance/${instance.id}/capabilities`)}
147
+ className="text-xs font-medium py-1.5 border border-white/10 rounded-md bg-white/5 hover:bg-white/10 text-neutral-300 transition-colors"
148
+ >
149
+ Capabilities
150
+ </button>
151
+ </div>
152
+ </div>
153
+ </div>
154
+ );
155
+ })}
156
+ </div>
157
+ )}
158
+ </main>
159
+ </>
160
+ );
161
+ }
162
+
163
+ const sidebarItems = [
164
+ { icon: Terminal, label: 'Console', path: 'console' },
165
+ { icon: Zap, label: 'Capabilities', path: 'capabilities' },
166
+ { icon: Target, label: 'Goals & Tasks', path: 'goals' },
167
+ { icon: Sparkles, label: 'Templates', path: 'templates' },
168
+ { icon: KeyRound, label: 'Credentials', path: 'credentials' },
169
+ { icon: Activity, label: 'Live Stream', path: 'stream' },
170
+ { icon: Wrench, label: 'Skills', path: 'skills' },
171
+ { icon: Code, label: 'Commands', path: 'commands' },
172
+ { icon: FileCode, label: 'Scripts', path: 'scripts' },
173
+ { icon: Package, label: 'Plugins', path: 'plugins' },
174
+ { icon: Server, label: 'Daemon', path: 'daemon' },
175
+ { icon: DollarSign, label: 'Costs', path: 'costs' },
176
+ { icon: Bell, label: 'Notifications', path: 'notifications' },
177
+ { icon: Brain, label: 'Memory', path: 'memory' },
178
+ { icon: Container, label: 'Sandbox', path: 'sandbox' },
179
+ { icon: Users, label: 'Swarm', path: 'swarm' },
180
+ { icon: Monitor, label: 'Desktop', path: 'desktop' },
181
+ { icon: Mic, label: 'Multimodal', path: 'multimodal' },
182
+ ];
183
+
184
+ function InstanceView() {
185
+ const navigate = useNavigate();
186
+ const { id } = useParams<{ id: string }>();
187
+ const currentTab = window.location.pathname.split('/').pop() || 'console';
188
+
189
+ return (
190
+ <div className="flex h-screen overflow-hidden">
191
+ {/* Sidebar */}
192
+ <aside className="w-56 border-r border-white/10 bg-neutral-900/50 flex flex-col shrink-0">
193
+ <div className="p-4 border-b border-white/10 flex items-center gap-2">
194
+ <button onClick={() => navigate('/')} className="hover:bg-white/10 p-1.5 rounded-md text-neutral-400 hover:text-white transition-colors">
195
+ <ArrowLeft size={16} />
196
+ </button>
197
+ <div className="font-medium truncate text-sm">Instance Control</div>
198
+ </div>
199
+
200
+ <nav className="p-2 space-y-0.5 mt-1 flex-1 overflow-y-auto">
201
+ {sidebarItems.map(({ icon: Icon, label, path }) => (
202
+ <Link
203
+ key={path}
204
+ to={`/instance/${id}/${path}`}
205
+ className={`flex items-center gap-2.5 px-3 py-2 rounded-md text-sm font-medium transition-colors ${currentTab === path
206
+ ? 'bg-indigo-500/10 text-indigo-400 border border-indigo-500/20'
207
+ : 'text-neutral-400 hover:bg-white/5 hover:text-neutral-200'
208
+ }`}
209
+ >
210
+ <Icon size={15} /> {label}
211
+ </Link>
212
+ ))}
213
+ </nav>
214
+ </aside>
215
+
216
+ {/* Main View Area */}
217
+ <div className="flex-1 bg-neutral-950 flex flex-col overflow-hidden relative">
218
+ <Routes>
219
+ <Route path="console" element={<TerminalComponent />} />
220
+ <Route path="capabilities" element={<Capabilities />} />
221
+ <Route path="goals" element={<GoalsPanel />} />
222
+ <Route path="templates" element={<GoalTemplates />} />
223
+ <Route path="credentials" element={<CredentialsManager />} />
224
+ <Route path="stream" element={<TaskStreaming />} />
225
+ <Route path="skills" element={<SkillsManager />} />
226
+ <Route path="commands" element={<CommandsManager />} />
227
+ <Route path="scripts" element={<ScriptsManager />} />
228
+ <Route path="plugins" element={<PluginsManager />} />
229
+ <Route path="daemon" element={<DaemonPanel />} />
230
+ <Route path="costs" element={<CostDashboard />} />
231
+ <Route path="notifications" element={<NotificationsPanel />} />
232
+ <Route path="memory" element={<MemoryExplorer />} />
233
+ <Route path="sandbox" element={<SandboxPanel />} />
234
+ <Route path="swarm" element={<SwarmPanel />} />
235
+ <Route path="desktop" element={<DesktopPanel />} />
236
+ <Route path="multimodal" element={<MultimodalPanel />} />
237
+ </Routes>
238
+ {/* Global credential capture modal */}
239
+ <CredentialCapture />
240
+ </div>
241
+ </div>
242
+ );
243
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
@@ -0,0 +1,80 @@
1
+ import { useState, useEffect } from 'react';
2
+ import { useParams } from 'react-router-dom';
3
+ import { Code, Wrench, Package, FileCode } from 'lucide-react';
4
+
5
+ export function Capabilities() {
6
+ const { id } = useParams<{ id: string }>();
7
+ const [data, setData] = useState<{ skills: any[], commands: any[], plugins: any[], scripts: any[] } | null>(null);
8
+
9
+ useEffect(() => {
10
+ fetch(`http://localhost:3333/api/instances/${id}/capabilities`)
11
+ .then(r => r.json())
12
+ .then(setData)
13
+ .catch((e) => console.error("Error loading capabilities", e));
14
+ }, [id]);
15
+
16
+ if (!data) return <div className="p-8 text-neutral-500 animate-pulse">Scanning capabilities...</div>;
17
+
18
+ return (
19
+ <div className="flex flex-col h-full bg-neutral-950 overflow-y-auto p-8 space-y-12">
20
+ <div>
21
+ <h2 className="text-xl font-semibold mb-6 flex items-center gap-2">
22
+ <Package className="text-indigo-400" size={20} /> Installed Plugins ({data.plugins?.length || 0})
23
+ </h2>
24
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
25
+ {data.plugins?.map((p, i) => (
26
+ <div key={i} className="border border-white/10 p-5 rounded-xl bg-white/[0.02]">
27
+ <div className="font-medium text-neutral-200">{p.name || 'Unknown Plugin'}</div>
28
+ <div className="text-xs text-neutral-500 mt-2 line-clamp-2 leading-relaxed">{p.description}</div>
29
+ </div>
30
+ ))}
31
+ </div>
32
+ </div>
33
+
34
+ <div>
35
+ <h2 className="text-xl font-semibold mb-6 flex items-center gap-2">
36
+ <Wrench className="text-emerald-400" size={20} /> Active Skills ({data.skills?.length || 0})
37
+ </h2>
38
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
39
+ {data.skills?.map((s, i) => (
40
+ <div key={i} className="border border-white/10 p-5 rounded-xl bg-white/[0.02] flex flex-col hover:border-white/20 transition-all">
41
+ <div className="font-medium text-neutral-200 mb-2">{s.name}</div>
42
+ <div className="text-[10px] text-emerald-400/80 font-mono mb-3 p-1.5 bg-emerald-500/10 rounded inline-flex w-max tracking-wide uppercase">{s.mcpId || 'Local Core Provider'}</div>
43
+ <div className="text-sm text-neutral-400 mt-auto leading-relaxed">{s.description}</div>
44
+ </div>
45
+ ))}
46
+ </div>
47
+ </div>
48
+
49
+ <div>
50
+ <h2 className="text-xl font-semibold mb-6 flex items-center gap-2">
51
+ <Code className="text-amber-400" size={20} /> Registered Commands ({data.commands?.length || 0})
52
+ </h2>
53
+ <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
54
+ {data.commands?.map((c, i) => (
55
+ <div key={i} className="border border-white/10 p-4 rounded-xl flex items-center gap-3 bg-white/[0.01]">
56
+ <span className="font-mono text-sm text-amber-200 bg-amber-500/10 px-2 py-0.5 rounded">/{c.name}</span>
57
+ </div>
58
+ ))}
59
+ </div>
60
+ </div>
61
+
62
+ <div>
63
+ <h2 className="text-xl font-semibold mb-6 flex items-center gap-2">
64
+ <FileCode className="text-pink-400" size={20} /> Scripts ({data.scripts?.length || 0})
65
+ </h2>
66
+ <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
67
+ {data.scripts?.map((s, i) => (
68
+ <div key={i} className="border border-white/10 p-4 rounded-xl flex flex-col gap-2 bg-white/[0.01] hover:border-white/20 transition-all">
69
+ <span className="font-mono text-sm text-pink-200">{s.manifest?.name || s.name || 'unnamed'}</span>
70
+ {(s.manifest?.description || s.description) && (
71
+ <span className="text-xs text-neutral-500 line-clamp-2">{s.manifest?.description || s.description}</span>
72
+ )}
73
+ <span className="text-[10px] font-mono text-neutral-600">{s.manifest?.entrypoint || s.entrypoint || ''}</span>
74
+ </div>
75
+ ))}
76
+ </div>
77
+ </div>
78
+ </div>
79
+ );
80
+ }
@@ -0,0 +1,94 @@
1
+ import { useState, useEffect } from 'react';
2
+ import { useParams } from 'react-router-dom';
3
+ import { Code, Plus, Trash2 } from 'lucide-react';
4
+
5
+ const API = 'http://localhost:3333/api';
6
+
7
+ export function CommandsManager() {
8
+ const { id } = useParams<{ id: string }>();
9
+ const [commands, setCommands] = useState<any[]>([]);
10
+ const [showCreate, setShowCreate] = useState(false);
11
+ const [form, setForm] = useState({ name: '', description: '', tools: '', body: '' });
12
+
13
+ const load = () => {
14
+ fetch(`${API}/instances/${id}/commands`).then(r => r.json()).then(d => setCommands(d.commands || [])).catch(console.error);
15
+ };
16
+
17
+ useEffect(() => { load(); }, [id]);
18
+
19
+ const createCommand = async () => {
20
+ if (!form.name.trim()) return;
21
+ await fetch(`${API}/instances/${id}/commands`, {
22
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
23
+ body: JSON.stringify({
24
+ name: form.name, description: form.description,
25
+ tools: form.tools ? form.tools.split(',').map(s => s.trim()) : [],
26
+ body: form.body,
27
+ }),
28
+ });
29
+ setForm({ name: '', description: '', tools: '', body: '' });
30
+ setShowCreate(false);
31
+ load();
32
+ };
33
+
34
+ const deleteCommand = async (name: string) => {
35
+ if (!confirm(`Delete command "${name}"?`)) return;
36
+ await fetch(`${API}/instances/${id}/commands/${name}`, { method: 'DELETE' });
37
+ load();
38
+ };
39
+
40
+ return (
41
+ <div className="flex flex-col h-full bg-neutral-950 overflow-y-auto p-8">
42
+ <div className="flex items-center justify-between mb-8">
43
+ <div>
44
+ <h2 className="text-xl font-semibold flex items-center gap-2">
45
+ <Code className="text-amber-400" size={22} /> Commands
46
+ </h2>
47
+ <p className="text-neutral-500 text-sm mt-1">{commands.length} command{commands.length !== 1 ? 's' : ''} loaded</p>
48
+ </div>
49
+ <button onClick={() => setShowCreate(!showCreate)}
50
+ className="flex items-center gap-2 px-4 py-2 rounded-lg bg-amber-500/20 border border-amber-500/30 text-amber-300 text-sm font-medium hover:bg-amber-500/30 transition-colors">
51
+ <Plus size={16} /> New Command
52
+ </button>
53
+ </div>
54
+
55
+ {showCreate && (
56
+ <div className="border border-white/10 rounded-xl p-5 bg-white/[0.02] mb-6 space-y-4">
57
+ <div className="grid grid-cols-2 gap-4">
58
+ <input value={form.name} onChange={e => setForm({ ...form, name: e.target.value })} placeholder="Command name..."
59
+ className="bg-neutral-900 border border-white/10 rounded-lg px-4 py-2.5 text-sm placeholder-neutral-600 focus:outline-none focus:border-amber-500/50" />
60
+ <input value={form.description} onChange={e => setForm({ ...form, description: e.target.value })} placeholder="Description..."
61
+ className="bg-neutral-900 border border-white/10 rounded-lg px-4 py-2.5 text-sm placeholder-neutral-600 focus:outline-none focus:border-amber-500/50" />
62
+ </div>
63
+ <input value={form.tools} onChange={e => setForm({ ...form, tools: e.target.value })} placeholder="Allowed tools (comma-separated)..."
64
+ className="w-full bg-neutral-900 border border-white/10 rounded-lg px-4 py-2.5 text-sm placeholder-neutral-600 focus:outline-none focus:border-amber-500/50" />
65
+ <textarea value={form.body} onChange={e => setForm({ ...form, body: e.target.value })} placeholder="Command body (markdown prompt)..."
66
+ rows={6} className="w-full bg-neutral-900 border border-white/10 rounded-lg px-4 py-2.5 text-sm placeholder-neutral-600 focus:outline-none focus:border-amber-500/50 resize-none font-mono" />
67
+ <div className="flex justify-end gap-3">
68
+ <button onClick={() => setShowCreate(false)} className="text-sm text-neutral-500 hover:text-neutral-300">Cancel</button>
69
+ <button onClick={createCommand} className="px-4 py-1.5 rounded-lg bg-amber-500 text-white text-sm font-medium hover:bg-amber-600 transition-colors">Create</button>
70
+ </div>
71
+ </div>
72
+ )}
73
+
74
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
75
+ {commands.map((c) => (
76
+ <div key={c.name} className="border border-white/10 rounded-xl bg-white/[0.02] p-5 flex flex-col hover:border-white/20 transition-all">
77
+ <div className="flex items-start justify-between mb-2">
78
+ <span className="font-mono text-sm text-amber-200 bg-amber-500/10 px-2.5 py-1 rounded">/{c.name}</span>
79
+ <button onClick={() => deleteCommand(c.name)} className="p-1.5 rounded hover:bg-white/10 text-red-400"><Trash2 size={14} /></button>
80
+ </div>
81
+ <p className="text-sm text-neutral-400 mt-2 flex-1">{c.description}</p>
82
+ {c.tools?.length > 0 && (
83
+ <div className="flex flex-wrap gap-1.5 mt-3">
84
+ {c.tools.map((t: string) => (
85
+ <span key={t} className="text-[10px] font-mono text-amber-400 bg-amber-500/10 px-2 py-0.5 rounded">{t}</span>
86
+ ))}
87
+ </div>
88
+ )}
89
+ </div>
90
+ ))}
91
+ </div>
92
+ </div>
93
+ );
94
+ }