| author | |
| committer | |
| log | 31b04e2ee929660d80d5931ed53fd17bf1d33ce6 |
| tree | 0a706e9eea32af1a0f39a15e29f23f62d3866dac |
| parent | 784b5625f9e228cca8dd67e6e24e402325672544 |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>77 files changed, 396 insertions(+), 380 deletions(-)
apps/server/scripts/record-grok-acp-replay-fixture.ts+2-2| ... | @@ -24,7 +24,7 @@ import * as Schema from "effect/Schema"; | ... | @@ -24,7 +24,7 @@ import * as Schema from "effect/Schema"; |
| 24 | import { ChildProcessSpawner } from "effect/process"; | 24 | import { ChildProcessSpawner } from "effect/process"; |
| 25 | import type * as EffectAcpProtocol from "effect-acp/protocol"; | 25 | import type * as EffectAcpProtocol from "effect-acp/protocol"; |
| 26 | 26 | ||
| 27 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 27 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 28 | import { | 28 | import { |
| 29 | GROK_DEFAULT_INSTANCE_ID, | 29 | GROK_DEFAULT_INSTANCE_ID, |
| 30 | GROK_PROVIDER, | 30 | GROK_PROVIDER, |
| ... | @@ -490,7 +490,7 @@ const recordScenario = Effect.fn("recordGrokScenario")(function* (fixtureName: s | ... | @@ -490,7 +490,7 @@ const recordScenario = Effect.fn("recordGrokScenario")(function* (fixtureName: s |
| 490 | ).pipe( | 490 | ).pipe( |
| 491 | Layer.provide( | 491 | Layer.provide( |
| 492 | Layer.mergeAll( | 492 | Layer.mergeAll( |
| 493 | layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), | 493 | TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)), |
| 494 | NodeServices.layer, | 494 | NodeServices.layer, |
| 495 | IdAllocator.layer, | 495 | IdAllocator.layer, |
| 496 | ), | 496 | ), |
apps/server/src/assets/AssetAccess.ts+2-2| ... | @@ -53,7 +53,7 @@ import * as ServerSecretStore from "../auth/ServerSecretStore.ts"; | ... | @@ -53,7 +53,7 @@ import * as ServerSecretStore from "../auth/ServerSecretStore.ts"; |
| 53 | import { parseAttachmentFileExtension, resolveAttachmentPathById } from "../attachmentStore.ts"; | 53 | import { parseAttachmentFileExtension, resolveAttachmentPathById } from "../attachmentStore.ts"; |
| 54 | import * as ServerConfig from "../config.ts"; | 54 | import * as ServerConfig from "../config.ts"; |
| 55 | import * as Orchestrator from "../orchestration-v2/Orchestrator.ts"; | 55 | import * as Orchestrator from "../orchestration-v2/Orchestrator.ts"; |
| 56 | import { expandHomePathWith } from "@t3tools/provider-core/server/pathExpansion"; | 56 | import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; |
| 57 | import * as ProjectFaviconResolver from "../project/ProjectFaviconResolver.ts"; | 57 | import * as ProjectFaviconResolver from "../project/ProjectFaviconResolver.ts"; |
| 58 | import * as WorkspacePaths from "../workspace/WorkspacePaths.ts"; | 58 | import * as WorkspacePaths from "../workspace/WorkspacePaths.ts"; |
| 59 | import * as NativeAppIconResolver from "./NativeAppIconResolver.ts"; | 59 | import * as NativeAppIconResolver from "./NativeAppIconResolver.ts"; |
| ... | @@ -469,7 +469,7 @@ export const issueAssetUrl = Effect.fn("AssetAccess.issueAssetUrl")(function* (i | ... | @@ -469,7 +469,7 @@ export const issueAssetUrl = Effect.fn("AssetAccess.issueAssetUrl")(function* (i |
| 469 | 469 | ||
| 470 | switch (input.resource._tag) { | 470 | switch (input.resource._tag) { |
| 471 | case "media-file": { | 471 | case "media-file": { |
| 472 | let requestedPath = expandHomePathWith(input.resource.path, path); | 472 | let requestedPath = expandHomePath(input.resource.path); |
| 473 | if (!path.isAbsolute(requestedPath)) { | 473 | if (!path.isAbsolute(requestedPath)) { |
| 474 | if (!input.workspaceRoot) { | 474 | if (!input.workspaceRoot) { |
| 475 | return yield* new AssetWorkspaceContextNotFoundError({ resource: input.resource }); | 475 | return yield* new AssetWorkspaceContextNotFoundError({ resource: input.resource }); |
apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts+2-2| ... | @@ -53,7 +53,7 @@ import * as EffectAcpErrors from "effect-acp/errors"; | ... | @@ -53,7 +53,7 @@ import * as EffectAcpErrors from "effect-acp/errors"; |
| 53 | import type * as EffectAcpProtocol from "effect-acp/protocol"; | 53 | import type * as EffectAcpProtocol from "effect-acp/protocol"; |
| 54 | import type * as EffectAcpSchema from "effect-acp/compat"; | 54 | import type * as EffectAcpSchema from "effect-acp/compat"; |
| 55 | 55 | ||
| 56 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 56 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 57 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; | 57 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; |
| 58 | import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; | 58 | import * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; |
| 59 | import { | 59 | import { |
| ... | @@ -94,7 +94,7 @@ import { | ... | @@ -94,7 +94,7 @@ import { |
| 94 | 94 | ||
| 95 | const DEFAULT_GROK_SETTINGS = Schema.decodeSync(GrokSettings)({}); | 95 | const DEFAULT_GROK_SETTINGS = Schema.decodeSync(GrokSettings)({}); |
| 96 | 96 | ||
| 97 | const layerHost = layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)); | 97 | const layerHost = TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)); |
| 98 | 98 | ||
| 99 | const layerTest = Layer.mergeAll( | 99 | const layerTest = Layer.mergeAll( |
| 100 | NodeServices.layer, | 100 | NodeServices.layer, |
apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.test.ts+2-2| ... | @@ -15,7 +15,7 @@ import * as EffectAcpErrors from "effect-acp/errors"; | ... | @@ -15,7 +15,7 @@ import * as EffectAcpErrors from "effect-acp/errors"; |
| 15 | 15 | ||
| 16 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | 16 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; |
| 17 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; | 17 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; |
| 18 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 18 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 19 | import * as ServerSettings from "../../serverSettings.ts"; | 19 | import * as ServerSettings from "../../serverSettings.ts"; |
| 20 | import type { | 20 | import type { |
| 21 | AcpRegistryAvailableCommands, | 21 | AcpRegistryAvailableCommands, |
| ... | @@ -44,7 +44,7 @@ const decodeAcpRegistryAdapterSettings = Schema.decodeUnknownEffect( | ... | @@ -44,7 +44,7 @@ const decodeAcpRegistryAdapterSettings = Schema.decodeUnknownEffect( |
| 44 | AcpRegistryAdapterV2Driver.configSchema, | 44 | AcpRegistryAdapterV2Driver.configSchema, |
| 45 | ); | 45 | ); |
| 46 | 46 | ||
| 47 | const layerHost = layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)); | 47 | const layerHost = TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)); |
| 48 | 48 | ||
| 49 | const layerRegistry = Layer.succeed( | 49 | const layerRegistry = Layer.succeed( |
| 50 | HttpClient.HttpClient, | 50 | HttpClient.HttpClient, |
apps/server/src/orchestration-v2/Adapters/AcpRegistryAdapterV2.testkit.ts+2-2| ... | @@ -8,7 +8,7 @@ import * as Path from "effect/Path"; | ... | @@ -8,7 +8,7 @@ import * as Path from "effect/Path"; |
| 8 | import * as Schema from "effect/Schema"; | 8 | import * as Schema from "effect/Schema"; |
| 9 | import { ChildProcessSpawner } from "effect/process"; | 9 | import { ChildProcessSpawner } from "effect/process"; |
| 10 | 10 | ||
| 11 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 11 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 12 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 12 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| 13 | import * as ProviderAdapterRegistry from "../ProviderAdapterRegistry.ts"; | 13 | import * as ProviderAdapterRegistry from "../ProviderAdapterRegistry.ts"; |
| 14 | import type { ProviderReplayGate } from "@t3tools/provider-testing/replayGate"; | 14 | import type { ProviderReplayGate } from "@t3tools/provider-testing/replayGate"; |
| ... | @@ -35,7 +35,7 @@ function layerAcpRegistryProviderAdapterRegistryReplay( | ... | @@ -35,7 +35,7 @@ function layerAcpRegistryProviderAdapterRegistryReplay( |
| 35 | transcript: AcpReplayTranscript, | 35 | transcript: AcpReplayTranscript, |
| 36 | options: { readonly replayGate?: ProviderReplayGate } = {}, | 36 | options: { readonly replayGate?: ProviderReplayGate } = {}, |
| 37 | ) { | 37 | ) { |
| 38 | const layerHost = layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)); | 38 | const layerHost = TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)); |
| 39 | 39 | ||
| 40 | return ProviderAdapterRegistry.layerFromAdaptersEffect( | 40 | return ProviderAdapterRegistry.layerFromAdaptersEffect( |
| 41 | Effect.gen(function* () { | 41 | Effect.gen(function* () { |
apps/server/src/orchestration-v2/Adapters/AntigravityAdapterV2.test.ts+2-2| ... | @@ -24,7 +24,7 @@ import type * as EffectAcpSchema from "effect-acp/compat"; | ... | @@ -24,7 +24,7 @@ import type * as EffectAcpSchema from "effect-acp/compat"; |
| 24 | 24 | ||
| 25 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | 25 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; |
| 26 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; | 26 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; |
| 27 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 27 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 28 | import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; | 28 | import type * as AcpSessionRuntime from "@t3tools/provider-acp/server/AcpSessionRuntime"; |
| 29 | import { makeAntigravityAcpRuntime } from "../../provider/acp/AntigravityAcpSupport.ts"; | 29 | import { makeAntigravityAcpRuntime } from "../../provider/acp/AntigravityAcpSupport.ts"; |
| 30 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 30 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| ... | @@ -131,7 +131,7 @@ const layerSession = Layer.mergeAll( | ... | @@ -131,7 +131,7 @@ const layerSession = Layer.mergeAll( |
| 131 | NodeServices.layer, | 131 | NodeServices.layer, |
| 132 | IdAllocator.layer, | 132 | IdAllocator.layer, |
| 133 | McpProviderSessions.layer, | 133 | McpProviderSessions.layer, |
| 134 | layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), | 134 | TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)), |
| 135 | ); | 135 | ); |
| 136 | 136 | ||
| 137 | describe("AntigravityAdapterV2 client file system", () => { | 137 | describe("AntigravityAdapterV2 client file system", () => { |
apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts+2-2| ... | @@ -108,7 +108,7 @@ import { | ... | @@ -108,7 +108,7 @@ import { |
| 108 | claudeRateLimitEventToUpdate, | 108 | claudeRateLimitEventToUpdate, |
| 109 | type ClaudeScopedLimitNames, | 109 | type ClaudeScopedLimitNames, |
| 110 | } from "../../provider/claudeUsageLimits.ts"; | 110 | } from "../../provider/claudeUsageLimits.ts"; |
| 111 | import type { ServerProviderShape } from "@t3tools/provider-core/server/snapshot"; | 111 | import type { ManagedServerProvider } from "@t3tools/provider-core/server/snapshot"; |
| 112 | import { mergeProviderInstanceEnvironment } from "@t3tools/provider-core/server/instanceEnvironment"; | 112 | import { mergeProviderInstanceEnvironment } from "@t3tools/provider-core/server/instanceEnvironment"; |
| 113 | import { T3_CODE_ORCHESTRATION_INSTRUCTIONS } from "@t3tools/provider-core/server/orchestrationInstructions"; | 113 | import { T3_CODE_ORCHESTRATION_INSTRUCTIONS } from "@t3tools/provider-core/server/orchestrationInstructions"; |
| 114 | import { buildRuntimeInstructions } from "@t3tools/provider-core/server/runtimeInstructions"; | 114 | import { buildRuntimeInstructions } from "@t3tools/provider-core/server/runtimeInstructions"; |
| ... | @@ -3018,7 +3018,7 @@ export interface ClaudeAdapterV2Options { | ... | @@ -3018,7 +3018,7 @@ export interface ClaudeAdapterV2Options { |
| 3018 | readonly idAllocator: IdAllocator.IdAllocatorV2["Service"]; | 3018 | readonly idAllocator: IdAllocator.IdAllocatorV2["Service"]; |
| 3019 | readonly queryRunner: ClaudeAgentSdkQueryRunnerShape; | 3019 | readonly queryRunner: ClaudeAgentSdkQueryRunnerShape; |
| 3020 | readonly scopedLimitNames?: Ref.Ref<ClaudeScopedLimitNames>; | 3020 | readonly scopedLimitNames?: Ref.Ref<ClaudeScopedLimitNames>; |
| 3021 | readonly onUsageLimits?: ServerProviderShape["applyUsageLimits"]; | 3021 | readonly onUsageLimits?: ManagedServerProvider["applyUsageLimits"]; |
| 3022 | /** Sink for wake-turn continuation requests; defaults to dropping them. */ | 3022 | /** Sink for wake-turn continuation requests; defaults to dropping them. */ |
| 3023 | readonly continuationRequests?: { | 3023 | readonly continuationRequests?: { |
| 3024 | readonly offer: ( | 3024 | readonly offer: ( |
apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.ts+2-2| ... | @@ -12,7 +12,7 @@ import { | ... | @@ -12,7 +12,7 @@ import { |
| 12 | completeCodexTurnTokenUsage, | 12 | completeCodexTurnTokenUsage, |
| 13 | type CodexTurnTokenUsageState, | 13 | type CodexTurnTokenUsageState, |
| 14 | } from "../../provider/CodexTurnTokenUsage.ts"; | 14 | } from "../../provider/CodexTurnTokenUsage.ts"; |
| 15 | import type { ServerProviderShape } from "@t3tools/provider-core/server/snapshot"; | 15 | import type { ManagedServerProvider } from "@t3tools/provider-core/server/snapshot"; |
| 16 | import type { CodexEffectiveRuntime } from "../../provider/CodexManagedRuntime.ts"; | 16 | import type { CodexEffectiveRuntime } from "../../provider/CodexManagedRuntime.ts"; |
| 17 | import { buildCodexInitializeParams } from "../../provider/CodexProvider.ts"; | 17 | import { buildCodexInitializeParams } from "../../provider/CodexProvider.ts"; |
| 18 | import { | 18 | import { |
| ... | @@ -1646,7 +1646,7 @@ export interface CodexAdapterV2Options { | ... | @@ -1646,7 +1646,7 @@ export interface CodexAdapterV2Options { |
| 1646 | readonly settings: CodexSettings; | 1646 | readonly settings: CodexSettings; |
| 1647 | readonly environment: NodeJS.ProcessEnv; | 1647 | readonly environment: NodeJS.ProcessEnv; |
| 1648 | readonly clientFactory: CodexAppServerClientFactoryShape; | 1648 | readonly clientFactory: CodexAppServerClientFactoryShape; |
| 1649 | readonly onUsageLimits?: ServerProviderShape["applyUsageLimits"]; | 1649 | readonly onUsageLimits?: ManagedServerProvider["applyUsageLimits"]; |
| 1650 | /** | 1650 | /** |
| 1651 | * Resolves launch settings when each session opens, replacing `settings` and | 1651 | * Resolves launch settings when each session opens, replacing `settings` and |
| 1652 | * `environment`. Managed ChatGPT sign-in uses it to launch the T3-installed | 1652 | * `environment`. Managed ChatGPT sign-in uses it to launch the T3-installed |
apps/server/src/orchestration-v2/Adapters/CursorAdapterV2.testkit.ts+2-2| ... | @@ -15,7 +15,7 @@ import * as FileSystem from "effect/FileSystem"; | ... | @@ -15,7 +15,7 @@ import * as FileSystem from "effect/FileSystem"; |
| 15 | import * as Layer from "effect/Layer"; | 15 | import * as Layer from "effect/Layer"; |
| 16 | import * as Schema from "effect/Schema"; | 16 | import * as Schema from "effect/Schema"; |
| 17 | 17 | ||
| 18 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 18 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 19 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 19 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| 20 | import { ProviderAdapterDriverCreateError } from "@t3tools/provider-core/server/adapterDriver"; | 20 | import { ProviderAdapterDriverCreateError } from "@t3tools/provider-core/server/adapterDriver"; |
| 21 | import * as ProviderAdapterRegistry from "../ProviderAdapterRegistry.ts"; | 21 | import * as ProviderAdapterRegistry from "../ProviderAdapterRegistry.ts"; |
| ... | @@ -537,7 +537,7 @@ export function layer( | ... | @@ -537,7 +537,7 @@ export function layer( |
| 537 | Layer.provide( | 537 | Layer.provide( |
| 538 | Layer.mergeAll( | 538 | Layer.mergeAll( |
| 539 | layerCursorAgentSdkReplay(transcript, options), | 539 | layerCursorAgentSdkReplay(transcript, options), |
| 540 | layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), | 540 | TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)), |
| 541 | layerHostEnvironment, | 541 | layerHostEnvironment, |
| 542 | NodeServices.layer, | 542 | NodeServices.layer, |
| 543 | IdAllocator.layer, | 543 | IdAllocator.layer, |
apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.test.ts+2-2| ... | @@ -20,7 +20,7 @@ import * as Schema from "effect/Schema"; | ... | @@ -20,7 +20,7 @@ import * as Schema from "effect/Schema"; |
| 20 | import { ChildProcessSpawner } from "effect/process"; | 20 | import { ChildProcessSpawner } from "effect/process"; |
| 21 | import type * as EffectAcpSchema from "effect-acp/compat"; | 21 | import type * as EffectAcpSchema from "effect-acp/compat"; |
| 22 | 22 | ||
| 23 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 23 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 24 | import * as ProjectStore from "../ProjectStore.ts"; | 24 | import * as ProjectStore from "../ProjectStore.ts"; |
| 25 | import { buildInitialGrokProviderSnapshot } from "@t3tools/provider-grok/testing"; | 25 | import { buildInitialGrokProviderSnapshot } from "@t3tools/provider-grok/testing"; |
| 26 | import type { ProviderInstance } from "@t3tools/provider-core/server/driver"; | 26 | import type { ProviderInstance } from "@t3tools/provider-core/server/driver"; |
| ... | @@ -309,7 +309,7 @@ describe("Grok permission prompts", () => { | ... | @@ -309,7 +309,7 @@ describe("Grok permission prompts", () => { |
| 309 | }); | 309 | }); |
| 310 | 310 | ||
| 311 | describe("Grok launch permission mode", () => { | 311 | describe("Grok launch permission mode", () => { |
| 312 | const layerHost = layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)); | 312 | const layerHost = TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)); |
| 313 | const layerTest = Layer.mergeAll( | 313 | const layerTest = Layer.mergeAll( |
| 314 | NodeServices.layer, | 314 | NodeServices.layer, |
| 315 | IdAllocator.layer, | 315 | IdAllocator.layer, |
apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.testkit.ts+2-2| ... | @@ -9,7 +9,7 @@ import { ChildProcessSpawner } from "effect/process"; | ... | @@ -9,7 +9,7 @@ import { ChildProcessSpawner } from "effect/process"; |
| 9 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; | 9 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; |
| 10 | import { resolveSelfInvocation } from "@t3tools/shared/nodeRuntime"; | 10 | import { resolveSelfInvocation } from "@t3tools/shared/nodeRuntime"; |
| 11 | 11 | ||
| 12 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 12 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 13 | import { GROK_ACP_CANCEL_META, GROK_ACP_INITIALIZE_META } from "@t3tools/provider-grok/testing"; | 13 | import { GROK_ACP_CANCEL_META, GROK_ACP_INITIALIZE_META } from "@t3tools/provider-grok/testing"; |
| 14 | import { makeXAiPromptCompletionRuntime } from "@t3tools/provider-grok/testing"; | 14 | import { makeXAiPromptCompletionRuntime } from "@t3tools/provider-grok/testing"; |
| 15 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 15 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| ... | @@ -36,7 +36,7 @@ function layerGrokProviderAdapterRegistryReplay( | ... | @@ -36,7 +36,7 @@ function layerGrokProviderAdapterRegistryReplay( |
| 36 | transcript: AcpReplayTranscript, | 36 | transcript: AcpReplayTranscript, |
| 37 | options: { readonly replayGate?: ProviderReplayGate } = {}, | 37 | options: { readonly replayGate?: ProviderReplayGate } = {}, |
| 38 | ) { | 38 | ) { |
| 39 | const layerHost = layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)); | 39 | const layerHost = TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)); |
| 40 | 40 | ||
| 41 | return ProviderAdapterRegistry.layerFromAdaptersEffect( | 41 | return ProviderAdapterRegistry.layerFromAdaptersEffect( |
| 42 | Effect.gen(function* () { | 42 | Effect.gen(function* () { |
apps/server/src/orchestration-v2/Adapters/MuseAdapterV2.testkit.ts+2-2| ... | @@ -27,7 +27,7 @@ import * as Effect from "effect/Effect"; | ... | @@ -27,7 +27,7 @@ import * as Effect from "effect/Effect"; |
| 27 | import * as Layer from "effect/Layer"; | 27 | import * as Layer from "effect/Layer"; |
| 28 | import * as Schema from "effect/Schema"; | 28 | import * as Schema from "effect/Schema"; |
| 29 | 29 | ||
| 30 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 30 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 31 | import { | 31 | import { |
| 32 | museInitializeParams, | 32 | museInitializeParams, |
| 33 | museServeArgs, | 33 | museServeArgs, |
| ... | @@ -460,7 +460,7 @@ export function layer(input: { | ... | @@ -460,7 +460,7 @@ export function layer(input: { |
| 460 | ).pipe( | 460 | ).pipe( |
| 461 | Layer.provide( | 461 | Layer.provide( |
| 462 | Layer.mergeAll( | 462 | Layer.mergeAll( |
| 463 | layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), | 463 | TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)), |
| 464 | NodeServices.layer, | 464 | NodeServices.layer, |
| 465 | IdAllocator.layer, | 465 | IdAllocator.layer, |
| 466 | ), | 466 | ), |
apps/server/src/orchestration-v2/Adapters/OpenCode2AdapterV2.testkit.ts+2-2| ... | @@ -26,7 +26,7 @@ import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | ... | @@ -26,7 +26,7 @@ import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| 26 | import * as ProviderAdapterRegistry from "../ProviderAdapterRegistry.ts"; | 26 | import * as ProviderAdapterRegistry from "../ProviderAdapterRegistry.ts"; |
| 27 | import type { ProviderReplayGate } from "@t3tools/provider-testing/replayGate"; | 27 | import type { ProviderReplayGate } from "@t3tools/provider-testing/replayGate"; |
| 28 | import type { OrchestratorV2ProviderReplayHarness } from "../testkit/ProviderReplayHarness.ts"; | 28 | import type { OrchestratorV2ProviderReplayHarness } from "../testkit/ProviderReplayHarness.ts"; |
| 29 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 29 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 30 | import { OPENCODE_PROVIDER } from "@t3tools/provider-opencode/testing"; | 30 | import { OPENCODE_PROVIDER } from "@t3tools/provider-opencode/testing"; |
| 31 | import { | 31 | import { |
| 32 | OpenCodeReplayController, | 32 | OpenCodeReplayController, |
| ... | @@ -267,7 +267,7 @@ const makeReplayAdapter = ( | ... | @@ -267,7 +267,7 @@ const makeReplayAdapter = ( |
| 267 | ); | 267 | ); |
| 268 | }); | 268 | }); |
| 269 | 269 | ||
| 270 | const layerReplayHost = layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)); | 270 | const layerReplayHost = TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)); |
| 271 | 271 | ||
| 272 | function layerRegistry( | 272 | function layerRegistry( |
| 273 | transcript: OpenCode2ReplayTranscript, | 273 | transcript: OpenCode2ReplayTranscript, |
apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.testkit.ts+3-3| ... | @@ -8,7 +8,7 @@ import * as Schema from "effect/Schema"; | ... | @@ -8,7 +8,7 @@ import * as Schema from "effect/Schema"; |
| 8 | 8 | ||
| 9 | import { OpenCodeAdapterV2Driver } from "@t3tools/provider-opencode/server"; | 9 | import { OpenCodeAdapterV2Driver } from "@t3tools/provider-opencode/server"; |
| 10 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; | 10 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; |
| 11 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 11 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 12 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; | 12 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; |
| 13 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 13 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| 14 | import { ProviderAdapterDriverCreateError } from "@t3tools/provider-core/server/adapterDriver"; | 14 | import { ProviderAdapterDriverCreateError } from "@t3tools/provider-core/server/adapterDriver"; |
| ... | @@ -448,7 +448,7 @@ function layerOpenCodeReplayRuntime(transcript: OpenCodeSdkReplayTranscript) { | ... | @@ -448,7 +448,7 @@ function layerOpenCodeReplayRuntime(transcript: OpenCodeSdkReplayTranscript) { |
| 448 | detail: "OpenCode replay does not load skills.", | 448 | detail: "OpenCode replay does not load skills.", |
| 449 | }), | 449 | }), |
| 450 | ), | 450 | ), |
| 451 | } satisfies OpenCodeRuntime.OpenCodeRuntimeShape); | 451 | } satisfies OpenCodeRuntime.OpenCodeRuntime["Service"]); |
| 452 | }), | 452 | }), |
| 453 | ); | 453 | ); |
| 454 | } | 454 | } |
| ... | @@ -466,7 +466,7 @@ function layerOpenCodeProviderAdapterRegistryReplay(transcript: OpenCodeSdkRepla | ... | @@ -466,7 +466,7 @@ function layerOpenCodeProviderAdapterRegistryReplay(transcript: OpenCodeSdkRepla |
| 466 | Layer.provide( | 466 | Layer.provide( |
| 467 | Layer.mergeAll( | 467 | Layer.mergeAll( |
| 468 | layerOpenCodeReplayRuntime(transcript), | 468 | layerOpenCodeReplayRuntime(transcript), |
| 469 | layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), | 469 | TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)), |
| 470 | NodeServices.layer, | 470 | NodeServices.layer, |
| 471 | IdAllocator.layer, | 471 | IdAllocator.layer, |
| 472 | Layer.succeed( | 472 | Layer.succeed( |
apps/server/src/orchestration-v2/Adapters/PiAdapterV2.testkit.ts+2-2| ... | @@ -30,7 +30,7 @@ import * as Sink from "effect/Sink"; | ... | @@ -30,7 +30,7 @@ import * as Sink from "effect/Sink"; |
| 30 | import * as Stream from "effect/Stream"; | 30 | import * as Stream from "effect/Stream"; |
| 31 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 31 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; |
| 32 | 32 | ||
| 33 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 33 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 34 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 34 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| 35 | import { ProviderAdapterDriverCreateError } from "@t3tools/provider-core/server/adapterDriver"; | 35 | import { ProviderAdapterDriverCreateError } from "@t3tools/provider-core/server/adapterDriver"; |
| 36 | import * as ProviderAdapterRegistry from "../ProviderAdapterRegistry.ts"; | 36 | import * as ProviderAdapterRegistry from "../ProviderAdapterRegistry.ts"; |
| ... | @@ -425,7 +425,7 @@ export function layer<E, R>(input: { | ... | @@ -425,7 +425,7 @@ export function layer<E, R>(input: { |
| 425 | Layer.provide(input.spawner), | 425 | Layer.provide(input.spawner), |
| 426 | Layer.provide( | 426 | Layer.provide( |
| 427 | Layer.mergeAll( | 427 | Layer.mergeAll( |
| 428 | layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), | 428 | TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)), |
| 429 | NodeServices.layer, | 429 | NodeServices.layer, |
| 430 | IdAllocator.layer, | 430 | IdAllocator.layer, |
| 431 | ), | 431 | ), |
apps/server/src/provider/CodexProvider.ts+1-1| ... | @@ -716,7 +716,7 @@ export const checkCodexProviderStatus = Effect.fn("checkCodexProviderStatus")(fu | ... | @@ -716,7 +716,7 @@ export const checkCodexProviderStatus = Effect.fn("checkCodexProviderStatus")(fu |
| 716 | // NOTE: the singleton `CodexProviderLive` Layer has been removed as part of | 716 | // NOTE: the singleton `CodexProviderLive` Layer has been removed as part of |
| 717 | // the per-instance-driver refactor. `CodexDriver.create()` builds a managed | 717 | // the per-instance-driver refactor. `CodexDriver.create()` builds a managed |
| 718 | // snapshot per instance (each with its own `CodexSettings`) and hands the | 718 | // snapshot per instance (each with its own `CodexSettings`) and hands the |
| 719 | // resulting `ServerProviderShape` back as `ProviderInstance.snapshot`. | 719 | // resulting `ManagedServerProvider` back as `ProviderInstance.snapshot`. |
| 720 | // | 720 | // |
| 721 | // The `makePendingCodexProvider` and `checkCodexProviderStatus` helpers are | 721 | // The `makePendingCodexProvider` and `checkCodexProviderStatus` helpers are |
| 722 | // re-exported for use by `CodexDriver`. | 722 | // re-exported for use by `CodexDriver`. |
apps/server/src/provider/Drivers/CodexDriver.ts+1-1| ... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
| 3 | * | 3 | * |
| 4 | * A driver is a plain value (not a Context.Service) whose `create()` returns | 4 | * A driver is a plain value (not a Context.Service) whose `create()` returns |
| 5 | * one `ProviderInstance` bundling: | 5 | * one `ProviderInstance` bundling: |
| 6 | * - `snapshot` — the live `ServerProviderShape` for this instance; | 6 | * - `snapshot` — the live `ManagedServerProvider` for this instance; |
| 7 | * - `adapter` — the Codex session/turn/approval runtime; | 7 | * - `adapter` — the Codex session/turn/approval runtime; |
| 8 | * - `textGeneration` — commit/PR/branch/title generation via `codex exec`. | 8 | * - `textGeneration` — commit/PR/branch/title generation via `codex exec`. |
| 9 | * | 9 | * |
apps/server/src/provider/ProviderRegistry.ts+2-2| ... | @@ -9,8 +9,8 @@ | ... | @@ -9,8 +9,8 @@ |
| 9 | * | 9 | * |
| 10 | * Historically this Layer composed four per-kind Live Layers | 10 | * Historically this Layer composed four per-kind Live Layers |
| 11 | * (`CodexProviderLive`, `ClaudeProviderLive`, …) that each exposed a | 11 | * (`CodexProviderLive`, `ClaudeProviderLive`, …) that each exposed a |
| 12 | * `ServerProviderShape`. Those Lives were deleted during the driver / | 12 | * `ManagedServerProvider`. Those Lives were deleted during the driver / |
| 13 | * instance refactor — every driver now carries its `snapshot: ServerProviderShape` | 13 | * instance refactor — every driver now carries its `snapshot: ManagedServerProvider` |
| 14 | * bundled onto the `ProviderInstance` the registry produces. | 14 | * bundled onto the `ProviderInstance` the registry produces. |
| 15 | * | 15 | * |
| 16 | * Each configured instance (including multi-instance setups like | 16 | * Each configured instance (including multi-instance setups like |
apps/server/src/provider/builtInProviderCatalog.ts+3-3| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | import type { ProviderDriverKind, ProviderInstanceId, ServerProvider } from "@t3tools/contracts"; | 1 | import type { ProviderDriverKind, ProviderInstanceId, ServerProvider } from "@t3tools/contracts"; |
| 2 | import type * as Stream from "effect/Stream"; | 2 | import type * as Stream from "effect/Stream"; |
| 3 | import type { ServerProviderShape } from "@t3tools/provider-core/server/snapshot"; | 3 | import type { ManagedServerProvider } from "@t3tools/provider-core/server/snapshot"; |
| 4 | 4 | ||
| 5 | export type ProviderSnapshotSource = { | 5 | export type ProviderSnapshotSource = { |
| 6 | /** | 6 | /** |
| ... | @@ -11,7 +11,7 @@ export type ProviderSnapshotSource = { | ... | @@ -11,7 +11,7 @@ export type ProviderSnapshotSource = { |
| 11 | readonly instanceId: ProviderInstanceId; | 11 | readonly instanceId: ProviderInstanceId; |
| 12 | /** Driver implementation kind. */ | 12 | /** Driver implementation kind. */ |
| 13 | readonly driverKind: ProviderDriverKind; | 13 | readonly driverKind: ProviderDriverKind; |
| 14 | readonly getSnapshot: ServerProviderShape["getSnapshot"]; | 14 | readonly getSnapshot: ManagedServerProvider["getSnapshot"]; |
| 15 | readonly refresh: ServerProviderShape["refresh"]; | 15 | readonly refresh: ManagedServerProvider["refresh"]; |
| 16 | readonly streamChanges: Stream.Stream<ServerProvider>; | 16 | readonly streamChanges: Stream.Stream<ServerProvider>; |
| 17 | }; | 17 | }; |
apps/server/src/sourceControl/SourceControlRepositoryService.ts+2-2| ... | @@ -21,7 +21,7 @@ import { | ... | @@ -21,7 +21,7 @@ import { |
| 21 | } from "@t3tools/contracts"; | 21 | } from "@t3tools/contracts"; |
| 22 | 22 | ||
| 23 | import * as ServerConfig from "../config.ts"; | 23 | import * as ServerConfig from "../config.ts"; |
| 24 | import { expandHomePathWith } from "@t3tools/provider-core/server/pathExpansion"; | 24 | import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; |
| 25 | import { | 25 | import { |
| 26 | parseGitCloneProgressLine, | 26 | parseGitCloneProgressLine, |
| 27 | type GitCloneProgressLine, | 27 | type GitCloneProgressLine, |
| ... | @@ -213,7 +213,7 @@ export const make = Effect.gen(function* () { | ... | @@ -213,7 +213,7 @@ export const make = Effect.gen(function* () { |
| 213 | }); | 213 | }); |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | return path.resolve(expandHomePathWith(trimmed, path)); | 216 | return path.resolve(expandHomePath(trimmed)); |
| 217 | }, | 217 | }, |
| 218 | ); | 218 | ); |
| 219 | 219 |
apps/server/src/textGeneration/OpenCode2TextGeneration.test.ts+2-2| ... | @@ -4,13 +4,13 @@ import { ProviderInstanceId } from "@t3tools/contracts"; | ... | @@ -4,13 +4,13 @@ import { ProviderInstanceId } from "@t3tools/contracts"; |
| 4 | import * as Effect from "effect/Effect"; | 4 | import * as Effect from "effect/Effect"; |
| 5 | import * as Layer from "effect/Layer"; | 5 | import * as Layer from "effect/Layer"; |
| 6 | 6 | ||
| 7 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 7 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 8 | import * as OpenCode2AdapterV2Testkit from "../orchestration-v2/Adapters/OpenCode2AdapterV2.testkit.ts"; | 8 | import * as OpenCode2AdapterV2Testkit from "../orchestration-v2/Adapters/OpenCode2AdapterV2.testkit.ts"; |
| 9 | import * as OpenCode2Server from "@t3tools/provider-opencode/server/v2/OpenCode2Server"; | 9 | import * as OpenCode2Server from "@t3tools/provider-opencode/server/v2/OpenCode2Server"; |
| 10 | import * as OpenCode2TextGeneration from "@t3tools/provider-opencode/server/v2/textGeneration"; | 10 | import * as OpenCode2TextGeneration from "@t3tools/provider-opencode/server/v2/textGeneration"; |
| 11 | import { OPENCODE2_TITLE_GENERATION } from "./OpenCode2TextGeneration.fixture.ts"; | 11 | import { OPENCODE2_TITLE_GENERATION } from "./OpenCode2TextGeneration.fixture.ts"; |
| 12 | 12 | ||
| 13 | const layer = layerTestProviderHost().pipe(Layer.provideMerge(NodeServices.layer)); | 13 | const layer = TestProviderHost.layer().pipe(Layer.provideMerge(NodeServices.layer)); |
| 14 | 14 | ||
| 15 | it.layer(layer)("OpenCode2TextGeneration", (it) => { | 15 | it.layer(layer)("OpenCode2TextGeneration", (it) => { |
| 16 | it.effect("generates a title in a temporary session on the free tier and removes it", () => | 16 | it.effect("generates a title in a temporary session on the free tier and removes it", () => |
apps/server/src/workspace/WorkspaceEntries.ts+3-3| ... | @@ -23,7 +23,7 @@ import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; | ... | @@ -23,7 +23,7 @@ import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; |
| 23 | import { isExplicitRelativePath, isWindowsAbsolutePath } from "@t3tools/shared/path"; | 23 | import { isExplicitRelativePath, isWindowsAbsolutePath } from "@t3tools/shared/path"; |
| 24 | import { normalizeSearchQuery } from "@t3tools/shared/searchRanking"; | 24 | import { normalizeSearchQuery } from "@t3tools/shared/searchRanking"; |
| 25 | 25 | ||
| 26 | import { expandHomePathWith } from "@t3tools/provider-core/server/pathExpansion"; | 26 | import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; |
| 27 | import * as VcsProcess from "../vcs/VcsProcess.ts"; | 27 | import * as VcsProcess from "../vcs/VcsProcess.ts"; |
| 28 | import * as WorkspacePaths from "./WorkspacePaths.ts"; | 28 | import * as WorkspacePaths from "./WorkspacePaths.ts"; |
| 29 | import * as WorkspaceSearchIndex from "./WorkspaceSearchIndex.ts"; | 29 | import * as WorkspaceSearchIndex from "./WorkspaceSearchIndex.ts"; |
| ... | @@ -120,7 +120,7 @@ const resolveBrowseTarget = Effect.fn("WorkspaceEntries.resolveBrowseTarget")(fu | ... | @@ -120,7 +120,7 @@ const resolveBrowseTarget = Effect.fn("WorkspaceEntries.resolveBrowseTarget")(fu |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | if (!isExplicitRelativePath(input.partialPath)) { | 122 | if (!isExplicitRelativePath(input.partialPath)) { |
| 123 | return path.resolve(expandHomePathWith(input.partialPath, path)); | 123 | return path.resolve(expandHomePath(input.partialPath)); |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | if (!input.cwd) { | 126 | if (!input.cwd) { |
| ... | @@ -128,7 +128,7 @@ const resolveBrowseTarget = Effect.fn("WorkspaceEntries.resolveBrowseTarget")(fu | ... | @@ -128,7 +128,7 @@ const resolveBrowseTarget = Effect.fn("WorkspaceEntries.resolveBrowseTarget")(fu |
| 128 | partialPath: input.partialPath, | 128 | partialPath: input.partialPath, |
| 129 | }); | 129 | }); |
| 130 | } | 130 | } |
| 131 | return path.resolve(expandHomePathWith(input.cwd, path), input.partialPath); | 131 | return path.resolve(expandHomePath(input.cwd), input.partialPath); |
| 132 | }); | 132 | }); |
| 133 | 133 | ||
| 134 | /** @public Service construction is part of the canonical Effect module API. */ | 134 | /** @public Service construction is part of the canonical Effect module API. */ |
apps/server/src/workspace/WorkspacePaths.ts+2-2| ... | @@ -14,7 +14,7 @@ import * as Layer from "effect/Layer"; | ... | @@ -14,7 +14,7 @@ import * as Layer from "effect/Layer"; |
| 14 | import * as Path from "effect/Path"; | 14 | import * as Path from "effect/Path"; |
| 15 | import * as Schema from "effect/Schema"; | 15 | import * as Schema from "effect/Schema"; |
| 16 | 16 | ||
| 17 | import { expandHomePathWith } from "@t3tools/provider-core/server/pathExpansion"; | 17 | import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; |
| 18 | 18 | ||
| 19 | export class WorkspaceRootNotExistsError extends Schema.TaggedError<WorkspaceRootNotExistsError>()( | 19 | export class WorkspaceRootNotExistsError extends Schema.TaggedError<WorkspaceRootNotExistsError>()( |
| 20 | "WorkspaceRootNotExistsError", | 20 | "WorkspaceRootNotExistsError", |
| ... | @@ -152,7 +152,7 @@ export const make = Effect.gen(function* () { | ... | @@ -152,7 +152,7 @@ export const make = Effect.gen(function* () { |
| 152 | const normalizeWorkspaceRoot: WorkspacePaths["Service"]["normalizeWorkspaceRoot"] = Effect.fn( | 152 | const normalizeWorkspaceRoot: WorkspacePaths["Service"]["normalizeWorkspaceRoot"] = Effect.fn( |
| 153 | "WorkspacePaths.normalizeWorkspaceRoot", | 153 | "WorkspacePaths.normalizeWorkspaceRoot", |
| 154 | )(function* (workspaceRoot, options) { | 154 | )(function* (workspaceRoot, options) { |
| 155 | const normalizedWorkspaceRoot = path.resolve(expandHomePathWith(workspaceRoot.trim(), path)); | 155 | const normalizedWorkspaceRoot = path.resolve(expandHomePath(workspaceRoot.trim())); |
| 156 | let workspaceStat = yield* statWorkspaceRoot( | 156 | let workspaceStat = yield* statWorkspaceRoot( |
| 157 | workspaceRoot, | 157 | workspaceRoot, |
| 158 | normalizedWorkspaceRoot, | 158 | normalizedWorkspaceRoot, |
apps/server/src/worktreesDirectory.ts+2-2| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | import type * as Path from "effect/Path"; | 1 | import type * as Path from "effect/Path"; |
| 2 | 2 | ||
| 3 | import { expandHomePathWith } from "@t3tools/provider-core/server/pathExpansion"; | 3 | import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; |
| 4 | 4 | ||
| 5 | /** | 5 | /** |
| 6 | * Directory new worktrees are created under: the `worktreesDirectory` | 6 | * Directory new worktrees are created under: the `worktreesDirectory` |
| ... | @@ -15,7 +15,7 @@ export function resolveWorktreesDirectory( | ... | @@ -15,7 +15,7 @@ export function resolveWorktreesDirectory( |
| 15 | path: Path.Path, | 15 | path: Path.Path, |
| 16 | ): string | null { | 16 | ): string | null { |
| 17 | if (setting === "") return defaultDir; | 17 | if (setting === "") return defaultDir; |
| 18 | const expanded = expandHomePathWith(setting, path); | 18 | const expanded = expandHomePath(setting); |
| 19 | if (!path.isAbsolute(expanded)) return null; | 19 | if (!path.isAbsolute(expanded)) return null; |
| 20 | const resolved = path.resolve(expanded); | 20 | const resolved = path.resolve(expanded); |
| 21 | return isFilesystemRoot(resolved, path) ? null : resolved; | 21 | return isFilesystemRoot(resolved, path) ? null : resolved; |
packages/provider-acp-registry/src/server/AcpRegistrySupport.test.ts+5-5| ... | @@ -24,7 +24,7 @@ import * as TestClock from "effect/testing/TestClock"; | ... | @@ -24,7 +24,7 @@ import * as TestClock from "effect/testing/TestClock"; |
| 24 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 24 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; |
| 25 | 25 | ||
| 26 | import * as AcpRegistrySupport from "./AcpRegistrySupport.ts"; | 26 | import * as AcpRegistrySupport from "./AcpRegistrySupport.ts"; |
| 27 | import { layerTestProviderHost, TestProviderHostSettings } from "@t3tools/provider-testing/host"; | 27 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 28 | 28 | ||
| 29 | const registryUrl = "https://registry.test/registry.json"; | 29 | const registryUrl = "https://registry.test/registry.json"; |
| 30 | const archiveUrl = "https://registry.test/example-agent.bin"; | 30 | const archiveUrl = "https://registry.test/example-agent.bin"; |
| ... | @@ -60,7 +60,7 @@ function layerResolver( | ... | @@ -60,7 +60,7 @@ function layerResolver( |
| 60 | ) { | 60 | ) { |
| 61 | return Layer.mergeAll( | 61 | return Layer.mergeAll( |
| 62 | NodeServices.layer, | 62 | NodeServices.layer, |
| 63 | layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), | 63 | TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)), |
| 64 | Layer.succeed(HostProcessPlatform, "linux"), | 64 | Layer.succeed(HostProcessPlatform, "linux"), |
| 65 | Layer.succeed(HostProcessArchitecture, "x64"), | 65 | Layer.succeed(HostProcessArchitecture, "x64"), |
| 66 | Layer.succeed(HostProcessEnvironment, environment), | 66 | Layer.succeed(HostProcessEnvironment, environment), |
| ... | @@ -776,7 +776,7 @@ describe("AcpRegistrySupport", () => { | ... | @@ -776,7 +776,7 @@ describe("AcpRegistrySupport", () => { |
| 776 | Effect.provide( | 776 | Effect.provide( |
| 777 | Layer.mergeAll( | 777 | Layer.mergeAll( |
| 778 | NodeServices.layer, | 778 | NodeServices.layer, |
| 779 | layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), | 779 | TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)), |
| 780 | ), | 780 | ), |
| 781 | ), | 781 | ), |
| 782 | Effect.provideService(HostProcessPlatform, "linux"), | 782 | Effect.provideService(HostProcessPlatform, "linux"), |
| ... | @@ -1374,7 +1374,7 @@ describe("AcpRegistrySupport", () => { | ... | @@ -1374,7 +1374,7 @@ describe("AcpRegistrySupport", () => { |
| 1374 | toolsDir: `${cacheDir}/tools`, | 1374 | toolsDir: `${cacheDir}/tools`, |
| 1375 | registryUrl, | 1375 | registryUrl, |
| 1376 | }); | 1376 | }); |
| 1377 | const hostSettings = yield* TestProviderHostSettings; | 1377 | const hostSettings = yield* TestProviderHost.TestProviderHostSettings; |
| 1378 | const instanceId = ProviderInstanceId.make("uninstall-reference"); | 1378 | const instanceId = ProviderInstanceId.make("uninstall-reference"); |
| 1379 | yield* hostSettings.set({ | 1379 | yield* hostSettings.set({ |
| 1380 | ...DEFAULT_SERVER_SETTINGS, | 1380 | ...DEFAULT_SERVER_SETTINGS, |
| ... | @@ -1492,7 +1492,7 @@ describe("AcpRegistrySupport", () => { | ... | @@ -1492,7 +1492,7 @@ describe("AcpRegistrySupport", () => { |
| 1492 | const agentRoot = `${cacheDir}/tools/${agent.id}`; | 1492 | const agentRoot = `${cacheDir}/tools/${agent.id}`; |
| 1493 | expect(yield* fileSystem.exists(agentRoot)).toBe(true); | 1493 | expect(yield* fileSystem.exists(agentRoot)).toBe(true); |
| 1494 | 1494 | ||
| 1495 | const hostSettings = yield* TestProviderHostSettings; | 1495 | const hostSettings = yield* TestProviderHost.TestProviderHostSettings; |
| 1496 | const instanceId = ProviderInstanceId.make("registry-reference"); | 1496 | const instanceId = ProviderInstanceId.make("registry-reference"); |
| 1497 | yield* hostSettings.set({ | 1497 | yield* hostSettings.set({ |
| 1498 | ...DEFAULT_SERVER_SETTINGS, | 1498 | ...DEFAULT_SERVER_SETTINGS, |
packages/provider-core/src/server/driver.ts+2-2| ... | @@ -40,7 +40,7 @@ import type * as Scope from "effect/Scope"; | ... | @@ -40,7 +40,7 @@ import type * as Scope from "effect/Scope"; |
| 40 | import type * as ProviderAdapter from "./ProviderAdapter.ts"; | 40 | import type * as ProviderAdapter from "./ProviderAdapter.ts"; |
| 41 | import type { ProviderAuthController } from "./auth.ts"; | 41 | import type { ProviderAuthController } from "./auth.ts"; |
| 42 | import type { ProviderDriverError } from "./errors.ts"; | 42 | import type { ProviderDriverError } from "./errors.ts"; |
| 43 | import type { ServerProviderShape } from "./snapshot.ts"; | 43 | import type { ManagedServerProvider } from "./snapshot.ts"; |
| 44 | import type { ProviderTextGeneration } from "./textGeneration.ts"; | 44 | import type { ProviderTextGeneration } from "./textGeneration.ts"; |
| 45 | 45 | ||
| 46 | /** | 46 | /** |
| ... | @@ -85,7 +85,7 @@ export interface ProviderInstance { | ... | @@ -85,7 +85,7 @@ export interface ProviderInstance { |
| 85 | readonly displayName: string | undefined; | 85 | readonly displayName: string | undefined; |
| 86 | readonly accentColor?: string | undefined; | 86 | readonly accentColor?: string | undefined; |
| 87 | readonly enabled: boolean; | 87 | readonly enabled: boolean; |
| 88 | readonly snapshot: ServerProviderShape; | 88 | readonly snapshot: ManagedServerProvider; |
| 89 | readonly snapshotForCwd?: ( | 89 | readonly snapshotForCwd?: ( |
| 90 | cwd: string, | 90 | cwd: string, |
| 91 | ) => Effect.Effect<ProviderWorkspaceSnapshot, ProviderDriverError>; | 91 | ) => Effect.Effect<ProviderWorkspaceSnapshot, ProviderDriverError>; |
packages/provider-core/src/server/maintenanceResolver.test.ts+2-2| ... | @@ -13,8 +13,8 @@ import * as Effect from "effect/Effect"; | ... | @@ -13,8 +13,8 @@ import * as Effect from "effect/Effect"; |
| 13 | import * as Fiber from "effect/Fiber"; | 13 | import * as Fiber from "effect/Fiber"; |
| 14 | import * as Sink from "effect/Sink"; | 14 | import * as Sink from "effect/Sink"; |
| 15 | import * as Stream from "effect/Stream"; | 15 | import * as Stream from "effect/Stream"; |
| 16 | import { HttpClient } from "effect/http"; | 16 | import * as HttpClient from "effect/http/HttpClient"; |
| 17 | import { ChildProcessSpawner } from "effect/process"; | 17 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; |
| 18 | import * as ProviderLatestVersions from "./ProviderLatestVersions.ts"; | 18 | import * as ProviderLatestVersions from "./ProviderLatestVersions.ts"; |
| 19 | import { | 19 | import { |
| 20 | createProviderVersionAdvisory, | 20 | createProviderVersionAdvisory, |
packages/provider-core/src/server/maintenanceResolver.ts+4-2| ... | @@ -25,8 +25,10 @@ import * as Option from "effect/Option"; | ... | @@ -25,8 +25,10 @@ import * as Option from "effect/Option"; |
| 25 | import * as Path from "effect/Path"; | 25 | import * as Path from "effect/Path"; |
| 26 | import * as Schema from "effect/Schema"; | 26 | import * as Schema from "effect/Schema"; |
| 27 | import * as Stream from "effect/Stream"; | 27 | import * as Stream from "effect/Stream"; |
| 28 | import { HttpClient, HttpClientRequest } from "effect/http"; | 28 | import * as HttpClient from "effect/http/HttpClient"; |
| 29 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 29 | import * as HttpClientRequest from "effect/http/HttpClientRequest"; |
| 30 | import * as ChildProcess from "effect/process/ChildProcess"; | ||
| 31 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ||
| 30 | 32 | ||
| 31 | import { collectUint8StreamText } from "./collectStreamText.ts"; | 33 | import { collectUint8StreamText } from "./collectStreamText.ts"; |
| 32 | import * as ProviderLatestVersions from "./ProviderLatestVersions.ts"; | 34 | import * as ProviderLatestVersions from "./ProviderLatestVersions.ts"; |
packages/provider-core/src/server/managedProvider.test.ts+1-1| ... | @@ -14,7 +14,7 @@ import * as Layer from "effect/Layer"; | ... | @@ -14,7 +14,7 @@ import * as Layer from "effect/Layer"; |
| 14 | import * as PubSub from "effect/PubSub"; | 14 | import * as PubSub from "effect/PubSub"; |
| 15 | import * as Ref from "effect/Ref"; | 15 | import * as Ref from "effect/Ref"; |
| 16 | import * as Stream from "effect/Stream"; | 16 | import * as Stream from "effect/Stream"; |
| 17 | import { TestClock } from "effect/testing"; | 17 | import * as TestClock from "effect/testing/TestClock"; |
| 18 | 18 | ||
| 19 | import * as ProviderHost from "./ProviderHost.ts"; | 19 | import * as ProviderHost from "./ProviderHost.ts"; |
| 20 | import { makeManagedServerProvider } from "./managedProvider.ts"; | 20 | import { makeManagedServerProvider } from "./managedProvider.ts"; |
packages/provider-core/src/server/managedProvider.ts+5-5| ... | @@ -17,7 +17,7 @@ import * as Semaphore from "effect/Semaphore"; | ... | @@ -17,7 +17,7 @@ import * as Semaphore from "effect/Semaphore"; |
| 17 | 17 | ||
| 18 | import * as ProviderHost from "./ProviderHost.ts"; | 18 | import * as ProviderHost from "./ProviderHost.ts"; |
| 19 | import { applyUsageLimitsUpdate, resolveUsageLimitsAfterProbe } from "./usageLimits.ts"; | 19 | import { applyUsageLimitsUpdate, resolveUsageLimitsAfterProbe } from "./usageLimits.ts"; |
| 20 | import type { ServerProviderShape } from "./snapshot.ts"; | 20 | import type { ManagedServerProvider } from "./snapshot.ts"; |
| 21 | 21 | ||
| 22 | interface ProviderSnapshotState { | 22 | interface ProviderSnapshotState { |
| 23 | readonly snapshot: ServerProvider; | 23 | readonly snapshot: ServerProvider; |
| ... | @@ -38,7 +38,7 @@ function withUsageLimits( | ... | @@ -38,7 +38,7 @@ function withUsageLimits( |
| 38 | export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")(function* < | 38 | export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")(function* < |
| 39 | Settings, | 39 | Settings, |
| 40 | >(input: { | 40 | >(input: { |
| 41 | readonly resolveMaintenance: ServerProviderShape["resolveMaintenance"]; | 41 | readonly resolveMaintenance: ManagedServerProvider["resolveMaintenance"]; |
| 42 | readonly getSettings: Effect.Effect<Settings, ServerSettingsError>; | 42 | readonly getSettings: Effect.Effect<Settings, ServerSettingsError>; |
| 43 | readonly streamSettings: Stream.Stream<Settings>; | 43 | readonly streamSettings: Stream.Stream<Settings>; |
| 44 | readonly haveSettingsChanged: (previous: Settings, next: Settings) => boolean; | 44 | readonly haveSettingsChanged: (previous: Settings, next: Settings) => boolean; |
| ... | @@ -54,7 +54,7 @@ export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( | ... | @@ -54,7 +54,7 @@ export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( |
| 54 | readonly refreshOnInterval?: boolean; | 54 | readonly refreshOnInterval?: boolean; |
| 55 | readonly checkProviderOnSettingsChange?: (previous: Settings, next: Settings) => boolean; | 55 | readonly checkProviderOnSettingsChange?: (previous: Settings, next: Settings) => boolean; |
| 56 | }): Effect.fn.Return< | 56 | }): Effect.fn.Return< |
| 57 | ServerProviderShape, | 57 | ManagedServerProvider, |
| 58 | ServerSettingsError, | 58 | ServerSettingsError, |
| 59 | Scope.Scope | ProviderHost.ProviderHost | 59 | Scope.Scope | ProviderHost.ProviderHost |
| 60 | > { | 60 | > { |
| ... | @@ -181,7 +181,7 @@ export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( | ... | @@ -181,7 +181,7 @@ export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( |
| 181 | * `usageLimits` on whatever snapshot is published and leave the enrichment | 181 | * `usageLimits` on whatever snapshot is published and leave the enrichment |
| 182 | * generation alone, so an in-flight enrichment still lands. | 182 | * generation alone, so an in-flight enrichment still lands. |
| 183 | */ | 183 | */ |
| 184 | const applyUsageLimits: ServerProviderShape["applyUsageLimits"] = (update) => | 184 | const applyUsageLimits: ManagedServerProvider["applyUsageLimits"] = (update) => |
| 185 | Effect.gen(function* () { | 185 | Effect.gen(function* () { |
| 186 | const snapshotToPublish = yield* Ref.modify(snapshotStateRef, (state) => { | 186 | const snapshotToPublish = yield* Ref.modify(snapshotStateRef, (state) => { |
| 187 | const usageLimits = applyUsageLimitsUpdate({ | 187 | const usageLimits = applyUsageLimitsUpdate({ |
| ... | @@ -289,5 +289,5 @@ export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( | ... | @@ -289,5 +289,5 @@ export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")( |
| 289 | get streamChanges() { | 289 | get streamChanges() { |
| 290 | return Stream.fromPubSub(changesPubSub); | 290 | return Stream.fromPubSub(changesPubSub); |
| 291 | }, | 291 | }, |
| 292 | } satisfies ServerProviderShape; | 292 | } satisfies ManagedServerProvider; |
| 293 | }); | 293 | }); |
packages/provider-core/src/server/pathExpansion.ts-18| ... | @@ -2,8 +2,6 @@ | ... | @@ -2,8 +2,6 @@ |
| 2 | import * as NodeOS from "node:os"; | 2 | import * as NodeOS from "node:os"; |
| 3 | import * as NodePath from "node:path"; | 3 | import * as NodePath from "node:path"; |
| 4 | 4 | ||
| 5 | import type * as Path from "effect/Path"; | ||
| 6 | |||
| 7 | /** | 5 | /** |
| 8 | * Expand a leading `~` (or `~/…`, `~\…`) in a user-supplied path to the | 6 | * Expand a leading `~` (or `~/…`, `~\…`) in a user-supplied path to the |
| 9 | * current user's home directory. Spawned processes don't get shell | 7 | * current user's home directory. Spawned processes don't get shell |
| ... | @@ -24,19 +22,3 @@ export function expandHomePath(value: string): string { | ... | @@ -24,19 +22,3 @@ export function expandHomePath(value: string): string { |
| 24 | } | 22 | } |
| 25 | return value; | 23 | return value; |
| 26 | } | 24 | } |
| 27 | |||
| 28 | /** | ||
| 29 | * Same expansion as `expandHomePath`, but joins with a caller-supplied | ||
| 30 | * `Path.Path` service instead of `node:path`. Use this inside Effect code that | ||
| 31 | * already has `Path.Path` in context so the platform layer stays in control of | ||
| 32 | * separator handling. | ||
| 33 | */ | ||
| 34 | export function expandHomePathWith(value: string, path: Path.Path): string { | ||
| 35 | if (value === "~") { | ||
| 36 | return NodeOS.homedir(); | ||
| 37 | } | ||
| 38 | if (value.startsWith("~/") || value.startsWith("~\\")) { | ||
| 39 | return path.join(NodeOS.homedir(), value.slice(2)); | ||
| 40 | } | ||
| 41 | return value; | ||
| 42 | } |
packages/provider-core/src/server/snapshot.ts+1-1| ... | @@ -3,7 +3,7 @@ import type * as Effect from "effect/Effect"; | ... | @@ -3,7 +3,7 @@ import type * as Effect from "effect/Effect"; |
| 3 | import type * as Stream from "effect/Stream"; | 3 | import type * as Stream from "effect/Stream"; |
| 4 | import type { ProviderMaintenanceCapabilities } from "./maintenance.ts"; | 4 | import type { ProviderMaintenanceCapabilities } from "./maintenance.ts"; |
| 5 | 5 | ||
| 6 | export interface ServerProviderShape { | 6 | export interface ManagedServerProvider { |
| 7 | /** | 7 | /** |
| 8 | * Ownership-derived update capabilities. Cached between reads; pass | 8 | * Ownership-derived update capabilities. Cached between reads; pass |
| 9 | * `{ fresh: true }` before executing an update so it never trusts a | 9 | * `{ fresh: true }` before executing an update so it never trusts a |
packages/provider-core/src/server/snapshotProbe.test.ts+2-1| ... | @@ -7,7 +7,8 @@ import * as Layer from "effect/Layer"; | ... | @@ -7,7 +7,8 @@ import * as Layer from "effect/Layer"; |
| 7 | import * as PlatformError from "effect/PlatformError"; | 7 | import * as PlatformError from "effect/PlatformError"; |
| 8 | import * as Sink from "effect/Sink"; | 8 | import * as Sink from "effect/Sink"; |
| 9 | import * as Stream from "effect/Stream"; | 9 | import * as Stream from "effect/Stream"; |
| 10 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 10 | import * as ChildProcess from "effect/process/ChildProcess"; |
| 11 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ||
| 11 | 12 | ||
| 12 | import { | 13 | import { |
| 13 | isCommandMissingCause, | 14 | isCommandMissingCause, |
packages/provider-core/src/server/snapshotProbe.ts+2-1| ... | @@ -16,7 +16,8 @@ import * as Effect from "effect/Effect"; | ... | @@ -16,7 +16,8 @@ import * as Effect from "effect/Effect"; |
| 16 | import * as PlatformError from "effect/PlatformError"; | 16 | import * as PlatformError from "effect/PlatformError"; |
| 17 | import * as Schema from "effect/Schema"; | 17 | import * as Schema from "effect/Schema"; |
| 18 | import * as Stream from "effect/Stream"; | 18 | import * as Stream from "effect/Stream"; |
| 19 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 19 | import * as ChildProcess from "effect/process/ChildProcess"; |
| 20 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ||
| 20 | import { readCustomModelEntries } from "@t3tools/shared/model"; | 21 | import { readCustomModelEntries } from "@t3tools/shared/model"; |
| 21 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; | 22 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; |
| 22 | import { createProviderVersionAdvisory } from "./maintenanceResolver.ts"; | 23 | import { createProviderVersionAdvisory } from "./maintenanceResolver.ts"; |
packages/provider-cursor/src/server/adapter.test.ts+4-4| ... | @@ -22,7 +22,7 @@ import * as Path from "effect/Path"; | ... | @@ -22,7 +22,7 @@ import * as Path from "effect/Path"; |
| 22 | import * as Schema from "effect/Schema"; | 22 | import * as Schema from "effect/Schema"; |
| 23 | import * as Stream from "effect/Stream"; | 23 | import * as Stream from "effect/Stream"; |
| 24 | 24 | ||
| 25 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 25 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 26 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 26 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| 27 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; | 27 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; |
| 28 | import * as ProviderAdapter from "@t3tools/provider-core/server/ProviderAdapter"; | 28 | import * as ProviderAdapter from "@t3tools/provider-core/server/ProviderAdapter"; |
| ... | @@ -125,7 +125,7 @@ describe("CursorAdapterV2", () => { | ... | @@ -125,7 +125,7 @@ describe("CursorAdapterV2", () => { |
| 125 | }), | 125 | }), |
| 126 | }), | 126 | }), |
| 127 | }), | 127 | }), |
| 128 | Effect.provide(layerTestProviderHost({ cwd: workspace })), | 128 | Effect.provide(TestProviderHost.layer({ cwd: workspace })), |
| 129 | ); | 129 | ); |
| 130 | const runtime = yield* adapter.openSession({ | 130 | const runtime = yield* adapter.openSession({ |
| 131 | threadId, | 131 | threadId, |
| ... | @@ -258,7 +258,7 @@ describe("CursorAdapterV2", () => { | ... | @@ -258,7 +258,7 @@ describe("CursorAdapterV2", () => { |
| 258 | }), | 258 | }), |
| 259 | }), | 259 | }), |
| 260 | }), | 260 | }), |
| 261 | Effect.provide(layerTestProviderHost({ cwd: workspace })), | 261 | Effect.provide(TestProviderHost.layer({ cwd: workspace })), |
| 262 | ); | 262 | ); |
| 263 | const runtime = yield* adapter.openSession({ | 263 | const runtime = yield* adapter.openSession({ |
| 264 | threadId, | 264 | threadId, |
| ... | @@ -597,7 +597,7 @@ describe("CursorAdapterV2", () => { | ... | @@ -597,7 +597,7 @@ describe("CursorAdapterV2", () => { |
| 597 | }), | 597 | }), |
| 598 | }), | 598 | }), |
| 599 | }), | 599 | }), |
| 600 | Effect.provide(layerTestProviderHost({ cwd: workspace })), | 600 | Effect.provide(TestProviderHost.layer({ cwd: workspace })), |
| 601 | ); | 601 | ); |
| 602 | const runtime = yield* adapter.openSession({ | 602 | const runtime = yield* adapter.openSession({ |
| 603 | threadId, | 603 | threadId, |
packages/provider-cursor/src/server/credentialStore.test.ts+2-2| ... | @@ -6,11 +6,11 @@ import * as FileSystem from "effect/FileSystem"; | ... | @@ -6,11 +6,11 @@ import * as FileSystem from "effect/FileSystem"; |
| 6 | import * as Path from "effect/Path"; | 6 | import * as Path from "effect/Path"; |
| 7 | 7 | ||
| 8 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | 8 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; |
| 9 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 9 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 10 | import * as Layer from "effect/Layer"; | 10 | import * as Layer from "effect/Layer"; |
| 11 | import { makeCursorCredentialStore } from "./credentialStore.ts"; | 11 | import { makeCursorCredentialStore } from "./credentialStore.ts"; |
| 12 | 12 | ||
| 13 | const layerHost = Layer.provideMerge(layerTestProviderHost(), NodeServices.layer); | 13 | const layerHost = Layer.provideMerge(TestProviderHost.layer(), NodeServices.layer); |
| 14 | 14 | ||
| 15 | const legacyCredentials = { | 15 | const legacyCredentials = { |
| 16 | version: 1 as const, | 16 | version: 1 as const, |
packages/provider-cursor/src/server/driver.test.ts+2-2| ... | @@ -11,7 +11,7 @@ import { HttpClient } from "effect/http"; | ... | @@ -11,7 +11,7 @@ import { HttpClient } from "effect/http"; |
| 11 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | 11 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; |
| 12 | 12 | ||
| 13 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; | 13 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; |
| 14 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 14 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 15 | import { CursorDriver } from "./driver.ts"; | 15 | import { CursorDriver } from "./driver.ts"; |
| 16 | import * as CursorAgentSdk from "./CursorAgentSdk.ts"; | 16 | import * as CursorAgentSdk from "./CursorAgentSdk.ts"; |
| 17 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 17 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| ... | @@ -19,7 +19,7 @@ import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderS | ... | @@ -19,7 +19,7 @@ import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderS |
| 19 | import * as ProviderAdapter from "@t3tools/provider-core/server/ProviderAdapter"; | 19 | import * as ProviderAdapter from "@t3tools/provider-core/server/ProviderAdapter"; |
| 20 | import { Cursor } from "./sdk.ts"; | 20 | import { Cursor } from "./sdk.ts"; |
| 21 | 21 | ||
| 22 | const layerTest = layerTestProviderHost({ runBackgroundWork: false }).pipe( | 22 | const layerTest = TestProviderHost.layer({ runBackgroundWork: false }).pipe( |
| 23 | Layer.provideMerge(NodeServices.layer), | 23 | Layer.provideMerge(NodeServices.layer), |
| 24 | Layer.provideMerge(IdAllocator.layer), | 24 | Layer.provideMerge(IdAllocator.layer), |
| 25 | Layer.provideMerge(McpProviderSessions.layer), | 25 | Layer.provideMerge(McpProviderSessions.layer), |
packages/provider-grok/src/server/driver.test.ts+2-2| ... | @@ -11,13 +11,13 @@ import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ... | @@ -11,13 +11,13 @@ import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; |
| 11 | 11 | ||
| 12 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | 12 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; |
| 13 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; | 13 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; |
| 14 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 14 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 15 | import { GrokDriver } from "./driver.ts"; | 15 | import { GrokDriver } from "./driver.ts"; |
| 16 | 16 | ||
| 17 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 17 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| 18 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; | 18 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; |
| 19 | 19 | ||
| 20 | const layerTest = layerTestProviderHost({ runBackgroundWork: false }).pipe( | 20 | const layerTest = TestProviderHost.layer({ runBackgroundWork: false }).pipe( |
| 21 | Layer.provideMerge(NodeServices.layer), | 21 | Layer.provideMerge(NodeServices.layer), |
| 22 | Layer.provideMerge(IdAllocator.layer), | 22 | Layer.provideMerge(IdAllocator.layer), |
| 23 | Layer.provideMerge(McpProviderSessions.layer), | 23 | Layer.provideMerge(McpProviderSessions.layer), |
packages/provider-muse/src/server/adapter.test.ts+2-2| ... | @@ -30,7 +30,7 @@ import * as Queue from "effect/Queue"; | ... | @@ -30,7 +30,7 @@ import * as Queue from "effect/Queue"; |
| 30 | import * as Schema from "effect/Schema"; | 30 | import * as Schema from "effect/Schema"; |
| 31 | import * as Stream from "effect/Stream"; | 31 | import * as Stream from "effect/Stream"; |
| 32 | 32 | ||
| 33 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 33 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 34 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; | 34 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; |
| 35 | import type { MuseItem } from "./protocol.ts"; | 35 | import type { MuseItem } from "./protocol.ts"; |
| 36 | import type { MuseSdkHost } from "./sdk.ts"; | 36 | import type { MuseSdkHost } from "./sdk.ts"; |
| ... | @@ -43,7 +43,7 @@ const testLayer = Layer.mergeAll( | ... | @@ -43,7 +43,7 @@ const testLayer = Layer.mergeAll( |
| 43 | NodeServices.layer, | 43 | NodeServices.layer, |
| 44 | IdAllocator.layer, | 44 | IdAllocator.layer, |
| 45 | McpProviderSessions.layer, | 45 | McpProviderSessions.layer, |
| 46 | layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), | 46 | TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)), |
| 47 | ); | 47 | ); |
| 48 | const MUSE_PROVIDER = ProviderDriverKind.make("muse"); | 48 | const MUSE_PROVIDER = ProviderDriverKind.make("muse"); |
| 49 | const INSTANCE_ID = ProviderInstanceId.make("muse_work"); | 49 | const INSTANCE_ID = ProviderInstanceId.make("muse_work"); |
packages/provider-muse/src/server/driver.ts+2-2| ... | @@ -5,8 +5,8 @@ import * as Effect from "effect/Effect"; | ... | @@ -5,8 +5,8 @@ import * as Effect from "effect/Effect"; |
| 5 | import * as FileSystem from "effect/FileSystem"; | 5 | import * as FileSystem from "effect/FileSystem"; |
| 6 | import * as Path from "effect/Path"; | 6 | import * as Path from "effect/Path"; |
| 7 | import * as Schema from "effect/Schema"; | 7 | import * as Schema from "effect/Schema"; |
| 8 | import { HttpClient } from "effect/http"; | 8 | import * as HttpClient from "effect/http/HttpClient"; |
| 9 | import { ChildProcessSpawner } from "effect/process"; | 9 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; |
| 10 | 10 | ||
| 11 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | 11 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; |
| 12 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | 12 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; |
packages/provider-muse/src/server/maintenance.test.ts+2-1| ... | @@ -3,7 +3,8 @@ import { expect, it } from "@effect/vitest"; | ... | @@ -3,7 +3,8 @@ import { expect, it } from "@effect/vitest"; |
| 3 | import { ProviderDriverKind, ProviderInstanceId, type ServerProvider } from "@t3tools/contracts"; | 3 | import { ProviderDriverKind, ProviderInstanceId, type ServerProvider } from "@t3tools/contracts"; |
| 4 | import * as Effect from "effect/Effect"; | 4 | import * as Effect from "effect/Effect"; |
| 5 | import * as FileSystem from "effect/FileSystem"; | 5 | import * as FileSystem from "effect/FileSystem"; |
| 6 | import { HttpClient, HttpClientResponse } from "effect/http"; | 6 | import * as HttpClient from "effect/http/HttpClient"; |
| 7 | import * as HttpClientResponse from "effect/http/HttpClientResponse"; | ||
| 7 | 8 | ||
| 8 | import { | 9 | import { |
| 9 | compareMuseVersions, | 10 | compareMuseVersions, |
packages/provider-muse/src/server/maintenance.ts+2-1| ... | @@ -3,7 +3,8 @@ import { compareSemverVersions } from "@t3tools/shared/semver"; | ... | @@ -3,7 +3,8 @@ import { compareSemverVersions } from "@t3tools/shared/semver"; |
| 3 | import * as Effect from "effect/Effect"; | 3 | import * as Effect from "effect/Effect"; |
| 4 | import * as FileSystem from "effect/FileSystem"; | 4 | import * as FileSystem from "effect/FileSystem"; |
| 5 | import * as Schema from "effect/Schema"; | 5 | import * as Schema from "effect/Schema"; |
| 6 | import { HttpClient, HttpClientRequest } from "effect/http"; | 6 | import * as HttpClient from "effect/http/HttpClient"; |
| 7 | import * as HttpClientRequest from "effect/http/HttpClientRequest"; | ||
| 7 | 8 | ||
| 8 | import { | 9 | import { |
| 9 | enrichProviderSnapshotWithVersionAdvisory, | 10 | enrichProviderSnapshotWithVersionAdvisory, |
packages/provider-muse/src/server/status.ts+1-1| ... | @@ -5,7 +5,7 @@ import * as DateTime from "effect/DateTime"; | ... | @@ -5,7 +5,7 @@ import * as DateTime from "effect/DateTime"; |
| 5 | import * as Effect from "effect/Effect"; | 5 | import * as Effect from "effect/Effect"; |
| 6 | import * as Option from "effect/Option"; | 6 | import * as Option from "effect/Option"; |
| 7 | import * as Result from "effect/Result"; | 7 | import * as Result from "effect/Result"; |
| 8 | import { ChildProcess } from "effect/process"; | 8 | import * as ChildProcess from "effect/process/ChildProcess"; |
| 9 | 9 | ||
| 10 | import { createMuseSdkHost, makeMuseEnvironment } from "./sdk.ts"; | 10 | import { createMuseSdkHost, makeMuseEnvironment } from "./sdk.ts"; |
| 11 | import { parseMuseVersion } from "./maintenance.ts"; | 11 | import { parseMuseVersion } from "./maintenance.ts"; |
packages/provider-opencode/src/server/OpenCodeRuntime.environment.test.ts+2-1| ... | @@ -12,7 +12,8 @@ import * as FileSystem from "effect/FileSystem"; | ... | @@ -12,7 +12,8 @@ import * as FileSystem from "effect/FileSystem"; |
| 12 | import * as Layer from "effect/Layer"; | 12 | import * as Layer from "effect/Layer"; |
| 13 | import * as Path from "effect/Path"; | 13 | import * as Path from "effect/Path"; |
| 14 | import * as TestClock from "effect/testing/TestClock"; | 14 | import * as TestClock from "effect/testing/TestClock"; |
| 15 | import { FetchHttpClient, HttpClient } from "effect/http"; | 15 | import * as FetchHttpClient from "effect/http/FetchHttpClient"; |
| 16 | import * as HttpClient from "effect/http/HttpClient"; | ||
| 16 | import { describe, expect, it } from "vite-plus/test"; | 17 | import { describe, expect, it } from "vite-plus/test"; |
| 17 | 18 | ||
| 18 | import * as OpenCodeRuntime from "./OpenCodeRuntime.ts"; | 19 | import * as OpenCodeRuntime from "./OpenCodeRuntime.ts"; |
packages/provider-opencode/src/server/OpenCodeRuntime.ts+80-76| ... | @@ -28,7 +28,8 @@ import * as Result from "effect/Result"; | ... | @@ -28,7 +28,8 @@ import * as Result from "effect/Result"; |
| 28 | import * as Scope from "effect/Scope"; | 28 | import * as Scope from "effect/Scope"; |
| 29 | import * as Schema from "effect/Schema"; | 29 | import * as Schema from "effect/Schema"; |
| 30 | import * as Stream from "effect/Stream"; | 30 | import * as Stream from "effect/Stream"; |
| 31 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 31 | import * as ChildProcess from "effect/process/ChildProcess"; |
| 32 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ||
| 32 | 33 | ||
| 33 | import { signalProcessGroup } from "@t3tools/provider-core/server/processGroup"; | 34 | import { signalProcessGroup } from "@t3tools/provider-core/server/processGroup"; |
| 34 | import { isWindowsCommandNotFound } from "@t3tools/provider-core/server/snapshotProbe"; | 35 | import { isWindowsCommandNotFound } from "@t3tools/provider-core/server/snapshotProbe"; |
| ... | @@ -227,68 +228,71 @@ const decodeOpenCodeSkillsCliOutputExit = Schema.decodeUnknownExit( | ... | @@ -227,68 +228,71 @@ const decodeOpenCodeSkillsCliOutputExit = Schema.decodeUnknownExit( |
| 227 | Schema.fromJsonString(Schema.Array(OpenCodeSkillSchema)), | 228 | Schema.fromJsonString(Schema.Array(OpenCodeSkillSchema)), |
| 228 | ); | 229 | ); |
| 229 | 230 | ||
| 230 | export interface OpenCodeRuntimeShape { | 231 | export class OpenCodeRuntime extends Context.Service< |
| 231 | /** | 232 | OpenCodeRuntime, |
| 232 | * Spawns a local OpenCode server process. Its lifetime is bound to the caller's | 233 | { |
| 233 | * `Scope.Scope` — the child is killed automatically when that scope closes. | 234 | /** |
| 234 | * Consumers that want a long-lived server must create and hold a scope explicitly | 235 | * Spawns a local OpenCode server process. Its lifetime is bound to the caller's |
| 235 | * (see {@link Scope.make}) and close it when done. | 236 | * `Scope.Scope` — the child is killed automatically when that scope closes. |
| 236 | */ | 237 | * Consumers that want a long-lived server must create and hold a scope explicitly |
| 237 | readonly startOpenCodeServerProcess: (input: { | 238 | * (see {@link Scope.make}) and close it when done. |
| 238 | readonly binaryPath: string; | 239 | */ |
| 239 | readonly directory: string; | 240 | readonly startOpenCodeServerProcess: (input: { |
| 240 | readonly serverPassword?: string; | 241 | readonly binaryPath: string; |
| 241 | readonly environment?: NodeJS.ProcessEnv; | 242 | readonly directory: string; |
| 242 | readonly port?: number; | 243 | readonly serverPassword?: string; |
| 243 | readonly hostname?: string; | 244 | readonly environment?: NodeJS.ProcessEnv; |
| 244 | readonly timeoutMs?: number; | 245 | readonly port?: number; |
| 245 | /** Checks the listening server and returns its version. Defaults to the 1.x health check. */ | 246 | readonly hostname?: string; |
| 246 | readonly verify?: (url: string) => Effect.Effect<string, OpenCodeRuntimeError>; | 247 | readonly timeoutMs?: number; |
| 247 | }) => Effect.Effect<OpenCodeServerProcess, OpenCodeRuntimeError, Scope.Scope>; | 248 | /** Checks the listening server and returns its version. Defaults to the 1.x health check. */ |
| 248 | /** | 249 | readonly verify?: (url: string) => Effect.Effect<string, OpenCodeRuntimeError>; |
| 249 | * Returns a handle to either an externally-managed OpenCode server (when | 250 | }) => Effect.Effect<OpenCodeServerProcess, OpenCodeRuntimeError, Scope.Scope>; |
| 250 | * `serverUrl` is provided — no lifetime is attached to the caller's scope) or a | 251 | /** |
| 251 | * freshly spawned local server whose lifetime is bound to the caller's scope. | 252 | * Returns a handle to either an externally-managed OpenCode server (when |
| 252 | */ | 253 | * `serverUrl` is provided — no lifetime is attached to the caller's scope) or a |
| 253 | readonly connectToOpenCodeServer: (input: { | 254 | * freshly spawned local server whose lifetime is bound to the caller's scope. |
| 254 | readonly binaryPath: string; | 255 | */ |
| 255 | readonly directory: string; | 256 | readonly connectToOpenCodeServer: (input: { |
| 256 | readonly serverUrl?: string | null; | 257 | readonly binaryPath: string; |
| 257 | readonly serverPassword?: string; | 258 | readonly directory: string; |
| 258 | readonly environment?: NodeJS.ProcessEnv; | 259 | readonly serverUrl?: string | null; |
| 259 | readonly port?: number; | 260 | readonly serverPassword?: string; |
| 260 | readonly hostname?: string; | 261 | readonly environment?: NodeJS.ProcessEnv; |
| 261 | readonly timeoutMs?: number; | 262 | readonly port?: number; |
| 262 | }) => Effect.Effect<OpenCodeServerConnection, OpenCodeRuntimeError, Scope.Scope>; | 263 | readonly hostname?: string; |
| 263 | readonly runOpenCodeCommand: (input: { | 264 | readonly timeoutMs?: number; |
| 264 | readonly binaryPath: string; | 265 | }) => Effect.Effect<OpenCodeServerConnection, OpenCodeRuntimeError, Scope.Scope>; |
| 265 | readonly args: ReadonlyArray<string>; | 266 | readonly runOpenCodeCommand: (input: { |
| 266 | readonly environment?: NodeJS.ProcessEnv; | 267 | readonly binaryPath: string; |
| 267 | readonly cwd?: string; | 268 | readonly args: ReadonlyArray<string>; |
| 268 | readonly maxOutputBytes?: number; | 269 | readonly environment?: NodeJS.ProcessEnv; |
| 269 | }) => Effect.Effect<OpenCodeCommandResult, OpenCodeRuntimeError>; | 270 | readonly cwd?: string; |
| 270 | readonly createOpenCodeSdkClient: (input: { | 271 | readonly maxOutputBytes?: number; |
| 271 | readonly baseUrl: string; | 272 | }) => Effect.Effect<OpenCodeCommandResult, OpenCodeRuntimeError>; |
| 272 | readonly directory: string; | 273 | readonly createOpenCodeSdkClient: (input: { |
| 273 | readonly serverPassword?: string; | 274 | readonly baseUrl: string; |
| 274 | }) => OpencodeClient; | 275 | readonly directory: string; |
| 275 | readonly loadOpenCodeInventory: ( | 276 | readonly serverPassword?: string; |
| 276 | client: OpencodeClient, | 277 | }) => OpencodeClient; |
| 277 | ) => Effect.Effect<OpenCodeInventory, OpenCodeRuntimeError>; | 278 | readonly loadOpenCodeInventory: ( |
| 278 | readonly loadOpenCodeSkills: ( | 279 | client: OpencodeClient, |
| 279 | client: OpencodeClient, | 280 | ) => Effect.Effect<OpenCodeInventory, OpenCodeRuntimeError>; |
| 280 | ) => Effect.Effect<ReadonlyArray<OpenCodeSkill>, OpenCodeRuntimeError>; | 281 | readonly loadOpenCodeSkills: ( |
| 281 | readonly loadInventoryFromCli: (input: { | 282 | client: OpencodeClient, |
| 282 | readonly binaryPath: string; | 283 | ) => Effect.Effect<ReadonlyArray<OpenCodeSkill>, OpenCodeRuntimeError>; |
| 283 | readonly cwd: string; | 284 | readonly loadInventoryFromCli: (input: { |
| 284 | readonly environment?: NodeJS.ProcessEnv; | 285 | readonly binaryPath: string; |
| 285 | }) => Effect.Effect<OpenCodeInventory, OpenCodeRuntimeError>; | 286 | readonly cwd: string; |
| 286 | readonly loadSkillsFromCli: (input: { | 287 | readonly environment?: NodeJS.ProcessEnv; |
| 287 | readonly binaryPath: string; | 288 | }) => Effect.Effect<OpenCodeInventory, OpenCodeRuntimeError>; |
| 288 | readonly cwd: string; | 289 | readonly loadSkillsFromCli: (input: { |
| 289 | readonly environment?: NodeJS.ProcessEnv; | 290 | readonly binaryPath: string; |
| 290 | }) => Effect.Effect<ReadonlyArray<OpenCodeSkill>, OpenCodeRuntimeError>; | 291 | readonly cwd: string; |
| 291 | } | 292 | readonly environment?: NodeJS.ProcessEnv; |
| 293 | }) => Effect.Effect<ReadonlyArray<OpenCodeSkill>, OpenCodeRuntimeError>; | ||
| 294 | } | ||
| 295 | >()("@t3tools/provider-opencode/server/OpenCodeRuntime") {} | ||
| 292 | 296 | ||
| 293 | function parseServerUrlFromOutput(output: string): string | null { | 297 | function parseServerUrlFromOutput(output: string): string | null { |
| 294 | for (const line of output.split("\n")) { | 298 | for (const line of output.split("\n")) { |
| ... | @@ -596,7 +600,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () { | ... | @@ -596,7 +600,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () { |
| 596 | const resolveCommand = (command: string, args: ReadonlyArray<string>, env?: NodeJS.ProcessEnv) => | 600 | const resolveCommand = (command: string, args: ReadonlyArray<string>, env?: NodeJS.ProcessEnv) => |
| 597 | resolveSpawnCommand(command, args, env ? { env } : {}); | 601 | resolveSpawnCommand(command, args, env ? { env } : {}); |
| 598 | 602 | ||
| 599 | const runOpenCodeCommand: OpenCodeRuntimeShape["runOpenCodeCommand"] = (input) => | 603 | const runOpenCodeCommand: OpenCodeRuntime["Service"]["runOpenCodeCommand"] = (input) => |
| 600 | Effect.gen(function* () { | 604 | Effect.gen(function* () { |
| 601 | const spawnCommand = yield* resolveCommand(input.binaryPath, input.args, input.environment); | 605 | const spawnCommand = yield* resolveCommand(input.binaryPath, input.args, input.environment); |
| 602 | const child = yield* spawner.spawn( | 606 | const child = yield* spawner.spawn( |
| ... | @@ -651,7 +655,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () { | ... | @@ -651,7 +655,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () { |
| 651 | ), | 655 | ), |
| 652 | ); | 656 | ); |
| 653 | 657 | ||
| 654 | const createOpenCodeSdkClient: OpenCodeRuntimeShape["createOpenCodeSdkClient"] = (input) => | 658 | const createOpenCodeSdkClient: OpenCodeRuntime["Service"]["createOpenCodeSdkClient"] = (input) => |
| 655 | createOpencodeClient({ | 659 | createOpencodeClient({ |
| 656 | baseUrl: input.baseUrl, | 660 | baseUrl: input.baseUrl, |
| 657 | directory: input.directory, | 661 | directory: input.directory, |
| ... | @@ -665,7 +669,9 @@ const makeOpenCodeRuntime = Effect.gen(function* () { | ... | @@ -665,7 +669,9 @@ const makeOpenCodeRuntime = Effect.gen(function* () { |
| 665 | throwOnError: true, | 669 | throwOnError: true, |
| 666 | }); | 670 | }); |
| 667 | 671 | ||
| 668 | const startOpenCodeServerProcess: OpenCodeRuntimeShape["startOpenCodeServerProcess"] = (input) => | 672 | const startOpenCodeServerProcess: OpenCodeRuntime["Service"]["startOpenCodeServerProcess"] = ( |
| 673 | input, | ||
| 674 | ) => | ||
| 669 | Effect.gen(function* () { | 675 | Effect.gen(function* () { |
| 670 | // Bind this server's lifetime to the caller's scope. When the caller's | 676 | // Bind this server's lifetime to the caller's scope. When the caller's |
| 671 | // scope closes, the spawned child is killed and all associated fibers | 677 | // scope closes, the spawned child is killed and all associated fibers |
| ... | @@ -872,7 +878,9 @@ const makeOpenCodeRuntime = Effect.gen(function* () { | ... | @@ -872,7 +878,9 @@ const makeOpenCodeRuntime = Effect.gen(function* () { |
| 872 | } satisfies OpenCodeServerProcess; | 878 | } satisfies OpenCodeServerProcess; |
| 873 | }); | 879 | }); |
| 874 | 880 | ||
| 875 | const connectToOpenCodeServer: OpenCodeRuntimeShape["connectToOpenCodeServer"] = (input) => { | 881 | const connectToOpenCodeServer: OpenCodeRuntime["Service"]["connectToOpenCodeServer"] = ( |
| 882 | input, | ||
| 883 | ) => { | ||
| 876 | const serverUrl = input.serverUrl?.trim(); | 884 | const serverUrl = input.serverUrl?.trim(); |
| 877 | if (serverUrl) { | 885 | if (serverUrl) { |
| 878 | const serverPassword = resolveOpenCodeServerPassword({ | 886 | const serverPassword = resolveOpenCodeServerPassword({ |
| ... | @@ -937,7 +945,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () { | ... | @@ -937,7 +945,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () { |
| 937 | Effect.orElseSucceed((): ReadonlyArray<Agent> => []), | 945 | Effect.orElseSucceed((): ReadonlyArray<Agent> => []), |
| 938 | ); | 946 | ); |
| 939 | 947 | ||
| 940 | const loadOpenCodeSkills: OpenCodeRuntimeShape["loadOpenCodeSkills"] = (client) => | 948 | const loadOpenCodeSkills: OpenCodeRuntime["Service"]["loadOpenCodeSkills"] = (client) => |
| 941 | runOpenCodeSdk("app.skills", (signal) => client.app.skills(undefined, { signal })).pipe( | 949 | runOpenCodeSdk("app.skills", (signal) => client.app.skills(undefined, { signal })).pipe( |
| 942 | Effect.map((result) => | 950 | Effect.map((result) => |
| 943 | (result.data ?? []).map((skill) => ({ | 951 | (result.data ?? []).map((skill) => ({ |
| ... | @@ -950,7 +958,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () { | ... | @@ -950,7 +958,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () { |
| 950 | const loadSkills = (client: OpencodeClient) => | 958 | const loadSkills = (client: OpencodeClient) => |
| 951 | loadOpenCodeSkills(client).pipe(Effect.orElseSucceed((): ReadonlyArray<OpenCodeSkill> => [])); | 959 | loadOpenCodeSkills(client).pipe(Effect.orElseSucceed((): ReadonlyArray<OpenCodeSkill> => [])); |
| 952 | 960 | ||
| 953 | const loadOpenCodeInventory: OpenCodeRuntimeShape["loadOpenCodeInventory"] = (client) => | 961 | const loadOpenCodeInventory: OpenCodeRuntime["Service"]["loadOpenCodeInventory"] = (client) => |
| 954 | Effect.all( | 962 | Effect.all( |
| 955 | [ | 963 | [ |
| 956 | loadProviders(client), | 964 | loadProviders(client), |
| ... | @@ -970,7 +978,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () { | ... | @@ -970,7 +978,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () { |
| 970 | })), | 978 | })), |
| 971 | ); | 979 | ); |
| 972 | 980 | ||
| 973 | const loadInventoryFromCli: OpenCodeRuntimeShape["loadInventoryFromCli"] = (input) => | 981 | const loadInventoryFromCli: OpenCodeRuntime["Service"]["loadInventoryFromCli"] = (input) => |
| 974 | Effect.gen(function* () { | 982 | Effect.gen(function* () { |
| 975 | const env = input.environment !== undefined ? { environment: input.environment } : ({} as {}); | 983 | const env = input.environment !== undefined ? { environment: input.environment } : ({} as {}); |
| 976 | const commandContext = { cwd: input.cwd, ...env }; | 984 | const commandContext = { cwd: input.cwd, ...env }; |
| ... | @@ -1070,7 +1078,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () { | ... | @@ -1070,7 +1078,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () { |
| 1070 | }; | 1078 | }; |
| 1071 | }); | 1079 | }); |
| 1072 | 1080 | ||
| 1073 | const loadSkillsFromCli: OpenCodeRuntimeShape["loadSkillsFromCli"] = (input) => | 1081 | const loadSkillsFromCli: OpenCodeRuntime["Service"]["loadSkillsFromCli"] = (input) => |
| 1074 | runOpenCodeCommand({ | 1082 | runOpenCodeCommand({ |
| 1075 | binaryPath: input.binaryPath, | 1083 | binaryPath: input.binaryPath, |
| 1076 | args: ["debug", "skill"], | 1084 | args: ["debug", "skill"], |
| ... | @@ -1099,13 +1107,9 @@ const makeOpenCodeRuntime = Effect.gen(function* () { | ... | @@ -1099,13 +1107,9 @@ const makeOpenCodeRuntime = Effect.gen(function* () { |
| 1099 | loadOpenCodeSkills, | 1107 | loadOpenCodeSkills, |
| 1100 | loadInventoryFromCli, | 1108 | loadInventoryFromCli, |
| 1101 | loadSkillsFromCli, | 1109 | loadSkillsFromCli, |
| 1102 | } satisfies OpenCodeRuntimeShape; | 1110 | } satisfies OpenCodeRuntime["Service"]; |
| 1103 | }); | 1111 | }); |
| 1104 | 1112 | ||
| 1105 | export class OpenCodeRuntime extends Context.Service<OpenCodeRuntime, OpenCodeRuntimeShape>()( | ||
| 1106 | "@t3tools/provider-opencode/server/OpenCodeRuntime", | ||
| 1107 | ) {} | ||
| 1108 | |||
| 1109 | export const layer = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe( | 1113 | export const layer = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe( |
| 1110 | Layer.provide(NetService.layer), | 1114 | Layer.provide(NetService.layer), |
| 1111 | ); | 1115 | ); |
packages/provider-opencode/src/server/OpenCodeServerLedger.test.ts+1-1| ... | @@ -12,7 +12,7 @@ import * as FileSystem from "effect/FileSystem"; | ... | @@ -12,7 +12,7 @@ import * as FileSystem from "effect/FileSystem"; |
| 12 | import * as Layer from "effect/Layer"; | 12 | import * as Layer from "effect/Layer"; |
| 13 | import * as Path from "effect/Path"; | 13 | import * as Path from "effect/Path"; |
| 14 | import * as Scope from "effect/Scope"; | 14 | import * as Scope from "effect/Scope"; |
| 15 | import { ChildProcessSpawner } from "effect/process"; | 15 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; |
| 16 | 16 | ||
| 17 | import * as OpenCodeRuntime from "./OpenCodeRuntime.ts"; | 17 | import * as OpenCodeRuntime from "./OpenCodeRuntime.ts"; |
| 18 | import * as OpenCodeServerLedger from "./OpenCodeServerLedger.ts"; | 18 | import * as OpenCodeServerLedger from "./OpenCodeServerLedger.ts"; |
packages/provider-opencode/src/server/OpenCodeServerLedger.ts+2-1| ... | @@ -6,7 +6,8 @@ import * as Layer from "effect/Layer"; | ... | @@ -6,7 +6,8 @@ import * as Layer from "effect/Layer"; |
| 6 | import * as Option from "effect/Option"; | 6 | import * as Option from "effect/Option"; |
| 7 | import * as Path from "effect/Path"; | 7 | import * as Path from "effect/Path"; |
| 8 | import * as Schema from "effect/Schema"; | 8 | import * as Schema from "effect/Schema"; |
| 9 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 9 | import * as ChildProcess from "effect/process/ChildProcess"; |
| 10 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ||
| 10 | 11 | ||
| 11 | import { writeFileStringAtomically } from "@t3tools/shared/atomicWrite"; | 12 | import { writeFileStringAtomically } from "@t3tools/shared/atomicWrite"; |
| 12 | import { signalProcessGroup } from "@t3tools/provider-core/server/processGroup"; | 13 | import { signalProcessGroup } from "@t3tools/provider-core/server/processGroup"; |
packages/provider-opencode/src/server/OpenCodeServerOwner.test.ts+4-4| ... | @@ -24,7 +24,7 @@ const makeRuntime = Effect.gen(function* () { | ... | @@ -24,7 +24,7 @@ const makeRuntime = Effect.gen(function* () { |
| 24 | const failNextStart = yield* Ref.make(false); | 24 | const failNextStart = yield* Ref.make(false); |
| 25 | const started = yield* Deferred.make<void>(); | 25 | const started = yield* Deferred.make<void>(); |
| 26 | const closed = yield* Deferred.make<void>(); | 26 | const closed = yield* Deferred.make<void>(); |
| 27 | const runtime: OpenCodeRuntime.OpenCodeRuntimeShape = { | 27 | const runtime: OpenCodeRuntime.OpenCodeRuntime["Service"] = { |
| 28 | startOpenCodeServerProcess: () => | 28 | startOpenCodeServerProcess: () => |
| 29 | Effect.gen(function* () { | 29 | Effect.gen(function* () { |
| 30 | if (yield* Ref.getAndSet(failNextStart, false)) { | 30 | if (yield* Ref.getAndSet(failNextStart, false)) { |
| ... | @@ -115,7 +115,7 @@ it.effect("invalidates an exited process so the next borrower starts a new one", | ... | @@ -115,7 +115,7 @@ it.effect("invalidates an exited process so the next borrower starts a new one", |
| 115 | const starts = yield* Ref.make(0); | 115 | const starts = yield* Ref.make(0); |
| 116 | const processExits: Array<Deferred.Deferred<number>> = []; | 116 | const processExits: Array<Deferred.Deferred<number>> = []; |
| 117 | const processClosed = yield* Deferred.make<void>(); | 117 | const processClosed = yield* Deferred.make<void>(); |
| 118 | const runtime: OpenCodeRuntime.OpenCodeRuntimeShape = { | 118 | const runtime: OpenCodeRuntime.OpenCodeRuntime["Service"] = { |
| 119 | startOpenCodeServerProcess: () => | 119 | startOpenCodeServerProcess: () => |
| 120 | Effect.gen(function* () { | 120 | Effect.gen(function* () { |
| 121 | const index = yield* Ref.updateAndGet(starts, (count) => count + 1); | 121 | const index = yield* Ref.updateAndGet(starts, (count) => count + 1); |
| ... | @@ -165,7 +165,7 @@ it.effect("replaces a dead cached process before its exit watcher runs", () => | ... | @@ -165,7 +165,7 @@ it.effect("replaces a dead cached process before its exit watcher runs", () => |
| 165 | const starts = yield* Ref.make(0); | 165 | const starts = yield* Ref.make(0); |
| 166 | const closes = yield* Ref.make(0); | 166 | const closes = yield* Ref.make(0); |
| 167 | const processRunning: Array<Ref.Ref<boolean>> = []; | 167 | const processRunning: Array<Ref.Ref<boolean>> = []; |
| 168 | const runtime: OpenCodeRuntime.OpenCodeRuntimeShape = { | 168 | const runtime: OpenCodeRuntime.OpenCodeRuntime["Service"] = { |
| 169 | startOpenCodeServerProcess: () => | 169 | startOpenCodeServerProcess: () => |
| 170 | Effect.gen(function* () { | 170 | Effect.gen(function* () { |
| 171 | const index = yield* Ref.updateAndGet(starts, (count) => count + 1); | 171 | const index = yield* Ref.updateAndGet(starts, (count) => count + 1); |
| ... | @@ -214,7 +214,7 @@ it.effect("cleans up an interrupted startup and allows a retry", () => | ... | @@ -214,7 +214,7 @@ it.effect("cleans up an interrupted startup and allows a retry", () => |
| 214 | const starts = yield* Ref.make(0); | 214 | const starts = yield* Ref.make(0); |
| 215 | const firstStartEntered = yield* Deferred.make<void>(); | 215 | const firstStartEntered = yield* Deferred.make<void>(); |
| 216 | const firstStartClosed = yield* Deferred.make<void>(); | 216 | const firstStartClosed = yield* Deferred.make<void>(); |
| 217 | const runtime: OpenCodeRuntime.OpenCodeRuntimeShape = { | 217 | const runtime: OpenCodeRuntime.OpenCodeRuntime["Service"] = { |
| 218 | startOpenCodeServerProcess: () => | 218 | startOpenCodeServerProcess: () => |
| 219 | Effect.gen(function* () { | 219 | Effect.gen(function* () { |
| 220 | const index = yield* Ref.updateAndGet(starts, (count) => count + 1); | 220 | const index = yield* Ref.updateAndGet(starts, (count) => count + 1); |
packages/provider-opencode/src/server/adapter.test.ts+6-6| ... | @@ -32,7 +32,7 @@ import * as Stream from "effect/Stream"; | ... | @@ -32,7 +32,7 @@ import * as Stream from "effect/Stream"; |
| 32 | import * as TestClock from "effect/testing/TestClock"; | 32 | import * as TestClock from "effect/testing/TestClock"; |
| 33 | 33 | ||
| 34 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | 34 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; |
| 35 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 35 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 36 | import type * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; | 36 | import type * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; |
| 37 | import * as OpenCodeRuntime from "./OpenCodeRuntime.ts"; | 37 | import * as OpenCodeRuntime from "./OpenCodeRuntime.ts"; |
| 38 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 38 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| ... | @@ -165,7 +165,7 @@ const makeOpenCodeRuntimeHarness = Effect.fn("makeOpenCodeRuntimeHarness")(funct | ... | @@ -165,7 +165,7 @@ const makeOpenCodeRuntimeHarness = Effect.fn("makeOpenCodeRuntimeHarness")(funct |
| 165 | Effect.provideService(OpenCodeRuntime.OpenCodeRuntime, { | 165 | Effect.provideService(OpenCodeRuntime.OpenCodeRuntime, { |
| 166 | connectToOpenCodeServer: () => Effect.succeed({ url: "http://test.invalid", external: true }), | 166 | connectToOpenCodeServer: () => Effect.succeed({ url: "http://test.invalid", external: true }), |
| 167 | createOpenCodeSdkClient: () => client, | 167 | createOpenCodeSdkClient: () => client, |
| 168 | } as unknown as OpenCodeRuntime.OpenCodeRuntimeShape), | 168 | } as unknown as OpenCodeRuntime.OpenCodeRuntime["Service"]), |
| 169 | Effect.provideService(ProviderHost.ProviderHost, { | 169 | Effect.provideService(ProviderHost.ProviderHost, { |
| 170 | paths: { cwd: "/workspace" }, | 170 | paths: { cwd: "/workspace" }, |
| 171 | resolveAttachmentPath: () => null, | 171 | resolveAttachmentPath: () => null, |
| ... | @@ -1538,7 +1538,7 @@ describe("OpenCodeAdapterV2", () => { | ... | @@ -1538,7 +1538,7 @@ describe("OpenCodeAdapterV2", () => { |
| 1538 | connectToOpenCodeServer: () => | 1538 | connectToOpenCodeServer: () => |
| 1539 | Effect.succeed({ url: "http://test.invalid", external: true }), | 1539 | Effect.succeed({ url: "http://test.invalid", external: true }), |
| 1540 | createOpenCodeSdkClient: () => client, | 1540 | createOpenCodeSdkClient: () => client, |
| 1541 | } as unknown as OpenCodeRuntime.OpenCodeRuntimeShape), | 1541 | } as unknown as OpenCodeRuntime.OpenCodeRuntime["Service"]), |
| 1542 | Effect.provideService(ProviderHost.ProviderHost, { | 1542 | Effect.provideService(ProviderHost.ProviderHost, { |
| 1543 | paths: { cwd: "/workspace" }, | 1543 | paths: { cwd: "/workspace" }, |
| 1544 | resolveAttachmentPath: () => null, | 1544 | resolveAttachmentPath: () => null, |
| ... | @@ -1835,7 +1835,7 @@ describe("OpenCodeAdapterV2", () => { | ... | @@ -1835,7 +1835,7 @@ describe("OpenCodeAdapterV2", () => { |
| 1835 | connectToOpenCodeServer: () => | 1835 | connectToOpenCodeServer: () => |
| 1836 | Effect.succeed({ url: "http://test.invalid", external: true }), | 1836 | Effect.succeed({ url: "http://test.invalid", external: true }), |
| 1837 | createOpenCodeSdkClient: () => client, | 1837 | createOpenCodeSdkClient: () => client, |
| 1838 | } as unknown as OpenCodeRuntime.OpenCodeRuntimeShape), | 1838 | } as unknown as OpenCodeRuntime.OpenCodeRuntime["Service"]), |
| 1839 | Effect.provideService(ProviderHost.ProviderHost, { | 1839 | Effect.provideService(ProviderHost.ProviderHost, { |
| 1840 | paths: { cwd: "/workspace" }, | 1840 | paths: { cwd: "/workspace" }, |
| 1841 | resolveAttachmentPath: () => null, | 1841 | resolveAttachmentPath: () => null, |
| ... | @@ -2507,7 +2507,7 @@ describe("OpenCodeAdapterV2", () => { | ... | @@ -2507,7 +2507,7 @@ describe("OpenCodeAdapterV2", () => { |
| 2507 | }, | 2507 | }, |
| 2508 | } as unknown as OpencodeClient; | 2508 | } as unknown as OpencodeClient; |
| 2509 | const unused = (operation: string) => () => Effect.die(`${operation} is not used`); | 2509 | const unused = (operation: string) => () => Effect.die(`${operation} is not used`); |
| 2510 | const runtime: OpenCodeRuntime.OpenCodeRuntimeShape = { | 2510 | const runtime: OpenCodeRuntime.OpenCodeRuntime["Service"] = { |
| 2511 | startOpenCodeServerProcess: unused("startOpenCodeServerProcess"), | 2511 | startOpenCodeServerProcess: unused("startOpenCodeServerProcess"), |
| 2512 | connectToOpenCodeServer: () => | 2512 | connectToOpenCodeServer: () => |
| 2513 | Effect.succeed({ | 2513 | Effect.succeed({ |
| ... | @@ -2585,7 +2585,7 @@ describe("OpenCodeAdapterV2", () => { | ... | @@ -2585,7 +2585,7 @@ describe("OpenCodeAdapterV2", () => { |
| 2585 | Layer.mergeAll( | 2585 | Layer.mergeAll( |
| 2586 | IdAllocator.layer, | 2586 | IdAllocator.layer, |
| 2587 | McpProviderSessions.layer, | 2587 | McpProviderSessions.layer, |
| 2588 | layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), | 2588 | TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)), |
| 2589 | ), | 2589 | ), |
| 2590 | ), | 2590 | ), |
| 2591 | ), | 2591 | ), |
packages/provider-opencode/src/server/adapter.ts+12-15| ... | @@ -48,6 +48,7 @@ import * as Layer from "effect/Layer"; | ... | @@ -48,6 +48,7 @@ import * as Layer from "effect/Layer"; |
| 48 | import * as Option from "effect/Option"; | 48 | import * as Option from "effect/Option"; |
| 49 | import * as Queue from "effect/Queue"; | 49 | import * as Queue from "effect/Queue"; |
| 50 | import * as Random from "effect/Random"; | 50 | import * as Random from "effect/Random"; |
| 51 | import * as Ref from "effect/Ref"; | ||
| 51 | import * as Schema from "effect/Schema"; | 52 | import * as Schema from "effect/Schema"; |
| 52 | import * as Semaphore from "effect/Semaphore"; | 53 | import * as Semaphore from "effect/Semaphore"; |
| 53 | import * as Scope from "effect/Scope"; | 54 | import * as Scope from "effect/Scope"; |
| ... | @@ -88,20 +89,15 @@ export const OPENCODE_DEFAULT_INSTANCE_ID = defaultInstanceIdForDriver(OPENCODE_ | ... | @@ -88,20 +89,15 @@ export const OPENCODE_DEFAULT_INSTANCE_ID = defaultInstanceIdForDriver(OPENCODE_ |
| 88 | export const OPENCODE_SDK_PROTOCOL = "opencode-sdk.sse" as const; | 89 | export const OPENCODE_SDK_PROTOCOL = "opencode-sdk.sse" as const; |
| 89 | const DEFAULT_OPENCODE_SETTINGS = Schema.decodeSync(OpenCodeSettings)({}); | 90 | const DEFAULT_OPENCODE_SETTINGS = Schema.decodeSync(OpenCodeSettings)({}); |
| 90 | 91 | ||
| 91 | let openCodeMessageIdEpochMillis = -1; | 92 | const makeOpenCodeMessageId = Effect.fnUntraced(function* ( |
| 92 | let openCodeMessageIdCounter = 0; | 93 | clock: Ref.Ref<{ readonly epochMillis: number; readonly counter: number }>, |
| 93 | 94 | ) { | |
| 94 | const makeOpenCodeMessageId = Effect.fnUntraced(function* () { | ||
| 95 | const epochMillis = DateTime.toEpochMillis(yield* DateTime.now); | 95 | const epochMillis = DateTime.toEpochMillis(yield* DateTime.now); |
| 96 | if (epochMillis !== openCodeMessageIdEpochMillis) { | 96 | const counter = yield* Ref.modify(clock, (previous) => { |
| 97 | openCodeMessageIdEpochMillis = epochMillis; | 97 | const next = previous.epochMillis === epochMillis ? previous.counter + 1 : 1; |
| 98 | openCodeMessageIdCounter = 0; | 98 | return [next, { epochMillis, counter: next }] as const; |
| 99 | } | 99 | }); |
| 100 | openCodeMessageIdCounter += 1; | 100 | const encodedTime = BigInt.asUintN(48, BigInt(epochMillis) * 0x1000n + BigInt(counter)) |
| 101 | const encodedTime = BigInt.asUintN( | ||
| 102 | 48, | ||
| 103 | BigInt(epochMillis) * 0x1000n + BigInt(openCodeMessageIdCounter), | ||
| 104 | ) | ||
| 105 | .toString(16) | 101 | .toString(16) |
| 106 | .padStart(12, "0"); | 102 | .padStart(12, "0"); |
| 107 | const alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | 103 | const alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; |
| ... | @@ -948,6 +944,7 @@ export const makeOpenCodeAdapterV2 = Effect.fn("makeOpenCodeAdapterV2")(function | ... | @@ -948,6 +944,7 @@ export const makeOpenCodeAdapterV2 = Effect.fn("makeOpenCodeAdapterV2")(function |
| 948 | const idAllocator = yield* IdAllocator.IdAllocatorV2; | 944 | const idAllocator = yield* IdAllocator.IdAllocatorV2; |
| 949 | const host = yield* ProviderHost.ProviderHost; | 945 | const host = yield* ProviderHost.ProviderHost; |
| 950 | const mcpSessions = yield* McpProviderSessions.McpProviderSessions; | 946 | const mcpSessions = yield* McpProviderSessions.McpProviderSessions; |
| 947 | const messageIdClock = yield* Ref.make({ epochMillis: -1, counter: 0 }); | ||
| 951 | 948 | ||
| 952 | return ProviderAdapter.ProviderAdapterV2.of({ | 949 | return ProviderAdapter.ProviderAdapterV2.of({ |
| 953 | instanceId: options.instanceId, | 950 | instanceId: options.instanceId, |
| ... | @@ -3170,7 +3167,7 @@ export const makeOpenCodeAdapterV2 = Effect.fn("makeOpenCodeAdapterV2")(function | ... | @@ -3170,7 +3167,7 @@ export const makeOpenCodeAdapterV2 = Effect.fn("makeOpenCodeAdapterV2")(function |
| 3170 | startedAt, | 3167 | startedAt, |
| 3171 | completedAt: null, | 3168 | completedAt: null, |
| 3172 | }; | 3169 | }; |
| 3173 | const admissionMessageId = yield* makeOpenCodeMessageId(); | 3170 | const admissionMessageId = yield* makeOpenCodeMessageId(messageIdClock); |
| 3174 | // No Effect may be yielded between this check and installing the | 3171 | // No Effect may be yielded between this check and installing the |
| 3175 | // turn. If the event stream ended while IDs were being prepared, | 3172 | // turn. If the event stream ended while IDs were being prepared, |
| 3176 | // registering afterward would leave a running turn that the EOF | 3173 | // registering afterward would leave a running turn that the EOF |
| ... | @@ -3369,7 +3366,7 @@ export const makeOpenCodeAdapterV2 = Effect.fn("makeOpenCodeAdapterV2")(function | ... | @@ -3369,7 +3366,7 @@ export const makeOpenCodeAdapterV2 = Effect.fn("makeOpenCodeAdapterV2")(function |
| 3369 | ...files, | 3366 | ...files, |
| 3370 | ]; | 3367 | ]; |
| 3371 | turn.admissionGeneration = state.nextAdmissionGeneration++; | 3368 | turn.admissionGeneration = state.nextAdmissionGeneration++; |
| 3372 | turn.admissionMessageId = yield* makeOpenCodeMessageId(); | 3369 | turn.admissionMessageId = yield* makeOpenCodeMessageId(messageIdClock); |
| 3373 | turn.admissionPending = true; | 3370 | turn.admissionPending = true; |
| 3374 | turn.admissionAccepted = false; | 3371 | turn.admissionAccepted = false; |
| 3375 | turn.admissionMessageObserved = false; | 3372 | turn.admissionMessageObserved = false; |
packages/provider-opencode/src/server/driver.test.ts+7-7| ... | @@ -12,8 +12,8 @@ import * as Effect from "effect/Effect"; | ... | @@ -12,8 +12,8 @@ import * as Effect from "effect/Effect"; |
| 12 | import * as Fiber from "effect/Fiber"; | 12 | import * as Fiber from "effect/Fiber"; |
| 13 | import * as Layer from "effect/Layer"; | 13 | import * as Layer from "effect/Layer"; |
| 14 | import * as TestClock from "effect/testing/TestClock"; | 14 | import * as TestClock from "effect/testing/TestClock"; |
| 15 | import { HttpClient } from "effect/http"; | 15 | import * as HttpClient from "effect/http/HttpClient"; |
| 16 | import { ChildProcessSpawner } from "effect/process"; | 16 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; |
| 17 | 17 | ||
| 18 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | 18 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; |
| 19 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 19 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| ... | @@ -27,7 +27,7 @@ import { | ... | @@ -27,7 +27,7 @@ import { |
| 27 | replayOpenCodeServer, | 27 | replayOpenCodeServer, |
| 28 | } from "./probeResponses.fixture.ts"; | 28 | } from "./probeResponses.fixture.ts"; |
| 29 | import { OpenCodeDriver, openCodeUpdateFor } from "./driver.ts"; | 29 | import { OpenCodeDriver, openCodeUpdateFor } from "./driver.ts"; |
| 30 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 30 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 31 | 31 | ||
| 32 | const serverStarts: Array<string> = []; | 32 | const serverStarts: Array<string> = []; |
| 33 | const reachedServer = (operation: string) => | 33 | const reachedServer = (operation: string) => |
| ... | @@ -46,13 +46,13 @@ const openCode2Runtime = { | ... | @@ -46,13 +46,13 @@ const openCode2Runtime = { |
| 46 | runOpenCodeCommand: () => Effect.succeed({ stdout: "opencode v2.0.18\n", stderr: "", code: 0 }), | 46 | runOpenCodeCommand: () => Effect.succeed({ stdout: "opencode v2.0.18\n", stderr: "", code: 0 }), |
| 47 | startOpenCodeServerProcess: () => reachedServer("start"), | 47 | startOpenCodeServerProcess: () => reachedServer("start"), |
| 48 | connectToOpenCodeServer: () => reachedServer("connect"), | 48 | connectToOpenCodeServer: () => reachedServer("connect"), |
| 49 | } as unknown as OpenCodeRuntime.OpenCodeRuntimeShape; | 49 | } as unknown as OpenCodeRuntime.OpenCodeRuntime["Service"]; |
| 50 | 50 | ||
| 51 | const layer = Layer.mergeAll( | 51 | const layer = Layer.mergeAll( |
| 52 | IdAllocator.layer, | 52 | IdAllocator.layer, |
| 53 | McpProviderSessions.layer, | 53 | McpProviderSessions.layer, |
| 54 | ProviderLatestVersions.layer, | 54 | ProviderLatestVersions.layer, |
| 55 | layerTestProviderHost(), | 55 | TestProviderHost.layer(), |
| 56 | Layer.succeed( | 56 | Layer.succeed( |
| 57 | ProviderEventLoggers.ProviderEventLoggers, | 57 | ProviderEventLoggers.ProviderEventLoggers, |
| 58 | ProviderEventLoggers.NoOpProviderEventLoggers, | 58 | ProviderEventLoggers.NoOpProviderEventLoggers, |
| ... | @@ -211,12 +211,12 @@ const changingRuntime = { | ... | @@ -211,12 +211,12 @@ const changingRuntime = { |
| 211 | ), | 211 | ), |
| 212 | startOpenCodeServerProcess: () => reachedServer("start"), | 212 | startOpenCodeServerProcess: () => reachedServer("start"), |
| 213 | connectToOpenCodeServer: () => reachedServer("connect"), | 213 | connectToOpenCodeServer: () => reachedServer("connect"), |
| 214 | } as unknown as OpenCodeRuntime.OpenCodeRuntimeShape; | 214 | } as unknown as OpenCodeRuntime.OpenCodeRuntime["Service"]; |
| 215 | const layerUpdate = Layer.mergeAll( | 215 | const layerUpdate = Layer.mergeAll( |
| 216 | IdAllocator.layer, | 216 | IdAllocator.layer, |
| 217 | McpProviderSessions.layer, | 217 | McpProviderSessions.layer, |
| 218 | ProviderLatestVersions.layer, | 218 | ProviderLatestVersions.layer, |
| 219 | layerTestProviderHost(), | 219 | TestProviderHost.layer(), |
| 220 | Layer.succeed( | 220 | Layer.succeed( |
| 221 | ProviderEventLoggers.ProviderEventLoggers, | 221 | ProviderEventLoggers.ProviderEventLoggers, |
| 222 | ProviderEventLoggers.NoOpProviderEventLoggers, | 222 | ProviderEventLoggers.NoOpProviderEventLoggers, |
packages/provider-opencode/src/server/driver.ts+2-2| ... | @@ -22,8 +22,8 @@ import * as FileSystem from "effect/FileSystem"; | ... | @@ -22,8 +22,8 @@ import * as FileSystem from "effect/FileSystem"; |
| 22 | import * as Path from "effect/Path"; | 22 | import * as Path from "effect/Path"; |
| 23 | import * as Schema from "effect/Schema"; | 23 | import * as Schema from "effect/Schema"; |
| 24 | import * as Stream from "effect/Stream"; | 24 | import * as Stream from "effect/Stream"; |
| 25 | import { HttpClient } from "effect/http"; | 25 | import * as HttpClient from "effect/http/HttpClient"; |
| 26 | import { ChildProcessSpawner } from "effect/process"; | 26 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; |
| 27 | 27 | ||
| 28 | import * as OpenCode2TextGeneration from "./v2/textGeneration.ts"; | 28 | import * as OpenCode2TextGeneration from "./v2/textGeneration.ts"; |
| 29 | import { makeOpenCodeTextGeneration } from "./textGeneration.ts"; | 29 | import { makeOpenCodeTextGeneration } from "./textGeneration.ts"; |
packages/provider-opencode/src/server/probeResponses.fixture.ts+2-1| ... | @@ -3,7 +3,8 @@ | ... | @@ -3,7 +3,8 @@ |
| 3 | * `HttpClient` so the version probe runs against real bytes. | 3 | * `HttpClient` so the version probe runs against real bytes. |
| 4 | */ | 4 | */ |
| 5 | import * as Effect from "effect/Effect"; | 5 | import * as Effect from "effect/Effect"; |
| 6 | import { HttpClient, HttpClientResponse } from "effect/http"; | 6 | import * as HttpClient from "effect/http/HttpClient"; |
| 7 | import * as HttpClientResponse from "effect/http/HttpClientResponse"; | ||
| 7 | 8 | ||
| 8 | interface RecordedResponse { | 9 | interface RecordedResponse { |
| 9 | readonly status: number; | 10 | readonly status: number; |
packages/provider-opencode/src/server/status.test.ts+5-4| ... | @@ -9,7 +9,8 @@ import * as FileSystem from "effect/FileSystem"; | ... | @@ -9,7 +9,8 @@ import * as FileSystem from "effect/FileSystem"; |
| 9 | import * as Layer from "effect/Layer"; | 9 | import * as Layer from "effect/Layer"; |
| 10 | import * as Schema from "effect/Schema"; | 10 | import * as Schema from "effect/Schema"; |
| 11 | import * as TestClock from "effect/testing/TestClock"; | 11 | import * as TestClock from "effect/testing/TestClock"; |
| 12 | import { HttpClient, HttpClientResponse } from "effect/http"; | 12 | import * as HttpClient from "effect/http/HttpClient"; |
| 13 | import * as HttpClientResponse from "effect/http/HttpClientResponse"; | ||
| 13 | import { beforeEach } from "vite-plus/test"; | 14 | import { beforeEach } from "vite-plus/test"; |
| 14 | 15 | ||
| 15 | import { OpenCodeSettings } from "../settings.ts"; | 16 | import { OpenCodeSettings } from "../settings.ts"; |
| ... | @@ -161,7 +162,7 @@ it.effect("keeps Go entitlement absence distinct from failed or malformed usage | ... | @@ -161,7 +162,7 @@ it.effect("keeps Go entitlement absence distinct from failed or malformed usage |
| 161 | * are deleted. The snapshot-producing logic they wrapped now lives in the | 162 | * are deleted. The snapshot-producing logic they wrapped now lives in the |
| 162 | * standalone `checkOpenCodeProviderStatus(settings, cwd)` Effect, which | 163 | * standalone `checkOpenCodeProviderStatus(settings, cwd)` Effect, which |
| 163 | * drivers call directly when building their per-instance snapshot | 164 | * drivers call directly when building their per-instance snapshot |
| 164 | * `ServerProviderShape`. Tests mirror that shape: build a settings payload, | 165 | * `ManagedServerProvider`. Tests mirror that shape: build a settings payload, |
| 165 | * invoke the check, assert on the returned snapshot. | 166 | * invoke the check, assert on the returned snapshot. |
| 166 | */ | 167 | */ |
| 167 | 168 | ||
| ... | @@ -202,7 +203,7 @@ const runtimeMock = { | ... | @@ -202,7 +203,7 @@ const runtimeMock = { |
| 202 | }, | 203 | }, |
| 203 | }; | 204 | }; |
| 204 | 205 | ||
| 205 | const OpenCodeRuntimeTestDouble: OpenCodeRuntime.OpenCodeRuntimeShape = { | 206 | const OpenCodeRuntimeTestDouble: OpenCodeRuntime.OpenCodeRuntime["Service"] = { |
| 206 | startOpenCodeServerProcess: ({ serverPassword, environment }) => | 207 | startOpenCodeServerProcess: ({ serverPassword, environment }) => |
| 207 | Effect.gen(function* () { | 208 | Effect.gen(function* () { |
| 208 | yield* Effect.addFinalizer(() => | 209 | yield* Effect.addFinalizer(() => |
| ... | @@ -264,7 +265,7 @@ const OpenCodeRuntimeTestDouble: OpenCodeRuntime.OpenCodeRuntimeShape = { | ... | @@ -264,7 +265,7 @@ const OpenCodeRuntimeTestDouble: OpenCodeRuntime.OpenCodeRuntimeShape = { |
| 264 | createOpenCodeSdkClient: (input) => { | 265 | createOpenCodeSdkClient: (input) => { |
| 265 | runtimeMock.state.sdkClientInputs.push(input); | 266 | runtimeMock.state.sdkClientInputs.push(input); |
| 266 | return {} as unknown as ReturnType< | 267 | return {} as unknown as ReturnType< |
| 267 | OpenCodeRuntime.OpenCodeRuntimeShape["createOpenCodeSdkClient"] | 268 | OpenCodeRuntime.OpenCodeRuntime["Service"]["createOpenCodeSdkClient"] |
| 268 | >; | 269 | >; |
| 269 | }, | 270 | }, |
| 270 | loadOpenCodeInventory: () => | 271 | loadOpenCodeInventory: () => |
packages/provider-opencode/src/server/textGeneration.test.ts+7-5| ... | @@ -10,7 +10,7 @@ import * as TestClock from "effect/testing/TestClock"; | ... | @@ -10,7 +10,7 @@ import * as TestClock from "effect/testing/TestClock"; |
| 10 | import * as NetService from "@t3tools/shared/Net"; | 10 | import * as NetService from "@t3tools/shared/Net"; |
| 11 | import { beforeEach, expect } from "vite-plus/test"; | 11 | import { beforeEach, expect } from "vite-plus/test"; |
| 12 | 12 | ||
| 13 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 13 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 14 | import * as OpenCodeRuntime from "./OpenCodeRuntime.ts"; | 14 | import * as OpenCodeRuntime from "./OpenCodeRuntime.ts"; |
| 15 | import * as OpenCodeServerOwner from "./OpenCodeServerOwner.ts"; | 15 | import * as OpenCodeServerOwner from "./OpenCodeServerOwner.ts"; |
| 16 | import * as OpenCodeTextGeneration from "./textGeneration.ts"; | 16 | import * as OpenCodeTextGeneration from "./textGeneration.ts"; |
| ... | @@ -47,7 +47,7 @@ const runtimeMock = { | ... | @@ -47,7 +47,7 @@ const runtimeMock = { |
| 47 | }, | 47 | }, |
| 48 | }; | 48 | }; |
| 49 | 49 | ||
| 50 | const OpenCodeRuntimeTestDouble: OpenCodeRuntime.OpenCodeRuntimeShape = { | 50 | const OpenCodeRuntimeTestDouble: OpenCodeRuntime.OpenCodeRuntime["Service"] = { |
| 51 | startOpenCodeServerProcess: ({ binaryPath, serverPassword, environment }) => | 51 | startOpenCodeServerProcess: ({ binaryPath, serverPassword, environment }) => |
| 52 | Effect.gen(function* () { | 52 | Effect.gen(function* () { |
| 53 | const index = runtimeMock.state.startCalls.length + 1; | 53 | const index = runtimeMock.state.startCalls.length + 1; |
| ... | @@ -128,7 +128,9 @@ const OpenCodeRuntimeTestDouble: OpenCodeRuntime.OpenCodeRuntimeShape = { | ... | @@ -128,7 +128,9 @@ const OpenCodeRuntimeTestDouble: OpenCodeRuntime.OpenCodeRuntimeShape = { |
| 128 | ); | 128 | ); |
| 129 | }, | 129 | }, |
| 130 | }, | 130 | }, |
| 131 | }) as unknown as ReturnType<OpenCodeRuntime.OpenCodeRuntimeShape["createOpenCodeSdkClient"]>, | 131 | }) as unknown as ReturnType< |
| 132 | OpenCodeRuntime.OpenCodeRuntime["Service"]["createOpenCodeSdkClient"] | ||
| 133 | >, | ||
| 132 | loadOpenCodeInventory: () => | 134 | loadOpenCodeInventory: () => |
| 133 | Effect.fail( | 135 | Effect.fail( |
| 134 | new OpenCodeRuntime.OpenCodeRuntimeError({ | 136 | new OpenCodeRuntime.OpenCodeRuntimeError({ |
| ... | @@ -167,7 +169,7 @@ const layerOpenCodeTextGenerationTest = Layer.succeed( | ... | @@ -167,7 +169,7 @@ const layerOpenCodeTextGenerationTest = Layer.succeed( |
| 167 | OpenCodeRuntime.OpenCodeRuntime, | 169 | OpenCodeRuntime.OpenCodeRuntime, |
| 168 | OpenCodeRuntimeTestDouble, | 170 | OpenCodeRuntimeTestDouble, |
| 169 | ).pipe( | 171 | ).pipe( |
| 170 | Layer.provideMerge(layerTestProviderHost()), | 172 | Layer.provideMerge(TestProviderHost.layer()), |
| 171 | Layer.provideMerge(NetService.layer), | 173 | Layer.provideMerge(NetService.layer), |
| 172 | Layer.provideMerge(NodeServices.layer), | 174 | Layer.provideMerge(NodeServices.layer), |
| 173 | ); | 175 | ); |
| ... | @@ -176,7 +178,7 @@ const layerOpenCodeTextGenerationExistingServerTest = Layer.succeed( | ... | @@ -176,7 +178,7 @@ const layerOpenCodeTextGenerationExistingServerTest = Layer.succeed( |
| 176 | OpenCodeRuntime.OpenCodeRuntime, | 178 | OpenCodeRuntime.OpenCodeRuntime, |
| 177 | OpenCodeRuntimeTestDouble, | 179 | OpenCodeRuntimeTestDouble, |
| 178 | ).pipe( | 180 | ).pipe( |
| 179 | Layer.provideMerge(layerTestProviderHost()), | 181 | Layer.provideMerge(TestProviderHost.layer()), |
| 180 | Layer.provideMerge(NetService.layer), | 182 | Layer.provideMerge(NetService.layer), |
| 181 | Layer.provideMerge(NodeServices.layer), | 183 | Layer.provideMerge(NodeServices.layer), |
| 182 | ); | 184 | ); |
packages/provider-opencode/src/server/usageLimits.ts+3-1| ... | @@ -9,7 +9,9 @@ import * as Option from "effect/Option"; | ... | @@ -9,7 +9,9 @@ import * as Option from "effect/Option"; |
| 9 | import * as Path from "effect/Path"; | 9 | import * as Path from "effect/Path"; |
| 10 | import * as Schema from "effect/Schema"; | 10 | import * as Schema from "effect/Schema"; |
| 11 | import * as Hex from "effect/encoding/Hex"; | 11 | import * as Hex from "effect/encoding/Hex"; |
| 12 | import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/http"; | 12 | import * as HttpClient from "effect/http/HttpClient"; |
| 13 | import * as HttpClientRequest from "effect/http/HttpClientRequest"; | ||
| 14 | import * as HttpClientResponse from "effect/http/HttpClientResponse"; | ||
| 13 | 15 | ||
| 14 | import { | 16 | import { |
| 15 | clampPercent, | 17 | clampPercent, |
packages/provider-opencode/src/server/v2/OpenCode2Client.live.test.ts+3-2| ... | @@ -20,8 +20,9 @@ import * as Layer from "effect/Layer"; | ... | @@ -20,8 +20,9 @@ import * as Layer from "effect/Layer"; |
| 20 | import * as Option from "effect/Option"; | 20 | import * as Option from "effect/Option"; |
| 21 | import * as Path from "effect/Path"; | 21 | import * as Path from "effect/Path"; |
| 22 | import * as Stream from "effect/Stream"; | 22 | import * as Stream from "effect/Stream"; |
| 23 | import { FetchHttpClient } from "effect/http"; | 23 | import * as FetchHttpClient from "effect/http/FetchHttpClient"; |
| 24 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 24 | import * as ChildProcess from "effect/process/ChildProcess"; |
| 25 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ||
| 25 | import { describe } from "vite-plus/test"; | 26 | import { describe } from "vite-plus/test"; |
| 26 | 27 | ||
| 27 | import * as OpenCode2Client from "./OpenCode2Client.ts"; | 28 | import * as OpenCode2Client from "./OpenCode2Client.ts"; |
packages/provider-opencode/src/server/v2/OpenCode2Client.test.ts+2-1| ... | @@ -2,7 +2,8 @@ import { assert, it } from "@effect/vitest"; | ... | @@ -2,7 +2,8 @@ import { assert, it } from "@effect/vitest"; |
| 2 | import * as Effect from "effect/Effect"; | 2 | import * as Effect from "effect/Effect"; |
| 3 | import * as Layer from "effect/Layer"; | 3 | import * as Layer from "effect/Layer"; |
| 4 | import * as Redacted from "effect/Redacted"; | 4 | import * as Redacted from "effect/Redacted"; |
| 5 | import { HttpClient, HttpClientResponse } from "effect/http"; | 5 | import * as HttpClient from "effect/http/HttpClient"; |
| 6 | import * as HttpClientResponse from "effect/http/HttpClientResponse"; | ||
| 6 | import { describe } from "vite-plus/test"; | 7 | import { describe } from "vite-plus/test"; |
| 7 | 8 | ||
| 8 | import * as OpenCode2Client from "./OpenCode2Client.ts"; | 9 | import * as OpenCode2Client from "./OpenCode2Client.ts"; |
packages/provider-opencode/src/server/v2/OpenCode2Client.ts+25-21| ... | @@ -139,26 +139,27 @@ const undecodable = (data: string) => | ... | @@ -139,26 +139,27 @@ const undecodable = (data: string) => |
| 139 | }); | 139 | }); |
| 140 | 140 | ||
| 141 | /** Subscribes to `/api/event`, then streams every frame this build can route. */ | 141 | /** Subscribes to `/api/event`, then streams every frame this build can route. */ |
| 142 | const readEvents = (httpClient: HttpClient.HttpClient) => | 142 | const readEvents = HttpClient.get("/api/event", { |
| 143 | httpClient.get("/api/event", { headers: { accept: "text/event-stream" } }).pipe( | 143 | headers: { accept: "text/event-stream" }, |
| 144 | Effect.flatMap(HttpClientResponse.filterStatusOk), | 144 | }).pipe( |
| 145 | Effect.map((response) => | 145 | Effect.flatMap(HttpClientResponse.filterStatusOk), |
| 146 | response.stream.pipe( | 146 | Effect.map((response) => |
| 147 | Stream.timeoutOrElse({ | 147 | response.stream.pipe( |
| 148 | duration: SILENT_STREAM_TIMEOUT, | 148 | Stream.timeoutOrElse({ |
| 149 | orElse: () => Stream.fail(new OpenCode2SilentStreamError()), | 149 | duration: SILENT_STREAM_TIMEOUT, |
| 150 | }), | 150 | orElse: () => Stream.fail(new OpenCode2SilentStreamError()), |
| 151 | Stream.decodeText, | 151 | }), |
| 152 | Stream.pipeThroughChannel(Sse.decode()), | 152 | Stream.decodeText, |
| 153 | Stream.filterMapEffect((frame) => { | 153 | Stream.pipeThroughChannel(Sse.decode()), |
| 154 | const decoded = decodeEvent(frame.data); | 154 | Stream.filterMapEffect((frame) => { |
| 155 | return Result.isSuccess(decoded) | 155 | const decoded = decodeEvent(frame.data); |
| 156 | ? Effect.succeed(Result.succeed<OpenCode2StreamEvent>(decoded.success)) | 156 | return Result.isSuccess(decoded) |
| 157 | : undecodable(frame.data); | 157 | ? Effect.succeed(Result.succeed<OpenCode2StreamEvent>(decoded.success)) |
| 158 | }), | 158 | : undecodable(frame.data); |
| 159 | ), | 159 | }), |
| 160 | ), | 160 | ), |
| 161 | ); | 161 | ), |
| 162 | ); | ||
| 162 | 163 | ||
| 163 | /** | 164 | /** |
| 164 | * OpenCode decodes Basic credentials as UTF-8. `HttpClientRequest.basicAuth` | 165 | * OpenCode decodes Basic credentials as UTF-8. `HttpClientRequest.basicAuth` |
| ... | @@ -182,8 +183,11 @@ export const make = Effect.gen(function* () { | ... | @@ -182,8 +183,11 @@ export const make = Effect.gen(function* () { |
| 182 | Effect.provideService(HttpClient.HttpClient, authenticated), | 183 | Effect.provideService(HttpClient.HttpClient, authenticated), |
| 183 | Effect.map((client) => ({ | 184 | Effect.map((client) => ({ |
| 184 | client, | 185 | client, |
| 185 | events: readEvents( | 186 | events: readEvents.pipe( |
| 186 | HttpClient.mapRequest(authenticated, HttpClientRequest.prependUrl(baseUrl)), | 187 | Effect.provideService( |
| 188 | HttpClient.HttpClient, | ||
| 189 | HttpClient.mapRequest(authenticated, HttpClientRequest.prependUrl(baseUrl)), | ||
| 190 | ), | ||
| 187 | ), | 191 | ), |
| 188 | })), | 192 | })), |
| 189 | ); | 193 | ); |
packages/provider-opencode/src/server/v2/OpenCode2Server.live.test.ts+3-2| ... | @@ -19,8 +19,9 @@ import * as Path from "effect/Path"; | ... | @@ -19,8 +19,9 @@ import * as Path from "effect/Path"; |
| 19 | import * as Redacted from "effect/Redacted"; | 19 | import * as Redacted from "effect/Redacted"; |
| 20 | import * as Scope from "effect/Scope"; | 20 | import * as Scope from "effect/Scope"; |
| 21 | import * as Stream from "effect/Stream"; | 21 | import * as Stream from "effect/Stream"; |
| 22 | import { FetchHttpClient } from "effect/http"; | 22 | import * as FetchHttpClient from "effect/http/FetchHttpClient"; |
| 23 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 23 | import * as ChildProcess from "effect/process/ChildProcess"; |
| 24 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ||
| 24 | import { describe } from "vite-plus/test"; | 25 | import { describe } from "vite-plus/test"; |
| 25 | 26 | ||
| 26 | import * as OpenCodeRuntime from "../OpenCodeRuntime.ts"; | 27 | import * as OpenCodeRuntime from "../OpenCodeRuntime.ts"; |
packages/provider-opencode/src/server/v2/OpenCode2Server.test.ts+3-1| ... | @@ -12,7 +12,9 @@ import * as Layer from "effect/Layer"; | ... | @@ -12,7 +12,9 @@ import * as Layer from "effect/Layer"; |
| 12 | import * as Path from "effect/Path"; | 12 | import * as Path from "effect/Path"; |
| 13 | import * as Redacted from "effect/Redacted"; | 13 | import * as Redacted from "effect/Redacted"; |
| 14 | import * as TestClock from "effect/testing/TestClock"; | 14 | import * as TestClock from "effect/testing/TestClock"; |
| 15 | import { FetchHttpClient, HttpClient, HttpClientResponse } from "effect/http"; | 15 | import * as FetchHttpClient from "effect/http/FetchHttpClient"; |
| 16 | import * as HttpClient from "effect/http/HttpClient"; | ||
| 17 | import * as HttpClientResponse from "effect/http/HttpClientResponse"; | ||
| 16 | import { describe } from "vite-plus/test"; | 18 | import { describe } from "vite-plus/test"; |
| 17 | 19 | ||
| 18 | import * as OpenCodeRuntime from "../OpenCodeRuntime.ts"; | 20 | import * as OpenCodeRuntime from "../OpenCodeRuntime.ts"; |
packages/provider-opencode/src/server/v2/textGeneration.ts+4-3| ... | @@ -40,9 +40,9 @@ type Outcome = | ... | @@ -40,9 +40,9 @@ type Outcome = |
| 40 | const runOnServer = ( | 40 | const runOnServer = ( |
| 41 | connection: OpenCode2Server.OpenCode2Connection, | 41 | connection: OpenCode2Server.OpenCode2Connection, |
| 42 | input: TextGenerationOperations.Request<Schema.Top>, | 42 | input: TextGenerationOperations.Request<Schema.Top>, |
| 43 | resolveAttachmentPath: ProviderHost.ProviderHost["Service"]["resolveAttachmentPath"], | ||
| 44 | ) => | 43 | ) => |
| 45 | Effect.gen(function* () { | 44 | Effect.gen(function* () { |
| 45 | const { resolveAttachmentPath } = yield* ProviderHost.ProviderHost; | ||
| 46 | const { client } = connection; | 46 | const { client } = connection; |
| 47 | const parsed = OpenCodeRuntime.parseOpenCodeModelSlug(input.modelSelection.model); | 47 | const parsed = OpenCodeRuntime.parseOpenCodeModelSlug(input.modelSelection.model); |
| 48 | if (parsed === null) { | 48 | if (parsed === null) { |
| ... | @@ -184,11 +184,12 @@ const runOnServer = ( | ... | @@ -184,11 +184,12 @@ const runOnServer = ( |
| 184 | /** Text generation for an instance whose server is OpenCode 2. */ | 184 | /** Text generation for an instance whose server is OpenCode 2. */ |
| 185 | export const make = Effect.fn("OpenCode2TextGeneration.make")(function* () { | 185 | export const make = Effect.fn("OpenCode2TextGeneration.make")(function* () { |
| 186 | const server = yield* OpenCode2Server.OpenCode2Server; | 186 | const server = yield* OpenCode2Server.OpenCode2Server; |
| 187 | const { resolveAttachmentPath } = yield* ProviderHost.ProviderHost; | 187 | const host = yield* ProviderHost.ProviderHost; |
| 188 | const run: TextGenerationOperations.Runner = (input) => | 188 | const run: TextGenerationOperations.Runner = (input) => |
| 189 | server | 189 | server |
| 190 | .withConnection((connection) => runOnServer(connection, input, resolveAttachmentPath)) | 190 | .withConnection((connection) => runOnServer(connection, input)) |
| 191 | .pipe( | 191 | .pipe( |
| 192 | Effect.provideService(ProviderHost.ProviderHost, host), | ||
| 192 | Effect.mapError((cause) => | 193 | Effect.mapError((cause) => |
| 193 | isTextGenerationError(cause) | 194 | isTextGenerationError(cause) |
| 194 | ? cause | 195 | ? cause |
packages/provider-opencode/src/server/versionProbe.test.ts+5-3| ... | @@ -1,6 +1,8 @@ | ... | @@ -1,6 +1,8 @@ |
| 1 | import { assert, describe, it } from "@effect/vitest"; | 1 | import { assert, describe, it } from "@effect/vitest"; |
| 2 | import * as Effect from "effect/Effect"; | 2 | import * as Effect from "effect/Effect"; |
| 3 | import { HttpClient, HttpClientError, HttpClientRequest } from "effect/http"; | 3 | import * as HttpClient from "effect/http/HttpClient"; |
| 4 | import * as HttpClientError from "effect/http/HttpClientError"; | ||
| 5 | import * as HttpClientRequest from "effect/http/HttpClientRequest"; | ||
| 4 | 6 | ||
| 5 | import * as OpenCodeRuntime from "./OpenCodeRuntime.ts"; | 7 | import * as OpenCodeRuntime from "./OpenCodeRuntime.ts"; |
| 6 | import { | 8 | import { |
| ... | @@ -16,7 +18,7 @@ import { | ... | @@ -16,7 +18,7 @@ import { |
| 16 | 18 | ||
| 17 | const noBinary = { | 19 | const noBinary = { |
| 18 | runOpenCodeCommand: () => Effect.die("A configured server must not run the local binary"), | 20 | runOpenCodeCommand: () => Effect.die("A configured server must not run the local binary"), |
| 19 | } as unknown as OpenCodeRuntime.OpenCodeRuntimeShape; | 21 | } as unknown as OpenCodeRuntime.OpenCodeRuntime["Service"]; |
| 20 | 22 | ||
| 21 | const probeServer = (serverUrl: string, serverPassword: string, http: HttpClient.HttpClient) => | 23 | const probeServer = (serverUrl: string, serverPassword: string, http: HttpClient.HttpClient) => |
| 22 | probeOpenCodeRuntime({ binaryPath: "opencode", serverUrl, serverPassword }).pipe( | 24 | probeOpenCodeRuntime({ binaryPath: "opencode", serverUrl, serverPassword }).pipe( |
| ... | @@ -172,7 +174,7 @@ describe("OpenCode version probe", () => { | ... | @@ -172,7 +174,7 @@ describe("OpenCode version probe", () => { |
| 172 | new OpenCodeRuntime.OpenCodeRuntimeError({ operation: "spawn", detail: "ENOENT" }), | 174 | new OpenCodeRuntime.OpenCodeRuntimeError({ operation: "spawn", detail: "ENOENT" }), |
| 173 | ); | 175 | ); |
| 174 | }, | 176 | }, |
| 175 | } as unknown as OpenCodeRuntime.OpenCodeRuntimeShape; | 177 | } as unknown as OpenCodeRuntime.OpenCodeRuntime["Service"]; |
| 176 | const probe = yield* makeOpenCodeRuntimeProbe( | 178 | const probe = yield* makeOpenCodeRuntimeProbe( |
| 177 | probeOpenCodeRuntime({ binaryPath: "opencode", serverUrl: "", serverPassword: "" }).pipe( | 179 | probeOpenCodeRuntime({ binaryPath: "opencode", serverUrl: "", serverPassword: "" }).pipe( |
| 178 | Effect.provideService(OpenCodeRuntime.OpenCodeRuntime, runtime), | 180 | Effect.provideService(OpenCodeRuntime.OpenCodeRuntime, runtime), |
packages/provider-opencode/src/server/versionProbe.ts+2-1| ... | @@ -6,7 +6,8 @@ import * as Effect from "effect/Effect"; | ... | @@ -6,7 +6,8 @@ import * as Effect from "effect/Effect"; |
| 6 | import * as Exit from "effect/Exit"; | 6 | import * as Exit from "effect/Exit"; |
| 7 | import * as Option from "effect/Option"; | 7 | import * as Option from "effect/Option"; |
| 8 | import * as Schema from "effect/Schema"; | 8 | import * as Schema from "effect/Schema"; |
| 9 | import { HttpClient, HttpClientRequest } from "effect/http"; | 9 | import * as HttpClient from "effect/http/HttpClient"; |
| 10 | import * as HttpClientRequest from "effect/http/HttpClientRequest"; | ||
| 10 | 11 | ||
| 11 | import * as OpenCodeRuntime from "./OpenCodeRuntime.ts"; | 12 | import * as OpenCodeRuntime from "./OpenCodeRuntime.ts"; |
| 12 | import { parseGenericCliVersion } from "@t3tools/provider-core/server/snapshotProbe"; | 13 | import { parseGenericCliVersion } from "@t3tools/provider-core/server/snapshotProbe"; |
packages/provider-pi/src/server/adapter.test.ts+4-3| ... | @@ -29,9 +29,10 @@ import * as Schema from "effect/Schema"; | ... | @@ -29,9 +29,10 @@ import * as Schema from "effect/Schema"; |
| 29 | import * as Sink from "effect/Sink"; | 29 | import * as Sink from "effect/Sink"; |
| 30 | import * as Stream from "effect/Stream"; | 30 | import * as Stream from "effect/Stream"; |
| 31 | import * as TestClock from "effect/testing/TestClock"; | 31 | import * as TestClock from "effect/testing/TestClock"; |
| 32 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 32 | import * as ChildProcess from "effect/process/ChildProcess"; |
| 33 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ||
| 33 | 34 | ||
| 34 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 35 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 35 | import * as ProviderContinuationRequests from "@t3tools/provider-core/server/ProviderContinuationRequests"; | 36 | import * as ProviderContinuationRequests from "@t3tools/provider-core/server/ProviderContinuationRequests"; |
| 36 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; | 37 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; |
| 37 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 38 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| ... | @@ -50,7 +51,7 @@ const layerTest = Layer.mergeAll( | ... | @@ -50,7 +51,7 @@ const layerTest = Layer.mergeAll( |
| 50 | NodeServices.layer, | 51 | NodeServices.layer, |
| 51 | IdAllocator.layer, | 52 | IdAllocator.layer, |
| 52 | McpProviderSessions.layer, | 53 | McpProviderSessions.layer, |
| 53 | layerTestProviderHost().pipe(Layer.provide(NodeServices.layer)), | 54 | TestProviderHost.layer().pipe(Layer.provide(NodeServices.layer)), |
| 54 | ); | 55 | ); |
| 55 | 56 | ||
| 56 | const decodeJsonLine = Schema.decodeSync(Schema.fromJsonString(Schema.Unknown)); | 57 | const decodeJsonLine = Schema.decodeSync(Schema.fromJsonString(Schema.Unknown)); |
packages/provider-pi/src/server/adapter.ts+1-1| ... | @@ -58,7 +58,7 @@ import * as Queue from "effect/Queue"; | ... | @@ -58,7 +58,7 @@ import * as Queue from "effect/Queue"; |
| 58 | import * as Schema from "effect/Schema"; | 58 | import * as Schema from "effect/Schema"; |
| 59 | import * as Semaphore from "effect/Semaphore"; | 59 | import * as Semaphore from "effect/Semaphore"; |
| 60 | import * as Stream from "effect/Stream"; | 60 | import * as Stream from "effect/Stream"; |
| 61 | import { ChildProcessSpawner } from "effect/process"; | 61 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; |
| 62 | 62 | ||
| 63 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | 63 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; |
| 64 | import { mcpToolPresentation } from "@t3tools/provider-core/server/mcpToolPresentation"; | 64 | import { mcpToolPresentation } from "@t3tools/provider-core/server/mcpToolPresentation"; |
packages/provider-pi/src/server/driver.test.ts+5-4| ... | @@ -10,18 +10,19 @@ import * as Schema from "effect/Schema"; | ... | @@ -10,18 +10,19 @@ import * as Schema from "effect/Schema"; |
| 10 | import * as Sink from "effect/Sink"; | 10 | import * as Sink from "effect/Sink"; |
| 11 | import * as Stream from "effect/Stream"; | 11 | import * as Stream from "effect/Stream"; |
| 12 | import * as TestClock from "effect/testing/TestClock"; | 12 | import * as TestClock from "effect/testing/TestClock"; |
| 13 | import { HttpClient } from "effect/http"; | 13 | import * as HttpClient from "effect/http/HttpClient"; |
| 14 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 14 | import * as ChildProcess from "effect/process/ChildProcess"; |
| 15 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ||
| 15 | 16 | ||
| 16 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | 17 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; |
| 17 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 18 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| 18 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; | 19 | import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; |
| 19 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 20 | import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost"; |
| 20 | import type { PiSettings } from "../settings.ts"; | 21 | import type { PiSettings } from "../settings.ts"; |
| 21 | import { PiDriver } from "./driver.ts"; | 22 | import { PiDriver } from "./driver.ts"; |
| 22 | 23 | ||
| 23 | const layerTest = Layer.mergeAll( | 24 | const layerTest = Layer.mergeAll( |
| 24 | layerTestProviderHost({ | 25 | TestProviderHost.layer({ |
| 25 | cwd: "/machine", | 26 | cwd: "/machine", |
| 26 | settings: { ...DEFAULT_SERVER_SETTINGS, enableProviderUpdateChecks: false }, | 27 | settings: { ...DEFAULT_SERVER_SETTINGS, enableProviderUpdateChecks: false }, |
| 27 | runBackgroundWork: false, | 28 | runBackgroundWork: false, |
packages/provider-pi/src/server/driver.ts+2-2| ... | @@ -12,8 +12,8 @@ import * as Effect from "effect/Effect"; | ... | @@ -12,8 +12,8 @@ import * as Effect from "effect/Effect"; |
| 12 | import * as FileSystem from "effect/FileSystem"; | 12 | import * as FileSystem from "effect/FileSystem"; |
| 13 | import * as Path from "effect/Path"; | 13 | import * as Path from "effect/Path"; |
| 14 | import * as Schema from "effect/Schema"; | 14 | import * as Schema from "effect/Schema"; |
| 15 | import { HttpClient } from "effect/http"; | 15 | import * as HttpClient from "effect/http/HttpClient"; |
| 16 | import { ChildProcessSpawner } from "effect/process"; | 16 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; |
| 17 | 17 | ||
| 18 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | 18 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; |
| 19 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | 19 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; |
packages/provider-pi/src/server/rpc.ts+2-1| ... | @@ -26,7 +26,8 @@ import * as Queue from "effect/Queue"; | ... | @@ -26,7 +26,8 @@ import * as Queue from "effect/Queue"; |
| 26 | import * as Scope from "effect/Scope"; | 26 | import * as Scope from "effect/Scope"; |
| 27 | import * as Schema from "effect/Schema"; | 27 | import * as Schema from "effect/Schema"; |
| 28 | import * as Stream from "effect/Stream"; | 28 | import * as Stream from "effect/Stream"; |
| 29 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 29 | import * as ChildProcess from "effect/process/ChildProcess"; |
| 30 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ||
| 30 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; | 31 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; |
| 31 | import { resolveSpawnCommand } from "@t3tools/shared/shell"; | 32 | import { resolveSpawnCommand } from "@t3tools/shared/shell"; |
| 32 | 33 |
packages/provider-pi/src/server/status.test.ts+2-1| ... | @@ -3,7 +3,8 @@ import { assert, describe, it } from "@effect/vitest"; | ... | @@ -3,7 +3,8 @@ import { assert, describe, it } from "@effect/vitest"; |
| 3 | import * as Effect from "effect/Effect"; | 3 | import * as Effect from "effect/Effect"; |
| 4 | import * as Sink from "effect/Sink"; | 4 | import * as Sink from "effect/Sink"; |
| 5 | import * as Stream from "effect/Stream"; | 5 | import * as Stream from "effect/Stream"; |
| 6 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 6 | import * as ChildProcess from "effect/process/ChildProcess"; |
| 7 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ||
| 7 | 8 | ||
| 8 | import { checkPiProviderStatus, MINIMUM_PI_VERSION } from "./status.ts"; | 9 | import { checkPiProviderStatus, MINIMUM_PI_VERSION } from "./status.ts"; |
| 9 | 10 |
packages/provider-pi/src/server/status.ts+3-2| ... | @@ -23,8 +23,9 @@ import * as Stream from "effect/Stream"; | ... | @@ -23,8 +23,9 @@ import * as Stream from "effect/Stream"; |
| 23 | import * as Exit from "effect/Exit"; | 23 | import * as Exit from "effect/Exit"; |
| 24 | import * as Option from "effect/Option"; | 24 | import * as Option from "effect/Option"; |
| 25 | import * as Result from "effect/Result"; | 25 | import * as Result from "effect/Result"; |
| 26 | import { HttpClient } from "effect/http"; | 26 | import * as HttpClient from "effect/http/HttpClient"; |
| 27 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 27 | import * as ChildProcess from "effect/process/ChildProcess"; |
| 28 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ||
| 28 | 29 | ||
| 29 | import { buildPiRpcLaunch, resolvePiLaunchArgs } from "./mcpInjection.ts"; | 30 | import { buildPiRpcLaunch, resolvePiLaunchArgs } from "./mcpInjection.ts"; |
| 30 | import { | 31 | import { |
packages/provider-pi/src/server/textGeneration.test.ts+1-1| ... | @@ -7,7 +7,7 @@ import * as Queue from "effect/Queue"; | ... | @@ -7,7 +7,7 @@ import * as Queue from "effect/Queue"; |
| 7 | import * as Schema from "effect/Schema"; | 7 | import * as Schema from "effect/Schema"; |
| 8 | import * as Sink from "effect/Sink"; | 8 | import * as Sink from "effect/Sink"; |
| 9 | import * as Stream from "effect/Stream"; | 9 | import * as Stream from "effect/Stream"; |
| 10 | import { ChildProcessSpawner } from "effect/process"; | 10 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; |
| 11 | 11 | ||
| 12 | import { makePiTextGeneration } from "./textGeneration.ts"; | 12 | import { makePiTextGeneration } from "./textGeneration.ts"; |
| 13 | 13 |
packages/provider-pi/src/server/textGeneration.ts+1-1| ... | @@ -8,7 +8,7 @@ import * as Effect from "effect/Effect"; | ... | @@ -8,7 +8,7 @@ import * as Effect from "effect/Effect"; |
| 8 | import * as Option from "effect/Option"; | 8 | import * as Option from "effect/Option"; |
| 9 | import * as Queue from "effect/Queue"; | 9 | import * as Queue from "effect/Queue"; |
| 10 | import * as Schema from "effect/Schema"; | 10 | import * as Schema from "effect/Schema"; |
| 11 | import { ChildProcessSpawner } from "effect/process"; | 11 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; |
| 12 | 12 | ||
| 13 | import { TextGenerationError } from "@t3tools/contracts"; | 13 | import { TextGenerationError } from "@t3tools/contracts"; |
| 14 | import type { PiSettings } from "../settings.ts"; | 14 | import type { PiSettings } from "../settings.ts"; |
packages/provider-testing/package.json+10-10| ... | @@ -3,25 +3,25 @@ | ... | @@ -3,25 +3,25 @@ |
| 3 | "private": true, | 3 | "private": true, |
| 4 | "type": "module", | 4 | "type": "module", |
| 5 | "exports": { | 5 | "exports": { |
| 6 | "./replayTranscript": { | 6 | "./fakeCli": { |
| 7 | "types": "./src/replayTranscript.ts", | 7 | "types": "./src/fakeCli.ts", |
| 8 | "import": "./src/replayTranscript.ts" | 8 | "import": "./src/fakeCli.ts" |
| 9 | }, | 9 | }, |
| 10 | "./replayGate": { | 10 | "./replayGate": { |
| 11 | "types": "./src/replayGate.ts", | 11 | "types": "./src/replayGate.ts", |
| 12 | "import": "./src/replayGate.ts" | 12 | "import": "./src/replayGate.ts" |
| 13 | }, | 13 | }, |
| 14 | "./replayTranscript": { | ||
| 15 | "types": "./src/replayTranscript.ts", | ||
| 16 | "import": "./src/replayTranscript.ts" | ||
| 17 | }, | ||
| 14 | "./replayWorkspace": { | 18 | "./replayWorkspace": { |
| 15 | "types": "./src/replayWorkspace.ts", | 19 | "types": "./src/replayWorkspace.ts", |
| 16 | "import": "./src/replayWorkspace.ts" | 20 | "import": "./src/replayWorkspace.ts" |
| 17 | }, | 21 | }, |
| 18 | "./host": { | 22 | "./TestProviderHost": { |
| 19 | "types": "./src/host.ts", | 23 | "types": "./src/TestProviderHost.ts", |
| 20 | "import": "./src/host.ts" | 24 | "import": "./src/TestProviderHost.ts" |
| 21 | }, | ||
| 22 | "./fakeCli": { | ||
| 23 | "types": "./src/fakeCli.ts", | ||
| 24 | "import": "./src/fakeCli.ts" | ||
| 25 | } | 25 | } |
| 26 | }, | 26 | }, |
| 27 | "scripts": { | 27 | "scripts": { |
packages/provider-testing/src/TestProviderHost.ts created+91| ... | @@ -0,0 +1,91 @@ | ||
| 1 | /** | ||
| 2 | * A `ProviderHost.ProviderHost` for driver and adapter tests. Its directories live in a | ||
| 3 | * scoped temp directory, settings are fixed, and background work always runs | ||
| 4 | * unless the test says otherwise. | ||
| 5 | * | ||
| 6 | * @module provider-testing/TestProviderHost | ||
| 7 | */ | ||
| 8 | import { DEFAULT_SERVER_SETTINGS, type ServerSettings } from "@t3tools/contracts"; | ||
| 9 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | ||
| 10 | import * as Context from "effect/Context"; | ||
| 11 | import * as Effect from "effect/Effect"; | ||
| 12 | import * as FileSystem from "effect/FileSystem"; | ||
| 13 | import * as Layer from "effect/Layer"; | ||
| 14 | import * as Option from "effect/Option"; | ||
| 15 | import * as Path from "effect/Path"; | ||
| 16 | import * as Ref from "effect/Ref"; | ||
| 17 | import * as Stream from "effect/Stream"; | ||
| 18 | |||
| 19 | export interface TestProviderHostOptions { | ||
| 20 | /** Session fallback cwd. Defaults to the test process cwd. */ | ||
| 21 | readonly cwd?: string; | ||
| 22 | /** Initial settings. A test changes them through `TestProviderHostSettings`. */ | ||
| 23 | readonly settings?: ServerSettings; | ||
| 24 | /** Whether background work such as status probes may run. Defaults to `true`. */ | ||
| 25 | readonly runBackgroundWork?: boolean; | ||
| 26 | } | ||
| 27 | |||
| 28 | /** Lets a test change the settings its `layer` reports. */ | ||
| 29 | export class TestProviderHostSettings extends Context.Service< | ||
| 30 | TestProviderHostSettings, | ||
| 31 | { readonly set: (settings: ServerSettings) => Effect.Effect<void> } | ||
| 32 | >()("@t3tools/provider-testing/TestProviderHost/TestProviderHostSettings") {} | ||
| 33 | |||
| 34 | export const layer = ( | ||
| 35 | options: TestProviderHostOptions = {}, | ||
| 36 | ): Layer.Layer< | ||
| 37 | ProviderHost.ProviderHost | TestProviderHostSettings, | ||
| 38 | never, | ||
| 39 | FileSystem.FileSystem | Path.Path | ||
| 40 | > => | ||
| 41 | Layer.effectContext( | ||
| 42 | Effect.gen(function* () { | ||
| 43 | const fileSystem = yield* FileSystem.FileSystem; | ||
| 44 | const path = yield* Path.Path; | ||
| 45 | const baseDir = yield* fileSystem | ||
| 46 | .makeTempDirectoryScoped({ prefix: "t3-provider-host-" }) | ||
| 47 | .pipe(Effect.orDie); | ||
| 48 | const stateDir = path.join(baseDir, "userdata"); | ||
| 49 | const providerStatusCacheDir = path.join(baseDir, "caches"); | ||
| 50 | const attachmentsDir = path.join(stateDir, "attachments"); | ||
| 51 | for (const directory of [stateDir, providerStatusCacheDir, attachmentsDir]) { | ||
| 52 | yield* fileSystem.makeDirectory(directory, { recursive: true }).pipe(Effect.orDie); | ||
| 53 | } | ||
| 54 | const settings = yield* Ref.make(options.settings ?? DEFAULT_SERVER_SETTINGS); | ||
| 55 | const credentials = new Map<string, Uint8Array>(); | ||
| 56 | const host = ProviderHost.ProviderHost.of({ | ||
| 57 | paths: { | ||
| 58 | cwd: options.cwd ?? process.cwd(), | ||
| 59 | baseDir, | ||
| 60 | stateDir, | ||
| 61 | providerStatusCacheDir, | ||
| 62 | attachmentsDir, | ||
| 63 | }, | ||
| 64 | settings: { | ||
| 65 | get: Ref.get(settings), | ||
| 66 | withSnapshot: (use) => Ref.get(settings).pipe(Effect.flatMap(use)), | ||
| 67 | changes: Stream.empty, | ||
| 68 | subscribe: Effect.succeed(Stream.empty), | ||
| 69 | }, | ||
| 70 | shouldRunBackgroundWork: () => Effect.succeed(options.runBackgroundWork ?? true), | ||
| 71 | // Tests store attachments flat under the attachments directory by id. | ||
| 72 | resolveAttachmentPath: (attachment) => path.join(attachmentsDir, attachment.id), | ||
| 73 | // Credentials live in memory for the layer's lifetime. | ||
| 74 | credentials: (namespace, bindingId) => | ||
| 75 | Effect.sync(() => { | ||
| 76 | const key = `${namespace}:${bindingId}`; | ||
| 77 | return { | ||
| 78 | binding: { owner: "t3" as const, key }, | ||
| 79 | get: Effect.sync(() => Option.fromUndefinedOr(credentials.get(key))), | ||
| 80 | set: (value: Uint8Array) => Effect.sync(() => void credentials.set(key, value)), | ||
| 81 | remove: Effect.sync(() => void credentials.delete(key)), | ||
| 82 | }; | ||
| 83 | }), | ||
| 84 | }); | ||
| 85 | return Context.make(ProviderHost.ProviderHost, host).pipe( | ||
| 86 | Context.add(TestProviderHostSettings, { | ||
| 87 | set: (next) => Ref.set(settings, next), | ||
| 88 | }), | ||
| 89 | ); | ||
| 90 | }), | ||
| 91 | ); | ||
packages/provider-testing/src/host.ts deleted-91| ... | @@ -1,91 +0,0 @@ | ||
| 1 | /** | ||
| 2 | * A `ProviderHost.ProviderHost` for driver and adapter tests. Its directories live in a | ||
| 3 | * scoped temp directory, settings are fixed, and background work always runs | ||
| 4 | * unless the test says otherwise. | ||
| 5 | * | ||
| 6 | * @module provider-testing/host | ||
| 7 | */ | ||
| 8 | import { DEFAULT_SERVER_SETTINGS, type ServerSettings } from "@t3tools/contracts"; | ||
| 9 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | ||
| 10 | import * as Context from "effect/Context"; | ||
| 11 | import * as Effect from "effect/Effect"; | ||
| 12 | import * as FileSystem from "effect/FileSystem"; | ||
| 13 | import * as Layer from "effect/Layer"; | ||
| 14 | import * as Option from "effect/Option"; | ||
| 15 | import * as Path from "effect/Path"; | ||
| 16 | import * as Ref from "effect/Ref"; | ||
| 17 | import * as Stream from "effect/Stream"; | ||
| 18 | |||
| 19 | export interface TestProviderHostOptions { | ||
| 20 | /** Session fallback cwd. Defaults to the test process cwd. */ | ||
| 21 | readonly cwd?: string; | ||
| 22 | /** Initial settings. A test changes them through `TestProviderHostSettings`. */ | ||
| 23 | readonly settings?: ServerSettings; | ||
| 24 | /** Whether background work such as status probes may run. Defaults to `true`. */ | ||
| 25 | readonly runBackgroundWork?: boolean; | ||
| 26 | } | ||
| 27 | |||
| 28 | /** Lets a test change the settings its `layerTestProviderHost` reports. */ | ||
| 29 | export class TestProviderHostSettings extends Context.Service< | ||
| 30 | TestProviderHostSettings, | ||
| 31 | { readonly set: (settings: ServerSettings) => Effect.Effect<void> } | ||
| 32 | >()("@t3tools/provider-testing/host/TestProviderHostSettings") {} | ||
| 33 | |||
| 34 | export const layerTestProviderHost = ( | ||
| 35 | options: TestProviderHostOptions = {}, | ||
| 36 | ): Layer.Layer< | ||
| 37 | ProviderHost.ProviderHost | TestProviderHostSettings, | ||
| 38 | never, | ||
| 39 | FileSystem.FileSystem | Path.Path | ||
| 40 | > => | ||
| 41 | Layer.effectContext( | ||
| 42 | Effect.gen(function* () { | ||
| 43 | const fileSystem = yield* FileSystem.FileSystem; | ||
| 44 | const path = yield* Path.Path; | ||
| 45 | const baseDir = yield* fileSystem | ||
| 46 | .makeTempDirectoryScoped({ prefix: "t3-provider-host-" }) | ||
| 47 | .pipe(Effect.orDie); | ||
| 48 | const stateDir = path.join(baseDir, "userdata"); | ||
| 49 | const providerStatusCacheDir = path.join(baseDir, "caches"); | ||
| 50 | const attachmentsDir = path.join(stateDir, "attachments"); | ||
| 51 | for (const directory of [stateDir, providerStatusCacheDir, attachmentsDir]) { | ||
| 52 | yield* fileSystem.makeDirectory(directory, { recursive: true }).pipe(Effect.orDie); | ||
| 53 | } | ||
| 54 | const settings = yield* Ref.make(options.settings ?? DEFAULT_SERVER_SETTINGS); | ||
| 55 | const credentials = new Map<string, Uint8Array>(); | ||
| 56 | const host = ProviderHost.ProviderHost.of({ | ||
| 57 | paths: { | ||
| 58 | cwd: options.cwd ?? process.cwd(), | ||
| 59 | baseDir, | ||
| 60 | stateDir, | ||
| 61 | providerStatusCacheDir, | ||
| 62 | attachmentsDir, | ||
| 63 | }, | ||
| 64 | settings: { | ||
| 65 | get: Ref.get(settings), | ||
| 66 | withSnapshot: (use) => Ref.get(settings).pipe(Effect.flatMap(use)), | ||
| 67 | changes: Stream.empty, | ||
| 68 | subscribe: Effect.succeed(Stream.empty), | ||
| 69 | }, | ||
| 70 | shouldRunBackgroundWork: () => Effect.succeed(options.runBackgroundWork ?? true), | ||
| 71 | // Tests store attachments flat under the attachments directory by id. | ||
| 72 | resolveAttachmentPath: (attachment) => path.join(attachmentsDir, attachment.id), | ||
| 73 | // Credentials live in memory for the layer's lifetime. | ||
| 74 | credentials: (namespace, bindingId) => | ||
| 75 | Effect.sync(() => { | ||
| 76 | const key = `${namespace}:${bindingId}`; | ||
| 77 | return { | ||
| 78 | binding: { owner: "t3" as const, key }, | ||
| 79 | get: Effect.sync(() => Option.fromUndefinedOr(credentials.get(key))), | ||
| 80 | set: (value: Uint8Array) => Effect.sync(() => void credentials.set(key, value)), | ||
| 81 | remove: Effect.sync(() => void credentials.delete(key)), | ||
| 82 | }; | ||
| 83 | }), | ||
| 84 | }); | ||
| 85 | return Context.make(ProviderHost.ProviderHost, host).pipe( | ||
| 86 | Context.add(TestProviderHostSettings, { | ||
| 87 | set: (next) => Ref.set(settings, next), | ||
| 88 | }), | ||
| 89 | ); | ||
| 90 | }), | ||
| 91 | ); | ||
packages/provider-testing/src/replayWorkspace.ts+2-1| ... | @@ -4,7 +4,8 @@ import * as FileSystem from "effect/FileSystem"; | ... | @@ -4,7 +4,8 @@ import * as FileSystem from "effect/FileSystem"; |
| 4 | import * as Path from "effect/Path"; | 4 | import * as Path from "effect/Path"; |
| 5 | import * as PlatformError from "effect/PlatformError"; | 5 | import * as PlatformError from "effect/PlatformError"; |
| 6 | import * as Schema from "effect/Schema"; | 6 | import * as Schema from "effect/Schema"; |
| 7 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 7 | import * as ChildProcess from "effect/process/ChildProcess"; |
| 8 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | ||
| 8 | 9 | ||
| 9 | class ReplayFixtureGitCommandError extends Schema.TaggedError<ReplayFixtureGitCommandError>()( | 10 | class ReplayFixtureGitCommandError extends Schema.TaggedError<ReplayFixtureGitCommandError>()( |
| 10 | "ReplayFixtureGitCommandError", | 11 | "ReplayFixtureGitCommandError", |