@suncreation/modu-arena 0.2.4 → 0.2.5

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.
@@ -0,0 +1,20 @@
1
+ ---
2
+ description: Collect structured feedback and convert into SPEC or fix plan
3
+ argument-hint: <feedback> [...]
4
+ allowed-tools: Task, Read, Grep, Glob, Edit, Write
5
+ ---
6
+
7
+ # /modu:feedback
8
+
9
+ Goal: turn feedback into actionable next steps.
10
+
11
+ Must do:
12
+
13
+ - Read `.modu-arena/development-plan.md`.
14
+ - If feedback implies a feature/change, propose a SPEC folder under `.modu-arena/specs/`.
15
+ - If feedback is a bug, propose `/modu:fix` steps.
16
+
17
+ Output requirements:
18
+
19
+ - Short plan + next command suggestion.
20
+ - End with `state: ulw`.
@@ -0,0 +1,20 @@
1
+ ---
2
+ description: Targeted fix workflow (minimal change, verify, report)
3
+ argument-hint: <symptom> [...]
4
+ allowed-tools: Task, Read, Grep, Glob, Bash, Edit, Write
5
+ ---
6
+
7
+ # /modu:fix
8
+
9
+ Goal: apply a minimal, behavior-correct fix.
10
+
11
+ Must do:
12
+
13
+ - Identify the failing surface area (error message, endpoint, file path).
14
+ - Fix root cause with minimal diff.
15
+ - Re-verify (type-check/build/tests) and report evidence.
16
+
17
+ Output requirements:
18
+
19
+ - 3 bullets: cause, fix, verification.
20
+ - End with `state: ulw`.
@@ -0,0 +1,20 @@
1
+ ---
2
+ description: Run iterative fix/verify loop until acceptance criteria are met
3
+ argument-hint: <goal> [...]
4
+ allowed-tools: Task, Read, Grep, Glob, Bash, Edit, Write
5
+ ---
6
+
7
+ # /modu:loop
8
+
9
+ Goal: iterate until the requested acceptance criteria are satisfied.
10
+
11
+ Must do:
12
+
13
+ - Start by reading `.modu-arena/development-plan.md` and the relevant SPEC acceptance criteria.
14
+ - Operate in a tight loop: observe -> change -> verify -> repeat.
15
+ - Stop if blocked and ask exactly one clarifying question.
16
+
17
+ Output requirements:
18
+
19
+ - Report final verification evidence.
20
+ - End with `state: ulw`.
@@ -0,0 +1,23 @@
1
+ ---
2
+ description: Create or refine SPEC using EARS + acceptance criteria (doc-first)
3
+ argument-hint: <topic> [...]
4
+ allowed-tools: Task, Read, Grep, Glob, Edit, Write
5
+ ---
6
+
7
+ # /modu:plan
8
+
9
+ Goal: create or refine a SPEC folder under `.modu-arena/specs/SPEC-*/`.
10
+
11
+ Must do:
12
+
13
+ - Read `.modu-arena/development-plan.md`.
14
+ - If a SPEC is referenced, read all 3 files:
15
+ - `.modu-arena/specs/<SPEC-ID>/spec.md`
16
+ - `.modu-arena/specs/<SPEC-ID>/plan.md`
17
+ - `.modu-arena/specs/<SPEC-ID>/acceptance.md`
18
+ - Keep requirements in EARS style and keep acceptance criteria testable.
19
+
20
+ Output requirements:
21
+
22
+ - Provide: what SPEC(s) were created/updated + next command suggestion.
23
+ - End with `state: ulw`.
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: Analyze repo and generate/refresh project docs used by SPEC workflow
3
+ argument-hint: [notes]
4
+ allowed-tools: Task, Read, Grep, Glob, Bash, Edit, Write
5
+ ---
6
+
7
+ # /modu:project
8
+
9
+ Goal: ensure project documentation exists and is current so later `/modu:plan` can reference it.
10
+
11
+ Must do:
12
+
13
+ - Read `.modu-arena/development-plan.md` first.
14
+ - Update or create the minimum docs needed by the plan (keep it brief):
15
+ - `.modu-arena/development-plan.md` (entry point)
16
+ - Any missing files under `.modu-arena/specs/` required by current work
17
+
18
+ Output requirements:
19
+
20
+ - Short checklist of what changed.
21
+ - End with `state: ulw`.
@@ -0,0 +1,20 @@
1
+ ---
2
+ description: Implement work described in SPEC (behavior-preserving when refactoring)
3
+ argument-hint: <SPEC-ID>
4
+ allowed-tools: Task, Read, Grep, Glob, Bash, Edit, Write
5
+ ---
6
+
7
+ # /modu:run
8
+
9
+ Goal: implement the referenced SPEC.
10
+
11
+ Must do:
12
+
13
+ - Read `.modu-arena/specs/<SPEC-ID>/{spec.md,plan.md,acceptance.md}`.
14
+ - Implement ONLY what the SPEC requires.
15
+ - Verify with appropriate checks (at least type-check/build/tests if available).
16
+
17
+ Output requirements:
18
+
19
+ - Short list: what changed + what was verified.
20
+ - End with `state: ulw`.
@@ -0,0 +1,169 @@
1
+ ---
2
+ description: Evaluate current project (local run) + README-only remote scoring
3
+ argument-hint: [project-path]
4
+ allowed-tools: Bash, Read, Grep, Glob
5
+ ---
6
+
7
+ # /modu:submit
8
+
9
+ Goal: submit a project for evaluation using README.md as the source of truth.
10
+
11
+ Hard rules:
12
+
13
+ - Read `.modu-arena/development-plan.md` first.
14
+ - Local evaluation MUST run using README `## Local Validation` -> `bash title="test"` (if present):
15
+ - If test succeeds: localScore=5
16
+ - If test fails or missing: localScore=0
17
+ - Remote evaluation MUST use README content only (do NOT send code; avoid sending fileStructure).
18
+
19
+ Behavior:
20
+
21
+ 1. Determine project path:
22
+ - If an argument is provided, use it.
23
+ - Otherwise, use the current working directory.
24
+ 2. Read `<project>/README.md` and use its contents as `description` (truncate to 5000 chars).
25
+ 3. Compute `projectName` from the directory name.
26
+ 4. Compute `projectPathHash = sha256(<absolute project path>)`.
27
+ 5. Load API key and server URL:
28
+ - From `~/.modu-arena.json` (apiKey + optional serverUrl), or
29
+ - From `MODU_ARENA_API_URL` env var override.
30
+ 6. Call `POST /api/v1/evaluate` with API key + HMAC auth.
31
+ - Body MUST include: projectName, description, projectPathHash, localScore.
32
+ 7. Print the evaluation fields and end with `state: ulw`.
33
+
34
+ ## Execution
35
+
36
+ Run this using the Bash tool. It reads the local README, runs local validation (if present), then sends a README-only payload to the server.
37
+
38
+ ```bash
39
+ set -euo pipefail
40
+
41
+ RUN_MODE=0
42
+ PROJECT_PATH=""
43
+ if [ -n "${ARGUMENTS:-}" ]; then
44
+ if [ "${ARGUMENTS%% *}" = "--run" ]; then
45
+ RUN_MODE=1
46
+ PROJECT_PATH="${ARGUMENTS#--run}"
47
+ PROJECT_PATH="${PROJECT_PATH# }"
48
+ else
49
+ PROJECT_PATH="$ARGUMENTS"
50
+ fi
51
+ fi
52
+ if [ -z "$PROJECT_PATH" ]; then PROJECT_PATH="$PWD"; fi
53
+
54
+ node - "$PROJECT_PATH" "$RUN_MODE" <<'NODE'
55
+ const fs = require('node:fs');
56
+ const path = require('node:path');
57
+ const os = require('node:os');
58
+ const crypto = require('node:crypto');
59
+ const { execSync } = require('node:child_process');
60
+
61
+ const projectPathArg = process.argv[2];
62
+ const runMode = process.argv[3] === '1';
63
+ const projectPath = path.resolve(projectPathArg || process.cwd());
64
+ const projectName = path.basename(projectPath);
65
+ const readmePath = path.join(projectPath, 'README.md');
66
+
67
+ if (!fs.existsSync(readmePath)) {
68
+ console.error('Error: README.md not found:', readmePath);
69
+ process.exit(1);
70
+ }
71
+
72
+ const readmeRaw = fs.readFileSync(readmePath, 'utf8');
73
+ if (!readmeRaw.trim()) {
74
+ console.error('Error: README.md is empty');
75
+ process.exit(1);
76
+ }
77
+
78
+ const description = readmeRaw.length > 5000 ? `${readmeRaw.slice(0, 5000)}\n... (truncated)` : readmeRaw;
79
+
80
+ function extractLocalValidationTestCommand(text) {
81
+ const idx = text.toLowerCase().indexOf('## local validation');
82
+ if (idx < 0) return null;
83
+ const section = text.slice(idx);
84
+ const m = section.match(/```bash[^\n]*title\s*=\s*['\"]test['\"][^\n]*\n([\s\S]*?)\n```/i);
85
+ if (!m) return null;
86
+ const cmd = (m[1] || '').trim();
87
+ return cmd ? cmd : null;
88
+ }
89
+
90
+ let localScore = 0;
91
+ const testCmd = extractLocalValidationTestCommand(readmeRaw);
92
+ let localEvaluationSummary = '';
93
+ if (!runMode) {
94
+ console.log('Planned /modu:submit');
95
+ console.log('projectPath:', projectPath);
96
+ console.log('projectName:', projectName);
97
+ console.log('readmePath:', readmePath);
98
+ console.log('localValidationTest:', testCmd ? testCmd : '(missing)');
99
+ console.log('');
100
+ console.log('To proceed and run the local test command, re-run:');
101
+ console.log(' /modu:submit --run ' + projectPath);
102
+ console.log('');
103
+ console.log('state: ulw');
104
+ process.exit(0);
105
+ }
106
+
107
+ if (testCmd) {
108
+ const start = Date.now();
109
+ try {
110
+ execSync(testCmd, { cwd: projectPath, stdio: 'ignore', timeout: 120000, windowsHide: true });
111
+ localScore = 5;
112
+ localEvaluationSummary = `Ran README Local Validation test: PASS (localScore=5) in ${Date.now() - start}ms.`;
113
+ } catch {
114
+ localScore = 0;
115
+ localEvaluationSummary = `Ran README Local Validation test: FAIL (localScore=0) in ${Date.now() - start}ms.`;
116
+ }
117
+ } else {
118
+ localEvaluationSummary = 'No README Local Validation test block found (localScore=0).';
119
+ }
120
+
121
+ const projectPathHash = crypto.createHash('sha256').update(projectPath).digest('hex');
122
+
123
+ const configPath = path.join(os.homedir(), '.modu-arena.json');
124
+ let config = {};
125
+ if (fs.existsSync(configPath)) {
126
+ try {
127
+ config = JSON.parse(fs.readFileSync(configPath, 'utf8')) || {};
128
+ } catch {
129
+ config = {};
130
+ }
131
+ }
132
+
133
+ const apiKey = config.apiKey;
134
+ if (!apiKey) {
135
+ console.error('Error: API key missing. Run `npx @suncreation/modu-arena login` or `install --api-key <key>` first.');
136
+ process.exit(1);
137
+ }
138
+
139
+ const baseUrl = process.env.MODU_ARENA_API_URL || config.serverUrl || 'http://backend.vibemakers.kr:23010';
140
+ const url = `${String(baseUrl).replace(/\/$/, '')}/api/v1/evaluate`;
141
+
142
+ const ts = String(Math.floor(Date.now() / 1000));
143
+ const body = JSON.stringify({ projectName, description, projectPathHash, localScore, localEvaluationSummary });
144
+ const sig = crypto.createHmac('sha256', apiKey).update(`${ts}:${body}`).digest('hex');
145
+
146
+ (async () => {
147
+ const res = await fetch(url, {
148
+ method: 'POST',
149
+ headers: {
150
+ 'Content-Type': 'application/json',
151
+ 'X-API-Key': apiKey,
152
+ 'X-Timestamp': ts,
153
+ 'X-Signature': sig,
154
+ },
155
+ body,
156
+ });
157
+
158
+ const text = await res.text();
159
+ if (!res.ok) {
160
+ console.error('Error:', res.status, text);
161
+ process.exit(1);
162
+ }
163
+
164
+ const json = JSON.parse(text);
165
+ console.log(JSON.stringify(json, null, 2));
166
+ console.log('\nstate: ulw');
167
+ })();
168
+ NODE
169
+ ```
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: Sync implementation changes back into docs (SPEC + API docs)
3
+ argument-hint: <SPEC-ID>
4
+ allowed-tools: Task, Read, Grep, Glob, Edit, Write
5
+ ---
6
+
7
+ # /modu:sync
8
+
9
+ Goal: ensure docs reflect reality after implementation.
10
+
11
+ Must do:
12
+
13
+ - Read `.modu-arena/development-plan.md`.
14
+ - Read `.modu-arena/specs/<SPEC-ID>/{spec.md,plan.md,acceptance.md}`.
15
+ - If APIs changed, update `docs/api-specification.md`.
16
+
17
+ Output requirements:
18
+
19
+ - Short list: what docs were updated.
20
+ - For each updated doc, one-line summary of what changed (e.g. "Added OpenCode plugin section", "Removed deprecated hook flow").
21
+ - End with `state: ulw`.
@@ -0,0 +1,31 @@
1
+ ---
2
+ description: Modu workflow router (project/plan/run/sync/fix/loop/feedback/submit)
3
+ argument-hint: <project|plan|run|sync|fix|loop|feedback|submit> [...]
4
+ allowed-tools: Task, Read, Grep, Glob, Bash, Edit, Write
5
+ ---
6
+
7
+ # /modu
8
+
9
+ Parse `$ARGUMENTS` and run the matching Modu workflow.
10
+
11
+ Hard rules:
12
+
13
+ - Treat these docs as the source of truth. Read them before doing anything:
14
+ - `.modu-arena/development-plan.md`
15
+ - `.modu-arena/specs/` (relevant SPEC folder)
16
+ - `docs/api-specification.md` (when touching API)
17
+ - Keep output short.
18
+ - When you finish a workflow, end with `state: ulw`.
19
+
20
+ Routing:
21
+
22
+ - If `$ARGUMENTS` starts with `project` -> follow `/modu:project`.
23
+ - If `$ARGUMENTS` starts with `plan` -> follow `/modu:plan`.
24
+ - If `$ARGUMENTS` starts with `run` -> follow `/modu:run`.
25
+ - If `$ARGUMENTS` starts with `sync` -> follow `/modu:sync`.
26
+ - If `$ARGUMENTS` starts with `fix` -> follow `/modu:fix`.
27
+ - If `$ARGUMENTS` starts with `loop` -> follow `/modu:loop`.
28
+ - If `$ARGUMENTS` starts with `feedback` -> follow `/modu:feedback`.
29
+ - If `$ARGUMENTS` starts with `submit` -> follow `/modu:submit`.
30
+
31
+ If no subcommand is provided, print a 1-screen help showing the subcommands and example invocations.
package/dist/index.js CHANGED
@@ -8,9 +8,10 @@ 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 readFileSync4, unlinkSync as unlinkSync2 } from "fs";
11
+ import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync as readdirSync2, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, unlinkSync as unlinkSync2 } from "fs";
12
12
  import { homedir as homedir5 } from "os";
13
- import { basename, join as join5 } from "path";
13
+ import { basename, dirname as dirname2, join as join5 } from "path";
14
+ import { fileURLToPath } from "url";
14
15
  import { createHash as createHash3 } from "crypto";
15
16
  import { execSync as execSync2 } from "child_process";
16
17
 
@@ -799,6 +800,7 @@ async function installCommand(apiKey) {
799
800
  "No AI coding tools detected. Install one of the supported tools:\n \u2022 Claude Code (https://docs.anthropic.com/s/claude-code)\n \u2022 OpenCode (https://opencode.ai)\n \u2022 Gemini CLI (https://github.com/google-gemini/gemini-cli)\n \u2022 Codex CLI (https://github.com/openai/codex)\n \u2022 Crush (https://charm.sh/crush)\n"
800
801
  );
801
802
  }
803
+ installSlashCommands();
802
804
  }
803
805
  async function rankCommand() {
804
806
  const config = requireConfig();
@@ -970,6 +972,37 @@ async function submitCommand() {
970
972
  console.log("");
971
973
  }
972
974
  }
975
+ function installSlashCommands() {
976
+ const cwd = process.cwd();
977
+ const thisDir = dirname2(fileURLToPath(import.meta.url));
978
+ const srcDir = join5(thisDir, "..", "commands");
979
+ if (!existsSync5(srcDir)) {
980
+ const altDir = join5(thisDir, "commands");
981
+ if (!existsSync5(altDir)) return;
982
+ return copyCommandsFrom(altDir, cwd);
983
+ }
984
+ copyCommandsFrom(srcDir, cwd);
985
+ }
986
+ function copyCommandsFrom(srcDir, cwd) {
987
+ const targetBase = join5(cwd, ".claude", "commands");
988
+ const routerSrc = join5(srcDir, "modu.md");
989
+ if (existsSync5(routerSrc)) {
990
+ mkdirSync5(targetBase, { recursive: true });
991
+ writeFileSync5(join5(targetBase, "modu.md"), readFileSync4(routerSrc));
992
+ }
993
+ const subDir = join5(srcDir, "modu");
994
+ if (!existsSync5(subDir)) return;
995
+ const targetSub = join5(targetBase, "modu");
996
+ mkdirSync5(targetSub, { recursive: true });
997
+ let count = 0;
998
+ for (const file of readdirSync2(subDir)) {
999
+ if (!file.endsWith(".md")) continue;
1000
+ writeFileSync5(join5(targetSub, file), readFileSync4(join5(subDir, file)));
1001
+ count++;
1002
+ }
1003
+ console.log(`
1004
+ \u2713 Slash commands installed to ${targetBase} (${count} commands)`);
1005
+ }
973
1006
  function formatNumber(n) {
974
1007
  if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
975
1008
  if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
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, 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, readFileSync, 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 private static readonly PLUGIN_NAME = 'opencode-modu-arena';\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 configFile() { return join(this.configDir, 'opencode.json'); }\n\n getHookPath() { return this.configFile; }\n detect() { return existsSync(this.configDir); }\n\n // OpenCode uses a JS plugin system, not shell hooks — registers plugin in opencode.json\n install(_apiKey: string) {\n try {\n let config: Record<string, unknown> = {};\n if (existsSync(this.configFile)) {\n const raw = readFileSync(this.configFile, 'utf-8');\n config = JSON.parse(raw) as Record<string, unknown>;\n }\n\n const plugins = (Array.isArray(config.plugin) ? config.plugin : []) as string[];\n\n if (plugins.some((p) => p === OpenCodeAdapter.PLUGIN_NAME || p.startsWith(`${OpenCodeAdapter.PLUGIN_NAME}@`))) {\n return { success: true, message: `${this.displayName} plugin already registered`, hookPath: this.configFile };\n }\n\n plugins.push(OpenCodeAdapter.PLUGIN_NAME);\n config.plugin = plugins;\n\n if (!existsSync(this.configDir)) mkdirSync(this.configDir, { recursive: true });\n writeFileSync(this.configFile, JSON.stringify(config, null, 4) + '\\n');\n\n return { success: true, message: `${this.displayName} plugin registered in ${this.configFile}`, hookPath: this.configFile };\n } catch (err) {\n return { success: false, message: `Failed to register ${this.displayName} plugin: ${err}` };\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":";;;;;;;;;AAIA,SAAS,uBAAuB;AAChC,SAAS,cAAAA,aAAY,gBAAAC,eAAc,cAAAC,mBAAkB;AACrD,SAAS,WAAAC,gBAAe;AACxB,SAAS,UAAU,QAAAC,aAAY;AAC/B,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,YAAAC,iBAAgB;;;ACFzB,SAAS,YAAY,cAAc,eAAe,iBAAiB;AACnE,SAAS,eAAe;AACxB,SAAS,YAAY;;;ACRd,IAAM,eACX,QAAQ,IAAI,sBAAsB;AAkB7B,IAAM,qBAA+C;AAAA,EAC1D,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,OAAO;AACT;AAGO,IAAM,mBAAmB;AAGzB,IAAM,oBAAoB;AAS1B,IAAM,2BAA2B;;;AD5BxC,IAAM,SAAS,QAAQ,aAAa;AA2BpC,IAAM,UAAU;AAEhB,SAAS,WAAW,QAA4B;AAC9C,SAAO;AAAA,IACL,EAAE,KAAK,aAAa,KAAK,GAAG,MAAM,eAAe,OAAO,UAAU,UAAU,GAAG;AAAA,IAC/E,EAAE,KAAK,aAAa,KAAK,GAAG,MAAM,uBAAuB,OAAO,UAAU,UAAU,GAAG;AAAA,IACvF,EAAE,KAAK,eAAe,KAAK,GAAG,MAAM,iBAAiB,OAAO,OAAO,UAAU,IAAI;AAAA,IACjF,EAAE,KAAK,gBAAgB,KAAK,GAAG,MAAM,kBAAkB,OAAO,OAAO,UAAU,IAAI;AAAA,IACnF,EAAE,KAAK,aAAa,KAAK,GAAG,MAAM,UAAU,OAAO,UAAU,UAAU,UAAU;AAAA,EACnF;AACF;AAEA,SAAS,eAAe,QAAgB,UAAkB,QAAgB,QAA4B;AACpG,QAAM,QAAQ,OAAO;AAAA,IAAI,CAAC,MACxB,EAAE,UAAU,QACR,OAAO,EAAE,GAAG,2BAA2B,EAAE,GAAG,UAAU,EAAE,QAAQ,WAChE,OAAO,EAAE,GAAG,kBAAkB,EAAE,GAAG,UAAU,EAAE,QAAQ;AAAA,EAC7D;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA,gBAIO,KAAK,UAAU,MAAM,CAAC;AAAA,gBACtB,KAAK,UAAU,YAAY,CAAC;AAAA;AAAA,oBAExB,MAAM;AAAA;AAAA;AAAA,gBAGV,KAAK,UAAU,QAAQ,CAAC;AAAA;AAAA,EAEtC,MAAM,KAAK,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcnB;AAEA,SAAS,eAAuB;AAC9B,SAAO;AAAA,6BACoB,OAAO;AAAA;AAEpC;AAEA,SAAS,aAAqB;AAC5B,SAAO,eAAe,OAAO;AAAA;AAC/B;AAIA,SAAS,YACP,aACA,UACA,WACA,QACA,UACA,QACA,QACe;AACf,MAAI;AACF,QAAI,CAAC,WAAW,QAAQ,EAAG,WAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AAElE,kBAAc,KAAK,UAAU,OAAO,GAAG,eAAe,QAAQ,UAAU,QAAQ,MAAM,GAAG,EAAE,MAAM,IAAM,CAAC;AAExG,QAAI,QAAQ;AACV,oBAAc,WAAW,WAAW,CAAC;AAAA,IACvC,OAAO;AACL,oBAAc,WAAW,aAAa,GAAG,EAAE,MAAM,IAAM,CAAC;AAAA,IAC1D;AAEA,WAAO,EAAE,SAAS,MAAM,SAAS,GAAG,WAAW,sBAAsB,SAAS,IAAI,UAAU,UAAU;AAAA,EACxG,SAAS,KAAK;AACZ,WAAO,EAAE,SAAS,OAAO,SAAS,qBAAqB,WAAW,UAAU,GAAG,GAAG;AAAA,EACpF;AACF;AAEA,SAAS,gBAAwB;AAC/B,SAAO,SAAS,oBAAoB;AACtC;AAIA,IAAM,oBAAN,MAA+C;AAAA,EAC7C,OAAO;AAAA,EACP,cAAc;AAAA,EAEd,IAAY,YAAY;AAAE,WAAO,KAAK,QAAQ,GAAG,SAAS;AAAA,EAAG;AAAA,EAC7D,IAAY,WAAW;AAAE,WAAO,KAAK,KAAK,WAAW,OAAO;AAAA,EAAG;AAAA,EAE/D,cAAc;AAAE,WAAO,KAAK,KAAK,UAAU,cAAc,CAAC;AAAA,EAAG;AAAA,EAC7D,SAAS;AAAE,WAAO,WAAW,KAAK,SAAS;AAAA,EAAG;AAAA,EAE9C,QAAQ,QAAgB;AACtB,WAAO;AAAA,MAAY,KAAK;AAAA,MAAa,KAAK;AAAA,MAAU,KAAK,YAAY;AAAA,MAAG;AAAA,MAAQ;AAAA,MAAe;AAAA,MAC7F;AAAA,QACE,GAAG,WAAW,QAAQ;AAAA,QACtB,EAAE,KAAK,uBAAuB,KAAK,gCAAgC,OAAO,OAAO,UAAU,IAAI;AAAA,QAC/F,EAAE,KAAK,mBAAmB,KAAK,4BAA4B,OAAO,OAAO,UAAU,IAAI;AAAA,MACzF;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,kBAAN,MAAM,iBAAuC;AAAA,EAC3C,OAAO;AAAA,EACP,cAAc;AAAA,EAEd,OAAwB,cAAc;AAAA;AAAA;AAAA,EAItC,IAAY,YAAY;AACtB,WAAO,KAAK,QAAQ,IAAI,mBAAmB,KAAK,QAAQ,GAAG,SAAS,GAAG,UAAU;AAAA,EACnF;AAAA,EACA,IAAY,aAAa;AAAE,WAAO,KAAK,KAAK,WAAW,eAAe;AAAA,EAAG;AAAA,EAEzE,cAAc;AAAE,WAAO,KAAK;AAAA,EAAY;AAAA,EACxC,SAAS;AAAE,WAAO,WAAW,KAAK,SAAS;AAAA,EAAG;AAAA;AAAA,EAG9C,QAAQ,SAAiB;AACvB,QAAI;AACF,UAAI,SAAkC,CAAC;AACvC,UAAI,WAAW,KAAK,UAAU,GAAG;AAC/B,cAAM,MAAM,aAAa,KAAK,YAAY,OAAO;AACjD,iBAAS,KAAK,MAAM,GAAG;AAAA,MACzB;AAEA,YAAM,UAAW,MAAM,QAAQ,OAAO,MAAM,IAAI,OAAO,SAAS,CAAC;AAEjE,UAAI,QAAQ,KAAK,CAAC,MAAM,MAAM,iBAAgB,eAAe,EAAE,WAAW,GAAG,iBAAgB,WAAW,GAAG,CAAC,GAAG;AAC7G,eAAO,EAAE,SAAS,MAAM,SAAS,GAAG,KAAK,WAAW,8BAA8B,UAAU,KAAK,WAAW;AAAA,MAC9G;AAEA,cAAQ,KAAK,iBAAgB,WAAW;AACxC,aAAO,SAAS;AAEhB,UAAI,CAAC,WAAW,KAAK,SAAS,EAAG,WAAU,KAAK,WAAW,EAAE,WAAW,KAAK,CAAC;AAC9E,oBAAc,KAAK,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AAErE,aAAO,EAAE,SAAS,MAAM,SAAS,GAAG,KAAK,WAAW,yBAAyB,KAAK,UAAU,IAAI,UAAU,KAAK,WAAW;AAAA,IAC5H,SAAS,KAAK;AACZ,aAAO,EAAE,SAAS,OAAO,SAAS,sBAAsB,KAAK,WAAW,YAAY,GAAG,GAAG;AAAA,IAC5F;AAAA,EACF;AACF;AAEA,IAAM,gBAAN,MAA2C;AAAA,EACzC,YACS,MACA,aACC,SACA,WACR;AAJO;AACA;AACC;AACA;AAAA,EACP;AAAA,EAEH,IAAY,YAAY;AAAE,WAAO,KAAK,QAAQ,GAAG,KAAK,OAAO;AAAA,EAAG;AAAA,EAChE,IAAY,WAAW;AAAE,WAAO,KAAK,KAAK,WAAW,OAAO;AAAA,EAAG;AAAA,EAE/D,cAAc;AAAE,WAAO,KAAK,KAAK,UAAU,cAAc,CAAC;AAAA,EAAG;AAAA,EAC7D,SAAS;AAAE,WAAO,WAAW,KAAK,SAAS;AAAA,EAAG;AAAA,EAE9C,QAAQ,QAAgB;AACtB,WAAO;AAAA,MAAY,KAAK;AAAA,MAAa,KAAK;AAAA,MAAU,KAAK,YAAY;AAAA,MAAG;AAAA,MAAQ,KAAK;AAAA,MAAM,KAAK;AAAA,MAC9F,WAAW,KAAK,SAAS;AAAA,IAC3B;AAAA,EACF;AACF;AAIO,SAAS,iBAAgC;AAC9C,SAAO;AAAA,IACL,IAAI,kBAAkB;AAAA,IACtB,IAAI,gBAAgB;AAAA,IACpB,IAAI,cAAc,UAAU,cAAc,WAAW,QAAQ;AAAA,IAC7D,IAAI,cAAc,SAAS,aAAa,UAAU,OAAO;AAAA,IACzD,IAAI,cAAc,SAAS,SAAS,UAAU,OAAO;AAAA,EACvD;AACF;;;AEpOA,SAAS,YAAY,kBAAkB;AAQhC,SAAS,qBACd,QACA,WACA,MACQ;AACR,QAAM,UAAU,GAAG,SAAS,IAAI,IAAI;AACpC,SAAO,WAAW,UAAU,MAAM,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AAClE;;;ACmCA,SAAS,QAAQ,MAA8B;AAC7C,SAAO,KAAK,aAAa;AAC3B;AAEA,SAAS,gBACP,QACA,MACwB;AACxB,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,IAChB,aAAa;AAAA,EACf;AAEA,MAAI,SAAS,QAAW;AACtB,UAAM,YAAY,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,EAAE,SAAS;AACzD,UAAM,YAAY,qBAAqB,QAAQ,WAAW,IAAI;AAC9D,YAAQ,aAAa,IAAI;AACzB,YAAQ,aAAa,IAAI;AAAA,EAC3B;AAEA,SAAO;AACT;AAmDA,eAAsB,QACpB,MAC2D;AAC3D,QAAM,MAAM,GAAG,QAAQ,IAAI,CAAC;AAE5B,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,aAAa,KAAK;AAAA,IACpB;AAAA,EACF,CAAC;AAED,QAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,MAAO,KAAkB;AAC/B,UAAM,SAAS,OAAO,QAAQ,WAAW,MAAO,KAAK,WAAW,QAAQ,IAAI,MAAM;AAClF,WAAO,EAAE,SAAS,OAAO,OAAO,OAAO;AAAA,EACzC;AACA,SAAO;AACT;AAWA,eAAsB,aACpB,SACA,WACuB;AACvB,QAAM,OAAO,KAAK,UAAU,OAAO;AACnC,QAAM,MAAM,GAAG,aAAa,YAAY;AAExC,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C;AAAA,EACF,CAAC;AAED,SAAQ,MAAM,IAAI,KAAK;AACzB;AAEA,eAAsB,UACpB,SACA,WACuB;AACvB,QAAM,OAAO,KAAK,UAAU,EAAE,GAAG,SAAS,QAAQ,MAAM,CAAC;AACzD,QAAM,MAAM,GAAG,aAAa,YAAY;AAExC,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C;AAAA,EACF,CAAC;AAED,SAAQ,MAAM,IAAI,KAAK;AACzB;AA+BA,eAAsB,iBACpB,SACA,MAC+D;AAC/D,QAAM,OAAO,KAAK,UAAU,OAAO;AACnC,QAAM,MAAM,GAAG,QAAQ,IAAI,CAAC;AAE5B,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,QAAQ;AAAA,IACR,SAAS,gBAAgB,KAAK,QAAQ,IAAI;AAAA,IAC1C;AAAA,EACF,CAAC;AAED,QAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,MAAO,KAAkB;AAC/B,UAAM,SAAS,OAAO,QAAQ,WAAW,MAAO,KAAK,WAAW,QAAQ,IAAI,MAAM;AAClF,WAAO,EAAE,SAAS,OAAO,OAAO,OAAO;AAAA,EACzC;AACA,SAAO;AACT;;;ACzOA,SAAS,gBAAAC,eAAc,iBAAAC,gBAAe,cAAAC,aAAY,aAAAC,kBAAiB;AACnE,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,OAAM,eAAe;AAS9B,SAAS,gBAAwB;AAC/B,SAAOC,MAAKC,SAAQ,GAAG,gBAAgB;AACzC;AAEO,SAAS,aAA4B;AAC1C,QAAM,aAAa,cAAc;AACjC,MAAI,CAACC,YAAW,UAAU,EAAG,QAAO;AAEpC,MAAI;AACF,UAAM,MAAMC,cAAa,YAAY,OAAO;AAC5C,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,WAAW,QAAsB;AAC/C,QAAM,aAAa,cAAc;AACjC,QAAM,MAAM,QAAQ,UAAU;AAC9B,MAAI,CAACD,YAAW,GAAG,EAAG,CAAAE,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACxD,EAAAC,eAAc,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,OAAO;AAC3E;AAEO,SAAS,gBAAwB;AACrC,QAAM,SAAS,WAAW;AAC1B,MAAI,CAAC,QAAQ,QAAQ;AACnB,YAAQ;AAAA,MACN;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACV;;;ACtCA,SAAS,iBAAAC,gBAAe,cAAAC,aAAY,YAAY,aAAAC,kBAAiB;AACjE,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,aAAY;AACrB,SAAS,gBAAgB;AAGzB,IAAMC,UAAS,QAAQ,aAAa;AACpC,IAAM,cAAc;AAEpB,SAAS,kBAA0B;AACjC,QAAM,MAAMC,MAAKC,SAAQ,GAAG,eAAe,MAAM;AACjD,MAAI,CAACC,YAAW,GAAG,EAAG,CAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACxD,SAAO;AACT;AAEA,SAAS,cAAsB;AAC7B,MAAI;AACF,WAAO,SAAS,cAAc,EAAE,UAAU,QAAQ,CAAC,EAAE,KAAK;AAAA,EAC5D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAqB;AAC5B,SAAO,UAAQ,QAAQ,YAAY,EAAE,QAAQ,cAAc,UAAU;AACvE;AAEO,SAAS,gBAAuD;AACrE,MAAIJ,SAAQ;AACV,WAAO,qBAAqB;AAAA,EAC9B;AACA,SAAO,mBAAmB;AAC5B;AAEO,SAAS,kBAAyD;AACvE,MAAIA,SAAQ;AACV,WAAO,uBAAuB;AAAA,EAChC;AACA,SAAO,qBAAqB;AAC9B;AAEO,SAAS,oBAA6B;AAC3C,MAAIA,SAAQ;AACV,QAAI;AACF,eAAS,wBAAwB,WAAW,KAAK,EAAE,UAAU,QAAQ,CAAC;AACtE,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,YAAYC,MAAKC,SAAQ,GAAG,WAAW,gBAAgB,GAAG,WAAW,QAAQ;AACnF,SAAOC,YAAW,SAAS;AAC7B;AAEA,SAAS,qBAA4D;AACnE,QAAM,kBAAkBF,MAAKC,SAAQ,GAAG,WAAW,cAAc;AACjE,QAAM,YAAYD,MAAK,iBAAiB,GAAG,WAAW,QAAQ;AAC9D,QAAM,SAAS,gBAAgB;AAC/B,QAAM,WAAW,YAAY;AAC7B,QAAM,UAAU,WAAW;AAE3B,QAAM,kBAAkB,KAAK,MAAM,2BAA2B,EAAE;AAEhE,QAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,cAKF,WAAW;AAAA;AAAA;AAAA,kBAGP,QAAQ;AAAA,kBACR,OAAO;AAAA;AAAA;AAAA;AAAA,eAIV,wBAAwB;AAAA;AAAA,cAEzB,MAAM;AAAA;AAAA,cAEN,MAAM;AAAA;AAAA;AAAA;AAAA;AAMlB,MAAI;AACF,QAAI,CAACE,YAAW,eAAe,GAAG;AAChC,MAAAC,WAAU,iBAAiB,EAAE,WAAW,KAAK,CAAC;AAAA,IAChD;AACA,IAAAC,eAAc,WAAW,KAAK;AAC9B,aAAS,kBAAkB,SAAS,IAAI,EAAE,UAAU,QAAQ,CAAC;AAC7D,WAAO,EAAE,SAAS,MAAM,SAAS,iCAAiC,eAAe,YAAY;AAAA,EAC/F,SAAS,GAAG;AACV,WAAO,EAAE,SAAS,OAAO,SAAS,6BAA6B,CAAC,GAAG;AAAA,EACrE;AACF;AAEA,SAAS,uBAA8D;AACrE,QAAM,YAAYJ,MAAKC,SAAQ,GAAG,WAAW,gBAAgB,GAAG,WAAW,QAAQ;AAEnF,MAAI;AACF,QAAIC,YAAW,SAAS,GAAG;AACzB,eAAS,oBAAoB,SAAS,IAAI,EAAE,UAAU,QAAQ,CAAC;AAC/D,iBAAW,SAAS;AAAA,IACtB;AACA,WAAO,EAAE,SAAS,MAAM,SAAS,sBAAsB;AAAA,EACzD,SAAS,GAAG;AACV,WAAO,EAAE,SAAS,OAAO,SAAS,+BAA+B,CAAC,GAAG;AAAA,EACvE;AACF;AAEA,SAAS,uBAA8D;AACrE,QAAM,WAAW,YAAY;AAC7B,QAAM,UAAU,WAAW;AAC3B,QAAM,kBAAkB,KAAK,MAAM,2BAA2B,EAAE;AAEhE,MAAI;AACF,UAAM,MAAM,yBAAyB,WAAW,aAAa,QAAQ,UAAU,OAAO,mCAAmC,eAAe;AACxI,aAAS,KAAK,EAAE,UAAU,QAAQ,CAAC;AACnC,WAAO,EAAE,SAAS,MAAM,SAAS,iCAAiC,eAAe,YAAY;AAAA,EAC/F,SAAS,GAAG;AACV,WAAO,EAAE,SAAS,OAAO,SAAS,6BAA6B,CAAC,GAAG;AAAA,EACrE;AACF;AAEA,SAAS,yBAAgE;AACvE,MAAI;AACF,aAAS,yBAAyB,WAAW,QAAQ,EAAE,UAAU,QAAQ,CAAC;AAC1E,WAAO,EAAE,SAAS,MAAM,SAAS,sBAAsB;AAAA,EACzD,SAAS,GAAG;AACV,WAAO,EAAE,SAAS,OAAO,SAAS,+BAA+B,CAAC,GAAG;AAAA,EACvE;AACF;AAEO,SAAS,kBAA8E;AAC5F,SAAO;AAAA,IACL,WAAW,kBAAkB;AAAA,IAC7B,UAAUH,UAAS,YAAY;AAAA,IAC/B,UAAU;AAAA,EACZ;AACF;;;AC5IA,SAAS,aAAa,gBAAAM,eAAc,cAAAC,aAAY,iBAAAC,sBAAgC;AAChF,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,aAAY;AACrB,SAAS,cAAAC,mBAAkB;AAI3B,IAAMC,UAAS,QAAQ,aAAa;AAoCpC,SAAS,0BAAkC;AACzC,MAAIA,SAAQ;AACV,WAAOC,MAAK,QAAQ,IAAI,WAAWA,MAAKC,SAAQ,GAAG,WAAW,SAAS,GAAG,QAAQ;AAAA,EACpF;AACA,SAAOD,MAAKC,SAAQ,GAAG,WAAW,uBAAuB,QAAQ;AACnE;AAEA,SAAS,iBAA2B;AAClC,QAAM,UAAU,wBAAwB;AACxC,QAAM,cAAcD,MAAK,SAAS,2BAA2B;AAC7D,MAAI,CAACE,YAAW,WAAW,EAAG,QAAO,CAAC;AAEtC,QAAM,UAAoB,CAAC;AAC3B,aAAW,SAAS,YAAY,aAAa,EAAE,eAAe,KAAK,CAAC,GAAG;AACrE,QAAI,MAAM,YAAY,KAAK,MAAM,SAAS,iBAAiB;AACzD,cAAQ,KAAKF,MAAK,aAAa,MAAM,IAAI,CAAC;AAAA,IAC5C;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,eAAe,SAA2B;AACjD,QAAM,QAAkB,CAAC;AAEzB,WAAS,KAAK,KAAa;AACzB,QAAI,CAACE,YAAW,GAAG,EAAG;AACtB,eAAW,SAAS,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC7D,YAAM,OAAOF,MAAK,KAAK,MAAM,IAAI;AACjC,UAAI,MAAM,YAAY,GAAG;AACvB,aAAK,IAAI;AAAA,MACX,WAAW,MAAM,KAAK,SAAS,QAAQ,KAAK,CAAC,MAAM,KAAK,SAAS,OAAO,GAAG;AACzE,cAAM,KAAK,IAAI;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAEA,OAAK,OAAO;AACZ,SAAO;AACT;AAEA,SAAS,eAAe,UAA2C;AACjE,QAAM,UAAUG,cAAa,UAAU,OAAO;AAC9C,QAAM,QAAQ,QAAQ,KAAK,EAAE,MAAM,IAAI;AAEvC,MAAI,YAAY;AAChB,MAAI,cAAc;AAClB,MAAI,eAAe;AACnB,MAAI,sBAAsB;AAC1B,MAAI,kBAAkB;AACtB,MAAI,QAAQ;AACZ,MAAI,YAAY;AAChB,MAAI,UAAU;AACd,MAAI,eAAe;AAEnB,aAAW,QAAQ,OAAO;AACxB,QAAI;AACF,YAAM,MAAoB,KAAK,MAAM,IAAI;AAEzC,UAAI,IAAI,aAAa,CAAC,WAAW;AAC/B,oBAAY,IAAI;AAAA,MAClB;AAEA,UAAI,IAAI,WAAW;AACjB,YAAI,CAAC,aAAa,IAAI,YAAY,WAAW;AAC3C,sBAAY,IAAI;AAAA,QAClB;AACA,YAAI,CAAC,WAAW,IAAI,YAAY,SAAS;AACvC,oBAAU,IAAI;AAAA,QAChB;AAAA,MACF;AAEA,UAAI,IAAI,SAAS,OAAO;AACtB,cAAM,QAAQ,IAAI,QAAQ;AAC1B,uBAAe,MAAM,gBAAgB;AACrC,wBAAgB,MAAM,iBAAiB;AACvC,+BAAuB,MAAM,+BAA+B;AAC5D,2BAAmB,MAAM,2BAA2B;AACpD;AAEA,YAAI,IAAI,QAAQ,OAAO;AACrB,kBAAQ,IAAI,QAAQ;AAAA,QACtB;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IACR;AAAA,EACF;AAEA,MAAI,CAAC,aAAa,iBAAiB,EAAG,QAAO;AAE7C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,qBAA6B;AACpC,SAAOH,MAAKC,SAAQ,GAAG,iBAAiB;AAC1C;AAEA,SAAS,kBAA+B;AACtC,QAAM,OAAO,mBAAmB;AAChC,MAAI,CAACC,YAAW,IAAI,GAAG;AACrB,WAAO,EAAE,WAAU,oBAAI,KAAK,CAAC,GAAE,YAAY,GAAG,gBAAgB,CAAC,EAAE;AAAA,EACnE;AACA,MAAI;AACF,WAAO,KAAK,MAAMC,cAAa,MAAM,OAAO,CAAC;AAAA,EAC/C,QAAQ;AACN,WAAO,EAAE,WAAU,oBAAI,KAAK,CAAC,GAAE,YAAY,GAAG,gBAAgB,CAAC,EAAE;AAAA,EACnE;AACF;AAEA,SAAS,gBAAgB,OAA0B;AACjD,QAAM,OAAO,mBAAmB;AAChC,EAAAC,eAAc,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AACpD;AAEA,SAAS,mBAAmB,SAAmC;AAC7D,QAAM,OAAO,GAAG,QAAQ,SAAS,IAAI,QAAQ,WAAW,IAAI,QAAQ,YAAY,IAAI,QAAQ,OAAO;AACnG,SAAOC,YAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK,EAAE,UAAU,GAAG,EAAE;AACxE;AAEA,eAAsB,kBAAkB,QAAgF;AACtH,QAAM,QAAQ,gBAAgB;AAC9B,QAAM,SAAmB,CAAC;AAC1B,MAAI,SAAS;AACb,MAAI,UAAU;AAEd,QAAM,cAAc,eAAe;AAEnC,aAAW,UAAU,aAAa;AAChC,UAAM,aAAa,eAAe,MAAM;AAExC,eAAW,QAAQ,YAAY;AAC7B,YAAM,UAAU,eAAe,IAAI;AACnC,UAAI,CAAC,QAAS;AAEd,YAAM,OAAO,mBAAmB,OAAO;AACvC,UAAI,MAAM,eAAe,SAAS,IAAI,GAAG;AACvC;AACA;AAAA,MACF;AAEA,UAAI,QAAQ,gBAAgB,KAAK,QAAQ,iBAAiB,GAAG;AAC3D;AACA;AAAA,MACF;AAEA,UAAI;AACF,cAAM,OAAO,KAAK,UAAU;AAAA,UAC1B,UAAU;AAAA,UACV,SAAS,QAAQ;AAAA,UACjB,WAAW,QAAQ;AAAA,UACnB,aAAa,QAAQ;AAAA,UACrB,cAAc,QAAQ;AAAA,UACtB,qBAAqB,QAAQ;AAAA,UAC7B,iBAAiB,QAAQ;AAAA,UACzB,WAAW,QAAQ;AAAA,QACrB,CAAC;AAED,cAAM,KAAK,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,EAAE,SAAS;AAClD,cAAM,MAAM,qBAAqB,QAAQ,IAAI,IAAI;AAEjD,cAAM,MAAM,MAAM,MAAM,GAAG,YAAY,oBAAoB;AAAA,UACzD,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,YAChB,aAAa;AAAA,YACb,eAAe;AAAA,YACf,eAAe;AAAA,UACjB;AAAA,UACA;AAAA,QACF,CAAC;AAED,YAAI,IAAI,IAAI;AACV,gBAAM,eAAe,KAAK,IAAI;AAC9B;AAAA,QACF,OAAO;AACL,gBAAM,MAAM,MAAM,IAAI,KAAK;AAC3B,iBAAO,KAAK,GAAG,QAAQ,SAAS,KAAK,GAAG,EAAE;AAAA,QAC5C;AAAA,MACF,SAAS,GAAG;AACV,eAAO,KAAK,GAAG,QAAQ,SAAS,KAAK,CAAC,EAAE;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAW,oBAAI,KAAK,GAAE,YAAY;AACxC,kBAAgB,KAAK;AAErB,SAAO,EAAE,QAAQ,SAAS,OAAO;AACnC;AAEO,SAAS,uBAAgC;AAC9C,QAAM,UAAU,wBAAwB;AACxC,QAAM,cAAcL,MAAK,SAAS,2BAA2B;AAC7D,SAAOE,YAAW,WAAW;AAC/B;;;AP3OA,SAAS,OAAO,UAAmC;AACjD,QAAM,KAAK,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC3E,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,OAAG,SAAS,UAAU,CAAC,WAAW;AAChC,SAAG,MAAM;AACT,cAAQ,OAAO,KAAK,CAAC;AAAA,IACvB,CAAC;AAAA,EACH,CAAC;AACH;AAEA,SAAS,eAAe,UAAmC;AACzD,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,YAAQ,OAAO,MAAM,QAAQ;AAC7B,UAAM,QAAkB,CAAC;AACzB,UAAM,QAAQ,QAAQ;AACtB,UAAM,SAAS,MAAM;AACrB,UAAM,WAAW,IAAI;AACrB,UAAM,OAAO;AACb,UAAM,YAAY,MAAM;AAExB,UAAM,SAAS,CAAC,OAAe;AAC7B,YAAM,IAAI,GAAG,SAAS;AACtB,UAAI,MAAM,QAAQ,MAAM,QAAQ,MAAM,KAAU;AAE9C,cAAM,WAAW,UAAU,KAAK;AAChC,cAAM,MAAM;AACZ,cAAM,eAAe,QAAQ,MAAM;AACnC,gBAAQ,OAAO,MAAM,IAAI;AACzB,gBAAQ,MAAM,KAAK,EAAE,EAAE,KAAK,CAAC;AAAA,MAC/B,WAAW,MAAM,KAAU;AAEzB,gBAAQ,OAAO,MAAM,IAAI;AACzB,gBAAQ,KAAK,CAAC;AAAA,MAChB,WAAW,MAAM,UAAY,MAAM,MAAM;AAEvC,YAAI,MAAM,SAAS,GAAG;AACpB,gBAAM,IAAI;AACV,kBAAQ,OAAO,MAAM,OAAO;AAAA,QAC9B;AAAA,MACF,OAAO;AACL,cAAM,KAAK,CAAC;AACZ,gBAAQ,OAAO,MAAM,GAAG;AAAA,MAC1B;AAAA,IACF;AAEA,UAAM,GAAG,QAAQ,MAAM;AAAA,EACzB,CAAC;AACH;AAIA,eAAsB,kBAAiC;AACrD,UAAQ,IAAI,0CAA8B;AAE1C,QAAM,WAAW,MAAM,OAAO,2BAA2B;AACzD,MAAI,CAAC,YAAY,SAAS,SAAS,KAAK,SAAS,SAAS,IAAI;AAC5D,YAAQ,MAAM,wDAAwD;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,WAAW,MAAM,eAAe,4BAA4B;AAClE,MAAI,CAAC,YAAY,SAAS,SAAS,GAAG;AACpC,YAAQ,MAAM,kDAAkD;AAChE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,cAAc,MAAM,OAAO,kDAAkD;AAEnF,UAAQ,IAAI,oBAAoB;AAEhC,QAAM,WAAW,WAAW;AAC5B,QAAM,SAAS,MAAM;AAAA,IACnB,EAAE,UAAU,UAAU,aAAa,eAAe,OAAU;AAAA,IAC5D,UAAU;AAAA,EACZ;AAEA,MAAI,OAAO,OAAO;AAChB,YAAQ,MAAM;AAAA,WAAc,OAAO,KAAK;AAAA,CAAI;AAC5C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,CAAC,OAAO,QAAQ;AAClB,YAAQ,MAAM,+CAA+C;AAC7D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,aAAW,EAAE,QAAQ,OAAO,QAAQ,WAAW,UAAU,UAAU,CAAC;AACpE,UAAQ,IAAI,qCAAgC;AAC5C,UAAQ,IAAI,8CAAyC;AACrD,UAAQ,IAAI;AAAA,cAAiB,OAAO,MAAM,QAAQ,EAAE;AACpD,UAAQ,IAAI,eAAe,OAAO,OAAO,MAAM,GAAG,EAAE,CAAC,MAAM,OAAO,OAAO,MAAM,EAAE,CAAC,EAAE;AACpF,UAAQ,IAAI,mEAAyD;AAErE,UAAQ,IAAI,sDAAsD;AAClE,QAAM,eAAe,OAAO,MAAM;AACpC;AAIA,eAAsB,eAA8B;AAClD,UAAQ,IAAI,uCAA2B;AAEvC,QAAM,WAAW,MAAM,OAAO,cAAc;AAC5C,MAAI,CAAC,UAAU;AACb,YAAQ,MAAM,gCAAgC;AAC9C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,WAAW,MAAM,eAAe,cAAc;AACpD,MAAI,CAAC,UAAU;AACb,YAAQ,MAAM,gCAAgC;AAC9C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,IAAI,mBAAmB;AAE/B,QAAM,WAAW,WAAW;AAC5B,QAAM,SAAS,MAAM,UAAU,EAAE,UAAU,SAAS,GAAG,UAAU,SAAS;AAE1E,MAAI,OAAO,OAAO;AAChB,YAAQ,MAAM;AAAA,WAAc,OAAO,KAAK;AAAA,CAAI;AAC5C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,CAAC,OAAO,QAAQ;AAClB,YAAQ,MAAM,+CAA+C;AAC7D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,aAAW,EAAE,QAAQ,OAAO,QAAQ,WAAW,UAAU,UAAU,CAAC;AACpE,UAAQ,IAAI,8BAAyB;AACrC,UAAQ,IAAI,8CAAyC;AACrD,UAAQ,IAAI;AAAA,cAAiB,OAAO,MAAM,QAAQ,EAAE;AACpD,UAAQ,IAAI,eAAe,OAAO,OAAO,MAAM,GAAG,EAAE,CAAC,MAAM,OAAO,OAAO,MAAM,EAAE,CAAC,EAAE;AACpF,UAAQ,IAAI,wEAAmE;AAE/E,UAAQ,IAAI,4CAA4C;AACxD,QAAM,eAAe,OAAO,MAAM;AACpC;AAIA,eAAsB,eAAe,QAAgC;AACnE,UAAQ,IAAI,8DAAkD;AAG9D,QAAM,WAAW,WAAW;AAC5B,MAAI,UAAU,UAAU,CAAC,QAAQ;AAC/B,YAAQ,IAAI,4BAAuB;AACnC,YAAQ,IAAI,iDAAiD;AAC7D,aAAS,SAAS;AAAA,EACpB;AAEA,MAAI,CAAC,QAAQ;AACX,YAAQ;AAAA,MACN;AAAA,IAGF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,CAAC,OAAO,WAAW,aAAa,GAAG;AACrC,YAAQ;AAAA,MACN;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,aAAW,EAAE,OAAO,CAAC;AACrB,UAAQ,IAAI,8CAAyC;AAGrD,QAAM,WAAW,eAAe;AAChC,QAAM,UAAqD,CAAC;AAE5D,UAAQ,IAAI,gCAAgC;AAE5C,aAAW,WAAW,UAAU;AAC9B,UAAM,WAAW,QAAQ,OAAO;AAChC,QAAI,UAAU;AACZ,cAAQ,IAAI,YAAO,QAAQ,WAAW,WAAW;AACjD,YAAM,SAAS,QAAQ,QAAQ,MAAM;AACrC,cAAQ,KAAK,EAAE,MAAM,QAAQ,aAAa,OAAO,CAAC;AAClD,UAAI,OAAO,SAAS;AAClB,gBAAQ,IAAI,8BAAyB,OAAO,QAAQ,EAAE;AAAA,MACxD,OAAO;AACL,gBAAQ,IAAI,cAAS,OAAO,OAAO,EAAE;AAAA,MACvC;AAAA,IACF,OAAO;AACL,cAAQ,IAAI,OAAO,QAAQ,WAAW,YAAY;AAAA,IACpD;AAAA,EACF;AAEA,QAAM,YAAY,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO,OAAO;AACxD,UAAQ;AAAA,IACN;AAAA,yBAAuB,UAAU,MAAM;AAAA;AAAA,EACzC;AAEA,MAAI,UAAU,WAAW,GAAG;AAC1B,YAAQ;AAAA,MACN;AAAA,IAMF;AAAA,EACF;AACF;AAIA,eAAsB,cAA6B;AACjD,QAAM,SAAS,cAAc;AAC5B,UAAQ,IAAI,4CAAgC;AAE7C,QAAM,SAAS,MAAM,QAAQ,EAAE,QAAQ,OAAO,QAAQ,WAAW,OAAO,UAAU,CAAC;AAEnF,MAAI,CAAC,OAAO,SAAS;AACnB,YAAQ,MAAM,UAAU,WAAW,SAAS,OAAO,QAAQ,eAAe;AAAA,CAAI;AAC9E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,EAAE,UAAU,WAAW,CAAC,OAAO,MAAM;AACvC,YAAQ,MAAM,sCAAsC;AACpD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,EAAE,UAAU,OAAO,SAAS,IAAI,OAAO;AAE7C,UAAQ,IAAI,eAAe,QAAQ,EAAE;AACrC,UAAQ,IAAI,eAAe,aAAa,MAAM,WAAW,CAAC,EAAE;AAC5D,UAAQ,IAAI,eAAe,MAAM,aAAa,EAAE;AAChD,UAAQ,IAAI,eAAe,SAAS,uBAAuB,EAAE;AAC7D,UAAQ,IAAI,EAAE;AAGd,MAAI,MAAM,cAAc,SAAS,GAAG;AAClC,YAAQ,IAAI,mBAAmB;AAC/B,eAAW,SAAS,MAAM,eAAe;AACvC,YAAM,OAAO,mBAAmB,MAAM,IAAgB,KAAK,MAAM;AACjE,cAAQ;AAAA,QACN,OAAO,IAAI,KAAK,aAAa,MAAM,MAAM,CAAC;AAAA,MAC5C;AAAA,IACF;AACA,YAAQ,IAAI,EAAE;AAAA,EAChB;AAGA,QAAM,OAAO,MAAM,UAAU;AAAA,IAC3B,CAAC,KAAK,OAAO,EAAE,QAAQ,IAAI,SAAS,EAAE,cAAc,EAAE,cAAc,UAAU,IAAI,WAAW,EAAE,SAAS;AAAA,IACxG,EAAE,QAAQ,GAAG,UAAU,EAAE;AAAA,EAC3B;AACA,QAAM,QAAQ,MAAM,WAAW;AAAA,IAC7B,CAAC,KAAK,OAAO,EAAE,QAAQ,IAAI,SAAS,EAAE,cAAc,EAAE,cAAc,UAAU,IAAI,WAAW,EAAE,SAAS;AAAA,IACxG,EAAE,QAAQ,GAAG,UAAU,EAAE;AAAA,EAC3B;AACA,UAAQ;AAAA,IACN,mBAAmB,aAAa,KAAK,MAAM,CAAC,YAAY,KAAK,QAAQ;AAAA,EACvE;AACA,UAAQ;AAAA,IACN,mBAAmB,aAAa,MAAM,MAAM,CAAC,YAAY,MAAM,QAAQ;AAAA,EACzE;AACA,UAAQ,IAAI,EAAE;AAChB;AAIO,SAAS,gBAAsB;AACnC,QAAM,SAAS,WAAW;AAC1B,UAAQ,IAAI,wCAA4B;AAExC,MAAI,CAAC,QAAQ,QAAQ;AACnB,YAAQ,IAAI,0BAA0B;AACtC,YAAQ;AAAA,MACN;AAAA,IACF;AACA;AAAA,EACF;AAED,QAAM,YACJ,OAAO,OAAO,MAAM,GAAG,EAAE,IAAI,QAAQ,OAAO,OAAO,MAAM,EAAE;AAC7D,UAAQ,IAAI,cAAc,SAAS,EAAE;AACrC,UAAQ,IAAI,cAAc,OAAO,aAAa,YAAY,EAAE;AAC5D,UAAQ,IAAI,EAAE;AAGd,QAAM,WAAW,eAAe;AAChC,UAAQ,IAAI,oBAAoB;AAChC,MAAI,YAAY;AAChB,aAAW,WAAW,UAAU;AAC9B,UAAM,WAAW,QAAQ,OAAO;AAChC,QAAI,UAAU;AACZ,YAAM,aAAaI,YAAW,QAAQ,YAAY,CAAC;AACnD,YAAM,SAAS,aAAa,kBAAa;AACzC,cAAQ,IAAI,OAAO,QAAQ,WAAW,KAAK,MAAM,EAAE;AACnD,UAAI,WAAY;AAAA,IAClB;AAAA,EACF;AACA,MAAI,cAAc,GAAG;AACnB,YAAQ,IAAI,YAAY;AAAA,EAC1B;AACA,UAAQ,IAAI,EAAE;AAChB;AAIO,SAAS,mBAAyB;AACtC,UAAQ,IAAI,kDAAiC;AAG9C,QAAM,WAAW,eAAe;AAChC,aAAW,WAAW,UAAU;AAC9B,UAAM,WAAW,QAAQ,YAAY;AACrC,QAAIA,YAAW,QAAQ,GAAG;AACxB,MAAAC,YAAW,QAAQ;AACnB,cAAQ,IAAI,oBAAe,QAAQ,WAAW,OAAO;AAAA,IACvD;AAAA,EACF;AAGC,QAAM,aAAaC,MAAKC,SAAQ,GAAG,kBAAkB;AACrD,MAAIH,YAAW,UAAU,GAAG;AAC1B,IAAAC,YAAW,UAAU;AACrB,YAAQ,IAAI,qCAAgC;AAAA,EAC9C;AAEA,UAAQ,IAAI,oCAA+B;AAC9C;AAIA,eAAsB,gBAA+B;AACnD,QAAM,SAAS,cAAc;AAC7B,UAAQ,IAAI,gDAAoC;AAEhD,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,cAAc,SAAS,GAAG;AAEhC,QAAM,aAAaC,MAAK,KAAK,WAAW;AACxC,MAAI,CAACF,YAAW,UAAU,GAAG;AAC3B,YAAQ,MAAM,sDAAsD;AACpE,YAAQ,MAAM,wDAAwD;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,iBAAiBI,cAAa,YAAY,OAAO;AACvD,MAAI,eAAe,KAAK,EAAE,WAAW,GAAG;AACtC,YAAQ,MAAM,8BAA8B;AAC5C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,cAAc,eAAe,SAAS,MACxC,eAAe,MAAM,GAAG,GAAI,IAAI,sBAChC;AAEJ,QAAM,kBAAkB,UAAU,GAAG;AACrC,QAAM,sBAAsB,kCAAkC,cAAc;AAC5E,MAAI,aAAa;AACjB,MAAI;AACJ,MAAI,qBAAqB;AACvB,YAAQ,IAAI,6DAA6D;AACzE,QAAI;AACF,YAAM,QAAQ,KAAK,IAAI;AACvB,MAAAC,UAAS,qBAAqB;AAAA,QAC5B;AAAA,QACA,OAAO;AAAA,QACP,SAAS;AAAA,QACT,aAAa;AAAA,MACf,CAAC;AACD,mBAAa;AACb,+BAAyB,4DAA4D,KAAK,IAAI,IAAI,KAAK;AACvG,cAAQ,IAAI,kCAA6B;AAAA,IAC3C,QAAQ;AACN,mBAAa;AACb,+BAAyB;AACzB,cAAQ,IAAI,kCAA6B;AAAA,IAC3C;AACA,YAAQ,IAAI,EAAE;AAAA,EAChB,OAAO;AACL,6BAAyB;AAAA,EAC3B;AAEA,UAAQ,IAAI,eAAe,WAAW,EAAE;AACxC,UAAQ,IAAI,eAAe,UAAU,EAAE;AACvC,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,kCAAkC;AAE9C,QAAM,SAAS,MAAM;AAAA,IACnB,EAAE,aAAa,aAAa,iBAAiB,YAAY,uBAAuB;AAAA,IAChF,EAAE,QAAQ,OAAO,QAAQ,WAAW,OAAO,UAAU;AAAA,EACvD;AAEA,MAAI,CAAC,OAAO,SAAS;AACnB,YAAQ,MAAM,UAAU,WAAW,SAAS,OAAO,QAAQ,eAAe;AAAA,CAAI;AAC9E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,EAAE,WAAW,IAAI;AACvB,QAAM,aAAa,WAAW,SAAS,WAAM;AAC7C,QAAM,aAAa,WAAW,SAAS,WAAW;AAElD,UAAQ,IAAI,aAAa,UAAU,IAAI,UAAU,EAAE;AACnD,UAAQ,IAAI,kBAAkB,WAAW,UAAU,KAAK;AACxD,UAAQ,IAAI,kBAAkB,WAAW,oBAAoB,EAAE;AAC/D,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,oBAAoB;AAChC,UAAQ,IAAI,qBAAqB,WAAW,UAAU,IAAI;AAC1D,UAAQ,IAAI,qBAAqB,WAAW,YAAY,IAAI;AAC5D,UAAQ,IAAI,qBAAqB,WAAW,YAAY,EAAE;AAC1D,UAAQ,IAAI,EAAE;AAEd,MAAI,WAAW,UAAU;AACvB,YAAQ,IAAI,aAAa;AACzB,UAAM,QAAQ,WAAW,SAAS,MAAM,IAAI;AAC5C,eAAW,QAAQ,OAAO;AACxB,cAAQ,IAAI,OAAO,IAAI,EAAE;AAAA,IAC3B;AACA,YAAQ,IAAI,EAAE;AAAA,EAChB;AACF;AAIA,SAAS,aAAa,GAAmB;AACvC,MAAI,KAAK,IAAW,QAAO,IAAI,IAAI,KAAW,QAAQ,CAAC,CAAC;AACxD,MAAI,KAAK,IAAO,QAAO,IAAI,IAAI,KAAO,QAAQ,CAAC,CAAC;AAChD,SAAO,EAAE,SAAS;AACpB;AAEA,SAAS,UAAU,OAAuB;AACxC,SAAOC,YAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK;AACxD;AAEA,SAAS,kCAAkC,QAA+B;AACxE,QAAM,MAAM,OAAO,YAAY,EAAE,QAAQ,qBAAqB;AAC9D,MAAI,MAAM,EAAG,QAAO;AACpB,QAAM,UAAU,OAAO,MAAM,GAAG;AAChC,QAAM,IAAI,QAAQ,MAAM,+DAA+D;AACvF,MAAI,CAAC,EAAG,QAAO;AACf,QAAM,OAAO,EAAE,CAAC,KAAK,IAAI,KAAK;AAC9B,SAAO,IAAI,SAAS,IAAI,MAAM;AAChC;AAIO,SAAS,uBAA6B;AAC3C,UAAQ,IAAI,uDAA2C;AAEvD,MAAI,CAAC,qBAAqB,GAAG;AAC3B,YAAQ,IAAI,yCAAoC;AAChD,YAAQ,IAAI,gEAAgE;AAC5E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,cAAc;AAE7B,MAAI,OAAO,SAAS;AAClB,YAAQ,IAAI,YAAO,OAAO,OAAO,EAAE;AACnC,YAAQ,IAAI,iEAA4D;AAAA,EAC1E,OAAO;AACL,YAAQ,MAAM,YAAO,OAAO,OAAO;AAAA,CAAI;AACvC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAIO,SAAS,yBAA+B;AAC7C,UAAQ,IAAI,uDAA2C;AAEvD,QAAM,SAAS,gBAAgB;AAE/B,MAAI,OAAO,SAAS;AAClB,YAAQ,IAAI,YAAO,OAAO,OAAO;AAAA,CAAI;AAAA,EACvC,OAAO;AACL,YAAQ,MAAM,YAAO,OAAO,OAAO;AAAA,CAAI;AACvC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAIO,SAAS,sBAA4B;AAC1C,UAAQ,IAAI,uDAA2C;AAEvD,QAAM,SAAS,gBAAgB;AAE/B,UAAQ,IAAI,eAAe,OAAO,QAAQ,EAAE;AAC5C,UAAQ,IAAI,gBAAgB,OAAO,YAAY,QAAQ,IAAI,EAAE;AAC7D,MAAI,OAAO,WAAW;AACpB,YAAQ,IAAI,oBAAoB,KAAK,MAAM,OAAO,WAAW,EAAE,CAAC,UAAU;AAAA,EAC5E;AAEA,MAAI,qBAAqB,GAAG;AAC1B,YAAQ,IAAI,8BAA8B;AAAA,EAC5C,OAAO;AACL,YAAQ,IAAI,kCAAkC;AAAA,EAChD;AACA,UAAQ,IAAI,EAAE;AAChB;AAIA,eAAsB,oBAAmC;AACvD,QAAM,SAAS,cAAc;AAE7B,MAAI,CAAC,qBAAqB,GAAG;AAC3B,YAAQ,IAAI,mDAAmD;AAC/D;AAAA,EACF;AAEA,UAAQ,IAAI,iCAAiC;AAE7C,QAAM,SAAS,MAAM,kBAAkB,OAAO,MAAM;AAEpD,UAAQ,IAAI,aAAa,OAAO,MAAM,WAAW;AACjD,UAAQ,IAAI,cAAc,OAAO,OAAO,4BAA4B;AAEpE,MAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,YAAQ,IAAI,aAAa,OAAO,OAAO,MAAM,EAAE;AAC/C,eAAW,OAAO,OAAO,OAAO,MAAM,GAAG,CAAC,GAAG;AAC3C,cAAQ,IAAI,SAAS,GAAG,EAAE;AAAA,IAC5B;AACA,QAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,cAAQ,IAAI,eAAe,OAAO,OAAO,SAAS,CAAC,OAAO;AAAA,IAC5D;AAAA,EACF;AACA,UAAQ,IAAI,EAAE;AAChB;;;AQ1gBA,IAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,IAAM,UAAU,KAAK,CAAC;AAEtB,SAAS,YAAkB;AACxB,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CA8Bd;AACD;AAEA,eAAe,OAAsB;AACnC,MAAI,CAAC,WAAW,YAAY,YAAY,YAAY,MAAM;AACxD,cAAU;AACV,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,YAAY,eAAe,YAAY,MAAM;AAC/C,YAAQ,IAAI,OAAO;AACnB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,YAAM,gBAAgB;AACtB;AAAA,IACF,KAAK;AACH,YAAM,aAAa;AACnB;AAAA,IACF,KAAK,WAAW;AACd,YAAM,WAAW,KAAK,QAAQ,WAAW;AACzC,YAAM,SAAS,YAAY,IAAI,KAAK,WAAW,CAAC,IAAI;AACpD,YAAM,eAAe,MAAM;AAC3B;AAAA,IACF;AAAA,IACA,KAAK;AACH,YAAM,YAAY;AAClB;AAAA,IACF,KAAK;AACH,oBAAc;AACd;AAAA,IACF,KAAK;AACH,YAAM,cAAc;AACpB;AAAA,IACF,KAAK;AACH,uBAAiB;AACjB;AAAA,IACF,KAAK;AACH,2BAAqB;AACrB;AAAA,IACF,KAAK;AAAA,IACL,KAAK;AACH,6BAAuB;AACvB;AAAA,IACF,KAAK;AACH,0BAAoB;AACpB;AAAA,IACF,KAAK;AACH,YAAM,kBAAkB;AACxB;AAAA,IACF;AACE,cAAQ,MAAM,oBAAoB,OAAO,EAAE;AAC3C,gBAAU;AACV,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,gBAAgB,GAAG;AACjC,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["existsSync","readFileSync","unlinkSync","homedir","join","createHash","execSync","readFileSync","writeFileSync","existsSync","mkdirSync","homedir","join","join","homedir","existsSync","readFileSync","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"]}
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, writeFileSync, mkdirSync, unlinkSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { basename, dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\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 installSlashCommands();\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// ─── slash commands ────────────────────────────────────────────────────────\n\nfunction installSlashCommands(): void {\n const cwd = process.cwd();\n const thisDir = dirname(fileURLToPath(import.meta.url));\n const srcDir = join(thisDir, '..', 'commands');\n\n if (!existsSync(srcDir)) {\n const altDir = join(thisDir, 'commands');\n if (!existsSync(altDir)) return;\n return copyCommandsFrom(altDir, cwd);\n }\n copyCommandsFrom(srcDir, cwd);\n}\n\nfunction copyCommandsFrom(srcDir: string, cwd: string): void {\n const targetBase = join(cwd, '.claude', 'commands');\n\n const routerSrc = join(srcDir, 'modu.md');\n if (existsSync(routerSrc)) {\n mkdirSync(targetBase, { recursive: true });\n writeFileSync(join(targetBase, 'modu.md'), readFileSync(routerSrc));\n }\n\n const subDir = join(srcDir, 'modu');\n if (!existsSync(subDir)) return;\n\n const targetSub = join(targetBase, 'modu');\n mkdirSync(targetSub, { recursive: true });\n\n let count = 0;\n for (const file of readdirSync(subDir)) {\n if (!file.endsWith('.md')) continue;\n writeFileSync(join(targetSub, file), readFileSync(join(subDir, file)));\n count++;\n }\n\n console.log(`\\n✓ Slash commands installed to ${targetBase} (${count} commands)`);\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, readFileSync, 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 private static readonly PLUGIN_NAME = 'opencode-modu-arena';\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 configFile() { return join(this.configDir, 'opencode.json'); }\n\n getHookPath() { return this.configFile; }\n detect() { return existsSync(this.configDir); }\n\n // OpenCode uses a JS plugin system, not shell hooks — registers plugin in opencode.json\n install(_apiKey: string) {\n try {\n let config: Record<string, unknown> = {};\n if (existsSync(this.configFile)) {\n const raw = readFileSync(this.configFile, 'utf-8');\n config = JSON.parse(raw) as Record<string, unknown>;\n }\n\n const plugins = (Array.isArray(config.plugin) ? config.plugin : []) as string[];\n\n if (plugins.some((p) => p === OpenCodeAdapter.PLUGIN_NAME || p.startsWith(`${OpenCodeAdapter.PLUGIN_NAME}@`))) {\n return { success: true, message: `${this.displayName} plugin already registered`, hookPath: this.configFile };\n }\n\n plugins.push(OpenCodeAdapter.PLUGIN_NAME);\n config.plugin = plugins;\n\n if (!existsSync(this.configDir)) mkdirSync(this.configDir, { recursive: true });\n writeFileSync(this.configFile, JSON.stringify(config, null, 4) + '\\n');\n\n return { success: true, message: `${this.displayName} plugin registered in ${this.configFile}`, hookPath: this.configFile };\n } catch (err) {\n return { success: false, message: `Failed to register ${this.displayName} plugin: ${err}` };\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","readdirSync","writeFileSync","mkdirSync","unlinkSync","homedir","dirname","join","createHash","execSync","readFileSync","writeFileSync","existsSync","mkdirSync","homedir","join","join","homedir","existsSync","readFileSync","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","dirname","mkdirSync","writeFileSync","readdirSync","createHash"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suncreation/modu-arena",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
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": {
@@ -8,6 +8,7 @@
8
8
  },
9
9
  "files": [
10
10
  "dist",
11
+ "commands",
11
12
  "README.md"
12
13
  ],
13
14
  "scripts": {