The statedb binary is a generic SQL-over-HTTP proxy. Schema creation is
the Python client's responsibility (HttpWorkflowStore), not the database
layer's. The existing migration machinery in the agents server already
handles this.
Phase 1 of the statedb plan. A new Go binary at cmd/statedb that exposes
a SQLite database over HTTP with transaction support (forked from ws4sqlite),
Bearer token auth, backup/restore endpoints, and embedded Litestream for
continuous WAL replication to S3.
Components:
- Transaction handler: POST /db with batched statements/queries, noFail mode,
mutex-serialized access, panic/recover for atomic rollback
- Migrations: embedded SQL files applied at startup, version-tracked
- Backup: GET /db/backup (VACUUM INTO, optional gzip compression)
- Restore: POST /db/restore (validates SQLite magic, swaps DB file, re-migrates)
- Litestream: S3 replication with 1s sync interval, restore-on-startup via
EnsureExists, graceful shutdown with final WAL sync
- Auth: Bearer token middleware, healthz exempt
- --no-s3 flag for local dev without S3
28 passing tests covering transactions, auth, migrations, backup/restore,
and parameter parsing.
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and publish to npm
yourself or [setup this action to publish
automatically](https://github.com/changesets/action#with-publishing). If
you're not ready to do a release yet, that's fine, whenever you add more
changesets to main, this PR will be updated.
# Releases
## llama-agents-dbos@0.3.0
### Minor Changes
- 56701a9: Add `max_recovery_attempts` to `DBOSRuntimeConfig`. When set,
it is forwarded to the `@DBOS.workflow` decorator wrapping the runtime's
control loop.
## llamactl@0.9.1
### Patch Changes
- 0b2098b: Fix `deployments update` crashing with `Event loop is closed`
after a transient failure on the internal git push. The command now runs
`get_deployment` and `update_deployment` in a single event loop instead
of reusing the same `ProjectClient` across two `asyncio.run` calls.
Co-authored-by: llama-org-ci-bot[bot] <231146559+llama-org-ci-bot[bot]@users.noreply.github.com>
## Summary
- Adds `max_recovery_attempts` to `DBOSRuntimeConfig`. When set, it is
forwarded to the `@DBOS.workflow` decorator wrapping the runtime's
control loop, capping how many times a workflow will be replayed after a
crash before being marked `MAX_RECOVERY_ATTEMPTS_EXCEEDED`.
- Only forwarded when explicitly set, so DBOS's own default (currently
100) keeps applying for unset configs.
- Motivated by OOM crash-loops: a workflow that exhausts pod memory gets
re-recovered on the new pod, OOMs again, and burns through ~100
recoveries before DBOS gives up. A user-tunable cap turns that into a
bounded failure.
`deployments history` joins the column framework: supports
-o text|json|yaml|wide and --project <id>, sorts newest-first, formats
timestamps as Z-suffixed UTC, and shows 7-char short SHAs in text mode
(JSON keeps the full 40-char). The rich-table rendering is gone —
ReleaseDisplay carries the column annotations and render_output picks
the format.
`deployments rollback --git-sha <TAB>` now completes from the
deployment's release history (via GitShaType.shell_complete reading
deployment_id + project from the click ctx), and the questionary
fallback uses short_sha so the picker matches the new --git-sha
display.
Drop the inline _render_text closures from auth list, auth env list,
and auth organizations; route everything through render_output via
AuthProfileDisplay, EnvDisplay, OrgDisplay. The Rich-styled tables
become plain-whitespace; -o json | yaml | wide all work.
auth list no longer leaks the api_key or OIDC tokens — auth_type
reports token / oidc / none. auth organizations gains -o for the
first time; the empty case stays an empty list ([]) instead of a Rich
"no orgs" placeholder. EnvDisplay intentionally omits
min_llamactl_version (not part of the public env-list contract).
No user-visible CLI behavior change. Lays the foundation for
DeploymentDisplay, ReleaseDisplay, AuthProfileDisplay, EnvDisplay,
OrgDisplay (which land with their respective commands) and for the
-o text|json|yaml|wide dispatch on read commands.
- cli/display.py: Column / ResolvedColumn / resolve_columns / render_columns,
the walker primitives that drive auto-derived tables.
- cli/render.py: render_table, gh_short, short_sha, format_iso_z, star_marker.
- cli/log_format.py: parse_log_body, trim_timestamp, render_plain. Lifted out
of textual/deployment_monitor.py so a non-Textual `deployments logs` can
share the structlog parser.
- cli/options.py: output_option, project_option, render_output. The
render_output helper dispatches between framework-derived tables, JSON, and
YAML; ``yaml`` is imported lazily to keep CLI startup cheap.
- cli/client.py: get_project_client / project_client_context now accept
project_id_override (for --project).
- cli/param_types.py: DeploymentType.shell_complete and
GitShaType.shell_complete read `project` off the click ctx so completion
hits the right project.
- cli/textual/deployment_monitor.py: refactored to consume parse_log_body /
trim_timestamp; capped the in-memory log buffer; cached container colors.
Default stays follow=true so existing streaming consumers (e.g. the TUI)
keep working. With follow=false the server returns currently-available
logs and ends the SSE stream — useful for "fetch and exit" callers that
don't want to reconnect across ReplicaSet changes.
Threads the flag through manage_client.stream_deployment_logs,
DeploymentService.stream_deployment_logs, and the underlying k8s_client
helpers (stream_replicaset_logs, stream_build_job_logs,
_stream_pod_container_logs, stream_container_logs). When follow=false,
read_namespaced_pod_log returns synchronously and 400/404 maps to an
empty generator rather than a wait-and-retry. Also hoists
_on_push_complete to module scope and tightens _get_deployment_or_raise
to skip the events fetch on a not-found / wrong-project deployment.
The skill plans and runs design QA against a real backend. The dev-cli
command symlinks .agents/skills/<name> into .claude/skills/<name> so the
checked-in copy is what Claude Code sees.
Canonical field on DeploymentCreate, DeploymentResponse, and DeploymentUpdate
is now appserver_version. The old name remains as a deprecated input alias
(via model_validator) and a serialized-output computed_field, so old clients
and old servers continue to interoperate.
Adds a `crds.version` values key auto-synced from the `llama-agents-crds`
workspace package at release time, and surfaces it in the generated README
plus install/upgrade snippets.
* chart: add optional s3proxy sidecar for the control plane
Gated on `s3proxy.enabled`. When on, the control plane pod gains an
s3proxy container plus an emptyDir volume, and `S3_ENDPOINT_URL` /
`S3_UNSIGNED` default to localhost / `true`. Explicit user values
still win.
Credentials go in `s3proxy.config` (raw passthrough to JCLOUDS_* env
vars). Examples for Azure Blob and GCS in docs/s3-proxy-setup.md.
* chart: trim s3proxy docs, drop MinIO mention from unsigned comment
* chart: align control plane S3 and s3proxy credentials on BYO-or-inline shape
Sidecar: add `s3proxy.secret` for BYO. Chart Secret renders only when `config`
is set and `secret` is not. Sidecar envFroms `secret` over `config`.
Control plane: add inline `controlPlane.objectStorage.s3.{accessKey,secretKey}`
rendering `llama-agents-controlplane-s3`, plus `s3.secret` for BYO. The legacy
`controlPlane.objectStorage.secretRef` keeps working as a silent alias.
Precedence: `s3.secret` > `secretRef` > inline. Partial inline errors out.
* chart: fold s3-proxy-setup.md into README
* chart: trim changeset
* chart: bump s3proxy to 3.1.0 and tighten sidecar resources