@the-open-engine/zeroshot 6.15.0 → 6.17.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/README.md +10 -7
- package/cli/commands/providers.js +1 -0
- package/cli/index.js +45 -4
- package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/codex.js +14 -2
- package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
- package/lib/agent-cli-provider/adapters/common.d.ts +1 -0
- package/lib/agent-cli-provider/adapters/common.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/common.js +14 -0
- package/lib/agent-cli-provider/adapters/common.js.map +1 -1
- package/lib/agent-cli-provider/adapters/index.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/index.js +6 -1
- package/lib/agent-cli-provider/adapters/index.js.map +1 -1
- package/lib/agent-cli-provider/adapters/omp.d.ts +3 -0
- package/lib/agent-cli-provider/adapters/omp.d.ts.map +1 -0
- package/lib/agent-cli-provider/adapters/omp.js +356 -0
- package/lib/agent-cli-provider/adapters/omp.js.map +1 -0
- package/lib/agent-cli-provider/adapters/opencode.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/opencode.js +52 -3
- package/lib/agent-cli-provider/adapters/opencode.js.map +1 -1
- package/lib/agent-cli-provider/contract-actions.d.ts.map +1 -1
- package/lib/agent-cli-provider/contract-actions.js +19 -8
- package/lib/agent-cli-provider/contract-actions.js.map +1 -1
- package/lib/agent-cli-provider/contract-fallback.d.ts.map +1 -1
- package/lib/agent-cli-provider/contract-fallback.js +9 -0
- package/lib/agent-cli-provider/contract-fallback.js.map +1 -1
- package/lib/agent-cli-provider/contract-options.d.ts.map +1 -1
- package/lib/agent-cli-provider/contract-options.js +7 -0
- package/lib/agent-cli-provider/contract-options.js.map +1 -1
- package/lib/agent-cli-provider/errors.d.ts +7 -0
- package/lib/agent-cli-provider/errors.d.ts.map +1 -1
- package/lib/agent-cli-provider/errors.js +14 -0
- package/lib/agent-cli-provider/errors.js.map +1 -1
- package/lib/agent-cli-provider/index.d.ts +1 -1
- package/lib/agent-cli-provider/index.d.ts.map +1 -1
- package/lib/agent-cli-provider/index.js.map +1 -1
- package/lib/agent-cli-provider/provider-registry.d.ts +66 -3
- package/lib/agent-cli-provider/provider-registry.d.ts.map +1 -1
- package/lib/agent-cli-provider/provider-registry.js +54 -2
- package/lib/agent-cli-provider/provider-registry.js.map +1 -1
- package/lib/agent-cli-provider/single-agent-runtime.d.ts +14 -2
- package/lib/agent-cli-provider/single-agent-runtime.d.ts.map +1 -1
- package/lib/agent-cli-provider/single-agent-runtime.js +97 -22
- package/lib/agent-cli-provider/single-agent-runtime.js.map +1 -1
- package/lib/agent-cli-provider/types.d.ts +30 -2
- 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/src/agent/agent-lifecycle.js +52 -1
- package/src/agent/agent-task-executor.js +8 -3
- package/src/agent-cli-provider/adapters/codex.ts +23 -2
- package/src/agent-cli-provider/adapters/common.ts +14 -0
- package/src/agent-cli-provider/adapters/index.ts +16 -2
- package/src/agent-cli-provider/adapters/omp.ts +448 -0
- package/src/agent-cli-provider/adapters/opencode.ts +60 -4
- package/src/agent-cli-provider/contract-actions.ts +20 -9
- package/src/agent-cli-provider/contract-fallback.ts +9 -0
- package/src/agent-cli-provider/contract-options.ts +7 -0
- package/src/agent-cli-provider/errors.ts +14 -0
- package/src/agent-cli-provider/index.ts +2 -0
- package/src/agent-cli-provider/provider-registry.ts +59 -2
- package/src/agent-cli-provider/single-agent-runtime.ts +144 -24
- package/src/agent-cli-provider/types.ts +32 -1
- package/src/claude-task-runner.js +11 -0
- package/src/orchestrator.js +8 -3
- package/src/providers/index.js +6 -0
- package/src/task-run-model-args.js +58 -40
- package/src/task-spawn-cleanup-ownership.js +3 -0
- package/src/task-startup-error.js +68 -0
|
@@ -34,6 +34,7 @@ const {
|
|
|
34
34
|
appendTaskRunModelArgs,
|
|
35
35
|
wrapTaskRunWithIsolatedSettings,
|
|
36
36
|
} = require('./task-run-model-args');
|
|
37
|
+
const { parseTaskStartupError } = require('./task-startup-error');
|
|
37
38
|
|
|
38
39
|
function rejectCallerSuppliedModelProvenance(options) {
|
|
39
40
|
if (Object.prototype.hasOwnProperty.call(options, 'modelSpecSource')) {
|
|
@@ -98,6 +99,7 @@ function runCommand(command, args, options = {}, callback = null) {
|
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
const TASK_TERMINAL_STATUSES = new Set(['completed', 'failed', 'killed', 'stale', 'cancelled']);
|
|
102
|
+
const TASK_STARTUP_STDERR_MAX_CHARS = 500;
|
|
101
103
|
|
|
102
104
|
async function cleanupPersistedTaskAfterLaunchFailure(ctPath, taskId) {
|
|
103
105
|
let lastError = null;
|
|
@@ -808,6 +810,7 @@ class ClaudeTaskRunner extends TaskRunner {
|
|
|
808
810
|
return new Promise((resolve, reject) => {
|
|
809
811
|
let output = '';
|
|
810
812
|
let resolved = false;
|
|
813
|
+
let stderr = '';
|
|
811
814
|
|
|
812
815
|
const proc = manager.spawnInContainer(clusterId, command, {
|
|
813
816
|
env: {
|
|
@@ -828,6 +831,7 @@ class ClaudeTaskRunner extends TaskRunner {
|
|
|
828
831
|
|
|
829
832
|
proc.stderr.on('data', (/** @type {Buffer} */ data) => {
|
|
830
833
|
const chunk = data.toString();
|
|
834
|
+
stderr = `${stderr}${chunk}`.slice(-TASK_STARTUP_STDERR_MAX_CHARS);
|
|
831
835
|
if (!this.quiet) {
|
|
832
836
|
console.error(`[${agentId}] stderr:`, chunk);
|
|
833
837
|
}
|
|
@@ -836,6 +840,13 @@ class ClaudeTaskRunner extends TaskRunner {
|
|
|
836
840
|
proc.on('close', (/** @type {number|null} */ code) => {
|
|
837
841
|
if (resolved) return;
|
|
838
842
|
resolved = true;
|
|
843
|
+
if (code !== 0) {
|
|
844
|
+
const startupError = parseTaskStartupError(stderr);
|
|
845
|
+
if (startupError) {
|
|
846
|
+
reject(startupError);
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
839
850
|
|
|
840
851
|
resolve({
|
|
841
852
|
success: code === 0,
|
package/src/orchestrator.js
CHANGED
|
@@ -2716,12 +2716,17 @@ class Orchestrator {
|
|
|
2716
2716
|
});
|
|
2717
2717
|
|
|
2718
2718
|
for (const error of errors) {
|
|
2719
|
+
const errorData = error.content?.data || {};
|
|
2719
2720
|
const failureInfo = {
|
|
2720
2721
|
agentId: error.sender,
|
|
2721
|
-
taskId:
|
|
2722
|
-
iteration:
|
|
2723
|
-
error:
|
|
2722
|
+
taskId: errorData.taskId || null,
|
|
2723
|
+
iteration: errorData.iteration || 0,
|
|
2724
|
+
error: errorData.error || error.content?.text,
|
|
2724
2725
|
timestamp: error.timestamp,
|
|
2726
|
+
...(errorData.code !== undefined ? { code: errorData.code } : {}),
|
|
2727
|
+
...(errorData.permanent !== undefined ? { permanent: errorData.permanent } : {}),
|
|
2728
|
+
...(errorData.provider !== undefined ? { provider: errorData.provider } : {}),
|
|
2729
|
+
...(errorData.capability !== undefined ? { capability: errorData.capability } : {}),
|
|
2725
2730
|
};
|
|
2726
2731
|
if (this._hasDurableProgressAfterFailure(cluster, clusterId, failureInfo)) {
|
|
2727
2732
|
this._log(
|
package/src/providers/index.js
CHANGED
|
@@ -159,6 +159,12 @@ class RuntimeProvider extends BaseProvider {
|
|
|
159
159
|
validateSettings(settings) {
|
|
160
160
|
const baseError = super.validateSettings(settings);
|
|
161
161
|
if (baseError) return baseError;
|
|
162
|
+
if (
|
|
163
|
+
Object.prototype.hasOwnProperty.call(settings, 'webSearch') &&
|
|
164
|
+
!this._metadata.settingsFields.includes('webSearch')
|
|
165
|
+
) {
|
|
166
|
+
return `Unknown provider setting: providerSettings.${this.name}.webSearch`;
|
|
167
|
+
}
|
|
162
168
|
if (this._metadata.settingsValidator) {
|
|
163
169
|
const providerError = this._metadata.settingsValidator(settings);
|
|
164
170
|
if (providerError) return providerError;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const { providerSupportsCapability } = require('../lib/provider-names');
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Append a resolved model selection to a nested `zeroshot task run` invocation.
|
|
3
5
|
*
|
|
@@ -61,9 +63,9 @@ try {
|
|
|
61
63
|
|
|
62
64
|
/**
|
|
63
65
|
* Wrap an isolated task command with a Docker-only, temporary settings-file
|
|
64
|
-
* bootstrap. The snapshot is a closed projection containing only
|
|
65
|
-
*
|
|
66
|
-
* credentials
|
|
66
|
+
* bootstrap. The snapshot is a closed projection containing only an enabled
|
|
67
|
+
* native-search control and, when needed, the selected OpenCode level/model.
|
|
68
|
+
* It never contains credentials or caller-owned keys.
|
|
67
69
|
*
|
|
68
70
|
* @param {string[]} command
|
|
69
71
|
* @param {{providerName: string, settings: Object, modelSpecSource: 'direct'|'provider-level', modelSpec: Object|null|undefined}} context
|
|
@@ -71,57 +73,73 @@ try {
|
|
|
71
73
|
*/
|
|
72
74
|
function wrapTaskRunWithIsolatedSettings(command, context) {
|
|
73
75
|
const { providerName, settings, modelSpecSource, modelSpec } = context;
|
|
74
|
-
if (providerName
|
|
75
|
-
const
|
|
76
|
+
if (!providerSupportsCapability(providerName, 'webSearch')) return command;
|
|
77
|
+
const includesOpencodeModel =
|
|
78
|
+
providerName === 'opencode' && modelSpecSource === 'provider-level';
|
|
79
|
+
const snapshot = buildIsolatedSettingsSnapshot(
|
|
80
|
+
settings,
|
|
81
|
+
providerName,
|
|
82
|
+
includesOpencodeModel ? modelSpec : null
|
|
83
|
+
);
|
|
76
84
|
if (snapshot === null) return command;
|
|
77
85
|
return ['node', '-e', SETTINGS_BOOTSTRAP_SCRIPT, snapshot, ...command];
|
|
78
86
|
}
|
|
79
87
|
|
|
80
|
-
function buildIsolatedSettingsSnapshot(settings,
|
|
81
|
-
const level = modelSpec?.level;
|
|
82
|
-
if (!['level1', 'level2', 'level3'].includes(level)) {
|
|
83
|
-
throw permanentError(
|
|
84
|
-
'Provider-level isolated OpenCode selections require a valid model level.'
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
+
function buildIsolatedSettingsSnapshot(settings, providerName, opencodeModelSpec) {
|
|
88
89
|
const providerSettings = ownRecordValue(settings, 'providerSettings', 'settings') ?? {};
|
|
89
|
-
const
|
|
90
|
+
const selectedSettings = ownRecordValue(
|
|
90
91
|
providerSettings,
|
|
91
|
-
|
|
92
|
+
providerName,
|
|
92
93
|
'settings.providerSettings'
|
|
93
94
|
);
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
'settings.providerSettings.opencode'
|
|
98
|
-
);
|
|
99
|
-
const levelOverride = ownRecordValue(
|
|
100
|
-
levelOverrides,
|
|
101
|
-
level,
|
|
102
|
-
'settings.providerSettings.opencode.levelOverrides'
|
|
103
|
-
);
|
|
104
|
-
const configuredModel =
|
|
105
|
-
levelOverride && Object.prototype.hasOwnProperty.call(levelOverride, 'model')
|
|
106
|
-
? levelOverride.model
|
|
107
|
-
: null;
|
|
108
|
-
if (configuredModel !== null && typeof configuredModel !== 'string') {
|
|
109
|
-
throw permanentError(`Configured isolated OpenCode ${level} model must be a string or null.`);
|
|
95
|
+
const webSearch = selectedSettings?.webSearch;
|
|
96
|
+
if (webSearch !== undefined && typeof webSearch !== 'boolean') {
|
|
97
|
+
throw permanentError(`settings.providerSettings.${providerName}.webSearch must be a boolean.`);
|
|
110
98
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
99
|
+
|
|
100
|
+
const snapshot = {};
|
|
101
|
+
if (webSearch === true) snapshot.webSearch = true;
|
|
102
|
+
if (opencodeModelSpec !== null) {
|
|
103
|
+
const level = opencodeModelSpec?.level;
|
|
104
|
+
if (!['level1', 'level2', 'level3'].includes(level)) {
|
|
105
|
+
throw permanentError(
|
|
106
|
+
'Provider-level isolated OpenCode selections require a valid model level.'
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const levelOverrides = ownRecordValue(
|
|
111
|
+
selectedSettings,
|
|
112
|
+
'levelOverrides',
|
|
113
|
+
'settings.providerSettings.opencode'
|
|
114
|
+
);
|
|
115
|
+
const levelOverride = ownRecordValue(
|
|
116
|
+
levelOverrides,
|
|
117
|
+
level,
|
|
118
|
+
'settings.providerSettings.opencode.levelOverrides'
|
|
114
119
|
);
|
|
120
|
+
const configuredModel =
|
|
121
|
+
levelOverride && Object.prototype.hasOwnProperty.call(levelOverride, 'model')
|
|
122
|
+
? levelOverride.model
|
|
123
|
+
: null;
|
|
124
|
+
if (configuredModel !== null && typeof configuredModel !== 'string') {
|
|
125
|
+
throw permanentError(`Configured isolated OpenCode ${level} model must be a string or null.`);
|
|
126
|
+
}
|
|
127
|
+
if (opencodeModelSpec.model !== configuredModel) {
|
|
128
|
+
throw permanentError(
|
|
129
|
+
`Provider-level model "${opencodeModelSpec.model}" does not match the effective isolated ${level} model "${configuredModel}".`
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
if (configuredModel !== null) {
|
|
133
|
+
snapshot.levelOverrides = {
|
|
134
|
+
[level]: { model: configuredModel },
|
|
135
|
+
};
|
|
136
|
+
}
|
|
115
137
|
}
|
|
116
|
-
if (configuredModel === null) return null;
|
|
117
138
|
|
|
139
|
+
if (Object.keys(snapshot).length === 0) return null;
|
|
118
140
|
return JSON.stringify({
|
|
119
141
|
providerSettings: {
|
|
120
|
-
|
|
121
|
-
levelOverrides: {
|
|
122
|
-
[level]: { model: configuredModel },
|
|
123
|
-
},
|
|
124
|
-
},
|
|
142
|
+
[providerName]: snapshot,
|
|
125
143
|
},
|
|
126
144
|
});
|
|
127
145
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const { randomUUID } = require('node:crypto');
|
|
2
|
+
const { parseTaskStartupError } = require('./task-startup-error');
|
|
2
3
|
|
|
3
4
|
const TASK_SPAWN_OWNERSHIP_TOKEN_ENV = 'ZEROSHOT_TASK_SPAWN_OWNERSHIP_TOKEN';
|
|
4
5
|
|
|
@@ -38,6 +39,8 @@ function requireTaskIdFromWrapperResult({
|
|
|
38
39
|
persistedTaskId = null,
|
|
39
40
|
}) {
|
|
40
41
|
if (code !== 0) {
|
|
42
|
+
const startupError = parseTaskStartupError(stderr);
|
|
43
|
+
if (startupError) throw startupError;
|
|
41
44
|
throw new Error(`zeroshot task run failed with code ${code}: ${stderr}`);
|
|
42
45
|
}
|
|
43
46
|
if (!persistedTaskId) {
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const TASK_STARTUP_ERROR_PREFIX = 'ZEROSHOT_TASK_STARTUP_ERROR:';
|
|
2
|
+
const SUPPORTED_STARTUP_ERROR_CODES = new Set(['unsupported-capability']);
|
|
3
|
+
|
|
4
|
+
function createUnsupportedProviderCapabilityError(provider, capability, message) {
|
|
5
|
+
const error = new Error(message);
|
|
6
|
+
error.name = 'UnsupportedProviderCapabilityError';
|
|
7
|
+
error.code = 'unsupported-capability';
|
|
8
|
+
error.permanent = true;
|
|
9
|
+
error.provider = provider;
|
|
10
|
+
error.capability = capability;
|
|
11
|
+
return error;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function serializeTaskStartupError(error) {
|
|
15
|
+
if (
|
|
16
|
+
!SUPPORTED_STARTUP_ERROR_CODES.has(error?.code) ||
|
|
17
|
+
error?.permanent !== true
|
|
18
|
+
) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const payload = {
|
|
22
|
+
version: 1,
|
|
23
|
+
code: error.code,
|
|
24
|
+
permanent: true,
|
|
25
|
+
message: String(error.message || error.code),
|
|
26
|
+
};
|
|
27
|
+
if (typeof error.provider === 'string') payload.provider = error.provider;
|
|
28
|
+
if (typeof error.capability === 'string') payload.capability = error.capability;
|
|
29
|
+
return `${TASK_STARTUP_ERROR_PREFIX}${JSON.stringify(payload)}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function parseTaskStartupError(stderr) {
|
|
33
|
+
const lines = String(stderr || '').split(/\r?\n/);
|
|
34
|
+
let line = lines.pop();
|
|
35
|
+
while (line === '' && lines.length > 0) line = lines.pop();
|
|
36
|
+
if (!line?.startsWith(TASK_STARTUP_ERROR_PREFIX)) return null;
|
|
37
|
+
|
|
38
|
+
let parsed;
|
|
39
|
+
try {
|
|
40
|
+
parsed = JSON.parse(line.slice(TASK_STARTUP_ERROR_PREFIX.length));
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
if (
|
|
45
|
+
parsed?.version !== 1 ||
|
|
46
|
+
!SUPPORTED_STARTUP_ERROR_CODES.has(parsed.code) ||
|
|
47
|
+
parsed.permanent !== true ||
|
|
48
|
+
typeof parsed.message !== 'string' ||
|
|
49
|
+
parsed.message.length === 0 ||
|
|
50
|
+
(parsed.provider !== undefined && typeof parsed.provider !== 'string') ||
|
|
51
|
+
(parsed.capability !== undefined && typeof parsed.capability !== 'string')
|
|
52
|
+
) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const error = new Error(parsed.message);
|
|
56
|
+
error.code = parsed.code;
|
|
57
|
+
error.permanent = true;
|
|
58
|
+
if (parsed.provider !== undefined) error.provider = parsed.provider;
|
|
59
|
+
if (parsed.capability !== undefined) error.capability = parsed.capability;
|
|
60
|
+
return error;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = {
|
|
64
|
+
TASK_STARTUP_ERROR_PREFIX,
|
|
65
|
+
createUnsupportedProviderCapabilityError,
|
|
66
|
+
parseTaskStartupError,
|
|
67
|
+
serializeTaskStartupError,
|
|
68
|
+
};
|