|
9 | 9 | ProviderSession, |
10 | 10 | ProviderDriverKind, |
11 | 11 | ProviderInstanceId, |
| 12 | + isMtModelInstanceId, |
12 | 13 | MT_MODEL_INSTANCE_ID, |
13 | 14 | MT_MODEL_SLUG, |
14 | 15 | } from "@t3tools/contracts"; |
@@ -333,6 +334,18 @@ describe("ProviderCommandReactor", () => { |
333 | 334 | }), |
334 | 335 | getInstanceInfo: (instanceId) => { |
335 | 336 | const raw = String(instanceId); |
| 337 | + // The router is virtual: the real registry has no `mt` instance and |
| 338 | + // fails the lookup, which is what surfaces as "references unknown |
| 339 | + // provider instance 'mt'" in the app. |
| 340 | + if (isMtModelInstanceId(instanceId)) { |
| 341 | + return Effect.fail( |
| 342 | + new ProviderAdapterRequestError({ |
| 343 | + provider: "mt", |
| 344 | + method: "provider.instance.info", |
| 345 | + detail: `Provider instance '${raw}' is not configured in this build.`, |
| 346 | + }), |
| 347 | + ) as ReturnType<ProviderServiceShape["getInstanceInfo"]>; |
| 348 | + } |
336 | 349 | const driverKind = ProviderDriverKind.make( |
337 | 350 | raw.startsWith("claude") ? "claudeAgent" : raw.startsWith("codex") ? "codex" : raw, |
338 | 351 | ); |
@@ -2082,6 +2095,69 @@ describe("ProviderCommandReactor", () => { |
2082 | 2095 | expect(thread?.session?.providerInstanceId).toBe(ProviderInstanceId.make("codex")); |
2083 | 2096 | }); |
2084 | 2097 |
|
| 2098 | + it("starts a turn when an MT Auto thread picks a real model", async () => { |
| 2099 | + const harness = await createHarness({ |
| 2100 | + threadModelSelection: { instanceId: MT_MODEL_INSTANCE_ID, model: MT_MODEL_SLUG }, |
| 2101 | + extraRegistryProviders: [ |
| 2102 | + { |
| 2103 | + instanceId: ProviderInstanceId.make("codex"), |
| 2104 | + driver: ProviderDriverKind.make("codex"), |
| 2105 | + enabled: true, |
| 2106 | + installed: true, |
| 2107 | + version: null, |
| 2108 | + status: "ready", |
| 2109 | + auth: { status: "unknown" }, |
| 2110 | + checkedAt: "2026-01-01T00:00:00.000Z", |
| 2111 | + models: [ |
| 2112 | + { |
| 2113 | + slug: "gpt-5-codex", |
| 2114 | + name: "GPT-5 Codex", |
| 2115 | + isCustom: false, |
| 2116 | + isDefault: true, |
| 2117 | + capabilities: null, |
| 2118 | + }, |
| 2119 | + ], |
| 2120 | + slashCommands: [], |
| 2121 | + skills: [], |
| 2122 | + }, |
| 2123 | + ], |
| 2124 | + }); |
| 2125 | + const now = "2026-01-01T00:00:00.000Z"; |
| 2126 | + |
| 2127 | + // The thread's saved selection is the router; the user picks a real model |
| 2128 | + // for this turn. Resolving the *current* instance used to hand `mt` to the |
| 2129 | + // registry, which fails with "references unknown provider instance 'mt'". |
| 2130 | + await Effect.runPromise( |
| 2131 | + harness.engine.dispatch({ |
| 2132 | + type: "thread.turn.start", |
| 2133 | + commandId: CommandId.make("cmd-mt-thread-explicit-model"), |
| 2134 | + threadId: ThreadId.make("thread-1"), |
| 2135 | + message: { |
| 2136 | + messageId: asMessageId("user-message-mt-explicit-model"), |
| 2137 | + role: "user", |
| 2138 | + text: "what is mv2 doing", |
| 2139 | + attachments: [], |
| 2140 | + }, |
| 2141 | + modelSelection: { |
| 2142 | + instanceId: ProviderInstanceId.make("codex"), |
| 2143 | + model: "gpt-5-codex", |
| 2144 | + }, |
| 2145 | + interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, |
| 2146 | + runtimeMode: "approval-required", |
| 2147 | + createdAt: now, |
| 2148 | + }), |
| 2149 | + ); |
| 2150 | + |
| 2151 | + await waitFor(() => harness.sendTurn.mock.calls.length === 1); |
| 2152 | + |
| 2153 | + const readModel = await harness.readModel(); |
| 2154 | + const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); |
| 2155 | + expect( |
| 2156 | + thread?.activities.filter((activity) => activity.kind === "provider.turn.start.failed"), |
| 2157 | + ).toHaveLength(0); |
| 2158 | + expect(thread?.session?.providerInstanceId).toBe(ProviderInstanceId.make("codex")); |
| 2159 | + }); |
| 2160 | + |
2085 | 2161 | it("reuses the same provider session when runtime mode is unchanged", async () => { |
2086 | 2162 | const harness = await createHarness(); |
2087 | 2163 | const now = "2026-01-01T00:00:00.000Z"; |
|
0 commit comments