@tracecode/harness 0.4.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 (55) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/LICENSE +674 -0
  3. package/README.md +266 -0
  4. package/dist/browser.cjs +1352 -0
  5. package/dist/browser.cjs.map +1 -0
  6. package/dist/browser.d.cts +49 -0
  7. package/dist/browser.d.ts +49 -0
  8. package/dist/browser.js +1317 -0
  9. package/dist/browser.js.map +1 -0
  10. package/dist/cli.cjs +70 -0
  11. package/dist/cli.cjs.map +1 -0
  12. package/dist/cli.d.cts +1 -0
  13. package/dist/cli.d.ts +1 -0
  14. package/dist/cli.js +70 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/core.cjs +286 -0
  17. package/dist/core.cjs.map +1 -0
  18. package/dist/core.d.cts +69 -0
  19. package/dist/core.d.ts +69 -0
  20. package/dist/core.js +254 -0
  21. package/dist/core.js.map +1 -0
  22. package/dist/index.cjs +2603 -0
  23. package/dist/index.cjs.map +1 -0
  24. package/dist/index.d.cts +6 -0
  25. package/dist/index.d.ts +6 -0
  26. package/dist/index.js +2538 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/internal/browser.cjs +647 -0
  29. package/dist/internal/browser.cjs.map +1 -0
  30. package/dist/internal/browser.d.cts +143 -0
  31. package/dist/internal/browser.d.ts +143 -0
  32. package/dist/internal/browser.js +617 -0
  33. package/dist/internal/browser.js.map +1 -0
  34. package/dist/javascript.cjs +549 -0
  35. package/dist/javascript.cjs.map +1 -0
  36. package/dist/javascript.d.cts +11 -0
  37. package/dist/javascript.d.ts +11 -0
  38. package/dist/javascript.js +518 -0
  39. package/dist/javascript.js.map +1 -0
  40. package/dist/python.cjs +744 -0
  41. package/dist/python.cjs.map +1 -0
  42. package/dist/python.d.cts +97 -0
  43. package/dist/python.d.ts +97 -0
  44. package/dist/python.js +698 -0
  45. package/dist/python.js.map +1 -0
  46. package/dist/runtime-types-C7d1LFbx.d.ts +85 -0
  47. package/dist/runtime-types-Dvgn07z9.d.cts +85 -0
  48. package/dist/types-Bzr1Ohcf.d.cts +96 -0
  49. package/dist/types-Bzr1Ohcf.d.ts +96 -0
  50. package/package.json +89 -0
  51. package/workers/javascript/javascript-worker.js +2918 -0
  52. package/workers/python/generated-python-harness-snippets.js +20 -0
  53. package/workers/python/pyodide-worker.js +1197 -0
  54. package/workers/python/runtime-core.js +1529 -0
  55. package/workers/vendor/typescript.js +200276 -0
