@elizaos/ui 2.0.0-alpha.528 → 2.0.0-alpha.529

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/package.json +1 -1
  2. package/packages/agent/src/actions/browser-autofill-login.d.ts +36 -0
  3. package/packages/agent/src/actions/browser-autofill-login.d.ts.map +1 -0
  4. package/packages/agent/src/actions/browser-autofill-login.js +347 -0
  5. package/packages/agent/src/api/experience-routes.d.ts.map +1 -1
  6. package/packages/agent/src/api/experience-routes.js +40 -2
  7. package/packages/agent/src/api/static-file-server.d.ts +2 -2
  8. package/packages/agent/src/api/static-file-server.d.ts.map +1 -1
  9. package/packages/agent/src/api/static-file-server.js +4 -2
  10. package/packages/agent/src/runtime/agent-wallets.d.ts +103 -0
  11. package/packages/agent/src/runtime/agent-wallets.d.ts.map +1 -0
  12. package/packages/agent/src/runtime/agent-wallets.js +244 -0
  13. package/packages/agent/src/runtime/eliza-plugin.d.ts.map +1 -1
  14. package/packages/agent/src/runtime/eliza-plugin.js +2 -0
  15. package/packages/agent/src/runtime/eliza.d.ts.map +1 -1
  16. package/packages/agent/src/runtime/eliza.js +67 -1
  17. package/packages/agent/src/runtime/operations/index.d.ts +1 -1
  18. package/packages/agent/src/runtime/operations/index.d.ts.map +1 -1
  19. package/packages/agent/src/runtime/operations/index.js +1 -1
  20. package/packages/agent/src/runtime/operations/vault-bridge.d.ts +22 -1
  21. package/packages/agent/src/runtime/operations/vault-bridge.d.ts.map +1 -1
  22. package/packages/agent/src/runtime/operations/vault-bridge.js +53 -0
  23. package/packages/agent/src/runtime/plugin-lifecycle.js +1 -1
  24. package/packages/agent/src/runtime/vault-profile-resolver.d.ts +37 -0
  25. package/packages/agent/src/runtime/vault-profile-resolver.d.ts.map +1 -0
  26. package/packages/agent/src/runtime/vault-profile-resolver.js +75 -0
  27. package/packages/app-core/src/api/client-agent.d.ts +1 -0
  28. package/packages/app-core/src/api/client-agent.d.ts.map +1 -1
  29. package/packages/app-core/src/api/client-base.d.ts.map +1 -1
  30. package/packages/app-core/src/api/client-base.js +11 -2
  31. package/packages/app-core/src/api/client-vault.d.ts +53 -0
  32. package/packages/app-core/src/api/client-vault.d.ts.map +1 -0
  33. package/packages/app-core/src/api/client-vault.js +48 -0
  34. package/packages/app-core/src/api/client.d.ts +1 -0
  35. package/packages/app-core/src/api/client.d.ts.map +1 -1
  36. package/packages/app-core/src/api/client.js +1 -0
  37. package/packages/app-core/src/registry/index.d.ts +7 -0
  38. package/packages/app-core/src/registry/index.d.ts.map +1 -0
  39. package/packages/app-core/src/registry/index.js +43 -0
  40. package/packages/app-core/src/registry/legacy-adapter.d.ts +32 -0
  41. package/packages/app-core/src/registry/legacy-adapter.d.ts.map +1 -0
  42. package/packages/app-core/src/registry/legacy-adapter.js +101 -0
  43. package/packages/app-core/src/registry/loader.d.ts +27 -0
  44. package/packages/app-core/src/registry/loader.d.ts.map +1 -0
  45. package/packages/app-core/src/registry/loader.js +111 -0
  46. package/packages/app-core/src/registry/schema.d.ts +986 -0
  47. package/packages/app-core/src/registry/schema.d.ts.map +1 -0
  48. package/packages/app-core/src/registry/schema.js +250 -0
  49. package/packages/app-core/src/services/vault-bootstrap.d.ts +31 -0
  50. package/packages/app-core/src/services/vault-bootstrap.d.ts.map +1 -0
  51. package/packages/app-core/src/services/vault-bootstrap.js +245 -0
  52. package/packages/app-core/src/services/vault-mirror.d.ts +44 -0
  53. package/packages/app-core/src/services/vault-mirror.d.ts.map +1 -0
  54. package/packages/app-core/src/services/vault-mirror.js +80 -0
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Per-agent wallet keys, stored in the Eliza vault.
3
+ *
4
+ * This module is the bridge between agent identity and the vault. Each
5
+ * agent gets its own EVM and Solana keypair, stored under
6
+ * `agent.<agentId>.wallet.<chain>` as a JSON record. Private keys are
7
+ * sensitive and AES-GCM encrypted at rest by the vault; the vault's
8
+ * master key lives in the OS keychain.
9
+ *
10
+ * The runtime-wide single wallet (process.env.EVM_PRIVATE_KEY etc.) is
11
+ * the *user* wallet, hydrated from the OS secure store via
12
+ * `hydrateWalletKeysFromNodePlatformSecureStore`. Per-agent wallets are
13
+ * stored *inside* the vault (encrypted file), enumerable and easy to
14
+ * surface in the UI alongside saved logins.
15
+ *
16
+ * This module does not generate or store keys on its own; callers
17
+ * supply a `Vault` instance. Agent-creation lifecycle code wires this
18
+ * up — see `runtime/eliza.ts`.
19
+ */
20
+ import { removeEntryMeta, setEntryMeta } from "@elizaos/vault";
21
+ import { deriveEvmAddress, generateWalletForChain } from "../api/wallet.js";
22
+ const PREFIX = "agent";
23
+ const SEGMENT = "wallet";
24
+ function encodeAgentSegment(agentId) {
25
+ if (typeof agentId !== "string" || agentId.trim().length === 0) {
26
+ throw new TypeError("agent-wallets: agentId must be a non-empty string");
27
+ }
28
+ // encodeURIComponent leaves `.` alone, but our vault keys split on `.`
29
+ // — escape it explicitly so an agent ID like "alice.bob" doesn't bleed
30
+ // into the layout (`agent.alice.bob.wallet.evm` has five parts, not four).
31
+ return encodeURIComponent(agentId.trim()).replace(/\./g, "%2E");
32
+ }
33
+ function decodeAgentSegment(segment) {
34
+ return decodeURIComponent(segment);
35
+ }
36
+ function walletKey(agentId, chain) {
37
+ return `${PREFIX}.${encodeAgentSegment(agentId)}.${SEGMENT}.${chain}`;
38
+ }
39
+ function agentPrefix(agentId) {
40
+ return `${PREFIX}.${encodeAgentSegment(agentId)}.${SEGMENT}`;
41
+ }
42
+ function parseAgentWalletKey(key) {
43
+ // Layout: agent.<encodedId>.wallet.<chain>
44
+ const parts = key.split(".");
45
+ if (parts.length !== 4)
46
+ return null;
47
+ if (parts[0] !== PREFIX || parts[2] !== SEGMENT)
48
+ return null;
49
+ const chain = parts[3];
50
+ if (chain !== "evm" && chain !== "solana")
51
+ return null;
52
+ return { agentId: decodeAgentSegment(parts[1]), chain };
53
+ }
54
+ function parseStored(raw) {
55
+ const parsed = JSON.parse(raw);
56
+ if ((parsed.chain !== "evm" && parsed.chain !== "solana") ||
57
+ typeof parsed.address !== "string" ||
58
+ typeof parsed.privateKey !== "string" ||
59
+ typeof parsed.lastModified !== "number") {
60
+ throw new Error("agent-wallets: stored entry malformed (expected chain/address/privateKey/lastModified)");
61
+ }
62
+ return {
63
+ chain: parsed.chain,
64
+ address: parsed.address,
65
+ privateKey: parsed.privateKey,
66
+ lastModified: parsed.lastModified,
67
+ };
68
+ }
69
+ /**
70
+ * Derive the public address from a stored private key. EVM uses the
71
+ * existing helper; Solana stores the public key alongside the secret in
72
+ * `generateWalletForChain`, so the stored `address` is authoritative
73
+ * and we trust it for the read path.
74
+ */
75
+ function deriveAddressFor(chain, privateKey) {
76
+ if (chain === "evm")
77
+ return deriveEvmAddress(privateKey);
78
+ // For Solana the keypair format already includes the public key; the
79
+ // caller is expected to have stored the public key as `address` at
80
+ // write time. Re-derivation would require @solana/web3.js, which we
81
+ // avoid pulling in here.
82
+ throw new Error("agent-wallets: deriveAddressFor only supports EVM; Solana addresses must be supplied at write time");
83
+ }
84
+ /**
85
+ * Read the public descriptor for an agent's wallet. Returns null when
86
+ * the agent has no wallet for that chain. Does NOT reveal the private
87
+ * key.
88
+ */
89
+ export async function getAgentWalletDescriptor(vault, agentId, chain) {
90
+ const key = walletKey(agentId, chain);
91
+ if (!(await vault.has(key)))
92
+ return null;
93
+ const raw = await vault.get(key);
94
+ const stored = parseStored(raw);
95
+ return {
96
+ agentId,
97
+ chain,
98
+ address: stored.address,
99
+ lastModified: stored.lastModified,
100
+ };
101
+ }
102
+ /**
103
+ * Reveal the private key. Audit-logged via the vault. Use only for
104
+ * signing flows.
105
+ */
106
+ export async function revealAgentWalletPrivateKey(vault, agentId, chain, caller) {
107
+ const key = walletKey(agentId, chain);
108
+ const raw = await vault.reveal(key, caller);
109
+ return parseStored(raw).privateKey;
110
+ }
111
+ /**
112
+ * Existence check. Does not reveal the key.
113
+ */
114
+ export async function hasAgentWallet(vault, agentId, chain) {
115
+ return vault.has(walletKey(agentId, chain));
116
+ }
117
+ /**
118
+ * List every wallet descriptor for an agent (typically [evm, solana]).
119
+ */
120
+ export async function listAgentWallets(vault, agentId) {
121
+ const keys = await vault.list(agentPrefix(agentId));
122
+ const out = [];
123
+ for (const key of keys) {
124
+ const parsed = parseAgentWalletKey(key);
125
+ if (!parsed)
126
+ continue;
127
+ const raw = await vault.get(key);
128
+ const stored = parseStored(raw);
129
+ out.push({
130
+ agentId: parsed.agentId,
131
+ chain: parsed.chain,
132
+ address: stored.address,
133
+ lastModified: stored.lastModified,
134
+ });
135
+ }
136
+ return out;
137
+ }
138
+ /**
139
+ * List every agent that has at least one wallet stored. Returns the
140
+ * agent IDs (decoded). Use for UI surfaces enumerating agent wallets.
141
+ */
142
+ export async function listAgentsWithWallets(vault) {
143
+ const keys = await vault.list(PREFIX);
144
+ const agents = new Set();
145
+ for (const key of keys) {
146
+ const parsed = parseAgentWalletKey(key);
147
+ if (!parsed)
148
+ continue;
149
+ agents.add(parsed.agentId);
150
+ }
151
+ return [...agents];
152
+ }
153
+ /**
154
+ * Persist a wallet for an agent. Replaces any existing entry for that
155
+ * (agentId, chain). Stamps `lastModified`.
156
+ *
157
+ * Caller is responsible for supplying the matching address — for EVM
158
+ * this can be derived from the private key, for Solana the keypair
159
+ * generator returns it directly.
160
+ */
161
+ export async function setAgentWallet(vault, agentId, chain, privateKey, address, caller) {
162
+ if (typeof privateKey !== "string" || privateKey.trim().length === 0) {
163
+ throw new TypeError("agent-wallets: privateKey required");
164
+ }
165
+ if (typeof address !== "string" || address.trim().length === 0) {
166
+ throw new TypeError("agent-wallets: address required");
167
+ }
168
+ const stored = {
169
+ chain,
170
+ address,
171
+ privateKey,
172
+ lastModified: Date.now(),
173
+ };
174
+ const key = walletKey(agentId, chain);
175
+ await vault.set(key, JSON.stringify(stored), {
176
+ sensitive: true,
177
+ ...(caller ? { caller } : {}),
178
+ });
179
+ // Surface per-agent wallets in Settings → Vault → Secrets under the
180
+ // "Wallet" group. Without explicit meta, the inventory categorizer
181
+ // falls back to "plugin" for the `agent.<id>.wallet.<chain>` shape.
182
+ await setEntryMeta(vault, key, {
183
+ category: "wallet",
184
+ label: `agent ${agentId} (${chain})`,
185
+ });
186
+ return {
187
+ agentId,
188
+ chain,
189
+ address: stored.address,
190
+ lastModified: stored.lastModified,
191
+ };
192
+ }
193
+ /**
194
+ * Generate a fresh wallet for an agent and persist it. Returns the
195
+ * public descriptor. Idempotent: callers should check `hasAgentWallet`
196
+ * first if they want to avoid replacing an existing wallet.
197
+ */
198
+ export async function generateAgentWallet(vault, agentId, chain, caller) {
199
+ const generated = generateWalletForChain(chain);
200
+ return setAgentWallet(vault, agentId, chain, generated.privateKey, generated.address, caller);
201
+ }
202
+ /**
203
+ * Generate any missing wallets (EVM + Solana) for an agent. Existing
204
+ * wallets are left alone. Returns descriptors for every chain that now
205
+ * has a wallet (whether it was generated this call or was already
206
+ * present).
207
+ */
208
+ export async function ensureAgentWallets(vault, agentId, caller) {
209
+ const chains = ["evm", "solana"];
210
+ const out = [];
211
+ for (const chain of chains) {
212
+ const existing = await getAgentWalletDescriptor(vault, agentId, chain);
213
+ if (existing) {
214
+ out.push(existing);
215
+ continue;
216
+ }
217
+ out.push(await generateAgentWallet(vault, agentId, chain, caller));
218
+ }
219
+ return out;
220
+ }
221
+ /**
222
+ * Remove an agent's wallet for one chain. Idempotent.
223
+ */
224
+ export async function removeAgentWallet(vault, agentId, chain) {
225
+ const key = walletKey(agentId, chain);
226
+ await vault.remove(key);
227
+ await removeEntryMeta(vault, key);
228
+ }
229
+ /**
230
+ * Remove every wallet for an agent. Use during agent deletion.
231
+ */
232
+ export async function removeAllAgentWallets(vault, agentId) {
233
+ const wallets = await listAgentWallets(vault, agentId);
234
+ for (const w of wallets) {
235
+ await removeAgentWallet(vault, agentId, w.chain);
236
+ }
237
+ }
238
+ // Internal helpers — exported for tests only.
239
+ export const __test__ = {
240
+ walletKey,
241
+ agentPrefix,
242
+ parseAgentWalletKey,
243
+ deriveAddressFor,
244
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"eliza-plugin.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/runtime/eliza-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAiB,MAAM,EAAgB,MAAM,eAAe,CAAC;AAkHzE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,CA0MpE"}
1
+ {"version":3,"file":"eliza-plugin.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/runtime/eliza-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAiB,MAAM,EAAgB,MAAM,eAAe,CAAC;AAmHzE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,CA2MpE"}
@@ -6,6 +6,7 @@
6
6
  * Memory search/get actions are superseded by plugin-clipboard.
