refactor(ai): rename llm package

This commit is contained in:
Dax Raad 2026-07-15 15:10:38 -04:00
commit bb15b16499
238 changed files with 209 additions and 210 deletions

View file

@ -87,7 +87,7 @@
"@opencode-ai/client": "workspace:*",
"@opencode-ai/cli": "workspace:*",
"@opencode-ai/codemode": "workspace:*",
"@opencode-ai/llm": "workspace:*",
"@opencode-ai/ai": "workspace:*",
"@opencode-ai/plugin": "workspace:*",
"@opencode-ai/protocol": "workspace:*",
"@opencode-ai/schema": "workspace:*",

View file

@ -2,7 +2,7 @@ import { APICallError } from "ai"
import { STATUS_CODES } from "http"
import { iife } from "@/util/iife"
import type { ProviderV2 } from "@opencode-ai/core/provider"
import { isContextOverflow } from "@opencode-ai/llm"
import { isContextOverflow } from "@opencode-ai/ai"
export class HeaderTimeoutError extends Error {
public override readonly name = "ProviderHeaderTimeoutError"

View file

@ -3,7 +3,7 @@ import { Provider } from "@/provider/provider"
import { LLM } from "@/session/llm"
import { MessageID, SessionID } from "@/session/schema"
import { Slug } from "@opencode-ai/core/util/slug"
import { LLMEvent } from "@opencode-ai/llm"
import { LLMEvent } from "@opencode-ai/ai"
import { Effect, Stream } from "effect"
import { HttpApiBuilder } from "effect/unstable/httpapi"
import { InstanceHttpApi } from "../api"

View file

@ -7,9 +7,9 @@ import { serviceUse } from "@opencode-ai/core/effect/service-use"
import { Context, Effect, Layer } from "effect"
import * as Stream from "effect/Stream"
import { streamText, wrapLanguageModel, type ModelMessage, type Tool } from "ai"
import type { LLMEvent } from "@opencode-ai/llm"
import { LLMClient } from "@opencode-ai/llm/route"
import type { LLMClientService } from "@opencode-ai/llm/route"
import type { LLMEvent } from "@opencode-ai/ai"
import { LLMClient } from "@opencode-ai/ai/route"
import type { LLMClientService } from "@opencode-ai/ai/route"
import { GitLabWorkflowLanguageModel } from "gitlab-ai-provider"
import { ProviderTransform } from "@/provider/transform"
import { Config } from "@/config/config"
@ -221,7 +221,7 @@ const live: Layer.Layer<
})
: undefined
// Runtime seam: native is an opt-in adapter over @opencode-ai/llm. It
// Runtime seam: native is an opt-in adapter over @opencode-ai/ai. It
// either returns a ready LLMEvent stream or a concrete fallback reason.
if (flags.experimentalNativeLlm) {
const native = LLMNativeRuntime.stream({

View file

@ -4,8 +4,8 @@
This folder contains adapters behind that service boundary:
- `ai-sdk.ts` converts AI SDK `fullStream` parts into `@opencode-ai/llm` `LLMEvent`s. This is the default runtime path.
- `native-request.ts` converts opencode's normalized session input into a native `@opencode-ai/llm` `LLMRequest`. It does not execute requests.
- `ai-sdk.ts` converts AI SDK `fullStream` parts into `@opencode-ai/ai` `LLMEvent`s. This is the default runtime path.
- `native-request.ts` converts opencode's normalized session input into a native `@opencode-ai/ai` `LLMRequest`. It does not execute requests.
- `native-runtime.ts` is the opt-in native runtime adapter. It decides whether a selected model is supported, builds the native request, bridges opencode tools into native executable tools, and delegates transport to `LLMClient` / `RequestExecutor`.
## File Structure
@ -15,19 +15,19 @@ src/session/
llm.ts session-owned orchestration and runtime selection
llm/
AGENTS.md boundary notes for the adapter layer
ai-sdk.ts AI SDK fullStream -> @opencode-ai/llm LLMEvent adapter
native-request.ts opencode/AI SDK-shaped input -> @opencode-ai/llm LLMRequest
ai-sdk.ts AI SDK fullStream -> @opencode-ai/ai LLMEvent adapter
native-request.ts opencode/AI SDK-shaped input -> @opencode-ai/ai LLMRequest
native-runtime.ts native runtime gate, tool bridge, and LLMClient handoff
```
Integration points:
- `../llm.ts` imports `LLMClient` from `@opencode-ai/llm/route`; native execution is the only path that calls it directly.
- `../llm.ts` imports `LLMClient` from `@opencode-ai/ai/route`; native execution is the only path that calls it directly.
- `../llm.ts` imports `LLMAISDK` from `./llm/ai-sdk`; the AI SDK path still calls `streamText(...)` locally, then adapts `result.fullStream` into shared `LLMEvent`s.
- `../llm.ts` imports `LLMNativeRuntime` from `./llm/native-runtime`; this is the runtime-selection seam. Unsupported native requests return a reason and fall back to AI SDK.
- `native-runtime.ts` imports `LLMNative` from `./native-request`; this keeps request lowering separate from transport and tool execution.
- `native-request.ts` is the only adapter file that should construct `LLM.request(...)`, `LLM.model(...)`, `Message.*`, `SystemPart`, `ToolCallPart`, `ToolResultPart`, or `ToolDefinition` values from `@opencode-ai/llm`.
- `ai-sdk.ts` and `native-runtime.ts` both emit `@opencode-ai/llm` `LLMEvent`s so downstream session processing does not care which runtime handled the request.
- `native-request.ts` is the only adapter file that should construct `LLM.request(...)`, `LLM.model(...)`, `Message.*`, `SystemPart`, `ToolCallPart`, `ToolResultPart`, or `ToolDefinition` values from `@opencode-ai/ai`.
- `ai-sdk.ts` and `native-runtime.ts` both emit `@opencode-ai/ai` `LLMEvent`s so downstream session processing does not care which runtime handled the request.
Keep new integration code on one of these seams. Avoid importing session services into `native-request.ts`; pass normalized data through `RequestInput` instead.
@ -80,7 +80,7 @@ Both runtimes converge on the same `LLMEvent` stream consumed by the session pro
╰─────────────────╯ ╰─────────────────────────────╯
```
`native-runtime.ts` evaluates the gate and either bridges into `@opencode-ai/llm` or returns control so `llm.ts` can take the AI SDK path. Tool execution stays opencode-owned in both branches; only request lowering and transport differ.
`native-runtime.ts` evaluates the gate and either bridges into `@opencode-ai/ai` or returns control so `llm.ts` can take the AI SDK path. Tool execution stays opencode-owned in both branches; only request lowering and transport differ.
Safety boundary:

View file

@ -1,4 +1,4 @@
import { FinishReason, LLMEvent, ProviderMetadata, ToolResultValue } from "@opencode-ai/llm"
import { FinishReason, LLMEvent, ProviderMetadata, ToolResultValue } from "@opencode-ai/ai"
import { Effect, Schema } from "effect"
import { type streamText } from "ai"
import { errorMessage } from "@/util/error"
@ -28,7 +28,7 @@ function providerMetadata(value: unknown): ProviderMetadata | undefined {
}
// Temporary AI SDK bridge: Copilot billing survives only in raw provider chunks here.
// Move this extraction into @opencode-ai/llm when Copilot is handled by the native runtime.
// Move this extraction into @opencode-ai/ai when Copilot is handled by the native runtime.
function copilotTotalNanoAiu(value: unknown) {
if (!value || typeof value !== "object") return
const raw = value as Record<string, unknown>

View file

@ -1,5 +1,5 @@
import type { JsonSchema, LLMRequest, ProviderMetadata } from "@opencode-ai/llm"
import { LLM, Message, SystemPart, ToolCallPart, ToolDefinition, ToolResultPart } from "@opencode-ai/llm"
import type { JsonSchema, LLMRequest, ProviderMetadata } from "@opencode-ai/ai"
import { LLM, Message, SystemPart, ToolCallPart, ToolDefinition, ToolResultPart } from "@opencode-ai/ai"
import {
AmazonBedrock,
Anthropic,
@ -8,7 +8,7 @@ import {
OpenAI,
OpenAICompatible,
OpenRouter,
} from "@opencode-ai/llm/providers"
} from "@opencode-ai/ai/providers"
import type { ModelMessage } from "ai"
import type { Provider } from "@/provider/provider"
import { isRecord } from "@/util/record"
@ -181,7 +181,7 @@ export const model = (input: Provider.Model | RequestInput, headers?: Record<str
export const request = (input: RequestInput) => {
const converted = messages(input.messages)
// This is the only native adapter boundary that should construct canonical
// @opencode-ai/llm request objects from opencode's session/AI SDK-shaped data.
// @opencode-ai/ai request objects from opencode's session/AI SDK-shaped data.
return LLM.request({
model: model(input, input.headers),
system: [...(input.system ?? []).map(SystemPart.make), ...converted.system],

View file

@ -15,8 +15,8 @@ import {
toDefinitions,
type JsonSchema,
type LLMEvent,
} from "@opencode-ai/llm"
import type { LLMClientShape } from "@opencode-ai/llm/route"
} from "@opencode-ai/ai"
import type { LLMClientShape } from "@opencode-ai/ai/route"
import { LLMNative } from "./native-request"
export type RuntimeStatus =
@ -76,7 +76,7 @@ export function stream(input: StreamInput): StreamResult {
const current = statusWithFetch(input, fetch)
if (current.type === "unsupported") return current
// Integration point with @opencode-ai/llm: native-request lowers session data
// Integration point with @opencode-ai/ai: native-request lowers session data
// into an LLMRequest, then LLMClient handles route selection and transport.
//
// ProviderTransform.providerOptions builds AI-SDK-shaped options for the
@ -171,7 +171,7 @@ export function nativeTools(tools: Record<string, Tool>, input: Pick<StreamInput
Object.entries(tools).map(([name, item]) => [
name,
// Tool execution remains opencode-owned. The native runtime only adapts
// the @opencode-ai/llm tool call back into the AI SDK Tool.execute shape.
// the @opencode-ai/ai tool call back into the AI SDK Tool.execute shape.
NativeTool.make({
description: item.description ?? "",
jsonSchema: nativeSchema(item.inputSchema),

View file

@ -24,7 +24,7 @@ import { errorMessage } from "@/util/error"
import { isRecord } from "@/util/record"
import { EventV2Bridge } from "@/event-v2-bridge"
import { Database } from "@opencode-ai/core/database/database"
import { Usage, type LLMEvent } from "@opencode-ai/llm"
import { Usage, type LLMEvent } from "@opencode-ai/ai"
const DOOM_LOOP_THRESHOLD = 3
export type Result = "compact" | "stop" | "continue"

View file

@ -55,7 +55,7 @@ import { eq } from "drizzle-orm"
import { SessionTable } from "@opencode-ai/core/session/sql"
import { SessionReminders } from "./reminders"
import { SessionTools } from "./tools"
import { LLMEvent } from "@opencode-ai/llm"
import { LLMEvent } from "@opencode-ai/ai"
// @ts-ignore
globalThis.AI_SDK_LOG_WARNINGS = false

View file

@ -9,7 +9,7 @@ import { serviceUse } from "@opencode-ai/core/effect/service-use"
import path from "path"
import { Job } from "@/job"
import { Decimal } from "decimal.js"
import type { ProviderMetadata, Usage } from "@opencode-ai/llm"
import type { ProviderMetadata, Usage } from "@opencode-ai/ai"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { Database } from "@opencode-ai/core/database/database"
import { EventV2Bridge } from "@/event-v2-bridge"

View file

@ -28,7 +28,7 @@ import { testEffect } from "../lib/effect"
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
import { TestConfig } from "../fixture/config"
import { RuntimeFlags } from "@/effect/runtime-flags"
import { LLMEvent, Usage } from "@opencode-ai/llm"
import { LLMEvent, Usage } from "@opencode-ai/ai"
import { ProviderV2 } from "@opencode-ai/core/provider"
import { ModelV2 } from "@opencode-ai/core/model"
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"

View file

@ -11,8 +11,8 @@ import { Auth } from "@/auth"
import { Provider } from "@/provider/provider"
import { Filesystem } from "@/util/filesystem"
import { LLMEvent, LLMResponse } from "@opencode-ai/llm"
import { RequestExecutor } from "@opencode-ai/llm/route"
import { LLMEvent, LLMResponse } from "@opencode-ai/ai"
import { RequestExecutor } from "@opencode-ai/ai/route"
import { RuntimeFlags } from "@/effect/runtime-flags"
import type { Agent } from "../../src/agent/agent"
import { LLM } from "../../src/session/llm"

View file

@ -1,6 +1,6 @@
import { describe, expect, test } from "bun:test"
import { LLMEvent, ToolFailure } from "@opencode-ai/llm"
import { LLMClient, RequestExecutor, WebSocketExecutor, type LLMClientShape } from "@opencode-ai/llm/route"
import { LLMEvent, ToolFailure } from "@opencode-ai/ai"
import { LLMClient, RequestExecutor, WebSocketExecutor, type LLMClientShape } from "@opencode-ai/ai/route"
import { jsonSchema, tool, type ModelMessage, type Tool } from "ai"
import { Effect, Fiber, Layer, Stream } from "effect"
import { FetchHttpClient } from "effect/unstable/http"

View file

@ -9,7 +9,7 @@ import { InstanceRef } from "../../src/effect/instance-ref"
import { HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
import z from "zod"
import { LLM } from "../../src/session/llm"
import { LLMClient, RequestExecutor } from "@opencode-ai/llm/route"
import { LLMClient, RequestExecutor } from "@opencode-ai/ai/route"
import { Provider } from "@/provider/provider"
import { ProviderTransform } from "@/provider/transform"
import { ModelsDev } from "@opencode-ai/core/models-dev"

View file

@ -25,7 +25,7 @@ import { RuntimeFlags } from "@/effect/runtime-flags"
import { ProviderV2 } from "@opencode-ai/core/provider"
import { ModelV2 } from "@opencode-ai/core/model"
import { SessionProjector } from "@opencode-ai/core/session/projector"
import { LLMEvent } from "@opencode-ai/llm"
import { LLMEvent } from "@opencode-ai/ai"
const summary = Layer.succeed(
SessionSummary.Service,