diff --git a/README.md b/README.md index 0d9f564..9e01838 100644 --- a/README.md +++ b/README.md @@ -333,6 +333,12 @@ env = { "FACE_WS_URL" = "ws://127.0.0.1:8765/ws", "MCP_TOOL_NAME_STYLE" = "under `run-bound-mcp-server.sh` starts the MCP server and preserves `MH_FACE_AGENT_ID` / `MH_FACE_AGENT_LABEL` from the current agent process or its parent process when available. This lets `face_ping`, `face_event`, and `face_say` omit `agent_id` in operator/helper panes that were launched by Minimum Headroom. +When face-app is bound outside loopback and requires `MH_FACE_AUTH_TOKEN`, the +same wrapper forwards `MH_FACE_AUTH_TOKEN` from the current environment, from a +parent process, or from `MH_FACE_ENV_FILE`. The default env file is +`~/.config/minimum-headroom.env`. Keep real tokens out of checked-in Codex +config files. + ### Gemini CLI Use `doc/examples/antigravity/mcp_config.json` as a template. Place in `~/.gemini/` or a project-local `.gemini/` folder. Gemini requires `MCP_TOOL_NAME_STYLE=underscore`. @@ -743,6 +749,12 @@ env = { "FACE_WS_URL" = "ws://127.0.0.1:8765/ws", "MCP_TOOL_NAME_STYLE" = "under `run-bound-mcp-server.sh` は MCP server を起動し、可能な場合は現在の agent process または親 process から `MH_FACE_AGENT_ID` / `MH_FACE_AGENT_LABEL` を引き継ぎます。Minimum Headroom から起動された operator/helper pane では、これにより `face_ping` / `face_event` / `face_say` の `agent_id` 省略が可能になります。 +face-app をループバック外に bind して `MH_FACE_AUTH_TOKEN` が必要な場合、 +同じ wrapper は現在の環境・親 process・`MH_FACE_ENV_FILE` から +`MH_FACE_AUTH_TOKEN` を転送します。既定の env file は +`~/.config/minimum-headroom.env` です。実 token は Codex config に +チェックインしないでください。 + ### Gemini CLI `doc/examples/antigravity/mcp_config.json` をテンプレートとして使い、`~/.gemini/` またはプロジェクト内 `.gemini/` に配置。Gemini は `MCP_TOOL_NAME_STYLE=underscore` が必要です。 diff --git a/asr-worker/pyproject.toml b/asr-worker/pyproject.toml index 33f8485..a78b27c 100644 --- a/asr-worker/pyproject.toml +++ b/asr-worker/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "asr-worker" -version = "1.13.12" +version = "1.15.1" description = "Local ASR worker for english-trainer (Parakeet EN/JA routing)" readme = "README.md" requires-python = ">=3.10" diff --git a/asr-worker/uv.lock b/asr-worker/uv.lock index 20425ef..e65c6a5 100644 --- a/asr-worker/uv.lock +++ b/asr-worker/uv.lock @@ -247,7 +247,7 @@ wheels = [ [[package]] name = "asr-worker" -version = "1.13.12" +version = "1.15.1" source = { editable = "." } dependencies = [ { name = "fastapi" }, diff --git a/doc/examples/codex/config.toml b/doc/examples/codex/config.toml index a217670..db53c00 100644 --- a/doc/examples/codex/config.toml +++ b/doc/examples/codex/config.toml @@ -9,3 +9,9 @@ env = { "FACE_WS_URL" = "ws://127.0.0.1:8765/ws", "MCP_TOOL_NAME_STYLE" = "under # The wrapper preserves MH_FACE_AGENT_ID / MH_FACE_AGENT_LABEL from the current # agent process or its parent when available, so face_* tools can omit agent_id. +# +# If face-app is bound outside loopback and requires MH_FACE_AUTH_TOKEN, the +# wrapper also forwards MH_FACE_AUTH_TOKEN from the current environment, from a +# parent process, or from MH_FACE_ENV_FILE. The default env file is: +# ~/.config/minimum-headroom.env +# Keep the real token out of this checked-in config. diff --git a/mcp-server/dist/index.js b/mcp-server/dist/index.js index 6a096ea..2cdf5ee 100644 --- a/mcp-server/dist/index.js +++ b/mcp-server/dist/index.js @@ -3,7 +3,7 @@ import { randomUUID } from 'node:crypto'; import { createFramedMessageParser, writeMessage } from './mcp_stdio.js'; const SERVER_NAME = 'minimum-headroom'; -const SERVER_VERSION = '1.15.0'; +const SERVER_VERSION = '1.15.1'; const PROTOCOL_VERSION = '2024-11-05'; const FACE_WS_URL = process.env.FACE_WS_URL ?? 'ws://127.0.0.1:8765/ws'; const FACE_AUTH_TOKEN = (() => { diff --git a/package.json b/package.json index 6db876b..579b8fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "minimum-headroom", - "version": "1.15.0", + "version": "1.15.1", "private": true, "type": "module", "scripts": { diff --git a/scripts/run-bound-mcp-server.sh b/scripts/run-bound-mcp-server.sh index 0fb2442..a993887 100755 --- a/scripts/run-bound-mcp-server.sh +++ b/scripts/run-bound-mcp-server.sh @@ -6,6 +6,7 @@ cd "$ROOT_DIR" : "${FACE_WS_URL:=ws://127.0.0.1:8765/ws}" : "${MCP_TOOL_NAME_STYLE:=dot}" +: "${MH_FACE_ENV_FILE:=$HOME/.config/minimum-headroom.env}" read_proc_env_var() { local pid="$1" @@ -47,6 +48,53 @@ inherit_from_parent_chain() { return 1 } +read_env_file_var() { + local file="$1" + local key="$2" + if [[ -z "$file" || ! -r "$file" ]]; then + return 1 + fi + awk -v key="$key" ' + function trim(value) { + sub(/^[[:space:]]+/, "", value) + sub(/[[:space:]]+$/, "", value) + return value + } + function unquote(value) { + value = trim(value) + if (value ~ /^"([^"\\]|\\.)*"$/) { + value = substr(value, 2, length(value) - 2) + gsub(/\\"/, "\"", value) + gsub(/\\\\/, "\\", value) + } else if (value ~ /^'\''[^'\'']*'\''$/) { + value = substr(value, 2, length(value) - 2) + } + return value + } + { + line = $0 + sub(/\r$/, "", line) + line = trim(line) + if (line == "" || line ~ /^#/) { + next + } + sub(/^export[[:space:]]+/, "", line) + equals = index(line, "=") + if (equals <= 1) { + next + } + name = trim(substr(line, 1, equals - 1)) + if (name != key) { + next + } + print unquote(substr(line, equals + 1)) + found = 1 + exit + } + END { exit found ? 0 : 1 } + ' "$file" +} + if [[ -z "${MH_FACE_AGENT_ID:-}" ]]; then if value="$(inherit_from_parent_chain MH_FACE_AGENT_ID 2>/dev/null)" && [[ -n "$value" ]]; then export MH_FACE_AGENT_ID="$value" @@ -61,6 +109,14 @@ if [[ -z "${MH_FACE_AGENT_LABEL:-}" ]]; then fi fi +if [[ -z "${MH_FACE_AUTH_TOKEN:-}" ]]; then + if value="$(inherit_from_parent_chain MH_FACE_AUTH_TOKEN 2>/dev/null)" && [[ -n "$value" ]]; then + export MH_FACE_AUTH_TOKEN="$value" + elif value="$(read_env_file_var "$MH_FACE_ENV_FILE" MH_FACE_AUTH_TOKEN 2>/dev/null)" && [[ -n "$value" ]]; then + export MH_FACE_AUTH_TOKEN="$value" + fi +fi + NODE_BIN="${MH_NODE_BIN:-}" if [[ -z "$NODE_BIN" ]]; then NODE_BIN="$(command -v node || true)" @@ -83,6 +139,9 @@ env_args=( if [[ -n "${FACE_HTTP_BASE_URL:-}" ]]; then env_args+=("FACE_HTTP_BASE_URL=$FACE_HTTP_BASE_URL") fi +if [[ -n "${MH_FACE_AUTH_TOKEN:-}" ]]; then + env_args+=("MH_FACE_AUTH_TOKEN=$MH_FACE_AUTH_TOKEN") +fi if [[ -n "${MH_FACE_AGENT_ID:-}" ]]; then env_args+=("MH_FACE_AGENT_ID=$MH_FACE_AGENT_ID") fi diff --git a/tts-worker/pyproject.toml b/tts-worker/pyproject.toml index 2e64733..37ce03a 100644 --- a/tts-worker/pyproject.toml +++ b/tts-worker/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "minimum-headroom-tts-worker" -version = "1.13.12" +version = "1.15.1" description = "Minimum Headroom phase3 tts worker" readme = "README.md" requires-python = ">=3.12" diff --git a/tts-worker/uv.lock b/tts-worker/uv.lock index 893f297..f240cd0 100644 --- a/tts-worker/uv.lock +++ b/tts-worker/uv.lock @@ -331,7 +331,7 @@ wheels = [ [[package]] name = "minimum-headroom-tts-worker" -version = "1.13.12" +version = "1.15.1" source = { editable = "." } dependencies = [ { name = "fugashi" },