@@ -0,0 +1,1352 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // packages/harness-browser/src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ DEFAULT_BROWSER_HARNESS_ASSET_RELATIVE_PATHS: () => DEFAULT_BROWSER_HARNESS_ASSET_RELATIVE_PATHS,
24
+ LANGUAGE_RUNTIME_PROFILES: () => LANGUAGE_RUNTIME_PROFILES,
25
+ SUPPORTED_LANGUAGES: () => SUPPORTED_LANGUAGES,
26
+ assertRuntimeRequestSupported: () => assertRuntimeRequestSupported,
27
+ createBrowserHarness: () => createBrowserHarness,
28
+ getLanguageRuntimeProfile: () => getLanguageRuntimeProfile,
29
+ getSupportedLanguageProfiles: () => getSupportedLanguageProfiles,
30
+ isLanguageSupported: () => isLanguageSupported,
31
+ resolveBrowserHarnessAssets: () => resolveBrowserHarnessAssets
32
+ });
33
+ module.exports = __toCommonJS(src_exports);
34
+
35
+ // packages/harness-browser/src/javascript-worker-client.ts
36
+ var EXECUTION_TIMEOUT_MS = 7e3;
37
+ var INTERVIEW_MODE_TIMEOUT_MS = 5e3;
38
+ var TRACING_TIMEOUT_MS = 7e3;
39
+ var INIT_TIMEOUT_MS = 1e4;
40
+ var MESSAGE_TIMEOUT_MS = 12e3;
41
+ var WORKER_READY_TIMEOUT_MS = 1e4;
42
+ var JavaScriptWorkerClient = class {
43
+ constructor(options) {
44
+ this.options = options;
45
+ this.debug = options.debug ?? process.env.NODE_ENV === "development";
46
+ }
47
+ worker = null;
48
+ pendingMessages = /* @__PURE__ */ new Map();
49
+ messageId = 0;
50
+ isInitializing = false;
51
+ initPromise = null;
52
+ workerReadyPromise = null;
53
+ workerReadyResolve = null;
54
+ workerReadyReject = null;
55
+ debug;
56
+ isSupported() {
57
+ return typeof Worker !== "undefined";
58
+ }
59
+ getWorker() {
60
+ if (this.worker) return this.worker;
61
+ if (!this.isSupported()) {
62
+ throw new Error("Web Workers are not supported in this environment");
63
+ }
64
+ this.workerReadyPromise = new Promise((resolve, reject) => {
65
+ this.workerReadyResolve = resolve;
66
+ this.workerReadyReject = (error) => reject(error);
67
+ });
68
+ const workerUrl = this.debug && !this.options.workerUrl.includes("?") ? `${this.options.workerUrl}?dev=${Date.now()}` : this.options.workerUrl;
69
+ this.worker = new Worker(workerUrl);
70
+ this.worker.onmessage = (event) => {
71
+ const { id, type, payload } = event.data;
72
+ if (type === "worker-ready") {
73
+ this.workerReadyResolve?.();
74
+ this.workerReadyResolve = null;
75
+ this.workerReadyReject = null;
76
+ if (this.debug) console.log("[JavaScriptWorkerClient] worker-ready");
77
+ return;
78
+ }
79
+ if (id) {
80
+ const pending = this.pendingMessages.get(id);
81
+ if (!pending) return;
82
+ this.pendingMessages.delete(id);
83
+ if (pending.timeoutId) globalThis.clearTimeout(pending.timeoutId);
84
+ if (type === "error") {
85
+ pending.reject(new Error(payload.error));
86
+ return;
87
+ }
88
+ pending.resolve(payload);
89
+ }
90
+ };
91
+ this.worker.onerror = (error) => {
92
+ console.error("[JavaScriptWorkerClient] Worker error:", error);
93
+ const workerError = new Error("Worker error");
94
+ this.workerReadyReject?.(workerError);
95
+ this.workerReadyResolve = null;
96
+ this.workerReadyReject = null;
97
+ for (const [id, pending] of this.pendingMessages) {
98
+ if (pending.timeoutId) globalThis.clearTimeout(pending.timeoutId);
99
+ pending.reject(workerError);
100
+ this.pendingMessages.delete(id);
101
+ }
102
+ };
103
+ return this.worker;
104
+ }
105
+ async waitForWorkerReady() {
106
+ const readyPromise = this.workerReadyPromise;
107
+ if (!readyPromise) return;
108
+ await new Promise((resolve, reject) => {
109
+ let settled = false;
110
+ const timeoutId = globalThis.setTimeout(() => {
111
+ if (settled) return;
112
+ settled = true;
113
+ const timeoutError = new Error(
114
+ `JavaScript worker failed to initialize in time (${Math.round(WORKER_READY_TIMEOUT_MS / 1e3)}s)`
115
+ );
116
+ this.terminateAndReset(timeoutError);
117
+ reject(timeoutError);
118
+ }, WORKER_READY_TIMEOUT_MS);
119
+ readyPromise.then(() => {
120
+ if (settled) return;
121
+ settled = true;
122
+ globalThis.clearTimeout(timeoutId);
123
+ resolve();
124
+ }).catch((error) => {
125
+ if (settled) return;
126
+ settled = true;
127
+ globalThis.clearTimeout(timeoutId);
128
+ reject(error instanceof Error ? error : new Error(String(error)));
129
+ });
130
+ });
131
+ }
132
+ async sendMessage(type, payload, timeoutMs = MESSAGE_TIMEOUT_MS) {
133
+ const worker = this.getWorker();
134
+ await this.waitForWorkerReady();
135
+ const id = String(++this.messageId);
136
+ return new Promise((resolve, reject) => {
137
+ this.pendingMessages.set(id, {
138
+ resolve,
139
+ reject
140
+ });
141
+ const timeoutId = globalThis.setTimeout(() => {
142
+ const pending2 = this.pendingMessages.get(id);
143
+ if (!pending2) return;
144
+ this.pendingMessages.delete(id);
145
+ pending2.reject(new Error(`Worker request timed out: ${type}`));
146
+ }, timeoutMs);
147
+ const pending = this.pendingMessages.get(id);
148
+ if (pending) pending.timeoutId = timeoutId;
149
+ worker.postMessage({ id, type, payload });
150
+ });
151
+ }
152
+ async executeWithTimeout(executor, timeoutMs) {
153
+ return new Promise((resolve, reject) => {
154
+ let settled = false;
155
+ const timeoutId = globalThis.setTimeout(() => {
156
+ if (settled) return;
157
+ settled = true;
158
+ this.terminateAndReset();
159
+ reject(
160
+ new Error(
161
+ `Execution timed out (possible infinite loop). Code execution was stopped after ${Math.round(timeoutMs / 1e3)} seconds.`
162
+ )
163
+ );
164
+ }, timeoutMs);
165
+ executor().then((result) => {
166
+ if (settled) return;
167
+ settled = true;
168
+ globalThis.clearTimeout(timeoutId);
169
+ resolve(result);
170
+ }).catch((error) => {
171
+ if (settled) return;
172
+ settled = true;
173
+ globalThis.clearTimeout(timeoutId);
174
+ reject(error);
175
+ });
176
+ });
177
+ }
178
+ terminateAndReset(reason = new Error("Worker was terminated")) {
179
+ this.workerReadyReject?.(reason);
180
+ if (this.worker) {
181
+ this.worker.terminate();
182
+ this.worker = null;
183
+ }
184
+ this.initPromise = null;
185
+ this.isInitializing = false;
186
+ this.workerReadyPromise = null;
187
+ this.workerReadyResolve = null;
188
+ this.workerReadyReject = null;
189
+ for (const [, pending] of this.pendingMessages) {
190
+ if (pending.timeoutId) globalThis.clearTimeout(pending.timeoutId);
191
+ pending.reject(reason);
192
+ }
193
+ this.pendingMessages.clear();
194
+ }
195
+ async init() {
196
+ if (this.initPromise) return this.initPromise;
197
+ if (this.isInitializing) {
198
+ await new Promise((resolve) => globalThis.setTimeout(resolve, 100));
199
+ return this.init();
200
+ }
201
+ this.isInitializing = true;
202
+ this.initPromise = this.sendMessage("init", void 0, INIT_TIMEOUT_MS);
203
+ try {
204
+ return await this.initPromise;
205
+ } catch (error) {
206
+ this.initPromise = null;
207
+ throw error;
208
+ } finally {
209
+ this.isInitializing = false;
210
+ }
211
+ }
212
+ async executeWithTracing(code, functionName, inputs, options, executionStyle = "function", language = "javascript") {
213
+ await this.init();
214
+ return this.executeWithTimeout(
215
+ () => this.sendMessage(
216
+ "execute-with-tracing",
217
+ {
218
+ code,
219
+ functionName,
220
+ inputs,
221
+ options,
222
+ executionStyle,
223
+ language
224
+ },
225
+ TRACING_TIMEOUT_MS + 2e3
226
+ ),
227
+ TRACING_TIMEOUT_MS
228
+ );
229
+ }
230
+ async executeCode(code, functionName, inputs, executionStyle = "function", language = "javascript") {
231
+ await this.init();
232
+ return this.executeWithTimeout(
233
+ () => this.sendMessage(
234
+ "execute-code",
235
+ {
236
+ code,
237
+ functionName,
238
+ inputs,
239
+ executionStyle,
240
+ language
241
+ },
242
+ EXECUTION_TIMEOUT_MS + 2e3
243
+ ),
244
+ EXECUTION_TIMEOUT_MS
245
+ );
246
+ }
247
+ async executeCodeInterviewMode(code, functionName, inputs, executionStyle = "function", language = "javascript") {
248
+ await this.init();
249
+ try {
250
+ const result = await this.executeWithTimeout(
251
+ () => this.sendMessage(
252
+ "execute-code-interview",
253
+ {
254
+ code,
255
+ functionName,
256
+ inputs,
257
+ executionStyle,
258
+ language
259
+ },
260
+ INTERVIEW_MODE_TIMEOUT_MS + 2e3
261
+ ),
262
+ INTERVIEW_MODE_TIMEOUT_MS
263
+ );
264
+ if (!result.success && result.error) {
265
+ const normalized = result.error.toLowerCase();
266
+ const isTimeoutOrResourceLimit = normalized.includes("timed out") || normalized.includes("infinite loop") || normalized.includes("line-limit") || normalized.includes("single-line-limit") || normalized.includes("recursion-limit") || normalized.includes("trace-limit") || normalized.includes("line events") || normalized.includes("trace steps") || normalized.includes("call depth");
267
+ if (isTimeoutOrResourceLimit) {
268
+ return {
269
+ success: false,
270
+ output: null,
271
+ error: "Time Limit Exceeded",
272
+ consoleOutput: result.consoleOutput ?? []
273
+ };
274
+ }
275
+ }
276
+ return result;
277
+ } catch {
278
+ return {
279
+ success: false,
280
+ output: null,
281
+ error: "Time Limit Exceeded",
282
+ consoleOutput: []
283
+ };
284
+ }
285
+ }
286
+ terminate() {
287
+ this.terminateAndReset();
288
+ }
289
+ };
290
+
291
+ // packages/harness-core/src/trace-contract.ts
292
+ var RUNTIME_TRACE_CONTRACT_SCHEMA_VERSION = "2026-03-07";
293
+ var TRACE_EVENTS = /* @__PURE__ */ new Set([
294
+ "line",
295
+ "call",
296
+ "return",
297
+ "exception",
298
+ "timeout",
299
+ "stdout"
300
+ ]);
301
+ var TRACE_ACCESS_KINDS = /* @__PURE__ */ new Set([
302
+ "indexed-read",
303
+ "indexed-write",
304
+ "cell-read",
305
+ "cell-write",
306
+ "mutating-call"
307
+ ]);
308
+ function normalizeLineNumber(value, fallback = 1) {
309
+ if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
310
+ const normalized = Math.floor(value);
311
+ return normalized > 0 ? normalized : fallback;
312
+ }
313
+ function normalizeOutputLineCount(value) {
314
+ if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
315
+ const normalized = Math.floor(value);
316
+ return normalized >= 0 ? normalized : void 0;
317
+ }
318
+ function normalizeEvent(value) {
319
+ if (typeof value === "string" && TRACE_EVENTS.has(value)) {
320
+ return value;
321
+ }
322
+ return "line";
323
+ }
324
+ function normalizeAccessKind(value) {
325
+ if (typeof value === "string" && TRACE_ACCESS_KINDS.has(value)) {
326
+ return value;
327
+ }
328
+ return null;
329
+ }
330
+ function normalizeFunctionName(value) {
331
+ if (typeof value === "string" && value.length > 0) return value;
332
+ return "<module>";
333
+ }
334
+ function normalizeKind(value) {
335
+ if (value === "map" || value === "set" || value === "hashmap") {
336
+ return value;
337
+ }
338
+ return "hashmap";
339
+ }
340
+ function normalizeObjectKind(value) {
341
+ if (value === "hashmap" || value === "map" || value === "set" || value === "tree" || value === "linked-list" || value === "graph-adjacency") {
342
+ return value;
343
+ }
344
+ return null;
345
+ }
346
+ function normalizeScalar(value) {
347
+ if (value === null || value === void 0) return value;
348
+ if (typeof value === "string" || typeof value === "boolean") return value;
349
+ if (typeof value === "number") return Number.isFinite(value) ? value : String(value);
350
+ if (typeof value === "bigint") {
351
+ const asNumber = Number(value);
352
+ return Number.isSafeInteger(asNumber) ? asNumber : String(value);
353
+ }
354
+ if (typeof value === "function") return "<function>";
355
+ return null;
356
+ }
357
+ function normalizeUnknown(value, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
358
+ if (depth > 48) return "<max depth>";
359
+ const scalar = normalizeScalar(value);
360
+ if (scalar !== null || value === null || value === void 0) {
361
+ return scalar;
362
+ }
363
+ if (Array.isArray(value)) {
364
+ return value.map((item) => {
365
+ if (item === void 0) return null;
366
+ return normalizeUnknown(item, depth + 1, seen);
367
+ });
368
+ }
369
+ if (typeof value === "object" && value) {
370
+ if (seen.has(value)) return "<cycle>";
371
+ seen.add(value);
372
+ const normalized = {};
373
+ for (const key of Object.keys(value).sort()) {
374
+ const child = value[key];
375
+ if (child === void 0) continue;
376
+ normalized[key] = normalizeUnknown(child, depth + 1, seen);
377
+ }
378
+ seen.delete(value);
379
+ return normalized;
380
+ }
381
+ return String(value);
382
+ }
383
+ function normalizeAccesses(accesses) {
384
+ if (!Array.isArray(accesses) || accesses.length === 0) {
385
+ return void 0;
386
+ }
387
+ const normalized = accesses.map((access) => {
388
+ const variable = typeof access?.variable === "string" && access.variable.length > 0 ? access.variable : "";
389
+ const kind = normalizeAccessKind(access?.kind);
390
+ if (!variable || !kind) {
391
+ return null;
392
+ }
393
+ const indices = Array.isArray(access?.indices) ? access.indices.map(
394
+ (index) => typeof index === "number" && Number.isFinite(index) ? Math.floor(index) : null
395
+ ).filter((index) => index !== null) : void 0;
396
+ const pathDepth = access?.pathDepth === 1 || access?.pathDepth === 2 ? access.pathDepth : void 0;
397
+ const method = typeof access?.method === "string" && access.method.length > 0 ? access.method : void 0;
398
+ const payload = {
399
+ variable,
400
+ kind
401
+ };
402
+ if (indices && indices.length > 0) {
403
+ payload.indices = indices;
404
+ }
405
+ if (pathDepth !== void 0) {
406
+ payload.pathDepth = pathDepth;
407
+ }
408
+ if (method) {
409
+ payload.method = method;
410
+ }
411
+ return payload;
412
+ }).filter((access) => access !== null);
413
+ return normalized.length > 0 ? normalized : void 0;
414
+ }
415
+ function normalizeRecord(value) {
416
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
417
+ return normalizeUnknown(value);
418
+ }
419
+ function normalizeCallStackFrame(frame) {
420
+ return {
421
+ function: normalizeFunctionName(frame?.function),
422
+ line: normalizeLineNumber(frame?.line, 1),
423
+ args: normalizeRecord(frame?.args)
424
+ };
425
+ }
426
+ function normalizeVisualizationPayload(payload) {
427
+ const hashMaps = Array.isArray(payload?.hashMaps) ? payload.hashMaps.map((entry) => ({
428
+ name: typeof entry?.name === "string" ? entry.name : "",
429
+ kind: normalizeKind(entry?.kind),
430
+ entries: Array.isArray(entry?.entries) ? entry.entries.map((item) => ({
431
+ key: normalizeUnknown(item?.key),
432
+ value: normalizeUnknown(item?.value),
433
+ ...item?.highlight ? { highlight: true } : {}
434
+ })) : [],
435
+ ...entry?.highlightedKey !== void 0 ? { highlightedKey: normalizeUnknown(entry.highlightedKey) } : {},
436
+ ...entry?.deletedKey !== void 0 ? { deletedKey: normalizeUnknown(entry.deletedKey) } : {}
437
+ })).sort((a, b) => `${a.name}:${a.kind}`.localeCompare(`${b.name}:${b.kind}`)) : [];
438
+ const objectKinds = payload?.objectKinds && typeof payload.objectKinds === "object" ? Object.fromEntries(
439
+ Object.entries(payload.objectKinds).filter(([name]) => typeof name === "string" && name.length > 0).map(([name, kind]) => [name, normalizeObjectKind(kind)]).filter((entry) => entry[1] !== null).sort((a, b) => a[0].localeCompare(b[0]))
440
+ ) : void 0;
441
+ if (hashMaps.length === 0 && (!objectKinds || Object.keys(objectKinds).length === 0)) {
442
+ return void 0;
443
+ }
444
+ return {
445
+ ...hashMaps.length > 0 ? { hashMaps } : {},
446
+ ...objectKinds && Object.keys(objectKinds).length > 0 ? { objectKinds } : {}
447
+ };
448
+ }
449
+ function normalizeTraceStep(step) {
450
+ const normalizedStdoutCount = normalizeOutputLineCount(step?.stdoutLineCount);
451
+ const normalizedVisualization = normalizeVisualizationPayload(step?.visualization);
452
+ const normalizedAccesses = normalizeAccesses(step?.accesses);
453
+ return {
454
+ event: normalizeEvent(step?.event),
455
+ line: normalizeLineNumber(step?.line, 1),
456
+ function: normalizeFunctionName(step?.function),
457
+ variables: normalizeRecord(step?.variables),
458
+ ...Array.isArray(step?.callStack) && step.callStack.length > 0 ? { callStack: step.callStack.map(normalizeCallStackFrame) } : {},
459
+ ...normalizedAccesses ? { accesses: normalizedAccesses } : {},
460
+ ...step?.returnValue !== void 0 ? { returnValue: normalizeUnknown(step.returnValue) } : {},
461
+ ...normalizedStdoutCount !== void 0 ? { stdoutLineCount: normalizedStdoutCount } : {},
462
+ ...normalizedVisualization ? { visualization: normalizedVisualization } : {}
463
+ };
464
+ }
465
+ function normalizeRuntimeTraceContract(language, result) {
466
+ const normalizedTrace = Array.isArray(result.trace) ? result.trace.map(normalizeTraceStep) : [];
467
+ const lineEventCount = typeof result.lineEventCount === "number" && Number.isFinite(result.lineEventCount) ? Math.floor(result.lineEventCount) : normalizedTrace.filter((step) => step.event === "line").length;
468
+ const normalizedConsole = Array.isArray(result.consoleOutput) ? result.consoleOutput.map((line) => String(line)) : [];
469
+ return {
470
+ schemaVersion: RUNTIME_TRACE_CONTRACT_SCHEMA_VERSION,
471
+ language,
472
+ success: Boolean(result.success),
473
+ ...Object.prototype.hasOwnProperty.call(result, "output") ? { output: normalizeUnknown(result.output) } : {},
474
+ ...typeof result.error === "string" && result.error.length > 0 ? { error: result.error } : {},
475
+ ...typeof result.errorLine === "number" && Number.isFinite(result.errorLine) ? { errorLine: Math.floor(result.errorLine) } : {},
476
+ consoleOutput: normalizedConsole,
477
+ trace: normalizedTrace,
478
+ ...result.traceLimitExceeded !== void 0 ? { traceLimitExceeded: Boolean(result.traceLimitExceeded) } : {},
479
+ ...typeof result.timeoutReason === "string" && result.timeoutReason.length > 0 ? { timeoutReason: result.timeoutReason } : {},
480
+ lineEventCount: Math.max(0, lineEventCount),
481
+ traceStepCount: normalizedTrace.length
482
+ };
483
+ }
484
+
485
+ // packages/harness-core/src/trace-adapters/shared.ts
486
+ function denormalizeCallStackFrame(frame) {
487
+ return {
488
+ function: frame.function,
489
+ line: frame.line,
490
+ args: frame.args
491
+ };
492
+ }
493
+ function denormalizeTraceStep(step) {
494
+ return {
495
+ line: step.line,
496
+ event: step.event,
497
+ variables: step.variables,
498
+ function: step.function,
499
+ ...step.callStack ? { callStack: step.callStack.map(denormalizeCallStackFrame) } : {},
500
+ ...step.accesses ? { accesses: step.accesses } : {},
501
+ ...step.returnValue !== void 0 ? { returnValue: step.returnValue } : {},
502
+ ...step.stdoutLineCount !== void 0 ? { stdoutLineCount: step.stdoutLineCount } : {},
503
+ ...step.visualization ? { visualization: step.visualization } : {}
504
+ };
505
+ }
506
+ function adaptTraceExecutionResult(language, result) {
507
+ const normalized = normalizeRuntimeTraceContract(language, result);
508
+ const adaptedTrace = normalized.trace.map(denormalizeTraceStep);
509
+ return {
510
+ success: normalized.success,
511
+ ...Object.prototype.hasOwnProperty.call(normalized, "output") ? { output: normalized.output } : {},
512
+ ...normalized.error ? { error: normalized.error } : {},
513
+ ...normalized.errorLine !== void 0 ? { errorLine: normalized.errorLine } : {},
514
+ trace: adaptedTrace,
515
+ executionTimeMs: typeof result.executionTimeMs === "number" && Number.isFinite(result.executionTimeMs) ? result.executionTimeMs : 0,
516
+ consoleOutput: normalized.consoleOutput,
517
+ ...normalized.traceLimitExceeded !== void 0 ? { traceLimitExceeded: normalized.traceLimitExceeded } : {},
518
+ ...normalized.timeoutReason ? { timeoutReason: normalized.timeoutReason } : {},
519
+ lineEventCount: normalized.lineEventCount,
520
+ traceStepCount: adaptedTrace.length
521
+ };
522
+ }
523
+
524
+ // packages/harness-core/src/trace-adapters/javascript.ts
525
+ function adaptJavaScriptTraceExecutionResult(language, result) {
526
+ return adaptTraceExecutionResult(language, result);
527
+ }
528
+
529
+ // packages/harness-browser/src/runtime-capability-guards.ts
530
+ function isScriptRequest(functionName) {
531
+ if (functionName == null) return true;
532
+ return functionName.trim().length === 0;
533
+ }
534
+ function executionStyleLabel(executionStyle) {
535
+ if (executionStyle === "solution-method") return "solution-method";
536
+ if (executionStyle === "ops-class") return "ops-class";
537
+ return "function";
538
+ }
539
+ function isExecutionStyleSupported(profile, executionStyle) {
540
+ const styles = profile.capabilities.execution.styles;
541
+ if (executionStyle === "solution-method") return styles.solutionMethod;
542
+ if (executionStyle === "ops-class") return styles.opsClass;
543
+ return styles.function;
544
+ }
545
+ function describeRequest(request) {
546
+ if (request === "trace") return "tracing";
547
+ if (request === "interview") return "interview execution";
548
+ return "execution";
549
+ }
550
+ function assertRuntimeRequestSupported(profile, options) {
551
+ if (options.request === "trace" && !profile.capabilities.tracing.supported) {
552
+ throw new Error(`Runtime "${profile.language}" does not support tracing.`);
553
+ }
554
+ if (options.request === "interview" && !profile.capabilities.execution.styles.interviewMode) {
555
+ throw new Error(`Runtime "${profile.language}" does not support interview execution.`);
556
+ }
557
+ if (!isExecutionStyleSupported(profile, options.executionStyle)) {
558
+ throw new Error(
559
+ `Runtime "${profile.language}" does not support execution style "${executionStyleLabel(options.executionStyle)}".`
560
+ );
561
+ }
562
+ if (isScriptRequest(options.functionName) && !profile.capabilities.execution.styles.script) {
563
+ throw new Error(`Runtime "${profile.language}" does not support script mode ${describeRequest(options.request)}.`);
564
+ }
565
+ }
566
+
567
+ // packages/harness-browser/src/runtime-profiles.ts
568
+ var PYTHON_RUNTIME_PROFILE = {
569
+ language: "python",
570
+ maturity: "stable",
571
+ capabilities: {
572
+ execution: {
573
+ styles: {
574
+ function: true,
575
+ solutionMethod: true,
576
+ opsClass: true,
577
+ script: true,
578
+ interviewMode: true
579
+ },
580
+ timeouts: {
581
+ clientTimeouts: true,
582
+ runtimeTimeouts: true
583
+ }
584
+ },
585
+ tracing: {
586
+ supported: true,
587
+ events: {
588
+ line: true,
589
+ call: true,
590
+ return: true,
591
+ exception: true,
592
+ stdout: true,
593
+ timeout: true
594
+ },
595
+ controls: {
596
+ maxTraceSteps: true,
597
+ maxLineEvents: true,
598
+ maxSingleLineHits: true,
599
+ minimalTrace: true
600
+ },
601
+ fidelity: {
602
+ preciseLineMapping: true,
603
+ stableFunctionNames: true,
604
+ callStack: true
605
+ }
606
+ },
607
+ diagnostics: {
608
+ compileErrors: false,
609
+ runtimeErrors: true,
610
+ mappedErrorLines: true,
611
+ stackTraces: false
612
+ },
613
+ structures: {
614
+ treeNodeRefs: true,
615
+ listNodeRefs: true,
616
+ mapSerialization: true,
617
+ setSerialization: true,
618
+ graphSerialization: true,
619
+ cycleReferences: true
620
+ },
621
+ visualization: {
622
+ runtimePayloads: true,
623
+ objectKinds: true,
624
+ hashMaps: true,
625
+ stepVisualization: true
626
+ }
627
+ }
628
+ };
629
+ var JAVASCRIPT_RUNTIME_PROFILE = {
630
+ language: "javascript",
631
+ maturity: "stable",
632
+ capabilities: {
633
+ execution: {
634
+ styles: {
635
+ function: true,
636
+ solutionMethod: true,
637
+ opsClass: true,
638
+ script: true,
639
+ interviewMode: true
640
+ },
641
+ timeouts: {
642
+ clientTimeouts: true,
643
+ runtimeTimeouts: false
644
+ }
645
+ },
646
+ tracing: {
647
+ supported: true,
648
+ events: {
649
+ line: true,
650
+ call: true,
651
+ return: true,
652
+ exception: true,
653
+ stdout: false,
654
+ timeout: true
655
+ },
656
+ controls: {
657
+ maxTraceSteps: true,
658
+ maxLineEvents: true,
659
+ maxSingleLineHits: true,
660
+ minimalTrace: true
661
+ },
662
+ fidelity: {
663
+ preciseLineMapping: true,
664
+ stableFunctionNames: true,
665
+ callStack: true
666
+ }
667
+ },
668
+ diagnostics: {
669
+ compileErrors: false,
670
+ runtimeErrors: true,
671
+ mappedErrorLines: false,
672
+ stackTraces: false
673
+ },
674
+ structures: {
675
+ treeNodeRefs: true,
676
+ listNodeRefs: true,
677
+ mapSerialization: true,
678
+ setSerialization: true,
679
+ graphSerialization: true,
680
+ cycleReferences: true
681
+ },
682
+ visualization: {
683
+ runtimePayloads: true,
684
+ objectKinds: true,
685
+ hashMaps: true,
686
+ stepVisualization: true
687
+ }
688
+ }
689
+ };
690
+ var TYPESCRIPT_RUNTIME_PROFILE = {
691
+ language: "typescript",
692
+ maturity: "stable",
693
+ capabilities: {
694
+ execution: {
695
+ styles: {
696
+ function: true,
697
+ solutionMethod: true,
698
+ opsClass: true,
699
+ script: true,
700
+ interviewMode: true
701
+ },
702
+ timeouts: {
703
+ clientTimeouts: true,
704
+ runtimeTimeouts: false
705
+ }
706
+ },
707
+ tracing: {
708
+ supported: true,
709
+ events: {
710
+ line: true,
711
+ call: true,
712
+ return: true,
713
+ exception: true,
714
+ stdout: false,
715
+ timeout: true
716
+ },
717
+ controls: {
718
+ maxTraceSteps: true,
719
+ maxLineEvents: true,
720
+ maxSingleLineHits: true,
721
+ minimalTrace: true
722
+ },
723
+ fidelity: {
724
+ preciseLineMapping: true,
725
+ stableFunctionNames: true,
726
+ callStack: true
727
+ }
728
+ },
729
+ diagnostics: {
730
+ compileErrors: true,
731
+ runtimeErrors: true,
732
+ mappedErrorLines: true,
733
+ stackTraces: false
734
+ },
735
+ structures: {
736
+ treeNodeRefs: true,
737
+ listNodeRefs: true,
738
+ mapSerialization: true,
739
+ setSerialization: true,
740
+ graphSerialization: true,
741
+ cycleReferences: true
742
+ },
743
+ visualization: {
744
+ runtimePayloads: true,
745
+ objectKinds: true,
746
+ hashMaps: true,
747
+ stepVisualization: true
748
+ }
749
+ }
750
+ };
751
+ var LANGUAGE_RUNTIME_PROFILES = {
752
+ python: PYTHON_RUNTIME_PROFILE,
753
+ javascript: JAVASCRIPT_RUNTIME_PROFILE,
754
+ typescript: TYPESCRIPT_RUNTIME_PROFILE
755
+ };
756
+ var SUPPORTED_LANGUAGES = Object.freeze(
757
+ Object.keys(LANGUAGE_RUNTIME_PROFILES)
758
+ );
759
+ function getLanguageRuntimeProfile(language) {
760
+ const profile = LANGUAGE_RUNTIME_PROFILES[language];
761
+ if (!profile) {
762
+ throw new Error(`Runtime profile for language "${language}" is not implemented yet.`);
763
+ }
764
+ return profile;
765
+ }
766
+ function getSupportedLanguageProfiles() {
767
+ return SUPPORTED_LANGUAGES.map((language) => LANGUAGE_RUNTIME_PROFILES[language]);
768
+ }
769
+ function isLanguageSupported(language) {
770
+ return SUPPORTED_LANGUAGES.includes(language);
771
+ }
772
+
773
+ // packages/harness-browser/src/javascript-runtime-client.ts
774
+ var JavaScriptRuntimeClient = class {
775
+ constructor(runtimeLanguage, workerClient) {
776
+ this.runtimeLanguage = runtimeLanguage;
777
+ this.workerClient = workerClient;
778
+ }
779
+ async init() {
780
+ return this.workerClient.init();
781
+ }
782
+ async executeWithTracing(code, functionName, inputs, options, executionStyle = "function") {
783
+ assertRuntimeRequestSupported(getLanguageRuntimeProfile(this.runtimeLanguage), {
784
+ request: "trace",
785
+ executionStyle,
786
+ functionName
787
+ });
788
+ const rawResult = await this.workerClient.executeWithTracing(
789
+ code,
790
+ functionName,
791
+ inputs,
792
+ options,
793
+ executionStyle,
794
+ this.runtimeLanguage
795
+ );
796
+ return adaptJavaScriptTraceExecutionResult(this.runtimeLanguage, rawResult);
797
+ }
798
+ async executeCode(code, functionName, inputs, executionStyle = "function") {
799
+ assertRuntimeRequestSupported(getLanguageRuntimeProfile(this.runtimeLanguage), {
800
+ request: "execute",
801
+ executionStyle,
802
+ functionName
803
+ });
804
+ return this.workerClient.executeCode(
805
+ code,
806
+ functionName,
807
+ inputs,
808
+ executionStyle,
809
+ this.runtimeLanguage
810
+ );
811
+ }
812
+ async executeCodeInterviewMode(code, functionName, inputs, executionStyle = "function") {
813
+ assertRuntimeRequestSupported(getLanguageRuntimeProfile(this.runtimeLanguage), {
814
+ request: "interview",
815
+ executionStyle,
816
+ functionName
817
+ });
818
+ return this.workerClient.executeCodeInterviewMode(
819
+ code,
820
+ functionName,
821
+ inputs,
822
+ executionStyle,
823
+ this.runtimeLanguage
824
+ );
825
+ }
826
+ };
827
+ function createJavaScriptRuntimeClient(runtimeLanguage, workerClient) {
828
+ return new JavaScriptRuntimeClient(runtimeLanguage, workerClient);
829
+ }
830
+
831
+ // packages/harness-browser/src/pyodide-worker-client.ts
832
+ var EXECUTION_TIMEOUT_MS2 = 1e4;
833
+ var INTERVIEW_MODE_TIMEOUT_MS2 = 5e3;
834
+ var TRACING_TIMEOUT_MS2 = 3e4;
835
+ var INIT_TIMEOUT_MS2 = 12e4;
836
+ var MESSAGE_TIMEOUT_MS2 = 2e4;
837
+ var WORKER_READY_TIMEOUT_MS2 = 1e4;
838
+ var PyodideWorkerClient = class {
839
+ constructor(options) {
840
+ this.options = options;
841
+ this.debug = options.debug ?? process.env.NODE_ENV === "development";
842
+ }
843
+ worker = null;
844
+ pendingMessages = /* @__PURE__ */ new Map();
845
+ messageId = 0;
846
+ isInitializing = false;
847
+ initPromise = null;
848
+ workerReadyPromise = null;
849
+ workerReadyResolve = null;
850
+ workerReadyReject = null;
851
+ debug;
852
+ /**
853
+ * Check if Web Workers are supported
854
+ */
855
+ isSupported() {
856
+ return typeof Worker !== "undefined";
857
+ }
858
+ /**
859
+ * Get or create the worker instance
860
+ */
861
+ getWorker() {
862
+ if (this.worker) return this.worker;
863
+ if (!this.isSupported()) {
864
+ throw new Error("Web Workers are not supported in this environment");
865
+ }
866
+ this.workerReadyPromise = new Promise((resolve, reject) => {
867
+ this.workerReadyResolve = resolve;
868
+ this.workerReadyReject = (error) => reject(error);
869
+ });
870
+ const workerUrl = this.debug && !this.options.workerUrl.includes("?") ? `${this.options.workerUrl}?dev=${Date.now()}` : this.options.workerUrl;
871
+ this.worker = new Worker(workerUrl);
872
+ this.worker.onmessage = (event) => {
873
+ const { id, type, payload } = event.data;
874
+ if (type === "worker-ready") {
875
+ this.workerReadyResolve?.();
876
+ this.workerReadyResolve = null;
877
+ this.workerReadyReject = null;
878
+ if (this.debug) console.log("[PyodideWorkerClient] worker-ready");
879
+ return;
880
+ }
881
+ if (this.debug && !id) {
882
+ console.log("[PyodideWorkerClient] event", { type, payload });
883
+ }
884
+ if (id) {
885
+ const pending = this.pendingMessages.get(id);
886
+ if (pending) {
887
+ this.pendingMessages.delete(id);
888
+ if (pending.timeoutId) globalThis.clearTimeout(pending.timeoutId);
889
+ if (type === "error") {
890
+ pending.reject(new Error(payload.error));
891
+ } else {
892
+ if (this.debug) console.log("[PyodideWorkerClient] recv", { id, type });
893
+ pending.resolve(payload);
894
+ }
895
+ }
896
+ }
897
+ };
898
+ this.worker.onerror = (error) => {
899
+ console.error("[PyodideWorkerClient] Worker error:", error);
900
+ const workerError = new Error("Worker error");
901
+ this.workerReadyReject?.(workerError);
902
+ this.workerReadyResolve = null;
903
+ this.workerReadyReject = null;
904
+ for (const [id, pending] of this.pendingMessages) {
905
+ if (pending.timeoutId) {
906
+ globalThis.clearTimeout(pending.timeoutId);
907
+ }
908
+ pending.reject(workerError);
909
+ this.pendingMessages.delete(id);
910
+ }
911
+ };
912
+ return this.worker;
913
+ }
914
+ /**
915
+ * Wait for worker bootstrap signal with timeout.
916
+ * Guards against deadlocks when the worker script fails before posting "worker-ready".
917
+ */
918
+ async waitForWorkerReady() {
919
+ const readyPromise = this.workerReadyPromise;
920
+ if (!readyPromise) return;
921
+ await new Promise((resolve, reject) => {
922
+ let settled = false;
923
+ const timeoutId = globalThis.setTimeout(() => {
924
+ if (settled) return;
925
+ settled = true;
926
+ const timeoutError = new Error(
927
+ `Python worker failed to initialize in time (${Math.round(WORKER_READY_TIMEOUT_MS2 / 1e3)}s)`
928
+ );
929
+ if (this.debug) {
930
+ console.warn("[PyodideWorkerClient] worker-ready timeout", { timeoutMs: WORKER_READY_TIMEOUT_MS2 });
931
+ }
932
+ this.terminateAndReset(timeoutError);
933
+ reject(timeoutError);
934
+ }, WORKER_READY_TIMEOUT_MS2);
935
+ readyPromise.then(() => {
936
+ if (settled) return;
937
+ settled = true;
938
+ globalThis.clearTimeout(timeoutId);
939
+ resolve();
940
+ }).catch((error) => {
941
+ if (settled) return;
942
+ settled = true;
943
+ globalThis.clearTimeout(timeoutId);
944
+ reject(error instanceof Error ? error : new Error(String(error)));
945
+ });
946
+ });
947
+ }
948
+ /**
949
+ * Send a message to the worker and wait for a response
950
+ */
951
+ async sendMessage(type, payload, timeoutMs = MESSAGE_TIMEOUT_MS2) {
952
+ const worker = this.getWorker();
953
+ await this.waitForWorkerReady();
954
+ const id = String(++this.messageId);
955
+ return new Promise((resolve, reject) => {
956
+ this.pendingMessages.set(id, {
957
+ resolve,
958
+ reject
959
+ });
960
+ if (this.debug) console.log("[PyodideWorkerClient] send", { id, type });
961
+ const timeoutId = globalThis.setTimeout(() => {
962
+ const pending2 = this.pendingMessages.get(id);
963
+ if (!pending2) return;
964
+ this.pendingMessages.delete(id);
965
+ if (this.debug) console.warn("[PyodideWorkerClient] timeout", { id, type });
966
+ pending2.reject(new Error(`Worker request timed out: ${type}`));
967
+ }, timeoutMs);
968
+ const pending = this.pendingMessages.get(id);
969
+ if (pending) pending.timeoutId = timeoutId;
970
+ worker.postMessage({ id, type, payload });
971
+ });
972
+ }
973
+ /**
974
+ * Execute code with a timeout - terminates worker if execution takes too long
975
+ */
976
+ async executeWithTimeout(executor, timeoutMs = EXECUTION_TIMEOUT_MS2) {
977
+ return new Promise((resolve, reject) => {
978
+ let settled = false;
979
+ const timeoutId = globalThis.setTimeout(() => {
980
+ if (settled) return;
981
+ settled = true;
982
+ if (this.debug) {
983
+ console.warn("[PyodideWorkerClient] Execution timeout - terminating worker");
984
+ }
985
+ this.terminateAndReset();
986
+ const seconds = Math.round(timeoutMs / 1e3);
987
+ reject(new Error(`Execution timed out (possible infinite loop). Code execution was stopped after ${seconds} seconds.`));
988
+ }, timeoutMs);
989
+ executor().then((result) => {
990
+ if (settled) return;
991
+ settled = true;
992
+ globalThis.clearTimeout(timeoutId);
993
+ resolve(result);
994
+ }).catch((error) => {
995
+ if (settled) return;
996
+ settled = true;
997
+ globalThis.clearTimeout(timeoutId);
998
+ reject(error);
999
+ });
1000
+ });
1001
+ }
1002
+ /**
1003
+ * Terminate the worker and reset state for recreation
1004
+ */
1005
+ terminateAndReset(reason = new Error("Worker was terminated")) {
1006
+ this.workerReadyReject?.(reason);
1007
+ if (this.worker) {
1008
+ this.worker.terminate();
1009
+ this.worker = null;
1010
+ }
1011
+ this.initPromise = null;
1012
+ this.isInitializing = false;
1013
+ this.workerReadyPromise = null;
1014
+ this.workerReadyResolve = null;
1015
+ for (const [, pending] of this.pendingMessages) {
1016
+ if (pending.timeoutId) globalThis.clearTimeout(pending.timeoutId);
1017
+ pending.reject(reason);
1018
+ }
1019
+ this.pendingMessages.clear();
1020
+ }
1021
+ /**
1022
+ * Initialize Pyodide in the worker
1023
+ */
1024
+ async init() {
1025
+ if (this.initPromise) {
1026
+ return this.initPromise;
1027
+ }
1028
+ if (this.isInitializing) {
1029
+ await new Promise((resolve) => setTimeout(resolve, 100));
1030
+ return this.init();
1031
+ }
1032
+ this.isInitializing = true;
1033
+ this.initPromise = (async () => {
1034
+ try {
1035
+ return await this.sendMessage("init", void 0, INIT_TIMEOUT_MS2);
1036
+ } catch (error) {
1037
+ const message = error instanceof Error ? error.message : String(error);
1038
+ const shouldRetry = message.includes("Worker request timed out: init") || message.includes("Worker was terminated") || message.includes("Worker error") || message.includes("failed to initialize in time");
1039
+ if (!shouldRetry) {
1040
+ throw error;
1041
+ }
1042
+ if (this.debug) {
1043
+ console.warn("[PyodideWorkerClient] init failed, resetting worker and retrying once", { message });
1044
+ }
1045
+ this.terminateAndReset();
1046
+ return this.sendMessage("init", void 0, INIT_TIMEOUT_MS2);
1047
+ }
1048
+ })();
1049
+ try {
1050
+ const result = await this.initPromise;
1051
+ return result;
1052
+ } catch (error) {
1053
+ this.initPromise = null;
1054
+ throw error;
1055
+ } finally {
1056
+ this.isInitializing = false;
1057
+ }
1058
+ }
1059
+ /**
1060
+ * Execute Python code with tracing for step-by-step visualization
1061
+ * @param options.maxLineEvents - Max line events before abort (for complexity analysis, use higher values)
1062
+ */
1063
+ async executeWithTracing(code, functionName, inputs, options, executionStyle = "function") {
1064
+ await this.init();
1065
+ try {
1066
+ return await this.executeWithTimeout(
1067
+ () => this.sendMessage("execute-with-tracing", {
1068
+ code,
1069
+ functionName,
1070
+ inputs,
1071
+ executionStyle,
1072
+ options
1073
+ }, TRACING_TIMEOUT_MS2 + 5e3),
1074
+ // Message timeout slightly longer than execution timeout
1075
+ TRACING_TIMEOUT_MS2
1076
+ );
1077
+ } catch (error) {
1078
+ const errorMessage = error instanceof Error ? error.message : String(error);
1079
+ const isClientTimeout = errorMessage.includes("Execution timed out") || errorMessage.includes("possible infinite loop");
1080
+ if (isClientTimeout) {
1081
+ return {
1082
+ success: false,
1083
+ error: errorMessage,
1084
+ trace: [],
1085
+ executionTimeMs: TRACING_TIMEOUT_MS2,
1086
+ consoleOutput: [],
1087
+ traceLimitExceeded: true,
1088
+ timeoutReason: "client-timeout",
1089
+ lineEventCount: 0,
1090
+ traceStepCount: 0
1091
+ };
1092
+ }
1093
+ throw error;
1094
+ }
1095
+ }
1096
+ /**
1097
+ * Execute Python code without tracing (for running tests)
1098
+ */
1099
+ async executeCode(code, functionName, inputs, executionStyle = "function") {
1100
+ await this.init();
1101
+ return this.executeWithTimeout(
1102
+ () => this.sendMessage("execute-code", {
1103
+ code,
1104
+ functionName,
1105
+ inputs,
1106
+ executionStyle
1107
+ }, EXECUTION_TIMEOUT_MS2 + 5e3),
1108
+ EXECUTION_TIMEOUT_MS2
1109
+ );
1110
+ }
1111
+ /**
1112
+ * Execute Python code in interview mode - 5 second timeout, generic error messages
1113
+ * Does not reveal which line caused the timeout
1114
+ */
1115
+ async executeCodeInterviewMode(code, functionName, inputs, executionStyle = "function") {
1116
+ await this.init();
1117
+ try {
1118
+ const result = await this.executeWithTimeout(
1119
+ () => this.sendMessage("execute-code-interview", {
1120
+ code,
1121
+ functionName,
1122
+ inputs,
1123
+ executionStyle
1124
+ }, INTERVIEW_MODE_TIMEOUT_MS2 + 2e3),
1125
+ INTERVIEW_MODE_TIMEOUT_MS2
1126
+ );
1127
+ if (!result.success && result.error) {
1128
+ const normalizedError = result.error.toLowerCase();
1129
+ const isTimeoutOrResourceLimit = normalizedError.includes("timed out") || normalizedError.includes("execution timeout") || normalizedError.includes("infinite loop") || normalizedError.includes("interview_guard_triggered") || normalizedError.includes("memory-limit") || normalizedError.includes("line-limit") || normalizedError.includes("single-line-limit") || normalizedError.includes("recursion-limit");
1130
+ if (isTimeoutOrResourceLimit) {
1131
+ return {
1132
+ success: false,
1133
+ output: null,
1134
+ error: "Time Limit Exceeded",
1135
+ consoleOutput: result.consoleOutput ?? []
1136
+ };
1137
+ }
1138
+ }
1139
+ return result;
1140
+ } catch (error) {
1141
+ const errorMsg = error instanceof Error ? error.message : String(error);
1142
+ if (errorMsg.includes("timed out") || errorMsg.includes("Execution timeout")) {
1143
+ return {
1144
+ success: false,
1145
+ output: null,
1146
+ error: "Time Limit Exceeded",
1147
+ consoleOutput: []
1148
+ };
1149
+ }
1150
+ return {
1151
+ success: false,
1152
+ output: null,
1153
+ error: errorMsg,
1154
+ consoleOutput: []
1155
+ };
1156
+ }
1157
+ }
1158
+ /**
1159
+ * Check the status of the worker
1160
+ */
1161
+ async getStatus() {
1162
+ return this.sendMessage("status");
1163
+ }
1164
+ /**
1165
+ * Analyze Python code using AST (off main thread)
1166
+ * Returns CodeFacts with semantic information about the code
1167
+ */
1168
+ async analyzeCode(code) {
1169
+ await this.init();
1170
+ return this.sendMessage("analyze-code", { code }, 5e3);
1171
+ }
1172
+ /**
1173
+ * Terminate the worker and clean up resources
1174
+ */
1175
+ terminate() {
1176
+ this.terminateAndReset();
1177
+ }
1178
+ };
1179
+
1180
+ // packages/harness-core/src/trace-adapters/python.ts
1181
+ function adaptPythonTraceExecutionResult(result) {
1182
+ return adaptTraceExecutionResult("python", result);
1183
+ }
1184
+
1185
+ // packages/harness-browser/src/python-runtime-client.ts
1186
+ var PythonRuntimeClient = class {
1187
+ constructor(workerClient) {
1188
+ this.workerClient = workerClient;
1189
+ }
1190
+ async init() {
1191
+ return this.workerClient.init();
1192
+ }
1193
+ async executeWithTracing(code, functionName, inputs, options, executionStyle = "function") {
1194
+ assertRuntimeRequestSupported(getLanguageRuntimeProfile("python"), {
1195
+ request: "trace",
1196
+ executionStyle,
1197
+ functionName
1198
+ });
1199
+ const rawResult = await this.workerClient.executeWithTracing(
1200
+ code,
1201
+ functionName,
1202
+ inputs,
1203
+ options,
1204
+ executionStyle
1205
+ );
1206
+ return adaptPythonTraceExecutionResult(rawResult);
1207
+ }
1208
+ async executeCode(code, functionName, inputs, executionStyle = "function") {
1209
+ assertRuntimeRequestSupported(getLanguageRuntimeProfile("python"), {
1210
+ request: "execute",
1211
+ executionStyle,
1212
+ functionName
1213
+ });
1214
+ return this.workerClient.executeCode(
1215
+ code,
1216
+ functionName,
1217
+ inputs,
1218
+ executionStyle
1219
+ );
1220
+ }
1221
+ async executeCodeInterviewMode(code, functionName, inputs, executionStyle = "function") {
1222
+ assertRuntimeRequestSupported(getLanguageRuntimeProfile("python"), {
1223
+ request: "interview",
1224
+ executionStyle,
1225
+ functionName
1226
+ });
1227
+ return this.workerClient.executeCodeInterviewMode(
1228
+ code,
1229
+ functionName,
1230
+ inputs,
1231
+ executionStyle
1232
+ );
1233
+ }
1234
+ };
1235
+ function createPythonRuntimeClient(workerClient) {
1236
+ return new PythonRuntimeClient(workerClient);
1237
+ }
1238
+
1239
+ // packages/harness-browser/src/runtime-assets.ts
1240
+ var DEFAULT_ASSET_BASE_URL = "/workers";
1241
+ var DEFAULT_BROWSER_HARNESS_ASSET_RELATIVE_PATHS = Object.freeze({
1242
+ pythonWorker: "pyodide-worker.js",
1243
+ pythonRuntimeCore: "pyodide/runtime-core.js",
1244
+ pythonSnippets: "generated-python-harness-snippets.js",
1245
+ javascriptWorker: "javascript-worker.js",
1246
+ typescriptCompiler: "vendor/typescript.js"
1247
+ });
1248
+ function isExplicitAssetPath(pathname) {
1249
+ return pathname.startsWith("/") || pathname.startsWith("./") || pathname.startsWith("../") || pathname.startsWith("http://") || pathname.startsWith("https://") || pathname.startsWith("data:") || pathname.startsWith("blob:");
1250
+ }
1251
+ function stripTrailingSlash(value) {
1252
+ return value.replace(/\/+$/, "");
1253
+ }
1254
+ function trimLeadingSlash(value) {
1255
+ return value.replace(/^\/+/, "");
1256
+ }
1257
+ function resolveAssetPath(baseUrl, pathname) {
1258
+ if (isExplicitAssetPath(pathname)) {
1259
+ return pathname;
1260
+ }
1261
+ const normalizedBase = stripTrailingSlash(baseUrl || DEFAULT_ASSET_BASE_URL);
1262
+ const normalizedPath = trimLeadingSlash(pathname);
1263
+ return `${normalizedBase}/${normalizedPath}`;
1264
+ }
1265
+ function resolveBrowserHarnessAssets(options = {}) {
1266
+ const assetBaseUrl = options.assetBaseUrl ?? DEFAULT_ASSET_BASE_URL;
1267
+ const assets = options.assets ?? {};
1268
+ return {
1269
+ pythonWorker: resolveAssetPath(assetBaseUrl, assets.pythonWorker ?? DEFAULT_BROWSER_HARNESS_ASSET_RELATIVE_PATHS.pythonWorker),
1270
+ pythonRuntimeCore: resolveAssetPath(
1271
+ assetBaseUrl,
1272
+ assets.pythonRuntimeCore ?? DEFAULT_BROWSER_HARNESS_ASSET_RELATIVE_PATHS.pythonRuntimeCore
1273
+ ),
1274
+ pythonSnippets: resolveAssetPath(assetBaseUrl, assets.pythonSnippets ?? DEFAULT_BROWSER_HARNESS_ASSET_RELATIVE_PATHS.pythonSnippets),
1275
+ javascriptWorker: resolveAssetPath(
1276
+ assetBaseUrl,
1277
+ assets.javascriptWorker ?? DEFAULT_BROWSER_HARNESS_ASSET_RELATIVE_PATHS.javascriptWorker
1278
+ ),
1279
+ typescriptCompiler: resolveAssetPath(
1280
+ assetBaseUrl,
1281
+ assets.typescriptCompiler ?? DEFAULT_BROWSER_HARNESS_ASSET_RELATIVE_PATHS.typescriptCompiler
1282
+ )
1283
+ };
1284
+ }
1285
+
1286
+ // packages/harness-browser/src/browser-harness.ts
1287
+ var BrowserHarnessRuntime = class {
1288
+ assets;
1289
+ supportedLanguages = SUPPORTED_LANGUAGES;
1290
+ pythonWorkerClient;
1291
+ javaScriptWorkerClient;
1292
+ clients;
1293
+ constructor(options = {}) {
1294
+ this.assets = resolveBrowserHarnessAssets(options);
1295
+ this.pythonWorkerClient = new PyodideWorkerClient({
1296
+ workerUrl: this.assets.pythonWorker,
1297
+ debug: options.debug
1298
+ });
1299
+ this.javaScriptWorkerClient = new JavaScriptWorkerClient({
1300
+ workerUrl: this.assets.javascriptWorker,
1301
+ debug: options.debug
1302
+ });
1303
+ this.clients = {
1304
+ python: createPythonRuntimeClient(this.pythonWorkerClient),
1305
+ javascript: createJavaScriptRuntimeClient("javascript", this.javaScriptWorkerClient),
1306
+ typescript: createJavaScriptRuntimeClient("typescript", this.javaScriptWorkerClient)
1307
+ };
1308
+ }
1309
+ getClient(language) {
1310
+ const client = this.clients[language];
1311
+ if (!client) {
1312
+ throw new Error(`Runtime for language "${language}" is not implemented yet.`);
1313
+ }
1314
+ return client;
1315
+ }
1316
+ getProfile(language) {
1317
+ return getLanguageRuntimeProfile(language);
1318
+ }
1319
+ getSupportedLanguageProfiles() {
1320
+ return getSupportedLanguageProfiles();
1321
+ }
1322
+ isLanguageSupported(language) {
1323
+ return isLanguageSupported(language);
1324
+ }
1325
+ disposeLanguage(language) {
1326
+ if (language === "python") {
1327
+ this.pythonWorkerClient.terminate();
1328
+ return;
1329
+ }
1330
+ this.javaScriptWorkerClient.terminate();
1331
+ }
1332
+ dispose() {
1333
+ this.pythonWorkerClient.terminate();
1334
+ this.javaScriptWorkerClient.terminate();
1335
+ }
1336
+ };
1337
+ function createBrowserHarness(options = {}) {
1338
+ return new BrowserHarnessRuntime(options);
1339
+ }
1340
+ // Annotate the CommonJS export names for ESM import in node:
1341
+ 0 && (module.exports = {
1342
+ DEFAULT_BROWSER_HARNESS_ASSET_RELATIVE_PATHS,
1343
+ LANGUAGE_RUNTIME_PROFILES,
1344
+ SUPPORTED_LANGUAGES,
1345
+ assertRuntimeRequestSupported,
1346
+ createBrowserHarness,
1347
+ getLanguageRuntimeProfile,
1348
+ getSupportedLanguageProfiles,
1349
+ isLanguageSupported,
1350
+ resolveBrowserHarnessAssets
1351
+ });
1352
+ //# sourceMappingURL=browser.cjs.map