@cloudflare/sandbox 0.13.0-next.769.1 → 1.0.0-rc.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.
Files changed (63) hide show
  1. package/README.md +62 -219
  2. package/dist/index.d.mts +548 -0
  3. package/dist/index.mjs +2452 -0
  4. package/package.json +17 -118
  5. package/Dockerfile +0 -327
  6. package/dist/bridge/index.d.ts +0 -181
  7. package/dist/bridge/index.d.ts.map +0 -1
  8. package/dist/bridge/index.js +0 -3053
  9. package/dist/bridge/index.js.map +0 -1
  10. package/dist/contexts-1EsLHByO.d.ts +0 -463
  11. package/dist/contexts-1EsLHByO.d.ts.map +0 -1
  12. package/dist/dist-Duor5GbS.js +0 -752
  13. package/dist/dist-Duor5GbS.js.map +0 -1
  14. package/dist/errors/index.d.ts +0 -4
  15. package/dist/errors/index.js +0 -4
  16. package/dist/errors-CXR0xBpw.js +0 -285
  17. package/dist/errors-CXR0xBpw.js.map +0 -1
  18. package/dist/errors-QYlSkVGz.js +0 -893
  19. package/dist/errors-QYlSkVGz.js.map +0 -1
  20. package/dist/extensions/index.d.ts +0 -4
  21. package/dist/extensions/index.js +0 -6
  22. package/dist/extensions-CFB2xHqY.js +0 -1023
  23. package/dist/extensions-CFB2xHqY.js.map +0 -1
  24. package/dist/filesystem-BWAZCZER.d.ts +0 -732
  25. package/dist/filesystem-BWAZCZER.d.ts.map +0 -1
  26. package/dist/git/index.d.ts +0 -63
  27. package/dist/git/index.d.ts.map +0 -1
  28. package/dist/git/index.js +0 -338
  29. package/dist/git/index.js.map +0 -1
  30. package/dist/index-Bs4bqXDR.d.ts +0 -438
  31. package/dist/index-Bs4bqXDR.d.ts.map +0 -1
  32. package/dist/index-HNYBk-az.d.ts +0 -444
  33. package/dist/index-HNYBk-az.d.ts.map +0 -1
  34. package/dist/index.d.ts +0 -576
  35. package/dist/index.d.ts.map +0 -1
  36. package/dist/index.js +0 -33
  37. package/dist/index.js.map +0 -1
  38. package/dist/interpreter/index.d.ts +0 -311
  39. package/dist/interpreter/index.d.ts.map +0 -1
  40. package/dist/interpreter/index.js +0 -292
  41. package/dist/interpreter/index.js.map +0 -1
  42. package/dist/openai/index.d.ts +0 -68
  43. package/dist/openai/index.d.ts.map +0 -1
  44. package/dist/openai/index.js +0 -367
  45. package/dist/openai/index.js.map +0 -1
  46. package/dist/opencode/index.d.ts +0 -182
  47. package/dist/opencode/index.d.ts.map +0 -1
  48. package/dist/opencode/index.js +0 -454
  49. package/dist/opencode/index.js.map +0 -1
  50. package/dist/process-types-GStiZ8f8.d.ts +0 -73
  51. package/dist/process-types-GStiZ8f8.d.ts.map +0 -1
  52. package/dist/sandbox-BbAabq93.d.ts +0 -42
  53. package/dist/sandbox-BbAabq93.d.ts.map +0 -1
  54. package/dist/sandbox-cmlgGVYX.js +0 -10056
  55. package/dist/sandbox-cmlgGVYX.js.map +0 -1
  56. package/dist/sidecar/index.d.ts +0 -77
  57. package/dist/sidecar/index.d.ts.map +0 -1
  58. package/dist/sidecar/index.js +0 -201
  59. package/dist/sidecar/index.js.map +0 -1
  60. package/dist/xterm/index.d.ts +0 -93
  61. package/dist/xterm/index.d.ts.map +0 -1
  62. package/dist/xterm/index.js +0 -220
  63. package/dist/xterm/index.js.map +0 -1
