-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsession-runner.js
More file actions
95 lines (79 loc) · 2.55 KB
/
Copy pathsession-runner.js
File metadata and controls
95 lines (79 loc) · 2.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
const path = require('path');
function createSessionRunner({ spawn, sessionsDir, timeoutMs } = {}) {
const spawnFn = spawn || require('child_process').spawn;
const defaultDir = sessionsDir || process.env.SESSIONS_DIR || path.join(__dirname, '..', 'opencode-sessions');
const defaultTimeout = timeoutMs || 30000;
function createSession({ prompt, directory, title }) {
return new Promise((resolve, reject) => {
if (!prompt || !prompt.trim()) {
reject(new Error('Prompt is required'));
return;
}
const args = [
'run', prompt.trim(),
'--format', 'json',
'--dangerously-skip-permissions'
];
const cwd = directory || process.env.HOME || defaultDir;
if (directory) {
args.push('--dir', directory);
}
const child = spawnFn('opencode', args, { cwd });
let sessionId = null;
let buffer = '';
let resolved = false;
let timeout;
function doResolve(value) {
if (!resolved) {
resolved = true;
if (timeout) clearTimeout(timeout);
resolve(value);
}
}
function doReject(reason) {
if (!resolved) {
resolved = true;
if (timeout) clearTimeout(timeout);
reject(reason);
}
}
child.stdout.on('data', (data) => {
buffer += data.toString();
const lines = buffer.split('\n');
buffer = lines.pop(); // Keep incomplete line in buffer
for (const line of lines) {
if (!line.trim()) continue;
try {
const event = JSON.parse(line);
if (event.type === 'step_start' && !sessionId) {
sessionId = event.session_id || event.sessionId;
}
if (sessionId) {
doResolve({ sessionId, processing: true });
child.stdout.removeAllListeners('data');
return;
}
} catch (e) {
// Ignore non-JSON lines
}
}
});
child.on('error', (err) => {
doReject(err);
});
child.on('close', (code) => {
if (sessionId) {
doResolve({ sessionId, processing: true });
} else {
doReject(new Error(`Process exited with code ${code} without producing a session ID`));
}
});
timeout = setTimeout(() => {
child.kill();
doReject(new Error('Timeout waiting for session ID from opencode run'));
}, defaultTimeout);
});
}
return { createSession };
}
module.exports = { createSessionRunner };