diff options
| author | Adam Malczewski <[email protected]> | 2026-05-19 19:40:21 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-05-19 19:40:21 +0900 |
| commit | f78a91c20f658dd404277919a0b872b352c99bb6 (patch) | |
| tree | 58cfffb655da4443f4b7a39543b86f988f15239f /bin | |
| download | dispatch-f78a91c20f658dd404277919a0b872b352c99bb6.tar.gz dispatch-f78a91c20f658dd404277919a0b872b352c99bb6.zip | |
- Bun monorepo with @dispatch/core, @dispatch/api, @dispatch/frontend
- Agent runtime with Vercel AI SDK, streaming via WebSocket
- Tools: read_file, write_file, list_files (scoped to working directory)
- Hono API server with POST /chat, GET /status, GET /health, WS /ws
- Svelte 5 + DaisyUI frontend with chat UI, theme switcher, copy button
- OpenCode Go (Zen) as LLM provider, deepseek-v4-flash-free model
- Docker setup (dev + prod) with bin/ scripts and gopass secrets
- Biome v2 linting/formatting, Vitest tests (44 passing)
- Debug info attached to error messages for diagnostics
Diffstat (limited to 'bin')
| -rwxr-xr-x | bin/build | 7 | ||||
| -rwxr-xr-x | bin/build-frontend | 17 | ||||
| -rwxr-xr-x | bin/clean | 8 | ||||
| -rwxr-xr-x | bin/dev_secrets | 27 | ||||
| -rwxr-xr-x | bin/down | 7 | ||||
| -rwxr-xr-x | bin/prod_secrets | 33 | ||||
| -rwxr-xr-x | bin/test | 10 | ||||
| -rwxr-xr-x | bin/up | 15 | ||||
| -rwxr-xr-x | bin/up-backend | 15 | ||||
| -rwxr-xr-x | bin/up-frontend | 8 |
10 files changed, 147 insertions, 0 deletions
diff --git a/bin/build b/bin/build new file mode 100755 index 0000000..3952364 --- /dev/null +++ b/bin/build @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" + +sudo docker compose -f "$PROJECT_DIR/docker-compose.yml" build "$@" diff --git a/bin/build-frontend b/bin/build-frontend new file mode 100755 index 0000000..703e072 --- /dev/null +++ b/bin/build-frontend @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" + +# Build frontend assets inside a temporary container +# Output lands in packages/frontend/dist/ on the host (via bind mount) +# +# VITE_API_URL can be set to configure the API endpoint for the build. +# Example: VITE_API_URL=https://api.example.com bin/build-frontend + +sudo VITE_API_URL="${VITE_API_URL:-}" \ + docker compose -f "$PROJECT_DIR/docker-compose.yml" \ + run --rm \ + -e VITE_API_URL \ + frontend bun run --cwd packages/frontend build "$@" diff --git a/bin/clean b/bin/clean new file mode 100755 index 0000000..1a3d459 --- /dev/null +++ b/bin/clean @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" + +# Stop containers, remove volumes, remove images +sudo docker compose -f "$PROJECT_DIR/docker-compose.yml" down --volumes --rmi local "$@" diff --git a/bin/dev_secrets b/bin/dev_secrets new file mode 100755 index 0000000..98af50d --- /dev/null +++ b/bin/dev_secrets @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Force GPG to use terminal-based pinentry (required for SSH sessions) +export GPG_TTY=$(tty) + +echo "Checking dev secrets for Dispatch..." +echo "" + +# --- OpenCode Go API Key --- + +if gopass show -o projects/ai-api/opencode_go_key &>/dev/null; then + echo "[ok] OpenCode Go API key exists" +else + echo "OpenCode Go API key not found in gopass." + echo "" + echo " 1. Go to https://opencode.ai/auth" + echo " 2. Sign in and copy your API key" + echo " 3. Paste it below" + echo "" + read -rp "Enter your OpenCode Go API key: " OPENCODE_KEY + echo "$OPENCODE_KEY" | gopass insert -f projects/ai-api/opencode_go_key + echo "[ok] OpenCode Go API key stored" +fi + +echo "" +echo "All dev secrets are configured." diff --git a/bin/down b/bin/down new file mode 100755 index 0000000..12a6000 --- /dev/null +++ b/bin/down @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" + +sudo docker compose -f "$PROJECT_DIR/docker-compose.yml" down "$@" diff --git a/bin/prod_secrets b/bin/prod_secrets new file mode 100755 index 0000000..68cc6d9 --- /dev/null +++ b/bin/prod_secrets @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Force GPG to use terminal-based pinentry (required for SSH sessions) +export GPG_TTY=$(tty) + +echo "Checking production secrets for Dispatch..." >&2 +echo "" >&2 + +# --- OpenCode Go API Key (shared across environments) --- + +if gopass show -o projects/ai-api/opencode_go_key &>/dev/null; then + echo "[ok] OpenCode Go API key exists" >&2 +else + echo "OpenCode Go API key not found in gopass." >&2 + echo "" >&2 + echo " 1. Go to https://opencode.ai/auth" >&2 + echo " 2. Sign in and copy your API key" >&2 + echo " 3. Paste it below" >&2 + echo "" >&2 + read -rp "Enter your OpenCode Go API key: " OPENCODE_KEY + echo "$OPENCODE_KEY" | gopass insert -f projects/ai-api/opencode_go_key + echo "[ok] OpenCode Go API key stored" >&2 +fi + +echo "" >&2 +echo "All production secrets are configured. Outputting .env:" >&2 +echo "" >&2 + +# --- Output .env format to stdout --- + +echo "OPENCODE_API_KEY=$(gopass show -o projects/ai-api/opencode_go_key)" +echo "DISPATCH_MODEL=deepseek-v4-flash-free" diff --git a/bin/test b/bin/test new file mode 100755 index 0000000..61b31ce --- /dev/null +++ b/bin/test @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" + +# Run the test suite inside the API container +# Uses the api service since it has access to the full workspace +sudo docker compose -f "$PROJECT_DIR/docker-compose.yml" \ + run --rm api bun run test "$@" @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Force GPG to use terminal-based pinentry (required for SSH sessions) +export GPG_TTY=$(tty) + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" + +# Load secrets from gopass +OPENCODE_API_KEY="$(gopass show -o projects/ai-api/opencode_go_key)" + +# Start all services +sudo OPENCODE_API_KEY="$OPENCODE_API_KEY" \ + docker compose -f "$PROJECT_DIR/docker-compose.yml" up "$@" diff --git a/bin/up-backend b/bin/up-backend new file mode 100755 index 0000000..722e5eb --- /dev/null +++ b/bin/up-backend @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Force GPG to use terminal-based pinentry (required for SSH sessions) +export GPG_TTY=$(tty) + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" + +# Load secrets from gopass +OPENCODE_API_KEY="$(gopass show -o projects/ai-api/opencode_go_key)" + +# Start API service only +sudo OPENCODE_API_KEY="$OPENCODE_API_KEY" \ + docker compose -f "$PROJECT_DIR/docker-compose.yml" up api "$@" diff --git a/bin/up-frontend b/bin/up-frontend new file mode 100755 index 0000000..82b4523 --- /dev/null +++ b/bin/up-frontend @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" + +# Frontend has no secrets — start frontend service only +sudo docker compose -f "$PROJECT_DIR/docker-compose.yml" up frontend "$@" |
