@the-open-engine/zeroshot 6.39.0 → 6.39.2
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 +39 -1
- package/cli/index.js +90 -24
- package/cluster-templates/conductor-bootstrap.json +1 -1
- package/lib/agent-cli-provider/adapters/claude.js +1 -1
- 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 +26 -1
- package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
- package/lib/agent-cli-provider/adapters/omp.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/omp.js +1 -1
- package/lib/agent-cli-provider/adapters/omp.js.map +1 -1
- package/lib/agent-cli-provider/omp/sdk-environment-policy.d.ts +4 -0
- package/lib/agent-cli-provider/omp/sdk-environment-policy.d.ts.map +1 -0
- package/lib/agent-cli-provider/omp/sdk-environment-policy.js +37 -0
- package/lib/agent-cli-provider/omp/sdk-environment-policy.js.map +1 -0
- package/lib/agent-cli-provider/omp/sdk-process-private-runtime.d.ts.map +1 -1
- package/lib/agent-cli-provider/omp/sdk-process-private-runtime.js +4 -15
- package/lib/agent-cli-provider/omp/sdk-process-private-runtime.js.map +1 -1
- package/lib/agent-cli-provider/omp/sdk-process-result.d.ts +2 -0
- package/lib/agent-cli-provider/omp/sdk-process-result.d.ts.map +1 -1
- package/lib/agent-cli-provider/omp/sdk-process-result.js +2 -2
- package/lib/agent-cli-provider/omp/sdk-process-result.js.map +1 -1
- package/lib/agent-cli-provider/omp/sdk-process-runner.d.ts.map +1 -1
- package/lib/agent-cli-provider/omp/sdk-process-runner.js +6 -1
- package/lib/agent-cli-provider/omp/sdk-process-runner.js.map +1 -1
- package/lib/agent-cli-provider/provider-registry.d.ts +3 -1
- package/lib/agent-cli-provider/provider-registry.d.ts.map +1 -1
- package/lib/agent-cli-provider/provider-registry.js +9 -2
- package/lib/agent-cli-provider/provider-registry.js.map +1 -1
- package/lib/agent-cli-provider/single-agent-runtime.d.ts +4 -1
- package/lib/agent-cli-provider/single-agent-runtime.d.ts.map +1 -1
- package/lib/agent-cli-provider/single-agent-runtime.js +18 -15
- package/lib/agent-cli-provider/single-agent-runtime.js.map +1 -1
- package/lib/agent-cli-provider/types.d.ts +3 -0
- package/lib/agent-cli-provider/types.d.ts.map +1 -1
- package/lib/agent-cli-provider/types.js.map +1 -1
- package/lib/cluster-worker/engine-adapter-common.js +18 -0
- package/lib/cluster-worker/engine-adapter.js +2 -1
- package/lib/detached-startup.d.ts +1 -0
- package/lib/detached-startup.js +2 -1
- package/lib/git-remote-utils.js +22 -5
- package/lib/start-cluster-environment.d.ts +1 -0
- package/lib/start-cluster-run-options.d.ts +1 -0
- package/lib/start-cluster-run-options.js +1 -0
- package/npm-shrinkwrap.json +6 -8
- package/package.json +4 -3
- package/scripts/omp/runtime-identities.js +31 -18
- package/scripts/omp/runtime.js +2 -0
- package/scripts/rust-distribution.js +13 -31
- package/src/agent/agent-lifecycle.js +17 -1
- package/src/agent/output-extraction-failures.js +73 -0
- package/src/agent/output-extraction-failures.ts +100 -0
- package/src/agent/output-extraction-types.ts +5 -0
- package/src/agent/provider-terminal-failure.js +2 -2
- package/src/agent/provider-terminal-failure.ts +4 -2
- package/src/agent-cli-provider/adapters/claude.ts +1 -1
- package/src/agent-cli-provider/adapters/codex.ts +36 -1
- package/src/agent-cli-provider/adapters/omp.ts +2 -1
- package/src/agent-cli-provider/omp/sdk-environment-policy.ts +38 -0
- package/src/agent-cli-provider/omp/sdk-process-private-runtime.ts +4 -16
- package/src/agent-cli-provider/omp/sdk-process-result.ts +4 -2
- package/src/agent-cli-provider/omp/sdk-process-runner.ts +7 -1
- package/src/agent-cli-provider/provider-registry.ts +10 -2
- package/src/agent-cli-provider/single-agent-runtime.ts +24 -15
- package/src/agent-cli-provider/types.ts +3 -0
- package/src/agents/git-pusher-template.js +78 -105
- package/src/attach/socket-paths.js +1 -1
- package/src/attach/socket-paths.ts +1 -1
- package/src/copy-containment.js +191 -0
- package/src/copy-containment.ts +259 -0
- package/src/copy-worker.js +29 -30
- package/src/copy-worker.ts +43 -30
- package/src/foreground-benchmark-run.js +24 -12
- package/src/isolation-manager.js +59 -20
- package/src/legacy-lib/detached-startup.ts +3 -1
- package/src/legacy-lib/git-remote-utils.ts +23 -5
- package/src/legacy-lib/start-cluster-environment.ts +1 -0
- package/src/legacy-lib/start-cluster-run-options.ts +2 -0
- package/src/omp-session-verifier.js +8 -5
- package/src/orchestrator.js +55 -3
- package/src/pr-body-template.js +71 -0
- package/src/preflight.js +31 -6
- package/src/providers/index.js +3 -3
- package/src/task-execution-context.js +22 -0
- package/src/watcher-prompt-channel.js +1 -1
- package/src/worktree-claude-config.js +25 -0
- package/src/worktree-claude-config.ts +28 -0
- package/task-lib/runner.js +57 -22
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const TASK_EXECUTION_CONTEXT_ENV = 'ZEROSHOT_TASK_EXECUTION_CONTEXT';
|
|
4
|
+
const TASK_EXECUTION_CONTEXTS = Object.freeze(['host', 'detached', 'docker', 'benchmark']);
|
|
5
|
+
const taskExecutionContexts = new Set(TASK_EXECUTION_CONTEXTS);
|
|
6
|
+
|
|
7
|
+
function resolveTaskExecutionContext(environment = process.env) {
|
|
8
|
+
const context = environment[TASK_EXECUTION_CONTEXT_ENV];
|
|
9
|
+
if (context === undefined) return 'detached';
|
|
10
|
+
if (!taskExecutionContexts.has(context)) {
|
|
11
|
+
throw new Error(
|
|
12
|
+
`${TASK_EXECUTION_CONTEXT_ENV} must be one of: ${TASK_EXECUTION_CONTEXTS.join(', ')}.`
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
return context;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
TASK_EXECUTION_CONTEXT_ENV,
|
|
20
|
+
TASK_EXECUTION_CONTEXTS,
|
|
21
|
+
resolveTaskExecutionContext,
|
|
22
|
+
};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* The OMP prompt is task content (repository text, instructions, whatever a caller pasted in), so
|
|
5
5
|
* it must never travel in the watcher's argv: `ps` and /proc/<pid>/cmdline expose argv to every
|
|
6
6
|
* local user for the entire lifetime of a long-lived watcher. task-lib/runner.js therefore hands
|
|
7
|
-
* the prompt to task-lib/rpc-watcher.js over
|
|
7
|
+
* the prompt to task-lib/rpc-watcher.js over its anonymous stdin pipe. The
|
|
8
8
|
* pipe has exactly two ends and no name, so nothing is written to the filesystem, the task log, or
|
|
9
9
|
* the ledger while the prompt is in transit.
|
|
10
10
|
*
|
|
@@ -12,6 +12,11 @@ const CLAUDE_SETTINGS_ENV = 'ZEROSHOT_CLAUDE_SETTINGS_FILE';
|
|
|
12
12
|
const CLAUDE_MCP_CONFIG_ENV = 'ZEROSHOT_CLAUDE_MCP_CONFIG_FILE';
|
|
13
13
|
const ASK_USER_HOOK = 'block-ask-user-question.py';
|
|
14
14
|
const DANGEROUS_GIT_HOOK = 'block-dangerous-git.py';
|
|
15
|
+
const ALTERNATE_BACKEND_ENV = [
|
|
16
|
+
'CLAUDE_CODE_USE_BEDROCK',
|
|
17
|
+
'CLAUDE_CODE_USE_VERTEX',
|
|
18
|
+
'CLAUDE_CODE_USE_FOUNDRY',
|
|
19
|
+
];
|
|
15
20
|
function isMutableRecord(value) {
|
|
16
21
|
return typeof value === 'object' && value !== null;
|
|
17
22
|
}
|
|
@@ -109,6 +114,25 @@ function ensureDangerousGitHook(targetClaudeDir) {
|
|
|
109
114
|
writeSettings(settingsPath, settings);
|
|
110
115
|
}
|
|
111
116
|
}
|
|
117
|
+
function ensureExplicitGatewayBackend(targetClaudeDir, environment) {
|
|
118
|
+
if (!environment.ANTHROPIC_AUTH_TOKEN?.trim() || !environment.ANTHROPIC_BASE_URL?.trim())
|
|
119
|
+
return;
|
|
120
|
+
const overlayDir = requireTargetClaudeDir(targetClaudeDir);
|
|
121
|
+
const settingsPath = path.join(overlayDir, SETTINGS_BASENAME);
|
|
122
|
+
const settings = readSettings(settingsPath);
|
|
123
|
+
const existingEnv = settings.env;
|
|
124
|
+
let env = {};
|
|
125
|
+
if (existingEnv !== undefined) {
|
|
126
|
+
if (!isMutableRecord(existingEnv)) {
|
|
127
|
+
throw new TypeError('Claude settings env must be an object.');
|
|
128
|
+
}
|
|
129
|
+
env = { ...existingEnv };
|
|
130
|
+
}
|
|
131
|
+
for (const name of ALTERNATE_BACKEND_ENV)
|
|
132
|
+
env[name] = '0';
|
|
133
|
+
settings.env = env;
|
|
134
|
+
writeSettings(settingsPath, settings);
|
|
135
|
+
}
|
|
112
136
|
function prepareClaudeSettingsOverlay(options = {}) {
|
|
113
137
|
const overlayDir = fs.mkdtempSync(path.join(os.tmpdir(), OVERLAY_PREFIX));
|
|
114
138
|
fs.chmodSync(overlayDir, 0o700);
|
|
@@ -116,6 +140,7 @@ function prepareClaudeSettingsOverlay(options = {}) {
|
|
|
116
140
|
ensureAskUserQuestionHook(overlayDir);
|
|
117
141
|
if (options.includeDangerousGit)
|
|
118
142
|
ensureDangerousGitHook(overlayDir);
|
|
143
|
+
ensureExplicitGatewayBackend(overlayDir, options.environment || process.env);
|
|
119
144
|
return path.join(overlayDir, SETTINGS_BASENAME);
|
|
120
145
|
}
|
|
121
146
|
catch (error) {
|
|
@@ -19,6 +19,7 @@ interface HookEntry {
|
|
|
19
19
|
|
|
20
20
|
interface OverlayOptions {
|
|
21
21
|
includeDangerousGit?: boolean;
|
|
22
|
+
environment?: NodeJS.ProcessEnv;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
interface WorktreeOptions {
|
|
@@ -34,6 +35,11 @@ const CLAUDE_SETTINGS_ENV = 'ZEROSHOT_CLAUDE_SETTINGS_FILE';
|
|
|
34
35
|
const CLAUDE_MCP_CONFIG_ENV = 'ZEROSHOT_CLAUDE_MCP_CONFIG_FILE';
|
|
35
36
|
const ASK_USER_HOOK = 'block-ask-user-question.py';
|
|
36
37
|
const DANGEROUS_GIT_HOOK = 'block-dangerous-git.py';
|
|
38
|
+
const ALTERNATE_BACKEND_ENV = [
|
|
39
|
+
'CLAUDE_CODE_USE_BEDROCK',
|
|
40
|
+
'CLAUDE_CODE_USE_VERTEX',
|
|
41
|
+
'CLAUDE_CODE_USE_FOUNDRY',
|
|
42
|
+
] as const;
|
|
37
43
|
|
|
38
44
|
function isMutableRecord(value: unknown): value is MutableRecord {
|
|
39
45
|
return typeof value === 'object' && value !== null;
|
|
@@ -155,12 +161,34 @@ function ensureDangerousGitHook(targetClaudeDir: unknown): void {
|
|
|
155
161
|
}
|
|
156
162
|
}
|
|
157
163
|
|
|
164
|
+
function ensureExplicitGatewayBackend(
|
|
165
|
+
targetClaudeDir: unknown,
|
|
166
|
+
environment: NodeJS.ProcessEnv
|
|
167
|
+
): void {
|
|
168
|
+
if (!environment.ANTHROPIC_AUTH_TOKEN?.trim() || !environment.ANTHROPIC_BASE_URL?.trim()) return;
|
|
169
|
+
const overlayDir = requireTargetClaudeDir(targetClaudeDir);
|
|
170
|
+
const settingsPath = path.join(overlayDir, SETTINGS_BASENAME);
|
|
171
|
+
const settings = readSettings(settingsPath);
|
|
172
|
+
const existingEnv = settings.env;
|
|
173
|
+
let env: MutableRecord = {};
|
|
174
|
+
if (existingEnv !== undefined) {
|
|
175
|
+
if (!isMutableRecord(existingEnv)) {
|
|
176
|
+
throw new TypeError('Claude settings env must be an object.');
|
|
177
|
+
}
|
|
178
|
+
env = { ...existingEnv };
|
|
179
|
+
}
|
|
180
|
+
for (const name of ALTERNATE_BACKEND_ENV) env[name] = '0';
|
|
181
|
+
settings.env = env;
|
|
182
|
+
writeSettings(settingsPath, settings);
|
|
183
|
+
}
|
|
184
|
+
|
|
158
185
|
function prepareClaudeSettingsOverlay(options: OverlayOptions = {}): string {
|
|
159
186
|
const overlayDir = fs.mkdtempSync(path.join(os.tmpdir(), OVERLAY_PREFIX));
|
|
160
187
|
fs.chmodSync(overlayDir, 0o700);
|
|
161
188
|
try {
|
|
162
189
|
ensureAskUserQuestionHook(overlayDir);
|
|
163
190
|
if (options.includeDangerousGit) ensureDangerousGitHook(overlayDir);
|
|
191
|
+
ensureExplicitGatewayBackend(overlayDir, options.environment || process.env);
|
|
164
192
|
return path.join(overlayDir, SETTINGS_BASENAME);
|
|
165
193
|
} catch (error) {
|
|
166
194
|
fs.rmSync(overlayDir, { recursive: true, force: true });
|
package/task-lib/runner.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { join, dirname, resolve as resolvePath } from 'path';
|
|
1
|
+
import { execFileSync, spawn } from 'child_process';
|
|
2
|
+
import { isAbsolute, join, dirname, relative, resolve as resolvePath } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import { mkdirSync } from 'fs';
|
|
5
5
|
import { LOGS_DIR } from './config.js';
|
|
@@ -17,6 +17,8 @@ import {
|
|
|
17
17
|
import { createRequire } from 'module';
|
|
18
18
|
|
|
19
19
|
const require = createRequire(import.meta.url);
|
|
20
|
+
const { resolveTaskExecutionContext } = require('../src/task-execution-context.js');
|
|
21
|
+
export { resolveTaskExecutionContext };
|
|
20
22
|
const {
|
|
21
23
|
buildOmpPrompt,
|
|
22
24
|
getProviderRegistryEntry,
|
|
@@ -43,8 +45,6 @@ const {
|
|
|
43
45
|
partitionPathFor,
|
|
44
46
|
createOmpSessionPartitionDirectory,
|
|
45
47
|
} = require('../src/omp-session-partition');
|
|
46
|
-
const TASK_EXECUTION_CONTEXT_ENV = 'ZEROSHOT_TASK_EXECUTION_CONTEXT';
|
|
47
|
-
const TASK_EXECUTION_CONTEXTS = new Set(['host', 'detached', 'docker', 'benchmark']);
|
|
48
48
|
export {
|
|
49
49
|
isOwnedProcessTreeRunning,
|
|
50
50
|
isProcessRunning,
|
|
@@ -401,8 +401,22 @@ function resolveOutputFormat(options) {
|
|
|
401
401
|
}
|
|
402
402
|
|
|
403
403
|
function resolveJsonSchema(options, outputFormat) {
|
|
404
|
-
let jsonSchema = options.jsonSchema
|
|
405
|
-
if (jsonSchema
|
|
404
|
+
let jsonSchema = options.jsonSchema ?? null;
|
|
405
|
+
if (typeof jsonSchema === 'string') {
|
|
406
|
+
try {
|
|
407
|
+
jsonSchema = JSON.parse(jsonSchema);
|
|
408
|
+
} catch (error) {
|
|
409
|
+
throw new Error(`--json-schema must be valid JSON: ${error.message}`);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (
|
|
413
|
+
jsonSchema !== null &&
|
|
414
|
+
typeof jsonSchema !== 'boolean' &&
|
|
415
|
+
(typeof jsonSchema !== 'object' || Array.isArray(jsonSchema))
|
|
416
|
+
) {
|
|
417
|
+
throw new Error('--json-schema must be a boolean or JSON Schema object.');
|
|
418
|
+
}
|
|
419
|
+
if (jsonSchema !== null && outputFormat !== 'json') {
|
|
406
420
|
console.warn('Warning: --json-schema requires --output-format json, ignoring schema');
|
|
407
421
|
jsonSchema = null;
|
|
408
422
|
}
|
|
@@ -411,11 +425,13 @@ function resolveJsonSchema(options, outputFormat) {
|
|
|
411
425
|
|
|
412
426
|
function buildProviderOptions(options, runtime, modelSelection) {
|
|
413
427
|
const structuredOutputRecovery = options.structuredOutputRecovery === true;
|
|
428
|
+
const executionContext = resolveTaskExecutionContext();
|
|
414
429
|
return {
|
|
415
430
|
outputFormat: runtime.outputFormat,
|
|
416
431
|
jsonSchema: runtime.jsonSchema,
|
|
417
432
|
cwd: runtime.cwd,
|
|
418
|
-
executionContext
|
|
433
|
+
...codexGitMetadataOption(options, runtime.cwd, executionContext),
|
|
434
|
+
executionContext,
|
|
419
435
|
autoApprove: !structuredOutputRecovery,
|
|
420
436
|
...(modelSelection === undefined ? {} : { modelSpec: modelSelection.modelSpec }),
|
|
421
437
|
...(structuredOutputRecovery ? {} : mcpConfigOption(options)),
|
|
@@ -430,15 +446,35 @@ function buildProviderOptions(options, runtime, modelSelection) {
|
|
|
430
446
|
};
|
|
431
447
|
}
|
|
432
448
|
|
|
433
|
-
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
449
|
+
function codexGitMetadataOption(options, cwd, executionContext) {
|
|
450
|
+
const settings = loadSettings();
|
|
451
|
+
const providerName = normalizeProviderName(
|
|
452
|
+
options.provider || settings.defaultProvider || getDefaultProviderId()
|
|
453
|
+
);
|
|
454
|
+
if (providerName !== 'codex') return {};
|
|
455
|
+
if (executionContext === 'docker' || executionContext === 'benchmark') return {};
|
|
456
|
+
const directories = resolveCodexGitMetadataDirectories(cwd);
|
|
457
|
+
return directories.length === 0 ? {} : { additionalWritableDirectories: directories };
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
export function resolveCodexGitMetadataDirectories(cwd, runGit = execFileSync) {
|
|
461
|
+
try {
|
|
462
|
+
const raw = runGit('git', ['rev-parse', '--git-common-dir'], {
|
|
463
|
+
cwd,
|
|
464
|
+
encoding: 'utf8',
|
|
465
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
466
|
+
});
|
|
467
|
+
const commonDirectory = resolvePath(cwd, raw.trim());
|
|
468
|
+
const fromWorkspace = relative(resolvePath(cwd), commonDirectory);
|
|
469
|
+
const outsideWorkspace =
|
|
470
|
+
isAbsolute(fromWorkspace) ||
|
|
471
|
+
fromWorkspace === '..' ||
|
|
472
|
+
fromWorkspace.startsWith('../') ||
|
|
473
|
+
fromWorkspace.startsWith('..\\');
|
|
474
|
+
return outsideWorkspace ? [commonDirectory] : [];
|
|
475
|
+
} catch {
|
|
476
|
+
return [];
|
|
440
477
|
}
|
|
441
|
-
return context;
|
|
442
478
|
}
|
|
443
479
|
|
|
444
480
|
function claudeSettingsFileOption() {
|
|
@@ -655,14 +691,14 @@ function resolveWatcherScript(options, providerName, invoke) {
|
|
|
655
691
|
function spawnWatcher({ watcherScript, id, cwd, logFile, finalArgs, watcherConfig, rpcPrompt }) {
|
|
656
692
|
const sendsPrompt = typeof rpcPrompt === 'string';
|
|
657
693
|
const watcherEnv = buildWatcherEnv();
|
|
658
|
-
const watcher =
|
|
659
|
-
|
|
660
|
-
[id, cwd, logFile, JSON.stringify(finalArgs), JSON.stringify(watcherConfig)],
|
|
694
|
+
const watcher = spawn(
|
|
695
|
+
process.execPath,
|
|
696
|
+
[watcherScript, id, cwd, logFile, JSON.stringify(finalArgs), JSON.stringify(watcherConfig)],
|
|
661
697
|
{
|
|
662
698
|
detached: true,
|
|
663
|
-
// A prompt-carrying lane needs a
|
|
664
|
-
//
|
|
665
|
-
stdio: sendsPrompt ? ['pipe', 'ignore', 'ignore'
|
|
699
|
+
// A prompt-carrying lane needs only a private stdin pipe; detached watchers have no parent
|
|
700
|
+
// messaging contract, so an IPC channel would add a second, racy wrapper-lifetime owner.
|
|
701
|
+
stdio: sendsPrompt ? ['pipe', 'ignore', 'ignore'] : 'ignore',
|
|
666
702
|
windowsHide: true,
|
|
667
703
|
env: watcherEnv,
|
|
668
704
|
}
|
|
@@ -673,7 +709,6 @@ function spawnWatcher({ watcherScript, id, cwd, logFile, finalArgs, watcherConfi
|
|
|
673
709
|
if (sendsPrompt) sendWatcherPrompt(watcher.stdin, rpcPrompt);
|
|
674
710
|
|
|
675
711
|
watcher.unref();
|
|
676
|
-
watcher.disconnect(); // Close IPC channel so parent can exit
|
|
677
712
|
}
|
|
678
713
|
|
|
679
714
|
export function buildWatcherEnv(sourceEnv = process.env) {
|