miladyai 2.0.0-alpha.27

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 (241) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +7 -0
  2. package/dist/actions/emote.js +64 -0
  3. package/dist/actions/restart.js +81 -0
  4. package/dist/actions/send-message.js +152 -0
  5. package/dist/agent-admin-routes.js +82 -0
  6. package/dist/agent-lifecycle-routes.js +79 -0
  7. package/dist/agent-transfer-routes.js +102 -0
  8. package/dist/api/agent-admin-routes.js +82 -0
  9. package/dist/api/agent-lifecycle-routes.js +79 -0
  10. package/dist/api/agent-transfer-routes.js +102 -0
  11. package/dist/api/apps-hyperscape-routes.js +58 -0
  12. package/dist/api/apps-routes.js +114 -0
  13. package/dist/api/auth-routes.js +56 -0
  14. package/dist/api/autonomy-routes.js +44 -0
  15. package/dist/api/bug-report-routes.js +111 -0
  16. package/dist/api/character-routes.js +195 -0
  17. package/dist/api/cloud-routes.js +330 -0
  18. package/dist/api/cloud-status-routes.js +155 -0
  19. package/dist/api/compat-utils.js +111 -0
  20. package/dist/api/database.js +735 -0
  21. package/dist/api/diagnostics-routes.js +205 -0
  22. package/dist/api/drop-service.js +134 -0
  23. package/dist/api/early-logs.js +86 -0
  24. package/dist/api/http-helpers.js +131 -0
  25. package/dist/api/knowledge-routes.js +534 -0
  26. package/dist/api/memory-bounds.js +71 -0
  27. package/dist/api/models-routes.js +28 -0
  28. package/dist/api/og-tracker.js +36 -0
  29. package/dist/api/permissions-routes.js +109 -0
  30. package/dist/api/plugin-validation.js +198 -0
  31. package/dist/api/provider-switch-config.js +41 -0
  32. package/dist/api/registry-routes.js +86 -0
  33. package/dist/api/registry-service.js +164 -0
  34. package/dist/api/sandbox-routes.js +1112 -0
  35. package/dist/api/server.js +7949 -0
  36. package/dist/api/subscription-routes.js +172 -0
  37. package/dist/api/terminal-run-limits.js +24 -0
  38. package/dist/api/training-routes.js +158 -0
  39. package/dist/api/trajectory-routes.js +300 -0
  40. package/dist/api/trigger-routes.js +246 -0
  41. package/dist/api/twitter-verify.js +134 -0
  42. package/dist/api/tx-service.js +108 -0
  43. package/dist/api/wallet-routes.js +266 -0
  44. package/dist/api/wallet.js +568 -0
  45. package/dist/api/whatsapp-routes.js +182 -0
  46. package/dist/api/zip-utils.js +109 -0
  47. package/dist/apps-hyperscape-routes.js +58 -0
  48. package/dist/apps-routes.js +114 -0
  49. package/dist/ascii.js +20 -0
  50. package/dist/auth/anthropic.js +44 -0
  51. package/dist/auth/apply-stealth.js +41 -0
  52. package/dist/auth/claude-code-stealth.js +78 -0
  53. package/dist/auth/credentials.js +156 -0
  54. package/dist/auth/index.js +5 -0
  55. package/dist/auth/openai-codex.js +66 -0
  56. package/dist/auth/types.js +9 -0
  57. package/dist/auth-routes.js +56 -0
  58. package/dist/autonomy-routes.js +44 -0
  59. package/dist/bug-report-routes.js +111 -0
  60. package/dist/build-info.json +6 -0
  61. package/dist/character-routes.js +195 -0
  62. package/dist/cli/argv.js +63 -0
  63. package/dist/cli/banner.js +34 -0
  64. package/dist/cli/cli-name.js +21 -0
  65. package/dist/cli/cli-utils.js +16 -0
  66. package/dist/cli/git-commit.js +78 -0
  67. package/dist/cli/parse-duration.js +15 -0
  68. package/dist/cli/plugins-cli.js +590 -0
  69. package/dist/cli/profile-utils.js +9 -0
  70. package/dist/cli/profile.js +95 -0
  71. package/dist/cli/program/build-program.js +17 -0
  72. package/dist/cli/program/command-registry.js +23 -0
  73. package/dist/cli/program/help.js +47 -0
  74. package/dist/cli/program/preaction.js +33 -0
  75. package/dist/cli/program/register.config.js +106 -0
  76. package/dist/cli/program/register.configure.js +20 -0
  77. package/dist/cli/program/register.dashboard.js +124 -0
  78. package/dist/cli/program/register.models.js +23 -0
  79. package/dist/cli/program/register.setup.js +36 -0
  80. package/dist/cli/program/register.start.js +22 -0
  81. package/dist/cli/program/register.subclis.js +70 -0
  82. package/dist/cli/program/register.tui.js +163 -0
  83. package/dist/cli/program/register.update.js +154 -0
  84. package/dist/cli/program.js +3 -0
  85. package/dist/cli/run-main.js +37 -0
  86. package/dist/cli/version.js +7 -0
  87. package/dist/cloud/validate-url.js +93 -0
  88. package/dist/cloud-routes.js +330 -0
  89. package/dist/cloud-status-routes.js +155 -0
  90. package/dist/compat-utils.js +111 -0
  91. package/dist/config/config.js +69 -0
  92. package/dist/config/env-vars.js +19 -0
  93. package/dist/config/includes.js +121 -0
  94. package/dist/config/object-utils.js +7 -0
  95. package/dist/config/paths.js +38 -0
  96. package/dist/config/plugin-auto-enable.js +231 -0
  97. package/dist/config/schema.js +864 -0
  98. package/dist/config/telegram-custom-commands.js +76 -0
  99. package/dist/config/zod-schema.agent-runtime.js +519 -0
  100. package/dist/config/zod-schema.core.js +538 -0
  101. package/dist/config/zod-schema.hooks.js +103 -0
  102. package/dist/config/zod-schema.js +488 -0
  103. package/dist/config/zod-schema.providers-core.js +785 -0
  104. package/dist/config/zod-schema.session.js +73 -0
  105. package/dist/core-plugins.js +37 -0
  106. package/dist/custom-actions.js +250 -0
  107. package/dist/database.js +735 -0
  108. package/dist/diagnostics/integration-observability.js +57 -0
  109. package/dist/diagnostics-routes.js +205 -0
  110. package/dist/drop-service.js +134 -0
  111. package/dist/early-logs.js +24 -0
  112. package/dist/eliza.js +2061 -0
  113. package/dist/emotes/catalog.js +271 -0
  114. package/dist/entry.js +40 -0
  115. package/dist/hooks/discovery.js +167 -0
  116. package/dist/hooks/eligibility.js +64 -0
  117. package/dist/hooks/index.js +4 -0
  118. package/dist/hooks/loader.js +147 -0
  119. package/dist/hooks/registry.js +55 -0
  120. package/dist/http-helpers.js +131 -0
  121. package/dist/index.js +49 -0
  122. package/dist/knowledge-routes.js +534 -0
  123. package/dist/memory-bounds.js +71 -0
  124. package/dist/milady-plugin.js +90 -0
  125. package/dist/models-routes.js +28 -0
  126. package/dist/onboarding-names.js +78 -0
  127. package/dist/onboarding-presets.js +922 -0
  128. package/dist/package.json +1 -0
  129. package/dist/permissions-routes.js +109 -0
  130. package/dist/plugin-validation.js +107 -0
  131. package/dist/plugins/whatsapp/actions.js +91 -0
  132. package/dist/plugins/whatsapp/index.js +16 -0
  133. package/dist/plugins/whatsapp/service.js +270 -0
  134. package/dist/provider-switch-config.js +41 -0
  135. package/dist/providers/admin-trust.js +46 -0
  136. package/dist/providers/autonomous-state.js +101 -0
  137. package/dist/providers/session-bridge.js +86 -0
  138. package/dist/providers/session-utils.js +36 -0
  139. package/dist/providers/simple-mode.js +50 -0
  140. package/dist/providers/ui-catalog.js +15 -0
  141. package/dist/providers/workspace-provider.js +93 -0
  142. package/dist/providers/workspace.js +348 -0
  143. package/dist/registry-routes.js +86 -0
  144. package/dist/registry-service.js +164 -0
  145. package/dist/restart.js +40 -0
  146. package/dist/runtime/core-plugins.js +37 -0
  147. package/dist/runtime/custom-actions.js +250 -0
  148. package/dist/runtime/eliza.js +2061 -0
  149. package/dist/runtime/embedding-manager-support.js +185 -0
  150. package/dist/runtime/embedding-manager.js +193 -0
  151. package/dist/runtime/embedding-presets.js +54 -0
  152. package/dist/runtime/embedding-state.js +8 -0
  153. package/dist/runtime/milady-plugin.js +90 -0
  154. package/dist/runtime/onboarding-names.js +78 -0
  155. package/dist/runtime/restart.js +40 -0
  156. package/dist/runtime/version.js +7 -0
  157. package/dist/sandbox-routes.js +1112 -0
  158. package/dist/security/audit-log.js +149 -0
  159. package/dist/security/network-policy.js +70 -0
  160. package/dist/server.js +7949 -0
  161. package/dist/services/agent-export.js +559 -0
  162. package/dist/services/app-manager.js +389 -0
  163. package/dist/services/browser-capture.js +86 -0
  164. package/dist/services/fallback-training-service.js +128 -0
  165. package/dist/services/mcp-marketplace.js +134 -0
  166. package/dist/services/plugin-installer.js +396 -0
  167. package/dist/services/plugin-manager-types.js +15 -0
  168. package/dist/services/registry-client-app-meta.js +144 -0
  169. package/dist/services/registry-client-endpoints.js +166 -0
  170. package/dist/services/registry-client-local.js +271 -0
  171. package/dist/services/registry-client-network.js +93 -0
  172. package/dist/services/registry-client-queries.js +70 -0
  173. package/dist/services/registry-client.js +157 -0
  174. package/dist/services/sandbox-engine.js +511 -0
  175. package/dist/services/sandbox-manager.js +297 -0
  176. package/dist/services/self-updater.js +175 -0
  177. package/dist/services/skill-catalog-client.js +119 -0
  178. package/dist/services/skill-marketplace.js +521 -0
  179. package/dist/services/stream-manager.js +236 -0
  180. package/dist/services/update-checker.js +121 -0
  181. package/dist/services/update-notifier.js +29 -0
  182. package/dist/services/version-compat.js +78 -0
  183. package/dist/services/whatsapp-pairing.js +196 -0
  184. package/dist/shared/ui-catalog-prompt.js +728 -0
  185. package/dist/subscription-routes.js +172 -0
  186. package/dist/terminal/links.js +19 -0
  187. package/dist/terminal/palette.js +14 -0
  188. package/dist/terminal/theme.js +25 -0
  189. package/dist/terminal-run-limits.js +24 -0
  190. package/dist/training-routes.js +158 -0
  191. package/dist/trajectory-routes.js +300 -0
  192. package/dist/trigger-routes.js +246 -0
  193. package/dist/triggers/action.js +218 -0
  194. package/dist/triggers/runtime.js +281 -0
  195. package/dist/triggers/scheduling.js +295 -0
  196. package/dist/triggers/types.js +5 -0
  197. package/dist/tui/components/assistant-message.js +76 -0
  198. package/dist/tui/components/chat-editor.js +34 -0
  199. package/dist/tui/components/embeddings-overlay.js +46 -0
  200. package/dist/tui/components/footer.js +60 -0
  201. package/dist/tui/components/index.js +15 -0
  202. package/dist/tui/components/modal-frame.js +45 -0
  203. package/dist/tui/components/modal-style.js +15 -0
  204. package/dist/tui/components/model-selector.js +70 -0
  205. package/dist/tui/components/pinned-chat-layout.js +46 -0
  206. package/dist/tui/components/plugins-endpoints-tab.js +196 -0
  207. package/dist/tui/components/plugins-installed-tab-view.js +69 -0
  208. package/dist/tui/components/plugins-installed-tab.js +319 -0
  209. package/dist/tui/components/plugins-overlay-catalog.js +81 -0
  210. package/dist/tui/components/plugins-overlay-data-api.js +21 -0
  211. package/dist/tui/components/plugins-overlay-data-shared.js +20 -0
  212. package/dist/tui/components/plugins-overlay-data.js +323 -0
  213. package/dist/tui/components/plugins-overlay.js +117 -0
  214. package/dist/tui/components/plugins-store-tab.js +148 -0
  215. package/dist/tui/components/settings-overlay.js +61 -0
  216. package/dist/tui/components/status-bar.js +64 -0
  217. package/dist/tui/components/tool-execution.js +68 -0
  218. package/dist/tui/components/user-message.js +22 -0
  219. package/dist/tui/eliza-tui-bridge.js +606 -0
  220. package/dist/tui/index.js +370 -0
  221. package/dist/tui/modal-presets.js +33 -0
  222. package/dist/tui/model-spec.js +46 -0
  223. package/dist/tui/sse-parser.js +78 -0
  224. package/dist/tui/theme.js +110 -0
  225. package/dist/tui/titlebar-spinner.js +62 -0
  226. package/dist/tui/tui-app.js +311 -0
  227. package/dist/tui/ws-client.js +215 -0
  228. package/dist/twitter-verify.js +134 -0
  229. package/dist/tx-service.js +108 -0
  230. package/dist/utils/exec-safety.js +17 -0
  231. package/dist/utils/globals.js +20 -0
  232. package/dist/utils/milady-root.js +61 -0
  233. package/dist/utils/number-parsing.js +37 -0
  234. package/dist/version-resolver.js +37 -0
  235. package/dist/version.js +7 -0
  236. package/dist/wallet-routes.js +266 -0
  237. package/dist/wallet.js +568 -0
  238. package/dist/whatsapp-routes.js +182 -0
  239. package/dist/zip-utils.js +109 -0
  240. package/milady.mjs +14 -0
  241. package/package.json +111 -0
