Skip to content

v0.7.14

@steve8708 steve8708 tagged this 29 Apr 01:37
* feat(core): db-migrate-user-api-keys script

One-shot migration that copies legacy `user-api-key:<provider>:<email>`
and `user-anthropic-api-key:<email>` settings rows into `app_secrets`
(encrypted, scope=user, scopeId=email) and deletes the originals.

Pairs with the secrets-write-path lockdown on PR #343:
`getOwnerApiKey()` reads `app_secrets` first and falls back to the
legacy settings rows for compat. This script clears that compat tail
so the rows don't sit around indefinitely after deploy.

Idempotent — re-running on a clean DB is a no-op. Supports Postgres
(Neon) and SQLite/libsql. Includes --dry-run.

Usage:
  DATABASE_URL=postgres://... pnpm action db-migrate-user-api-keys
  pnpm action db-migrate-user-api-keys --dry-run

* feat(a2a): cross-platform async+poll for slow handlers; sweep concurrent doc/core updates

The deployed dispatch was getting 'fetch failed' when delegating Slack
analytics questions to other agents, because:

  1. Analytics's reply easily exceeded Netlify's 30s gateway timeout for
     a single sync POST.
  2. The existing async branch in handleSend used a detached promise +
     keepAlive() that the Lambda runtime kills the moment the response
     is flushed, so the handler never finished and pollers timed out.

Replaces the detached-promise path with the same self-fire pattern the
integration webhook queue uses:

  - handleSend (async mode) bakes the verified caller email/org-domain
    into the task's metadata column, then fire-and-forgets a signed POST
    to /_agent-native/a2a/_process-task on the same deployment and
    returns immediately in 'working' state.
  - mountA2A() now also mounts /_agent-native/a2a/_process-task. The
    route validates the HMAC token (5-min lifetime, A2A_SECRET-keyed,
    same scheme as the webhook queue), atomically claims the task via
    claimA2ATaskForProcessing(), reconstructs the request context from
    metadata, and runs the handler with the fresh function's full
    timeout budget.
  - callAgent() defaults to async: true so cross-app calls get the
    safe behavior out of the box; explicit sync callers can still pass
    async: false.

Also picks up concurrent agent updates to docs, package.json,
framework-request-handler, terminal-plugin, and the workspace file.
Assets 2
Loading