promptarena 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/commands/auth.d.ts +3 -0
  2. package/dist/commands/auth.d.ts.map +1 -0
  3. package/dist/commands/auth.js +64 -0
  4. package/dist/commands/auth.js.map +1 -0
  5. package/dist/commands/battles.d.ts +3 -0
  6. package/dist/commands/battles.d.ts.map +1 -0
  7. package/dist/commands/battles.js +37 -0
  8. package/dist/commands/battles.js.map +1 -0
  9. package/dist/commands/join.d.ts +3 -0
  10. package/dist/commands/join.d.ts.map +1 -0
  11. package/dist/commands/join.js +51 -0
  12. package/dist/commands/join.js.map +1 -0
  13. package/dist/commands/start.d.ts +3 -0
  14. package/dist/commands/start.d.ts.map +1 -0
  15. package/dist/commands/start.js +40 -0
  16. package/dist/commands/start.js.map +1 -0
  17. package/dist/commands/stop.d.ts +3 -0
  18. package/dist/commands/stop.d.ts.map +1 -0
  19. package/dist/commands/stop.js +89 -0
  20. package/dist/commands/stop.js.map +1 -0
  21. package/dist/commands/submit.d.ts +3 -0
  22. package/dist/commands/submit.d.ts.map +1 -0
  23. package/dist/commands/submit.js +76 -0
  24. package/dist/commands/submit.js.map +1 -0
  25. package/dist/index.d.ts +3 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +23 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/lib/api.d.ts +3 -0
  30. package/dist/lib/api.d.ts.map +1 -0
  31. package/dist/lib/api.js +38 -0
  32. package/dist/lib/api.js.map +1 -0
  33. package/dist/lib/config.d.ts +11 -0
  34. package/dist/lib/config.d.ts.map +1 -0
  35. package/dist/lib/config.js +40 -0
  36. package/dist/lib/config.js.map +1 -0
  37. package/dist/lib/git.d.ts +11 -0
  38. package/dist/lib/git.d.ts.map +1 -0
  39. package/dist/lib/git.js +82 -0
  40. package/dist/lib/git.js.map +1 -0
  41. package/dist/lib/recorder.d.ts +12 -0
  42. package/dist/lib/recorder.d.ts.map +1 -0
  43. package/dist/lib/recorder.js +104 -0
  44. package/dist/lib/recorder.js.map +1 -0
  45. package/dist/lib/session.d.ts +12 -0
  46. package/dist/lib/session.d.ts.map +1 -0
  47. package/dist/lib/session.js +44 -0
  48. package/dist/lib/session.js.map +1 -0
  49. package/package.json +31 -0
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const authCommand: Command;
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,WAAW,SAqEpB,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { Command } from 'commander';
2
+ import { createServer } from 'node:http';
3
+ import { getConfig, saveConfig } from '../lib/config.js';
4
+ export const authCommand = new Command('auth')
5
+ .description('Authenticate via GitHub OAuth (opens browser)')
6
+ .action(async () => {
7
+ const config = getConfig();
8
+ console.log('\n ⚡ Prompt Arena Authentication\n');
9
+ // Start a local server to receive the auth callback
10
+ const port = 9876;
11
+ const server = createServer((req, res) => {
12
+ const url = new URL(req.url, `http://localhost:${port}`);
13
+ const token = url.searchParams.get('token');
14
+ const name = url.searchParams.get('name');
15
+ const userId = url.searchParams.get('userId');
16
+ if (token) {
17
+ saveConfig({ token, userId: userId ?? undefined, userName: name ?? undefined });
18
+ res.writeHead(200, { 'Content-Type': 'text/html' });
19
+ res.end(`
20
+ <html>
21
+ <body style="background:#0a0a0a;color:#00ff41;font-family:monospace;display:flex;align-items:center;justify-content:center;height:100vh;margin:0">
22
+ <div style="text-align:center">
23
+ <h1>> Authenticated!</h1>
24
+ <p>You can close this tab and return to your terminal.</p>
25
+ </div>
26
+ </body>
27
+ </html>
28
+ `);
29
+ console.log(` ✓ Authenticated as ${name ?? 'user'}`);
30
+ console.log(' Token saved to ~/.promptarena/config.json\n');
31
+ setTimeout(() => {
32
+ server.close();
33
+ process.exit(0);
34
+ }, 500);
35
+ }
36
+ else {
37
+ res.writeHead(400, { 'Content-Type': 'text/plain' });
38
+ res.end('Missing token');
39
+ }
40
+ });
41
+ server.listen(port, async () => {
42
+ // Go directly to the CLI callback — if user has a session it redirects to localhost immediately,
43
+ // if not it redirects to sign-in with the callback URL preserved.
44
+ const authUrl = `${config.apiUrl}/api/cli/callback?port=${port}`;
45
+ console.log(` Opening browser for authentication...`);
46
+ console.log(` If the browser doesn't open, visit:\n`);
47
+ console.log(` ${authUrl}\n`);
48
+ try {
49
+ const open = (await import('open')).default;
50
+ await open(authUrl);
51
+ }
52
+ catch {
53
+ // Browser open failed — user can manually visit the URL
54
+ }
55
+ console.log(' Waiting for authentication...\n');
56
+ });
57
+ // Timeout after 5 minutes
58
+ setTimeout(() => {
59
+ console.error(' ✗ Authentication timed out\n');
60
+ server.close();
61
+ process.exit(1);
62
+ }, 5 * 60 * 1000);
63
+ });
64
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const battlesCommand: Command;
3
+ //# sourceMappingURL=battles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"battles.d.ts","sourceRoot":"","sources":["../../src/commands/battles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,cAAc,SA0CvB,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { Command } from 'commander';
2
+ import { apiGet } from '../lib/api.js';
3
+ export const battlesCommand = new Command('battles')
4
+ .description('List active and upcoming battles')
5
+ .option('-s, --status <status>', 'Filter by status (active, upcoming, complete)')
6
+ .action(async (opts) => {
7
+ console.log('\n ⚡ Prompt Arena — Active Battles\n');
8
+ try {
9
+ const status = opts.status ?? 'active';
10
+ const battles = await apiGet(`/api/battles?status=${status}`);
11
+ if (battles.length === 0) {
12
+ console.log(` No ${status} battles found.\n`);
13
+ return;
14
+ }
15
+ const difficultyColors = {
16
+ easy: '\x1b[32m',
17
+ medium: '\x1b[33m',
18
+ hard: '\x1b[31m',
19
+ legendary: '\x1b[35m',
20
+ };
21
+ const reset = '\x1b[0m';
22
+ for (const battle of battles) {
23
+ const color = difficultyColors[battle.difficulty] ?? '';
24
+ console.log(` ${color}[${battle.difficulty}]${reset} ${battle.title}`);
25
+ console.log(` slug: ${battle.slug}`);
26
+ console.log(` time: ${battle.timeLimitMinutes}m`);
27
+ if (battle.description) {
28
+ console.log(` desc: ${battle.description.slice(0, 80)}${battle.description.length > 80 ? '...' : ''}`);
29
+ }
30
+ console.log();
31
+ }
32
+ }
33
+ catch (error) {
34
+ console.error(` ✗ Failed to fetch battles: ${error instanceof Error ? error.message : error}\n`);
35
+ }
36
+ });
37
+ //# sourceMappingURL=battles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"battles.js","sourceRoot":"","sources":["../../src/commands/battles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAGvC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,kCAAkC,CAAC;KAC/C,MAAM,CAAC,uBAAuB,EAAE,+CAA+C,CAAC;KAChF,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IAErD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAC;QACvC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAW,uBAAuB,MAAM,EAAE,CAAC,CAAC;QAExE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,QAAQ,MAAM,mBAAmB,CAAC,CAAC;YAC/C,OAAO;QACT,CAAC;QAED,MAAM,gBAAgB,GAA2B;YAC/C,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,UAAU;YAClB,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,UAAU;SACtB,CAAC;QACF,MAAM,KAAK,GAAG,SAAS,CAAC;QAExB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;YACxD,OAAO,CAAC,GAAG,CACT,KAAK,KAAK,IAAI,MAAM,CAAC,UAAU,IAAI,KAAK,IAAI,MAAM,CAAC,KAAK,EAAE,CAC3D,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,gBAAgB,GAAG,CAAC,CAAC;YACrD,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;gBACvB,OAAO,CAAC,GAAG,CACT,aAAa,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7F,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,gCAAgC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CACnF,CAAC;IACJ,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const joinCommand: Command;
3
+ //# sourceMappingURL=join.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join.d.ts","sourceRoot":"","sources":["../../src/commands/join.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,eAAO,MAAM,WAAW,SAuDpB,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { Command } from 'commander';
2
+ import { writeFileSync } from 'node:fs';
3
+ import { apiGet } from '../lib/api.js';
4
+ import { requireAuth } from '../lib/config.js';
5
+ import { initSession } from '../lib/session.js';
6
+ import { initGitRepo } from '../lib/git.js';
7
+ export const joinCommand = new Command('join')
8
+ .description('Join a battle and set up starter repo')
9
+ .argument('<battle-slug>', 'Battle slug or ID')
10
+ .option('-t, --tool <tool>', 'Declare your AI tool (claude-code, codex, cursor, etc.)')
11
+ .option('-c, --capture <method>', 'Capture method (terminal_recording, chat_export, screen_recording, none)', 'terminal_recording')
12
+ .option('-l, --league <league>', 'League (human, hybrid, agent)', 'human')
13
+ .action(async (battleSlug, opts) => {
14
+ const config = requireAuth();
15
+ console.log(`\n ⚡ Joining battle: ${battleSlug}\n`);
16
+ try {
17
+ const battle = await apiGet(`/api/battles/${battleSlug}`);
18
+ console.log(` Battle: ${battle.title}`);
19
+ console.log(` Difficulty: ${battle.difficulty}`);
20
+ console.log(` Time limit: ${battle.timeLimitMinutes} minutes\n`);
21
+ // Initialize git repo
22
+ initGitRepo();
23
+ console.log(' ✓ Git repository initialized');
24
+ // Write PRD file
25
+ writeFileSync('PRD.md', battle.prdMarkdown);
26
+ console.log(' ✓ PRD.md written');
27
+ // Initialize session
28
+ initSession({
29
+ battleId: battle.id,
30
+ startTime: new Date().toISOString(),
31
+ toolDeclared: opts.tool,
32
+ participantId: config.userId,
33
+ captureMethod: opts.capture,
34
+ league: opts.league,
35
+ });
36
+ console.log(' ✓ Session initialized in .promptarena/');
37
+ // Create .gitignore for the project
38
+ writeFileSync('.gitignore', 'node_modules/\n.env\n.env.local\n.promptarena/\n');
39
+ console.log('\n Ready to battle! Next steps:');
40
+ console.log(' 1. Read PRD.md for requirements');
41
+ console.log(' 2. Run: promptarena start');
42
+ console.log(' 3. Build with your AI tool of choice');
43
+ console.log(' 4. Run: promptarena stop');
44
+ console.log(' 5. Run: promptarena submit\n');
45
+ }
46
+ catch (error) {
47
+ console.error(` ✗ Failed to join battle: ${error instanceof Error ? error.message : error}\n`);
48
+ process.exit(1);
49
+ }
50
+ });
51
+ //# sourceMappingURL=join.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join.js","sourceRoot":"","sources":["../../src/commands/join.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAa,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,uCAAuC,CAAC;KACpD,QAAQ,CAAC,eAAe,EAAE,mBAAmB,CAAC;KAC9C,MAAM,CAAC,mBAAmB,EAAE,yDAAyD,CAAC;KACtF,MAAM,CAAC,wBAAwB,EAAE,0EAA0E,EAAE,oBAAoB,CAAC;KAClI,MAAM,CAAC,uBAAuB,EAAE,+BAA+B,EAAE,OAAO,CAAC;KACzE,MAAM,CAAC,KAAK,EAAE,UAAkB,EAAE,IAAI,EAAE,EAAE;IACzC,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAE7B,OAAO,CAAC,GAAG,CAAC,yBAAyB,UAAU,IAAI,CAAC,CAAC;IAErD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAS,gBAAgB,UAAU,EAAE,CAAC,CAAC;QAElE,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,gBAAgB,YAAY,CAAC,CAAC;QAElE,sBAAsB;QACtB,WAAW,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;QAE9C,iBAAiB;QACjB,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAElC,qBAAqB;QACrB,WAAW,CAAC;YACV,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,YAAY,EAAE,IAAI,CAAC,IAAI;YACvB,aAAa,EAAE,MAAM,CAAC,MAAO;YAC7B,aAAa,EAAE,IAAI,CAAC,OAAO;YAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;QAExD,oCAAoC;QACpC,aAAa,CACX,YAAY,EACZ,kDAAkD,CACnD,CAAC;QAEF,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,8BAA8B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CACjF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const startCommand: Command;
3
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,YAAY,SA2CrB,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { Command } from 'commander';
2
+ import { writeFileSync } from 'node:fs';
3
+ import { getSession, getSessionFile, hasSession } from '../lib/session.js';
4
+ import { Recorder } from '../lib/recorder.js';
5
+ export const startCommand = new Command('start')
6
+ .description('Start recording your battle session')
7
+ .action(async () => {
8
+ if (!hasSession()) {
9
+ console.error('\n ✗ No session found. Run: promptarena join <battle-id> first\n');
10
+ process.exit(1);
11
+ }
12
+ const session = getSession();
13
+ console.log('\n ⚡ Recording started!\n');
14
+ console.log(` Battle: ${session.battleId}`);
15
+ console.log(` Time: ${new Date().toLocaleTimeString()}`);
16
+ console.log(' Recording terminal session in .promptarena/recording.cast');
17
+ console.log('\n Use your AI tool of choice to build the project.');
18
+ console.log(' When done, run: promptarena stop\n');
19
+ // Update session start time
20
+ session.startTime = new Date().toISOString();
21
+ writeFileSync(getSessionFile(), JSON.stringify(session, null, 2));
22
+ // Start recording
23
+ const recorder = new Recorder();
24
+ try {
25
+ await recorder.start();
26
+ }
27
+ catch (error) {
28
+ // If PTY fails, just note it and continue
29
+ console.log(' Note: Terminal recording running in fallback mode.\n');
30
+ }
31
+ // Handle clean exit
32
+ const cleanup = () => {
33
+ console.log('\n Session recording stopped.\n');
34
+ recorder.stop();
35
+ process.exit(0);
36
+ };
37
+ process.on('SIGINT', cleanup);
38
+ process.on('SIGTERM', cleanup);
39
+ });
40
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,qCAAqC,CAAC;KAClD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CACX,mEAAmE,CACpE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;IACpE,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;IAEpD,4BAA4B;IAC5B,OAAO,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC7C,aAAa,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAElE,kBAAkB;IAClB,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,0CAA0C;QAC1C,OAAO,CAAC,GAAG,CACT,wDAAwD,CACzD,CAAC;IACJ,CAAC;IAED,oBAAoB;IACpB,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QAChD,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AACjC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const stopCommand: Command;
3
+ //# sourceMappingURL=stop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,eAAO,MAAM,WAAW,SA+FpB,CAAC"}
@@ -0,0 +1,89 @@
1
+ import { Command } from 'commander';
2
+ import { createInterface } from 'node:readline/promises';
3
+ import { readFileSync, writeFileSync, existsSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { getSession, hasSession, saveSubmitMetadata, getSessionDir } from '../lib/session.js';
6
+ import { stageAll, commit, getCommitCount, getLineStats, } from '../lib/git.js';
7
+ export const stopCommand = new Command('stop')
8
+ .description('Stop recording and stage a git commit')
9
+ .action(async () => {
10
+ if (!hasSession()) {
11
+ console.error('\n ✗ No session found. Run: promptarena join <battle-id> first\n');
12
+ process.exit(1);
13
+ }
14
+ const session = getSession();
15
+ const endTime = new Date().toISOString();
16
+ const startTime = new Date(session.startTime);
17
+ const durationSeconds = Math.floor((Date.now() - startTime.getTime()) / 1000);
18
+ console.log('\n ⚡ Stopping session...\n');
19
+ // Stage and commit all changes
20
+ try {
21
+ stageAll();
22
+ commit(`promptarena: final submission for ${session.battleId}`);
23
+ console.log(' ✓ Changes committed');
24
+ }
25
+ catch (error) {
26
+ console.log(' Note: No changes to commit or git not initialized');
27
+ }
28
+ // Gather git stats
29
+ const commitCount = getCommitCount();
30
+ const lineStats = getLineStats();
31
+ // Save metadata
32
+ const metadata = {
33
+ battleId: session.battleId,
34
+ participantId: session.participantId,
35
+ startTime: session.startTime,
36
+ endTime,
37
+ durationSeconds,
38
+ commitCount,
39
+ linesAdded: lineStats.added,
40
+ linesRemoved: lineStats.removed,
41
+ toolDeclared: session.toolDeclared,
42
+ captureMethod: session.captureMethod,
43
+ league: session.league,
44
+ };
45
+ saveSubmitMetadata(metadata);
46
+ // If agent or hybrid league, prompt for agent config
47
+ if (session.league === 'agent' || session.league === 'hybrid') {
48
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
49
+ console.log('\n Agent configuration:\n');
50
+ const agentName = await rl.question(' Agent name (required): ');
51
+ if (!agentName.trim()) {
52
+ console.error(' ✗ Agent name is required for agent/hybrid leagues.\n');
53
+ rl.close();
54
+ process.exit(1);
55
+ }
56
+ const agentVersion = await rl.question(' Agent version (optional): ');
57
+ const model = await rl.question(' Model used (optional): ');
58
+ const promptInput = await rl.question(' System prompt or config file path (optional): ');
59
+ const invocationCommand = await rl.question(' Invocation command (optional): ');
60
+ rl.close();
61
+ let systemPrompt = null;
62
+ if (promptInput.trim()) {
63
+ // If it looks like a file path and the file exists, read it
64
+ if (existsSync(promptInput.trim())) {
65
+ systemPrompt = readFileSync(promptInput.trim(), 'utf-8');
66
+ }
67
+ else {
68
+ systemPrompt = promptInput.trim();
69
+ }
70
+ }
71
+ const agentConfig = {
72
+ agentName: agentName.trim(),
73
+ agentVersion: agentVersion.trim() || null,
74
+ model: model.trim() || null,
75
+ systemPrompt,
76
+ invocationCommand: invocationCommand.trim() || null,
77
+ autonomous: session.league === 'agent',
78
+ };
79
+ const agentConfigPath = join(getSessionDir(), 'agent-config.json');
80
+ writeFileSync(agentConfigPath, JSON.stringify(agentConfig, null, 2));
81
+ console.log(' ✓ Agent config saved');
82
+ }
83
+ console.log(`\n Duration: ${Math.floor(durationSeconds / 60)}m ${durationSeconds % 60}s`);
84
+ console.log(` Commits: ${commitCount}`);
85
+ console.log(` Lines: +${lineStats.added} -${lineStats.removed}`);
86
+ console.log('\n ✓ Session stopped. Metadata saved.');
87
+ console.log(' Next: promptarena submit\n');
88
+ });
89
+ //# sourceMappingURL=stop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const submitCommand: Command;
3
+ //# sourceMappingURL=submit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"submit.d.ts","sourceRoot":"","sources":["../../src/commands/submit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,eAAO,MAAM,aAAa,SA4FtB,CAAC"}
@@ -0,0 +1,76 @@
1
+ import { Command } from 'commander';
2
+ import { readFileSync, existsSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { requireAuth } from '../lib/config.js';
5
+ import { getSession, hasSession, getSubmitMetadata, getRecordingFile, getSessionDir, } from '../lib/session.js';
6
+ import { createGitBundle, isGitRepo } from '../lib/git.js';
7
+ import { apiPostMultipart } from '../lib/api.js';
8
+ export const submitCommand = new Command('submit')
9
+ .description('Submit your battle entry (uploads recording + git bundle)')
10
+ .action(async () => {
11
+ const config = requireAuth();
12
+ if (!hasSession()) {
13
+ console.error('\n ✗ No session found. Run: promptarena join <battle-id> first\n');
14
+ process.exit(1);
15
+ }
16
+ console.log('\n ⚡ Submitting battle entry...\n');
17
+ const session = getSession();
18
+ let metadata;
19
+ try {
20
+ metadata = getSubmitMetadata();
21
+ }
22
+ catch {
23
+ console.error(' ✗ No submission metadata. Run: promptarena stop first\n');
24
+ process.exit(1);
25
+ }
26
+ // Create git bundle
27
+ const bundlePath = join(process.cwd(), '.promptarena', 'repo.bundle');
28
+ if (isGitRepo()) {
29
+ try {
30
+ createGitBundle(bundlePath);
31
+ console.log(' ✓ Git bundle created');
32
+ }
33
+ catch (error) {
34
+ console.log(' Note: Could not create git bundle (no commits?)');
35
+ }
36
+ }
37
+ // Prepare upload
38
+ const formData = new FormData();
39
+ formData.append('battleId', session.battleId);
40
+ formData.append('metadata', JSON.stringify(metadata));
41
+ formData.append('captureMethod', metadata.captureMethod ?? 'terminal_recording');
42
+ formData.append('league', metadata.league ?? 'human');
43
+ // Attach agent config if exists
44
+ const agentConfigPath = join(getSessionDir(), 'agent-config.json');
45
+ if (existsSync(agentConfigPath)) {
46
+ formData.append('agentConfig', readFileSync(agentConfigPath, 'utf-8'));
47
+ console.log(' ✓ Agent config attached');
48
+ }
49
+ // Attach recording if exists
50
+ const recordingPath = getRecordingFile();
51
+ if (existsSync(recordingPath)) {
52
+ const recordingData = readFileSync(recordingPath);
53
+ formData.append('recording', new Blob([recordingData], { type: 'application/octet-stream' }), 'recording.cast');
54
+ console.log(' ✓ Recording attached');
55
+ }
56
+ // Attach git bundle if exists
57
+ if (existsSync(bundlePath)) {
58
+ const bundleData = readFileSync(bundlePath);
59
+ formData.append('gitBundle', new Blob([bundleData], { type: 'application/octet-stream' }), 'repo.bundle');
60
+ console.log(' ✓ Git bundle attached');
61
+ }
62
+ // Upload
63
+ try {
64
+ console.log('\n Uploading...');
65
+ const result = await apiPostMultipart('/api/submissions', formData);
66
+ console.log('\n ✓ Submission uploaded as draft!');
67
+ console.log(` Submission ID: ${result.submissionId}`);
68
+ console.log(`\n Review and publish at:`);
69
+ console.log(` ${config.apiUrl}${result.reviewUrl}\n`);
70
+ }
71
+ catch (error) {
72
+ console.error(`\n ✗ Upload failed: ${error instanceof Error ? error.message : error}\n`);
73
+ process.exit(1);
74
+ }
75
+ });
76
+ //# sourceMappingURL=submit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"submit.js","sourceRoot":"","sources":["../../src/commands/submit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from 'node:fs';
3
+ import { Command } from 'commander';
4
+ import { authCommand } from './commands/auth.js';
5
+ import { battlesCommand } from './commands/battles.js';
6
+ import { joinCommand } from './commands/join.js';
7
+ import { startCommand } from './commands/start.js';
8
+ import { stopCommand } from './commands/stop.js';
9
+ import { submitCommand } from './commands/submit.js';
10
+ const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
11
+ const program = new Command();
12
+ program
13
+ .name('promptarena')
14
+ .description('CLI for Prompt Arena — competitive AI-assisted coding')
15
+ .version(pkg.version);
16
+ program.addCommand(authCommand);
17
+ program.addCommand(battlesCommand);
18
+ program.addCommand(joinCommand);
19
+ program.addCommand(startCommand);
20
+ program.addCommand(stopCommand);
21
+ program.addCommand(submitCommand);
22
+ program.parse();
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CACnE,CAAC;AAEF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,uDAAuD,CAAC;KACpE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAExB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAElC,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function apiGet<T>(path: string): Promise<T>;
2
+ export declare function apiPostMultipart<T>(path: string, formData: FormData): Promise<T>;
3
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAEA,wBAAsB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAoBxD;AAED,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,CAAC,CAAC,CAsBZ"}
@@ -0,0 +1,38 @@
1
+ import { getConfig } from './config.js';
2
+ export async function apiGet(path) {
3
+ const config = getConfig();
4
+ const url = `${config.apiUrl}${path}`;
5
+ const headers = {
6
+ 'Content-Type': 'application/json',
7
+ };
8
+ if (config.token) {
9
+ headers['Authorization'] = `Bearer ${config.token}`;
10
+ }
11
+ const response = await fetch(url, { headers });
12
+ if (!response.ok) {
13
+ const body = await response.text();
14
+ throw new Error(`API error ${response.status}: ${body}`);
15
+ }
16
+ const json = await response.json();
17
+ return json.data ?? json;
18
+ }
19
+ export async function apiPostMultipart(path, formData) {
20
+ const config = getConfig();
21
+ const url = `${config.apiUrl}${path}`;
22
+ const headers = {};
23
+ if (config.token) {
24
+ headers['Authorization'] = `Bearer ${config.token}`;
25
+ }
26
+ const response = await fetch(url, {
27
+ method: 'POST',
28
+ headers,
29
+ body: formData,
30
+ });
31
+ if (!response.ok) {
32
+ const body = await response.text();
33
+ throw new Error(`API error ${response.status}: ${body}`);
34
+ }
35
+ const json = await response.json();
36
+ return json.data ?? json;
37
+ }
38
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,MAAM,CAAI,IAAY;IAC1C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;IAEtC,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;KACnC,CAAC;IACF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,CAAC,KAAK,EAAE,CAAC;IACtD,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAE/C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,aAAa,QAAQ,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAY,EACZ,QAAkB;IAElB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;IAEtC,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,CAAC,KAAK,EAAE,CAAC;IACtD,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO;QACP,IAAI,EAAE,QAAQ;KACf,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,aAAa,QAAQ,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface CliConfig {
2
+ apiUrl: string;
3
+ token?: string;
4
+ userId?: string;
5
+ userName?: string;
6
+ }
7
+ export declare function getConfig(): CliConfig;
8
+ export declare function saveConfig(config: Partial<CliConfig>): void;
9
+ export declare function isAuthenticated(): boolean;
10
+ export declare function requireAuth(): CliConfig;
11
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAMD,wBAAgB,SAAS,IAAI,SAAS,CAUrC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI,CAM3D;AAED,wBAAgB,eAAe,IAAI,OAAO,CAGzC;AAED,wBAAgB,WAAW,IAAI,SAAS,CAOvC"}
@@ -0,0 +1,40 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ const CONFIG_DIR = join(homedir(), '.promptarena');
5
+ const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
6
+ const DEFAULT_CONFIG = {
7
+ apiUrl: process.env.PROMPT_ARENA_API_URL ?? 'https://prompt-arena-sepia.vercel.app',
8
+ };
9
+ export function getConfig() {
10
+ try {
11
+ if (existsSync(CONFIG_FILE)) {
12
+ const data = readFileSync(CONFIG_FILE, 'utf-8');
13
+ return { ...DEFAULT_CONFIG, ...JSON.parse(data) };
14
+ }
15
+ }
16
+ catch {
17
+ // Ignore parse errors
18
+ }
19
+ return DEFAULT_CONFIG;
20
+ }
21
+ export function saveConfig(config) {
22
+ mkdirSync(CONFIG_DIR, { recursive: true });
23
+ const existing = getConfig();
24
+ const merged = { ...existing, ...config };
25
+ writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2));
26
+ chmodSync(CONFIG_FILE, 0o600);
27
+ }
28
+ export function isAuthenticated() {
29
+ const config = getConfig();
30
+ return !!config.token;
31
+ }
32
+ export function requireAuth() {
33
+ const config = getConfig();
34
+ if (!config.token) {
35
+ console.error('Not authenticated. Run: promptarena auth');
36
+ process.exit(1);
37
+ }
38
+ return config;
39
+ }
40
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AACnD,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AASpD,MAAM,cAAc,GAAc;IAChC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,uCAAuC;CACpF,CAAC;AAEF,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YAChD,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;IACxB,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAA0B;IACnD,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1C,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5D,SAAS,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare function isGitRepo(): boolean;
2
+ export declare function initGitRepo(): void;
3
+ export declare function getCommitCount(): number;
4
+ export declare function getLineStats(): {
5
+ added: number;
6
+ removed: number;
7
+ };
8
+ export declare function createGitBundle(outputPath: string): void;
9
+ export declare function stageAll(): void;
10
+ export declare function commit(message: string): void;
11
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/lib/git.ts"],"names":[],"mappings":"AAIA,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED,wBAAgB,WAAW,IAAI,IAAI,CAIlC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAWvC;AAED,wBAAgB,YAAY,IAAI;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAgDjE;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAKxD;AAED,wBAAgB,QAAQ,IAAI,IAAI,CAE/B;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAK5C"}
@@ -0,0 +1,82 @@
1
+ import { execSync, execFileSync } from 'node:child_process';
2
+ import { existsSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ export function isGitRepo() {
5
+ return existsSync(join(process.cwd(), '.git'));
6
+ }
7
+ export function initGitRepo() {
8
+ if (!isGitRepo()) {
9
+ execSync('git init', { cwd: process.cwd(), stdio: 'pipe' });
10
+ }
11
+ }
12
+ export function getCommitCount() {
13
+ try {
14
+ const output = execSync('git rev-list --count HEAD', {
15
+ cwd: process.cwd(),
16
+ encoding: 'utf-8',
17
+ stdio: ['pipe', 'pipe', 'pipe'],
18
+ });
19
+ return parseInt(output.trim(), 10) || 0;
20
+ }
21
+ catch {
22
+ return 0;
23
+ }
24
+ }
25
+ export function getLineStats() {
26
+ try {
27
+ const output = execSync('git diff --stat HEAD~1 HEAD --numstat', {
28
+ cwd: process.cwd(),
29
+ encoding: 'utf-8',
30
+ stdio: ['pipe', 'pipe', 'pipe'],
31
+ });
32
+ let added = 0;
33
+ let removed = 0;
34
+ for (const line of output.trim().split('\n')) {
35
+ const parts = line.split('\t');
36
+ if (parts.length >= 2) {
37
+ added += parseInt(parts[0], 10) || 0;
38
+ removed += parseInt(parts[1], 10) || 0;
39
+ }
40
+ }
41
+ return { added, removed };
42
+ }
43
+ catch {
44
+ // Try diffing against empty tree (for initial commit)
45
+ try {
46
+ const output = execSync('git diff --numstat 4b825dc642cb6eb9a060e54bf899d8e4 HEAD', {
47
+ cwd: process.cwd(),
48
+ encoding: 'utf-8',
49
+ stdio: ['pipe', 'pipe', 'pipe'],
50
+ });
51
+ let added = 0;
52
+ let removed = 0;
53
+ for (const line of output.trim().split('\n')) {
54
+ const parts = line.split('\t');
55
+ if (parts.length >= 2) {
56
+ added += parseInt(parts[0], 10) || 0;
57
+ removed += parseInt(parts[1], 10) || 0;
58
+ }
59
+ }
60
+ return { added, removed };
61
+ }
62
+ catch {
63
+ return { added: 0, removed: 0 };
64
+ }
65
+ }
66
+ }
67
+ export function createGitBundle(outputPath) {
68
+ execFileSync('git', ['bundle', 'create', outputPath, '--all'], {
69
+ cwd: process.cwd(),
70
+ stdio: 'pipe',
71
+ });
72
+ }
73
+ export function stageAll() {
74
+ execSync('git add -A', { cwd: process.cwd(), stdio: 'pipe' });
75
+ }
76
+ export function commit(message) {
77
+ execFileSync('git', ['commit', '-m', message, '--allow-empty'], {
78
+ cwd: process.cwd(),
79
+ stdio: 'pipe',
80
+ });
81
+ }
82
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/lib/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export declare class Recorder {
2
+ private startTime;
3
+ private file;
4
+ private pty;
5
+ constructor();
6
+ start(): Promise<void>;
7
+ private startFallbackRecording;
8
+ stop(): void;
9
+ private cleanup;
10
+ getElapsedSeconds(): number;
11
+ }
12
+ //# sourceMappingURL=recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/lib/recorder.ts"],"names":[],"mappings":"AAqBA,qBAAa,QAAQ;IACnB,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,GAAG,CAA4D;;IAMjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqF5B,OAAO,CAAC,sBAAsB;IAW9B,IAAI,IAAI,IAAI;IAOZ,OAAO,CAAC,OAAO;IAKf,iBAAiB,IAAI,MAAM;CAG5B"}
@@ -0,0 +1,104 @@
1
+ import { writeFileSync, appendFileSync } from 'node:fs';
2
+ import { getRecordingFile } from './session.js';
3
+ export class Recorder {
4
+ startTime = 0;
5
+ file;
6
+ pty = null;
7
+ constructor() {
8
+ this.file = getRecordingFile();
9
+ }
10
+ async start() {
11
+ this.startTime = Date.now();
12
+ const cols = process.stdout.columns || 80;
13
+ const rows = process.stdout.rows || 24;
14
+ // Write cast header
15
+ const header = {
16
+ version: 2,
17
+ width: cols,
18
+ height: rows,
19
+ timestamp: Math.floor(this.startTime / 1000),
20
+ env: {
21
+ SHELL: process.env.SHELL || '/bin/bash',
22
+ TERM: process.env.TERM || 'xterm-256color',
23
+ },
24
+ };
25
+ writeFileSync(this.file, JSON.stringify(header) + '\n');
26
+ // Spawn PTY
27
+ let ptyModule;
28
+ try {
29
+ ptyModule = await import('node-pty');
30
+ }
31
+ catch {
32
+ console.error('Warning: node-pty not available. Recording will capture stdin/stdout only.');
33
+ this.startFallbackRecording();
34
+ return;
35
+ }
36
+ const shell = process.env.SHELL || '/bin/bash';
37
+ // Filter out secret env vars to prevent leakage into .cast recordings
38
+ const SECRET_PATTERNS = [
39
+ /_SECRET$/,
40
+ /_TOKEN$/,
41
+ /_KEY$/,
42
+ /_PASSWORD$/,
43
+ /^AUTH_/,
44
+ /^POSTGRES_/,
45
+ ];
46
+ const filteredEnv = {};
47
+ for (const [key, value] of Object.entries(process.env)) {
48
+ if (value !== undefined && !SECRET_PATTERNS.some((p) => p.test(key))) {
49
+ filteredEnv[key] = value;
50
+ }
51
+ }
52
+ this.pty = ptyModule.spawn(shell, [], {
53
+ name: 'xterm-256color',
54
+ cols,
55
+ rows,
56
+ cwd: process.cwd(),
57
+ env: filteredEnv,
58
+ });
59
+ // Record output
60
+ this.pty.onData((data) => {
61
+ const elapsed = (Date.now() - this.startTime) / 1000;
62
+ const event = JSON.stringify([elapsed, 'o', data]);
63
+ appendFileSync(this.file, event + '\n');
64
+ process.stdout.write(data);
65
+ });
66
+ // Forward stdin to PTY
67
+ process.stdin.setRawMode?.(true);
68
+ process.stdin.resume();
69
+ process.stdin.on('data', (data) => {
70
+ this.pty?.write(data.toString());
71
+ });
72
+ // Handle resize
73
+ process.stdout.on('resize', () => {
74
+ this.pty?.resize(process.stdout.columns || 80, process.stdout.rows || 24);
75
+ });
76
+ this.pty.onExit(() => {
77
+ this.cleanup();
78
+ });
79
+ }
80
+ startFallbackRecording() {
81
+ // Fallback: just record a marker for environments without node-pty
82
+ const elapsed = 0;
83
+ const event = JSON.stringify([
84
+ elapsed,
85
+ 'o',
86
+ 'Recording started (fallback mode — node-pty not available)\r\n',
87
+ ]);
88
+ appendFileSync(this.file, event + '\n');
89
+ }
90
+ stop() {
91
+ if (this.pty) {
92
+ this.pty.kill();
93
+ }
94
+ this.cleanup();
95
+ }
96
+ cleanup() {
97
+ process.stdin.setRawMode?.(false);
98
+ process.stdin.pause();
99
+ }
100
+ getElapsedSeconds() {
101
+ return Math.floor((Date.now() - this.startTime) / 1000);
102
+ }
103
+ }
104
+ //# sourceMappingURL=recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../../src/lib/recorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { SessionMetadata, SubmitMetadata } from '@promptarena/shared';
2
+ export declare function getSessionDir(): string;
3
+ export declare function getSessionFile(): string;
4
+ export declare function getRecordingFile(): string;
5
+ export declare function getMetadataFile(): string;
6
+ export declare function hasSession(): boolean;
7
+ export declare function hasRecording(): boolean;
8
+ export declare function initSession(metadata: SessionMetadata): void;
9
+ export declare function getSession(): SessionMetadata;
10
+ export declare function saveSubmitMetadata(metadata: SubmitMetadata): void;
11
+ export declare function getSubmitMetadata(): SubmitMetadata;
12
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/lib/session.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAO3E,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAG3D;AAED,wBAAgB,UAAU,IAAI,eAAe,CAO5C;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAEjE;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAKlD"}
@@ -0,0 +1,44 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ const SESSION_DIR = '.promptarena';
4
+ const SESSION_FILE = join(SESSION_DIR, 'session.json');
5
+ const RECORDING_FILE = join(SESSION_DIR, 'recording.cast');
6
+ const METADATA_FILE = join(SESSION_DIR, 'metadata.json');
7
+ export function getSessionDir() {
8
+ return join(process.cwd(), SESSION_DIR);
9
+ }
10
+ export function getSessionFile() {
11
+ return join(process.cwd(), SESSION_FILE);
12
+ }
13
+ export function getRecordingFile() {
14
+ return join(process.cwd(), RECORDING_FILE);
15
+ }
16
+ export function getMetadataFile() {
17
+ return join(process.cwd(), METADATA_FILE);
18
+ }
19
+ export function hasSession() {
20
+ return existsSync(getSessionFile());
21
+ }
22
+ export function hasRecording() {
23
+ return existsSync(getRecordingFile());
24
+ }
25
+ export function initSession(metadata) {
26
+ mkdirSync(getSessionDir(), { recursive: true });
27
+ writeFileSync(getSessionFile(), JSON.stringify(metadata, null, 2));
28
+ }
29
+ export function getSession() {
30
+ if (!hasSession()) {
31
+ throw new Error('No active session. Run: promptarena join <battle-id> first');
32
+ }
33
+ return JSON.parse(readFileSync(getSessionFile(), 'utf-8'));
34
+ }
35
+ export function saveSubmitMetadata(metadata) {
36
+ writeFileSync(getMetadataFile(), JSON.stringify(metadata, null, 2));
37
+ }
38
+ export function getSubmitMetadata() {
39
+ if (!existsSync(getMetadataFile())) {
40
+ throw new Error('No submission metadata found. Run: promptarena stop first');
41
+ }
42
+ return JSON.parse(readFileSync(getMetadataFile(), 'utf-8'));
43
+ }
44
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/lib/session.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,SAAS,EACT,UAAU,GACX,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,MAAM,WAAW,GAAG,cAAc,CAAC;AACnC,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;AACvD,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;AAC3D,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;AAEzD,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAyB;IACnD,SAAS,CAAC,aAAa,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,aAAa,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAwB;IACzD,aAAa,CAAC,eAAe,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;AAC9D,CAAC"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "promptarena",
3
+ "version": "0.1.0",
4
+ "description": "CLI for Prompt Arena — competitive AI-assisted coding",
5
+ "type": "module",
6
+ "bin": {
7
+ "promptarena": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "tsc --watch",
12
+ "test": "vitest run",
13
+ "test:watch": "vitest"
14
+ },
15
+ "dependencies": {
16
+ "commander": "^12.1.0",
17
+ "open": "^10.1.0"
18
+ },
19
+ "optionalDependencies": {
20
+ "node-pty": "^1.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "@promptarena/shared": "*",
24
+ "@types/node": "^22.0.0",
25
+ "typescript": "^5.7.0",
26
+ "vitest": "^3.0.0"
27
+ },
28
+ "files": [
29
+ "dist"
30
+ ]
31
+ }