Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

9.8 KiB

@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

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 — 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>.