diff --git a/.devcontainer/continue-config.yaml b/.devcontainer/continue-config.yaml index 3da790d..0b8bfff 100644 --- a/.devcontainer/continue-config.yaml +++ b/.devcontainer/continue-config.yaml @@ -1,101 +1,36 @@ -name: Local Assistant +name: Local Config version: 1.0.0 schema: v1 models: - # - name: Llama 3.1 8B - # model: llama3.1:8b - # provider: openai - # apiBase: ${{ secrets.OPENWEB_BASE_URL }} - # apiKey: ${{ secrets.OPENWEB_API_KEY }} - # roles: - # - chat - # - edit - # - apply - - name: gemma3 4B - model: gemma3:4b - provider: openai - apiBase: ${{ secrets.OPENWEB_BASE_URL }} - apiKey: ${{ secrets.OPENWEB_API_KEY }} - roles: - - chat - - edit - - apply - - autocomplete +- name: Qwen3-Coder-30B-A3B-Instruct + provider: openai + apiBase: ${{ secrets.OPENAI_BASE_URL }} + apiKey: ${{ secrets.OPENAI_API_KEY }} + model: qwen3-coder:30b + roles: + - chat + - edit + - apply + - autocomplete + capabilities: + - tool use - - name: deepseek-r1 8b - model: deepseek-r1:8b - provider: openai - apiBase: ${{ secrets.OPENWEB_BASE_URL }} - apiKey: ${{ secrets.OPENWEB_API_KEY }} - roles: - - chat - - edit - - apply +- name: nomic-embed-text + provider: openai + apiBase: ${{ secrets.OPENAI_BASE_URL }} + apiKey: ${{ secrets.OPENAI_API_KEY }} + model: nomic-embed-text:v1.5 + roles: + - embed - - name: qwen3 8B - model: qwen3:8b - provider: openai - apiBase: ${{ secrets.OPENWEB_BASE_URL }} - apiKey: ${{ secrets.OPENWEB_API_KEY }} - roles: - - chat - - edit - - apply - - autocomplete - - - name: Nomic Embed - model: nomic-embed-text:latest - provider: openai - apiBase: ${{ secrets.OPENWEB_BASE_URL }} - apiKey: ${{ secrets.OPENWEB_API_KEY }} - embedOptions: - maxChunkSize: 8192 - roles: - - embed - - - name: Qwen 2.5b Autocomplete Model - model: qwen2.5-coder:1.5b - provider: openai - apiBase: ${{ secrets.OPENWEB_BASE_URL }} - apiKey: ${{ secrets.OPENWEB_API_KEY }} - roles: - - chat - - edit - - apply - - autocomplete - defaultCompletionOptions: - contextLength: 32768 - maxTokens: 8192 - - - name: gpt-oss-20b - provider: openai - model: gpt-oss:20b - apiBase: ${{ secrets.OPENWEB_BASE_URL }} - apiKey: ${{ secrets.OPENWEB_API_KEY }} - roles: - - chat - - edit - - apply - - # - name: Qwen3-Coder-30B-A3B-Instruct - # provider: openai - # model: qwen3-coder:30b - # apiBase: ${{ secrets.OPENWEB_BASE_URL }} - # apiKey: ${{ secrets.OPENWEB_API_KEY }} - # roles: - # - chat - # - edit - # - apply - -context: - - provider: code - - provider: currentFile - - provider: codebase - - provider: docs - - provider: diff - - provider: file - - provider: problems - - provider: repo-map - - provider: terminal - - provider: tree +# - name: Autodetect +# provider: ollama +# apiBase: http://localhost:11434 +# model: AUTODETECT +# roles: +# - chat +# - edit +# - apply +# - rerank +# - autocomplete diff --git a/.devcontainer/continue.env b/.devcontainer/continue.env index b2e0433..f94b095 100644 --- a/.devcontainer/continue.env +++ b/.devcontainer/continue.env @@ -1,2 +1,4 @@ # Open WebUI -OPENWEB_BASE_URL=http://host.containers.internal:11434/v1 +OPENAI_BASE_URL="https://host.containers.internal:8080/api" +# WARNING: Replace the value below with your actual OpenAI API key before use. +OPENAI_API_KEY="REPLACE_ME" \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3eafdbf..63e37d5 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -27,21 +27,21 @@ "userUid": "automatic", "userGid": "automatic" }, - "ghcr.io/rocker-org/devcontainer-features/quarto-cli:1": { - "installTinyTex": true, - "installChromium": true, - "version": "latest" - }, - // R language support, https://github.com/rocker-org/devcontainer-features/tree/main/src/r-apt - "ghcr.io/rocker-org/devcontainer-features/r-apt:0": { - "installDevTools": true, - "installREnv": true, - "installRMarkdown": true, - "installRadian": true, - "installVscDebugger": true, - "useTesting": true, - "vscodeRSupport": "full" - }, + // "ghcr.io/rocker-org/devcontainer-features/quarto-cli:1": { + // "installTinyTex": true, + // "installChromium": true, + // "version": "latest" + // }, + // // R language support, https://github.com/rocker-org/devcontainer-features/tree/main/src/r-apt + // "ghcr.io/rocker-org/devcontainer-features/r-apt:0": { + // "installDevTools": true, + // "installREnv": true, + // "installRMarkdown": true, + // "installRadian": true, + // "installVscDebugger": true, + // "useTesting": true, + // "vscodeRSupport": "full" + // }, "ghcr.io/devcontainers-extra/features/npm-packages:1": { "packages": "@continuedev/cli@latest,@openai/codex@latest,@qwen-code/qwen-code@latest" }, diff --git a/.devcontainer/qwen-settings.json b/.devcontainer/qwen-settings.json new file mode 100644 index 0000000..c03bb13 --- /dev/null +++ b/.devcontainer/qwen-settings.json @@ -0,0 +1,14 @@ +{ + "security": { + "auth": { + // WARNING: Replace the placeholder API key below with your actual API key before use. + "selectedType": "openai", + "apiKey": "sk-", + "baseUrl": "http://host.containers.internal:8080/api" + } + }, + "model": { + "name": "qwen3-coder:30b" + }, + "$version": 2 +} \ No newline at end of file diff --git a/.devcontainer/vscode-init/02-download-extensions.sh b/.devcontainer/vscode-init/02-download-extensions.sh index 06c28d2..38e7b83 100755 --- a/.devcontainer/vscode-init/02-download-extensions.sh +++ b/.devcontainer/vscode-init/02-download-extensions.sh @@ -10,9 +10,11 @@ set -e # of the extension and its functionality gets inherited by devcontainers. EXTENSIONS_FILE="extensions-to-download.txt" -DOWNLOAD_DIR="/opt" +DOWNLOAD_DIR="/opt/vscode-extensions" SUCCESSFUL_DOWNLOADS=() +mkdir -p "${DOWNLOAD_DIR}" + if [ ! -f "${EXTENSIONS_FILE}" ]; then echo "Error: Extensions file not found at ${EXTENSIONS_FILE}" exit 1 @@ -41,7 +43,10 @@ download_extension() { local extension_name="${extension_id#*.}" local extension_filepath="${DOWNLOAD_DIR}/${extension_id}.vsix" - local download_url="https://${publisher}.gallery.vsassets.io/_apis/public/gallery/publisher/${publisher}/extension/${extension_name}/latest/assetbyname/Microsoft.VisualStudio.Services.VSIXPackage" + + # We first need to lookup releases to find the latest version and architecture to download URL + local download_url="$(curl -sSL https://marketplace.visualstudio.com/_apis/public/gallery/vscode/${publisher}/${extension_name}/latest \ + | jq -r '.versions[] | select(.targetPlatform == "linux-x64" or .targetPlatform == null) | select(.flags | contains("prerelease") | not) | .files[] | select(.assetType == "Microsoft.VisualStudio.Services.VSIXPackage") | .source' | head -n1)" echo "Downloading ${extension_id}..." diff --git a/.devcontainer/vscode-init/extensions-to-download.txt b/.devcontainer/vscode-init/extensions-to-download.txt index 2b70d1c..5b9aa4b 100644 --- a/.devcontainer/vscode-init/extensions-to-download.txt +++ b/.devcontainer/vscode-init/extensions-to-download.txt @@ -9,4 +9,5 @@ vscodevim.vim Continue.continue ms-toolsai.jupyter-keymap openai.chatgpt +qwenlm.qwen-code-vscode-ide-companion REditorSupport.r-syntax \ No newline at end of file diff --git a/.devcontainer/vscode-init/extensions-to-install.txt b/.devcontainer/vscode-init/extensions-to-install.txt index e2ca3e6..9fb91ff 100644 --- a/.devcontainer/vscode-init/extensions-to-install.txt +++ b/.devcontainer/vscode-init/extensions-to-install.txt @@ -2,17 +2,18 @@ # These extensions will be enabled for all users of the devcontainer. # One extension ID per line. charliermarsh.ruff -#Continue.continue +Continue.continue --pre-release DavidAnson.vscode-markdownlint eamodio.gitlens # The marimo extension has been removed from the marketplace whilst it is being rewritten. -# marimo-team.vscode-marimo +marimo-team.vscode-marimo mechatroner.rainbow-csv ms-ossdata.vscode-pgsql --pre-release ms-python.black-formatter ms-toolsai.datawrangler ms-toolsai.jupyter #openai.chatgpt +qwenlm.qwen-code-vscode-ide-companion REditorSupport.r REditorSupport.r-syntax yzhang.markdown-all-in-one \ No newline at end of file diff --git a/.github/workflows/build-devcontainer.yml b/.github/workflows/build-devcontainer.yml index 3849499..b3fc65c 100644 --- a/.github/workflows/build-devcontainer.yml +++ b/.github/workflows/build-devcontainer.yml @@ -117,6 +117,7 @@ jobs: imageTag: ${{ steps.tags.outputs.tags }} cacheFrom: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} push: always + platform: linux/amd64 # Test the container with a simple validation runCmd: | echo "=== Testing dev container ===" diff --git a/Dockerfile b/Dockerfile index dd41a68..7c7c481 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/devcontainers/base:noble +FROM --platform=linux/amd64 mcr.microsoft.com/devcontainers/base:noble # VS Code commit ID for devcontainer compatibility. Can be overridden at build time via build args. # Default chosen for current stable VS Code Server version used in this repository. @@ -9,6 +9,9 @@ ENV VSCODE_COMMIT=${VSCODE_COMMIT} # Copy and run VS Code installation files COPY .devcontainer/vscode-init /opt/vscode-init +# Copy Qwen settings +COPY .devcontainer/qwen-settings.json /root/.qwen/settings.json + # Copy Codex config COPY .devcontainer/codex-config.toml /root/.codex/config.toml @@ -16,7 +19,7 @@ COPY .devcontainer/codex-config.toml /root/.codex/config.toml COPY .devcontainer/continue-config.yaml /root/.continue/config.yaml COPY .devcontainer/continue.env /root/.continue/.env -# Copy scripts folder +# Copy scripts folder to /opt/scripts (accessible at runtime) COPY scripts /opt/scripts RUN cd /opt/vscode-init \ diff --git a/README.md b/README.md index 64145f1..9d74dfc 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ ces-pull a a ghcr.io/smartdatafoundry/devcontainer:latest # 2. Extract the setup scripts podman run --rm -v $HOME:$HOME -w $HOME \ ghcr.io/smartdatafoundry/devcontainer:latest \ - cp -r /workspace/scripts $HOME/devcontainer-scripts + cp -r /opt/scripts $HOME/devcontainer-scripts # 3. Run the setup script (one-time setup) cd $HOME/devcontainer-scripts @@ -79,10 +79,10 @@ devcontainerctl start The setup script will: - Create a symlink to `devcontainerctl` in `~/bin` - Add `~/bin` to your PATH -- Configure a daily cron job to keep the image updated +- Configure a daily cron job (8:00 AM) to update your container with the latest version Available `devcontainerctl` commands: -- `devcontainerctl start` - Pull latest image and start container +- `devcontainerctl start` - Start container with existing image - `devcontainerctl stop` - Stop the container - `devcontainerctl restart` - Restart the container - `devcontainerctl status` - Check container status @@ -147,7 +147,7 @@ This dev container includes comprehensive R language support through the [Rocker ## ⚙️ VS Code Server -Pre-installed. Pin a version using the tag families described above or via build arg `VSCODE_COMMIT`. For environment-specific considerations (e.g. TRE) see [`docs/SDF_TRE_SETUP.md`](docs/SDF_TRE_SETUP.md). +Pre-installed. Pin a version using the tag families described above or via build arg `VSCODE_COMMIT` (default: `7d842fb85a0275a4a8e4d7e040d2625abbf7f084`). For environment-specific considerations (e.g. TRE) see [`docs/SDF_TRE_SETUP.md`](docs/SDF_TRE_SETUP.md). ## Adding New Extensions To add new VS Code extensions to the container, follow these steps: diff --git a/docs/DEVCONTAINER.md b/docs/DEVCONTAINER.md index 7a33128..71df145 100644 --- a/docs/DEVCONTAINER.md +++ b/docs/DEVCONTAINER.md @@ -75,11 +75,11 @@ This dev container includes: * **Marimo**: Alternative interactive notebook/presentation tool * **VS Code Server**: Pre-installed (pin via tag families) * **VS Code Extensions**: Curated list (see [`.devcontainer/vscode-init/extensions-to-install.txt`](.devcontainer/vscode-init/extensions-to-install.txt)) -* **User Setup Scripts**: Automated deployment and management tools +* **User Setup Scripts**: Automated deployment and management tools (at `/opt/scripts/` in container) ### User Setup Scripts -The container includes scripts in [`/workspace/scripts/`](scripts/) to simplify deployment and management: +The container includes scripts in [`/opt/scripts/`](../scripts/) to simplify deployment and management: #### [`scripts/devcontainerctl`](scripts/devcontainerctl) A comprehensive container lifecycle management script that provides: @@ -103,10 +103,13 @@ A comprehensive container lifecycle management script that provides: **Usage:** ```bash -devcontainerctl start # Start with auto-detected VS Code version -devcontainerctl start vscode-abc123 # Start with specific tag -devcontainerctl status # Check status -devcontainerctl sync # Update image (used by daily cron) +devcontainerctl start # Start with auto-detected VS Code version (image must already be pulled; run 'update' or 'sync' first if needed) +devcontainerctl start vscode-abc123 # Start with specific tag (image must already be pulled) +devcontainerctl status # Check status +devcontainerctl sync # Update image (used by daily cron) +devcontainerctl update # Update and restart +devcontainerctl stop # Stop container +devcontainerctl remove # Remove container ``` #### [`scripts/setup.sh`](scripts/setup.sh) @@ -116,14 +119,14 @@ One-time setup script that configures your environment: - Creates `~/bin` directory if needed - Creates symlink to `devcontainerctl` in `~/bin` - Adds `~/bin` to PATH in `~/.bashrc` -- Configures daily cron job (8:00 AM) to sync images +- Configures daily cron job (8:00 AM) to sync images using `devcontainerctl sync` **Usage:** ```bash # Extract scripts from container first podman run --rm -v $HOME:$HOME -w $HOME \ ghcr.io/smartdatafoundry/devcontainer:latest \ - cp -r /workspace/scripts $HOME/devcontainer-scripts + cp -r /opt/scripts $HOME/devcontainer-scripts # Run setup cd $HOME/devcontainer-scripts diff --git a/docs/SDF_TRE_SETUP.md b/docs/SDF_TRE_SETUP.md index 614d83e..4793689 100644 --- a/docs/SDF_TRE_SETUP.md +++ b/docs/SDF_TRE_SETUP.md @@ -15,7 +15,7 @@ ces-pull a a ghcr.io/smartdatafoundry/devcontainer:latest # 2. Extract the setup scripts podman run --rm -v $HOME:$HOME -w $HOME \ ghcr.io/smartdatafoundry/devcontainer:latest \ - cp -r /workspace/scripts $HOME/devcontainer-scripts + cp -r /opt/scripts $HOME/devcontainer-scripts # 3. Run the one-time setup cd $HOME/devcontainer-scripts @@ -61,7 +61,7 @@ This script will: - Create `~/bin` directory if it doesn't exist - Create a symlink to `devcontainerctl` in `~/bin` - Add `~/bin` to your PATH (in `~/.bashrc`) -- Configure a daily cron job (8:00 AM) to keep your image updated +- Configure a daily cron job (8:00 AM) to sync your image with latest version After running the setup, either restart your terminal or run: ```bash @@ -96,9 +96,9 @@ devcontainerctl remove The setup provides several automatic features: -1. **Daily Updates**: A cron job runs at 8:00 AM daily to sync your container image with the latest version matching your VS Code installation +1. **Daily Updates**: A cron job runs at 8:00 AM daily to sync your container image with the latest version matching your VS Code installation (using `devcontainerctl sync`) -2. **VS Code Tag Alignment**: The `devcontainerctl start` command automatically detects your installed VS Code version and pulls the matching container image tag (e.g., `vscode-abc1234`) +2. **VS Code Tag Alignment**: The `devcontainerctl update` command automatically detects your installed VS Code version and starts the matching container image tag (e.g., `vscode-7d842fb`) 3. **Automatic Mounting**: Your home directory and `/safe_data` are automatically mounted when the container starts @@ -135,11 +135,11 @@ ces-pull a a ghcr.io/smartdatafoundry/devcontainer:latest The Dev Containers extension VSIX is baked into the image for offline / restricted environments. Extract it: ```bash -podman run --rm -it \ +podman run --rm \ -v $PWD:$PWD \ -w $PWD \ ghcr.io/smartdatafoundry/devcontainer:latest \ - cp /opt/ms-vscode-remote.remote-containers.vsix . + cp /opt/vscode-init/ms-vscode-remote.remote-containers.vsix . ``` ### 3. Install the Extension @@ -193,8 +193,8 @@ Create a `.devcontainer/devcontainer.json` file in your project root: "runArgs": [ "--userns=host", - "-e HTTP_PROXY", - "-e HTTPS_PROXY" + "-e http_proxy", + "-e https_proxy" ], "remoteUser": "root" @@ -211,7 +211,7 @@ After creating this file you can reopen the project in VS Code using the Dev Con - **`runArgs`**: - `--userns=host`: Uses the host user namespace for TRE compatibility - - `-e HTTP_PROXY` and `-e HTTPS_PROXY`: **Essential** for `pip` and network calls to work within the TRE. These inherit proxy credentials from your TRE environment + - `-e http_proxy` and `-e https_proxy`: **Essential** for `pip` and network calls to work within the TRE. These inherit proxy credentials from your TRE environment - **`remoteUser`**: Set to `root` for TRE compatibility @@ -258,7 +258,7 @@ If you can't see "Dev Containers" in the VS Code command palette: If you experience network-related delays: -- Ensure your proxy settings are correctly configured in the `runArgs` (HTTP_PROXY and HTTPS_PROXY are essential) +- Ensure your proxy settings are correctly configured in the `runArgs` (http_proxy and https_proxy are essential) - File system responsiveness may vary depending on TRE network conditions ### Script Issues @@ -271,7 +271,7 @@ If `devcontainerctl` command is not found: If cron job is not running: -- Verify it's configured: `crontab -l` +- Verify it's configured: `crontab -l` (should show: `0 8 * * * $HOME/bin/devcontainerctl sync`) - Check cron logs for errors - Manually test the sync command: `devcontainerctl sync` diff --git a/scripts/devcontainerctl b/scripts/devcontainerctl index c12c51d..6083c3f 100755 --- a/scripts/devcontainerctl +++ b/scripts/devcontainerctl @@ -11,7 +11,7 @@ CONTAINER_NAME="devcontainer" show_usage() { echo "Combined script to start or stop the devcontainer" - echo "Usage: devcontainerctl [start | stop | restart | remove | shell | status | sync] VSCODE_TAG" + echo "Usage: devcontainerctl [start | stop | restart | remove | update | shell | status | sync | sync-rc] VSCODE_TAG" } get_latest_devcontainer() { @@ -42,8 +42,6 @@ get_latest_devcontainer() { start() { echo "Starting devcontainer..." - get_latest_devcontainer - # Stop and remove any existing containers with these names podman stop $CONTAINER_NAME 2>/dev/null podman rm $CONTAINER_NAME 2>/dev/null @@ -52,10 +50,12 @@ start() { podman run -d \ --name devcontainer \ --restart unless-stopped \ - -e http_proxy \ -v /safe_data:/safe_data \ -v $HOME:$HOME \ -w $HOME \ + -e http_proxy \ + -e https_proxy \ + -e no_proxy \ ghcr.io/smartdatafoundry/devcontainer:$VSCODE_TAG sleep infinity echo "devcontainer service started. Check status with '$0 status'" @@ -67,6 +67,12 @@ stop() { echo "devcontainer stopped." } +restart() { + echo "Restarting devcontainer service..." + podman restart $CONTAINER_NAME 2>/dev/null + echo "devcontainer restarted." +} + remove() { echo "Stopping and removing devcontainer service..." podman stop $CONTAINER_NAME 2>/dev/null @@ -92,6 +98,7 @@ show_status() { update() { echo "Updating devcontainer image..." + sync remove start # Restarts the container with the updated image automatically echo "devcontainer replaced with updated image." @@ -106,8 +113,7 @@ case "${1:-}" in stop ;; restart) - stop - start + restart ;; status) show_status