parent
34d4136f2e
commit
94a66e1957
4 changed files with 171 additions and 34 deletions
118
bin/disinto
118
bin/disinto
|
|
@ -31,6 +31,9 @@ FACTORY_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|||
export USER="${USER:-$(id -un)}"
|
||||
export HOME="${HOME:-$(eval echo "~${USER}")}"
|
||||
|
||||
# Chat Claude identity directory — separate from factory agents (#707)
|
||||
export CHAT_CLAUDE_DIR="${CHAT_CLAUDE_DIR:-${HOME}/.claude-chat}"
|
||||
|
||||
source "${FACTORY_ROOT}/lib/env.sh"
|
||||
source "${FACTORY_ROOT}/lib/ops-setup.sh" # setup_ops_repo, migrate_ops_repo
|
||||
source "${FACTORY_ROOT}/lib/hire-agent.sh"
|
||||
|
|
@ -640,6 +643,98 @@ prompt_admin_password() {
|
|||
exit 1
|
||||
}
|
||||
|
||||
# ── Chat identity prompt helper ───────────────────────────────────────────────
|
||||
# Prompts for separate Claude identity for disinto-chat (#707).
|
||||
# On yes, creates ~/.claude-chat/ and runs claude login in subshell.
|
||||
# Returns 0 on success, 1 on failure/skip.
|
||||
# Usage: prompt_chat_identity [<env_file>]
|
||||
prompt_chat_identity() {
|
||||
local env_file="${1:-${FACTORY_ROOT}/.env}"
|
||||
local chat_claude_dir="${CHAT_CLAUDE_DIR:-${HOME}/.claude-chat}"
|
||||
local config_dir="${chat_claude_dir}/config"
|
||||
|
||||
# Skip if ANTHROPIC_API_KEY is set (API key mode — no OAuth needed)
|
||||
if grep -q '^ANTHROPIC_API_KEY=' "$env_file" 2>/dev/null; then
|
||||
local api_key
|
||||
api_key=$(grep '^ANTHROPIC_API_KEY=' "$env_file" | cut -d= -f2-)
|
||||
if [ -n "$api_key" ]; then
|
||||
echo "Chat: ANTHROPIC_API_KEY set — skipping OAuth identity setup"
|
||||
echo "Chat: Chat will use API key authentication (no ~/.claude-chat mount)"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if ~/.claude-chat already exists and has credentials
|
||||
if [ -d "$chat_claude_dir" ]; then
|
||||
if [ -d "${config_dir}/credentials" ] && [ -n "$(ls -A "${config_dir}/credentials" 2>/dev/null)" ]; then
|
||||
echo "Chat: ~/.claude-chat already configured (resuming from existing identity)"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Non-interactive mode without explicit yes
|
||||
if [ "$auto_yes" = true ]; then
|
||||
echo "Chat: --yes provided — creating ~/.claude-chat identity"
|
||||
# Create directory structure
|
||||
install -d -m 0700 -o "$USER" "$config_dir"
|
||||
# Skip claude login in non-interactive mode — user must run manually
|
||||
echo "Chat: Identity directory created at ${chat_claude_dir}"
|
||||
echo "Chat: Run 'CLAUDE_CONFIG_DIR=${config_dir} claude login' to authenticate"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Interactive mode: prompt for separate identity
|
||||
if [ -t 0 ]; then
|
||||
echo ""
|
||||
echo "── Separate Claude identity for disinto-chat ──────────────────────"
|
||||
echo "Create a separate Claude identity for disinto-chat to avoid OAuth"
|
||||
echo "refresh races with factory agents sharing ~/.claude?"
|
||||
echo ""
|
||||
printf "Use separate identity for chat? [Y/n] "
|
||||
|
||||
local response
|
||||
IFS= read -r response
|
||||
response="${response:-Y}"
|
||||
|
||||
case "$response" in
|
||||
[Nn][Oo]|[Nn])
|
||||
echo "Chat: Skipping separate identity — chat will use shared ~/.claude"
|
||||
echo "Chat: Note: OAuth refresh races may occur with concurrent agents"
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
# User said yes — create identity and run login
|
||||
echo ""
|
||||
echo "Chat: Creating identity directory at ${chat_claude_dir}"
|
||||
install -d -m 0700 -o "$USER" "$config_dir"
|
||||
|
||||
# Run claude login in subshell with CLAUDE_CONFIG_DIR set
|
||||
echo "Chat: Launching Claude login for chat identity..."
|
||||
echo "Chat: (This will authenticate to a separate Anthropic account)"
|
||||
echo ""
|
||||
CLAUDE_CONFIG_DIR="$config_dir" claude login
|
||||
local login_rc=$?
|
||||
|
||||
if [ $login_rc -eq 0 ]; then
|
||||
echo ""
|
||||
echo "Chat: Claude identity configured at ${chat_claude_dir}"
|
||||
echo "Chat: Chat container will use: ${chat_claude_dir}:/home/chat/.claude-chat"
|
||||
return 0
|
||||
else
|
||||
echo "Error: Claude login failed (exit code ${login_rc})" >&2
|
||||
echo "Chat: Identity not configured"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Non-interactive, no TTY
|
||||
echo "Warning: cannot prompt for chat identity (no TTY)" >&2
|
||||
echo "Chat: Skipping identity setup — run manually if needed"
|
||||
return 1
|
||||
}
|
||||
|
||||
# ── init command ─────────────────────────────────────────────────────────────
|
||||
|
||||
disinto_init() {
|
||||
|
|
@ -768,6 +863,9 @@ p.write_text(text)
|
|||
# This ensures the password is set before Forgejo user creation
|
||||
prompt_admin_password "${FACTORY_ROOT}/.env"
|
||||
|
||||
# Prompt for separate chat identity (#707)
|
||||
prompt_chat_identity "${FACTORY_ROOT}/.env"
|
||||
|
||||
# Set up local Forgejo instance (provision if needed, create users/tokens/repo)
|
||||
if [ "$rotate_tokens" = true ]; then
|
||||
echo "Note: Forcing token rotation (tokens/passwords will be regenerated)"
|
||||
|
|
@ -991,9 +1089,10 @@ p.write_text(text)
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Write CLAUDE_SHARED_DIR and CLAUDE_CONFIG_DIR to .env (idempotent)
|
||||
# Write CLAUDE_SHARED_DIR, CLAUDE_CONFIG_DIR, and CHAT_CLAUDE_DIR to .env (idempotent)
|
||||
_env_set_idempotent "CLAUDE_SHARED_DIR" "$CLAUDE_SHARED_DIR" "$env_file"
|
||||
_env_set_idempotent "CLAUDE_CONFIG_DIR" "$CLAUDE_CONFIG_DIR" "$env_file"
|
||||
_env_set_idempotent "CHAT_CLAUDE_DIR" "$CHAT_CLAUDE_DIR" "$env_file"
|
||||
|
||||
# Activate default agents (zero-cost when idle — they only invoke Claude
|
||||
# when there is actual work, so an empty project burns no LLM tokens)
|
||||
|
|
@ -1021,15 +1120,24 @@ p.write_text(text)
|
|||
fi
|
||||
echo ""
|
||||
echo "── Claude authentication ──────────────────────────────"
|
||||
echo " OAuth (shared across containers):"
|
||||
echo " Factory agents (shared OAuth):"
|
||||
echo " Run 'claude auth login' on the host once."
|
||||
echo " Credentials in ${CLAUDE_CONFIG_DIR} are shared across containers."
|
||||
echo ""
|
||||
echo " disinto-chat (separate identity #707):"
|
||||
echo " Separate identity created at ${CHAT_CLAUDE_DIR:-${HOME}/.claude-chat}"
|
||||
echo " Container mounts: ${CHAT_CLAUDE_DIR:-${HOME}/.claude-chat}:/home/chat/.claude-chat"
|
||||
echo " CLAUDE_CONFIG_DIR=/home/chat/.claude-chat/config"
|
||||
echo ""
|
||||
echo " API key (alternative — metered billing, no rotation issues):"
|
||||
echo " Set ANTHROPIC_API_KEY in .env to skip OAuth entirely."
|
||||
echo " Chat container will not mount identity directory."
|
||||
echo ""
|
||||
echo "── Claude config directory ────────────────────────────"
|
||||
echo " CLAUDE_CONFIG_DIR=${CLAUDE_CONFIG_DIR}"
|
||||
echo " Add this to your shell rc (~/.bashrc or ~/.zshrc):"
|
||||
echo "── Claude config directories ───────────────────────────"
|
||||
echo " Factory agents: CLAUDE_CONFIG_DIR=${CLAUDE_CONFIG_DIR}"
|
||||
echo " Chat service: CLAUDE_CONFIG_DIR=/home/chat/.claude-chat/config"
|
||||
echo ""
|
||||
echo " Add factory agents CLAUDE_CONFIG_DIR to your shell rc:"
|
||||
echo " export CLAUDE_CONFIG_DIR=${CLAUDE_CONFIG_DIR}"
|
||||
echo " This ensures interactive Claude Code sessions on this host"
|
||||
echo " share the same OAuth lock and token store as the factory."
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue