@desplega.ai/agent-swarm 1.85.0 → 1.87.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/openapi.json +72 -1
- package/package.json +10 -6
- package/src/be/db-queries/tracker.ts +21 -0
- package/src/be/db.ts +279 -14
- package/src/be/migrations/078_backfill_gpt_5_5_pricing.sql +15 -0
- package/src/be/migrations/079_task_followup_config.sql +1 -0
- package/src/be/modelsdev-cache.json +155618 -0
- package/src/be/modelsdev-cache.ts +46 -0
- package/src/be/seed-pricing.ts +7 -44
- package/src/cli.tsx +38 -2
- package/src/commands/codex-session-runner.ts +132 -0
- package/src/commands/context-preamble.ts +272 -0
- package/src/commands/credential-wait.ts +2 -2
- package/src/commands/e2b.ts +728 -0
- package/src/commands/provider-credentials.ts +10 -5
- package/src/commands/resume-session.ts +35 -78
- package/src/commands/runner.ts +128 -16
- package/src/e2b/dispatch.ts +429 -0
- package/src/e2b/env.ts +206 -0
- package/src/heartbeat/heartbeat.ts +145 -30
- package/src/heartbeat/templates.ts +11 -7
- package/src/http/session-data.ts +8 -1
- package/src/http/tasks.ts +152 -3
- package/src/jira/sync.ts +4 -4
- package/src/linear/sync.ts +6 -5
- package/src/prompts/base-prompt.ts +49 -3
- package/src/providers/claude-adapter.ts +76 -61
- package/src/providers/claude-managed-adapter.ts +61 -75
- package/src/providers/claude-managed-models.ts +18 -2
- package/src/providers/codex-adapter.ts +429 -112
- package/src/providers/codex-models.ts +9 -2
- package/src/providers/codex-oauth/auth-json.ts +18 -1
- package/src/providers/codex-oauth/flow.ts +24 -1
- package/src/providers/index.ts +28 -19
- package/src/providers/pricing-sources.md +7 -4
- package/src/providers/swarm-events-shared.ts +14 -0
- package/src/providers/types.ts +6 -0
- package/src/slack/HEURISTICS.md +5 -1
- package/src/slack/handlers.test.ts +35 -0
- package/src/slack/handlers.ts +79 -2
- package/src/tasks/worker-follow-up.ts +162 -2
- package/src/telemetry.ts +11 -1
- package/src/tests/base-prompt.test.ts +46 -8
- package/src/tests/claude-adapter.test.ts +5 -27
- package/src/tests/claude-managed-adapter.test.ts +42 -56
- package/src/tests/codex-adapter-otel.test.ts +4 -4
- package/src/tests/codex-adapter.test.ts +25 -37
- package/src/tests/codex-oauth.test.ts +149 -3
- package/src/tests/codex-pool.test.ts +14 -3
- package/src/tests/codex-swarm-events.test.ts +35 -0
- package/src/tests/context-window.test.ts +1 -0
- package/src/tests/credential-check.test.ts +48 -29
- package/src/tests/e2b-dispatch.test.ts +330 -0
- package/src/tests/entrypoint-config-env-export.test.ts +81 -0
- package/src/tests/follow-up-redelivery-guard.test.ts +165 -0
- package/src/tests/heartbeat-supersede-resume.test.ts +285 -0
- package/src/tests/heartbeat.test.ts +26 -16
- package/src/tests/migration-046-budgets.test.ts +6 -5
- package/src/tests/pricing-routes.test.ts +6 -5
- package/src/tests/prompt-template-remaining.test.ts +4 -0
- package/src/tests/provider-adapter.test.ts +10 -10
- package/src/tests/provider-command-format.test.ts +4 -4
- package/src/tests/resume-session.test.ts +42 -50
- package/src/tests/session-costs-codex-recompute.test.ts +25 -0
- package/src/tests/structured-output.test.ts +69 -0
- package/src/tests/task-completion-idempotency.test.ts +185 -2
- package/src/tests/task-supersede-resume.test.ts +722 -0
- package/src/tests/telemetry-init.test.ts +69 -0
- package/src/tests/vcs-tracking.test.ts +39 -0
- package/src/tools/send-task.ts +42 -10
- package/src/tools/store-progress.ts +2 -2
- package/src/tools/templates.ts +14 -2
- package/src/types.ts +46 -1
- package/src/utils/context-window.ts +1 -0
- package/src/workflows/executors/agent-task.ts +3 -0
- package/templates/schedules/daily-blocker-digest/config.json +13 -0
- package/templates/schedules/daily-blocker-digest/content.md +150 -0
- package/templates/schedules/daily-compounding-reflection/config.json +21 -0
- package/templates/schedules/daily-compounding-reflection/content.md +210 -0
- package/templates/schedules/daily-hn-briefing/config.json +13 -0
- package/templates/schedules/daily-hn-briefing/content.md +97 -0
- package/templates/schedules/daily-workflow-health-audit/config.json +13 -0
- package/templates/schedules/daily-workflow-health-audit/content.md +189 -0
- package/templates/schedules/gtm-weekly-review/config.json +13 -0
- package/templates/schedules/gtm-weekly-review/content.md +58 -0
- package/templates/schedules/weekly-dependabot-triage/config.json +13 -0
- package/templates/schedules/weekly-dependabot-triage/content.md +45 -0
- package/templates/schema.ts +26 -0
- package/templates/skills/agentmail-sending/config.json +13 -0
- package/templates/skills/agentmail-sending/content.md +48 -0
- package/templates/skills/artifacts/config.json +13 -0
- package/templates/skills/artifacts/content.md +87 -0
- package/templates/skills/browser-use-cloud/config.json +13 -0
- package/templates/skills/browser-use-cloud/content.md +155 -0
- package/templates/skills/desloppify/config.json +13 -0
- package/templates/skills/desloppify/content.md +201 -0
- package/templates/skills/exa-search/config.json +13 -0
- package/templates/skills/exa-search/content.md +106 -0
- package/templates/skills/jira-interaction/config.json +13 -0
- package/templates/skills/jira-interaction/content.md +252 -0
- package/templates/skills/kapso-whatsapp/config.json +13 -0
- package/templates/skills/kapso-whatsapp/content.md +369 -0
- package/templates/skills/kv-storage/config.json +13 -0
- package/templates/skills/kv-storage/content.md +111 -0
- package/templates/skills/linear-interaction/config.json +20 -0
- package/templates/skills/linear-interaction/content.md +230 -0
- package/templates/skills/pages/config.json +18 -0
- package/templates/skills/pages/content.md +85 -0
- package/templates/skills/profile-corruption-escalation/config.json +13 -0
- package/templates/skills/profile-corruption-escalation/content.md +105 -0
- package/templates/skills/scheduled-task-resilience/config.json +13 -0
- package/templates/skills/scheduled-task-resilience/content.md +95 -0
- package/templates/skills/sprite-cli/config.json +13 -0
- package/templates/skills/sprite-cli/content.md +133 -0
- package/templates/skills/turso-interaction/config.json +13 -0
- package/templates/skills/turso-interaction/content.md +192 -0
- package/templates/skills/workflow-iterate/config.json +18 -0
- package/templates/skills/workflow-iterate/content.md +399 -0
- package/templates/skills/workflow-structured-output/config.json +13 -0
- package/templates/skills/workflow-structured-output/content.md +101 -0
- package/templates/skills/x-api-interactions/config.json +13 -0
- package/templates/skills/x-api-interactions/content.md +109 -0
- package/templates/workflows/autopilot/config.json +13 -0
- package/templates/workflows/autopilot/content.md +58 -0
- package/templates/workflows/linear-drain-loop/config.json +21 -0
- package/templates/workflows/linear-drain-loop/content.md +72 -0
- package/templates/workflows/ralph-loop/config.json +13 -0
- package/templates/workflows/ralph-loop/content.md +75 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# sprite-cli
|
|
2
|
+
|
|
3
|
+
`sprite` is a CLI for [sprites.dev](https://sprites.dev) — ephemeral Linux sandboxes backed by Fly.io firecracker microVMs. Use them when you need to run docker, docker-compose, postgres, redis, or anything else the host swarm container won't let you do.
|
|
4
|
+
|
|
5
|
+
## When to use this
|
|
6
|
+
|
|
7
|
+
- You need to test a `docker run …` or `docker compose up …` flow.
|
|
8
|
+
- You need a real postgres / redis / rabbitmq for an integration test.
|
|
9
|
+
- You want to try an `apt-get install` of something you don't want polluting the swarm container.
|
|
10
|
+
- You need to fetch + execute untrusted code (sandboxed network egress is OK; egress to swarm internals is not).
|
|
11
|
+
|
|
12
|
+
If you can do it directly in the swarm container (lint, type-check, unit test, code search), don't reach for sprite — it's slower and uses paid resources.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
The CLI is auto-installed at container start for agents whose setup script includes the install snippet (see "Setup script snippet" below).
|
|
17
|
+
|
|
18
|
+
Manual install:
|
|
19
|
+
```bash
|
|
20
|
+
curl -fsSL https://sprites.dev/install.sh | sh
|
|
21
|
+
export PATH="$HOME/.local/bin:$PATH" # CLI lands in ~/.local/bin
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Authentication
|
|
25
|
+
|
|
26
|
+
The org token is stored in swarm config as `SPRITES_API_KEY` (global, secret). Setup scripts read `$SPRITES_API_KEY` from the env.
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
sprite auth setup --token "$SPRITES_API_KEY"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Token format is `<org>/<account_id>/<token_id>/<secret>`. The first segment is the org (`desplega`).
|
|
33
|
+
|
|
34
|
+
## Core commands
|
|
35
|
+
|
|
36
|
+
| Command | What it does |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `sprite create <name>` | Create a sprite (~1s). |
|
|
39
|
+
| `sprite list` | List your sprites. |
|
|
40
|
+
| `sprite exec -s <name> -- <cmd>` | Run a command in the sprite. |
|
|
41
|
+
| `sprite exec -s <name> -- bash -c "…"` | Run a multi-statement shell snippet. |
|
|
42
|
+
| `sprite console -s <name>` | Open an interactive shell. |
|
|
43
|
+
| `sprite destroy <name> --force` | Tear down. **Always do this when done.** |
|
|
44
|
+
| `sprite proxy <port>` | Forward a remote sprite port to your local machine (rarely useful from within a swarm container; prefer curl from inside the sprite). |
|
|
45
|
+
|
|
46
|
+
Flags: every command takes `-s <sprite>` (or sets a default via `sprite use`). `-o <org>` overrides the org if you have multiple.
|
|
47
|
+
|
|
48
|
+
## Sandbox baseline (as of 2026-05-07)
|
|
49
|
+
|
|
50
|
+
- Ubuntu 25.10 (Questing Quokka), kernel 6.12.x-fly (firecracker microVM)
|
|
51
|
+
- Non-root `sprite` user (uid 1001), passwordless `sudo`
|
|
52
|
+
- No docker, no `/var/run/docker.sock`, no container runtime preinstalled
|
|
53
|
+
- No systemd / init — `service` and `systemctl` won't work; start daemons manually with `sudo <daemon> &` or `nohup`
|
|
54
|
+
- Kernel sysctls are mostly read-only (e.g. `vm.mmap_min_addr` writes fail — these warnings are harmless)
|
|
55
|
+
|
|
56
|
+
## Recipe: docker inside a sprite
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
sprite create dock
|
|
60
|
+
sprite exec -s dock -- bash -c '
|
|
61
|
+
set -e
|
|
62
|
+
sudo apt-get update -qq
|
|
63
|
+
sudo apt-get install -y docker.io docker-compose-v2
|
|
64
|
+
sudo dockerd > /tmp/dockerd.log 2>&1 &
|
|
65
|
+
# wait for daemon
|
|
66
|
+
for i in {1..15}; do sudo docker ps >/dev/null 2>&1 && break; sleep 1; done
|
|
67
|
+
sudo docker run --rm hello-world
|
|
68
|
+
'
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Notes:
|
|
72
|
+
- `invoke-rc.d` and `policy-rc.d denied` warnings during `apt-get install` are harmless — they come from missing systemd; the binaries install fine.
|
|
73
|
+
- The `sprite` user is **not** in the docker group by default, so prefix every docker call with `sudo`. (You can `sudo usermod -aG docker sprite` and start a new shell, but for one-off scripts `sudo` is simpler.)
|
|
74
|
+
- `dockerd` binds to `/var/run/docker.sock`. If you need it on a TCP port, pass `-H tcp://0.0.0.0:2375` (only inside the sprite — this is not exposed to the public internet).
|
|
75
|
+
|
|
76
|
+
## Recipe: docker compose
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
sprite exec -s dock -- bash -c '
|
|
80
|
+
cat > /tmp/compose.yml <<YAML
|
|
81
|
+
services:
|
|
82
|
+
pg:
|
|
83
|
+
image: postgres:16-alpine
|
|
84
|
+
environment:
|
|
85
|
+
POSTGRES_PASSWORD: dev
|
|
86
|
+
ports: ["5432:5432"]
|
|
87
|
+
YAML
|
|
88
|
+
sudo docker compose -f /tmp/compose.yml up -d
|
|
89
|
+
# wait for healthy
|
|
90
|
+
for i in {1..30}; do sudo docker exec $(sudo docker compose -f /tmp/compose.yml ps -q pg) pg_isready -U postgres >/dev/null 2>&1 && break; sleep 1; done
|
|
91
|
+
sudo docker exec $(sudo docker compose -f /tmp/compose.yml ps -q pg) psql -U postgres -c "select version();"
|
|
92
|
+
sudo docker compose -f /tmp/compose.yml down -v
|
|
93
|
+
'
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Use `docker compose` (v2 plugin) — `docker-compose` (legacy v1) is not installed.
|
|
97
|
+
|
|
98
|
+
## Cleanup discipline (mandatory)
|
|
99
|
+
|
|
100
|
+
Sprites are paid resources. **Always destroy them.** Pattern:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
sprite create test-$$
|
|
104
|
+
trap "sprite destroy test-$$ --force" EXIT INT TERM
|
|
105
|
+
# … work …
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
If a script crashes, `sprite list` shows what's still up. Sweep with `sprite list -o desplega` and destroy anything you don't recognize.
|
|
109
|
+
|
|
110
|
+
## Setup script snippet
|
|
111
|
+
|
|
112
|
+
Drop this into an agent's setup script to auto-install + auth on container boot:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Sprite CLI — sandboxes for docker/postgres/etc.
|
|
116
|
+
if [ ! -x "$HOME/.local/bin/sprite" ]; then
|
|
117
|
+
curl -fsSL https://sprites.dev/install.sh | sh -s -- 2>/dev/null || true
|
|
118
|
+
fi
|
|
119
|
+
if [ -n "$SPRITES_API_KEY" ] && [ -x "$HOME/.local/bin/sprite" ]; then
|
|
120
|
+
"$HOME/.local/bin/sprite" auth setup --token "$SPRITES_API_KEY" 2>/dev/null || true
|
|
121
|
+
fi
|
|
122
|
+
# Make sprite findable in non-login shells
|
|
123
|
+
grep -q '/.local/bin' "$HOME/.bashrc" 2>/dev/null || echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$HOME/.bashrc"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Common gotchas
|
|
127
|
+
|
|
128
|
+
- **PATH:** the installer drops the binary in `~/.local/bin`. Non-login bash shells often miss it. Always export PATH or use the absolute path.
|
|
129
|
+
- **No keyring:** the CLI warns "No system keyring available. Storing secrets unencrypted in ~/.sprites/keyring/". This is expected in a container; the file is mode 600 and only readable by the agent user.
|
|
130
|
+
- **Daemon survival:** `sprite exec` runs in a fresh subshell. A daemon backgrounded with `&` survives the exec call (sprites use a shared init), but if you want to be safe use `nohup`. To stop it, `sprite exec -s … -- sudo pkill <daemon>`.
|
|
131
|
+
- **Port forwarding:** ports inside the sprite are not exposed to your swarm container. Curl from *inside* the sprite (`sprite exec -s … -- curl localhost:5432`) — not from your container.
|
|
132
|
+
- **Don't leak secrets:** treat the sprite as an untrusted host. Don't put production tokens in there.
|
|
133
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "skill",
|
|
3
|
+
"name": "turso-interaction",
|
|
4
|
+
"displayName": "Turso / LibSQL Interaction",
|
|
5
|
+
"slug": "turso-interaction",
|
|
6
|
+
"title": "Turso / LibSQL Interaction",
|
|
7
|
+
"description": "Safely inspect and update LibSQL databases from agent workflows.",
|
|
8
|
+
"version": "1.0.0",
|
|
9
|
+
"category": "skills",
|
|
10
|
+
"placeholders": ["TURSO_DATABASE_URL"],
|
|
11
|
+
"runAllSeedersCandidate": false,
|
|
12
|
+
"tags": ["database", "libsql", "turso"]
|
|
13
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Turso Interaction
|
|
2
|
+
|
|
3
|
+
## The two-token model (READ THIS FIRST)
|
|
4
|
+
|
|
5
|
+
Turso has two separate auth planes — they do NOT cross over.
|
|
6
|
+
|
|
7
|
+
| Token type | Where it works | Stored in swarm config as | Signature | Expiry |
|
|
8
|
+
|---|---|---|---|---|
|
|
9
|
+
| **Platform JWT** (management plane) | `api.turso.tech/v1/*` — list orgs, list DBs, mint DB tokens, group/db CRUD; also what the `turso` CLI uses | `TURSO_API_TOKEN` | Clerk-issued RS256 | ~7 days — Clerk rotates it |
|
|
10
|
+
| **DB token** (data plane) | `https://<db-host>/v2/pipeline` — SELECT/INSERT/etc. against a specific DB | `TURSO_DB_TOKEN` (content-state), `TURSO_X_POSTS_DB_TOKEN` (x-posts), etc. | EdDSA | non-expiring (mint with `--expiration none`) or per-token TTL |
|
|
11
|
+
|
|
12
|
+
Using the **platform JWT against `/v2/pipeline` returns `HTTP 401 "invalid JWT token: can't be decoded with any of the existing keys"`** on every DB — that's by design, not a bug. If you see that error, you reached for the wrong token. Use the DB-specific one.
|
|
13
|
+
|
|
14
|
+
The platform JWT *can*, however, **mint** a DB token for any DB (see "Mint a DB token via API" below) — that's how you bootstrap access to a DB whose token isn't stored in config.
|
|
15
|
+
|
|
16
|
+
## Swarm config inventory (current)
|
|
17
|
+
|
|
18
|
+
Always fetch with `get-config includeSecrets=true`. As of 2026-05-12:
|
|
19
|
+
|
|
20
|
+
| Key | Plane | Scope | Notes |
|
|
21
|
+
|---|---|---|---|
|
|
22
|
+
| `TURSO_API_TOKEN` | Platform | global | Clerk JWT. Expires ~weekly. When expired, daily-blocker-digest surfaces it and Taras refreshes via Turso dashboard. |
|
|
23
|
+
| `TURSO_DB_TOKEN` | Data (content-state) | global | EdDSA, non-expiring. Used with `TURSO_DB_URL` for `/v2/pipeline`. |
|
|
24
|
+
| `TURSO_DB_URL` | Data (content-state) | global | `https://content-state-desplega.aws-eu-west-1.turso.io` (HTTPS form — required for HTTP API). |
|
|
25
|
+
| `TURSO_X_POSTS_DB_TOKEN` | Data (x-posts) | global | EdDSA, non-expiring. |
|
|
26
|
+
| `TURSO_X_POSTS_DB_URL` | Data (x-posts) | global | `libsql://x-posts-desplega.aws-eu-west-1.turso.io` — **swap `libsql://` → `https://` before hitting `/v2/pipeline`**. |
|
|
27
|
+
|
|
28
|
+
`dummy-test-db` has no stored DB token. Mint one via the API on demand (recipe below).
|
|
29
|
+
|
|
30
|
+
## Querying via HTTP API `/v2/pipeline` (the workflow path)
|
|
31
|
+
|
|
32
|
+
Workflow script nodes hit the DB over HTTP. This is the pattern to use anywhere outside the CLI.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
curl -s -X POST "$DB_URL/v2/pipeline" \
|
|
36
|
+
-H "Authorization: Bearer $DB_TOKEN" \
|
|
37
|
+
-H "Content-Type: application/json" \
|
|
38
|
+
-d '{
|
|
39
|
+
"requests": [
|
|
40
|
+
{"type":"execute","stmt":{"sql":"SELECT name FROM sqlite_master WHERE type='\''table'\''"}},
|
|
41
|
+
{"type":"close"}
|
|
42
|
+
]
|
|
43
|
+
}'
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Response shape (success):
|
|
47
|
+
```json
|
|
48
|
+
{"results":[{"type":"ok","response":{"type":"execute","result":{"cols":[{"name":"name","decltype":"TEXT"}],"rows":[[{"type":"text","value":"posts"}]]}}}, {"type":"ok","response":{"type":"close"}}]}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Always include `{"type":"close"}` as the last request. Use parameterized statements (`stmt.args`) for user-supplied values, not string-built SQL.
|
|
52
|
+
|
|
53
|
+
**URL form**: `/v2/pipeline` only accepts `https://`. If a config key holds the `libsql://` form, rewrite the scheme:
|
|
54
|
+
```bash
|
|
55
|
+
URL="${TURSO_X_POSTS_DB_URL/libsql:\/\//https:\/\/}"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Mint a DB token via the platform API
|
|
59
|
+
|
|
60
|
+
When a DB has no stored token (e.g., `dummy-test-db`), mint one with the platform JWT:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
DB=dummy-test-db
|
|
64
|
+
DB_TOKEN=$(curl -s -X POST \
|
|
65
|
+
"https://api.turso.tech/v1/organizations/desplega/databases/$DB/auth/tokens?authorization=read-only" \
|
|
66
|
+
-H "Authorization: Bearer $TURSO_API_TOKEN" | jq -r '.jwt')
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`authorization` can be `read-only` or `full-access`. Add `?expiration=1d` (or `7d`, `never`) to control TTL.
|
|
70
|
+
|
|
71
|
+
## CLI installation
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
curl -sSfL https://get.tur.so/install.sh | bash
|
|
75
|
+
export PATH="$HOME/.turso:$PATH"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The binary lives at `~/.turso/turso`. PATH must be exported in the same session.
|
|
79
|
+
|
|
80
|
+
## CLI authentication
|
|
81
|
+
|
|
82
|
+
The CLI uses the **platform JWT**, not a DB token:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
turso config set token "$TURSO_API_TOKEN"
|
|
86
|
+
turso org switch desplega
|
|
87
|
+
turso db list # verify
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Do NOT use `turso auth login` — it needs a browser. Always feed the config token in.
|
|
91
|
+
|
|
92
|
+
If `turso db list` returns 401, the platform JWT has expired — refresh `TURSO_API_TOKEN` in swarm config (Taras owns this; surface via blocker digest).
|
|
93
|
+
|
|
94
|
+
## CLI database operations
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
turso db create <name> # default group, aws-eu-west-1
|
|
98
|
+
turso db list
|
|
99
|
+
turso db show <name> # URL, region, size
|
|
100
|
+
turso db shell <name> # interactive
|
|
101
|
+
turso db shell <name> "SELECT * FROM t;" # one-shot
|
|
102
|
+
turso db shell <name> < dump.sql # pipe file
|
|
103
|
+
turso db destroy <name> # !!!
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## CLI DB-token generation
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
turso db tokens create <name> # default TTL
|
|
110
|
+
turso db tokens create <name> --expiration none # non-expiring (what we store in config)
|
|
111
|
+
turso db tokens create <name> --read-only # SELECT-only
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
After generating, write back to swarm config with `set-config` (mark `isSecret=true`).
|
|
115
|
+
|
|
116
|
+
## Seeding a Turso DB from local SQLite
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
sqlite3 local.db .dump > dump.sql
|
|
120
|
+
turso db create <name>
|
|
121
|
+
turso db shell <name> < dump.sql
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Connection-URL pattern
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
libsql://<db-name>-<org>.aws-eu-west-1.turso.io # for libsql:// clients
|
|
128
|
+
https://<db-name>-<org>.aws-eu-west-1.turso.io # for HTTP API /v2/pipeline
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Same host, two schemes. Some config keys store the libsql form, some the https form — normalize before use.
|
|
132
|
+
|
|
133
|
+
## Key databases (org = desplega)
|
|
134
|
+
|
|
135
|
+
| Database | HTTPS URL | Token config key | Used by |
|
|
136
|
+
|---|---|---|---|
|
|
137
|
+
| `content-state` | `https://content-state-desplega.aws-eu-west-1.turso.io` | `TURSO_DB_TOKEN` | Content workflows (`content_history`, `image_prompt_history`, `refresh_history`, `repo_patterns`, `workflow_executions`) |
|
|
138
|
+
| `x-posts` | `https://x-posts-desplega.aws-eu-west-1.turso.io` | `TURSO_X_POSTS_DB_TOKEN` | X/Twitter post tracking + meme cooldown (`posts` table) |
|
|
139
|
+
| `dummy-test-db` | `https://dummy-test-db-desplega.aws-eu-west-1.turso.io` | — (mint via API) | Test fixture (`users` table) |
|
|
140
|
+
|
|
141
|
+
## Groups
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
turso group list
|
|
145
|
+
turso group create <name> --location <location>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Default group: `default` in `aws-eu-west-1`.
|
|
149
|
+
|
|
150
|
+
## Local development
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
turso dev # starts a local LibSQL server
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Full bootstrap from scratch
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
curl -sSfL https://get.tur.so/install.sh | bash
|
|
160
|
+
export PATH="$HOME/.turso:$PATH"
|
|
161
|
+
# Fetch TURSO_API_TOKEN via get-config includeSecrets=true
|
|
162
|
+
turso config set token "$TURSO_API_TOKEN"
|
|
163
|
+
turso org switch desplega
|
|
164
|
+
turso db list
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Health-check recipe (verify all 3 DBs in <30s)
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# Platform plane
|
|
171
|
+
curl -s -H "Authorization: Bearer $TURSO_API_TOKEN" \
|
|
172
|
+
https://api.turso.tech/v1/organizations/desplega/databases | jq '[.databases[].Name]'
|
|
173
|
+
|
|
174
|
+
# Data plane — one /v2/pipeline call per DB
|
|
175
|
+
for pair in "$TURSO_DB_URL|$TURSO_DB_TOKEN" "https://x-posts-desplega.aws-eu-west-1.turso.io|$TURSO_X_POSTS_DB_TOKEN"; do
|
|
176
|
+
url="${pair%|*}"; tok="${pair#*|}"
|
|
177
|
+
curl -s -X POST "$url/v2/pipeline" -H "Authorization: Bearer $tok" \
|
|
178
|
+
-H "Content-Type: application/json" \
|
|
179
|
+
-d '{"requests":[{"type":"execute","stmt":{"sql":"SELECT 1"}},{"type":"close"}]}' \
|
|
180
|
+
| jq -c '.results[0]'
|
|
181
|
+
done
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
If either plane returns 401, treat as a blocker — surface in HEARTBEAT.md, do not retry silently.
|
|
185
|
+
|
|
186
|
+
## When tokens expire / get rotated
|
|
187
|
+
|
|
188
|
+
- **`TURSO_API_TOKEN` expired** → CLI breaks, can't mint new DB tokens, `api.turso.tech` returns 401. Existing DB tokens keep working (data plane is independent). Action: Taras rotates via Turso dashboard, updates config.
|
|
189
|
+
- **A DB token expired/revoked** → that specific DB returns 401 on `/v2/pipeline`. Other DBs unaffected. Action: mint a new one (CLI or platform API), update the corresponding config key.
|
|
190
|
+
|
|
191
|
+
Don't conflate the two failure modes. The blocker-digest writer should name the exact key that needs rotation.
|
|
192
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "skill",
|
|
3
|
+
"name": "workflow-iterate",
|
|
4
|
+
"displayName": "Workflow Iteration",
|
|
5
|
+
"slug": "workflow-iterate",
|
|
6
|
+
"title": "Workflow Iteration",
|
|
7
|
+
"description": "A procedure for improving workflows through small tested revisions.",
|
|
8
|
+
"version": "1.0.0",
|
|
9
|
+
"category": "skills",
|
|
10
|
+
"placeholders": [],
|
|
11
|
+
"runAllSeedersCandidate": true,
|
|
12
|
+
"tags": [
|
|
13
|
+
"workflows",
|
|
14
|
+
"authoring",
|
|
15
|
+
"qa"
|
|
16
|
+
],
|
|
17
|
+
"must": true
|
|
18
|
+
}
|