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.
- package/dist/_virtual/_rolldown/runtime.js +7 -0
- package/dist/actions/emote.js +64 -0
- package/dist/actions/restart.js +81 -0
- package/dist/actions/send-message.js +152 -0
- package/dist/agent-admin-routes.js +82 -0
- package/dist/agent-lifecycle-routes.js +79 -0
- package/dist/agent-transfer-routes.js +102 -0
- package/dist/api/agent-admin-routes.js +82 -0
- package/dist/api/agent-lifecycle-routes.js +79 -0
- package/dist/api/agent-transfer-routes.js +102 -0
- package/dist/api/apps-hyperscape-routes.js +58 -0
- package/dist/api/apps-routes.js +114 -0
- package/dist/api/auth-routes.js +56 -0
- package/dist/api/autonomy-routes.js +44 -0
- package/dist/api/bug-report-routes.js +111 -0
- package/dist/api/character-routes.js +195 -0
- package/dist/api/cloud-routes.js +330 -0
- package/dist/api/cloud-status-routes.js +155 -0
- package/dist/api/compat-utils.js +111 -0
- package/dist/api/database.js +735 -0
- package/dist/api/diagnostics-routes.js +205 -0
- package/dist/api/drop-service.js +134 -0
- package/dist/api/early-logs.js +86 -0
- package/dist/api/http-helpers.js +131 -0
- package/dist/api/knowledge-routes.js +534 -0
- package/dist/api/memory-bounds.js +71 -0
- package/dist/api/models-routes.js +28 -0
- package/dist/api/og-tracker.js +36 -0
- package/dist/api/permissions-routes.js +109 -0
- package/dist/api/plugin-validation.js +198 -0
- package/dist/api/provider-switch-config.js +41 -0
- package/dist/api/registry-routes.js +86 -0
- package/dist/api/registry-service.js +164 -0
- package/dist/api/sandbox-routes.js +1112 -0
- package/dist/api/server.js +7949 -0
- package/dist/api/subscription-routes.js +172 -0
- package/dist/api/terminal-run-limits.js +24 -0
- package/dist/api/training-routes.js +158 -0
- package/dist/api/trajectory-routes.js +300 -0
- package/dist/api/trigger-routes.js +246 -0
- package/dist/api/twitter-verify.js +134 -0
- package/dist/api/tx-service.js +108 -0
- package/dist/api/wallet-routes.js +266 -0
- package/dist/api/wallet.js +568 -0
- package/dist/api/whatsapp-routes.js +182 -0
- package/dist/api/zip-utils.js +109 -0
- package/dist/apps-hyperscape-routes.js +58 -0
- package/dist/apps-routes.js +114 -0
- package/dist/ascii.js +20 -0
- package/dist/auth/anthropic.js +44 -0
- package/dist/auth/apply-stealth.js +41 -0
- package/dist/auth/claude-code-stealth.js +78 -0
- package/dist/auth/credentials.js +156 -0
- package/dist/auth/index.js +5 -0
- package/dist/auth/openai-codex.js +66 -0
- package/dist/auth/types.js +9 -0
- package/dist/auth-routes.js +56 -0
- package/dist/autonomy-routes.js +44 -0
- package/dist/bug-report-routes.js +111 -0
- package/dist/build-info.json +6 -0
- package/dist/character-routes.js +195 -0
- package/dist/cli/argv.js +63 -0
- package/dist/cli/banner.js +34 -0
- package/dist/cli/cli-name.js +21 -0
- package/dist/cli/cli-utils.js +16 -0
- package/dist/cli/git-commit.js +78 -0
- package/dist/cli/parse-duration.js +15 -0
- package/dist/cli/plugins-cli.js +590 -0
- package/dist/cli/profile-utils.js +9 -0
- package/dist/cli/profile.js +95 -0
- package/dist/cli/program/build-program.js +17 -0
- package/dist/cli/program/command-registry.js +23 -0
- package/dist/cli/program/help.js +47 -0
- package/dist/cli/program/preaction.js +33 -0
- package/dist/cli/program/register.config.js +106 -0
- package/dist/cli/program/register.configure.js +20 -0
- package/dist/cli/program/register.dashboard.js +124 -0
- package/dist/cli/program/register.models.js +23 -0
- package/dist/cli/program/register.setup.js +36 -0
- package/dist/cli/program/register.start.js +22 -0
- package/dist/cli/program/register.subclis.js +70 -0
- package/dist/cli/program/register.tui.js +163 -0
- package/dist/cli/program/register.update.js +154 -0
- package/dist/cli/program.js +3 -0
- package/dist/cli/run-main.js +37 -0
- package/dist/cli/version.js +7 -0
- package/dist/cloud/validate-url.js +93 -0
- package/dist/cloud-routes.js +330 -0
- package/dist/cloud-status-routes.js +155 -0
- package/dist/compat-utils.js +111 -0
- package/dist/config/config.js +69 -0
- package/dist/config/env-vars.js +19 -0
- package/dist/config/includes.js +121 -0
- package/dist/config/object-utils.js +7 -0
- package/dist/config/paths.js +38 -0
- package/dist/config/plugin-auto-enable.js +231 -0
- package/dist/config/schema.js +864 -0
- package/dist/config/telegram-custom-commands.js +76 -0
- package/dist/config/zod-schema.agent-runtime.js +519 -0
- package/dist/config/zod-schema.core.js +538 -0
- package/dist/config/zod-schema.hooks.js +103 -0
- package/dist/config/zod-schema.js +488 -0
- package/dist/config/zod-schema.providers-core.js +785 -0
- package/dist/config/zod-schema.session.js +73 -0
- package/dist/core-plugins.js +37 -0
- package/dist/custom-actions.js +250 -0
- package/dist/database.js +735 -0
- package/dist/diagnostics/integration-observability.js +57 -0
- package/dist/diagnostics-routes.js +205 -0
- package/dist/drop-service.js +134 -0
- package/dist/early-logs.js +24 -0
- package/dist/eliza.js +2061 -0
- package/dist/emotes/catalog.js +271 -0
- package/dist/entry.js +40 -0
- package/dist/hooks/discovery.js +167 -0
- package/dist/hooks/eligibility.js +64 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/loader.js +147 -0
- package/dist/hooks/registry.js +55 -0
- package/dist/http-helpers.js +131 -0
- package/dist/index.js +49 -0
- package/dist/knowledge-routes.js +534 -0
- package/dist/memory-bounds.js +71 -0
- package/dist/milady-plugin.js +90 -0
- package/dist/models-routes.js +28 -0
- package/dist/onboarding-names.js +78 -0
- package/dist/onboarding-presets.js +922 -0
- package/dist/package.json +1 -0
- package/dist/permissions-routes.js +109 -0
- package/dist/plugin-validation.js +107 -0
- package/dist/plugins/whatsapp/actions.js +91 -0
- package/dist/plugins/whatsapp/index.js +16 -0
- package/dist/plugins/whatsapp/service.js +270 -0
- package/dist/provider-switch-config.js +41 -0
- package/dist/providers/admin-trust.js +46 -0
- package/dist/providers/autonomous-state.js +101 -0
- package/dist/providers/session-bridge.js +86 -0
- package/dist/providers/session-utils.js +36 -0
- package/dist/providers/simple-mode.js +50 -0
- package/dist/providers/ui-catalog.js +15 -0
- package/dist/providers/workspace-provider.js +93 -0
- package/dist/providers/workspace.js +348 -0
- package/dist/registry-routes.js +86 -0
- package/dist/registry-service.js +164 -0
- package/dist/restart.js +40 -0
- package/dist/runtime/core-plugins.js +37 -0
- package/dist/runtime/custom-actions.js +250 -0
- package/dist/runtime/eliza.js +2061 -0
- package/dist/runtime/embedding-manager-support.js +185 -0
- package/dist/runtime/embedding-manager.js +193 -0
- package/dist/runtime/embedding-presets.js +54 -0
- package/dist/runtime/embedding-state.js +8 -0
- package/dist/runtime/milady-plugin.js +90 -0
- package/dist/runtime/onboarding-names.js +78 -0
- package/dist/runtime/restart.js +40 -0
- package/dist/runtime/version.js +7 -0
- package/dist/sandbox-routes.js +1112 -0
- package/dist/security/audit-log.js +149 -0
- package/dist/security/network-policy.js +70 -0
- package/dist/server.js +7949 -0
- package/dist/services/agent-export.js +559 -0
- package/dist/services/app-manager.js +389 -0
- package/dist/services/browser-capture.js +86 -0
- package/dist/services/fallback-training-service.js +128 -0
- package/dist/services/mcp-marketplace.js +134 -0
- package/dist/services/plugin-installer.js +396 -0
- package/dist/services/plugin-manager-types.js +15 -0
- package/dist/services/registry-client-app-meta.js +144 -0
- package/dist/services/registry-client-endpoints.js +166 -0
- package/dist/services/registry-client-local.js +271 -0
- package/dist/services/registry-client-network.js +93 -0
- package/dist/services/registry-client-queries.js +70 -0
- package/dist/services/registry-client.js +157 -0
- package/dist/services/sandbox-engine.js +511 -0
- package/dist/services/sandbox-manager.js +297 -0
- package/dist/services/self-updater.js +175 -0
- package/dist/services/skill-catalog-client.js +119 -0
- package/dist/services/skill-marketplace.js +521 -0
- package/dist/services/stream-manager.js +236 -0
- package/dist/services/update-checker.js +121 -0
- package/dist/services/update-notifier.js +29 -0
- package/dist/services/version-compat.js +78 -0
- package/dist/services/whatsapp-pairing.js +196 -0
- package/dist/shared/ui-catalog-prompt.js +728 -0
- package/dist/subscription-routes.js +172 -0
- package/dist/terminal/links.js +19 -0
- package/dist/terminal/palette.js +14 -0
- package/dist/terminal/theme.js +25 -0
- package/dist/terminal-run-limits.js +24 -0
- package/dist/training-routes.js +158 -0
- package/dist/trajectory-routes.js +300 -0
- package/dist/trigger-routes.js +246 -0
- package/dist/triggers/action.js +218 -0
- package/dist/triggers/runtime.js +281 -0
- package/dist/triggers/scheduling.js +295 -0
- package/dist/triggers/types.js +5 -0
- package/dist/tui/components/assistant-message.js +76 -0
- package/dist/tui/components/chat-editor.js +34 -0
- package/dist/tui/components/embeddings-overlay.js +46 -0
- package/dist/tui/components/footer.js +60 -0
- package/dist/tui/components/index.js +15 -0
- package/dist/tui/components/modal-frame.js +45 -0
- package/dist/tui/components/modal-style.js +15 -0
- package/dist/tui/components/model-selector.js +70 -0
- package/dist/tui/components/pinned-chat-layout.js +46 -0
- package/dist/tui/components/plugins-endpoints-tab.js +196 -0
- package/dist/tui/components/plugins-installed-tab-view.js +69 -0
- package/dist/tui/components/plugins-installed-tab.js +319 -0
- package/dist/tui/components/plugins-overlay-catalog.js +81 -0
- package/dist/tui/components/plugins-overlay-data-api.js +21 -0
- package/dist/tui/components/plugins-overlay-data-shared.js +20 -0
- package/dist/tui/components/plugins-overlay-data.js +323 -0
- package/dist/tui/components/plugins-overlay.js +117 -0
- package/dist/tui/components/plugins-store-tab.js +148 -0
- package/dist/tui/components/settings-overlay.js +61 -0
- package/dist/tui/components/status-bar.js +64 -0
- package/dist/tui/components/tool-execution.js +68 -0
- package/dist/tui/components/user-message.js +22 -0
- package/dist/tui/eliza-tui-bridge.js +606 -0
- package/dist/tui/index.js +370 -0
- package/dist/tui/modal-presets.js +33 -0
- package/dist/tui/model-spec.js +46 -0
- package/dist/tui/sse-parser.js +78 -0
- package/dist/tui/theme.js +110 -0
- package/dist/tui/titlebar-spinner.js +62 -0
- package/dist/tui/tui-app.js +311 -0
- package/dist/tui/ws-client.js +215 -0
- package/dist/twitter-verify.js +134 -0
- package/dist/tx-service.js +108 -0
- package/dist/utils/exec-safety.js +17 -0
- package/dist/utils/globals.js +20 -0
- package/dist/utils/milady-root.js +61 -0
- package/dist/utils/number-parsing.js +37 -0
- package/dist/version-resolver.js +37 -0
- package/dist/version.js +7 -0
- package/dist/wallet-routes.js +266 -0
- package/dist/wallet.js +568 -0
- package/dist/whatsapp-routes.js +182 -0
- package/dist/zip-utils.js +109 -0
- package/milady.mjs +14 -0
- 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 };
|