effect 4.0.0-beta.10 → 4.0.0-beta.12

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 (189) hide show
  1. package/dist/Channel.d.ts +7 -7
  2. package/dist/Config.d.ts +157 -0
  3. package/dist/Config.d.ts.map +1 -1
  4. package/dist/Config.js +56 -1
  5. package/dist/Config.js.map +1 -1
  6. package/dist/Effect.d.ts +296 -8
  7. package/dist/Effect.d.ts.map +1 -1
  8. package/dist/Effect.js +72 -0
  9. package/dist/Effect.js.map +1 -1
  10. package/dist/ErrorReporter.d.ts +376 -0
  11. package/dist/ErrorReporter.d.ts.map +1 -0
  12. package/dist/ErrorReporter.js +246 -0
  13. package/dist/ErrorReporter.js.map +1 -0
  14. package/dist/Fiber.d.ts +2 -2
  15. package/dist/Fiber.d.ts.map +1 -1
  16. package/dist/Fiber.js.map +1 -1
  17. package/dist/Graph.d.ts.map +1 -1
  18. package/dist/Graph.js +3 -6
  19. package/dist/Graph.js.map +1 -1
  20. package/dist/LogLevel.d.ts +5 -0
  21. package/dist/LogLevel.d.ts.map +1 -1
  22. package/dist/LogLevel.js.map +1 -1
  23. package/dist/Logger.d.ts +25 -91
  24. package/dist/Logger.d.ts.map +1 -1
  25. package/dist/Logger.js +2 -3
  26. package/dist/Logger.js.map +1 -1
  27. package/dist/Queue.d.ts.map +1 -1
  28. package/dist/Queue.js +0 -1
  29. package/dist/Queue.js.map +1 -1
  30. package/dist/Random.d.ts +17 -0
  31. package/dist/Random.d.ts.map +1 -1
  32. package/dist/Random.js +17 -0
  33. package/dist/Random.js.map +1 -1
  34. package/dist/References.d.ts +3 -3
  35. package/dist/References.d.ts.map +1 -1
  36. package/dist/Schema.d.ts +3 -1
  37. package/dist/Schema.d.ts.map +1 -1
  38. package/dist/SchemaAST.d.ts.map +1 -1
  39. package/dist/SchemaAST.js +2 -1
  40. package/dist/SchemaAST.js.map +1 -1
  41. package/dist/Stream.d.ts +5 -5
  42. package/dist/index.d.ts +4 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +4 -0
  45. package/dist/index.js.map +1 -1
  46. package/dist/internal/effect.js +98 -33
  47. package/dist/internal/effect.js.map +1 -1
  48. package/dist/internal/hashMap.js +2 -2
  49. package/dist/internal/hashMap.js.map +1 -1
  50. package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
  51. package/dist/unstable/ai/LanguageModel.js +86 -14
  52. package/dist/unstable/ai/LanguageModel.js.map +1 -1
  53. package/dist/unstable/ai/McpSchema.d.ts +112 -36
  54. package/dist/unstable/ai/McpSchema.d.ts.map +1 -1
  55. package/dist/unstable/ai/McpSchema.js +47 -10
  56. package/dist/unstable/ai/McpSchema.js.map +1 -1
  57. package/dist/unstable/ai/McpServer.d.ts.map +1 -1
  58. package/dist/unstable/ai/McpServer.js +33 -6
  59. package/dist/unstable/ai/McpServer.js.map +1 -1
  60. package/dist/unstable/ai/Tool.d.ts +16 -0
  61. package/dist/unstable/ai/Tool.d.ts.map +1 -1
  62. package/dist/unstable/ai/Tool.js +14 -0
  63. package/dist/unstable/ai/Tool.js.map +1 -1
  64. package/dist/unstable/cli/CliOutput.js +37 -6
  65. package/dist/unstable/cli/CliOutput.js.map +1 -1
  66. package/dist/unstable/cli/Command.d.ts +199 -7
  67. package/dist/unstable/cli/Command.d.ts.map +1 -1
  68. package/dist/unstable/cli/Command.js +116 -6
  69. package/dist/unstable/cli/Command.js.map +1 -1
  70. package/dist/unstable/cli/HelpDoc.d.ts +60 -2
  71. package/dist/unstable/cli/HelpDoc.d.ts.map +1 -1
  72. package/dist/unstable/cli/internal/command.d.ts +11 -1
  73. package/dist/unstable/cli/internal/command.d.ts.map +1 -1
  74. package/dist/unstable/cli/internal/command.js +33 -8
  75. package/dist/unstable/cli/internal/command.js.map +1 -1
  76. package/dist/unstable/cli/internal/completions/CommandDescriptor.js +7 -2
  77. package/dist/unstable/cli/internal/completions/CommandDescriptor.js.map +1 -1
  78. package/dist/unstable/cli/internal/parser.js +10 -2
  79. package/dist/unstable/cli/internal/parser.js.map +1 -1
  80. package/dist/unstable/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  81. package/dist/unstable/cluster/ClusterWorkflowEngine.js +2 -2
  82. package/dist/unstable/cluster/ClusterWorkflowEngine.js.map +1 -1
  83. package/dist/unstable/http/Headers.d.ts.map +1 -1
  84. package/dist/unstable/http/Headers.js +27 -10
  85. package/dist/unstable/http/Headers.js.map +1 -1
  86. package/dist/unstable/http/HttpClient.d.ts +28 -4
  87. package/dist/unstable/http/HttpClient.d.ts.map +1 -1
  88. package/dist/unstable/http/HttpClient.js.map +1 -1
  89. package/dist/unstable/http/HttpEffect.d.ts +3 -8
  90. package/dist/unstable/http/HttpEffect.d.ts.map +1 -1
  91. package/dist/unstable/http/HttpEffect.js +25 -31
  92. package/dist/unstable/http/HttpEffect.js.map +1 -1
  93. package/dist/unstable/http/HttpMiddleware.d.ts.map +1 -1
  94. package/dist/unstable/http/HttpMiddleware.js +4 -8
  95. package/dist/unstable/http/HttpMiddleware.js.map +1 -1
  96. package/dist/unstable/http/HttpServerError.d.ts +14 -27
  97. package/dist/unstable/http/HttpServerError.d.ts.map +1 -1
  98. package/dist/unstable/http/HttpServerError.js +37 -44
  99. package/dist/unstable/http/HttpServerError.js.map +1 -1
  100. package/dist/unstable/http/HttpServerRespondable.d.ts +2 -2
  101. package/dist/unstable/http/HttpServerRespondable.d.ts.map +1 -1
  102. package/dist/unstable/http/HttpServerRespondable.js +5 -5
  103. package/dist/unstable/http/HttpServerRespondable.js.map +1 -1
  104. package/dist/unstable/http/HttpServerResponse.d.ts +2 -1
  105. package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
  106. package/dist/unstable/http/HttpServerResponse.js +2 -0
  107. package/dist/unstable/http/HttpServerResponse.js.map +1 -1
  108. package/dist/unstable/http/internal/preResponseHandler.d.ts +2 -0
  109. package/dist/unstable/http/internal/preResponseHandler.d.ts.map +1 -0
  110. package/dist/unstable/http/internal/preResponseHandler.js +10 -0
  111. package/dist/unstable/http/internal/preResponseHandler.js.map +1 -0
  112. package/dist/unstable/httpapi/HttpApiBuilder.d.ts +1 -1
  113. package/dist/unstable/httpapi/HttpApiBuilder.d.ts.map +1 -1
  114. package/dist/unstable/httpapi/HttpApiBuilder.js +1 -1
  115. package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
  116. package/dist/unstable/httpapi/HttpApiError.d.ts +11 -0
  117. package/dist/unstable/httpapi/HttpApiError.d.ts.map +1 -1
  118. package/dist/unstable/httpapi/HttpApiError.js +29 -9
  119. package/dist/unstable/httpapi/HttpApiError.js.map +1 -1
  120. package/dist/unstable/observability/OtlpLogger.d.ts.map +1 -1
  121. package/dist/unstable/observability/OtlpLogger.js +7 -4
  122. package/dist/unstable/observability/OtlpLogger.js.map +1 -1
  123. package/dist/unstable/reactivity/Atom.js +1 -1
  124. package/dist/unstable/reactivity/Atom.js.map +1 -1
  125. package/dist/unstable/reactivity/AtomRegistry.d.ts +6 -0
  126. package/dist/unstable/reactivity/AtomRegistry.d.ts.map +1 -1
  127. package/dist/unstable/reactivity/AtomRegistry.js +22 -1
  128. package/dist/unstable/reactivity/AtomRegistry.js.map +1 -1
  129. package/dist/unstable/rpc/RpcSchema.d.ts +13 -0
  130. package/dist/unstable/rpc/RpcSchema.d.ts.map +1 -1
  131. package/dist/unstable/rpc/RpcSchema.js +14 -0
  132. package/dist/unstable/rpc/RpcSchema.js.map +1 -1
  133. package/dist/unstable/rpc/RpcSerialization.d.ts.map +1 -1
  134. package/dist/unstable/rpc/RpcSerialization.js +34 -9
  135. package/dist/unstable/rpc/RpcSerialization.js.map +1 -1
  136. package/dist/unstable/rpc/RpcServer.d.ts +0 -7
  137. package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
  138. package/dist/unstable/rpc/RpcServer.js +9 -10
  139. package/dist/unstable/rpc/RpcServer.js.map +1 -1
  140. package/dist/unstable/workflow/WorkflowEngine.d.ts +6 -0
  141. package/dist/unstable/workflow/WorkflowEngine.d.ts.map +1 -1
  142. package/dist/unstable/workflow/WorkflowEngine.js +131 -0
  143. package/dist/unstable/workflow/WorkflowEngine.js.map +1 -1
  144. package/package.json +1 -1
  145. package/src/Channel.ts +9 -9
  146. package/src/Config.ts +171 -9
  147. package/src/Effect.ts +315 -8
  148. package/src/ErrorReporter.ts +459 -0
  149. package/src/Fiber.ts +9 -2
  150. package/src/Graph.ts +16 -6
  151. package/src/LogLevel.ts +6 -0
  152. package/src/Logger.ts +28 -95
  153. package/src/Queue.ts +0 -1
  154. package/src/Random.ts +18 -0
  155. package/src/References.ts +4 -4
  156. package/src/Schema.ts +1 -1
  157. package/src/SchemaAST.ts +2 -1
  158. package/src/Stream.ts +7 -7
  159. package/src/index.ts +5 -0
  160. package/src/internal/effect.ts +205 -49
  161. package/src/internal/hashMap.ts +2 -2
  162. package/src/unstable/ai/LanguageModel.ts +117 -16
  163. package/src/unstable/ai/McpSchema.ts +57 -11
  164. package/src/unstable/ai/McpServer.ts +44 -6
  165. package/src/unstable/ai/Tool.ts +15 -0
  166. package/src/unstable/cli/CliOutput.ts +45 -6
  167. package/src/unstable/cli/Command.ts +298 -11
  168. package/src/unstable/cli/HelpDoc.ts +68 -2
  169. package/src/unstable/cli/internal/command.ts +47 -11
  170. package/src/unstable/cli/internal/completions/CommandDescriptor.ts +7 -2
  171. package/src/unstable/cli/internal/parser.ts +11 -3
  172. package/src/unstable/cluster/ClusterWorkflowEngine.ts +2 -2
  173. package/src/unstable/http/Headers.ts +28 -13
  174. package/src/unstable/http/HttpClient.ts +45 -10
  175. package/src/unstable/http/HttpEffect.ts +30 -44
  176. package/src/unstable/http/HttpMiddleware.ts +4 -14
  177. package/src/unstable/http/HttpServerError.ts +42 -45
  178. package/src/unstable/http/HttpServerRespondable.ts +6 -6
  179. package/src/unstable/http/HttpServerResponse.ts +3 -1
  180. package/src/unstable/http/internal/preResponseHandler.ts +15 -0
  181. package/src/unstable/httpapi/HttpApiBuilder.ts +2 -1
  182. package/src/unstable/httpapi/HttpApiError.ts +30 -9
  183. package/src/unstable/observability/OtlpLogger.ts +9 -5
  184. package/src/unstable/reactivity/Atom.ts +1 -1
  185. package/src/unstable/reactivity/AtomRegistry.ts +29 -1
  186. package/src/unstable/rpc/RpcSchema.ts +17 -0
  187. package/src/unstable/rpc/RpcSerialization.ts +44 -9
  188. package/src/unstable/rpc/RpcServer.ts +14 -19
  189. package/src/unstable/workflow/WorkflowEngine.ts +178 -0
