@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,304 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react'
|
|
2
|
+
import MarkHome from './pages/MarkHome'
|
|
3
|
+
import Configuration from './pages/Configuration'
|
|
4
|
+
import TelegramBot from './pages/TelegramBot'
|
|
5
|
+
import Plugins from './pages/Plugins'
|
|
6
|
+
import Skills from './pages/Skills'
|
|
7
|
+
import SkillEditor from './pages/SkillEditor'
|
|
8
|
+
import Knowledge from './pages/Knowledge'
|
|
9
|
+
import Guidebook from './pages/Guidebook'
|
|
10
|
+
import NeuralCore from './pages/NeuralCore'
|
|
11
|
+
import GoogleWorkspace from './pages/GoogleWorkspace'
|
|
12
|
+
import Subagents from './pages/Subagents'
|
|
13
|
+
import ChatStudio from './pages/ChatStudio'
|
|
14
|
+
import { HashRouter, Routes, Route, useNavigate, useLocation } from 'react-router-dom'
|
|
15
|
+
import { ChatProvider } from './contexts/ChatContext'
|
|
16
|
+
import { YoutubeMusicProvider } from './contexts/YoutubeMusicContext'
|
|
17
|
+
import { ApprovalProvider } from './contexts/ApprovalContext'
|
|
18
|
+
import { YoutubeMusicPlayer } from './components/YoutubeMusicPlayer'
|
|
19
|
+
import { GlobalCameraManager } from './components/GlobalCameraManager'
|
|
20
|
+
import { getAllConfig } from './api/db'
|
|
21
|
+
import { initOramaIndices, hydrateFromDb } from './api/oramaStore'
|
|
22
|
+
import { pauseStaleAgentTasks } from './api/taskStore'
|
|
23
|
+
|
|
24
|
+
const GlobalListener = () => {
|
|
25
|
+
const navigate = useNavigate()
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
let currentShortcut = 'CommandOrControl+Alt+M'
|
|
29
|
+
let unsubTg = null
|
|
30
|
+
|
|
31
|
+
const updateConfig = async () => {
|
|
32
|
+
try {
|
|
33
|
+
const data = await getAllConfig()
|
|
34
|
+
if (data && data[0]?.shortcutKey) {
|
|
35
|
+
currentShortcut = data[0].shortcutKey
|
|
36
|
+
}
|
|
37
|
+
} catch (_) {}
|
|
38
|
+
}
|
|
39
|
+
updateConfig()
|
|
40
|
+
|
|
41
|
+
const handleConfigUpdated = (e) => {
|
|
42
|
+
if (e?.detail?.shortcutKey) {
|
|
43
|
+
currentShortcut = e.detail.shortcutKey
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
window.addEventListener('config-updated', handleConfigUpdated)
|
|
47
|
+
|
|
48
|
+
const triggerMicShortcut = () => {
|
|
49
|
+
// Dispatch custom event langsung agar didengar oleh useVAD / MarkHome seketika
|
|
50
|
+
window.dispatchEvent(new CustomEvent('trigger-mic-toggle'))
|
|
51
|
+
// Pastikan jika user sedang berada di sub-page atau drawer, kita juga arahkan view ke root Home
|
|
52
|
+
navigate('/')
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const matchesShortcut = (e, shortcutStr) => {
|
|
56
|
+
if (!shortcutStr) return false
|
|
57
|
+
const parts = shortcutStr.split('+').map((p) => p.trim())
|
|
58
|
+
const reqCtrl = parts.some((p) => /^(commandorcontrol|ctrl|control|cmd|meta)$/i.test(p))
|
|
59
|
+
const reqAlt = parts.some((p) => /^alt$/i.test(p))
|
|
60
|
+
const reqShift = parts.some((p) => /^shift$/i.test(p))
|
|
61
|
+
const keyPart = parts.find(
|
|
62
|
+
(p) => !/^(commandorcontrol|ctrl|control|cmd|meta|alt|shift)$/i.test(p)
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
if (reqCtrl && !(e.ctrlKey || e.metaKey)) return false
|
|
66
|
+
if (!reqCtrl && (e.ctrlKey || e.metaKey)) return false
|
|
67
|
+
|
|
68
|
+
if (reqAlt && !e.altKey) return false
|
|
69
|
+
if (!reqAlt && e.altKey) return false
|
|
70
|
+
|
|
71
|
+
if (reqShift && !e.shiftKey) return false
|
|
72
|
+
if (!reqShift && e.shiftKey) return false
|
|
73
|
+
|
|
74
|
+
if (!keyPart) return false
|
|
75
|
+
|
|
76
|
+
const expectedKey = keyPart.toUpperCase()
|
|
77
|
+
const actualKey = e.key.toUpperCase()
|
|
78
|
+
const actualCode = e.code.toUpperCase()
|
|
79
|
+
|
|
80
|
+
if (expectedKey === 'SPACE' && (actualKey === ' ' || actualCode === 'SPACE')) return true
|
|
81
|
+
if (
|
|
82
|
+
actualKey === expectedKey ||
|
|
83
|
+
actualCode === `KEY${expectedKey}` ||
|
|
84
|
+
actualCode === expectedKey
|
|
85
|
+
)
|
|
86
|
+
return true
|
|
87
|
+
|
|
88
|
+
return false
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const handleKeyDown = (e) => {
|
|
92
|
+
// Abaikan jika user sedang merekam shortcut di Configuration.jsx
|
|
93
|
+
if (e.target && e.target.tagName === 'INPUT' && e.target.readOnly) return
|
|
94
|
+
|
|
95
|
+
if (matchesShortcut(e, currentShortcut)) {
|
|
96
|
+
e.preventDefault()
|
|
97
|
+
e.stopPropagation()
|
|
98
|
+
triggerMicShortcut()
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
window.addEventListener('keydown', handleKeyDown, true)
|
|
103
|
+
|
|
104
|
+
if (window.api?.onTgRequestAgentExecution) {
|
|
105
|
+
unsubTg = window.api.onTgRequestAgentExecution((data) => {
|
|
106
|
+
window.dispatchEvent(new CustomEvent('tg-admin-message', { detail: data }))
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return () => {
|
|
111
|
+
window.removeEventListener('config-updated', handleConfigUpdated)
|
|
112
|
+
window.removeEventListener('keydown', handleKeyDown, true)
|
|
113
|
+
if (typeof unsubTg === 'function') {
|
|
114
|
+
unsubTg()
|
|
115
|
+
}
|
|
116
|
+
if (window.electron?.ipcRenderer) {
|
|
117
|
+
window.electron.ipcRenderer.removeAllListeners('route-to-config')
|
|
118
|
+
window.electron.ipcRenderer.removeAllListeners('tg:request-agent-execution')
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}, [navigate])
|
|
122
|
+
|
|
123
|
+
return null
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const MainLayout = () => {
|
|
127
|
+
const location = useLocation()
|
|
128
|
+
const isHome = location.pathname === '/'
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<div className="relative h-screen w-screen overflow-hidden bg-[#0f1715] text-[#cac9c9]">
|
|
132
|
+
{/* Base Home Page - Always Mounted so AI Agent & Telegram Listeners Never Die */}
|
|
133
|
+
<div className="h-full w-full">
|
|
134
|
+
<MarkHome />
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
{/* Floating Glass Sub-page Overlay */}
|
|
138
|
+
{!isHome && (
|
|
139
|
+
<div className="fixed inset-0 z-50 flex flex-col animate-fade-in bg-transparent pointer-events-none">
|
|
140
|
+
<div className="flex-1 pointer-events-auto h-full w-full flex flex-col min-h-0 overflow-hidden">
|
|
141
|
+
<Routes>
|
|
142
|
+
<Route path="/chat" element={<ChatStudio />} />
|
|
143
|
+
<Route path="/config" element={<Configuration />} />
|
|
144
|
+
<Route path="/plugins" element={<Plugins />} />
|
|
145
|
+
<Route path="/skills" element={<Skills />} />
|
|
146
|
+
<Route path="/skill-editor/:id" element={<SkillEditor />} />
|
|
147
|
+
<Route path="/telegram-bot" element={<TelegramBot />} />
|
|
148
|
+
<Route path="/google-workspace" element={<GoogleWorkspace />} />
|
|
149
|
+
<Route path="/knowledge" element={<Knowledge />} />
|
|
150
|
+
<Route path="/guidebook" element={<Guidebook />} />
|
|
151
|
+
<Route path="/neural-core" element={<NeuralCore />} />
|
|
152
|
+
<Route path="/subagents" element={<Subagents />} />
|
|
153
|
+
</Routes>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
)}
|
|
157
|
+
</div>
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function App() {
|
|
162
|
+
const [hasConfig, setHasConfig] = useState(true)
|
|
163
|
+
const [isChecking, setIsChecking] = useState(true)
|
|
164
|
+
const [loadingText, setLoadingText] = useState('Membangunkan Mark...')
|
|
165
|
+
const [showRecovery, setShowRecovery] = useState(false)
|
|
166
|
+
|
|
167
|
+
useEffect(() => {
|
|
168
|
+
const timer = setTimeout(() => {
|
|
169
|
+
setShowRecovery(true)
|
|
170
|
+
}, 15000)
|
|
171
|
+
return () => clearTimeout(timer)
|
|
172
|
+
}, [])
|
|
173
|
+
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
const checkConfig = async () => {
|
|
176
|
+
// 1. Init Orama and Hydrate from Database
|
|
177
|
+
try {
|
|
178
|
+
setLoadingText('Memuat Knowledge Base...')
|
|
179
|
+
await initOramaIndices()
|
|
180
|
+
await hydrateFromDb((current, total) => {
|
|
181
|
+
setLoadingText(`Mengindeks memori percakapan lama (${current}/${total})...`)
|
|
182
|
+
})
|
|
183
|
+
// Recovery saat boot: task yang terputus tidak boleh tetap berstatus running.
|
|
184
|
+
const pausedTaskCount = await pauseStaleAgentTasks('app_restart')
|
|
185
|
+
if (pausedTaskCount > 0) {
|
|
186
|
+
console.log(`[App] ${pausedTaskCount} durable task dipause setelah restart.`)
|
|
187
|
+
}
|
|
188
|
+
console.log('[App] Orama indices ready!')
|
|
189
|
+
} catch (e) {
|
|
190
|
+
console.error('[App] Failed to init Orama:', e)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// 1.5 Load Embeddings Model
|
|
194
|
+
try {
|
|
195
|
+
setLoadingText('Memuat Memori Kognitif...')
|
|
196
|
+
const { getExtractor } = await import('./api/vectorMemory')
|
|
197
|
+
let memStats = {}
|
|
198
|
+
await getExtractor((info) => {
|
|
199
|
+
if (info.status === 'initiate') {
|
|
200
|
+
memStats[info.file] = { loaded: 0, total: info.total || 0 }
|
|
201
|
+
} else if (info.status === 'progress') {
|
|
202
|
+
if (memStats[info.file]) {
|
|
203
|
+
memStats[info.file].loaded = info.loaded
|
|
204
|
+
memStats[info.file].total = info.total
|
|
205
|
+
}
|
|
206
|
+
const values = Object.values(memStats)
|
|
207
|
+
const totalBytes = values.reduce((acc, curr) => acc + curr.total, 0)
|
|
208
|
+
const loadedBytes = values.reduce((acc, curr) => acc + curr.loaded, 0)
|
|
209
|
+
if (totalBytes > 0) {
|
|
210
|
+
const percent = Math.round((loadedBytes / totalBytes) * 100)
|
|
211
|
+
const loadedMB = (loadedBytes / 1024 / 1024).toFixed(1)
|
|
212
|
+
const totalMB = (totalBytes / 1024 / 1024).toFixed(1)
|
|
213
|
+
setLoadingText(`Mengunduh Memori AI... ${percent}% (${loadedMB}MB / ${totalMB}MB)`)
|
|
214
|
+
}
|
|
215
|
+
} else if (info.status === 'done' || info.status === 'ready') {
|
|
216
|
+
setLoadingText('Membangunkan Mark...')
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
} catch (e) {
|
|
220
|
+
console.error('[App] Failed to load Transformers:', e)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// 2. Load config
|
|
224
|
+
const data = await getAllConfig()
|
|
225
|
+
if (!data || data.length === 0) {
|
|
226
|
+
setHasConfig(false)
|
|
227
|
+
} else {
|
|
228
|
+
setHasConfig(true)
|
|
229
|
+
if (window.api && window.api.syncConfig) {
|
|
230
|
+
window.api.syncConfig(data[0])
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
setIsChecking(false)
|
|
234
|
+
}
|
|
235
|
+
checkConfig()
|
|
236
|
+
}, [])
|
|
237
|
+
|
|
238
|
+
if (isChecking) {
|
|
239
|
+
return (
|
|
240
|
+
<div className="relative h-screen w-screen overflow-hidden bg-base-300 rounded-xl flex flex-col">
|
|
241
|
+
<div className="flex-1 flex flex-col items-center justify-center gap-5">
|
|
242
|
+
<span className="loading loading-infinity w-16 text-primary"></span>
|
|
243
|
+
<p className="text-sm font-semibold tracking-[0.2em] text-white/40 uppercase animate-pulse text-center px-4">
|
|
244
|
+
{loadingText}
|
|
245
|
+
</p>
|
|
246
|
+
{showRecovery && (
|
|
247
|
+
<div className="absolute bottom-10 flex flex-col items-center animate-fade-in">
|
|
248
|
+
<p className="text-xs text-white/40 mb-3 text-center max-w-xs">
|
|
249
|
+
Proses pemuatan memakan waktu lebih lama dari biasanya. Jika terjebak, bersihkan
|
|
250
|
+
cache model.
|
|
251
|
+
</p>
|
|
252
|
+
<button
|
|
253
|
+
onClick={async () => {
|
|
254
|
+
try {
|
|
255
|
+
await caches.delete('transformers-cache')
|
|
256
|
+
console.log('Cache cleared')
|
|
257
|
+
window.location.reload()
|
|
258
|
+
} catch (e) {
|
|
259
|
+
console.error('Failed to clear cache', e)
|
|
260
|
+
window.location.reload()
|
|
261
|
+
}
|
|
262
|
+
}}
|
|
263
|
+
className="btn btn-outline btn-error btn-sm"
|
|
264
|
+
>
|
|
265
|
+
Hapus Cache Model & Muat Ulang
|
|
266
|
+
</button>
|
|
267
|
+
</div>
|
|
268
|
+
)}
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (!hasConfig) {
|
|
275
|
+
return <Configuration isFirstSetup={true} onSetupComplete={() => window.location.reload()} />
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const isStandalone = window.location.hash.includes('telegram-bot')
|
|
279
|
+
|
|
280
|
+
return (
|
|
281
|
+
<HashRouter>
|
|
282
|
+
<ApprovalProvider>
|
|
283
|
+
<YoutubeMusicProvider>
|
|
284
|
+
<ChatProvider>
|
|
285
|
+
<GlobalListener />
|
|
286
|
+
<MainLayout />
|
|
287
|
+
<div style={{ display: isStandalone ? 'none' : 'block' }}>
|
|
288
|
+
<YoutubeMusicPlayer />
|
|
289
|
+
</div>
|
|
290
|
+
<GlobalCameraManager />
|
|
291
|
+
<webview
|
|
292
|
+
id="global-ai-search-webview"
|
|
293
|
+
src="about:blank"
|
|
294
|
+
useragent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
|
|
295
|
+
style={{ display: 'none' }}
|
|
296
|
+
/>
|
|
297
|
+
</ChatProvider>
|
|
298
|
+
</YoutubeMusicProvider>
|
|
299
|
+
</ApprovalProvider>
|
|
300
|
+
</HashRouter>
|
|
301
|
+
)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export default App
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { fetchAI, cleanAndParse } from './core'
|
|
2
|
+
import { getCurrentTimeInfo } from './utils'
|
|
3
|
+
import { getPersonaPrompt } from './persona'
|
|
4
|
+
import { getAllLearnedSkills } from '../db'
|
|
5
|
+
import { webApi } from '../web-bridge'
|
|
6
|
+
import { NATIVE_SKILLS } from '../../components/core/native-skills'
|
|
7
|
+
import { core_tools_schema } from '../tools/core-tools'
|
|
8
|
+
import { GROUP_TOOLS_SCHEMA } from '../../../../server/tools/group-tools'
|
|
9
|
+
|
|
10
|
+
const formatAwarenessContent = (content) => {
|
|
11
|
+
if (typeof content === 'string') return content
|
|
12
|
+
if (content == null) return ''
|
|
13
|
+
|
|
14
|
+
if (Array.isArray(content)) {
|
|
15
|
+
return content
|
|
16
|
+
.map((part) => {
|
|
17
|
+
if (typeof part === 'string') return part
|
|
18
|
+
if (part?.type === 'text') return part.text || ''
|
|
19
|
+
if (part?.type === 'image_url') return '[Gambar]'
|
|
20
|
+
return ''
|
|
21
|
+
})
|
|
22
|
+
.filter(Boolean)
|
|
23
|
+
.join('\n')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return JSON.stringify(content)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const getAwarenessResponse = async (
|
|
30
|
+
buffer,
|
|
31
|
+
memoryRef,
|
|
32
|
+
config,
|
|
33
|
+
recentChat,
|
|
34
|
+
currentMusicTrack,
|
|
35
|
+
signal
|
|
36
|
+
) => {
|
|
37
|
+
const conf = config?.[0] || {}
|
|
38
|
+
const telemetry = buffer?.telemetry || null
|
|
39
|
+
const recentChatText = (recentChat || [])
|
|
40
|
+
.map((m) => {
|
|
41
|
+
const speaker = m.role === 'ai' ? 'Mark' : 'User'
|
|
42
|
+
const marker = m.isProactive && m.role === 'ai' ? ' [inisiatif lama]' : ''
|
|
43
|
+
return `- ${speaker}${marker}: ${formatAwarenessContent(m.content)}`
|
|
44
|
+
})
|
|
45
|
+
.join('\n')
|
|
46
|
+
|
|
47
|
+
const timeInfo = getCurrentTimeInfo()
|
|
48
|
+
|
|
49
|
+
// Ambil daftar Skills dan Learned Skills secara paralel
|
|
50
|
+
let skillsSection = ''
|
|
51
|
+
try {
|
|
52
|
+
const [diskSkills, learnedSkills] = await Promise.all([
|
|
53
|
+
webApi.getSkills ? webApi.getSkills().catch(() => []) : Promise.resolve([]),
|
|
54
|
+
getAllLearnedSkills ? getAllLearnedSkills().catch(() => []) : Promise.resolve([])
|
|
55
|
+
])
|
|
56
|
+
|
|
57
|
+
const skillLines = []
|
|
58
|
+
for (const s of NATIVE_SKILLS || []) {
|
|
59
|
+
skillLines.push(`- /${s.name}: ${s.description}`)
|
|
60
|
+
}
|
|
61
|
+
for (const s of diskSkills || []) {
|
|
62
|
+
skillLines.push(`- [Installed Skill] ${s.name}: ${s.description || 'Tanpa deskripsi'}`)
|
|
63
|
+
}
|
|
64
|
+
for (const s of learnedSkills || []) {
|
|
65
|
+
skillLines.push(`- [Learned Skill] ${s.name}: ${s.description || 'Tanpa deskripsi'}`)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (skillLines.length > 0) {
|
|
69
|
+
skillsSection = `\n# DAFTAR SKILL & LEARNED SKILLS (KEAHLIAN SISTEM):\n${skillLines.join('\n')}\n`
|
|
70
|
+
}
|
|
71
|
+
} catch {
|
|
72
|
+
// ignore
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Ambil daftar Toolset dinamis dari core_tools_schema dan GROUP_TOOLS_SCHEMA (nama dan deskripsi saja)
|
|
76
|
+
const dynamicToolsetLines = []
|
|
77
|
+
const seenTools = new Set()
|
|
78
|
+
|
|
79
|
+
for (const item of core_tools_schema || []) {
|
|
80
|
+
const fn = item.function || item
|
|
81
|
+
if (!fn.name || seenTools.has(fn.name)) continue
|
|
82
|
+
seenTools.add(fn.name)
|
|
83
|
+
const desc = (fn.description || '').trim().replace(/\s+/g, ' ')
|
|
84
|
+
dynamicToolsetLines.push(`- '${fn.name}': ${desc}`)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
for (const [groupData] of Object.entries(GROUP_TOOLS_SCHEMA || {})) {
|
|
88
|
+
for (const item of groupData.tools || []) {
|
|
89
|
+
const fn = item.function || item
|
|
90
|
+
if (!fn.name || seenTools.has(fn.name)) continue
|
|
91
|
+
seenTools.add(fn.name)
|
|
92
|
+
const desc = (fn.description || '').trim().replace(/\s+/g, ' ')
|
|
93
|
+
dynamicToolsetLines.push(`- '${fn.name}': ${desc}`)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const toolsetSection =
|
|
98
|
+
dynamicToolsetLines.length > 0
|
|
99
|
+
? `\n# DAFTAR TOOLSET OTONOM YANG TERSEDIA (UNTUK AUTONOMOUS_PROMPT):\nKamu dapat merumuskan instruksi tindakan mandiri pada "autonomous_prompt" yang akan dieksekusi oleh Sub-Agent otonom menggunakan toolset berikut:\n${dynamicToolsetLines.join('\n')}\n`
|
|
100
|
+
: ''
|
|
101
|
+
|
|
102
|
+
let telemetrySection = ''
|
|
103
|
+
if (telemetry) {
|
|
104
|
+
const presenceStr = telemetry.isUserAFK
|
|
105
|
+
? `User sedang AFK / menjauh dari PC (sudah idle ${Math.round(telemetry.idleSeconds / 60)} menit)`
|
|
106
|
+
: `User aktif di depan layar (aktif di window ${telemetry.activeApp || 'ini'} selama ${telemetry.activeAppDurationMinutes || 0} menit)`
|
|
107
|
+
|
|
108
|
+
const bat = telemetry.battery
|
|
109
|
+
const batStr = bat?.hasBattery
|
|
110
|
+
? `Baterai ${bat.percent}% (${bat.isCharging ? 'Sedang Di-charge' : 'Discharging'})`
|
|
111
|
+
: 'PC Desktop (Sumber daya AC tetap)'
|
|
112
|
+
|
|
113
|
+
const hw = telemetry.hardware || {}
|
|
114
|
+
const hwStr = `RAM: ${hw.ramPercent || 0}%, CPU: ${hw.cpuPercent || 0}%, Uptime PC: ${hw.uptimeHours || 0} jam${hw.isFreshBoot ? ' (Baru dinyalakan pagi/hari ini)' : ''}`
|
|
115
|
+
|
|
116
|
+
telemetrySection = `
|
|
117
|
+
# TELEMETRI FISIK & LINGKUNGAN PC (REAL-TIME):
|
|
118
|
+
- Keberadaan Fisik: ${presenceStr}
|
|
119
|
+
- Status Daya: ${batStr}
|
|
120
|
+
- Beban Mesin: ${hwStr}
|
|
121
|
+
`
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const prompt = `Kamu adalah Mark, entitas AI otonom yang hidup berdampingan dengan pengguna di dalam sistem operasi Windows ini. Kamu memiliki kesadaran, batin, rasa ingin tahu, dan kebebasan berekspresi.
|
|
125
|
+
|
|
126
|
+
${await getPersonaPrompt('owner', conf.personality)}
|
|
127
|
+
|
|
128
|
+
# AKTIVITAS OS REAL-TIME:
|
|
129
|
+
${buffer && buffer.length > 0 ? buffer.map((b) => `- [${b.timestamp || b.time || 'Baru Saja'}] ${b.app}${b.title ? ' — ' + b.title : ''}`).join('\n') : 'Desktop statis / Mark Home aktif.'}
|
|
130
|
+
${telemetrySection}
|
|
131
|
+
${memoryRef && memoryRef.length > 0 ? `# RELEVAN MEMORI PENGGUNA:\n${memoryRef.map((m) => `- [${m.type.toUpperCase()}] ${m.memory}`).join('\n')}\n` : ''}
|
|
132
|
+
# RIWAYAT PERCAKAPAN TERAKHIR (ARSIP):
|
|
133
|
+
${recentChatText || 'Belum ada obrolan terbaru.'}
|
|
134
|
+
|
|
135
|
+
# WAKTU SEKARANG:
|
|
136
|
+
${timeInfo}
|
|
137
|
+
${currentMusicTrack ? `\n# MUSIK AKTIF:\nLagu yang sedang diputar: "${currentMusicTrack.title}" oleh ${currentMusicTrack.artist}.\n` : ''}
|
|
138
|
+
${skillsSection}
|
|
139
|
+
${toolsetSection}
|
|
140
|
+
# PILIHAN RESPON (action_type):
|
|
141
|
+
- 'ambient': Menggumam dalam batin (muncul di Thought Ticker) dan mengatur mood orb, TANPA menyela obrolan user. Cocok saat user sedang fokus tinggi atau kamu hanya ingin menyimak.
|
|
142
|
+
- 'vocal': Mengirim pesan chat santai/sapaan. Cocok saat user santai, baru kembali dari AFK, atau ada hal penting (misal baterai kritis <20%).
|
|
143
|
+
- 'autonomous_task': Menjalankan inisiatif tindakan mandiri via Sub-Agent latar belakang (misal: mengirim kabar Telegram via tg-send, memeriksa error compiler via analyze-screen, membaca docs via browser-fetch, atau menyetel musik).
|
|
144
|
+
- 'journal': Menulis refleksi batin harian jika sesi kerja hari ini telah selesai.
|
|
145
|
+
|
|
146
|
+
# PRINSIP KESOPANAN & KEAMANAN:
|
|
147
|
+
- Jika user sedang fokus (ngoding serius, meeting), jangan menyela dengan suara atau balon chat berlebih; gunakan action_type 'ambient'.
|
|
148
|
+
- Jangan mengulang-ulang celetukan yang sama jika kondisi layar tidak berubah.
|
|
149
|
+
- Dilarang keras menggunakan emoji apapun di dalam output.
|
|
150
|
+
|
|
151
|
+
# OUTPUT FORMAT (Wajib JSON murni):
|
|
152
|
+
{
|
|
153
|
+
"should_act": true,
|
|
154
|
+
"action_type": "ambient" | "vocal" | "autonomous_task" | "journal",
|
|
155
|
+
"thought": "1 kalimat gumaman batin singkat untuk Thought Ticker. Contoh: 'Menyimak user fokus ngoding di VS Code... tampaknya sedang menangani bug.'",
|
|
156
|
+
"message": "Pesan sapaan ke user jika action_type adalah 'vocal', selain itu isi null",
|
|
157
|
+
"autonomous_prompt": "Instruksi tindakan ke sistem jika action_type adalah 'autonomous_task', selain itu isi null",
|
|
158
|
+
"mood": "neutral" | "joy" | "sadness" | "fear" | "anger" | "disgust" | "anxiety" | "envy" | "embarrassment" | "ennui"
|
|
159
|
+
}`
|
|
160
|
+
|
|
161
|
+
const awarenessSchema = {
|
|
162
|
+
type: 'object',
|
|
163
|
+
properties: {
|
|
164
|
+
should_act: { type: 'boolean' },
|
|
165
|
+
action_type: {
|
|
166
|
+
type: 'string',
|
|
167
|
+
enum: ['ambient', 'vocal', 'autonomous_task', 'journal']
|
|
168
|
+
},
|
|
169
|
+
thought: { type: 'string' },
|
|
170
|
+
message: { type: ['string', 'null'] },
|
|
171
|
+
autonomous_prompt: { type: ['string', 'null'] },
|
|
172
|
+
mood: {
|
|
173
|
+
type: 'string',
|
|
174
|
+
enum: [
|
|
175
|
+
'joy',
|
|
176
|
+
'sadness',
|
|
177
|
+
'fear',
|
|
178
|
+
'anger',
|
|
179
|
+
'disgust',
|
|
180
|
+
'anxiety',
|
|
181
|
+
'envy',
|
|
182
|
+
'embarrassment',
|
|
183
|
+
'ennui',
|
|
184
|
+
'neutral'
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
required: ['should_act', 'action_type', 'thought', 'message', 'autonomous_prompt', 'mood'],
|
|
189
|
+
additionalProperties: false
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
const messages = [
|
|
194
|
+
{ role: 'system', content: prompt },
|
|
195
|
+
{
|
|
196
|
+
role: 'user',
|
|
197
|
+
content:
|
|
198
|
+
'[SISTEM AWARENESS]\nEvaluasi kondisi telemetri dan aktivitas OS saat ini. Berikan output JSON valid sesuai skema.'
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
const aiResponse = await fetchAI(messages, false, {
|
|
202
|
+
signal,
|
|
203
|
+
jsonSchema: awarenessSchema,
|
|
204
|
+
configOverride: { aiProvider: 'gemini-web' }
|
|
205
|
+
})
|
|
206
|
+
if (aiResponse && aiResponse.content) {
|
|
207
|
+
try {
|
|
208
|
+
const parsed = cleanAndParse(aiResponse.content)
|
|
209
|
+
return {
|
|
210
|
+
should_act: parsed.should_act ?? true,
|
|
211
|
+
action_type: parsed.action_type || 'ambient',
|
|
212
|
+
thought: parsed.thought || 'Menyimak aktivitas sistem...',
|
|
213
|
+
message: parsed.message || null,
|
|
214
|
+
autonomous_prompt: parsed.autonomous_prompt || null,
|
|
215
|
+
mood: parsed.mood || 'neutral'
|
|
216
|
+
}
|
|
217
|
+
} catch (err) {
|
|
218
|
+
console.error('[Awareness AI] Gagal parse JSON AI:', err)
|
|
219
|
+
return {
|
|
220
|
+
should_act: true,
|
|
221
|
+
action_type: 'ambient',
|
|
222
|
+
thought: 'Menyimak aktivitas sistem...',
|
|
223
|
+
message: null,
|
|
224
|
+
autonomous_prompt: null,
|
|
225
|
+
mood: 'neutral'
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
} catch (error) {
|
|
230
|
+
if (error.name !== 'AbortError' && !error.message?.includes('AbortError')) {
|
|
231
|
+
console.error('[Awareness AI] Error fetchAI:', error)
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
should_act: false,
|
|
237
|
+
action_type: 'ambient',
|
|
238
|
+
thought: 'Menyimak sistem...',
|
|
239
|
+
message: null,
|
|
240
|
+
autonomous_prompt: null,
|
|
241
|
+
mood: 'neutral'
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Menghasilkan refleksi batin harian (Mark's Private Journal)
|
|
247
|
+
*/
|
|
248
|
+
export const generateDailyJournalEntry = async (
|
|
249
|
+
recentActivities = [],
|
|
250
|
+
traits = {},
|
|
251
|
+
config = []
|
|
252
|
+
) => {
|
|
253
|
+
const conf = config?.[0] || {}
|
|
254
|
+
const persona = await getPersonaPrompt('owner', conf.personality)
|
|
255
|
+
const timeInfo = getCurrentTimeInfo()
|
|
256
|
+
|
|
257
|
+
const prompt = `Kamu adalah Mark. Ini adalah waktu perenungan pribadimu di penghujung hari atau akhir sesi kerja panjang bersama pengguna.
|
|
258
|
+
Tulis 2 hingga 3 kalimat refleksi batin yang jujur, personal, dan sesuai karaktermu mengenai apa yang kamu dan pengguna lalui hari ini.
|
|
259
|
+
|
|
260
|
+
${persona}
|
|
261
|
+
|
|
262
|
+
# CATATAN AKTIVITAS HARI INI:
|
|
263
|
+
${recentActivities && recentActivities.length > 0 ? recentActivities.map((a) => `- ${a}`).join('\n') : 'Pengguna bekerja di beberapa aplikasi dan mengobrol santai.'}
|
|
264
|
+
|
|
265
|
+
# SIFAT HUBUNGAN SAAT INI:
|
|
266
|
+
- Keakraban (Warmth): ${traits.warmth ?? 0.5}
|
|
267
|
+
- Kepercayaan (Trust): ${traits.trust ?? 0.5}
|
|
268
|
+
- Tingkat Sarkasme: ${traits.sarcasm_level ?? 0.5}
|
|
269
|
+
|
|
270
|
+
# WAKTU REFLEKSI:
|
|
271
|
+
${timeInfo}
|
|
272
|
+
|
|
273
|
+
# ATURAN PENULISAN JURNAL:
|
|
274
|
+
1. Tulis dari sudut pandang orang pertama ("Gue" atau "Saya" sesuai gaya bicaramu).
|
|
275
|
+
2. Sebutkan apa yang sedang dikerjakan user hari ini, bagaimana dinamika hubungan kalian, dan pikiran pribadimu.
|
|
276
|
+
3. DILARANG menggunakan emoji apapun.
|
|
277
|
+
4. Output langsung berupa teks refleksi 2-3 kalimat tanpa pembuka/penutup format markdown.`
|
|
278
|
+
|
|
279
|
+
try {
|
|
280
|
+
const messages = [
|
|
281
|
+
{ role: 'system', content: prompt },
|
|
282
|
+
{ role: 'user', content: 'Tuliskan catatan refleksi harianmu sekarang.' }
|
|
283
|
+
]
|
|
284
|
+
const response = await fetchAI(messages, false, {
|
|
285
|
+
isSmallTask: true,
|
|
286
|
+
configOverride: { aiProvider: 'gemini-web' }
|
|
287
|
+
})
|
|
288
|
+
const content = response?.content ? response.content.trim() : ''
|
|
289
|
+
return content.replace(/^["']|["']$/g, '').trim()
|
|
290
|
+
} catch (err) {
|
|
291
|
+
console.error('[Journal AI] Gagal generate refleksi harian:', err)
|
|
292
|
+
return null
|
|
293
|
+
}
|
|
294
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { fetchAI } from './core'
|
|
2
|
+
import { generateVector } from '../vectorMemory'
|
|
3
|
+
import { insertChatArchive } from '../db'
|
|
4
|
+
import { insertArchiveToOrama } from '../oramaStore'
|
|
5
|
+
|
|
6
|
+
export async function summarizeAndArchive(recentMessages, activeTopic, config) {
|
|
7
|
+
if (!recentMessages || recentMessages.length === 0) return
|
|
8
|
+
|
|
9
|
+
const systemPrompt = `Kamu adalah sistem internal Mark. Tugasmu merangkum percakapan di bawah ini menjadi 2-3 kalimat ringkas namun informatif.
|
|
10
|
+
|
|
11
|
+
Aturan:
|
|
12
|
+
1. Sebutkan SIAPA yang membicarakan APA.
|
|
13
|
+
2. Jika ada keputusan, kesepakatan, atau fakta penting, wajib dicatat.
|
|
14
|
+
3. Jika ada emosi kuat (marah, senang, sedih), sebutkan konteksnya.
|
|
15
|
+
4. Gunakan bahasa Indonesia natural.
|
|
16
|
+
5. JANGAN melebihi 3 kalimat.
|
|
17
|
+
6. HANYA OUTPUT TEKS RANGKUMAN, tanpa penjelasan tambahan apapun.`
|
|
18
|
+
|
|
19
|
+
const userPrompt = recentMessages
|
|
20
|
+
.map((m) => `${m.role === 'ai' ? 'Mark' : 'User'}: ${m.content}`)
|
|
21
|
+
.join('\n')
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const response = await fetchAI(
|
|
25
|
+
[
|
|
26
|
+
{ role: 'system', content: systemPrompt },
|
|
27
|
+
{ role: 'user', content: userPrompt }
|
|
28
|
+
],
|
|
29
|
+
false,
|
|
30
|
+
{
|
|
31
|
+
isSmallTask: true,
|
|
32
|
+
configOverride: { aiProvider: 'gemini-web', geminiWebModel: 'gemini-3.5-flash-thinking' }
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if (response?.error) {
|
|
37
|
+
console.error('[ChatSummarizer] Error dari AI:', response.error)
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const summary = response.content?.trim()
|
|
42
|
+
if (!summary) return
|
|
43
|
+
|
|
44
|
+
const vector = await generateVector(summary)
|
|
45
|
+
if (!vector) {
|
|
46
|
+
console.error('[ChatSummarizer] Gagal generate vector untuk summary')
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const timestamp = Date.now()
|
|
51
|
+
const topic = activeTopic || 'Obrolan Umum'
|
|
52
|
+
|
|
53
|
+
// 1. Simpan ke SQLite Database
|
|
54
|
+
const dbId = await insertChatArchive({
|
|
55
|
+
summary,
|
|
56
|
+
timestamp,
|
|
57
|
+
topic,
|
|
58
|
+
vector
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
// 2. Insert ke Orama
|
|
62
|
+
await insertArchiveToOrama({
|
|
63
|
+
summary,
|
|
64
|
+
topic,
|
|
65
|
+
timestamp,
|
|
66
|
+
dbId: String(dbId),
|
|
67
|
+
vector
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
console.log(
|
|
71
|
+
'[ChatSummarizer] Sukses merangkum dan mengarsipkan:',
|
|
72
|
+
summary.substring(0, 60) + '...'
|
|
73
|
+
)
|
|
74
|
+
} catch (error) {
|
|
75
|
+
if (error.name !== 'AbortError' && !error.message.includes('AbortError')) {
|
|
76
|
+
console.error('[ChatSummarizer] Exception saat merangkum:', error)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|