@namzu/sdk 35.0.0 → 36.0.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 (82) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/provider/token-budget.d.ts.map +1 -1
  3. package/dist/provider/token-budget.js +56 -8
  4. package/dist/provider/token-budget.js.map +1 -1
  5. package/dist/public-runtime.d.ts +2 -2
  6. package/dist/public-runtime.d.ts.map +1 -1
  7. package/dist/public-runtime.js +1 -1
  8. package/dist/public-runtime.js.map +1 -1
  9. package/dist/runtime/query/executor.d.ts +1 -0
  10. package/dist/runtime/query/executor.d.ts.map +1 -1
  11. package/dist/runtime/query/executor.js +50 -10
  12. package/dist/runtime/query/executor.js.map +1 -1
  13. package/dist/runtime/query/index.d.ts +7 -0
  14. package/dist/runtime/query/index.d.ts.map +1 -1
  15. package/dist/runtime/query/index.js +1 -0
  16. package/dist/runtime/query/index.js.map +1 -1
  17. package/dist/runtime/query/iteration/index.d.ts +3 -3
  18. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  19. package/dist/runtime/query/iteration/index.js +31 -6
  20. package/dist/runtime/query/iteration/index.js.map +1 -1
  21. package/dist/runtime/query/iteration/phases/context.d.ts +2 -0
  22. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  23. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  24. package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
  25. package/dist/runtime/query/iteration/stream-turn.js +10 -5
  26. package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
  27. package/dist/runtime/query/prompt.d.ts.map +1 -1
  28. package/dist/runtime/query/prompt.js +14 -4
  29. package/dist/runtime/query/prompt.js.map +1 -1
  30. package/dist/sandbox/file-walk-program.d.ts +3 -0
  31. package/dist/sandbox/file-walk-program.d.ts.map +1 -0
  32. package/dist/sandbox/file-walk-program.js +94 -0
  33. package/dist/sandbox/file-walk-program.js.map +1 -0
  34. package/dist/sandbox/file-walk.d.ts +12 -0
  35. package/dist/sandbox/file-walk.d.ts.map +1 -0
  36. package/dist/sandbox/file-walk.js +429 -0
  37. package/dist/sandbox/file-walk.js.map +1 -0
  38. package/dist/sandbox/index.d.ts +2 -0
  39. package/dist/sandbox/index.d.ts.map +1 -1
  40. package/dist/sandbox/index.js +1 -0
  41. package/dist/sandbox/index.js.map +1 -1
  42. package/dist/sandbox/provider/local.d.ts.map +1 -1
  43. package/dist/sandbox/provider/local.js +9 -0
  44. package/dist/sandbox/provider/local.js.map +1 -1
  45. package/dist/scheduler/completion-inbox.d.ts +3 -2
  46. package/dist/scheduler/completion-inbox.d.ts.map +1 -1
  47. package/dist/scheduler/completion-inbox.js +29 -15
  48. package/dist/scheduler/completion-inbox.js.map +1 -1
  49. package/dist/tools/builtins/bash.d.ts.map +1 -1
  50. package/dist/tools/builtins/bash.js +215 -59
  51. package/dist/tools/builtins/bash.js.map +1 -1
  52. package/dist/tools/builtins/glob.d.ts +2 -1
  53. package/dist/tools/builtins/glob.d.ts.map +1 -1
  54. package/dist/tools/builtins/glob.js +95 -103
  55. package/dist/tools/builtins/glob.js.map +1 -1
  56. package/dist/tools/builtins/grep.d.ts.map +1 -1
  57. package/dist/tools/builtins/grep.js +155 -111
  58. package/dist/tools/builtins/grep.js.map +1 -1
  59. package/dist/tools/builtins/ls.js +2 -2
  60. package/dist/tools/builtins/ls.js.map +1 -1
  61. package/dist/types/sandbox/index.d.ts +20 -0
  62. package/dist/types/sandbox/index.d.ts.map +1 -1
  63. package/dist/types/sandbox/index.js.map +1 -1
  64. package/package.json +6 -1
  65. package/src/provider/token-budget.ts +52 -8
  66. package/src/public-runtime.ts +2 -1
  67. package/src/runtime/query/executor.ts +54 -14
  68. package/src/runtime/query/index.ts +8 -0
  69. package/src/runtime/query/iteration/index.ts +29 -9
  70. package/src/runtime/query/iteration/phases/context.ts +2 -0
  71. package/src/runtime/query/iteration/stream-turn.ts +9 -5
  72. package/src/runtime/query/prompt.ts +21 -4
  73. package/src/sandbox/file-walk-program.ts +93 -0
  74. package/src/sandbox/file-walk.ts +463 -0
  75. package/src/sandbox/index.ts +2 -0
  76. package/src/sandbox/provider/local.ts +13 -0
  77. package/src/scheduler/completion-inbox.ts +29 -19
  78. package/src/tools/builtins/bash.ts +230 -58
  79. package/src/tools/builtins/glob.ts +104 -122
  80. package/src/tools/builtins/grep.ts +166 -132
  81. package/src/tools/builtins/ls.ts +2 -2
  82. package/src/types/sandbox/index.ts +21 -0
