abxbus 2.5.4 → 2.5.9

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 (41) hide show
  1. package/dist/cjs/BaseEvent.d.ts +53 -28
  2. package/dist/cjs/BaseEvent.js +148 -28
  3. package/dist/cjs/BaseEvent.js.map +2 -2
  4. package/dist/cjs/LockManager.js +1 -1
  5. package/dist/cjs/LockManager.js.map +2 -2
  6. package/dist/cjs/events_suck.d.ts +8 -15
  7. package/dist/cjs/events_suck.js +1 -1
  8. package/dist/cjs/events_suck.js.map +2 -2
  9. package/dist/cjs/jsonschema.d.ts +6 -0
  10. package/dist/cjs/jsonschema.js +155 -0
  11. package/dist/cjs/jsonschema.js.map +7 -0
  12. package/dist/cjs/retry.d.ts +2 -0
  13. package/dist/cjs/retry.js +110 -35
  14. package/dist/cjs/retry.js.map +3 -3
  15. package/dist/cjs/types.d.ts +6 -10
  16. package/dist/cjs/types.js +9 -16
  17. package/dist/cjs/types.js.map +2 -2
  18. package/dist/esm/BaseEvent.js +148 -28
  19. package/dist/esm/BaseEvent.js.map +2 -2
  20. package/dist/esm/LockManager.js +1 -1
  21. package/dist/esm/LockManager.js.map +2 -2
  22. package/dist/esm/events_suck.js +1 -1
  23. package/dist/esm/events_suck.js.map +2 -2
  24. package/dist/esm/jsonschema.js +135 -0
  25. package/dist/esm/jsonschema.js.map +7 -0
  26. package/dist/esm/retry.js +110 -35
  27. package/dist/esm/retry.js.map +3 -3
  28. package/dist/esm/types.js +8 -15
  29. package/dist/esm/types.js.map +2 -2
  30. package/dist/types/BaseEvent.d.ts +53 -28
  31. package/dist/types/events_suck.d.ts +8 -15
  32. package/dist/types/jsonschema.d.ts +6 -0
  33. package/dist/types/retry.d.ts +2 -0
  34. package/dist/types/types.d.ts +6 -10
  35. package/package.json +1 -1
  36. package/src/BaseEvent.ts +321 -80
  37. package/src/LockManager.ts +1 -1
  38. package/src/events_suck.ts +20 -22
  39. package/src/jsonschema.ts +146 -0
  40. package/src/retry.ts +132 -38
  41. package/src/types.ts +10 -19
