@mazees/mark 5.0.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 (227) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +209 -0
  3. package/bin/mark.js +27 -0
  4. package/out/renderer/assets/icon-DHo2CYph.svg +1 -0
  5. package/out/renderer/assets/index-G2fADWO-.js +4768 -0
  6. package/out/renderer/assets/index-f3mVse3c.css +1 -0
  7. package/out/renderer/assets/music-cover-CG4vi3kZ.png +0 -0
  8. package/out/renderer/assets/poppins-devanagari-400-normal-CJDn6rn8.woff2 +0 -0
  9. package/out/renderer/assets/poppins-devanagari-400-normal-CqVvlrh5.woff +0 -0
  10. package/out/renderer/assets/poppins-devanagari-500-normal-BIdkeU1p.woff2 +0 -0
  11. package/out/renderer/assets/poppins-devanagari-500-normal-DMPDjHtT.woff +0 -0
  12. package/out/renderer/assets/poppins-devanagari-600-normal-ClASKHrr.woff +0 -0
  13. package/out/renderer/assets/poppins-devanagari-600-normal-STEjXBNN.woff2 +0 -0
  14. package/out/renderer/assets/poppins-devanagari-700-normal-O-jipLrW.woff2 +0 -0
  15. package/out/renderer/assets/poppins-devanagari-700-normal-fHs-vx92.woff +0 -0
  16. package/out/renderer/assets/poppins-latin-400-normal-BOb3E3N0.woff +0 -0
  17. package/out/renderer/assets/poppins-latin-400-normal-cpxAROuN.woff2 +0 -0
  18. package/out/renderer/assets/poppins-latin-500-normal-C8OXljZJ.woff2 +0 -0
  19. package/out/renderer/assets/poppins-latin-500-normal-DGXqpDMm.woff +0 -0
  20. package/out/renderer/assets/poppins-latin-600-normal-BJdTmd5m.woff +0 -0
  21. package/out/renderer/assets/poppins-latin-600-normal-zEkxB9Mr.woff2 +0 -0
  22. package/out/renderer/assets/poppins-latin-700-normal-BVuQR_eA.woff +0 -0
  23. package/out/renderer/assets/poppins-latin-700-normal-Qrb0O0WB.woff2 +0 -0
  24. package/out/renderer/assets/poppins-latin-ext-400-normal-DaBSavcJ.woff +0 -0
  25. package/out/renderer/assets/poppins-latin-ext-400-normal-by3JarPu.woff2 +0 -0
  26. package/out/renderer/assets/poppins-latin-ext-500-normal-CK-6C4Hw.woff2 +0 -0
  27. package/out/renderer/assets/poppins-latin-ext-500-normal-CgAe2rWW.woff +0 -0
  28. package/out/renderer/assets/poppins-latin-ext-600-normal-CAhIAdZj.woff2 +0 -0
  29. package/out/renderer/assets/poppins-latin-ext-600-normal-Df5ffKXP.woff +0 -0
  30. package/out/renderer/assets/poppins-latin-ext-700-normal-DctTR6Tg.woff +0 -0
  31. package/out/renderer/assets/poppins-latin-ext-700-normal-cby-RkWa.woff2 +0 -0
  32. package/out/renderer/favicon.ico +0 -0
  33. package/out/renderer/icon-256.png +0 -0
  34. package/out/renderer/icon.svg +1 -0
  35. package/out/renderer/index.html +25 -0
  36. package/out/renderer/manifest.json +25 -0
  37. package/out/renderer/robot-simulator.html +1640 -0
  38. package/package.json +106 -0
  39. package/src/cli/index.js +332 -0
  40. package/src/cli/monitor.js +413 -0
  41. package/src/cli/theme.js +347 -0
  42. package/src/launcher/MarkTray.cs +227 -0
  43. package/src/main/browser-agent.js +1132 -0
  44. package/src/main/git-service.js +90 -0
  45. package/src/main/google/google-calendar.js +69 -0
  46. package/src/main/google/google-drive.js +263 -0
  47. package/src/main/google/google-gmail.js +131 -0
  48. package/src/main/google/google-service.js +241 -0
  49. package/src/main/node-tools.js +23 -0
  50. package/src/main/pc-agent-scripts/mouse-locker.ps1 +76 -0
  51. package/src/main/pc-agent-scripts/ocr-region.ps1 +185 -0
  52. package/src/main/pc-agent-scripts/pc-daemon.ps1 +726 -0
  53. package/src/main/pc-agent-scripts/pc-overlay.ps1 +253 -0
  54. package/src/main/pc-agent-scripts/pick-folder.ps1 +33 -0
  55. package/src/main/pc-agent-scripts/read-ui.ps1 +181 -0
  56. package/src/main/pc-agent-scripts/take-screenshot.ps1 +24 -0
  57. package/src/main/pc-agent-scripts/win-action.ps1 +380 -0
  58. package/src/main/plugins/plugin-loader.js +306 -0
  59. package/src/main/skills/skill-manager.js +265 -0
  60. package/src/main/syntax-validator.js +455 -0
  61. package/src/main/task-daemon.js +117 -0
  62. package/src/main/telegram/telegram-service.js +835 -0
  63. package/src/main/tools/browser-tools.js +516 -0
  64. package/src/main/tools/file-tools.js +1126 -0
  65. package/src/main/tools/git-tools.js +79 -0
  66. package/src/main/tools/google-tools.js +566 -0
  67. package/src/main/tools/index.js +36 -0
  68. package/src/main/tools/media-tools.js +42 -0
  69. package/src/main/tools/system-tools.js +295 -0
  70. package/src/main/tools/task-tools.js +73 -0
  71. package/src/main/tools/telegram-tools.js +101 -0
  72. package/src/renderer/index.html +24 -0
  73. package/src/renderer/public/favicon.ico +0 -0
  74. package/src/renderer/public/icon-256.png +0 -0
  75. package/src/renderer/public/icon.svg +1 -0
  76. package/src/renderer/public/manifest.json +25 -0
  77. package/src/renderer/public/robot-simulator.html +1640 -0
  78. package/src/renderer/src/App.jsx +304 -0
  79. package/src/renderer/src/api/ai/awareness.js +294 -0
  80. package/src/renderer/src/api/ai/chatSummarizer.js +79 -0
  81. package/src/renderer/src/api/ai/contextCompactor.js +129 -0
  82. package/src/renderer/src/api/ai/contextManager.js +1130 -0
  83. package/src/renderer/src/api/ai/core.js +167 -0
  84. package/src/renderer/src/api/ai/index.js +4 -0
  85. package/src/renderer/src/api/ai/memoryGroomer.js +101 -0
  86. package/src/renderer/src/api/ai/persona.js +115 -0
  87. package/src/renderer/src/api/ai/planning.js +317 -0
  88. package/src/renderer/src/api/ai/relationship.js +177 -0
  89. package/src/renderer/src/api/ai/skillSynthesizer.js +168 -0
  90. package/src/renderer/src/api/ai/tools.js +167 -0
  91. package/src/renderer/src/api/ai/utils.js +359 -0
  92. package/src/renderer/src/api/db.js +1013 -0
  93. package/src/renderer/src/api/oramaStore.js +592 -0
  94. package/src/renderer/src/api/ragPipeline.js +87 -0
  95. package/src/renderer/src/api/subagent/subagentExecutor.js +780 -0
  96. package/src/renderer/src/api/subagent/subagentPrompt.js +44 -0
  97. package/src/renderer/src/api/subagent/subagentStore.js +173 -0
  98. package/src/renderer/src/api/taskExecutor.js +18 -0
  99. package/src/renderer/src/api/taskStore.js +315 -0
  100. package/src/renderer/src/api/tools/core-tools.js +707 -0
  101. package/src/renderer/src/api/tools/index.js +151 -0
  102. package/src/renderer/src/api/turnPairMigrator.js +200 -0
  103. package/src/renderer/src/api/vectorMemory.js +136 -0
  104. package/src/renderer/src/api/wakeWord.js +101 -0
  105. package/src/renderer/src/api/web-bridge.js +885 -0
  106. package/src/renderer/src/api/webSpeech.js +178 -0
  107. package/src/renderer/src/api/workspaceRag.js +76 -0
  108. package/src/renderer/src/assets/electron.svg +10 -0
  109. package/src/renderer/src/assets/icon.svg +1 -0
  110. package/src/renderer/src/assets/main.css +589 -0
  111. package/src/renderer/src/assets/music-cover.png +0 -0
  112. package/src/renderer/src/assets/wavy-lines.svg +25 -0
  113. package/src/renderer/src/components/Chat/ApprovalBubble.jsx +127 -0
  114. package/src/renderer/src/components/Chat/CodeBlock.jsx +83 -0
  115. package/src/renderer/src/components/Chat/DurableTaskBubble.jsx +455 -0
  116. package/src/renderer/src/components/Chat/FileDiffModal.jsx +328 -0
  117. package/src/renderer/src/components/Chat/GeminiWidgets.jsx +82 -0
  118. package/src/renderer/src/components/Chat/MemoryFooterBubble.jsx +34 -0
  119. package/src/renderer/src/components/Chat/MessageBubble.jsx +459 -0
  120. package/src/renderer/src/components/Chat/PluginExecutionBubble.jsx +41 -0
  121. package/src/renderer/src/components/Chat/ThinkingBubble.jsx +316 -0
  122. package/src/renderer/src/components/Chat/YoutubeSearchBubble.jsx +43 -0
  123. package/src/renderer/src/components/Chat/YoutubeSummaryBubble.jsx +40 -0
  124. package/src/renderer/src/components/Chat/index.js +11 -0
  125. package/src/renderer/src/components/ChatList.jsx +434 -0
  126. package/src/renderer/src/components/GlobalCameraManager.jsx +67 -0
  127. package/src/renderer/src/components/Versions.jsx +15 -0
  128. package/src/renderer/src/components/YoutubeMusicPlayer.jsx +375 -0
  129. package/src/renderer/src/components/camera/CameraPreview.jsx +236 -0
  130. package/src/renderer/src/components/config/AiEngineSection.jsx +363 -0
  131. package/src/renderer/src/components/config/CameraSection.jsx +100 -0
  132. package/src/renderer/src/components/config/PermissionsSection.jsx +130 -0
  133. package/src/renderer/src/components/config/ShortcutSection.jsx +102 -0
  134. package/src/renderer/src/components/config/VoiceSection.jsx +110 -0
  135. package/src/renderer/src/components/config/index.js +5 -0
  136. package/src/renderer/src/components/core/Avatar.jsx +2197 -0
  137. package/src/renderer/src/components/core/ConfirmModal.jsx +80 -0
  138. package/src/renderer/src/components/core/DraggableHoloCard.jsx +125 -0
  139. package/src/renderer/src/components/core/FloatingMenu.jsx +272 -0
  140. package/src/renderer/src/components/core/HoloCard.jsx +64 -0
  141. package/src/renderer/src/components/core/InputBar.jsx +1346 -0
  142. package/src/renderer/src/components/core/ProcessPanel.jsx +216 -0
  143. package/src/renderer/src/components/core/ResponseArea.jsx +149 -0
  144. package/src/renderer/src/components/core/StatusIndicator.jsx +59 -0
  145. package/src/renderer/src/components/core/ThoughtNeuralFlow.jsx +168 -0
  146. package/src/renderer/src/components/core/ToolClustersDeck.jsx +210 -0
  147. package/src/renderer/src/components/core/native-skills.js +43 -0
  148. package/src/renderer/src/components/neural-core/EmotionalCortexLobe.jsx +359 -0
  149. package/src/renderer/src/components/neural-core/NodeDissectionModal.jsx +57 -0
  150. package/src/renderer/src/components/neural-core/ProceduralMatrixLobe.jsx +193 -0
  151. package/src/renderer/src/components/neural-core/ProceduralSkillModal.jsx +53 -0
  152. package/src/renderer/src/components/neural-core/ResetAiModal.jsx +198 -0
  153. package/src/renderer/src/components/neural-core/SynapticMemoryLobe.jsx +204 -0
  154. package/src/renderer/src/components/neural-core/traitMeta.js +102 -0
  155. package/src/renderer/src/components/subagent/AgentChatFeed.jsx +603 -0
  156. package/src/renderer/src/components/subagent/AgentInspector.jsx +224 -0
  157. package/src/renderer/src/components/subagent/AgentSidebar.jsx +216 -0
  158. package/src/renderer/src/components/subagent/SubagentIntercom.jsx +572 -0
  159. package/src/renderer/src/components/subagent/SubagentTopologyMap.jsx +423 -0
  160. package/src/renderer/src/contexts/ApprovalContext.jsx +425 -0
  161. package/src/renderer/src/contexts/ChatContext.jsx +61 -0
  162. package/src/renderer/src/contexts/YoutubeMusicContext.jsx +333 -0
  163. package/src/renderer/src/data/faqData.js +202 -0
  164. package/src/renderer/src/hooks/agent/executeAgentTool.js +895 -0
  165. package/src/renderer/src/hooks/agent/index.js +4 -0
  166. package/src/renderer/src/hooks/agent/useMarkMusic.js +75 -0
  167. package/src/renderer/src/hooks/agent/useMarkPlan.js +2739 -0
  168. package/src/renderer/src/hooks/agent/useMarkState.js +173 -0
  169. package/src/renderer/src/hooks/agent/useMarkYoutube.js +82 -0
  170. package/src/renderer/src/hooks/agent/useRelationalGrowth.js +201 -0
  171. package/src/renderer/src/hooks/telegram/useTelegramBot.js +63 -0
  172. package/src/renderer/src/hooks/useAwareness.js +289 -0
  173. package/src/renderer/src/hooks/useChatArchiver.js +52 -0
  174. package/src/renderer/src/hooks/useConfirm.jsx +68 -0
  175. package/src/renderer/src/hooks/useMarkAgent.js +454 -0
  176. package/src/renderer/src/hooks/useMemoryGroomer.js +152 -0
  177. package/src/renderer/src/hooks/useVAD.js +511 -0
  178. package/src/renderer/src/hooks/useWebSpeechWakeWord.js +122 -0
  179. package/src/renderer/src/main.jsx +12 -0
  180. package/src/renderer/src/pages/ChatStudio.jsx +922 -0
  181. package/src/renderer/src/pages/Configuration.jsx +360 -0
  182. package/src/renderer/src/pages/GoogleWorkspace.jsx +293 -0
  183. package/src/renderer/src/pages/Guidebook.jsx +917 -0
  184. package/src/renderer/src/pages/Knowledge.jsx +241 -0
  185. package/src/renderer/src/pages/MarkHome.jsx +491 -0
  186. package/src/renderer/src/pages/NeuralCore.jsx +786 -0
  187. package/src/renderer/src/pages/Plugins.jsx +630 -0
  188. package/src/renderer/src/pages/SkillEditor.jsx +380 -0
  189. package/src/renderer/src/pages/Skills.jsx +219 -0
  190. package/src/renderer/src/pages/Subagents.jsx +342 -0
  191. package/src/renderer/src/pages/TelegramBot.jsx +343 -0
  192. package/src/renderer/src/utils/chatContentParser.js +203 -0
  193. package/src/renderer/src/utils/toolClusters.js +201 -0
  194. package/src/server/bin/sha3_wasm_bg.wasm +0 -0
  195. package/src/server/config-manager.js +57 -0
  196. package/src/server/index.js +195 -0
  197. package/src/server/launcher.js +87 -0
  198. package/src/server/memory/db-store.js +758 -0
  199. package/src/server/memory/orama-store.js +177 -0
  200. package/src/server/memory/vector-engine.js +109 -0
  201. package/src/server/routes/ai.routes.js +280 -0
  202. package/src/server/routes/awareness.routes.js +62 -0
  203. package/src/server/routes/chat.routes.js +61 -0
  204. package/src/server/routes/config.routes.js +41 -0
  205. package/src/server/routes/index.js +35 -0
  206. package/src/server/routes/integrations.routes.js +116 -0
  207. package/src/server/routes/memory.routes.js +256 -0
  208. package/src/server/routes/plugins.routes.js +72 -0
  209. package/src/server/routes/skills.routes.js +139 -0
  210. package/src/server/routes/subagents.routes.js +70 -0
  211. package/src/server/routes/tasks.routes.js +175 -0
  212. package/src/server/routes/workspace.routes.js +127 -0
  213. package/src/server/services/ai/ai-utils.js +161 -0
  214. package/src/server/services/ai/openai-provider.js +757 -0
  215. package/src/server/services/ai/web-provider.js +729 -0
  216. package/src/server/services/ai-bridge.js +46 -0
  217. package/src/server/services/deepseek-web.js +956 -0
  218. package/src/server/services/gemini-web.js +170 -0
  219. package/src/server/services/notification-service.js +91 -0
  220. package/src/server/services/updater.js +125 -0
  221. package/src/server/tools/awareness-tracker.js +292 -0
  222. package/src/server/tools/group-tools.js +1164 -0
  223. package/src/server/tools/media-tools.js +244 -0
  224. package/src/server/tools/pc-agent.js +327 -0
  225. package/src/server/tools/screen-service.js +51 -0
  226. package/src/server/ws-hub.js +168 -0
  227. package/src/shared/parsers/mark-tag-parser.js +275 -0
