From 6d22d4920ebcf7b59e35c38cd9008f554dfc9ae8 Mon Sep 17 00:00:00 2001 From: OoO Date: Sun, 24 May 2026 15:36:16 +0800 Subject: [PATCH] V10.422 persist 111 Ollama proxy launch agent --- config.py | 2 +- docs/AI_INTELLIGENCE_MODULE_SOT.md | 4 +- docs/memory/history_logs.md | 1 + scripts/ops/install_ollama111_allow_proxy.sh | 108 +++++++++++++++++++ scripts/ops/ollama111_allow_proxy.py | 0 5 files changed, 112 insertions(+), 3 deletions(-) create mode 100755 scripts/ops/install_ollama111_allow_proxy.sh mode change 100644 => 100755 scripts/ops/ollama111_allow_proxy.py diff --git a/config.py b/config.py index 75bd402..1d2170d 100644 --- a/config.py +++ b/config.py @@ -325,7 +325,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.421" +SYSTEM_VERSION = "V10.422" LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log') public_url = PUBLIC_URL # 用於模板顯示 diff --git a/docs/AI_INTELLIGENCE_MODULE_SOT.md b/docs/AI_INTELLIGENCE_MODULE_SOT.md index 57e4ff1..a19c71c 100644 --- a/docs/AI_INTELLIGENCE_MODULE_SOT.md +++ b/docs/AI_INTELLIGENCE_MODULE_SOT.md @@ -2,7 +2,7 @@ > **最後更新**: 2026-05-24 (台北時間) > **狀態**: 🟢 四 AI Agent 自動化閉環已落地;LLM 路由紅線升級為 Ollama-first 三主機級聯,Gemini 備援預設關閉 -> **適用版本**: V10.420 +> **適用版本**: V10.422 --- @@ -31,7 +31,7 @@ - Gemini 不可被任何狀態面板或 router 推薦為主提供者:`AIProviderService._get_recommended_provider()` 不得回傳 `gemini`,只能顯示為 fallback 狀態;`llm_model_router` 的 `ea_engine` 若收到 `gemini-*` default 必須改回 `hermes3:latest`,需要深推理時才升本地 `deepseek-r1:14b`。 - ElephantAlpha prompt / agent registry 不得再把 OpenClaw 描述為 Gemini 主模型;OpenClaw 是 `qwen2.5-coder:7b` / `qwen3:14b` Ollama-first 策略師,Gemini 僅能在 guard 顯式解鎖後作 emergency fallback。 - 111 `192.168.0.111` 只是最後一道 Mac fallback,不承接 7B+、vision、long-context 模型長駐;`OllamaService.generate()` 落到 111 時會將 `qwen3`、`deepseek-r1`、`hermes3`、`qwen2.5*`、`gemma3`、`llava`、`minicpm-v` 與 7B+ 模型依 `OLLAMA_111_MODEL_DOWNGRADE_PATTERNS` 降級到 `OLLAMA_111_MODEL_FALLBACK=llama3.2:latest`,並以 `OLLAMA_111_KEEP_ALIVE=5m`、`OLLAMA_111_MAX_TIMEOUT=20`、`OLLAMA_111_NUM_CTX=4096`、`OLLAMA_111_NUM_PREDICT=512` 封頂。OpenClaw 報告型路徑的業務 keep-alive 預設 `5m`;Code Review 以 `CODE_REVIEW_ALLOW_111_FALLBACK=false`、Hermes 以 `HERMES_ALLOW_111_FALLBACK=false` 預設跳過 111,避免 16GB RAM 主機與 GCP-B 被長駐 runner、長輸出與 24h keep-alive 壓到高 load。 -- 111 的 LAN 入口必須經 `scripts/ops/ollama111_allow_proxy.py` allowlist proxy:真實 Ollama 綁 `127.0.0.1:11434`,proxy 綁 `192.168.0.111:11434`,預設只允許 111 本機與 188 生產宿主;110 / 121 / 其他 LAN client 不能直接打 111,避免跨專案 CI 或 VM 繞過 momo-pro router 載入 7B+ runner。 +- 111 的 LAN 入口必須經 `scripts/ops/ollama111_allow_proxy.py` allowlist proxy:真實 Ollama 綁 `127.0.0.1:11434`,proxy 綁 `192.168.0.111:11434`,預設只允許 111 本機與 188 生產宿主;110 / 121 / 其他 LAN client 不能直接打 111,避免跨專案 CI 或 VM 繞過 momo-pro router 載入 7B+ runner。111 上以 `scripts/ops/install_ollama111_allow_proxy.sh` 安裝 user LaunchAgent,讓 proxy 與 `OLLAMA_HOST=127.0.0.1:11434` 在登入/重啟後自動恢復。 - ElephantAlpha 的 `price_drop_alert` / `market_opportunity` Telegram HITL 告警必須把同款證據獨立呈現,至少包含 `match_type`、`price_basis`、`alert_tier` 與 `match_score`;沒有高信心同款與總價可比證據時,不得把 PChome/MOMO 價差寫成可直接跟價建議。 ## 一、四 AI Agent 路由架構 diff --git a/docs/memory/history_logs.md b/docs/memory/history_logs.md index cc0faaf..8dcfc7f 100644 --- a/docs/memory/history_logs.md +++ b/docs/memory/history_logs.md @@ -13,6 +13,7 @@ ## 📅 詳細更新日誌 (考古存檔) ### 2026-05-24:PChome 近門檻身份回收第二輪 +- **V10.422 111 proxy LaunchAgent 持久化**: 新增 `scripts/ops/install_ollama111_allow_proxy.sh`,在 111 以 user LaunchAgent 安裝 `com.momo.ollama111-allow-proxy`,啟動時設定 `OLLAMA_HOST=127.0.0.1:11434`、重啟 Ollama、載入 allowlist proxy,避免重開機或重新登入後 111 又回到 LAN 全開狀態。 - **V10.421 Kanebo Milano / hoi 蠟燭品類防錯配**: marketplace matcher 追加 `kanebo_milano_type_conflict` 與 `hoi_candle_line_conflict`,將 Kanebo Milano Collection 蜜粉餅 vs 絕色香水、hoi 日京山風香氛蠟燭 vs hoi!LAB 實驗室香氛蠟燭經典篇列為 hard veto;同品牌、同系列字樣或同容量仍不可跨品類/跨產品線直接比價。 - **V10.420 111 Ollama LAN allowlist proxy**: 追查 111 高負載時確認來源不是 momo-pro,而是 110 上 `awoooi-cd` 臨時測試與 121 VMware VM 直接打 `192.168.0.111:11434`,繞過 `ai_calls` 與 momo-pro router 載入 7B runner。新增 `scripts/ops/ollama111_allow_proxy.py`,將真實 Ollama 收斂到 `127.0.0.1:11434`,由 user-space proxy 綁 `192.168.0.111:11434` 並預設只允許 111 本機與 188 生產宿主;110 / 121 會被 reset,111 fallback 保留給 momo production。 - **V10.419 Dr.Hsieh LabSmart 精華品線防錯配**: marketplace matcher 追加 `dr_hsieh_labsmart_line_conflict`,只針對 Dr.Hsieh/達特醫的 `LabSmart Hi-Tech` / `LabSmart Classic` 精華被拿去對 `神經醯胺多重修復保濕精華液` 的近門檻錯配做 hard veto;同品牌同容量但不同產品線不再因規格相同停在 `true_low_confidence` 或被誤推進比價。 diff --git a/scripts/ops/install_ollama111_allow_proxy.sh b/scripts/ops/install_ollama111_allow_proxy.sh new file mode 100755 index 0000000..dad6754 --- /dev/null +++ b/scripts/ops/install_ollama111_allow_proxy.sh @@ -0,0 +1,108 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Install a user LaunchAgent that keeps the 111 Ollama LAN entrypoint behind +# scripts/ops/ollama111_allow_proxy.py. This avoids sudo/pfctl and keeps the +# real Ollama process bound to localhost while exposing an allowlisted LAN port. + +PROJECT_DIR="${PROJECT_DIR:-$(cd "$(dirname "$0")/../.." && pwd)}" +LABEL="${OLLAMA111_PROXY_LABEL:-com.momo.ollama111-allow-proxy}" +PLIST_DIR="${HOME}/Library/LaunchAgents" +PLIST_PATH="${PLIST_DIR}/${LABEL}.plist" +LOG_DIR="${HOME}/Library/Logs" +PID_FILE="${HOME}/.ollama/ollama111-allow-proxy.pid" +PYTHON_BIN="${PYTHON_BIN:-/usr/bin/python3}" +OLLAMA_APP="${OLLAMA_APP:-/Applications/Ollama.app}" +OLLAMA_HOST_VALUE="${OLLAMA_HOST_VALUE:-127.0.0.1:11434}" +ALLOWED_CIDRS="${OLLAMA111_PROXY_ALLOWED_CIDRS:-127.0.0.1/32,192.168.0.80/32,192.168.0.111/32,192.168.0.188/32}" +GUI_DOMAIN="gui/$(id -u)" + +if [[ ! -f "${PROJECT_DIR}/scripts/ops/ollama111_allow_proxy.py" ]]; then + echo "missing proxy script under PROJECT_DIR=${PROJECT_DIR}" >&2 + exit 1 +fi + +mkdir -p "${PLIST_DIR}" "${LOG_DIR}" "${HOME}/.ollama" + +launchctl setenv OLLAMA_HOST "${OLLAMA_HOST_VALUE}" + +# Stop the ad-hoc nohup proxy from the initial incident response, if present. +if [[ -f "${PID_FILE}" ]]; then + old_pid="$(cat "${PID_FILE}" 2>/dev/null || true)" + if [[ -n "${old_pid}" ]]; then + kill "${old_pid}" >/dev/null 2>&1 || true + fi + rm -f "${PID_FILE}" +fi +while IFS= read -r old_proxy_pid; do + [[ -n "${old_proxy_pid}" ]] && kill "${old_proxy_pid}" >/dev/null 2>&1 || true +done < <(pgrep -f '[o]llama111_allow_proxy.py' || true) + +# Restart Ollama so it observes the launchd user environment. The pgrep pattern +# intentionally avoids matching this installer command. +osascript -e 'quit app "Ollama"' >/dev/null 2>&1 || true +while IFS= read -r old_ollama_pid; do + [[ -n "${old_ollama_pid}" ]] && kill "${old_ollama_pid}" >/dev/null 2>&1 || true +done < <(pgrep -f '[o]llama serve' || true) +sleep 2 +open "${OLLAMA_APP}" + +for _ in $(seq 1 20); do + if curl -fsS --max-time 2 "http://${OLLAMA_HOST_VALUE}/api/version" >/dev/null 2>&1; then + break + fi + sleep 1 +done + +cat > "${PLIST_PATH}" < + + + + Label + ${LABEL} + ProgramArguments + + ${PYTHON_BIN} + ${PROJECT_DIR}/scripts/ops/ollama111_allow_proxy.py + + WorkingDirectory + ${PROJECT_DIR} + EnvironmentVariables + + OLLAMA111_PROXY_ALLOWED_CIDRS + ${ALLOWED_CIDRS} + OLLAMA111_PROXY_LISTEN_HOST + 192.168.0.111 + OLLAMA111_PROXY_LISTEN_PORT + 11434 + OLLAMA111_PROXY_TARGET_HOST + 127.0.0.1 + OLLAMA111_PROXY_TARGET_PORT + 11434 + PYTHONUNBUFFERED + 1 + + RunAtLoad + + KeepAlive + + StandardOutPath + ${LOG_DIR}/ollama111-allow-proxy.log + StandardErrorPath + ${LOG_DIR}/ollama111-allow-proxy.err.log + + +PLIST + +launchctl bootout "${GUI_DOMAIN}" "${PLIST_PATH}" >/dev/null 2>&1 || true +launchctl bootstrap "${GUI_DOMAIN}" "${PLIST_PATH}" +launchctl kickstart -k "${GUI_DOMAIN}/${LABEL}" + +sleep 2 +echo "installed ${LABEL}" +echo "plist=${PLIST_PATH}" +echo "allowed=${ALLOWED_CIDRS}" +launchctl print "${GUI_DOMAIN}/${LABEL}" | head -40 || true +tail -20 "${LOG_DIR}/ollama111-allow-proxy.log" || true diff --git a/scripts/ops/ollama111_allow_proxy.py b/scripts/ops/ollama111_allow_proxy.py old mode 100644 new mode 100755