forked from microsoft/amplifier
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDockerfile
More file actions
369 lines (293 loc) Β· 11.4 KB
/
Dockerfile
File metadata and controls
369 lines (293 loc) Β· 11.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
FROM ubuntu:22.04
# Avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive
# Install system dependencies
RUN apt-get update && apt-get install -y \
curl \
git \
build-essential \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js (required for Claude Code)
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y nodejs
# Install Python 3.11
RUN apt-get update && apt-get install -y python3.11 python3.11-venv python3.11-dev && rm -rf /var/lib/apt/lists/*
# Install uv (Python package manager)
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
ENV PATH="/root/.local/bin:/root/.cargo/bin:$PATH"
ENV PNPM_HOME="/root/.local/share/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
# Install Claude Code, pyright, and pnpm
ENV SHELL=/bin/bash
RUN npm install -g @anthropic-ai/claude-code pyright pnpm && \
SHELL=/bin/bash pnpm setup && \
echo 'export PNPM_HOME="/root/.local/share/pnpm"' >> ~/.bashrc && \
echo 'export PATH="$PNPM_HOME:$PATH"' >> ~/.bashrc
# Pre-configure Claude Code to use environment variables
RUN mkdir -p /root/.config/claude-code
# Create working directory
WORKDIR /app
# Clone Amplifier repository
RUN git clone https://github.com/microsoft/amplifier.git /app/amplifier
# Set working directory to amplifier
WORKDIR /app/amplifier
# Initialize Python environment with uv and install dependencies
RUN uv venv --python python3.11 .venv && \
uv sync && \
. .venv/bin/activate && make install
# Create data directory for Amplifier and required subdirectories
RUN mkdir -p /app/amplifier-data && \
mkdir -p /app/amplifier/.data
# Clone Amplifier to /root/amplifier where Claude Code will start
RUN git clone https://github.com/microsoft/amplifier.git /root/amplifier
# Build Amplifier in /root/amplifier
WORKDIR /root/amplifier
RUN uv venv --python python3.11 .venv && \
uv sync && \
. .venv/bin/activate && make install
# Create required .data directory structure
RUN mkdir -p /root/amplifier/.data/knowledge && \
mkdir -p /root/amplifier/.data/indexes && \
mkdir -p /root/amplifier/.data/state && \
mkdir -p /root/amplifier/.data/memories && \
mkdir -p /root/amplifier/.data/cache
# Create Claude Code settings and tools
RUN mkdir -p /root/amplifier/.claude/tools && \
cat > /root/amplifier/.claude/settings.json << 'SETTINGS_EOF'
{
"statusLine": {
"type": "command",
"command": "bash /root/amplifier/.claude/tools/statusline-example.sh"
}
}
SETTINGS_EOF
# Create the statusline script referenced in settings
RUN cat > /root/amplifier/.claude/tools/statusline-example.sh << 'STATUSLINE_EOF'
#!/bin/bash
# Simple statusline script for Claude Code
# Shows current directory, git branch (if available), and timestamp
# Get current directory (relative to home)
current_dir=$(pwd | sed "s|$HOME|~|")
# Try to get git branch if in a git repository
git_info=""
if git rev-parse --git-dir > /dev/null 2>&1; then
branch=$(git branch --show-current 2>/dev/null || echo "detached")
git_info=" [git:$branch]"
fi
# Get current timestamp
timestamp=$(date '+%H:%M:%S')
# Output statusline
echo "π $current_dir$git_info | π $timestamp"
STATUSLINE_EOF
# Make the statusline script executable
RUN chmod +x /root/amplifier/.claude/tools/statusline-example.sh
# Create entrypoint script with comprehensive Claude Code configuration
RUN cat > /app/entrypoint.sh << 'EOF'
#!/bin/bash
set -e
# Logging function with timestamps
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
# Error handling function
error_exit() {
log "ERROR: $1"
exit 1
}
# Validate API key format
validate_api_key() {
local api_key="$1"
if [[ ! "$api_key" =~ ^sk-ant-[a-zA-Z0-9_-]+$ ]]; then
log "WARNING: API key format may be invalid (should start with 'sk-ant-')"
return 1
fi
return 0
}
# Create comprehensive Claude configuration file
create_claude_config() {
local api_key="$1"
local config_file="$HOME/.claude.json"
log "Creating Claude configuration at: $config_file"
# Extract last 20 characters for approved list
local key_suffix="${api_key: -20}"
# Create configuration directory
mkdir -p "$(dirname "$config_file")"
cat > "$config_file" << CONFIG_EOF
{
"apiKey": "$api_key",
"hasCompletedOnboarding": true,
"projects": {},
"customApiKeyResponses": {
"approved": ["$key_suffix"],
"rejected": []
},
"mcpServers": {}
}
CONFIG_EOF
# Verify JSON validity using python (more reliable than jq)
if ! python3 -m json.tool "$config_file" > /dev/null 2>&1; then
error_exit "Generated configuration file contains invalid JSON"
fi
log "Configuration file created successfully"
}
# Set CLI configuration flags
configure_claude_cli() {
log "Setting Claude CLI configuration flags..."
# Set configuration flags to skip interactive prompts
claude config set hasCompletedOnboarding true 2>/dev/null || log "WARNING: Failed to set hasCompletedOnboarding"
claude config set hasTrustDialogAccepted true 2>/dev/null || log "WARNING: Failed to set hasTrustDialogAccepted"
log "CLI configuration completed"
}
# Verify configuration
verify_configuration() {
local config_file="$HOME/.claude.json"
log "Verifying Claude configuration..."
# Check file existence
if [[ ! -f "$config_file" ]]; then
error_exit "Configuration file not found: $config_file"
fi
# Validate JSON structure using python
if ! python3 -m json.tool "$config_file" > /dev/null 2>&1; then
error_exit "Configuration file contains invalid JSON"
fi
# Check required fields using python
local api_key=$(python3 -c "import json; print(json.load(open('$config_file')).get('apiKey', ''))" 2>/dev/null || echo "")
local onboarding=$(python3 -c "import json; print(json.load(open('$config_file')).get('hasCompletedOnboarding', False))" 2>/dev/null || echo "false")
if [[ -z "$api_key" ]]; then
error_exit "API key not found in configuration"
fi
if [[ "$onboarding" != "True" ]]; then
error_exit "Onboarding not marked as complete"
fi
log "Configuration verification successful"
}
# Test Claude functionality
test_claude_functionality() {
log "Testing Claude Code functionality..."
# Test basic command
if claude --version >/dev/null 2>&1; then
local version=$(claude --version 2>/dev/null || echo "Unknown")
log "Claude Code version check successful: $version"
else
log "WARNING: Claude Code version check failed"
fi
# Test configuration access
if claude config show >/dev/null 2>&1; then
log "Claude Code configuration accessible"
else
log "WARNING: Claude Code configuration not accessible"
fi
}
# Main setup function
main() {
# Default to /workspace if no target directory specified
TARGET_DIR=${TARGET_DIR:-/workspace}
AMPLIFIER_DATA_DIR=${AMPLIFIER_DATA_DIR:-/app/amplifier-data}
log "π Starting Amplifier Docker Container with Enhanced Claude Configuration"
log "π Target project: $TARGET_DIR"
log "π Amplifier data: $AMPLIFIER_DATA_DIR"
# Comprehensive environment variable debugging
log "π Environment Variable Debug Information:"
log " HOME: $HOME"
log " USER: $(whoami)"
log " PWD: $PWD"
# Debug API key availability (masked for security)
if [ ! -z "$ANTHROPIC_API_KEY" ]; then
local masked_key="sk-ant-****${ANTHROPIC_API_KEY: -4}"
log " ANTHROPIC_API_KEY: $masked_key (length: ${#ANTHROPIC_API_KEY})"
validate_api_key "$ANTHROPIC_API_KEY" || log " API key format validation failed"
else
log " ANTHROPIC_API_KEY: (not set)"
fi
if [ ! -z "$AWS_ACCESS_KEY_ID" ]; then
local masked_aws="****${AWS_ACCESS_KEY_ID: -4}"
log " AWS_ACCESS_KEY_ID: $masked_aws"
else
log " AWS_ACCESS_KEY_ID: (not set)"
fi
# Validate target directory exists
if [ -d "$TARGET_DIR" ]; then
log "β
Target directory found: $TARGET_DIR"
else
log "β Target directory not found: $TARGET_DIR"
log "π‘ Make sure you mounted your project directory to $TARGET_DIR"
exit 1
fi
# Change to Amplifier directory and activate environment
log "π§ Setting up Amplifier environment..."
cd /root/amplifier
source .venv/bin/activate
# Configure Amplifier data directory
log "π Configuring Amplifier data directory..."
export AMPLIFIER_DATA_DIR="$AMPLIFIER_DATA_DIR"
# Check if API key is available
if [ -z "$ANTHROPIC_API_KEY" ] && [ -z "$AWS_ACCESS_KEY_ID" ]; then
error_exit "No API keys found! Please set ANTHROPIC_API_KEY or AWS credentials"
fi
# Configure Claude Code based on available credentials
if [ ! -z "$ANTHROPIC_API_KEY" ]; then
log "π§ Configuring Claude Code with Anthropic API..."
log "π Backend: ANTHROPIC DIRECT API"
# Create comprehensive Claude configuration
create_claude_config "$ANTHROPIC_API_KEY"
# Set CLI configuration flags
configure_claude_cli
# Verify configuration
verify_configuration
# Test basic functionality
test_claude_functionality
log "β
Claude Code configuration completed successfully"
log "π Adding target directory: $TARGET_DIR"
log "π Starting interactive Claude Code session with initial prompt..."
log ""
# Start Claude with enhanced configuration and initial prompt
claude --add-dir "$TARGET_DIR" --permission-mode acceptEdits "I'm working in $TARGET_DIR which doesn't have Amplifier files. Please cd to that directory and work there. Do NOT update any issues or PRs in the Amplifier repo."
elif [ ! -z "$AWS_ACCESS_KEY_ID" ]; then
log "π§ Configuring Claude Code with AWS Bedrock..."
log "π Backend: AWS BEDROCK"
log "π Using provided AWS credentials"
log "β οΈ Setting CLAUDE_CODE_USE_BEDROCK=1"
export CLAUDE_CODE_USE_BEDROCK=1
# Create basic config for Bedrock with comprehensive structure
mkdir -p "$HOME/.claude"
cat > "$HOME/.claude.json" << CONFIG_EOF
{
"useBedrock": true,
"hasCompletedOnboarding": true,
"projects": {},
"customApiKeyResponses": {
"approved": [],
"rejected": []
},
"mcpServers": {}
}
CONFIG_EOF
# Set CLI configuration flags
configure_claude_cli
# Test basic functionality
test_claude_functionality
log "β
Claude Code Bedrock configuration completed"
log "π Adding target directory: $TARGET_DIR"
log "π Starting interactive Claude Code session with initial prompt..."
log ""
# Start Claude with directory access, explicit permission mode, and initial prompt
claude --add-dir "$TARGET_DIR" --permission-mode acceptEdits "I'm working in $TARGET_DIR which doesn't have Amplifier files. Please cd to that directory and work there. Do NOT update any issues or PRs in the Amplifier repo."
else
error_exit "No supported API configuration found!"
fi
}
# Execute main function
main "$@"
EOF
RUN chmod +x /app/entrypoint.sh
# Set environment variables
ENV TARGET_DIR=/workspace
ENV AMPLIFIER_DATA_DIR=/app/amplifier-data
ENV PATH="/app/amplifier:$PATH"
# Create volumes for mounting
VOLUME ["/workspace", "/app/amplifier-data"]
# Set the working directory to Amplifier before entrypoint
WORKDIR /root/amplifier
# Set entrypoint
ENTRYPOINT ["/app/entrypoint.sh"]