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.
- package/dist/commands/auth.d.ts +3 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +64 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/battles.d.ts +3 -0
- package/dist/commands/battles.d.ts.map +1 -0
- package/dist/commands/battles.js +37 -0
- package/dist/commands/battles.js.map +1 -0
- package/dist/commands/join.d.ts +3 -0
- package/dist/commands/join.d.ts.map +1 -0
- package/dist/commands/join.js +51 -0
- package/dist/commands/join.js.map +1 -0
- package/dist/commands/start.d.ts +3 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +40 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/stop.d.ts +3 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +89 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/commands/submit.d.ts +3 -0
- package/dist/commands/submit.d.ts.map +1 -0
- package/dist/commands/submit.js +76 -0
- package/dist/commands/submit.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api.d.ts +3 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/api.js +38 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/config.d.ts +11 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +40 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/git.d.ts +11 -0
- package/dist/lib/git.d.ts.map +1 -0
- package/dist/lib/git.js +82 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/recorder.d.ts +12 -0
- package/dist/lib/recorder.d.ts.map +1 -0
- package/dist/lib/recorder.js +104 -0
- package/dist/lib/recorder.js.map +1 -0
- package/dist/lib/session.d.ts +12 -0
- package/dist/lib/session.d.ts.map +1 -0
- package/dist/lib/session.js +44 -0
- package/dist/lib/session.js.map +1 -0
- package/package.json +31 -0
|
@@ -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":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEzD,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IAEnD,oDAAoD;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC;IAElB,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACvC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAI,EAAE,oBAAoB,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAE9C,IAAI,KAAK,EAAE,CAAC;YACV,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,SAAS,EAAE,QAAQ,EAAE,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC;YAEhF,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC;;;;;;;;;SASP,CAAC,CAAC;YAEH,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,IAAI,MAAM,EAAE,CAAC,CAAC;YACtD,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;YAE7D,UAAU,CAAC,GAAG,EAAE;gBACd,MAAM,CAAC,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC,EAAE,GAAG,CAAC,CAAC;QACV,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;YACrD,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;QAC7B,iGAAiG;QACjG,kEAAkE;QAClE,MAAM,OAAO,GAAG,GAAG,MAAM,CAAC,MAAM,0BAA0B,IAAI,EAAE,CAAC;QAEjE,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,IAAI,CAAC,CAAC;QAE9B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YAC5C,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,wDAAwD;QAC1D,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,0BAA0B;IAC1B,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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 @@
|
|
|
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"}
|
package/dist/lib/api.js
ADDED
|
@@ -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"}
|
package/dist/lib/git.js
ADDED
|
@@ -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
|
+
}
|