@the-open-engine/zeroshot 6.32.0 → 6.33.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 +14 -6
- package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
- package/lib/agent-cli-provider/provider-registry.d.ts +4 -2
- package/lib/agent-cli-provider/provider-registry.d.ts.map +1 -1
- package/lib/agent-cli-provider/provider-registry.js +13 -3
- package/lib/agent-cli-provider/provider-registry.js.map +1 -1
- package/lib/agent-cli-provider/single-agent-runtime.d.ts.map +1 -1
- package/lib/agent-cli-provider/single-agent-runtime.js +7 -4
- package/lib/agent-cli-provider/single-agent-runtime.js.map +1 -1
- package/lib/agent-cli-provider/types.d.ts +2 -0
- package/lib/agent-cli-provider/types.d.ts.map +1 -1
- package/lib/agent-cli-provider/types.js.map +1 -1
- package/lib/detached-startup.js +4 -0
- package/lib/hosted-target/adapter-request.cjs +6 -3
- package/lib/hosted-target/adapter-request.mjs +6 -3
- package/lib/target/discovery-sections.cjs +35 -13
- package/lib/target/discovery-sections.d.cts +5 -1
- package/lib/target/discovery-sections.d.mts +5 -1
- package/lib/target/discovery-sections.d.ts +5 -1
- package/lib/target/discovery-sections.js +35 -13
- package/lib/target/discovery-sections.mjs +35 -13
- package/lib/target/discovery.cjs +49 -38
- package/lib/target/discovery.d.cts +3 -0
- package/lib/target/discovery.d.mts +3 -0
- package/lib/target/discovery.d.ts +3 -0
- package/lib/target/discovery.js +49 -38
- package/lib/target/discovery.mjs +49 -38
- package/lib/target/index.d.ts +1 -1
- package/lib/target/run-intent-discovery.cjs +30 -0
- package/lib/target/run-intent-discovery.d.cts +11 -0
- package/lib/target/run-intent-discovery.d.mts +11 -0
- package/lib/target/run-intent-discovery.d.ts +11 -0
- package/lib/target/run-intent-discovery.js +30 -0
- package/lib/target/run-intent-discovery.mjs +27 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -3
- package/src/agent/agent-lifecycle.js +11 -1
- package/src/agent/agent-task-executor.js +25 -7
- package/src/agent/structured-output-error.js +42 -0
- package/src/agent-cli-provider/adapters/codex.ts +15 -16
- package/src/agent-cli-provider/provider-registry.ts +15 -3
- package/src/agent-cli-provider/single-agent-runtime.ts +11 -11
- package/src/agent-cli-provider/types.ts +2 -0
- package/src/hosted-target/adapter-request.ts +8 -3
- package/src/isolation-manager.js +52 -0
- package/src/orchestrator.js +6 -0
- package/src/target/discovery-sections.ts +59 -41
- package/src/target/discovery.ts +71 -54
- package/src/target/index.ts +1 -0
- package/src/target/run-intent-discovery.ts +39 -0
package/lib/target/discovery.js
CHANGED
|
@@ -33,52 +33,27 @@ const ROOT_FIELDS = [
|
|
|
33
33
|
'transport',
|
|
34
34
|
'extensions',
|
|
35
35
|
];
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
await response.body?.cancel().catch(() => undefined);
|
|
47
|
-
throw new discovery_errors_js_1.TargetDiscoveryError('request changed target route or authority');
|
|
48
|
-
}
|
|
49
|
-
if (!response.ok) {
|
|
50
|
-
await response.body?.cancel().catch(() => undefined);
|
|
51
|
-
throw new discovery_errors_js_1.TargetDiscoveryError(`request failed with status ${response.status}`);
|
|
52
|
-
}
|
|
53
|
-
return (0, discovery_validation_js_1.record)(await readBoundedJson(response), 'response');
|
|
54
|
-
}
|
|
55
|
-
async function discoverTarget(targetUrl, http) {
|
|
56
|
-
const target = new URL(targetUrl);
|
|
57
|
-
const origin = target.origin;
|
|
58
|
-
const discovery = await fetchDocument(http, new URL(DISCOVERY_PATH, target).href);
|
|
36
|
+
const FLAGS = [
|
|
37
|
+
'capsule_allocate',
|
|
38
|
+
'capsule_read',
|
|
39
|
+
'capsule_terminate',
|
|
40
|
+
'capsule_access',
|
|
41
|
+
'connections_onboarding',
|
|
42
|
+
];
|
|
43
|
+
const SIZE_ERROR = 'response exceeds the size limit';
|
|
44
|
+
const JSON_ERROR = 'response is not valid UTF-8 JSON';
|
|
45
|
+
function parseDiscoveryDocument(discovery, origin) {
|
|
59
46
|
(0, discovery_validation_js_1.exact)(discovery.kind, 'openengine.hosted-target/v1', 'kind');
|
|
60
47
|
const adapter = (0, discovery_sections_js_1.parseAdapter)(discovery);
|
|
61
48
|
const endpoint = (0, discovery_sections_js_1.parseEndpoint)(discovery, origin);
|
|
62
49
|
const capsule = (0, discovery_sections_js_1.parseCapsule)(discovery, origin);
|
|
63
50
|
const oauth = (0, discovery_sections_js_1.parseOAuth)(discovery, origin);
|
|
64
51
|
(0, discovery_validation_js_1.exact)(discovery.organization_binding, 'device_approval', 'organization_binding');
|
|
65
|
-
const capabilityFlags = (0, discovery_validation_js_1.exactStringSet)(discovery.capability_flags, 'capability_flags',
|
|
66
|
-
'capsule_allocate',
|
|
67
|
-
'capsule_read',
|
|
68
|
-
'capsule_terminate',
|
|
69
|
-
'capsule_access',
|
|
70
|
-
'connections_onboarding',
|
|
71
|
-
]);
|
|
52
|
+
const capabilityFlags = (0, discovery_validation_js_1.exactStringSet)(discovery.capability_flags, 'capability_flags', FLAGS);
|
|
72
53
|
const sizes = (0, discovery_sections_js_1.parseSizes)(discovery);
|
|
73
54
|
const session = (0, discovery_sections_js_1.parseSession)(discovery);
|
|
74
55
|
const transport = (0, discovery_sections_js_1.parseTransport)(discovery);
|
|
75
|
-
const
|
|
76
|
-
const metadata = await fetchDocument(http, oauth.metadataUrl);
|
|
77
|
-
(0, discovery_sections_js_1.validateOAuthMetadata)(metadata, origin, [
|
|
78
|
-
oauth.deviceAuthorizationEndpoint,
|
|
79
|
-
oauth.tokenEndpoint,
|
|
80
|
-
oauth.revocationEndpoint,
|
|
81
|
-
]);
|
|
56
|
+
const extensions = (0, discovery_sections_js_1.parseExtensions)(discovery, origin);
|
|
82
57
|
const additional = Object.freeze(Object.fromEntries(Object.entries(discovery).filter(([key]) => !ROOT_FIELDS.includes(key))));
|
|
83
58
|
return Object.freeze({
|
|
84
59
|
origin,
|
|
@@ -92,10 +67,24 @@ async function discoverTarget(targetUrl, http) {
|
|
|
92
67
|
capsule,
|
|
93
68
|
transport,
|
|
94
69
|
capabilityFlags,
|
|
95
|
-
credentialInstall,
|
|
70
|
+
credentialInstall: extensions.credentialInstall,
|
|
71
|
+
runIntent: extensions.runIntent,
|
|
96
72
|
additional,
|
|
97
73
|
});
|
|
98
74
|
}
|
|
75
|
+
async function discoverTarget(targetUrl, http) {
|
|
76
|
+
const target = new URL(targetUrl);
|
|
77
|
+
const origin = target.origin;
|
|
78
|
+
const discovery = await fetchDocument(http, new URL(DISCOVERY_PATH, target).href);
|
|
79
|
+
const descriptor = parseDiscoveryDocument(discovery, origin);
|
|
80
|
+
const metadata = await fetchDocument(http, descriptor.oauth.metadataUrl);
|
|
81
|
+
(0, discovery_sections_js_1.validateOAuthMetadata)(metadata, origin, [
|
|
82
|
+
descriptor.oauth.deviceAuthorizationEndpoint,
|
|
83
|
+
descriptor.oauth.tokenEndpoint,
|
|
84
|
+
descriptor.oauth.revocationEndpoint,
|
|
85
|
+
]);
|
|
86
|
+
return descriptor;
|
|
87
|
+
}
|
|
99
88
|
async function discoverTargetSessionEndpoints(targetUrl, http) {
|
|
100
89
|
const descriptor = await discoverTarget(targetUrl, http);
|
|
101
90
|
return Object.freeze({
|
|
@@ -110,3 +99,25 @@ async function discoverTargetSessionEndpoints(targetUrl, http) {
|
|
|
110
99
|
descriptor,
|
|
111
100
|
});
|
|
112
101
|
}
|
|
102
|
+
function boundedResponseError(kind) {
|
|
103
|
+
return new discovery_errors_js_1.TargetDiscoveryError(kind === 'size' ? SIZE_ERROR : JSON_ERROR);
|
|
104
|
+
}
|
|
105
|
+
async function readBoundedJson(response) {
|
|
106
|
+
return (0, bounded_response_js_1.readBoundedResponseJson)(response, MAX_DISCOVERY_BYTES, boundedResponseError);
|
|
107
|
+
}
|
|
108
|
+
async function fetchDocument(http, url) {
|
|
109
|
+
const response = await http.fetch(url, {
|
|
110
|
+
method: 'GET',
|
|
111
|
+
headers: { Accept: 'application/json' },
|
|
112
|
+
redirect: 'error',
|
|
113
|
+
});
|
|
114
|
+
if (response.url && new URL(response.url).href !== url) {
|
|
115
|
+
await response.body?.cancel().catch(() => undefined);
|
|
116
|
+
throw new discovery_errors_js_1.TargetDiscoveryError('request changed target route or authority');
|
|
117
|
+
}
|
|
118
|
+
if (!response.ok) {
|
|
119
|
+
await response.body?.cancel().catch(() => undefined);
|
|
120
|
+
throw new discovery_errors_js_1.TargetDiscoveryError(`request failed with status ${response.status}`);
|
|
121
|
+
}
|
|
122
|
+
return (0, discovery_validation_js_1.record)(await readBoundedJson(response), 'response');
|
|
123
|
+
}
|
package/lib/target/discovery.mjs
CHANGED
|
@@ -26,52 +26,27 @@ const ROOT_FIELDS = [
|
|
|
26
26
|
'transport',
|
|
27
27
|
'extensions',
|
|
28
28
|
];
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
await response.body?.cancel().catch(() => undefined);
|
|
40
|
-
throw new TargetDiscoveryError('request changed target route or authority');
|
|
41
|
-
}
|
|
42
|
-
if (!response.ok) {
|
|
43
|
-
await response.body?.cancel().catch(() => undefined);
|
|
44
|
-
throw new TargetDiscoveryError(`request failed with status ${response.status}`);
|
|
45
|
-
}
|
|
46
|
-
return record(await readBoundedJson(response), 'response');
|
|
47
|
-
}
|
|
48
|
-
export async function discoverTarget(targetUrl, http) {
|
|
49
|
-
const target = new URL(targetUrl);
|
|
50
|
-
const origin = target.origin;
|
|
51
|
-
const discovery = await fetchDocument(http, new URL(DISCOVERY_PATH, target).href);
|
|
29
|
+
const FLAGS = [
|
|
30
|
+
'capsule_allocate',
|
|
31
|
+
'capsule_read',
|
|
32
|
+
'capsule_terminate',
|
|
33
|
+
'capsule_access',
|
|
34
|
+
'connections_onboarding',
|
|
35
|
+
];
|
|
36
|
+
const SIZE_ERROR = 'response exceeds the size limit';
|
|
37
|
+
const JSON_ERROR = 'response is not valid UTF-8 JSON';
|
|
38
|
+
function parseDiscoveryDocument(discovery, origin) {
|
|
52
39
|
exact(discovery.kind, 'openengine.hosted-target/v1', 'kind');
|
|
53
40
|
const adapter = parseAdapter(discovery);
|
|
54
41
|
const endpoint = parseEndpoint(discovery, origin);
|
|
55
42
|
const capsule = parseCapsule(discovery, origin);
|
|
56
43
|
const oauth = parseOAuth(discovery, origin);
|
|
57
44
|
exact(discovery.organization_binding, 'device_approval', 'organization_binding');
|
|
58
|
-
const capabilityFlags = exactStringSet(discovery.capability_flags, 'capability_flags',
|
|
59
|
-
'capsule_allocate',
|
|
60
|
-
'capsule_read',
|
|
61
|
-
'capsule_terminate',
|
|
62
|
-
'capsule_access',
|
|
63
|
-
'connections_onboarding',
|
|
64
|
-
]);
|
|
45
|
+
const capabilityFlags = exactStringSet(discovery.capability_flags, 'capability_flags', FLAGS);
|
|
65
46
|
const sizes = parseSizes(discovery);
|
|
66
47
|
const session = parseSession(discovery);
|
|
67
48
|
const transport = parseTransport(discovery);
|
|
68
|
-
const
|
|
69
|
-
const metadata = await fetchDocument(http, oauth.metadataUrl);
|
|
70
|
-
validateOAuthMetadata(metadata, origin, [
|
|
71
|
-
oauth.deviceAuthorizationEndpoint,
|
|
72
|
-
oauth.tokenEndpoint,
|
|
73
|
-
oauth.revocationEndpoint,
|
|
74
|
-
]);
|
|
49
|
+
const extensions = parseExtensions(discovery, origin);
|
|
75
50
|
const additional = Object.freeze(Object.fromEntries(Object.entries(discovery).filter(([key]) => !ROOT_FIELDS.includes(key))));
|
|
76
51
|
return Object.freeze({
|
|
77
52
|
origin,
|
|
@@ -85,10 +60,24 @@ export async function discoverTarget(targetUrl, http) {
|
|
|
85
60
|
capsule,
|
|
86
61
|
transport,
|
|
87
62
|
capabilityFlags,
|
|
88
|
-
credentialInstall,
|
|
63
|
+
credentialInstall: extensions.credentialInstall,
|
|
64
|
+
runIntent: extensions.runIntent,
|
|
89
65
|
additional,
|
|
90
66
|
});
|
|
91
67
|
}
|
|
68
|
+
export async function discoverTarget(targetUrl, http) {
|
|
69
|
+
const target = new URL(targetUrl);
|
|
70
|
+
const origin = target.origin;
|
|
71
|
+
const discovery = await fetchDocument(http, new URL(DISCOVERY_PATH, target).href);
|
|
72
|
+
const descriptor = parseDiscoveryDocument(discovery, origin);
|
|
73
|
+
const metadata = await fetchDocument(http, descriptor.oauth.metadataUrl);
|
|
74
|
+
validateOAuthMetadata(metadata, origin, [
|
|
75
|
+
descriptor.oauth.deviceAuthorizationEndpoint,
|
|
76
|
+
descriptor.oauth.tokenEndpoint,
|
|
77
|
+
descriptor.oauth.revocationEndpoint,
|
|
78
|
+
]);
|
|
79
|
+
return descriptor;
|
|
80
|
+
}
|
|
92
81
|
export async function discoverTargetSessionEndpoints(targetUrl, http) {
|
|
93
82
|
const descriptor = await discoverTarget(targetUrl, http);
|
|
94
83
|
return Object.freeze({
|
|
@@ -103,3 +92,25 @@ export async function discoverTargetSessionEndpoints(targetUrl, http) {
|
|
|
103
92
|
descriptor,
|
|
104
93
|
});
|
|
105
94
|
}
|
|
95
|
+
function boundedResponseError(kind) {
|
|
96
|
+
return new TargetDiscoveryError(kind === 'size' ? SIZE_ERROR : JSON_ERROR);
|
|
97
|
+
}
|
|
98
|
+
async function readBoundedJson(response) {
|
|
99
|
+
return readBoundedResponseJson(response, MAX_DISCOVERY_BYTES, boundedResponseError);
|
|
100
|
+
}
|
|
101
|
+
async function fetchDocument(http, url) {
|
|
102
|
+
const response = await http.fetch(url, {
|
|
103
|
+
method: 'GET',
|
|
104
|
+
headers: { Accept: 'application/json' },
|
|
105
|
+
redirect: 'error',
|
|
106
|
+
});
|
|
107
|
+
if (response.url && new URL(response.url).href !== url) {
|
|
108
|
+
await response.body?.cancel().catch(() => undefined);
|
|
109
|
+
throw new TargetDiscoveryError('request changed target route or authority');
|
|
110
|
+
}
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
await response.body?.cancel().catch(() => undefined);
|
|
113
|
+
throw new TargetDiscoveryError(`request failed with status ${response.status}`);
|
|
114
|
+
}
|
|
115
|
+
return record(await readBoundedJson(response), 'response');
|
|
116
|
+
}
|
package/lib/target/index.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ export { acquireTargetLock } from './credential-lock.js';
|
|
|
3
3
|
export { requestDeviceCode, pollForToken, parseTokenResponse, DeviceFlowDeniedError, DeviceFlowExpiredError, UnboundSessionError, type DeviceCodeResponse, type DeviceExchangeContext, type TokenResponse, type HttpTransport, type Clock, } from './device-flow.js';
|
|
4
4
|
export { addTarget, removeTarget, getTarget, listTargets, updateTargetOrganization, validateTargetName, normalizeAndValidateUrl, TargetNameInvalidError, TargetNameExistsError, TargetNotFoundError, TargetUrlInvalidError, type TargetRecord, type SettingsPort, } from './target-registry.js';
|
|
5
5
|
export { TargetSessionManager, LoginRequiredError, type BrowserOpener, type TargetSessionDeps, type TargetSessionManagerInit, } from './target-session.js';
|
|
6
|
-
export { discoverTarget, discoverTargetSessionEndpoints, expandRoute, TargetDiscoveryError, type CredentialInstallDescriptor, type RouteTemplate, type TargetDiscoveryDescriptor, type TargetSessionEndpoints, } from './discovery.js';
|
|
6
|
+
export { discoverTarget, discoverTargetSessionEndpoints, expandRoute, TargetDiscoveryError, type CredentialInstallDescriptor, type RunIntentDescriptor, type RouteTemplate, type TargetDiscoveryDescriptor, type TargetSessionEndpoints, } from './discovery.js';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseRunIntent = parseRunIntent;
|
|
4
|
+
const route_template_js_1 = require("./route-template.cjs");
|
|
5
|
+
const discovery_validation_js_1 = require("./discovery-validation.cjs");
|
|
6
|
+
function parseRunIntent(value, origin) {
|
|
7
|
+
if (value === undefined || value === null)
|
|
8
|
+
return null;
|
|
9
|
+
const extension = (0, discovery_validation_js_1.closedRecord)(value, 'extensions.run_intent', [
|
|
10
|
+
'kind',
|
|
11
|
+
'base_url',
|
|
12
|
+
'route_templates',
|
|
13
|
+
]);
|
|
14
|
+
(0, discovery_validation_js_1.exact)(extension.kind, 'zeroshot.run-intent/v2', 'extensions.run_intent.kind');
|
|
15
|
+
const routes = (0, discovery_validation_js_1.closedRecord)(extension.route_templates, 'extensions.run_intent.route_templates', [
|
|
16
|
+
'submit',
|
|
17
|
+
'status',
|
|
18
|
+
'cancel',
|
|
19
|
+
]);
|
|
20
|
+
const route = (name, variables) => (0, route_template_js_1.routeTemplate)(routes[name], `extensions.run_intent.route_templates.${name}`, variables);
|
|
21
|
+
return Object.freeze({
|
|
22
|
+
kind: 'zeroshot.run-intent/v2',
|
|
23
|
+
baseUrl: (0, discovery_validation_js_1.sameOriginUrl)(extension.base_url, 'extensions.run_intent.base_url', origin),
|
|
24
|
+
routes: Object.freeze({
|
|
25
|
+
submit: route('submit', ['org_id']),
|
|
26
|
+
status: route('status', ['org_id', 'intent_id']),
|
|
27
|
+
cancel: route('cancel', ['org_id', 'intent_id']),
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RouteTemplate } from './route-template.js';
|
|
2
|
+
export interface RunIntentDescriptor {
|
|
3
|
+
readonly kind: 'zeroshot.run-intent/v2';
|
|
4
|
+
readonly baseUrl: string;
|
|
5
|
+
readonly routes: {
|
|
6
|
+
readonly submit: RouteTemplate;
|
|
7
|
+
readonly status: RouteTemplate;
|
|
8
|
+
readonly cancel: RouteTemplate;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare function parseRunIntent(value: unknown, origin: string): RunIntentDescriptor | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RouteTemplate } from './route-template.js';
|
|
2
|
+
export interface RunIntentDescriptor {
|
|
3
|
+
readonly kind: 'zeroshot.run-intent/v2';
|
|
4
|
+
readonly baseUrl: string;
|
|
5
|
+
readonly routes: {
|
|
6
|
+
readonly submit: RouteTemplate;
|
|
7
|
+
readonly status: RouteTemplate;
|
|
8
|
+
readonly cancel: RouteTemplate;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare function parseRunIntent(value: unknown, origin: string): RunIntentDescriptor | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RouteTemplate } from './route-template.js';
|
|
2
|
+
export interface RunIntentDescriptor {
|
|
3
|
+
readonly kind: 'zeroshot.run-intent/v2';
|
|
4
|
+
readonly baseUrl: string;
|
|
5
|
+
readonly routes: {
|
|
6
|
+
readonly submit: RouteTemplate;
|
|
7
|
+
readonly status: RouteTemplate;
|
|
8
|
+
readonly cancel: RouteTemplate;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare function parseRunIntent(value: unknown, origin: string): RunIntentDescriptor | null;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseRunIntent = parseRunIntent;
|
|
4
|
+
const route_template_js_1 = require("./route-template.js");
|
|
5
|
+
const discovery_validation_js_1 = require("./discovery-validation.js");
|
|
6
|
+
function parseRunIntent(value, origin) {
|
|
7
|
+
if (value === undefined || value === null)
|
|
8
|
+
return null;
|
|
9
|
+
const extension = (0, discovery_validation_js_1.closedRecord)(value, 'extensions.run_intent', [
|
|
10
|
+
'kind',
|
|
11
|
+
'base_url',
|
|
12
|
+
'route_templates',
|
|
13
|
+
]);
|
|
14
|
+
(0, discovery_validation_js_1.exact)(extension.kind, 'zeroshot.run-intent/v2', 'extensions.run_intent.kind');
|
|
15
|
+
const routes = (0, discovery_validation_js_1.closedRecord)(extension.route_templates, 'extensions.run_intent.route_templates', [
|
|
16
|
+
'submit',
|
|
17
|
+
'status',
|
|
18
|
+
'cancel',
|
|
19
|
+
]);
|
|
20
|
+
const route = (name, variables) => (0, route_template_js_1.routeTemplate)(routes[name], `extensions.run_intent.route_templates.${name}`, variables);
|
|
21
|
+
return Object.freeze({
|
|
22
|
+
kind: 'zeroshot.run-intent/v2',
|
|
23
|
+
baseUrl: (0, discovery_validation_js_1.sameOriginUrl)(extension.base_url, 'extensions.run_intent.base_url', origin),
|
|
24
|
+
routes: Object.freeze({
|
|
25
|
+
submit: route('submit', ['org_id']),
|
|
26
|
+
status: route('status', ['org_id', 'intent_id']),
|
|
27
|
+
cancel: route('cancel', ['org_id', 'intent_id']),
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { routeTemplate } from './route-template.mjs';
|
|
2
|
+
import { closedRecord, exact, sameOriginUrl } from './discovery-validation.mjs';
|
|
3
|
+
export function parseRunIntent(value, origin) {
|
|
4
|
+
if (value === undefined || value === null)
|
|
5
|
+
return null;
|
|
6
|
+
const extension = closedRecord(value, 'extensions.run_intent', [
|
|
7
|
+
'kind',
|
|
8
|
+
'base_url',
|
|
9
|
+
'route_templates',
|
|
10
|
+
]);
|
|
11
|
+
exact(extension.kind, 'zeroshot.run-intent/v2', 'extensions.run_intent.kind');
|
|
12
|
+
const routes = closedRecord(extension.route_templates, 'extensions.run_intent.route_templates', [
|
|
13
|
+
'submit',
|
|
14
|
+
'status',
|
|
15
|
+
'cancel',
|
|
16
|
+
]);
|
|
17
|
+
const route = (name, variables) => routeTemplate(routes[name], `extensions.run_intent.route_templates.${name}`, variables);
|
|
18
|
+
return Object.freeze({
|
|
19
|
+
kind: 'zeroshot.run-intent/v2',
|
|
20
|
+
baseUrl: sameOriginUrl(extension.base_url, 'extensions.run_intent.base_url', origin),
|
|
21
|
+
routes: Object.freeze({
|
|
22
|
+
submit: route('submit', ['org_id']),
|
|
23
|
+
status: route('status', ['org_id', 'intent_id']),
|
|
24
|
+
cancel: route('cancel', ['org_id', 'intent_id']),
|
|
25
|
+
}),
|
|
26
|
+
});
|
|
27
|
+
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@the-open-engine/zeroshot",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.33.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.33.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.33.0",
|
|
4
4
|
"description": "Independent executor–verifier orchestration for software changes.",
|
|
5
5
|
"main": "src/orchestrator.js",
|
|
6
6
|
"bin": {
|
|
@@ -77,7 +77,6 @@
|
|
|
77
77
|
"protocol:generate": "node scripts/generate-cluster-types.js",
|
|
78
78
|
"protocol:check": "cargo run -p openengine-cluster-testkit --bin generate-cluster-protocol -- --check && node scripts/generate-cluster-types.js --check",
|
|
79
79
|
"rust:distribution:check": "node scripts/rust-distribution.js check-repository",
|
|
80
|
-
"hosted-oecp:image:check": "node scripts/hosted-oecp-image.js check",
|
|
81
80
|
"rust:check": "cargo fmt --all -- --check && cargo clippy --workspace --all-targets -- -D warnings && cargo test --workspace",
|
|
82
81
|
"deadcode": "ts-prune --skip node_modules",
|
|
83
82
|
"deadcode:files": "unimported",
|
|
@@ -177,8 +176,8 @@
|
|
|
177
176
|
"!scripts/hosted-oecp-ci-relevance.js",
|
|
178
177
|
"!scripts/hosted-oecp-image.js",
|
|
179
178
|
"!scripts/hosted-oecp-image-commands.js",
|
|
179
|
+
"!scripts/hosted-oecp-image-inspection.js",
|
|
180
180
|
"!scripts/hosted-oecp-image-smoke.js",
|
|
181
|
-
"!scripts/hosted-oecp-manifest.js",
|
|
182
181
|
"!scripts/hosted-oecp-smoke-capability.js",
|
|
183
182
|
"!scripts/hosted-oecp-smoke-client.js",
|
|
184
183
|
"!scripts/hosted-oecp-smoke-codex.mjs",
|
|
@@ -24,6 +24,10 @@ const { findPlatformMismatchReason } = require('./validation-platform');
|
|
|
24
24
|
const { calculateRateLimitDelay, isRateLimitError } = require('./rate-limit-backoff');
|
|
25
25
|
const { updateAgentProviderSession } = require('./provider-session');
|
|
26
26
|
const { rebuildProviderSessionAfterCommit } = require('./agent-task-executor');
|
|
27
|
+
const {
|
|
28
|
+
buildStructuredOutputClusterFailure,
|
|
29
|
+
isStructuredOutputInvalidError,
|
|
30
|
+
} = require('./structured-output-error');
|
|
27
31
|
const {
|
|
28
32
|
commitRecordedOwnership,
|
|
29
33
|
markCleanupRequired,
|
|
@@ -735,6 +739,7 @@ async function handleFinalFailure(agent, triggeringMessage, error, maxRetries) {
|
|
|
735
739
|
const failureAttempts = error?.terminationAttempts ?? maxRetries;
|
|
736
740
|
const unsupportedCapability =
|
|
737
741
|
error?.code === 'unsupported-capability' && error?.permanent === true;
|
|
742
|
+
const structuredOutputInvalid = isStructuredOutputInvalidError(error);
|
|
738
743
|
console.error(`
|
|
739
744
|
${'='.repeat(80)}`);
|
|
740
745
|
console.error(`🔴🔴🔴 MAX RETRIES EXHAUSTED - AGENT: ${agent.id} 🔴🔴🔴`);
|
|
@@ -810,6 +815,9 @@ ${'='.repeat(80)}`);
|
|
|
810
815
|
});
|
|
811
816
|
}
|
|
812
817
|
|
|
818
|
+
if (structuredOutputInvalid) {
|
|
819
|
+
agent._publish(buildStructuredOutputClusterFailure(agent, error));
|
|
820
|
+
}
|
|
813
821
|
if (unsupportedCapability) {
|
|
814
822
|
agent._publish({
|
|
815
823
|
topic: 'CLUSTER_FAILED',
|
|
@@ -880,6 +888,7 @@ ${'='.repeat(80)}`);
|
|
|
880
888
|
capability: error.capability,
|
|
881
889
|
}
|
|
882
890
|
: {}),
|
|
891
|
+
...(structuredOutputInvalid ? { code: error.code, details: error.details ?? null } : {}),
|
|
883
892
|
timestamp: Date.now(),
|
|
884
893
|
};
|
|
885
894
|
|
|
@@ -910,6 +919,7 @@ ${'='.repeat(80)}`);
|
|
|
910
919
|
capability: error.capability,
|
|
911
920
|
}
|
|
912
921
|
: {}),
|
|
922
|
+
...(structuredOutputInvalid ? { code: error.code, details: error.details ?? null } : {}),
|
|
913
923
|
hookFailureContext: error.message.includes('Hook uses result')
|
|
914
924
|
? {
|
|
915
925
|
taskId: agent.currentTaskId || 'UNKNOWN',
|
|
@@ -936,7 +946,7 @@ ${'='.repeat(80)}`);
|
|
|
936
946
|
orchestrator: agent.orchestrator,
|
|
937
947
|
});
|
|
938
948
|
|
|
939
|
-
if (!error?.terminationExhausted && !unsupportedCapability) {
|
|
949
|
+
if (!error?.terminationExhausted && !unsupportedCapability && !structuredOutputInvalid) {
|
|
940
950
|
agent.state = 'idle';
|
|
941
951
|
}
|
|
942
952
|
}
|
|
@@ -52,6 +52,10 @@ const {
|
|
|
52
52
|
validateCompletedResumeIdentity,
|
|
53
53
|
} = require('./provider-session');
|
|
54
54
|
const { extractClaudeVertexModelError } = require('./output-extraction');
|
|
55
|
+
const {
|
|
56
|
+
createStructuredOutputInvalidError,
|
|
57
|
+
isStructuredOutputInvalidError,
|
|
58
|
+
} = require('./structured-output-error');
|
|
55
59
|
const TASK_TERMINAL_STATUSES = new Set(['completed', 'failed', 'killed', 'stale']);
|
|
56
60
|
function runCommandWithTimeout(command, args, options = {}, callback = null) {
|
|
57
61
|
const timeout = options.timeout ?? 30000;
|
|
@@ -1412,6 +1416,7 @@ async function evaluateStructuredSuccess({ agent, taskId, state, success, allowR
|
|
|
1412
1416
|
return { success: true, error: null };
|
|
1413
1417
|
} catch (error) {
|
|
1414
1418
|
if (
|
|
1419
|
+
isStructuredOutputInvalidError(error) ||
|
|
1415
1420
|
isNestedLifecycleError(error) ||
|
|
1416
1421
|
error?.permanent === true ||
|
|
1417
1422
|
error?.recoveryAbort === true
|
|
@@ -2858,7 +2863,10 @@ async function parseResultOutput(agent, output, { allowRecovery = true } = {}) {
|
|
|
2858
2863
|
const schema = agent.config.jsonSchema;
|
|
2859
2864
|
if (!schema) {
|
|
2860
2865
|
if (parsed) return parsed;
|
|
2861
|
-
throw
|
|
2866
|
+
throw createStructuredOutputInvalidError(
|
|
2867
|
+
`Agent ${agent.id} output missing required JSON block`,
|
|
2868
|
+
'missing_json'
|
|
2869
|
+
);
|
|
2862
2870
|
}
|
|
2863
2871
|
|
|
2864
2872
|
const { createStructuredOutputValidator, reformatOutput } = require('./output-reformatter');
|
|
@@ -2911,7 +2919,12 @@ async function parseResultOutput(agent, output, { allowRecovery = true } = {}) {
|
|
|
2911
2919
|
throw new Error('Task execution failed - no output');
|
|
2912
2920
|
}
|
|
2913
2921
|
const recoveryDetail = recovery?.lastError ? ` Recovery exhausted: ${recovery.lastError}.` : '';
|
|
2914
|
-
throw
|
|
2922
|
+
throw createStructuredOutputInvalidError(
|
|
2923
|
+
`Agent ${agent.id} output missing required JSON block.${recoveryDetail}`,
|
|
2924
|
+
'missing_json',
|
|
2925
|
+
directValidation,
|
|
2926
|
+
recovery
|
|
2927
|
+
);
|
|
2915
2928
|
}
|
|
2916
2929
|
|
|
2917
2930
|
if (!allowRecovery) {
|
|
@@ -2921,13 +2934,18 @@ async function parseResultOutput(agent, output, { allowRecovery = true } = {}) {
|
|
|
2921
2934
|
|
|
2922
2935
|
const errorDetail = directValidation?.error || 'unknown schema error';
|
|
2923
2936
|
const message = `Agent ${agent.id} output failed JSON schema validation: ${errorDetail}`;
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2937
|
+
const terminalStructuredRole = ['planner', 'conductor', 'validator'].includes(agent.role);
|
|
2938
|
+
if (recovery?.status === 'exhausted' && terminalStructuredRole) {
|
|
2939
|
+
throw createStructuredOutputInvalidError(
|
|
2940
|
+
`${message}. Recovery exhausted after ${recovery.attempts} attempts: ${recovery.lastError}`,
|
|
2941
|
+
'schema_validation',
|
|
2942
|
+
directValidation,
|
|
2943
|
+
recovery
|
|
2929
2944
|
);
|
|
2930
2945
|
}
|
|
2946
|
+
if (agent.role === 'validator') {
|
|
2947
|
+
throw new Error(message);
|
|
2948
|
+
}
|
|
2931
2949
|
|
|
2932
2950
|
console.warn(`⚠️ ${message}`);
|
|
2933
2951
|
agent._publish({
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const STRUCTURED_OUTPUT_INVALID_CODE = 'STRUCTURED_OUTPUT_INVALID';
|
|
2
|
+
|
|
3
|
+
function createStructuredOutputInvalidError(message, kind, validation = null, recovery = null) {
|
|
4
|
+
const error = new Error(message);
|
|
5
|
+
error.code = STRUCTURED_OUTPUT_INVALID_CODE;
|
|
6
|
+
error.details = {
|
|
7
|
+
kind,
|
|
8
|
+
validationError: validation?.error ?? null,
|
|
9
|
+
recoveryAttempts: recovery?.status === 'exhausted' ? recovery.attempts : 0,
|
|
10
|
+
recoveryError: recovery?.status === 'exhausted' ? recovery.lastError : null,
|
|
11
|
+
};
|
|
12
|
+
return error;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function isStructuredOutputInvalidError(error) {
|
|
16
|
+
return error?.code === STRUCTURED_OUTPUT_INVALID_CODE;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function buildStructuredOutputClusterFailure(agent, error) {
|
|
20
|
+
return {
|
|
21
|
+
topic: 'CLUSTER_FAILED',
|
|
22
|
+
receiver: 'broadcast',
|
|
23
|
+
content: {
|
|
24
|
+
text: `Cluster failed: structured output is invalid for ${agent.id} - ${error.message}`,
|
|
25
|
+
data: {
|
|
26
|
+
reason: 'structured_output_invalid',
|
|
27
|
+
agentId: agent.id,
|
|
28
|
+
role: agent.role,
|
|
29
|
+
code: error.code,
|
|
30
|
+
details: error.details ?? null,
|
|
31
|
+
error: error.message,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
STRUCTURED_OUTPUT_INVALID_CODE,
|
|
39
|
+
createStructuredOutputInvalidError,
|
|
40
|
+
isStructuredOutputInvalidError,
|
|
41
|
+
buildStructuredOutputClusterFailure,
|
|
42
|
+
};
|
|
@@ -55,11 +55,12 @@ function detectCliFeatures(
|
|
|
55
55
|
const help = helpText ?? '';
|
|
56
56
|
const unknown = !help;
|
|
57
57
|
const supportsConfigOverride = supports(help, /--config\b/);
|
|
58
|
+
const supportsSandbox = !unknown && /--sandbox\b/.test(help);
|
|
58
59
|
return {
|
|
59
60
|
provider: 'codex',
|
|
60
61
|
supportsJson: supports(help, /--json\b/),
|
|
61
62
|
supportsOutputSchema: supports(help, /--output-schema\b/),
|
|
62
|
-
supportsAutoApprove:
|
|
63
|
+
supportsAutoApprove: !unknown && supportsConfigOverride && supportsSandbox,
|
|
63
64
|
supportsCwd: supports(help, /\s-C\b/) || supports(help, /--cwd\b/),
|
|
64
65
|
supportsConfigOverride,
|
|
65
66
|
supportsModel: supports(help, /\s-m\b/) || supports(help, /--model\b/),
|
|
@@ -67,7 +68,7 @@ function detectCliFeatures(
|
|
|
67
68
|
supportsResume: supports(help, /\bresume\b/),
|
|
68
69
|
supportsWebSearch:
|
|
69
70
|
!unknown && supportsConfigOverride && isCliVersionAtLeast(versionText, '0.146.0'),
|
|
70
|
-
supportsSandbox
|
|
71
|
+
supportsSandbox,
|
|
71
72
|
supportsEphemeral: !unknown && /--ephemeral\b/.test(help),
|
|
72
73
|
supportsIgnoreUserConfig: !unknown && /--ignore-user-config\b/.test(help),
|
|
73
74
|
supportsIgnoreRules: !unknown && /--ignore-rules\b/.test(help),
|
|
@@ -113,7 +114,9 @@ function addCwdArgs(args: string[], options: BuildProviderCommandOptions): void
|
|
|
113
114
|
function addAutoApproveArgs(args: string[], options: BuildProviderCommandOptions): void {
|
|
114
115
|
const features = optionFeatures(options);
|
|
115
116
|
if (options.autoApprove && features.supportsAutoApprove) {
|
|
116
|
-
|
|
117
|
+
const sandboxMode =
|
|
118
|
+
options.executionContext === 'docker' ? 'danger-full-access' : 'workspace-write';
|
|
119
|
+
args.push('--sandbox', sandboxMode, '--config', 'approval_policy="never"');
|
|
117
120
|
}
|
|
118
121
|
}
|
|
119
122
|
|
|
@@ -166,7 +169,7 @@ function collectWarnings(options: BuildProviderCommandOptions): WarningMetadata[
|
|
|
166
169
|
warning(
|
|
167
170
|
'codex',
|
|
168
171
|
'codex-auto-approve',
|
|
169
|
-
'Codex CLI does not support
|
|
172
|
+
'Codex CLI does not support unattended workspace-write mode; continuing without it.'
|
|
170
173
|
)
|
|
171
174
|
);
|
|
172
175
|
}
|
|
@@ -255,7 +258,9 @@ function assertStructuredOutputRecoveryFeatures(options: BuildProviderCommandOpt
|
|
|
255
258
|
const missing = [
|
|
256
259
|
['--sandbox', features.supportsSandbox],
|
|
257
260
|
['--ephemeral', features.supportsEphemeral],
|
|
258
|
-
|
|
261
|
+
...(options.trustIsolatedCodexProfile === true
|
|
262
|
+
? []
|
|
263
|
+
: [['--ignore-user-config', features.supportsIgnoreUserConfig] as const]),
|
|
259
264
|
['--ignore-rules', features.supportsIgnoreRules],
|
|
260
265
|
['--strict-config', features.supportsStrictConfig],
|
|
261
266
|
['--config', features.supportsConfigOverride],
|
|
@@ -284,17 +289,11 @@ function buildStructuredOutputRecoveryCommand(
|
|
|
284
289
|
const args = [...spec.args];
|
|
285
290
|
const prompt = args.pop();
|
|
286
291
|
if (prompt === undefined) throw new Error('Codex recovery command is missing its prompt');
|
|
287
|
-
args.push(
|
|
288
|
-
|
|
289
|
-
'
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
'--ignore-rules',
|
|
293
|
-
'--strict-config',
|
|
294
|
-
'--config',
|
|
295
|
-
'web_search="disabled"',
|
|
296
|
-
prompt
|
|
297
|
-
);
|
|
292
|
+
args.push('--sandbox', 'read-only', '--ephemeral');
|
|
293
|
+
if (options.trustIsolatedCodexProfile !== true) {
|
|
294
|
+
args.push('--ignore-user-config');
|
|
295
|
+
}
|
|
296
|
+
args.push('--ignore-rules', '--strict-config', '--config', 'web_search="disabled"', prompt);
|
|
298
297
|
return { ...spec, args };
|
|
299
298
|
}
|
|
300
299
|
|