426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
160 lines
9.8 KiB
Markdown
160 lines
9.8 KiB
Markdown
# @elizaos/plugin-cloud-apps
|
|
|
|
Lets an Eliza agent **manage the user's Eliza Cloud Apps from any connector**
|
|
(in-app chat, Discord, Telegram, cloud-hosted) through the shared AgentRuntime
|
|
pipeline. One plugin registration exposes the whole app lifecycle — list,
|
|
create, deploy (with a live-verification gate), monetize, take/withdraw
|
|
earnings, rotate keys, buy + manage custom domains, and the growth surfaces
|
|
(frontend hosting, ad slots, influencer bookings) — as planner actions plus a
|
|
context provider.
|
|
|
|
It is a **client of `@elizaos/cloud-sdk`** (`ElizaCloudClient`), not of the
|
|
cloud backend directly. Read the root `AGENTS.md` for repo-wide rules; this doc
|
|
is specific to the plugin.
|
|
|
|
## Auth
|
|
|
|
Reads `ELIZAOS_CLOUD_API_KEY` (+ optional `ELIZAOS_CLOUD_BASE_URL`, defaults to
|
|
`https://www.elizacloud.ai/api/v1`) via `runtime.getSetting` — the same
|
|
credentials `plugin-elizacloud` uses. With no key, `validate` returns false,
|
|
every action degrades gracefully with a "no key" message, and the provider
|
|
stays empty. Construction lives in `src/client.ts` (`getCloudClient`).
|
|
|
|
## Layout
|
|
|
|
```
|
|
src/
|
|
index.ts Plugin registration: the actions[] array + CLOUD_APPS provider.
|
|
client.ts getCloudClient (SDK construction), resolveCloudApiKey/BaseUrl/SiteBaseUrl,
|
|
reference resolution (generic matchByReference + matchAppByReference/
|
|
resolveApp — id → exact name/slug → whole-word-in-sentence → fragment;
|
|
ties = ambiguous; BOOK_INFLUENCER reuses it for profiles),
|
|
and the app formatters (formatAppLine/formatAppDetail).
|
|
safety.ts Two-phase confirm state machine for destructive/paid actions:
|
|
readStructuredConfirmation (planner boolean, NEVER prose parsing),
|
|
persist/find/deleteCloudAppConfirmation (task-backed, room-scoped),
|
|
CONFIRM_TTL_MS + pendingExpired (shared 15-min pending TTL; expired
|
|
pendings refuse the bare confirm and are re-stated/re-quoted),
|
|
conflictingConfirmTarget/Amount/Domain (frozen-target guard: a confirm
|
|
whose own params name a different target/amount refuses + clears the
|
|
pending instead of executing the frozen snapshot),
|
|
confirmationPrompt, buildConnectorCta (label+https URL only — never a
|
|
secret/amount). CloudAppConfirmationAction is the gated-action union.
|
|
deploy-gate.ts runDeployGate: poll deploy status → READY, then reachability-probe the
|
|
authoritative production_url before claiming live (pure + injectable).
|
|
reachability.ts probeReachable + respondedLive (2xx / non-gateway-down = live).
|
|
app-facts.ts record/removeAppDeployFact — durable "app is live at <url>" memory fact.
|
|
domain-facts.ts record/remove/hasInterruptedDomainPurchase — durable marker for a 502
|
|
persist_failed_recoverable buy so the free recovery stays reachable.
|
|
domain-intent.ts Pure domain helpers: extractDomainReferences (boundary-guarded),
|
|
resolveDomainTargetApp (sole-app default), cloudErrorInfo (duck-typed
|
|
CloudApiError), usdFromCents, formatDomainLine.
|
|
providers/cloud-apps.ts CLOUD_APPS provider (app inventory into planner context) + a 60s
|
|
WeakMap cache with invalidateAppsCache(runtime).
|
|
actions/ One file per action (see below).
|
|
__tests__/ bun test suites (helpers.ts fakes ONLY the SDK boundary).
|
|
test/scenarios/ cloud-apps-structured-confirm.scenario.ts — real SDK over a loopback
|
|
cloud, proving the two-phase confirm on the pr-deterministic lane.
|
|
```
|
|
|
|
## Actions
|
|
|
|
**Read-core**
|
|
- `LIST_CLOUD_APPS` — list the user's apps (name / url / status).
|
|
- `GET_APP` — details for one app by name or id.
|
|
- Provider `CLOUD_APPS` — injects the app inventory into planner context.
|
|
|
|
**Create → deploy → live loop + safe delete**
|
|
- `CREATE_APP` — create from name/description/monetization intent.
|
|
- `DEPLOY_APP` — deploy + COMPLETION GATE (READY, then `/health` 2xx on the
|
|
authoritative `production_url`) before claiming live; records a deploy fact.
|
|
- `GET_APP_DEPLOY_STATUS` — DRAFT/BUILDING/DEPLOYING/READY/ERROR + url.
|
|
- `DELETE_APP` — DESTRUCTIVE: two-phase connector-agnostic confirm; honest
|
|
partial-failure reporting; invalidates cache + removes the deploy fact.
|
|
|
|
**Manage (edit / monetize / earnings / money-out / key rotation)**
|
|
- `UPDATE_APP` — rename / edit description, logo, website, email.
|
|
- `UPDATE_MONETIZATION` — enable/disable + markup % / purchase share %; range-guarded.
|
|
- `GET_APP_EARNINGS` — READ-ONLY: withdrawable / pending / lifetime / withdrawn.
|
|
- `WITHDRAW_APP_EARNINGS` — MONEY-OUT: two-phase confirm + dashboard CTA; the
|
|
safe, idempotent, server-gated request endpoint fires on confirm.
|
|
- `REGENERATE_APP_API_KEY` — SECURITY: two-phase confirm; new key shown ONCE, never logged.
|
|
|
|
**Domains (check → buy → list)**
|
|
- `CHECK_APP_DOMAIN` — READ-ONLY availability + purchase/renewal price quote.
|
|
- `BUY_APP_DOMAIN` — MONEY-OUT: read-only quote first, two-phase confirm with a
|
|
15-min quote TTL + confirm-time price re-check; maps the server's idempotent
|
|
replay / refund-on-registrar-failure / no-charge-recovery outcomes to honest
|
|
replies; interrupted purchases are tracked in `domain-facts.ts`.
|
|
- `LIST_APP_DOMAINS` — READ-ONLY: registrar/status/SSL/verification per domain
|
|
(with the exact `_eliza-cloud-verify` TXT record for unverified external domains).
|
|
|
|
**Growth surfaces**
|
|
- `DEPLOY_FRONTEND` / `ROLLBACK_FRONTEND` / `LIST_FRONTEND_DEPLOYMENTS` — managed
|
|
frontend hosting (publish/rollback app frontends on Cloud).
|
|
- `CREATE_AD_SLOT` / `LIST_AD_SLOTS` — SSP ad inventory for monetized apps.
|
|
- `CREATE_INFLUENCER_PROFILE` / `LIST_INFLUENCERS` / `BOOK_INFLUENCER` — influencer
|
|
marketing marketplace.
|
|
- `BACKUP_APP` — export an app's config snapshot.
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
bun run --cwd plugins/plugin-cloud-apps test # bun test __tests__ (SDK boundary faked)
|
|
bun run --cwd plugins/plugin-cloud-apps typecheck # tsgo --noEmit
|
|
bun run --cwd plugins/plugin-cloud-apps lint # biome check --write
|
|
bun run --cwd plugins/plugin-cloud-apps build # bun build.ts
|
|
```
|
|
|
|
## Conventions / gotchas
|
|
|
|
- **Every money/destructive action uses the `safety.ts` two-phase confirm.** The
|
|
first ask NEVER mutates — it runs read-only pre-checks and returns a
|
|
confirmation prompt naming the exact target (+ amount/domain/price), storing a
|
|
room-scoped pending task. The mutation fires only when a later turn carries the
|
|
planner's structured `confirm: true` for that pending task, using the params
|
|
FROZEN at the first ask — never re-parsed from the follow-up text, never from
|
|
English keyword matching (so non-English confirmations work).
|
|
- **A confirm that names a DIFFERENT target/amount refuses (frozen-target
|
|
guard).** When the confirm turn's own structured params clearly name another
|
|
target than the frozen snapshot ("yes — delete Beta Dashboard" while the
|
|
pending delete is for Acme Bot; a different domain, influencer, or a
|
|
different structured amount), the gated action refuses, clears the pending,
|
|
and asks the user to re-state — it never executes the frozen target the user
|
|
is no longer talking about, and never silently switches to the new one.
|
|
Helpers: `conflictingConfirmTarget` / `conflictingConfirmAmount` /
|
|
`conflictingConfirmDomain` (safety.ts). Deliberately lenient: bare confirms,
|
|
partial names of the SAME target, and generic filler ("my app") never block,
|
|
and prose is never parsed.
|
|
- **Secrets/money never transit the connector.** CTAs (`buildConnectorCta`) carry
|
|
a label + an https URL only. Created/rotated API keys are surfaced once and
|
|
never logged.
|
|
- **Cache invalidation is an invariant.** Any action that mutates app inventory
|
|
or deploy/monetization state calls `invalidateAppsCache(runtime)`; server-side
|
|
writes that change `apps` rows must evict `appsService` caches too (the app row
|
|
is cached ~5 min via `getById`; a missed eviction was a real payment-gate
|
|
staleness bug — #11213).
|
|
- **`validate` is only the API-key check.** All real validation lives in the
|
|
handler; every exit calls `callback` AND returns an `ActionResult` with
|
|
`userFacingText` (and `verifiedUserFacing: true` on truthful outcomes).
|
|
- **Deploy "done" ≠ 202-accepted.** It is READY status + a live reachability
|
|
probe of the authoritative `production_url` (`deploy-gate.ts`).
|
|
- **Tests fake ONLY the SDK.** `__tests__/helpers.ts` provides `FakeElizaCloudClient`
|
|
+ keyed/unkeyed/memory runtimes; the actions/formatters/confirm-machine run for
|
|
real. Adding an SDK method means adding its `*Fn`/state/setter/fake method.
|
|
- **Live e2e:** the app lifecycle + charges + attribution run against real staging
|
|
in `packages/cloud/api/test/e2e/group-i/l/n`; see that dir's live-staging runbook.
|
|
|
|
## ⛔ NON-NEGOTIABLE — evidence, trajectories & real end-to-end tests
|
|
|
|
The binding, repo-wide standard is **[AGENTS.md](../../AGENTS.md)** — read
|
|
it. Nothing here is *done* until a reviewer can confirm it works **without reading
|
|
the code**, from the artifacts you attach: real-LLM trajectories for
|
|
action/prompt changes (`packages/scenario-runner/bin/eliza-scenarios run …`
|
|
against a **live** model, read by hand), the real request→response traces + the
|
|
domain artifacts the change produced (app rows, deploy status, credit/earnings
|
|
ledger rows, domain records), and — for anything user-exercisable — before/after
|
|
UI proof. "Tests pass" and "CI green" are not proof. No TODOs, stubs, or
|
|
"follow-ups"; clear blockers by the hard path. Artifacts →
|
|
attached inline in the PR (MP4 video, JPG screenshots, logs in `<details>`), or mark a row `N/A - <reason>`.
|