From 756ac41aba8ed8742ed86d286f42474e9c374ef3 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Thu, 2 Apr 2026 00:30:28 +0000 Subject: [PATCH] feat(kugetsu): add env pass-through for agent delegation Add environment variable management for delegating to agents. Features: - Add ENV_DIR constant (\~/.kugetsu/env) - Add mask_sensitive_vars() to hide sensitive values in logs - Add load_agent_env() to load agent-specific env files - Add cmd_env command for managing env files: - list: List all env files - show [agent]: Show env file contents (masked) - set [agent]: Set key=value - get [agent]: Get value for key - rm [agent]: Remove key - Update cmd_delegate to load pm-agent.env or default.env before running Example usage: kugetsu env set GITEA_TOKEN xxx pm-agent kugetsu delegate "post comment on #69" Fixes #76 --- skills/kugetsu/scripts/kugetsu | 140 ++++++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 1 deletion(-) diff --git a/skills/kugetsu/scripts/kugetsu b/skills/kugetsu/scripts/kugetsu index 4026b07..5004491 100755 --- a/skills/kugetsu/scripts/kugetsu +++ b/skills/kugetsu/scripts/kugetsu @@ -8,6 +8,7 @@ REPOS_CONFIG="$KUGETSU_DIR/repos.json" INDEX_FILE="$KUGETSU_DIR/index.json" NOTIFICATIONS_FILE="$KUGETSU_DIR/notifications.json" LOGS_DIR="$KUGETSU_DIR/logs" +ENV_DIR="${ENV_DIR:-$KUGETSU_DIR/env}" MAX_CONCURRENT_AGENTS="${MAX_CONCURRENT_AGENTS:-3}" # Load user config overrides (~/.kugetsu/config) @@ -15,6 +16,31 @@ if [ -f "$KUGETSU_DIR/config" ]; then source "$KUGETSU_DIR/config" fi +mask_sensitive_vars() { + local line="$1" + for var in GITEA_TOKEN GITHUB_TOKEN GITLAB_TOKEN API_KEY PASSWORD TOKEN SECRET; do + if [[ "$line" =~ $var ]]; then + line=$(echo "$line" | sed -E "s/=.*/=***MASKED***/") + fi + done + echo "$line" +} + +load_agent_env() { + local agent_type="${1:-base}" + local env_file="$ENV_DIR/${agent_type}.env" + + if [ -f "$env_file" ]; then + set -a + source "$env_file" + set +a + elif [ -f "$ENV_DIR/default.env" ]; then + set -a + source "$ENV_DIR/default.env" + set +a + fi +} + count_active_dev_sessions() { local count=0 if [ -d "$SESSIONS_DIR" ]; then @@ -536,7 +562,16 @@ cmd_delegate() { mkdir -p "$LOGS_DIR" local log_file="$LOGS_DIR/delegate-$(date +%s).log" - nohup sh -c "opencode run '$message' --continue --session '$pm_session' >> '$log_file' 2>&1" > /dev/null 2>&1 & + + mkdir -p "$ENV_DIR" + local env_sh="" + if [ -f "$ENV_DIR/pm-agent.env" ]; then + env_sh="source '$ENV_DIR/pm-agent.env'; " + elif [ -f "$ENV_DIR/default.env" ]; then + env_sh="source '$ENV_DIR/default.env'; " + fi + + nohup sh -c "${env_sh}opencode run '$message' --continue --session '$pm_session' >> '$log_file' 2>&1" > /dev/null 2>&1 & disown echo "Delegated to PM agent (logged to $(basename "$log_file"))" } @@ -557,6 +592,106 @@ cmd_logs() { done } +cmd_env() { + local action="${1:-}" + local agent_type="${2:-}" + + mkdir -p "$ENV_DIR" + + case "$action" in + ""|"list") + echo "Environment files in $ENV_DIR:" + if [ -d "$ENV_DIR" ]; then + for f in "$ENV_DIR"/*.env; do + if [ -f "$f" ]; then + echo " $(basename "$f")" + fi + done + fi + if [ ! -d "$ENV_DIR" ] || [ -z "$(ls -A "$ENV_DIR"/*.env 2>/dev/null)" ]; then + echo " (no env files found)" + fi + ;; + "show") + local file="$ENV_DIR/${agent_type:-default}.env" + if [ -f "$file" ]; then + echo "=== $file ===" + while IFS= read -r line; do + echo "$(mask_sensitive_vars "$line")" + done < "$file" + else + echo "No env file for: ${agent_type:-default}" + fi + ;; + "set") + local key="${2:-}" + local value="${3:-}" + local target="${4:-default}" + if [ -z "$key" ] || [ -z "$value" ]; then + echo "Usage: kugetsu env set [agent]" >&2 + echo " agent: default, pm-agent, or issue ref" >&2 + exit 1 + fi + local file="$ENV_DIR/${target}.env" + if [ -f "$file" ]; then + if grep -q "^${key}=" "$file"; then + sed -i "s|^${key}=.*|${key}=\"${value}\"|" "$file" + else + echo "${key}=\"${value}\"" >> "$file" + fi + else + echo "${key}=\"${value}\"" > "$file" + fi + echo "Set ${key}=${value} in ${target}.env" + ;; + "get") + local key="${2:-}" + local target="${3:-default}" + local file="$ENV_DIR/${target}.env" + if [ -z "$key" ]; then + echo "Usage: kugetsu env get [agent]" >&2 + exit 1 + fi + if [ -f "$file" ]; then + local val=$(grep "^${key}=" "$file" | cut -d'=' -f2 | tr -d '"') + if [ -n "$val" ]; then + echo "$val" + else + echo "Key '$key' not found in ${target}.env" >&2 + exit 1 + fi + else + echo "No env file for: ${target}" >&2 + exit 1 + fi + ;; + "rm"|"remove"|"delete") + local key="${2:-}" + local target="${3:-default}" + if [ -z "$key" ]; then + echo "Usage: kugetsu env rm [agent]" >&2 + exit 1 + fi + local file="$ENV_DIR/${target}.env" + if [ -f "$file" ]; then + sed -i "/^${key}=/d" "$file" + echo "Removed $key from ${target}.env" + fi + ;; + *) + echo "Usage: kugetsu env [args]" >&2 + echo "" >&2 + echo "Commands:" >&2 + echo " list List all env files" >&2 + echo " show [agent] Show env file contents (masked)" >&2 + echo " set [a] Set key=value in agent env (default/pm-agent)" >&2 + echo " get [a] Get value for key" >&2 + echo " rm [a] Remove key from agent env" >&2 + exit 1 + ;; + esac +} + cmd_doctor() { local fix=false @@ -1311,6 +1446,9 @@ main() { server) cmd_server "$@" ;; + env) + cmd_env "$@" + ;; doctor) cmd_doctor "$@" ;;