Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 0 additions & 57 deletions apps/server/src/provider/ModelManifest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { HttpClient, HttpClientResponse } from "effect/unstable/http";
import * as ServerConfig from "../config.ts";
import * as ServerSettings from "../serverSettings.ts";
import * as ModelManifest from "./ModelManifest.ts";
import { resolveProviderCompatibility } from "./providerCompatibility.ts";

/**
* Test policy: this file covers manifest machinery, not manifest contents.
Expand Down Expand Up @@ -584,62 +583,6 @@ describe("ModelManifest service", () => {
);
});

// TEMPORARY V2 preview stopgap; remove with `withPreviewCompatibility` (#2829).
describe("compatibility policy by release channel", () => {
const OPENCODE = ProviderDriverKind.make("opencode");
// Main's OpenCode policy (#14198): stable and nightly have no OpenCode 2 runtime.
const remote: ModelManifest.ModelManifestData = {
...REMOTE_MANIFEST,
compatibility: [
{
driver: OPENCODE,
t3CodeRange: ">=0.0.42",
recommendedRange: ">=1.14.19 <2.0.0",
recommendedVersion: "1.14.19",
ranges: [
{ range: ">=2.0.0", status: "broken" },
{ range: ">=1.14.19 <2.0.0", status: "supported" },
{ range: "<1.14.19", status: "broken" },
],
},
],
};

for (const [channel, t3CodeVersion, expected, openCode2Status] of [
[
"preview builds keep the bundled policy",
"0.0.44-preview.20260929.1",
{ ...remote, compatibility: ModelManifest.BUNDLED_MODEL_MANIFEST.compatibility },
"supported",
],
["stable builds adopt the fetched policy", "0.0.44", remote, "broken"],
["nightly builds adopt the fetched policy", "0.0.44-nightly.20260929.1", remote, "broken"],
] as const) {
it.live(channel, () =>
Effect.gen(function* () {
const openCode2 = (manifest: ModelManifest.ModelManifestData) =>
resolveProviderCompatibility(manifest.compatibility, OPENCODE, "2.0.18", t3CodeVersion)
?.status;
const refreshed = yield* (yield* ModelManifest.makeForVersion(t3CodeVersion)).refresh;
assert.deepStrictEqual(refreshed, expected);
assert.strictEqual(openCode2(refreshed), openCode2Status);

// A restart reads the fetched manifest back from the disk cache.
const rebooted = yield* (yield* ModelManifest.makeForVersion(t3CodeVersion)).current;
assert.deepStrictEqual(rebooted, expected);
}).pipe(
Effect.scoped,
Effect.provide(
serviceLayers({
prefix: "model-manifest-channel-compatibility-test",
response: () => Response.json(remote),
}),
),
),
);
}
});

it.effect("caches valid compatibility policies and keeps them after a malformed refresh", () => {
const remote: ModelManifest.ModelManifestData = {
...REMOTE_MANIFEST,
Expand Down
30 changes: 3 additions & 27 deletions apps/server/src/provider/ModelManifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
type ProviderDriverKind,
type ServerProviderModel,
} from "@t3tools/contracts";
import { cliReleaseChannelOf } from "@t3tools/shared/cliRelease";
import { codexModelFamily } from "@t3tools/shared/model";
import * as Clock from "effect/Clock";
import * as Context from "effect/Context";
Expand All @@ -31,7 +30,6 @@ import * as Schema from "effect/Schema";
import * as Semaphore from "effect/Semaphore";
import { HttpClient, HttpClientResponse } from "effect/unstable/http";

import packageJson from "../../package.json" with { type: "json" };
import { ServerConfig } from "../config.ts";
import * as ServerSettings from "../serverSettings.ts";
import { hasValidClaudeManifestAdapters } from "./ClaudeModelManifest.ts";
Expand Down Expand Up @@ -142,25 +140,6 @@ const decodeManifest = Schema.decodeUnknownEffect(ModelManifestSchema);
export const BUNDLED_MODEL_MANIFEST: ModelManifestData =
Schema.decodeUnknownSync(ModelManifestSchema)(bundledManifestJson);

/**
* TEMPORARY V2 preview stopgap. Revert before V2 merges into main; it is on
* #2829's "Revert before merging into main" checklist.
*
* The fetched manifest is `main`'s, and its compatibility policy is written for
* stable and nightly builds, which do not run OpenCode 2. A policy's
* `t3CodeRange` cannot single out preview builds because range matching drops
* prerelease tags. Preview builds therefore keep the compatibility policy they
* shipped with and take everything else from the fetched manifest.
*/
function withPreviewCompatibility(
manifest: ModelManifestData,
t3CodeVersion: string,
): ModelManifestData {
return cliReleaseChannelOf(t3CodeVersion) === "preview"
? { ...manifest, compatibility: BUNDLED_MODEL_MANIFEST.compatibility }
: manifest;
}

