summaryrefslogtreecommitdiffhomepage
path: root/bin
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-05-21 17:30:08 +0900
committerAdam Malczewski <[email protected]>2026-05-21 17:30:08 +0900
commitd6b208342edf97bafa5b1dcc986b782f9879d141 (patch)
treec6d8f9bffa86f78e3b1369b811bef9642df788d0 /bin
parent1f309ccca20aabbd0ee3fb8fbb3c8192124edd95 (diff)
downloaddispatch-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-xbin/import-credentials.ts26
-rw-r--r--bin/seed-opencode-keys.ts28
-rwxr-xr-xbin/up5
-rwxr-xr-xbin/up-backend8
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.");
diff --git a/bin/up b/bin/up
index 03df1b7..2cccfa8 100755
--- a/bin/up
+++ b/bin/up
@@ -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 "$@"