@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.
- package/LICENSE +29 -0
- package/README.md +209 -0
- package/bin/mark.js +27 -0
- package/out/renderer/assets/icon-DHo2CYph.svg +1 -0
- package/out/renderer/assets/index-G2fADWO-.js +4768 -0
- package/out/renderer/assets/index-f3mVse3c.css +1 -0
- package/out/renderer/assets/music-cover-CG4vi3kZ.png +0 -0
- package/out/renderer/assets/poppins-devanagari-400-normal-CJDn6rn8.woff2 +0 -0
- package/out/renderer/assets/poppins-devanagari-400-normal-CqVvlrh5.woff +0 -0
- package/out/renderer/assets/poppins-devanagari-500-normal-BIdkeU1p.woff2 +0 -0
- package/out/renderer/assets/poppins-devanagari-500-normal-DMPDjHtT.woff +0 -0
- package/out/renderer/assets/poppins-devanagari-600-normal-ClASKHrr.woff +0 -0
- package/out/renderer/assets/poppins-devanagari-600-normal-STEjXBNN.woff2 +0 -0
- package/out/renderer/assets/poppins-devanagari-700-normal-O-jipLrW.woff2 +0 -0
- package/out/renderer/assets/poppins-devanagari-700-normal-fHs-vx92.woff +0 -0
- package/out/renderer/assets/poppins-latin-400-normal-BOb3E3N0.woff +0 -0
- package/out/renderer/assets/poppins-latin-400-normal-cpxAROuN.woff2 +0 -0
- package/out/renderer/assets/poppins-latin-500-normal-C8OXljZJ.woff2 +0 -0
- package/out/renderer/assets/poppins-latin-500-normal-DGXqpDMm.woff +0 -0
- package/out/renderer/assets/poppins-latin-600-normal-BJdTmd5m.woff +0 -0
- package/out/renderer/assets/poppins-latin-600-normal-zEkxB9Mr.woff2 +0 -0
- package/out/renderer/assets/poppins-latin-700-normal-BVuQR_eA.woff +0 -0
- package/out/renderer/assets/poppins-latin-700-normal-Qrb0O0WB.woff2 +0 -0
- package/out/renderer/assets/poppins-latin-ext-400-normal-DaBSavcJ.woff +0 -0
- package/out/renderer/assets/poppins-latin-ext-400-normal-by3JarPu.woff2 +0 -0
- package/out/renderer/assets/poppins-latin-ext-500-normal-CK-6C4Hw.woff2 +0 -0
- package/out/renderer/assets/poppins-latin-ext-500-normal-CgAe2rWW.woff +0 -0
- package/out/renderer/assets/poppins-latin-ext-600-normal-CAhIAdZj.woff2 +0 -0
- package/out/renderer/assets/poppins-latin-ext-600-normal-Df5ffKXP.woff +0 -0
- package/out/renderer/assets/poppins-latin-ext-700-normal-DctTR6Tg.woff +0 -0
- package/out/renderer/assets/poppins-latin-ext-700-normal-cby-RkWa.woff2 +0 -0
- package/out/renderer/favicon.ico +0 -0
- package/out/renderer/icon-256.png +0 -0
- package/out/renderer/icon.svg +1 -0
- package/out/renderer/index.html +25 -0
- package/out/renderer/manifest.json +25 -0
- package/out/renderer/robot-simulator.html +1640 -0
- package/package.json +106 -0
- package/src/cli/index.js +332 -0
- package/src/cli/monitor.js +413 -0
- package/src/cli/theme.js +347 -0
- package/src/launcher/MarkTray.cs +227 -0
- package/src/main/browser-agent.js +1132 -0
- package/src/main/git-service.js +90 -0
- package/src/main/google/google-calendar.js +69 -0
- package/src/main/google/google-drive.js +263 -0
- package/src/main/google/google-gmail.js +131 -0
- package/src/main/google/google-service.js +241 -0
- package/src/main/node-tools.js +23 -0
- package/src/main/pc-agent-scripts/mouse-locker.ps1 +76 -0
- package/src/main/pc-agent-scripts/ocr-region.ps1 +185 -0
- package/src/main/pc-agent-scripts/pc-daemon.ps1 +726 -0
- package/src/main/pc-agent-scripts/pc-overlay.ps1 +253 -0
- package/src/main/pc-agent-scripts/pick-folder.ps1 +33 -0
- package/src/main/pc-agent-scripts/read-ui.ps1 +181 -0
- package/src/main/pc-agent-scripts/take-screenshot.ps1 +24 -0
- package/src/main/pc-agent-scripts/win-action.ps1 +380 -0
- package/src/main/plugins/plugin-loader.js +306 -0
- package/src/main/skills/skill-manager.js +265 -0
- package/src/main/syntax-validator.js +455 -0
- package/src/main/task-daemon.js +117 -0
- package/src/main/telegram/telegram-service.js +835 -0
- package/src/main/tools/browser-tools.js +516 -0
- package/src/main/tools/file-tools.js +1126 -0
- package/src/main/tools/git-tools.js +79 -0
- package/src/main/tools/google-tools.js +566 -0
- package/src/main/tools/index.js +36 -0
- package/src/main/tools/media-tools.js +42 -0
- package/src/main/tools/system-tools.js +295 -0
- package/src/main/tools/task-tools.js +73 -0
- package/src/main/tools/telegram-tools.js +101 -0
- package/src/renderer/index.html +24 -0
- package/src/renderer/public/favicon.ico +0 -0
- package/src/renderer/public/icon-256.png +0 -0
- package/src/renderer/public/icon.svg +1 -0
- package/src/renderer/public/manifest.json +25 -0
- package/src/renderer/public/robot-simulator.html +1640 -0
- package/src/renderer/src/App.jsx +304 -0
- package/src/renderer/src/api/ai/awareness.js +294 -0
- package/src/renderer/src/api/ai/chatSummarizer.js +79 -0
- package/src/renderer/src/api/ai/contextCompactor.js +129 -0
- package/src/renderer/src/api/ai/contextManager.js +1130 -0
- package/src/renderer/src/api/ai/core.js +167 -0
- package/src/renderer/src/api/ai/index.js +4 -0
- package/src/renderer/src/api/ai/memoryGroomer.js +101 -0
- package/src/renderer/src/api/ai/persona.js +115 -0
- package/src/renderer/src/api/ai/planning.js +317 -0
- package/src/renderer/src/api/ai/relationship.js +177 -0
- package/src/renderer/src/api/ai/skillSynthesizer.js +168 -0
- package/src/renderer/src/api/ai/tools.js +167 -0
- package/src/renderer/src/api/ai/utils.js +359 -0
- package/src/renderer/src/api/db.js +1013 -0
- package/src/renderer/src/api/oramaStore.js +592 -0
- package/src/renderer/src/api/ragPipeline.js +87 -0
- package/src/renderer/src/api/subagent/subagentExecutor.js +780 -0
- package/src/renderer/src/api/subagent/subagentPrompt.js +44 -0
- package/src/renderer/src/api/subagent/subagentStore.js +173 -0
- package/src/renderer/src/api/taskExecutor.js +18 -0
- package/src/renderer/src/api/taskStore.js +315 -0
- package/src/renderer/src/api/tools/core-tools.js +707 -0
- package/src/renderer/src/api/tools/index.js +151 -0
- package/src/renderer/src/api/turnPairMigrator.js +200 -0
- package/src/renderer/src/api/vectorMemory.js +136 -0
- package/src/renderer/src/api/wakeWord.js +101 -0
- package/src/renderer/src/api/web-bridge.js +885 -0
- package/src/renderer/src/api/webSpeech.js +178 -0
- package/src/renderer/src/api/workspaceRag.js +76 -0
- package/src/renderer/src/assets/electron.svg +10 -0
- package/src/renderer/src/assets/icon.svg +1 -0
- package/src/renderer/src/assets/main.css +589 -0
- package/src/renderer/src/assets/music-cover.png +0 -0
- package/src/renderer/src/assets/wavy-lines.svg +25 -0
- package/src/renderer/src/components/Chat/ApprovalBubble.jsx +127 -0
- package/src/renderer/src/components/Chat/CodeBlock.jsx +83 -0
- package/src/renderer/src/components/Chat/DurableTaskBubble.jsx +455 -0
- package/src/renderer/src/components/Chat/FileDiffModal.jsx +328 -0
- package/src/renderer/src/components/Chat/GeminiWidgets.jsx +82 -0
- package/src/renderer/src/components/Chat/MemoryFooterBubble.jsx +34 -0
- package/src/renderer/src/components/Chat/MessageBubble.jsx +459 -0
- package/src/renderer/src/components/Chat/PluginExecutionBubble.jsx +41 -0
- package/src/renderer/src/components/Chat/ThinkingBubble.jsx +316 -0
- package/src/renderer/src/components/Chat/YoutubeSearchBubble.jsx +43 -0
- package/src/renderer/src/components/Chat/YoutubeSummaryBubble.jsx +40 -0
- package/src/renderer/src/components/Chat/index.js +11 -0
- package/src/renderer/src/components/ChatList.jsx +434 -0
- package/src/renderer/src/components/GlobalCameraManager.jsx +67 -0
- package/src/renderer/src/components/Versions.jsx +15 -0
- package/src/renderer/src/components/YoutubeMusicPlayer.jsx +375 -0
- package/src/renderer/src/components/camera/CameraPreview.jsx +236 -0
- package/src/renderer/src/components/config/AiEngineSection.jsx +363 -0
- package/src/renderer/src/components/config/CameraSection.jsx +100 -0
- package/src/renderer/src/components/config/PermissionsSection.jsx +130 -0
- package/src/renderer/src/components/config/ShortcutSection.jsx +102 -0
- package/src/renderer/src/components/config/VoiceSection.jsx +110 -0
- package/src/renderer/src/components/config/index.js +5 -0
- package/src/renderer/src/components/core/Avatar.jsx +2197 -0
- package/src/renderer/src/components/core/ConfirmModal.jsx +80 -0
- package/src/renderer/src/components/core/DraggableHoloCard.jsx +125 -0
- package/src/renderer/src/components/core/FloatingMenu.jsx +272 -0
- package/src/renderer/src/components/core/HoloCard.jsx +64 -0
- package/src/renderer/src/components/core/InputBar.jsx +1346 -0
- package/src/renderer/src/components/core/ProcessPanel.jsx +216 -0
- package/src/renderer/src/components/core/ResponseArea.jsx +149 -0
- package/src/renderer/src/components/core/StatusIndicator.jsx +59 -0
- package/src/renderer/src/components/core/ThoughtNeuralFlow.jsx +168 -0
- package/src/renderer/src/components/core/ToolClustersDeck.jsx +210 -0
- package/src/renderer/src/components/core/native-skills.js +43 -0
- package/src/renderer/src/components/neural-core/EmotionalCortexLobe.jsx +359 -0
- package/src/renderer/src/components/neural-core/NodeDissectionModal.jsx +57 -0
- package/src/renderer/src/components/neural-core/ProceduralMatrixLobe.jsx +193 -0
- package/src/renderer/src/components/neural-core/ProceduralSkillModal.jsx +53 -0
- package/src/renderer/src/components/neural-core/ResetAiModal.jsx +198 -0
- package/src/renderer/src/components/neural-core/SynapticMemoryLobe.jsx +204 -0
- package/src/renderer/src/components/neural-core/traitMeta.js +102 -0
- package/src/renderer/src/components/subagent/AgentChatFeed.jsx +603 -0
- package/src/renderer/src/components/subagent/AgentInspector.jsx +224 -0
- package/src/renderer/src/components/subagent/AgentSidebar.jsx +216 -0
- package/src/renderer/src/components/subagent/SubagentIntercom.jsx +572 -0
- package/src/renderer/src/components/subagent/SubagentTopologyMap.jsx +423 -0
- package/src/renderer/src/contexts/ApprovalContext.jsx +425 -0
- package/src/renderer/src/contexts/ChatContext.jsx +61 -0
- package/src/renderer/src/contexts/YoutubeMusicContext.jsx +333 -0
- package/src/renderer/src/data/faqData.js +202 -0
- package/src/renderer/src/hooks/agent/executeAgentTool.js +895 -0
- package/src/renderer/src/hooks/agent/index.js +4 -0
- package/src/renderer/src/hooks/agent/useMarkMusic.js +75 -0
- package/src/renderer/src/hooks/agent/useMarkPlan.js +2739 -0
- package/src/renderer/src/hooks/agent/useMarkState.js +173 -0
- package/src/renderer/src/hooks/agent/useMarkYoutube.js +82 -0
- package/src/renderer/src/hooks/agent/useRelationalGrowth.js +201 -0
- package/src/renderer/src/hooks/telegram/useTelegramBot.js +63 -0
- package/src/renderer/src/hooks/useAwareness.js +289 -0
- package/src/renderer/src/hooks/useChatArchiver.js +52 -0
- package/src/renderer/src/hooks/useConfirm.jsx +68 -0
- package/src/renderer/src/hooks/useMarkAgent.js +454 -0
- package/src/renderer/src/hooks/useMemoryGroomer.js +152 -0
- package/src/renderer/src/hooks/useVAD.js +511 -0
- package/src/renderer/src/hooks/useWebSpeechWakeWord.js +122 -0
- package/src/renderer/src/main.jsx +12 -0
- package/src/renderer/src/pages/ChatStudio.jsx +922 -0
- package/src/renderer/src/pages/Configuration.jsx +360 -0
- package/src/renderer/src/pages/GoogleWorkspace.jsx +293 -0
- package/src/renderer/src/pages/Guidebook.jsx +917 -0
- package/src/renderer/src/pages/Knowledge.jsx +241 -0
- package/src/renderer/src/pages/MarkHome.jsx +491 -0
- package/src/renderer/src/pages/NeuralCore.jsx +786 -0
- package/src/renderer/src/pages/Plugins.jsx +630 -0
- package/src/renderer/src/pages/SkillEditor.jsx +380 -0
- package/src/renderer/src/pages/Skills.jsx +219 -0
- package/src/renderer/src/pages/Subagents.jsx +342 -0
- package/src/renderer/src/pages/TelegramBot.jsx +343 -0
- package/src/renderer/src/utils/chatContentParser.js +203 -0
- package/src/renderer/src/utils/toolClusters.js +201 -0
- package/src/server/bin/sha3_wasm_bg.wasm +0 -0
- package/src/server/config-manager.js +57 -0
- package/src/server/index.js +195 -0
- package/src/server/launcher.js +87 -0
- package/src/server/memory/db-store.js +758 -0
- package/src/server/memory/orama-store.js +177 -0
- package/src/server/memory/vector-engine.js +109 -0
- package/src/server/routes/ai.routes.js +280 -0
- package/src/server/routes/awareness.routes.js +62 -0
- package/src/server/routes/chat.routes.js +61 -0
- package/src/server/routes/config.routes.js +41 -0
- package/src/server/routes/index.js +35 -0
- package/src/server/routes/integrations.routes.js +116 -0
- package/src/server/routes/memory.routes.js +256 -0
- package/src/server/routes/plugins.routes.js +72 -0
- package/src/server/routes/skills.routes.js +139 -0
- package/src/server/routes/subagents.routes.js +70 -0
- package/src/server/routes/tasks.routes.js +175 -0
- package/src/server/routes/workspace.routes.js +127 -0
- package/src/server/services/ai/ai-utils.js +161 -0
- package/src/server/services/ai/openai-provider.js +757 -0
- package/src/server/services/ai/web-provider.js +729 -0
- package/src/server/services/ai-bridge.js +46 -0
- package/src/server/services/deepseek-web.js +956 -0
- package/src/server/services/gemini-web.js +170 -0
- package/src/server/services/notification-service.js +91 -0
- package/src/server/services/updater.js +125 -0
- package/src/server/tools/awareness-tracker.js +292 -0
- package/src/server/tools/group-tools.js +1164 -0
- package/src/server/tools/media-tools.js +244 -0
- package/src/server/tools/pc-agent.js +327 -0
- package/src/server/tools/screen-service.js +51 -0
- package/src/server/ws-hub.js +168 -0
- package/src/shared/parsers/mark-tag-parser.js +275 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { useState, useEffect, useRef } from 'react'
|
|
2
|
+
import { getAllConfig, saveMainThread, getMainThread } from '../../api/db'
|
|
3
|
+
|
|
4
|
+
export const useMarkState = () => {
|
|
5
|
+
const [chatData, setChatData] = useState([])
|
|
6
|
+
const [config, setConfig] = useState([])
|
|
7
|
+
const [message, setMessage] = useState('')
|
|
8
|
+
const [isLoading, setIsLoading] = useState(false)
|
|
9
|
+
const [isAgentBusy, setIsAgentBusy] = useState(false)
|
|
10
|
+
const [runningSessionIds, setRunningSessionIds] = useState([])
|
|
11
|
+
const runningSessionId = runningSessionIds[0] || null
|
|
12
|
+
|
|
13
|
+
const addRunningSessionId = (id) => {
|
|
14
|
+
const num = Number(id)
|
|
15
|
+
setRunningSessionIds((prev) => (prev.map(Number).includes(num) ? prev : [...prev, num]))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const removeRunningSessionId = (id) => {
|
|
19
|
+
const num = Number(id)
|
|
20
|
+
setRunningSessionIds((prev) => prev.filter((x) => Number(x) !== num))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const setRunningSessionId = (id) => {
|
|
24
|
+
if (id === null || id === undefined) {
|
|
25
|
+
setRunningSessionIds([])
|
|
26
|
+
} else {
|
|
27
|
+
addRunningSessionId(id)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const [isSpeak, setIsSpeak] = useState(false)
|
|
31
|
+
const [orbStatus, setOrbStatus] = useState('idle')
|
|
32
|
+
const [currentResponse, setCurrentResponse] = useState(null)
|
|
33
|
+
const [notifications, setNotifications] = useState([])
|
|
34
|
+
const [activeProcesses, setActiveProcesses] = useState([])
|
|
35
|
+
const [inputSource, setInputSource] = useState('pc')
|
|
36
|
+
const [activeTopic, setActiveTopic] = useState(null)
|
|
37
|
+
const [currentActiveSessionId, setCurrentActiveSessionId] = useState('1')
|
|
38
|
+
const [isChatLoaded, setIsChatLoaded] = useState(false)
|
|
39
|
+
const [isBooting, setIsBooting] = useState(true)
|
|
40
|
+
const sessionId = useRef('mark-main-thread')
|
|
41
|
+
|
|
42
|
+
const abortControllerRef = useRef(null)
|
|
43
|
+
|
|
44
|
+
const loadConfig = async () => {
|
|
45
|
+
const data = await getAllConfig()
|
|
46
|
+
if (data.length > 0) setConfig(data)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
loadConfig()
|
|
51
|
+
loadMainThread()
|
|
52
|
+
|
|
53
|
+
const handleConfigUpdate = (e) => {
|
|
54
|
+
if (e.detail) {
|
|
55
|
+
setConfig([e.detail])
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const handleAiReset = () => {
|
|
60
|
+
setChatData([])
|
|
61
|
+
setCurrentActiveSessionId('1')
|
|
62
|
+
setActiveTopic(null)
|
|
63
|
+
setCurrentResponse(null)
|
|
64
|
+
setNotifications([])
|
|
65
|
+
setActiveProcesses([])
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
window.addEventListener('config-updated', handleConfigUpdate)
|
|
69
|
+
window.addEventListener('ai-reset-complete', handleAiReset)
|
|
70
|
+
return () => {
|
|
71
|
+
window.removeEventListener('config-updated', handleConfigUpdate)
|
|
72
|
+
window.removeEventListener('ai-reset-complete', handleAiReset)
|
|
73
|
+
}
|
|
74
|
+
}, [])
|
|
75
|
+
|
|
76
|
+
const loadMainThread = async () => {
|
|
77
|
+
const data = await getMainThread()
|
|
78
|
+
if (data && data.length > 0) {
|
|
79
|
+
setChatData(data)
|
|
80
|
+
}
|
|
81
|
+
setIsChatLoaded(true)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
// Debounce simpan ke DB agar tidak membanjiri SQLite REST endpoint saat streaming token
|
|
86
|
+
if (chatData !== undefined && isChatLoaded) {
|
|
87
|
+
const timer = setTimeout(() => {
|
|
88
|
+
saveMainThread(chatData)
|
|
89
|
+
}, 800)
|
|
90
|
+
return () => clearTimeout(timer)
|
|
91
|
+
}
|
|
92
|
+
}, [chatData, isChatLoaded])
|
|
93
|
+
|
|
94
|
+
const clearChat = () => {
|
|
95
|
+
setChatData([]) // saveMainThread will auto save the empty array
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const pushNotification = (type, message) => {
|
|
99
|
+
setNotifications((prev) => [
|
|
100
|
+
...prev,
|
|
101
|
+
{ id: Date.now() + Math.random(), type, message, timestamp: Date.now() }
|
|
102
|
+
])
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const pushProcess = (process) => {
|
|
106
|
+
// process: { id, type, status, data }
|
|
107
|
+
setActiveProcesses((prev) => {
|
|
108
|
+
const existing = prev.findIndex((p) => p.id === process.id)
|
|
109
|
+
if (existing !== -1) {
|
|
110
|
+
// Update
|
|
111
|
+
const next = [...prev]
|
|
112
|
+
next[existing] = { ...next[existing], ...process }
|
|
113
|
+
return next
|
|
114
|
+
}
|
|
115
|
+
// Add new
|
|
116
|
+
return [...prev, process]
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const dismissProcess = (id) => {
|
|
121
|
+
setActiveProcesses((prev) => prev.filter((p) => p.id !== id))
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const handleStop = () => {
|
|
125
|
+
abortControllerRef.current?.abort()
|
|
126
|
+
if (window.api?.browserClose) {
|
|
127
|
+
window.api.browserClose()
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
chatData,
|
|
133
|
+
setChatData,
|
|
134
|
+
sessionId: sessionId.current,
|
|
135
|
+
config,
|
|
136
|
+
setConfig,
|
|
137
|
+
message,
|
|
138
|
+
setMessage,
|
|
139
|
+
isLoading,
|
|
140
|
+
setIsLoading,
|
|
141
|
+
isAgentBusy,
|
|
142
|
+
setIsAgentBusy,
|
|
143
|
+
runningSessionId,
|
|
144
|
+
setRunningSessionId,
|
|
145
|
+
runningSessionIds,
|
|
146
|
+
setRunningSessionIds,
|
|
147
|
+
addRunningSessionId,
|
|
148
|
+
removeRunningSessionId,
|
|
149
|
+
isSpeak,
|
|
150
|
+
setIsSpeak,
|
|
151
|
+
orbStatus,
|
|
152
|
+
setOrbStatus,
|
|
153
|
+
currentResponse,
|
|
154
|
+
setCurrentResponse,
|
|
155
|
+
notifications,
|
|
156
|
+
pushNotification,
|
|
157
|
+
activeProcesses,
|
|
158
|
+
setActiveProcesses,
|
|
159
|
+
pushProcess,
|
|
160
|
+
dismissProcess,
|
|
161
|
+
inputSource,
|
|
162
|
+
setInputSource,
|
|
163
|
+
activeTopic,
|
|
164
|
+
setActiveTopic,
|
|
165
|
+
currentActiveSessionId,
|
|
166
|
+
setCurrentActiveSessionId,
|
|
167
|
+
isChatLoaded,
|
|
168
|
+
isBooting,
|
|
169
|
+
setIsBooting,
|
|
170
|
+
abortControllerRef,
|
|
171
|
+
handleStop
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
import { getYoutubeSummary } from '../../api/ai/tools'
|
|
3
|
+
|
|
4
|
+
export const useMarkYoutube = (setChatData) => {
|
|
5
|
+
const handleYoutubeSearch = async (answer, signal, customSetChatData) => {
|
|
6
|
+
const targetSet = customSetChatData || setChatData
|
|
7
|
+
try {
|
|
8
|
+
const searchResults = await window.api.searchYoutube(answer.command.query)
|
|
9
|
+
targetSet((prev) => [
|
|
10
|
+
...prev.filter((item) => !item.isThinking),
|
|
11
|
+
{
|
|
12
|
+
role: 'ai',
|
|
13
|
+
content: answer.answer,
|
|
14
|
+
isYoutubeSearch: true,
|
|
15
|
+
youtubeLink: [...searchResults],
|
|
16
|
+
queryYoutube: answer.command.query
|
|
17
|
+
}
|
|
18
|
+
])
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error('Youtube Search Error:', error)
|
|
21
|
+
if (error.name === 'AbortError') {
|
|
22
|
+
targetSet((prev) => [...prev.filter((item) => !item.isThinking)])
|
|
23
|
+
targetSet((prev) => prev.slice(0, -1))
|
|
24
|
+
} else {
|
|
25
|
+
targetSet((prev) => [
|
|
26
|
+
...prev.filter((item) => !item.isThinking),
|
|
27
|
+
{
|
|
28
|
+
role: 'ai',
|
|
29
|
+
content: 'Gagal dapet info dari youtube nih, koneksi atau captcha mungkin bermasalah.'
|
|
30
|
+
}
|
|
31
|
+
])
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const getYoutubeData = async (url) => {
|
|
37
|
+
try {
|
|
38
|
+
const endpoint = `https://www.youtube.com/embed?url=${encodeURIComponent(url)}&format=json`
|
|
39
|
+
const response = await axios.get(endpoint)
|
|
40
|
+
const data = response.data
|
|
41
|
+
return {
|
|
42
|
+
judul: data.title,
|
|
43
|
+
author: data.author_name,
|
|
44
|
+
thumbnail: data.thumbnail_url,
|
|
45
|
+
success: true
|
|
46
|
+
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error('Gagal ambil data YouTube:', error.message)
|
|
49
|
+
return { judul: 'Video Tidak Ditemukan', author: '-', thumbnail: null, success: false }
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const handleYoutubeSummary = async (url, signal, customSetChatData) => {
|
|
54
|
+
const targetSet = customSetChatData || setChatData
|
|
55
|
+
targetSet((prev) => [...prev, { role: 'ai', content: 'Sedang menonton video youtube (hal ini akan membutuhkan waktu beberapa saat mohon ditunggu)...', isSummarizing: true, youtubeLink: url }])
|
|
56
|
+
try {
|
|
57
|
+
const data = await getYoutubeData(url)
|
|
58
|
+
const searchResults = await getYoutubeSummary(url, data, signal)
|
|
59
|
+
targetSet((prev) => [
|
|
60
|
+
...prev.filter((item) => !item.isSummarizing),
|
|
61
|
+
{ role: 'ai', content: searchResults, isYoutubeSummary: true, youtubeLink: url }
|
|
62
|
+
])
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error('Youtube Summary Error:', error)
|
|
65
|
+
if (error.name === 'AbortError') {
|
|
66
|
+
targetSet((prev) => [...prev.filter((item) => !item.isSummarizing)])
|
|
67
|
+
targetSet((prev) => prev.slice(0, -1))
|
|
68
|
+
} else {
|
|
69
|
+
targetSet((prev) => [
|
|
70
|
+
...prev.filter((item) => !item.isSummarizing),
|
|
71
|
+
{
|
|
72
|
+
role: 'ai',
|
|
73
|
+
content: 'Gagal dapet info dari youtube nih, koneksi atau captcha mungkin bermasalah.'
|
|
74
|
+
}
|
|
75
|
+
])
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
return { handleYoutubeSearch, handleYoutubeSummary, getYoutubeData }
|
|
82
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react'
|
|
2
|
+
import { getRelationship, saveRelationship, insertMemory, normalizeDbId } from '../../api/db'
|
|
3
|
+
import { evaluateTraitDrift } from '../../api/ai/relationship'
|
|
4
|
+
|
|
5
|
+
export const useRelationalGrowth = ({
|
|
6
|
+
chatData,
|
|
7
|
+
currentActiveSessionId = '1',
|
|
8
|
+
isLoading = false
|
|
9
|
+
}) => {
|
|
10
|
+
const lastEvalChatLenRef = useRef(0)
|
|
11
|
+
|
|
12
|
+
// --- RELATIONAL GROWTH EVALUATION (Event-Based) ---
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
// Evaluasi hubungan emosi HANYA dilakukan di sesi utama ('1') dan saat turn chat selesai (tidak sedang loading)
|
|
15
|
+
if (normalizeDbId(currentActiveSessionId) !== '1' || isLoading) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const evaluateGrowth = async () => {
|
|
20
|
+
try {
|
|
21
|
+
const allCleanChats = (chatData || []).filter(
|
|
22
|
+
(m) => !m.isThinking && !m.isSearching && !m.isSummarizing
|
|
23
|
+
)
|
|
24
|
+
const currentCleanLen = allCleanChats.length
|
|
25
|
+
if (currentCleanLen === 0) return
|
|
26
|
+
|
|
27
|
+
// Initialize state dari database saat pertama kali jalan
|
|
28
|
+
const oldTraits = await getRelationship('owner')
|
|
29
|
+
const dbLastIndex = oldTraits.lastChatIndex ?? oldTraits.last_chat_index ?? 0
|
|
30
|
+
|
|
31
|
+
if (lastEvalChatLenRef.current === 0) {
|
|
32
|
+
// Jika dbLastIndex belum diset (0) atau melebihi jumlah chat saat ini (karena prune/archive),
|
|
33
|
+
// set baseline awal ke currentCleanLen saat ini
|
|
34
|
+
if (dbLastIndex === 0 || dbLastIndex > currentCleanLen) {
|
|
35
|
+
lastEvalChatLenRef.current = currentCleanLen
|
|
36
|
+
await saveRelationship({
|
|
37
|
+
userId: 'owner',
|
|
38
|
+
...oldTraits,
|
|
39
|
+
lastChatIndex: currentCleanLen,
|
|
40
|
+
last_chat_index: currentCleanLen
|
|
41
|
+
})
|
|
42
|
+
} else {
|
|
43
|
+
lastEvalChatLenRef.current = dbLastIndex
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Jika chat pernah dibersihkan/dipangkas sehingga lebih kecil dari baseline sebelumnya
|
|
48
|
+
if (currentCleanLen < lastEvalChatLenRef.current) {
|
|
49
|
+
lastEvalChatLenRef.current = currentCleanLen
|
|
50
|
+
await saveRelationship({
|
|
51
|
+
userId: 'owner',
|
|
52
|
+
...oldTraits,
|
|
53
|
+
lastChatIndex: currentCleanLen,
|
|
54
|
+
last_chat_index: currentCleanLen
|
|
55
|
+
})
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Trigger evaluasi setiap selisih 15 pesan
|
|
60
|
+
if (currentCleanLen - lastEvalChatLenRef.current >= 15) {
|
|
61
|
+
console.log(
|
|
62
|
+
'[Relational Growth] Threshold 15 chat tercapai di sesi utama. Mengevaluasi mood...'
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
// Batasi maksimal 20 pesan terbaru dan batasi panjang teks per pesan
|
|
66
|
+
const startIndex = Math.max(lastEvalChatLenRef.current, currentCleanLen - 20)
|
|
67
|
+
const recentForEval = allCleanChats
|
|
68
|
+
.slice(startIndex)
|
|
69
|
+
.map((m) => {
|
|
70
|
+
let timeStr = ''
|
|
71
|
+
if (m.timestamp) {
|
|
72
|
+
timeStr =
|
|
73
|
+
typeof m.timestamp === 'number'
|
|
74
|
+
? `[${new Date(m.timestamp).toLocaleString('id-ID')}] `
|
|
75
|
+
: `[${m.timestamp}] `
|
|
76
|
+
}
|
|
77
|
+
const rawContent =
|
|
78
|
+
typeof m.content === 'string'
|
|
79
|
+
? m.content
|
|
80
|
+
: m.content
|
|
81
|
+
? JSON.stringify(m.content)
|
|
82
|
+
: ''
|
|
83
|
+
const safeContent =
|
|
84
|
+
rawContent.length > 500 ? `${rawContent.slice(0, 500)}... [dipotong]` : rawContent
|
|
85
|
+
return `${timeStr}${m.role === 'user' ? 'User' : 'Mark'}: ${safeContent}`
|
|
86
|
+
})
|
|
87
|
+
.join('\n')
|
|
88
|
+
|
|
89
|
+
// Simpan state panjang chat saat ini untuk evaluasi berikutnya
|
|
90
|
+
lastEvalChatLenRef.current = currentCleanLen
|
|
91
|
+
|
|
92
|
+
// Evaluasi AI
|
|
93
|
+
const newTraits = await evaluateTraitDrift(oldTraits, recentForEval, 'owner')
|
|
94
|
+
console.log('[Relational Growth] Trait shift:', newTraits)
|
|
95
|
+
|
|
96
|
+
// Simpan trait baru ke database
|
|
97
|
+
const updatedRecord = {
|
|
98
|
+
userId: 'owner',
|
|
99
|
+
...newTraits,
|
|
100
|
+
lastEvaluation: new Date().toISOString(),
|
|
101
|
+
evalCount: (oldTraits.evalCount || 0) + 1,
|
|
102
|
+
lastChatIndex: currentCleanLen,
|
|
103
|
+
last_chat_index: currentCleanLen
|
|
104
|
+
}
|
|
105
|
+
await saveRelationship(updatedRecord)
|
|
106
|
+
|
|
107
|
+
window.dispatchEvent(
|
|
108
|
+
new CustomEvent('relationship-updated', {
|
|
109
|
+
detail: updatedRecord
|
|
110
|
+
})
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
// Simpan relational memory jika AI merasa ada hal penting
|
|
114
|
+
if (newTraits.new_relational_memory) {
|
|
115
|
+
await insertMemory({
|
|
116
|
+
type: 'notes',
|
|
117
|
+
summary: '[Relational] Catatan hubungan otomatis',
|
|
118
|
+
memory: newTraits.new_relational_memory
|
|
119
|
+
})
|
|
120
|
+
console.log(
|
|
121
|
+
'[Relational Growth] Relational memory tersimpan:',
|
|
122
|
+
newTraits.new_relational_memory
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} catch (err) {
|
|
127
|
+
console.error('[Relational Growth] Gagal mengevaluasi hubungan:', err)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
evaluateGrowth()
|
|
132
|
+
}, [chatData, currentActiveSessionId, isLoading])
|
|
133
|
+
|
|
134
|
+
// Listener untuk evaluasi relasi berbasis event (misal dari Private Journal / akhir sesi)
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
const handleForceRelationalEval = async (e) => {
|
|
137
|
+
try {
|
|
138
|
+
const oldTraits = await getRelationship('owner')
|
|
139
|
+
const contextText =
|
|
140
|
+
e.detail?.summary || 'Sesi kerja panjang dan refleksi batin harian bersama pengguna.'
|
|
141
|
+
const newTraits = await evaluateTraitDrift(oldTraits, contextText, 'owner')
|
|
142
|
+
const updatedRecord = {
|
|
143
|
+
userId: 'owner',
|
|
144
|
+
...newTraits,
|
|
145
|
+
lastEvaluation: new Date().toISOString(),
|
|
146
|
+
evalCount: (oldTraits.evalCount || 0) + 1
|
|
147
|
+
}
|
|
148
|
+
await saveRelationship(updatedRecord)
|
|
149
|
+
window.dispatchEvent(
|
|
150
|
+
new CustomEvent('relationship-updated', {
|
|
151
|
+
detail: updatedRecord
|
|
152
|
+
})
|
|
153
|
+
)
|
|
154
|
+
if (newTraits.new_relational_memory) {
|
|
155
|
+
await insertMemory({
|
|
156
|
+
type: 'notes',
|
|
157
|
+
summary: '[Relational] Catatan hubungan otomatis',
|
|
158
|
+
memory: newTraits.new_relational_memory
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
} catch (err) {
|
|
162
|
+
console.warn('[Relational Growth] Gagal evaluasi relasi dari event:', err)
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
window.addEventListener('mark:evaluate-relationship', handleForceRelationalEval)
|
|
166
|
+
return () => window.removeEventListener('mark:evaluate-relationship', handleForceRelationalEval)
|
|
167
|
+
}, [])
|
|
168
|
+
|
|
169
|
+
// --- TACTILE INTERACTION DRIFT (Touch, Pet, Bonk) ---
|
|
170
|
+
useEffect(() => {
|
|
171
|
+
const handleTactile = async (e) => {
|
|
172
|
+
const type = e.detail?.type
|
|
173
|
+
if (!type) return
|
|
174
|
+
try {
|
|
175
|
+
const current = await getRelationship('owner')
|
|
176
|
+
let { warmth = 0.5, trust = 0.5, sarcasm_level = 0.5 } = current || {}
|
|
177
|
+
if (type === 'petting' || type === 'pet_purr') {
|
|
178
|
+
warmth = Math.min(1.0, warmth + 0.005)
|
|
179
|
+
trust = Math.min(1.0, trust + 0.005)
|
|
180
|
+
} else if (type === 'bonk_annoyed') {
|
|
181
|
+
sarcasm_level = Math.min(1.0, sarcasm_level + 0.005)
|
|
182
|
+
} else if (type === 'bonk_dizzy' || type === 'shield_block') {
|
|
183
|
+
sarcasm_level = Math.min(1.0, sarcasm_level + 0.01)
|
|
184
|
+
trust = Math.max(0.15, trust - 0.005)
|
|
185
|
+
}
|
|
186
|
+
const updatedRecord = {
|
|
187
|
+
...current,
|
|
188
|
+
userId: 'owner',
|
|
189
|
+
warmth,
|
|
190
|
+
trust,
|
|
191
|
+
sarcasm_level,
|
|
192
|
+
lastEvaluation: new Date().toISOString()
|
|
193
|
+
}
|
|
194
|
+
await saveRelationship(updatedRecord)
|
|
195
|
+
window.dispatchEvent(new CustomEvent('relationship-updated', { detail: updatedRecord }))
|
|
196
|
+
} catch (_) {}
|
|
197
|
+
}
|
|
198
|
+
window.addEventListener('mark-tactile-interaction', handleTactile)
|
|
199
|
+
return () => window.removeEventListener('mark-tactile-interaction', handleTactile)
|
|
200
|
+
}, [])
|
|
201
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react'
|
|
2
|
+
import { webApi } from '../../api/web-bridge'
|
|
3
|
+
|
|
4
|
+
export const useTelegramBot = () => {
|
|
5
|
+
const [status, setStatus] = useState('disconnected')
|
|
6
|
+
const [messages, setMessages] = useState([])
|
|
7
|
+
const [isThinking, setIsThinking] = useState(false)
|
|
8
|
+
const [currentSender, setCurrentSender] = useState('')
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
webApi.tgGetStatus().then((res) => {
|
|
12
|
+
if (res?.status) setStatus(res.status)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
webApi.tgGetHistory().then((history) => {
|
|
16
|
+
if (history && history.length > 0) {
|
|
17
|
+
setMessages(history)
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const unsubConn = webApi.onTgConnection((newStatus) => {
|
|
22
|
+
setStatus(newStatus)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const unsubThink = webApi.onTgThinking(({ sender }) => {
|
|
26
|
+
setIsThinking(true)
|
|
27
|
+
setCurrentSender(sender)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const unsubMsg = webApi.onTgMessage((data) => {
|
|
31
|
+
setMessages((prev) => [...prev, { type: 'incoming', ...data }])
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const unsubReply = webApi.onTgReplySent((data) => {
|
|
35
|
+
setMessages((prev) => [...prev, { type: 'outgoing', ...data }])
|
|
36
|
+
setIsThinking(false)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
return () => {
|
|
40
|
+
if (typeof unsubConn === 'function') unsubConn()
|
|
41
|
+
if (typeof unsubThink === 'function') unsubThink()
|
|
42
|
+
if (typeof unsubMsg === 'function') unsubMsg()
|
|
43
|
+
if (typeof unsubReply === 'function') unsubReply()
|
|
44
|
+
}
|
|
45
|
+
}, [])
|
|
46
|
+
|
|
47
|
+
const startBot = (token) => {
|
|
48
|
+
webApi.tgStart(token)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const stopBot = () => {
|
|
52
|
+
webApi.tgStop()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
status,
|
|
57
|
+
messages,
|
|
58
|
+
isThinking,
|
|
59
|
+
currentSender,
|
|
60
|
+
startBot,
|
|
61
|
+
stopBot
|
|
62
|
+
}
|
|
63
|
+
}
|