@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
package/src/cli/theme.js
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import readline from 'readline'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
|
|
4
|
+
let appVersion = '5.0.0'
|
|
5
|
+
try {
|
|
6
|
+
const pkg = JSON.parse(fs.readFileSync(new URL('../../package.json', import.meta.url), 'utf-8'))
|
|
7
|
+
if (pkg.version) appVersion = pkg.version
|
|
8
|
+
} catch (_) {}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* CLI Theme and Formatting Utilities for MARK
|
|
12
|
+
* Claude Code & Antigravity aesthetic (Zero Emojis, Clean Box Drawing, Developer-grade Typography)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export const colors = {
|
|
16
|
+
reset: '\x1b[0m',
|
|
17
|
+
bold: '\x1b[1m',
|
|
18
|
+
dim: '\x1b[2m',
|
|
19
|
+
italic: '\x1b[3m',
|
|
20
|
+
underline: '\x1b[4m',
|
|
21
|
+
|
|
22
|
+
// Foreground
|
|
23
|
+
green: '\x1b[38;2;31;184;84m', // #1fb854 (MARK Primary Green)
|
|
24
|
+
emerald: '\x1b[38;2;16;185;129m',
|
|
25
|
+
teal: '\x1b[38;2;45;212;191m',
|
|
26
|
+
cyan: '\x1b[38;2;56;189;248m',
|
|
27
|
+
blue: '\x1b[38;2;96;165;250m',
|
|
28
|
+
purple: '\x1b[38;2;192;132;252m',
|
|
29
|
+
yellow: '\x1b[38;2;251;191;36m',
|
|
30
|
+
orange: '\x1b[38;2;251;146;60m',
|
|
31
|
+
red: '\x1b[38;2;248;113;113m',
|
|
32
|
+
gray: '\x1b[38;2;148;163;184m',
|
|
33
|
+
darkGray: '\x1b[38;2;71;85;105m',
|
|
34
|
+
white: '\x1b[38;2;241;245;249m',
|
|
35
|
+
|
|
36
|
+
// Background
|
|
37
|
+
bgDark: '\x1b[48;2;15;23;21m',
|
|
38
|
+
bgCard: '\x1b[48;2;25;54;45m'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function stripAnsi(str) {
|
|
42
|
+
if (typeof str !== 'string') return ''
|
|
43
|
+
return str.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function truncateAnsi(str, maxWidth) {
|
|
47
|
+
if (!str) return ''
|
|
48
|
+
const plain = stripAnsi(str)
|
|
49
|
+
if (plain.length <= maxWidth) return str
|
|
50
|
+
if (maxWidth <= 3) return '.'.repeat(Math.max(1, maxWidth))
|
|
51
|
+
|
|
52
|
+
const targetLen = maxWidth - 3
|
|
53
|
+
let visible = 0
|
|
54
|
+
let result = ''
|
|
55
|
+
let inAnsi = false
|
|
56
|
+
|
|
57
|
+
for (let i = 0; i < str.length; i++) {
|
|
58
|
+
const char = str[i]
|
|
59
|
+
if (char === '\x1b') {
|
|
60
|
+
inAnsi = true
|
|
61
|
+
result += char
|
|
62
|
+
continue
|
|
63
|
+
}
|
|
64
|
+
if (inAnsi) {
|
|
65
|
+
result += char
|
|
66
|
+
if (/[a-zA-Z]/.test(char)) {
|
|
67
|
+
inAnsi = false
|
|
68
|
+
}
|
|
69
|
+
continue
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
result += char
|
|
73
|
+
visible++
|
|
74
|
+
if (visible >= targetLen) {
|
|
75
|
+
result += '...\x1b[0m'
|
|
76
|
+
break
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return result
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function resolveWidth(customWidth = null, fallbackMax = 78, min = 40) {
|
|
83
|
+
const cols = process.stdout.columns || 80
|
|
84
|
+
const maxAllowed = Math.max(min, cols - 3)
|
|
85
|
+
if (typeof customWidth === 'number' && customWidth > 0) {
|
|
86
|
+
return Math.min(customWidth, maxAllowed)
|
|
87
|
+
}
|
|
88
|
+
return Math.min(fallbackMax, maxAllowed)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function drawDivider(label = '', width = null, color = colors.darkGray) {
|
|
92
|
+
const w = resolveWidth(width)
|
|
93
|
+
if (!label) {
|
|
94
|
+
return `${color}${'─'.repeat(Math.max(0, w))}${colors.reset}`
|
|
95
|
+
}
|
|
96
|
+
const clean = stripAnsi(label)
|
|
97
|
+
const remain = Math.max(0, w - clean.length - 4)
|
|
98
|
+
return `${color}── ${label} ${'─'.repeat(remain)}${colors.reset}`
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function drawBox(
|
|
102
|
+
title = '',
|
|
103
|
+
contentLines = [],
|
|
104
|
+
width = null,
|
|
105
|
+
borderColor = colors.darkGray
|
|
106
|
+
) {
|
|
107
|
+
const c = colors
|
|
108
|
+
const w = resolveWidth(width, 78)
|
|
109
|
+
const cleanTitle = stripAnsi(title)
|
|
110
|
+
|
|
111
|
+
let topBorder
|
|
112
|
+
if (cleanTitle) {
|
|
113
|
+
const dashCount = Math.max(0, w - cleanTitle.length - 5)
|
|
114
|
+
topBorder = `${borderColor}╭─ ${c.bold}${c.green}${title}${c.reset}${borderColor} ${'─'.repeat(dashCount)}╮${c.reset}`
|
|
115
|
+
} else {
|
|
116
|
+
const dashCount = Math.max(0, w - 3)
|
|
117
|
+
topBorder = `${borderColor}╭─${'─'.repeat(dashCount)}╮${c.reset}`
|
|
118
|
+
}
|
|
119
|
+
const bottomBorder = `${borderColor}╰${'─'.repeat(Math.max(0, w - 2))}╯${c.reset}`
|
|
120
|
+
|
|
121
|
+
console.log(topBorder)
|
|
122
|
+
const innerWidth = Math.max(10, w - 2)
|
|
123
|
+
|
|
124
|
+
// Flatten lines in case content contains embedded newlines
|
|
125
|
+
const flatLines = []
|
|
126
|
+
for (const raw of contentLines) {
|
|
127
|
+
const parts = String(raw ?? '').split(/\r?\n/)
|
|
128
|
+
flatLines.push(...parts)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
for (const line of flatLines) {
|
|
132
|
+
const safeLine = truncateAnsi(line, innerWidth)
|
|
133
|
+
const padLen = Math.max(0, innerWidth - stripAnsi(safeLine).length)
|
|
134
|
+
console.log(
|
|
135
|
+
`${borderColor}│${c.reset}${safeLine}${' '.repeat(padLen)}${borderColor}│${c.reset}`
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
console.log(bottomBorder)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function drawLeftRail(
|
|
142
|
+
title = '',
|
|
143
|
+
contentLines = [],
|
|
144
|
+
width = null,
|
|
145
|
+
borderColor = colors.darkGray
|
|
146
|
+
) {
|
|
147
|
+
const c = colors
|
|
148
|
+
const w = resolveWidth(width, 78)
|
|
149
|
+
const cleanTitle = stripAnsi(title)
|
|
150
|
+
|
|
151
|
+
let topBorder
|
|
152
|
+
if (cleanTitle) {
|
|
153
|
+
const dashCount = Math.max(0, w - cleanTitle.length - 4)
|
|
154
|
+
topBorder = `${borderColor}┌─ ${c.bold}${c.green}${title}${c.reset}${borderColor} ${'─'.repeat(dashCount)}${c.reset}`
|
|
155
|
+
} else {
|
|
156
|
+
const dashCount = Math.max(0, w - 2)
|
|
157
|
+
topBorder = `${borderColor}┌─${'─'.repeat(dashCount)}${c.reset}`
|
|
158
|
+
}
|
|
159
|
+
const bottomBorder = `${borderColor}└${'─'.repeat(Math.max(0, w - 1))}${c.reset}`
|
|
160
|
+
|
|
161
|
+
console.log(topBorder)
|
|
162
|
+
const innerWidth = Math.max(10, w - 2)
|
|
163
|
+
|
|
164
|
+
const flatLines = []
|
|
165
|
+
for (const raw of contentLines) {
|
|
166
|
+
const parts = String(raw ?? '').split(/\r?\n/)
|
|
167
|
+
flatLines.push(...parts)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
for (const line of flatLines) {
|
|
171
|
+
const safeLine = truncateAnsi(line, innerWidth)
|
|
172
|
+
console.log(`${borderColor}│${c.reset}${safeLine}`)
|
|
173
|
+
}
|
|
174
|
+
console.log(bottomBorder)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function printHeader(config = {}) {
|
|
178
|
+
const c = colors
|
|
179
|
+
console.clear()
|
|
180
|
+
const provider = config.aiProvider || 'gemini-web'
|
|
181
|
+
const model =
|
|
182
|
+
provider === 'gemini-web'
|
|
183
|
+
? config.geminiWebModel || 'gemini-3.6-flash'
|
|
184
|
+
: provider === 'custom'
|
|
185
|
+
? config.customModel || 'default-model'
|
|
186
|
+
: config.model || 'local-model'
|
|
187
|
+
const cwd = process.cwd()
|
|
188
|
+
const termWidth = resolveWidth(null, 78)
|
|
189
|
+
const maxCwd = Math.max(15, termWidth - 18)
|
|
190
|
+
const displayCwd = cwd.length > maxCwd ? '...' + cwd.slice(-(maxCwd - 3)) : cwd
|
|
191
|
+
|
|
192
|
+
const lines = [
|
|
193
|
+
` ${c.bold}${c.green}● MARK${c.reset} ${c.white}Autonomous Companion${c.reset} ${c.darkGray}[v${appVersion}]${c.reset}`,
|
|
194
|
+
` ${c.darkGray}Workspace :${c.reset} ${c.gray}${displayCwd}${c.reset}`,
|
|
195
|
+
` ${c.darkGray}Provider :${c.reset} ${c.cyan}${provider}${c.reset} ${c.darkGray}(${model})${c.reset} ${c.darkGray}|${c.reset} ${c.darkGray}Port:${c.reset} ${c.teal}3000${c.reset}`,
|
|
196
|
+
` ${c.darkGray}WebUI :${c.reset} ${c.blue}http://localhost:3000${c.reset} ${c.darkGray}[Edge App Mode Ready]${c.reset}`
|
|
197
|
+
]
|
|
198
|
+
|
|
199
|
+
drawBox('', lines, termWidth, c.darkGray)
|
|
200
|
+
|
|
201
|
+
const cols = process.stdout.columns || 80
|
|
202
|
+
if (cols < 70) {
|
|
203
|
+
console.log(
|
|
204
|
+
` ${c.darkGray}Cmds:${c.reset} ${c.green}/ui /web /provider /model /memory /status /clear /exit${c.reset}\n`
|
|
205
|
+
)
|
|
206
|
+
} else {
|
|
207
|
+
console.log(
|
|
208
|
+
` ${c.darkGray}Commands:${c.reset} ${c.green}/ui${c.reset} ${c.darkGray}|${c.reset} ${c.green}/web${c.reset} ${c.darkGray}|${c.reset} ${c.green}/provider${c.reset} ${c.darkGray}|${c.reset} ${c.green}/model${c.reset} ${c.darkGray}|${c.reset} ${c.green}/memory${c.reset} ${c.darkGray}|${c.reset} ${c.green}/status${c.reset} ${c.darkGray}|${c.reset} ${c.green}/clear${c.reset} ${c.darkGray}|${c.reset} ${c.green}/exit${c.reset}\n`
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function printThought(thought, turn = 1) {
|
|
214
|
+
const c = colors
|
|
215
|
+
const lines = [` ${c.gray}${thought.trim()}${c.reset}`]
|
|
216
|
+
drawBox(`Thought (Turn ${turn})`, lines, null, c.darkGray)
|
|
217
|
+
console.log()
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function printToolCall(tool, query) {
|
|
221
|
+
const c = colors
|
|
222
|
+
const cols = process.stdout.columns || 80
|
|
223
|
+
const maxQuery = Math.max(20, cols - 30)
|
|
224
|
+
const safeQuery =
|
|
225
|
+
query && String(query).length > maxQuery ? String(query).slice(0, maxQuery - 3) + '...' : query
|
|
226
|
+
console.log(
|
|
227
|
+
` ${c.yellow}⚡ Action${c.reset} › ${c.bold}${c.white}${tool}${c.reset} ${safeQuery ? `${c.darkGray}› ${c.gray}${safeQuery}${c.reset}` : ''}`
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function printToolResult(tool, result) {
|
|
232
|
+
const c = colors
|
|
233
|
+
const cols = process.stdout.columns || 80
|
|
234
|
+
const maxLen = Math.max(25, cols - 30)
|
|
235
|
+
const raw = String(result ?? '')
|
|
236
|
+
.trim()
|
|
237
|
+
.replace(/\n/g, ' ')
|
|
238
|
+
const preview = raw.length > maxLen ? raw.slice(0, maxLen - 3) + '...' : raw
|
|
239
|
+
console.log(
|
|
240
|
+
` ${c.green}✓ Result${c.reset} › ${c.darkGray}[${tool}]${c.reset} ${c.gray}${preview}${c.reset}\n`
|
|
241
|
+
)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function printAssistantAnswer(answer) {
|
|
245
|
+
const c = colors
|
|
246
|
+
console.log(`\n${c.bold}${c.green}Mark ›${c.reset}`)
|
|
247
|
+
console.log(`${c.white}${answer.trim()}${c.reset}\n`)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Interactive Arrow-Key Navigable Selector
|
|
252
|
+
* Supports Up/Down arrow keys, j/k, Number keys 1-N, Enter to select, and Esc to cancel.
|
|
253
|
+
*/
|
|
254
|
+
export async function promptSelect({ title = 'Select Option', options = [], activeId = null }) {
|
|
255
|
+
return new Promise((resolve) => {
|
|
256
|
+
let selectedIndex = options.findIndex((o) => o.id === activeId)
|
|
257
|
+
if (selectedIndex === -1) selectedIndex = 0
|
|
258
|
+
|
|
259
|
+
const width = resolveWidth(null, 76)
|
|
260
|
+
const innerWidth = Math.max(10, width - 2)
|
|
261
|
+
let renderedLines = 0
|
|
262
|
+
|
|
263
|
+
const render = (isFirst = false) => {
|
|
264
|
+
if (!isFirst && renderedLines > 0) {
|
|
265
|
+
process.stdout.write(`\x1b[${renderedLines}A\r`)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const cleanTitle = stripAnsi(title)
|
|
269
|
+
const dashCount = Math.max(0, width - cleanTitle.length - 5)
|
|
270
|
+
const topBorder = `${colors.darkGray}╭─ ${colors.bold}${colors.green}${title}${colors.reset}${colors.darkGray} ${'─'.repeat(dashCount)}╮${colors.reset}`
|
|
271
|
+
const bottomBorder = `${colors.darkGray}╰${'─'.repeat(Math.max(0, width - 2))}╯${colors.reset}`
|
|
272
|
+
const hint = ` ${colors.darkGray}Gunakan panah ↑/↓ atau [1-${options.length}] lalu Enter. Esc untuk batal.${colors.reset}`
|
|
273
|
+
|
|
274
|
+
const lines = options.map((opt, i) => {
|
|
275
|
+
const isSelected = i === selectedIndex
|
|
276
|
+
const isCurrent = opt.id === activeId
|
|
277
|
+
const bullet = isCurrent
|
|
278
|
+
? `${colors.green}●${colors.reset}`
|
|
279
|
+
: `${colors.darkGray}○${colors.reset}`
|
|
280
|
+
const pointer = isSelected ? `${colors.bold}${colors.green}›${colors.reset}` : ' '
|
|
281
|
+
const titleText = isSelected
|
|
282
|
+
? `${colors.bold}${colors.green}${opt.title}${colors.reset}`
|
|
283
|
+
: `${colors.white}${opt.title}${colors.reset}`
|
|
284
|
+
const descText = `${colors.darkGray}${opt.description || ''}${colors.reset}`
|
|
285
|
+
const num = `${colors.darkGray}[${i + 1}]${colors.reset}`
|
|
286
|
+
const rawLine = ` ${pointer} ${bullet} ${num} ${titleText} ${descText}`
|
|
287
|
+
const safeLine = truncateAnsi(rawLine, innerWidth)
|
|
288
|
+
const padLen = Math.max(0, innerWidth - stripAnsi(safeLine).length)
|
|
289
|
+
return `${colors.darkGray}│${colors.reset}${safeLine}${' '.repeat(padLen)}${colors.darkGray}│${colors.reset}`
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
process.stdout.write(`\x1b[K${topBorder}\n`)
|
|
293
|
+
for (const line of lines) {
|
|
294
|
+
process.stdout.write(`\x1b[K${line}\n`)
|
|
295
|
+
}
|
|
296
|
+
process.stdout.write(`\x1b[K${bottomBorder}\n`)
|
|
297
|
+
process.stdout.write(`\x1b[K${hint}\n`)
|
|
298
|
+
|
|
299
|
+
renderedLines = lines.length + 3
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
process.stdout.write('\x1b[?25l')
|
|
303
|
+
|
|
304
|
+
if (process.stdin.isTTY) {
|
|
305
|
+
process.stdin.setRawMode(true)
|
|
306
|
+
}
|
|
307
|
+
readline.emitKeypressEvents(process.stdin)
|
|
308
|
+
process.stdin.resume()
|
|
309
|
+
|
|
310
|
+
render(true)
|
|
311
|
+
|
|
312
|
+
const onKeypress = (chunk, key) => {
|
|
313
|
+
if (!key) return
|
|
314
|
+
|
|
315
|
+
if (key.name === 'up' || key.name === 'k') {
|
|
316
|
+
selectedIndex = (selectedIndex - 1 + options.length) % options.length
|
|
317
|
+
render()
|
|
318
|
+
} else if (key.name === 'down' || key.name === 'j') {
|
|
319
|
+
selectedIndex = (selectedIndex + 1) % options.length
|
|
320
|
+
render()
|
|
321
|
+
} else if (key.name === 'return' || key.name === 'enter') {
|
|
322
|
+
cleanup()
|
|
323
|
+
resolve(options[selectedIndex].id)
|
|
324
|
+
} else if (key.name === 'escape' || (key.ctrl && key.name === 'c')) {
|
|
325
|
+
cleanup()
|
|
326
|
+
resolve(null)
|
|
327
|
+
} else if (key.name >= '1' && key.name <= String(options.length)) {
|
|
328
|
+
const numIdx = parseInt(key.name, 10) - 1
|
|
329
|
+
if (numIdx >= 0 && numIdx < options.length) {
|
|
330
|
+
selectedIndex = numIdx
|
|
331
|
+
cleanup()
|
|
332
|
+
resolve(options[numIdx].id)
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const cleanup = () => {
|
|
338
|
+
process.stdin.removeListener('keypress', onKeypress)
|
|
339
|
+
if (process.stdin.isTTY) {
|
|
340
|
+
process.stdin.setRawMode(false)
|
|
341
|
+
}
|
|
342
|
+
process.stdout.write('\x1b[?25h')
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
process.stdin.on('keypress', onKeypress)
|
|
346
|
+
})
|
|
347
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Diagnostics;
|
|
3
|
+
using System.Drawing;
|
|
4
|
+
using System.IO;
|
|
5
|
+
using System.Net.Http;
|
|
6
|
+
using System.Reflection;
|
|
7
|
+
using System.Runtime.InteropServices;
|
|
8
|
+
using System.Text;
|
|
9
|
+
using System.Threading;
|
|
10
|
+
using System.Threading.Tasks;
|
|
11
|
+
using System.Windows.Forms;
|
|
12
|
+
|
|
13
|
+
namespace MarkLauncher
|
|
14
|
+
{
|
|
15
|
+
static class Program
|
|
16
|
+
{
|
|
17
|
+
[DllImport("user32.dll")]
|
|
18
|
+
private static extern bool SetForegroundWindow(IntPtr hWnd);
|
|
19
|
+
|
|
20
|
+
[DllImport("user32.dll")]
|
|
21
|
+
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
|
22
|
+
|
|
23
|
+
private const int SW_RESTORE = 9;
|
|
24
|
+
|
|
25
|
+
private static NotifyIcon _trayIcon;
|
|
26
|
+
private static ContextMenuStrip _trayMenu;
|
|
27
|
+
private static Process _nodeProcess;
|
|
28
|
+
private static readonly int ServerPort = 3000;
|
|
29
|
+
private static string _appDirectory;
|
|
30
|
+
private static string _iconPath;
|
|
31
|
+
|
|
32
|
+
[STAThread]
|
|
33
|
+
static void Main(string[] args)
|
|
34
|
+
{
|
|
35
|
+
// Cegah multiple instance launcher
|
|
36
|
+
bool createdNew;
|
|
37
|
+
using (Mutex mutex = new Mutex(true, "MARK_AI_OS_COMPANION_MUTEX", out createdNew))
|
|
38
|
+
{
|
|
39
|
+
if (!createdNew)
|
|
40
|
+
{
|
|
41
|
+
// Jika sudah berjalan, buka jendela UI
|
|
42
|
+
OpenOrFocusUI();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
Application.EnableVisualStyles();
|
|
47
|
+
Application.SetCompatibleTextRenderingDefault(false);
|
|
48
|
+
|
|
49
|
+
_appDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
|
50
|
+
_iconPath = Path.Combine(_appDirectory, "resources", "icon.ico");
|
|
51
|
+
|
|
52
|
+
InitializeTray();
|
|
53
|
+
StartNodeServer();
|
|
54
|
+
|
|
55
|
+
// Buka UI otomatis saat pertama kali start
|
|
56
|
+
Task.Run(async () =>
|
|
57
|
+
{
|
|
58
|
+
await WaitForServerReadyAsync();
|
|
59
|
+
OpenOrFocusUI();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
Application.Run();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private static void InitializeTray()
|
|
67
|
+
{
|
|
68
|
+
_trayMenu = new ContextMenuStrip();
|
|
69
|
+
|
|
70
|
+
var itemOpen = new ToolStripMenuItem("Buka MARK", null, (s, e) => OpenOrFocusUI());
|
|
71
|
+
itemOpen.Font = new Font(itemOpen.Font, FontStyle.Bold);
|
|
72
|
+
_trayMenu.Items.Add(itemOpen);
|
|
73
|
+
|
|
74
|
+
_trayMenu.Items.Add("Buka di Browser", null, (s, e) => OpenInDefaultBrowser());
|
|
75
|
+
_trayMenu.Items.Add("Restart Server", null, (s, e) => RestartNodeServer());
|
|
76
|
+
_trayMenu.Items.Add(new ToolStripSeparator());
|
|
77
|
+
_trayMenu.Items.Add("Keluar", null, (s, e) => ExitApplication());
|
|
78
|
+
|
|
79
|
+
_trayIcon = new NotifyIcon
|
|
80
|
+
{
|
|
81
|
+
Text = "Mark Agent",
|
|
82
|
+
ContextMenuStrip = _trayMenu,
|
|
83
|
+
Visible = true
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Load Custom Icon
|
|
87
|
+
if (File.Exists(_iconPath))
|
|
88
|
+
{
|
|
89
|
+
try
|
|
90
|
+
{
|
|
91
|
+
_trayIcon.Icon = new Icon(_iconPath);
|
|
92
|
+
}
|
|
93
|
+
catch
|
|
94
|
+
{
|
|
95
|
+
_trayIcon.Icon = SystemIcons.Application;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else
|
|
99
|
+
{
|
|
100
|
+
_trayIcon.Icon = SystemIcons.Application;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
_trayIcon.DoubleClick += (s, e) => OpenOrFocusUI();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private static void StartNodeServer()
|
|
107
|
+
{
|
|
108
|
+
try
|
|
109
|
+
{
|
|
110
|
+
// Prioritaskan node runtime lokal jika ada di folder ./node/node.exe, atau gunakan global node
|
|
111
|
+
string localNode = Path.Combine(_appDirectory, "node", "node.exe");
|
|
112
|
+
string nodeExe = File.Exists(localNode) ? localNode : "node.exe";
|
|
113
|
+
string scriptPath = Path.Combine(_appDirectory, "bin", "mark.js");
|
|
114
|
+
|
|
115
|
+
if (!File.Exists(scriptPath))
|
|
116
|
+
{
|
|
117
|
+
scriptPath = Path.Combine(_appDirectory, "src", "server", "index.js");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
ProcessStartInfo psi = new ProcessStartInfo
|
|
121
|
+
{
|
|
122
|
+
FileName = nodeExe,
|
|
123
|
+
Arguments = string.Format("\"{0}\" --headless", scriptPath),
|
|
124
|
+
WorkingDirectory = _appDirectory,
|
|
125
|
+
UseShellExecute = false,
|
|
126
|
+
CreateNoWindow = true,
|
|
127
|
+
RedirectStandardOutput = false,
|
|
128
|
+
RedirectStandardError = false
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
_nodeProcess = Process.Start(psi);
|
|
132
|
+
}
|
|
133
|
+
catch (Exception ex)
|
|
134
|
+
{
|
|
135
|
+
MessageBox.Show("Gagal menjalankan server MARK: " + ex.Message, "MARK Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private static async Task WaitForServerReadyAsync()
|
|
140
|
+
{
|
|
141
|
+
using (HttpClient client = new HttpClient())
|
|
142
|
+
{
|
|
143
|
+
client.Timeout = TimeSpan.FromSeconds(2);
|
|
144
|
+
for (int i = 0; i < 30; i++)
|
|
145
|
+
{
|
|
146
|
+
try
|
|
147
|
+
{
|
|
148
|
+
var res = await client.GetAsync(string.Format("http://localhost:{0}/api/health", ServerPort));
|
|
149
|
+
if (res.IsSuccessStatusCode) return;
|
|
150
|
+
}
|
|
151
|
+
catch
|
|
152
|
+
{
|
|
153
|
+
// Server belum siap
|
|
154
|
+
}
|
|
155
|
+
await Task.Delay(500);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private static void OpenOrFocusUI()
|
|
161
|
+
{
|
|
162
|
+
string url = string.Format("http://localhost:{0}", ServerPort);
|
|
163
|
+
string profileDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "mark-agent", "ui-profile");
|
|
164
|
+
|
|
165
|
+
try
|
|
166
|
+
{
|
|
167
|
+
// Luncurkan Microsoft Edge dalam mode App dengan profil terisolasi MARK
|
|
168
|
+
ProcessStartInfo psi = new ProcessStartInfo
|
|
169
|
+
{
|
|
170
|
+
FileName = "msedge.exe",
|
|
171
|
+
Arguments = string.Format("--app=\"{0}\" --user-data-dir=\"{1}\" --window-size=1280,800 --app-id=mark-ai-companion", url, profileDir),
|
|
172
|
+
UseShellExecute = true
|
|
173
|
+
};
|
|
174
|
+
Process.Start(psi);
|
|
175
|
+
}
|
|
176
|
+
catch
|
|
177
|
+
{
|
|
178
|
+
// Fallback ke default browser
|
|
179
|
+
OpenInDefaultBrowser();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private static void OpenInDefaultBrowser()
|
|
184
|
+
{
|
|
185
|
+
try
|
|
186
|
+
{
|
|
187
|
+
Process.Start(new ProcessStartInfo(string.Format("http://localhost:{0}", ServerPort)) { UseShellExecute = true });
|
|
188
|
+
}
|
|
189
|
+
catch { }
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private static void RestartNodeServer()
|
|
193
|
+
{
|
|
194
|
+
KillNodeProcess();
|
|
195
|
+
Thread.Sleep(500);
|
|
196
|
+
StartNodeServer();
|
|
197
|
+
_trayIcon.ShowBalloonTip(2000, "MARK AI", "Server berhasil direstart.", ToolTipIcon.Info);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private static void KillNodeProcess()
|
|
201
|
+
{
|
|
202
|
+
try
|
|
203
|
+
{
|
|
204
|
+
if (_nodeProcess != null && !_nodeProcess.HasExited)
|
|
205
|
+
{
|
|
206
|
+
_nodeProcess.Kill();
|
|
207
|
+
_nodeProcess.Dispose();
|
|
208
|
+
_nodeProcess = null;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
catch { }
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private static void ExitApplication()
|
|
215
|
+
{
|
|
216
|
+
if (_trayIcon != null)
|
|
217
|
+
{
|
|
218
|
+
_trayIcon.Visible = false;
|
|
219
|
+
_trayIcon.Dispose();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
KillNodeProcess();
|
|
223
|
+
Application.Exit();
|
|
224
|
+
Environment.Exit(0);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|