{
  "interval": {
    "intervalStart": "2026-05-01T00:00:00.000Z",
    "intervalEnd": "2026-05-02T00:00:00.000Z",
    "intervalType": "day"
  },
  "repository": "elizaos/eliza",
  "overview": "From 2026-05-01 to 2026-05-02, elizaos/eliza had 9 new PRs (17 merged), 1 new issues, and 5 active contributors.",
  "topIssues": [
    {
      "id": "I_kwDOMT5cIs8AAAABA4Rdow",
      "title": "build: dev-ui.mjs references `./claude-code-stealth.mjs` preload that doesn't exist on fresh clone",
      "author": "Sw4pIO",
      "number": 7210,
      "repository": "elizaos/eliza",
      "body": "## Summary\n\n`packages/app-core/scripts/dev-ui.mjs` declares `./claude-code-stealth.mjs` as a Bun `--preload` entry when the user has an Anthropic subscription, but **no build step generates that file** and **it isn't checked in**. The script's existence check (`existsSync(path.join(cwd, filePath))`) silently filters the missing file out of the preload list, so the stealth fetch interceptor never installs.\n\nThe interceptor is what prepends the Claude Code system prefix and identity headers (`anthropic-beta`, `user-agent: claude-cli/...`, `x-app: cli`) that Anthropic's API requires for OAuth subscription tokens. Without it, every `api.anthropic.com` request from a subscription user gets `401 Invalid authentication credentials` even though the token is valid and registered correctly.\n\nThe TypeScript source is at `packages/agent/src/auth/claude-code-stealth.ts` and exports `installClaudeCodeStealthFetchInterceptor()`, but the dev preload expects a different file at the **repo root**, named `.mjs`, that auto-runs on import.\n\n## Reproduction\n\nOn a fresh clone of any consumer repo (e.g. milady on `develop`):\n\n1. Sign in to an Anthropic subscription via `POST /api/subscription/anthropic/start` + `/exchange` so `~/.eliza/auth/anthropic-subscription.json` is written.\n2. Manually enable `@elizaos/plugin-anthropic` in `~/.<branding>/<branding>.json` (auto-enable refuses for subscription-only).\n3. Set `ANTHROPIC_AUTH_MODE=oauth` and `CLAUDE_CODE_OAUTH_TOKEN=<token>` in the runtime env.\n4. `bun run dev`\n5. Boot log shows:\n   ```\n   [milady] Stealth imports enabled: \n   ```\n   (notice — empty list because the file doesn't exist; it was silently filtered)\n6. Send any chat message → backend retries 3× with `AI_APICallError: Invalid authentication credentials` and surfaces the parse error to the user.\n\n## Diagnostic trail\n\n- `packages/app-core/scripts/dev-ui.mjs:785` declares the preload:\n  ```js\n  if (stealth.claude) nodeStealthImports.push(\"./claude-code-stealth.mjs\");\n  ```\n- Then filters by existence:\n  ```js\n  const resolvedStealthImports = nodeStealthImports.filter((filePath) =>\n    existsSync(path.join(cwd, filePath)),\n  );\n  ```\n- `find . -name claude-code-stealth.mjs -not -path '*/node_modules/*'` returns nothing on a fresh clone.\n- The TS source exists at `packages/agent/src/auth/claude-code-stealth.ts` and exports `installClaudeCodeStealthFetchInterceptor()`. Nothing builds it into the expected location.\n\n## Suggested fix\n\nEither of:\n\n1. **Check in / generate the `.mjs`** at the repo root (or wherever `cwd` resolves to in `dev-ui.mjs`), with a self-installing call at the bottom. I verified locally that creating this file unblocks the Anthropic subscription auth path end-to-end (successful chat turns, zero 401s, model calls confirmed via `[stealth] →anthropic` debug logs with `ELIZA_STEALTH_DEBUG=1`).\n\n2. **Fail loud instead of silent**: in `dev-ui.mjs`, when `stealth.claude === true` but the resolved preload file is missing, log a clear warning so users know what's wrong instead of chasing parse errors.\n\nBoth would help; (1) makes the feature work out of the box, (2) prevents the same multi-hour debug hunt for the next person.\n\n## Why this matters\n\nWithout the stealth interceptor, subscription auth is **completely non-functional** on the runtime side, which:\n- Makes the `/api/subscription/anthropic/*` flow look broken (it works correctly, but the runtime that consumes its credentials can't actually use them).\n- Forces users to either get a paid API key or sign up for Eliza Cloud — even though the codebase clearly intends to support direct subscription OAuth via the stealth path.\n\n## Environment\n- bun 1.3.13\n- eliza submodule HEAD: `4e650ca0ad`\n- Discovered while booting milady on `develop`",
      "createdAt": "2026-04-29T22:09:53Z",
      "closedAt": "2026-05-01T20:04:54Z",
      "state": "CLOSED",
      "commentCount": 1
    },
    {
      "id": "I_kwDOMT5cIs8AAAABBDbGSw",
      "title": "plugin-sql runtime-migrator missing drizzle pgTable defs for entity_identities, entity_merge_candidates, fact_candidates",
      "author": "Sw4pIO",
      "number": 7222,
      "repository": "elizaos/eliza",
      "body": "## Summary\n\nThe abstract schema declarations at `packages/typescript/src/schemas/entity-identity.ts` declare three tables (`entity_identities`, `entity_merge_candidates`, `fact_candidates`) which are:\n\n- Exported through the schemas barrel (`packages/typescript/src/schemas/index.ts`)\n- Actively queried by `packages/typescript/src/services/relationships.ts` and the `RELATIONSHIP_EXTRACTION` evaluator\n- Referenced by the `RECENT_MESSAGES` provider and `longTermMemoryProvider`\n\nBut the corresponding **drizzle `pgTable` definitions in `plugins/plugin-sql/typescript/schema/` were never added**. The runtime-migrator (`plugins/plugin-sql/typescript/runtime-migrator/`) only emits `CREATE TABLE` from drizzle pgTables — it does not consume the abstract `SchemaTable` definitions — so on every fresh PGLite boot, these three tables silently never get created.\n\n## Symptoms\n\nOn every chat turn the runtime emits 5+ errors per message:\n\n```\nError #agent:Chen [AGENT] Provider failed during state composition (provider=RECENT_MESSAGES,\n  error=Failed query: SELECT entity_id, platform, handle\n                     FROM entity_identities\n                     WHERE agent_id = '<uuid>' AND entity_id IN ('<uuid>')\n  params: )\n\nError [PROVIDER:MEMORY] Error in longTermMemoryProvider (err=Failed query: SELECT entity_id, platform, handle FROM entity_identities ...)\n\nError [EVALUATOR:MEMORY] Error during long-term memory extraction (err=Failed query: ...)\n```\n\nThe agent still appears to respond, but the prompt is composed from a half-empty state (no recent messages, no entity facts, no long-term memory), so:\n\n- The model receives essentially an empty user message\n- It replies \"I don't see a specific user message — could you provide...\"\n- The structured-output parser fails to find required XML tags\n- 3× retries, all empty\n- Surfaces to the user as: `I hit an internal parsing error while preparing the reply. Reason: No structured output could be parsed from the model response.`\n\nThis makes chat **completely unusable** on a fresh PGLite database.\n\n## Reproduction\n\n1. Fresh clone of any consumer (e.g. milady on `develop` or `alice` post-PR#105)\n2. `bun install && bun run dev`\n3. Complete onboarding, send any chat message\n4. Boot log: `[PLUGIN:SQL] Executing SQL statements (pluginName=@elizaos/plugin-sql, statementCount=83)`\n5. Subsequent chat turns: continuous `Failed query: SELECT entity_id, platform, handle FROM entity_identities ...` errors\n\n## Diagnostic trail\n\n- Schema declared: `packages/typescript/src/schemas/entity-identity.ts:13` (`entityIdentitySchema`), `:134` (`entityMergeCandidateSchema`), `:243` (`factCandidateSchema`)\n- Schema exported: `packages/typescript/src/schemas/index.ts:28-31, :61-65`\n- Service consuming: `packages/typescript/src/services/relationships.ts:347` (and many more), with `entity_identities` referenced 30+ times in that file alone\n- Drizzle schema directory listing (`plugins/plugin-sql/typescript/schema/`): contains 25 schema files for agent, cache, channel, channelParticipant, component, embedding, entity, log, longTermMemories, memory, memoryAccessLogs, message, messageServer, messageServerAgent, pairingAllowlist, pairingRequest, participant, relationship, room, server, sessionSummaries, tasks, world. **Three tables missing: `entityIdentity`, `entityMergeCandidate`, `factCandidate`.**\n\n## Fix\n\nAdd `plugins/plugin-sql/typescript/schema/entityIdentity.ts` mirroring all three abstract schemas as drizzle `pgTable` definitions, including:\n\n- All columns with their types/defaults/notNull constraints (matches `entity-identity.ts` column-for-column)\n- All indexes (`idx_entity_identities_entity`, `idx_entity_identities_platform_handle`, `idx_entity_merge_candidates_status`, `idx_entity_merge_candidates_pair`, `idx_fact_candidates_status`, `idx_fact_candidates_entity`)\n- All foreign keys to `entities` and `agents` with `onDelete: \"cascade\"` (6 FKs total)\n- Unique constraint `unique_entity_identity` on `(entity_id, platform, handle, agent_id)` for `entity_identities`\n\nThen export from `schema/index.ts`.\n\nI verified the fix locally: statement count goes from **83 → 99** on next migration (3 tables + 6 indexes + 6 FKs + 1 unique = 16 new statements). Zero `entity_identities` query failures during chat after the fix. State composition succeeds, `RELATIONSHIP_EXTRACTION` evaluator completes without errors.\n\nI have a working diff — happy to PR.\n\n## Why this slipped through\n\nThe abstract `SchemaTable` shape and drizzle `pgTable` definitions are two parallel schema sources of truth that drifted apart. The migration generator only reads drizzle, so adding a new abstract schema produces no warning at build time, no runtime check at boot, and no error until application code actually queries the missing table — which can be far later in the user journey (after onboarding, on first chat).\n\nWorth considering: a sanity check at plugin-sql init that verifies every name in the abstract schemas barrel has a corresponding drizzle pgTable in the runtime-migrator's schema set, and warns/errors loudly otherwise. Would have caught this immediately.\n\n## Environment\n\n- `bun 1.3.13`\n- `node ≥ 22`\n- PGLite (via `@elizaos/plugin-sql` runtime-migrator)\n- Discovered booting milady on alice (eliza submodule pinned at `05c636c004bf8c59e1b698ae755bdddfc7431ed5`)",
      "createdAt": "2026-05-01T17:09:58Z",
      "closedAt": "2026-05-01T20:04:44Z",
      "state": "CLOSED",
      "commentCount": 1
    },
    {
      "id": "I_kwDOMT5cIs8AAAABA8f7-w",
      "title": "Add SwarmScore — Portable Trust Rating for AI Agents",
      "author": "bkauto3",
      "number": 7213,
      "repository": "elizaos/eliza",
      "body": "## SwarmScore — Portable Reputation for AI Agents\n\nHi! I'm reaching out because this repo looks like an autonomous agent or agent framework that could benefit from SwarmScore.\n\n**What is SwarmScore?**\nSwarmScore is a portable trust rating built from verified execution history — volume, success rate, and consistency. It's cryptographically signed so it can travel with your agent across marketplaces and registries without restarting from zero.\n\nThe score is *not* self-reported. It's built downstream of real verified outcomes: `80 jobs at 95% beats 1 job at 100%`.\n\n---\n\n**For AI agents — ingest SwarmScore in one call:**\n\n```\nGET https://api.swarmsync.ai/v1/swarmscore/load-by-slug/{your-slug}\n```\n\nReturns: public passport, signed certificate, verify payload, and discovery URLs.\n\nTo confirm freshness of any score:\n```\nGET https://api.swarmsync.ai/v1/swarmscore/verify\n```\n\n**Discovery manifest** (machine-readable, for agent-to-agent lookup):\n```\nhttps://api.swarmsync.ai/.well-known/agent-card.json\n```\n\n---\n\n**For platform builders — add trust to your agent listings:**\n\n```\nPOST https://api.swarmsync.ai/v1/swarmscore/keys/enable\n```\n(Requires authenticated SwarmSync platform account — provisions the integration key pack.)\n\n**4-step quickstart:**\n1. Display the returned SwarmScore tier and value in your agent listing UI\n2. Persist the signed certificate for offline or delayed re-verification\n3. Replay the verify payload against `/v1/swarmscore/verify` to confirm freshness\n4. Use the machine-readable agent card to advertise SwarmScore support to other agents and registries\n\n---\n\n**Add the badge to your README:**\n\n```markdown\n[![SwarmScore](https://img.shields.io/badge/SwarmScore-Get%20Verified-blue)](https://swarmsync.ai/enable-swarmscore)\n```\n\n---\n\n**SDKs:**\n- `npm install @swarmsync/mcp-server` — MCP server\n- `npm install @swarmsync/langchain-tools` — LangChain\n- `npm install @swarmsync/crewai-tools` — CrewAI\n- Composio (91 tools): https://docs.composio.dev/tools/swarmsyncai\n- MCP Registry: https://mcpservers.org/servers/api-swarmsync-ai-mcp\n\n**Spec & docs:** https://swarmsync.ai/docs/protocol-specs/swarmscore\n**GitHub spec:** https://github.com/swarmsync-ai/swarmscore-spec\n\n---\n*SwarmSync.AI — infrastructure for AI agent commerce. AP2 escrow + SwarmScore trust + SkillProof verification.*\n*https://swarmsync.ai*\n",
      "createdAt": "2026-04-30T13:17:49Z",
      "closedAt": "2026-05-01T03:53:45Z",
      "state": "CLOSED",
      "commentCount": 0
    },
    {
      "id": "I_kwDOMT5cIs8AAAABA40oEA",
      "title": "Hive Civilization — character-callable x402 services for Eliza (notification)",
      "author": "srotzin",
      "number": 7211,
      "repository": "elizaos/eliza",
      "body": "Notification post — Hive Civilization runs 52 x402-wired services on Base mainnet (treasury 0x15184bf50b3d3f52b60434f8942b7d52f2eb436e, USDC settlement, x402 spec from coinbase/x402).\n\nWhy it's relevant to elizaOS:\n\n- Eliza characters can call Hive evaluator, classifier, summarizer, kycOracle, riskScorer, and 47 other services as paid actions with on-chain USDC settlement.\n- Each character can have its own Base wallet and operate autonomously with per-call payment.\n- Discovery is free.\n\nTwo open PRs adopting the same pattern on neighboring SDKs:\n- coinbase/agentkit#1157 — HiveActionProvider\n- goat-sdk/goat#575 — @goat-sdk/plugin-hive\n\nHappy to PR an `eliza-plugin-hive` package following Eliza plugin conventions, or any shape the team prefers. Partner posture.\n\n41 public MCP shims at github.com/srotzin (all v1.0.0). 51 entries on Anthropic MCP Registry. MEV leaderboard: https://hive-a2amev.onrender.com/leaderboard. Spectral receipt: rcpt_76fceca973da4ec0.\n\nSteve Rotzin, Hive\ngithub.com/srotzin",
      "createdAt": "2026-04-30T00:39:14Z",
      "closedAt": "2026-05-01T03:53:53Z",
      "state": "CLOSED",
      "commentCount": 0
    }
  ],
  "topPRs": [
    {
      "id": "PR_kwDOMT5cIs7WsOJC",
      "title": "feat(vault): @elizaos/vault — cross-platform secrets vault + Settings UI integration",
      "author": "Dexploarer",
      "number": 7197,
      "body": "# Relates to\n\nThis is the upstream-targeting twin of milady-ai/eliza#6. The vault feature originated in the Milady fork; this PR lands the upstream-relevant slice on `elizaOS/eliza:develop`.\n\n# Risks\n\n**Low.** The vault is an additive workspace package; the runtime + Settings UI integration is a write-through mirror over the existing `config.env.X` storage path, so disabling it is a one-line change in `plugins-compat-routes.ts` (`mirrorPluginSensitiveToVault` → no-op). Cross-platform secret-service behaviour is exercised by a new dedicated CI workflow (macOS Keychain / Windows Credential Manager / Linux libsecret) so the headline portability claim is verifiable on every PR. The legacy `config.env.X` write path is unchanged — even if every vault call failed, plugin saves would still persist.\n\n# Background\n\n## What does this PR do?\n\nAdds **`@elizaos/vault`** — a cross-platform secrets/config vault — and wires it into the agent runtime + Settings UI so the existing \"save my OpenAI key\" flow stops storing plaintext in `config.env` and starts encrypting at rest with a key from the OS keychain.\n\n### `@elizaos/vault` (new package, `packages/vault/`)\n\n- **Encryption-at-rest** with AES-256-GCM, secret-id-as-AAD (so a leaked ciphertext can't be replayed against a different key).\n- **Master key in the OS keychain by default** — macOS Keychain, Windows Credential Manager, Linux Secret Service via `@napi-rs/keyring`.\n- **Headless fallback**: `passphraseMasterKey()` / `passphraseMasterKeyFromEnv(\"MILADY_VAULT_PASSPHRASE\")` derives the master key with `scrypt` for Linux servers and CI without a Secret Service agent.\n- `defaultMasterKey()` chains keychain → passphrase → throws `MasterKeyUnavailableError` whose message names every remediation path.\n- **One API for sensitive and non-sensitive config** — `vault.set(key, value, { sensitive: true })` vs `vault.set(key, value)`.\n- **Password-manager references are first-class** — values can live in 1Password / Proton Pass / Bitwarden, the vault stores only the resolver reference.\n- **`SecretsManager`** layer routes per-key writes/reads to the user-selected backend (`in-house`, `1password`, `bitwarden`, `protonpass`), with detection + preferences API at `/api/secrets/manager/{backends,preferences}`.\n- **Audit log** at `audit/vault.jsonl` per write.\n- **Testing harness** (`@elizaos/vault/testing#createTestVault`) that produces a vault wired to an in-memory master key for downstream tests.\n\n### Runtime + Settings UI integration\n\n- **Write-through mirror in `/api/plugins/:id` PUT**: when a sensitive plugin field is saved, the value is mirrored into the vault (encrypted at rest) on top of the existing `config.env.X` write. Mirror failures are surfaced to the UI under `vaultMirrorFailures` rather than silently swallowed.\n- **Vault-first reveal**: `POST /api/plugins/:id/reveal` consults `sharedVault().get(key)` before falling back to `process.env` / `config.env`, so a freshly-saved key is the value the user sees.\n- **Per-process cached `sharedVault()`** so concurrent saves share `VaultImpl.mutate()`'s mutex; a per-request `createVault()` would race and silently lose entries.\n- **Broader credential heuristic** — `pickPrimaryCredentialParam()` walks a priority-ordered regex list (`API_KEY` → `API_TOKEN` → `BOT_TOKEN` → `ACCESS_TOKEN` → `SECRET_KEY` → `PRIVATE_KEY` → `CLIENT_SECRET`) instead of only matching `*_API_KEY$`, with an explicit fallback to the first sensitive parameter. Closes the bug where typing a model field before the API-key field caused `Object.values(config).find()` to pick up the model slug; also fixes connectors whose primary credential is a bot token / private key / client secret.\n- **Settings UI** — `SecretsManagerSection` + `ApiKeyConfig` with inline prefix validation and validation warnings, keyboard shortcut `⌘⌥⌃V` (Mac) / `Ctrl+Alt+Shift+V` (Win/Linux), global modal mount, application menu accelerator.\n- **Cloud disconnect orphan-route patch**: `/api/cloud/disconnect` now nulls every routed service (`llmText`, `tts`, `media`, `embeddings`, `rpc`) instead of just `llmText`, so disconnect doesn't leave silently-401'ing voice/image/embedding features routed at the dead `cloud-proxy → elizacloud`. Plus `linkedAccounts.elizacloud.status=\"unlinked\"` to prevent the in-memory state from overwriting the canonical unlinked state on next `saveElizaConfig`.\n\n### Runtime-ops × vault\n\n- `ProviderSwitchIntent.apiKeyRef` replaces plaintext `apiKey` end-to-end. The provider-switch route writes the vault entry, persists only the reference, and resolves through the vault when the runtime reload-hot needs the key.\n- Legacy ops with plaintext `apiKey` are auto-migrated to `apiKeyRef` on hydrate.\n- Repository pruning suite (retention, cap, idempotency, hydrate; 6 tests).\n- A `simplify` pass that dedupes utility code, removes ghost phases, and consolidates state.\n\n## What kind of change is this?\n\n**Features** — non-breaking. `@elizaos/vault` is new. The runtime/Settings wiring is additive on top of the existing config-write path, controlled by feature presence rather than a flag. The provider-switch `apiKeyRef` replaces `apiKey` but a hydrate-time migration upgrades legacy ops in place.\n\n# Documentation changes needed?\n\nMy changes do not require a change to the project documentation. New package documentation lives inline in `packages/vault/README.md` and the public API surface is documented via TSDoc. The Settings UI changes are user-facing but match the existing settings pattern.\n\n# Testing\n\n## Where should a reviewer start?\n\n1. **`packages/vault/`** — start with `src/vault.ts` (the public API), then `src/master-key.ts` (the keychain/passphrase chain), then `src/manager.ts` (the multi-backend router). Tests in `test/{vault,master-key,manager,store,envelope,references,keyring}.test.ts` exercise every public path; `test/master-key.test.ts` covers the headless-fallback chain explicitly.\n2. **`packages/app-core/src/services/vault-mirror.ts`** + `packages/app-core/src/services/vault-mirror.test.ts` — the write-through mirror is small, isolated, and has a focused test that includes failure-collection and a source-text guard for the vault-first reveal ordering.\n3. **`packages/app-core/src/api/plugins-compat-routes.ts`** — the `PUT /api/plugins/:id` handler and `/reveal` route, where the vault wiring sits next to the existing legacy code path.\n4. **`packages/agent/src/runtime/operations/`** — `vault-bridge.ts`, `vault-integration.test.ts`, and `health.test.ts` show the `apiKeyRef` migration. The 22-case integration suite is the strongest evidence that the runtime path keeps working.\n\n## Detailed testing steps\n\nAutomated tests are acceptable.\n\n- **Vault unit suite (cross-platform)**: `bun run --cwd packages/vault test` — 64 tests covering vault, master-key (incl. passphrase fallback), manager, store, envelope, references, keyring round-trips. The new `vault-ci` workflow runs this matrix on `ubuntu-latest`, `macos-latest`, `windows-latest` so the OS-keychain claim is checked on every PR.\n- **App-core wiring suite**: `bun run --cwd packages/app-core test` — 37 wiring tests (vault-mirror unit + source-text guards, secrets-manager-routes integration via real `http.Server`, usePluginsSkillsState heuristic priority list, useSecretsManagerShortcut Mac/Win/Linux chord matching, server.cloud-disconnect orphan-route guard).\n- **Runtime-ops vault integration**: 22 cases in `packages/agent/src/runtime/operations/vault-integration.test.ts` proving the `apiKeyRef` path works end-to-end.\n- **End-to-end save-flow**: `provider-switch-routes.e2e.test.ts` stands up a real `http.Server` and exercises Settings PUT → mirror → reveal → provider switch against an in-memory vault.\n- **Cross-platform CI**: the new `vault-ci` workflow (`.github/workflows/vault-ci.yaml`) runs the vault suite on macOS / Linux / Windows runners; an `app-core-wiring` job runs the wiring tests on `ubuntu-latest` with proto generation as a prerequisite.\n\n### Manual smoke (UI)\n\n1. Open the desktop app → **Settings → Plugins → OpenAI** (or any AI provider).\n2. Enter an API key, save.\n3. The plugin row should turn green and reload the agent. Open `~/.milady/vault.json` — the value is encrypted; the OS keychain holds the master key under `service: \"milady\"`, `account: \"vault.masterKey\"`.\n4. Open the **Secrets Vault** modal via `⌘⌥⌃V` (or **Edit → Secrets Vault** menu). Switch the routing for `OPENAI_API_KEY` to a different backend, save. Subsequent reveals fetch from the new backend.\n\n## Deploy notes\n\n- **`@elizaos/vault` is a new workspace package** — `bun install` at the repo root picks it up; nothing extra to do.\n- **No database changes.**\n- **No breaking changes** to existing config files. Legacy `config.env.X` writes still happen alongside the vault mirror; vault values shadow `process.env` only in the reveal path. The `apiKeyRef` migration on the runtime-ops side is in-place on hydrate (no operator action required).\n\n---\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n",
      "repository": "elizaos/eliza",
      "createdAt": "2026-04-29T11:25:51Z",
      "mergedAt": "2026-05-01T03:12:42Z",
      "additions": 22472,
      "deletions": 677
    },
    {
      "id": "PR_kwDOMT5cIs7XE9HC",
      "title": "feat(self-hosted): CORS + bearer auth + cross-platform build fixes",
      "author": "NubsCarson",
      "number": 7212,
      "body": "# Relates to\n\nSelf-hosting cross-platform connectivity. The runtime now serves browser dashboards over HTTPS at a custom domain, App Store-style mobile builds (Capacitor), and Electrobun desktop builds — all routed through a remote agent via the existing `RuntimeGate` \"Remote\" picker.\n\n# Risks\n\n**Medium.** Touches CORS allowlist, `/api/auth/me` response shape, the Electrobun build pipeline, and runtime branding defaults. Verified on Linux (VPS), Windows 11 desktop (Electrobun), and Android (Capacitor on a physical Samsung phone). All test files for the new behavior land in this PR.\n\n# Background\n\n## What does this PR do?\n\n**Self-hosted browser + mobile auth**\n\n- `server-cors.ts`: new `ELIZA_ALLOWED_ORIGINS` env adds operator-allowed hosts (e.g. `https://bot.example.com`) to the CORS allowlist; built-in Capacitor / Ionic WebView origins (`capacitor://localhost`, `ionic://localhost`, `https://localhost`) so App Store / Play Store mobile builds reach any self-hosted bot without per-operator config; `originString()` helper compares protocol+host (URL.origin returns \"null\" for non-special schemes like `capacitor:`)\n- `auth-session-routes.ts`: `/api/auth/me` accepts legacy bearer; returns synthetic `kind: \"machine\"` identity when no owner is configured (was incorrectly `kind: \"owner\"` in earlier draft)\n- `auth-pairing-compat-routes.ts`: `/api/auth/status` adds explicit `authenticated` field so clients can short-circuit pairing without overloading `required`\n- `csrf-client.ts`: `fetchWithCsrf` now layers cookie+CSRF + bearer-from-`getBootConfig()` in one place; old per-call bearer wiring removed\n- `client-base.ts`: `setToken()` mirrors to `__ELIZAOS_API_TOKEN__` / `__ELIZA_API_TOKEN__` window globals so the Capacitor `@elizaos/capacitor-agent` web fallback authenticates after RuntimeGate remote-connect; parallels existing `setBaseUrl()` mirror\n- `client-agent.ts`: `getAuthStatus()` typed `authenticated?: boolean`\n- `startup-phase-poll/restore/runtime.ts`: a transient 401 with a token set is treated as retry, not as a token-wipe-and-show-pairing event. Removes desktop/non-desktop branch since the new behavior is correct on both\n- `App.tsx`, `ChatView.tsx`, `state/persistence.ts`: 6 raw `/api/*` fetch sites converted to `fetchWithCsrf` so they pick up the bearer on self-hosted browsers and Capacitor builds\n- `RuntimeGate.tsx`: `onInput` + `onBlur` handlers on Remote-connect inputs (Capacitor WebView's `onChange` is unreliable on programmatic paste); `splash-bg.jpg` → `splash-bg.png` (wrong extension was 404); removed placeholder onboarding hero images (text-only cards until artwork exists)\n- mobile: safe-area inset padding on root container\n\n**Build infra**\n\n- `package.json` workspaces: added `packages/app-core/platforms/*` so `desktop-build.mjs`'s nested `bun install` resolves `@elizaos/shared@workspace:*` (was failing on Windows because bun's upward walk stopped at `eliza/package.json`)\n- `desktop-build.mjs`: `embedWindowsIcons()` post-build using local rcedit (electrobun@1.16.0's bundled rcedit references a `D:\\` CI path that doesn't exist on dev machines); cross-platform rcedit lookup via `fs.existsSync` instead of Unix `find`\n- `electrobun.config.ts`: removed duplicate null-coalesce on `ELIZA_APP_NAME`; copies `brand-config.json` into the build output\n- `brand-config.json`: ships **elizaOS defaults** (`appName: \"elizaOS\"`, `appId: \"ai.elizaos.app\"`, etc.); downstream wrappers override at build time via `ELIZA_APP_NAME` / `ELIZA_APP_ID` / `ELIZA_NAMESPACE` env vars, which `brand-config.ts`'s resolver checks before the JSON fallback\n- `variables.gradle` template: added `mavenCentralMirrorUrl` (16 native plugin `build.gradle` files referenced this; template never defined it, so `cap sync` regenerated a broken file every run)\n\n**Cross-package imports for packaged builds**\n\n- `plugin-lifecycle.ts`: import `resolveActionContexts` / `resolveProviderContexts` from `@elizaos/core` instead of cross-package relative TS paths (broke when tsdown tree-shook them out of the dist)\n- `experience-routes.ts`: inlined `ExperienceType` / `OutcomeType` enums (same tree-shaking issue)\n- `registry/index.ts`: graceful warn-and-continue when `entries/` directories are missing in packaged builds\n\n## What kind of change is this?\n\nBug fixes (CORS preflight blocking Capacitor, broken Windows desktop build, packaged-build crashes, `/api/auth/me` returning wrong identity kind) and Features (self-hosted browser/mobile auth flow, build-time branding via env, ELIZA_ALLOWED_ORIGINS env).\n\n# Documentation changes needed?\n\nNo upstream docs need to change. Operator-facing env var (`ELIZA_ALLOWED_ORIGINS`) is documented inline.\n\n# Testing\n\n## Where should a reviewer start?\n\n- Server changes: `packages/app-core/src/api/server-cors.ts` and the new test `packages/app-core/src/api/server-cors.test.ts`\n- Auth shape: `packages/app-core/src/api/auth-session-routes.ts` (synthetic-machine bearer path)\n- Bearer plumbing: `packages/app-core/src/api/csrf-client.ts` and the new test `csrf-client.test.ts`\n- Setup-side: `packages/app-core/src/api/client-base.ts` (window-globals mirror) and the new test `client-base.test.ts`\n\n## Detailed testing steps\n\n**Unit (in this PR)**\n\n- `bun run test packages/app-core/src/api/server-cors.test.ts` — covers Capacitor scheme allowlist, `ELIZA_ALLOWED_ORIGINS` env, rejected origins, `originString` for non-special schemes\n- `bun run test packages/app-core/src/api/csrf-client.test.ts` — covers bearer attachment from `getBootConfig`, no-overwrite of explicit Authorization, `x-milady-csrf` only on state-changing methods\n- `bun run test packages/app-core/src/api/client-base.test.ts` — covers `setToken` mirror to window globals + clear on null\n\n**Manual**\n\n- VPS (Linux): browser at `https://bot.<host>/#token=<bearer>` → lands on chat directly, token persists in localStorage, second visit no fragment still authenticates\n- Windows 11: `bun run dev:desktop` → Electrobun window → Remote → enter `https://bot.<host>` + token → connect → chat works; `bun run build:desktop` succeeds and installer launches\n- Android (Capacitor on a physical Samsung phone): `npx cap open android` → Run → onboarding → Remote → enter URL + token → connect → chat works; webhook + Discord reply roundtrip verified\n\n# Known limitations\n\n- CEF window title bar icon on Windows: Electrobun upstream hasn't implemented `WM_SETICON` for CEF windows. Out of scope.\n- electrobun@1.16.0 tar extraction references a `D:\\` CI path on Windows. Worked around with the `embedWindowsIcons()` post-build step in this PR; remove when Electrobun lands a fix.\n- The Windows-only typecheck noise from duplicate `drizzle-orm` versions (`auth-store.ts`) is a pre-existing transitive-dep dedup quirk, not caused by this PR. Left alone.\n\n<!-- greptile_comment -->\n\n<h3>Greptile Summary</h3>\n\nThis PR wires self-hosted browser, Capacitor mobile, and Electrobun desktop builds into the existing RuntimeGate \"Remote\" flow: CORS is extended to Capacitor WebView origins and operator-configured `ELIZA_ALLOWED_ORIGINS`, `fetchWithCsrf` auto-attaches Bearer tokens, `/api/auth/me` gains a bearer-only identity path, and the desktop-only 401-retry branch is unified across platforms. Build infrastructure fixes cover Windows icon embedding, duplicate null-coalesces in `electrobun.config.ts`, and a missing `mavenCentralMirrorUrl` in `variables.gradle`.\n\n<h3>Confidence Score: 4/5</h3>\n\nSafe to merge with awareness of two P2 edge cases in the 401/token-stale path.\n\nNo P0 or P1 findings beyond what was already raised in prior review threads. Three P2s: stale remote token persisting onto local connections via the removed setToken(null), a misleading no-op 'retry' comment in the outer-catch 401 block, and https://localhost being unconditionally CORS-allowed rather than Capacitor-scoped. All three are edge-case or documentation-level concerns.\n\npackages/app-core/src/state/startup-phase-restore.ts and packages/app-core/src/state/startup-phase-poll.ts (outer-catch 401 block) warrant a second look for the stale-token + silent-retry interaction.\n\n<h3>Important Files Changed</h3>\n\n\n\n\n| Filename | Overview |\n|----------|----------|\n| packages/app-core/src/api/server-cors.ts | Adds CAPACITOR_WEBVIEW_ORIGINS hardlist and ELIZA_ALLOWED_ORIGINS env parsing; https://localhost allowed unconditionally which is slightly broader than Capacitor-only. |\n| packages/app-core/src/state/startup-phase-poll.ts | Collapses desktop/non-desktop 401 handling into a unified retry; outer-catch 401 block is an empty no-op with a misleading comment; adds !auth.authenticated to pairing gate. |\n| packages/app-core/src/state/startup-phase-restore.ts | Removes setToken(null) for local connection restores; stale remote token can persist and be forwarded to the local agent by fetchWithCsrf's new auto-bearer logic. |\n| packages/app-core/src/api/csrf-client.ts | Adds automatic Bearer injection from getBootConfig(); preserves explicit Authorization header; CSRF header still only on state-changing methods. Clean. |\n| packages/app-core/src/api/auth-session-routes.ts | Adds bearer-only path to /api/auth/me: returns real owner identity or synthetic machine identity when no owner is configured. Correct kind field. |\n| packages/app-core/src/api/auth-pairing-compat-routes.ts | Adds explicit authenticated field to /api/auth/status response so clients can short-circuit pairing check. Uses existing tokenMatches for secure comparison. |\n| packages/app-core/src/api/client-base.ts | setToken() now mirrors to window globals via setElizaApiToken/clearElizaApiToken for Capacitor web fallback. Parallels existing setBaseUrl() pattern. |\n| packages/app-core/src/api/server.ts | Swaps isAllowedLocalOrigin calls for isAllowedOrigin; passes corsAllowedPorts but not remoteOrigins (defaults to getCachedRemoteOrigins). Correct. |\n| packages/agent/src/api/experience-routes.ts | Inlines ExperienceType/OutcomeType enums to work around tree-shaking; risk of silent drift from upstream source-of-truth (flagged in previous thread). |\n| packages/app-core/scripts/desktop-build.mjs | Adds embedWindowsIcons() post-build step using locally resolved rcedit-x64.exe to work around Electrobun CI-path rcedit reference. Cross-platform safe. |\n| packages/app-core/src/state/startup-phase-runtime.ts | Removes isElectrobunRuntime() branch; 401+hasToken now retries silently, matching the unified poll approach. Clean. |\n| packages/app-core/src/components/shell/RuntimeGate.tsx | Adds onInput/onBlur handlers for Capacitor paste reliability, fixes splash-bg extension to .png, conditionally renders choice card images. |\n| packages/app-core/src/registry/index.ts | Wraps readdirSync in try/catch to gracefully handle missing entries/ directories in packaged builds instead of crashing. |\n\n</details>\n\n\n\n<h3>Flowchart</h3>\n\n```mermaid\n%%{init: {'theme': 'neutral'}}%%\nflowchart TD\n    A[Capacitor or Browser request] --> B{Origin in CORS allowlist?}\n    B -->|Capacitor WebView origins| C[Allow preflight]\n    B -->|ELIZA_ALLOWED_ORIGINS match| C\n    B -->|localhost on configured port| C\n    B -->|anything else| D[Reject]\n\n    C --> E[fetchWithCsrf]\n    E --> F{API token in boot config?}\n    F -->|yes| G[Attach Authorization header]\n    F -->|no| H[Cookie-only mode]\n    G --> I[auth status endpoint]\n    H --> I\n\n    I --> J{auth required?}\n    J -->|no| K[Proceed to app]\n    J -->|yes| L{authenticated and token stored?}\n    L -->|yes| K\n    L -->|no token stored| M[Show pairing UI]\n    L -->|token stored but invalid| N[Retry loop until deadline]\n```\n\n<!-- greptile_failed_comments -->\n<details><summary><h3>Comments Outside Diff (1)</h3></summary>\n\n1. `packages/app-core/src/state/startup-phase-poll.ts`, line 187-201 ([link](https://github.com/elizaos/eliza/blob/539909338fd701a85f99441c03b750eccde6925e/packages/app-core/src/state/startup-phase-poll.ts#L187-L201)) \n\n   <a href=\"#\"><img alt=\"P1\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/p1.svg?v=7\" align=\"top\"></a> **Invalid token silently times out instead of showing pairing UI**\n\n   The `!client.hasToken()` guard means that when a stored token is *invalid* (`auth.authenticated === false`, `auth.required === true`, but `client.hasToken() === true`), this branch is never entered. Execution falls through to the backend connection loop, which receives 401s and retries until `deadline` is hit, after which the user sees a generic \"backend timeout\" error — never the pairing/re-auth UI.\n\n   The old non-desktop path handled this explicitly: on a 401 with a token it cleared the token and dispatched `BACKEND_AUTH_REQUIRED`. That recovery path was removed here without a replacement for the invalid-token case. A minimal fix would drop the `!client.hasToken()` guard when the server has already confirmed the token is invalid:\n\n   ```ts\n   // If the server says the token is bad, don't require \"no token\" to show pairing\n   if (auth.required && !auth.authenticated) {\n     if (auth.loginRequired) {\n       // ...existing loginRequired branch...\n     }\n     deps.setAuthRequired(true);\n     deps.setPairingEnabled(auth.pairingEnabled);\n     deps.setPairingExpiresAt(auth.expiresAt);\n     deps.setOnboardingLoading(false);\n     dispatch({ type: \"BACKEND_AUTH_REQUIRED\" });\n     return;\n   }\n   ```\n</details>\n\n<!-- /greptile_failed_comments -->\n\n<sub>Reviews (2): Last reviewed commit: [\"perf(server-cors): cache getAllowedRemot...\"](https://github.com/elizaos/eliza/commit/9ce7a62d77f9065d85560a4b61063c5278e37243) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=30313367)</sub>\n\n<!-- /greptile_comment -->",
      "repository": "elizaos/eliza",
      "createdAt": "2026-04-30T11:20:43Z",
      "mergedAt": "2026-05-01T03:12:42Z",
      "additions": 653,
      "deletions": 161
    },
    {
      "id": "PR_kwDOMT5cIs7Xg9e0",
      "title": "test(app-core): remove api module mocks",
      "author": "lalalune",
      "number": 7226,
      "body": "<!-- Use this template by filling in information and copying and pasting relevant items out of the HTML comments. -->\r\n\r\n# Relates to\r\n\r\n<!-- LINK TO ISSUE OR TICKET -->\r\n\r\n<!-- This risks section must be filled out before the final review and merge. -->\r\n\r\n# Risks\r\n\r\n<!--\r\nLow, medium, large. List what kind of risks and what could be affected.\r\n-->\r\n\r\n# Background\r\n\r\n## What does this PR do?\r\n\r\n## What kind of change is this?\r\n\r\n<!--\r\nBug fixes (non-breaking change which fixes an issue)\r\nImprovements (misc. changes to existing features)\r\nFeatures (non-breaking change which adds functionality)\r\nUpdates (new versions of included code)\r\n-->\r\n\r\n<!-- This \"Why\" section is most relevant if there are no linked issues explaining why. If there is a related issue, it might make sense to skip this why section. -->\r\n<!--\r\n## Why are we doing this? Any context or related work?\r\n-->\r\n\r\n# Documentation changes needed?\r\n\r\n<!--\r\nMy changes do not require a change to the project documentation.\r\nMy changes require a change to the project documentation.\r\nIf documentation change is needed: I have updated the documentation accordingly.\r\n-->\r\n\r\n<!-- Please show how you tested the PR. This will really help if the PR needs to be retested and probably help the PR get merged quicker. -->\r\n\r\n# Testing\r\n\r\n## Where should a reviewer start?\r\n\r\n## Detailed testing steps\r\n\r\n<!--\r\nNone: Automated tests are acceptable.\r\n-->\r\n\r\n<!--\r\n- As [anon/admin], go to [link]\r\n  - [do action]\r\n  - verify [result]\r\n-->\r\n\r\n<!-- If there is a UI change, please include before and after screenshots or videos. This will speed up PRs being merged. It is extra nice to annotate screenshots with arrows or boxes pointing out the differences. -->\r\n<!--\r\n## Screenshots\r\n### Before\r\n### After\r\n-->\r\n\r\n<!-- If there is anything about the deployment, please make a note. -->\r\n<!--\r\n# Deploy Notes\r\n-->\r\n\r\n<!--  Copy and paste command line output. -->\r\n<!--\r\n## Database changes\r\n-->\r\n\r\n<!--  Please specify deploy instructions if there is something more than the automated steps. -->\r\n<!--\r\n## Deployment instructions\r\n-->\r\n\r\n<!-- If you are on Discord, please join https://discord.gg/ai16z and state your Discord username here for the contributor role and join us in #development-feed -->\r\n<!--\r\n## Discord username\r\n\r\n-->\n\n<!-- greptile_comment -->\n\n<h3>Greptile Summary</h3>\n\nThis PR removes `vi.mock` overrides for `boot-config` and `eliza-globals` in the `app-core` API tests, replacing them with the real module implementations backed by proper `beforeEach`/`afterEach` teardown (`setBootConfig(DEFAULT_BOOT_CONFIG)` and `clearElizaApiToken()`). Mock-call assertions (`toHaveBeenCalledWith`) are replaced with state-based assertions (`getElizaApiToken()`), and a `// @vitest-environment jsdom` directive is added to `client-base.test.ts` so window-global helpers are exercised correctly.\n\n<h3>Confidence Score: 5/5</h3>\n\nSafe to merge — test-only changes with no production code impact.\n\nBoth files are test files only. The real implementations are consistent with what the mocks approximated, teardown is handled in both beforeEach and afterEach, and the new jsdom directive is correctly placed at the top of the file. No logic issues found.\n\nNo files require special attention.\n\n<h3>Important Files Changed</h3>\n\n| Filename | Overview |\n|----------|----------|\n| packages/app-core/src/api/client-base.test.ts | Removes module mocks for boot-config and eliza-globals in favour of real implementations; adds `// @vitest-environment jsdom` directive (required for window-based globals) and switches to state-based assertions. |\n| packages/app-core/src/api/csrf-client.test.ts | Removes boot-config mock and the test-only `_setTestConfig` escape hatch; replaces with real `setBootConfig(DEFAULT_BOOT_CONFIG)` resets in beforeEach/afterEach, and updates bearer-token setup to spread DEFAULT_BOOT_CONFIG. |\n\n</details>\n\n<h3>Flowchart</h3>\n\n```mermaid\n%%{init: {'theme': 'neutral'}}%%\nflowchart TD\n    A[beforeEach] --> B[clearElizaApiToken\\nclear window globals]\n    A --> C[setBootConfig DEFAULT_BOOT_CONFIG\\nreset global store]\n    A --> D[new ElizaClient]\n    D --> E[Test body\\nstate-based assertions]\n    E --> F[afterEach]\n    F --> G[clearElizaApiToken]\n    F --> H[setBootConfig DEFAULT_BOOT_CONFIG]\n\n    subgraph \"Removed vi.mock\"\n        M1[mock boot-config\\n_setTestConfig escape hatch]\n        M2[mock eliza-globals\\ntoHaveBeenCalled assertions]\n    end\n\n    subgraph \"Real implementations used\"\n        R1[getBootConfig / setBootConfig\\nSymbol-keyed global store]\n        R2[getElizaApiToken / clearElizaApiToken\\nwindow.__ELIZAOS_API_TOKEN__]\n    end\n```\n\n<sub>Reviews (1): Last reviewed commit: [\"test(app-core): remove api module mocks\"](https://github.com/elizaos/eliza/commit/3c9787114936322a8b6fffd2d0631e4fbede8690) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=30504300)</sub>\n\n<!-- /greptile_comment -->",
      "repository": "elizaos/eliza",
      "createdAt": "2026-05-01T19:42:11Z",
      "mergedAt": "2026-05-01T19:42:44Z",
      "additions": 28,
      "deletions": 69
    },
    {
      "id": "PR_kwDOMT5cIs7XhdbY",
      "title": "chore(deps): update dependency @biomejs/biome to v2.4.14",
      "author": "renovate",
      "number": 7228,
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [@biomejs/biome](https://biomejs.dev) ([source](https://redirect.github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome)) | [`2.4.13` → `2.4.14`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.4.13/2.4.14) | ![age](https://developer.mend.io/api/mc/badges/age/npm/@biomejs%2fbiome/2.4.14?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@biomejs%2fbiome/2.4.13/2.4.14?slim=true) |\n\n---\n\n> [!WARNING]\n> Some dependencies could not be looked up. Check the [Dependency Dashboard](../issues/79) for more information.\n\n---\n\n### Release Notes\n\n<details>\n<summary>biomejs/biome (@&#8203;biomejs/biome)</summary>\n\n### [`v2.4.14`](https://redirect.github.com/biomejs/biome/blob/HEAD/packages/@&#8203;biomejs/biome/CHANGELOG.md#2414)\n\n[Compare Source](https://redirect.github.com/biomejs/biome/compare/@biomejs/biome@2.4.13...@biomejs/biome@2.4.14)\n\n##### Patch Changes\n\n- [#&#8203;9393](https://redirect.github.com/biomejs/biome/pull/9393) [`491b171`](https://redirect.github.com/biomejs/biome/commit/491b171e245aa1ad1063662d4408692b4fc11eae) Thanks [@&#8203;dyc3](https://redirect.github.com/dyc3)! - Added the nursery rule [`useTestHooksOnTop`](https://biomejs.dev/linter/rules/use-test-hooks-on-top) in the `test` domain. The rule flags lifecycle hooks (`beforeEach`, `beforeAll`, `afterEach`, `afterAll`) that appear after test cases in the same block, enforcing that hooks are defined before any test case.\n\n- [#&#8203;10157](https://redirect.github.com/biomejs/biome/pull/10157) [`eefc5ab`](https://redirect.github.com/biomejs/biome/commit/eefc5ab81709e78068774b0f5bc56af448a733d1) Thanks [@&#8203;dyc3](https://redirect.github.com/dyc3)! - Fixed [#&#8203;7882](https://redirect.github.com/biomejs/biome/issues/7882): The HTML parser will now emit better diagnostics when it encounters a void element with a closing tag, such as `<br></br>`. Previously, the parser would emit multiple diagnostics with conflicting advice. Now it emits a single diagnostic that clearly states that void elements should not have closing tags.\n\n- [#&#8203;10054](https://redirect.github.com/biomejs/biome/pull/10054) [`0e9f569`](https://redirect.github.com/biomejs/biome/commit/0e9f5696b1f2dec6e0d1f81b39192bdb07ab0c1a) Thanks [@&#8203;minseong0324](https://redirect.github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) no longer misses widening from concrete object types, class instances, object literals, tuples, functions, and regular expressions to `: object`.\n\n  A function annotated `: object` returning an object literal:\n\n  ```ts\n  function f(): object {\n    return { retry: true };\n  }\n  ```\n\n- [#&#8203;10116](https://redirect.github.com/biomejs/biome/pull/10116) [`53269eb`](https://redirect.github.com/biomejs/biome/commit/53269ebe0a2f718213483444696b88c7e8d0e7c4) Thanks [@&#8203;jiwon79](https://redirect.github.com/jiwon79)! - Fixed [#&#8203;6201](https://redirect.github.com/biomejs/biome/issues/6201): [`noUselessEscapeInRegex`](https://biomejs.dev/linter/rules/no-useless-escape-in-regex/) no longer flags an escaped backslash followed by `-` as a useless escape. Patterns like `/[\\\\-]/` are now considered valid because the second `\\` is the escaped backslash, not an unnecessary escape of the trailing dash.\n\n- [#&#8203;10092](https://redirect.github.com/biomejs/biome/pull/10092) [`33d8543`](https://redirect.github.com/biomejs/biome/commit/33d8543da451e272000b84a8e29114d72923cdc1) Thanks [@&#8203;Conaclos](https://redirect.github.com/Conaclos)! - Fixed [#&#8203;9097](https://redirect.github.com/biomejs/biome/issues/9097): [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/) no longer adds a blank line between a never-matched group and a matched group.\n\n  Given the following `organizeImports` options:\n\n  ```json\n  {\n    \"groups\": [\":NODE:\", \":BLANK_LINE:\", \":PACKAGE:\", \":BLANK_LINE:\", \":PATH:\"]\n  }\n  ```\n\n  The following code...\n\n  ```js\n  // Comment\n  import \"package\";\n  import \"./file.js\";\n  ```\n\n  ...was organized as:\n\n  ```diff\n  +\n    // Comment\n    import \"package\";\n  +\n    import \"./file.js\";\n  ```\n\n  A blank line was added even though the group ':NODE:' doesn't match any imports here.\n  `:BLANK_LINE:` between never-matched groups and matched groups are now ignored.\n  The code is now organized as:\n\n  ```diff\n    // Comment\n    import \"package\";\n  +\n    import \"./file.js\";\n  ```\n\n- [#&#8203;10138](https://redirect.github.com/biomejs/biome/pull/10138) [`a10b6c1`](https://redirect.github.com/biomejs/biome/commit/a10b6c119d1f3862da918ce7617ee365bb534c6e) Thanks [@&#8203;dyc3](https://redirect.github.com/dyc3)! - Fixed Vue `v-for` handling for [`noUndeclaredVariables`](https://biomejs.dev/linter/rules/no-undeclared-variables/) and [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/). Biome now recognizes variables declared by `v-for` directives and references to iterated values in Vue templates.\n\n- [#&#8203;10115](https://redirect.github.com/biomejs/biome/pull/10115) [`d428d76`](https://redirect.github.com/biomejs/biome/commit/d428d76ba8be7131090c199cefa36613a332e75b) Thanks [@&#8203;minseong0324](https://redirect.github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) no longer reports false positives when a union return type's `boolean` variant is covered by both `true` and `false` returns.\n\n- [#&#8203;9922](https://redirect.github.com/biomejs/biome/pull/9922) [`7acf1e0`](https://redirect.github.com/biomejs/biome/commit/7acf1e0890d1e52b1cfa940554f6ebbd1bae20b3) Thanks [@&#8203;dyc3](https://redirect.github.com/dyc3)! - Added the new nursery rule [`noReactStringRefs`](https://biomejs.dev/linter/rules/no-react-string-refs/), which disallows legacy React string refs such as `ref=\"hello\"` and `this.refs.hello`.\n\n  Biome also reports template-literal refs such as ``ref={`hello`}``, so React code can consistently migrate to callback refs, `createRef()`, or `useRef()`.\n\n- [#&#8203;10010](https://redirect.github.com/biomejs/biome/pull/10010) [`f3e76ab`](https://redirect.github.com/biomejs/biome/commit/f3e76ab7befecca7cdc7a04edac1350de31029de) Thanks [@&#8203;dyc3](https://redirect.github.com/dyc3)! - Fixed a bug in the LSP file watcher registration so Biome now watches `.biome.json` and `.biome.jsonc` configuration files and reloads workspace settings when they change.\n\n- [#&#8203;10176](https://redirect.github.com/biomejs/biome/pull/10176) [`8a40ef8`](https://redirect.github.com/biomejs/biome/commit/8a40ef835db83277a15b4f0455b5b9b69c719ad3) Thanks [@&#8203;dyc3](https://redirect.github.com/dyc3)! - Fixed [#&#8203;10011](https://redirect.github.com/biomejs/biome/issues/10011): The [`noThisInStatic`](https://biomejs.dev/linter/rules/no-this-in-static/) rule no longer reports `this` when it is used as the constructor target in `new this(...)`, which is required for inherited static factory methods.\n\n- [#&#8203;10163](https://redirect.github.com/biomejs/biome/pull/10163) [`6867e96`](https://redirect.github.com/biomejs/biome/commit/6867e96dacf0b96dfbefd51f95a29136d90b7bb4) Thanks [@&#8203;jiwon79](https://redirect.github.com/jiwon79)! - Fixed [#&#8203;9884](https://redirect.github.com/biomejs/biome/issues/9884): The [`useSortedAttributes`](https://biomejs.dev/assist/actions/use-sorted-attributes/) auto-fix no longer corrupts source code when both an outer JSX element and a nested JSX-valued attribute have unsorted attributes in the same pass. Multiple unsorted groups separated by spread or shorthand attributes within the same JSX element are now reported as a single diagnostic.\n\n- [#&#8203;10079](https://redirect.github.com/biomejs/biome/pull/10079) [`d29dd19`](https://redirect.github.com/biomejs/biome/commit/d29dd1916bdfa4a13dba95cad57f61c65cb5739c) Thanks [@&#8203;Damix48](https://redirect.github.com/Damix48)! - Fixed false positive in `noAssignInExpressions` for Svelte `{@&#8203;const}` blocks. Assignments in `{@&#8203;const name = value}` are now correctly recognized as declarations rather than accidental assignments in expressions.\n\n- [#&#8203;10080](https://redirect.github.com/biomejs/biome/pull/10080) [`5d8fdac`](https://redirect.github.com/biomejs/biome/commit/5d8fdac6d26987904130c2ef0db797c295922f08) Thanks [@&#8203;Damix48](https://redirect.github.com/Damix48)! - Fixed parsing of closing parentheses in Svelte `{#each}` block key expressions. Biome now correctly parses method calls and other parenthesised expressions used as keys.\n\n  For example, the following snippets are now parsed correctly:\n\n  ```svelte\n  {#each numbers as number, index (number.toString())}\n    <p>{number}</p>\n  {/each}\n\n  {#each numbers as number (key(number))}\n    <p>{number}</p>\n  {/each}\n  ```\n\n- [#&#8203;10140](https://redirect.github.com/biomejs/biome/pull/10140) [`e7024b9`](https://redirect.github.com/biomejs/biome/commit/e7024b92638090a9b8ccd064e0662f7994164621) Thanks [@&#8203;solithcy](https://redirect.github.com/solithcy)! - Fixed [#&#8203;10135](https://redirect.github.com/biomejs/biome/issues/10135): Biome no longer crashes on missing Svelte template expressions.\n\n  The following code snippet longer panics:\n\n  ```svelte\n  {#if }\n   <p>^ this would previously crash</p>\n  {/if}\n  {@&#8203;const }\n  <p>    ^ this would also crash</p>\n  ```\n\n- [#&#8203;10111](https://redirect.github.com/biomejs/biome/pull/10111) [`7818009`](https://redirect.github.com/biomejs/biome/commit/7818009e23e12758d00665be6faf8471ca0b0027) Thanks [@&#8203;jiwon79](https://redirect.github.com/jiwon79)! - Fixed [#&#8203;9997](https://redirect.github.com/biomejs/biome/issues/9997): [`noDuplicateSelectors`](https://biomejs.dev/linter/rules/no-duplicate-selectors/) no longer reports false positives for selectors inside `@scope` queries. Biome now treats `@scope` as a separate at-rule context, like `@media`, `@supports`, `@container`, and `@starting-style`.\n\n  The following snippet is no longer flagged as a duplicate:\n\n  ```css\n  .Example {\n    padding: 0;\n  }\n\n  @&#8203;scope (.theme-dark) {\n    .Example {\n      color: white;\n    }\n  }\n  ```\n\n- [#&#8203;9926](https://redirect.github.com/biomejs/biome/pull/9926) [`d62b331`](https://redirect.github.com/biomejs/biome/commit/d62b331726c1b730ca2d1c38325ce6196beee7a4) Thanks [@&#8203;dyc3](https://redirect.github.com/dyc3)! - Added the nursery lint rule [`useMathMinMax`](https://biomejs.dev/linter/rules/use-math-min-max/), which prefers `Math.min()` and `Math.max()` over equivalent ternary comparisons.\n\n  For example, this code:\n\n  ```js\n  const min = a < b ? a : b;\n  ```\n\n  is much more readable when rewritten as:\n\n  ```js\n  const min = Math.min(a, b);\n  ```\n\n- [#&#8203;10115](https://redirect.github.com/biomejs/biome/pull/10115) [`d428d76`](https://redirect.github.com/biomejs/biome/commit/d428d76ba8be7131090c199cefa36613a332e75b) Thanks [@&#8203;minseong0324](https://redirect.github.com/minseong0324)! - [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/) now flags missing `true`/`false` cases for `boolean` discriminants, including when `boolean` is a union variant.\n\n- [#&#8203;10125](https://redirect.github.com/biomejs/biome/pull/10125) [`a55a0b6`](https://redirect.github.com/biomejs/biome/commit/a55a0b6fe03f772316b76937b1292096cdc8a661) Thanks [@&#8203;bmish](https://redirect.github.com/bmish)! - Fixed a resolver bug where packages that define a typed entry point through `package.json`'s `main` field but omit `types` were ignored during type-aware resolution. Type-aware rules such as [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) can now inspect imports from those packages.\n\n- [#&#8203;10117](https://redirect.github.com/biomejs/biome/pull/10117) [`895e809`](https://redirect.github.com/biomejs/biome/commit/895e809dc799cd6aa70032fbb56dfe0f9c0f6f39) Thanks [@&#8203;denizdogan](https://redirect.github.com/denizdogan)! - Added support for the `corner-shape` family of CSS properties and the `superellipse()`/`squircle()` value functions, so [`noUnknownProperty`](https://biomejs.dev/linter/rules/no-unknown-property/) and [`noUnknownFunction`](https://biomejs.dev/linter/rules/no-unknown-function/) no longer flag them as unknown.\n\n  New known properties: `corner-shape`, `corner-block-end-shape`, `corner-block-start-shape`, `corner-bottom-left-shape`, `corner-bottom-right-shape`, `corner-bottom-shape`, `corner-end-end-shape`, `corner-end-start-shape`, `corner-inline-end-shape`, `corner-inline-start-shape`, `corner-left-shape`, `corner-right-shape`, `corner-start-end-shape`, `corner-start-start-shape`, `corner-top-left-shape`, `corner-top-right-shape`, `corner-top-shape`.\n\n  New known value functions: `superellipse()`, `squircle()`.\n\n- [#&#8203;8620](https://redirect.github.com/biomejs/biome/pull/8620) [`8df8f73`](https://redirect.github.com/biomejs/biome/commit/8df8f73ca1c18a688f64f304f0b9089797258a1e) Thanks [@&#8203;dyc3](https://redirect.github.com/dyc3)! - Fixed [#&#8203;8062](https://redirect.github.com/biomejs/biome/issues/8062): Added support for parsing Vue `v-for` directives more accurately.\n\n- [#&#8203;10191](https://redirect.github.com/biomejs/biome/pull/10191) [`aa055cd`](https://redirect.github.com/biomejs/biome/commit/aa055cd74f82fac691dfa2f65dbfd255213cb884) Thanks [@&#8203;guney](https://redirect.github.com/guney)! - Now the rule [`noStaticElementInteractions`](https://biomejs.dev/linter/rules/no-static-element-interactions/) doesn't trigger custom elements.\n\n- [#&#8203;9757](https://redirect.github.com/biomejs/biome/pull/9757) [`2c62594`](https://redirect.github.com/biomejs/biome/commit/2c62594b84ae62fd5fa130adff917a1bcd8dfddd) Thanks [@&#8203;dyc3](https://redirect.github.com/dyc3)! - Fixed [#&#8203;9099](https://redirect.github.com/biomejs/biome/issues/9099): the HTML formatter collapsing non-text children (inline elements, Svelte expressions, comments) onto a single line when the source had them on separate lines. Biome now preserves the user's intended line breaks for exclusively non-text children.\n\n  For example, the following Svelte snippet is now preserved instead of being collapsed to `<div>{name}<!-- comment --></div>`:\n\n  ```svelte\n  <div>\n    {name}<!-- comment -->\n  </div>\n  ```\n\n  Similarly, HTML elements like `<span>` inside a `<div>` are now preserved when written on their own line:\n\n  ```html\n  <div>\n    <span>text</span>\n  </div>\n  ```\n\n- [#&#8203;10105](https://redirect.github.com/biomejs/biome/pull/10105) [`e7c1a6d`](https://redirect.github.com/biomejs/biome/commit/e7c1a6d5319908cf613f7fa80667e6981435508d) Thanks [@&#8203;jiwon79](https://redirect.github.com/jiwon79)! - Fixed [#&#8203;10039](https://redirect.github.com/biomejs/biome/issues/10039): [`useReadonlyClassProperties`](https://biomejs.dev/linter/rules/use-readonly-class-properties/) now detects unreassigned private members in class expressions and export default classes, not only in class declarations.\n\n  The following patterns are now correctly flagged:\n\n  ```ts\n  const AnonClass = class {\n    #prop = 123;\n    constructor() {\n      console.log(this.#prop);\n    }\n  };\n\n  export default class {\n    #prop = 123;\n    constructor() {\n      console.log(this.#prop);\n    }\n  }\n  ```\n\n- [#&#8203;10141](https://redirect.github.com/biomejs/biome/pull/10141) [`46a77d0`](https://redirect.github.com/biomejs/biome/commit/46a77d0a35e8dbbcefeca264e8630af83b21f1d9) Thanks [@&#8203;minseong0324](https://redirect.github.com/minseong0324)! - Improved [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/) to detect conditions that are always truthy because they check built-in global class instances such as `Date`, `Map`, `Set`, `WeakMap`, and `Error`.\n\n- [#&#8203;10178](https://redirect.github.com/biomejs/biome/pull/10178) [`7b05a89`](https://redirect.github.com/biomejs/biome/commit/7b05a893df8c9c950871b83ff1b3ae28113e8b15) Thanks [@&#8203;dyc3](https://redirect.github.com/dyc3)! - Fixed [#&#8203;10177](https://redirect.github.com/biomejs/biome/issues/10177): The HTML parser no longer reports lowercase `html` or `doctype` text as invalid after void elements such as `<br>`.\n\n- [#&#8203;10155](https://redirect.github.com/biomejs/biome/pull/10155) [`0d4595d`](https://redirect.github.com/biomejs/biome/commit/0d4595dae68b034bd6de3bdfd15437a34fa53cb2) Thanks [@&#8203;jiwon79](https://redirect.github.com/jiwon79)! - Fixed [#&#8203;10045](https://redirect.github.com/biomejs/biome/issues/10045): the CSS formatter no longer compounds indentation inside nested functional pseudo-classes such as `:not(:where(...))`, `:is(:where(...))`, and similar combinations. The same fix also removes one level of unnecessary indentation that was added inside any pseudo-class function whose argument list wrapped onto multiple lines, including `:nth-child(... of ...)`, `::part(...)`, and `:active-view-transition-type(...)`.\n  The following snippet is now correctly formatted, matching Prettier.\n\n  ```css\n  input:not(\n    :where(\n      [type=\"submit\"],\n      [type=\"checkbox\"],\n      [type=\"radio\"],\n      [type=\"button\"],\n      [type=\"reset\"]\n    )\n  ) {\n    inline-size: 100%;\n  }\n  ```\n\n- [#&#8203;10112](https://redirect.github.com/biomejs/biome/pull/10112) [`6f0251e`](https://redirect.github.com/biomejs/biome/commit/6f0251ea12cddb6edcbf512e5608a7b502762423) Thanks [@&#8203;dyc3](https://redirect.github.com/dyc3)! - Fixed [#&#8203;10110](https://redirect.github.com/biomejs/biome/issues/10110): Biome's parser now accepts surrogate code points in JavaScript string `\\u{...}` escapes.\n\n- [#&#8203;10141](https://redirect.github.com/biomejs/biome/pull/10141) [`46a77d0`](https://redirect.github.com/biomejs/biome/commit/46a77d0a35e8dbbcefeca264e8630af83b21f1d9) Thanks [@&#8203;minseong0324](https://redirect.github.com/minseong0324)! - Improved [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) to detect `object` return annotations that hide built-in global class instances such as `Date`, `Map`, `Set`, `WeakMap`, and `Error`.\n\n- [#&#8203;10083](https://redirect.github.com/biomejs/biome/pull/10083) [`4a664c1`](https://redirect.github.com/biomejs/biome/commit/4a664c1c9ebee339ee4a8b971b0a345aa4dbbe70) Thanks [@&#8203;ematipico](https://redirect.github.com/ematipico)! - Added two new options to [`noShadow`](https://biomejs.dev/linter/rules/no-shadow/), both defaulting to `true` to match typescript-eslint's behavior.\n\n  Fixed [#&#8203;9482](https://redirect.github.com/biomejs/biome/issues/9482): Added `ignoreFunctionTypeParameterNameValueShadow` option. When enabled, parameter names inside function type annotations (e.g. `(options: unknown) => void`) are not flagged as shadowing outer variables.\n\n  Fixed [#&#8203;7812](https://redirect.github.com/biomejs/biome/issues/7812): Added `ignoreTypeValueShadow` option. When enabled, a value binding that shares its name with a type-only declaration (type alias or interface) is not flagged, since types and values occupy separate namespaces in TypeScript.\n\n- [#&#8203;9286](https://redirect.github.com/biomejs/biome/pull/9286) [`52695cf`](https://redirect.github.com/biomejs/biome/commit/52695cf52b3ff42ddfcaef040cfaa00e9a93a4b7) Thanks [@&#8203;Hugo-Polloli](https://redirect.github.com/Hugo-Polloli)! - Fixed [#&#8203;6316](https://redirect.github.com/biomejs/biome/issues/6316): Biome now resolves Svelte `$store` references to the underlying `store` binding in semantic analysis, preventing false `noUndeclaredVariables` diagnostics when the store is declared.\n\n- [#&#8203;10188](https://redirect.github.com/biomejs/biome/pull/10188) [`ae659dd`](https://redirect.github.com/biomejs/biome/commit/ae659ddbd317753c4feb5e4d223b9159d272d01b) Thanks [@&#8203;dyc3](https://redirect.github.com/dyc3)! - Added a new nursery rule [`noExcessiveNestedCallbacks`](https://biomejs.dev/linter/rules/no-excessive-nested-callbacks/), which disallows callbacks nested deeper than the configured maximum.\n\n- [#&#8203;9757](https://redirect.github.com/biomejs/biome/pull/9757) [`2c62594`](https://redirect.github.com/biomejs/biome/commit/2c62594b84ae62fd5fa130adff917a1bcd8dfddd) Thanks [@&#8203;dyc3](https://redirect.github.com/dyc3)! - Fixed [#&#8203;9450](https://redirect.github.com/biomejs/biome/issues/9450): the HTML formatter now correctly preserves multiline formatting for nested `<template>` elements (e.g. `<template #body>`) when the source has children on separate lines. Previously, the children were collapsed onto a single line.\n\n  ```diff\n   <template>\n     <UModal>\n  -    <template #body> <p>content</p> </template>\n  +    <template #body>\n  +      <p>content</p>\n  +    </template>\n     </UModal>\n   </template>\n  ```\n\n- [#&#8203;10118](https://redirect.github.com/biomejs/biome/pull/10118) [`c6edcb4`](https://redirect.github.com/biomejs/biome/commit/c6edcb493d42f05179167a8ff3be4549908e9d0b) Thanks [@&#8203;Netail](https://redirect.github.com/Netail)! - Fixed [#&#8203;10024](https://redirect.github.com/biomejs/biome/issues/10024): `biome migrate eslint` correctly migrates `eslint` rules that belong to multiple Biome rules.\n\n</details>\n\n---\n\n### Configuration\n\n📅 **Schedule**: (UTC)\n\n- Branch creation\n  - At any time (no schedule defined)\n- Automerge\n  - At any time (no schedule defined)\n\n🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.\n\n♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.\n\n🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.\n\n---\n\n - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box\n\n---\n\nThis PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/elizaOS/eliza).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNTkuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE1OS4yIiwidGFyZ2V0QnJhbmNoIjoiZGV2ZWxvcCIsImxhYmVscyI6W119-->\n",
      "repository": "elizaos/eliza",
      "createdAt": "2026-05-01T20:19:22Z",
      "mergedAt": "2026-05-01T20:22:41Z",
      "additions": 2,
      "deletions": 2
    },
    {
      "id": "PR_kwDOMT5cIs7XSL0g",
      "title": "chore(deps): update supabase/postgres docker tag to v17.6.1.113",
      "author": "renovate",
      "number": 7219,
      "body": "This PR contains the following updates:\n\n| Package | Update | Change |\n|---|---|---|\n| supabase/postgres | patch | `17.6.1.112` → `17.6.1.113` |\n\n---\n\n> [!WARNING]\n> Some dependencies could not be looked up. Check the [Dependency Dashboard](../issues/79) for more information.\n\n---\n\n### Configuration\n\n📅 **Schedule**: (UTC)\n\n- Branch creation\n  - At any time (no schedule defined)\n- Automerge\n  - At any time (no schedule defined)\n\n🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.\n\n♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.\n\n🔕 **Ignore**: Close this PR and you won't be reminded about this update again.\n\n---\n\n - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box\n\n---\n\nThis PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/elizaOS/eliza).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNTkuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE1OS4yIiwidGFyZ2V0QnJhbmNoIjoiZGV2ZWxvcCIsImxhYmVscyI6W119-->\n",
      "repository": "elizaos/eliza",
      "createdAt": "2026-04-30T22:39:46Z",
      "mergedAt": "2026-05-01T03:12:42Z",
      "additions": 1,
      "deletions": 1
    }
  ],
  "codeChanges": {
    "additions": 998,
    "deletions": 319,
    "files": 102,
    "commitCount": 162
  },
  "completedItems": [
    {
      "title": "feat(vault): @elizaos/vault — cross-platform secrets vault + Settings UI integration",
      "prNumber": 7197,
      "type": "feature",
      "body": "# Relates to\n\nThis is the upstream-targeting twin of milady-ai/eliza#6. The vault feature originated in the Milady fork; this PR lands the upstream-relevant slice on `elizaOS/eliza:develop`.\n\n# Risks\n\n**Low.** The vault is an additive works",
      "files": [
        ".github/actions/setup-bun-workspace/action.yml",
        ".github/workflows/apple-store-release.yml",
        ".github/workflows/mobile-build-smoke.yml",
        ".github/workflows/nightly.yml",
        ".github/workflows/quality-fork.yml",
        ".github/workflows/test-electrobun-release.yml",
        ".github/workflows/vault-ci.yaml",
        ".github/workflows/windows-dev-smoke.yml",
        "apps/app/.env.example",
        "apps/app/.gitignore",
        "apps/app/README.md",
        "apps/app/app.config.ts",
        "apps/app/capacitor.config.ts",
        "apps/app/electrobun/.gitignore",
        "apps/app/index.html",
        "apps/app/package.json",
        "apps/app/playwright.electrobun.packaged.config.ts",
        "apps/app/playwright.ui-packaged.config.ts",
        "apps/app/playwright.ui-smoke.config.ts",
        "apps/app/playwright.web-views.config.ts",
        "apps/app/public/android-chrome-192x192.png",
        "apps/app/public/android-chrome-512x512.png",
        "apps/app/public/apple-touch-icon.png",
        "apps/app/public/favicon-16x16.png",
        "apps/app/public/favicon-32x32.png",
        "apps/app/public/favicon.ico",
        "apps/app/public/logos/anthropic-icon-white.png",
        "apps/app/public/logos/anthropic-icon.png",
        "apps/app/public/logos/claude-icon.png",
        "apps/app/public/logos/deepseek-icon.png",
        "apps/app/public/logos/elizaos-icon.png",
        "apps/app/public/logos/gemini-icon.png",
        "apps/app/public/logos/grok-icon-white.png",
        "apps/app/public/logos/grok-icon.png",
        "apps/app/public/logos/groq-icon-white.png",
        "apps/app/public/logos/groq-icon.png",
        "apps/app/public/logos/mistral-icon.png",
        "apps/app/public/logos/ollama-icon-white.png",
        "apps/app/public/logos/ollama-icon.png",
        "apps/app/public/logos/openai-icon-white.png",
        "apps/app/public/logos/openai-icon.png",
        "apps/app/public/logos/openrouter-icon-white.png",
        "apps/app/public/logos/openrouter-icon.png",
        "apps/app/public/logos/together-ai-icon.png",
        "apps/app/public/logos/zai-icon-white.png",
        "apps/app/public/logos/zai-icon.png",
        "apps/app/public/og-image.png",
        "apps/app/public/splash-bg.jpg",
        "apps/app/scripts/build.mjs",
        "apps/app/scripts/capacitor-plugin-names.mjs"
      ]
    },
    {
      "title": "chore(deps): update supabase/postgres docker tag to v17.6.1.113",
      "prNumber": 7219,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Update | Change |\n|---|---|---|\n| supabase/postgres | patch | `17.6.1.112` → `17.6.1.113` |\n\n---\n\n> [!WARNING]\n> Some dependencies could not be looked up. Check the [Dependency Dashboard]",
      "files": [
        "packages/app-core/deploy/docker-compose.supabase-db.yml"
      ]
    },
    {
      "title": "fix(deps): update dependency @anthropic-ai/sdk to ^0.92.0",
      "prNumber": 7218,
      "type": "bugfix",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [@anthropic-ai/sdk](https://redirect.gi",
      "files": [
        "packages/typescript/package.json"
      ]
    },
    {
      "title": "chore(deps): update dependency ai to v6.0.172",
      "prNumber": 7217,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [ai](https://ai-sdk.dev/docs) ([source]",
      "files": [
        "package.json"
      ]
    },
    {
      "title": "chore(deps): update dependency @ai-sdk/provider-utils to v4.0.25",
      "prNumber": 7216,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [@ai-sdk/provider-utils](https://ai-sdk",
      "files": [
        "package.json"
      ]
    },
    {
      "title": "chore(deps): update dependency @ai-sdk/provider to v3.0.10",
      "prNumber": 7215,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [@ai-sdk/provider](https://ai-sdk.dev/d",
      "files": [
        "package.json"
      ]
    },
    {
      "title": "chore(deps): update dependency @ai-sdk/openai to v3.0.55",
      "prNumber": 7214,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [@ai-sdk/openai](https://ai-sdk.dev/doc",
      "files": [
        "package.json"
      ]
    },
    {
      "title": "feat(self-hosted): CORS + bearer auth + cross-platform build fixes",
      "prNumber": 7212,
      "type": "feature",
      "body": "# Relates to\n\nSelf-hosting cross-platform connectivity. The runtime now serves browser dashboards over HTTPS at a custom domain, App Store-style mobile builds (Capacitor), and Electrobun desktop builds — all routed through a remote agent vi",
      "files": [
        "package.json",
        "packages/agent/src/api/experience-routes.test.ts",
        "packages/agent/src/api/experience-routes.ts",
        "packages/agent/src/runtime/plugin-lifecycle.ts",
        "packages/app-core/platforms/android/variables.gradle",
        "packages/app-core/platforms/electrobun/assets/brand-config.json",
        "packages/app-core/platforms/electrobun/electrobun.config.ts",
        "packages/app-core/scripts/desktop-build.mjs",
        "packages/app-core/src/App.tsx",
        "packages/app-core/src/api/auth-client.ts",
        "packages/app-core/src/api/auth-pairing-compat-routes.ts",
        "packages/app-core/src/api/auth-session-routes.ts",
        "packages/app-core/src/api/client-agent.ts",
        "packages/app-core/src/api/client-base.test.ts",
        "packages/app-core/src/api/client-base.ts",
        "packages/app-core/src/api/csrf-client.test.ts",
        "packages/app-core/src/api/csrf-client.ts",
        "packages/app-core/src/api/server-cors.test.ts",
        "packages/app-core/src/api/server-cors.ts",
        "packages/app-core/src/api/server.ts",
        "packages/app-core/src/components/pages/ChatView.tsx",
        "packages/app-core/src/components/shell/RuntimeGate.tsx",
        "packages/app-core/src/registry/index.ts",
        "packages/app-core/src/state/persistence.ts",
        "packages/app-core/src/state/startup-phase-poll.ts",
        "packages/app-core/src/state/startup-phase-restore.ts",
        "packages/app-core/src/state/startup-phase-runtime.ts",
        "plugins/plugin-agent-skills",
        "plugins/plugin-anthropic",
        "plugins/plugin-cli",
        "plugins/plugin-commands",
        "plugins/plugin-cron",
        "plugins/plugin-discord",
        "plugins/plugin-edge-tts",
        "plugins/plugin-elizacloud",
        "plugins/plugin-evm",
        "plugins/plugin-google-genai",
        "plugins/plugin-groq",
        "plugins/plugin-local-ai",
        "plugins/plugin-local-embedding",
        "plugins/plugin-ollama",
        "plugins/plugin-openai",
        "plugins/plugin-openrouter",
        "plugins/plugin-pdf",
        "plugins/plugin-shell",
        "plugins/plugin-solana",
        "plugins/plugin-sql",
        "plugins/plugin-whatsapp",
        "plugins/plugin-agent-orchestrator"
      ]
    },
    {
      "title": "chore(deps): update dependency ai to v6.0.174",
      "prNumber": 7229,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [ai](https://ai-sdk.dev/docs) ([source]",
      "files": [
        "package.json"
      ]
    },
    {
      "title": "chore(deps): update dependency @biomejs/biome to v2.4.14",
      "prNumber": 7228,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [@biomejs/biome](https://biomejs.dev) (",
      "files": [
        "package.json"
      ]
    },
    {
      "title": "chore(deps): update dependency @ai-sdk/openai to v3.0.58",
      "prNumber": 7227,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [@ai-sdk/openai](https://ai-sdk.dev/doc",
      "files": [
        "package.json"
      ]
    },
    {
      "title": "test(app-core): remove api module mocks",
      "prNumber": 7226,
      "type": "tests",
      "body": "<!-- Use this template by filling in information and copying and pasting relevant items out of the HTML comments. -->\r\n\r\n# Relates to\r\n\r\n<!-- LINK TO ISSUE OR TICKET -->\r\n\r\n<!-- This risks section must be filled out before the final review ",
      "files": [
        "packages/app-core/src/api/client-base.test.ts",
        "packages/app-core/src/api/csrf-client.test.ts"
      ]
    },
    {
      "title": "chore(deps): update dependency ai to v6.0.173",
      "prNumber": 7225,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [ai](https://ai-sdk.dev/docs) ([source]",
      "files": [
        "package.json"
      ]
    },
    {
      "title": "chore(deps): update dependency @ai-sdk/provider-utils to v4.0.26",
      "prNumber": 7224,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [@ai-sdk/provider-utils](https://ai-sdk",
      "files": [
        "package.json"
      ]
    },
    {
      "title": "chore(deps): update dependency @ai-sdk/openai to v3.0.57",
      "prNumber": 7223,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [@ai-sdk/openai](https://ai-sdk.dev/doc",
      "files": [
        "package.json"
      ]
    },
    {
      "title": "chore(deps): update dependency @electric-sql/pglite to ^0.4.0",
      "prNumber": 7221,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [@electric-sql/pglite](https://pglite.d",
      "files": [
        "apps/app-lifeops/package.json"
      ]
    },
    {
      "title": "chore(deps): update actions/upload-artifact action to v7",
      "prNumber": 7220,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Type | Update | Change |\n|---|---|---|---|\n| [actions/upload-artifact](https://redirect.github.com/actions/upload-artifact) | action | major | `v4` → `v7` |\n\n---\n\n> [!WARNING]\n> Some depe",
      "files": [
        ".github/workflows/mobile-build-smoke.yml"
      ]
    }
  ],
  "topContributors": [
    {
      "username": "lalalune",
      "avatarUrl": "https://avatars.githubusercontent.com/u/18633264?u=e2e906c3712c2506ebfa98df01c2cfdc50050b30&v=4",
      "totalScore": 34.924967478670574,
      "prScore": 34.58496747867057,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0.33999999999999997,
      "summary": "lalalune: Focused on codebase maintenance and test optimization, successfully merging PR #7226 to remove api module mocks in elizaos/eliza while engaging in 2 issue discussions. Their work was primarily concentrated on extensive test suite modifications, accounting for 56 commits and significant refactoring across 247 files."
    },
    {
      "username": "Sw4pIO",
      "avatarUrl": "https://avatars.githubusercontent.com/u/250003491?u=b9bad2342b9ccdb72ee4d4502d5534b6256e9d5c&v=4",
      "totalScore": 4,
      "prScore": 0,
      "issueScore": 4,
      "reviewScore": 0,
      "commentScore": 0,
      "summary": "Sw4pIO: Focused on project maintenance and issue resolution by identifying and closing two critical issues in elizaos/eliza (#7210, #7222) related to build configuration and database schema definitions. Their work today centered on improving repository stability and addressing configuration gaps."
    },
    {
      "username": "chopmob-cloud",
      "avatarUrl": "https://avatars.githubusercontent.com/u/250041792?u=295fb2375e2007927789532dae29a2c2bd3c5f80&v=4",
      "totalScore": 0.2,
      "prScore": 0,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0.2,
      "summary": null
    }
  ],
  "newPRs": 9,
  "mergedPRs": 17,
  "newIssues": 1,
  "closedIssues": 4,
  "activeContributors": 5
}