@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.
- package/package.json +1 -1
- package/packages/agent/src/actions/browser-autofill-login.d.ts +36 -0
- package/packages/agent/src/actions/browser-autofill-login.d.ts.map +1 -0
- package/packages/agent/src/actions/browser-autofill-login.js +347 -0
- package/packages/agent/src/api/experience-routes.d.ts.map +1 -1
- package/packages/agent/src/api/experience-routes.js +40 -2
- package/packages/agent/src/api/static-file-server.d.ts +2 -2
- package/packages/agent/src/api/static-file-server.d.ts.map +1 -1
- package/packages/agent/src/api/static-file-server.js +4 -2
- package/packages/agent/src/runtime/agent-wallets.d.ts +103 -0
- package/packages/agent/src/runtime/agent-wallets.d.ts.map +1 -0
- package/packages/agent/src/runtime/agent-wallets.js +244 -0
- package/packages/agent/src/runtime/eliza-plugin.d.ts.map +1 -1
- package/packages/agent/src/runtime/eliza-plugin.js +2 -0
- package/packages/agent/src/runtime/eliza.d.ts.map +1 -1
- package/packages/agent/src/runtime/eliza.js +67 -1
- package/packages/agent/src/runtime/operations/index.d.ts +1 -1
- package/packages/agent/src/runtime/operations/index.d.ts.map +1 -1
- package/packages/agent/src/runtime/operations/index.js +1 -1
- package/packages/agent/src/runtime/operations/vault-bridge.d.ts +22 -1
- package/packages/agent/src/runtime/operations/vault-bridge.d.ts.map +1 -1
- package/packages/agent/src/runtime/operations/vault-bridge.js +53 -0
- package/packages/agent/src/runtime/plugin-lifecycle.js +1 -1
- package/packages/agent/src/runtime/vault-profile-resolver.d.ts +37 -0
- package/packages/agent/src/runtime/vault-profile-resolver.d.ts.map +1 -0
- package/packages/agent/src/runtime/vault-profile-resolver.js +75 -0
- package/packages/app-core/src/api/client-agent.d.ts +1 -0
- package/packages/app-core/src/api/client-agent.d.ts.map +1 -1
- package/packages/app-core/src/api/client-base.d.ts.map +1 -1
- package/packages/app-core/src/api/client-base.js +11 -2
- package/packages/app-core/src/api/client-vault.d.ts +53 -0
- package/packages/app-core/src/api/client-vault.d.ts.map +1 -0
- package/packages/app-core/src/api/client-vault.js +48 -0
- package/packages/app-core/src/api/client.d.ts +1 -0
- package/packages/app-core/src/api/client.d.ts.map +1 -1
- package/packages/app-core/src/api/client.js +1 -0
- package/packages/app-core/src/registry/index.d.ts +7 -0
- package/packages/app-core/src/registry/index.d.ts.map +1 -0
- package/packages/app-core/src/registry/index.js +43 -0
- package/packages/app-core/src/registry/legacy-adapter.d.ts +32 -0
- package/packages/app-core/src/registry/legacy-adapter.d.ts.map +1 -0
- package/packages/app-core/src/registry/legacy-adapter.js +101 -0
- package/packages/app-core/src/registry/loader.d.ts +27 -0
- package/packages/app-core/src/registry/loader.d.ts.map +1 -0
- package/packages/app-core/src/registry/loader.js +111 -0
- package/packages/app-core/src/registry/schema.d.ts +986 -0
- package/packages/app-core/src/registry/schema.d.ts.map +1 -0
- package/packages/app-core/src/registry/schema.js +250 -0
- package/packages/app-core/src/services/vault-bootstrap.d.ts +31 -0
- package/packages/app-core/src/services/vault-bootstrap.d.ts.map +1 -0
- package/packages/app-core/src/services/vault-bootstrap.js +245 -0
- package/packages/app-core/src/services/vault-mirror.d.ts +44 -0
- package/packages/app-core/src/services/vault-mirror.d.ts.map +1 -0
- package/packages/app-core/src/services/vault-mirror.js +80 -0
package/package.json
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BROWSER_AUTOFILL_LOGIN — agent-driven browser login autofill.
|
|
3
|
+
*
|
|
4
|
+
* Lets the agent say "log into github.com for me" and have the saved
|
|
5
|
+
* credentials filled into an open Milady browser tab without a per-call
|
|
6
|
+
* consent prompt.
|
|
7
|
+
*
|
|
8
|
+
* Authorization model (mirrors the user-driven autofill flow):
|
|
9
|
+
* - The user must have set `creds.<domain>.:autoallow = "1"` on the
|
|
10
|
+
* domain. This is the same vault key the React-side consent flow
|
|
11
|
+
* uses; toggling it from Settings -> Vault -> Logins is the
|
|
12
|
+
* SOLE way to let the agent autofill silently.
|
|
13
|
+
* - Without that flag, this action returns
|
|
14
|
+
* `{ ok: false, reason: "user has not pre-authorized agent autofill for <domain>" }`.
|
|
15
|
+
* The agent should NOT fall back to the user-driven flow on its own
|
|
16
|
+
* because the user-driven flow is gated by an interactive React
|
|
17
|
+
* modal that an autonomous agent cannot consent to.
|
|
18
|
+
*
|
|
19
|
+
* Tab selection:
|
|
20
|
+
* - Lists the live browser-workspace tabs and picks the first one
|
|
21
|
+
* whose URL hostname matches `domain` (registrable hostname,
|
|
22
|
+
* case-insensitive). Returns a clean error when no such tab exists
|
|
23
|
+
* so the agent can decide whether to open one first via
|
|
24
|
+
* BROWSER_SESSION.
|
|
25
|
+
*
|
|
26
|
+
* Fill mechanism:
|
|
27
|
+
* - Injects a small JS snippet that mirrors the same form-detection
|
|
28
|
+
* and `setNativeInputValue` helpers the in-tab preload uses, so
|
|
29
|
+
* React-controlled inputs see the change.
|
|
30
|
+
* - When `submit: true`, the snippet also calls `form.submit()` (or
|
|
31
|
+
* clicks a likely submit button) after filling. Off by default —
|
|
32
|
+
* the safer behaviour is fill-only and let the user click submit.
|
|
33
|
+
*/
|
|
34
|
+
import type { Action } from "@elizaos/core";
|
|
35
|
+
export declare const browserAutofillLoginAction: Action;
|
|
36
|
+
//# sourceMappingURL=browser-autofill-login.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-autofill-login.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/actions/browser-autofill-login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EACV,MAAM,EAKP,MAAM,eAAe,CAAC;AA2GvB,eAAO,MAAM,0BAA0B,EAAE,MA8PxC,CAAC"}
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BROWSER_AUTOFILL_LOGIN — agent-driven browser login autofill.
|
|
3
|
+
*
|
|
4
|
+
* Lets the agent say "log into github.com for me" and have the saved
|
|
5
|
+
* credentials filled into an open Milady browser tab without a per-call
|
|
6
|
+
* consent prompt.
|
|
7
|
+
*
|
|
8
|
+
* Authorization model (mirrors the user-driven autofill flow):
|
|
9
|
+
* - The user must have set `creds.<domain>.:autoallow = "1"` on the
|
|
10
|
+
* domain. This is the same vault key the React-side consent flow
|
|
11
|
+
* uses; toggling it from Settings -> Vault -> Logins is the
|
|
12
|
+
* SOLE way to let the agent autofill silently.
|
|
13
|
+
* - Without that flag, this action returns
|
|
14
|
+
* `{ ok: false, reason: "user has not pre-authorized agent autofill for <domain>" }`.
|
|
15
|
+
* The agent should NOT fall back to the user-driven flow on its own
|
|
16
|
+
* because the user-driven flow is gated by an interactive React
|
|
17
|
+
* modal that an autonomous agent cannot consent to.
|
|
18
|
+
*
|
|
19
|
+
* Tab selection:
|
|
20
|
+
* - Lists the live browser-workspace tabs and picks the first one
|
|
21
|
+
* whose URL hostname matches `domain` (registrable hostname,
|
|
22
|
+
* case-insensitive). Returns a clean error when no such tab exists
|
|
23
|
+
* so the agent can decide whether to open one first via
|
|
24
|
+
* BROWSER_SESSION.
|
|
25
|
+
*
|
|
26
|
+
* Fill mechanism:
|
|
27
|
+
* - Injects a small JS snippet that mirrors the same form-detection
|
|
28
|
+
* and `setNativeInputValue` helpers the in-tab preload uses, so
|
|
29
|
+
* React-controlled inputs see the change.
|
|
30
|
+
* - When `submit: true`, the snippet also calls `form.submit()` (or
|
|
31
|
+
* clicks a likely submit button) after filling. Off by default —
|
|
32
|
+
* the safer behaviour is fill-only and let the user click submit.
|
|
33
|
+
*/
|
|
34
|
+
import { logger } from "@elizaos/core";
|
|
35
|
+
import { getAutofillAllowed, getSavedLogin, listSavedLogins, } from "@elizaos/vault";
|
|
36
|
+
import { hasOwnerAccess } from "../security/access.js";
|
|
37
|
+
import { evaluateBrowserWorkspaceTab, isBrowserWorkspaceBridgeConfigured, listBrowserWorkspaceTabs, } from "../services/browser-workspace.js";
|
|
38
|
+
function tabUrlMatchesDomain(tabUrl, domain) {
|
|
39
|
+
if (!tabUrl)
|
|
40
|
+
return false;
|
|
41
|
+
let hostname;
|
|
42
|
+
try {
|
|
43
|
+
hostname = new URL(tabUrl).hostname;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return hostname.toLowerCase() === domain.toLowerCase();
|
|
49
|
+
}
|
|
50
|
+
function buildAutofillScript(args) {
|
|
51
|
+
// Inline snippet — runs in the OOPIF (the page's content world) via
|
|
52
|
+
// electrobun tab eval. Uses setNativeInputValue to bypass React's
|
|
53
|
+
// value-setter override.
|
|
54
|
+
return `
|
|
55
|
+
(() => {
|
|
56
|
+
const USERNAME = ${JSON.stringify(args.username)};
|
|
57
|
+
const PASSWORD = ${JSON.stringify(args.password)};
|
|
58
|
+
const SUBMIT = ${args.submit ? "true" : "false"};
|
|
59
|
+
|
|
60
|
+
function setNativeInputValue(input, value) {
|
|
61
|
+
const proto = Object.getPrototypeOf(input);
|
|
62
|
+
const desc = Object.getOwnPropertyDescriptor(proto, "value");
|
|
63
|
+
if (desc && typeof desc.set === "function") {
|
|
64
|
+
desc.set.call(input, value);
|
|
65
|
+
} else {
|
|
66
|
+
input.value = value;
|
|
67
|
+
}
|
|
68
|
+
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
69
|
+
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function findPrecedingTextInput(passwordInput) {
|
|
73
|
+
const root = passwordInput.form || document.body;
|
|
74
|
+
const candidates = root.querySelectorAll(
|
|
75
|
+
'input[type="text"], input[type="email"], input:not([type])'
|
|
76
|
+
);
|
|
77
|
+
let lastBefore = null;
|
|
78
|
+
for (const el of candidates) {
|
|
79
|
+
if (el.compareDocumentPosition(passwordInput) & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
80
|
+
lastBefore = el;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return lastBefore;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const password = document.querySelector('input[type="password"]');
|
|
87
|
+
if (!password) {
|
|
88
|
+
return { ok: false, reason: "no_password_input" };
|
|
89
|
+
}
|
|
90
|
+
const form = password.form;
|
|
91
|
+
const username =
|
|
92
|
+
(form && form.querySelector(
|
|
93
|
+
'input[type="email"], input[name*="user" i], input[name*="email" i], input[name*="login" i]'
|
|
94
|
+
)) || findPrecedingTextInput(password);
|
|
95
|
+
|
|
96
|
+
if (username) setNativeInputValue(username, USERNAME);
|
|
97
|
+
setNativeInputValue(password, PASSWORD);
|
|
98
|
+
|
|
99
|
+
if (SUBMIT) {
|
|
100
|
+
if (form && typeof form.requestSubmit === "function") {
|
|
101
|
+
form.requestSubmit();
|
|
102
|
+
} else if (form && typeof form.submit === "function") {
|
|
103
|
+
form.submit();
|
|
104
|
+
} else {
|
|
105
|
+
const button =
|
|
106
|
+
(form && form.querySelector('button[type="submit"], input[type="submit"]')) ||
|
|
107
|
+
document.querySelector('button[type="submit"], input[type="submit"]');
|
|
108
|
+
if (button) (button).click();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
ok: true,
|
|
114
|
+
filled: { username: !!username, password: true },
|
|
115
|
+
submitted: SUBMIT,
|
|
116
|
+
};
|
|
117
|
+
})();
|
|
118
|
+
`;
|
|
119
|
+
}
|
|
120
|
+
export const browserAutofillLoginAction = {
|
|
121
|
+
name: "BROWSER_AUTOFILL_LOGIN",
|
|
122
|
+
similes: [
|
|
123
|
+
"AGENT_AUTOFILL",
|
|
124
|
+
"AUTOFILL_BROWSER_LOGIN",
|
|
125
|
+
"AUTOFILL_LOGIN",
|
|
126
|
+
"FILL_BROWSER_CREDENTIALS",
|
|
127
|
+
"LOG_INTO_SITE",
|
|
128
|
+
"SIGN_IN_TO_SITE",
|
|
129
|
+
],
|
|
130
|
+
description: "Autofill saved credentials into an open Milady browser tab for the requested domain. Requires the user to have pre-authorized agent autofill for the domain via Settings -> Vault -> Logins (`creds.<domain>.:autoallow = 1`).",
|
|
131
|
+
validate: async (runtime, message, _state) => {
|
|
132
|
+
return hasOwnerAccess(runtime, message);
|
|
133
|
+
},
|
|
134
|
+
handler: async (runtime, message, _state, options) => {
|
|
135
|
+
if (!(await hasOwnerAccess(runtime, message))) {
|
|
136
|
+
return {
|
|
137
|
+
text: "Permission denied: only the owner may run BROWSER_AUTOFILL_LOGIN.",
|
|
138
|
+
success: false,
|
|
139
|
+
values: { success: false, error: "PERMISSION_DENIED" },
|
|
140
|
+
data: { actionName: "BROWSER_AUTOFILL_LOGIN" },
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
const params = options?.parameters;
|
|
144
|
+
const domain = params?.domain?.trim().toLowerCase() ?? "";
|
|
145
|
+
const requestedUsername = params?.username?.trim();
|
|
146
|
+
const submit = params?.submit === true;
|
|
147
|
+
if (!domain) {
|
|
148
|
+
return {
|
|
149
|
+
text: "BROWSER_AUTOFILL_LOGIN requires a `domain` parameter.",
|
|
150
|
+
success: false,
|
|
151
|
+
values: {
|
|
152
|
+
success: false,
|
|
153
|
+
error: "BROWSER_AUTOFILL_LOGIN_BAD_PARAMS",
|
|
154
|
+
},
|
|
155
|
+
data: { actionName: "BROWSER_AUTOFILL_LOGIN" },
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
if (!isBrowserWorkspaceBridgeConfigured(process.env)) {
|
|
159
|
+
return {
|
|
160
|
+
text: "BROWSER_AUTOFILL_LOGIN requires the desktop browser workspace bridge.",
|
|
161
|
+
success: false,
|
|
162
|
+
values: {
|
|
163
|
+
success: false,
|
|
164
|
+
error: "BROWSER_BRIDGE_UNAVAILABLE",
|
|
165
|
+
},
|
|
166
|
+
data: { actionName: "BROWSER_AUTOFILL_LOGIN" },
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
// Resolve the shared vault via dynamic import — the agent package
|
|
170
|
+
// doesn't directly depend on @elizaos/app-core to avoid a circular
|
|
171
|
+
// graph; the runtime bootstraps app-core before any action runs.
|
|
172
|
+
const { sharedVault } = (await import("@elizaos/app-core/services/vault-mirror"));
|
|
173
|
+
const vault = sharedVault();
|
|
174
|
+
// ── Authorization gate: per-domain autoallow flag ─────────────
|
|
175
|
+
const allowed = await getAutofillAllowed(vault, domain);
|
|
176
|
+
if (!allowed) {
|
|
177
|
+
const text = `User has not pre-authorized agent autofill for ${domain}. Toggle "Allow agent to autofill" for this domain under Settings -> Vault -> Logins.`;
|
|
178
|
+
return {
|
|
179
|
+
text,
|
|
180
|
+
success: false,
|
|
181
|
+
values: {
|
|
182
|
+
success: false,
|
|
183
|
+
error: "AGENT_AUTOFILL_NOT_AUTHORIZED",
|
|
184
|
+
domain,
|
|
185
|
+
},
|
|
186
|
+
data: { actionName: "BROWSER_AUTOFILL_LOGIN", domain, reason: text },
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
// ── Look up credentials ──────────────────────────────────────
|
|
190
|
+
let savedLogin = null;
|
|
191
|
+
if (requestedUsername) {
|
|
192
|
+
savedLogin = await getSavedLogin(vault, domain, requestedUsername);
|
|
193
|
+
if (!savedLogin) {
|
|
194
|
+
return {
|
|
195
|
+
text: `No saved login for ${requestedUsername} on ${domain}.`,
|
|
196
|
+
success: false,
|
|
197
|
+
values: {
|
|
198
|
+
success: false,
|
|
199
|
+
error: "AGENT_AUTOFILL_NO_LOGIN",
|
|
200
|
+
domain,
|
|
201
|
+
username: requestedUsername,
|
|
202
|
+
},
|
|
203
|
+
data: { actionName: "BROWSER_AUTOFILL_LOGIN" },
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
// No username supplied — pick the most recently modified entry.
|
|
209
|
+
const summaries = await listSavedLogins(vault, domain);
|
|
210
|
+
if (summaries.length === 0) {
|
|
211
|
+
return {
|
|
212
|
+
text: `No saved logins for ${domain}.`,
|
|
213
|
+
success: false,
|
|
214
|
+
values: {
|
|
215
|
+
success: false,
|
|
216
|
+
error: "AGENT_AUTOFILL_NO_LOGIN",
|
|
217
|
+
domain,
|
|
218
|
+
},
|
|
219
|
+
data: { actionName: "BROWSER_AUTOFILL_LOGIN" },
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
const sorted = [...summaries].sort((a, b) => b.lastModified - a.lastModified);
|
|
223
|
+
const chosen = sorted[0];
|
|
224
|
+
if (!chosen) {
|
|
225
|
+
return {
|
|
226
|
+
text: `No saved logins for ${domain}.`,
|
|
227
|
+
success: false,
|
|
228
|
+
values: {
|
|
229
|
+
success: false,
|
|
230
|
+
error: "AGENT_AUTOFILL_NO_LOGIN",
|
|
231
|
+
domain,
|
|
232
|
+
},
|
|
233
|
+
data: { actionName: "BROWSER_AUTOFILL_LOGIN" },
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
savedLogin = await getSavedLogin(vault, domain, chosen.username);
|
|
237
|
+
if (!savedLogin) {
|
|
238
|
+
return {
|
|
239
|
+
text: `Saved login ${chosen.username} on ${domain} disappeared between list and reveal.`,
|
|
240
|
+
success: false,
|
|
241
|
+
values: {
|
|
242
|
+
success: false,
|
|
243
|
+
error: "AGENT_AUTOFILL_RACE",
|
|
244
|
+
domain,
|
|
245
|
+
},
|
|
246
|
+
data: { actionName: "BROWSER_AUTOFILL_LOGIN" },
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// ── Locate the open tab ──────────────────────────────────────
|
|
251
|
+
const tabs = await listBrowserWorkspaceTabs();
|
|
252
|
+
const matchingTab = tabs.find((t) => tabUrlMatchesDomain(t.url, domain));
|
|
253
|
+
if (!matchingTab) {
|
|
254
|
+
return {
|
|
255
|
+
text: `No open browser tab on ${domain}. Open one with BROWSER_SESSION first.`,
|
|
256
|
+
success: false,
|
|
257
|
+
values: {
|
|
258
|
+
success: false,
|
|
259
|
+
error: "AGENT_AUTOFILL_NO_TAB",
|
|
260
|
+
domain,
|
|
261
|
+
},
|
|
262
|
+
data: { actionName: "BROWSER_AUTOFILL_LOGIN" },
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
// ── Inject and evaluate the autofill script ──────────────────
|
|
266
|
+
const script = buildAutofillScript({
|
|
267
|
+
username: savedLogin.username,
|
|
268
|
+
password: savedLogin.password,
|
|
269
|
+
submit,
|
|
270
|
+
});
|
|
271
|
+
const rawResult = await evaluateBrowserWorkspaceTab({
|
|
272
|
+
id: matchingTab.id,
|
|
273
|
+
script,
|
|
274
|
+
});
|
|
275
|
+
// The injected snippet returns
|
|
276
|
+
// { ok: boolean; reason?: string; filled?: { username, password }; submitted?: boolean }
|
|
277
|
+
// — narrow to the fields we surface in `values` so the action result
|
|
278
|
+
// is plain JSON.
|
|
279
|
+
const filled = rawResult &&
|
|
280
|
+
typeof rawResult === "object" &&
|
|
281
|
+
"filled" in rawResult
|
|
282
|
+
? Boolean(rawResult.filled)
|
|
283
|
+
: false;
|
|
284
|
+
const fillReason = rawResult &&
|
|
285
|
+
typeof rawResult === "object" &&
|
|
286
|
+
typeof rawResult.reason === "string"
|
|
287
|
+
? rawResult.reason
|
|
288
|
+
: null;
|
|
289
|
+
logger.info(`[browser-autofill-login] domain=${domain} tabId=${matchingTab.id} submit=${submit} filled=${filled}`);
|
|
290
|
+
return {
|
|
291
|
+
text: submit
|
|
292
|
+
? `Filled and submitted login on ${domain} (tab ${matchingTab.id}).`
|
|
293
|
+
: `Filled login on ${domain} (tab ${matchingTab.id}). User must click submit.`,
|
|
294
|
+
success: true,
|
|
295
|
+
values: {
|
|
296
|
+
success: true,
|
|
297
|
+
domain,
|
|
298
|
+
tabId: matchingTab.id,
|
|
299
|
+
submitted: submit,
|
|
300
|
+
filled,
|
|
301
|
+
...(fillReason ? { fillReason } : {}),
|
|
302
|
+
},
|
|
303
|
+
data: {
|
|
304
|
+
actionName: "BROWSER_AUTOFILL_LOGIN",
|
|
305
|
+
domain,
|
|
306
|
+
tabId: matchingTab.id,
|
|
307
|
+
filled,
|
|
308
|
+
...(fillReason ? { fillReason } : {}),
|
|
309
|
+
},
|
|
310
|
+
};
|
|
311
|
+
},
|
|
312
|
+
parameters: [
|
|
313
|
+
{
|
|
314
|
+
name: "domain",
|
|
315
|
+
description: "Registrable hostname to autofill (e.g. `github.com`, no protocol or path).",
|
|
316
|
+
required: true,
|
|
317
|
+
schema: { type: "string" },
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
name: "username",
|
|
321
|
+
description: "Specific saved login to use. When omitted, the most recently modified saved login for the domain is selected.",
|
|
322
|
+
required: false,
|
|
323
|
+
schema: { type: "string" },
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
name: "submit",
|
|
327
|
+
description: "When true, submit the form after filling. Defaults to false (fill-only).",
|
|
328
|
+
required: false,
|
|
329
|
+
schema: { type: "boolean" },
|
|
330
|
+
},
|
|
331
|
+
],
|
|
332
|
+
examples: [
|
|
333
|
+
[
|
|
334
|
+
{
|
|
335
|
+
name: "{{user1}}",
|
|
336
|
+
content: { text: "Log into github.com for me" },
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
name: "{{agentName}}",
|
|
340
|
+
content: {
|
|
341
|
+
text: "Filled login on github.com. Click submit when ready.",
|
|
342
|
+
actions: ["BROWSER_AUTOFILL_LOGIN"],
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
],
|
|
346
|
+
],
|
|
347
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"experience-routes.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/api/experience-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAQ,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"experience-routes.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/api/experience-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAQ,MAAM,eAAe,CAAC;AA0FxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAiB9D,MAAM,WAAW,sBAAuB,SAAQ,mBAAmB;IACjE,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,GAAG,CAAC;CACV;AA8ZD,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,sBAAsB,GAC1B,OAAO,CAAC,OAAO,CAAC,CAoLlB"}
|
|
@@ -1,12 +1,50 @@
|
|
|
1
|
-
|
|
1
|
+
// These enums and types are defined in @elizaos/core's advanced-capabilities
|
|
2
|
+
// experience module but not re-exported from the compiled dist bundle (tsdown
|
|
3
|
+
// tree-shakes them). Inlined here so the packaged desktop build works without
|
|
4
|
+
// a cross-package source import.
|
|
5
|
+
var ExperienceType;
|
|
6
|
+
(function (ExperienceType) {
|
|
7
|
+
ExperienceType["SUCCESS"] = "success";
|
|
8
|
+
ExperienceType["FAILURE"] = "failure";
|
|
9
|
+
ExperienceType["DISCOVERY"] = "discovery";
|
|
10
|
+
ExperienceType["CORRECTION"] = "correction";
|
|
11
|
+
ExperienceType["LEARNING"] = "learning";
|
|
12
|
+
ExperienceType["HYPOTHESIS"] = "hypothesis";
|
|
13
|
+
ExperienceType["VALIDATION"] = "validation";
|
|
14
|
+
ExperienceType["WARNING"] = "warning";
|
|
15
|
+
})(ExperienceType || (ExperienceType = {}));
|
|
16
|
+
var OutcomeType;
|
|
17
|
+
(function (OutcomeType) {
|
|
18
|
+
OutcomeType["POSITIVE"] = "positive";
|
|
19
|
+
OutcomeType["NEGATIVE"] = "negative";
|
|
20
|
+
OutcomeType["NEUTRAL"] = "neutral";
|
|
21
|
+
OutcomeType["MIXED"] = "mixed";
|
|
22
|
+
})(OutcomeType || (OutcomeType = {}));
|
|
2
23
|
const EXPERIENCE_ROUTE_PREFIXES = [
|
|
3
24
|
"/api/experiences",
|
|
4
25
|
"/api/character/experiences",
|
|
5
26
|
];
|
|
6
27
|
const EXPERIENCE_LIST_DEFAULT_LIMIT = 100;
|
|
7
28
|
const EXPERIENCE_LIST_MAX_LIMIT = 200;
|
|
29
|
+
function isExperienceService(service) {
|
|
30
|
+
if (!service || typeof service !== "object") {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const candidate = service;
|
|
34
|
+
const requiredMethods = [
|
|
35
|
+
"recordExperience",
|
|
36
|
+
"listExperiences",
|
|
37
|
+
"getExperience",
|
|
38
|
+
"updateExperience",
|
|
39
|
+
"deleteExperience",
|
|
40
|
+
"getExperienceGraph",
|
|
41
|
+
"consolidateDuplicateExperiences",
|
|
42
|
+
];
|
|
43
|
+
return requiredMethods.every((method) => typeof candidate[method] === "function");
|
|
44
|
+
}
|
|
8
45
|
function getExperienceService(runtime) {
|
|
9
|
-
|
|
46
|
+
const service = runtime?.getService("EXPERIENCE");
|
|
47
|
+
return isExperienceService(service) ? service : null;
|
|
10
48
|
}
|
|
11
49
|
function matchExperiencePath(pathname) {
|
|
12
50
|
for (const basePath of EXPERIENCE_ROUTE_PREFIXES) {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Static file serving for the built React dashboard (production mode).
|
|
3
3
|
*
|
|
4
|
-
* Extracted from server.ts — serves
|
|
4
|
+
* Extracted from server.ts — serves packages/app/dist/ with SPA fallback,
|
|
5
5
|
* caching, and API-base injection for reverse-proxy deployments.
|
|
6
6
|
*/
|
|
7
7
|
import type http from "node:http";
|
|
8
8
|
export declare function resolveUiDir(): string | null;
|
|
9
9
|
export declare function sendStaticResponse(req: http.IncomingMessage, res: http.ServerResponse, status: number, headers: Record<string, string | number>, body?: Buffer): void;
|
|
10
10
|
/**
|
|
11
|
-
* Serve built dashboard assets from
|
|
11
|
+
* Serve built dashboard assets from packages/app/dist with SPA fallback.
|
|
12
12
|
* Returns true when the request is handled.
|
|
13
13
|
*/
|
|
14
14
|
export declare function injectApiBaseIntoHtml(html: Buffer, externalBase?: string | null, opts?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static-file-server.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/api/static-file-server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAkDlC,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"static-file-server.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/api/static-file-server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAkDlC,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CAiC5C;AAMD,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EACxC,IAAI,CAAC,EAAE,MAAM,GACZ,IAAI,CAON;AAyBD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,EAC5B,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAClC,MAAM,CAuBR;AAMD,wBAAgB,aAAa,CAC3B,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CA2GT;AAMD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAS9D"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Static file serving for the built React dashboard (production mode).
|
|
3
3
|
*
|
|
4
|
-
* Extracted from server.ts — serves
|
|
4
|
+
* Extracted from server.ts — serves packages/app/dist/ with SPA fallback,
|
|
5
5
|
* caching, and API-base injection for reverse-proxy deployments.
|
|
6
6
|
*/
|
|
7
7
|
import fs from "node:fs";
|
|
@@ -59,7 +59,9 @@ export function resolveUiDir() {
|
|
|
59
59
|
const thisDir = path.dirname(fileURLToPath(import.meta.url));
|
|
60
60
|
const packageRoot = findOwnPackageRoot(thisDir);
|
|
61
61
|
const candidates = [
|
|
62
|
+
path.resolve("packages/app/dist"),
|
|
62
63
|
path.resolve("apps/app/dist"),
|
|
64
|
+
path.resolve(packageRoot, "packages", "app", "dist"),
|
|
63
65
|
path.resolve(packageRoot, "apps", "app", "dist"),
|
|
64
66
|
];
|
|
65
67
|
for (const candidate of candidates) {
|
|
@@ -104,7 +106,7 @@ function getCachedFile(filePath, mtimeMs) {
|
|
|
104
106
|
// API base injection (reverse-proxy support)
|
|
105
107
|
// ---------------------------------------------------------------------------
|
|
106
108
|
/**
|
|
107
|
-
* Serve built dashboard assets from
|
|
109
|
+
* Serve built dashboard assets from packages/app/dist with SPA fallback.
|
|
108
110
|
* Returns true when the request is handled.
|
|
109
111
|
*/
|
|
110
112
|
export function injectApiBaseIntoHtml(html, externalBase, opts) {
|
|
@@ -0,0 +1,103 @@
|
|
|
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 { type Vault } from "@elizaos/vault";
|
|
21
|
+
import type { WalletChain } from "../contracts/wallet.js";
|
|
22
|
+
/** Public, non-sensitive description of an agent wallet. */
|
|
23
|
+
export interface AgentWalletDescriptor {
|
|
24
|
+
readonly agentId: string;
|
|
25
|
+
readonly chain: WalletChain;
|
|
26
|
+
readonly address: string;
|
|
27
|
+
readonly lastModified: number;
|
|
28
|
+
}
|
|
29
|
+
declare function walletKey(agentId: string, chain: WalletChain): string;
|
|
30
|
+
declare function agentPrefix(agentId: string): string;
|
|
31
|
+
declare function parseAgentWalletKey(key: string): {
|
|
32
|
+
agentId: string;
|
|
33
|
+
chain: WalletChain;
|
|
34
|
+
} | null;
|
|
35
|
+
/**
|
|
36
|
+
* Derive the public address from a stored private key. EVM uses the
|
|
37
|
+
* existing helper; Solana stores the public key alongside the secret in
|
|
38
|
+
* `generateWalletForChain`, so the stored `address` is authoritative
|
|
39
|
+
* and we trust it for the read path.
|
|
40
|
+
*/
|
|
41
|
+
declare function deriveAddressFor(chain: WalletChain, privateKey: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* Read the public descriptor for an agent's wallet. Returns null when
|
|
44
|
+
* the agent has no wallet for that chain. Does NOT reveal the private
|
|
45
|
+
* key.
|
|
46
|
+
*/
|
|
47
|
+
export declare function getAgentWalletDescriptor(vault: Vault, agentId: string, chain: WalletChain): Promise<AgentWalletDescriptor | null>;
|
|
48
|
+
/**
|
|
49
|
+
* Reveal the private key. Audit-logged via the vault. Use only for
|
|
50
|
+
* signing flows.
|
|
51
|
+
*/
|
|
52
|
+
export declare function revealAgentWalletPrivateKey(vault: Vault, agentId: string, chain: WalletChain, caller?: string): Promise<string>;
|
|
53
|
+
/**
|
|
54
|
+
* Existence check. Does not reveal the key.
|
|
55
|
+
*/
|
|
56
|
+
export declare function hasAgentWallet(vault: Vault, agentId: string, chain: WalletChain): Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* List every wallet descriptor for an agent (typically [evm, solana]).
|
|
59
|
+
*/
|
|
60
|
+
export declare function listAgentWallets(vault: Vault, agentId: string): Promise<readonly AgentWalletDescriptor[]>;
|
|
61
|
+
/**
|
|
62
|
+
* List every agent that has at least one wallet stored. Returns the
|
|
63
|
+
* agent IDs (decoded). Use for UI surfaces enumerating agent wallets.
|
|
64
|
+
*/
|
|
65
|
+
export declare function listAgentsWithWallets(vault: Vault): Promise<readonly string[]>;
|
|
66
|
+
/**
|
|
67
|
+
* Persist a wallet for an agent. Replaces any existing entry for that
|
|
68
|
+
* (agentId, chain). Stamps `lastModified`.
|
|
69
|
+
*
|
|
70
|
+
* Caller is responsible for supplying the matching address — for EVM
|
|
71
|
+
* this can be derived from the private key, for Solana the keypair
|
|
72
|
+
* generator returns it directly.
|
|
73
|
+
*/
|
|
74
|
+
export declare function setAgentWallet(vault: Vault, agentId: string, chain: WalletChain, privateKey: string, address: string, caller?: string): Promise<AgentWalletDescriptor>;
|
|
75
|
+
/**
|
|
76
|
+
* Generate a fresh wallet for an agent and persist it. Returns the
|
|
77
|
+
* public descriptor. Idempotent: callers should check `hasAgentWallet`
|
|
78
|
+
* first if they want to avoid replacing an existing wallet.
|
|
79
|
+
*/
|
|
80
|
+
export declare function generateAgentWallet(vault: Vault, agentId: string, chain: WalletChain, caller?: string): Promise<AgentWalletDescriptor>;
|
|
81
|
+
/**
|
|
82
|
+
* Generate any missing wallets (EVM + Solana) for an agent. Existing
|
|
83
|
+
* wallets are left alone. Returns descriptors for every chain that now
|
|
84
|
+
* has a wallet (whether it was generated this call or was already
|
|
85
|
+
* present).
|
|
86
|
+
*/
|
|
87
|
+
export declare function ensureAgentWallets(vault: Vault, agentId: string, caller?: string): Promise<readonly AgentWalletDescriptor[]>;
|
|
88
|
+
/**
|
|
89
|
+
* Remove an agent's wallet for one chain. Idempotent.
|
|
90
|
+
*/
|
|
91
|
+
export declare function removeAgentWallet(vault: Vault, agentId: string, chain: WalletChain): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Remove every wallet for an agent. Use during agent deletion.
|
|
94
|
+
*/
|
|
95
|
+
export declare function removeAllAgentWallets(vault: Vault, agentId: string): Promise<void>;
|
|
96
|
+
export declare const __test__: {
|
|
97
|
+
walletKey: typeof walletKey;
|
|
98
|
+
agentPrefix: typeof agentPrefix;
|
|
99
|
+
parseAgentWalletKey: typeof parseAgentWalletKey;
|
|
100
|
+
deriveAddressFor: typeof deriveAddressFor;
|
|
101
|
+
};
|
|
102
|
+
export {};
|
|
103
|
+
//# sourceMappingURL=agent-wallets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-wallets.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/runtime/agent-wallets.ts"],"names":[],"mappings":"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"}
|