From 971a8f775d5e89e484e56a575e8ae2706fe2b53f Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Wed, 20 May 2026 15:43:07 +0900 Subject: fix: sidebar layout, copilot auth script, config setup - Sidebar uses absolute inset-0 with overflow-y-auto for proper scrolling - Border moved to inner div so it hides with sidebar - Copilot auth script uses portable sed instead of grep -P (macOS compat) - dispatch.toml with 3 keys, 4 models, fallback order - .env.dispatch with key placeholders and script reference - docker-compose loads .env.dispatch via env_file --- .gitignore | 1 + bin/copilot-auth | 84 +++++++++++++++++++++++++++++++++++++++ dispatch.toml | 86 ++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 4 +- packages/frontend/src/App.svelte | 4 +- 5 files changed, 175 insertions(+), 4 deletions(-) create mode 100755 bin/copilot-auth create mode 100644 dispatch.toml diff --git a/.gitignore b/.gitignore index 405d693..3d7cb2d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ node_modules/ dist/ build/ .env +.env.dispatch *.db *.sqlite .DS_Store diff --git a/bin/copilot-auth b/bin/copilot-auth new file mode 100755 index 0000000..28d08a1 --- /dev/null +++ b/bin/copilot-auth @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +set -euo pipefail + +CLIENT_ID="Ov23li8tweQw6odWQebz" +ENV_FILE="$(cd "$(dirname "$0")/.." && pwd)/.env.dispatch" + +# Parse form-encoded key=value pairs +parse() { + local key="$1" data="$2" + local val + val=$(echo "$data" | sed -n "s/.*${key}=\([^&]*\).*/\1/p") + python3 -c "import sys,urllib.parse; print(urllib.parse.unquote(sys.stdin.read().strip()))" <<< "$val" +} + +echo "=== GitHub Copilot OAuth ===" +echo "" + +# Step 1: Request device code +echo "Requesting device code..." +RESP=$(curl -s https://github.com/login/device/code \ + -d "client_id=$CLIENT_ID" \ + -d "scope=read:user") + +DEVICE_CODE=$(parse "device_code" "$RESP") + +if [ -z "$DEVICE_CODE" ]; then + echo "Failed to get device code: $RESP" + exit 1 +fi + +USER_CODE=$(parse "user_code" "$RESP") +VERIF_URI=$(parse "verification_uri" "$RESP") +INTERVAL=$(parse "interval" "$RESP") +INTERVAL=${INTERVAL:-5} + +echo "" +echo "Open this URL and enter the code:" +echo " $VERIF_URI" +echo " Code: $USER_CODE" +echo "" +echo "Waiting for you to authorize..." + +# Step 2: Poll for access token +TOKEN="" +ATTEMPTS=0 +while [ -z "$TOKEN" ] && [ $ATTEMPTS -lt 60 ]; do + sleep "$INTERVAL" + ATTEMPTS=$((ATTEMPTS + 1)) + + TOKEN_RESP=$(curl -s https://github.com/login/oauth/access_token \ + -d "client_id=$CLIENT_ID" \ + -d "device_code=$DEVICE_CODE" \ + -d "grant_type=urn:ietf:params:oauth:grant-type:device_code") + + TOKEN=$(parse "access_token" "$TOKEN_RESP" || true) + ERROR=$(parse "error" "$TOKEN_RESP" || true) + + if [ "$ERROR" = "authorization_pending" ]; then + continue + elif [ "$ERROR" = "slow_down" ]; then + INTERVAL=$((INTERVAL + 5)) + continue + elif [ -n "$ERROR" ]; then + echo "Error: $ERROR" + exit 1 + fi +done + +if [ -z "$TOKEN" ]; then + echo "Timed out waiting for authorization." + exit 1 +fi + +# Step 3: Write to .env.dispatch +mkdir -p "$(dirname "$ENV_FILE")" +if [ -f "$ENV_FILE" ] && grep -q "^COPILOT_TOKEN=" "$ENV_FILE" 2>/dev/null; then + sed -i "s/^COPILOT_TOKEN=.*/COPILOT_TOKEN=$TOKEN/" "$ENV_FILE" +else + echo "COPILOT_TOKEN=$TOKEN" >> "$ENV_FILE" +fi + +echo "" +echo "Token saved to .env.dispatch" +echo "Ready — run: docker compose up" diff --git a/dispatch.toml b/dispatch.toml new file mode 100644 index 0000000..1559578 --- /dev/null +++ b/dispatch.toml @@ -0,0 +1,86 @@ +# Dispatch — Model & Key Configuration +# Keys reference env var names in .env.dispatch + +# ─── Fallback Order (highest priority first) ──────────────────── +# Exhaust opencode-1 first, then opencode-2, then copilot. +# When all keys are exhausted the agent enters wait-for-refresh. +# Must be declared BEFORE any [[keys]] / [[models]] blocks. + +fallback = ["opencode-1", "opencode-2", "copilot"] + +# ─── API Keys ─────────────────────────────────────────────────── + +[[keys]] +id = "opencode-1" +provider = "opencode-go" +env = "OPENCODE_KEY_1" +base_url = "https://opencode.ai/zen/go/v1" + +[[keys]] +id = "opencode-2" +provider = "opencode-go" +env = "OPENCODE_KEY_2" +base_url = "https://opencode.ai/zen/go/v1" + +[[keys]] +id = "copilot" +provider = "github-copilot" +env = "COPILOT_TOKEN" +base_url = "https://api.githubcopilot.com" + +# ─── Models ───────────────────────────────────────────────────── + +[[models]] +id = "deepseek-v4-pro" +provider = "opencode-go" +tags = ["heavy", "coding"] + +[[models]] +id = "deepseek-v4-flash" +provider = "opencode-go" +tags = ["light", "quick"] + +[[models]] +id = "gpt-4o" +provider = "github-copilot" +tags = ["heavy", "coding"] + +[[models]] +id = "claude-3.5-sonnet" +provider = "github-copilot" +tags = ["heavy", "coding", "review"] + +# ─── Agent Templates ───────────────────────────────────────────── + +[agents.default] +name = "Dispatch" +description = "Default coding assistant" +system_prompt = "You are a helpful AI coding assistant." +tools = ["read_file", "write_file", "list_files", "run_shell", "task_list"] +model_tag = "heavy" + +# ─── Permissions ───────────────────────────────────────────────── + +[permissions] +read = "allow" + +[permissions.edit] +"*" = "ask" +"src/**" = "allow" + +[permissions.bash] +"npm test" = "allow" +"npm run *" = "allow" +"git status" = "allow" +"git diff" = "allow" +"git log *" = "allow" +"git branch *" = "allow" +"git add *" = "allow" +"git commit *" = "allow" +"git push *" = "allow" +"ls *" = "allow" +"*" = "ask" + +[permissions.external_directory] +"~/*" = "ask" +"/tmp/*" = "allow" diff --git a/docker-compose.yml b/docker-compose.yml index e52d3f2..f669705 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,9 +8,9 @@ services: - "3000:3000" volumes: - .:/app + env_file: + - .env.dispatch environment: - OPENCODE_API_KEY: ${OPENCODE_API_KEY:-} - DISPATCH_MODEL: ${DISPATCH_MODEL:-deepseek-v4-flash} DISPATCH_WORKING_DIR: /app frontend: diff --git a/packages/frontend/src/App.svelte b/packages/frontend/src/App.svelte index 02a80ba..43fcc5d 100644 --- a/packages/frontend/src/App.svelte +++ b/packages/frontend/src/App.svelte @@ -92,12 +92,12 @@ onMount(() => {
-- cgit v1.2.3