@suncreation/modu-arena 0.2.1 → 0.2.3

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/dist/index.js CHANGED
@@ -8,9 +8,11 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
8
8
 
9
9
  // src/commands.ts
10
10
  import { createInterface } from "readline";
11
- import { existsSync as existsSync5, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync, unlinkSync as unlinkSync2 } from "fs";
11
+ import { existsSync as existsSync5, readFileSync as readFileSync3, unlinkSync as unlinkSync2 } from "fs";
12
12
  import { homedir as homedir5 } from "os";
13
13
  import { basename, join as join5 } from "path";
14
+ import { createHash as createHash3 } from "crypto";
15
+ import { execSync as execSync2 } from "child_process";
14
16
 
15
17
  // src/adapters.ts
16
18
  import { existsSync, writeFileSync, mkdirSync } from "fs";
@@ -69,7 +71,9 @@ fetch(SERVER + "/api/v1/sessions", {
69
71
  method: "POST",
70
72
  headers: { "Content-Type": "application/json", "X-API-Key": API_KEY, "X-Timestamp": ts, "X-Signature": sig },
71
73
  body: body
72
- }).catch(function(){});
74
+ }).then(function(r) {
75
+ if (!r.ok) r.text().then(function(t) { process.stderr.write("[modu-arena] " + r.status + " " + t + "\\n"); });
76
+ }).catch(function(e) { process.stderr.write("[modu-arena] hook error: " + e.message + "\\n"); });
73
77
  `;
74
78
  }
75
79
  function shellWrapper() {
@@ -583,7 +587,7 @@ async function syncClaudeDesktop(apiKey) {
583
587
  modelName: session.model
584
588
  });
585
589
  const ts = Math.floor(Date.now() / 1e3).toString();
586
- const sig = createHash2("sha256").update(ts + ":" + body).update(apiKey).digest("hex");
590
+ const sig = computeHmacSignature(apiKey, ts, body);
587
591
  const res = await fetch(`${API_BASE_URL}/api/v1/sessions`, {
588
592
  method: "POST",
589
593
  headers: {
@@ -878,58 +882,6 @@ function uninstallCommand() {
878
882
  }
879
883
  console.log("\n\u2713 Modu-Arena uninstalled.\n");
880
884
  }
881
- var IGNORE_DIRS = /* @__PURE__ */ new Set([
882
- "node_modules",
883
- ".git",
884
- ".next",
885
- ".nuxt",
886
- "dist",
887
- "build",
888
- "out",
889
- ".cache",
890
- ".turbo",
891
- ".vercel",
892
- "__pycache__",
893
- ".svelte-kit",
894
- "coverage",
895
- ".output",
896
- ".parcel-cache"
897
- ]);
898
- function collectFileStructure(dir, maxDepth, currentDepth = 0) {
899
- const result = {};
900
- if (currentDepth >= maxDepth) return result;
901
- let entries;
902
- try {
903
- entries = readdirSync2(dir);
904
- } catch {
905
- return result;
906
- }
907
- const files = [];
908
- for (const entry of entries) {
909
- if (entry.startsWith(".") && IGNORE_DIRS.has(entry)) continue;
910
- if (IGNORE_DIRS.has(entry)) continue;
911
- const fullPath = join5(dir, entry);
912
- let stat;
913
- try {
914
- stat = statSync(fullPath);
915
- } catch {
916
- continue;
917
- }
918
- if (stat.isDirectory()) {
919
- const sub = collectFileStructure(fullPath, maxDepth, currentDepth + 1);
920
- for (const [key, val] of Object.entries(sub)) {
921
- result[key] = val;
922
- }
923
- } else {
924
- files.push(entry);
925
- }
926
- }
927
- if (files.length > 0) {
928
- const relDir = currentDepth === 0 ? "." : dir.split("/").slice(-currentDepth).join("/");
929
- result[relDir] = files;
930
- }
931
- return result;
932
- }
933
885
  async function submitCommand() {
934
886
  const config = requireConfig();
935
887
  console.log("\n\u{1F680} Modu-Arena \u2014 Project Submit\n");
@@ -947,17 +899,38 @@ async function submitCommand() {
947
899
  process.exit(1);
948
900
  }
949
901
  const description = descriptionRaw.length > 5e3 ? descriptionRaw.slice(0, 5e3) + "\n... (truncated)" : descriptionRaw;
902
+ const projectPathHash = sha256Hex(cwd);
903
+ const localValidationTest = extractLocalValidationTestCommand(descriptionRaw);
904
+ let localScore = 0;
905
+ let localEvaluationSummary;
906
+ if (localValidationTest) {
907
+ console.log(" Running local validation (README: ## Local Validation)...");
908
+ try {
909
+ const start = Date.now();
910
+ execSync2(localValidationTest, {
911
+ cwd,
912
+ stdio: "ignore",
913
+ timeout: 12e4,
914
+ windowsHide: true
915
+ });
916
+ localScore = 5;
917
+ localEvaluationSummary = `Ran README Local Validation test: PASS (localScore=5) in ${Date.now() - start}ms.`;
918
+ console.log(" \u2713 Local validation passed");
919
+ } catch {
920
+ localScore = 0;
921
+ localEvaluationSummary = "Ran README Local Validation test: FAIL (localScore=0).";
922
+ console.log(" \u2717 Local validation failed");
923
+ }
924
+ console.log("");
925
+ } else {
926
+ localEvaluationSummary = "No README Local Validation test block found (localScore=0).";
927
+ }
950
928
  console.log(` Project: ${projectName}`);
951
929
  console.log(` README: ${readmePath}`);
952
930
  console.log("");
953
- console.log(" Collecting file structure...");
954
- const fileStructure = collectFileStructure(cwd, 3);
955
- const fileCount = Object.values(fileStructure).reduce((sum, files) => sum + files.length, 0);
956
- console.log(` Found ${fileCount} file(s) in ${Object.keys(fileStructure).length} director${Object.keys(fileStructure).length === 1 ? "y" : "ies"}`);
957
- console.log("");
958
931
  console.log(" Submitting for evaluation...\n");
959
932
  const result = await submitEvaluation(
960
- { projectName, description, fileStructure },
933
+ { projectName, description, projectPathHash, localScore, localEvaluationSummary },
961
934
  { apiKey: config.apiKey, serverUrl: config.serverUrl }
962
935
  );
963
936
  if (!result.success) {
@@ -969,11 +942,13 @@ async function submitCommand() {
969
942
  const statusIcon = evaluation.passed ? "\u2705" : "\u274C";
970
943
  const statusText = evaluation.passed ? "PASSED" : "FAILED";
971
944
  console.log(` Result: ${statusIcon} ${statusText}`);
972
- console.log(` Total Score: ${evaluation.totalScore}/100`);
945
+ console.log(` Final Score: ${evaluation.finalScore}/10`);
946
+ console.log(` Cumulative: ${evaluation.cumulativeScoreAfter}`);
973
947
  console.log("");
974
- console.log(" Rubric Scores:");
975
- console.log(` Functionality: ${evaluation.rubricFunctionality}/50`);
976
- console.log(` Practicality: ${evaluation.rubricPracticality}/50`);
948
+ console.log(" Score Breakdown:");
949
+ console.log(` localScore: ${evaluation.localScore}/5`);
950
+ console.log(` backendScore: ${evaluation.backendScore}/5`);
951
+ console.log(` penaltyScore: ${evaluation.penaltyScore}`);
977
952
  console.log("");
978
953
  if (evaluation.feedback) {
979
954
  console.log(" Feedback:");
@@ -989,6 +964,18 @@ function formatNumber(n) {
989
964
  if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
990
965
  return n.toString();
991
966
  }
967
+ function sha256Hex(input) {
968
+ return createHash3("sha256").update(input).digest("hex");
969
+ }
970
+ function extractLocalValidationTestCommand(readme) {
971
+ const idx = readme.toLowerCase().indexOf("## local validation");
972
+ if (idx < 0) return null;
973
+ const section = readme.slice(idx);
974
+ const m = section.match(/```bash[^\n]*title\s*=\s*['"]test['"][^\n]*\n([\s\S]*?)\n```/i);
975
+ if (!m) return null;
976
+ const cmd = (m[1] || "").trim();
977
+ return cmd.length > 0 ? cmd : null;
978
+ }
992
979
  function daemonInstallCommand() {
993
980
  console.log("\n\u{1F504} Modu-Arena \u2014 Claude Desktop Daemon\n");
994
981
  if (!hasClaudeDesktopData()) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands.ts","../src/adapters.ts","../src/constants.ts","../src/crypto.ts","../src/api.ts","../src/config.ts","../src/daemon.ts","../src/claude-desktop.ts","../src/index.ts"],"sourcesContent":["/**\n * CLI Commands — install, rank, status, uninstall\n */\n\nimport { createInterface } from 'node:readline';\nimport { existsSync, readFileSync, readdirSync, statSync, unlinkSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { basename, join } from 'node:path';\nimport { getAllAdapters, type InstallResult } from './adapters.js';\nimport { getRank, registerUser, loginUser, submitEvaluation } from './api.js';\nimport { loadConfig, saveConfig, requireConfig } from './config.js';\nimport { API_BASE_URL, TOOL_DISPLAY_NAMES, type ToolType } from './constants.js';\nimport { installDaemon, uninstallDaemon, getDaemonStatus } from './daemon.js';\nimport { syncClaudeDesktop, hasClaudeDesktopData } from './claude-desktop.js';\n\nfunction prompt(question: string): Promise<string> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nfunction promptPassword(question: string): Promise<string> {\n return new Promise((resolve) => {\n process.stdout.write(question);\n const chars: string[] = [];\n const stdin = process.stdin;\n const wasRaw = stdin.isRaw;\n stdin.setRawMode(true);\n stdin.resume();\n stdin.setEncoding('utf8');\n\n const onData = (ch: string) => {\n const c = ch.toString();\n if (c === '\\n' || c === '\\r' || c === '\\u0004') {\n // Enter or Ctrl+D\n stdin.setRawMode(wasRaw ?? false);\n stdin.pause();\n stdin.removeListener('data', onData);\n process.stdout.write('\\n');\n resolve(chars.join('').trim());\n } else if (c === '\\u0003') {\n // Ctrl+C\n process.stdout.write('\\n');\n process.exit(0);\n } else if (c === '\\u007f' || c === '\\b') {\n // Backspace\n if (chars.length > 0) {\n chars.pop();\n process.stdout.write('\\b \\b');\n }\n } else {\n chars.push(c);\n process.stdout.write('*');\n }\n };\n\n stdin.on('data', onData);\n });\n}\n\n// ─── register ──────────────────────────────────────────────────────────────\n\nexport async function registerCommand(): Promise<void> {\n console.log('\\n📝 Modu-Arena — Register\\n');\n\n const username = await prompt(' Username (3-50 chars): ');\n if (!username || username.length < 3 || username.length > 50) {\n console.error('Error: Username must be between 3 and 50 characters.\\n');\n process.exit(1);\n }\n\n const password = await promptPassword(' Password (min 8 chars): ');\n if (!password || password.length < 8) {\n console.error('Error: Password must be at least 8 characters.\\n');\n process.exit(1);\n }\n\n const displayName = await prompt(' Display name (optional, press Enter to skip): ');\n\n console.log('\\n Registering...');\n\n const existing = loadConfig();\n const result = await registerUser(\n { username, password, displayName: displayName || undefined },\n existing?.serverUrl,\n );\n\n if (result.error) {\n console.error(`\\n Error: ${result.error}\\n`);\n process.exit(1);\n }\n\n if (!result.apiKey) {\n console.error('\\n Error: No API key returned from server.\\n');\n process.exit(1);\n }\n\n saveConfig({ apiKey: result.apiKey, serverUrl: existing?.serverUrl });\n console.log('\\n ✓ Registration successful!');\n console.log(` ✓ API key saved to ~/.modu-arena.json`);\n console.log(`\\n Username: ${result.user?.username}`);\n console.log(` API Key: ${result.apiKey.slice(0, 20)}...${result.apiKey.slice(-4)}`);\n console.log('\\n ⚠ Save your API key — it will not be shown again.\\n');\n\n console.log(' Installing hooks for detected AI coding tools...\\n');\n await installCommand(result.apiKey);\n}\n\n// ─── login ─────────────────────────────────────────────────────────────────\n\nexport async function loginCommand(): Promise<void> {\n console.log('\\n🔑 Modu-Arena — Login\\n');\n\n const username = await prompt(' Username: ');\n if (!username) {\n console.error('Error: Username is required.\\n');\n process.exit(1);\n }\n\n const password = await promptPassword(' Password: ');\n if (!password) {\n console.error('Error: Password is required.\\n');\n process.exit(1);\n }\n\n console.log('\\n Logging in...');\n\n const existing = loadConfig();\n const result = await loginUser({ username, password }, existing?.serverUrl);\n\n if (result.error) {\n console.error(`\\n Error: ${result.error}\\n`);\n process.exit(1);\n }\n\n if (!result.apiKey) {\n console.error('\\n Error: No API key returned from server.\\n');\n process.exit(1);\n }\n\n saveConfig({ apiKey: result.apiKey, serverUrl: existing?.serverUrl });\n console.log('\\n ✓ Login successful!');\n console.log(` ✓ API key saved to ~/.modu-arena.json`);\n console.log(`\\n Username: ${result.user?.username}`);\n console.log(` API Key: ${result.apiKey.slice(0, 20)}...${result.apiKey.slice(-4)}`);\n console.log('\\n ⚠ A new API key was generated. Previous key is now invalid.\\n');\n\n console.log(' Reinstalling hooks with new API key...\\n');\n await installCommand(result.apiKey);\n}\n\n// ─── install ───────────────────────────────────────────────────────────────\n\nexport async function installCommand(apiKey?: string): Promise<void> {\n console.log('\\n🔧 Modu-Arena — AI Coding Tool Usage Tracker\\n');\n\n // Check if already configured\n const existing = loadConfig();\n if (existing?.apiKey && !apiKey) {\n console.log('✓ Already configured.');\n console.log(' Use --api-key <key> to update your API key.\\n');\n apiKey = existing.apiKey;\n }\n\n if (!apiKey) {\n console.error(\n 'Error: API key required.\\n' +\n ' Get your API key from the Modu-Arena dashboard.\\n' +\n ' Usage: npx @suncreation/modu-arena install --api-key <your-api-key>\\n',\n );\n process.exit(1);\n }\n\n // Validate API key format\n if (!apiKey.startsWith('modu_arena_')) {\n console.error(\n 'Error: Invalid API key format. Key must start with \"modu_arena_\".\\n',\n );\n process.exit(1);\n }\n\n // Save config\n saveConfig({ apiKey });\n console.log('✓ API key saved to ~/.modu-arena.json\\n');\n\n // Detect and install hooks for each tool\n const adapters = getAllAdapters();\n const results: { tool: string; result: InstallResult }[] = [];\n\n console.log('Detecting AI coding tools...\\n');\n\n for (const adapter of adapters) {\n const detected = adapter.detect();\n if (detected) {\n console.log(` ✓ ${adapter.displayName} detected`);\n const result = adapter.install(apiKey);\n results.push({ tool: adapter.displayName, result });\n if (result.success) {\n console.log(` → Hook installed: ${result.hookPath}`);\n } else {\n console.log(` ✗ ${result.message}`);\n }\n } else {\n console.log(` - ${adapter.displayName} not found`);\n }\n }\n\n const installed = results.filter((r) => r.result.success);\n console.log(\n `\\n✓ Setup complete. ${installed.length} tool(s) configured.\\n`,\n );\n\n if (installed.length === 0) {\n console.log(\n 'No AI coding tools detected. Install one of the supported tools:\\n' +\n ' • Claude Code (https://docs.anthropic.com/s/claude-code)\\n' +\n ' • OpenCode (https://opencode.ai)\\n' +\n ' • Gemini CLI (https://github.com/google-gemini/gemini-cli)\\n' +\n ' • Codex CLI (https://github.com/openai/codex)\\n' +\n ' • Crush (https://charm.sh/crush)\\n',\n );\n }\n}\n\n// ─── rank ──────────────────────────────────────────────────────────────────\n\nexport async function rankCommand(): Promise<void> {\n const config = requireConfig();\n console.log('\\n📊 Modu-Arena — Your Stats\\n');\n\n const result = await getRank({ apiKey: config.apiKey, serverUrl: config.serverUrl });\n\n if (!result.success) {\n console.error(`Error: ${'error' in result ? result.error : 'Unknown error'}\\n`);\n process.exit(1);\n }\n\n if (!('data' in result) || !result.data) {\n console.error('Error: Unexpected response format.\\n');\n process.exit(1);\n }\n\n const { username, usage, overview } = result.data;\n\n console.log(` User: ${username}`);\n console.log(` Tokens: ${formatNumber(usage.totalTokens)}`);\n console.log(` Sessions: ${usage.totalSessions}`);\n console.log(` Projects: ${overview.successfulProjectsCount}`);\n console.log('');\n\n // Tool breakdown\n if (usage.toolBreakdown.length > 0) {\n console.log(' Tool Breakdown:');\n for (const entry of usage.toolBreakdown) {\n const name = TOOL_DISPLAY_NAMES[entry.tool as ToolType] || entry.tool;\n console.log(\n ` ${name}: ${formatNumber(entry.tokens)} tokens`,\n );\n }\n console.log('');\n }\n\n // Period stats (aggregate from daily arrays)\n const sum7 = usage.last7Days.reduce(\n (acc, d) => ({ tokens: acc.tokens + d.inputTokens + d.outputTokens, sessions: acc.sessions + d.sessions }),\n { tokens: 0, sessions: 0 },\n );\n const sum30 = usage.last30Days.reduce(\n (acc, d) => ({ tokens: acc.tokens + d.inputTokens + d.outputTokens, sessions: acc.sessions + d.sessions }),\n { tokens: 0, sessions: 0 },\n );\n console.log(\n ` Last 7 days: ${formatNumber(sum7.tokens)} tokens, ${sum7.sessions} sessions`,\n );\n console.log(\n ` Last 30 days: ${formatNumber(sum30.tokens)} tokens, ${sum30.sessions} sessions`,\n );\n console.log('');\n}\n\n// ─── status ────────────────────────────────────────────────────────────────\n\nexport function statusCommand(): void {\n const config = loadConfig();\n console.log('\\n🔍 Modu-Arena — Status\\n');\n\n if (!config?.apiKey) {\n console.log(' Status: Not configured');\n console.log(\n ' Run `npx @suncreation/modu-arena install --api-key <key>` to set up.\\n',\n );\n return;\n }\n\n const maskedKey =\n config.apiKey.slice(0, 15) + '...' + config.apiKey.slice(-4);\n console.log(` API Key: ${maskedKey}`);\n console.log(` Server: ${config.serverUrl || API_BASE_URL}`);\n console.log('');\n\n // Check installed hooks\n const adapters = getAllAdapters();\n console.log(' Installed Hooks:');\n let hookCount = 0;\n for (const adapter of adapters) {\n const detected = adapter.detect();\n if (detected) {\n const hookExists = existsSync(adapter.getHookPath());\n const status = hookExists ? '✓ Active' : '✗ Not installed';\n console.log(` ${adapter.displayName}: ${status}`);\n if (hookExists) hookCount++;\n }\n }\n if (hookCount === 0) {\n console.log(' (none)');\n }\n console.log('');\n}\n\n// ─── uninstall ─────────────────────────────────────────────────────────────\n\nexport function uninstallCommand(): void {\n console.log('\\n🗑️ Modu-Arena — Uninstall\\n');\n\n // Remove hooks\n const adapters = getAllAdapters();\n for (const adapter of adapters) {\n const hookPath = adapter.getHookPath();\n if (existsSync(hookPath)) {\n unlinkSync(hookPath);\n console.log(` ✓ Removed ${adapter.displayName} hook`);\n }\n }\n\n // Remove config\n const configPath = join(homedir(), '.modu-arena.json');\n if (existsSync(configPath)) {\n unlinkSync(configPath);\n console.log(' ✓ Removed ~/.modu-arena.json');\n }\n\n console.log('\\n✓ Modu-Arena uninstalled.\\n');\n}\n\n// ─── submit ─────────────────────────────────────────────────────────────────\n\nconst IGNORE_DIRS = new Set([\n 'node_modules', '.git', '.next', '.nuxt', 'dist', 'build', 'out',\n '.cache', '.turbo', '.vercel', '__pycache__', '.svelte-kit',\n 'coverage', '.output', '.parcel-cache',\n]);\n\nfunction collectFileStructure(\n dir: string,\n maxDepth: number,\n currentDepth = 0,\n): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n if (currentDepth >= maxDepth) return result;\n\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return result;\n }\n\n const files: string[] = [];\n for (const entry of entries) {\n if (entry.startsWith('.') && IGNORE_DIRS.has(entry)) continue;\n if (IGNORE_DIRS.has(entry)) continue;\n\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n\n if (stat.isDirectory()) {\n const sub = collectFileStructure(fullPath, maxDepth, currentDepth + 1);\n for (const [key, val] of Object.entries(sub)) {\n result[key] = val;\n }\n } else {\n files.push(entry);\n }\n }\n\n if (files.length > 0) {\n const relDir = currentDepth === 0 ? '.' : dir.split('/').slice(-(currentDepth)).join('/');\n result[relDir] = files;\n }\n\n return result;\n}\n\nexport async function submitCommand(): Promise<void> {\n const config = requireConfig();\n console.log('\\n🚀 Modu-Arena — Project Submit\\n');\n\n const cwd = process.cwd();\n const projectName = basename(cwd);\n\n const readmePath = join(cwd, 'README.md');\n if (!existsSync(readmePath)) {\n console.error('Error: README.md not found in the current directory.');\n console.error(' Please create a README.md describing your project.\\n');\n process.exit(1);\n }\n\n const descriptionRaw = readFileSync(readmePath, 'utf-8');\n if (descriptionRaw.trim().length === 0) {\n console.error('Error: README.md is empty.\\n');\n process.exit(1);\n }\n const description = descriptionRaw.length > 5000 \n ? descriptionRaw.slice(0, 5000) + '\\n... (truncated)'\n : descriptionRaw;\n\n console.log(` Project: ${projectName}`);\n console.log(` README: ${readmePath}`);\n console.log('');\n console.log(' Collecting file structure...');\n\n const fileStructure = collectFileStructure(cwd, 3);\n const fileCount = Object.values(fileStructure).reduce((sum, files) => sum + files.length, 0);\n console.log(` Found ${fileCount} file(s) in ${Object.keys(fileStructure).length} director${Object.keys(fileStructure).length === 1 ? 'y' : 'ies'}`);\n console.log('');\n console.log(' Submitting for evaluation...\\n');\n\n const result = await submitEvaluation(\n { projectName, description, fileStructure },\n { apiKey: config.apiKey, serverUrl: config.serverUrl },\n );\n\n if (!result.success) {\n console.error(`Error: ${'error' in result ? result.error : 'Unknown error'}\\n`);\n process.exit(1);\n }\n\n const { evaluation } = result;\n const statusIcon = evaluation.passed ? '✅' : '❌';\n const statusText = evaluation.passed ? 'PASSED' : 'FAILED';\n\n console.log(` Result: ${statusIcon} ${statusText}`);\n console.log(` Total Score: ${evaluation.totalScore}/100`);\n console.log('');\n console.log(' Rubric Scores:');\n console.log(` Functionality: ${evaluation.rubricFunctionality}/50`);\n console.log(` Practicality: ${evaluation.rubricPracticality}/50`);\n console.log('');\n\n if (evaluation.feedback) {\n console.log(' Feedback:');\n const lines = evaluation.feedback.split('\\n');\n for (const line of lines) {\n console.log(` ${line}`);\n }\n console.log('');\n }\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────────\n\nfunction formatNumber(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n\n// ─── daemon install ────────────────────────────────────────────────────────\n\nexport function daemonInstallCommand(): void {\n console.log('\\n🔄 Modu-Arena — Claude Desktop Daemon\\n');\n \n if (!hasClaudeDesktopData()) {\n console.log(' ✗ Claude Desktop data not found.');\n console.log(' Make sure Claude Desktop is installed and has been used.\\n');\n process.exit(1);\n }\n \n const result = installDaemon();\n \n if (result.success) {\n console.log(` ✓ ${result.message}`);\n console.log(' ✓ Daemon will sync Claude Desktop usage automatically.\\n');\n } else {\n console.error(` ✗ ${result.message}\\n`);\n process.exit(1);\n }\n}\n\n// ─── daemon uninstall ──────────────────────────────────────────────────────\n\nexport function daemonUninstallCommand(): void {\n console.log('\\n🔄 Modu-Arena — Claude Desktop Daemon\\n');\n \n const result = uninstallDaemon();\n \n if (result.success) {\n console.log(` ✓ ${result.message}\\n`);\n } else {\n console.error(` ✗ ${result.message}\\n`);\n process.exit(1);\n }\n}\n\n// ─── daemon status ─────────────────────────────────────────────────────────\n\nexport function daemonStatusCommand(): void {\n console.log('\\n🔄 Modu-Arena — Claude Desktop Daemon\\n');\n \n const status = getDaemonStatus();\n \n console.log(` Platform: ${status.platform}`);\n console.log(` Installed: ${status.installed ? 'Yes' : 'No'}`);\n if (status.installed) {\n console.log(` Sync Interval: ${Math.floor(status.interval / 60)} minutes`);\n }\n \n if (hasClaudeDesktopData()) {\n console.log(' Claude Desktop Data: Found');\n } else {\n console.log(' Claude Desktop Data: Not found');\n }\n console.log('');\n}\n\n// ─── daemon sync ───────────────────────────────────────────────────────────\n\nexport async function daemonSyncCommand(): Promise<void> {\n const config = requireConfig();\n \n if (!hasClaudeDesktopData()) {\n console.log('Claude Desktop data not found. Nothing to sync.\\n');\n return;\n }\n \n console.log('Syncing Claude Desktop usage...');\n \n const result = await syncClaudeDesktop(config.apiKey);\n \n console.log(` Synced: ${result.synced} sessions`);\n console.log(` Skipped: ${result.skipped} sessions (already synced)`);\n \n if (result.errors.length > 0) {\n console.log(` Errors: ${result.errors.length}`);\n for (const err of result.errors.slice(0, 3)) {\n console.log(` - ${err}`);\n }\n if (result.errors.length > 3) {\n console.log(` ... and ${result.errors.length - 3} more`);\n }\n }\n console.log('');\n}\n","/**\n * Tool Adapters — Cross-platform hook installation for AI coding tools.\n *\n * Generates Node.js hook scripts (works on all platforms) with\n * thin shell wrappers (.sh on Unix, .cmd on Windows).\n */\n\nimport { existsSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { API_BASE_URL, type ToolType } from './constants.js';\n\n// ─── Platform ──────────────────────────────────────────────────────────────\n\nconst IS_WIN = process.platform === 'win32';\n\n// ─── Types ─────────────────────────────────────────────────────────────────\n\nexport interface ToolAdapter {\n slug: ToolType;\n displayName: string;\n detect(): boolean;\n install(apiKey: string): InstallResult;\n getHookPath(): string;\n}\n\nexport interface InstallResult {\n success: boolean;\n message: string;\n hookPath?: string;\n}\n\ninterface EnvField {\n key: string;\n env: string;\n parse: 'string' | 'int';\n fallback: string;\n}\n\n// ─── Hook Script Generation ────────────────────────────────────────────────\n\nconst HOOK_JS = '_modu-hook.js';\n\nfunction baseFields(prefix: string): EnvField[] {\n return [\n { key: 'sessionId', env: `${prefix}_SESSION_ID`, parse: 'string', fallback: '' },\n { key: 'startedAt', env: `${prefix}_SESSION_STARTED_AT`, parse: 'string', fallback: '' },\n { key: 'inputTokens', env: `${prefix}_INPUT_TOKENS`, parse: 'int', fallback: '0' },\n { key: 'outputTokens', env: `${prefix}_OUTPUT_TOKENS`, parse: 'int', fallback: '0' },\n { key: 'modelName', env: `${prefix}_MODEL`, parse: 'string', fallback: 'unknown' },\n ];\n}\n\nfunction generateHookJs(apiKey: string, toolType: string, prefix: string, fields: EnvField[]): string {\n const lines = fields.map((f) =>\n f.parse === 'int'\n ? ` ${f.key}: parseInt(process.env[\"${f.env}\"] || \"${f.fallback}\", 10)`\n : ` ${f.key}: process.env[\"${f.env}\"] || \"${f.fallback}\"`\n );\n\n return `#!/usr/bin/env node\n\"use strict\";\nvar crypto = require(\"crypto\");\n\nvar API_KEY = ${JSON.stringify(apiKey)};\nvar SERVER = ${JSON.stringify(API_BASE_URL)};\n\nif (!process.env[\"${prefix}_SESSION_ID\"]) process.exit(0);\n\nvar body = JSON.stringify({\n toolType: ${JSON.stringify(toolType)},\n endedAt: new Date().toISOString(),\n${lines.join(\",\\n\")}\n});\n\nvar ts = Math.floor(Date.now() / 1000).toString();\nvar sig = crypto.createHmac(\"sha256\", API_KEY).update(ts + \":\" + body).digest(\"hex\");\n\nfetch(SERVER + \"/api/v1/sessions\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-API-Key\": API_KEY, \"X-Timestamp\": ts, \"X-Signature\": sig },\n body: body\n}).catch(function(){});\n`;\n}\n\nfunction shellWrapper(): string {\n return `#!/bin/bash\nexec node \"$(dirname \"$0\")/${HOOK_JS}\"\n`;\n}\n\nfunction cmdWrapper(): string {\n return `@node \"%~dp0${HOOK_JS}\" 2>nul\\r\\n`;\n}\n\n// ─── Shared Install Logic ──────────────────────────────────────────────────\n\nfunction installHook(\n displayName: string,\n hooksDir: string,\n entryPath: string,\n apiKey: string,\n toolType: string,\n prefix: string,\n fields: EnvField[],\n): InstallResult {\n try {\n if (!existsSync(hooksDir)) mkdirSync(hooksDir, { recursive: true });\n\n writeFileSync(join(hooksDir, HOOK_JS), generateHookJs(apiKey, toolType, prefix, fields), { mode: 0o755 });\n\n if (IS_WIN) {\n writeFileSync(entryPath, cmdWrapper());\n } else {\n writeFileSync(entryPath, shellWrapper(), { mode: 0o755 });\n }\n\n return { success: true, message: `${displayName} hook installed at ${entryPath}`, hookPath: entryPath };\n } catch (err) {\n return { success: false, message: `Failed to install ${displayName} hook: ${err}` };\n }\n}\n\nfunction hookEntryName(): string {\n return IS_WIN ? 'session-end.cmd' : 'session-end.sh';\n}\n\n// ─── Adapters ──────────────────────────────────────────────────────────────\n\nclass ClaudeCodeAdapter implements ToolAdapter {\n slug = 'claude-code' as const;\n displayName = 'Claude Code';\n\n private get configDir() { return join(homedir(), '.claude'); }\n private get hooksDir() { return join(this.configDir, 'hooks'); }\n\n getHookPath() { return join(this.hooksDir, hookEntryName()); }\n detect() { return existsSync(this.configDir); }\n\n install(apiKey: string) {\n return installHook(this.displayName, this.hooksDir, this.getHookPath(), apiKey, 'claude-code', 'CLAUDE',\n [\n ...baseFields('CLAUDE'),\n { key: 'cacheCreationTokens', env: 'CLAUDE_CACHE_CREATION_TOKENS', parse: 'int', fallback: '0' },\n { key: 'cacheReadTokens', env: 'CLAUDE_CACHE_READ_TOKENS', parse: 'int', fallback: '0' },\n ],\n );\n }\n}\n\nclass OpenCodeAdapter implements ToolAdapter {\n slug = 'opencode' as const;\n displayName = 'OpenCode';\n\n // OpenCode uses ~/.config/opencode on ALL platforms (including Windows)\n // It uses xdg-basedir which respects XDG_CONFIG_HOME on all platforms\n private get configDir() {\n return join(process.env.XDG_CONFIG_HOME || join(homedir(), '.config'), 'opencode');\n }\n private get hooksDir() { return join(this.configDir, 'hooks'); }\n\n getHookPath() { return join(this.hooksDir, hookEntryName()); }\n detect() { return existsSync(this.configDir); }\n\n install(apiKey: string) {\n return installHook(this.displayName, this.hooksDir, this.getHookPath(), apiKey, 'opencode', 'OPENCODE',\n baseFields('OPENCODE'),\n );\n }\n}\n\nclass SimpleAdapter implements ToolAdapter {\n constructor(\n public slug: ToolType,\n public displayName: string,\n private dirName: string,\n private envPrefix: string,\n ) {}\n\n private get configDir() { return join(homedir(), this.dirName); }\n private get hooksDir() { return join(this.configDir, 'hooks'); }\n\n getHookPath() { return join(this.hooksDir, hookEntryName()); }\n detect() { return existsSync(this.configDir); }\n\n install(apiKey: string) {\n return installHook(this.displayName, this.hooksDir, this.getHookPath(), apiKey, this.slug, this.envPrefix,\n baseFields(this.envPrefix),\n );\n }\n}\n\n// ─── Registry ──────────────────────────────────────────────────────────────\n\nexport function getAllAdapters(): ToolAdapter[] {\n return [\n new ClaudeCodeAdapter(),\n new OpenCodeAdapter(),\n new SimpleAdapter('gemini', 'Gemini CLI', '.gemini', 'GEMINI'),\n new SimpleAdapter('codex', 'Codex CLI', '.codex', 'CODEX'),\n new SimpleAdapter('crush', 'Crush', '.crush', 'CRUSH'),\n ];\n}\n\nexport function getAdapter(slug: string): ToolAdapter | undefined {\n return getAllAdapters().find((a) => a.slug === slug);\n}\n","/** Base URL for the Modu-Arena API server */\nexport const API_BASE_URL =\n process.env.MODU_ARENA_API_URL ?? 'http://backend.vibemakers.kr:23010';\n\n/** API key prefix used for all keys */\nexport const API_KEY_PREFIX = 'modu_arena_';\n\n/** Supported AI coding tools */\nexport const TOOL_TYPES = [\n 'claude-code',\n 'claude-desktop',\n 'opencode',\n 'gemini',\n 'codex',\n 'crush',\n] as const;\n\nexport type ToolType = (typeof TOOL_TYPES)[number];\n\n/** Display names for each tool */\nexport const TOOL_DISPLAY_NAMES: Record<ToolType, string> = {\n 'claude-code': 'Claude Code',\n 'claude-desktop': 'Claude Desktop',\n opencode: 'OpenCode',\n gemini: 'Gemini CLI',\n codex: 'Codex CLI',\n crush: 'Crush',\n};\n\n/** Config file name stored in user home directory */\nexport const CONFIG_FILE_NAME = '.modu-arena.json';\n\n/** Daemon state file for tracking synced sessions */\nexport const DAEMON_STATE_FILE = '.modu-arena-daemon.json';\n\n/** Minimum interval between sessions (seconds) */\nexport const MIN_SESSION_INTERVAL_SEC = 60;\n\n/** HMAC timestamp tolerance (seconds) */\nexport const HMAC_TIMESTAMP_TOLERANCE_SEC = 300;\n\n/** Daemon sync interval in seconds */\nexport const DAEMON_SYNC_INTERVAL_SEC = 300; // 5 minutes\n","import { createHmac, createHash } from 'node:crypto';\n\n/**\n * Compute HMAC-SHA256 signature for API authentication.\n *\n * message = \"{timestamp}:{bodyJsonString}\"\n * signature = HMAC-SHA256(apiKey, message).hex()\n */\nexport function computeHmacSignature(\n apiKey: string,\n timestamp: string,\n body: string,\n): string {\n const message = `${timestamp}:${body}`;\n return createHmac('sha256', apiKey).update(message).digest('hex');\n}\n\n/**\n * Compute SHA-256 session hash for integrity verification.\n *\n * data = \"{userId}:{userSalt}:{inputTokens}:{outputTokens}:{cacheCreationTokens}:{cacheReadTokens}:{modelName}:{endedAt}\"\n * hash = SHA-256(data).hex()\n */\nexport function computeSessionHash(\n userId: string,\n userSalt: string,\n inputTokens: number,\n outputTokens: number,\n cacheCreationTokens: number,\n cacheReadTokens: number,\n modelName: string,\n endedAt: string,\n): string {\n const data = `${userId}:${userSalt}:${inputTokens}:${outputTokens}:${cacheCreationTokens}:${cacheReadTokens}:${modelName}:${endedAt}`;\n return createHash('sha256').update(data).digest('hex');\n}\n","import { computeHmacSignature } from './crypto.js';\nimport { API_BASE_URL } from './constants.js';\n\nexport interface SessionPayload {\n toolType: string;\n sessionId: string;\n startedAt: string;\n endedAt: string;\n inputTokens: number;\n outputTokens: number;\n cacheCreationTokens?: number;\n cacheReadTokens?: number;\n modelName?: string;\n codeMetrics?: Record<string, unknown> | null;\n}\n\nexport interface BatchPayload {\n sessions: SessionPayload[];\n}\n\nexport interface RankResponse {\n success: boolean;\n data: {\n username: string;\n usage: {\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCacheTokens: number;\n totalTokens: number;\n totalSessions: number;\n toolBreakdown: Array<{ tool: string; tokens: number }>;\n last7Days: Array<{ date: string; inputTokens: number; outputTokens: number; sessions: number }>;\n last30Days: Array<{ date: string; inputTokens: number; outputTokens: number; sessions: number }>;\n };\n overview: {\n successfulProjectsCount: number;\n };\n lastUpdated: string;\n };\n}\n\nexport interface ApiError {\n error?: string | { code?: string; message?: string };\n}\n\ninterface RequestOptions {\n apiKey: string;\n serverUrl?: string;\n}\n\nfunction baseUrl(opts: RequestOptions): string {\n return opts.serverUrl || API_BASE_URL;\n}\n\nfunction makeAuthHeaders(\n apiKey: string,\n body?: string,\n): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-API-Key': apiKey,\n };\n\n if (body !== undefined) {\n const timestamp = Math.floor(Date.now() / 1000).toString();\n const signature = computeHmacSignature(apiKey, timestamp, body);\n headers['X-Timestamp'] = timestamp;\n headers['X-Signature'] = signature;\n }\n\n return headers;\n}\n\nexport async function submitSession(\n session: SessionPayload,\n opts: RequestOptions,\n): Promise<{ success: boolean; session?: unknown; error?: string }> {\n const body = JSON.stringify(session);\n const url = `${baseUrl(opts)}/api/v1/sessions`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: makeAuthHeaders(opts.apiKey, body),\n body,\n });\n\n const data = await res.json();\n if (!res.ok) {\n const err = (data as ApiError).error;\n const errMsg = typeof err === 'string' ? err : (err?.message || `HTTP ${res.status}`);\n return { success: false, error: errMsg };\n }\n return data as { success: boolean; session: unknown };\n}\n\nexport async function submitBatch(\n sessions: SessionPayload[],\n opts: RequestOptions,\n): Promise<{\n success: boolean;\n processed?: number;\n duplicatesSkipped?: number;\n error?: string;\n}> {\n const body = JSON.stringify({ sessions });\n const url = `${baseUrl(opts)}/api/v1/sessions/batch`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: makeAuthHeaders(opts.apiKey, body),\n body,\n });\n\n const data = await res.json();\n if (!res.ok) {\n const err = (data as ApiError).error;\n const errMsg = typeof err === 'string' ? err : (err?.message || `HTTP ${res.status}`);\n return { success: false, error: errMsg };\n }\n return data as { success: boolean; processed: number; duplicatesSkipped: number };\n}\n\nexport async function getRank(\n opts: RequestOptions,\n): Promise<RankResponse | { success: false; error: string }> {\n const url = `${baseUrl(opts)}/api/v1/rank`;\n\n const res = await fetch(url, {\n method: 'GET',\n headers: {\n 'X-API-Key': opts.apiKey,\n },\n });\n\n const data = await res.json();\n if (!res.ok) {\n const err = (data as ApiError).error;\n const errMsg = typeof err === 'string' ? err : (err?.message || `HTTP ${res.status}`);\n return { success: false, error: errMsg };\n }\n return data as RankResponse;\n}\n\n// ─── Auth ─────────────────────────────────────────────────────────────────\n\nexport interface AuthResponse {\n success: boolean;\n apiKey?: string;\n user?: { id: string; username: string; displayName?: string };\n error?: string;\n}\n\nexport async function registerUser(\n payload: { username: string; password: string; displayName?: string },\n serverUrl?: string,\n): Promise<AuthResponse> {\n const body = JSON.stringify(payload);\n const url = `${serverUrl || API_BASE_URL}/api/auth/register`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n });\n\n return (await res.json()) as AuthResponse;\n}\n\nexport async function loginUser(\n payload: { username: string; password: string },\n serverUrl?: string,\n): Promise<AuthResponse> {\n const body = JSON.stringify({ ...payload, source: 'cli' });\n const url = `${serverUrl || API_BASE_URL}/api/auth/login`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n });\n\n return (await res.json()) as AuthResponse;\n}\n\n// ─── Evaluate ─────────────────────────────────────────────────────────────\n\nexport interface EvaluatePayload {\n projectName: string;\n description: string;\n fileStructure?: Record<string, string[]>;\n}\n\nexport interface EvaluationResult {\n passed: boolean;\n totalScore: number;\n rubricFunctionality: number;\n rubricPracticality: number;\n feedback: string;\n}\n\nexport interface EvaluateResponse {\n success: true;\n evaluation: EvaluationResult;\n}\n\nexport async function submitEvaluation(\n payload: EvaluatePayload,\n opts: RequestOptions,\n): Promise<EvaluateResponse | { success: false; error: string }> {\n const body = JSON.stringify(payload);\n const url = `${baseUrl(opts)}/api/v1/evaluate`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: makeAuthHeaders(opts.apiKey, body),\n body,\n });\n\n const data = await res.json();\n if (!res.ok) {\n const err = (data as ApiError).error;\n const errMsg = typeof err === 'string' ? err : (err?.message || `HTTP ${res.status}`);\n return { success: false, error: errMsg };\n }\n return data as EvaluateResponse;\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join, dirname } from 'node:path';\nimport { CONFIG_FILE_NAME } from './constants.js';\n\nexport interface Config {\n apiKey: string;\n serverUrl?: string;\n tools?: string[];\n}\n\nfunction getConfigPath(): string {\n return join(homedir(), CONFIG_FILE_NAME);\n}\n\nexport function loadConfig(): Config | null {\n const configPath = getConfigPath();\n if (!existsSync(configPath)) return null;\n\n try {\n const raw = readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as Config;\n } catch {\n return null;\n }\n}\n\nexport function saveConfig(config: Config): void {\n const configPath = getConfigPath();\n const dir = dirname(configPath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function requireConfig(): Config {\n const config = loadConfig();\n if (!config?.apiKey) {\n console.error(\n 'Error: Not configured. Run `npx @suncreation/modu-arena install` first.',\n );\n process.exit(1);\n }\n return config;\n}\n","/**\n * Platform-specific daemon installation for Claude Desktop sync.\n * macOS: launchd (LaunchAgent)\n * Windows: Scheduled Task\n */\nimport { writeFileSync, existsSync, unlinkSync, mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { DAEMON_SYNC_INTERVAL_SEC } from './constants.js';\n\nconst IS_WIN = process.platform === 'win32';\nconst DAEMON_NAME = 'com.modu-arena.sync';\n\nfunction getDaemonLogDir(): string {\n const dir = join(homedir(), '.modu-arena', 'logs');\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n return dir;\n}\n\nfunction getNodePath(): string {\n try {\n return execSync('which node', { encoding: 'utf-8' }).trim();\n } catch {\n return 'node';\n }\n}\n\nfunction getCliPath(): string {\n return require.resolve('./index.js').replace(/index\\.js$/, 'index.js');\n}\n\nexport function installDaemon(): { success: boolean; message: string } {\n if (IS_WIN) {\n return installWindowsDaemon();\n }\n return installMacosDaemon();\n}\n\nexport function uninstallDaemon(): { success: boolean; message: string } {\n if (IS_WIN) {\n return uninstallWindowsDaemon();\n }\n return uninstallMacosDaemon();\n}\n\nexport function isDaemonInstalled(): boolean {\n if (IS_WIN) {\n try {\n execSync(`schtasks /Query /TN \"${DAEMON_NAME}\"`, { encoding: 'utf-8' });\n return true;\n } catch {\n return false;\n }\n }\n const plistPath = join(homedir(), 'Library', 'LaunchAgents', `${DAEMON_NAME}.plist`);\n return existsSync(plistPath);\n}\n\nfunction installMacosDaemon(): { success: boolean; message: string } {\n const launchAgentsDir = join(homedir(), 'Library', 'LaunchAgents');\n const plistPath = join(launchAgentsDir, `${DAEMON_NAME}.plist`);\n const logDir = getDaemonLogDir();\n const nodePath = getNodePath();\n const cliPath = getCliPath();\n \n const intervalMinutes = Math.floor(DAEMON_SYNC_INTERVAL_SEC / 60);\n \n const plist = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${DAEMON_NAME}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${nodePath}</string>\n <string>${cliPath}</string>\n <string>daemon-sync</string>\n </array>\n <key>StartInterval</key>\n <integer>${DAEMON_SYNC_INTERVAL_SEC}</integer>\n <key>StandardOutPath</key>\n <string>${logDir}/daemon.log</string>\n <key>StandardErrorPath</key>\n <string>${logDir}/daemon-error.log</string>\n <key>RunAtLoad</key>\n <true/>\n</dict>\n</plist>`;\n\n try {\n if (!existsSync(launchAgentsDir)) {\n mkdirSync(launchAgentsDir, { recursive: true });\n }\n writeFileSync(plistPath, plist);\n execSync(`launchctl load ${plistPath}`, { encoding: 'utf-8' });\n return { success: true, message: `Daemon installed. Syncs every ${intervalMinutes} minutes.` };\n } catch (e) {\n return { success: false, message: `Failed to install daemon: ${e}` };\n }\n}\n\nfunction uninstallMacosDaemon(): { success: boolean; message: string } {\n const plistPath = join(homedir(), 'Library', 'LaunchAgents', `${DAEMON_NAME}.plist`);\n \n try {\n if (existsSync(plistPath)) {\n execSync(`launchctl unload ${plistPath}`, { encoding: 'utf-8' });\n unlinkSync(plistPath);\n }\n return { success: true, message: 'Daemon uninstalled.' };\n } catch (e) {\n return { success: false, message: `Failed to uninstall daemon: ${e}` };\n }\n}\n\nfunction installWindowsDaemon(): { success: boolean; message: string } {\n const nodePath = getNodePath();\n const cliPath = getCliPath();\n const intervalMinutes = Math.floor(DAEMON_SYNC_INTERVAL_SEC / 60);\n \n try {\n const cmd = `schtasks /Create /TN \"${DAEMON_NAME}\" /TR \"\\\\\"${nodePath}\\\\\" \\\\\"${cliPath}\\\\\" daemon-sync\" /SC MINUTE /MO ${intervalMinutes} /F`;\n execSync(cmd, { encoding: 'utf-8' });\n return { success: true, message: `Daemon installed. Syncs every ${intervalMinutes} minutes.` };\n } catch (e) {\n return { success: false, message: `Failed to install daemon: ${e}` };\n }\n}\n\nfunction uninstallWindowsDaemon(): { success: boolean; message: string } {\n try {\n execSync(`schtasks /Delete /TN \"${DAEMON_NAME}\" /F`, { encoding: 'utf-8' });\n return { success: true, message: 'Daemon uninstalled.' };\n } catch (e) {\n return { success: false, message: `Failed to uninstall daemon: ${e}` };\n }\n}\n\nexport function getDaemonStatus(): { installed: boolean; platform: string; interval: number } {\n return {\n installed: isDaemonInstalled(),\n platform: IS_WIN ? 'windows' : 'macos',\n interval: DAEMON_SYNC_INTERVAL_SEC,\n };\n}\n","/**\n * Claude Desktop session parser and sync logic.\n * \n * Reads JSONL files from ~/Library/Application Support/Claude/local-agent-mode-sessions/\n * on macOS and %APPDATA%\\Claude\\local-agent-mode-sessions\\ on Windows.\n */\nimport { readdirSync, readFileSync, existsSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { API_BASE_URL, DAEMON_STATE_FILE } from './constants.js';\n\nconst IS_WIN = process.platform === 'win32';\n\ninterface UsageData {\n input_tokens: number;\n output_tokens: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n}\n\ninterface JsonlMessage {\n type: string;\n sessionId?: string;\n timestamp?: string;\n message?: {\n model?: string;\n usage?: UsageData;\n };\n}\n\ninterface SessionAggregate {\n sessionId: string;\n inputTokens: number;\n outputTokens: number;\n cacheCreationTokens: number;\n cacheReadTokens: number;\n model: string;\n startedAt: string;\n endedAt: string;\n messageCount: number;\n}\n\ninterface DaemonState {\n lastSync: string;\n syncedSessions: string[];\n}\n\nfunction getClaudeDesktopDataDir(): string {\n if (IS_WIN) {\n return join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'Claude');\n }\n return join(homedir(), 'Library', 'Application Support', 'Claude');\n}\n\nfunction getSessionDirs(): string[] {\n const dataDir = getClaudeDesktopDataDir();\n const sessionsDir = join(dataDir, 'local-agent-mode-sessions');\n if (!existsSync(sessionsDir)) return [];\n \n const orgDirs: string[] = [];\n for (const entry of readdirSync(sessionsDir, { withFileTypes: true })) {\n if (entry.isDirectory() && entry.name !== 'skills-plugin') {\n orgDirs.push(join(sessionsDir, entry.name));\n }\n }\n return orgDirs;\n}\n\nfunction findJsonlFiles(baseDir: string): string[] {\n const files: string[] = [];\n \n function walk(dir: string) {\n if (!existsSync(dir)) return;\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n walk(full);\n } else if (entry.name.endsWith('.jsonl') && !entry.name.includes('audit')) {\n files.push(full);\n }\n }\n }\n \n walk(baseDir);\n return files;\n}\n\nfunction parseJsonlFile(filePath: string): SessionAggregate | null {\n const content = readFileSync(filePath, 'utf-8');\n const lines = content.trim().split('\\n');\n \n let sessionId = '';\n let inputTokens = 0;\n let outputTokens = 0;\n let cacheCreationTokens = 0;\n let cacheReadTokens = 0;\n let model = 'unknown';\n let startedAt = '';\n let endedAt = '';\n let messageCount = 0;\n \n for (const line of lines) {\n try {\n const msg: JsonlMessage = JSON.parse(line);\n \n if (msg.sessionId && !sessionId) {\n sessionId = msg.sessionId;\n }\n \n if (msg.timestamp) {\n if (!startedAt || msg.timestamp < startedAt) {\n startedAt = msg.timestamp;\n }\n if (!endedAt || msg.timestamp > endedAt) {\n endedAt = msg.timestamp;\n }\n }\n \n if (msg.message?.usage) {\n const usage = msg.message.usage;\n inputTokens += usage.input_tokens || 0;\n outputTokens += usage.output_tokens || 0;\n cacheCreationTokens += usage.cache_creation_input_tokens || 0;\n cacheReadTokens += usage.cache_read_input_tokens || 0;\n messageCount++;\n \n if (msg.message.model) {\n model = msg.message.model;\n }\n }\n } catch {\n }\n }\n \n if (!sessionId || messageCount === 0) return null;\n \n return {\n sessionId,\n inputTokens,\n outputTokens,\n cacheCreationTokens,\n cacheReadTokens,\n model,\n startedAt,\n endedAt,\n messageCount,\n };\n}\n\nfunction getDaemonStatePath(): string {\n return join(homedir(), DAEMON_STATE_FILE);\n}\n\nfunction loadDaemonState(): DaemonState {\n const path = getDaemonStatePath();\n if (!existsSync(path)) {\n return { lastSync: new Date(0).toISOString(), syncedSessions: [] };\n }\n try {\n return JSON.parse(readFileSync(path, 'utf-8'));\n } catch {\n return { lastSync: new Date(0).toISOString(), syncedSessions: [] };\n }\n}\n\nfunction saveDaemonState(state: DaemonState): void {\n const path = getDaemonStatePath();\n writeFileSync(path, JSON.stringify(state, null, 2));\n}\n\nfunction computeSessionHash(session: SessionAggregate): string {\n const data = `${session.sessionId}:${session.inputTokens}:${session.outputTokens}:${session.endedAt}`;\n return createHash('sha256').update(data).digest('hex').substring(0, 16);\n}\n\nexport async function syncClaudeDesktop(apiKey: string): Promise<{ synced: number; skipped: number; errors: string[] }> {\n const state = loadDaemonState();\n const errors: string[] = [];\n let synced = 0;\n let skipped = 0;\n \n const sessionDirs = getSessionDirs();\n \n for (const orgDir of sessionDirs) {\n const jsonlFiles = findJsonlFiles(orgDir);\n \n for (const file of jsonlFiles) {\n const session = parseJsonlFile(file);\n if (!session) continue;\n \n const hash = computeSessionHash(session);\n if (state.syncedSessions.includes(hash)) {\n skipped++;\n continue;\n }\n \n if (session.inputTokens === 0 && session.outputTokens === 0) {\n skipped++;\n continue;\n }\n \n try {\n const body = JSON.stringify({\n toolType: 'claude-desktop',\n endedAt: session.endedAt,\n startedAt: session.startedAt,\n inputTokens: session.inputTokens,\n outputTokens: session.outputTokens,\n cacheCreationTokens: session.cacheCreationTokens,\n cacheReadTokens: session.cacheReadTokens,\n modelName: session.model,\n });\n \n const ts = Math.floor(Date.now() / 1000).toString();\n const sig = createHash('sha256')\n .update(ts + ':' + body)\n .update(apiKey)\n .digest('hex');\n \n const res = await fetch(`${API_BASE_URL}/api/v1/sessions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-API-Key': apiKey,\n 'X-Timestamp': ts,\n 'X-Signature': sig,\n },\n body,\n });\n \n if (res.ok) {\n state.syncedSessions.push(hash);\n synced++;\n } else {\n const err = await res.text();\n errors.push(`${session.sessionId}: ${err}`);\n }\n } catch (e) {\n errors.push(`${session.sessionId}: ${e}`);\n }\n }\n }\n \n state.lastSync = new Date().toISOString();\n saveDaemonState(state);\n \n return { synced, skipped, errors };\n}\n\nexport function hasClaudeDesktopData(): boolean {\n const dataDir = getClaudeDesktopDataDir();\n const sessionsDir = join(dataDir, 'local-agent-mode-sessions');\n return existsSync(sessionsDir);\n}\n\nexport function getClaudeDesktopDataPath(): string {\n return getClaudeDesktopDataDir();\n}\n","/**\n * @suncreation/modu-arena CLI\n *\n * Track and rank your AI coding tool usage.\n *\n * Usage:\n * npx @suncreation/modu-arena install --api-key <key>\n * npx @suncreation/modu-arena rank\n * npx @suncreation/modu-arena status\n * npx @suncreation/modu-arena uninstall\n */\n\nimport {\n installCommand,\n loginCommand,\n rankCommand,\n registerCommand,\n statusCommand,\n submitCommand,\n uninstallCommand,\n daemonInstallCommand,\n daemonUninstallCommand,\n daemonStatusCommand,\n daemonSyncCommand,\n} from './commands.js';\n\nconst args = process.argv.slice(2);\nconst command = args[0];\n\nfunction printHelp(): void {\n console.log(`\nModu-Arena — AI Coding Tool Usage Tracker\n\nUsage:\n npx @suncreation/modu-arena <command> [options]\n\nCommands:\n register Create a new account (interactive)\n login Log in to an existing account (interactive)\n install Set up hooks for detected AI coding tools\n rank View your current stats and ranking\n status Check configuration and installed hooks\n submit Submit current project for evaluation\n uninstall Remove all hooks and configuration\n daemon-install Install Claude Desktop sync daemon\n daemon-status Check daemon status\n daemon-sync Manually sync Claude Desktop data\n daemon-remove Remove the daemon\n\nOptions:\n --api-key <key> Your Modu-Arena API key (for install)\n --help, -h Show this help message\n --version, -v Show version\n\nExamples:\n npx @suncreation/modu-arena register\n npx @suncreation/modu-arena login\n npx @suncreation/modu-arena install --api-key modu_arena_AbCdEfGh_xxx...\n npx @suncreation/modu-arena rank\n npx @suncreation/modu-arena daemon-install\n`);\n}\n\nasync function main(): Promise<void> {\n if (!command || command === '--help' || command === '-h') {\n printHelp();\n process.exit(0);\n }\n\n if (command === '--version' || command === '-v') {\n console.log('0.1.0');\n process.exit(0);\n }\n\n switch (command) {\n case 'register':\n await registerCommand();\n break;\n case 'login':\n await loginCommand();\n break;\n case 'install': {\n const keyIndex = args.indexOf('--api-key');\n const apiKey = keyIndex >= 0 ? args[keyIndex + 1] : undefined;\n await installCommand(apiKey);\n break;\n }\n case 'rank':\n await rankCommand();\n break;\n case 'status':\n statusCommand();\n break;\n case 'submit':\n await submitCommand();\n break;\n case 'uninstall':\n uninstallCommand();\n break;\n case 'daemon-install':\n daemonInstallCommand();\n break;\n case 'daemon-uninstall':\n case 'daemon-remove':\n daemonUninstallCommand();\n break;\n case 'daemon-status':\n daemonStatusCommand();\n break;\n case 'daemon-sync':\n await daemonSyncCommand();\n break;\n default:\n console.error(`Unknown command: ${command}`);\n printHelp();\n process.exit(1);\n }\n}\n\nmain().catch((err) => {\n console.error('Fatal error:', err);\n process.exit(1);\n});\n"],"mappings":"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","names":["existsSync","readFileSync","readdirSync","unlinkSync","homedir","join","writeFileSync","existsSync","mkdirSync","homedir","join","join","homedir","existsSync","mkdirSync","writeFileSync","writeFileSync","existsSync","mkdirSync","homedir","join","IS_WIN","join","homedir","existsSync","mkdirSync","writeFileSync","readFileSync","existsSync","writeFileSync","homedir","join","createHash","IS_WIN","join","homedir","existsSync","readFileSync","writeFileSync","createHash","existsSync","unlinkSync","join","homedir","readdirSync","readFileSync"]}
1
+ {"version":3,"sources":["../src/commands.ts","../src/adapters.ts","../src/constants.ts","../src/crypto.ts","../src/api.ts","../src/config.ts","../src/daemon.ts","../src/claude-desktop.ts","../src/index.ts"],"sourcesContent":["/**\n * CLI Commands — install, rank, status, uninstall\n */\n\nimport { createInterface } from 'node:readline';\nimport { existsSync, readFileSync, unlinkSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { basename, join } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { execSync } from 'node:child_process';\nimport { getAllAdapters, type InstallResult } from './adapters.js';\nimport { getRank, registerUser, loginUser, submitEvaluation } from './api.js';\nimport { loadConfig, saveConfig, requireConfig } from './config.js';\nimport { API_BASE_URL, TOOL_DISPLAY_NAMES, type ToolType } from './constants.js';\nimport { installDaemon, uninstallDaemon, getDaemonStatus } from './daemon.js';\nimport { syncClaudeDesktop, hasClaudeDesktopData } from './claude-desktop.js';\n\nfunction prompt(question: string): Promise<string> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nfunction promptPassword(question: string): Promise<string> {\n return new Promise((resolve) => {\n process.stdout.write(question);\n const chars: string[] = [];\n const stdin = process.stdin;\n const wasRaw = stdin.isRaw;\n stdin.setRawMode(true);\n stdin.resume();\n stdin.setEncoding('utf8');\n\n const onData = (ch: string) => {\n const c = ch.toString();\n if (c === '\\n' || c === '\\r' || c === '\\u0004') {\n // Enter or Ctrl+D\n stdin.setRawMode(wasRaw ?? false);\n stdin.pause();\n stdin.removeListener('data', onData);\n process.stdout.write('\\n');\n resolve(chars.join('').trim());\n } else if (c === '\\u0003') {\n // Ctrl+C\n process.stdout.write('\\n');\n process.exit(0);\n } else if (c === '\\u007f' || c === '\\b') {\n // Backspace\n if (chars.length > 0) {\n chars.pop();\n process.stdout.write('\\b \\b');\n }\n } else {\n chars.push(c);\n process.stdout.write('*');\n }\n };\n\n stdin.on('data', onData);\n });\n}\n\n// ─── register ──────────────────────────────────────────────────────────────\n\nexport async function registerCommand(): Promise<void> {\n console.log('\\n📝 Modu-Arena — Register\\n');\n\n const username = await prompt(' Username (3-50 chars): ');\n if (!username || username.length < 3 || username.length > 50) {\n console.error('Error: Username must be between 3 and 50 characters.\\n');\n process.exit(1);\n }\n\n const password = await promptPassword(' Password (min 8 chars): ');\n if (!password || password.length < 8) {\n console.error('Error: Password must be at least 8 characters.\\n');\n process.exit(1);\n }\n\n const displayName = await prompt(' Display name (optional, press Enter to skip): ');\n\n console.log('\\n Registering...');\n\n const existing = loadConfig();\n const result = await registerUser(\n { username, password, displayName: displayName || undefined },\n existing?.serverUrl,\n );\n\n if (result.error) {\n console.error(`\\n Error: ${result.error}\\n`);\n process.exit(1);\n }\n\n if (!result.apiKey) {\n console.error('\\n Error: No API key returned from server.\\n');\n process.exit(1);\n }\n\n saveConfig({ apiKey: result.apiKey, serverUrl: existing?.serverUrl });\n console.log('\\n ✓ Registration successful!');\n console.log(` ✓ API key saved to ~/.modu-arena.json`);\n console.log(`\\n Username: ${result.user?.username}`);\n console.log(` API Key: ${result.apiKey.slice(0, 20)}...${result.apiKey.slice(-4)}`);\n console.log('\\n ⚠ Save your API key — it will not be shown again.\\n');\n\n console.log(' Installing hooks for detected AI coding tools...\\n');\n await installCommand(result.apiKey);\n}\n\n// ─── login ─────────────────────────────────────────────────────────────────\n\nexport async function loginCommand(): Promise<void> {\n console.log('\\n🔑 Modu-Arena — Login\\n');\n\n const username = await prompt(' Username: ');\n if (!username) {\n console.error('Error: Username is required.\\n');\n process.exit(1);\n }\n\n const password = await promptPassword(' Password: ');\n if (!password) {\n console.error('Error: Password is required.\\n');\n process.exit(1);\n }\n\n console.log('\\n Logging in...');\n\n const existing = loadConfig();\n const result = await loginUser({ username, password }, existing?.serverUrl);\n\n if (result.error) {\n console.error(`\\n Error: ${result.error}\\n`);\n process.exit(1);\n }\n\n if (!result.apiKey) {\n console.error('\\n Error: No API key returned from server.\\n');\n process.exit(1);\n }\n\n saveConfig({ apiKey: result.apiKey, serverUrl: existing?.serverUrl });\n console.log('\\n ✓ Login successful!');\n console.log(` ✓ API key saved to ~/.modu-arena.json`);\n console.log(`\\n Username: ${result.user?.username}`);\n console.log(` API Key: ${result.apiKey.slice(0, 20)}...${result.apiKey.slice(-4)}`);\n console.log('\\n ⚠ A new API key was generated. Previous key is now invalid.\\n');\n\n console.log(' Reinstalling hooks with new API key...\\n');\n await installCommand(result.apiKey);\n}\n\n// ─── install ───────────────────────────────────────────────────────────────\n\nexport async function installCommand(apiKey?: string): Promise<void> {\n console.log('\\n🔧 Modu-Arena — AI Coding Tool Usage Tracker\\n');\n\n // Check if already configured\n const existing = loadConfig();\n if (existing?.apiKey && !apiKey) {\n console.log('✓ Already configured.');\n console.log(' Use --api-key <key> to update your API key.\\n');\n apiKey = existing.apiKey;\n }\n\n if (!apiKey) {\n console.error(\n 'Error: API key required.\\n' +\n ' Get your API key from the Modu-Arena dashboard.\\n' +\n ' Usage: npx @suncreation/modu-arena install --api-key <your-api-key>\\n',\n );\n process.exit(1);\n }\n\n // Validate API key format\n if (!apiKey.startsWith('modu_arena_')) {\n console.error(\n 'Error: Invalid API key format. Key must start with \"modu_arena_\".\\n',\n );\n process.exit(1);\n }\n\n // Save config\n saveConfig({ apiKey });\n console.log('✓ API key saved to ~/.modu-arena.json\\n');\n\n // Detect and install hooks for each tool\n const adapters = getAllAdapters();\n const results: { tool: string; result: InstallResult }[] = [];\n\n console.log('Detecting AI coding tools...\\n');\n\n for (const adapter of adapters) {\n const detected = adapter.detect();\n if (detected) {\n console.log(` ✓ ${adapter.displayName} detected`);\n const result = adapter.install(apiKey);\n results.push({ tool: adapter.displayName, result });\n if (result.success) {\n console.log(` → Hook installed: ${result.hookPath}`);\n } else {\n console.log(` ✗ ${result.message}`);\n }\n } else {\n console.log(` - ${adapter.displayName} not found`);\n }\n }\n\n const installed = results.filter((r) => r.result.success);\n console.log(\n `\\n✓ Setup complete. ${installed.length} tool(s) configured.\\n`,\n );\n\n if (installed.length === 0) {\n console.log(\n 'No AI coding tools detected. Install one of the supported tools:\\n' +\n ' • Claude Code (https://docs.anthropic.com/s/claude-code)\\n' +\n ' • OpenCode (https://opencode.ai)\\n' +\n ' • Gemini CLI (https://github.com/google-gemini/gemini-cli)\\n' +\n ' • Codex CLI (https://github.com/openai/codex)\\n' +\n ' • Crush (https://charm.sh/crush)\\n',\n );\n }\n}\n\n// ─── rank ──────────────────────────────────────────────────────────────────\n\nexport async function rankCommand(): Promise<void> {\n const config = requireConfig();\n console.log('\\n📊 Modu-Arena — Your Stats\\n');\n\n const result = await getRank({ apiKey: config.apiKey, serverUrl: config.serverUrl });\n\n if (!result.success) {\n console.error(`Error: ${'error' in result ? result.error : 'Unknown error'}\\n`);\n process.exit(1);\n }\n\n if (!('data' in result) || !result.data) {\n console.error('Error: Unexpected response format.\\n');\n process.exit(1);\n }\n\n const { username, usage, overview } = result.data;\n\n console.log(` User: ${username}`);\n console.log(` Tokens: ${formatNumber(usage.totalTokens)}`);\n console.log(` Sessions: ${usage.totalSessions}`);\n console.log(` Projects: ${overview.successfulProjectsCount}`);\n console.log('');\n\n // Tool breakdown\n if (usage.toolBreakdown.length > 0) {\n console.log(' Tool Breakdown:');\n for (const entry of usage.toolBreakdown) {\n const name = TOOL_DISPLAY_NAMES[entry.tool as ToolType] || entry.tool;\n console.log(\n ` ${name}: ${formatNumber(entry.tokens)} tokens`,\n );\n }\n console.log('');\n }\n\n // Period stats (aggregate from daily arrays)\n const sum7 = usage.last7Days.reduce(\n (acc, d) => ({ tokens: acc.tokens + d.inputTokens + d.outputTokens, sessions: acc.sessions + d.sessions }),\n { tokens: 0, sessions: 0 },\n );\n const sum30 = usage.last30Days.reduce(\n (acc, d) => ({ tokens: acc.tokens + d.inputTokens + d.outputTokens, sessions: acc.sessions + d.sessions }),\n { tokens: 0, sessions: 0 },\n );\n console.log(\n ` Last 7 days: ${formatNumber(sum7.tokens)} tokens, ${sum7.sessions} sessions`,\n );\n console.log(\n ` Last 30 days: ${formatNumber(sum30.tokens)} tokens, ${sum30.sessions} sessions`,\n );\n console.log('');\n}\n\n// ─── status ────────────────────────────────────────────────────────────────\n\nexport function statusCommand(): void {\n const config = loadConfig();\n console.log('\\n🔍 Modu-Arena — Status\\n');\n\n if (!config?.apiKey) {\n console.log(' Status: Not configured');\n console.log(\n ' Run `npx @suncreation/modu-arena install --api-key <key>` to set up.\\n',\n );\n return;\n }\n\n const maskedKey =\n config.apiKey.slice(0, 15) + '...' + config.apiKey.slice(-4);\n console.log(` API Key: ${maskedKey}`);\n console.log(` Server: ${config.serverUrl || API_BASE_URL}`);\n console.log('');\n\n // Check installed hooks\n const adapters = getAllAdapters();\n console.log(' Installed Hooks:');\n let hookCount = 0;\n for (const adapter of adapters) {\n const detected = adapter.detect();\n if (detected) {\n const hookExists = existsSync(adapter.getHookPath());\n const status = hookExists ? '✓ Active' : '✗ Not installed';\n console.log(` ${adapter.displayName}: ${status}`);\n if (hookExists) hookCount++;\n }\n }\n if (hookCount === 0) {\n console.log(' (none)');\n }\n console.log('');\n}\n\n// ─── uninstall ─────────────────────────────────────────────────────────────\n\nexport function uninstallCommand(): void {\n console.log('\\n🗑️ Modu-Arena — Uninstall\\n');\n\n // Remove hooks\n const adapters = getAllAdapters();\n for (const adapter of adapters) {\n const hookPath = adapter.getHookPath();\n if (existsSync(hookPath)) {\n unlinkSync(hookPath);\n console.log(` ✓ Removed ${adapter.displayName} hook`);\n }\n }\n\n // Remove config\n const configPath = join(homedir(), '.modu-arena.json');\n if (existsSync(configPath)) {\n unlinkSync(configPath);\n console.log(' ✓ Removed ~/.modu-arena.json');\n }\n\n console.log('\\n✓ Modu-Arena uninstalled.\\n');\n}\n\n// ─── submit ─────────────────────────────────────────────────────────────────\n\nexport async function submitCommand(): Promise<void> {\n const config = requireConfig();\n console.log('\\n🚀 Modu-Arena — Project Submit\\n');\n\n const cwd = process.cwd();\n const projectName = basename(cwd);\n\n const readmePath = join(cwd, 'README.md');\n if (!existsSync(readmePath)) {\n console.error('Error: README.md not found in the current directory.');\n console.error(' Please create a README.md describing your project.\\n');\n process.exit(1);\n }\n\n const descriptionRaw = readFileSync(readmePath, 'utf-8');\n if (descriptionRaw.trim().length === 0) {\n console.error('Error: README.md is empty.\\n');\n process.exit(1);\n }\n const description = descriptionRaw.length > 5000 \n ? descriptionRaw.slice(0, 5000) + '\\n... (truncated)'\n : descriptionRaw;\n\n const projectPathHash = sha256Hex(cwd);\n const localValidationTest = extractLocalValidationTestCommand(descriptionRaw);\n let localScore = 0;\n let localEvaluationSummary: string | undefined;\n if (localValidationTest) {\n console.log(' Running local validation (README: ## Local Validation)...');\n try {\n const start = Date.now();\n execSync(localValidationTest, {\n cwd,\n stdio: 'ignore',\n timeout: 120000,\n windowsHide: true,\n });\n localScore = 5;\n localEvaluationSummary = `Ran README Local Validation test: PASS (localScore=5) in ${Date.now() - start}ms.`;\n console.log(' ✓ Local validation passed');\n } catch {\n localScore = 0;\n localEvaluationSummary = 'Ran README Local Validation test: FAIL (localScore=0).';\n console.log(' ✗ Local validation failed');\n }\n console.log('');\n } else {\n localEvaluationSummary = 'No README Local Validation test block found (localScore=0).';\n }\n\n console.log(` Project: ${projectName}`);\n console.log(` README: ${readmePath}`);\n console.log('');\n console.log(' Submitting for evaluation...\\n');\n\n const result = await submitEvaluation(\n { projectName, description, projectPathHash, localScore, localEvaluationSummary },\n { apiKey: config.apiKey, serverUrl: config.serverUrl },\n );\n\n if (!result.success) {\n console.error(`Error: ${'error' in result ? result.error : 'Unknown error'}\\n`);\n process.exit(1);\n }\n\n const { evaluation } = result;\n const statusIcon = evaluation.passed ? '✅' : '❌';\n const statusText = evaluation.passed ? 'PASSED' : 'FAILED';\n\n console.log(` Result: ${statusIcon} ${statusText}`);\n console.log(` Final Score: ${evaluation.finalScore}/10`);\n console.log(` Cumulative: ${evaluation.cumulativeScoreAfter}`);\n console.log('');\n console.log(' Score Breakdown:');\n console.log(` localScore: ${evaluation.localScore}/5`);\n console.log(` backendScore: ${evaluation.backendScore}/5`);\n console.log(` penaltyScore: ${evaluation.penaltyScore}`);\n console.log('');\n\n if (evaluation.feedback) {\n console.log(' Feedback:');\n const lines = evaluation.feedback.split('\\n');\n for (const line of lines) {\n console.log(` ${line}`);\n }\n console.log('');\n }\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────────\n\nfunction formatNumber(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n\nfunction sha256Hex(input: string): string {\n return createHash('sha256').update(input).digest('hex');\n}\n\nfunction extractLocalValidationTestCommand(readme: string): string | null {\n const idx = readme.toLowerCase().indexOf('## local validation');\n if (idx < 0) return null;\n const section = readme.slice(idx);\n const m = section.match(/```bash[^\\n]*title\\s*=\\s*['\"]test['\"][^\\n]*\\n([\\s\\S]*?)\\n```/i);\n if (!m) return null;\n const cmd = (m[1] || '').trim();\n return cmd.length > 0 ? cmd : null;\n}\n\n// ─── daemon install ────────────────────────────────────────────────────────\n\nexport function daemonInstallCommand(): void {\n console.log('\\n🔄 Modu-Arena — Claude Desktop Daemon\\n');\n \n if (!hasClaudeDesktopData()) {\n console.log(' ✗ Claude Desktop data not found.');\n console.log(' Make sure Claude Desktop is installed and has been used.\\n');\n process.exit(1);\n }\n \n const result = installDaemon();\n \n if (result.success) {\n console.log(` ✓ ${result.message}`);\n console.log(' ✓ Daemon will sync Claude Desktop usage automatically.\\n');\n } else {\n console.error(` ✗ ${result.message}\\n`);\n process.exit(1);\n }\n}\n\n// ─── daemon uninstall ──────────────────────────────────────────────────────\n\nexport function daemonUninstallCommand(): void {\n console.log('\\n🔄 Modu-Arena — Claude Desktop Daemon\\n');\n \n const result = uninstallDaemon();\n \n if (result.success) {\n console.log(` ✓ ${result.message}\\n`);\n } else {\n console.error(` ✗ ${result.message}\\n`);\n process.exit(1);\n }\n}\n\n// ─── daemon status ─────────────────────────────────────────────────────────\n\nexport function daemonStatusCommand(): void {\n console.log('\\n🔄 Modu-Arena — Claude Desktop Daemon\\n');\n \n const status = getDaemonStatus();\n \n console.log(` Platform: ${status.platform}`);\n console.log(` Installed: ${status.installed ? 'Yes' : 'No'}`);\n if (status.installed) {\n console.log(` Sync Interval: ${Math.floor(status.interval / 60)} minutes`);\n }\n \n if (hasClaudeDesktopData()) {\n console.log(' Claude Desktop Data: Found');\n } else {\n console.log(' Claude Desktop Data: Not found');\n }\n console.log('');\n}\n\n// ─── daemon sync ───────────────────────────────────────────────────────────\n\nexport async function daemonSyncCommand(): Promise<void> {\n const config = requireConfig();\n \n if (!hasClaudeDesktopData()) {\n console.log('Claude Desktop data not found. Nothing to sync.\\n');\n return;\n }\n \n console.log('Syncing Claude Desktop usage...');\n \n const result = await syncClaudeDesktop(config.apiKey);\n \n console.log(` Synced: ${result.synced} sessions`);\n console.log(` Skipped: ${result.skipped} sessions (already synced)`);\n \n if (result.errors.length > 0) {\n console.log(` Errors: ${result.errors.length}`);\n for (const err of result.errors.slice(0, 3)) {\n console.log(` - ${err}`);\n }\n if (result.errors.length > 3) {\n console.log(` ... and ${result.errors.length - 3} more`);\n }\n }\n console.log('');\n}\n","/**\n * Tool Adapters — Cross-platform hook installation for AI coding tools.\n *\n * Generates Node.js hook scripts (works on all platforms) with\n * thin shell wrappers (.sh on Unix, .cmd on Windows).\n */\n\nimport { existsSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { API_BASE_URL, type ToolType } from './constants.js';\n\n// ─── Platform ──────────────────────────────────────────────────────────────\n\nconst IS_WIN = process.platform === 'win32';\n\n// ─── Types ─────────────────────────────────────────────────────────────────\n\nexport interface ToolAdapter {\n slug: ToolType;\n displayName: string;\n detect(): boolean;\n install(apiKey: string): InstallResult;\n getHookPath(): string;\n}\n\nexport interface InstallResult {\n success: boolean;\n message: string;\n hookPath?: string;\n}\n\ninterface EnvField {\n key: string;\n env: string;\n parse: 'string' | 'int';\n fallback: string;\n}\n\n// ─── Hook Script Generation ────────────────────────────────────────────────\n\nconst HOOK_JS = '_modu-hook.js';\n\nfunction baseFields(prefix: string): EnvField[] {\n return [\n { key: 'sessionId', env: `${prefix}_SESSION_ID`, parse: 'string', fallback: '' },\n { key: 'startedAt', env: `${prefix}_SESSION_STARTED_AT`, parse: 'string', fallback: '' },\n { key: 'inputTokens', env: `${prefix}_INPUT_TOKENS`, parse: 'int', fallback: '0' },\n { key: 'outputTokens', env: `${prefix}_OUTPUT_TOKENS`, parse: 'int', fallback: '0' },\n { key: 'modelName', env: `${prefix}_MODEL`, parse: 'string', fallback: 'unknown' },\n ];\n}\n\nfunction generateHookJs(apiKey: string, toolType: string, prefix: string, fields: EnvField[]): string {\n const lines = fields.map((f) =>\n f.parse === 'int'\n ? ` ${f.key}: parseInt(process.env[\"${f.env}\"] || \"${f.fallback}\", 10)`\n : ` ${f.key}: process.env[\"${f.env}\"] || \"${f.fallback}\"`\n );\n\n return `#!/usr/bin/env node\n\"use strict\";\nvar crypto = require(\"crypto\");\n\nvar API_KEY = ${JSON.stringify(apiKey)};\nvar SERVER = ${JSON.stringify(API_BASE_URL)};\n\nif (!process.env[\"${prefix}_SESSION_ID\"]) process.exit(0);\n\nvar body = JSON.stringify({\n toolType: ${JSON.stringify(toolType)},\n endedAt: new Date().toISOString(),\n${lines.join(\",\\n\")}\n});\n\nvar ts = Math.floor(Date.now() / 1000).toString();\nvar sig = crypto.createHmac(\"sha256\", API_KEY).update(ts + \":\" + body).digest(\"hex\");\n\nfetch(SERVER + \"/api/v1/sessions\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"X-API-Key\": API_KEY, \"X-Timestamp\": ts, \"X-Signature\": sig },\n body: body\n}).then(function(r) {\n if (!r.ok) r.text().then(function(t) { process.stderr.write(\"[modu-arena] \" + r.status + \" \" + t + \"\\\\n\"); });\n}).catch(function(e) { process.stderr.write(\"[modu-arena] hook error: \" + e.message + \"\\\\n\"); });\n`;\n}\n\nfunction shellWrapper(): string {\n return `#!/bin/bash\nexec node \"$(dirname \"$0\")/${HOOK_JS}\"\n`;\n}\n\nfunction cmdWrapper(): string {\n return `@node \"%~dp0${HOOK_JS}\" 2>nul\\r\\n`;\n}\n\n// ─── Shared Install Logic ──────────────────────────────────────────────────\n\nfunction installHook(\n displayName: string,\n hooksDir: string,\n entryPath: string,\n apiKey: string,\n toolType: string,\n prefix: string,\n fields: EnvField[],\n): InstallResult {\n try {\n if (!existsSync(hooksDir)) mkdirSync(hooksDir, { recursive: true });\n\n writeFileSync(join(hooksDir, HOOK_JS), generateHookJs(apiKey, toolType, prefix, fields), { mode: 0o755 });\n\n if (IS_WIN) {\n writeFileSync(entryPath, cmdWrapper());\n } else {\n writeFileSync(entryPath, shellWrapper(), { mode: 0o755 });\n }\n\n return { success: true, message: `${displayName} hook installed at ${entryPath}`, hookPath: entryPath };\n } catch (err) {\n return { success: false, message: `Failed to install ${displayName} hook: ${err}` };\n }\n}\n\nfunction hookEntryName(): string {\n return IS_WIN ? 'session-end.cmd' : 'session-end.sh';\n}\n\n// ─── Adapters ──────────────────────────────────────────────────────────────\n\nclass ClaudeCodeAdapter implements ToolAdapter {\n slug = 'claude-code' as const;\n displayName = 'Claude Code';\n\n private get configDir() { return join(homedir(), '.claude'); }\n private get hooksDir() { return join(this.configDir, 'hooks'); }\n\n getHookPath() { return join(this.hooksDir, hookEntryName()); }\n detect() { return existsSync(this.configDir); }\n\n install(apiKey: string) {\n return installHook(this.displayName, this.hooksDir, this.getHookPath(), apiKey, 'claude-code', 'CLAUDE',\n [\n ...baseFields('CLAUDE'),\n { key: 'cacheCreationTokens', env: 'CLAUDE_CACHE_CREATION_TOKENS', parse: 'int', fallback: '0' },\n { key: 'cacheReadTokens', env: 'CLAUDE_CACHE_READ_TOKENS', parse: 'int', fallback: '0' },\n ],\n );\n }\n}\n\nclass OpenCodeAdapter implements ToolAdapter {\n slug = 'opencode' as const;\n displayName = 'OpenCode';\n\n // OpenCode uses ~/.config/opencode on ALL platforms (including Windows)\n // It uses xdg-basedir which respects XDG_CONFIG_HOME on all platforms\n private get configDir() {\n return join(process.env.XDG_CONFIG_HOME || join(homedir(), '.config'), 'opencode');\n }\n private get hooksDir() { return join(this.configDir, 'hooks'); }\n\n getHookPath() { return join(this.hooksDir, hookEntryName()); }\n detect() { return existsSync(this.configDir); }\n\n install(apiKey: string) {\n return installHook(this.displayName, this.hooksDir, this.getHookPath(), apiKey, 'opencode', 'OPENCODE',\n baseFields('OPENCODE'),\n );\n }\n}\n\nclass SimpleAdapter implements ToolAdapter {\n constructor(\n public slug: ToolType,\n public displayName: string,\n private dirName: string,\n private envPrefix: string,\n ) {}\n\n private get configDir() { return join(homedir(), this.dirName); }\n private get hooksDir() { return join(this.configDir, 'hooks'); }\n\n getHookPath() { return join(this.hooksDir, hookEntryName()); }\n detect() { return existsSync(this.configDir); }\n\n install(apiKey: string) {\n return installHook(this.displayName, this.hooksDir, this.getHookPath(), apiKey, this.slug, this.envPrefix,\n baseFields(this.envPrefix),\n );\n }\n}\n\n// ─── Registry ──────────────────────────────────────────────────────────────\n\nexport function getAllAdapters(): ToolAdapter[] {\n return [\n new ClaudeCodeAdapter(),\n new OpenCodeAdapter(),\n new SimpleAdapter('gemini', 'Gemini CLI', '.gemini', 'GEMINI'),\n new SimpleAdapter('codex', 'Codex CLI', '.codex', 'CODEX'),\n new SimpleAdapter('crush', 'Crush', '.crush', 'CRUSH'),\n ];\n}\n\nexport function getAdapter(slug: string): ToolAdapter | undefined {\n return getAllAdapters().find((a) => a.slug === slug);\n}\n","/** Base URL for the Modu-Arena API server */\nexport const API_BASE_URL =\n process.env.MODU_ARENA_API_URL ?? 'http://backend.vibemakers.kr:23010';\n\n/** API key prefix used for all keys */\nexport const API_KEY_PREFIX = 'modu_arena_';\n\n/** Supported AI coding tools */\nexport const TOOL_TYPES = [\n 'claude-code',\n 'claude-desktop',\n 'opencode',\n 'gemini',\n 'codex',\n 'crush',\n] as const;\n\nexport type ToolType = (typeof TOOL_TYPES)[number];\n\n/** Display names for each tool */\nexport const TOOL_DISPLAY_NAMES: Record<ToolType, string> = {\n 'claude-code': 'Claude Code',\n 'claude-desktop': 'Claude Desktop',\n opencode: 'OpenCode',\n gemini: 'Gemini CLI',\n codex: 'Codex CLI',\n crush: 'Crush',\n};\n\n/** Config file name stored in user home directory */\nexport const CONFIG_FILE_NAME = '.modu-arena.json';\n\n/** Daemon state file for tracking synced sessions */\nexport const DAEMON_STATE_FILE = '.modu-arena-daemon.json';\n\n/** Minimum interval between sessions (seconds) */\nexport const MIN_SESSION_INTERVAL_SEC = 60;\n\n/** HMAC timestamp tolerance (seconds) */\nexport const HMAC_TIMESTAMP_TOLERANCE_SEC = 300;\n\n/** Daemon sync interval in seconds */\nexport const DAEMON_SYNC_INTERVAL_SEC = 300; // 5 minutes\n","import { createHmac, createHash } from 'node:crypto';\n\n/**\n * Compute HMAC-SHA256 signature for API authentication.\n *\n * message = \"{timestamp}:{bodyJsonString}\"\n * signature = HMAC-SHA256(apiKey, message).hex()\n */\nexport function computeHmacSignature(\n apiKey: string,\n timestamp: string,\n body: string,\n): string {\n const message = `${timestamp}:${body}`;\n return createHmac('sha256', apiKey).update(message).digest('hex');\n}\n\n/**\n * Compute SHA-256 session hash for integrity verification.\n *\n * data = \"{userId}:{userSalt}:{inputTokens}:{outputTokens}:{cacheCreationTokens}:{cacheReadTokens}:{modelName}:{endedAt}\"\n * hash = SHA-256(data).hex()\n */\nexport function computeSessionHash(\n userId: string,\n userSalt: string,\n inputTokens: number,\n outputTokens: number,\n cacheCreationTokens: number,\n cacheReadTokens: number,\n modelName: string,\n endedAt: string,\n): string {\n const data = `${userId}:${userSalt}:${inputTokens}:${outputTokens}:${cacheCreationTokens}:${cacheReadTokens}:${modelName}:${endedAt}`;\n return createHash('sha256').update(data).digest('hex');\n}\n","import { computeHmacSignature } from './crypto.js';\nimport { API_BASE_URL } from './constants.js';\n\nexport interface SessionPayload {\n toolType: string;\n sessionId: string;\n startedAt: string;\n endedAt: string;\n inputTokens: number;\n outputTokens: number;\n cacheCreationTokens?: number;\n cacheReadTokens?: number;\n modelName?: string;\n codeMetrics?: Record<string, unknown> | null;\n}\n\nexport interface BatchPayload {\n sessions: SessionPayload[];\n}\n\nexport interface RankResponse {\n success: boolean;\n data: {\n username: string;\n usage: {\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCacheTokens: number;\n totalTokens: number;\n totalSessions: number;\n toolBreakdown: Array<{ tool: string; tokens: number }>;\n last7Days: Array<{ date: string; inputTokens: number; outputTokens: number; sessions: number }>;\n last30Days: Array<{ date: string; inputTokens: number; outputTokens: number; sessions: number }>;\n };\n overview: {\n successfulProjectsCount: number;\n };\n lastUpdated: string;\n };\n}\n\nexport interface ApiError {\n error?: string | { code?: string; message?: string };\n}\n\ninterface RequestOptions {\n apiKey: string;\n serverUrl?: string;\n}\n\nfunction baseUrl(opts: RequestOptions): string {\n return opts.serverUrl || API_BASE_URL;\n}\n\nfunction makeAuthHeaders(\n apiKey: string,\n body?: string,\n): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-API-Key': apiKey,\n };\n\n if (body !== undefined) {\n const timestamp = Math.floor(Date.now() / 1000).toString();\n const signature = computeHmacSignature(apiKey, timestamp, body);\n headers['X-Timestamp'] = timestamp;\n headers['X-Signature'] = signature;\n }\n\n return headers;\n}\n\nexport async function submitSession(\n session: SessionPayload,\n opts: RequestOptions,\n): Promise<{ success: boolean; session?: unknown; error?: string }> {\n const body = JSON.stringify(session);\n const url = `${baseUrl(opts)}/api/v1/sessions`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: makeAuthHeaders(opts.apiKey, body),\n body,\n });\n\n const data = await res.json();\n if (!res.ok) {\n const err = (data as ApiError).error;\n const errMsg = typeof err === 'string' ? err : (err?.message || `HTTP ${res.status}`);\n return { success: false, error: errMsg };\n }\n return data as { success: boolean; session: unknown };\n}\n\nexport async function submitBatch(\n sessions: SessionPayload[],\n opts: RequestOptions,\n): Promise<{\n success: boolean;\n processed?: number;\n duplicatesSkipped?: number;\n error?: string;\n}> {\n const body = JSON.stringify({ sessions });\n const url = `${baseUrl(opts)}/api/v1/sessions/batch`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: makeAuthHeaders(opts.apiKey, body),\n body,\n });\n\n const data = await res.json();\n if (!res.ok) {\n const err = (data as ApiError).error;\n const errMsg = typeof err === 'string' ? err : (err?.message || `HTTP ${res.status}`);\n return { success: false, error: errMsg };\n }\n return data as { success: boolean; processed: number; duplicatesSkipped: number };\n}\n\nexport async function getRank(\n opts: RequestOptions,\n): Promise<RankResponse | { success: false; error: string }> {\n const url = `${baseUrl(opts)}/api/v1/rank`;\n\n const res = await fetch(url, {\n method: 'GET',\n headers: {\n 'X-API-Key': opts.apiKey,\n },\n });\n\n const data = await res.json();\n if (!res.ok) {\n const err = (data as ApiError).error;\n const errMsg = typeof err === 'string' ? err : (err?.message || `HTTP ${res.status}`);\n return { success: false, error: errMsg };\n }\n return data as RankResponse;\n}\n\n// ─── Auth ─────────────────────────────────────────────────────────────────\n\nexport interface AuthResponse {\n success: boolean;\n apiKey?: string;\n user?: { id: string; username: string; displayName?: string };\n error?: string;\n}\n\nexport async function registerUser(\n payload: { username: string; password: string; displayName?: string },\n serverUrl?: string,\n): Promise<AuthResponse> {\n const body = JSON.stringify(payload);\n const url = `${serverUrl || API_BASE_URL}/api/auth/register`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n });\n\n return (await res.json()) as AuthResponse;\n}\n\nexport async function loginUser(\n payload: { username: string; password: string },\n serverUrl?: string,\n): Promise<AuthResponse> {\n const body = JSON.stringify({ ...payload, source: 'cli' });\n const url = `${serverUrl || API_BASE_URL}/api/auth/login`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n });\n\n return (await res.json()) as AuthResponse;\n}\n\n// ─── Evaluate ─────────────────────────────────────────────────────────────\n\nexport interface EvaluatePayload {\n projectName: string;\n description: string;\n fileStructure?: Record<string, string[]>;\n projectPathHash?: string;\n localScore?: number;\n localEvaluationSummary?: string;\n}\n\nexport interface EvaluationResult {\n passed: boolean;\n projectName: string;\n projectPathHash: string;\n localScore: number;\n backendScore: number;\n penaltyScore: number;\n finalScore: number;\n cumulativeScoreAfter: number;\n feedback: string;\n evaluatedAt: string;\n}\n\nexport interface EvaluateResponse {\n success: true;\n evaluation: EvaluationResult;\n}\n\nexport async function submitEvaluation(\n payload: EvaluatePayload,\n opts: RequestOptions,\n): Promise<EvaluateResponse | { success: false; error: string }> {\n const body = JSON.stringify(payload);\n const url = `${baseUrl(opts)}/api/v1/evaluate`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: makeAuthHeaders(opts.apiKey, body),\n body,\n });\n\n const data = await res.json();\n if (!res.ok) {\n const err = (data as ApiError).error;\n const errMsg = typeof err === 'string' ? err : (err?.message || `HTTP ${res.status}`);\n return { success: false, error: errMsg };\n }\n return data as EvaluateResponse;\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join, dirname } from 'node:path';\nimport { CONFIG_FILE_NAME } from './constants.js';\n\nexport interface Config {\n apiKey: string;\n serverUrl?: string;\n tools?: string[];\n}\n\nfunction getConfigPath(): string {\n return join(homedir(), CONFIG_FILE_NAME);\n}\n\nexport function loadConfig(): Config | null {\n const configPath = getConfigPath();\n if (!existsSync(configPath)) return null;\n\n try {\n const raw = readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as Config;\n } catch {\n return null;\n }\n}\n\nexport function saveConfig(config: Config): void {\n const configPath = getConfigPath();\n const dir = dirname(configPath);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function requireConfig(): Config {\n const config = loadConfig();\n if (!config?.apiKey) {\n console.error(\n 'Error: Not configured. Run `npx @suncreation/modu-arena install` first.',\n );\n process.exit(1);\n }\n return config;\n}\n","/**\n * Platform-specific daemon installation for Claude Desktop sync.\n * macOS: launchd (LaunchAgent)\n * Windows: Scheduled Task\n */\nimport { writeFileSync, existsSync, unlinkSync, mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { DAEMON_SYNC_INTERVAL_SEC } from './constants.js';\n\nconst IS_WIN = process.platform === 'win32';\nconst DAEMON_NAME = 'com.modu-arena.sync';\n\nfunction getDaemonLogDir(): string {\n const dir = join(homedir(), '.modu-arena', 'logs');\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n return dir;\n}\n\nfunction getNodePath(): string {\n try {\n return execSync('which node', { encoding: 'utf-8' }).trim();\n } catch {\n return 'node';\n }\n}\n\nfunction getCliPath(): string {\n return require.resolve('./index.js').replace(/index\\.js$/, 'index.js');\n}\n\nexport function installDaemon(): { success: boolean; message: string } {\n if (IS_WIN) {\n return installWindowsDaemon();\n }\n return installMacosDaemon();\n}\n\nexport function uninstallDaemon(): { success: boolean; message: string } {\n if (IS_WIN) {\n return uninstallWindowsDaemon();\n }\n return uninstallMacosDaemon();\n}\n\nexport function isDaemonInstalled(): boolean {\n if (IS_WIN) {\n try {\n execSync(`schtasks /Query /TN \"${DAEMON_NAME}\"`, { encoding: 'utf-8' });\n return true;\n } catch {\n return false;\n }\n }\n const plistPath = join(homedir(), 'Library', 'LaunchAgents', `${DAEMON_NAME}.plist`);\n return existsSync(plistPath);\n}\n\nfunction installMacosDaemon(): { success: boolean; message: string } {\n const launchAgentsDir = join(homedir(), 'Library', 'LaunchAgents');\n const plistPath = join(launchAgentsDir, `${DAEMON_NAME}.plist`);\n const logDir = getDaemonLogDir();\n const nodePath = getNodePath();\n const cliPath = getCliPath();\n \n const intervalMinutes = Math.floor(DAEMON_SYNC_INTERVAL_SEC / 60);\n \n const plist = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${DAEMON_NAME}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${nodePath}</string>\n <string>${cliPath}</string>\n <string>daemon-sync</string>\n </array>\n <key>StartInterval</key>\n <integer>${DAEMON_SYNC_INTERVAL_SEC}</integer>\n <key>StandardOutPath</key>\n <string>${logDir}/daemon.log</string>\n <key>StandardErrorPath</key>\n <string>${logDir}/daemon-error.log</string>\n <key>RunAtLoad</key>\n <true/>\n</dict>\n</plist>`;\n\n try {\n if (!existsSync(launchAgentsDir)) {\n mkdirSync(launchAgentsDir, { recursive: true });\n }\n writeFileSync(plistPath, plist);\n execSync(`launchctl load ${plistPath}`, { encoding: 'utf-8' });\n return { success: true, message: `Daemon installed. Syncs every ${intervalMinutes} minutes.` };\n } catch (e) {\n return { success: false, message: `Failed to install daemon: ${e}` };\n }\n}\n\nfunction uninstallMacosDaemon(): { success: boolean; message: string } {\n const plistPath = join(homedir(), 'Library', 'LaunchAgents', `${DAEMON_NAME}.plist`);\n \n try {\n if (existsSync(plistPath)) {\n execSync(`launchctl unload ${plistPath}`, { encoding: 'utf-8' });\n unlinkSync(plistPath);\n }\n return { success: true, message: 'Daemon uninstalled.' };\n } catch (e) {\n return { success: false, message: `Failed to uninstall daemon: ${e}` };\n }\n}\n\nfunction installWindowsDaemon(): { success: boolean; message: string } {\n const nodePath = getNodePath();\n const cliPath = getCliPath();\n const intervalMinutes = Math.floor(DAEMON_SYNC_INTERVAL_SEC / 60);\n \n try {\n const cmd = `schtasks /Create /TN \"${DAEMON_NAME}\" /TR \"\\\\\"${nodePath}\\\\\" \\\\\"${cliPath}\\\\\" daemon-sync\" /SC MINUTE /MO ${intervalMinutes} /F`;\n execSync(cmd, { encoding: 'utf-8' });\n return { success: true, message: `Daemon installed. Syncs every ${intervalMinutes} minutes.` };\n } catch (e) {\n return { success: false, message: `Failed to install daemon: ${e}` };\n }\n}\n\nfunction uninstallWindowsDaemon(): { success: boolean; message: string } {\n try {\n execSync(`schtasks /Delete /TN \"${DAEMON_NAME}\" /F`, { encoding: 'utf-8' });\n return { success: true, message: 'Daemon uninstalled.' };\n } catch (e) {\n return { success: false, message: `Failed to uninstall daemon: ${e}` };\n }\n}\n\nexport function getDaemonStatus(): { installed: boolean; platform: string; interval: number } {\n return {\n installed: isDaemonInstalled(),\n platform: IS_WIN ? 'windows' : 'macos',\n interval: DAEMON_SYNC_INTERVAL_SEC,\n };\n}\n","/**\n * Claude Desktop session parser and sync logic.\n * \n * Reads JSONL files from ~/Library/Application Support/Claude/local-agent-mode-sessions/\n * on macOS and %APPDATA%\\Claude\\local-agent-mode-sessions\\ on Windows.\n */\nimport { readdirSync, readFileSync, existsSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { API_BASE_URL, DAEMON_STATE_FILE } from './constants.js';\nimport { computeHmacSignature } from './crypto.js';\n\nconst IS_WIN = process.platform === 'win32';\n\ninterface UsageData {\n input_tokens: number;\n output_tokens: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n}\n\ninterface JsonlMessage {\n type: string;\n sessionId?: string;\n timestamp?: string;\n message?: {\n model?: string;\n usage?: UsageData;\n };\n}\n\ninterface SessionAggregate {\n sessionId: string;\n inputTokens: number;\n outputTokens: number;\n cacheCreationTokens: number;\n cacheReadTokens: number;\n model: string;\n startedAt: string;\n endedAt: string;\n messageCount: number;\n}\n\ninterface DaemonState {\n lastSync: string;\n syncedSessions: string[];\n}\n\nfunction getClaudeDesktopDataDir(): string {\n if (IS_WIN) {\n return join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'Claude');\n }\n return join(homedir(), 'Library', 'Application Support', 'Claude');\n}\n\nfunction getSessionDirs(): string[] {\n const dataDir = getClaudeDesktopDataDir();\n const sessionsDir = join(dataDir, 'local-agent-mode-sessions');\n if (!existsSync(sessionsDir)) return [];\n \n const orgDirs: string[] = [];\n for (const entry of readdirSync(sessionsDir, { withFileTypes: true })) {\n if (entry.isDirectory() && entry.name !== 'skills-plugin') {\n orgDirs.push(join(sessionsDir, entry.name));\n }\n }\n return orgDirs;\n}\n\nfunction findJsonlFiles(baseDir: string): string[] {\n const files: string[] = [];\n \n function walk(dir: string) {\n if (!existsSync(dir)) return;\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n walk(full);\n } else if (entry.name.endsWith('.jsonl') && !entry.name.includes('audit')) {\n files.push(full);\n }\n }\n }\n \n walk(baseDir);\n return files;\n}\n\nfunction parseJsonlFile(filePath: string): SessionAggregate | null {\n const content = readFileSync(filePath, 'utf-8');\n const lines = content.trim().split('\\n');\n \n let sessionId = '';\n let inputTokens = 0;\n let outputTokens = 0;\n let cacheCreationTokens = 0;\n let cacheReadTokens = 0;\n let model = 'unknown';\n let startedAt = '';\n let endedAt = '';\n let messageCount = 0;\n \n for (const line of lines) {\n try {\n const msg: JsonlMessage = JSON.parse(line);\n \n if (msg.sessionId && !sessionId) {\n sessionId = msg.sessionId;\n }\n \n if (msg.timestamp) {\n if (!startedAt || msg.timestamp < startedAt) {\n startedAt = msg.timestamp;\n }\n if (!endedAt || msg.timestamp > endedAt) {\n endedAt = msg.timestamp;\n }\n }\n \n if (msg.message?.usage) {\n const usage = msg.message.usage;\n inputTokens += usage.input_tokens || 0;\n outputTokens += usage.output_tokens || 0;\n cacheCreationTokens += usage.cache_creation_input_tokens || 0;\n cacheReadTokens += usage.cache_read_input_tokens || 0;\n messageCount++;\n \n if (msg.message.model) {\n model = msg.message.model;\n }\n }\n } catch {\n }\n }\n \n if (!sessionId || messageCount === 0) return null;\n \n return {\n sessionId,\n inputTokens,\n outputTokens,\n cacheCreationTokens,\n cacheReadTokens,\n model,\n startedAt,\n endedAt,\n messageCount,\n };\n}\n\nfunction getDaemonStatePath(): string {\n return join(homedir(), DAEMON_STATE_FILE);\n}\n\nfunction loadDaemonState(): DaemonState {\n const path = getDaemonStatePath();\n if (!existsSync(path)) {\n return { lastSync: new Date(0).toISOString(), syncedSessions: [] };\n }\n try {\n return JSON.parse(readFileSync(path, 'utf-8'));\n } catch {\n return { lastSync: new Date(0).toISOString(), syncedSessions: [] };\n }\n}\n\nfunction saveDaemonState(state: DaemonState): void {\n const path = getDaemonStatePath();\n writeFileSync(path, JSON.stringify(state, null, 2));\n}\n\nfunction computeSessionHash(session: SessionAggregate): string {\n const data = `${session.sessionId}:${session.inputTokens}:${session.outputTokens}:${session.endedAt}`;\n return createHash('sha256').update(data).digest('hex').substring(0, 16);\n}\n\nexport async function syncClaudeDesktop(apiKey: string): Promise<{ synced: number; skipped: number; errors: string[] }> {\n const state = loadDaemonState();\n const errors: string[] = [];\n let synced = 0;\n let skipped = 0;\n \n const sessionDirs = getSessionDirs();\n \n for (const orgDir of sessionDirs) {\n const jsonlFiles = findJsonlFiles(orgDir);\n \n for (const file of jsonlFiles) {\n const session = parseJsonlFile(file);\n if (!session) continue;\n \n const hash = computeSessionHash(session);\n if (state.syncedSessions.includes(hash)) {\n skipped++;\n continue;\n }\n \n if (session.inputTokens === 0 && session.outputTokens === 0) {\n skipped++;\n continue;\n }\n \n try {\n const body = JSON.stringify({\n toolType: 'claude-desktop',\n endedAt: session.endedAt,\n startedAt: session.startedAt,\n inputTokens: session.inputTokens,\n outputTokens: session.outputTokens,\n cacheCreationTokens: session.cacheCreationTokens,\n cacheReadTokens: session.cacheReadTokens,\n modelName: session.model,\n });\n \n const ts = Math.floor(Date.now() / 1000).toString();\n const sig = computeHmacSignature(apiKey, ts, body);\n \n const res = await fetch(`${API_BASE_URL}/api/v1/sessions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-API-Key': apiKey,\n 'X-Timestamp': ts,\n 'X-Signature': sig,\n },\n body,\n });\n \n if (res.ok) {\n state.syncedSessions.push(hash);\n synced++;\n } else {\n const err = await res.text();\n errors.push(`${session.sessionId}: ${err}`);\n }\n } catch (e) {\n errors.push(`${session.sessionId}: ${e}`);\n }\n }\n }\n \n state.lastSync = new Date().toISOString();\n saveDaemonState(state);\n \n return { synced, skipped, errors };\n}\n\nexport function hasClaudeDesktopData(): boolean {\n const dataDir = getClaudeDesktopDataDir();\n const sessionsDir = join(dataDir, 'local-agent-mode-sessions');\n return existsSync(sessionsDir);\n}\n\nexport function getClaudeDesktopDataPath(): string {\n return getClaudeDesktopDataDir();\n}\n","/**\n * @suncreation/modu-arena CLI\n *\n * Track and rank your AI coding tool usage.\n *\n * Usage:\n * npx @suncreation/modu-arena install --api-key <key>\n * npx @suncreation/modu-arena rank\n * npx @suncreation/modu-arena status\n * npx @suncreation/modu-arena uninstall\n */\n\nimport {\n installCommand,\n loginCommand,\n rankCommand,\n registerCommand,\n statusCommand,\n submitCommand,\n uninstallCommand,\n daemonInstallCommand,\n daemonUninstallCommand,\n daemonStatusCommand,\n daemonSyncCommand,\n} from './commands.js';\n\nconst args = process.argv.slice(2);\nconst command = args[0];\n\nfunction printHelp(): void {\n console.log(`\nModu-Arena — AI Coding Tool Usage Tracker\n\nUsage:\n npx @suncreation/modu-arena <command> [options]\n\nCommands:\n register Create a new account (interactive)\n login Log in to an existing account (interactive)\n install Set up hooks for detected AI coding tools\n rank View your current stats and ranking\n status Check configuration and installed hooks\n submit Submit current project for evaluation\n uninstall Remove all hooks and configuration\n daemon-install Install Claude Desktop sync daemon\n daemon-status Check daemon status\n daemon-sync Manually sync Claude Desktop data\n daemon-remove Remove the daemon\n\nOptions:\n --api-key <key> Your Modu-Arena API key (for install)\n --help, -h Show this help message\n --version, -v Show version\n\nExamples:\n npx @suncreation/modu-arena register\n npx @suncreation/modu-arena login\n npx @suncreation/modu-arena install --api-key modu_arena_AbCdEfGh_xxx...\n npx @suncreation/modu-arena rank\n npx @suncreation/modu-arena daemon-install\n`);\n}\n\nasync function main(): Promise<void> {\n if (!command || command === '--help' || command === '-h') {\n printHelp();\n process.exit(0);\n }\n\n if (command === '--version' || command === '-v') {\n console.log('0.1.0');\n process.exit(0);\n }\n\n switch (command) {\n case 'register':\n await registerCommand();\n break;\n case 'login':\n await loginCommand();\n break;\n case 'install': {\n const keyIndex = args.indexOf('--api-key');\n const apiKey = keyIndex >= 0 ? args[keyIndex + 1] : undefined;\n await installCommand(apiKey);\n break;\n }\n case 'rank':\n await rankCommand();\n break;\n case 'status':\n statusCommand();\n break;\n case 'submit':\n await submitCommand();\n break;\n case 'uninstall':\n uninstallCommand();\n break;\n case 'daemon-install':\n daemonInstallCommand();\n break;\n case 'daemon-uninstall':\n case 'daemon-remove':\n daemonUninstallCommand();\n break;\n case 'daemon-status':\n daemonStatusCommand();\n break;\n case 'daemon-sync':\n await daemonSyncCommand();\n break;\n default:\n console.error(`Unknown command: ${command}`);\n printHelp();\n process.exit(1);\n }\n}\n\nmain().catch((err) => {\n console.error('Fatal error:', err);\n process.exit(1);\n});\n"],"mappings":"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","names":["existsSync","readFileSync","unlinkSync","homedir","join","createHash","execSync","writeFileSync","existsSync","mkdirSync","homedir","join","join","homedir","existsSync","mkdirSync","writeFileSync","writeFileSync","existsSync","mkdirSync","homedir","join","IS_WIN","join","homedir","existsSync","mkdirSync","writeFileSync","readFileSync","existsSync","writeFileSync","homedir","join","createHash","IS_WIN","join","homedir","existsSync","readFileSync","writeFileSync","createHash","existsSync","unlinkSync","join","homedir","readFileSync","execSync","createHash"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suncreation/modu-arena",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "description": "Track and rank your AI coding tool usage across Claude Code, Claude Desktop, OpenCode, Gemini CLI, Codex CLI, and Crush",
6
6
  "bin": {
@@ -22,6 +22,7 @@
22
22
  "devDependencies": {
23
23
  "@biomejs/biome": "2.3.10",
24
24
  "@types/node": "^20",
25
+ "bun-types": "^1.3.9",
25
26
  "tsup": "^8.4.0",
26
27
  "typescript": "^5.7.3"
27
28
  },