Shaw/pr 2067 eliza fix#7175
Conversation
agent/api/index.ts
- Re-export `matchPluginRoutePath` and `tryHandleRuntimePluginRoute`
from `./runtime-plugin-routes.js`. Plugin authors and their tests
(apps/app-vincent/src/vincent-plugin-dispatch.test.ts is the most
visible) reach for the matcher via `@elizaos/agent` — without the
re-export the tests fail with `TypeError: matchPluginRoutePath is
not a function`.
steward-sidecar.ts + steward-sidecar/process-management.ts +
steward-sidecar/wallet-setup.ts
- Replace `await import("node:fs|node:path|node:child_process")`
with static namespace imports (`import * as fs from "node:fs"`).
These files only run inside the bun process — they manage the
Steward API child process and were never meant to load in the
renderer. The dynamic loading wasn't preventing browser bundling
(other steward modules already use static node:*) and was the
source of the Vite "dynamically imported but also statically
imported" warnings for `node:fs`, `node:path`, and
`node:child_process` in the renderer build.
Net build: 0 warnings (was 11+ across circular-chunk, empty-chunk,
and dynamic↔static collision categories).
Rollup warning: `widgets/index.ts` re-exports `WidgetHost` from `widgets/WidgetHost.tsx`, but the WidgetHost module also pulls other widgets/* code that depends back through the barrel. When two consumers end up in different chunks (e.g. the lazy AutomationsView chunk vs the main shell), the cycle blocks proper splitting: Export "WidgetHost" of module ".../widgets/WidgetHost.tsx" was reexported through module ".../widgets/index.ts" while both modules are dependencies of each other and will end up in different chunks by current Rollup settings. This scenario is not well supported at the moment as it will produce a circular dependency between chunks and will likely lead to broken execution order. Fix: switch the four non-widget callers (AutomationsView, HeartbeatsView, CharacterHubView, TasksEventsPanel) from barrel imports to a direct sub-path import of `widgets/WidgetHost`. The barrel itself stays for non-cyclic exports (resolveWidgetsForSlot, declarations registry, etc.). Build: still 0 warnings.
…ycle-and-greenup # Conflicts: # packages/app-core/src/components/pages/AppDetailsView.tsx # packages/app-core/src/components/pages/AppsView.tsx
@elizaos/plugin-todo@2.0.0-alpha.14 (resolved via the 'alpha' dist-tag in packages/autonomous/package.json) declares a hard pin to @elizaos/plugin-rolodex@2.0.0-alpha.114 — but rolodex was never published past alpha.10. As a result, every `bun install` against develop fails with: No version matching '2.0.0-alpha.114' found for specifier '@elizaos/plugin-rolodex' (but package exists) This was masked because ci.yaml (the workflow that actually runs `bun install` and tests) hasn't run on develop in months — the `Code Quality: Push on develop` workflow that does run does not install dependencies. Add an override to force the plugin-rolodex transitive resolution to its highest published version (2.0.0-alpha.10), restoring `bun install` on develop. Real fix is to coordinate sibling-package release versioning so plugin-todo and plugin-rolodex stay in sync.
rimraf v6 drops Node <18 support and reorganizes ESM entry points; v5 introduced new glob handling. The breaking changes are largely about Node version requirements — we're already on Node 24 (this stack also includes a Node 22/23 -> 24 bump), so v6 is safe. lerna@9.0.3 declares rimraf@^4.4.1, but uses rimraf only via its top- level callback API, which is stable across v4-v6. A smoke test of `bunx lerna --version` succeeds with the override applied. Closes the rimraf -> v6 row of #79.
Snapshot of the in-flight work before pulling origin/develop. Covers: - electrobun-webview tab kit (cursor overlay, realistic events, wallet shims) - LAUNCHPAD_LAUNCH action + four.meme/flap.sh profile engine - Solana tx signing through wallet-browser-compat-routes - cloud balance string|number coercion across three readers - dev-ui.mjs API supervisor restart-on-clean-exit Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…up' into feat/widget-host-cycle-and-greenup
flap.sh launches tokens via Portal.newTokenV6(NewTokenV6Params) on BNB Chain (mainnet chain 56, testnet chain 97). Per https://docs.flap.sh/flap/developers/token-launcher-developers — the website UI wraps that contract call; the resulting eth_sendTransaction flows through our existing browser-wallet bridge and steward approval path. No Solana plumbing was needed. Renames flap-sh:devnet -> flap-sh:testnet across the action / tests / profile, and adds Portal contract addresses + docs reference to the profile header so future selector tuning has the on-chain context. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… health, hot reload New `packages/agent/src/runtime/operations/` module: - `manager.ts` — RuntimeOperationManager, the single-flight gate for provider switches, restarts, and reloads. Replaces the ad-hoc `providerSwitchInProgress` boolean. - `repository.ts` — operation-state store, surfaces pending/active/done. - `classifier.ts` + `classifier.test.ts` — decides whether an inbound request is a duplicate of an in-flight op via the idempotency key. - `health.ts` + `health.test.ts` + `health-checks.ts` — runtime health predicates used by the reload/cold strategies. - `cold-strategy.ts`, `reload-hot.ts` — strategy implementations for full restart vs hot reload. - `index.ts` + `types.ts` — module barrel and shared types. Wires the manager through: - `api/provider-switch-routes.ts` — reads Idempotency-Key header, routes through the manager rather than the legacy boolean gate. - `api/server.ts`, `runtime/restart.ts` — refactored against the new manager; the old single-flight scaffolding is gone. - `app-core/scripts/dev-platform.mjs`, `app-core/src/api/client-base.ts`, `client-types-core.ts`, `cli/run-main.ts`, `runtime/error-handlers.ts`, `shared/scripts/generate-keywords.mjs` — companion changes the manager required (dev-platform integration, error surfacing, client-side typing for the new op-status responses). WIP — preserving in a commit so it doesn't sit as uncommitted state on the feature branch. Squash / split as needed in the PR.
Introduces @elizaos/confidant — the single seam at which credentials can be observed inside an Eliza agent. Skills never read process.env for credentials; they request from a per-skill ScopedConfidant that goes through policy + audit. Confidant stores values literally (AES-256-GCM at rest with secret id bound as AAD) or as references into external password managers. Phase 0 closes seven concrete failure modes in the existing credential pipeline (skill exfiltration via process.env, dual-writer bug between provider-switch-config and plugins-compat-routes, the Object.values(config).find(non-empty) heuristic that lets a model slug overwrite an API key, etc.). The runtime does not yet call into Confidant — that is phase 1. This commit ships the contract. Public API - createConfidant, ScopedConfidant - defineSecretSchema(...) — single source of truth for "this id is a secret" decisions; replaces the catalog-as-authoritative pattern - parseReference / buildReference — URI scheme dispatch (op://, pass://, keyring://, file://, env://, cloud://) - AES-256-GCM envelope helpers (encrypt/decrypt with AAD binding) - Identifier validation + glob-pattern matching with most-specific selection Backends - KeyringBackend — cross-platform via @napi-rs/keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service / libsecret). Prebuilt binaries for darwin/win/linux/freebsd. - EnvLegacyBackend — read-only env://VAR migration scaffolding, removed in phase 6. - 1Password / Proton Pass / Cloud are deferred to phase 4+. Storage - ~/.milady/confidant.json mode 0600, atomic-rename writes. - Master key sourced from OS keychain by default; pluggable via inMemoryMasterKey (tests + headless deployments). - The secret id is bound as AAD so a swapped ciphertext fails closed. Policy - Deny-by-default. - Implicit grant: the plugin that registered a secret id via defineSecretSchema gets always-access to that id. - Explicit grants persisted per-skill with glob patterns. Most- specific-wins; deny is absolute. - prompt mode requires a PromptHandler; without one, prompt-mode grants resolve to deny. Audit log - ~/.milady/audit/confidant.jsonl, append-only JSONL. - Records ids, never values. Explicit test verifies the secret value never appears in the log even after a successful resolve. Tests - 70 vitest cases across envelope, identifiers, references, store, policy, end-to-end Confidant flows, and a real cross-platform keyring round-trip. The keyring round-trip skips cleanly on hosts without a usable Secret Service agent.
Adds a dedicated workflow that runs the package's vitest suite on ubuntu / macos / windows. The package's headline claim is that the OS-keyring credential mediation layer works the same on all three platforms; this workflow makes that claim verifiable in every PR that touches packages/confidant/**. Notes - Confidant installs standalone (`cd packages/confidant && bun install`) rather than going through the root workspace install. This keeps the CI run independent of which submodules are initialized in the checkout, and finishes in seconds rather than minutes. - On Linux, libsecret + gnome-keyring + dbus are installed and a session DBus + unlocked secret-service daemon are started so the real keyring round-trip tests run. Without those, the tests are designed to skip cleanly via a module-import-time probe — fail-open on hosts without a usable Secret Service. - The workflow is path-filtered to packages/confidant/** + the workflow file itself, so unrelated changes don't trigger it. - Both `develop` and `main` are listed as branches so the workflow runs for the standard elizaOS PR target.
Adds six end-to-end integration tests that prove Confidant's contract is sufficient to close the failure modes documented in §2 of the design doc, without requiring runtime wiring. Each test names a specific bug from the existing elizaOS credential pipeline and demonstrates that the bug is structurally impossible against the new architecture. Tests added (test/integration.test.ts) - bug #3 model-slug-overwrites-API-key: schema-driven save makes the legacy `Object.values(config).find(non-empty)` heuristic structurally unnecessary; reproducing the user's actual incident produces correct persistence regardless of input order. - bug #1 skill exfiltration: non-owning skills cannot resolve another plugin's credentials. Implicit owner grant is exact-id, not pattern-spanning. - bug #6 no-reveal: saved values can be round-tripped programmatically via `resolveDetailed`, foundation for a Settings "Reveal" button. - schema-driven save: arbitrary input ordering produces correct persistence (input map iteration order doesn't affect outcome). - storage opacity: the same id can be a literal one moment and a reference the next; consumer call signature is unchanged. - audit trail: granted + denied resolves are both recorded; the secret value never appears in the log. Test count: 70 → 76. All passing on macOS; cross-platform CI matrix (added in the previous commit) runs the full suite on Linux / Windows once a maintainer approves the workflow run. CHANGELOG.md added per elizaOS package conventions.
…cy env bridge Adds two integration modules so an elizaOS host app can adopt Confidant in two lines of bootstrap rather than 14 individual schema declarations. Both are pure data-shape, non-invasive to existing runtime code: - `registerElizaProviderSchemas()` — registers the canonical schema for every AI provider in the elizaOS catalog (anthropic, openai, openrouter, google, groq, xai, deepseek, mistral, together, zai, elizacloud, ollama) plus the two subscription credential types (anthropic-subscription, openai-codex). Each entry carries the human label, format-prefix hint (sk-or-v1-..., sk-ant-..., sk-...), sensitivity flag, and ownership attribution to the matching plugin id (so the implicit-grant rule fires automatically once those plugins migrate to Confidant reads). - `mirrorLegacyEnvCredentials(confidant, credentials)` — bulk-registers `env://VAR_NAME` references in Confidant given a list of resolved credentials in the shape `@elizaos/app-core`'s `credential-resolver` already produces. Returns a structured report of migrated vs. skipped entries (unknown-provider / missing-env-var), so callers can log adoption progress at boot. Also exports `isSubscriptionProviderId(providerId)` (used by the future CloudBackend to refuse syncing device-bound tokens) and `providerIdForSecretId(id)` (inverse lookup for telemetry). Why not in `@elizaos/agent` or `@elizaos/typescript` - The bridge is data-shape-only — `ResolvedCredentialLike` mirrors the existing `credential-resolver` shape but the import is structural, not a runtime dependency. This avoids forcing `@elizaos/confidant` into a dependency cycle with the runtime packages and keeps the Confidant package consumable by any host app, not just the elizaOS reference runtime. Tests added (test/integrations.test.ts) - Coverage of the canonical map, the schema registration, the bridge migration paths (success / unknown / missing-env), the subscription flag, and the inverse lookup. - An end-to-end "real-world bootstrap" test that wires schema + bridge + scoped resolve through env-legacy and verifies the audit log records the granted resolve correctly with `source: env-legacy`. Test count: 76 → 86. All passing.
Adds MIGRATION.md showing step-by-step how an existing Eliza host app adopts Confidant without breaking the running app at any point. Mirrors the 7-phase plan from §9 of the architecture design doc but operationalized for someone reading this package's docs: Phase 1 — initialize Confidant at app boot (mirror legacy env) Phase 2 — single canonical writer (Settings saves through confidant.set) Phase 3 — built-in AI providers migrate to Confidant reads Phase 4 — password manager backends (1Password, Proton Pass) Phase 5 — third-party plugins migrate Phase 6 — close the boundary (process.env.*_API_KEY undefined) Phase 7 (optional) — E2E-encrypted Cloud sync Each phase has steps, an exit criterion, and a one-liner test the migrator can run to verify they actually completed it. Also documents migration anti-patterns (reading process.env after phase 6, `*` grants, caching resolved values) and a "When something breaks" section pointing at the audit log.
… catalog
Following review feedback that the LLM-only `ELIZA_PROVIDER_SECRET_IDS`
map didn't reflect Confidant's full scope, replaced it with a
comprehensive `ELIZA_ENV_TO_SECRET_ID` keyed by env-var name and
covering every secret field across the 31 plugins in the elizaOS
catalog.
Domains added (and their canonical SecretId namespaces):
- llm.* — anthropic, openai, openrouter, google, groq, xai,
deepseek, mistral, together, zai, vercelAiGateway
(formerly already supported, kept)
- subscription.* — anthropic, openai (device-bound OAuth tokens)
- tts.* — elevenlabs
- connector.* — github, linear, twilio, roblox, x (X/Twitter — NOT
to be confused with xai the LLM provider)
- tool.* — n8n, capsolver, browserbase
- storage.* — s3 (AWS access key id + secret access key)
- wallet.* — default (chain-agnostic), evm, solana, hedera,
polymarket — every entry flagged device-bound
- rpc.* — alchemy, infura, ankr, helius, birdeye, jupiter,
moralis, coingecko, dexscreener, zeroex
- trading.* — polymarket (CLOB credential triplet)
- music.* — lastfm, genius, theaudiodb, spotify
- service.* — elizacloud, acp, blooio, moltbook
API surface
- `ELIZA_ENV_TO_SECRET_ID` — env-var-name → SecretId (primary key,
matches credential-resolver's `envVar` field).
- `ELIZA_PROVIDER_TO_SECRET_ID` — provider-id → SecretId (legacy index
for callers working in the catalog's providerId space).
- `mirrorLegacyEnvCredentials` — bulk env-reference registration,
works across every domain. Returns structured `MirrorResult` with
per-credential `unknown-env-var` / `missing-env-var` skip reasons.
- `isSubscriptionProviderId` — flags Anthropic/Codex subscriptions.
- `isDeviceBoundSecretId` (NEW) — flags subscription tokens AND wallet
private-key material; future CloudBackend (phase 7) refuses to sync
any id flagged here.
- `providerIdForSecretId` / `envVarForSecretId` (NEW) — inverse
lookups for telemetry / migration tooling.
Schema generator (`registerElizaSecretSchemas`) now produces
human-readable labels across every domain (with Eliza-aware acronym
casing: S3, EVM, RPC, ACP, OpenAI, OpenRouter, GitHub, ElevenLabs,
DeepSeek, Z.AI, Last.fm, TheAudioDB, DEXScreener, 0x, etc.) and
plugin-id ownership for every catalog credential.
Backwards-compatibility
- `registerElizaProviderSchemas` is kept as a deprecated alias for
`registerElizaSecretSchemas`. Existing callers continue to work.
Tests
- Reworked test/integrations.test.ts to spot-check across all 11
domains. Asserts every catalog env-var appears in the map, every
provider-id has a SecretId, label and ownership generation work
across LLM / connector / wallet / storage / TTS / RPC.
- New end-to-end test exercises a multi-domain credential set
(LLM + connector + wallet) through the bridge with cross-plugin
permission denial enforced.
- Test count: 86 → 91. All passing.
MIGRATION.md updated with multi-domain examples (LLM, connector,
wallet, RPC, storage) and a TL;DR that names the full catalog scope
up front instead of focusing on the original OpenRouter incident.
…into develop # Conflicts: # bun.lock # package.json
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
Relates to
Risks
Background
What does this PR do?
What kind of change is this?
Documentation changes needed?
Testing
Where should a reviewer start?
Detailed testing steps