@matteeh/osq 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/LICENSE +21 -0
- package/README.md +183 -0
- package/dist/cli/approve.d.ts +6 -0
- package/dist/cli/approve.d.ts.map +1 -0
- package/dist/cli/approve.js +26 -0
- package/dist/cli/approve.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +5 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +76 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +4 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +19 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/new.d.ts +4 -0
- package/dist/cli/new.d.ts.map +1 -0
- package/dist/cli/new.js +15 -0
- package/dist/cli/new.js.map +1 -0
- package/dist/cli/report.d.ts +10 -0
- package/dist/cli/report.d.ts.map +1 -0
- package/dist/cli/report.js +84 -0
- package/dist/cli/report.js.map +1 -0
- package/dist/cli/setup.d.ts +2 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +10 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/show.d.ts +7 -0
- package/dist/cli/show.d.ts.map +1 -0
- package/dist/cli/show.js +27 -0
- package/dist/cli/show.js.map +1 -0
- package/dist/cli/status.d.ts +7 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +23 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/watch.d.ts +9 -0
- package/dist/cli/watch.d.ts.map +1 -0
- package/dist/cli/watch.js +20 -0
- package/dist/cli/watch.js.map +1 -0
- package/dist/core/approve.d.ts +11 -0
- package/dist/core/approve.d.ts.map +1 -0
- package/dist/core/approve.js +52 -0
- package/dist/core/approve.js.map +1 -0
- package/dist/core/config.d.ts +53 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +124 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/hasher.d.ts +4 -0
- package/dist/core/hasher.d.ts.map +1 -0
- package/dist/core/hasher.js +49 -0
- package/dist/core/hasher.js.map +1 -0
- package/dist/core/init.d.ts +12 -0
- package/dist/core/init.d.ts.map +1 -0
- package/dist/core/init.js +151 -0
- package/dist/core/init.js.map +1 -0
- package/dist/core/linter.d.ts +8 -0
- package/dist/core/linter.d.ts.map +1 -0
- package/dist/core/linter.js +100 -0
- package/dist/core/linter.js.map +1 -0
- package/dist/core/lock.d.ts +17 -0
- package/dist/core/lock.d.ts.map +1 -0
- package/dist/core/lock.js +104 -0
- package/dist/core/lock.js.map +1 -0
- package/dist/core/logger.d.ts +32 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +106 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/new.d.ts +11 -0
- package/dist/core/new.d.ts.map +1 -0
- package/dist/core/new.js +79 -0
- package/dist/core/new.js.map +1 -0
- package/dist/core/parser.d.ts +32 -0
- package/dist/core/parser.d.ts.map +1 -0
- package/dist/core/parser.js +87 -0
- package/dist/core/parser.js.map +1 -0
- package/dist/core/report.d.ts +54 -0
- package/dist/core/report.d.ts.map +1 -0
- package/dist/core/report.js +475 -0
- package/dist/core/report.js.map +1 -0
- package/dist/core/show.d.ts +50 -0
- package/dist/core/show.d.ts.map +1 -0
- package/dist/core/show.js +374 -0
- package/dist/core/show.js.map +1 -0
- package/dist/core/state.d.ts +25 -0
- package/dist/core/state.d.ts.map +1 -0
- package/dist/core/state.js +180 -0
- package/dist/core/state.js.map +1 -0
- package/dist/core/status.d.ts +10 -0
- package/dist/core/status.d.ts.map +1 -0
- package/dist/core/status.js +106 -0
- package/dist/core/status.js.map +1 -0
- package/dist/harness/agy.d.ts +31 -0
- package/dist/harness/agy.d.ts.map +1 -0
- package/dist/harness/agy.js +251 -0
- package/dist/harness/agy.js.map +1 -0
- package/dist/harness/index.d.ts +7 -0
- package/dist/harness/index.d.ts.map +1 -0
- package/dist/harness/index.js +20 -0
- package/dist/harness/index.js.map +1 -0
- package/dist/harness/mock.d.ts +19 -0
- package/dist/harness/mock.d.ts.map +1 -0
- package/dist/harness/mock.js +62 -0
- package/dist/harness/mock.js.map +1 -0
- package/dist/harness/opencode.d.ts +39 -0
- package/dist/harness/opencode.d.ts.map +1 -0
- package/dist/harness/opencode.js +394 -0
- package/dist/harness/opencode.js.map +1 -0
- package/dist/harness/process.d.ts +26 -0
- package/dist/harness/process.d.ts.map +1 -0
- package/dist/harness/process.js +99 -0
- package/dist/harness/process.js.map +1 -0
- package/dist/harness/stream.d.ts +34 -0
- package/dist/harness/stream.d.ts.map +1 -0
- package/dist/harness/stream.js +75 -0
- package/dist/harness/stream.js.map +1 -0
- package/dist/harness/types.d.ts +53 -0
- package/dist/harness/types.d.ts.map +1 -0
- package/dist/harness/types.js +10 -0
- package/dist/harness/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/watcher/archiver.d.ts +5 -0
- package/dist/watcher/archiver.d.ts.map +1 -0
- package/dist/watcher/archiver.js +66 -0
- package/dist/watcher/archiver.js.map +1 -0
- package/dist/watcher/loop.d.ts +34 -0
- package/dist/watcher/loop.d.ts.map +1 -0
- package/dist/watcher/loop.js +235 -0
- package/dist/watcher/loop.js.map +1 -0
- package/dist/watcher/runner.d.ts +70 -0
- package/dist/watcher/runner.d.ts.map +1 -0
- package/dist/watcher/runner.js +604 -0
- package/dist/watcher/runner.js.map +1 -0
- package/package.json +66 -0
- package/templates/.env.example +3 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { MANAGED_AGENTS_BLOCK, OSQ_END_MARKER, OSQ_START_MARKER } from '../core/init.js';
|
|
4
|
+
import { parseFrontmatter, parseSpecMd } from '../core/parser.js';
|
|
5
|
+
import { spawnWithTimeout } from './process.js';
|
|
6
|
+
import { EventStreamParser, asRecord, firstNonEmptyString, resolveEventTimestamp, } from './stream.js';
|
|
7
|
+
import { appendHarnessEvent, } from './types.js';
|
|
8
|
+
export const OPENCODE_AGENT_TEMPLATE = `---
|
|
9
|
+
description: Autonomous task execution agent for osq
|
|
10
|
+
mode: all
|
|
11
|
+
permission:
|
|
12
|
+
read: allow
|
|
13
|
+
edit: allow
|
|
14
|
+
bash: allow
|
|
15
|
+
glob: allow
|
|
16
|
+
grep: allow
|
|
17
|
+
webfetch: deny
|
|
18
|
+
websearch: deny
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
${MANAGED_AGENTS_BLOCK}
|
|
22
|
+
`;
|
|
23
|
+
export async function resolveOpencodeBinary(config) {
|
|
24
|
+
if (process.env.OPENCODE_PATH) {
|
|
25
|
+
return process.env.OPENCODE_PATH;
|
|
26
|
+
}
|
|
27
|
+
if (config?.opencode?.bin) {
|
|
28
|
+
return config.opencode.bin;
|
|
29
|
+
}
|
|
30
|
+
return 'opencode';
|
|
31
|
+
}
|
|
32
|
+
export function buildOpencodePrompt(options) {
|
|
33
|
+
const { projectRoot, specFolderPath, taskNumber, taskTitle, scope, entry, verifyCommand } = options;
|
|
34
|
+
const taskRelPath = path.relative(projectRoot, path.resolve(specFolderPath, 'tasks', `${taskNumber}.md`));
|
|
35
|
+
const specRelPath = path.relative(projectRoot, path.resolve(specFolderPath, 'spec.md'));
|
|
36
|
+
const resultRelPath = path.relative(projectRoot, path.resolve(specFolderPath, '.run', 'results', `${taskNumber}.md`));
|
|
37
|
+
return [
|
|
38
|
+
'You are a coding agent working autonomously on an osq task. Follow AGENTS.md strictly.',
|
|
39
|
+
`Task File: ${taskRelPath}`,
|
|
40
|
+
`Parent Spec: ${specRelPath}`,
|
|
41
|
+
`Task Title: ${taskTitle}`,
|
|
42
|
+
`Scope: ${scope.join(', ')}`,
|
|
43
|
+
`Entry: ${entry.join(', ')}`,
|
|
44
|
+
`Verify Command: ${verifyCommand}`,
|
|
45
|
+
'',
|
|
46
|
+
'Rules:',
|
|
47
|
+
`1. Read ${taskRelPath}, ${specRelPath}, and features docs referenced in ${specRelPath}.`,
|
|
48
|
+
'2. Write tests for each acceptance line before implementing.',
|
|
49
|
+
'3. Keep all edits strictly inside scope.',
|
|
50
|
+
`4. Verify your work by running: ${verifyCommand}`,
|
|
51
|
+
`5. CRITICAL: Before exiting, you MUST write ${resultRelPath} documenting: changed, deviated, drift against features/, missing context, and next steps.`,
|
|
52
|
+
`6. Do not modify tasks.md, spec.md, or any file outside your scope and ${resultRelPath}.`,
|
|
53
|
+
`7. When done, write ${resultRelPath} and exit cleanly.`,
|
|
54
|
+
].join('\n');
|
|
55
|
+
}
|
|
56
|
+
export async function buildOpencodeArgs(options) {
|
|
57
|
+
const { projectRoot, specFolderPath, taskNumber, config } = options;
|
|
58
|
+
const agent = config?.opencode?.agent || 'osq-coder';
|
|
59
|
+
const model = config?.opencode?.model || process.env.OSQ_MODEL || 'deepseek/deepseek-flash';
|
|
60
|
+
const prompt = buildOpencodePrompt(options);
|
|
61
|
+
const args = [
|
|
62
|
+
'run',
|
|
63
|
+
prompt,
|
|
64
|
+
'--agent',
|
|
65
|
+
agent,
|
|
66
|
+
'--auto',
|
|
67
|
+
'--format',
|
|
68
|
+
'json',
|
|
69
|
+
'--dir',
|
|
70
|
+
projectRoot,
|
|
71
|
+
'--model',
|
|
72
|
+
model,
|
|
73
|
+
];
|
|
74
|
+
if (config?.opencode?.variant) {
|
|
75
|
+
args.push('--variant', config.opencode.variant);
|
|
76
|
+
}
|
|
77
|
+
const taskRelPath = path.relative(projectRoot, path.resolve(specFolderPath, 'tasks', `${taskNumber}.md`));
|
|
78
|
+
const specRelPath = path.relative(projectRoot, path.resolve(specFolderPath, 'spec.md'));
|
|
79
|
+
args.push('--file', taskRelPath);
|
|
80
|
+
args.push('--file', specRelPath);
|
|
81
|
+
let featureNames = [];
|
|
82
|
+
try {
|
|
83
|
+
const taskPath = path.resolve(specFolderPath, 'tasks', `${taskNumber}.md`);
|
|
84
|
+
const taskContent = await fs.readFile(taskPath, 'utf8');
|
|
85
|
+
const { data: taskData } = parseFrontmatter(taskContent);
|
|
86
|
+
if (taskData.features) {
|
|
87
|
+
if (Array.isArray(taskData.features)) {
|
|
88
|
+
featureNames = taskData.features
|
|
89
|
+
.map(String)
|
|
90
|
+
.map((s) => s.trim())
|
|
91
|
+
.filter(Boolean);
|
|
92
|
+
}
|
|
93
|
+
else if (typeof taskData.features === 'object' && taskData.features !== null) {
|
|
94
|
+
const featObj = taskData.features;
|
|
95
|
+
const reads = Array.isArray(featObj.reads) ? featObj.reads : [];
|
|
96
|
+
const writes = Array.isArray(featObj.writes) ? featObj.writes : [];
|
|
97
|
+
featureNames = [...reads, ...writes]
|
|
98
|
+
.map(String)
|
|
99
|
+
.map((s) => s.trim())
|
|
100
|
+
.filter(Boolean);
|
|
101
|
+
}
|
|
102
|
+
else if (typeof taskData.features === 'string' && taskData.features.trim()) {
|
|
103
|
+
featureNames = [taskData.features.trim()];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch { }
|
|
108
|
+
if (featureNames.length === 0) {
|
|
109
|
+
try {
|
|
110
|
+
const specPath = path.resolve(specFolderPath, 'spec.md');
|
|
111
|
+
const specContent = await fs.readFile(specPath, 'utf8');
|
|
112
|
+
const specData = parseSpecMd(specContent);
|
|
113
|
+
const allSpecFeatures = [...specData.features.reads, ...specData.features.writes];
|
|
114
|
+
featureNames = Array.from(new Set(allSpecFeatures.map((s) => s.trim()).filter(Boolean)));
|
|
115
|
+
}
|
|
116
|
+
catch { }
|
|
117
|
+
}
|
|
118
|
+
const featuresDirName = config?.paths?.features || 'features';
|
|
119
|
+
for (const feature of featureNames) {
|
|
120
|
+
const featureFileName = feature.endsWith('.md') ? feature : `${feature}.md`;
|
|
121
|
+
let featurePath;
|
|
122
|
+
if (featureFileName.startsWith('features/') ||
|
|
123
|
+
featureFileName.startsWith(`${featuresDirName}/`)) {
|
|
124
|
+
featurePath = path.resolve(projectRoot, featureFileName);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
featurePath = path.resolve(projectRoot, featuresDirName, featureFileName);
|
|
128
|
+
}
|
|
129
|
+
const featureRelPath = path.relative(projectRoot, featurePath);
|
|
130
|
+
args.push('--file', featureRelPath);
|
|
131
|
+
}
|
|
132
|
+
return args;
|
|
133
|
+
}
|
|
134
|
+
export const spawnTask = buildOpencodeArgs;
|
|
135
|
+
export function extractOpencodeTokens(event) {
|
|
136
|
+
if (!event || typeof event !== 'object') {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
const eventObj = event;
|
|
140
|
+
const part = typeof eventObj.part === 'object' && eventObj.part !== null
|
|
141
|
+
? eventObj.part
|
|
142
|
+
: eventObj;
|
|
143
|
+
const tokensObj = typeof part.tokens === 'object' && part.tokens !== null
|
|
144
|
+
? part.tokens
|
|
145
|
+
: typeof eventObj.tokens === 'object' && eventObj.tokens !== null
|
|
146
|
+
? eventObj.tokens
|
|
147
|
+
: null;
|
|
148
|
+
if (!tokensObj) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
const promptTokens = Number(tokensObj.input ?? tokensObj.promptTokens ?? tokensObj.prompt ?? 0) || 0;
|
|
152
|
+
const candidateTokens = Number(tokensObj.output ?? tokensObj.candidateTokens ?? tokensObj.completionTokens ?? 0) || 0;
|
|
153
|
+
const totalTokens = Number(tokensObj.total ?? tokensObj.totalTokens ?? promptTokens + candidateTokens) || 0;
|
|
154
|
+
let cachedTokens = 0;
|
|
155
|
+
if (typeof tokensObj.cache === 'number') {
|
|
156
|
+
cachedTokens = tokensObj.cache;
|
|
157
|
+
}
|
|
158
|
+
else if (typeof tokensObj.cachedTokens === 'number') {
|
|
159
|
+
cachedTokens = tokensObj.cachedTokens;
|
|
160
|
+
}
|
|
161
|
+
else if (typeof tokensObj.cached === 'number') {
|
|
162
|
+
cachedTokens = tokensObj.cached;
|
|
163
|
+
}
|
|
164
|
+
else if (typeof tokensObj.cache === 'object' && tokensObj.cache !== null) {
|
|
165
|
+
const cacheObj = tokensObj.cache;
|
|
166
|
+
const read = Number(cacheObj.read) || 0;
|
|
167
|
+
const write = Number(cacheObj.write) || 0;
|
|
168
|
+
cachedTokens = read + write;
|
|
169
|
+
}
|
|
170
|
+
const rawCost = part.cost ?? eventObj.cost;
|
|
171
|
+
const cost = typeof rawCost === 'number' && !Number.isNaN(rawCost) ? rawCost : Number(rawCost) || 0;
|
|
172
|
+
const reasoningTokens = Number(tokensObj.reasoning ?? tokensObj.reasoningTokens ?? tokensObj.thinking ?? 0) || 0;
|
|
173
|
+
return {
|
|
174
|
+
promptTokens,
|
|
175
|
+
candidateTokens,
|
|
176
|
+
totalTokens,
|
|
177
|
+
cachedTokens,
|
|
178
|
+
reasoningTokens,
|
|
179
|
+
cost,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
const TOOL_SUMMARY_MAX_LENGTH = 60;
|
|
183
|
+
const FILE_TOOLS = new Set(['read', 'edit', 'write', 'glob']);
|
|
184
|
+
export function extractToolEventSummary(toolName, input) {
|
|
185
|
+
const tool = (toolName || '').toLowerCase();
|
|
186
|
+
const inputObj = asRecord(input);
|
|
187
|
+
if (FILE_TOOLS.has(tool)) {
|
|
188
|
+
return (firstNonEmptyString(inputObj?.path, inputObj?.file, inputObj?.filepath, inputObj?.filePath, inputObj?.pattern) ?? '');
|
|
189
|
+
}
|
|
190
|
+
if (tool === 'bash') {
|
|
191
|
+
const command = firstNonEmptyString(inputObj?.command, inputObj?.cmd) ?? '';
|
|
192
|
+
return command.slice(0, TOOL_SUMMARY_MAX_LENGTH);
|
|
193
|
+
}
|
|
194
|
+
const raw = inputObj ? JSON.stringify(inputObj) : input === undefined ? '' : String(input);
|
|
195
|
+
return raw.slice(0, TOOL_SUMMARY_MAX_LENGTH);
|
|
196
|
+
}
|
|
197
|
+
export function extractOpencodeToolEvent(event) {
|
|
198
|
+
const eventObj = asRecord(event);
|
|
199
|
+
if (!eventObj) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
const part = asRecord(eventObj.part);
|
|
203
|
+
const isToolUse = eventObj.type === 'tool_use' || part?.type === 'tool-use' || part?.type === 'tool_use';
|
|
204
|
+
if (!isToolUse) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
const tool = firstNonEmptyString(eventObj.tool, eventObj.name, part?.tool, part?.name);
|
|
208
|
+
if (!tool) {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
const state = asRecord(part?.state);
|
|
212
|
+
const input = eventObj.input ??
|
|
213
|
+
eventObj.parameters ??
|
|
214
|
+
part?.input ??
|
|
215
|
+
part?.parameters ??
|
|
216
|
+
state?.input ??
|
|
217
|
+
state?.parameters;
|
|
218
|
+
return { tool, summary: extractToolEventSummary(tool, input) };
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Single code path for tool observation: the events.jsonl entry and its verbose
|
|
222
|
+
* stderr log line are always emitted together by the shared stdout handler.
|
|
223
|
+
*/
|
|
224
|
+
async function recordToolEvent(specFolderPath, taskNumber, toolEvent, timestamp, logger) {
|
|
225
|
+
await appendHarnessEvent(specFolderPath, taskNumber, {
|
|
226
|
+
type: 'tool',
|
|
227
|
+
timestamp,
|
|
228
|
+
data: { tool: toolEvent.tool, summary: toolEvent.summary },
|
|
229
|
+
});
|
|
230
|
+
logger?.verbose(`[tool] ${toolEvent.tool}: ${toolEvent.summary}`);
|
|
231
|
+
}
|
|
232
|
+
export async function processOpencodeStdoutLine(line, specFolderPath, taskNumber, logger) {
|
|
233
|
+
const trimmed = line.trim();
|
|
234
|
+
if (!trimmed) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
let event;
|
|
238
|
+
try {
|
|
239
|
+
event = JSON.parse(trimmed);
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
// Malformed or unparseable non-JSON stdout lines do not crash the adapter process
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (!event || typeof event !== 'object') {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const eventObj = event;
|
|
249
|
+
const toolEvent = extractOpencodeToolEvent(eventObj);
|
|
250
|
+
if (toolEvent) {
|
|
251
|
+
await recordToolEvent(specFolderPath, taskNumber, toolEvent, resolveEventTimestamp(eventObj), logger);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (eventObj.type === 'step_finish') {
|
|
255
|
+
const tokensData = extractOpencodeTokens(eventObj);
|
|
256
|
+
if (tokensData) {
|
|
257
|
+
await appendHarnessEvent(specFolderPath, taskNumber, {
|
|
258
|
+
type: 'tokens',
|
|
259
|
+
timestamp: resolveEventTimestamp(eventObj),
|
|
260
|
+
data: {
|
|
261
|
+
promptTokens: tokensData.promptTokens,
|
|
262
|
+
candidateTokens: tokensData.candidateTokens,
|
|
263
|
+
totalTokens: tokensData.totalTokens,
|
|
264
|
+
cachedTokens: tokensData.cachedTokens,
|
|
265
|
+
reasoningTokens: tokensData.reasoningTokens,
|
|
266
|
+
cost: tokensData.cost,
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
// A completed text part is the adapter's final assistant message. Only whole
|
|
273
|
+
// text parts become `text` events; step deltas are never persisted.
|
|
274
|
+
if (eventObj.type === 'text') {
|
|
275
|
+
const part = asRecord(eventObj.part);
|
|
276
|
+
const text = firstNonEmptyString(part?.text, eventObj.text);
|
|
277
|
+
if (text !== undefined) {
|
|
278
|
+
await appendHarnessEvent(specFolderPath, taskNumber, {
|
|
279
|
+
type: 'text',
|
|
280
|
+
timestamp: resolveEventTimestamp(eventObj),
|
|
281
|
+
data: { text },
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
// Unrecognised event types route exclusively to verbose logging so harness
|
|
287
|
+
// stdout can never leak onto the terminal.
|
|
288
|
+
logger?.verbose(`[opencode] Unknown event type: ${eventObj.type}`);
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Compatibility subclass retained for existing callers and tests; the buffering
|
|
292
|
+
* and serialization logic lives entirely in the shared {@link EventStreamParser}.
|
|
293
|
+
*/
|
|
294
|
+
export class OpencodeEventStreamParser extends EventStreamParser {
|
|
295
|
+
constructor(specFolderPath, taskNumber, logger) {
|
|
296
|
+
super((line) => processOpencodeStdoutLine(line, specFolderPath, taskNumber, logger));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
export async function preflightOpencode(projectRoot, config) {
|
|
300
|
+
const bin = await resolveOpencodeBinary(config);
|
|
301
|
+
let result;
|
|
302
|
+
try {
|
|
303
|
+
result = await spawnWithTimeout({
|
|
304
|
+
command: bin,
|
|
305
|
+
args: ['--version'],
|
|
306
|
+
cwd: projectRoot,
|
|
307
|
+
timeoutSeconds: 10,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
catch {
|
|
311
|
+
console.error(`OpenCode binary not found or failed: ${bin}`);
|
|
312
|
+
process.exitCode = 1;
|
|
313
|
+
process.exit(1);
|
|
314
|
+
return { version: '', bin };
|
|
315
|
+
}
|
|
316
|
+
if (result.exitCode !== 0) {
|
|
317
|
+
console.error(`OpenCode binary not found or failed: ${bin}`);
|
|
318
|
+
process.exitCode = 1;
|
|
319
|
+
process.exit(1);
|
|
320
|
+
return { version: '', bin };
|
|
321
|
+
}
|
|
322
|
+
const version = (result.stdout || result.stderr).trim().split('\n')[0].trim();
|
|
323
|
+
console.log(version);
|
|
324
|
+
return { version, bin };
|
|
325
|
+
}
|
|
326
|
+
export class OpencodeAdapter {
|
|
327
|
+
name = 'opencode';
|
|
328
|
+
async preflight(projectRoot, config) {
|
|
329
|
+
await preflightOpencode(projectRoot, config);
|
|
330
|
+
}
|
|
331
|
+
async setup(projectRoot, config) {
|
|
332
|
+
const agentDir = path.join(projectRoot, '.opencode', 'agent');
|
|
333
|
+
await fs.mkdir(agentDir, { recursive: true });
|
|
334
|
+
const agentName = config.opencode?.agent || 'osq-coder';
|
|
335
|
+
const agentPath = path.join(agentDir, `${agentName}.md`);
|
|
336
|
+
const exists = await fs
|
|
337
|
+
.stat(agentPath)
|
|
338
|
+
.then(() => true)
|
|
339
|
+
.catch(() => false);
|
|
340
|
+
if (!exists) {
|
|
341
|
+
await fs.writeFile(agentPath, OPENCODE_AGENT_TEMPLATE, 'utf8');
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
const currentContent = await fs.readFile(agentPath, 'utf8');
|
|
345
|
+
const startIndex = currentContent.indexOf(OSQ_START_MARKER);
|
|
346
|
+
const endIndex = currentContent.indexOf(OSQ_END_MARKER);
|
|
347
|
+
if (startIndex !== -1 && endIndex !== -1 && endIndex >= startIndex) {
|
|
348
|
+
const before = currentContent.slice(0, startIndex);
|
|
349
|
+
const after = currentContent.slice(endIndex + OSQ_END_MARKER.length);
|
|
350
|
+
const updated = `${before}${MANAGED_AGENTS_BLOCK}${after}`;
|
|
351
|
+
await fs.writeFile(agentPath, updated, 'utf8');
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
const separator = currentContent.endsWith('\n\n')
|
|
355
|
+
? ''
|
|
356
|
+
: currentContent.endsWith('\n')
|
|
357
|
+
? '\n'
|
|
358
|
+
: '\n\n';
|
|
359
|
+
const updated = `${currentContent}${separator}${MANAGED_AGENTS_BLOCK}\n`;
|
|
360
|
+
await fs.writeFile(agentPath, updated, 'utf8');
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
async spawn(options) {
|
|
364
|
+
const { projectRoot, specFolderPath, taskNumber, timeoutSeconds = 1800, config } = options;
|
|
365
|
+
const args = await buildOpencodeArgs(options);
|
|
366
|
+
const bin = await resolveOpencodeBinary(config);
|
|
367
|
+
const streamParser = new EventStreamParser((line) => processOpencodeStdoutLine(line, specFolderPath, taskNumber, options.logger));
|
|
368
|
+
const result = await spawnWithTimeout({
|
|
369
|
+
command: bin,
|
|
370
|
+
args,
|
|
371
|
+
cwd: projectRoot,
|
|
372
|
+
env: {
|
|
373
|
+
...process.env,
|
|
374
|
+
OSQ_TASK_NUMBER: taskNumber,
|
|
375
|
+
OSQ_SPEC_FOLDER: specFolderPath,
|
|
376
|
+
},
|
|
377
|
+
timeoutSeconds,
|
|
378
|
+
onStdout: (chunk) => {
|
|
379
|
+
streamParser.feed(chunk);
|
|
380
|
+
},
|
|
381
|
+
onSpawn: options.onSpawn,
|
|
382
|
+
});
|
|
383
|
+
await streamParser.flush();
|
|
384
|
+
return {
|
|
385
|
+
exitCode: result.exitCode,
|
|
386
|
+
timedOut: result.timedOut,
|
|
387
|
+
signal: result.signal,
|
|
388
|
+
error: result.error,
|
|
389
|
+
pid: result.pid,
|
|
390
|
+
elapsedMs: result.elapsedMs,
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
//# sourceMappingURL=opencode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/harness/opencode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type StdioOptions } from 'node:child_process';
|
|
2
|
+
export declare const DEFAULT_KILL_GRACE_PERIOD_MS = 5000;
|
|
3
|
+
export interface SpawnWithTimeoutOptions {
|
|
4
|
+
command: string;
|
|
5
|
+
args?: string[];
|
|
6
|
+
cwd?: string;
|
|
7
|
+
env?: NodeJS.ProcessEnv;
|
|
8
|
+
timeoutSeconds?: number;
|
|
9
|
+
killGracePeriodMs?: number;
|
|
10
|
+
stdio?: StdioOptions;
|
|
11
|
+
onStdout?: (data: string) => void;
|
|
12
|
+
onStderr?: (data: string) => void;
|
|
13
|
+
onSpawn?: (pid: number) => void;
|
|
14
|
+
}
|
|
15
|
+
export interface SpawnProcessResult {
|
|
16
|
+
exitCode: number;
|
|
17
|
+
stdout: string;
|
|
18
|
+
stderr: string;
|
|
19
|
+
timedOut: boolean;
|
|
20
|
+
signal?: NodeJS.Signals | string | null;
|
|
21
|
+
error?: string;
|
|
22
|
+
pid?: number;
|
|
23
|
+
elapsedMs?: number;
|
|
24
|
+
}
|
|
25
|
+
export declare function spawnWithTimeout(options: SpawnWithTimeoutOptions): Promise<SpawnProcessResult>;
|
|
26
|
+
//# sourceMappingURL=process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/harness/process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,oBAAoB,CAAC;AAE9D,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAsH9F"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
export const DEFAULT_KILL_GRACE_PERIOD_MS = 5000;
|
|
3
|
+
export function spawnWithTimeout(options) {
|
|
4
|
+
const { command, args = [], cwd, env = process.env, timeoutSeconds = 0, killGracePeriodMs = DEFAULT_KILL_GRACE_PERIOD_MS, stdio = ['ignore', 'pipe', 'pipe'], onStdout, onStderr, onSpawn, } = options;
|
|
5
|
+
return new Promise((resolve) => {
|
|
6
|
+
const startTime = Date.now();
|
|
7
|
+
let timedOut = false;
|
|
8
|
+
let settled = false;
|
|
9
|
+
let timeoutTimer = null;
|
|
10
|
+
let killTimer = null;
|
|
11
|
+
let stdoutOutput = '';
|
|
12
|
+
let stderrOutput = '';
|
|
13
|
+
const child = spawn(command, args, {
|
|
14
|
+
cwd,
|
|
15
|
+
env,
|
|
16
|
+
stdio,
|
|
17
|
+
});
|
|
18
|
+
const childPid = child.pid;
|
|
19
|
+
if (childPid !== undefined) {
|
|
20
|
+
onSpawn?.(childPid);
|
|
21
|
+
}
|
|
22
|
+
const cleanup = () => {
|
|
23
|
+
if (timeoutTimer) {
|
|
24
|
+
clearTimeout(timeoutTimer);
|
|
25
|
+
timeoutTimer = null;
|
|
26
|
+
}
|
|
27
|
+
if (killTimer) {
|
|
28
|
+
clearTimeout(killTimer);
|
|
29
|
+
killTimer = null;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const finish = (result) => {
|
|
33
|
+
if (settled)
|
|
34
|
+
return;
|
|
35
|
+
settled = true;
|
|
36
|
+
cleanup();
|
|
37
|
+
resolve({
|
|
38
|
+
...result,
|
|
39
|
+
pid: childPid,
|
|
40
|
+
elapsedMs: Date.now() - startTime,
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
if (timeoutSeconds > 0) {
|
|
44
|
+
timeoutTimer = setTimeout(() => {
|
|
45
|
+
timedOut = true;
|
|
46
|
+
child.kill('SIGTERM');
|
|
47
|
+
killTimer = setTimeout(() => {
|
|
48
|
+
try {
|
|
49
|
+
child.kill('SIGKILL');
|
|
50
|
+
}
|
|
51
|
+
catch { }
|
|
52
|
+
}, killGracePeriodMs);
|
|
53
|
+
}, timeoutSeconds * 1000);
|
|
54
|
+
}
|
|
55
|
+
child.stdout?.on('data', (chunk) => {
|
|
56
|
+
const text = chunk.toString();
|
|
57
|
+
stdoutOutput += text;
|
|
58
|
+
onStdout?.(text);
|
|
59
|
+
});
|
|
60
|
+
child.stderr?.on('data', (chunk) => {
|
|
61
|
+
const text = chunk.toString();
|
|
62
|
+
stderrOutput += text;
|
|
63
|
+
onStderr?.(text);
|
|
64
|
+
});
|
|
65
|
+
child.on('error', (err) => {
|
|
66
|
+
finish({
|
|
67
|
+
exitCode: 1,
|
|
68
|
+
stdout: stdoutOutput,
|
|
69
|
+
stderr: stderrOutput,
|
|
70
|
+
timedOut: false,
|
|
71
|
+
signal: null,
|
|
72
|
+
error: err.message,
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
child.on('close', (code, signal) => {
|
|
76
|
+
const exitCode = timedOut
|
|
77
|
+
? code !== null && code !== 0
|
|
78
|
+
? code
|
|
79
|
+
: 124
|
|
80
|
+
: code !== null
|
|
81
|
+
? code
|
|
82
|
+
: 1;
|
|
83
|
+
const error = exitCode !== 0
|
|
84
|
+
? timedOut
|
|
85
|
+
? 'Task execution timed out'
|
|
86
|
+
: stderrOutput || stdoutOutput || undefined
|
|
87
|
+
: undefined;
|
|
88
|
+
finish({
|
|
89
|
+
exitCode,
|
|
90
|
+
stdout: stdoutOutput,
|
|
91
|
+
stderr: stderrOutput,
|
|
92
|
+
timedOut,
|
|
93
|
+
signal: signal ?? null,
|
|
94
|
+
error,
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/harness/process.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared harness stream helpers. Harness adapters translate an unbounded stdout
|
|
3
|
+
* stream of JSON lines into `events.jsonl`; the record coercion, string picking,
|
|
4
|
+
* timestamp resolution, and line buffering are identical across adapters and
|
|
5
|
+
* live here so each adapter only owns its event translation.
|
|
6
|
+
*/
|
|
7
|
+
/** Coerce an unknown JSON value into a plain object, or `undefined` for arrays and primitives. */
|
|
8
|
+
export declare function asRecord(value: unknown): Record<string, unknown> | undefined;
|
|
9
|
+
/** Return the first candidate that is a non-empty string, skipping every other type. */
|
|
10
|
+
export declare function firstNonEmptyString(...values: unknown[]): string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Resolve an event timestamp to ISO form. Harnesses report either a top-level
|
|
13
|
+
* `timestamp` or, for Antigravity step updates, a nested `step_update.timestamp`.
|
|
14
|
+
* Invalid or missing timestamps fall back to the current time so an event is
|
|
15
|
+
* never written without one.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveEventTimestamp(eventObj: Record<string, unknown>): string;
|
|
18
|
+
/**
|
|
19
|
+
* Buffers arbitrarily chunked stdout and delivers complete, non-blank lines to
|
|
20
|
+
* an async handler one at a time in arrival order. A handler rejection is
|
|
21
|
+
* swallowed so a single malformed line can never abort the rest of the stream;
|
|
22
|
+
* `flush` drains whatever partial line remains and resolves after every queued
|
|
23
|
+
* handler has settled.
|
|
24
|
+
*/
|
|
25
|
+
export declare class EventStreamParser {
|
|
26
|
+
private readonly onLine;
|
|
27
|
+
private buffer;
|
|
28
|
+
private pending;
|
|
29
|
+
constructor(onLine: (line: string) => Promise<void>);
|
|
30
|
+
feed(chunk: string): void;
|
|
31
|
+
flush(): Promise<void>;
|
|
32
|
+
private enqueue;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/harness/stream.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,kGAAkG;AAClG,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAI5E;AAED,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,GAAG,SAAS,CAO5E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAU/E;AAED;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAIhB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,OAAO,CAAoC;gBAEtB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;IAEpE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAUnB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B,OAAO,CAAC,OAAO;CAMhB"}
|