From 2c7a446e657e705c257db28540819f4c0115b2fc Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 8 Oct 2026 18:05:10 -0700 Subject: [PATCH] refactor(providers): namespace-import service modules in core, Muse, Pi, and testing (#17375) Co-authored-by: Claude Opus 5.5 --- .../provider-core/src/server/adapterDriver.ts | 8 +- packages/provider-core/src/server/driver.ts | 4 +- .../provider-core/src/server/failure.test.ts | 4 +- packages/provider-core/src/server/failure.ts | 6 +- .../src/server/managedProvider.test.ts | 10 +- .../src/server/managedProvider.ts | 10 +- .../src/server/snapshotSettings.ts | 4 +- .../provider-muse/src/server/adapter.test.ts | 37 ++++---- packages/provider-muse/src/server/adapter.ts | 91 ++++++++----------- packages/provider-muse/src/server/driver.ts | 6 +- .../provider-pi/src/server/adapter.test.ts | 23 ++--- packages/provider-pi/src/server/adapter.ts | 10 +- packages/provider-pi/src/server/driver.ts | 6 +- packages/provider-testing/src/host.ts | 10 +- 14 files changed, 112 insertions(+), 117 deletions(-) diff --git a/packages/provider-core/src/server/adapterDriver.ts b/packages/provider-core/src/server/adapterDriver.ts index 6a2e57daab0bb6121a8bd78e411ac574c5314710..7445dc7ed016228f6d1a1dcf47943e97bf16da0b 100644 --- a/packages/provider-core/src/server/adapterDriver.ts +++ b/packages/provider-core/src/server/adapterDriver.ts @@ -7,7 +7,7 @@ import * as Schema from "effect/Schema"; import type * as Effect from "effect/Effect"; import type * as Scope from "effect/Scope"; -import type { ProviderAdapterV2Shape } from "@t3tools/provider-core/server/ProviderAdapter"; +import type * as ProviderAdapter from "@t3tools/provider-core/server/ProviderAdapter"; export class ProviderAdapterDriverCreateError extends Schema.TaggedError()( "ProviderAdapterDriverCreateError", @@ -38,7 +38,11 @@ export interface ProviderAdapterDriver { readonly defaultConfig: () => Config; readonly create: ( input: ProviderAdapterDriverCreateInput, - ) => Effect.Effect; + ) => Effect.Effect< + ProviderAdapter.ProviderAdapterV2Shape, + ProviderAdapterDriverCreateError, + R | Scope.Scope + >; } export type AnyProviderAdapterDriver = ProviderAdapterDriver; diff --git a/packages/provider-core/src/server/driver.ts b/packages/provider-core/src/server/driver.ts index 88e46b937d13624a6b816cbb5ed8831e8d3d19d8..b177ba926ba4636274413187a4008e02542dd1b0 100644 --- a/packages/provider-core/src/server/driver.ts +++ b/packages/provider-core/src/server/driver.ts @@ -37,7 +37,7 @@ import type * as Effect from "effect/Effect"; import type * as Schema from "effect/Schema"; import type * as Scope from "effect/Scope"; -import type { ProviderAdapterV2Shape } from "./ProviderAdapter.ts"; +import type * as ProviderAdapter from "./ProviderAdapter.ts"; import type { ProviderAuthController } from "./auth.ts"; import type { ProviderDriverError } from "./errors.ts"; import type { ServerProviderShape } from "./snapshot.ts"; @@ -101,7 +101,7 @@ export interface ProviderInstance { ProviderConsumeResetCreditOutcome, ProviderDriverError >; - readonly orchestrationAdapter: ProviderAdapterV2Shape; + readonly orchestrationAdapter: ProviderAdapter.ProviderAdapterV2Shape; readonly textGeneration: ProviderTextGeneration; readonly auth?: ProviderAuthController; readonly acpSessionManagement?: { diff --git a/packages/provider-core/src/server/failure.test.ts b/packages/provider-core/src/server/failure.test.ts index 47fe4c724eb101d932ecac42a5d119cdfb4b68ef..a4429213db28e4c6ebcf7dd127abf29fd0f1f1fd 100644 --- a/packages/provider-core/src/server/failure.test.ts +++ b/packages/provider-core/src/server/failure.test.ts @@ -19,7 +19,7 @@ import { ContextHandoffBudgetError, } from "./failure.ts"; import * as IdAllocator from "./IdAllocator.ts"; -import { ProviderAdapterTurnStartError } from "@t3tools/provider-core/server/ProviderAdapter"; +import * as ProviderAdapter from "@t3tools/provider-core/server/ProviderAdapter"; it("redacts credentials and URL secrets from provider failures", () => { const failure = makeProviderFailure({ @@ -88,7 +88,7 @@ it("does not expose arbitrary cause messages and preserves explicit messages", ( }); it("preserves actionable handoff errors wrapped by turn startup", () => { - const cause = new ProviderAdapterTurnStartError({ + const cause = new ProviderAdapter.ProviderAdapterTurnStartError({ driver: ProviderDriverKind.make("codex"), threadId: ThreadId.make("thread:handoff-error"), providerThreadId: ProviderThreadId.make("provider-thread:handoff-error"), diff --git a/packages/provider-core/src/server/failure.ts b/packages/provider-core/src/server/failure.ts index 53e663a4c8d960a4c985cbb5d5d29df53e1d9827..8a745f83aaac20bccf3af1ba127082488154edf7 100644 --- a/packages/provider-core/src/server/failure.ts +++ b/packages/provider-core/src/server/failure.ts @@ -13,7 +13,7 @@ import type { import * as DateTime from "effect/DateTime"; import * as Cause from "effect/Cause"; -import type { IdAllocatorV2Shape } from "./IdAllocator.ts"; +import type * as IdAllocator from "./IdAllocator.ts"; import * as Schema from "effect/Schema"; /** Raised when portable history does not fit the target provider's context window. */ @@ -172,7 +172,7 @@ export function makeProviderFailure(input: { } export function makeProviderFailureTurnItem(input: { - readonly idAllocator: IdAllocatorV2Shape; + readonly idAllocator: IdAllocator.IdAllocatorV2Shape; readonly driver: ProviderDriverKind; readonly threadId: ThreadId; readonly runId: RunId | null; @@ -210,7 +210,7 @@ export function makeProviderFailureTurnItem(input: { } export function makeProviderRetryTurnItem(input: { - readonly idAllocator: IdAllocatorV2Shape; + readonly idAllocator: IdAllocator.IdAllocatorV2Shape; readonly driver: ProviderDriverKind; readonly threadId: ThreadId; readonly runId: RunId | null; diff --git a/packages/provider-core/src/server/managedProvider.test.ts b/packages/provider-core/src/server/managedProvider.test.ts index f46eb897bbb6a9384c3e127f701e623d03af116c..a4d7dc752f1ca2a0e8e4bf5a18782f79fc8bbc67 100644 --- a/packages/provider-core/src/server/managedProvider.test.ts +++ b/packages/provider-core/src/server/managedProvider.test.ts @@ -16,7 +16,7 @@ import * as Ref from "effect/Ref"; import * as Stream from "effect/Stream"; import { TestClock } from "effect/testing"; -import { ProviderHost, type ProviderHostShape } from "./ProviderHost.ts"; +import * as ProviderHost from "./ProviderHost.ts"; import { makeManagedServerProvider } from "./managedProvider.ts"; const emptyCapabilities = createModelCapabilities({ optionDescriptors: [] }); @@ -99,11 +99,11 @@ const refreshedSnapshotSecond: ServerProvider = { /** A host whose settings never change and whose background demand is fixed. */ function layerProviderHost(input: { readonly runBackgroundWork: boolean; - readonly settings?: Pick["settings"]; + readonly settings?: Pick["settings"]; }) { return Layer.succeed( - ProviderHost, - ProviderHost.of({ + ProviderHost.ProviderHost, + ProviderHost.ProviderHost.of({ paths: { cwd: process.cwd(), baseDir: "/t3", @@ -281,7 +281,7 @@ describe("makeManagedServerProvider", () => { }; const serverSettingsRef = yield* Ref.make(initialServerSettings); const serverSettingsChanges = yield* PubSub.unbounded(); - const hostSettings: ProviderHostShape["settings"] = { + const hostSettings: ProviderHost.ProviderHostShape["settings"] = { get: Ref.get(serverSettingsRef), changes: Stream.empty, subscribe: PubSub.subscribe(serverSettingsChanges).pipe( diff --git a/packages/provider-core/src/server/managedProvider.ts b/packages/provider-core/src/server/managedProvider.ts index a04873f0e6087c057ca6b42aa14814c0b854f2cb..946f9ad86217dc66507922869f3ad1e3951bf8c1 100644 --- a/packages/provider-core/src/server/managedProvider.ts +++ b/packages/provider-core/src/server/managedProvider.ts @@ -15,7 +15,7 @@ import * as Scope from "effect/Scope"; import * as Stream from "effect/Stream"; import * as Semaphore from "effect/Semaphore"; -import { ProviderHost } from "./ProviderHost.ts"; +import * as ProviderHost from "./ProviderHost.ts"; import { applyUsageLimitsUpdate, resolveUsageLimitsAfterProbe } from "./usageLimits.ts"; import type { ServerProviderShape } from "./snapshot.ts"; @@ -53,8 +53,12 @@ export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( readonly refreshInterval?: Duration.Input; readonly refreshOnInterval?: boolean; readonly checkProviderOnSettingsChange?: (previous: Settings, next: Settings) => boolean; -}): Effect.fn.Return { - const host = yield* ProviderHost; +}): Effect.fn.Return< + ServerProviderShape, + ServerSettingsError, + Scope.Scope | ProviderHost.ProviderHost +> { + const host = yield* ProviderHost.ProviderHost; const refreshSemaphore = yield* Semaphore.make(1); const changesPubSub = yield* Effect.acquireRelease( PubSub.unbounded(), diff --git a/packages/provider-core/src/server/snapshotSettings.ts b/packages/provider-core/src/server/snapshotSettings.ts index 87286728fe60c1dfba11b6d2dd84999bcc6bd9b2..5a1d207b15eedc9903bd38c8978f5d5f4fb0937b 100644 --- a/packages/provider-core/src/server/snapshotSettings.ts +++ b/packages/provider-core/src/server/snapshotSettings.ts @@ -3,7 +3,7 @@ import * as Effect from "effect/Effect"; import * as Equal from "effect/Equal"; import * as Stream from "effect/Stream"; -import type { ProviderHostShape } from "./ProviderHost.ts"; +import type * as ProviderHost from "./ProviderHost.ts"; export interface ProviderSnapshotSettings { readonly provider: Settings; @@ -29,7 +29,7 @@ export function haveProviderSnapshotSettingsChanged( export function makeProviderSnapshotSettingsSource( provider: Settings, - settings: ProviderHostShape["settings"], + settings: ProviderHost.ProviderHostShape["settings"], ): { readonly getSettings: Effect.Effect, ServerSettingsError>; readonly streamSettings: Stream.Stream>; diff --git a/packages/provider-muse/src/server/adapter.test.ts b/packages/provider-muse/src/server/adapter.test.ts index 59f8adec402682450152bb3d07834ee26623b784..c73dbb4e2297191f97963663df3d61f2a2d5dbc5 100644 --- a/packages/provider-muse/src/server/adapter.test.ts +++ b/packages/provider-muse/src/server/adapter.test.ts @@ -31,17 +31,13 @@ import * as Queue from "effect/Queue"; import * as Schema from "effect/Schema"; import * as Stream from "effect/Stream"; -import { ProviderHost } from "@t3tools/provider-core/server/ProviderHost"; +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 type { MuseItem } from "./protocol.ts"; import type { MuseSdkHost } from "./sdk.ts"; import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; -import { - ProviderAdapterV2RuntimePolicy, - type ProviderAdapterV2Event, - type ProviderAdapterV2TurnInput, -} from "@t3tools/provider-core/server/ProviderAdapter"; +import * as ProviderAdapter from "@t3tools/provider-core/server/ProviderAdapter"; import type { ProviderContinuationRequest } from "@t3tools/provider-core/server/continuationRequests"; import { makeMuseAdapterV2, type MuseAdapterV2Options } from "./adapter.ts"; @@ -55,7 +51,7 @@ const INSTANCE_ID = ProviderInstanceId.make("muse_work"); const THREAD_ID = ThreadId.make("thread-muse-test"); const MODEL = "muse-spark-1.3-contributor"; const museSettings = Schema.decodeSync(MuseSettings)({ enabled: true }); -const runtimePolicy = ProviderAdapterV2RuntimePolicy.make({ +const runtimePolicy = ProviderAdapter.ProviderAdapterV2RuntimePolicy.make({ runtimeMode: "full-access", interactionMode: "default", cwd: null, @@ -204,7 +200,7 @@ const makeHarness = Effect.fnUntraced(function* ( settings: museSettings, environment: { PATH: "/fake/bin" }, idAllocator: yield* IdAllocator.IdAllocatorV2, - host: yield* ProviderHost, + host: yield* ProviderHost.ProviderHost, fileSystem: yield* FileSystem.FileSystem, createHost: async () => (hostCount++ === 0 ? fake.host : (replacement ?? fake).host), ...overrides, @@ -216,8 +212,8 @@ const makeHarness = Effect.fnUntraced(function* ( runtimePolicy: policy, ...(initialNativeThreadId ? { initialNativeThreadId } : {}), }); - const emitted = yield* Queue.unbounded(); - const allEvents: ProviderAdapterV2Event[] = []; + const emitted = yield* Queue.unbounded(); + const allEvents: ProviderAdapter.ProviderAdapterV2Event[] = []; const eventsEnded = yield* Deferred.make>>(); yield* runtime.events.pipe( Stream.runForEach((event) => @@ -236,14 +232,21 @@ const makeHarness = Effect.fnUntraced(function* ( runtimePolicy: policy, ...(existingProviderThread ? { existingProviderThread } : {}), }); - const takeEvent = Effect.fnUntraced(function* ( + const takeEvent = Effect.fnUntraced(function* < + T extends ProviderAdapter.ProviderAdapterV2Event["type"], + >( type: T, - predicate: (event: Extract) => boolean = () => true, + predicate: ( + event: Extract, + ) => boolean = () => true, ) { while (true) { const event = yield* Queue.take(emitted); - if (event.type === type && predicate(event as Extract)) { - return event as Extract; + if ( + event.type === type && + predicate(event as Extract) + ) { + return event as Extract; } } }); @@ -275,7 +278,7 @@ const turnInput = Effect.fnUntraced(function* ( providerThread: OrchestrationV2ProviderThread, runOrdinal = 1, policy = runtimePolicy, -): Effect.fn.Return { +): Effect.fn.Return { const now = yield* DateTime.now; const threadId = providerThread.appThreadId ?? THREAD_ID; const selection = modelSelection(providerThread.providerInstanceId); @@ -436,7 +439,7 @@ describe("MuseAdapterV2", () => { settings: museSettings, environment: { PATH: "/fake/bin" }, idAllocator: yield* IdAllocator.IdAllocatorV2, - host: yield* ProviderHost, + host: yield* ProviderHost.ProviderHost, fileSystem: yield* FileSystem.FileSystem, createHost: async () => fake.host, }); @@ -833,7 +836,7 @@ describe("MuseAdapterV2", () => { it.effect("keeps a workflow child's approval pending for the user past the turn's end", () => Effect.gen(function* () { const fake = yield* makeFakeMuse(); - const policy = ProviderAdapterV2RuntimePolicy.make({ + const policy = ProviderAdapter.ProviderAdapterV2RuntimePolicy.make({ ...runtimePolicy, runtimeMode: "approval-required", }); diff --git a/packages/provider-muse/src/server/adapter.ts b/packages/provider-muse/src/server/adapter.ts index bf1699055534c0b08ecd0399b33d79338abc190f..686fb64f1dc8a058584fdfcab5140e111ee4e6b3 100644 --- a/packages/provider-muse/src/server/adapter.ts +++ b/packages/provider-muse/src/server/adapter.ts @@ -35,7 +35,7 @@ import * as Semaphore from "effect/Semaphore"; import * as Scope from "effect/Scope"; import * as Stream from "effect/Stream"; -import type { ProviderHostShape } from "@t3tools/provider-core/server/ProviderHost"; +import type * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; import * as McpProviderSession from "@t3tools/provider-core/server/mcpSession"; import { buildRuntimeInstructions } from "@t3tools/provider-core/server/runtimeInstructions"; import { museModelCapabilities, resolveMuseReasoningEffort } from "./modelCatalog.ts"; @@ -63,35 +63,13 @@ import { type createMuseSdkHost, type MuseSdkHost, } from "./sdk.ts"; -import type { EventNdjsonLogger } from "@t3tools/provider-core/server/ProviderEventLoggers"; +import type * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; import { providerMessageTextWithAttachmentPaths, isProviderNativeImageAttachment, } from "@t3tools/provider-core/server/attachmentPrompt"; import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; -import { - ProviderAdapterEnsureThreadError, - ProviderAdapterForkThreadError, - ProviderAdapterInterruptError, - ProviderAdapterOpenSessionError, - ProviderAdapterProtocolError, - ProviderAdapterReadThreadSnapshotError, - ProviderAdapterResumeThreadError, - ProviderAdapterRollbackThreadError, - ProviderAdapterRuntimeRequestResponseError, - ProviderAdapterSteerRunError, - ProviderAdapterTurnStartError, - ProviderAdapterV2, - type ProviderAdapterV2Error, - type ProviderAdapterV2Event, - type ProviderAdapterV2EnsureThreadInput, - type ProviderAdapterV2OpenSessionInput, - type ProviderAdapterV2SessionRuntime, - type ProviderAdapterV2Shape, - type ProviderAdapterV2ThreadSnapshot, - type ProviderAdapterV2TurnInput, - type ProviderAdapterV2TurnMessage, -} from "@t3tools/provider-core/server/ProviderAdapter"; +import * as ProviderAdapter from "@t3tools/provider-core/server/ProviderAdapter"; import { backgroundWorkNotification, type BackgroundWorkReport, @@ -102,8 +80,8 @@ import { turnScopedSelectionTransition } from "@t3tools/provider-core/server/sel import { museItemStatus, museToolPresentation } from "./itemPresentation.ts"; const MUSE_PROVIDER = ProviderDriverKind.make("muse"); -const isOpenSessionError = Schema.is(ProviderAdapterOpenSessionError); -const isProtocolError = Schema.is(ProviderAdapterProtocolError); +const isOpenSessionError = Schema.is(ProviderAdapter.ProviderAdapterOpenSessionError); +const isProtocolError = Schema.is(ProviderAdapter.ProviderAdapterProtocolError); const MuseProviderCapabilitiesV2 = { runtimePolicy: { enforcement: "native" }, @@ -204,12 +182,12 @@ export interface MuseAdapterV2Options { readonly settings: MuseSettings; readonly environment: NodeJS.ProcessEnv; readonly idAllocator: IdAllocator.IdAllocatorV2["Service"]; - readonly host: ProviderHostShape; + readonly host: ProviderHost.ProviderHostShape; readonly fileSystem: FileSystem.FileSystem; readonly modelCatalog?: Effect.Effect>; readonly createHost?: typeof createMuseSdkHost; readonly requestTimeoutMs?: number; - readonly nativeEventLogger?: EventNdjsonLogger; + readonly nativeEventLogger?: ProviderEventLoggers.EventNdjsonLogger; /** Where a turn Muse starts on its own (a finished workflow's report) asks for its run. */ readonly continuationRequests?: { readonly offer: ( @@ -219,7 +197,7 @@ export interface MuseAdapterV2Options { } interface ActiveTurn { - readonly input: ProviderAdapterV2TurnInput; + readonly input: ProviderAdapter.ProviderAdapterV2TurnInput; providerTurn: OrchestrationV2ProviderTurn; readonly nativeId: string; /** Turns Muse started on its own while this run was active, which this run shows. */ @@ -267,21 +245,23 @@ const TOOLS_WITH_NATIVE_ROWS = new Set(["write_todos", "request_user_input", "wo const responseAnswerSchema = Schema.Union([Schema.String, Schema.Array(Schema.String)]); /** One scoped Muse host owns one native session; the orchestrator owns app runs and queuing. */ -export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapterV2Shape { +export function makeMuseAdapterV2( + options: MuseAdapterV2Options, +): ProviderAdapter.ProviderAdapterV2Shape { const { idAllocator } = options; const protocolError = (detail: string, payload?: unknown) => - new ProviderAdapterProtocolError({ + new ProviderAdapter.ProviderAdapterProtocolError({ driver: MUSE_PROVIDER, detail, ...(payload === undefined ? {} : { payload }), }); - return ProviderAdapterV2.of({ + return ProviderAdapter.ProviderAdapterV2.of({ instanceId: options.instanceId, driver: MUSE_PROVIDER, getCapabilities: () => Effect.succeed(MuseProviderCapabilitiesV2), planSelectionTransition: () => Effect.succeed(turnScopedSelectionTransition()), openSession: Effect.fn("MuseAdapterV2.openSession")(function* ( - input: ProviderAdapterV2OpenSessionInput, + input: ProviderAdapter.ProviderAdapterV2OpenSessionInput, ) { if (!options.settings.enabled) return yield* protocolError("Muse Code is disabled"); if (input.runtimePolicy.interactionMode === "plan") @@ -307,8 +287,8 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte lastError: null, }; const events = yield* Queue.unbounded< - ProviderAdapterV2Event, - ProviderAdapterV2Error | Cause.Done + ProviderAdapter.ProviderAdapterV2Event, + ProviderAdapter.ProviderAdapterV2Error | Cause.Done >(); type Inbox = | { type: "notification"; method: string; params: unknown; epoch: number } @@ -344,7 +324,7 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte let wake: | { readonly nativeId: string; readonly events: Array<[string, unknown]> } | undefined; - const emit = (event: ProviderAdapterV2Event) => + const emit = (event: ProviderAdapter.ProviderAdapterV2Event) => Queue.offer(events, event).pipe(Effect.asVoid); const decode = (schema: Schema.Codec, data: unknown) => Schema.decodeUnknownEffect(schema)(data).pipe( @@ -1400,7 +1380,7 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte ).pipe( Effect.mapError( (error) => - new ProviderAdapterOpenSessionError({ + new ProviderAdapter.ProviderAdapterOpenSessionError({ driver: MUSE_PROVIDER, providerSessionId: input.providerSessionId, cause: error.cause, @@ -1472,7 +1452,9 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte ); yield* launchHost(); - const register = Effect.fnUntraced(function* (args: ProviderAdapterV2EnsureThreadInput) { + const register = Effect.fnUntraced(function* ( + args: ProviderAdapter.ProviderAdapterV2EnsureThreadInput, + ) { if (broken || closed) return yield* protocolError("Muse host is unavailable; reopen the session"); if (active) @@ -1592,7 +1574,9 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte ), ); }); - const prompt = Effect.fnUntraced(function* (message: ProviderAdapterV2TurnMessage) { + const prompt = Effect.fnUntraced(function* ( + message: ProviderAdapter.ProviderAdapterV2TurnMessage, + ) { const parts: SendUserTurnOptions["input"] = []; const text = providerMessageTextWithAttachmentPaths({ text: message.text, @@ -1635,7 +1619,7 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte ); }); const start = Effect.fnUntraced(function* ( - turnInput: ProviderAdapterV2TurnInput, + turnInput: ProviderAdapter.ProviderAdapterV2TurnInput, compact = false, ) { if (!validateThread(turnInput.providerThread) || broken || closed) @@ -1783,7 +1767,10 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte // Only messages are read back; T3 owns turn and item history. const snapshot = Effect.fnUntraced(function* ( current: OrchestrationV2ProviderThread, - ): Effect.fn.Return { + ): Effect.fn.Return< + ProviderAdapter.ProviderAdapterV2ThreadSnapshot, + ProviderAdapter.ProviderAdapterV2Error + > { const result = yield* request("session/read", { excludeItems: false }, false).pipe( Effect.flatMap((value) => decode(MuseSessionResult, value)), ); @@ -1821,7 +1808,7 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte providerPayload: items, }; }); - const runtime: ProviderAdapterV2SessionRuntime = { + const runtime: ProviderAdapter.ProviderAdapterV2SessionRuntime = { instanceId: options.instanceId, driver: MUSE_PROVIDER, providerSessionId: input.providerSessionId, @@ -1836,7 +1823,7 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte commands.withPermits(1), Effect.mapError( (cause) => - new ProviderAdapterEnsureThreadError({ + new ProviderAdapter.ProviderAdapterEnsureThreadError({ driver: MUSE_PROVIDER, threadId: args.threadId, cause, @@ -1853,7 +1840,7 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte commands.withPermits(1), Effect.mapError( (cause) => - new ProviderAdapterResumeThreadError({ + new ProviderAdapter.ProviderAdapterResumeThreadError({ driver: MUSE_PROVIDER, providerSessionId: input.providerSessionId, providerThreadId: args.providerThread.id, @@ -1866,7 +1853,7 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte commands.withPermits(1), Effect.mapError( (cause) => - new ProviderAdapterTurnStartError({ + new ProviderAdapter.ProviderAdapterTurnStartError({ driver: MUSE_PROVIDER, threadId: args.threadId, providerThreadId: args.providerThread.id, @@ -1897,7 +1884,7 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte commands.withPermits(1), Effect.mapError( (cause) => - new ProviderAdapterSteerRunError({ + new ProviderAdapter.ProviderAdapterSteerRunError({ driver: MUSE_PROVIDER, providerThreadId: args.providerThread.id, providerTurnId: args.providerTurnId, @@ -1946,7 +1933,7 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte commands.withPermits(1), Effect.mapError( (cause) => - new ProviderAdapterInterruptError({ + new ProviderAdapter.ProviderAdapterInterruptError({ driver: MUSE_PROVIDER, providerThreadId: args.providerThread.id, providerTurnId: args.providerTurnId, @@ -1999,7 +1986,7 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte }).pipe( Effect.mapError( (cause) => - new ProviderAdapterRuntimeRequestResponseError({ + new ProviderAdapter.ProviderAdapterRuntimeRequestResponseError({ driver: MUSE_PROVIDER, requestId: args.requestId, cause, @@ -2014,7 +2001,7 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte commands.withPermits(1), Effect.mapError( (cause) => - new ProviderAdapterReadThreadSnapshotError({ + new ProviderAdapter.ProviderAdapterReadThreadSnapshotError({ driver: MUSE_PROVIDER, providerThreadId: args.providerThread.id, cause, @@ -2025,7 +2012,7 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte // portable context handoff for forks and does not rewind Muse conversations. rollbackThread: (args) => Effect.fail( - new ProviderAdapterRollbackThreadError({ + new ProviderAdapter.ProviderAdapterRollbackThreadError({ driver: MUSE_PROVIDER, providerThreadId: args.providerThread.id, checkpointId: args.target.checkpointId, @@ -2034,7 +2021,7 @@ export function makeMuseAdapterV2(options: MuseAdapterV2Options): ProviderAdapte ), forkThread: (args) => Effect.fail( - new ProviderAdapterForkThreadError({ + new ProviderAdapter.ProviderAdapterForkThreadError({ driver: MUSE_PROVIDER, providerThreadId: args.sourceProviderThread.id, cause: "Muse Code does not support native forks in T3 Code.", diff --git a/packages/provider-muse/src/server/driver.ts b/packages/provider-muse/src/server/driver.ts index 87f6b2818907832260665d4d9f46936facd2c425..8b9b5b1fa9672bc94e16a9f9c9293f03a6064e91 100644 --- a/packages/provider-muse/src/server/driver.ts +++ b/packages/provider-muse/src/server/driver.ts @@ -8,7 +8,7 @@ import * as Schema from "effect/Schema"; import { HttpClient } from "effect/http"; import { ChildProcessSpawner } from "effect/process"; -import { ProviderHost } from "@t3tools/provider-core/server/ProviderHost"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; import { makeMuseTextGeneration } from "./textGeneration.ts"; import { ProviderDriverError } from "@t3tools/provider-core/server/errors"; @@ -42,7 +42,7 @@ const decodeMuseSettings = Schema.decodeSync(MuseSettings); export type MuseDriverEnv = | IdAllocator.IdAllocatorV2 - | ProviderHost + | ProviderHost.ProviderHost | ChildProcessSpawner.ChildProcessSpawner | FileSystem.FileSystem | HttpClient.HttpClient @@ -60,7 +60,7 @@ export const MuseDriver: ProviderDriver = { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const httpClient = yield* HttpClient.HttpClient; - const host = yield* ProviderHost; + const host = yield* ProviderHost.ProviderHost; const eventLoggers = yield* ProviderEventLoggers.ProviderEventLoggers; const { cwd } = host.paths; const idAllocator = yield* IdAllocator.IdAllocatorV2; diff --git a/packages/provider-pi/src/server/adapter.test.ts b/packages/provider-pi/src/server/adapter.test.ts index 65a01a4030952c3af63b12ba5865179e74439223..19a32596ee0e204b055c9287b42f91f262479fc4 100644 --- a/packages/provider-pi/src/server/adapter.test.ts +++ b/packages/provider-pi/src/server/adapter.test.ts @@ -33,16 +33,12 @@ import * as TestClock from "effect/testing/TestClock"; import { ChildProcess, ChildProcessSpawner } from "effect/process"; import { HostProcessEnvironment } from "@t3tools/shared/hostProcess"; -import { ProviderHost } from "@t3tools/provider-core/server/ProviderHost"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; import { layerTestProviderHost } from "@t3tools/provider-testing/host"; import * as ProviderContinuationRequests from "@t3tools/provider-core/server/continuationRequests"; import * as McpProviderSession from "@t3tools/provider-core/server/mcpSession"; import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; -import { - ProviderAdapterV2RuntimePolicy, - type ProviderAdapterV2Event, - type ProviderAdapterV2SessionRuntime, -} from "@t3tools/provider-core/server/ProviderAdapter"; +import * as ProviderAdapter from "@t3tools/provider-core/server/ProviderAdapter"; import { handoffBudget } from "@t3tools/provider-core/server/handoffBudget"; import { makePiAdapterV2, @@ -68,7 +64,7 @@ const FAKE_SESSION_FILE = "/fake/.pi/agent/sessions/--workspace--/0001_abc.jsonl /** Deliberately outside the valid pid range so a group-kill can never land. */ const FAKE_PID = 999_999_999; -const runtimePolicy = ProviderAdapterV2RuntimePolicy.make({ +const runtimePolicy = ProviderAdapter.ProviderAdapterV2RuntimePolicy.make({ runtimeMode: "full-access", interactionMode: "default", cwd: null, @@ -331,7 +327,7 @@ const makeAdapter = Effect.fnUntraced(function* ( continuationRequests?: PiAdapterV2Options["continuationRequests"], ) { const idAllocator = yield* IdAllocator.IdAllocatorV2; - const host = yield* ProviderHost; + const host = yield* ProviderHost.ProviderHost; const fileSystem = yield* FileSystem.FileSystem; const spawner = forkFake === undefined @@ -383,12 +379,12 @@ const openRuntime = Effect.fnUntraced(function* ( modelSelection: modelSelection(model), runtimePolicy, }); - const emitted = yield* Queue.unbounded(); + const emitted = yield* Queue.unbounded(); yield* runtime.events.pipe( Stream.runForEach((event) => Queue.offer(emitted, event)), Effect.forkScoped, ); - const takeEvent = (predicate: (event: ProviderAdapterV2Event) => boolean) => + const takeEvent = (predicate: (event: ProviderAdapter.ProviderAdapterV2Event) => boolean) => Effect.gen(function* () { while (true) { const event = yield* Queue.take(emitted); @@ -426,7 +422,7 @@ const makeAppThread = Effect.fnUntraced(function* (model: string, threadId = THR }); const startTurn = Effect.fnUntraced(function* ( - runtime: ProviderAdapterV2SessionRuntime, + runtime: ProviderAdapter.ProviderAdapterV2SessionRuntime, providerThread: OrchestrationV2ProviderThread, model = "default", attachments: ReadonlyArray = [], @@ -832,8 +828,9 @@ describe("PiAdapterV2", () => { }); yield* fake.emit({ type: "agent_start" }); yield* Queue.take(offers); - const requests: Array> = - []; + const requests: Array< + Extract + > = []; fake.deferNextModelSelection(); const starting = yield* startTurn( runtime, diff --git a/packages/provider-pi/src/server/adapter.ts b/packages/provider-pi/src/server/adapter.ts index 73e1f64953c5c997bdba1775c8975adf4adaba77..06f702c7eb31006ad8fb7aa3da7fb3bc844aba58 100644 --- a/packages/provider-pi/src/server/adapter.ts +++ b/packages/provider-pi/src/server/adapter.ts @@ -60,7 +60,7 @@ import * as Semaphore from "effect/Semaphore"; import * as Stream from "effect/Stream"; import { ChildProcessSpawner } from "effect/process"; -import { ProviderHost, type ProviderHostShape } from "@t3tools/provider-core/server/ProviderHost"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; import { mcpToolPresentation } from "@t3tools/provider-core/server/mcpToolPresentation"; import * as McpProviderSession from "@t3tools/provider-core/server/mcpSession"; import { @@ -231,7 +231,7 @@ export interface PiAdapterV2Options { readonly spawner: ChildProcessSpawner.ChildProcessSpawner["Service"]; readonly fileSystem: FileSystem.FileSystem; readonly idAllocator: IdAllocator.IdAllocatorV2["Service"]; - readonly host: ProviderHostShape; + readonly host: ProviderHost.ProviderHostShape; readonly continuationRequests?: { readonly offer: ( request: ProviderContinuationRequests.ProviderContinuationRequest, @@ -3201,7 +3201,7 @@ export type PiAdapterV2DriverEnv = | ChildProcessSpawner.ChildProcessSpawner | FileSystem.FileSystem | IdAllocator.IdAllocatorV2 - | ProviderHost; + | ProviderHost.ProviderHost; export const PiAdapterV2Driver: ProviderAdapterDriver = { driverKind: PI_DRIVER_KIND, @@ -3213,7 +3213,7 @@ export const PiAdapterV2Driver: ProviderAdapterDriver = { const fileSystem = yield* FileSystem.FileSystem; const pathService = yield* Path.Path; const httpClient = yield* HttpClient.HttpClient; - const host = yield* ProviderHost; + const host = yield* ProviderHost.ProviderHost; const { cwd } = host.paths; const processEnv = mergeProviderInstanceEnvironment(environment); const continuationIdentity = defaultProviderContinuationIdentity({ diff --git a/packages/provider-testing/src/host.ts b/packages/provider-testing/src/host.ts index 1b3e74922eb57c835dae063548b1ba6468f12e2e..6c9a9e11347275511c6590a3282973ce7b271fa8 100644 --- a/packages/provider-testing/src/host.ts +++ b/packages/provider-testing/src/host.ts @@ -1,12 +1,12 @@ /** - * A `ProviderHost` for driver and adapter tests. Its directories live in a + * A `ProviderHost.ProviderHost` for driver and adapter tests. Its directories live in a * scoped temp directory, settings are fixed, and background work always runs * unless the test says otherwise. * * @module provider-testing/host */ import { DEFAULT_SERVER_SETTINGS, type ServerSettings } from "@t3tools/contracts"; -import { ProviderHost } from "@t3tools/provider-core/server/ProviderHost"; +import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; @@ -23,9 +23,9 @@ export interface TestProviderHostOptions { export const layerTestProviderHost = ( options: TestProviderHostOptions = {}, -): Layer.Layer => +): Layer.Layer => Layer.effect( - ProviderHost, + ProviderHost.ProviderHost, Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; @@ -39,7 +39,7 @@ export const layerTestProviderHost = ( yield* fileSystem.makeDirectory(directory, { recursive: true }).pipe(Effect.orDie); } const settings = options.settings ?? DEFAULT_SERVER_SETTINGS; - return ProviderHost.of({ + return ProviderHost.ProviderHost.of({ paths: { cwd: options.cwd ?? process.cwd(), baseDir, stateDir, providerStatusCacheDir }, settings: { get: Effect.succeed(settings), -- 2.54.0