refactor(cli): parse variants from model refs
This commit is contained in:
parent
cccd013801
commit
67f2393f83
10 changed files with 79 additions and 34 deletions
|
|
@ -171,7 +171,7 @@ export const Commands = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCO
|
|||
),
|
||||
model: Flag.string("model").pipe(
|
||||
Flag.withAlias("m"),
|
||||
Flag.withDescription("Model to use in the format provider/model"),
|
||||
Flag.withDescription("Model to use in the format provider/model#variant"),
|
||||
Flag.optional,
|
||||
),
|
||||
agent: Flag.string("agent").pipe(Flag.withDescription("Agent to use"), Flag.optional),
|
||||
|
|
@ -185,7 +185,6 @@ export const Commands = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCO
|
|||
Flag.atMost(100),
|
||||
),
|
||||
title: Flag.string("title").pipe(Flag.withDescription("Session title"), Flag.optional),
|
||||
variant: Flag.string("variant").pipe(Flag.withDescription("Model variant"), Flag.optional),
|
||||
thinking: Flag.boolean("thinking").pipe(
|
||||
Flag.withDescription("Show thinking blocks"),
|
||||
Flag.withDefault(false),
|
||||
|
|
@ -195,10 +194,6 @@ export const Commands = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCO
|
|||
Flag.withDefault(false),
|
||||
),
|
||||
yolo: Flag.boolean("yolo").pipe(Flag.withDefault(false), Flag.withHidden),
|
||||
dangerouslySkipPermissions: Flag.boolean("dangerously-skip-permissions").pipe(
|
||||
Flag.withDefault(false),
|
||||
Flag.withHidden,
|
||||
),
|
||||
},
|
||||
}),
|
||||
Spec.make("service", {
|
||||
|
|
|
|||
|
|
@ -23,9 +23,8 @@ export default Runtime.handler(Commands.commands.run, (input) =>
|
|||
format: input.format,
|
||||
file: [...input.file],
|
||||
title: Option.getOrUndefined(input.title),
|
||||
variant: Option.getOrUndefined(input.variant),
|
||||
thinking: input.thinking,
|
||||
dangerouslySkipPermissions: input.auto || input.yolo || input.dangerouslySkipPermissions,
|
||||
auto: input.auto || input.yolo,
|
||||
}),
|
||||
)
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -3,5 +3,6 @@ export {
|
|||
runNonInteractive,
|
||||
mergeInput as mergeNonInteractiveInput,
|
||||
pickRunModel,
|
||||
parseRunModel,
|
||||
type RunCommandInput,
|
||||
} from "./run"
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ type Input = {
|
|||
variant?: string
|
||||
thinking: boolean
|
||||
format: "default" | "json"
|
||||
dangerouslySkipPermissions: boolean
|
||||
auto: boolean
|
||||
/** True when the client is attached to a shared server rather than an exclusive in-process one. */
|
||||
attached: boolean
|
||||
renderTool: (part: ToolPart) => Promise<void>
|
||||
|
|
@ -91,7 +91,7 @@ export async function runNonInteractivePrompt(input: Input) {
|
|||
}
|
||||
|
||||
const replyPermission = async (request: { id: string; action: string; resources: ReadonlyArray<string> }) => {
|
||||
if (!input.dangerouslySkipPermissions) {
|
||||
if (!input.auto) {
|
||||
permissionRejected = true
|
||||
UI.println(
|
||||
UI.Style.TEXT_WARNING_BOLD + "!",
|
||||
|
|
@ -103,10 +103,10 @@ export async function runNonInteractivePrompt(input: Input) {
|
|||
.reply({
|
||||
sessionID: input.sessionID,
|
||||
requestID: request.id,
|
||||
reply: input.dangerouslySkipPermissions ? "once" : "reject",
|
||||
reply: input.auto ? "once" : "reject",
|
||||
})
|
||||
.catch(() => {})
|
||||
if (!input.dangerouslySkipPermissions) {
|
||||
if (!input.auto) {
|
||||
await input.client.session.interrupt({ sessionID: input.sessionID }).catch(() => {})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Service } from "@opencode-ai/client/effect"
|
||||
import { OpenCode, type OpenCodeClient } from "@opencode-ai/client/promise"
|
||||
import { FSUtil } from "@opencode-ai/core/fs-util"
|
||||
import { Model } from "@opencode-ai/schema/model"
|
||||
import type { ToolPart } from "@opencode-ai/sdk/v2"
|
||||
import { open } from "node:fs/promises"
|
||||
import path from "node:path"
|
||||
|
|
@ -21,9 +22,8 @@ export type RunCommandInput = {
|
|||
format: "default" | "json"
|
||||
file: string[]
|
||||
title?: string
|
||||
variant?: string
|
||||
thinking?: boolean
|
||||
dangerouslySkipPermissions?: boolean
|
||||
auto?: boolean
|
||||
}
|
||||
|
||||
type FilePart = {
|
||||
|
|
@ -62,7 +62,9 @@ async function execute(input: RunCommandInput, prepared: Prepared, endpoint: Ser
|
|||
const session = await selectSession(client, requestedDirectory, input)
|
||||
const cwd = session?.location.directory ?? requestedDirectory
|
||||
const workspace = session?.location.workspaceID
|
||||
const explicitModel = parseModel(input.model)
|
||||
const explicit = parseRunModel(input.model)
|
||||
const explicitModel = explicit?.model
|
||||
const variant = explicit?.variant
|
||||
const sessionModel = session?.model ? { providerID: session.model.providerID, modelID: session.model.id } : undefined
|
||||
const defaultModel =
|
||||
!explicitModel && !sessionModel
|
||||
|
|
@ -70,8 +72,8 @@ async function execute(input: RunCommandInput, prepared: Prepared, endpoint: Ser
|
|||
.default({ location: { directory: cwd, workspace } })
|
||||
.then((result) => (result.data ? { providerID: result.data.providerID, modelID: result.data.id } : undefined))
|
||||
: undefined
|
||||
const model = pickRunModel(explicitModel, input.variant, sessionModel, defaultModel)
|
||||
if (input.variant && !model)
|
||||
const model = pickRunModel(explicitModel, variant, sessionModel, defaultModel)
|
||||
if (variant && !model)
|
||||
return reportError(input, "Cannot select a variant before selecting a model", session?.id)
|
||||
if (model) {
|
||||
await waitForCatalogReady({ sdk: client, directory: cwd, workspace, model })
|
||||
|
|
@ -84,7 +86,7 @@ async function execute(input: RunCommandInput, prepared: Prepared, endpoint: Ser
|
|||
session ??
|
||||
(await client.session.create({
|
||||
agent,
|
||||
model: model ? { providerID: model.providerID, id: model.modelID, variant: input.variant } : undefined,
|
||||
model: model ? { providerID: model.providerID, id: model.modelID, variant } : undefined,
|
||||
location: { directory: cwd },
|
||||
}))
|
||||
if (!session && input.title !== undefined) {
|
||||
|
|
@ -101,10 +103,10 @@ async function execute(input: RunCommandInput, prepared: Prepared, endpoint: Ser
|
|||
files: prepared.files,
|
||||
agent,
|
||||
model,
|
||||
variant: input.variant,
|
||||
variant,
|
||||
thinking: input.thinking ?? false,
|
||||
format: input.format,
|
||||
dangerouslySkipPermissions: input.dangerouslySkipPermissions ?? false,
|
||||
auto: input.auto ?? false,
|
||||
attached: true,
|
||||
renderTool,
|
||||
renderToolError,
|
||||
|
|
@ -142,12 +144,13 @@ function localDirectory(root: string) {
|
|||
}
|
||||
}
|
||||
|
||||
function parseModel(value?: string) {
|
||||
export function parseRunModel(value?: string) {
|
||||
if (!value) return
|
||||
const [providerID, ...rest] = value.split("/")
|
||||
const modelID = rest.join("/")
|
||||
if (!providerID || !modelID) fail("--model must use the format provider/model")
|
||||
return { providerID, modelID }
|
||||
const ref = Model.Ref.parse(value)
|
||||
return {
|
||||
model: { providerID: ref.providerID, modelID: ref.id },
|
||||
variant: ref.variant,
|
||||
}
|
||||
}
|
||||
|
||||
async function validateAgent(client: OpenCodeClient, directory: string, name?: string) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue