mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-15 07:48:24 -04:00
cli: inline text imports as content in the node bundle
Vite's built-in asset plugin claims known asset types (.txt) before normal-priority plugins load, rewriting the import to an asset URL string — the models.dev snapshot shipped as "/assets/snapshot-*.txt" and cold-cache catalog access died decoding it. Pre-existing instances of the same class: the node bundle's prompt and tool-description .txt imports. enforce: "pre" intercepts first; a build assertion now fails the build if text imports surface as asset URLs, since the bundle still builds and runs --help convincingly without their content. Also: drop the redundant text.d.ts (bun-types already declares *.txt), give the snapshot refresh script a provider-count floor and Windows-safe path printing.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import { spawnSync } from "node:child_process"
|
||||
import { createHash } from "node:crypto"
|
||||
import { chmod, copyFile, mkdir, mkdtemp, realpath, rename, rm, stat, writeFile } from "node:fs/promises"
|
||||
import { chmod, copyFile, mkdir, mkdtemp, readFile, realpath, rename, rm, stat, writeFile } from "node:fs/promises"
|
||||
import os from "node:os"
|
||||
import path from "node:path"
|
||||
import { build } from "vite"
|
||||
@@ -55,6 +55,25 @@ const builder =
|
||||
? await resolveHostNode()
|
||||
: undefined
|
||||
|
||||
// Vite silently rewrites text imports of known asset types (.txt) to asset
|
||||
// URL strings when the raw-text plugin doesn't intercept them first — the
|
||||
// bundle still builds and `--help` still runs, so only content assertions
|
||||
// catch it. Guards the models.dev snapshot and the prompt/tool description
|
||||
// text that ships inside the bundle.
|
||||
async function assertTextImportsInlined(bundlePath: string) {
|
||||
const bundle = await readFile(bundlePath, "utf8")
|
||||
const markers = [
|
||||
{ marker: '"zhipuai"', source: "models-dev snapshot" },
|
||||
{ marker: "/assets/snapshot", source: "models-dev snapshot inlined as asset URL", forbidden: true },
|
||||
{ marker: '="/assets/', source: "text import inlined as asset URL", forbidden: true },
|
||||
]
|
||||
for (const { marker, source, forbidden } of markers) {
|
||||
const present = bundle.includes(marker)
|
||||
if (forbidden ? present : !present)
|
||||
throw new Error(`${bundlePath}: ${source} — text imports are not inlined as content (marker ${marker})`)
|
||||
}
|
||||
}
|
||||
|
||||
for (const target of targets) {
|
||||
console.log(`building cli-node-${targetName(target)}`)
|
||||
const assets = await collectNodeAssets(target)
|
||||
@@ -63,6 +82,7 @@ for (const target of targets) {
|
||||
const input = { version: Script.version, channel: Script.channel, assetHash, target }
|
||||
await copyNodeAssets(assets)
|
||||
await build(mainConfig(input))
|
||||
await assertTextImportsInlined("dist-node/opencode.mjs")
|
||||
|
||||
const host = target.platform === process.platform && target.arch === process.arch
|
||||
if (host) {
|
||||
|
||||
@@ -10,6 +10,11 @@ const dir = import.meta.dirname
|
||||
function rawTextPlugin(): Plugin {
|
||||
return {
|
||||
name: "opencode:raw-text",
|
||||
// "pre" is load-bearing for .txt: Vite's built-in asset plugin claims
|
||||
// known asset types (.txt among them) ahead of normal-priority plugins,
|
||||
// replacing the import with an asset URL string instead of the content.
|
||||
// .md only ever worked without it because .md is not a known asset type.
|
||||
enforce: "pre",
|
||||
async load(id) {
|
||||
if (!id.endsWith(".md") && !id.endsWith(".txt")) return
|
||||
return `export default ${JSON.stringify(await readFile(id, "utf8"))}`
|
||||
|
||||
@@ -12,10 +12,13 @@ if (!response.ok) {
|
||||
}
|
||||
const text = await response.text()
|
||||
const parsed: unknown = JSON.parse(text)
|
||||
if (typeof parsed !== "object" || parsed === null || Object.keys(parsed).length === 0) {
|
||||
console.error("Fetched catalog is empty; refusing to write snapshot")
|
||||
// A floor, not equality: guards against committing an error page or a
|
||||
// truncated body that still parses as a small object.
|
||||
const MINIMUM_PROVIDERS = 100
|
||||
if (typeof parsed !== "object" || parsed === null || Object.keys(parsed).length < MINIMUM_PROVIDERS) {
|
||||
console.error(`Fetched catalog has fewer than ${MINIMUM_PROVIDERS} providers; refusing to write snapshot`)
|
||||
process.exit(1)
|
||||
}
|
||||
const target = new URL("../src/models-dev/snapshot.txt", import.meta.url)
|
||||
await Bun.write(target, text)
|
||||
console.log(`Wrote ${Object.keys(parsed).length} providers (${text.length} bytes) to ${target.pathname}`)
|
||||
console.log(`Wrote ${Object.keys(parsed).length} providers (${text.length} bytes) to ${Bun.fileURLToPath(target)}`)
|
||||
|
||||
Vendored
-4
@@ -1,4 +0,0 @@
|
||||
declare module "*.txt" {
|
||||
const content: string
|
||||
export default content
|
||||
}
|
||||
Reference in New Issue
Block a user