@@ -649,8 +649,9 @@ export {
649
649
  LocalSandboxProvider,
650
650
  missingIsolation,
651
651
  SandboxProviderFactory,
652
+ walkFilesViaExec,
652
653
  } from './sandbox/index.js'
653
- export type { LocalSandboxProviderOptions } from './sandbox/index.js'
654
+ export type { LocalSandboxProviderOptions, SandboxFileWalkExec } from './sandbox/index.js'
654
655
 
655
656
  // The classified provider-failure surface: a driver states what went wrong
656
657
  // first-hand, and the run boundary reads it to choose between a pause and a
@@ -1279,6 +1279,9 @@ export class ToolExecutor {
1279
1279
  settleProgress: () => Promise<void>,
1280
1280
  preparedCall?: PreparedDirectCall,
1281
1281
  ): Promise<ToolCallOutcome> {
1282
+ if (this.config.abortSignal.aborted) {
1283
+ return this.recordCancelledBeforeExecution(toolCall.id, toolCall.function.name, {})
1284
+ }
1282
1285
  if (preparedCall?.kind === 'synthetic') {
1283
1286
  return this.recordSyntheticPreparation(preparedCall)
1284
1287
  }
@@ -1376,7 +1379,15 @@ export class ToolExecutor {
1376
1379
 
1377
1380
  input = resolved.input
1378
1381
 
1379
- const preOutcome = await this.runPreToolHook(toolName, input)
1382
+ let preOutcome: PreToolHookOutcome
1383
+ try {
1384
+ preOutcome = await this.runPreToolHook(toolName, input)
1385
+ } catch (error) {
1386
+ if (!this.config.abortSignal.aborted) throw error
1387
+ // A later call's interrupted preparation must not reject the batch
1388
+ // that already holds an earlier call's settled side-effect receipt.
1389
+ return this.recordCancelledBeforeExecution(toolCall.id, toolName, input)
1390
+ }
1380
1391
  if (preOutcome.kind === 'skip' || preOutcome.kind === 'error') {
1381
1392
  return this.recordSyntheticHookOutcome(toolCall.id, toolName, preOutcome.input, preOutcome)
1382
1393
  }
@@ -1483,6 +1494,7 @@ export class ToolExecutor {
1483
1494
  ...this.config.toolRetryBackoff,
1484
1495
  }
1485
1496
  for (let attempt = 1; ; attempt++) {
1497
+ if (this.config.abortSignal.aborted) break
1486
1498
  // A missing file will not appear on the second attempt; burning
1487
1499
  // the budget on it only delays the error the model needs to see.
1488
1500
  const toolWants = !result.success && result.retryable === true
@@ -1606,7 +1618,7 @@ export class ToolExecutor {
1606
1618
 
1607
1619
  if (this.workingStateManager) {
1608
1620
  extractFromToolResult(this.workingStateManager, toolName, output, effectiveIsError)
1609
- for (const pin of result.workingState ?? []) {
1621
+ for (const pin of this.config.abortSignal.aborted ? [] : (result.workingState ?? [])) {
1610
1622
  this.workingStateManager.pin(pin.key, pin.text, toolName)
1611
1623
  }
1612
1624
  }
@@ -1623,7 +1635,7 @@ export class ToolExecutor {
1623
1635
  [NAMZU.RUN_ID]: this.config.runId,
1624
1636
  [GENAI.TOOL_NAME]: toolName,
1625
1637
  'namzu.duration_ms': durationMs,
1626
- 'exception.message': result.error ?? 'unknown',
1638
+ 'exception.message': postOverride ? output : (result.error ?? 'unknown'),
1627
1639
  })
1628
1640
  }
1629
1641
 
@@ -2369,17 +2381,33 @@ export class ToolExecutor {
2369
2381
  toolResult: ToolResult,
2370
2382
  ): Promise<{ override: PostToolOverride | null; retry: boolean }> {
2371
2383
  if (!this.config.pluginManager) return { override: null, retry: false }
2372
- const results = await this.config.pluginManager.executeHooks(
2373
- 'post_tool_use',
2374
- {
2375
- runId: this.config.runId,
2376
- toolName,
2377
- toolInput: input,
2378
- toolResult,
2379
- signal: this.config.abortSignal,
2380
- },
2381
- this.emitEvent,
2382
- )
2384
+ let results: PluginHookResult[]
2385
+ try {
2386
+ results = await this.config.pluginManager.executeHooks(
2387
+ 'post_tool_use',
2388
+ {
2389
+ runId: this.config.runId,
2390
+ toolName,
2391
+ toolInput: input,
2392
+ toolResult,
2393
+ signal: this.config.abortSignal,
2394
+ },
2395
+ this.emitEvent,
2396
+ )
2397
+ } catch (error) {
2398
+ if (!this.config.abortSignal.aborted) throw error
2399
+ // The tool has already returned. Cancellation of a later redaction
2400
+ // cannot erase that execution or turn it into a safe-to-repeat call.
2401
+ // Withhold both channels until their post-tool policy has completed.
2402
+ const outcome = toolResult.success
2403
+ ? 'reported success before cancellation. The call already executed.'
2404
+ : 'reported failure while cancellation was in progress. Side effects are possible.'
2405
+ const output = `Tool "${toolName}" ${outcome} Output withheld because post-tool review was interrupted. Inspect external state before any retry.`
2406
+ return {
2407
+ override: { output, content: output, isError: !toolResult.success },
2408
+ retry: false,
2409
+ }
2410
+ }
2383
2411
  let override: PostToolOverride | null = null
2384
2412
  let retry = false
2385
2413
  for (const result of results) {
@@ -2484,6 +2512,18 @@ export class ToolExecutor {
2484
2512
  return { toolCallId: toolCall.id, toolName, output, isError: true }
2485
2513
  }
2486
2514
 
2515
+ private recordCancelledBeforeExecution(
2516
+ toolCallId: string,
2517
+ toolName: string,
2518
+ input: unknown,
2519
+ ): Promise<ToolCallOutcome> {
2520
+ const reason = abortReasonText(this.config.abortSignal.reason)
2521
+ return this.recordSyntheticHookOutcome(toolCallId, toolName, input, {
2522
+ kind: 'error',
2523
+ output: `Tool "${toolName}" was not started because the run was cancelled${reason ? `: ${reason}` : '.'}`,
2524
+ })
2525
+ }
2526
+
2487
2527
  private async recordSyntheticHookOutcome(
2488
2528
  toolCallId: string,
2489
2529
  toolName: string,
@@ -671,6 +671,13 @@ export interface QueryParams {
671
671
  * started. See `BaseAgentConfig.inboundMessages` for what it closes.
672
672
  */
673
673
  inboundMessages?: () => import('../../types/message/index.js').Message[]
674
+ /**
675
+ * Wake a background-task hold when operator input is available, without draining it.
676
+ * Resolve immediately if input is already pending. Otherwise wait for its arrival;
677
+ * the supplied signal ends the wait and must release any listeners. Messages are
678
+ * still consumed only through `inboundMessages` at a provider-valid boundary.
679
+ */
680
+ waitForInbound?: (signal: AbortSignal) => Promise<void>
674
681
 
675
682
  /**
676
683
  * Live project policy for this run. Unlike `inboundMessages`, snapshot
@@ -1963,6 +1970,7 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1963
1970
  ...(params.repeatCallAdvisory === false ? {} : { repeatCalls: new RepeatCallTracker() }),
1964
1971
  compactionConfig,
1965
1972
  ...(params.inboundMessages ? { inboundMessages: params.inboundMessages } : {}),
1973
+ ...(params.waitForInbound ? { waitForInbound: params.waitForInbound } : {}),
1966
1974
  ...(params.projectInstructionContext
1967
1975
  ? { projectInstructionContext: params.projectInstructionContext }
1968
1976
  : {}),
@@ -1450,9 +1450,9 @@ export class IterationOrchestrator {
1450
1450
  /**
1451
1451
  * Hold the run open for a worker that has not finished, and deliver it.
1452
1452
  *
1453
- * Returns whether a completion arrived and was put in the transcript — the
1454
- * caller continues the loop on `true`, so the model gets a turn in which to
1455
- * USE the result. That turn is the entire justification for waiting, which
1453
+ * Returns whether a completion or operator message entered the transcript —
1454
+ * the caller continues on `true`, so the model gets a turn to respond.
1455
+ * That turn is the entire justification for waiting, which
1456
1456
  * is why only the exits that can still take one call this.
1457
1457
  *
1458
1458
  * Bounded by `settleGraceMs` and by `maxIterations`, so a worker that never
@@ -1473,14 +1473,34 @@ export class IterationOrchestrator {
1473
1473
  [NAMZU.ITERATION]: iterationNum,
1474
1474
  'namzu.runtime.grace_ms': graceMs,
1475
1475
  })
1476
- await this.ctx.completionInbox.waitForArrival(graceMs)
1476
+ // User input releases this wait without cancelling any child. Both waits
1477
+ // share a disposable signal so the losing arrival listener cannot leak.
1478
+ const waiting = new AbortController()
1479
+ const runSignal = this.ctx.abortController.signal
1480
+ const cancelWait = () => waiting.abort(runSignal.reason)
1481
+ runSignal.addEventListener('abort', cancelWait, { once: true })
1482
+ if (runSignal.aborted) cancelWait()
1483
+ try {
1484
+ await Promise.race([
1485
+ this.ctx.completionInbox.waitForArrival(graceMs, waiting.signal),
1486
+ ...(this.ctx.waitForInbound ? [this.ctx.waitForInbound(waiting.signal)] : []),
1487
+ ])
1488
+ } catch (error) {
1489
+ if (!runSignal.aborted) throw error
1490
+ } finally {
1491
+ waiting.abort()
1492
+ runSignal.removeEventListener('abort', cancelWait)
1493
+ }
1494
+ runSignal.throwIfAborted()
1477
1495
 
1478
1496
  const arrived = this.ctx.completionInbox.drain()
1479
- if (arrived.length === 0) return false
1480
-
1481
- this.ctx.runMgr.pushMessage(
1482
- createRuntimeContextMessage(formatCompletionNotification(arrived), 'task-completion'),
1483
- )
1497
+ if (arrived.length > 0) {
1498
+ this.ctx.runMgr.pushMessage(
1499
+ createRuntimeContextMessage(formatCompletionNotification(arrived), 'task-completion'),
1500
+ )
1501
+ }
1502
+ const inbound = this.deliverInbound()
1503
+ if (arrived.length === 0 && inbound === 0) return false
1484
1504
  await this.ctx.emitEvent({
1485
1505
  type: 'iteration_completed',
1486
1506
  runId: this.ctx.runMgr.id,
@@ -188,6 +188,8 @@ export interface IterationContext {
188
188
  * after tool results and before the next turn.
189
189
  */
190
190
  readonly inboundMessages?: () => readonly import('../../../../types/message/index.js').Message[]
191
+ /** Observes pending input without draining it; abort releases the waiter. */
192
+ readonly waitForInbound?: (signal: AbortSignal) => Promise<void>
191
193
 
192
194
  /** Live project policy; separate from human inbound continuation. */
193
195
  readonly projectInstructionContext?: ProjectInstructionContext
@@ -518,11 +518,15 @@ export async function* streamProviderTurn(
518
518
  streamCause = err
519
519
  } finally {
520
520
  if (onAbort) signal?.removeEventListener('abort', onAbort)
521
- // Release the underlying connection on every exit (natural end, error,
522
- // or abort). `for await` did this implicitly on natural completion; the
523
- // manual drive must do it explicitly. `.return()` on an already-finished
524
- // provider generator is a no-op.
525
- await it.return?.().catch(() => {})
521
+ // Request cleanup on every exit, but never wait for a blocked provider's
522
+ // pending next(). An async generator queues return() behind that pull;
523
+ // awaiting it would undo the cancellation race above. Provider metering
524
+ // independently records cancellation and any already-issued late receipt.
525
+ try {
526
+ void it.return?.().catch(() => {})
527
+ } catch {
528
+ // Cleanup cannot replace the original stream outcome.
529
+ }
526
530
  }
527
531
 
528
532
  // Flush any tool buckets the provider failed to close (no toolCallEnd
@@ -41,7 +41,8 @@ export interface PromptBuilderConfig {
41
41
  contributions?: PromptContributionRegistry
42
42
  }
43
43
 
44
- function buildEnvContext(workingDirectory: string, runtimeContext?: AgentRuntimeContext): string {
44
+ function buildEnvContext(workingDirectory: string, config: PromptBuilderConfig): string {
45
+ const { runtimeContext, tools, allowedTools } = config
45
46
  const lines = [
46
47
  `<env>
47
48
  Working directory: ${workingDirectory}
@@ -69,7 +70,23 @@ Platform: ${process.platform}`,
69
70
 
70
71
  lines.push(`</env>
71
72
 
72
- IMPORTANT: Always use absolute paths based on the working directory above. Before reading a file, use the glob tool to discover actual file paths never guess or hallucinate paths.`)
73
+ Resolve relative paths against the working directory above; use supplied absolute paths as given.`)
74
+
75
+ if (hasFilesystemTools(tools, allowedTools)) {
76
+ lines.push(
77
+ 'When file contents are needed, read known file paths directly. Discover unknown paths with available filesystem tools using targeted directories and patterns.',
78
+ )
79
+ const canGlob =
80
+ tools.has('glob') &&
81
+ (!allowedTools || allowedTools.includes('glob')) &&
82
+ tools.getAvailability('glob') === 'active'
83
+ lines.push(
84
+ canGlob
85
+ ? "For an immediate directory overview, use glob with pattern '*' or an available directory listing tool. Use '**' only when recursive discovery is needed."
86
+ : 'For an immediate directory overview, use an available directory listing tool.',
87
+ "Keep discovery within the task's scope; do not recursively inventory unrelated home directories or cache trees.",
88
+ )
89
+ }
73
90
 
74
91
  return lines.join('\n')
75
92
  }
@@ -224,7 +241,7 @@ export class PromptBuilder {
224
241
  hasFilesystemTools(this.config.tools, this.config.allowedTools) ||
225
242
  Boolean(this.config.runtimeContext)
226
243
  if (shouldIncludeEnv) {
227
- parts.push(buildEnvContext(workingDirectory, this.config.runtimeContext))
244
+ parts.push(buildEnvContext(workingDirectory, this.config))
228
245
  }
229
246
  }
230
247
 
@@ -290,7 +307,7 @@ export class PromptBuilder {
290
307
  hasFilesystemTools(this.config.tools, this.config.allowedTools) ||
291
308
  Boolean(this.config.runtimeContext)
292
309
  if (shouldIncludeEnv) {
293
- dynamicParts.push(buildEnvContext(workingDirectory, this.config.runtimeContext))
310
+ dynamicParts.push(buildEnvContext(workingDirectory, this.config))
294
311
  }
295
312
  }
296
313
 
@@ -0,0 +1,93 @@
1
+ /** Stable guest code: host bundlers must never rewrite a function we serialize. */
2
+ export const FILE_WALK_PROGRAM = String.raw`
3
+ const fs = require('node:fs/promises');
4
+ const path = require('node:path');
5
+ const plan = JSON.parse(process.argv[1]);
6
+ const missing = error => ['ENOENT', 'ENOTDIR'].includes(error.code);
7
+ const write = async value => {
8
+ if (!process.stdout.write(JSON.stringify(value) + '\n')) {
9
+ await new Promise(resolve => process.stdout.once('drain', resolve));
10
+ }
11
+ };
12
+ const visit = count => {
13
+ if (count > plan.maxVisitedEntries) {
14
+ throw Object.assign(new Error('File search stopped after examining ' + plan.maxVisitedEntries + ' entries; narrow its root or pattern.'), {code:'ERR_FILE_WALK_LIMIT'});
15
+ }
16
+ };
17
+ const patterns = plan.patterns.map(set => set.map(part =>
18
+ typeof part === 'object' && part !== null ? new RegExp(part.source, part.flags + 's') : part));
19
+ const canDescend = relative => patterns.some(pattern => {
20
+ const closure = states => {
21
+ for (const index of states) if (pattern[index] === null) states.add(index + 1);
22
+ return states;
23
+ };
24
+ let states = closure(new Set([0]));
25
+ for (const name of relative.split('/')) {
26
+ const next = new Set();
27
+ for (const index of states) {
28
+ const segment = pattern[index];
29
+ if (segment === null) {
30
+ if (plan.includeHidden || !name.startsWith('.')) next.add(index);
31
+ } else if (typeof segment === 'string' ? segment === name : segment?.test(name)) next.add(index + 1);
32
+ }
33
+ states = closure(next);
34
+ if (states.size === 0) return false;
35
+ }
36
+ return [...states].some(index => index < pattern.length);
37
+ });
38
+ async function run() {
39
+ const stack = [];
40
+ let visited = 0;
41
+ let emitted = 0;
42
+ const matchers = plan.expressions.map(({source, flags}) => new RegExp(source, flags + 's'));
43
+ const maxDepth = plan.maxDepth === null ? Infinity : plan.maxDepth;
44
+ const open = async (absolute, relative, depth) => {
45
+ try { stack.push({dir: await fs.opendir(absolute), relative, depth}); }
46
+ catch (error) { if (!missing(error)) throw error; }
47
+ };
48
+ try {
49
+ if (plan.patterns.length === 0) return;
50
+ let canonicalRoot;
51
+ try { canonicalRoot = await fs.realpath(plan.root); }
52
+ catch (error) { if (missing(error)) return; throw error; }
53
+ if (canonicalRoot !== path.resolve(plan.root)) throw new Error('File walk root follows a symbolic link; use its authorized real directory');
54
+ let start = plan.root;
55
+ for (const part of plan.prefix) {
56
+ start = path.join(start, part);
57
+ let info;
58
+ try { info = await fs.lstat(start); }
59
+ catch (error) { if (missing(error)) return; throw error; }
60
+ visit(++visited);
61
+ if (!info.isDirectory()) return;
62
+ }
63
+ if (plan.prefix.length >= maxDepth) return;
64
+ await open(start, plan.prefix.join('/'), plan.prefix.length);
65
+ while (stack.length) {
66
+ const frame = stack[stack.length - 1];
67
+ const entry = await frame.dir.read();
68
+ if (!entry) { stack.pop(); await frame.dir.close(); continue; }
69
+ visit(++visited);
70
+ const relative = frame.relative ? frame.relative + '/' + entry.name : entry.name;
71
+ const absolute = path.join(plan.root, relative);
72
+ const depth = frame.depth + 1;
73
+ if (entry.isDirectory()) {
74
+ if (depth < maxDepth && canDescend(relative)) await open(absolute, relative, depth);
75
+ continue;
76
+ }
77
+ if (!entry.isFile() || !matchers.some(matcher => matcher.test(relative))) continue;
78
+ let info;
79
+ try { info = await fs.lstat(absolute); }
80
+ catch (error) { if (missing(error)) continue; throw error; }
81
+ if (!info.isFile()) continue;
82
+ await write({type:'entry', path:absolute, size:info.size});
83
+ if (++emitted >= plan.maxEntries) return;
84
+ }
85
+ } finally {
86
+ for (const {dir} of stack.reverse()) await dir.close();
87
+ }
88
+ }
89
+ run().then(
90
+ () => write({type:'done'}),
91
+ async error => { await write({type:'error', message:error.message, code:error.code}); process.exitCode = 1; },
92
+ );
93
+ `