@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,413 @@
|
|
|
1
|
+
import readline from 'readline'
|
|
2
|
+
import http from 'http'
|
|
3
|
+
import { WebSocket } from 'ws'
|
|
4
|
+
import { colors as c, drawLeftRail, drawDivider, resolveWidth, stripAnsi } from './theme.js'
|
|
5
|
+
import { launchUI, closeUI } from '../server/launcher.js'
|
|
6
|
+
import { checkForUpdate, getCurrentVersion } from '../server/services/updater.js'
|
|
7
|
+
|
|
8
|
+
const SERVER_URL = process.env.MARK_SERVER_URL || 'http://localhost:3000'
|
|
9
|
+
const WS_URL = process.env.MARK_WS_URL || 'ws://localhost:3000/stream'
|
|
10
|
+
|
|
11
|
+
let activeServerPort = 3000
|
|
12
|
+
let isUiActive = false
|
|
13
|
+
let currentConfig = {}
|
|
14
|
+
let lastFetchPayload = null
|
|
15
|
+
let isJsonInspectorOpen = false
|
|
16
|
+
let updateInfo = null
|
|
17
|
+
let isUpdateModalOpen = false
|
|
18
|
+
|
|
19
|
+
export function setUpdateInfo(info) {
|
|
20
|
+
updateInfo = info
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getUpdateInfo() {
|
|
24
|
+
return updateInfo
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getTimeString() {
|
|
28
|
+
return new Date().toLocaleTimeString('id-ID', {
|
|
29
|
+
hour: '2-digit',
|
|
30
|
+
minute: '2-digit',
|
|
31
|
+
second: '2-digit'
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function checkServerHealth() {
|
|
36
|
+
return new Promise((resolve) => {
|
|
37
|
+
http
|
|
38
|
+
.get(`${SERVER_URL}/api/health`, (res) => {
|
|
39
|
+
resolve(res.statusCode === 200)
|
|
40
|
+
})
|
|
41
|
+
.on('error', () => {
|
|
42
|
+
resolve(false)
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function fetchConfig() {
|
|
48
|
+
try {
|
|
49
|
+
const res = await fetch(`${SERVER_URL}/api/config`)
|
|
50
|
+
const data = await res.json()
|
|
51
|
+
return data.config || {}
|
|
52
|
+
} catch (_) {
|
|
53
|
+
return {}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function printMonitorHeader(config = {}, uiActive = false) {
|
|
58
|
+
const provider = config.aiProvider || 'gemini-web'
|
|
59
|
+
const model =
|
|
60
|
+
provider === 'gemini-web'
|
|
61
|
+
? config.geminiWebModel || 'gemini-3.6-flash'
|
|
62
|
+
: provider === 'custom'
|
|
63
|
+
? config.customModel || 'default-model'
|
|
64
|
+
: config.model || 'local-model'
|
|
65
|
+
const cwd = process.cwd()
|
|
66
|
+
const termWidth = resolveWidth(null, 78)
|
|
67
|
+
|
|
68
|
+
const agentStatus = uiActive
|
|
69
|
+
? `${c.green}● Aktif${c.reset} ${c.darkGray}(Siap Digunakan)${c.reset}`
|
|
70
|
+
: `${c.yellow}○ Standby${c.reset} ${c.darkGray}(Jendela Ditutup)${c.reset}`
|
|
71
|
+
|
|
72
|
+
const maxCwd = Math.max(15, termWidth - 18)
|
|
73
|
+
const displayCwd = cwd.length > maxCwd ? '...' + cwd.slice(-(maxCwd - 3)) : cwd
|
|
74
|
+
|
|
75
|
+
const serverLine =
|
|
76
|
+
termWidth < 68
|
|
77
|
+
? ` ${c.darkGray}Core Server:${c.reset} ${c.blue}http://localhost:${activeServerPort}${c.reset}`
|
|
78
|
+
: ` ${c.darkGray}Core Server:${c.reset} ${c.blue}http://localhost:${activeServerPort}${c.reset} ${c.darkGray}|${c.reset} ${c.darkGray}Status:${c.reset} ${c.teal}Online${c.reset}`
|
|
79
|
+
|
|
80
|
+
const lines = [
|
|
81
|
+
` ${c.bold}${c.green}● MARK${c.reset} ${c.white}Autonomous Companion${c.reset} ${c.darkGray}[v${getCurrentVersion()}]${c.reset}`,
|
|
82
|
+
` ${c.darkGray}Workspace :${c.reset} ${c.gray}${displayCwd}${c.reset}`,
|
|
83
|
+
serverLine,
|
|
84
|
+
` ${c.darkGray}Status MARK:${c.reset} ${agentStatus}`,
|
|
85
|
+
` ${c.darkGray}AI Model :${c.reset} ${c.cyan}${provider}${c.reset} ${c.darkGray}(${model})${c.reset}`
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
if (updateInfo && updateInfo.hasUpdate) {
|
|
89
|
+
lines.push('')
|
|
90
|
+
const updateTitle =
|
|
91
|
+
termWidth < 70
|
|
92
|
+
? `▲ UPDATE: v${updateInfo.currentVersion} → v${updateInfo.latestVersion} [p]`
|
|
93
|
+
: `▲ UPDATE TERSEDIA: v${updateInfo.currentVersion} → v${updateInfo.latestVersion} (Tekan [p] untuk info)`
|
|
94
|
+
lines.push(` ${c.bold}${c.yellow}${updateTitle}${c.reset}`)
|
|
95
|
+
lines.push(
|
|
96
|
+
` ${c.darkGray}Perintah :${c.reset} ${c.green}${updateInfo.instruction || 'npm i -g @mazees/mark'}${c.reset}`
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!uiActive) {
|
|
101
|
+
lines.push('')
|
|
102
|
+
const standbyMsg =
|
|
103
|
+
termWidth < 65
|
|
104
|
+
? 'MARK standby. Tekan [u] untuk buka.'
|
|
105
|
+
: 'MARK sedang standby. Tekan [u] untuk membuka MARK.'
|
|
106
|
+
lines.push(` ${c.yellow}${standbyMsg}${c.reset}`)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Bersihkan layar & reset scrolling region sementara untuk render header
|
|
110
|
+
process.stdout.write('\x1b[r\x1b[2J\x1b[1;1H')
|
|
111
|
+
drawLeftRail('', lines, termWidth, uiActive ? c.darkGray : c.yellow)
|
|
112
|
+
|
|
113
|
+
let shortcutsText = ''
|
|
114
|
+
if (termWidth < 60) {
|
|
115
|
+
shortcutsText = ` ${c.darkGray}Keys:${c.reset} ${c.green}[u]${c.reset}${c.gray}UI${c.reset}${updateInfo?.hasUpdate ? ` ${c.green}[p]${c.reset}${c.yellow}Upd${c.reset}` : ''} ${c.green}[c]${c.reset}${c.gray}Clr${c.reset} ${c.green}[q]${c.reset}${c.gray}Quit${c.reset}`
|
|
116
|
+
} else if (termWidth < 76) {
|
|
117
|
+
shortcutsText = ` ${c.darkGray}Shortcuts:${c.reset} ${c.green}[u]${c.reset} ${c.gray}Buka${c.reset}${updateInfo?.hasUpdate ? ` | ${c.green}[p]${c.reset} ${c.yellow}Update${c.reset}` : ''} | ${c.green}[c]${c.reset} ${c.gray}Bersih${c.reset} | ${c.green}[q]${c.reset} ${c.gray}Keluar${c.reset}`
|
|
118
|
+
} else {
|
|
119
|
+
const updateShortcut = updateInfo?.hasUpdate
|
|
120
|
+
? ` ${c.darkGray}|${c.reset} ${c.green}[p]${c.reset} ${c.yellow}Update Info${c.reset}`
|
|
121
|
+
: ''
|
|
122
|
+
shortcutsText = ` ${c.darkGray}Shortcuts:${c.reset} ${c.green}[u]${c.reset} ${c.gray}Buka MARK${c.reset}${updateShortcut} ${c.darkGray}|${c.reset} ${c.green}[c]${c.reset} ${c.gray}Bersihkan Layar${c.reset} ${c.darkGray}|${c.reset} ${c.green}[q]${c.reset} ${c.gray}Keluar${c.reset}`
|
|
123
|
+
}
|
|
124
|
+
console.log(shortcutsText + '\n')
|
|
125
|
+
console.log(' ' + drawDivider('Live Activity', termWidth - 1, c.darkGray))
|
|
126
|
+
|
|
127
|
+
// Kunci baris 1 s/d headerHeight agar tidak tertimbun oleh scroll log
|
|
128
|
+
const headerHeight = lines.length + 5
|
|
129
|
+
const totalRows = process.stdout.rows || 30
|
|
130
|
+
if (totalRows > headerHeight + 2) {
|
|
131
|
+
process.stdout.write(`\x1b[${headerHeight + 1};${totalRows}r`)
|
|
132
|
+
process.stdout.write(`\x1b[${headerHeight + 1};1H`)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function logActivity(type, title, detail = '') {
|
|
137
|
+
const time = getTimeString()
|
|
138
|
+
let badge = `${c.darkGray}● Info ${c.reset}`
|
|
139
|
+
if (type === 'agent') badge = `${c.cyan}● Agent ${c.reset}`
|
|
140
|
+
else if (type === 'tool') badge = `${c.yellow}⚡ Tool ${c.reset}`
|
|
141
|
+
else if (type === 'result') badge = `${c.green}✓ Result ${c.reset}`
|
|
142
|
+
else if (type === 'thought') badge = `${c.purple}● Thought${c.reset}`
|
|
143
|
+
else if (type === 'fetch') badge = `${c.blue}📡 Fetch ${c.reset}`
|
|
144
|
+
else if (type === 'error') badge = `${c.red}● Error ${c.reset}`
|
|
145
|
+
|
|
146
|
+
const cols = process.stdout.columns || 80
|
|
147
|
+
const prefixWidth = 1 + 8 + 2 + 8 + 2 // 1 space + time (8) + 2 spaces + badge (8) + 2 spaces = 21
|
|
148
|
+
|
|
149
|
+
let displayTitle = String(title || '')
|
|
150
|
+
.replace(/\n/g, ' ')
|
|
151
|
+
.trim()
|
|
152
|
+
const maxTitleLen = Math.max(15, cols - prefixWidth - (detail ? 20 : 3))
|
|
153
|
+
if (displayTitle.length > maxTitleLen) {
|
|
154
|
+
displayTitle = displayTitle.slice(0, Math.max(0, maxTitleLen - 3)) + '...'
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const remainingForDetail = Math.max(10, cols - prefixWidth - displayTitle.length - 5)
|
|
158
|
+
const rawDetail = String(detail || '')
|
|
159
|
+
.replace(/\n/g, ' ')
|
|
160
|
+
.trim()
|
|
161
|
+
const safeDetail =
|
|
162
|
+
rawDetail.length > remainingForDetail
|
|
163
|
+
? rawDetail.slice(0, Math.max(0, remainingForDetail - 3)) + '...'
|
|
164
|
+
: rawDetail
|
|
165
|
+
|
|
166
|
+
const cleanDetail = safeDetail ? ` ${c.darkGray}›${c.reset} ${c.gray}${safeDetail}${c.reset}` : ''
|
|
167
|
+
console.log(
|
|
168
|
+
` ${c.darkGray}${time}${c.reset} ${badge} ${c.white}${displayTitle}${c.reset}${cleanDetail}`
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function toggleUpdateModal(config) {
|
|
173
|
+
isUpdateModalOpen = !isUpdateModalOpen
|
|
174
|
+
if (!isUpdateModalOpen) {
|
|
175
|
+
printMonitorHeader(config, isUiActive)
|
|
176
|
+
logActivity('agent', 'Info update ditutup. Monitor kembali ke mode live.')
|
|
177
|
+
} else {
|
|
178
|
+
process.stdout.write('\x1b[r')
|
|
179
|
+
printUpdateModal(updateInfo)
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function printUpdateModal(info) {
|
|
184
|
+
const modalWidth = resolveWidth(null, 76)
|
|
185
|
+
const latest = info?.latestVersion || 'terbaru'
|
|
186
|
+
const curr = info?.currentVersion || getCurrentVersion()
|
|
187
|
+
const instruction = info?.instruction || 'npm install -g @mazees/mark@latest'
|
|
188
|
+
|
|
189
|
+
console.log(`\n ${c.bold}${drawDivider('[INFO UPDATE MARK]', modalWidth, c.green)}\n`)
|
|
190
|
+
console.log(
|
|
191
|
+
` Versi terbaru ${c.bold}${c.cyan}@mazees/mark${c.reset} (${c.green}v${latest}${c.reset}) telah dirilis di npm!`
|
|
192
|
+
)
|
|
193
|
+
console.log(` Versi yang terpasang saat ini: ${c.yellow}v${curr}${c.reset}\n`)
|
|
194
|
+
console.log(
|
|
195
|
+
` ${c.white}Untuk memperbarui ke versi terbaru, jalankan perintah berikut di terminal:${c.reset}`
|
|
196
|
+
)
|
|
197
|
+
console.log(`\n ${c.bold}${c.green}${instruction}${c.reset}\n`)
|
|
198
|
+
console.log(
|
|
199
|
+
` ${c.darkGray}Petunjuk: Matikan MARK terlebih dahulu ([q]) sebelum menjalankan perintah update.${c.reset}`
|
|
200
|
+
)
|
|
201
|
+
console.log(`\n ${c.bold}${drawDivider('', modalWidth, c.green)}`)
|
|
202
|
+
console.log(
|
|
203
|
+
` ${c.gray}Tekan ${c.green}[p]${c.gray} atau ${c.green}[Enter]${c.gray} untuk kembali ke dashboard live...${c.reset}\n`
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export function toggleJsonInspector(config) {
|
|
208
|
+
isJsonInspectorOpen = !isJsonInspectorOpen
|
|
209
|
+
if (!isJsonInspectorOpen) {
|
|
210
|
+
printMonitorHeader(config, isUiActive)
|
|
211
|
+
logActivity('agent', 'JSON Inspector ditutup. Monitor kembali ke mode live.')
|
|
212
|
+
} else {
|
|
213
|
+
process.stdout.write('\x1b[r')
|
|
214
|
+
printJsonInspector(lastFetchPayload)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function printJsonInspector(payload) {
|
|
219
|
+
const inspectorWidth = resolveWidth(null, 76)
|
|
220
|
+
console.log(
|
|
221
|
+
`\n ${c.bold}${drawDivider('[INFO] AI Request Inspector', inspectorWidth, c.green)}\n`
|
|
222
|
+
)
|
|
223
|
+
console.log(
|
|
224
|
+
` ${c.gray}Untuk performa maksimal dan bebas lag, payload raksasa kini diinspeksi via:${c.reset}`
|
|
225
|
+
)
|
|
226
|
+
console.log(` ${c.cyan}WebUI DevTools Console (F12) › window.__LAST_AI__${c.reset}\n`)
|
|
227
|
+
if (payload) {
|
|
228
|
+
console.log(` ${c.white}Metadata Permintaan Terakhir:${c.reset}`)
|
|
229
|
+
console.log(
|
|
230
|
+
` ${c.darkGray}Provider :${c.reset} ${c.teal}${payload.provider || '-'}${c.reset}`
|
|
231
|
+
)
|
|
232
|
+
console.log(
|
|
233
|
+
` ${c.darkGray}Model :${c.reset} ${c.teal}${payload.model || '-'}${c.reset}`
|
|
234
|
+
)
|
|
235
|
+
console.log(
|
|
236
|
+
` ${c.darkGray}Messages Count:${c.reset} ${c.teal}${payload.messagesCount ?? '-'}${c.reset}`
|
|
237
|
+
)
|
|
238
|
+
console.log(
|
|
239
|
+
` ${c.darkGray}Has Tools :${c.reset} ${c.teal}${payload.hasTools ? 'Ya' : 'Tidak'}${c.reset}`
|
|
240
|
+
)
|
|
241
|
+
} else {
|
|
242
|
+
console.log(` ${c.yellow}● Belum ada riwayat aktivitas request AI.${c.reset}`)
|
|
243
|
+
}
|
|
244
|
+
console.log(`\n ${c.bold}${drawDivider('', inspectorWidth, c.green)}\n`)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export async function runMonitor(portOverride) {
|
|
248
|
+
let serverPort = portOverride || Number(process.env.PORT) || 3000
|
|
249
|
+
activeServerPort = serverPort
|
|
250
|
+
let serverUrl = `http://localhost:${serverPort}`
|
|
251
|
+
let wsUrl = `ws://localhost:${serverPort}/stream`
|
|
252
|
+
|
|
253
|
+
let isAlive = await new Promise((resolve) => {
|
|
254
|
+
http
|
|
255
|
+
.get(`${serverUrl}/api/health`, (res) => resolve(res.statusCode === 200))
|
|
256
|
+
.on('error', () => resolve(false))
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
if (!isAlive) {
|
|
260
|
+
const serverModule = await import('../server/index.js')
|
|
261
|
+
serverPort = serverModule.activePort || serverPort
|
|
262
|
+
activeServerPort = serverPort
|
|
263
|
+
serverUrl = `http://localhost:${serverPort}`
|
|
264
|
+
wsUrl = `ws://localhost:${serverPort}/stream`
|
|
265
|
+
await new Promise((resolve) => setTimeout(resolve, 600))
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
currentConfig = await (async () => {
|
|
269
|
+
try {
|
|
270
|
+
const res = await fetch(`${serverUrl}/api/config`)
|
|
271
|
+
const data = await res.json()
|
|
272
|
+
return data.config || {}
|
|
273
|
+
const json = await res.json()
|
|
274
|
+
return json.data || json.config || {}
|
|
275
|
+
} catch (_) {
|
|
276
|
+
return {}
|
|
277
|
+
}
|
|
278
|
+
})()
|
|
279
|
+
|
|
280
|
+
printMonitorHeader(currentConfig, isUiActive)
|
|
281
|
+
|
|
282
|
+
logActivity('agent', `MARK Server aktif di port ${serverPort}`)
|
|
283
|
+
logActivity('agent', 'Membuka antarmuka MARK...')
|
|
284
|
+
|
|
285
|
+
// Pengecekan update versi terbaru di latar belakang (non-blocking)
|
|
286
|
+
checkForUpdate()
|
|
287
|
+
.then((info) => {
|
|
288
|
+
if (info && info.hasUpdate) {
|
|
289
|
+
updateInfo = info
|
|
290
|
+
if (!isJsonInspectorOpen && !isUpdateModalOpen) {
|
|
291
|
+
printMonitorHeader(currentConfig, isUiActive)
|
|
292
|
+
logActivity(
|
|
293
|
+
'agent',
|
|
294
|
+
'Update Tersedia',
|
|
295
|
+
`v${info.currentVersion} → v${info.latestVersion} (Tekan [p] utk perintah update)`
|
|
296
|
+
)
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
})
|
|
300
|
+
.catch(() => {})
|
|
301
|
+
|
|
302
|
+
// Connect WebSocket live streaming
|
|
303
|
+
try {
|
|
304
|
+
const ws = new WebSocket(wsUrl)
|
|
305
|
+
ws.on('open', () => {
|
|
306
|
+
logActivity('agent', 'Core server siap menerima koneksi.')
|
|
307
|
+
})
|
|
308
|
+
ws.on('message', (data) => {
|
|
309
|
+
try {
|
|
310
|
+
const { event, payload } = JSON.parse(data.toString())
|
|
311
|
+
if (event === 'ui:status') {
|
|
312
|
+
const wasActive = isUiActive
|
|
313
|
+
isUiActive = !!payload?.active
|
|
314
|
+
if (wasActive !== isUiActive && !isJsonInspectorOpen) {
|
|
315
|
+
printMonitorHeader(currentConfig, isUiActive)
|
|
316
|
+
if (isUiActive) {
|
|
317
|
+
logActivity('agent', 'MARK terhubung dan siap digunakan.')
|
|
318
|
+
} else {
|
|
319
|
+
logActivity('agent', 'MARK ditutup (mode standby). Tekan [u] untuk membuka kembali.')
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
} else if (event === 'config:updated') {
|
|
323
|
+
currentConfig = payload || {}
|
|
324
|
+
if (!isJsonInspectorOpen) {
|
|
325
|
+
printMonitorHeader(currentConfig, isUiActive)
|
|
326
|
+
const providerStr = currentConfig.aiProvider || 'AI'
|
|
327
|
+
const modelStr =
|
|
328
|
+
providerStr === 'custom'
|
|
329
|
+
? currentConfig.customModel || 'custom'
|
|
330
|
+
: providerStr === 'gemini-web'
|
|
331
|
+
? currentConfig.geminiWebModel || 'gemini'
|
|
332
|
+
: currentConfig.model || ''
|
|
333
|
+
logActivity('agent', 'Konfigurasi diperbarui', `${providerStr} (${modelStr})`)
|
|
334
|
+
}
|
|
335
|
+
} else if (event === 'ai:fetch') {
|
|
336
|
+
lastFetchPayload = payload
|
|
337
|
+
const info = `[${payload.provider}/${payload.model}] ${payload.messagesCount || 0} msgs${payload.hasTools ? `, ${payload.toolsCount || 0} tools` : ''}`
|
|
338
|
+
logActivity('fetch', `AI Request (${payload.type || 'fetch'})`, info)
|
|
339
|
+
} else if (event === 'agent:thought') {
|
|
340
|
+
logActivity('thought', `Turn ${payload.turn}`, payload.thought)
|
|
341
|
+
} else if (event === 'tool:call') {
|
|
342
|
+
logActivity('tool', payload.tool, payload.query)
|
|
343
|
+
} else if (event === 'tool:result') {
|
|
344
|
+
logActivity('result', payload.tool, payload.observation)
|
|
345
|
+
} else if (event === 'chat:receive') {
|
|
346
|
+
logActivity('agent', 'Pesan diterima', payload.message)
|
|
347
|
+
} else if (event === 'awareness:entry') {
|
|
348
|
+
logActivity('agent', 'Active Window', `[${payload.app}] ${payload.title}`)
|
|
349
|
+
} else if (event === 'browser:preview' && !payload.closed) {
|
|
350
|
+
logActivity('tool', 'Browser Preview', `${payload.title || ''} (${payload.url || ''})`)
|
|
351
|
+
}
|
|
352
|
+
} catch (_) {}
|
|
353
|
+
})
|
|
354
|
+
} catch (_) {}
|
|
355
|
+
|
|
356
|
+
// Restore scroll region saat resize terminal
|
|
357
|
+
process.stdout.on('resize', () => {
|
|
358
|
+
if (isUpdateModalOpen) {
|
|
359
|
+
process.stdout.write('\x1b[r\x1b[2J\x1b[1;1H')
|
|
360
|
+
printUpdateModal(updateInfo)
|
|
361
|
+
} else if (isJsonInspectorOpen) {
|
|
362
|
+
process.stdout.write('\x1b[r\x1b[2J\x1b[1;1H')
|
|
363
|
+
printJsonInspector(lastFetchPayload)
|
|
364
|
+
} else {
|
|
365
|
+
printMonitorHeader(currentConfig, isUiActive)
|
|
366
|
+
}
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
// Pastikan terminal dikembalikan normal saat exit
|
|
370
|
+
process.on('exit', () => {
|
|
371
|
+
process.stdout.write('\x1b[r\x1b[?25h')
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
// Raw Mode Keyboard Listener for quick actions
|
|
375
|
+
if (process.stdin.isTTY) {
|
|
376
|
+
process.stdin.setRawMode(true)
|
|
377
|
+
}
|
|
378
|
+
readline.emitKeypressEvents(process.stdin)
|
|
379
|
+
process.stdin.resume()
|
|
380
|
+
|
|
381
|
+
process.stdin.on('keypress', async (chunk, key) => {
|
|
382
|
+
if (!key) return
|
|
383
|
+
|
|
384
|
+
if (key.name === 'q' || (key.ctrl && key.name === 'c')) {
|
|
385
|
+
process.stdout.write('\x1b[r\x1b[?25h')
|
|
386
|
+
console.log(
|
|
387
|
+
`\n ${c.yellow}●${c.reset} ${c.gray}Mematikan MARK Core Engine. Sampai jumpa!${c.reset}\n`
|
|
388
|
+
)
|
|
389
|
+
closeUI()
|
|
390
|
+
process.exit(0)
|
|
391
|
+
} else if (key.name === 'u' || key.name === 'o') {
|
|
392
|
+
logActivity('agent', 'Membuka MARK...')
|
|
393
|
+
await launchUI({ port: serverPort, mode: 'app' })
|
|
394
|
+
} else if (key.name === 'p') {
|
|
395
|
+
currentConfig = await fetchConfig()
|
|
396
|
+
toggleUpdateModal(currentConfig)
|
|
397
|
+
} else if (key.name === 'j' || key.name === 'd') {
|
|
398
|
+
currentConfig = await fetchConfig()
|
|
399
|
+
toggleJsonInspector(currentConfig)
|
|
400
|
+
} else if (key.name === 'c') {
|
|
401
|
+
currentConfig = await fetchConfig()
|
|
402
|
+
printMonitorHeader(currentConfig, isUiActive)
|
|
403
|
+
logActivity('agent', 'Layar dibersihkan.')
|
|
404
|
+
} else if (isUpdateModalOpen && (key.name === 'return' || key.name === 'escape')) {
|
|
405
|
+
toggleUpdateModal(currentConfig)
|
|
406
|
+
}
|
|
407
|
+
})
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Jalankan jika dipanggil mandiri
|
|
411
|
+
if (process.argv[1]?.endsWith('cli/monitor.js')) {
|
|
412
|
+
runMonitor().catch((err) => console.error('[Monitor Fatal Error]:', err))
|
|
413
|
+
}
|