| author | |
| committer | |
| log | 742dd7af0dcb54c32774f87fd354105726c7a9db |
| tree | 45d2a18f157ea43645a48bf8aa3bda0cf56647d7 |
| parent | 5c1ac922574340be4560eacf928237929497d11d |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: codex <codex@users.noreply.github.com>14 files changed, 661 insertions(+), 544 deletions(-)
apps/server/src/provider/Layers/CodexProvider.ts+3-2| ... | ... | @@ -7,7 +7,8 @@ import * as Result from "effect/Result"; |
| 7 | 7 | import * as Schema from "effect/Schema"; |
| 8 | 8 | import * as Scope from "effect/Scope"; |
| 9 | 9 | import * as Types from "effect/Types"; |
| 10 | import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"; | |
| 10 | import * as ChildProcess from "effect/unstable/process/ChildProcess"; | |
| 11 | import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; | |
| 11 | 12 | import * as CodexClient from "effect-codex-app-server/client"; |
| 12 | 13 | import * as CodexSchema from "effect-codex-app-server/schema"; |
| 13 | 14 | import * as CodexErrors from "effect-codex-app-server/errors"; |
| ... | ... | @@ -253,7 +254,7 @@ function parseCodexSkillsListResponse( |
| 253 | 254 | } |
| 254 | 255 | |
| 255 | 256 | const requestAllCodexModels = Effect.fn("requestAllCodexModels")(function* ( |
| 256 | client: CodexClient.CodexAppServerClientShape, | |
| 257 | client: CodexClient.CodexAppServerClient["Service"], | |
| 257 | 258 | ) { |
| 258 | 259 | const models: ServerProviderModel[] = []; |
| 259 | 260 | let cursor: string | null | undefined = undefined; |
apps/server/src/provider/Layers/CursorAdapter.ts+4-4| ... | ... | @@ -36,7 +36,7 @@ import * as Scope from "effect/Scope"; |
| 36 | 36 | import * as Semaphore from "effect/Semaphore"; |
| 37 | 37 | import * as Stream from "effect/Stream"; |
| 38 | 38 | import * as SynchronizedRef from "effect/SynchronizedRef"; |
| 39 | import { ChildProcessSpawner } from "effect/unstable/process"; | |
| 39 | import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; | |
| 40 | 40 | import * as EffectAcpErrors from "effect-acp/errors"; |
| 41 | 41 | import type * as EffectAcpSchema from "effect-acp/schema"; |
| 42 | 42 | |
| ... | ... | @@ -50,7 +50,7 @@ import { |
| 50 | 50 | ProviderAdapterValidationError, |
| 51 | 51 | } from "../Errors.ts"; |
| 52 | 52 | import { acpPermissionOutcome, mapAcpToAdapterError } from "../acp/AcpAdapterSupport.ts"; |
| 53 | import { type AcpSessionRuntimeShape } from "../acp/AcpSessionRuntime.ts"; | |
| 53 | import type * as AcpSessionRuntime from "../acp/AcpSessionRuntime.ts"; | |
| 54 | 54 | import { |
| 55 | 55 | makeAcpAssistantItemEvent, |
| 56 | 56 | makeAcpContentDeltaEvent, |
| ... | ... | @@ -126,7 +126,7 @@ interface CursorSessionContext { |
| 126 | 126 | readonly threadId: ThreadId; |
| 127 | 127 | session: ProviderSession; |
| 128 | 128 | readonly scope: Scope.Closeable; |
| 129 | readonly acp: AcpSessionRuntimeShape; | |
| 129 | readonly acp: AcpSessionRuntime.AcpSessionRuntime["Service"]; | |
| 130 | 130 | notificationFiber: Fiber.Fiber<void, never> | undefined; |
| 131 | 131 | readonly pendingApprovals: Map<ApprovalRequestId, PendingApproval>; |
| 132 | 132 | readonly pendingUserInputs: Map<ApprovalRequestId, PendingUserInput>; |
| ... | ... | @@ -246,7 +246,7 @@ function resolveRequestedModeId(input: { |
| 246 | 246 | } |
| 247 | 247 | |
| 248 | 248 | function applyRequestedSessionConfiguration<E>(input: { |
| 249 | readonly runtime: AcpSessionRuntimeShape; | |
| 249 | readonly runtime: AcpSessionRuntime.AcpSessionRuntime["Service"]; | |
| 250 | 250 | readonly runtimeMode: RuntimeMode; |
| 251 | 251 | readonly interactionMode: ProviderInteractionMode | undefined; |
| 252 | 252 | readonly modelSelection: |
apps/server/src/provider/Layers/CursorProvider.ts+7-4| ... | ... | @@ -21,7 +21,8 @@ import * as Path from "effect/Path"; |
| 21 | 21 | import * as Result from "effect/Result"; |
| 22 | 22 | import * as Schema from "effect/Schema"; |
| 23 | 23 | import { HttpClient } from "effect/unstable/http"; |
| 24 | import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"; | |
| 24 | import * as ChildProcess from "effect/unstable/process/ChildProcess"; | |
| 25 | import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; | |
| 25 | 26 | import { |
| 26 | 27 | createModelCapabilities, |
| 27 | 28 | getProviderOptionBooleanSelectionValue, |
| ... | ... | @@ -43,7 +44,7 @@ import { |
| 43 | 44 | enrichProviderSnapshotWithVersionAdvisory, |
| 44 | 45 | type ProviderMaintenanceCapabilities, |
| 45 | 46 | } from "../providerMaintenance.ts"; |
| 46 | import { AcpSessionRuntime } from "../acp/AcpSessionRuntime.ts"; | |
| 47 | import * as AcpSessionRuntime from "../acp/AcpSessionRuntime.ts"; | |
| 47 | 48 | import { CursorListAvailableModelsResponse } from "../acp/CursorAcpExtension.ts"; |
| 48 | 49 | |
| 49 | 50 | const decodeCursorListAvailableModelsResponse = Schema.decodeUnknownEffect( |
| ... | ... | @@ -416,12 +417,14 @@ const makeCursorAcpProbeRuntime = ( |
| 416 | 417 | clientCapabilities: CURSOR_PARAMETERIZED_MODEL_PICKER_CAPABILITIES, |
| 417 | 418 | }).pipe(Layer.provide(Layer.succeed(ChildProcessSpawner.ChildProcessSpawner, spawner))), |
| 418 | 419 | ); |
| 419 | return yield* Effect.service(AcpSessionRuntime).pipe(Effect.provide(acpContext)); | |
| 420 | return yield* Effect.service(AcpSessionRuntime.AcpSessionRuntime).pipe( | |
| 421 | Effect.provide(acpContext), | |
| 422 | ); | |
| 420 | 423 | }); |
| 421 | 424 | |
| 422 | 425 | const withCursorAcpProbeRuntime = <A, E, R>( |
| 423 | 426 | cursorSettings: CursorSettings, |
| 424 | useRuntime: (acp: AcpSessionRuntime["Service"]) => Effect.Effect<A, E, R>, | |
| 427 | useRuntime: (acp: AcpSessionRuntime.AcpSessionRuntime["Service"]) => Effect.Effect<A, E, R>, | |
| 425 | 428 | environment?: NodeJS.ProcessEnv, |
| 426 | 429 | ) => |
| 427 | 430 | makeCursorAcpProbeRuntime(cursorSettings, environment).pipe( |
apps/server/src/provider/Layers/GrokAdapter.ts+3-3| ... | ... | @@ -27,7 +27,7 @@ import * as Scope from "effect/Scope"; |
| 27 | 27 | import * as Semaphore from "effect/Semaphore"; |
| 28 | 28 | import * as Stream from "effect/Stream"; |
| 29 | 29 | import * as SynchronizedRef from "effect/SynchronizedRef"; |
| 30 | import { ChildProcessSpawner } from "effect/unstable/process"; | |
| 30 | import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; | |
| 31 | 31 | import * as EffectAcpErrors from "effect-acp/errors"; |
| 32 | 32 | import type * as EffectAcpSchema from "effect-acp/schema"; |
| 33 | 33 | |
| ... | ... | @@ -41,7 +41,7 @@ import { |
| 41 | 41 | ProviderAdapterValidationError, |
| 42 | 42 | } from "../Errors.ts"; |
| 43 | 43 | import { mapAcpToAdapterError } from "../acp/AcpAdapterSupport.ts"; |
| 44 | import { type AcpSessionRuntimeShape } from "../acp/AcpSessionRuntime.ts"; | |
| 44 | import type * as AcpSessionRuntime from "../acp/AcpSessionRuntime.ts"; | |
| 45 | 45 | import { |
| 46 | 46 | makeAcpAssistantItemEvent, |
| 47 | 47 | makeAcpContentDeltaEvent, |
| ... | ... | @@ -101,7 +101,7 @@ interface GrokSessionContext { |
| 101 | 101 | readonly acpSessionId: string; |
| 102 | 102 | session: ProviderSession; |
| 103 | 103 | readonly scope: Scope.Closeable; |
| 104 | readonly acp: AcpSessionRuntimeShape; | |
| 104 | readonly acp: AcpSessionRuntime.AcpSessionRuntime["Service"]; | |
| 105 | 105 | notificationFiber: Fiber.Fiber<void, never> | undefined; |
| 106 | 106 | readonly pendingApprovals: Map<ApprovalRequestId, PendingApproval>; |
| 107 | 107 | readonly pendingUserInputs: Map<ApprovalRequestId, PendingUserInput>; |
apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts+12-12| ... | ... | @@ -10,7 +10,7 @@ import * as Effect from "effect/Effect"; |
| 10 | 10 | import * as Stream from "effect/Stream"; |
| 11 | 11 | import { describe, expect } from "vite-plus/test"; |
| 12 | 12 | |
| 13 | import { AcpSessionRuntime, type AcpSessionRequestLogEvent } from "./AcpSessionRuntime.ts"; | |
| 13 | import * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; | |
| 14 | 14 | import type * as EffectAcpProtocol from "effect-acp/protocol"; |
| 15 | 15 | |
| 16 | 16 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); |
| ... | ... | @@ -20,9 +20,9 @@ const mockAgentArgs = [mockAgentPath]; |
| 20 | 20 | |
| 21 | 21 | describe("AcpSessionRuntime", () => { |
| 22 | 22 | it.effect("merges custom initialize client capabilities into the ACP handshake", () => { |
| 23 | const requestEvents: Array<AcpSessionRequestLogEvent> = []; | |
| 23 | const requestEvents: Array<AcpSessionRuntime.AcpSessionRequestLogEvent> = []; | |
| 24 | 24 | return Effect.gen(function* () { |
| 25 | const runtime = yield* AcpSessionRuntime; | |
| 25 | const runtime = yield* AcpSessionRuntime.AcpSessionRuntime; | |
| 26 | 26 | yield* runtime.start(); |
| 27 | 27 | |
| 28 | 28 | const initializeStarted = requestEvents.find( |
| ... | ... | @@ -64,7 +64,7 @@ describe("AcpSessionRuntime", () => { |
| 64 | 64 | |
| 65 | 65 | it.effect("starts a session, prompts, and emits normalized events against the mock agent", () => |
| 66 | 66 | Effect.gen(function* () { |
| 67 | const runtime = yield* AcpSessionRuntime; | |
| 67 | const runtime = yield* AcpSessionRuntime.AcpSessionRuntime; | |
| 68 | 68 | const started = yield* runtime.start(); |
| 69 | 69 | |
| 70 | 70 | expect(started.initializeResult).toMatchObject({ protocolVersion: 1 }); |
| ... | ... | @@ -115,7 +115,7 @@ describe("AcpSessionRuntime", () => { |
| 115 | 115 | |
| 116 | 116 | it.effect("segments assistant text around ACP tool calls", () => |
| 117 | 117 | Effect.gen(function* () { |
| 118 | const runtime = yield* AcpSessionRuntime; | |
| 118 | const runtime = yield* AcpSessionRuntime.AcpSessionRuntime; | |
| 119 | 119 | yield* runtime.start(); |
| 120 | 120 | |
| 121 | 121 | const promptResult = yield* runtime.prompt({ |
| ... | ... | @@ -176,7 +176,7 @@ describe("AcpSessionRuntime", () => { |
| 176 | 176 | |
| 177 | 177 | it.effect("suppresses generic placeholder tool updates until completion", () => |
| 178 | 178 | Effect.gen(function* () { |
| 179 | const runtime = yield* AcpSessionRuntime; | |
| 179 | const runtime = yield* AcpSessionRuntime.AcpSessionRuntime; | |
| 180 | 180 | yield* runtime.start(); |
| 181 | 181 | |
| 182 | 182 | const promptResult = yield* runtime.prompt({ |
| ... | ... | @@ -213,9 +213,9 @@ describe("AcpSessionRuntime", () => { |
| 213 | 213 | ); |
| 214 | 214 | |
| 215 | 215 | it.effect("logs ACP requests from the shared runtime", () => { |
| 216 | const requestEvents: Array<AcpSessionRequestLogEvent> = []; | |
| 216 | const requestEvents: Array<AcpSessionRuntime.AcpSessionRequestLogEvent> = []; | |
| 217 | 217 | return Effect.gen(function* () { |
| 218 | const runtime = yield* AcpSessionRuntime; | |
| 218 | const runtime = yield* AcpSessionRuntime.AcpSessionRuntime; | |
| 219 | 219 | yield* runtime.start(); |
| 220 | 220 | |
| 221 | 221 | yield* runtime.setModel("composer-2"); |
| ... | ... | @@ -265,9 +265,9 @@ describe("AcpSessionRuntime", () => { |
| 265 | 265 | }); |
| 266 | 266 | |
| 267 | 267 | it.effect("skips no-op session config writes when the requested value is already active", () => { |
| 268 | const requestEvents: Array<AcpSessionRequestLogEvent> = []; | |
| 268 | const requestEvents: Array<AcpSessionRuntime.AcpSessionRequestLogEvent> = []; | |
| 269 | 269 | return Effect.gen(function* () { |
| 270 | const runtime = yield* AcpSessionRuntime; | |
| 270 | const runtime = yield* AcpSessionRuntime.AcpSessionRuntime; | |
| 271 | 271 | yield* runtime.start(); |
| 272 | 272 | |
| 273 | 273 | yield* runtime.setConfigOption("model", "default"); |
| ... | ... | @@ -302,7 +302,7 @@ describe("AcpSessionRuntime", () => { |
| 302 | 302 | it.effect("emits low-level ACP protocol logs for raw and decoded messages", () => { |
| 303 | 303 | const protocolEvents: Array<EffectAcpProtocol.AcpProtocolLogEvent> = []; |
| 304 | 304 | return Effect.gen(function* () { |
| 305 | const runtime = yield* AcpSessionRuntime; | |
| 305 | const runtime = yield* AcpSessionRuntime.AcpSessionRuntime; | |
| 306 | 306 | yield* runtime.start(); |
| 307 | 307 | |
| 308 | 308 | yield* runtime.prompt({ |
| ... | ... | @@ -350,7 +350,7 @@ describe("AcpSessionRuntime", () => { |
| 350 | 350 | const tempDir = mkdtempSync(path.join(os.tmpdir(), "acp-runtime-")); |
| 351 | 351 | const requestLogPath = path.join(tempDir, "requests.ndjson"); |
| 352 | 352 | return Effect.gen(function* () { |
| 353 | const runtime = yield* AcpSessionRuntime; | |
| 353 | const runtime = yield* AcpSessionRuntime.AcpSessionRuntime; | |
| 354 | 354 | yield* runtime.start(); |
| 355 | 355 | |
| 356 | 356 | const error = yield* runtime.setModel("composer-2[fast=false]").pipe(Effect.flip); |
apps/server/src/provider/acp/AcpNativeLogging.ts+5-5| ... | ... | @@ -6,9 +6,9 @@ import * as Effect from "effect/Effect"; |
| 6 | 6 | import type * as EffectAcpProtocol from "effect-acp/protocol"; |
| 7 | 7 | |
| 8 | 8 | import type { EventNdjsonLogger } from "../Layers/EventNdjsonLogger.ts"; |
| 9 | import type { AcpSessionRequestLogEvent, AcpSessionRuntimeOptions } from "./AcpSessionRuntime.ts"; | |
| 9 | import type * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; | |
| 10 | 10 | |
| 11 | function formatRequestLogPayload(event: AcpSessionRequestLogEvent) { | |
| 11 | function formatRequestLogPayload(event: AcpSessionRuntime.AcpSessionRequestLogEvent) { | |
| 12 | 12 | return { |
| 13 | 13 | method: event.method, |
| 14 | 14 | status: event.status, |
| ... | ... | @@ -24,7 +24,7 @@ export const makeAcpNativeLoggerFactory = Effect.fn("makeAcpNativeLoggerFactory" |
| 24 | 24 | readonly nativeEventLogger: EventNdjsonLogger | undefined; |
| 25 | 25 | readonly provider: ProviderDriverKind; |
| 26 | 26 | readonly threadId: ThreadId; |
| 27 | }): Pick<AcpSessionRuntimeOptions, "requestLogger" | "protocolLogging"> => { | |
| 27 | }): Pick<AcpSessionRuntime.AcpSessionRuntimeOptions, "requestLogger" | "protocolLogging"> => { | |
| 28 | 28 | const writeNativeAcpLog = (logInput: { |
| 29 | 29 | readonly kind: "request" | "protocol"; |
| 30 | 30 | readonly payload: unknown; |
| ... | ... | @@ -57,7 +57,7 @@ export const makeAcpNativeLoggerFactory = Effect.fn("makeAcpNativeLoggerFactory" |
| 57 | 57 | ); |
| 58 | 58 | |
| 59 | 59 | return { |
| 60 | requestLogger: (event: AcpSessionRequestLogEvent) => | |
| 60 | requestLogger: (event: AcpSessionRuntime.AcpSessionRequestLogEvent) => | |
| 61 | 61 | writeNativeAcpLog({ |
| 62 | 62 | kind: "request", |
| 63 | 63 | payload: formatRequestLogPayload(event), |
| ... | ... | @@ -72,7 +72,7 @@ export const makeAcpNativeLoggerFactory = Effect.fn("makeAcpNativeLoggerFactory" |
| 72 | 72 | kind: "protocol", |
| 73 | 73 | payload: event, |
| 74 | 74 | }), |
| 75 | } satisfies NonNullable<AcpSessionRuntimeOptions["protocolLogging"]>, | |
| 75 | } satisfies NonNullable<AcpSessionRuntime.AcpSessionRuntimeOptions["protocolLogging"]>, | |
| 76 | 76 | } |
| 77 | 77 | : {}), |
| 78 | 78 | }; |
apps/server/src/provider/acp/AcpSessionRuntime.ts+161-63| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | import * as Cause from "effect/Cause"; |
| 2 | import * as Context from "effect/Context"; | |
| 2 | 3 | import * as Deferred from "effect/Deferred"; |
| 3 | 4 | import * as Effect from "effect/Effect"; |
| 4 | 5 | import * as Exit from "effect/Exit"; |
| ... | ... | @@ -6,9 +7,9 @@ import * as Layer from "effect/Layer"; |
| 6 | 7 | import * as Queue from "effect/Queue"; |
| 7 | 8 | import * as Ref from "effect/Ref"; |
| 8 | 9 | import * as Scope from "effect/Scope"; |
| 9 | import * as Context from "effect/Context"; | |
| 10 | 10 | import * as Stream from "effect/Stream"; |
| 11 | import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"; | |
| 11 | import * as ChildProcess from "effect/unstable/process/ChildProcess"; | |
| 12 | import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; | |
| 12 | 13 | import * as EffectAcpClient from "effect-acp/client"; |
| 13 | 14 | import * as EffectAcpErrors from "effect-acp/errors"; |
| 14 | 15 | import type * as EffectAcpSchema from "effect-acp/schema"; |
| ... | ... | @@ -75,50 +76,153 @@ export interface AcpSessionRuntimeStartResult { |
| 75 | 76 | readonly modelConfigId: string | undefined; |
| 76 | 77 | } |
| 77 | 78 | |
| 78 | export interface AcpSessionRuntimeShape { | |
| 79 | readonly handleRequestPermission: EffectAcpClient.AcpClientShape["handleRequestPermission"]; | |
| 80 | readonly handleElicitation: EffectAcpClient.AcpClientShape["handleElicitation"]; | |
| 81 | readonly handleReadTextFile: EffectAcpClient.AcpClientShape["handleReadTextFile"]; | |
| 82 | readonly handleWriteTextFile: EffectAcpClient.AcpClientShape["handleWriteTextFile"]; | |
| 83 | readonly handleCreateTerminal: EffectAcpClient.AcpClientShape["handleCreateTerminal"]; | |
| 84 | readonly handleTerminalOutput: EffectAcpClient.AcpClientShape["handleTerminalOutput"]; | |
| 85 | readonly handleTerminalWaitForExit: EffectAcpClient.AcpClientShape["handleTerminalWaitForExit"]; | |
| 86 | readonly handleTerminalKill: EffectAcpClient.AcpClientShape["handleTerminalKill"]; | |
| 87 | readonly handleTerminalRelease: EffectAcpClient.AcpClientShape["handleTerminalRelease"]; | |
| 88 | readonly handleSessionUpdate: EffectAcpClient.AcpClientShape["handleSessionUpdate"]; | |
| 89 | readonly handleElicitationComplete: EffectAcpClient.AcpClientShape["handleElicitationComplete"]; | |
| 90 | readonly handleUnknownExtRequest: EffectAcpClient.AcpClientShape["handleUnknownExtRequest"]; | |
| 91 | readonly handleUnknownExtNotification: EffectAcpClient.AcpClientShape["handleUnknownExtNotification"]; | |
| 92 | readonly handleExtRequest: EffectAcpClient.AcpClientShape["handleExtRequest"]; | |
| 93 | readonly handleExtNotification: EffectAcpClient.AcpClientShape["handleExtNotification"]; | |
| 94 | readonly start: () => Effect.Effect<AcpSessionRuntimeStartResult, EffectAcpErrors.AcpError>; | |
| 95 | readonly getEvents: () => Stream.Stream<AcpParsedSessionEvent, never>; | |
| 96 | readonly getModeState: Effect.Effect<AcpSessionModeState | undefined>; | |
| 97 | readonly getConfigOptions: Effect.Effect<ReadonlyArray<EffectAcpSchema.SessionConfigOption>>; | |
| 98 | readonly prompt: ( | |
| 99 | payload: Omit<EffectAcpSchema.PromptRequest, "sessionId">, | |
| 100 | ) => Effect.Effect<EffectAcpSchema.PromptResponse, EffectAcpErrors.AcpError>; | |
| 101 | readonly cancel: Effect.Effect<void, EffectAcpErrors.AcpError>; | |
| 102 | readonly setMode: ( | |
| 103 | modeId: string, | |
| 104 | ) => Effect.Effect<EffectAcpSchema.SetSessionModeResponse, EffectAcpErrors.AcpError>; | |
| 105 | readonly setConfigOption: ( | |
| 106 | configId: string, | |
| 107 | value: string | boolean, | |
| 108 | ) => Effect.Effect<EffectAcpSchema.SetSessionConfigOptionResponse, EffectAcpErrors.AcpError>; | |
| 109 | readonly setModel: (model: string) => Effect.Effect<void, EffectAcpErrors.AcpError>; | |
| 110 | readonly setSessionModel: ( | |
| 111 | modelId: string, | |
| 112 | ) => Effect.Effect<EffectAcpSchema.SetSessionModelResponse, EffectAcpErrors.AcpError>; | |
| 113 | readonly request: ( | |
| 114 | method: string, | |
| 115 | payload: unknown, | |
| 116 | ) => Effect.Effect<unknown, EffectAcpErrors.AcpError>; | |
| 117 | readonly notify: ( | |
| 118 | method: string, | |
| 119 | payload: unknown, | |
| 120 | ) => Effect.Effect<void, EffectAcpErrors.AcpError>; | |
| 121 | } | |
| 79 | export class AcpSessionRuntime extends Context.Service< | |
| 80 | AcpSessionRuntime, | |
| 81 | { | |
| 82 | /** | |
| 83 | * Registers a handler for `session/request_permission`. | |
| 84 | * @see https://agentclientprotocol.com/protocol/schema#session/request_permission | |
| 85 | */ | |
| 86 | readonly handleRequestPermission: EffectAcpClient.AcpClient["Service"]["handleRequestPermission"]; | |
| 87 | /** | |
| 88 | * Registers a handler for `session/elicitation`. | |
| 89 | * @see https://agentclientprotocol.com/protocol/schema#session/elicitation | |
| 90 | */ | |
| 91 | readonly handleElicitation: EffectAcpClient.AcpClient["Service"]["handleElicitation"]; | |
| 92 | /** | |
| 93 | * Registers a handler for `fs/read_text_file`. | |
| 94 | * @see https://agentclientprotocol.com/protocol/schema#fs/read_text_file | |
| 95 | */ | |
| 96 | readonly handleReadTextFile: EffectAcpClient.AcpClient["Service"]["handleReadTextFile"]; | |
| 97 | /** | |
| 98 | * Registers a handler for `fs/write_text_file`. | |
| 99 | * @see https://agentclientprotocol.com/protocol/schema#fs/write_text_file | |
| 100 | */ | |
| 101 | readonly handleWriteTextFile: EffectAcpClient.AcpClient["Service"]["handleWriteTextFile"]; | |
| 102 | /** | |
| 103 | * Registers a handler for `terminal/create`. | |
| 104 | * @see https://agentclientprotocol.com/protocol/schema#terminal/create | |
| 105 | */ | |
| 106 | readonly handleCreateTerminal: EffectAcpClient.AcpClient["Service"]["handleCreateTerminal"]; | |
| 107 | /** | |
| 108 | * Registers a handler for `terminal/output`. | |
| 109 | * @see https://agentclientprotocol.com/protocol/schema#terminal/output | |
| 110 | */ | |
| 111 | readonly handleTerminalOutput: EffectAcpClient.AcpClient["Service"]["handleTerminalOutput"]; | |
| 112 | /** | |
| 113 | * Registers a handler for `terminal/wait_for_exit`. | |
| 114 | * @see https://agentclientprotocol.com/protocol/schema#terminal/wait_for_exit | |
| 115 | */ | |
| 116 | readonly handleTerminalWaitForExit: EffectAcpClient.AcpClient["Service"]["handleTerminalWaitForExit"]; | |
| 117 | /** | |
| 118 | * Registers a handler for `terminal/kill`. | |
| 119 | * @see https://agentclientprotocol.com/protocol/schema#terminal/kill | |
| 120 | */ | |
| 121 | readonly handleTerminalKill: EffectAcpClient.AcpClient["Service"]["handleTerminalKill"]; | |
| 122 | /** | |
| 123 | * Registers a handler for `terminal/release`. | |
| 124 | * @see https://agentclientprotocol.com/protocol/schema#terminal/release | |
| 125 | */ | |
| 126 | readonly handleTerminalRelease: EffectAcpClient.AcpClient["Service"]["handleTerminalRelease"]; | |
| 127 | /** | |
| 128 | * Registers a handler for `session/update`. | |
| 129 | * @see https://agentclientprotocol.com/protocol/schema#session/update | |
| 130 | */ | |
| 131 | readonly handleSessionUpdate: EffectAcpClient.AcpClient["Service"]["handleSessionUpdate"]; | |
| 132 | /** | |
| 133 | * Registers a handler for `session/elicitation/complete`. | |
| 134 | * @see https://agentclientprotocol.com/protocol/schema#session/elicitation/complete | |
| 135 | */ | |
| 136 | readonly handleElicitationComplete: EffectAcpClient.AcpClient["Service"]["handleElicitationComplete"]; | |
| 137 | /** | |
| 138 | * Registers a fallback extension request handler. | |
| 139 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 140 | */ | |
| 141 | readonly handleUnknownExtRequest: EffectAcpClient.AcpClient["Service"]["handleUnknownExtRequest"]; | |
| 142 | /** | |
| 143 | * Registers a fallback extension notification handler. | |
| 144 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 145 | */ | |
| 146 | readonly handleUnknownExtNotification: EffectAcpClient.AcpClient["Service"]["handleUnknownExtNotification"]; | |
| 147 | /** | |
| 148 | * Registers a typed extension request handler. | |
| 149 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 150 | */ | |
| 151 | readonly handleExtRequest: EffectAcpClient.AcpClient["Service"]["handleExtRequest"]; | |
| 152 | /** | |
| 153 | * Registers a typed extension notification handler. | |
| 154 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 155 | */ | |
| 156 | readonly handleExtNotification: EffectAcpClient.AcpClient["Service"]["handleExtNotification"]; | |
| 157 | /** | |
| 158 | * Initializes the ACP connection, authenticates, and loads, resumes, or creates the session. | |
| 159 | * Concurrent calls share the same in-flight startup and a failed startup may be retried. | |
| 160 | */ | |
| 161 | readonly start: () => Effect.Effect<AcpSessionRuntimeStartResult, EffectAcpErrors.AcpError>; | |
| 162 | /** Stream of parsed ACP session events emitted after startup. */ | |
| 163 | readonly getEvents: () => Stream.Stream<AcpParsedSessionEvent, never>; | |
| 164 | /** Latest mode state observed from session setup and `session/update` notifications. */ | |
| 165 | readonly getModeState: Effect.Effect<AcpSessionModeState | undefined>; | |
| 166 | /** Latest configuration options observed from session setup and configuration writes. */ | |
| 167 | readonly getConfigOptions: Effect.Effect<ReadonlyArray<EffectAcpSchema.SessionConfigOption>>; | |
| 168 | /** | |
| 169 | * Sends a prompt turn to the active session. | |
| 170 | * @see https://agentclientprotocol.com/protocol/schema#session/prompt | |
| 171 | */ | |
| 172 | readonly prompt: ( | |
| 173 | payload: Omit<EffectAcpSchema.PromptRequest, "sessionId">, | |
| 174 | ) => Effect.Effect<EffectAcpSchema.PromptResponse, EffectAcpErrors.AcpError>; | |
| 175 | /** | |
| 176 | * Sends a real ACP `session/cancel` notification for the active session. | |
| 177 | * @see https://agentclientprotocol.com/protocol/schema#session/cancel | |
| 178 | */ | |
| 179 | readonly cancel: Effect.Effect<void, EffectAcpErrors.AcpError>; | |
| 180 | /** | |
| 181 | * Selects the active mode through the negotiated `mode` configuration option. | |
| 182 | * This is a no-op when the requested mode is already active. | |
| 183 | * @see https://agentclientprotocol.com/protocol/schema#session/set_config_option | |
| 184 | */ | |
| 185 | readonly setMode: ( | |
| 186 | modeId: string, | |
| 187 | ) => Effect.Effect<EffectAcpSchema.SetSessionModeResponse, EffectAcpErrors.AcpError>; | |
| 188 | /** | |
| 189 | * Updates a session configuration option and the runtime configuration snapshot. | |
| 190 | * @see https://agentclientprotocol.com/protocol/schema#session/set_config_option | |
| 191 | */ | |
| 192 | readonly setConfigOption: ( | |
| 193 | configId: string, | |
| 194 | value: string | boolean, | |
| 195 | ) => Effect.Effect<EffectAcpSchema.SetSessionConfigOptionResponse, EffectAcpErrors.AcpError>; | |
| 196 | /** | |
| 197 | * Selects the base model through the negotiated model configuration option. | |
| 198 | * @see https://agentclientprotocol.com/protocol/schema#session/set_config_option | |
| 199 | */ | |
| 200 | readonly setModel: (model: string) => Effect.Effect<void, EffectAcpErrors.AcpError>; | |
| 201 | /** | |
| 202 | * Selects the active model through the unstable ACP `session/set_model` capability. | |
| 203 | * @see https://agentclientprotocol.com/protocol/schema#session/set_model | |
| 204 | */ | |
| 205 | readonly setSessionModel: ( | |
| 206 | modelId: string, | |
| 207 | ) => Effect.Effect<EffectAcpSchema.SetSessionModelResponse, EffectAcpErrors.AcpError>; | |
| 208 | /** | |
| 209 | * Sends a generic ACP extension request and records it through the request logger. | |
| 210 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 211 | */ | |
| 212 | readonly request: ( | |
| 213 | method: string, | |
| 214 | payload: unknown, | |
| 215 | ) => Effect.Effect<unknown, EffectAcpErrors.AcpError>; | |
| 216 | /** | |
| 217 | * Sends a generic ACP extension notification. | |
| 218 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 219 | */ | |
| 220 | readonly notify: ( | |
| 221 | method: string, | |
| 222 | payload: unknown, | |
| 223 | ) => Effect.Effect<void, EffectAcpErrors.AcpError>; | |
| 224 | } | |
| 225 | >()("t3/provider/acp/AcpSessionRuntime") {} | |
| 122 | 226 | |
| 123 | 227 | interface AcpStartedState extends AcpSessionRuntimeStartResult {} |
| 124 | 228 | |
| ... | ... | @@ -140,24 +244,10 @@ interface EnsureActiveAssistantSegmentResult { |
| 140 | 244 | readonly startedEvent?: Extract<AcpParsedSessionEvent, { readonly _tag: "AssistantItemStarted" }>; |
| 141 | 245 | } |
| 142 | 246 | |
| 143 | export class AcpSessionRuntime extends Context.Service<AcpSessionRuntime, AcpSessionRuntimeShape>()( | |
| 144 | "t3/provider/acp/AcpSessionRuntime", | |
| 145 | ) { | |
| 146 | static layer( | |
| 147 | options: AcpSessionRuntimeOptions, | |
| 148 | ): Layer.Layer< | |
| 149 | AcpSessionRuntime, | |
| 150 | EffectAcpErrors.AcpError, | |
| 151 | ChildProcessSpawner.ChildProcessSpawner | |
| 152 | > { | |
| 153 | return Layer.effect(AcpSessionRuntime, makeAcpSessionRuntime(options)); | |
| 154 | } | |
| 155 | } | |
| 156 | ||
| 157 | const makeAcpSessionRuntime = ( | |
| 247 | export const make = ( | |
| 158 | 248 | options: AcpSessionRuntimeOptions, |
| 159 | 249 | ): Effect.Effect< |
| 160 | AcpSessionRuntimeShape, | |
| 250 | AcpSessionRuntime["Service"], | |
| 161 | 251 | EffectAcpErrors.AcpError, |
| 162 | 252 | ChildProcessSpawner.ChildProcessSpawner | Scope.Scope |
| 163 | 253 | > => |
| ... | ... | @@ -573,9 +663,17 @@ const makeAcpSessionRuntime = ( |
| 573 | 663 | request: (method, payload) => |
| 574 | 664 | runLoggedRequest(method, payload, acp.raw.request(method, payload)), |
| 575 | 665 | notify: acp.raw.notify, |
| 576 | } satisfies AcpSessionRuntimeShape; | |
| 666 | } satisfies AcpSessionRuntime["Service"]; | |
| 577 | 667 | }); |
| 578 | 668 | |
| 669 | export const layer = ( | |
| 670 | options: AcpSessionRuntimeOptions, | |
| 671 | ): Layer.Layer< | |
| 672 | AcpSessionRuntime, | |
| 673 | EffectAcpErrors.AcpError, | |
| 674 | ChildProcessSpawner.ChildProcessSpawner | |
| 675 | > => Layer.effect(AcpSessionRuntime, make(options)); | |
| 676 | ||
| 579 | 677 | function sessionConfigOptionsFromSetup( |
| 580 | 678 | response: |
| 581 | 679 | | { |
apps/server/src/provider/acp/CursorAcpCliProbe.test.ts+4-4| ... | ... | @@ -9,12 +9,12 @@ import * as Effect from "effect/Effect"; |
| 9 | 9 | import { describe, expect } from "vite-plus/test"; |
| 10 | 10 | import type * as EffectAcpSchema from "effect-acp/schema"; |
| 11 | 11 | |
| 12 | import { AcpSessionRuntime } from "./AcpSessionRuntime.ts"; | |
| 12 | import * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; | |
| 13 | 13 | |
| 14 | 14 | describe.runIf(process.env.T3_CURSOR_ACP_PROBE === "1")("Cursor ACP CLI probe", () => { |
| 15 | 15 | it.effect("initialize and authenticate against real agent acp", () => |
| 16 | 16 | Effect.gen(function* () { |
| 17 | const runtime = yield* AcpSessionRuntime; | |
| 17 | const runtime = yield* AcpSessionRuntime.AcpSessionRuntime; | |
| 18 | 18 | const started = yield* runtime.start(); |
| 19 | 19 | expect(started.initializeResult).toBeDefined(); |
| 20 | 20 | }).pipe( |
| ... | ... | @@ -42,7 +42,7 @@ describe.runIf(process.env.T3_CURSOR_ACP_PROBE === "1")("Cursor ACP CLI probe", |
| 42 | 42 | |
| 43 | 43 | it.effect("session/new returns configOptions with a model selector", () => |
| 44 | 44 | Effect.gen(function* () { |
| 45 | const runtime = yield* AcpSessionRuntime; | |
| 45 | const runtime = yield* AcpSessionRuntime.AcpSessionRuntime; | |
| 46 | 46 | const started = yield* runtime.start(); |
| 47 | 47 | const result = started.sessionSetupResult; |
| 48 | 48 | // @effect-diagnostics-next-line preferSchemaOverJson:off |
| ... | ... | @@ -97,7 +97,7 @@ describe.runIf(process.env.T3_CURSOR_ACP_PROBE === "1")("Cursor ACP CLI probe", |
| 97 | 97 | |
| 98 | 98 | it.effect("session/set_config_option switches the model in-session", () => |
| 99 | 99 | Effect.gen(function* () { |
| 100 | const runtime = yield* AcpSessionRuntime; | |
| 100 | const runtime = yield* AcpSessionRuntime.AcpSessionRuntime; | |
| 101 | 101 | const started = yield* runtime.start(); |
| 102 | 102 | const newResult = started.sessionSetupResult; |
| 103 | 103 |
apps/server/src/provider/acp/CursorAcpSupport.ts+13-12| ... | ... | @@ -2,7 +2,7 @@ import { type CursorSettings, type ProviderOptionSelection } from "@t3tools/cont |
| 2 | 2 | import * as Effect from "effect/Effect"; |
| 3 | 3 | import * as Layer from "effect/Layer"; |
| 4 | 4 | import * as Scope from "effect/Scope"; |
| 5 | import { ChildProcessSpawner } from "effect/unstable/process"; | |
| 5 | import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; | |
| 6 | 6 | import type * as EffectAcpErrors from "effect-acp/errors"; |
| 7 | 7 | |
| 8 | 8 | import { |
| ... | ... | @@ -10,17 +10,12 @@ import { |
| 10 | 10 | resolveCursorAcpBaseModelId, |
| 11 | 11 | resolveCursorAcpConfigUpdates, |
| 12 | 12 | } from "../Layers/CursorProvider.ts"; |
| 13 | import { | |
| 14 | AcpSessionRuntime, | |
| 15 | type AcpSessionRuntimeOptions, | |
| 16 | type AcpSessionRuntimeShape, | |
| 17 | type AcpSpawnInput, | |
| 18 | } from "./AcpSessionRuntime.ts"; | |
| 13 | import * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; | |
| 19 | 14 | |
| 20 | 15 | type CursorAcpRuntimeCursorSettings = Pick<CursorSettings, "apiEndpoint" | "binaryPath">; |
| 21 | 16 | |
| 22 | 17 | export interface CursorAcpRuntimeInput extends Omit< |
| 23 | AcpSessionRuntimeOptions, | |
| 18 | AcpSessionRuntime.AcpSessionRuntimeOptions, | |
| 24 | 19 | "authMethodId" | "clientCapabilities" | "spawn" |
| 25 | 20 | > { |
| 26 | 21 | readonly childProcessSpawner: ChildProcessSpawner.ChildProcessSpawner["Service"]; |
| ... | ... | @@ -38,7 +33,7 @@ export function buildCursorAcpSpawnInput( |
| 38 | 33 | cursorSettings: CursorAcpRuntimeCursorSettings | null | undefined, |
| 39 | 34 | cwd: string, |
| 40 | 35 | environment?: NodeJS.ProcessEnv, |
| 41 | ): AcpSpawnInput { | |
| 36 | ): AcpSessionRuntime.AcpSpawnInput { | |
| 42 | 37 | return { |
| 43 | 38 | command: cursorSettings?.binaryPath || "agent", |
| 44 | 39 | args: [ |
| ... | ... | @@ -52,7 +47,11 @@ export function buildCursorAcpSpawnInput( |
| 52 | 47 | |
| 53 | 48 | export const makeCursorAcpRuntime = ( |
| 54 | 49 | input: CursorAcpRuntimeInput, |
| 55 | ): Effect.Effect<AcpSessionRuntimeShape, EffectAcpErrors.AcpError, Scope.Scope> => | |
| 50 | ): Effect.Effect< | |
| 51 | AcpSessionRuntime.AcpSessionRuntime["Service"], | |
| 52 | EffectAcpErrors.AcpError, | |
| 53 | Scope.Scope | |
| 54 | > => | |
| 56 | 55 | Effect.gen(function* () { |
| 57 | 56 | const acpContext = yield* Layer.build( |
| 58 | 57 | AcpSessionRuntime.layer({ |
| ... | ... | @@ -66,11 +65,13 @@ export const makeCursorAcpRuntime = ( |
| 66 | 65 | ), |
| 67 | 66 | ), |
| 68 | 67 | ); |
| 69 | return yield* Effect.service(AcpSessionRuntime).pipe(Effect.provide(acpContext)); | |
| 68 | return yield* Effect.service(AcpSessionRuntime.AcpSessionRuntime).pipe( | |
| 69 | Effect.provide(acpContext), | |
| 70 | ); | |
| 70 | 71 | }); |
| 71 | 72 | |
| 72 | 73 | interface CursorAcpModelSelectionRuntime { |
| 73 | readonly getConfigOptions: AcpSessionRuntimeShape["getConfigOptions"]; | |
| 74 | readonly getConfigOptions: AcpSessionRuntime.AcpSessionRuntime["Service"]["getConfigOptions"]; | |
| 74 | 75 | readonly setConfigOption: ( |
| 75 | 76 | configId: string, |
| 76 | 77 | value: string | boolean, |
apps/server/src/provider/acp/GrokAcpSupport.ts+13-12| ... | ... | @@ -2,17 +2,12 @@ import { type GrokSettings, ProviderDriverKind } from "@t3tools/contracts"; |
| 2 | 2 | import * as Effect from "effect/Effect"; |
| 3 | 3 | import * as Layer from "effect/Layer"; |
| 4 | 4 | import * as Scope from "effect/Scope"; |
| 5 | import { ChildProcessSpawner } from "effect/unstable/process"; | |
| 5 | import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; | |
| 6 | 6 | import * as EffectAcpErrors from "effect-acp/errors"; |
| 7 | 7 | import type * as EffectAcpSchema from "effect-acp/schema"; |
| 8 | 8 | import { normalizeModelSlug } from "@t3tools/shared/model"; |
| 9 | 9 | |
| 10 | import { | |
| 11 | AcpSessionRuntime, | |
| 12 | type AcpSessionRuntimeOptions, | |
| 13 | type AcpSessionRuntimeShape, | |
| 14 | type AcpSpawnInput, | |
| 15 | } from "./AcpSessionRuntime.ts"; | |
| 10 | import * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; | |
| 16 | 11 | |
| 17 | 12 | const GROK_API_KEY_ENV = "XAI_API_KEY"; |
| 18 | 13 | const GROK_OAUTH2_REFERRER_ENV = "GROK_OAUTH2_REFERRER"; |
| ... | ... | @@ -24,7 +19,7 @@ const GROK_DRIVER_KIND = ProviderDriverKind.make("grok"); |
| 24 | 19 | type GrokAcpRuntimeGrokSettings = Pick<GrokSettings, "binaryPath">; |
| 25 | 20 | |
| 26 | 21 | interface GrokAcpRuntimeInput extends Omit< |
| 27 | AcpSessionRuntimeOptions, | |
| 22 | AcpSessionRuntime.AcpSessionRuntimeOptions, | |
| 28 | 23 | "authMethodId" | "clientCapabilities" | "spawn" |
| 29 | 24 | > { |
| 30 | 25 | readonly childProcessSpawner: ChildProcessSpawner.ChildProcessSpawner["Service"]; |
| ... | ... | @@ -36,7 +31,7 @@ export function buildGrokAcpSpawnInput( |
| 36 | 31 | grokSettings: GrokAcpRuntimeGrokSettings | null | undefined, |
| 37 | 32 | cwd: string, |
| 38 | 33 | environment?: NodeJS.ProcessEnv, |
| 39 | ): AcpSpawnInput { | |
| 34 | ): AcpSessionRuntime.AcpSpawnInput { | |
| 40 | 35 | return { |
| 41 | 36 | command: grokSettings?.binaryPath || "grok", |
| 42 | 37 | args: ["agent", "stdio"], |
| ... | ... | @@ -56,7 +51,11 @@ function resolveGrokAuthMethodId(environment: NodeJS.ProcessEnv | undefined): st |
| 56 | 51 | |
| 57 | 52 | export const makeGrokAcpRuntime = ( |
| 58 | 53 | input: GrokAcpRuntimeInput, |
| 59 | ): Effect.Effect<AcpSessionRuntimeShape, EffectAcpErrors.AcpError, Scope.Scope> => | |
| 54 | ): Effect.Effect< | |
| 55 | AcpSessionRuntime.AcpSessionRuntime["Service"], | |
| 56 | EffectAcpErrors.AcpError, | |
| 57 | Scope.Scope | |
| 58 | > => | |
| 60 | 59 | Effect.gen(function* () { |
| 61 | 60 | const acpContext = yield* Layer.build( |
| 62 | 61 | AcpSessionRuntime.layer({ |
| ... | ... | @@ -69,7 +68,9 @@ export const makeGrokAcpRuntime = ( |
| 69 | 68 | ), |
| 70 | 69 | ), |
| 71 | 70 | ); |
| 72 | return yield* Effect.service(AcpSessionRuntime).pipe(Effect.provide(acpContext)); | |
| 71 | return yield* Effect.service(AcpSessionRuntime.AcpSessionRuntime).pipe( | |
| 72 | Effect.provide(acpContext), | |
| 73 | ); | |
| 73 | 74 | }); |
| 74 | 75 | |
| 75 | 76 | export function resolveGrokAcpBaseModelId(model: string | null | undefined): string { |
| ... | ... | @@ -88,7 +89,7 @@ export function currentGrokModelIdFromSessionSetup( |
| 88 | 89 | } |
| 89 | 90 | |
| 90 | 91 | export function applyGrokAcpModelSelection<E>(input: { |
| 91 | readonly runtime: Pick<AcpSessionRuntimeShape, "setSessionModel">; | |
| 92 | readonly runtime: Pick<AcpSessionRuntime.AcpSessionRuntime["Service"], "setSessionModel">; | |
| 92 | 93 | readonly currentModelId: string | undefined; |
| 93 | 94 | readonly requestedModelId: string | undefined; |
| 94 | 95 | readonly mapError: (cause: EffectAcpErrors.AcpError) => E; |
packages/effect-acp/src/agent.ts+177-176| ... | ... | @@ -27,189 +27,190 @@ export interface AcpAgentOptions { |
| 27 | 27 | readonly logger?: (event: AcpProtocol.AcpProtocolLogEvent) => Effect.Effect<void, never>; |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | export interface AcpAgentShape { | |
| 31 | readonly raw: { | |
| 30 | export class AcpAgent extends Context.Service< | |
| 31 | AcpAgent, | |
| 32 | { | |
| 33 | readonly raw: { | |
| 34 | /** | |
| 35 | * Stream of inbound ACP notifications observed on the connection. | |
| 36 | */ | |
| 37 | readonly notifications: Stream.Stream<AcpProtocol.AcpIncomingNotification>; | |
| 38 | /** | |
| 39 | * Sends a generic ACP extension request. | |
| 40 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 41 | */ | |
| 42 | readonly request: ( | |
| 43 | method: string, | |
| 44 | payload: unknown, | |
| 45 | ) => Effect.Effect<unknown, AcpError.AcpError>; | |
| 46 | /** | |
| 47 | * Sends a generic ACP extension notification. | |
| 48 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 49 | */ | |
| 50 | readonly notify: (method: string, payload: unknown) => Effect.Effect<void, AcpError.AcpError>; | |
| 51 | }; | |
| 52 | readonly client: { | |
| 53 | /** | |
| 54 | * Requests client permission for an operation. | |
| 55 | * @see https://agentclientprotocol.com/protocol/schema#session/request_permission | |
| 56 | */ | |
| 57 | readonly requestPermission: ( | |
| 58 | payload: AcpSchema.RequestPermissionRequest, | |
| 59 | ) => Effect.Effect<AcpSchema.RequestPermissionResponse, AcpError.AcpError>; | |
| 60 | /** | |
| 61 | * Requests structured user input from the client. | |
| 62 | * @see https://agentclientprotocol.com/protocol/schema#session/elicitation | |
| 63 | */ | |
| 64 | readonly elicit: ( | |
| 65 | payload: AcpSchema.ElicitationRequest, | |
| 66 | ) => Effect.Effect<AcpSchema.ElicitationResponse, AcpError.AcpError>; | |
| 67 | /** | |
| 68 | * Requests file contents from the client. | |
| 69 | * @see https://agentclientprotocol.com/protocol/schema#fs/read_text_file | |
| 70 | */ | |
| 71 | readonly readTextFile: ( | |
| 72 | payload: AcpSchema.ReadTextFileRequest, | |
| 73 | ) => Effect.Effect<AcpSchema.ReadTextFileResponse, AcpError.AcpError>; | |
| 74 | /** | |
| 75 | * Writes a text file through the client. | |
| 76 | * @see https://agentclientprotocol.com/protocol/schema#fs/write_text_file | |
| 77 | */ | |
| 78 | readonly writeTextFile: ( | |
| 79 | payload: AcpSchema.WriteTextFileRequest, | |
| 80 | ) => Effect.Effect<AcpSchema.WriteTextFileResponse, AcpError.AcpError>; | |
| 81 | /** | |
| 82 | * Creates a terminal on the client side. | |
| 83 | * @see https://agentclientprotocol.com/protocol/schema#terminal/create | |
| 84 | */ | |
| 85 | readonly createTerminal: ( | |
| 86 | payload: AcpSchema.CreateTerminalRequest, | |
| 87 | ) => Effect.Effect<AcpTerminal.AcpTerminal, AcpError.AcpError>; | |
| 88 | /** | |
| 89 | * Sends a `session/update` notification to the client. | |
| 90 | * @see https://agentclientprotocol.com/protocol/schema#session/update | |
| 91 | */ | |
| 92 | readonly sessionUpdate: ( | |
| 93 | payload: AcpSchema.SessionNotification, | |
| 94 | ) => Effect.Effect<void, AcpError.AcpError>; | |
| 95 | /** | |
| 96 | * Sends a `session/elicitation/complete` notification to the client. | |
| 97 | * @see https://agentclientprotocol.com/protocol/schema#session/elicitation/complete | |
| 98 | */ | |
| 99 | readonly elicitationComplete: ( | |
| 100 | payload: AcpSchema.ElicitationCompleteNotification, | |
| 101 | ) => Effect.Effect<void, AcpError.AcpError>; | |
| 102 | /** | |
| 103 | * Sends an ACP extension request to the client. | |
| 104 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 105 | */ | |
| 106 | readonly extRequest: ( | |
| 107 | method: string, | |
| 108 | payload: unknown, | |
| 109 | ) => Effect.Effect<unknown, AcpError.AcpError>; | |
| 110 | /** | |
| 111 | * Sends an ACP extension notification to the client. | |
| 112 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 113 | */ | |
| 114 | readonly extNotification: ( | |
| 115 | method: string, | |
| 116 | payload: unknown, | |
| 117 | ) => Effect.Effect<void, AcpError.AcpError>; | |
| 118 | }; | |
| 32 | 119 | /** |
| 33 | * Stream of inbound ACP notifications observed on the connection. | |
| 120 | * Registers a handler for `initialize`. | |
| 121 | * @see https://agentclientprotocol.com/protocol/schema#initialize | |
| 34 | 122 | */ |
| 35 | readonly notifications: Stream.Stream<AcpProtocol.AcpIncomingNotification>; | |
| 123 | readonly handleInitialize: ( | |
| 124 | handler: ( | |
| 125 | request: AcpSchema.InitializeRequest, | |
| 126 | ) => Effect.Effect<AcpSchema.InitializeResponse, AcpError.AcpError>, | |
| 127 | ) => Effect.Effect<void>; | |
| 36 | 128 | /** |
| 37 | * Sends a generic ACP extension request. | |
| 38 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 129 | * Registers a handler for `authenticate`. | |
| 130 | * @see https://agentclientprotocol.com/protocol/schema#authenticate | |
| 39 | 131 | */ |
| 40 | readonly request: ( | |
| 41 | method: string, | |
| 42 | payload: unknown, | |
| 43 | ) => Effect.Effect<unknown, AcpError.AcpError>; | |
| 44 | /** | |
| 45 | * Sends a generic ACP extension notification. | |
| 46 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 47 | */ | |
| 48 | readonly notify: (method: string, payload: unknown) => Effect.Effect<void, AcpError.AcpError>; | |
| 49 | }; | |
| 50 | readonly client: { | |
| 51 | /** | |
| 52 | * Requests client permission for an operation. | |
| 53 | * @see https://agentclientprotocol.com/protocol/schema#session/request_permission | |
| 54 | */ | |
| 55 | readonly requestPermission: ( | |
| 56 | payload: AcpSchema.RequestPermissionRequest, | |
| 57 | ) => Effect.Effect<AcpSchema.RequestPermissionResponse, AcpError.AcpError>; | |
| 58 | /** | |
| 59 | * Requests structured user input from the client. | |
| 60 | * @see https://agentclientprotocol.com/protocol/schema#session/elicitation | |
| 61 | */ | |
| 62 | readonly elicit: ( | |
| 63 | payload: AcpSchema.ElicitationRequest, | |
| 64 | ) => Effect.Effect<AcpSchema.ElicitationResponse, AcpError.AcpError>; | |
| 65 | /** | |
| 66 | * Requests file contents from the client. | |
| 67 | * @see https://agentclientprotocol.com/protocol/schema#fs/read_text_file | |
| 68 | */ | |
| 69 | readonly readTextFile: ( | |
| 70 | payload: AcpSchema.ReadTextFileRequest, | |
| 71 | ) => Effect.Effect<AcpSchema.ReadTextFileResponse, AcpError.AcpError>; | |
| 72 | /** | |
| 73 | * Writes a text file through the client. | |
| 74 | * @see https://agentclientprotocol.com/protocol/schema#fs/write_text_file | |
| 75 | */ | |
| 76 | readonly writeTextFile: ( | |
| 77 | payload: AcpSchema.WriteTextFileRequest, | |
| 78 | ) => Effect.Effect<AcpSchema.WriteTextFileResponse, AcpError.AcpError>; | |
| 132 | readonly handleAuthenticate: ( | |
| 133 | handler: ( | |
| 134 | request: AcpSchema.AuthenticateRequest, | |
| 135 | ) => Effect.Effect<AcpSchema.AuthenticateResponse, AcpError.AcpError>, | |
| 136 | ) => Effect.Effect<void>; | |
| 137 | readonly handleLogout: ( | |
| 138 | handler: ( | |
| 139 | request: AcpSchema.LogoutRequest, | |
| 140 | ) => Effect.Effect<AcpSchema.LogoutResponse, AcpError.AcpError>, | |
| 141 | ) => Effect.Effect<void>; | |
| 142 | readonly handleCreateSession: ( | |
| 143 | handler: ( | |
| 144 | request: AcpSchema.NewSessionRequest, | |
| 145 | ) => Effect.Effect<AcpSchema.NewSessionResponse, AcpError.AcpError>, | |
| 146 | ) => Effect.Effect<void>; | |
| 147 | readonly handleLoadSession: ( | |
| 148 | handler: ( | |
| 149 | request: AcpSchema.LoadSessionRequest, | |
| 150 | ) => Effect.Effect<AcpSchema.LoadSessionResponse, AcpError.AcpError>, | |
| 151 | ) => Effect.Effect<void>; | |
| 152 | readonly handleListSessions: ( | |
| 153 | handler: ( | |
| 154 | request: AcpSchema.ListSessionsRequest, | |
| 155 | ) => Effect.Effect<AcpSchema.ListSessionsResponse, AcpError.AcpError>, | |
| 156 | ) => Effect.Effect<void>; | |
| 157 | readonly handleForkSession: ( | |
| 158 | handler: ( | |
| 159 | request: AcpSchema.ForkSessionRequest, | |
| 160 | ) => Effect.Effect<AcpSchema.ForkSessionResponse, AcpError.AcpError>, | |
| 161 | ) => Effect.Effect<void>; | |
| 162 | readonly handleResumeSession: ( | |
| 163 | handler: ( | |
| 164 | request: AcpSchema.ResumeSessionRequest, | |
| 165 | ) => Effect.Effect<AcpSchema.ResumeSessionResponse, AcpError.AcpError>, | |
| 166 | ) => Effect.Effect<void>; | |
| 167 | readonly handleCloseSession: ( | |
| 168 | handler: ( | |
| 169 | request: AcpSchema.CloseSessionRequest, | |
| 170 | ) => Effect.Effect<AcpSchema.CloseSessionResponse, AcpError.AcpError>, | |
| 171 | ) => Effect.Effect<void>; | |
| 172 | readonly handleSetSessionModel: ( | |
| 173 | handler: ( | |
| 174 | request: AcpSchema.SetSessionModelRequest, | |
| 175 | ) => Effect.Effect<AcpSchema.SetSessionModelResponse, AcpError.AcpError>, | |
| 176 | ) => Effect.Effect<void>; | |
| 177 | readonly handleSetSessionConfigOption: ( | |
| 178 | handler: ( | |
| 179 | request: AcpSchema.SetSessionConfigOptionRequest, | |
| 180 | ) => Effect.Effect<AcpSchema.SetSessionConfigOptionResponse, AcpError.AcpError>, | |
| 181 | ) => Effect.Effect<void>; | |
| 182 | readonly handlePrompt: ( | |
| 183 | handler: ( | |
| 184 | request: AcpSchema.PromptRequest, | |
| 185 | ) => Effect.Effect<AcpSchema.PromptResponse, AcpError.AcpError>, | |
| 186 | ) => Effect.Effect<void>; | |
| 79 | 187 | /** |
| 80 | * Creates a terminal on the client side. | |
| 81 | * @see https://agentclientprotocol.com/protocol/schema#terminal/create | |
| 188 | * Registers a handler for `session/cancel`. | |
| 189 | * @see https://agentclientprotocol.com/protocol/schema#session/cancel | |
| 82 | 190 | */ |
| 83 | readonly createTerminal: ( | |
| 84 | payload: AcpSchema.CreateTerminalRequest, | |
| 85 | ) => Effect.Effect<AcpTerminal.AcpTerminal, AcpError.AcpError>; | |
| 86 | /** | |
| 87 | * Sends a `session/update` notification to the client. | |
| 88 | * @see https://agentclientprotocol.com/protocol/schema#session/update | |
| 89 | */ | |
| 90 | readonly sessionUpdate: ( | |
| 91 | payload: AcpSchema.SessionNotification, | |
| 92 | ) => Effect.Effect<void, AcpError.AcpError>; | |
| 93 | /** | |
| 94 | * Sends a `session/elicitation/complete` notification to the client. | |
| 95 | * @see https://agentclientprotocol.com/protocol/schema#session/elicitation/complete | |
| 96 | */ | |
| 97 | readonly elicitationComplete: ( | |
| 98 | payload: AcpSchema.ElicitationCompleteNotification, | |
| 99 | ) => Effect.Effect<void, AcpError.AcpError>; | |
| 100 | /** | |
| 101 | * Sends an ACP extension request to the client. | |
| 102 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 103 | */ | |
| 104 | readonly extRequest: ( | |
| 191 | readonly handleCancel: ( | |
| 192 | handler: ( | |
| 193 | notification: AcpSchema.CancelNotification, | |
| 194 | ) => Effect.Effect<void, AcpError.AcpError>, | |
| 195 | ) => Effect.Effect<void>; | |
| 196 | readonly handleUnknownExtRequest: ( | |
| 197 | handler: (method: string, params: unknown) => Effect.Effect<unknown, AcpError.AcpError>, | |
| 198 | ) => Effect.Effect<void>; | |
| 199 | readonly handleUnknownExtNotification: ( | |
| 200 | handler: (method: string, params: unknown) => Effect.Effect<void, AcpError.AcpError>, | |
| 201 | ) => Effect.Effect<void>; | |
| 202 | readonly handleExtRequest: <A, I>( | |
| 105 | 203 | method: string, |
| 106 | payload: unknown, | |
| 107 | ) => Effect.Effect<unknown, AcpError.AcpError>; | |
| 108 | /** | |
| 109 | * Sends an ACP extension notification to the client. | |
| 110 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 111 | */ | |
| 112 | readonly extNotification: ( | |
| 204 | payload: Schema.Codec<A, I>, | |
| 205 | handler: (payload: A) => Effect.Effect<unknown, AcpError.AcpError>, | |
| 206 | ) => Effect.Effect<void>; | |
| 207 | readonly handleExtNotification: <A, I>( | |
| 113 | 208 | method: string, |
| 114 | payload: unknown, | |
| 115 | ) => Effect.Effect<void, AcpError.AcpError>; | |
| 116 | }; | |
| 117 | /** | |
| 118 | * Registers a handler for `initialize`. | |
| 119 | * @see https://agentclientprotocol.com/protocol/schema#initialize | |
| 120 | */ | |
| 121 | readonly handleInitialize: ( | |
| 122 | handler: ( | |
| 123 | request: AcpSchema.InitializeRequest, | |
| 124 | ) => Effect.Effect<AcpSchema.InitializeResponse, AcpError.AcpError>, | |
| 125 | ) => Effect.Effect<void>; | |
| 126 | /** | |
| 127 | * Registers a handler for `authenticate`. | |
| 128 | * @see https://agentclientprotocol.com/protocol/schema#authenticate | |
| 129 | */ | |
| 130 | readonly handleAuthenticate: ( | |
| 131 | handler: ( | |
| 132 | request: AcpSchema.AuthenticateRequest, | |
| 133 | ) => Effect.Effect<AcpSchema.AuthenticateResponse, AcpError.AcpError>, | |
| 134 | ) => Effect.Effect<void>; | |
| 135 | readonly handleLogout: ( | |
| 136 | handler: ( | |
| 137 | request: AcpSchema.LogoutRequest, | |
| 138 | ) => Effect.Effect<AcpSchema.LogoutResponse, AcpError.AcpError>, | |
| 139 | ) => Effect.Effect<void>; | |
| 140 | readonly handleCreateSession: ( | |
| 141 | handler: ( | |
| 142 | request: AcpSchema.NewSessionRequest, | |
| 143 | ) => Effect.Effect<AcpSchema.NewSessionResponse, AcpError.AcpError>, | |
| 144 | ) => Effect.Effect<void>; | |
| 145 | readonly handleLoadSession: ( | |
| 146 | handler: ( | |
| 147 | request: AcpSchema.LoadSessionRequest, | |
| 148 | ) => Effect.Effect<AcpSchema.LoadSessionResponse, AcpError.AcpError>, | |
| 149 | ) => Effect.Effect<void>; | |
| 150 | readonly handleListSessions: ( | |
| 151 | handler: ( | |
| 152 | request: AcpSchema.ListSessionsRequest, | |
| 153 | ) => Effect.Effect<AcpSchema.ListSessionsResponse, AcpError.AcpError>, | |
| 154 | ) => Effect.Effect<void>; | |
| 155 | readonly handleForkSession: ( | |
| 156 | handler: ( | |
| 157 | request: AcpSchema.ForkSessionRequest, | |
| 158 | ) => Effect.Effect<AcpSchema.ForkSessionResponse, AcpError.AcpError>, | |
| 159 | ) => Effect.Effect<void>; | |
| 160 | readonly handleResumeSession: ( | |
| 161 | handler: ( | |
| 162 | request: AcpSchema.ResumeSessionRequest, | |
| 163 | ) => Effect.Effect<AcpSchema.ResumeSessionResponse, AcpError.AcpError>, | |
| 164 | ) => Effect.Effect<void>; | |
| 165 | readonly handleCloseSession: ( | |
| 166 | handler: ( | |
| 167 | request: AcpSchema.CloseSessionRequest, | |
| 168 | ) => Effect.Effect<AcpSchema.CloseSessionResponse, AcpError.AcpError>, | |
| 169 | ) => Effect.Effect<void>; | |
| 170 | readonly handleSetSessionModel: ( | |
| 171 | handler: ( | |
| 172 | request: AcpSchema.SetSessionModelRequest, | |
| 173 | ) => Effect.Effect<AcpSchema.SetSessionModelResponse, AcpError.AcpError>, | |
| 174 | ) => Effect.Effect<void>; | |
| 175 | readonly handleSetSessionConfigOption: ( | |
| 176 | handler: ( | |
| 177 | request: AcpSchema.SetSessionConfigOptionRequest, | |
| 178 | ) => Effect.Effect<AcpSchema.SetSessionConfigOptionResponse, AcpError.AcpError>, | |
| 179 | ) => Effect.Effect<void>; | |
| 180 | readonly handlePrompt: ( | |
| 181 | handler: ( | |
| 182 | request: AcpSchema.PromptRequest, | |
| 183 | ) => Effect.Effect<AcpSchema.PromptResponse, AcpError.AcpError>, | |
| 184 | ) => Effect.Effect<void>; | |
| 185 | /** | |
| 186 | * Registers a handler for `session/cancel`. | |
| 187 | * @see https://agentclientprotocol.com/protocol/schema#session/cancel | |
| 188 | */ | |
| 189 | readonly handleCancel: ( | |
| 190 | handler: (notification: AcpSchema.CancelNotification) => Effect.Effect<void, AcpError.AcpError>, | |
| 191 | ) => Effect.Effect<void>; | |
| 192 | readonly handleUnknownExtRequest: ( | |
| 193 | handler: (method: string, params: unknown) => Effect.Effect<unknown, AcpError.AcpError>, | |
| 194 | ) => Effect.Effect<void>; | |
| 195 | readonly handleUnknownExtNotification: ( | |
| 196 | handler: (method: string, params: unknown) => Effect.Effect<void, AcpError.AcpError>, | |
| 197 | ) => Effect.Effect<void>; | |
| 198 | readonly handleExtRequest: <A, I>( | |
| 199 | method: string, | |
| 200 | payload: Schema.Codec<A, I>, | |
| 201 | handler: (payload: A) => Effect.Effect<unknown, AcpError.AcpError>, | |
| 202 | ) => Effect.Effect<void>; | |
| 203 | readonly handleExtNotification: <A, I>( | |
| 204 | method: string, | |
| 205 | payload: Schema.Codec<A, I>, | |
| 206 | handler: (payload: A) => Effect.Effect<void, AcpError.AcpError>, | |
| 207 | ) => Effect.Effect<void>; | |
| 208 | } | |
| 209 | ||
| 210 | export class AcpAgent extends Context.Service<AcpAgent, AcpAgentShape>()( | |
| 211 | "effect-acp/agent/AcpAgent", | |
| 212 | ) {} | |
| 209 | payload: Schema.Codec<A, I>, | |
| 210 | handler: (payload: A) => Effect.Effect<void, AcpError.AcpError>, | |
| 211 | ) => Effect.Effect<void>; | |
| 212 | } | |
| 213 | >()("effect-acp/agent/AcpAgent") {} | |
| 213 | 214 | |
| 214 | 215 | interface AcpCoreAgentRequestHandlers { |
| 215 | 216 | initialize?: ( |
| ... | ... | @@ -255,7 +256,7 @@ const decodeCancelNotification = Schema.decodeUnknownEffect(AcpSchema.CancelNoti |
| 255 | 256 | export const make = Effect.fn("effect-acp/AcpAgent.make")(function* ( |
| 256 | 257 | stdio: Stdio.Stdio, |
| 257 | 258 | options: AcpAgentOptions = {}, |
| 258 | ): Effect.fn.Return<AcpAgentShape, never, Scope.Scope> { | |
| 259 | ): Effect.fn.Return<AcpAgent["Service"], never, Scope.Scope> { | |
| 259 | 260 | const coreHandlers: AcpCoreAgentRequestHandlers = {}; |
| 260 | 261 | const cancelHandlers: Array< |
| 261 | 262 | (notification: AcpSchema.CancelNotification) => Effect.Effect<void, AcpError.AcpError> |
packages/effect-acp/src/client.ts+209-207| ... | ... | @@ -7,7 +7,7 @@ import * as Scope from "effect/Scope"; |
| 7 | 7 | import * as Stream from "effect/Stream"; |
| 8 | 8 | import * as RpcClient from "effect/unstable/rpc/RpcClient"; |
| 9 | 9 | import * as RpcServer from "effect/unstable/rpc/RpcServer"; |
| 10 | import { ChildProcessSpawner } from "effect/unstable/process"; | |
| 10 | import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; | |
| 11 | 11 | |
| 12 | 12 | import * as AcpError from "./errors.ts"; |
| 13 | 13 | import * as AcpProtocol from "./protocol.ts"; |
| ... | ... | @@ -34,237 +34,236 @@ type AcpClientRaw = { |
| 34 | 34 | readonly notify: (method: string, payload: unknown) => Effect.Effect<void, AcpError.AcpError>; |
| 35 | 35 | }; |
| 36 | 36 | |
| 37 | export interface AcpClientShape { | |
| 38 | readonly raw: AcpClientRaw; | |
| 39 | readonly agent: { | |
| 37 | export class AcpClient extends Context.Service< | |
| 38 | AcpClient, | |
| 39 | { | |
| 40 | readonly raw: AcpClientRaw; | |
| 41 | readonly agent: { | |
| 42 | /** | |
| 43 | * Initializes the ACP session and negotiates capabilities. | |
| 44 | * @see https://agentclientprotocol.com/protocol/schema#initialize | |
| 45 | */ | |
| 46 | readonly initialize: ( | |
| 47 | payload: AcpSchema.InitializeRequest, | |
| 48 | ) => Effect.Effect<AcpSchema.InitializeResponse, AcpError.AcpError>; | |
| 49 | /** | |
| 50 | * Performs ACP authentication when the agent requires it. | |
| 51 | * @see https://agentclientprotocol.com/protocol/schema#authenticate | |
| 52 | */ | |
| 53 | readonly authenticate: ( | |
| 54 | payload: AcpSchema.AuthenticateRequest, | |
| 55 | ) => Effect.Effect<AcpSchema.AuthenticateResponse, AcpError.AcpError>; | |
| 56 | /** | |
| 57 | * Logs out the current ACP identity. | |
| 58 | * @see https://agentclientprotocol.com/protocol/schema#logout | |
| 59 | */ | |
| 60 | readonly logout: ( | |
| 61 | payload: AcpSchema.LogoutRequest, | |
| 62 | ) => Effect.Effect<AcpSchema.LogoutResponse, AcpError.AcpError>; | |
| 63 | /** | |
| 64 | * Starts a new ACP session. | |
| 65 | * @see https://agentclientprotocol.com/protocol/schema#session/new | |
| 66 | */ | |
| 67 | readonly createSession: ( | |
| 68 | payload: AcpSchema.NewSessionRequest, | |
| 69 | ) => Effect.Effect<AcpSchema.NewSessionResponse, AcpError.AcpError>; | |
| 70 | /** | |
| 71 | * Loads a previously saved ACP session. | |
| 72 | * @see https://agentclientprotocol.com/protocol/schema#session/load | |
| 73 | */ | |
| 74 | readonly loadSession: ( | |
| 75 | payload: AcpSchema.LoadSessionRequest, | |
| 76 | ) => Effect.Effect<AcpSchema.LoadSessionResponse, AcpError.AcpError>; | |
| 77 | /** | |
| 78 | * Lists available ACP sessions. | |
| 79 | * @see https://agentclientprotocol.com/protocol/schema#session/list | |
| 80 | */ | |
| 81 | readonly listSessions: ( | |
| 82 | payload: AcpSchema.ListSessionsRequest, | |
| 83 | ) => Effect.Effect<AcpSchema.ListSessionsResponse, AcpError.AcpError>; | |
| 84 | /** | |
| 85 | * Forks an ACP session. | |
| 86 | * @see https://agentclientprotocol.com/protocol/schema#session/fork | |
| 87 | */ | |
| 88 | readonly forkSession: ( | |
| 89 | payload: AcpSchema.ForkSessionRequest, | |
| 90 | ) => Effect.Effect<AcpSchema.ForkSessionResponse, AcpError.AcpError>; | |
| 91 | /** | |
| 92 | * Resumes an ACP session. | |
| 93 | * @see https://agentclientprotocol.com/protocol/schema#session/resume | |
| 94 | */ | |
| 95 | readonly resumeSession: ( | |
| 96 | payload: AcpSchema.ResumeSessionRequest, | |
| 97 | ) => Effect.Effect<AcpSchema.ResumeSessionResponse, AcpError.AcpError>; | |
| 98 | /** | |
| 99 | * Closes an ACP session. | |
| 100 | * @see https://agentclientprotocol.com/protocol/schema#session/close | |
| 101 | */ | |
| 102 | readonly closeSession: ( | |
| 103 | payload: AcpSchema.CloseSessionRequest, | |
| 104 | ) => Effect.Effect<AcpSchema.CloseSessionResponse, AcpError.AcpError>; | |
| 105 | /** | |
| 106 | * Selects the active model for a session. | |
| 107 | * @see https://agentclientprotocol.com/protocol/schema#session/set_model | |
| 108 | */ | |
| 109 | readonly setSessionModel: ( | |
| 110 | payload: AcpSchema.SetSessionModelRequest, | |
| 111 | ) => Effect.Effect<AcpSchema.SetSessionModelResponse, AcpError.AcpError>; | |
| 112 | /** | |
| 113 | * Updates a session configuration option. | |
| 114 | * @see https://agentclientprotocol.com/protocol/schema#session/set_config_option | |
| 115 | */ | |
| 116 | readonly setSessionConfigOption: ( | |
| 117 | payload: AcpSchema.SetSessionConfigOptionRequest, | |
| 118 | ) => Effect.Effect<AcpSchema.SetSessionConfigOptionResponse, AcpError.AcpError>; | |
| 119 | /** | |
| 120 | * Sends a prompt turn to the agent. | |
| 121 | * @see https://agentclientprotocol.com/protocol/schema#session/prompt | |
| 122 | */ | |
| 123 | readonly prompt: ( | |
| 124 | payload: AcpSchema.PromptRequest, | |
| 125 | ) => Effect.Effect<AcpSchema.PromptResponse, AcpError.AcpError>; | |
| 126 | /** | |
| 127 | * Sends a real ACP `session/cancel` notification. | |
| 128 | * @see https://agentclientprotocol.com/protocol/schema#session/cancel | |
| 129 | */ | |
| 130 | readonly cancel: ( | |
| 131 | payload: AcpSchema.CancelNotification, | |
| 132 | ) => Effect.Effect<void, AcpError.AcpError>; | |
| 133 | }; | |
| 40 | 134 | /** |
| 41 | * Initializes the ACP session and negotiates capabilities. | |
| 42 | * @see https://agentclientprotocol.com/protocol/schema#initialize | |
| 135 | * Registers a handler for `session/request_permission`. | |
| 136 | * @see https://agentclientprotocol.com/protocol/schema#session/request_permission | |
| 43 | 137 | */ |
| 44 | readonly initialize: ( | |
| 45 | payload: AcpSchema.InitializeRequest, | |
| 46 | ) => Effect.Effect<AcpSchema.InitializeResponse, AcpError.AcpError>; | |
| 138 | readonly handleRequestPermission: ( | |
| 139 | handler: ( | |
| 140 | request: AcpSchema.RequestPermissionRequest, | |
| 141 | ) => Effect.Effect<AcpSchema.RequestPermissionResponse, AcpError.AcpError>, | |
| 142 | ) => Effect.Effect<void>; | |
| 47 | 143 | /** |
| 48 | * Performs ACP authentication when the agent requires it. | |
| 49 | * @see https://agentclientprotocol.com/protocol/schema#authenticate | |
| 144 | * Registers a handler for `session/elicitation`. | |
| 145 | * @see https://agentclientprotocol.com/protocol/schema#session/elicitation | |
| 50 | 146 | */ |
| 51 | readonly authenticate: ( | |
| 52 | payload: AcpSchema.AuthenticateRequest, | |
| 53 | ) => Effect.Effect<AcpSchema.AuthenticateResponse, AcpError.AcpError>; | |
| 147 | readonly handleElicitation: ( | |
| 148 | handler: ( | |
| 149 | request: AcpSchema.ElicitationRequest, | |
| 150 | ) => Effect.Effect<AcpSchema.ElicitationResponse, AcpError.AcpError>, | |
| 151 | ) => Effect.Effect<void>; | |
| 54 | 152 | /** |
| 55 | * Logs out the current ACP identity. | |
| 56 | * @see https://agentclientprotocol.com/protocol/schema#logout | |
| 153 | * Registers a handler for `fs/read_text_file`. | |
| 154 | * @see https://agentclientprotocol.com/protocol/schema#fs/read_text_file | |
| 57 | 155 | */ |
| 58 | readonly logout: ( | |
| 59 | payload: AcpSchema.LogoutRequest, | |
| 60 | ) => Effect.Effect<AcpSchema.LogoutResponse, AcpError.AcpError>; | |
| 156 | readonly handleReadTextFile: ( | |
| 157 | handler: ( | |
| 158 | request: AcpSchema.ReadTextFileRequest, | |
| 159 | ) => Effect.Effect<AcpSchema.ReadTextFileResponse, AcpError.AcpError>, | |
| 160 | ) => Effect.Effect<void>; | |
| 61 | 161 | /** |
| 62 | * Starts a new ACP session. | |
| 63 | * @see https://agentclientprotocol.com/protocol/schema#session/new | |
| 162 | * Registers a handler for `fs/write_text_file`. | |
| 163 | * @see https://agentclientprotocol.com/protocol/schema#fs/write_text_file | |
| 64 | 164 | */ |
| 65 | readonly createSession: ( | |
| 66 | payload: AcpSchema.NewSessionRequest, | |
| 67 | ) => Effect.Effect<AcpSchema.NewSessionResponse, AcpError.AcpError>; | |
| 165 | readonly handleWriteTextFile: ( | |
| 166 | handler: ( | |
| 167 | request: AcpSchema.WriteTextFileRequest, | |
| 168 | ) => Effect.Effect<AcpSchema.WriteTextFileResponse | void, AcpError.AcpError>, | |
| 169 | ) => Effect.Effect<void>; | |
| 68 | 170 | /** |
| 69 | * Loads a previously saved ACP session. | |
| 70 | * @see https://agentclientprotocol.com/protocol/schema#session/load | |
| 171 | * Registers a handler for `terminal/create`. | |
| 172 | * @see https://agentclientprotocol.com/protocol/schema#terminal/create | |
| 71 | 173 | */ |
| 72 | readonly loadSession: ( | |
| 73 | payload: AcpSchema.LoadSessionRequest, | |
| 74 | ) => Effect.Effect<AcpSchema.LoadSessionResponse, AcpError.AcpError>; | |
| 174 | readonly handleCreateTerminal: ( | |
| 175 | handler: ( | |
| 176 | request: AcpSchema.CreateTerminalRequest, | |
| 177 | ) => Effect.Effect<AcpSchema.CreateTerminalResponse, AcpError.AcpError>, | |
| 178 | ) => Effect.Effect<void>; | |
| 75 | 179 | /** |
| 76 | * Lists available ACP sessions. | |
| 77 | * @see https://agentclientprotocol.com/protocol/schema#session/list | |
| 180 | * Registers a handler for `terminal/output`. | |
| 181 | * @see https://agentclientprotocol.com/protocol/schema#terminal/output | |
| 78 | 182 | */ |
| 79 | readonly listSessions: ( | |
| 80 | payload: AcpSchema.ListSessionsRequest, | |
| 81 | ) => Effect.Effect<AcpSchema.ListSessionsResponse, AcpError.AcpError>; | |
| 183 | readonly handleTerminalOutput: ( | |
| 184 | handler: ( | |
| 185 | request: AcpSchema.TerminalOutputRequest, | |
| 186 | ) => Effect.Effect<AcpSchema.TerminalOutputResponse, AcpError.AcpError>, | |
| 187 | ) => Effect.Effect<void>; | |
| 82 | 188 | /** |
| 83 | * Forks an ACP session. | |
| 84 | * @see https://agentclientprotocol.com/protocol/schema#session/fork | |
| 189 | * Registers a handler for `terminal/wait_for_exit`. | |
| 190 | * @see https://agentclientprotocol.com/protocol/schema#terminal/wait_for_exit | |
| 85 | 191 | */ |
| 86 | readonly forkSession: ( | |
| 87 | payload: AcpSchema.ForkSessionRequest, | |
| 88 | ) => Effect.Effect<AcpSchema.ForkSessionResponse, AcpError.AcpError>; | |
| 192 | readonly handleTerminalWaitForExit: ( | |
| 193 | handler: ( | |
| 194 | request: AcpSchema.WaitForTerminalExitRequest, | |
| 195 | ) => Effect.Effect<AcpSchema.WaitForTerminalExitResponse, AcpError.AcpError>, | |
| 196 | ) => Effect.Effect<void>; | |
| 89 | 197 | /** |
| 90 | * Resumes an ACP session. | |
| 91 | * @see https://agentclientprotocol.com/protocol/schema#session/resume | |
| 198 | * Registers a handler for `terminal/kill`. | |
| 199 | * @see https://agentclientprotocol.com/protocol/schema#terminal/kill | |
| 92 | 200 | */ |
| 93 | readonly resumeSession: ( | |
| 94 | payload: AcpSchema.ResumeSessionRequest, | |
| 95 | ) => Effect.Effect<AcpSchema.ResumeSessionResponse, AcpError.AcpError>; | |
| 201 | readonly handleTerminalKill: ( | |
| 202 | handler: ( | |
| 203 | request: AcpSchema.KillTerminalRequest, | |
| 204 | ) => Effect.Effect<AcpSchema.KillTerminalResponse | void, AcpError.AcpError>, | |
| 205 | ) => Effect.Effect<void>; | |
| 96 | 206 | /** |
| 97 | * Closes an ACP session. | |
| 98 | * @see https://agentclientprotocol.com/protocol/schema#session/close | |
| 207 | * Registers a handler for `terminal/release`. | |
| 208 | * @see https://agentclientprotocol.com/protocol/schema#terminal/release | |
| 99 | 209 | */ |
| 100 | readonly closeSession: ( | |
| 101 | payload: AcpSchema.CloseSessionRequest, | |
| 102 | ) => Effect.Effect<AcpSchema.CloseSessionResponse, AcpError.AcpError>; | |
| 210 | readonly handleTerminalRelease: ( | |
| 211 | handler: ( | |
| 212 | request: AcpSchema.ReleaseTerminalRequest, | |
| 213 | ) => Effect.Effect<AcpSchema.ReleaseTerminalResponse | void, AcpError.AcpError>, | |
| 214 | ) => Effect.Effect<void>; | |
| 103 | 215 | /** |
| 104 | * Selects the active model for a session. | |
| 105 | * @see https://agentclientprotocol.com/protocol/schema#session/set_model | |
| 216 | * Registers a handler for `session/update`. | |
| 217 | * @see https://agentclientprotocol.com/protocol/schema#session/update | |
| 106 | 218 | */ |
| 107 | readonly setSessionModel: ( | |
| 108 | payload: AcpSchema.SetSessionModelRequest, | |
| 109 | ) => Effect.Effect<AcpSchema.SetSessionModelResponse, AcpError.AcpError>; | |
| 219 | readonly handleSessionUpdate: ( | |
| 220 | handler: ( | |
| 221 | notification: AcpSchema.SessionNotification, | |
| 222 | ) => Effect.Effect<void, AcpError.AcpError>, | |
| 223 | ) => Effect.Effect<void>; | |
| 110 | 224 | /** |
| 111 | * Updates a session configuration option. | |
| 112 | * @see https://agentclientprotocol.com/protocol/schema#session/set_config_option | |
| 225 | * Registers a handler for `session/elicitation/complete`. | |
| 226 | * @see https://agentclientprotocol.com/protocol/schema#session/elicitation/complete | |
| 113 | 227 | */ |
| 114 | readonly setSessionConfigOption: ( | |
| 115 | payload: AcpSchema.SetSessionConfigOptionRequest, | |
| 116 | ) => Effect.Effect<AcpSchema.SetSessionConfigOptionResponse, AcpError.AcpError>; | |
| 228 | readonly handleElicitationComplete: ( | |
| 229 | handler: ( | |
| 230 | notification: AcpSchema.ElicitationCompleteNotification, | |
| 231 | ) => Effect.Effect<void, AcpError.AcpError>, | |
| 232 | ) => Effect.Effect<void>; | |
| 117 | 233 | /** |
| 118 | * Sends a prompt turn to the agent. | |
| 119 | * @see https://agentclientprotocol.com/protocol/schema#session/prompt | |
| 234 | * Registers a fallback extension request handler. | |
| 235 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 120 | 236 | */ |
| 121 | readonly prompt: ( | |
| 122 | payload: AcpSchema.PromptRequest, | |
| 123 | ) => Effect.Effect<AcpSchema.PromptResponse, AcpError.AcpError>; | |
| 237 | readonly handleUnknownExtRequest: ( | |
| 238 | handler: (method: string, params: unknown) => Effect.Effect<unknown, AcpError.AcpError>, | |
| 239 | ) => Effect.Effect<void>; | |
| 124 | 240 | /** |
| 125 | * Sends a real ACP `session/cancel` notification. | |
| 126 | * @see https://agentclientprotocol.com/protocol/schema#session/cancel | |
| 241 | * Registers a fallback extension notification handler. | |
| 242 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 127 | 243 | */ |
| 128 | readonly cancel: ( | |
| 129 | payload: AcpSchema.CancelNotification, | |
| 130 | ) => Effect.Effect<void, AcpError.AcpError>; | |
| 131 | }; | |
| 132 | /** | |
| 133 | * Registers a handler for `session/request_permission`. | |
| 134 | * @see https://agentclientprotocol.com/protocol/schema#session/request_permission | |
| 135 | */ | |
| 136 | readonly handleRequestPermission: ( | |
| 137 | handler: ( | |
| 138 | request: AcpSchema.RequestPermissionRequest, | |
| 139 | ) => Effect.Effect<AcpSchema.RequestPermissionResponse, AcpError.AcpError>, | |
| 140 | ) => Effect.Effect<void>; | |
| 141 | /** | |
| 142 | * Registers a handler for `session/elicitation`. | |
| 143 | * @see https://agentclientprotocol.com/protocol/schema#session/elicitation | |
| 144 | */ | |
| 145 | readonly handleElicitation: ( | |
| 146 | handler: ( | |
| 147 | request: AcpSchema.ElicitationRequest, | |
| 148 | ) => Effect.Effect<AcpSchema.ElicitationResponse, AcpError.AcpError>, | |
| 149 | ) => Effect.Effect<void>; | |
| 150 | /** | |
| 151 | * Registers a handler for `fs/read_text_file`. | |
| 152 | * @see https://agentclientprotocol.com/protocol/schema#fs/read_text_file | |
| 153 | */ | |
| 154 | readonly handleReadTextFile: ( | |
| 155 | handler: ( | |
| 156 | request: AcpSchema.ReadTextFileRequest, | |
| 157 | ) => Effect.Effect<AcpSchema.ReadTextFileResponse, AcpError.AcpError>, | |
| 158 | ) => Effect.Effect<void>; | |
| 159 | /** | |
| 160 | * Registers a handler for `fs/write_text_file`. | |
| 161 | * @see https://agentclientprotocol.com/protocol/schema#fs/write_text_file | |
| 162 | */ | |
| 163 | readonly handleWriteTextFile: ( | |
| 164 | handler: ( | |
| 165 | request: AcpSchema.WriteTextFileRequest, | |
| 166 | ) => Effect.Effect<AcpSchema.WriteTextFileResponse | void, AcpError.AcpError>, | |
| 167 | ) => Effect.Effect<void>; | |
| 168 | /** | |
| 169 | * Registers a handler for `terminal/create`. | |
| 170 | * @see https://agentclientprotocol.com/protocol/schema#terminal/create | |
| 171 | */ | |
| 172 | readonly handleCreateTerminal: ( | |
| 173 | handler: ( | |
| 174 | request: AcpSchema.CreateTerminalRequest, | |
| 175 | ) => Effect.Effect<AcpSchema.CreateTerminalResponse, AcpError.AcpError>, | |
| 176 | ) => Effect.Effect<void>; | |
| 177 | /** | |
| 178 | * Registers a handler for `terminal/output`. | |
| 179 | * @see https://agentclientprotocol.com/protocol/schema#terminal/output | |
| 180 | */ | |
| 181 | readonly handleTerminalOutput: ( | |
| 182 | handler: ( | |
| 183 | request: AcpSchema.TerminalOutputRequest, | |
| 184 | ) => Effect.Effect<AcpSchema.TerminalOutputResponse, AcpError.AcpError>, | |
| 185 | ) => Effect.Effect<void>; | |
| 186 | /** | |
| 187 | * Registers a handler for `terminal/wait_for_exit`. | |
| 188 | * @see https://agentclientprotocol.com/protocol/schema#terminal/wait_for_exit | |
| 189 | */ | |
| 190 | readonly handleTerminalWaitForExit: ( | |
| 191 | handler: ( | |
| 192 | request: AcpSchema.WaitForTerminalExitRequest, | |
| 193 | ) => Effect.Effect<AcpSchema.WaitForTerminalExitResponse, AcpError.AcpError>, | |
| 194 | ) => Effect.Effect<void>; | |
| 195 | /** | |
| 196 | * Registers a handler for `terminal/kill`. | |
| 197 | * @see https://agentclientprotocol.com/protocol/schema#terminal/kill | |
| 198 | */ | |
| 199 | readonly handleTerminalKill: ( | |
| 200 | handler: ( | |
| 201 | request: AcpSchema.KillTerminalRequest, | |
| 202 | ) => Effect.Effect<AcpSchema.KillTerminalResponse | void, AcpError.AcpError>, | |
| 203 | ) => Effect.Effect<void>; | |
| 204 | /** | |
| 205 | * Registers a handler for `terminal/release`. | |
| 206 | * @see https://agentclientprotocol.com/protocol/schema#terminal/release | |
| 207 | */ | |
| 208 | readonly handleTerminalRelease: ( | |
| 209 | handler: ( | |
| 210 | request: AcpSchema.ReleaseTerminalRequest, | |
| 211 | ) => Effect.Effect<AcpSchema.ReleaseTerminalResponse | void, AcpError.AcpError>, | |
| 212 | ) => Effect.Effect<void>; | |
| 213 | /** | |
| 214 | * Registers a handler for `session/update`. | |
| 215 | * @see https://agentclientprotocol.com/protocol/schema#session/update | |
| 216 | */ | |
| 217 | readonly handleSessionUpdate: ( | |
| 218 | handler: ( | |
| 219 | notification: AcpSchema.SessionNotification, | |
| 220 | ) => Effect.Effect<void, AcpError.AcpError>, | |
| 221 | ) => Effect.Effect<void>; | |
| 222 | /** | |
| 223 | * Registers a handler for `session/elicitation/complete`. | |
| 224 | * @see https://agentclientprotocol.com/protocol/schema#session/elicitation/complete | |
| 225 | */ | |
| 226 | readonly handleElicitationComplete: ( | |
| 227 | handler: ( | |
| 228 | notification: AcpSchema.ElicitationCompleteNotification, | |
| 229 | ) => Effect.Effect<void, AcpError.AcpError>, | |
| 230 | ) => Effect.Effect<void>; | |
| 231 | /** | |
| 232 | * Registers a fallback extension request handler. | |
| 233 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 234 | */ | |
| 235 | readonly handleUnknownExtRequest: ( | |
| 236 | handler: (method: string, params: unknown) => Effect.Effect<unknown, AcpError.AcpError>, | |
| 237 | ) => Effect.Effect<void>; | |
| 238 | /** | |
| 239 | * Registers a fallback extension notification handler. | |
| 240 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 241 | */ | |
| 242 | readonly handleUnknownExtNotification: ( | |
| 243 | handler: (method: string, params: unknown) => Effect.Effect<void, AcpError.AcpError>, | |
| 244 | ) => Effect.Effect<void>; | |
| 245 | /** | |
| 246 | * Registers a typed extension request handler. | |
| 247 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 248 | */ | |
| 249 | readonly handleExtRequest: <A, I>( | |
| 250 | method: string, | |
| 251 | payload: Schema.Codec<A, I>, | |
| 252 | handler: (payload: A) => Effect.Effect<unknown, AcpError.AcpError>, | |
| 253 | ) => Effect.Effect<void>; | |
| 254 | /** | |
| 255 | * Registers a typed extension notification handler. | |
| 256 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 257 | */ | |
| 258 | readonly handleExtNotification: <A, I>( | |
| 259 | method: string, | |
| 260 | payload: Schema.Codec<A, I>, | |
| 261 | handler: (payload: A) => Effect.Effect<void, AcpError.AcpError>, | |
| 262 | ) => Effect.Effect<void>; | |
| 263 | } | |
| 264 | ||
| 265 | export class AcpClient extends Context.Service<AcpClient, AcpClientShape>()( | |
| 266 | "effect-acp/client/AcpClient", | |
| 267 | ) {} | |
| 244 | readonly handleUnknownExtNotification: ( | |
| 245 | handler: (method: string, params: unknown) => Effect.Effect<void, AcpError.AcpError>, | |
| 246 | ) => Effect.Effect<void>; | |
| 247 | /** | |
| 248 | * Registers a typed extension request handler. | |
| 249 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 250 | */ | |
| 251 | readonly handleExtRequest: <A, I>( | |
| 252 | method: string, | |
| 253 | payload: Schema.Codec<A, I>, | |
| 254 | handler: (payload: A) => Effect.Effect<unknown, AcpError.AcpError>, | |
| 255 | ) => Effect.Effect<void>; | |
| 256 | /** | |
| 257 | * Registers a typed extension notification handler. | |
| 258 | * @see https://agentclientprotocol.com/protocol/extensibility | |
| 259 | */ | |
| 260 | readonly handleExtNotification: <A, I>( | |
| 261 | method: string, | |
| 262 | payload: Schema.Codec<A, I>, | |
| 263 | handler: (payload: A) => Effect.Effect<void, AcpError.AcpError>, | |
| 264 | ) => Effect.Effect<void>; | |
| 265 | } | |
| 266 | >()("effect-acp/client/AcpClient") {} | |
| 268 | 267 | |
| 269 | 268 | interface AcpCoreRequestHandlers { |
| 270 | 269 | requestPermission?: ( |
| ... | ... | @@ -310,7 +309,7 @@ export const make = Effect.fn("effect-acp/AcpClient.make")(function* ( |
| 310 | 309 | stdio: Stdio.Stdio, |
| 311 | 310 | options: AcpClientOptions = {}, |
| 312 | 311 | terminationError?: Effect.Effect<AcpError.AcpError>, |
| 313 | ): Effect.fn.Return<AcpClientShape, never, Scope.Scope> { | |
| 312 | ): Effect.fn.Return<AcpClient["Service"], never, Scope.Scope> { | |
| 314 | 313 | const coreHandlers: AcpCoreRequestHandlers = {}; |
| 315 | 314 | const notificationHandlers: AcpNotificationHandlers = { |
| 316 | 315 | sessionUpdate: { handlers: [], pending: [] }, |
| ... | ... | @@ -559,6 +558,9 @@ export const make = Effect.fn("effect-acp/AcpClient.make")(function* ( |
| 559 | 558 | }); |
| 560 | 559 | }); |
| 561 | 560 | |
| 561 | export const layer = (stdio: Stdio.Stdio, options: AcpClientOptions = {}): Layer.Layer<AcpClient> => | |
| 562 | Layer.effect(AcpClient, make(stdio, options)); | |
| 563 | ||
| 562 | 564 | export const layerChildProcess = ( |
| 563 | 565 | handle: ChildProcessSpawner.ChildProcessHandle, |
| 564 | 566 | options: AcpClientOptions = {}, |
packages/effect-acp/src/errors.ts+5-1| ... | ... | @@ -45,7 +45,11 @@ export class AcpTransportError extends Schema.TaggedErrorClass<AcpTransportError |
| 45 | 45 | detail: Schema.String, |
| 46 | 46 | cause: Schema.Defect(), |
| 47 | 47 | }, |
| 48 | ) {} | |
| 48 | ) { | |
| 49 | override get message() { | |
| 50 | return this.detail; | |
| 51 | } | |
| 52 | } | |
| 49 | 53 | |
| 50 | 54 | export class AcpRequestError extends Schema.TaggedErrorClass<AcpRequestError>()("AcpRequestError", { |
| 51 | 55 | code: AcpSchema.ErrorCode, |
packages/effect-codex-app-server/src/client.ts+45-39| ... | ... | @@ -5,7 +5,7 @@ import * as Schema from "effect/Schema"; |
| 5 | 5 | import * as Scope from "effect/Scope"; |
| 6 | 6 | import * as Stdio from "effect/Stdio"; |
| 7 | 7 | import * as Stream from "effect/Stream"; |
| 8 | import { ChildProcessSpawner } from "effect/unstable/process"; | |
| 8 | import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; | |
| 9 | 9 | |
| 10 | 10 | import * as CodexRpc from "./_generated/meta.gen.ts"; |
| 11 | 11 | import * as CodexError from "./errors.ts"; |
| ... | ... | @@ -35,45 +35,46 @@ interface CodexAppServerClientRaw { |
| 35 | 35 | readonly respondError: CodexProtocol.CodexAppServerPatchedProtocol["respondError"]; |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | export interface CodexAppServerClientShape { | |
| 39 | readonly raw: CodexAppServerClientRaw; | |
| 40 | readonly request: <M extends CodexRpc.ClientRequestMethod>( | |
| 41 | method: M, | |
| 42 | payload: CodexRpc.ClientRequestParamsByMethod[M], | |
| 43 | ) => Effect.Effect<CodexRpc.ClientRequestResponsesByMethod[M], CodexError.CodexAppServerError>; | |
| 44 | readonly notify: <M extends CodexRpc.ClientNotificationMethod>( | |
| 45 | method: M, | |
| 46 | payload: CodexRpc.ClientNotificationParamsByMethod[M], | |
| 47 | ) => Effect.Effect<void, CodexError.CodexAppServerError>; | |
| 48 | readonly handleServerRequest: <M extends CodexRpc.ServerRequestMethod>( | |
| 49 | method: M, | |
| 50 | handler: ( | |
| 51 | payload: CodexRpc.ServerRequestParamsByMethod[M], | |
| 52 | ) => Effect.Effect<CodexRpc.ServerRequestResponsesByMethod[M], CodexError.CodexAppServerError>, | |
| 53 | ) => Effect.Effect<void>; | |
| 54 | readonly handleServerNotification: <M extends CodexRpc.ServerNotificationMethod>( | |
| 55 | method: M, | |
| 56 | handler: ( | |
| 57 | payload: CodexRpc.ServerNotificationParamsByMethod[M], | |
| 58 | ) => Effect.Effect<void, CodexError.CodexAppServerError>, | |
| 59 | ) => Effect.Effect<void>; | |
| 60 | readonly handleUnknownServerRequest: ( | |
| 61 | handler: ( | |
| 62 | method: string, | |
| 63 | params: unknown, | |
| 64 | ) => Effect.Effect<unknown, CodexError.CodexAppServerError>, | |
| 65 | ) => Effect.Effect<void>; | |
| 66 | readonly handleUnknownServerNotification: ( | |
| 67 | handler: ( | |
| 68 | method: string, | |
| 69 | params: unknown, | |
| 70 | ) => Effect.Effect<void, CodexError.CodexAppServerError>, | |
| 71 | ) => Effect.Effect<void>; | |
| 72 | } | |
| 73 | ||
| 74 | 38 | export class CodexAppServerClient extends Context.Service< |
| 75 | 39 | CodexAppServerClient, |
| 76 | CodexAppServerClientShape | |
| 40 | { | |
| 41 | readonly raw: CodexAppServerClientRaw; | |
| 42 | readonly request: <M extends CodexRpc.ClientRequestMethod>( | |
| 43 | method: M, | |
| 44 | payload: CodexRpc.ClientRequestParamsByMethod[M], | |
| 45 | ) => Effect.Effect<CodexRpc.ClientRequestResponsesByMethod[M], CodexError.CodexAppServerError>; | |
| 46 | readonly notify: <M extends CodexRpc.ClientNotificationMethod>( | |
| 47 | method: M, | |
| 48 | payload: CodexRpc.ClientNotificationParamsByMethod[M], | |
| 49 | ) => Effect.Effect<void, CodexError.CodexAppServerError>; | |
| 50 | readonly handleServerRequest: <M extends CodexRpc.ServerRequestMethod>( | |
| 51 | method: M, | |
| 52 | handler: ( | |
| 53 | payload: CodexRpc.ServerRequestParamsByMethod[M], | |
| 54 | ) => Effect.Effect< | |
| 55 | CodexRpc.ServerRequestResponsesByMethod[M], | |
| 56 | CodexError.CodexAppServerError | |
| 57 | >, | |
| 58 | ) => Effect.Effect<void>; | |
| 59 | readonly handleServerNotification: <M extends CodexRpc.ServerNotificationMethod>( | |
| 60 | method: M, | |
| 61 | handler: ( | |
| 62 | payload: CodexRpc.ServerNotificationParamsByMethod[M], | |
| 63 | ) => Effect.Effect<void, CodexError.CodexAppServerError>, | |
| 64 | ) => Effect.Effect<void>; | |
| 65 | readonly handleUnknownServerRequest: ( | |
| 66 | handler: ( | |
| 67 | method: string, | |
| 68 | params: unknown, | |
| 69 | ) => Effect.Effect<unknown, CodexError.CodexAppServerError>, | |
| 70 | ) => Effect.Effect<void>; | |
| 71 | readonly handleUnknownServerNotification: ( | |
| 72 | handler: ( | |
| 73 | method: string, | |
| 74 | params: unknown, | |
| 75 | ) => Effect.Effect<void, CodexError.CodexAppServerError>, | |
| 76 | ) => Effect.Effect<void>; | |
| 77 | } | |
| 77 | 78 | >()("effect-codex-app-server/client/CodexAppServerClient") {} |
| 78 | 79 | |
| 79 | 80 | type ServerRequestHandler = ( |
| ... | ... | @@ -87,7 +88,7 @@ export const make = Effect.fn("effect-codex-app-server/CodexAppServerClient.make |
| 87 | 88 | stdio: Stdio.Stdio, |
| 88 | 89 | options: CodexAppServerClientOptions = {}, |
| 89 | 90 | terminationError?: Effect.Effect<CodexError.CodexAppServerError>, |
| 90 | ): Effect.fn.Return<CodexAppServerClientShape, never, Scope.Scope> { | |
| 91 | ): Effect.fn.Return<CodexAppServerClient["Service"], never, Scope.Scope> { | |
| 91 | 92 | const requestHandlers = new Map<string, ServerRequestHandler>(); |
| 92 | 93 | const notificationHandlers = new Map<string, Array<ServerNotificationHandler>>(); |
| 93 | 94 | let unknownRequestHandler: |
| ... | ... | @@ -249,6 +250,11 @@ export const make = Effect.fn("effect-codex-app-server/CodexAppServerClient.make |
| 249 | 250 | }); |
| 250 | 251 | }); |
| 251 | 252 | |
| 253 | export const layer = ( | |
| 254 | stdio: Stdio.Stdio, | |
| 255 | options: CodexAppServerClientOptions = {}, | |
| 256 | ): Layer.Layer<CodexAppServerClient> => Layer.effect(CodexAppServerClient, make(stdio, options)); | |
| 257 | ||
| 252 | 258 | export const layerChildProcess = ( |
| 253 | 259 | handle: ChildProcessSpawner.ChildProcessHandle, |
| 254 | 260 | options: CodexAppServerClientOptions = {}, |