poe-code 3.0.258 → 3.0.259

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 (76) hide show
  1. package/dist/cli/commands/gaslight.js +84 -1
  2. package/dist/cli/commands/gaslight.js.map +1 -1
  3. package/dist/cli/poe-theme.d.ts +1 -0
  4. package/dist/cli/poe-theme.js +5 -0
  5. package/dist/cli/poe-theme.js.map +1 -0
  6. package/dist/cli/program.js +1 -0
  7. package/dist/cli/program.js.map +1 -1
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.js +2753 -1123
  10. package/dist/index.js.map +4 -4
  11. package/dist/metafile.json +1 -1
  12. package/dist/sdk/gaslight.d.ts +1 -1
  13. package/dist/sdk/gaslight.js +1 -1
  14. package/dist/sdk/gaslight.js.map +1 -1
  15. package/package.json +3 -1
  16. package/packages/agent-gaslight/dist/config.d.ts +5 -1
  17. package/packages/agent-gaslight/dist/config.js +32 -11
  18. package/packages/agent-gaslight/dist/index.d.ts +3 -2
  19. package/packages/agent-gaslight/dist/index.js +2 -1
  20. package/packages/agent-gaslight/dist/ingest.d.ts +2 -0
  21. package/packages/agent-gaslight/dist/ingest.js +486 -0
  22. package/packages/agent-gaslight/dist/run.js +1 -1
  23. package/packages/agent-gaslight/dist/types.d.ts +41 -6
  24. package/packages/agent-harness/dist/loader/run.js +6 -21
  25. package/packages/agent-script/dist/cli.d.ts +2 -3
  26. package/packages/agent-script/dist/cli.js +70 -36
  27. package/packages/agent-script/dist/example-runner.d.ts +2 -3
  28. package/packages/agent-script/dist/example-runner.js +69 -56
  29. package/packages/agent-script/dist/interp/exceptions.js +1 -1
  30. package/packages/agent-script/dist/interp/globals/object-array.d.ts +1 -1
  31. package/packages/agent-script/dist/interp/globals/object-array.js +39 -20
  32. package/packages/agent-script/dist/interp/host-bridge.js +1 -1
  33. package/packages/agent-script/dist/interp/interpreter.js +83 -17
  34. package/packages/agent-script/dist/interp/methods/array.js +25 -2
  35. package/packages/agent-script/dist/interp/methods/regex.js +1 -1
  36. package/packages/agent-script/dist/interp/promise-tracker.d.ts +16 -0
  37. package/packages/agent-script/dist/interp/promise-tracker.js +58 -0
  38. package/packages/agent-script/dist/interp/promise.js +38 -7
  39. package/packages/agent-script/dist/interp/scope.d.ts +1 -0
  40. package/packages/agent-script/dist/interp/scope.js +3 -0
  41. package/packages/agent-script/dist/interp/values.js +2 -0
  42. package/packages/agent-script/dist/lint/index.d.ts +2 -0
  43. package/packages/agent-script/dist/lint/index.js +2 -0
  44. package/packages/agent-script/dist/lint/rules/AS-export-import-meta.d.ts +6 -1
  45. package/packages/agent-script/dist/lint/rules/AS-export-import-meta.js +33 -4
  46. package/packages/agent-script/dist/modules/agent.js +10 -1
  47. package/packages/agent-script/dist/modules/log.js +5 -1
  48. package/packages/agent-script/dist/modules/registry.js +9 -3
  49. package/packages/agent-script/dist/output-stream.d.ts +12 -0
  50. package/packages/agent-script/dist/output-stream.js +50 -0
  51. package/packages/agent-script/dist/parse/parser.d.ts +1 -1
  52. package/packages/agent-script/dist/parse/parser.js +151 -45
  53. package/packages/agent-script/dist/parse/tokenizer.js +26 -3
  54. package/packages/agent-script/dist/run.js +14 -3
  55. package/packages/agent-script/dist/runner/run-harness.js +28 -5
  56. package/packages/agent-traces/dist/collect.d.ts +4 -0
  57. package/packages/agent-traces/dist/collect.js +102 -0
  58. package/packages/agent-traces/dist/index.d.ts +4 -0
  59. package/packages/agent-traces/dist/index.js +3 -0
  60. package/packages/agent-traces/dist/jsonl.d.ts +2 -0
  61. package/packages/agent-traces/dist/jsonl.js +7 -0
  62. package/packages/agent-traces/dist/line-json.d.ts +4 -0
  63. package/packages/agent-traces/dist/line-json.js +40 -0
  64. package/packages/agent-traces/dist/readers/claude.d.ts +2 -0
  65. package/packages/agent-traces/dist/readers/claude.js +192 -0
  66. package/packages/agent-traces/dist/readers/codex.d.ts +2 -0
  67. package/packages/agent-traces/dist/readers/codex.js +266 -0
  68. package/packages/agent-traces/dist/readers/index.d.ts +5 -0
  69. package/packages/agent-traces/dist/readers/index.js +4 -0
  70. package/packages/agent-traces/dist/types.d.ts +84 -0
  71. package/packages/agent-traces/dist/types.js +1 -0
  72. package/packages/package-lint/dist/model.js +5 -1
  73. package/packages/package-lint/dist/source-imports.d.ts +11 -1
  74. package/packages/package-lint/dist/source-imports.js +30 -4
  75. package/packages/tiny-stdio-mcp-test-server/dist/cli.js +41 -0
  76. package/packages/tiny-stdio-mcp-test-server/dist/index.js +8 -0
