@the-open-engine/zeroshot 6.7.2 → 6.8.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/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 +46 -15
- package/src/agent/agent-task-executor.js +18 -9
- 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/providers/index.js +5 -0
- package/src/task-run-model-args.js +155 -0
- package/task-lib/runner.js +66 -26
|
@@ -23,6 +23,10 @@ const {
|
|
|
23
23
|
prepareClaudeConfigDir,
|
|
24
24
|
resolveRepoMcpConfigPath,
|
|
25
25
|
} = require('../worktree-claude-config.js');
|
|
26
|
+
const {
|
|
27
|
+
appendTaskRunModelArgs,
|
|
28
|
+
wrapTaskRunWithIsolatedSettings,
|
|
29
|
+
} = require('../task-run-model-args.js');
|
|
26
30
|
const { buildRawLogOnlyMetadata } = require('./context-replay-policy');
|
|
27
31
|
|
|
28
32
|
function runCommandWithTimeout(command, args, options = {}, callback = null) {
|
|
@@ -722,14 +726,10 @@ function resolveOutputFormatConfig(agent) {
|
|
|
722
726
|
|
|
723
727
|
function buildTaskRunArgs({ agent, providerName, modelSpec, runOutputFormat }) {
|
|
724
728
|
const args = ['task', 'run', '--output-format', runOutputFormat, '--provider', providerName];
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
if (modelSpec?.reasoningEffort) {
|
|
731
|
-
args.push('--reasoning-effort', modelSpec.reasoningEffort);
|
|
732
|
-
}
|
|
729
|
+
const modelSpecSource = agent._resolveModelSpecSource
|
|
730
|
+
? agent._resolveModelSpecSource()
|
|
731
|
+
: 'direct';
|
|
732
|
+
appendTaskRunModelArgs(args, modelSpec, modelSpecSource);
|
|
733
733
|
|
|
734
734
|
// Add verification mode flag if configured
|
|
735
735
|
if (agent.config.verificationMode) {
|
|
@@ -1509,11 +1509,14 @@ async function spawnClaudeTaskIsolated(agent, context) {
|
|
|
1509
1509
|
const { manager, clusterId } = agent.isolation;
|
|
1510
1510
|
const providerName = agent._resolveProvider ? agent._resolveProvider() : 'claude';
|
|
1511
1511
|
const modelSpec = resolveAgentModelSpec(agent);
|
|
1512
|
+
const modelSpecSource = agent._resolveModelSpecSource
|
|
1513
|
+
? agent._resolveModelSpecSource()
|
|
1514
|
+
: 'direct';
|
|
1512
1515
|
|
|
1513
1516
|
agent._log(`📦 Agent ${agent.id}: Running task in isolated container using zeroshot task run...`);
|
|
1514
1517
|
|
|
1515
1518
|
const { desiredOutputFormat, runOutputFormat } = resolveOutputFormatConfig(agent);
|
|
1516
|
-
|
|
1519
|
+
let command = [
|
|
1517
1520
|
'zeroshot',
|
|
1518
1521
|
...buildTaskRunArgs({
|
|
1519
1522
|
agent,
|
|
@@ -1531,6 +1534,12 @@ async function spawnClaudeTaskIsolated(agent, context) {
|
|
|
1531
1534
|
});
|
|
1532
1535
|
|
|
1533
1536
|
command.push(finalContext);
|
|
1537
|
+
command = wrapTaskRunWithIsolatedSettings(command, {
|
|
1538
|
+
providerName,
|
|
1539
|
+
settings: loadSettings(),
|
|
1540
|
+
modelSpecSource,
|
|
1541
|
+
modelSpec,
|
|
1542
|
+
});
|
|
1534
1543
|
|
|
1535
1544
|
// STEP 1: Spawn task and extract task ID (same as non-isolated mode)
|
|
1536
1545
|
// Timeout for spawn phase - if CLI hangs during init (e.g., opencode 429 bug), kill it
|
|
@@ -99,7 +99,7 @@ export function validateModelIdFromCatalog(
|
|
|
99
99
|
modelId: string | null | undefined
|
|
100
100
|
): string | null | undefined {
|
|
101
101
|
if (!modelId) return modelId;
|
|
102
|
-
if (catalog
|
|
102
|
+
if (Object.prototype.hasOwnProperty.call(catalog, modelId)) return modelId;
|
|
103
103
|
const validModels = Object.keys(catalog).join(', ');
|
|
104
104
|
throw new InvalidProviderModelError(
|
|
105
105
|
`Invalid model "${modelId}" for provider "${provider}". Valid models: ${validModels}.`
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { unknownToMessage } from '../json';
|
|
2
|
+
import {
|
|
3
|
+
InvalidProviderModelError,
|
|
4
|
+
type LevelModelSpec,
|
|
5
|
+
type LevelOverrides,
|
|
6
|
+
type ModelCatalogEntry,
|
|
7
|
+
type ModelLevel,
|
|
8
|
+
type ResolvedModelSpec,
|
|
9
|
+
} from '../types';
|
|
10
|
+
import { validateModelIdFromCatalog } from './common';
|
|
11
|
+
|
|
12
|
+
export const MODEL_CATALOG: Readonly<Record<string, ModelCatalogEntry>> = {
|
|
13
|
+
'opencode/big-pickle': { rank: 1 },
|
|
14
|
+
'opencode/glm-4.7-free': { rank: 1 },
|
|
15
|
+
'opencode/gpt-5-nano': { rank: 1 },
|
|
16
|
+
'opencode/grok-code': { rank: 1 },
|
|
17
|
+
'opencode/minimax-m2.1-free': { rank: 1 },
|
|
18
|
+
'google/gemini-1.5-flash': { rank: 1 },
|
|
19
|
+
'google/gemini-1.5-flash-8b': { rank: 1 },
|
|
20
|
+
'google/gemini-1.5-pro': { rank: 1 },
|
|
21
|
+
'google/gemini-2.0-flash': { rank: 1 },
|
|
22
|
+
'google/gemini-2.0-flash-lite': { rank: 1 },
|
|
23
|
+
'google/gemini-2.5-flash': { rank: 1 },
|
|
24
|
+
'google/gemini-2.5-flash-image': { rank: 1 },
|
|
25
|
+
'google/gemini-2.5-flash-image-preview': { rank: 1 },
|
|
26
|
+
'google/gemini-2.5-flash-lite': { rank: 1 },
|
|
27
|
+
'google/gemini-2.5-flash-lite-preview-06-17': { rank: 1 },
|
|
28
|
+
'google/gemini-2.5-flash-lite-preview-09-2025': { rank: 1 },
|
|
29
|
+
'google/gemini-2.5-flash-preview-04-17': { rank: 1 },
|
|
30
|
+
'google/gemini-2.5-flash-preview-05-20': { rank: 1 },
|
|
31
|
+
'google/gemini-2.5-flash-preview-09-2025': { rank: 1 },
|
|
32
|
+
'google/gemini-2.5-flash-preview-tts': { rank: 1 },
|
|
33
|
+
'google/gemini-2.5-pro': { rank: 1 },
|
|
34
|
+
'google/gemini-2.5-pro-preview-05-06': { rank: 1 },
|
|
35
|
+
'google/gemini-2.5-pro-preview-06-05': { rank: 1 },
|
|
36
|
+
'google/gemini-2.5-pro-preview-tts': { rank: 1 },
|
|
37
|
+
'google/gemini-3-flash-preview': { rank: 1 },
|
|
38
|
+
'google/gemini-3-pro-preview': { rank: 1 },
|
|
39
|
+
'google/gemini-embedding-001': { rank: 1 },
|
|
40
|
+
'google/gemini-flash-latest': { rank: 1 },
|
|
41
|
+
'google/gemini-flash-lite-latest': { rank: 1 },
|
|
42
|
+
'google/gemini-live-2.5-flash': { rank: 1 },
|
|
43
|
+
'google/gemini-live-2.5-flash-preview-native-audio': { rank: 1 },
|
|
44
|
+
'openai/gpt-5.1-codex-max': { rank: 1 },
|
|
45
|
+
'openai/gpt-5.1-codex-mini': { rank: 1 },
|
|
46
|
+
'openai/gpt-5.2': { rank: 1 },
|
|
47
|
+
'openai/gpt-5.2-codex': { rank: 1 },
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const LEVEL_MAPPING: Readonly<Record<ModelLevel, LevelModelSpec>> = {
|
|
51
|
+
level1: { rank: 1, model: null, reasoningEffort: 'low' },
|
|
52
|
+
level2: { rank: 2, model: null, reasoningEffort: 'medium' },
|
|
53
|
+
level3: { rank: 3, model: null, reasoningEffort: 'high' },
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
function containsControlCharacter(value: string): boolean {
|
|
57
|
+
return Array.from(value).some((character) => {
|
|
58
|
+
const codePoint = character.codePointAt(0);
|
|
59
|
+
return codePoint !== undefined && (codePoint <= 0x1f || codePoint === 0x7f);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function resolveModelSpec(level: ModelLevel, overrides?: LevelOverrides): ResolvedModelSpec {
|
|
64
|
+
const base = LEVEL_MAPPING[level] ?? LEVEL_MAPPING.level2;
|
|
65
|
+
const override = overrides?.[level];
|
|
66
|
+
const selectedModel = override?.model ?? base.model;
|
|
67
|
+
return {
|
|
68
|
+
level,
|
|
69
|
+
model:
|
|
70
|
+
override?.model === undefined || override.model === null
|
|
71
|
+
? (validateModelId(selectedModel) ?? null)
|
|
72
|
+
: (validateConfiguredModelId(selectedModel) ?? null),
|
|
73
|
+
reasoningEffort: override?.reasoningEffort ?? base.reasoningEffort,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function validateConfiguredModelId(
|
|
78
|
+
modelId: string | null | undefined
|
|
79
|
+
): string | null | undefined {
|
|
80
|
+
if (modelId && Object.prototype.hasOwnProperty.call(MODEL_CATALOG, modelId)) return modelId;
|
|
81
|
+
if (typeof modelId !== 'string') return validateModelId(modelId);
|
|
82
|
+
const segments = modelId.split('/');
|
|
83
|
+
if (
|
|
84
|
+
segments.length >= 2 &&
|
|
85
|
+
segments.every(Boolean) &&
|
|
86
|
+
!/\s/u.test(modelId) &&
|
|
87
|
+
!containsControlCharacter(modelId)
|
|
88
|
+
) {
|
|
89
|
+
return modelId;
|
|
90
|
+
}
|
|
91
|
+
throw new InvalidProviderModelError(
|
|
92
|
+
`Invalid configured model "${unknownToMessage(
|
|
93
|
+
modelId
|
|
94
|
+
)}" for provider "opencode". Expected "provider/model" with no whitespace, control characters, or empty path segments.`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function validateModelId(modelId: string | null | undefined): string | null | undefined {
|
|
99
|
+
return validateModelIdFromCatalog('opencode', MODEL_CATALOG, modelId);
|
|
100
|
+
}
|
|
@@ -11,14 +11,9 @@ import {
|
|
|
11
11
|
type BuildProviderCommandOptions,
|
|
12
12
|
type CommandSpec,
|
|
13
13
|
type ErrorClassification,
|
|
14
|
-
type LevelModelSpec,
|
|
15
|
-
type LevelOverrides,
|
|
16
|
-
type ModelCatalogEntry,
|
|
17
|
-
type ModelLevel,
|
|
18
14
|
type OpencodeCliFeatures,
|
|
19
15
|
type OutputEvent,
|
|
20
16
|
type ProviderAdapter,
|
|
21
|
-
type ResolvedModelSpec,
|
|
22
17
|
type WarningMetadata,
|
|
23
18
|
} from '../types';
|
|
24
19
|
import {
|
|
@@ -26,55 +21,16 @@ import {
|
|
|
26
21
|
commandSpec,
|
|
27
22
|
createParserState,
|
|
28
23
|
optionFeatures,
|
|
29
|
-
resolveModelSpecWithConfig,
|
|
30
24
|
unsupportedSessionControlWarnings,
|
|
31
|
-
validateModelIdFromCatalog,
|
|
32
25
|
warning,
|
|
33
26
|
} from './common';
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
'google/gemini-1.5-flash': { rank: 1 },
|
|
42
|
-
'google/gemini-1.5-flash-8b': { rank: 1 },
|
|
43
|
-
'google/gemini-1.5-pro': { rank: 1 },
|
|
44
|
-
'google/gemini-2.0-flash': { rank: 1 },
|
|
45
|
-
'google/gemini-2.0-flash-lite': { rank: 1 },
|
|
46
|
-
'google/gemini-2.5-flash': { rank: 1 },
|
|
47
|
-
'google/gemini-2.5-flash-image': { rank: 1 },
|
|
48
|
-
'google/gemini-2.5-flash-image-preview': { rank: 1 },
|
|
49
|
-
'google/gemini-2.5-flash-lite': { rank: 1 },
|
|
50
|
-
'google/gemini-2.5-flash-lite-preview-06-17': { rank: 1 },
|
|
51
|
-
'google/gemini-2.5-flash-lite-preview-09-2025': { rank: 1 },
|
|
52
|
-
'google/gemini-2.5-flash-preview-04-17': { rank: 1 },
|
|
53
|
-
'google/gemini-2.5-flash-preview-05-20': { rank: 1 },
|
|
54
|
-
'google/gemini-2.5-flash-preview-09-2025': { rank: 1 },
|
|
55
|
-
'google/gemini-2.5-flash-preview-tts': { rank: 1 },
|
|
56
|
-
'google/gemini-2.5-pro': { rank: 1 },
|
|
57
|
-
'google/gemini-2.5-pro-preview-05-06': { rank: 1 },
|
|
58
|
-
'google/gemini-2.5-pro-preview-06-05': { rank: 1 },
|
|
59
|
-
'google/gemini-2.5-pro-preview-tts': { rank: 1 },
|
|
60
|
-
'google/gemini-3-flash-preview': { rank: 1 },
|
|
61
|
-
'google/gemini-3-pro-preview': { rank: 1 },
|
|
62
|
-
'google/gemini-embedding-001': { rank: 1 },
|
|
63
|
-
'google/gemini-flash-latest': { rank: 1 },
|
|
64
|
-
'google/gemini-flash-lite-latest': { rank: 1 },
|
|
65
|
-
'google/gemini-live-2.5-flash': { rank: 1 },
|
|
66
|
-
'google/gemini-live-2.5-flash-preview-native-audio': { rank: 1 },
|
|
67
|
-
'openai/gpt-5.1-codex-max': { rank: 1 },
|
|
68
|
-
'openai/gpt-5.1-codex-mini': { rank: 1 },
|
|
69
|
-
'openai/gpt-5.2': { rank: 1 },
|
|
70
|
-
'openai/gpt-5.2-codex': { rank: 1 },
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const LEVEL_MAPPING: Readonly<Record<ModelLevel, LevelModelSpec>> = {
|
|
74
|
-
level1: { rank: 1, model: null, reasoningEffort: 'low' },
|
|
75
|
-
level2: { rank: 2, model: null, reasoningEffort: 'medium' },
|
|
76
|
-
level3: { rank: 3, model: null, reasoningEffort: 'high' },
|
|
77
|
-
};
|
|
27
|
+
import {
|
|
28
|
+
LEVEL_MAPPING,
|
|
29
|
+
MODEL_CATALOG,
|
|
30
|
+
resolveModelSpec,
|
|
31
|
+
validateConfiguredModelId,
|
|
32
|
+
validateModelId,
|
|
33
|
+
} from './opencode-models';
|
|
78
34
|
|
|
79
35
|
function detectCliFeatures(helpText?: string | null): OpencodeCliFeatures {
|
|
80
36
|
const help = helpText ?? '';
|
|
@@ -244,20 +200,6 @@ function parseEvent(line: string): OutputEvent | null {
|
|
|
244
200
|
return null;
|
|
245
201
|
}
|
|
246
202
|
|
|
247
|
-
function resolveModelSpec(level: ModelLevel, overrides?: LevelOverrides): ResolvedModelSpec {
|
|
248
|
-
return resolveModelSpecWithConfig({
|
|
249
|
-
mapping: LEVEL_MAPPING,
|
|
250
|
-
defaultLevel: 'level2',
|
|
251
|
-
level,
|
|
252
|
-
overrides,
|
|
253
|
-
validateModelId,
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
function validateModelId(modelId: string | null | undefined): string | null | undefined {
|
|
258
|
-
return validateModelIdFromCatalog('opencode', MODEL_CATALOG, modelId);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
203
|
function classifyError(error: unknown): ErrorClassification {
|
|
262
204
|
return classifyBaseProviderError(error, [], []);
|
|
263
205
|
}
|
|
@@ -285,5 +227,6 @@ export const opencodeAdapter: ProviderAdapter = {
|
|
|
285
227
|
createParserState: () => createParserState('opencode'),
|
|
286
228
|
resolveModelSpec,
|
|
287
229
|
validateModelId,
|
|
230
|
+
validateConfiguredModelId,
|
|
288
231
|
classifyError,
|
|
289
232
|
};
|
|
@@ -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
|