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,300 @@
1
+ import { readJsonBody, sendJson, sendJsonError } from "./http-helpers.js";
2
+ import { createZipArchive } from "./zip-utils.js";
3
+
4
+ //#region src/api/trajectory-routes.ts
5
+ function isRouteCompatibleTrajectoryLogger(candidate) {
6
+ if (!candidate || typeof candidate !== "object") return false;
7
+ const logger = candidate;
8
+ return typeof logger.isEnabled === "function" && typeof logger.setEnabled === "function" && typeof logger.listTrajectories === "function" && typeof logger.getTrajectoryDetail === "function" && typeof logger.getStats === "function" && typeof logger.deleteTrajectories === "function" && typeof logger.clearAllTrajectories === "function" && typeof logger.exportTrajectories === "function";
9
+ }
10
+ function getTrajectoryLogger(runtime) {
11
+ const runtimeLike = runtime;
12
+ const seen = /* @__PURE__ */ new Set();
13
+ const candidates = [];
14
+ const addCandidate = (candidate) => {
15
+ if (!candidate || seen.has(candidate)) return;
16
+ seen.add(candidate);
17
+ candidates.push(candidate);
18
+ };
19
+ if (typeof runtimeLike.getServicesByType === "function") {
20
+ const byType = runtimeLike.getServicesByType("trajectory_logger");
21
+ if (Array.isArray(byType)) for (const candidate of byType) addCandidate(candidate);
22
+ else addCandidate(byType);
23
+ }
24
+ if (typeof runtimeLike.getService === "function") addCandidate(runtimeLike.getService("trajectory_logger"));
25
+ for (const candidate of candidates) if (isRouteCompatibleTrajectoryLogger(candidate)) return candidate;
26
+ return null;
27
+ }
28
+ function toNullableString(value) {
29
+ return typeof value === "string" ? value : null;
30
+ }
31
+ function listItemToUIRecord(item) {
32
+ const status = item.status === "timeout" || item.status === "error" ? "error" : item.status;
33
+ return {
34
+ id: item.id,
35
+ agentId: item.agentId,
36
+ roomId: null,
37
+ entityId: null,
38
+ conversationId: null,
39
+ source: item.source,
40
+ status,
41
+ startTime: item.startTime,
42
+ endTime: item.endTime,
43
+ durationMs: item.durationMs,
44
+ llmCallCount: item.llmCallCount,
45
+ providerAccessCount: 0,
46
+ totalPromptTokens: item.totalPromptTokens,
47
+ totalCompletionTokens: item.totalCompletionTokens,
48
+ metadata: {},
49
+ createdAt: item.createdAt,
50
+ updatedAt: item.createdAt
51
+ };
52
+ }
53
+ function trajectoryToUIDetail(traj) {
54
+ const finalStatus = traj.metrics?.finalStatus ?? "completed";
55
+ const normalizedEndTime = typeof traj.endTime === "number" && traj.endTime > 0 ? traj.endTime : null;
56
+ const status = finalStatus === "timeout" || finalStatus === "terminated" || finalStatus === "error" ? "error" : finalStatus === "completed" ? "completed" : normalizedEndTime ? "completed" : "active";
57
+ const llmCalls = [];
58
+ const providerAccesses = [];
59
+ let totalPromptTokens = 0;
60
+ let totalCompletionTokens = 0;
61
+ const steps = traj.steps || [];
62
+ const trajectoryId = String(traj.trajectoryId);
63
+ for (let i = 0; i < steps.length; i++) {
64
+ const step = steps[i];
65
+ const stepId = typeof step.stepId === "string" ? step.stepId : `step-${i}`;
66
+ const calls = step.llmCalls || [];
67
+ for (let j = 0; j < calls.length; j++) {
68
+ const call = calls[j];
69
+ llmCalls.push({
70
+ id: call.callId || `${stepId}-call-${j}`,
71
+ trajectoryId,
72
+ stepId,
73
+ model: call.model || "unknown",
74
+ systemPrompt: call.systemPrompt || "",
75
+ userPrompt: call.userPrompt || "",
76
+ response: call.response || "",
77
+ temperature: typeof call.temperature === "number" ? call.temperature : 0,
78
+ maxTokens: typeof call.maxTokens === "number" ? call.maxTokens : 0,
79
+ purpose: call.purpose || "",
80
+ actionType: call.actionType || "",
81
+ latencyMs: call.latencyMs || 0,
82
+ promptTokens: call.promptTokens,
83
+ completionTokens: call.completionTokens,
84
+ timestamp: call.timestamp || step.timestamp,
85
+ createdAt: new Date(call.timestamp || step.timestamp).toISOString()
86
+ });
87
+ totalPromptTokens += call.promptTokens || 0;
88
+ totalCompletionTokens += call.completionTokens || 0;
89
+ }
90
+ const accesses = step.providerAccesses || [];
91
+ for (let k = 0; k < accesses.length; k++) {
92
+ const access = accesses[k];
93
+ providerAccesses.push({
94
+ id: access.providerId || `${stepId}-provider-${k}`,
95
+ trajectoryId,
96
+ stepId,
97
+ providerName: access.providerName || "unknown",
98
+ purpose: access.purpose || "",
99
+ data: access.data || {},
100
+ query: access.query,
101
+ timestamp: access.timestamp || step.timestamp,
102
+ createdAt: new Date(access.timestamp || step.timestamp).toISOString()
103
+ });
104
+ }
105
+ }
106
+ const metadata = traj.metadata ?? {};
107
+ const normalizedDurationMs = status === "active" ? null : typeof traj.durationMs === "number" ? traj.durationMs : null;
108
+ const updatedAtMs = normalizedEndTime ?? (traj.startTime || Date.now());
109
+ return {
110
+ trajectory: {
111
+ id: trajectoryId,
112
+ agentId: String(traj.agentId),
113
+ roomId: toNullableString(metadata.roomId),
114
+ entityId: toNullableString(metadata.entityId),
115
+ conversationId: toNullableString(metadata.conversationId),
116
+ source: toNullableString(metadata.source) ?? "chat",
117
+ status,
118
+ startTime: traj.startTime,
119
+ endTime: normalizedEndTime,
120
+ durationMs: normalizedDurationMs,
121
+ llmCallCount: llmCalls.length,
122
+ providerAccessCount: providerAccesses.length,
123
+ totalPromptTokens,
124
+ totalCompletionTokens,
125
+ metadata,
126
+ createdAt: new Date(traj.startTime).toISOString(),
127
+ updatedAt: new Date(updatedAtMs).toISOString()
128
+ },
129
+ llmCalls,
130
+ providerAccesses
131
+ };
132
+ }
133
+ async function handleGetTrajectories(req, res, runtime) {
134
+ const logger = getTrajectoryLogger(runtime);
135
+ if (!logger) {
136
+ sendJsonError(res, "Trajectory logger service not available", 503);
137
+ return;
138
+ }
139
+ const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
140
+ const options = {
141
+ limit: Math.min(500, Math.max(1, Number(url.searchParams.get("limit")) || 50)),
142
+ offset: Math.max(0, Number(url.searchParams.get("offset")) || 0),
143
+ source: url.searchParams.get("source") || void 0,
144
+ status: url.searchParams.get("status") || void 0,
145
+ startDate: url.searchParams.get("startDate") || void 0,
146
+ endDate: url.searchParams.get("endDate") || void 0,
147
+ search: url.searchParams.get("search") || void 0,
148
+ scenarioId: url.searchParams.get("scenarioId") || void 0,
149
+ batchId: url.searchParams.get("batchId") || void 0,
150
+ isTrainingData: url.searchParams.has("isTrainingData") ? url.searchParams.get("isTrainingData") === "true" : void 0
151
+ };
152
+ const result = await logger.listTrajectories(options);
153
+ sendJson(res, {
154
+ trajectories: result.trajectories.map(listItemToUIRecord),
155
+ total: result.total,
156
+ offset: result.offset,
157
+ limit: result.limit
158
+ });
159
+ }
160
+ async function handleGetTrajectoryDetail(_req, res, runtime, trajectoryId) {
161
+ const logger = getTrajectoryLogger(runtime);
162
+ if (!logger) {
163
+ sendJsonError(res, "Trajectory logger service not available", 503);
164
+ return;
165
+ }
166
+ const trajectory = await logger.getTrajectoryDetail(trajectoryId);
167
+ if (!trajectory) {
168
+ sendJsonError(res, `Trajectory "${trajectoryId}" not found`, 404);
169
+ return;
170
+ }
171
+ sendJson(res, trajectoryToUIDetail(trajectory));
172
+ }
173
+ async function handleGetStats(_req, res, runtime) {
174
+ const logger = getTrajectoryLogger(runtime);
175
+ if (!logger) {
176
+ sendJsonError(res, "Trajectory logger service not available", 503);
177
+ return;
178
+ }
179
+ sendJson(res, await logger.getStats());
180
+ }
181
+ async function handleGetConfig(_req, res, runtime) {
182
+ const logger = getTrajectoryLogger(runtime);
183
+ if (!logger) {
184
+ sendJsonError(res, "Trajectory logger service not available", 503);
185
+ return;
186
+ }
187
+ sendJson(res, { enabled: logger.isEnabled() });
188
+ }
189
+ async function handlePutConfig(req, res, runtime) {
190
+ const logger = getTrajectoryLogger(runtime);
191
+ if (!logger) {
192
+ sendJsonError(res, "Trajectory logger service not available", 503);
193
+ return;
194
+ }
195
+ const body = await readJsonBody(req, res);
196
+ if (!body) return;
197
+ if (typeof body.enabled === "boolean") logger.setEnabled(body.enabled);
198
+ sendJson(res, { enabled: logger.isEnabled() });
199
+ }
200
+ async function handleExportTrajectories(req, res, runtime) {
201
+ const logger = getTrajectoryLogger(runtime);
202
+ if (!logger) {
203
+ sendJsonError(res, "Trajectory logger service not available", 503);
204
+ return;
205
+ }
206
+ const body = await readJsonBody(req, res);
207
+ if (!body) return;
208
+ if (body.format === "zip") {
209
+ if (typeof logger.exportTrajectoriesZip !== "function") {
210
+ sendJsonError(res, "Trajectory ZIP export is unavailable in the active logger", 503);
211
+ return;
212
+ }
213
+ const zipOptions = {
214
+ includePrompts: body.includePrompts,
215
+ trajectoryIds: body.trajectoryIds,
216
+ startDate: body.startDate,
217
+ endDate: body.endDate,
218
+ scenarioId: body.scenarioId,
219
+ batchId: body.batchId
220
+ };
221
+ const zipResult = await logger.exportTrajectoriesZip(zipOptions);
222
+ const archive = createZipArchive(zipResult.entries);
223
+ res.statusCode = 200;
224
+ res.setHeader("Content-Type", "application/zip");
225
+ res.setHeader("Content-Disposition", `attachment; filename="${zipResult.filename}"`);
226
+ res.end(archive);
227
+ return;
228
+ }
229
+ if (body.format !== "json" && body.format !== "csv" && body.format !== "art") {
230
+ sendJsonError(res, "Format must be 'json', 'csv', 'art', or 'zip'", 400);
231
+ return;
232
+ }
233
+ const result = await logger.exportTrajectories({
234
+ format: body.format,
235
+ includePrompts: body.includePrompts,
236
+ trajectoryIds: body.trajectoryIds,
237
+ startDate: body.startDate,
238
+ endDate: body.endDate,
239
+ scenarioId: body.scenarioId,
240
+ batchId: body.batchId
241
+ });
242
+ res.statusCode = 200;
243
+ res.setHeader("Content-Type", result.mimeType);
244
+ res.setHeader("Content-Disposition", `attachment; filename="${result.filename}"`);
245
+ res.end(result.data);
246
+ }
247
+ async function handleDeleteTrajectories(req, res, runtime) {
248
+ const logger = getTrajectoryLogger(runtime);
249
+ if (!logger) {
250
+ sendJsonError(res, "Trajectory logger service not available", 503);
251
+ return;
252
+ }
253
+ const body = await readJsonBody(req, res);
254
+ if (!body) return;
255
+ if (body.all) {
256
+ sendJson(res, { deleted: await logger.clearAllTrajectories() });
257
+ return;
258
+ }
259
+ if (Array.isArray(body.trajectoryIds) && body.trajectoryIds.length > 0) {
260
+ sendJson(res, { deleted: await logger.deleteTrajectories(body.trajectoryIds) });
261
+ return;
262
+ }
263
+ sendJson(res, { deleted: 0 });
264
+ }
265
+ async function handleTrajectoryRoute(req, res, runtime, pathname, method) {
266
+ if (!pathname.startsWith("/api/trajectories")) return false;
267
+ if (pathname === "/api/trajectories/config" && method === "GET") {
268
+ await handleGetConfig(req, res, runtime);
269
+ return true;
270
+ }
271
+ if (pathname === "/api/trajectories/config" && method === "PUT") {
272
+ await handlePutConfig(req, res, runtime);
273
+ return true;
274
+ }
275
+ if (pathname === "/api/trajectories/export" && method === "POST") {
276
+ await handleExportTrajectories(req, res, runtime);
277
+ return true;
278
+ }
279
+ if (pathname === "/api/trajectories" && method === "DELETE") {
280
+ await handleDeleteTrajectories(req, res, runtime);
281
+ return true;
282
+ }
283
+ if (pathname === "/api/trajectories/stats" && method === "GET") {
284
+ await handleGetStats(req, res, runtime);
285
+ return true;
286
+ }
287
+ const detailMatch = pathname.match(/^\/api\/trajectories\/([^/]+)$/);
288
+ if (detailMatch && method === "GET") {
289
+ await handleGetTrajectoryDetail(req, res, runtime, detailMatch[1]);
290
+ return true;
291
+ }
292
+ if (pathname === "/api/trajectories" && method === "GET") {
293
+ await handleGetTrajectories(req, res, runtime);
294
+ return true;
295
+ }
296
+ return false;
297
+ }
298
+
299
+ //#endregion
300
+ export { handleTrajectoryRoute };
@@ -0,0 +1,246 @@
1
+ import { DISABLED_TRIGGER_INTERVAL_MS, buildTriggerConfig, buildTriggerMetadata, normalizeTriggerDraft } from "./triggers/scheduling.js";
2
+ import { TRIGGER_TASK_NAME, TRIGGER_TASK_TAGS, executeTriggerTask, getTriggerHealthSnapshot, getTriggerLimit, listTriggerTasks, readTriggerConfig, readTriggerRuns, taskToTriggerSummary, triggersFeatureEnabled } from "./triggers/runtime.js";
3
+ import crypto from "node:crypto";
4
+ import { stringToUuid } from "@elizaos/core";
5
+
6
+ //#region src/api/trigger-routes.ts
7
+ function trim(s) {
8
+ return s.trim().replace(/\s+/g, " ");
9
+ }
10
+ async function findTask(runtime, id) {
11
+ return (await listTriggerTasks(runtime)).find((t) => {
12
+ return readTriggerConfig(t)?.triggerId === id || t.id === id;
13
+ }) ?? null;
14
+ }
15
+ async function handleTriggerRoutes(ctx) {
16
+ const { method, pathname, req, res, runtime, readJsonBody, json, error } = ctx;
17
+ if (!pathname.startsWith("/api/triggers")) return false;
18
+ if (!runtime) {
19
+ error(res, "Agent is not running", 503);
20
+ return true;
21
+ }
22
+ if (!triggersFeatureEnabled(runtime) && pathname !== "/api/triggers/health") {
23
+ error(res, "Triggers are disabled by configuration", 503);
24
+ return true;
25
+ }
26
+ if (method === "GET" && pathname === "/api/triggers/health") {
27
+ json(res, await getTriggerHealthSnapshot(runtime));
28
+ return true;
29
+ }
30
+ if (method === "GET" && pathname === "/api/triggers") {
31
+ json(res, { triggers: (await listTriggerTasks(runtime)).map(taskToTriggerSummary).filter((s) => s !== null).sort((a, b) => a.displayName.localeCompare(b.displayName)) });
32
+ return true;
33
+ }
34
+ if (method === "POST" && pathname === "/api/triggers") {
35
+ const body = await readJsonBody(req, res);
36
+ if (!body) return true;
37
+ const creator = trim(body.createdBy ?? "") || "api";
38
+ const normalized = normalizeTriggerDraft({
39
+ input: {
40
+ ...body,
41
+ enabled: body.enabled ?? true,
42
+ createdBy: creator
43
+ },
44
+ fallback: {
45
+ displayName: trim(body.displayName ?? "") || "New Trigger",
46
+ instructions: trim(body.instructions ?? ""),
47
+ triggerType: body.triggerType ?? "interval",
48
+ wakeMode: body.wakeMode ?? "inject_now",
49
+ enabled: body.enabled ?? true,
50
+ createdBy: creator
51
+ }
52
+ });
53
+ if (!normalized.draft) {
54
+ error(res, normalized.error ?? "Invalid trigger request", 400);
55
+ return true;
56
+ }
57
+ const existingTasks = await listTriggerTasks(runtime);
58
+ const activeCount = existingTasks.filter((t) => {
59
+ const tr = readTriggerConfig(t);
60
+ return tr?.enabled && tr.createdBy === creator;
61
+ }).length;
62
+ const limit = getTriggerLimit(runtime);
63
+ if (activeCount >= limit) {
64
+ error(res, `Active trigger limit reached (${limit})`, 429);
65
+ return true;
66
+ }
67
+ const triggerId = stringToUuid(crypto.randomUUID());
68
+ const trigger = buildTriggerConfig({
69
+ draft: normalized.draft,
70
+ triggerId
71
+ });
72
+ if (existingTasks.find((t) => {
73
+ const et = readTriggerConfig(t);
74
+ return et?.enabled && et.dedupeKey && et.dedupeKey === trigger.dedupeKey;
75
+ })?.id) {
76
+ error(res, "Equivalent trigger already exists", 409);
77
+ return true;
78
+ }
79
+ const metadata = buildTriggerMetadata({
80
+ trigger,
81
+ nowMs: Date.now()
82
+ });
83
+ if (!metadata) {
84
+ error(res, "Unable to compute trigger schedule", 400);
85
+ return true;
86
+ }
87
+ const roomId = runtime.getService("AUTONOMY")?.getAutonomousRoomId?.();
88
+ const taskId = await runtime.createTask({
89
+ name: TRIGGER_TASK_NAME,
90
+ description: trigger.displayName,
91
+ roomId,
92
+ tags: [...TRIGGER_TASK_TAGS],
93
+ metadata
94
+ });
95
+ const created = await runtime.getTask(taskId);
96
+ const summary = created ? taskToTriggerSummary(created) : null;
97
+ if (!summary) {
98
+ error(res, "Trigger created but summary could not be generated", 500);
99
+ return true;
100
+ }
101
+ json(res, { trigger: summary }, 201);
102
+ return true;
103
+ }
104
+ const runsMatch = /^\/api\/triggers\/([^/]+)\/runs$/.exec(pathname);
105
+ if (method === "GET" && runsMatch) {
106
+ const task = await findTask(runtime, decodeURIComponent(runsMatch[1]));
107
+ if (!task) {
108
+ error(res, "Trigger not found", 404);
109
+ return true;
110
+ }
111
+ json(res, { runs: readTriggerRuns(task) });
112
+ return true;
113
+ }
114
+ const execMatch = /^\/api\/triggers\/([^/]+)\/execute$/.exec(pathname);
115
+ if (method === "POST" && execMatch) {
116
+ const task = await findTask(runtime, decodeURIComponent(execMatch[1]));
117
+ if (!task) {
118
+ error(res, "Trigger not found", 404);
119
+ return true;
120
+ }
121
+ const result = await executeTriggerTask(runtime, task, {
122
+ source: "manual",
123
+ force: true
124
+ });
125
+ const refreshed = task.id ? await runtime.getTask(task.id) : null;
126
+ json(res, {
127
+ ok: true,
128
+ result,
129
+ trigger: refreshed ? taskToTriggerSummary(refreshed) : null
130
+ });
131
+ return true;
132
+ }
133
+ const itemMatch = /^\/api\/triggers\/([^/]+)$/.exec(pathname);
134
+ if (!itemMatch) return false;
135
+ const triggerId = decodeURIComponent(itemMatch[1]);
136
+ if (method === "GET") {
137
+ const task = await findTask(runtime, triggerId);
138
+ if (!task) {
139
+ error(res, "Trigger not found", 404);
140
+ return true;
141
+ }
142
+ const summary = taskToTriggerSummary(task);
143
+ if (!summary) {
144
+ error(res, "Trigger metadata is invalid", 500);
145
+ return true;
146
+ }
147
+ json(res, { trigger: summary });
148
+ return true;
149
+ }
150
+ if (method === "DELETE") {
151
+ const task = await findTask(runtime, triggerId);
152
+ if (!task?.id) {
153
+ error(res, "Trigger not found", 404);
154
+ return true;
155
+ }
156
+ await runtime.deleteTask(task.id);
157
+ json(res, { ok: true });
158
+ return true;
159
+ }
160
+ if (method === "PUT") {
161
+ const task = await findTask(runtime, triggerId);
162
+ if (!task?.id) {
163
+ error(res, "Trigger not found", 404);
164
+ return true;
165
+ }
166
+ const current = readTriggerConfig(task);
167
+ if (!current) {
168
+ error(res, "Trigger metadata is invalid", 500);
169
+ return true;
170
+ }
171
+ const body = await readJsonBody(req, res);
172
+ if (!body) return true;
173
+ const normalized = normalizeTriggerDraft({
174
+ input: {
175
+ ...body,
176
+ createdBy: current.createdBy,
177
+ intervalMs: body.intervalMs ?? current.intervalMs,
178
+ scheduledAtIso: body.scheduledAtIso ?? current.scheduledAtIso,
179
+ cronExpression: body.cronExpression ?? current.cronExpression,
180
+ maxRuns: body.maxRuns ?? current.maxRuns
181
+ },
182
+ fallback: {
183
+ displayName: current.displayName,
184
+ instructions: current.instructions,
185
+ triggerType: current.triggerType,
186
+ wakeMode: current.wakeMode,
187
+ enabled: body.enabled ?? current.enabled,
188
+ createdBy: current.createdBy
189
+ }
190
+ });
191
+ if (!normalized.draft) {
192
+ error(res, normalized.error ?? "Invalid update", 400);
193
+ return true;
194
+ }
195
+ const nextTrigger = buildTriggerConfig({
196
+ draft: normalized.draft,
197
+ triggerId: current.triggerId,
198
+ previous: current
199
+ });
200
+ const existingMeta = task.metadata ?? {};
201
+ const existingRuns = readTriggerRuns(task);
202
+ let nextMeta;
203
+ if (!nextTrigger.enabled) nextMeta = {
204
+ ...existingMeta,
205
+ updatedAt: Date.now(),
206
+ updateInterval: DISABLED_TRIGGER_INTERVAL_MS,
207
+ trigger: {
208
+ ...nextTrigger,
209
+ nextRunAtMs: Date.now() + DISABLED_TRIGGER_INTERVAL_MS
210
+ },
211
+ triggerRuns: existingRuns
212
+ };
213
+ else {
214
+ const built = buildTriggerMetadata({
215
+ existingMetadata: existingMeta,
216
+ trigger: nextTrigger,
217
+ nowMs: Date.now()
218
+ });
219
+ if (!built) {
220
+ error(res, "Unable to compute trigger schedule", 400);
221
+ return true;
222
+ }
223
+ nextMeta = built;
224
+ }
225
+ await runtime.updateTask(task.id, {
226
+ description: nextTrigger.displayName,
227
+ metadata: nextMeta
228
+ });
229
+ const refreshed = await runtime.getTask(task.id);
230
+ if (!refreshed) {
231
+ error(res, "Trigger updated but no longer available", 500);
232
+ return true;
233
+ }
234
+ const summary = taskToTriggerSummary(refreshed);
235
+ if (!summary) {
236
+ error(res, "Trigger metadata is invalid", 500);
237
+ return true;
238
+ }
239
+ json(res, { trigger: summary });
240
+ return true;
241
+ }
242
+ return false;
243
+ }
244
+
245
+ //#endregion
246
+ export { handleTriggerRoutes };