@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,434 @@
1
+ /* eslint-disable react/prop-types */
2
+ import { memo, useState } from 'react'
3
+ import { Copy, Check, Bot, User, ChevronRight } from 'lucide-react'
4
+ import { FaTelegramPlane } from 'react-icons/fa'
5
+ import {
6
+ MessageBubble,
7
+ ThinkingBubble,
8
+ DurableTaskBubble,
9
+ MemoryFooterBubble,
10
+ PluginExecutionBubble,
11
+ YoutubeSummaryBubble,
12
+ YoutubeSearchBubble,
13
+ FollowUp,
14
+ Elicitation,
15
+ ElicitationsGroup,
16
+ ApprovalBubble
17
+ } from './Chat'
18
+ import { parseUserContent, parseAiContent, parseSubagentReport } from '../utils/chatContentParser'
19
+
20
+ const ChatList = ({
21
+ id = null,
22
+ role = 'user',
23
+ content = '',
24
+ reasoning = null,
25
+ isThinking = false,
26
+ isIntervention = false,
27
+ isCompacting = false,
28
+ compactProgress = '',
29
+ isLastCompacted = false,
30
+ lastCompactedMessageId = null,
31
+ isMemorySaved = false,
32
+ isMemoryUpdated = false,
33
+ isMemoryDeleted = false,
34
+ isSummarizing = false,
35
+ isYoutubeSummary = false,
36
+ isYoutubeSearch = false,
37
+ queryYoutube = '',
38
+ youtubeLink = '',
39
+ isSearchingMusic = false,
40
+ sources = [],
41
+ executionSteps = null,
42
+ executedTools = [],
43
+ isPlanSteps = false,
44
+ plan = [],
45
+ currentStep,
46
+ taskId = null,
47
+ taskTitle = '',
48
+ taskObjective = '',
49
+ taskStatus = null,
50
+ artifactRoot = null,
51
+ isPlanConclusion = false,
52
+ pluginExecution = null,
53
+ timestamp = '',
54
+ source = null,
55
+ sender = null,
56
+ onStop = null,
57
+ activeLiveTools = null,
58
+ activeThinkingContent = null,
59
+ isApproval = false,
60
+ approvalId = null,
61
+ approvalTool = '',
62
+ approvalQuery = null,
63
+ approvalStatus = 'pending'
64
+ }) => {
65
+ const [isCopied, setIsCopied] = useState(false)
66
+ const resolvedCurrentStep = currentStep !== undefined ? currentStep : plan ? plan.length : 0
67
+
68
+ if (isCompacting) {
69
+ return (
70
+ <div className="flex items-center justify-center my-4 opacity-75 select-none animate-fade-in">
71
+ <div className="border-t border-dashed border-white/20 flex-grow" />
72
+ <div className="flex items-center gap-2 px-3 font-mono text-[11px] uppercase tracking-wider text-white/70">
73
+ <span>{compactProgress || 'Merangkum Pesan'}</span>
74
+ <span className="loading loading-spinner loading-xs text-primary" />
75
+ </div>
76
+ <div className="border-t border-dashed border-white/20 flex-grow" />
77
+ </div>
78
+ )
79
+ }
80
+
81
+ const handleCopy = () => {
82
+ if (!content) return
83
+ let textToCopy = ''
84
+ if (typeof content === 'string') {
85
+ textToCopy = content
86
+ } else if (Array.isArray(content)) {
87
+ textToCopy = content
88
+ .filter((c) => c && (c.type === 'text' || typeof c === 'string'))
89
+ .map((c) => (typeof c === 'string' ? c : c.text))
90
+ .join('\n')
91
+ } else {
92
+ textToCopy = JSON.stringify(content, null, 2)
93
+ }
94
+ if (!textToCopy) return
95
+ navigator.clipboard.writeText(textToCopy)
96
+ setIsCopied(true)
97
+ setTimeout(() => setIsCopied(false), 2000)
98
+ }
99
+
100
+ const isUser = role === 'user'
101
+ const isTelegram = source === 'telegram'
102
+ const isSubagent = source === 'subagent'
103
+
104
+ // Bersihkan teks instruksi sistem skill jika pesan berasal dari user
105
+ const { displayUserContent, extractedSkillTag } = isUser
106
+ ? parseUserContent(content)
107
+ : { displayUserContent: content, extractedSkillTag: null }
108
+
109
+ // Ekstraksi tag-tag aksi Gemini Web bawaan (<FollowUp>, <ElicitationsGroup>, dll.)
110
+ const { cleanAiContent, followUpChips, elicitationGroup } = !isUser
111
+ ? parseAiContent(content)
112
+ : { cleanAiContent: content, followUpChips: [], elicitationGroup: null }
113
+
114
+ const handleChipClick = (queryText) => {
115
+ if (!queryText) return
116
+ window.dispatchEvent(new CustomEvent('trigger-quick-prompt', { detail: { prompt: queryText } }))
117
+ }
118
+
119
+ if (isApproval) {
120
+ return (
121
+ <div className="w-full my-3 py-1 group animate-[response-fade-in_0.2s_ease-out_forwards]">
122
+ {/* Header */}
123
+ <div className="flex items-center gap-2 mb-2 px-0.5 text-xs font-medium text-white/70">
124
+ <Bot className="w-4 h-4 text-primary" />
125
+ <span className="font-semibold text-white/90">Mark</span>
126
+ {timestamp && <span className="text-[10px] opacity-50 font-normal">{timestamp}</span>}
127
+ </div>
128
+
129
+ {/* Approval Bubble */}
130
+ <div className="w-full max-w-3xl">
131
+ <ApprovalBubble
132
+ approvalId={approvalId}
133
+ tool={approvalTool}
134
+ message={content}
135
+ query={approvalQuery}
136
+ status={approvalStatus}
137
+ timestamp={timestamp}
138
+ />
139
+ </div>
140
+ </div>
141
+ )
142
+ }
143
+
144
+ if (isPlanSteps && plan && plan.length > 0) {
145
+ return (
146
+ <div className="w-full my-3 py-1 group animate-[response-fade-in_0.2s_ease-out_forwards]">
147
+ {/* Header */}
148
+ <div className="flex items-center gap-2 mb-2 px-0.5 text-xs font-medium text-white/70">
149
+ <Bot className="w-4 h-4 text-primary" />
150
+ <span className="font-semibold text-white/90">Mark</span>
151
+ {timestamp && <span className="text-[10px] opacity-50 font-normal">{timestamp}</span>}
152
+ </div>
153
+
154
+ {/* Normal Bubble Content Flow */}
155
+ <div className="w-full text-base-content leading-relaxed">
156
+ <DurableTaskBubble
157
+ plan={plan}
158
+ resolvedCurrentStep={resolvedCurrentStep}
159
+ reasoning={reasoning}
160
+ taskId={taskId}
161
+ taskTitle={taskTitle}
162
+ taskObjective={taskObjective}
163
+ taskStatus={taskStatus}
164
+ artifactRoot={artifactRoot}
165
+ onStop={onStop}
166
+ executedTools={executedTools}
167
+ activeLiveTools={activeLiveTools}
168
+ activeThinkingContent={activeThinkingContent}
169
+ />
170
+ </div>
171
+ </div>
172
+ )
173
+ }
174
+
175
+ // Jika pesan berasal dari laporan subagent, render dalam kontainer flat collapsible
176
+ if (isSubagent) {
177
+ const { cleanReportContent, artifactInfo } = parseSubagentReport(content)
178
+
179
+ return (
180
+ <div className="w-full my-4 group animate-[response-fade-in_0.2s_ease-out_forwards]">
181
+ {/* Header (Nama Sub-Agent & Badge) */}
182
+ <div className="flex items-center gap-2 mb-2 px-1 text-[11px] font-semibold opacity-75">
183
+ <Bot className="w-4 h-4 text-white/70" />
184
+ <span className="text-white font-medium">{sender || 'Sub-Agent'}</span>
185
+ {timestamp && <span className="text-[10px] opacity-50 font-normal">{timestamp}</span>}
186
+ </div>
187
+
188
+ {/* Flat Collapsible Container */}
189
+ <div className="w-full rounded-2xl bg-base-200/80 border border-white/10 shadow-sm backdrop-blur-md overflow-hidden">
190
+ <details className="group/subreport">
191
+ <summary className="list-none flex items-center justify-between px-4 py-3 cursor-pointer hover:bg-white/5 transition-colors select-none">
192
+ <div className="flex items-center gap-2 min-w-0 pr-2">
193
+ <span className="text-xs font-semibold text-white/90 truncate">
194
+ Lihat Rangkuman Laporan Dari Sub Agents
195
+ </span>
196
+ </div>
197
+ <ChevronRight className="w-4 h-4 text-white/50 transition-transform duration-200 group-open/subreport:rotate-90 shrink-0" />
198
+ </summary>
199
+
200
+ <div className="p-4 border-t border-white/10 text-sm leading-relaxed custom-markdown bg-black/20">
201
+ <MessageBubble
202
+ isUser={false}
203
+ content={cleanReportContent}
204
+ reasoning={reasoning}
205
+ sources={sources}
206
+ executionSteps={executionSteps}
207
+ executedTools={executedTools}
208
+ />
209
+
210
+ {artifactInfo && (
211
+ <div className="mt-3 pt-3 border-t border-white/10 flex items-center gap-2 text-xs text-emerald-400 font-mono">
212
+ <span className="font-semibold text-slate-400 uppercase text-[10px]">
213
+ Artefak:
214
+ </span>
215
+ <span className="bg-black/40 px-2 py-1 rounded border border-white/10 truncate max-w-md">
216
+ {artifactInfo}
217
+ </span>
218
+ </div>
219
+ )}
220
+ </div>
221
+ </details>
222
+ </div>
223
+ </div>
224
+ )
225
+ }
226
+
227
+ const showCompactedDivider =
228
+ isLastCompacted ||
229
+ (lastCompactedMessageId &&
230
+ (String(id) === String(lastCompactedMessageId) ||
231
+ String(timestamp) === String(lastCompactedMessageId)))
232
+
233
+ return (
234
+ <>
235
+ {isUser ? (
236
+ isIntervention ? (
237
+ <div className="max-w-[85%] md:max-w-2xl ml-auto mb-2 flex flex-col items-end group animate-[response-fade-in_0.2s_ease-out_forwards]">
238
+ <div
239
+ title={timestamp ? `Intervensi sela • ${timestamp}` : 'Intervensi sela'}
240
+ className="rounded-xl rounded-tr-sm bg-base-200/80 text-white/90 border border-white/10 px-3.5 py-1.5 text-xs shadow-sm backdrop-blur-md select-text break-words transition-all hover:border-white/20"
241
+ >
242
+ <MessageBubble
243
+ isUser={true}
244
+ content={displayUserContent}
245
+ reasoning={reasoning}
246
+ sources={sources}
247
+ executionSteps={executionSteps}
248
+ executedTools={executedTools}
249
+ isPlanConclusion={isPlanConclusion}
250
+ />
251
+ </div>
252
+ </div>
253
+ ) : (
254
+ <div className="max-w-[85%] md:max-w-3xl ml-auto mb-3 flex flex-col items-end group animate-[response-fade-in_0.2s_ease-out_forwards]">
255
+ {/* Header */}
256
+ <div className="text-[11px] font-semibold opacity-75 mb-1.5 flex items-center gap-2 px-1 text-white/70">
257
+ <User className="w-3.5 h-3.5 text-white/50" />
258
+ <span>{isTelegram ? sender || 'Telegram Admin' : 'You'}</span>
259
+ {isTelegram && (
260
+ <span className="badge badge-xs bg-[#229ED9]/15 text-[#229ED9] border-[#229ED9]/30 gap-1 font-mono text-[9px] py-0.5 px-1.5 flex items-center font-normal">
261
+ <FaTelegramPlane className="w-2.5 h-2.5" /> Telegram
262
+ </span>
263
+ )}
264
+ {extractedSkillTag && (
265
+ <span className="badge badge-xs bg-black/40 text-primary border border-primary/40 font-mono text-[9px] py-0.5 px-1.5 font-semibold">
266
+ Skill: /{extractedSkillTag}
267
+ </span>
268
+ )}
269
+ {timestamp && <span className="text-[10px] opacity-50 font-normal">{timestamp}</span>}
270
+ </div>
271
+
272
+ {/* User Bubble Card */}
273
+ <div
274
+ className={`rounded-2xl rounded-tr-sm shadow-md transition-all duration-200 break-words overflow-hidden px-5 py-3.5 border ${
275
+ isTelegram
276
+ ? 'bg-gradient-to-br from-[#229ED9]/30 to-[#0088cc]/30 text-white border-[#229ED9]/40 backdrop-blur-md'
277
+ : 'bg-base-200/90 text-base-content border-white/10 backdrop-blur-md'
278
+ }`}
279
+ >
280
+ <MessageBubble
281
+ isUser={true}
282
+ content={displayUserContent}
283
+ reasoning={reasoning}
284
+ sources={sources}
285
+ executionSteps={executionSteps}
286
+ executedTools={executedTools}
287
+ isPlanConclusion={isPlanConclusion}
288
+ />
289
+ </div>
290
+
291
+ <MemoryFooterBubble
292
+ isMemorySaved={isMemorySaved}
293
+ isMemoryUpdated={isMemoryUpdated}
294
+ isMemoryDeleted={isMemoryDeleted}
295
+ />
296
+ </div>
297
+ )
298
+ ) : (
299
+ <div className="w-full my-3 py-1 group animate-[response-fade-in_0.2s_ease-out_forwards]">
300
+ {/* Header & Actions */}
301
+ <div className="flex items-center justify-between mb-2.5 px-0.5">
302
+ <div className="flex items-center gap-2 text-xs font-medium text-white/70">
303
+ <Bot className="w-4 h-4 text-primary" />
304
+ <span className="font-semibold text-white/90">Mark</span>
305
+ {isTelegram && (
306
+ <span className="badge badge-xs bg-[#229ED9]/15 text-[#229ED9] border-[#229ED9]/30 gap-1 font-mono text-[9px] py-0.5 px-1.5 flex items-center font-normal">
307
+ <FaTelegramPlane className="w-2.5 h-2.5" /> Telegram Reply
308
+ </span>
309
+ )}
310
+ {timestamp && <span className="text-[10px] opacity-50 font-normal">{timestamp}</span>}
311
+ </div>
312
+
313
+ {/* Action: Copy Button on hover */}
314
+ {content && !isThinking && !isSummarizing && !isSearchingMusic && (
315
+ <div className="opacity-0 group-hover:opacity-100 transition-opacity flex items-center gap-1.5">
316
+ <button
317
+ onClick={handleCopy}
318
+ className="btn btn-ghost btn-xs text-white/50 hover:text-white p-1 h-auto min-h-0 flex items-center gap-1 rounded cursor-pointer"
319
+ title="Salin teks pesan"
320
+ >
321
+ {isCopied ? (
322
+ <>
323
+ <Check className="w-3.5 h-3.5 text-success" />
324
+ <span className="text-[10px] text-success font-medium">Tersalin</span>
325
+ </>
326
+ ) : (
327
+ <>
328
+ <Copy className="w-3.5 h-3.5" />
329
+ <span className="text-[10px]">Salin</span>
330
+ </>
331
+ )}
332
+ </button>
333
+ </div>
334
+ )}
335
+ </div>
336
+
337
+ {/* Document Content Flow */}
338
+ <div className="w-full text-base-content leading-relaxed">
339
+ {(isThinking &&
340
+ (!content ||
341
+ content.startsWith('Mengeksekusi') ||
342
+ content.startsWith('Sedang') ||
343
+ content.startsWith('Memproses') ||
344
+ content.startsWith('Mengakses') ||
345
+ content.startsWith('Menganalisis') ||
346
+ content.startsWith('(Sedang berbicara)') ||
347
+ content === 'Mark sedang menganalisis & mengeksekusi...')) ||
348
+ isSummarizing ||
349
+ isSearchingMusic ? (
350
+ <ThinkingBubble
351
+ isThinking={isThinking}
352
+ isSummarizing={isSummarizing}
353
+ isSearchingMusic={isSearchingMusic}
354
+ content={content}
355
+ youtubeLink={youtubeLink}
356
+ reasoning={reasoning}
357
+ executionSteps={executionSteps}
358
+ executedTools={executedTools}
359
+ />
360
+ ) : (
361
+ <div className="flex flex-col gap-3">
362
+ {isYoutubeSummary && <YoutubeSummaryBubble youtubeLink={youtubeLink} />}
363
+ {isYoutubeSearch && (
364
+ <YoutubeSearchBubble queryYoutube={queryYoutube} youtubeLink={youtubeLink} />
365
+ )}
366
+ {pluginExecution && <PluginExecutionBubble pluginExecution={pluginExecution} />}
367
+ <MessageBubble
368
+ isUser={false}
369
+ content={cleanAiContent}
370
+ reasoning={reasoning}
371
+ sources={sources}
372
+ executionSteps={executionSteps}
373
+ executedTools={executedTools}
374
+ isPlanConclusion={isPlanConclusion}
375
+ isThinking={isThinking}
376
+ />
377
+
378
+ {/* Opsi Klarifikasi (ElicitationsGroup dari Gemini) */}
379
+ {elicitationGroup && elicitationGroup.options?.length > 0 && (
380
+ <ElicitationsGroup message={elicitationGroup.message}>
381
+ {elicitationGroup.options.map((opt, idx) => (
382
+ <Elicitation
383
+ key={idx}
384
+ label={opt.label}
385
+ query={opt.query}
386
+ onClick={handleChipClick}
387
+ />
388
+ ))}
389
+ </ElicitationsGroup>
390
+ )}
391
+
392
+ {/* Rekomendasi Pertanyaan / Aksi Lanjutan (FollowUp / Suggestion dari Gemini) */}
393
+ {followUpChips && followUpChips.length > 0 && (
394
+ <div className="mt-3 pt-2.5 border-t border-white/10 flex flex-col gap-1.5 animate-fade-in">
395
+ <span className="text-[10px] font-medium text-slate-400">
396
+ Rekomendasi Pertanyaan:
397
+ </span>
398
+ <div className="flex flex-wrap gap-1.5">
399
+ {followUpChips.map((chip, idx) => (
400
+ <FollowUp
401
+ key={idx}
402
+ label={chip.label}
403
+ query={chip.query}
404
+ onClick={handleChipClick}
405
+ />
406
+ ))}
407
+ </div>
408
+ </div>
409
+ )}
410
+ </div>
411
+ )}
412
+ </div>
413
+
414
+ <MemoryFooterBubble
415
+ isMemorySaved={isMemorySaved}
416
+ isMemoryUpdated={isMemoryUpdated}
417
+ isMemoryDeleted={isMemoryDeleted}
418
+ />
419
+ </div>
420
+ )}
421
+ {showCompactedDivider && (
422
+ <div className="flex items-center justify-center my-4 opacity-50 select-none">
423
+ <div className="border-t border-dashed border-white/20 flex-grow" />
424
+ <span className="px-3 font-mono text-[11px] uppercase tracking-wider text-white/60">
425
+ Message Compacted
426
+ </span>
427
+ <div className="border-t border-dashed border-white/20 flex-grow" />
428
+ </div>
429
+ )}
430
+ </>
431
+ )
432
+ }
433
+
434
+ export default memo(ChatList)
@@ -0,0 +1,67 @@
1
+ import { useState, useEffect, useRef } from 'react'
2
+ import { useChat } from '../contexts/ChatContext'
3
+ import { CameraPreview } from './camera/CameraPreview'
4
+
5
+ export const GlobalCameraManager = () => {
6
+ const { requestCameraCaptureRef } = useChat()
7
+ const [isCameraOpen, setIsCameraOpen] = useState(false)
8
+ const [cameraIsAutonomous, setCameraIsAutonomous] = useState(false)
9
+ const [cameraDeviceId, setCameraDeviceId] = useState(null)
10
+ const cameraResolverRef = useRef(null)
11
+
12
+ useEffect(() => {
13
+ if (requestCameraCaptureRef) {
14
+ console.log('[GlobalCameraManager] Setting requestCameraCaptureRef.current callback')
15
+ requestCameraCaptureRef.current = ({ isAutonomous, deviceId }) => {
16
+ console.log(
17
+ '[GlobalCameraManager] Camera capture requested! isAutonomous:',
18
+ isAutonomous,
19
+ 'deviceId:',
20
+ deviceId
21
+ )
22
+ return new Promise((resolve) => {
23
+ cameraResolverRef.current = resolve
24
+ setCameraIsAutonomous(isAutonomous || false)
25
+ setCameraDeviceId(deviceId || null)
26
+ setIsCameraOpen(true)
27
+ })
28
+ }
29
+
30
+ return () => {
31
+ requestCameraCaptureRef.current = null
32
+ if (cameraResolverRef.current) {
33
+ cameraResolverRef.current(null)
34
+ cameraResolverRef.current = null
35
+ }
36
+ }
37
+ } else {
38
+ console.warn('[GlobalCameraManager] requestCameraCaptureRef is undefined/null from context!')
39
+ }
40
+ }, [requestCameraCaptureRef])
41
+
42
+ const handleCameraCapture = (base64) => {
43
+ if (cameraResolverRef.current) {
44
+ cameraResolverRef.current(base64)
45
+ cameraResolverRef.current = null
46
+ }
47
+ setIsCameraOpen(false)
48
+ }
49
+
50
+ const handleCameraClose = () => {
51
+ if (cameraResolverRef.current) {
52
+ cameraResolverRef.current(null)
53
+ cameraResolverRef.current = null
54
+ }
55
+ setIsCameraOpen(false)
56
+ }
57
+
58
+ return (
59
+ <CameraPreview
60
+ isOpen={isCameraOpen}
61
+ onClose={handleCameraClose}
62
+ onCapture={handleCameraCapture}
63
+ isAutonomous={cameraIsAutonomous}
64
+ deviceId={cameraDeviceId}
65
+ />
66
+ )
67
+ }
@@ -0,0 +1,15 @@
1
+ import { useState } from 'react'
2
+
3
+ function Versions() {
4
+ const [versions] = useState(window.electron.process.versions)
5
+
6
+ return (
7
+ <ul className="versions">
8
+ <li className="electron-version">Electron v{versions.electron}</li>
9
+ <li className="chrome-version">Chromium v{versions.chrome}</li>
10
+ <li className="node-version">Node v{versions.node}</li>
11
+ </ul>
12
+ )
13
+ }
14
+
15
+ export default Versions