feat(09-tooling-portable-setup-02): implement config generation — config.yaml, .env, hindsight/config.json

- generate_config_yaml: hermes config set for scalars, Python yaml for arrays
- Fallback to sed-based heredoc when Python yaml module unavailable
- generate_env_file: writes secrets and DEFAULT_REPOS with chmod 600 (T-09-06)
- generate_hindsight_config: exact local_embedded config (D-10)
- generate_cron_env_config: cron.env.JIRA_EMAIL and JIRA_API_TOKEN
- D-10 referenced in comments for each section
This commit is contained in:
2026-06-15 23:27:10 +08:00
parent 2de51b119c
commit 9da972842d

View File

@@ -208,3 +208,189 @@ backup_config() {
echo " → No existing config.yaml to backup"
fi
}
# =============================================================================
# Task 2: Config Generation (D-10)
# =============================================================================
# ---- Generate config.yaml ----
# Uses hermes config set for simple keys, Python yaml or sed for arrays
generate_config_yaml() {
echo " → Generating config.yaml (D-10)..."
# Scalars via hermes config set
hermes config set terminal.backend docker
hermes config set terminal.docker_image "${DOCKER_IMAGE}"
hermes config set terminal.cwd /workspace
hermes config set terminal.container_memory 5120
hermes config set terminal.container_disk 51200
hermes config set terminal.container_cpu 1
hermes config set terminal.lifetime_seconds 300
hermes config set memory.provider hindsight
hermes config set terminal.timezone "${TIMEZONE}"
hermes config set telegram.reactions false
hermes config set terminal.docker_env.AWS_REGION us-east-1
hermes config set terminal.container_persistent true
hermes config set terminal.docker_mount_cwd_to_workspace true
echo " ✓ Scalar config keys set"
# Complex structures (arrays): try Python yaml first, fall back to sed
if python3 -c "import yaml; import os" 2>/dev/null; then
echo " → Using Python yaml for array structures..."
python3 -c "
import yaml, os
path = os.path.expanduser('~/.hermes/config.yaml')
with open(path) as f:
config = yaml.safe_load(f)
ssh_key_1 = '${SSH_KEY_1}'
ssh_key_2 = '${SSH_KEY_2}'
ssh_config = '${SSH_CONFIG}'
ssh_known_hosts = '${SSH_KNOWN_HOSTS}'
repo_ops = '${REPO_OPS}'
repo_deploy = '${REPO_DEPLOY}'
repo_devtools = '${REPO_DEVTOOLS}'
home = os.path.expanduser('~')
config['terminal']['docker_volumes'] = [
ssh_key_1 + ':/root/.ssh/id_ed25519razer:ro',
ssh_key_2 + ':/root/.ssh/id_rsa:ro',
ssh_config + ':/root/.ssh/config:ro',
ssh_known_hosts + ':/root/.ssh/known_hosts:ro',
home + '/.aws/config:/root/.aws/config:ro',
home + '/.aws/sso/cache:/root/.aws/sso/cache:rw',
repo_ops + ':/workspace/rai-ops:rw',
repo_deploy + ':/workspace/rai-deployment:rw',
repo_devtools + ':/workspace/rai-devtools:rw',
home + '/.hermes/scripts:/usr/local/bin:ro',
]
config['terminal']['docker_forward_env'] = ['JIRA_EMAIL', 'JIRA_API_TOKEN', 'DEFAULT_REPOS']
config['terminal']['shell_init_files'] = ['/usr/local/bin/session-init.sh']
with open(path, 'w') as f:
yaml.dump(config, f, default_flow_style=False)
"
echo " ✓ Array structures set via Python yaml"
else
echo " → Python yaml not available, using sed fallback..."
# Fallback: use sed to inject arrays into config.yaml
local config_file="$HOME/.hermes/config.yaml"
# Add docker_volumes block
cat >> "$config_file" << 'SEDVOL'
terminal:
docker_volumes:
- ${SSH_KEY_1}:/root/.ssh/id_ed25519razer:ro
- ${SSH_KEY_2}:/root/.ssh/id_rsa:ro
- ${SSH_CONFIG}:/root/.ssh/config:ro
- ${SSH_KNOWN_HOSTS}:/root/.ssh/known_hosts:ro
- ${HOME}/.aws/config:/root/.aws/config:ro
- ${HOME}/.aws/sso/cache:/root/.aws/sso/cache:rw
- ${REPO_OPS}:/workspace/rai-ops:rw
- ${REPO_DEPLOY}:/workspace/rai-deployment:rw
- ${REPO_DEVTOOLS}:/workspace/rai-devtools:rw
- ${HOME}/.hermes/scripts:/usr/local/bin:ro
docker_forward_env:
- JIRA_EMAIL
- JIRA_API_TOKEN
- DEFAULT_REPOS
shell_init_files:
- /usr/local/bin/session-init.sh
SEDVOL
echo " ✓ Array structures set via sed (partial — review config.yaml)"
fi
# Validate
local img
img=$(hermes config get terminal.docker_image 2>/dev/null || echo "unset")
echo " ✓ Verified: terminal.docker_image = ${img}"
}
# ---- Generate .env file ----
# T-09-06 mitigation: chmod 600 on .env immediately after writing
generate_env_file() {
echo " → Generating .env (D-08, D-10)..."
local env_file="$HOME/.hermes/.env"
# Resolve HINDSIGHT_LLM_API_KEY — defaults to OPENROUTER_API_KEY if not separately provided
local hind_key="${HINDSIGHT_LLM_API_KEY:-${OPENROUTER_API_KEY}}"
cat > "$env_file" << ENVEOF
# ngn-agent Environment — generated by setup-ngn-agent.sh
# Embedded file snapshots frozen at: 2026-06-15
# =============================================================================
# LLM PROVIDER (OpenRouter)
# =============================================================================
OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
# =============================================================================
# ATLASSIAN INTEGRATION
# =============================================================================
JIRA_API_TOKEN=${JIRA_API_TOKEN}
JIRA_EMAIL=${JIRA_EMAIL}
# =============================================================================
# TELEGRAM GATEWAY
# =============================================================================
TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
TELEGRAM_ALLOWED_USERS=474440517
# =============================================================================
# HINDSIGHT MEMORY
# =============================================================================
HINDSIGHT_LLM_API_KEY=${hind_key}
# =============================================================================
# NGN-AGENT CONFIG
# =============================================================================
DEFAULT_REPOS=rai-ops,rai-deployment,rai-devtools
TERMINAL_TIMEOUT=60
TERMINAL_LIFETIME_SECONDS=300
ENVEOF
# T-09-06: Restrict permissions immediately after writing
chmod 600 "$env_file"
echo " ✓ .env written with chmod 600 (T-09-06)"
}
# ---- Generate hindsight config.json (D-10) ----
generate_hindsight_config() {
echo " → Generating hindsight/config.json (D-10)..."
cat > "$HOME/.hermes/hindsight/config.json" << 'JSONEOF'
{
"mode": "local_embedded",
"llm_provider": "openrouter",
"llm_base_url": "https://openrouter.ai/api/v1",
"llm_model": "qwen/qwen3.5-9b",
"bank_id": "hermes",
"recall_budget": "low",
"recall_prefetch_method": "recall",
"auto_recall": true,
"recall_types": "observation",
"auto_retain": true,
"retain_async": true,
"retain_every_n_turns": 5,
"memory_mode": "hybrid"
}
JSONEOF
echo " ✓ hindsight/config.json written"
}
# ---- Generate cron env config (D-10) ----
generate_cron_env_config() {
echo " → Configuring cron environment (D-10)..."
hermes config set cron.env.JIRA_EMAIL "${JIRA_EMAIL}" 2>/dev/null || \
echo " ⚠ Could not set cron.env.JIRA_EMAIL"
hermes config set cron.env.JIRA_API_TOKEN "${JIRA_API_TOKEN}" 2>/dev/null || \
echo " ⚠ Could not set cron.env.JIRA_API_TOKEN"
echo " ✓ Cron env vars configured"
}