@tracecode/harness 0.4.0 → 0.5.1

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 (45) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +67 -80
  3. package/README.md +2 -1
  4. package/dist/browser.cjs +16 -4
  5. package/dist/browser.cjs.map +1 -1
  6. package/dist/browser.d.cts +2 -2
  7. package/dist/browser.d.ts +2 -2
  8. package/dist/browser.js +16 -4
  9. package/dist/browser.js.map +1 -1
  10. package/dist/cli.js +0 -0
  11. package/dist/core.cjs +16 -4
  12. package/dist/core.cjs.map +1 -1
  13. package/dist/core.d.cts +9 -6
  14. package/dist/core.d.ts +9 -6
  15. package/dist/core.js +16 -4
  16. package/dist/core.js.map +1 -1
  17. package/dist/index.cjs +354 -44
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.cts +2 -2
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.js +354 -44
  22. package/dist/index.js.map +1 -1
  23. package/dist/internal/browser.d.cts +1 -1
  24. package/dist/internal/browser.d.ts +1 -1
  25. package/dist/javascript.cjs +262 -26
  26. package/dist/javascript.cjs.map +1 -1
  27. package/dist/javascript.d.cts +4 -4
  28. package/dist/javascript.d.ts +4 -4
  29. package/dist/javascript.js +262 -26
  30. package/dist/javascript.js.map +1 -1
  31. package/dist/python.cjs +76 -14
  32. package/dist/python.cjs.map +1 -1
  33. package/dist/python.d.cts +8 -8
  34. package/dist/python.d.ts +8 -8
  35. package/dist/python.js +76 -14
  36. package/dist/python.js.map +1 -1
  37. package/dist/{runtime-types-Dvgn07z9.d.cts → runtime-types--lBQ6rYu.d.cts} +1 -1
  38. package/dist/{runtime-types-C7d1LFbx.d.ts → runtime-types-DtaaAhHL.d.ts} +1 -1
  39. package/dist/{types-Bzr1Ohcf.d.cts → types-DwIYM3Ku.d.cts} +5 -2
  40. package/dist/{types-Bzr1Ohcf.d.ts → types-DwIYM3Ku.d.ts} +5 -2
  41. package/package.json +13 -11
  42. package/workers/javascript/javascript-worker.js +455 -31
  43. package/workers/python/generated-python-harness-snippets.js +1 -1
  44. package/workers/python/pyodide-worker.js +31 -0
  45. package/workers/python/runtime-core.js +235 -8
