somratpro commited on
Commit
67a5cb1
Β·
1 Parent(s): c6ffa66

feat: update Claude Code authentication wrapper and increase sync interval while removing Gemini debug logs

Browse files
Files changed (4) hide show
  1. .env.example +13 -2
  2. Dockerfile +25 -17
  3. health-server.js +2 -16
  4. start.sh +19 -3
.env.example CHANGED
@@ -45,8 +45,19 @@ PAPERCLIP_DEPLOYMENT_MODE=authenticated
45
  # Paperclip Agent Providers (varies by setup)
46
  # ============================================================================
47
 
48
- # If using Claude as an agent provider
49
- ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
 
 
 
 
 
 
 
 
 
 
 
50
 
51
  # For other LLM providers (OpenAI, etc.)
52
  # LLM_API_KEY=your-api-key
 
45
  # Paperclip Agent Providers (varies by setup)
46
  # ============================================================================
47
 
48
+ # Claude Code β€” choose one mode or neither:
49
+ #
50
+ # Subscription mode (Claude Pro/Max β€” no per-token cost):
51
+ # 1. Run `claude login` locally to authenticate once
52
+ # 2. Copy the token from ~/.claude/.credentials.json
53
+ # 3. Paste it here (takes priority over API key if both are set)
54
+ # ANTHROPIC_AUTH_TOKEN=your-oauth-token-from-credentials-json
55
+ #
56
+ # API key mode (pay-per-use):
57
+ # ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
58
+ #
59
+ # Neither set β†’ Claude Code uses stored OAuth credentials from ~/.claude/
60
+ # (requires first-time login inside the container)
61
 
62
  # For other LLM providers (OpenAI, etc.)
63
  # LLM_API_KEY=your-api-key
Dockerfile CHANGED
@@ -57,17 +57,30 @@ RUN npm init -y && npm install express@4 cors morgan
57
  # Install agent CLIs globally
58
  RUN npm install -g @google/gemini-cli @anthropic-ai/claude-code @openai/codex
59
 
60
- # Wrap agent CLIs so they:
61
- # 1. Drop cloudflare-proxy.js NODE_OPTIONS (would conflict with their HTTP)
62
- # 2. Pre-set --max-old-space-size=4096 so gemini doesn't trigger heap-size
63
- # self-relaunch (the spawn fails in HF Spaces containers)
64
- RUN for cmd in claude codex; do \
65
- if [ -e /usr/local/bin/$cmd ]; then \
66
- mv /usr/local/bin/$cmd /usr/local/bin/${cmd}-real && \
67
- printf '#!/bin/sh\nunset NODE_OPTIONS\nexport NODE_OPTIONS="--max-old-space-size=4096 --no-deprecation --no-warnings"\nexec /usr/local/bin/%s-real "$@"\n' "$cmd" > /usr/local/bin/$cmd && \
68
- chmod +x /usr/local/bin/$cmd; \
69
- fi; \
70
- done
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
  # Gemini wrapper β€” fix for "Failed to relaunch the CLI process":
73
  #
@@ -86,10 +99,6 @@ RUN for cmd in claude codex; do \
86
  RUN mv /usr/local/bin/gemini /usr/local/bin/gemini-real && \
87
  { \
88
  echo '#!/bin/sh'; \
89
- echo '# Log invocation so we can see what env Paperclip actually passes'; \
90
- echo 'echo "=== gemini wrapper $(date) args: $@ ===" >> /tmp/gemini-wrapper.log'; \
91
- echo 'env | sort >> /tmp/gemini-wrapper.log'; \
92
- echo ''; \
93
  echo 'unset NODE_OPTIONS'; \
94
  echo 'export NODE_OPTIONS="--max-old-space-size=4096 --no-deprecation --no-warnings"'; \
95
  echo 'export GEMINI_CLI_NO_RELAUNCH=1'; \
@@ -100,8 +109,7 @@ RUN mv /usr/local/bin/gemini /usr/local/bin/gemini-real && \
100
  echo 'export SANDBOX=1'; \
101
  echo 'exec /usr/local/bin/gemini-real "$@"'; \
102
  } > /usr/local/bin/gemini && \
103
- chmod +x /usr/local/bin/gemini && \
104
- echo "=== gemini wrapper ===" && cat /usr/local/bin/gemini
105
 
106
  # Install Python dependencies for sync
107
  RUN pip install --no-cache-dir --break-system-packages huggingface_hub PyYAML
 
57
  # Install agent CLIs globally
58
  RUN npm install -g @google/gemini-cli @anthropic-ai/claude-code @openai/codex
59
 