@@ -86,15 +86,16 @@ export async function interpret(node, options = {}) {
86
86
  peakDataSize: { enumerable: false, value: 0, writable: true }
87
87
  });
88
88
  const activeLoopIterations = new Map();
89
+ const microtasks = [];
89
90
  hoistVarDeclarations(node, scope);
90
- const evaluation = await evaluateNode(node, {
91
+ const context = {
91
92
  budget,
92
93
  callStack: [],
93
94
  onYield: options.onYield,
94
95
  rootNode: node,
95
96
  scope,
96
97
  stats,
97
- microtasks: [],
98
+ microtasks,
98
99
  activeLoopIterations,
99
100
  restoredLoopIterations: new Map(Object.entries(options.snapshot?.loopIterations ?? {}).map(([nodeId, iteration]) => [
100
101
  Number(nodeId),
@@ -102,7 +103,9 @@ export async function interpret(node, options = {}) {
102
103
  ])),
103
104
  generatorResume: options.generatorResume,
104
105
  generatorYield: options.generatorYield
105
- });
106
+ };
107
+ const evaluation = await evaluateNode(node, context);
108
+ await drainMicrotasks(context);
106
109
  const snapshot = scope.snapshot();
107
110
  reconcileDataBudget(budget, stats, scope, "hasValue" in evaluation && evaluation.hasValue ? evaluation.value : undefined);
108
111
  if (evaluation.kind === "error") {
@@ -143,6 +146,21 @@ export async function interpret(node, options = {}) {
143
146
  };
144
147
  }
145
148
  export { Scope } from "./scope.js";
149
+ async function drainMicrotasks(context) {
150
+ let idleTurns = 0;
151
+ while (idleTurns < 20) {
152
+ const task = context.microtasks.shift();
153
+ if (task === undefined) {
154
+ idleTurns += 1;
155
+ await Promise.resolve();
156
+ continue;
157
+ }
158
+ idleTurns = 0;
159
+ context.budget.visitNode();
160
+ task();
161
+ await Promise.resolve();
162
+ }
163
+ }
146
164
  async function evaluateNode(node, context) {
147
165
  context.budget.visitNode();
148
166
  context.stats.nodeVisits += 1;
@@ -225,7 +243,7 @@ async function evaluateArrayExpression(node, context) {
225
243
  if (!spreadValues.ok) {
226
244
  return spreadValues.result;
227
245
  }
228
- values.push(...spreadValues.value);
246
+ appendArrayValues(values, spreadValues.value);
229
247
  context.budget.allocateArrayLength(values.length);
230
248
  continue;
231
249
  }
@@ -263,6 +281,9 @@ async function evaluateObjectExpression(node, context) {
263
281
  if (value.kind !== "normal") {
264
282
  return value;
265
283
  }
284
+ if (isObjectPrototypeSetterProperty(property, key.value)) {
285
+ continue;
286
+ }
266
287
  defineSandboxProperty(object, String(key.value), value.value);
267
288
  }
268
289
  return {
@@ -271,6 +292,9 @@ async function evaluateObjectExpression(node, context) {
271
292
  value: object
272
293
  };
273
294
  }
295
+ function isObjectPrototypeSetterProperty(property, key) {
296
+ return !property.computed && !property.shorthand && key === "__proto__";
297
+ }
274
298
  async function evaluateTemplateLiteral(node, context) {
275
299
  let value = context.budget.allocateString(node.quasis[0]?.value.cooked ?? "");
276
300
  for (let index = 0; index < node.expressions.length; index += 1) {
@@ -326,7 +350,9 @@ async function evaluateTemplateExpressionValues(node, context) {
326
350
  }
327
351
  function createTaggedTemplateStrings(node, context) {
328
352
  context.budget.allocateArrayLength(node.quasis.length);
329
- const strings = node.quasis.map((quasi) => context.budget.allocateString(quasi.value.cooked));
353
+ const strings = node.quasis.map((quasi) => quasi.value.cooked === undefined
354
+ ? undefined
355
+ : context.budget.allocateString(quasi.value.cooked));
330
356
  context.budget.allocateArrayLength(node.quasis.length);
331
357
  const raw = node.quasis.map((quasi) => context.budget.allocateString(quasi.value.raw));
332
358
  Object.defineProperty(strings, "raw", {
@@ -565,7 +591,7 @@ async function evaluateIdentifier(node, context) {
565
591
  if (!binding.found) {
566
592
  return {
567
593
  kind: "error",
568
- error: createError("UNBOUND_IDENTIFIER", node, `Identifier '${node.name}' is not defined.`)
594
+ error: createError("UNBOUND_IDENTIFIER", node, `Identifier '${node.name}' is not defined.`, context.callStack)
569
595
  };
570
596
  }
571
597
  return {
@@ -609,6 +635,12 @@ async function evaluateVariableDeclaration(node, context) {
609
635
  predeclareDeclarationBindings(node, context.scope);
610
636
  }
611
637
  for (const declarator of node.declarations) {
638
+ if (node.kind === "var" &&
639
+ declarator.init === undefined &&
640
+ declarator.id.type === "Identifier" &&
641
+ context.scope.lookup(declarator.id.name).found) {
642
+ continue;
643
+ }
612
644
  const restoredValue = declarator.id.type === "Identifier"
613
645
  ? context.scope.consumeRestoredBinding(declarator.id.name)
614
646
  : { found: false };
@@ -774,11 +806,21 @@ function predeclareStatementListBindings(statements, context) {
774
806
  for (const statement of statements) {
775
807
  if (statement.type === "FunctionDeclaration") {
776
808
  const name = statement.id.name;
777
- if (names.has(name) || scope.hasOwnBinding(name)) {
809
+ if (names.has(name)) {
810
+ throw new Error(`Cannot redeclare binding '${name}' in the same scope.`);
811
+ }
812
+ const closure = createInterpretedClosure(statement, context, evaluateNode);
813
+ const ownBindingKind = scope.getOwnBindingKind(name);
814
+ if (ownBindingKind === "var") {
815
+ names.add(name);
816
+ scope.assign(name, closure);
817
+ continue;
818
+ }
819
+ if (ownBindingKind !== undefined) {
778
820
  throw new Error(`Cannot redeclare binding '${name}' in the same scope.`);
779
821
  }
780
822
  names.add(name);
781
- scope.declare(name, "const", createInterpretedClosure(statement, context, evaluateNode));
823
+ scope.declare(name, "const", closure);
782
824
  continue;
783
825
  }
784
826
  if (statement.type !== "VariableDeclaration" || statement.kind === "var") {
@@ -1380,7 +1422,7 @@ async function evaluateUnaryExpression(node, context) {
1380
1422
  return {
1381
1423
  kind: "normal",
1382
1424
  hasValue: true,
1383
- value: applyUnaryOperator(node.operator, argument.value)
1425
+ value: await applyUnaryOperator(node.operator, argument.value, context)
1384
1426
  };
1385
1427
  }
1386
1428
  async function evaluateDeleteExpression(node, context) {
@@ -1634,8 +1676,9 @@ function getConstructorName(callee) {
1634
1676
  function formatStackFrame(node, name) {
1635
1677
  return ` at ${name ?? "<anonymous>"} (line ${node.span.start.line}, column ${node.span.start.column})`;
1636
1678
  }
1637
- function createError(code, node, message) {
1679
+ function createError(code, node, message, stackFrames = []) {
1638
1680
  const name = code === "UNBOUND_IDENTIFIER" ? "ReferenceError" : "Error";
1681
+ const stack = [...stackFrames, formatStackFrame(node, undefined)];
1639
1682
  return {
1640
1683
  code,
1641
1684
  message,
@@ -1643,7 +1686,7 @@ function createError(code, node, message) {
1643
1686
  nodeId: node.nodeId,
1644
1687
  nodeType: node.type,
1645
1688
  span: node.span,
1646
- stack: formatErrorStack(name, message, [formatStackFrame(node, undefined)])
1689
+ stack: formatErrorStack(name, message, stack)
1647
1690
  };
1648
1691
  }
1649
1692
  function attachFatalSandboxErrorContext(error, node, stackFrames) {
@@ -1900,7 +1943,7 @@ async function evaluateSetMethodCall(node, target, methodName, context) {
1900
1943
  leaveCall();
1901
1944
  }
1902
1945
  }
1903
- function applyUnaryOperator(operator, value) {
1946
+ async function applyUnaryOperator(operator, value, context) {
1904
1947
  switch (operator) {
1905
1948
  case "!":
1906
1949
  return !value;
@@ -1911,11 +1954,11 @@ function applyUnaryOperator(operator, value) {
1911
1954
  case "void":
1912
1955
  return undefined;
1913
1956
  case "+":
1914
- return toNumber(value);
1957
+ return toNumber(await toNumericPrimitive(value, context));
1915
1958
  case "-":
1916
- return -toNumber(value);
1959
+ return -toNumber(await toNumericPrimitive(value, context));
1917
1960
  case "~":
1918
- return ~toNumber(value);
1961
+ return ~toNumber(await toNumericPrimitive(value, context));
1919
1962
  }
1920
1963
  }
1921
1964
  function describeTypeofValue(value) {
@@ -1928,7 +1971,7 @@ function describeTypeofValue(value) {
1928
1971
  return typeof value;
1929
1972
  }
1930
1973
  function isTruthy(value) {
1931
- return applyUnaryOperator("!", value) === false;
1974
+ return Boolean(value);
1932
1975
  }
1933
1976
  function applyBinaryOperator(node, left, right, context) {
1934
1977
  switch (node.operator) {
@@ -2112,6 +2155,24 @@ function toPrimitive(value) {
2112
2155
  }
2113
2156
  return toString(value);
2114
2157
  }
2158
+ async function toNumericPrimitive(value, context) {
2159
+ if (isPrimitiveCoercionType(getCoercionType(value))) {
2160
+ return value;
2161
+ }
2162
+ if (isIndexableSandboxValue(value)) {
2163
+ for (const methodName of ["valueOf", "toString"]) {
2164
+ const method = getMemberValue(value, methodName, context);
2165
+ if (!isSandboxClosure(method)) {
2166
+ continue;
2167
+ }
2168
+ const result = await invokeSandboxClosure(method, [], context, context.callStack, undefined, value);
2169
+ if (isPrimitiveCoercionType(getCoercionType(result))) {
2170
+ return result;
2171
+ }
2172
+ }
2173
+ }
2174
+ return toString(value);
2175
+ }
2115
2176
  function toNumber(value) {
2116
2177
  if (typeof value === "number") {
2117
2178
  return value;
@@ -2144,6 +2205,11 @@ function toString(value) {
2144
2205
  function isIndexableSandboxValue(value) {
2145
2206
  return Array.isArray(value) || isPlainSandboxObject(value);
2146
2207
  }
2208
+ function appendArrayValues(target, values) {
2209
+ for (const value of values) {
2210
+ target.push(value);
2211
+ }
2212
+ }
2147
2213
  function isPlainSandboxObject(value) {
2148
2214
  return (typeof value === "object" &&
2149
2215
  value !== null &&
@@ -2287,7 +2353,7 @@ async function evaluateCallArguments(args, context) {
2287
2353
  if (!spreadValues.ok) {
2288
2354
  return spreadValues;
2289
2355
  }
2290
- values.push(...spreadValues.value);
2356
+ appendArrayValues(values, spreadValues.value);
2291
2357
  context.budget.allocateArrayLength(values.length);
2292
2358
  continue;
2293
2359
  }
@@ -180,7 +180,8 @@ async function callArrayMethodUnlocked(value, methodName, args, options, stack)
180
180
  return budgetProducedValue(result, options.budget);
181
181
  }
182
182
  case "push": {
183
- const nextLength = value.push(...args);
183
+ appendArrayValues(value, args);
184
+ const nextLength = value.length;
184
185
  budgetProducedValue(value, options.budget);
185
186
  return nextLength;
186
187
  }
@@ -189,12 +190,34 @@ async function callArrayMethodUnlocked(value, methodName, args, options, stack)
189
190
  case "shift":
190
191
  return budgetProducedValue(value.shift(), options.budget);
191
192
  case "unshift": {
192
- const nextLength = value.unshift(...args);
193
+ prependArrayValues(value, args);
194
+ const nextLength = value.length;
193
195
  budgetProducedValue(value, options.budget);
194
196
  return nextLength;
195
197
  }
196
198
  }
197
199
  }
200
+ function appendArrayValues(target, values) {
201
+ for (const value of values) {
202
+ target.push(value);
203
+ }
204
+ }
205
+ function prependArrayValues(target, values) {
206
+ const originalLength = target.length;
207
+ target.length = originalLength + values.length;
208
+ for (let index = originalLength - 1; index >= 0; index -= 1) {
209
+ const targetIndex = index + values.length;
210
+ if (Object.hasOwn(target, index)) {
211
+ target[targetIndex] = target[index];
212
+ }
213
+ else {
214
+ delete target[targetIndex];
215
+ }
216
+ }
217
+ for (let index = 0; index < values.length; index += 1) {
218
+ target[index] = values[index];
219
+ }
220
+ }
198
221
  function isCallbackArrayMethod(methodName) {
199
222
  return (methodName === "map" ||
200
223
  methodName === "filter" ||
@@ -39,6 +39,6 @@ export function toMatchArray(match, input) {
39
39
  return null;
40
40
  }
41
41
  const result = [match.text, ...match.captures];
42
- Object.assign(result, { index: match.index, input });
42
+ Object.assign(result, { groups: undefined, index: match.index, input });
43
43
  return result;
44
44
  }
@@ -0,0 +1,16 @@
1
+ import type { ErrorSourceSpan } from "../error/shape.js";
2
+ import type { SandboxPromise, SandboxValue } from "./values.js";
3
+ export declare class SandboxPromiseRejectionTracker {
4
+ private readonly records;
5
+ private readonly recordsByPromise;
6
+ observe(promise: SandboxPromise): void;
7
+ track(promise: SandboxPromise): void;
8
+ findUnhandledRejection(): Promise<{
9
+ reason: SandboxValue | undefined;
10
+ span: ErrorSourceSpan | undefined;
11
+ } | undefined>;
12
+ }
13
+ export declare function createSandboxPromiseRejectionTracker(): SandboxPromiseRejectionTracker;
14
+ export declare function observeSandboxPromise(promise: SandboxPromise): void;
15
+ export declare function trackSandboxPromise(promise: SandboxPromise): void;
16
+ export declare function withSandboxPromiseRejectionTracker<TResult>(tracker: SandboxPromiseRejectionTracker, callback: () => TResult): TResult;
@@ -0,0 +1,58 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ export class SandboxPromiseRejectionTracker {
3
+ records = new Set();
4
+ recordsByPromise = new WeakMap();
5
+ observe(promise) {
6
+ const record = this.recordsByPromise.get(promise);
7
+ if (record !== undefined) {
8
+ record.observed = true;
9
+ }
10
+ }
11
+ track(promise) {
12
+ if (this.recordsByPromise.has(promise)) {
13
+ return;
14
+ }
15
+ const record = {
16
+ observed: false,
17
+ promise,
18
+ rejected: false
19
+ };
20
+ this.records.add(record);
21
+ this.recordsByPromise.set(promise, record);
22
+ promise.promise.then(() => undefined, (reason) => {
23
+ record.rejected = true;
24
+ record.rejectionReason = reason;
25
+ });
26
+ promise.promise.catch(() => undefined);
27
+ }
28
+ async findUnhandledRejection() {
29
+ await flushPromiseJobs();
30
+ for (const record of this.records) {
31
+ if (record.rejected && !record.observed) {
32
+ return {
33
+ reason: record.rejectionReason,
34
+ span: record.promise.span
35
+ };
36
+ }
37
+ }
38
+ return undefined;
39
+ }
40
+ }
41
+ const activePromiseTracker = new AsyncLocalStorage();
42
+ export function createSandboxPromiseRejectionTracker() {
43
+ return new SandboxPromiseRejectionTracker();
44
+ }
45
+ export function observeSandboxPromise(promise) {
46
+ activePromiseTracker.getStore()?.observe(promise);
47
+ }
48
+ export function trackSandboxPromise(promise) {
49
+ activePromiseTracker.getStore()?.track(promise);
50
+ }
51
+ export function withSandboxPromiseRejectionTracker(tracker, callback) {
52
+ return activePromiseTracker.run(tracker, callback);
53
+ }
54
+ async function flushPromiseJobs() {
55
+ for (let index = 0; index < 20; index += 1) {
56
+ await Promise.resolve();
57
+ }
58
+ }
@@ -1,4 +1,5 @@
1
1
  import { SandboxError } from "./budget.js";
2
+ import { observeSandboxPromise } from "./promise-tracker.js";
2
3
  import { createSandboxClosure, createSandboxPromise, isSandboxClosure, isSandboxPromise } from "./values.js";
3
4
  export function createPromiseGlobals(options) {
4
5
  return {
@@ -54,21 +55,33 @@ export function getPromiseMember(target, property, budget, enqueue = (task) => P
54
55
  if (property === "then") {
55
56
  return createSandboxClosure({
56
57
  async: true,
57
- call: ([onFulfilled, onRejected]) => createSandboxPromise(enqueue(() => target.promise.then((value) => runPromiseReaction(onFulfilled, value, "fulfilled", budget), (reason) => runPromiseReaction(onRejected, reason, "rejected", budget)))),
58
+ call: ([onFulfilled, onRejected]) => {
59
+ observeSandboxPromise(target);
60
+ const chained = createSandboxPromise(enqueue(() => target.promise.then((value) => runPromiseReaction(onFulfilled, value, "fulfilled", budget, chained), (reason) => runPromiseReaction(onRejected, reason, "rejected", budget, chained))));
61
+ return chained;
62
+ },
58
63
  name: "then"
59
64
  });
60
65
  }
61
66
  if (property === "catch") {
62
67
  return createSandboxClosure({
63
68
  async: true,
64
- call: ([onRejected]) => createSandboxPromise(enqueue(() => target.promise.then((value) => runPromiseReaction(undefined, value, "fulfilled", budget), (reason) => runPromiseReaction(onRejected, reason, "rejected", budget)))),
69
+ call: ([onRejected]) => {
70
+ observeSandboxPromise(target);
71
+ const chained = createSandboxPromise(enqueue(() => target.promise.then((value) => runPromiseReaction(undefined, value, "fulfilled", budget, chained), (reason) => runPromiseReaction(onRejected, reason, "rejected", budget, chained))));
72
+ return chained;
73
+ },
65
74
  name: "catch"
66
75
  });
67
76
  }
68
77
  if (property === "finally") {
69
78
  return createSandboxClosure({
70
79
  async: true,
71
- call: ([onFinally]) => createSandboxPromise(enqueue(() => target.promise.then((value) => runPromiseFinally(onFinally, value, "fulfilled", budget), (reason) => runPromiseFinally(onFinally, reason, "rejected", budget)))),
80
+ call: ([onFinally]) => {
81
+ observeSandboxPromise(target);
82
+ const chained = createSandboxPromise(enqueue(() => target.promise.then((value) => runPromiseFinally(onFinally, value, "fulfilled", budget, chained), (reason) => runPromiseFinally(onFinally, reason, "rejected", budget, chained))));
83
+ return chained;
84
+ },
72
85
  name: "finally"
73
86
  });
74
87
  }
@@ -140,6 +153,7 @@ function resolveSandboxValueNow(value, options, seenThenables) {
140
153
  return Promise.resolve(value).then((resolved) => resolveSandboxValueNow(resolved, options, seenThenables), (reason) => Promise.reject(budgetIfNeeded(reason, options.budget)));
141
154
  }
142
155
  if (isSandboxPromise(value)) {
156
+ observeSandboxPromise(value);
143
157
  return value.promise.then((resolved) => {
144
158
  value.hostCallJournal?.consume(value.hostCall);
145
159
  return resolveSandboxValueNow(resolved, options, seenThenables);
@@ -226,30 +240,47 @@ function resolveThenable(value, then, options, seenThenables) {
226
240
  }
227
241
  }).then((resolved) => budgetIfNeeded(resolved, options.budget));
228
242
  }
229
- function runPromiseReaction(handler, value, state, budget) {
243
+ function runPromiseReaction(handler, value, state, budget, self) {
230
244
  if (!isSandboxClosure(handler)) {
231
245
  return state === "fulfilled"
232
246
  ? Promise.resolve(value)
233
247
  : Promise.reject(budgetSandboxValue(value, budget));
234
248
  }
235
249
  try {
236
- return resolveSandboxValue(handler.call([value]), { budget });
250
+ const result = handler.call([value]);
251
+ return resolveReactionResult(result, budget, self);
237
252
  }
238
253
  catch (error) {
239
254
  return Promise.reject(error);
240
255
  }
241
256
  }
242
- function runPromiseFinally(handler, value, state, budget) {
257
+ function runPromiseFinally(handler, value, state, budget, self) {
243
258
  if (!isSandboxClosure(handler)) {
244
259
  return runPromiseReaction(undefined, value, state, budget);
245
260
  }
246
261
  try {
247
- return resolveSandboxValue(handler.call([]), { budget }).then(() => runPromiseReaction(undefined, value, state, budget));
262
+ const result = handler.call([]);
263
+ return resolveReactionResult(result, budget, self).then(() => runPromiseReaction(undefined, value, state, budget));
248
264
  }
249
265
  catch (error) {
250
266
  return Promise.reject(error);
251
267
  }
252
268
  }
269
+ function resolveReactionResult(result, budget, self) {
270
+ return Promise.resolve(result).then((resolved) => {
271
+ if (isSelfResolution(resolved, self)) {
272
+ return Promise.reject({
273
+ message: "Promise cannot resolve to itself.",
274
+ name: "TypeError"
275
+ });
276
+ }
277
+ return resolveSandboxValue(resolved, { budget });
278
+ });
279
+ }
280
+ function isSelfResolution(result, self) {
281
+ return (self !== undefined &&
282
+ (result === self || (isSandboxPromise(result) && result.promise === self.promise)));
283
+ }
253
284
  function getThenable(value) {
254
285
  if (typeof value !== "object" ||
255
286
  value === null ||
@@ -25,6 +25,7 @@ export declare class Scope {
25
25
  found: false;
26
26
  };
27
27
  hasOwnBinding(name: string): boolean;
28
+ getOwnBindingKind(name: string): VariableDeclarationKind | undefined;
28
29
  isFunctionBoundary(): boolean;
29
30
  iterationChild(names: readonly string[]): Scope;
30
31
  lookupImportMeta(): InterpreterValue;
@@ -39,6 +39,9 @@ export class Scope {
39
39
  hasOwnBinding(name) {
40
40
  return this.#bindings.has(name);
41
41
  }
42
+ getOwnBindingKind(name) {
43
+ return this.#bindings.get(name)?.kind;
44
+ }
42
45
  isFunctionBoundary() {
43
46
  return this.options.functionBoundary === true;
44
47
  }
@@ -1,5 +1,6 @@
1
1
  import { bindOtelSpan, getBoundOtelSpan } from "../observability/otel.js";
2
2
  import { SandboxError } from "./budget.js";
3
+ import { trackSandboxPromise } from "./promise-tracker.js";
3
4
  import { parseRegex } from "./regex/parse.js";
4
5
  import { assertSandboxDataDepth } from "../graph-depth.js";
5
6
  const sandboxClosureBrand = Symbol("SandboxClosure");
@@ -57,6 +58,7 @@ export function createSandboxPromise(promise, metadata = {}) {
57
58
  value: metadata.hostCallJournal
58
59
  });
59
60
  }
61
+ trackSandboxPromise(sandboxPromise);
60
62
  return Object.freeze(sandboxPromise);
61
63
  }
62
64
  export function createSandboxGenerator(channel, metadata = undefined) {
@@ -1,3 +1,4 @@
1
+ import type { DefaultExportSignature } from "./rules/AS-export-import-meta.js";
1
2
  import { type SourceSpan } from "../parse/parser.js";
2
3
  import type { Modules } from "./rules/module-registry.js";
3
4
  export type Diagnostic = {
@@ -18,6 +19,7 @@ export type Fix = {
18
19
  export type LintOptions = {
19
20
  allowedExportNames?: readonly string[];
20
21
  allowedGlobals?: readonly string[];
22
+ defaultExport?: DefaultExportSignature;
21
23
  fix?: boolean;
22
24
  filename?: string;
23
25
  largeLiteralThreshold?: number;
@@ -77,9 +77,11 @@ const KNOWN_DIAGNOSTIC_CODES = new Set([
77
77
  "AS015",
78
78
  "AS-ASYNC-NOT-NEEDED",
79
79
  "AS-AWAIT-NON-PROMISE",
80
+ "AS-EXPORT-DEFAULT-MISSING",
80
81
  "AS-DESTRUCTURE-NULL-DEFAULT",
81
82
  "AS-EXPORT-DEFAULT-MULTIPLE",
82
83
  "AS-EXPORT-DEFAULT-NOT-ARROW",
84
+ "AS-EXPORT-DEFAULT-SIGNATURE",
83
85
  "AS-EXPORT-IMPORT-META",
84
86
  "AS-EXPORT-UNKNOWN",
85
87
  "AS-FLOATING-PROMISE",
@@ -1,5 +1,5 @@
1
1
  import { type SourceSpan } from "../../parse/parser.js";
2
- type DiagnosticCode = "AS-EXPORT-DEFAULT-MULTIPLE" | "AS-EXPORT-DEFAULT-NOT-ARROW" | "AS-EXPORT-UNKNOWN" | "AS-IMPORT-META-ASSIGN" | "AS-RETURN-AT-TOP";
2
+ type DiagnosticCode = "AS-EXPORT-DEFAULT-MISSING" | "AS-EXPORT-DEFAULT-MULTIPLE" | "AS-EXPORT-DEFAULT-NOT-ARROW" | "AS-EXPORT-DEFAULT-SIGNATURE" | "AS-EXPORT-UNKNOWN" | "AS-IMPORT-META-ASSIGN" | "AS-RETURN-AT-TOP";
3
3
  export type Diagnostic = {
4
4
  code: DiagnosticCode;
5
5
  severity: "error" | "warning";
@@ -9,8 +9,13 @@ export type Diagnostic = {
9
9
  column: number;
10
10
  span: SourceSpan;
11
11
  };
12
+ export type DefaultExportSignature = {
13
+ parameters?: readonly string[];
14
+ required?: boolean;
15
+ };
12
16
  export declare function AS_EXPORT_IMPORT_META(source: string, options?: {
13
17
  allowedExportNames?: readonly string[];
18
+ defaultExport?: DefaultExportSignature;
14
19
  filename?: string;
15
20
  }): Diagnostic[];
16
21
  export {};
@@ -1,14 +1,16 @@
1
1
  import { parseModule } from "../../parse/parser.js";
2
2
  export function AS_EXPORT_IMPORT_META(source, options = {}) {
3
- return new Scanner(options.filename ?? "<input>", new Set(options.allowedExportNames ?? [])).scan(source);
3
+ return new Scanner(options.filename ?? "<input>", new Set(options.allowedExportNames ?? []), options.defaultExport).scan(source);
4
4
  }
5
5
  class Scanner {
6
6
  filename;
7
7
  allowedExportNames;
8
+ defaultExport;
8
9
  diagnostics = [];
9
- constructor(filename, allowedExportNames) {
10
+ constructor(filename, allowedExportNames, defaultExport) {
10
11
  this.filename = filename;
11
12
  this.allowedExportNames = allowedExportNames;
13
+ this.defaultExport = defaultExport;
12
14
  }
13
15
  scan(source) {
14
16
  this.visitModule(parseModule(source, this.filename));
@@ -17,6 +19,9 @@ class Scanner {
17
19
  visitModule(node) {
18
20
  const defaultExports = node.body.filter((statement) => statement.type === "ExportDefaultDeclaration");
19
21
  const hasDefaultExport = defaultExports.length > 0;
22
+ if (!hasDefaultExport && this.defaultExport?.required === true) {
23
+ this.pushDiagnostic("AS-EXPORT-DEFAULT-MISSING", "error", "Module must export a default entry point.", node.span);
24
+ }
20
25
  for (const [index, statement] of defaultExports.entries()) {
21
26
  if (index > 0) {
22
27
  this.pushDiagnostic("AS-EXPORT-DEFAULT-MULTIPLE", "error", "Module contains more than one export default declaration.", statement.span);
@@ -35,8 +40,11 @@ class Scanner {
35
40
  this.visitExportNamedDeclaration(node.declaration);
36
41
  return;
37
42
  case "ExportDefaultDeclaration":
38
- if (node.declaration.type !== "ArrowFunctionExpression") {
39
- this.pushDiagnostic("AS-EXPORT-DEFAULT-NOT-ARROW", "error", "Export default initializer must be an arrow expression.", node.declaration.span);
43
+ if (!isDefaultExportCallable(node.declaration)) {
44
+ this.pushDiagnostic("AS-EXPORT-DEFAULT-NOT-ARROW", "error", "Export default initializer must be an arrow or function expression.", node.declaration.span);
45
+ }
46
+ else {
47
+ this.visitDefaultExportSignature(node.declaration);
40
48
  }
41
49
  this.visitExpression(node.declaration);
42
50
  return;
@@ -89,6 +97,15 @@ class Scanner {
89
97
  }
90
98
  this.visitVariableDeclaration(node);
91
99
  }
100
+ visitDefaultExportSignature(node) {
101
+ const parameters = this.defaultExport?.parameters;
102
+ if (parameters === undefined) {
103
+ return;
104
+ }
105
+ if (!hasParameterNames(node, parameters)) {
106
+ this.pushDiagnostic("AS-EXPORT-DEFAULT-SIGNATURE", "error", `Default export must declare signature (${parameters.join(", ")}).`, node.span);
107
+ }
108
+ }
92
109
  visitIfStatement(node) {
93
110
  this.visitExpression(node.test);
94
111
  this.visitStatement(node.consequent);
@@ -162,6 +179,9 @@ class Scanner {
162
179
  this.visitExpression(node.body);
163
180
  }
164
181
  return;
182
+ case "FunctionExpression":
183
+ this.visitStatement(node.body);
184
+ return;
165
185
  case "AwaitExpression":
166
186
  this.visitExpression(node.argument);
167
187
  return;
@@ -314,6 +334,15 @@ class Scanner {
314
334
  });
315
335
  }
316
336
  }
337
+ function isDefaultExportCallable(node) {
338
+ return node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression";
339
+ }
340
+ function hasParameterNames(node, names) {
341
+ if (node.params.length !== names.length) {
342
+ return false;
343
+ }
344
+ return node.params.every((param, index) => param.type === "Identifier" && param.name === names[index]);
345
+ }
317
346
  function isImportMetaReference(node) {
318
347
  if (node.type === "MetaProperty") {
319
348
  return true;
@@ -147,10 +147,11 @@ async function runSpawnAttempt(spawnAgent, input, onEvent, spawnId) {
147
147
  }
148
148
  function runObservedSpawn(moduleSink, input, operation) {
149
149
  const otelSink = input.otelSink ?? moduleSink ?? getActiveOtelSink();
150
+ const cwd = input.cwd ?? readCurrentWorkingDirectory();
150
151
  const span = safeStartSpan(otelSink, "agent.spawn", {
151
152
  agent: input.agent,
152
153
  mode: input.mode ?? "yolo",
153
- cwd: input.cwd ?? process.cwd()
154
+ cwd
154
155
  });
155
156
  const deactivateSpan = activateOtelSpan(span);
156
157
  safeAddEvent(span, "prompt", { prompt: input.prompt });
@@ -176,6 +177,14 @@ function runObservedSpawn(moduleSink, input, operation) {
176
177
  bindOtelSpan(promise, span);
177
178
  return promise;
178
179
  }
180
+ function readCurrentWorkingDirectory() {
181
+ try {
182
+ return process.cwd();
183
+ }
184
+ catch (error) {
185
+ throw new Error(`Unable to resolve current working directory: ${formatSpawnError(error)}`);
186
+ }
187
+ }
179
188
  async function runSpawnRetry(spawnAgent, input, retryOptions, onEvent, spawnId, throwOnResultFailure = true) {
180
189
  const task = resolveTaskLabel(input);
181
190
  const startedAt = Date.now();