subharness 0.0.1 → 0.0.3
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/LICENSE +201 -21
- package/README.md +51 -18
- package/dist/adapters/claude-process.d.ts +10 -0
- package/dist/adapters/claude-process.js +58 -0
- package/dist/adapters/claude-process.js.map +1 -0
- package/dist/adapters/claude.js +52 -10
- package/dist/adapters/claude.js.map +1 -1
- package/dist/adapters/codex-input.d.ts +2 -0
- package/dist/adapters/codex-input.js +14 -0
- package/dist/adapters/codex-input.js.map +1 -0
- package/dist/adapters/codex-permissions.d.ts +13 -0
- package/dist/adapters/codex-permissions.js +30 -0
- package/dist/adapters/codex-permissions.js.map +1 -0
- package/dist/adapters/codex.js +12 -6
- package/dist/adapters/codex.js.map +1 -1
- package/dist/adapters/fx-auth.js +3 -0
- package/dist/adapters/fx-auth.js.map +1 -1
- package/dist/adapters/fx-permissions.d.ts +3 -0
- package/dist/adapters/fx-permissions.js +128 -0
- package/dist/adapters/fx-permissions.js.map +1 -0
- package/dist/adapters/fx.js +4 -0
- package/dist/adapters/fx.js.map +1 -1
- package/dist/cli/args.d.ts +3 -1
- package/dist/cli/args.js +18 -12
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/dashboard-client.d.ts +3 -0
- package/dist/cli/dashboard-client.js +78 -0
- package/dist/cli/dashboard-client.js.map +1 -0
- package/dist/cli/dashboard-layout.d.ts +21 -0
- package/dist/cli/dashboard-layout.js +211 -0
- package/dist/cli/dashboard-layout.js.map +1 -0
- package/dist/cli/dashboard-renderer.d.ts +30 -0
- package/dist/cli/dashboard-renderer.js +80 -0
- package/dist/cli/dashboard-renderer.js.map +1 -0
- package/dist/cli/dashboard.d.ts +31 -0
- package/dist/cli/dashboard.js +81 -0
- package/dist/cli/dashboard.js.map +1 -0
- package/dist/cli/help.d.ts +1 -1
- package/dist/cli/help.js +35 -9
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/main.js +19 -6
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/output.js +10 -1
- package/dist/cli/output.js.map +1 -1
- package/dist/config/access.js +4 -4
- package/dist/config/access.js.map +1 -1
- package/dist/config/loader.js +2 -2
- package/dist/config/loader.js.map +1 -1
- package/dist/runtime/client.d.ts +5 -1
- package/dist/runtime/client.js +91 -40
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/coordinator.d.ts +7 -1
- package/dist/runtime/coordinator.js +72 -8
- package/dist/runtime/coordinator.js.map +1 -1
- package/dist/runtime/daemon.js +100 -18
- package/dist/runtime/daemon.js.map +1 -1
- package/dist/runtime/dashboard-workspace.d.ts +2 -0
- package/dist/runtime/dashboard-workspace.js +38 -0
- package/dist/runtime/dashboard-workspace.js.map +1 -0
- package/dist/runtime/dashboard.d.ts +28 -0
- package/dist/runtime/dashboard.js +19 -0
- package/dist/runtime/dashboard.js.map +1 -0
- package/dist/runtime/readiness.d.ts +4 -0
- package/dist/runtime/readiness.js +17 -0
- package/dist/runtime/readiness.js.map +1 -0
- package/dist/runtime/select-native.d.ts +2 -1
- package/dist/runtime/select-native.js +5 -3
- package/dist/runtime/select-native.js.map +1 -1
- package/dist/runtime/service.d.ts +1 -1
- package/dist/runtime/service.js +10 -3
- package/dist/runtime/service.js.map +1 -1
- package/dist/runtime/startup-lock.d.ts +5 -0
- package/dist/runtime/startup-lock.js +37 -0
- package/dist/runtime/startup-lock.js.map +1 -0
- package/dist/runtime/startup-protocol.d.ts +17 -0
- package/dist/runtime/startup-protocol.js +23 -0
- package/dist/runtime/startup-protocol.js.map +1 -0
- package/dist/runtime/state.d.ts +1 -2
- package/dist/runtime/state.js +8 -43
- package/dist/runtime/state.js.map +1 -1
- package/dist/runtime/types.d.ts +16 -2
- package/dist/runtime/types.js.map +1 -1
- package/dist/runtime/worker-client.d.ts +7 -2
- package/dist/runtime/worker-client.js +69 -12
- package/dist/runtime/worker-client.js.map +1 -1
- package/dist/runtime/worker-server.d.ts +7 -0
- package/dist/runtime/worker-server.js +101 -0
- package/dist/runtime/worker-server.js.map +1 -0
- package/dist/runtime/worker.js +2 -66
- package/dist/runtime/worker.js.map +1 -1
- package/dist/sdk/definitions.js +23 -13
- package/dist/sdk/definitions.js.map +1 -1
- package/dist/sdk/permission-validation.d.ts +4 -0
- package/dist/sdk/permission-validation.js +55 -0
- package/dist/sdk/permission-validation.js.map +1 -0
- package/dist/sdk/types.d.ts +14 -0
- package/dist/sdk/types.js.map +1 -1
- package/package.json +17 -17
- package/sdk/access-config.md +4 -2
- package/sdk/adapter-contract.md +14 -2
- package/sdk/agent-skill.md +38 -0
- package/sdk/agent.md +6 -2
- package/sdk/cli/dashboard-design.md +40 -0
- package/sdk/cli/index.md +47 -13
- package/sdk/cli/output.md +21 -3
- package/sdk/completion-notifications.md +9 -5
- package/sdk/config.md +33 -8
- package/sdk/distribution.md +21 -7
- package/sdk/evals.md +171 -0
- package/sdk/fx.md +4 -3
- package/sdk/harnesses.md +6 -0
- package/sdk/index.md +2 -0
- package/sdk/message-delivery.md +6 -2
- package/sdk/permissions.md +65 -0
- package/sdk/plugins/sub-agents.md +7 -4
- package/sdk/pr-integration.md +37 -0
- package/sdk/project-team.md +13 -8
- package/sdk/sessions.md +1 -1
- package/sdk/tools.md +2 -0
- package/sdk/v1-runtime.md +22 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-client.js","sourceRoot":"","sources":["../../src/runtime/worker-client.ts"],"names":[],"mappings":"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","sourcesContent":["import { fork, type ChildProcess } from 'node:child_process';\nimport { fileURLToPath } from 'node:url';\nimport { delimiter } from 'node:path';\nimport { AgentError, type ErrorInfo } from '../errors.js';\nimport type { NativeSession } from '../adapters/types.js';\nimport type { DriverInput } from './types.js';\nimport { createSessionLauncher } from './session-launcher.js';\n\nexport async function createWorker(input: DriverInput): Promise<NativeSession> {\n const launcher = await createSessionLauncher(input.env.AGENT_STATE_DIR!,input.token);\n const extension = import.meta.url.endsWith('.ts') ? 'ts' : 'js';\n let child: ChildProcess;\n try {\n child = fork(fileURLToPath(new URL(`./worker.${extension}`, import.meta.url)), [], {\n cwd: input.cwd, env: {...input.env,AGENT_PARENT_TOKEN:input.token,AGENT_CLI_PATH:launcher.path,\n PATH:launcher.directory + delimiter + (input.env.PATH ?? '')},\n execArgv: extension === 'ts' ? ['--import', import.meta.resolve('tsx')] : [],\n stdio: ['ignore','ignore','ignore','ipc'],\n });\n } catch (error) { await launcher.close(); throw error; }\n let nextId = 1;\n const pending = new Map<number, {resolve(value:unknown):void;reject(error:Error):void}>();\n let exited = false;\n const exit = () => {\n if (exited) return;\n exited = true;\n void launcher.close().catch(() => {}).then(() => {\n for (const waiting of pending.values()) waiting.reject(new AgentError('HARNESS_FAILED','The session worker exited.'));\n pending.clear();\n });\n };\n child.once('error', exit); child.once('exit', exit);\n child.on('message', (message: {id:number;result?:unknown;error?:ErrorInfo}) => {\n const request = pending.get(message.id);\n if (!request) return;\n pending.delete(message.id);\n if (message.error) request.reject(new AgentError(message.error.code, message.error.message));\n else request.resolve(message.result);\n });\n const request = (method:string, extra:Record<string,unknown> = {}) => new Promise<unknown>((resolve,reject) => {\n if (exited) { reject(new AgentError('HARNESS_FAILED','The session worker is unavailable.')); return; }\n const id = nextId++;\n pending.set(id,{resolve,reject});\n child.send({id,method,...extra}, error => { if (error) { pending.delete(id); reject(new AgentError('HARNESS_FAILED','Cannot reach the session worker.')); } });\n });\n try { await request('open',{input}); } catch (error) { child.kill(); await launcher.close(); throw error; }\n return {\n turn: prompt => request('turn',{prompt}) as Promise<string>,\n steer: async prompt => { await request('steer',{prompt}); },\n interrupt: async () => { await request('interrupt'); },\n resume: () => request('resume') as Promise<string>,\n close: async () => { try { if (!exited) await request('close'); } finally { await launcher.close(); } },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"worker-client.js","sourceRoot":"","sources":["../../src/runtime/worker-client.ts"],"names":[],"mappings":"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","sourcesContent":["import { fork, type ChildProcess } from 'node:child_process';\nimport { fileURLToPath } from 'node:url';\nimport { delimiter } from 'node:path';\nimport { AgentError, type ErrorInfo } from '../errors.js';\nimport type { DriverInput } from './types.js';\nimport type { ManagedNativeSession } from './types.js';\nimport type { HarnessKind } from '../sdk/types.js';\nimport { createSessionLauncher } from './session-launcher.js';\n\ninterface WorkerClientOptions {\n workerModule?: URL;\n shutdownTimeoutMs?: number;\n}\n\nconst closeResponseTimeoutMs = 15_000;\nconst shutdownTimeoutMs = 1_000;\n\nfunction waitWithin(promise: Promise<unknown>, timeout: number): Promise<boolean> {\n return new Promise(resolve => {\n const timer = setTimeout(() => resolve(false),timeout);\n promise.then(\n () => { clearTimeout(timer); resolve(true); },\n () => { clearTimeout(timer); resolve(true); },\n );\n });\n}\n\nfunction withTimeout<T>(promise: Promise<T>, timeout: number): Promise<T> {\n return new Promise((resolve,reject) => {\n const timer = setTimeout(() => reject(new AgentError('HARNESS_FAILED','The session worker did not complete cleanup.')),timeout);\n promise.then(\n value => { clearTimeout(timer); resolve(value); },\n error => { clearTimeout(timer); reject(error); },\n );\n });\n}\n\nexport async function createWorker(input: DriverInput, options: WorkerClientOptions = {}): Promise<ManagedNativeSession> {\n const launcher = await createSessionLauncher(input.env.AGENT_STATE_DIR!,input.token);\n const workerModule = options.workerModule ?? new URL(`./worker.${import.meta.url.endsWith('.ts') ? 'ts' : 'js'}`, import.meta.url);\n const extension = workerModule.pathname.endsWith('.ts') ? 'ts' : 'js';\n let child: ChildProcess;\n try {\n child = fork(fileURLToPath(workerModule), [], {\n cwd: input.cwd, env: {...input.env,AGENT_PARENT_TOKEN:input.token,AGENT_CLI_PATH:launcher.path,\n PATH:launcher.directory + delimiter + (input.env.PATH ?? '')},\n execArgv: extension === 'ts' ? ['--import', import.meta.resolve('tsx')] : [],\n stdio: ['ignore','ignore','ignore','ipc'],\n });\n } catch (error) { await launcher.close(); throw error; }\n let nextId = 1;\n const pending = new Map<number, {resolve(value:unknown):void;reject(error:Error):void}>();\n let exited = false;\n let markExited!: () => void;\n const processExit = new Promise<void>(resolve => { markExited = resolve; });\n const exit = () => {\n if (exited) return;\n exited = true;\n markExited();\n void launcher.close().catch(() => {}).finally(() => {\n for (const waiting of pending.values()) waiting.reject(new AgentError('HARNESS_FAILED','The session worker exited.'));\n pending.clear();\n });\n };\n child.once('error', exit); child.once('exit', exit);\n child.on('message', (message: {id:number;result?:unknown;error?:ErrorInfo}) => {\n const request = pending.get(message.id);\n if (!request) return;\n pending.delete(message.id);\n if (message.error) request.reject(new AgentError(message.error.code, message.error.message));\n else request.resolve(message.result);\n });\n const request = (method:string, extra:Record<string,unknown> = {}) => new Promise<unknown>((resolve,reject) => {\n if (exited) { reject(new AgentError('HARNESS_FAILED','The session worker is unavailable.')); return; }\n const id = nextId++;\n pending.set(id,{resolve,reject});\n child.send({id,method,...extra}, error => { if (error) { pending.delete(id); reject(new AgentError('HARNESS_FAILED','Cannot reach the session worker.')); } });\n });\n let selectedHarness: HarnessKind;\n try { selectedHarness = await request('open',{input}) as HarnessKind; } catch (error) { child.kill(); await launcher.close(); throw error; }\n const stopWorker = async () => {\n if (exited) return;\n if (child.connected) try { child.disconnect(); } catch { /* Continue to termination escalation. */ }\n const timeout = options.shutdownTimeoutMs ?? shutdownTimeoutMs;\n if (await waitWithin(processExit,timeout)) return;\n child.kill('SIGTERM');\n if (await waitWithin(processExit,timeout)) return;\n child.kill('SIGKILL');\n if (await waitWithin(processExit,timeout)) return;\n throw new AgentError('HARNESS_FAILED','The session worker did not confirm termination.');\n };\n return {\n selectedHarness,\n turn: prompt => request('turn',{prompt}) as Promise<string>,\n steer: async prompt => { await request('steer',{prompt}); },\n interrupt: async () => { await request('interrupt'); },\n resume: () => request('resume') as Promise<string>,\n close: async () => {\n let failure: unknown;\n if (!exited) {\n try { await withTimeout(request('close'),closeResponseTimeoutMs); }\n catch (error) { failure = error; }\n }\n try { await stopWorker(); } catch (error) { failure ??= error; }\n try { await launcher.close(); } catch (error) { failure ??= error; }\n if (failure) throw failure;\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ExecutionDefinition } from '../adapters/types.js';
|
|
2
|
+
interface WorkerServerDependencies {
|
|
3
|
+
removeLauncherDirectory?(path: string): Promise<void>;
|
|
4
|
+
}
|
|
5
|
+
export declare function delegationInstructions(definition: ExecutionDefinition, launcherPath: string): string;
|
|
6
|
+
export declare function startWorker(dependencies?: WorkerServerDependencies): void;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { dirname } from 'node:path';
|
|
2
|
+
import { rm } from 'node:fs/promises';
|
|
3
|
+
import { loadExecutionDefinition } from './definition.js';
|
|
4
|
+
import { loadAccess } from '../config/access.js';
|
|
5
|
+
import { errorInfo } from '../errors.js';
|
|
6
|
+
import { selectNative } from './select-native.js';
|
|
7
|
+
import { NativeOwner } from './native-owner.js';
|
|
8
|
+
import { shellQuote } from '../shell.js';
|
|
9
|
+
export function delegationInstructions(definition, launcherPath) {
|
|
10
|
+
const children = Object.entries(definition.subagents ?? {});
|
|
11
|
+
if (children.length === 0)
|
|
12
|
+
return definition.instructions;
|
|
13
|
+
const launcher = shellQuote(launcherPath);
|
|
14
|
+
return definition.instructions + '\n\nAvailable delegated agents:\n' +
|
|
15
|
+
children.map(([name, child]) => `- subagent:${name}: ${child.description}`).join('\n') +
|
|
16
|
+
'\nOnly the listed delegated agents are authorized. Do not infer native background-command support from the ' +
|
|
17
|
+
'harness name, and do not invent native tool parameters.\n' +
|
|
18
|
+
'\nCopy the launcher path and its quoting exactly from the command below. Do not shorten or replace the path. ' +
|
|
19
|
+
'Replace only the angle-bracket arguments. Use --prompt-file instead of --prompt when needed.\n' +
|
|
20
|
+
'When the native host is known to support background commands, use one ordinary run through those controls, ' +
|
|
21
|
+
'continue independent work, and later collect that hosted command\'s output:\n' +
|
|
22
|
+
`\n\`\`\`sh\n${launcher} run subagent:<name> --cwd <existing-directory> --prompt <task>\n\`\`\`\n` +
|
|
23
|
+
'That ordinary run already observes the first response. Do not invoke a separate Subharness wait or an ' +
|
|
24
|
+
'unconditional status for it.\n' +
|
|
25
|
+
'If native background-command support is unavailable or uncertain, use the detached fallback:\n' +
|
|
26
|
+
`\n\`\`\`sh\n${launcher} run subagent:<name> --detach --cwd <existing-directory> --prompt <task>\n\`\`\`\n` +
|
|
27
|
+
'Retain the returned task and session identifiers, continue independent work, and later collect the result with wait:\n' +
|
|
28
|
+
`\n\`\`\`sh\n${launcher} wait <task-id>\n\`\`\`\n` +
|
|
29
|
+
'Use status only when a snapshot or additional state is needed:\n' +
|
|
30
|
+
`\n\`\`\`sh\n${launcher} status <task-id> --full\n\`\`\`\n` +
|
|
31
|
+
'Confirm its terminal outcome. Detached admission is not completion, and shell `&` does not replace the ' +
|
|
32
|
+
'managed task record. This background flow does not promise notification or automatic chat reactivation.\n' +
|
|
33
|
+
'If native permissions block the launcher or coordinator connection, report the exact blocked operation. ' +
|
|
34
|
+
'Do not retry an unchanged permission failure or broaden the permission policy.\n' +
|
|
35
|
+
'For follow-ups, queue, steer, interrupt, wait, status, and cancellation, read the help:\n' +
|
|
36
|
+
`\n\`\`\`sh\n${launcher} --help\n\`\`\`\n` +
|
|
37
|
+
'Include needed task context; child sessions do not inherit your conversation.';
|
|
38
|
+
}
|
|
39
|
+
export function startWorker(dependencies = {}) {
|
|
40
|
+
const removeLauncherDirectory = dependencies.removeLauncherDirectory ??
|
|
41
|
+
((path) => rm(path, { recursive: true, force: true }));
|
|
42
|
+
let native;
|
|
43
|
+
const owner = new NativeOwner();
|
|
44
|
+
const launcherDirectory = dirname(process.env.AGENT_CLI_PATH);
|
|
45
|
+
let closing;
|
|
46
|
+
const close = () => closing ??= (async () => {
|
|
47
|
+
try {
|
|
48
|
+
await owner.close();
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
await removeLauncherDirectory(launcherDirectory);
|
|
52
|
+
}
|
|
53
|
+
})();
|
|
54
|
+
const reply = (message) => { if (process.connected)
|
|
55
|
+
process.send?.(message, () => { }); };
|
|
56
|
+
process.on('message', async (message) => {
|
|
57
|
+
if (message.method === 'close') {
|
|
58
|
+
try {
|
|
59
|
+
await close();
|
|
60
|
+
reply({ id: message.id, result: null });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
reply({ id: message.id, error: errorInfo(error) });
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
if (process.connected)
|
|
67
|
+
process.disconnect();
|
|
68
|
+
}
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
let result;
|
|
73
|
+
if (message.method === 'open') {
|
|
74
|
+
let selectedHarness;
|
|
75
|
+
native = await owner.open(async () => {
|
|
76
|
+
const input = message.input;
|
|
77
|
+
const definition = await loadExecutionDefinition(input.reference);
|
|
78
|
+
const instructions = delegationInstructions(definition, process.env.AGENT_CLI_PATH);
|
|
79
|
+
return selectNative({ ...definition, instructions }, input.cwd, process.env, await loadAccess(input.cwd), undefined, harness => { selectedHarness = harness; });
|
|
80
|
+
});
|
|
81
|
+
result = selectedHarness;
|
|
82
|
+
}
|
|
83
|
+
else if (message.method === 'turn')
|
|
84
|
+
result = await native.turn(message.prompt);
|
|
85
|
+
else if (message.method === 'steer')
|
|
86
|
+
result = await native.steer(message.prompt);
|
|
87
|
+
else if (message.method === 'interrupt')
|
|
88
|
+
result = await native.interrupt();
|
|
89
|
+
else if (message.method === 'resume')
|
|
90
|
+
result = await native.resume();
|
|
91
|
+
else
|
|
92
|
+
throw new Error('Unknown worker operation');
|
|
93
|
+
reply({ id: message.id, result: result ?? null });
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
reply({ id: message.id, error: errorInfo(error) });
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
process.on('disconnect', () => { void close().catch(() => { }).finally(() => process.exit()); });
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=worker-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-server.js","sourceRoot":"","sources":["../../src/runtime/worker-server.ts"],"names":[],"mappings":"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","sourcesContent":["import { dirname } from 'node:path';\nimport { rm } from 'node:fs/promises';\nimport { loadExecutionDefinition } from './definition.js';\nimport { loadAccess } from '../config/access.js';\nimport { errorInfo } from '../errors.js';\nimport { selectNative } from './select-native.js';\nimport { NativeOwner } from './native-owner.js';\nimport type { DriverInput } from './types.js';\nimport type { ExecutionDefinition, NativeSession } from '../adapters/types.js';\nimport type { HarnessKind } from '../sdk/types.js';\nimport { shellQuote } from '../shell.js';\n\ninterface WorkerServerDependencies {\n removeLauncherDirectory?(path: string): Promise<void>;\n}\n\nexport function delegationInstructions(definition: ExecutionDefinition, launcherPath: string): string {\n const children = Object.entries(definition.subagents ?? {});\n if (children.length === 0) return definition.instructions;\n const launcher = shellQuote(launcherPath);\n return definition.instructions + '\\n\\nAvailable delegated agents:\\n' +\n children.map(([name, child]) => `- subagent:${name}: ${child.description}`).join('\\n') +\n '\\nOnly the listed delegated agents are authorized. Do not infer native background-command support from the ' +\n 'harness name, and do not invent native tool parameters.\\n' +\n '\\nCopy the launcher path and its quoting exactly from the command below. Do not shorten or replace the path. ' +\n 'Replace only the angle-bracket arguments. Use --prompt-file instead of --prompt when needed.\\n' +\n 'When the native host is known to support background commands, use one ordinary run through those controls, ' +\n 'continue independent work, and later collect that hosted command\\'s output:\\n' +\n `\\n\\`\\`\\`sh\\n${launcher} run subagent:<name> --cwd <existing-directory> --prompt <task>\\n\\`\\`\\`\\n` +\n 'That ordinary run already observes the first response. Do not invoke a separate Subharness wait or an ' +\n 'unconditional status for it.\\n' +\n 'If native background-command support is unavailable or uncertain, use the detached fallback:\\n' +\n `\\n\\`\\`\\`sh\\n${launcher} run subagent:<name> --detach --cwd <existing-directory> --prompt <task>\\n\\`\\`\\`\\n` +\n 'Retain the returned task and session identifiers, continue independent work, and later collect the result with wait:\\n' +\n `\\n\\`\\`\\`sh\\n${launcher} wait <task-id>\\n\\`\\`\\`\\n` +\n 'Use status only when a snapshot or additional state is needed:\\n' +\n `\\n\\`\\`\\`sh\\n${launcher} status <task-id> --full\\n\\`\\`\\`\\n` +\n 'Confirm its terminal outcome. Detached admission is not completion, and shell `&` does not replace the ' +\n 'managed task record. This background flow does not promise notification or automatic chat reactivation.\\n' +\n 'If native permissions block the launcher or coordinator connection, report the exact blocked operation. ' +\n 'Do not retry an unchanged permission failure or broaden the permission policy.\\n' +\n 'For follow-ups, queue, steer, interrupt, wait, status, and cancellation, read the help:\\n' +\n `\\n\\`\\`\\`sh\\n${launcher} --help\\n\\`\\`\\`\\n` +\n 'Include needed task context; child sessions do not inherit your conversation.';\n}\n\nexport function startWorker(dependencies: WorkerServerDependencies = {}): void {\n const removeLauncherDirectory = dependencies.removeLauncherDirectory ??\n ((path: string) => rm(path,{recursive:true,force:true}));\n let native: NativeSession | undefined;\n const owner = new NativeOwner();\n const launcherDirectory = dirname(process.env.AGENT_CLI_PATH!);\n let closing: Promise<void> | undefined;\n const close = () => closing ??= (async () => {\n try { await owner.close(); }\n finally { await removeLauncherDirectory(launcherDirectory); }\n })();\n const reply = (message: unknown) => { if (process.connected) process.send?.(message as object, () => {}); };\n\n process.on('message', async (message: {id:number;method:string;input?:DriverInput;prompt?:string}) => {\n if (message.method === 'close') {\n try { await close(); reply({id:message.id,result:null}); }\n catch (error) { reply({id:message.id,error:errorInfo(error)}); }\n finally { if (process.connected) process.disconnect(); }\n return;\n }\n try {\n let result: unknown;\n if (message.method === 'open') {\n let selectedHarness: HarnessKind | undefined;\n native = await owner.open(async () => {\n const input = message.input!;\n const definition = await loadExecutionDefinition(input.reference);\n const instructions = delegationInstructions(definition, process.env.AGENT_CLI_PATH!);\n return selectNative({...definition,instructions}, input.cwd, process.env, await loadAccess(input.cwd), undefined,\n harness => { selectedHarness = harness; });\n });\n result = selectedHarness;\n } else if (message.method === 'turn') result = await native!.turn(message.prompt!);\n else if (message.method === 'steer') result = await native!.steer(message.prompt!);\n else if (message.method === 'interrupt') result = await native!.interrupt();\n else if (message.method === 'resume') result = await native!.resume();\n else throw new Error('Unknown worker operation');\n reply({id:message.id,result:result ?? null});\n } catch (error) { reply({id:message.id,error:errorInfo(error)}); }\n });\n process.on('disconnect', () => { void close().catch(() => {}).finally(() => process.exit()); });\n}\n"]}
|
package/dist/runtime/worker.js
CHANGED
|
@@ -1,67 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { errorInfo } from '../errors.js';
|
|
4
|
-
import { selectNative } from './select-native.js';
|
|
5
|
-
import { NativeOwner } from './native-owner.js';
|
|
6
|
-
import { dirname } from 'node:path';
|
|
7
|
-
import { rm } from 'node:fs/promises';
|
|
8
|
-
import { shellQuote } from '../shell.js';
|
|
9
|
-
let native;
|
|
10
|
-
const owner = new NativeOwner();
|
|
11
|
-
const launcherDirectory = dirname(process.env.AGENT_CLI_PATH);
|
|
12
|
-
let closing;
|
|
13
|
-
const close = () => closing ??= (async () => {
|
|
14
|
-
try {
|
|
15
|
-
await owner.close();
|
|
16
|
-
}
|
|
17
|
-
finally {
|
|
18
|
-
await rm(launcherDirectory, { recursive: true, force: true });
|
|
19
|
-
}
|
|
20
|
-
})();
|
|
21
|
-
const reply = (message) => { if (process.connected)
|
|
22
|
-
process.send?.(message, () => { }); };
|
|
23
|
-
process.on('message', async (message) => {
|
|
24
|
-
try {
|
|
25
|
-
let result;
|
|
26
|
-
if (message.method === 'open') {
|
|
27
|
-
native = await owner.open(async () => {
|
|
28
|
-
const input = message.input;
|
|
29
|
-
const definition = await loadExecutionDefinition(input.reference);
|
|
30
|
-
const children = Object.entries(definition.subagents ?? {});
|
|
31
|
-
const launcher = children.length ? shellQuote(process.env.AGENT_CLI_PATH) : '';
|
|
32
|
-
const instructions = children.length ? definition.instructions + '\n\nAvailable delegated agents:\n' +
|
|
33
|
-
children.map(([name, child]) => `- subagent:${name}: ${child.description}`).join('\n') +
|
|
34
|
-
'\nCopy the launcher path and its quoting exactly from the command below. Do not shorten or replace the path. ' +
|
|
35
|
-
'Replace only the angle-bracket arguments. Use --prompt-file instead of --prompt when needed.\n' +
|
|
36
|
-
`\n\`\`\`sh\n${launcher} run subagent:<name> --cwd <existing-directory> --prompt <task>\n\`\`\`\n` +
|
|
37
|
-
'For follow-ups, queue, steer, interrupt, wait, and cancellation, read the help:\n' +
|
|
38
|
-
`\n\`\`\`sh\n${launcher} --help\n\`\`\`\n` +
|
|
39
|
-
'Include needed task context; child sessions do not inherit your conversation.' : definition.instructions;
|
|
40
|
-
return selectNative({ ...definition, instructions }, input.cwd, process.env, await loadAccess(input.cwd));
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
else if (message.method === 'turn')
|
|
44
|
-
result = await native.turn(message.prompt);
|
|
45
|
-
else if (message.method === 'steer')
|
|
46
|
-
result = await native.steer(message.prompt);
|
|
47
|
-
else if (message.method === 'interrupt')
|
|
48
|
-
result = await native.interrupt();
|
|
49
|
-
else if (message.method === 'resume')
|
|
50
|
-
result = await native.resume();
|
|
51
|
-
else if (message.method === 'close') {
|
|
52
|
-
await close();
|
|
53
|
-
reply({ id: message.id, result: null });
|
|
54
|
-
if (process.connected)
|
|
55
|
-
process.disconnect();
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
else
|
|
59
|
-
throw new Error('Unknown worker operation');
|
|
60
|
-
reply({ id: message.id, result: result ?? null });
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
63
|
-
reply({ id: message.id, error: errorInfo(error) });
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
process.on('disconnect', () => { void close().catch(() => { }).finally(() => process.exit()); });
|
|
1
|
+
import { startWorker } from './worker-server.js';
|
|
2
|
+
startWorker();
|
|
67
3
|
//# sourceMappingURL=worker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/runtime/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/runtime/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,WAAW,EAAE,CAAC","sourcesContent":["import { startWorker } from './worker-server.js';\n\nstartWorker();\n"]}
|
package/dist/sdk/definitions.js
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
import { invalid, nonempty, object, validName } from "./validation.js";
|
|
2
|
+
import { permissionOptionFields, validateHarnessPermissions } from "./permission-validation.js";
|
|
2
3
|
import { validateTool } from "./tools.js";
|
|
3
|
-
function validateHarness(value, configured = false) {
|
|
4
|
-
object(value
|
|
4
|
+
function validateHarness(value, configured = false, expectedKind) {
|
|
5
|
+
object(value);
|
|
6
|
+
const candidate = configured ? value.kind : expectedKind;
|
|
7
|
+
if (candidate !== "codex" && candidate !== "claudeCode" && candidate !== "fx")
|
|
8
|
+
invalid("Unsupported harness kind.");
|
|
9
|
+
const kind = candidate;
|
|
10
|
+
const fields = ["model", "effort"];
|
|
11
|
+
if (kind === "codex" || kind === "claudeCode")
|
|
12
|
+
fields.push("fast");
|
|
13
|
+
fields.push(...permissionOptionFields(kind));
|
|
14
|
+
object(value, configured ? ["kind", ...fields] : fields);
|
|
5
15
|
nonempty(value.model, "Model");
|
|
6
16
|
if (value.effort !== undefined)
|
|
7
17
|
nonempty(value.effort, "Effort");
|
|
8
18
|
if (value.fast !== undefined && typeof value.fast !== "boolean")
|
|
9
19
|
invalid("fast must be a boolean.");
|
|
10
|
-
if (configured && value.kind !== "codex" && value.kind !== "claudeCode" && value.kind !== "fx")
|
|
11
|
-
invalid("Unsupported harness kind.");
|
|
12
|
-
if (configured && value.kind === "fx" && "fast" in value)
|
|
13
|
-
invalid("Unknown configuration field.");
|
|
14
20
|
if (configured && value.kind === "claudeCode")
|
|
15
21
|
validateClaudeEffort(value.effort);
|
|
22
|
+
validateHarnessPermissions(kind, value);
|
|
16
23
|
}
|
|
17
24
|
function validateClaudeEffort(effort) {
|
|
18
25
|
if (effort !== undefined && !["low", "medium", "high", "xhigh", "max"].includes(effort)) {
|
|
@@ -20,19 +27,22 @@ function validateClaudeEffort(effort) {
|
|
|
20
27
|
}
|
|
21
28
|
}
|
|
22
29
|
export function codex(options) {
|
|
23
|
-
validateHarness(options);
|
|
30
|
+
validateHarness(options, false, "codex");
|
|
24
31
|
return Object.freeze({ ...options, kind: "codex", fast: options.fast ?? false });
|
|
25
32
|
}
|
|
26
33
|
export function claudeCode(options) {
|
|
27
|
-
validateHarness(options);
|
|
34
|
+
validateHarness(options, false, "claudeCode");
|
|
28
35
|
validateClaudeEffort(options.effort);
|
|
29
|
-
return Object.freeze({
|
|
36
|
+
return Object.freeze({
|
|
37
|
+
...options,
|
|
38
|
+
...(options.allowedTools ? { allowedTools: Object.freeze([...options.allowedTools]) } : {}),
|
|
39
|
+
...(options.disallowedTools ? { disallowedTools: Object.freeze([...options.disallowedTools]) } : {}),
|
|
40
|
+
kind: "claudeCode",
|
|
41
|
+
fast: options.fast ?? false,
|
|
42
|
+
});
|
|
30
43
|
}
|
|
31
44
|
export function fx(options) {
|
|
32
|
-
|
|
33
|
-
nonempty(options.model, "Model");
|
|
34
|
-
if (options.effort !== undefined)
|
|
35
|
-
nonempty(options.effort, "Effort");
|
|
45
|
+
validateHarness(options, false, "fx");
|
|
36
46
|
return Object.freeze({ ...options, kind: "fx" });
|
|
37
47
|
}
|
|
38
48
|
export function agent(definition) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/sdk/definitions.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,SAAS,eAAe,CAAC,KAAc,EAAE,UAAU,GAAG,KAAK;
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/sdk/definitions.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AgentDefinition,\n ClaudeCodeConfig,\n ClaudeCodeOptions,\n CodexConfig,\n CodexOptions,\n FxConfig,\n FxOptions,\n HarnessConfig,\n} from \"./types.js\";\nimport { invalid, nonempty, object, validName } from \"./validation.js\";\nimport { permissionOptionFields, validateHarnessPermissions } from \"./permission-validation.js\";\nimport { validateTool } from \"./tools.js\";\n\nfunction validateHarness(value: unknown, configured = false, expectedKind?: HarnessConfig[\"kind\"]): void {\n object(value);\n const candidate = configured ? value.kind : expectedKind;\n if (candidate !== \"codex\" && candidate !== \"claudeCode\" && candidate !== \"fx\") invalid(\"Unsupported harness kind.\");\n const kind: HarnessConfig[\"kind\"] = candidate;\n const fields = [\"model\", \"effort\"];\n if (kind === \"codex\" || kind === \"claudeCode\") fields.push(\"fast\");\n fields.push(...permissionOptionFields(kind));\n object(value, configured ? [\"kind\", ...fields] : fields);\n nonempty(value.model, \"Model\");\n if (value.effort !== undefined) nonempty(value.effort, \"Effort\");\n if (value.fast !== undefined && typeof value.fast !== \"boolean\") invalid(\"fast must be a boolean.\");\n if (configured && value.kind === \"claudeCode\") validateClaudeEffort(value.effort);\n validateHarnessPermissions(kind, value);\n}\n\nfunction validateClaudeEffort(effort: unknown): void {\n if (effort !== undefined && ![\"low\", \"medium\", \"high\", \"xhigh\", \"max\"].includes(effort as string)) {\n invalid(\"Claude effort must be low, medium, high, xhigh, or max.\");\n }\n}\n\nexport function codex(options: CodexOptions): CodexConfig {\n validateHarness(options, false, \"codex\");\n return Object.freeze({ ...options, kind: \"codex\", fast: options.fast ?? false });\n}\n\nexport function claudeCode(options: ClaudeCodeOptions): ClaudeCodeConfig {\n validateHarness(options, false, \"claudeCode\");\n validateClaudeEffort(options.effort);\n return Object.freeze({\n ...options,\n ...(options.allowedTools ? { allowedTools: Object.freeze([...options.allowedTools]) } : {}),\n ...(options.disallowedTools ? { disallowedTools: Object.freeze([...options.disallowedTools]) } : {}),\n kind: \"claudeCode\",\n fast: options.fast ?? false,\n });\n}\n\nexport function fx(options: FxOptions): FxConfig {\n validateHarness(options, false, \"fx\");\n return Object.freeze({ ...options, kind: \"fx\" });\n}\n\nexport function agent(definition: AgentDefinition): AgentDefinition {\n validateAgent(definition);\n return Object.freeze({\n ...definition,\n ...(Array.isArray(definition.harness) ? { harness: Object.freeze([...definition.harness]) } : {}),\n ...(definition.tools ? { tools: Object.freeze({ ...definition.tools }) } : {}),\n ...(definition.subagents ? { subagents: Object.freeze({ ...definition.subagents }) } : {}),\n });\n}\n\nexport function validateAgent(value: unknown, ancestors = new Set<unknown>()): asserts value is AgentDefinition {\n object(value, [\"name\", \"description\", \"instructions\", \"harness\", \"tools\", \"subagents\"]);\n if (ancestors.has(value)) invalid(\"Subagent definitions cannot contain recursive references.\");\n validName(value.name);\n nonempty(value.description, \"Description\");\n nonempty(value.instructions, \"Instructions\");\n const harnesses = Array.isArray(value.harness) ? value.harness : [value.harness];\n if (!harnesses.length) invalid(\"At least one harness is required.\");\n harnesses.forEach((harness) => validateHarness(harness, true));\n if (value.tools !== undefined) {\n object(value.tools);\n Object.keys(value.tools).forEach(validName);\n Object.values(value.tools).forEach(validateTool);\n }\n if (value.subagents !== undefined) {\n object(value.subagents);\n const next = new Set(ancestors).add(value);\n for (const [name, child] of Object.entries(value.subagents)) {\n validName(name);\n validateAgent(child, next);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { HarnessKind } from "./types.js";
|
|
2
|
+
export declare function permissionOptionFields(kind: HarnessKind): readonly string[];
|
|
3
|
+
/** Validates only native permission fields, ignoring unrelated caller-owned fields. */
|
|
4
|
+
export declare function validateHarnessPermissions(kind: HarnessKind, value: Readonly<Record<string, unknown>>): void;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { invalid } from "./validation.js";
|
|
2
|
+
const fields = {
|
|
3
|
+
codex: Object.freeze(["approvalPolicy", "sandboxMode", "networkAccessEnabled"]),
|
|
4
|
+
claudeCode: Object.freeze(["permissionMode", "allowedTools", "disallowedTools"]),
|
|
5
|
+
fx: Object.freeze(["permissionMode"]),
|
|
6
|
+
};
|
|
7
|
+
const allFields = new Set(Object.values(fields).flat());
|
|
8
|
+
export function permissionOptionFields(kind) {
|
|
9
|
+
return fields[kind];
|
|
10
|
+
}
|
|
11
|
+
/** Validates only native permission fields, ignoring unrelated caller-owned fields. */
|
|
12
|
+
export function validateHarnessPermissions(kind, value) {
|
|
13
|
+
const supported = new Set(fields[kind]);
|
|
14
|
+
if ([...allFields].some(field => Object.hasOwn(value, field) && !supported.has(field))) {
|
|
15
|
+
invalid("Unknown configuration field.");
|
|
16
|
+
}
|
|
17
|
+
if (kind === "codex") {
|
|
18
|
+
if (value.approvalPolicy !== undefined && !["never", "on-request", "untrusted"].includes(value.approvalPolicy)) {
|
|
19
|
+
invalid("Codex approvalPolicy must be never, on-request, or untrusted.");
|
|
20
|
+
}
|
|
21
|
+
if (value.sandboxMode !== undefined && !["read-only", "workspace-write", "danger-full-access"].includes(value.sandboxMode)) {
|
|
22
|
+
invalid("Codex sandboxMode must be read-only, workspace-write, or danger-full-access.");
|
|
23
|
+
}
|
|
24
|
+
if (value.networkAccessEnabled !== undefined && typeof value.networkAccessEnabled !== "boolean") {
|
|
25
|
+
invalid("Codex networkAccessEnabled must be a boolean.");
|
|
26
|
+
}
|
|
27
|
+
if (value.networkAccessEnabled !== undefined && value.sandboxMode !== "workspace-write") {
|
|
28
|
+
invalid("Codex networkAccessEnabled requires sandboxMode workspace-write.");
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (kind === "claudeCode") {
|
|
33
|
+
if (value.permissionMode !== undefined && !["default", "acceptEdits", "bypassPermissions", "plan", "dontAsk", "auto"].includes(value.permissionMode)) {
|
|
34
|
+
invalid("Claude permissionMode is unsupported.");
|
|
35
|
+
}
|
|
36
|
+
for (const field of ["allowedTools", "disallowedTools"]) {
|
|
37
|
+
const rules = value[field];
|
|
38
|
+
if (rules === undefined)
|
|
39
|
+
continue;
|
|
40
|
+
if (!Array.isArray(rules))
|
|
41
|
+
invalid(`Claude ${field} must be an array of nonempty strings.`);
|
|
42
|
+
for (let index = 0; index < rules.length; index++) {
|
|
43
|
+
const rule = rules[index];
|
|
44
|
+
if (typeof rule !== "string" || !rule.trim()) {
|
|
45
|
+
invalid(`Claude ${field} must be an array of nonempty strings.`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (value.permissionMode !== undefined && !["ask", "auto", "full-access"].includes(value.permissionMode)) {
|
|
52
|
+
invalid("fx permissionMode must be ask, auto, or full-access.");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=permission-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-validation.js","sourceRoot":"","sources":["../../src/sdk/permission-validation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { HarnessKind } from \"./types.js\";\nimport { invalid } from \"./validation.js\";\n\nconst fields = {\n codex: Object.freeze([\"approvalPolicy\", \"sandboxMode\", \"networkAccessEnabled\"]),\n claudeCode: Object.freeze([\"permissionMode\", \"allowedTools\", \"disallowedTools\"]),\n fx: Object.freeze([\"permissionMode\"]),\n} as const satisfies Record<HarnessKind, readonly string[]>;\n\nconst allFields = new Set(Object.values(fields).flat());\n\nexport function permissionOptionFields(kind: HarnessKind): readonly string[] {\n return fields[kind];\n}\n\n/** Validates only native permission fields, ignoring unrelated caller-owned fields. */\nexport function validateHarnessPermissions(kind: HarnessKind, value: Readonly<Record<string, unknown>>): void {\n const supported = new Set<string>(fields[kind]);\n if ([...allFields].some(field => Object.hasOwn(value, field) && !supported.has(field))) {\n invalid(\"Unknown configuration field.\");\n }\n\n if (kind === \"codex\") {\n if (value.approvalPolicy !== undefined && ![\"never\", \"on-request\", \"untrusted\"].includes(value.approvalPolicy as string)) {\n invalid(\"Codex approvalPolicy must be never, on-request, or untrusted.\");\n }\n if (value.sandboxMode !== undefined && ![\"read-only\", \"workspace-write\", \"danger-full-access\"].includes(value.sandboxMode as string)) {\n invalid(\"Codex sandboxMode must be read-only, workspace-write, or danger-full-access.\");\n }\n if (value.networkAccessEnabled !== undefined && typeof value.networkAccessEnabled !== \"boolean\") {\n invalid(\"Codex networkAccessEnabled must be a boolean.\");\n }\n if (value.networkAccessEnabled !== undefined && value.sandboxMode !== \"workspace-write\") {\n invalid(\"Codex networkAccessEnabled requires sandboxMode workspace-write.\");\n }\n return;\n }\n\n if (kind === \"claudeCode\") {\n if (value.permissionMode !== undefined && ![\"default\", \"acceptEdits\", \"bypassPermissions\", \"plan\", \"dontAsk\", \"auto\"].includes(value.permissionMode as string)) {\n invalid(\"Claude permissionMode is unsupported.\");\n }\n for (const field of [\"allowedTools\", \"disallowedTools\"] as const) {\n const rules = value[field];\n if (rules === undefined) continue;\n if (!Array.isArray(rules)) invalid(`Claude ${field} must be an array of nonempty strings.`);\n for (let index = 0; index < rules.length; index++) {\n const rule = rules[index];\n if (typeof rule !== \"string\" || !rule.trim()) {\n invalid(`Claude ${field} must be an array of nonempty strings.`);\n }\n }\n }\n return;\n }\n\n if (value.permissionMode !== undefined && ![\"ask\", \"auto\", \"full-access\"].includes(value.permissionMode as string)) {\n invalid(\"fx permissionMode must be ask, auto, or full-access.\");\n }\n}\n"]}
|
package/dist/sdk/types.d.ts
CHANGED
|
@@ -5,17 +5,24 @@ export interface CodexConfig {
|
|
|
5
5
|
readonly model: string;
|
|
6
6
|
readonly effort?: string;
|
|
7
7
|
readonly fast: boolean;
|
|
8
|
+
readonly approvalPolicy?: "never" | "on-request" | "untrusted";
|
|
9
|
+
readonly sandboxMode?: "read-only" | "workspace-write" | "danger-full-access";
|
|
10
|
+
readonly networkAccessEnabled?: boolean;
|
|
8
11
|
}
|
|
9
12
|
export interface ClaudeCodeConfig {
|
|
10
13
|
readonly kind: "claudeCode";
|
|
11
14
|
readonly model: string;
|
|
12
15
|
readonly effort?: "low" | "medium" | "high" | "xhigh" | "max";
|
|
13
16
|
readonly fast: boolean;
|
|
17
|
+
readonly permissionMode?: "default" | "acceptEdits" | "bypassPermissions" | "plan" | "dontAsk" | "auto";
|
|
18
|
+
readonly allowedTools?: readonly string[];
|
|
19
|
+
readonly disallowedTools?: readonly string[];
|
|
14
20
|
}
|
|
15
21
|
export interface FxConfig {
|
|
16
22
|
readonly kind: "fx";
|
|
17
23
|
readonly model: string;
|
|
18
24
|
readonly effort?: string;
|
|
25
|
+
readonly permissionMode?: "ask" | "auto" | "full-access";
|
|
19
26
|
}
|
|
20
27
|
export type HarnessConfig = CodexConfig | ClaudeCodeConfig | (FxConfig & {
|
|
21
28
|
readonly fast?: never;
|
|
@@ -24,15 +31,22 @@ export interface CodexOptions {
|
|
|
24
31
|
readonly model: string;
|
|
25
32
|
readonly effort?: string;
|
|
26
33
|
readonly fast?: boolean;
|
|
34
|
+
readonly approvalPolicy?: "never" | "on-request" | "untrusted";
|
|
35
|
+
readonly sandboxMode?: "read-only" | "workspace-write" | "danger-full-access";
|
|
36
|
+
readonly networkAccessEnabled?: boolean;
|
|
27
37
|
}
|
|
28
38
|
export interface ClaudeCodeOptions {
|
|
29
39
|
readonly model: string;
|
|
30
40
|
readonly effort?: "low" | "medium" | "high" | "xhigh" | "max";
|
|
31
41
|
readonly fast?: boolean;
|
|
42
|
+
readonly permissionMode?: "default" | "acceptEdits" | "bypassPermissions" | "plan" | "dontAsk" | "auto";
|
|
43
|
+
readonly allowedTools?: readonly string[];
|
|
44
|
+
readonly disallowedTools?: readonly string[];
|
|
32
45
|
}
|
|
33
46
|
export interface FxOptions {
|
|
34
47
|
readonly model: string;
|
|
35
48
|
readonly effort?: string;
|
|
49
|
+
readonly permissionMode?: "ask" | "auto" | "full-access";
|
|
36
50
|
}
|
|
37
51
|
export interface ToolDefinition<S extends z.ZodObject = z.ZodObject> {
|
|
38
52
|
readonly description: string;
|
package/dist/sdk/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sdk/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { z } from \"zod\";\n\nexport type HarnessKind = \"codex\" | \"claudeCode\" | \"fx\";\n\nexport interface CodexConfig {\n readonly kind: \"codex\";\n readonly model: string;\n readonly effort?: string;\n readonly fast: boolean;\n}\n\nexport interface ClaudeCodeConfig {\n readonly kind: \"claudeCode\";\n readonly model: string;\n readonly effort?: \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n readonly fast: boolean;\n}\n\nexport interface FxConfig {\n readonly kind: \"fx\";\n readonly model: string;\n readonly effort?: string;\n}\n\nexport type HarnessConfig = CodexConfig | ClaudeCodeConfig | (FxConfig & { readonly fast?: never });\n\nexport interface CodexOptions {\n readonly model: string;\n readonly effort?: string;\n readonly fast?: boolean;\n}\n\nexport interface ClaudeCodeOptions {\n readonly model: string;\n readonly effort?: \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n readonly fast?: boolean;\n}\n\nexport interface FxOptions {\n readonly model: string;\n readonly effort?: string;\n}\n\nexport interface ToolDefinition<S extends z.ZodObject = z.ZodObject> {\n readonly description: string;\n readonly inputSchema: S;\n readonly execute: (input: z.output<S>) => unknown | Promise<unknown>;\n}\n\nexport interface AgentDefinition {\n readonly name: string;\n readonly description: string;\n readonly instructions: string;\n readonly harness: HarnessConfig | readonly HarnessConfig[];\n readonly tools?: Readonly<Record<string, ToolDefinition<any>>>;\n readonly subagents?: Readonly<Record<string, AgentDefinition>>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sdk/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { z } from \"zod\";\n\nexport type HarnessKind = \"codex\" | \"claudeCode\" | \"fx\";\n\nexport interface CodexConfig {\n readonly kind: \"codex\";\n readonly model: string;\n readonly effort?: string;\n readonly fast: boolean;\n readonly approvalPolicy?: \"never\" | \"on-request\" | \"untrusted\";\n readonly sandboxMode?: \"read-only\" | \"workspace-write\" | \"danger-full-access\";\n readonly networkAccessEnabled?: boolean;\n}\n\nexport interface ClaudeCodeConfig {\n readonly kind: \"claudeCode\";\n readonly model: string;\n readonly effort?: \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n readonly fast: boolean;\n readonly permissionMode?: \"default\" | \"acceptEdits\" | \"bypassPermissions\" | \"plan\" | \"dontAsk\" | \"auto\";\n readonly allowedTools?: readonly string[];\n readonly disallowedTools?: readonly string[];\n}\n\nexport interface FxConfig {\n readonly kind: \"fx\";\n readonly model: string;\n readonly effort?: string;\n readonly permissionMode?: \"ask\" | \"auto\" | \"full-access\";\n}\n\nexport type HarnessConfig = CodexConfig | ClaudeCodeConfig | (FxConfig & { readonly fast?: never });\n\nexport interface CodexOptions {\n readonly model: string;\n readonly effort?: string;\n readonly fast?: boolean;\n readonly approvalPolicy?: \"never\" | \"on-request\" | \"untrusted\";\n readonly sandboxMode?: \"read-only\" | \"workspace-write\" | \"danger-full-access\";\n readonly networkAccessEnabled?: boolean;\n}\n\nexport interface ClaudeCodeOptions {\n readonly model: string;\n readonly effort?: \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n readonly fast?: boolean;\n readonly permissionMode?: \"default\" | \"acceptEdits\" | \"bypassPermissions\" | \"plan\" | \"dontAsk\" | \"auto\";\n readonly allowedTools?: readonly string[];\n readonly disallowedTools?: readonly string[];\n}\n\nexport interface FxOptions {\n readonly model: string;\n readonly effort?: string;\n readonly permissionMode?: \"ask\" | \"auto\" | \"full-access\";\n}\n\nexport interface ToolDefinition<S extends z.ZodObject = z.ZodObject> {\n readonly description: string;\n readonly inputSchema: S;\n readonly execute: (input: z.output<S>) => unknown | Promise<unknown>;\n}\n\nexport interface AgentDefinition {\n readonly name: string;\n readonly description: string;\n readonly instructions: string;\n readonly harness: HarnessConfig | readonly HarnessConfig[];\n readonly tools?: Readonly<Record<string, ToolDefinition<any>>>;\n readonly subagents?: Readonly<Record<string, AgentDefinition>>;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "subharness",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"workspaces": [
|
|
5
|
-
"apps/docs"
|
|
6
|
-
],
|
|
3
|
+
"version": "0.0.3",
|
|
7
4
|
"type": "module",
|
|
8
5
|
"engines": {
|
|
9
6
|
"node": ">=22.18.0"
|
|
@@ -23,29 +20,20 @@
|
|
|
23
20
|
"sdk",
|
|
24
21
|
"README.md"
|
|
25
22
|
],
|
|
26
|
-
"scripts": {
|
|
27
|
-
"build": "tsc -p tsconfig.build.json && node --input-type=module -e \"import { chmodSync } from 'node:fs'; chmodSync('dist/cli/main.js', 0o755)\"",
|
|
28
|
-
"typecheck": "tsc --noEmit",
|
|
29
|
-
"test": "node --import tsx --test test/*.test.ts",
|
|
30
|
-
"check": "npm run build && npm run typecheck && npm test",
|
|
31
|
-
"dev:site": "npm run dev --workspace @subharness/docs --",
|
|
32
|
-
"build:site": "npm run build --workspace @subharness/docs",
|
|
33
|
-
"check:site": "npm run check --workspace @subharness/docs",
|
|
34
|
-
"prepack": "npm run build",
|
|
35
|
-
"check:package": "node --test test/package-consumer/package.test.mjs"
|
|
36
|
-
},
|
|
37
23
|
"dependencies": {
|
|
38
24
|
"@anthropic-ai/claude-agent-sdk": "0.3.278",
|
|
39
25
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
26
|
+
"string-width": "8.2.1",
|
|
40
27
|
"tsx": "4.23.15",
|
|
41
28
|
"zod": "4.6.5"
|
|
42
29
|
},
|
|
43
30
|
"devDependencies": {
|
|
44
31
|
"@types/node": "^22.0.0",
|
|
32
|
+
"errore": "0.14.1",
|
|
45
33
|
"typescript": "7.0.2"
|
|
46
34
|
},
|
|
47
35
|
"description": "Run native coding agents and coordinate optional specialists through a local CLI.",
|
|
48
|
-
"license": "
|
|
36
|
+
"license": "Apache-2.0",
|
|
49
37
|
"repository": {
|
|
50
38
|
"type": "git",
|
|
51
39
|
"url": "git+https://github.com/vercel-labs/subharness.git"
|
|
@@ -57,5 +45,17 @@
|
|
|
57
45
|
"publishConfig": {
|
|
58
46
|
"access": "public",
|
|
59
47
|
"registry": "https://registry.npmjs.org/"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsc -p tsconfig.build.json && node --input-type=module -e \"import { chmodSync } from 'node:fs'; chmodSync('dist/cli/main.js', 0o755)\"",
|
|
51
|
+
"typecheck": "tsc --noEmit",
|
|
52
|
+
"test": "node --import tsx --test test/*.test.ts",
|
|
53
|
+
"test:evals": "node --import tsx --test test/eval-*.test.ts",
|
|
54
|
+
"evals": "node --import tsx evals/main.ts",
|
|
55
|
+
"check": "pnpm run build && pnpm run typecheck && pnpm test",
|
|
56
|
+
"dev:site": "pnpm --filter @subharness/docs run dev",
|
|
57
|
+
"build:site": "pnpm --filter @subharness/docs run build",
|
|
58
|
+
"check:site": "pnpm --filter @subharness/docs run check",
|
|
59
|
+
"check:package": "node --test test/package-consumer/package.test.mjs"
|
|
60
60
|
}
|
|
61
|
-
}
|
|
61
|
+
}
|
package/sdk/access-config.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Personal Access Configuration
|
|
2
2
|
|
|
3
|
-
The optional `.
|
|
3
|
+
The optional `.subharness/agents.local.json` file selects access independently of versioned agent definitions. In linked Git worktrees it is read from the main checkout. Without Git, it is read from the execution project root. Global definitions still use the selected project's access preferences.
|
|
4
4
|
|
|
5
5
|
```json
|
|
6
6
|
{
|
|
@@ -37,6 +37,8 @@ Without `envFile`, the named variable is read from the invoking environment. Wit
|
|
|
37
37
|
|
|
38
38
|
Omitting `codex` or `claudeCode` retains native subscription discovery. A nonempty array replaces discovery with the listed connections in order. An empty array disables that harness. Supported keys are `codex`, `claudeCode`, and `fx`. Omitting `fx` does not enable any connection because its adapter requires explicit Gateway access; see [fx access](fx.md). Missing credentials make a connection unavailable before submission; malformed settings, malformed tokens, expired tokens, and project mismatches are errors. Only known unavailability permits advancing to another explicitly enabled connection or harness. Failures after submission never automatically migrate or replay the task.
|
|
39
39
|
|
|
40
|
+
`subharness check` resolves these settings and tries eligible connections and declared harness alternatives exactly as `run` does before submission. It does not infer readiness from environment variables or duplicate adapter authentication checks. A successful check applies only to the connection and harness selected by that fallback process at that moment.
|
|
41
|
+
|
|
40
42
|
## OIDC project selection
|
|
41
43
|
|
|
42
44
|
The selected project directory must contain `.vercel/project.json` with `projectId` and `orgId`. In a deployment without local linkage, `VERCEL_PROJECT_ID` and `VERCEL_ORG_ID` identify the expected project and organization when `project` is omitted. A supplied `project` always requires its explicit linkage. Token claims must match the expected project and organization and be within their validity interval. Local claim checks prevent accidental selection errors; the Gateway authenticates the token.
|
|
@@ -47,6 +49,6 @@ Gateway API keys and OIDC are distinct routes. An API key does not acquire proje
|
|
|
47
49
|
|
|
48
50
|
## Local file management
|
|
49
51
|
|
|
50
|
-
The file can be edited directly; no library login wizard is required. Before using an existing personal settings file in Git, the CLI ensures `/.
|
|
52
|
+
The file can be edited directly; no library login wizard is required. Before using an existing personal settings file in Git, the CLI ensures `/.subharness/agents.local.json` is excluded through the repository's local Git exclude file. This can update Git's local exclude file during `run` or `check`. A tracked personal settings file is rejected with instructions to remove it from the index. The library never copies secrets or personal settings into worktrees. A file left at the former `.agents/agents.local.json` location is not read.
|
|
51
53
|
|
|
52
54
|
Native login remains external: the CLI reports which harness needs login when no eligible access exists. It never extracts a subscription token for use by another harness. Explicit API/Gateway startup prevents ambient credentials from silently selecting a competing billing route. Native subscription access and accelerated modes remain subject to provider eligibility and spending controls; the library is not a spending cap.
|