vibemancer 0.1.8 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +23 -10
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -15,7 +15,7 @@ import { execFile } from "child_process";
|
|
|
15
15
|
// src/bot-discovery.ts
|
|
16
16
|
import fs from "fs";
|
|
17
17
|
import path from "path";
|
|
18
|
-
async function discoverBot(projectDir, overridePath) {
|
|
18
|
+
async function discoverBot(projectDir, overridePath, options = {}) {
|
|
19
19
|
const absDir = path.resolve(projectDir);
|
|
20
20
|
if (overridePath) {
|
|
21
21
|
const absPath = path.resolve(absDir, overridePath);
|
|
@@ -43,7 +43,17 @@ async function discoverBot(projectDir, overridePath) {
|
|
|
43
43
|
if (config.bot) {
|
|
44
44
|
const botPath = path.resolve(absDir, config.bot);
|
|
45
45
|
if (!fs.existsSync(botPath)) {
|
|
46
|
-
|
|
46
|
+
if (!options.allowMissingFile) {
|
|
47
|
+
throw new Error(`Bot file from vibemancer.json not found: ${botPath}`);
|
|
48
|
+
}
|
|
49
|
+
if (!config.export) {
|
|
50
|
+
throw new Error(
|
|
51
|
+
`Bot file ${botPath} does not exist yet, and vibemancer.json has no "export" field.
|
|
52
|
+
Add the wizard name so it can be restored, e.g.:
|
|
53
|
+
{"bot": "src/bot.ts", "export": "MyWizard"}`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
return { sourcePath: botPath, exportName: config.export };
|
|
47
57
|
}
|
|
48
58
|
const exportName = config.export || await findExportName(botPath);
|
|
49
59
|
return { sourcePath: botPath, exportName };
|
|
@@ -994,10 +1004,10 @@ function credentialsPath() {
|
|
|
994
1004
|
return join(configDir(), "credentials.json");
|
|
995
1005
|
}
|
|
996
1006
|
function loadCredentials() {
|
|
997
|
-
const
|
|
998
|
-
if (!existsSync(
|
|
1007
|
+
const path5 = credentialsPath();
|
|
1008
|
+
if (!existsSync(path5)) return null;
|
|
999
1009
|
try {
|
|
1000
|
-
const parsed = JSON.parse(readFileSync2(
|
|
1010
|
+
const parsed = JSON.parse(readFileSync2(path5, "utf-8"));
|
|
1001
1011
|
if (typeof parsed === "object" && parsed !== null && "refreshToken" in parsed && typeof parsed.refreshToken === "string" && "accessToken" in parsed && typeof parsed.accessToken === "string" && "expiresAt" in parsed && typeof parsed.expiresAt === "number") {
|
|
1002
1012
|
return { refreshToken: parsed.refreshToken, accessToken: parsed.accessToken, expiresAt: parsed.expiresAt };
|
|
1003
1013
|
}
|
|
@@ -1008,10 +1018,10 @@ function loadCredentials() {
|
|
|
1008
1018
|
}
|
|
1009
1019
|
function saveCredentials(credentials) {
|
|
1010
1020
|
mkdirSync(configDir(), { recursive: true });
|
|
1011
|
-
const
|
|
1012
|
-
writeFileSync2(
|
|
1021
|
+
const path5 = credentialsPath();
|
|
1022
|
+
writeFileSync2(path5, JSON.stringify(credentials, null, 2), { mode: 384 });
|
|
1013
1023
|
try {
|
|
1014
|
-
chmodSync(
|
|
1024
|
+
chmodSync(path5, 384);
|
|
1015
1025
|
} catch {
|
|
1016
1026
|
}
|
|
1017
1027
|
}
|
|
@@ -1158,15 +1168,18 @@ async function runUpload(options) {
|
|
|
1158
1168
|
|
|
1159
1169
|
// src/commands/pull.ts
|
|
1160
1170
|
import fs5 from "fs";
|
|
1171
|
+
import path4 from "path";
|
|
1161
1172
|
async function runPull(options) {
|
|
1162
1173
|
const projectDir = process.cwd();
|
|
1163
|
-
const botInfo = await discoverBot(projectDir, options.bot);
|
|
1174
|
+
const botInfo = await discoverBot(projectDir, options.bot, { allowMissingFile: true });
|
|
1175
|
+
const isNew = !fs5.existsSync(botInfo.sourcePath);
|
|
1164
1176
|
console.log(`
|
|
1165
1177
|
Pulling latest source for ${botInfo.exportName}...`);
|
|
1166
1178
|
try {
|
|
1167
1179
|
const sourceCode = await pullSource(botInfo.exportName);
|
|
1180
|
+
fs5.mkdirSync(path4.dirname(botInfo.sourcePath), { recursive: true });
|
|
1168
1181
|
fs5.writeFileSync(botInfo.sourcePath, sourceCode);
|
|
1169
|
-
console.log(` \u2713 Updated ${botInfo.sourcePath}`);
|
|
1182
|
+
console.log(` \u2713 ${isNew ? "Created" : "Updated"} ${botInfo.sourcePath}`);
|
|
1170
1183
|
console.log(` ${(sourceCode.length / 1024).toFixed(1)} KB written`);
|
|
1171
1184
|
} catch (err) {
|
|
1172
1185
|
if (err instanceof NotLoggedInError) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/dev.ts","../src/bot-discovery.ts","../src/server.ts","../src/compile-single-bot.ts","../src/commands/test.ts","../src/commands/fight.ts","../src/remote-opponent.ts","../src/commands/trace.ts","../src/commands/tournament.ts","../src/commands/optimize.ts","../src/commands/build.ts","../src/commands/bots.ts","../src/commands/upload.ts","../src/auth/oauth-client.ts","../src/auth/credentials-store.ts","../src/auth/gateway-client.ts","../src/commands/pull.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/commands/feedback.ts","../src/commands/missile-calc.ts","../src/cli.ts"],"sourcesContent":["/**\r\n * vibemancer dev\r\n *\r\n * Starts the local development server. Auto-discovers every bot in the\r\n * project's src/ tree and serves them to the hosted web client at\r\n * vibemancer.com via the #botserver= URL hash. Compiles fresh on each\r\n * request so a browser refresh always picks up the latest code. Opens\r\n * the browser automatically.\r\n *\r\n * The --bot flag is accepted for backward compatibility but no longer\r\n * used — multi-bot discovery scans src/ regardless.\r\n */\r\n\r\nimport {execFile} from 'node:child_process';\r\nimport {discoverAllBots} from '../bot-discovery.js';\r\nimport {startServer} from '../server.js';\r\n\r\nexport interface DevOptions\r\n{\r\n\tport: number;\r\n\tbot?: string;\r\n}\r\n\r\nexport async function runDev(options: DevOptions): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\r\n\t// Show what we discovered up front so the user sees it before the\r\n\t// banner lands — purely informational; the server re-scans on every\r\n\t// /local-bots request.\r\n\tconst bots = await discoverAllBots(projectDir);\r\n\tif (bots.length === 0)\r\n\t{\r\n\t\tconsole.log('No bots discovered in src/. Add a .ts file with a PascalCase export, e.g.:');\r\n\t\tconsole.log(' export function MyWizard() { return move(0, 0); }');\r\n\t}\r\n\telse\r\n\t{\r\n\t\tconsole.log(`Discovered ${bots.length} bot${bots.length === 1 ? '' : 's'}: ${bots.map((b) => b.exportName).join(', ')}`);\r\n\t}\r\n\r\n\tconst server = startServer({\r\n\t\tport: options.port,\r\n\t\tprojectDir,\r\n\t});\r\n\r\n\t// Auto-open browser once server is listening\r\n\tserver.once('listening', () =>\r\n\t{\r\n\t\tconst url = `https://vibemancer.com/#botserver=localhost:${options.port}`;\r\n\t\topenBrowser(url);\r\n\t});\r\n}\r\n\r\nfunction openBrowser(url: string): void\r\n{\r\n\tconst platform = process.platform;\r\n\r\n\ttry\r\n\t{\r\n\t\tif (platform === 'darwin')\r\n\t\t{\r\n\t\t\texecFile('open', [url], () => \r\n\t\t\t{});\r\n\t\t}\r\n\t\telse if (platform === 'win32')\r\n\t\t{\r\n\t\t\texecFile('cmd', ['/c', 'start', '', url], () => \r\n\t\t\t{});\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Linux / WSL — try xdg-open, fall back to wslview\r\n\t\t\texecFile('xdg-open', [url], (err) =>\r\n\t\t\t{\r\n\t\t\t\tif (err) execFile('wslview', [url], () => \r\n\t\t\t\t{});\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\tcatch\r\n\t{\r\n\t\t// Silently ignore — user can always open manually\r\n\t}\r\n}\r\n","/**\r\n * Bot Discovery\r\n *\r\n * Finds the user's bot source file(s) and export name(s).\r\n *\r\n * Single-bot mode (used by upload, fight, trace, etc.) resolves one bot:\r\n * 1. --bot flag\r\n * 2. vibemancer.json config\r\n * 3. Auto-scan src/ — if exactly one bot found, use it; if multiple,\r\n * error with a list so the user can pick with --bot\r\n *\r\n * Multi-bot mode (used by the dev server) auto-scans src/ for all bots.\r\n */\r\n\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\n\r\nexport interface BotInfo\r\n{\r\n\t/** Absolute path to the bot source file. */\r\n\tsourcePath: string;\r\n\t/** Named export of the bot function. */\r\n\texportName: string;\r\n}\r\n\r\ninterface VibemancerConfig\r\n{\r\n\tbot?: string;\r\n\texport?: string;\r\n}\r\n\r\nexport async function discoverBot(projectDir: string, overridePath?: string): Promise<BotInfo>\r\n{\r\n\tconst absDir = path.resolve(projectDir);\r\n\r\n\t// 1. Explicit --bot flag\r\n\tif (overridePath)\r\n\t{\r\n\t\tconst absPath = path.resolve(absDir, overridePath);\r\n\t\tif (!fs.existsSync(absPath))\r\n\t\t{\r\n\t\t\tthrow new Error(`Bot file not found: ${absPath}`);\r\n\t\t}\r\n\t\tconst exportName = await findExportName(absPath);\r\n\t\treturn {sourcePath: absPath, exportName};\r\n\t}\r\n\r\n\t// 2. vibemancer.json config\r\n\tconst configPath = path.join(absDir, 'vibemancer.json');\r\n\tif (fs.existsSync(configPath))\r\n\t{\r\n\t\tconst raw = fs.readFileSync(configPath, 'utf-8');\r\n\t\tlet config: VibemancerConfig;\r\n\t\ttry\r\n\t\t{\r\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- JSON.parse returns unknown, manual validation follows\r\n\t\t\tconfig = JSON.parse(raw) as VibemancerConfig;\r\n\t\t}\r\n\t\tcatch\r\n\t\t{\r\n\t\t\tthrow new Error(`Invalid JSON in vibemancer.json: ${configPath}`);\r\n\t\t}\r\n\r\n\t\tif (config.bot !== null && config.bot !== undefined && typeof config.bot !== 'string')\r\n\t\t{\r\n\t\t\tthrow new Error(`Invalid \"bot\" field in vibemancer.json: expected string, got ${typeof config.bot}`);\r\n\t\t}\r\n\r\n\t\tif (config.export !== null && config.export !== undefined && typeof config.export !== 'string')\r\n\t\t{\r\n\t\t\tthrow new Error(`Invalid \"export\" field in vibemancer.json: expected string, got ${typeof config.export}`);\r\n\t\t}\r\n\r\n\t\tif (config.bot)\r\n\t\t{\r\n\t\t\tconst botPath = path.resolve(absDir, config.bot);\r\n\t\t\tif (!fs.existsSync(botPath))\r\n\t\t\t{\r\n\t\t\t\tthrow new Error(`Bot file from vibemancer.json not found: ${botPath}`);\r\n\t\t\t}\r\n\t\t\tconst exportName = config.export || await findExportName(botPath);\r\n\t\t\treturn {sourcePath: botPath, exportName};\r\n\t\t}\r\n\t}\r\n\r\n\t// 3. Auto-discover from src/\r\n\tconst allBots = await discoverAllBots(absDir);\r\n\tif (allBots.length === 1)\r\n\t{\r\n\t\treturn allBots[0]!;\r\n\t}\r\n\tif (allBots.length > 1)\r\n\t{\r\n\t\tconst list = allBots.map((b) => ` --bot ${path.relative(absDir, b.sourcePath).replace(/\\\\/g, '/')} (${b.exportName})`).join('\\n');\r\n\t\tthrow new Error(\r\n\t\t\t`Found ${allBots.length} bots. Pick one with --bot:\\n\\n${list}`,\r\n\t\t);\r\n\t}\r\n\r\n\t// No bots auto-discovered. If src/bot.ts exists, try it directly\r\n\t// so the user gets a specific error (e.g. \"no PascalCase export\").\r\n\tconst defaultPath = path.join(absDir, 'src', 'bot.ts');\r\n\tif (fs.existsSync(defaultPath))\r\n\t{\r\n\t\tconst exportName = await findExportName(defaultPath);\r\n\t\treturn {sourcePath: defaultPath, exportName};\r\n\t}\r\n\r\n\tthrow new Error(\r\n\t\t'Could not find bot source file.\\n'\r\n\t\t+ 'Create a .ts file in src/ with a PascalCase export, e.g.:\\n'\r\n\t\t+ ' export function MyWizard() { ... }',\r\n\t);\r\n}\r\n\r\n/**\r\n * Find the first named export from a TypeScript file.\r\n * Uses a simple regex scan — no full parser needed.\r\n */\r\nasync function findExportName(filePath: string): Promise<string>\r\n{\r\n\tconst content = fs.readFileSync(filePath, 'utf-8');\r\n\r\n\t// Match: export function Foo, export const Foo, export class Foo\r\n\tconst match = content.match(/export\\s+(?:function|const|class)\\s+([A-Z]\\w*)/);\r\n\tif (match?.[1])\r\n\t{\r\n\t\treturn match[1];\r\n\t}\r\n\r\n\t// Match: export { Foo }\r\n\tconst reExport = content.match(/export\\s*\\{\\s*([A-Z]\\w*)/);\r\n\tif (reExport?.[1])\r\n\t{\r\n\t\treturn reExport[1];\r\n\t}\r\n\r\n\tthrow new Error(\r\n\t\t`Could not find a named export in ${filePath}.\\n`\r\n\t\t+ 'Bot export must start with a capital letter (PascalCase).\\n'\r\n\t\t+ 'Example: export function MyWizard() { ... }',\r\n\t);\r\n}\r\n\r\nconst SCAN_SKIP_FILE_PATTERNS = [\r\n\t/\\.d\\.ts$/,\r\n\t/\\.test\\.tsx?$/,\r\n\t/\\.spec\\.tsx?$/,\r\n];\r\nconst SCAN_SKIP_DIR_NAMES = new Set([\r\n\t'node_modules',\r\n\t'dist',\r\n\t'build',\r\n\t'.cache',\r\n\t'.turbo',\r\n\t'__tests__',\r\n]);\r\nconst SCAN_SKIP_FILE_NAMES = new Set([\r\n\t'index.ts', 'index.tsx',\r\n\t'types.ts', 'types.tsx',\r\n\t'helpers.ts', 'helpers.tsx',\r\n]);\r\n\r\nfunction listTsFilesRecursively(rootDir: string): string[]\r\n{\r\n\tconst out: string[] = [];\r\n\tconst stack: string[] = [rootDir];\r\n\twhile (stack.length > 0)\r\n\t{\r\n\t\tconst dir = stack.pop();\r\n\t\tif (dir === undefined) continue;\r\n\t\tlet entries: fs.Dirent[];\r\n\t\ttry\r\n\t\t{\r\n\t\t\tentries = fs.readdirSync(dir, {withFileTypes: true});\r\n\t\t}\r\n\t\tcatch\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tfor (const entry of entries)\r\n\t\t{\r\n\t\t\tconst full = path.join(dir, entry.name);\r\n\t\t\tif (entry.isDirectory())\r\n\t\t\t{\r\n\t\t\t\tif (SCAN_SKIP_DIR_NAMES.has(entry.name)) continue;\r\n\t\t\t\tif (entry.name.startsWith('.')) continue;\r\n\t\t\t\tstack.push(full);\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif (!entry.isFile()) continue;\r\n\t\t\tif (!entry.name.endsWith('.ts') && !entry.name.endsWith('.tsx')) continue;\r\n\t\t\tif (SCAN_SKIP_FILE_NAMES.has(entry.name)) continue;\r\n\t\t\tif (SCAN_SKIP_FILE_PATTERNS.some((re) => re.test(entry.name))) continue;\r\n\t\t\tout.push(full);\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\n/**\r\n * Discover every bot in the project's src/ tree. One file → one bot\r\n * (using its first PascalCase named export). Files without a qualifying\r\n * export are skipped. Returns BotInfo[] sorted alphabetically by export\r\n * name; the array is empty if nothing was found (callers should treat\r\n * that as \"no local bots\", not an error).\r\n *\r\n * Used by the dev server to expose every in-development bot to the web\r\n * client. Single-bot commands (upload, fight, build) still go through\r\n * discoverBot() with its --bot/--export overrides.\r\n */\r\nexport async function discoverAllBots(projectDir: string): Promise<BotInfo[]>\r\n{\r\n\tconst absDir = path.resolve(projectDir);\r\n\tconst srcDir = path.join(absDir, 'src');\r\n\tif (!fs.existsSync(srcDir)) return [];\r\n\r\n\tconst files = listTsFilesRecursively(srcDir);\r\n\tconst bots: BotInfo[] = [];\r\n\tconst seenNames = new Set<string>();\r\n\tfor (const file of files)\r\n\t{\r\n\t\tlet exportName: string;\r\n\t\ttry\r\n\t\t{\r\n\t\t\texportName = await findExportName(file);\r\n\t\t}\r\n\t\tcatch\r\n\t\t{\r\n\t\t\tcontinue; // file has no PascalCase export — not a bot\r\n\t\t}\r\n\t\tif (seenNames.has(exportName)) continue; // duplicate name — keep the first\r\n\t\tseenNames.add(exportName);\r\n\t\tbots.push({sourcePath: file, exportName});\r\n\t}\r\n\tbots.sort((a, b) => a.exportName.localeCompare(b.exportName));\r\n\treturn bots;\r\n}\r\n","/**\n * Dev Server\n *\n * HTTP server with CORS that exposes every locally-developed bot in the\n * project's src/ tree to the VibeMancer web client. Each request compiles\n * the requested bot fresh from source — no caching — so a browser refresh\n * always picks up the latest code.\n *\n * Endpoints:\n * GET /local-bots → {bots: [{name, exportName, sourcePath}]}\n * GET /local-bots/:name/bundle → IIFE bundle setting __injectedBot1\n * GET /health → {status: 'ok'}\n *\n * The web client picks this up via the #botserver=localhost:PORT URL\n * hash and renders the local bots in WizardSourceSelector's \"Local\"\n * tab — usable as either combatant in Arena fights and as the\n * opponent in Manual Play.\n */\n\nimport http from 'node:http';\nimport {discoverAllBots, type BotInfo} from './bot-discovery.js';\nimport {compileSingleBotBundle} from './compile-single-bot.js';\n\nexport interface ServerOptions\n{\n\tport: number;\n\tprojectDir: string;\n}\n\ninterface LocalBotsResponse\n{\n\tbots: {\n\t\tname: string;\n\t\texportName: string;\n\t\tsourcePath: string;\n\t}[];\n}\n\nfunction botInfoToWire(info: BotInfo): LocalBotsResponse['bots'][number]\n{\n\treturn {\n\t\tname: info.exportName,\n\t\texportName: info.exportName,\n\t\tsourcePath: info.sourcePath,\n\t};\n}\n\n/**\n * Start the dev server.\n * Returns the running server instance.\n */\nexport function startServer(options: ServerOptions): http.Server\n{\n\tconst {port, projectDir} = options;\n\n\tasync function loadBots(): Promise<BotInfo[]>\n\t{\n\t\t// Re-scan on every request so newly-added bot files are picked up\n\t\t// without having to restart the server. Discovery is cheap (regex\n\t\t// scan of src/), so this is fine.\n\t\treturn discoverAllBots(projectDir);\n\t}\n\n\tconst server = http.createServer(async(req, res) =>\n\t{\n\t\t// CORS — the hosted viewer at vibemancer.com has to be able to call us\n\t\tres.setHeader('Access-Control-Allow-Origin', '*');\n\t\tres.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');\n\t\tres.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n\t\tif (req.method === 'OPTIONS')\n\t\t{\n\t\t\tres.writeHead(204);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url ?? '/', `http://localhost:${port}`);\n\t\tconst pathname = url.pathname;\n\n\t\ttry\n\t\t{\n\t\t\tif (pathname === '/health')\n\t\t\t{\n\t\t\t\trespond(res, 200, {status: 'ok'});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (pathname === '/local-bots')\n\t\t\t{\n\t\t\t\tconst bots = await loadBots();\n\t\t\t\tconst body: LocalBotsResponse = {bots: bots.map(botInfoToWire)};\n\t\t\t\trespond(res, 200, body);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst bundleMatch = /^\\/local-bots\\/([A-Za-z_][A-Za-z0-9_]*)\\/bundle$/.exec(pathname);\n\t\t\tif (bundleMatch)\n\t\t\t{\n\t\t\t\tconst requestedName = bundleMatch[1]!;\n\t\t\t\tconst bots = await loadBots();\n\t\t\t\tconst target = bots.find((b) => b.exportName === requestedName);\n\t\t\t\tif (!target)\n\t\t\t\t{\n\t\t\t\t\trespond(res, 404, {error: `No local bot named \"${requestedName}\". Found: ${bots.map((b) => b.exportName).join(', ') || '(none)'}`});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst start = Date.now();\n\t\t\t\tconst bundle = await compileSingleBotBundle(target.sourcePath, target.exportName);\n\t\t\t\tconst elapsed = Date.now() - start;\n\t\t\t\tconsole.log(` Compiled ${target.exportName} (${(bundle.length / 1024).toFixed(1)} KB) in ${elapsed}ms`);\n\n\t\t\t\tres.writeHead(200, {'Content-Type': 'text/javascript'});\n\t\t\t\tres.end(bundle);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\trespond(res, 404, {error: `Not found: ${pathname}`});\n\t\t}\n\t\tcatch(error)\n\t\t{\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.error(` Error: ${message}`);\n\t\t\trespond(res, 500, {error: message});\n\t\t}\n\t});\n\n\tserver.listen(port, () =>\n\t{\n\t\tconsole.log(`\\nVibemancer dev server running at http://localhost:${port}`);\n\t\tvoid (async(): Promise<void> =>\n\t\t{\n\t\t\tconst bots = await loadBots();\n\t\t\tif (bots.length === 0)\n\t\t\t{\n\t\t\t\tconsole.log(' (no bots discovered in src/ — add a .ts file with a PascalCase export)');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tconsole.log(` Bots: ${bots.map((b) => b.exportName).join(', ')}`);\n\t\t\t}\n\t\t\tconsole.log('');\n\t\t\tconsole.log('Open your browser to play:');\n\t\t\tconsole.log(` https://vibemancer.com/#botserver=localhost:${port}\\n`);\n\t\t\tconsole.log('Endpoints:');\n\t\t\tconsole.log(' GET /local-bots - List of locally-discovered bots');\n\t\t\tconsole.log(' GET /local-bots/<name>/bundle - Compile a single bot to a sandbox-ready bundle');\n\t\t\tconsole.log(' GET /health - Server health check\\n');\n\t\t})();\n\t});\n\n\treturn server;\n}\n\nfunction respond(res: http.ServerResponse, status: number, data: unknown): void\n{\n\tres.writeHead(status, {'Content-Type': 'application/json'});\n\tres.end(JSON.stringify(data));\n}\n","/**\n * Compile a single bot to a self-contained IIFE bundle.\n *\n * The output sets `globalThis.__injectedBot1` to the bot's exported function.\n * This is the canonical \"uploaded wizard\" bundle shape — the same format the\n * Storage-uploaded wizards live in, the same format the fight-runner /\n * BrowserMatchSandbox concatenates with MATCH_TEMPLATE / MANUAL_MATCH_TEMPLATE.\n *\n * Used by:\n * - `vibemancer upload` (CLI) — uploads to Firebase Storage\n * - dev server's /local-bots/:name/bundle endpoint — served to the web\n * client when picking a local bot\n *\n * `@vibemancer/core` is aliased to the package's TypeScript source (mirroring\n * seed-bots.ts) so the bundle is fully self-contained — no runtime shims, no\n * CJS `require()`, just an IIFE that runs anywhere a Web Worker can.\n */\n\nimport {build} from 'esbuild';\nimport {findCoreSourceDir} from './opponent-resolver.js';\n\nexport async function compileSingleBotBundle(\n\tsourcePath: string,\n\texportName: string,\n): Promise<string>\n{\n\tconst coreSourceDir = findCoreSourceDir();\n\n\tconst result = await build({\n\t\tentryPoints: [sourcePath],\n\t\tbundle: true,\n\t\twrite: false,\n\t\tformat: 'iife',\n\t\tglobalName: '__botExport',\n\t\tplatform: 'neutral',\n\t\ttarget: 'es2022',\n\t\tlogLevel: 'error',\n\t\tfooter: {js: `globalThis.__injectedBot1 = __botExport.${exportName};`},\n\t\texternal: [\n\t\t\t'isolated-vm', 'esbuild',\n\t\t\t'node:*',\n\t\t],\n\t\talias: {\n\t\t\t'@vibemancer/core': coreSourceDir + '/index-browser.ts',\n\t\t},\n\t});\n\n\tif (!result.outputFiles?.[0])\n\t{\n\t\tthrow new Error('esbuild produced no output');\n\t}\n\n\treturn result.outputFiles[0].text;\n}\n","/**\r\n * vibemancer test\r\n *\r\n * Runs the user's vitest test suite. Scaffolded projects include a\r\n * tests/ directory with example tests using the testBot() helper.\r\n */\r\n\r\nimport {execSync} from 'node:child_process';\r\n\r\nexport interface TestOptions\r\n{\r\n\tbot?: string;\r\n}\r\n\r\nexport async function runTest(_options: TestOptions): Promise<void>\r\n{\r\n\tconsole.log('\\n Running tests...\\n');\r\n\r\n\ttry\r\n\t{\r\n\t\texecSync('npx vitest run', {\r\n\t\t\tstdio: 'inherit',\r\n\t\t\tcwd: process.cwd(),\r\n\t\t});\r\n\t}\r\n\tcatch\r\n\t{\r\n\t\tprocess.exit(1);\r\n\t}\r\n}\r\n","/**\r\n * vibemancer fight\r\n *\r\n * With no args: fights your bot against all 29 built-in bots and shows ranking.\r\n * With --opponent: quick fight against a single opponent.\r\n *\r\n * Results are saved to .vibemancer/history.json for comparison across runs.\r\n */\r\n\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport {BotBundle, sandboxFight, scoreFight, runBundleFight} from '@vibemancer/core';\r\nimport type {FightWinner, FightResult} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, getBuiltinBotNames, getCoreCompileOptions} from '../opponent-resolver.js';\r\nimport {isHandleSelector, resolveRemoteOpponent} from '../remote-opponent.js';\r\nimport {compileSingleBotBundle} from '../compile-single-bot.js';\r\n\r\nexport interface FightOptions\r\n{\r\n\topponent?: string;\r\n\tbot?: string;\r\n\tseed?: number;\r\n}\r\n\r\ninterface FightEntry\r\n{\r\n\topponent: string;\r\n\twinner: FightWinner;\r\n\twizard1Wins: number;\r\n\twizard2Wins: number;\r\n\tdraws: number;\r\n\tscore: number;\r\n\telapsedMs: number;\r\n}\r\n\r\ninterface HistoryEntry\r\n{\r\n\ttimestamp: string;\r\n\tbotName: string;\r\n\tresults: FightEntry[];\r\n\tsummary: {wins: number; losses: number; draws: number; score: number; maxScore: number};\r\n}\r\n\r\nexport async function runFight(options: FightOptions): Promise<void>\r\n{\r\n\tif (options.opponent)\r\n\t{\r\n\t\treturn runSingleFight({...options, opponent: options.opponent});\r\n\t}\r\n\treturn runFullFight(options);\r\n}\r\n\r\n// ─── Single opponent fight ───────────────────────────────────────────────────\r\n\r\nasync function runSingleFight(options: FightOptions & {opponent: string}): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\tconst botInfo = await discoverBot(projectDir, options.bot);\r\n\r\n\tconsole.log(`\\n Bot: ${botInfo.exportName}`);\r\n\tconsole.log(` Opponent: ${options.opponent}\\n`);\r\n\r\n\tconst start = Date.now();\r\n\tlet result: FightResult;\r\n\tif (isHandleSelector(options.opponent))\r\n\t{\r\n\t\t// Another user's uploaded bot: resolve + download its public bundle, then\r\n\t\t// run locally through the same isolated-vm engine the matchmaker uses.\r\n\t\tconsole.log(' Resolving uploaded opponent...');\r\n\t\tconst remote = await resolveRemoteOpponent(options.opponent);\r\n\t\tconst userBundle = await compileSingleBotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\t\tresult = await runBundleFight(userBundle, remote.bundle, {seed: options.seed ?? 1});\r\n\t}\r\n\telse\r\n\t{\r\n\t\tconst userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\t\tconst opponentBundle = resolveOpponent(options.opponent);\r\n\t\tresult = await sandboxFight(userBundle, opponentBundle, {\r\n\t\t\tseed: options.seed,\r\n\t\t\tcompileOptions: getCoreCompileOptions(),\r\n\t\t});\r\n\t}\r\n\tconst elapsed = Date.now() - start;\r\n\r\n\tconst {wizard1Wins, wizard2Wins, draws} = result;\r\n\tconst total = wizard1Wins + wizard2Wins + draws;\r\n\tconst outcome = result.winner === 'wizard-1' ? 'WIN'\r\n\t\t: result.winner === 'wizard-2' ? 'LOSS'\r\n\t\t\t: 'DRAW';\r\n\r\n\tconsole.log(` Result: ${outcome}`);\r\n\tconsole.log(` ${botInfo.exportName}: ${wizard1Wins}W | ${options.opponent}: ${wizard2Wins}W | Draws: ${draws}`);\r\n\tconsole.log(` (${total} matches in ${elapsed}ms)\\n`);\r\n\r\n\tif (result.winner === 'wizard-2')\r\n\t{\r\n\t\tprocess.exit(1);\r\n\t}\r\n}\r\n\r\n// ─── Full fight (all built-in bots) ─────────────────────────────────────────\r\n\r\nasync function runFullFight(options: FightOptions): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\tconst botInfo = await discoverBot(projectDir, options.bot);\r\n\tconst userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\r\n\tconst opponents = getBuiltinBotNames();\r\n\tconsole.log(`\\n Fighting ${botInfo.exportName} against ${opponents.length} built-in bots...\\n`);\r\n\r\n\tconst entries: FightEntry[] = [];\r\n\tconst overallStart = Date.now();\r\n\r\n\tfor (const opponentName of opponents)\r\n\t{\r\n\t\tconst opponentBundle = resolveOpponent(opponentName);\r\n\t\tconst start = Date.now();\r\n\t\tconst result = await sandboxFight(userBundle, opponentBundle, {\r\n\t\t\tseed: options.seed,\r\n\t\t\tcompileOptions: getCoreCompileOptions(),\r\n\t\t});\r\n\t\tconst elapsed = Date.now() - start;\r\n\t\tconst score = scoreFight(result);\r\n\r\n\t\tentries.push({\r\n\t\t\topponent: opponentName,\r\n\t\t\twinner: result.winner,\r\n\t\t\twizard1Wins: result.wizard1Wins,\r\n\t\t\twizard2Wins: result.wizard2Wins,\r\n\t\t\tdraws: result.draws,\r\n\t\t\tscore,\r\n\t\t\telapsedMs: elapsed,\r\n\t\t});\r\n\r\n\t\tconst outcome = result.winner === 'wizard-1' ? 'W'\r\n\t\t\t: result.winner === 'wizard-2' ? 'L'\r\n\t\t\t\t: 'D';\r\n\t\tconst pad = opponentName.padEnd(14);\r\n\t\tconsole.log(` ${pad} ${outcome} ${result.wizard1Wins}-${result.wizard2Wins}-${result.draws} (${elapsed}ms)`);\r\n\t}\r\n\r\n\tconst totalElapsed = Date.now() - overallStart;\r\n\tconst wins = entries.filter((e) => e.winner === 'wizard-1').length;\r\n\tconst losses = entries.filter((e) => e.winner === 'wizard-2').length;\r\n\tconst drawCount = entries.filter((e) => e.winner === 'draw').length;\r\n\tconst totalScore = entries.reduce((sum, e) => sum + e.score, 0);\r\n\tconst maxScore = opponents.length * 17.5; // 5 matches × 3.5 max per match per opponent\r\n\r\n\tconsole.log(`\\n Summary: ${wins}W ${losses}L ${drawCount}D out of ${opponents.length} opponents`);\r\n\tconsole.log(` Score: ${totalScore.toFixed(1)} / ${maxScore.toFixed(1)} (${((totalScore / maxScore) * 100).toFixed(1)}%)`);\r\n\tconsole.log(` Total time: ${(totalElapsed / 1000).toFixed(1)}s`);\r\n\r\n\t// Load previous results and show diff\r\n\tconst history = loadHistory(projectDir);\r\n\tconst previous = history.length > 0 ? history[history.length - 1]! : null;\r\n\r\n\tif (previous && previous.botName === botInfo.exportName)\r\n\t{\r\n\t\tshowDiff(entries, previous.results);\r\n\t}\r\n\r\n\t// Save current results\r\n\tconst current: HistoryEntry = {\r\n\t\ttimestamp: new Date().toISOString(),\r\n\t\tbotName: botInfo.exportName,\r\n\t\tresults: entries,\r\n\t\tsummary: {wins, losses, draws: drawCount, score: totalScore, maxScore},\r\n\t};\r\n\tsaveHistory(projectDir, history, current);\r\n\tconsole.log('');\r\n}\r\n\r\n// ─── History persistence ─────────────────────────────────────────────────────\r\n\r\nfunction getHistoryPath(projectDir: string): string\r\n{\r\n\treturn path.join(projectDir, '.vibemancer', 'history.json');\r\n}\r\n\r\nfunction loadHistory(projectDir: string): HistoryEntry[]\r\n{\r\n\tconst historyPath = getHistoryPath(projectDir);\r\n\tif (!fs.existsSync(historyPath)) return [];\r\n\ttry\r\n\t{\r\n\t\tconst raw = fs.readFileSync(historyPath, 'utf-8');\r\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- JSON file we wrote\r\n\t\treturn JSON.parse(raw) as HistoryEntry[];\r\n\t}\r\n\tcatch\r\n\t{\r\n\t\treturn [];\r\n\t}\r\n}\r\n\r\nfunction saveHistory(projectDir: string, history: HistoryEntry[], current: HistoryEntry): void\r\n{\r\n\tconst historyPath = getHistoryPath(projectDir);\r\n\tconst dir = path.dirname(historyPath);\r\n\tfs.mkdirSync(dir, {recursive: true});\r\n\r\n\t// Keep last 20 runs\r\n\tconst updated = [...history.slice(-19), current];\r\n\tfs.writeFileSync(historyPath, JSON.stringify(updated, null, '\\t') + '\\n');\r\n}\r\n\r\nfunction showDiff(current: FightEntry[], previous: FightEntry[]): void\r\n{\r\n\tconst prevMap = new Map(previous.map((e) => [e.opponent, e]));\r\n\tconst changes: string[] = [];\r\n\r\n\tfor (const entry of current)\r\n\t{\r\n\t\tconst prev = prevMap.get(entry.opponent);\r\n\t\tif (!prev) continue;\r\n\r\n\t\tconst prevOutcome = prev.winner === 'wizard-1' ? 'W' : prev.winner === 'wizard-2' ? 'L' : 'D';\r\n\t\tconst curOutcome = entry.winner === 'wizard-1' ? 'W' : entry.winner === 'wizard-2' ? 'L' : 'D';\r\n\r\n\t\tif (prevOutcome !== curOutcome)\r\n\t\t{\r\n\t\t\tchanges.push(` ${entry.opponent.padEnd(14)} ${prevOutcome} -> ${curOutcome}`);\r\n\t\t}\r\n\t}\r\n\r\n\tconst prevScore = previous.reduce((sum, e) => sum + e.score, 0);\r\n\tconst curScore = current.reduce((sum, e) => sum + e.score, 0);\r\n\tconst diff = curScore - prevScore;\r\n\r\n\tif (changes.length > 0 || Math.abs(diff) > 0.1)\r\n\t{\r\n\t\tconsole.log('\\n vs last run:');\r\n\t\tif (Math.abs(diff) > 0.1)\r\n\t\t{\r\n\t\t\tconst sign = diff > 0 ? '+' : '';\r\n\t\t\tconsole.log(` Score: ${sign}${diff.toFixed(1)}`);\r\n\t\t}\r\n\t\tfor (const change of changes)\r\n\t\t{\r\n\t\t\tconsole.log(change);\r\n\t\t}\r\n\t}\r\n}\r\n","/**\n * Resolve a `handle/botname` selector to a downloaded, ready-to-run opponent\n * bundle — so the devkit can fight any user's uploaded bot, identically to the\n * MCP fight tool and the live ladder.\n *\n * All reads are PUBLIC (no login): the wizards collection is world-readable and\n * compiled bundles in Storage are public (required for browser spectating), so\n * resolution + download need no auth. The fight then runs locally via core's\n * runBundleFight — the same isolated-vm engine the matchmaker uses.\n */\n\nimport {initializeApp, getApps, type FirebaseApp} from 'firebase/app';\nimport {getFirestore, collection, query, where, limit, getDocs, connectFirestoreEmulator, type Firestore} from 'firebase/firestore';\nimport {getStorage, ref, getBytes, connectStorageEmulator, type FirebaseStorage} from 'firebase/storage';\nimport {isBannedBotName} from '@vibemancer/core';\nimport {FIREBASE_CONFIG} from './firebase-config.js';\n\nexport interface RemoteOpponent\n{\n\tbundle: string;\n\texportName: string;\n\tlabel: string;\n}\n\n/** True when the opponent string is a `handle/botname` selector (vs a built-in name). */\nexport function isHandleSelector(opponent: string): boolean\n{\n\tconst trimmed = opponent.trim();\n\tconst slash = trimmed.indexOf('/');\n\treturn slash > 0 && slash < trimmed.length - 1;\n}\n\nlet cachedDb: Firestore | null = null;\nlet cachedStorage: FirebaseStorage | null = null;\n\nfunction getApp(): FirebaseApp\n{\n\tconst apps = getApps();\n\treturn apps.length > 0 ? apps[0]! : initializeApp(FIREBASE_CONFIG);\n}\n\n/** Talk to the local emulator instead of prod when VIBEMANCER_EMULATOR=1 (E2E tests). */\nfunction getDb(): Firestore\n{\n\tif (!cachedDb)\n\t{\n\t\tcachedDb = getFirestore(getApp());\n\t\tif (process.env.VIBEMANCER_EMULATOR === '1') connectFirestoreEmulator(cachedDb, '127.0.0.1', 8085);\n\t}\n\treturn cachedDb;\n}\n\nfunction getBucket(): FirebaseStorage\n{\n\tif (!cachedStorage)\n\t{\n\t\tcachedStorage = getStorage(getApp());\n\t\tif (process.env.VIBEMANCER_EMULATOR === '1') connectStorageEmulator(cachedStorage, '127.0.0.1', 9199);\n\t}\n\treturn cachedStorage;\n}\n\nexport async function resolveRemoteOpponent(selector: string): Promise<RemoteOpponent>\n{\n\tconst slash = selector.indexOf('/');\n\tconst handle = selector.slice(0, slash).trim().toLowerCase();\n\tconst botName = selector.slice(slash + 1).trim();\n\tif (!handle || !botName)\n\t{\n\t\tthrow new Error(`Invalid opponent \"${selector}\" — expected handle/botname (e.g. happy-golden-banana/FireMage).`);\n\t}\n\t// A filtered (banned) name resolves to nothing — same message as not-found.\n\tif (isBannedBotName(botName))\n\t{\n\t\tthrow new Error(`No active bot \"${botName}\" found for handle \"${handle}\". Check the handle + bot name (both case-insensitive) on the leaderboard.`);\n\t}\n\n\tconst db = getDb();\n\tconst snap = await getDocs(query(\n\t\tcollection(db, 'wizards'),\n\t\twhere('ownerHandle', '==', handle),\n\t\twhere('nameLower', '==', botName.toLowerCase()),\n\t\twhere('active', '==', true),\n\t\tlimit(1),\n\t));\n\tif (snap.empty)\n\t{\n\t\tthrow new Error(`No active bot \"${botName}\" found for handle \"${handle}\". Check the handle + bot name (both case-insensitive) on the leaderboard.`);\n\t}\n\n\tconst docSnap = snap.docs[0]!;\n\tconst data = docSnap.data() as {exportName?: unknown; bundlePath?: unknown};\n\tconst exportName = typeof data.exportName === 'string' ? data.exportName : '';\n\tif (!exportName)\n\t{\n\t\tthrow new Error(`Bot \"${handle}/${botName}\" is missing its export name.`);\n\t}\n\tconst bundlePath = typeof data.bundlePath === 'string' ? data.bundlePath : `bundles/${docSnap.id}.js`;\n\n\tconst bytes = await getBytes(ref(getBucket(), bundlePath));\n\tconst bundle = new TextDecoder().decode(bytes);\n\n\treturn {bundle, exportName, label: `${handle}/${botName}`};\n}\n","/**\r\n * vibemancer trace\r\n *\r\n * Runs a single match and prints a full event trace for debugging.\r\n * Shows both bots' actions: state changes, missile launches (with config),\r\n * hits, damage, dodge proximity, movement patterns, and stats.\r\n */\r\n\r\nimport {\r\n\tBotBundle, sandboxSimulate, runBundleSimulate,\r\n\textractTraceEvents, summarizeTrace, formatTraceEvents, formatTraceSummary,\r\n\tdiagnoseTrace, formatDiagnosis,\r\n\textractStats, formatStats,\r\n} from '@vibemancer/core';\r\nimport type {SimulateResult} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, getCoreCompileOptions} from '../opponent-resolver.js';\r\nimport {isHandleSelector, resolveRemoteOpponent} from '../remote-opponent.js';\r\nimport {compileSingleBotBundle} from '../compile-single-bot.js';\r\n\r\nexport interface TraceOptions\r\n{\r\n\topponent: string;\r\n\tbot?: string;\r\n\tseed?: number;\r\n\tdistance?: number;\r\n\tmaxTicks?: number;\r\n}\r\n\r\nexport async function runTrace(options: TraceOptions): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\tconst botInfo = await discoverBot(projectDir, options.bot);\r\n\r\n\tconst distance = options.distance ?? 600;\r\n\tconsole.log(`\\n Trace: ${botInfo.exportName} (W1) vs ${options.opponent} (W2) | distance: ${distance} | seed: ${options.seed ?? 1}\\n`);\r\n\r\n\tlet result: SimulateResult;\r\n\tif (isHandleSelector(options.opponent))\r\n\t{\r\n\t\t// Another user's uploaded bot: resolve + download its public bundle, then\r\n\t\t// simulate locally through the same engine the matchmaker uses.\r\n\t\tconsole.log(' Resolving uploaded opponent...');\r\n\t\tconst remote = await resolveRemoteOpponent(options.opponent);\r\n\t\tconst userBundle = await compileSingleBotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\t\tresult = await runBundleSimulate(userBundle, remote.bundle, {\r\n\t\t\tseed: options.seed ?? 1,\r\n\t\t\tspawnDistance: distance,\r\n\t\t\tmaxTicks: options.maxTicks ?? 3000,\r\n\t\t});\r\n\t}\r\n\telse\r\n\t{\r\n\t\tconst userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\t\tconst opponentBundle = resolveOpponent(options.opponent);\r\n\t\tresult = await sandboxSimulate(userBundle, opponentBundle, {\r\n\t\t\tseed: options.seed ?? 1,\r\n\t\t\tspawnDistance: distance,\r\n\t\t\tmaxTicks: options.maxTicks ?? 3000,\r\n\t\t\tcompileOptions: getCoreCompileOptions(),\r\n\t\t});\r\n\t}\r\n\r\n\tconst history = result.history;\r\n\tif (history.length === 0)\r\n\t{\r\n\t\tconsole.log(' No history available.\\n');\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Extract and print full event trace (including any bot runtime errors)\r\n\tconst events = extractTraceEvents(history, result.errors);\r\n\tconsole.log(formatTraceEvents(events));\r\n\r\n\t// Print summary (both bots)\r\n\tconst summary = summarizeTrace(events, result, botInfo.exportName, options.opponent);\r\n\tconsole.log('\\n' + formatTraceSummary(summary));\r\n\r\n\t// Print detailed stats for the user's bot\r\n\tconst stats = extractStats(result);\r\n\tconsole.log('');\r\n\tconsole.log(formatStats(stats, botInfo.exportName));\r\n\r\n\t// Print auto-diagnosis (tips for common problems)\r\n\tconst tips = diagnoseTrace(events, summary);\r\n\tif (tips.length > 0)\r\n\t{\r\n\t\tconsole.log('');\r\n\t\tconsole.log(formatDiagnosis(tips));\r\n\t}\r\n\tconsole.log('');\r\n}\r\n","/**\r\n * vibemancer tournament\r\n *\r\n * Runs the user's bot in a round-robin tournament against selected opponents.\r\n * Each pairing is a fight (10 matches: 5 spawn distances × 2 sides).\r\n */\r\n\r\nimport {BotBundle, sandboxFight, scoreFight, scoreFightAsWizard2} from '@vibemancer/core';\r\nimport type {FightResult} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, getBuiltinBotNames, getCoreCompileOptions} from '../opponent-resolver.js';\r\n\r\nexport interface TournamentOptions\r\n{\r\n\topponents?: string[];\r\n\tbot?: string;\r\n}\r\n\r\ninterface Pairing\r\n{\r\n\tbot1Name: string;\r\n\tbot2Name: string;\r\n\tbot1Bundle: BotBundle;\r\n\tbot2Bundle: BotBundle;\r\n}\r\n\r\ninterface PairingResult\r\n{\r\n\tbot1Name: string;\r\n\tbot2Name: string;\r\n\tresult: FightResult;\r\n}\r\n\r\nexport async function runTournament(options: TournamentOptions): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\tconst botInfo = await discoverBot(projectDir, options.bot);\r\n\tconst userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\r\n\t// Determine opponents\r\n\tconst opponentNames = options.opponents && options.opponents.length > 0\r\n\t\t? options.opponents\r\n\t\t: getBuiltinBotNames();\r\n\r\n\t// Build list of all participants\r\n\tconst participants: {name: string; bundle: BotBundle}[] = [\r\n\t\t{name: botInfo.exportName, bundle: userBundle},\r\n\t];\r\n\r\n\tfor (const name of opponentNames)\r\n\t{\r\n\t\tparticipants.push({name, bundle: resolveOpponent(name)});\r\n\t}\r\n\r\n\tconsole.log(`\\n Tournament: ${participants.length} participants (${participants.length * (participants.length - 1) / 2} pairings)\\n`);\r\n\r\n\t// Generate all pairings\r\n\tconst pairings: Pairing[] = [];\r\n\tfor (let i = 0; i < participants.length; i++)\r\n\t{\r\n\t\tfor (let j = i + 1; j < participants.length; j++)\r\n\t\t{\r\n\t\t\tpairings.push({\r\n\t\t\t\tbot1Name: participants[i]!.name,\r\n\t\t\t\tbot2Name: participants[j]!.name,\r\n\t\t\t\tbot1Bundle: participants[i]!.bundle,\r\n\t\t\t\tbot2Bundle: participants[j]!.bundle,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\t// Run all fights\r\n\tconst results: PairingResult[] = [];\r\n\tconst overallStart = Date.now();\r\n\r\n\tfor (const pairing of pairings)\r\n\t{\r\n\t\tconst result = await sandboxFight(pairing.bot1Bundle, pairing.bot2Bundle, {\r\n\t\t\tcompileOptions: getCoreCompileOptions(),\r\n\t\t});\r\n\t\tresults.push({\r\n\t\t\tbot1Name: pairing.bot1Name,\r\n\t\t\tbot2Name: pairing.bot2Name,\r\n\t\t\tresult,\r\n\t\t});\r\n\r\n\t\tconst outcome = result.winner === 'wizard-1' ? `${pairing.bot1Name} wins`\r\n\t\t\t: result.winner === 'wizard-2' ? `${pairing.bot2Name} wins`\r\n\t\t\t\t: 'Draw';\r\n\t\tconsole.log(` ${pairing.bot1Name} vs ${pairing.bot2Name}: ${result.wizard1Wins}-${result.wizard2Wins}-${result.draws} (${outcome})`);\r\n\t}\r\n\r\n\t// Calculate standings\r\n\tconst points = new Map<string, number>();\r\n\tconst wins = new Map<string, number>();\r\n\r\n\tfor (const p of participants)\r\n\t{\r\n\t\tpoints.set(p.name, 0);\r\n\t\twins.set(p.name, 0);\r\n\t}\r\n\r\n\tfor (const r of results)\r\n\t{\r\n\t\tconst score1 = scoreFight(r.result);\r\n\t\tconst score2 = scoreFightAsWizard2(r.result);\r\n\r\n\t\tpoints.set(r.bot1Name, (points.get(r.bot1Name) ?? 0) + score1);\r\n\t\tpoints.set(r.bot2Name, (points.get(r.bot2Name) ?? 0) + score2);\r\n\t\twins.set(r.bot1Name, (wins.get(r.bot1Name) ?? 0) + r.result.wizard1Wins);\r\n\t\twins.set(r.bot2Name, (wins.get(r.bot2Name) ?? 0) + r.result.wizard2Wins);\r\n\t}\r\n\r\n\tconst totalElapsed = Date.now() - overallStart;\r\n\r\n\t// Sort standings by points desc, then wins desc\r\n\tconst standings = [...points.entries()].sort((a, b) =>\r\n\t{\r\n\t\tif (b[1] !== a[1]) return b[1] - a[1];\r\n\t\treturn (wins.get(b[0]) ?? 0) - (wins.get(a[0]) ?? 0);\r\n\t});\r\n\r\n\tconsole.log('\\n Standings:');\r\n\tconsole.log(' ' + '-'.repeat(40));\r\n\tfor (let i = 0; i < standings.length; i++)\r\n\t{\r\n\t\tconst [name, pts] = standings[i]!;\r\n\t\tconst w = wins.get(name) ?? 0;\r\n\t\tconst rank = `#${(i + 1).toString().padStart(2)}`;\r\n\t\tconst isUser = name === botInfo.exportName ? ' *' : '';\r\n\t\tconsole.log(` ${rank} ${name.padEnd(16)} ${pts.toFixed(1)} pts ${w}W${isUser}`);\r\n\t}\r\n\r\n\tconsole.log(`\\n Total time: ${(totalElapsed / 1000).toFixed(1)}s\\n`);\r\n}\r\n","/**\r\n * vibemancer optimize\r\n *\r\n * Runs parameter optimization for the user's bot.\r\n * Scans for useParam() calls, runs coordinate descent against\r\n * all built-in opponents, and rewrites source with optimal values.\r\n */\r\n\r\nimport {readFileSync, writeFileSync} from 'node:fs';\r\nimport {BotBundle, MatchSandbox, scoreFight, generateCandidates, getEffectiveRange} from '@vibemancer/core';\r\nimport type {FightResult, FightWinner, SimulateResult, ParamDeclaration} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, getBuiltinBotNames, getCoreCompileOptions} from '../opponent-resolver.js';\r\n\r\nexport interface OptimizeOptions\r\n{\r\n\tbot?: string;\r\n\tsteps?: number;\r\n\trounds?: number;\r\n\topponents?: string[];\r\n}\r\n\r\nexport interface ParsedParam\r\n{\r\n\tname: string;\r\n\tdefaultValue: number;\r\n\tmin?: number;\r\n\tmax?: number;\r\n\tstep?: number;\r\n}\r\n\r\n// Parser-style capture: grab everything until the next , or ) instead of matching specific number formats.\r\n// This handles integers, floats, scientific notation (1e-5), negative numbers, etc.\r\nconst USEPAR_RE = /useParam\\(\\s*['\"](\\w+)['\"]\\s*,\\s*([^,)]+?)\\s*(?:,\\s*\\{([^}]*)\\})?\\s*\\)/g;\r\n\r\nfunction parseNumValue(s: string): number\r\n{\r\n\tconst n = parseFloat(s.trim());\r\n\tif (Number.isNaN(n)) throw new Error(`useParam default is not a number: \"${s.trim()}\"`);\r\n\treturn n;\r\n}\r\n\r\nexport function parseParams(source: string): ParsedParam[]\r\n{\r\n\tconst params: ParsedParam[] = [];\r\n\tconst re = new RegExp(USEPAR_RE.source, 'g');\r\n\tlet match: RegExpExecArray | null;\r\n\r\n\twhile ((match = re.exec(source)) !== null)\r\n\t{\r\n\t\tconst name = match[1]!;\r\n\t\tconst defaultValue = parseNumValue(match[2]!);\r\n\t\tconst optsStr = match[3];\r\n\r\n\t\tlet min: number | undefined;\r\n\t\tlet max: number | undefined;\r\n\t\tlet step: number | undefined;\r\n\r\n\t\tif (optsStr)\r\n\t\t{\r\n\t\t\tconst minMatch = optsStr.match(/min\\s*:\\s*([^,}]+)/);\r\n\t\t\tconst maxMatch = optsStr.match(/max\\s*:\\s*([^,}]+)/);\r\n\t\t\tconst stepMatch = optsStr.match(/step\\s*:\\s*([^,}]+)/);\r\n\t\t\tif (minMatch) min = parseNumValue(minMatch[1]!);\r\n\t\t\tif (maxMatch) max = parseNumValue(maxMatch[1]!);\r\n\t\t\tif (stepMatch) step = parseNumValue(stepMatch[1]!);\r\n\t\t}\r\n\r\n\t\tparams.push({name, defaultValue, min, max, step});\r\n\t}\r\n\r\n\treturn params;\r\n}\r\n\r\nfunction toParamDeclaration(p: ParsedParam): ParamDeclaration\r\n{\r\n\treturn {\r\n\t\tname: p.name,\r\n\t\tvalue: p.defaultValue,\r\n\t\tmin: p.min,\r\n\t\tmax: p.max,\r\n\t\tsteps: p.step ?? 5,\r\n\t};\r\n}\r\n\r\n/**\r\n * Run a full fight (10 matches: 5 spawn distances × 2 sides)\r\n * using sandbox.simulate() with param overrides.\r\n */\r\nconst SPAWN_DISTANCES = [200, 300, 400, 500, 600];\r\nconst SEEDS = [42, 137, 256];\r\n\r\nfunction runFightWithParams(\r\n\tsandbox: MatchSandbox,\r\n\tparams1: Record<string, number>,\r\n): FightResult\r\n{\r\n\tlet w1 = 0;\r\n\tlet w2 = 0;\r\n\tlet draws = 0;\r\n\tconst matches: SimulateResult[] = [];\r\n\r\n\tfor (const seed of SEEDS)\r\n\t{\r\n\t\tfor (const dist of SPAWN_DISTANCES)\r\n\t\t{\r\n\t\t\tconst r = sandbox.simulate({\r\n\t\t\t\tseed,\r\n\t\t\t\tspawnDistance: dist,\r\n\t\t\t\tskipHistory: true,\r\n\t\t\t\tparams1,\r\n\t\t\t});\r\n\t\t\tif (r.winner === 'wizard-1') w1++;\r\n\t\t\telse if (r.winner === 'wizard-2') w2++;\r\n\t\t\telse draws++;\r\n\r\n\t\t\tmatches.push(r);\r\n\t\t}\r\n\t}\r\n\r\n\treturn {\r\n\t\twizard1Wins: w1,\r\n\t\twizard2Wins: w2,\r\n\t\tdraws,\r\n\t\twinner: (w1 > w2 ? 'wizard-1' : w2 > w1 ? 'wizard-2' : 'draw') as FightWinner,\r\n\t\tmatches,\r\n\t};\r\n}\r\n\r\nasync function evaluateParams(\r\n\tuserBundle: BotBundle,\r\n\topponentBundles: BotBundle[],\r\n\tparams1: Record<string, number>,\r\n): Promise<number>\r\n{\r\n\tlet totalScore = 0;\r\n\tfor (const opponent of opponentBundles)\r\n\t{\r\n\t\tconst sandbox = await MatchSandbox.create(userBundle, opponent, {\r\n\t\t\tcompileOptions: getCoreCompileOptions(),\r\n\t\t});\r\n\t\ttry\r\n\t\t{\r\n\t\t\tconst result = runFightWithParams(sandbox, params1);\r\n\t\t\ttotalScore += scoreFight(result);\r\n\t\t}\r\n\t\tfinally\r\n\t\t{\r\n\t\t\tsandbox.dispose();\r\n\t\t}\r\n\t}\r\n\treturn totalScore;\r\n}\r\n\r\n/**\r\n * Resolve the opponent names to use for optimization.\r\n * If opponents are specified, validates them. Otherwise uses all built-in bots.\r\n */\r\nexport function resolveOpponentNames(opponents: string[] | undefined): string[]\r\n{\r\n\tif (!opponents || opponents.length === 0)\r\n\t{\r\n\t\treturn getBuiltinBotNames();\r\n\t}\r\n\r\n\t// Validate all names before starting\r\n\tconst allNames = getBuiltinBotNames();\r\n\tfor (const name of opponents)\r\n\t{\r\n\t\tif (!allNames.includes(name))\r\n\t\t{\r\n\t\t\tthrow new Error(\r\n\t\t\t\t`Unknown opponent: \"${name}\". Available bots:\\n ${allNames.join(', ')}`,\r\n\t\t\t);\r\n\t\t}\r\n\t}\r\n\r\n\treturn opponents;\r\n}\r\n\r\nexport async function runOptimize(options: OptimizeOptions): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\tconst botInfo = await discoverBot(projectDir, options.bot);\r\n\r\n\tconst source = readFileSync(botInfo.sourcePath, 'utf-8');\r\n\tconst params = parseParams(source);\r\n\r\n\tif (params.length === 0)\r\n\t{\r\n\t\tconsole.log('\\n No useParam() calls found in your bot.');\r\n\t\tconsole.log(' Add useParam(\"paramName\", defaultValue, {min, max}) to enable optimization.\\n');\r\n\t\treturn;\r\n\t}\r\n\r\n\tconsole.log(`\\n Bot: ${botInfo.exportName}`);\r\n\tconsole.log(` Parameters: ${params.length}`);\r\n\tparams.forEach((p) => console.log(` ${p.name} = ${p.defaultValue} [${p.min ?? 'auto'} .. ${p.max ?? 'auto'}]`));\r\n\r\n\tconst steps = options.steps ?? 5;\r\n\tconst maxRounds = options.rounds ?? 3;\r\n\tconst opponentNames = resolveOpponentNames(options.opponents);\r\n\tconst opponentBundles = opponentNames.map((name) => resolveOpponent(name));\r\n\tconst userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\r\n\tconsole.log(` Opponents: ${opponentBundles.length}`);\r\n\tconsole.log(` Steps per param: ${steps}`);\r\n\tconsole.log(` Max rounds: ${maxRounds}\\n`);\r\n\r\n\t// Current best values\r\n\tconst best: Record<string, number> = {};\r\n\tfor (const p of params) best[p.name] = p.defaultValue;\r\n\r\n\t// Baseline score\r\n\tlet bestScore = await evaluateParams(userBundle, opponentBundles, best);\r\n\tconsole.log(` Baseline score: ${bestScore.toFixed(1)} / ${(opponentBundles.length * SPAWN_DISTANCES.length * SEEDS.length * 3.5).toFixed(1)}\\n`);\r\n\r\n\t// Coordinate descent\r\n\tfor (let round = 0; round < maxRounds; round++)\r\n\t{\r\n\t\tlet improved = false;\r\n\t\tconsole.log(` Round ${round + 1}:`);\r\n\r\n\t\tfor (const p of params)\r\n\t\t{\r\n\t\t\tconst decl = toParamDeclaration(p);\r\n\t\t\tconst range = getEffectiveRange(decl);\r\n\t\t\tconst candidates = generateCandidates(range.min, range.max, steps);\r\n\r\n\t\t\tlet paramBest = best[p.name]!;\r\n\t\t\tlet paramBestScore = bestScore;\r\n\r\n\t\t\tfor (const candidate of candidates)\r\n\t\t\t{\r\n\t\t\t\tif (Math.abs(candidate - paramBest) < 0.001) continue;\r\n\r\n\t\t\t\tconst trial = {...best, [p.name]: candidate};\r\n\t\t\t\tconst score = await evaluateParams(userBundle, opponentBundles, trial);\r\n\r\n\t\t\t\tif (score > paramBestScore)\r\n\t\t\t\t{\r\n\t\t\t\t\tparamBest = candidate;\r\n\t\t\t\t\tparamBestScore = score;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (paramBest !== best[p.name])\r\n\t\t\t{\r\n\t\t\t\tconsole.log(` ${p.name}: ${best[p.name]} -> ${paramBest} (+${(paramBestScore - bestScore).toFixed(1)})`);\r\n\t\t\t\tbest[p.name] = paramBest;\r\n\t\t\t\tbestScore = paramBestScore;\r\n\t\t\t\timproved = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tconsole.log(` ${p.name}: ${best[p.name]} (no improvement)`);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!improved)\r\n\t\t{\r\n\t\t\tconsole.log(' No improvements found, stopping.\\n');\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tconsole.log(` Round ${round + 1} score: ${bestScore.toFixed(1)}\\n`);\r\n\t}\r\n\r\n\t// Rewrite source\r\n\tlet updated = source;\r\n\tfor (const p of params)\r\n\t{\r\n\t\tconst newVal = best[p.name]!;\r\n\t\tif (newVal !== p.defaultValue)\r\n\t\t{\r\n\t\t\tconst pattern = new RegExp(\r\n\t\t\t\t`(useParam\\\\(\\\\s*['\"]${escapeRegex(p.name)}['\"]\\\\s*,\\\\s*)${escapeRegex(String(p.defaultValue))}`,\r\n\t\t\t);\r\n\t\t\tupdated = updated.replace(pattern, `$1${newVal}`);\r\n\t\t}\r\n\t}\r\n\r\n\tif (updated !== source)\r\n\t{\r\n\t\twriteFileSync(botInfo.sourcePath, updated);\r\n\t\tconsole.log(` Source updated: ${botInfo.sourcePath}`);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tconsole.log(' No parameter changes to write.');\r\n\t}\r\n\r\n\tconsole.log(` Final score: ${bestScore.toFixed(1)} / ${(opponentBundles.length * SPAWN_DISTANCES.length * SEEDS.length * 3.5).toFixed(1)}\\n`);\r\n}\r\n\r\nfunction escapeRegex(s: string): string\r\n{\r\n\treturn s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n}\r\n","/**\r\n * vibemancer build\r\n *\r\n * Compiles the user's bot against an opponent into a standalone bundle.\r\n */\r\n\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport {BotBundle, compileMatchBundle} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, findCoreSourceDir} from '../opponent-resolver.js';\r\n\r\nexport interface BuildOptions\r\n{\r\n\topponent: string;\r\n\tbot?: string;\r\n\toutput?: string;\r\n}\r\n\r\nexport async function runBuild(options: BuildOptions): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\tconst botInfo = await discoverBot(projectDir, options.bot);\r\n\tconst coreSourceDir = findCoreSourceDir();\r\n\r\n\tconst userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\tconst opponentBundle = resolveOpponent(options.opponent);\r\n\r\n\tconsole.log(`\\n Compiling ${botInfo.exportName} vs ${options.opponent}...`);\r\n\r\n\tconst start = Date.now();\r\n\tconst bundle = await compileMatchBundle(userBundle, opponentBundle, {\r\n\t\talias: {\r\n\t\t\t'@vibemancer/core': coreSourceDir + '/index-browser.ts',\r\n\t\t},\r\n\t});\r\n\tconst elapsed = Date.now() - start;\r\n\r\n\tconst outFile = options.output ?? `dist/${botInfo.exportName}-vs-${options.opponent}.js`;\r\n\tconst outDir = path.dirname(path.resolve(outFile));\r\n\tfs.mkdirSync(outDir, {recursive: true});\r\n\tfs.writeFileSync(path.resolve(outFile), bundle);\r\n\r\n\tconst sizeKb = (bundle.length / 1024).toFixed(1);\r\n\tconsole.log(` Output: ${outFile} (${sizeKb} KB)`);\r\n\tconsole.log(` Compiled in ${elapsed}ms\\n`);\r\n}\r\n","/**\r\n * vibemancer bots\r\n *\r\n * Lists all built-in bots with descriptions, grouped by archetype.\r\n * With --name: shows detailed info about a specific bot.\r\n */\r\n\r\nimport {BOT_GROUPS, ALL_BOTS} from '@vibemancer/core';\r\nimport type {WizardEntry} from '@vibemancer/core';\r\n\r\nexport interface BotsOptions\r\n{\r\n\tname?: string;\r\n}\r\n\r\nexport function runBots(options: BotsOptions): void\r\n{\r\n\tif (options.name)\r\n\t{\r\n\t\tshowBotDetail(options.name);\r\n\t\treturn;\r\n\t}\r\n\tlistAllBots();\r\n}\r\n\r\nfunction listAllBots(): void\r\n{\r\n\tconsole.log('\\n Built-in Bots (29 total, ranked weakest → strongest)\\n');\r\n\r\n\tfor (const group of BOT_GROUPS)\r\n\t{\r\n\t\tconsole.log(` ${group.label}:`);\r\n\t\tfor (const bot of group.bots)\r\n\t\t{\r\n\t\t\tconst rank = ALL_BOTS.indexOf(bot) + 1;\r\n\t\t\tconst tierLabel = bot.tier ? `T${bot.tier}` : ' ';\r\n\t\t\tconst rankStr = `#${String(rank).padStart(2)}`;\r\n\t\t\tconsole.log(` ${rankStr} ${tierLabel} ${bot.name.padEnd(14)} ${bot.description}`);\r\n\t\t}\r\n\t\tconsole.log('');\r\n\t}\r\n}\r\n\r\nfunction showBotDetail(name: string): void\r\n{\r\n\tconst bot = ALL_BOTS.find((b) => b.name.toLowerCase() === name.toLowerCase());\r\n\tif (!bot)\r\n\t{\r\n\t\tconst available = ALL_BOTS.map((b) => b.name).join(', ');\r\n\t\tconsole.error(`\\n Unknown bot: \"${name}\"\\n Available: ${available}\\n`);\r\n\t\tprocess.exit(1);\r\n\t}\r\n\r\n\tconst rank = ALL_BOTS.indexOf(bot) + 1;\r\n\r\n\tconsole.log(`\\n ${bot.name}`);\r\n\tconsole.log(` ${'─'.repeat(40)}`);\r\n\tconsole.log(` Rank: #${rank} of ${ALL_BOTS.length}`);\r\n\tconsole.log(` Group: ${bot.group}`);\r\n\tif (bot.tier) console.log(` Tier: ${bot.tier} of 3`);\r\n\tconsole.log(` Description: ${bot.description}`);\r\n\tconsole.log(` Style: ${getStyleDescription(bot)}`);\r\n\r\n\t// Show group progression if tiered\r\n\tif (bot.tier && bot.group !== 'Standalone')\r\n\t{\r\n\t\tconst groupBots = BOT_GROUPS.find((g) => g.label === bot.group)?.bots ?? [];\r\n\t\tif (groupBots.length > 1)\r\n\t\t{\r\n\t\t\tconsole.log(`\\n ${bot.group} progression:`);\r\n\t\t\tfor (const gb of groupBots)\r\n\t\t\t{\r\n\t\t\t\tconst gbRank = ALL_BOTS.indexOf(gb) + 1;\r\n\t\t\t\tconst marker = gb.name === bot.name ? ' ←' : '';\r\n\t\t\t\tconsole.log(` T${gb.tier} ${gb.name.padEnd(14)} #${gbRank} — ${gb.description}${marker}`);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tconsole.log(`\\n To fight: vibemancer fight --opponent ${bot.name}`);\r\n\tconsole.log(` To trace: vibemancer trace --opponent ${bot.name}\\n`);\r\n}\r\n\r\nfunction getStyleDescription(bot: WizardEntry): string\r\n{\r\n\tswitch (bot.group)\r\n\t{\r\n\t\tcase 'Standalone':\r\n\t\t\tif (bot.name === 'TargetDummy') return 'Does nothing. Use for basic testing.';\r\n\t\t\tif (bot.name === 'Critter') return 'Random actions. Tests handling of unpredictable opponents.';\r\n\t\t\tif (bot.name === 'Rookie') return 'Simple homing missiles. Good first benchmark.';\r\n\t\t\tif (bot.name === 'Hogger') return 'Random but with real damage. Chaos test.';\r\n\t\t\tif (bot.name === 'Doombringer') return 'One huge missile. Tests shield timing.';\r\n\t\t\treturn bot.description;\r\n\t\tcase 'Defensive': return 'Prioritizes shields and survival. Punishes aggression with counter-missiles. Weak to chip damage and shield baiting.';\r\n\t\tcase 'Melee': return 'Blinks in close, fires fast low-range stabs. Weak to kiting and ranged pressure.';\r\n\t\tcase 'Homing': return 'Slow tracking missiles that are hard to dodge. Weak to shields and fast burst.';\r\n\t\tcase 'Caster': return 'Medium-range homing with adaptive missile fitting. Balanced offense and defense.';\r\n\t\tcase 'Sniper': return 'Intercept-predicted straight shots. High accuracy, weak to erratic movement.';\r\n\t\tcase 'Duelist': return 'Close-range fighters with balanced offense/defense. Jack of all trades.';\r\n\t\tcase 'Berserker': return 'Aggressive traders who close distance fast. Weak to kiting and strong defense.';\r\n\t\tcase 'Kiter': return 'Maintains distance while firing homing missiles. Weak to fast closers and blink gap-close.';\r\n\t\tdefault: return bot.description;\r\n\t}\r\n}\r\n","/**\n * vibemancer upload\n *\n * Compiles the user's bot into a standalone bundle and uploads it to Vibemancer\n * via the authed gateway (`POST /api/upload`), owned by the canonical Firebase\n * identity from `vibemancer login`. The server validates + dedupes; if the same\n * code was uploaded before, the old wizard is reactivated (rating/history kept).\n */\n\nimport fs from 'node:fs';\nimport {discoverBot} from '../bot-discovery.js';\nimport {compileSingleBotBundle} from '../compile-single-bot.js';\nimport {uploadBot} from '../auth/gateway-client.js';\nimport {NotLoggedInError} from '../auth/oauth-client.js';\n\nexport interface UploadOptions\n{\n\tbot?: string;\n}\n\nconst MAX_BUNDLE_BYTES = 500 * 1024;\n\nexport async function runUpload(options: UploadOptions): Promise<void>\n{\n\tconst projectDir = process.cwd();\n\tconst botInfo = await discoverBot(projectDir, options.bot);\n\n\tconsole.log(`\\n Compiling ${botInfo.exportName}...`);\n\tconst bundle = await compileSingleBotBundle(botInfo.sourcePath, botInfo.exportName);\n\tconst sizeKb = (bundle.length / 1024).toFixed(1);\n\tconsole.log(` Bundle: ${sizeKb} KB`);\n\n\tif (bundle.length > MAX_BUNDLE_BYTES)\n\t{\n\t\tconsole.error(` Error: Bundle too large (${sizeKb} KB). Max ${MAX_BUNDLE_BYTES / 1024} KB.`);\n\t\tprocess.exit(1);\n\t}\n\n\tlet sourceCode = '';\n\ttry\n\t{\n\t\tsourceCode = fs.readFileSync(botInfo.sourcePath, 'utf-8');\n\t}\n\tcatch\n\t{\n\t\t// non-fatal — source storage is optional\n\t}\n\n\tconsole.log(` Wizard: ${botInfo.exportName}`);\n\tconsole.log(' Uploading to Vibemancer...');\n\n\ttry\n\t{\n\t\tconst result = await uploadBot({\n\t\t\tbundle,\n\t\t\tname: botInfo.exportName,\n\t\t\texportName: botInfo.exportName,\n\t\t\tsourceCode,\n\t\t});\n\t\tconsole.log(` ✓ ${result.message}`);\n\t\tif (result.wizardId) console.log(` Wizard ID: ${result.wizardId}`);\n\t\tconsole.log(` Your wizard \"${botInfo.exportName}\" is now competing.\\n`);\n\t}\n\tcatch(err)\n\t{\n\t\tif (err instanceof NotLoggedInError)\n\t\t{\n\t\t\tconsole.error('\\n Not logged in. Run: vibemancer login\\n');\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconsole.error(` ✗ Upload failed: ${err instanceof Error ? err.message : String(err)}\\n`);\n\t\t}\n\t\tprocess.exit(1);\n\t}\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- OAuth 2.0 wire-format field names (grant_type, access_token, …) are snake_case by spec */\n\n/**\n * CLI OAuth client for the Vibemancer MCP gateway.\n *\n * The CLI is a PKCE OAuth client of mcp.vibemancer.com (the same gateway the MCP\n * AI clients use). `vibemancer login` runs the authorization-code flow; the\n * resulting session token carries the canonical Firebase uid. This module owns\n * PKCE, the token exchange/refresh, and handing callers a fresh access token.\n */\n\nimport {createHash, randomBytes} from 'node:crypto';\nimport {loadCredentials, saveCredentials, type Credentials} from './credentials-store.js';\n\n/** Gateway base URL; overridable for emulator/E2E via VIBEMANCER_MCP_URL. */\nexport const MCP_BASE_URL = process.env.VIBEMANCER_MCP_URL ?? 'https://mcp.vibemancer.com';\n\nexport class NotLoggedInError extends Error\n{\n\tconstructor()\n\t{\n\t\tsuper('Not logged in. Run: vibemancer login');\n\t\tthis.name = 'NotLoggedInError';\n\t}\n}\n\nexport interface Pkce\n{\n\tverifier: string;\n\tchallenge: string;\n}\n\nexport function generatePkce(): Pkce\n{\n\tconst verifier = randomBytes(32).toString('base64url');\n\tconst challenge = createHash('sha256').update(verifier).digest('base64url');\n\treturn {verifier, challenge};\n}\n\n/** Dynamic client registration → client_id (localhost/https redirect allowed). */\nexport async function registerClient(redirectUri: string): Promise<string>\n{\n\tconst res = await fetch(`${MCP_BASE_URL}/register`, {\n\t\tmethod: 'POST',\n\t\theaders: {'Content-Type': 'application/json'},\n\t\tbody: JSON.stringify({redirect_uris: [redirectUri], client_name: 'vibemancer-cli'}),\n\t});\n\tif (!res.ok) throw new Error(`Client registration failed (${res.status}).`);\n\tconst json: unknown = await res.json();\n\tconst clientId = typeof json === 'object' && json !== null && 'client_id' in json && typeof json.client_id === 'string'\n\t\t? json.client_id\n\t\t: '';\n\tif (!clientId) throw new Error('Client registration returned no client_id.');\n\treturn clientId;\n}\n\nfunction parseTokenResponse(json: unknown, fallbackRefresh: string): Credentials\n{\n\tif (typeof json !== 'object' || json === null) throw new Error('Invalid token response.');\n\tconst accessToken = 'access_token' in json && typeof json.access_token === 'string' ? json.access_token : '';\n\tif (!accessToken) throw new Error('Token response missing access_token.');\n\tconst refreshToken = 'refresh_token' in json && typeof json.refresh_token === 'string' ? json.refresh_token : fallbackRefresh;\n\tconst expiresIn = 'expires_in' in json && typeof json.expires_in === 'number' ? json.expires_in : 3600;\n\treturn {accessToken, refreshToken, expiresAt: Date.now() + expiresIn * 1000};\n}\n\n/** Exchange an authorization code (PKCE) for tokens, and persist them. */\nexport async function exchangeCode(code: string, codeVerifier: string): Promise<Credentials>\n{\n\tconst res = await fetch(`${MCP_BASE_URL}/token`, {\n\t\tmethod: 'POST',\n\t\theaders: {'Content-Type': 'application/json'},\n\t\tbody: JSON.stringify({grant_type: 'authorization_code', code, code_verifier: codeVerifier}),\n\t});\n\tif (!res.ok) throw new Error(`Token exchange failed (${res.status}): ${await res.text()}`);\n\tconst creds = parseTokenResponse(await res.json(), '');\n\tsaveCredentials(creds);\n\treturn creds;\n}\n\nasync function refreshCredentials(refreshToken: string): Promise<Credentials>\n{\n\tconst res = await fetch(`${MCP_BASE_URL}/token`, {\n\t\tmethod: 'POST',\n\t\theaders: {'Content-Type': 'application/json'},\n\t\tbody: JSON.stringify({grant_type: 'refresh_token', refresh_token: refreshToken}),\n\t});\n\tif (!res.ok) throw new NotLoggedInError();\n\tconst creds = parseTokenResponse(await res.json(), refreshToken);\n\tsaveCredentials(creds);\n\treturn creds;\n}\n\nconst REFRESH_SKEW_MS = 60_000;\n\n/** A valid access token, refreshing silently when within 60s of expiry. */\nexport async function getAccessToken(): Promise<string>\n{\n\tconst creds = loadCredentials();\n\tif (!creds) throw new NotLoggedInError();\n\tif (creds.expiresAt - Date.now() > REFRESH_SKEW_MS) return creds.accessToken;\n\tconst refreshed = await refreshCredentials(creds.refreshToken);\n\treturn refreshed.accessToken;\n}\n","/**\n * Local credential store for the CLI's OAuth session.\n *\n * Persists the refresh + access tokens at ~/.vibemancer/credentials.json so the\n * user stays logged in between commands. The directory is overridable via\n * VIBEMANCER_CONFIG_DIR (tests, or users who relocate their config).\n */\n\nimport {chmodSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync} from 'node:fs';\nimport {homedir} from 'node:os';\nimport {join} from 'node:path';\n\nexport interface Credentials\n{\n\trefreshToken: string;\n\taccessToken: string;\n\t/** Epoch milliseconds at which the access token expires. */\n\texpiresAt: number;\n}\n\nfunction configDir(): string\n{\n\treturn process.env.VIBEMANCER_CONFIG_DIR ?? join(homedir(), '.vibemancer');\n}\n\nfunction credentialsPath(): string\n{\n\treturn join(configDir(), 'credentials.json');\n}\n\nexport function loadCredentials(): Credentials | null\n{\n\tconst path = credentialsPath();\n\tif (!existsSync(path)) return null;\n\ttry\n\t{\n\t\tconst parsed: unknown = JSON.parse(readFileSync(path, 'utf-8'));\n\t\tif (\n\t\t\ttypeof parsed === 'object' && parsed !== null\n\t\t\t&& 'refreshToken' in parsed && typeof parsed.refreshToken === 'string'\n\t\t\t&& 'accessToken' in parsed && typeof parsed.accessToken === 'string'\n\t\t\t&& 'expiresAt' in parsed && typeof parsed.expiresAt === 'number'\n\t\t)\n\t\t{\n\t\t\treturn {refreshToken: parsed.refreshToken, accessToken: parsed.accessToken, expiresAt: parsed.expiresAt};\n\t\t}\n\t\treturn null;\n\t}\n\tcatch\n\t{\n\t\treturn null;\n\t}\n}\n\nexport function saveCredentials(credentials: Credentials): void\n{\n\tmkdirSync(configDir(), {recursive: true});\n\tconst path = credentialsPath();\n\twriteFileSync(path, JSON.stringify(credentials, null, 2), {mode: 0o600});\n\t// Best-effort tighten perms (no-op semantics on Windows).\n\ttry\n\t{\n\t\tchmodSync(path, 0o600);\n\t}\n\tcatch\n\t{\n\t\t// ignore — Windows / restricted FS\n\t}\n}\n\nexport function clearCredentials(): void\n{\n\ttry\n\t{\n\t\trmSync(credentialsPath(), {force: true});\n\t}\n\tcatch\n\t{\n\t\t// ignore\n\t}\n}\n","/**\n * Client for the authed gateway REST endpoints. Attaches the Bearer session\n * token (carrying the canonical Firebase uid) and parses responses. This is the\n * single network path the CLI uses to upload + pull.\n */\n\nimport {getAccessToken, MCP_BASE_URL} from './oauth-client.js';\n\nexport interface UploadPayload\n{\n\tbundle: string;\n\tname: string;\n\texportName: string;\n\tsourceCode: string;\n}\n\nexport interface UploadResult\n{\n\twizardId: string;\n\tmessage: string;\n}\n\nexport async function uploadBot(payload: UploadPayload): Promise<UploadResult>\n{\n\tconst token = await getAccessToken();\n\tconst res = await fetch(`${MCP_BASE_URL}/api/upload`, {\n\t\tmethod: 'POST',\n\t\theaders: {'Content-Type': 'application/json', Authorization: `Bearer ${token}`},\n\t\tbody: JSON.stringify(payload),\n\t});\n\tif (!res.ok) throw new Error(`Upload failed (${res.status}): ${await res.text()}`);\n\tconst data: unknown = await res.json();\n\tconst wizardId = typeof data === 'object' && data !== null && 'wizardId' in data && typeof data.wizardId === 'string'\n\t\t? data.wizardId\n\t\t: '';\n\tconst message = typeof data === 'object' && data !== null && 'message' in data && typeof data.message === 'string'\n\t\t? data.message\n\t\t: 'Uploaded.';\n\treturn {wizardId, message};\n}\n\nexport async function pullSource(name: string): Promise<string>\n{\n\tconst token = await getAccessToken();\n\tconst res = await fetch(`${MCP_BASE_URL}/api/pull?name=${encodeURIComponent(name)}`, {\n\t\theaders: {Authorization: `Bearer ${token}`},\n\t});\n\tif (!res.ok) throw new Error(`Pull failed (${res.status}): ${await res.text()}`);\n\tconst data: unknown = await res.json();\n\tconst source = typeof data === 'object' && data !== null && 'sourceCode' in data && typeof data.sourceCode === 'string'\n\t\t? data.sourceCode\n\t\t: '';\n\tif (source) return source;\n\tconst error = typeof data === 'object' && data !== null && 'error' in data && typeof data.error === 'string'\n\t\t? data.error\n\t\t: 'No source returned.';\n\tthrow new Error(error);\n}\n","/**\n * vibemancer pull\n *\n * Downloads the latest source of your active wizard (by export name) from the\n * authed gateway (`GET /api/pull`) and writes it to the local bot file. Enables\n * round-tripping between MCP chat sessions and local CLI development.\n */\n\nimport fs from 'node:fs';\nimport {discoverBot} from '../bot-discovery.js';\nimport {pullSource} from '../auth/gateway-client.js';\nimport {NotLoggedInError} from '../auth/oauth-client.js';\n\nexport interface PullOptions\n{\n\tbot?: string;\n}\n\nexport async function runPull(options: PullOptions): Promise<void>\n{\n\tconst projectDir = process.cwd();\n\tconst botInfo = await discoverBot(projectDir, options.bot);\n\n\tconsole.log(`\\n Pulling latest source for ${botInfo.exportName}...`);\n\n\ttry\n\t{\n\t\tconst sourceCode = await pullSource(botInfo.exportName);\n\t\tfs.writeFileSync(botInfo.sourcePath, sourceCode);\n\t\tconsole.log(` ✓ Updated ${botInfo.sourcePath}`);\n\t\tconsole.log(` ${(sourceCode.length / 1024).toFixed(1)} KB written`);\n\t}\n\tcatch(err)\n\t{\n\t\tif (err instanceof NotLoggedInError)\n\t\t{\n\t\t\tconsole.error('\\n Not logged in. Run: vibemancer login\\n');\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconsole.error(` Pull failed: ${err instanceof Error ? err.message : String(err)}`);\n\t\t\tconsole.error(' Upload first with: vibemancer upload\\n');\n\t\t}\n\t\tprocess.exit(1);\n\t}\n}\n","/**\n * vibemancer login\n *\n * Authenticates the CLI as an OAuth client of the MCP gateway. The resulting\n * session token carries the canonical Firebase uid (the same identity the web\n * and MCP use), so uploads from the CLI are owned by the same account.\n *\n * Default: browser loopback (a localhost server catches the redirect).\n * `--no-browser`: print the URL + paste the code shown on the gateway page.\n */\n\nimport {createServer, type IncomingMessage, type ServerResponse} from 'node:http';\nimport {randomBytes} from 'node:crypto';\nimport {spawn} from 'node:child_process';\nimport {createInterface} from 'node:readline/promises';\nimport {generatePkce, registerClient, exchangeCode, MCP_BASE_URL} from '../auth/oauth-client.js';\n\nexport interface LoginOptions\n{\n\tnoBrowser?: boolean;\n}\n\nexport function buildAuthorizeUrl(\n\tbaseUrl: string,\n\tparams: {clientId: string; redirectUri: string; challenge: string; state: string},\n): string\n{\n\tconst u = new URL(`${baseUrl}/authorize`);\n\tu.searchParams.set('response_type', 'code');\n\tu.searchParams.set('client_id', params.clientId);\n\tu.searchParams.set('redirect_uri', params.redirectUri);\n\tu.searchParams.set('code_challenge', params.challenge);\n\tu.searchParams.set('code_challenge_method', 'S256');\n\tu.searchParams.set('state', params.state);\n\treturn u.toString();\n}\n\nexport function extractCodeFromCallback(reqUrl: string, expectedState: string): {code: string} | {error: string}\n{\n\tconst u = new URL(reqUrl, 'http://localhost');\n\tconst code = u.searchParams.get('code');\n\tconst state = u.searchParams.get('state');\n\tif (!code) return {error: 'No authorization code in the callback.'};\n\tif (state !== expectedState) return {error: 'State mismatch (possible CSRF) — try again.'};\n\treturn {code};\n}\n\nfunction openBrowser(url: string): void\n{\n\ttry\n\t{\n\t\tconst child = process.platform === 'win32'\n\t\t\t? spawn('cmd', ['/c', 'start', '', url], {stdio: 'ignore', detached: true})\n\t\t\t: spawn(process.platform === 'darwin' ? 'open' : 'xdg-open', [url], {stdio: 'ignore', detached: true});\n\t\tchild.unref();\n\t}\n\tcatch\n\t{\n\t\t// non-fatal — the URL is also printed for manual opening\n\t}\n}\n\ninterface LoopbackServer\n{\n\tport: number;\n\twaitForCode: Promise<string>;\n\tclose: () => void;\n}\n\nfunction startLoopbackServer(expectedState: string): Promise<LoopbackServer>\n{\n\treturn new Promise((resolveServer) =>\n\t{\n\t\tlet resolveCode: (code: string) => void = () => undefined;\n\t\tlet rejectCode: (err: Error) => void = () => undefined;\n\t\tconst waitForCode = new Promise<string>((res, rej) =>\n\t\t{\n\t\t\tresolveCode = res;\n\t\t\trejectCode = rej;\n\t\t});\n\n\t\tconst server = createServer((req: IncomingMessage, res: ServerResponse) =>\n\t\t{\n\t\t\tconst result = extractCodeFromCallback(req.url ?? '', expectedState);\n\t\t\tif ('error' in result)\n\t\t\t{\n\t\t\t\tres.writeHead(400, {'Content-Type': 'text/html'});\n\t\t\t\tres.end('<h2>Login failed</h2><p>You can close this tab and try again.</p>');\n\t\t\t\trejectCode(new Error(result.error));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tres.writeHead(200, {'Content-Type': 'text/html'});\n\t\t\tres.end('<h2>Vibemancer login complete</h2><p>You can close this tab and return to the terminal.</p>');\n\t\t\tresolveCode(result.code);\n\t\t});\n\n\t\tserver.listen(0, '127.0.0.1', () =>\n\t\t{\n\t\t\tconst addr = server.address();\n\t\t\tconst port = typeof addr === 'object' && addr !== null ? addr.port : 0;\n\t\t\tresolveServer({port, waitForCode, close: () => server.close()});\n\t\t});\n\t});\n}\n\nasync function runBrowserLogin(challenge: string, verifier: string, state: string): Promise<void>\n{\n\tconst {port, waitForCode, close} = await startLoopbackServer(state);\n\tconst redirectUri = `http://localhost:${port}/callback`;\n\ttry\n\t{\n\t\tconst clientId = await registerClient(redirectUri);\n\t\tconst authUrl = buildAuthorizeUrl(MCP_BASE_URL, {clientId, redirectUri, challenge, state});\n\t\tconsole.log('\\n Opening your browser to sign in with Google...');\n\t\tconsole.log(` If it doesn't open, visit:\\n ${authUrl}\\n`);\n\t\topenBrowser(authUrl);\n\t\tconst code = await waitForCode;\n\t\tawait exchangeCode(code, verifier);\n\t\tconsole.log(' ✓ Logged in. You can now run `vibemancer upload`.\\n');\n\t}\n\tfinally\n\t{\n\t\tclose();\n\t}\n}\n\nasync function runPasteLogin(challenge: string, verifier: string, state: string): Promise<void>\n{\n\tconst redirectUri = `${MCP_BASE_URL}/cli-code`;\n\tconst clientId = await registerClient(redirectUri);\n\tconst authUrl = buildAuthorizeUrl(MCP_BASE_URL, {clientId, redirectUri, challenge, state});\n\tconsole.log('\\n Open this URL in a browser, sign in, then paste the code shown:\\n');\n\tconsole.log(` ${authUrl}\\n`);\n\tconst rl = createInterface({input: process.stdin, output: process.stdout});\n\tconst code = (await rl.question(' Paste code: ')).trim();\n\trl.close();\n\tif (!code)\n\t{\n\t\tconsole.error(' No code entered.');\n\t\tprocess.exit(1);\n\t}\n\tawait exchangeCode(code, verifier);\n\tconsole.log(' ✓ Logged in.\\n');\n}\n\nexport async function runLogin(options: LoginOptions): Promise<void>\n{\n\tconst {verifier, challenge} = generatePkce();\n\tconst state = randomBytes(16).toString('hex');\n\tif (options.noBrowser)\n\t{\n\t\tawait runPasteLogin(challenge, verifier, state);\n\t}\n\telse\n\t{\n\t\tawait runBrowserLogin(challenge, verifier, state);\n\t}\n}\n","/**\n * vibemancer logout — clear the cached OAuth credentials.\n */\n\nimport {clearCredentials} from '../auth/credentials-store.js';\n\nexport function runLogout(): void\n{\n\tclearCredentials();\n\tconsole.log(' Logged out.');\n}\n","export interface FeedbackOptions\n{\n\tmessage: string;\n}\n\nexport async function runFeedback(options: FeedbackOptions): Promise<void>\n{\n\tconst message = options.message.trim();\n\tif (!message)\n\t{\n\t\tconsole.error(' Error: feedback message cannot be empty.');\n\t\tprocess.exit(1);\n\t}\n\n\tconsole.log('\\n Submitting feedback...');\n\n\ttry\n\t{\n\t\tconst {initializeApp} = await import('firebase/app');\n\t\tconst {getFunctions, httpsCallable} = await import('firebase/functions');\n\t\tconst {FIREBASE_CONFIG} = await import('../firebase-config.js');\n\n\t\tconst app = initializeApp(FIREBASE_CONFIG);\n\n\t\tconst functions = getFunctions(app, 'us-central1');\n\t\tconst submitFn = httpsCallable(functions, 'submitFeedback');\n\t\tawait submitFn({message});\n\n\t\tconsole.log(' Sent! Thanks for the feedback.\\n');\n\t}\n\tcatch(err: unknown)\n\t{\n\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\tconsole.error(` Failed to submit: ${msg}\\n`);\n\t\tprocess.exit(1);\n\t}\n}\n","import {calculateMissileCastTime, GCD_DURATION, TICKS_PER_SECOND, calculateMissileRadius} from '@vibemancer/core';\n\nexport interface MissileCalcOptions\n{\n\tdamage: number;\n\tspeed: number;\n\tduration: number;\n\tturnRate: number;\n}\n\nexport function runMissileCalc(options: MissileCalcOptions): void\n{\n\tconst config = {\n\t\tdamage: options.damage,\n\t\tspeed: options.speed,\n\t\tduration: options.duration,\n\t\tturnRate: options.turnRate,\n\t};\n\n\tconst castTimeSec = calculateMissileCastTime(config);\n\tconst castFrames = Math.max(1, Math.round(castTimeSec * TICKS_PER_SECOND));\n\tconst gcdSec = GCD_DURATION / TICKS_PER_SECOND;\n\tconst totalCycleSec = castTimeSec + gcdSec;\n\tconst dps = config.damage / totalCycleSec;\n\tconst range = config.speed * config.duration;\n\tconst radius = calculateMissileRadius(config.damage);\n\n\tconsole.log(`\n Missile Calculator\n ──────────────────\n Config: damage=${config.damage} speed=${config.speed} duration=${config.duration} turnRate=${config.turnRate}\n Cast time: ${castTimeSec.toFixed(3)}s (${castFrames} frames)\n GCD: ${gcdSec}s (${GCD_DURATION} frames)\n Full cycle: ${totalCycleSec.toFixed(3)}s (cast + GCD)\n Eff. DPS: ${dps.toFixed(2)} HP/s\n Range: ${range} units (speed × duration)\n Hitbox: ${radius.toFixed(2)} radius\n`);\n}\n","/**\r\n * Vibemancer CLI\r\n *\r\n * Development tools for building wizard bots.\r\n *\r\n * Usage:\r\n * vibemancer dev [--port 4242] [--bot src/bot.ts]\r\n * vibemancer test\r\n * vibemancer fight [--opponent Battlemage]\r\n * vibemancer trace --opponent Battlemage\r\n * vibemancer tournament [opponents...]\r\n * vibemancer optimize [--opponents Battlemage,Warmage]\r\n * vibemancer build --opponent Battlemage\r\n */\r\n\r\nimport {runDev} from './commands/dev.js';\r\nimport {runTest} from './commands/test.js';\r\nimport {runFight} from './commands/fight.js';\r\nimport {runTrace} from './commands/trace.js';\r\nimport {runTournament} from './commands/tournament.js';\r\nimport {runOptimize} from './commands/optimize.js';\r\nimport {runBuild} from './commands/build.js';\r\nimport {runBots} from './commands/bots.js';\r\nimport {runUpload} from './commands/upload.js';\r\nimport {runPull} from './commands/pull.js';\r\nimport {runLogin} from './commands/login.js';\r\nimport {runLogout} from './commands/logout.js';\r\nimport {runFeedback} from './commands/feedback.js';\r\nimport {runMissileCalc} from './commands/missile-calc.js';\r\n\r\nconst args = process.argv.slice(2);\r\nconst command = args[0];\r\n\r\nfunction parseFlag(flag: string): string | undefined\r\n{\r\n\tconst idx = args.indexOf(flag);\r\n\tif (idx !== -1 && idx + 1 < args.length)\r\n\t{\r\n\t\treturn args[idx + 1];\r\n\t}\r\n\treturn undefined;\r\n}\r\n\r\nfunction parseIntFlag(flag: string, fallback: number): number\r\n{\r\n\tconst str = parseFlag(flag);\r\n\tif (str === undefined) return fallback;\r\n\tconst n = parseInt(str, 10);\r\n\tif (Number.isNaN(n))\r\n\t{\r\n\t\tconsole.error(`Error: ${flag} must be a number, got \"${str}\".`);\r\n\t\tprocess.exit(1);\r\n\t}\r\n\treturn n;\r\n}\r\n\r\nfunction printHelp(): void\r\n{\r\n\tconsole.log(`\r\nVibemancer CLI - Development tools for wizard bots\r\n\r\nUsage:\r\n vibemancer <command> [options]\r\n\r\nCommands:\r\n dev Start the development server (auto-opens browser)\r\n test Run your test suite (vitest)\r\n fight Fight against all 29 built-in bots (or a single opponent)\r\n bots List all built-in bots with descriptions\r\n trace Per-tick debug trace of a single match\r\n tournament Round-robin tournament between your bot + selected opponents\r\n optimize Optimize bot parameters via coordinate descent\r\n build Compile bot to a standalone bundle\r\n login Sign in to VibeMancer (required before upload/pull)\r\n logout Sign out\r\n upload Upload bot to VibeMancer for online competition\r\n pull Download latest source code from VibeMancer\r\n feedback Submit a bug report or suggestion\r\n missile-calc Calculate missile cast time and DPS for a config\r\n\r\nCommon options:\r\n --bot <path> Path to bot source file (default: auto-discover)\r\n\r\nDev options:\r\n --port <n> Server port (default: 4242)\r\n\r\nFight options:\r\n --opponent <name> Fight a single opponent: a built-in name OR another\r\n user's uploaded bot as handle/botname\r\n --seed <n> Random seed\r\n\r\nTrace options:\r\n --opponent <name> Opponent: a built-in name OR handle/botname (required)\r\n --seed <n> Random seed (default: 1)\r\n --distance <n> Spawn distance (default: 600)\r\n\r\nBuild options:\r\n --opponent <name> Opponent bot name (required)\r\n --output <path> Output file path (default: dist/<Bot>-vs-<Opponent>.js)\r\n\r\nOptimize options:\r\n --steps <n> Candidates per parameter (default: 5)\r\n --rounds <n> Max optimization rounds (default: 3)\r\n --opponents <list> Comma-separated bot names to optimize against (default: all)\r\n\r\nExamples:\r\n vibemancer dev\r\n vibemancer test\r\n vibemancer fight\r\n vibemancer fight --opponent Battlemage\r\n vibemancer trace --opponent Battlemage\r\n vibemancer trace --opponent Nightblade --distance 300\r\n vibemancer tournament Battlemage Warmage Archmage\r\n vibemancer optimize\r\n vibemancer build --opponent Battlemage\r\n vibemancer feedback \"missiles go through walls sometimes\"\r\n vibemancer missile-calc --damage 15 --speed 7 --duration 200 --turnRate 3\r\n`);\r\n}\r\n\r\nasync function main(): Promise<void>\r\n{\r\n\tif (!command || command === '--help' || command === '-h')\r\n\t{\r\n\t\tprintHelp();\r\n\t\treturn;\r\n\t}\r\n\r\n\tswitch (command)\r\n\t{\r\n\t\tcase 'dev':\r\n\t\t{\r\n\t\t\tconst port = parseIntFlag('--port', 4242);\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tawait runDev({port, bot});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'test':\r\n\t\t{\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tawait runTest({bot});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'fight':\r\n\t\t{\r\n\t\t\tconst opponent = parseFlag('--opponent');\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tconst seed = parseFlag('--seed') !== undefined ? parseIntFlag('--seed', 0) : undefined;\r\n\t\t\tawait runFight({opponent, bot, seed});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'trace':\r\n\t\t{\r\n\t\t\tconst opponent = parseFlag('--opponent');\r\n\t\t\tif (!opponent)\r\n\t\t\t{\r\n\t\t\t\tconst {getBuiltinBotNames} = await import('./opponent-resolver.js');\r\n\t\t\t\tconst names = getBuiltinBotNames();\r\n\t\t\t\tconst list = names.map((n) => ` --opponent ${n}`).join('\\n');\r\n\t\t\t\tconsole.error('Error: --opponent is required for trace.\\n');\r\n\t\t\t\tconsole.error(`Available opponents:\\n\\n${list}\\n`);\r\n\t\t\t\tconsole.error('Usage: vibemancer trace --opponent Battlemage');\r\n\t\t\t\tprocess.exit(1);\r\n\t\t\t}\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tconst seed = parseFlag('--seed') !== undefined ? parseIntFlag('--seed', 0) : undefined;\r\n\t\t\tconst distance = parseFlag('--distance') !== undefined ? parseIntFlag('--distance', 600) : undefined;\r\n\t\t\tawait runTrace({opponent, bot, seed, distance});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'bots':\r\n\t\t{\r\n\t\t\tconst name = parseFlag('--name') ?? args[1];\r\n\t\t\trunBots({name: name?.startsWith('--') ? undefined : name});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'tournament':\r\n\t\t{\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tconst flagIndices = new Set<number>();\r\n\t\t\tfor (let i = 1; i < args.length; i++)\r\n\t\t\t{\r\n\t\t\t\tif (args[i]!.startsWith('--'))\r\n\t\t\t\t{\r\n\t\t\t\t\tflagIndices.add(i);\r\n\t\t\t\t\tflagIndices.add(i + 1);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tconst opponents = args.slice(1).filter((_, i) => !flagIndices.has(i + 1));\r\n\t\t\tawait runTournament({opponents, bot});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'optimize':\r\n\t\t{\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tconst opponentsStr = parseFlag('--opponents');\r\n\t\t\tconst opponents = opponentsStr ? opponentsStr.split(',').map((s) => s.trim()).filter(Boolean) : undefined;\r\n\t\t\tawait runOptimize({\r\n\t\t\t\tbot,\r\n\t\t\t\tsteps: parseFlag('--steps') !== undefined ? parseIntFlag('--steps', 5) : undefined,\r\n\t\t\t\trounds: parseFlag('--rounds') !== undefined ? parseIntFlag('--rounds', 3) : undefined,\r\n\t\t\t\topponents,\r\n\t\t\t});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'build':\r\n\t\t{\r\n\t\t\tconst opponent = parseFlag('--opponent');\r\n\t\t\tif (!opponent)\r\n\t\t\t{\r\n\t\t\t\tconsole.error('Error: --opponent is required for build command.');\r\n\t\t\t\tconsole.error('Usage: vibemancer build --opponent Battlemage');\r\n\t\t\t\tprocess.exit(1);\r\n\t\t\t}\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tconst output = parseFlag('--output');\r\n\t\t\tawait runBuild({opponent, bot, output});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'upload':\r\n\t\t{\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tawait runUpload({bot});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'pull':\r\n\t\t{\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tawait runPull({bot});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'login':\r\n\t\t{\r\n\t\t\tawait runLogin({noBrowser: args.includes('--no-browser')});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'logout':\r\n\t\t{\r\n\t\t\trunLogout();\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'feedback':\r\n\t\t{\r\n\t\t\tconst message = args.slice(1).join(' ');\r\n\t\t\tawait runFeedback({message});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'missile-calc':\r\n\t\t{\r\n\t\t\trunMissileCalc({\r\n\t\t\t\tdamage: parseIntFlag('--damage', 15),\r\n\t\t\t\tspeed: parseIntFlag('--speed', 7),\r\n\t\t\t\tduration: parseIntFlag('--duration', 200),\r\n\t\t\t\tturnRate: parseIntFlag('--turnRate', 0),\r\n\t\t\t});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t\tconsole.error(`Unknown command: ${command}`);\r\n\t\t\tprintHelp();\r\n\t\t\tprocess.exit(1);\r\n\t}\r\n}\r\n\r\nmain().catch((error) =>\r\n{\r\n\tconsole.error('Error:', error instanceof Error ? error.message : error);\r\n\tprocess.exit(1);\r\n});\r\n"],"mappings":"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","names":["fs","path","path","fs","BotBundle","BotBundle","BotBundle","sandboxFight","scoreFight","BotBundle","sandboxFight","scoreFight","BotBundle","scoreFight","scoreFight","BotBundle","fs","path","BotBundle","BotBundle","path","fs","fs","readFileSync","writeFileSync","path","fs","fs","fs","randomBytes","openBrowser","randomBytes","initializeApp","FIREBASE_CONFIG","getBuiltinBotNames"]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/dev.ts","../src/bot-discovery.ts","../src/server.ts","../src/compile-single-bot.ts","../src/commands/test.ts","../src/commands/fight.ts","../src/remote-opponent.ts","../src/commands/trace.ts","../src/commands/tournament.ts","../src/commands/optimize.ts","../src/commands/build.ts","../src/commands/bots.ts","../src/commands/upload.ts","../src/auth/oauth-client.ts","../src/auth/credentials-store.ts","../src/auth/gateway-client.ts","../src/commands/pull.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/commands/feedback.ts","../src/commands/missile-calc.ts","../src/cli.ts"],"sourcesContent":["/**\r\n * vibemancer dev\r\n *\r\n * Starts the local development server. Auto-discovers every bot in the\r\n * project's src/ tree and serves them to the hosted web client at\r\n * vibemancer.com via the #botserver= URL hash. Compiles fresh on each\r\n * request so a browser refresh always picks up the latest code. Opens\r\n * the browser automatically.\r\n *\r\n * The --bot flag is accepted for backward compatibility but no longer\r\n * used — multi-bot discovery scans src/ regardless.\r\n */\r\n\r\nimport {execFile} from 'node:child_process';\r\nimport {discoverAllBots} from '../bot-discovery.js';\r\nimport {startServer} from '../server.js';\r\n\r\nexport interface DevOptions\r\n{\r\n\tport: number;\r\n\tbot?: string;\r\n}\r\n\r\nexport async function runDev(options: DevOptions): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\r\n\t// Show what we discovered up front so the user sees it before the\r\n\t// banner lands — purely informational; the server re-scans on every\r\n\t// /local-bots request.\r\n\tconst bots = await discoverAllBots(projectDir);\r\n\tif (bots.length === 0)\r\n\t{\r\n\t\tconsole.log('No bots discovered in src/. Add a .ts file with a PascalCase export, e.g.:');\r\n\t\tconsole.log(' export function MyWizard() { return move(0, 0); }');\r\n\t}\r\n\telse\r\n\t{\r\n\t\tconsole.log(`Discovered ${bots.length} bot${bots.length === 1 ? '' : 's'}: ${bots.map((b) => b.exportName).join(', ')}`);\r\n\t}\r\n\r\n\tconst server = startServer({\r\n\t\tport: options.port,\r\n\t\tprojectDir,\r\n\t});\r\n\r\n\t// Auto-open browser once server is listening\r\n\tserver.once('listening', () =>\r\n\t{\r\n\t\tconst url = `https://vibemancer.com/#botserver=localhost:${options.port}`;\r\n\t\topenBrowser(url);\r\n\t});\r\n}\r\n\r\nfunction openBrowser(url: string): void\r\n{\r\n\tconst platform = process.platform;\r\n\r\n\ttry\r\n\t{\r\n\t\tif (platform === 'darwin')\r\n\t\t{\r\n\t\t\texecFile('open', [url], () => \r\n\t\t\t{});\r\n\t\t}\r\n\t\telse if (platform === 'win32')\r\n\t\t{\r\n\t\t\texecFile('cmd', ['/c', 'start', '', url], () => \r\n\t\t\t{});\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Linux / WSL — try xdg-open, fall back to wslview\r\n\t\t\texecFile('xdg-open', [url], (err) =>\r\n\t\t\t{\r\n\t\t\t\tif (err) execFile('wslview', [url], () => \r\n\t\t\t\t{});\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\tcatch\r\n\t{\r\n\t\t// Silently ignore — user can always open manually\r\n\t}\r\n}\r\n","/**\r\n * Bot Discovery\r\n *\r\n * Finds the user's bot source file(s) and export name(s).\r\n *\r\n * Single-bot mode (used by upload, fight, trace, etc.) resolves one bot:\r\n * 1. --bot flag\r\n * 2. vibemancer.json config\r\n * 3. Auto-scan src/ — if exactly one bot found, use it; if multiple,\r\n * error with a list so the user can pick with --bot\r\n *\r\n * Multi-bot mode (used by the dev server) auto-scans src/ for all bots.\r\n */\r\n\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\n\r\nexport interface BotInfo\r\n{\r\n\t/** Absolute path to the bot source file. */\r\n\tsourcePath: string;\r\n\t/** Named export of the bot function. */\r\n\texportName: string;\r\n}\r\n\r\ninterface VibemancerConfig\r\n{\r\n\tbot?: string;\r\n\texport?: string;\r\n}\r\n\r\nexport interface DiscoverOptions\r\n{\r\n\t/**\r\n\t * Resolve the bot even when its source file does not exist yet. Only `pull` sets this:\r\n\t * it RESTORES the source onto a machine that has never had it (new laptop, fresh clone,\r\n\t * a bot written in an MCP chat session). vibemancer.json already carries both the path\r\n\t * and the export name, so nothing has to be read off disk. Commands that consume the\r\n\t * source — upload, fight, trace — leave this off and still require a real file.\r\n\t */\r\n\tallowMissingFile?: boolean;\r\n}\r\n\r\nexport async function discoverBot(projectDir: string, overridePath?: string, options: DiscoverOptions = {}): Promise<BotInfo>\r\n{\r\n\tconst absDir = path.resolve(projectDir);\r\n\r\n\t// 1. Explicit --bot flag\r\n\tif (overridePath)\r\n\t{\r\n\t\tconst absPath = path.resolve(absDir, overridePath);\r\n\t\tif (!fs.existsSync(absPath))\r\n\t\t{\r\n\t\t\tthrow new Error(`Bot file not found: ${absPath}`);\r\n\t\t}\r\n\t\tconst exportName = await findExportName(absPath);\r\n\t\treturn {sourcePath: absPath, exportName};\r\n\t}\r\n\r\n\t// 2. vibemancer.json config\r\n\tconst configPath = path.join(absDir, 'vibemancer.json');\r\n\tif (fs.existsSync(configPath))\r\n\t{\r\n\t\tconst raw = fs.readFileSync(configPath, 'utf-8');\r\n\t\tlet config: VibemancerConfig;\r\n\t\ttry\r\n\t\t{\r\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- JSON.parse returns unknown, manual validation follows\r\n\t\t\tconfig = JSON.parse(raw) as VibemancerConfig;\r\n\t\t}\r\n\t\tcatch\r\n\t\t{\r\n\t\t\tthrow new Error(`Invalid JSON in vibemancer.json: ${configPath}`);\r\n\t\t}\r\n\r\n\t\tif (config.bot !== null && config.bot !== undefined && typeof config.bot !== 'string')\r\n\t\t{\r\n\t\t\tthrow new Error(`Invalid \"bot\" field in vibemancer.json: expected string, got ${typeof config.bot}`);\r\n\t\t}\r\n\r\n\t\tif (config.export !== null && config.export !== undefined && typeof config.export !== 'string')\r\n\t\t{\r\n\t\t\tthrow new Error(`Invalid \"export\" field in vibemancer.json: expected string, got ${typeof config.export}`);\r\n\t\t}\r\n\r\n\t\tif (config.bot)\r\n\t\t{\r\n\t\t\tconst botPath = path.resolve(absDir, config.bot);\r\n\t\t\tif (!fs.existsSync(botPath))\r\n\t\t\t{\r\n\t\t\t\tif (!options.allowMissingFile)\r\n\t\t\t\t{\r\n\t\t\t\t\tthrow new Error(`Bot file from vibemancer.json not found: ${botPath}`);\r\n\t\t\t\t}\r\n\t\t\t\t// Restoring a bot that isn't on this machine yet: the export name can't be read\r\n\t\t\t\t// off disk, so vibemancer.json has to name it.\r\n\t\t\t\tif (!config.export)\r\n\t\t\t\t{\r\n\t\t\t\t\tthrow new Error(\r\n\t\t\t\t\t\t`Bot file ${botPath} does not exist yet, and vibemancer.json has no \"export\" field.\\n`\r\n\t\t\t\t\t\t+ 'Add the wizard name so it can be restored, e.g.:\\n'\r\n\t\t\t\t\t\t+ ' {\"bot\": \"src/bot.ts\", \"export\": \"MyWizard\"}',\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t\treturn {sourcePath: botPath, exportName: config.export};\r\n\t\t\t}\r\n\t\t\tconst exportName = config.export || await findExportName(botPath);\r\n\t\t\treturn {sourcePath: botPath, exportName};\r\n\t\t}\r\n\t}\r\n\r\n\t// 3. Auto-discover from src/\r\n\tconst allBots = await discoverAllBots(absDir);\r\n\tif (allBots.length === 1)\r\n\t{\r\n\t\treturn allBots[0]!;\r\n\t}\r\n\tif (allBots.length > 1)\r\n\t{\r\n\t\tconst list = allBots.map((b) => ` --bot ${path.relative(absDir, b.sourcePath).replace(/\\\\/g, '/')} (${b.exportName})`).join('\\n');\r\n\t\tthrow new Error(\r\n\t\t\t`Found ${allBots.length} bots. Pick one with --bot:\\n\\n${list}`,\r\n\t\t);\r\n\t}\r\n\r\n\t// No bots auto-discovered. If src/bot.ts exists, try it directly\r\n\t// so the user gets a specific error (e.g. \"no PascalCase export\").\r\n\tconst defaultPath = path.join(absDir, 'src', 'bot.ts');\r\n\tif (fs.existsSync(defaultPath))\r\n\t{\r\n\t\tconst exportName = await findExportName(defaultPath);\r\n\t\treturn {sourcePath: defaultPath, exportName};\r\n\t}\r\n\r\n\tthrow new Error(\r\n\t\t'Could not find bot source file.\\n'\r\n\t\t+ 'Create a .ts file in src/ with a PascalCase export, e.g.:\\n'\r\n\t\t+ ' export function MyWizard() { ... }',\r\n\t);\r\n}\r\n\r\n/**\r\n * Find the first named export from a TypeScript file.\r\n * Uses a simple regex scan — no full parser needed.\r\n */\r\nasync function findExportName(filePath: string): Promise<string>\r\n{\r\n\tconst content = fs.readFileSync(filePath, 'utf-8');\r\n\r\n\t// Match: export function Foo, export const Foo, export class Foo\r\n\tconst match = content.match(/export\\s+(?:function|const|class)\\s+([A-Z]\\w*)/);\r\n\tif (match?.[1])\r\n\t{\r\n\t\treturn match[1];\r\n\t}\r\n\r\n\t// Match: export { Foo }\r\n\tconst reExport = content.match(/export\\s*\\{\\s*([A-Z]\\w*)/);\r\n\tif (reExport?.[1])\r\n\t{\r\n\t\treturn reExport[1];\r\n\t}\r\n\r\n\tthrow new Error(\r\n\t\t`Could not find a named export in ${filePath}.\\n`\r\n\t\t+ 'Bot export must start with a capital letter (PascalCase).\\n'\r\n\t\t+ 'Example: export function MyWizard() { ... }',\r\n\t);\r\n}\r\n\r\nconst SCAN_SKIP_FILE_PATTERNS = [\r\n\t/\\.d\\.ts$/,\r\n\t/\\.test\\.tsx?$/,\r\n\t/\\.spec\\.tsx?$/,\r\n];\r\nconst SCAN_SKIP_DIR_NAMES = new Set([\r\n\t'node_modules',\r\n\t'dist',\r\n\t'build',\r\n\t'.cache',\r\n\t'.turbo',\r\n\t'__tests__',\r\n]);\r\nconst SCAN_SKIP_FILE_NAMES = new Set([\r\n\t'index.ts', 'index.tsx',\r\n\t'types.ts', 'types.tsx',\r\n\t'helpers.ts', 'helpers.tsx',\r\n]);\r\n\r\nfunction listTsFilesRecursively(rootDir: string): string[]\r\n{\r\n\tconst out: string[] = [];\r\n\tconst stack: string[] = [rootDir];\r\n\twhile (stack.length > 0)\r\n\t{\r\n\t\tconst dir = stack.pop();\r\n\t\tif (dir === undefined) continue;\r\n\t\tlet entries: fs.Dirent[];\r\n\t\ttry\r\n\t\t{\r\n\t\t\tentries = fs.readdirSync(dir, {withFileTypes: true});\r\n\t\t}\r\n\t\tcatch\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tfor (const entry of entries)\r\n\t\t{\r\n\t\t\tconst full = path.join(dir, entry.name);\r\n\t\t\tif (entry.isDirectory())\r\n\t\t\t{\r\n\t\t\t\tif (SCAN_SKIP_DIR_NAMES.has(entry.name)) continue;\r\n\t\t\t\tif (entry.name.startsWith('.')) continue;\r\n\t\t\t\tstack.push(full);\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif (!entry.isFile()) continue;\r\n\t\t\tif (!entry.name.endsWith('.ts') && !entry.name.endsWith('.tsx')) continue;\r\n\t\t\tif (SCAN_SKIP_FILE_NAMES.has(entry.name)) continue;\r\n\t\t\tif (SCAN_SKIP_FILE_PATTERNS.some((re) => re.test(entry.name))) continue;\r\n\t\t\tout.push(full);\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\n/**\r\n * Discover every bot in the project's src/ tree. One file → one bot\r\n * (using its first PascalCase named export). Files without a qualifying\r\n * export are skipped. Returns BotInfo[] sorted alphabetically by export\r\n * name; the array is empty if nothing was found (callers should treat\r\n * that as \"no local bots\", not an error).\r\n *\r\n * Used by the dev server to expose every in-development bot to the web\r\n * client. Single-bot commands (upload, fight, build) still go through\r\n * discoverBot() with its --bot/--export overrides.\r\n */\r\nexport async function discoverAllBots(projectDir: string): Promise<BotInfo[]>\r\n{\r\n\tconst absDir = path.resolve(projectDir);\r\n\tconst srcDir = path.join(absDir, 'src');\r\n\tif (!fs.existsSync(srcDir)) return [];\r\n\r\n\tconst files = listTsFilesRecursively(srcDir);\r\n\tconst bots: BotInfo[] = [];\r\n\tconst seenNames = new Set<string>();\r\n\tfor (const file of files)\r\n\t{\r\n\t\tlet exportName: string;\r\n\t\ttry\r\n\t\t{\r\n\t\t\texportName = await findExportName(file);\r\n\t\t}\r\n\t\tcatch\r\n\t\t{\r\n\t\t\tcontinue; // file has no PascalCase export — not a bot\r\n\t\t}\r\n\t\tif (seenNames.has(exportName)) continue; // duplicate name — keep the first\r\n\t\tseenNames.add(exportName);\r\n\t\tbots.push({sourcePath: file, exportName});\r\n\t}\r\n\tbots.sort((a, b) => a.exportName.localeCompare(b.exportName));\r\n\treturn bots;\r\n}\r\n","/**\n * Dev Server\n *\n * HTTP server with CORS that exposes every locally-developed bot in the\n * project's src/ tree to the VibeMancer web client. Each request compiles\n * the requested bot fresh from source — no caching — so a browser refresh\n * always picks up the latest code.\n *\n * Endpoints:\n * GET /local-bots → {bots: [{name, exportName, sourcePath}]}\n * GET /local-bots/:name/bundle → IIFE bundle setting __injectedBot1\n * GET /health → {status: 'ok'}\n *\n * The web client picks this up via the #botserver=localhost:PORT URL\n * hash and renders the local bots in WizardSourceSelector's \"Local\"\n * tab — usable as either combatant in Arena fights and as the\n * opponent in Manual Play.\n */\n\nimport http from 'node:http';\nimport {discoverAllBots, type BotInfo} from './bot-discovery.js';\nimport {compileSingleBotBundle} from './compile-single-bot.js';\n\nexport interface ServerOptions\n{\n\tport: number;\n\tprojectDir: string;\n}\n\ninterface LocalBotsResponse\n{\n\tbots: {\n\t\tname: string;\n\t\texportName: string;\n\t\tsourcePath: string;\n\t}[];\n}\n\nfunction botInfoToWire(info: BotInfo): LocalBotsResponse['bots'][number]\n{\n\treturn {\n\t\tname: info.exportName,\n\t\texportName: info.exportName,\n\t\tsourcePath: info.sourcePath,\n\t};\n}\n\n/**\n * Start the dev server.\n * Returns the running server instance.\n */\nexport function startServer(options: ServerOptions): http.Server\n{\n\tconst {port, projectDir} = options;\n\n\tasync function loadBots(): Promise<BotInfo[]>\n\t{\n\t\t// Re-scan on every request so newly-added bot files are picked up\n\t\t// without having to restart the server. Discovery is cheap (regex\n\t\t// scan of src/), so this is fine.\n\t\treturn discoverAllBots(projectDir);\n\t}\n\n\tconst server = http.createServer(async(req, res) =>\n\t{\n\t\t// CORS — the hosted viewer at vibemancer.com has to be able to call us\n\t\tres.setHeader('Access-Control-Allow-Origin', '*');\n\t\tres.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');\n\t\tres.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n\t\tif (req.method === 'OPTIONS')\n\t\t{\n\t\t\tres.writeHead(204);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\n\t\tconst url = new URL(req.url ?? '/', `http://localhost:${port}`);\n\t\tconst pathname = url.pathname;\n\n\t\ttry\n\t\t{\n\t\t\tif (pathname === '/health')\n\t\t\t{\n\t\t\t\trespond(res, 200, {status: 'ok'});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (pathname === '/local-bots')\n\t\t\t{\n\t\t\t\tconst bots = await loadBots();\n\t\t\t\tconst body: LocalBotsResponse = {bots: bots.map(botInfoToWire)};\n\t\t\t\trespond(res, 200, body);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst bundleMatch = /^\\/local-bots\\/([A-Za-z_][A-Za-z0-9_]*)\\/bundle$/.exec(pathname);\n\t\t\tif (bundleMatch)\n\t\t\t{\n\t\t\t\tconst requestedName = bundleMatch[1]!;\n\t\t\t\tconst bots = await loadBots();\n\t\t\t\tconst target = bots.find((b) => b.exportName === requestedName);\n\t\t\t\tif (!target)\n\t\t\t\t{\n\t\t\t\t\trespond(res, 404, {error: `No local bot named \"${requestedName}\". Found: ${bots.map((b) => b.exportName).join(', ') || '(none)'}`});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst start = Date.now();\n\t\t\t\tconst bundle = await compileSingleBotBundle(target.sourcePath, target.exportName);\n\t\t\t\tconst elapsed = Date.now() - start;\n\t\t\t\tconsole.log(` Compiled ${target.exportName} (${(bundle.length / 1024).toFixed(1)} KB) in ${elapsed}ms`);\n\n\t\t\t\tres.writeHead(200, {'Content-Type': 'text/javascript'});\n\t\t\t\tres.end(bundle);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\trespond(res, 404, {error: `Not found: ${pathname}`});\n\t\t}\n\t\tcatch(error)\n\t\t{\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.error(` Error: ${message}`);\n\t\t\trespond(res, 500, {error: message});\n\t\t}\n\t});\n\n\tserver.listen(port, () =>\n\t{\n\t\tconsole.log(`\\nVibemancer dev server running at http://localhost:${port}`);\n\t\tvoid (async(): Promise<void> =>\n\t\t{\n\t\t\tconst bots = await loadBots();\n\t\t\tif (bots.length === 0)\n\t\t\t{\n\t\t\t\tconsole.log(' (no bots discovered in src/ — add a .ts file with a PascalCase export)');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tconsole.log(` Bots: ${bots.map((b) => b.exportName).join(', ')}`);\n\t\t\t}\n\t\t\tconsole.log('');\n\t\t\tconsole.log('Open your browser to play:');\n\t\t\tconsole.log(` https://vibemancer.com/#botserver=localhost:${port}\\n`);\n\t\t\tconsole.log('Endpoints:');\n\t\t\tconsole.log(' GET /local-bots - List of locally-discovered bots');\n\t\t\tconsole.log(' GET /local-bots/<name>/bundle - Compile a single bot to a sandbox-ready bundle');\n\t\t\tconsole.log(' GET /health - Server health check\\n');\n\t\t})();\n\t});\n\n\treturn server;\n}\n\nfunction respond(res: http.ServerResponse, status: number, data: unknown): void\n{\n\tres.writeHead(status, {'Content-Type': 'application/json'});\n\tres.end(JSON.stringify(data));\n}\n","/**\n * Compile a single bot to a self-contained IIFE bundle.\n *\n * The output sets `globalThis.__injectedBot1` to the bot's exported function.\n * This is the canonical \"uploaded wizard\" bundle shape — the same format the\n * Storage-uploaded wizards live in, the same format the fight-runner /\n * BrowserMatchSandbox concatenates with MATCH_TEMPLATE / MANUAL_MATCH_TEMPLATE.\n *\n * Used by:\n * - `vibemancer upload` (CLI) — uploads to Firebase Storage\n * - dev server's /local-bots/:name/bundle endpoint — served to the web\n * client when picking a local bot\n *\n * `@vibemancer/core` is aliased to the package's TypeScript source (mirroring\n * seed-bots.ts) so the bundle is fully self-contained — no runtime shims, no\n * CJS `require()`, just an IIFE that runs anywhere a Web Worker can.\n */\n\nimport {build} from 'esbuild';\nimport {findCoreSourceDir} from './opponent-resolver.js';\n\nexport async function compileSingleBotBundle(\n\tsourcePath: string,\n\texportName: string,\n): Promise<string>\n{\n\tconst coreSourceDir = findCoreSourceDir();\n\n\tconst result = await build({\n\t\tentryPoints: [sourcePath],\n\t\tbundle: true,\n\t\twrite: false,\n\t\tformat: 'iife',\n\t\tglobalName: '__botExport',\n\t\tplatform: 'neutral',\n\t\ttarget: 'es2022',\n\t\tlogLevel: 'error',\n\t\tfooter: {js: `globalThis.__injectedBot1 = __botExport.${exportName};`},\n\t\texternal: [\n\t\t\t'isolated-vm', 'esbuild',\n\t\t\t'node:*',\n\t\t],\n\t\talias: {\n\t\t\t'@vibemancer/core': coreSourceDir + '/index-browser.ts',\n\t\t},\n\t});\n\n\tif (!result.outputFiles?.[0])\n\t{\n\t\tthrow new Error('esbuild produced no output');\n\t}\n\n\treturn result.outputFiles[0].text;\n}\n","/**\r\n * vibemancer test\r\n *\r\n * Runs the user's vitest test suite. Scaffolded projects include a\r\n * tests/ directory with example tests using the testBot() helper.\r\n */\r\n\r\nimport {execSync} from 'node:child_process';\r\n\r\nexport interface TestOptions\r\n{\r\n\tbot?: string;\r\n}\r\n\r\nexport async function runTest(_options: TestOptions): Promise<void>\r\n{\r\n\tconsole.log('\\n Running tests...\\n');\r\n\r\n\ttry\r\n\t{\r\n\t\texecSync('npx vitest run', {\r\n\t\t\tstdio: 'inherit',\r\n\t\t\tcwd: process.cwd(),\r\n\t\t});\r\n\t}\r\n\tcatch\r\n\t{\r\n\t\tprocess.exit(1);\r\n\t}\r\n}\r\n","/**\r\n * vibemancer fight\r\n *\r\n * With no args: fights your bot against all 29 built-in bots and shows ranking.\r\n * With --opponent: quick fight against a single opponent.\r\n *\r\n * Results are saved to .vibemancer/history.json for comparison across runs.\r\n */\r\n\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport {BotBundle, sandboxFight, scoreFight, runBundleFight} from '@vibemancer/core';\r\nimport type {FightWinner, FightResult} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, getBuiltinBotNames, getCoreCompileOptions} from '../opponent-resolver.js';\r\nimport {isHandleSelector, resolveRemoteOpponent} from '../remote-opponent.js';\r\nimport {compileSingleBotBundle} from '../compile-single-bot.js';\r\n\r\nexport interface FightOptions\r\n{\r\n\topponent?: string;\r\n\tbot?: string;\r\n\tseed?: number;\r\n}\r\n\r\ninterface FightEntry\r\n{\r\n\topponent: string;\r\n\twinner: FightWinner;\r\n\twizard1Wins: number;\r\n\twizard2Wins: number;\r\n\tdraws: number;\r\n\tscore: number;\r\n\telapsedMs: number;\r\n}\r\n\r\ninterface HistoryEntry\r\n{\r\n\ttimestamp: string;\r\n\tbotName: string;\r\n\tresults: FightEntry[];\r\n\tsummary: {wins: number; losses: number; draws: number; score: number; maxScore: number};\r\n}\r\n\r\nexport async function runFight(options: FightOptions): Promise<void>\r\n{\r\n\tif (options.opponent)\r\n\t{\r\n\t\treturn runSingleFight({...options, opponent: options.opponent});\r\n\t}\r\n\treturn runFullFight(options);\r\n}\r\n\r\n// ─── Single opponent fight ───────────────────────────────────────────────────\r\n\r\nasync function runSingleFight(options: FightOptions & {opponent: string}): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\tconst botInfo = await discoverBot(projectDir, options.bot);\r\n\r\n\tconsole.log(`\\n Bot: ${botInfo.exportName}`);\r\n\tconsole.log(` Opponent: ${options.opponent}\\n`);\r\n\r\n\tconst start = Date.now();\r\n\tlet result: FightResult;\r\n\tif (isHandleSelector(options.opponent))\r\n\t{\r\n\t\t// Another user's uploaded bot: resolve + download its public bundle, then\r\n\t\t// run locally through the same isolated-vm engine the matchmaker uses.\r\n\t\tconsole.log(' Resolving uploaded opponent...');\r\n\t\tconst remote = await resolveRemoteOpponent(options.opponent);\r\n\t\tconst userBundle = await compileSingleBotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\t\tresult = await runBundleFight(userBundle, remote.bundle, {seed: options.seed ?? 1});\r\n\t}\r\n\telse\r\n\t{\r\n\t\tconst userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\t\tconst opponentBundle = resolveOpponent(options.opponent);\r\n\t\tresult = await sandboxFight(userBundle, opponentBundle, {\r\n\t\t\tseed: options.seed,\r\n\t\t\tcompileOptions: getCoreCompileOptions(),\r\n\t\t});\r\n\t}\r\n\tconst elapsed = Date.now() - start;\r\n\r\n\tconst {wizard1Wins, wizard2Wins, draws} = result;\r\n\tconst total = wizard1Wins + wizard2Wins + draws;\r\n\tconst outcome = result.winner === 'wizard-1' ? 'WIN'\r\n\t\t: result.winner === 'wizard-2' ? 'LOSS'\r\n\t\t\t: 'DRAW';\r\n\r\n\tconsole.log(` Result: ${outcome}`);\r\n\tconsole.log(` ${botInfo.exportName}: ${wizard1Wins}W | ${options.opponent}: ${wizard2Wins}W | Draws: ${draws}`);\r\n\tconsole.log(` (${total} matches in ${elapsed}ms)\\n`);\r\n\r\n\tif (result.winner === 'wizard-2')\r\n\t{\r\n\t\tprocess.exit(1);\r\n\t}\r\n}\r\n\r\n// ─── Full fight (all built-in bots) ─────────────────────────────────────────\r\n\r\nasync function runFullFight(options: FightOptions): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\tconst botInfo = await discoverBot(projectDir, options.bot);\r\n\tconst userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\r\n\tconst opponents = getBuiltinBotNames();\r\n\tconsole.log(`\\n Fighting ${botInfo.exportName} against ${opponents.length} built-in bots...\\n`);\r\n\r\n\tconst entries: FightEntry[] = [];\r\n\tconst overallStart = Date.now();\r\n\r\n\tfor (const opponentName of opponents)\r\n\t{\r\n\t\tconst opponentBundle = resolveOpponent(opponentName);\r\n\t\tconst start = Date.now();\r\n\t\tconst result = await sandboxFight(userBundle, opponentBundle, {\r\n\t\t\tseed: options.seed,\r\n\t\t\tcompileOptions: getCoreCompileOptions(),\r\n\t\t});\r\n\t\tconst elapsed = Date.now() - start;\r\n\t\tconst score = scoreFight(result);\r\n\r\n\t\tentries.push({\r\n\t\t\topponent: opponentName,\r\n\t\t\twinner: result.winner,\r\n\t\t\twizard1Wins: result.wizard1Wins,\r\n\t\t\twizard2Wins: result.wizard2Wins,\r\n\t\t\tdraws: result.draws,\r\n\t\t\tscore,\r\n\t\t\telapsedMs: elapsed,\r\n\t\t});\r\n\r\n\t\tconst outcome = result.winner === 'wizard-1' ? 'W'\r\n\t\t\t: result.winner === 'wizard-2' ? 'L'\r\n\t\t\t\t: 'D';\r\n\t\tconst pad = opponentName.padEnd(14);\r\n\t\tconsole.log(` ${pad} ${outcome} ${result.wizard1Wins}-${result.wizard2Wins}-${result.draws} (${elapsed}ms)`);\r\n\t}\r\n\r\n\tconst totalElapsed = Date.now() - overallStart;\r\n\tconst wins = entries.filter((e) => e.winner === 'wizard-1').length;\r\n\tconst losses = entries.filter((e) => e.winner === 'wizard-2').length;\r\n\tconst drawCount = entries.filter((e) => e.winner === 'draw').length;\r\n\tconst totalScore = entries.reduce((sum, e) => sum + e.score, 0);\r\n\tconst maxScore = opponents.length * 17.5; // 5 matches × 3.5 max per match per opponent\r\n\r\n\tconsole.log(`\\n Summary: ${wins}W ${losses}L ${drawCount}D out of ${opponents.length} opponents`);\r\n\tconsole.log(` Score: ${totalScore.toFixed(1)} / ${maxScore.toFixed(1)} (${((totalScore / maxScore) * 100).toFixed(1)}%)`);\r\n\tconsole.log(` Total time: ${(totalElapsed / 1000).toFixed(1)}s`);\r\n\r\n\t// Load previous results and show diff\r\n\tconst history = loadHistory(projectDir);\r\n\tconst previous = history.length > 0 ? history[history.length - 1]! : null;\r\n\r\n\tif (previous && previous.botName === botInfo.exportName)\r\n\t{\r\n\t\tshowDiff(entries, previous.results);\r\n\t}\r\n\r\n\t// Save current results\r\n\tconst current: HistoryEntry = {\r\n\t\ttimestamp: new Date().toISOString(),\r\n\t\tbotName: botInfo.exportName,\r\n\t\tresults: entries,\r\n\t\tsummary: {wins, losses, draws: drawCount, score: totalScore, maxScore},\r\n\t};\r\n\tsaveHistory(projectDir, history, current);\r\n\tconsole.log('');\r\n}\r\n\r\n// ─── History persistence ─────────────────────────────────────────────────────\r\n\r\nfunction getHistoryPath(projectDir: string): string\r\n{\r\n\treturn path.join(projectDir, '.vibemancer', 'history.json');\r\n}\r\n\r\nfunction loadHistory(projectDir: string): HistoryEntry[]\r\n{\r\n\tconst historyPath = getHistoryPath(projectDir);\r\n\tif (!fs.existsSync(historyPath)) return [];\r\n\ttry\r\n\t{\r\n\t\tconst raw = fs.readFileSync(historyPath, 'utf-8');\r\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- JSON file we wrote\r\n\t\treturn JSON.parse(raw) as HistoryEntry[];\r\n\t}\r\n\tcatch\r\n\t{\r\n\t\treturn [];\r\n\t}\r\n}\r\n\r\nfunction saveHistory(projectDir: string, history: HistoryEntry[], current: HistoryEntry): void\r\n{\r\n\tconst historyPath = getHistoryPath(projectDir);\r\n\tconst dir = path.dirname(historyPath);\r\n\tfs.mkdirSync(dir, {recursive: true});\r\n\r\n\t// Keep last 20 runs\r\n\tconst updated = [...history.slice(-19), current];\r\n\tfs.writeFileSync(historyPath, JSON.stringify(updated, null, '\\t') + '\\n');\r\n}\r\n\r\nfunction showDiff(current: FightEntry[], previous: FightEntry[]): void\r\n{\r\n\tconst prevMap = new Map(previous.map((e) => [e.opponent, e]));\r\n\tconst changes: string[] = [];\r\n\r\n\tfor (const entry of current)\r\n\t{\r\n\t\tconst prev = prevMap.get(entry.opponent);\r\n\t\tif (!prev) continue;\r\n\r\n\t\tconst prevOutcome = prev.winner === 'wizard-1' ? 'W' : prev.winner === 'wizard-2' ? 'L' : 'D';\r\n\t\tconst curOutcome = entry.winner === 'wizard-1' ? 'W' : entry.winner === 'wizard-2' ? 'L' : 'D';\r\n\r\n\t\tif (prevOutcome !== curOutcome)\r\n\t\t{\r\n\t\t\tchanges.push(` ${entry.opponent.padEnd(14)} ${prevOutcome} -> ${curOutcome}`);\r\n\t\t}\r\n\t}\r\n\r\n\tconst prevScore = previous.reduce((sum, e) => sum + e.score, 0);\r\n\tconst curScore = current.reduce((sum, e) => sum + e.score, 0);\r\n\tconst diff = curScore - prevScore;\r\n\r\n\tif (changes.length > 0 || Math.abs(diff) > 0.1)\r\n\t{\r\n\t\tconsole.log('\\n vs last run:');\r\n\t\tif (Math.abs(diff) > 0.1)\r\n\t\t{\r\n\t\t\tconst sign = diff > 0 ? '+' : '';\r\n\t\t\tconsole.log(` Score: ${sign}${diff.toFixed(1)}`);\r\n\t\t}\r\n\t\tfor (const change of changes)\r\n\t\t{\r\n\t\t\tconsole.log(change);\r\n\t\t}\r\n\t}\r\n}\r\n","/**\n * Resolve a `handle/botname` selector to a downloaded, ready-to-run opponent\n * bundle — so the devkit can fight any user's uploaded bot, identically to the\n * MCP fight tool and the live ladder.\n *\n * All reads are PUBLIC (no login): the wizards collection is world-readable and\n * compiled bundles in Storage are public (required for browser spectating), so\n * resolution + download need no auth. The fight then runs locally via core's\n * runBundleFight — the same isolated-vm engine the matchmaker uses.\n */\n\nimport {initializeApp, getApps, type FirebaseApp} from 'firebase/app';\nimport {getFirestore, collection, query, where, limit, getDocs, connectFirestoreEmulator, type Firestore} from 'firebase/firestore';\nimport {getStorage, ref, getBytes, connectStorageEmulator, type FirebaseStorage} from 'firebase/storage';\nimport {isBannedBotName} from '@vibemancer/core';\nimport {FIREBASE_CONFIG} from './firebase-config.js';\n\nexport interface RemoteOpponent\n{\n\tbundle: string;\n\texportName: string;\n\tlabel: string;\n}\n\n/** True when the opponent string is a `handle/botname` selector (vs a built-in name). */\nexport function isHandleSelector(opponent: string): boolean\n{\n\tconst trimmed = opponent.trim();\n\tconst slash = trimmed.indexOf('/');\n\treturn slash > 0 && slash < trimmed.length - 1;\n}\n\nlet cachedDb: Firestore | null = null;\nlet cachedStorage: FirebaseStorage | null = null;\n\nfunction getApp(): FirebaseApp\n{\n\tconst apps = getApps();\n\treturn apps.length > 0 ? apps[0]! : initializeApp(FIREBASE_CONFIG);\n}\n\n/** Talk to the local emulator instead of prod when VIBEMANCER_EMULATOR=1 (E2E tests). */\nfunction getDb(): Firestore\n{\n\tif (!cachedDb)\n\t{\n\t\tcachedDb = getFirestore(getApp());\n\t\tif (process.env.VIBEMANCER_EMULATOR === '1') connectFirestoreEmulator(cachedDb, '127.0.0.1', 8085);\n\t}\n\treturn cachedDb;\n}\n\nfunction getBucket(): FirebaseStorage\n{\n\tif (!cachedStorage)\n\t{\n\t\tcachedStorage = getStorage(getApp());\n\t\tif (process.env.VIBEMANCER_EMULATOR === '1') connectStorageEmulator(cachedStorage, '127.0.0.1', 9199);\n\t}\n\treturn cachedStorage;\n}\n\nexport async function resolveRemoteOpponent(selector: string): Promise<RemoteOpponent>\n{\n\tconst slash = selector.indexOf('/');\n\tconst handle = selector.slice(0, slash).trim().toLowerCase();\n\tconst botName = selector.slice(slash + 1).trim();\n\tif (!handle || !botName)\n\t{\n\t\tthrow new Error(`Invalid opponent \"${selector}\" — expected handle/botname (e.g. happy-golden-banana/FireMage).`);\n\t}\n\t// A filtered (banned) name resolves to nothing — same message as not-found.\n\tif (isBannedBotName(botName))\n\t{\n\t\tthrow new Error(`No active bot \"${botName}\" found for handle \"${handle}\". Check the handle + bot name (both case-insensitive) on the leaderboard.`);\n\t}\n\n\tconst db = getDb();\n\tconst snap = await getDocs(query(\n\t\tcollection(db, 'wizards'),\n\t\twhere('ownerHandle', '==', handle),\n\t\twhere('nameLower', '==', botName.toLowerCase()),\n\t\twhere('active', '==', true),\n\t\tlimit(1),\n\t));\n\tif (snap.empty)\n\t{\n\t\tthrow new Error(`No active bot \"${botName}\" found for handle \"${handle}\". Check the handle + bot name (both case-insensitive) on the leaderboard.`);\n\t}\n\n\tconst docSnap = snap.docs[0]!;\n\tconst data = docSnap.data() as {exportName?: unknown; bundlePath?: unknown};\n\tconst exportName = typeof data.exportName === 'string' ? data.exportName : '';\n\tif (!exportName)\n\t{\n\t\tthrow new Error(`Bot \"${handle}/${botName}\" is missing its export name.`);\n\t}\n\tconst bundlePath = typeof data.bundlePath === 'string' ? data.bundlePath : `bundles/${docSnap.id}.js`;\n\n\tconst bytes = await getBytes(ref(getBucket(), bundlePath));\n\tconst bundle = new TextDecoder().decode(bytes);\n\n\treturn {bundle, exportName, label: `${handle}/${botName}`};\n}\n","/**\r\n * vibemancer trace\r\n *\r\n * Runs a single match and prints a full event trace for debugging.\r\n * Shows both bots' actions: state changes, missile launches (with config),\r\n * hits, damage, dodge proximity, movement patterns, and stats.\r\n */\r\n\r\nimport {\r\n\tBotBundle, sandboxSimulate, runBundleSimulate,\r\n\textractTraceEvents, summarizeTrace, formatTraceEvents, formatTraceSummary,\r\n\tdiagnoseTrace, formatDiagnosis,\r\n\textractStats, formatStats,\r\n} from '@vibemancer/core';\r\nimport type {SimulateResult} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, getCoreCompileOptions} from '../opponent-resolver.js';\r\nimport {isHandleSelector, resolveRemoteOpponent} from '../remote-opponent.js';\r\nimport {compileSingleBotBundle} from '../compile-single-bot.js';\r\n\r\nexport interface TraceOptions\r\n{\r\n\topponent: string;\r\n\tbot?: string;\r\n\tseed?: number;\r\n\tdistance?: number;\r\n\tmaxTicks?: number;\r\n}\r\n\r\nexport async function runTrace(options: TraceOptions): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\tconst botInfo = await discoverBot(projectDir, options.bot);\r\n\r\n\tconst distance = options.distance ?? 600;\r\n\tconsole.log(`\\n Trace: ${botInfo.exportName} (W1) vs ${options.opponent} (W2) | distance: ${distance} | seed: ${options.seed ?? 1}\\n`);\r\n\r\n\tlet result: SimulateResult;\r\n\tif (isHandleSelector(options.opponent))\r\n\t{\r\n\t\t// Another user's uploaded bot: resolve + download its public bundle, then\r\n\t\t// simulate locally through the same engine the matchmaker uses.\r\n\t\tconsole.log(' Resolving uploaded opponent...');\r\n\t\tconst remote = await resolveRemoteOpponent(options.opponent);\r\n\t\tconst userBundle = await compileSingleBotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\t\tresult = await runBundleSimulate(userBundle, remote.bundle, {\r\n\t\t\tseed: options.seed ?? 1,\r\n\t\t\tspawnDistance: distance,\r\n\t\t\tmaxTicks: options.maxTicks ?? 3000,\r\n\t\t});\r\n\t}\r\n\telse\r\n\t{\r\n\t\tconst userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\t\tconst opponentBundle = resolveOpponent(options.opponent);\r\n\t\tresult = await sandboxSimulate(userBundle, opponentBundle, {\r\n\t\t\tseed: options.seed ?? 1,\r\n\t\t\tspawnDistance: distance,\r\n\t\t\tmaxTicks: options.maxTicks ?? 3000,\r\n\t\t\tcompileOptions: getCoreCompileOptions(),\r\n\t\t});\r\n\t}\r\n\r\n\tconst history = result.history;\r\n\tif (history.length === 0)\r\n\t{\r\n\t\tconsole.log(' No history available.\\n');\r\n\t\treturn;\r\n\t}\r\n\r\n\t// Extract and print full event trace (including any bot runtime errors)\r\n\tconst events = extractTraceEvents(history, result.errors);\r\n\tconsole.log(formatTraceEvents(events));\r\n\r\n\t// Print summary (both bots)\r\n\tconst summary = summarizeTrace(events, result, botInfo.exportName, options.opponent);\r\n\tconsole.log('\\n' + formatTraceSummary(summary));\r\n\r\n\t// Print detailed stats for the user's bot\r\n\tconst stats = extractStats(result);\r\n\tconsole.log('');\r\n\tconsole.log(formatStats(stats, botInfo.exportName));\r\n\r\n\t// Print auto-diagnosis (tips for common problems)\r\n\tconst tips = diagnoseTrace(events, summary);\r\n\tif (tips.length > 0)\r\n\t{\r\n\t\tconsole.log('');\r\n\t\tconsole.log(formatDiagnosis(tips));\r\n\t}\r\n\tconsole.log('');\r\n}\r\n","/**\r\n * vibemancer tournament\r\n *\r\n * Runs the user's bot in a round-robin tournament against selected opponents.\r\n * Each pairing is a fight (10 matches: 5 spawn distances × 2 sides).\r\n */\r\n\r\nimport {BotBundle, sandboxFight, scoreFight, scoreFightAsWizard2} from '@vibemancer/core';\r\nimport type {FightResult} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, getBuiltinBotNames, getCoreCompileOptions} from '../opponent-resolver.js';\r\n\r\nexport interface TournamentOptions\r\n{\r\n\topponents?: string[];\r\n\tbot?: string;\r\n}\r\n\r\ninterface Pairing\r\n{\r\n\tbot1Name: string;\r\n\tbot2Name: string;\r\n\tbot1Bundle: BotBundle;\r\n\tbot2Bundle: BotBundle;\r\n}\r\n\r\ninterface PairingResult\r\n{\r\n\tbot1Name: string;\r\n\tbot2Name: string;\r\n\tresult: FightResult;\r\n}\r\n\r\nexport async function runTournament(options: TournamentOptions): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\tconst botInfo = await discoverBot(projectDir, options.bot);\r\n\tconst userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\r\n\t// Determine opponents\r\n\tconst opponentNames = options.opponents && options.opponents.length > 0\r\n\t\t? options.opponents\r\n\t\t: getBuiltinBotNames();\r\n\r\n\t// Build list of all participants\r\n\tconst participants: {name: string; bundle: BotBundle}[] = [\r\n\t\t{name: botInfo.exportName, bundle: userBundle},\r\n\t];\r\n\r\n\tfor (const name of opponentNames)\r\n\t{\r\n\t\tparticipants.push({name, bundle: resolveOpponent(name)});\r\n\t}\r\n\r\n\tconsole.log(`\\n Tournament: ${participants.length} participants (${participants.length * (participants.length - 1) / 2} pairings)\\n`);\r\n\r\n\t// Generate all pairings\r\n\tconst pairings: Pairing[] = [];\r\n\tfor (let i = 0; i < participants.length; i++)\r\n\t{\r\n\t\tfor (let j = i + 1; j < participants.length; j++)\r\n\t\t{\r\n\t\t\tpairings.push({\r\n\t\t\t\tbot1Name: participants[i]!.name,\r\n\t\t\t\tbot2Name: participants[j]!.name,\r\n\t\t\t\tbot1Bundle: participants[i]!.bundle,\r\n\t\t\t\tbot2Bundle: participants[j]!.bundle,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\t// Run all fights\r\n\tconst results: PairingResult[] = [];\r\n\tconst overallStart = Date.now();\r\n\r\n\tfor (const pairing of pairings)\r\n\t{\r\n\t\tconst result = await sandboxFight(pairing.bot1Bundle, pairing.bot2Bundle, {\r\n\t\t\tcompileOptions: getCoreCompileOptions(),\r\n\t\t});\r\n\t\tresults.push({\r\n\t\t\tbot1Name: pairing.bot1Name,\r\n\t\t\tbot2Name: pairing.bot2Name,\r\n\t\t\tresult,\r\n\t\t});\r\n\r\n\t\tconst outcome = result.winner === 'wizard-1' ? `${pairing.bot1Name} wins`\r\n\t\t\t: result.winner === 'wizard-2' ? `${pairing.bot2Name} wins`\r\n\t\t\t\t: 'Draw';\r\n\t\tconsole.log(` ${pairing.bot1Name} vs ${pairing.bot2Name}: ${result.wizard1Wins}-${result.wizard2Wins}-${result.draws} (${outcome})`);\r\n\t}\r\n\r\n\t// Calculate standings\r\n\tconst points = new Map<string, number>();\r\n\tconst wins = new Map<string, number>();\r\n\r\n\tfor (const p of participants)\r\n\t{\r\n\t\tpoints.set(p.name, 0);\r\n\t\twins.set(p.name, 0);\r\n\t}\r\n\r\n\tfor (const r of results)\r\n\t{\r\n\t\tconst score1 = scoreFight(r.result);\r\n\t\tconst score2 = scoreFightAsWizard2(r.result);\r\n\r\n\t\tpoints.set(r.bot1Name, (points.get(r.bot1Name) ?? 0) + score1);\r\n\t\tpoints.set(r.bot2Name, (points.get(r.bot2Name) ?? 0) + score2);\r\n\t\twins.set(r.bot1Name, (wins.get(r.bot1Name) ?? 0) + r.result.wizard1Wins);\r\n\t\twins.set(r.bot2Name, (wins.get(r.bot2Name) ?? 0) + r.result.wizard2Wins);\r\n\t}\r\n\r\n\tconst totalElapsed = Date.now() - overallStart;\r\n\r\n\t// Sort standings by points desc, then wins desc\r\n\tconst standings = [...points.entries()].sort((a, b) =>\r\n\t{\r\n\t\tif (b[1] !== a[1]) return b[1] - a[1];\r\n\t\treturn (wins.get(b[0]) ?? 0) - (wins.get(a[0]) ?? 0);\r\n\t});\r\n\r\n\tconsole.log('\\n Standings:');\r\n\tconsole.log(' ' + '-'.repeat(40));\r\n\tfor (let i = 0; i < standings.length; i++)\r\n\t{\r\n\t\tconst [name, pts] = standings[i]!;\r\n\t\tconst w = wins.get(name) ?? 0;\r\n\t\tconst rank = `#${(i + 1).toString().padStart(2)}`;\r\n\t\tconst isUser = name === botInfo.exportName ? ' *' : '';\r\n\t\tconsole.log(` ${rank} ${name.padEnd(16)} ${pts.toFixed(1)} pts ${w}W${isUser}`);\r\n\t}\r\n\r\n\tconsole.log(`\\n Total time: ${(totalElapsed / 1000).toFixed(1)}s\\n`);\r\n}\r\n","/**\r\n * vibemancer optimize\r\n *\r\n * Runs parameter optimization for the user's bot.\r\n * Scans for useParam() calls, runs coordinate descent against\r\n * all built-in opponents, and rewrites source with optimal values.\r\n */\r\n\r\nimport {readFileSync, writeFileSync} from 'node:fs';\r\nimport {BotBundle, MatchSandbox, scoreFight, generateCandidates, getEffectiveRange} from '@vibemancer/core';\r\nimport type {FightResult, FightWinner, SimulateResult, ParamDeclaration} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, getBuiltinBotNames, getCoreCompileOptions} from '../opponent-resolver.js';\r\n\r\nexport interface OptimizeOptions\r\n{\r\n\tbot?: string;\r\n\tsteps?: number;\r\n\trounds?: number;\r\n\topponents?: string[];\r\n}\r\n\r\nexport interface ParsedParam\r\n{\r\n\tname: string;\r\n\tdefaultValue: number;\r\n\tmin?: number;\r\n\tmax?: number;\r\n\tstep?: number;\r\n}\r\n\r\n// Parser-style capture: grab everything until the next , or ) instead of matching specific number formats.\r\n// This handles integers, floats, scientific notation (1e-5), negative numbers, etc.\r\nconst USEPAR_RE = /useParam\\(\\s*['\"](\\w+)['\"]\\s*,\\s*([^,)]+?)\\s*(?:,\\s*\\{([^}]*)\\})?\\s*\\)/g;\r\n\r\nfunction parseNumValue(s: string): number\r\n{\r\n\tconst n = parseFloat(s.trim());\r\n\tif (Number.isNaN(n)) throw new Error(`useParam default is not a number: \"${s.trim()}\"`);\r\n\treturn n;\r\n}\r\n\r\nexport function parseParams(source: string): ParsedParam[]\r\n{\r\n\tconst params: ParsedParam[] = [];\r\n\tconst re = new RegExp(USEPAR_RE.source, 'g');\r\n\tlet match: RegExpExecArray | null;\r\n\r\n\twhile ((match = re.exec(source)) !== null)\r\n\t{\r\n\t\tconst name = match[1]!;\r\n\t\tconst defaultValue = parseNumValue(match[2]!);\r\n\t\tconst optsStr = match[3];\r\n\r\n\t\tlet min: number | undefined;\r\n\t\tlet max: number | undefined;\r\n\t\tlet step: number | undefined;\r\n\r\n\t\tif (optsStr)\r\n\t\t{\r\n\t\t\tconst minMatch = optsStr.match(/min\\s*:\\s*([^,}]+)/);\r\n\t\t\tconst maxMatch = optsStr.match(/max\\s*:\\s*([^,}]+)/);\r\n\t\t\tconst stepMatch = optsStr.match(/step\\s*:\\s*([^,}]+)/);\r\n\t\t\tif (minMatch) min = parseNumValue(minMatch[1]!);\r\n\t\t\tif (maxMatch) max = parseNumValue(maxMatch[1]!);\r\n\t\t\tif (stepMatch) step = parseNumValue(stepMatch[1]!);\r\n\t\t}\r\n\r\n\t\tparams.push({name, defaultValue, min, max, step});\r\n\t}\r\n\r\n\treturn params;\r\n}\r\n\r\nfunction toParamDeclaration(p: ParsedParam): ParamDeclaration\r\n{\r\n\treturn {\r\n\t\tname: p.name,\r\n\t\tvalue: p.defaultValue,\r\n\t\tmin: p.min,\r\n\t\tmax: p.max,\r\n\t\tsteps: p.step ?? 5,\r\n\t};\r\n}\r\n\r\n/**\r\n * Run a full fight (10 matches: 5 spawn distances × 2 sides)\r\n * using sandbox.simulate() with param overrides.\r\n */\r\nconst SPAWN_DISTANCES = [200, 300, 400, 500, 600];\r\nconst SEEDS = [42, 137, 256];\r\n\r\nfunction runFightWithParams(\r\n\tsandbox: MatchSandbox,\r\n\tparams1: Record<string, number>,\r\n): FightResult\r\n{\r\n\tlet w1 = 0;\r\n\tlet w2 = 0;\r\n\tlet draws = 0;\r\n\tconst matches: SimulateResult[] = [];\r\n\r\n\tfor (const seed of SEEDS)\r\n\t{\r\n\t\tfor (const dist of SPAWN_DISTANCES)\r\n\t\t{\r\n\t\t\tconst r = sandbox.simulate({\r\n\t\t\t\tseed,\r\n\t\t\t\tspawnDistance: dist,\r\n\t\t\t\tskipHistory: true,\r\n\t\t\t\tparams1,\r\n\t\t\t});\r\n\t\t\tif (r.winner === 'wizard-1') w1++;\r\n\t\t\telse if (r.winner === 'wizard-2') w2++;\r\n\t\t\telse draws++;\r\n\r\n\t\t\tmatches.push(r);\r\n\t\t}\r\n\t}\r\n\r\n\treturn {\r\n\t\twizard1Wins: w1,\r\n\t\twizard2Wins: w2,\r\n\t\tdraws,\r\n\t\twinner: (w1 > w2 ? 'wizard-1' : w2 > w1 ? 'wizard-2' : 'draw') as FightWinner,\r\n\t\tmatches,\r\n\t};\r\n}\r\n\r\nasync function evaluateParams(\r\n\tuserBundle: BotBundle,\r\n\topponentBundles: BotBundle[],\r\n\tparams1: Record<string, number>,\r\n): Promise<number>\r\n{\r\n\tlet totalScore = 0;\r\n\tfor (const opponent of opponentBundles)\r\n\t{\r\n\t\tconst sandbox = await MatchSandbox.create(userBundle, opponent, {\r\n\t\t\tcompileOptions: getCoreCompileOptions(),\r\n\t\t});\r\n\t\ttry\r\n\t\t{\r\n\t\t\tconst result = runFightWithParams(sandbox, params1);\r\n\t\t\ttotalScore += scoreFight(result);\r\n\t\t}\r\n\t\tfinally\r\n\t\t{\r\n\t\t\tsandbox.dispose();\r\n\t\t}\r\n\t}\r\n\treturn totalScore;\r\n}\r\n\r\n/**\r\n * Resolve the opponent names to use for optimization.\r\n * If opponents are specified, validates them. Otherwise uses all built-in bots.\r\n */\r\nexport function resolveOpponentNames(opponents: string[] | undefined): string[]\r\n{\r\n\tif (!opponents || opponents.length === 0)\r\n\t{\r\n\t\treturn getBuiltinBotNames();\r\n\t}\r\n\r\n\t// Validate all names before starting\r\n\tconst allNames = getBuiltinBotNames();\r\n\tfor (const name of opponents)\r\n\t{\r\n\t\tif (!allNames.includes(name))\r\n\t\t{\r\n\t\t\tthrow new Error(\r\n\t\t\t\t`Unknown opponent: \"${name}\". Available bots:\\n ${allNames.join(', ')}`,\r\n\t\t\t);\r\n\t\t}\r\n\t}\r\n\r\n\treturn opponents;\r\n}\r\n\r\nexport async function runOptimize(options: OptimizeOptions): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\tconst botInfo = await discoverBot(projectDir, options.bot);\r\n\r\n\tconst source = readFileSync(botInfo.sourcePath, 'utf-8');\r\n\tconst params = parseParams(source);\r\n\r\n\tif (params.length === 0)\r\n\t{\r\n\t\tconsole.log('\\n No useParam() calls found in your bot.');\r\n\t\tconsole.log(' Add useParam(\"paramName\", defaultValue, {min, max}) to enable optimization.\\n');\r\n\t\treturn;\r\n\t}\r\n\r\n\tconsole.log(`\\n Bot: ${botInfo.exportName}`);\r\n\tconsole.log(` Parameters: ${params.length}`);\r\n\tparams.forEach((p) => console.log(` ${p.name} = ${p.defaultValue} [${p.min ?? 'auto'} .. ${p.max ?? 'auto'}]`));\r\n\r\n\tconst steps = options.steps ?? 5;\r\n\tconst maxRounds = options.rounds ?? 3;\r\n\tconst opponentNames = resolveOpponentNames(options.opponents);\r\n\tconst opponentBundles = opponentNames.map((name) => resolveOpponent(name));\r\n\tconst userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\r\n\tconsole.log(` Opponents: ${opponentBundles.length}`);\r\n\tconsole.log(` Steps per param: ${steps}`);\r\n\tconsole.log(` Max rounds: ${maxRounds}\\n`);\r\n\r\n\t// Current best values\r\n\tconst best: Record<string, number> = {};\r\n\tfor (const p of params) best[p.name] = p.defaultValue;\r\n\r\n\t// Baseline score\r\n\tlet bestScore = await evaluateParams(userBundle, opponentBundles, best);\r\n\tconsole.log(` Baseline score: ${bestScore.toFixed(1)} / ${(opponentBundles.length * SPAWN_DISTANCES.length * SEEDS.length * 3.5).toFixed(1)}\\n`);\r\n\r\n\t// Coordinate descent\r\n\tfor (let round = 0; round < maxRounds; round++)\r\n\t{\r\n\t\tlet improved = false;\r\n\t\tconsole.log(` Round ${round + 1}:`);\r\n\r\n\t\tfor (const p of params)\r\n\t\t{\r\n\t\t\tconst decl = toParamDeclaration(p);\r\n\t\t\tconst range = getEffectiveRange(decl);\r\n\t\t\tconst candidates = generateCandidates(range.min, range.max, steps);\r\n\r\n\t\t\tlet paramBest = best[p.name]!;\r\n\t\t\tlet paramBestScore = bestScore;\r\n\r\n\t\t\tfor (const candidate of candidates)\r\n\t\t\t{\r\n\t\t\t\tif (Math.abs(candidate - paramBest) < 0.001) continue;\r\n\r\n\t\t\t\tconst trial = {...best, [p.name]: candidate};\r\n\t\t\t\tconst score = await evaluateParams(userBundle, opponentBundles, trial);\r\n\r\n\t\t\t\tif (score > paramBestScore)\r\n\t\t\t\t{\r\n\t\t\t\t\tparamBest = candidate;\r\n\t\t\t\t\tparamBestScore = score;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (paramBest !== best[p.name])\r\n\t\t\t{\r\n\t\t\t\tconsole.log(` ${p.name}: ${best[p.name]} -> ${paramBest} (+${(paramBestScore - bestScore).toFixed(1)})`);\r\n\t\t\t\tbest[p.name] = paramBest;\r\n\t\t\t\tbestScore = paramBestScore;\r\n\t\t\t\timproved = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tconsole.log(` ${p.name}: ${best[p.name]} (no improvement)`);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!improved)\r\n\t\t{\r\n\t\t\tconsole.log(' No improvements found, stopping.\\n');\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tconsole.log(` Round ${round + 1} score: ${bestScore.toFixed(1)}\\n`);\r\n\t}\r\n\r\n\t// Rewrite source\r\n\tlet updated = source;\r\n\tfor (const p of params)\r\n\t{\r\n\t\tconst newVal = best[p.name]!;\r\n\t\tif (newVal !== p.defaultValue)\r\n\t\t{\r\n\t\t\tconst pattern = new RegExp(\r\n\t\t\t\t`(useParam\\\\(\\\\s*['\"]${escapeRegex(p.name)}['\"]\\\\s*,\\\\s*)${escapeRegex(String(p.defaultValue))}`,\r\n\t\t\t);\r\n\t\t\tupdated = updated.replace(pattern, `$1${newVal}`);\r\n\t\t}\r\n\t}\r\n\r\n\tif (updated !== source)\r\n\t{\r\n\t\twriteFileSync(botInfo.sourcePath, updated);\r\n\t\tconsole.log(` Source updated: ${botInfo.sourcePath}`);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tconsole.log(' No parameter changes to write.');\r\n\t}\r\n\r\n\tconsole.log(` Final score: ${bestScore.toFixed(1)} / ${(opponentBundles.length * SPAWN_DISTANCES.length * SEEDS.length * 3.5).toFixed(1)}\\n`);\r\n}\r\n\r\nfunction escapeRegex(s: string): string\r\n{\r\n\treturn s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n}\r\n","/**\r\n * vibemancer build\r\n *\r\n * Compiles the user's bot against an opponent into a standalone bundle.\r\n */\r\n\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport {BotBundle, compileMatchBundle} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, findCoreSourceDir} from '../opponent-resolver.js';\r\n\r\nexport interface BuildOptions\r\n{\r\n\topponent: string;\r\n\tbot?: string;\r\n\toutput?: string;\r\n}\r\n\r\nexport async function runBuild(options: BuildOptions): Promise<void>\r\n{\r\n\tconst projectDir = process.cwd();\r\n\tconst botInfo = await discoverBot(projectDir, options.bot);\r\n\tconst coreSourceDir = findCoreSourceDir();\r\n\r\n\tconst userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\tconst opponentBundle = resolveOpponent(options.opponent);\r\n\r\n\tconsole.log(`\\n Compiling ${botInfo.exportName} vs ${options.opponent}...`);\r\n\r\n\tconst start = Date.now();\r\n\tconst bundle = await compileMatchBundle(userBundle, opponentBundle, {\r\n\t\talias: {\r\n\t\t\t'@vibemancer/core': coreSourceDir + '/index-browser.ts',\r\n\t\t},\r\n\t});\r\n\tconst elapsed = Date.now() - start;\r\n\r\n\tconst outFile = options.output ?? `dist/${botInfo.exportName}-vs-${options.opponent}.js`;\r\n\tconst outDir = path.dirname(path.resolve(outFile));\r\n\tfs.mkdirSync(outDir, {recursive: true});\r\n\tfs.writeFileSync(path.resolve(outFile), bundle);\r\n\r\n\tconst sizeKb = (bundle.length / 1024).toFixed(1);\r\n\tconsole.log(` Output: ${outFile} (${sizeKb} KB)`);\r\n\tconsole.log(` Compiled in ${elapsed}ms\\n`);\r\n}\r\n","/**\r\n * vibemancer bots\r\n *\r\n * Lists all built-in bots with descriptions, grouped by archetype.\r\n * With --name: shows detailed info about a specific bot.\r\n */\r\n\r\nimport {BOT_GROUPS, ALL_BOTS} from '@vibemancer/core';\r\nimport type {WizardEntry} from '@vibemancer/core';\r\n\r\nexport interface BotsOptions\r\n{\r\n\tname?: string;\r\n}\r\n\r\nexport function runBots(options: BotsOptions): void\r\n{\r\n\tif (options.name)\r\n\t{\r\n\t\tshowBotDetail(options.name);\r\n\t\treturn;\r\n\t}\r\n\tlistAllBots();\r\n}\r\n\r\nfunction listAllBots(): void\r\n{\r\n\tconsole.log('\\n Built-in Bots (29 total, ranked weakest → strongest)\\n');\r\n\r\n\tfor (const group of BOT_GROUPS)\r\n\t{\r\n\t\tconsole.log(` ${group.label}:`);\r\n\t\tfor (const bot of group.bots)\r\n\t\t{\r\n\t\t\tconst rank = ALL_BOTS.indexOf(bot) + 1;\r\n\t\t\tconst tierLabel = bot.tier ? `T${bot.tier}` : ' ';\r\n\t\t\tconst rankStr = `#${String(rank).padStart(2)}`;\r\n\t\t\tconsole.log(` ${rankStr} ${tierLabel} ${bot.name.padEnd(14)} ${bot.description}`);\r\n\t\t}\r\n\t\tconsole.log('');\r\n\t}\r\n}\r\n\r\nfunction showBotDetail(name: string): void\r\n{\r\n\tconst bot = ALL_BOTS.find((b) => b.name.toLowerCase() === name.toLowerCase());\r\n\tif (!bot)\r\n\t{\r\n\t\tconst available = ALL_BOTS.map((b) => b.name).join(', ');\r\n\t\tconsole.error(`\\n Unknown bot: \"${name}\"\\n Available: ${available}\\n`);\r\n\t\tprocess.exit(1);\r\n\t}\r\n\r\n\tconst rank = ALL_BOTS.indexOf(bot) + 1;\r\n\r\n\tconsole.log(`\\n ${bot.name}`);\r\n\tconsole.log(` ${'─'.repeat(40)}`);\r\n\tconsole.log(` Rank: #${rank} of ${ALL_BOTS.length}`);\r\n\tconsole.log(` Group: ${bot.group}`);\r\n\tif (bot.tier) console.log(` Tier: ${bot.tier} of 3`);\r\n\tconsole.log(` Description: ${bot.description}`);\r\n\tconsole.log(` Style: ${getStyleDescription(bot)}`);\r\n\r\n\t// Show group progression if tiered\r\n\tif (bot.tier && bot.group !== 'Standalone')\r\n\t{\r\n\t\tconst groupBots = BOT_GROUPS.find((g) => g.label === bot.group)?.bots ?? [];\r\n\t\tif (groupBots.length > 1)\r\n\t\t{\r\n\t\t\tconsole.log(`\\n ${bot.group} progression:`);\r\n\t\t\tfor (const gb of groupBots)\r\n\t\t\t{\r\n\t\t\t\tconst gbRank = ALL_BOTS.indexOf(gb) + 1;\r\n\t\t\t\tconst marker = gb.name === bot.name ? ' ←' : '';\r\n\t\t\t\tconsole.log(` T${gb.tier} ${gb.name.padEnd(14)} #${gbRank} — ${gb.description}${marker}`);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tconsole.log(`\\n To fight: vibemancer fight --opponent ${bot.name}`);\r\n\tconsole.log(` To trace: vibemancer trace --opponent ${bot.name}\\n`);\r\n}\r\n\r\nfunction getStyleDescription(bot: WizardEntry): string\r\n{\r\n\tswitch (bot.group)\r\n\t{\r\n\t\tcase 'Standalone':\r\n\t\t\tif (bot.name === 'TargetDummy') return 'Does nothing. Use for basic testing.';\r\n\t\t\tif (bot.name === 'Critter') return 'Random actions. Tests handling of unpredictable opponents.';\r\n\t\t\tif (bot.name === 'Rookie') return 'Simple homing missiles. Good first benchmark.';\r\n\t\t\tif (bot.name === 'Hogger') return 'Random but with real damage. Chaos test.';\r\n\t\t\tif (bot.name === 'Doombringer') return 'One huge missile. Tests shield timing.';\r\n\t\t\treturn bot.description;\r\n\t\tcase 'Defensive': return 'Prioritizes shields and survival. Punishes aggression with counter-missiles. Weak to chip damage and shield baiting.';\r\n\t\tcase 'Melee': return 'Blinks in close, fires fast low-range stabs. Weak to kiting and ranged pressure.';\r\n\t\tcase 'Homing': return 'Slow tracking missiles that are hard to dodge. Weak to shields and fast burst.';\r\n\t\tcase 'Caster': return 'Medium-range homing with adaptive missile fitting. Balanced offense and defense.';\r\n\t\tcase 'Sniper': return 'Intercept-predicted straight shots. High accuracy, weak to erratic movement.';\r\n\t\tcase 'Duelist': return 'Close-range fighters with balanced offense/defense. Jack of all trades.';\r\n\t\tcase 'Berserker': return 'Aggressive traders who close distance fast. Weak to kiting and strong defense.';\r\n\t\tcase 'Kiter': return 'Maintains distance while firing homing missiles. Weak to fast closers and blink gap-close.';\r\n\t\tdefault: return bot.description;\r\n\t}\r\n}\r\n","/**\n * vibemancer upload\n *\n * Compiles the user's bot into a standalone bundle and uploads it to Vibemancer\n * via the authed gateway (`POST /api/upload`), owned by the canonical Firebase\n * identity from `vibemancer login`. The server validates + dedupes; if the same\n * code was uploaded before, the old wizard is reactivated (rating/history kept).\n */\n\nimport fs from 'node:fs';\nimport {discoverBot} from '../bot-discovery.js';\nimport {compileSingleBotBundle} from '../compile-single-bot.js';\nimport {uploadBot} from '../auth/gateway-client.js';\nimport {NotLoggedInError} from '../auth/oauth-client.js';\n\nexport interface UploadOptions\n{\n\tbot?: string;\n}\n\nconst MAX_BUNDLE_BYTES = 500 * 1024;\n\nexport async function runUpload(options: UploadOptions): Promise<void>\n{\n\tconst projectDir = process.cwd();\n\tconst botInfo = await discoverBot(projectDir, options.bot);\n\n\tconsole.log(`\\n Compiling ${botInfo.exportName}...`);\n\tconst bundle = await compileSingleBotBundle(botInfo.sourcePath, botInfo.exportName);\n\tconst sizeKb = (bundle.length / 1024).toFixed(1);\n\tconsole.log(` Bundle: ${sizeKb} KB`);\n\n\tif (bundle.length > MAX_BUNDLE_BYTES)\n\t{\n\t\tconsole.error(` Error: Bundle too large (${sizeKb} KB). Max ${MAX_BUNDLE_BYTES / 1024} KB.`);\n\t\tprocess.exit(1);\n\t}\n\n\tlet sourceCode = '';\n\ttry\n\t{\n\t\tsourceCode = fs.readFileSync(botInfo.sourcePath, 'utf-8');\n\t}\n\tcatch\n\t{\n\t\t// non-fatal — source storage is optional\n\t}\n\n\tconsole.log(` Wizard: ${botInfo.exportName}`);\n\tconsole.log(' Uploading to Vibemancer...');\n\n\ttry\n\t{\n\t\tconst result = await uploadBot({\n\t\t\tbundle,\n\t\t\tname: botInfo.exportName,\n\t\t\texportName: botInfo.exportName,\n\t\t\tsourceCode,\n\t\t});\n\t\tconsole.log(` ✓ ${result.message}`);\n\t\tif (result.wizardId) console.log(` Wizard ID: ${result.wizardId}`);\n\t\tconsole.log(` Your wizard \"${botInfo.exportName}\" is now competing.\\n`);\n\t}\n\tcatch(err)\n\t{\n\t\tif (err instanceof NotLoggedInError)\n\t\t{\n\t\t\tconsole.error('\\n Not logged in. Run: vibemancer login\\n');\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconsole.error(` ✗ Upload failed: ${err instanceof Error ? err.message : String(err)}\\n`);\n\t\t}\n\t\tprocess.exit(1);\n\t}\n}\n","/* eslint-disable @typescript-eslint/naming-convention -- OAuth 2.0 wire-format field names (grant_type, access_token, …) are snake_case by spec */\n\n/**\n * CLI OAuth client for the Vibemancer MCP gateway.\n *\n * The CLI is a PKCE OAuth client of mcp.vibemancer.com (the same gateway the MCP\n * AI clients use). `vibemancer login` runs the authorization-code flow; the\n * resulting session token carries the canonical Firebase uid. This module owns\n * PKCE, the token exchange/refresh, and handing callers a fresh access token.\n */\n\nimport {createHash, randomBytes} from 'node:crypto';\nimport {loadCredentials, saveCredentials, type Credentials} from './credentials-store.js';\n\n/** Gateway base URL; overridable for emulator/E2E via VIBEMANCER_MCP_URL. */\nexport const MCP_BASE_URL = process.env.VIBEMANCER_MCP_URL ?? 'https://mcp.vibemancer.com';\n\nexport class NotLoggedInError extends Error\n{\n\tconstructor()\n\t{\n\t\tsuper('Not logged in. Run: vibemancer login');\n\t\tthis.name = 'NotLoggedInError';\n\t}\n}\n\nexport interface Pkce\n{\n\tverifier: string;\n\tchallenge: string;\n}\n\nexport function generatePkce(): Pkce\n{\n\tconst verifier = randomBytes(32).toString('base64url');\n\tconst challenge = createHash('sha256').update(verifier).digest('base64url');\n\treturn {verifier, challenge};\n}\n\n/** Dynamic client registration → client_id (localhost/https redirect allowed). */\nexport async function registerClient(redirectUri: string): Promise<string>\n{\n\tconst res = await fetch(`${MCP_BASE_URL}/register`, {\n\t\tmethod: 'POST',\n\t\theaders: {'Content-Type': 'application/json'},\n\t\tbody: JSON.stringify({redirect_uris: [redirectUri], client_name: 'vibemancer-cli'}),\n\t});\n\tif (!res.ok) throw new Error(`Client registration failed (${res.status}).`);\n\tconst json: unknown = await res.json();\n\tconst clientId = typeof json === 'object' && json !== null && 'client_id' in json && typeof json.client_id === 'string'\n\t\t? json.client_id\n\t\t: '';\n\tif (!clientId) throw new Error('Client registration returned no client_id.');\n\treturn clientId;\n}\n\nfunction parseTokenResponse(json: unknown, fallbackRefresh: string): Credentials\n{\n\tif (typeof json !== 'object' || json === null) throw new Error('Invalid token response.');\n\tconst accessToken = 'access_token' in json && typeof json.access_token === 'string' ? json.access_token : '';\n\tif (!accessToken) throw new Error('Token response missing access_token.');\n\tconst refreshToken = 'refresh_token' in json && typeof json.refresh_token === 'string' ? json.refresh_token : fallbackRefresh;\n\tconst expiresIn = 'expires_in' in json && typeof json.expires_in === 'number' ? json.expires_in : 3600;\n\treturn {accessToken, refreshToken, expiresAt: Date.now() + expiresIn * 1000};\n}\n\n/** Exchange an authorization code (PKCE) for tokens, and persist them. */\nexport async function exchangeCode(code: string, codeVerifier: string): Promise<Credentials>\n{\n\tconst res = await fetch(`${MCP_BASE_URL}/token`, {\n\t\tmethod: 'POST',\n\t\theaders: {'Content-Type': 'application/json'},\n\t\tbody: JSON.stringify({grant_type: 'authorization_code', code, code_verifier: codeVerifier}),\n\t});\n\tif (!res.ok) throw new Error(`Token exchange failed (${res.status}): ${await res.text()}`);\n\tconst creds = parseTokenResponse(await res.json(), '');\n\tsaveCredentials(creds);\n\treturn creds;\n}\n\nasync function refreshCredentials(refreshToken: string): Promise<Credentials>\n{\n\tconst res = await fetch(`${MCP_BASE_URL}/token`, {\n\t\tmethod: 'POST',\n\t\theaders: {'Content-Type': 'application/json'},\n\t\tbody: JSON.stringify({grant_type: 'refresh_token', refresh_token: refreshToken}),\n\t});\n\tif (!res.ok) throw new NotLoggedInError();\n\tconst creds = parseTokenResponse(await res.json(), refreshToken);\n\tsaveCredentials(creds);\n\treturn creds;\n}\n\nconst REFRESH_SKEW_MS = 60_000;\n\n/** A valid access token, refreshing silently when within 60s of expiry. */\nexport async function getAccessToken(): Promise<string>\n{\n\tconst creds = loadCredentials();\n\tif (!creds) throw new NotLoggedInError();\n\tif (creds.expiresAt - Date.now() > REFRESH_SKEW_MS) return creds.accessToken;\n\tconst refreshed = await refreshCredentials(creds.refreshToken);\n\treturn refreshed.accessToken;\n}\n","/**\n * Local credential store for the CLI's OAuth session.\n *\n * Persists the refresh + access tokens at ~/.vibemancer/credentials.json so the\n * user stays logged in between commands. The directory is overridable via\n * VIBEMANCER_CONFIG_DIR (tests, or users who relocate their config).\n */\n\nimport {chmodSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync} from 'node:fs';\nimport {homedir} from 'node:os';\nimport {join} from 'node:path';\n\nexport interface Credentials\n{\n\trefreshToken: string;\n\taccessToken: string;\n\t/** Epoch milliseconds at which the access token expires. */\n\texpiresAt: number;\n}\n\nfunction configDir(): string\n{\n\treturn process.env.VIBEMANCER_CONFIG_DIR ?? join(homedir(), '.vibemancer');\n}\n\nfunction credentialsPath(): string\n{\n\treturn join(configDir(), 'credentials.json');\n}\n\nexport function loadCredentials(): Credentials | null\n{\n\tconst path = credentialsPath();\n\tif (!existsSync(path)) return null;\n\ttry\n\t{\n\t\tconst parsed: unknown = JSON.parse(readFileSync(path, 'utf-8'));\n\t\tif (\n\t\t\ttypeof parsed === 'object' && parsed !== null\n\t\t\t&& 'refreshToken' in parsed && typeof parsed.refreshToken === 'string'\n\t\t\t&& 'accessToken' in parsed && typeof parsed.accessToken === 'string'\n\t\t\t&& 'expiresAt' in parsed && typeof parsed.expiresAt === 'number'\n\t\t)\n\t\t{\n\t\t\treturn {refreshToken: parsed.refreshToken, accessToken: parsed.accessToken, expiresAt: parsed.expiresAt};\n\t\t}\n\t\treturn null;\n\t}\n\tcatch\n\t{\n\t\treturn null;\n\t}\n}\n\nexport function saveCredentials(credentials: Credentials): void\n{\n\tmkdirSync(configDir(), {recursive: true});\n\tconst path = credentialsPath();\n\twriteFileSync(path, JSON.stringify(credentials, null, 2), {mode: 0o600});\n\t// Best-effort tighten perms (no-op semantics on Windows).\n\ttry\n\t{\n\t\tchmodSync(path, 0o600);\n\t}\n\tcatch\n\t{\n\t\t// ignore — Windows / restricted FS\n\t}\n}\n\nexport function clearCredentials(): void\n{\n\ttry\n\t{\n\t\trmSync(credentialsPath(), {force: true});\n\t}\n\tcatch\n\t{\n\t\t// ignore\n\t}\n}\n","/**\n * Client for the authed gateway REST endpoints. Attaches the Bearer session\n * token (carrying the canonical Firebase uid) and parses responses. This is the\n * single network path the CLI uses to upload + pull.\n */\n\nimport {getAccessToken, MCP_BASE_URL} from './oauth-client.js';\n\nexport interface UploadPayload\n{\n\tbundle: string;\n\tname: string;\n\texportName: string;\n\tsourceCode: string;\n}\n\nexport interface UploadResult\n{\n\twizardId: string;\n\tmessage: string;\n}\n\nexport async function uploadBot(payload: UploadPayload): Promise<UploadResult>\n{\n\tconst token = await getAccessToken();\n\tconst res = await fetch(`${MCP_BASE_URL}/api/upload`, {\n\t\tmethod: 'POST',\n\t\theaders: {'Content-Type': 'application/json', Authorization: `Bearer ${token}`},\n\t\tbody: JSON.stringify(payload),\n\t});\n\tif (!res.ok) throw new Error(`Upload failed (${res.status}): ${await res.text()}`);\n\tconst data: unknown = await res.json();\n\tconst wizardId = typeof data === 'object' && data !== null && 'wizardId' in data && typeof data.wizardId === 'string'\n\t\t? data.wizardId\n\t\t: '';\n\tconst message = typeof data === 'object' && data !== null && 'message' in data && typeof data.message === 'string'\n\t\t? data.message\n\t\t: 'Uploaded.';\n\treturn {wizardId, message};\n}\n\nexport async function pullSource(name: string): Promise<string>\n{\n\tconst token = await getAccessToken();\n\tconst res = await fetch(`${MCP_BASE_URL}/api/pull?name=${encodeURIComponent(name)}`, {\n\t\theaders: {Authorization: `Bearer ${token}`},\n\t});\n\tif (!res.ok) throw new Error(`Pull failed (${res.status}): ${await res.text()}`);\n\tconst data: unknown = await res.json();\n\tconst source = typeof data === 'object' && data !== null && 'sourceCode' in data && typeof data.sourceCode === 'string'\n\t\t? data.sourceCode\n\t\t: '';\n\tif (source) return source;\n\tconst error = typeof data === 'object' && data !== null && 'error' in data && typeof data.error === 'string'\n\t\t? data.error\n\t\t: 'No source returned.';\n\tthrow new Error(error);\n}\n","/**\n * vibemancer pull\n *\n * Downloads the latest source of your active wizard (by export name) from the\n * authed gateway (`GET /api/pull`) and writes it to the local bot file. Enables\n * round-tripping between MCP chat sessions and local CLI development.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport {discoverBot} from '../bot-discovery.js';\nimport {pullSource} from '../auth/gateway-client.js';\nimport {NotLoggedInError} from '../auth/oauth-client.js';\n\nexport interface PullOptions\n{\n\tbot?: string;\n}\n\nexport async function runPull(options: PullOptions): Promise<void>\n{\n\tconst projectDir = process.cwd();\n\t// pull RESTORES source, so the file legitimately may not exist yet — a new machine, a\n\t// fresh clone, or a bot authored in an MCP chat session. See DiscoverOptions.\n\tconst botInfo = await discoverBot(projectDir, options.bot, {allowMissingFile: true});\n\tconst isNew = !fs.existsSync(botInfo.sourcePath);\n\n\tconsole.log(`\\n Pulling latest source for ${botInfo.exportName}...`);\n\n\ttry\n\t{\n\t\tconst sourceCode = await pullSource(botInfo.exportName);\n\t\t// On a fresh machine the containing directory (src/) may not exist either.\n\t\tfs.mkdirSync(path.dirname(botInfo.sourcePath), {recursive: true});\n\t\tfs.writeFileSync(botInfo.sourcePath, sourceCode);\n\t\tconsole.log(` ✓ ${isNew ? 'Created' : 'Updated'} ${botInfo.sourcePath}`);\n\t\tconsole.log(` ${(sourceCode.length / 1024).toFixed(1)} KB written`);\n\t}\n\tcatch(err)\n\t{\n\t\tif (err instanceof NotLoggedInError)\n\t\t{\n\t\t\tconsole.error('\\n Not logged in. Run: vibemancer login\\n');\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconsole.error(` Pull failed: ${err instanceof Error ? err.message : String(err)}`);\n\t\t\tconsole.error(' Upload first with: vibemancer upload\\n');\n\t\t}\n\t\tprocess.exit(1);\n\t}\n}\n","/**\n * vibemancer login\n *\n * Authenticates the CLI as an OAuth client of the MCP gateway. The resulting\n * session token carries the canonical Firebase uid (the same identity the web\n * and MCP use), so uploads from the CLI are owned by the same account.\n *\n * Default: browser loopback (a localhost server catches the redirect).\n * `--no-browser`: print the URL + paste the code shown on the gateway page.\n */\n\nimport {createServer, type IncomingMessage, type ServerResponse} from 'node:http';\nimport {randomBytes} from 'node:crypto';\nimport {spawn} from 'node:child_process';\nimport {createInterface} from 'node:readline/promises';\nimport {generatePkce, registerClient, exchangeCode, MCP_BASE_URL} from '../auth/oauth-client.js';\n\nexport interface LoginOptions\n{\n\tnoBrowser?: boolean;\n}\n\nexport function buildAuthorizeUrl(\n\tbaseUrl: string,\n\tparams: {clientId: string; redirectUri: string; challenge: string; state: string},\n): string\n{\n\tconst u = new URL(`${baseUrl}/authorize`);\n\tu.searchParams.set('response_type', 'code');\n\tu.searchParams.set('client_id', params.clientId);\n\tu.searchParams.set('redirect_uri', params.redirectUri);\n\tu.searchParams.set('code_challenge', params.challenge);\n\tu.searchParams.set('code_challenge_method', 'S256');\n\tu.searchParams.set('state', params.state);\n\treturn u.toString();\n}\n\nexport function extractCodeFromCallback(reqUrl: string, expectedState: string): {code: string} | {error: string}\n{\n\tconst u = new URL(reqUrl, 'http://localhost');\n\tconst code = u.searchParams.get('code');\n\tconst state = u.searchParams.get('state');\n\tif (!code) return {error: 'No authorization code in the callback.'};\n\tif (state !== expectedState) return {error: 'State mismatch (possible CSRF) — try again.'};\n\treturn {code};\n}\n\nfunction openBrowser(url: string): void\n{\n\ttry\n\t{\n\t\tconst child = process.platform === 'win32'\n\t\t\t? spawn('cmd', ['/c', 'start', '', url], {stdio: 'ignore', detached: true})\n\t\t\t: spawn(process.platform === 'darwin' ? 'open' : 'xdg-open', [url], {stdio: 'ignore', detached: true});\n\t\tchild.unref();\n\t}\n\tcatch\n\t{\n\t\t// non-fatal — the URL is also printed for manual opening\n\t}\n}\n\ninterface LoopbackServer\n{\n\tport: number;\n\twaitForCode: Promise<string>;\n\tclose: () => void;\n}\n\nfunction startLoopbackServer(expectedState: string): Promise<LoopbackServer>\n{\n\treturn new Promise((resolveServer) =>\n\t{\n\t\tlet resolveCode: (code: string) => void = () => undefined;\n\t\tlet rejectCode: (err: Error) => void = () => undefined;\n\t\tconst waitForCode = new Promise<string>((res, rej) =>\n\t\t{\n\t\t\tresolveCode = res;\n\t\t\trejectCode = rej;\n\t\t});\n\n\t\tconst server = createServer((req: IncomingMessage, res: ServerResponse) =>\n\t\t{\n\t\t\tconst result = extractCodeFromCallback(req.url ?? '', expectedState);\n\t\t\tif ('error' in result)\n\t\t\t{\n\t\t\t\tres.writeHead(400, {'Content-Type': 'text/html'});\n\t\t\t\tres.end('<h2>Login failed</h2><p>You can close this tab and try again.</p>');\n\t\t\t\trejectCode(new Error(result.error));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tres.writeHead(200, {'Content-Type': 'text/html'});\n\t\t\tres.end('<h2>Vibemancer login complete</h2><p>You can close this tab and return to the terminal.</p>');\n\t\t\tresolveCode(result.code);\n\t\t});\n\n\t\tserver.listen(0, '127.0.0.1', () =>\n\t\t{\n\t\t\tconst addr = server.address();\n\t\t\tconst port = typeof addr === 'object' && addr !== null ? addr.port : 0;\n\t\t\tresolveServer({port, waitForCode, close: () => server.close()});\n\t\t});\n\t});\n}\n\nasync function runBrowserLogin(challenge: string, verifier: string, state: string): Promise<void>\n{\n\tconst {port, waitForCode, close} = await startLoopbackServer(state);\n\tconst redirectUri = `http://localhost:${port}/callback`;\n\ttry\n\t{\n\t\tconst clientId = await registerClient(redirectUri);\n\t\tconst authUrl = buildAuthorizeUrl(MCP_BASE_URL, {clientId, redirectUri, challenge, state});\n\t\tconsole.log('\\n Opening your browser to sign in with Google...');\n\t\tconsole.log(` If it doesn't open, visit:\\n ${authUrl}\\n`);\n\t\topenBrowser(authUrl);\n\t\tconst code = await waitForCode;\n\t\tawait exchangeCode(code, verifier);\n\t\tconsole.log(' ✓ Logged in. You can now run `vibemancer upload`.\\n');\n\t}\n\tfinally\n\t{\n\t\tclose();\n\t}\n}\n\nasync function runPasteLogin(challenge: string, verifier: string, state: string): Promise<void>\n{\n\tconst redirectUri = `${MCP_BASE_URL}/cli-code`;\n\tconst clientId = await registerClient(redirectUri);\n\tconst authUrl = buildAuthorizeUrl(MCP_BASE_URL, {clientId, redirectUri, challenge, state});\n\tconsole.log('\\n Open this URL in a browser, sign in, then paste the code shown:\\n');\n\tconsole.log(` ${authUrl}\\n`);\n\tconst rl = createInterface({input: process.stdin, output: process.stdout});\n\tconst code = (await rl.question(' Paste code: ')).trim();\n\trl.close();\n\tif (!code)\n\t{\n\t\tconsole.error(' No code entered.');\n\t\tprocess.exit(1);\n\t}\n\tawait exchangeCode(code, verifier);\n\tconsole.log(' ✓ Logged in.\\n');\n}\n\nexport async function runLogin(options: LoginOptions): Promise<void>\n{\n\tconst {verifier, challenge} = generatePkce();\n\tconst state = randomBytes(16).toString('hex');\n\tif (options.noBrowser)\n\t{\n\t\tawait runPasteLogin(challenge, verifier, state);\n\t}\n\telse\n\t{\n\t\tawait runBrowserLogin(challenge, verifier, state);\n\t}\n}\n","/**\n * vibemancer logout — clear the cached OAuth credentials.\n */\n\nimport {clearCredentials} from '../auth/credentials-store.js';\n\nexport function runLogout(): void\n{\n\tclearCredentials();\n\tconsole.log(' Logged out.');\n}\n","export interface FeedbackOptions\n{\n\tmessage: string;\n}\n\nexport async function runFeedback(options: FeedbackOptions): Promise<void>\n{\n\tconst message = options.message.trim();\n\tif (!message)\n\t{\n\t\tconsole.error(' Error: feedback message cannot be empty.');\n\t\tprocess.exit(1);\n\t}\n\n\tconsole.log('\\n Submitting feedback...');\n\n\ttry\n\t{\n\t\tconst {initializeApp} = await import('firebase/app');\n\t\tconst {getFunctions, httpsCallable} = await import('firebase/functions');\n\t\tconst {FIREBASE_CONFIG} = await import('../firebase-config.js');\n\n\t\tconst app = initializeApp(FIREBASE_CONFIG);\n\n\t\tconst functions = getFunctions(app, 'us-central1');\n\t\tconst submitFn = httpsCallable(functions, 'submitFeedback');\n\t\tawait submitFn({message});\n\n\t\tconsole.log(' Sent! Thanks for the feedback.\\n');\n\t}\n\tcatch(err: unknown)\n\t{\n\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\tconsole.error(` Failed to submit: ${msg}\\n`);\n\t\tprocess.exit(1);\n\t}\n}\n","import {calculateMissileCastTime, GCD_DURATION, TICKS_PER_SECOND, calculateMissileRadius} from '@vibemancer/core';\n\nexport interface MissileCalcOptions\n{\n\tdamage: number;\n\tspeed: number;\n\tduration: number;\n\tturnRate: number;\n}\n\nexport function runMissileCalc(options: MissileCalcOptions): void\n{\n\tconst config = {\n\t\tdamage: options.damage,\n\t\tspeed: options.speed,\n\t\tduration: options.duration,\n\t\tturnRate: options.turnRate,\n\t};\n\n\tconst castTimeSec = calculateMissileCastTime(config);\n\tconst castFrames = Math.max(1, Math.round(castTimeSec * TICKS_PER_SECOND));\n\tconst gcdSec = GCD_DURATION / TICKS_PER_SECOND;\n\tconst totalCycleSec = castTimeSec + gcdSec;\n\tconst dps = config.damage / totalCycleSec;\n\tconst range = config.speed * config.duration;\n\tconst radius = calculateMissileRadius(config.damage);\n\n\tconsole.log(`\n Missile Calculator\n ──────────────────\n Config: damage=${config.damage} speed=${config.speed} duration=${config.duration} turnRate=${config.turnRate}\n Cast time: ${castTimeSec.toFixed(3)}s (${castFrames} frames)\n GCD: ${gcdSec}s (${GCD_DURATION} frames)\n Full cycle: ${totalCycleSec.toFixed(3)}s (cast + GCD)\n Eff. DPS: ${dps.toFixed(2)} HP/s\n Range: ${range} units (speed × duration)\n Hitbox: ${radius.toFixed(2)} radius\n`);\n}\n","/**\r\n * Vibemancer CLI\r\n *\r\n * Development tools for building wizard bots.\r\n *\r\n * Usage:\r\n * vibemancer dev [--port 4242] [--bot src/bot.ts]\r\n * vibemancer test\r\n * vibemancer fight [--opponent Battlemage]\r\n * vibemancer trace --opponent Battlemage\r\n * vibemancer tournament [opponents...]\r\n * vibemancer optimize [--opponents Battlemage,Warmage]\r\n * vibemancer build --opponent Battlemage\r\n */\r\n\r\nimport {runDev} from './commands/dev.js';\r\nimport {runTest} from './commands/test.js';\r\nimport {runFight} from './commands/fight.js';\r\nimport {runTrace} from './commands/trace.js';\r\nimport {runTournament} from './commands/tournament.js';\r\nimport {runOptimize} from './commands/optimize.js';\r\nimport {runBuild} from './commands/build.js';\r\nimport {runBots} from './commands/bots.js';\r\nimport {runUpload} from './commands/upload.js';\r\nimport {runPull} from './commands/pull.js';\r\nimport {runLogin} from './commands/login.js';\r\nimport {runLogout} from './commands/logout.js';\r\nimport {runFeedback} from './commands/feedback.js';\r\nimport {runMissileCalc} from './commands/missile-calc.js';\r\n\r\nconst args = process.argv.slice(2);\r\nconst command = args[0];\r\n\r\nfunction parseFlag(flag: string): string | undefined\r\n{\r\n\tconst idx = args.indexOf(flag);\r\n\tif (idx !== -1 && idx + 1 < args.length)\r\n\t{\r\n\t\treturn args[idx + 1];\r\n\t}\r\n\treturn undefined;\r\n}\r\n\r\nfunction parseIntFlag(flag: string, fallback: number): number\r\n{\r\n\tconst str = parseFlag(flag);\r\n\tif (str === undefined) return fallback;\r\n\tconst n = parseInt(str, 10);\r\n\tif (Number.isNaN(n))\r\n\t{\r\n\t\tconsole.error(`Error: ${flag} must be a number, got \"${str}\".`);\r\n\t\tprocess.exit(1);\r\n\t}\r\n\treturn n;\r\n}\r\n\r\nfunction printHelp(): void\r\n{\r\n\tconsole.log(`\r\nVibemancer CLI - Development tools for wizard bots\r\n\r\nUsage:\r\n vibemancer <command> [options]\r\n\r\nCommands:\r\n dev Start the development server (auto-opens browser)\r\n test Run your test suite (vitest)\r\n fight Fight against all 29 built-in bots (or a single opponent)\r\n bots List all built-in bots with descriptions\r\n trace Per-tick debug trace of a single match\r\n tournament Round-robin tournament between your bot + selected opponents\r\n optimize Optimize bot parameters via coordinate descent\r\n build Compile bot to a standalone bundle\r\n login Sign in to VibeMancer (required before upload/pull)\r\n logout Sign out\r\n upload Upload bot to VibeMancer for online competition\r\n pull Download latest source code from VibeMancer\r\n feedback Submit a bug report or suggestion\r\n missile-calc Calculate missile cast time and DPS for a config\r\n\r\nCommon options:\r\n --bot <path> Path to bot source file (default: auto-discover)\r\n\r\nDev options:\r\n --port <n> Server port (default: 4242)\r\n\r\nFight options:\r\n --opponent <name> Fight a single opponent: a built-in name OR another\r\n user's uploaded bot as handle/botname\r\n --seed <n> Random seed\r\n\r\nTrace options:\r\n --opponent <name> Opponent: a built-in name OR handle/botname (required)\r\n --seed <n> Random seed (default: 1)\r\n --distance <n> Spawn distance (default: 600)\r\n\r\nBuild options:\r\n --opponent <name> Opponent bot name (required)\r\n --output <path> Output file path (default: dist/<Bot>-vs-<Opponent>.js)\r\n\r\nOptimize options:\r\n --steps <n> Candidates per parameter (default: 5)\r\n --rounds <n> Max optimization rounds (default: 3)\r\n --opponents <list> Comma-separated bot names to optimize against (default: all)\r\n\r\nExamples:\r\n vibemancer dev\r\n vibemancer test\r\n vibemancer fight\r\n vibemancer fight --opponent Battlemage\r\n vibemancer trace --opponent Battlemage\r\n vibemancer trace --opponent Nightblade --distance 300\r\n vibemancer tournament Battlemage Warmage Archmage\r\n vibemancer optimize\r\n vibemancer build --opponent Battlemage\r\n vibemancer feedback \"missiles go through walls sometimes\"\r\n vibemancer missile-calc --damage 15 --speed 7 --duration 200 --turnRate 3\r\n`);\r\n}\r\n\r\nasync function main(): Promise<void>\r\n{\r\n\tif (!command || command === '--help' || command === '-h')\r\n\t{\r\n\t\tprintHelp();\r\n\t\treturn;\r\n\t}\r\n\r\n\tswitch (command)\r\n\t{\r\n\t\tcase 'dev':\r\n\t\t{\r\n\t\t\tconst port = parseIntFlag('--port', 4242);\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tawait runDev({port, bot});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'test':\r\n\t\t{\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tawait runTest({bot});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'fight':\r\n\t\t{\r\n\t\t\tconst opponent = parseFlag('--opponent');\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tconst seed = parseFlag('--seed') !== undefined ? parseIntFlag('--seed', 0) : undefined;\r\n\t\t\tawait runFight({opponent, bot, seed});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'trace':\r\n\t\t{\r\n\t\t\tconst opponent = parseFlag('--opponent');\r\n\t\t\tif (!opponent)\r\n\t\t\t{\r\n\t\t\t\tconst {getBuiltinBotNames} = await import('./opponent-resolver.js');\r\n\t\t\t\tconst names = getBuiltinBotNames();\r\n\t\t\t\tconst list = names.map((n) => ` --opponent ${n}`).join('\\n');\r\n\t\t\t\tconsole.error('Error: --opponent is required for trace.\\n');\r\n\t\t\t\tconsole.error(`Available opponents:\\n\\n${list}\\n`);\r\n\t\t\t\tconsole.error('Usage: vibemancer trace --opponent Battlemage');\r\n\t\t\t\tprocess.exit(1);\r\n\t\t\t}\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tconst seed = parseFlag('--seed') !== undefined ? parseIntFlag('--seed', 0) : undefined;\r\n\t\t\tconst distance = parseFlag('--distance') !== undefined ? parseIntFlag('--distance', 600) : undefined;\r\n\t\t\tawait runTrace({opponent, bot, seed, distance});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'bots':\r\n\t\t{\r\n\t\t\tconst name = parseFlag('--name') ?? args[1];\r\n\t\t\trunBots({name: name?.startsWith('--') ? undefined : name});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'tournament':\r\n\t\t{\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tconst flagIndices = new Set<number>();\r\n\t\t\tfor (let i = 1; i < args.length; i++)\r\n\t\t\t{\r\n\t\t\t\tif (args[i]!.startsWith('--'))\r\n\t\t\t\t{\r\n\t\t\t\t\tflagIndices.add(i);\r\n\t\t\t\t\tflagIndices.add(i + 1);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tconst opponents = args.slice(1).filter((_, i) => !flagIndices.has(i + 1));\r\n\t\t\tawait runTournament({opponents, bot});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'optimize':\r\n\t\t{\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tconst opponentsStr = parseFlag('--opponents');\r\n\t\t\tconst opponents = opponentsStr ? opponentsStr.split(',').map((s) => s.trim()).filter(Boolean) : undefined;\r\n\t\t\tawait runOptimize({\r\n\t\t\t\tbot,\r\n\t\t\t\tsteps: parseFlag('--steps') !== undefined ? parseIntFlag('--steps', 5) : undefined,\r\n\t\t\t\trounds: parseFlag('--rounds') !== undefined ? parseIntFlag('--rounds', 3) : undefined,\r\n\t\t\t\topponents,\r\n\t\t\t});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'build':\r\n\t\t{\r\n\t\t\tconst opponent = parseFlag('--opponent');\r\n\t\t\tif (!opponent)\r\n\t\t\t{\r\n\t\t\t\tconsole.error('Error: --opponent is required for build command.');\r\n\t\t\t\tconsole.error('Usage: vibemancer build --opponent Battlemage');\r\n\t\t\t\tprocess.exit(1);\r\n\t\t\t}\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tconst output = parseFlag('--output');\r\n\t\t\tawait runBuild({opponent, bot, output});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'upload':\r\n\t\t{\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tawait runUpload({bot});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'pull':\r\n\t\t{\r\n\t\t\tconst bot = parseFlag('--bot');\r\n\t\t\tawait runPull({bot});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'login':\r\n\t\t{\r\n\t\t\tawait runLogin({noBrowser: args.includes('--no-browser')});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'logout':\r\n\t\t{\r\n\t\t\trunLogout();\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'feedback':\r\n\t\t{\r\n\t\t\tconst message = args.slice(1).join(' ');\r\n\t\t\tawait runFeedback({message});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tcase 'missile-calc':\r\n\t\t{\r\n\t\t\trunMissileCalc({\r\n\t\t\t\tdamage: parseIntFlag('--damage', 15),\r\n\t\t\t\tspeed: parseIntFlag('--speed', 7),\r\n\t\t\t\tduration: parseIntFlag('--duration', 200),\r\n\t\t\t\tturnRate: parseIntFlag('--turnRate', 0),\r\n\t\t\t});\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t\tconsole.error(`Unknown command: ${command}`);\r\n\t\t\tprintHelp();\r\n\t\t\tprocess.exit(1);\r\n\t}\r\n}\r\n\r\nmain().catch((error) =>\r\n{\r\n\tconsole.error('Error:', error instanceof Error ? error.message : error);\r\n\tprocess.exit(1);\r\n});\r\n"],"mappings":"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","names":["fs","path","path","fs","BotBundle","BotBundle","BotBundle","sandboxFight","scoreFight","BotBundle","sandboxFight","scoreFight","BotBundle","scoreFight","scoreFight","BotBundle","fs","path","BotBundle","BotBundle","path","fs","fs","readFileSync","writeFileSync","path","fs","fs","path","fs","path","randomBytes","openBrowser","randomBytes","initializeApp","FIREBASE_CONFIG","getBuiltinBotNames"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibemancer",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Vibemancer devkit - dev server, testing, and tournament tools for wizard bots",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Low Entry",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"prepublishOnly": "pnpm run test && pnpm run clean && pnpm run build"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@vibemancer/core": "~0.1
|
|
31
|
+
"@vibemancer/core": "~0.2.1",
|
|
32
32
|
"firebase": "^12.12.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|