From bf0d2a4e2adaacc30295bb8bfec56df4a97f79bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 24 Aug 2026 20:58:35 -0400 Subject: [PATCH] AI default/tests: env-passed key, secure creation, harness install, isolated strict mocks Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01QKxGW1raAWaqeU8WdHsMsp --- bin/omarchy-cn-ai-default | 33 ++++++++++++++++++++----------- test/shell.d/omarchycn-ai-test.sh | 24 ++++++++++++++++++++-- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/bin/omarchy-cn-ai-default b/bin/omarchy-cn-ai-default index 4a067a93..9553fc83 100755 --- a/bin/omarchy-cn-ai-default +++ b/bin/omarchy-cn-ai-default @@ -29,6 +29,13 @@ codex) agent="codex" ;; ;; esac +command=$(cn_ai_harness_field "$harness" command) +if ! command -v "$command" > /dev/null 2>&1; then + install=$(cn_ai_harness_field "$harness" install) + echo "Installing $harness: $install" + $install +fi + key=$(omarchy-cn-ai-secret get "$provider") case "$harness" in @@ -44,17 +51,21 @@ claude-code) current=$(cat "$settings") cp "$settings" "$settings.omarchycn-bak-$(date +%Y%m%d-%H%M%S)" fi - jq --arg base "$base" --arg key "$key" --arg model "$model" --arg fast "$fast" \ - '.env = (.env // {}) + { - ANTHROPIC_BASE_URL: $base, - ANTHROPIC_AUTH_TOKEN: $key, - ANTHROPIC_API_KEY: $key, - ANTHROPIC_MODEL: $model, - ANTHROPIC_DEFAULT_SONNET_MODEL: $model, - ANTHROPIC_DEFAULT_OPUS_MODEL: $model, - ANTHROPIC_DEFAULT_HAIKU_MODEL: $fast - }' <<<"$current" > "$settings.omarchycn-new" - chmod 600 "$settings.omarchycn-new" + # Key reaches jq via environment, never the argument list + rm -f "$settings.omarchycn-new" + ( + umask 077 + CN_AI_KEY="$key" jq --arg base "$base" --arg model "$model" --arg fast "$fast" \ + '.env = (.env // {}) + { + ANTHROPIC_BASE_URL: $base, + ANTHROPIC_AUTH_TOKEN: env.CN_AI_KEY, + ANTHROPIC_API_KEY: env.CN_AI_KEY, + ANTHROPIC_MODEL: $model, + ANTHROPIC_DEFAULT_SONNET_MODEL: $model, + ANTHROPIC_DEFAULT_OPUS_MODEL: $model, + ANTHROPIC_DEFAULT_HAIKU_MODEL: $fast + }' <<<"$current" > "$settings.omarchycn-new" + ) mv "$settings.omarchycn-new" "$settings" ;; codex) diff --git a/test/shell.d/omarchycn-ai-test.sh b/test/shell.d/omarchycn-ai-test.sh index 43d48e65..5fe2b1b2 100755 --- a/test/shell.d/omarchycn-ai-test.sh +++ b/test/shell.d/omarchycn-ai-test.sh @@ -19,6 +19,17 @@ cleanup() { trap cleanup EXIT export HOME="$TEST_HOME" +# Force the file backend: production Secret Service / pass must never be touched +mkdir -p "$TEST_HOME/stubs" +printf '#!/bin/bash +exit 1 +' > "$TEST_HOME/stubs/secret-tool" +printf '#!/bin/bash +exit 1 +' > "$TEST_HOME/stubs/pass" +chmod +x "$TEST_HOME/stubs/secret-tool" "$TEST_HOME/stubs/pass" +export PATH="$TEST_HOME/stubs:$PATH" + # Registries parse and carry the P0 providers and harnesses for reg in ai-providers ai-harnesses ai-compatibility; do jq -e . "$ROOT/cn/registry/$reg.json" > /dev/null || fail "$reg.json parses" @@ -91,11 +102,15 @@ python3 - "$port" <<'PYEOF' & import http.server, sys class H(http.server.BaseHTTPRequestHandler): def do_POST(self): - self.rfile.read(int(self.headers.get("Content-Length", 0))) + body = self.rfile.read(int(self.headers.get("Content-Length", 0))) key = self.headers.get("x-api-key") or (self.headers.get("Authorization") or "").replace("Bearer ", "") if key != "sk-secret-1": code = 401 - elif self.path in ("/v1/messages", "/responses", "/chat/completions"): + elif self.path == "/v1/messages" and b"messages" in body and self.headers.get("anthropic-version"): + code = 200 + elif self.path == "/responses" and b"input" in body and b"messages" not in body: + code = 200 + elif self.path == "/chat/completions" and b"messages" in body: code = 200 else: code = 404 @@ -122,6 +137,10 @@ fi pass "mock regression: 200 pass, 401 fail, responses path exercised" # ai-default merges into claude settings without clobbering user config +printf '#!/bin/bash +exit 0 +' > "$TEST_HOME/stubs/claude" +chmod +x "$TEST_HOME/stubs/claude" echo "sk-secret-1" | omarchy-cn-ai-secret set deepseek > /dev/null mkdir -p "$HOME/.claude" printf '{"permissions":{"allow":["Bash"]},"env":{"KEEP":"1"}}' > "$HOME/.claude/settings.json" @@ -130,4 +149,5 @@ omarchy-cn-ai-default good > /dev/null [[ $(jq -r '.permissions.allow[0]' "$HOME/.claude/settings.json") == Bash ]] || fail "ai-default preserves permissions" [[ $(jq -r '.env.ANTHROPIC_BASE_URL' "$HOME/.claude/settings.json") == "https://api.deepseek.com/anthropic" ]] || fail "ai-default env written" [[ $(cat "$HOME/.config/omarchy/defaults/agent") == claude ]] || fail "upstream default agent set" +[[ $(stat -c %a "$HOME/.claude/settings.json") == 600 ]] || fail "claude settings 0600" pass "ai-default maps the profile onto the upstream agent entry"