@the-open-engine/zeroshot 6.17.0 → 6.18.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/cli/index.js +9 -13
- package/lib/agent-cli-provider/adapters/claude.d.ts +2 -2
- package/lib/agent-cli-provider/adapters/claude.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/claude.js +30 -0
- package/lib/agent-cli-provider/adapters/claude.js.map +1 -1
- package/lib/agent-cli-provider/adapters/codex.d.ts +2 -2
- package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/codex.js +37 -0
- package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
- package/lib/agent-cli-provider/adapters/gemini.d.ts +2 -2
- package/lib/agent-cli-provider/adapters/gemini.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/gemini.js +115 -4
- package/lib/agent-cli-provider/adapters/gemini.js.map +1 -1
- package/lib/agent-cli-provider/adapters/opencode.d.ts +2 -2
- package/lib/agent-cli-provider/adapters/opencode.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/opencode.js +108 -0
- package/lib/agent-cli-provider/adapters/opencode.js.map +1 -1
- package/lib/agent-cli-provider/contract-options.d.ts.map +1 -1
- package/lib/agent-cli-provider/contract-options.js +12 -0
- package/lib/agent-cli-provider/contract-options.js.map +1 -1
- package/lib/agent-cli-provider/index.d.ts +2 -2
- package/lib/agent-cli-provider/index.d.ts.map +1 -1
- package/lib/agent-cli-provider/index.js +2 -1
- package/lib/agent-cli-provider/index.js.map +1 -1
- package/lib/agent-cli-provider/provider-registry.d.ts +19 -7
- package/lib/agent-cli-provider/provider-registry.d.ts.map +1 -1
- package/lib/agent-cli-provider/provider-registry.js +4 -0
- package/lib/agent-cli-provider/provider-registry.js.map +1 -1
- package/lib/agent-cli-provider/single-agent-runtime.d.ts.map +1 -1
- package/lib/agent-cli-provider/single-agent-runtime.js +35 -4
- package/lib/agent-cli-provider/single-agent-runtime.js.map +1 -1
- package/lib/agent-cli-provider/types.d.ts +30 -3
- package/lib/agent-cli-provider/types.d.ts.map +1 -1
- package/lib/agent-cli-provider/types.js.map +1 -1
- package/lib/cluster/errors.cjs +4 -1
- package/lib/cluster/errors.d.ts +2 -0
- package/lib/cluster/errors.mjs +2 -0
- package/lib/cluster/index.cjs +8 -1
- package/lib/cluster/index.d.ts +4 -1
- package/lib/cluster/index.mjs +4 -1
- package/lib/cluster/json-source.cjs +61 -0
- package/lib/cluster/json-source.d.ts +4 -0
- package/lib/cluster/json-source.mjs +55 -0
- package/lib/cluster/payload-value.cjs +76 -0
- package/lib/cluster/payload-value.d.ts +7 -0
- package/lib/cluster/payload-value.mjs +72 -0
- package/lib/cluster/validators.cjs +21 -0
- package/lib/cluster/validators.d.ts +4 -1
- package/lib/cluster/validators.mjs +19 -1
- package/lib/provider-names.js +5 -0
- package/package.json +2 -2
- package/src/agent/agent-task-executor.js +194 -410
- package/src/agent/output-extraction.js +39 -14
- package/src/agent/output-reformatter.js +154 -111
- package/src/agent-cli-provider/adapters/claude.ts +39 -2
- package/src/agent-cli-provider/adapters/codex.ts +56 -2
- package/src/agent-cli-provider/adapters/gemini.ts +102 -6
- package/src/agent-cli-provider/adapters/opencode.ts +85 -2
- package/src/agent-cli-provider/contract-options.ts +16 -0
- package/src/agent-cli-provider/index.ts +4 -0
- package/src/agent-cli-provider/provider-registry.ts +23 -3
- package/src/agent-cli-provider/single-agent-runtime.ts +50 -4
- package/src/agent-cli-provider/types.ts +36 -2
- package/src/agent-wrapper.js +2 -2
- package/src/cluster/errors.ts +1 -0
- package/src/cluster/index.ts +4 -0
- package/src/cluster/json-source.ts +71 -0
- package/src/cluster/payload-value.ts +84 -0
- package/src/cluster/validators.ts +31 -2
- package/src/orchestrator.js +33 -13
- package/task-lib/attachable-watcher.js +1 -0
- package/task-lib/command-spec-cleanup.js +57 -11
- package/task-lib/commands/run.js +1 -0
- package/task-lib/provider-session-capture.js +8 -0
- package/task-lib/runner.js +9 -6
- package/task-lib/watcher.js +1 -0
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
|
|
6
|
+
import { UnsupportedProviderCapabilityError } from '../errors';
|
|
1
7
|
import { appendJsonSchemaPrompt } from '../schema';
|
|
2
8
|
import {
|
|
3
9
|
getOrStringFromKeys,
|
|
@@ -16,7 +22,7 @@ import {
|
|
|
16
22
|
type ModelCatalogEntry,
|
|
17
23
|
type ModelLevel,
|
|
18
24
|
type OutputEvent,
|
|
19
|
-
type
|
|
25
|
+
type StructuredOutputRecoveryAdapter,
|
|
20
26
|
type ProviderParserState,
|
|
21
27
|
type ResolvedModelSpec,
|
|
22
28
|
type WarningMetadata,
|
|
@@ -52,6 +58,7 @@ function detectCliFeatures(helpText?: string | null): GeminiCliFeatures {
|
|
|
52
58
|
supportsAutoApprove: unknown ? true : /--yolo\b/.test(help),
|
|
53
59
|
supportsCwd: unknown ? true : /--cwd\b/.test(help),
|
|
54
60
|
supportsModel: unknown ? true : /\s-m\b/.test(help) || /--model\b/.test(help),
|
|
61
|
+
supportsAdminPolicy: !unknown && /--admin-policy\b/.test(help),
|
|
55
62
|
unknown,
|
|
56
63
|
};
|
|
57
64
|
}
|
|
@@ -109,6 +116,75 @@ function buildCommand(context: string, options: BuildProviderCommandOptions = {}
|
|
|
109
116
|
});
|
|
110
117
|
}
|
|
111
118
|
|
|
119
|
+
function standardAdminPolicyDirectory(): string {
|
|
120
|
+
if (process.platform === 'darwin') {
|
|
121
|
+
return '/Library/Application Support/GeminiCli/policies';
|
|
122
|
+
}
|
|
123
|
+
if (process.platform === 'win32') {
|
|
124
|
+
return path.join(process.env.ProgramData || 'C:\\ProgramData', 'gemini-cli', 'policies');
|
|
125
|
+
}
|
|
126
|
+
return '/etc/gemini-cli/policies';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function assertSupplementalAdminPolicyEffective(): void {
|
|
130
|
+
const directory = standardAdminPolicyDirectory();
|
|
131
|
+
let entries: fs.Dirent[];
|
|
132
|
+
try {
|
|
133
|
+
entries = fs.readdirSync(directory, { withFileTypes: true });
|
|
134
|
+
} catch (error) {
|
|
135
|
+
if (isRecord(error) && error.code === 'ENOENT') return;
|
|
136
|
+
throw new UnsupportedProviderCapabilityError(
|
|
137
|
+
'gemini',
|
|
138
|
+
'structuredOutputRecovery',
|
|
139
|
+
`Gemini structured-output recovery cannot inspect the standard admin-policy directory ${directory}; refuse a supplemental policy that may be ignored.`
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
if (!entries.some((entry) => entry.isFile() && entry.name.endsWith('.toml'))) return;
|
|
143
|
+
throw new UnsupportedProviderCapabilityError(
|
|
144
|
+
'gemini',
|
|
145
|
+
'structuredOutputRecovery',
|
|
146
|
+
`Gemini ignores --admin-policy when ${directory} contains TOML policies. Remove the conflict or use an administrator-managed deny-all policy before retrying.`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function writeRecoveryAdminPolicy(): string {
|
|
151
|
+
const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'zeroshot-gemini-policy-'));
|
|
152
|
+
const policyPath = path.join(directory, `${randomUUID()}.toml`);
|
|
153
|
+
fs.writeFileSync(policyPath, '[[rule]]\ntoolName = "*"\ndecision = "deny"\npriority = 999\n', {
|
|
154
|
+
flag: 'wx',
|
|
155
|
+
mode: 0o600,
|
|
156
|
+
});
|
|
157
|
+
return policyPath;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function buildStructuredOutputRecoveryCommand(
|
|
161
|
+
context: string,
|
|
162
|
+
options: BuildProviderCommandOptions = {}
|
|
163
|
+
): CommandSpec {
|
|
164
|
+
if (optionFeatures(options).supportsAdminPolicy !== true) {
|
|
165
|
+
throw new UnsupportedProviderCapabilityError(
|
|
166
|
+
'gemini',
|
|
167
|
+
'structuredOutputRecovery',
|
|
168
|
+
'Gemini structured-output recovery requires CLI evidence for --admin-policy. Upgrade @google/gemini-cli before retrying.'
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
assertSupplementalAdminPolicyEffective();
|
|
172
|
+
const recoveryOptions = { ...options };
|
|
173
|
+
delete recoveryOptions.resumeSessionId;
|
|
174
|
+
delete recoveryOptions.continueSession;
|
|
175
|
+
const spec = buildCommand(context, { ...recoveryOptions, autoApprove: false });
|
|
176
|
+
const policyPath = writeRecoveryAdminPolicy();
|
|
177
|
+
return {
|
|
178
|
+
...spec,
|
|
179
|
+
args: ['--admin-policy', policyPath, ...spec.args],
|
|
180
|
+
cleanup: [...(spec.cleanup || []), policyPath],
|
|
181
|
+
cleanupMetadata: [
|
|
182
|
+
...spec.cleanupMetadata,
|
|
183
|
+
{ kind: 'temp-file', provider: 'gemini', path: policyPath, reason: 'admin-policy' },
|
|
184
|
+
],
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
112
188
|
function normalizeMessageContent(content: unknown): string {
|
|
113
189
|
if (typeof content === 'string') return content;
|
|
114
190
|
if (Array.isArray(content)) {
|
|
@@ -148,6 +224,11 @@ function parseToolUseEvent(
|
|
|
148
224
|
};
|
|
149
225
|
}
|
|
150
226
|
|
|
227
|
+
function geminiErrorMessage(event: Record<string, unknown>, fallback: string): string {
|
|
228
|
+
const error = isRecord(event.error) ? event.error : null;
|
|
229
|
+
return (error && getString(error, 'message')) || getString(event, 'message') || fallback;
|
|
230
|
+
}
|
|
231
|
+
|
|
151
232
|
function parseToolResultEvent(
|
|
152
233
|
event: Record<string, unknown>,
|
|
153
234
|
state: ProviderParserState
|
|
@@ -157,20 +238,32 @@ function parseToolResultEvent(
|
|
|
157
238
|
['tool_call_id', 'tool_id', 'id'],
|
|
158
239
|
state.lastToolId
|
|
159
240
|
);
|
|
241
|
+
const isError = getString(event, 'status') === 'error';
|
|
160
242
|
return {
|
|
161
243
|
type: 'tool_result',
|
|
162
244
|
toolId,
|
|
163
|
-
content: event.output ?? event
|
|
164
|
-
isError
|
|
245
|
+
content: event.output ?? (isError ? geminiErrorMessage(event, 'Tool failed') : ''),
|
|
246
|
+
isError,
|
|
165
247
|
};
|
|
166
248
|
}
|
|
167
249
|
|
|
168
250
|
function parseResultEvent(event: Record<string, unknown>): OutputEvent {
|
|
251
|
+
const success = getString(event, 'status') === 'success';
|
|
169
252
|
return {
|
|
170
253
|
type: 'result',
|
|
171
|
-
success
|
|
254
|
+
success,
|
|
172
255
|
result: event.result || '',
|
|
173
|
-
error:
|
|
256
|
+
error: success ? null : geminiErrorMessage(event, 'Result failed'),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function parseErrorEvent(event: Record<string, unknown>): OutputEvent | null {
|
|
261
|
+
if (getString(event, 'severity') !== 'error') return null;
|
|
262
|
+
return {
|
|
263
|
+
type: 'result',
|
|
264
|
+
success: false,
|
|
265
|
+
result: '',
|
|
266
|
+
error: getString(event, 'message') || 'Gemini CLI error',
|
|
174
267
|
};
|
|
175
268
|
}
|
|
176
269
|
|
|
@@ -189,6 +282,8 @@ function parseEvent(line: string, state: ProviderParserState): OutputEvent | nul
|
|
|
189
282
|
return parseToolResultEvent(event, state);
|
|
190
283
|
case 'result':
|
|
191
284
|
return parseResultEvent(event);
|
|
285
|
+
case 'error':
|
|
286
|
+
return parseErrorEvent(event);
|
|
192
287
|
default:
|
|
193
288
|
return null;
|
|
194
289
|
}
|
|
@@ -229,7 +324,7 @@ function classifyError(error: unknown): ErrorClassification {
|
|
|
229
324
|
);
|
|
230
325
|
}
|
|
231
326
|
|
|
232
|
-
export const geminiAdapter:
|
|
327
|
+
export const geminiAdapter: StructuredOutputRecoveryAdapter = {
|
|
233
328
|
id: 'gemini',
|
|
234
329
|
displayName: 'Gemini',
|
|
235
330
|
binary: 'gemini',
|
|
@@ -242,6 +337,7 @@ export const geminiAdapter: ProviderAdapter = {
|
|
|
242
337
|
defaultMinLevel: 'level1',
|
|
243
338
|
detectCliFeatures,
|
|
244
339
|
buildCommand,
|
|
340
|
+
buildStructuredOutputRecoveryCommand,
|
|
245
341
|
parseEvent,
|
|
246
342
|
createParserState: () => createParserState('gemini'),
|
|
247
343
|
resolveModelSpec,
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { contractError } from '../contract-errors';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import * as fs from 'node:fs';
|
|
4
|
+
import * as os from 'node:os';
|
|
5
|
+
import * as path from 'node:path';
|
|
2
6
|
import { UnsupportedProviderCapabilityError } from '../errors';
|
|
3
7
|
import { appendJsonSchemaPrompt } from '../schema';
|
|
4
8
|
import {
|
|
@@ -15,7 +19,7 @@ import {
|
|
|
15
19
|
type ErrorClassification,
|
|
16
20
|
type OpencodeCliFeatures,
|
|
17
21
|
type OutputEvent,
|
|
18
|
-
type
|
|
22
|
+
type StructuredOutputRecoveryAdapter,
|
|
19
23
|
type WarningMetadata,
|
|
20
24
|
} from '../types';
|
|
21
25
|
import {
|
|
@@ -49,7 +53,9 @@ function detectCliFeatures(
|
|
|
49
53
|
supportsCwd: unknown ? false : /--cwd\b/.test(help),
|
|
50
54
|
supportsAutoApprove: false,
|
|
51
55
|
supportsResume: !unknown && /--session\b/.test(help) && /--continue\b/.test(help),
|
|
56
|
+
supportsAgent: !unknown && /--agent\b/.test(help),
|
|
52
57
|
supportsWebSearch: isCliVersionAtLeast(versionText, '1.0.137'),
|
|
58
|
+
supportsRecoveryIsolation: isCliVersionAtLeast(versionText, '1.17.20'),
|
|
53
59
|
unknown,
|
|
54
60
|
};
|
|
55
61
|
}
|
|
@@ -162,6 +168,82 @@ function buildCommand(context: string, options: BuildProviderCommandOptions = {}
|
|
|
162
168
|
});
|
|
163
169
|
}
|
|
164
170
|
|
|
171
|
+
function buildStructuredOutputRecoveryCommand(
|
|
172
|
+
context: string,
|
|
173
|
+
options: BuildProviderCommandOptions = {}
|
|
174
|
+
): CommandSpec {
|
|
175
|
+
const features = optionFeatures(options);
|
|
176
|
+
if (features.supportsAgent !== true || features.supportsRecoveryIsolation !== true) {
|
|
177
|
+
throw new UnsupportedProviderCapabilityError(
|
|
178
|
+
'opencode',
|
|
179
|
+
'structuredOutputRecovery',
|
|
180
|
+
'OpenCode structured-output recovery requires CLI evidence for --agent and isolation controls available in OpenCode >= 1.17.20. Upgrade OpenCode before retrying.'
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
const agentName = `zeroshot-output-reformatter-${randomUUID()}`;
|
|
184
|
+
const profile = {
|
|
185
|
+
description: 'Convert supplied text to schema-valid JSON without external actions',
|
|
186
|
+
mode: 'primary',
|
|
187
|
+
permission: { '*': 'deny' },
|
|
188
|
+
tools: { '*': false },
|
|
189
|
+
};
|
|
190
|
+
const recoveryOptions = { ...options };
|
|
191
|
+
delete recoveryOptions.resumeSessionId;
|
|
192
|
+
delete recoveryOptions.continueSession;
|
|
193
|
+
const isolatedConfigHome = fs.mkdtempSync(path.join(os.tmpdir(), 'zeroshot-opencode-config-'));
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
const spec = buildCommand(context, {
|
|
197
|
+
...recoveryOptions,
|
|
198
|
+
agentName,
|
|
199
|
+
autoApprove: false,
|
|
200
|
+
webSearch: false,
|
|
201
|
+
});
|
|
202
|
+
const restrictedConfig = {
|
|
203
|
+
default_agent: agentName,
|
|
204
|
+
permission: { '*': 'deny' },
|
|
205
|
+
tools: { '*': false },
|
|
206
|
+
agent: { [agentName]: profile },
|
|
207
|
+
mode: { [agentName]: profile },
|
|
208
|
+
mcp: {},
|
|
209
|
+
instructions: [],
|
|
210
|
+
plugin: [],
|
|
211
|
+
command: {},
|
|
212
|
+
};
|
|
213
|
+
return {
|
|
214
|
+
...spec,
|
|
215
|
+
env: {
|
|
216
|
+
...spec.env,
|
|
217
|
+
ZEROSHOT_OPENCODE_AGENT: agentName,
|
|
218
|
+
XDG_CONFIG_HOME: isolatedConfigHome,
|
|
219
|
+
OPENCODE_DB: ':memory:',
|
|
220
|
+
OPENCODE_CONFIG: '',
|
|
221
|
+
OPENCODE_CONFIG_DIR: isolatedConfigHome,
|
|
222
|
+
OPENCODE_CONFIG_CONTENT: JSON.stringify(restrictedConfig),
|
|
223
|
+
OPENCODE_PERMISSION: JSON.stringify({ '*': 'deny' }),
|
|
224
|
+
OPENCODE_DISABLE_PROJECT_CONFIG: '1',
|
|
225
|
+
OPENCODE_PURE: '1',
|
|
226
|
+
OPENCODE_DISABLE_DEFAULT_PLUGINS: '1',
|
|
227
|
+
OPENCODE_DISABLE_EXTERNAL_SKILLS: '1',
|
|
228
|
+
OPENCODE_DISABLE_CLAUDE_CODE: '1',
|
|
229
|
+
},
|
|
230
|
+
cleanup: [...(spec.cleanup || []), isolatedConfigHome],
|
|
231
|
+
cleanupMetadata: [
|
|
232
|
+
...(spec.cleanupMetadata || []),
|
|
233
|
+
{
|
|
234
|
+
kind: 'temp-directory',
|
|
235
|
+
provider: 'opencode',
|
|
236
|
+
path: isolatedConfigHome,
|
|
237
|
+
reason: 'isolated-config',
|
|
238
|
+
},
|
|
239
|
+
],
|
|
240
|
+
};
|
|
241
|
+
} catch (error) {
|
|
242
|
+
fs.rmSync(isolatedConfigHome, { recursive: true, force: true });
|
|
243
|
+
throw error;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
165
247
|
function parseToolPart(part: Record<string, unknown>): OutputEvent | null {
|
|
166
248
|
const state = getRecord(part, 'state') ?? {};
|
|
167
249
|
const status = getString(state, 'status');
|
|
@@ -262,7 +344,7 @@ function classifyError(error: unknown): ErrorClassification {
|
|
|
262
344
|
return classifyBaseProviderError(error, [], []);
|
|
263
345
|
}
|
|
264
346
|
|
|
265
|
-
export const opencodeAdapter:
|
|
347
|
+
export const opencodeAdapter: StructuredOutputRecoveryAdapter = {
|
|
266
348
|
id: 'opencode',
|
|
267
349
|
displayName: 'Opencode',
|
|
268
350
|
binary: 'opencode',
|
|
@@ -281,6 +363,7 @@ export const opencodeAdapter: ProviderAdapter = {
|
|
|
281
363
|
defaultMinLevel: 'level1',
|
|
282
364
|
detectCliFeatures,
|
|
283
365
|
buildCommand,
|
|
366
|
+
buildStructuredOutputRecoveryCommand,
|
|
284
367
|
extractSessionId,
|
|
285
368
|
parseEvent,
|
|
286
369
|
createParserState: () => createParserState('opencode'),
|
|
@@ -24,6 +24,9 @@ const CLI_FEATURE_FIELDS = [
|
|
|
24
24
|
'supportsModel',
|
|
25
25
|
'supportsEffort',
|
|
26
26
|
'supportsSettings',
|
|
27
|
+
'supportsTools',
|
|
28
|
+
'supportsStrictMcpConfig',
|
|
29
|
+
'supportsNoSessionPersistence',
|
|
27
30
|
'supportsJson',
|
|
28
31
|
'supportsOutputSchema',
|
|
29
32
|
'supportsDir',
|
|
@@ -31,8 +34,16 @@ const CLI_FEATURE_FIELDS = [
|
|
|
31
34
|
'supportsConfigOverride',
|
|
32
35
|
'supportsSkipGitRepoCheck',
|
|
33
36
|
'supportsVariant',
|
|
37
|
+
'supportsSandbox',
|
|
38
|
+
'supportsEphemeral',
|
|
39
|
+
'supportsIgnoreUserConfig',
|
|
40
|
+
'supportsIgnoreRules',
|
|
41
|
+
'supportsStrictConfig',
|
|
34
42
|
'supportsJsonMode',
|
|
43
|
+
'supportsAdminPolicy',
|
|
35
44
|
'supportsNoSession',
|
|
45
|
+
'supportsAgent',
|
|
46
|
+
'supportsRecoveryIsolation',
|
|
36
47
|
'supportsNoExtensions',
|
|
37
48
|
'supportsNoSkills',
|
|
38
49
|
'supportsNoPromptTemplates',
|
|
@@ -229,6 +240,11 @@ function normalizeBuildOptions(value: Record<string, unknown>): BuildProviderCom
|
|
|
229
240
|
'strictSchema',
|
|
230
241
|
optionalBooleanValue(value.strictSchema, 'options.strictSchema')
|
|
231
242
|
);
|
|
243
|
+
addDefined(
|
|
244
|
+
result,
|
|
245
|
+
'structuredOutputRecovery',
|
|
246
|
+
optionalBooleanValue(value.structuredOutputRecovery, 'options.structuredOutputRecovery')
|
|
247
|
+
);
|
|
232
248
|
addDefined(
|
|
233
249
|
result,
|
|
234
250
|
'gateway',
|
|
@@ -53,6 +53,7 @@ export {
|
|
|
53
53
|
providerRegistry,
|
|
54
54
|
resolveProviderCommand,
|
|
55
55
|
supportsProviderCapability,
|
|
56
|
+
supportsProviderOutputReformatting,
|
|
56
57
|
} from './provider-registry';
|
|
57
58
|
|
|
58
59
|
export type {
|
|
@@ -93,6 +94,9 @@ export type {
|
|
|
93
94
|
ProviderCliFeatures,
|
|
94
95
|
ProviderId,
|
|
95
96
|
ProviderRegistryEntry,
|
|
97
|
+
StructuredOutputRecoveryAdapter,
|
|
98
|
+
StructuredOutputProviderRegistryEntry,
|
|
99
|
+
UnstructuredOutputProviderRegistryEntry,
|
|
96
100
|
RedactionMetadata,
|
|
97
101
|
ReasoningEffort,
|
|
98
102
|
ResolvedGatewayBuildOptions,
|
|
@@ -8,7 +8,7 @@ import { opencodeAdapter } from './adapters/opencode';
|
|
|
8
8
|
import { ompAdapter } from './adapters/omp';
|
|
9
9
|
import { piAdapter } from './adapters/pi';
|
|
10
10
|
import { resolveClaudeCommand } from './claude-command';
|
|
11
|
-
import type { ModelLevel, ProviderAdapter } from './types';
|
|
11
|
+
import type { ModelLevel, ProviderAdapter, StructuredOutputRecoveryAdapter } from './types';
|
|
12
12
|
|
|
13
13
|
export type ProviderCapabilityState = boolean | 'experimental';
|
|
14
14
|
|
|
@@ -69,7 +69,7 @@ export interface ProviderDockerMetadata {
|
|
|
69
69
|
readonly install?: string;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
interface ProviderRegistryEntryBase {
|
|
73
73
|
readonly id: string;
|
|
74
74
|
readonly aliases: readonly string[];
|
|
75
75
|
readonly displayName: string;
|
|
@@ -84,7 +84,6 @@ export interface ProviderRegistryEntry {
|
|
|
84
84
|
readonly settingsDefaults?: Readonly<Record<string, unknown>>;
|
|
85
85
|
readonly settingsValidator?: (settings: Record<string, unknown>) => string | null;
|
|
86
86
|
readonly availabilityProbe?: 'command' | 'help-or-version';
|
|
87
|
-
readonly capabilities: ProviderCapabilities;
|
|
88
87
|
readonly docs: ProviderDocsMetadata;
|
|
89
88
|
readonly docker: ProviderDockerMetadata;
|
|
90
89
|
readonly defaultLevels: Readonly<{
|
|
@@ -92,9 +91,26 @@ export interface ProviderRegistryEntry {
|
|
|
92
91
|
readonly default: ModelLevel;
|
|
93
92
|
readonly max: ModelLevel;
|
|
94
93
|
}>;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface StructuredOutputProviderRegistryEntry extends ProviderRegistryEntryBase {
|
|
97
|
+
readonly capabilities: Omit<ProviderCapabilities, 'jsonSchema'> & {
|
|
98
|
+
readonly jsonSchema: true | 'experimental';
|
|
99
|
+
};
|
|
100
|
+
readonly adapter: StructuredOutputRecoveryAdapter;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface UnstructuredOutputProviderRegistryEntry extends ProviderRegistryEntryBase {
|
|
104
|
+
readonly capabilities: Omit<ProviderCapabilities, 'jsonSchema'> & {
|
|
105
|
+
readonly jsonSchema: false;
|
|
106
|
+
};
|
|
95
107
|
readonly adapter: ProviderAdapter;
|
|
96
108
|
}
|
|
97
109
|
|
|
110
|
+
export type ProviderRegistryEntry =
|
|
111
|
+
| StructuredOutputProviderRegistryEntry
|
|
112
|
+
| UnstructuredOutputProviderRegistryEntry;
|
|
113
|
+
|
|
98
114
|
const STANDARD_CAPABILITIES: Readonly<
|
|
99
115
|
Pick<
|
|
100
116
|
ProviderCapabilities,
|
|
@@ -590,3 +606,7 @@ export function supportsProviderCapability(
|
|
|
590
606
|
): boolean {
|
|
591
607
|
return getProviderRegistryEntry(name).capabilities[capability] === true;
|
|
592
608
|
}
|
|
609
|
+
|
|
610
|
+
export function supportsProviderOutputReformatting(name: string): boolean {
|
|
611
|
+
return getProviderRegistryEntry(name).capabilities.jsonSchema !== false;
|
|
612
|
+
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
getProviderRegistryEntry,
|
|
7
7
|
resolveProviderCommand,
|
|
8
8
|
supportsProviderCapability,
|
|
9
|
+
supportsProviderOutputReformatting,
|
|
9
10
|
} from './provider-registry';
|
|
10
11
|
import type {
|
|
11
12
|
BuildProviderCommandOptions,
|
|
@@ -16,6 +17,7 @@ import type {
|
|
|
16
17
|
ModelLevel,
|
|
17
18
|
ModelSpec,
|
|
18
19
|
ProviderAdapter,
|
|
20
|
+
StructuredOutputRecoveryAdapter,
|
|
19
21
|
ProviderCliFeatures,
|
|
20
22
|
ProviderId,
|
|
21
23
|
ResolvedGatewayBuildOptions,
|
|
@@ -106,7 +108,9 @@ export function prepareSingleAgentProviderCommand(
|
|
|
106
108
|
adapter.id,
|
|
107
109
|
baseOptions.cwd ?? process.cwd()
|
|
108
110
|
);
|
|
109
|
-
const requestedWebSearch = baseOptions.
|
|
111
|
+
const requestedWebSearch = baseOptions.structuredOutputRecovery
|
|
112
|
+
? recoveryWebSearchOption(adapter)
|
|
113
|
+
: (baseOptions.webSearch ?? providerSettings.webSearch);
|
|
110
114
|
assertWebSearchDeclared(adapter.id, requestedWebSearch);
|
|
111
115
|
const cliFeatures = resolveRuntimeCliFeatures(
|
|
112
116
|
adapter.id,
|
|
@@ -125,10 +129,37 @@ export function prepareSingleAgentProviderCommand(
|
|
|
125
129
|
configuration: {
|
|
126
130
|
webSearch: webSearchAttestation(options),
|
|
127
131
|
},
|
|
128
|
-
commandSpec: adapter
|
|
132
|
+
commandSpec: buildRuntimeCommand(adapter, input.context, options),
|
|
129
133
|
};
|
|
130
134
|
}
|
|
131
135
|
|
|
136
|
+
function buildRuntimeCommand(
|
|
137
|
+
adapter: ProviderAdapter,
|
|
138
|
+
context: string,
|
|
139
|
+
options: BuildProviderCommandOptions
|
|
140
|
+
): CommandSpec {
|
|
141
|
+
if (options.structuredOutputRecovery !== true) {
|
|
142
|
+
return adapter.buildCommand(context, options);
|
|
143
|
+
}
|
|
144
|
+
if (!supportsProviderOutputReformatting(adapter.id)) {
|
|
145
|
+
throw new UnsupportedProviderCapabilityError(
|
|
146
|
+
adapter.id,
|
|
147
|
+
'structuredOutputRecovery',
|
|
148
|
+
`Provider ${adapter.id} does not advertise structured-output recovery.`
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
const recoveryAdapter = adapter as ProviderAdapter &
|
|
152
|
+
Partial<StructuredOutputRecoveryAdapter>;
|
|
153
|
+
if (typeof recoveryAdapter.buildStructuredOutputRecoveryCommand !== 'function') {
|
|
154
|
+
throw new UnsupportedProviderCapabilityError(
|
|
155
|
+
adapter.id,
|
|
156
|
+
'structuredOutputRecovery',
|
|
157
|
+
`Provider ${adapter.id} advertises structured output without a recovery adapter. Upgrade Zeroshot before retrying.`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
return recoveryAdapter.buildStructuredOutputRecoveryCommand(context, options);
|
|
161
|
+
}
|
|
162
|
+
|
|
132
163
|
export function detectRuntimeProviderCliFeatures(provider: string): ProviderCliFeatures {
|
|
133
164
|
return probeRuntimeProviderCli(provider).capabilities;
|
|
134
165
|
}
|
|
@@ -262,15 +293,26 @@ function buildRuntimeOptions(
|
|
|
262
293
|
providerSettings,
|
|
263
294
|
modelSpec
|
|
264
295
|
);
|
|
265
|
-
const webSearch = baseOptions.
|
|
296
|
+
const webSearch = baseOptions.structuredOutputRecovery
|
|
297
|
+
? recoveryWebSearchOption(adapter)
|
|
298
|
+
: (baseOptions.webSearch ?? providerSettings.webSearch);
|
|
266
299
|
assertWebSearchDeclared(adapter.id, webSearch);
|
|
267
|
-
const
|
|
300
|
+
const baseResolved = {
|
|
268
301
|
...baseOptions,
|
|
269
302
|
modelSpec,
|
|
270
303
|
...(gateway === undefined ? {} : { gateway }),
|
|
271
304
|
...(webSearch === undefined ? {} : { webSearch }),
|
|
272
305
|
cliFeatures: runtime.cliFeatures,
|
|
273
306
|
};
|
|
307
|
+
const resolved = { ...baseResolved };
|
|
308
|
+
if (baseOptions.structuredOutputRecovery) {
|
|
309
|
+
delete resolved.resumeSessionId;
|
|
310
|
+
delete resolved.continueSession;
|
|
311
|
+
delete resolved.mcpConfig;
|
|
312
|
+
resolved.autoApprove = false;
|
|
313
|
+
if (recoveryWebSearchOption(adapter) === undefined) delete resolved.webSearch;
|
|
314
|
+
else resolved.webSearch = false;
|
|
315
|
+
}
|
|
274
316
|
if (baseOptions.jsonSchema && !supportsProviderCapability(adapter.id, 'jsonSchema')) {
|
|
275
317
|
if (!shouldIncludeAuthEnv(baseOptions, runtime.authEnv)) {
|
|
276
318
|
return { ...resolved, strictSchema: false };
|
|
@@ -281,6 +323,10 @@ function buildRuntimeOptions(
|
|
|
281
323
|
return { ...resolved, authEnv: runtime.authEnv };
|
|
282
324
|
}
|
|
283
325
|
|
|
326
|
+
function recoveryWebSearchOption(adapter: ProviderAdapter): false | undefined {
|
|
327
|
+
return getProviderRegistryEntry(adapter.id).capabilities.webSearch === false ? undefined : false;
|
|
328
|
+
}
|
|
329
|
+
|
|
284
330
|
function resolveRuntimeGatewayOptions(
|
|
285
331
|
provider: ProviderId,
|
|
286
332
|
baseOptions: BuildProviderCommandOptions,
|
|
@@ -9,6 +9,8 @@ import type {
|
|
|
9
9
|
ProviderDocsMetadata,
|
|
10
10
|
ProviderInvokeSpec,
|
|
11
11
|
ProviderRegistryEntry,
|
|
12
|
+
StructuredOutputProviderRegistryEntry,
|
|
13
|
+
UnstructuredOutputProviderRegistryEntry,
|
|
12
14
|
} from './provider-registry';
|
|
13
15
|
|
|
14
16
|
export type ProviderId = (typeof providerIds)[number];
|
|
@@ -27,8 +29,9 @@ export type {
|
|
|
27
29
|
ProviderDocsMetadata,
|
|
28
30
|
ProviderInvokeSpec,
|
|
29
31
|
ProviderRegistryEntry,
|
|
32
|
+
StructuredOutputProviderRegistryEntry,
|
|
33
|
+
UnstructuredOutputProviderRegistryEntry,
|
|
30
34
|
};
|
|
31
|
-
|
|
32
35
|
export interface AgentCliProviderHelperMetadata {
|
|
33
36
|
readonly packageName: '@the-open-engine/zeroshot';
|
|
34
37
|
readonly buildOutputDir: 'lib/agent-cli-provider';
|
|
@@ -105,6 +108,9 @@ export interface ClaudeCliFeatures extends BaseCliFeatures {
|
|
|
105
108
|
readonly supportsSettings: boolean;
|
|
106
109
|
readonly supportsMcpConfig: boolean;
|
|
107
110
|
readonly supportsResume: boolean;
|
|
111
|
+
readonly supportsTools: boolean;
|
|
112
|
+
readonly supportsStrictMcpConfig: boolean;
|
|
113
|
+
readonly supportsNoSessionPersistence: boolean;
|
|
108
114
|
}
|
|
109
115
|
|
|
110
116
|
export interface CodexCliFeatures extends BaseCliFeatures {
|
|
@@ -118,6 +124,11 @@ export interface CodexCliFeatures extends BaseCliFeatures {
|
|
|
118
124
|
readonly supportsSkipGitRepoCheck: boolean;
|
|
119
125
|
readonly supportsResume: boolean;
|
|
120
126
|
readonly supportsWebSearch: boolean;
|
|
127
|
+
readonly supportsSandbox: boolean;
|
|
128
|
+
readonly supportsEphemeral: boolean;
|
|
129
|
+
readonly supportsIgnoreUserConfig: boolean;
|
|
130
|
+
readonly supportsIgnoreRules: boolean;
|
|
131
|
+
readonly supportsStrictConfig: boolean;
|
|
121
132
|
}
|
|
122
133
|
|
|
123
134
|
export interface GeminiCliFeatures extends BaseCliFeatures {
|
|
@@ -126,6 +137,7 @@ export interface GeminiCliFeatures extends BaseCliFeatures {
|
|
|
126
137
|
readonly supportsAutoApprove: boolean;
|
|
127
138
|
readonly supportsCwd: boolean;
|
|
128
139
|
readonly supportsModel: boolean;
|
|
140
|
+
readonly supportsAdminPolicy: boolean;
|
|
129
141
|
}
|
|
130
142
|
|
|
131
143
|
export interface OpencodeCliFeatures extends BaseCliFeatures {
|
|
@@ -138,6 +150,8 @@ export interface OpencodeCliFeatures extends BaseCliFeatures {
|
|
|
138
150
|
readonly supportsAutoApprove: false;
|
|
139
151
|
readonly supportsResume: boolean;
|
|
140
152
|
readonly supportsWebSearch: boolean;
|
|
153
|
+
readonly supportsAgent: boolean;
|
|
154
|
+
readonly supportsRecoveryIsolation: boolean;
|
|
141
155
|
}
|
|
142
156
|
|
|
143
157
|
export interface PiCliFeatures extends BaseCliFeatures {
|
|
@@ -215,6 +229,9 @@ export interface CliFeatureOverrides {
|
|
|
215
229
|
readonly supportsIncludePartials?: boolean;
|
|
216
230
|
readonly supportsVerbose?: boolean;
|
|
217
231
|
readonly supportsModel?: boolean;
|
|
232
|
+
readonly supportsTools?: boolean;
|
|
233
|
+
readonly supportsStrictMcpConfig?: boolean;
|
|
234
|
+
readonly supportsNoSessionPersistence?: boolean;
|
|
218
235
|
readonly supportsEffort?: boolean;
|
|
219
236
|
readonly supportsSettings?: boolean;
|
|
220
237
|
readonly supportsJson?: boolean;
|
|
@@ -223,12 +240,20 @@ export interface CliFeatureOverrides {
|
|
|
223
240
|
readonly supportsCwd?: boolean;
|
|
224
241
|
readonly supportsConfigOverride?: boolean;
|
|
225
242
|
readonly supportsSkipGitRepoCheck?: boolean;
|
|
243
|
+
readonly supportsSandbox?: boolean;
|
|
244
|
+
readonly supportsEphemeral?: boolean;
|
|
245
|
+
readonly supportsIgnoreUserConfig?: boolean;
|
|
246
|
+
readonly supportsIgnoreRules?: boolean;
|
|
247
|
+
readonly supportsStrictConfig?: boolean;
|
|
226
248
|
readonly supportsVariant?: boolean;
|
|
249
|
+
readonly supportsAdminPolicy?: boolean;
|
|
227
250
|
readonly supportsJsonMode?: boolean;
|
|
228
251
|
readonly supportsNoSession?: boolean;
|
|
229
252
|
readonly supportsNoExtensions?: boolean;
|
|
230
253
|
readonly supportsNoSkills?: boolean;
|
|
231
254
|
readonly supportsNoPromptTemplates?: boolean;
|
|
255
|
+
readonly supportsAgent?: boolean;
|
|
256
|
+
readonly supportsRecoveryIsolation?: boolean;
|
|
232
257
|
readonly supportsNoContextFiles?: boolean;
|
|
233
258
|
readonly supportsNoApprove?: boolean;
|
|
234
259
|
readonly supportsModeJson?: boolean;
|
|
@@ -262,7 +287,7 @@ export interface CleanupMetadata {
|
|
|
262
287
|
readonly kind: 'temp-file' | 'temp-directory';
|
|
263
288
|
readonly provider: ProviderId;
|
|
264
289
|
readonly path: string;
|
|
265
|
-
readonly reason: 'output-schema' | 'settings-overlay';
|
|
290
|
+
readonly reason: 'output-schema' | 'settings-overlay' | 'admin-policy' | 'isolated-config';
|
|
266
291
|
}
|
|
267
292
|
|
|
268
293
|
export interface WarningMetadata {
|
|
@@ -312,6 +337,8 @@ export interface BuildProviderCommandOptions {
|
|
|
312
337
|
// one variadic `--mcp-config` followed by file paths; adapters such as Copilot accept repeated
|
|
313
338
|
// flags with inline JSON so configs survive container path translation.
|
|
314
339
|
readonly mcpConfig?: readonly string[];
|
|
340
|
+
/** Internal profile for provider-neutral structured-output correction turns. */
|
|
341
|
+
readonly structuredOutputRecovery?: boolean;
|
|
315
342
|
}
|
|
316
343
|
|
|
317
344
|
export interface TextEvent {
|
|
@@ -415,6 +442,13 @@ export interface ProviderAdapter {
|
|
|
415
442
|
classifyError(error: unknown): ErrorClassification;
|
|
416
443
|
}
|
|
417
444
|
|
|
445
|
+
export interface StructuredOutputRecoveryAdapter extends ProviderAdapter {
|
|
446
|
+
buildStructuredOutputRecoveryCommand(
|
|
447
|
+
context: string,
|
|
448
|
+
options?: BuildProviderCommandOptions
|
|
449
|
+
): CommandSpec;
|
|
450
|
+
}
|
|
451
|
+
|
|
418
452
|
export class InvalidProviderModelError extends Error {
|
|
419
453
|
readonly permanent = true;
|
|
420
454
|
|
package/src/agent-wrapper.js
CHANGED
|
@@ -586,8 +586,8 @@ class AgentWrapper {
|
|
|
586
586
|
* Falls back to reformatting if extraction fails
|
|
587
587
|
* @private
|
|
588
588
|
*/
|
|
589
|
-
_parseResultOutput(output) {
|
|
590
|
-
return parseResultOutput(this, output);
|
|
589
|
+
_parseResultOutput(output, options = {}) {
|
|
590
|
+
return parseResultOutput(this, output, options);
|
|
591
591
|
}
|
|
592
592
|
|
|
593
593
|
/**
|
package/src/cluster/errors.ts
CHANGED
|
@@ -13,6 +13,7 @@ export class ClusterInternalError extends ClusterError {}
|
|
|
13
13
|
export class ClusterProtocolError extends ClusterError {}
|
|
14
14
|
export class ClusterTransportError extends ClusterError {}
|
|
15
15
|
export class ClusterTimeoutError extends ClusterError {}
|
|
16
|
+
export class ClusterRequestError extends ClusterError {}
|
|
16
17
|
|
|
17
18
|
export function requestAbortError(method: string): DOMException {
|
|
18
19
|
return new DOMException(
|
package/src/cluster/index.ts
CHANGED
|
@@ -5,11 +5,15 @@ export {
|
|
|
5
5
|
ClusterError,
|
|
6
6
|
ClusterInternalError,
|
|
7
7
|
ClusterProtocolError,
|
|
8
|
+
ClusterRequestError,
|
|
8
9
|
ClusterRpcError,
|
|
9
10
|
ClusterStateError,
|
|
10
11
|
ClusterTimeoutError,
|
|
11
12
|
ClusterTransportError,
|
|
12
13
|
} from './errors.js';
|
|
14
|
+
export { assertGraphProfile, assertGraphProfileSupported, assertGraphSpec } from './validators.js';
|
|
15
|
+
export * from './payload-value.js';
|
|
16
|
+
export * from './json-source.js';
|
|
13
17
|
export { CONNECTION_TRANSITIONS, PROTOCOL_DIAGNOSTIC_CAPACITY, Connection } from './connection.js';
|
|
14
18
|
export type {
|
|
15
19
|
CallOptions,
|