@@ -1,752 +0,0 @@
1
- //#region ../shared/dist/env.js
2
- /**
3
- * Safely extract a string value from an environment object
4
- *
5
- * @param env - Environment object with dynamic keys
6
- * @param key - The environment variable key to access
7
- * @returns The string value if present and is a string, undefined otherwise
8
- */
9
- function getEnvString(env, key) {
10
- const value = env?.[key];
11
- return typeof value === "string" ? value : void 0;
12
- }
13
- /**
14
- * Partition environment variables into values to set and keys to unset.
15
- *
16
- * - String values → toSet (will be exported)
17
- * - undefined/null → toUnset (will be unset)
18
- *
19
- * This enables idiomatic JS patterns where undefined means "remove":
20
- * ```typescript
21
- * await sandbox.setEnvVars({
22
- * API_KEY: 'new-key', // will be set
23
- * OLD_VAR: undefined, // will be unset
24
- * });
25
- * ```
26
- */
27
- function partitionEnvVars(envVars) {
28
- const toSet = {};
29
- const toUnset = [];
30
- for (const [key, value] of Object.entries(envVars)) if (value != null && typeof value === "string") toSet[key] = value;
31
- else toUnset.push(key);
32
- return {
33
- toSet,
34
- toUnset
35
- };
36
- }
37
-
38
- //#endregion
39
- //#region ../shared/dist/logger/sanitize.js
40
- /**
41
- * Log-only sanitization helpers
42
- *
43
- * These functions redact sensitive values for logging output.
44
- * They MUST NOT be used to mutate command strings before execution.
45
- */
46
- /**
47
- * Sensitive query parameter names to redact from URLs.
48
- * Anchored to query string context ([?&]) to avoid matching path segments.
49
- * Value matching stops at & and common URL/command delimiters.
50
- */
51
- const SENSITIVE_PARAMS = /([?&])(X-Amz-Credential|X-Amz-Signature|X-Amz-Security-Token|token|secret|password)=[^&\s"'`<>]*/gi;
52
- /**
53
- * Redact credentials from URLs for secure logging
54
- *
55
- * Replaces any credentials (username:password, tokens, etc.) embedded
56
- * in URLs with ****** to prevent sensitive data exposure in logs.
57
- * Works with URLs embedded in text.
58
- *
59
- * @param text - String that may contain URLs with credentials
60
- * @returns String with credentials redacted from any URLs
61
- */
62
- function redactCredentials(text) {
63
- let result = text;
64
- let pos = 0;
65
- while (pos < result.length) {
66
- const httpPos = result.indexOf("http://", pos);
67
- const httpsPos = result.indexOf("https://", pos);
68
- let protocolPos = -1;
69
- let protocolLen = 0;
70
- if (httpPos === -1 && httpsPos === -1) break;
71
- if (httpPos !== -1 && (httpsPos === -1 || httpPos < httpsPos)) {
72
- protocolPos = httpPos;
73
- protocolLen = 7;
74
- } else {
75
- protocolPos = httpsPos;
76
- protocolLen = 8;
77
- }
78
- const searchStart = protocolPos + protocolLen;
79
- const atPos = result.indexOf("@", searchStart);
80
- let urlEnd = searchStart;
81
- while (urlEnd < result.length) {
82
- const char = result[urlEnd];
83
- if (/[\s"'`<>,;{}[\]]/.test(char)) break;
84
- urlEnd++;
85
- }
86
- if (atPos !== -1 && atPos < urlEnd) {
87
- result = `${result.substring(0, searchStart)}******${result.substring(atPos)}`;
88
- pos = searchStart + 6;
89
- } else pos = protocolPos + protocolLen;
90
- }
91
- return result;
92
- }
93
- /**
94
- * Redact sensitive query parameters from URLs
95
- *
96
- * Strips X-Amz-Credential, X-Amz-Signature, X-Amz-Security-Token,
97
- * token, secret, and password query params from URLs. Returns
98
- * non-URL strings unchanged.
99
- *
100
- * @param input - String that may contain URLs with sensitive params
101
- * @returns String with sensitive params replaced by REDACTED
102
- */
103
- function redactSensitiveParams(input) {
104
- if (!input.includes("?") || !input.includes("=")) return input;
105
- return input.replace(SENSITIVE_PARAMS, "$1$2=REDACTED");
106
- }
107
- /**
108
- * Redact sensitive data from a command string for logging
109
- *
110
- * Composes redactCredentials (URL credentials) and redactSensitiveParams
111
- * (presigned URL query params). For log values only — never mutate
112
- * command strings before execution.
113
- *
114
- * @param command - Command string to sanitize for logging
115
- * @returns Sanitized command string
116
- */
117
- function redactCommand(command) {
118
- return redactSensitiveParams(redactCredentials(command));
119
- }
120
- /**
121
- * Truncate a string for log output with a truncation indicator
122
- *
123
- * @param value - String to potentially truncate
124
- * @param maxLen - Maximum length before truncation (default 120)
125
- * @returns Object with truncated value and boolean flag
126
- */
127
- function truncateForLog(value, maxLen = 120) {
128
- if (value.length <= maxLen) return {
129
- value,
130
- truncated: false
131
- };
132
- const cutoff = Math.max(0, maxLen - 3);
133
- return {
134
- value: `${value.substring(0, cutoff)}...`,
135
- truncated: true
136
- };
137
- }
138
-
139
- //#endregion
140
- //#region ../shared/dist/git.js
141
- /**
142
- * Fallback repository name used when URL parsing fails
143
- */
144
- const FALLBACK_REPO_NAME = "repository";
145
- /** Default wall-clock timeout in milliseconds for git clone operations. */
146
- const DEFAULT_GIT_CLONE_TIMEOUT_MS = 6e5;
147
- /**
148
- * Extract repository name from a Git URL
149
- *
150
- * Supports multiple URL formats:
151
- * - HTTPS: https://github.com/user/repo.git → repo
152
- * - HTTPS without .git: https://github.com/user/repo → repo
153
- * - SSH: git@github.com:user/repo.git → repo
154
- * - GitLab/others: https://gitlab.com/org/project.git → project
155
- *
156
- * @param repoUrl - Git repository URL (HTTPS or SSH format)
157
- * @returns Repository name extracted from URL, or 'repository' as fallback
158
- */
159
- function extractRepoName(repoUrl) {
160
- try {
161
- const pathParts = new URL(repoUrl).pathname.split("/");
162
- const lastPart = pathParts[pathParts.length - 1];
163
- if (lastPart) return lastPart.replace(/\.git$/, "");
164
- } catch {}
165
- if (repoUrl.includes(":") || repoUrl.includes("/")) {
166
- const segments = repoUrl.split(/[:/]/).filter(Boolean);
167
- const lastSegment = segments[segments.length - 1];
168
- if (lastSegment) return lastSegment.replace(/\.git$/, "");
169
- }
170
- return FALLBACK_REPO_NAME;
171
- }
172
-
173
- //#endregion
174
- //#region ../shared/dist/logger/canonical.js
175
- /** Events that are low-value at info on success */
176
- const DEBUG_ON_SUCCESS = new Set([
177
- "file.read",
178
- "file.write",
179
- "file.delete",
180
- "file.mkdir"
181
- ]);
182
- function resolveLogLevel(payload, options) {
183
- if (payload.outcome === "error") return "error";
184
- if (options?.successLevel) return options.successLevel;
185
- if (payload.origin === "internal") return "debug";
186
- if (DEBUG_ON_SUCCESS.has(payload.event)) return "debug";
187
- return "info";
188
- }
189
- /**
190
- * Sanitize an Error object by redacting sensitive data from message and stack.
191
- * Produces a copy so the caller's original Error is not mutated.
192
- */
193
- function sanitizeError(error) {
194
- if (!error) return void 0;
195
- const sanitized = new Error(redactCommand(error.message));
196
- sanitized.name = error.name;
197
- sanitized.stack = error.stack ? redactCommand(error.stack) : void 0;
198
- return sanitized;
199
- }
200
- /**
201
- * Sanitize and prepare payload fields for both message building and context emission.
202
- * Called once by logCanonicalEvent to avoid double-redaction.
203
- */
204
- function sanitizePayload(payload) {
205
- if (payload.command === void 0) return { commandTruncated: false };
206
- const { value, truncated } = truncateForLog(redactCommand(payload.command));
207
- return {
208
- sanitizedCommand: value,
209
- commandTruncated: truncated
210
- };
211
- }
212
- /**
213
- * Build a human-readable canonical event message for dashboards and log viewers.
214
- *
215
- * Format: `{event} {outcome} {key_context} [— {reason}] ({durationMs}ms[, {sizeBytes}B])`
216
- *
217
- * The if/else chain for key context has implicit priority: command > path >
218
- * port > repoUrl > pid. If a payload has multiple, only the highest-priority
219
- * one appears in the message. All fields are still present as discrete
220
- * queryable keys in the structured log context.
221
- */
222
- function buildMessage(payload, sanitizedCommand) {
223
- const { event } = payload;
224
- if (event === "version.check") {
225
- const parts$1 = ["version.check"];
226
- if (payload.sdkVersion) parts$1.push(`sdk=${payload.sdkVersion}`);
227
- if (payload.containerVersion) parts$1.push(`container=${payload.containerVersion}`);
228
- if (payload.versionOutcome && payload.versionOutcome !== "compatible") parts$1.push(`(${payload.versionOutcome})`);
229
- return parts$1.join(" ");
230
- }
231
- const parts = [event, payload.outcome];
232
- if (sanitizedCommand !== void 0) parts.push(sanitizedCommand);
233
- else if (payload.command !== void 0) {
234
- const { value } = truncateForLog(redactCommand(payload.command));
235
- parts.push(value);
236
- } else if (payload.path !== void 0) parts.push(payload.path);
237
- else if (payload.port !== void 0) parts.push(String(payload.port));
238
- else if (payload.repoUrl !== void 0) {
239
- let gitContext = payload.repoUrl;
240
- if (payload.branch !== void 0) gitContext += ` ${payload.branch}`;
241
- parts.push(gitContext);
242
- } else if (payload.pid !== void 0) parts.push(String(payload.pid));
243
- else if (payload.backupId !== void 0) parts.push(payload.backupId);
244
- else if (payload.repoPath !== void 0) {
245
- let gitContext = payload.repoPath;
246
- if (payload.branch !== void 0) gitContext += ` branch=${payload.branch}`;
247
- parts.push(gitContext);
248
- } else if (payload.mountsProcessed !== void 0) {
249
- let destroyContext = `${payload.mountsProcessed} mounts`;
250
- if (payload.mountFailures) destroyContext += `, ${payload.mountFailures} failed`;
251
- parts.push(destroyContext);
252
- } else if (payload.mountPath !== void 0) parts.push(payload.mountPath);
253
- if (payload.outcome === "error") {
254
- if (payload.errorMessage !== void 0) parts.push(`\u2014 ${payload.errorMessage}`);
255
- else if (payload.exitCode !== void 0) parts.push(`\u2014 exitCode=${payload.exitCode}`);
256
- }
257
- const durationSuffix = payload.sizeBytes !== void 0 ? `(${payload.durationMs}ms, ${payload.sizeBytes}B)` : `(${payload.durationMs}ms)`;
258
- parts.push(durationSuffix);
259
- return parts.join(" ");
260
- }
261
- /**
262
- * Log a canonical event — the single entry point for all structured operational events.
263
- *
264
- * Sanitizes command fields once, builds the message, selects log level from
265
- * outcome, and emits a structured log entry with the full payload as context.
266
- */
267
- function logCanonicalEvent(logger, payload, options) {
268
- const resolvedErrorMessage = payload.errorMessage ?? payload.error?.message;
269
- const sanitizedErrorMessage = resolvedErrorMessage ? redactCommand(resolvedErrorMessage) : void 0;
270
- const enrichedPayload = sanitizedErrorMessage !== void 0 ? {
271
- ...payload,
272
- errorMessage: sanitizedErrorMessage
273
- } : payload;
274
- const { sanitizedCommand, commandTruncated } = sanitizePayload(enrichedPayload);
275
- const message = buildMessage(enrichedPayload, sanitizedCommand);
276
- const context = {};
277
- for (const [key, value] of Object.entries(enrichedPayload)) {
278
- if (key === "error") continue;
279
- context[key] = value;
280
- }
281
- if (sanitizedCommand !== void 0) {
282
- context.command = sanitizedCommand;
283
- if (commandTruncated) context.commandTruncated = true;
284
- }
285
- const level = resolveLogLevel(enrichedPayload, options);
286
- if (level === "error") logger.error(message, sanitizeError(payload.error), context);
287
- else if (level === "warn") logger.warn(message, context);
288
- else if (level === "debug") logger.debug(message, context);
289
- else logger.info(message, context);
290
- }
291
-
292
- //#endregion
293
- //#region ../shared/dist/logger/types.js
294
- /**
295
- * Logger types for Cloudflare Sandbox SDK
296
- *
297
- * Provides structured, trace-aware logging across Worker, Durable Object, and Container.
298
- */
299
- /**
300
- * Log levels (from most to least verbose)
301
- */
302
- var LogLevel;
303
- (function(LogLevel$1) {
304
- LogLevel$1[LogLevel$1["DEBUG"] = 0] = "DEBUG";
305
- LogLevel$1[LogLevel$1["INFO"] = 1] = "INFO";
306
- LogLevel$1[LogLevel$1["WARN"] = 2] = "WARN";
307
- LogLevel$1[LogLevel$1["ERROR"] = 3] = "ERROR";
308
- })(LogLevel || (LogLevel = {}));
309
-
310
- //#endregion
311
- //#region ../shared/dist/logger/logger.js
312
- /**
313
- * Logger implementation
314
- */
315
- /**
316
- * ANSI color codes for terminal output
317
- */
318
- const COLORS = {
319
- reset: "\x1B[0m",
320
- debug: "\x1B[36m",
321
- info: "\x1B[32m",
322
- warn: "\x1B[33m",
323
- error: "\x1B[31m",
324
- dim: "\x1B[2m"
325
- };
326
- /**
327
- * CloudflareLogger implements structured logging with support for
328
- * both JSON output (production) and pretty printing (development).
329
- */
330
- var CloudflareLogger = class CloudflareLogger {
331
- baseContext;
332
- minLevel;
333
- outputMode;
334
- /**
335
- * Create a new CloudflareLogger
336
- *
337
- * @param baseContext Base context included in all log entries
338
- * @param minLevel Minimum log level to output (default: INFO)
339
- * @param outputMode How log entries are formatted and emitted (default: 'structured')
340
- */
341
- constructor(baseContext, minLevel = LogLevel.INFO, outputMode = "structured") {
342
- this.baseContext = baseContext;
343
- this.minLevel = minLevel;
344
- this.outputMode = outputMode;
345
- }
346
- /**
347
- * Log debug-level message
348
- */
349
- debug(message, context) {
350
- if (this.shouldLog(LogLevel.DEBUG)) {
351
- const logData = this.buildLogData("debug", message, context);
352
- this.output(console.log, logData);
353
- }
354
- }
355
- /**
356
- * Log info-level message
357
- */
358
- info(message, context) {
359
- if (this.shouldLog(LogLevel.INFO)) {
360
- const logData = this.buildLogData("info", message, context);
361
- this.output(console.log, logData);
362
- }
363
- }
364
- /**
365
- * Log warning-level message
366
- */
367
- warn(message, context) {
368
- if (this.shouldLog(LogLevel.WARN)) {
369
- const logData = this.buildLogData("warn", message, context);
370
- this.output(console.warn, logData);
371
- }
372
- }
373
- /**
374
- * Log error-level message
375
- */
376
- error(message, error, context) {
377
- if (this.shouldLog(LogLevel.ERROR)) {
378
- const logData = this.buildLogData("error", message, context, error);
379
- this.output(console.error, logData);
380
- }
381
- }
382
- /**
383
- * Create a child logger with additional context
384
- */
385
- child(context) {
386
- return new CloudflareLogger({
387
- ...this.baseContext,
388
- ...context
389
- }, this.minLevel, this.outputMode);
390
- }
391
- /**
392
- * Check if a log level should be output
393
- */
394
- shouldLog(level) {
395
- return level >= this.minLevel;
396
- }
397
- /**
398
- * Build log data object
399
- */
400
- buildLogData(level, message, context, error) {
401
- const logData = {
402
- level,
403
- message,
404
- ...this.baseContext,
405
- ...context,
406
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
407
- };
408
- if (error) logData.error = {
409
- message: error.message,
410
- stack: error.stack,
411
- name: error.name
412
- };
413
- return logData;
414
- }
415
- /**
416
- * Output log data using the configured output mode
417
- */
418
- output(consoleFn, data) {
419
- switch (this.outputMode) {
420
- case "pretty":
421
- this.outputPretty(consoleFn, data);
422
- break;
423
- case "json-line":
424
- this.outputJsonLine(consoleFn, data);
425
- break;
426
- case "structured":
427
- this.outputStructured(consoleFn, data);
428
- break;
429
- }
430
- }
431
- /**
432
- * Output as JSON string (container stdout — parsed by Containers pipeline)
433
- */
434
- outputJsonLine(consoleFn, data) {
435
- consoleFn(JSON.stringify(data));
436
- }
437
- /**
438
- * Output as raw object (Workers/DOs — Workers Logs auto-indexes fields)
439
- */
440
- outputStructured(consoleFn, data) {
441
- consoleFn(data);
442
- }
443
- /**
444
- * Output as pretty-printed, colored text (development)
445
- *
446
- * Each log event is a single consoleFn() call so it appears as one entry
447
- * in the Cloudflare dashboard. Context is rendered inline as compact key=value pairs.
448
- *
449
- * Format: LEVEL [component] message trace=tr_... key=value key=value
450
- */
451
- outputPretty(consoleFn, data) {
452
- const { level, message: msg, timestamp, traceId, component, sandboxId, processId, commandId, durationMs, serviceVersion, instanceId, error, ...rest } = data;
453
- const levelStr = String(level || "INFO").toUpperCase();
454
- const levelColor = this.getLevelColor(levelStr);
455
- const componentBadge = component ? `[${component}]` : "";
456
- let logLine = `${timestamp ? `${COLORS.dim}${new Date(timestamp).toISOString().substring(11, 23)}${COLORS.reset} ` : ""}${levelColor}${levelStr.padEnd(5)}${COLORS.reset} ${componentBadge} ${msg}`;
457
- const pairs = [];
458
- if (traceId) pairs.push(`trace=${String(traceId).substring(0, 12)}`);
459
- if (commandId) pairs.push(`cmd=${String(commandId).substring(0, 12)}`);
460
- if (sandboxId) pairs.push(`sandbox=${sandboxId}`);
461
- if (processId) pairs.push(`proc=${processId}`);
462
- if (durationMs !== void 0) pairs.push(`dur=${durationMs}ms`);
463
- for (const [key, value] of Object.entries(rest)) {
464
- if (value === void 0 || value === null) continue;
465
- const v = typeof value === "object" ? JSON.stringify(value) : this.sanitizePrettyValue(String(value));
466
- pairs.push(`${key}=${v}`);
467
- }
468
- if (error && typeof error === "object") {
469
- const errorObj = error;
470
- if (errorObj.name) pairs.push(`err.name=${this.sanitizePrettyValue(errorObj.name)}`);
471
- if (errorObj.message) pairs.push(`err.msg=${this.sanitizePrettyValue(errorObj.message)}`);
472
- if (errorObj.stack) pairs.push(`err.stack=${this.sanitizePrettyValue(errorObj.stack)}`);
473
- }
474
- if (pairs.length > 0) logLine += ` ${COLORS.dim}${pairs.join(" ")}${COLORS.reset}`;
475
- consoleFn(logLine);
476
- }
477
- /**
478
- * Collapse newlines so a single consoleFn() call stays on one line.
479
- * Cloudflare's log pipeline splits on literal newlines, which fragments
480
- * stack traces and multi-line error messages into separate entries.
481
- */
482
- sanitizePrettyValue(value) {
483
- return value.replace(/\r/g, "\\r").replace(/\n/g, "\\n");
484
- }
485
- /**
486
- * Get ANSI color code for log level
487
- */
488
- getLevelColor(level) {
489
- switch (level.toLowerCase()) {
490
- case "debug": return COLORS.debug;
491
- case "info": return COLORS.info;
492
- case "warn": return COLORS.warn;
493
- case "error": return COLORS.error;
494
- default: return COLORS.reset;
495
- }
496
- }
497
- };
498
-
499
- //#endregion
500
- //#region ../shared/dist/logger/trace-context.js
501
- /**
502
- * Trace context utilities for request correlation
503
- *
504
- * Trace IDs enable correlating logs across distributed components:
505
- * Worker → Durable Object → Container → back
506
- *
507
- * The trace ID is propagated via the X-Trace-Id HTTP header.
508
- */
509
- /**
510
- * Utility for managing trace context across distributed components
511
- */
512
- var TraceContext = class TraceContext {
513
- /**
514
- * HTTP header name for trace ID propagation
515
- */
516
- static TRACE_HEADER = "X-Trace-Id";
517
- /**
518
- * Generate a new trace ID
519
- *
520
- * Format: "tr_" + 16 random hex characters
521
- * Example: "tr_7f3a9b2c4e5d6f1a"
522
- *
523
- * @returns Newly generated trace ID
524
- */
525
- static generate() {
526
- return `tr_${crypto.randomUUID().replace(/-/g, "").substring(0, 16)}`;
527
- }
528
- /**
529
- * Extract trace ID from HTTP request headers
530
- *
531
- * @param headers Request headers
532
- * @returns Trace ID if present, null otherwise
533
- */
534
- static fromHeaders(headers) {
535
- return headers.get(TraceContext.TRACE_HEADER);
536
- }
537
- /**
538
- * Create headers object with trace ID for outgoing requests
539
- *
540
- * @param traceId Trace ID to include
541
- * @returns Headers object with X-Trace-Id set
542
- */
543
- static toHeaders(traceId) {
544
- return { [TraceContext.TRACE_HEADER]: traceId };
545
- }
546
- /**
547
- * Get the header name used for trace ID propagation
548
- *
549
- * @returns Header name ("X-Trace-Id")
550
- */
551
- static getHeaderName() {
552
- return TraceContext.TRACE_HEADER;
553
- }
554
- };
555
-
556
- //#endregion
557
- //#region ../shared/dist/logger/index.js
558
- /**
559
- * Logger module
560
- *
561
- * Provides structured, trace-aware logging with:
562
- * - Explicit logger passing via constructor injection
563
- * - Three output modes: structured (Workers/DOs), json-line (container), pretty (local dev)
564
- * - Environment auto-detection
565
- * - Log level configuration
566
- *
567
- * Usage:
568
- *
569
- * ```typescript
570
- * // Create a logger at entry point
571
- * const logger = createLogger({ component: 'sandbox-do', traceId: 'tr_abc123' });
572
- *
573
- * // Pass to classes via constructor
574
- * const service = new MyService(logger);
575
- *
576
- * // Create child loggers for additional context
577
- * const execLogger = logger.child({ commandId: 'cmd-456' });
578
- * execLogger.info('Operation started');
579
- * ```
580
- */
581
- /**
582
- * Create a no-op logger for testing
583
- *
584
- * Returns a logger that implements the Logger interface but does nothing.
585
- * Useful for tests that don't need actual logging output.
586
- *
587
- * @returns No-op logger instance
588
- *
589
- * @example
590
- * ```typescript
591
- * // In tests
592
- * const client = new HttpClient({
593
- * baseUrl: 'http://test.com',
594
- * logger: createNoOpLogger() // Optional - tests can enable real logging if needed
595
- * });
596
- * ```
597
- */
598
- function createNoOpLogger() {
599
- return {
600
- debug: () => {},
601
- info: () => {},
602
- warn: () => {},
603
- error: () => {},
604
- child: () => createNoOpLogger()
605
- };
606
- }
607
- /**
608
- * Create a new logger instance
609
- *
610
- * @param context Base context for the logger. Must include 'component'.
611
- * TraceId will be auto-generated if not provided.
612
- * @returns New logger instance
613
- *
614
- * @example
615
- * ```typescript
616
- * // In Durable Object
617
- * const logger = createLogger({
618
- * component: 'sandbox-do',
619
- * traceId: TraceContext.fromHeaders(request.headers) || TraceContext.generate(),
620
- * sandboxId: this.id
621
- * });
622
- *
623
- * // In Container
624
- * const logger = createLogger({
625
- * component: 'container',
626
- * traceId: TraceContext.fromHeaders(request.headers)!,
627
- * sandboxId: this.id
628
- * });
629
- * ```
630
- */
631
- function createLogger(context) {
632
- const minLevel = getLogLevelFromEnv();
633
- const outputMode = getOutputMode(context.component);
634
- return new CloudflareLogger({
635
- ...context,
636
- traceId: context.traceId || TraceContext.generate(),
637
- component: context.component,
638
- serviceVersion: context.serviceVersion || getEnvVar("SANDBOX_VERSION") || void 0,
639
- instanceId: context.instanceId || getEnvVar("HOSTNAME") || getEnvVar("SANDBOX_INSTANCE_ID") || void 0
640
- }, minLevel, outputMode);
641
- }
642
- /**
643
- * Get log level from environment variable
644
- *
645
- * Checks SANDBOX_LOG_LEVEL env var, falls back to default based on environment.
646
- * Default: 'debug' for development, 'info' for production
647
- */
648
- function getLogLevelFromEnv() {
649
- switch ((getEnvVar("SANDBOX_LOG_LEVEL") || "info").toLowerCase()) {
650
- case "debug": return LogLevel.DEBUG;
651
- case "info": return LogLevel.INFO;
652
- case "warn": return LogLevel.WARN;
653
- case "error": return LogLevel.ERROR;
654
- default: return LogLevel.INFO;
655
- }
656
- }
657
- /**
658
- * Determine output mode based on component and environment:
659
- * - SANDBOX_LOG_FORMAT=pretty → 'pretty' for all components (local wrangler dev)
660
- * - Container/Executor without pretty → 'json-line' (Bun stdout → Containers pipeline)
661
- * - Everything else without pretty → 'structured' (Workers/DOs → Workers Logs)
662
- *
663
- * In local dev, setting SANDBOX_LOG_FORMAT=pretty gives readable terminal
664
- * output on both the DO side and container side. In production (where the
665
- * var isn't set), DOs emit structured objects and containers emit single-line
666
- * JSON — both queryable by their respective observability pipelines.
667
- */
668
- function getOutputMode(component) {
669
- if (getEnvVar("SANDBOX_LOG_FORMAT")?.toLowerCase() === "pretty") return "pretty";
670
- if (component === "container" || component === "executor") return "json-line";
671
- return "structured";
672
- }
673
- /**
674
- * Get environment variable value
675
- *
676
- * Supports both Node.js (process.env) and Bun (Bun.env)
677
- */
678
- function getEnvVar(name) {
679
- if (typeof process !== "undefined" && process.env) return process.env[name];
680
- if (typeof Bun !== "undefined") {
681
- const bunEnv = Bun.env;
682
- if (bunEnv) return bunEnv[name];
683
- }
684
- }
685
-
686
- //#endregion
687
- //#region ../shared/dist/rpc-types.js
688
- /**
689
- * Shared interface types for the container-control path.
690
- *
691
- * Defines the contract between the SDK control client and the container
692
- * control-plane API. The current wire implementation uses capnweb RPC.
693
- */
694
- /**
695
- * Error name thrown by the host's `connect` when it has not yet provisioned
696
- * the requested hash and the request did not carry tarball bytes. The SDK
697
- * recognises this name via `Error.name` and retries the connect with the
698
- * bytes attached. Kept as a string constant so it survives capnweb
699
- * cross-realm error reconstruction.
700
- */
701
- const EXTENSION_TARBALL_REQUIRED = "ExtensionTarballRequired";
702
-
703
- //#endregion
704
- //#region ../shared/dist/sse.js
705
- /**
706
- * Shared SSE parsing utilities.
707
- *
708
- * Parses SSE frames from arbitrary text chunks while preserving partial state
709
- * across chunk boundaries.
710
- */
711
- /**
712
- * Parse SSE frames from a buffer.
713
- *
714
- * Returns parsed events, remaining unparsed text, and the current partial event
715
- * so callers can continue parsing on the next chunk.
716
- */
717
- function parseSSEFrames(buffer, currentEvent = { data: [] }) {
718
- const events = [];
719
- let i = 0;
720
- while (i < buffer.length) {
721
- const newlineIndex = buffer.indexOf("\n", i);
722
- if (newlineIndex === -1) break;
723
- const rawLine = buffer.substring(i, newlineIndex);
724
- const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
725
- i = newlineIndex + 1;
726
- if (line === "" && currentEvent.data.length > 0) {
727
- events.push({
728
- event: currentEvent.event,
729
- data: currentEvent.data.join("\n")
730
- });
731
- currentEvent = { data: [] };
732
- continue;
733
- }
734
- if (line.startsWith("event:")) {
735
- currentEvent.event = line.startsWith("event: ") ? line.substring(7) : line.substring(6);
736
- continue;
737
- }
738
- if (line.startsWith("data:")) {
739
- const value = line.startsWith("data: ") ? line.substring(6) : line.substring(5);
740
- currentEvent.data.push(value);
741
- }
742
- }
743
- return {
744
- events,
745
- remaining: buffer.substring(i),
746
- currentEvent
747
- };
748
- }
749
-
750
- //#endregion
751
- export { TraceContext as a, extractRepoName as c, partitionEnvVars as d, createNoOpLogger as i, redactCommand as l, EXTENSION_TARBALL_REQUIRED as n, logCanonicalEvent as o, createLogger as r, DEFAULT_GIT_CLONE_TIMEOUT_MS as s, parseSSEFrames as t, getEnvString as u };
752
- //# sourceMappingURL=dist-Duor5GbS.js.map