7
7
  */
8
8
  import { AgentEventService } from "@elizaos/core";
9
+ import { browserAutofillLoginAction } from "../actions/browser-autofill-login.js";
9
10
  import { browserSessionAction } from "../actions/browser-session.js";
10
11
  import { disconnectConnectorAction, listConnectorsAction, saveConnectorConfigAction, toggleConnectorAction, } from "../actions/connector-control.js";
11
12
  import { executeDatabaseQueryAction, getTableDataAction, listDatabaseTablesAction, searchVectorsAction, } from "../actions/database.js";
@@ -186,6 +187,7 @@ export function createElizaPlugin(config) {
186
187
  webSearchAction,
187
188
  extractPageAction,
188
189
  browserSessionAction,
190
+ browserAutofillLoginAction,
189
191
  launchpadLaunchAction,
190
192
  readChannelAction,
191
193
  searchConversationsAction,
@@ -1 +1 @@
1
- {"version":3,"file":"eliza.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/runtime/eliza.ts"],"names":[],"mappings":"AA8BA,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAO/B,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,EACvB,6BAA6B,EAC7B,uBAAuB,EACvB,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,yBAAyB,EACzB,iCAAiC,EACjC,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,+BAA+B,GAChC,MAAM,mBAAmB,CAAC;AAiB3B,OAAO,EACL,YAAY,EASZ,KAAK,QAAQ,EAIb,KAAK,MAAM,EAKZ,MAAM,eAAe,CAAC;AA2BvB,OAAO,EAEL,KAAK,WAAW,EAEjB,MAAM,qBAAqB,CAAC;AAuB7B,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAqQxE,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,WAAW,GACnB,IAAI,CA2IN;AAgPD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,EACxC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAgBhE;AAgMD,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,CAAC;AA4B/C;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CA+BjE;AAunBD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMzD;AA8KD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAO/D;AA8MD,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CA6NxE;AA0YD;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,WAAW,EACnB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,GAAG,SAAS,CAKpB;AA0DD,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,YAAY,CAAC,CAYvB;AAcD,eAAO,MAAM,iBAAiB,GAAI,OAAO,QAAQ,SAiChD,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,IAAI,CAAC,EAAE,iBAAiB,GACvB,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAq8CnC;AASD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,iBAAiB,GACvB,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CA8FnC"}
1
+ {"version":3,"file":"eliza.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/runtime/eliza.ts"],"names":[],"mappings":"AA+BA,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAO/B,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,EACvB,6BAA6B,EAC7B,uBAAuB,EACvB,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,yBAAyB,EACzB,iCAAiC,EACjC,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,+BAA+B,GAChC,MAAM,mBAAmB,CAAC;AAiB3B,OAAO,EACL,YAAY,EASZ,KAAK,QAAQ,EAIb,KAAK,MAAM,EAKZ,MAAM,eAAe,CAAC;AA2BvB,OAAO,EAEL,KAAK,WAAW,EAEjB,MAAM,qBAAqB,CAAC;AAuB7B,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAqQxE,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,WAAW,GACnB,IAAI,CA2IN;AAgPD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,EACxC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAgBhE;AAgMD,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,CAAC;AA4B/C;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CA+BjE;AAunBD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMzD;AA8KD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAO/D;AA8MD,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CA6NxE;AA0YD;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,WAAW,EACnB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,GAAG,SAAS,CAKpB;AA0DD,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,YAAY,CAAC,CAYvB;AAcD,eAAO,MAAM,iBAAiB,GAAI,OAAO,QAAQ,SAiChD,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,IAAI,CAAC,EAAE,iBAAiB,GACvB,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAwiDnC;AASD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,iBAAiB,GACvB,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CA8FnC"}
@@ -20,6 +20,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
20
20
  // Extracted modules — re-exported for backward compatibility
