@vectorlingo/cli 0.1.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/dist/oauth.js ADDED
@@ -0,0 +1,369 @@
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ import { createServer } from 'node:http';
3
+ import { platform } from 'node:os';
4
+ import { spawn } from 'node:child_process';
5
+ import { AgentError } from './contracts.js';
6
+ import { validateLoopbackRedirect, validateServiceUrl } from './http.js';
7
+ export class OAuthClient {
8
+ issuer;
9
+ resource;
10
+ configuredClientId;
11
+ scopes;
12
+ fetch;
13
+ browser;
14
+ callbackTimeoutMs;
15
+ constructor(options) {
16
+ this.issuer = validateServiceUrl(options.issuer, 'OAuth issuer');
17
+ this.resource = validateServiceUrl(options.resource, 'OAuth resource');
18
+ this.configuredClientId = options.clientId;
19
+ this.scopes = [...new Set(options.scopes)].sort();
20
+ this.fetch = options.fetch ?? globalThis.fetch;
21
+ this.browser = options.openBrowser ?? openSystemBrowser;
22
+ this.callbackTimeoutMs = options.callbackTimeoutMs ?? 180_000;
23
+ if (this.scopes.length === 0 || this.scopes.some((scope) => !scope || /\s/.test(scope))) {
24
+ throw new AgentError('invalid_configuration', 'At least one valid OAuth scope is required');
25
+ }
26
+ }
27
+ async discover() {
28
+ const metadataUrl = authorizationServerMetadataUrl(this.issuer);
29
+ const response = await this.fetch(metadataUrl, {
30
+ headers: { accept: 'application/json' },
31
+ redirect: 'manual',
32
+ });
33
+ if (!response.ok) {
34
+ throw new AgentError('oauth_discovery_failed', `OAuth discovery failed with HTTP ${response.status}`);
35
+ }
36
+ const value = (await response.json());
37
+ if (typeof value.issuer !== 'string' ||
38
+ normaliseIssuer(value.issuer) !== normaliseIssuer(this.issuer.href) ||
39
+ typeof value.authorization_endpoint !== 'string' ||
40
+ typeof value.token_endpoint !== 'string') {
41
+ throw new AgentError('oauth_discovery_failed', 'OAuth metadata is incomplete or has the wrong issuer');
42
+ }
43
+ const metadata = {
44
+ issuer: value.issuer,
45
+ authorization_endpoint: secureEndpoint(value.authorization_endpoint, 'OAuth authorisation endpoint'),
46
+ token_endpoint: secureEndpoint(value.token_endpoint, 'OAuth token endpoint'),
47
+ ...(typeof value.registration_endpoint === 'string'
48
+ ? { registration_endpoint: secureEndpoint(value.registration_endpoint, 'OAuth registration endpoint') }
49
+ : {}),
50
+ ...(typeof value.revocation_endpoint === 'string'
51
+ ? { revocation_endpoint: secureEndpoint(value.revocation_endpoint, 'OAuth revocation endpoint') }
52
+ : {}),
53
+ ...(Array.isArray(value.code_challenge_methods_supported)
54
+ ? { code_challenge_methods_supported: value.code_challenge_methods_supported }
55
+ : {}),
56
+ };
57
+ if (metadata.code_challenge_methods_supported &&
58
+ !metadata.code_challenge_methods_supported.includes('S256')) {
59
+ throw new AgentError('oauth_pkce_unsupported', 'OAuth server does not advertise PKCE S256');
60
+ }
61
+ return metadata;
62
+ }
63
+ async login(baseUrl) {
64
+ const metadata = await this.discover();
65
+ const callback = await startLoopbackCallback(this.callbackTimeoutMs);
66
+ try {
67
+ const redirectUri = validateLoopbackRedirect(callback.redirectUri).href;
68
+ const clientId = this.configuredClientId ?? (await this.registerClient(metadata, redirectUri));
69
+ const state = randomUrlSafe(32);
70
+ const verifier = randomUrlSafe(64);
71
+ const challenge = createHash('sha256').update(verifier).digest('base64url');
72
+ const authorization = new URL(metadata.authorization_endpoint);
73
+ authorization.search = new URLSearchParams({
74
+ response_type: 'code',
75
+ client_id: clientId,
76
+ redirect_uri: redirectUri,
77
+ code_challenge: challenge,
78
+ code_challenge_method: 'S256',
79
+ state,
80
+ scope: this.scopes.join(' '),
81
+ resource: this.resource.href,
82
+ }).toString();
83
+ await this.browser(authorization);
84
+ const code = await callback.waitForCode(state);
85
+ const tokens = await this.exchangeCode(metadata, clientId, redirectUri, code, verifier);
86
+ return {
87
+ baseUrl: validateServiceUrl(baseUrl, 'VectorLingo base URL').href,
88
+ issuer: this.issuer.href,
89
+ resource: this.resource.href,
90
+ clientId,
91
+ tokens,
92
+ };
93
+ }
94
+ finally {
95
+ await callback.close();
96
+ }
97
+ }
98
+ async refresh(profile) {
99
+ const refreshToken = profile.tokens.refreshToken;
100
+ if (!refreshToken) {
101
+ throw new AgentError('reauthentication_required', 'The OAuth session cannot be refreshed');
102
+ }
103
+ const metadata = await this.discover();
104
+ const body = new URLSearchParams({
105
+ grant_type: 'refresh_token',
106
+ refresh_token: refreshToken,
107
+ client_id: profile.clientId,
108
+ resource: profile.resource,
109
+ });
110
+ const response = await this.fetch(metadata.token_endpoint, {
111
+ method: 'POST',
112
+ headers: {
113
+ accept: 'application/json',
114
+ 'content-type': 'application/x-www-form-urlencoded',
115
+ },
116
+ body,
117
+ redirect: 'manual',
118
+ });
119
+ return parseTokenResponse(response, refreshToken);
120
+ }
121
+ /**
122
+ * Revoke the refresh token only. The access token is a short-lived JWT: the broker answers
123
+ * `unsupported_token_type` for it, which made logout fail until the token expired.
124
+ */
125
+ async revoke(profile) {
126
+ const refreshToken = profile.tokens.refreshToken;
127
+ if (!refreshToken)
128
+ return;
129
+ const metadata = await this.discover();
130
+ if (!metadata.revocation_endpoint) {
131
+ throw new AgentError('oauth_revocation_unsupported', 'OAuth server does not advertise revocation');
132
+ }
133
+ const response = await this.fetch(metadata.revocation_endpoint, {
134
+ method: 'POST',
135
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
136
+ body: new URLSearchParams({
137
+ token: refreshToken,
138
+ token_type_hint: 'refresh_token',
139
+ client_id: profile.clientId,
140
+ }),
141
+ redirect: 'manual',
142
+ });
143
+ if (!response.ok) {
144
+ throw new AgentError('oauth_revocation_failed', `OAuth revocation failed with HTTP ${response.status}; local credentials were kept. ` +
145
+ 'Retry, or run vectorlingo logout --local to remove them without revoking.');
146
+ }
147
+ }
148
+ async registerClient(metadata, redirectUri) {
149
+ if (!metadata.registration_endpoint) {
150
+ throw new AgentError('oauth_client_required', 'OAuth client ID is required because dynamic registration is unavailable');
151
+ }
152
+ const response = await this.fetch(metadata.registration_endpoint, {
153
+ method: 'POST',
154
+ headers: { accept: 'application/json', 'content-type': 'application/json' },
155
+ // RFC 7591 + RFC 8707. `native` is required: Better Auth defaults DCR clients to `web`,
156
+ // which rejects http loopback redirects. `resources` must match a server resource
157
+ // exactly; without it the client is linked only to the server's default (MCP) resource.
158
+ body: JSON.stringify({
159
+ client_name: 'VectorLingo CLI',
160
+ application_type: 'native',
161
+ redirect_uris: [redirectUri],
162
+ grant_types: ['authorization_code', 'refresh_token'],
163
+ response_types: ['code'],
164
+ token_endpoint_auth_method: 'none',
165
+ scope: this.scopes.join(' '),
166
+ resources: [this.resource.href],
167
+ }),
168
+ redirect: 'manual',
169
+ });
170
+ if (!response.ok) {
171
+ const error = (await response.json().catch(() => ({})));
172
+ const code = typeof error.error === 'string' ? error.error : undefined;
173
+ throw new AgentError('oauth_registration_failed', `OAuth registration failed with HTTP ${response.status}${code ? ` (${code})` : ''}`, {
174
+ httpStatus: response.status,
175
+ details: {
176
+ ...(code ? { error: code } : {}),
177
+ ...(typeof error.error_description === 'string' ? { error_description: error.error_description } : {}),
178
+ },
179
+ });
180
+ }
181
+ const value = (await response.json());
182
+ if (typeof value.client_id !== 'string' || typeof value.client_secret === 'string') {
183
+ throw new AgentError('oauth_registration_failed', 'OAuth registration did not return a public client');
184
+ }
185
+ return value.client_id;
186
+ }
187
+ async exchangeCode(metadata, clientId, redirectUri, code, verifier) {
188
+ const response = await this.fetch(metadata.token_endpoint, {
189
+ method: 'POST',
190
+ headers: {
191
+ accept: 'application/json',
192
+ 'content-type': 'application/x-www-form-urlencoded',
193
+ },
194
+ body: new URLSearchParams({
195
+ grant_type: 'authorization_code',
196
+ code,
197
+ redirect_uri: redirectUri,
198
+ code_verifier: verifier,
199
+ client_id: clientId,
200
+ resource: this.resource.href,
201
+ }),
202
+ redirect: 'manual',
203
+ });
204
+ return parseTokenResponse(response);
205
+ }
206
+ }
207
+ export function createStoredTokenProvider(store, oauth) {
208
+ return async (options) => {
209
+ const snapshot = await store.load();
210
+ if (!snapshot)
211
+ throw new AgentError('authentication_required', 'Run vectorlingo login first');
212
+ const observedToken = snapshot.tokens.accessToken;
213
+ const mustRefresh = options?.forceRefresh === true || snapshot.tokens.expiresAt <= Date.now() + 30_000;
214
+ if (!mustRefresh)
215
+ return observedToken;
216
+ let accessToken;
217
+ await store.update(async (current) => {
218
+ if (!current)
219
+ throw new AgentError('authentication_required', 'Run vectorlingo login first');
220
+ if (current.tokens.accessToken !== observedToken &&
221
+ current.tokens.expiresAt > Date.now() + 30_000) {
222
+ accessToken = current.tokens.accessToken;
223
+ return current;
224
+ }
225
+ const tokens = await oauth.refresh(current);
226
+ accessToken = tokens.accessToken;
227
+ return { ...current, tokens };
228
+ });
229
+ if (!accessToken)
230
+ throw new AgentError('reauthentication_required', 'OAuth refresh failed');
231
+ return accessToken;
232
+ };
233
+ }
234
+ async function parseTokenResponse(response, previousRefreshToken) {
235
+ const value = (await response.json().catch(() => ({})));
236
+ if (!response.ok) {
237
+ throw new AgentError(response.status === 400 || response.status === 401
238
+ ? 'reauthentication_required'
239
+ : 'oauth_token_failed', `OAuth token request failed with HTTP ${response.status}` +
240
+ (typeof value.error === 'string' ? ` (${value.error})` : ''));
241
+ }
242
+ if (typeof value.access_token !== 'string' ||
243
+ typeof value.token_type !== 'string' ||
244
+ value.token_type.toLowerCase() !== 'bearer' ||
245
+ (value.expires_in !== undefined && typeof value.expires_in !== 'number') ||
246
+ (value.refresh_token !== undefined && typeof value.refresh_token !== 'string')) {
247
+ throw new AgentError('oauth_token_failed', 'OAuth server returned an invalid token response');
248
+ }
249
+ const expiresIn = value.expires_in ?? 300;
250
+ if (!Number.isFinite(expiresIn) || expiresIn <= 0) {
251
+ throw new AgentError('oauth_token_failed', 'OAuth server returned an invalid token lifetime');
252
+ }
253
+ return {
254
+ accessToken: value.access_token,
255
+ tokenType: 'Bearer',
256
+ expiresAt: Date.now() + expiresIn * 1_000,
257
+ ...(typeof value.refresh_token === 'string'
258
+ ? { refreshToken: value.refresh_token }
259
+ : previousRefreshToken
260
+ ? { refreshToken: previousRefreshToken }
261
+ : {}),
262
+ ...(typeof value.scope === 'string' ? { scope: value.scope } : {}),
263
+ };
264
+ }
265
+ async function startLoopbackCallback(timeoutMs) {
266
+ let resolver;
267
+ const result = new Promise((resolve) => {
268
+ resolver = resolve;
269
+ });
270
+ let settled = false;
271
+ const server = createServer((request, response) => {
272
+ const url = new URL(request.url ?? '/', 'http://127.0.0.1');
273
+ if (request.method !== 'GET' || url.pathname !== '/oauth/callback' || settled) {
274
+ response.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' }).end('Not found');
275
+ return;
276
+ }
277
+ settled = true;
278
+ const code = url.searchParams.get('code');
279
+ const state = url.searchParams.get('state');
280
+ const error = url.searchParams.get('error');
281
+ resolver?.({
282
+ ...(code === null ? {} : { code }),
283
+ ...(state === null ? {} : { state }),
284
+ ...(error === null ? {} : { error }),
285
+ });
286
+ response
287
+ .writeHead(200, {
288
+ 'content-type': 'text/plain; charset=utf-8',
289
+ 'cache-control': 'no-store',
290
+ 'x-content-type-options': 'nosniff',
291
+ })
292
+ .end('VectorLingo sign-in complete. You may close this window.');
293
+ });
294
+ await listenLoopback(server);
295
+ const address = server.address();
296
+ if (!address || typeof address === 'string') {
297
+ await closeServer(server);
298
+ throw new AgentError('oauth_callback_failed', 'Could not start the OAuth callback server');
299
+ }
300
+ const redirectUri = `http://127.0.0.1:${address.port}/oauth/callback`;
301
+ return {
302
+ redirectUri,
303
+ async waitForCode(expectedState) {
304
+ let timeout;
305
+ const callback = await Promise.race([
306
+ result,
307
+ new Promise((_, reject) => {
308
+ timeout = setTimeout(() => reject(new AgentError('oauth_callback_timeout', 'OAuth sign-in timed out')), timeoutMs);
309
+ timeout.unref();
310
+ }),
311
+ ]).finally(() => {
312
+ if (timeout)
313
+ clearTimeout(timeout);
314
+ });
315
+ if (callback.state !== expectedState) {
316
+ throw new AgentError('oauth_state_mismatch', 'OAuth callback state did not match');
317
+ }
318
+ if (callback.error)
319
+ throw new AgentError('oauth_authorisation_denied', 'OAuth authorisation was denied');
320
+ if (!callback.code)
321
+ throw new AgentError('oauth_callback_failed', 'OAuth callback did not include a code');
322
+ return callback.code;
323
+ },
324
+ close: () => closeServer(server),
325
+ };
326
+ }
327
+ function listenLoopback(server) {
328
+ return new Promise((resolve, reject) => {
329
+ server.once('error', reject);
330
+ server.listen(0, '127.0.0.1', () => {
331
+ server.off('error', reject);
332
+ resolve();
333
+ });
334
+ });
335
+ }
336
+ function closeServer(server) {
337
+ return new Promise((resolve, reject) => {
338
+ server.close((error) => (error ? reject(error) : resolve()));
339
+ // A real browser keeps keep-alive and preconnected sockets open; close() alone waits for them
340
+ // (about two minutes with Chrome) before login can finish.
341
+ server.closeAllConnections();
342
+ });
343
+ }
344
+ function authorizationServerMetadataUrl(issuer) {
345
+ const path = issuer.pathname === '/' ? '' : issuer.pathname.replace(/\/$/, '');
346
+ return new URL(`/.well-known/oauth-authorization-server${path}`, issuer.origin);
347
+ }
348
+ function secureEndpoint(value, label) {
349
+ return validateServiceUrl(value, label).href;
350
+ }
351
+ function normaliseIssuer(value) {
352
+ return value.replace(/\/$/, '');
353
+ }
354
+ function randomUrlSafe(bytes) {
355
+ return randomBytes(bytes).toString('base64url');
356
+ }
357
+ export function openSystemBrowser(url) {
358
+ const command = platform() === 'darwin' ? 'open' : platform() === 'win32' ? 'cmd' : 'xdg-open';
359
+ const args = platform() === 'win32' ? ['/c', 'start', '', url.href] : [url.href];
360
+ return new Promise((resolve, reject) => {
361
+ const child = spawn(command, args, { detached: true, stdio: 'ignore' });
362
+ child.once('error', reject);
363
+ child.once('spawn', () => {
364
+ child.unref();
365
+ resolve();
366
+ });
367
+ });
368
+ }
369
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { type DownloadDescriptor, type FileDescriptor } from './contracts.js';
2
+ import type { AgentAccessClient } from './client.js';
3
+ export interface UploadFileOptions {
4
+ tenantId: string;
5
+ path: string;
6
+ mimeType: string;
7
+ attachmentKind: string;
8
+ initRequestId: string;
9
+ completeRequestId: string;
10
+ maxFileBytes?: number;
11
+ fetch?: typeof globalThis.fetch;
12
+ }
13
+ export interface DownloadFileOptions {
14
+ tenantId: string;
15
+ artifactId: string;
16
+ destination: string;
17
+ maxFileBytes?: number;
18
+ fetch?: typeof globalThis.fetch;
19
+ }
20
+ export declare function uploadFile(client: AgentAccessClient, options: UploadFileOptions): Promise<FileDescriptor>;
21
+ export declare function downloadArtifact(client: AgentAccessClient, options: DownloadFileOptions): Promise<{
22
+ path: string;
23
+ descriptor: DownloadDescriptor;
24
+ }>;
25
+ export declare function validateDownloadDestination(rawPath: string): string;
26
+ //# sourceMappingURL=safe-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-files.d.ts","sourceRoot":"","sources":["../src/safe-files.ts"],"names":[],"mappings":"AAIA,OAAO,EAAc,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAA2D,MAAM,gBAAgB,CAAA;AAClJ,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAGpD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;CAChC;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,cAAc,CAAC,CAgDzB;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,kBAAkB,CAAA;CAAE,CAAC,CAoB3D;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CASnE"}
@@ -0,0 +1,203 @@
1
+ import { constants, createReadStream } from 'node:fs';
2
+ import { link, lstat, mkdir, open, rm } from 'node:fs/promises';
3
+ import { basename, dirname, isAbsolute, parse, resolve, sep } from 'node:path';
4
+ import { createHash, randomBytes } from 'node:crypto';
5
+ import { AgentError } from './contracts.js';
6
+ import { validateServiceUrl } from './http.js';
7
+ export async function uploadFile(client, options) {
8
+ const maxBytes = options.maxFileBytes ?? 100 * 1024 * 1024;
9
+ const handle = await openNoFollow(options.path);
10
+ try {
11
+ const info = await handle.stat();
12
+ if (!info.isFile())
13
+ throw new AgentError('unsafe_local_path', 'Upload source must be a regular file');
14
+ if (info.size > maxBytes) {
15
+ throw new AgentError('file_too_large', 'Upload source exceeds the client file-size limit', {
16
+ details: { max_bytes: maxBytes },
17
+ });
18
+ }
19
+ const sha256 = await digestFile(handle.fd, maxBytes);
20
+ const initial = await client.execute({
21
+ tenant_id: options.tenantId,
22
+ operation: 'files.init_upload',
23
+ request_id: options.initRequestId,
24
+ input: {
25
+ file_name: basename(options.path),
26
+ mime_type: options.mimeType,
27
+ size: info.size,
28
+ sha256,
29
+ attachment_kind: options.attachmentKind,
30
+ },
31
+ });
32
+ if (initial.status !== 'completed' || !initial.result) {
33
+ throw new AgentError('upload_initialisation_failed', 'Upload initialisation did not complete', {
34
+ ...(initial.operation_id === undefined ? {} : { operationId: initial.operation_id }),
35
+ });
36
+ }
37
+ if ('completed_file' in initial.result)
38
+ return initial.result.completed_file;
39
+ if (initial.result.transfer_required !== false) {
40
+ await putUpload(initial.result, handle.fd, info.size, options.fetch ?? globalThis.fetch);
41
+ }
42
+ const completed = await client.execute({
43
+ tenant_id: options.tenantId,
44
+ operation: 'files.complete_upload',
45
+ request_id: options.completeRequestId,
46
+ input: { upload_id: initial.result.upload_id, sha256 },
47
+ });
48
+ if (completed.status !== 'completed' || !completed.result) {
49
+ throw new AgentError('upload_completion_failed', 'Upload completion did not complete', {
50
+ ...(completed.operation_id === undefined ? {} : { operationId: completed.operation_id }),
51
+ });
52
+ }
53
+ return completed.result;
54
+ }
55
+ finally {
56
+ await handle.close();
57
+ }
58
+ }
59
+ export async function downloadArtifact(client, options) {
60
+ const response = await client.execute({
61
+ tenant_id: options.tenantId,
62
+ operation: 'files.download',
63
+ input: { artifact_id: options.artifactId },
64
+ });
65
+ if (response.status !== 'completed' || !response.result) {
66
+ throw new AgentError('download_initialisation_failed', 'Download initialisation did not complete', {
67
+ ...(response.operation_id === undefined ? {} : { operationId: response.operation_id }),
68
+ });
69
+ }
70
+ const destination = validateDownloadDestination(options.destination);
71
+ const maxBytes = options.maxFileBytes ?? 100 * 1024 * 1024;
72
+ await streamDownload(response.result, destination, maxBytes, options.fetch ?? globalThis.fetch);
73
+ return { path: destination, descriptor: response.result };
74
+ }
75
+ export function validateDownloadDestination(rawPath) {
76
+ if (!rawPath || rawPath.includes('\0')) {
77
+ throw new AgentError('unsafe_local_path', 'Download destination is invalid');
78
+ }
79
+ const components = rawPath.replaceAll('\\', '/').split('/');
80
+ if (components.includes('..')) {
81
+ throw new AgentError('unsafe_local_path', 'Download destination must not contain path traversal');
82
+ }
83
+ return isAbsolute(rawPath) ? resolve(rawPath) : resolve(process.cwd(), rawPath);
84
+ }
85
+ async function putUpload(instruction, sourceFd, size, fetcher) {
86
+ const url = validateServiceUrl(instruction.upload_url, 'Signed upload URL');
87
+ let response;
88
+ try {
89
+ response = await fetcher(url, {
90
+ method: instruction.method,
91
+ headers: {
92
+ ...instruction.headers,
93
+ 'content-length': String(size),
94
+ },
95
+ body: createReadStream('', { fd: sourceFd, autoClose: false, start: 0 }),
96
+ duplex: 'half',
97
+ redirect: 'manual',
98
+ });
99
+ }
100
+ catch (cause) {
101
+ throw new AgentError('upload_transfer_failed', 'Upload transfer outcome is unknown; retry with the same request IDs', { cause });
102
+ }
103
+ // Storage rejects a second PUT to an existing object with 409. The bytes may be ours from a
104
+ // lost response, so completion (which re-verifies size and SHA-256 server-side) decides.
105
+ if (response.status === 409)
106
+ return;
107
+ if (!response.ok) {
108
+ throw new AgentError('upload_transfer_failed', `Upload transfer failed with HTTP ${response.status}`);
109
+ }
110
+ }
111
+ async function streamDownload(descriptor, destination, maxBytes, fetcher) {
112
+ const url = validateServiceUrl(descriptor.download_url, 'Signed download URL');
113
+ const parent = dirname(destination);
114
+ await mkdir(parent, { recursive: true });
115
+ await assertNoSymlinkAncestors(parent);
116
+ try {
117
+ await lstat(destination);
118
+ throw new AgentError('destination_exists', 'Download destination already exists');
119
+ }
120
+ catch (error) {
121
+ if (error.code !== 'ENOENT')
122
+ throw error;
123
+ }
124
+ const response = await fetcher(url, { method: 'GET', redirect: 'manual' });
125
+ if (!response.ok || !response.body) {
126
+ throw new AgentError('download_transfer_failed', `Download transfer failed with HTTP ${response.status}`);
127
+ }
128
+ const length = Number(response.headers.get('content-length'));
129
+ if (Number.isFinite(length) && length > maxBytes) {
130
+ throw new AgentError('file_too_large', 'Download exceeds the client file-size limit');
131
+ }
132
+ const temporary = `${destination}.${process.pid}.${randomBytes(8).toString('hex')}.download`;
133
+ const file = await open(temporary, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY, 0o600);
134
+ const digest = createHash('sha256');
135
+ let size = 0;
136
+ try {
137
+ try {
138
+ for await (const rawChunk of response.body) {
139
+ const chunk = Buffer.from(rawChunk);
140
+ size += chunk.length;
141
+ if (size > maxBytes)
142
+ throw new AgentError('file_too_large', 'Download exceeds the client file-size limit');
143
+ digest.update(chunk);
144
+ await file.write(chunk);
145
+ }
146
+ await file.sync();
147
+ }
148
+ finally {
149
+ await file.close();
150
+ }
151
+ if (size !== descriptor.size || digest.digest('hex') !== descriptor.sha256.toLowerCase()) {
152
+ throw new AgentError('download_integrity_failed', 'Downloaded file did not match its metadata');
153
+ }
154
+ await link(temporary, destination);
155
+ }
156
+ catch (error) {
157
+ if (error.code === 'EEXIST') {
158
+ throw new AgentError('destination_exists', 'Download destination already exists');
159
+ }
160
+ throw error;
161
+ }
162
+ finally {
163
+ await rm(temporary, { force: true });
164
+ }
165
+ }
166
+ async function openNoFollow(path) {
167
+ try {
168
+ const info = await lstat(path);
169
+ if (info.isSymbolicLink())
170
+ throw new AgentError('unsafe_local_path', 'Upload source must not be a symlink');
171
+ return await open(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
172
+ }
173
+ catch (error) {
174
+ if (error instanceof AgentError)
175
+ throw error;
176
+ throw new AgentError('unsafe_local_path', 'Upload source could not be opened safely', { cause: error });
177
+ }
178
+ }
179
+ async function digestFile(fd, maxBytes) {
180
+ const digest = createHash('sha256');
181
+ let size = 0;
182
+ for await (const rawChunk of createReadStream('', { fd, autoClose: false, start: 0 })) {
183
+ const chunk = Buffer.from(rawChunk);
184
+ size += chunk.length;
185
+ if (size > maxBytes)
186
+ throw new AgentError('file_too_large', 'Upload source exceeds the client file-size limit');
187
+ digest.update(chunk);
188
+ }
189
+ return digest.digest('hex');
190
+ }
191
+ async function assertNoSymlinkAncestors(directory) {
192
+ const root = parse(directory).root;
193
+ const relative = directory.slice(root.length);
194
+ let current = root;
195
+ for (const component of relative.split(sep).filter(Boolean)) {
196
+ current = resolve(current, component);
197
+ const info = await lstat(current);
198
+ if (!info.isDirectory() || info.isSymbolicLink()) {
199
+ throw new AgentError('unsafe_local_path', 'Download destination has an unsafe parent directory');
200
+ }
201
+ }
202
+ }
203
+ //# sourceMappingURL=safe-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-files.js","sourceRoot":"","sources":["../src/safe-files.ts"],"names":[],"mappings":"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"}