1import * as Context from "effect/Context";
2import * as Effect from "effect/Effect";
3import * as ErrorReporter from "effect/ErrorReporter";
4import * as Layer from "effect/Layer";
5import * as Schema from "effect/Schema";
6import * as Scope from "effect/Scope";
7import * as Stream from "effect/Stream";
8import * as Stdio from "effect/Stdio";
9import * as RpcClient from "effect/rpc/RpcClient";
10import * as RpcMessage from "effect/rpc/RpcMessage";
11import * as RpcServer from "effect/rpc/RpcServer";
12
13import * as AcpSchema from "./schema.ts";
14import { AGENT_METHODS, CLIENT_METHODS } from "./_generated/meta.gen.ts";
15import * as AcpError from "./errors.ts";
16import * as AcpProtocol from "./protocol.ts";
17import * as AcpRpcs from "./rpc.ts";
18import {
19 callRpc,
20 decodeExtNotificationRegistration,
21 decodeExtRequestRegistration,
22 isolateNotificationHandler,
23 runHandler,
24} from "./_internal/shared.ts";
25
26export interface AcpAgentOptions {
27 readonly logIncoming?: boolean;
28 readonly logOutgoing?: boolean;
29 readonly logger?: (event: AcpProtocol.AcpProtocolLogEvent) => Effect.Effect<void, never>;
30}
31
32export type AcpRequestHandler<Request, Response> = AcpProtocol.AcpRequestHandler<Request, Response>;
33
34export class AcpAgent extends Context.Service<
35 AcpAgent,
36 {
37 readonly raw: {
38 /**
39 * Stream of inbound ACP notifications observed on the connection.
40 */
41 readonly notifications: Stream.Stream<AcpProtocol.AcpIncomingNotification>;
42 /**
43 * Sends a generic ACP extension request.
44 * @see https://agentclientprotocol.com/protocol/extensibility
45 */
46 readonly request: (
47 method: string,
48 payload: unknown,
49 ) => Effect.Effect<unknown, AcpError.AcpError>;
50 /**
51 * Sends a generic ACP extension notification.
52 * @see https://agentclientprotocol.com/protocol/extensibility
53 */
54 readonly notify: (method: string, payload: unknown) => Effect.Effect<void, AcpError.AcpError>;
55 };
56 readonly client: {
57 /**
58 * Requests client permission for an operation.
59 * @see https://agentclientprotocol.com/protocol/schema#session/request_permission
60 */
61 readonly requestPermission: (
62 payload: AcpSchema.RequestPermissionRequest,
63 ) => Effect.Effect<AcpSchema.RequestPermissionResponse, AcpError.AcpError>;
64 /**
65 * Requests structured user input from the client.
66 * @see https://agentclientprotocol.com/protocol/schema#elicitation/create
67 */
68 readonly elicit: (
69 payload: AcpSchema.CreateElicitationRequest,
70 ) => Effect.Effect<AcpSchema.CreateElicitationResponse, AcpError.AcpError>;
71 /**
72 * Sends a `session/update` notification to the client.
73 * @see https://agentclientprotocol.com/protocol/schema#session/update
74 */
75 readonly sessionUpdate: (
76 payload: AcpSchema.SessionNotification,
77 ) => Effect.Effect<void, AcpError.AcpError>;
78 /**
79 * Sends an `elicitation/complete` notification to the client.
80 * @see https://agentclientprotocol.com/protocol/schema#elicitation/complete
81 */
82 readonly elicitationComplete: (
83 payload: AcpSchema.CompleteElicitationNotification,
84 ) => Effect.Effect<void, AcpError.AcpError>;
85 readonly connectMcp: (
86 payload: AcpSchema.ConnectMcpRequest,
87 ) => Effect.Effect<AcpSchema.ConnectMcpResponse, AcpError.AcpError>;
88 readonly messageMcp: (
89 payload: AcpSchema.MessageMcpRequest,
90 ) => Effect.Effect<AcpSchema.MessageMcpResponse, AcpError.AcpError>;
91 readonly disconnectMcp: (
92 payload: AcpSchema.DisconnectMcpRequest,
93 ) => Effect.Effect<AcpSchema.DisconnectMcpResponse, AcpError.AcpError>;
94 readonly notifyMcp: (
95 payload: AcpSchema.MessageMcpNotification,
96 ) => Effect.Effect<void, AcpError.AcpError>;
97 /**
98 * Sends an ACP extension request to the client.
99 * @see https://agentclientprotocol.com/protocol/extensibility
100 */
101 readonly extRequest: (
102 method: string,
103 payload: unknown,
104 ) => Effect.Effect<unknown, AcpError.AcpError>;
105 /**
106 * Sends an ACP extension notification to the client.
107 * @see https://agentclientprotocol.com/protocol/extensibility
108 */
109 readonly extNotification: (
110 method: string,
111 payload: unknown,
112 ) => Effect.Effect<void, AcpError.AcpError>;
113 };
114 /**
115 * Registers a handler for `initialize`.
116 * @see https://agentclientprotocol.com/protocol/schema#initialize
117 */
118 readonly handleInitialize: (
119 handler: AcpRequestHandler<AcpSchema.InitializeRequest, AcpSchema.InitializeResponse>,
120 ) => Effect.Effect<void>;
121 /**
122 * Registers a handler for `authenticate`.
123 * @see https://agentclientprotocol.com/protocol/schema#authenticate
124 */
125 readonly handleAuthenticate: (
126 handler: AcpRequestHandler<AcpSchema.AuthenticateRequest, AcpSchema.AuthenticateResponse>,
127 ) => Effect.Effect<void>;
128 readonly handleLogout: (
129 handler: AcpRequestHandler<AcpSchema.LogoutRequest, AcpSchema.LogoutResponse>,
130 ) => Effect.Effect<void>;
131 readonly handleCreateSession: (
132 handler: AcpRequestHandler<AcpSchema.NewSessionRequest, AcpSchema.NewSessionResponse>,
133 ) => Effect.Effect<void>;
134 readonly handleLoadSession: (
135 handler: AcpRequestHandler<AcpSchema.LoadSessionRequest, AcpSchema.LoadSessionResponse>,
136 ) => Effect.Effect<void>;
137 readonly handleListSessions: (
138 handler: AcpRequestHandler<AcpSchema.ListSessionsRequest, AcpSchema.ListSessionsResponse>,
139 ) => Effect.Effect<void>;
140 readonly handleForkSession: (
141 handler: AcpRequestHandler<AcpSchema.ForkSessionRequest, AcpSchema.ForkSessionResponse>,
142 ) => Effect.Effect<void>;
143 readonly handleResumeSession: (
144 handler: AcpRequestHandler<AcpSchema.ResumeSessionRequest, AcpSchema.ResumeSessionResponse>,
145 ) => Effect.Effect<void>;
146 readonly handleCloseSession: (
147 handler: AcpRequestHandler<AcpSchema.CloseSessionRequest, AcpSchema.CloseSessionResponse>,
148 ) => Effect.Effect<void>;
149 readonly handleDeleteSession: (
150 handler: AcpRequestHandler<AcpSchema.DeleteSessionRequest, AcpSchema.DeleteSessionResponse>,
151 ) => Effect.Effect<void>;
152 readonly handleListProviders: (
153 handler: AcpRequestHandler<AcpSchema.ListProvidersRequest, AcpSchema.ListProvidersResponse>,
154 ) => Effect.Effect<void>;
155 readonly handleSetProvider: (
156 handler: AcpRequestHandler<AcpSchema.SetProviderRequest, AcpSchema.SetProviderResponse>,
157 ) => Effect.Effect<void>;
158 readonly handleDisableProvider: (
159 handler: AcpRequestHandler<
160 AcpSchema.DisableProviderRequest,
161 AcpSchema.DisableProviderResponse
162 >,
163 ) => Effect.Effect<void>;
164 readonly handleSetSessionConfigOption: (
165 handler: AcpRequestHandler<
166 AcpSchema.SetSessionConfigOptionRequest,
167 AcpSchema.SetSessionConfigOptionResponse
168 >,
169 ) => Effect.Effect<void>;
170 readonly handlePrompt: (
171 handler: AcpRequestHandler<AcpSchema.PromptRequest, AcpSchema.PromptResponse>,
172 ) => Effect.Effect<void>;
173 /**
174 * Registers a handler for `session/cancel`.
175 * @see https://agentclientprotocol.com/protocol/schema#session/cancel
176 */
177 readonly handleCancel: (
178 handler: (
179 notification: AcpSchema.CancelNotification,
180 ) => Effect.Effect<void, AcpError.AcpError>,
181 ) => Effect.Effect<void>;
182 readonly handleUnknownExtRequest: (
183 handler: (
184 method: string,
185 params: unknown,
186 context: AcpProtocol.AcpRequestContext,
187 ) => Effect.Effect<unknown, AcpError.AcpError>,
188 ) => Effect.Effect<void>;
189 readonly handleUnknownExtNotification: (
190 handler: (method: string, params: unknown) => Effect.Effect<void, AcpError.AcpError>,
191 ) => Effect.Effect<void>;
192 readonly handleExtRequest: <A, I>(
193 method: string,
194 payload: Schema.Codec<A, I>,
195 handler: AcpRequestHandler<A, unknown>,
196 ) => Effect.Effect<void>;
197 readonly handleExtNotification: <A, I>(
198 method: string,
199 payload: Schema.Codec<A, I>,
200 handler: (payload: A) => Effect.Effect<void, AcpError.AcpError>,
201 ) => Effect.Effect<void>;
202 }
203>()("effect-acp/agent/AcpAgent") {}
204
205interface AcpCoreAgentRequestHandlers {
206 initialize?: AcpRequestHandler<AcpSchema.InitializeRequest, AcpSchema.InitializeResponse>;
207 authenticate?: AcpRequestHandler<AcpSchema.AuthenticateRequest, AcpSchema.AuthenticateResponse>;
208 logout?: AcpRequestHandler<AcpSchema.LogoutRequest, AcpSchema.LogoutResponse>;
209 createSession?: AcpRequestHandler<AcpSchema.NewSessionRequest, AcpSchema.NewSessionResponse>;
210 loadSession?: AcpRequestHandler<AcpSchema.LoadSessionRequest, AcpSchema.LoadSessionResponse>;
211 listSessions?: AcpRequestHandler<AcpSchema.ListSessionsRequest, AcpSchema.ListSessionsResponse>;
212 forkSession?: AcpRequestHandler<AcpSchema.ForkSessionRequest, AcpSchema.ForkSessionResponse>;
213 resumeSession?: AcpRequestHandler<
214 AcpSchema.ResumeSessionRequest,
215 AcpSchema.ResumeSessionResponse
216 >;
217 closeSession?: AcpRequestHandler<AcpSchema.CloseSessionRequest, AcpSchema.CloseSessionResponse>;
218 deleteSession?: AcpRequestHandler<
219 AcpSchema.DeleteSessionRequest,
220 AcpSchema.DeleteSessionResponse
221 >;
222 listProviders?: AcpRequestHandler<
223 AcpSchema.ListProvidersRequest,
224 AcpSchema.ListProvidersResponse
225 >;
226 setProvider?: AcpRequestHandler<AcpSchema.SetProviderRequest, AcpSchema.SetProviderResponse>;
227 disableProvider?: AcpRequestHandler<
228 AcpSchema.DisableProviderRequest,
229 AcpSchema.DisableProviderResponse
230 >;
231 setSessionConfigOption?: AcpRequestHandler<
232 AcpSchema.SetSessionConfigOptionRequest,
233 AcpSchema.SetSessionConfigOptionResponse
234 >;
235 prompt?: AcpRequestHandler<AcpSchema.PromptRequest, AcpSchema.PromptResponse>;
236}
237
238const decodeCancelNotification = Schema.decodeUnknownEffect(AcpSchema.CancelNotification);
239
240/** @public Service construction is part of the canonical Effect module API. */
241export const make = Effect.fn("effect-acp/AcpAgent.make")(function* (
242 stdio: Stdio.Stdio,
243 options: AcpAgentOptions = {},
244): Effect.fn.Return<AcpAgent["Service"], never, Scope.Scope> {
245 const coreHandlers: AcpCoreAgentRequestHandlers = {};
246 const cancelHandlers: Array<
247 (notification: AcpSchema.CancelNotification) => Effect.Effect<void, AcpError.AcpError>
248 > = [];
249 const extRequestHandlers = new Map<string, AcpRequestHandler<unknown, unknown>>();
250 const extNotificationHandlers = new Map<
251 string,
252 (params: unknown) => Effect.Effect<void, AcpError.AcpError>
253 >();
254 let unknownExtRequestHandler:
255 | ((
256 method: string,
257 params: unknown,
258 context: AcpProtocol.AcpRequestContext,
259 ) => Effect.Effect<unknown, AcpError.AcpError>)
260 | undefined;
261 let unknownExtNotificationHandler:
262 | ((method: string, params: unknown) => Effect.Effect<void, AcpError.AcpError>)
263 | undefined;
264
265 const transport = yield* AcpProtocol.makeAcpPatchedProtocol({
266 stdio,
267 serverRequestMethods: new Set(AcpRpcs.AgentRpcs.requests.keys()),
268 ...(options.logIncoming !== undefined ? { logIncoming: options.logIncoming } : {}),
269 ...(options.logOutgoing !== undefined ? { logOutgoing: options.logOutgoing } : {}),
270 ...(options.logger ? { logger: options.logger } : {}),
271 onNotification: (notification) => {
272 if (
273 notification._tag === "ExtNotification" &&
274 notification.method === AGENT_METHODS.session_cancel
275 ) {
276 return decodeCancelNotification(notification.params).pipe(
277 Effect.mapError((error) =>
278 AcpError.AcpProtocolParseError.fromSchemaError(
279 "decode-notification-payload",
280 AGENT_METHODS.session_cancel,
281 error,
282 ),
283 ),
284 Effect.flatMap((decoded) =>
285 Effect.forEach(
286 cancelHandlers,
287 (handler) => isolateNotificationHandler(handler(decoded)),
288 { discard: true },
289 ),
290 ),
291 );
292 }
293
294 if (notification._tag !== "ExtNotification") {
295 return Effect.void;
296 }
297
298 const handler = extNotificationHandlers.get(notification.method);
299 if (handler) {
300 return handler(notification.params);
301 }
302 return unknownExtNotificationHandler
303 ? unknownExtNotificationHandler(notification.method, notification.params)
304 : Effect.void;
305 },
306 onExtRequest: (method, params, context) => {
307 const handler = extRequestHandlers.get(method);
308 if (handler) {
309 return handler(params, context);
310 }
311 return unknownExtRequestHandler
312 ? unknownExtRequestHandler(method, params, context)
313 : Effect.fail(AcpError.AcpRequestError.methodNotFound(method));
314 },
315 });
316
317 const requestContext = (
318 requestId: RpcMessage.RequestId,
319 method: string,
320 ): AcpProtocol.AcpRequestContext => ({
321 requestId: AcpProtocol.acpRequestIdentity(requestId),
322 method,
323 });
324
325 const layerAgentHandler = AcpRpcs.AgentRpcs.toLayer(
326 AcpRpcs.AgentRpcs.of({
327 [AGENT_METHODS.initialize]: (payload, { requestId }) =>
328 runHandler(
329 coreHandlers.initialize,
330 payload,
331 AGENT_METHODS.initialize,
332 requestContext(requestId, AGENT_METHODS.initialize),
333 ),
334 [AGENT_METHODS.auth_login]: (payload, { requestId }) =>
335 runHandler(
336 coreHandlers.authenticate,
337 payload,
338 AGENT_METHODS.auth_login,
339 requestContext(requestId, AGENT_METHODS.auth_login),
340 ),
341 [AGENT_METHODS.auth_logout]: (payload, { requestId }) =>
342 runHandler(
343 coreHandlers.logout,
344 payload,
345 AGENT_METHODS.auth_logout,
346 requestContext(requestId, AGENT_METHODS.auth_logout),
347 ),
348 [AGENT_METHODS.session_new]: (payload, { requestId }) =>
349 runHandler(
350 coreHandlers.createSession,
351 payload,
352 AGENT_METHODS.session_new,
353 requestContext(requestId, AGENT_METHODS.session_new),
354 ),
355 [AGENT_METHODS.session_list]: (payload, { requestId }) =>
356 runHandler(
357 coreHandlers.listSessions,
358 payload,
359 AGENT_METHODS.session_list,
360 requestContext(requestId, AGENT_METHODS.session_list),
361 ),
362 [AGENT_METHODS.session_fork]: (payload, { requestId }) =>
363 runHandler(
364 coreHandlers.forkSession,
365 payload,
366 AGENT_METHODS.session_fork,
367 requestContext(requestId, AGENT_METHODS.session_fork),
368 ),
369 [AGENT_METHODS.session_resume]: (payload, { requestId }) =>
370 runHandler(
371 payload.replayFrom?.type === "start"
372 ? (coreHandlers.loadSession ?? coreHandlers.resumeSession)
373 : (coreHandlers.resumeSession ?? coreHandlers.loadSession),
374 payload,
375 AGENT_METHODS.session_resume,
376 requestContext(requestId, AGENT_METHODS.session_resume),
377 ),
378 [AGENT_METHODS.session_close]: (payload, { requestId }) =>
379 runHandler(
380 coreHandlers.closeSession,
381 payload,
382 AGENT_METHODS.session_close,
383 requestContext(requestId, AGENT_METHODS.session_close),
384 ),
385 [AGENT_METHODS.session_delete]: (payload, { requestId }) =>
386 runHandler(
387 coreHandlers.deleteSession,
388 payload,
389 AGENT_METHODS.session_delete,
390 requestContext(requestId, AGENT_METHODS.session_delete),
391 ),
392 [AGENT_METHODS.providers_list]: (payload, { requestId }) =>
393 runHandler(
394 coreHandlers.listProviders,
395 payload,
396 AGENT_METHODS.providers_list,
397 requestContext(requestId, AGENT_METHODS.providers_list),
398 ),
399 [AGENT_METHODS.providers_set]: (payload, { requestId }) =>
400 runHandler(
401 coreHandlers.setProvider,
402 payload,
403 AGENT_METHODS.providers_set,
404 requestContext(requestId, AGENT_METHODS.providers_set),
405 ),
406 [AGENT_METHODS.providers_disable]: (payload, { requestId }) =>
407 runHandler(
408 coreHandlers.disableProvider,
409 payload,
410 AGENT_METHODS.providers_disable,
411 requestContext(requestId, AGENT_METHODS.providers_disable),
412 ),
413 [AGENT_METHODS.session_set_config_option]: (payload, { requestId }) =>
414 runHandler(
415 coreHandlers.setSessionConfigOption,
416 payload,
417 AGENT_METHODS.session_set_config_option,
418 requestContext(requestId, AGENT_METHODS.session_set_config_option),
419 ),
420 [AGENT_METHODS.session_prompt]: (payload, { requestId }) =>
421 runHandler(
422 coreHandlers.prompt,
423 payload,
424 AGENT_METHODS.session_prompt,
425 requestContext(requestId, AGENT_METHODS.session_prompt),
426 ),
427 }),
428 );
429
430 yield* RpcServer.make(AcpRpcs.AgentRpcs, { disableFatalDefects: true }).pipe(
431 // runHandler logs handler defects with their method. A reporter inherited
432 // from the caller (a WebSocket request, say) would log them again.
433 Effect.provideService(ErrorReporter.CurrentErrorReporters, new Set()),
434 Effect.provideService(RpcServer.Protocol, transport.serverProtocol),
435 Effect.provide(layerAgentHandler),
436 Effect.forkScoped,
437 );
438
439 let nextRpcRequestId = 2 ** 32;
440 const rpc = yield* RpcClient.make(AcpRpcs.ClientRpcs, {
441 generateRequestId: () => RpcMessage.RequestId(nextRpcRequestId++),
442 }).pipe(Effect.provideService(RpcClient.Protocol, transport.clientProtocol));
443
444 return AcpAgent.of({
445 raw: {
446 notifications: transport.incoming,
447 request: transport.request,
448 notify: transport.notify,
449 },
450 client: {
451 requestPermission: (payload) =>
452 callRpc(
453 CLIENT_METHODS.session_request_permission,
454 rpc[CLIENT_METHODS.session_request_permission](payload),
455 ),
456 elicit: (payload) =>
457 callRpc(CLIENT_METHODS.elicitation_create, rpc[CLIENT_METHODS.elicitation_create](payload)),
458 sessionUpdate: (payload) => transport.notify(CLIENT_METHODS.session_update, payload),
459 elicitationComplete: (payload) =>
460 transport.notify(CLIENT_METHODS.elicitation_complete, payload),
461 connectMcp: (payload) =>
462 callRpc(CLIENT_METHODS.mcp_connect, rpc[CLIENT_METHODS.mcp_connect](payload)),
463 messageMcp: (payload) =>
464 callRpc(CLIENT_METHODS.mcp_message, rpc[CLIENT_METHODS.mcp_message](payload)),
465 disconnectMcp: (payload) =>
466 callRpc(CLIENT_METHODS.mcp_disconnect, rpc[CLIENT_METHODS.mcp_disconnect](payload)),
467 notifyMcp: (payload) => transport.notify(CLIENT_METHODS.mcp_message, payload),
468 extRequest: transport.request,
469 extNotification: transport.notify,
470 },
471 handleInitialize: (handler) =>
472 Effect.suspend(() => {
473 coreHandlers.initialize = handler;
474 return Effect.void;
475 }),
476 handleAuthenticate: (handler) =>
477 Effect.suspend(() => {
478 coreHandlers.authenticate = handler;
479 return Effect.void;
480 }),
481 handleLogout: (handler) =>
482 Effect.suspend(() => {
483 coreHandlers.logout = handler;
484 return Effect.void;
485 }),
486 handleCreateSession: (handler) =>
487 Effect.suspend(() => {
488 coreHandlers.createSession = handler;
489 return Effect.void;
490 }),
491 handleLoadSession: (handler) =>
492 Effect.suspend(() => {
493 coreHandlers.loadSession = handler;
494 return Effect.void;
495 }),
496 handleListSessions: (handler) =>
497 Effect.suspend(() => {
498 coreHandlers.listSessions = handler;
499 return Effect.void;
500 }),
501 handleForkSession: (handler) =>
502 Effect.suspend(() => {
503 coreHandlers.forkSession = handler;
504 return Effect.void;
505 }),
506 handleResumeSession: (handler) =>
507 Effect.suspend(() => {
508 coreHandlers.resumeSession = handler;
509 return Effect.void;
510 }),
511 handleCloseSession: (handler) =>
512 Effect.suspend(() => {
513 coreHandlers.closeSession = handler;
514 return Effect.void;
515 }),
516 handleDeleteSession: (handler) =>
517 Effect.suspend(() => {
518 coreHandlers.deleteSession = handler;
519 return Effect.void;
520 }),
521 handleListProviders: (handler) =>
522 Effect.suspend(() => {
523 coreHandlers.listProviders = handler;
524 return Effect.void;
525 }),
526 handleSetProvider: (handler) =>
527 Effect.suspend(() => {
528 coreHandlers.setProvider = handler;
529 return Effect.void;
530 }),
531 handleDisableProvider: (handler) =>
532 Effect.suspend(() => {
533 coreHandlers.disableProvider = handler;
534 return Effect.void;
535 }),
536 handleSetSessionConfigOption: (handler) =>
537 Effect.suspend(() => {
538 coreHandlers.setSessionConfigOption = handler;
539 return Effect.void;
540 }),
541 handlePrompt: (handler) =>
542 Effect.suspend(() => {
543 coreHandlers.prompt = handler;
544 return Effect.void;
545 }),
546 handleCancel: (handler) =>
547 Effect.suspend(() => {
548 cancelHandlers.push(handler);
549 return Effect.void;
550 }),
551 handleUnknownExtRequest: (handler) =>
552 Effect.suspend(() => {
553 unknownExtRequestHandler = handler;
554 return Effect.void;
555 }),
556 handleUnknownExtNotification: (handler) =>
557 Effect.suspend(() => {
558 unknownExtNotificationHandler = handler;
559 return Effect.void;
560 }),
561 handleExtRequest: (method, payload, handler) =>
562 Effect.suspend(() => {
563 extRequestHandlers.set(method, decodeExtRequestRegistration(method, payload, handler));
564 return Effect.void;
565 }),
566 handleExtNotification: (method, payload, handler) =>
567 Effect.suspend(() => {
568 extNotificationHandlers.set(
569 method,
570 decodeExtNotificationRegistration(method, payload, handler),
571 );
572 return Effect.void;
573 }),
574 });
575});
576
577export const layer = (stdio: Stdio.Stdio, options: AcpAgentOptions = {}): Layer.Layer<AcpAgent> =>
578 Layer.effect(AcpAgent, make(stdio, options));
579
580export const layerStdio = (
581 options: AcpAgentOptions = {},
582): Layer.Layer<AcpAgent, never, Stdio.Stdio> =>
583 Layer.effect(
584 AcpAgent,
585 Effect.flatMap(Effect.service(Stdio.Stdio), (stdio) => make(stdio, options)),
586 );