@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.
Files changed (140) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +183 -0
  3. package/dist/cli/approve.d.ts +6 -0
  4. package/dist/cli/approve.d.ts.map +1 -0
  5. package/dist/cli/approve.js +26 -0
  6. package/dist/cli/approve.js.map +1 -0
  7. package/dist/cli/bin.d.ts +3 -0
  8. package/dist/cli/bin.d.ts.map +1 -0
  9. package/dist/cli/bin.js +5 -0
  10. package/dist/cli/bin.js.map +1 -0
  11. package/dist/cli/index.d.ts +4 -0
  12. package/dist/cli/index.d.ts.map +1 -0
  13. package/dist/cli/index.js +76 -0
  14. package/dist/cli/index.js.map +1 -0
  15. package/dist/cli/init.d.ts +4 -0
  16. package/dist/cli/init.d.ts.map +1 -0
  17. package/dist/cli/init.js +19 -0
  18. package/dist/cli/init.js.map +1 -0
  19. package/dist/cli/new.d.ts +4 -0
  20. package/dist/cli/new.d.ts.map +1 -0
  21. package/dist/cli/new.js +15 -0
  22. package/dist/cli/new.js.map +1 -0
  23. package/dist/cli/report.d.ts +10 -0
  24. package/dist/cli/report.d.ts.map +1 -0
  25. package/dist/cli/report.js +84 -0
  26. package/dist/cli/report.js.map +1 -0
  27. package/dist/cli/setup.d.ts +2 -0
  28. package/dist/cli/setup.d.ts.map +1 -0
  29. package/dist/cli/setup.js +10 -0
  30. package/dist/cli/setup.js.map +1 -0
  31. package/dist/cli/show.d.ts +7 -0
  32. package/dist/cli/show.d.ts.map +1 -0
  33. package/dist/cli/show.js +27 -0
  34. package/dist/cli/show.js.map +1 -0
  35. package/dist/cli/status.d.ts +7 -0
  36. package/dist/cli/status.d.ts.map +1 -0
  37. package/dist/cli/status.js +23 -0
  38. package/dist/cli/status.js.map +1 -0
  39. package/dist/cli/watch.d.ts +9 -0
  40. package/dist/cli/watch.d.ts.map +1 -0
  41. package/dist/cli/watch.js +20 -0
  42. package/dist/cli/watch.js.map +1 -0
  43. package/dist/core/approve.d.ts +11 -0
  44. package/dist/core/approve.d.ts.map +1 -0
  45. package/dist/core/approve.js +52 -0
  46. package/dist/core/approve.js.map +1 -0
  47. package/dist/core/config.d.ts +53 -0
  48. package/dist/core/config.d.ts.map +1 -0
  49. package/dist/core/config.js +124 -0
  50. package/dist/core/config.js.map +1 -0
  51. package/dist/core/hasher.d.ts +4 -0
  52. package/dist/core/hasher.d.ts.map +1 -0
  53. package/dist/core/hasher.js +49 -0
  54. package/dist/core/hasher.js.map +1 -0
  55. package/dist/core/init.d.ts +12 -0
  56. package/dist/core/init.d.ts.map +1 -0
  57. package/dist/core/init.js +151 -0
  58. package/dist/core/init.js.map +1 -0
  59. package/dist/core/linter.d.ts +8 -0
  60. package/dist/core/linter.d.ts.map +1 -0
  61. package/dist/core/linter.js +100 -0
  62. package/dist/core/linter.js.map +1 -0
  63. package/dist/core/lock.d.ts +17 -0
  64. package/dist/core/lock.d.ts.map +1 -0
  65. package/dist/core/lock.js +104 -0
  66. package/dist/core/lock.js.map +1 -0
  67. package/dist/core/logger.d.ts +32 -0
  68. package/dist/core/logger.d.ts.map +1 -0
  69. package/dist/core/logger.js +106 -0
  70. package/dist/core/logger.js.map +1 -0
  71. package/dist/core/new.d.ts +11 -0
  72. package/dist/core/new.d.ts.map +1 -0
  73. package/dist/core/new.js +79 -0
  74. package/dist/core/new.js.map +1 -0
  75. package/dist/core/parser.d.ts +32 -0
  76. package/dist/core/parser.d.ts.map +1 -0
  77. package/dist/core/parser.js +87 -0
  78. package/dist/core/parser.js.map +1 -0
  79. package/dist/core/report.d.ts +54 -0
  80. package/dist/core/report.d.ts.map +1 -0
  81. package/dist/core/report.js +475 -0
  82. package/dist/core/report.js.map +1 -0
  83. package/dist/core/show.d.ts +50 -0
  84. package/dist/core/show.d.ts.map +1 -0
  85. package/dist/core/show.js +374 -0
  86. package/dist/core/show.js.map +1 -0
  87. package/dist/core/state.d.ts +25 -0
  88. package/dist/core/state.d.ts.map +1 -0
  89. package/dist/core/state.js +180 -0
  90. package/dist/core/state.js.map +1 -0
  91. package/dist/core/status.d.ts +10 -0
  92. package/dist/core/status.d.ts.map +1 -0
  93. package/dist/core/status.js +106 -0
  94. package/dist/core/status.js.map +1 -0
  95. package/dist/harness/agy.d.ts +31 -0
  96. package/dist/harness/agy.d.ts.map +1 -0
  97. package/dist/harness/agy.js +251 -0
  98. package/dist/harness/agy.js.map +1 -0
  99. package/dist/harness/index.d.ts +7 -0
  100. package/dist/harness/index.d.ts.map +1 -0
  101. package/dist/harness/index.js +20 -0
  102. package/dist/harness/index.js.map +1 -0
  103. package/dist/harness/mock.d.ts +19 -0
  104. package/dist/harness/mock.d.ts.map +1 -0
  105. package/dist/harness/mock.js +62 -0
  106. package/dist/harness/mock.js.map +1 -0
  107. package/dist/harness/opencode.d.ts +39 -0
  108. package/dist/harness/opencode.d.ts.map +1 -0
  109. package/dist/harness/opencode.js +394 -0
  110. package/dist/harness/opencode.js.map +1 -0
  111. package/dist/harness/process.d.ts +26 -0
  112. package/dist/harness/process.d.ts.map +1 -0
  113. package/dist/harness/process.js +99 -0
  114. package/dist/harness/process.js.map +1 -0
  115. package/dist/harness/stream.d.ts +34 -0
  116. package/dist/harness/stream.d.ts.map +1 -0
  117. package/dist/harness/stream.js +75 -0
  118. package/dist/harness/stream.js.map +1 -0
  119. package/dist/harness/types.d.ts +53 -0
  120. package/dist/harness/types.d.ts.map +1 -0
  121. package/dist/harness/types.js +10 -0
  122. package/dist/harness/types.js.map +1 -0
  123. package/dist/index.d.ts +3 -0
  124. package/dist/index.d.ts.map +1 -0
  125. package/dist/index.js +2 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/watcher/archiver.d.ts +5 -0
  128. package/dist/watcher/archiver.d.ts.map +1 -0
  129. package/dist/watcher/archiver.js +66 -0
  130. package/dist/watcher/archiver.js.map +1 -0
  131. package/dist/watcher/loop.d.ts +34 -0
  132. package/dist/watcher/loop.d.ts.map +1 -0
  133. package/dist/watcher/loop.js +235 -0
  134. package/dist/watcher/loop.js.map +1 -0
  135. package/dist/watcher/runner.d.ts +70 -0
  136. package/dist/watcher/runner.d.ts.map +1 -0
  137. package/dist/watcher/runner.js +604 -0
  138. package/dist/watcher/runner.js.map +1 -0
  139. package/package.json +66 -0
  140. 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"}