@elizaos/autonomous 2.0.0-alpha.10

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/LICENSE +21 -0
  2. package/package.json +270 -0
  3. package/src/actions/emote.ts +101 -0
  4. package/src/actions/restart.ts +101 -0
  5. package/src/actions/send-message.ts +168 -0
  6. package/src/actions/stream-control.ts +439 -0
  7. package/src/actions/switch-stream-source.ts +126 -0
  8. package/src/actions/terminal.ts +186 -0
  9. package/src/api/agent-admin-routes.ts +178 -0
  10. package/src/api/agent-lifecycle-routes.ts +129 -0
  11. package/src/api/agent-model.ts +143 -0
  12. package/src/api/agent-transfer-routes.ts +211 -0
  13. package/src/api/apps-routes.ts +210 -0
  14. package/src/api/auth-routes.ts +90 -0
  15. package/src/api/bsc-trade.ts +736 -0
  16. package/src/api/bug-report-routes.ts +161 -0
  17. package/src/api/character-routes.ts +421 -0
  18. package/src/api/cloud-billing-routes.ts +598 -0
  19. package/src/api/cloud-compat-routes.ts +192 -0
  20. package/src/api/cloud-routes.ts +529 -0
  21. package/src/api/cloud-status-routes.ts +234 -0
  22. package/src/api/compat-utils.ts +154 -0
  23. package/src/api/connector-health.ts +135 -0
  24. package/src/api/coordinator-wiring.ts +179 -0
  25. package/src/api/credit-detection.ts +47 -0
  26. package/src/api/database.ts +1357 -0
  27. package/src/api/diagnostics-routes.ts +389 -0
  28. package/src/api/drop-service.ts +205 -0
  29. package/src/api/early-logs.ts +111 -0
  30. package/src/api/http-helpers.ts +252 -0
  31. package/src/api/index.ts +85 -0
  32. package/src/api/knowledge-routes.ts +1189 -0
  33. package/src/api/knowledge-service-loader.ts +92 -0
  34. package/src/api/memory-bounds.ts +121 -0
  35. package/src/api/memory-routes.ts +349 -0
  36. package/src/api/merkle-tree.ts +239 -0
  37. package/src/api/models-routes.ts +72 -0
  38. package/src/api/nfa-routes.ts +169 -0
  39. package/src/api/nft-verify.ts +188 -0
  40. package/src/api/og-tracker.ts +72 -0
  41. package/src/api/parse-action-block.ts +145 -0
  42. package/src/api/permissions-routes.ts +222 -0
  43. package/src/api/plugin-validation.ts +355 -0
  44. package/src/api/provider-switch-config.ts +455 -0
  45. package/src/api/registry-routes.ts +165 -0
  46. package/src/api/registry-service.ts +292 -0
  47. package/src/api/route-helpers.ts +21 -0
  48. package/src/api/sandbox-routes.ts +1480 -0
  49. package/src/api/server.ts +17674 -0
  50. package/src/api/signal-routes.ts +265 -0
  51. package/src/api/stream-persistence.ts +297 -0
  52. package/src/api/stream-route-state.ts +48 -0
  53. package/src/api/stream-routes.ts +1046 -0
  54. package/src/api/stream-voice-routes.ts +208 -0
  55. package/src/api/streaming-text.ts +129 -0
  56. package/src/api/streaming-types.ts +23 -0
  57. package/src/api/subscription-routes.ts +283 -0
  58. package/src/api/terminal-run-limits.ts +31 -0
  59. package/src/api/training-backend-check.ts +40 -0
  60. package/src/api/training-routes.ts +314 -0
  61. package/src/api/training-service-like.ts +46 -0
  62. package/src/api/trajectory-routes.ts +714 -0
  63. package/src/api/trigger-routes.ts +438 -0
  64. package/src/api/twitter-verify.ts +226 -0
  65. package/src/api/tx-service.ts +193 -0
  66. package/src/api/wallet-dex-prices.ts +206 -0
  67. package/src/api/wallet-evm-balance.ts +989 -0
  68. package/src/api/wallet-routes.ts +505 -0
  69. package/src/api/wallet-rpc.ts +523 -0
  70. package/src/api/wallet-trading-profile.ts +694 -0
  71. package/src/api/wallet.ts +745 -0
  72. package/src/api/whatsapp-routes.ts +282 -0
  73. package/src/api/zip-utils.ts +130 -0
  74. package/src/auth/anthropic.ts +63 -0
  75. package/src/auth/apply-stealth.ts +38 -0
  76. package/src/auth/claude-code-stealth.ts +141 -0
  77. package/src/auth/credentials.ts +226 -0
  78. package/src/auth/index.ts +18 -0
  79. package/src/auth/openai-codex.ts +94 -0
  80. package/src/auth/types.ts +24 -0
  81. package/src/awareness/registry.ts +220 -0
  82. package/src/bin.ts +10 -0
  83. package/src/cli/index.ts +36 -0
  84. package/src/cli/parse-duration.ts +43 -0
  85. package/src/cloud/auth.test.ts +370 -0
  86. package/src/cloud/auth.ts +176 -0
  87. package/src/cloud/backup.test.ts +150 -0
  88. package/src/cloud/backup.ts +50 -0
  89. package/src/cloud/base-url.ts +45 -0
  90. package/src/cloud/bridge-client.test.ts +481 -0
  91. package/src/cloud/bridge-client.ts +307 -0
  92. package/src/cloud/cloud-manager.test.ts +223 -0
  93. package/src/cloud/cloud-manager.ts +151 -0
  94. package/src/cloud/cloud-proxy.test.ts +122 -0
  95. package/src/cloud/cloud-proxy.ts +52 -0
  96. package/src/cloud/index.ts +23 -0
  97. package/src/cloud/reconnect.test.ts +178 -0
  98. package/src/cloud/reconnect.ts +108 -0
  99. package/src/cloud/validate-url.test.ts +147 -0
  100. package/src/cloud/validate-url.ts +176 -0
  101. package/src/config/character-schema.ts +44 -0
  102. package/src/config/config.ts +149 -0
  103. package/src/config/env-vars.ts +86 -0
  104. package/src/config/includes.ts +196 -0
  105. package/src/config/index.ts +15 -0
  106. package/src/config/object-utils.ts +10 -0
  107. package/src/config/paths.ts +92 -0
  108. package/src/config/plugin-auto-enable.ts +520 -0
  109. package/src/config/schema.ts +1342 -0
  110. package/src/config/telegram-custom-commands.ts +99 -0
  111. package/src/config/types.agent-defaults.ts +342 -0
  112. package/src/config/types.agents.ts +112 -0
  113. package/src/config/types.gateway.ts +243 -0
  114. package/src/config/types.hooks.ts +124 -0
  115. package/src/config/types.messages.ts +201 -0
  116. package/src/config/types.milady.ts +791 -0
  117. package/src/config/types.tools.ts +416 -0
  118. package/src/config/types.ts +7 -0
  119. package/src/config/zod-schema.agent-runtime.ts +777 -0
  120. package/src/config/zod-schema.core.ts +778 -0
  121. package/src/config/zod-schema.hooks.ts +139 -0
  122. package/src/config/zod-schema.providers-core.ts +1126 -0
  123. package/src/config/zod-schema.session.ts +98 -0
  124. package/src/config/zod-schema.ts +865 -0
  125. package/src/contracts/apps.ts +46 -0
  126. package/src/contracts/awareness.ts +56 -0
  127. package/src/contracts/config.ts +172 -0
  128. package/src/contracts/drop.ts +21 -0
  129. package/src/contracts/index.ts +8 -0
  130. package/src/contracts/onboarding.ts +592 -0
  131. package/src/contracts/permissions.ts +52 -0
  132. package/src/contracts/verification.ts +9 -0
  133. package/src/contracts/wallet.ts +503 -0
  134. package/src/diagnostics/integration-observability.ts +132 -0
  135. package/src/emotes/catalog.ts +655 -0
  136. package/src/external-modules.d.ts +7 -0
  137. package/src/hooks/discovery.test.ts +357 -0
  138. package/src/hooks/discovery.ts +231 -0
  139. package/src/hooks/eligibility.ts +146 -0
  140. package/src/hooks/hooks.test.ts +320 -0
  141. package/src/hooks/index.ts +8 -0
  142. package/src/hooks/loader.test.ts +418 -0
  143. package/src/hooks/loader.ts +256 -0
  144. package/src/hooks/registry.test.ts +168 -0
  145. package/src/hooks/registry.ts +74 -0
  146. package/src/hooks/types.ts +121 -0
  147. package/src/index.ts +19 -0
  148. package/src/onboarding-presets.ts +828 -0
  149. package/src/plugins/custom-rtmp/index.ts +40 -0
  150. package/src/providers/admin-trust.ts +76 -0
  151. package/src/providers/session-bridge.ts +143 -0
  152. package/src/providers/session-utils.ts +42 -0
  153. package/src/providers/simple-mode.ts +113 -0
  154. package/src/providers/ui-catalog.ts +135 -0
  155. package/src/providers/workspace-provider.ts +213 -0
  156. package/src/providers/workspace.ts +497 -0
  157. package/src/runtime/agent-event-service.ts +57 -0
  158. package/src/runtime/cloud-onboarding.test.ts +489 -0
  159. package/src/runtime/cloud-onboarding.ts +408 -0
  160. package/src/runtime/core-plugins.ts +53 -0
  161. package/src/runtime/custom-actions.ts +605 -0
  162. package/src/runtime/eliza.ts +4941 -0
  163. package/src/runtime/embedding-presets.ts +73 -0
  164. package/src/runtime/index.ts +8 -0
  165. package/src/runtime/milady-plugin.ts +180 -0
  166. package/src/runtime/onboarding-names.ts +76 -0
  167. package/src/runtime/release-plugin-policy.ts +119 -0
  168. package/src/runtime/restart.ts +59 -0
  169. package/src/runtime/trajectory-persistence.ts +2584 -0
  170. package/src/runtime/version.ts +6 -0
  171. package/src/security/audit-log.ts +222 -0
  172. package/src/security/network-policy.ts +91 -0
  173. package/src/server/index.ts +6 -0
  174. package/src/services/agent-export.ts +976 -0
  175. package/src/services/app-manager.ts +755 -0
  176. package/src/services/browser-capture.ts +215 -0
  177. package/src/services/coding-agent-context.ts +355 -0
  178. package/src/services/fallback-training-service.ts +196 -0
  179. package/src/services/index.ts +17 -0
  180. package/src/services/mcp-marketplace.ts +327 -0
  181. package/src/services/plugin-manager-types.ts +185 -0
  182. package/src/services/privy-wallets.ts +352 -0
  183. package/src/services/registry-client-app-meta.ts +201 -0
  184. package/src/services/registry-client-endpoints.ts +253 -0
  185. package/src/services/registry-client-local.ts +485 -0
  186. package/src/services/registry-client-network.ts +173 -0
  187. package/src/services/registry-client-queries.ts +176 -0
  188. package/src/services/registry-client-types.ts +104 -0
  189. package/src/services/registry-client.ts +366 -0
  190. package/src/services/remote-signing-service.ts +261 -0
  191. package/src/services/sandbox-engine.ts +753 -0
  192. package/src/services/sandbox-manager.ts +503 -0
  193. package/src/services/self-updater.ts +213 -0
  194. package/src/services/signal-pairing.ts +189 -0
  195. package/src/services/signing-policy.ts +230 -0
  196. package/src/services/skill-catalog-client.ts +195 -0
  197. package/src/services/skill-marketplace.ts +909 -0
  198. package/src/services/stream-manager.ts +707 -0
  199. package/src/services/tts-stream-bridge.ts +465 -0
  200. package/src/services/update-checker.ts +163 -0
  201. package/src/services/version-compat.ts +367 -0
  202. package/src/services/whatsapp-pairing.ts +279 -0
  203. package/src/shared/ui-catalog-prompt.ts +1158 -0
  204. package/src/test-support/process-helpers.ts +35 -0
  205. package/src/test-support/route-test-helpers.ts +113 -0
  206. package/src/test-support/test-helpers.ts +304 -0
  207. package/src/testing/index.ts +3 -0
  208. package/src/triggers/action.ts +342 -0
  209. package/src/triggers/runtime.ts +432 -0
  210. package/src/triggers/scheduling.ts +472 -0
  211. package/src/triggers/types.ts +133 -0
  212. package/src/types/app-hyperscape-routes-shim.d.ts +29 -0
  213. package/src/types/external-modules.d.ts +7 -0
  214. package/src/utils/exec-safety.ts +23 -0
  215. package/src/utils/number-parsing.ts +112 -0
  216. package/src/utils/spoken-text.ts +65 -0
  217. package/src/version-resolver.ts +60 -0
  218. package/test/api/agent-admin-routes.test.ts +160 -0
  219. package/test/api/agent-lifecycle-routes.test.ts +164 -0
  220. package/test/api/agent-transfer-routes.test.ts +136 -0
  221. package/test/api/apps-routes.test.ts +140 -0
  222. package/test/api/auth-routes.test.ts +160 -0
  223. package/test/api/bug-report-routes.test.ts +88 -0
  224. package/test/api/knowledge-routes.test.ts +73 -0
  225. package/test/api/lifecycle.test.ts +342 -0
  226. package/test/api/memory-routes.test.ts +74 -0
  227. package/test/api/models-routes.test.ts +112 -0
  228. package/test/api/nfa-routes.test.ts +78 -0
  229. package/test/api/permissions-routes.test.ts +185 -0
  230. package/test/api/registry-routes.test.ts +157 -0
  231. package/test/api/signal-routes.test.ts +113 -0
  232. package/test/api/subscription-routes.test.ts +90 -0
  233. package/test/api/trigger-routes.test.ts +87 -0
  234. package/test/api/wallet-routes.observability.test.ts +191 -0
  235. package/test/api/wallet-routes.test.ts +502 -0
  236. package/test/diagnostics/integration-observability.test.ts +135 -0
  237. package/test/security/audit-log.test.ts +229 -0
  238. package/test/security/network-policy.test.ts +143 -0
  239. package/test/services/version-compat.test.ts +127 -0
  240. package/tsconfig.build.json +21 -0
  241. package/tsconfig.json +19 -0
