@the-open-engine/zeroshot 6.4.0 → 6.6.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 (146) hide show
  1. package/cli/commands/providers.js +11 -5
  2. package/cli/index.js +79 -16
  3. package/cli/lib/first-run.js +14 -3
  4. package/docker/zeroshot-cluster/Dockerfile +11 -1
  5. package/lib/agent-cli-provider/acp-stdio-runner.d.ts +4 -0
  6. package/lib/agent-cli-provider/acp-stdio-runner.d.ts.map +1 -0
  7. package/lib/agent-cli-provider/acp-stdio-runner.js +259 -0
  8. package/lib/agent-cli-provider/acp-stdio-runner.js.map +1 -0
  9. package/lib/agent-cli-provider/adapters/acp.d.ts +23 -0
  10. package/lib/agent-cli-provider/adapters/acp.d.ts.map +1 -0
  11. package/lib/agent-cli-provider/adapters/acp.js +373 -0
  12. package/lib/agent-cli-provider/adapters/acp.js.map +1 -0
  13. package/lib/agent-cli-provider/adapters/claude.d.ts.map +1 -1
  14. package/lib/agent-cli-provider/adapters/claude.js +2 -29
  15. package/lib/agent-cli-provider/adapters/claude.js.map +1 -1
  16. package/lib/agent-cli-provider/adapters/copilot-parser.d.ts +3 -0
  17. package/lib/agent-cli-provider/adapters/copilot-parser.d.ts.map +1 -0
  18. package/lib/agent-cli-provider/adapters/copilot-parser.js +154 -0
  19. package/lib/agent-cli-provider/adapters/copilot-parser.js.map +1 -0
  20. package/lib/agent-cli-provider/adapters/copilot.d.ts +3 -0
  21. package/lib/agent-cli-provider/adapters/copilot.d.ts.map +1 -0
  22. package/lib/agent-cli-provider/adapters/copilot.js +176 -0
  23. package/lib/agent-cli-provider/adapters/copilot.js.map +1 -0
  24. package/lib/agent-cli-provider/adapters/gateway.d.ts +6 -0
  25. package/lib/agent-cli-provider/adapters/gateway.d.ts.map +1 -0
  26. package/lib/agent-cli-provider/adapters/gateway.js +161 -0
  27. package/lib/agent-cli-provider/adapters/gateway.js.map +1 -0
  28. package/lib/agent-cli-provider/adapters/gemini.d.ts.map +1 -1
  29. package/lib/agent-cli-provider/adapters/gemini.js +9 -2
  30. package/lib/agent-cli-provider/adapters/gemini.js.map +1 -1
  31. package/lib/agent-cli-provider/adapters/index.d.ts.map +1 -1
  32. package/lib/agent-cli-provider/adapters/index.js +6 -34
  33. package/lib/agent-cli-provider/adapters/index.js.map +1 -1
  34. package/lib/agent-cli-provider/adapters/opencode.d.ts.map +1 -1
  35. package/lib/agent-cli-provider/adapters/opencode.js +5 -1
  36. package/lib/agent-cli-provider/adapters/opencode.js.map +1 -1
  37. package/lib/agent-cli-provider/adapters/pi.d.ts +3 -0
  38. package/lib/agent-cli-provider/adapters/pi.d.ts.map +1 -0
  39. package/lib/agent-cli-provider/adapters/pi.js +331 -0
  40. package/lib/agent-cli-provider/adapters/pi.js.map +1 -0
  41. package/lib/agent-cli-provider/claude-command.d.ts +6 -0
  42. package/lib/agent-cli-provider/claude-command.d.ts.map +1 -0
  43. package/lib/agent-cli-provider/claude-command.js +43 -0
  44. package/lib/agent-cli-provider/claude-command.js.map +1 -0
  45. package/lib/agent-cli-provider/contract-actions.d.ts.map +1 -1
  46. package/lib/agent-cli-provider/contract-actions.js +13 -17
  47. package/lib/agent-cli-provider/contract-actions.js.map +1 -1
  48. package/lib/agent-cli-provider/contract-invoke.d.ts.map +1 -1
  49. package/lib/agent-cli-provider/contract-invoke.js +10 -3
  50. package/lib/agent-cli-provider/contract-invoke.js.map +1 -1
  51. package/lib/agent-cli-provider/contract-options.d.ts.map +1 -1
  52. package/lib/agent-cli-provider/contract-options.js +57 -2
  53. package/lib/agent-cli-provider/contract-options.js.map +1 -1
  54. package/lib/agent-cli-provider/contract-support.d.ts +1 -0
  55. package/lib/agent-cli-provider/contract-support.d.ts.map +1 -1
  56. package/lib/agent-cli-provider/contract-support.js +25 -3
  57. package/lib/agent-cli-provider/contract-support.js.map +1 -1
  58. package/lib/agent-cli-provider/errors.d.ts +1 -0
  59. package/lib/agent-cli-provider/errors.d.ts.map +1 -1
  60. package/lib/agent-cli-provider/errors.js +14 -5
  61. package/lib/agent-cli-provider/errors.js.map +1 -1
  62. package/lib/agent-cli-provider/gateway-client.d.ts +32 -0
  63. package/lib/agent-cli-provider/gateway-client.d.ts.map +1 -0
  64. package/lib/agent-cli-provider/gateway-client.js +135 -0
  65. package/lib/agent-cli-provider/gateway-client.js.map +1 -0
  66. package/lib/agent-cli-provider/gateway-runner.d.ts +9 -0
  67. package/lib/agent-cli-provider/gateway-runner.d.ts.map +1 -0
  68. package/lib/agent-cli-provider/gateway-runner.js +294 -0
  69. package/lib/agent-cli-provider/gateway-runner.js.map +1 -0
  70. package/lib/agent-cli-provider/gateway-tools.d.ts +14 -0
  71. package/lib/agent-cli-provider/gateway-tools.d.ts.map +1 -0
  72. package/lib/agent-cli-provider/gateway-tools.js +495 -0
  73. package/lib/agent-cli-provider/gateway-tools.js.map +1 -0
  74. package/lib/agent-cli-provider/index.d.ts +3 -2
  75. package/lib/agent-cli-provider/index.d.ts.map +1 -1
  76. package/lib/agent-cli-provider/index.js +14 -1
  77. package/lib/agent-cli-provider/index.js.map +1 -1
  78. package/lib/agent-cli-provider/invoke-evidence.d.ts +2 -2
  79. package/lib/agent-cli-provider/invoke-evidence.d.ts.map +1 -1
  80. package/lib/agent-cli-provider/invoke-evidence.js +17 -3
  81. package/lib/agent-cli-provider/invoke-evidence.js.map +1 -1
  82. package/lib/agent-cli-provider/provider-registry.d.ts +437 -0
  83. package/lib/agent-cli-provider/provider-registry.d.ts.map +1 -0
  84. package/lib/agent-cli-provider/provider-registry.js +411 -0
  85. package/lib/agent-cli-provider/provider-registry.js.map +1 -0
  86. package/lib/agent-cli-provider/single-agent-runtime.d.ts +7 -0
  87. package/lib/agent-cli-provider/single-agent-runtime.d.ts.map +1 -1
  88. package/lib/agent-cli-provider/single-agent-runtime.js +139 -19
  89. package/lib/agent-cli-provider/single-agent-runtime.js.map +1 -1
  90. package/lib/agent-cli-provider/types.d.ts +106 -4
  91. package/lib/agent-cli-provider/types.d.ts.map +1 -1
  92. package/lib/agent-cli-provider/types.js.map +1 -1
  93. package/lib/docker-config.js +24 -13
  94. package/lib/provider-defaults.js +15 -4
  95. package/lib/provider-detection.js +2 -0
  96. package/lib/provider-names.js +32 -12
  97. package/lib/repo-settings.js +15 -1
  98. package/lib/settings/claude-auth.js +3 -6
  99. package/lib/settings.js +17 -2
  100. package/lib/setup-apply.js +300 -0
  101. package/lib/setup-journal.js +109 -0
  102. package/lib/setup-plan.js +406 -0
  103. package/lib/setup-undo.js +88 -0
  104. package/lib/start-cluster.js +12 -1
  105. package/lib/stream-json-parser.js +7 -5
  106. package/package.json +31 -1
  107. package/scripts/assert-release-published.js +53 -0
  108. package/scripts/live-provider-smoke.js +221 -0
  109. package/scripts/release-preflight.js +236 -0
  110. package/src/agent/agent-lifecycle.js +5 -4
  111. package/src/agent/agent-quality-gate-schema.js +2 -2
  112. package/src/agent/agent-task-executor.js +41 -2
  113. package/src/agent-cli-provider/acp-stdio-runner.ts +314 -0
  114. package/src/agent-cli-provider/adapters/acp.ts +493 -0
  115. package/src/agent-cli-provider/adapters/claude.ts +2 -32
  116. package/src/agent-cli-provider/adapters/copilot-parser.ts +166 -0
  117. package/src/agent-cli-provider/adapters/copilot.ts +231 -0
  118. package/src/agent-cli-provider/adapters/gateway.ts +186 -0
  119. package/src/agent-cli-provider/adapters/gemini.ts +9 -2
  120. package/src/agent-cli-provider/adapters/index.ts +5 -36
  121. package/src/agent-cli-provider/adapters/opencode.ts +4 -1
  122. package/src/agent-cli-provider/adapters/pi.ts +410 -0
  123. package/src/agent-cli-provider/claude-command.ts +47 -0
  124. package/src/agent-cli-provider/contract-actions.ts +14 -17
  125. package/src/agent-cli-provider/contract-invoke.ts +12 -3
  126. package/src/agent-cli-provider/contract-options.ts +72 -3
  127. package/src/agent-cli-provider/contract-support.ts +30 -3
  128. package/src/agent-cli-provider/errors.ts +14 -4
  129. package/src/agent-cli-provider/gateway-client.ts +170 -0
  130. package/src/agent-cli-provider/gateway-runner.ts +353 -0
  131. package/src/agent-cli-provider/gateway-tools.ts +616 -0
  132. package/src/agent-cli-provider/index.ts +28 -0
  133. package/src/agent-cli-provider/invoke-evidence.ts +24 -3
  134. package/src/agent-cli-provider/provider-registry.ts +515 -0
  135. package/src/agent-cli-provider/single-agent-runtime.ts +192 -18
  136. package/src/agent-cli-provider/types.ts +145 -4
  137. package/src/config-validator.js +33 -15
  138. package/src/isolation-manager.js +124 -19
  139. package/src/orchestrator.js +23 -10
  140. package/src/preflight.js +83 -30
  141. package/src/providers/capabilities.js +15 -42
  142. package/src/providers/index.js +52 -72
  143. package/src/worktree-claude-config.js +17 -0
  144. package/task-lib/commands/run.js +1 -0
  145. package/task-lib/provider-helper-runtime.js +11 -0
  146. package/task-lib/runner.js +7 -0