21
21
  // ---------------------------------------------------------------------------
22
22
  import { runFirstTimeSetup } from "./first-time-setup.js";
23
+ import { resolveConfigEnvForProcess } from "./operations/vault-bridge.js";
23
24
  import { resolvePlugins } from "./plugin-resolver.js";
24
25
  import { CUSTOM_PLUGINS_DIRNAME as CUSTOM_RUNTIME_PLUGINS_DIRNAME, STATIC_ELIZA_PLUGINS, } from "./plugin-types.js";
25
26
  export { CHANNEL_PLUGIN_MAP, collectPluginNames, OPTIONAL_PLUGIN_MAP, PROVIDER_PLUGIN_MAP, } from "./plugin-collector.js";
@@ -2217,7 +2218,35 @@ export async function startEliza(opts) {
2217
2218
  applyX402ConfigToEnv(config);
2218
2219
  // 2d. Propagate database config into process.env for plugin-sql
2219
2220
  applyDatabaseConfigToEnv(config);
2220
- // 2e. Propagate arbitrary env vars from config.env into process.env.
2221
+ // 2e. Boot-time vault hydration. Migrate plaintext sensitive values from
2222
+ // milady.json + config.env + sensitive process.env keys into the OS-keychain
2223
+ // vault, then resolve any vault://KEY sentinels in `config.env` so the
2224
+ // legacy hydration loop below sees real values.
2225
+ {
2226
+ const { runVaultBootstrap } = await import("@elizaos/app-core/services/vault-bootstrap");
2227
+ const { sharedVault } = await import("@elizaos/app-core/services/vault-mirror");
2228
+ const bootResult = await runVaultBootstrap();
2229
+ logger.info(`[vault-bootstrap] migrated=${bootResult.migrated} already-hydrated=${bootResult.alreadyHydrated} failed=${bootResult.failed.length}`);
2230
+ const { resolved, missing } = await resolveConfigEnvForProcess(config.env, sharedVault());
2231
+ if (missing.length > 0) {
2232
+ logger.warn(`[vault-bootstrap] sentinel(s) without vault entry: ${missing.join(", ")}`);
2233
+ }
2234
+ if (config.env &&
2235
+ typeof config.env === "object" &&
2236
+ !Array.isArray(config.env)) {
2237
+ for (const [key, value] of Object.entries(resolved)) {
2238
+ config.env[key] = value;
2239
+ }
2240
+ }
2241
+ const varsBag = config.env?.vars;
2242
+ if (varsBag && typeof varsBag === "object" && !Array.isArray(varsBag)) {
2243
+ const varsResult = await resolveConfigEnvForProcess(varsBag, sharedVault());
2244
+ for (const [key, value] of Object.entries(varsResult.resolved)) {
2245
+ varsBag[key] = value;
2246
+ }
2247
+ }
2248
+ }
2249
+ // 2f. Propagate arbitrary env vars from config.env into process.env.
2221
2250
  // Eliza stores user-defined env vars (plugin settings, API URLs, etc.)
2222
2251
  // in config.env; elizaOS plugins read them via process.env / getSetting.
2223
2252
  // Skip ELIZAOS_CLOUD_* — applyCloudConfigToEnv() owns those; otherwise a
@@ -2338,6 +2367,43 @@ export async function startEliza(opts) {
2338
2367
  });
