@the-open-engine/zeroshot 6.33.0 → 6.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/codex.js +3 -1
- package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
- package/lib/hosted-target/adapter-request.cjs +55 -0
- package/lib/hosted-target/adapter-request.d.cts +9 -0
- package/lib/hosted-target/adapter-request.d.mts +9 -0
- package/lib/hosted-target/adapter-request.d.ts +9 -0
- package/lib/hosted-target/adapter-request.mjs +55 -1
- package/lib/hosted-target/adapter-types.d.cts +1 -0
- package/lib/hosted-target/adapter-types.d.mts +1 -0
- package/lib/hosted-target/adapter-types.d.ts +1 -0
- package/lib/hosted-target/response-status.cjs +18 -0
- package/lib/hosted-target/response-status.d.cts +2 -0
- package/lib/hosted-target/response-status.d.mts +2 -0
- package/lib/hosted-target/response-status.d.ts +2 -0
- package/lib/hosted-target/response-status.mjs +15 -0
- package/lib/hosted-target/retry-executor.d.cts +1 -1
- package/lib/hosted-target/retry-executor.d.mts +1 -1
- package/lib/hosted-target/retry-executor.d.ts +1 -1
- package/lib/hosted-target/runtime-install.cjs +45 -0
- package/lib/hosted-target/runtime-install.d.cts +14 -0
- package/lib/hosted-target/runtime-install.d.mts +14 -0
- package/lib/hosted-target/runtime-install.d.ts +14 -0
- package/lib/hosted-target/runtime-install.mjs +42 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.cjs +35 -66
- package/lib/hosted-target/zero-cloud-v1-adapter.d.cts +1 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.d.mts +1 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.d.ts +1 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.mjs +37 -68
- package/lib/target/discovery-validation.cjs +11 -18
- package/lib/target/discovery-validation.d.cts +1 -12
- package/lib/target/discovery-validation.d.mts +1 -12
- package/lib/target/discovery-validation.d.ts +1 -12
- package/lib/target/discovery-validation.js +11 -18
- package/lib/target/discovery-validation.mjs +11 -18
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -1
- package/src/agent/agent-config.js +3 -5
- package/src/agent-cli-provider/adapters/codex.ts +3 -1
- package/src/hosted-target/adapter-request.ts +75 -1
- package/src/hosted-target/adapter-types.ts +6 -0
- package/src/hosted-target/response-status.ts +21 -0
- package/src/hosted-target/retry-executor.ts +8 -1
- package/src/hosted-target/runtime-install.ts +83 -0
- package/src/hosted-target/zero-cloud-v1-adapter.ts +65 -100
- package/src/target/discovery-validation.ts +26 -28
- package/task-lib/runner.js +14 -1
|
@@ -10,4 +10,5 @@ export declare class ZeroCloudV1TargetAdapter implements TargetAdapter {
|
|
|
10
10
|
terminate(capsuleId: string, signal?: AbortSignal): Promise<Capsule>;
|
|
11
11
|
limits(signal?: AbortSignal): Promise<CapsuleLimits>;
|
|
12
12
|
access(capsuleId: string, signal?: AbortSignal): Promise<CapsuleAccess>;
|
|
13
|
+
installRuntime(capsuleId: string, runtime: unknown, accessToken: string, signal?: AbortSignal): Promise<void>;
|
|
13
14
|
}
|
|
@@ -10,4 +10,5 @@ export declare class ZeroCloudV1TargetAdapter implements TargetAdapter {
|
|
|
10
10
|
terminate(capsuleId: string, signal?: AbortSignal): Promise<Capsule>;
|
|
11
11
|
limits(signal?: AbortSignal): Promise<CapsuleLimits>;
|
|
12
12
|
access(capsuleId: string, signal?: AbortSignal): Promise<CapsuleAccess>;
|
|
13
|
+
installRuntime(capsuleId: string, runtime: unknown, accessToken: string, signal?: AbortSignal): Promise<void>;
|
|
13
14
|
}
|
|
@@ -10,4 +10,5 @@ export declare class ZeroCloudV1TargetAdapter implements TargetAdapter {
|
|
|
10
10
|
terminate(capsuleId: string, signal?: AbortSignal): Promise<Capsule>;
|
|
11
11
|
limits(signal?: AbortSignal): Promise<CapsuleLimits>;
|
|
12
12
|
access(capsuleId: string, signal?: AbortSignal): Promise<CapsuleAccess>;
|
|
13
|
+
installRuntime(capsuleId: string, runtime: unknown, accessToken: string, signal?: AbortSignal): Promise<void>;
|
|
13
14
|
}
|
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
import { IDEMPOTENCY_KEY_PATTERN, MAX_RESPONSE_BYTES } from './bounds.mjs';
|
|
2
|
-
import {
|
|
2
|
+
import { TargetProtocolError } from './errors.mjs';
|
|
3
3
|
import { DefaultRetryPolicy } from './retry.mjs';
|
|
4
4
|
import { assertCapsule, assertCapsuleAccess, assertCapsuleLimits, assertCapsuleListPage, } from './response-validation.mjs';
|
|
5
5
|
import { readBoundedResponseJson } from '../target/bounded-response.mjs';
|
|
6
|
-
import { throwCapsuleServerError } from './capsule-error-response.mjs';
|
|
7
6
|
import { validateAccessUrl } from './access-url.mjs';
|
|
8
7
|
import { withTargetRetry } from './retry-executor.mjs';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return globalThis.fetch(url, init);
|
|
13
|
-
},
|
|
14
|
-
};
|
|
8
|
+
import { installRuntime as installOpaqueRuntime } from './runtime-install.mjs';
|
|
9
|
+
import { assertCapsuleResponseStatus } from './response-status.mjs';
|
|
10
|
+
import { createAdapterRequester, } from './adapter-request.mjs';
|
|
15
11
|
const DEFAULT_CLOCK = { now: () => Date.now() };
|
|
16
|
-
function throwIfAborted(signal) {
|
|
17
|
-
if (signal?.aborted)
|
|
18
|
-
throw signal.reason ?? new globalThis.DOMException('The operation was aborted', 'AbortError');
|
|
19
|
-
}
|
|
20
12
|
function validOpaque(value, field) {
|
|
21
13
|
if (value.length === 0 || value.length > 1024)
|
|
22
14
|
throw new TargetProtocolError(`${field} is invalid`);
|
|
@@ -27,16 +19,14 @@ function jsonRequest(body) {
|
|
|
27
19
|
export class ZeroCloudV1TargetAdapter {
|
|
28
20
|
#descriptor;
|
|
29
21
|
#organizationId;
|
|
30
|
-
#
|
|
31
|
-
#transport;
|
|
22
|
+
#request;
|
|
32
23
|
#clock;
|
|
33
24
|
#retryPolicy;
|
|
34
25
|
constructor(options) {
|
|
35
26
|
this.#descriptor = options.descriptor;
|
|
36
27
|
this.#organizationId = options.organization.id;
|
|
37
28
|
validOpaque(this.#organizationId, 'organization id');
|
|
38
|
-
this.#
|
|
39
|
-
this.#transport = options.transport ?? DEFAULT_TRANSPORT;
|
|
29
|
+
this.#request = createAdapterRequester(options.descriptor, options.tokenProvider, options.transport);
|
|
40
30
|
this.#clock = options.clock ?? DEFAULT_CLOCK;
|
|
41
31
|
this.#retryPolicy = options.retryPolicy ?? new DefaultRetryPolicy();
|
|
42
32
|
}
|
|
@@ -106,11 +96,33 @@ export class ZeroCloudV1TargetAdapter {
|
|
|
106
96
|
validateAccessUrl(result.websocketUrl, capsuleId, this.#descriptor);
|
|
107
97
|
return result;
|
|
108
98
|
}
|
|
99
|
+
async installRuntime(capsuleId, runtime, accessToken, signal) {
|
|
100
|
+
const descriptor = this.#descriptor.credentialInstall;
|
|
101
|
+
if (descriptor === null) {
|
|
102
|
+
throw new TargetProtocolError('Target does not advertise runtime installation');
|
|
103
|
+
}
|
|
104
|
+
await installOpaqueRuntime({
|
|
105
|
+
capsuleId,
|
|
106
|
+
runtime,
|
|
107
|
+
accessToken,
|
|
108
|
+
descriptor,
|
|
109
|
+
...(signal === undefined ? {} : { signal }),
|
|
110
|
+
clock: this.#clock,
|
|
111
|
+
retryPolicy: this.#retryPolicy,
|
|
112
|
+
request: (method, path, requestSignal, body, token) => this.#request({
|
|
113
|
+
method,
|
|
114
|
+
path,
|
|
115
|
+
signal: requestSignal,
|
|
116
|
+
request: { body },
|
|
117
|
+
accessToken: token,
|
|
118
|
+
}),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
109
121
|
#execute(...args) {
|
|
110
122
|
return Promise.resolve().then(() => this.#executeExpanded(args));
|
|
111
123
|
}
|
|
112
124
|
#executeExpanded(args) {
|
|
113
|
-
const [operation, method, template, values, expectedStatus, validate, signal, request = {}
|
|
125
|
+
const [operation, method, template, values, expectedStatus, validate, signal, request = {}] = args;
|
|
114
126
|
let path;
|
|
115
127
|
try {
|
|
116
128
|
path = template.expand(values);
|
|
@@ -119,60 +131,17 @@ export class ZeroCloudV1TargetAdapter {
|
|
|
119
131
|
throw new TargetProtocolError('Capsule route expansion is unsafe');
|
|
120
132
|
}
|
|
121
133
|
return withTargetRetry(operation, async () => {
|
|
122
|
-
const response = await this.#request(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
throw new TargetProtocolError('Target returned an unexpected success status');
|
|
131
|
-
}
|
|
132
|
-
await throwCapsuleServerError(response, (errorResponse) => this.#readJson(errorResponse), this.#clock);
|
|
133
|
-
}
|
|
134
|
+
const response = await this.#request({
|
|
135
|
+
method,
|
|
136
|
+
path,
|
|
137
|
+
signal,
|
|
138
|
+
request,
|
|
139
|
+
accessToken: undefined,
|
|
140
|
+
});
|
|
141
|
+
await assertCapsuleResponseStatus(response, expectedStatus, (errorResponse) => this.#readJson(errorResponse), this.#clock);
|
|
134
142
|
return validate(await this.#readJson(response));
|
|
135
143
|
}, signal, { clock: this.#clock, policy: this.#retryPolicy });
|
|
136
144
|
}
|
|
137
|
-
async #request(method, path, signal, request) {
|
|
138
|
-
throwIfAborted(signal);
|
|
139
|
-
const url = requestUrl(path, this.#descriptor);
|
|
140
|
-
let token;
|
|
141
|
-
try {
|
|
142
|
-
token = await this.#tokenProvider.getAccessToken(signal);
|
|
143
|
-
}
|
|
144
|
-
catch {
|
|
145
|
-
throw new TargetAuthError('Target access authorization failed');
|
|
146
|
-
}
|
|
147
|
-
const init = {
|
|
148
|
-
method,
|
|
149
|
-
headers: {
|
|
150
|
-
Accept: 'application/json',
|
|
151
|
-
Authorization: `Bearer ${token}`,
|
|
152
|
-
...(request.body === undefined ? {} : { 'Content-Type': 'application/json' }),
|
|
153
|
-
...request.headers,
|
|
154
|
-
},
|
|
155
|
-
redirect: 'manual',
|
|
156
|
-
};
|
|
157
|
-
if (request.body !== undefined)
|
|
158
|
-
init.body = request.body;
|
|
159
|
-
if (signal !== undefined)
|
|
160
|
-
init.signal = signal;
|
|
161
|
-
try {
|
|
162
|
-
const response = await this.#transport.fetch(url.href, init);
|
|
163
|
-
if (response.url && new globalThis.URL(response.url).href !== url.href) {
|
|
164
|
-
await response.body?.cancel().catch(() => undefined);
|
|
165
|
-
throw new TargetProtocolError('Capsule response changed target route');
|
|
166
|
-
}
|
|
167
|
-
return response;
|
|
168
|
-
}
|
|
169
|
-
catch (error) {
|
|
170
|
-
if (error instanceof TargetAdapterError)
|
|
171
|
-
throw error;
|
|
172
|
-
throwIfAborted(signal);
|
|
173
|
-
throw new TargetTransportError('Capsule transport failed');
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
145
|
#readJson(response) {
|
|
177
146
|
return readBoundedResponseJson(response, MAX_RESPONSE_BYTES, (kind) => new TargetProtocolError(kind === 'size'
|
|
178
147
|
? 'Capsule response exceeds the size limit'
|
|
@@ -81,29 +81,22 @@ function parseCredentialInstall(value) {
|
|
|
81
81
|
if (value === undefined || value === null)
|
|
82
82
|
return null;
|
|
83
83
|
const extension = closedRecord(value, 'extensions.credential_install', [
|
|
84
|
-
'kind',
|
|
84
|
+
'kind',
|
|
85
|
+
'install',
|
|
86
|
+
'max_body_bytes',
|
|
85
87
|
]);
|
|
86
88
|
exact(extension.kind, 'openengine.capsule-credential-install/v1', 'extensions.credential_install.kind');
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
exact(install.method, 'PUT', 'extensions.credential_install.install.method');
|
|
91
|
-
exact(extension.upload_url_origin, 'same_origin', 'extensions.credential_install.upload_url_origin');
|
|
92
|
-
exactStringSet(extension.sealed_envelope_algorithms, 'extensions.credential_install.sealed_envelope_algorithms', ['RSA-OAEP-3072-SHA256']);
|
|
93
|
-
const bounds = closedRecord(extension.bounds, 'extensions.credential_install.bounds', [
|
|
94
|
-
'max_envelope_bytes', 'max_body_bytes', 'grant_ttl_seconds', 'max_clock_skew_seconds',
|
|
89
|
+
const install = closedRecord(extension.install, 'extensions.credential_install.install', [
|
|
90
|
+
'route_template',
|
|
91
|
+
'method',
|
|
95
92
|
]);
|
|
93
|
+
exact(install.method, 'PUT', 'extensions.credential_install.install.method');
|
|
96
94
|
return Object.freeze({
|
|
97
95
|
kind: 'openengine.capsule-credential-install/v1',
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
sealedEnvelopeAlgorithms: Object.freeze(['RSA-OAEP-3072-SHA256']),
|
|
102
|
-
bounds: Object.freeze({
|
|
103
|
-
maxEnvelopeBytes: integer(bounds.max_envelope_bytes, 'extensions.credential_install.bounds.max_envelope_bytes', 1, 1_048_576),
|
|
104
|
-
maxBodyBytes: integer(bounds.max_body_bytes, 'extensions.credential_install.bounds.max_body_bytes', 1, 1_048_576),
|
|
105
|
-
grantTtlSeconds: integer(bounds.grant_ttl_seconds, 'extensions.credential_install.bounds.grant_ttl_seconds', 1, 3_600),
|
|
106
|
-
maxClockSkewSeconds: integer(bounds.max_clock_skew_seconds, 'extensions.credential_install.bounds.max_clock_skew_seconds', 0, 300),
|
|
96
|
+
install: Object.freeze({
|
|
97
|
+
routeTemplate: (0, route_template_js_1.routeTemplate)(install.route_template, 'extensions.credential_install.install.route_template', ['capsule_id']),
|
|
98
|
+
method: 'PUT',
|
|
107
99
|
}),
|
|
100
|
+
maxBodyBytes: integer(extension.max_body_bytes, 'extensions.credential_install.max_body_bytes', 1, 4 * 1024 * 1024),
|
|
108
101
|
});
|
|
109
102
|
}
|
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
import { type RouteTemplate } from './route-template.js';
|
|
2
2
|
export interface CredentialInstallDescriptor {
|
|
3
3
|
readonly kind: 'openengine.capsule-credential-install/v1';
|
|
4
|
-
readonly grant: {
|
|
5
|
-
readonly routeTemplate: RouteTemplate;
|
|
6
|
-
readonly method: 'POST';
|
|
7
|
-
};
|
|
8
4
|
readonly install: {
|
|
9
5
|
readonly routeTemplate: RouteTemplate;
|
|
10
6
|
readonly method: 'PUT';
|
|
11
7
|
};
|
|
12
|
-
readonly
|
|
13
|
-
readonly sealedEnvelopeAlgorithms: readonly ['RSA-OAEP-3072-SHA256'];
|
|
14
|
-
readonly bounds: {
|
|
15
|
-
readonly maxEnvelopeBytes: number;
|
|
16
|
-
readonly maxBodyBytes: number;
|
|
17
|
-
readonly grantTtlSeconds: number;
|
|
18
|
-
readonly maxClockSkewSeconds: number;
|
|
19
|
-
};
|
|
8
|
+
readonly maxBodyBytes: number;
|
|
20
9
|
}
|
|
21
10
|
export declare function record(value: unknown, field: string): Record<string, unknown>;
|
|
22
11
|
export declare function closedRecord(value: unknown, field: string, fields: readonly string[]): Record<string, unknown>;
|
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
import { type RouteTemplate } from './route-template.js';
|
|
2
2
|
export interface CredentialInstallDescriptor {
|
|
3
3
|
readonly kind: 'openengine.capsule-credential-install/v1';
|
|
4
|
-
readonly grant: {
|
|
5
|
-
readonly routeTemplate: RouteTemplate;
|
|
6
|
-
readonly method: 'POST';
|
|
7
|
-
};
|
|
8
4
|
readonly install: {
|
|
9
5
|
readonly routeTemplate: RouteTemplate;
|
|
10
6
|
readonly method: 'PUT';
|
|
11
7
|
};
|
|
12
|
-
readonly
|
|
13
|
-
readonly sealedEnvelopeAlgorithms: readonly ['RSA-OAEP-3072-SHA256'];
|
|
14
|
-
readonly bounds: {
|
|
15
|
-
readonly maxEnvelopeBytes: number;
|
|
16
|
-
readonly maxBodyBytes: number;
|
|
17
|
-
readonly grantTtlSeconds: number;
|
|
18
|
-
readonly maxClockSkewSeconds: number;
|
|
19
|
-
};
|
|
8
|
+
readonly maxBodyBytes: number;
|
|
20
9
|
}
|
|
21
10
|
export declare function record(value: unknown, field: string): Record<string, unknown>;
|
|
22
11
|
export declare function closedRecord(value: unknown, field: string, fields: readonly string[]): Record<string, unknown>;
|
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
import { type RouteTemplate } from './route-template.js';
|
|
2
2
|
export interface CredentialInstallDescriptor {
|
|
3
3
|
readonly kind: 'openengine.capsule-credential-install/v1';
|
|
4
|
-
readonly grant: {
|
|
5
|
-
readonly routeTemplate: RouteTemplate;
|
|
6
|
-
readonly method: 'POST';
|
|
7
|
-
};
|
|
8
4
|
readonly install: {
|
|
9
5
|
readonly routeTemplate: RouteTemplate;
|
|
10
6
|
readonly method: 'PUT';
|
|
11
7
|
};
|
|
12
|
-
readonly
|
|
13
|
-
readonly sealedEnvelopeAlgorithms: readonly ['RSA-OAEP-3072-SHA256'];
|
|
14
|
-
readonly bounds: {
|
|
15
|
-
readonly maxEnvelopeBytes: number;
|
|
16
|
-
readonly maxBodyBytes: number;
|
|
17
|
-
readonly grantTtlSeconds: number;
|
|
18
|
-
readonly maxClockSkewSeconds: number;
|
|
19
|
-
};
|
|
8
|
+
readonly maxBodyBytes: number;
|
|
20
9
|
}
|
|
21
10
|
export declare function record(value: unknown, field: string): Record<string, unknown>;
|
|
22
11
|
export declare function closedRecord(value: unknown, field: string, fields: readonly string[]): Record<string, unknown>;
|
|
@@ -81,29 +81,22 @@ function parseCredentialInstall(value) {
|
|
|
81
81
|
if (value === undefined || value === null)
|
|
82
82
|
return null;
|
|
83
83
|
const extension = closedRecord(value, 'extensions.credential_install', [
|
|
84
|
-
'kind',
|
|
84
|
+
'kind',
|
|
85
|
+
'install',
|
|
86
|
+
'max_body_bytes',
|
|
85
87
|
]);
|
|
86
88
|
exact(extension.kind, 'openengine.capsule-credential-install/v1', 'extensions.credential_install.kind');
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
exact(install.method, 'PUT', 'extensions.credential_install.install.method');
|
|
91
|
-
exact(extension.upload_url_origin, 'same_origin', 'extensions.credential_install.upload_url_origin');
|
|
92
|
-
exactStringSet(extension.sealed_envelope_algorithms, 'extensions.credential_install.sealed_envelope_algorithms', ['RSA-OAEP-3072-SHA256']);
|
|
93
|
-
const bounds = closedRecord(extension.bounds, 'extensions.credential_install.bounds', [
|
|
94
|
-
'max_envelope_bytes', 'max_body_bytes', 'grant_ttl_seconds', 'max_clock_skew_seconds',
|
|
89
|
+
const install = closedRecord(extension.install, 'extensions.credential_install.install', [
|
|
90
|
+
'route_template',
|
|
91
|
+
'method',
|
|
95
92
|
]);
|
|
93
|
+
exact(install.method, 'PUT', 'extensions.credential_install.install.method');
|
|
96
94
|
return Object.freeze({
|
|
97
95
|
kind: 'openengine.capsule-credential-install/v1',
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
sealedEnvelopeAlgorithms: Object.freeze(['RSA-OAEP-3072-SHA256']),
|
|
102
|
-
bounds: Object.freeze({
|
|
103
|
-
maxEnvelopeBytes: integer(bounds.max_envelope_bytes, 'extensions.credential_install.bounds.max_envelope_bytes', 1, 1_048_576),
|
|
104
|
-
maxBodyBytes: integer(bounds.max_body_bytes, 'extensions.credential_install.bounds.max_body_bytes', 1, 1_048_576),
|
|
105
|
-
grantTtlSeconds: integer(bounds.grant_ttl_seconds, 'extensions.credential_install.bounds.grant_ttl_seconds', 1, 3_600),
|
|
106
|
-
maxClockSkewSeconds: integer(bounds.max_clock_skew_seconds, 'extensions.credential_install.bounds.max_clock_skew_seconds', 0, 300),
|
|
96
|
+
install: Object.freeze({
|
|
97
|
+
routeTemplate: (0, route_template_js_1.routeTemplate)(install.route_template, 'extensions.credential_install.install.route_template', ['capsule_id']),
|
|
98
|
+
method: 'PUT',
|
|
107
99
|
}),
|
|
100
|
+
maxBodyBytes: integer(extension.max_body_bytes, 'extensions.credential_install.max_body_bytes', 1, 4 * 1024 * 1024),
|
|
108
101
|
});
|
|
109
102
|
}
|
|
@@ -71,29 +71,22 @@ export function parseCredentialInstall(value) {
|
|
|
71
71
|
if (value === undefined || value === null)
|
|
72
72
|
return null;
|
|
73
73
|
const extension = closedRecord(value, 'extensions.credential_install', [
|
|
74
|
-
'kind',
|
|
74
|
+
'kind',
|
|
75
|
+
'install',
|
|
76
|
+
'max_body_bytes',
|
|
75
77
|
]);
|
|
76
78
|
exact(extension.kind, 'openengine.capsule-credential-install/v1', 'extensions.credential_install.kind');
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
exact(install.method, 'PUT', 'extensions.credential_install.install.method');
|
|
81
|
-
exact(extension.upload_url_origin, 'same_origin', 'extensions.credential_install.upload_url_origin');
|
|
82
|
-
exactStringSet(extension.sealed_envelope_algorithms, 'extensions.credential_install.sealed_envelope_algorithms', ['RSA-OAEP-3072-SHA256']);
|
|
83
|
-
const bounds = closedRecord(extension.bounds, 'extensions.credential_install.bounds', [
|
|
84
|
-
'max_envelope_bytes', 'max_body_bytes', 'grant_ttl_seconds', 'max_clock_skew_seconds',
|
|
79
|
+
const install = closedRecord(extension.install, 'extensions.credential_install.install', [
|
|
80
|
+
'route_template',
|
|
81
|
+
'method',
|
|
85
82
|
]);
|
|
83
|
+
exact(install.method, 'PUT', 'extensions.credential_install.install.method');
|
|
86
84
|
return Object.freeze({
|
|
87
85
|
kind: 'openengine.capsule-credential-install/v1',
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
sealedEnvelopeAlgorithms: Object.freeze(['RSA-OAEP-3072-SHA256']),
|
|
92
|
-
bounds: Object.freeze({
|
|
93
|
-
maxEnvelopeBytes: integer(bounds.max_envelope_bytes, 'extensions.credential_install.bounds.max_envelope_bytes', 1, 1_048_576),
|
|
94
|
-
maxBodyBytes: integer(bounds.max_body_bytes, 'extensions.credential_install.bounds.max_body_bytes', 1, 1_048_576),
|
|
95
|
-
grantTtlSeconds: integer(bounds.grant_ttl_seconds, 'extensions.credential_install.bounds.grant_ttl_seconds', 1, 3_600),
|
|
96
|
-
maxClockSkewSeconds: integer(bounds.max_clock_skew_seconds, 'extensions.credential_install.bounds.max_clock_skew_seconds', 0, 300),
|
|
86
|
+
install: Object.freeze({
|
|
87
|
+
routeTemplate: routeTemplate(install.route_template, 'extensions.credential_install.install.route_template', ['capsule_id']),
|
|
88
|
+
method: 'PUT',
|
|
97
89
|
}),
|
|
90
|
+
maxBodyBytes: integer(extension.max_body_bytes, 'extensions.credential_install.max_body_bytes', 1, 4 * 1024 * 1024),
|
|
98
91
|
});
|
|
99
92
|
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@the-open-engine/zeroshot",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.34.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@the-open-engine/zeroshot",
|
|
9
|
-
"version": "6.
|
|
9
|
+
"version": "6.34.0",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@the-open-engine/zeroshot",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.34.0",
|
|
4
4
|
"description": "Independent executor–verifier orchestration for software changes.",
|
|
5
5
|
"main": "src/orchestrator.js",
|
|
6
6
|
"bin": {
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"typecheck:agent-cli-provider": "tsc --project tsconfig.agent-cli-provider.json",
|
|
45
45
|
"typecheck:hosted-target": "tsc --project tsconfig.hosted-target.json",
|
|
46
46
|
"typecheck:hosted-session": "tsc --project tsconfig.hosted-session.json",
|
|
47
|
+
"test:hosted": "npm run build:cluster && node --test tests/private-hosted-cli/*.test.js && npm run test:hosted-target",
|
|
47
48
|
"test:hosted-target": "npm run build:cluster && npm run build:target && node --test tests/hosted-target/*.test.ts",
|
|
48
49
|
"test:target": "npm run build:agent-cli-provider && npm run build:target && node --test tests/target/*.test.ts",
|
|
49
50
|
"typecheck:target": "tsc --project tsconfig.target.json",
|
|
@@ -21,12 +21,10 @@ const DEFAULT_MAX_ITERATIONS = 100;
|
|
|
21
21
|
// Use positive number for timeout in milliseconds
|
|
22
22
|
const DEFAULT_TIMEOUT = 0;
|
|
23
23
|
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
// Only flags as stuck when ALL indicators show inactivity (score >= 3.5)
|
|
27
|
-
// Single-indicator detection (just output freshness) was too risky - this is safe.
|
|
24
|
+
// Output-silence detection is opt-in because healthy provider operations may be quiet for
|
|
25
|
+
// longer than the stale threshold. Explicit task timeouts remain independently supported.
|
|
28
26
|
const DEFAULT_STALE_DURATION_MS = 30 * 60 * 1000; // 30 minutes before triggering analysis
|
|
29
|
-
const DEFAULT_LIVENESS_CHECK_ENABLED =
|
|
27
|
+
const DEFAULT_LIVENESS_CHECK_ENABLED = false;
|
|
30
28
|
|
|
31
29
|
function applyOutputDefaults(config) {
|
|
32
30
|
// CRITICAL: Enforce JSON schema output by default to prevent parse failures and crashes
|
|
@@ -115,7 +115,9 @@ function addAutoApproveArgs(args: string[], options: BuildProviderCommandOptions
|
|
|
115
115
|
const features = optionFeatures(options);
|
|
116
116
|
if (options.autoApprove && features.supportsAutoApprove) {
|
|
117
117
|
const sandboxMode =
|
|
118
|
-
options.executionContext === 'docker'
|
|
118
|
+
options.executionContext === 'docker' || options.executionContext === 'benchmark'
|
|
119
|
+
? 'danger-full-access'
|
|
120
|
+
: 'workspace-write';
|
|
119
121
|
args.push('--sandbox', sandboxMode, '--config', 'approval_policy="never"');
|
|
120
122
|
}
|
|
121
123
|
}
|
|
@@ -1,12 +1,50 @@
|
|
|
1
1
|
import type { RouteTemplate, TargetDiscoveryDescriptor } from '../target/discovery.js';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
TargetAdapterError,
|
|
4
|
+
TargetAuthError,
|
|
5
|
+
TargetProtocolError,
|
|
6
|
+
TargetTransportError,
|
|
7
|
+
} from './errors.js';
|
|
3
8
|
import type { TargetOperation } from './retry-executor.js';
|
|
9
|
+
import type { HttpTransport, TargetAccessTokenProvider } from './types.js';
|
|
10
|
+
|
|
11
|
+
const DEFAULT_TRANSPORT: HttpTransport = {
|
|
12
|
+
fetch(url, init) {
|
|
13
|
+
return globalThis.fetch(url, init);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function throwIfAborted(signal?: AbortSignal): void {
|
|
18
|
+
if (signal?.aborted)
|
|
19
|
+
throw signal.reason ?? new globalThis.DOMException('The operation was aborted', 'AbortError');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function resolveAccessToken(
|
|
23
|
+
tokenProvider: TargetAccessTokenProvider,
|
|
24
|
+
accessToken: string | undefined,
|
|
25
|
+
signal: AbortSignal | undefined
|
|
26
|
+
): Promise<string> {
|
|
27
|
+
if (accessToken !== undefined) return accessToken;
|
|
28
|
+
try {
|
|
29
|
+
return await tokenProvider.getAccessToken(signal);
|
|
30
|
+
} catch {
|
|
31
|
+
throw new TargetAuthError('Target access authorization failed');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
4
34
|
|
|
5
35
|
export type AdapterRequest = {
|
|
6
36
|
readonly body?: string;
|
|
7
37
|
readonly headers?: Readonly<Record<string, string>>;
|
|
8
38
|
};
|
|
9
39
|
|
|
40
|
+
export type AdapterRequester = (input: {
|
|
41
|
+
readonly method: string;
|
|
42
|
+
readonly path: string;
|
|
43
|
+
readonly signal: AbortSignal | undefined;
|
|
44
|
+
readonly request: AdapterRequest;
|
|
45
|
+
readonly accessToken: string | undefined;
|
|
46
|
+
}) => Promise<Response>;
|
|
47
|
+
|
|
10
48
|
export type ExecuteArguments<T> = [
|
|
11
49
|
operation: TargetOperation,
|
|
12
50
|
method: string,
|
|
@@ -31,3 +69,39 @@ export function requestUrl(path: string, descriptor: TargetDiscoveryDescriptor):
|
|
|
31
69
|
}
|
|
32
70
|
return url;
|
|
33
71
|
}
|
|
72
|
+
|
|
73
|
+
export function createAdapterRequester(
|
|
74
|
+
descriptor: TargetDiscoveryDescriptor,
|
|
75
|
+
tokenProvider: TargetAccessTokenProvider,
|
|
76
|
+
transport: HttpTransport = DEFAULT_TRANSPORT
|
|
77
|
+
): AdapterRequester {
|
|
78
|
+
return async ({ method, path, signal, request, accessToken }) => {
|
|
79
|
+
throwIfAborted(signal);
|
|
80
|
+
const url = requestUrl(path, descriptor);
|
|
81
|
+
const token = await resolveAccessToken(tokenProvider, accessToken, signal);
|
|
82
|
+
const init: RequestInit & { redirect: 'manual' } = {
|
|
83
|
+
method,
|
|
84
|
+
headers: {
|
|
85
|
+
Accept: 'application/json',
|
|
86
|
+
Authorization: `Bearer ${token}`,
|
|
87
|
+
...(request.body === undefined ? {} : { 'Content-Type': 'application/json' }),
|
|
88
|
+
...request.headers,
|
|
89
|
+
},
|
|
90
|
+
redirect: 'manual',
|
|
91
|
+
};
|
|
92
|
+
if (request.body !== undefined) init.body = request.body;
|
|
93
|
+
if (signal !== undefined) init.signal = signal;
|
|
94
|
+
try {
|
|
95
|
+
const response = await transport.fetch(url.href, init);
|
|
96
|
+
if (response.url && new globalThis.URL(response.url).href !== url.href) {
|
|
97
|
+
await response.body?.cancel().catch(() => undefined);
|
|
98
|
+
throw new TargetProtocolError('Capsule response changed target route');
|
|
99
|
+
}
|
|
100
|
+
return response;
|
|
101
|
+
} catch (error) {
|
|
102
|
+
if (error instanceof TargetAdapterError) throw error;
|
|
103
|
+
throwIfAborted(signal);
|
|
104
|
+
throw new TargetTransportError('Capsule transport failed');
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
@@ -26,6 +26,12 @@ export interface TargetAdapter {
|
|
|
26
26
|
terminate(capsuleId: string, signal?: AbortSignal): Promise<Capsule>;
|
|
27
27
|
limits(signal?: AbortSignal): Promise<CapsuleLimits>;
|
|
28
28
|
access(capsuleId: string, signal?: AbortSignal): Promise<CapsuleAccess>;
|
|
29
|
+
installRuntime(
|
|
30
|
+
capsuleId: string,
|
|
31
|
+
runtime: unknown,
|
|
32
|
+
accessToken: string,
|
|
33
|
+
signal?: AbortSignal
|
|
34
|
+
): Promise<void>;
|
|
29
35
|
readonly credentialInstall: CredentialInstallCapability;
|
|
30
36
|
}
|
|
31
37
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { throwCapsuleServerError } from './capsule-error-response.js';
|
|
2
|
+
import { TargetProtocolError } from './errors.js';
|
|
3
|
+
import type { Clock } from './types.js';
|
|
4
|
+
|
|
5
|
+
export async function assertCapsuleResponseStatus(
|
|
6
|
+
response: Response,
|
|
7
|
+
expectedStatus: number,
|
|
8
|
+
readJson: (response: Response) => Promise<unknown>,
|
|
9
|
+
clock: Clock
|
|
10
|
+
): Promise<void> {
|
|
11
|
+
if (response.status >= 300 && response.status < 400) {
|
|
12
|
+
await response.body?.cancel().catch(() => undefined);
|
|
13
|
+
throw new TargetProtocolError('Capsule redirects are forbidden');
|
|
14
|
+
}
|
|
15
|
+
if (response.status === expectedStatus) return;
|
|
16
|
+
if (response.status >= 200 && response.status < 300) {
|
|
17
|
+
await response.body?.cancel().catch(() => undefined);
|
|
18
|
+
throw new TargetProtocolError('Target returned an unexpected success status');
|
|
19
|
+
}
|
|
20
|
+
await throwCapsuleServerError(response, readJson, clock);
|
|
21
|
+
}
|
|
@@ -2,7 +2,14 @@ import { MAX_RETRY_ELAPSED_MS } from './bounds.js';
|
|
|
2
2
|
import { TargetAdapterError } from './errors.js';
|
|
3
3
|
import type { Clock, RetryPolicy } from './types.js';
|
|
4
4
|
|
|
5
|
-
export type TargetOperation =
|
|
5
|
+
export type TargetOperation =
|
|
6
|
+
| 'allocate'
|
|
7
|
+
| 'list'
|
|
8
|
+
| 'inspect'
|
|
9
|
+
| 'terminate'
|
|
10
|
+
| 'limits'
|
|
11
|
+
| 'access'
|
|
12
|
+
| 'installRuntime';
|
|
6
13
|
|
|
7
14
|
function throwIfAborted(signal?: AbortSignal): void {
|
|
8
15
|
if (signal?.aborted) {
|