@@ -19,6 +19,7 @@ import {
1919 type ProviderDriverKind ,
2020 type ServerProviderModel ,
2121} from "@t3tools/contracts" ;
22+ import { cliReleaseChannelOf } from "@t3tools/shared/cliRelease" ;
2223import { codexModelFamily } from "@t3tools/shared/model" ;
2324import * as Clock from "effect/Clock" ;
2425import * as Context from "effect/Context" ;
@@ -30,6 +31,7 @@ import * as Schema from "effect/Schema";
3031import * as Semaphore from "effect/Semaphore" ;
3132import { HttpClient , HttpClientResponse } from "effect/unstable/http" ;
3233
34+ import packageJson from "../../package.json" with { type : "json" } ;
3335import { ServerConfig } from "../config.ts" ;
3436import * as ServerSettings from "../serverSettings.ts" ;
3537import { hasValidClaudeManifestAdapters } from "./ClaudeModelManifest.ts" ;
@@ -140,6 +142,25 @@ const decodeManifest = Schema.decodeUnknownEffect(ModelManifestSchema);
140142export const BUNDLED_MODEL_MANIFEST : ModelManifestData =
141143 Schema . decodeUnknownSync ( ModelManifestSchema ) ( bundledManifestJson ) ;
142144
145+ /**
146+ * TEMPORARY V2 preview stopgap. Revert before V2 merges into main; it is on
147+ * #2829's "Revert before merging into main" checklist.
148+ *
149+ * The fetched manifest is `main`'s, and its compatibility policy is written for
150+ * stable and nightly builds, which do not run OpenCode 2. A policy's
151+ * `t3CodeRange` cannot single out preview builds because range matching drops
152+ * prerelease tags. Preview builds therefore keep the compatibility policy they
153+ * shipped with and take everything else from the fetched manifest.
154+ */
155+ function withPreviewCompatibility (
156+ manifest : ModelManifestData ,
157+ t3CodeVersion : string ,
158+ ) : ModelManifestData {
159+ return cliReleaseChannelOf ( t3CodeVersion ) === "preview"
160+ ? { ...manifest , compatibility : BUNDLED_MODEL_MANIFEST . compatibility }
161+ : manifest ;
162+ }
163+
143164/** Epoch millis of the manifest's `updatedAt`, or 0 when absent or unparsable. */
144165function manifestUpdatedAtMs ( manifest : ModelManifestData ) : number {
145166 if ( manifest . updatedAt === undefined ) return 0 ;
@@ -336,7 +357,8 @@ const BundledOnlyModelManifest: ModelManifest["Service"] = {
336357
337358export const layerTest = Layer . succeed ( ModelManifest , BundledOnlyModelManifest ) ;
338359
339- export const make = Effect . gen ( function * ( ) {
360+ /** `make` for a given T3 Code version, so tests can exercise each release channel. */
361+ export const makeForVersion = Effect . fnUntraced ( function * ( t3CodeVersion : string ) {
340362 const fileSystem = yield * FileSystem . FileSystem ;
341363 const path = yield * Path . Path ;
342364 const config = yield * ServerConfig ;
@@ -369,7 +391,7 @@ export const make = Effect.gen(function* () {
369391 if ( manifestUpdatedAtMs ( BUNDLED_MODEL_MANIFEST ) > manifestUpdatedAtMs ( fromDisk . manifest ) ) {
370392 return ;
371393 }
372- manifest = fromDisk . manifest ;
394+ manifest = withPreviewCompatibility ( fromDisk . manifest , t3CodeVersion ) ;
373395 fetchedAtMs = fromDisk . fetchedAtMs ;
374396 } ) ,
375397 ) ;
@@ -408,7 +430,7 @@ export const make = Effect.gen(function* () {
408430 return manifest ;
409431 }
410432
411- manifest = fetched ;
433+ manifest = withPreviewCompatibility ( fetched , t3CodeVersion ) ;
412434 fetchedAtMs = now ;
413435 yield * encodeManifestCache ( { fetchedAtMs : now , manifest : fetched } ) . pipe (
414436 Effect . flatMap ( ( serialized ) => fileSystem . writeFileString ( cachePath , serialized ) ) ,
@@ -427,4 +449,6 @@ export const make = Effect.gen(function* () {
427449 } ) ;
428450} ) ;
429451
452+ export const make = makeForVersion ( packageJson . version ) ;
453+
430454export const layer = Layer . effect ( ModelManifest , make ) ;
0 commit comments