2339
2368
  // 5. Create the Eliza bridge plugin (workspace context + session keys + compaction)
2340
2369
  const agentId = character.name?.toLowerCase().replace(/\s+/g, "-") ?? "main";
2370
+ // 5-pre0. Apply per-agent vault profile overrides to process.env.
2371
+ //
2372
+ // Vault keys with multiple named profiles (work / personal / throwaway)
2373
+ // resolve the active profile for THIS agent through the vault's
2374
+ // routing layer, then write the resolved value into process.env so
2375
+ // the synchronous runtime.getSetting fast path picks it up. Idempotent;
2376
+ // safe to run multiple times. Opt-out via
2377
+ // MILADY_DISABLE_VAULT_PROFILE_RESOLVER=1.
2378
+ if (process.env.MILADY_DISABLE_VAULT_PROFILE_RESOLVER !== "1") {
2379
+ try {
2380
+ const { sharedVault } = await import("@elizaos/app-core/services/vault-mirror");
2381
+ const { applyVaultProfilesForAgent } = await import("./vault-profile-resolver.js");
2382
+ await applyVaultProfilesForAgent(sharedVault(), agentId);
2383
+ }
2384
+ catch (err) {
2385
+ logger.warn(`[vault-profile-resolver] boot-time apply failed agent="${agentId}": ${err instanceof Error ? err.message : String(err)}`);
2386
+ }
2387
+ }
2388
+ // 5-pre. Ensure each agent has its own EVM + Solana keypair in the vault.
2389
+ // The runtime-wide EVM_PRIVATE_KEY / SOLANA_PRIVATE_KEY (process.env) is
2390
+ // the *user* wallet; per-agent wallets live inside the encrypted vault and
2391
+ // are surfaced separately in the in-app browser. Idempotent — existing
2392
+ // wallets are preserved. Opt-out via MILADY_DISABLE_AGENT_WALLET_BOOTSTRAP=1.
2393
+ if (process.env.MILADY_DISABLE_AGENT_WALLET_BOOTSTRAP !== "1") {
2394
+ try {
2395
+ const { sharedVault } = await import("@elizaos/app-core/services/vault-mirror");
2396
+ const { ensureAgentWallets } = await import("./agent-wallets.js");
2397
+ const descriptors = await ensureAgentWallets(sharedVault(), agentId, "agent-bootstrap");
2398
+ const summary = descriptors
2399
+ .map((d) => `${d.chain}:${d.address}`)
2400
+ .join(" ");
2401
+ logger.info(`[agent-wallets] agent="${agentId}" wallets ready (${summary})`);
2402
+ }
2403
+ catch (err) {
2404
+ logger.warn(`[agent-wallets] failed to ensure wallets for agent="${agentId}": ${err instanceof Error ? err.message : String(err)}`);
2405
+ }
2406
+ }
2341
2407
  // 5a. If cloud is configured and no local GitHub token, try fetching from cloud
