effect 4.0.0-beta.10 → 4.0.0-beta.11

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 (122) hide show
  1. package/dist/Channel.d.ts +7 -7
  2. package/dist/Effect.d.ts +217 -8
  3. package/dist/Effect.d.ts.map +1 -1
  4. package/dist/Effect.js +46 -0
  5. package/dist/Effect.js.map +1 -1
  6. package/dist/ErrorReporter.d.ts +376 -0
  7. package/dist/ErrorReporter.d.ts.map +1 -0
  8. package/dist/ErrorReporter.js +246 -0
  9. package/dist/ErrorReporter.js.map +1 -0
  10. package/dist/LogLevel.d.ts +5 -0
  11. package/dist/LogLevel.d.ts.map +1 -1
  12. package/dist/LogLevel.js.map +1 -1
  13. package/dist/Logger.d.ts +25 -91
  14. package/dist/Logger.d.ts.map +1 -1
  15. package/dist/Logger.js +2 -3
  16. package/dist/Logger.js.map +1 -1
  17. package/dist/Queue.d.ts.map +1 -1
  18. package/dist/Queue.js +0 -1
  19. package/dist/Queue.js.map +1 -1
  20. package/dist/References.d.ts +3 -3
  21. package/dist/References.d.ts.map +1 -1
  22. package/dist/SchemaAST.d.ts.map +1 -1
  23. package/dist/SchemaAST.js +2 -1
  24. package/dist/SchemaAST.js.map +1 -1
  25. package/dist/Stream.d.ts +5 -5
  26. package/dist/index.d.ts +4 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +4 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/internal/effect.js +54 -4
  31. package/dist/internal/effect.js.map +1 -1
  32. package/dist/internal/hashMap.js +2 -2
  33. package/dist/internal/hashMap.js.map +1 -1
  34. package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
  35. package/dist/unstable/ai/LanguageModel.js +41 -0
  36. package/dist/unstable/ai/LanguageModel.js.map +1 -1
  37. package/dist/unstable/cli/CliOutput.js +37 -6
  38. package/dist/unstable/cli/CliOutput.js.map +1 -1
  39. package/dist/unstable/cli/Command.d.ts +199 -7
  40. package/dist/unstable/cli/Command.d.ts.map +1 -1
  41. package/dist/unstable/cli/Command.js +116 -6
  42. package/dist/unstable/cli/Command.js.map +1 -1
  43. package/dist/unstable/cli/HelpDoc.d.ts +60 -2
  44. package/dist/unstable/cli/HelpDoc.d.ts.map +1 -1
  45. package/dist/unstable/cli/internal/command.d.ts +11 -1
  46. package/dist/unstable/cli/internal/command.d.ts.map +1 -1
  47. package/dist/unstable/cli/internal/command.js +33 -8
  48. package/dist/unstable/cli/internal/command.js.map +1 -1
  49. package/dist/unstable/cli/internal/completions/CommandDescriptor.js +7 -2
  50. package/dist/unstable/cli/internal/completions/CommandDescriptor.js.map +1 -1
  51. package/dist/unstable/cli/internal/parser.js +10 -2
  52. package/dist/unstable/cli/internal/parser.js.map +1 -1
  53. package/dist/unstable/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  54. package/dist/unstable/http/Headers.d.ts.map +1 -1
  55. package/dist/unstable/http/Headers.js +27 -10
  56. package/dist/unstable/http/Headers.js.map +1 -1
  57. package/dist/unstable/http/HttpEffect.d.ts.map +1 -1
  58. package/dist/unstable/http/HttpEffect.js +12 -7
  59. package/dist/unstable/http/HttpEffect.js.map +1 -1
  60. package/dist/unstable/http/HttpServerError.d.ts +8 -26
  61. package/dist/unstable/http/HttpServerError.d.ts.map +1 -1
  62. package/dist/unstable/http/HttpServerError.js +11 -27
  63. package/dist/unstable/http/HttpServerError.js.map +1 -1
  64. package/dist/unstable/http/HttpServerRespondable.d.ts +2 -2
  65. package/dist/unstable/http/HttpServerRespondable.d.ts.map +1 -1
  66. package/dist/unstable/http/HttpServerRespondable.js +5 -5
  67. package/dist/unstable/http/HttpServerRespondable.js.map +1 -1
  68. package/dist/unstable/http/HttpServerResponse.d.ts +2 -1
  69. package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
  70. package/dist/unstable/http/HttpServerResponse.js +2 -0
  71. package/dist/unstable/http/HttpServerResponse.js.map +1 -1
  72. package/dist/unstable/httpapi/HttpApiBuilder.js +1 -1
  73. package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
  74. package/dist/unstable/httpapi/HttpApiError.d.ts +11 -0
  75. package/dist/unstable/httpapi/HttpApiError.d.ts.map +1 -1
  76. package/dist/unstable/httpapi/HttpApiError.js +29 -9
  77. package/dist/unstable/httpapi/HttpApiError.js.map +1 -1
  78. package/dist/unstable/observability/OtlpLogger.d.ts.map +1 -1
  79. package/dist/unstable/observability/OtlpLogger.js +7 -4
  80. package/dist/unstable/observability/OtlpLogger.js.map +1 -1
  81. package/dist/unstable/reactivity/AtomRegistry.d.ts +6 -0
  82. package/dist/unstable/reactivity/AtomRegistry.d.ts.map +1 -1
  83. package/dist/unstable/reactivity/AtomRegistry.js +22 -1
  84. package/dist/unstable/reactivity/AtomRegistry.js.map +1 -1
  85. package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
  86. package/dist/unstable/rpc/RpcServer.js +4 -0
  87. package/dist/unstable/rpc/RpcServer.js.map +1 -1
  88. package/dist/unstable/workflow/WorkflowEngine.d.ts +6 -0
  89. package/dist/unstable/workflow/WorkflowEngine.d.ts.map +1 -1
  90. package/dist/unstable/workflow/WorkflowEngine.js +131 -0
  91. package/dist/unstable/workflow/WorkflowEngine.js.map +1 -1
  92. package/package.json +1 -1
  93. package/src/Channel.ts +9 -9
  94. package/src/Effect.ts +235 -8
  95. package/src/ErrorReporter.ts +459 -0
  96. package/src/LogLevel.ts +6 -0
  97. package/src/Logger.ts +28 -95
  98. package/src/Queue.ts +0 -1
  99. package/src/References.ts +4 -4
  100. package/src/SchemaAST.ts +2 -1
  101. package/src/Stream.ts +7 -7
  102. package/src/index.ts +5 -0
  103. package/src/internal/effect.ts +137 -14
  104. package/src/internal/hashMap.ts +2 -2
  105. package/src/unstable/ai/LanguageModel.ts +71 -0
  106. package/src/unstable/cli/CliOutput.ts +45 -6
  107. package/src/unstable/cli/Command.ts +298 -11
  108. package/src/unstable/cli/HelpDoc.ts +68 -2
  109. package/src/unstable/cli/internal/command.ts +47 -11
  110. package/src/unstable/cli/internal/completions/CommandDescriptor.ts +7 -2
  111. package/src/unstable/cli/internal/parser.ts +11 -3
  112. package/src/unstable/http/Headers.ts +28 -13
  113. package/src/unstable/http/HttpEffect.ts +10 -5
  114. package/src/unstable/http/HttpServerError.ts +13 -27
  115. package/src/unstable/http/HttpServerRespondable.ts +6 -6
  116. package/src/unstable/http/HttpServerResponse.ts +3 -1
  117. package/src/unstable/httpapi/HttpApiBuilder.ts +1 -0
  118. package/src/unstable/httpapi/HttpApiError.ts +30 -9
  119. package/src/unstable/observability/OtlpLogger.ts +9 -5
  120. package/src/unstable/reactivity/AtomRegistry.ts +29 -1
  121. package/src/unstable/rpc/RpcServer.ts +4 -0
  122. package/src/unstable/workflow/WorkflowEngine.ts +178 -0