@@ -0,0 +1,146 @@
1
+ import { z } from 'zod'
2
+
3
+ export type JsonSchema = boolean | z.core.JSONSchema.JSONSchema
4
+ type JsonSchemaObject = z.core.JSONSchema.JSONSchema
5
+
6
+ const isJsonSchemaObject = (value: unknown): value is JsonSchemaObject => {
7
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
8
+ }
9
+
10
+ export const isJsonSchema = (value: unknown): value is JsonSchema => {
11
+ if (typeof value === 'boolean') {
12
+ return true
13
+ }
14
+ if (!isJsonSchemaObject(value)) {
15
+ return false
16
+ }
17
+ if ('_zod' in value || '_def' in value || '~standard' in value) {
18
+ return false
19
+ }
20
+ return true
21
+ }
22
+
23
+ const nullUnionCandidates = (schema: Record<string, unknown>): Record<string, unknown>[] | null => {
24
+ if (Array.isArray(schema.type) && schema.type.includes('null')) {
25
+ const non_null_types = schema.type.filter((item): item is string => typeof item === 'string' && item !== 'null')
26
+ if (non_null_types.length > 0) {
27
+ return [{ type: non_null_types.length === 1 ? non_null_types[0] : non_null_types }, { type: 'null' }]
28
+ }
29
+ }
30
+
31
+ return null
32
+ }
33
+
34
+ export const normalizeJsonSchema = (schema: JsonSchema): JsonSchema => {
35
+ const normalized = normalizeJsonSchemaValue(schema)
36
+ if (!isJsonSchemaObject(normalized)) {
37
+ return normalized as JsonSchema
38
+ }
39
+ const schema_record = { ...normalized } as JsonSchemaObject
40
+ const definitions = schema_record.$defs
41
+ const root_ref = rootRefForSchema(schema_record, definitions)
42
+ if (!root_ref || !definitions) {
43
+ schema_record.$schema ??= 'https://json-schema.org/draft/2020-12/schema'
44
+ return schema_record
45
+ }
46
+ const root_name = root_ref.slice('#/$defs/'.length)
47
+ const root_schema = definitions[root_name]
48
+ if (!isJsonSchemaObject(root_schema)) {
49
+ schema_record.$schema ??= 'https://json-schema.org/draft/2020-12/schema'
50
+ return schema_record
51
+ }
52
+ const rewritten_root = rewriteJsonSchemaRefs(root_schema, { [root_ref]: '#' }) as JsonSchemaObject
53
+ const remaining_defs = Object.fromEntries(Object.entries(definitions).filter(([name]) => name !== root_name))
54
+ if (Object.keys(remaining_defs).length > 0) {
55
+ rewritten_root.$defs = rewriteJsonSchemaRefs(remaining_defs, { [root_ref]: '#' }) as Record<string, JsonSchemaObject>
56
+ }
57
+ rewritten_root.$schema ??= schema_record.$schema ?? 'https://json-schema.org/draft/2020-12/schema'
58
+ setTitleFromInlinedRootDefinition(rewritten_root, root_name)
59
+ return rewritten_root
60
+ }
61
+
62
+ const rootRefForSchema = (schema: JsonSchemaObject, definitions: Record<string, JsonSchemaObject> | undefined): string | null => {
63
+ if (typeof schema.$ref === 'string' && schema.$ref.startsWith('#/$defs/')) {
64
+ return schema.$ref
65
+ }
66
+ if (!definitions) {
67
+ return null
68
+ }
69
+ const root = schemaWithoutSchemaAndDefinitions(schema)
70
+ for (const [name, definition] of Object.entries(definitions)) {
71
+ if (JSON.stringify(definition) === JSON.stringify(root)) {
72
+ return `#/$defs/${name}`
73
+ }
74
+ }
75
+ return null
76
+ }
77
+
78
+ const schemaWithoutSchemaAndDefinitions = (schema: JsonSchemaObject): Record<string, unknown> => {
79
+ const root: Record<string, unknown> = {}
80
+ for (const [key, value] of Object.entries(schema)) {
81
+ if (key !== '$schema' && key !== '$defs') {
82
+ root[key] = value
83
+ }
84
+ }
85
+ return root
86
+ }
87
+
88
+ const setTitleFromInlinedRootDefinition = (schema: JsonSchemaObject, root_name: string): void => {
89
+ if (root_name.startsWith('__schema')) return
90
+ schema.title ??= root_name
91
+ }
92
+
93
+ const rewriteJsonSchemaRefs = (schema: unknown, refs: Record<string, string>): unknown => {
94
+ if (Array.isArray(schema)) {
95
+ return schema.map((item) => rewriteJsonSchemaRefs(item, refs))
96
+ }
97
+ if (!isJsonSchemaObject(schema)) {
98
+ return schema
99
+ }
100
+ const rewritten: Record<string, unknown> = {}
101
+ for (const [key, value] of Object.entries(schema)) {
102
+ rewritten[key] = rewriteJsonSchemaRefs(value, refs)
103
+ }
104
+ if (typeof rewritten.$ref === 'string' && rewritten.$ref in refs) {
105
+ rewritten.$ref = refs[rewritten.$ref]
106
+ }
107
+ return rewritten
108
+ }
109
+
110
+ const normalizeJsonSchemaValue = (schema: unknown): unknown => {
111
+ if (Array.isArray(schema)) {
112
+ return schema.map((item) => normalizeJsonSchemaValue(item))
113
+ }
114
+ if (!isJsonSchemaObject(schema)) {
115
+ return schema
116
+ }
117
+
118
+ const normalized: Record<string, unknown> = {}
119
+ for (const [key, value] of Object.entries(schema)) {
120
+ normalized[key] = normalizeJsonSchemaValue(value)
121
+ }
122
+ if (Array.isArray(normalized.required) && normalized.required.every((item) => typeof item === 'string')) {
123
+ normalized.required = [...normalized.required].sort()
124
+ }
125
+
126
+ const null_union_candidates = nullUnionCandidates(normalized)
127
+ if (null_union_candidates !== null) {
128
+ const merged: Record<string, unknown> = { anyOf: normalizeJsonSchemaValue(null_union_candidates) }
129
+ for (const [key, value] of Object.entries(normalized)) {
130
+ if (key !== 'type') {
131
+ merged[key] = value
132
+ }
133
+ }
134
+ return merged
135
+ }
136
+
137
+ return normalized
138
+ }
139
+
140
+ export const toJsonSchema = (schema: z.core.$ZodType): JsonSchema => {
141
+ return normalizeJsonSchema(z.toJSONSchema(schema) as JsonSchema)
142
+ }
143
+
144
+ export const fromJsonSchema = (schema: JsonSchema): z.ZodTypeAny => {
145
+ return z.fromJSONSchema(schema)
146
+ }
package/src/retry.ts CHANGED
@@ -21,6 +21,8 @@ type RetryDecorator = {
21
21
 
22
22
  const MULTIPROCESS_SEMAPHORE_DIRNAME = 'browser_use_semaphores'
23
23
  const MULTIPROCESS_STALE_LOCK_MS = 5 * 60 * 1000
24
+ const RETRY_SLOW_WARNING_THROTTLE_MS = 2000
25
+ const RETRY_SLOW_WARNING_ARGS_MAX_LENGTH = 80
24
26
 
25
27
  let multiprocess_fallback_reason_logged: string | null = null
26
28
 
@@ -44,6 +46,9 @@ export interface RetryOptions {
44
46
  /** Per-attempt timeout in seconds. Default: undefined (no per-attempt timeout) */
45
47
  timeout?: number | null
46
48
 
49
+ /** Emit a warning when a decorated call exceeds this many seconds. Default: undefined (disabled) */
50
+ slow_timeout?: number | null
51
+
47
52
  /** Maximum concurrent executions sharing this semaphore. Default: undefined (no concurrency limit) */
48
53
  semaphore_limit?: number | null
49
54
 
@@ -238,6 +243,7 @@ export function retry(options: RetryOptions = {}): RetryDecorator {
238
243
  retry_backoff_factor = 1.0,
239
244
  retry_on_errors,
240
245
  timeout,
246
+ slow_timeout,
241
247
  semaphore_limit,
242
248
  semaphore_name: semaphore_name_option,
243
249
  semaphore_lax = true,
@@ -245,10 +251,13 @@ export function retry(options: RetryOptions = {}): RetryDecorator {
245
251
  semaphore_timeout,
246
252
  } = options
247
253
 
248
- const decorateFunction = <T extends AnyFunction>(target: T, _context?: ClassMethodDecoratorContext): T => {
249
- const fn_name = target.name || (_context?.name as string) || 'anonymous'
254
+ const decorateFunction = <T extends AnyFunction>(target: T, _context?: ClassMethodDecoratorContext, owner_name?: string | null): T => {
255
+ const base_fn_name = target.name || (_context?.name as string) || 'anonymous'
256
+ let fn_name = owner_name ? `${owner_name}.${base_fn_name}` : base_fn_name
250
257
  const effective_max_attempts = Math.max(1, max_attempts)
251
258
  const effective_retry_after = Math.max(0, retry_after)
259
+ const effective_slow_timeout_ms = slow_timeout != null && slow_timeout > 0 ? slow_timeout * 1000 : null
260
+ let last_slow_warning_at = 0
252
261
 
253
262
  const shouldRetry = (error: unknown): boolean => {
254
263
  if (!retry_on_errors || retry_on_errors.length === 0) return true
@@ -275,6 +284,14 @@ export function retry(options: RetryOptions = {}): RetryDecorator {
275
284
  }
276
285
  }
277
286
 
287
+ const emitSlowWarningIfDue = (args: any[], start_time: number): void => {
288
+ if (effective_slow_timeout_ms == null) return
289
+ const now = Date.now()
290
+ if (now - last_slow_warning_at < RETRY_SLOW_WARNING_THROTTLE_MS) return
291
+ last_slow_warning_at = now
292
+ console.warn(`Warning: ${fn_name}(${formatRetrySlowWarningArgs(args)}) slow (${((now - start_time) / 1000).toFixed(1)}s)`)
293
+ }
294
+
278
295
  const runRetryLoopFromThenable = async (
279
296
  this_arg: any,
280
297
  args: any[],
@@ -373,26 +390,45 @@ export function retry(options: RetryOptions = {}): RetryDecorator {
373
390
 
374
391
  // ── Retry loop (runs inside the semaphore and re-entrancy context) ──
375
392
  const runRetryLoop = async (): Promise<any> => {
376
- for (let attempt = 1; attempt <= effective_max_attempts; attempt++) {
377
- try {
378
- if (timeout != null && timeout > 0) {
379
- return await _runWithTimeout(() => Promise.resolve(target.apply(this, args)), timeout * 1000, attempt)
380
- } else {
381
- return await Promise.resolve(target.apply(this, args))
382
- }
383
- } catch (error) {
384
- if (!shouldRetry(error)) throw error
393
+ const call_started_at = Date.now()
394
+ const warning_args = [...args]
395
+ const slow_warning_timer =
396
+ effective_slow_timeout_ms == null
397
+ ? null
398
+ : setTimeout(() => emitSlowWarningIfDue(warning_args, call_started_at), effective_slow_timeout_ms)
399
+ const finishSlowWarning = (): void => {
400
+ if (slow_warning_timer !== null) {
401
+ clearTimeout(slow_warning_timer)
402
+ }
403
+ if (effective_slow_timeout_ms != null && Date.now() - call_started_at >= effective_slow_timeout_ms) {
404
+ emitSlowWarningIfDue(warning_args, call_started_at)
405
+ }
406
+ }
385
407
 
386
- // Last attempt: rethrow
387
- if (attempt >= effective_max_attempts) throw error
408
+ try {
409
+ for (let attempt = 1; attempt <= effective_max_attempts; attempt++) {
410
+ try {
411
+ if (timeout != null && timeout > 0) {
412
+ return await _runWithTimeout(() => Promise.resolve(target.apply(this, args)), timeout * 1000, attempt)
413
+ } else {
414
+ return await Promise.resolve(target.apply(this, args))
415
+ }
416
+ } catch (error) {
417
+ if (!shouldRetry(error)) throw error
418
+
419
+ // Last attempt: rethrow
420
+ if (attempt >= effective_max_attempts) throw error
388
421
 
389
- // Wait before next attempt with exponential backoff
390
- await asyncRetryDelay(attempt)
422
+ // Wait before next attempt with exponential backoff
423
+ await asyncRetryDelay(attempt)
424
+ }
391
425
  }
392
- }
393
426
 
394
- // Unreachable, but satisfies the type checker
395
- throw new Error(`retry(${fn_name}): unexpected end of retry loop`)
427
+ // Unreachable, but satisfies the type checker
428
+ throw new Error(`retry(${fn_name}): unexpected end of retry loop`)
429
+ } finally {
430
+ finishSlowWarning()
431
+ }
396
432
  }
397
433
 
398
434
  try {
@@ -452,27 +488,52 @@ export function retry(options: RetryOptions = {}): RetryDecorator {
452
488
  }
453
489
 
454
490
  const runRetryLoop = (): any => {
455
- for (let attempt = 1; attempt <= effective_max_attempts; attempt++) {
456
- const attempt_started_at = Date.now()
457
- try {
458
- const result = target.apply(this, args)
459
- if (isThenable(result)) {
460
- return runRetryLoopFromThenable(this, args, result, attempt)
461
- }
462
- if (timeout != null && timeout > 0 && Date.now() - attempt_started_at > timeout * 1000) {
463
- throw new RetryTimeoutError(`Timed out after ${timeout}s (attempt ${attempt})`, {
464
- timeout_seconds: timeout,
465
- attempt,
466
- })
491
+ const call_started_at = Date.now()
492
+ const warning_args = [...args]
493
+ const slow_warning_timer =
494
+ effective_slow_timeout_ms == null
495
+ ? null
496
+ : setTimeout(() => emitSlowWarningIfDue(warning_args, call_started_at), effective_slow_timeout_ms)
497
+ const finishSlowWarning = (): void => {
498
+ if (slow_warning_timer !== null) {
499
+ clearTimeout(slow_warning_timer)
500
+ }
501
+ if (effective_slow_timeout_ms != null && Date.now() - call_started_at >= effective_slow_timeout_ms) {
502
+ emitSlowWarningIfDue(warning_args, call_started_at)
503
+ }
504
+ }
505
+
506
+ let finish_on_return = true
507
+ try {
508
+ for (let attempt = 1; attempt <= effective_max_attempts; attempt++) {
509
+ const attempt_started_at = Date.now()
510
+ try {
511
+ const result = target.apply(this, args)
512
+ if (isThenable(result)) {
513
+ finish_on_return = false
514
+ return runRetryLoopFromThenable(this, args, result, attempt).finally(finishSlowWarning)
515
+ }
516
+ if (timeout != null && timeout > 0 && Date.now() - attempt_started_at > timeout * 1000) {
517
+ throw new RetryTimeoutError(`Timed out after ${timeout}s (attempt ${attempt})`, {
518
+ timeout_seconds: timeout,
519
+ attempt,
520
+ })
521
+ }
522
+ return result
523
+ } catch (error) {
524
+ if (!shouldRetry(error)) throw error
525
+ if (attempt >= effective_max_attempts) {
526
+ throw error
527
+ }
528
+ syncRetryDelay(attempt)
467
529
  }
468
- return result
469
- } catch (error) {
470
- if (!shouldRetry(error)) throw error
471
- if (attempt >= effective_max_attempts) throw error
472
- syncRetryDelay(attempt)
530
+ }
531
+ throw new Error(`retry(${fn_name}): unexpected end of retry loop`)
532
+ } finally {
533
+ if (finish_on_return) {
534
+ finishSlowWarning()
473
535
  }
474
536
  }
475
- throw new Error(`retry(${fn_name}): unexpected end of retry loop`)
476
537
  }
477
538
 
478
539
  try {
@@ -494,7 +555,8 @@ export function retry(options: RetryOptions = {}): RetryDecorator {
494
555
  _context.addInitializer(function (this: unknown) {
495
556
  const owner_name = findDecoratedMethodOwnerName(this, _context, retryWrapper)
496
557
  if (owner_name) {
497
- Object.defineProperty(retryWrapper, 'name', { value: `${owner_name}.${fn_name}`, configurable: true })
558
+ fn_name = `${owner_name}.${target.name || (_context.name as string) || 'anonymous'}`
559
+ Object.defineProperty(retryWrapper, 'name', { value: fn_name, configurable: true })
498
560
  }
499
561
  })
500
562
  }
@@ -507,7 +569,13 @@ export function retry(options: RetryOptions = {}): RetryDecorator {
507
569
  descriptor?: LegacyMethodDescriptor
508
570
  ): T | LegacyMethodDescriptor {
509
571
  if (descriptor?.value && typeof descriptor.value === 'function') {
510
- descriptor.value = decorateFunction(descriptor.value)
572
+ const owner_name =
573
+ target && (typeof target === 'object' || typeof target === 'function')
574
+ ? typeof target === 'function'
575
+ ? target.name
576
+ : (target as { constructor?: { name?: string } }).constructor?.name
577
+ : null
578
+ descriptor.value = decorateFunction(descriptor.value, undefined, owner_name)
511
579
  return descriptor
512
580
  }
513
581
  if (typeof target === 'function') {
@@ -569,6 +637,32 @@ function isThenable(value: unknown): value is PromiseLike<unknown> {
569
637
  )
570
638
  }
571
639
 
640
+ function formatRetrySlowWarningArgs(args: any[]): string {
641
+ const preview = args.map(formatRetrySlowWarningValue).join(', ')
642
+ if (preview.length > RETRY_SLOW_WARNING_ARGS_MAX_LENGTH) {
643
+ return `${preview.slice(0, RETRY_SLOW_WARNING_ARGS_MAX_LENGTH - 3).replace(/,?\s*$/, '')}...`
644
+ }
645
+ return preview
646
+ }
647
+
648
+ function formatRetrySlowWarningValue(value: unknown): string {
649
+ let text: string
650
+ if (typeof value === 'string') {
651
+ text = value
652
+ } else if (value === null || value === undefined) {
653
+ text = String(value)
654
+ } else if (typeof value === 'object') {
655
+ try {
656
+ text = JSON.stringify(value)
657
+ } catch {
658
+ text = String(value)
659
+ }
660
+ } else {
661
+ text = String(value)
662
+ }
663
+ return text.replace(/['"]/g, '').slice(0, 3)
664
+ }
665
+
572
666
  /**
573
667
  * Try to acquire a semaphore within a timeout. Returns true if acquired, false if timed out.
574
668
  * If the semaphore is acquired after the timeout (due to the waiter remaining queued),
package/src/types.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { z } from 'zod'
2
- import type { BaseEvent } from './BaseEvent.js'
2
+ import type { BaseEvent, EventClass as BaseEventClass } from './BaseEvent.js'
3
+ import { fromJsonSchema, isJsonSchema, type JsonSchema } from './jsonschema.js'
3
4
 
4
5
  export type EventStatus = 'pending' | 'started' | 'completed'
6
+ export type { EventClass } from './BaseEvent.js'
5
7
 
6
- export type EventClass<T extends BaseEvent = BaseEvent> = { event_type?: string } & (new (...args: any[]) => T)
7
-
8
- export type EventPattern<T extends BaseEvent = BaseEvent> = string | EventClass<T>
8
+ export type EventPattern<T extends BaseEvent = BaseEvent> = string | BaseEventClass<T>
9
9
 
10
10
  export type EventWithResultSchema<TResult> = BaseEvent & { __event_result_type__?: TResult }
11
11
 
@@ -13,7 +13,7 @@ export type EventResultType<TEvent extends BaseEvent> = TEvent extends { __event
13
13
 
14
14
  export type EventResultTypeConstructor = StringConstructor | NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor
15
15
 
16
- export type EventResultTypeInput = z.ZodTypeAny | EventResultTypeConstructor | unknown
16
+ export type EventResultTypeInput = z.ZodTypeAny | EventResultTypeConstructor | JsonSchema
17
17
 
18
18
  export type EventHandlerReturn<T extends BaseEvent = BaseEvent> = EventResultType<T> | BaseEvent | null | void
19
19
 
@@ -74,7 +74,7 @@ export const normalizeEventPattern = (event_pattern: EventPattern | '*'): string
74
74
  } catch {
75
75
  preview = String(event_pattern).slice(0, 30)
76
76
  }
77
- throw new Error('bus.on(match_pattern, ...) must be a string event type, "*", or a BaseEvent class, got: ' + preview)
77
+ throw new Error('bus.on(match_pattern, ...) must be a string event type, "*", or a BaseEvent.extend() event class, got: ' + preview)
78
78
  }
79
79
 
80
80
  export const isZodSchema = (value: unknown): value is z.ZodTypeAny => !!value && typeof (value as z.ZodTypeAny).safeParse === 'function'
@@ -107,19 +107,7 @@ export const extractZodShape = (raw: Record<string, unknown>): z.ZodRawShape =>
107
107
  return shape as z.ZodRawShape
108
108
  }
109
109
 
110
- export const toJsonSchema = (schema: unknown): unknown => {
111
- if (!schema || !isZodSchema(schema)) return schema
112
- const zod_any = z as unknown as { toJSONSchema: (input: z.ZodTypeAny) => unknown }
113
- // Cross-language roundtrips preserve core structural types; constraint keywords may not roundtrip exactly.
114
- return zod_any.toJSONSchema(schema)
115
- }
116
-
117
- export const fromJsonSchema = (schema: unknown): z.ZodTypeAny => {
118
- const zod_any = z as unknown as { fromJSONSchema: (input: unknown) => z.ZodTypeAny }
119
- return zod_any.fromJSONSchema(schema)
120
- }
121
-
122
- export const normalizeEventResultType = (value: EventResultTypeInput): z.ZodTypeAny | undefined => {
110
+ export function normalizeEventResultType(value: unknown): z.ZodTypeAny | undefined {
123
111
  if (value === undefined || value === null) {
124
112
  return undefined
125
113
  }
@@ -130,5 +118,8 @@ export const normalizeEventResultType = (value: EventResultTypeInput): z.ZodType
130
118
  if (constructor_schema) {
131
119
  return constructor_schema
132
120
  }
121
+ if (!isJsonSchema(value)) {
122
+ throw new Error(`event_result_type must be a Zod schema, constructor shorthand, or JSON Schema value, got: ${typeof value}`)
123
+ }
133
124
  return fromJsonSchema(value)
134
125
  }