2342
2408
  await autoFetchCloudGithubToken(config.cloud?.agentId?.trim() || agentId);
2343
2409
  // 5b. Pump N8N_HOST + N8N_API_KEY into process.env for
@@ -13,5 +13,5 @@ export { DefaultRuntimeOperationManager, type DefaultRuntimeOperationManagerOpti
13
13
  export { createHotStrategy, type HotStrategyDeps } from "./reload-hot.js";
14
14
  export { FilesystemRuntimeOperationRepository, getDefaultRepository, } from "./repository.js";
15
15
  export * from "./types.js";
16
- export { _resetDefaultSecretsManagerForTesting, defaultSecretsManager, persistProviderApiKey, resolveProviderApiKey, vaultKeyForProviderApiKey, } from "./vault-bridge.js";
16
+ export { _resetDefaultSecretsManagerForTesting, defaultSecretsManager, formatVaultRef, isVaultRef, parseVaultRef, persistProviderApiKey, resolveConfigEnvForProcess, resolveProviderApiKey, type VaultLike, vaultKeyForProviderApiKey, } from "./vault-bridge.js";
17
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../agent/src/runtime/operations/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,KAAK,eAAe,EACpB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,8BAA8B,EAC9B,KAAK,qCAAqC,EAC1C,KAAK,gBAAgB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EACL,oCAAoC,EACpC,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,qCAAqC,EACrC,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../agent/src/runtime/operations/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,KAAK,eAAe,EACpB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,8BAA8B,EAC9B,KAAK,qCAAqC,EAC1C,KAAK,gBAAgB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EACL,oCAAoC,EACpC,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,qCAAqC,EACrC,qBAAqB,EACrB,cAAc,EACd,UAAU,EACV,aAAa,EACb,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,KAAK,SAAS,EACd,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC"}
@@ -12,4 +12,4 @@ export { DefaultRuntimeOperationManager, } from "./manager.js";
12
12
  export { createHotStrategy } from "./reload-hot.js";
13
13
  export { FilesystemRuntimeOperationRepository, getDefaultRepository, } from "./repository.js";
14
14
  export * from "./types.js";
15
- export { _resetDefaultSecretsManagerForTesting, defaultSecretsManager, persistProviderApiKey, resolveProviderApiKey, vaultKeyForProviderApiKey, } from "./vault-bridge.js";
15
+ export { _resetDefaultSecretsManagerForTesting, defaultSecretsManager, formatVaultRef, isVaultRef, parseVaultRef, persistProviderApiKey, resolveConfigEnvForProcess, resolveProviderApiKey, vaultKeyForProviderApiKey, } from "./vault-bridge.js";
@@ -13,12 +13,33 @@
13
13
  * SecretsManager (tests), or call `defaultSecretsManager()` (production)
14
14
  * which constructs a fresh manager backed by the OS-keychain vault.
15
15
  */
16
- import { type SecretsManager } from "@elizaos/vault";
16
+ import { type SecretsManager, type Vault } from "@elizaos/vault";
17
17
  import type { OperationErrorCode } from "./types.js";
18
18
  export declare class VaultResolveError extends Error {
19
19
  readonly code: OperationErrorCode;
20
20
  constructor(apiKeyRef: string, cause: unknown);
21
21
  }
22
+ /** Format a stable vault key into the `vault://<key>` sentinel form. */
23
+ export declare function formatVaultRef(key: string): string;
24
+ /** Type guard: true when `value` is a `vault://<key>` sentinel string. */
25
+ export declare function isVaultRef(value: unknown): value is string;
26
+ /** Extract the underlying vault key from a sentinel; null if malformed. */
27
+ export declare function parseVaultRef(value: string): string | null;
28
+ /** Narrow surface of `Vault` used by the boot resolver — easier to stub. */
29
+ export type VaultLike = Pick<Vault, "get" | "has">;
30
+ /**
31
+ * Walk an env-shaped record and replace `vault://<key>` sentinels with the
32
+ * resolved vault values. Non-sentinel strings are passed through unchanged;
33
+ * non-string values are dropped (process.env only accepts strings).
34
+ *
35
+ * Returns `missing` for sentinel keys the vault does not contain — callers
36
+ * should warn but continue (the legacy hydrate-from-config-env path will run
37
+ * next and may still backfill from non-sentinel sources).
38
+ */
39
+ export declare function resolveConfigEnvForProcess(envBag: Record<string, unknown> | undefined, vault: VaultLike): Promise<{
40
+ resolved: Record<string, string>;
41
+ missing: string[];
42
+ }>;
22
43
  /** Stable vault key for a provider API key. */
23
44
  export declare function vaultKeyForProviderApiKey(normalizedProvider: string): string;
24
45
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"vault-bridge.d.ts","sourceRoot":"","sources":["../../../../../../../agent/src/runtime/operations/vault-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAA0B;gBAE/C,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAQ9C;AAED,+CAA+C;AAC/C,wBAAgB,yBAAyB,CAAC,kBAAkB,EAAE,MAAM,GAAG,MAAM,CAO5E;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,OAAO,EAAE,cAAc,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAOlB;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,OAAO,EAAE,cAAc,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAO9B;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,cAAc,CAGtD;AAED,0CAA0C;AAC1C,wBAAgB,qCAAqC,IAAI,IAAI,CAE5D"}
1
+ {"version":3,"file":"vault-bridge.d.ts","sourceRoot":"","sources":["../../../../../../../agent/src/runtime/operations/vault-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAiB,KAAK,cAAc,EAAE,KAAK,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAA0B;gBAE/C,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAQ9C;AAKD,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAM1D;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG1D;AAED,4EAA4E;AAC5E,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC;AAEnD;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,KAAK,EAAE,SAAS,GACf,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAqBlE;AAED,+CAA+C;AAC/C,wBAAgB,yBAAyB,CAAC,kBAAkB,EAAE,MAAM,GAAG,MAAM,CAO5E;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,OAAO,EAAE,cAAc,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAOlB;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,OAAO,EAAE,cAAc,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAO9B;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,cAAc,CAGtD;AAED,0CAA0C;AAC1C,wBAAgB,qCAAqC,IAAI,IAAI,CAE5D"}
@@ -21,6 +21,59 @@ export class VaultResolveError extends Error {
21
21
  this.name = "VaultResolveError";
22
22
  }
23
23
  }
24
+ /** Sentinel prefix marking a config value that resolves through the vault. */
25
+ const VAULT_REF_PREFIX = "vault://";
26
+ /** Format a stable vault key into the `vault://<key>` sentinel form. */
27
+ export function formatVaultRef(key) {
28
+ if (typeof key !== "string" || key.length === 0) {
29
+ throw new TypeError(`[runtime-ops:vault] formatVaultRef requires a non-empty key`);
30
+ }
31
+ return `${VAULT_REF_PREFIX}${key}`;
32
+ }
33
+ /** Type guard: true when `value` is a `vault://<key>` sentinel string. */
34
+ export function isVaultRef(value) {
35
+ return (typeof value === "string" &&
36
+ value.startsWith(VAULT_REF_PREFIX) &&
37
+ value.length > VAULT_REF_PREFIX.length);
38
+ }
39
+ /** Extract the underlying vault key from a sentinel; null if malformed. */
40
+ export function parseVaultRef(value) {
41
+ if (!isVaultRef(value))
42
+ return null;
43
+ return value.slice(VAULT_REF_PREFIX.length);
44
+ }
45
+ /**
46
+ * Walk an env-shaped record and replace `vault://<key>` sentinels with the
47
+ * resolved vault values. Non-sentinel strings are passed through unchanged;
48
+ * non-string values are dropped (process.env only accepts strings).
49
+ *
50
+ * Returns `missing` for sentinel keys the vault does not contain — callers
51
+ * should warn but continue (the legacy hydrate-from-config-env path will run
52
+ * next and may still backfill from non-sentinel sources).
53
+ */
54
+ export async function resolveConfigEnvForProcess(envBag, vault) {
55
+ const resolved = {};
56
+ const missing = [];
57
+ if (!envBag)
58
+ return { resolved, missing };
59
+ for (const [envKey, value] of Object.entries(envBag)) {
60
+ if (typeof value !== "string")
61
+ continue;
62
+ if (!isVaultRef(value)) {
63
+ resolved[envKey] = value;
64
+ continue;
65
+ }
66
+ const vaultKey = parseVaultRef(value);
67
+ if (!vaultKey)
68
+ continue;
69
+ if (!(await vault.has(vaultKey))) {
70
+ missing.push(vaultKey);
71
+ continue;
72
+ }
73
+ resolved[envKey] = await vault.get(vaultKey);
74
+ }
75
+ return { resolved, missing };
76
+ }
24
77
  /** Stable vault key for a provider API key. */
25
78
  export function vaultKeyForProviderApiKey(normalizedProvider) {
26
79
  if (!normalizedProvider || normalizedProvider.includes(".")) {
@@ -1,5 +1,5 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
- import { resolveActionContexts, resolveProviderContexts, } from "../../../typescript/src/utils/context-catalog.js";
2
+ import { resolveActionContexts, resolveProviderContexts, } from "@elizaos/core";
3
3
  const pluginRegistrationContext = new AsyncLocalStorage();
4
4
  const pluginServiceStartContext = new AsyncLocalStorage();
5
5
  const serviceClassOwners = new WeakMap();
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Per-agent vault profile resolver.
3
+ *
4
+ * Walks every vault entry that has profile metadata, asks the vault's
5
+ * routing layer which profile applies for the current agent, and pumps
6
+ * the resolved value into `process.env[KEY]`. Runtime hot paths read
7
+ * env vars synchronously (`process.env.OPENROUTER_API_KEY`, etc.), so
8
+ * we resolve once at agent boot rather than instrumenting every call
9
+ * site.
10
+ *
11
+ * Scope: this is the minimum-viable wiring per the spec —
12
+ * - Only `agent` scope rules apply; the runtime knows agentId.
13
+ * - `app` and `skill` scope rules are persisted but not yet
14
+ * resolved here (no call site has the context).
15
+ *
16
+ * Idempotent: re-running for the same agent overwrites with the same
17
+ * value. Opt-out via `MILADY_DISABLE_VAULT_PROFILE_RESOLVER=1`.
18
+ */
19
+ import { type Vault } from "@elizaos/vault";
20
+ export interface ResolveProfilesResult {
21
+ /** Number of keys whose env value was overridden. */
22
+ readonly overridden: number;
23
+ /** Keys that had profiles but every candidate profile was empty. */
24
+ readonly skipped: ReadonlyArray<string>;
25
+ /** Keys where resolution failed (vault read error). */
26
+ readonly failed: ReadonlyArray<string>;
27
+ }
28
+ /**
29
+ * For each inventory entry that has `hasProfiles === true`, resolve
30
+ * the active value for `agentId` and write it into `process.env[KEY]`.
31
+ *
32
+ * Keys without profiles are left alone — `process.env` already holds
33
+ * whatever the legacy hydration path put there (config.env, milady.json,
34
+ * direct env). This resolver is purely additive.
35
+ */
36
+ export declare function applyVaultProfilesForAgent(vault: Vault, agentId: string): Promise<ResolveProfilesResult>;
37
+ //# sourceMappingURL=vault-profile-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-profile-resolver.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/runtime/vault-profile-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAGL,KAAK,KAAK,EAEX,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,qBAAqB;IACpC,qDAAqD;IACrD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC,uDAAuD;IACvD,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACxC;AAED;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,qBAAqB,CAAC,CAsDhC"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Per-agent vault profile resolver.
3
+ *
4
+ * Walks every vault entry that has profile metadata, asks the vault's
5
+ * routing layer which profile applies for the current agent, and pumps
6
+ * the resolved value into `process.env[KEY]`. Runtime hot paths read
7
+ * env vars synchronously (`process.env.OPENROUTER_API_KEY`, etc.), so
8
+ * we resolve once at agent boot rather than instrumenting every call
9
+ * site.
10
+ *
11
+ * Scope: this is the minimum-viable wiring per the spec —
12
+ * - Only `agent` scope rules apply; the runtime knows agentId.
13
+ * - `app` and `skill` scope rules are persisted but not yet
14
+ * resolved here (no call site has the context).
15
+ *
16
+ * Idempotent: re-running for the same agent overwrites with the same
17
+ * value. Opt-out via `MILADY_DISABLE_VAULT_PROFILE_RESOLVER=1`.
18
+ */
19
+ import { logger } from "@elizaos/core";
20
+ import { listVaultInventory, resolveActiveValue, } from "@elizaos/vault";
21
+ /**
22
+ * For each inventory entry that has `hasProfiles === true`, resolve
23
+ * the active value for `agentId` and write it into `process.env[KEY]`.
24
+ *
25
+ * Keys without profiles are left alone — `process.env` already holds
26
+ * whatever the legacy hydration path put there (config.env, milady.json,
27
+ * direct env). This resolver is purely additive.
28
+ */
29
+ export async function applyVaultProfilesForAgent(vault, agentId) {
30
+ if (process.env.MILADY_DISABLE_VAULT_PROFILE_RESOLVER === "1") {
31
+ return { overridden: 0, skipped: [], failed: [] };
32
+ }
33
+ let entries;
34
+ try {
35
+ entries = await listVaultInventory(vault);
36
+ }
37
+ catch (err) {
38
+ logger.warn(`[vault-profile-resolver] inventory listing failed for agent="${agentId}": ${err instanceof Error ? err.message : String(err)}`);
39
+ return { overridden: 0, skipped: [], failed: [] };
40
+ }
41
+ let overridden = 0;
42
+ const skipped = [];
43
+ const failed = [];
44
+ for (const entry of entries) {
45
+ if (!entry.hasProfiles)
46
+ continue;
47
+ if (entry.kind === "reference") {
48
+ // Reference entries resolve through their backing password
49
+ // manager, not through profiles. Skip — but only after auditing
50
+ // we'd actually have a profile blob to read.
51
+ continue;
52
+ }
53
+ try {
54
+ const value = await resolveActiveValue(vault, entry.key, { agentId });
55
+ if (typeof value !== "string" || value.length === 0) {
56
+ skipped.push(entry.key);
57
+ continue;
58
+ }
59
+ process.env[entry.key] = value;
60
+ overridden += 1;
61
+ }
62
+ catch (err) {
63
+ // resolveActiveValue throws when no profile and no bare value
64
+ // resolves. Don't try to fall back to legacy env — the user
65
+ // explicitly declared profiles for this key, so an unresolvable
66
+ // active profile is a real failure they should see.
67
+ failed.push(entry.key);
68
+ logger.warn(`[vault-profile-resolver] failed to resolve agent="${agentId}" key="${entry.key}": ${err instanceof Error ? err.message : String(err)}`);
69
+ }
70
+ }
71
+ if (overridden > 0 || failed.length > 0) {
72
+ logger.info(`[vault-profile-resolver] agent="${agentId}" overridden=${overridden} skipped=${skipped.length} failed=${failed.length}`);
73
+ }
74
+ return { overridden, skipped: Object.freeze(skipped), failed: Object.freeze(failed) };
75
+ }
@@ -94,6 +94,7 @@ declare module "./client-base" {
94
94
  }>;
95
95
  getAuthStatus(): Promise<{
96
96
  required: boolean;
97
+ authenticated?: boolean;
97
98
  loginRequired?: boolean;
98
99
  bootstrapRequired?: boolean;
99
100
  localAccess?: boolean;