@@ -0,0 +1,472 @@
1
+ import type { UUID } from "@elizaos/core";
2
+ import {
3
+ type NormalizedTriggerDraft,
4
+ TRIGGER_SCHEMA_VERSION,
5
+ type TriggerConfig,
6
+ type TriggerTaskMetadata,
7
+ type TriggerType,
8
+ type TriggerWakeMode,
9
+ } from "./types";
10
+
11
+ export const MIN_TRIGGER_INTERVAL_MS = 60_000;
12
+ export const MAX_TRIGGER_INTERVAL_MS = 31 * 24 * 60 * 60 * 1000;
13
+ export const DISABLED_TRIGGER_INTERVAL_MS = 365 * 24 * 60 * 60 * 1000;
14
+ export const MAX_TRIGGER_RUN_HISTORY = 100;
15
+
16
+ const CRON_FIELDS = 5;
17
+ const CRON_SCAN_WINDOW_MS = 366 * 24 * 60 * 60 * 1000;
18
+ const CRON_MINUTE_MS = 60_000;
19
+
20
+ interface CronRange {
21
+ min: number;
22
+ max: number;
23
+ }
24
+
25
+ interface CronSchedule {
26
+ minute: Set<number>;
27
+ hour: Set<number>;
28
+ dayOfMonth: Set<number>;
29
+ month: Set<number>;
30
+ dayOfWeek: Set<number>;
31
+ }
32
+
33
+ const CRON_RANGES: readonly CronRange[] = [
34
+ { min: 0, max: 59 },
35
+ { min: 0, max: 23 },
36
+ { min: 1, max: 31 },
37
+ { min: 1, max: 12 },
38
+ { min: 0, max: 6 },
39
+ ];
40
+
41
+ export interface TriggerTiming {
42
+ updatedAt: number;
43
+ updateIntervalMs: number;
44
+ nextRunAtMs: number;
45
+ }
46
+
47
+ interface DraftInput {
48
+ displayName?: string;
49
+ instructions?: string;
50
+ triggerType?: TriggerType;
51
+ wakeMode?: TriggerWakeMode;
52
+ enabled?: boolean;
53
+ createdBy?: string;
54
+ timezone?: string;
55
+ intervalMs?: number;
56
+ scheduledAtIso?: string;
57
+ cronExpression?: string;
58
+ maxRuns?: number;
59
+ }
60
+
61
+ function parseInteger(raw: string): number | null {
62
+ if (!/^-?\d+$/.test(raw)) return null;
63
+ const value = Number(raw);
64
+ if (!Number.isFinite(value)) return null;
65
+ return value;
66
+ }
67
+
68
+ function clamp(value: number, min: number, max: number): number {
69
+ if (value < min) return min;
70
+ if (value > max) return max;
71
+ return value;
72
+ }
73
+
74
+ function normalizeText(value: string): string {
75
+ return value.trim().replace(/\s+/g, " ");
76
+ }
77
+
78
+ function parseCronPart(part: string, range: CronRange): Set<number> | null {
79
+ const output = new Set<number>();
80
+ const chunks = part.split(",");
81
+
82
+ for (const chunkRaw of chunks) {
83
+ const chunk = chunkRaw.trim();
84
+ if (!chunk) return null;
85
+
86
+ const stepParts = chunk.split("/");
87
+ if (stepParts.length > 2) return null;
88
+ const step = stepParts.length === 2 ? parseInteger(stepParts[1].trim()) : 1;
89
+ if (step === null || step <= 0) return null;
90
+
91
+ const base = stepParts[0].trim();
92
+ if (base === "*") {
93
+ for (let value = range.min; value <= range.max; value += step) {
94
+ output.add(value);
95
+ }
96
+ continue;
97
+ }
98
+
99
+ const rangeParts = base.split("-");
100
+ if (rangeParts.length === 1) {
101
+ const single = parseInteger(rangeParts[0].trim());
102
+ if (single === null) return null;
103
+ if (single < range.min || single > range.max) return null;
104
+ output.add(single);
105
+ continue;
106
+ }
107
+
108
+ if (rangeParts.length !== 2) return null;
109
+ const start = parseInteger(rangeParts[0].trim());
110
+ const end = parseInteger(rangeParts[1].trim());
111
+ if (start === null || end === null) return null;
112
+ if (start > end) return null;
113
+ if (start < range.min || end > range.max) return null;
114
+ for (let value = start; value <= end; value += step) {
115
+ output.add(value);
116
+ }
117
+ }
118
+
119
+ return output.size > 0 ? output : null;
120
+ }
121
+
122
+ export function parseCronExpression(expression: string): CronSchedule | null {
123
+ const trimmed = expression.trim();
124
+ if (!trimmed) return null;
125
+ const parts = trimmed.split(/\s+/);
126
+ if (parts.length !== CRON_FIELDS) return null;
127
+
128
+ const minute = parseCronPart(parts[0], CRON_RANGES[0]);
129
+ const hour = parseCronPart(parts[1], CRON_RANGES[1]);
130
+ const dayOfMonth = parseCronPart(parts[2], CRON_RANGES[2]);
131
+ const month = parseCronPart(parts[3], CRON_RANGES[3]);
132
+ const dayOfWeek = parseCronPart(parts[4], CRON_RANGES[4]);
133
+
134
+ if (!minute || !hour || !dayOfMonth || !month || !dayOfWeek) {
135
+ return null;
136
+ }
137
+
138
+ return {
139
+ minute,
140
+ hour,
141
+ dayOfMonth,
142
+ month,
143
+ dayOfWeek,
144
+ };
145
+ }
146
+
147
+ function cronMatchesUTC(schedule: CronSchedule, candidateMs: number): boolean {
148
+ const candidate = new Date(candidateMs);
149
+ return (
150
+ schedule.minute.has(candidate.getUTCMinutes()) &&
151
+ schedule.hour.has(candidate.getUTCHours()) &&
152
+ schedule.dayOfMonth.has(candidate.getUTCDate()) &&
153
+ schedule.month.has(candidate.getUTCMonth() + 1) &&
154
+ schedule.dayOfWeek.has(candidate.getUTCDay())
155
+ );
156
+ }
157
+
158
+ function getTimezoneOffsetMs(
159
+ timezone: string | undefined,
160
+ atMs: number,
161
+ ): number {
162
+ if (!timezone || timezone === "UTC") return 0;
163
+ try {
164
+ const formatter = new Intl.DateTimeFormat("en-US", {
165
+ timeZone: timezone,
166
+ year: "numeric",
167
+ month: "2-digit",
168
+ day: "2-digit",
169
+ hour: "2-digit",
170
+ minute: "2-digit",
171
+ second: "2-digit",
172
+ hour12: false,
173
+ });
174
+ const parts = formatter.formatToParts(new Date(atMs));
175
+ const get = (type: string): number => {
176
+ const part = parts.find((p) => p.type === type);
177
+ return part ? Number(part.value) : 0;
178
+ };
179
+ const tzDate = Date.UTC(
180
+ get("year"),
181
+ get("month") - 1,
182
+ get("day"),
183
+ get("hour"),
184
+ get("minute"),
185
+ get("second"),
186
+ );
187
+ return tzDate - atMs;
188
+ } catch {
189
+ return 0;
190
+ }
191
+ }
192
+
193
+ function cronMatches(
194
+ schedule: CronSchedule,
195
+ candidateMs: number,
196
+ timezone?: string,
197
+ ): boolean {
198
+ if (!timezone || timezone === "UTC") {
199
+ return cronMatchesUTC(schedule, candidateMs);
200
+ }
201
+ const offsetMs = getTimezoneOffsetMs(timezone, candidateMs);
202
+ const wallClockMs = candidateMs + offsetMs;
203
+ return cronMatchesUTC(schedule, wallClockMs);
204
+ }
205
+
206
+ export function computeNextCronRunAtMs(
207
+ expression: string,
208
+ fromMs: number,
209
+ timezone?: string,
210
+ ): number | null {
211
+ const schedule = parseCronExpression(expression);
212
+ if (!schedule) return null;
213
+
214
+ const start = Math.floor(fromMs / CRON_MINUTE_MS) * CRON_MINUTE_MS;
215
+ const cutoff = start + CRON_SCAN_WINDOW_MS;
216
+ for (
217
+ let candidate = start + CRON_MINUTE_MS;
218
+ candidate <= cutoff;
219
+ candidate += CRON_MINUTE_MS
220
+ ) {
221
+ if (cronMatches(schedule, candidate, timezone)) {
222
+ return candidate;
223
+ }
224
+ }
225
+ return null;
226
+ }
227
+
228
+ export function parseScheduledAtIso(scheduledAtIso: string): number | null {
229
+ const parsed = Date.parse(scheduledAtIso);
230
+ if (!Number.isFinite(parsed)) return null;
231
+ return parsed;
232
+ }
233
+
234
+ export function normalizeTriggerIntervalMs(intervalMs: number): number {
235
+ if (!Number.isFinite(intervalMs)) return MIN_TRIGGER_INTERVAL_MS;
236
+ const rounded = Math.floor(intervalMs);
237
+ return clamp(rounded, MIN_TRIGGER_INTERVAL_MS, MAX_TRIGGER_INTERVAL_MS);
238
+ }
239
+
240
+ export function resolveTriggerTiming(
241
+ trigger: TriggerConfig,
242
+ nowMs: number,
243
+ ): TriggerTiming | null {
244
+ if (!trigger.enabled) return null;
245
+
246
+ if (trigger.triggerType === "interval") {
247
+ const intervalMs = normalizeTriggerIntervalMs(trigger.intervalMs ?? 0);
248
+ return {
249
+ updatedAt: nowMs,
250
+ updateIntervalMs: intervalMs,
251
+ nextRunAtMs: nowMs + intervalMs,
252
+ };
253
+ }
254
+
255
+ if (trigger.triggerType === "once") {
256
+ const scheduledAt = trigger.scheduledAtIso
257
+ ? parseScheduledAtIso(trigger.scheduledAtIso)
258
+ : null;
259
+ if (scheduledAt === null) return null;
260
+ const nextRunAtMs = Math.max(nowMs, scheduledAt);
261
+ return {
262
+ updatedAt: nowMs,
263
+ updateIntervalMs: Math.max(0, nextRunAtMs - nowMs),
264
+ nextRunAtMs,
265
+ };
266
+ }
267
+
268
+ const nextRunAtMs = trigger.cronExpression
269
+ ? computeNextCronRunAtMs(trigger.cronExpression, nowMs, trigger.timezone)
270
+ : null;
271
+ if (nextRunAtMs === null) return null;
272
+ return {
273
+ updatedAt: nowMs,
274
+ updateIntervalMs: Math.max(0, nextRunAtMs - nowMs),
275
+ nextRunAtMs,
276
+ };
277
+ }
278
+
279
+ export function buildTriggerMetadata(params: {
280
+ existingMetadata?: TriggerTaskMetadata;
281
+ trigger: TriggerConfig;
282
+ nowMs: number;
283
+ }): TriggerTaskMetadata | null {
284
+ const timing = resolveTriggerTiming(params.trigger, params.nowMs);
285
+ if (!timing) return null;
286
+
287
+ return {
288
+ ...(params.existingMetadata ?? {}),
289
+ blocking: true,
290
+ updatedAt: timing.updatedAt,
291
+ updateInterval: timing.updateIntervalMs,
292
+ trigger: {
293
+ ...params.trigger,
294
+ nextRunAtMs: timing.nextRunAtMs,
295
+ },
296
+ };
297
+ }
298
+
299
+ export function buildTriggerDedupeKey(parts: {
300
+ triggerType: TriggerType;
301
+ instructions: string;
302
+ intervalMs?: number;
303
+ scheduledAtIso?: string;
304
+ cronExpression?: string;
305
+ wakeMode: TriggerWakeMode;
306
+ }): string {
307
+ const normalized = [
308
+ parts.triggerType,
309
+ normalizeText(parts.instructions).toLowerCase(),
310
+ String(parts.intervalMs ?? ""),
311
+ parts.scheduledAtIso ?? "",
312
+ parts.cronExpression ?? "",
313
+ parts.wakeMode,
314
+ ].join("|");
315
+ let hash = 5381;
316
+ for (const char of normalized) {
317
+ hash = (hash * 33) ^ char.charCodeAt(0);
318
+ }
319
+ return `trigger-${Math.abs(hash >>> 0).toString(16)}`;
320
+ }
321
+
322
+ export function buildTriggerConfig(params: {
323
+ draft: NormalizedTriggerDraft;
324
+ triggerId: UUID;
325
+ previous?: TriggerConfig;
326
+ }): TriggerConfig {
327
+ const previous = params.previous;
328
+ return {
329
+ version: TRIGGER_SCHEMA_VERSION,
330
+ triggerId: params.triggerId,
331
+ displayName: params.draft.displayName,
332
+ instructions: params.draft.instructions,
333
+ triggerType: params.draft.triggerType,
334
+ enabled: params.draft.enabled,
335
+ wakeMode: params.draft.wakeMode,
336
+ createdBy: params.draft.createdBy,
337
+ timezone: params.draft.timezone,
338
+ intervalMs:
339
+ params.draft.triggerType === "interval"
340
+ ? normalizeTriggerIntervalMs(params.draft.intervalMs ?? 0)
341
+ : undefined,
342
+ scheduledAtIso:
343
+ params.draft.triggerType === "once"
344
+ ? params.draft.scheduledAtIso
345
+ : undefined,
346
+ cronExpression:
347
+ params.draft.triggerType === "cron"
348
+ ? params.draft.cronExpression
349
+ : undefined,
350
+ maxRuns: params.draft.maxRuns,
351
+ runCount: previous?.runCount ?? 0,
352
+ dedupeKey: buildTriggerDedupeKey({
353
+ triggerType: params.draft.triggerType,
354
+ instructions: params.draft.instructions,
355
+ intervalMs: params.draft.intervalMs,
356
+ scheduledAtIso: params.draft.scheduledAtIso,
357
+ cronExpression: params.draft.cronExpression,
358
+ wakeMode: params.draft.wakeMode,
359
+ }),
360
+ nextRunAtMs: previous?.nextRunAtMs,
361
+ lastRunAtIso: previous?.lastRunAtIso,
362
+ lastStatus: previous?.lastStatus,
363
+ lastError: previous?.lastError,
364
+ };
365
+ }
366
+
367
+ export function normalizeTriggerDraft(params: {
368
+ input: DraftInput;
369
+ fallback: {
370
+ displayName: string;
371
+ instructions: string;
372
+ triggerType: TriggerType;
373
+ wakeMode: TriggerWakeMode;
374
+ enabled: boolean;
375
+ createdBy: string;
376
+ };
377
+ }): { draft?: NormalizedTriggerDraft; error?: string } {
378
+ const displayName =
379
+ normalizeText(params.input.displayName ?? "") ||
380
+ normalizeText(params.fallback.displayName);
381
+ const instructions =
382
+ normalizeText(params.input.instructions ?? "") ||
383
+ normalizeText(params.fallback.instructions);
384
+ if (!displayName) {
385
+ return { error: "displayName is required" };
386
+ }
387
+ if (!instructions) {
388
+ return { error: "instructions is required" };
389
+ }
390
+
391
+ const triggerType =
392
+ params.input.triggerType ?? params.fallback.triggerType ?? "interval";
393
+ const wakeMode = params.input.wakeMode ?? params.fallback.wakeMode;
394
+ const enabled = params.input.enabled ?? params.fallback.enabled;
395
+ const createdBy = params.input.createdBy ?? params.fallback.createdBy;
396
+ const timezone = params.input.timezone;
397
+ const intervalMsRaw =
398
+ typeof params.input.intervalMs === "number"
399
+ ? params.input.intervalMs
400
+ : undefined;
401
+ const scheduledAtIso = params.input.scheduledAtIso?.trim();
402
+ const cronExpression = params.input.cronExpression?.trim();
403
+ const maxRuns =
404
+ typeof params.input.maxRuns === "number"
405
+ ? Math.floor(params.input.maxRuns)
406
+ : undefined;
407
+
408
+ if (wakeMode !== "inject_now" && wakeMode !== "next_autonomy_cycle") {
409
+ return { error: "wakeMode must be inject_now or next_autonomy_cycle" };
410
+ }
411
+
412
+ if (maxRuns !== undefined && maxRuns <= 0) {
413
+ return { error: "maxRuns must be a positive integer" };
414
+ }
415
+
416
+ if (triggerType === "interval") {
417
+ if (intervalMsRaw === undefined) {
418
+ return { error: "intervalMs is required for interval triggers" };
419
+ }
420
+ const intervalMs = normalizeTriggerIntervalMs(intervalMsRaw);
421
+ return {
422
+ draft: {
423
+ displayName,
424
+ instructions,
425
+ triggerType,
426
+ wakeMode,
427
+ enabled,
428
+ createdBy,
429
+ timezone,
430
+ intervalMs,
431
+ maxRuns,
432
+ },
433
+ };
434
+ }
435
+
436
+ if (triggerType === "once") {
437
+ if (!scheduledAtIso || parseScheduledAtIso(scheduledAtIso) === null) {
438
+ return { error: "scheduledAtIso must be a valid ISO timestamp" };
439
+ }
440
+ return {
441
+ draft: {
442
+ displayName,
443
+ instructions,
444
+ triggerType,
445
+ wakeMode,
446
+ enabled,
447
+ createdBy,
448
+ timezone,
449
+ scheduledAtIso,
450
+ maxRuns,
451
+ },
452
+ };
453
+ }
454
+
455
+ if (!cronExpression || !parseCronExpression(cronExpression)) {
456
+ return { error: "cronExpression must be a valid 5-field cron expression" };
457
+ }
458
+
459
+ return {
460
+ draft: {
461
+ displayName,
462
+ instructions,
463
+ triggerType,
464
+ wakeMode,
465
+ enabled,
466
+ createdBy,
467
+ timezone,
468
+ cronExpression,
469
+ maxRuns,
470
+ },
471
+ };
472
+ }
@@ -0,0 +1,133 @@
1
+ import type { UUID } from "@elizaos/core";
2
+
3
+ export const TRIGGER_SCHEMA_VERSION = 1 as const;
4
+
5
+ export type TriggerType = "interval" | "once" | "cron";
6
+ export type TriggerWakeMode = "inject_now" | "next_autonomy_cycle";
7
+ export type TriggerLastStatus = "success" | "error" | "skipped";
8
+
9
+ export interface TriggerConfig {
10
+ version: typeof TRIGGER_SCHEMA_VERSION;
11
+ triggerId: UUID;
12
+ displayName: string;
13
+ instructions: string;
14
+ triggerType: TriggerType;
15
+ enabled: boolean;
16
+ wakeMode: TriggerWakeMode;
17
+ createdBy: string;
18
+ timezone?: string;
19
+ intervalMs?: number;
20
+ scheduledAtIso?: string;
21
+ cronExpression?: string;
22
+ maxRuns?: number;
23
+ runCount: number;
24
+ dedupeKey?: string;
25
+ nextRunAtMs?: number;
26
+ lastRunAtIso?: string;
27
+ lastStatus?: TriggerLastStatus;
28
+ lastError?: string;
29
+ }
30
+
31
+ export interface TriggerRunRecord {
32
+ triggerRunId: UUID;
33
+ triggerId: UUID;
34
+ taskId: UUID;
35
+ startedAt: number;
36
+ finishedAt: number;
37
+ status: TriggerLastStatus;
38
+ error?: string;
39
+ latencyMs: number;
40
+ source: "scheduler" | "manual";
41
+ }
42
+
43
+ export interface TriggerTaskMetadata {
44
+ updatedAt?: number;
45
+ updateInterval?: number;
46
+ blocking?: boolean;
47
+ trigger?: TriggerConfig;
48
+ triggerRuns?: TriggerRunRecord[];
49
+ [key: string]:
50
+ | string
51
+ | number
52
+ | boolean
53
+ | string[]
54
+ | number[]
55
+ | Record<string, string | number | boolean>
56
+ | undefined
57
+ | TriggerConfig
58
+ | TriggerRunRecord[];
59
+ }
60
+
61
+ export interface TriggerSummary {
62
+ id: UUID;
63
+ taskId: UUID;
64
+ displayName: string;
65
+ instructions: string;
66
+ triggerType: TriggerType;
67
+ enabled: boolean;
68
+ wakeMode: TriggerWakeMode;
69
+ createdBy: string;
70
+ timezone?: string;
71
+ intervalMs?: number;
72
+ scheduledAtIso?: string;
73
+ cronExpression?: string;
74
+ maxRuns?: number;
75
+ runCount: number;
76
+ nextRunAtMs?: number;
77
+ lastRunAtIso?: string;
78
+ lastStatus?: TriggerLastStatus;
79
+ lastError?: string;
80
+ updatedAt?: number;
81
+ updateInterval?: number;
82
+ }
83
+
84
+ export interface TriggerHealthSnapshot {
85
+ triggersEnabled: boolean;
86
+ activeTriggers: number;
87
+ disabledTriggers: number;
88
+ totalExecutions: number;
89
+ totalFailures: number;
90
+ totalSkipped: number;
91
+ lastExecutionAt?: number;
92
+ }
93
+
94
+ export interface CreateTriggerRequest {
95
+ displayName?: string;
96
+ instructions?: string;
97
+ triggerType?: TriggerType;
98
+ wakeMode?: TriggerWakeMode;
99
+ enabled?: boolean;
100
+ createdBy?: string;
101
+ timezone?: string;
102
+ intervalMs?: number;
103
+ scheduledAtIso?: string;
104
+ cronExpression?: string;
105
+ maxRuns?: number;
106
+ }
107
+
108
+ export interface UpdateTriggerRequest {
109
+ displayName?: string;
110
+ instructions?: string;
111
+ triggerType?: TriggerType;
112
+ wakeMode?: TriggerWakeMode;
113
+ enabled?: boolean;
114
+ timezone?: string;
115
+ intervalMs?: number;
116
+ scheduledAtIso?: string;
117
+ cronExpression?: string;
118
+ maxRuns?: number;
119
+ }
120
+
121
+ export interface NormalizedTriggerDraft {
122
+ displayName: string;
123
+ instructions: string;
124
+ triggerType: TriggerType;
125
+ wakeMode: TriggerWakeMode;
126
+ enabled: boolean;
127
+ createdBy: string;
128
+ timezone?: string;
129
+ intervalMs?: number;
130
+ scheduledAtIso?: string;
131
+ cronExpression?: string;
132
+ maxRuns?: number;
133
+ }
@@ -0,0 +1,29 @@
1
+ declare module "@elizaos/app-hyperscape/routes" {
2
+ import type * as http from "node:http";
3
+
4
+ export interface HyperscapeRelayOptions {
5
+ rawBodyOverride?: string;
6
+ contentTypeOverride?: string;
7
+ }
8
+
9
+ export interface AppsHyperscapeRouteContext {
10
+ req: http.IncomingMessage;
11
+ res: http.ServerResponse;
12
+ method: string;
13
+ pathname: string;
14
+ readJsonBody: <T extends object>(
15
+ req: http.IncomingMessage,
16
+ res: http.ServerResponse,
17
+ ) => Promise<T | null>;
18
+ error: (res: http.ServerResponse, message: string, status?: number) => void;
19
+ relayHyperscapeApi: (
20
+ method: "GET" | "POST",
21
+ path: string,
22
+ options?: HyperscapeRelayOptions,
23
+ ) => Promise<void>;
24
+ }
25
+
26
+ export function handleAppsHyperscapeRoutes(
27
+ ctx: AppsHyperscapeRouteContext,
28
+ ): Promise<boolean>;
29
+ }
@@ -0,0 +1,7 @@
1
+ declare module "@elizaos/plugin-coding-agent";
2
+ declare module "@elizaos/plugin-pi-ai";
3
+ declare module "@elizaos/plugin-secrets-manager";
4
+ declare module "@elizaos/plugin-trajectory-logger";
5
+ declare module "@elizaos/skills";
6
+ declare module "@elizaos/signal-native";
7
+ declare module "qrcode";
@@ -0,0 +1,23 @@
1
+ const UNSAFE_CHARS = /[\0\r\n;&|`$<>"']/;
2
+ const BARE_NAME = /^[A-Za-z0-9._+-]+$/;
3
+
4
+ function isLikelyPath(value: string): boolean {
5
+ return (
6
+ value.startsWith(".") ||
7
+ value.startsWith("~") ||
8
+ value.includes("/") ||
9
+ value.includes("\\") ||
10
+ /^[A-Za-z]:[\\/]/.test(value)
11
+ );
12
+ }
13
+
14
+ export function isSafeExecutableValue(
15
+ value: string | null | undefined,
16
+ ): boolean {
17
+ const trimmed = value?.trim();
18
+ if (!trimmed) return false;
19
+ if (UNSAFE_CHARS.test(trimmed)) return false;
20
+ if (isLikelyPath(trimmed)) return true;
21
+ if (trimmed.startsWith("-")) return false;
22
+ return BARE_NAME.test(trimmed);
23
+ }