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:
@@ -37,7 +37,8 @@ env)
|
|||||||
cn_ai_render_codex_config "$provider" "$model" "$key"
|
cn_ai_render_codex_config "$provider" "$model" "$key"
|
||||||
exec "$command"
|
exec "$command"
|
||||||
fi
|
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"
|
exec "$command"
|
||||||
;;
|
;;
|
||||||
native)
|
native)
|
||||||
|
|||||||
@@ -32,13 +32,29 @@ if [[ $level == "unsupported" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
resolved=$(cn_ai_model_by_alias "$provider" "$model" 2>/dev/null || true)
|
allowlist=$(cn_ai_combo_models "$harness" "$provider")
|
||||||
if [[ -n $resolved ]]; then
|
if [[ -n $allowlist ]]; then
|
||||||
model="$resolved"
|
# Combo-restricted model set (e.g. codex uses its own catalog slugs)
|
||||||
elif ! cn_ai_models "$provider" | grep -qxF "$model"; then
|
if ! grep -qxF "$model" <<<"$allowlist"; then
|
||||||
echo "Unknown model for $provider: $model" >&2
|
echo "Model $model not supported for $harness x $provider" >&2
|
||||||
echo "Available: $(cn_ai_models "$provider" | tr '\n' ' ')" >&2
|
echo "Supported: $(tr '\n' ' ' <<<"$allowlist")" >&2
|
||||||
exit 1
|
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
|
fi
|
||||||
|
|
||||||
mkdir -p "$CN_AI_PROFILE_DIR"
|
mkdir -p "$CN_AI_PROFILE_DIR"
|
||||||
|
|||||||
+47
-21
@@ -35,6 +35,16 @@ cn_ai_combo_level() {
|
|||||||
jq -r --arg h "$1" --arg p "$2" '.combos[$h][$p].level // "unsupported"' "$CN_AI_COMPAT"
|
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
|
# Profile files are flat key="value" lines
|
||||||
cn_ai_profile_field() {
|
cn_ai_profile_field() {
|
||||||
local file="$CN_AI_PROFILE_DIR/$1.toml" key="$2"
|
local file="$CN_AI_PROFILE_DIR/$1.toml" key="$2"
|
||||||
@@ -60,7 +70,9 @@ cn_ai_render_env() {
|
|||||||
base=$(cn_ai_endpoint "$provider" anthropic)
|
base=$(cn_ai_endpoint "$provider" anthropic)
|
||||||
fast=$(cn_ai_fast_model "$provider")
|
fast=$(cn_ai_fast_model "$provider")
|
||||||
printf 'export ANTHROPIC_BASE_URL=%q\n' "$base"
|
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_AUTH_TOKEN=%q\n' "$key"
|
||||||
|
printf 'export ANTHROPIC_API_KEY=%q\n' "$key"
|
||||||
printf 'export ANTHROPIC_MODEL=%q\n' "$model"
|
printf 'export ANTHROPIC_MODEL=%q\n' "$model"
|
||||||
printf 'export ANTHROPIC_DEFAULT_SONNET_MODEL=%q\n' "$model"
|
printf 'export ANTHROPIC_DEFAULT_SONNET_MODEL=%q\n' "$model"
|
||||||
printf 'export ANTHROPIC_DEFAULT_OPUS_MODEL=%q\n' "$model"
|
printf 'export ANTHROPIC_DEFAULT_OPUS_MODEL=%q\n' "$model"
|
||||||
@@ -80,7 +92,8 @@ cn_ai_render_env() {
|
|||||||
esac
|
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() {
|
cn_ai_render_codex_config() {
|
||||||
local provider="$1" model="$2" key="$3"
|
local provider="$1" model="$2" key="$3"
|
||||||
local base cfg="$HOME/.codex/config.toml"
|
local base cfg="$HOME/.codex/config.toml"
|
||||||
@@ -93,34 +106,47 @@ cn_ai_render_codex_config() {
|
|||||||
|
|
||||||
mkdir -p "${cfg%/*}"
|
mkdir -p "${cfg%/*}"
|
||||||
touch "$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 first, then check for an unmanaged provider table
|
||||||
# Strip our old blocks and any pre-section model keys, keep the rest intact.
|
|
||||||
awk '
|
awk '
|
||||||
/^# OmarchyCN ai (model|provider) begin$/ { skip = 1; next }
|
/^# OmarchyCN ai (model|provider) begin$/ { skip = 1; next }
|
||||||
/^# OmarchyCN ai (model|provider) end$/ { skip = 0; next }
|
/^# OmarchyCN ai (model|provider) end$/ { skip = 0; next }
|
||||||
skip { next }
|
skip { next }
|
||||||
/^\[/ { in_section = 1 }
|
/^\[/ { in_section = 1 }
|
||||||
!in_section && /^(model|model_provider) = / { next }
|
!in_section && /^(model|model_provider|model_catalog_json)[[:space:]]*=/ { next }
|
||||||
{ print }
|
{ print }
|
||||||
' "$cfg" > "$cfg.omarchycn-tmp"
|
' "$cfg" > "$cfg.omarchycn-tmp"
|
||||||
|
|
||||||
{
|
if grep -qE "^\[model_providers\.$provider\]" "$cfg.omarchycn-tmp"; then
|
||||||
echo "# OmarchyCN ai model begin"
|
rm -f "$cfg.omarchycn-tmp"
|
||||||
echo "model = \"$model\""
|
echo "codex: $cfg 已有非托管的 [model_providers.$provider],请手动清理后重试" >&2
|
||||||
echo "model_provider = \"$provider\""
|
return 1
|
||||||
echo "# OmarchyCN ai model end"
|
fi
|
||||||
cat "$cfg.omarchycn-tmp"
|
|
||||||
echo "# OmarchyCN ai provider begin"
|
if [[ -s $cfg ]]; then
|
||||||
echo "[model_providers.$provider]"
|
cp "$cfg" "$cfg.omarchycn-bak-$(date +%Y%m%d-%H%M%S)"
|
||||||
echo "name = \"$provider\""
|
fi
|
||||||
echo "base_url = \"$base\""
|
|
||||||
echo "experimental_bearer_token = \"$key\""
|
cp "$OMARCHY_PATH/cn/registry/codex-deepseek-models.json" "$HOME/.codex/models.json"
|
||||||
echo "# OmarchyCN ai provider end"
|
|
||||||
} > "$cfg"
|
(
|
||||||
|
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"
|
rm -f "$cfg.omarchycn-tmp"
|
||||||
chmod 600 "$cfg"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,13 @@
|
|||||||
"codex": {
|
"codex": {
|
||||||
"deepseek": {
|
"deepseek": {
|
||||||
"level": "official-doc",
|
"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": {
|
"opencode": {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user