Refactor devcontainer setup with MCP servers and dynamic config
Ajout d'une configuration DevContainer complète avec MCP Servers (LSP multi-langages, GitHub/Gitea), scripts de setup automatisés (crazycoder-setup.sh, setup-devcontainer.sh), et optimisation de l’image Docker (rustup/cargo-binstall, nettoyage des artefacts). Mise à jour du README avec documentation MCP et gestion dynamique des variables d’environnement (.env généré automatiquement selon la forge détectée). Simplification des entrypoints et postStartCommand pour une initialisation plus fiable.
This commit is contained in:
@@ -1,150 +1,15 @@
|
||||
#!/bin/bash
|
||||
# docker-entrypoint.sh
|
||||
# docker-entrypoint.sh — minimal, just sets up PATH and execs the command
|
||||
|
||||
export USERNAME=${USERNAME:-devuser}
|
||||
export PATH=/usr/local/cargo/bin:/usr/local/go/bin:$HOME/.local/bin:$PATH
|
||||
|
||||
export WORKSPACE=${WORKSPACE:-/workspace}
|
||||
export LOCAL_LLM_API=${LOCAL_LLM_API:-http://host.docker.internal:1248/v1}
|
||||
export LLM_MODEL=${LLM_MODEL:-'ollama:qwen/qwen3-coder-next@4bit'}
|
||||
export AICHAT_API_BASE=$(sed -E 's@(https?://[^/]+).*$@\1@' <<< $LOCAL_LLM_API)
|
||||
export MAXTOKEN=${MAXTOKEN:-4096}
|
||||
export NUM_CTX=${NUM_CTX:-32768}
|
||||
export REPEAT_PENALTY=${REPEAT_PENALTY:-1.3}
|
||||
export TEMPERATURE=${TEMPERATURE:-0.5}
|
||||
export TOP_P=${TOP_P:-0.95}
|
||||
export TOP_K=${TOP_K:-40}
|
||||
export STOP=${STOP:-"[\"</s>\", \"\\n\\n\", \"def \", \"class \"]"}
|
||||
# Set npm prefix to user directory so global installs don't require root
|
||||
npm config set prefix "$HOME/.local"
|
||||
|
||||
# --- Initialise .ai_index si nécessaire ---
|
||||
if [ ! -d "/workspace/.ai_index" ]; then
|
||||
mkdir -p /workspace/.ai_index/ast
|
||||
mkdir -p /workspace/.ai_index/embeddings
|
||||
touch /workspace/.ai_index/graph.db
|
||||
fi
|
||||
# Clear Zed external_agents on each start so Zed can re-download without
|
||||
# hitting "Directory not empty" on atomic rename.
|
||||
rm -rf "$HOME/.local/share/zed/external_agents"
|
||||
|
||||
# --- Configure LOCAL_LLM_API pour Bash ---
|
||||
if [ -n "$LOCAL_LLM_API" ]; then
|
||||
if ! grep -q "LOCAL_LLM_API" /home/${USERNAME}/.bashrc; then
|
||||
echo "export LOCAL_LLM_API=$LOCAL_LLM_API" >> /home/${USERNAME}/.bashrc
|
||||
echo "export AICHAT_API_BASE=$AICHAT_API_BASE" >> /home/${USERNAME}/.bashrc
|
||||
echo "export PATH=\$HOME/.cargo/bin:\$HOME/go/bin:\$HOME/.local/bin:\$PATH" >> /home/${USERNAME}/.bashrc
|
||||
fi
|
||||
|
||||
# --- Configure aichat ---
|
||||
mkdir -p /home/${USERNAME}/.config/aichat
|
||||
AICHAT_CONFIG=/home/${USERNAME}/.config/aichat/config.yaml
|
||||
cat > $AICHAT_CONFIG <<EOF
|
||||
model: lmstudio:${LLM_MODEL#*:}
|
||||
clients:
|
||||
- type: openai-compatible
|
||||
name: lmstudio
|
||||
api_base: ${LOCAL_LLM_API}
|
||||
api_key: placeholder
|
||||
models:
|
||||
- name: ${LLM_MODEL#*:}
|
||||
max_input_tokens: ${NUM_CTX}
|
||||
temperature: ${TEMPERATURE}
|
||||
top_p: ${TOP_P}
|
||||
EOF
|
||||
chown ${USERNAME}:${USERNAME} ${AICHAT_CONFIG}
|
||||
|
||||
mkdir -p /home/${USERNAME}/.config/opencode
|
||||
CONFIG_FILE=/home/${USERNAME}/.config/opencode/opencode.json
|
||||
|
||||
cat > $CONFIG_FILE <<EOF
|
||||
{
|
||||
"\$schema": "https://opencode.ai/config.json",
|
||||
"mcp": {
|
||||
"go-lsp-tools": {
|
||||
"type": "local",
|
||||
"command": ["mcp-language-server",
|
||||
"--workspace", "$WORKSPACE",
|
||||
"--lsp", "gopls"
|
||||
],
|
||||
"enabled": true,
|
||||
"environment": {
|
||||
"GOPATH": "$GOPATH"
|
||||
}
|
||||
},
|
||||
"python-lsp-tools": {
|
||||
"type": "local",
|
||||
"command": ["mcp-language-server",
|
||||
"--workspace", "$WORKSPACE",
|
||||
"--lsp", "pyright-langserver",
|
||||
"--", "--stdio"
|
||||
],
|
||||
"enabled": true
|
||||
},
|
||||
"rust-lsp-tools": {
|
||||
"type": "local",
|
||||
"command": ["mcp-language-server",
|
||||
"--workspace", "$WORKSPACE",
|
||||
"--lsp", "$(find /usr/local/rustup/toolchains -type f -name rust-analyzer)"
|
||||
],
|
||||
"enabled": true
|
||||
},
|
||||
"typescript-lsp-tools": {
|
||||
"type": "local",
|
||||
"command": ["mcp-language-server",
|
||||
"--workspace", "$WORKSPACE",
|
||||
"--lsp", "typescript-language-server",
|
||||
"--", "--stdio"
|
||||
],
|
||||
"enabled": true
|
||||
},
|
||||
},
|
||||
"provider": {
|
||||
"lmstudio": {
|
||||
"npm": "@ai-sdk/openai-compatible",
|
||||
"name": "LM Studio (local)",
|
||||
"options": {
|
||||
"baseURL": "$LOCAL_LLM_API",
|
||||
"apiKey": ""
|
||||
},
|
||||
"models": {
|
||||
"qwen/qwen3-coder-next@4bit": {
|
||||
"name": "Qwen 3 Coder Next 80B — (LLMStudio ; 4-bit)",
|
||||
"limit": {
|
||||
"context": 200000,
|
||||
"output": 65536
|
||||
},
|
||||
"settings": {
|
||||
"temperature": $TEMPERATURE,
|
||||
"top_p": $TOP_P,
|
||||
"top_k": $TOP_K,
|
||||
"max_tokens": ${MAXTOKEN},
|
||||
"num_ctx": ${NUM_CTX},
|
||||
"repeat_penalty": ${REPEAT_PENALTY},
|
||||
"stop": ${STOP}
|
||||
}
|
||||
},
|
||||
"qwen/qwen3-coder-next@6bit": {
|
||||
"name": "Qwen 3 Coder Next 80B — (LLMStudio ; 6-bit)",
|
||||
"limit": {
|
||||
"context": 200000,
|
||||
"output": 65536
|
||||
},
|
||||
"settings": {
|
||||
"temperature": $TEMPERATURE,
|
||||
"top_p": $TOP_P,
|
||||
"top_k": $TOP_K,
|
||||
"max_tokens": ${MAXTOKEN},
|
||||
"num_ctx": ${NUM_CTX},
|
||||
"repeat_penalty": ${REPEAT_PENALTY},
|
||||
"stop": ${STOP}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"model": "${LLM_MODEL}"
|
||||
}
|
||||
EOF
|
||||
|
||||
chown ${USERNAME}:${USERNAME} ${CONFIG_FILE}
|
||||
fi
|
||||
|
||||
# --- Force Bash comme shell par défaut ---
|
||||
if [ -z "$1" ]; then
|
||||
exec /bin/bash
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user