package/src/SchemaAST.ts CHANGED
@@ -1455,7 +1455,8 @@ export class Arrays extends Base {
1455
1455
  // handle post rest elements
1456
1456
  // ---------------------------------------------
1457
1457
  for (let j = 0; j < tail.length; j++) {
1458
- if (len < i + 1) {
1458
+ i += j
1459
+ if (len < i) {
1459
1460
  continue
1460
1461
  } else {
1461
1462
  const tailj = tail[j]
package/src/Stream.ts CHANGED
@@ -22,7 +22,7 @@ import { addSpanStackTrace } from "./internal/tracer.ts"
22
22
  import * as Iterable from "./Iterable.ts"
23
23
  import * as Latch from "./Latch.ts"
24
24
  import type * as Layer from "./Layer.ts"
25
- import type { LogLevel } from "./LogLevel.ts"
25
+ import type { Severity } from "./LogLevel.ts"
26
26
  import * as MutableHashMap from "./MutableHashMap.ts"
27
27
  import * as MutableList from "./MutableList.ts"
28
28
  import * as Option from "./Option.ts"
@@ -8820,12 +8820,12 @@ export const orDie = <A, E, R>(self: Stream<A, E, R>): Stream<A, never, R> => fr
8820
8820
  */
8821
8821
  export const ignore: <
8822
8822
  Arg extends Stream<any, any, any> | {
8823
- readonly log?: boolean | LogLevel | undefined
8823
+ readonly log?: boolean | Severity | undefined
8824
8824
  } | undefined
8825
8825
  >(
8826
8826
  selfOrOptions: Arg,
8827
8827
  options?: {
8828
- readonly log?: boolean | LogLevel | undefined
8828
+ readonly log?: boolean | Severity | undefined
8829
8829
  } | undefined
8830
8830
  ) => [Arg] extends [Stream<infer A, infer _E, infer R>] ? Stream<A, never, R>
8831
8831
  : <A, E, R>(self: Stream<A, E, R>) => Stream<A, never, R> = dual(
@@ -8833,7 +8833,7 @@ export const ignore: <
8833
8833
  <A, E, R>(
8834
8834
  self: Stream<A, E, R>,
8835
8835
  options?: {
8836
- readonly log?: boolean | LogLevel | undefined
8836
+ readonly log?: boolean | Severity | undefined
8837
8837
  } | undefined
8838
8838
  ): Stream<A, never, R> => fromChannel(Channel.ignore(self.channel, options))
8839
8839
  )
@@ -8860,19 +8860,19 @@ export const ignore: <
8860
8860
  */
8861
8861
  export const ignoreCause: <
8862
8862
  Arg extends Stream<any, any, any> | {
8863
- readonly log?: boolean | LogLevel | undefined
8863
+ readonly log?: boolean | Severity | undefined
8864
8864
  } | undefined
8865
8865
  >(
8866
8866
  streamOrOptions: Arg,
8867
8867
  options?: {
8868
- readonly log?: boolean | LogLevel | undefined
8868
+ readonly log?: boolean | Severity | undefined
8869
8869
  } | undefined
8870
8870
  ) => [Arg] extends [Stream<infer A, infer _E, infer R>] ? Stream<A, never, R>
8871
8871
  : <A, E, R>(self: Stream<A, E, R>) => Stream<A, never, R> = dual(
8872
8872
  (args) => isStream(args[0]),
8873
8873
  <A, E, R>(
8874
8874
  self: Stream<A, E, R>,
8875
- options?: { readonly log?: boolean | LogLevel | undefined } | undefined
8875
+ options?: { readonly log?: boolean | Severity | undefined } | undefined
8876
8876
  ): Stream<A, never, R> => fromChannel(Channel.ignoreCause(self.channel, options))
8877
8877
  )
8878
8878
 
package/src/index.ts CHANGED
@@ -1119,6 +1119,11 @@ export * as Equal from "./Equal.ts"
1119
1119
  */
1120
1120
  export * as Equivalence from "./Equivalence.ts"
1121
1121
 
1122
+ /**
1123
+ * @since 4.0.0
1124
+ */
1125
+ export * as ErrorReporter from "./ErrorReporter.ts"
1126
+
1122
1127
  /**
1123
1128
  * @since 3.16.0
1124
1129
  */
@@ -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
+ const start = (() => {
496
+ const setInterval = globalThis.setInterval
497
+ const clearInterval = globalThis.clearInterval
498
+ try {
499
+ const running = setInterval(constVoid, 2_147_483_647)
500
+ clearInterval(running)
501
+ return {
502
+ setInterval,
503
+ clearInterval
504
+ }
505
+ } catch {
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 (start !== undefined && running === undefined) {
515
+ running = start.setInterval(constVoid, 2_147_483_647)
516
+ }
499
517
  },
500
518
  decrement() {
501
519
  count--
502
- if (count === 0 && running !== undefined) {
503
- globalThis.clearInterval(running)
520
+ if (count === 0 && start !== undefined && running !== undefined) {
521
+ start.clearInterval(running)
504
522
  running = undefined
505
523
  }
506
524
  }
@@ -3093,14 +3111,14 @@ export const eventually = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect
3093
3111
  /** @internal */
3094
3112
  export const ignore: <
3095
3113
  Arg extends Effect.Effect<any, any, any> | {
3096
- readonly log?: boolean | LogLevel.LogLevel | undefined
3114
+ readonly log?: boolean | LogLevel.Severity | undefined
3097
3115
  } | undefined = {
3098
- readonly log?: boolean | LogLevel.LogLevel | undefined
3116
+ readonly log?: boolean | LogLevel.Severity | undefined
3099
3117
  }
3100
3118
  >(
3101
3119
  effectOrOptions: Arg,
3102
3120
  options?: {
3103
- readonly log?: boolean | LogLevel.LogLevel | undefined
3121
+ readonly log?: boolean | LogLevel.Severity | undefined
3104
3122
  } | undefined
3105
3123
  ) => [Arg] extends [Effect.Effect<infer _A, infer _E, infer _R>] ? Effect.Effect<void, never, _R>
3106
3124
  : <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, never, R> = dual(
@@ -3108,7 +3126,7 @@ export const ignore: <
3108
3126
  <A, E, R>(
3109
3127
  self: Effect.Effect<A, E, R>,
3110
3128
  options?: {
3111
- readonly log?: boolean | LogLevel.LogLevel | undefined
3129
+ readonly log?: boolean | LogLevel.Severity | undefined
3112
3130
  } | undefined
3113
3131
  ): Effect.Effect<void, never, R> => {
3114
3132
  if (!options?.log) {
@@ -3128,14 +3146,14 @@ export const ignore: <
3128
3146
  /** @internal */
3129
3147
  export const ignoreCause: <
3130
3148
  Arg extends Effect.Effect<any, any, any> | {
3131
- readonly log?: boolean | LogLevel.LogLevel | undefined
3149
+ readonly log?: boolean | LogLevel.Severity | undefined
3132
3150
  } | undefined = {
3133
- readonly log?: boolean | LogLevel.LogLevel | undefined
3151
+ readonly log?: boolean | LogLevel.Severity | undefined
3134
3152
  }
3135
3153
  >(
3136
3154
  effectOrOptions: Arg,
3137
3155
  options?: {
3138
- readonly log?: boolean | LogLevel.LogLevel | undefined
3156
+ readonly log?: boolean | LogLevel.Severity | undefined
3139
3157
  } | undefined
3140
3158
  ) => [Arg] extends [Effect.Effect<infer _A, infer _E, infer _R>] ? Effect.Effect<void, never, _R>
3141
3159
  : <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, never, R> = dual(
@@ -3143,7 +3161,7 @@ export const ignoreCause: <
3143
3161
  <A, E, R>(
3144
3162
  self: Effect.Effect<A, E, R>,
3145
3163
  options?: {
3146
- readonly log?: boolean | LogLevel.LogLevel | undefined
3164
+ readonly log?: boolean | LogLevel.Severity | undefined
3147
3165
  } | undefined
3148
3166
  ): Effect.Effect<void, never, R> => {
3149
3167
  if (!options?.log) {
@@ -4080,6 +4098,59 @@ export const partition: {
4080
4098
  )
4081
4099
  )
4082
4100
 
4101
+ /** @internal */
4102
+ export const validate: {
4103
+ <A, B, E, R>(
4104
+ f: (a: A, i: number) => Effect.Effect<B, E, R>,
4105
+ options?: {
4106
+ readonly concurrency?: Concurrency | undefined
4107
+ readonly discard?: false | undefined
4108
+ } | undefined
4109
+ ): (elements: Iterable<A>) => Effect.Effect<Array<B>, Arr.NonEmptyArray<E>, R>
4110
+ <A, B, E, R>(
4111
+ f: (a: A, i: number) => Effect.Effect<B, E, R>,
4112
+ options: {
4113
+ readonly concurrency?: Concurrency | undefined
4114
+ readonly discard: true
4115
+ }
4116
+ ): (elements: Iterable<A>) => Effect.Effect<void, Arr.NonEmptyArray<E>, R>
4117
+ <A, B, E, R>(
4118
+ elements: Iterable<A>,
4119
+ f: (a: A, i: number) => Effect.Effect<B, E, R>,
4120
+ options?: {
4121
+ readonly concurrency?: Concurrency | undefined
4122
+ readonly discard?: false | undefined
4123
+ } | undefined
4124
+ ): Effect.Effect<Array<B>, Arr.NonEmptyArray<E>, R>
4125
+ <A, B, E, R>(
4126
+ elements: Iterable<A>,
4127
+ f: (a: A, i: number) => Effect.Effect<B, E, R>,
4128
+ options: {
4129
+ readonly concurrency?: Concurrency | undefined
4130
+ readonly discard: true
4131
+ }
4132
+ ): Effect.Effect<void, Arr.NonEmptyArray<E>, R>
4133
+ } = dual(
4134
+ (args) => isIterable(args[0]) && !isEffect(args[0]),
4135
+ <A, B, E, R>(
4136
+ elements: Iterable<A>,
4137
+ f: (a: A, i: number) => Effect.Effect<B, E, R>,
4138
+ options?: {
4139
+ readonly concurrency?: Concurrency | undefined
4140
+ readonly discard?: boolean | undefined
4141
+ } | undefined
4142
+ ): Effect.Effect<Array<B> | void, Arr.NonEmptyArray<E>, R> =>
4143
+ flatMap(
4144
+ partition(elements, f, { concurrency: options?.concurrency }),
4145
+ ([excluded, satisfying]) => {
4146
+ if (Arr.isArrayNonEmpty(excluded)) {
4147
+ return fail(excluded)
4148
+ }
4149
+ return options?.discard ? void_ : succeed(satisfying)
4150
+ }
4151
+ )
4152
+ )
4153
+
4083
4154
  /** @internal */
4084
4155
  export const whileLoop: <A, E, R>(options: {
4085
4156
  readonly while: LazyArg<boolean>
@@ -5499,7 +5570,7 @@ const LoggerProto = {
5499
5570
 
5500
5571
  /** @internal */
5501
5572
  export const loggerMake = <Message, Output>(
5502
- log: (options: Logger.Logger.Options<Message>) => Output
5573
+ log: (options: Logger.Options<Message>) => Output
5503
5574
  ): Logger.Logger<Message, Output> => {
5504
5575
  const self = Object.create(LoggerProto)
5505
5576
  self.log = log
@@ -5539,7 +5610,7 @@ export const structuredMessage = (u: unknown): unknown => {
5539
5610
  }
5540
5611
 
5541
5612
  /** @internal */
5542
- export const logWithLevel = (level?: LogLevel.LogLevel) =>
5613
+ export const logWithLevel = (level?: LogLevel.Severity) =>
5543
5614
  (
5544
5615
  ...message: ReadonlyArray<any>
5545
5616
  ): Effect.Effect<void> => {
@@ -5830,3 +5901,55 @@ const undefined_ = succeed(undefined)
5830
5901
 
5831
5902
  /** @internal */
5832
5903
  export { undefined_ as undefined }
5904
+
5905
+ // ----------------------------------------------------------------------------
5906
+ // ErrorReporter
5907
+ // ----------------------------------------------------------------------------
5908
+
5909
+ /** @internal */
5910
+ export const CurrentErrorReporters = ServiceMap.Reference<
5911
+ ReadonlySet<ErrorReporter>
5912
+ >("effect/ErrorReporter/CurrentErrorReporters", {
5913
+ defaultValue: () => new Set()
5914
+ })
5915
+
5916
+ /** @internal */
5917
+ export const withErrorReporting: <
5918
+ Arg extends Effect.Effect<any, any, any> | {
5919
+ readonly defectsOnly?: boolean | undefined
5920
+ } | undefined = {
5921
+ readonly defectsOnly?: boolean | undefined
5922
+ }
5923
+ >(
5924
+ effectOrOptions: Arg,
5925
+ options?: {
5926
+ readonly defectsOnly?: boolean | undefined
5927
+ } | undefined
5928
+ ) => [Arg] extends [Effect.Effect<infer _A, infer _E, infer _R>] ? Arg
5929
+ : <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> = dual(
5930
+ (args) => isEffect(args[0]),
5931
+ <A, E, R>(
5932
+ self: Effect.Effect<A, E, R>,
5933
+ options?: {
5934
+ readonly defectsOnly?: boolean | undefined
5935
+ } | undefined
5936
+ ): Effect.Effect<A, E, R> =>
5937
+ onError(self, (cause) =>
5938
+ withFiber((fiber) => {
5939
+ reportCauseUnsafe(fiber, cause, options?.defectsOnly)
5940
+ return void_
5941
+ }))
5942
+ )
5943
+
5944
+ /** @internal */
5945
+ export const reportCauseUnsafe = (
5946
+ fiber: Fiber.Fiber<unknown, unknown>,
5947
+ cause: Cause.Cause<unknown>,
5948
+ defectsOnly?: boolean
5949
+ ) => {
5950
+ const reporters = fiber.getRef(CurrentErrorReporters)
5951
+ if (reporters.size === 0) return
5952
+ if (defectsOnly && !hasDies(cause)) return
5953
+ const opts = { cause, fiber, timestamp: fiber.getRef(ClockRef).currentTimeNanosUnsafe() }
5954
+ reporters.forEach((reporter) => reporter.report(opts))
5955
+ }
@@ -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
 
@@ -984,6 +984,13 @@ export const make: (params: ConstructorParams) => Effect.Effect<Service> = Effec
984
984
  toolMessage
985
985
  ])
986
986
  }
987
+
988
+ // Strip consumed approval artifacts so they don't reach the provider
989
+ providerOptions.prompt = stripResolvedApprovals(
990
+ providerOptions.prompt,
991
+ approved,
992
+ denied
993
+ )
987
994
  }
988
995
 
989
996
  const tools = typeof toolChoice === "object" && "oneOf" in toolChoice
@@ -1165,6 +1172,13 @@ export const make: (params: ConstructorParams) => Effect.Effect<Service> = Effec
1165
1172
  toolMessage
1166
1173
  ])
1167
1174
  }
1175
+
1176
+ // Strip consumed approval artifacts so they don't reach the provider
1177
+ providerOptions.prompt = stripResolvedApprovals(
1178
+ providerOptions.prompt,
1179
+ pendingApproved,
1180
+ pendingDenied
1181
+ )
1168
1182
  }
1169
1183
 
1170
1184
  const tools = typeof toolChoice === "object" && "oneOf" in toolChoice
@@ -1506,6 +1520,63 @@ const collectToolApprovals = (
1506
1520
  return { approved, denied }
1507
1521
  }
1508
1522
 
1523
+ /**
1524
+ * Strip resolved approval artifacts from the prompt before sending to the
1525
+ * provider. After pre-resolving approvals (executing approved tools and
1526
+ * creating denial results), the original `tool-approval-request` parts in
1527
+ * assistant messages and `tool-approval-response` parts in tool messages are
1528
+ * no longer needed. Leaving them in causes provider-specific errors (e.g.
1529
+ * OpenAI rejects `mcp_approval_response` items that reference approval
1530
+ * requests it never issued).
1531
+ */
1532
+ const stripResolvedApprovals = (
1533
+ prompt: Prompt.Prompt,
1534
+ approved: ReadonlyArray<ApprovalResult>,
1535
+ denied: ReadonlyArray<ApprovalResult>
1536
+ ): Prompt.Prompt => {
1537
+ const resolvedApprovalIds = new Set<string>()
1538
+ for (const a of approved) resolvedApprovalIds.add(a.approvalId)
1539
+ for (const d of denied) resolvedApprovalIds.add(d.approvalId)
1540
+
1541
+ const cleanedMessages: Array<Prompt.Message> = []
1542
+
1543
+ for (const message of prompt.content) {
1544
+ if (message.role === "assistant") {
1545
+ const filteredContent = message.content.filter(
1546
+ (part) =>
1547
+ part.type !== "tool-approval-request" ||
1548
+ !resolvedApprovalIds.has(part.approvalId)
1549
+ )
1550
+ if (filteredContent.length > 0) {
1551
+ cleanedMessages.push(
1552
+ Prompt.makeMessage("assistant", {
1553
+ content: filteredContent,
1554
+ options: message.options
1555
+ })
1556
+ )
1557
+ }
1558
+ } else if (message.role === "tool") {
1559
+ const filteredContent = message.content.filter(
1560
+ (part) =>
1561
+ part.type !== "tool-approval-response" ||
1562
+ !resolvedApprovalIds.has(part.approvalId)
1563
+ )
1564
+ if (filteredContent.length > 0) {
1565
+ cleanedMessages.push(
1566
+ Prompt.makeMessage("tool", {
1567
+ content: filteredContent,
1568
+ options: message.options
1569
+ })
1570
+ )
1571
+ }
1572
+ } else {
1573
+ cleanedMessages.push(message)
1574
+ }
1575
+ }
1576
+
1577
+ return Prompt.fromMessages(cleanedMessages)
1578
+ }
1579
+
1509
1580
  const isApprovalNeeded = Effect.fnUntraced(function*<T extends Tool.Any>(
1510
1581
  tool: T,
1511
1582
  toolCall: Response.ToolCallPartEncoded,
@@ -499,14 +499,53 @@ const formatHelpDocImpl = (doc: HelpDoc, colors: ColorFunctions): string => {
499
499
 
500
500
  // Subcommands section
501
501
  if (doc.subcommands && doc.subcommands.length > 0) {
502
- sections.push(colors.bold("SUBCOMMANDS"))
502
+ const ungrouped = doc.subcommands.find((group) => group.group === undefined)
503
+
504
+ if (ungrouped) {
505
+ sections.push(colors.bold("SUBCOMMANDS"))
506
+ sections.push(renderTable(
507
+ ungrouped.commands.map((sub) => ({
508
+ left: colors.cyan(sub.name),
509
+ right: sub.shortDescription ?? sub.description
510
+ })),
511
+ 20
512
+ ))
513
+ if (doc.subcommands.length > 1) {
514
+ sections.push("")
515
+ }
516
+ }
503
517
 
504
- const subcommandRows: Array<Row> = doc.subcommands.map((sub) => ({
505
- left: colors.cyan(sub.name),
506
- right: sub.description
507
- }))
518
+ for (const group of doc.subcommands) {
519
+ if (group.group === undefined) continue
520
+ sections.push(colors.bold(`${group.group}:`))
521
+ sections.push(renderTable(
522
+ group.commands.map((sub) => ({
523
+ left: colors.cyan(sub.name),
524
+ right: sub.shortDescription ?? sub.description
525
+ })),
526
+ 20
527
+ ))
528
+ sections.push("")
529
+ }
530
+ }
508
531
 
509
- sections.push(renderTable(subcommandRows, 20))
532
+ // Examples section
533
+ if (doc.examples && doc.examples.length > 0) {
534
+ sections.push(colors.bold("EXAMPLES"))
535
+
536
+ let first = true
537
+ let previousHadDescription = false
538
+ for (const example of doc.examples) {
539
+ if (example.description) {
540
+ if (!first) sections.push("")
541
+ sections.push(` ${colors.dim(`# ${example.description}`)}`)
542
+ } else if (previousHadDescription) {
543
+ sections.push("")
544
+ }
545
+ sections.push(` ${colors.cyan(example.command)}`)
546
+ first = false
547
+ previousHadDescription = !!example.description
548
+ }
510
549
  sections.push("")
511
550
  }
512
551