package/dist/index.cjs CHANGED
@@ -63,7 +63,7 @@ __export(src_exports, {
63
63
  module.exports = __toCommonJS(src_exports);
64
64
 
65
65
  // packages/harness-core/src/trace-contract.ts
66
- var RUNTIME_TRACE_CONTRACT_SCHEMA_VERSION = "2026-03-07";
66
+ var RUNTIME_TRACE_CONTRACT_SCHEMA_VERSION = "2026-03-13";
67
67
  var TRACE_EVENTS = /* @__PURE__ */ new Set([
68
68
  "line",
69
69
  "call",
@@ -106,13 +106,13 @@ function normalizeFunctionName(value) {
106
106
  return "<module>";
107
107
  }
108
108
  function normalizeKind(value) {
109
- if (value === "map" || value === "set" || value === "hashmap") {
109
+ if (value === "map" || value === "set" || value === "hashmap" || value === "object") {
110
110
  return value;
111
111
  }
112
112
  return "hashmap";
113
113
  }
114
114
  function normalizeObjectKind(value) {
115
- if (value === "hashmap" || value === "map" || value === "set" || value === "tree" || value === "linked-list" || value === "graph-adjacency") {
115
+ if (value === "hashmap" || value === "object" || value === "map" || value === "set" || value === "tree" || value === "linked-list" || value === "graph-adjacency") {
116
116
  return value;
117
117
  }
118
118
  return null;
@@ -190,6 +190,14 @@ function normalizeRecord(value) {
190
190
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
191
191
  return normalizeUnknown(value);
192
192
  }
193
+ function normalizeVariableSources(value) {
194
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
195
+ const entries = Object.entries(value).filter(
196
+ ([name, source]) => typeof name === "string" && name.length > 0 && (source === "user" || source === "user-input" || source === "harness-prelude")
197
+ ).sort((a, b) => a[0].localeCompare(b[0]));
198
+ if (entries.length === 0) return void 0;
199
+ return Object.fromEntries(entries);
200
+ }
193
201
  function normalizeCallStackFrame(frame) {
194
202
  return {
195
203
  function: normalizeFunctionName(frame?.function),
@@ -207,7 +215,9 @@ function normalizeVisualizationPayload(payload) {
207
215
  ...item?.highlight ? { highlight: true } : {}
208
216
  })) : [],
209
217
  ...entry?.highlightedKey !== void 0 ? { highlightedKey: normalizeUnknown(entry.highlightedKey) } : {},
210
- ...entry?.deletedKey !== void 0 ? { deletedKey: normalizeUnknown(entry.deletedKey) } : {}
218
+ ...entry?.deletedKey !== void 0 ? { deletedKey: normalizeUnknown(entry.deletedKey) } : {},
219
+ ...typeof entry?.objectClassName === "string" && entry.objectClassName.length > 0 ? { objectClassName: entry.objectClassName } : {},
220
+ ...typeof entry?.objectId === "string" && entry.objectId.length > 0 ? { objectId: entry.objectId } : {}
211
221
  })).sort((a, b) => `${a.name}:${a.kind}`.localeCompare(`${b.name}:${b.kind}`)) : [];
212
222
  const objectKinds = payload?.objectKinds && typeof payload.objectKinds === "object" ? Object.fromEntries(
213
223
  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]))
@@ -224,11 +234,13 @@ function normalizeTraceStep(step) {
224
234
  const normalizedStdoutCount = normalizeOutputLineCount(step?.stdoutLineCount);
225
235
  const normalizedVisualization = normalizeVisualizationPayload(step?.visualization);
226
236
  const normalizedAccesses = normalizeAccesses(step?.accesses);
237
+ const normalizedVariableSources = normalizeVariableSources(step?.variableSources);
227
238
  return {
228
239
  event: normalizeEvent(step?.event),
229
240
  line: normalizeLineNumber(step?.line, 1),
230
241
  function: normalizeFunctionName(step?.function),
231
242
  variables: normalizeRecord(step?.variables),
243
+ ...normalizedVariableSources ? { variableSources: normalizedVariableSources } : {},
232
244
  ...Array.isArray(step?.callStack) && step.callStack.length > 0 ? { callStack: step.callStack.map(normalizeCallStackFrame) } : {},
233
245
  ...normalizedAccesses ? { accesses: normalizedAccesses } : {},
234
246
  ...step?.returnValue !== void 0 ? { returnValue: normalizeUnknown(step.returnValue) } : {},
@@ -1439,6 +1451,7 @@ var PYTHON_TRACE_SERIALIZE_FUNCTION = `
1439
1451
  # Sentinel to mark skipped values (functions, etc.) - distinct from None
1440
1452
  _SKIP_SENTINEL = "__TRACECODE_SKIP__"
1441
1453
  _MAX_SERIALIZE_DEPTH = 48
1454
+ _MAX_OBJECT_FIELDS = 32
1442
1455
 
1443
1456
  def _serialize(obj, depth=0, node_refs=None):
1444
1457
  if node_refs is None:
@@ -1466,7 +1479,7 @@ def _serialize(obj, depth=0, node_refs=None):
1466
1479
  except TypeError:
1467
1480
  sorted_vals = [_serialize(x, depth + 1, node_refs) for x in obj]
1468
1481
  return {"__type__": "set", "values": sorted_vals}
1469
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and (hasattr(obj, 'left') or hasattr(obj, 'right')):
1482
+ elif isinstance(obj, TreeNode):
1470
1483
  obj_ref = id(obj)
1471
1484
  if obj_ref in node_refs:
1472
1485
  return {"__ref__": node_refs[obj_ref]}
@@ -1482,7 +1495,7 @@ def _serialize(obj, depth=0, node_refs=None):
1482
1495
  if hasattr(obj, 'right'):
1483
1496
  result["right"] = _serialize(obj.right, depth + 1, node_refs)
1484
1497
  return result
1485
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and hasattr(obj, 'next'):
1498
+ elif isinstance(obj, ListNode):
1486
1499
  obj_ref = id(obj)
1487
1500
  if obj_ref in node_refs:
1488
1501
  return {"__ref__": node_refs[obj_ref]}
@@ -1495,6 +1508,36 @@ def _serialize(obj, depth=0, node_refs=None):
1495
1508
  }
1496
1509
  result["next"] = _serialize(obj.next, depth + 1, node_refs)
1497
1510
  return result
1511
+ elif hasattr(obj, '__dict__'):
1512
+ obj_ref = id(obj)
1513
+ if obj_ref in node_refs:
1514
+ return {"__ref__": node_refs[obj_ref]}
1515
+ node_id = f"object-{obj_ref}"
1516
+ node_refs[obj_ref] = node_id
1517
+ class_name = getattr(getattr(obj, '__class__', None), '__name__', 'object')
1518
+ result = {
1519
+ "__type__": "object",
1520
+ "__class__": class_name,
1521
+ "__id__": node_id,
1522
+ }
1523
+ try:
1524
+ raw_fields = getattr(obj, '__dict__', None)
1525
+ except Exception:
1526
+ raw_fields = None
1527
+ if isinstance(raw_fields, dict):
1528
+ added = 0
1529
+ for key, value in raw_fields.items():
1530
+ key_str = str(key)
1531
+ if key_str.startswith('_'):
1532
+ continue
1533
+ if callable(value):
1534
+ continue
1535
+ result[key_str] = _serialize(value, depth + 1, node_refs)
1536
+ added += 1
1537
+ if added >= _MAX_OBJECT_FIELDS:
1538
+ result["__truncated__"] = True
1539
+ break
1540
+ return result
1498
1541
  elif callable(obj):
1499
1542
  # Skip functions entirely - return sentinel
1500
1543
  return _SKIP_SENTINEL
@@ -1530,14 +1573,14 @@ def _serialize(obj, depth=0):
1530
1573
  return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
1531
1574
  except TypeError:
1532
1575
  return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
1533
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and (hasattr(obj, 'left') or hasattr(obj, 'right')):
1576
+ elif isinstance(obj, TreeNode):
1534
1577
  result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
1535
1578
  if hasattr(obj, 'left'):
1536
1579
  result["left"] = _serialize(obj.left, depth + 1)
1537
1580
  if hasattr(obj, 'right'):
1538
1581
  result["right"] = _serialize(obj.right, depth + 1)
1539
1582
  return result
1540
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and hasattr(obj, 'next'):
1583
+ elif isinstance(obj, ListNode):
1541
1584
  result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
1542
1585
  result["next"] = _serialize(obj.next, depth + 1)
1543
1586
  return result
@@ -1612,14 +1655,14 @@ def _serialize(obj, depth=0):
1612
1655
  return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
1613
1656
  except TypeError:
1614
1657
  return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
1615
- elif hasattr(obj, 'val') and (hasattr(obj, 'left') or hasattr(obj, 'right')):
1658
+ elif isinstance(obj, TreeNode):
1616
1659
  result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', None), depth + 1)}
1617
1660
  if hasattr(obj, 'left'):
1618
1661
  result["left"] = _serialize(obj.left, depth + 1)
1619
1662
  if hasattr(obj, 'right'):
1620
1663
  result["right"] = _serialize(obj.right, depth + 1)
1621
1664
  return result
1622
- elif hasattr(obj, 'val') and hasattr(obj, 'next'):
1665
+ elif isinstance(obj, ListNode):
1623
1666
  result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', None), depth + 1)}
1624
1667
  result["next"] = _serialize(obj.next, depth + 1)
1625
1668
  return result
@@ -1651,14 +1694,14 @@ def _serialize(obj, depth=0):
1651
1694
  return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
1652
1695
  except TypeError:
1653
1696
  return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
1654
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and (hasattr(obj, 'left') or hasattr(obj, 'right')):
1697
+ elif isinstance(obj, TreeNode):
1655
1698
  result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
1656
1699
  if hasattr(obj, 'left'):
1657
1700
  result["left"] = _serialize(obj.left, depth + 1)
1658
1701
  if hasattr(obj, 'right'):
1659
1702
  result["right"] = _serialize(obj.right, depth + 1)
1660
1703
  return result
1661
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and hasattr(obj, 'next'):
1704
+ elif isinstance(obj, ListNode):
1662
1705
  result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
1663
1706
  result["next"] = _serialize(obj.next, depth + 1)
1664
1707
  return result
@@ -1858,6 +1901,7 @@ var TEMPLATE_PYTHON_TRACE_SERIALIZE_FUNCTION = `
1858
1901
  # Sentinel to mark skipped values (functions, etc.) - distinct from None
1859
1902
  _SKIP_SENTINEL = "__TRACECODE_SKIP__"
1860
1903
  _MAX_SERIALIZE_DEPTH = 48
1904
+ _MAX_OBJECT_FIELDS = 32
1861
1905
 
1862
1906
  def _serialize(obj, depth=0, node_refs=None):
1863
1907
  if node_refs is None:
@@ -1885,7 +1929,7 @@ def _serialize(obj, depth=0, node_refs=None):
1885
1929
  except TypeError:
1886
1930
  sorted_vals = [_serialize(x, depth + 1, node_refs) for x in obj]
1887
1931
  return {"__type__": "set", "values": sorted_vals}
1888
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and (hasattr(obj, 'left') or hasattr(obj, 'right')):
1932
+ elif isinstance(obj, TreeNode):
1889
1933
  obj_ref = id(obj)
1890
1934
  if obj_ref in node_refs:
1891
1935
  return {"__ref__": node_refs[obj_ref]}
@@ -1901,7 +1945,7 @@ def _serialize(obj, depth=0, node_refs=None):
1901
1945
  if hasattr(obj, 'right'):
1902
1946
  result["right"] = _serialize(obj.right, depth + 1, node_refs)
1903
1947
  return result
1904
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and hasattr(obj, 'next'):
1948
+ elif isinstance(obj, ListNode):
1905
1949
  obj_ref = id(obj)
1906
1950
  if obj_ref in node_refs:
1907
1951
  return {"__ref__": node_refs[obj_ref]}
@@ -1914,6 +1958,36 @@ def _serialize(obj, depth=0, node_refs=None):
1914
1958
  }
1915
1959
  result["next"] = _serialize(obj.next, depth + 1, node_refs)
1916
1960
  return result
1961
+ elif hasattr(obj, '__dict__'):
1962
+ obj_ref = id(obj)
1963
+ if obj_ref in node_refs:
1964
+ return {"__ref__": node_refs[obj_ref]}
1965
+ node_id = f"object-{obj_ref}"
1966
+ node_refs[obj_ref] = node_id
1967
+ class_name = getattr(getattr(obj, '__class__', None), '__name__', 'object')
1968
+ result = {
1969
+ "__type__": "object",
1970
+ "__class__": class_name,
1971
+ "__id__": node_id,
1972
+ }
1973
+ try:
1974
+ raw_fields = getattr(obj, '__dict__', None)
1975
+ except Exception:
1976
+ raw_fields = None
1977
+ if isinstance(raw_fields, dict):
1978
+ added = 0
1979
+ for key, value in raw_fields.items():
1980
+ key_str = str(key)
1981
+ if key_str.startswith('_'):
1982
+ continue
1983
+ if callable(value):
1984
+ continue
1985
+ result[key_str] = _serialize(value, depth + 1, node_refs)
1986
+ added += 1
1987
+ if added >= _MAX_OBJECT_FIELDS:
1988
+ result["__truncated__"] = True
1989
+ break
1990
+ return result
1917
1991
  elif callable(obj):
1918
1992
  # Skip functions entirely - return sentinel
1919
1993
  return _SKIP_SENTINEL
@@ -1949,14 +2023,14 @@ def _serialize(obj, depth=0):
1949
2023
  return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
1950
2024
  except TypeError:
1951
2025
  return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
1952
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and (hasattr(obj, 'left') or hasattr(obj, 'right')):
2026
+ elif isinstance(obj, TreeNode):
1953
2027
  result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
1954
2028
  if hasattr(obj, 'left'):
1955
2029
  result["left"] = _serialize(obj.left, depth + 1)
1956
2030
  if hasattr(obj, 'right'):
1957
2031
  result["right"] = _serialize(obj.right, depth + 1)
1958
2032
  return result
1959
- elif (hasattr(obj, 'val') or hasattr(obj, 'value')) and hasattr(obj, 'next'):
2033
+ elif isinstance(obj, ListNode):
1960
2034
  result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', getattr(obj, 'value', None)), depth + 1)}
1961
2035
  result["next"] = _serialize(obj.next, depth + 1)
1962
2036
  return result
@@ -2031,14 +2105,14 @@ def _serialize(obj, depth=0):
2031
2105
  return {"__type__": "set", "values": sorted([_serialize(x, depth + 1) for x in obj])}
2032
2106
  except TypeError:
2033
2107
  return {"__type__": "set", "values": [_serialize(x, depth + 1) for x in obj]}
2034
- elif hasattr(obj, 'val') and (hasattr(obj, 'left') or hasattr(obj, 'right')):
2108
+ elif isinstance(obj, TreeNode):
2035
2109
  result = {"__type__": "TreeNode", "val": _serialize(getattr(obj, 'val', None), depth + 1)}
2036
2110
  if hasattr(obj, 'left'):
2037
2111
  result["left"] = _serialize(obj.left, depth + 1)
2038
2112
  if hasattr(obj, 'right'):
2039
2113
  result["right"] = _serialize(obj.right, depth + 1)
2040
2114
  return result
2041
- elif hasattr(obj, 'val') and hasattr(obj, 'next'):
2115
+ elif isinstance(obj, ListNode):
2042
2116
  result = {"__type__": "ListNode", "val": _serialize(getattr(obj, 'val', None), depth + 1)}
2043
2117
  result["next"] = _serialize(obj.next, depth + 1)
2044
2118
  return result
@@ -2132,16 +2206,28 @@ function createConsoleProxy(output) {
2132
2206
  }
2133
2207
  function isLikelyTreeNodeValue(value) {
2134
2208
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
2135
- const hasValue = "val" in value || "value" in value;
2136
- const hasTreeLinks = "left" in value || "right" in value;
2137
- return hasValue && hasTreeLinks;
2209
+ const record = value;
2210
+ if (record.__type__ === "TreeNode") return true;
2211
+ const ctor = value.constructor;
2212
+ return ctor?.name === "TreeNode";
2138
2213
  }
2139
2214
  function isLikelyListNodeValue(value) {
2140
2215
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
2141
- const hasValue = "val" in value || "value" in value;
2142
- const hasTreeLinks = "left" in value || "right" in value;
2143
- const hasListLinks = "next" in value || "prev" in value;
2144
- return hasValue && hasListLinks && !hasTreeLinks;
2216
+ const record = value;
2217
+ if (record.__type__ === "ListNode") return true;
2218
+ const ctor = value.constructor;
2219
+ return ctor?.name === "ListNode";
2220
+ }
2221
+ function getCustomClassName(value) {
2222
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
2223
+ if (value instanceof Map || value instanceof Set) return null;
2224
+ if (isLikelyTreeNodeValue(value) || isLikelyListNodeValue(value)) return null;
2225
+ const ctor = value.constructor;
2226
+ const name = typeof ctor?.name === "string" ? ctor.name : "";
2227
+ if (!name || name === "Object" || name === "Array" || name === "Map" || name === "Set") {
2228
+ return null;
2229
+ }
2230
+ return name;
2145
2231
  }
2146
2232
  function serializeValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet(), nodeRefState = { ids: /* @__PURE__ */ new Map(), nextId: 1 }) {
2147
2233
  if (depth > 48) return "<max depth>";
@@ -2185,22 +2271,47 @@ function serializeValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet(),
2185
2271
  const nodePrefix = isTree ? "tree" : "list";
2186
2272
  const nodeId = `${nodePrefix}-${nodeRefState.nextId++}`;
2187
2273
  nodeRefState.ids.set(objectValue, nodeId);
2188
- if (isTree) {
2189
- return {
2190
- __type__: "TreeNode",
2191
- __id__: nodeId,
2192
- val: serializeValue(nodeValue.val ?? nodeValue.value ?? null, depth + 1, seen, nodeRefState),
2193
- left: serializeValue(nodeValue.left ?? null, depth + 1, seen, nodeRefState),
2194
- right: serializeValue(nodeValue.right ?? null, depth + 1, seen, nodeRefState)
2195
- };
2196
- }
2197
- return {
2274
+ const out2 = isTree ? {
2275
+ __type__: "TreeNode",
2276
+ __id__: nodeId,
2277
+ val: serializeValue(nodeValue.val ?? nodeValue.value ?? null, depth + 1, seen, nodeRefState),
2278
+ left: serializeValue(nodeValue.left ?? null, depth + 1, seen, nodeRefState),
2279
+ right: serializeValue(nodeValue.right ?? null, depth + 1, seen, nodeRefState)
2280
+ } : {
2198
2281
  __type__: "ListNode",
2199
2282
  __id__: nodeId,
2200
2283
  val: serializeValue(nodeValue.val ?? nodeValue.value ?? null, depth + 1, seen, nodeRefState),
2201
2284
  next: serializeValue(nodeValue.next ?? null, depth + 1, seen, nodeRefState),
2202
2285
  ..."prev" in nodeValue ? { prev: serializeValue(nodeValue.prev ?? null, depth + 1, seen, nodeRefState) } : {}
2203
2286
  };
2287
+ const skipped = isTree ? /* @__PURE__ */ new Set(["__id__", "__type__", "__class__", "val", "value", "left", "right"]) : /* @__PURE__ */ new Set(["__id__", "__type__", "__class__", "val", "value", "next", "prev"]);
2288
+ for (const [k, v] of Object.entries(nodeValue)) {
2289
+ if (skipped.has(k)) continue;
2290
+ out2[k] = serializeValue(v, depth + 1, seen, nodeRefState);
2291
+ }
2292
+ return out2;
2293
+ }
2294
+ const customClassName = getCustomClassName(value);
2295
+ if (customClassName) {
2296
+ const objectValue = value;
2297
+ const existingId = nodeRefState.ids.get(objectValue);
2298
+ if (existingId) {
2299
+ return { __ref__: existingId };
2300
+ }
2301
+ const objectId = `object-${nodeRefState.nextId++}`;
2302
+ nodeRefState.ids.set(objectValue, objectId);
2303
+ if (seen.has(objectValue)) return { __ref__: objectId };
2304
+ seen.add(objectValue);
2305
+ const out2 = {
2306
+ __type__: "object",
2307
+ __class__: customClassName,
2308
+ __id__: objectId
2309
+ };
2310
+ for (const [k, v] of Object.entries(value)) {
2311
+ out2[k] = serializeValue(v, depth + 1, seen, nodeRefState);
2312
+ }
2313
+ seen.delete(objectValue);
2314
+ return out2;
2204
2315
  }
2205
2316
  if (seen.has(value)) return "<cycle>";
2206
2317
  seen.add(value);
@@ -2291,6 +2402,194 @@ function normalizeInputs(inputs) {
2291
2402
  }
2292
2403
  return hydrated;
2293
2404
  }
2405
+ function buildTreeNodeFromLevelOrder(values) {
2406
+ if (!Array.isArray(values) || values.length === 0) return null;
2407
+ const firstValue = values[0];
2408
+ if (firstValue === null || firstValue === void 0) return null;
2409
+ const root = {
2410
+ val: firstValue,
2411
+ value: firstValue,
2412
+ left: null,
2413
+ right: null
2414
+ };
2415
+ const queue = [root];
2416
+ let index = 1;
2417
+ while (queue.length > 0 && index < values.length) {
2418
+ const node = queue.shift();
2419
+ if (!node) break;
2420
+ const leftValue = values[index++];
2421
+ if (leftValue !== null && leftValue !== void 0) {
2422
+ const leftNode = {
2423
+ val: leftValue,
2424
+ value: leftValue,
2425
+ left: null,
2426
+ right: null
2427
+ };
2428
+ node.left = leftNode;
2429
+ queue.push(leftNode);
2430
+ }
2431
+ if (index >= values.length) break;
2432
+ const rightValue = values[index++];
2433
+ if (rightValue !== null && rightValue !== void 0) {
2434
+ const rightNode = {
2435
+ val: rightValue,
2436
+ value: rightValue,
2437
+ left: null,
2438
+ right: null
2439
+ };
2440
+ node.right = rightNode;
2441
+ queue.push(rightNode);
2442
+ }
2443
+ }
2444
+ return root;
2445
+ }
2446
+ function materializeTreeInput(value) {
2447
+ if (value === null || value === void 0) return value;
2448
+ if (Array.isArray(value)) {
2449
+ return buildTreeNodeFromLevelOrder(value);
2450
+ }
2451
+ if (!isPlainObjectRecord(value)) {
2452
+ return value;
2453
+ }
2454
+ const record = value;
2455
+ if (isLikelyTreeNodeValue(record)) {
2456
+ const node = {
2457
+ val: record.val ?? record.value ?? null,
2458
+ value: record.val ?? record.value ?? null,
2459
+ left: materializeTreeInput(record.left ?? null),
2460
+ right: materializeTreeInput(record.right ?? null)
2461
+ };
2462
+ for (const [key, nested] of Object.entries(record)) {
2463
+ if (key === "__id__" || key === "__type__" || key === "val" || key === "value" || key === "left" || key === "right") continue;
2464
+ node[key] = materializeTreeInput(nested);
2465
+ }
2466
+ return node;
2467
+ }
2468
+ const taggedRecord = value;
2469
+ if (taggedRecord.__type__ === "TreeNode") {
2470
+ const node = {
2471
+ val: taggedRecord.val ?? taggedRecord.value ?? null,
2472
+ value: taggedRecord.val ?? taggedRecord.value ?? null,
2473
+ left: materializeTreeInput(taggedRecord.left ?? null),
2474
+ right: materializeTreeInput(taggedRecord.right ?? null)
2475
+ };
2476
+ for (const [key, nested] of Object.entries(taggedRecord)) {
2477
+ if (key === "__id__" || key === "__type__" || key === "val" || key === "value" || key === "left" || key === "right") continue;
2478
+ node[key] = materializeTreeInput(nested);
2479
+ }
2480
+ return node;
2481
+ }
2482
+ return value;
2483
+ }
2484
+ function materializeListInput(value, refs = /* @__PURE__ */ new Map(), materialized = /* @__PURE__ */ new WeakMap()) {
2485
+ if (value === null || value === void 0) return value;
2486
+ if (Array.isArray(value)) {
2487
+ if (value.length === 0) return null;
2488
+ const head = {
2489
+ val: value[0],
2490
+ value: value[0],
2491
+ next: null
2492
+ };
2493
+ let current = head;
2494
+ for (let i = 1; i < value.length; i++) {
2495
+ const nextNode = { val: value[i], value: value[i], next: null };
2496
+ current.next = nextNode;
2497
+ current = nextNode;
2498
+ }
2499
+ return head;
2500
+ }
2501
+ if (!isPlainObjectRecord(value)) {
2502
+ return value;
2503
+ }
2504
+ const record = value;
2505
+ if (typeof record.__ref__ === "string") {
2506
+ return refs.get(record.__ref__) ?? null;
2507
+ }
2508
+ const taggedRecord = value;
2509
+ if (isLikelyListNodeValue(record) || taggedRecord.__type__ === "ListNode") {
2510
+ const existingMaterialized = materialized.get(record);
2511
+ if (existingMaterialized) {
2512
+ return existingMaterialized;
2513
+ }
2514
+ const node = {
2515
+ val: taggedRecord.val ?? taggedRecord.value ?? null,
2516
+ value: taggedRecord.val ?? taggedRecord.value ?? null,
2517
+ next: null
2518
+ };
2519
+ materialized.set(record, node);
2520
+ if (typeof taggedRecord.__id__ === "string" && taggedRecord.__id__.length > 0) {
2521
+ refs.set(taggedRecord.__id__, node);
2522
+ }
2523
+ node.next = materializeListInput(taggedRecord.next ?? null, refs, materialized);
2524
+ for (const [key, nested] of Object.entries(taggedRecord)) {
2525
+ if (key === "__id__" || key === "__type__" || key === "__class__" || key === "val" || key === "value" || key === "next") continue;
2526
+ node[key] = materializeListInput(nested, refs, materialized);
2527
+ }
2528
+ return node;
2529
+ }
2530
+ return value;
2531
+ }
2532
+ function detectMaterializerKind(ts, typeNode) {
2533
+ if (!typeNode) return null;
2534
+ if (ts.isParenthesizedTypeNode(typeNode)) {
2535
+ return detectMaterializerKind(ts, typeNode.type);
2536
+ }
2537
+ if (ts.isUnionTypeNode(typeNode)) {
2538
+ for (const child of typeNode.types) {
2539
+ const resolved = detectMaterializerKind(ts, child);
2540
+ if (resolved) return resolved;
2541
+ }
2542
+ return null;
2543
+ }
2544
+ if (ts.isTypeReferenceNode(typeNode)) {
2545
+ const typeNameText = typeNode.typeName.getText();
2546
+ if (typeNameText === "TreeNode") return "tree";
2547
+ if (typeNameText === "ListNode") return "list";
2548
+ return null;
2549
+ }
2550
+ return null;
2551
+ }
2552
+ function collectInputMaterializers(ts, functionLikeNode) {
2553
+ const out = {};
2554
+ for (const parameter of functionLikeNode.parameters ?? []) {
2555
+ if (!ts.isIdentifier(parameter.name)) continue;
2556
+ if (parameter.name.text === "this") continue;
2557
+ const kind = detectMaterializerKind(ts, parameter.type);
2558
+ if (kind) {
2559
+ out[parameter.name.text] = kind;
2560
+ }
2561
+ }
2562
+ return out;
2563
+ }
2564
+ async function resolveInputMaterializers(code, functionName, executionStyle, language) {
2565
+ if (!functionName || executionStyle === "ops-class" || language !== "typescript") {
2566
+ return {};
2567
+ }
2568
+ try {
2569
+ const ts = await getTypeScriptModule();
2570
+ const sourceFile = ts.createSourceFile(
2571
+ "runtime-input.ts",
2572
+ code,
2573
+ ts.ScriptTarget.ES2020,
2574
+ true,
2575
+ ts.ScriptKind.TS
2576
+ );
2577
+ const target = findFunctionLikeNode(ts, sourceFile, functionName, executionStyle);
2578
+ if (!target) return {};
2579
+ return collectInputMaterializers(ts, target);
2580
+ } catch {
2581
+ return {};
2582
+ }
2583
+ }
2584
+ function applyInputMaterializers(inputs, materializers) {
2585
+ if (Object.keys(materializers).length === 0) return inputs;
2586
+ const next = { ...inputs };
2587
+ for (const [name, kind] of Object.entries(materializers)) {
2588
+ if (!Object.prototype.hasOwnProperty.call(next, name)) continue;
2589
+ next[name] = kind === "tree" ? materializeTreeInput(next[name]) : materializeListInput(next[name]);
2590
+ }
2591
+ return next;
2592
+ }
2294
2593
  function collectSimpleParameterNames(ts, functionLikeNode) {
2295
2594
  const names = [];
2296
2595
  for (const parameter of functionLikeNode.parameters ?? []) {
@@ -2344,14 +2643,20 @@ function findFunctionLikeNode(ts, sourceFile, functionName, executionStyle) {
2344
2643
  visit(sourceFile);
2345
2644
  return found;
2346
2645
  }
2347
- async function resolveOrderedInputKeys(code, functionName, inputs, executionStyle) {
2646
+ async function resolveOrderedInputKeys(code, functionName, inputs, executionStyle, language = "javascript") {
2348
2647
  const fallbackKeys = Object.keys(inputs);
2349
2648
  if (!functionName || executionStyle === "ops-class" || fallbackKeys.length <= 1) {
2350
2649
  return fallbackKeys;
2351
2650
  }
2352
2651
  try {
2353
2652
  const ts = await getTypeScriptModule();
2354
- const sourceFile = ts.createSourceFile("runtime-input.js", code, ts.ScriptTarget.ES2020, true, ts.ScriptKind.JS);
2653
+ const sourceFile = ts.createSourceFile(
2654
+ `runtime-input.${language === "typescript" ? "ts" : "js"}`,
2655
+ code,
2656
+ ts.ScriptTarget.ES2020,
2657
+ true,
2658
+ language === "typescript" ? ts.ScriptKind.TS : ts.ScriptKind.JS
2659
+ );
2355
2660
  const target = findFunctionLikeNode(ts, sourceFile, functionName, executionStyle);
2356
2661
  if (!target) {
2357
2662
  return fallbackKeys;
@@ -2495,20 +2800,22 @@ async function transpileTypeScript(code) {
2495
2800
  }
2496
2801
  return transpiled.outputText;
2497
2802
  }
2498
- async function executeJavaScriptCode(code, functionName, inputs, executionStyle = "function") {
2803
+ async function executeJavaScriptCode(code, functionName, inputs, executionStyle = "function", language = "javascript") {
2499
2804
  const consoleOutput = [];
2500
2805
  const consoleProxy = createConsoleProxy(consoleOutput);
2501
2806
  const normalizedInputs = normalizeInputs(inputs);
2807
+ const materializers = await resolveInputMaterializers(code, functionName, executionStyle, language);
2808
+ const materializedInputs = applyInputMaterializers(normalizedInputs, materializers);
2502
2809
  try {
2503
2810
  let output;
2504
2811
  if (executionStyle === "ops-class") {
2505
- const { operations, argumentsList } = getOpsClassInputs(normalizedInputs);
2812
+ const { operations, argumentsList } = getOpsClassInputs(materializedInputs);
2506
2813
  const runner = buildRunner(code, executionStyle, []);
2507
2814
  output = await Promise.resolve(runner(consoleProxy, functionName, operations, argumentsList));
2508
2815
  } else {
2509
- const inputKeys = await resolveOrderedInputKeys(code, functionName, normalizedInputs, executionStyle);
2816
+ const inputKeys = await resolveOrderedInputKeys(code, functionName, materializedInputs, executionStyle, language);
2510
2817
  const argNames = inputKeys.map((_, index) => `__arg${index}`);
2511
- const argValues = inputKeys.map((key) => normalizedInputs[key]);
2818
+ const argValues = inputKeys.map((key) => materializedInputs[key]);
2512
2819
  const runner = buildRunner(code, executionStyle, argNames);
2513
2820
  output = await Promise.resolve(runner(consoleProxy, functionName, ...argValues));
2514
2821
  }
@@ -2527,9 +2834,9 @@ async function executeJavaScriptCode(code, functionName, inputs, executionStyle
2527
2834
  };
2528
2835
  }
2529
2836
  }
2530
- async function executeJavaScriptWithTracing(code, functionName, inputs, executionStyle = "function") {
2837
+ async function executeJavaScriptWithTracing(code, functionName, inputs, executionStyle = "function", language = "javascript") {
2531
2838
  const startedAt = performanceNow();
2532
- const codeResult = await executeJavaScriptCode(code, functionName ?? "", inputs, executionStyle);
2839
+ const codeResult = await executeJavaScriptCode(code, functionName ?? "", inputs, executionStyle, language);
2533
2840
  const executionTimeMs = performanceNow() - startedAt;
2534
2841
  if (!codeResult.success) {
2535
2842
  return {
@@ -2554,8 +2861,11 @@ async function executeJavaScriptWithTracing(code, functionName, inputs, executio
2554
2861
  };
2555
2862
  }
2556
2863
  async function executeTypeScriptCode(code, functionName, inputs, executionStyle = "function") {
2864
+ const normalizedInputs = normalizeInputs(inputs);
2865
+ const materializers = await resolveInputMaterializers(code, functionName, executionStyle, "typescript");
2866
+ const materializedInputs = applyInputMaterializers(normalizedInputs, materializers);
2557
2867
  const transpiledCode = await transpileTypeScript(code);
2558
- return executeJavaScriptCode(transpiledCode, functionName, inputs, executionStyle);
2868
+ return executeJavaScriptCode(transpiledCode, functionName, materializedInputs, executionStyle, "typescript");
2559
2869
  }
2560
2870
  // Annotate the CommonJS export names for ESM import in node:
2561
2871
  0 && (module.exports = {