@the-open-engine/zeroshot 6.7.2 → 6.8.1
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/lib/agent-cli-provider/adapters/claude.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/claude.js +1 -0
- package/lib/agent-cli-provider/adapters/claude.js.map +1 -1
- package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/codex.js +3 -0
- package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
- package/lib/agent-cli-provider/adapters/common.js +1 -1
- package/lib/agent-cli-provider/adapters/common.js.map +1 -1
- package/lib/agent-cli-provider/adapters/opencode-models.d.ts +7 -0
- package/lib/agent-cli-provider/adapters/opencode-models.d.ts.map +1 -0
- package/lib/agent-cli-provider/adapters/opencode-models.js +87 -0
- package/lib/agent-cli-provider/adapters/opencode-models.js.map +1 -0
- package/lib/agent-cli-provider/adapters/opencode.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/opencode.js +6 -58
- package/lib/agent-cli-provider/adapters/opencode.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 +27 -13
- package/lib/agent-cli-provider/single-agent-runtime.js.map +1 -1
- package/lib/agent-cli-provider/types.d.ts +1 -0
- package/lib/agent-cli-provider/types.d.ts.map +1 -1
- package/lib/agent-cli-provider/types.js.map +1 -1
- package/package.json +1 -1
- package/scripts/assert-release-published.js +145 -35
- package/src/agent/agent-task-executor.js +23 -10
- package/src/agent-cli-provider/adapters/claude.ts +1 -0
- package/src/agent-cli-provider/adapters/codex.ts +3 -0
- package/src/agent-cli-provider/adapters/common.ts +1 -1
- package/src/agent-cli-provider/adapters/opencode-models.ts +100 -0
- package/src/agent-cli-provider/adapters/opencode.ts +8 -65
- package/src/agent-cli-provider/single-agent-runtime.ts +51 -33
- package/src/agent-cli-provider/types.ts +1 -0
- package/src/agent-wrapper.js +14 -2
- package/src/claude-task-runner.js +121 -37
- package/src/config-validator.js +2 -2
- package/src/isolation-manager.js +4 -1
- package/src/providers/index.js +5 -0
- package/src/task-run-model-args.js +155 -0
- package/task-lib/runner.js +66 -26
|
@@ -34,6 +34,11 @@ interface RuntimeProviderSettings {
|
|
|
34
34
|
readonly gateway?: GatewayBuildOptions;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
interface RuntimeCommandContext {
|
|
38
|
+
readonly cliFeatures: CliFeatureOverrides;
|
|
39
|
+
readonly authEnv: Readonly<Record<string, string>>;
|
|
40
|
+
}
|
|
41
|
+
|
|
37
42
|
export interface SingleAgentProviderCommandInput {
|
|
38
43
|
readonly provider?: string | null;
|
|
39
44
|
readonly context: string;
|
|
@@ -62,6 +67,7 @@ type MutableModelSpec = {
|
|
|
62
67
|
|
|
63
68
|
const MODEL_LEVELS: readonly ModelLevel[] = ['level1', 'level2', 'level3'];
|
|
64
69
|
const REASONING_EFFORTS: readonly ReasoningEffort[] = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
70
|
+
const LEGACY_ISOLATED_PROVIDER_SETTINGS_ENV = 'ZEROSHOT_ISOLATED_PROVIDER_SETTINGS_JSON';
|
|
65
71
|
const settingsModule: unknown = require('../../lib/settings');
|
|
66
72
|
const providerDetectionModule: unknown = require('../../lib/provider-detection');
|
|
67
73
|
const claudeAuthModule: unknown = require('../../lib/settings/claude-auth');
|
|
@@ -76,6 +82,7 @@ const resolveClaudeAuthFn = moduleFunction(claudeAuthModule, 'resolveClaudeAuth'
|
|
|
76
82
|
export function prepareSingleAgentProviderCommand(
|
|
77
83
|
input: SingleAgentProviderCommandInput
|
|
78
84
|
): PreparedSingleAgentProviderCommand {
|
|
85
|
+
rejectCallerSuppliedModelProvenance(input);
|
|
79
86
|
const baseOptions = input.options ?? {};
|
|
80
87
|
const settings = loadRuntimeSettings();
|
|
81
88
|
const adapter = adapterForRuntimeInput(input.provider, settings);
|
|
@@ -86,7 +93,10 @@ export function prepareSingleAgentProviderCommand(
|
|
|
86
93
|
);
|
|
87
94
|
const cliFeatures = resolveRuntimeCliFeatures(adapter.id, baseOptions.cliFeatures);
|
|
88
95
|
const authEnv = baseOptions.authEnv ?? resolveRuntimeAuthEnv(adapter.id, settings);
|
|
89
|
-
const options = buildRuntimeOptions(baseOptions, adapter, providerSettings,
|
|
96
|
+
const options = buildRuntimeOptions(baseOptions, adapter, providerSettings, {
|
|
97
|
+
cliFeatures,
|
|
98
|
+
authEnv,
|
|
99
|
+
});
|
|
90
100
|
return {
|
|
91
101
|
adapter,
|
|
92
102
|
options,
|
|
@@ -128,8 +138,7 @@ function mergeAcpFailClosedCliFeatures(
|
|
|
128
138
|
...detected,
|
|
129
139
|
...overrides,
|
|
130
140
|
supportsAcpStdio: detected.supportsAcpStdio && overrides.supportsAcpStdio !== false,
|
|
131
|
-
supportsPromptImages:
|
|
132
|
-
detected.supportsPromptImages && overrides.supportsPromptImages !== false,
|
|
141
|
+
supportsPromptImages: detected.supportsPromptImages && overrides.supportsPromptImages !== false,
|
|
133
142
|
supportsLoadSession: detected.supportsLoadSession && overrides.supportsLoadSession !== false,
|
|
134
143
|
supportsSessionCancel:
|
|
135
144
|
detected.supportsSessionCancel && overrides.supportsSessionCancel !== false,
|
|
@@ -162,7 +171,9 @@ export function probeRuntimeProviderCli(provider: string): RuntimeProviderProbe
|
|
|
162
171
|
}
|
|
163
172
|
|
|
164
173
|
const helpText = stringResult(getHelpOutputFn(helpCommand.command, helpCommand.args)).trim();
|
|
165
|
-
const versionText = stringResult(
|
|
174
|
+
const versionText = stringResult(
|
|
175
|
+
getVersionOutputFn(helpCommand.command, helpCommand.args)
|
|
176
|
+
).trim();
|
|
166
177
|
const availabilityProbe = getProviderRegistryEntry(adapter.id).availabilityProbe ?? 'command';
|
|
167
178
|
|
|
168
179
|
return {
|
|
@@ -177,8 +188,7 @@ function buildRuntimeOptions(
|
|
|
177
188
|
baseOptions: BuildProviderCommandOptions,
|
|
178
189
|
adapter: ProviderAdapter,
|
|
179
190
|
providerSettings: RuntimeProviderSettings,
|
|
180
|
-
|
|
181
|
-
authEnv: Readonly<Record<string, string>>
|
|
191
|
+
runtime: RuntimeCommandContext
|
|
182
192
|
): BuildProviderCommandOptions {
|
|
183
193
|
const modelSpec = resolveRuntimeModelSpec(adapter, baseOptions.modelSpec, providerSettings);
|
|
184
194
|
const gateway = resolveRuntimeGatewayOptions(
|
|
@@ -191,16 +201,16 @@ function buildRuntimeOptions(
|
|
|
191
201
|
...baseOptions,
|
|
192
202
|
modelSpec,
|
|
193
203
|
...(gateway === undefined ? {} : { gateway }),
|
|
194
|
-
cliFeatures,
|
|
204
|
+
cliFeatures: runtime.cliFeatures,
|
|
195
205
|
};
|
|
196
206
|
if (baseOptions.jsonSchema && !supportsProviderCapability(adapter.id, 'jsonSchema')) {
|
|
197
|
-
if (!shouldIncludeAuthEnv(baseOptions, authEnv)) {
|
|
207
|
+
if (!shouldIncludeAuthEnv(baseOptions, runtime.authEnv)) {
|
|
198
208
|
return { ...resolved, strictSchema: false };
|
|
199
209
|
}
|
|
200
|
-
return { ...resolved, authEnv, strictSchema: false };
|
|
210
|
+
return { ...resolved, authEnv: runtime.authEnv, strictSchema: false };
|
|
201
211
|
}
|
|
202
|
-
if (!shouldIncludeAuthEnv(baseOptions, authEnv)) return resolved;
|
|
203
|
-
return { ...resolved, authEnv };
|
|
212
|
+
if (!shouldIncludeAuthEnv(baseOptions, runtime.authEnv)) return resolved;
|
|
213
|
+
return { ...resolved, authEnv: runtime.authEnv };
|
|
204
214
|
}
|
|
205
215
|
|
|
206
216
|
function resolveRuntimeGatewayOptions(
|
|
@@ -218,23 +228,19 @@ function resolveRuntimeGatewayOptions(
|
|
|
218
228
|
? settingsGateway.headers
|
|
219
229
|
: { ...(settingsGateway.headers ?? {}), ...requestGateway.headers };
|
|
220
230
|
const mergedGateway: GatewayBuildOptions = {
|
|
221
|
-
...(requestGateway.baseUrl ?? settingsGateway.baseUrl
|
|
231
|
+
...((requestGateway.baseUrl ?? settingsGateway.baseUrl)
|
|
222
232
|
? { baseUrl: requestGateway.baseUrl ?? settingsGateway.baseUrl }
|
|
223
233
|
: {}),
|
|
224
|
-
...(requestGateway.apiKey ?? settingsGateway.apiKey
|
|
234
|
+
...((requestGateway.apiKey ?? settingsGateway.apiKey)
|
|
225
235
|
? { apiKey: requestGateway.apiKey ?? settingsGateway.apiKey }
|
|
226
236
|
: {}),
|
|
227
237
|
...(mergedHeaders === undefined ? {} : { headers: mergedHeaders }),
|
|
228
238
|
model: requestGateway.model ?? modelSpec.model ?? settingsGateway.model ?? null,
|
|
229
|
-
...(requestGateway.toolPolicy ?? settingsGateway.toolPolicy
|
|
239
|
+
...((requestGateway.toolPolicy ?? settingsGateway.toolPolicy)
|
|
230
240
|
? { toolPolicy: requestGateway.toolPolicy ?? settingsGateway.toolPolicy }
|
|
231
241
|
: {}),
|
|
232
242
|
};
|
|
233
|
-
return resolveGatewayConfiguration(
|
|
234
|
-
mergedGateway,
|
|
235
|
-
'options.gateway',
|
|
236
|
-
cwd
|
|
237
|
-
);
|
|
243
|
+
return resolveGatewayConfiguration(mergedGateway, 'options.gateway', cwd);
|
|
238
244
|
}
|
|
239
245
|
|
|
240
246
|
function shouldIncludeAuthEnv(
|
|
@@ -286,7 +292,8 @@ function adapterForRuntimeInput(
|
|
|
286
292
|
provider: string | null | undefined,
|
|
287
293
|
settings: Record<string, unknown>
|
|
288
294
|
): ProviderAdapter {
|
|
289
|
-
const configured =
|
|
295
|
+
const configured =
|
|
296
|
+
provider ?? optionalString(settings.defaultProvider, 'settings.defaultProvider');
|
|
290
297
|
return getProviderAdapter(configured ?? 'claude');
|
|
291
298
|
}
|
|
292
299
|
|
|
@@ -309,16 +316,14 @@ function runtimeProviderSettings(
|
|
|
309
316
|
);
|
|
310
317
|
const gateway =
|
|
311
318
|
provider === 'gateway'
|
|
312
|
-
? normalizeGatewayBuildOptions(
|
|
313
|
-
providerSettings,
|
|
314
|
-
'settings.providerSettings.gateway',
|
|
315
|
-
cwd
|
|
316
|
-
)
|
|
319
|
+
? normalizeGatewayBuildOptions(providerSettings, 'settings.providerSettings.gateway', cwd)
|
|
317
320
|
: undefined;
|
|
318
321
|
if (defaultLevel === undefined) {
|
|
319
322
|
return gateway === undefined ? { levelOverrides } : { levelOverrides, gateway };
|
|
320
323
|
}
|
|
321
|
-
return gateway === undefined
|
|
324
|
+
return gateway === undefined
|
|
325
|
+
? { defaultLevel, levelOverrides }
|
|
326
|
+
: { defaultLevel, levelOverrides, gateway };
|
|
322
327
|
}
|
|
323
328
|
|
|
324
329
|
function runtimeHelpCommand(provider: ProviderId): CommandParts {
|
|
@@ -333,7 +338,11 @@ function probeGatewayProvider(adapter: ProviderAdapter): RuntimeProviderProbe {
|
|
|
333
338
|
try {
|
|
334
339
|
const settings = loadRuntimeSettings();
|
|
335
340
|
const providerSettings = runtimeProviderSettings(settings, 'gateway', process.cwd());
|
|
336
|
-
resolveGatewayConfiguration(
|
|
341
|
+
resolveGatewayConfiguration(
|
|
342
|
+
providerSettings.gateway,
|
|
343
|
+
'settings.providerSettings.gateway',
|
|
344
|
+
process.cwd()
|
|
345
|
+
);
|
|
337
346
|
return {
|
|
338
347
|
available: true,
|
|
339
348
|
helpText: 'Bundled gateway runner',
|
|
@@ -351,8 +360,20 @@ function probeGatewayProvider(adapter: ProviderAdapter): RuntimeProviderProbe {
|
|
|
351
360
|
}
|
|
352
361
|
|
|
353
362
|
function loadRuntimeSettings(): Record<string, unknown> {
|
|
354
|
-
|
|
355
|
-
|
|
363
|
+
if (Object.prototype.hasOwnProperty.call(process.env, LEGACY_ISOLATED_PROVIDER_SETTINGS_ENV)) {
|
|
364
|
+
throw new Error(
|
|
365
|
+
`${LEGACY_ISOLATED_PROVIDER_SETTINGS_ENV} is not a trusted settings channel; use the settings file.`
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
return requiredRecord(loadSettingsFn(), 'loadSettings');
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function rejectCallerSuppliedModelProvenance(input: SingleAgentProviderCommandInput): void {
|
|
372
|
+
if (Object.prototype.hasOwnProperty.call(input, 'modelSpecSource')) {
|
|
373
|
+
throw new Error(
|
|
374
|
+
'modelSpecSource is not accepted at the child provider boundary; use modelLevel and effective provider settings.'
|
|
375
|
+
);
|
|
376
|
+
}
|
|
356
377
|
}
|
|
357
378
|
|
|
358
379
|
function moduleFunction(moduleValue: unknown, field: string): UnknownFunction {
|
|
@@ -456,10 +477,7 @@ function requiredRecord(value: unknown, field: string): Record<string, unknown>
|
|
|
456
477
|
throw new Error(`${field} must be an object.`);
|
|
457
478
|
}
|
|
458
479
|
|
|
459
|
-
function stringRecordFromUnknown(
|
|
460
|
-
value: unknown,
|
|
461
|
-
field: string
|
|
462
|
-
): Readonly<Record<string, string>> {
|
|
480
|
+
function stringRecordFromUnknown(value: unknown, field: string): Readonly<Record<string, string>> {
|
|
463
481
|
if (value === undefined || value === null) return {};
|
|
464
482
|
const record = requiredRecord(value, field);
|
|
465
483
|
const result: Record<string, string> = {};
|
|
@@ -367,6 +367,7 @@ export interface ProviderAdapter {
|
|
|
367
367
|
createParserState(): ProviderParserState;
|
|
368
368
|
resolveModelSpec(level: ModelLevel, overrides?: LevelOverrides): ResolvedModelSpec;
|
|
369
369
|
validateModelId(modelId: string | null | undefined): string | null | undefined;
|
|
370
|
+
validateConfiguredModelId?(modelId: string | null | undefined): string | null | undefined;
|
|
370
371
|
classifyError(error: unknown): ErrorClassification;
|
|
371
372
|
}
|
|
372
373
|
|
package/src/agent-wrapper.js
CHANGED
|
@@ -103,10 +103,11 @@ class AgentWrapper {
|
|
|
103
103
|
const taskRunner = options.taskRunner;
|
|
104
104
|
this.mockSpawnFn = (args, { context }) => {
|
|
105
105
|
const spec = this._resolveModelSpec();
|
|
106
|
+
const source = this._resolveModelSpecSource();
|
|
106
107
|
return taskRunner.run(context, {
|
|
107
108
|
agentId: this.id,
|
|
108
|
-
model:
|
|
109
|
-
|
|
109
|
+
...(source === 'direct' ? { model: spec.model } : { modelLevel: spec.level }),
|
|
110
|
+
...(spec.reasoningEffort ? { reasoningEffort: spec.reasoningEffort } : {}),
|
|
110
111
|
provider: this._resolveProvider(),
|
|
111
112
|
cwd: this.config.cwd || process.cwd(),
|
|
112
113
|
worktreePath: this.worktree?.path || null,
|
|
@@ -222,6 +223,17 @@ class AgentWrapper {
|
|
|
222
223
|
return applyReasoningOverride({ ...spec, level }, this.config.reasoningEffort);
|
|
223
224
|
}
|
|
224
225
|
|
|
226
|
+
_resolveModelSpecSource() {
|
|
227
|
+
if (this.modelConfig.type === 'rules') {
|
|
228
|
+
for (const rule of this.modelConfig.rules) {
|
|
229
|
+
if (this._matchesIterationRange(rule.iterations)) {
|
|
230
|
+
return rule.model ? 'direct' : 'provider-level';
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return this.modelConfig.model ? 'direct' : 'provider-level';
|
|
235
|
+
}
|
|
236
|
+
|
|
225
237
|
/**
|
|
226
238
|
* Publish a message to the message bus, always including sender_model
|
|
227
239
|
* @private
|
|
@@ -13,6 +13,18 @@ const { normalizeProviderName } = require('../lib/provider-names');
|
|
|
13
13
|
const { getProvider } = require('./providers');
|
|
14
14
|
const { prependWorktreeToolBinToEnv } = require('./worktree-tooling-env');
|
|
15
15
|
const { prepareClaudeConfigDir } = require('./worktree-claude-config');
|
|
16
|
+
const {
|
|
17
|
+
appendTaskRunModelArgs,
|
|
18
|
+
wrapTaskRunWithIsolatedSettings,
|
|
19
|
+
} = require('./task-run-model-args');
|
|
20
|
+
|
|
21
|
+
function rejectCallerSuppliedModelProvenance(options) {
|
|
22
|
+
if (Object.prototype.hasOwnProperty.call(options, 'modelSpecSource')) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
'modelSpecSource is derived from model versus modelLevel/default and cannot be supplied.'
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
16
28
|
|
|
17
29
|
function runCommand(command, args, options = {}, callback = null) {
|
|
18
30
|
const timeout = options.timeout ?? 30000;
|
|
@@ -112,10 +124,11 @@ class ClaudeTaskRunner extends TaskRunner {
|
|
|
112
124
|
* Execute a task via zeroshot CLI
|
|
113
125
|
*
|
|
114
126
|
* @param {string} context - Full prompt/context
|
|
115
|
-
* @param {{agentId?: string, model?: string, outputFormat?: string, jsonSchema?: any, strictSchema?: boolean, cwd?: string, worktreePath?: string|null, isolation?: any}} options - Execution options
|
|
127
|
+
* @param {{agentId?: string, model?: string, modelLevel?: string, modelSpec?: Object|null, reasoningEffort?: string, outputFormat?: string, jsonSchema?: any, strictSchema?: boolean, cwd?: string, worktreePath?: string|null, isolation?: any}} options - Execution options
|
|
116
128
|
* @returns {Promise<{success: boolean, output: string, error: string|null, taskId?: string}>}
|
|
117
129
|
*/
|
|
118
130
|
async run(context, options = {}) {
|
|
131
|
+
rejectCallerSuppliedModelProvenance(options);
|
|
119
132
|
const {
|
|
120
133
|
agentId = 'unknown',
|
|
121
134
|
provider,
|
|
@@ -137,7 +150,7 @@ class ClaudeTaskRunner extends TaskRunner {
|
|
|
137
150
|
providerName,
|
|
138
151
|
settings
|
|
139
152
|
);
|
|
140
|
-
const
|
|
153
|
+
const modelSelection = this._resolveModelSelection({
|
|
141
154
|
explicitModelSpec,
|
|
142
155
|
model,
|
|
143
156
|
reasoningEffort,
|
|
@@ -146,13 +159,13 @@ class ClaudeTaskRunner extends TaskRunner {
|
|
|
146
159
|
providerSettings,
|
|
147
160
|
levelOverrides,
|
|
148
161
|
});
|
|
162
|
+
const resolvedModelSpec = modelSelection.modelSpec;
|
|
149
163
|
|
|
150
164
|
// Isolation mode delegates to separate method
|
|
151
165
|
if (isolation?.enabled) {
|
|
152
166
|
return this._runIsolated(context, {
|
|
153
167
|
...options,
|
|
154
168
|
provider: providerName,
|
|
155
|
-
modelSpec: resolvedModelSpec,
|
|
156
169
|
});
|
|
157
170
|
}
|
|
158
171
|
|
|
@@ -168,6 +181,7 @@ class ClaudeTaskRunner extends TaskRunner {
|
|
|
168
181
|
providerName,
|
|
169
182
|
runOutputFormat,
|
|
170
183
|
resolvedModelSpec,
|
|
184
|
+
modelSpecSource: modelSelection.source,
|
|
171
185
|
jsonSchema,
|
|
172
186
|
});
|
|
173
187
|
|
|
@@ -204,25 +218,74 @@ class ClaudeTaskRunner extends TaskRunner {
|
|
|
204
218
|
providerSettings,
|
|
205
219
|
levelOverrides,
|
|
206
220
|
}) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
221
|
+
return this._resolveModelSelection({
|
|
222
|
+
explicitModelSpec,
|
|
223
|
+
model,
|
|
224
|
+
reasoningEffort,
|
|
225
|
+
modelLevel,
|
|
226
|
+
providerModule,
|
|
227
|
+
providerSettings,
|
|
228
|
+
levelOverrides,
|
|
229
|
+
}).modelSpec;
|
|
230
|
+
}
|
|
213
231
|
|
|
232
|
+
_resolveModelSelection({
|
|
233
|
+
explicitModelSpec,
|
|
234
|
+
model,
|
|
235
|
+
reasoningEffort,
|
|
236
|
+
modelLevel,
|
|
237
|
+
providerModule,
|
|
238
|
+
providerSettings,
|
|
239
|
+
levelOverrides,
|
|
240
|
+
}) {
|
|
214
241
|
if (model) {
|
|
215
242
|
providerModule.validateModelId(model);
|
|
216
|
-
return {
|
|
243
|
+
return {
|
|
244
|
+
source: 'direct',
|
|
245
|
+
modelSpec: { model, reasoningEffort },
|
|
246
|
+
};
|
|
217
247
|
}
|
|
218
248
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
249
|
+
if (explicitModelSpec?.model !== undefined) {
|
|
250
|
+
providerModule.validateModelId(explicitModelSpec.model);
|
|
251
|
+
return {
|
|
252
|
+
source: 'direct',
|
|
253
|
+
modelSpec: explicitModelSpec,
|
|
254
|
+
};
|
|
223
255
|
}
|
|
224
256
|
|
|
225
|
-
return
|
|
257
|
+
return {
|
|
258
|
+
source: 'provider-level',
|
|
259
|
+
modelSpec: this._resolveProviderLevelModelSpec({
|
|
260
|
+
explicitModelSpec,
|
|
261
|
+
modelLevel,
|
|
262
|
+
reasoningEffort,
|
|
263
|
+
providerModule,
|
|
264
|
+
providerSettings,
|
|
265
|
+
levelOverrides,
|
|
266
|
+
}),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
_resolveProviderLevelModelSpec({
|
|
271
|
+
explicitModelSpec,
|
|
272
|
+
modelLevel,
|
|
273
|
+
reasoningEffort,
|
|
274
|
+
providerModule,
|
|
275
|
+
providerSettings,
|
|
276
|
+
levelOverrides,
|
|
277
|
+
}) {
|
|
278
|
+
const level =
|
|
279
|
+
explicitModelSpec?.level ||
|
|
280
|
+
modelLevel ||
|
|
281
|
+
providerSettings.defaultLevel ||
|
|
282
|
+
providerModule.getDefaultLevel();
|
|
283
|
+
const resolvedModelSpec = providerModule.resolveModelSpec(level, levelOverrides);
|
|
284
|
+
const resolvedReasoningEffort = explicitModelSpec?.reasoningEffort || reasoningEffort;
|
|
285
|
+
|
|
286
|
+
return resolvedReasoningEffort
|
|
287
|
+
? { ...resolvedModelSpec, reasoningEffort: resolvedReasoningEffort }
|
|
288
|
+
: resolvedModelSpec;
|
|
226
289
|
}
|
|
227
290
|
|
|
228
291
|
_resolveOutputFormat({ outputFormat, jsonSchema, strictSchema }) {
|
|
@@ -232,16 +295,16 @@ class ClaudeTaskRunner extends TaskRunner {
|
|
|
232
295
|
return jsonSchema && outputFormat === 'json' && !strictSchema ? 'stream-json' : outputFormat;
|
|
233
296
|
}
|
|
234
297
|
|
|
235
|
-
_buildRunArgs({
|
|
298
|
+
_buildRunArgs({
|
|
299
|
+
context,
|
|
300
|
+
providerName,
|
|
301
|
+
runOutputFormat,
|
|
302
|
+
resolvedModelSpec,
|
|
303
|
+
modelSpecSource = 'direct',
|
|
304
|
+
jsonSchema,
|
|
305
|
+
}) {
|
|
236
306
|
const args = ['task', 'run', '--output-format', runOutputFormat, '--provider', providerName];
|
|
237
|
-
|
|
238
|
-
if (resolvedModelSpec?.model) {
|
|
239
|
-
args.push('--model', resolvedModelSpec.model);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (resolvedModelSpec?.reasoningEffort) {
|
|
243
|
-
args.push('--reasoning-effort', resolvedModelSpec.reasoningEffort);
|
|
244
|
-
}
|
|
307
|
+
appendTaskRunModelArgs(args, resolvedModelSpec, modelSpecSource);
|
|
245
308
|
|
|
246
309
|
// Pass schema to CLI only when using json output (strictSchema=true or no conflict)
|
|
247
310
|
if (jsonSchema && runOutputFormat === 'json') {
|
|
@@ -542,20 +605,40 @@ class ClaudeTaskRunner extends TaskRunner {
|
|
|
542
605
|
/**
|
|
543
606
|
* Run task in isolated Docker container
|
|
544
607
|
* @param {string} context
|
|
545
|
-
* @param {{agentId?: string, model?: string, outputFormat?: string, jsonSchema?: any, strictSchema?: boolean, isolation?: any}} options
|
|
608
|
+
* @param {{agentId?: string, provider?: string, model?: string, modelLevel?: string, modelSpec?: Object|null, reasoningEffort?: string, outputFormat?: string, jsonSchema?: any, strictSchema?: boolean, isolation?: any}} options
|
|
546
609
|
* @returns {Promise<{success: boolean, output: string, error: string|null}>}
|
|
547
610
|
*/
|
|
548
611
|
_runIsolated(context, options) {
|
|
612
|
+
rejectCallerSuppliedModelProvenance(options);
|
|
549
613
|
const {
|
|
550
614
|
agentId = 'unknown',
|
|
551
615
|
provider = 'claude',
|
|
552
|
-
|
|
616
|
+
model = null,
|
|
617
|
+
modelLevel = null,
|
|
618
|
+
modelSpec: explicitModelSpec = null,
|
|
619
|
+
reasoningEffort = null,
|
|
553
620
|
outputFormat = 'stream-json',
|
|
554
621
|
jsonSchema = null,
|
|
555
622
|
strictSchema = false,
|
|
556
623
|
isolation,
|
|
557
624
|
} = options;
|
|
558
625
|
const { manager, clusterId } = isolation;
|
|
626
|
+
const settings = loadSettings();
|
|
627
|
+
const { providerModule, providerSettings, levelOverrides } = this._getProviderContext(
|
|
628
|
+
provider,
|
|
629
|
+
settings
|
|
630
|
+
);
|
|
631
|
+
const modelSelection = this._resolveModelSelection({
|
|
632
|
+
explicitModelSpec,
|
|
633
|
+
model,
|
|
634
|
+
reasoningEffort,
|
|
635
|
+
modelLevel,
|
|
636
|
+
providerModule,
|
|
637
|
+
providerSettings,
|
|
638
|
+
levelOverrides,
|
|
639
|
+
});
|
|
640
|
+
const modelSpec = modelSelection.modelSpec;
|
|
641
|
+
const modelSpecSource = modelSelection.source;
|
|
559
642
|
|
|
560
643
|
this._log(`📦 [${agentId}]: Running task in isolated container...`);
|
|
561
644
|
|
|
@@ -565,7 +648,7 @@ class ClaudeTaskRunner extends TaskRunner {
|
|
|
565
648
|
? 'stream-json'
|
|
566
649
|
: desiredOutputFormat;
|
|
567
650
|
|
|
568
|
-
|
|
651
|
+
let command = [
|
|
569
652
|
'zeroshot',
|
|
570
653
|
'task',
|
|
571
654
|
'run',
|
|
@@ -575,13 +658,7 @@ class ClaudeTaskRunner extends TaskRunner {
|
|
|
575
658
|
provider,
|
|
576
659
|
];
|
|
577
660
|
|
|
578
|
-
|
|
579
|
-
command.push('--model', modelSpec.model);
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
if (modelSpec?.reasoningEffort) {
|
|
583
|
-
command.push('--reasoning-effort', modelSpec.reasoningEffort);
|
|
584
|
-
}
|
|
661
|
+
appendTaskRunModelArgs(command, modelSpec, modelSpecSource);
|
|
585
662
|
|
|
586
663
|
if (jsonSchema && runOutputFormat === 'json') {
|
|
587
664
|
command.push('--json-schema', JSON.stringify(jsonSchema));
|
|
@@ -597,16 +674,23 @@ class ClaudeTaskRunner extends TaskRunner {
|
|
|
597
674
|
}
|
|
598
675
|
|
|
599
676
|
command.push(finalContext);
|
|
677
|
+
command = wrapTaskRunWithIsolatedSettings(command, {
|
|
678
|
+
providerName: provider,
|
|
679
|
+
settings,
|
|
680
|
+
modelSpecSource,
|
|
681
|
+
modelSpec,
|
|
682
|
+
});
|
|
600
683
|
|
|
601
684
|
return new Promise((resolve, reject) => {
|
|
602
685
|
let output = '';
|
|
603
686
|
let resolved = false;
|
|
604
687
|
|
|
605
688
|
const proc = manager.spawnInContainer(clusterId, command, {
|
|
606
|
-
env:
|
|
607
|
-
provider === 'claude' && modelSpec?.model
|
|
689
|
+
env: {
|
|
690
|
+
...(provider === 'claude' && modelSpec?.model
|
|
608
691
|
? { ANTHROPIC_MODEL: modelSpec.model, ZEROSHOT_BLOCK_ASK_USER: '1' }
|
|
609
|
-
: {},
|
|
692
|
+
: {}),
|
|
693
|
+
},
|
|
610
694
|
});
|
|
611
695
|
|
|
612
696
|
proc.stdout.on('data', (/** @type {Buffer} */ data) => {
|
package/src/config-validator.js
CHANGED
|
@@ -2053,8 +2053,8 @@ function validateProviderSettings(provider, providerSettings) {
|
|
|
2053
2053
|
`Invalid model override (must be non-empty string) for provider "${provider}"`
|
|
2054
2054
|
);
|
|
2055
2055
|
}
|
|
2056
|
-
if (override?.model) {
|
|
2057
|
-
providerModule.
|
|
2056
|
+
if (override?.model || (provider === 'opencode' && override?.model === '')) {
|
|
2057
|
+
providerModule.resolveModelSpec(level, { [level]: override });
|
|
2058
2058
|
}
|
|
2059
2059
|
if (override?.reasoningEffort && !providerSupportsCapability(provider, 'reasoningEffort')) {
|
|
2060
2060
|
throw new Error(
|
package/src/isolation-manager.js
CHANGED
|
@@ -727,7 +727,10 @@ class IsolationManager {
|
|
|
727
727
|
|
|
728
728
|
args.push(containerId, ...command);
|
|
729
729
|
|
|
730
|
-
|
|
730
|
+
// spawn() throws on null bytes in argv; strip them before they get there.
|
|
731
|
+
const safeArgs = args.map((arg) => (typeof arg === 'string' ? arg.replace(/\0/g, '') : arg));
|
|
732
|
+
|
|
733
|
+
return spawn('docker', safeArgs, {
|
|
731
734
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
732
735
|
...options.spawnOptions,
|
|
733
736
|
});
|
package/src/providers/index.js
CHANGED
|
@@ -129,6 +129,11 @@ class RuntimeProvider extends BaseProvider {
|
|
|
129
129
|
return this._adapter.validateModelId(modelId);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
validateConfiguredModelId(modelId) {
|
|
133
|
+
const validator = this._adapter.validateConfiguredModelId || this._adapter.validateModelId;
|
|
134
|
+
return validator(modelId);
|
|
135
|
+
}
|
|
136
|
+
|
|
132
137
|
isRetryableError(err) {
|
|
133
138
|
return helper.classifyProviderError(this.name, err).retryable;
|
|
134
139
|
}
|