/** Epoch millis of the manifest's `updatedAt`, or 0 when absent or unparsable. */
function manifestUpdatedAtMs(manifest: ModelManifestData): number {
if (manifest.updatedAt === undefined) return 0;
Expand Down Expand Up @@ -357,8 +336,7 @@ const BundledOnlyModelManifest: ModelManifest["Service"] = {

export const layerTest = Layer.succeed(ModelManifest, BundledOnlyModelManifest);

/** `make` for a given T3 Code version, so tests can exercise each release channel. */
export const makeForVersion = Effect.fnUntraced(function* (t3CodeVersion: string) {
export const make = Effect.gen(function* () {
const fileSystem = yield* FileSystem.FileSystem;
const path = yield* Path.Path;
const config = yield* ServerConfig;
Expand Down Expand Up @@ -391,7 +369,7 @@ export const makeForVersion = Effect.fnUntraced(function* (t3CodeVersion: string
if (manifestUpdatedAtMs(BUNDLED_MODEL_MANIFEST) > manifestUpdatedAtMs(fromDisk.manifest)) {
return;
}
manifest = withPreviewCompatibility(fromDisk.manifest, t3CodeVersion);
manifest = fromDisk.manifest;
fetchedAtMs = fromDisk.fetchedAtMs;
}),
);
Expand Down Expand Up @@ -430,7 +408,7 @@ export const makeForVersion = Effect.fnUntraced(function* (t3CodeVersion: string
return manifest;
}

manifest = withPreviewCompatibility(fetched, t3CodeVersion);
manifest = fetched;
fetchedAtMs = now;
yield* encodeManifestCache({ fetchedAtMs: now, manifest: fetched }).pipe(
Effect.flatMap((serialized) => fileSystem.writeFileString(cachePath, serialized)),
Expand All @@ -449,6 +427,4 @@ export const makeForVersion = Effect.fnUntraced(function* (t3CodeVersion: string
});
});

export const make = makeForVersion(packageJson.version);

export const layer = Layer.effect(ModelManifest, make);
17 changes: 14 additions & 3 deletions apps/server/src/provider/model-manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": 1,
"updatedAt": "2026-09-30T22:00:00Z",
"updatedAt": "2026-10-02T19:45:00Z",
"compatibility": [
{
"driver": "codex",
Expand Down Expand Up @@ -52,7 +52,18 @@
},
{
"driver": "opencode",
"t3CodeRange": ">=0.0.42",
"t3CodeRange": ">=0.0.42 <0.0.46",
"recommendedRange": ">=1.14.19 <2.0.0",
"recommendedVersion": "1.14.19",
"ranges": [
{ "range": ">=2.0.0", "status": "broken" },
{ "range": ">=1.14.19 <2.0.0", "status": "supported" },
{ "range": "<1.14.19", "status": "broken" }
]
},
{
"driver": "opencode",
"t3CodeRange": ">=0.0.46",
"recommendedRange": ">=2.0.18",
"ranges": [
{ "range": ">=2.0.18", "status": "supported" },
Expand All @@ -69,7 +80,7 @@
},
{
"driver": "pi",
"t3CodeRange": ">=0.0.42",
"t3CodeRange": ">=0.0.46",
"recommendedRange": ">=1.0.0",
"ranges": [
{ "range": ">=0.80.5", "status": "supported" },
Expand Down
59 changes: 51 additions & 8 deletions apps/server/src/provider/providerCompatibility.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ const provider: ServerProvider = {
slashCommands: [],
};

// The first release that runs the V2 orchestrator.
const V2_RELEASE = "0.0.46";

describe("provider compatibility", () => {
it("bundles a compatibility policy for every built-in harness", () => {
for (const builtIn of BUILT_IN_DRIVERS) {
Expand All @@ -61,12 +64,42 @@ describe("provider compatibility", () => {
ModelManifest.BUNDLED_MODEL_MANIFEST.compatibility,
builtIn.driverKind,
null,
V2_RELEASE,
),
`Missing bundled compatibility policy for ${builtIn.driverKind}`,
);
}
});

it("keeps releases before V2 on the OpenCode 1 policy they shipped with", () => {
// Every installed build fetches main's manifest, and 0.0.45 and older run the
// V1 orchestrator, which cannot drive OpenCode 2.
const opencode = ProviderDriverKind.make("opencode");
for (const [version, expected] of [
["1.14.19", "supported"],
["2.0.18", "broken"],
["1.14.18", "broken"],
] as const) {
const advisory = resolveProviderCompatibility(
ModelManifest.BUNDLED_MODEL_MANIFEST.compatibility,
opencode,
version,
"0.0.45",
);
assert.strictEqual(advisory?.status, expected, `OpenCode ${version} on 0.0.45`);
assert.strictEqual(advisory?.recommendedVersion, "1.14.19");
}
// Pi has no driver before V2.
assert.isUndefined(
resolveProviderCompatibility(
ModelManifest.BUNDLED_MODEL_MANIFEST.compatibility,
ProviderDriverKind.make("pi"),
"1.0.0",
"0.0.45",
),
);
});

it("supports OpenCode 2 and gives OpenCode 1.x limited support", () => {
const opencode = ProviderDriverKind.make("opencode");
for (const [version, expected] of [
Expand All @@ -79,13 +112,16 @@ describe("provider compatibility", () => {
["1.14.19", "graceful"],
["1.14.18", "broken"],
] as const) {
const advisory = resolveProviderCompatibility(
ModelManifest.BUNDLED_MODEL_MANIFEST.compatibility,
opencode,
version,
);
assert.strictEqual(advisory?.status, expected, `OpenCode ${version}`);
assert.strictEqual(advisory?.recommendedRange, ">=2.0.18");
for (const t3CodeVersion of [V2_RELEASE, "0.0.46-preview.20261002.2598"]) {
const advisory = resolveProviderCompatibility(
ModelManifest.BUNDLED_MODEL_MANIFEST.compatibility,
opencode,
version,
t3CodeVersion,
);
assert.strictEqual(advisory?.status, expected, `OpenCode ${version} on ${t3CodeVersion}`);
assert.strictEqual(advisory?.recommendedRange, ">=2.0.18");
}
}
// The advisory rides beside the probe: a ready 1.x instance stays ready and selectable.
const ready = applyProviderCompatibility(
Expand All @@ -94,7 +130,14 @@ describe("provider compatibility", () => {
ModelManifest.BUNDLED_MODEL_MANIFEST.compatibility,
);
assert.strictEqual(ready.status, "ready");
assert.strictEqual(ready.compatibilityAdvisory?.status, "graceful");
assert.strictEqual(
ready.compatibilityAdvisory?.status,
resolveProviderCompatibility(
ModelManifest.BUNDLED_MODEL_MANIFEST.compatibility,
opencode,
"1.18.33",
)?.status,
);
});

it("compares Cursor build dates without treating semver prereleases as stable", () => {
Expand Down
Loading