@@ -0,0 +1,314 @@
1
+ /* eslint-disable max-lines-per-function */
2
+ import { spawn } from 'node:child_process';
3
+ import { omitProcessControlEnv, omitUnsafeProviderEnv } from './env-safety';
4
+ import type { CommandSpec, ProviderId } from './types';
5
+ import type { ProcessResult, ProcessRunnerOptions } from './process-runner';
6
+
7
+ const DEFAULT_TIMEOUT_KILL_GRACE_MS = 100;
8
+
9
+ interface JsonRpcRequest {
10
+ readonly jsonrpc: '2.0';
11
+ readonly id: number;
12
+ readonly method: string;
13
+ readonly params: Record<string, unknown>;
14
+ }
15
+
16
+ interface JsonRpcResponse {
17
+ readonly jsonrpc?: string;
18
+ readonly id?: number | string | null;
19
+ readonly result?: unknown;
20
+ readonly error?: unknown;
21
+ }
22
+
23
+ interface PendingRequest {
24
+ resolve(response: JsonRpcResponse): void;
25
+ reject(error: Error): void;
26
+ }
27
+
28
+ function spawnOptions(commandSpec: CommandSpec): {
29
+ readonly shell: false;
30
+ readonly env: NodeJS.ProcessEnv;
31
+ readonly stdio: ['pipe', 'pipe', 'pipe'];
32
+ cwd?: string;
33
+ } {
34
+ const options: {
35
+ readonly shell: false;
36
+ readonly env: NodeJS.ProcessEnv;
37
+ readonly stdio: ['pipe', 'pipe', 'pipe'];
38
+ cwd?: string;
39
+ } = {
40
+ shell: false,
41
+ env: { ...omitProcessControlEnv(process.env), ...omitUnsafeProviderEnv(commandSpec.env) },
42
+ stdio: ['pipe', 'pipe', 'pipe'],
43
+ };
44
+ if (commandSpec.cwd !== undefined) options.cwd = commandSpec.cwd;
45
+ return options;
46
+ }
47
+
48
+ function processResult(input: {
49
+ readonly stdout: readonly Buffer[];
50
+ readonly stderr: readonly Buffer[];
51
+ readonly exitCode: number | null;
52
+ readonly signal: string | null;
53
+ readonly startedAt: number;
54
+ readonly timedOut: boolean;
55
+ readonly timeoutMs?: number;
56
+ }): ProcessResult {
57
+ return {
58
+ stdout: Buffer.concat(input.stdout).toString('utf8'),
59
+ stderr: Buffer.concat(input.stderr).toString('utf8'),
60
+ exitCode: input.exitCode,
61
+ signal: input.signal,
62
+ durationMs: Date.now() - input.startedAt,
63
+ timedOut: input.timedOut,
64
+ ...(input.timedOut && input.timeoutMs !== undefined ? { timeoutMs: input.timeoutMs } : {}),
65
+ };
66
+ }
67
+
68
+ function isRecord(value: unknown): value is Record<string, unknown> {
69
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
70
+ }
71
+
72
+ function parseProtocolLine(line: string): Record<string, unknown> {
73
+ let parsed: unknown;
74
+ try {
75
+ parsed = JSON.parse(line);
76
+ } catch (error) {
77
+ const reason = error instanceof Error ? error.message : 'Unknown JSON parse error.';
78
+ throw new Error(`malformed ACP stdout JSON: ${reason}`);
79
+ }
80
+ if (!isRecord(parsed)) throw new Error('malformed ACP stdout JSON: expected a JSON object.');
81
+ return parsed;
82
+ }
83
+
84
+ function createPromptParams(sessionId: string, prompt: string): Record<string, unknown> {
85
+ return {
86
+ sessionId,
87
+ prompt: [
88
+ {
89
+ role: 'user',
90
+ content: [{ type: 'text', text: prompt }],
91
+ },
92
+ ],
93
+ };
94
+ }
95
+
96
+ export function runAcpStdioPrompt(
97
+ provider: ProviderId,
98
+ commandSpec: CommandSpec,
99
+ prompt: string,
100
+ options: ProcessRunnerOptions = {}
101
+ ): Promise<ProcessResult> {
102
+ return new Promise<ProcessResult>((resolve, reject) => {
103
+ const startedAt = Date.now();
104
+ const stdout: Buffer[] = [];
105
+ const stderr: Buffer[] = [];
106
+ const child = spawn(commandSpec.binary, [...commandSpec.args], spawnOptions(commandSpec));
107
+ const pending = new Map<number, PendingRequest>();
108
+ let stdoutBuffer = '';
109
+ let nextId = 1;
110
+ let timedOut = false;
111
+ let protocolFailure: Error | null = null;
112
+ let sessionId: string | null = null;
113
+ let closeResolved = false;
114
+ let timeout: NodeJS.Timeout | undefined;
115
+ let timeoutKill: NodeJS.Timeout | undefined;
116
+
117
+ function cleanupTimers(): void {
118
+ if (timeout !== undefined) clearTimeout(timeout);
119
+ if (timeoutKill !== undefined) clearTimeout(timeoutKill);
120
+ }
121
+
122
+ function finalize(exitCode: number | null, signal: string | null): void {
123
+ if (closeResolved) return;
124
+ closeResolved = true;
125
+ cleanupTimers();
126
+ if (protocolFailure) {
127
+ const failureMessage = protocolFailure.message;
128
+ if (!stderr.some((chunk) => chunk.toString('utf8').includes(failureMessage))) {
129
+ stderr.push(Buffer.from(`${failureMessage}\n`, 'utf8'));
130
+ }
131
+ }
132
+ const effectiveExitCode =
133
+ protocolFailure && exitCode === 0 && signal === null ? 1 : exitCode;
134
+ resolve(
135
+ processResult({
136
+ stdout,
137
+ stderr,
138
+ exitCode: effectiveExitCode,
139
+ signal,
140
+ startedAt,
141
+ timedOut,
142
+ ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
143
+ })
144
+ );
145
+ }
146
+
147
+ function failClosed(message: string): void {
148
+ if (protocolFailure) return;
149
+ protocolFailure = new Error(`${provider} ACP stdio fail-closed: ${message}`);
150
+ for (const request of pending.values()) {
151
+ request.reject(protocolFailure);
152
+ }
153
+ pending.clear();
154
+ if (sessionId && child.stdin && !child.stdin.destroyed) {
155
+ child.stdin.write(
156
+ `${JSON.stringify({
157
+ jsonrpc: '2.0',
158
+ method: 'session/cancel',
159
+ params: { sessionId },
160
+ })}\n`
161
+ );
162
+ }
163
+ child.stdin?.end();
164
+ child.kill('SIGTERM');
165
+ }
166
+
167
+ function handleProtocolMessage(message: Record<string, unknown>): void {
168
+ const responseId = typeof message.id === 'number' ? message.id : null;
169
+ if (responseId !== null && (message.result !== undefined || message.error !== undefined)) {
170
+ const request = pending.get(responseId);
171
+ if (request) {
172
+ pending.delete(responseId);
173
+ request.resolve(message);
174
+ }
175
+ return;
176
+ }
177
+
178
+ const method = typeof message.method === 'string' ? message.method : null;
179
+ if (!method) return;
180
+ if (method === 'session/update') return;
181
+ if (method.startsWith('_')) return;
182
+ if (method === 'session/request_permission') {
183
+ failClosed('unsupported session/request_permission callback.');
184
+ return;
185
+ }
186
+ if (method.startsWith('fs/')) {
187
+ failClosed(`unsupported ${method} callback.`);
188
+ return;
189
+ }
190
+ if (method.startsWith('terminal/')) {
191
+ failClosed(`unsupported ${method} callback.`);
192
+ return;
193
+ }
194
+ if (method.startsWith('session/')) {
195
+ failClosed(`unsupported ${method} session-control callback.`);
196
+ }
197
+ }
198
+
199
+ function consumeStdoutLine(line: string): void {
200
+ try {
201
+ handleProtocolMessage(parseProtocolLine(line));
202
+ } catch (error) {
203
+ failClosed(error instanceof Error ? error.message : 'malformed ACP stdout JSON.');
204
+ }
205
+ }
206
+
207
+ function flushStdoutRemainder(): void {
208
+ const line = stdoutBuffer.trim();
209
+ stdoutBuffer = '';
210
+ if (line) consumeStdoutLine(line);
211
+ }
212
+
213
+ function flushStdout(data: Buffer): void {
214
+ stdout.push(data);
215
+ stdoutBuffer += data.toString('utf8');
216
+ let newline = stdoutBuffer.indexOf('\n');
217
+ while (newline !== -1) {
218
+ const line = stdoutBuffer.slice(0, newline).trim();
219
+ stdoutBuffer = stdoutBuffer.slice(newline + 1);
220
+ if (line) consumeStdoutLine(line);
221
+ newline = stdoutBuffer.indexOf('\n');
222
+ }
223
+ }
224
+
225
+ function sendRequest(method: string, params: Record<string, unknown>): Promise<JsonRpcResponse> {
226
+ const id = nextId;
227
+ nextId += 1;
228
+ const request: JsonRpcRequest = {
229
+ jsonrpc: '2.0',
230
+ id,
231
+ method,
232
+ params,
233
+ };
234
+ return new Promise<JsonRpcResponse>((requestResolve, requestReject) => {
235
+ pending.set(id, { resolve: requestResolve, reject: requestReject });
236
+ child.stdin?.write(`${JSON.stringify(request)}\n`);
237
+ });
238
+ }
239
+
240
+ async function driveProtocol(): Promise<void> {
241
+ const initialize = await sendRequest('initialize', {
242
+ protocolVersion: 1,
243
+ clientInfo: {
244
+ name: '@the-open-engine/zeroshot',
245
+ version: '1',
246
+ },
247
+ clientCapabilities: {
248
+ fs: false,
249
+ terminal: false,
250
+ promptCapabilities: {
251
+ image: false,
252
+ },
253
+ },
254
+ });
255
+ if (initialize.error !== undefined) {
256
+ child.stdin?.end();
257
+ return;
258
+ }
259
+
260
+ const session = await sendRequest('session/new', {
261
+ cwd: commandSpec.cwd ?? process.cwd(),
262
+ mcpServers: [],
263
+ });
264
+ if (session.error !== undefined) {
265
+ child.stdin?.end();
266
+ return;
267
+ }
268
+ const sessionResult = isRecord(session.result) ? session.result : {};
269
+ const nextSessionId = typeof sessionResult.sessionId === 'string' ? sessionResult.sessionId : null;
270
+ if (!nextSessionId) {
271
+ failClosed('session/new response omitted sessionId.');
272
+ return;
273
+ }
274
+ sessionId = nextSessionId;
275
+
276
+ await sendRequest('session/prompt', createPromptParams(sessionId, prompt));
277
+ child.stdin?.end();
278
+ }
279
+
280
+ if (options.timeoutMs !== undefined) {
281
+ timeout = setTimeout(() => {
282
+ timedOut = true;
283
+ if (sessionId && child.stdin && !child.stdin.destroyed) {
284
+ child.stdin.write(
285
+ `${JSON.stringify({
286
+ jsonrpc: '2.0',
287
+ method: 'session/cancel',
288
+ params: { sessionId },
289
+ })}\n`
290
+ );
291
+ }
292
+ child.kill('SIGTERM');
293
+ timeoutKill = setTimeout(() => {
294
+ if (!closeResolved) child.kill('SIGKILL');
295
+ }, options.timeoutKillGraceMs ?? DEFAULT_TIMEOUT_KILL_GRACE_MS);
296
+ }, options.timeoutMs);
297
+ }
298
+
299
+ child.stdout?.on('data', flushStdout);
300
+ child.stdout?.once('end', flushStdoutRemainder);
301
+ child.stderr?.on('data', (data: Buffer) => stderr.push(data));
302
+ child.once('error', (error) => {
303
+ cleanupTimers();
304
+ reject(error);
305
+ });
306
+ child.once('close', (exitCode, signal) => {
307
+ finalize(exitCode, signal);
308
+ });
309
+
310
+ driveProtocol().catch((error: unknown) => {
311
+ failClosed(error instanceof Error ? error.message : 'ACP protocol failed.');
312
+ });
313
+ });
314
+ }