From 43f8a8de17a7ac1baa7a3cf36d681856de2d8add Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 8 Oct 2026 23:08:35 -0700 Subject: [PATCH] refactor(provider-acp-registry): move the ACP Registry into its own package (#17405) --- apps/mobile/package.json | 1 + apps/mobile/src/lib/providerClients.ts | 2 + apps/server/package.json | 2 +- .../Adapters/AcpAdapterV2.test.ts | 4 +- .../Adapters/AcpRegistryAdapterV2.test.ts | 8 +- .../Adapters/AcpRegistryAdapterV2.testkit.ts | 4 +- .../ProviderAdapterRegistry.test.ts | 2 +- .../builtInProviderAdapterDrivers.ts | 2 +- .../server/src/provider/AcpRegistryCatalog.ts | 22 ------ .../{acp => }/AcpRegistryProbe.test.ts | 9 ++- apps/server/src/provider/CodexChatGptAuth.ts | 4 +- apps/server/src/provider/ProviderHostLive.ts | 1 + .../ProviderInstanceRegistryHydration.ts | 5 +- apps/server/src/provider/builtInDrivers.ts | 5 +- apps/server/src/server.ts | 5 +- apps/server/src/terminal/Manager.test.ts | 2 +- apps/server/src/terminal/Manager.ts | 4 +- .../src/terminal/NodePtyAdapter.test.ts | 2 +- apps/server/src/terminal/NodePtyAdapter.ts | 2 +- apps/server/src/ws.ts | 4 +- apps/web/package.json | 1 + .../components/settings/providerDriverMeta.ts | 9 +-- package.json | 2 +- packages/contracts/src/settings.ts | 67 ---------------- packages/provider-acp-registry/package.json | 51 +++++++++++++ packages/provider-acp-registry/src/client.ts | 28 +++++++ packages/provider-acp-registry/src/server.ts | 16 ++++ .../AcpRegistryRuntimeCoordinator.test.ts | 50 +++--------- .../server}/AcpRegistryRuntimeCoordinator.ts | 13 +--- .../src/server}/AcpRegistrySupport.test.ts | 66 +++++++++------- .../src/server}/AcpRegistrySupport.ts | 44 ++++++++--- .../src/server/adapter.ts | 17 ++--- .../src/server/auth.test.ts | 11 +-- .../provider-acp-registry/src/server/auth.ts | 8 +- .../src/server/authenticationState.test.ts | 5 +- .../src/server/authenticationState.ts | 7 +- .../src/server/devinAcp.ts | 0 .../src/server/driver.test.ts | 11 +-- .../src/server/driver.ts | 23 +++--- .../provider-acp-registry/src/server/probe.ts | 4 +- .../testing/AcpRegistrySupport.npm.fixture.sh | 0 .../testing/AcpRegistrySupport.uv.fixture.sh | 0 .../provider-acp-registry/src/settings.ts | 76 +++++++++++++++++++ packages/provider-acp-registry/src/testing.ts | 29 +++++++ packages/provider-acp-registry/tsconfig.json | 8 ++ .../src/server/AcpSessionRuntime.ts | 12 +-- packages/provider-core/package.json | 4 + .../src/server}/ProviderAuthFlow.test.ts | 0 .../src/server}/ProviderAuthFlow.ts | 8 +- .../provider-core/src/server/ProviderHost.ts | 4 + .../src/server/managedProvider.test.ts | 2 + .../src/server/OpenCodeRuntime.ts | 12 +-- .../src/server/v2/OpenCode2Server.ts | 2 +- packages/provider-testing/src/host.ts | 30 ++++++-- packages/shared/package.json | 4 + .../shared/src}/PtyAdapter.ts | 2 +- pnpm-lock.yaml | 52 ++++++++++++- scripts/release-smoke.ts | 1 + 58 files changed, 470 insertions(+), 299 deletions(-) delete mode 100644 apps/server/src/provider/AcpRegistryCatalog.ts rename apps/server/src/provider/{acp => }/AcpRegistryProbe.test.ts (98%) create mode 100644 packages/provider-acp-registry/package.json create mode 100644 packages/provider-acp-registry/src/client.ts create mode 100644 packages/provider-acp-registry/src/server.ts rename {apps/server/src/provider/acp => packages/provider-acp-registry/src/server}/AcpRegistryRuntimeCoordinator.test.ts (91%) rename {apps/server/src/provider/acp => packages/provider-acp-registry/src/server}/AcpRegistryRuntimeCoordinator.ts (98%) rename {apps/server/src/provider/acp => packages/provider-acp-registry/src/server}/AcpRegistrySupport.test.ts (97%) rename {apps/server/src/provider/acp => packages/provider-acp-registry/src/server}/AcpRegistrySupport.ts (98%) rename apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.ts => packages/provider-acp-registry/src/server/adapter.ts (96%) rename apps/server/src/provider/acp/AcpRegistryAuth.test.ts => packages/provider-acp-registry/src/server/auth.test.ts (98%) rename apps/server/src/provider/acp/AcpRegistryAuth.ts => packages/provider-acp-registry/src/server/auth.ts (98%) rename apps/server/src/provider/acp/AcpRegistryAuthenticationState.test.ts => packages/provider-acp-registry/src/server/authenticationState.test.ts (95%) rename apps/server/src/provider/acp/AcpRegistryAuthenticationState.ts => packages/provider-acp-registry/src/server/authenticationState.ts (95%) rename apps/server/src/orchestration-v2/Adapters/DevinAcp.ts => packages/provider-acp-registry/src/server/devinAcp.ts (100%) rename apps/server/src/provider/Drivers/AcpRegistryDriver.test.ts => packages/provider-acp-registry/src/server/driver.test.ts (98%) rename apps/server/src/provider/Drivers/AcpRegistryDriver.ts => packages/provider-acp-registry/src/server/driver.ts (97%) rename apps/server/src/provider/acp/AcpRegistryProbe.ts => packages/provider-acp-registry/src/server/probe.ts (99%) rename {apps/server/src/provider/acp => packages/provider-acp-registry/src/server}/testing/AcpRegistrySupport.npm.fixture.sh (100%) rename {apps/server/src/provider/acp => packages/provider-acp-registry/src/server}/testing/AcpRegistrySupport.uv.fixture.sh (100%) create mode 100644 packages/provider-acp-registry/src/settings.ts create mode 100644 packages/provider-acp-registry/src/testing.ts create mode 100644 packages/provider-acp-registry/tsconfig.json rename {apps/server/src/provider => packages/provider-core/src/server}/ProviderAuthFlow.test.ts (100%) rename {apps/server/src/provider => packages/provider-core/src/server}/ProviderAuthFlow.ts (98%) rename {apps/server/src/terminal => packages/shared/src}/PtyAdapter.ts (98%) diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 97a0cd33ac744a6672e7e5f47d939d8d29a14353..0efb5e01a11dff5c0a8eb9d4dcd8e9b78a0dde42 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -69,6 +69,7 @@ "@t3tools/mobile-markdown-text": "file:./modules/t3-markdown-text", "@t3tools/mobile-review-diff-native": "file:./modules/t3-review-diff", "@t3tools/mobile-terminal-native": "file:./modules/t3-terminal", + "@t3tools/provider-acp-registry": "workspace:*", "@t3tools/provider-core": "workspace:*", "@t3tools/provider-cursor": "workspace:*", "@t3tools/provider-grok": "workspace:*", diff --git a/apps/mobile/src/lib/providerClients.ts b/apps/mobile/src/lib/providerClients.ts index d434e6bde328a507056fa6d09f2f5a4254dfbd83..96755bd85410a5881ae6c885b744326c20972886 100644 --- a/apps/mobile/src/lib/providerClients.ts +++ b/apps/mobile/src/lib/providerClients.ts @@ -1,4 +1,5 @@ import { isProviderDriverKind } from "@t3tools/contracts"; +import { acpRegistryClient } from "@t3tools/provider-acp-registry/client"; import { makeProviderClientRegistry } from "@t3tools/provider-core/client"; import { cursorClient } from "@t3tools/provider-cursor/client"; import { grokClient } from "@t3tools/provider-grok/client"; @@ -13,6 +14,7 @@ const providerClients = makeProviderClientRegistry([ museClient, openCodeClient, piClient, + acpRegistryClient, ]); /** The client definition for a driver kind, or `undefined` for drivers drawn by hand. */ diff --git a/apps/server/package.json b/apps/server/package.json index cb0f2dfcdc135d2f964f1a6fb45b832b9803db37..bb166039abd95cb1e49908ad61bf46526b7ac532 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -36,9 +36,9 @@ "@ff-labs/fff-node": "0.9.4", "@muse-code/sdk": "1.4.2", "@napi-rs/keyring": "^1.3.0", - "@noble/hashes": "catalog:", "@opencode-ai/sdk": "^1.3.15", "@t3tools/provider-acp": "workspace:*", + "@t3tools/provider-acp-registry": "workspace:*", "@t3tools/provider-core": "workspace:*", "@t3tools/provider-cursor": "workspace:*", "@t3tools/provider-grok": "workspace:*", diff --git a/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts b/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts index a8c958209214170c26befe2f588b591a39d18eed..bda7b91e735a57b65ee8c80e6dffde200ad1282e 100644 --- a/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts +++ b/apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts @@ -2,7 +2,7 @@ import { normalizeDevinSessionUpdate, normalizeDevinToolCall, extractDevinSubagentUpdate, -} from "./DevinAcp.ts"; +} from "@t3tools/provider-acp-registry/testing"; // @effect-diagnostics nodeBuiltinImport:off import * as NodeChildProcess from "node:child_process"; import * as NodeFS from "node:fs"; @@ -95,7 +95,7 @@ import { makeGrokAdapterV2 } from "@t3tools/provider-grok/testing"; import { acpRegistryPromptFailure, registerMistralVibeAcpExtensions, -} from "./AcpRegistryAdapterV2.ts"; +} from "@t3tools/provider-acp-registry/testing"; const DEFAULT_GROK_SETTINGS = Schema.decodeSync(GrokSettings)({}); diff --git a/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.test.ts b/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.test.ts index 3762cbb6769a6ab065ecc61e678a80bff37c7b4f..728e8bc4c91dae55164d095175633363c5234a41 100644 --- a/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.test.ts +++ b/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.test.ts @@ -19,8 +19,8 @@ import * as ServerSettings from "../../serverSettings.ts"; import type { AcpRegistryAvailableCommands, AcpRegistryLiveConfiguration, -} from "../../provider/acp/AcpRegistryProbe.ts"; -import * as AcpRegistrySupport from "../../provider/acp/AcpRegistrySupport.ts"; +} from "@t3tools/provider-acp-registry/testing"; +import * as AcpRegistrySupport from "@t3tools/provider-acp-registry/server/AcpRegistrySupport"; 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"; @@ -31,12 +31,12 @@ import { } from "./AcpAdapterV2.testkit.ts"; import { ProviderAdapterV2RuntimePolicy } from "@t3tools/provider-core/server/ProviderAdapter"; import { BUILT_IN_PROVIDER_ADAPTER_DRIVER_KINDS_V2 } from "../builtInProviderAdapterDrivers.ts"; +import { AcpRegistryAdapterV2Driver } from "@t3tools/provider-acp-registry/server"; import { ACP_REGISTRY_PROVIDER, - AcpRegistryAdapterV2Driver, makeAcpRegistryAdapterV2, acpRegistryPromptFailure, -} from "./AcpRegistryAdapterV2.ts"; +} from "@t3tools/provider-acp-registry/testing"; const registryUrl = "https://registry.test/registry.json"; const decodeAcpRegistryAdapterSettings = Schema.decodeUnknownEffect( diff --git a/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.testkit.ts b/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.testkit.ts index aefcd190f33d18dbda1df1c1d4b727cb8a54b632..c3015252900649af6b88d0369e8da345837501cc 100644 --- a/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.testkit.ts +++ b/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.testkit.ts @@ -1,5 +1,5 @@ import * as NodeServices from "@effect/platform-node/NodeServices"; -import { AcpRegistrySettings } from "@t3tools/contracts"; +import { AcpRegistrySettings } from "@t3tools/provider-acp-registry/settings"; import { resolveSelfInvocation } from "@t3tools/shared/nodeRuntime"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; @@ -24,7 +24,7 @@ import { ACP_REGISTRY_DEFAULT_INSTANCE_ID, ACP_REGISTRY_PROVIDER, makeAcpRegistryAdapterV2, -} from "./AcpRegistryAdapterV2.ts"; +} from "@t3tools/provider-acp-registry/testing"; const REPLAY_SETTINGS = Schema.decodeUnknownSync(AcpRegistrySettings)({ agentId: "replay-agent", diff --git a/apps/server/src/orchestration-v2/ProviderAdapterRegistry.test.ts b/apps/server/src/orchestration-v2/ProviderAdapterRegistry.test.ts index 3a11ab7c2722b6bb040b6ead6b585f6b22e92fbd..3e8f6dfa297bb79f4b5f5225cc476616868c2479 100644 --- a/apps/server/src/orchestration-v2/ProviderAdapterRegistry.test.ts +++ b/apps/server/src/orchestration-v2/ProviderAdapterRegistry.test.ts @@ -18,7 +18,7 @@ import * as Schema from "effect/Schema"; import type * as Scope from "effect/Scope"; import * as Stream from "effect/Stream"; -import * as ProviderAuthFlow from "../provider/ProviderAuthFlow.ts"; +import * as ProviderAuthFlow from "@t3tools/provider-core/server/ProviderAuthFlow"; import type { ProviderAuthController } from "../provider/ProviderAuthService.ts"; import type { ProviderInstance } from "@t3tools/provider-core/server/driver"; import * as ProviderInstanceRegistry from "../provider/ProviderInstanceRegistry.ts"; diff --git a/apps/server/src/orchestration-v2/builtInProviderAdapterDrivers.ts b/apps/server/src/orchestration-v2/builtInProviderAdapterDrivers.ts index f1ce18c12f88c83bcd6c7ea28bb51d2c45d4a010..77cd6f3933d527f8b3691e1d0ab294af74c83a3d 100644 --- a/apps/server/src/orchestration-v2/builtInProviderAdapterDrivers.ts +++ b/apps/server/src/orchestration-v2/builtInProviderAdapterDrivers.ts @@ -3,7 +3,7 @@ import type { ProviderDriverKind } from "@t3tools/contracts"; import { AcpRegistryAdapterV2Driver, type AcpRegistryAdapterV2DriverEnv, -} from "./Adapters/AcpRegistryAdapterV2.ts"; +} from "@t3tools/provider-acp-registry/server"; import { ClaudeAdapterV2Driver, type ClaudeAdapterV2DriverEnv, diff --git a/apps/server/src/provider/AcpRegistryCatalog.ts b/apps/server/src/provider/AcpRegistryCatalog.ts deleted file mode 100644 index 9141793ee5455f82569485dce77026bd2f61d245..0000000000000000000000000000000000000000 --- a/apps/server/src/provider/AcpRegistryCatalog.ts +++ /dev/null @@ -1,22 +0,0 @@ -import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; -import * as Path from "effect/Path"; - -import * as ServerConfig from "../config.ts"; -import * as AcpRegistrySupport from "./acp/AcpRegistrySupport.ts"; -import * as AcpRegistryRuntimeCoordinator from "./acp/AcpRegistryRuntimeCoordinator.ts"; - -/** Server-lifetime ACP Registry catalog shared by setup, snapshots, and turn launch. */ -export const layer = Layer.merge( - Layer.unwrap( - Effect.gen(function* () { - const config = yield* ServerConfig.ServerConfig; - const path = yield* Path.Path; - return AcpRegistrySupport.AcpRegistryCatalog.layer({ - cacheDir: config.providerStatusCacheDir, - toolsDir: path.join(config.baseDir, "tools"), - }); - }), - ), - AcpRegistryRuntimeCoordinator.AcpRegistryRuntimeCoordinator.layer, -); diff --git a/apps/server/src/provider/acp/AcpRegistryProbe.test.ts b/apps/server/src/provider/AcpRegistryProbe.test.ts similarity index 98% rename from apps/server/src/provider/acp/AcpRegistryProbe.test.ts rename to apps/server/src/provider/AcpRegistryProbe.test.ts index 37066157fc0b8ac8d6b356e9fcb08eeb52f665ee..7b69ca58baaaf8fef3459d655ea40b519c9d7493 100644 --- a/apps/server/src/provider/acp/AcpRegistryProbe.test.ts +++ b/apps/server/src/provider/AcpRegistryProbe.test.ts @@ -3,7 +3,8 @@ import * as NodePath from "node:path"; import * as NodeURL from "node:url"; import * as NodeServices from "@effect/platform-node/NodeServices"; -import { AcpRegistrySettings, ProviderInstanceId } from "@t3tools/contracts"; +import { ProviderInstanceId } from "@t3tools/contracts"; +import { AcpRegistrySettings } from "@t3tools/provider-acp-registry/settings"; import { describe, expect, it } from "@effect/vitest"; import * as Deferred from "effect/Deferred"; import * as Effect from "effect/Effect"; @@ -21,12 +22,12 @@ import { normalizeAcpRegistryAuthMethods, normalizeAcpRegistryCommands, probeAcpRegistryConfiguration, -} from "./AcpRegistryProbe.ts"; -import * as AcpRegistrySupport from "./AcpRegistrySupport.ts"; +} from "@t3tools/provider-acp-registry/testing"; +import * as AcpRegistrySupport from "@t3tools/provider-acp-registry/server/AcpRegistrySupport"; const instanceId = ProviderInstanceId.make("acpRegistry_codex"); const __dirname = NodePath.dirname(NodeURL.fileURLToPath(import.meta.url)); -const mockAgentPath = NodePath.join(__dirname, "../../../scripts/acp-mock-agent.ts"); +const mockAgentPath = NodePath.join(__dirname, "../../scripts/acp-mock-agent.ts"); const decodeSettings = Schema.decodeSync(AcpRegistrySettings); describe("ACP Registry probe", () => { diff --git a/apps/server/src/provider/CodexChatGptAuth.ts b/apps/server/src/provider/CodexChatGptAuth.ts index b5f30c2e54fd7844a0f234224636636cf5dbf57a..b6845a02972115b4f94bb9855e38162e14bb9748 100644 --- a/apps/server/src/provider/CodexChatGptAuth.ts +++ b/apps/server/src/provider/CodexChatGptAuth.ts @@ -19,8 +19,8 @@ import * as Effect from "effect/Effect"; import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; import * as Semaphore from "effect/Semaphore"; -import * as ProviderAuthFlow from "./ProviderAuthFlow.ts"; -import type { ProviderAuthFlowContext } from "./ProviderAuthFlow.ts"; +import * as ProviderAuthFlow from "@t3tools/provider-core/server/ProviderAuthFlow"; +import type { ProviderAuthFlowContext } from "@t3tools/provider-core/server/ProviderAuthFlow"; import { HttpClient, HttpClientRequest } from "effect/http"; import * as ProviderCredentialStore from "./ProviderCredentialStore.ts"; import { withChatGptSessionLock } from "./CodexChatGptSessionLock.ts"; diff --git a/apps/server/src/provider/ProviderHostLive.ts b/apps/server/src/provider/ProviderHostLive.ts index 19042fc2805e1b66899f31bacb8aa2700c2a8fc7..3a924b39bd664b381c09a9841346757e86282f87 100644 --- a/apps/server/src/provider/ProviderHostLive.ts +++ b/apps/server/src/provider/ProviderHostLive.ts @@ -35,6 +35,7 @@ export const layer = Layer.effect( }, settings: { get: serverSettings.getSettings, + withSnapshot: serverSettings.withSettingsSnapshot, changes: serverSettings.streamChanges, subscribe: serverSettings.subscribeChanges, }, diff --git a/apps/server/src/provider/ProviderInstanceRegistryHydration.ts b/apps/server/src/provider/ProviderInstanceRegistryHydration.ts index 177aace04c57f17bccfb0d2e9fb8dc64c293b2dd..6048f48636ea2b00e6740b1f5cacc6ce1bb93c55 100644 --- a/apps/server/src/provider/ProviderInstanceRegistryHydration.ts +++ b/apps/server/src/provider/ProviderInstanceRegistryHydration.ts @@ -38,8 +38,7 @@ import { BUILT_IN_DRIVERS, type BuiltInDriversEnv } from "./builtInDrivers.ts"; import * as ProviderInstanceRegistry from "./ProviderInstanceRegistry.ts"; import * as ProviderInstanceRegistryMutator from "./ProviderInstanceRegistryMutator.ts"; import * as ProviderOrchestrationAdapterInfrastructure from "./ProviderOrchestrationAdapterInfrastructure.ts"; -import * as AcpRegistrySupport from "./acp/AcpRegistrySupport.ts"; -import * as AcpRegistryCatalog from "./AcpRegistryCatalog.ts"; +import * as AcpRegistrySupport from "@t3tools/provider-acp-registry/server/AcpRegistrySupport"; import * as ProviderHostLive from "./ProviderHostLive.ts"; import type { ProviderHost } from "@t3tools/provider-core/server/ProviderHost"; import type * as BackgroundPolicy from "../background/BackgroundPolicy.ts"; @@ -144,7 +143,7 @@ export const layer: Layer.Layer< configMap: initialConfigMap, }).pipe( Layer.provide(ProviderOrchestrationAdapterInfrastructure.layer), - Layer.provide(AcpRegistryCatalog.layer), + Layer.provide(AcpRegistrySupport.layerFromHost), Layer.provide(ProviderHostLive.layer), ); diff --git a/apps/server/src/provider/builtInDrivers.ts b/apps/server/src/provider/builtInDrivers.ts index 1e21b8dc7cc199b0057dbe31975f5828f442495d..845ffcf137c40cc9dd68816c2ac04d2e35c8bfd5 100644 --- a/apps/server/src/provider/builtInDrivers.ts +++ b/apps/server/src/provider/builtInDrivers.ts @@ -20,7 +20,10 @@ * * @module provider/builtInDrivers */ -import { AcpRegistryDriver, type AcpRegistryDriverEnv } from "./Drivers/AcpRegistryDriver.ts"; +import { + AcpRegistryDriver, + type AcpRegistryDriverEnv, +} from "@t3tools/provider-acp-registry/server"; import { AntigravityDriver, type AntigravityDriverEnv } from "./Drivers/AntigravityDriver.ts"; import { ClaudeDriver, type ClaudeDriverEnv } from "./Drivers/ClaudeDriver.ts"; import { CodexDriver, type CodexDriverEnv } from "./Drivers/CodexDriver.ts"; diff --git a/apps/server/src/server.ts b/apps/server/src/server.ts index f91976f38ece92999306a05dab03e7a69f635810..6a698c2e46ab1e32746313cb483ab699f5442795 100644 --- a/apps/server/src/server.ts +++ b/apps/server/src/server.ts @@ -45,7 +45,8 @@ import * as ResetCreditCoordinator from "./provider/resetCreditCoordinator.ts"; import * as ProviderEventLoggers from "./provider/ProviderEventLoggers.ts"; import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; import * as OpenCodeServerLedger from "@t3tools/provider-opencode/server/OpenCodeServerLedger"; -import * as AcpRegistryCatalog from "./provider/AcpRegistryCatalog.ts"; +import * as ProviderHostLive from "./provider/ProviderHostLive.ts"; +import * as AcpRegistrySupport from "@t3tools/provider-acp-registry/server/AcpRegistrySupport"; import * as CheckpointDiffQuery from "./checkpointing/CheckpointDiffQuery.ts"; import * as CheckpointStore from "./checkpointing/CheckpointStore.ts"; import * as AzureDevOpsCli from "./sourceControl/AzureDevOpsCli.ts"; @@ -597,7 +598,7 @@ const layerRuntimeCoreDependencies = layerRuntimeCoreDependenciesBase.pipe( Layer.provideMerge(layerPtyAdapter), // Search, prepare, status inspection, and turn launch share one registry // cache so every client and provider instance sees the same prepared agents. - Layer.provideMerge(AcpRegistryCatalog.layer.pipe(Layer.provide(layerServerSettings))), + Layer.provideMerge(AcpRegistrySupport.layerFromHost.pipe(Layer.provide(ProviderHostLive.layer))), // Shared native/canonical NDJSON writers used by both the per-instance // V2 drivers and the orchestration runtime. Provide resource attribution so // the rewritten telemetry pipeline can account for logical NDJSON writes. diff --git a/apps/server/src/terminal/Manager.test.ts b/apps/server/src/terminal/Manager.test.ts index 95819d285236886ae43f1cde57f31464e55febd5..5a40f7bbb93346679aa53458a576dc7a699eb0be 100644 --- a/apps/server/src/terminal/Manager.test.ts +++ b/apps/server/src/terminal/Manager.test.ts @@ -41,7 +41,7 @@ import * as SqlitePersistence from "../persistence/Sqlite.ts"; import * as ProcessRunner from "../processRunner.ts"; import * as ServerSettings from "../serverSettings.ts"; import * as TerminalManager from "./Manager.ts"; -import * as PtyAdapter from "./PtyAdapter.ts"; +import * as PtyAdapter from "@t3tools/shared/PtyAdapter"; const encodeUnknownJson = Schema.encodeUnknownSync(Schema.fromJsonString(Schema.Unknown)); diff --git a/apps/server/src/terminal/Manager.ts b/apps/server/src/terminal/Manager.ts index 23b9e549e0de056605142d23e9f7fbed7bcdf780..562307477dcf7a045bd073748e907939a8c4612b 100644 --- a/apps/server/src/terminal/Manager.ts +++ b/apps/server/src/terminal/Manager.ts @@ -45,7 +45,7 @@ import * as KeyedLock from "@t3tools/shared/KeyedLock"; import { HostProcessArchitecture, HostProcessPlatform } from "@t3tools/shared/hostProcess"; import { mergePathEntries } from "@t3tools/shared/shell"; -import { acpRegistryManagedBinaryDirectories } from "../provider/acp/AcpRegistrySupport.ts"; +import { acpRegistryManagedBinaryDirectories } from "@t3tools/provider-acp-registry/server"; import { getTerminalLabel } from "@t3tools/shared/terminalLabels"; import * as DateTime from "effect/DateTime"; import * as Context from "effect/Context"; @@ -77,7 +77,7 @@ import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; import * as ProcessRunner from "../processRunner.ts"; import * as PortScanner from "../preview/PortScanner.ts"; import * as NativeTelemetryClient from "../resourceTelemetry/NativeTelemetryClient.ts"; -import * as PtyAdapter from "./PtyAdapter.ts"; +import * as PtyAdapter from "@t3tools/shared/PtyAdapter"; export { TerminalCwdError, diff --git a/apps/server/src/terminal/NodePtyAdapter.test.ts b/apps/server/src/terminal/NodePtyAdapter.test.ts index fbfa62ab993a81f97ccb165a379d8bb6054ac8ef..e8c2e4d75ff75b87ed2d2cd44e4a470c47f6c692 100644 --- a/apps/server/src/terminal/NodePtyAdapter.test.ts +++ b/apps/server/src/terminal/NodePtyAdapter.test.ts @@ -14,7 +14,7 @@ import * as Scheduler from "effect/Scheduler"; import { expect, vi } from "vite-plus/test"; import * as NodePtyAdapter from "./NodePtyAdapter.ts"; -import * as PtyAdapter from "./PtyAdapter.ts"; +import * as PtyAdapter from "@t3tools/shared/PtyAdapter"; function makeNativeProcess(pid = 42) { const events = new NodeEvents.EventEmitter(); diff --git a/apps/server/src/terminal/NodePtyAdapter.ts b/apps/server/src/terminal/NodePtyAdapter.ts index 8ba78ee4d288bb1d51444d60a1cd4981123915a6..ed4aee84006efa2844bd5b667093bc937795feed 100644 --- a/apps/server/src/terminal/NodePtyAdapter.ts +++ b/apps/server/src/terminal/NodePtyAdapter.ts @@ -9,7 +9,7 @@ import * as Path from "effect/Path"; import * as Schema from "effect/Schema"; import { HostProcessArchitecture, HostProcessPlatform } from "@t3tools/shared/hostProcess"; -import * as PtyAdapter from "./PtyAdapter.ts"; +import * as PtyAdapter from "@t3tools/shared/PtyAdapter"; export class NodePtyModuleLoadError extends Schema.TaggedError()( "NodePtyModuleLoadError", diff --git a/apps/server/src/ws.ts b/apps/server/src/ws.ts index 31b07cea2baf34997f7447e29a9863a62dd029eb..1b045f7e963f1ddf8d933275937b78eee25f2c8a 100644 --- a/apps/server/src/ws.ts +++ b/apps/server/src/ws.ts @@ -165,8 +165,8 @@ import * as OrchestrationEventStore from "./persistence/OrchestrationEventStore. import { userFacingDispatchErrorMessage } from "./orchestration-v2/UserFacingErrors.ts"; import * as ProviderRegistry from "./provider/ProviderRegistry.ts"; import * as ProviderInstanceRegistry from "./provider/ProviderInstanceRegistry.ts"; -import * as AcpRegistrySupport from "./provider/acp/AcpRegistrySupport.ts"; -import * as AcpRegistryRuntimeCoordinator from "./provider/acp/AcpRegistryRuntimeCoordinator.ts"; +import * as AcpRegistrySupport from "@t3tools/provider-acp-registry/server/AcpRegistrySupport"; +import * as AcpRegistryRuntimeCoordinator from "@t3tools/provider-acp-registry/server/AcpRegistryRuntimeCoordinator"; import * as ModelManifest from "./provider/ModelManifest.ts"; import * as ProviderMaintenance from "@t3tools/provider-core/server/maintenanceResolver"; import * as ProviderMaintenanceRunner from "./provider/providerMaintenanceRunner.ts"; diff --git a/apps/web/package.json b/apps/web/package.json index 5e9c5e1e97852aaf70f268a537f82773d68d7c04..1d2d93ed36a93e4a83e25e11924f16877a7961af 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -28,6 +28,7 @@ "@pierre/trees": "1.0.0-beta.6", "@t3tools/client-runtime": "workspace:*", "@t3tools/contracts": "workspace:*", + "@t3tools/provider-acp-registry": "workspace:*", "@t3tools/provider-core": "workspace:*", "@t3tools/provider-cursor": "workspace:*", "@t3tools/provider-grok": "workspace:*", diff --git a/apps/web/src/components/settings/providerDriverMeta.ts b/apps/web/src/components/settings/providerDriverMeta.ts index e18a271f9278b38bd87428e37f727369086790d9..b64f5d714badd24b8eaa8a8aa125244596460e33 100644 --- a/apps/web/src/components/settings/providerDriverMeta.ts +++ b/apps/web/src/components/settings/providerDriverMeta.ts @@ -1,10 +1,10 @@ import { - AcpRegistrySettings, AntigravitySettings, ClaudeSettings, CodexSettings, ProviderDriverKind, } from "@t3tools/contracts"; +import { acpRegistryClient } from "@t3tools/provider-acp-registry/client"; import { makeProviderClientRegistry } from "@t3tools/provider-core/client"; import { cursorClient } from "@t3tools/provider-cursor/client"; import { grokClient } from "@t3tools/provider-grok/client"; @@ -34,10 +34,5 @@ export const providerClients = makeProviderClientRegistry([ }, museClient, piClient, - { - driverKind: ProviderDriverKind.make("acpRegistry"), - label: "ACP Registry", - settingsSchema: AcpRegistrySettings, - hasDefaultInstance: false, - }, + acpRegistryClient, ]); diff --git a/package.json b/package.json index df724bd09a289136ce73673c1b07f8abdeac45cc..55869fc4b3911ff6b6486767dea7fc9a9230ab7a 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-acp --workspace packages/provider-testing --workspace packages/provider-pi --workspace packages/provider-muse --workspace packages/provider-opencode --workspace packages/provider-cursor --workspace packages/provider-grok --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-acp-registry --workspace packages/provider-testing --workspace packages/provider-pi --workspace packages/provider-muse --workspace packages/provider-opencode --workspace packages/provider-cursor --workspace packages/provider-grok --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/contracts/src/settings.ts b/packages/contracts/src/settings.ts index bd8af77a4ea15dab19fdcfa8a6e2b258be10522e..0e8027b9f5fdcef949d2802c5d5903c09165146e 100644 --- a/packages/contracts/src/settings.ts +++ b/packages/contracts/src/settings.ts @@ -788,73 +788,6 @@ export const AntigravitySettings = makeProviderSettingsSchema( ); export type AntigravitySettings = typeof AntigravitySettings.Type; -export const AcpRegistryDistributionPreference = Schema.Literals(["auto", "binary", "npx", "uvx"]); -export type AcpRegistryDistributionPreference = typeof AcpRegistryDistributionPreference.Type; - -export const AcpRegistrySettings = makeProviderSettingsSchema( - { - source: Schema.Literals(["registry", "local"]).pipe( - Schema.withDecodingDefault(Effect.succeed("registry")), - Schema.annotateKey({ - title: "ACP source", - providerSettingsForm: { - control: "select", - options: [ - { value: "registry", label: "ACP Registry" }, - { value: "local", label: "Local command" }, - ], - }, - }), - ), - enabled: Schema.Boolean.pipe( - Schema.withDecodingDefault(Effect.succeed(true)), - Schema.annotateKey({ providerSettingsForm: { hidden: true } }), - ), - agentId: TrimmedString.pipe( - Schema.withDecodingDefault(Effect.succeed("")), - Schema.annotateKey({ - title: "Registry agent ID", - description: "Agent identifier from the official ACP Registry, for example 'devin'.", - providerSettingsForm: { placeholder: "devin", clearWhenEmpty: "persist" }, - }), - ), - commandPath: TrimmedString.pipe( - Schema.withDecodingDefault(Effect.succeed("")), - Schema.annotateKey({ - title: "Executable override", - description: - "Executable on this environment. For registry agents, this overrides the distribution executable while keeping its arguments and environment.", - providerSettingsForm: { placeholder: "Registry default", clearWhenEmpty: "omit" }, - }), - ), - commandArgs: Schema.Array(Schema.String).pipe( - Schema.withDecodingDefault(Effect.succeed([])), - Schema.annotateKey({ providerSettingsForm: { hidden: true } }), - ), - authMethodId: TrimmedString.pipe( - Schema.withDecodingDefault(Effect.succeed("")), - Schema.annotateKey({ - title: "Authentication method", - description: - "Optional ACP authentication method ID. By default, the first agent-managed method is selected.", - providerSettingsForm: { placeholder: "auto", clearWhenEmpty: "omit" }, - }), - ), - distribution: AcpRegistryDistributionPreference.pipe( - Schema.withDecodingDefault(Effect.succeed("auto")), - Schema.annotateKey({ providerSettingsForm: { hidden: true } }), - ), - customModels: Schema.Array(Schema.String).pipe( - Schema.withDecodingDefault(Effect.succeed([])), - Schema.annotateKey({ providerSettingsForm: { hidden: true } }), - ), - }, - { - order: ["source", "agentId", "commandPath", "authMethodId"], - }, -); -export type AcpRegistrySettings = typeof AcpRegistrySettings.Type; - /** * A read-only quota source outside this environment's provider CLIs. The * only kind today is a CLIProxyAPI hub, whose management API reports the diff --git a/packages/provider-acp-registry/package.json b/packages/provider-acp-registry/package.json new file mode 100644 index 0000000000000000000000000000000000000000..a9c474a9148f89b255714c69f23dea7e0d179c3e --- /dev/null +++ b/packages/provider-acp-registry/package.json @@ -0,0 +1,51 @@ +{ + "name": "@t3tools/provider-acp-registry", + "private": true, + "type": "module", + "exports": { + "./client": { + "types": "./src/client.ts", + "import": "./src/client.ts" + }, + "./settings": { + "types": "./src/settings.ts", + "import": "./src/settings.ts" + }, + "./server": { + "types": "./src/server.ts", + "import": "./src/server.ts" + }, + "./testing": { + "types": "./src/testing.ts", + "import": "./src/testing.ts" + }, + "./server/AcpRegistrySupport": { + "types": "./src/server/AcpRegistrySupport.ts", + "import": "./src/server/AcpRegistrySupport.ts" + }, + "./server/AcpRegistryRuntimeCoordinator": { + "types": "./src/server/AcpRegistryRuntimeCoordinator.ts", + "import": "./src/server/AcpRegistryRuntimeCoordinator.ts" + } + }, + "scripts": { + "typecheck": "tsc --noEmit", + "test": "vp test run --config ../../vite.config.ts --dir ." + }, + "dependencies": { + "@noble/hashes": "catalog:", + "@t3tools/contracts": "workspace:*", + "@t3tools/provider-acp": "workspace:*", + "@t3tools/provider-core": "workspace:*", + "@t3tools/shared": "workspace:*", + "effect": "catalog:" + }, + "devDependencies": { + "@effect/platform-node": "catalog:", + "@effect/vitest": "catalog:", + "@t3tools/provider-testing": "workspace:*", + "@types/node": "catalog:", + "effect-acp": "workspace:*", + "vite-plus": "catalog:" + } +} diff --git a/packages/provider-acp-registry/src/client.ts b/packages/provider-acp-registry/src/client.ts new file mode 100644 index 0000000000000000000000000000000000000000..9d5cbd2fdce079ba912cbcb1e8794770e359c00f --- /dev/null +++ b/packages/provider-acp-registry/src/client.ts @@ -0,0 +1,28 @@ +/** + * ACP Registry's client definition: settings form, label, and the registry + * glyph clients fall back to while an agent's own icon loads. + * Browser- and React Native-safe. + * + * @module provider-acp-registry/client + */ +import { ProviderDriverKind } from "@t3tools/contracts"; +import { defineProviderClient } from "@t3tools/provider-core/client"; + +import { AcpRegistrySettings } from "./settings.ts"; + +export const acpRegistryClient = defineProviderClient({ + driverKind: ProviderDriverKind.make("acpRegistry"), + label: "ACP Registry", + settingsSchema: AcpRegistrySettings, + // Each instance is an agent the user adds from the registry. + hasDefaultInstance: false, + icon: { + viewBox: "0 0 576 220", + fill: { light: "#000000", dark: "#FFFFFF" }, + paths: [ + { + d: "M568.003 115.821L517.278 27.9661C507.183 10.4816 489.084 0.0227367 468.894 0.0227367C448.727 0.0227367 430.674 10.4361 420.556 27.8752L343.251 161.749H242.755C236.23 161.749 230.386 158.384 227.135 152.745C223.861 147.106 223.861 140.376 227.135 134.715L277.861 46.8603C281.112 41.2216 286.955 37.8338 293.481 37.8338C300.006 37.8338 305.827 41.1988 309.101 46.8603L312.125 52.0897C313.353 54.2042 315.604 55.5002 318.036 55.5002C320.469 55.5002 322.743 54.1815 323.948 52.067L337.385 28.5118C338.795 26.0335 338.522 22.9413 336.703 20.7586C325.699 7.57131 309.874 0 293.322 0C292.662 0 292.003 0 291.321 0.0454733C272.04 0.75031 254.76 11.1864 245.074 27.9434L200.215 105.657L155.81 29.1484C145.465 11.2092 126.594 0.0227367 106.608 0.0227367C105.949 0.0227367 105.289 0.0227367 104.607 0.06821C85.3265 0.773047 68.0467 11.2092 58.3608 27.9661L7.65806 115.821C-6.25678 139.899 -0.868187 168.82 21.05 187.759C29.8945 195.422 41.6039 199.628 54.0181 199.628H148.648C151.081 199.628 153.332 198.332 154.56 196.217L168.52 172.026C169.748 169.911 169.748 167.319 168.52 165.205C167.292 163.09 165.041 161.794 162.608 161.794H56.0417C49.5163 161.794 43.6729 158.429 40.4216 152.79C37.1475 147.152 37.1475 140.422 40.4216 134.76L91.1471 46.9057C94.3985 41.2671 100.242 37.8793 106.767 37.8793C113.293 37.8793 119.113 41.2443 122.387 46.9057L194.826 172.526C195.031 172.89 195.258 173.208 195.531 173.526C198.76 178.665 202.83 183.485 207.786 187.782C216.631 195.444 228.34 199.651 240.754 199.651H321.424L315.581 209.769C314.353 211.883 314.353 214.475 315.581 216.59C316.809 218.704 319.059 220 321.492 220H349.436C351.868 220 354.119 218.704 355.347 216.59L364.396 200.901L367.17 196.468C367.17 196.468 367.261 196.331 367.284 196.263L453.274 46.9285C456.525 41.2898 462.369 37.902 468.894 37.902C475.42 37.902 481.263 41.2671 484.514 46.9285L535.24 134.783C538.491 140.422 538.514 147.174 535.24 152.813C531.988 158.452 526.145 161.84 519.62 161.84H418.669C416.236 161.84 413.985 163.136 412.757 165.25L398.774 189.442C397.546 191.556 397.546 194.148 398.774 196.263C400.002 198.377 402.253 199.673 404.686 199.673H518.21C539.81 199.673 559.295 188.237 569.026 169.843C578.053 152.79 577.666 132.623 567.981 115.843L568.003 115.821Z", + }, + ], + }, +}); diff --git a/packages/provider-acp-registry/src/server.ts b/packages/provider-acp-registry/src/server.ts new file mode 100644 index 0000000000000000000000000000000000000000..b8ca0bbe1872948f28a40f3ee4763b334a462446 --- /dev/null +++ b/packages/provider-acp-registry/src/server.ts @@ -0,0 +1,16 @@ +/** + * ACP Registry's server entry: the driver and adapter driver the server + * registers, the catalog layer it provides once, and the managed-binary + * directories the terminal manager keeps off agent PATHs. + * + * The catalog and runtime coordinator are services; import them from + * `./server/AcpRegistrySupport` and `./server/AcpRegistryRuntimeCoordinator`. + * + * @module provider-acp-registry/server + */ +export { AcpRegistryDriver, type AcpRegistryDriverEnv } from "./server/driver.ts"; +export { + AcpRegistryAdapterV2Driver, + type AcpRegistryAdapterV2DriverEnv, +} from "./server/adapter.ts"; +export { acpRegistryManagedBinaryDirectories } from "./server/AcpRegistrySupport.ts"; diff --git a/apps/server/src/provider/acp/AcpRegistryRuntimeCoordinator.test.ts b/packages/provider-acp-registry/src/server/AcpRegistryRuntimeCoordinator.test.ts similarity index 91% rename from apps/server/src/provider/acp/AcpRegistryRuntimeCoordinator.test.ts rename to packages/provider-acp-registry/src/server/AcpRegistryRuntimeCoordinator.test.ts index 619d794db8335fca46892008ad3840be5263d098..6fd3d627f05fac2712dbce6ab641939e44792cec 100644 --- a/apps/server/src/provider/acp/AcpRegistryRuntimeCoordinator.test.ts +++ b/packages/provider-acp-registry/src/server/AcpRegistryRuntimeCoordinator.test.ts @@ -6,10 +6,7 @@ import * as Fiber from "effect/Fiber"; import * as Option from "effect/Option"; import * as TestClock from "effect/testing/TestClock"; -import type { - AcpRegistryAvailableCommands, - AcpRegistryLiveConfiguration, -} from "./AcpRegistryProbe.ts"; +import type { AcpRegistryAvailableCommands, AcpRegistryLiveConfiguration } from "./probe.ts"; import * as AcpRegistryRuntimeCoordinator from "./AcpRegistryRuntimeCoordinator.ts"; describe("AcpRegistryRuntimeCoordinator", () => { @@ -33,10 +30,7 @@ describe("AcpRegistryRuntimeCoordinator", () => { yield* Deferred.succeed(releaseForeground, undefined); yield* Fiber.join(foreground); - }).pipe( - Effect.provide(AcpRegistryRuntimeCoordinator.AcpRegistryRuntimeCoordinator.layer), - Effect.scoped, - ), + }).pipe(Effect.provide(AcpRegistryRuntimeCoordinator.layer), Effect.scoped), ); it.effect("interrupts an active background probe when foreground startup begins", () => @@ -64,10 +58,7 @@ describe("AcpRegistryRuntimeCoordinator", () => { yield* Deferred.succeed(releaseForeground, undefined); yield* Fiber.join(foreground); - }).pipe( - Effect.provide(AcpRegistryRuntimeCoordinator.AcpRegistryRuntimeCoordinator.layer), - Effect.scoped, - ), + }).pipe(Effect.provide(AcpRegistryRuntimeCoordinator.layer), Effect.scoped), ); it.effect("serializes native session mutations across callers", () => @@ -94,10 +85,7 @@ describe("AcpRegistryRuntimeCoordinator", () => { yield* Fiber.join(first); yield* Fiber.join(second); expect(Option.isSome(yield* Deferred.poll(secondEntered))).toBe(true); - }).pipe( - Effect.provide(AcpRegistryRuntimeCoordinator.AcpRegistryRuntimeCoordinator.layer), - Effect.scoped, - ), + }).pipe(Effect.provide(AcpRegistryRuntimeCoordinator.layer), Effect.scoped), ); it.effect("replays and replaces late command advertisements per provider instance", () => @@ -145,10 +133,7 @@ describe("AcpRegistryRuntimeCoordinator", () => { ); yield* coordinator.clearAvailableCommands(codex); expect(Option.isNone(yield* coordinator.getAvailableCommands(codex))).toBe(true); - }).pipe( - Effect.provide(AcpRegistryRuntimeCoordinator.AcpRegistryRuntimeCoordinator.layer), - Effect.scoped, - ), + }).pipe(Effect.provide(AcpRegistryRuntimeCoordinator.layer), Effect.scoped), ); it.effect("replays and replaces live configuration per provider instance", () => @@ -189,10 +174,7 @@ describe("AcpRegistryRuntimeCoordinator", () => { expect(yield* coordinator.getLiveConfiguration(instanceId)).toEqual(Option.some(replacement)); yield* coordinator.clearLiveConfiguration(instanceId); expect(Option.isNone(yield* coordinator.getLiveConfiguration(instanceId))).toBe(true); - }).pipe( - Effect.provide(AcpRegistryRuntimeCoordinator.AcpRegistryRuntimeCoordinator.layer), - Effect.scoped, - ), + }).pipe(Effect.provide(AcpRegistryRuntimeCoordinator.layer), Effect.scoped), ); it.effect("requires matching user consent before accepting URL authentication", () => @@ -234,10 +216,7 @@ describe("AcpRegistryRuntimeCoordinator", () => { expect(yield* Fiber.join(request)).toBe(true); expect(Option.isNone(yield* coordinator.getUrlAuthAction(instanceId))).toBe(true); yield* Fiber.interrupt(consumer); - }).pipe( - Effect.provide(AcpRegistryRuntimeCoordinator.AcpRegistryRuntimeCoordinator.layer), - Effect.scoped, - ), + }).pipe(Effect.provide(AcpRegistryRuntimeCoordinator.layer), Effect.scoped), ); it.effect("expires stale URL authentication actions without accepting them", () => @@ -271,10 +250,7 @@ describe("AcpRegistryRuntimeCoordinator", () => { ).toBe(false); expect(Option.isNone(yield* coordinator.getUrlAuthAction(instanceId))).toBe(true); yield* Fiber.interrupt(consumer); - }).pipe( - Effect.provide(AcpRegistryRuntimeCoordinator.AcpRegistryRuntimeCoordinator.layer), - Effect.scoped, - ), + }).pipe(Effect.provide(AcpRegistryRuntimeCoordinator.layer), Effect.scoped), ); it.effect("publishes a replacement URL action before retiring the previous request", () => @@ -326,10 +302,7 @@ describe("AcpRegistryRuntimeCoordinator", () => { ).toBe(true); expect(yield* Fiber.join(replacement)).toBe(true); yield* Fiber.interrupt(consumer); - }).pipe( - Effect.provide(AcpRegistryRuntimeCoordinator.AcpRegistryRuntimeCoordinator.layer), - Effect.scoped, - ), + }).pipe(Effect.provide(AcpRegistryRuntimeCoordinator.layer), Effect.scoped), ); it.effect("clears a published URL action when its request is interrupted", () => @@ -358,9 +331,6 @@ describe("AcpRegistryRuntimeCoordinator", () => { yield* Deferred.await(cleared); expect(Option.isNone(yield* coordinator.getUrlAuthAction(instanceId))).toBe(true); yield* Fiber.interrupt(consumer); - }).pipe( - Effect.provide(AcpRegistryRuntimeCoordinator.AcpRegistryRuntimeCoordinator.layer), - Effect.scoped, - ), + }).pipe(Effect.provide(AcpRegistryRuntimeCoordinator.layer), Effect.scoped), ); }); diff --git a/apps/server/src/provider/acp/AcpRegistryRuntimeCoordinator.ts b/packages/provider-acp-registry/src/server/AcpRegistryRuntimeCoordinator.ts similarity index 98% rename from apps/server/src/provider/acp/AcpRegistryRuntimeCoordinator.ts rename to packages/provider-acp-registry/src/server/AcpRegistryRuntimeCoordinator.ts index d14f2586b5ba88137ffb0391e3f2aa7fe78ecc67..ef86c87fa1134d801bec98d719661b3a6a559d55 100644 --- a/apps/server/src/provider/acp/AcpRegistryRuntimeCoordinator.ts +++ b/packages/provider-acp-registry/src/server/AcpRegistryRuntimeCoordinator.ts @@ -15,10 +15,7 @@ import * as Ref from "effect/Ref"; import * as Semaphore from "effect/Semaphore"; import * as Stream from "effect/Stream"; -import type { - AcpRegistryAvailableCommands, - AcpRegistryLiveConfiguration, -} from "./AcpRegistryProbe.ts"; +import type { AcpRegistryAvailableCommands, AcpRegistryLiveConfiguration } from "./probe.ts"; interface AvailableCommandsUpdate { readonly instanceId: ProviderInstanceId; @@ -99,11 +96,7 @@ export class AcpRegistryRuntimeCoordinator extends Context.Service< onUpdate: (action: AcpRegistryUrlAuthAction | null) => Effect.Effect, ) => Effect.Effect; } ->()("t3/provider/acp/AcpRegistryRuntimeCoordinator") { - static get layer() { - return layer; - } -} +>()("@t3tools/provider-acp-registry/server/AcpRegistryRuntimeCoordinator") {} const make = Effect.gen(function* () { const foregroundStarts = yield* PubSub.unbounded(); @@ -366,4 +359,4 @@ const make = Effect.gen(function* () { }); }); -const layer = Layer.effect(AcpRegistryRuntimeCoordinator, make); +export const layer = Layer.effect(AcpRegistryRuntimeCoordinator, make); diff --git a/apps/server/src/provider/acp/AcpRegistrySupport.test.ts b/packages/provider-acp-registry/src/server/AcpRegistrySupport.test.ts similarity index 97% rename from apps/server/src/provider/acp/AcpRegistrySupport.test.ts rename to packages/provider-acp-registry/src/server/AcpRegistrySupport.test.ts index 959fab6e256e81d25a69fbd2c4978fb3fb712581..35cf0f199b9da79b593f107b03d890467a21baa5 100644 --- a/apps/server/src/provider/acp/AcpRegistrySupport.test.ts +++ b/packages/provider-acp-registry/src/server/AcpRegistrySupport.test.ts @@ -1,6 +1,11 @@ import * as NodeServices from "@effect/platform-node/NodeServices"; import { describe, expect, it } from "@effect/vitest"; -import { AcpRegistrySettings, ProviderDriverKind, ProviderInstanceId } from "@t3tools/contracts"; +import { + DEFAULT_SERVER_SETTINGS, + ProviderDriverKind, + ProviderInstanceId, +} from "@t3tools/contracts"; +import { AcpRegistrySettings } from "../settings.ts"; import { HostProcessArchitecture, HostProcessEnvironment, @@ -19,7 +24,7 @@ import * as TestClock from "effect/testing/TestClock"; import { ChildProcess, ChildProcessSpawner } from "effect/process"; import * as AcpRegistrySupport from "./AcpRegistrySupport.ts"; -import * as ServerSettings from "../../serverSettings.ts"; +import { layerTestProviderHost, TestProviderHostSettings } from "@t3tools/provider-testing/host"; const registryUrl = "https://registry.test/registry.json"; const archiveUrl = "https://registry.test/example-agent.bin"; @@ -55,7 +60,7 @@ function layerResolver( ) { return Layer.mergeAll( NodeServices.layer, - ServerSettings.layerTest(), + layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), Layer.succeed(HostProcessPlatform, "linux"), Layer.succeed(HostProcessArchitecture, "x64"), Layer.succeed(HostProcessEnvironment, environment), @@ -768,7 +773,12 @@ describe("AcpRegistrySupport", () => { ); }).pipe( Effect.scoped, - Effect.provide(Layer.mergeAll(NodeServices.layer, ServerSettings.layerTest())), + Effect.provide( + Layer.mergeAll( + NodeServices.layer, + layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), + ), + ), Effect.provideService(HostProcessPlatform, "linux"), Effect.provideService(HostProcessArchitecture, "x64"), ); @@ -1364,26 +1374,27 @@ describe("AcpRegistrySupport", () => { toolsDir: `${cacheDir}/tools`, registryUrl, }); - const serverSettings = yield* ServerSettings.ServerSettingsService; + const hostSettings = yield* TestProviderHostSettings; const instanceId = ProviderInstanceId.make("uninstall-reference"); - yield* serverSettings.updateProviderInstance({ - operation: "upsert", - instanceId, - instance: { - driver: ProviderDriverKind.make("acpRegistry"), - displayName: "Uninstall reference", - enabled: true, - config: { - agentId, - commandPath: "/local/agent", - ...(source ? { source } : {}), + yield* hostSettings.set({ + ...DEFAULT_SERVER_SETTINGS, + providerInstances: { + [instanceId]: { + driver: ProviderDriverKind.make("acpRegistry"), + displayName: "Uninstall reference", + enabled: true, + config: { + agentId, + commandPath: "/local/agent", + ...(source ? { source } : {}), + }, }, }, }); const first = yield* resolver.uninstallManagedBinary({ agentId: "example-agent" }); expect(first).toEqual({ agentId: "example-agent", removed: !referenced }); expect(yield* fileSystem.exists(agentRoot)).toBe(referenced); - yield* serverSettings.updateProviderInstance({ operation: "remove", instanceId }); + yield* hostSettings.set(DEFAULT_SERVER_SETTINGS); const second = yield* resolver.uninstallManagedBinary({ agentId: "example-agent" }); expect(second).toEqual({ agentId: "example-agent", removed: referenced }); @@ -1481,23 +1492,24 @@ describe("AcpRegistrySupport", () => { const agentRoot = `${cacheDir}/tools/${agent.id}`; expect(yield* fileSystem.exists(agentRoot)).toBe(true); - const serverSettings = yield* ServerSettings.ServerSettingsService; + const hostSettings = yield* TestProviderHostSettings; const instanceId = ProviderInstanceId.make("registry-reference"); - yield* serverSettings.updateProviderInstance({ - operation: "upsert", - instanceId, - instance: { - driver: ProviderDriverKind.make("acpRegistry"), - displayName: "Registry reference", - enabled: true, - config: { agentId: agent.id }, + yield* hostSettings.set({ + ...DEFAULT_SERVER_SETTINGS, + providerInstances: { + [instanceId]: { + driver: ProviderDriverKind.make("acpRegistry"), + displayName: "Registry reference", + enabled: true, + config: { agentId: agent.id }, + }, }, }); expect(yield* resolver.uninstallManagedBinary({ agentId: agent.id })).toEqual({ agentId: agent.id, removed: false, }); - yield* serverSettings.updateProviderInstance({ operation: "remove", instanceId }); + yield* hostSettings.set(DEFAULT_SERVER_SETTINGS); expect(yield* resolver.uninstallManagedBinary({ agentId: agent.id })).toEqual({ agentId: agent.id, removed: true, diff --git a/apps/server/src/provider/acp/AcpRegistrySupport.ts b/packages/provider-acp-registry/src/server/AcpRegistrySupport.ts similarity index 98% rename from apps/server/src/provider/acp/AcpRegistrySupport.ts rename to packages/provider-acp-registry/src/server/AcpRegistrySupport.ts index dd4ef66f7876d36d151da14f3f3aca2dd31d57b4..9055f9e070ebbba03e3f861edaf5b0f5dfd2430a 100644 --- a/apps/server/src/provider/acp/AcpRegistrySupport.ts +++ b/packages/provider-acp-registry/src/server/AcpRegistrySupport.ts @@ -9,9 +9,9 @@ import { type AcpRegistrySearchInput, type AcpRegistrySearchResult, type AcpRegistryDistribution as AcpRegistryDistributionKind, - type AcpRegistryDistributionPreference, - type AcpRegistrySettings, } from "@t3tools/contracts"; +import type { AcpRegistryDistributionPreference } from "../settings.ts"; +import type { AcpRegistrySettings } from "../settings.ts"; import { HostProcessArchitecture, HostProcessEnvironment, @@ -32,6 +32,7 @@ import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import * as Path from "effect/Path"; +import * as AcpRegistryRuntimeCoordinator from "./AcpRegistryRuntimeCoordinator.ts"; import * as PlatformError from "effect/PlatformError"; import * as Ref from "effect/Ref"; import * as Schema from "effect/Schema"; @@ -42,7 +43,7 @@ import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/http"; import { ChildProcess, ChildProcessSpawner } from "effect/process"; import { collectUint8StreamText } from "@t3tools/provider-core/server/collectStreamText"; -import * as ServerSettings from "../../serverSettings.ts"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; const ACP_REGISTRY_URL = "https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json"; @@ -503,11 +504,30 @@ export class AcpRegistryCatalog extends Context.Service< input: AcpRegistryManagedBinaryUninstallInput, ) => Effect.Effect; } ->()("t3/provider/acp/AcpRegistrySupport/AcpRegistryCatalog") { - static layer(options: AcpRegistryCatalogOptions) { - return Layer.effect(AcpRegistryCatalog, makeAcpRegistryCatalog(options)); - } -} +>()("@t3tools/provider-acp-registry/server/AcpRegistrySupport/AcpRegistryCatalog") {} + +const layer = (options: AcpRegistryCatalogOptions) => + Layer.effect(AcpRegistryCatalog, makeAcpRegistryCatalog(options)); + +/** + * The server-lifetime catalog, with the runtime coordinator built alongside + * it so setup, snapshots, and turn launch share one of each. Its cache lives + * in the host's provider status cache and installed agents under the T3 + * home's `tools` directory. + */ +export const layerFromHost = Layer.merge( + Layer.unwrap( + Effect.gen(function* () { + const { paths } = yield* ProviderHost.ProviderHost; + const path = yield* Path.Path; + return layer({ + cacheDir: paths.providerStatusCacheDir, + toolsDir: path.join(paths.baseDir, "tools"), + }); + }), + ), + AcpRegistryRuntimeCoordinator.layer, +); export interface AcpRegistryCatalogOptions { readonly cacheDir: string; @@ -603,7 +623,7 @@ export const makeAcpRegistryCatalog = Effect.fn("AcpRegistryCatalog.make")(funct | FileSystem.FileSystem | HttpClient.HttpClient | Path.Path - | ServerSettings.ServerSettingsService + | ProviderHost.ProviderHost > { const crypto = yield* Crypto.Crypto; const sha256Hex = (data: Uint8Array) => @@ -612,7 +632,7 @@ export const makeAcpRegistryCatalog = Effect.fn("AcpRegistryCatalog.make")(funct const path = yield* Path.Path; const httpClient = yield* HttpClient.HttpClient; const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; - const serverSettings = yield* ServerSettings.ServerSettingsService; + const { settings: hostSettings } = yield* ProviderHost.ProviderHost; const platform = yield* HostProcessPlatform; const architecture = yield* HostProcessArchitecture; const hostEnvironment = yield* HostProcessEnvironment; @@ -1842,8 +1862,8 @@ export const makeAcpRegistryCatalog = Effect.fn("AcpRegistryCatalog.make")(funct }); const uninstallManagedBinary: AcpRegistryCatalog["Service"]["uninstallManagedBinary"] = (input) => - serverSettings - .withSettingsSnapshot((settings) => + hostSettings + .withSnapshot((settings) => installSemaphore.withPermits(1)( Effect.gen(function* () { const safeAgentId = yield* decodeBoundedAgentId(input.agentId).pipe( diff --git a/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.ts b/packages/provider-acp-registry/src/server/adapter.ts similarity index 96% rename from apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.ts rename to packages/provider-acp-registry/src/server/adapter.ts index 99168e136592e4f1ca2c01b8f4f7d073c6261c9b..223aef7b81d2783735e485bc51be4a956247e028 100644 --- a/apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.ts +++ b/packages/provider-acp-registry/src/server/adapter.ts @@ -2,12 +2,9 @@ import { normalizeDevinSessionUpdate, normalizeDevinToolCall, extractDevinSubagentUpdate, -} from "./DevinAcp.ts"; -import { - AcpRegistrySettings, - defaultInstanceIdForDriver, - ProviderDriverKind, -} from "@t3tools/contracts"; +} from "./devinAcp.ts"; +import { defaultInstanceIdForDriver, ProviderDriverKind } from "@t3tools/contracts"; +import { AcpRegistrySettings } from "../settings.ts"; import { HostProcessEnvironment } from "@t3tools/shared/hostProcess"; import { resolveSelfInvocation, type SelfInvocation } from "@t3tools/shared/nodeRuntime"; import * as Crypto from "effect/Crypto"; @@ -26,12 +23,12 @@ import { normalizeAcpRegistryCommands, normalizeAcpRegistryLiveConfiguration, normalizeAcpRegistryWebUrl, -} from "../../provider/acp/AcpRegistryProbe.ts"; -import * as AcpRegistrySupport from "../../provider/acp/AcpRegistrySupport.ts"; -import * as AcpRegistryRuntimeCoordinator from "../../provider/acp/AcpRegistryRuntimeCoordinator.ts"; +} from "./probe.ts"; +import * as AcpRegistrySupport from "./AcpRegistrySupport.ts"; +import * as AcpRegistryRuntimeCoordinator from "./AcpRegistryRuntimeCoordinator.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 * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; import { mergeProviderInstanceEnvironment } from "@t3tools/provider-core/server/instanceEnvironment"; import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; import { makeProviderFailure } from "@t3tools/provider-core/server/failure"; diff --git a/apps/server/src/provider/acp/AcpRegistryAuth.test.ts b/packages/provider-acp-registry/src/server/auth.test.ts similarity index 98% rename from apps/server/src/provider/acp/AcpRegistryAuth.test.ts rename to packages/provider-acp-registry/src/server/auth.test.ts index f19be06f26341c31fb8479d605ba17df7974875a..5a9fc049c4937a42ef77aa4ea3db27deefd1ad65 100644 --- a/apps/server/src/provider/acp/AcpRegistryAuth.test.ts +++ b/packages/provider-acp-registry/src/server/auth.test.ts @@ -1,10 +1,7 @@ import * as NodeServices from "@effect/platform-node/NodeServices"; import { assert, it } from "@effect/vitest"; -import { - AcpRegistrySettings, - ProviderInstanceId, - type ProviderAuthState, -} from "@t3tools/contracts"; +import { ProviderInstanceId, type ProviderAuthState } from "@t3tools/contracts"; +import { AcpRegistrySettings } from "../settings.ts"; import * as Deferred from "effect/Deferred"; import * as Effect from "effect/Effect"; import * as Option from "effect/Option"; @@ -13,8 +10,8 @@ import * as Stream from "effect/Stream"; import type * as AcpSchema from "effect-acp/compat"; import { AcpRequestError } from "effect-acp/errors"; -import * as PtyAdapter from "../../terminal/PtyAdapter.ts"; -import { makeAcpRegistryAuth } from "./AcpRegistryAuth.ts"; +import * as PtyAdapter from "@t3tools/shared/PtyAdapter"; +import { makeAcpRegistryAuth } from "./auth.ts"; import * as AcpRegistrySupport from "./AcpRegistrySupport.ts"; import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; diff --git a/apps/server/src/provider/acp/AcpRegistryAuth.ts b/packages/provider-acp-registry/src/server/auth.ts similarity index 98% rename from apps/server/src/provider/acp/AcpRegistryAuth.ts rename to packages/provider-acp-registry/src/server/auth.ts index 3232b7b370a20a75d59b27a37c6afda9953cf235..7189d5a4fdec6e17d64b858bcda94fa5fc0e8e2a 100644 --- a/apps/server/src/provider/acp/AcpRegistryAuth.ts +++ b/packages/provider-acp-registry/src/server/auth.ts @@ -1,9 +1,9 @@ import { ProviderSetupError, - type AcpRegistrySettings, type ProviderAuthMethod, type ProviderInstanceId, } from "@t3tools/contracts"; +import type { AcpRegistrySettings } from "../settings.ts"; import * as Crypto from "effect/Crypto"; import * as Deferred from "effect/Deferred"; import * as Effect from "effect/Effect"; @@ -15,9 +15,9 @@ import * as Scope from "effect/Scope"; import { ChildProcessSpawner } from "effect/process"; import type * as AcpSchema from "effect-acp/compat"; -import * as PtyAdapter from "../../terminal/PtyAdapter.ts"; -import * as ProviderAuthFlow from "../ProviderAuthFlow.ts"; -import { normalizeAcpRegistryAuthMethods, normalizeAcpRegistryWebUrl } from "./AcpRegistryProbe.ts"; +import * as PtyAdapter from "@t3tools/shared/PtyAdapter"; +import * as ProviderAuthFlow from "@t3tools/provider-core/server/ProviderAuthFlow"; +import { normalizeAcpRegistryAuthMethods, normalizeAcpRegistryWebUrl } from "./probe.ts"; import * as AcpRegistrySupport from "./AcpRegistrySupport.ts"; import * as AcpRegistryRuntimeCoordinator from "./AcpRegistryRuntimeCoordinator.ts"; import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; diff --git a/apps/server/src/provider/acp/AcpRegistryAuthenticationState.test.ts b/packages/provider-acp-registry/src/server/authenticationState.test.ts similarity index 95% rename from apps/server/src/provider/acp/AcpRegistryAuthenticationState.test.ts rename to packages/provider-acp-registry/src/server/authenticationState.test.ts index 8f5e1ba63c2c1d1f37f28f8ed83cb3037a1a65dc..ee3edcee49236605cc1edc286c61b0eef70428b3 100644 --- a/apps/server/src/provider/acp/AcpRegistryAuthenticationState.test.ts +++ b/packages/provider-acp-registry/src/server/authenticationState.test.ts @@ -1,11 +1,12 @@ import * as NodeServices from "@effect/platform-node/NodeServices"; import { assert, it } from "@effect/vitest"; -import { AcpRegistrySettings, ProviderInstanceId } from "@t3tools/contracts"; +import { ProviderInstanceId } from "@t3tools/contracts"; +import { AcpRegistrySettings } from "../settings.ts"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; import * as Schema from "effect/Schema"; -import { makeAcpRegistryAuthenticationState } from "./AcpRegistryAuthenticationState.ts"; +import { makeAcpRegistryAuthenticationState } from "./authenticationState.ts"; const settings = Schema.decodeSync(AcpRegistrySettings)({ agentId: "devin" }); diff --git a/apps/server/src/provider/acp/AcpRegistryAuthenticationState.ts b/packages/provider-acp-registry/src/server/authenticationState.ts similarity index 95% rename from apps/server/src/provider/acp/AcpRegistryAuthenticationState.ts rename to packages/provider-acp-registry/src/server/authenticationState.ts index 986ed6d0ca72784cedb2ee49a66b773f51e6aaa1..f01f8f2a8dab2252261be4fbdce9de167c51730d 100644 --- a/apps/server/src/provider/acp/AcpRegistryAuthenticationState.ts +++ b/packages/provider-acp-registry/src/server/authenticationState.ts @@ -1,8 +1,5 @@ -import type { - AcpRegistrySettings, - ProviderInstanceEnvironment, - ProviderInstanceId, -} from "@t3tools/contracts"; +import type { ProviderInstanceEnvironment, ProviderInstanceId } from "@t3tools/contracts"; +import type { AcpRegistrySettings } from "../settings.ts"; import * as Crypto from "effect/Crypto"; import * as Effect from "effect/Effect"; import * as Hex from "effect/encoding/Hex"; diff --git a/apps/server/src/orchestration-v2/Adapters/DevinAcp.ts b/packages/provider-acp-registry/src/server/devinAcp.ts similarity index 100% rename from apps/server/src/orchestration-v2/Adapters/DevinAcp.ts rename to packages/provider-acp-registry/src/server/devinAcp.ts diff --git a/apps/server/src/provider/Drivers/AcpRegistryDriver.test.ts b/packages/provider-acp-registry/src/server/driver.test.ts similarity index 98% rename from apps/server/src/provider/Drivers/AcpRegistryDriver.test.ts rename to packages/provider-acp-registry/src/server/driver.test.ts index ceb9c695a590fa37d03994dc4d4a37e9f6ac259d..3a67cc3d86fdefef54c926f6157ce208d6df576d 100644 --- a/apps/server/src/provider/Drivers/AcpRegistryDriver.test.ts +++ b/packages/provider-acp-registry/src/server/driver.test.ts @@ -1,14 +1,11 @@ -import { - AcpRegistryOperationError, - AcpRegistrySettings, - ProviderInstanceId, -} from "@t3tools/contracts"; +import { AcpRegistryOperationError, ProviderInstanceId } from "@t3tools/contracts"; +import { AcpRegistrySettings } from "../settings.ts"; import { describe, expect, it } from "@effect/vitest"; import * as Effect from "effect/Effect"; import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; -import * as AcpRegistrySupport from "../acp/AcpRegistrySupport.ts"; +import * as AcpRegistrySupport from "./AcpRegistrySupport.ts"; import { acpRegistrySnapshotReadiness, applyAcpRegistryAvailableCommands, @@ -16,7 +13,7 @@ import { buildCheckedAcpRegistrySnapshot, checkAcpRegistryProviderReadiness, checkAcpRegistryProviderStatus, -} from "./AcpRegistryDriver.ts"; +} from "./driver.ts"; const decodeSettings = Schema.decodeSync(AcpRegistrySettings); const identity = { diff --git a/apps/server/src/provider/Drivers/AcpRegistryDriver.ts b/packages/provider-acp-registry/src/server/driver.ts similarity index 97% rename from apps/server/src/provider/Drivers/AcpRegistryDriver.ts rename to packages/provider-acp-registry/src/server/driver.ts index be570db9160c6df995d7a57398ae6e68caadebf4..17ca9ea3ddcbb073577d3639f3b4c35de0606b91 100644 --- a/apps/server/src/provider/Drivers/AcpRegistryDriver.ts +++ b/packages/provider-acp-registry/src/server/driver.ts @@ -1,5 +1,4 @@ import { - AcpRegistrySettings, officialAcpRegistryIconUrlForAgentId, ProviderDriverKind, resolveOfficialAcpRegistryIconUrl, @@ -8,6 +7,7 @@ import { type ServerProvider, type ServerProviderModel, } from "@t3tools/contracts"; +import { AcpRegistrySettings } from "../settings.ts"; import { HostProcessEnvironment } from "@t3tools/shared/hostProcess"; import { createModelCapabilities } from "@t3tools/shared/model"; import * as Clock from "effect/Clock"; @@ -22,12 +22,9 @@ import * as Semaphore from "effect/Semaphore"; import { ChildProcessSpawner } from "effect/process"; import { ProviderHost } from "@t3tools/provider-core/server/ProviderHost"; -import { - AcpRegistryAdapterV2Driver, - type AcpRegistryAdapterV2DriverEnv, -} from "../../orchestration-v2/Adapters/AcpRegistryAdapterV2.ts"; -import type { TextGeneration } from "../../textGeneration/TextGeneration.ts"; -import { ProviderDriverError } from "../Errors.ts"; +import { AcpRegistryAdapterV2Driver, type AcpRegistryAdapterV2DriverEnv } from "./adapter.ts"; +import type { ProviderTextGeneration } from "@t3tools/provider-core/server/textGeneration"; +import { ProviderDriverError } from "@t3tools/provider-core/server/errors"; import { makeManagedServerProvider } from "@t3tools/provider-core/server/managedProvider"; import { mergeProviderInstanceEnvironment } from "@t3tools/provider-core/server/instanceEnvironment"; import { @@ -54,11 +51,11 @@ import { logoutAcpRegistry, probeAcpRegistryConfiguration, setAcpRegistryProvider, -} from "../acp/AcpRegistryProbe.ts"; -import * as AcpRegistrySupport from "../acp/AcpRegistrySupport.ts"; -import * as AcpRegistryRuntimeCoordinator from "../acp/AcpRegistryRuntimeCoordinator.ts"; -import * as AcpRegistryAuth from "../acp/AcpRegistryAuth.ts"; -import * as AcpRegistryAuthenticationState from "../acp/AcpRegistryAuthenticationState.ts"; +} from "./probe.ts"; +import * as AcpRegistrySupport from "./AcpRegistrySupport.ts"; +import * as AcpRegistryRuntimeCoordinator from "./AcpRegistryRuntimeCoordinator.ts"; +import * as AcpRegistryAuth from "./auth.ts"; +import * as AcpRegistryAuthenticationState from "./authenticationState.ts"; const DRIVER_KIND = ProviderDriverKind.make("acpRegistry"); const decodeSettings = Schema.decodeSync(AcpRegistrySettings); @@ -73,7 +70,7 @@ const MAINTENANCE = makeManualOnlyProviderMaintenanceCapabilities({ packageName: null, }); -const makeUnsupportedTextGeneration = (): TextGeneration["Service"] => { +const makeUnsupportedTextGeneration = (): ProviderTextGeneration => { const unsupported = (operation: string) => Effect.fail( new TextGenerationError({ diff --git a/apps/server/src/provider/acp/AcpRegistryProbe.ts b/packages/provider-acp-registry/src/server/probe.ts similarity index 99% rename from apps/server/src/provider/acp/AcpRegistryProbe.ts rename to packages/provider-acp-registry/src/server/probe.ts index 9fc142c35dc3685ee46c5311cd24c15263b40450..c88dacb8f063dd0271749d074584b04fc268f8ba 100644 --- a/apps/server/src/provider/acp/AcpRegistryProbe.ts +++ b/packages/provider-acp-registry/src/server/probe.ts @@ -3,7 +3,6 @@ import { AcpRegistryOperationError, AcpRegistryListSessionsResult, AcpRegistryProbeResult, - AcpRegistrySettings, type AcpRegistryProbeAuthMethod, type AcpRegistryProbeModel, type AcpRegistryUrlAuthAction, @@ -11,6 +10,7 @@ import { type ServerProviderSkill, type ServerProviderSlashCommand, } from "@t3tools/contracts"; +import { AcpRegistrySettings } from "../settings.ts"; import * as Crypto from "effect/Crypto"; import * as Deferred from "effect/Deferred"; import * as Duration from "effect/Duration"; @@ -23,7 +23,7 @@ import { ChildProcessSpawner } from "effect/process"; import type * as EffectAcpErrors from "effect-acp/errors"; import type * as EffectAcpSchema from "effect-acp/compat"; -import * as PtyAdapter from "../../terminal/PtyAdapter.ts"; +import * as PtyAdapter from "@t3tools/shared/PtyAdapter"; import * as AcpRegistrySupport from "./AcpRegistrySupport.ts"; import { parseSessionModeState } from "@t3tools/provider-acp/server/runtimeModel"; import { acpProviderOptionDescriptors } from "@t3tools/provider-acp/server/sessionConfig"; diff --git a/apps/server/src/provider/acp/testing/AcpRegistrySupport.npm.fixture.sh b/packages/provider-acp-registry/src/server/testing/AcpRegistrySupport.npm.fixture.sh similarity index 100% rename from apps/server/src/provider/acp/testing/AcpRegistrySupport.npm.fixture.sh rename to packages/provider-acp-registry/src/server/testing/AcpRegistrySupport.npm.fixture.sh diff --git a/apps/server/src/provider/acp/testing/AcpRegistrySupport.uv.fixture.sh b/packages/provider-acp-registry/src/server/testing/AcpRegistrySupport.uv.fixture.sh similarity index 100% rename from apps/server/src/provider/acp/testing/AcpRegistrySupport.uv.fixture.sh rename to packages/provider-acp-registry/src/server/testing/AcpRegistrySupport.uv.fixture.sh diff --git a/packages/provider-acp-registry/src/settings.ts b/packages/provider-acp-registry/src/settings.ts new file mode 100644 index 0000000000000000000000000000000000000000..bb9274a0598104cf706fc65b90897bb99b0a736c --- /dev/null +++ b/packages/provider-acp-registry/src/settings.ts @@ -0,0 +1,76 @@ +/** + * ACP Registry instance settings. Shared by the server driver and the client + * settings form, so it holds only browser-safe schema code. + * + * @module provider-acp-registry/settings + */ +import { TrimmedString, makeProviderSettingsSchema } from "@t3tools/contracts"; +import * as Effect from "effect/Effect"; +import * as Schema from "effect/Schema"; + +export const AcpRegistryDistributionPreference = Schema.Literals(["auto", "binary", "npx", "uvx"]); +export type AcpRegistryDistributionPreference = typeof AcpRegistryDistributionPreference.Type; + +export const AcpRegistrySettings = makeProviderSettingsSchema( + { + source: Schema.Literals(["registry", "local"]).pipe( + Schema.withDecodingDefault(Effect.succeed("registry")), + Schema.annotateKey({ + title: "ACP source", + providerSettingsForm: { + control: "select", + options: [ + { value: "registry", label: "ACP Registry" }, + { value: "local", label: "Local command" }, + ], + }, + }), + ), + enabled: Schema.Boolean.pipe( + Schema.withDecodingDefault(Effect.succeed(true)), + Schema.annotateKey({ providerSettingsForm: { hidden: true } }), + ), + agentId: TrimmedString.pipe( + Schema.withDecodingDefault(Effect.succeed("")), + Schema.annotateKey({ + title: "Registry agent ID", + description: "Agent identifier from the official ACP Registry, for example 'devin'.", + providerSettingsForm: { placeholder: "devin", clearWhenEmpty: "persist" }, + }), + ), + commandPath: TrimmedString.pipe( + Schema.withDecodingDefault(Effect.succeed("")), + Schema.annotateKey({ + title: "Executable override", + description: + "Executable on this environment. For registry agents, this overrides the distribution executable while keeping its arguments and environment.", + providerSettingsForm: { placeholder: "Registry default", clearWhenEmpty: "omit" }, + }), + ), + commandArgs: Schema.Array(Schema.String).pipe( + Schema.withDecodingDefault(Effect.succeed([])), + Schema.annotateKey({ providerSettingsForm: { hidden: true } }), + ), + authMethodId: TrimmedString.pipe( + Schema.withDecodingDefault(Effect.succeed("")), + Schema.annotateKey({ + title: "Authentication method", + description: + "Optional ACP authentication method ID. By default, the first agent-managed method is selected.", + providerSettingsForm: { placeholder: "auto", clearWhenEmpty: "omit" }, + }), + ), + distribution: AcpRegistryDistributionPreference.pipe( + Schema.withDecodingDefault(Effect.succeed("auto")), + Schema.annotateKey({ providerSettingsForm: { hidden: true } }), + ), + customModels: Schema.Array(Schema.String).pipe( + Schema.withDecodingDefault(Effect.succeed([])), + Schema.annotateKey({ providerSettingsForm: { hidden: true } }), + ), + }, + { + order: ["source", "agentId", "commandPath", "authMethodId"], + }, +); +export type AcpRegistrySettings = typeof AcpRegistrySettings.Type; diff --git a/packages/provider-acp-registry/src/testing.ts b/packages/provider-acp-registry/src/testing.ts new file mode 100644 index 0000000000000000000000000000000000000000..f1c64a89c15c013ea74ba7df67a4d3b25f25532d --- /dev/null +++ b/packages/provider-acp-registry/src/testing.ts @@ -0,0 +1,29 @@ +/** + * ACP Registry internals the server's replay testkit and ACP adapter tests + * drive directly. + * + * @module provider-acp-registry/testing + */ +export { + ACP_REGISTRY_DEFAULT_INSTANCE_ID, + ACP_REGISTRY_PROVIDER, + acpRegistryPromptFailure, + makeAcpRegistryAdapterV2, + registerMistralVibeAcpExtensions, +} from "./server/adapter.ts"; +export { + extractDevinSubagentUpdate, + normalizeDevinSessionUpdate, + normalizeDevinToolCall, +} from "./server/devinAcp.ts"; +export { + acpRegistryProbeFailure, + acpRegistryProbeResult, + listAcpRegistrySessions, + logoutAcpRegistry, + normalizeAcpRegistryAuthMethods, + normalizeAcpRegistryCommands, + probeAcpRegistryConfiguration, + type AcpRegistryAvailableCommands, + type AcpRegistryLiveConfiguration, +} from "./server/probe.ts"; diff --git a/packages/provider-acp-registry/tsconfig.json b/packages/provider-acp-registry/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..024a9dc2d66f35cc921b4124147d194860b487e6 --- /dev/null +++ b/packages/provider-acp-registry/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "types": ["node"], + "lib": ["ESNext", "esnext.disposable"] + }, + "include": ["src"] +} diff --git a/packages/provider-acp/src/server/AcpSessionRuntime.ts b/packages/provider-acp/src/server/AcpSessionRuntime.ts index 8b060291f8b8312b459859d511c0209344bf90b9..ae3423c6f921c0d0a6dd29a8d8fb8f9b4711f5f8 100644 --- a/packages/provider-acp/src/server/AcpSessionRuntime.ts +++ b/packages/provider-acp/src/server/AcpSessionRuntime.ts @@ -1329,17 +1329,7 @@ export class AcpSessionRuntime extends Context.Service< payload: unknown, ) => Effect.Effect; } ->()("@t3tools/provider-acp/server/AcpSessionRuntime") { - static layer( - options: AcpSessionRuntimeOptions, - ): Layer.Layer< - AcpSessionRuntime, - EffectAcpErrors.AcpError, - ChildProcessSpawner.ChildProcessSpawner | Crypto.Crypto - > { - return Layer.effect(AcpSessionRuntime, make(options)); - } -} +>()("@t3tools/provider-acp/server/AcpSessionRuntime") {} interface AcpStartedState extends AcpSessionRuntimeStartResult {} diff --git a/packages/provider-core/package.json b/packages/provider-core/package.json index a733491676b758b464df8e530f4a8a3422c3c265..b069cc57298964f8b55d8dc05be1591b45ceb0c5 100644 --- a/packages/provider-core/package.json +++ b/packages/provider-core/package.json @@ -99,6 +99,10 @@ "types": "./src/server/ProviderAdapter.ts", "import": "./src/server/ProviderAdapter.ts" }, + "./server/ProviderAuthFlow": { + "types": "./src/server/ProviderAuthFlow.ts", + "import": "./src/server/ProviderAuthFlow.ts" + }, "./server/ProviderEventLoggers": { "types": "./src/server/ProviderEventLoggers.ts", "import": "./src/server/ProviderEventLoggers.ts" diff --git a/apps/server/src/provider/ProviderAuthFlow.test.ts b/packages/provider-core/src/server/ProviderAuthFlow.test.ts similarity index 100% rename from apps/server/src/provider/ProviderAuthFlow.test.ts rename to packages/provider-core/src/server/ProviderAuthFlow.test.ts diff --git a/apps/server/src/provider/ProviderAuthFlow.ts b/packages/provider-core/src/server/ProviderAuthFlow.ts similarity index 98% rename from apps/server/src/provider/ProviderAuthFlow.ts rename to packages/provider-core/src/server/ProviderAuthFlow.ts index ff7c5cfd14b3d06a9f7b89fb04c4cea32db90f8e..b1cdde7637a7da1ba671e3243f5dbaa0390a9594 100644 --- a/apps/server/src/provider/ProviderAuthFlow.ts +++ b/packages/provider-core/src/server/ProviderAuthFlow.ts @@ -21,7 +21,7 @@ import * as Semaphore from "effect/Semaphore"; import * as Stream from "effect/Stream"; import * as SubscriptionRef from "effect/SubscriptionRef"; -import type * as ProviderAuthService from "./ProviderAuthService.ts"; +import type * as ProviderAuth from "./auth.ts"; export interface ProviderAuthFlowContext { readonly flowId: string; @@ -61,9 +61,7 @@ interface Flow { /** Adapters do login and credential handling; this owns client consent and flow lifetime. */ export const make = Effect.fn("ProviderAuthFlow.make")(function* (options: { readonly instanceId: ProviderInstanceId; - readonly credentialBinding: NonNullable< - ProviderAuthService.ProviderAuthController["credentialBinding"] - >; + readonly credentialBinding: NonNullable; readonly methods: Effect.Effect, ProviderSetupError>; readonly defaultMethodId?: string; /** Stored account profiles can change the advertised methods after auth/logout. */ @@ -145,7 +143,7 @@ export const make = Effect.fn("ProviderAuthFlow.make")(function* (options: { ); yield* refreshMethods.pipe(Effect.forkIn(scope)); - const controller: ProviderAuthService.ProviderAuthController = { + const controller: ProviderAuth.ProviderAuthController = { credentialBinding: options.credentialBinding, adoptCredentials: (update, stopSessions) => Effect.gen(function* () { diff --git a/packages/provider-core/src/server/ProviderHost.ts b/packages/provider-core/src/server/ProviderHost.ts index 9e889f1f816a250001d7fd36e475fb077b72ae6b..050ad0882fd96a8a123976679ef393a35f89044c 100644 --- a/packages/provider-core/src/server/ProviderHost.ts +++ b/packages/provider-core/src/server/ProviderHost.ts @@ -49,6 +49,10 @@ interface ProviderHostService { readonly paths: ProviderHostPaths; readonly settings: { readonly get: Effect.Effect; + /** Runs `use` on a settings snapshot that no settings write can change until it finishes. */ + readonly withSnapshot: ( + use: (settings: ServerSettings) => Effect.Effect, + ) => Effect.Effect; /** Every settings change after subscription, starting with the next one. */ readonly changes: Stream.Stream; /** Changes buffered from the moment the scoped subscription is acquired. */ diff --git a/packages/provider-core/src/server/managedProvider.test.ts b/packages/provider-core/src/server/managedProvider.test.ts index 58eae9fbbd319bf80d461691bcbfba0ed8b91232..dab08b246ce3ce1545b6dd4360be5437f420ce6b 100644 --- a/packages/provider-core/src/server/managedProvider.test.ts +++ b/packages/provider-core/src/server/managedProvider.test.ts @@ -113,6 +113,7 @@ function layerProviderHost(input: { }, settings: input.settings ?? { get: Effect.succeed(DEFAULT_SERVER_SETTINGS), + withSnapshot: (use) => use(DEFAULT_SERVER_SETTINGS), changes: Stream.empty, subscribe: Effect.succeed(Stream.empty), }, @@ -285,6 +286,7 @@ describe("makeManagedServerProvider", () => { const serverSettingsChanges = yield* PubSub.unbounded(); const hostSettings: ProviderHost.ProviderHost["Service"]["settings"] = { get: Ref.get(serverSettingsRef), + withSnapshot: (use) => Ref.get(serverSettingsRef).pipe(Effect.flatMap(use)), changes: Stream.empty, subscribe: PubSub.subscribe(serverSettingsChanges).pipe( Effect.map((subscription) => Stream.fromSubscription(subscription)), diff --git a/packages/provider-opencode/src/server/OpenCodeRuntime.ts b/packages/provider-opencode/src/server/OpenCodeRuntime.ts index 935294575057d062c82f32852a00a9007aa5a9b7..91e1a6e11d5e1f2b4021fe78735cc32eda645111 100644 --- a/packages/provider-opencode/src/server/OpenCodeRuntime.ts +++ b/packages/provider-opencode/src/server/OpenCodeRuntime.ts @@ -105,10 +105,10 @@ export class OpenCodeRuntimeError extends Data.TaggedError(OPENCODE_RUNTIME_ERRO readonly operation: string; readonly cause?: unknown; readonly detail: string; -}> { - static readonly is = (u: unknown): u is OpenCodeRuntimeError => - P.isTagged(u, OPENCODE_RUNTIME_ERROR_TAG); -} +}> {} + +export const isOpenCodeRuntimeError = (u: unknown): u is OpenCodeRuntimeError => + P.isTagged(u, OPENCODE_RUNTIME_ERROR_TAG); function encodeJsonStringForDiagnostics(input: unknown): string | undefined { const result = encodeUnknownJsonStringExit(input); @@ -116,7 +116,7 @@ function encodeJsonStringForDiagnostics(input: unknown): string | undefined { } export function openCodeRuntimeErrorDetail(cause: unknown): string { - if (OpenCodeRuntimeError.is(cause)) return cause.detail; + if (isOpenCodeRuntimeError(cause)) return cause.detail; if (cause instanceof Error && cause.message.trim().length > 0) return cause.message.trim(); if (cause && typeof cause === "object") { // SDK v2 throws { response, request, error? } shapes — extract what's useful @@ -583,7 +583,7 @@ function ensureRuntimeError( detail: string, cause: unknown, ): OpenCodeRuntimeError { - return OpenCodeRuntimeError.is(cause) + return isOpenCodeRuntimeError(cause) ? cause : new OpenCodeRuntimeError({ operation, detail, cause }); } diff --git a/packages/provider-opencode/src/server/v2/OpenCode2Server.ts b/packages/provider-opencode/src/server/v2/OpenCode2Server.ts index 80b3dda1a10157529d2d3cc612348b13b5d12b52..ea50c22b37a569085cb76beb5a8cfb67c28b8e38 100644 --- a/packages/provider-opencode/src/server/v2/OpenCode2Server.ts +++ b/packages/provider-opencode/src/server/v2/OpenCode2Server.ts @@ -123,7 +123,7 @@ export const verifyServer = (client: OpenCodeClient) => ), }), Effect.mapError((cause) => - OpenCodeRuntime.OpenCodeRuntimeError.is(cause) + OpenCodeRuntime.isOpenCodeRuntimeError(cause) ? cause : new OpenCodeRuntime.OpenCodeRuntimeError({ operation: "server.info", diff --git a/packages/provider-testing/src/host.ts b/packages/provider-testing/src/host.ts index 2436648579107c5786a4de4d2e584250789af239..3316f1a9df2c92153b7e1bf97c632d86f1a70a96 100644 --- a/packages/provider-testing/src/host.ts +++ b/packages/provider-testing/src/host.ts @@ -7,26 +7,38 @@ */ import { DEFAULT_SERVER_SETTINGS, type ServerSettings } from "@t3tools/contracts"; import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; +import * as Context from "effect/Context"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import * as Path from "effect/Path"; +import * as Ref from "effect/Ref"; import * as Stream from "effect/Stream"; export interface TestProviderHostOptions { /** Session fallback cwd. Defaults to the test process cwd. */ readonly cwd?: string; + /** Initial settings. A test changes them through `TestProviderHostSettings`. */ readonly settings?: ServerSettings; /** Whether background work such as status probes may run. Defaults to `true`. */ readonly runBackgroundWork?: boolean; } +/** Lets a test change the settings its `layerTestProviderHost` reports. */ +export class TestProviderHostSettings extends Context.Service< + TestProviderHostSettings, + { readonly set: (settings: ServerSettings) => Effect.Effect } +>()("@t3tools/provider-testing/host/TestProviderHostSettings") {} + export const layerTestProviderHost = ( options: TestProviderHostOptions = {}, -): Layer.Layer => - Layer.effect( - ProviderHost.ProviderHost, +): Layer.Layer< + ProviderHost.ProviderHost | TestProviderHostSettings, + never, + FileSystem.FileSystem | Path.Path +> => + Layer.effectContext( Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; @@ -39,9 +51,9 @@ export const layerTestProviderHost = ( for (const directory of [stateDir, providerStatusCacheDir, attachmentsDir]) { yield* fileSystem.makeDirectory(directory, { recursive: true }).pipe(Effect.orDie); } - const settings = options.settings ?? DEFAULT_SERVER_SETTINGS; + const settings = yield* Ref.make(options.settings ?? DEFAULT_SERVER_SETTINGS); const credentials = new Map(); - return ProviderHost.ProviderHost.of({ + const host = ProviderHost.ProviderHost.of({ paths: { cwd: options.cwd ?? process.cwd(), baseDir, @@ -50,7 +62,8 @@ export const layerTestProviderHost = ( attachmentsDir, }, settings: { - get: Effect.succeed(settings), + get: Ref.get(settings), + withSnapshot: (use) => Ref.get(settings).pipe(Effect.flatMap(use)), changes: Stream.empty, subscribe: Effect.succeed(Stream.empty), }, @@ -69,5 +82,10 @@ export const layerTestProviderHost = ( }; }), }); + return Context.make(ProviderHost.ProviderHost, host).pipe( + Context.add(TestProviderHostSettings, { + set: (next) => Ref.set(settings, next), + }), + ); }), ); diff --git a/packages/shared/package.json b/packages/shared/package.json index 4942d700caddb3a58ad41b4084b56253375370db..fdc368b6c3995b71b1e7f9182d1ecb742bc0a8c0 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -470,6 +470,10 @@ "./mcpResponsePayloads": { "types": "./src/mcpResponsePayloads.ts", "import": "./src/mcpResponsePayloads.ts" + }, + "./PtyAdapter": { + "types": "./src/PtyAdapter.ts", + "import": "./src/PtyAdapter.ts" } }, "scripts": { diff --git a/apps/server/src/terminal/PtyAdapter.ts b/packages/shared/src/PtyAdapter.ts similarity index 98% rename from apps/server/src/terminal/PtyAdapter.ts rename to packages/shared/src/PtyAdapter.ts index c56dfa93efe6ed6d36911b63c9a489503941a3c4..7abb51cbfe6d963b03f61d6d02de5338a60eeb23 100644 --- a/apps/server/src/terminal/PtyAdapter.ts +++ b/packages/shared/src/PtyAdapter.ts @@ -63,4 +63,4 @@ export class PtyAdapter extends Context.Service< */ readonly spawn: (input: PtySpawnInput) => Effect.Effect; } ->()("t3/terminal/PtyAdapter") {} +>()("@t3tools/shared/PtyAdapter") {} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a965df78a8243ff1c4fb79748fada9c67ea4e341..711ef69a8bbd8499053c6c74082d9389453932c8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -353,6 +353,9 @@ importers: '@t3tools/mobile-terminal-native': specifier: file:./modules/t3-terminal version: file:apps/mobile/modules/t3-terminal + '@t3tools/provider-acp-registry': + specifier: workspace:* + version: link:../../packages/provider-acp-registry '@t3tools/provider-core': specifier: workspace:* version: link:../../packages/provider-core @@ -597,15 +600,15 @@ importers: '@napi-rs/keyring': specifier: ^1.3.0 version: 1.3.0 - '@noble/hashes': - specifier: 'catalog:' - version: 1.8.0 '@opencode-ai/sdk': specifier: ^1.3.15 version: 1.15.13 '@t3tools/provider-acp': specifier: workspace:* version: link:../../packages/provider-acp + '@t3tools/provider-acp-registry': + specifier: workspace:* + version: link:../../packages/provider-acp-registry '@t3tools/provider-core': specifier: workspace:* version: link:../../packages/provider-core @@ -748,6 +751,9 @@ importers: '@t3tools/contracts': specifier: workspace:* version: link:../../packages/contracts + '@t3tools/provider-acp-registry': + specifier: workspace:* + version: link:../../packages/provider-acp-registry '@t3tools/provider-core': specifier: workspace:* version: link:../../packages/provider-core @@ -1138,6 +1144,46 @@ 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-registry: + dependencies: + '@noble/hashes': + specifier: 'catalog:' + version: 1.8.0 + '@t3tools/contracts': + specifier: workspace:* + version: link:../contracts + '@t3tools/provider-acp': + specifier: workspace:* + version: link:../provider-acp + '@t3tools/provider-core': + specifier: workspace:* + version: link:../provider-core + '@t3tools/shared': + specifier: workspace:* + version: link:../shared + 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) + '@t3tools/provider-testing': + specifier: workspace:* + version: link:../provider-testing + '@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 3eabff5674fe25e94b1f30afce2aa22f15eceeff..fd8921b67c1265477b7c5db10650179cb6610ca8 100644 --- a/scripts/release-smoke.ts +++ b/scripts/release-smoke.ts @@ -32,6 +32,7 @@ const workspaceFiles = [ "packages/provider-testing/package.json", "packages/provider-pi/package.json", "packages/provider-acp/package.json", + "packages/provider-acp-registry/package.json", "packages/provider-cursor/package.json", "packages/provider-grok/package.json", "packages/provider-muse/package.json", -- 2.54.0