AI: harness-aware model validation, official codex contract, launch fail-fast

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QKxGW1raAWaqeU8WdHsMsp
This commit is contained in:
2026-08-24 20:38:43 -04:00
co-authored by Claude Fable 5
parent 02d0d5c991
commit 717ba305bf
5 changed files with 285 additions and 30 deletions
+2 -1
View File
@@ -37,7 +37,8 @@ env)
cn_ai_render_codex_config "$provider" "$model" "$key"
exec "$command"
fi
eval "$(cn_ai_render_env "$harness" "$provider" "$model" "$key")"
env_exports=$(cn_ai_render_env "$harness" "$provider" "$model" "$key")
eval "$env_exports"
exec "$command"
;;
native)
+23 -7
View File
@@ -32,13 +32,29 @@ if [[ $level == "unsupported" ]]; then
exit 1
fi
resolved=$(cn_ai_model_by_alias "$provider" "$model" 2>/dev/null || true)
if [[ -n $resolved ]]; then
model="$resolved"
elif ! cn_ai_models "$provider" | grep -qxF "$model"; then
echo "Unknown model for $provider: $model" >&2
echo "Available: $(cn_ai_models "$provider" | tr '\n' ' ')" >&2
exit 1
allowlist=$(cn_ai_combo_models "$harness" "$provider")
if [[ -n $allowlist ]]; then
# Combo-restricted model set (e.g. codex uses its own catalog slugs)
if ! grep -qxF "$model" <<<"$allowlist"; then
echo "Model $model not supported for $harness x $provider" >&2
echo "Supported: $(tr '\n' ' ' <<<"$allowlist")" >&2
exit 1
fi
else
resolved=$(cn_ai_model_by_alias "$provider" "$model" 2>/dev/null || true)
if [[ -n $resolved ]]; then
model="$resolved"
elif ! cn_ai_models "$provider" | grep -qxF "$model"; then
echo "Unknown model for $provider: $model" >&2
echo "Available: $(cn_ai_models "$provider" | tr '\n' ' ')" >&2
exit 1
fi
model_proto=$(cn_ai_model_protocol "$provider" "$model")
harness_proto=$(cn_ai_harness_field "$harness" protocol)
if [[ -n $model_proto && $model_proto != "$harness_proto" ]]; then
echo "Model $model speaks $model_proto, but $harness needs $harness_proto" >&2
exit 1
fi
fi
mkdir -p "$CN_AI_PROFILE_DIR"
+47 -21
View File
@@ -35,6 +35,16 @@ cn_ai_combo_level() {
jq -r --arg h "$1" --arg p "$2" '.combos[$h][$p].level // "unsupported"' "$CN_AI_COMPAT"
}
# Combo-specific model allowlist; empty output means no restriction
cn_ai_combo_models() {
jq -r --arg h "$1" --arg p "$2" '.combos[$h][$p].models // [] | .[]' "$CN_AI_COMPAT"
}
cn_ai_model_protocol() {
jq -r --arg p "$1" --arg m "$2" \
'.providers[$p].models[] | select(.id == $m) | .protocol // ""' "$CN_AI_PROVIDERS"
}
# Profile files are flat key="value" lines
cn_ai_profile_field() {
local file="$CN_AI_PROFILE_DIR/$1.toml" key="$2"
@@ -60,7 +70,9 @@ cn_ai_render_env() {
base=$(cn_ai_endpoint "$provider" anthropic)
fast=$(cn_ai_fast_model "$provider")
printf 'export ANTHROPIC_BASE_URL=%q\n' "$base"
# Docs vary between AUTH_TOKEN (deepseek/zai) and API_KEY (kimi): set both
printf 'export ANTHROPIC_AUTH_TOKEN=%q\n' "$key"
printf 'export ANTHROPIC_API_KEY=%q\n' "$key"
printf 'export ANTHROPIC_MODEL=%q\n' "$model"
printf 'export ANTHROPIC_DEFAULT_SONNET_MODEL=%q\n' "$model"
printf 'export ANTHROPIC_DEFAULT_OPUS_MODEL=%q\n' "$model"
@@ -80,7 +92,8 @@ cn_ai_render_env() {
esac
}
# Write ~/.codex/config.toml provider block (official DeepSeek codex format)
# Write ~/.codex/config.toml + models.json per DeepSeek's official codex
# integration contract (mirrors cdn.deepseek.com codex-deepseek-setup script)
cn_ai_render_codex_config() {
local provider="$1" model="$2" key="$3"
local base cfg="$HOME/.codex/config.toml"
@@ -93,34 +106,47 @@ cn_ai_render_codex_config() {
mkdir -p "${cfg%/*}"
touch "$cfg"
if [[ -s $cfg ]]; then
cp "$cfg" "$cfg.omarchycn-bak-$(date +%Y%m%d-%H%M%S)"
fi
# Top-level keys must precede the first [section]; provider table goes last.
# Strip our old blocks and any pre-section model keys, keep the rest intact.
# Strip our old blocks first, then check for an unmanaged provider table
awk '
/^# OmarchyCN ai (model|provider) begin$/ { skip = 1; next }
/^# OmarchyCN ai (model|provider) end$/ { skip = 0; next }
skip { next }
/^\[/ { in_section = 1 }
!in_section && /^(model|model_provider) = / { next }
!in_section && /^(model|model_provider|model_catalog_json)[[:space:]]*=/ { next }
{ print }
' "$cfg" > "$cfg.omarchycn-tmp"
{
echo "# OmarchyCN ai model begin"
echo "model = \"$model\""
echo "model_provider = \"$provider\""
echo "# OmarchyCN ai model end"
cat "$cfg.omarchycn-tmp"
echo "# OmarchyCN ai provider begin"
echo "[model_providers.$provider]"
echo "name = \"$provider\""
echo "base_url = \"$base\""
echo "experimental_bearer_token = \"$key\""
echo "# OmarchyCN ai provider end"
} > "$cfg"
if grep -qE "^\[model_providers\.$provider\]" "$cfg.omarchycn-tmp"; then
rm -f "$cfg.omarchycn-tmp"
echo "codex: $cfg 已有非托管的 [model_providers.$provider],请手动清理后重试" >&2
return 1
fi
if [[ -s $cfg ]]; then
cp "$cfg" "$cfg.omarchycn-bak-$(date +%Y%m%d-%H%M%S)"
fi
cp "$OMARCHY_PATH/cn/registry/codex-deepseek-models.json" "$HOME/.codex/models.json"
(
umask 077
{
echo "# OmarchyCN ai model begin"
echo "model = \"$model\""
echo "model_provider = \"$provider\""
echo "model_catalog_json = \"~/.codex/models.json\""
echo "# OmarchyCN ai model end"
cat "$cfg.omarchycn-tmp"
echo "# OmarchyCN ai provider begin"
echo "[model_providers.$provider]"
echo "name = \"$provider\""
echo "base_url = \"$base\""
echo "wire_api = \"responses\""
echo "experimental_bearer_token = \"$key\""
echo "# OmarchyCN ai provider end"
} > "$cfg.omarchycn-new"
)
mv "$cfg.omarchycn-new" "$cfg"
rm -f "$cfg.omarchycn-tmp"
chmod 600 "$cfg"
}
+7 -1
View File
@@ -18,7 +18,13 @@
"codex": {
"deepseek": {
"level": "official-doc",
"doc": "https://api-docs.deepseek.com/quick_start/agent_integrations/codex/"
"doc": "https://api-docs.deepseek.com/quick_start/agent_integrations/codex/",
"models": [
"deepseek-v4-flash",
"deepseek-v4-pro",
"deepseek-v4-flash-vision-exp"
],
"catalog": "codex-deepseek-models.json"
}
},
"opencode": {
File diff suppressed because one or more lines are too long