diff options
| author | Adam Malczewski <[email protected]> | 2026-05-21 17:30:08 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-05-21 17:30:08 +0900 |
| commit | d6b208342edf97bafa5b1dcc986b782f9879d141 (patch) | |
| tree | c6d8f9bffa86f78e3b1369b811bef9642df788d0 /bin | |
| parent | 1f309ccca20aabbd0ee3fb8fbb3c8192124edd95 (diff) | |
| download | dispatch-d6b208342edf97bafa5b1dcc986b782f9879d141.tar.gz dispatch-d6b208342edf97bafa5b1dcc986b782f9879d141.zip | |
feat: SQLite database for all credentials, keys, wake schedule, and usage cache
- Add SQLite database at ~/.local/share/dispatch/dispatch.db with tables: credentials, api_keys, wake_schedule, usage_cache
- Store Claude OAuth credentials in DB with import button in Model Status UI
- Store OpenCode/Copilot API keys in DB with paste-to-import modal
- Store OpenCode cookie and workspace IDs in DB
- Migrate wake schedule from .wake-schedule.json to DB
- Migrate usage cache from in-memory Map + localStorage to DB
- Remove all env var and file fallbacks — DB is the single source of truth
- Add seed scripts: bin/import-credentials.ts, bin/seed-opencode-keys.ts
- Docker: container runs as host UID/GID with matching home directory
- Clean up dispatch.toml: remove env fields, update comments
- Progress bar time markers for usage cycle tracking
Diffstat (limited to 'bin')
| -rwxr-xr-x | bin/import-credentials.ts | 26 | ||||
| -rw-r--r-- | bin/seed-opencode-keys.ts | 28 | ||||
| -rwxr-xr-x | bin/up | 5 | ||||
| -rwxr-xr-x | bin/up-backend | 8 |
4 files changed, 66 insertions, 1 deletions
diff --git a/bin/import-credentials.ts b/bin/import-credentials.ts new file mode 100755 index 0000000..f99f20a --- /dev/null +++ b/bin/import-credentials.ts @@ -0,0 +1,26 @@ +#!/usr/bin/env bun +/** + * Import Claude credentials into the Dispatch SQLite database. + * Reads from ~/.claude/.credentials-{1,2}.json and stores them + * for the configured keys (claude-pro, claude-max). + */ +import { importCredentialsFromFile, getDatabasePath } from "../packages/core/src/index.js"; + +const imports = [ + { keyId: "claude-pro", provider: "anthropic", file: `${process.env.HOME}/.claude/.credentials-1.json` }, + { keyId: "claude-max", provider: "anthropic", file: `${process.env.HOME}/.claude/.credentials-2.json` }, +]; + +console.log(`Database: ${getDatabasePath()}\n`); + +for (const { keyId, provider, file } of imports) { + process.stdout.write(`Importing ${keyId} from ${file} ... `); + const result = importCredentialsFromFile(keyId, provider, file); + if (result.success) { + console.log("OK"); + } else { + console.log(`FAILED: ${result.error}`); + } +} + +console.log("\nDone."); diff --git a/bin/seed-opencode-keys.ts b/bin/seed-opencode-keys.ts new file mode 100644 index 0000000..c461592 --- /dev/null +++ b/bin/seed-opencode-keys.ts @@ -0,0 +1,28 @@ +#!/usr/bin/env bun +/** + * Seed API keys from environment variables into the SQLite database. + */ +import { setApiKey, getDatabasePath } from "../packages/core/src/index.js"; + +console.log(`Database: ${getDatabasePath()}\n`); + +const keys = [ + { keyId: "opencode-1", provider: "opencode-go", envVar: "OPENCODE_KEY_1" }, + { keyId: "opencode-2", provider: "opencode-go", envVar: "OPENCODE_KEY_2" }, + { keyId: "copilot", provider: "github-copilot", envVar: "COPILOT_TOKEN" }, + { keyId: "opencode-cookie", provider: "opencode-go", envVar: "OPENCODE_COOKIE" }, + { keyId: "opencode-ws1", provider: "opencode-go", envVar: "OPENCODE_WS1_ID" }, + { keyId: "opencode-ws2", provider: "opencode-go", envVar: "OPENCODE_WS2_ID" }, +]; + +for (const { keyId, provider, envVar } of keys) { + const value = process.env[envVar]; + if (value) { + setApiKey(keyId, provider, value); + console.log(`${keyId}: imported from $${envVar}`); + } else { + console.log(`${keyId}: SKIPPED ($${envVar} not set)`); + } +} + +console.log("\nDone."); @@ -10,6 +10,11 @@ PROJECT_DIR="$(dirname "$SCRIPT_DIR")" # Load secrets from gopass OPENCODE_API_KEY="$(gopass show -o projects/ai-api/opencode_go_key)" +# Pass host user identity so the container runs as the same UID/GID +export HOST_UID="$(id -u)" +export HOST_GID="$(id -g)" +export HOST_USER="$(whoami)" + # Start all services 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 index 722e5eb..894fc01 100755 --- a/bin/up-backend +++ b/bin/up-backend @@ -10,6 +10,12 @@ PROJECT_DIR="$(dirname "$SCRIPT_DIR")" # Load secrets from gopass OPENCODE_API_KEY="$(gopass show -o projects/ai-api/opencode_go_key)" +# Pass host user identity so the container runs as the same UID/GID +export HOST_UID="$(id -u)" +export HOST_GID="$(id -g)" +export HOST_USER="$(whoami)" + # Start API service only -sudo OPENCODE_API_KEY="$OPENCODE_API_KEY" \ +sudo -E OPENCODE_API_KEY="$OPENCODE_API_KEY" \ + HOST_UID="$HOST_UID" HOST_GID="$HOST_GID" HOST_USER="$HOST_USER" \ docker compose -f "$PROJECT_DIR/docker-compose.yml" up api "$@" |
