resolve merge conflicts
This commit is contained in:
@@ -381,38 +381,6 @@ export async function CodexAuthPlugin(input: PluginInput): Promise<Hooks> {
|
||||
delete provider.models[modelId]
|
||||
}
|
||||
|
||||
if (!provider.models["gpt-5.3-codex"]) {
|
||||
const model = {
|
||||
id: ModelID.make("gpt-5.3-codex"),
|
||||
providerID: ProviderID.openai,
|
||||
api: {
|
||||
id: "gpt-5.3-codex",
|
||||
url: "https://chatgpt.com/backend-api/codex",
|
||||
npm: "@ai-sdk/openai",
|
||||
},
|
||||
name: "GPT-5.3 Codex",
|
||||
capabilities: {
|
||||
temperature: false,
|
||||
reasoning: true,
|
||||
attachment: true,
|
||||
toolcall: true,
|
||||
input: { text: true, audio: false, image: true, video: false, pdf: false },
|
||||
output: { text: true, audio: false, image: false, video: false, pdf: false },
|
||||
interleaved: false,
|
||||
},
|
||||
cost: { input: 0, output: 0, cache: { read: 0, write: 0 } },
|
||||
limit: { context: 400_000, input: 272_000, output: 128_000 },
|
||||
status: "active" as const,
|
||||
options: {},
|
||||
headers: {},
|
||||
release_date: "2026-02-05",
|
||||
variants: {} as Record<string, Record<string, any>>,
|
||||
family: "gpt-codex",
|
||||
}
|
||||
model.variants = ProviderTransform.variants(model)
|
||||
provider.models["gpt-5.3-codex"] = model
|
||||
}
|
||||
|
||||
// Zero out costs for Codex (included with ChatGPT subscription)
|
||||
for (const model of Object.values(provider.models)) {
|
||||
model.cost = {
|
||||
|
||||
@@ -165,6 +165,14 @@ export namespace Plugin {
|
||||
|
||||
const resolved = await PluginLoader.resolve(plan, "server")
|
||||
if (!resolved.ok) {
|
||||
if (resolved.stage === "missing") {
|
||||
log.warn("plugin has no server entrypoint", {
|
||||
path: plan.spec,
|
||||
message: resolved.message,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const cause =
|
||||
resolved.error instanceof Error ? (resolved.error.cause ?? resolved.error) : resolved.error
|
||||
const message = errorMessage(cause)
|
||||
|
||||
@@ -11,6 +11,7 @@ import { ConfigPaths } from "@/config/paths"
|
||||
import { Global } from "@/global"
|
||||
import { Filesystem } from "@/util/filesystem"
|
||||
import { Flock } from "@/util/flock"
|
||||
import { isRecord } from "@/util/record"
|
||||
|
||||
import { parsePluginSpecifier, readPluginPackage, resolvePluginTarget } from "./shared"
|
||||
|
||||
@@ -101,28 +102,60 @@ function pluginList(data: unknown) {
|
||||
return item.plugin
|
||||
}
|
||||
|
||||
function parseTarget(item: unknown): Target | undefined {
|
||||
if (item === "server" || item === "tui") return { kind: item }
|
||||
if (!Array.isArray(item)) return
|
||||
if (item[0] !== "server" && item[0] !== "tui") return
|
||||
if (item.length < 2) return { kind: item[0] }
|
||||
const opt = item[1]
|
||||
if (!opt || typeof opt !== "object" || Array.isArray(opt)) return { kind: item[0] }
|
||||
return {
|
||||
kind: item[0],
|
||||
opts: opt,
|
||||
function exportValue(value: unknown): string | undefined {
|
||||
if (typeof value === "string") {
|
||||
const next = value.trim()
|
||||
if (next) return next
|
||||
return
|
||||
}
|
||||
if (!isRecord(value)) return
|
||||
for (const key of ["import", "default"]) {
|
||||
const next = value[key]
|
||||
if (typeof next !== "string") continue
|
||||
const hit = next.trim()
|
||||
if (!hit) continue
|
||||
return hit
|
||||
}
|
||||
}
|
||||
|
||||
function parseTargets(raw: unknown) {
|
||||
if (!Array.isArray(raw)) return []
|
||||
const map = new Map<Kind, Target>()
|
||||
for (const item of raw) {
|
||||
const hit = parseTarget(item)
|
||||
if (!hit) continue
|
||||
map.set(hit.kind, hit)
|
||||
function exportOptions(value: unknown): Record<string, unknown> | undefined {
|
||||
if (!isRecord(value)) return
|
||||
const config = value.config
|
||||
if (!isRecord(config)) return
|
||||
return config
|
||||
}
|
||||
|
||||
function exportTarget(pkg: Record<string, unknown>, kind: Kind) {
|
||||
const exports = pkg.exports
|
||||
if (!isRecord(exports)) return
|
||||
const value = exports[`./${kind}`]
|
||||
const entry = exportValue(value)
|
||||
if (!entry) return
|
||||
return {
|
||||
opts: exportOptions(value),
|
||||
}
|
||||
return [...map.values()]
|
||||
}
|
||||
|
||||
function hasMainTarget(pkg: Record<string, unknown>) {
|
||||
const main = pkg.main
|
||||
if (typeof main !== "string") return false
|
||||
return Boolean(main.trim())
|
||||
}
|
||||
|
||||
function packageTargets(pkg: Record<string, unknown>) {
|
||||
const targets: Target[] = []
|
||||
const server = exportTarget(pkg, "server")
|
||||
if (server) {
|
||||
targets.push({ kind: "server", opts: server.opts })
|
||||
} else if (hasMainTarget(pkg)) {
|
||||
targets.push({ kind: "server" })
|
||||
}
|
||||
|
||||
const tui = exportTarget(pkg, "tui")
|
||||
if (tui) {
|
||||
targets.push({ kind: "tui", opts: tui.opts })
|
||||
}
|
||||
return targets
|
||||
}
|
||||
|
||||
function patch(text: string, path: Array<string | number>, value: unknown, insert = false) {
|
||||
@@ -260,7 +293,7 @@ export async function readPluginManifest(target: string): Promise<ManifestResult
|
||||
}
|
||||
}
|
||||
|
||||
const targets = parseTargets(pkg.item.json["oc-plugin"])
|
||||
const targets = packageTargets(pkg.item.json)
|
||||
if (!targets.length) {
|
||||
return {
|
||||
ok: false,
|
||||
@@ -330,7 +363,7 @@ async function patchOne(dir: string, target: Target, spec: string, force: boolea
|
||||
}
|
||||
|
||||
const list = pluginList(data)
|
||||
const item = target.opts ? [spec, target.opts] : spec
|
||||
const item = target.opts ? ([spec, target.opts] as const) : spec
|
||||
const out = patchPluginList(text, list, spec, item, force)
|
||||
if (out.mode === "noop") {
|
||||
return {
|
||||
|
||||
@@ -43,7 +43,9 @@ export namespace PluginLoader {
|
||||
plan: Plan,
|
||||
kind: PluginKind,
|
||||
): Promise<
|
||||
{ ok: true; value: Resolved } | { ok: false; stage: "install" | "entry" | "compatibility"; error: unknown }
|
||||
| { ok: true; value: Resolved }
|
||||
| { ok: false; stage: "missing"; message: string }
|
||||
| { ok: false; stage: "install" | "entry" | "compatibility"; error: unknown }
|
||||
> {
|
||||
let target = ""
|
||||
try {
|
||||
@@ -77,8 +79,8 @@ export namespace PluginLoader {
|
||||
if (!base.entry) {
|
||||
return {
|
||||
ok: false,
|
||||
stage: "entry",
|
||||
error: new Error(`Plugin ${plan.spec} entry is empty`),
|
||||
stage: "missing",
|
||||
message: `Plugin ${plan.spec} does not expose a ${kind} entrypoint`,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ export type PluginEntry = {
|
||||
source: PluginSource
|
||||
target: string
|
||||
pkg?: PluginPackage
|
||||
entry: string
|
||||
entry?: string
|
||||
}
|
||||
|
||||
const INDEX_FILES = ["index.ts", "index.tsx", "index.js", "index.mjs", "index.cjs"]
|
||||
@@ -128,13 +128,8 @@ async function resolvePluginEntrypoint(spec: string, target: string, kind: Plugi
|
||||
if (index) return pathToFileURL(index).href
|
||||
}
|
||||
|
||||
if (source === "npm") {
|
||||
throw new TypeError(`Plugin ${spec} must define package.json exports["./tui"]`)
|
||||
}
|
||||
|
||||
if (dir) {
|
||||
throw new TypeError(`Plugin ${spec} must define package.json exports["./tui"] or include index file`)
|
||||
}
|
||||
if (source === "npm") return
|
||||
if (dir) return
|
||||
|
||||
return target
|
||||
}
|
||||
@@ -145,7 +140,7 @@ async function resolvePluginEntrypoint(spec: string, target: string, kind: Plugi
|
||||
if (index) return pathToFileURL(index).href
|
||||
}
|
||||
|
||||
throw new TypeError(`Plugin ${spec} must define package.json exports["./server"] or package.json main`)
|
||||
return
|
||||
}
|
||||
|
||||
return target
|
||||
@@ -189,7 +184,7 @@ export async function checkPluginCompatibility(target: string, opencodeVersion:
|
||||
|
||||
export async function resolvePluginTarget(spec: string, parsed = parsePluginSpecifier(spec)) {
|
||||
if (isPathPluginSpec(spec)) return resolvePathPluginTarget(spec)
|
||||
return BunProc.install(parsed.pkg, parsed.version)
|
||||
return BunProc.install(parsed.pkg, parsed.version, { ignoreScripts: true })
|
||||
}
|
||||
|
||||
export async function readPluginPackage(target: string): Promise<PluginPackage> {
|
||||
|
||||
Reference in New Issue
Block a user