@@ -0,0 +1,423 @@
1
+ import React, { useState, useMemo } from 'react'
2
+ import {
3
+ Brain,
4
+ Bot,
5
+ Activity,
6
+ Send,
7
+ Terminal,
8
+ ExternalLink,
9
+ Layers,
10
+ Sparkles,
11
+ CheckCircle2,
12
+ AlertTriangle
13
+ } from 'lucide-react'
14
+
15
+ // Primary MARK Theme (Forest Theme)
16
+ const PRIMARY = '#1fb854'
17
+ const PRIMARY_DARK = '#142e22'
18
+ const WHITE = '#ffffff'
19
+
20
+ export default function SubagentTopologyMap({
21
+ subagents = [],
22
+ selectedId = null,
23
+ onSelectAgent = () => {},
24
+ onOpenIntercom = () => {},
25
+ onSendMessage = () => {}
26
+ }) {
27
+ const [hoveredId, setHoveredId] = useState(null)
28
+ const [quickInput, setQuickInput] = useState('')
29
+ const [isSending, setIsSending] = useState(false)
30
+
31
+ // Filter agent untuk topologi:
32
+ // Saat ada sub-agent yang sedang berjalan (running), HANYA tampilkan yang aktif agar diagram fokus & tidak penuh.
33
+ // Saat semua tugas selesai / idle, tampilkan seluruh sub-agent yang standby.
34
+ const displayAgents = useMemo(() => {
35
+ const running = subagents.filter((a) => a.status === 'running')
36
+ if (running.length > 0) {
37
+ return running
38
+ }
39
+ return subagents
40
+ }, [subagents])
41
+
42
+ // Layout geometry for constellation placement
43
+ const totalAgents = displayAgents.length
44
+ const center = { x: 340, y: 240 }
45
+ const radius = Math.min(180, Math.max(130, totalAgents * 24))
46
+
47
+ const nodes = useMemo(() => {
48
+ if (totalAgents === 0) return []
49
+ return displayAgents.map((agent, index) => {
50
+ const angle = (index / totalAgents) * 2 * Math.PI - Math.PI / 2
51
+ const x = center.x + radius * Math.cos(angle)
52
+ const y = center.y + radius * Math.sin(angle)
53
+ return {
54
+ ...agent,
55
+ x,
56
+ y,
57
+ angle
58
+ }
59
+ })
60
+ }, [displayAgents, totalAgents, center.x, center.y, radius])
61
+
62
+ const selectedAgent = useMemo(
63
+ () => subagents.find((a) => a.id === selectedId) || null,
64
+ [subagents, selectedId]
65
+ )
66
+
67
+ const activeCount = subagents.filter((a) => a.status === 'running').length
68
+ const idleCount = subagents.filter((a) => a.status === 'idle').length
69
+ const completedCount = subagents.filter((a) => a.status === 'completed').length
70
+ const failedCount = subagents.filter((a) => a.status === 'failed' || a.status === 'killed').length
71
+
72
+ const handleQuickSend = async (e) => {
73
+ e?.preventDefault()
74
+ if (!quickInput.trim() || !selectedAgent || isSending) return
75
+ setIsSending(true)
76
+ try {
77
+ await onSendMessage(selectedAgent.id, quickInput.trim())
78
+ setQuickInput('')
79
+ } finally {
80
+ setIsSending(false)
81
+ }
82
+ }
83
+
84
+ return (
85
+ <div className="flex-1 flex flex-col md:flex-row h-full overflow-hidden gap-4 font-['Poppins',sans-serif]">
86
+ {/* Visual Canvas Area */}
87
+ <div className="flex-1 bg-base-200/50 rounded-2xl border border-base-content/10 relative overflow-hidden flex flex-col items-center justify-center p-4 backdrop-blur-md">
88
+ {/* Subtle Ambient Radial Highlight */}
89
+ <div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,#1fb8540d_0%,transparent_70%)] pointer-events-none" />
90
+
91
+ {/* Top Minimal Telemetry Bar */}
92
+ <div className="absolute top-3 left-4 right-4 flex items-center justify-between pointer-events-none z-10">
93
+ <div className="flex items-center gap-2 bg-base-300/80 backdrop-blur-md px-3 py-1.5 rounded-xl border border-base-content/5 text-xs shadow-sm">
94
+ <span className="w-2 h-2 rounded-full bg-primary animate-pulse" />
95
+ <span className="font-semibold text-[11px] tracking-wide text-base-content/80">
96
+ Topology Network {activeCount > 0 ? '(Active Squad)' : '(Standby)'}
97
+ </span>
98
+ </div>
99
+
100
+ <div className="flex items-center gap-2 font-mono text-[11px]">
101
+ {activeCount > 0 && (
102
+ <span className="px-2.5 py-1 bg-base-300/80 backdrop-blur-md rounded-lg border border-primary/30 flex items-center gap-1.5 text-primary shadow-sm font-semibold">
103
+ <span className="w-1.5 h-1.5 rounded-full bg-primary animate-ping" />
104
+ {activeCount} Aktif
105
+ </span>
106
+ )}
107
+ {idleCount > 0 && (
108
+ <span className="px-2.5 py-1 bg-base-300/80 backdrop-blur-md rounded-lg border border-base-content/5 flex items-center gap-1.5 text-base-content/80 shadow-sm">
109
+ <span className="w-1.5 h-1.5 rounded-full bg-primary/70" />
110
+ {idleCount} Standby
111
+ </span>
112
+ )}
113
+ {completedCount > 0 && (
114
+ <span className="px-2.5 py-1 bg-base-300/80 backdrop-blur-md rounded-lg border border-base-content/5 flex items-center gap-1.5 text-base-content/80 shadow-sm">
115
+ <span className="w-1.5 h-1.5 rounded-full bg-primary" />
116
+ {completedCount} Selesai
117
+ </span>
118
+ )}
119
+ {failedCount > 0 && (
120
+ <span className="px-2.5 py-1 bg-base-300/80 backdrop-blur-md rounded-lg border border-error/30 text-error flex items-center gap-1.5 shadow-sm">
121
+ {failedCount} Gagal
122
+ </span>
123
+ )}
124
+ </div>
125
+ </div>
126
+
127
+ {totalAgents === 0 ? (
128
+ <div className="flex flex-col items-center justify-center text-center p-8 z-10 text-base-content/40 space-y-2.5">
129
+ <div className="w-14 h-14 rounded-2xl bg-base-300/80 border border-base-content/10 flex items-center justify-center text-primary shadow-inner">
130
+ <Layers className="w-7 h-7 stroke-[1.5]" />
131
+ </div>
132
+ <div>
133
+ <p className="font-semibold text-sm text-base-content/70">
134
+ Belum Ada Sub-Agent
135
+ </p>
136
+ <p className="text-xs text-base-content/40 mt-0.5 max-w-sm">
137
+ Saat Mark mendelegasikan tugas ke sub-agent, topologi tim akan muncul di sini.
138
+ </p>
139
+ </div>
140
+ </div>
141
+ ) : (
142
+ <div className="relative w-full h-full flex items-center justify-center">
143
+ {/* SVG Clean Topology Network */}
144
+ <svg
145
+ viewBox="0 0 680 480"
146
+ className="w-full h-full max-w-[680px] max-h-[480px] select-none"
147
+ style={{ overflow: 'visible' }}
148
+ >
149
+ {/* Single Clean Orbital Track - Slow Gentle Spin */}
150
+ <circle
151
+ cx={center.x}
152
+ cy={center.y}
153
+ r={radius}
154
+ fill="none"
155
+ stroke={PRIMARY}
156
+ strokeOpacity="0.18"
157
+ strokeWidth="1"
158
+ strokeDasharray="4 6"
159
+ className="animate-[spin_90s_linear_infinite]"
160
+ />
161
+
162
+ {/* Minimal Clean Connector Lines */}
163
+ {nodes.map((node) => {
164
+ const isSelected = node.id === selectedId
165
+ const isHovered = node.id === hoveredId
166
+ const isRunning = node.status === 'running'
167
+ const isFailed = node.status === 'failed' || node.status === 'killed'
168
+ const lineColor = isFailed ? '#ef4444' : PRIMARY
169
+
170
+ return (
171
+ <g key={`beam-${node.id}`}>
172
+ <line
173
+ x1={center.x}
174
+ y1={center.y}
175
+ x2={node.x}
176
+ y2={node.y}
177
+ stroke={lineColor}
178
+ strokeWidth={isSelected || isHovered ? 2 : 1}
179
+ strokeOpacity={isSelected || isHovered ? 0.9 : isFailed ? 0.6 : isRunning ? 0.6 : 0.25}
180
+ strokeDasharray={isRunning || isFailed ? '4 3' : undefined}
181
+ />
182
+
183
+ {/* Active Minimal Pulse */}
184
+ {isRunning && (
185
+ <circle
186
+ r="3"
187
+ fill={PRIMARY}
188
+ stroke={WHITE}
189
+ strokeWidth="0.8"
190
+ >
191
+ <animateMotion
192
+ path={`M ${center.x} ${center.y} L ${node.x} ${node.y}`}
193
+ dur="1.8s"
194
+ repeatCount="indefinite"
195
+ />
196
+ </circle>
197
+ )}
198
+ </g>
199
+ )
200
+ })}
201
+
202
+ {/* Center Node: Mark (Lead Agent) */}
203
+ <g transform={`translate(${center.x}, ${center.y})`} className="cursor-pointer">
204
+ {/* Subtle Ambient Breath Ring */}
205
+ <circle
206
+ r="34"
207
+ fill={PRIMARY}
208
+ fillOpacity="0.12"
209
+ className="animate-pulse"
210
+ />
211
+
212
+ {/* Node Core */}
213
+ <circle
214
+ r="26"
215
+ fill={PRIMARY}
216
+ stroke={WHITE}
217
+ strokeWidth="2"
218
+ />
219
+ <foreignObject x="-16" y="-16" width="32" height="32">
220
+ <div className="w-full h-full flex items-center justify-center text-white">
221
+ <Brain className="w-5 h-5" />
222
+ </div>
223
+ </foreignObject>
224
+
225
+ {/* Minimal Text Label */}
226
+ <text
227
+ y="42"
228
+ textAnchor="middle"
229
+ fill={WHITE}
230
+ className="text-[10px] font-semibold tracking-wider font-mono"
231
+ >
232
+ MARK (LEAD)
233
+ </text>
234
+ </g>
235
+
236
+ {/* Satellite Nodes: Sub-Agents */}
237
+ {nodes.map((node) => {
238
+ const isSelected = node.id === selectedId
239
+ const isHovered = node.id === hoveredId
240
+ const isRunning = node.status === 'running'
241
+ const isFailed = node.status === 'failed' || node.status === 'killed'
242
+ const nodeColor = isFailed ? '#ef4444' : PRIMARY
243
+
244
+ return (
245
+ <g
246
+ key={`node-${node.id}`}
247
+ transform={`translate(${node.x}, ${node.y})`}
248
+ className="cursor-pointer"
249
+ onClick={() => onSelectAgent(node.id)}
250
+ onMouseEnter={() => setHoveredId(node.id)}
251
+ onMouseLeave={() => setHoveredId(null)}
252
+ >
253
+ {/* Invisible Hitbox */}
254
+ <circle r="30" fill="transparent" />
255
+
256
+ {/* Active/Hover Clean Ring with Gentle Spin */}
257
+ {(isSelected || isHovered) && (
258
+ <circle
259
+ r="25"
260
+ fill="none"
261
+ stroke={nodeColor}
262
+ strokeWidth="1.5"
263
+ strokeDasharray="3 3"
264
+ className="animate-[spin_10s_linear_infinite]"
265
+ />
266
+ )}
267
+
268
+ {/* Node Core Body */}
269
+ <circle
270
+ r={isSelected || isHovered ? 20 : 18}
271
+ fill={nodeColor}
272
+ stroke={WHITE}
273
+ strokeWidth={isSelected || isHovered ? 2 : 1.2}
274
+ className="transition-all duration-150"
275
+ />
276
+
277
+ {/* Icon Inside Node */}
278
+ <foreignObject x="-11" y="-11" width="22" height="22">
279
+ <div className="w-full h-full flex items-center justify-center text-white">
280
+ {isFailed ? (
281
+ <AlertTriangle className="w-3.5 h-3.5 text-white" />
282
+ ) : isRunning ? (
283
+ <Activity className="w-3.5 h-3.5 animate-spin" />
284
+ ) : node.status === 'idle' ? (
285
+ <Bot className="w-3.5 h-3.5 text-white" />
286
+ ) : (
287
+ <CheckCircle2 className="w-3.5 h-3.5 text-white" />
288
+ )}
289
+ </div>
290
+ </foreignObject>
291
+
292
+ {/* Clean Sub-agent Name Label */}
293
+ <text
294
+ y="34"
295
+ textAnchor="middle"
296
+ fill={isFailed ? '#fca5a5' : WHITE}
297
+ className="text-[9px] font-medium tracking-tight"
298
+ >
299
+ {node.name.length > 14 ? node.name.slice(0, 12) + '..' : node.name}
300
+ </text>
301
+ </g>
302
+ )
303
+ })}
304
+ </svg>
305
+ </div>
306
+ )}
307
+ </div>
308
+
309
+ {/* Right Telemetry / Inspector Drawer */}
310
+ <div className="w-full md:w-80 flex flex-col bg-base-200/50 rounded-2xl border border-base-content/10 overflow-hidden flex-none backdrop-blur-md">
311
+ <div className="p-3.5 border-b border-base-content/10 flex items-center justify-between bg-base-300/40">
312
+ <div className="flex items-center gap-2">
313
+ <Terminal className="w-4 h-4 text-primary" />
314
+ <span className="font-semibold text-xs tracking-wide">Inspeksi Agen</span>
315
+ </div>
316
+ {selectedAgent && (
317
+ <button
318
+ type="button"
319
+ onClick={() => onOpenIntercom(selectedAgent.id)}
320
+ className="btn btn-ghost btn-xs gap-1 text-[10px] text-primary hover:bg-primary/10"
321
+ title="Buka Chat Intercom Penuh"
322
+ >
323
+ Intercom <ExternalLink className="w-3 h-3" />
324
+ </button>
325
+ )}
326
+ </div>
327
+
328
+ {selectedAgent ? (
329
+ <div className="flex-1 flex flex-col overflow-y-auto p-3.5 space-y-3.5 custom-scrollbar">
330
+ {/* Agent Header Card */}
331
+ <div className="p-3 bg-base-100/60 rounded-xl border border-base-content/10 space-y-2">
332
+ <div className="flex items-center justify-between gap-2">
333
+ <div className="flex items-center gap-2 min-w-0">
334
+ <div className="w-7 h-7 rounded-lg bg-primary/15 border border-primary/30 text-primary flex items-center justify-center font-bold text-xs flex-none">
335
+ {selectedAgent.name.slice(0, 2).toUpperCase()}
336
+ </div>
337
+ <div className="min-w-0">
338
+ <h4 className="font-semibold text-xs truncate">{selectedAgent.name}</h4>
339
+ <p className="text-[10px] opacity-60 truncate font-mono">{selectedAgent.role}</p>
340
+ </div>
341
+ </div>
342
+ <div className="flex-none">
343
+ {selectedAgent.status === 'running' ? (
344
+ <span className="badge badge-primary badge-xs gap-1 font-mono text-[9px]">
345
+ <span className="w-1.5 h-1.5 rounded-full bg-primary-content animate-ping" />
346
+ RUNNING
347
+ </span>
348
+ ) : selectedAgent.status === 'idle' ? (
349
+ <span className="badge badge-primary badge-outline badge-xs font-mono text-[9px]">
350
+ IDLE / STANDBY
351
+ </span>
352
+ ) : selectedAgent.status === 'failed' || selectedAgent.status === 'killed' ? (
353
+ <span className="badge badge-error badge-xs font-mono text-[9px]">FAILED</span>
354
+ ) : (
355
+ <span className="badge badge-primary badge-outline badge-xs font-mono text-[9px]">COMPLETED</span>
356
+ )}
357
+ </div>
358
+ </div>
359
+
360
+ <div className="text-[10px] text-base-content/70 font-mono bg-base-200/60 p-2.5 rounded-lg border border-base-content/5">
361
+ <span className="text-primary font-bold block text-[9px] mb-0.5 uppercase tracking-wider">Misi / Goal:</span>
362
+ <p className="line-clamp-2 leading-relaxed">{selectedAgent.goal}</p>
363
+ </div>
364
+ </div>
365
+
366
+ {/* Live Progress / Output Preview */}
367
+ <div className="flex-1 bg-base-100/40 rounded-xl border border-base-content/10 p-3 space-y-2 flex flex-col">
368
+ <div className="flex items-center justify-between text-[10px] font-semibold text-base-content/70">
369
+ <span className="flex items-center gap-1.5">
370
+ <Sparkles className="w-3.5 h-3.5 text-primary" /> Laporan Terkini:
371
+ </span>
372
+ <span className="font-mono text-[9px]">Turn #{selectedAgent.turnCount || 0}</span>
373
+ </div>
374
+
375
+ <div className="flex-1 bg-base-200/50 rounded-lg p-2.5 text-[11px] font-mono leading-relaxed overflow-y-auto max-h-44 text-base-content/90 border border-base-content/5">
376
+ {selectedAgent.finalAnswer ? (
377
+ <p className="whitespace-pre-wrap">{selectedAgent.finalAnswer}</p>
378
+ ) : selectedAgent.status === 'running' ? (
379
+ <div className="flex items-center gap-2 text-primary opacity-80 py-2">
380
+ <Activity className="w-3.5 h-3.5 animate-spin" />
381
+ <span>Sedang memproses langkah...</span>
382
+ </div>
383
+ ) : (
384
+ <span className="opacity-40 italic">Belum ada output yang tercatat.</span>
385
+ )}
386
+ </div>
387
+ </div>
388
+
389
+ {/* Quick Mentoring / Correction Dispatch */}
390
+ <form onSubmit={handleQuickSend} className="space-y-1.5 pt-1">
391
+ <label className="text-[10px] font-semibold text-base-content/70 flex items-center gap-1">
392
+ <Send className="w-2.5 h-2.5 text-primary" /> Kirim Arahan Cepat (Lead Agent):
393
+ </label>
394
+ <div className="flex gap-1.5">
395
+ <input
396
+ type="text"
397
+ placeholder="Ketik instruksi koreksi..."
398
+ value={quickInput}
399
+ onChange={(e) => setQuickInput(e.target.value)}
400
+ className="input input-xs input-bordered flex-1 rounded-lg text-[11px] bg-base-100/60 focus:border-primary"
401
+ disabled={isSending}
402
+ />
403
+ <button
404
+ type="submit"
405
+ disabled={!quickInput.trim() || isSending}
406
+ className="btn btn-primary btn-xs rounded-lg px-2.5"
407
+ title="Kirim Pesan ke Sub-Agent"
408
+ >
409
+ {isSending ? <span className="loading loading-spinner loading-xs" /> : <Send className="w-3 h-3" />}
410
+ </button>
411
+ </div>
412
+ </form>
413
+ </div>
414
+ ) : (
415
+ <div className="flex-1 flex flex-col items-center justify-center p-6 text-center text-base-content/40 space-y-2">
416
+ <Bot className="w-8 h-8 stroke-[1.2] opacity-40 text-primary" />
417
+ <p className="text-xs">Klik salah satu node sub-agent pada diagram di samping untuk memeriksa status & memberikan arahan langsung.</p>
418
+ </div>
419
+ )}
420
+ </div>
421
+ </div>
422
+ )
423
+ }