From 664bd5e524bb58b23ecab0f2e413fc2ecb4caf55 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 8 Oct 2026 18:30:58 -0700 Subject: [PATCH] refactor(provider-acp): move the shared ACP adapter into its own package (#17354) Co-authored-by: Claude Opus 5.5 --- apps/server/package.json | 1 + .../scripts/record-grok-acp-replay-fixture.ts | 13 +- apps/server/src/mcp/AcpMcpStdioBridge.ts | 57 +-- .../Adapters/AcpAdapterV2.test.ts | 351 +++++++++--------- .../Adapters/AcpAdapterV2.testkit.ts | 4 +- .../Adapters/AcpRegistryAdapterV2.test.ts | 27 +- .../Adapters/AcpRegistryAdapterV2.testkit.ts | 15 +- .../Adapters/AcpRegistryAdapterV2.ts | 18 +- .../Adapters/AntigravityAdapterV2.test.ts | 25 +- .../Adapters/AntigravityAdapterV2.ts | 16 +- .../src/orchestration-v2/Adapters/DevinAcp.ts | 4 +- .../Adapters/GrokAdapterV2.test.ts | 15 +- .../Adapters/GrokAdapterV2.testkit.ts | 15 +- .../Adapters/GrokAdapterV2.ts | 26 +- .../ProviderSelectionTransition.test.ts | 2 +- .../ProviderSwitch.integration.test.ts | 2 +- .../src/provider/AntigravityAuth.test.ts | 4 +- apps/server/src/provider/AntigravityAuth.ts | 8 +- .../src/provider/AntigravityProvider.test.ts | 4 +- .../src/provider/AntigravityProvider.ts | 6 +- .../src/provider/Drivers/AcpRegistryDriver.ts | 8 +- .../src/provider/Drivers/AntigravityDriver.ts | 20 +- apps/server/src/provider/GrokProvider.ts | 2 +- .../src/provider/ProviderAuthService.test.ts | 2 +- apps/server/src/provider/ProviderHostLive.ts | 1 + .../provider/acp/AcpJsonRpcConnection.test.ts | 2 +- .../src/provider/acp/AcpRegistryAuth.test.ts | 4 +- .../src/provider/acp/AcpRegistryAuth.ts | 2 +- .../src/provider/acp/AcpRegistryProbe.test.ts | 12 +- .../src/provider/acp/AcpRegistryProbe.ts | 6 +- .../src/provider/acp/AcpRegistrySupport.ts | 4 +- .../acp/AcpSessionRuntime.processTree.test.ts | 257 ++++++------- .../src/provider/acp/AntigravityAcpSupport.ts | 2 +- .../provider/acp/AntigravityProtocol.test.ts | 5 +- .../src/provider/acp/AntigravityProtocol.ts | 2 +- .../server/src/provider/acp/GrokAcpSupport.ts | 2 +- .../src/provider/acp/XAiAcpExtension.test.ts | 4 +- .../src/provider/acp/XAiAcpExtension.ts | 4 +- .../src/provider/antigravityAuthSupport.ts | 4 +- .../AntigravityTextGeneration.test.ts | 4 +- .../AntigravityTextGeneration.ts | 4 +- docs/internals/adding-a-provider.md | 2 +- package.json | 2 +- packages/provider-acp/package.json | 65 ++++ .../src/server}/AcpSessionRuntime.ts | 6 +- .../provider-acp/src/server/adapter.ts | 30 +- .../src/server/clientPolicy.test.ts | 2 +- .../provider-acp/src/server/clientPolicy.ts | 0 .../src/server/clientTerminals.test.ts | 2 +- .../src/server/clientTerminals.ts | 0 .../src/server/coreRuntimeEvents.test.ts | 2 +- .../src/server/coreRuntimeEvents.ts | 2 +- .../src/server/mcpOverAcpBridge.test.ts | 2 +- .../src/server/mcpOverAcpBridge.ts | 4 +- .../src/server/nativeLogging.test.ts | 6 +- .../provider-acp/src/server/nativeLogging.ts | 4 +- .../src/server/runtimeModel.test.ts | 2 +- .../provider-acp/src/server/runtimeModel.ts | 0 .../src/server/sessionConfig.test.ts | 2 +- .../provider-acp/src/server/sessionConfig.ts | 2 +- .../provider-acp/src/server/stderr.test.ts | 2 +- .../provider-acp/src/server/stderr.ts | 0 packages/provider-acp/tsconfig.json | 7 + .../provider-core/src/server/ProviderHost.ts | 2 + .../src/server/managedProvider.test.ts | 1 + packages/provider-testing/src/host.ts | 8 +- packages/shared/package.json | 4 + packages/shared/src/mcpResponsePayloads.ts | 65 ++++ pnpm-lock.yaml | 37 ++ scripts/release-smoke.ts | 1 + 70 files changed, 673 insertions(+), 553 deletions(-) create mode 100644 packages/provider-acp/package.json rename {apps/server/src/provider/acp => packages/provider-acp/src/server}/AcpSessionRuntime.ts (99%) rename apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.ts => packages/provider-acp/src/server/adapter.ts (99%) rename apps/server/src/provider/acp/AcpClientPolicy.test.ts => packages/provider-acp/src/server/clientPolicy.test.ts (99%) rename apps/server/src/provider/acp/AcpClientPolicy.ts => packages/provider-acp/src/server/clientPolicy.ts (100%) rename apps/server/src/provider/acp/AcpClientTerminals.test.ts => packages/provider-acp/src/server/clientTerminals.test.ts (99%) rename apps/server/src/provider/acp/AcpClientTerminals.ts => packages/provider-acp/src/server/clientTerminals.ts (100%) rename apps/server/src/provider/acp/AcpCoreRuntimeEvents.test.ts => packages/provider-acp/src/server/coreRuntimeEvents.test.ts (99%) rename apps/server/src/provider/acp/AcpCoreRuntimeEvents.ts => packages/provider-acp/src/server/coreRuntimeEvents.ts (99%) rename apps/server/src/mcp/AcpMcpOverAcpBridge.test.ts => packages/provider-acp/src/server/mcpOverAcpBridge.test.ts (98%) rename apps/server/src/mcp/AcpMcpOverAcpBridge.ts => packages/provider-acp/src/server/mcpOverAcpBridge.ts (98%) rename apps/server/src/provider/acp/AcpNativeLogging.test.ts => packages/provider-acp/src/server/nativeLogging.test.ts (97%) rename apps/server/src/provider/acp/AcpNativeLogging.ts => packages/provider-acp/src/server/nativeLogging.ts (97%) rename apps/server/src/provider/acp/AcpRuntimeModel.test.ts => packages/provider-acp/src/server/runtimeModel.test.ts (99%) rename apps/server/src/provider/acp/AcpRuntimeModel.ts => packages/provider-acp/src/server/runtimeModel.ts (100%) rename apps/server/src/provider/acp/AcpSessionConfig.test.ts => packages/provider-acp/src/server/sessionConfig.test.ts (99%) rename apps/server/src/provider/acp/AcpSessionConfig.ts => packages/provider-acp/src/server/sessionConfig.ts (98%) rename apps/server/src/provider/acp/AcpStderr.test.ts => packages/provider-acp/src/server/stderr.test.ts (98%) rename apps/server/src/provider/acp/AcpStderr.ts => packages/provider-acp/src/server/stderr.ts (100%) create mode 100644 packages/provider-acp/tsconfig.json create mode 100644 packages/shared/src/mcpResponsePayloads.ts diff --git a/apps/server/package.json b/apps/server/package.json index de20a01de3b9ce3f30514cded1e4902c132fdd0a..5e731012c583a1be73dc1d890d53368580f7d8bd 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -38,6 +38,7 @@ "@napi-rs/keyring": "^1.3.0", "@noble/hashes": "catalog:", "@opencode-ai/sdk": "^1.3.15", + "@t3tools/provider-acp": "workspace:*", "@t3tools/provider-core": "workspace:*", "@t3tools/provider-cursor": "workspace:*", "@t3tools/provider-muse": "workspace:*", diff --git a/apps/server/scripts/record-grok-acp-replay-fixture.ts b/apps/server/scripts/record-grok-acp-replay-fixture.ts index 23d687eb91309e98a9efab764f43173465ff2f98..30db5e0ef85a7feb95ba5768364bb08bb32d641a 100644 --- a/apps/server/scripts/record-grok-acp-replay-fixture.ts +++ b/apps/server/scripts/record-grok-acp-replay-fixture.ts @@ -24,14 +24,15 @@ import * as Schema from "effect/Schema"; import { ChildProcessSpawner } from "effect/process"; import type * as EffectAcpProtocol from "effect-acp/protocol"; -import * as ServerConfig from "../src/config.ts"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; +import { layerTestProviderHost } from "@t3tools/provider-testing/host"; import { GROK_DEFAULT_INSTANCE_ID, GROK_PROVIDER, grokLaunchRuntimeMode, makeGrokAdapterV2, } from "../src/orchestration-v2/Adapters/GrokAdapterV2.ts"; -import { ACP_PROTOCOL } from "../src/orchestration-v2/Adapters/AcpAdapterV2.ts"; +import { ACP_PROTOCOL } from "@t3tools/provider-acp/server/adapter"; import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; import type { ProviderAdapterV2SessionRuntime } from "@t3tools/provider-core/server/ProviderAdapter"; import * as ProviderContinuationRequests from "@t3tools/provider-core/server/continuationRequests"; @@ -40,7 +41,6 @@ import { provideDeterministicTestRuntime } from "../src/orchestration-v2/testkit import { ORCHESTRATOR_REPLAY_FIXTURES } from "../src/orchestration-v2/testkit/fixtures/index.ts"; import { materializeFixtureInput } from "../src/orchestration-v2/testkit/fixtures/shared.ts"; import { runOrchestratorV2Scenario } from "../src/orchestration-v2/testkit/OrchestratorScenario.ts"; -import { makeReplayServerConfig } from "../src/orchestration-v2/testkit/ProviderReplayHarness.ts"; import * as ProviderReplayHarness from "../src/orchestration-v2/testkit/ProviderReplayHarness.ts"; import { checkpointWorkspace } from "@t3tools/provider-testing/replayWorkspace"; import { makeGrokAcpRuntime } from "../src/provider/acp/GrokAcpSupport.ts"; @@ -455,7 +455,7 @@ const recordScenario = Effect.fn("recordGrokScenario")(function* (fixtureName: s crypto: yield* Crypto.Crypto, fileSystem: yield* FileSystem.FileSystem, idAllocator: yield* IdAllocator.IdAllocatorV2, - serverConfig: yield* ServerConfig.ServerConfig, + host: yield* ProviderHost.ProviderHost, selfInvocation: yield* resolveSelfInvocation(), continuationRequests: yield* ProviderContinuationRequests.ProviderContinuationRequests, // Production's runtime factory, with the protocol logger teeing raw lines. @@ -496,10 +496,7 @@ const recordScenario = Effect.fn("recordGrokScenario")(function* (fixtureName: s ).pipe( Layer.provide( Layer.mergeAll( - Layer.effect( - ServerConfig.ServerConfig, - makeReplayServerConfig(`grok-record-${fixtureName}`), - ).pipe(Layer.provide(NodeServices.layer)), + layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), NodeServices.layer, IdAllocator.layer, ), diff --git a/apps/server/src/mcp/AcpMcpStdioBridge.ts b/apps/server/src/mcp/AcpMcpStdioBridge.ts index 5c7bfe6889d5545798e0aa6a9b581fef4ac21555..02e6cdeac60799f30d30abb3a54061ce8e85ce43 100644 --- a/apps/server/src/mcp/AcpMcpStdioBridge.ts +++ b/apps/server/src/mcp/AcpMcpStdioBridge.ts @@ -7,6 +7,7 @@ import * as Cause from "effect/Cause"; import * as Effect from "effect/Effect"; import * as Fiber from "effect/Fiber"; import * as Stream from "effect/Stream"; +import { discardResponseBody, responsePayloads } from "@t3tools/shared/mcpResponsePayloads"; /** * Stdio-to-HTTP bridge for T3's MCP endpoint. @@ -63,58 +64,6 @@ function protocolVersionOf(entry: unknown): string | null { return typeof version === "string" && version.length > 0 ? version : null; } -async function* sseDataLines(response: Response): AsyncGenerator { - if (response.body === null) return; - const decoder = new TextDecoder(); - let buffered = ""; - for await (const chunk of response.body) { - buffered += decoder.decode(chunk as Uint8Array, { stream: true }); - let separatorIndex = buffered.search(/\n\n|\r\n\r\n/u); - while (separatorIndex !== -1) { - const rawEvent = buffered.slice(0, separatorIndex); - buffered = buffered.slice(separatorIndex).replace(/^(?:\r?\n){2}/u, ""); - const data = rawEvent - .split(/\r?\n/u) - .filter((line) => line.startsWith("data:")) - .map((line) => line.slice("data:".length).trimStart()) - .join("\n"); - if (data.length > 0) yield data; - separatorIndex = buffered.search(/\n\n|\r\n\r\n/u); - } - } -} - -const discardResponseBody = (response: Response): Effect.Effect => - Effect.promise(() => response.body?.cancel().catch(() => undefined) ?? Promise.resolve()); - -/** - * Every JSON-RPC payload carried by a response, in arrival order: nothing for - * notification acknowledgements, each SSE `data:` event as it streams in, or - * the single JSON body. - */ -export function responsePayloads(response: Response): Stream.Stream { - if (response.status === 202 || response.status === 204) { - return Stream.unwrap(discardResponseBody(response).pipe(Effect.as(Stream.empty))); - } - const contentType = response.headers.get("content-type") ?? ""; - if (contentType.includes("text/event-stream")) { - return Stream.fromAsyncIterable(sseDataLines(response), bridgeError).pipe( - Stream.mapEffect((data) => Effect.try({ try: () => JSON.parse(data), catch: bridgeError })), - ); - } - return Stream.unwrap( - Effect.tryPromise({ try: () => response.text(), catch: bridgeError }).pipe( - Effect.flatMap((text) => - text.trim().length === 0 - ? Effect.succeed(Stream.empty) - : Effect.try({ try: () => JSON.parse(text) as unknown, catch: bridgeError }).pipe( - Effect.map((payload) => Stream.fromIterable([payload])), - ), - ), - ), - ); -} - export interface AcpMcpToolCallOptions { readonly endpoint: string; readonly authorization: string; @@ -164,7 +113,7 @@ export function callAcpMcpTool( new AcpMcpBridgeError(`T3 Code MCP endpoint responded with HTTP ${response.status}.`), ); } - const payloads = yield* Stream.runCollect(responsePayloads(response)); + const payloads = yield* Stream.runCollect(responsePayloads(response, bridgeError)); for (const payload of payloads) { protocolVersion = protocolVersionOf(payload) ?? protocolVersion; } @@ -271,7 +220,7 @@ export function runAcpMcpStdioBridge(options: AcpMcpStdioBridgeOptions): Effect. } return yield* discardResponseBody(response); } - yield* Stream.runForEach(responsePayloads(response), handleServerPayload); + yield* Stream.runForEach(responsePayloads(response, bridgeError), handleServerPayload); }).pipe( Effect.catchCause((cause) => { if (envelope.id === undefined) return Effect.void; diff --git a/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts b/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts index c908265271764f7ea0b7d32d7c95c23c5ad05723..5e225d570d7a4f79bcc09f92efbf4d9e2c84faee 100644 --- a/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts +++ b/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts @@ -54,9 +54,10 @@ import * as EffectAcpErrors from "effect-acp/errors"; import type * as EffectAcpProtocol from "effect-acp/protocol"; import type * as EffectAcpSchema from "effect-acp/compat"; -import * as ServerConfig from "../../config.ts"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; +import { layerTestProviderHost } from "@t3tools/provider-testing/host"; import * as McpProviderSession from "@t3tools/provider-core/server/mcpSession"; -import * as AcpSessionRuntime from "../../provider/acp/AcpSessionRuntime.ts"; +import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import { extractXAiAcpSubagentEndNotice, extractXAiAcpSubagentUpdate, @@ -90,7 +91,7 @@ import { type AcpAdapterV2Flavor, type AcpAdapterV2RuntimeInput, type AcpAdapterV2SubagentUpdate, -} from "./AcpAdapterV2.ts"; +} from "@t3tools/provider-acp/server/adapter"; import { makeGrokAdapterV2 } from "./GrokAdapterV2.ts"; import { @@ -100,11 +101,9 @@ import { const DEFAULT_GROK_SETTINGS = Schema.decodeSync(GrokSettings)({}); -const layerServerConfig = ServerConfig.layerTest(process.cwd(), { - prefix: "t3-acp-v2-adapter-", -}).pipe(Layer.provide(NodeServices.layer)); +const layerHost = layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)); -const layerTest = Layer.mergeAll(NodeServices.layer, IdAllocator.layer, layerServerConfig); +const layerTest = Layer.mergeAll(NodeServices.layer, IdAllocator.layer, layerHost); const ACP_TEST_DRIVER = ProviderDriverKind.make("acp-test"); const decodeUnknownJson = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Unknown)); @@ -616,7 +615,7 @@ describe("AcpAdapterV2", () => { instanceId, fileSystem: yield* FileSystem.FileSystem, idAllocator: yield* IdAllocator.IdAllocatorV2, - serverConfig: yield* ServerConfig.ServerConfig, + host: yield* ProviderHost.ProviderHost, selfInvocation: yield* resolveSelfInvocation(), flavor: { driver: ProviderDriverKind.make("acpRegistry"), @@ -713,7 +712,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation().pipe( Effect.provideService(HostProcessIsExecutable, true), ); @@ -753,7 +752,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const runtimePolicy = ProviderAdapterV2RuntimePolicy.make({ @@ -786,7 +785,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -816,7 +815,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const policy = (interactionMode: "default" | "plan") => @@ -913,7 +912,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -941,7 +940,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-v2-plan-replay-boundary"); @@ -1049,7 +1048,7 @@ describe("AcpAdapterV2", () => { crypto: yield* Crypto.Crypto, fileSystem: yield* FileSystem.FileSystem, idAllocator: yield* IdAllocator.IdAllocatorV2, - serverConfig: yield* ServerConfig.ServerConfig, + host: yield* ProviderHost.ProviderHost, selfInvocation: yield* resolveSelfInvocation(), flavor: { driver: ACP_TEST_DRIVER, @@ -1195,7 +1194,7 @@ describe("AcpAdapterV2", () => { crypto: yield* Crypto.Crypto, fileSystem: yield* FileSystem.FileSystem, idAllocator, - serverConfig: yield* ServerConfig.ServerConfig, + host: yield* ProviderHost.ProviderHost, selfInvocation: yield* resolveSelfInvocation(), flavor: { driver: ACP_TEST_DRIVER, @@ -1515,7 +1514,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -1544,7 +1543,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-v2-fidelity"); @@ -1709,7 +1708,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -1730,7 +1729,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-eager-resume"); @@ -1794,7 +1793,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -1817,7 +1816,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-stale-eager-resume"); @@ -1940,7 +1939,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -1969,7 +1968,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-unexpected-termination"); @@ -2023,7 +2022,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -2058,7 +2057,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-provider-exit-running-command"); @@ -2108,7 +2107,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -2137,7 +2136,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-cgroup-unavailable"); @@ -2164,7 +2163,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -2209,7 +2208,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-cgroup-join-failure"); @@ -2242,7 +2241,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -2286,7 +2285,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, clientTerminals: { childProcessSpawner }, }); @@ -2454,7 +2453,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -2484,7 +2483,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-no-client-fs"); @@ -2551,7 +2550,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -2591,7 +2590,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, clientTerminals: { childProcessSpawner }, }); @@ -2688,7 +2687,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -2704,7 +2703,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-missing-native-thread"); @@ -2750,7 +2749,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -2788,7 +2787,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-rollback-session"); @@ -2917,7 +2916,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -3001,7 +3000,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: () => Effect.void }, }); @@ -3078,7 +3077,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -3120,7 +3119,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-rollback-failure-compensation"); @@ -3194,7 +3193,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -3211,7 +3210,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-idle-finalizer"); @@ -3245,7 +3244,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -3261,7 +3260,7 @@ describe("AcpAdapterV2", () => { crypto: yield* Crypto.Crypto, fileSystem, idAllocator, - serverConfig, + host, selfInvocation: yield* resolveSelfInvocation(), // Production Grok runtimes are wrapped by the x.ai prompt runtime. makeRuntime: (input) => @@ -3300,7 +3299,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -3316,7 +3315,7 @@ describe("AcpAdapterV2", () => { crypto: yield* Crypto.Crypto, fileSystem, idAllocator, - serverConfig, + host, selfInvocation: yield* resolveSelfInvocation(), // Production Grok runtimes are wrapped by the x.ai prompt runtime. makeRuntime: (input) => @@ -3381,7 +3380,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -3397,7 +3396,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-unsupported-option"); @@ -3430,7 +3429,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -3447,7 +3446,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const firstThreadId = ThreadId.make("thread-acp-active-setup:first"); @@ -3541,7 +3540,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -3568,7 +3567,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-empty-successful-bash"); @@ -3688,7 +3687,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const protocolEvents = yield* Queue.unbounded(); const native: { current?: AcpSessionRuntime.AcpSessionRuntime["Service"] } = {}; @@ -3715,7 +3714,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-native-cancel"); @@ -3802,7 +3801,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -3824,7 +3823,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-cancel-permission"); @@ -3903,7 +3902,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -3930,7 +3929,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-response-wins-permission"); @@ -4002,7 +4001,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -4029,7 +4028,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-reordered-elicitation"); @@ -4091,7 +4090,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -4111,7 +4110,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-mcp-approval-elicitation"); @@ -4159,7 +4158,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -4187,7 +4186,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, testHooks: { onNativeResponseLifecycle: (event) => @@ -4267,7 +4266,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -4292,7 +4291,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, testHooks: { afterNativeResponseTransportClosed: () => @@ -4381,7 +4380,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -4426,7 +4425,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, testHooks: { onNativeResponseLifecycle: (event) => @@ -4522,7 +4521,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -4564,7 +4563,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-pending-response-cancel"); @@ -4638,7 +4637,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -4679,7 +4678,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make(`thread-acp-immediate-permission-${name}`); @@ -4743,7 +4742,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -4778,7 +4777,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-immediate-url-elicitation"); @@ -4836,7 +4835,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -4875,7 +4874,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-missing-response-ack"); @@ -4929,7 +4928,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -4964,7 +4963,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-teardown-wins-elicitation"); @@ -5042,7 +5041,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -5064,7 +5063,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-cancel-timeout"); @@ -5145,7 +5144,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -5171,7 +5170,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-double-stop"); @@ -5243,7 +5242,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -5281,7 +5280,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-interrupt-background-hold"); @@ -5339,7 +5338,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -5391,7 +5390,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-subagent-carryover"); @@ -5487,7 +5486,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -5537,7 +5536,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: () => Effect.void }, }); @@ -5634,7 +5633,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -5707,7 +5706,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: () => Effect.void }, }); @@ -5871,7 +5870,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -5958,7 +5957,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: () => Effect.void }, }); @@ -6094,7 +6093,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -6157,7 +6156,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -6313,7 +6312,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -6355,7 +6354,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: () => Effect.void }, }); @@ -6461,7 +6460,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -6520,7 +6519,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -6713,7 +6712,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -6774,7 +6773,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -7001,7 +7000,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -7072,7 +7071,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -7242,7 +7241,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -7316,7 +7315,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -7471,7 +7470,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -7533,7 +7532,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -7742,7 +7741,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -7803,7 +7802,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -7984,7 +7983,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -8053,7 +8052,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-settled-soft-steer"); @@ -8160,7 +8159,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -8192,7 +8191,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-unsettled-steer-stays-hard"); @@ -8250,7 +8249,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -8298,7 +8297,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -8444,7 +8443,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -8484,7 +8483,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: () => Effect.void }, }); @@ -8591,7 +8590,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -8630,7 +8629,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: () => Effect.void }, }); @@ -8722,7 +8721,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -8799,7 +8798,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-stop-after-soft-steer-orphan"); @@ -9026,7 +9025,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -9087,7 +9086,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: () => Effect.void }, }); @@ -9223,7 +9222,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -9298,7 +9297,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-settled-soft-admission-race"); @@ -9393,7 +9392,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -9431,7 +9430,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -9524,7 +9523,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -9554,7 +9553,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -9644,7 +9643,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -9690,7 +9689,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -9853,7 +9852,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -9897,7 +9896,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-injected-report-hold"); @@ -10019,7 +10018,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -10078,7 +10077,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -10221,7 +10220,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -10276,7 +10275,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -10461,7 +10460,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -10523,7 +10522,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -10680,7 +10679,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -10746,7 +10745,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -10895,7 +10894,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -10983,7 +10982,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -11267,7 +11266,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -11306,7 +11305,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -11421,7 +11420,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -11490,7 +11489,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -11752,7 +11751,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -11802,7 +11801,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -11939,7 +11938,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -11993,7 +11992,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -12183,7 +12182,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -12235,7 +12234,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -12373,7 +12372,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -12395,7 +12394,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-restart-after-interrupt"); @@ -12619,7 +12618,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -12668,7 +12667,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: (request) => @@ -12837,7 +12836,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -12861,7 +12860,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-missing-hard-teardown"); @@ -12926,7 +12925,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -12963,7 +12962,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-concurrent-hard-teardown"); @@ -13039,7 +13038,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -13122,7 +13121,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, testHooks: { afterHardTeardownTransportDrained: () => @@ -13401,7 +13400,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -13428,7 +13427,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-stale-deferred-cleanup"); @@ -13526,7 +13525,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -13563,7 +13562,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-concurrent-resume-teardown"); @@ -13660,7 +13659,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -13714,7 +13713,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests: { offer: () => Effect.void }, }); @@ -13937,7 +13936,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -13987,7 +13986,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-direct-stop-subagent-hold"); @@ -14091,7 +14090,7 @@ describe("AcpAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const selfInvocation = yield* resolveSelfInvocation(); const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -14136,7 +14135,7 @@ describe("AcpAdapterV2", () => { }, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, }); const threadId = ThreadId.make("thread-acp-restart-active-in-process"); diff --git a/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.testkit.ts b/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.testkit.ts index 960ac6f57f011cd369d17f3110d1684e5a5b3d44..8a4310c3d542c478131397950be2df899b4444e8 100644 --- a/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.testkit.ts +++ b/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.testkit.ts @@ -13,9 +13,9 @@ import * as Stream from "effect/Stream"; import { ChildProcessSpawner } from "effect/process"; import * as EffectAcpErrors from "effect-acp/errors"; -import * as AcpSessionRuntime from "../../provider/acp/AcpSessionRuntime.ts"; +import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import type { ProviderReplayGate } from "@t3tools/provider-testing/replayGate"; -import { ACP_PROTOCOL, type AcpAdapterV2RuntimeInput } from "./AcpAdapterV2.ts"; +import { ACP_PROTOCOL, type AcpAdapterV2RuntimeInput } from "@t3tools/provider-acp/server/adapter"; export const AcpReplayTranscript = Schema.Struct({ provider: ProviderDriverKind, diff --git a/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.test.ts b/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.test.ts index 85ae7368ee676e7a4cc50c08ceb20888ddcc6238..fa861a22dde77bfff156b3c6271ad4f8c95a3826 100644 --- a/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.test.ts +++ b/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.test.ts @@ -14,15 +14,16 @@ import { HttpClient, HttpClientResponse } from "effect/http"; import { ChildProcessSpawner } from "effect/process"; import * as EffectAcpErrors from "effect-acp/errors"; -import * as ServerConfig from "../../config.ts"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; +import { layerTestProviderHost } from "@t3tools/provider-testing/host"; import * as ServerSettings from "../../serverSettings.ts"; import type { AcpRegistryAvailableCommands, AcpRegistryLiveConfiguration, } from "../../provider/acp/AcpRegistryProbe.ts"; import * as AcpRegistrySupport from "../../provider/acp/AcpRegistrySupport.ts"; -import { ACP_SESSION_MODE_OPTION_ID } from "../../provider/acp/AcpSessionConfig.ts"; -import * as AcpSessionRuntime from "../../provider/acp/AcpSessionRuntime.ts"; +import { ACP_SESSION_MODE_OPTION_ID } from "@t3tools/provider-acp/server/sessionConfig"; +import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; import { decodeAcpReplayTranscript, @@ -43,9 +44,7 @@ const decodeAcpRegistryAdapterSettings = Schema.decodeUnknownEffect( AcpRegistryAdapterV2Driver.configSchema, ); -const layerServerConfig = ServerConfig.layerTest(process.cwd(), { - prefix: "t3-acp-registry-v2-adapter-", -}).pipe(Layer.provide(NodeServices.layer)); +const layerHost = layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)); const layerRegistry = Layer.succeed( HttpClient.HttpClient, @@ -86,7 +85,7 @@ const layerRegistry = Layer.succeed( const layerTest = Layer.mergeAll( NodeServices.layer, IdAllocator.layer, - layerServerConfig, + layerHost, layerRegistry, ServerSettings.layerTest(), ); @@ -202,7 +201,7 @@ describe("AcpRegistryAdapterV2", () => { fileSystem, idAllocator: yield* IdAllocator.IdAllocatorV2, resolver: { resolve: () => Effect.die("the runtime is injected") }, - serverConfig: yield* ServerConfig.ServerConfig, + host: yield* ProviderHost.ProviderHost, makeRuntime: makeAcpReplayRuntime({ transcript, statusPath, @@ -272,7 +271,7 @@ describe("AcpRegistryAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), ); @@ -291,7 +290,7 @@ describe("AcpRegistryAdapterV2", () => { fileSystem, idAllocator, resolver: { resolve: () => Effect.die("the runtime is injected") }, - serverConfig, + host, makeRuntime: (input) => Effect.gen(function* () { clientCapabilities = input.clientCapabilities; @@ -348,13 +347,13 @@ describe("AcpRegistryAdapterV2", () => { const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), ); const resolver = yield* AcpRegistrySupport.makeAcpRegistryCatalog({ - cacheDir: serverConfig.providerStatusCacheDir, - toolsDir: serverConfig.baseDir + "/tools", + cacheDir: host.paths.providerStatusCacheDir, + toolsDir: host.paths.baseDir + "/tools", registryUrl, }); const settings = yield* decodeAcpRegistryAdapterSettings({ @@ -429,7 +428,7 @@ describe("AcpRegistryAdapterV2", () => { })), ), }, - serverConfig, + host, }); const threadId = ThreadId.make("thread-acp-registry-fixture"); const runtimePolicy = ProviderAdapterV2RuntimePolicy.make({ diff --git a/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.testkit.ts b/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.testkit.ts index 7d829741862dbe9cae3d6546b4d608a1dda5a860..9ebe08e40ec10def3343846752b4c451baebcc67 100644 --- a/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.testkit.ts +++ b/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.testkit.ts @@ -9,12 +9,12 @@ import * as Path from "effect/Path"; import * as Schema from "effect/Schema"; import { ChildProcessSpawner } from "effect/process"; -import * as ServerConfig from "../../config.ts"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; +import { layerTestProviderHost } from "@t3tools/provider-testing/host"; import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; import * as ProviderAdapterRegistry from "../ProviderAdapterRegistry.ts"; import type { ProviderReplayGate } from "@t3tools/provider-testing/replayGate"; import type { OrchestratorV2ProviderReplayHarness } from "../testkit/ProviderReplayHarness.ts"; -import { makeReplayServerConfig } from "../testkit/ProviderReplayHarness.ts"; import { type AcpReplayTranscript, AcpReplayTranscriptDecodeError, @@ -37,10 +37,7 @@ function layerAcpRegistryProviderAdapterRegistryReplay( transcript: AcpReplayTranscript, options: { readonly replayGate?: ProviderReplayGate } = {}, ) { - const layerServerConfig = Layer.effect( - ServerConfig.ServerConfig, - makeReplayServerConfig(`acp-registry-${transcript.scenario}`).pipe(Effect.orDie), - ).pipe(Layer.provide(NodeServices.layer)); + const layerHost = layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)); return ProviderAdapterRegistry.layerFromAdaptersEffect( Effect.gen(function* () { @@ -49,7 +46,7 @@ function layerAcpRegistryProviderAdapterRegistryReplay( const childProcessSpawner = yield* ChildProcessSpawner.ChildProcessSpawner; const crypto = yield* Crypto.Crypto; const idAllocator = yield* IdAllocator.IdAllocatorV2; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const replayGate = options.replayGate; const replayDir = yield* fileSystem .makeTempDirectory({ @@ -71,7 +68,7 @@ function layerAcpRegistryProviderAdapterRegistryReplay( resolver: { resolve: () => Effect.die("ACP registry resolver must not run during replay"), }, - serverConfig, + host, selfInvocation: yield* resolveSelfInvocation(), makeRuntime: makeAcpReplayRuntime({ transcript, @@ -86,7 +83,7 @@ function layerAcpRegistryProviderAdapterRegistryReplay( return [adapter]; }), ).pipe( - Layer.provide(Layer.mergeAll(layerServerConfig, NodeServices.layer, IdAllocator.layer)), + Layer.provide(Layer.mergeAll(layerHost, NodeServices.layer, IdAllocator.layer)), // Held inbound lines must not outlive the scenario and wedge teardown. Layer.merge( Layer.effectDiscard( diff --git a/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.ts b/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.ts index f1a1ef3a583f2795e942deb4b65456bd60c6a5ed..d188f9c9266f6b7eeb0aa2f3c44cfbd435e5436b 100644 --- a/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.ts +++ b/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.ts @@ -21,7 +21,7 @@ import type * as Scope from "effect/Scope"; import { ChildProcessSpawner } from "effect/process"; import * as EffectAcpErrors from "effect-acp/errors"; -import * as ServerConfig from "../../config.ts"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; import { normalizeAcpRegistryCommands, normalizeAcpRegistryLiveConfiguration, @@ -29,8 +29,8 @@ import { } from "../../provider/acp/AcpRegistryProbe.ts"; import * as AcpRegistrySupport from "../../provider/acp/AcpRegistrySupport.ts"; import * as AcpRegistryRuntimeCoordinator from "../../provider/acp/AcpRegistryRuntimeCoordinator.ts"; -import * as AcpSessionRuntime from "../../provider/acp/AcpSessionRuntime.ts"; -import { makeAcpNativeLoggerFactory } from "../../provider/acp/AcpNativeLogging.ts"; +import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; +import { makeAcpNativeLoggerFactory } from "@t3tools/provider-acp/server/nativeLogging"; import * as ProviderEventLoggers from "../../provider/ProviderEventLoggers.ts"; import { mergeProviderInstanceEnvironment } from "@t3tools/provider-core/server/instanceEnvironment"; import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; @@ -46,7 +46,7 @@ import { type AcpAdapterV2ExtensionContext, type AcpAdapterV2Flavor, type AcpAdapterV2RuntimeInput, -} from "./AcpAdapterV2.ts"; +} from "@t3tools/provider-acp/server/adapter"; export const ACP_REGISTRY_PROVIDER = ProviderDriverKind.make("acpRegistry"); export const ACP_REGISTRY_DEFAULT_INSTANCE_ID = defaultInstanceIdForDriver(ACP_REGISTRY_PROVIDER); @@ -65,7 +65,7 @@ export interface AcpRegistryAdapterV2Options { readonly idAllocator: IdAllocator.IdAllocatorV2["Service"]; readonly resolver: Pick; readonly runtimeCoordinator?: AcpRegistryRuntimeCoordinator.AcpRegistryRuntimeCoordinator["Service"]; - readonly serverConfig: ServerConfig.ServerConfig["Service"]; + readonly host: ProviderHost.ProviderHostShape; readonly nativeLogging?: Parameters[0]["nativeLogging"]; readonly makeRuntime?: ( input: AcpAdapterV2RuntimeInput, @@ -243,7 +243,7 @@ export function makeAcpRegistryAdapterV2(options: AcpRegistryAdapterV2Options) { crypto: options.crypto, fileSystem: options.fileSystem, idAllocator: options.idAllocator, - serverConfig: options.serverConfig, + host: options.host, selfInvocation: options.selfInvocation, // Per-agent exception (see the note above registerMistralVibeAcpExtensions): // Devin runs commands through client terminals and has no ask mode over @@ -269,7 +269,7 @@ export type AcpRegistryAdapterV2DriverEnv = | IdAllocator.IdAllocatorV2 | Path.Path | ProviderEventLoggers.ProviderEventLoggers - | ServerConfig.ServerConfig; + | ProviderHost.ProviderHost; export const AcpRegistryAdapterV2Driver: ProviderAdapterDriver< AcpRegistrySettings, @@ -287,7 +287,7 @@ export const AcpRegistryAdapterV2Driver: ProviderAdapterDriver< const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const providerEventLoggers = yield* ProviderEventLoggers.ProviderEventLoggers; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const makeNativeLogger = yield* makeAcpNativeLoggerFactory(); const resolver = yield* AcpRegistrySupport.AcpRegistryCatalog; const runtimeCoordinator = yield* Effect.serviceOption( @@ -305,7 +305,7 @@ export const AcpRegistryAdapterV2Driver: ProviderAdapterDriver< ...(Option.isSome(runtimeCoordinator) ? { runtimeCoordinator: runtimeCoordinator.value } : {}), - serverConfig, + host, selfInvocation, nativeLogging: (threadId) => makeNativeLogger({ diff --git a/apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.test.ts b/apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.test.ts index ed00f33728b7c99dac368810cf834ce14be45d92..4ce55c783307b3b4ee84563d78c8d90dc51abdb0 100644 --- a/apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.test.ts +++ b/apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.test.ts @@ -22,8 +22,9 @@ import * as Stream from "effect/Stream"; import { ChildProcessSpawner } from "effect/process"; import type * as EffectAcpSchema from "effect-acp/compat"; -import * as ServerConfig from "../../config.ts"; -import type * as AcpSessionRuntime from "../../provider/acp/AcpSessionRuntime.ts"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; +import { layerTestProviderHost } from "@t3tools/provider-testing/host"; +import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import { makeAntigravityAcpRuntime } from "../../provider/acp/AntigravityAcpSupport.ts"; import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; import { ProviderAdapterV2RuntimePolicy } from "@t3tools/provider-core/server/ProviderAdapter"; @@ -38,7 +39,7 @@ const flavor = makeAntigravityAcpAdapterFlavor({ fileSystem: undefined as never, path: undefined as never, idAllocator: undefined as never, - serverConfig: undefined as never, + host: undefined as never, selfInvocation: undefined as never, makeRuntime: () => Effect.die("not spawned in this test"), withProcess: (_stop, task) => task, @@ -129,9 +130,7 @@ describe("AntigravityAdapterV2 flavor", () => { const layerSession = Layer.mergeAll( NodeServices.layer, IdAllocator.layer, - ServerConfig.layerTest(process.cwd(), { prefix: "t3-antigravity-v2-adapter-" }).pipe( - Layer.provide(NodeServices.layer), - ), + layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), ); describe("AntigravityAdapterV2 client file system", () => { @@ -140,7 +139,7 @@ describe("AntigravityAdapterV2 client file system", () => { const childProcessSpawner = yield* ChildProcessSpawner.ChildProcessSpawner; const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), ); @@ -157,7 +156,7 @@ describe("AntigravityAdapterV2 client file system", () => { fileSystem, path, idAllocator: yield* IdAllocator.IdAllocatorV2, - serverConfig, + host, makeRuntime: (input) => makeAntigravityAcpRuntime({ ...input, @@ -193,7 +192,7 @@ describe("AntigravityAdapterV2 client file system", () => { }); const outsideFile = path.join(outside, "secret.txt"); yield* fileSystem.writeFileString(outsideFile, "secret"); - const attachment = path.join(serverConfig.attachmentsDir, "pasted.txt"); + const attachment = path.join(host.paths.attachmentsDir, "pasted.txt"); yield* fileSystem.writeFileString(attachment, "pasted"); const threadId = ThreadId.make("thread-antigravity-containment"); @@ -294,7 +293,7 @@ describe("AntigravityAdapterV2 workspace changes", () => { const childProcessSpawner = yield* ChildProcessSpawner.ChildProcessSpawner; const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const crypto = yield* Crypto.Crypto; const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -309,7 +308,7 @@ describe("AntigravityAdapterV2 workspace changes", () => { fileSystem, path, idAllocator: yield* IdAllocator.IdAllocatorV2, - serverConfig, + host, makeRuntime: (input) => makeAntigravityAcpRuntime({ ...input, @@ -431,7 +430,7 @@ describe("AntigravityAdapterV2 client file system under restrictive policies", ( const childProcessSpawner = yield* ChildProcessSpawner.ChildProcessSpawner; const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const crypto = yield* Crypto.Crypto; const mockAgentPath = yield* path.fromFileUrl( new URL("../../../scripts/acp-mock-agent.ts", import.meta.url), @@ -459,7 +458,7 @@ describe("AntigravityAdapterV2 client file system under restrictive policies", ( fileSystem, path, idAllocator: yield* IdAllocator.IdAllocatorV2, - serverConfig, + host, makeRuntime: (input) => makeAntigravityAcpRuntime({ ...input, diff --git a/apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.ts b/apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.ts index 3d8f8f75091a7a62f500b06dc285ca956a434869..4263618cf32c818b4527a7e76b7ea2909dc7c398 100644 --- a/apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.ts +++ b/apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.ts @@ -14,9 +14,9 @@ import * as Exit from "effect/Exit"; import * as Scope from "effect/Scope"; import * as EffectAcpErrors from "effect-acp/errors"; -import type { ServerConfig } from "../../config.ts"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; import type { AntigravityAuth } from "../../provider/AntigravityAuth.ts"; -import type * as AcpSessionRuntime from "../../provider/acp/AcpSessionRuntime.ts"; +import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import { antigravityPermissionMode, applyAntigravityAcpModelSelection, @@ -40,7 +40,7 @@ import { makeAcpAdapterV2, type AcpAdapterV2Flavor, type AcpAdapterV2RuntimeInput, -} from "./AcpAdapterV2.ts"; +} from "@t3tools/provider-acp/server/adapter"; const ANTIGRAVITY_PROVIDER = ProviderDriverKind.make("antigravity"); @@ -68,7 +68,7 @@ export interface AntigravityAdapterV2Options { readonly fileSystem: FileSystem.FileSystem; readonly path: Path.Path; readonly idAllocator: IdAllocatorV2["Service"]; - readonly serverConfig: ServerConfig["Service"]; + readonly host: ProviderHost.ProviderHostShape; /** Spawns the official agent with the instance's Google profile. */ readonly makeRuntime: ( input: Omit, @@ -125,9 +125,7 @@ export function makeAntigravityAcpAdapterFlavor( // the turn text references. It is a leaf directory of uploads. A session // without a workspace gets no workspace root rather than the server's cwd. const antigravityClientFileRoots = (cwd: string | null) => - cwd === null - ? [options.serverConfig.attachmentsDir] - : [cwd, options.serverConfig.attachmentsDir]; + cwd === null ? [options.host.paths.attachmentsDir] : [cwd, options.host.paths.attachmentsDir]; const makeRuntime = (input: AcpAdapterV2RuntimeInput) => Effect.gen(function* () { // AcpAdapterV2 owns the runtime scope; sign-in and sign-out stop the @@ -139,7 +137,7 @@ export function makeAntigravityAcpAdapterFlavor( options.makeRuntime({ ...input, clientFileSystem: true, - additionalDirectories: [options.serverConfig.attachmentsDir], + additionalDirectories: [options.host.paths.attachmentsDir], }), ) .pipe(Effect.provideService(Scope.Scope, scope)); @@ -233,7 +231,7 @@ export function makeAntigravityAdapterV2(options: AntigravityAdapterV2Options) { crypto: options.crypto, fileSystem: options.fileSystem, idAllocator: options.idAllocator, - serverConfig: options.serverConfig, + host: options.host, selfInvocation: options.selfInvocation, ...(options.nativeLogging === undefined ? {} : { nativeLogging: options.nativeLogging }), ...(options.continuationRequests === undefined diff --git a/apps/server/src/orchestration-v2/Adapters/DevinAcp.ts b/apps/server/src/orchestration-v2/Adapters/DevinAcp.ts index 23c3b896900ca3d1697198bcb69dcff14b9992e7..6f78d2506adc2539b0291be3de4f9fa384c73471 100644 --- a/apps/server/src/orchestration-v2/Adapters/DevinAcp.ts +++ b/apps/server/src/orchestration-v2/Adapters/DevinAcp.ts @@ -1,6 +1,6 @@ import type * as AcpSchema from "effect-acp/compat"; -import type { AcpToolCallState } from "../../provider/acp/AcpRuntimeModel.ts"; -import type { AcpAdapterV2SubagentUpdate } from "./AcpAdapterV2.ts"; +import type { AcpToolCallState } from "@t3tools/provider-acp/server/runtimeModel"; +import type { AcpAdapterV2SubagentUpdate } from "@t3tools/provider-acp/server/adapter"; function record(value: unknown): Record | undefined { return typeof value === "object" && value !== null && !Array.isArray(value) diff --git a/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.test.ts b/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.test.ts index 4284de473a17d22bf8f40f395c92a7550af58e0f..23ebb1b4f2a13258fca847fc126535595a4c760e 100644 --- a/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.test.ts +++ b/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.test.ts @@ -22,7 +22,8 @@ import * as Schema from "effect/Schema"; import { ChildProcessSpawner } from "effect/process"; import type * as EffectAcpSchema from "effect-acp/compat"; -import * as ServerConfig from "../../config.ts"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; +import { layerTestProviderHost } from "@t3tools/provider-testing/host"; import * as ProjectStore from "../ProjectStore.ts"; import { buildInitialGrokProviderSnapshot } from "../../provider/GrokProvider.ts"; import type { ProviderInstance } from "@t3tools/provider-core/server/driver"; @@ -30,13 +31,13 @@ import * as ProviderInstanceRegistry from "../../provider/ProviderInstanceRegist import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; import { ProviderAdapterV2RuntimePolicy } from "@t3tools/provider-core/server/ProviderAdapter"; import * as RuntimePolicy from "../RuntimePolicy.ts"; -import { acpPermissionDisposition } from "../../provider/acp/AcpClientPolicy.ts"; +import { acpPermissionDisposition } from "@t3tools/provider-acp/server/clientPolicy"; import { AcpProviderCapabilitiesV2, acpCompletedTurnShouldTerminalizeTool, acpSubagentStatusBlocksTurnSettlement, acpSupportsImagePrompts, -} from "./AcpAdapterV2.ts"; +} from "@t3tools/provider-acp/server/adapter"; import { makeGrokAcpAdapterFlavor, makeGrokAdapterV2, @@ -311,10 +312,8 @@ describe("Grok permission prompts", () => { }); describe("Grok launch permission mode", () => { - const layerServerConfig = ServerConfig.layerTest(process.cwd(), { - prefix: "t3-grok-v2-launch-", - }).pipe(Layer.provide(NodeServices.layer)); - const layerTest = Layer.mergeAll(NodeServices.layer, IdAllocator.layer, layerServerConfig); + const layerHost = layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)); + const layerTest = Layer.mergeAll(NodeServices.layer, IdAllocator.layer, layerHost); // Opens a session through the adapter's own Grok runtime factory and returns // the argv it tried to launch. The spawn fails after recording, so no @@ -342,7 +341,7 @@ describe("Grok launch permission mode", () => { crypto: yield* Crypto.Crypto, fileSystem: yield* FileSystem.FileSystem, idAllocator: yield* IdAllocator.IdAllocatorV2, - serverConfig: yield* ServerConfig.ServerConfig, + host: yield* ProviderHost.ProviderHost, selfInvocation: yield* resolveSelfInvocation(), }); yield* adapter diff --git a/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.testkit.ts b/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.testkit.ts index b770efd77136a53db520f47e731f183ba1e8e46c..58446793decd9bd221b7ae4adc27415024a0a352 100644 --- a/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.testkit.ts +++ b/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.testkit.ts @@ -10,7 +10,8 @@ import { ChildProcessSpawner } from "effect/process"; import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; import { resolveSelfInvocation } from "@t3tools/shared/nodeRuntime"; -import * as ServerConfig from "../../config.ts"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; +import { layerTestProviderHost } from "@t3tools/provider-testing/host"; import { GROK_ACP_CANCEL_META, GROK_ACP_INITIALIZE_META, @@ -21,7 +22,6 @@ import * as ProviderContinuationRequests from "@t3tools/provider-core/server/con import * as ProviderAdapterRegistry from "../ProviderAdapterRegistry.ts"; import type { ProviderReplayGate } from "@t3tools/provider-testing/replayGate"; import type { OrchestratorV2ProviderReplayHarness } from "../testkit/ProviderReplayHarness.ts"; -import { makeReplayServerConfig } from "../testkit/ProviderReplayHarness.ts"; import { type AcpReplayTranscript, AcpReplayTranscriptDecodeError, @@ -37,10 +37,7 @@ function layerGrokProviderAdapterRegistryReplay( transcript: AcpReplayTranscript, options: { readonly replayGate?: ProviderReplayGate } = {}, ) { - const layerServerConfig = Layer.effect( - ServerConfig.ServerConfig, - makeReplayServerConfig(`grok-${transcript.scenario}`).pipe(Effect.orDie), - ).pipe(Layer.provide(NodeServices.layer)); + const layerHost = layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)); return ProviderAdapterRegistry.layerFromAdaptersEffect( Effect.gen(function* () { @@ -50,7 +47,7 @@ function layerGrokProviderAdapterRegistryReplay( const crypto = yield* Crypto.Crypto; const hostPlatform = yield* HostProcessPlatform; const idAllocator = yield* IdAllocator.IdAllocatorV2; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; // Same queue the continuation worker drains when the fixture runs it. const continuationRequests = yield* ProviderContinuationRequests.ProviderContinuationRequests; const replayGate = options.replayGate; @@ -72,7 +69,7 @@ function layerGrokProviderAdapterRegistryReplay( crypto, fileSystem, idAllocator, - serverConfig, + host, selfInvocation: yield* resolveSelfInvocation(), // Same wrapping as makeGrokAcpRuntime: client type and Ctrl+C cancel // metadata and the x.ai prompt-completion race, so replay sends what @@ -102,7 +99,7 @@ function layerGrokProviderAdapterRegistryReplay( return [adapter]; }), ).pipe( - Layer.provide(Layer.mergeAll(layerServerConfig, NodeServices.layer, IdAllocator.layer)), + Layer.provide(Layer.mergeAll(layerHost, NodeServices.layer, IdAllocator.layer)), // Held inbound lines must not outlive the scenario and wedge teardown. Layer.merge( Layer.effectDiscard( diff --git a/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.ts b/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.ts index de3c77a696ace12b923ed55e82d481c48c9ae670..e44c2da421a9e39b29d164922be16b033c293180 100644 --- a/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.ts +++ b/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.ts @@ -23,8 +23,8 @@ import type * as Scope from "effect/Scope"; import { ChildProcessSpawner } from "effect/process"; import * as EffectAcpErrors from "effect-acp/errors"; -import * as ServerConfig from "../../config.ts"; -import { makeAcpNativeLoggerFactory } from "../../provider/acp/AcpNativeLogging.ts"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; +import { makeAcpNativeLoggerFactory } from "@t3tools/provider-acp/server/nativeLogging"; import { applyGrokAcpModelSelection, currentGrokModelIdFromSessionSetup, @@ -54,8 +54,8 @@ import { XAiExitPlanModeRequest, } from "../../provider/acp/XAiAcpExtension.ts"; import { mergeProviderInstanceEnvironment } from "@t3tools/provider-core/server/instanceEnvironment"; -import { acpPermissionDisposition } from "../../provider/acp/AcpClientPolicy.ts"; -import * as AcpSessionRuntime from "../../provider/acp/AcpSessionRuntime.ts"; +import { acpPermissionDisposition } from "@t3tools/provider-acp/server/clientPolicy"; +import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import * as ProviderEventLoggers from "../../provider/ProviderEventLoggers.ts"; import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; import * as ProviderContinuationRequests from "@t3tools/provider-core/server/continuationRequests"; @@ -71,7 +71,7 @@ import { type AcpAdapterV2ExtensionContext, type AcpAdapterV2Flavor, type AcpAdapterV2RuntimeInput, -} from "./AcpAdapterV2.ts"; +} from "@t3tools/provider-acp/server/adapter"; export const GROK_PROVIDER = ProviderDriverKind.make("grok"); const GROK_DRIVER_KIND = GROK_PROVIDER; @@ -117,7 +117,7 @@ export interface GrokAdapterV2Options { readonly selfInvocation: SelfInvocation; readonly fileSystem: FileSystem.FileSystem; readonly idAllocator: IdAllocator.IdAllocatorV2["Service"]; - readonly serverConfig: ServerConfig.ServerConfig["Service"]; + readonly host: ProviderHost.ProviderHostShape; readonly nativeLogging?: Parameters[0]["nativeLogging"]; readonly continuationRequests?: Parameters[0]["continuationRequests"]; readonly testHooks?: Parameters[0]["testHooks"]; @@ -337,7 +337,7 @@ export function makeGrokAdapterV2(options: GrokAdapterV2Options) { crypto: options.crypto, fileSystem: options.fileSystem, idAllocator: options.idAllocator, - serverConfig: options.serverConfig, + host: options.host, selfInvocation: options.selfInvocation, ...(options.nativeLogging === undefined ? {} : { nativeLogging: options.nativeLogging }), ...(options.continuationRequests === undefined @@ -354,7 +354,7 @@ export type GrokAdapterV2DriverEnv = | IdAllocator.IdAllocatorV2 | Path.Path | ProviderEventLoggers.ProviderEventLoggers - | ServerConfig.ServerConfig; + | ProviderHost.ProviderHost; export const GrokAdapterV2Driver: ProviderAdapterDriver = { driverKind: GROK_DRIVER_KIND, @@ -370,7 +370,7 @@ export const GrokAdapterV2Driver: ProviderAdapterDriver @@ -417,7 +417,7 @@ const layer: Layer.Layer< | FileSystem.FileSystem | IdAllocator.IdAllocatorV2 | ProviderEventLoggers.ProviderEventLoggers - | ServerConfig.ServerConfig + | ProviderHost.ProviderHost > = Layer.effect( ProviderAdapter.ProviderAdapterV2, Effect.gen(function* () { @@ -429,7 +429,7 @@ const layer: Layer.Layer< const fileSystem = yield* FileSystem.FileSystem; const idAllocator = yield* IdAllocator.IdAllocatorV2; const providerEventLoggers = yield* ProviderEventLoggers.ProviderEventLoggers; - const serverConfig = yield* ServerConfig.ServerConfig; + const host = yield* ProviderHost.ProviderHost; const continuationRequests = yield* ProviderContinuationRequests.ProviderContinuationRequests; const makeNativeLogger = yield* makeAcpNativeLoggerFactory(); return makeGrokAdapterV2({ @@ -441,7 +441,7 @@ const layer: Layer.Layer< crypto, fileSystem, idAllocator, - serverConfig, + host, selfInvocation, continuationRequests, nativeLogging: (threadId) => diff --git a/apps/server/src/orchestration-v2/ProviderSelectionTransition.test.ts b/apps/server/src/orchestration-v2/ProviderSelectionTransition.test.ts index 4a6d6a6a91d12ddde755bbd3052f7dcb0f23423c..adc4ae1543a47689b440c0e3145e3df882eb9579 100644 --- a/apps/server/src/orchestration-v2/ProviderSelectionTransition.test.ts +++ b/apps/server/src/orchestration-v2/ProviderSelectionTransition.test.ts @@ -6,7 +6,7 @@ import { ProviderInstanceId, } from "@t3tools/contracts"; -import { AcpProviderCapabilitiesV2 } from "./Adapters/AcpAdapterV2.ts"; +import { AcpProviderCapabilitiesV2 } from "@t3tools/provider-acp/server/adapter"; import { acpSelectionTransition } from "@t3tools/provider-core/server/selectionTransition"; const selection = (model: string, effort = "medium"): ModelSelection => ({ diff --git a/apps/server/src/orchestration-v2/testkit/ProviderSwitch.integration.test.ts b/apps/server/src/orchestration-v2/testkit/ProviderSwitch.integration.test.ts index b71043aabc4e62a0bcb56f02b6c06384a5623c38..e7633781036bf9735d2ec174a1a75f9767f90527 100644 --- a/apps/server/src/orchestration-v2/testkit/ProviderSwitch.integration.test.ts +++ b/apps/server/src/orchestration-v2/testkit/ProviderSwitch.integration.test.ts @@ -42,7 +42,7 @@ import { CodexProviderCapabilitiesV2, canReuseCodexContextUsage, } from "../Adapters/CodexAdapterV2.ts"; -import { AcpProviderCapabilitiesV2 } from "../Adapters/AcpAdapterV2.ts"; +import { AcpProviderCapabilitiesV2 } from "@t3tools/provider-acp/server/adapter"; import { CursorProviderCapabilitiesV2 } from "@t3tools/provider-cursor/testing"; import * as EventSink from "../EventSink.ts"; import * as EventStore from "../EventStore.ts"; diff --git a/apps/server/src/provider/AntigravityAuth.test.ts b/apps/server/src/provider/AntigravityAuth.test.ts index 39deaa4ecd39b72e0664ba548d5cd007c9d30276..46bc2aeec2800d92eafaac6691b6322e162b7c87 100644 --- a/apps/server/src/provider/AntigravityAuth.test.ts +++ b/apps/server/src/provider/AntigravityAuth.test.ts @@ -17,7 +17,7 @@ import { type AntigravityAuth, type AntigravityAuthRuntime, } from "./AntigravityAuth.ts"; -import type { AcpSessionRuntimeStartResult } from "./acp/AcpSessionRuntime.ts"; +import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; const instanceId = ProviderInstanceId.make("antigravity-auth-test"); const owner = "t3-auth-session-owner"; @@ -31,7 +31,7 @@ const initialized = { authMethods: [{ id: "oauth-personal", name: "Log in with Google" }], agentCapabilities: { auth: { logout: {} } }, } satisfies AcpSchema.InitializeResponse; -const started: AcpSessionRuntimeStartResult = { +const started: AcpSessionRuntime.AcpSessionRuntimeStartResult = { sessionId: "native-session", initializeResult: initialized, sessionSetupResult: { diff --git a/apps/server/src/provider/AntigravityAuth.ts b/apps/server/src/provider/AntigravityAuth.ts index d25ac40f32e751841500f63244ce74a2b7b3a9fe..d711abe7c1dc5118e9fd0dbf170eade9bfa0d4ee 100644 --- a/apps/server/src/provider/AntigravityAuth.ts +++ b/apps/server/src/provider/AntigravityAuth.ts @@ -19,7 +19,7 @@ import * as Stream from "effect/Stream"; import * as SubscriptionRef from "effect/SubscriptionRef"; import * as AcpErrors from "effect-acp/errors"; -import type { AcpSessionRuntime, AcpSessionRuntimeStartResult } from "./acp/AcpSessionRuntime.ts"; +import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import { parseAntigravityAuthorizationUrl, type AntigravityAuthorizationUrl, @@ -66,19 +66,19 @@ export interface AntigravityAuth { } export type AntigravityAuthRuntime = Pick< - AcpSessionRuntime["Service"], + AcpSessionRuntime.AcpSessionRuntime["Service"], "initialize" | "start" | "request" >; export interface AntigravityAuthOptions< - Runtime extends AntigravityAuthRuntime = AcpSessionRuntime["Service"], + Runtime extends AntigravityAuthRuntime = AcpSessionRuntime.AcpSessionRuntime["Service"], > { readonly instanceId: ProviderInstanceId; readonly makeRuntime: (input: { readonly onAuthorizationUrl?: (url: string) => Effect.Effect; }) => Effect.Effect; readonly onAuthenticated: ( - result: AcpSessionRuntimeStartResult, + result: AcpSessionRuntime.AcpSessionRuntimeStartResult, runtime: Runtime, ) => Effect.Effect; readonly onSignedOut: Effect.Effect; diff --git a/apps/server/src/provider/AntigravityProvider.test.ts b/apps/server/src/provider/AntigravityProvider.test.ts index 69502047f73dcf5e6428290132800fcfec7fb1f0..f1728108dfae619e1a1ffb9ca4551db87fa7108d 100644 --- a/apps/server/src/provider/AntigravityProvider.test.ts +++ b/apps/server/src/provider/AntigravityProvider.test.ts @@ -23,7 +23,7 @@ import * as ServerConfig from "../config.ts"; import * as ServerSettings from "../serverSettings.ts"; import * as ProviderHostLive from "./ProviderHostLive.ts"; import * as ServerSecretStore from "../auth/ServerSecretStore.ts"; -import type { AcpSessionRuntimeStartResult } from "./acp/AcpSessionRuntime.ts"; +import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import { buildAntigravityModelsFromSession, makeAntigravityProvider, @@ -98,7 +98,7 @@ const started = { initializeResult, sessionSetupResult, modelConfigId: "model", -} satisfies AcpSessionRuntimeStartResult; +} satisfies AcpSessionRuntime.AcpSessionRuntimeStartResult; const commands = [ { name: "plan", description: "Create a plan", input: { type: "text", hint: "What to plan" } }, diff --git a/apps/server/src/provider/AntigravityProvider.ts b/apps/server/src/provider/AntigravityProvider.ts index 143b6522bd469d2f5b4700f5479e8f1d6a505c4f..ce4663a9be416e7a3a96109403637b23c479fd2c 100644 --- a/apps/server/src/provider/AntigravityProvider.ts +++ b/apps/server/src/provider/AntigravityProvider.ts @@ -18,7 +18,7 @@ import * as SubscriptionRef from "effect/SubscriptionRef"; import type * as EffectAcpErrors from "effect-acp/errors"; import type * as EffectAcpSchema from "effect-acp/compat"; -import type { AcpSessionRuntimeStartResult } from "./acp/AcpSessionRuntime.ts"; +import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import { makeManagedServerProvider } from "@t3tools/provider-core/server/managedProvider"; import { makeManualOnlyProviderMaintenanceCapabilities, @@ -38,7 +38,7 @@ const AUTH_UNCHECKED_MESSAGE = "Antigravity is installed. Google account access is not checked yet."; type SessionSetupResult = Pick< - AcpSessionRuntimeStartResult["sessionSetupResult"], + AcpSessionRuntime.AcpSessionRuntimeStartResult["sessionSetupResult"], "configOptions" | "models" >; @@ -256,7 +256,7 @@ export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(func }); const onSessionStarted = Effect.fn("AntigravityProvider.onSessionStarted")(function* ( - started: AcpSessionRuntimeStartResult, + started: AcpSessionRuntime.AcpSessionRuntimeStartResult, cwd?: string, ) { const before = yield* SubscriptionRef.get(metadata); diff --git a/apps/server/src/provider/Drivers/AcpRegistryDriver.ts b/apps/server/src/provider/Drivers/AcpRegistryDriver.ts index bdd5c0449a2c6961719ebd9b872fbe5a5641a915..be570db9160c6df995d7a57398ae6e68caadebf4 100644 --- a/apps/server/src/provider/Drivers/AcpRegistryDriver.ts +++ b/apps/server/src/provider/Drivers/AcpRegistryDriver.ts @@ -22,7 +22,6 @@ import * as Semaphore from "effect/Semaphore"; import { ChildProcessSpawner } from "effect/process"; import { ProviderHost } from "@t3tools/provider-core/server/ProviderHost"; -import * as ServerConfig from "../../config.ts"; import { AcpRegistryAdapterV2Driver, type AcpRegistryAdapterV2DriverEnv, @@ -489,7 +488,6 @@ export const AcpRegistryDriver: ProviderDriver confirmedAuthentication diff --git a/apps/server/src/provider/Drivers/AntigravityDriver.ts b/apps/server/src/provider/Drivers/AntigravityDriver.ts index f354dc4b4aa74c17b6ff6a7026812ba0c52fe482..fa075fa28dfc44b84dbd8833ff270c098dc12af5 100644 --- a/apps/server/src/provider/Drivers/AntigravityDriver.ts +++ b/apps/server/src/provider/Drivers/AntigravityDriver.ts @@ -19,7 +19,6 @@ import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; import type { AcpError } from "effect-acp/errors"; import { ProviderHost } from "@t3tools/provider-core/server/ProviderHost"; -import * as ServerConfig from "../../config.ts"; import { isAntigravityTextGenerationAvailable, makeAntigravityTextGeneration, @@ -40,7 +39,7 @@ import { makeAntigravityAcpRuntime, type AntigravityAcpRuntimeInput, } from "../acp/AntigravityAcpSupport.ts"; -import type { AcpSessionRuntime, AcpSessionRuntimeStartResult } from "../acp/AcpSessionRuntime.ts"; +import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import type { ServerProviderDraft } from "@t3tools/provider-core/server/snapshotProbe"; import { removeAntigravityRuntimeTempDirs, @@ -49,7 +48,7 @@ import { import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; import * as ProviderContinuationRequests from "@t3tools/provider-core/server/continuationRequests"; import { makeAntigravityAdapterV2 } from "../../orchestration-v2/Adapters/AntigravityAdapterV2.ts"; -import { makeAcpNativeLoggerFactory } from "../acp/AcpNativeLogging.ts"; +import { makeAcpNativeLoggerFactory } from "@t3tools/provider-acp/server/nativeLogging"; import { ProviderDriverError } from "../Errors.ts"; import { makeAntigravityProvider } from "../AntigravityProvider.ts"; import * as ProviderEventLoggers from "../ProviderEventLoggers.ts"; @@ -76,8 +75,7 @@ export type AntigravityDriverEnv = | IdAllocator.IdAllocatorV2 | ModelManifest.ModelManifest | Path.Path - | ProviderEventLoggers.ProviderEventLoggers - | ServerConfig.ServerConfig; + | ProviderEventLoggers.ProviderEventLoggers; /** Each instance owns its Google profile. Executable releases are shared by the environment. */ export const AntigravityDriver: ProviderDriver = { @@ -91,7 +89,7 @@ export const AntigravityDriver: ProviderDriver, ): Effect.fn.Return< - AcpSessionRuntime["Service"], + AcpSessionRuntime.AcpSessionRuntime["Service"], AcpError | ProviderSetupError, Scope.Scope > { @@ -303,8 +301,8 @@ export const AntigravityDriver: ProviderDriver, + started: AcpSessionRuntime.AcpSessionRuntimeStartResult, + runtime: Pick, ): Effect.Effect => Effect.gen(function* () { yield* provider.onSessionStarted(started); @@ -405,7 +403,7 @@ export const AntigravityDriver: ProviderDriver[0] + | Parameters[0] | undefined; return { initialize: () => Effect.succeed(initialized), diff --git a/apps/server/src/provider/acp/AcpRegistryAuth.ts b/apps/server/src/provider/acp/AcpRegistryAuth.ts index 6a885b71112069f276e197a9e4ca0dc1e6612789..3232b7b370a20a75d59b27a37c6afda9953cf235 100644 --- a/apps/server/src/provider/acp/AcpRegistryAuth.ts +++ b/apps/server/src/provider/acp/AcpRegistryAuth.ts @@ -20,7 +20,7 @@ import * as ProviderAuthFlow from "../ProviderAuthFlow.ts"; import { normalizeAcpRegistryAuthMethods, normalizeAcpRegistryWebUrl } from "./AcpRegistryProbe.ts"; import * as AcpRegistrySupport from "./AcpRegistrySupport.ts"; import * as AcpRegistryRuntimeCoordinator from "./AcpRegistryRuntimeCoordinator.ts"; -import * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; +import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; type Runtime = Pick< AcpSessionRuntime.AcpSessionRuntime["Service"], diff --git a/apps/server/src/provider/acp/AcpRegistryProbe.test.ts b/apps/server/src/provider/acp/AcpRegistryProbe.test.ts index 9d5288c957ee58ba42bffd13bb0d349e80f6aa96..37066157fc0b8ac8d6b356e9fcb08eeb52f665ee 100644 --- a/apps/server/src/provider/acp/AcpRegistryProbe.test.ts +++ b/apps/server/src/provider/acp/AcpRegistryProbe.test.ts @@ -12,7 +12,7 @@ import * as Schema from "effect/Schema"; import * as TestClock from "effect/testing/TestClock"; import * as EffectAcpErrors from "effect-acp/errors"; -import type { AcpSessionRuntimeStartResult } from "./AcpSessionRuntime.ts"; +import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import { acpRegistryProbeFailure, acpRegistryProbeResult, @@ -68,7 +68,7 @@ describe("ACP Registry probe", () => { ], }, modelConfigId: "model", - } satisfies AcpSessionRuntimeStartResult); + } satisfies AcpSessionRuntime.AcpSessionRuntimeStartResult); expect(result).toEqual({ instanceId, @@ -186,7 +186,7 @@ describe("ACP Registry probe", () => { ], }, modelConfigId: "model", - } satisfies AcpSessionRuntimeStartResult); + } satisfies AcpSessionRuntime.AcpSessionRuntimeStartResult); expect(result.models).toEqual([ { id: "sonnet", name: "Sonnet", description: "Balanced" }, @@ -216,7 +216,7 @@ describe("ACP Registry probe", () => { ], }, modelConfigId: "model", - } satisfies AcpSessionRuntimeStartResult); + } satisfies AcpSessionRuntime.AcpSessionRuntimeStartResult); expect(result.models).toEqual([{ id: "valid", name: "Valid", description: null }]); expect(result.currentModelId).toBeNull(); @@ -270,7 +270,7 @@ describe("ACP Registry probe", () => { ], }, modelConfigId: "model", - } satisfies AcpSessionRuntimeStartResult); + } satisfies AcpSessionRuntime.AcpSessionRuntimeStartResult); expect(result.models).toEqual([ { id: codexModel, name: "GPT-6.1 Sol", description: null }, @@ -312,7 +312,7 @@ describe("ACP Registry probe", () => { ], }, modelConfigId: "model", - } satisfies AcpSessionRuntimeStartResult); + } satisfies AcpSessionRuntime.AcpSessionRuntimeStartResult); expect(result.models).toHaveLength(256); expect(result.currentModelId).toBeNull(); diff --git a/apps/server/src/provider/acp/AcpRegistryProbe.ts b/apps/server/src/provider/acp/AcpRegistryProbe.ts index 0ee7ea1a878b0bde99d28d684150fecc06b253de..9fc142c35dc3685ee46c5311cd24c15263b40450 100644 --- a/apps/server/src/provider/acp/AcpRegistryProbe.ts +++ b/apps/server/src/provider/acp/AcpRegistryProbe.ts @@ -25,10 +25,10 @@ import type * as EffectAcpSchema from "effect-acp/compat"; import * as PtyAdapter from "../../terminal/PtyAdapter.ts"; import * as AcpRegistrySupport from "./AcpRegistrySupport.ts"; -import { parseSessionModeState } from "./AcpRuntimeModel.ts"; -import { acpProviderOptionDescriptors } from "./AcpSessionConfig.ts"; +import { parseSessionModeState } from "@t3tools/provider-acp/server/runtimeModel"; +import { acpProviderOptionDescriptors } from "@t3tools/provider-acp/server/sessionConfig"; import * as AcpRegistryRuntimeCoordinator from "./AcpRegistryRuntimeCoordinator.ts"; -import * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; +import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; const MAX_AUTH_METHODS = 32; const MAX_MODELS = 256; diff --git a/apps/server/src/provider/acp/AcpRegistrySupport.ts b/apps/server/src/provider/acp/AcpRegistrySupport.ts index c62f93dae4006dc9a5e1162fd2054413f29c627a..dd4ef66f7876d36d151da14f3f3aca2dd31d57b4 100644 --- a/apps/server/src/provider/acp/AcpRegistrySupport.ts +++ b/apps/server/src/provider/acp/AcpRegistrySupport.ts @@ -43,7 +43,7 @@ import { ChildProcess, ChildProcessSpawner } from "effect/process"; import { collectUint8StreamText } from "@t3tools/provider-core/server/collectStreamText"; import * as ServerSettings from "../../serverSettings.ts"; -import type { AcpSpawnInput } from "./AcpSessionRuntime.ts"; +import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; const ACP_REGISTRY_URL = "https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json"; @@ -444,7 +444,7 @@ export function resolveAcpRegistryDistribution(input: { export interface ResolvedAcpRegistryAgent { readonly agent?: AcpRegistryAgent; readonly distribution: AcpRegistryDistributionKind | "local"; - readonly spawn: AcpSpawnInput; + readonly spawn: AcpSessionRuntime.AcpSpawnInput; } export type AcpRegistryInspection = diff --git a/apps/server/src/provider/acp/AcpSessionRuntime.processTree.test.ts b/apps/server/src/provider/acp/AcpSessionRuntime.processTree.test.ts index 9067ee93f096eb97ae7f5ee8c2f15d51550da5f0..13a7dd6c2c81615563d289d915a21c4199a3e55a 100644 --- a/apps/server/src/provider/acp/AcpSessionRuntime.processTree.test.ts +++ b/apps/server/src/provider/acp/AcpSessionRuntime.processTree.test.ts @@ -11,29 +11,7 @@ import * as Effect from "effect/Effect"; import * as Exit from "effect/Exit"; import * as Scope from "effect/Scope"; -import { - capturePosixOwnershipLedger, - isSafeCgroupPath, - makeLinuxCgroupController, - makePosixProcessTreeController, - observePosixOwnershipLedger, - observePosixOwnershipLedgerContinuously, - parseCgroup2Mount, - parseCgroup2Mounts, - parseUnifiedCgroupPath, - posixProcessIsZombie, - resolveLinuxCgroupTargetCommand, - signalLinuxCgroupRootTerm, - sweepStaleLinuxCgroupSiblings, - terminateLinuxCgroupLease, - terminatePosixOwnedProcessTree, - wrapCommandForLinuxCgroup, - type AcpOwnedPosixProcess, - type AcpLinuxCgroupLease, - type AcpPosixOwnershipRoot, - type AcpPosixProcessIdentity, - type AcpPosixProcessTreeController, -} from "./AcpSessionRuntime.ts"; +import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; const threadSpawnHelperSource = NodeURL.fileURLToPath( new URL("../../../scripts/acp-thread-spawn-helper.c", import.meta.url), @@ -46,7 +24,7 @@ const identity = ( sid: number, startTime = String(pid), state = "S", -): AcpPosixProcessIdentity => ({ +): AcpSessionRuntime.AcpPosixProcessIdentity => ({ executable: `/proc/${pid}/exe`, pgid, pid, @@ -57,16 +35,16 @@ const identity = ( }); function makeController(input: { - readonly processes: ReadonlyArray; + readonly processes: ReadonlyArray; readonly onProcess?: ( - processes: Map, + processes: Map, pid: number, signal: NodeJS.Signals, ) => void; }) { const processes = new Map(input.processes.map((process) => [process.pid, process])); const signals: Array = []; - const controller: AcpPosixProcessTreeController = { + const controller: AcpSessionRuntime.AcpPosixProcessTreeController = { childPidsOf: (pid) => [...processes.values()] .filter((process) => process.ppid === pid) @@ -96,19 +74,23 @@ function processExists(pid: number): boolean { describe("terminatePosixOwnedProcessTree", () => { it("parses unified cgroup paths and escaped cgroup2 mountinfo", () => { - expect(parseUnifiedCgroupPath("0::/user.slice/app.scope\n")).toBe("/user.slice/app.scope"); - expect(parseUnifiedCgroupPath("0::/one\n0::/two\n")).toBeUndefined(); - expect(isSafeCgroupPath("/user.slice/app.scope")).toBe(true); - expect(isSafeCgroupPath("/user.slice/../escape")).toBe(false); - expect(isSafeCgroupPath("/user.slice/app.scope (deleted)")).toBe(false); + expect(AcpSessionRuntime.parseUnifiedCgroupPath("0::/user.slice/app.scope\n")).toBe( + "/user.slice/app.scope", + ); + expect(AcpSessionRuntime.parseUnifiedCgroupPath("0::/one\n0::/two\n")).toBeUndefined(); + expect(AcpSessionRuntime.isSafeCgroupPath("/user.slice/app.scope")).toBe(true); + expect(AcpSessionRuntime.isSafeCgroupPath("/user.slice/../escape")).toBe(false); + expect(AcpSessionRuntime.isSafeCgroupPath("/user.slice/app.scope (deleted)")).toBe(false); expect( - parseCgroup2Mount( + AcpSessionRuntime.parseCgroup2Mount( "42 31 0:37 /user.slice /sys/fs/cgroup/user\\040mount rw - cgroup2 cgroup2 rw\n", ), ).toEqual({ mountPoint: "/sys/fs/cgroup/user mount", root: "/user.slice" }); - expect(parseCgroup2Mount("42 31 0:37 / /sys/fs/cgroup rw - tmpfs tmpfs rw\n")).toBeUndefined(); expect( - parseCgroup2Mounts( + AcpSessionRuntime.parseCgroup2Mount("42 31 0:37 / /sys/fs/cgroup rw - tmpfs tmpfs rw\n"), + ).toBeUndefined(); + expect( + AcpSessionRuntime.parseCgroup2Mounts( "41 31 0:36 /other /sys/fs/cgroup/other rw - cgroup2 cgroup2 rw\n" + "42 31 0:37 /user.slice /sys/fs/cgroup/user rw - cgroup2 cgroup2 rw\n", ), @@ -140,7 +122,7 @@ describe("terminatePosixOwnedProcessTree", () => { const unrelated = writeSibling("other-lease", "0"); const isProcessAlive = (pid: number) => pid === process.pid || pid === liveForeignPid; try { - sweepStaleLinuxCgroupSiblings(parent, { + AcpSessionRuntime.sweepStaleLinuxCgroupSiblings(parent, { isProcessAlive, readPopulated: (path) => populatedByPath.get(path), remove: (path) => { @@ -155,7 +137,7 @@ describe("terminatePosixOwnedProcessTree", () => { expect(NodeFS.existsSync(unrelated)).toBe(true); // Missing populated state must not remove a sibling. writeSibling(`t3-acp-${deadPid}-eeee`, null); - sweepStaleLinuxCgroupSiblings(parent, { + AcpSessionRuntime.sweepStaleLinuxCgroupSiblings(parent, { isProcessAlive, readPopulated: (path) => populatedByPath.get(path), remove: (path) => { @@ -174,7 +156,7 @@ describe("terminatePosixOwnedProcessTree", () => { it.live("preserves exact argv and strips wrapper-only environment before exec", () => Effect.gen(function* () { if ((yield* HostProcessPlatform) !== "linux") return; - const lease = makeLinuxCgroupController().create(); + const lease = AcpSessionRuntime.makeLinuxCgroupController().create(); if (lease === undefined) return; const scratchRoot = NodePath.join(process.cwd(), "tmp"); NodeFS.mkdirSync(scratchRoot, { recursive: true }); @@ -192,17 +174,27 @@ describe("terminatePosixOwnedProcessTree", () => { NodeFS.symlinkSync(process.execPath, bareGrok); NodeFS.symlinkSync(process.execPath, NodePath.join(relativeBin, "grok")); NodeFS.symlinkSync(process.execPath, NodePath.join(validBin, "grok")); - expect(resolveLinuxCgroupTargetCommand("grok", scratch, { PATH: scratch })).toBe(bareGrok); - expect(resolveLinuxCgroupTargetCommand("grok", scratch, { PATH: "" })).toBe(bareGrok); + expect( + AcpSessionRuntime.resolveLinuxCgroupTargetCommand("grok", scratch, { PATH: scratch }), + ).toBe(bareGrok); + expect(AcpSessionRuntime.resolveLinuxCgroupTargetCommand("grok", scratch, { PATH: "" })).toBe( + bareGrok, + ); // Undefined PATH uses Node's default search path (/usr/bin:/bin), not cwd alone // (bareGrok lives only in cwd / PATH=scratch). - expect(resolveLinuxCgroupTargetCommand("grok", scratch, { PATH: undefined })).toBeUndefined(); - expect(resolveLinuxCgroupTargetCommand("node", scratch, { PATH: undefined })).toBeDefined(); - expect(resolveLinuxCgroupTargetCommand("grok", scratch, { PATH: "relative-bin" })).toBe( - NodePath.join(relativeBin, "grok"), - ); expect( - resolveLinuxCgroupTargetCommand("grok", scratch, { + AcpSessionRuntime.resolveLinuxCgroupTargetCommand("grok", scratch, { PATH: undefined }), + ).toBeUndefined(); + expect( + AcpSessionRuntime.resolveLinuxCgroupTargetCommand("node", scratch, { PATH: undefined }), + ).toBeDefined(); + expect( + AcpSessionRuntime.resolveLinuxCgroupTargetCommand("grok", scratch, { + PATH: "relative-bin", + }), + ).toBe(NodePath.join(relativeBin, "grok")); + expect( + AcpSessionRuntime.resolveLinuxCgroupTargetCommand("grok", scratch, { PATH: `directory-bin${NodePath.delimiter}valid-bin`, }), ).toBe(NodePath.join(validBin, "grok")); @@ -214,7 +206,7 @@ describe("terminatePosixOwnedProcessTree", () => { " wrapper: process.env.T3_ACP_CGROUP_WRAPPER,", "}));", ].join("\n"); - const wrapped = wrapCommandForLinuxCgroup(lease, linkedNode, [ + const wrapped = AcpSessionRuntime.wrapCommandForLinuxCgroup(lease, linkedNode, [ "-e", target, outputPath, @@ -236,7 +228,7 @@ describe("terminatePosixOwnedProcessTree", () => { '{"args":["space value","single\'quote","double\\"quote"]}', ); } finally { - yield* terminateLinuxCgroupLease(lease).pipe(Effect.ignore); + yield* AcpSessionRuntime.terminateLinuxCgroupLease(lease).pipe(Effect.ignore); NodeFS.rmSync(scratch, { recursive: true, force: true }); } }), @@ -251,9 +243,11 @@ describe("terminatePosixOwnedProcessTree", () => { const outputPath = NodePath.join(scratch, "argv output"); NodeFS.mkdirSync(leasePath); NodeFS.writeFileSync(NodePath.join(leasePath, "cgroup.procs"), ""); - const relativePath = parseUnifiedCgroupPath(NodeFS.readFileSync("/proc/self/cgroup", "utf8")); + const relativePath = AcpSessionRuntime.parseUnifiedCgroupPath( + NodeFS.readFileSync("/proc/self/cgroup", "utf8"), + ); expect(relativePath).toBeDefined(); - const lease: AcpLinuxCgroupLease = { + const lease: AcpSessionRuntime.AcpLinuxCgroupLease = { contains: () => false, exists: () => true, path: leasePath, @@ -264,7 +258,7 @@ describe("terminatePosixOwnedProcessTree", () => { }; const packagedExecPath = vi.spyOn(process, "execPath", "get").mockReturnValue("/bin/sh"); try { - const wrapped = wrapCommandForLinuxCgroup(lease, "/bin/sh", [ + const wrapped = AcpSessionRuntime.wrapCommandForLinuxCgroup(lease, "/bin/sh", [ "-c", 'printf "%s\\n" "$0" "$1" "$2" "$3" "${ELECTRON_RUN_AS_NODE-}" "${T3_ACP_CGROUP_WRAPPER-}" > "$4"', "packaged-target", @@ -289,7 +283,7 @@ describe("terminatePosixOwnedProcessTree", () => { /^\d+\n$/, ); - const mismatch = wrapCommandForLinuxCgroup( + const mismatch = AcpSessionRuntime.wrapCommandForLinuxCgroup( { ...lease, relativePath: "/not-the-current-cgroup" }, "/bin/sh", ["-c", 'printf executed > "$0"', outputPath], @@ -301,7 +295,11 @@ describe("terminatePosixOwnedProcessTree", () => { expect(mismatchResult.status, mismatchResult.stderr).toBe(126); expect(NodeFS.existsSync(outputPath)).toBe(false); - const missingTarget = wrapCommandForLinuxCgroup(lease, "/nonexistent-t3-probe", []); + const missingTarget = AcpSessionRuntime.wrapCommandForLinuxCgroup( + lease, + "/nonexistent-t3-probe", + [], + ); const missingTargetResult = NodeChildProcess.spawnSync( missingTarget.command, missingTarget.args, @@ -319,12 +317,12 @@ describe("terminatePosixOwnedProcessTree", () => { it.live("kills a post-TERM detached double fork without touching an unrelated sentinel", () => Effect.gen(function* () { if ((yield* HostProcessPlatform) !== "linux") return; - const controller = makeLinuxCgroupController(); + const controller = AcpSessionRuntime.makeLinuxCgroupController(); const lease = controller.create(); if (lease === undefined) return; - expect(parseUnifiedCgroupPath(NodeFS.readFileSync("/proc/self/cgroup", "utf8"))).not.toBe( - lease.relativePath, - ); + expect( + AcpSessionRuntime.parseUnifiedCgroupPath(NodeFS.readFileSync("/proc/self/cgroup", "utf8")), + ).not.toBe(lease.relativePath); const scratchRoot = NodePath.join(process.cwd(), "tmp"); NodeFS.mkdirSync(scratchRoot, { recursive: true }); const scratch = NodeFS.mkdtempSync(NodePath.join(scratchRoot, "acp-cgroup-kill-")); @@ -349,7 +347,7 @@ describe("terminatePosixOwnedProcessTree", () => { "});", "setInterval(() => {}, 1000);", ].join("\n"); - const wrapped = wrapCommandForLinuxCgroup(lease, process.execPath, [ + const wrapped = AcpSessionRuntime.wrapCommandForLinuxCgroup(lease, process.execPath, [ "-e", providerProgram, readyPath, @@ -386,7 +384,7 @@ describe("terminatePosixOwnedProcessTree", () => { } }).pipe(Effect.timeout("2 seconds")); expect(processExists(detachedChildPid)).toBe(true); - yield* terminateLinuxCgroupLease(lease); + yield* AcpSessionRuntime.terminateLinuxCgroupLease(lease); expect(processExists(sentinel.pid!)).toBe(true); yield* Effect.gen(function* () { while (processExists(detachedChildPid!)) yield* Effect.sleep("10 millis"); @@ -397,11 +395,11 @@ describe("terminatePosixOwnedProcessTree", () => { expect(replacement?.path).not.toBe(lease.path); if (replacement !== undefined) { NodeFS.mkdirSync(NodePath.join(replacement.path, "nested")); - yield* terminateLinuxCgroupLease(replacement); + yield* AcpSessionRuntime.terminateLinuxCgroupLease(replacement); expect(NodeFS.existsSync(replacement.path)).toBe(false); } } finally { - yield* terminateLinuxCgroupLease(lease).pipe(Effect.ignore); + yield* AcpSessionRuntime.terminateLinuxCgroupLease(lease).pipe(Effect.ignore); try { process.kill(-provider.pid!, "SIGKILL"); } catch { @@ -430,7 +428,7 @@ describe("terminatePosixOwnedProcessTree", () => { let killCalls = 0; let populated = false; let removeCalls = 0; - const lease: AcpLinuxCgroupLease = { + const lease: AcpSessionRuntime.AcpLinuxCgroupLease = { contains: () => false, exists: () => exists, path: "/test/t3-acp-repopulation", @@ -457,11 +455,11 @@ describe("terminatePosixOwnedProcessTree", () => { }, }; - yield* terminateLinuxCgroupLease(lease); + yield* AcpSessionRuntime.terminateLinuxCgroupLease(lease); expect(killCalls).toBeGreaterThanOrEqual(3); expect(removeCalls).toBe(3); expect(exists).toBe(false); - yield* terminateLinuxCgroupLease(lease); + yield* AcpSessionRuntime.terminateLinuxCgroupLease(lease); expect(removeCalls).toBe(3); }), ); @@ -471,7 +469,7 @@ describe("terminatePosixOwnedProcessTree", () => { const removeError = Object.assign(new Error("cgroup remains busy"), { code: "EBUSY", }); - const lease: AcpLinuxCgroupLease = { + const lease: AcpSessionRuntime.AcpLinuxCgroupLease = { contains: () => false, exists: () => true, path: "/test/t3-acp-busy", @@ -483,7 +481,7 @@ describe("terminatePosixOwnedProcessTree", () => { }, }; - const error = yield* Effect.flip(terminateLinuxCgroupLease(lease)); + const error = yield* Effect.flip(AcpSessionRuntime.terminateLinuxCgroupLease(lease)); expect(error.detail).toBe("Failed to remove ACP cgroup /test/t3-acp-busy"); expect(error.cause).toBe(removeError); }), @@ -493,13 +491,16 @@ describe("terminatePosixOwnedProcessTree", () => { const fixture = makeController({ processes: [server(), identity(100, process.pid, 100, 100, "owned")], }); - const ownedRoot: AcpOwnedPosixProcess = { + const ownedRoot: AcpSessionRuntime.AcpOwnedPosixProcess = { ...identity(100, process.pid, 100, 100, "owned"), parentExecutable: server().executable, parentStartTime: server().startTime, }; - const root: AcpPosixOwnershipRoot = { captureAttempted: true, value: ownedRoot }; - const lease: AcpLinuxCgroupLease = { + const root: AcpSessionRuntime.AcpPosixOwnershipRoot = { + captureAttempted: true, + value: ownedRoot, + }; + const lease: AcpSessionRuntime.AcpLinuxCgroupLease = { contains: () => true, exists: () => true, path: "/test/t3-acp-root", @@ -508,19 +509,19 @@ describe("terminatePosixOwnedProcessTree", () => { populated: () => true, remove: () => undefined, }; - signalLinuxCgroupRootTerm({ controller: fixture.controller, lease, root }); + AcpSessionRuntime.signalLinuxCgroupRootTerm({ controller: fixture.controller, lease, root }); expect(fixture.signals).toEqual(["process:100:SIGTERM"]); const reused = makeController({ processes: [server(), identity(100, process.pid, 100, 100, "reused")], }); - signalLinuxCgroupRootTerm({ controller: reused.controller, lease, root }); + AcpSessionRuntime.signalLinuxCgroupRootTerm({ controller: reused.controller, lease, root }); expect(reused.signals).toEqual([]); const migrated = makeController({ processes: [server(), identity(100, process.pid, 100, 100, "owned")], }); - signalLinuxCgroupRootTerm({ + AcpSessionRuntime.signalLinuxCgroupRootTerm({ controller: migrated.controller, lease: { ...lease, contains: () => false }, root, @@ -565,9 +566,9 @@ describe("terminatePosixOwnedProcessTree", () => { }).pipe(Effect.timeout("2 seconds")); const [workerTid, childPid] = published; expect(workerTid).not.toBe(helper.pid); - expect(makePosixProcessTreeController("linux").childrenOf(helper.pid!)).toContainEqual( - expect.objectContaining({ pid: childPid, ppid: helper.pid }), - ); + expect( + AcpSessionRuntime.makePosixProcessTreeController("linux").childrenOf(helper.pid!), + ).toContainEqual(expect.objectContaining({ pid: childPid, ppid: helper.pid })); } finally { try { process.kill(-helper.pid!, "SIGKILL"); @@ -585,11 +586,11 @@ describe("terminatePosixOwnedProcessTree", () => { const fixture = makeController({ processes: [server(), identity(100, process.pid, 100, 100), beforeExec], }); - const frontier = new Map(); + const frontier = new Map(); const childQueues = new Map>(); - const ledger = new Map(); - const root: AcpPosixOwnershipRoot = { value: undefined }; - observePosixOwnershipLedger({ + const ledger = new Map(); + const root: AcpSessionRuntime.AcpPosixOwnershipRoot = { value: undefined }; + AcpSessionRuntime.observePosixOwnershipLedger({ childQueues, controller: fixture.controller, frontier, @@ -598,7 +599,7 @@ describe("terminatePosixOwnedProcessTree", () => { rootPid: 100, }); fixture.processes.set(110, { ...beforeExec, executable: "/usr/bin/bash" }); - observePosixOwnershipLedger({ + AcpSessionRuntime.observePosixOwnershipLedger({ childQueues, controller: fixture.controller, frontier, @@ -610,7 +611,7 @@ describe("terminatePosixOwnedProcessTree", () => { expect([...ledger.values()].find((process) => process.pid === 110)?.executable).toBe( "/usr/bin/bash", ); - yield* terminatePosixOwnedProcessTree({ + yield* AcpSessionRuntime.terminatePosixOwnedProcessTree({ controller: fixture.controller, grace: 0, ledger, @@ -623,13 +624,13 @@ describe("terminatePosixOwnedProcessTree", () => { it("never adopts a replacement PID after initial root capture failed", () => { const fixture = makeController({ processes: [server()] }); - const frontier = new Map(); + const frontier = new Map(); const childQueues = new Map>(); - const ledger = new Map(); - const root: AcpPosixOwnershipRoot = { value: undefined }; + const ledger = new Map(); + const root: AcpSessionRuntime.AcpPosixOwnershipRoot = { value: undefined }; const capture = () => { try { - observePosixOwnershipLedger({ + AcpSessionRuntime.observePosixOwnershipLedger({ childQueues, controller: fixture.controller, frontier, @@ -663,7 +664,7 @@ describe("terminatePosixOwnedProcessTree", () => { const fixture = makeController({ processes: [server(), identity(100, process.pid, 100, 100)], }); - const controller: AcpPosixProcessTreeController = { + const controller: AcpSessionRuntime.AcpPosixProcessTreeController = { ...fixture.controller, childPidsOf: (pid) => { childListReads += 1; @@ -678,10 +679,10 @@ describe("terminatePosixOwnedProcessTree", () => { return fixture.controller.snapshot(); }, }; - const frontier = new Map(); + const frontier = new Map(); const childQueues = new Map>(); - const ledger = new Map(); - const root: AcpPosixOwnershipRoot = { value: undefined }; + const ledger = new Map(); + const root: AcpSessionRuntime.AcpPosixOwnershipRoot = { value: undefined }; for (let index = 0; index < 5_000; index += 1) { const tombstone = identity(100_000 + index, 1, 100_000 + index, 100_000 + index); ledger.set(`${tombstone.pid}:${tombstone.startTime}`, { @@ -690,7 +691,7 @@ describe("terminatePosixOwnedProcessTree", () => { parentStartTime: "", }); } - observePosixOwnershipLedger({ + AcpSessionRuntime.observePosixOwnershipLedger({ childQueues, controller, frontier, @@ -714,7 +715,7 @@ describe("terminatePosixOwnedProcessTree", () => { ) { childListReads = 0; identityCalls = 0; - observePosixOwnershipLedger({ + AcpSessionRuntime.observePosixOwnershipLedger({ childQueues, controller, frontier, @@ -732,7 +733,7 @@ describe("terminatePosixOwnedProcessTree", () => { ); expect(missing, `missing after ${passes} passes`).toEqual([]); expect(passes).toBeGreaterThan(2); - yield* terminatePosixOwnedProcessTree({ + yield* AcpSessionRuntime.terminatePosixOwnedProcessTree({ controller, grace: 0, ledger, @@ -751,7 +752,7 @@ describe("terminatePosixOwnedProcessTree", () => { const fixture = makeController({ processes: [server(), identity(100, process.pid, 100, 100), identity(110, 100, 110, 110)], }); - const controller: AcpPosixProcessTreeController = { + const controller: AcpSessionRuntime.AcpPosixProcessTreeController = { ...fixture.controller, childPidsOf: (pid) => { childrenCalls += 1; @@ -767,16 +768,16 @@ describe("terminatePosixOwnedProcessTree", () => { }, }; const scope = yield* Scope.make(); - const frontier = new Map(); + const frontier = new Map(); const childQueues = new Map>(); let ledgerValuesCalls = 0; - const ledger = new (class extends Map { - override values(): MapIterator { + const ledger = new (class extends Map { + override values(): MapIterator { ledgerValuesCalls += 1; return super.values(); } })(); - const root: AcpPosixOwnershipRoot = { value: undefined }; + const root: AcpSessionRuntime.AcpPosixOwnershipRoot = { value: undefined }; for (let index = 0; index < 5_000; index += 1) { const tombstone = identity(10_000 + index, 1, 10_000 + index, 10_000 + index); ledger.set(`${tombstone.pid}:${tombstone.startTime}`, { @@ -785,7 +786,7 @@ describe("terminatePosixOwnedProcessTree", () => { parentStartTime: "", }); } - yield* observePosixOwnershipLedgerContinuously({ + yield* AcpSessionRuntime.observePosixOwnershipLedgerContinuously({ childQueues, controller, frontier, @@ -831,7 +832,7 @@ describe("terminatePosixOwnedProcessTree", () => { }, }); - yield* terminatePosixOwnedProcessTree({ + yield* AcpSessionRuntime.terminatePosixOwnedProcessTree({ controller: fixture.controller, grace: 0, rootPid: 100, @@ -865,7 +866,7 @@ describe("terminatePosixOwnedProcessTree", () => { }, }); - yield* terminatePosixOwnedProcessTree({ + yield* AcpSessionRuntime.terminatePosixOwnedProcessTree({ controller: fixture.controller, grace: 0, rootPid: 100, @@ -893,7 +894,7 @@ describe("terminatePosixOwnedProcessTree", () => { }); const result = yield* Effect.exit( - terminatePosixOwnedProcessTree({ + AcpSessionRuntime.terminatePosixOwnedProcessTree({ controller: fixture.controller, grace: 0, rootPid: 100, @@ -913,9 +914,13 @@ describe("terminatePosixOwnedProcessTree", () => { it.live("does not treat zombie residual entries as teardown survivors", () => Effect.gen(function* () { - expect(posixProcessIsZombie({ ...identity(1, 0, 1, 1), state: "Z" })).toBe(true); - expect(posixProcessIsZombie({ ...identity(1, 0, 1, 1), state: "S" })).toBe(false); - const withoutState: AcpPosixProcessIdentity = { + expect(AcpSessionRuntime.posixProcessIsZombie({ ...identity(1, 0, 1, 1), state: "Z" })).toBe( + true, + ); + expect(AcpSessionRuntime.posixProcessIsZombie({ ...identity(1, 0, 1, 1), state: "S" })).toBe( + false, + ); + const withoutState: AcpSessionRuntime.AcpPosixProcessIdentity = { executable: "/proc/1/exe", pgid: 1, pid: 1, @@ -923,7 +928,7 @@ describe("terminatePosixOwnedProcessTree", () => { sid: 1, startTime: "1", }; - expect(posixProcessIsZombie(withoutState)).toBe(false); + expect(AcpSessionRuntime.posixProcessIsZombie(withoutState)).toBe(false); const root = identity(100, process.pid, 100, 100); const zombieChild = identity(110, 100, 110, 110, "110", "Z"); @@ -936,7 +941,7 @@ describe("terminatePosixOwnedProcessTree", () => { processes.set(pid, { ...current, state: "Z" }); }, }); - yield* terminatePosixOwnedProcessTree({ + yield* AcpSessionRuntime.terminatePosixOwnedProcessTree({ controller: fixture.controller, grace: 0, rootPid: 100, @@ -948,19 +953,19 @@ describe("terminatePosixOwnedProcessTree", () => { ); it("admits a live child after a free PID was previously reserved by a dead entry", () => { - const staleChild: AcpOwnedPosixProcess = { + const staleChild: AcpSessionRuntime.AcpOwnedPosixProcess = { ...identity(200, 100, 200, 200, "stale-child"), parentExecutable: `/proc/100/exe`, parentStartTime: "100", }; const liveChild = identity(200, 100, 200, 200, "live-child"); const root = identity(100, process.pid, 100, 100); - const ownedRoot: AcpOwnedPosixProcess = { + const ownedRoot: AcpSessionRuntime.AcpOwnedPosixProcess = { ...root, parentExecutable: `/proc/${process.pid}/exe`, parentStartTime: "server", }; - const ledger = new Map([ + const ledger = new Map([ [`100:${root.startTime}`, ownedRoot], [`200:${staleChild.startTime}`, staleChild], ]); @@ -969,7 +974,7 @@ describe("terminatePosixOwnedProcessTree", () => { }).controller; // First capture: PID 200 is free, so the dead reservation is dropped. - capturePosixOwnershipLedger({ + AcpSessionRuntime.capturePosixOwnershipLedger({ controller, ledger, rootPid: 100, @@ -978,7 +983,7 @@ describe("terminatePosixOwnedProcessTree", () => { expect([...ledger.values()].some((entry) => entry.pid === 200)).toBe(false); // Second capture: a new process reuses PID 200 under the owned parent. - capturePosixOwnershipLedger({ + AcpSessionRuntime.capturePosixOwnershipLedger({ controller: makeController({ processes: [server(), root, liveChild] }).controller, ledger, rootPid: 100, @@ -990,24 +995,24 @@ describe("terminatePosixOwnedProcessTree", () => { }); it("admits a live child when a stale ledger entry still occupies the reused PID", () => { - const staleChild: AcpOwnedPosixProcess = { + const staleChild: AcpSessionRuntime.AcpOwnedPosixProcess = { ...identity(200, 100, 200, 200, "stale-child"), parentExecutable: `/proc/100/exe`, parentStartTime: "100", }; const liveChild = identity(200, 100, 200, 200, "live-child"); const root = identity(100, process.pid, 100, 100); - const ownedRoot: AcpOwnedPosixProcess = { + const ownedRoot: AcpSessionRuntime.AcpOwnedPosixProcess = { ...root, parentExecutable: `/proc/${process.pid}/exe`, parentStartTime: "server", }; - const ledger = new Map([ + const ledger = new Map([ [`100:${root.startTime}`, ownedRoot], [`200:${staleChild.startTime}`, staleChild], ]); - capturePosixOwnershipLedger({ + AcpSessionRuntime.capturePosixOwnershipLedger({ controller: makeController({ processes: [server(), root, liveChild] }).controller, ledger, rootPid: 100, @@ -1040,7 +1045,7 @@ describe("terminatePosixOwnedProcessTree", () => { }, }); - yield* terminatePosixOwnedProcessTree({ + yield* AcpSessionRuntime.terminatePosixOwnedProcessTree({ controller: fixture.controller, grace: 0, rootPid: 100, @@ -1064,7 +1069,7 @@ describe("terminatePosixOwnedProcessTree", () => { }, }); let snapshotCalls = 0; - const controller: AcpPosixProcessTreeController = { + const controller: AcpSessionRuntime.AcpPosixProcessTreeController = { ...fixture.controller, snapshot: () => { snapshotCalls += 1; @@ -1076,7 +1081,7 @@ describe("terminatePosixOwnedProcessTree", () => { }; const error = yield* Effect.flip( - terminatePosixOwnedProcessTree({ + AcpSessionRuntime.terminatePosixOwnedProcessTree({ controller, discoveryPasses: 2, grace: 0, @@ -1092,10 +1097,10 @@ describe("terminatePosixOwnedProcessTree", () => { it.live("retains the ledger across root exit and an explicit failure for finalizer retry", () => Effect.gen(function* () { let ignoreSignals = true; - const ledger = new Map(); - const frontier = new Map(); + const ledger = new Map(); + const frontier = new Map(); const childQueues = new Map>(); - const root: AcpPosixOwnershipRoot = { value: undefined }; + const root: AcpSessionRuntime.AcpPosixOwnershipRoot = { value: undefined }; const fixture = makeController({ processes: [ server(), @@ -1108,7 +1113,7 @@ describe("terminatePosixOwnedProcessTree", () => { if (!ignoreSignals) processes.delete(pid); }, }); - observePosixOwnershipLedger({ + AcpSessionRuntime.observePosixOwnershipLedger({ childQueues, controller: fixture.controller, frontier, @@ -1118,7 +1123,7 @@ describe("terminatePosixOwnedProcessTree", () => { }); const explicit = yield* Effect.exit( - terminatePosixOwnedProcessTree({ + AcpSessionRuntime.terminatePosixOwnedProcessTree({ controller: fixture.controller, grace: 0, ledger, @@ -1130,7 +1135,7 @@ describe("terminatePosixOwnedProcessTree", () => { expect(fixture.processes.has(111)).toBe(true); fixture.processes.set(112, identity(112, 110, 112, 112)); - observePosixOwnershipLedger({ + AcpSessionRuntime.observePosixOwnershipLedger({ childQueues, controller: fixture.controller, frontier, @@ -1139,7 +1144,7 @@ describe("terminatePosixOwnedProcessTree", () => { rootPid: 100, }); ignoreSignals = false; - yield* terminatePosixOwnedProcessTree({ + yield* AcpSessionRuntime.terminatePosixOwnedProcessTree({ controller: fixture.controller, grace: 0, ledger, @@ -1153,7 +1158,7 @@ describe("terminatePosixOwnedProcessTree", () => { it("fails closed where a stable POSIX identity provider is unavailable", () => { try { - makePosixProcessTreeController("darwin"); + AcpSessionRuntime.makePosixProcessTreeController("darwin"); throw new Error("Expected Darwin process ownership to fail closed"); } catch (error) { expect(error).toMatchObject({ diff --git a/apps/server/src/provider/acp/AntigravityAcpSupport.ts b/apps/server/src/provider/acp/AntigravityAcpSupport.ts index a3aa8005cfb13dccfc7ec4c9db3fa8f969a9eda0..d03ce73d09e225b5ba65681fb78de40b656963b8 100644 --- a/apps/server/src/provider/acp/AntigravityAcpSupport.ts +++ b/apps/server/src/provider/acp/AntigravityAcpSupport.ts @@ -22,7 +22,7 @@ import { makeAntigravityStderrHandler, makeAntigravityStdoutTransform, } from "../antigravityAuthSupport.ts"; -import * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; +import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import { normalizeAntigravitySessionUpdate } from "./AntigravityProtocol.ts"; export interface AntigravityAcpRuntimeInput extends Omit< diff --git a/apps/server/src/provider/acp/AntigravityProtocol.test.ts b/apps/server/src/provider/acp/AntigravityProtocol.test.ts index 0a628eb03c565fe7dd9c7f6066b8f9d1c0cdf4c3..cfc7a6adfbe19d75485481df385ac5387285e834 100644 --- a/apps/server/src/provider/acp/AntigravityProtocol.test.ts +++ b/apps/server/src/provider/acp/AntigravityProtocol.test.ts @@ -17,7 +17,10 @@ import { sanitizeAntigravityToolPayload, selectAntigravityPermissionOptionId, } from "./AntigravityProtocol.ts"; -import { mergeToolCallState, parseSessionUpdateEvent } from "./AcpRuntimeModel.ts"; +import { + mergeToolCallState, + parseSessionUpdateEvent, +} from "@t3tools/provider-acp/server/runtimeModel"; const isSessionNotification = Schema.is(AcpWireSchema.SessionNotification); diff --git a/apps/server/src/provider/acp/AntigravityProtocol.ts b/apps/server/src/provider/acp/AntigravityProtocol.ts index 77eff09f7e876db67cd4b60f0a2b108027ffa81d..3f99288328d4a1c8d550228746473aade06400e7 100644 --- a/apps/server/src/provider/acp/AntigravityProtocol.ts +++ b/apps/server/src/provider/acp/AntigravityProtocol.ts @@ -11,7 +11,7 @@ import * as Schema from "effect/Schema"; import type * as EffectAcpSchema from "effect-acp/compat"; import * as AcpWireSchema from "effect-acp/schema-v1"; -import type { AcpToolCallState } from "./AcpRuntimeModel.ts"; +import type { AcpToolCallState } from "@t3tools/provider-acp/server/runtimeModel"; const TOOL_TEXT_LIMIT = 8_000; const TOOL_TEXT_TRUNCATED = "[Earlier output truncated]\n\n"; diff --git a/apps/server/src/provider/acp/GrokAcpSupport.ts b/apps/server/src/provider/acp/GrokAcpSupport.ts index 0039a12683b8c95701590e7f502adabe3b192968..57b4c8fb9d421145613af2f2041ad4f1142960fb 100644 --- a/apps/server/src/provider/acp/GrokAcpSupport.ts +++ b/apps/server/src/provider/acp/GrokAcpSupport.ts @@ -15,7 +15,7 @@ import * as EffectAcpErrors from "effect-acp/errors"; import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; import { normalizeModelSlug } from "@t3tools/shared/model"; -import * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; +import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import { makeXAiPromptCompletionRuntime } from "./XAiAcpExtension.ts"; const GROK_API_KEY_ENV = "XAI_API_KEY"; diff --git a/apps/server/src/provider/acp/XAiAcpExtension.test.ts b/apps/server/src/provider/acp/XAiAcpExtension.test.ts index f4282006f98dfa64be0c078b6b84065ebcabd450..84e5511785b40de5c52abd1b1d32fdcfadb174eb 100644 --- a/apps/server/src/provider/acp/XAiAcpExtension.test.ts +++ b/apps/server/src/provider/acp/XAiAcpExtension.test.ts @@ -34,12 +34,12 @@ import { xAiSubagentFinishedNotice, XAiAskUserQuestionRequest, } from "./XAiAcpExtension.ts"; -import * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; +import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import { type AcpToolCallState, mergeToolCallState, parseSessionUpdateEvent, -} from "./AcpRuntimeModel.ts"; +} from "@t3tools/provider-acp/server/runtimeModel"; const decodeXAiAskUserQuestionRequest = Schema.decodeUnknownSync(XAiAskUserQuestionRequest); diff --git a/apps/server/src/provider/acp/XAiAcpExtension.ts b/apps/server/src/provider/acp/XAiAcpExtension.ts index 94d278cfa5a9c0b13554ac9b5ebe6b4a4c4336da..4c424a664d903f54ff19132bccccd0cef55f8f06 100644 --- a/apps/server/src/provider/acp/XAiAcpExtension.ts +++ b/apps/server/src/provider/acp/XAiAcpExtension.ts @@ -11,8 +11,8 @@ import * as Schema from "effect/Schema"; import * as EffectAcpErrors from "effect-acp/errors"; import type * as EffectAcpSchema from "effect-acp/compat"; -import type * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; -import type { AcpToolCallState } from "./AcpRuntimeModel.ts"; +import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; +import type { AcpToolCallState } from "@t3tools/provider-acp/server/runtimeModel"; const xAiStopReasonMissingMetaKey = "xAiStopReasonMissing"; export const xAiRateLimitedErrorCode = -32003; diff --git a/apps/server/src/provider/antigravityAuthSupport.ts b/apps/server/src/provider/antigravityAuthSupport.ts index ea5aff4b4c77468302eaefa85012e15930759595..c4816709a2f67c2ce9fe542812b7109cdd592637 100644 --- a/apps/server/src/provider/antigravityAuthSupport.ts +++ b/apps/server/src/provider/antigravityAuthSupport.ts @@ -17,7 +17,7 @@ import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; import * as AcpErrors from "effect-acp/errors"; import { collectUint8StreamText } from "@t3tools/provider-core/server/collectStreamText"; -import type { AcpSpawnInput } from "./acp/AcpSessionRuntime.ts"; +import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import { antigravityUserSkillDirectories, resolveAntigravityUserHome, @@ -440,7 +440,7 @@ export function buildAntigravityAcpSpawnInput(input: { readonly auth?: AntigravityAuthConfig; /** Per-process temp directory. Defaults to the profile's shared temp directory. */ readonly runtimeTempDirectory?: string; -}): AcpSpawnInput { +}): AcpSessionRuntime.AcpSpawnInput { return { command: input.installation.executablePath, args: input.profile.platform === "linux" ? ["--uid="] : [], diff --git a/apps/server/src/textGeneration/AntigravityTextGeneration.test.ts b/apps/server/src/textGeneration/AntigravityTextGeneration.test.ts index 4fab9e92b9f5e4ebfbc7700d2061d0a94c1c08a1..454c683896d2bfb4873af3888cdc26495ec0b983 100644 --- a/apps/server/src/textGeneration/AntigravityTextGeneration.test.ts +++ b/apps/server/src/textGeneration/AntigravityTextGeneration.test.ts @@ -20,7 +20,7 @@ import { type AcpError, AcpRequestError } from "effect-acp/errors"; import type * as AcpSchema from "effect-acp/compat"; import { expect } from "vite-plus/test"; -import type { AcpSessionRuntimeEvent } from "../provider/acp/AcpSessionRuntime.ts"; +import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import { removeAntigravitySessionFiles } from "../provider/acp/AntigravitySessionFiles.ts"; import { @@ -121,7 +121,7 @@ const makeFixture = Effect.fn("makeAntigravityTextGenerationFixture")(function* const makeRuntime: AntigravityTextGenerationOptions["makeRuntime"] = (cwd) => Effect.gen(function* () { - const events = yield* Queue.unbounded(); + const events = yield* Queue.unbounded(); state.workspaces.push(cwd); expect(yield* fs.readDirectory(cwd).pipe(Effect.orDie)).toEqual([]); yield* Effect.addFinalizer(() => diff --git a/apps/server/src/textGeneration/AntigravityTextGeneration.ts b/apps/server/src/textGeneration/AntigravityTextGeneration.ts index 2ff9cb659e8b2102e06b9ddee910ecdb627672fc..2c06b082feef44966359ac01ab7bdadb661362ce 100644 --- a/apps/server/src/textGeneration/AntigravityTextGeneration.ts +++ b/apps/server/src/textGeneration/AntigravityTextGeneration.ts @@ -13,7 +13,7 @@ import { type AcpError, AcpRequestError } from "effect-acp/errors"; import { applyAntigravityAcpModelSelection } from "../provider/acp/AntigravityAcpSupport.ts"; import { removeAntigravitySessionFiles } from "../provider/acp/AntigravitySessionFiles.ts"; -import type { AcpSessionRuntime } from "../provider/acp/AcpSessionRuntime.ts"; +import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; import * as TextGenerationOperations from "@t3tools/provider-core/server/textGenerationOperations"; const ANTIGRAVITY_TIMEOUT_MS = 180_000; @@ -25,7 +25,7 @@ const decodeConfiguration = Schema.decodeEffect(Schema.fromJsonString(Configurat const decodeConfigurationObject = Schema.decodeUnknownEffect(Configuration); type AntigravityTextRuntime = Pick< - AcpSessionRuntime["Service"], + AcpSessionRuntime.AcpSessionRuntime["Service"], | "start" | "setMode" | "getConfigOptions" diff --git a/docs/internals/adding-a-provider.md b/docs/internals/adding-a-provider.md index b442053c8001c809e729ff5bebf19a482b79b6be..518e3ea05b23ff6f9124b455927dc5952b45d39c 100644 --- a/docs/internals/adding-a-provider.md +++ b/docs/internals/adding-a-provider.md @@ -10,7 +10,7 @@ whether a turn runs. This page lists the decisions and evidence a new driver nee - **ACP agents** start as [ACP Registry](../user/providers-acp.md) entries, which follow the ACP spec with no per-agent handling. An agent gets a dedicated driver only when it needs behavior the spec does not cover, and then it is a small flavor over the - [shared ACP adapter](../../apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.ts), like Grok + [shared ACP adapter](../../packages/provider-acp/src/server/adapter.ts), like Grok and Antigravity. Never add agent-id checks to the generic registry adapter. - **Other protocols** get a native adapter that implements [`ProviderAdapterV2`](../../packages/provider-core/src/server/ProviderAdapter.ts), like Codex, diff --git a/package.json b/package.json index 545a4247c098df9650aadf7f163f536f70645b96..f85d50c4a2268dda8ca075b4299b09528be9d9a6 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "tc": "vp run -r --concurrency-limit 2 typecheck", "lint": "vp lint --report-unused-disable-directives", "knip": "knip --preprocessor ./scripts/knip-schemas.ts", - "knip:check": "knip --include files,dependencies --no-config-hints && knip --workspace apps/server --workspace apps/desktop --workspace apps/web --workspace packages/client-runtime --workspace packages/contracts --workspace packages/effect-acp --workspace packages/effect-codex-app-server --workspace packages/shared --workspace packages/ssh --workspace packages/tailscale --workspace packages/provider-core --workspace packages/provider-testing --workspace packages/provider-pi --workspace packages/provider-muse --workspace packages/provider-opencode --workspace packages/provider-cursor --exports --preprocessor ./scripts/knip-schemas.ts --no-config-hints", + "knip:check": "knip --include files,dependencies --no-config-hints && knip --workspace apps/server --workspace apps/desktop --workspace apps/web --workspace packages/client-runtime --workspace packages/contracts --workspace packages/effect-acp --workspace packages/effect-codex-app-server --workspace packages/shared --workspace packages/ssh --workspace packages/tailscale --workspace packages/provider-core --workspace packages/provider-acp --workspace packages/provider-testing --workspace packages/provider-pi --workspace packages/provider-muse --workspace packages/provider-opencode --workspace packages/provider-cursor --exports --preprocessor ./scripts/knip-schemas.ts --no-config-hints", "knip:production": "knip --production --preprocessor ./scripts/knip-schemas.ts", "lint:mobile": "node scripts/mobile-native-static-check.ts", "test": "vp run -r test", diff --git a/packages/provider-acp/package.json b/packages/provider-acp/package.json new file mode 100644 index 0000000000000000000000000000000000000000..f3bbfa0dad3855e9f7650295f2317ad135e6f69e --- /dev/null +++ b/packages/provider-acp/package.json @@ -0,0 +1,65 @@ +{ + "name": "@t3tools/provider-acp", + "private": true, + "type": "module", + "exports": { + "./server/AcpSessionRuntime": { + "types": "./src/server/AcpSessionRuntime.ts", + "import": "./src/server/AcpSessionRuntime.ts" + }, + "./server/adapter": { + "types": "./src/server/adapter.ts", + "import": "./src/server/adapter.ts" + }, + "./server/clientPolicy": { + "types": "./src/server/clientPolicy.ts", + "import": "./src/server/clientPolicy.ts" + }, + "./server/clientTerminals": { + "types": "./src/server/clientTerminals.ts", + "import": "./src/server/clientTerminals.ts" + }, + "./server/coreRuntimeEvents": { + "types": "./src/server/coreRuntimeEvents.ts", + "import": "./src/server/coreRuntimeEvents.ts" + }, + "./server/mcpOverAcpBridge": { + "types": "./src/server/mcpOverAcpBridge.ts", + "import": "./src/server/mcpOverAcpBridge.ts" + }, + "./server/nativeLogging": { + "types": "./src/server/nativeLogging.ts", + "import": "./src/server/nativeLogging.ts" + }, + "./server/runtimeModel": { + "types": "./src/server/runtimeModel.ts", + "import": "./src/server/runtimeModel.ts" + }, + "./server/sessionConfig": { + "types": "./src/server/sessionConfig.ts", + "import": "./src/server/sessionConfig.ts" + }, + "./server/stderr": { + "types": "./src/server/stderr.ts", + "import": "./src/server/stderr.ts" + } + }, + "scripts": { + "typecheck": "tsc --noEmit", + "test": "vp test run --config ../../vite.config.ts --dir ." + }, + "dependencies": { + "@t3tools/contracts": "workspace:*", + "@t3tools/provider-core": "workspace:*", + "@t3tools/shared": "workspace:*", + "diff": "8.0.3", + "effect": "catalog:" + }, + "devDependencies": { + "@effect/platform-node": "catalog:", + "@effect/vitest": "catalog:", + "@types/node": "catalog:", + "effect-acp": "workspace:*", + "vite-plus": "catalog:" + } +} diff --git a/apps/server/src/provider/acp/AcpSessionRuntime.ts b/packages/provider-acp/src/server/AcpSessionRuntime.ts similarity index 99% rename from apps/server/src/provider/acp/AcpSessionRuntime.ts rename to packages/provider-acp/src/server/AcpSessionRuntime.ts index 9c2cb395f3074b0e78dd23998702fe261aba53ad..8b060291f8b8312b459859d511c0209344bf90b9 100644 --- a/apps/server/src/provider/acp/AcpSessionRuntime.ts +++ b/packages/provider-acp/src/server/AcpSessionRuntime.ts @@ -30,7 +30,7 @@ import { resolveSpawnCommand } from "@t3tools/shared/shell"; import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; import { signalProcessGroup } from "@t3tools/provider-core/server/processGroup"; -import { appendAcpStderrTail, sanitizeAcpStderrExcerpt } from "./AcpStderr.ts"; +import { appendAcpStderrTail, sanitizeAcpStderrExcerpt } from "./stderr.ts"; import { collectSessionConfigOptionValues, decideToolCallUpdateEmission, @@ -47,7 +47,7 @@ import { type AcpParsedSessionEvent, type AcpSessionModeState, type AcpToolCallState, -} from "./AcpRuntimeModel.ts"; +} from "./runtimeModel.ts"; const MAX_SHOWN_TOOL_CALL_IDS = 256; @@ -1329,7 +1329,7 @@ export class AcpSessionRuntime extends Context.Service< payload: unknown, ) => Effect.Effect; } ->()("t3/provider/acp/AcpSessionRuntime") { +>()("@t3tools/provider-acp/server/AcpSessionRuntime") { static layer( options: AcpSessionRuntimeOptions, ): Layer.Layer< diff --git a/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.ts b/packages/provider-acp/src/server/adapter.ts similarity index 99% rename from apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.ts rename to packages/provider-acp/src/server/adapter.ts index 03a5c629b66302c3dcf3d02971a57fea2de3b6e3..03d168c04a5be816341204c3d6e8e6c128f95d3f 100644 --- a/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.ts +++ b/packages/provider-acp/src/server/adapter.ts @@ -57,12 +57,8 @@ import type * as EffectAcpProtocol from "effect-acp/protocol"; import type * as EffectAcpSchema from "effect-acp/compat"; import { formatReadToolLabel, formatSearchToolLabel } from "@t3tools/shared/toolActivity"; -import { resolveAttachmentPath } from "../../attachmentStore.ts"; -import * as ServerConfig from "../../config.ts"; -import { - makeAcpMcpOverAcpBridge, - type AcpMcpOverAcpBridge, -} from "../../mcp/AcpMcpOverAcpBridge.ts"; +import type * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; +import { makeAcpMcpOverAcpBridge, type AcpMcpOverAcpBridge } from "./mcpOverAcpBridge.ts"; import { mcpToolPresentation } from "@t3tools/provider-core/server/mcpToolPresentation"; import * as McpProviderSession from "@t3tools/provider-core/server/mcpSession"; import { @@ -78,7 +74,7 @@ import { type AcpAgentTerminalState, type AcpSessionModeState, type AcpToolCallState, -} from "../../provider/acp/AcpRuntimeModel.ts"; +} from "./runtimeModel.ts"; import { acpClientExecuteDisposition, acpMcpToolApprovalElicitationDisposition, @@ -86,14 +82,14 @@ import { type AcpPermissionDisposition, makeAcpClientPolicyGrants, unknownRecord, -} from "../../provider/acp/AcpClientPolicy.ts"; +} from "./clientPolicy.ts"; import { makeAcpClientTerminals, resolveEmbeddedTerminalContent, type AcpClientTerminals, -} from "../../provider/acp/AcpClientTerminals.ts"; -import { ACP_SESSION_MODE_OPTION_ID } from "../../provider/acp/AcpSessionConfig.ts"; -import * as AcpSessionRuntime from "../../provider/acp/AcpSessionRuntime.ts"; +} from "./clientTerminals.ts"; +import { ACP_SESSION_MODE_OPTION_ID } from "./sessionConfig.ts"; +import * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; import { t3AcpPromptWithInstructions, type T3AcpInstructionState, @@ -487,7 +483,7 @@ export interface AcpAdapterV2Options { readonly crypto: Crypto.Crypto; readonly fileSystem: FileSystem.FileSystem; readonly idAllocator: IdAllocator.IdAllocatorV2Shape; - readonly serverConfig: ServerConfig.ServerConfig["Service"]; + readonly host: ProviderHost.ProviderHostShape; /** How agents spawn this install's `acp-mcp-bridge`; see `resolveSelfInvocation`. */ readonly selfInvocation: SelfInvocation; /** @@ -1497,7 +1493,7 @@ function shouldPersistToolUpdate( export function makeAcpAdapterV2( options: AcpAdapterV2Options, ): ProviderAdapter.ProviderAdapterV2Shape { - const { flavor, fileSystem, idAllocator, serverConfig, selfInvocation: self } = options; + const { flavor, fileSystem, idAllocator, host, selfInvocation: self } = options; const driver = flavor.driver; const continuationRequests = options.continuationRequests; const postSettleContinuationEnabled = @@ -6781,8 +6777,7 @@ export function makeAcpAdapterV2( const messageText = providerMessageTextWithAttachmentPaths({ text: turnInput.message.text, attachments: turnInput.message.attachments, - resolveAttachmentPath: (attachment) => - resolveAttachmentPath({ attachmentsDir: serverConfig.attachmentsDir, attachment }), + resolveAttachmentPath: host.resolveAttachmentPath, }); const text = t3AcpPromptWithInstructions({ prompt: messageText, @@ -6804,10 +6799,7 @@ export function makeAcpAdapterV2( }); } for (const attachment of imageAttachments) { - const path = resolveAttachmentPath({ - attachmentsDir: serverConfig.attachmentsDir, - attachment: attachment as ChatAttachment, - }); + const path = host.resolveAttachmentPath(attachment as ChatAttachment); if (path === null) { return yield* new ProviderAdapter.ProviderAdapterProtocolError({ driver, diff --git a/apps/server/src/provider/acp/AcpClientPolicy.test.ts b/packages/provider-acp/src/server/clientPolicy.test.ts similarity index 99% rename from apps/server/src/provider/acp/AcpClientPolicy.test.ts rename to packages/provider-acp/src/server/clientPolicy.test.ts index 6ee2716279345ded3afada8cd77245f1b5269aef..fd2a9714c57cf6e75b20dc9ec0ae5ce593220f7e 100644 --- a/apps/server/src/provider/acp/AcpClientPolicy.test.ts +++ b/packages/provider-acp/src/server/clientPolicy.test.ts @@ -13,7 +13,7 @@ import { acpPermissionDisposition, makeAcpClientPolicyGrants, type AcpRuntimePolicy, -} from "./AcpClientPolicy.ts"; +} from "./clientPolicy.ts"; function permissionRequest( kind: NonNullable, diff --git a/apps/server/src/provider/acp/AcpClientPolicy.ts b/packages/provider-acp/src/server/clientPolicy.ts similarity index 100% rename from apps/server/src/provider/acp/AcpClientPolicy.ts rename to packages/provider-acp/src/server/clientPolicy.ts diff --git a/apps/server/src/provider/acp/AcpClientTerminals.test.ts b/packages/provider-acp/src/server/clientTerminals.test.ts similarity index 99% rename from apps/server/src/provider/acp/AcpClientTerminals.test.ts rename to packages/provider-acp/src/server/clientTerminals.test.ts index c923a996898f779ce2999aca9445ff5f15e267f2..83b5273a21add58c97a5e8cd51faabf33a099735 100644 --- a/apps/server/src/provider/acp/AcpClientTerminals.test.ts +++ b/packages/provider-acp/src/server/clientTerminals.test.ts @@ -8,7 +8,7 @@ import { makeAcpClientTerminals, resolveEmbeddedTerminalContent, type AcpClientTerminals, -} from "./AcpClientTerminals.ts"; +} from "./clientTerminals.ts"; const withTerminals = (use: (terminals: AcpClientTerminals) => Effect.Effect) => Effect.gen(function* () { diff --git a/apps/server/src/provider/acp/AcpClientTerminals.ts b/packages/provider-acp/src/server/clientTerminals.ts similarity index 100% rename from apps/server/src/provider/acp/AcpClientTerminals.ts rename to packages/provider-acp/src/server/clientTerminals.ts diff --git a/apps/server/src/provider/acp/AcpCoreRuntimeEvents.test.ts b/packages/provider-acp/src/server/coreRuntimeEvents.test.ts similarity index 99% rename from apps/server/src/provider/acp/AcpCoreRuntimeEvents.test.ts rename to packages/provider-acp/src/server/coreRuntimeEvents.test.ts index 65c133012fb08ddacf7ce3194ff2a7843c9c1ed2..dc4f5ea70605f5ecf8e767caaeb680b92030f835 100644 --- a/apps/server/src/provider/acp/AcpCoreRuntimeEvents.test.ts +++ b/packages/provider-acp/src/server/coreRuntimeEvents.test.ts @@ -8,7 +8,7 @@ import { makeAcpRequestOpenedEvent, makeAcpRequestResolvedEvent, makeAcpToolCallEvent, -} from "./AcpCoreRuntimeEvents.ts"; +} from "./coreRuntimeEvents.ts"; describe("AcpCoreRuntimeEvents", () => { it("maps ACP permission requests to canonical runtime events", () => { diff --git a/apps/server/src/provider/acp/AcpCoreRuntimeEvents.ts b/packages/provider-acp/src/server/coreRuntimeEvents.ts similarity index 99% rename from apps/server/src/provider/acp/AcpCoreRuntimeEvents.ts rename to packages/provider-acp/src/server/coreRuntimeEvents.ts index c3fa348d2763d7c73e6c24fd953387329bebaca7..3218e23cd88c3671f856cbad2a906eed9c4e4ddc 100644 --- a/apps/server/src/provider/acp/AcpCoreRuntimeEvents.ts +++ b/packages/provider-acp/src/server/coreRuntimeEvents.ts @@ -17,7 +17,7 @@ import { type AcpPlanUpdate, type AcpToolCallState, canonicalItemTypeFromAcpToolKind, -} from "./AcpRuntimeModel.ts"; +} from "./runtimeModel.ts"; type AcpAdapterRawSource = Extract< RuntimeEventRawSource, diff --git a/apps/server/src/mcp/AcpMcpOverAcpBridge.test.ts b/packages/provider-acp/src/server/mcpOverAcpBridge.test.ts similarity index 98% rename from apps/server/src/mcp/AcpMcpOverAcpBridge.test.ts rename to packages/provider-acp/src/server/mcpOverAcpBridge.test.ts index a564a711a2f638ea247bb9d10790724d4b6984b6..c9d7b2bbf2344e030353f3b3bdab65cff6f4ef16 100644 --- a/apps/server/src/mcp/AcpMcpOverAcpBridge.test.ts +++ b/packages/provider-acp/src/server/mcpOverAcpBridge.test.ts @@ -3,7 +3,7 @@ import { describe, expect, it } from "@effect/vitest"; import * as Effect from "effect/Effect"; import * as Fiber from "effect/Fiber"; -import { makeAcpMcpOverAcpBridge } from "./AcpMcpOverAcpBridge.ts"; +import { makeAcpMcpOverAcpBridge } from "./mcpOverAcpBridge.ts"; describe("AcpMcpOverAcpBridge", () => { it.effect("forwards authenticated MCP requests and closes the negotiated session", () => diff --git a/apps/server/src/mcp/AcpMcpOverAcpBridge.ts b/packages/provider-acp/src/server/mcpOverAcpBridge.ts similarity index 98% rename from apps/server/src/mcp/AcpMcpOverAcpBridge.ts rename to packages/provider-acp/src/server/mcpOverAcpBridge.ts index a5185e2515ecde86137c6f73e9177af9e5076694..831bde8756be3b7e8df95b1171eb34689eb70eda 100644 --- a/apps/server/src/mcp/AcpMcpOverAcpBridge.ts +++ b/packages/provider-acp/src/server/mcpOverAcpBridge.ts @@ -5,7 +5,7 @@ import * as Semaphore from "effect/Semaphore"; import * as Stream from "effect/Stream"; import type * as AcpSchema from "effect-acp/compat"; -import { responsePayloads } from "./AcpMcpStdioBridge.ts"; +import { responsePayloads } from "@t3tools/shared/mcpResponsePayloads"; const MAX_CONNECTIONS = 16; const MAX_MESSAGE_BYTES = 8 * 1024 * 1024; @@ -133,7 +133,7 @@ export const makeAcpMcpOverAcpBridge = Effect.fn("AcpMcpOverAcpBridge.make")(fun new AcpMcpOverAcpError(`T3 Code MCP endpoint responded with HTTP ${response.status}.`), ); } - const payloads = [...(yield* Stream.runCollect(responsePayloads(response)))]; + const payloads = [...(yield* Stream.runCollect(responsePayloads(response, bridgeError)))]; for (const payload of payloads) { connection.protocolVersion = protocolVersionOf(payload) ?? connection.protocolVersion; } diff --git a/apps/server/src/provider/acp/AcpNativeLogging.test.ts b/packages/provider-acp/src/server/nativeLogging.test.ts similarity index 97% rename from apps/server/src/provider/acp/AcpNativeLogging.test.ts rename to packages/provider-acp/src/server/nativeLogging.test.ts index 54b485613f379d7dd5954ff9764b7140b9d24b2c..3872121bc6d7ccc7ea0d78a40e0f4feebb5be0d2 100644 --- a/apps/server/src/provider/acp/AcpNativeLogging.test.ts +++ b/packages/provider-acp/src/server/nativeLogging.test.ts @@ -8,8 +8,8 @@ import * as Logger from "effect/Logger"; import * as Schema from "effect/Schema"; import * as AcpErrors from "effect-acp/errors"; -import type { EventNdjsonLogger } from "../EventNdjsonLogger.ts"; -import { makeAcpNativeLoggerFactory } from "./AcpNativeLogging.ts"; +import type * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; +import { makeAcpNativeLoggerFactory } from "./nativeLogging.ts"; const nodeServicesIt = it.layer(NodeServices.layer); const encodeUnknownJson = Schema.encodeUnknownSync(Schema.fromJsonString(Schema.Unknown)); @@ -18,7 +18,7 @@ nodeServicesIt("ACP native logging", (it) => { it.effect("records bounded request and protocol diagnostics without raw payloads", () => Effect.gen(function* () { const records: Array = []; - const nativeEventLogger: EventNdjsonLogger = { + const nativeEventLogger: ProviderEventLoggers.EventNdjsonLogger = { filePath: "/tmp/provider-native.ndjson", write: (event) => Effect.sync(() => void records.push(event)), close: () => Effect.void, diff --git a/apps/server/src/provider/acp/AcpNativeLogging.ts b/packages/provider-acp/src/server/nativeLogging.ts similarity index 97% rename from apps/server/src/provider/acp/AcpNativeLogging.ts rename to packages/provider-acp/src/server/nativeLogging.ts index a510c5f88b5a3f12ff05a213ca95710c0eec8a6e..b869efe47259670d835443da012c11f1eae4b125 100644 --- a/apps/server/src/provider/acp/AcpNativeLogging.ts +++ b/packages/provider-acp/src/server/nativeLogging.ts @@ -6,7 +6,7 @@ import * as DateTime from "effect/DateTime"; import * as Effect from "effect/Effect"; import type * as EffectAcpProtocol from "effect-acp/protocol"; -import type { EventNdjsonLogger } from "../EventNdjsonLogger.ts"; +import type * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; import { structuralProtocolMethod, summarizeNativeProtocolPayload, @@ -121,7 +121,7 @@ function filterTransientProtocolLog( export const makeAcpNativeLoggerFactory = Effect.fn("makeAcpNativeLoggerFactory")(function* () { const crypto = yield* Crypto.Crypto; return (input: { - readonly nativeEventLogger: EventNdjsonLogger | undefined; + readonly nativeEventLogger: ProviderEventLoggers.EventNdjsonLogger | undefined; readonly provider: ProviderDriverKind; readonly threadId: ThreadId; readonly verboseProtocolLogging?: boolean; diff --git a/apps/server/src/provider/acp/AcpRuntimeModel.test.ts b/packages/provider-acp/src/server/runtimeModel.test.ts similarity index 99% rename from apps/server/src/provider/acp/AcpRuntimeModel.test.ts rename to packages/provider-acp/src/server/runtimeModel.test.ts index 27cb3234b3752062848c6a1d0a1e8921ec908edf..dab23a53fead6b190474b29172df694ed3f4a1b4 100644 --- a/apps/server/src/provider/acp/AcpRuntimeModel.test.ts +++ b/packages/provider-acp/src/server/runtimeModel.test.ts @@ -19,7 +19,7 @@ import { syntheticLoadSessionResponseFromInitialize, toolCallProgressLength, type AcpToolCallState, -} from "./AcpRuntimeModel.ts"; +} from "./runtimeModel.ts"; describe("AcpRuntimeModel", () => { it("parses session mode state from typed ACP session setup responses", () => { diff --git a/apps/server/src/provider/acp/AcpRuntimeModel.ts b/packages/provider-acp/src/server/runtimeModel.ts similarity index 100% rename from apps/server/src/provider/acp/AcpRuntimeModel.ts rename to packages/provider-acp/src/server/runtimeModel.ts diff --git a/apps/server/src/provider/acp/AcpSessionConfig.test.ts b/packages/provider-acp/src/server/sessionConfig.test.ts similarity index 99% rename from apps/server/src/provider/acp/AcpSessionConfig.test.ts rename to packages/provider-acp/src/server/sessionConfig.test.ts index 8400605be264bc1b12e17280a9a10ae0933eed37..8e208e88aa5cc19118f6dd82a1ae11b213f833a4 100644 --- a/apps/server/src/provider/acp/AcpSessionConfig.test.ts +++ b/packages/provider-acp/src/server/sessionConfig.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "@effect/vitest"; -import { ACP_SESSION_MODE_OPTION_ID, acpProviderOptionDescriptors } from "./AcpSessionConfig.ts"; +import { ACP_SESSION_MODE_OPTION_ID, acpProviderOptionDescriptors } from "./sessionConfig.ts"; describe("acpProviderOptionDescriptors", () => { it("maps non-model select options and excludes model and collaboration categories", () => { diff --git a/apps/server/src/provider/acp/AcpSessionConfig.ts b/packages/provider-acp/src/server/sessionConfig.ts similarity index 98% rename from apps/server/src/provider/acp/AcpSessionConfig.ts rename to packages/provider-acp/src/server/sessionConfig.ts index 6454eb4444c980a8c38633ddc835473c8efe0631..0d2a821762e511c385736fba149b7366a53bdce3 100644 --- a/apps/server/src/provider/acp/AcpSessionConfig.ts +++ b/packages/provider-acp/src/server/sessionConfig.ts @@ -1,7 +1,7 @@ import type { ProviderOptionChoice, ProviderOptionDescriptor } from "@t3tools/contracts"; import type * as EffectAcpSchema from "effect-acp/compat"; -import type { AcpSessionModeState } from "./AcpRuntimeModel.ts"; +import type { AcpSessionModeState } from "./runtimeModel.ts"; /** * Maps ACP session configuration and session modes onto T3's provider option diff --git a/apps/server/src/provider/acp/AcpStderr.test.ts b/packages/provider-acp/src/server/stderr.test.ts similarity index 98% rename from apps/server/src/provider/acp/AcpStderr.test.ts rename to packages/provider-acp/src/server/stderr.test.ts index e88b59bdb0e1453d38224e1c4a7634068c826f2f..f5f704f049967d774ee633b92e733b64bfb00f1a 100644 --- a/apps/server/src/provider/acp/AcpStderr.test.ts +++ b/packages/provider-acp/src/server/stderr.test.ts @@ -4,7 +4,7 @@ import { ACP_STDERR_TAIL_MAX_CHARS, appendAcpStderrTail, sanitizeAcpStderrExcerpt, -} from "./AcpStderr.ts"; +} from "./stderr.ts"; describe("AcpStderr", () => { it("keeps a bounded tail of stderr chunks", () => { diff --git a/apps/server/src/provider/acp/AcpStderr.ts b/packages/provider-acp/src/server/stderr.ts similarity index 100% rename from apps/server/src/provider/acp/AcpStderr.ts rename to packages/provider-acp/src/server/stderr.ts diff --git a/packages/provider-acp/tsconfig.json b/packages/provider-acp/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..374bac55202ddcad695ede1c567ec219a61e9c48 --- /dev/null +++ b/packages/provider-acp/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "types": ["node"] + }, + "include": ["src"] +} diff --git a/packages/provider-core/src/server/ProviderHost.ts b/packages/provider-core/src/server/ProviderHost.ts index 318037cdcb3bf0b5e92bb65e9ff480e9c1fd4177..a8509b01e1309a3df6dd0a40c4a30f8870019155 100644 --- a/packages/provider-core/src/server/ProviderHost.ts +++ b/packages/provider-core/src/server/ProviderHost.ts @@ -32,6 +32,8 @@ export interface ProviderHostPaths { readonly stateDir: string; /** Scratch space for provider probes and generated helper files. */ readonly providerStatusCacheDir: string; + /** Where chat attachments are stored; agents that sandbox file reads must be granted it. */ + readonly attachmentsDir: string; } /** One opaque credential blob in the server's secret store. Only the provider decodes it. */ diff --git a/packages/provider-core/src/server/managedProvider.test.ts b/packages/provider-core/src/server/managedProvider.test.ts index 6d9e3827531bd58f600bcbda8028c16d6fcbd865..76f7fda46954106fb38c79396e6f52ee2a05d45e 100644 --- a/packages/provider-core/src/server/managedProvider.test.ts +++ b/packages/provider-core/src/server/managedProvider.test.ts @@ -109,6 +109,7 @@ function layerProviderHost(input: { baseDir: "/t3", stateDir: "/t3/userdata", providerStatusCacheDir: "/t3/caches", + attachmentsDir: "/t3/userdata/attachments", }, settings: input.settings ?? { get: Effect.succeed(DEFAULT_SERVER_SETTINGS), diff --git a/packages/provider-testing/src/host.ts b/packages/provider-testing/src/host.ts index eb1d07af6c8615b6a62c5831d0c629b3768cb16e..2436648579107c5786a4de4d2e584250789af239 100644 --- a/packages/provider-testing/src/host.ts +++ b/packages/provider-testing/src/host.ts @@ -42,7 +42,13 @@ export const layerTestProviderHost = ( const settings = options.settings ?? DEFAULT_SERVER_SETTINGS; const credentials = new Map(); return ProviderHost.ProviderHost.of({ - paths: { cwd: options.cwd ?? process.cwd(), baseDir, stateDir, providerStatusCacheDir }, + paths: { + cwd: options.cwd ?? process.cwd(), + baseDir, + stateDir, + providerStatusCacheDir, + attachmentsDir, + }, settings: { get: Effect.succeed(settings), changes: Stream.empty, diff --git a/packages/shared/package.json b/packages/shared/package.json index c5bca30542902a24907e24e49323dd2699275094..4942d700caddb3a58ad41b4084b56253375370db 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -466,6 +466,10 @@ "./atomicWrite": { "types": "./src/atomicWrite.ts", "import": "./src/atomicWrite.ts" + }, + "./mcpResponsePayloads": { + "types": "./src/mcpResponsePayloads.ts", + "import": "./src/mcpResponsePayloads.ts" } }, "scripts": { diff --git a/packages/shared/src/mcpResponsePayloads.ts b/packages/shared/src/mcpResponsePayloads.ts new file mode 100644 index 0000000000000000000000000000000000000000..d46ef8e73fe94ccdaa1956f8a015b23d4b118154 --- /dev/null +++ b/packages/shared/src/mcpResponsePayloads.ts @@ -0,0 +1,65 @@ +// MCP responses carry opaque JSON-RPC that callers relay verbatim. +// @effect-diagnostics preferSchemaOverJson:off +/** + * Reads the JSON-RPC payloads of a response from an MCP streamable-HTTP + * endpoint. Used on the ACP bridge fast path, so it imports only effect core. + * + * @module mcpResponsePayloads + */ +import * as Effect from "effect/Effect"; +import * as Stream from "effect/Stream"; + +async function* sseDataLines(response: Response): AsyncGenerator { + if (response.body === null) return; + const decoder = new TextDecoder(); + let buffered = ""; + for await (const chunk of response.body) { + buffered += decoder.decode(chunk as Uint8Array, { stream: true }); + let separatorIndex = buffered.search(/\n\n|\r\n\r\n/u); + while (separatorIndex !== -1) { + const rawEvent = buffered.slice(0, separatorIndex); + buffered = buffered.slice(separatorIndex).replace(/^(?:\r?\n){2}/u, ""); + const data = rawEvent + .split(/\r?\n/u) + .filter((line) => line.startsWith("data:")) + .map((line) => line.slice("data:".length).trimStart()) + .join("\n"); + if (data.length > 0) yield data; + separatorIndex = buffered.search(/\n\n|\r\n\r\n/u); + } + } +} + +export const discardResponseBody = (response: Response): Effect.Effect => + Effect.promise(() => response.body?.cancel().catch(() => undefined) ?? Promise.resolve()); + +/** + * Every JSON-RPC payload carried by a response, in arrival order: nothing for + * notification acknowledgements, each SSE `data:` event as it streams in, or + * the single JSON body. + */ +export function responsePayloads( + response: Response, + onError: (cause: unknown) => E, +): Stream.Stream { + if (response.status === 202 || response.status === 204) { + return Stream.unwrap(discardResponseBody(response).pipe(Effect.as(Stream.empty))); + } + const contentType = response.headers.get("content-type") ?? ""; + if (contentType.includes("text/event-stream")) { + return Stream.fromAsyncIterable(sseDataLines(response), onError).pipe( + Stream.mapEffect((data) => Effect.try({ try: () => JSON.parse(data), catch: onError })), + ); + } + return Stream.unwrap( + Effect.tryPromise({ try: () => response.text(), catch: onError }).pipe( + Effect.flatMap((text) => + text.trim().length === 0 + ? Effect.succeed(Stream.empty) + : Effect.try({ try: () => JSON.parse(text) as unknown, catch: onError }).pipe( + Effect.map((payload) => Stream.fromIterable([payload])), + ), + ), + ), + ); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 85e33ad5cabe2b5820fe500be6c861ff18574586..d0b0d970c12bd65948f79eb89f21724c066c975b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -600,6 +600,9 @@ importers: '@opencode-ai/sdk': specifier: ^1.3.15 version: 1.15.13 + '@t3tools/provider-acp': + specifier: workspace:* + version: link:../../packages/provider-acp '@t3tools/provider-core': specifier: workspace:* version: link:../../packages/provider-core @@ -1092,6 +1095,40 @@ importers: specifier: 1.0.0 version: 1.0.0(@types/node@24.12.4)(@vitest/ui@5.0.1(vitest@5.0.1))(bufferutil@4.1.0)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.1.0(@noble/hashes@1.8.0))(msw@2.12.11(@types/node@24.12.4)(typescript@7.0.2))(terser@5.48.0)(typescript@7.0.2)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + packages/provider-acp: + dependencies: + '@t3tools/contracts': + specifier: workspace:* + version: link:../contracts + '@t3tools/provider-core': + specifier: workspace:* + version: link:../provider-core + '@t3tools/shared': + specifier: workspace:* + version: link:../shared + diff: + specifier: 8.0.3 + version: 8.0.3 + effect: + specifier: 4.0.1 + version: 4.0.1(patch_hash=a33cba07c41f32374c2aaa86ea4a84d3ab9a872a78c94b65e929b19f8361856f) + devDependencies: + '@effect/platform-node': + specifier: 4.0.1 + version: 4.0.1(bufferutil@4.1.0)(effect@4.0.1(patch_hash=a33cba07c41f32374c2aaa86ea4a84d3ab9a872a78c94b65e929b19f8361856f))(redis@6.2.1)(utf-8-validate@6.0.6) + '@effect/vitest': + specifier: 4.0.1 + version: 4.0.1(patch_hash=359f6fb2f7b3ec145bb72208edb9034f02489791aa2491a55cdbd69bd56ee0d2)(@types/node@24.12.4)(@vitest/ui@5.0.1)(bufferutil@4.1.0)(effect@4.0.1(patch_hash=a33cba07c41f32374c2aaa86ea4a84d3ab9a872a78c94b65e929b19f8361856f))(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.1.0(@noble/hashes@1.8.0))(msw@2.12.11(@types/node@24.12.4)(typescript@7.0.2))(terser@5.48.0)(typescript@7.0.2)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + '@types/node': + specifier: 24.12.4 + version: 24.12.4 + effect-acp: + specifier: workspace:* + version: link:../effect-acp + vite-plus: + specifier: 1.0.0 + version: 1.0.0(@types/node@24.12.4)(@vitest/ui@5.0.1(vitest@5.0.1))(bufferutil@4.1.0)(esbuild@0.28.2)(jiti@2.7.0)(jsdom@30.1.0(@noble/hashes@1.8.0))(msw@2.12.11(@types/node@24.12.4)(typescript@7.0.2))(terser@5.48.0)(typescript@7.0.2)(unrun@0.2.39)(utf-8-validate@6.0.6)(yaml@2.9.0) + packages/provider-core: dependencies: '@t3tools/contracts': diff --git a/scripts/release-smoke.ts b/scripts/release-smoke.ts index 6c5a1707854f31218b41c55d6ce76f49c50f938e..40dfbc7c8d3cf62b23403640f992a3c9a3299083 100644 --- a/scripts/release-smoke.ts +++ b/scripts/release-smoke.ts @@ -31,6 +31,7 @@ const workspaceFiles = [ "packages/provider-core/package.json", "packages/provider-testing/package.json", "packages/provider-pi/package.json", + "packages/provider-acp/package.json", "packages/provider-cursor/package.json", "packages/provider-muse/package.json", "packages/provider-opencode/package.json", -- 2.54.0