60
+ # Claude Code wrapper β€” auth mode selection:
61
+ # ANTHROPIC_AUTH_TOKEN set β†’ subscription mode (OAuth token, takes priority)
62
+ # ANTHROPIC_API_KEY set β†’ API key mode
63
+ # Neither set β†’ uses stored OAuth credentials in ~/.claude/
64
+ # If both are set, subscription token wins: unset API key to avoid conflict.
65
+ # Also drops cloudflare NODE_OPTIONS and caps heap size.
66
+ RUN if [ -e /usr/local/bin/claude ]; then \
67
+ mv /usr/local/bin/claude /usr/local/bin/claude-real && \
68
+ { \
69
+ echo '#!/bin/sh'; \
70
+ echo 'unset NODE_OPTIONS'; \
71
+ echo '[ -n "$ANTHROPIC_AUTH_TOKEN" ] && unset ANTHROPIC_API_KEY'; \
72
+ echo 'export NODE_OPTIONS="--max-old-space-size=4096 --no-deprecation --no-warnings"'; \
73
+ echo 'exec /usr/local/bin/claude-real "$@"'; \
74
+ } > /usr/local/bin/claude && \
75
+ chmod +x /usr/local/bin/claude; \
76
+ fi
77
+
78
+ # Codex wrapper β€” drops cloudflare NODE_OPTIONS, caps heap size
79
+ RUN if [ -e /usr/local/bin/codex ]; then \
80
+ mv /usr/local/bin/codex /usr/local/bin/codex-real && \
81
+ printf '#!/bin/sh\nunset NODE_OPTIONS\nexport NODE_OPTIONS="--max-old-space-size=4096 --no-deprecation --no-warnings"\nexec /usr/local/bin/codex-real "$@"\n' > /usr/local/bin/codex && \
82
+ chmod +x /usr/local/bin/codex; \
83
+ fi
84
 
85
  # Gemini wrapper β€” fix for "Failed to relaunch the CLI process":
86
  #
 
99
  RUN mv /usr/local/bin/gemini /usr/local/bin/gemini-real && \
100
  { \
101
  echo '#!/bin/sh'; \
 
 
 
 
102
  echo 'unset NODE_OPTIONS'; \
103
  echo 'export NODE_OPTIONS="--max-old-space-size=4096 --no-deprecation --no-warnings"'; \
104
  echo 'export GEMINI_CLI_NO_RELAUNCH=1'; \
 
109
  echo 'export SANDBOX=1'; \
110
  echo 'exec /usr/local/bin/gemini-real "$@"'; \
111
  } > /usr/local/bin/gemini && \
112
+ chmod +x /usr/local/bin/gemini
 
113
 
114
  # Install Python dependencies for sync
115
  RUN pip install --no-cache-dir --break-system-packages huggingface_hub PyYAML
health-server.js CHANGED
@@ -10,7 +10,7 @@ const PAPERCLIP_PORT = 3100;
10
  const startTime = Date.now();
11
 
12
  const HF_BACKUP_ENABLED = !!process.env.HF_TOKEN;
13
- const SYNC_INTERVAL = process.env.SYNC_INTERVAL || "180";
14
 
15
  const UPTIMEROBOT_SETUP_ENABLED =
16
  String(process.env.UPTIMEROBOT_SETUP_ENABLED || "true").toLowerCase() === "true";
@@ -36,8 +36,7 @@ function isLocalRoute(pathname) {
36
  return (
37
  pathname === "/health" ||
38
  pathname === "/status" ||
39
- pathname === "/uptimerobot/setup" ||
40
- pathname === "/debug/gemini-log"
41
  );
42
  }
43
 
