@agentuity/core 1.0.48 → 1.0.50
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/dist/services/api.d.ts.map +1 -1
- package/dist/services/api.js +13 -5
- package/dist/services/api.js.map +1 -1
- package/dist/services/oauth/flow.d.ts +51 -0
- package/dist/services/oauth/flow.d.ts.map +1 -0
- package/dist/services/oauth/flow.js +183 -0
- package/dist/services/oauth/flow.js.map +1 -0
- package/dist/services/oauth/index.d.ts +1 -0
- package/dist/services/oauth/index.d.ts.map +1 -1
- package/dist/services/oauth/index.js +1 -0
- package/dist/services/oauth/index.js.map +1 -1
- package/dist/services/oauth/types.d.ts +34 -0
- package/dist/services/oauth/types.d.ts.map +1 -1
- package/dist/services/oauth/types.js +52 -0
- package/dist/services/oauth/types.js.map +1 -1
- package/dist/services/sandbox/client.d.ts.map +1 -1
- package/dist/services/sandbox/client.js +35 -13
- package/dist/services/sandbox/client.js.map +1 -1
- package/dist/services/sandbox/create.d.ts +2 -0
- package/dist/services/sandbox/create.d.ts.map +1 -1
- package/dist/services/sandbox/create.js +4 -0
- package/dist/services/sandbox/create.js.map +1 -1
- package/dist/services/sandbox/execution.d.ts +1 -0
- package/dist/services/sandbox/execution.d.ts.map +1 -1
- package/dist/services/sandbox/execution.js +4 -2
- package/dist/services/sandbox/execution.js.map +1 -1
- package/dist/services/sandbox/files.js +1 -1
- package/dist/services/sandbox/files.js.map +1 -1
- package/dist/services/sandbox/index.d.ts +2 -0
- package/dist/services/sandbox/index.d.ts.map +1 -1
- package/dist/services/sandbox/index.js +1 -0
- package/dist/services/sandbox/index.js.map +1 -1
- package/dist/services/sandbox/job.d.ts +227 -0
- package/dist/services/sandbox/job.d.ts.map +1 -0
- package/dist/services/sandbox/job.js +109 -0
- package/dist/services/sandbox/job.js.map +1 -0
- package/dist/services/sandbox/types.d.ts +35 -0
- package/dist/services/sandbox/types.d.ts.map +1 -1
- package/dist/services/sandbox/types.js +23 -0
- package/dist/services/sandbox/types.js.map +1 -1
- package/dist/services/sandbox/util.d.ts +1 -0
- package/dist/services/sandbox/util.d.ts.map +1 -1
- package/dist/services/sandbox/util.js +1 -0
- package/dist/services/sandbox/util.js.map +1 -1
- package/package.json +2 -2
- package/src/services/api.ts +15 -5
- package/src/services/oauth/flow.ts +215 -0
- package/src/services/oauth/index.ts +1 -0
- package/src/services/oauth/types.ts +66 -0
- package/src/services/sandbox/client.ts +40 -14
- package/src/services/sandbox/create.ts +4 -0
- package/src/services/sandbox/execution.ts +5 -2
- package/src/services/sandbox/files.ts +1 -1
- package/src/services/sandbox/index.ts +18 -0
- package/src/services/sandbox/job.ts +161 -0
- package/src/services/sandbox/types.ts +29 -0
- package/src/services/sandbox/util.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/services/sandbox/util.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/services/sandbox/util.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentuity/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.50",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Agentuity employees and contributors",
|
|
6
6
|
"type": "module",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"zod": "^4.3.5"
|
|
90
90
|
},
|
|
91
91
|
"devDependencies": {
|
|
92
|
-
"@agentuity/test-utils": "1.0.
|
|
92
|
+
"@agentuity/test-utils": "1.0.50",
|
|
93
93
|
"@types/bun": "latest",
|
|
94
94
|
"bun-types": "latest",
|
|
95
95
|
"esbuild": "^0.25.0",
|
package/src/services/api.ts
CHANGED
|
@@ -272,7 +272,7 @@ export class APIClient {
|
|
|
272
272
|
signal?: AbortSignal,
|
|
273
273
|
extraHeaders?: Record<string, string>
|
|
274
274
|
): Promise<Response> {
|
|
275
|
-
return this.#makeRequest('GET', endpoint, undefined, signal, undefined, extraHeaders);
|
|
275
|
+
return this.#makeRequest('GET', endpoint, undefined, signal, undefined, extraHeaders, true);
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
/**
|
|
@@ -285,7 +285,7 @@ export class APIClient {
|
|
|
285
285
|
contentType: string,
|
|
286
286
|
signal?: AbortSignal
|
|
287
287
|
): Promise<Response> {
|
|
288
|
-
return this.#makeRequest('POST', endpoint, body, signal, contentType);
|
|
288
|
+
return this.#makeRequest('POST', endpoint, body, signal, contentType, undefined, true);
|
|
289
289
|
}
|
|
290
290
|
|
|
291
291
|
/**
|
|
@@ -299,7 +299,7 @@ export class APIClient {
|
|
|
299
299
|
signal?: AbortSignal,
|
|
300
300
|
extraHeaders?: Record<string, string>
|
|
301
301
|
): Promise<Response> {
|
|
302
|
-
return this.#makeRequest('PUT', endpoint, body, signal, contentType, extraHeaders);
|
|
302
|
+
return this.#makeRequest('PUT', endpoint, body, signal, contentType, extraHeaders, true);
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
/**
|
|
@@ -375,7 +375,8 @@ export class APIClient {
|
|
|
375
375
|
body?: unknown,
|
|
376
376
|
signal?: AbortSignal,
|
|
377
377
|
contentType?: string,
|
|
378
|
-
extraHeaders?: Record<string, string
|
|
378
|
+
extraHeaders?: Record<string, string>,
|
|
379
|
+
raw?: boolean
|
|
379
380
|
): Promise<Response> {
|
|
380
381
|
this.#logger.trace('sending %s to %s%s', method, this.#baseUrl, endpoint);
|
|
381
382
|
|
|
@@ -599,7 +600,10 @@ export class APIClient {
|
|
|
599
600
|
}
|
|
600
601
|
|
|
601
602
|
// Handle error responses
|
|
602
|
-
|
|
603
|
+
// When raw mode is set, skip error handling and return the response as-is
|
|
604
|
+
// so callers (e.g., sandboxReadFile) can inspect the status and provide
|
|
605
|
+
// context-aware error messages (including sandbox ID, file path, etc.).
|
|
606
|
+
if (!raw && !response.ok) {
|
|
603
607
|
const responseBody = await response.text();
|
|
604
608
|
const contentType = response.headers.get('content-type');
|
|
605
609
|
|
|
@@ -722,6 +726,12 @@ export class APIClient {
|
|
|
722
726
|
|
|
723
727
|
this.#logger.debug('%s succeeded with status: %d', url, response.status);
|
|
724
728
|
|
|
729
|
+
// In raw mode, return the untouched Response (status, headers, body)
|
|
730
|
+
// so callers can inspect everything themselves.
|
|
731
|
+
if (raw) {
|
|
732
|
+
return response;
|
|
733
|
+
}
|
|
734
|
+
|
|
725
735
|
// Successful response; handle empty bodies (e.g., 204 No Content)
|
|
726
736
|
if (response.status === 204 || response.headers.get('content-length') === '0') {
|
|
727
737
|
return new Response(null, { status: 204 });
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { getEnv } from '../env.ts';
|
|
2
|
+
import { OAuthResponseError } from './util.ts';
|
|
3
|
+
import { OAuthTokenResponseSchema, OAuthUserInfoSchema } from './types.ts';
|
|
4
|
+
import type { OAuthFlowConfig, OAuthTokenResponse, OAuthUserInfo } from './types.ts';
|
|
5
|
+
|
|
6
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Resolve OAuth configuration by merging explicit config with environment variables.
|
|
10
|
+
* Priority: explicit config > env vars > issuer-derived URLs > defaults.
|
|
11
|
+
*/
|
|
12
|
+
function resolveConfig(config?: OAuthFlowConfig) {
|
|
13
|
+
const clientId = config?.clientId ?? getEnv('OAUTH_CLIENT_ID');
|
|
14
|
+
const clientSecret = config?.clientSecret ?? getEnv('OAUTH_CLIENT_SECRET');
|
|
15
|
+
const issuer = config?.issuer ?? getEnv('OAUTH_ISSUER');
|
|
16
|
+
const authorizeUrl =
|
|
17
|
+
config?.authorizeUrl ??
|
|
18
|
+
getEnv('OAUTH_AUTHORIZE_URL') ??
|
|
19
|
+
(issuer ? `${issuer}/authorize` : undefined);
|
|
20
|
+
const tokenUrl =
|
|
21
|
+
config?.tokenUrl ??
|
|
22
|
+
getEnv('OAUTH_TOKEN_URL') ??
|
|
23
|
+
(issuer ? `${issuer}/oauth/token` : undefined);
|
|
24
|
+
const userinfoUrl =
|
|
25
|
+
config?.userinfoUrl ??
|
|
26
|
+
getEnv('OAUTH_USERINFO_URL') ??
|
|
27
|
+
(issuer ? `${issuer}/userinfo` : undefined);
|
|
28
|
+
const scopes = config?.scopes ?? getEnv('OAUTH_SCOPES') ?? 'openid profile email';
|
|
29
|
+
|
|
30
|
+
const prompt = config?.prompt;
|
|
31
|
+
|
|
32
|
+
return { clientId, clientSecret, issuer, authorizeUrl, tokenUrl, userinfoUrl, scopes, prompt };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Build an OAuth 2.0 authorization URL for redirecting the user to the OIDC provider.
|
|
37
|
+
*
|
|
38
|
+
* @param redirectUri - The callback URL the provider will redirect to after authentication
|
|
39
|
+
* @param config - Optional OAuth configuration. Falls back to environment variables.
|
|
40
|
+
* @returns The full authorization URL to redirect the user to
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* // Uses OAUTH_CLIENT_ID, OAUTH_AUTHORIZE_URL (or OAUTH_ISSUER) from env
|
|
45
|
+
* const url = buildAuthorizeUrl('http://localhost:3500/api/oauth/login');
|
|
46
|
+
*
|
|
47
|
+
* // Or with explicit config
|
|
48
|
+
* const url = buildAuthorizeUrl('http://localhost:3500/api/oauth/login', {
|
|
49
|
+
* issuer: 'https://auth.agentuity.cloud',
|
|
50
|
+
* clientId: 'my-client-id',
|
|
51
|
+
* });
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export function buildAuthorizeUrl(redirectUri: string, config?: OAuthFlowConfig): string {
|
|
55
|
+
const resolved = resolveConfig(config);
|
|
56
|
+
|
|
57
|
+
if (!resolved.authorizeUrl) {
|
|
58
|
+
throw new OAuthResponseError({
|
|
59
|
+
message:
|
|
60
|
+
'No authorize URL configured. Set OAUTH_AUTHORIZE_URL or OAUTH_ISSUER environment variable.',
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (!resolved.clientId) {
|
|
64
|
+
throw new OAuthResponseError({
|
|
65
|
+
message: 'No client ID configured. Set OAUTH_CLIENT_ID environment variable.',
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const params = new URLSearchParams({
|
|
70
|
+
client_id: resolved.clientId,
|
|
71
|
+
redirect_uri: redirectUri,
|
|
72
|
+
response_type: 'code',
|
|
73
|
+
scope: resolved.scopes,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (resolved.prompt) {
|
|
77
|
+
params.set('prompt', resolved.prompt);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return `${resolved.authorizeUrl}?${params.toString()}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Exchange an authorization code for an access token.
|
|
85
|
+
*
|
|
86
|
+
* @param code - The authorization code received from the OAuth callback
|
|
87
|
+
* @param redirectUri - The same redirect URI used in the authorization request
|
|
88
|
+
* @param config - Optional OAuth configuration. Falls back to environment variables.
|
|
89
|
+
* @returns The token response including access_token, and optionally refresh_token, id_token, etc.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* const token = await exchangeToken(code, 'http://localhost:3500/api/oauth/login');
|
|
94
|
+
* console.log(token.access_token);
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export async function exchangeToken(
|
|
98
|
+
code: string,
|
|
99
|
+
redirectUri: string,
|
|
100
|
+
config?: OAuthFlowConfig
|
|
101
|
+
): Promise<OAuthTokenResponse> {
|
|
102
|
+
const resolved = resolveConfig(config);
|
|
103
|
+
|
|
104
|
+
if (!resolved.tokenUrl) {
|
|
105
|
+
throw new OAuthResponseError({
|
|
106
|
+
message:
|
|
107
|
+
'No token URL configured. Set OAUTH_TOKEN_URL or OAUTH_ISSUER environment variable.',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
if (!resolved.clientId) {
|
|
111
|
+
throw new OAuthResponseError({
|
|
112
|
+
message: 'No client ID configured. Set OAUTH_CLIENT_ID environment variable.',
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
if (!resolved.clientSecret) {
|
|
116
|
+
throw new OAuthResponseError({
|
|
117
|
+
message: 'No client secret configured. Set OAUTH_CLIENT_SECRET environment variable.',
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const controller = new AbortController();
|
|
122
|
+
const timer = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
|
|
123
|
+
|
|
124
|
+
let response: Response;
|
|
125
|
+
try {
|
|
126
|
+
response = await fetch(resolved.tokenUrl, {
|
|
127
|
+
method: 'POST',
|
|
128
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
129
|
+
body: new URLSearchParams({
|
|
130
|
+
grant_type: 'authorization_code',
|
|
131
|
+
code,
|
|
132
|
+
redirect_uri: redirectUri,
|
|
133
|
+
client_id: resolved.clientId,
|
|
134
|
+
client_secret: resolved.clientSecret,
|
|
135
|
+
}),
|
|
136
|
+
signal: controller.signal,
|
|
137
|
+
});
|
|
138
|
+
} catch (err) {
|
|
139
|
+
clearTimeout(timer);
|
|
140
|
+
if (err instanceof DOMException && err.name === 'AbortError') {
|
|
141
|
+
throw new OAuthResponseError({
|
|
142
|
+
message: `Token exchange timed out after ${DEFAULT_TIMEOUT_MS}ms`,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
throw err;
|
|
146
|
+
}
|
|
147
|
+
clearTimeout(timer);
|
|
148
|
+
|
|
149
|
+
if (!response.ok) {
|
|
150
|
+
const error = await response.text();
|
|
151
|
+
throw new OAuthResponseError({
|
|
152
|
+
message: `Token exchange failed (${response.status}): ${error}`,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const data = await response.json();
|
|
157
|
+
return OAuthTokenResponseSchema.parse(data);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Fetch user information from the OIDC userinfo endpoint using an access token.
|
|
162
|
+
*
|
|
163
|
+
* @param accessToken - The access token obtained from the token exchange
|
|
164
|
+
* @param config - Optional OAuth configuration. Falls back to environment variables.
|
|
165
|
+
* @returns The user info including sub, name, email, and any additional claims
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* const user = await fetchUserInfo(token.access_token);
|
|
170
|
+
* console.log(user.name, user.email);
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
export async function fetchUserInfo(
|
|
174
|
+
accessToken: string,
|
|
175
|
+
config?: OAuthFlowConfig
|
|
176
|
+
): Promise<OAuthUserInfo> {
|
|
177
|
+
const resolved = resolveConfig(config);
|
|
178
|
+
|
|
179
|
+
if (!resolved.userinfoUrl) {
|
|
180
|
+
throw new OAuthResponseError({
|
|
181
|
+
message:
|
|
182
|
+
'No userinfo URL configured. Set OAUTH_USERINFO_URL or OAUTH_ISSUER environment variable.',
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const controller = new AbortController();
|
|
187
|
+
const timer = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
|
|
188
|
+
|
|
189
|
+
let response: Response;
|
|
190
|
+
try {
|
|
191
|
+
response = await fetch(resolved.userinfoUrl, {
|
|
192
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
193
|
+
signal: controller.signal,
|
|
194
|
+
});
|
|
195
|
+
} catch (err) {
|
|
196
|
+
clearTimeout(timer);
|
|
197
|
+
if (err instanceof DOMException && err.name === 'AbortError') {
|
|
198
|
+
throw new OAuthResponseError({
|
|
199
|
+
message: `Userinfo request timed out after ${DEFAULT_TIMEOUT_MS}ms`,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
throw err;
|
|
203
|
+
}
|
|
204
|
+
clearTimeout(timer);
|
|
205
|
+
|
|
206
|
+
if (!response.ok) {
|
|
207
|
+
const error = await response.text();
|
|
208
|
+
throw new OAuthResponseError({
|
|
209
|
+
message: `Failed to fetch user info (${response.status}): ${error}`,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const data = await response.json();
|
|
214
|
+
return OAuthUserInfoSchema.parse(data);
|
|
215
|
+
}
|
|
@@ -238,3 +238,69 @@ export type OAuthUserConsentRevokeResponse = z.infer<typeof OAuthUserConsentRevo
|
|
|
238
238
|
export type OAuthScopesResponse = z.infer<typeof OAuthScopesResponseSchema>;
|
|
239
239
|
export type OAuthOrgMembersResponse = z.infer<typeof OAuthOrgMembersResponseSchema>;
|
|
240
240
|
export type OAuthKeysRotateResponse = z.infer<typeof OAuthKeysRotateResponseSchema>;
|
|
241
|
+
|
|
242
|
+
// ============================================================================
|
|
243
|
+
// OAuth 2.0 Authorization Code Flow Types
|
|
244
|
+
// ============================================================================
|
|
245
|
+
|
|
246
|
+
export const OAuthFlowConfigSchema = z.object({
|
|
247
|
+
clientId: z.string().optional().describe('OAuth client ID. Defaults to OAUTH_CLIENT_ID env var'),
|
|
248
|
+
clientSecret: z
|
|
249
|
+
.string()
|
|
250
|
+
.optional()
|
|
251
|
+
.describe('OAuth client secret. Defaults to OAUTH_CLIENT_SECRET env var'),
|
|
252
|
+
issuer: z
|
|
253
|
+
.string()
|
|
254
|
+
.optional()
|
|
255
|
+
.describe(
|
|
256
|
+
'OIDC issuer base URL. Defaults to OAUTH_ISSUER env var. Used to derive authorize/token/userinfo URLs'
|
|
257
|
+
),
|
|
258
|
+
authorizeUrl: z
|
|
259
|
+
.string()
|
|
260
|
+
.optional()
|
|
261
|
+
.describe('Authorization endpoint. Defaults to OAUTH_AUTHORIZE_URL or {issuer}/authorize'),
|
|
262
|
+
tokenUrl: z
|
|
263
|
+
.string()
|
|
264
|
+
.optional()
|
|
265
|
+
.describe('Token endpoint. Defaults to OAUTH_TOKEN_URL or {issuer}/oauth/token'),
|
|
266
|
+
userinfoUrl: z
|
|
267
|
+
.string()
|
|
268
|
+
.optional()
|
|
269
|
+
.describe('UserInfo endpoint. Defaults to OAUTH_USERINFO_URL or {issuer}/userinfo'),
|
|
270
|
+
scopes: z
|
|
271
|
+
.string()
|
|
272
|
+
.optional()
|
|
273
|
+
.describe('Space-separated scopes. Defaults to OAUTH_SCOPES or "openid profile email"'),
|
|
274
|
+
prompt: z
|
|
275
|
+
.enum(['none', 'login', 'consent', 'select_account'])
|
|
276
|
+
.optional()
|
|
277
|
+
.describe(
|
|
278
|
+
'OIDC prompt parameter. Controls authentication UX: "login" forces re-auth, "consent" forces consent screen, "none" fails if not authenticated, "select_account" lets user pick an account'
|
|
279
|
+
),
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
export type OAuthFlowConfig = z.infer<typeof OAuthFlowConfigSchema>;
|
|
283
|
+
|
|
284
|
+
export const OAuthTokenResponseSchema = z.object({
|
|
285
|
+
access_token: z.string(),
|
|
286
|
+
token_type: z.string().optional(),
|
|
287
|
+
expires_in: z.number().optional(),
|
|
288
|
+
refresh_token: z.string().optional(),
|
|
289
|
+
scope: z.string().optional(),
|
|
290
|
+
id_token: z.string().optional(),
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
export type OAuthTokenResponse = z.infer<typeof OAuthTokenResponseSchema>;
|
|
294
|
+
|
|
295
|
+
export const OAuthUserInfoSchema = z
|
|
296
|
+
.object({
|
|
297
|
+
sub: z.string(),
|
|
298
|
+
name: z.string().optional(),
|
|
299
|
+
given_name: z.string().optional(),
|
|
300
|
+
family_name: z.string().optional(),
|
|
301
|
+
email: z.string().optional(),
|
|
302
|
+
email_verified: z.boolean().optional(),
|
|
303
|
+
})
|
|
304
|
+
.catchall(z.unknown());
|
|
305
|
+
|
|
306
|
+
export type OAuthUserInfo = z.infer<typeof OAuthUserInfoSchema>;
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
type SandboxInfo,
|
|
6
6
|
type SandboxStatus,
|
|
7
7
|
type Execution,
|
|
8
|
+
type ExecutionStatus,
|
|
8
9
|
type FileToWrite,
|
|
9
10
|
type SandboxRunOptions,
|
|
10
11
|
type SandboxRunResult,
|
|
@@ -35,13 +36,25 @@ import { createMinimalLogger } from '../logger.ts';
|
|
|
35
36
|
import { getServiceUrls } from '../config.ts';
|
|
36
37
|
import { writeAndDrain } from './util.ts';
|
|
37
38
|
|
|
38
|
-
// Server-side long-poll wait duration (max 5 minutes supported by server)
|
|
39
|
+
// Server-side long-poll wait duration per iteration (max 5 minutes supported by server)
|
|
39
40
|
const EXECUTION_WAIT_DURATION = '5m';
|
|
40
41
|
|
|
42
|
+
/** Terminal execution statuses that indicate the command has finished. */
|
|
43
|
+
const TERMINAL_STATUSES: Set<ExecutionStatus> = new Set([
|
|
44
|
+
'completed',
|
|
45
|
+
'failed',
|
|
46
|
+
'timeout',
|
|
47
|
+
'cancelled',
|
|
48
|
+
]);
|
|
49
|
+
|
|
41
50
|
/**
|
|
42
|
-
* Wait for execution completion using server-side long-polling.
|
|
43
|
-
*
|
|
44
|
-
*
|
|
51
|
+
* Wait for execution completion using server-side long-polling with automatic retry.
|
|
52
|
+
*
|
|
53
|
+
* Each iteration asks the server to hold the connection for up to
|
|
54
|
+
* EXECUTION_WAIT_DURATION. If the execution is still running when the
|
|
55
|
+
* server-side wait expires, we loop and issue another long-poll request.
|
|
56
|
+
* This continues until the execution reaches a terminal state or the
|
|
57
|
+
* caller's AbortSignal fires.
|
|
45
58
|
*/
|
|
46
59
|
async function waitForExecution(
|
|
47
60
|
client: APIClient,
|
|
@@ -49,17 +62,30 @@ async function waitForExecution(
|
|
|
49
62
|
orgId?: string,
|
|
50
63
|
signal?: AbortSignal
|
|
51
64
|
): Promise<ExecutionInfo> {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
while (true) {
|
|
66
|
+
if (signal?.aborted) {
|
|
67
|
+
throw new DOMException('The operation was aborted.', 'AbortError');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Use server-side long-polling - the server will hold the connection
|
|
71
|
+
// until the execution reaches a terminal state or the wait duration expires.
|
|
72
|
+
// The signal is forwarded so the in-flight fetch is cancelled immediately
|
|
73
|
+
// when the caller aborts, rather than waiting the full poll duration.
|
|
74
|
+
const result = await executionGet(client, {
|
|
75
|
+
executionId,
|
|
76
|
+
orgId,
|
|
77
|
+
wait: EXECUTION_WAIT_DURATION,
|
|
78
|
+
signal,
|
|
79
|
+
});
|
|
55
80
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
81
|
+
// If the execution reached a terminal state, return immediately
|
|
82
|
+
if (TERMINAL_STATUSES.has(result.status as ExecutionStatus)) {
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Non-terminal status (e.g., 'running', 'queued') — the server-side
|
|
87
|
+
// long-poll expired before the command finished. Loop to poll again.
|
|
88
|
+
}
|
|
63
89
|
}
|
|
64
90
|
|
|
65
91
|
/**
|
|
@@ -133,6 +133,10 @@ export const SandboxCreateDataSchema = z
|
|
|
133
133
|
'failed',
|
|
134
134
|
])
|
|
135
135
|
.describe('Current status of the sandbox'),
|
|
136
|
+
url: z
|
|
137
|
+
.string()
|
|
138
|
+
.optional()
|
|
139
|
+
.describe('Public URL for the sandbox (only set when a network port is configured)'),
|
|
136
140
|
stdoutStreamId: z.string().optional().describe('Stream ID for reading stdout'),
|
|
137
141
|
stdoutStreamUrl: z.string().optional().describe('URL for streaming stdout output'),
|
|
138
142
|
stderrStreamId: z.string().optional().describe('Stream ID for reading stderr'),
|
|
@@ -44,6 +44,8 @@ export const ExecutionGetParamsSchema = z.object({
|
|
|
44
44
|
orgId: z.string().optional().describe('organization id'),
|
|
45
45
|
/** Optional wait duration for long-polling. */
|
|
46
46
|
wait: z.string().optional().describe('wait duration for long-polling'),
|
|
47
|
+
/** Optional AbortSignal to cancel the in-flight request. */
|
|
48
|
+
signal: z.custom<AbortSignal>().optional().describe('abort signal for cancellation'),
|
|
47
49
|
});
|
|
48
50
|
export type ExecutionGetParams = z.infer<typeof ExecutionGetParamsSchema>;
|
|
49
51
|
|
|
@@ -67,7 +69,7 @@ export async function executionGet(
|
|
|
67
69
|
client: APIClient,
|
|
68
70
|
params: ExecutionGetParams
|
|
69
71
|
): Promise<ExecutionInfo> {
|
|
70
|
-
const { executionId, orgId, wait } = params;
|
|
72
|
+
const { executionId, orgId, wait, signal } = params;
|
|
71
73
|
const queryParams = new URLSearchParams();
|
|
72
74
|
if (orgId) {
|
|
73
75
|
queryParams.set('orgId', orgId);
|
|
@@ -80,7 +82,8 @@ export async function executionGet(
|
|
|
80
82
|
|
|
81
83
|
const resp = await client.get<z.infer<typeof ExecutionGetResponseSchema>>(
|
|
82
84
|
url,
|
|
83
|
-
ExecutionGetResponseSchema
|
|
85
|
+
ExecutionGetResponseSchema,
|
|
86
|
+
signal
|
|
84
87
|
);
|
|
85
88
|
|
|
86
89
|
if (resp.success) {
|
|
@@ -124,7 +124,7 @@ export async function sandboxReadFile(
|
|
|
124
124
|
if (!response.ok) {
|
|
125
125
|
const text = await response.text().catch(() => 'Unknown error');
|
|
126
126
|
throw new SandboxResponseError({
|
|
127
|
-
message: `Failed to read file: ${response.status} ${text}`,
|
|
127
|
+
message: `Failed to read file "${path}": ${response.status} ${text}`,
|
|
128
128
|
sandboxId,
|
|
129
129
|
sessionId,
|
|
130
130
|
});
|
|
@@ -78,6 +78,24 @@ export {
|
|
|
78
78
|
executionGet,
|
|
79
79
|
executionList,
|
|
80
80
|
} from './execution.ts';
|
|
81
|
+
export type {
|
|
82
|
+
JobCreateParams,
|
|
83
|
+
JobGetParams,
|
|
84
|
+
JobListParams,
|
|
85
|
+
JobListResponse,
|
|
86
|
+
JobStopParams,
|
|
87
|
+
} from './job.ts';
|
|
88
|
+
export {
|
|
89
|
+
JobCreateParamsSchema,
|
|
90
|
+
JobGetParamsSchema,
|
|
91
|
+
JobListParamsSchema,
|
|
92
|
+
JobListResponseSchema,
|
|
93
|
+
JobStopParamsSchema,
|
|
94
|
+
jobCreate,
|
|
95
|
+
jobGet,
|
|
96
|
+
jobList,
|
|
97
|
+
jobStop,
|
|
98
|
+
} from './job.ts';
|
|
81
99
|
export type {
|
|
82
100
|
SandboxEventInfo,
|
|
83
101
|
SandboxEventListParams,
|