@@ -5,6 +5,7 @@ import type * as Console from "../Console.ts"
5
5
  import * as Duration from "../Duration.ts"
6
6
  import type * as Effect from "../Effect.ts"
7
7
  import * as Equal from "../Equal.ts"
8
+ import type { ErrorReporter } from "../ErrorReporter.ts"
8
9
  import type * as Exit from "../Exit.ts"
9
10
  import type * as Fiber from "../Fiber.ts"
10
11
  import * as Filter from "../Filter.ts"
@@ -341,7 +342,8 @@ export const causePrettyErrors = <E>(self: Cause.Cause<E>): Array<Error> => {
341
342
  return errors
342
343
  }
343
344
 
344
- const causePrettyError = (
345
+ /** @internal */
346
+ export const causePrettyError = (
345
347
  original: Record<string, unknown> | Error,
346
348
  annotations?: ReadonlyMap<string, unknown>
347
349
  ): Error => {
@@ -490,17 +492,33 @@ const fiberIdStore = { id: 0 }
490
492
  export const getCurrentFiber = (): Fiber.Fiber<any, any> | undefined => (globalThis as any)[currentFiberTypeId]
491
493
 
492
494
  const keepAlive = (() => {
495
+ let isAvailable: boolean | undefined
496
+ const start = () => {
497
+ if (isAvailable === true) return setInterval(constVoid, 2_147_483_647)
498
+ else if (isAvailable === false) return undefined
499
+
500
+ try {
501
+ const running = setInterval(constVoid, 2_147_483_647)
502
+ isAvailable = true
503
+ return running
504
+ } catch {
505
+ isAvailable = false
506
+ return undefined
507
+ }
508
+ }
493
509
  let count = 0
494
510
  let running: ReturnType<typeof globalThis.setInterval> | undefined = undefined
495
511
  return ({
496
512
  increment() {
497
513
  count++
498
- running ??= globalThis.setInterval(constVoid, 2_147_483_647)
514
+ if (running === undefined) {
515
+ running = start()
516
+ }
499
517
  },
500
518
  decrement() {
501
519
  count--
502
520
  if (count === 0 && running !== undefined) {
503
- globalThis.clearInterval(running)
521
+ clearInterval(running)
504
522
  running = undefined
505
523
  }
506
524
  }
@@ -814,13 +832,29 @@ export const fiberInterrupt = <A, E>(
814
832
 
815
833
  /** @internal */
816
834
  export const fiberInterruptAs: {
817
- (fiberId: number): <A, E>(self: Fiber.Fiber<A, E>) => Effect.Effect<void>
818
- <A, E>(self: Fiber.Fiber<A, E>, fiberId: number): Effect.Effect<void>
819
- } = dual(2, <A, E>(self: Fiber.Fiber<A, E>, fiberId: number): Effect.Effect<void> =>
820
- withFiber((parent) => {
821
- self.interruptUnsafe(fiberId, fiberStackAnnotations(parent))
822
- return asVoid(fiberAwait(self))
823
- }))
835
+ (
836
+ fiberId: number | undefined,
837
+ annotations?: ServiceMap.ServiceMap<never> | undefined
838
+ ): <A, E>(self: Fiber.Fiber<A, E>) => Effect.Effect<void>
839
+ <A, E>(
840
+ self: Fiber.Fiber<A, E>,
841
+ fiberId: number | undefined,
842
+ annotations?: ServiceMap.ServiceMap<never> | undefined
843
+ ): Effect.Effect<void>
844
+ } = dual(
845
+ (args) => hasProperty(args[0], FiberTypeId),
846
+ <A, E>(
847
+ self: Fiber.Fiber<A, E>,
848
+ fiberId: number | undefined,
849
+ annotations?: ServiceMap.ServiceMap<never> | undefined
850
+ ): Effect.Effect<void> =>
851
+ withFiber((parent) => {
852
+ let ann = fiberStackAnnotations(parent)
853
+ ann = ann && annotations ? ServiceMap.merge(ann, annotations) : ann ?? annotations
854
+ self.interruptUnsafe(fiberId, ann)
855
+ return asVoid(fiberAwait(self))
856
+ })
857
+ )
824
858
 
825
859
  /** @internal */
826
860
  export const fiberInterruptAll = <A extends Iterable<Fiber.Fiber<any, any>>>(
@@ -1985,23 +2019,8 @@ export const updateServices: {
1985
2019
  const nextServices = f(prev)
1986
2020
  if (prev === nextServices) return self as any
1987
2021
  fiber.setServices(nextServices)
1988
- const newServices = new Map<string, unknown>()
1989
- for (const [key, value] of fiber.services.mapUnsafe) {
1990
- if (!prev.mapUnsafe.has(key) || value !== prev.mapUnsafe.get(key)) {
1991
- newServices.set(key, value)
1992
- }
1993
- }
1994
- return onExitPrimitive(self as any, () => {
1995
- const map = new Map(fiber.services.mapUnsafe)
1996
- for (const [key, value] of newServices) {
1997
- if (value !== map.get(key)) continue
1998
- if (prev.mapUnsafe.has(key)) {
1999
- map.set(key, prev.mapUnsafe.get(key))
2000
- } else {
2001
- map.delete(key)
2002
- }
2003
- }
2004
- fiber.setServices(ServiceMap.makeUnsafe(map))
2022
+ return onExitPrimitive(self, () => {
2023
+ fiber.setServices(prev)
2005
2024
  return undefined
2006
2025
  })
2007
2026
  })
@@ -2025,12 +2044,11 @@ export const updateService: {
2025
2044
  service: ServiceMap.Service<I, A>,
2026
2045
  f: (value: A) => A
2027
2046
  ): Effect.Effect<XA, E, R | I> =>
2028
- withFiber((fiber) => {
2029
- const prev = ServiceMap.getUnsafe(fiber.services, service)
2047
+ updateServices(self, (s) => {
2048
+ const prev = ServiceMap.getUnsafe(s, service)
2030
2049
  const next = f(prev)
2031
- if (prev === next) return self
2032
- fiber.setServices(ServiceMap.add(fiber.services, service, next))
2033
- return onExit(self, () => sync(() => fiber.setServices(ServiceMap.add(fiber.services, service, prev))))
2050
+ if (prev === next) return s
2051
+ return ServiceMap.add(s, service, next)
2034
2052
  })
2035
2053
  )
2036
2054
 
@@ -2097,11 +2115,10 @@ const provideServiceImpl = <A, E, R, I, S>(
2097
2115
  service: ServiceMap.Service<I, S>,
2098
2116
  implementation: S
2099
2117
  ): Effect.Effect<A, E, Exclude<R, I>> =>
2100
- withFiber((fiber) => {
2101
- const prev = ServiceMap.getOption(fiber.services, service)
2102
- if (prev._tag === "Some" && prev.value === implementation) return self
2103
- fiber.setServices(ServiceMap.add(fiber.services, service, implementation))
2104
- return onExit(self, () => sync(() => fiber.setServices(ServiceMap.addOrOmit(fiber.services, service, prev))))
2118
+ updateServices(self, (s) => {
2119
+ const prev = s.mapUnsafe.get(service.key)
2120
+ if (prev === implementation) return s
2121
+ return ServiceMap.add(s, service, implementation)
2105
2122
  }) as any
2106
2123
 
2107
2124
  /** @internal */
@@ -3093,14 +3110,14 @@ export const eventually = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect
3093
3110
  /** @internal */
3094
3111
  export const ignore: <
3095
3112
  Arg extends Effect.Effect<any, any, any> | {
3096
- readonly log?: boolean | LogLevel.LogLevel | undefined
3113
+ readonly log?: boolean | LogLevel.Severity | undefined
3097
3114
  } | undefined = {
3098
- readonly log?: boolean | LogLevel.LogLevel | undefined
3115
+ readonly log?: boolean | LogLevel.Severity | undefined
3099
3116
  }
3100
3117
  >(
3101
3118
  effectOrOptions: Arg,
3102
3119
  options?: {
3103
- readonly log?: boolean | LogLevel.LogLevel | undefined
3120
+ readonly log?: boolean | LogLevel.Severity | undefined
3104
3121
  } | undefined
3105
3122
  ) => [Arg] extends [Effect.Effect<infer _A, infer _E, infer _R>] ? Effect.Effect<void, never, _R>
3106
3123
  : <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, never, R> = dual(
@@ -3108,7 +3125,7 @@ export const ignore: <
3108
3125
  <A, E, R>(
3109
3126
  self: Effect.Effect<A, E, R>,
3110
3127
  options?: {
3111
- readonly log?: boolean | LogLevel.LogLevel | undefined
3128
+ readonly log?: boolean | LogLevel.Severity | undefined
3112
3129
  } | undefined
3113
3130
  ): Effect.Effect<void, never, R> => {
3114
3131
  if (!options?.log) {
@@ -3128,14 +3145,14 @@ export const ignore: <
3128
3145
  /** @internal */
3129
3146
  export const ignoreCause: <
3130
3147
  Arg extends Effect.Effect<any, any, any> | {
3131
- readonly log?: boolean | LogLevel.LogLevel | undefined
3148
+ readonly log?: boolean | LogLevel.Severity | undefined
3132
3149
  } | undefined = {
3133
- readonly log?: boolean | LogLevel.LogLevel | undefined
3150
+ readonly log?: boolean | LogLevel.Severity | undefined
3134
3151
  }
3135
3152
  >(
3136
3153
  effectOrOptions: Arg,
3137
3154
  options?: {
3138
- readonly log?: boolean | LogLevel.LogLevel | undefined
3155
+ readonly log?: boolean | LogLevel.Severity | undefined
3139
3156
  } | undefined
3140
3157
  ) => [Arg] extends [Effect.Effect<infer _A, infer _E, infer _R>] ? Effect.Effect<void, never, _R>
3141
3158
  : <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, never, R> = dual(
@@ -3143,7 +3160,7 @@ export const ignoreCause: <
3143
3160
  <A, E, R>(
3144
3161
  self: Effect.Effect<A, E, R>,
3145
3162
  options?: {
3146
- readonly log?: boolean | LogLevel.LogLevel | undefined
3163
+ readonly log?: boolean | LogLevel.Severity | undefined
3147
3164
  } | undefined
3148
3165
  ): Effect.Effect<void, never, R> => {
3149
3166
  if (!options?.log) {
@@ -3648,11 +3665,11 @@ export const provideScope: {
3648
3665
  /** @internal */
3649
3666
  export const scoped = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, Exclude<R, Scope.Scope>> =>
3650
3667
  withFiber((fiber) => {
3651
- const prev = ServiceMap.getOption(fiber.services, scopeTag)
3668
+ const prev = fiber.services
3652
3669
  const scope = scopeMakeUnsafe()
3653
3670
  fiber.setServices(ServiceMap.add(fiber.services, scopeTag, scope))
3654
3671
  return onExitPrimitive(self, (exit) => {
3655
- fiber.setServices(ServiceMap.addOrOmit(fiber.services, scopeTag, prev))
3672
+ fiber.setServices(prev)
3656
3673
  return scopeCloseUnsafe(scope, exit)
3657
3674
  })
3658
3675
  }) as any
@@ -4080,6 +4097,59 @@ export const partition: {
4080
4097
  )
4081
4098
  )
4082
4099
 
4100
+ /** @internal */
4101
+ export const validate: {
4102
+ <A, B, E, R>(
4103
+ f: (a: A, i: number) => Effect.Effect<B, E, R>,
4104
+ options?: {
4105
+ readonly concurrency?: Concurrency | undefined
4106
+ readonly discard?: false | undefined
4107
+ } | undefined
4108
+ ): (elements: Iterable<A>) => Effect.Effect<Array<B>, Arr.NonEmptyArray<E>, R>
4109
+ <A, B, E, R>(
4110
+ f: (a: A, i: number) => Effect.Effect<B, E, R>,
4111
+ options: {
4112
+ readonly concurrency?: Concurrency | undefined
4113
+ readonly discard: true
4114
+ }
4115
+ ): (elements: Iterable<A>) => Effect.Effect<void, Arr.NonEmptyArray<E>, R>
4116
+ <A, B, E, R>(
4117
+ elements: Iterable<A>,
4118
+ f: (a: A, i: number) => Effect.Effect<B, E, R>,
4119
+ options?: {
4120
+ readonly concurrency?: Concurrency | undefined
4121
+ readonly discard?: false | undefined
4122
+ } | undefined
4123
+ ): Effect.Effect<Array<B>, Arr.NonEmptyArray<E>, R>
4124
+ <A, B, E, R>(
4125
+ elements: Iterable<A>,
4126
+ f: (a: A, i: number) => Effect.Effect<B, E, R>,
4127
+ options: {
4128
+ readonly concurrency?: Concurrency | undefined
4129
+ readonly discard: true
4130
+ }
4131
+ ): Effect.Effect<void, Arr.NonEmptyArray<E>, R>
4132
+ } = dual(
4133
+ (args) => isIterable(args[0]) && !isEffect(args[0]),
4134
+ <A, B, E, R>(
4135
+ elements: Iterable<A>,
4136
+ f: (a: A, i: number) => Effect.Effect<B, E, R>,
4137
+ options?: {
4138
+ readonly concurrency?: Concurrency | undefined
4139
+ readonly discard?: boolean | undefined
4140
+ } | undefined
4141
+ ): Effect.Effect<Array<B> | void, Arr.NonEmptyArray<E>, R> =>
4142
+ flatMap(
4143
+ partition(elements, f, { concurrency: options?.concurrency }),
4144
+ ([excluded, satisfying]) => {
4145
+ if (Arr.isArrayNonEmpty(excluded)) {
4146
+ return fail(excluded)
4147
+ }
4148
+ return options?.discard ? void_ : succeed(satisfying)
4149
+ }
4150
+ )
4151
+ )
4152
+
4083
4153
  /** @internal */
4084
4154
  export const whileLoop: <A, E, R>(options: {
4085
4155
  readonly while: LazyArg<boolean>
@@ -5484,6 +5554,40 @@ export const LogToStderr = ServiceMap.Reference<boolean>("effect/Logger/LogToStd
5484
5554
  defaultValue: constFalse
5485
5555
  })
5486
5556
 
5557
+ /** @internal */
5558
+ export const annotateLogsScoped: {
5559
+ (key: string, value: unknown): Effect.Effect<void, never, Scope.Scope>
5560
+ (values: Record<string, unknown>): Effect.Effect<void, never, Scope.Scope>
5561
+ } = function() {
5562
+ const entries = typeof arguments[0] === "string" ?
5563
+ [[arguments[0], arguments[1]]] :
5564
+ Object.entries(arguments[0])
5565
+ return uninterruptible(withFiber((fiber) => {
5566
+ const prev = fiber.getRef(CurrentLogAnnotations)
5567
+ const next = { ...prev }
5568
+ for (let i = 0; i < entries.length; i++) {
5569
+ const [key, value] = entries[i]
5570
+ next[key] = value
5571
+ }
5572
+ fiber.setServices(ServiceMap.add(fiber.services, CurrentLogAnnotations, next))
5573
+ return scopeAddFinalizerExit(ServiceMap.getUnsafe(fiber.services, scopeTag), (_) => {
5574
+ const current = fiber.getRef(CurrentLogAnnotations)
5575
+ const next = { ...current }
5576
+ for (let i = 0; i < entries.length; i++) {
5577
+ const [key, value] = entries[i]
5578
+ if (current[key] !== value) continue
5579
+ if (key in prev) {
5580
+ next[key] = prev[key]
5581
+ } else {
5582
+ delete next[key]
5583
+ }
5584
+ }
5585
+ fiber.setServices(ServiceMap.add(fiber.services, CurrentLogAnnotations, next))
5586
+ return void_
5587
+ })
5588
+ }))
5589
+ }
5590
+
5487
5591
  /** @internal */
5488
5592
  export const LoggerTypeId = "~effect/Logger"
5489
5593
 
@@ -5499,7 +5603,7 @@ const LoggerProto = {
5499
5603
 
5500
5604
  /** @internal */
5501
5605
  export const loggerMake = <Message, Output>(
5502
- log: (options: Logger.Logger.Options<Message>) => Output
5606
+ log: (options: Logger.Options<Message>) => Output
5503
5607
  ): Logger.Logger<Message, Output> => {
5504
5608
  const self = Object.create(LoggerProto)
5505
5609
  self.log = log
@@ -5539,7 +5643,7 @@ export const structuredMessage = (u: unknown): unknown => {
5539
5643
  }
5540
5644
 
5541
5645
  /** @internal */
5542
- export const logWithLevel = (level?: LogLevel.LogLevel) =>
5646
+ export const logWithLevel = (level?: LogLevel.Severity) =>
5543
5647
  (
5544
5648
  ...message: ReadonlyArray<any>
5545
5649
  ): Effect.Effect<void> => {
@@ -5830,3 +5934,55 @@ const undefined_ = succeed(undefined)
5830
5934
 
5831
5935
  /** @internal */
5832
5936
  export { undefined_ as undefined }
5937
+
5938
+ // ----------------------------------------------------------------------------
5939
+ // ErrorReporter
5940
+ // ----------------------------------------------------------------------------
5941
+
5942
+ /** @internal */
5943
+ export const CurrentErrorReporters = ServiceMap.Reference<
5944
+ ReadonlySet<ErrorReporter>
5945
+ >("effect/ErrorReporter/CurrentErrorReporters", {
5946
+ defaultValue: () => new Set()
5947
+ })
5948
+
5949
+ /** @internal */
5950
+ export const withErrorReporting: <
5951
+ Arg extends Effect.Effect<any, any, any> | {
5952
+ readonly defectsOnly?: boolean | undefined
5953
+ } | undefined = {
5954
+ readonly defectsOnly?: boolean | undefined
5955
+ }
5956
+ >(
5957
+ effectOrOptions: Arg,
5958
+ options?: {
5959
+ readonly defectsOnly?: boolean | undefined
5960
+ } | undefined
5961
+ ) => [Arg] extends [Effect.Effect<infer _A, infer _E, infer _R>] ? Arg
5962
+ : <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> = dual(
5963
+ (args) => isEffect(args[0]),
5964
+ <A, E, R>(
5965
+ self: Effect.Effect<A, E, R>,
5966
+ options?: {
5967
+ readonly defectsOnly?: boolean | undefined
5968
+ } | undefined
5969
+ ): Effect.Effect<A, E, R> =>
5970
+ onError(self, (cause) =>
5971
+ withFiber((fiber) => {
5972
+ reportCauseUnsafe(fiber, cause, options?.defectsOnly)
5973
+ return void_
5974
+ }))
5975
+ )
5976
+
5977
+ /** @internal */
5978
+ export const reportCauseUnsafe = (
5979
+ fiber: Fiber.Fiber<unknown, unknown>,
5980
+ cause: Cause.Cause<unknown>,
5981
+ defectsOnly?: boolean
5982
+ ) => {
5983
+ const reporters = fiber.getRef(CurrentErrorReporters)
5984
+ if (reporters.size === 0) return
5985
+ if (defectsOnly && !hasDies(cause)) return
5986
+ const opts = { cause, fiber, timestamp: fiber.getRef(ClockRef).currentTimeNanosUnsafe() }
5987
+ reporters.forEach((reporter) => reporter.report(opts))
5988
+ }
@@ -83,7 +83,7 @@ function mergeLeaves<K, V>(
83
83
  }
84
84
 
85
85
  const bitmap = bit1 | bit2
86
- const children: Array<Node<K, V>> = bit1 < bit2
86
+ const children: Array<Node<K, V>> = (bit1 >>> 0) < (bit2 >>> 0)
87
87
  ? [node1, node2]
88
88
  : [node2, node1]
89
89
 
@@ -248,7 +248,7 @@ class LeafNode<K, V> extends Node<K, V> {
248
248
  }
249
249
 
250
250
  const bitmap = newBit | existingBit
251
- const nodes: Array<Node<K, V>> = newBit < existingBit
251
+ const nodes: Array<Node<K, V>> = (newBit >>> 0) < (existingBit >>> 0)
252
252
  ? [new LeafNode(edit, hash, key, value), this]
253
253
  : [this, new LeafNode(edit, hash, key, value)]
254
254
 
@@ -949,9 +949,8 @@ export const make: (params: ConstructorParams) => Effect.Effect<Service> = Effec
949
949
  return content as Array<Response.Part<Tools>>
950
950
  }
951
951
 
952
- // Pre-resolve tool approvals before calling the LLM
952
+ // Pre-resolve pending tool approvals before calling the LLM
953
953
  if (hasPendingApprovals) {
954
- // Validate all approved tools exist in the toolkit
955
954
  for (const approval of approved) {
956
955
  if (approval.toolCall && !toolkit.tools[approval.toolCall.name]) {
957
956
  return yield* AiError.make({
@@ -965,7 +964,6 @@ export const make: (params: ConstructorParams) => Effect.Effect<Service> = Effec
965
964
  }
966
965
  }
967
966
 
968
- // Execute approved tools and create denial results
969
967
  const approvedResults = yield* executeApprovedToolCalls(
970
968
  approved,
971
969
  toolkit,
@@ -974,18 +972,29 @@ export const make: (params: ConstructorParams) => Effect.Effect<Service> = Effec
974
972
  const deniedResults = createDenialResults(denied)
975
973
  const preResolvedResults = [...approvedResults, ...deniedResults]
976
974
 
977
- // Add pre-resolved results to the prompt
978
975
  if (preResolvedResults.length > 0) {
979
- const toolMessage = Prompt.makeMessage("tool", {
980
- content: preResolvedResults
981
- })
982
976
  providerOptions.prompt = Prompt.fromMessages([
983
977
  ...providerOptions.prompt.content,
984
- toolMessage
978
+ Prompt.makeMessage("tool", { content: preResolvedResults })
985
979
  ])
986
980
  }
987
981
  }
988
982
 
983
+ // Strip all resolved approval artifacts (both current and from previous
984
+ // rounds) in a single pass before sending to the provider.
985
+ {
986
+ const { approved: allResolved, denied: allDenied } = collectToolApprovals(
987
+ providerOptions.prompt.content
988
+ )
989
+ if (allResolved.length > 0 || allDenied.length > 0) {
990
+ providerOptions.prompt = stripResolvedApprovals(
991
+ providerOptions.prompt,
992
+ allResolved,
993
+ allDenied
994
+ )
995
+ }
996
+ }
997
+
989
998
  const tools = typeof toolChoice === "object" && "oneOf" in toolChoice
990
999
  ? Object.values(toolkit.tools).filter((tool) => toolChoice.oneOf.includes(tool.name))
991
1000
  : Object.values(toolkit.tools)
@@ -1130,9 +1139,10 @@ export const make: (params: ConstructorParams) => Effect.Effect<Service> = Effec
1130
1139
  >
1131
1140
  }
1132
1141
 
1133
- // Pre-resolve tool approvals before calling the LLM
1142
+ // Pre-resolve pending tool approvals before calling the LLM
1143
+ let preResolvedStreamParts: Array<Response.StreamPart<Tools>> = []
1144
+
1134
1145
  if (hasPendingApprovals) {
1135
- // Validate all approved tools exist in the toolkit
1136
1146
  for (const approval of pendingApproved) {
1137
1147
  if (approval.toolCall && !toolkit.tools[approval.toolCall.name]) {
1138
1148
  return yield* AiError.make({
@@ -1146,7 +1156,6 @@ export const make: (params: ConstructorParams) => Effect.Effect<Service> = Effec
1146
1156
  }
1147
1157
  }
1148
1158
 
1149
- // Execute approved tools and create denial results
1150
1159
  const approvedResults = yield* executeApprovedToolCalls(
1151
1160
  pendingApproved,
1152
1161
  toolkit,
@@ -1155,16 +1164,44 @@ export const make: (params: ConstructorParams) => Effect.Effect<Service> = Effec
1155
1164
  const deniedResults = createDenialResults(pendingDenied)
1156
1165
  const preResolvedResults = [...approvedResults, ...deniedResults]
1157
1166
 
1158
- // Add pre-resolved results to the prompt
1159
1167
  if (preResolvedResults.length > 0) {
1160
- const toolMessage = Prompt.makeMessage("tool", {
1161
- content: preResolvedResults
1162
- })
1163
1168
  providerOptions.prompt = Prompt.fromMessages([
1164
1169
  ...providerOptions.prompt.content,
1165
- toolMessage
1170
+ Prompt.makeMessage("tool", { content: preResolvedResults })
1166
1171
  ])
1167
1172
  }
1173
+
1174
+ // Emit pre-resolved tool-results as stream parts so Chat.streamText
1175
+ // persists them to history. This lets collectToolApprovals find them
1176
+ // on subsequent rounds and skip the now-resolved approvals.
1177
+ // Note: r.result is already encoded (from executeApprovedToolCalls /
1178
+ // createDenialResults), so it goes into both result and encodedResult.
1179
+ for (const r of preResolvedResults) {
1180
+ preResolvedStreamParts.push(
1181
+ Response.makePart("tool-result", {
1182
+ id: r.id,
1183
+ name: r.name,
1184
+ providerExecuted: false,
1185
+ preliminary: false,
1186
+ result: r.result,
1187
+ encodedResult: r.result,
1188
+ isFailure: r.isFailure
1189
+ }) as Response.StreamPart<Tools>
1190
+ )
1191
+ }
1192
+ }
1193
+
1194
+ // Strip all resolved approval artifacts (both current and from previous
1195
+ // rounds) in a single pass before sending to the provider.
1196
+ const { approved: allResolved, denied: allDenied } = collectToolApprovals(
1197
+ providerOptions.prompt.content
1198
+ )
1199
+ if (allResolved.length > 0 || allDenied.length > 0) {
1200
+ providerOptions.prompt = stripResolvedApprovals(
1201
+ providerOptions.prompt,
1202
+ allResolved,
1203
+ allDenied
1204
+ )
1168
1205
  }
1169
1206
 
1170
1207
  const tools = typeof toolChoice === "object" && "oneOf" in toolChoice
@@ -1201,6 +1238,13 @@ export const make: (params: ConstructorParams) => Effect.Effect<Service> = Effec
1201
1238
  | Schema.SchemaError
1202
1239
  >()
1203
1240
 
1241
+ // Emit pre-resolved tool results so Chat.streamText persists them to
1242
+ // history. This ensures collectToolApprovals({ excludeResolved }) can
1243
+ // find the corresponding tool-results on future rounds.
1244
+ if (preResolvedStreamParts.length > 0) {
1245
+ yield* Queue.offerAll(queue, preResolvedStreamParts)
1246
+ }
1247
+
1204
1248
  // FiberSet to track concurrent tool call handlers
1205
1249
  const toolCallFibers = yield* FiberSet.make<void, AiError.AiError>()
1206
1250
 
@@ -1506,6 +1550,63 @@ const collectToolApprovals = (
1506
1550
  return { approved, denied }
1507
1551
  }
1508
1552
 
1553
+ /**
1554
+ * Strip resolved approval artifacts from the prompt before sending to the
1555
+ * provider. After pre-resolving approvals (executing approved tools and
1556
+ * creating denial results), the original `tool-approval-request` parts in
1557
+ * assistant messages and `tool-approval-response` parts in tool messages are
1558
+ * no longer needed. Leaving them in causes provider-specific errors (e.g.
1559
+ * OpenAI rejects `mcp_approval_response` items that reference approval
1560
+ * requests it never issued).
1561
+ */
1562
+ const stripResolvedApprovals = (
1563
+ prompt: Prompt.Prompt,
1564
+ approved: ReadonlyArray<ApprovalResult>,
1565
+ denied: ReadonlyArray<ApprovalResult>
1566
+ ): Prompt.Prompt => {
1567
+ const resolvedApprovalIds = new Set<string>()
1568
+ for (const a of approved) resolvedApprovalIds.add(a.approvalId)
1569
+ for (const d of denied) resolvedApprovalIds.add(d.approvalId)
1570
+
1571
+ const cleanedMessages: Array<Prompt.Message> = []
1572
+
1573
+ for (const message of prompt.content) {
1574
+ if (message.role === "assistant") {
1575
+ const filteredContent = message.content.filter(
1576
+ (part) =>
1577
+ part.type !== "tool-approval-request" ||
1578
+ !resolvedApprovalIds.has(part.approvalId)
1579
+ )
1580
+ if (filteredContent.length > 0) {
1581
+ cleanedMessages.push(
1582
+ Prompt.makeMessage("assistant", {
1583
+ content: filteredContent,
1584
+ options: message.options
1585
+ })
1586
+ )
1587
+ }
1588
+ } else if (message.role === "tool") {
1589
+ const filteredContent = message.content.filter(
1590
+ (part) =>
1591
+ part.type !== "tool-approval-response" ||
1592
+ !resolvedApprovalIds.has(part.approvalId)
1593
+ )
1594
+ if (filteredContent.length > 0) {
1595
+ cleanedMessages.push(
1596
+ Prompt.makeMessage("tool", {
1597
+ content: filteredContent,
1598
+ options: message.options
1599
+ })
1600
+ )
1601
+ }
1602
+ } else {
1603
+ cleanedMessages.push(message)
1604
+ }
1605
+ }
1606
+
1607
+ return Prompt.fromMessages(cleanedMessages)
1608
+ }
1609
+
1509
1610
  const isApprovalNeeded = Effect.fnUntraced(function*<T extends Tool.Any>(
1510
1611
  tool: T,
1511
1612
  toolCall: Response.ToolCallPartEncoded,