Files
wehub-resource-sync b3a7f98e5a
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:23:53 +08:00

99 lines
3.3 KiB
JavaScript

#!/usr/bin/env node
// Resolves the model alias from a /bonk, /review, or @ask-bonk comment body
// and emits the model id and OPENCODE_CONFIG_CONTENT for the ask-bonk action.
//
// Inputs (env):
// BODY — the raw comment / review body
// GITHUB_OUTPUT — path to the workflow step output file
//
// Outputs (to $GITHUB_OUTPUT):
// alias — resolved alias (default if none requested)
// model — full model id passed to ask-bonk's `model:` input
// opencode_config — JSON string for OPENCODE_CONFIG_CONTENT env var
//
// The first word after a trigger ("/bonk", "/review", or "@ask-bonk") selects
// an alias from .github/bonk-models.json. An absent or unknown word falls
// back to the registry's `default`. Only the selected model is registered in
// the opencode provider config; the rest of the registry stays unused at
// runtime to keep the env var small.
import { appendFileSync, readFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const here = dirname(fileURLToPath(import.meta.url));
const registryPath = resolve(here, "..", "bonk-models.json");
const registry = JSON.parse(readFileSync(registryPath, "utf8"));
const body = process.env.BODY ?? "";
// Match a trigger preceded by start-of-string or whitespace, then capture the
// next bare word. The leading-boundary guard avoids matching "/bonk" as a
// substring of unrelated text (e.g. a URL fragment).
const triggerRe = /(?:^|\s)(?:\/bonk|\/review|@ask-bonk)\s+([a-zA-Z][a-zA-Z0-9_-]*)/;
const match = body.match(triggerRe);
const requested = match ? match[1].toLowerCase() : null;
const fallback = registry.default;
const alias = requested && registry.models[requested] ? requested : fallback;
const entry = registry.models[alias];
if (!entry) {
console.error(`bonk-models.json default "${fallback}" missing from models map`);
process.exit(1);
}
const model = `cloudflare-ai-gateway/${entry.id}`;
// OPENCODE_CONFIG_CONTENT bundles two unrelated overrides:
//
// 1. Register the selected model with the pinned opencode version. Without
// this, opencode raises ProviderModelNotFoundError on any model whose
// release_date is after its bundled models.dev snapshot.
//
// 2. Resolve the two opencode permission defaults that ask interactively
// (`external_directory` and `doom_loop`) so a CI run with no TTY can
// never deadlock waiting for approval. external_directory is
// deny-by-default with /tmp/** and ~/** allowed (scratch files,
// home-dir caches); doom_loop is deny so a stuck loop aborts instead
// of prompting. Repro: PR #769 timed out at 30 min waiting for an
// `external_directory` prompt on `git show ... > /tmp/foo`.
const opencodeConfig = {
permission: {
external_directory: {
"*": "deny",
"/tmp/**": "allow",
"~/**": "allow",
},
doom_loop: "deny",
},
provider: {
"cloudflare-ai-gateway": {
models: {
[entry.id]: entry.registration,
},
},
},
};
const out = process.env.GITHUB_OUTPUT;
if (!out) {
console.error("GITHUB_OUTPUT is not set");
process.exit(1);
}
const eof = "OPENCODE_CONFIG_EOF";
appendFileSync(
out,
[
`alias=${alias}`,
`requested=${requested ?? ""}`,
`model=${model}`,
`opencode_config<<${eof}`,
JSON.stringify(opencodeConfig),
eof,
"",
].join("\n"),
);
console.log(`Resolved alias "${alias}" -> ${model}`);