effect 4.0.4 → 4.0.5

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 (308) hide show
  1. package/ai-docs/src/52_graphql/10_basics.ts +19 -13
  2. package/ai-docs/src/52_graphql/30_batching.ts +6 -4
  3. package/ai-docs/src/52_graphql/40_aliased-batching.ts +6 -4
  4. package/dist/Array.d.ts +90 -6
  5. package/dist/Array.d.ts.map +1 -1
  6. package/dist/Array.js +4 -2
  7. package/dist/Array.js.map +1 -1
  8. package/dist/Channel.d.ts +6 -1
  9. package/dist/Channel.d.ts.map +1 -1
  10. package/dist/Channel.js +17 -3
  11. package/dist/Channel.js.map +1 -1
  12. package/dist/ConfigProvider.d.ts.map +1 -1
  13. package/dist/ConfigProvider.js +33 -32
  14. package/dist/ConfigProvider.js.map +1 -1
  15. package/dist/Duration.d.ts.map +1 -1
  16. package/dist/Duration.js +2 -5
  17. package/dist/Duration.js.map +1 -1
  18. package/dist/Effect.d.ts +61 -19
  19. package/dist/Effect.d.ts.map +1 -1
  20. package/dist/Effect.js +58 -39
  21. package/dist/Effect.js.map +1 -1
  22. package/dist/FileSystem.d.ts +23 -9
  23. package/dist/FileSystem.d.ts.map +1 -1
  24. package/dist/FileSystem.js.map +1 -1
  25. package/dist/Match.d.ts +20 -6
  26. package/dist/Match.d.ts.map +1 -1
  27. package/dist/Match.js +2 -2
  28. package/dist/Match.js.map +1 -1
  29. package/dist/Path.d.ts +37 -5
  30. package/dist/Path.d.ts.map +1 -1
  31. package/dist/Path.js +36 -5
  32. package/dist/Path.js.map +1 -1
  33. package/dist/Schema.d.ts +7 -2
  34. package/dist/Schema.d.ts.map +1 -1
  35. package/dist/Schema.js +9 -2
  36. package/dist/Schema.js.map +1 -1
  37. package/dist/String.d.ts +12 -0
  38. package/dist/String.d.ts.map +1 -1
  39. package/dist/String.js +17 -4
  40. package/dist/String.js.map +1 -1
  41. package/dist/TxRef.d.ts.map +1 -1
  42. package/dist/TxRef.js +3 -2
  43. package/dist/TxRef.js.map +1 -1
  44. package/dist/ai/AiError.d.ts +10 -10
  45. package/dist/ai/AiError.d.ts.map +1 -1
  46. package/dist/ai/AiError.js +1 -1
  47. package/dist/ai/AiError.js.map +1 -1
  48. package/dist/ai/Decision.d.ts +70 -19
  49. package/dist/ai/Decision.d.ts.map +1 -1
  50. package/dist/ai/Decision.js +37 -3
  51. package/dist/ai/Decision.js.map +1 -1
  52. package/dist/ai/DecisionModel.js +1 -1
  53. package/dist/ai/DecisionModel.js.map +1 -1
  54. package/dist/ai/LanguageModel.d.ts.map +1 -1
  55. package/dist/ai/LanguageModel.js +47 -35
  56. package/dist/ai/LanguageModel.js.map +1 -1
  57. package/dist/ai/McpServer.d.ts +6 -52
  58. package/dist/ai/McpServer.d.ts.map +1 -1
  59. package/dist/ai/McpServer.js +2 -28
  60. package/dist/ai/McpServer.js.map +1 -1
  61. package/dist/ai/Response.d.ts +1 -1
  62. package/dist/cli/Completions.d.ts +5 -0
  63. package/dist/cli/Completions.d.ts.map +1 -1
  64. package/dist/cli/Completions.js.map +1 -1
  65. package/dist/cli/Flag.d.ts +100 -0
  66. package/dist/cli/Flag.d.ts.map +1 -1
  67. package/dist/cli/Flag.js +33 -0
  68. package/dist/cli/Flag.js.map +1 -1
  69. package/dist/cli/Param.d.ts +87 -0
  70. package/dist/cli/Param.d.ts.map +1 -1
  71. package/dist/cli/Param.js +30 -0
  72. package/dist/cli/Param.js.map +1 -1
  73. package/dist/cli/internal/command.d.ts.map +1 -1
  74. package/dist/cli/internal/command.js +2 -1
  75. package/dist/cli/internal/command.js.map +1 -1
  76. package/dist/cli/internal/completions/bash.js +4 -3
  77. package/dist/cli/internal/completions/bash.js.map +1 -1
  78. package/dist/cli/internal/completions/descriptor.js +8 -1
  79. package/dist/cli/internal/completions/descriptor.js.map +1 -1
  80. package/dist/cli/internal/completions/fish.js +4 -4
  81. package/dist/cli/internal/completions/fish.js.map +1 -1
  82. package/dist/cli/internal/completions/powershell.js +3 -2
  83. package/dist/cli/internal/completions/powershell.js.map +1 -1
  84. package/dist/cli/internal/completions/zsh.js +7 -3
  85. package/dist/cli/internal/completions/zsh.js.map +1 -1
  86. package/dist/cli/internal/parser.js +11 -3
  87. package/dist/cli/internal/parser.js.map +1 -1
  88. package/dist/cli/internal/wizard.d.ts.map +1 -1
  89. package/dist/cli/internal/wizard.js +2 -1
  90. package/dist/cli/internal/wizard.js.map +1 -1
  91. package/dist/cluster/ClusterWorkflowEngine.d.ts +1 -0
  92. package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  93. package/dist/cluster/ClusterWorkflowEngine.js +67 -13
  94. package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
  95. package/dist/cluster/MessageStorage.d.ts.map +1 -1
  96. package/dist/cluster/MessageStorage.js +20 -12
  97. package/dist/cluster/MessageStorage.js.map +1 -1
  98. package/dist/cluster/Runners.d.ts.map +1 -1
  99. package/dist/cluster/Runners.js +54 -34
  100. package/dist/cluster/Runners.js.map +1 -1
  101. package/dist/cluster/internal/entityManager.js +1 -1
  102. package/dist/cluster/internal/entityManager.js.map +1 -1
  103. package/dist/encoding/Sse.js +1 -1
  104. package/dist/encoding/Sse.js.map +1 -1
  105. package/dist/graphql/GraphQLClient.d.ts.map +1 -1
  106. package/dist/graphql/GraphQLClient.js +12 -5
  107. package/dist/graphql/GraphQLClient.js.map +1 -1
  108. package/dist/graphql/GraphQLProtocol.d.ts +249 -11
  109. package/dist/graphql/GraphQLProtocol.d.ts.map +1 -1
  110. package/dist/graphql/GraphQLProtocol.js +98 -8
  111. package/dist/graphql/GraphQLProtocol.js.map +1 -1
  112. package/dist/graphql/GraphQLResolver.d.ts +1 -1
  113. package/dist/graphql/GraphQLResolver.d.ts.map +1 -1
  114. package/dist/graphql/GraphQLResolver.js +46 -16
  115. package/dist/graphql/GraphQLResolver.js.map +1 -1
  116. package/dist/http/FetchHttpClient.d.ts +6 -3
  117. package/dist/http/FetchHttpClient.d.ts.map +1 -1
  118. package/dist/http/FetchHttpClient.js +6 -3
  119. package/dist/http/FetchHttpClient.js.map +1 -1
  120. package/dist/http/FindMyWay/internal/router.js +2 -1
  121. package/dist/http/FindMyWay/internal/router.js.map +1 -1
  122. package/dist/http/Headers.d.ts +3 -3
  123. package/dist/http/Headers.d.ts.map +1 -1
  124. package/dist/http/Headers.js +6 -5
  125. package/dist/http/Headers.js.map +1 -1
  126. package/dist/http/HttpClient.d.ts +12 -0
  127. package/dist/http/HttpClient.d.ts.map +1 -1
  128. package/dist/http/HttpClient.js +14 -1
  129. package/dist/http/HttpClient.js.map +1 -1
  130. package/dist/http/HttpClientError.d.ts.map +1 -1
  131. package/dist/http/HttpClientError.js +8 -6
  132. package/dist/http/HttpClientError.js.map +1 -1
  133. package/dist/http/HttpClientRequest.d.ts +147 -4
  134. package/dist/http/HttpClientRequest.d.ts.map +1 -1
  135. package/dist/http/HttpClientRequest.js +47 -1
  136. package/dist/http/HttpClientRequest.js.map +1 -1
  137. package/dist/http/HttpMiddleware.d.ts +60 -0
  138. package/dist/http/HttpMiddleware.d.ts.map +1 -1
  139. package/dist/http/HttpMiddleware.js +67 -5
  140. package/dist/http/HttpMiddleware.js.map +1 -1
  141. package/dist/http/HttpRouter.d.ts.map +1 -1
  142. package/dist/http/HttpRouter.js +52 -13
  143. package/dist/http/HttpRouter.js.map +1 -1
  144. package/dist/http/HttpServerError.d.ts.map +1 -1
  145. package/dist/http/HttpServerError.js +6 -4
  146. package/dist/http/HttpServerError.js.map +1 -1
  147. package/dist/http/HttpServerRequest.js +2 -2
  148. package/dist/http/HttpServerRequest.js.map +1 -1
  149. package/dist/http/HttpStaticServer.d.ts.map +1 -1
  150. package/dist/http/HttpStaticServer.js +4 -10
  151. package/dist/http/HttpStaticServer.js.map +1 -1
  152. package/dist/http/HttpTraceContext.js +1 -1
  153. package/dist/http/HttpTraceContext.js.map +1 -1
  154. package/dist/http/Url.d.ts.map +1 -1
  155. package/dist/http/Url.js +2 -1
  156. package/dist/http/Url.js.map +1 -1
  157. package/dist/http/UrlParams.d.ts +112 -8
  158. package/dist/http/UrlParams.d.ts.map +1 -1
  159. package/dist/http/UrlParams.js +141 -14
  160. package/dist/http/UrlParams.js.map +1 -1
  161. package/dist/http/internal/compression.d.ts +1 -1
  162. package/dist/http/internal/compression.d.ts.map +1 -1
  163. package/dist/http/internal/compression.js +2 -10
  164. package/dist/http/internal/compression.js.map +1 -1
  165. package/dist/http/internal/compressionBody.d.ts +2 -0
  166. package/dist/http/internal/compressionBody.d.ts.map +1 -0
  167. package/dist/http/internal/compressionBody.js +36 -0
  168. package/dist/http/internal/compressionBody.js.map +1 -0
  169. package/dist/http/internal/decompression.d.ts +2 -0
  170. package/dist/http/internal/decompression.d.ts.map +1 -0
  171. package/dist/http/internal/decompression.js +162 -0
  172. package/dist/http/internal/decompression.js.map +1 -0
  173. package/dist/http/internal/tracing.js +14 -4
  174. package/dist/http/internal/tracing.js.map +1 -1
  175. package/dist/http/internal/urlParams.d.ts +2 -0
  176. package/dist/http/internal/urlParams.d.ts.map +1 -0
  177. package/dist/http/internal/urlParams.js +4 -0
  178. package/dist/http/internal/urlParams.js.map +1 -0
  179. package/dist/http-api/HttpApiClient.d.ts.map +1 -1
  180. package/dist/http-api/HttpApiClient.js +2 -1
  181. package/dist/http-api/HttpApiClient.js.map +1 -1
  182. package/dist/internal/core.js +17 -1
  183. package/dist/internal/core.js.map +1 -1
  184. package/dist/internal/effect.js +5 -3
  185. package/dist/internal/effect.js.map +1 -1
  186. package/dist/internal/graphql.js +12 -2
  187. package/dist/internal/graphql.js.map +1 -1
  188. package/dist/internal/version.js +1 -1
  189. package/dist/observability/Otlp.d.ts +15 -0
  190. package/dist/observability/Otlp.d.ts.map +1 -1
  191. package/dist/observability/Otlp.js +3 -0
  192. package/dist/observability/Otlp.js.map +1 -1
  193. package/dist/observability/OtlpExporter.d.ts +8 -0
  194. package/dist/observability/OtlpExporter.d.ts.map +1 -1
  195. package/dist/observability/OtlpExporter.js +10 -1
  196. package/dist/observability/OtlpExporter.js.map +1 -1
  197. package/dist/observability/OtlpLogger.d.ts +17 -0
  198. package/dist/observability/OtlpLogger.d.ts.map +1 -1
  199. package/dist/observability/OtlpLogger.js +14 -1
  200. package/dist/observability/OtlpLogger.js.map +1 -1
  201. package/dist/observability/OtlpMetrics.d.ts +17 -0
  202. package/dist/observability/OtlpMetrics.d.ts.map +1 -1
  203. package/dist/observability/OtlpMetrics.js +13 -0
  204. package/dist/observability/OtlpMetrics.js.map +1 -1
  205. package/dist/observability/OtlpTracer.d.ts +17 -0
  206. package/dist/observability/OtlpTracer.d.ts.map +1 -1
  207. package/dist/observability/OtlpTracer.js +15 -2
  208. package/dist/observability/OtlpTracer.js.map +1 -1
  209. package/dist/reactivity/AsyncResult.d.ts +6 -0
  210. package/dist/reactivity/AsyncResult.d.ts.map +1 -1
  211. package/dist/reactivity/AsyncResult.js +27 -0
  212. package/dist/reactivity/AsyncResult.js.map +1 -1
  213. package/dist/reactivity/AtomRegistry.js +3 -1
  214. package/dist/reactivity/AtomRegistry.js.map +1 -1
  215. package/dist/rpc/RpcClient.d.ts.map +1 -1
  216. package/dist/rpc/RpcClient.js +6 -1
  217. package/dist/rpc/RpcClient.js.map +1 -1
  218. package/dist/sql/SqlClient.d.ts +8 -7
  219. package/dist/sql/SqlClient.d.ts.map +1 -1
  220. package/dist/sql/SqlClient.js +8 -7
  221. package/dist/sql/SqlClient.js.map +1 -1
  222. package/dist/testing/TestClock.d.ts +16 -3
  223. package/dist/testing/TestClock.d.ts.map +1 -1
  224. package/dist/testing/TestClock.js +112 -22
  225. package/dist/testing/TestClock.js.map +1 -1
  226. package/dist/workflow/Activity.js +1 -0
  227. package/dist/workflow/Activity.js.map +1 -1
  228. package/dist/workflow/Workflow.d.ts +22 -0
  229. package/dist/workflow/Workflow.d.ts.map +1 -1
  230. package/dist/workflow/Workflow.js +15 -3
  231. package/dist/workflow/Workflow.js.map +1 -1
  232. package/dist/workflow/WorkflowEngine.d.ts +20 -1
  233. package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
  234. package/dist/workflow/WorkflowEngine.js +35 -21
  235. package/dist/workflow/WorkflowEngine.js.map +1 -1
  236. package/package.json +1 -1
  237. package/src/Array.ts +95 -6
  238. package/src/Channel.ts +24 -3
  239. package/src/ConfigProvider.ts +40 -44
  240. package/src/Duration.ts +4 -5
  241. package/src/Effect.ts +140 -53
  242. package/src/FileSystem.ts +23 -9
  243. package/src/Match.ts +65 -12
  244. package/src/Path.ts +52 -7
  245. package/src/Schema.ts +17 -4
  246. package/src/String.ts +17 -4
  247. package/src/TxRef.ts +4 -2
  248. package/src/ai/AiError.ts +3 -1
  249. package/src/ai/Decision.ts +70 -21
  250. package/src/ai/DecisionModel.ts +1 -1
  251. package/src/ai/LanguageModel.ts +57 -51
  252. package/src/ai/McpServer.ts +15 -55
  253. package/src/cli/Completions.ts +5 -0
  254. package/src/cli/Flag.ts +101 -0
  255. package/src/cli/Param.ts +96 -0
  256. package/src/cli/internal/command.ts +2 -1
  257. package/src/cli/internal/completions/bash.ts +4 -3
  258. package/src/cli/internal/completions/descriptor.ts +10 -1
  259. package/src/cli/internal/completions/fish.ts +4 -4
  260. package/src/cli/internal/completions/powershell.ts +5 -2
  261. package/src/cli/internal/completions/zsh.ts +7 -3
  262. package/src/cli/internal/parser.ts +12 -3
  263. package/src/cli/internal/wizard.ts +2 -1
  264. package/src/cluster/ClusterWorkflowEngine.ts +92 -24
  265. package/src/cluster/MessageStorage.ts +14 -3
  266. package/src/cluster/Runners.ts +88 -66
  267. package/src/cluster/internal/entityManager.ts +1 -1
  268. package/src/encoding/Sse.ts +1 -1
  269. package/src/graphql/GraphQLClient.ts +17 -5
  270. package/src/graphql/GraphQLProtocol.ts +274 -20
  271. package/src/graphql/GraphQLResolver.ts +45 -17
  272. package/src/http/FetchHttpClient.ts +6 -3
  273. package/src/http/FindMyWay/internal/router.ts +2 -1
  274. package/src/http/Headers.ts +6 -9
  275. package/src/http/HttpClient.ts +18 -1
  276. package/src/http/HttpClientError.ts +10 -6
  277. package/src/http/HttpClientRequest.ts +173 -7
  278. package/src/http/HttpMiddleware.ts +85 -5
  279. package/src/http/HttpRouter.ts +60 -13
  280. package/src/http/HttpServerError.ts +8 -4
  281. package/src/http/HttpServerRequest.ts +2 -2
  282. package/src/http/HttpStaticServer.ts +4 -10
  283. package/src/http/HttpTraceContext.ts +1 -1
  284. package/src/http/Url.ts +2 -1
  285. package/src/http/UrlParams.ts +225 -26
  286. package/src/http/internal/compression.ts +3 -17
  287. package/src/http/internal/compressionBody.ts +56 -0
  288. package/src/http/internal/decompression.ts +226 -0
  289. package/src/http/internal/tracing.ts +21 -4
  290. package/src/http/internal/urlParams.ts +5 -0
  291. package/src/http-api/HttpApiClient.ts +2 -1
  292. package/src/internal/core.ts +21 -1
  293. package/src/internal/effect.ts +5 -4
  294. package/src/internal/graphql.ts +30 -7
  295. package/src/internal/version.ts +1 -1
  296. package/src/observability/Otlp.ts +18 -0
  297. package/src/observability/OtlpExporter.ts +14 -3
  298. package/src/observability/OtlpLogger.ts +31 -2
  299. package/src/observability/OtlpMetrics.ts +30 -1
  300. package/src/observability/OtlpTracer.ts +32 -3
  301. package/src/reactivity/AsyncResult.ts +31 -0
  302. package/src/reactivity/AtomRegistry.ts +3 -1
  303. package/src/rpc/RpcClient.ts +6 -1
  304. package/src/sql/SqlClient.ts +9 -7
  305. package/src/testing/TestClock.ts +144 -29
  306. package/src/workflow/Activity.ts +1 -0
  307. package/src/workflow/Workflow.ts +31 -5
  308. package/src/workflow/WorkflowEngine.ts +60 -22
