| author | |
| committer | |
| log | 68ab16f3084236871685bed5032cb05c7c436dbd |
| tree | 050b9f440c3622cdaba255ce726bccf26ac1f9a9 |
| parent | b66dd402e86899c3fb4341d46c32d0d69df1eefc |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>28 files changed, 196 insertions(+), 91 deletions(-)
apps/server/src/orchestration-v2/AcpRegistryOrchestratorV2.live.test.ts+2| ... | @@ -29,6 +29,7 @@ import * as CodexInstallation from "../provider/CodexInstallation.ts"; | ... | @@ -29,6 +29,7 @@ import * as CodexInstallation from "../provider/CodexInstallation.ts"; |
| 29 | import * as ServerEnvironment from "../environment/ServerEnvironment.ts"; | 29 | import * as ServerEnvironment from "../environment/ServerEnvironment.ts"; |
| 30 | import * as ModelManifest from "../provider/ModelManifest.ts"; | 30 | import * as ModelManifest from "../provider/ModelManifest.ts"; |
| 31 | import * as ProviderInstanceRegistryHydration from "../provider/ProviderInstanceRegistryHydration.ts"; | 31 | import * as ProviderInstanceRegistryHydration from "../provider/ProviderInstanceRegistryHydration.ts"; |
| 32 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 32 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; | 33 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; |
| 33 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; | 34 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; |
| 34 | import * as OpenCodeServerLedger from "@t3tools/provider-opencode/server/OpenCodeServerLedger"; | 35 | import * as OpenCodeServerLedger from "@t3tools/provider-opencode/server/OpenCodeServerLedger"; |
| ... | @@ -112,6 +113,7 @@ const layerProviderInstanceRegistry = ProviderInstanceRegistryHydration.layer.pi | ... | @@ -112,6 +113,7 @@ const layerProviderInstanceRegistry = ProviderInstanceRegistryHydration.layer.pi |
| 112 | ProviderEventLoggers.ProviderEventLoggers, | 113 | ProviderEventLoggers.ProviderEventLoggers, |
| 113 | ProviderEventLoggers.NoOpProviderEventLoggers, | 114 | ProviderEventLoggers.NoOpProviderEventLoggers, |
| 114 | ), | 115 | ), |
| 116 | ProviderLatestVersions.layer, | ||
| 115 | ModelManifest.layerTest, | 117 | ModelManifest.layerTest, |
| 116 | AntigravityInstallation.AntigravityInstallation.layer.pipe( | 118 | AntigravityInstallation.AntigravityInstallation.layer.pipe( |
| 117 | Layer.provide(layerServerConfig.pipe(Layer.provide(layerPlatformTest))), | 119 | Layer.provide(layerServerConfig.pipe(Layer.provide(layerPlatformTest))), |
apps/server/src/orchestration-v2/CursorOrchestratorV2.live.test.ts+2| ... | @@ -29,6 +29,7 @@ import * as CodexInstallation from "../provider/CodexInstallation.ts"; | ... | @@ -29,6 +29,7 @@ import * as CodexInstallation from "../provider/CodexInstallation.ts"; |
| 29 | import * as ServerEnvironment from "../environment/ServerEnvironment.ts"; | 29 | import * as ServerEnvironment from "../environment/ServerEnvironment.ts"; |
| 30 | import * as ModelManifest from "../provider/ModelManifest.ts"; | 30 | import * as ModelManifest from "../provider/ModelManifest.ts"; |
| 31 | import * as ProviderInstanceRegistryHydration from "../provider/ProviderInstanceRegistryHydration.ts"; | 31 | import * as ProviderInstanceRegistryHydration from "../provider/ProviderInstanceRegistryHydration.ts"; |
| 32 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 32 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; | 33 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; |
| 33 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; | 34 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; |
| 34 | import * as OpenCodeServerLedger from "@t3tools/provider-opencode/server/OpenCodeServerLedger"; | 35 | import * as OpenCodeServerLedger from "@t3tools/provider-opencode/server/OpenCodeServerLedger"; |
| ... | @@ -92,6 +93,7 @@ const layerProviderInstanceRegistry = ProviderInstanceRegistryHydration.layer.pi | ... | @@ -92,6 +93,7 @@ const layerProviderInstanceRegistry = ProviderInstanceRegistryHydration.layer.pi |
| 92 | ProviderEventLoggers.ProviderEventLoggers, | 93 | ProviderEventLoggers.ProviderEventLoggers, |
| 93 | ProviderEventLoggers.NoOpProviderEventLoggers, | 94 | ProviderEventLoggers.NoOpProviderEventLoggers, |
| 94 | ), | 95 | ), |
| 96 | ProviderLatestVersions.layer, | ||
| 95 | ModelManifest.layerTest, | 97 | ModelManifest.layerTest, |
| 96 | AntigravityInstallation.AntigravityInstallation.layer.pipe( | 98 | AntigravityInstallation.AntigravityInstallation.layer.pipe( |
| 97 | Layer.provide(layerServerConfig.pipe(Layer.provide(layerPlatformTest))), | 99 | Layer.provide(layerServerConfig.pipe(Layer.provide(layerPlatformTest))), |
apps/server/src/orchestration-v2/GrokOrchestratorV2.live.test.ts+2| ... | @@ -29,6 +29,7 @@ import * as CodexInstallation from "../provider/CodexInstallation.ts"; | ... | @@ -29,6 +29,7 @@ import * as CodexInstallation from "../provider/CodexInstallation.ts"; |
| 29 | import * as ServerEnvironment from "../environment/ServerEnvironment.ts"; | 29 | import * as ServerEnvironment from "../environment/ServerEnvironment.ts"; |
| 30 | import * as ModelManifest from "../provider/ModelManifest.ts"; | 30 | import * as ModelManifest from "../provider/ModelManifest.ts"; |
| 31 | import * as ProviderInstanceRegistryHydration from "../provider/ProviderInstanceRegistryHydration.ts"; | 31 | import * as ProviderInstanceRegistryHydration from "../provider/ProviderInstanceRegistryHydration.ts"; |
| 32 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 32 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; | 33 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; |
| 33 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; | 34 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; |
| 34 | import * as OpenCodeServerLedger from "@t3tools/provider-opencode/server/OpenCodeServerLedger"; | 35 | import * as OpenCodeServerLedger from "@t3tools/provider-opencode/server/OpenCodeServerLedger"; |
| ... | @@ -91,6 +92,7 @@ const layerProviderInstanceRegistry = ProviderInstanceRegistryHydration.layer.pi | ... | @@ -91,6 +92,7 @@ const layerProviderInstanceRegistry = ProviderInstanceRegistryHydration.layer.pi |
| 91 | ProviderEventLoggers.ProviderEventLoggers, | 92 | ProviderEventLoggers.ProviderEventLoggers, |
| 92 | ProviderEventLoggers.NoOpProviderEventLoggers, | 93 | ProviderEventLoggers.NoOpProviderEventLoggers, |
| 93 | ), | 94 | ), |
| 95 | ProviderLatestVersions.layer, | ||
| 94 | ModelManifest.layerTest, | 96 | ModelManifest.layerTest, |
| 95 | AntigravityInstallation.AntigravityInstallation.layer.pipe( | 97 | AntigravityInstallation.AntigravityInstallation.layer.pipe( |
| 96 | Layer.provide(layerServerConfig.pipe(Layer.provide(layerPlatformTest))), | 98 | Layer.provide(layerServerConfig.pipe(Layer.provide(layerPlatformTest))), |
apps/server/src/orchestration-v2/OpenCode2OrchestratorV2.live.test.ts+2| ... | @@ -54,6 +54,7 @@ import * as CodexInstallation from "../provider/CodexInstallation.ts"; | ... | @@ -54,6 +54,7 @@ import * as CodexInstallation from "../provider/CodexInstallation.ts"; |
| 54 | import * as ServerEnvironment from "../environment/ServerEnvironment.ts"; | 54 | import * as ServerEnvironment from "../environment/ServerEnvironment.ts"; |
| 55 | import * as ModelManifest from "../provider/ModelManifest.ts"; | 55 | import * as ModelManifest from "../provider/ModelManifest.ts"; |
| 56 | import * as ProviderInstanceRegistryHydration from "../provider/ProviderInstanceRegistryHydration.ts"; | 56 | import * as ProviderInstanceRegistryHydration from "../provider/ProviderInstanceRegistryHydration.ts"; |
| 57 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 57 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; | 58 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; |
| 58 | import * as OpenCode2Client from "@t3tools/provider-opencode/server/v2/OpenCode2Client"; | 59 | import * as OpenCode2Client from "@t3tools/provider-opencode/server/v2/OpenCode2Client"; |
| 59 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; | 60 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; |
| ... | @@ -185,6 +186,7 @@ const layerProviderInstanceRegistry = ProviderInstanceRegistryHydration.layer.pi | ... | @@ -185,6 +186,7 @@ const layerProviderInstanceRegistry = ProviderInstanceRegistryHydration.layer.pi |
| 185 | ProviderEventLoggers.ProviderEventLoggers, | 186 | ProviderEventLoggers.ProviderEventLoggers, |
| 186 | ProviderEventLoggers.NoOpProviderEventLoggers, | 187 | ProviderEventLoggers.NoOpProviderEventLoggers, |
| 187 | ), | 188 | ), |
| 189 | ProviderLatestVersions.layer, | ||
| 188 | ModelManifest.layerTest, | 190 | ModelManifest.layerTest, |
| 189 | AntigravityInstallation.AntigravityInstallation.layer.pipe( | 191 | AntigravityInstallation.AntigravityInstallation.layer.pipe( |
| 190 | Layer.provide(layerServerConfig.pipe(Layer.provide(layerPlatformTest))), | 192 | Layer.provide(layerServerConfig.pipe(Layer.provide(layerPlatformTest))), |
apps/server/src/provider/Drivers/ClaudeDriver.ts+4| ... | @@ -24,6 +24,7 @@ import { HttpClient } from "effect/http"; | ... | @@ -24,6 +24,7 @@ import { HttpClient } from "effect/http"; |
| 24 | import { ChildProcessSpawner } from "effect/process"; | 24 | import { ChildProcessSpawner } from "effect/process"; |
| 25 | 25 | ||
| 26 | import { makeClaudeTextGeneration } from "../../textGeneration/ClaudeTextGeneration.ts"; | 26 | import { makeClaudeTextGeneration } from "../../textGeneration/ClaudeTextGeneration.ts"; |
| 27 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 27 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | 28 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; |
| 28 | import * as ServerConfig from "../../config.ts"; | 29 | import * as ServerConfig from "../../config.ts"; |
| 29 | import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; | 30 | import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; |
| ... | @@ -100,6 +101,7 @@ export type ClaudeDriverEnv = | ... | @@ -100,6 +101,7 @@ export type ClaudeDriverEnv = |
| 100 | | Crypto.Crypto | 101 | | Crypto.Crypto |
| 101 | | FileSystem.FileSystem | 102 | | FileSystem.FileSystem |
| 102 | | HttpClient.HttpClient | 103 | | HttpClient.HttpClient |
| 104 | | ProviderLatestVersions.ProviderLatestVersions | ||
| 103 | | ModelCatalog.ModelCatalog | 105 | | ModelCatalog.ModelCatalog |
| 104 | | Path.Path | 106 | | Path.Path |
| 105 | | ProviderEventLoggers.ProviderEventLoggers | 107 | | ProviderEventLoggers.ProviderEventLoggers |
| ... | @@ -120,6 +122,7 @@ export const ClaudeDriver: ProviderDriver<ClaudeSettings, ClaudeDriverEnv> = { | ... | @@ -120,6 +122,7 @@ export const ClaudeDriver: ProviderDriver<ClaudeSettings, ClaudeDriverEnv> = { |
| 120 | const path = yield* Path.Path; | 122 | const path = yield* Path.Path; |
| 121 | const { cwd } = yield* ServerConfig.ServerConfig; | 123 | const { cwd } = yield* ServerConfig.ServerConfig; |
| 122 | const httpClient = yield* HttpClient.HttpClient; | 124 | const httpClient = yield* HttpClient.HttpClient; |
| 125 | const latestVersions = yield* ProviderLatestVersions.ProviderLatestVersions; | ||
| 123 | const resetCreditCoordinator = yield* ResetCreditCoordinator.ResetCreditCoordinator; | 126 | const resetCreditCoordinator = yield* ResetCreditCoordinator.ResetCreditCoordinator; |
| 124 | const catalogService = yield* ModelCatalog.ModelCatalog; | 127 | const catalogService = yield* ModelCatalog.ModelCatalog; |
| 125 | const modelCatalog = catalogService | 128 | const modelCatalog = catalogService |
| ... | @@ -256,6 +259,7 @@ export const ClaudeDriver: ProviderDriver<ClaudeSettings, ClaudeDriverEnv> = { | ... | @@ -256,6 +259,7 @@ export const ClaudeDriver: ProviderDriver<ClaudeSettings, ClaudeDriverEnv> = { |
| 256 | }), | 259 | }), |
| 257 | ), | 260 | ), |
| 258 | Effect.provideService(HttpClient.HttpClient, httpClient), | 261 | Effect.provideService(HttpClient.HttpClient, httpClient), |
| 262 | Effect.provideService(ProviderLatestVersions.ProviderLatestVersions, latestVersions), | ||
| 259 | Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)), | 263 | Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)), |
| 260 | ), | 264 | ), |
| 261 | }).pipe( | 265 | }).pipe( |
apps/server/src/provider/Drivers/CodexDriver.test.ts+5-6| ... | @@ -26,11 +26,11 @@ import * as BackgroundPolicy from "../../background/BackgroundPolicy.ts"; | ... | @@ -26,11 +26,11 @@ import * as BackgroundPolicy from "../../background/BackgroundPolicy.ts"; |
| 26 | import * as ServerConfig from "../../config.ts"; | 26 | import * as ServerConfig from "../../config.ts"; |
| 27 | import * as ServerSettings from "../../serverSettings.ts"; | 27 | import * as ServerSettings from "../../serverSettings.ts"; |
| 28 | import * as ResetCreditCoordinator from "../resetCreditCoordinator.ts"; | 28 | import * as ResetCreditCoordinator from "../resetCreditCoordinator.ts"; |
| 29 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 29 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; | 30 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; |
| 30 | import * as ModelManifest from "../ModelManifest.ts"; | 31 | import * as ModelManifest from "../ModelManifest.ts"; |
| 31 | import { | 32 | import { |
| 32 | createProviderVersionAdvisory, | 33 | createProviderVersionAdvisory, |
| 33 | ProviderVersionCache, | ||
| 34 | resolveLatestProviderVersion, | 34 | resolveLatestProviderVersion, |
| 35 | } from "@t3tools/provider-core/server/maintenanceResolver"; | 35 | } from "@t3tools/provider-core/server/maintenanceResolver"; |
| 36 | import { CodexDriver } from "./CodexDriver.ts"; | 36 | import { CodexDriver } from "./CodexDriver.ts"; |
| ... | @@ -75,6 +75,7 @@ const layerDeps = ServerConfig.layerTest(process.cwd(), { | ... | @@ -75,6 +75,7 @@ const layerDeps = ServerConfig.layerTest(process.cwd(), { |
| 75 | ProviderEventLoggers.NoOpProviderEventLoggers, | 75 | ProviderEventLoggers.NoOpProviderEventLoggers, |
| 76 | ), | 76 | ), |
| 77 | ), | 77 | ), |
| 78 | Layer.provideMerge(ProviderLatestVersions.layer), | ||
| 78 | Layer.provideMerge( | 79 | Layer.provideMerge( |
| 79 | Layer.succeed( | 80 | Layer.succeed( |
| 80 | HttpClient.HttpClient, | 81 | HttpClient.HttpClient, |
| ... | @@ -557,11 +558,9 @@ it.layer(layerTest)("CodexDriver", (it) => { | ... | @@ -557,11 +558,9 @@ it.layer(layerTest)("CodexDriver", (it) => { |
| 557 | }).pipe(Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, metadataSpawner)); | 558 | }).pipe(Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, metadataSpawner)); |
| 558 | const capabilities = yield* instance.snapshot.resolveMaintenance(); | 559 | const capabilities = yield* instance.snapshot.resolveMaintenance(); |
| 559 | const latestVersion = yield* resolveLatestProviderVersion(capabilities).pipe( | 560 | const latestVersion = yield* resolveLatestProviderVersion(capabilities).pipe( |
| 560 | Effect.provideService( | 561 | Effect.provideServiceEffect( |
| 561 | ProviderVersionCache, | 562 | ProviderLatestVersions.ProviderLatestVersions, |
| 562 | new Map([ | 563 | ProviderLatestVersions.make([["@openai/codex", "0.153.4"]]), |
| 563 | ["@openai/codex", { expiresAt: Number.MAX_SAFE_INTEGER, version: "0.153.4" }], | ||
| 564 | ]), | ||
| 565 | ), | 564 | ), |
| 566 | ); | 565 | ); |
| 567 | expect(probes).toEqual([]); | 566 | expect(probes).toEqual([]); |
apps/server/src/provider/Drivers/CodexDriver.ts+4| ... | @@ -31,6 +31,7 @@ import { HttpClient } from "effect/http"; | ... | @@ -31,6 +31,7 @@ import { HttpClient } from "effect/http"; |
| 31 | import { ChildProcessSpawner } from "effect/process"; | 31 | import { ChildProcessSpawner } from "effect/process"; |
| 32 | 32 | ||
| 33 | import { makeCodexTextGeneration } from "../../textGeneration/CodexTextGeneration.ts"; | 33 | import { makeCodexTextGeneration } from "../../textGeneration/CodexTextGeneration.ts"; |
| 34 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 34 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | 35 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; |
| 35 | import * as ServerConfig from "../../config.ts"; | 36 | import * as ServerConfig from "../../config.ts"; |
| 36 | import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; | 37 | import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; |
| ... | @@ -115,6 +116,7 @@ export type CodexDriverEnv = | ... | @@ -115,6 +116,7 @@ export type CodexDriverEnv = |
| 115 | | Crypto.Crypto | 116 | | Crypto.Crypto |
| 116 | | FileSystem.FileSystem | 117 | | FileSystem.FileSystem |
| 117 | | HttpClient.HttpClient | 118 | | HttpClient.HttpClient |
| 119 | | ProviderLatestVersions.ProviderLatestVersions | ||
| 118 | | ModelCatalog.ModelCatalog | 120 | | ModelCatalog.ModelCatalog |
| 119 | | Path.Path | 121 | | Path.Path |
| 120 | | ProviderEventLoggers.ProviderEventLoggers | 122 | | ProviderEventLoggers.ProviderEventLoggers |
| ... | @@ -147,6 +149,7 @@ export const CodexDriver: ProviderDriver<CodexSettings, CodexDriverEnv> = { | ... | @@ -147,6 +149,7 @@ export const CodexDriver: ProviderDriver<CodexSettings, CodexDriverEnv> = { |
| 147 | const fileSystem = yield* FileSystem.FileSystem; | 149 | const fileSystem = yield* FileSystem.FileSystem; |
| 148 | const pathService = yield* Path.Path; | 150 | const pathService = yield* Path.Path; |
| 149 | const httpClient = yield* HttpClient.HttpClient; | 151 | const httpClient = yield* HttpClient.HttpClient; |
| 152 | const latestVersions = yield* ProviderLatestVersions.ProviderLatestVersions; | ||
| 150 | const modelCatalog = yield* ModelCatalog.ModelCatalog; | 153 | const modelCatalog = yield* ModelCatalog.ModelCatalog; |
| 151 | const currentCatalog = modelCatalog.current(DRIVER_KIND); | 154 | const currentCatalog = modelCatalog.current(DRIVER_KIND); |
| 152 | const processEnv = mergeProviderInstanceEnvironment(environment); | 155 | const processEnv = mergeProviderInstanceEnvironment(environment); |
| ... | @@ -251,6 +254,7 @@ export const CodexDriver: ProviderDriver<CodexSettings, CodexDriverEnv> = { | ... | @@ -251,6 +254,7 @@ export const CodexDriver: ProviderDriver<CodexSettings, CodexDriverEnv> = { |
| 251 | }), | 254 | }), |
| 252 | ), | 255 | ), |
| 253 | Effect.provideService(HttpClient.HttpClient, httpClient), | 256 | Effect.provideService(HttpClient.HttpClient, httpClient), |
| 257 | Effect.provideService(ProviderLatestVersions.ProviderLatestVersions, latestVersions), | ||
| 254 | Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)), | 258 | Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)), |
| 255 | ), | 259 | ), |
| 256 | }).pipe( | 260 | }).pipe( |
apps/server/src/provider/ProviderInstanceRegistry.test.ts+3| ... | @@ -35,6 +35,7 @@ import { | ... | @@ -35,6 +35,7 @@ import { |
| 35 | type ProviderInstanceConfigMap, | 35 | type ProviderInstanceConfigMap, |
| 36 | ProviderInstanceId, | 36 | ProviderInstanceId, |
| 37 | } from "@t3tools/contracts"; | 37 | } from "@t3tools/contracts"; |
| 38 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 38 | import type { GrokSettings } from "@t3tools/provider-grok/settings"; | 39 | import type { GrokSettings } from "@t3tools/provider-grok/settings"; |
| 39 | import type { CursorSettings } from "@t3tools/provider-cursor/settings"; | 40 | import type { CursorSettings } from "@t3tools/provider-cursor/settings"; |
| 40 | import { HostProcessPlatform, isHostWindows } from "@t3tools/shared/hostProcess"; | 41 | import { HostProcessPlatform, isHostWindows } from "@t3tools/shared/hostProcess"; |
| ... | @@ -228,6 +229,7 @@ describe("ProviderInstanceRegistry — multi-instance codex slice", () => { | ... | @@ -228,6 +229,7 @@ describe("ProviderInstanceRegistry — multi-instance codex slice", () => { |
| 228 | ProviderEventLoggers.NoOpProviderEventLoggers, | 229 | ProviderEventLoggers.NoOpProviderEventLoggers, |
| 229 | ), | 230 | ), |
| 230 | ), | 231 | ), |
| 232 | Layer.provideMerge(ProviderLatestVersions.layer), | ||
| 231 | Layer.provideMerge(ModelManifest.layerTest), | 233 | Layer.provideMerge(ModelManifest.layerTest), |
| 232 | Layer.provideMerge(ResetCreditCoordinator.layerTest), | 234 | Layer.provideMerge(ResetCreditCoordinator.layerTest), |
| 233 | ); | 235 | ); |
| ... | @@ -609,6 +611,7 @@ describe("ProviderInstanceRegistry — all drivers slice", () => { | ... | @@ -609,6 +611,7 @@ describe("ProviderInstanceRegistry — all drivers slice", () => { |
| 609 | ProviderEventLoggers.NoOpProviderEventLoggers, | 611 | ProviderEventLoggers.NoOpProviderEventLoggers, |
| 610 | ), | 612 | ), |
| 611 | ), | 613 | ), |
| 614 | Layer.provideMerge(ProviderLatestVersions.layer), | ||
| 612 | Layer.provideMerge(ModelManifest.layerTest), | 615 | Layer.provideMerge(ModelManifest.layerTest), |
| 613 | Layer.provideMerge(ResetCreditCoordinator.layerTest), | 616 | Layer.provideMerge(ResetCreditCoordinator.layerTest), |
| 614 | ); | 617 | ); |
apps/server/src/provider/ProviderRegistry.test.ts+5| ... | @@ -45,6 +45,7 @@ import * as AntigravityInstallation from "./AntigravityInstallation.ts"; | ... | @@ -45,6 +45,7 @@ import * as AntigravityInstallation from "./AntigravityInstallation.ts"; |
| 45 | import * as ModelManifest from "./ModelManifest.ts"; | 45 | import * as ModelManifest from "./ModelManifest.ts"; |
| 46 | import { applyProviderCompatibility } from "./providerCompatibility.ts"; | 46 | import { applyProviderCompatibility } from "./providerCompatibility.ts"; |
| 47 | import * as ResetCreditCoordinator from "./resetCreditCoordinator.ts"; | 47 | import * as ResetCreditCoordinator from "./resetCreditCoordinator.ts"; |
| 48 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 48 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; | 49 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; |
| 49 | import * as OpenCodeServerLedger from "@t3tools/provider-opencode/server/OpenCodeServerLedger"; | 50 | import * as OpenCodeServerLedger from "@t3tools/provider-opencode/server/OpenCodeServerLedger"; |
| 50 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; | 51 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; |
| ... | @@ -2759,6 +2760,7 @@ it.layer( | ... | @@ -2759,6 +2760,7 @@ it.layer( |
| 2759 | ProviderEventLoggers.NoOpProviderEventLoggers, | 2760 | ProviderEventLoggers.NoOpProviderEventLoggers, |
| 2760 | ), | 2761 | ), |
| 2761 | ), | 2762 | ), |
| 2763 | Layer.provideMerge(ProviderLatestVersions.layer), | ||
| 2762 | Layer.provideMerge(ModelManifest.layerTest), | 2764 | Layer.provideMerge(ModelManifest.layerTest), |
| 2763 | Layer.provideMerge(ResetCreditCoordinator.layerTest), | 2765 | Layer.provideMerge(ResetCreditCoordinator.layerTest), |
| 2764 | Layer.provideMerge( | 2766 | Layer.provideMerge( |
| ... | @@ -2862,6 +2864,7 @@ it.layer( | ... | @@ -2862,6 +2864,7 @@ it.layer( |
| 2862 | ProviderEventLoggers.NoOpProviderEventLoggers, | 2864 | ProviderEventLoggers.NoOpProviderEventLoggers, |
| 2863 | ), | 2865 | ), |
| 2864 | ), | 2866 | ), |
| 2867 | Layer.provideMerge(ProviderLatestVersions.layer), | ||
| 2865 | Layer.provideMerge(ModelManifest.layerTest), | 2868 | Layer.provideMerge(ModelManifest.layerTest), |
| 2866 | Layer.provideMerge(ResetCreditCoordinator.layerTest), | 2869 | Layer.provideMerge(ResetCreditCoordinator.layerTest), |
| 2867 | Layer.provideMerge( | 2870 | Layer.provideMerge( |
| ... | @@ -2980,6 +2983,7 @@ it.layer( | ... | @@ -2980,6 +2983,7 @@ it.layer( |
| 2980 | ProviderEventLoggers.NoOpProviderEventLoggers, | 2983 | ProviderEventLoggers.NoOpProviderEventLoggers, |
| 2981 | ), | 2984 | ), |
| 2982 | ), | 2985 | ), |
| 2986 | Layer.provideMerge(ProviderLatestVersions.layer), | ||
| 2983 | Layer.provideMerge(ModelManifest.layerTest), | 2987 | Layer.provideMerge(ModelManifest.layerTest), |
| 2984 | Layer.provideMerge(ResetCreditCoordinator.layerTest), | 2988 | Layer.provideMerge(ResetCreditCoordinator.layerTest), |
| 2985 | Layer.provideMerge( | 2989 | Layer.provideMerge( |
| ... | @@ -3038,6 +3042,7 @@ it.layer( | ... | @@ -3038,6 +3042,7 @@ it.layer( |
| 3038 | ProviderEventLoggers.NoOpProviderEventLoggers, | 3042 | ProviderEventLoggers.NoOpProviderEventLoggers, |
| 3039 | ), | 3043 | ), |
| 3040 | ), | 3044 | ), |
| 3045 | Layer.provideMerge(ProviderLatestVersions.layer), | ||
| 3041 | Layer.provideMerge(ModelManifest.layerTest), | 3046 | Layer.provideMerge(ModelManifest.layerTest), |
| 3042 | Layer.provideMerge(ResetCreditCoordinator.layerTest), | 3047 | Layer.provideMerge(ResetCreditCoordinator.layerTest), |
| 3043 | Layer.provideMerge( | 3048 | Layer.provideMerge( |
apps/server/src/provider/providerMaintenanceRunner.test.ts+2-2| ... | @@ -26,9 +26,9 @@ import { SpawnExecutableResolution } from "@t3tools/shared/shell"; | ... | @@ -26,9 +26,9 @@ import { SpawnExecutableResolution } from "@t3tools/shared/shell"; |
| 26 | import * as ProviderRegistry from "./ProviderRegistry.ts"; | 26 | import * as ProviderRegistry from "./ProviderRegistry.ts"; |
| 27 | import * as ModelManifest from "./ModelManifest.ts"; | 27 | import * as ModelManifest from "./ModelManifest.ts"; |
| 28 | import * as ProviderMaintenanceRunner from "./providerMaintenanceRunner.ts"; | 28 | import * as ProviderMaintenanceRunner from "./providerMaintenanceRunner.ts"; |
| 29 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 29 | import { | 30 | import { |
| 30 | makeProviderMaintenanceCapabilities, | 31 | makeProviderMaintenanceCapabilities, |
| 31 | ProviderVersionCache, | ||
| 32 | type ProviderMaintenanceCapabilities, | 32 | type ProviderMaintenanceCapabilities, |
| 33 | } from "@t3tools/provider-core/server/maintenanceResolver"; | 33 | } from "@t3tools/provider-core/server/maintenanceResolver"; |
| 34 | const isServerProviderUpdateError = Schema.is(ServerProviderUpdateError); | 34 | const isServerProviderUpdateError = Schema.is(ServerProviderUpdateError); |
| ... | @@ -239,7 +239,7 @@ const makeTestRunner = ( | ... | @@ -239,7 +239,7 @@ const makeTestRunner = ( |
| 239 | refreshInBackground: Effect.void, | 239 | refreshInBackground: Effect.void, |
| 240 | }), | 240 | }), |
| 241 | // Fresh per runner so a version cached by one test cannot leak into another. | 241 | // Fresh per runner so a version cached by one test cannot leak into another. |
| 242 | Layer.sync(ProviderVersionCache, () => new Map()), | 242 | ProviderLatestVersions.layer, |
| 243 | ), | 243 | ), |
| 244 | ), | 244 | ), |
| 245 | ), | 245 | ), |
apps/server/src/provider/providerMaintenanceRunner.ts+7-4| ... | @@ -33,8 +33,8 @@ import { | ... | @@ -33,8 +33,8 @@ import { |
| 33 | makeTargetedProviderUpdateAction, | 33 | makeTargetedProviderUpdateAction, |
| 34 | resolveLatestProviderVersion, | 34 | resolveLatestProviderVersion, |
| 35 | type ProviderMaintenanceCommandAction, | 35 | type ProviderMaintenanceCommandAction, |
| 36 | ProviderVersionCache, | ||
| 37 | } from "@t3tools/provider-core/server/maintenanceResolver"; | 36 | } from "@t3tools/provider-core/server/maintenanceResolver"; |
| 37 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 38 | import type { ProviderMaintenanceCapabilities } from "@t3tools/provider-core/server/maintenanceResolver"; | 38 | import type { ProviderMaintenanceCapabilities } from "@t3tools/provider-core/server/maintenanceResolver"; |
| 39 | import { collectUint8StreamText } from "@t3tools/provider-core/server/collectStreamText"; | 39 | import { collectUint8StreamText } from "@t3tools/provider-core/server/collectStreamText"; |
| 40 | const isServerProviderUpdateError = Schema.is(ServerProviderUpdateError); | 40 | const isServerProviderUpdateError = Schema.is(ServerProviderUpdateError); |
| ... | @@ -291,7 +291,7 @@ export const make = Effect.fn("ProviderMaintenanceRunner.make")(function* () { | ... | @@ -291,7 +291,7 @@ export const make = Effect.fn("ProviderMaintenanceRunner.make")(function* () { |
| 291 | const manifestService = yield* ModelManifest.ModelManifest; | 291 | const manifestService = yield* ModelManifest.ModelManifest; |
| 292 | const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; | 292 | const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; |
| 293 | const httpClient = yield* HttpClient.HttpClient; | 293 | const httpClient = yield* HttpClient.HttpClient; |
| 294 | const versionCache = yield* ProviderVersionCache; | 294 | const latestVersions = yield* ProviderLatestVersions.ProviderLatestVersions; |
| 295 | const runMaintenanceCommand = ( | 295 | const runMaintenanceCommand = ( |
| 296 | update: ProviderMaintenanceCommandAction, | 296 | update: ProviderMaintenanceCommandAction, |
| 297 | onProgress: (line: string) => Effect.Effect<void>, | 297 | onProgress: (line: string) => Effect.Effect<void>, |
| ... | @@ -356,7 +356,7 @@ export const make = Effect.fn("ProviderMaintenanceRunner.make")(function* () { | ... | @@ -356,7 +356,7 @@ export const make = Effect.fn("ProviderMaintenanceRunner.make")(function* () { |
| 356 | maintenanceCapabilities, | 356 | maintenanceCapabilities, |
| 357 | ).pipe( | 357 | ).pipe( |
| 358 | Effect.provideService(HttpClient.HttpClient, httpClient), | 358 | Effect.provideService(HttpClient.HttpClient, httpClient), |
| 359 | Effect.provideService(ProviderVersionCache, versionCache), | 359 | Effect.provideService(ProviderLatestVersions.ProviderLatestVersions, latestVersions), |
| 360 | ), | 360 | ), |
| 361 | { | 361 | { |
| 362 | concurrency: "unbounded", | 362 | concurrency: "unbounded", |
| ... | @@ -463,7 +463,10 @@ export const make = Effect.fn("ProviderMaintenanceRunner.make")(function* () { | ... | @@ -463,7 +463,10 @@ export const make = Effect.fn("ProviderMaintenanceRunner.make")(function* () { |
| 463 | targetVersion ?? | 463 | targetVersion ?? |
| 464 | (yield* resolveLatestProviderVersion(fresh).pipe( | 464 | (yield* resolveLatestProviderVersion(fresh).pipe( |
| 465 | Effect.provideService(HttpClient.HttpClient, httpClient), | 465 | Effect.provideService(HttpClient.HttpClient, httpClient), |
| 466 | Effect.provideService(ProviderVersionCache, versionCache), | 466 | Effect.provideService( |
| 467 | ProviderLatestVersions.ProviderLatestVersions, | ||
| 468 | latestVersions, | ||
| 469 | ), | ||
| 467 | )); | 470 | )); |
| 468 | const advisory = | 471 | const advisory = |
| 469 | resolveProviderCompatibility(manifest.compatibility, provider, candidateVersion) ?? | 472 | resolveProviderCompatibility(manifest.compatibility, provider, candidateVersion) ?? |
apps/server/src/server.ts+2| ... | @@ -44,6 +44,7 @@ import * as ProviderEventIngestor from "./orchestration-v2/ProviderEventIngestor | ... | @@ -44,6 +44,7 @@ import * as ProviderEventIngestor from "./orchestration-v2/ProviderEventIngestor |
| 44 | import * as ModelManifest from "./provider/ModelManifest.ts"; | 44 | import * as ModelManifest from "./provider/ModelManifest.ts"; |
| 45 | import * as ResetCreditCoordinator from "./provider/resetCreditCoordinator.ts"; | 45 | import * as ResetCreditCoordinator from "./provider/resetCreditCoordinator.ts"; |
| 46 | import * as EventNdjsonLogger from "./provider/EventNdjsonLogger.ts"; | 46 | import * as EventNdjsonLogger from "./provider/EventNdjsonLogger.ts"; |
| 47 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 47 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; | 48 | import * as OpenCodeRuntime from "@t3tools/provider-opencode/server/OpenCodeRuntime"; |
| 48 | import * as OpenCodeServerLedger from "@t3tools/provider-opencode/server/OpenCodeServerLedger"; | 49 | import * as OpenCodeServerLedger from "@t3tools/provider-opencode/server/OpenCodeServerLedger"; |
| 49 | import * as ProviderHostLive from "./provider/ProviderHostLive.ts"; | 50 | import * as ProviderHostLive from "./provider/ProviderHostLive.ts"; |
| ... | @@ -634,6 +635,7 @@ const layerRuntimeCoreDependencies = layerRuntimeCoreDependenciesBase.pipe( | ... | @@ -634,6 +635,7 @@ const layerRuntimeCoreDependencies = layerRuntimeCoreDependenciesBase.pipe( |
| 634 | layerProviderEventLoggers, | 635 | layerProviderEventLoggers, |
| 635 | ModelManifest.layerModelCatalog.pipe(Layer.provideMerge(ModelManifest.layer)), | 636 | ModelManifest.layerModelCatalog.pipe(Layer.provideMerge(ModelManifest.layer)), |
| 636 | ResetCreditCoordinator.layer, | 637 | ResetCreditCoordinator.layer, |
| 638 | ProviderLatestVersions.layer, | ||
| 637 | ), | 639 | ), |
| 638 | ), | 640 | ), |
| 639 | // `OpenCodeDriver.create()` yields `OpenCodeRuntime`; previously the old | 641 | // `OpenCodeDriver.create()` yields `OpenCodeRuntime`; previously the old |
apps/server/src/ws.ts+3-3| ... | @@ -168,7 +168,7 @@ import * as ProviderInstanceRegistry from "./provider/ProviderInstanceRegistry.t | ... | @@ -168,7 +168,7 @@ import * as ProviderInstanceRegistry from "./provider/ProviderInstanceRegistry.t |
| 168 | import * as AcpRegistrySupport from "@t3tools/provider-acp-registry/server/AcpRegistrySupport"; | 168 | import * as AcpRegistrySupport from "@t3tools/provider-acp-registry/server/AcpRegistrySupport"; |
| 169 | import * as AcpRegistryRuntimeCoordinator from "@t3tools/provider-acp-registry/server/AcpRegistryRuntimeCoordinator"; | 169 | import * as AcpRegistryRuntimeCoordinator from "@t3tools/provider-acp-registry/server/AcpRegistryRuntimeCoordinator"; |
| 170 | import * as ModelManifest from "./provider/ModelManifest.ts"; | 170 | import * as ModelManifest from "./provider/ModelManifest.ts"; |
| 171 | import * as ProviderMaintenance from "@t3tools/provider-core/server/maintenanceResolver"; | 171 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; |
| 172 | import * as ProviderMaintenanceRunner from "./provider/providerMaintenanceRunner.ts"; | 172 | import * as ProviderMaintenanceRunner from "./provider/providerMaintenanceRunner.ts"; |
| 173 | import * as ProviderAuthService from "./provider/ProviderAuthService.ts"; | 173 | import * as ProviderAuthService from "./provider/ProviderAuthService.ts"; |
| 174 | import { makeProviderInstallation } from "./provider/providerInstallation.ts"; | 174 | import { makeProviderInstallation } from "./provider/providerInstallation.ts"; |
| ... | @@ -1271,7 +1271,7 @@ const layerWsRpc = ( | ... | @@ -1271,7 +1271,7 @@ const layerWsRpc = ( |
| 1271 | const portDiscovery = yield* PortScanner.PortDiscovery; | 1271 | const portDiscovery = yield* PortScanner.PortDiscovery; |
| 1272 | const providerRegistry = yield* ProviderRegistry.ProviderRegistry; | 1272 | const providerRegistry = yield* ProviderRegistry.ProviderRegistry; |
| 1273 | const modelManifest = yield* ModelManifest.ModelManifest; | 1273 | const modelManifest = yield* ModelManifest.ModelManifest; |
| 1274 | const providerVersionCache = yield* ProviderMaintenance.ProviderVersionCache; | 1274 | const providerLatestVersions = yield* ProviderLatestVersions.ProviderLatestVersions; |
| 1275 | const providerInstances = yield* ProviderInstanceRegistry.ProviderInstanceRegistry; | 1275 | const providerInstances = yield* ProviderInstanceRegistry.ProviderInstanceRegistry; |
| 1276 | const acpRegistryCatalog = yield* AcpRegistrySupport.AcpRegistryCatalog; | 1276 | const acpRegistryCatalog = yield* AcpRegistrySupport.AcpRegistryCatalog; |
| 1277 | const acpRegistryRuntimeCoordinator = | 1277 | const acpRegistryRuntimeCoordinator = |
| ... | @@ -2193,7 +2193,7 @@ const layerWsRpc = ( | ... | @@ -2193,7 +2193,7 @@ const layerWsRpc = ( |
| 2193 | fresh: true, | 2193 | fresh: true, |
| 2194 | }); | 2194 | }); |
| 2195 | if (maintenance.packageName) | 2195 | if (maintenance.packageName) |
| 2196 | providerVersionCache.delete(maintenance.packageName); | 2196 | yield* providerLatestVersions.invalidate(maintenance.packageName); |
| 2197 | }), | 2197 | }), |
| 2198 | { concurrency: "unbounded", discard: true }, | 2198 | { concurrency: "unbounded", discard: true }, |
| 2199 | ); | 2199 | ); |
packages/provider-core/package.json+4| ... | @@ -115,6 +115,10 @@ | ... | @@ -115,6 +115,10 @@ |
| 115 | "types": "./src/server/ProviderHost.ts", | 115 | "types": "./src/server/ProviderHost.ts", |
| 116 | "import": "./src/server/ProviderHost.ts" | 116 | "import": "./src/server/ProviderHost.ts" |
| 117 | }, | 117 | }, |
| 118 | "./server/ProviderLatestVersions": { | ||
| 119 | "types": "./src/server/ProviderLatestVersions.ts", | ||
| 120 | "import": "./src/server/ProviderLatestVersions.ts" | ||
| 121 | }, | ||
| 118 | "./server/randomUuid": { | 122 | "./server/randomUuid": { |
| 119 | "types": "./src/server/randomUuid.ts", | 123 | "types": "./src/server/randomUuid.ts", |
| 120 | "import": "./src/server/randomUuid.ts" | 124 | "import": "./src/server/randomUuid.ts" |
packages/provider-core/src/server/ProviderLatestVersions.ts created+75| ... | @@ -0,0 +1,75 @@ | ||
| 1 | /** | ||
| 2 | * Memoizes "latest available version" lookups (npm registry, release | ||
| 3 | * channels) for the version advisory. One instance is shared by every driver | ||
| 4 | * and the maintenance runner, so a provider update can invalidate the entry | ||
| 5 | * the next snapshot refresh reads. | ||
| 6 | * | ||
| 7 | * @module provider-core/server/ProviderLatestVersions | ||
| 8 | */ | ||
| 9 | import * as Context from "effect/Context"; | ||
| 10 | import * as DateTime from "effect/DateTime"; | ||
| 11 | import * as Duration from "effect/Duration"; | ||
| 12 | import * as Effect from "effect/Effect"; | ||
| 13 | import * as Layer from "effect/Layer"; | ||
| 14 | import * as Ref from "effect/Ref"; | ||
| 15 | |||
| 16 | /** A found version stays fresh this long. */ | ||
| 17 | const FOUND_TTL = Duration.hours(1); | ||
| 18 | /** A failed lookup is retried sooner, so a flaky network does not hide an update for an hour. */ | ||
| 19 | const MISSING_TTL = Duration.minutes(1); | ||
| 20 | |||
| 21 | interface Entry { | ||
| 22 | readonly expiresAt: number; | ||
| 23 | readonly version: string | null; | ||
| 24 | } | ||
| 25 | |||
| 26 | export class ProviderLatestVersions extends Context.Service< | ||
| 27 | ProviderLatestVersions, | ||
| 28 | { | ||
| 29 | /** | ||
| 30 | * Returns the cached version for `key`, running `lookup` when there is no | ||
| 31 | * fresh entry or `fresh` is set. `null` means the lookup found nothing. | ||
| 32 | */ | ||
| 33 | readonly cached: <E, R>( | ||
| 34 | key: string, | ||
| 35 | lookup: Effect.Effect<string | null, E, R>, | ||
| 36 | options?: { readonly fresh?: boolean }, | ||
| 37 | ) => Effect.Effect<string | null, E, R>; | ||
| 38 | readonly invalidate: (key: string) => Effect.Effect<void>; | ||
| 39 | } | ||
| 40 | >()("@t3tools/provider-core/server/ProviderLatestVersions") {} | ||
| 41 | |||
| 42 | /** Starts from `seed`, for tests that need a cached entry. */ | ||
| 43 | export const make = (seed: Iterable<readonly [key: string, version: string | null]> = []) => | ||
| 44 | Effect.gen(function* () { | ||
| 45 | const entries = yield* Ref.make( | ||
| 46 | new Map<string, Entry>( | ||
| 47 | Array.from(seed, ([key, version]) => [ | ||
| 48 | key, | ||
| 49 | { version, expiresAt: Number.MAX_SAFE_INTEGER }, | ||
| 50 | ]), | ||
| 51 | ), | ||
| 52 | ); | ||
| 53 | return ProviderLatestVersions.of({ | ||
| 54 | cached: (key, lookup, options) => | ||
| 55 | Effect.gen(function* () { | ||
| 56 | const now = DateTime.toEpochMillis(yield* DateTime.now); | ||
| 57 | const existing = (yield* Ref.get(entries)).get(key); | ||
| 58 | if (!options?.fresh && existing && existing.expiresAt > now) return existing.version; | ||
| 59 | const version = yield* lookup; | ||
| 60 | const ttl = version === null ? MISSING_TTL : FOUND_TTL; | ||
| 61 | yield* Ref.update(entries, (current) => | ||
| 62 | new Map(current).set(key, { version, expiresAt: now + Duration.toMillis(ttl) }), | ||
| 63 | ); | ||
| 64 | return version; | ||
| 65 | }), | ||
| 66 | invalidate: (key) => | ||
| 67 | Ref.update(entries, (current) => { | ||
| 68 | const next = new Map(current); | ||
| 69 | next.delete(key); | ||
| 70 | return next; | ||
| 71 | }), | ||
| 72 | }); | ||
| 73 | }); | ||
| 74 | |||
| 75 | export const layer = Layer.effect(ProviderLatestVersions, make()); | ||
packages/provider-core/src/server/maintenanceResolver.test.ts+7-15| ... | @@ -15,6 +15,7 @@ import * as Sink from "effect/Sink"; | ... | @@ -15,6 +15,7 @@ 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 { HttpClient } from "effect/http"; |
| 17 | import { ChildProcessSpawner } from "effect/process"; | 17 | import { ChildProcessSpawner } from "effect/process"; |
| 18 | import * as ProviderLatestVersions from "./ProviderLatestVersions.ts"; | ||
| 18 | import { | 19 | import { |
| 19 | createProviderVersionAdvisory, | 20 | createProviderVersionAdvisory, |
| 20 | makeTargetedProviderUpdateAction, | 21 | makeTargetedProviderUpdateAction, |
| ... | @@ -26,7 +27,6 @@ import { | ... | @@ -26,7 +27,6 @@ import { |
| 26 | normalizeCommandPath, | 27 | normalizeCommandPath, |
| 27 | npmGlobalPrefixFromCommandPath, | 28 | npmGlobalPrefixFromCommandPath, |
| 28 | parseHomebrewLatestVersion, | 29 | parseHomebrewLatestVersion, |
| 29 | ProviderVersionCache, | ||
| 30 | resolveLatestProviderVersion, | 30 | resolveLatestProviderVersion, |
| 31 | resolvePackageManagedProviderMaintenance, | 31 | resolvePackageManagedProviderMaintenance, |
| 32 | resolveProviderMaintenanceCapabilitiesEffect, | 32 | resolveProviderMaintenanceCapabilitiesEffect, |
| ... | @@ -124,19 +124,11 @@ function stdoutSpawner(onSpawn: (command: string, args: ReadonlyArray<string>) = | ... | @@ -124,19 +124,11 @@ function stdoutSpawner(onSpawn: (command: string, args: ReadonlyArray<string>) = |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | it.layer(NodeServices.layer)("providerMaintenance", (it) => { | 126 | it.layer(NodeServices.layer)("providerMaintenance", (it) => { |
| 127 | it.effect("reads cached versions through the injectable cache reference", () => | 127 | it.effect("reads cached versions through ProviderLatestVersions", () => |
| 128 | resolveLatestProviderVersion(manualPackageTool).pipe( | 128 | resolveLatestProviderVersion(manualPackageTool).pipe( |
| 129 | Effect.provideService( | 129 | Effect.provideServiceEffect( |
| 130 | ProviderVersionCache, | 130 | ProviderLatestVersions.ProviderLatestVersions, |
| 131 | new Map([ | 131 | ProviderLatestVersions.make([["@example/package-tool", "9.9.9"]]), |
| 132 | [ | ||
| 133 | "@example/package-tool", | ||
| 134 | { | ||
| 135 | expiresAt: Number.MAX_SAFE_INTEGER, | ||
| 136 | version: "9.9.9", | ||
| 137 | }, | ||
| 138 | ], | ||
| 139 | ]), | ||
| 140 | ), | 132 | ), |
| 141 | Effect.provideService( | 133 | Effect.provideService( |
| 142 | HttpClient.HttpClient, | 134 | HttpClient.HttpClient, |
| ... | @@ -152,7 +144,7 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { | ... | @@ -152,7 +144,7 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { |
| 152 | 144 | ||
| 153 | it.effect("prefers the installer's own latest version over the npm registry", () => | 145 | it.effect("prefers the installer's own latest version over the npm registry", () => |
| 154 | resolveLatestProviderVersion({ ...manualPackageTool, latestVersion: "1.2.0" }).pipe( | 146 | resolveLatestProviderVersion({ ...manualPackageTool, latestVersion: "1.2.0" }).pipe( |
| 155 | Effect.provideService(ProviderVersionCache, new Map()), | 147 | Effect.provide(ProviderLatestVersions.layer), |
| 156 | Effect.provideService( | 148 | Effect.provideService( |
| 157 | HttpClient.HttpClient, | 149 | HttpClient.HttpClient, |
| 158 | HttpClient.make(() => | 150 | HttpClient.make(() => |
| ... | @@ -169,7 +161,7 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { | ... | @@ -169,7 +161,7 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { |
| 169 | enrichProviderSnapshotWithVersionAdvisory(installedPackageToolProvider, manualPackageTool, { | 161 | enrichProviderSnapshotWithVersionAdvisory(installedPackageToolProvider, manualPackageTool, { |
| 170 | enableProviderUpdateChecks: false, | 162 | enableProviderUpdateChecks: false, |
| 171 | }).pipe( | 163 | }).pipe( |
| 172 | Effect.provideService(ProviderVersionCache, new Map()), | 164 | Effect.provide(ProviderLatestVersions.layer), |
| 173 | Effect.provideService( | 165 | Effect.provideService( |
| 174 | HttpClient.HttpClient, | 166 | HttpClient.HttpClient, |
| 175 | HttpClient.make(() => | 167 | HttpClient.make(() => |
packages/provider-core/src/server/maintenanceResolver.ts+3-26| ... | @@ -17,7 +17,6 @@ import { causeErrorTag } from "@t3tools/shared/observability"; | ... | @@ -17,7 +17,6 @@ import { causeErrorTag } from "@t3tools/shared/observability"; |
| 17 | import { resolveCommandPath } from "@t3tools/shared/shell"; | 17 | import { resolveCommandPath } from "@t3tools/shared/shell"; |
| 18 | import * as Cache from "effect/Cache"; | 18 | import * as Cache from "effect/Cache"; |
| 19 | import * as Config from "effect/Config"; | 19 | import * as Config from "effect/Config"; |
| 20 | import * as Context from "effect/Context"; | ||
| 21 | import * as DateTime from "effect/DateTime"; | 20 | import * as DateTime from "effect/DateTime"; |
| 22 | import * as Duration from "effect/Duration"; | 21 | import * as Duration from "effect/Duration"; |
| 23 | import * as Effect from "effect/Effect"; | 22 | import * as Effect from "effect/Effect"; |
| ... | @@ -30,8 +29,8 @@ import { HttpClient, HttpClientRequest } from "effect/http"; | ... | @@ -30,8 +29,8 @@ import { HttpClient, HttpClientRequest } from "effect/http"; |
| 30 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 29 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; |
| 31 | 30 | ||
| 32 | import { collectUint8StreamText } from "./collectStreamText.ts"; | 31 | import { collectUint8StreamText } from "./collectStreamText.ts"; |
| 32 | import * as ProviderLatestVersions from "./ProviderLatestVersions.ts"; | ||
| 33 | 33 | ||
| 34 | const LATEST_VERSION_CACHE_TTL_MS = 60 * 60 * 1_000; | ||
| 35 | const LATEST_VERSION_TIMEOUT_MS = 4_000; | 34 | const LATEST_VERSION_TIMEOUT_MS = 4_000; |
| 36 | const HOMEBREW_INFO_TIMEOUT_MS = 10_000; | 35 | const HOMEBREW_INFO_TIMEOUT_MS = 10_000; |
| 37 | const HOMEBREW_INFO_MAX_BYTES = 256 * 1_024; | 36 | const HOMEBREW_INFO_MAX_BYTES = 256 * 1_024; |
| ... | @@ -102,17 +101,6 @@ export interface PackageManagedProviderMaintenanceDefinition { | ... | @@ -102,17 +101,6 @@ export interface PackageManagedProviderMaintenanceDefinition { |
| 102 | } | null; | 101 | } | null; |
| 103 | } | 102 | } |
| 104 | 103 | ||
| 105 | export interface ProviderVersionCacheEntry { | ||
| 106 | readonly expiresAt: number; | ||
| 107 | readonly version: string | null; | ||
| 108 | } | ||
| 109 | |||
| 110 | export const ProviderVersionCache = Context.Reference<Map<string, ProviderVersionCacheEntry>>( | ||
| 111 | "@t3tools/server/providerMaintenance/ProviderVersionCache", | ||
| 112 | { | ||
| 113 | defaultValue: () => new Map(), | ||
| 114 | }, | ||
| 115 | ); | ||
| 116 | const NpmLatestVersionResponse = Schema.Struct({ | 104 | const NpmLatestVersionResponse = Schema.Struct({ |
| 117 | version: Schema.optional(Schema.String), | 105 | version: Schema.optional(Schema.String), |
| 118 | }); | 106 | }); |
| ... | @@ -784,19 +772,8 @@ export const resolveLatestProviderVersion = Effect.fn("resolveLatestProviderVers | ... | @@ -784,19 +772,8 @@ export const resolveLatestProviderVersion = Effect.fn("resolveLatestProviderVers |
| 784 | return null; | 772 | return null; |
| 785 | } | 773 | } |
| 786 | 774 | ||
| 787 | const latestVersionCache = yield* ProviderVersionCache; | 775 | const latestVersions = yield* ProviderLatestVersions.ProviderLatestVersions; |
| 788 | const cached = latestVersionCache.get(packageName); | 776 | return yield* latestVersions.cached(packageName, fetchNpmLatestVersion(packageName)); |
| 789 | const now = DateTime.toEpochMillis(yield* DateTime.now); | ||
| 790 | if (cached && cached.expiresAt > now) { | ||
| 791 | return cached.version; | ||
| 792 | } | ||
| 793 | |||
| 794 | const version = yield* fetchNpmLatestVersion(packageName); | ||
| 795 | latestVersionCache.set(packageName, { | ||
| 796 | expiresAt: now + LATEST_VERSION_CACHE_TTL_MS, | ||
| 797 | version, | ||
| 798 | }); | ||
| 799 | return version; | ||
| 800 | }); | 777 | }); |
| 801 | 778 | ||
| 802 | export const enrichProviderSnapshotWithVersionAdvisory = Effect.fn( | 779 | export const enrichProviderSnapshotWithVersionAdvisory = Effect.fn( |
packages/provider-grok/src/server/driver.test.ts+2| ... | @@ -9,6 +9,7 @@ import * as Path from "effect/Path"; | ... | @@ -9,6 +9,7 @@ import * as Path from "effect/Path"; |
| 9 | import { HttpClient } from "effect/http"; | 9 | import { HttpClient } from "effect/http"; |
| 10 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; | 10 | import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; |
| 11 | 11 | ||
| 12 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 12 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; | 13 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; |
| 13 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 14 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; |
| 14 | import { GrokDriver } from "./driver.ts"; | 15 | import { GrokDriver } from "./driver.ts"; |
| ... | @@ -18,6 +19,7 @@ import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | ... | @@ -18,6 +19,7 @@ import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| 18 | const layerTest = layerTestProviderHost({ runBackgroundWork: false }).pipe( | 19 | const layerTest = layerTestProviderHost({ runBackgroundWork: false }).pipe( |
| 19 | Layer.provideMerge(NodeServices.layer), | 20 | Layer.provideMerge(NodeServices.layer), |
| 20 | Layer.provideMerge(IdAllocator.layer), | 21 | Layer.provideMerge(IdAllocator.layer), |
| 22 | Layer.provideMerge(ProviderLatestVersions.layer), | ||
| 21 | Layer.provideMerge( | 23 | Layer.provideMerge( |
| 22 | Layer.succeed( | 24 | Layer.succeed( |
| 23 | ProviderEventLoggers.ProviderEventLoggers, | 25 | ProviderEventLoggers.ProviderEventLoggers, |
packages/provider-grok/src/server/driver.ts+5-1| ... | @@ -8,6 +8,7 @@ import * as Schema from "effect/Schema"; | ... | @@ -8,6 +8,7 @@ import * as Schema from "effect/Schema"; |
| 8 | import { HttpClient } from "effect/http"; | 8 | import { HttpClient } from "effect/http"; |
| 9 | import { ChildProcessSpawner } from "effect/process"; | 9 | import { ChildProcessSpawner } from "effect/process"; |
| 10 | 10 | ||
| 11 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 11 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | 12 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; |
| 12 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; | 13 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; |
| 13 | import { makeGrokTextGeneration } from "./textGeneration.ts"; | 14 | import { makeGrokTextGeneration } from "./textGeneration.ts"; |
| ... | @@ -77,6 +78,7 @@ export type GrokDriverEnv = | ... | @@ -77,6 +78,7 @@ export type GrokDriverEnv = |
| 77 | | Crypto.Crypto | 78 | | Crypto.Crypto |
| 78 | | FileSystem.FileSystem | 79 | | FileSystem.FileSystem |
| 79 | | HttpClient.HttpClient | 80 | | HttpClient.HttpClient |
| 81 | | ProviderLatestVersions.ProviderLatestVersions | ||
| 80 | | Path.Path | 82 | | Path.Path |
| 81 | | ProviderEventLoggers.ProviderEventLoggers; | 83 | | ProviderEventLoggers.ProviderEventLoggers; |
| 82 | 84 | ||
| ... | @@ -93,6 +95,7 @@ export const GrokDriver: ProviderDriver<GrokSettings, GrokDriverEnv> = { | ... | @@ -93,6 +95,7 @@ export const GrokDriver: ProviderDriver<GrokSettings, GrokDriverEnv> = { |
| 93 | const crypto = yield* Crypto.Crypto; | 95 | const crypto = yield* Crypto.Crypto; |
| 94 | const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; | 96 | const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; |
| 95 | const httpClient = yield* HttpClient.HttpClient; | 97 | const httpClient = yield* HttpClient.HttpClient; |
| 98 | const latestVersions = yield* ProviderLatestVersions.ProviderLatestVersions; | ||
| 96 | const fileSystem = yield* FileSystem.FileSystem; | 99 | const fileSystem = yield* FileSystem.FileSystem; |
| 97 | const path = yield* Path.Path; | 100 | const path = yield* Path.Path; |
| 98 | const host = yield* ProviderHost.ProviderHost; | 101 | const host = yield* ProviderHost.ProviderHost; |
| ... | @@ -177,9 +180,10 @@ export const GrokDriver: ProviderDriver<GrokSettings, GrokDriverEnv> = { | ... | @@ -177,9 +180,10 @@ export const GrokDriver: ProviderDriver<GrokSettings, GrokDriverEnv> = { |
| 177 | maintenanceCapabilities, | 180 | maintenanceCapabilities, |
| 178 | enableProviderUpdateChecks: settings.enableProviderUpdateChecks, | 181 | enableProviderUpdateChecks: settings.enableProviderUpdateChecks, |
| 179 | publishSnapshot, | 182 | publishSnapshot, |
| 180 | httpClient, | ||
| 181 | }), | 183 | }), |
| 182 | ), | 184 | ), |
| 185 | Effect.provideService(HttpClient.HttpClient, httpClient), | ||
| 186 | Effect.provideService(ProviderLatestVersions.ProviderLatestVersions, latestVersions), | ||
| 183 | ), | 187 | ), |
| 184 | }).pipe( | 188 | }).pipe( |
| 185 | Effect.mapError( | 189 | Effect.mapError( |
packages/provider-grok/src/server/status.ts+6-3| ... | @@ -21,6 +21,7 @@ import { ChildProcess, ChildProcessSpawner } from "effect/process"; | ... | @@ -21,6 +21,7 @@ import { ChildProcess, ChildProcessSpawner } from "effect/process"; |
| 21 | import { createModelCapabilities } from "@t3tools/shared/model"; | 21 | import { createModelCapabilities } from "@t3tools/shared/model"; |
| 22 | import { resolveSpawnCommand } from "@t3tools/shared/shell"; | 22 | import { resolveSpawnCommand } from "@t3tools/shared/shell"; |
| 23 | 23 | ||
| 24 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 24 | import { | 25 | import { |
| 25 | AUTH_PROBE_TIMEOUT_MS, | 26 | AUTH_PROBE_TIMEOUT_MS, |
| 26 | buildServerProvider, | 27 | buildServerProvider, |
| ... | @@ -567,14 +568,16 @@ export const enrichGrokSnapshot = (input: { | ... | @@ -567,14 +568,16 @@ export const enrichGrokSnapshot = (input: { |
| 567 | readonly maintenanceCapabilities: ProviderMaintenanceCapabilities; | 568 | readonly maintenanceCapabilities: ProviderMaintenanceCapabilities; |
| 568 | readonly enableProviderUpdateChecks?: boolean; | 569 | readonly enableProviderUpdateChecks?: boolean; |
| 569 | readonly publishSnapshot: (snapshot: ServerProvider) => Effect.Effect<void>; | 570 | readonly publishSnapshot: (snapshot: ServerProvider) => Effect.Effect<void>; |
| 570 | readonly httpClient: HttpClient.HttpClient; | 571 | }): Effect.Effect< |
| 571 | }): Effect.Effect<void> => { | 572 | void, |
| 573 | never, | ||
| 574 | HttpClient.HttpClient | ProviderLatestVersions.ProviderLatestVersions | ||
| 575 | > => { | ||
| 572 | const { snapshot, publishSnapshot } = input; | 576 | const { snapshot, publishSnapshot } = input; |
| 573 | 577 | ||
| 574 | return enrichProviderSnapshotWithVersionAdvisory(snapshot, input.maintenanceCapabilities, { | 578 | return enrichProviderSnapshotWithVersionAdvisory(snapshot, input.maintenanceCapabilities, { |
| 575 | enableProviderUpdateChecks: input.enableProviderUpdateChecks, | 579 | enableProviderUpdateChecks: input.enableProviderUpdateChecks, |
| 576 | }).pipe( | 580 | }).pipe( |
| 577 | Effect.provideService(HttpClient.HttpClient, input.httpClient), | ||
| 578 | Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)), | 581 | Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)), |
| 579 | Effect.catchCause((cause) => | 582 | Effect.catchCause((cause) => |
| 580 | Effect.logWarning("Grok version advisory enrichment failed", { | 583 | Effect.logWarning("Grok version advisory enrichment failed", { |
packages/provider-muse/src/server/driver.ts+8| ... | @@ -8,6 +8,7 @@ import * as Schema from "effect/Schema"; | ... | @@ -8,6 +8,7 @@ import * as Schema from "effect/Schema"; |
| 8 | import { HttpClient } from "effect/http"; | 8 | import { HttpClient } from "effect/http"; |
| 9 | import { ChildProcessSpawner } from "effect/process"; | 9 | import { ChildProcessSpawner } from "effect/process"; |
| 10 | 10 | ||
| 11 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 11 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | 12 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; |
| 12 | import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; | 13 | import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; |
| 13 | import { makeMuseTextGeneration } from "./textGeneration.ts"; | 14 | import { makeMuseTextGeneration } from "./textGeneration.ts"; |
| ... | @@ -46,6 +47,7 @@ export type MuseDriverEnv = | ... | @@ -46,6 +47,7 @@ export type MuseDriverEnv = |
| 46 | | ChildProcessSpawner.ChildProcessSpawner | 47 | | ChildProcessSpawner.ChildProcessSpawner |
| 47 | | FileSystem.FileSystem | 48 | | FileSystem.FileSystem |
| 48 | | HttpClient.HttpClient | 49 | | HttpClient.HttpClient |
| 50 | | ProviderLatestVersions.ProviderLatestVersions | ||
| 49 | | Path.Path | 51 | | Path.Path |
| 50 | | ProviderEventLoggers.ProviderEventLoggers; | 52 | | ProviderEventLoggers.ProviderEventLoggers; |
| 51 | 53 | ||
| ... | @@ -60,6 +62,7 @@ export const MuseDriver: ProviderDriver<MuseSettings, MuseDriverEnv> = { | ... | @@ -60,6 +62,7 @@ export const MuseDriver: ProviderDriver<MuseSettings, MuseDriverEnv> = { |
| 60 | const fileSystem = yield* FileSystem.FileSystem; | 62 | const fileSystem = yield* FileSystem.FileSystem; |
| 61 | const path = yield* Path.Path; | 63 | const path = yield* Path.Path; |
| 62 | const httpClient = yield* HttpClient.HttpClient; | 64 | const httpClient = yield* HttpClient.HttpClient; |
| 65 | const latestVersions = yield* ProviderLatestVersions.ProviderLatestVersions; | ||
| 63 | const host = yield* ProviderHost.ProviderHost; | 66 | const host = yield* ProviderHost.ProviderHost; |
| 64 | const eventLoggers = yield* ProviderEventLoggers.ProviderEventLoggers; | 67 | const eventLoggers = yield* ProviderEventLoggers.ProviderEventLoggers; |
| 65 | const { cwd } = host.paths; | 68 | const { cwd } = host.paths; |
| ... | @@ -105,6 +108,10 @@ export const MuseDriver: ProviderDriver<MuseSettings, MuseDriverEnv> = { | ... | @@ -105,6 +108,10 @@ export const MuseDriver: ProviderDriver<MuseSettings, MuseDriverEnv> = { |
| 105 | const latestVersion = options?.fresh | 108 | const latestVersion = options?.fresh |
| 106 | ? yield* latestMuseVersion(processEnvironment, { fresh: true }).pipe( | 109 | ? yield* latestMuseVersion(processEnvironment, { fresh: true }).pipe( |
| 107 | Effect.provideService(HttpClient.HttpClient, httpClient), | 110 | Effect.provideService(HttpClient.HttpClient, httpClient), |
| 111 | Effect.provideService( | ||
| 112 | ProviderLatestVersions.ProviderLatestVersions, | ||
| 113 | latestVersions, | ||
| 114 | ), | ||
| 108 | ) | 115 | ) |
| 109 | : undefined; | 116 | : undefined; |
| 110 | return latestVersion !== undefined ? { ...capabilities, latestVersion } : capabilities; | 117 | return latestVersion !== undefined ? { ...capabilities, latestVersion } : capabilities; |
| ... | @@ -133,6 +140,7 @@ export const MuseDriver: ProviderDriver<MuseSettings, MuseDriverEnv> = { | ... | @@ -133,6 +140,7 @@ export const MuseDriver: ProviderDriver<MuseSettings, MuseDriverEnv> = { |
| 133 | }), | 140 | }), |
| 134 | ), | 141 | ), |
| 135 | Effect.provideService(HttpClient.HttpClient, httpClient), | 142 | Effect.provideService(HttpClient.HttpClient, httpClient), |
| 143 | Effect.provideService(ProviderLatestVersions.ProviderLatestVersions, latestVersions), | ||
| 136 | Effect.flatMap(publishSnapshot), | 144 | Effect.flatMap(publishSnapshot), |
| 137 | ), | 145 | ), |
| 138 | }).pipe( | 146 | }).pipe( |
packages/provider-muse/src/server/maintenance.test.ts+7-8| ... | @@ -12,10 +12,8 @@ import { | ... | @@ -12,10 +12,8 @@ import { |
| 12 | latestMuseVersion, | 12 | latestMuseVersion, |
| 13 | parseMuseVersion, | 13 | parseMuseVersion, |
| 14 | } from "./maintenance.ts"; | 14 | } from "./maintenance.ts"; |
| 15 | import { | 15 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; |
| 16 | ProviderVersionCache, | 16 | import { makeManualOnlyProviderMaintenanceCapabilities } from "@t3tools/provider-core/server/maintenanceResolver"; |
| 17 | makeManualOnlyProviderMaintenanceCapabilities, | ||
| 18 | } from "@t3tools/provider-core/server/maintenanceResolver"; | ||
| 19 | 17 | ||
| 20 | const maintenanceCapabilities = { | 18 | const maintenanceCapabilities = { |
| 21 | ...makeManualOnlyProviderMaintenanceCapabilities({ | 19 | ...makeManualOnlyProviderMaintenanceCapabilities({ |
| ... | @@ -50,7 +48,7 @@ it.layer(NodeServices.layer)("Muse maintenance", (it) => { | ... | @@ -50,7 +48,7 @@ it.layer(NodeServices.layer)("Muse maintenance", (it) => { |
| 50 | expect(yield* latestMuseVersion({}, { fresh: true })).toBe("1.1.1-R10.1"); | 48 | expect(yield* latestMuseVersion({}, { fresh: true })).toBe("1.1.1-R10.1"); |
| 51 | }); | 49 | }); |
| 52 | yield* check.pipe( | 50 | yield* check.pipe( |
| 53 | Effect.provideService(ProviderVersionCache, new Map()), | 51 | Effect.provide(ProviderLatestVersions.layer), |
| 54 | Effect.provideService( | 52 | Effect.provideService( |
| 55 | HttpClient.HttpClient, | 53 | HttpClient.HttpClient, |
| 56 | HttpClient.make((request) => { | 54 | HttpClient.make((request) => { |
| ... | @@ -101,7 +99,7 @@ it.layer(NodeServices.layer)("Muse maintenance", (it) => { | ... | @@ -101,7 +99,7 @@ it.layer(NodeServices.layer)("Muse maintenance", (it) => { |
| 101 | }); | 99 | }); |
| 102 | const [first, second] = yield* Effect.all([check, check], { concurrency: 1 }).pipe( | 100 | const [first, second] = yield* Effect.all([check, check], { concurrency: 1 }).pipe( |
| 103 | Effect.provideService(HttpClient.HttpClient, httpClient), | 101 | Effect.provideService(HttpClient.HttpClient, httpClient), |
| 104 | Effect.provideService(ProviderVersionCache, new Map()), | 102 | Effect.provide(ProviderLatestVersions.layer), |
| 105 | ); | 103 | ); |
| 106 | expect(first.versionAdvisory).toMatchObject({ | 104 | expect(first.versionAdvisory).toMatchObject({ |
| 107 | status: "behind_latest", | 105 | status: "behind_latest", |
| ... | @@ -134,7 +132,7 @@ it.layer(NodeServices.layer)("Muse maintenance", (it) => { | ... | @@ -134,7 +132,7 @@ it.layer(NodeServices.layer)("Muse maintenance", (it) => { |
| 134 | ), | 132 | ), |
| 135 | ), | 133 | ), |
| 136 | ), | 134 | ), |
| 137 | Effect.provideService(ProviderVersionCache, new Map()), | 135 | Effect.provide(ProviderLatestVersions.layer), |
| 138 | ); | 136 | ); |
| 139 | expect(result.versionAdvisory?.status).toBe(status); | 137 | expect(result.versionAdvisory?.status).toBe(status); |
| 140 | } | 138 | } |
| ... | @@ -153,6 +151,7 @@ it.layer(NodeServices.layer)("Muse maintenance", (it) => { | ... | @@ -153,6 +151,7 @@ it.layer(NodeServices.layer)("Muse maintenance", (it) => { |
| 153 | maintenanceCapabilities, | 151 | maintenanceCapabilities, |
| 154 | environment: {}, | 152 | environment: {}, |
| 155 | }).pipe( | 153 | }).pipe( |
| 154 | Effect.provide(ProviderLatestVersions.layer), | ||
| 156 | Effect.provideService( | 155 | Effect.provideService( |
| 157 | HttpClient.HttpClient, | 156 | HttpClient.HttpClient, |
| 158 | HttpClient.make(() => Effect.die("Unexpected release request")), | 157 | HttpClient.make(() => Effect.die("Unexpected release request")), |
| ... | @@ -182,7 +181,7 @@ it.layer(NodeServices.layer)("Muse maintenance", (it) => { | ... | @@ -182,7 +181,7 @@ it.layer(NodeServices.layer)("Muse maintenance", (it) => { |
| 182 | Effect.succeed(HttpClientResponse.fromWeb(request, response)), | 181 | Effect.succeed(HttpClientResponse.fromWeb(request, response)), |
| 183 | ), | 182 | ), |
| 184 | ), | 183 | ), |
| 185 | Effect.provideService(ProviderVersionCache, new Map()), | 184 | Effect.provide(ProviderLatestVersions.layer), |
| 186 | ); | 185 | ); |
| 187 | expect(result.status).toBe("ready"); | 186 | expect(result.status).toBe("ready"); |
| 188 | expect(result.versionAdvisory?.status).toBe("unknown"); | 187 | expect(result.versionAdvisory?.status).toBe("unknown"); |
packages/provider-muse/src/server/maintenance.ts+16-19| ... | @@ -1,6 +1,5 @@ | ... | @@ -1,6 +1,5 @@ |
| 1 | import { ProviderDriverKind, type ServerProvider } from "@t3tools/contracts"; | 1 | import { ProviderDriverKind, type ServerProvider } from "@t3tools/contracts"; |
| 2 | import { compareSemverVersions } from "@t3tools/shared/semver"; | 2 | import { compareSemverVersions } from "@t3tools/shared/semver"; |
| 3 | import * as DateTime from "effect/DateTime"; | ||
| 4 | import * as Effect from "effect/Effect"; | 3 | import * as Effect from "effect/Effect"; |
| 5 | import * as FileSystem from "effect/FileSystem"; | 4 | import * as FileSystem from "effect/FileSystem"; |
| 6 | import * as Schema from "effect/Schema"; | 5 | import * as Schema from "effect/Schema"; |
| ... | @@ -10,10 +9,10 @@ import { | ... | @@ -10,10 +9,10 @@ import { |
| 10 | enrichProviderSnapshotWithVersionAdvisory, | 9 | enrichProviderSnapshotWithVersionAdvisory, |
| 11 | makeManualOnlyProviderMaintenanceCapabilities, | 10 | makeManualOnlyProviderMaintenanceCapabilities, |
| 12 | makeProviderMaintenanceCapabilities, | 11 | makeProviderMaintenanceCapabilities, |
| 13 | ProviderVersionCache, | ||
| 14 | type ProviderMaintenanceCapabilities, | 12 | type ProviderMaintenanceCapabilities, |
| 15 | type ProviderMaintenanceCapabilitiesResolver, | 13 | type ProviderMaintenanceCapabilitiesResolver, |
| 16 | } from "@t3tools/provider-core/server/maintenanceResolver"; | 14 | } from "@t3tools/provider-core/server/maintenanceResolver"; |
| 15 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 17 | import { parseGenericCliVersion } from "@t3tools/provider-core/server/snapshotProbe"; | 16 | import { parseGenericCliVersion } from "@t3tools/provider-core/server/snapshotProbe"; |
| 18 | 17 | ||
| 19 | const DRIVER = ProviderDriverKind.make("muse"); | 18 | const DRIVER = ProviderDriverKind.make("muse"); |
| ... | @@ -97,26 +96,24 @@ export const latestMuseVersion = Effect.fn("latestMuseVersion")(function* ( | ... | @@ -97,26 +96,24 @@ export const latestMuseVersion = Effect.fn("latestMuseVersion")(function* ( |
| 97 | const channel = environment.MUSE_CHANNEL || "muse-stable"; | 96 | const channel = environment.MUSE_CHANNEL || "muse-stable"; |
| 98 | if (!MUSE_CHANNELS.has(channel)) return null; | 97 | if (!MUSE_CHANNELS.has(channel)) return null; |
| 99 | const channelUrl = `https://api.meta.ai/muse-code/channels/${channel}`; | 98 | const channelUrl = `https://api.meta.ai/muse-code/channels/${channel}`; |
| 100 | const cache = yield* ProviderVersionCache; | ||
| 101 | const key = `muse:${channelUrl}`; | ||
| 102 | const now = DateTime.toEpochMillis(yield* DateTime.now); | ||
| 103 | const cached = cache.get(key); | ||
| 104 | if (!options?.fresh && cached && cached.expiresAt > now) return cached.version; | ||
| 105 | const client = yield* HttpClient.HttpClient; | 99 | const client = yield* HttpClient.HttpClient; |
| 106 | const version = yield* client.execute(HttpClientRequest.get(channelUrl)).pipe( | 100 | const latestVersions = yield* ProviderLatestVersions.ProviderLatestVersions; |
| 107 | Effect.flatMap((response) => | 101 | return yield* latestVersions.cached( |
| 108 | response.status >= 200 && response.status < 300 | 102 | `muse:${channelUrl}`, |
| 109 | ? response.json.pipe( | 103 | client.execute(HttpClientRequest.get(channelUrl)).pipe( |
| 110 | Effect.flatMap(Schema.decodeUnknownEffect(ChannelManifest)), | 104 | Effect.flatMap((response) => |
| 111 | Effect.map((manifest) => parseMuseVersion(manifest.version)), | 105 | response.status >= 200 && response.status < 300 |
| 112 | ) | 106 | ? response.json.pipe( |
| 113 | : Effect.succeed(null), | 107 | Effect.flatMap(Schema.decodeUnknownEffect(ChannelManifest)), |
| 108 | Effect.map((manifest) => parseMuseVersion(manifest.version)), | ||
| 109 | ) | ||
| 110 | : Effect.succeed(null), | ||
| 111 | ), | ||
| 112 | Effect.timeout(4_000), | ||
| 113 | Effect.orElseSucceed(() => null), | ||
| 114 | ), | 114 | ), |
| 115 | Effect.timeout(4_000), | 115 | options, |
| 116 | Effect.orElseSucceed(() => null), | ||
| 117 | ); | 116 | ); |
| 118 | cache.set(key, { version, expiresAt: now + (version === null ? 60_000 : 60 * 60 * 1_000) }); | ||
| 119 | return version; | ||
| 120 | }); | 117 | }); |
| 121 | 118 | ||
| 122 | /** Feed Muse's release channel into the same advisory and notification flow as other drivers. */ | 119 | /** Feed Muse's release channel into the same advisory and notification flow as other drivers. */ |
packages/provider-opencode/src/server/driver.test.ts+3| ... | @@ -15,6 +15,7 @@ import * as TestClock from "effect/testing/TestClock"; | ... | @@ -15,6 +15,7 @@ import * as TestClock from "effect/testing/TestClock"; |
| 15 | import { HttpClient } from "effect/http"; | 15 | import { HttpClient } from "effect/http"; |
| 16 | import { ChildProcessSpawner } from "effect/process"; | 16 | import { ChildProcessSpawner } from "effect/process"; |
| 17 | 17 | ||
| 18 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 18 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 19 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| 19 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; | 20 | import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; |
| 20 | import * as ProviderMaintenance from "@t3tools/provider-core/server/maintenanceResolver"; | 21 | import * as ProviderMaintenance from "@t3tools/provider-core/server/maintenanceResolver"; |
| ... | @@ -48,6 +49,7 @@ const openCode2Runtime = { | ... | @@ -48,6 +49,7 @@ const openCode2Runtime = { |
| 48 | 49 | ||
| 49 | const layer = Layer.mergeAll( | 50 | const layer = Layer.mergeAll( |
| 50 | IdAllocator.layer, | 51 | IdAllocator.layer, |
| 52 | ProviderLatestVersions.layer, | ||
| 51 | layerTestProviderHost(), | 53 | layerTestProviderHost(), |
| 52 | Layer.succeed( | 54 | Layer.succeed( |
| 53 | ProviderEventLoggers.ProviderEventLoggers, | 55 | ProviderEventLoggers.ProviderEventLoggers, |
| ... | @@ -210,6 +212,7 @@ const changingRuntime = { | ... | @@ -210,6 +212,7 @@ const changingRuntime = { |
| 210 | } as unknown as OpenCodeRuntime.OpenCodeRuntimeShape; | 212 | } as unknown as OpenCodeRuntime.OpenCodeRuntimeShape; |
| 211 | const layerUpdate = Layer.mergeAll( | 213 | const layerUpdate = Layer.mergeAll( |
| 212 | IdAllocator.layer, | 214 | IdAllocator.layer, |
| 215 | ProviderLatestVersions.layer, | ||
| 213 | layerTestProviderHost(), | 216 | layerTestProviderHost(), |
| 214 | Layer.succeed( | 217 | Layer.succeed( |
| 215 | ProviderEventLoggers.ProviderEventLoggers, | 218 | ProviderEventLoggers.ProviderEventLoggers, |
packages/provider-opencode/src/server/driver.ts+4| ... | @@ -27,6 +27,7 @@ import { ChildProcessSpawner } from "effect/process"; | ... | @@ -27,6 +27,7 @@ import { ChildProcessSpawner } from "effect/process"; |
| 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"; |
| 30 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 30 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | 31 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; |
| 31 | import * as OpenCodeAdapterV2 from "./adapter.ts"; | 32 | import * as OpenCodeAdapterV2 from "./adapter.ts"; |
| 32 | import * as OpenCode2AdapterV2 from "./v2/adapter.ts"; | 33 | import * as OpenCode2AdapterV2 from "./v2/adapter.ts"; |
| ... | @@ -177,6 +178,7 @@ export type OpenCodeDriverEnv = | ... | @@ -177,6 +178,7 @@ export type OpenCodeDriverEnv = |
| 177 | | Crypto.Crypto | 178 | | Crypto.Crypto |
| 178 | | FileSystem.FileSystem | 179 | | FileSystem.FileSystem |
| 179 | | HttpClient.HttpClient | 180 | | HttpClient.HttpClient |
| 181 | | ProviderLatestVersions.ProviderLatestVersions | ||
| 180 | | OpenCodeRuntime.OpenCodeRuntime | 182 | | OpenCodeRuntime.OpenCodeRuntime |
| 181 | | Path.Path; | 183 | | Path.Path; |
| 182 | 184 | ||
| ... | @@ -195,6 +197,7 @@ export const OpenCodeDriver: ProviderDriver<OpenCodeSettings, OpenCodeDriverEnv> | ... | @@ -195,6 +197,7 @@ export const OpenCodeDriver: ProviderDriver<OpenCodeSettings, OpenCodeDriverEnv> |
| 195 | const pathService = yield* Path.Path; | 197 | const pathService = yield* Path.Path; |
| 196 | const openCodeRuntime = yield* OpenCodeRuntime.OpenCodeRuntime; | 198 | const openCodeRuntime = yield* OpenCodeRuntime.OpenCodeRuntime; |
| 197 | const httpClient = yield* HttpClient.HttpClient; | 199 | const httpClient = yield* HttpClient.HttpClient; |
| 200 | const latestVersions = yield* ProviderLatestVersions.ProviderLatestVersions; | ||
| 198 | const crypto = yield* Crypto.Crypto; | 201 | const crypto = yield* Crypto.Crypto; |
| 199 | const host = yield* ProviderHost.ProviderHost; | 202 | const host = yield* ProviderHost.ProviderHost; |
| 200 | const processEnv = mergeProviderInstanceEnvironment(environment); | 203 | const processEnv = mergeProviderInstanceEnvironment(environment); |
| ... | @@ -465,6 +468,7 @@ export const OpenCodeDriver: ProviderDriver<OpenCodeSettings, OpenCodeDriverEnv> | ... | @@ -465,6 +468,7 @@ export const OpenCodeDriver: ProviderDriver<OpenCodeSettings, OpenCodeDriverEnv> |
| 465 | }), | 468 | }), |
| 466 | ), | 469 | ), |
| 467 | Effect.provideService(HttpClient.HttpClient, httpClient), | 470 | Effect.provideService(HttpClient.HttpClient, httpClient), |
| 471 | Effect.provideService(ProviderLatestVersions.ProviderLatestVersions, latestVersions), | ||
| 468 | Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)), | 472 | Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)), |
| 469 | ), | 473 | ), |
| 470 | }, | 474 | }, |
packages/provider-pi/src/server/driver.test.ts+2| ... | @@ -13,6 +13,7 @@ import * as TestClock from "effect/testing/TestClock"; | ... | @@ -13,6 +13,7 @@ import * as TestClock from "effect/testing/TestClock"; |
| 13 | import { HttpClient } from "effect/http"; | 13 | import { HttpClient } from "effect/http"; |
| 14 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; | 14 | import { ChildProcess, ChildProcessSpawner } from "effect/process"; |
| 15 | 15 | ||
| 16 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 16 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; | 17 | import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator"; |
| 17 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; | 18 | import { layerTestProviderHost } from "@t3tools/provider-testing/host"; |
| 18 | import type { PiSettings } from "../settings.ts"; | 19 | import type { PiSettings } from "../settings.ts"; |
| ... | @@ -25,6 +26,7 @@ const layerTest = Layer.mergeAll( | ... | @@ -25,6 +26,7 @@ const layerTest = Layer.mergeAll( |
| 25 | runBackgroundWork: false, | 26 | runBackgroundWork: false, |
| 26 | }), | 27 | }), |
| 27 | IdAllocator.layer, | 28 | IdAllocator.layer, |
| 29 | ProviderLatestVersions.layer, | ||
| 28 | Layer.succeed( | 30 | Layer.succeed( |
| 29 | HttpClient.HttpClient, | 31 | HttpClient.HttpClient, |
| 30 | HttpClient.make(() => Effect.die("Unexpected HTTP")), | 32 | HttpClient.make(() => Effect.die("Unexpected HTTP")), |
packages/provider-pi/src/server/driver.ts+5-1| ... | @@ -15,6 +15,7 @@ import * as Schema from "effect/Schema"; | ... | @@ -15,6 +15,7 @@ import * as Schema from "effect/Schema"; |
| 15 | import { HttpClient } from "effect/http"; | 15 | import { HttpClient } from "effect/http"; |
| 16 | import { ChildProcessSpawner } from "effect/process"; | 16 | import { ChildProcessSpawner } from "effect/process"; |
| 17 | 17 | ||
| 18 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 18 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; | 19 | import * as ProviderHost from "@t3tools/provider-core/server/ProviderHost"; |
| 19 | import { makePiTextGeneration } from "./textGeneration.ts"; | 20 | import { makePiTextGeneration } from "./textGeneration.ts"; |
| 20 | import { PiAdapterV2Driver, type PiAdapterV2DriverEnv } from "./adapter.ts"; | 21 | import { PiAdapterV2Driver, type PiAdapterV2DriverEnv } from "./adapter.ts"; |
| ... | @@ -60,6 +61,7 @@ export type PiDriverEnv = | ... | @@ -60,6 +61,7 @@ export type PiDriverEnv = |
| 60 | | ChildProcessSpawner.ChildProcessSpawner | 61 | | ChildProcessSpawner.ChildProcessSpawner |
| 61 | | FileSystem.FileSystem | 62 | | FileSystem.FileSystem |
| 62 | | HttpClient.HttpClient | 63 | | HttpClient.HttpClient |
| 64 | | ProviderLatestVersions.ProviderLatestVersions | ||
| 63 | | Path.Path; | 65 | | Path.Path; |
| 64 | 66 | ||
| 65 | const withInstanceIdentity = | 67 | const withInstanceIdentity = |
| ... | @@ -92,6 +94,7 @@ export const PiDriver: ProviderDriver<PiSettings, PiDriverEnv> = { | ... | @@ -92,6 +94,7 @@ export const PiDriver: ProviderDriver<PiSettings, PiDriverEnv> = { |
| 92 | const fileSystem = yield* FileSystem.FileSystem; | 94 | const fileSystem = yield* FileSystem.FileSystem; |
| 93 | const pathService = yield* Path.Path; | 95 | const pathService = yield* Path.Path; |
| 94 | const httpClient = yield* HttpClient.HttpClient; | 96 | const httpClient = yield* HttpClient.HttpClient; |
| 97 | const latestVersions = yield* ProviderLatestVersions.ProviderLatestVersions; | ||
| 95 | const host = yield* ProviderHost.ProviderHost; | 98 | const host = yield* ProviderHost.ProviderHost; |
| 96 | const { cwd } = host.paths; | 99 | const { cwd } = host.paths; |
| 97 | const processEnv = mergeProviderInstanceEnvironment(environment); | 100 | const processEnv = mergeProviderInstanceEnvironment(environment); |
| ... | @@ -159,9 +162,10 @@ export const PiDriver: ProviderDriver<PiSettings, PiDriverEnv> = { | ... | @@ -159,9 +162,10 @@ export const PiDriver: ProviderDriver<PiSettings, PiDriverEnv> = { |
| 159 | maintenanceCapabilities, | 162 | maintenanceCapabilities, |
| 160 | enableProviderUpdateChecks: settings.enableProviderUpdateChecks, | 163 | enableProviderUpdateChecks: settings.enableProviderUpdateChecks, |
| 161 | publishSnapshot, | 164 | publishSnapshot, |
| 162 | httpClient, | ||
| 163 | }), | 165 | }), |
| 164 | ), | 166 | ), |
| 167 | Effect.provideService(HttpClient.HttpClient, httpClient), | ||
| 168 | Effect.provideService(ProviderLatestVersions.ProviderLatestVersions, latestVersions), | ||
| 165 | ), | 169 | ), |
| 166 | }).pipe( | 170 | }).pipe( |
| 167 | Effect.mapError( | 171 | Effect.mapError( |
packages/provider-pi/src/server/status.ts+6-3| ... | @@ -34,6 +34,7 @@ import { | ... | @@ -34,6 +34,7 @@ import { |
| 34 | piRecordField as recordField, | 34 | piRecordField as recordField, |
| 35 | piRecordString as recordString, | 35 | piRecordString as recordString, |
| 36 | } from "./rpc.ts"; | 36 | } from "./rpc.ts"; |
| 37 | import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; | ||
| 37 | import { | 38 | import { |
| 38 | buildServerProvider, | 39 | buildServerProvider, |
| 39 | isCommandMissingCause, | 40 | isCommandMissingCause, |
| ... | @@ -461,13 +462,15 @@ export const enrichPiSnapshot = (input: { | ... | @@ -461,13 +462,15 @@ export const enrichPiSnapshot = (input: { |
| 461 | readonly maintenanceCapabilities: ProviderMaintenanceCapabilities; | 462 | readonly maintenanceCapabilities: ProviderMaintenanceCapabilities; |
| 462 | readonly enableProviderUpdateChecks?: boolean; | 463 | readonly enableProviderUpdateChecks?: boolean; |
| 463 | readonly publishSnapshot: (snapshot: ServerProvider) => Effect.Effect<void>; | 464 | readonly publishSnapshot: (snapshot: ServerProvider) => Effect.Effect<void>; |
| 464 | readonly httpClient: HttpClient.HttpClient; | 465 | }): Effect.Effect< |
| 465 | }): Effect.Effect<void> => { | 466 | void, |
| 467 | never, | ||
| 468 | HttpClient.HttpClient | ProviderLatestVersions.ProviderLatestVersions | ||
| 469 | > => { | ||
| 466 | const { snapshot, publishSnapshot } = input; | 470 | const { snapshot, publishSnapshot } = input; |
| 467 | return enrichProviderSnapshotWithVersionAdvisory(snapshot, input.maintenanceCapabilities, { | 471 | return enrichProviderSnapshotWithVersionAdvisory(snapshot, input.maintenanceCapabilities, { |
| 468 | enableProviderUpdateChecks: input.enableProviderUpdateChecks, | 472 | enableProviderUpdateChecks: input.enableProviderUpdateChecks, |
| 469 | }).pipe( | 473 | }).pipe( |
| 470 | Effect.provideService(HttpClient.HttpClient, input.httpClient), | ||
| 471 | Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)), | 474 | Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)), |
| 472 | Effect.catchCause((cause) => | 475 | Effect.catchCause((cause) => |
| 473 | Effect.logWarning("Pi version advisory enrichment failed", { | 476 | Effect.logWarning("Pi version advisory enrichment failed", { |