vibemancer 0.1.2 → 0.1.4

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 CHANGED
@@ -966,6 +966,7 @@ function getStyleDescription(bot) {
966
966
 
967
967
  // src/commands/upload.ts
968
968
  import { createHash } from "crypto";
969
+ import fs5 from "fs";
969
970
  async function runUpload(options) {
970
971
  const projectDir = process.cwd();
971
972
  const botInfo = await discoverBot(projectDir, options.bot);
@@ -994,10 +995,16 @@ async function runUpload(options) {
994
995
  });
995
996
  const functions = getFunctions(app, "us-central1");
996
997
  const uploadFn = httpsCallable(functions, "uploadWizard");
998
+ let sourceCode;
999
+ try {
1000
+ sourceCode = fs5.readFileSync(botInfo.sourcePath, "utf-8");
1001
+ } catch {
1002
+ }
997
1003
  const result = await uploadFn({
998
1004
  bundle,
999
1005
  name: wizardName,
1000
- exportName: botInfo.exportName
1006
+ exportName: botInfo.exportName,
1007
+ sourceCode
1001
1008
  });
1002
1009
  const data = result.data;
1003
1010
  if (data.active) {
@@ -1022,6 +1029,67 @@ async function runUpload(options) {
1022
1029
  }
1023
1030
  }
1024
1031
 
1032
+ // src/commands/pull.ts
1033
+ import fs6 from "fs";
1034
+ async function runPull(options) {
1035
+ const projectDir = process.cwd();
1036
+ const botInfo = await discoverBot(projectDir, options.bot);
1037
+ console.log(`
1038
+ Pulling latest source for ${botInfo.exportName}...`);
1039
+ try {
1040
+ const { initializeApp } = await import("firebase/app");
1041
+ const { getAuth, signInWithPopup, GoogleAuthProvider } = await import("firebase/auth");
1042
+ const { getFirestore, collection, query, where, getDocs, doc, getDoc, limit: fbLimit } = await import("firebase/firestore");
1043
+ const app = initializeApp({
1044
+ apiKey: "AIzaSyDSUJ2jlk5_vlpGOypMtvqKjHhDmbgomIY",
1045
+ authDomain: "le-vibemancer.firebaseapp.com",
1046
+ projectId: "le-vibemancer"
1047
+ });
1048
+ const auth = getAuth(app);
1049
+ console.log(" Signing in...");
1050
+ const cred = await signInWithPopup(auth, new GoogleAuthProvider());
1051
+ const userId = cred.user.uid;
1052
+ console.log(` Signed in as ${cred.user.displayName ?? cred.user.email ?? userId}`);
1053
+ const db = getFirestore(app);
1054
+ const wizardQuery = query(
1055
+ collection(db, "wizards"),
1056
+ where("ownerId", "==", userId),
1057
+ where("name", "==", botInfo.exportName),
1058
+ where("active", "==", true),
1059
+ fbLimit(1)
1060
+ );
1061
+ const wizardSnap = await getDocs(wizardQuery);
1062
+ if (wizardSnap.empty) {
1063
+ console.error(` No active wizard named "${botInfo.exportName}" found on your account.`);
1064
+ console.error(" Upload first with: vibemancer upload");
1065
+ process.exit(1);
1066
+ }
1067
+ const wizardId = wizardSnap.docs[0].id;
1068
+ const sourceDoc = await getDoc(doc(db, "wizard-sources", wizardId));
1069
+ if (!sourceDoc.exists()) {
1070
+ console.error(" No source code stored for this wizard.");
1071
+ console.error(" Re-upload with the latest CLI to store source: vibemancer upload");
1072
+ process.exit(1);
1073
+ }
1074
+ const data = sourceDoc.data();
1075
+ const sourceCode = data?.sourceCode;
1076
+ if (typeof sourceCode !== "string" || sourceCode.length === 0) {
1077
+ console.error(" Source code is empty. Re-upload to store it.");
1078
+ process.exit(1);
1079
+ }
1080
+ fs6.writeFileSync(botInfo.sourcePath, sourceCode);
1081
+ console.log(` \u2713 Updated ${botInfo.sourcePath}`);
1082
+ console.log(` ${(sourceCode.length / 1024).toFixed(1)} KB written`);
1083
+ } catch (err) {
1084
+ if (err instanceof Error && err.message.includes("popup")) {
1085
+ console.error(" Sign-in popup was blocked or closed. Try again.");
1086
+ } else {
1087
+ console.error(" Pull failed:", err instanceof Error ? err.message : err);
1088
+ }
1089
+ process.exit(1);
1090
+ }
1091
+ }
1092
+
1025
1093
  // src/cli.ts
1026
1094
  var args = process.argv.slice(2);
1027
1095
  var command = args[0];
@@ -1059,6 +1127,7 @@ Commands:
1059
1127
  optimize Optimize bot parameters via coordinate descent
1060
1128
  build Compile bot to a standalone bundle
1061
1129
  upload Upload bot to VibeMancer for online competition
1130
+ pull Download latest source code from VibeMancer
1062
1131
 
1063
1132
  Common options:
1064
1133
  --bot <path> Path to bot source file (default: auto-discover)
@@ -1180,6 +1249,11 @@ async function main() {
1180
1249
  await runUpload({ bot });
1181
1250
  break;
1182
1251
  }
1252
+ case "pull": {
1253
+ const bot = parseFlag("--bot");
1254
+ await runPull({ bot });
1255
+ break;
1256
+ }
1183
1257
  default:
1184
1258
  console.error(`Unknown command: ${command}`);
1185
1259
  printHelp();
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/opponent-resolver.ts","../src/commands/test.ts","../src/commands/fight.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/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(props) { return {move: {x: 0, y: 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, build, etc.) honors --bot/--export\r\n * flags or vibemancer.json, falling back to src/bot.ts. Multi-bot mode (used\r\n * by the dev server, which exposes every locally-developed bot to the web\r\n * client) auto-scans src/ for .ts files with PascalCase named exports —\r\n * each such file becomes one local bot.\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\n/**\r\n * Discover the user's bot in the given project directory.\r\n *\r\n * Resolution order:\r\n * 1. vibemancer.json → { \"bot\": \"src/bot.ts\", \"export\": \"MyWizard\" }\r\n * 2. Default: src/bot.ts with first capitalized export found\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// If user passed --bot flag, use that directly\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// Try vibemancer.json\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// Default: src/bot.ts\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 src/bot.ts or add a vibemancer.json with {\"bot\": \"path/to/bot.ts\"}',\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 * Opponent Resolver\r\n *\r\n * Resolves an opponent name (e.g., \"Battlemage\", \"Turtle\") to a BotBundle\r\n * pointing at the built-in bot's TypeScript source file.\r\n */\r\n\r\nimport path from 'node:path';\r\nimport fs from 'node:fs';\r\nimport {fileURLToPath} from 'node:url';\r\nimport {BotBundle} from '@vibemancer/core';\r\nimport type {CompileOptions} from '@vibemancer/core';\r\n\r\n/**\r\n * Find the @vibemancer/core package's source directory.\r\n * The core package ships with both dist/ and src/ (TypeScript source).\r\n * esbuild needs the TypeScript source for compilation.\r\n */\r\nexport function findCoreSourceDir(): string\r\n{\r\n\t// When running from the monorepo (development), core is a sibling package\r\n\tconst monorepoCore = path.resolve(import.meta.dirname, '..', '..', 'core', 'src');\r\n\tif (fs.existsSync(path.join(monorepoCore, 'engine', 'simulation.ts')))\r\n\t{\r\n\t\treturn monorepoCore;\r\n\t}\r\n\r\n\t// When installed as a dependency, core is in node_modules\r\n\t// Use import.meta.resolve to find the package\r\n\ttry\r\n\t{\r\n\t\tconst coreIndex = import.meta.resolve('@vibemancer/core');\r\n\t\t// coreIndex = file:///path/to/node_modules/@vibemancer/core/dist/index.js\r\n\t\tconst coreIndexPath = fileURLToPath(coreIndex);\r\n\t\tconst coreRoot = path.resolve(path.dirname(coreIndexPath), '..');\r\n\t\tconst srcDir = path.join(coreRoot, 'src');\r\n\t\tif (fs.existsSync(path.join(srcDir, 'engine', 'simulation.ts')))\r\n\t\t{\r\n\t\t\treturn srcDir;\r\n\t\t}\r\n\t}\r\n\tcatch\r\n\t{\r\n\t\t// import.meta.resolve failed\r\n\t}\r\n\r\n\tthrow new Error(\r\n\t\t'Could not find @vibemancer/core source directory.\\n'\r\n\t\t+ 'Ensure @vibemancer/core is installed and includes its src/ directory.',\r\n\t);\r\n}\r\n\r\n/**\r\n * Built-in bot source file mapping.\r\n * Maps bot name → relative path from core's src/bots/ directory.\r\n *\r\n * Derived from the naming convention:\r\n * - Standalone: standalone/{Name}.ts\r\n * - Tiered: {group}/{nn}_{Name}.ts\r\n */\r\nconst BUILTIN_BOTS: Record<string, string> = {\r\n\t// Standalone\r\n\tTargetDummy: 'standalone/TargetDummy.ts',\r\n\tCritter: 'standalone/Critter.ts',\r\n\tRookie: 'standalone/Rookie.ts',\r\n\tHogger: 'standalone/Hogger.ts',\r\n\tDoombringer: 'standalone/Doombringer.ts',\r\n\t// Defensive\r\n\tTurtle: 'defensive/01_Turtle.ts',\r\n\tSentinel: 'defensive/02_Sentinel.ts',\r\n\tGolem: 'defensive/03_Golem.ts',\r\n\t// Melee\r\n\tShadowblade: 'melee/01_Shadowblade.ts',\r\n\tNightblade: 'melee/02_Nightblade.ts',\r\n\tVoidblade: 'melee/03_Voidblade.ts',\r\n\t// Homing\r\n\tBonemancer: 'homing/01_Bonemancer.ts',\r\n\tLich: 'homing/02_Lich.ts',\r\n\tArchlich: 'homing/03_Archlich.ts',\r\n\t// Caster\r\n\tFlamecaller: 'caster/01_Flamecaller.ts',\r\n\tPyromancer: 'caster/02_Pyromancer.ts',\r\n\tInfernalist: 'caster/03_Infernalist.ts',\r\n\t// Sniper\r\n\tSpellshot: 'sniper/01_Spellshot.ts',\r\n\tSpelltracer: 'sniper/02_Spelltracer.ts',\r\n\tSpellseeker: 'sniper/03_Spellseeker.ts',\r\n\t// Duelist\r\n\tBattlemage: 'duelist/01_Battlemage.ts',\r\n\tWarmage: 'duelist/02_Warmage.ts',\r\n\tArchmage: 'duelist/03_Archmage.ts',\r\n\t// Berserker\r\n\tStormchaser: 'berserker/01_Stormchaser.ts',\r\n\tStormcaller: 'berserker/02_Stormcaller.ts',\r\n\tStormforger: 'berserker/03_Stormforger.ts',\r\n\t// Kiter\r\n\tSpellspinner: 'kiter/01_Spellspinner.ts',\r\n\tSpellweaver: 'kiter/02_Spellweaver.ts',\r\n\tSpellbinder: 'kiter/03_Spellbinder.ts',\r\n};\r\n\r\n/**\r\n * Get CompileOptions that alias @vibemancer/core to the TypeScript source.\r\n * Required for compiling user bots that import from @vibemancer/core.\r\n */\r\nexport function getCoreCompileOptions(): CompileOptions\r\n{\r\n\tconst coreSourceDir = findCoreSourceDir();\r\n\treturn {\r\n\t\talias: {\r\n\t\t\t'@vibemancer/core': coreSourceDir + '/index-browser.ts',\r\n\t\t},\r\n\t};\r\n}\r\n\r\n/**\r\n * Get the list of all built-in bot names.\r\n */\r\nexport function getBuiltinBotNames(): string[]\r\n{\r\n\treturn Object.keys(BUILTIN_BOTS);\r\n}\r\n\r\n/**\r\n * Resolve an opponent name to a BotBundle.\r\n *\r\n * @param name - Built-in bot name (e.g., \"Battlemage\")\r\n * @returns BotBundle pointing at the bot's TypeScript source\r\n */\r\nexport function resolveOpponent(name: string): BotBundle\r\n{\r\n\tconst relativePath = BUILTIN_BOTS[name];\r\n\tif (!relativePath)\r\n\t{\r\n\t\tconst available = Object.keys(BUILTIN_BOTS).join(', ');\r\n\t\tthrow new Error(\r\n\t\t\t`Unknown opponent \"${name}\".\\n`\r\n\t\t\t+ `Available built-in bots: ${available}`,\r\n\t\t);\r\n\t}\r\n\r\n\tconst coreSourceDir = findCoreSourceDir();\r\n\tconst sourcePath = path.join(coreSourceDir, 'bots', relativePath);\r\n\r\n\tif (!fs.existsSync(sourcePath))\r\n\t{\r\n\t\tthrow new Error(`Built-in bot source not found: ${sourcePath}`);\r\n\t}\r\n\r\n\treturn new BotBundle(sourcePath, name);\r\n}\r\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} from '@vibemancer/core';\r\nimport type {FightWinner} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, getBuiltinBotNames, getCoreCompileOptions} from '../opponent-resolver.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 userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\tconst opponentBundle = resolveOpponent(options.opponent);\r\n\r\n\tconst start = Date.now();\r\n\tconst result = await sandboxFight(userBundle, opponentBundle, {\r\n\t\tseed: options.seed,\r\n\t\tcompileOptions: getCoreCompileOptions(),\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","/**\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,\r\n\textractTraceEvents, summarizeTrace, formatTraceEvents, formatTraceSummary,\r\n\tdiagnoseTrace, formatDiagnosis,\r\n\textractStats, formatStats,\r\n} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, getCoreCompileOptions} from '../opponent-resolver.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 userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\tconst opponentBundle = resolveOpponent(options.opponent);\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\tconst result = await sandboxSimulate(userBundle, opponentBundle, {\r\n\t\tseed: options.seed ?? 1,\r\n\t\tspawnDistance: distance,\r\n\t\tmaxTicks: options.maxTicks ?? 3000,\r\n\t\tcompileOptions: getCoreCompileOptions(),\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 {BotEntry} 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: BotEntry): 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","/**\r\n * vibemancer upload\r\n *\r\n * Compiles the user's bot into a standalone bundle and uploads it\r\n * to the VibeMancer server via Firebase Cloud Functions.\r\n *\r\n * The bundle contains only the bot code (+ any npm deps used).\r\n * The server validates it by running a test fight against TargetDummy.\r\n * Deduplication: if the same code was uploaded before, the old wizard\r\n * is reactivated (preserving its rating and match history).\r\n */\r\n\r\nimport {createHash} from 'node:crypto';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {compileSingleBotBundle} from '../compile-single-bot.js';\r\n\r\nexport interface UploadOptions\r\n{\r\n\tbot?: string;\r\n}\r\n\r\nexport async function runUpload(options: UploadOptions): 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 Compiling ${botInfo.exportName}...`);\r\n\r\n\tconst bundle = await compileSingleBotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\tconst sizeKb = (bundle.length / 1024).toFixed(1);\r\n\tconsole.log(` Bundle: ${sizeKb} KB`);\r\n\r\n\tif (bundle.length > 500 * 1024)\r\n\t{\r\n\t\tconsole.error(` Error: Bundle too large (${sizeKb} KB). Max 500 KB.`);\r\n\t\tprocess.exit(1);\r\n\t}\r\n\r\n\t// Extract wizard name from source (looks for: export const name = \"...\")\r\n\tconst nameMatch = bundle.match(/export\\s+(?:const|var|let)\\s+name\\s*=\\s*[\"']([^\"']+)[\"']/);\r\n\tconst wizardName = nameMatch?.[1] ?? botInfo.exportName;\r\n\r\n\t// Compute SHA256 hash for deduplication\r\n\tconst bundleHash = createHash('sha256').update(bundle).digest('hex');\r\n\r\n\tconsole.log(` Wizard: ${wizardName}`);\r\n\tconsole.log(` Hash: ${bundleHash.slice(0, 12)}...`);\r\n\tconsole.log(' Uploading to VibeMancer...');\r\n\r\n\t// Call the uploadWizard Cloud Function\r\n\ttry\r\n\t{\r\n\t\tconst {initializeApp} = await import('firebase/app');\r\n\t\tconst {getFunctions, httpsCallable} = await import('firebase/functions');\r\n\r\n\t\tconst app = initializeApp({\r\n\t\t\tapiKey: 'AIzaSyDSUJ2jlk5_vlpGOypMtvqKjHhDmbgomIY',\r\n\t\t\tauthDomain: 'le-vibemancer.firebaseapp.com',\r\n\t\t\tprojectId: 'le-vibemancer',\r\n\t\t});\r\n\r\n\t\tinterface UploadRequest\r\n\t\t{\r\n\t\t\tbundle: string;\r\n\t\t\tname: string;\r\n\t\t\texportName: string;\r\n\t\t}\r\n\t\tinterface UploadResponse\r\n\t\t{\r\n\t\t\twizardId: string;\r\n\t\t\tactive: boolean;\r\n\t\t\treactivated: boolean;\r\n\t\t\terror: string | null;\r\n\t\t\tmessage: string;\r\n\t\t}\r\n\r\n\t\tconst functions = getFunctions(app, 'us-central1');\r\n\t\tconst uploadFn = httpsCallable<UploadRequest, UploadResponse>(functions, 'uploadWizard');\r\n\r\n\t\tconst result = await uploadFn({\r\n\t\t\tbundle,\r\n\t\t\tname: wizardName,\r\n\t\t\texportName: botInfo.exportName,\r\n\t\t});\r\n\r\n\t\tconst data = result.data;\r\n\r\n\t\tif (data.active)\r\n\t\t{\r\n\t\t\tif (data.reactivated)\r\n\t\t\t{\r\n\t\t\t\tconsole.log(` ↺ ${data.message}`);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tconsole.log(` ✓ ${data.message}`);\r\n\t\t\t}\r\n\t\t\tconsole.log(` Wizard ID: ${data.wizardId}`);\r\n\t\t\tconsole.log(` Your wizard \"${wizardName}\" is now competing.\\n`);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tconsole.error(` ✗ ${data.message}`);\r\n\t\t\tconsole.error(' Fix the error and try again.\\n');\r\n\t\t\tprocess.exit(1);\r\n\t\t}\r\n\t}\r\n\tcatch(err: unknown)\r\n\t{\r\n\t\tconst message = err instanceof Error ? err.message : String(err);\r\n\t\tconsole.error(` ✗ Upload failed: ${message}\\n`);\r\n\t\tprocess.exit(1);\r\n\t}\r\n}\r\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\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 upload Upload bot to VibeMancer for online competition\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 instead of all bots\r\n --seed <n> Random seed\r\n\r\nTrace options:\r\n --opponent <name> Opponent bot name (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`);\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\tconsole.error('Error: --opponent is required for trace command.');\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\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":";;;AAaA,SAAQ,gBAAe;;;ACDvB,OAAO,QAAQ;AACf,OAAO,UAAU;AAuBjB,eAAsB,YAAY,YAAoB,cACtD;AACC,QAAM,SAAS,KAAK,QAAQ,UAAU;AAGtC,MAAI,cACJ;AACC,UAAM,UAAU,KAAK,QAAQ,QAAQ,YAAY;AACjD,QAAI,CAAC,GAAG,WAAW,OAAO,GAC1B;AACC,YAAM,IAAI,MAAM,uBAAuB,OAAO,EAAE;AAAA,IACjD;AACA,UAAM,aAAa,MAAM,eAAe,OAAO;AAC/C,WAAO,EAAC,YAAY,SAAS,WAAU;AAAA,EACxC;AAGA,QAAM,aAAa,KAAK,KAAK,QAAQ,iBAAiB;AACtD,MAAI,GAAG,WAAW,UAAU,GAC5B;AACC,UAAM,MAAM,GAAG,aAAa,YAAY,OAAO;AAC/C,QAAI;AACJ,QACA;AAEC,eAAS,KAAK,MAAM,GAAG;AAAA,IACxB,QAEA;AACC,YAAM,IAAI,MAAM,oCAAoC,UAAU,EAAE;AAAA,IACjE;AAEA,QAAI,OAAO,QAAQ,QAAQ,OAAO,QAAQ,UAAa,OAAO,OAAO,QAAQ,UAC7E;AACC,YAAM,IAAI,MAAM,gEAAgE,OAAO,OAAO,GAAG,EAAE;AAAA,IACpG;AAEA,QAAI,OAAO,WAAW,QAAQ,OAAO,WAAW,UAAa,OAAO,OAAO,WAAW,UACtF;AACC,YAAM,IAAI,MAAM,mEAAmE,OAAO,OAAO,MAAM,EAAE;AAAA,IAC1G;AAEA,QAAI,OAAO,KACX;AACC,YAAM,UAAU,KAAK,QAAQ,QAAQ,OAAO,GAAG;AAC/C,UAAI,CAAC,GAAG,WAAW,OAAO,GAC1B;AACC,cAAM,IAAI,MAAM,4CAA4C,OAAO,EAAE;AAAA,MACtE;AACA,YAAM,aAAa,OAAO,UAAU,MAAM,eAAe,OAAO;AAChE,aAAO,EAAC,YAAY,SAAS,WAAU;AAAA,IACxC;AAAA,EACD;AAGA,QAAM,cAAc,KAAK,KAAK,QAAQ,OAAO,QAAQ;AACrD,MAAI,GAAG,WAAW,WAAW,GAC7B;AACC,UAAM,aAAa,MAAM,eAAe,WAAW;AACnD,WAAO,EAAC,YAAY,aAAa,WAAU;AAAA,EAC5C;AAEA,QAAM,IAAI;AAAA,IACT;AAAA,EAED;AACD;AAMA,eAAe,eAAe,UAC9B;AACC,QAAM,UAAU,GAAG,aAAa,UAAU,OAAO;AAGjD,QAAM,QAAQ,QAAQ,MAAM,gDAAgD;AAC5E,MAAI,QAAQ,CAAC,GACb;AACC,WAAO,MAAM,CAAC;AAAA,EACf;AAGA,QAAM,WAAW,QAAQ,MAAM,0BAA0B;AACzD,MAAI,WAAW,CAAC,GAChB;AACC,WAAO,SAAS,CAAC;AAAA,EAClB;AAEA,QAAM,IAAI;AAAA,IACT,oCAAoC,QAAQ;AAAA;AAAA;AAAA,EAG7C;AACD;AAEA,IAAM,0BAA0B;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AACD;AACA,IAAM,sBAAsB,oBAAI,IAAI;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,CAAC;AACD,IAAM,uBAAuB,oBAAI,IAAI;AAAA,EACpC;AAAA,EAAY;AAAA,EACZ;AAAA,EAAY;AAAA,EACZ;AAAA,EAAc;AACf,CAAC;AAED,SAAS,uBAAuB,SAChC;AACC,QAAM,MAAgB,CAAC;AACvB,QAAM,QAAkB,CAAC,OAAO;AAChC,SAAO,MAAM,SAAS,GACtB;AACC,UAAM,MAAM,MAAM,IAAI;AACtB,QAAI,QAAQ,OAAW;AACvB,QAAI;AACJ,QACA;AACC,gBAAU,GAAG,YAAY,KAAK,EAAC,eAAe,KAAI,CAAC;AAAA,IACpD,QAEA;AACC;AAAA,IACD;AACA,eAAW,SAAS,SACpB;AACC,YAAM,OAAO,KAAK,KAAK,KAAK,MAAM,IAAI;AACtC,UAAI,MAAM,YAAY,GACtB;AACC,YAAI,oBAAoB,IAAI,MAAM,IAAI,EAAG;AACzC,YAAI,MAAM,KAAK,WAAW,GAAG,EAAG;AAChC,cAAM,KAAK,IAAI;AACf;AAAA,MACD;AACA,UAAI,CAAC,MAAM,OAAO,EAAG;AACrB,UAAI,CAAC,MAAM,KAAK,SAAS,KAAK,KAAK,CAAC,MAAM,KAAK,SAAS,MAAM,EAAG;AACjE,UAAI,qBAAqB,IAAI,MAAM,IAAI,EAAG;AAC1C,UAAI,wBAAwB,KAAK,CAAC,OAAO,GAAG,KAAK,MAAM,IAAI,CAAC,EAAG;AAC/D,UAAI,KAAK,IAAI;AAAA,IACd;AAAA,EACD;AACA,SAAO;AACR;AAaA,eAAsB,gBAAgB,YACtC;AACC,QAAM,SAAS,KAAK,QAAQ,UAAU;AACtC,QAAM,SAAS,KAAK,KAAK,QAAQ,KAAK;AACtC,MAAI,CAAC,GAAG,WAAW,MAAM,EAAG,QAAO,CAAC;AAEpC,QAAM,QAAQ,uBAAuB,MAAM;AAC3C,QAAM,OAAkB,CAAC;AACzB,QAAM,YAAY,oBAAI,IAAY;AAClC,aAAW,QAAQ,OACnB;AACC,QAAI;AACJ,QACA;AACC,mBAAa,MAAM,eAAe,IAAI;AAAA,IACvC,QAEA;AACC;AAAA,IACD;AACA,QAAI,UAAU,IAAI,UAAU,EAAG;AAC/B,cAAU,IAAI,UAAU;AACxB,SAAK,KAAK,EAAC,YAAY,MAAM,WAAU,CAAC;AAAA,EACzC;AACA,OAAK,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,cAAc,EAAE,UAAU,CAAC;AAC5D,SAAO;AACR;;;AC/MA,OAAO,UAAU;;;ACDjB,SAAQ,aAAY;;;ACXpB,OAAOA,WAAU;AACjB,OAAOC,SAAQ;AACf,SAAQ,qBAAoB;AAC5B,SAAQ,iBAAgB;AAQjB,SAAS,oBAChB;AAEC,QAAM,eAAeD,MAAK,QAAQ,YAAY,SAAS,MAAM,MAAM,QAAQ,KAAK;AAChF,MAAIC,IAAG,WAAWD,MAAK,KAAK,cAAc,UAAU,eAAe,CAAC,GACpE;AACC,WAAO;AAAA,EACR;AAIA,MACA;AACC,UAAM,YAAY,YAAY,QAAQ,kBAAkB;AAExD,UAAM,gBAAgB,cAAc,SAAS;AAC7C,UAAM,WAAWA,MAAK,QAAQA,MAAK,QAAQ,aAAa,GAAG,IAAI;AAC/D,UAAM,SAASA,MAAK,KAAK,UAAU,KAAK;AACxC,QAAIC,IAAG,WAAWD,MAAK,KAAK,QAAQ,UAAU,eAAe,CAAC,GAC9D;AACC,aAAO;AAAA,IACR;AAAA,EACD,QAEA;AAAA,EAEA;AAEA,QAAM,IAAI;AAAA,IACT;AAAA,EAED;AACD;AAUA,IAAM,eAAuC;AAAA;AAAA,EAE5C,aAAa;AAAA,EACb,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,aAAa;AAAA;AAAA,EAEb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,OAAO;AAAA;AAAA,EAEP,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,WAAW;AAAA;AAAA,EAEX,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,UAAU;AAAA;AAAA,EAEV,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,aAAa;AAAA;AAAA,EAEb,WAAW;AAAA,EACX,aAAa;AAAA,EACb,aAAa;AAAA;AAAA,EAEb,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,UAAU;AAAA;AAAA,EAEV,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA;AAAA,EAEb,cAAc;AAAA,EACd,aAAa;AAAA,EACb,aAAa;AACd;AAMO,SAAS,wBAChB;AACC,QAAM,gBAAgB,kBAAkB;AACxC,SAAO;AAAA,IACN,OAAO;AAAA,MACN,oBAAoB,gBAAgB;AAAA,IACrC;AAAA,EACD;AACD;AAKO,SAAS,qBAChB;AACC,SAAO,OAAO,KAAK,YAAY;AAChC;AAQO,SAAS,gBAAgB,MAChC;AACC,QAAM,eAAe,aAAa,IAAI;AACtC,MAAI,CAAC,cACL;AACC,UAAM,YAAY,OAAO,KAAK,YAAY,EAAE,KAAK,IAAI;AACrD,UAAM,IAAI;AAAA,MACT,qBAAqB,IAAI;AAAA,2BACK,SAAS;AAAA,IACxC;AAAA,EACD;AAEA,QAAM,gBAAgB,kBAAkB;AACxC,QAAM,aAAaA,MAAK,KAAK,eAAe,QAAQ,YAAY;AAEhE,MAAI,CAACC,IAAG,WAAW,UAAU,GAC7B;AACC,UAAM,IAAI,MAAM,kCAAkC,UAAU,EAAE;AAAA,EAC/D;AAEA,SAAO,IAAI,UAAU,YAAY,IAAI;AACtC;;;ADjIA,eAAsB,uBACrB,YACA,YAED;AACC,QAAM,gBAAgB,kBAAkB;AAExC,QAAM,SAAS,MAAM,MAAM;AAAA,IAC1B,aAAa,CAAC,UAAU;AAAA,IACxB,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,QAAQ,EAAC,IAAI,2CAA2C,UAAU,IAAG;AAAA,IACrE,UAAU;AAAA,MACT;AAAA,MAAe;AAAA,MACf;AAAA,IACD;AAAA,IACA,OAAO;AAAA,MACN,oBAAoB,gBAAgB;AAAA,IACrC;AAAA,EACD,CAAC;AAED,MAAI,CAAC,OAAO,cAAc,CAAC,GAC3B;AACC,UAAM,IAAI,MAAM,4BAA4B;AAAA,EAC7C;AAEA,SAAO,OAAO,YAAY,CAAC,EAAE;AAC9B;;;ADfA,SAAS,cAAc,MACvB;AACC,SAAO;AAAA,IACN,MAAM,KAAK;AAAA,IACX,YAAY,KAAK;AAAA,IACjB,YAAY,KAAK;AAAA,EAClB;AACD;AAMO,SAAS,YAAY,SAC5B;AACC,QAAM,EAAC,MAAM,WAAU,IAAI;AAE3B,iBAAe,WACf;AAIC,WAAO,gBAAgB,UAAU;AAAA,EAClC;AAEA,QAAM,SAAS,KAAK,aAAa,OAAM,KAAK,QAC5C;AAEC,QAAI,UAAU,+BAA+B,GAAG;AAChD,QAAI,UAAU,gCAAgC,cAAc;AAC5D,QAAI,UAAU,gCAAgC,cAAc;AAE5D,QAAI,IAAI,WAAW,WACnB;AACC,UAAI,UAAU,GAAG;AACjB,UAAI,IAAI;AACR;AAAA,IACD;AAEA,UAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,oBAAoB,IAAI,EAAE;AAC9D,UAAM,WAAW,IAAI;AAErB,QACA;AACC,UAAI,aAAa,WACjB;AACC,gBAAQ,KAAK,KAAK,EAAC,QAAQ,KAAI,CAAC;AAChC;AAAA,MACD;AAEA,UAAI,aAAa,eACjB;AACC,cAAM,OAAO,MAAM,SAAS;AAC5B,cAAM,OAA0B,EAAC,MAAM,KAAK,IAAI,aAAa,EAAC;AAC9D,gBAAQ,KAAK,KAAK,IAAI;AACtB;AAAA,MACD;AAEA,YAAM,cAAc,mDAAmD,KAAK,QAAQ;AACpF,UAAI,aACJ;AACC,cAAM,gBAAgB,YAAY,CAAC;AACnC,cAAM,OAAO,MAAM,SAAS;AAC5B,cAAM,SAAS,KAAK,KAAK,CAAC,MAAM,EAAE,eAAe,aAAa;AAC9D,YAAI,CAAC,QACL;AACC,kBAAQ,KAAK,KAAK,EAAC,OAAO,uBAAuB,aAAa,aAAa,KAAK,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,IAAI,KAAK,QAAQ,GAAE,CAAC;AAClI;AAAA,QACD;AAEA,cAAM,QAAQ,KAAK,IAAI;AACvB,cAAM,SAAS,MAAM,uBAAuB,OAAO,YAAY,OAAO,UAAU;AAChF,cAAM,UAAU,KAAK,IAAI,IAAI;AAC7B,gBAAQ,IAAI,cAAc,OAAO,UAAU,MAAM,OAAO,SAAS,MAAM,QAAQ,CAAC,CAAC,WAAW,OAAO,IAAI;AAEvG,YAAI,UAAU,KAAK,EAAC,gBAAgB,kBAAiB,CAAC;AACtD,YAAI,IAAI,MAAM;AACd;AAAA,MACD;AAEA,cAAQ,KAAK,KAAK,EAAC,OAAO,cAAc,QAAQ,GAAE,CAAC;AAAA,IACpD,SACM,OACN;AACC,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,cAAQ,MAAM,YAAY,OAAO,EAAE;AACnC,cAAQ,KAAK,KAAK,EAAC,OAAO,QAAO,CAAC;AAAA,IACnC;AAAA,EACD,CAAC;AAED,SAAO,OAAO,MAAM,MACpB;AACC,YAAQ,IAAI;AAAA,oDAAuD,IAAI,EAAE;AACzE,UAAM,YACN;AACC,YAAM,OAAO,MAAM,SAAS;AAC5B,UAAI,KAAK,WAAW,GACpB;AACC,gBAAQ,IAAI,+EAA0E;AAAA,MACvF,OAEA;AACC,gBAAQ,IAAI,WAAW,KAAK,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,MAClE;AACA,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,4BAA4B;AACxC,cAAQ,IAAI,iDAAiD,IAAI;AAAA,CAAI;AACrE,cAAQ,IAAI,YAAY;AACxB,cAAQ,IAAI,yEAAyE;AACrF,cAAQ,IAAI,wFAAwF;AACpG,cAAQ,IAAI,+DAA+D;AAAA,IAC5E,GAAG;AAAA,EACJ,CAAC;AAED,SAAO;AACR;AAEA,SAAS,QAAQ,KAA0B,QAAgB,MAC3D;AACC,MAAI,UAAU,QAAQ,EAAC,gBAAgB,mBAAkB,CAAC;AAC1D,MAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAC7B;;;AFxIA,eAAsB,OAAO,SAC7B;AACC,QAAM,aAAa,QAAQ,IAAI;AAK/B,QAAM,OAAO,MAAM,gBAAgB,UAAU;AAC7C,MAAI,KAAK,WAAW,GACpB;AACC,YAAQ,IAAI,4EAA4E;AACxF,YAAQ,IAAI,oEAAoE;AAAA,EACjF,OAEA;AACC,YAAQ,IAAI,cAAc,KAAK,MAAM,OAAO,KAAK,WAAW,IAAI,KAAK,GAAG,KAAK,KAAK,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EACxH;AAEA,QAAM,SAAS,YAAY;AAAA,IAC1B,MAAM,QAAQ;AAAA,IACd;AAAA,EACD,CAAC;AAGD,SAAO,KAAK,aAAa,MACzB;AACC,UAAM,MAAM,+CAA+C,QAAQ,IAAI;AACvE,gBAAY,GAAG;AAAA,EAChB,CAAC;AACF;AAEA,SAAS,YAAY,KACrB;AACC,QAAM,WAAW,QAAQ;AAEzB,MACA;AACC,QAAI,aAAa,UACjB;AACC,eAAS,QAAQ,CAAC,GAAG,GAAG,MACxB;AAAA,MAAC,CAAC;AAAA,IACH,WACS,aAAa,SACtB;AACC,eAAS,OAAO,CAAC,MAAM,SAAS,IAAI,GAAG,GAAG,MAC1C;AAAA,MAAC,CAAC;AAAA,IACH,OAEA;AAEC,eAAS,YAAY,CAAC,GAAG,GAAG,CAAC,QAC7B;AACC,YAAI,IAAK,UAAS,WAAW,CAAC,GAAG,GAAG,MACpC;AAAA,QAAC,CAAC;AAAA,MACH,CAAC;AAAA,IACF;AAAA,EACD,QAEA;AAAA,EAEA;AACD;;;AK7EA,SAAQ,gBAAe;AAOvB,eAAsB,QAAQ,UAC9B;AACC,UAAQ,IAAI,wBAAwB;AAEpC,MACA;AACC,aAAS,kBAAkB;AAAA,MAC1B,OAAO;AAAA,MACP,KAAK,QAAQ,IAAI;AAAA,IAClB,CAAC;AAAA,EACF,QAEA;AACC,YAAQ,KAAK,CAAC;AAAA,EACf;AACD;;;ACpBA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAQ,aAAAC,YAAW,cAAc,kBAAiB;AA+BlD,eAAsB,SAAS,SAC/B;AACC,MAAI,QAAQ,UACZ;AACC,WAAO,eAAe,EAAC,GAAG,SAAS,UAAU,QAAQ,SAAQ,CAAC;AAAA,EAC/D;AACA,SAAO,aAAa,OAAO;AAC5B;AAIA,eAAe,eAAe,SAC9B;AACC,QAAM,aAAa,QAAQ,IAAI;AAC/B,QAAM,UAAU,MAAM,YAAY,YAAY,QAAQ,GAAG;AAEzD,UAAQ,IAAI;AAAA,SAAY,QAAQ,UAAU,EAAE;AAC5C,UAAQ,IAAI,eAAe,QAAQ,QAAQ;AAAA,CAAI;AAE/C,QAAM,aAAa,IAAIC,WAAU,QAAQ,YAAY,QAAQ,UAAU;AACvE,QAAM,iBAAiB,gBAAgB,QAAQ,QAAQ;AAEvD,QAAM,QAAQ,KAAK,IAAI;AACvB,QAAM,SAAS,MAAM,aAAa,YAAY,gBAAgB;AAAA,IAC7D,MAAM,QAAQ;AAAA,IACd,gBAAgB,sBAAsB;AAAA,EACvC,CAAC;AACD,QAAM,UAAU,KAAK,IAAI,IAAI;AAE7B,QAAM,EAAC,aAAa,aAAa,MAAK,IAAI;AAC1C,QAAM,QAAQ,cAAc,cAAc;AAC1C,QAAM,UAAU,OAAO,WAAW,aAAa,QAC5C,OAAO,WAAW,aAAa,SAC9B;AAEJ,UAAQ,IAAI,aAAa,OAAO,EAAE;AAClC,UAAQ,IAAI,KAAK,QAAQ,UAAU,KAAK,WAAW,SAAS,QAAQ,QAAQ,KAAK,WAAW,gBAAgB,KAAK,EAAE;AACnH,UAAQ,IAAI,MAAM,KAAK,eAAe,OAAO;AAAA,CAAO;AAEpD,MAAI,OAAO,WAAW,YACtB;AACC,YAAQ,KAAK,CAAC;AAAA,EACf;AACD;AAIA,eAAe,aAAa,SAC5B;AACC,QAAM,aAAa,QAAQ,IAAI;AAC/B,QAAM,UAAU,MAAM,YAAY,YAAY,QAAQ,GAAG;AACzD,QAAM,aAAa,IAAIA,WAAU,QAAQ,YAAY,QAAQ,UAAU;AAEvE,QAAM,YAAY,mBAAmB;AACrC,UAAQ,IAAI;AAAA,aAAgB,QAAQ,UAAU,YAAY,UAAU,MAAM;AAAA,CAAqB;AAE/F,QAAM,UAAwB,CAAC;AAC/B,QAAM,eAAe,KAAK,IAAI;AAE9B,aAAW,gBAAgB,WAC3B;AACC,UAAM,iBAAiB,gBAAgB,YAAY;AACnD,UAAM,QAAQ,KAAK,IAAI;AACvB,UAAM,SAAS,MAAM,aAAa,YAAY,gBAAgB;AAAA,MAC7D,MAAM,QAAQ;AAAA,MACd,gBAAgB,sBAAsB;AAAA,IACvC,CAAC;AACD,UAAM,UAAU,KAAK,IAAI,IAAI;AAC7B,UAAM,QAAQ,WAAW,MAAM;AAE/B,YAAQ,KAAK;AAAA,MACZ,UAAU;AAAA,MACV,QAAQ,OAAO;AAAA,MACf,aAAa,OAAO;AAAA,MACpB,aAAa,OAAO;AAAA,MACpB,OAAO,OAAO;AAAA,MACd;AAAA,MACA,WAAW;AAAA,IACZ,CAAC;AAED,UAAM,UAAU,OAAO,WAAW,aAAa,MAC5C,OAAO,WAAW,aAAa,MAC9B;AACJ,UAAM,MAAM,aAAa,OAAO,EAAE;AAClC,YAAQ,IAAI,KAAK,GAAG,IAAI,OAAO,KAAK,OAAO,WAAW,IAAI,OAAO,WAAW,IAAI,OAAO,KAAK,MAAM,OAAO,KAAK;AAAA,EAC/G;AAEA,QAAM,eAAe,KAAK,IAAI,IAAI;AAClC,QAAM,OAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU,EAAE;AAC5D,QAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU,EAAE;AAC9D,QAAM,YAAY,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM,EAAE;AAC7D,QAAM,aAAa,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC;AAC9D,QAAM,WAAW,UAAU,SAAS;AAEpC,UAAQ,IAAI;AAAA,aAAgB,IAAI,KAAK,MAAM,KAAK,SAAS,YAAY,UAAU,MAAM,YAAY;AACjG,UAAQ,IAAI,YAAY,WAAW,QAAQ,CAAC,CAAC,MAAM,SAAS,QAAQ,CAAC,CAAC,MAAO,aAAa,WAAY,KAAK,QAAQ,CAAC,CAAC,IAAI;AACzH,UAAQ,IAAI,kBAAkB,eAAe,KAAM,QAAQ,CAAC,CAAC,GAAG;AAGhE,QAAM,UAAU,YAAY,UAAU;AACtC,QAAM,WAAW,QAAQ,SAAS,IAAI,QAAQ,QAAQ,SAAS,CAAC,IAAK;AAErE,MAAI,YAAY,SAAS,YAAY,QAAQ,YAC7C;AACC,aAAS,SAAS,SAAS,OAAO;AAAA,EACnC;AAGA,QAAM,UAAwB;AAAA,IAC7B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,SAAS,QAAQ;AAAA,IACjB,SAAS;AAAA,IACT,SAAS,EAAC,MAAM,QAAQ,OAAO,WAAW,OAAO,YAAY,SAAQ;AAAA,EACtE;AACA,cAAY,YAAY,SAAS,OAAO;AACxC,UAAQ,IAAI,EAAE;AACf;AAIA,SAAS,eAAe,YACxB;AACC,SAAOC,MAAK,KAAK,YAAY,eAAe,cAAc;AAC3D;AAEA,SAAS,YAAY,YACrB;AACC,QAAM,cAAc,eAAe,UAAU;AAC7C,MAAI,CAACC,IAAG,WAAW,WAAW,EAAG,QAAO,CAAC;AACzC,MACA;AACC,UAAM,MAAMA,IAAG,aAAa,aAAa,OAAO;AAEhD,WAAO,KAAK,MAAM,GAAG;AAAA,EACtB,QAEA;AACC,WAAO,CAAC;AAAA,EACT;AACD;AAEA,SAAS,YAAY,YAAoB,SAAyB,SAClE;AACC,QAAM,cAAc,eAAe,UAAU;AAC7C,QAAM,MAAMD,MAAK,QAAQ,WAAW;AACpC,EAAAC,IAAG,UAAU,KAAK,EAAC,WAAW,KAAI,CAAC;AAGnC,QAAM,UAAU,CAAC,GAAG,QAAQ,MAAM,GAAG,GAAG,OAAO;AAC/C,EAAAA,IAAG,cAAc,aAAa,KAAK,UAAU,SAAS,MAAM,GAAI,IAAI,IAAI;AACzE;AAEA,SAAS,SAAS,SAAuB,UACzC;AACC,QAAM,UAAU,IAAI,IAAI,SAAS,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AAC5D,QAAM,UAAoB,CAAC;AAE3B,aAAW,SAAS,SACpB;AACC,UAAM,OAAO,QAAQ,IAAI,MAAM,QAAQ;AACvC,QAAI,CAAC,KAAM;AAEX,UAAM,cAAc,KAAK,WAAW,aAAa,MAAM,KAAK,WAAW,aAAa,MAAM;AAC1F,UAAM,aAAa,MAAM,WAAW,aAAa,MAAM,MAAM,WAAW,aAAa,MAAM;AAE3F,QAAI,gBAAgB,YACpB;AACC,cAAQ,KAAK,OAAO,MAAM,SAAS,OAAO,EAAE,CAAC,IAAI,WAAW,OAAO,UAAU,EAAE;AAAA,IAChF;AAAA,EACD;AAEA,QAAM,YAAY,SAAS,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC;AAC9D,QAAM,WAAW,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC;AAC5D,QAAM,OAAO,WAAW;AAExB,MAAI,QAAQ,SAAS,KAAK,KAAK,IAAI,IAAI,IAAI,KAC3C;AACC,YAAQ,IAAI,kBAAkB;AAC9B,QAAI,KAAK,IAAI,IAAI,IAAI,KACrB;AACC,YAAM,OAAO,OAAO,IAAI,MAAM;AAC9B,cAAQ,IAAI,cAAc,IAAI,GAAG,KAAK,QAAQ,CAAC,CAAC,EAAE;AAAA,IACnD;AACA,eAAW,UAAU,SACrB;AACC,cAAQ,IAAI,MAAM;AAAA,IACnB;AAAA,EACD;AACD;;;AC9NA;AAAA,EACC,aAAAC;AAAA,EAAW;AAAA,EACX;AAAA,EAAoB;AAAA,EAAgB;AAAA,EAAmB;AAAA,EACvD;AAAA,EAAe;AAAA,EACf;AAAA,EAAc;AAAA,OACR;AAaP,eAAsB,SAAS,SAC/B;AACC,QAAM,aAAa,QAAQ,IAAI;AAC/B,QAAM,UAAU,MAAM,YAAY,YAAY,QAAQ,GAAG;AAEzD,QAAM,aAAa,IAAIC,WAAU,QAAQ,YAAY,QAAQ,UAAU;AACvE,QAAM,iBAAiB,gBAAgB,QAAQ,QAAQ;AAEvD,QAAM,WAAW,QAAQ,YAAY;AACrC,UAAQ,IAAI;AAAA,WAAc,QAAQ,UAAU,YAAY,QAAQ,QAAQ,qBAAqB,QAAQ,YAAY,QAAQ,QAAQ,CAAC;AAAA,CAAI;AAEtI,QAAM,SAAS,MAAM,gBAAgB,YAAY,gBAAgB;AAAA,IAChE,MAAM,QAAQ,QAAQ;AAAA,IACtB,eAAe;AAAA,IACf,UAAU,QAAQ,YAAY;AAAA,IAC9B,gBAAgB,sBAAsB;AAAA,EACvC,CAAC;AAED,QAAM,UAAU,OAAO;AACvB,MAAI,QAAQ,WAAW,GACvB;AACC,YAAQ,IAAI,2BAA2B;AACvC;AAAA,EACD;AAGA,QAAM,SAAS,mBAAmB,SAAS,OAAO,MAAM;AACxD,UAAQ,IAAI,kBAAkB,MAAM,CAAC;AAGrC,QAAM,UAAU,eAAe,QAAQ,QAAQ,QAAQ,YAAY,QAAQ,QAAQ;AACnF,UAAQ,IAAI,OAAO,mBAAmB,OAAO,CAAC;AAG9C,QAAM,QAAQ,aAAa,MAAM;AACjC,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,YAAY,OAAO,QAAQ,UAAU,CAAC;AAGlD,QAAM,OAAO,cAAc,QAAQ,OAAO;AAC1C,MAAI,KAAK,SAAS,GAClB;AACC,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,gBAAgB,IAAI,CAAC;AAAA,EAClC;AACA,UAAQ,IAAI,EAAE;AACf;;;ACjEA,SAAQ,aAAAC,YAAW,gBAAAC,eAAc,cAAAC,aAAY,2BAA0B;AA0BvE,eAAsB,cAAc,SACpC;AACC,QAAM,aAAa,QAAQ,IAAI;AAC/B,QAAM,UAAU,MAAM,YAAY,YAAY,QAAQ,GAAG;AACzD,QAAM,aAAa,IAAIC,WAAU,QAAQ,YAAY,QAAQ,UAAU;AAGvE,QAAM,gBAAgB,QAAQ,aAAa,QAAQ,UAAU,SAAS,IACnE,QAAQ,YACR,mBAAmB;AAGtB,QAAM,eAAoD;AAAA,IACzD,EAAC,MAAM,QAAQ,YAAY,QAAQ,WAAU;AAAA,EAC9C;AAEA,aAAW,QAAQ,eACnB;AACC,iBAAa,KAAK,EAAC,MAAM,QAAQ,gBAAgB,IAAI,EAAC,CAAC;AAAA,EACxD;AAEA,UAAQ,IAAI;AAAA,gBAAmB,aAAa,MAAM,kBAAkB,aAAa,UAAU,aAAa,SAAS,KAAK,CAAC;AAAA,CAAc;AAGrI,QAAM,WAAsB,CAAC;AAC7B,WAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KACzC;AACC,aAAS,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAC7C;AACC,eAAS,KAAK;AAAA,QACb,UAAU,aAAa,CAAC,EAAG;AAAA,QAC3B,UAAU,aAAa,CAAC,EAAG;AAAA,QAC3B,YAAY,aAAa,CAAC,EAAG;AAAA,QAC7B,YAAY,aAAa,CAAC,EAAG;AAAA,MAC9B,CAAC;AAAA,IACF;AAAA,EACD;AAGA,QAAM,UAA2B,CAAC;AAClC,QAAM,eAAe,KAAK,IAAI;AAE9B,aAAW,WAAW,UACtB;AACC,UAAM,SAAS,MAAMC,cAAa,QAAQ,YAAY,QAAQ,YAAY;AAAA,MACzE,gBAAgB,sBAAsB;AAAA,IACvC,CAAC;AACD,YAAQ,KAAK;AAAA,MACZ,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,MAClB;AAAA,IACD,CAAC;AAED,UAAM,UAAU,OAAO,WAAW,aAAa,GAAG,QAAQ,QAAQ,UAC/D,OAAO,WAAW,aAAa,GAAG,QAAQ,QAAQ,UACjD;AACJ,YAAQ,IAAI,KAAK,QAAQ,QAAQ,OAAO,QAAQ,QAAQ,KAAK,OAAO,WAAW,IAAI,OAAO,WAAW,IAAI,OAAO,KAAK,KAAK,OAAO,GAAG;AAAA,EACrI;AAGA,QAAM,SAAS,oBAAI,IAAoB;AACvC,QAAM,OAAO,oBAAI,IAAoB;AAErC,aAAW,KAAK,cAChB;AACC,WAAO,IAAI,EAAE,MAAM,CAAC;AACpB,SAAK,IAAI,EAAE,MAAM,CAAC;AAAA,EACnB;AAEA,aAAW,KAAK,SAChB;AACC,UAAM,SAASC,YAAW,EAAE,MAAM;AAClC,UAAM,SAAS,oBAAoB,EAAE,MAAM;AAE3C,WAAO,IAAI,EAAE,WAAW,OAAO,IAAI,EAAE,QAAQ,KAAK,KAAK,MAAM;AAC7D,WAAO,IAAI,EAAE,WAAW,OAAO,IAAI,EAAE,QAAQ,KAAK,KAAK,MAAM;AAC7D,SAAK,IAAI,EAAE,WAAW,KAAK,IAAI,EAAE,QAAQ,KAAK,KAAK,EAAE,OAAO,WAAW;AACvE,SAAK,IAAI,EAAE,WAAW,KAAK,IAAI,EAAE,QAAQ,KAAK,KAAK,EAAE,OAAO,WAAW;AAAA,EACxE;AAEA,QAAM,eAAe,KAAK,IAAI,IAAI;AAGlC,QAAM,YAAY,CAAC,GAAG,OAAO,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MACjD;AACC,QAAI,EAAE,CAAC,MAAM,EAAE,CAAC,EAAG,QAAO,EAAE,CAAC,IAAI,EAAE,CAAC;AACpC,YAAQ,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK;AAAA,EACnD,CAAC;AAED,UAAQ,IAAI,gBAAgB;AAC5B,UAAQ,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;AACjC,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KACtC;AACC,UAAM,CAAC,MAAM,GAAG,IAAI,UAAU,CAAC;AAC/B,UAAM,IAAI,KAAK,IAAI,IAAI,KAAK;AAC5B,UAAM,OAAO,KAAK,IAAI,GAAG,SAAS,EAAE,SAAS,CAAC,CAAC;AAC/C,UAAM,SAAS,SAAS,QAAQ,aAAa,OAAO;AACpD,YAAQ,IAAI,KAAK,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC,IAAI,IAAI,QAAQ,CAAC,CAAC,SAAS,CAAC,IAAI,MAAM,EAAE;AAAA,EAClF;AAEA,UAAQ,IAAI;AAAA,iBAAoB,eAAe,KAAM,QAAQ,CAAC,CAAC;AAAA,CAAK;AACrE;;;AC9HA,SAAQ,cAAc,qBAAoB;AAC1C,SAAQ,aAAAC,YAAW,cAAc,cAAAC,aAAY,oBAAoB,yBAAwB;AAwBzF,IAAM,YAAY;AAElB,SAAS,cAAc,GACvB;AACC,QAAM,IAAI,WAAW,EAAE,KAAK,CAAC;AAC7B,MAAI,OAAO,MAAM,CAAC,EAAG,OAAM,IAAI,MAAM,sCAAsC,EAAE,KAAK,CAAC,GAAG;AACtF,SAAO;AACR;AAEO,SAAS,YAAY,QAC5B;AACC,QAAM,SAAwB,CAAC;AAC/B,QAAM,KAAK,IAAI,OAAO,UAAU,QAAQ,GAAG;AAC3C,MAAI;AAEJ,UAAQ,QAAQ,GAAG,KAAK,MAAM,OAAO,MACrC;AACC,UAAM,OAAO,MAAM,CAAC;AACpB,UAAM,eAAe,cAAc,MAAM,CAAC,CAAE;AAC5C,UAAM,UAAU,MAAM,CAAC;AAEvB,QAAI;AACJ,QAAI;AACJ,QAAI;AAEJ,QAAI,SACJ;AACC,YAAM,WAAW,QAAQ,MAAM,oBAAoB;AACnD,YAAM,WAAW,QAAQ,MAAM,oBAAoB;AACnD,YAAM,YAAY,QAAQ,MAAM,qBAAqB;AACrD,UAAI,SAAU,OAAM,cAAc,SAAS,CAAC,CAAE;AAC9C,UAAI,SAAU,OAAM,cAAc,SAAS,CAAC,CAAE;AAC9C,UAAI,UAAW,QAAO,cAAc,UAAU,CAAC,CAAE;AAAA,IAClD;AAEA,WAAO,KAAK,EAAC,MAAM,cAAc,KAAK,KAAK,KAAI,CAAC;AAAA,EACjD;AAEA,SAAO;AACR;AAEA,SAAS,mBAAmB,GAC5B;AACC,SAAO;AAAA,IACN,MAAM,EAAE;AAAA,IACR,OAAO,EAAE;AAAA,IACT,KAAK,EAAE;AAAA,IACP,KAAK,EAAE;AAAA,IACP,OAAO,EAAE,QAAQ;AAAA,EAClB;AACD;AAMA,IAAM,kBAAkB,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AAChD,IAAM,QAAQ,CAAC,IAAI,KAAK,GAAG;AAE3B,SAAS,mBACR,SACA,SAED;AACC,MAAI,KAAK;AACT,MAAI,KAAK;AACT,MAAI,QAAQ;AACZ,QAAM,UAA4B,CAAC;AAEnC,aAAW,QAAQ,OACnB;AACC,eAAW,QAAQ,iBACnB;AACC,YAAM,IAAI,QAAQ,SAAS;AAAA,QAC1B;AAAA,QACA,eAAe;AAAA,QACf,aAAa;AAAA,QACb;AAAA,MACD,CAAC;AACD,UAAI,EAAE,WAAW,WAAY;AAAA,eACpB,EAAE,WAAW,WAAY;AAAA,UAC7B;AAEL,cAAQ,KAAK,CAAC;AAAA,IACf;AAAA,EACD;AAEA,SAAO;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb;AAAA,IACA,QAAS,KAAK,KAAK,aAAa,KAAK,KAAK,aAAa;AAAA,IACvD;AAAA,EACD;AACD;AAEA,eAAe,eACd,YACA,iBACA,SAED;AACC,MAAI,aAAa;AACjB,aAAW,YAAY,iBACvB;AACC,UAAM,UAAU,MAAM,aAAa,OAAO,YAAY,UAAU;AAAA,MAC/D,gBAAgB,sBAAsB;AAAA,IACvC,CAAC;AACD,QACA;AACC,YAAM,SAAS,mBAAmB,SAAS,OAAO;AAClD,oBAAcC,YAAW,MAAM;AAAA,IAChC,UACA;AAEC,cAAQ,QAAQ;AAAA,IACjB;AAAA,EACD;AACA,SAAO;AACR;AAMO,SAAS,qBAAqB,WACrC;AACC,MAAI,CAAC,aAAa,UAAU,WAAW,GACvC;AACC,WAAO,mBAAmB;AAAA,EAC3B;AAGA,QAAM,WAAW,mBAAmB;AACpC,aAAW,QAAQ,WACnB;AACC,QAAI,CAAC,SAAS,SAAS,IAAI,GAC3B;AACC,YAAM,IAAI;AAAA,QACT,sBAAsB,IAAI;AAAA,IAAyB,SAAS,KAAK,IAAI,CAAC;AAAA,MACvE;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAEA,eAAsB,YAAY,SAClC;AACC,QAAM,aAAa,QAAQ,IAAI;AAC/B,QAAM,UAAU,MAAM,YAAY,YAAY,QAAQ,GAAG;AAEzD,QAAM,SAAS,aAAa,QAAQ,YAAY,OAAO;AACvD,QAAM,SAAS,YAAY,MAAM;AAEjC,MAAI,OAAO,WAAW,GACtB;AACC,YAAQ,IAAI,4CAA4C;AACxD,YAAQ,IAAI,iFAAiF;AAC7F;AAAA,EACD;AAEA,UAAQ,IAAI;AAAA,SAAY,QAAQ,UAAU,EAAE;AAC5C,UAAQ,IAAI,iBAAiB,OAAO,MAAM,EAAE;AAC5C,SAAO,QAAQ,CAAC,MAAM,QAAQ,IAAI,OAAO,EAAE,IAAI,MAAM,EAAE,YAAY,KAAK,EAAE,OAAO,MAAM,OAAO,EAAE,OAAO,MAAM,GAAG,CAAC;AAEjH,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,YAAY,QAAQ,UAAU;AACpC,QAAM,gBAAgB,qBAAqB,QAAQ,SAAS;AAC5D,QAAM,kBAAkB,cAAc,IAAI,CAAC,SAAS,gBAAgB,IAAI,CAAC;AACzE,QAAM,aAAa,IAAIC,WAAU,QAAQ,YAAY,QAAQ,UAAU;AAEvE,UAAQ,IAAI,gBAAgB,gBAAgB,MAAM,EAAE;AACpD,UAAQ,IAAI,sBAAsB,KAAK,EAAE;AACzC,UAAQ,IAAI,iBAAiB,SAAS;AAAA,CAAI;AAG1C,QAAM,OAA+B,CAAC;AACtC,aAAW,KAAK,OAAQ,MAAK,EAAE,IAAI,IAAI,EAAE;AAGzC,MAAI,YAAY,MAAM,eAAe,YAAY,iBAAiB,IAAI;AACtE,UAAQ,IAAI,qBAAqB,UAAU,QAAQ,CAAC,CAAC,OAAO,gBAAgB,SAAS,gBAAgB,SAAS,MAAM,SAAS,KAAK,QAAQ,CAAC,CAAC;AAAA,CAAI;AAGhJ,WAAS,QAAQ,GAAG,QAAQ,WAAW,SACvC;AACC,QAAI,WAAW;AACf,YAAQ,IAAI,WAAW,QAAQ,CAAC,GAAG;AAEnC,eAAW,KAAK,QAChB;AACC,YAAM,OAAO,mBAAmB,CAAC;AACjC,YAAM,QAAQ,kBAAkB,IAAI;AACpC,YAAM,aAAa,mBAAmB,MAAM,KAAK,MAAM,KAAK,KAAK;AAEjE,UAAI,YAAY,KAAK,EAAE,IAAI;AAC3B,UAAI,iBAAiB;AAErB,iBAAW,aAAa,YACxB;AACC,YAAI,KAAK,IAAI,YAAY,SAAS,IAAI,KAAO;AAE7C,cAAM,QAAQ,EAAC,GAAG,MAAM,CAAC,EAAE,IAAI,GAAG,UAAS;AAC3C,cAAM,QAAQ,MAAM,eAAe,YAAY,iBAAiB,KAAK;AAErE,YAAI,QAAQ,gBACZ;AACC,sBAAY;AACZ,2BAAiB;AAAA,QAClB;AAAA,MACD;AAEA,UAAI,cAAc,KAAK,EAAE,IAAI,GAC7B;AACC,gBAAQ,IAAI,OAAO,EAAE,IAAI,KAAK,KAAK,EAAE,IAAI,CAAC,OAAO,SAAS,OAAO,iBAAiB,WAAW,QAAQ,CAAC,CAAC,GAAG;AAC1G,aAAK,EAAE,IAAI,IAAI;AACf,oBAAY;AACZ,mBAAW;AAAA,MACZ,OAEA;AACC,gBAAQ,IAAI,OAAO,EAAE,IAAI,KAAK,KAAK,EAAE,IAAI,CAAC,mBAAmB;AAAA,MAC9D;AAAA,IACD;AAEA,QAAI,CAAC,UACL;AACC,cAAQ,IAAI,sCAAsC;AAClD;AAAA,IACD;AACA,YAAQ,IAAI,WAAW,QAAQ,CAAC,WAAW,UAAU,QAAQ,CAAC,CAAC;AAAA,CAAI;AAAA,EACpE;AAGA,MAAI,UAAU;AACd,aAAW,KAAK,QAChB;AACC,UAAM,SAAS,KAAK,EAAE,IAAI;AAC1B,QAAI,WAAW,EAAE,cACjB;AACC,YAAM,UAAU,IAAI;AAAA,QACnB,uBAAuB,YAAY,EAAE,IAAI,CAAC,iBAAiB,YAAY,OAAO,EAAE,YAAY,CAAC,CAAC;AAAA,MAC/F;AACA,gBAAU,QAAQ,QAAQ,SAAS,KAAK,MAAM,EAAE;AAAA,IACjD;AAAA,EACD;AAEA,MAAI,YAAY,QAChB;AACC,kBAAc,QAAQ,YAAY,OAAO;AACzC,YAAQ,IAAI,qBAAqB,QAAQ,UAAU,EAAE;AAAA,EACtD,OAEA;AACC,YAAQ,IAAI,kCAAkC;AAAA,EAC/C;AAEA,UAAQ,IAAI,kBAAkB,UAAU,QAAQ,CAAC,CAAC,OAAO,gBAAgB,SAAS,gBAAgB,SAAS,MAAM,SAAS,KAAK,QAAQ,CAAC,CAAC;AAAA,CAAI;AAC9I;AAEA,SAAS,YAAY,GACrB;AACC,SAAO,EAAE,QAAQ,uBAAuB,MAAM;AAC/C;;;ACnSA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAQ,aAAAC,YAAW,0BAAyB;AAW5C,eAAsB,SAAS,SAC/B;AACC,QAAM,aAAa,QAAQ,IAAI;AAC/B,QAAM,UAAU,MAAM,YAAY,YAAY,QAAQ,GAAG;AACzD,QAAM,gBAAgB,kBAAkB;AAExC,QAAM,aAAa,IAAIC,WAAU,QAAQ,YAAY,QAAQ,UAAU;AACvE,QAAM,iBAAiB,gBAAgB,QAAQ,QAAQ;AAEvD,UAAQ,IAAI;AAAA,cAAiB,QAAQ,UAAU,OAAO,QAAQ,QAAQ,KAAK;AAE3E,QAAM,QAAQ,KAAK,IAAI;AACvB,QAAM,SAAS,MAAM,mBAAmB,YAAY,gBAAgB;AAAA,IACnE,OAAO;AAAA,MACN,oBAAoB,gBAAgB;AAAA,IACrC;AAAA,EACD,CAAC;AACD,QAAM,UAAU,KAAK,IAAI,IAAI;AAE7B,QAAM,UAAU,QAAQ,UAAU,QAAQ,QAAQ,UAAU,OAAO,QAAQ,QAAQ;AACnF,QAAM,SAASC,MAAK,QAAQA,MAAK,QAAQ,OAAO,CAAC;AACjD,EAAAC,IAAG,UAAU,QAAQ,EAAC,WAAW,KAAI,CAAC;AACtC,EAAAA,IAAG,cAAcD,MAAK,QAAQ,OAAO,GAAG,MAAM;AAE9C,QAAM,UAAU,OAAO,SAAS,MAAM,QAAQ,CAAC;AAC/C,UAAQ,IAAI,aAAa,OAAO,KAAK,MAAM,MAAM;AACjD,UAAQ,IAAI,iBAAiB,OAAO;AAAA,CAAM;AAC3C;;;ACvCA,SAAQ,YAAY,gBAAe;AAQ5B,SAAS,QAAQ,SACxB;AACC,MAAI,QAAQ,MACZ;AACC,kBAAc,QAAQ,IAAI;AAC1B;AAAA,EACD;AACA,cAAY;AACb;AAEA,SAAS,cACT;AACC,UAAQ,IAAI,iEAA4D;AAExE,aAAW,SAAS,YACpB;AACC,YAAQ,IAAI,KAAK,MAAM,KAAK,GAAG;AAC/B,eAAW,OAAO,MAAM,MACxB;AACC,YAAM,OAAO,SAAS,QAAQ,GAAG,IAAI;AACrC,YAAM,YAAY,IAAI,OAAO,IAAI,IAAI,IAAI,KAAK;AAC9C,YAAM,UAAU,IAAI,OAAO,IAAI,EAAE,SAAS,CAAC,CAAC;AAC5C,cAAQ,IAAI,OAAO,OAAO,IAAI,SAAS,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC,IAAI,IAAI,WAAW,EAAE;AAAA,IACpF;AACA,YAAQ,IAAI,EAAE;AAAA,EACf;AACD;AAEA,SAAS,cAAc,MACvB;AACC,QAAM,MAAM,SAAS,KAAK,CAAC,MAAM,EAAE,KAAK,YAAY,MAAM,KAAK,YAAY,CAAC;AAC5E,MAAI,CAAC,KACL;AACC,UAAM,YAAY,SAAS,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI;AACvD,YAAQ,MAAM;AAAA,kBAAqB,IAAI;AAAA,eAAmB,SAAS;AAAA,CAAI;AACvE,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,OAAO,SAAS,QAAQ,GAAG,IAAI;AAErC,UAAQ,IAAI;AAAA,IAAO,IAAI,IAAI,EAAE;AAC7B,UAAQ,IAAI,KAAK,SAAI,OAAO,EAAE,CAAC,EAAE;AACjC,UAAQ,IAAI,mBAAmB,IAAI,OAAO,SAAS,MAAM,EAAE;AAC3D,UAAQ,IAAI,kBAAkB,IAAI,KAAK,EAAE;AACzC,MAAI,IAAI,KAAM,SAAQ,IAAI,kBAAkB,IAAI,IAAI,OAAO;AAC3D,UAAQ,IAAI,kBAAkB,IAAI,WAAW,EAAE;AAC/C,UAAQ,IAAI,kBAAkB,oBAAoB,GAAG,CAAC,EAAE;AAGxD,MAAI,IAAI,QAAQ,IAAI,UAAU,cAC9B;AACC,UAAM,YAAY,WAAW,KAAK,CAAC,MAAM,EAAE,UAAU,IAAI,KAAK,GAAG,QAAQ,CAAC;AAC1E,QAAI,UAAU,SAAS,GACvB;AACC,cAAQ,IAAI;AAAA,IAAO,IAAI,KAAK,eAAe;AAC3C,iBAAW,MAAM,WACjB;AACC,cAAM,SAAS,SAAS,QAAQ,EAAE,IAAI;AACtC,cAAM,SAAS,GAAG,SAAS,IAAI,OAAO,YAAO;AAC7C,gBAAQ,IAAI,QAAQ,GAAG,IAAI,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC,KAAK,MAAM,WAAM,GAAG,WAAW,GAAG,MAAM,EAAE;AAAA,MAC5F;AAAA,IACD;AAAA,EACD;AAEA,UAAQ,IAAI;AAAA,2CAA8C,IAAI,IAAI,EAAE;AACpE,UAAQ,IAAI,4CAA4C,IAAI,IAAI;AAAA,CAAI;AACrE;AAEA,SAAS,oBAAoB,KAC7B;AACC,UAAQ,IAAI,OACZ;AAAA,IACC,KAAK;AACJ,UAAI,IAAI,SAAS,cAAe,QAAO;AACvC,UAAI,IAAI,SAAS,UAAW,QAAO;AACnC,UAAI,IAAI,SAAS,SAAU,QAAO;AAClC,UAAI,IAAI,SAAS,SAAU,QAAO;AAClC,UAAI,IAAI,SAAS,cAAe,QAAO;AACvC,aAAO,IAAI;AAAA,IACZ,KAAK;AAAa,aAAO;AAAA,IACzB,KAAK;AAAS,aAAO;AAAA,IACrB,KAAK;AAAU,aAAO;AAAA,IACtB,KAAK;AAAU,aAAO;AAAA,IACtB,KAAK;AAAU,aAAO;AAAA,IACtB,KAAK;AAAW,aAAO;AAAA,IACvB,KAAK;AAAa,aAAO;AAAA,IACzB,KAAK;AAAS,aAAO;AAAA,IACrB;AAAS,aAAO,IAAI;AAAA,EACrB;AACD;;;AC5FA,SAAQ,kBAAiB;AASzB,eAAsB,UAAU,SAChC;AACC,QAAM,aAAa,QAAQ,IAAI;AAC/B,QAAM,UAAU,MAAM,YAAY,YAAY,QAAQ,GAAG;AAEzD,UAAQ,IAAI;AAAA,cAAiB,QAAQ,UAAU,KAAK;AAEpD,QAAM,SAAS,MAAM,uBAAuB,QAAQ,YAAY,QAAQ,UAAU;AAClF,QAAM,UAAU,OAAO,SAAS,MAAM,QAAQ,CAAC;AAC/C,UAAQ,IAAI,aAAa,MAAM,KAAK;AAEpC,MAAI,OAAO,SAAS,MAAM,MAC1B;AACC,YAAQ,MAAM,8BAA8B,MAAM,mBAAmB;AACrE,YAAQ,KAAK,CAAC;AAAA,EACf;AAGA,QAAM,YAAY,OAAO,MAAM,0DAA0D;AACzF,QAAM,aAAa,YAAY,CAAC,KAAK,QAAQ;AAG7C,QAAM,aAAa,WAAW,QAAQ,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK;AAEnE,UAAQ,IAAI,aAAa,UAAU,EAAE;AACrC,UAAQ,IAAI,WAAW,WAAW,MAAM,GAAG,EAAE,CAAC,KAAK;AACnD,UAAQ,IAAI,8BAA8B;AAG1C,MACA;AACC,UAAM,EAAC,cAAa,IAAI,MAAM,OAAO,cAAc;AACnD,UAAM,EAAC,cAAc,cAAa,IAAI,MAAM,OAAO,oBAAoB;AAEvE,UAAM,MAAM,cAAc;AAAA,MACzB,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,WAAW;AAAA,IACZ,CAAC;AAiBD,UAAM,YAAY,aAAa,KAAK,aAAa;AACjD,UAAM,WAAW,cAA6C,WAAW,cAAc;AAEvF,UAAM,SAAS,MAAM,SAAS;AAAA,MAC7B;AAAA,MACA,MAAM;AAAA,MACN,YAAY,QAAQ;AAAA,IACrB,CAAC;AAED,UAAM,OAAO,OAAO;AAEpB,QAAI,KAAK,QACT;AACC,UAAI,KAAK,aACT;AACC,gBAAQ,IAAI,YAAO,KAAK,OAAO,EAAE;AAAA,MAClC,OAEA;AACC,gBAAQ,IAAI,YAAO,KAAK,OAAO,EAAE;AAAA,MAClC;AACA,cAAQ,IAAI,gBAAgB,KAAK,QAAQ,EAAE;AAC3C,cAAQ,IAAI,kBAAkB,UAAU;AAAA,CAAuB;AAAA,IAChE,OAEA;AACC,cAAQ,MAAM,YAAO,KAAK,OAAO,EAAE;AACnC,cAAQ,MAAM,kCAAkC;AAChD,cAAQ,KAAK,CAAC;AAAA,IACf;AAAA,EACD,SACM,KACN;AACC,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,YAAQ,MAAM,2BAAsB,OAAO;AAAA,CAAI;AAC/C,YAAQ,KAAK,CAAC;AAAA,EACf;AACD;;;ACxFA,IAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,IAAM,UAAU,KAAK,CAAC;AAEtB,SAAS,UAAU,MACnB;AACC,QAAM,MAAM,KAAK,QAAQ,IAAI;AAC7B,MAAI,QAAQ,MAAM,MAAM,IAAI,KAAK,QACjC;AACC,WAAO,KAAK,MAAM,CAAC;AAAA,EACpB;AACA,SAAO;AACR;AAEA,SAAS,aAAa,MAAc,UACpC;AACC,QAAM,MAAM,UAAU,IAAI;AAC1B,MAAI,QAAQ,OAAW,QAAO;AAC9B,QAAM,IAAI,SAAS,KAAK,EAAE;AAC1B,MAAI,OAAO,MAAM,CAAC,GAClB;AACC,YAAQ,MAAM,UAAU,IAAI,2BAA2B,GAAG,IAAI;AAC9D,YAAQ,KAAK,CAAC;AAAA,EACf;AACA,SAAO;AACR;AAEA,SAAS,YACT;AACC,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAmDZ;AACD;AAEA,eAAe,OACf;AACC,MAAI,CAAC,WAAW,YAAY,YAAY,YAAY,MACpD;AACC,cAAU;AACV;AAAA,EACD;AAEA,UAAQ,SACR;AAAA,IACC,KAAK,OACL;AACC,YAAM,OAAO,aAAa,UAAU,IAAI;AACxC,YAAM,MAAM,UAAU,OAAO;AAC7B,YAAM,OAAO,EAAC,MAAM,IAAG,CAAC;AACxB;AAAA,IACD;AAAA,IAEA,KAAK,QACL;AACC,YAAM,MAAM,UAAU,OAAO;AAC7B,YAAM,QAAQ,EAAC,IAAG,CAAC;AACnB;AAAA,IACD;AAAA,IAEA,KAAK,SACL;AACC,YAAM,WAAW,UAAU,YAAY;AACvC,YAAM,MAAM,UAAU,OAAO;AAC7B,YAAM,OAAO,UAAU,QAAQ,MAAM,SAAY,aAAa,UAAU,CAAC,IAAI;AAC7E,YAAM,SAAS,EAAC,UAAU,KAAK,KAAI,CAAC;AACpC;AAAA,IACD;AAAA,IAEA,KAAK,SACL;AACC,YAAM,WAAW,UAAU,YAAY;AACvC,UAAI,CAAC,UACL;AACC,gBAAQ,MAAM,kDAAkD;AAChE,gBAAQ,MAAM,+CAA+C;AAC7D,gBAAQ,KAAK,CAAC;AAAA,MACf;AACA,YAAM,MAAM,UAAU,OAAO;AAC7B,YAAM,OAAO,UAAU,QAAQ,MAAM,SAAY,aAAa,UAAU,CAAC,IAAI;AAC7E,YAAM,WAAW,UAAU,YAAY,MAAM,SAAY,aAAa,cAAc,GAAG,IAAI;AAC3F,YAAM,SAAS,EAAC,UAAU,KAAK,MAAM,SAAQ,CAAC;AAC9C;AAAA,IACD;AAAA,IAEA,KAAK,QACL;AACC,YAAM,OAAO,UAAU,QAAQ,KAAK,KAAK,CAAC;AAC1C,cAAQ,EAAC,MAAM,MAAM,WAAW,IAAI,IAAI,SAAY,KAAI,CAAC;AACzD;AAAA,IACD;AAAA,IAEA,KAAK,cACL;AACC,YAAM,MAAM,UAAU,OAAO;AAC7B,YAAM,cAAc,oBAAI,IAAY;AACpC,eAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KACjC;AACC,YAAI,KAAK,CAAC,EAAG,WAAW,IAAI,GAC5B;AACC,sBAAY,IAAI,CAAC;AACjB,sBAAY,IAAI,IAAI,CAAC;AAAA,QACtB;AAAA,MACD;AACA,YAAM,YAAY,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC;AACxE,YAAM,cAAc,EAAC,WAAW,IAAG,CAAC;AACpC;AAAA,IACD;AAAA,IAEA,KAAK,YACL;AACC,YAAM,MAAM,UAAU,OAAO;AAC7B,YAAM,eAAe,UAAU,aAAa;AAC5C,YAAM,YAAY,eAAe,aAAa,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,IAAI;AAChG,YAAM,YAAY;AAAA,QACjB;AAAA,QACA,OAAO,UAAU,SAAS,MAAM,SAAY,aAAa,WAAW,CAAC,IAAI;AAAA,QACzE,QAAQ,UAAU,UAAU,MAAM,SAAY,aAAa,YAAY,CAAC,IAAI;AAAA,QAC5E;AAAA,MACD,CAAC;AACD;AAAA,IACD;AAAA,IAEA,KAAK,SACL;AACC,YAAM,WAAW,UAAU,YAAY;AACvC,UAAI,CAAC,UACL;AACC,gBAAQ,MAAM,kDAAkD;AAChE,gBAAQ,MAAM,+CAA+C;AAC7D,gBAAQ,KAAK,CAAC;AAAA,MACf;AACA,YAAM,MAAM,UAAU,OAAO;AAC7B,YAAM,SAAS,UAAU,UAAU;AACnC,YAAM,SAAS,EAAC,UAAU,KAAK,OAAM,CAAC;AACtC;AAAA,IACD;AAAA,IAEA,KAAK,UACL;AACC,YAAM,MAAM,UAAU,OAAO;AAC7B,YAAM,UAAU,EAAC,IAAG,CAAC;AACrB;AAAA,IACD;AAAA,IAEA;AACC,cAAQ,MAAM,oBAAoB,OAAO,EAAE;AAC3C,gBAAU;AACV,cAAQ,KAAK,CAAC;AAAA,EAChB;AACD;AAEA,KAAK,EAAE,MAAM,CAAC,UACd;AACC,UAAQ,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtE,UAAQ,KAAK,CAAC;AACf,CAAC;","names":["path","fs","fs","path","BotBundle","BotBundle","path","fs","BotBundle","BotBundle","BotBundle","sandboxFight","scoreFight","BotBundle","sandboxFight","scoreFight","BotBundle","scoreFight","scoreFight","BotBundle","fs","path","BotBundle","BotBundle","path","fs"]}
1
+ {"version":3,"sources":["../src/commands/dev.ts","../src/bot-discovery.ts","../src/server.ts","../src/compile-single-bot.ts","../src/opponent-resolver.ts","../src/commands/test.ts","../src/commands/fight.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/commands/pull.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(props) { return {move: {x: 0, y: 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, build, etc.) honors --bot/--export\r\n * flags or vibemancer.json, falling back to src/bot.ts. Multi-bot mode (used\r\n * by the dev server, which exposes every locally-developed bot to the web\r\n * client) auto-scans src/ for .ts files with PascalCase named exports —\r\n * each such file becomes one local bot.\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\n/**\r\n * Discover the user's bot in the given project directory.\r\n *\r\n * Resolution order:\r\n * 1. vibemancer.json → { \"bot\": \"src/bot.ts\", \"export\": \"MyWizard\" }\r\n * 2. Default: src/bot.ts with first capitalized export found\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// If user passed --bot flag, use that directly\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// Try vibemancer.json\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// Default: src/bot.ts\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 src/bot.ts or add a vibemancer.json with {\"bot\": \"path/to/bot.ts\"}',\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 * Opponent Resolver\r\n *\r\n * Resolves an opponent name (e.g., \"Battlemage\", \"Turtle\") to a BotBundle\r\n * pointing at the built-in bot's TypeScript source file.\r\n */\r\n\r\nimport path from 'node:path';\r\nimport fs from 'node:fs';\r\nimport {fileURLToPath} from 'node:url';\r\nimport {BotBundle} from '@vibemancer/core';\r\nimport type {CompileOptions} from '@vibemancer/core';\r\n\r\n/**\r\n * Find the @vibemancer/core package's source directory.\r\n * The core package ships with both dist/ and src/ (TypeScript source).\r\n * esbuild needs the TypeScript source for compilation.\r\n */\r\nexport function findCoreSourceDir(): string\r\n{\r\n\t// When running from the monorepo (development), core is a sibling package\r\n\tconst monorepoCore = path.resolve(import.meta.dirname, '..', '..', 'core', 'src');\r\n\tif (fs.existsSync(path.join(monorepoCore, 'engine', 'simulation.ts')))\r\n\t{\r\n\t\treturn monorepoCore;\r\n\t}\r\n\r\n\t// When installed as a dependency, core is in node_modules\r\n\t// Use import.meta.resolve to find the package\r\n\ttry\r\n\t{\r\n\t\tconst coreIndex = import.meta.resolve('@vibemancer/core');\r\n\t\t// coreIndex = file:///path/to/node_modules/@vibemancer/core/dist/index.js\r\n\t\tconst coreIndexPath = fileURLToPath(coreIndex);\r\n\t\tconst coreRoot = path.resolve(path.dirname(coreIndexPath), '..');\r\n\t\tconst srcDir = path.join(coreRoot, 'src');\r\n\t\tif (fs.existsSync(path.join(srcDir, 'engine', 'simulation.ts')))\r\n\t\t{\r\n\t\t\treturn srcDir;\r\n\t\t}\r\n\t}\r\n\tcatch\r\n\t{\r\n\t\t// import.meta.resolve failed\r\n\t}\r\n\r\n\tthrow new Error(\r\n\t\t'Could not find @vibemancer/core source directory.\\n'\r\n\t\t+ 'Ensure @vibemancer/core is installed and includes its src/ directory.',\r\n\t);\r\n}\r\n\r\n/**\r\n * Built-in bot source file mapping.\r\n * Maps bot name → relative path from core's src/bots/ directory.\r\n *\r\n * Derived from the naming convention:\r\n * - Standalone: standalone/{Name}.ts\r\n * - Tiered: {group}/{nn}_{Name}.ts\r\n */\r\nconst BUILTIN_BOTS: Record<string, string> = {\r\n\t// Standalone\r\n\tTargetDummy: 'standalone/TargetDummy.ts',\r\n\tCritter: 'standalone/Critter.ts',\r\n\tRookie: 'standalone/Rookie.ts',\r\n\tHogger: 'standalone/Hogger.ts',\r\n\tDoombringer: 'standalone/Doombringer.ts',\r\n\t// Defensive\r\n\tTurtle: 'defensive/01_Turtle.ts',\r\n\tSentinel: 'defensive/02_Sentinel.ts',\r\n\tGolem: 'defensive/03_Golem.ts',\r\n\t// Melee\r\n\tShadowblade: 'melee/01_Shadowblade.ts',\r\n\tNightblade: 'melee/02_Nightblade.ts',\r\n\tVoidblade: 'melee/03_Voidblade.ts',\r\n\t// Homing\r\n\tBonemancer: 'homing/01_Bonemancer.ts',\r\n\tLich: 'homing/02_Lich.ts',\r\n\tArchlich: 'homing/03_Archlich.ts',\r\n\t// Caster\r\n\tFlamecaller: 'caster/01_Flamecaller.ts',\r\n\tPyromancer: 'caster/02_Pyromancer.ts',\r\n\tInfernalist: 'caster/03_Infernalist.ts',\r\n\t// Sniper\r\n\tSpellshot: 'sniper/01_Spellshot.ts',\r\n\tSpelltracer: 'sniper/02_Spelltracer.ts',\r\n\tSpellseeker: 'sniper/03_Spellseeker.ts',\r\n\t// Duelist\r\n\tBattlemage: 'duelist/01_Battlemage.ts',\r\n\tWarmage: 'duelist/02_Warmage.ts',\r\n\tArchmage: 'duelist/03_Archmage.ts',\r\n\t// Berserker\r\n\tStormchaser: 'berserker/01_Stormchaser.ts',\r\n\tStormcaller: 'berserker/02_Stormcaller.ts',\r\n\tStormforger: 'berserker/03_Stormforger.ts',\r\n\t// Kiter\r\n\tSpellspinner: 'kiter/01_Spellspinner.ts',\r\n\tSpellweaver: 'kiter/02_Spellweaver.ts',\r\n\tSpellbinder: 'kiter/03_Spellbinder.ts',\r\n};\r\n\r\n/**\r\n * Get CompileOptions that alias @vibemancer/core to the TypeScript source.\r\n * Required for compiling user bots that import from @vibemancer/core.\r\n */\r\nexport function getCoreCompileOptions(): CompileOptions\r\n{\r\n\tconst coreSourceDir = findCoreSourceDir();\r\n\treturn {\r\n\t\talias: {\r\n\t\t\t'@vibemancer/core': coreSourceDir + '/index-browser.ts',\r\n\t\t},\r\n\t};\r\n}\r\n\r\n/**\r\n * Get the list of all built-in bot names.\r\n */\r\nexport function getBuiltinBotNames(): string[]\r\n{\r\n\treturn Object.keys(BUILTIN_BOTS);\r\n}\r\n\r\n/**\r\n * Resolve an opponent name to a BotBundle.\r\n *\r\n * @param name - Built-in bot name (e.g., \"Battlemage\")\r\n * @returns BotBundle pointing at the bot's TypeScript source\r\n */\r\nexport function resolveOpponent(name: string): BotBundle\r\n{\r\n\tconst relativePath = BUILTIN_BOTS[name];\r\n\tif (!relativePath)\r\n\t{\r\n\t\tconst available = Object.keys(BUILTIN_BOTS).join(', ');\r\n\t\tthrow new Error(\r\n\t\t\t`Unknown opponent \"${name}\".\\n`\r\n\t\t\t+ `Available built-in bots: ${available}`,\r\n\t\t);\r\n\t}\r\n\r\n\tconst coreSourceDir = findCoreSourceDir();\r\n\tconst sourcePath = path.join(coreSourceDir, 'bots', relativePath);\r\n\r\n\tif (!fs.existsSync(sourcePath))\r\n\t{\r\n\t\tthrow new Error(`Built-in bot source not found: ${sourcePath}`);\r\n\t}\r\n\r\n\treturn new BotBundle(sourcePath, name);\r\n}\r\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} from '@vibemancer/core';\r\nimport type {FightWinner} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, getBuiltinBotNames, getCoreCompileOptions} from '../opponent-resolver.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 userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\tconst opponentBundle = resolveOpponent(options.opponent);\r\n\r\n\tconst start = Date.now();\r\n\tconst result = await sandboxFight(userBundle, opponentBundle, {\r\n\t\tseed: options.seed,\r\n\t\tcompileOptions: getCoreCompileOptions(),\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","/**\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,\r\n\textractTraceEvents, summarizeTrace, formatTraceEvents, formatTraceSummary,\r\n\tdiagnoseTrace, formatDiagnosis,\r\n\textractStats, formatStats,\r\n} from '@vibemancer/core';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {resolveOpponent, getCoreCompileOptions} from '../opponent-resolver.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 userBundle = new BotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\tconst opponentBundle = resolveOpponent(options.opponent);\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\tconst result = await sandboxSimulate(userBundle, opponentBundle, {\r\n\t\tseed: options.seed ?? 1,\r\n\t\tspawnDistance: distance,\r\n\t\tmaxTicks: options.maxTicks ?? 3000,\r\n\t\tcompileOptions: getCoreCompileOptions(),\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 {BotEntry} 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: BotEntry): 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","/**\r\n * vibemancer upload\r\n *\r\n * Compiles the user's bot into a standalone bundle and uploads it\r\n * to the VibeMancer server via Firebase Cloud Functions.\r\n *\r\n * The bundle contains only the bot code (+ any npm deps used).\r\n * The server validates it by running a test fight against TargetDummy.\r\n * Deduplication: if the same code was uploaded before, the old wizard\r\n * is reactivated (preserving its rating and match history).\r\n */\r\n\r\nimport {createHash} from 'node:crypto';\r\nimport fs from 'node:fs';\r\nimport {discoverBot} from '../bot-discovery.js';\r\nimport {compileSingleBotBundle} from '../compile-single-bot.js';\r\n\r\nexport interface UploadOptions\r\n{\r\n\tbot?: string;\r\n}\r\n\r\nexport async function runUpload(options: UploadOptions): 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 Compiling ${botInfo.exportName}...`);\r\n\r\n\tconst bundle = await compileSingleBotBundle(botInfo.sourcePath, botInfo.exportName);\r\n\tconst sizeKb = (bundle.length / 1024).toFixed(1);\r\n\tconsole.log(` Bundle: ${sizeKb} KB`);\r\n\r\n\tif (bundle.length > 500 * 1024)\r\n\t{\r\n\t\tconsole.error(` Error: Bundle too large (${sizeKb} KB). Max 500 KB.`);\r\n\t\tprocess.exit(1);\r\n\t}\r\n\r\n\t// Extract wizard name from source (looks for: export const name = \"...\")\r\n\tconst nameMatch = bundle.match(/export\\s+(?:const|var|let)\\s+name\\s*=\\s*[\"']([^\"']+)[\"']/);\r\n\tconst wizardName = nameMatch?.[1] ?? botInfo.exportName;\r\n\r\n\t// Compute SHA256 hash for deduplication\r\n\tconst bundleHash = createHash('sha256').update(bundle).digest('hex');\r\n\r\n\tconsole.log(` Wizard: ${wizardName}`);\r\n\tconsole.log(` Hash: ${bundleHash.slice(0, 12)}...`);\r\n\tconsole.log(' Uploading to VibeMancer...');\r\n\r\n\t// Call the uploadWizard Cloud Function\r\n\ttry\r\n\t{\r\n\t\tconst {initializeApp} = await import('firebase/app');\r\n\t\tconst {getFunctions, httpsCallable} = await import('firebase/functions');\r\n\r\n\t\tconst app = initializeApp({\r\n\t\t\tapiKey: 'AIzaSyDSUJ2jlk5_vlpGOypMtvqKjHhDmbgomIY',\r\n\t\t\tauthDomain: 'le-vibemancer.firebaseapp.com',\r\n\t\t\tprojectId: 'le-vibemancer',\r\n\t\t});\r\n\r\n\t\tinterface UploadRequest\r\n\t\t{\r\n\t\t\tbundle: string;\r\n\t\t\tname: string;\r\n\t\t\texportName: string;\r\n\t\t\tsourceCode?: string;\r\n\t\t}\r\n\t\tinterface UploadResponse\r\n\t\t{\r\n\t\t\twizardId: string;\r\n\t\t\tactive: boolean;\r\n\t\t\treactivated: boolean;\r\n\t\t\terror: string | null;\r\n\t\t\tmessage: string;\r\n\t\t}\r\n\r\n\t\tconst functions = getFunctions(app, 'us-central1');\r\n\t\tconst uploadFn = httpsCallable<UploadRequest, UploadResponse>(functions, 'uploadWizard');\r\n\r\n\t\t// Read the original TypeScript source so it can be stored server-side\r\n\t\t// for later retrieval (e.g. via MCP chat session resumption).\r\n\t\tlet sourceCode: string | undefined;\r\n\t\ttry\r\n\t\t{\r\n\t\t\tsourceCode = fs.readFileSync(botInfo.sourcePath, 'utf-8');\r\n\t\t}\r\n\t\tcatch\r\n\t\t{\r\n\t\t\t// Non-fatal — source storage is optional\r\n\t\t}\r\n\r\n\t\tconst result = await uploadFn({\r\n\t\t\tbundle,\r\n\t\t\tname: wizardName,\r\n\t\t\texportName: botInfo.exportName,\r\n\t\t\tsourceCode,\r\n\t\t});\r\n\r\n\t\tconst data = result.data;\r\n\r\n\t\tif (data.active)\r\n\t\t{\r\n\t\t\tif (data.reactivated)\r\n\t\t\t{\r\n\t\t\t\tconsole.log(` ↺ ${data.message}`);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tconsole.log(` ✓ ${data.message}`);\r\n\t\t\t}\r\n\t\t\tconsole.log(` Wizard ID: ${data.wizardId}`);\r\n\t\t\tconsole.log(` Your wizard \"${wizardName}\" is now competing.\\n`);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tconsole.error(` ✗ ${data.message}`);\r\n\t\t\tconsole.error(' Fix the error and try again.\\n');\r\n\t\t\tprocess.exit(1);\r\n\t\t}\r\n\t}\r\n\tcatch(err: unknown)\r\n\t{\r\n\t\tconst message = err instanceof Error ? err.message : String(err);\r\n\t\tconsole.error(` ✗ Upload failed: ${message}\\n`);\r\n\t\tprocess.exit(1);\r\n\t}\r\n}\r\n","/**\n * vibemancer pull\n *\n * Downloads the latest source code of your active wizard from the\n * server and writes it to the local bot file. Enables round-tripping\n * between MCP chat sessions and local CLI development.\n *\n * Flow:\n * 1. Sign in (Google, interactive)\n * 2. Query wizards by ownerId + name (from vibemancer.json)\n * 3. Read wizard-sources/{wizardId}.sourceCode\n * 4. Write to src/bot.ts (or the configured bot path)\n */\n\nimport fs from 'node:fs';\nimport {discoverBot} from '../bot-discovery.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 {initializeApp} = await import('firebase/app');\n\t\tconst {getAuth, signInWithPopup, GoogleAuthProvider} = await import('firebase/auth');\n\t\tconst {getFirestore, collection, query, where, getDocs, doc, getDoc, limit: fbLimit} = await import('firebase/firestore');\n\n\t\tconst app = initializeApp({\n\t\t\tapiKey: 'AIzaSyDSUJ2jlk5_vlpGOypMtvqKjHhDmbgomIY',\n\t\t\tauthDomain: 'le-vibemancer.firebaseapp.com',\n\t\t\tprojectId: 'le-vibemancer',\n\t\t});\n\n\t\tconst auth = getAuth(app);\n\t\tconsole.log(' Signing in...');\n\t\tconst cred = await signInWithPopup(auth, new GoogleAuthProvider());\n\t\tconst userId = cred.user.uid;\n\t\tconsole.log(` Signed in as ${cred.user.displayName ?? cred.user.email ?? userId}`);\n\n\t\tconst db = getFirestore(app);\n\n\t\t// Find the active wizard with this name owned by this user\n\t\tconst wizardQuery = query(\n\t\t\tcollection(db, 'wizards'),\n\t\t\twhere('ownerId', '==', userId),\n\t\t\twhere('name', '==', botInfo.exportName),\n\t\t\twhere('active', '==', true),\n\t\t\tfbLimit(1),\n\t\t);\n\t\tconst wizardSnap = await getDocs(wizardQuery);\n\n\t\tif (wizardSnap.empty)\n\t\t{\n\t\t\tconsole.error(` No active wizard named \"${botInfo.exportName}\" found on your account.`);\n\t\t\tconsole.error(' Upload first with: vibemancer upload');\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconst wizardId = wizardSnap.docs[0]!.id;\n\n\t\t// Read the source code\n\t\tconst sourceDoc = await getDoc(doc(db, 'wizard-sources', wizardId));\n\n\t\tif (!sourceDoc.exists())\n\t\t{\n\t\t\tconsole.error(' No source code stored for this wizard.');\n\t\t\tconsole.error(' Re-upload with the latest CLI to store source: vibemancer upload');\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconst data = sourceDoc.data();\n\t\tconst sourceCode = data?.sourceCode;\n\n\t\tif (typeof sourceCode !== 'string' || sourceCode.length === 0)\n\t\t{\n\t\t\tconsole.error(' Source code is empty. Re-upload to store it.');\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Write to the local bot file\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 Error && err.message.includes('popup'))\n\t\t{\n\t\t\tconsole.error(' Sign-in popup was blocked or closed. Try again.');\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconsole.error(' Pull failed:', err instanceof Error ? err.message : err);\n\t\t}\n\t\tprocess.exit(1);\n\t}\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\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 upload Upload bot to VibeMancer for online competition\r\n pull Download latest source code from VibeMancer\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 instead of all bots\r\n --seed <n> Random seed\r\n\r\nTrace options:\r\n --opponent <name> Opponent bot name (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`);\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\tconsole.error('Error: --opponent is required for trace command.');\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\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":["path","fs","fs","path","BotBundle","BotBundle","path","fs","BotBundle","BotBundle","BotBundle","sandboxFight","scoreFight","BotBundle","sandboxFight","scoreFight","BotBundle","scoreFight","scoreFight","BotBundle","fs","path","BotBundle","BotBundle","path","fs","fs","fs","fs","fs"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibemancer",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
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.2",
31
+ "@vibemancer/core": "~0.1.4",
32
32
  "firebase": "^11.0.0"
33
33
  },
34
34
  "devDependencies": {