@@ -893,6 +893,13 @@ export const make: (params: {
893
893
  Effect.map(Option.getOrElse(() => defaultIdGenerator))
894
894
  )
895
895
 
896
+ const contentDecoderFor = makeResponseDecoder((toolkit, deferred) =>
897
+ Schema.decodeEffect(Schema.mutable(Schema.Array(withUndeclaredToolCalls(Response.Part(toolkit), deferred))))
898
+ )
899
+ const streamDecoderFor = makeResponseDecoder((toolkit, deferred) =>
900
+ Schema.decodeEffect(Schema.NonEmptyArray(withUndeclaredToolCalls(Response.StreamPart(toolkit), deferred)))
901
+ )
902
+
896
903
  const generateText = <
897
904
  Options extends NoExcessProperties<GenerateTextOptions<any>, Options>,
898
905
  Tools extends Record<string, Tool.Any> = {}
@@ -1132,10 +1139,8 @@ export const make: (params: {
1132
1139
  }
1133
1140
 
1134
1141
  // Check for pending approvals that need resolution
1135
- const { approved, denied } = collectToolApprovals(
1136
- providerOptions.prompt.content,
1137
- { excludeResolved: true }
1138
- )
1142
+ const { approved: allResolved, denied: allDenied, pendingApproved: approved, pendingDenied: denied } =
1143
+ collectToolApprovals(providerOptions.prompt.content)
1139
1144
  const hasPendingApprovals = approved.length > 0 || denied.length > 0
1140
1145
 
1141
1146
  // If there is no toolkit, the generated content can be returned immediately
@@ -1245,17 +1250,12 @@ export const make: (params: {
1245
1250
 
1246
1251
  // Strip all resolved approval artifacts (both current and from previous
1247
1252
  // rounds) in a single pass before sending to the provider.
1248
- {
1249
- const { approved: allResolved, denied: allDenied } = collectToolApprovals(
1250
- providerOptions.prompt.content
1253
+ if (allResolved.length > 0 || allDenied.length > 0) {
1254
+ providerOptions.prompt = stripResolvedApprovals(
1255
+ providerOptions.prompt,
1256
+ allResolved,
1257
+ allDenied
1251
1258
  )
1252
- if (allResolved.length > 0 || allDenied.length > 0) {
1253
- providerOptions.prompt = stripResolvedApprovals(
1254
- providerOptions.prompt,
1255
- allResolved,
1256
- allDenied
1257
- )
1258
- }
1259
1259
  }
1260
1260
 
1261
1261
  const tools = typeof toolChoice === "object" && "oneOf" in toolChoice
@@ -1272,20 +1272,17 @@ export const make: (params: {
1272
1272
  }
1273
1273
  }
1274
1274
 
1275
- const ResponseSchema = Schema.mutable(Schema.Array(withUndeclaredToolCalls(
1276
- Response.Part(
1277
- options.disableToolCallResolution === true && !deferToolCallValidation
1278
- ? makeToolkitWithEncodedParameters(toolkit)
1279
- : makeToolkitWithOpaqueParameters(toolkit)
1280
- ),
1275
+ const decodeContent = contentDecoderFor(
1276
+ toolkit,
1277
+ options.disableToolCallResolution === true && !deferToolCallValidation,
1281
1278
  deferToolCallValidation
1282
- )))
1279
+ )
1283
1280
 
1284
1281
  // If tool call resolution is disabled, return the response without
1285
1282
  // resolving the tool calls that were generated
1286
1283
  if (options.disableToolCallResolution === true) {
1287
1284
  const rawContent = yield* generateWithNonIncrementalFallback()
1288
- const content = yield* Schema.decodeEffect(ResponseSchema)(rawContent)
1285
+ const content = yield* decodeContent(rawContent)
1289
1286
  if (deferToolCallValidation) {
1290
1287
  yield* validateProviderExecutedToolCalls(makeToolkitWithEncodedParameters(toolkit), rawContent)
1291
1288
  }
@@ -1301,7 +1298,7 @@ export const make: (params: {
1301
1298
  const rawContent = yield* generateWithNonIncrementalFallback()
1302
1299
 
1303
1300
  // Validate before running tool handlers.
1304
- const content = yield* Schema.decodeEffect(ResponseSchema)(rawContent)
1301
+ const content = yield* decodeContent(rawContent)
1305
1302
  yield* validateProviderExecutedToolCalls(toolkit, rawContent)
1306
1303
 
1307
1304
  // Resolve the generated tool calls. When the finish reason indicates an
@@ -1407,9 +1404,9 @@ export const make: (params: {
1407
1404
  }
1408
1405
 
1409
1406
  // Check for pending approvals that need resolution
1410
- const { approved: pendingApproved, denied: pendingDenied } = collectToolApprovals(providerOptions.prompt.content, {
1411
- excludeResolved: true
1412
- })
1407
+ const { approved: allResolved, denied: allDenied, pendingApproved, pendingDenied } = collectToolApprovals(
1408
+ providerOptions.prompt.content
1409
+ )
1413
1410
  const hasPendingApprovals = pendingApproved.length > 0 || pendingDenied.length > 0
1414
1411
 
1415
1412
  // If there is no toolkit, return immediately
@@ -1564,9 +1561,6 @@ export const make: (params: {
1564
1561
 
1565
1562
  // Strip all resolved approval artifacts (both current and from previous
1566
1563
  // rounds) in a single pass before sending to the provider.
1567
- const { approved: allResolved, denied: allDenied } = collectToolApprovals(
1568
- providerOptions.prompt.content
1569
- )
1570
1564
  if (allResolved.length > 0 || allDenied.length > 0) {
1571
1565
  providerOptions.prompt = stripResolvedApprovals(
1572
1566
  providerOptions.prompt,
@@ -1589,15 +1583,11 @@ export const make: (params: {
1589
1583
  }
1590
1584
  }
1591
1585
 
1592
- const ResponseSchema = Schema.NonEmptyArray(withUndeclaredToolCalls(
1593
- Response.StreamPart(
1594
- options.disableToolCallResolution === true && !deferToolCallValidation
1595
- ? makeToolkitWithEncodedParameters(toolkit)
1596
- : makeToolkitWithOpaqueParameters(toolkit)
1597
- ),
1586
+ const decodeParts = streamDecoderFor(
1587
+ toolkit,
1588
+ options.disableToolCallResolution === true && !deferToolCallValidation,
1598
1589
  deferToolCallValidation
1599
- ))
1600
- const decodeParts = Schema.decodeEffect(ResponseSchema)
1590
+ )
1601
1591
 
1602
1592
  // If tool call resolution is disabled, return the response without
1603
1593
  // resolving the tool calls that were generated
@@ -1638,8 +1628,7 @@ export const make: (params: {
1638
1628
  const deferredFinishParts: Array<Response.StreamPart<Tools>> = []
1639
1629
 
1640
1630
  // Emit pre-resolved tool results so Chat.streamText persists them to
1641
- // history. This ensures collectToolApprovals({ excludeResolved }) can
1642
- // find the corresponding tool-results on future rounds.
1631
+ // history, where collectToolApprovals finds them on future rounds.
1643
1632
  if (preResolvedStreamParts.length > 0) {
1644
1633
  yield* Queue.offerAll(queue, preResolvedStreamParts)
1645
1634
  }
@@ -2072,16 +2061,13 @@ interface ApprovalResult {
2072
2061
  readonly toolCall?: Prompt.ToolCallPart | undefined
2073
2062
  }
2074
2063
 
2075
- interface CollectToolApprovalsOptions {
2076
- readonly excludeResolved?: boolean
2077
- }
2078
-
2079
2064
  const collectToolApprovals = (
2080
- messages: ReadonlyArray<Prompt.Message>,
2081
- options?: CollectToolApprovalsOptions
2065
+ messages: ReadonlyArray<Prompt.Message>
2082
2066
  ): {
2083
2067
  readonly approved: Array<ApprovalResult>
2084
2068
  readonly denied: Array<ApprovalResult>
2069
+ readonly pendingApproved: Array<ApprovalResult>
2070
+ readonly pendingDenied: Array<ApprovalResult>
2085
2071
  } => {
2086
2072
  const requests = new Map<
2087
2073
  string,
@@ -2124,15 +2110,12 @@ const collectToolApprovals = (
2124
2110
 
2125
2111
  const approved: Array<ApprovalResult> = []
2126
2112
  const denied: Array<ApprovalResult> = []
2113
+ const pendingApproved: Array<ApprovalResult> = []
2114
+ const pendingDenied: Array<ApprovalResult> = []
2127
2115
 
2128
2116
  for (const response of responses) {
2129
2117
  const request = requests.get(response.approvalId)
2130
2118
  if (Predicate.isNotUndefined(request)) {
2131
- // Skip if already resolved
2132
- if (options?.excludeResolved && toolResultIds.has(request.toolCallId)) {
2133
- continue
2134
- }
2135
-
2136
2119
  const result: ApprovalResult = {
2137
2120
  ...response,
2138
2121
  toolCallId: request.toolCallId,
@@ -2141,13 +2124,15 @@ const collectToolApprovals = (
2141
2124
 
2142
2125
  if (response.approved) {
2143
2126
  approved.push(result)
2127
+ if (!toolResultIds.has(request.toolCallId)) pendingApproved.push(result)
2144
2128
  } else {
2145
2129
  denied.push(result)
2130
+ if (!toolResultIds.has(request.toolCallId)) pendingDenied.push(result)
2146
2131
  }
2147
2132
  }
2148
2133
  }
2149
2134
 
2150
- return { approved, denied }
2135
+ return { approved, denied, pendingApproved, pendingDenied }
2151
2136
  }
2152
2137
 
2153
2138
  /**
@@ -2476,6 +2461,27 @@ const resolveToolCalls = <Tools extends Record<string, Tool.Any>>(
2476
2461
  // Utilities
2477
2462
  // =============================================================================
2478
2463
 
2464
+ // Cache one decoder per model and response kind, keyed by validation mode
2465
+ // and tool names and schema identities in insertion order.
2466
+ const makeResponseDecoder = <Decode>(make: (toolkit: Toolkit.Any, deferred: boolean) => Decode) => {
2467
+ let cached: { readonly key: ReadonlyArray<unknown>; readonly decode: Decode } | undefined
2468
+ return (toolkit: Toolkit.WithHandler<any>, encoded: boolean, deferred: boolean): Decode => {
2469
+ const key: Array<unknown> = [encoded, deferred]
2470
+ for (const tool of Object.values(toolkit.tools as Record<string, Tool.Any>)) {
2471
+ key.push(tool.name, tool.parametersSchema, tool.successSchema, tool.failureSchema)
2472
+ }
2473
+ if (cached !== undefined && cached.key.length === key.length && cached.key.every((part, i) => part === key[i])) {
2474
+ return cached.decode
2475
+ }
2476
+ const decode = make(
2477
+ encoded ? makeToolkitWithEncodedParameters(toolkit) : makeToolkitWithOpaqueParameters(toolkit),
2478
+ deferred
2479
+ )
2480
+ cached = { key, decode }
2481
+ return decode
2482
+ }
2483
+ }
2484
+
2479
2485
  // Stable parameter-mode copies let Response reuse each tool's part schemas.
2480
2486
  const parameterModeTools = new WeakMap<Tool.Any, { encoded?: Tool.Any; opaque?: Tool.Any }>()
2481
2487
 
@@ -2277,12 +2277,6 @@ export type ResourceCompletions<Schemas extends ReadonlyArray<Schema.Constraint>
2277
2277
  /**
2278
2278
  * Registers an MCP resource or resource template from an Effect program.
2279
2279
  *
2280
- * **When to use**
2281
- *
2282
- * Use when you are already inside an Effect program with an `McpServer`
2283
- * service and need to add a concrete resource or URI-template resource
2284
- * directly.
2285
- *
2286
2280
  * @see {@link resource} for the layer-based resource registration wrapper
2287
2281
  *
2288
2282
  * @stability unstable
@@ -2293,12 +2287,6 @@ export const registerResource: {
2293
2287
  /**
2294
2288
  * Registers an MCP resource or resource template from an Effect program.
2295
2289
  *
2296
- * **When to use**
2297
- *
2298
- * Use when you are already inside an Effect program with an `McpServer`
2299
- * service and need to add a concrete resource or URI-template resource
2300
- * directly.
2301
- *
2302
2290
  * @see {@link resource} for the layer-based resource registration wrapper
2303
2291
  *
2304
2292
  * @stability unstable
@@ -2324,12 +2312,6 @@ export const registerResource: {
2324
2312
  /**
2325
2313
  * Registers an MCP resource or resource template from an Effect program.
2326
2314
  *
2327
- * **When to use**
2328
- *
2329
- * Use when you are already inside an Effect program with an `McpServer`
2330
- * service and need to add a concrete resource or URI-template resource
2331
- * directly.
2332
- *
2333
2315
  * @see {@link resource} for the layer-based resource registration wrapper
2334
2316
  *
2335
2317
  * @stability unstable
@@ -2360,9 +2342,7 @@ export const registerResource: {
2360
2342
  | Schemas[number]["DecodingServices"]
2361
2343
  | Schemas[number]["EncodingServices"]
2362
2344
  | R
2363
- | (Completions[keyof Completions] extends (input: string) => infer Ret ?
2364
- Ret extends Effect.Effect<infer _A, infer _E, infer _R> ? _R : never
2365
- : never),
2345
+ | CompletionServices<Completions>,
2366
2346
  McpRequestContext
2367
2347
  >
2368
2348
  | McpServer
@@ -2491,10 +2471,6 @@ export const registerResource: {
2491
2471
  /**
2492
2472
  * Creates a layer that registers an MCP resource or resource template.
2493
2473
  *
2494
- * **When to use**
2495
- *
2496
- * Use to compose resource registration into an MCP server layer.
2497
- *
2498
2474
  * @see {@link registerResource} for the Effect-level resource registration API
2499
2475
  *
2500
2476
  * @stability unstable
@@ -2505,10 +2481,6 @@ export const resource: {
2505
2481
  /**
2506
2482
  * Creates a layer that registers an MCP resource or resource template.
2507
2483
  *
2508
- * **When to use**
2509
- *
2510
- * Use to compose resource registration into an MCP server layer.
2511
- *
2512
2484
  * @see {@link registerResource} for the Effect-level resource registration API
2513
2485
  *
2514
2486
  * @stability unstable
@@ -2533,10 +2505,6 @@ export const resource: {
2533
2505
  /**
2534
2506
  * Creates a layer that registers an MCP resource or resource template.
2535
2507
  *
2536
- * **When to use**
2537
- *
2538
- * Use to compose resource registration into an MCP server layer.
2539
- *
2540
2508
  * @see {@link registerResource} for the Effect-level resource registration API
2541
2509
  *
2542
2510
  * @stability unstable
@@ -2563,10 +2531,10 @@ export const resource: {
2563
2531
  never,
2564
2532
  never,
2565
2533
  Exclude<
2534
+ | Schemas[number]["DecodingServices"]
2535
+ | Schemas[number]["EncodingServices"]
2566
2536
  | R
2567
- | (Completions[keyof Completions] extends (input: string) => infer Ret ?
2568
- Ret extends Effect.Effect<infer _A, infer _E, infer _R> ? _R : never
2569
- : never),
2537
+ | CompletionServices<Completions>,
2570
2538
  McpRequestContext
2571
2539
  >
2572
2540
  >
@@ -2586,16 +2554,10 @@ export const resource: {
2586
2554
  /**
2587
2555
  * Registers an MCP prompt from an Effect program.
2588
2556
  *
2589
- * **When to use**
2590
- *
2591
- * Use when you are already inside an Effect program with an `McpServer`
2592
- * service and need to add a prompt handler directly.
2593
- *
2594
2557
  * **Details**
2595
2558
  *
2596
- * Parameters are decoded with the supplied schema, completion handlers encode
2597
- * per-parameter suggestions, and string prompt content is converted into a user
2598
- * text message.
2559
+ * Decodes parameters and encodes completion suggestions using their schemas.
2560
+ * String content becomes a user text message.
2599
2561
  *
2600
2562
  * @see {@link prompt} for the layer-based prompt registration wrapper
2601
2563
  *
@@ -2630,6 +2592,7 @@ export const registerPrompt = <
2630
2592
  never,
2631
2593
  | Exclude<
2632
2594
  | Schema.Struct.DecodingServices<Params>
2595
+ | Params[Extract<keyof Completions, keyof Params>]["EncodingServices"]
2633
2596
  | R
2634
2597
  | CompletionServices<Completions>,
2635
2598
  McpRequestContext
@@ -2665,7 +2628,13 @@ export const registerPrompt = <
2665
2628
  const registry = yield* McpServer
2666
2629
  const services = omitRequestServices(
2667
2630
  yield* Effect.context<
2668
- Exclude<R | Schema.Struct.DecodingServices<Params>, McpRequestContext>
2631
+ Exclude<
2632
+ | R
2633
+ | Schema.Struct.DecodingServices<Params>
2634
+ | Params[Extract<keyof Completions, keyof Params>]["EncodingServices"]
2635
+ | CompletionServices<Completions>,
2636
+ McpRequestContext
2637
+ >
2669
2638
  >()
2670
2639
  )
2671
2640
  const completions: Record<
@@ -2731,16 +2700,6 @@ export const registerPrompt = <
2731
2700
  /**
2732
2701
  * Creates a layer that registers an MCP prompt.
2733
2702
  *
2734
- * **When to use**
2735
- *
2736
- * Use to compose prompt registration into an MCP server layer.
2737
- *
2738
- * **Details**
2739
- *
2740
- * Parameters are decoded with the supplied schema, completion handlers encode
2741
- * per-parameter suggestions, and string prompt content is converted into a user
2742
- * text message.
2743
- *
2744
2703
  * @see {@link registerPrompt} for the Effect-level prompt registration API
2745
2704
  *
2746
2705
  * @stability unstable
@@ -2774,6 +2733,7 @@ export const prompt = <
2774
2733
  never,
2775
2734
  Exclude<
2776
2735
  | Schema.Struct.DecodingServices<Params>
2736
+ | Params[Extract<keyof Completions, keyof Params>]["EncodingServices"]
2777
2737
  | R
2778
2738
  | CompletionServices<Completions>,
2779
2739
  McpRequestContext
@@ -48,6 +48,11 @@ export interface FlagDescriptor {
48
48
  readonly aliases: ReadonlyArray<string>
49
49
  readonly description: string | undefined
50
50
  readonly type: FlagType
51
+ /**
52
+ * Whether the flag's value is optional. Its value can only be attached with
53
+ * `=` (`--name=value`), never given as the next word.
54
+ */
55
+ readonly optionalValue?: boolean | undefined
51
56
  }
52
57
 
53
58
  /**
package/src/cli/Flag.ts CHANGED
@@ -611,6 +611,107 @@ export const withDescription: {
611
611
  <A>(self: Flag<A>, description: string): Flag<A>
612
612
  } = dual(2, <A>(self: Flag<A>, description: string) => Param.withDescription(self, description))
613
613
 
614
+ /**
615
+ * Lets a flag be given without a value, in which case `value` is used.
616
+ *
617
+ * **Details**
618
+ *
619
+ * Follows GNU-style optional values, like `--color[=WHEN]`. An explicit value
620
+ * must be attached with `=` (`--watch=until-done` or `-w=until-done`). A bare
621
+ * `--watch` is parsed as `--watch=<value>`, so `value` is validated like any
622
+ * other input. The flag never consumes the next token, so in `--watch build`,
623
+ * `build` stays a positional argument or subcommand. The flag is still
624
+ * required unless it is made optional or given a default.
625
+ *
626
+ * **Example** (Flag with an optional value)
627
+ *
628
+ * ```ts import.meta.vitest
629
+ * import { Flag } from "effect/cli"
630
+ *
631
+ * const watch = Flag.Literals("watch", ["first-failure", "until-done"]).pipe(
632
+ * Flag.withOptionalValue("first-failure"),
633
+ * Flag.optional
634
+ * )
635
+ * // --watch => Option.some("first-failure")
636
+ * // --watch=until-done => Option.some("until-done")
637
+ * // (absent) => Option.none()
638
+ * // In help: --watch [=choice]
639
+ * watch.kind // => "flag"
640
+ * ```
641
+ *
642
+ * @stability unstable
643
+ * @category combinators
644
+ * @since 4.1.0
645
+ */
646
+ export const withOptionalValue: {
647
+ /**
648
+ * Lets a flag be given without a value, in which case `value` is used.
649
+ *
650
+ * **Details**
651
+ *
652
+ * Follows GNU-style optional values, like `--color[=WHEN]`. An explicit value
653
+ * must be attached with `=` (`--watch=until-done` or `-w=until-done`). A bare
654
+ * `--watch` is parsed as `--watch=<value>`, so `value` is validated like any
655
+ * other input. The flag never consumes the next token, so in `--watch build`,
656
+ * `build` stays a positional argument or subcommand. The flag is still
657
+ * required unless it is made optional or given a default.
658
+ *
659
+ * **Example** (Flag with an optional value)
660
+ *
661
+ * ```ts import.meta.vitest
662
+ * import { Flag } from "effect/cli"
663
+ *
664
+ * const watch = Flag.Literals("watch", ["first-failure", "until-done"]).pipe(
665
+ * Flag.withOptionalValue("first-failure"),
666
+ * Flag.optional
667
+ * )
668
+ * // --watch => Option.some("first-failure")
669
+ * // --watch=until-done => Option.some("until-done")
670
+ * // (absent) => Option.none()
671
+ * // In help: --watch [=choice]
672
+ * watch.kind // => "flag"
673
+ * ```
674
+ *
675
+ * @stability unstable
676
+ * @category combinators
677
+ * @since 4.1.0
678
+ */
679
+ (value: string): <A>(self: Flag<A>) => Flag<A>
680
+ /**
681
+ * Lets a flag be given without a value, in which case `value` is used.
682
+ *
683
+ * **Details**
684
+ *
685
+ * Follows GNU-style optional values, like `--color[=WHEN]`. An explicit value
686
+ * must be attached with `=` (`--watch=until-done` or `-w=until-done`). A bare
687
+ * `--watch` is parsed as `--watch=<value>`, so `value` is validated like any
688
+ * other input. The flag never consumes the next token, so in `--watch build`,
689
+ * `build` stays a positional argument or subcommand. The flag is still
690
+ * required unless it is made optional or given a default.
691
+ *
692
+ * **Example** (Flag with an optional value)
693
+ *
694
+ * ```ts import.meta.vitest
695
+ * import { Flag } from "effect/cli"
696
+ *
697
+ * const watch = Flag.Literals("watch", ["first-failure", "until-done"]).pipe(
698
+ * Flag.withOptionalValue("first-failure"),
699
+ * Flag.optional
700
+ * )
701
+ * // --watch => Option.some("first-failure")
702
+ * // --watch=until-done => Option.some("until-done")
703
+ * // (absent) => Option.none()
704
+ * // In help: --watch [=choice]
705
+ * watch.kind // => "flag"
706
+ * ```
707
+ *
708
+ * @stability unstable
709
+ * @category combinators
710
+ * @since 4.1.0
711
+ */
712
+ <A>(self: Flag<A>, value: string): Flag<A>
713
+ } = dual(2, <A>(self: Flag<A>, value: string) => Param.withOptionalValue(self, value))
714
+
614
715
  // -------------------------------------------------------------------------------------
615
716
  // metadata
616
717
  // -------------------------------------------------------------------------------------
package/src/cli/Param.ts CHANGED
@@ -213,6 +213,10 @@ export interface Single<Kind extends ParamKind, out A> extends Param<Kind, A> {
213
213
  readonly primitiveType: Primitive.Primitive<A>
214
214
  readonly typeName?: string | undefined
215
215
  readonly hidden: boolean
216
+ /**
217
+ * Raw value used for a bare flag. See `withOptionalValue`.
218
+ */
219
+ readonly optionalValue?: string | undefined
216
220
  }
217
221
 
218
222
  /**
@@ -362,6 +366,7 @@ export const makeSingle = <const Kind extends ParamKind, A>(params: {
362
366
  readonly description?: Option.Option<string> | undefined
363
367
  readonly aliases?: ReadonlyArray<string> | undefined
364
368
  readonly hidden?: boolean | undefined
369
+ readonly optionalValue?: string | undefined
365
370
  }): Single<Kind, A> => {
366
371
  const parse: Parse<A> = (args) =>
367
372
  params.kind === argumentKind
@@ -2664,6 +2669,97 @@ export const withMetavar: {
2664
2669
  typeName: metavar
2665
2670
  })))
2666
2671
 
2672
+ /**
2673
+ * Lets a flag be given without a value, in which case `value` is used.
2674
+ *
2675
+ * **Details**
2676
+ *
2677
+ * Follows GNU-style optional values. An explicit value must be attached with
2678
+ * `=` (`--watch=until-done`), and a bare `--watch` is parsed as
2679
+ * `--watch=<value>`. The flag never consumes the next token. It is still
2680
+ * required unless it is made optional or given a default.
2681
+ *
2682
+ * **Example** (Flag with an optional value)
2683
+ *
2684
+ * ```ts import.meta.vitest
2685
+ * import { Param } from "effect/cli"
2686
+ *
2687
+ * const watch = Param.String(Param.flagKind, "watch").pipe(
2688
+ * Param.withOptionalValue("first-failure"),
2689
+ * Param.optional
2690
+ * )
2691
+ * watch.kind // => "flag"
2692
+ * ```
2693
+ *
2694
+ * @stability unstable
2695
+ * @category combinators
2696
+ * @since 4.1.0
2697
+ */
2698
+ export const withOptionalValue: {
2699
+ /**
2700
+ * Lets a flag be given without a value, in which case `value` is used.
2701
+ *
2702
+ * **Details**
2703
+ *
2704
+ * Follows GNU-style optional values. An explicit value must be attached with
2705
+ * `=` (`--watch=until-done`), and a bare `--watch` is parsed as
2706
+ * `--watch=<value>`. The flag never consumes the next token. It is still
2707
+ * required unless it is made optional or given a default.
2708
+ *
2709
+ * **Example** (Flag with an optional value)
2710
+ *
2711
+ * ```ts import.meta.vitest
2712
+ * import { Param } from "effect/cli"
2713
+ *
2714
+ * const watch = Param.String(Param.flagKind, "watch").pipe(
2715
+ * Param.withOptionalValue("first-failure"),
2716
+ * Param.optional
2717
+ * )
2718
+ * watch.kind // => "flag"
2719
+ * ```
2720
+ *
2721
+ * @stability unstable
2722
+ * @category combinators
2723
+ * @since 4.1.0
2724
+ */
2725
+ (value: string): <A>(self: Param<typeof flagKind, A>) => Param<typeof flagKind, A>
2726
+ /**
2727
+ * Lets a flag be given without a value, in which case `value` is used.
2728
+ *
2729
+ * **Details**
2730
+ *
2731
+ * Follows GNU-style optional values. An explicit value must be attached with
2732
+ * `=` (`--watch=until-done`), and a bare `--watch` is parsed as
2733
+ * `--watch=<value>`. The flag never consumes the next token. It is still
2734
+ * required unless it is made optional or given a default.
2735
+ *
2736
+ * **Example** (Flag with an optional value)
2737
+ *
2738
+ * ```ts import.meta.vitest
2739
+ * import { Param } from "effect/cli"
2740
+ *
2741
+ * const watch = Param.String(Param.flagKind, "watch").pipe(
2742
+ * Param.withOptionalValue("first-failure"),
2743
+ * Param.optional
2744
+ * )
2745
+ * watch.kind // => "flag"
2746
+ * ```
2747
+ *
2748
+ * @stability unstable
2749
+ * @category combinators
2750
+ * @since 4.1.0
2751
+ */
2752
+ <A>(self: Param<typeof flagKind, A>, value: string): Param<typeof flagKind, A>
2753
+ } = dual(2, <A>(
2754
+ self: Param<typeof flagKind, A>,
2755
+ value: string
2756
+ ) =>
2757
+ transformSingle(self, (single) =>
2758
+ makeSingle({
2759
+ ...single,
2760
+ optionalValue: value
2761
+ })))
2762
+
2667
2763
  /**
2668
2764
  * Validates parsed values against a Schema, providing detailed error messages.
2669
2765
  *
@@ -242,10 +242,11 @@ export const toFlagDoc = (
242
242
  metadata: ReturnType<typeof Param.getParamMetadata>
243
243
  ): FlagDoc => {
244
244
  const formattedAliases = single.aliases.map((alias) => alias.length === 1 ? `-${alias}` : `--${alias}`)
245
+ const type = single.typeName ?? Primitive.getTypeName(single.primitiveType)
245
246
  return {
246
247
  name: single.name,
247
248
  aliases: formattedAliases,
248
- type: single.typeName ?? Primitive.getTypeName(single.primitiveType),
249
+ type: single.optionalValue === undefined ? type : `[=${type}]`,
249
250
  description: appendChoiceKeys(single.description, Primitive.getChoiceKeys(single.primitiveType)),
250
251
  required: single.primitiveType._tag !== "Boolean" && !metadata.isOptional
251
252
  }
@@ -7,6 +7,7 @@
7
7
  * @internal
8
8
  */
9
9
  import type * as Completions from "../../Completions.ts"
10
+ import { takesSeparateValue } from "./descriptor.ts"
10
11
 
11
12
  // ---------------------------------------------------------------------------
12
13
  // Helpers
@@ -164,7 +165,7 @@ const generateFunction = (
164
165
  lines.push(``)
165
166
 
166
167
  // Build flag-value dispatch
167
- const flagsWithValues = descriptor.flags.filter((f) => f.type._tag !== "Boolean")
168
+ const flagsWithValues = descriptor.flags.filter(takesSeparateValue)
168
169
  if (flagsWithValues.length > 0) {
169
170
  lines.push(` # Flag value completions`)
170
171
  lines.push(` case "$prev" in`)
@@ -196,7 +197,7 @@ const generateFunction = (
196
197
  lines.push(` fi`)
197
198
  lines.push(` case "\${words[i]}" in`)
198
199
  for (const flag of descriptor.flags) {
199
- if (flag.type._tag === "Boolean") continue
200
+ if (!takesSeparateValue(flag)) continue
200
201
  const forms = flagNamesForWordlist(flag)
201
202
  lines.push(` ${forms.join("|")}) _skip_next=1 ;;`)
202
203
  lines.push(` ${forms.map((form) => `${form}=*`).join("|")}) ;;`)
@@ -248,7 +249,7 @@ const generateFunction = (
248
249
  lines.push(` --) _end_of_options=1 ;;`)
249
250
  for (const flag of descriptor.flags) {
250
251
  const forms = flagNamesForWordlist(flag)
251
- if (flag.type._tag === "Boolean") {
252
+ if (!takesSeparateValue(flag)) {
252
253
  lines.push(` ${forms.join("|")}) ;;`)
253
254
  } else {
254
255
  lines.push(` ${forms.join("|")}) _skip_next=1 ;;`)
@@ -95,7 +95,8 @@ export const fromCommand = (
95
95
  name: single.name,
96
96
  aliases: single.aliases,
97
97
  description: Option.getOrUndefined(single.description),
98
- type: toFlagType(single as Param.Single<"flag", unknown>)
98
+ type: toFlagType(single as Param.Single<"flag", unknown>),
99
+ optionalValue: single.optionalValue !== undefined
99
100
  })
100
101
  }
101
102
  }
@@ -139,3 +140,11 @@ export const fromCommand = (
139
140
  subcommands
140
141
  }
141
142
  }
143
+
144
+ /**
145
+ * Whether the flag reads its value from the next word.
146
+ *
147
+ * @internal
148
+ */
149
+ export const takesSeparateValue = (flag: Completions.FlagDescriptor): boolean =>
150
+ flag.type._tag !== "Boolean" && flag.optionalValue !== true