subharness 0.0.4 → 0.0.7
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 +95 -9
- package/dist/adapters/claude-process.d.ts +3 -0
- package/dist/adapters/claude-process.js +19 -2
- package/dist/adapters/claude-process.js.map +1 -1
- package/dist/adapters/claude-result.d.ts +2 -0
- package/dist/adapters/claude-result.js +22 -0
- package/dist/adapters/claude-result.js.map +1 -0
- package/dist/adapters/claude-tools.d.ts +6 -2
- package/dist/adapters/claude-tools.js +14 -12
- package/dist/adapters/claude-tools.js.map +1 -1
- package/dist/adapters/claude-worker-client.d.ts +49 -0
- package/dist/adapters/claude-worker-client.js +359 -0
- package/dist/adapters/claude-worker-client.js.map +1 -0
- package/dist/adapters/claude-worker-process.d.ts +20 -0
- package/dist/adapters/claude-worker-process.js +76 -0
- package/dist/adapters/claude-worker-process.js.map +1 -0
- package/dist/adapters/claude-worker-protocol.d.ts +38 -0
- package/dist/adapters/claude-worker-protocol.js +2 -0
- package/dist/adapters/claude-worker-protocol.js.map +1 -0
- package/dist/adapters/claude-worker.d.ts +1 -0
- package/dist/adapters/claude-worker.js +126 -0
- package/dist/adapters/claude-worker.js.map +1 -0
- package/dist/adapters/claude.d.ts +16 -6
- package/dist/adapters/claude.js +164 -75
- package/dist/adapters/claude.js.map +1 -1
- package/dist/adapters/codex.js +4 -1
- package/dist/adapters/codex.js.map +1 -1
- package/dist/adapters/copilot-permissions.d.ts +26 -0
- package/dist/adapters/copilot-permissions.js +121 -0
- package/dist/adapters/copilot-permissions.js.map +1 -0
- package/dist/adapters/copilot-tools.d.ts +12 -0
- package/dist/adapters/copilot-tools.js +61 -0
- package/dist/adapters/copilot-tools.js.map +1 -0
- package/dist/adapters/copilot.d.ts +108 -0
- package/dist/adapters/copilot.js +819 -0
- package/dist/adapters/copilot.js.map +1 -0
- package/dist/adapters/cursor-cli-approvals.d.ts +2 -0
- package/dist/adapters/cursor-cli-approvals.js +83 -0
- package/dist/adapters/cursor-cli-approvals.js.map +1 -0
- package/dist/adapters/cursor-cli-model.d.ts +4 -0
- package/dist/adapters/cursor-cli-model.js +64 -0
- package/dist/adapters/cursor-cli-model.js.map +1 -0
- package/dist/adapters/cursor-cli-session.d.ts +32 -0
- package/dist/adapters/cursor-cli-session.js +316 -0
- package/dist/adapters/cursor-cli-session.js.map +1 -0
- package/dist/adapters/cursor-cli-tools.d.ts +20 -0
- package/dist/adapters/cursor-cli-tools.js +181 -0
- package/dist/adapters/cursor-cli-tools.js.map +1 -0
- package/dist/adapters/cursor-cli.d.ts +2 -0
- package/dist/adapters/cursor-cli.js +306 -0
- package/dist/adapters/cursor-cli.js.map +1 -0
- package/dist/adapters/cursor-model.d.ts +7 -0
- package/dist/adapters/cursor-model.js +67 -0
- package/dist/adapters/cursor-model.js.map +1 -0
- package/dist/adapters/cursor-rpc.d.ts +42 -0
- package/dist/adapters/cursor-rpc.js +271 -0
- package/dist/adapters/cursor-rpc.js.map +1 -0
- package/dist/adapters/cursor-session.d.ts +4 -0
- package/dist/adapters/cursor-session.js +327 -0
- package/dist/adapters/cursor-session.js.map +1 -0
- package/dist/adapters/cursor-startup.d.ts +16 -0
- package/dist/adapters/cursor-startup.js +74 -0
- package/dist/adapters/cursor-startup.js.map +1 -0
- package/dist/adapters/cursor-tools.d.ts +11 -0
- package/dist/adapters/cursor-tools.js +49 -0
- package/dist/adapters/cursor-tools.js.map +1 -0
- package/dist/adapters/cursor.d.ts +6 -0
- package/dist/adapters/cursor.js +17 -0
- package/dist/adapters/cursor.js.map +1 -0
- package/dist/adapters/fx-auth.d.ts +12 -2
- package/dist/adapters/fx-auth.js +51 -61
- package/dist/adapters/fx-auth.js.map +1 -1
- package/dist/adapters/fx-profile.d.ts +8 -0
- package/dist/adapters/fx-profile.js +101 -0
- package/dist/adapters/fx-profile.js.map +1 -0
- package/dist/adapters/fx-rpc.d.ts +2 -0
- package/dist/adapters/fx-rpc.js +30 -4
- package/dist/adapters/fx-rpc.js.map +1 -1
- package/dist/adapters/fx-status.d.ts +2 -0
- package/dist/adapters/fx-status.js +96 -0
- package/dist/adapters/fx-status.js.map +1 -0
- package/dist/adapters/fx.js +28 -12
- package/dist/adapters/fx.js.map +1 -1
- package/dist/adapters/opencode-access.d.ts +13 -0
- package/dist/adapters/opencode-access.js +76 -0
- package/dist/adapters/opencode-access.js.map +1 -0
- package/dist/adapters/opencode-config.d.ts +11 -0
- package/dist/adapters/opencode-config.js +238 -0
- package/dist/adapters/opencode-config.js.map +1 -0
- package/dist/adapters/opencode-http.d.ts +28 -0
- package/dist/adapters/opencode-http.js +297 -0
- package/dist/adapters/opencode-http.js.map +1 -0
- package/dist/adapters/opencode-tools.d.ts +19 -0
- package/dist/adapters/opencode-tools.js +127 -0
- package/dist/adapters/opencode-tools.js.map +1 -0
- package/dist/adapters/opencode.d.ts +2 -0
- package/dist/adapters/opencode.js +569 -0
- package/dist/adapters/opencode.js.map +1 -0
- package/dist/adapters/rpc.d.ts +3 -0
- package/dist/adapters/rpc.js +45 -4
- package/dist/adapters/rpc.js.map +1 -1
- package/dist/adapters/types.d.ts +5 -0
- package/dist/adapters/types.js.map +1 -1
- package/dist/approvals/types.d.ts +1 -1
- package/dist/approvals/types.js.map +1 -1
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.js +4 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/catalog-worker.js.map +1 -1
- package/dist/cli/dashboard-client.js +20 -31
- package/dist/cli/dashboard-client.js.map +1 -1
- package/dist/cli/dashboard-controller.d.ts +7 -0
- package/dist/cli/dashboard-controller.js +27 -0
- package/dist/cli/dashboard-controller.js.map +1 -0
- package/dist/cli/dashboard-detail-view.d.ts +1 -1
- package/dist/cli/dashboard-detail-view.js +3 -4
- package/dist/cli/dashboard-detail-view.js.map +1 -1
- package/dist/cli/dashboard-history-view.js.map +1 -1
- package/dist/cli/dashboard-input.d.ts +1 -1
- package/dist/cli/dashboard-input.js +11 -1
- package/dist/cli/dashboard-input.js.map +1 -1
- package/dist/cli/dashboard-layout.js +3 -3
- package/dist/cli/dashboard-layout.js.map +1 -1
- package/dist/cli/dashboard-renderer.js.map +1 -1
- package/dist/cli/dashboard-style.js +2 -2
- package/dist/cli/dashboard-style.js.map +1 -1
- package/dist/cli/dashboard.d.ts +2 -2
- package/dist/cli/dashboard.js +7 -32
- package/dist/cli/dashboard.js.map +1 -1
- package/dist/cli/help.d.ts +1 -1
- package/dist/cli/help.js +30 -12
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/main.js +55 -43
- package/dist/cli/main.js.map +1 -1
- package/dist/config/access-provenance.d.ts +10 -0
- package/dist/config/access-provenance.js +31 -0
- package/dist/config/access-provenance.js.map +1 -0
- package/dist/config/access.d.ts +12 -2
- package/dist/config/access.js +125 -27
- package/dist/config/access.js.map +1 -1
- package/dist/config/loader.js +1 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/oidc.js +4 -2
- package/dist/config/oidc.js.map +1 -1
- package/dist/config/project.js +2 -1
- package/dist/config/project.js.map +1 -1
- package/dist/config/resolve-access.js +24 -10
- package/dist/config/resolve-access.js.map +1 -1
- package/dist/errors.d.ts +2 -2
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/process-diagnostics.d.ts +2 -0
- package/dist/process-diagnostics.js +11 -0
- package/dist/process-diagnostics.js.map +1 -0
- package/dist/runtime/access-errors.d.ts +4 -0
- package/dist/runtime/access-errors.js +25 -0
- package/dist/runtime/access-errors.js.map +1 -0
- package/dist/runtime/approval-registry.d.ts +9 -0
- package/dist/runtime/approval-registry.js +144 -5
- package/dist/runtime/approval-registry.js.map +1 -1
- package/dist/runtime/capture.d.ts +22 -0
- package/dist/runtime/capture.js +320 -0
- package/dist/runtime/capture.js.map +1 -0
- package/dist/runtime/catalog.d.ts +39 -0
- package/dist/runtime/catalog.js +84 -0
- package/dist/runtime/catalog.js.map +1 -0
- package/dist/runtime/client.d.ts +2 -1
- package/dist/runtime/client.js +74 -47
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/coordinator.d.ts +44 -7
- package/dist/runtime/coordinator.js +265 -31
- package/dist/runtime/coordinator.js.map +1 -1
- package/dist/runtime/daemon.js +12 -6
- package/dist/runtime/daemon.js.map +1 -1
- package/dist/runtime/dashboard-sanitize.d.ts +2 -0
- package/dist/runtime/dashboard-sanitize.js +7 -0
- package/dist/runtime/dashboard-sanitize.js.map +1 -0
- package/dist/runtime/dashboard-workspace.js +5 -1
- package/dist/runtime/dashboard-workspace.js.map +1 -1
- package/dist/runtime/dashboard.d.ts +1 -1
- package/dist/runtime/dashboard.js +2 -3
- package/dist/runtime/dashboard.js.map +1 -1
- package/dist/runtime/definition.d.ts +6 -1
- package/dist/runtime/definition.js +42 -2
- package/dist/runtime/definition.js.map +1 -1
- package/dist/runtime/native-owner.js +7 -1
- package/dist/runtime/native-owner.js.map +1 -1
- package/dist/runtime/pagination.d.ts +9 -0
- package/dist/runtime/pagination.js +36 -0
- package/dist/runtime/pagination.js.map +1 -0
- package/dist/runtime/sdk-observation.d.ts +8 -0
- package/dist/runtime/sdk-observation.js +75 -0
- package/dist/runtime/sdk-observation.js.map +1 -0
- package/dist/runtime/sdk-projection.d.ts +8 -0
- package/dist/runtime/sdk-projection.js +19 -0
- package/dist/runtime/sdk-projection.js.map +1 -0
- package/dist/runtime/sdk-service.d.ts +11 -0
- package/dist/runtime/sdk-service.js +109 -0
- package/dist/runtime/sdk-service.js.map +1 -0
- package/dist/runtime/select-native.d.ts +4 -1
- package/dist/runtime/select-native.js +28 -13
- package/dist/runtime/select-native.js.map +1 -1
- package/dist/runtime/service.d.ts +11 -1
- package/dist/runtime/service.js +178 -3
- package/dist/runtime/service.js.map +1 -1
- package/dist/runtime/session-launcher.js +1 -1
- package/dist/runtime/session-launcher.js.map +1 -1
- package/dist/runtime/snapshots.d.ts +103 -0
- package/dist/runtime/snapshots.js +124 -0
- package/dist/runtime/snapshots.js.map +1 -0
- package/dist/runtime/state.d.ts +26 -0
- package/dist/runtime/state.js +86 -17
- package/dist/runtime/state.js.map +1 -1
- package/dist/runtime/task-data.d.ts +38 -0
- package/dist/runtime/task-data.js +2 -0
- package/dist/runtime/task-data.js.map +1 -0
- package/dist/runtime/transport.d.ts +13 -0
- package/dist/runtime/transport.js +166 -0
- package/dist/runtime/transport.js.map +1 -0
- package/dist/runtime/types.d.ts +28 -9
- package/dist/runtime/types.js.map +1 -1
- package/dist/runtime/worker-client.js +40 -13
- package/dist/runtime/worker-client.js.map +1 -1
- package/dist/runtime/worker-server.js +105 -24
- package/dist/runtime/worker-server.js.map +1 -1
- package/dist/sdk/connected-types.d.ts +42 -0
- package/dist/sdk/connected-types.js +2 -0
- package/dist/sdk/connected-types.js.map +1 -0
- package/dist/sdk/connected.d.ts +3 -0
- package/dist/sdk/connected.js +232 -0
- package/dist/sdk/connected.js.map +1 -0
- package/dist/sdk/definitions.d.ts +4 -1
- package/dist/sdk/definitions.js +16 -2
- package/dist/sdk/definitions.js.map +1 -1
- package/dist/sdk/execution-definition.d.ts +3 -0
- package/dist/sdk/execution-definition.js +59 -0
- package/dist/sdk/execution-definition.js.map +1 -0
- package/dist/sdk/execution-driver.d.ts +6 -0
- package/dist/sdk/execution-driver.js +86 -0
- package/dist/sdk/execution-driver.js.map +1 -0
- package/dist/sdk/execution-observation.d.ts +3 -0
- package/dist/sdk/execution-observation.js +35 -0
- package/dist/sdk/execution-observation.js.map +1 -0
- package/dist/sdk/execution-options.d.ts +17 -0
- package/dist/sdk/execution-options.js +115 -0
- package/dist/sdk/execution-options.js.map +1 -0
- package/dist/sdk/execution-types.d.ts +72 -0
- package/dist/sdk/execution-types.js +2 -0
- package/dist/sdk/execution-types.js.map +1 -0
- package/dist/sdk/execution.d.ts +3 -0
- package/dist/sdk/execution.js +3 -0
- package/dist/sdk/execution.js.map +1 -0
- package/dist/sdk/hosted-error.d.ts +3 -0
- package/dist/sdk/hosted-error.js +14 -0
- package/dist/sdk/hosted-error.js.map +1 -0
- package/dist/sdk/hosted.d.ts +23 -0
- package/dist/sdk/hosted.js +204 -0
- package/dist/sdk/hosted.js.map +1 -0
- package/dist/sdk/permission-validation.js +10 -1
- package/dist/sdk/permission-validation.js.map +1 -1
- package/dist/sdk/runner.d.ts +5 -0
- package/dist/sdk/runner.js +107 -0
- package/dist/sdk/runner.js.map +1 -0
- package/dist/sdk/tools.js +4 -1
- package/dist/sdk/tools.js.map +1 -1
- package/dist/sdk/types.d.ts +29 -1
- package/dist/sdk/types.js.map +1 -1
- package/package.json +6 -3
- package/sdk/access-config.md +60 -4
- package/sdk/adapter-contract.md +13 -3
- package/sdk/additional-harnesses.md +43 -0
- package/sdk/agent-skill.md +2 -2
- package/sdk/agent.md +6 -4
- package/sdk/approvals.md +5 -1
- package/sdk/authentication.md +1 -1
- package/sdk/cli/dashboard-design.md +6 -0
- package/sdk/cli/index.md +9 -6
- package/sdk/cli/output.md +3 -1
- package/sdk/completion-notifications.md +2 -0
- package/sdk/config.md +1 -1
- package/sdk/copilot.md +53 -0
- package/sdk/cursor.md +68 -0
- package/sdk/diagnostics.md +29 -0
- package/sdk/distribution.md +5 -3
- package/sdk/evals.md +1 -1
- package/sdk/examples/chat-tool.ts +126 -0
- package/sdk/execution.md +743 -0
- package/sdk/fx.md +50 -5
- package/sdk/harnesses.md +13 -13
- package/sdk/index.md +45 -20
- package/sdk/message-delivery.md +2 -0
- package/sdk/opencode.md +57 -0
- package/sdk/permissions.md +6 -2
- package/sdk/plugins/sub-agents.md +4 -2
- package/sdk/project-team.md +25 -1
- package/sdk/sessions.md +2 -0
- package/sdk/tools.md +4 -2
- package/sdk/v1-runtime.md +8 -6
- package/dist/cli/catalog.d.ts +0 -26
- package/dist/cli/catalog.js +0 -41
- package/dist/cli/catalog.js.map +0 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { AgentError } from '../errors.js';
|
|
2
|
+
import { Coordinator } from '../runtime/coordinator.js';
|
|
3
|
+
import { captureDefinition } from './execution-definition.js';
|
|
4
|
+
import { executionDriver } from './execution-driver.js';
|
|
5
|
+
import { delivery, observeOptions, runCwd, runnerConfiguration, validateCwd, validatePrompt, watchOptions } from './execution-options.js';
|
|
6
|
+
export function createRunner(options) { return createApplicationRunner(options); }
|
|
7
|
+
/** Internal test seam replacing only the external native adapter boundary. */
|
|
8
|
+
export function createRunnerWithNativeOpener(options, open) {
|
|
9
|
+
return createApplicationRunner(options, open);
|
|
10
|
+
}
|
|
11
|
+
function createApplicationRunner(options, open) {
|
|
12
|
+
const configuration = runnerConfiguration(options);
|
|
13
|
+
let coordinator;
|
|
14
|
+
coordinator = new Coordinator(input => executionDriver(coordinator, configuration.access, open)(input));
|
|
15
|
+
return new ApplicationRunner(coordinator, configuration.env);
|
|
16
|
+
}
|
|
17
|
+
class ApplicationRunner {
|
|
18
|
+
coordinator;
|
|
19
|
+
env;
|
|
20
|
+
accepting = true;
|
|
21
|
+
constructor(coordinator, env) {
|
|
22
|
+
this.coordinator = coordinator;
|
|
23
|
+
this.env = env;
|
|
24
|
+
}
|
|
25
|
+
async createSession(definition, options) {
|
|
26
|
+
this.assertAccepting();
|
|
27
|
+
const captured = captureDefinition(definition);
|
|
28
|
+
const cwd = await validateCwd(runCwd(options));
|
|
29
|
+
this.assertAccepting();
|
|
30
|
+
const id = this.coordinator.createSession({ reference: { kind: 'inline', definition: captured }, cwd, env: { ...this.env } });
|
|
31
|
+
return this.session(id);
|
|
32
|
+
}
|
|
33
|
+
session(id) {
|
|
34
|
+
this.coordinator.sessionSnapshot(id);
|
|
35
|
+
return new ApplicationSession(this, this.coordinator, id);
|
|
36
|
+
}
|
|
37
|
+
task(id) {
|
|
38
|
+
const snapshot = this.coordinator.snapshot(id);
|
|
39
|
+
return new ApplicationTask(this.coordinator, snapshot.taskId, snapshot.sessionId);
|
|
40
|
+
}
|
|
41
|
+
async respond(requestId, response) {
|
|
42
|
+
this.assertAccepting();
|
|
43
|
+
this.coordinator.respondSdk(requestId, response);
|
|
44
|
+
}
|
|
45
|
+
async close() { this.accepting = false; await this.coordinator.close(); }
|
|
46
|
+
assertAccepting() { if (!this.accepting)
|
|
47
|
+
throw new AgentError('RUNNER_CLOSED', 'The application runner is closing or closed.'); }
|
|
48
|
+
}
|
|
49
|
+
class ApplicationSession {
|
|
50
|
+
runner;
|
|
51
|
+
coordinator;
|
|
52
|
+
id;
|
|
53
|
+
constructor(runner, coordinator, id) {
|
|
54
|
+
this.runner = runner;
|
|
55
|
+
this.coordinator = coordinator;
|
|
56
|
+
this.id = id;
|
|
57
|
+
}
|
|
58
|
+
async prompt(text, options) {
|
|
59
|
+
this.runner.assertAccepting();
|
|
60
|
+
validatePrompt(text);
|
|
61
|
+
const requestedDelivery = delivery(options);
|
|
62
|
+
let receipt;
|
|
63
|
+
try {
|
|
64
|
+
receipt = await this.coordinator.send(this.id, text, requestedDelivery);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (error instanceof AgentError && error.code === 'COORDINATOR_UNAVAILABLE')
|
|
68
|
+
throw new AgentError('RUNNER_CLOSED', 'The application runner is closing or closed.');
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
return { task: new ApplicationTask(this.coordinator, receipt.taskId, receipt.sessionId), requestedDelivery,
|
|
72
|
+
effectiveDelivery: receipt.delivery ?? requestedDelivery,
|
|
73
|
+
...(receipt.paused ? { paused: true, blockedByTaskId: receipt.blockedByTaskId } : {}) };
|
|
74
|
+
}
|
|
75
|
+
snapshot() { return this.coordinator.sdkSessionSnapshot(this.id); }
|
|
76
|
+
async close() { await this.coordinator.closeSession(this.id); }
|
|
77
|
+
}
|
|
78
|
+
class ApplicationTask {
|
|
79
|
+
coordinator;
|
|
80
|
+
id;
|
|
81
|
+
sessionId;
|
|
82
|
+
resultPromise;
|
|
83
|
+
constructor(coordinator, id, sessionId) {
|
|
84
|
+
this.coordinator = coordinator;
|
|
85
|
+
this.id = id;
|
|
86
|
+
this.sessionId = sessionId;
|
|
87
|
+
}
|
|
88
|
+
get result() {
|
|
89
|
+
if (!this.resultPromise) {
|
|
90
|
+
this.resultPromise = this.coordinator.taskResult(this.id);
|
|
91
|
+
void this.resultPromise.catch(() => undefined);
|
|
92
|
+
}
|
|
93
|
+
return this.resultPromise;
|
|
94
|
+
}
|
|
95
|
+
async snapshot() { return this.coordinator.sdkTaskSnapshot(this.id); }
|
|
96
|
+
async inspect() { return this.coordinator.taskDetails(this.id); }
|
|
97
|
+
watch(options) {
|
|
98
|
+
const selected = watchOptions(options);
|
|
99
|
+
return this.coordinator.watchTask(this.id, selected.signal);
|
|
100
|
+
}
|
|
101
|
+
responses(options) {
|
|
102
|
+
const selected = observeOptions(options);
|
|
103
|
+
return this.coordinator.taskResponses(this.id, selected.after, selected.signal);
|
|
104
|
+
}
|
|
105
|
+
async cancel() { await this.coordinator.cancel(this.id); return this.snapshot(); }
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/sdk/runner.ts"],"names":[],"mappings":"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","sourcesContent":["import { AgentError } from '../errors.js';\nimport { Coordinator } from '../runtime/coordinator.js';\nimport type { ApprovalResponse } from '../runtime/task-data.js';\nimport type { TaskSnapshot } from './execution-types.js';\nimport { captureDefinition } from './execution-definition.js';\nimport { executionDriver, type NativeOpener } from './execution-driver.js';\nimport { delivery, observeOptions, runCwd, runnerConfiguration, validateCwd, validatePrompt, watchOptions } from './execution-options.js';\nimport type { Delivery, PromptReceipt, Runner, RunnerOptions, SessionHandle, TaskHandle } from './execution-types.js';\nimport type { AgentDefinition } from './types.js';\n\nexport function createRunner(options?:RunnerOptions):Runner { return createApplicationRunner(options); }\n/** Internal test seam replacing only the external native adapter boundary. */\nexport function createRunnerWithNativeOpener(options:RunnerOptions|undefined,open:NativeOpener):Runner {\n return createApplicationRunner(options,open);\n}\n\nfunction createApplicationRunner(options?:RunnerOptions,open?:NativeOpener):Runner {\n const configuration=runnerConfiguration(options);\n let coordinator!:Coordinator;\n coordinator=new Coordinator(input=>executionDriver(coordinator,configuration.access,open)(input));\n return new ApplicationRunner(coordinator,configuration.env);\n}\n\nclass ApplicationRunner implements Runner {\n private accepting=true;\n constructor(private readonly coordinator:Coordinator,private readonly env:NodeJS.ProcessEnv) {}\n\n async createSession(definition:AgentDefinition,options:{readonly cwd:string}):Promise<SessionHandle> {\n this.assertAccepting();\n const captured=captureDefinition(definition);\n const cwd=await validateCwd(runCwd(options));\n this.assertAccepting();\n const id=this.coordinator.createSession({reference:{kind:'inline',definition:captured},cwd,env:{...this.env}});\n return this.session(id);\n }\n session(id:string):SessionHandle {\n this.coordinator.sessionSnapshot(id);\n return new ApplicationSession(this,this.coordinator,id);\n }\n task(id:string):TaskHandle {\n const snapshot=this.coordinator.snapshot(id);\n return new ApplicationTask(this.coordinator,snapshot.taskId,snapshot.sessionId);\n }\n async respond(requestId:string,response:ApprovalResponse):Promise<void> {\n this.assertAccepting(); this.coordinator.respondSdk(requestId,response);\n }\n async close():Promise<void> { this.accepting=false; await this.coordinator.close(); }\n assertAccepting() { if (!this.accepting) throw new AgentError('RUNNER_CLOSED','The application runner is closing or closed.'); }\n}\n\nclass ApplicationSession implements SessionHandle {\n constructor(private readonly runner:ApplicationRunner,private readonly coordinator:Coordinator,readonly id:string) {}\n async prompt(text:string,options?:{readonly delivery?:Delivery}):Promise<PromptReceipt> {\n this.runner.assertAccepting(); validatePrompt(text);\n const requestedDelivery=delivery(options);\n let receipt;\n try { receipt=await this.coordinator.send(this.id,text,requestedDelivery); }\n catch(error) {\n if (error instanceof AgentError && error.code === 'COORDINATOR_UNAVAILABLE')\n throw new AgentError('RUNNER_CLOSED','The application runner is closing or closed.');\n throw error;\n }\n return {task:new ApplicationTask(this.coordinator,receipt.taskId,receipt.sessionId),requestedDelivery,\n effectiveDelivery:receipt.delivery ?? requestedDelivery,\n ...(receipt.paused ? {paused:true as const,blockedByTaskId:receipt.blockedByTaskId!} : {})};\n }\n snapshot() { return this.coordinator.sdkSessionSnapshot(this.id); }\n async close() { await this.coordinator.closeSession(this.id); }\n}\n\nclass ApplicationTask implements TaskHandle {\n private resultPromise?:Promise<import('./execution-types.js').TaskResult>;\n constructor(private readonly coordinator:Coordinator,readonly id:string,readonly sessionId:string) {}\n get result() {\n if (!this.resultPromise) {\n this.resultPromise=this.coordinator.taskResult(this.id);\n void this.resultPromise.catch(()=>undefined);\n }\n return this.resultPromise;\n }\n async snapshot() { return this.coordinator.sdkTaskSnapshot(this.id); }\n async inspect() { return this.coordinator.taskDetails(this.id); }\n watch(options?:{readonly signal?:AbortSignal}) {\n const selected=watchOptions(options); return this.coordinator.watchTask(this.id,selected.signal);\n }\n responses(options?:{readonly after?:string;readonly signal?:AbortSignal}) {\n const selected=observeOptions(options); return this.coordinator.taskResponses(this.id,selected.after,selected.signal);\n }\n async cancel():Promise<TaskSnapshot> { await this.coordinator.cancel(this.id); return this.snapshot(); }\n}\n"]}
|
package/dist/sdk/tools.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { AgentError } from "../errors.js";
|
|
3
3
|
import { richToolResult } from "./tool-result.js";
|
|
4
|
+
import { isHostedError } from "./hosted-error.js";
|
|
4
5
|
import { invalid, nonempty, object } from "./validation.js";
|
|
5
6
|
export { toolResult } from "./tool-result.js";
|
|
6
7
|
export function tool(definition) {
|
|
@@ -38,7 +39,9 @@ export async function executeTool(definition, input) {
|
|
|
38
39
|
try {
|
|
39
40
|
result = await definition.execute(parsed.data);
|
|
40
41
|
}
|
|
41
|
-
catch {
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (isHostedError(error))
|
|
44
|
+
throw error;
|
|
42
45
|
throw new AgentError("TOOL_EXECUTION_FAILED", "The custom tool failed during execution.");
|
|
43
46
|
}
|
|
44
47
|
let rich;
|
package/dist/sdk/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/sdk/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,cAAc,EAA2B,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,UAAU,IAAI,CAAwB,UAA6B;IACvE,YAAY,CAAC,UAAU,CAAC,CAAC;IACzB,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,UAAmB;IAC9C,MAAM,CAAC,UAAU,EAAE,CAAC,aAAa,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;IAC9D,QAAQ,CAAC,UAAU,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;IACrD,IAAI,CAAC,CAAC,UAAU,CAAC,WAAW,YAAY,CAAC,CAAC,SAAS,CAAC;QAAE,OAAO,CAAC,sCAAsC,CAAC,CAAC;IACtG,IAAI,OAAO,UAAU,CAAC,OAAO,KAAK,UAAU;QAAE,OAAO,CAAC,kCAAkC,CAAC,CAAC;IAC1F,cAAc,CAAC,UAAuC,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,UAA+B;IAC5D,IAAI,CAAC;QACH,OAAO,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,yDAAyD,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAA+B,EAAE,KAAc;IAC/E,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,EAAE,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE,kDAAkD,CAAC,CAAC;IACjG,CAAC;IACD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/sdk/tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport { AgentError } from \"../errors.js\";\nimport type { ToolDefinition } from \"./types.js\";\nimport { richToolResult, type ExecutedToolResult } from \"./tool-result.js\";\nimport { isHostedError } from \"./hosted-error.js\";\nimport { invalid, nonempty, object } from \"./validation.js\";\n\nexport { toolResult } from \"./tool-result.js\";\nexport type { ToolContent, ToolResult } from \"./tool-result.js\";\n\nexport function tool<S extends z.ZodObject>(definition: ToolDefinition<S>): ToolDefinition<S> {\n validateTool(definition);\n return Object.freeze({ ...definition });\n}\n\nexport function validateTool(definition: unknown): asserts definition is ToolDefinition<any> {\n object(definition, [\"description\", \"inputSchema\", \"execute\"]);\n nonempty(definition.description, \"Tool description\");\n if (!(definition.inputSchema instanceof z.ZodObject)) invalid(\"Tools require a Zod 4 object schema.\");\n if (typeof definition.execute !== \"function\") invalid(\"Tool execute must be a function.\");\n toolJsonSchema(definition as unknown as ToolDefinition);\n}\n\nexport function toolJsonSchema(definition: ToolDefinition<any>): Record<string, unknown> {\n try {\n return z.toJSONSchema(definition.inputSchema, { io: \"input\" });\n } catch {\n return invalid(\"Tool input schema cannot be represented as JSON Schema.\");\n }\n}\n\nexport async function executeTool(definition: ToolDefinition<any>, input: unknown): Promise<ExecutedToolResult> {\n let parsed;\n try {\n parsed = await definition.inputSchema.safeParseAsync(input);\n if (!parsed.success) throw new Error();\n } catch {\n throw new AgentError(\"TOOL_INPUT_INVALID\", \"Tool arguments do not match the declared schema.\");\n }\n let result: unknown;\n try {\n result = await definition.execute(parsed.data);\n } catch (error) {\n if (isHostedError(error)) throw error;\n throw new AgentError(\"TOOL_EXECUTION_FAILED\", \"The custom tool failed during execution.\");\n }\n let rich;\n try {\n rich = richToolResult(result);\n } catch (error) {\n if (error instanceof AgentError) throw error;\n throw new AgentError(\"TOOL_RESULT_INVALID\", \"Tool returned invalid rich content.\");\n }\n if (rich) return { kind: \"content\", content: rich.content };\n let text: string | undefined;\n try {\n text = typeof result === \"string\" ? result : JSON.stringify(result, (_key, value: unknown) => {\n if ([\"undefined\", \"function\", \"symbol\", \"bigint\"].includes(typeof value)\n || (typeof value === \"number\" && !Number.isFinite(value))) throw new Error();\n return value;\n });\n } catch {\n throw new AgentError(\"TOOL_RESULT_INVALID\", \"Tool result must be a string or JSON-serializable value.\");\n }\n if (text === undefined) throw new AgentError(\"TOOL_RESULT_INVALID\", \"Tool result must be a string or JSON-serializable value.\");\n if (Buffer.byteLength(text, \"utf8\") > 1024 * 1024) throw new AgentError(\"TOOL_RESULT_TOO_LARGE\", \"Tool result exceeds 1 MiB.\");\n return text;\n}\n"]}
|
package/dist/sdk/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { z } from "zod";
|
|
2
|
-
export type HarnessKind = "codex" | "claudeCode" | "fx";
|
|
2
|
+
export type HarnessKind = "codex" | "claudeCode" | "fx" | "opencode" | "copilot" | "cursor";
|
|
3
3
|
export interface CodexConfig {
|
|
4
4
|
readonly kind: "codex";
|
|
5
5
|
readonly model: string;
|
|
@@ -24,8 +24,36 @@ export interface FxConfig {
|
|
|
24
24
|
readonly effort?: string;
|
|
25
25
|
readonly permissionMode?: "ask" | "auto" | "full-access";
|
|
26
26
|
}
|
|
27
|
+
export interface OpencodeOptions {
|
|
28
|
+
readonly model: string;
|
|
29
|
+
}
|
|
30
|
+
export interface OpencodeConfig extends OpencodeOptions {
|
|
31
|
+
readonly kind: "opencode";
|
|
32
|
+
}
|
|
33
|
+
export interface CopilotOptions {
|
|
34
|
+
readonly model: string;
|
|
35
|
+
}
|
|
36
|
+
export interface CopilotConfig extends CopilotOptions {
|
|
37
|
+
readonly kind: "copilot";
|
|
38
|
+
}
|
|
39
|
+
export interface CursorOptions {
|
|
40
|
+
readonly model: string;
|
|
41
|
+
readonly sandboxMode?: "enabled" | "disabled";
|
|
42
|
+
}
|
|
43
|
+
export interface CursorConfig extends CursorOptions {
|
|
44
|
+
readonly kind: "cursor";
|
|
45
|
+
}
|
|
27
46
|
export type HarnessConfig = CodexConfig | ClaudeCodeConfig | (FxConfig & {
|
|
28
47
|
readonly fast?: never;
|
|
48
|
+
}) | (OpencodeConfig & {
|
|
49
|
+
readonly effort?: never;
|
|
50
|
+
readonly fast?: never;
|
|
51
|
+
}) | (CopilotConfig & {
|
|
52
|
+
readonly effort?: never;
|
|
53
|
+
readonly fast?: never;
|
|
54
|
+
}) | (CursorConfig & {
|
|
55
|
+
readonly effort?: never;
|
|
56
|
+
readonly fast?: never;
|
|
29
57
|
});
|
|
30
58
|
export interface CodexOptions {
|
|
31
59
|
readonly model: 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 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
|
|
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\" | \"opencode\" | \"copilot\" | \"cursor\";\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 interface OpencodeOptions {\n readonly model: string;\n}\n\nexport interface OpencodeConfig extends OpencodeOptions {\n readonly kind: \"opencode\";\n}\n\nexport interface CopilotOptions {\n readonly model: string;\n}\n\nexport interface CopilotConfig extends CopilotOptions {\n readonly kind: \"copilot\";\n}\n\nexport interface CursorOptions {\n readonly model: string;\n readonly sandboxMode?: \"enabled\" | \"disabled\";\n}\n\nexport interface CursorConfig extends CursorOptions {\n readonly kind: \"cursor\";\n}\n\nexport type HarnessConfig =\n | CodexConfig\n | ClaudeCodeConfig\n | (FxConfig & { readonly fast?: never })\n | (OpencodeConfig & { readonly effort?: never; readonly fast?: never })\n | (CopilotConfig & { readonly effort?: never; readonly fast?: never })\n | (CursorConfig & { readonly effort?: never; 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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "subharness",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.18.0"
|
|
@@ -22,8 +22,11 @@
|
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@anthropic-ai/claude-agent-sdk": "0.3.278",
|
|
25
|
+
"@cursor/sdk": "1.0.32",
|
|
26
|
+
"@github/copilot-sdk": "1.0.14",
|
|
25
27
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
26
28
|
"string-width": "8.2.1",
|
|
29
|
+
"strip-ansi": "7.2.0",
|
|
27
30
|
"tsx": "4.23.15",
|
|
28
31
|
"zod": "4.6.5"
|
|
29
32
|
},
|
|
@@ -32,7 +35,7 @@
|
|
|
32
35
|
"errore": "0.14.1",
|
|
33
36
|
"typescript": "7.0.2"
|
|
34
37
|
},
|
|
35
|
-
"description": "Run native coding agents
|
|
38
|
+
"description": "Run native coding agents from application code or a local CLI, with sessions and optional specialists.",
|
|
36
39
|
"license": "Apache-2.0",
|
|
37
40
|
"repository": {
|
|
38
41
|
"type": "git",
|
|
@@ -49,7 +52,7 @@
|
|
|
49
52
|
"scripts": {
|
|
50
53
|
"build": "tsc -p tsconfig.build.json && node --input-type=module -e \"import { chmodSync } from 'node:fs'; chmodSync('dist/cli/main.js', 0o755)\"",
|
|
51
54
|
"typecheck": "tsc --noEmit",
|
|
52
|
-
"test": "node --import tsx --test test/*.test.ts",
|
|
55
|
+
"test": "node --import tsx --test --test-concurrency=2 test/*.test.ts",
|
|
53
56
|
"test:evals": "node --import tsx --test test/eval-*.test.ts",
|
|
54
57
|
"evals": "node --import tsx evals/main.ts",
|
|
55
58
|
"check": "pnpm run build && pnpm run typecheck && pnpm test",
|
package/sdk/access-config.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Personal Access Configuration
|
|
2
2
|
|
|
3
|
+
Embedded [execution SDK](execution.md) runners accept explicit `RunnerOptions.access` and an environment snapshot. They use the connection rules here without implicitly loading personal settings or modifying Git excludes. Connected sessions use the same project-based personal settings discovery as the CLI, with the caller's captured environment.
|
|
4
|
+
|
|
3
5
|
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
6
|
|
|
5
7
|
```json
|
|
@@ -26,19 +28,73 @@ This example explicitly enables subscription-to-Gateway fallback for Codex befor
|
|
|
26
28
|
|
|
27
29
|
| `type` | Credential source | Default `env` |
|
|
28
30
|
| --- | --- | --- |
|
|
29
|
-
| `subscription` | The harness's
|
|
30
|
-
| `api-key` | Direct native provider API key | `OPENAI_API_KEY` for Codex, `ANTHROPIC_API_KEY` for Claude Code |
|
|
31
|
+
| `subscription` | The harness's saved native login for the selected route | Not applicable |
|
|
32
|
+
| `api-key` | Direct native provider API key | `OPENAI_API_KEY` for Codex, `ANTHROPIC_API_KEY` for Claude Code, `CURSOR_API_KEY` for Cursor |
|
|
31
33
|
| `vercel-api-key` | AI Gateway API key | `AI_GATEWAY_API_KEY` |
|
|
32
34
|
| `vercel-oidc` | Project OIDC token | `VERCEL_OIDC_TOKEN` |
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
The connection shapes are:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
type AccessConnection =
|
|
40
|
+
| { type: "subscription"; provider?: string }
|
|
41
|
+
| {
|
|
42
|
+
type: "api-key";
|
|
43
|
+
provider?: string;
|
|
44
|
+
env?: string;
|
|
45
|
+
envFile?: string;
|
|
46
|
+
baseUrl?: string;
|
|
47
|
+
wireApi?: "completions" | "responses";
|
|
48
|
+
apiVersion?: string;
|
|
49
|
+
wireModel?: string;
|
|
50
|
+
}
|
|
51
|
+
| { type: "vercel-api-key"; env?: string; envFile?: string }
|
|
52
|
+
| { type: "vercel-oidc"; env?: string; envFile?: string; project?: string };
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`provider` selects a native authentication or inference provider; it does not change the agent definition. Its meaning is harness-specific:
|
|
56
|
+
|
|
57
|
+
| Harness | `subscription` | Direct `api-key` |
|
|
58
|
+
| --- | --- | --- |
|
|
59
|
+
| Codex | Native Codex login; no `provider` field | OpenAI; defaults to `OPENAI_API_KEY`; no provider options |
|
|
60
|
+
| Claude Code | Native Claude Code login; no `provider` field | Anthropic; defaults to `ANTHROPIC_API_KEY`; no provider options |
|
|
61
|
+
| Cursor | Native Cursor CLI login; no `provider` field | Cursor; defaults to `CURSOR_API_KEY`; no provider options |
|
|
62
|
+
| OpenCode | Required `provider`: `openai`, `github-copilot`, or `xai` | Required `provider` and explicit `env`; supported providers are defined in [OpenCode](opencode.md) |
|
|
63
|
+
| Copilot | Native Copilot or GitHub CLI login; no `provider` field | Required `provider`: `github`, `openai`, `anthropic`, or `azure` |
|
|
64
|
+
| fx | Required `provider`: `gateway`, `codex`, or `grok` | Required `provider` naming an existing native custom connection and explicit `env` |
|
|
65
|
+
|
|
66
|
+
For Copilot API keys, default variables are respectively `COPILOT_GITHUB_TOKEN`, `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, and `AZURE_OPENAI_API_KEY`. A GitHub token selects GitHub Copilot billing; the other three providers select direct provider billing. An explicit `env` replaces the default rather than adding credential discovery.
|
|
67
|
+
|
|
68
|
+
`baseUrl` is supported only for OpenCode direct API keys and Copilot BYOK providers. It must be an absolute HTTP or HTTPS URL without user information, query, or fragment; credentials belong in environment references. OpenCode preserves the selected provider's native endpoint when it is omitted. Copilot defaults OpenAI to `https://api.openai.com/v1` and Anthropic to `https://api.anthropic.com`; Azure requires an explicit `baseUrl`. OpenAI-compatible endpoints use Copilot `provider: "openai"` with an explicit URL. This does not define custom OpenCode provider or model metadata.
|
|
69
|
+
|
|
70
|
+
`wireApi` is supported only for Copilot OpenAI/Azure routes, defaulting to `completions`. `apiVersion` is supported only for Copilot Azure and maps to the native Azure API version; omission preserves its native versionless route. `wireModel` is supported only for Copilot BYOK and supplies the provider model or deployment name when it differs from the agent's native behavior model. Omission uses the agent's model for both. These fields are not accepted for GitHub-token, subscription, or Gateway routes. No arbitrary headers, token callbacks, or native configuration objects are accepted.
|
|
71
|
+
|
|
72
|
+
Gateway connection shapes and billing behavior are unchanged; they do not accept provider overrides. `vercel-oidc` accepts `project`, defaulting to `.`. Unknown or inapplicable fields and missing required provider/source selections fail before native startup. Variable names match `[A-Za-z_][A-Za-z0-9_]*`. Tokens and API keys must never appear directly in this file. Native logins are completed through each harness's own login command, outside Subharness.
|
|
35
73
|
|
|
36
74
|
Without `envFile`, the named variable is read from the invoking environment. With `envFile`, only that variable is read from that explicit UTF-8 dotenv file; its other values are not imported, and the process environment does not override the selected file. File and project paths resolve relative to the main checkout, or project root outside Git. Shell expansion and command execution in dotenv values are not supported. Sources are read at native session startup; changing a file does not refresh a token already supplied to a running harness.
|
|
37
75
|
|
|
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`,
|
|
76
|
+
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`, `fx`, `opencode`, `copilot`, and `cursor`. The last four require an explicit connection; omission enables no access, even when a native login or ambient key exists. fx, OpenCode, and Copilot accept their documented native login, direct-key, and Gateway routes. Cursor accepts native CLI login or Cursor SDK API-key access and rejects Gateway connections. Each connection selects one billing route without implicit substitution. See [fx](fx.md), [OpenCode](opencode.md), [Copilot](copilot.md), and [Cursor](cursor.md).
|
|
77
|
+
|
|
78
|
+
Missing credentials make a connection unavailable before submission; malformed settings, malformed tokens, expired OIDC tokens, and project mismatches are errors. Only known unavailability permits advancing to another explicitly enabled connection or harness. Native status and configuration checks do not prove remote credential validity, quota, or plan eligibility. Failures after submission never automatically migrate or replay the task.
|
|
39
79
|
|
|
40
80
|
`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
81
|
|
|
82
|
+
## Access context in errors
|
|
83
|
+
|
|
84
|
+
Schema validation locations and distinct OIDC temporal errors are defined in [error diagnostics](diagnostics.md). A settings validation failure identifies the file and structural location before native access selection begins.
|
|
85
|
+
|
|
86
|
+
When a connection fails during native startup, `check` and `run` include the harness and attempted connection type in the diagnostic. They retain the original error code and fallback rules. A model configuration failure reported by an already opened session also includes its selected connection context. This context describes the connection attempted by Subharness; it does not claim that the native harness authenticated successfully through that connection.
|
|
87
|
+
|
|
88
|
+
Diagnostics distinguish explicitly configured connections from default native subscription discovery. For settings loaded from disk, they identify the absolute personal settings path in the main checkout, or the execution project outside Git. If the file is absent, the diagnostic says that native subscription discovery was used because no personal access settings were found there. If the file exists but omits the harness's access entry, the diagnostic says that the entry is omitted. An explicit connection identifies its type and its position in the configured list, so multiple connections of the same type remain distinguishable.
|
|
89
|
+
|
|
90
|
+
When the current personal settings file is absent and an entry exists at the former `.agents/agents.local.json` location, the diagnostic also identifies that legacy path and explains that it is not read. Detecting the legacy entry does not read its contents, migrate it, or change connection selection. Failure to inspect the legacy location does not replace the original startup error. Settings presence and selection context are captured when access settings are loaded, so a later file change does not rewrite the explanation for an existing session.
|
|
91
|
+
|
|
92
|
+
Claude model mismatch diagnostics identify whether the mismatch was observed during startup settings validation, native initialization, or retained-session validation before submission. They do not infer that a mismatch is transient or that missing access settings caused it. A mismatch still fails without automatic retry, model substitution, or task replay.
|
|
93
|
+
|
|
94
|
+
For example, a startup mismatch with a missing access file reports the model validation failure together with `claudeCode`, the attempted `subscription` connection, and `No personal access settings were found at "/project/.subharness/agents.local.json"; using native subscription discovery.` Explicit Gateway access instead reports the configured `vercel-oidc` or `vercel-api-key` connection and its list position.
|
|
95
|
+
|
|
96
|
+
Added diagnostic context contains only connection-selection metadata and settings paths. It never includes credential values, environment contents, settings-file contents, or raw native output. Paths are quoted with C0 and C1 control characters, DEL, and Unicode line separators escaped so one path cannot inject terminal controls or extra diagnostic lines. Successful command output and the public error record shape remain unchanged.
|
|
97
|
+
|
|
42
98
|
## OIDC project selection
|
|
43
99
|
|
|
44
100
|
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.
|
package/sdk/adapter-contract.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# Native Adapter Contract
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The [execution SDK](execution.md) reuses native adapters. Embedded runners use an in-process session driver and host-owned custom tools; connected clients use coordinator-owned captured definitions and native sessions. It exposes complete responses and task snapshots, without promising a native token/tool-progress stream.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Adapters create native Codex, Claude Code, fx, OpenCode, GitHub Copilot, or Cursor conversations in the caller-supplied directory. Their implementation interface is internal and is not an SDK extension API. A session supplies `turn(prompt)`, `steer(prompt)`, `interrupt()`, `resume()`, and `close()`. A turn resolves with its complete text; machine-reported execution failures reject with a stable error code. The Cursor subscription ACP route has the documented limitation that some native backend failures arrive only as assistant text. Interrupt resolves only when active execution has stopped. Unsupported operations return explicit capability errors. Harness-specific contracts are defined for [fx](fx.md), [OpenCode](opencode.md), [Copilot](copilot.md), and [Cursor](cursor.md).
|
|
6
|
+
|
|
7
|
+
[Error diagnostics](diagnostics.md) defines startup failure classification, safe native failure categories, and process termination context. Unexpected Claude account-inspection or model-catalog exceptions are harness failures, not evidence that another access route should be tried.
|
|
8
|
+
|
|
9
|
+
Adapter startup receives the selected harness configuration, loaded agent definition, execution directory, environment, and resolved personal access. Startup verifies compatibility and access before submitting any task. A direct CLI harness target supplies no specialist instructions, custom tools, or declared children. Codex, Claude Code, and fx may request a verifiable native default model internally; OpenCode, Copilot, and Cursor require an explicit CLI model. Public SDK constructors always require a model. Default resolution happens before the first prompt, within the authorized access route, and the resolved model is retained for follow-ups. An unavailable or unverifiable default fails with guidance to supply `--model`, without probing it through a paid generation. Explicit model and effort validation remains effective. `HARNESS_UNAVAILABLE` and `ACCESS_UNAVAILABLE` permit trying another declared alternative before submission. Invalid configuration and unsupported explicit options do not. No adapter performs automatic fallback after turn submission.
|
|
6
10
|
|
|
7
11
|
The CLI readiness check uses this same startup and pre-submission fallback path in an isolated worker, then closes the native session without calling `turn`. It therefore verifies only capabilities observable during startup. It does not probe quota with generation, exercise native tools, or establish shell and child-launch permissions. Startup may create an empty native conversation and private temporary files; normal close removes library-owned temporary files under the adapter lifecycle rules.
|
|
8
12
|
|
|
@@ -12,6 +16,12 @@ Agent instructions supplement native instructions. The adapter exposes declared
|
|
|
12
16
|
|
|
13
17
|
Codex uses its native App Server protocol. Claude Code uses its native Agent SDK with the installed Claude executable. A Claude session accepts queued native turns and interruption. Its native steering method reports `UNSUPPORTED_DELIVERY` before any mutation; the coordinator converts that request to the documented interrupt operation and reports the effective delivery mode. Codex steering targets the active native turn. Neither adapter synthesizes native recovery by replaying the original prompt; unavailable recovery returns `RECOVERY_UNSUPPORTED`.
|
|
14
18
|
|
|
19
|
+
Adapter selection loads only the adapter being attempted. Claude's Agent SDK runs in a private worker for each session because its module initialization can change process environment variables. The worker receives a copy of the captured session environment and never shares the application's `process.env`. This boundary is internal and does not change the public session or tool interfaces.
|
|
20
|
+
|
|
21
|
+
The host retains the original tool schemas, closures, validation, and callback admission and draining. The worker receives tool descriptions and JSON schemas and forwards calls to those original host tools; it does not reconstruct application schemas or execute application callbacks. Native approval requests, answers, and withdrawals cross the same private boundary without changing offered permissions or admitting stale answers. No environment or credential values enter bridge diagnostics.
|
|
22
|
+
|
|
23
|
+
The host owns Claude's concrete native subprocess and private configuration cleanup, including when the worker fails. The SDK's custom process hook bridges native streams and process events to the worker with backpressure. Closing confirms native termination and drains admitted callbacks before reporting completion; terminating the worker alone is insufficient. A close requested during startup waits for that attempt to settle and closes any resulting session without submitting a turn; it does not impose a startup deadline. Interruption confirms that the active native turn has stopped and drains its admitted callbacks while retaining the session. Cleanup failures retain ownership for retry. Unexpected worker or bridge failures are execution failures, not reasons to replay input or switch providers.
|
|
24
|
+
|
|
15
25
|
Personal subscription selection must verify native subscription access. Ambient API keys, alternate endpoints, provider overrides, and native API-key helpers must not silently change the selected billing method. Explicit API or Gateway selections supply only the selected credential route. Credentials are never included in CLI records or diagnostic output.
|
|
16
26
|
|
|
17
27
|
Unsupported approval and interactive-input diagnostics use `INPUT_REQUIRED`. Claude diagnostics may identify a bounded native tool name; Codex diagnostics identify the recognized fixed approval method and category. Diagnostics do not expose raw tool arguments, settings or credentials. Supported approval requests expose the bounded action context needed for the caller's decision under the [approval contract](approvals.md), separately from error diagnostics.
|
|
@@ -22,7 +32,7 @@ Claude accelerated mode with subscription access is rejected in v1 because it re
|
|
|
22
32
|
|
|
23
33
|
## Native default selection
|
|
24
34
|
|
|
25
|
-
Direct CLI targets resolve omitted models through the native session's effective configuration before submitting user input. Codex uses the model returned by App Server `thread/start`, verifies the selected provider and subscription catalog when applicable, and retains that model in subsequent turns. fx uses the
|
|
35
|
+
Direct CLI targets resolve omitted models through the native session's effective configuration before submitting user input. Codex uses the model returned by App Server `thread/start`, verifies the selected provider and subscription catalog when applicable, and retains that model in subsequent turns. fx uses the selected native provider and model reported by ACP `session/new`, then verifies any explicit effort through the existing configuration control.
|
|
26
36
|
|
|
27
37
|
Claude Code resolves its effective model through a capability-checked native settings control. Only applied model and effort fields are retained; merged settings and credential-bearing source details are never logged or included in output. The adapter pins the resolved model for the session through the native model control and verifies the applied result before input is admitted. If the installed SDK or executable cannot expose a verifiable applied model before submission, omitted-model startup fails with `INVALID_CONFIG` and guidance to supply `--model`. Explicit models retain compatibility with native versions that lack that introspection, along with the existing catalog and initialization checks.
|
|
28
38
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Additional native harnesses
|
|
2
|
+
|
|
3
|
+
OpenCode, GitHub Copilot, and Cursor are native harness targets. The SDK exports `opencode`, `copilot`, and `cursor`. Their configuration discriminators, personal access keys, and reserved CLI targets are respectively `opencode`, `copilot`, and `cursor`.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { opencode, copilot, cursor } from "subharness";
|
|
7
|
+
|
|
8
|
+
opencode({ model: "anthropic/claude-sonnet-5" });
|
|
9
|
+
copilot({ model: "openai/gpt-6-astra" });
|
|
10
|
+
cursor({ model: "CURSOR_MODEL_ID", sandboxMode: "enabled" });
|
|
11
|
+
|
|
12
|
+
interface OpencodeOptions { readonly model: string }
|
|
13
|
+
interface CopilotOptions { readonly model: string }
|
|
14
|
+
interface OpencodeConfig extends OpencodeOptions { readonly kind: "opencode" }
|
|
15
|
+
interface CopilotConfig extends CopilotOptions { readonly kind: "copilot" }
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Constructors return immutable configurations. Models must be nonempty. These options deliberately expose only verified capabilities. `fast`, `effort`, unknown fields, and permission options for other harnesses are rejected. Cursor's additional sandbox option and native lifecycle are specified in [Cursor](cursor.md).
|
|
19
|
+
|
|
20
|
+
All three direct CLI targets require an explicit `--model` and reject `--effort`. An omitted or unverifiable model fails with `INVALID_CONFIG` and guidance to supply `--model`, without a generation to discover it. SDK constructors always require the model. OpenCode and Copilot Gateway models use the Gateway's `creator/model` identifier; adapters translate native provider prefixes internally and never silently select a different model.
|
|
21
|
+
|
|
22
|
+
## Access routes
|
|
23
|
+
|
|
24
|
+
OpenCode and Copilot accept explicit native saved-login, direct API-key, and Vercel AI Gateway connections. Each route is selected independently; Gateway is optional. The provider selectors, credential variables, endpoint options, and route-specific model IDs are defined in [personal access](access-config.md), [OpenCode](opencode.md), and [Copilot](copilot.md). Cursor accepts native CLI `subscription` or Cursor SDK `api-key` access and does not support Gateway connections. Omitting any of the three access keys enables no connections. Empty arrays disable them. No ambient credential enables spending.
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"access": {
|
|
28
|
+
"opencode": [{ "type": "vercel-oidc", "project": ".", "envFile": ".env.local" }],
|
|
29
|
+
"copilot": [{ "type": "vercel-oidc", "project": ".", "envFile": ".env.local" }],
|
|
30
|
+
"cursor": [{ "type": "api-key", "env": "CURSOR_API_KEY" }]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Existing credential reference, main-checkout path, OIDC identity/expiry, fallback, and credential redaction rules apply. Gateway API keys default to `AI_GATEWAY_API_KEY`, OIDC defaults to `VERCEL_OIDC_TOKEN`, and Cursor API keys default to `CURSOR_API_KEY`. Unsupported explicit connections fail before native startup, without choosing another billing route.
|
|
36
|
+
|
|
37
|
+
## CLI and coordination
|
|
38
|
+
|
|
39
|
+
The built-in catalog lists `codex`, `claude`, `fx`, `opencode`, `copilot`, and `cursor` in that order before specialists. Same-named specialists require a scope qualifier. Direct targets bypass catalog evaluation. These labels are accepted by the dashboard and execution records. Readiness checks use the same selection and cleanup path as runs and never submit a prompt.
|
|
40
|
+
|
|
41
|
+
The existing queue, declared-child launcher, task/result, interruption, and fallback contracts apply. These adapters do not expose verified active steering or prompt-free recovery. Steering uses the coordinator's documented interrupt behavior; `resume` returns `RECOVERY_UNSUPPORTED`. Unsupported interactive input fails with `INPUT_REQUIRED` without automatically granting permission. An adapter reports interruption only after native execution has stopped and admitted custom tool callbacks have settled. Native processes and resources must be closed before readiness can succeed.
|
|
42
|
+
|
|
43
|
+
The eval runner's named scenarios remain limited to the existing Codex, Claude Code, and fx matrix. Adding runtime harnesses does not implicitly add paid eval scenarios or native credentials.
|
package/sdk/agent-skill.md
CHANGED
|
@@ -14,7 +14,7 @@ The installer reads the source repository, so installation requires access to [v
|
|
|
14
14
|
|
|
15
15
|
## Location and discovery
|
|
16
16
|
|
|
17
|
-
The skill's entry point is `skills/subharness/SKILL.md` at the repository root, with its credential helper in `skills/subharness/scripts/refresh-vercel-oidc.mjs`. Its frontmatter `name` is `subharness`, and its `description` states that the skill applies when the human asks the agent to delegate, parallelize, or hand off work to Codex, Claude Code, or
|
|
17
|
+
The skill's entry point is `skills/subharness/SKILL.md` at the repository root, with its credential helper in `skills/subharness/scripts/refresh-vercel-oidc.mjs`. Its frontmatter `name` is `subharness`, and its `description` states that the skill applies when the human asks the agent to delegate, parallelize, or hand off work to Codex, Claude Code, fx, OpenCode, GitHub Copilot, or Cursor, or to follow up on, check, or cancel delegated work.
|
|
18
18
|
|
|
19
19
|
`npx skills add vercel-labs/subharness` offers only this skill. The repository's development skills under `.agents/skills/` set `metadata.internal: true` in their frontmatter, which the installer hides by default. That field does not change how native harnesses read those skills.
|
|
20
20
|
|
|
@@ -25,7 +25,7 @@ The skill is not part of the npm package. [Package Distribution](distribution.md
|
|
|
25
25
|
The skill is concise, task-oriented guidance for the main agent. It agrees with the [CLI](cli/index.md), [Output](cli/output.md), [Message delivery](message-delivery.md), and [Sessions](sessions.md), and [Responding to Native Permission Requests](approvals.md) references and introduces no commands, flags, defaults, or behavior they do not document. It covers:
|
|
26
26
|
|
|
27
27
|
- When to delegate: independent, well-scoped work that can run while the conversation continues, and when the human names a harness.
|
|
28
|
-
- Choosing a target: the reserved `claude`, `
|
|
28
|
+
- Choosing a target: the reserved `codex`, `claude`, `fx`, `opencode`, `copilot`, and `cursor` direct targets, and `subharness list` for discovered specialists.
|
|
29
29
|
- Starting work with `subharness run <target> [--cwd <directory>] <prompt>`, `--prompt`, or `--prompt-file`, including quoting a positional prompt and giving the child explicit task context, because children do not receive the main conversation's transcript or loaded skills.
|
|
30
30
|
- Preferring a single `subharness run <target> <prompt>` through the host's background-task controls when that capability is known to be available. The caller collects that hosted command's output later; a separate `--detach` and `wait` sequence is unnecessary for its first response.
|
|
31
31
|
- Using `subharness run <target> --detach <prompt>` when background-command support is unavailable or uncertain, returning after admission and retaining the task identifier. `wait` returns or awaits the first response and runs only after useful independent work, when the caller is ready to wait. The minimal example contains only `run --detach` and `wait`; `status` is a separate optional nonblocking snapshot, not an unconditional step before or after `wait`.
|
package/sdk/agent.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Defining an Agent
|
|
2
2
|
|
|
3
|
-
Import definitions from `subharness`. The helpers are synchronous declarations: they do not start harnesses, authenticate, call models, or execute tools. Execution uses the CLI.
|
|
3
|
+
Import definitions from `subharness`. The helpers are synchronous declarations: they do not start harnesses, authenticate, call models, or execute tools. Execution uses either the CLI or the application-owned [execution SDK](execution.md).
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
6
|
import { agent, codex, claudeCode } from "subharness";
|
|
@@ -45,12 +45,14 @@ Children do not inherit loaded skill contents or the parent's transcript. Includ
|
|
|
45
45
|
|
|
46
46
|
`codex(options)` and `claudeCode(options)` return configurations. Both require `model`, accept native `effort`, and accept `fast?: boolean`, defaulting to `false`. Options are typed independently to preserve each harness's capabilities. Codex effort values depend on the native model catalog; Claude effort accepts `low`, `medium`, `high`, `xhigh`, and `max`, subject to native model restrictions.
|
|
47
47
|
|
|
48
|
-
`fx(options)` requires `model` and accepts optional native `effort`. It has no `fast` option. Its readonly configuration has `kind: "fx"`; see the [fx contract](fx.md) for
|
|
48
|
+
`fx(options)` requires `model` and accepts optional native `effort`. It has no `fast` option. Its readonly configuration has `kind: "fx"`; see the [fx contract](fx.md) for supported access routes, native capabilities, and permission limits. `HarnessConfig` is the union of the native harness configurations, so narrowing by `kind` exposes the options supported by that harness.
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
`opencode(options)` and `copilot(options)` require only `model`. Their readonly configurations use `kind: "opencode"` and `kind: "copilot"`. `cursor(options)` requires `model` and accepts `sandboxMode?: "enabled" | "disabled"`; omission preserves Cursor's native default. These constructors reject `effort`, `fast`, and permission fields belonging to other harnesses. See [Additional native harnesses](additional-harnesses.md), [OpenCode](opencode.md), [Copilot](copilot.md), and [Cursor](cursor.md).
|
|
51
|
+
|
|
52
|
+
The package exports the corresponding `Options` and readonly `Config` types for all six constructors. Runtime validation also enforces Claude's listed effort values and Cursor's sandbox values when TypeScript checking is absent; unsupported values fail with `INVALID_DEFINITION` before native execution.
|
|
51
53
|
|
|
52
54
|
The `harness` property always uses that name, even for an array. Alternatives are considered in declaration order; an array does not mean parallel execution. [Personal access settings](access-config.md) determine which connections are eligible without editing a shared agent.
|
|
53
55
|
|
|
54
56
|
## Native permission options
|
|
55
57
|
|
|
56
|
-
|
|
58
|
+
The Codex, Claude Code, and fx constructors also accept the native permission options defined in [Native Permissions](permissions.md). Options are typed and validated independently for each harness. Omitted values preserve native settings; explicit values configure only the new native session and remain fixed for follow-ups. Cursor's `sandboxMode` selects the SDK sandbox for API-key access; subscription ACP access rejects explicit sandbox settings. OpenCode and Copilot expose no public permission option. There is no permission profile registry.
|
package/sdk/approvals.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Responding to Native Permission Requests
|
|
2
2
|
|
|
3
|
+
The [execution SDK](execution.md#unified-approval-types) exposes normalized approval actions through task snapshots. `runner.respond` and `client.approvals.respond` select an advertised action ID, with explicit permission grants when required. They resolve the same retained requests as the native-schema CLI and hosted-tool flow below. These are separate response formats: SDK callers use `{ actionId, grants? }`; CLI and hosted tools use request-specific native schema content. Neither response completes or restarts the task. The internal native approval callback remains adapter-facing.
|
|
4
|
+
|
|
3
5
|
A native tool permission request suspends the operation that needs authorization while its original native turn stays open. Subharness returns a structured request to the observing caller. The caller can answer the request and then observe the same task. Permission handling never replays a prompt, creates a replacement task, changes the selected native policy, or automatically approves an operation. Independent native operations and sibling tasks may continue.
|
|
4
6
|
|
|
5
7
|
## Observe and respond
|
|
@@ -70,6 +72,8 @@ Claude tool approvals expose allow-once and denial. Session-scoped reuse is offe
|
|
|
70
72
|
|
|
71
73
|
fx retains the actual ACP option identifiers and descriptive labels. In the supported fx integration, `allow_always` means the session, not a permanent grant. The adapter accepts only offered options and translates the selected ID to the original ACP response. Native cancellation remains distinct from a chosen denial.
|
|
72
74
|
|
|
75
|
+
OpenCode exposes only its native once and rejection decisions for supported active permission requests. Copilot exposes only the specific offered approve-once and rejection decisions. Neither adapter exposes or invents a reusable grant. Their bounded action context and withdrawal behavior are defined in [OpenCode](opencode.md) and [Copilot](copilot.md). Cursor subscription sessions expose offered ACP allow-once and reject-once options, retaining native IDs and bounded tool context; persistent choices are excluded. Its API-key SDK route has no interactive approval bridge. Other Cursor interactive requests fail with `INPUT_REQUIRED` as defined in [Cursor](cursor.md).
|
|
76
|
+
|
|
73
77
|
Requests which cannot be represented faithfully, unsupported interactive input, and startup-time interactions fail explicitly with `INPUT_REQUIRED`. Policies such as `never` or `dontAsk` may suppress native requests entirely; hard sandbox denials cannot be approved through this mechanism. Omitted native settings remain unchanged.
|
|
74
78
|
|
|
75
79
|
These answer objects illustrate different schemas; submit one only when its fields and values are offered by the actual request:
|
|
@@ -102,7 +106,7 @@ These signatures describe an internal implementation boundary, not new package e
|
|
|
102
106
|
type ApprovalContent = Record<string, string | number | boolean | string[]>;
|
|
103
107
|
interface NativeApprovalRequest {
|
|
104
108
|
kind: "permission";
|
|
105
|
-
harness: "codex" | "claudeCode" | "fx";
|
|
109
|
+
harness: "codex" | "claudeCode" | "fx" | "opencode" | "copilot" | "cursor";
|
|
106
110
|
message: string;
|
|
107
111
|
requestedSchema: ApprovalSchema;
|
|
108
112
|
context?: Record<string, unknown>;
|
package/sdk/authentication.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Login belongs to the selected native harness or access provider. The library selects compatible access at startup and does not create a separate subscription account or transfer subscription tokens between harnesses.
|
|
4
4
|
|
|
5
|
-
Without personal settings,
|
|
5
|
+
Without personal settings, Codex and Claude Code retain native subscription discovery. Other harnesses require an explicit connection. An API credential in the environment does not enable API billing. Saved-login routes verify the native credential source according to each adapter contract; they do not infer plan eligibility, free usage, or a spending cap from OAuth alone. The fx saved Vercel login is a native-login route that still bills AI Gateway.
|
|
6
6
|
|
|
7
7
|
Users can mix subscription, direct API, Gateway API-key, and Gateway OIDC access in one project. Preferences belong to the user, separately from versioned agent definitions. Two contributors can run the same definition through different declared harness alternatives and compatible connections.
|
|
8
8
|
|
|
@@ -72,3 +72,9 @@ The overview remains a small snapshot. An open history requests only metadata fo
|
|
|
72
72
|
Inspection never sends prompts, steers, cancels, resumes or acknowledges work, starts execution, or restarts the coordinator. The private transport is defined in [Inspection transport](dashboard-inspection.md).
|
|
73
73
|
|
|
74
74
|
Snapshots require finished-history and grouped-context capabilities. A missing capability or the exact legacy unknown-operation response reports `COORDINATOR_OUTDATED` with restart guidance. Opening history against a coordinator without the history operation reports the same error rather than presenting incomplete history. Other malformed or failed reads report `COORDINATOR_UNAVAILABLE` after terminal cleanup. Restarting a coordinator discards retained history and is never performed automatically.
|
|
75
|
+
|
|
76
|
+
## Shared presentation boundary
|
|
77
|
+
|
|
78
|
+
The terminal command and website demonstration reuse the internal ANSI renderer, layout, history/detail formatting, text sanitization, input decoding and key-action dispatch. Presentation code accepts explicit dimensions, data and time; it does not discover workspaces, access credentials, read files or contact the coordinator. This boundary adds no public SDK method. The terminal command preserves its existing process lifecycle, serialized reads and backpressure behavior. The website supplies fictional read-only projections and owns its browser terminal lifecycle.
|
|
79
|
+
|
|
80
|
+
The internal `dispatchDashboardKey(renderer, key)` function in `src/cli/dashboard-controller.ts` applies a `DashboardKey` to a `DashboardRenderer` and returns `{ interrupt: boolean; refreshInspection: boolean }`. Interrupt requests process exit only in the CLI host; the browser host instead releases focus. `refreshInspection` is true when a successful open, toggle, leave or selected-request change invalidates the previous inspection read, including collapsing an expanded request by changing selection. Hosts cancel obsolete reads or load their local sample projection after that signal. Overview movement and scrolling an unchanged expansion do not request new detail reads. The dispatcher never fetches data or schedules timers.
|