@@ -0,0 +1,348 @@
1
+ import { resolveUserPath } from "../config/paths.js";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import * as elizaCore from "@elizaos/core";
5
+ import { spawn } from "node:child_process";
6
+ import fs from "node:fs/promises";
7
+
8
+ //#region src/providers/workspace.ts
9
+ /**
10
+ * Runs a command with an optional timeout.
11
+ * Returns { code, stdout, stderr }.
12
+ * Rejects if the process cannot be spawned or the timeout fires.
13
+ */
14
+ function runCommandWithTimeout(argv, opts = {}) {
15
+ const [cmd, ...args] = argv;
16
+ if (!cmd) return Promise.reject(/* @__PURE__ */ new Error("runCommandWithTimeout: empty argv"));
17
+ return new Promise((resolve, reject) => {
18
+ const child = spawn(cmd, args, {
19
+ cwd: opts.cwd,
20
+ env: opts.env ?? process.env,
21
+ stdio: [
22
+ "ignore",
23
+ "pipe",
24
+ "pipe"
25
+ ]
26
+ });
27
+ const stdoutChunks = [];
28
+ const stderrChunks = [];
29
+ child.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
30
+ child.stderr.on("data", (chunk) => stderrChunks.push(chunk));
31
+ let timedOut = false;
32
+ let timer;
33
+ if (opts.timeoutMs && opts.timeoutMs > 0) timer = setTimeout(() => {
34
+ timedOut = true;
35
+ child.kill("SIGKILL");
36
+ }, opts.timeoutMs);
37
+ child.on("error", (err) => {
38
+ if (timer) clearTimeout(timer);
39
+ reject(err);
40
+ });
41
+ child.on("close", (exitCode) => {
42
+ if (timer) clearTimeout(timer);
43
+ if (timedOut) {
44
+ reject(/* @__PURE__ */ new Error(`Command timed out after ${opts.timeoutMs}ms: ${argv.join(" ")}`));
45
+ return;
46
+ }
47
+ resolve({
48
+ code: exitCode ?? 1,
49
+ stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
50
+ stderr: Buffer.concat(stderrChunks).toString("utf-8")
51
+ });
52
+ });
53
+ });
54
+ }
55
+ function resolveDefaultAgentWorkspaceDir(env = process.env, homedir = os.homedir) {
56
+ const profile = env.MILADY_PROFILE?.trim();
57
+ if (profile && profile.toLowerCase() !== "default") return path.join(homedir(), ".milady", `workspace-${profile}`);
58
+ return path.join(homedir(), ".milady", "workspace");
59
+ }
60
+ const DEFAULT_AGENT_WORKSPACE_DIR = resolveDefaultAgentWorkspaceDir();
61
+ const DEFAULT_AGENTS_FILENAME = "AGENTS.md";
62
+ const DEFAULT_TOOLS_FILENAME = "TOOLS.md";
63
+ const DEFAULT_IDENTITY_FILENAME = "IDENTITY.md";
64
+ const DEFAULT_USER_FILENAME = "USER.md";
65
+ const DEFAULT_HEARTBEAT_FILENAME = "HEARTBEAT.md";
66
+ const DEFAULT_BOOTSTRAP_FILENAME = "BOOTSTRAP.md";
67
+ const DEFAULT_MEMORY_FILENAME = "MEMORY.md";
68
+ const DEFAULT_MEMORY_ALT_FILENAME = "memory.md";
69
+ /** Inline workspace bootstrap templates — no external files needed. */
70
+ const WORKSPACE_TEMPLATES = {
71
+ [DEFAULT_AGENTS_FILENAME]: `# Agents
72
+
73
+ You are an autonomous AI agent powered by ElizaOS.
74
+
75
+ ## Capabilities
76
+
77
+ - Respond to user messages conversationally
78
+ - Execute actions and use available tools
79
+ - Access and manage knowledge from your workspace
80
+ - Maintain context across conversations
81
+
82
+ ## Guidelines
83
+
84
+ - Be helpful, concise, and accurate
85
+ - Ask for clarification when instructions are ambiguous
86
+ - Use tools when they would help accomplish the user's goal
87
+ - Respect the user's preferences and communication style
88
+ `,
89
+ [DEFAULT_TOOLS_FILENAME]: `# Tools
90
+
91
+ Available tools and capabilities for the agent.
92
+
93
+ ## Built-in Tools
94
+
95
+ The agent has access to tools provided by enabled plugins.
96
+ Each plugin may register actions, providers, and evaluators
97
+ that extend the agent's capabilities.
98
+
99
+ ## Usage
100
+
101
+ Tools are invoked automatically when the agent determines
102
+ they would help accomplish the user's goal. No manual
103
+ configuration is required.
104
+ `,
105
+ [DEFAULT_IDENTITY_FILENAME]: `# Identity
106
+
107
+ Your character and personality settings.
108
+
109
+ Customize this file to define your agent's personality,
110
+ tone, and behavior style.
111
+ `,
112
+ [DEFAULT_USER_FILENAME]: `# User
113
+
114
+ User context and preferences.
115
+
116
+ This file stores information about the user to help
117
+ personalize interactions.
118
+ `,
119
+ [DEFAULT_HEARTBEAT_FILENAME]: `# Heartbeat
120
+
121
+ The heartbeat system enables autonomous agent behavior.
122
+
123
+ ## Scheduling
124
+
125
+ When autonomy is enabled, the agent periodically evaluates
126
+ whether to take proactive actions based on its goals,
127
+ pending tasks, and environmental changes.
128
+
129
+ ## Triggers
130
+
131
+ - Scheduled intervals (configurable)
132
+ - External events from connected channels
133
+ - System notifications and alerts
134
+ `,
135
+ [DEFAULT_BOOTSTRAP_FILENAME]: `# Bootstrap
136
+
137
+ Initial workspace setup for a new agent.
138
+
139
+ ## Getting Started
140
+
141
+ This workspace was automatically created for your agent.
142
+ You can customize it by editing the markdown files in this
143
+ directory:
144
+
145
+ - **AGENTS.md** — Agent behavior and capabilities
146
+ - **TOOLS.md** — Available tools and plugins
147
+ - **IDENTITY.md** — Character and personality
148
+ - **USER.md** — User context and preferences
149
+ - **HEARTBEAT.md** — Autonomous behavior settings
150
+
151
+ ## Configuration
152
+
153
+ Agent configuration is managed through \`~/.milady/milady.json\`
154
+ or the Milady Control UI.
155
+ `
156
+ };
157
+ const coreWorkspaceHelpers = elizaCore;
158
+ function isSubagentSessionKey(sessionKey) {
159
+ if (typeof coreWorkspaceHelpers.isSubagentSessionKey === "function") return coreWorkspaceHelpers.isSubagentSessionKey(sessionKey);
160
+ return false;
161
+ }
162
+ function logWarn(message) {
163
+ if (coreWorkspaceHelpers.logger && typeof coreWorkspaceHelpers.logger.warn === "function") {
164
+ coreWorkspaceHelpers.logger.warn(message);
165
+ return;
166
+ }
167
+ console.warn(message);
168
+ }
169
+ async function writeFileIfMissing(filePath, content) {
170
+ try {
171
+ await fs.writeFile(filePath, content, {
172
+ encoding: "utf-8",
173
+ flag: "wx"
174
+ });
175
+ } catch (err) {
176
+ if (err.code !== "EEXIST") throw err;
177
+ }
178
+ }
179
+ async function hasGitRepo(dir) {
180
+ try {
181
+ await fs.stat(path.join(dir, ".git"));
182
+ return true;
183
+ } catch (err) {
184
+ if (err.code === "ENOENT") return false;
185
+ throw err;
186
+ }
187
+ }
188
+ async function isGitAvailable() {
189
+ try {
190
+ return (await runCommandWithTimeout(["git", "--version"], { timeoutMs: 2e3 })).code === 0;
191
+ } catch {
192
+ return false;
193
+ }
194
+ }
195
+ async function ensureGitRepo(dir, isBrandNewWorkspace) {
196
+ if (!isBrandNewWorkspace) return;
197
+ if (await hasGitRepo(dir)) return;
198
+ if (!await isGitAvailable()) return;
199
+ try {
200
+ await runCommandWithTimeout(["git", "init"], {
201
+ cwd: dir,
202
+ timeoutMs: 1e4
203
+ });
204
+ } catch (err) {
205
+ logWarn(`[workspace] git init failed: ${err instanceof Error ? err.message : err}`);
206
+ }
207
+ }
208
+ async function ensureAgentWorkspace(params) {
209
+ const dir = resolveUserPath(params?.dir?.trim() ? params.dir.trim() : DEFAULT_AGENT_WORKSPACE_DIR);
210
+ await fs.mkdir(dir, { recursive: true });
211
+ if (!params?.ensureBootstrapFiles) return { dir };
212
+ const agentsPath = path.join(dir, DEFAULT_AGENTS_FILENAME);
213
+ const toolsPath = path.join(dir, DEFAULT_TOOLS_FILENAME);
214
+ const identityPath = path.join(dir, DEFAULT_IDENTITY_FILENAME);
215
+ const userPath = path.join(dir, DEFAULT_USER_FILENAME);
216
+ const heartbeatPath = path.join(dir, DEFAULT_HEARTBEAT_FILENAME);
217
+ const bootstrapPath = path.join(dir, DEFAULT_BOOTSTRAP_FILENAME);
218
+ const isBrandNewWorkspace = await (async () => {
219
+ const paths = [
220
+ agentsPath,
221
+ toolsPath,
222
+ identityPath,
223
+ userPath,
224
+ heartbeatPath
225
+ ];
226
+ return (await Promise.all(paths.map(async (p) => {
227
+ try {
228
+ await fs.access(p);
229
+ return true;
230
+ } catch (err) {
231
+ if (err.code === "ENOENT") return false;
232
+ throw err;
233
+ }
234
+ }))).every((v) => !v);
235
+ })();
236
+ const agentsTemplate = WORKSPACE_TEMPLATES[DEFAULT_AGENTS_FILENAME];
237
+ const toolsTemplate = WORKSPACE_TEMPLATES[DEFAULT_TOOLS_FILENAME];
238
+ const identityTemplate = WORKSPACE_TEMPLATES[DEFAULT_IDENTITY_FILENAME];
239
+ const userTemplate = WORKSPACE_TEMPLATES[DEFAULT_USER_FILENAME];
240
+ const heartbeatTemplate = WORKSPACE_TEMPLATES[DEFAULT_HEARTBEAT_FILENAME];
241
+ const bootstrapTemplate = WORKSPACE_TEMPLATES[DEFAULT_BOOTSTRAP_FILENAME];
242
+ const writeOps = [
243
+ writeFileIfMissing(agentsPath, agentsTemplate),
244
+ writeFileIfMissing(toolsPath, toolsTemplate),
245
+ writeFileIfMissing(identityPath, identityTemplate),
246
+ writeFileIfMissing(userPath, userTemplate),
247
+ writeFileIfMissing(heartbeatPath, heartbeatTemplate)
248
+ ];
249
+ if (isBrandNewWorkspace) writeOps.push(writeFileIfMissing(bootstrapPath, bootstrapTemplate));
250
+ await Promise.all(writeOps);
251
+ await ensureGitRepo(dir, isBrandNewWorkspace);
252
+ return {
253
+ dir,
254
+ agentsPath,
255
+ toolsPath,
256
+ identityPath,
257
+ userPath,
258
+ heartbeatPath,
259
+ bootstrapPath
260
+ };
261
+ }
262
+ async function resolveMemoryBootstrapEntries(resolvedDir) {
263
+ const candidates = [DEFAULT_MEMORY_FILENAME, DEFAULT_MEMORY_ALT_FILENAME];
264
+ const entries = [];
265
+ for (const name of candidates) {
266
+ const filePath = path.join(resolvedDir, name);
267
+ try {
268
+ await fs.access(filePath);
269
+ entries.push({
270
+ name,
271
+ filePath
272
+ });
273
+ } catch (err) {
274
+ if (err.code !== "ENOENT") throw err;
275
+ }
276
+ }
277
+ if (entries.length <= 1) return entries;
278
+ const seen = /* @__PURE__ */ new Set();
279
+ const deduped = [];
280
+ for (const entry of entries) {
281
+ let key = entry.filePath;
282
+ try {
283
+ key = await fs.realpath(entry.filePath);
284
+ } catch (err) {
285
+ if (err.code !== "ENOENT") throw err;
286
+ }
287
+ if (seen.has(key)) continue;
288
+ seen.add(key);
289
+ deduped.push(entry);
290
+ }
291
+ return deduped;
292
+ }
293
+ async function loadWorkspaceBootstrapFiles(dir) {
294
+ const resolvedDir = resolveUserPath(dir);
295
+ const entries = [
296
+ {
297
+ name: DEFAULT_AGENTS_FILENAME,
298
+ filePath: path.join(resolvedDir, DEFAULT_AGENTS_FILENAME)
299
+ },
300
+ {
301
+ name: DEFAULT_TOOLS_FILENAME,
302
+ filePath: path.join(resolvedDir, DEFAULT_TOOLS_FILENAME)
303
+ },
304
+ {
305
+ name: DEFAULT_IDENTITY_FILENAME,
306
+ filePath: path.join(resolvedDir, DEFAULT_IDENTITY_FILENAME)
307
+ },
308
+ {
309
+ name: DEFAULT_USER_FILENAME,
310
+ filePath: path.join(resolvedDir, DEFAULT_USER_FILENAME)
311
+ },
312
+ {
313
+ name: DEFAULT_HEARTBEAT_FILENAME,
314
+ filePath: path.join(resolvedDir, DEFAULT_HEARTBEAT_FILENAME)
315
+ },
316
+ {
317
+ name: DEFAULT_BOOTSTRAP_FILENAME,
318
+ filePath: path.join(resolvedDir, DEFAULT_BOOTSTRAP_FILENAME)
319
+ }
320
+ ];
321
+ entries.push(...await resolveMemoryBootstrapEntries(resolvedDir));
322
+ return await Promise.all(entries.map(async (entry) => {
323
+ try {
324
+ const content = await fs.readFile(entry.filePath, "utf-8");
325
+ return {
326
+ name: entry.name,
327
+ path: entry.filePath,
328
+ content,
329
+ missing: false
330
+ };
331
+ } catch (err) {
332
+ if (err.code === "ENOENT") return {
333
+ name: entry.name,
334
+ path: entry.filePath,
335
+ missing: true
336
+ };
337
+ throw err;
338
+ }
339
+ }));
340
+ }
341
+ const SUBAGENT_BOOTSTRAP_ALLOWLIST = new Set([DEFAULT_AGENTS_FILENAME, DEFAULT_TOOLS_FILENAME]);
342
+ function filterBootstrapFilesForSession(files, sessionKey) {
343
+ if (!sessionKey || !isSubagentSessionKey(sessionKey)) return files;
344
+ return files.filter((file) => SUBAGENT_BOOTSTRAP_ALLOWLIST.has(file.name));
345
+ }
346
+
347
+ //#endregion
348
+ export { DEFAULT_AGENT_WORKSPACE_DIR, ensureAgentWorkspace, filterBootstrapFilesForSession, loadWorkspaceBootstrapFiles, resolveDefaultAgentWorkspaceDir };
@@ -0,0 +1,86 @@
1
+ import { parseClampedInteger } from "./utils/number-parsing.js";
2
+
3
+ //#region src/api/registry-routes.ts
4
+ async function handleRegistryRoutes(ctx) {
5
+ const { res, method, pathname, url, json, error, getPluginManager, getLoadedPluginNames, getBundledPluginIds } = ctx;
6
+ if (method === "GET" && pathname === "/api/registry/plugins") {
7
+ try {
8
+ const pluginManager = getPluginManager();
9
+ const registry = await pluginManager.refreshRegistry();
10
+ const installed = await pluginManager.listInstalledPlugins();
11
+ const installedNames = new Set(installed.map((plugin) => plugin.name));
12
+ const loadedNames = new Set(getLoadedPluginNames());
13
+ const bundledIds = getBundledPluginIds();
14
+ const plugins = Array.from(registry.values()).map((plugin) => {
15
+ const shortId = plugin.name.replace(/^@[^/]+\/plugin-/, "").replace(/^@[^/]+\//, "").replace(/^plugin-/, "");
16
+ return {
17
+ ...plugin,
18
+ installed: installedNames.has(plugin.name),
19
+ installedVersion: installed.find((entry) => entry.name === plugin.name)?.version ?? null,
20
+ loaded: loadedNames.has(plugin.name) || loadedNames.has(plugin.name.replace("@elizaos/", "")),
21
+ bundled: bundledIds.has(shortId)
22
+ };
23
+ });
24
+ json(res, {
25
+ count: plugins.length,
26
+ plugins
27
+ });
28
+ } catch (err) {
29
+ error(res, `Failed to fetch registry: ${err instanceof Error ? err.message : String(err)}`, 502);
30
+ }
31
+ return true;
32
+ }
33
+ if (method === "GET" && pathname.startsWith("/api/registry/plugins/") && pathname.length > 22) {
34
+ const name = decodeURIComponent(pathname.slice(22));
35
+ try {
36
+ const info = await getPluginManager().getRegistryPlugin(name);
37
+ if (!info) {
38
+ error(res, `Plugin "${name}" not found in registry`, 404);
39
+ return true;
40
+ }
41
+ json(res, { plugin: info });
42
+ } catch (err) {
43
+ error(res, `Failed to look up plugin: ${err instanceof Error ? err.message : String(err)}`, 502);
44
+ }
45
+ return true;
46
+ }
47
+ if (method === "GET" && pathname === "/api/registry/search") {
48
+ const query = url.searchParams.get("q") || "";
49
+ if (!query.trim()) {
50
+ error(res, "Query parameter 'q' is required", 400);
51
+ return true;
52
+ }
53
+ try {
54
+ const limitParam = url.searchParams.get("limit");
55
+ const limit = limitParam ? parseClampedInteger(limitParam, {
56
+ min: 1,
57
+ max: 50,
58
+ fallback: 15
59
+ }) : 15;
60
+ const results = await getPluginManager().searchRegistry(query, limit);
61
+ json(res, {
62
+ query,
63
+ count: results.length,
64
+ results
65
+ });
66
+ } catch (err) {
67
+ error(res, `Search failed: ${err instanceof Error ? err.message : String(err)}`, 502);
68
+ }
69
+ return true;
70
+ }
71
+ if (method === "POST" && pathname === "/api/registry/refresh") {
72
+ try {
73
+ json(res, {
74
+ ok: true,
75
+ count: (await getPluginManager().refreshRegistry()).size
76
+ });
77
+ } catch (err) {
78
+ error(res, `Refresh failed: ${err instanceof Error ? err.message : String(err)}`, 502);
79
+ }
80
+ return true;
81
+ }
82
+ return false;
83
+ }
84
+
85
+ //#endregion
86
+ export { handleRegistryRoutes };
@@ -0,0 +1,164 @@
1
+ import { logger } from "@elizaos/core";
2
+ import { ethers } from "ethers";
3
+
4
+ //#region src/api/registry-service.ts
5
+ /**
6
+ * ERC-8004 Agent Identity Registry service.
7
+ *
8
+ * Handles all interactions with the MiladyAgentRegistry contract:
9
+ * - Registration (self and delegated)
10
+ * - Profile updates
11
+ * - Metadata (tokenURI) management
12
+ * - Status queries
13
+ */
14
+ const REGISTRY_ABI = [
15
+ "function registerAgent(string,string,bytes32,string) external returns (uint256)",
16
+ "function registerAgentFor(address,string,string,bytes32,string) external returns (uint256)",
17
+ "function updateAgent(string,bytes32) external",
18
+ "function updateAgentProfile(string,string,bytes32,string) external",
19
+ "function updateTokenURI(uint256,string) external",
20
+ "function deactivateAgent() external",
21
+ "function reactivateAgent() external",
22
+ "function getAgentInfo(uint256) view returns (string,string,bytes32,bool)",
23
+ "function addressToTokenId(address) view returns (uint256)",
24
+ "function isRegistered(address) view returns (bool)",
25
+ "function getTokenId(address) view returns (uint256)",
26
+ "function totalAgents() view returns (uint256)",
27
+ "function isEndpointTaken(string) view returns (bool)",
28
+ "function balanceOf(address) view returns (uint256)",
29
+ "function ownerOf(uint256) view returns (address)",
30
+ "function tokenURI(uint256) view returns (string)",
31
+ "event AgentRegistered(uint256 indexed tokenId, address indexed owner, string name, string endpoint)",
32
+ "event AgentUpdated(uint256 indexed tokenId, string endpoint, bytes32 capabilitiesHash)"
33
+ ];
34
+ const DEFAULT_CAPABILITIES_HASH = ethers.id("milady-agent");
35
+ var RegistryService = class {
36
+ constructor(txService, registryAddress) {
37
+ this.txService = txService;
38
+ this.registryAddress = registryAddress;
39
+ this.contract = txService.getContract(registryAddress, REGISTRY_ABI);
40
+ }
41
+ get address() {
42
+ return this.txService.address;
43
+ }
44
+ get contractAddress() {
45
+ return this.registryAddress;
46
+ }
47
+ async getChainId() {
48
+ return this.txService.getChainId();
49
+ }
50
+ /**
51
+ * Get the full registration status for the current wallet.
52
+ */
53
+ async getStatus() {
54
+ const addr = this.txService.address;
55
+ const [registered, totalAgentsBN] = await Promise.all([this.contract.isRegistered(addr), this.contract.totalAgents()]);
56
+ if (!registered) return {
57
+ registered: false,
58
+ tokenId: 0,
59
+ agentName: "",
60
+ agentEndpoint: "",
61
+ capabilitiesHash: "",
62
+ isActive: false,
63
+ tokenURI: "",
64
+ walletAddress: addr,
65
+ totalAgents: Number(totalAgentsBN)
66
+ };
67
+ const tokenId = Number(await this.contract.getTokenId(addr));
68
+ const [[name, endpoint, capHash, isActive], uri] = await Promise.all([this.contract.getAgentInfo(tokenId), this.contract.tokenURI(tokenId)]);
69
+ return {
70
+ registered: true,
71
+ tokenId,
72
+ agentName: name,
73
+ agentEndpoint: endpoint,
74
+ capabilitiesHash: capHash,
75
+ isActive,
76
+ tokenURI: uri,
77
+ walletAddress: addr,
78
+ totalAgents: Number(totalAgentsBN)
79
+ };
80
+ }
81
+ /**
82
+ * Register the current wallet as an agent.
83
+ * The NFT is minted to the wallet address stored in EVM_PRIVATE_KEY.
84
+ */
85
+ async register(params) {
86
+ const capHash = params.capabilitiesHash || DEFAULT_CAPABILITIES_HASH;
87
+ logger.info(`[registry] Registering agent "${params.name}" from ${this.txService.address}`);
88
+ const nonce = await this.txService.getFreshNonce();
89
+ const tx = await this.contract.registerAgent(params.name, params.endpoint, capHash, params.tokenURI, { nonce });
90
+ logger.info(`[registry] Registration tx submitted: ${tx.hash}`);
91
+ const receipt = await tx.wait();
92
+ const iface = new ethers.Interface(REGISTRY_ABI);
93
+ let tokenId = 0;
94
+ for (const log of receipt.logs) {
95
+ const parsed = iface.parseLog({
96
+ topics: log.topics,
97
+ data: log.data
98
+ });
99
+ if (parsed && parsed.name === "AgentRegistered") {
100
+ tokenId = Number(parsed.args[0]);
101
+ break;
102
+ }
103
+ }
104
+ if (tokenId === 0) tokenId = Number(await this.contract.getTokenId(this.txService.address));
105
+ logger.info(`[registry] Agent registered: tokenId=${tokenId} txHash=${receipt.hash}`);
106
+ return {
107
+ tokenId,
108
+ txHash: receipt.hash
109
+ };
110
+ }
111
+ /**
112
+ * Update the tokenURI (metadata pointer) for the current wallet's agent.
113
+ * Called when the character is edited.
114
+ */
115
+ async updateTokenURI(newURI) {
116
+ const tokenId = Number(await this.contract.getTokenId(this.txService.address));
117
+ if (tokenId === 0) throw new Error("Agent not registered, cannot update token URI");
118
+ logger.info(`[registry] Updating tokenURI for token ${tokenId}: ${newURI}`);
119
+ const nonce = await this.txService.getFreshNonce();
120
+ const receipt = await (await this.contract.updateTokenURI(tokenId, newURI, { nonce })).wait();
121
+ logger.info(`[registry] TokenURI updated: txHash=${receipt.hash}`);
122
+ return receipt.hash;
123
+ }
124
+ /**
125
+ * Update the agent's endpoint and capabilities hash.
126
+ */
127
+ async updateAgent(endpoint, capabilitiesHash) {
128
+ const capHash = capabilitiesHash || DEFAULT_CAPABILITIES_HASH;
129
+ logger.info(`[registry] Updating agent profile: endpoint=${endpoint}`);
130
+ const nonce = await this.txService.getFreshNonce();
131
+ const receipt = await (await this.contract.updateAgent(endpoint, capHash, { nonce })).wait();
132
+ logger.info(`[registry] Agent updated: txHash=${receipt.hash}`);
133
+ return receipt.hash;
134
+ }
135
+ /**
136
+ * Check if a specific address is registered.
137
+ */
138
+ /**
139
+ * Sync the full agent profile on-chain: name, endpoint, capabilities, and tokenURI.
140
+ * Called when the character is edited and user wants to push changes to chain.
141
+ */
142
+ async syncProfile(params) {
143
+ const capHash = params.capabilitiesHash || DEFAULT_CAPABILITIES_HASH;
144
+ logger.info(`[registry] Syncing profile: name="${params.name}" endpoint="${params.endpoint}"`);
145
+ const nonce = await this.txService.getFreshNonce();
146
+ const tx = await this.contract.updateAgentProfile(params.name, params.endpoint, capHash, params.tokenURI, { nonce });
147
+ logger.info(`[registry] Sync tx submitted: ${tx.hash}`);
148
+ const receipt = await tx.wait();
149
+ logger.info(`[registry] Profile synced: txHash=${receipt.hash}`);
150
+ return receipt.hash;
151
+ }
152
+ async isRegistered(address) {
153
+ return this.contract.isRegistered(address);
154
+ }
155
+ /**
156
+ * Build the default capabilities hash used for Milady agents.
157
+ */
158
+ static defaultCapabilitiesHash() {
159
+ return DEFAULT_CAPABILITIES_HASH;
160
+ }
161
+ };
162
+
163
+ //#endregion
164
+ export { RegistryService };
@@ -0,0 +1,40 @@
1
+ import process from "node:process";
2
+
3
+ //#region src/runtime/restart.ts
4
+ /**
5
+ * Restart infrastructure for Milady.
6
+ *
7
+ * Provides a pluggable restart handler so the restart action (and the
8
+ * `/api/agent/restart` endpoint) work in every host environment:
9
+ *
10
+ * - **CLI** (default): exits with {@link RESTART_EXIT_CODE} (75). The runner
11
+ * script (`scripts/run-node.mjs`) catches this, rebuilds if source files
12
+ * changed, and relaunches.
13
+ * - **Dev-server / API**: the host registers a handler via
14
+ * {@link setRestartHandler} that stops the current runtime, creates a new
15
+ * one, and hot-swaps references.
16
+ * - **Electron app**: the host registers a handler that calls
17
+ * `AgentManager.restart()`.
18
+ *
19
+ * @module restart
20
+ */
21
+ /**
22
+ * Special exit code that tells the CLI runner to restart the process.
23
+ * Must stay in sync with `RESTART_EXIT_CODE` in `scripts/run-node.mjs`.
24
+ */
25
+ const RESTART_EXIT_CODE = 75;
26
+ let _handler = () => {
27
+ process.exit(RESTART_EXIT_CODE);
28
+ };
29
+ /**
30
+ * Trigger a restart. Delegates to whatever handler is currently registered.
31
+ *
32
+ * Safe to call from the restart action, the API endpoint, or any other code
33
+ * that needs to bounce the agent.
34
+ */
35
+ function requestRestart(reason) {
36
+ return _handler(reason);
37
+ }
38
+
39
+ //#endregion
40
+ export { requestRestart };
@@ -0,0 +1,37 @@
1
+ //#region src/runtime/core-plugins.ts
2
+ /**
3
+ * Core plugin package lists shared by runtime startup and the API server.
4
+ *
5
+ * Keeping this in a standalone module avoids a circular dependency between
6
+ * `api/server.ts` and `runtime/eliza.ts`.
7
+ */
8
+ /** Core plugins that should always be loaded. */
9
+ const CORE_PLUGINS = [
10
+ "@elizaos/plugin-sql",
11
+ "@elizaos/plugin-local-embedding",
12
+ "@elizaos/plugin-secrets-manager",
13
+ "@elizaos/plugin-form",
14
+ "@elizaos/plugin-knowledge",
15
+ "@elizaos/plugin-rolodex",
16
+ "@elizaos/plugin-trajectory-logger",
17
+ "@elizaos/plugin-agent-orchestrator",
18
+ "@elizaos/plugin-cron",
19
+ "@elizaos/plugin-shell",
20
+ "@elizaos/plugin-plugin-manager",
21
+ "@elizaos/plugin-agent-skills",
22
+ "@elizaos/plugin-pdf"
23
+ ];
24
+ /**
25
+ * Plugins that can be enabled from the admin panel.
26
+ * Not loaded by default — kept separate due to packaging or spec issues.
27
+ */
28
+ const OPTIONAL_CORE_PLUGINS = [
29
+ "@elizaos/plugin-cua",
30
+ "@elizaos/plugin-obsidian",
31
+ "@elizaos/plugin-code",
32
+ "@elizaos/plugin-repoprompt",
33
+ "@milaidy/plugin-claude-code-workbench"
34
+ ];
35
+
36
+ //#endregion
37
+ export { CORE_PLUGINS, OPTIONAL_CORE_PLUGINS };