@@ -804,19 +803,6 @@ const server = http.createServer((req, res) => {
804
  return;
805
  }
806
 
807
- // ── Gemini wrapper debug log ──────────────────────────────────────────────
808
- if (pathname === "/debug/gemini-log") {
809
- try {
810
- const log = fs.readFileSync("/tmp/gemini-wrapper.log", "utf8");
811
- res.writeHead(200, { "Content-Type": "text/plain" });
812
- res.end(log);
813
- } catch {
814
- res.writeHead(200, { "Content-Type": "text/plain" });
815
- res.end("No log yet β€” click 'Test now' on the Gemini adapter first.\n");
816
- }
817
- return;
818
- }
819
-
820
  // ── UptimeRobot setup endpoint ─────────────────────────────────────────────
821
  if (pathname === "/uptimerobot/setup") {
822
  if (req.method !== "POST") {
 
10
  const startTime = Date.now();
11
 
12
  const HF_BACKUP_ENABLED = !!process.env.HF_TOKEN;
13
+ const SYNC_INTERVAL = process.env.SYNC_INTERVAL || "86400";
14
 
15
  const UPTIMEROBOT_SETUP_ENABLED =
16
  String(process.env.UPTIMEROBOT_SETUP_ENABLED || "true").toLowerCase() === "true";
 
36
  return (
37
  pathname === "/health" ||
38
  pathname === "/status" ||
39
+ pathname === "/uptimerobot/setup"
 
40
  );
41
  }
42
 
 
803
  return;
804
  }
805
 
 
 
 
 
 
 
 
 
 
 
 
 
 
806
  // ── UptimeRobot setup endpoint ─────────────────────────────────────────────
807
  if (pathname === "/uptimerobot/setup") {
808
  if (req.method !== "POST") {
start.sh CHANGED
@@ -35,8 +35,12 @@ export PAPERCLIP_ALLOWED_HOSTNAMES="${PAPERCLIP_ALLOWED_HOSTNAMES:-${_ALLOWED}}"
35
 
36
  # LLM API keys
37
  export GEMINI_API_KEY="${GEMINI_API_KEY:-}"
38
- export ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}"
39
  export OPENAI_API_KEY="${OPENAI_API_KEY:-}"
 
 
 
 
 
40
 
41
  mkdir -p "${PAPERCLIP_HOME}"
42
 
@@ -64,9 +68,9 @@ if [ -z "${PAPERCLIP_AGENT_JWT_SECRET:-}" ]; then
64
  fi
65
 
66
  # ── Validate LLM providers ───────────────────────────────────────────────────
67
- if [ -z "${GEMINI_API_KEY:-}" ] && [ -z "${ANTHROPIC_API_KEY:-}" ] && [ -z "${OPENAI_API_KEY:-}" ]; then
68
  echo "⚠️ WARNING: No LLM provider configured"
69
- echo " Set at least one of: GEMINI_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY"
70
  echo " Agents will fail to run without an LLM provider"
71
  echo ""
72
  fi
@@ -288,6 +292,18 @@ cleanup() {
288
  }
289
  trap cleanup SIGTERM SIGINT
290
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  # ── Ensure paperclip user owns runtime dirs ──────────────────────────────────
292
  chown -R paperclip:paperclip /app /paperclip 2>/dev/null || true
293
 
 
35
 
36
  # LLM API keys
37
  export GEMINI_API_KEY="${GEMINI_API_KEY:-}"
 
38
  export OPENAI_API_KEY="${OPENAI_API_KEY:-}"
39
+ # Anthropic/Claude Code β€” set one or neither:
40
+ # ANTHROPIC_AUTH_TOKEN : subscription mode (OAuth token from ~/.claude/.credentials.json)
41
+ # ANTHROPIC_API_KEY : API key mode (sk-ant-...)
42
+ export ANTHROPIC_AUTH_TOKEN="${ANTHROPIC_AUTH_TOKEN:-}"
43
+ export ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}"
44
 
45
  mkdir -p "${PAPERCLIP_HOME}"
46
 
 
68
  fi
69
 
70
  # ── Validate LLM providers ───────────────────────────────────────────────────
71
+ if [ -z "${GEMINI_API_KEY:-}" ] && [ -z "${ANTHROPIC_API_KEY:-}" ] && [ -z "${ANTHROPIC_AUTH_TOKEN:-}" ] && [ -z "${OPENAI_API_KEY:-}" ]; then
72
  echo "⚠️ WARNING: No LLM provider configured"
73
+ echo " Set at least one of: GEMINI_API_KEY, ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, OPENAI_API_KEY"
74
  echo " Agents will fail to run without an LLM provider"
75
  echo ""
76
  fi
 
292
  }
293
  trap cleanup SIGTERM SIGINT
294
 
295
+ # ── Codex API key config ─────────────────────────────────────────────────────
296
+ # Codex default auth mode is "chatgpt" (OAuth). Setting forced_login_method="api"
297
+ # makes it read OPENAI_API_KEY from env instead of prompting for browser login.
298
+ if [ -n "${OPENAI_API_KEY:-}" ]; then
299
+ mkdir -p /home/paperclip/.codex
300
+ cat > /home/paperclip/.codex/config.toml <<'TOMLEOF'
301
+ forced_login_method = "api"
302
+ TOMLEOF
303
+ chmod 600 /home/paperclip/.codex/config.toml
304
+ chown -R paperclip:paperclip /home/paperclip/.codex
305
+ fi
306
+
307
  # ── Ensure paperclip user owns runtime dirs ──────────────────────────────────
308
  chown -R paperclip:paperclip /app /paperclip 2>/dev/null || true
309