@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.
- package/LICENSE +21 -0
- package/package.json +270 -0
- package/src/actions/emote.ts +101 -0
- package/src/actions/restart.ts +101 -0
- package/src/actions/send-message.ts +168 -0
- package/src/actions/stream-control.ts +439 -0
- package/src/actions/switch-stream-source.ts +126 -0
- package/src/actions/terminal.ts +186 -0
- package/src/api/agent-admin-routes.ts +178 -0
- package/src/api/agent-lifecycle-routes.ts +129 -0
- package/src/api/agent-model.ts +143 -0
- package/src/api/agent-transfer-routes.ts +211 -0
- package/src/api/apps-routes.ts +210 -0
- package/src/api/auth-routes.ts +90 -0
- package/src/api/bsc-trade.ts +736 -0
- package/src/api/bug-report-routes.ts +161 -0
- package/src/api/character-routes.ts +421 -0
- package/src/api/cloud-billing-routes.ts +598 -0
- package/src/api/cloud-compat-routes.ts +192 -0
- package/src/api/cloud-routes.ts +529 -0
- package/src/api/cloud-status-routes.ts +234 -0
- package/src/api/compat-utils.ts +154 -0
- package/src/api/connector-health.ts +135 -0
- package/src/api/coordinator-wiring.ts +179 -0
- package/src/api/credit-detection.ts +47 -0
- package/src/api/database.ts +1357 -0
- package/src/api/diagnostics-routes.ts +389 -0
- package/src/api/drop-service.ts +205 -0
- package/src/api/early-logs.ts +111 -0
- package/src/api/http-helpers.ts +252 -0
- package/src/api/index.ts +85 -0
- package/src/api/knowledge-routes.ts +1189 -0
- package/src/api/knowledge-service-loader.ts +92 -0
- package/src/api/memory-bounds.ts +121 -0
- package/src/api/memory-routes.ts +349 -0
- package/src/api/merkle-tree.ts +239 -0
- package/src/api/models-routes.ts +72 -0
- package/src/api/nfa-routes.ts +169 -0
- package/src/api/nft-verify.ts +188 -0
- package/src/api/og-tracker.ts +72 -0
- package/src/api/parse-action-block.ts +145 -0
- package/src/api/permissions-routes.ts +222 -0
- package/src/api/plugin-validation.ts +355 -0
- package/src/api/provider-switch-config.ts +455 -0
- package/src/api/registry-routes.ts +165 -0
- package/src/api/registry-service.ts +292 -0
- package/src/api/route-helpers.ts +21 -0
- package/src/api/sandbox-routes.ts +1480 -0
- package/src/api/server.ts +17674 -0
- package/src/api/signal-routes.ts +265 -0
- package/src/api/stream-persistence.ts +297 -0
- package/src/api/stream-route-state.ts +48 -0
- package/src/api/stream-routes.ts +1046 -0
- package/src/api/stream-voice-routes.ts +208 -0
- package/src/api/streaming-text.ts +129 -0
- package/src/api/streaming-types.ts +23 -0
- package/src/api/subscription-routes.ts +283 -0
- package/src/api/terminal-run-limits.ts +31 -0
- package/src/api/training-backend-check.ts +40 -0
- package/src/api/training-routes.ts +314 -0
- package/src/api/training-service-like.ts +46 -0
- package/src/api/trajectory-routes.ts +714 -0
- package/src/api/trigger-routes.ts +438 -0
- package/src/api/twitter-verify.ts +226 -0
- package/src/api/tx-service.ts +193 -0
- package/src/api/wallet-dex-prices.ts +206 -0
- package/src/api/wallet-evm-balance.ts +989 -0
- package/src/api/wallet-routes.ts +505 -0
- package/src/api/wallet-rpc.ts +523 -0
- package/src/api/wallet-trading-profile.ts +694 -0
- package/src/api/wallet.ts +745 -0
- package/src/api/whatsapp-routes.ts +282 -0
- package/src/api/zip-utils.ts +130 -0
- package/src/auth/anthropic.ts +63 -0
- package/src/auth/apply-stealth.ts +38 -0
- package/src/auth/claude-code-stealth.ts +141 -0
- package/src/auth/credentials.ts +226 -0
- package/src/auth/index.ts +18 -0
- package/src/auth/openai-codex.ts +94 -0
- package/src/auth/types.ts +24 -0
- package/src/awareness/registry.ts +220 -0
- package/src/bin.ts +10 -0
- package/src/cli/index.ts +36 -0
- package/src/cli/parse-duration.ts +43 -0
- package/src/cloud/auth.test.ts +370 -0
- package/src/cloud/auth.ts +176 -0
- package/src/cloud/backup.test.ts +150 -0
- package/src/cloud/backup.ts +50 -0
- package/src/cloud/base-url.ts +45 -0
- package/src/cloud/bridge-client.test.ts +481 -0
- package/src/cloud/bridge-client.ts +307 -0
- package/src/cloud/cloud-manager.test.ts +223 -0
- package/src/cloud/cloud-manager.ts +151 -0
- package/src/cloud/cloud-proxy.test.ts +122 -0
- package/src/cloud/cloud-proxy.ts +52 -0
- package/src/cloud/index.ts +23 -0
- package/src/cloud/reconnect.test.ts +178 -0
- package/src/cloud/reconnect.ts +108 -0
- package/src/cloud/validate-url.test.ts +147 -0
- package/src/cloud/validate-url.ts +176 -0
- package/src/config/character-schema.ts +44 -0
- package/src/config/config.ts +149 -0
- package/src/config/env-vars.ts +86 -0
- package/src/config/includes.ts +196 -0
- package/src/config/index.ts +15 -0
- package/src/config/object-utils.ts +10 -0
- package/src/config/paths.ts +92 -0
- package/src/config/plugin-auto-enable.ts +520 -0
- package/src/config/schema.ts +1342 -0
- package/src/config/telegram-custom-commands.ts +99 -0
- package/src/config/types.agent-defaults.ts +342 -0
- package/src/config/types.agents.ts +112 -0
- package/src/config/types.gateway.ts +243 -0
- package/src/config/types.hooks.ts +124 -0
- package/src/config/types.messages.ts +201 -0
- package/src/config/types.milady.ts +791 -0
- package/src/config/types.tools.ts +416 -0
- package/src/config/types.ts +7 -0
- package/src/config/zod-schema.agent-runtime.ts +777 -0
- package/src/config/zod-schema.core.ts +778 -0
- package/src/config/zod-schema.hooks.ts +139 -0
- package/src/config/zod-schema.providers-core.ts +1126 -0
- package/src/config/zod-schema.session.ts +98 -0
- package/src/config/zod-schema.ts +865 -0
- package/src/contracts/apps.ts +46 -0
- package/src/contracts/awareness.ts +56 -0
- package/src/contracts/config.ts +172 -0
- package/src/contracts/drop.ts +21 -0
- package/src/contracts/index.ts +8 -0
- package/src/contracts/onboarding.ts +592 -0
- package/src/contracts/permissions.ts +52 -0
- package/src/contracts/verification.ts +9 -0
- package/src/contracts/wallet.ts +503 -0
- package/src/diagnostics/integration-observability.ts +132 -0
- package/src/emotes/catalog.ts +655 -0
- package/src/external-modules.d.ts +7 -0
- package/src/hooks/discovery.test.ts +357 -0
- package/src/hooks/discovery.ts +231 -0
- package/src/hooks/eligibility.ts +146 -0
- package/src/hooks/hooks.test.ts +320 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/loader.test.ts +418 -0
- package/src/hooks/loader.ts +256 -0
- package/src/hooks/registry.test.ts +168 -0
- package/src/hooks/registry.ts +74 -0
- package/src/hooks/types.ts +121 -0
- package/src/index.ts +19 -0
- package/src/onboarding-presets.ts +828 -0
- package/src/plugins/custom-rtmp/index.ts +40 -0
- package/src/providers/admin-trust.ts +76 -0
- package/src/providers/session-bridge.ts +143 -0
- package/src/providers/session-utils.ts +42 -0
- package/src/providers/simple-mode.ts +113 -0
- package/src/providers/ui-catalog.ts +135 -0
- package/src/providers/workspace-provider.ts +213 -0
- package/src/providers/workspace.ts +497 -0
- package/src/runtime/agent-event-service.ts +57 -0
- package/src/runtime/cloud-onboarding.test.ts +489 -0
- package/src/runtime/cloud-onboarding.ts +408 -0
- package/src/runtime/core-plugins.ts +53 -0
- package/src/runtime/custom-actions.ts +605 -0
- package/src/runtime/eliza.ts +4941 -0
- package/src/runtime/embedding-presets.ts +73 -0
- package/src/runtime/index.ts +8 -0
- package/src/runtime/milady-plugin.ts +180 -0
- package/src/runtime/onboarding-names.ts +76 -0
- package/src/runtime/release-plugin-policy.ts +119 -0
- package/src/runtime/restart.ts +59 -0
- package/src/runtime/trajectory-persistence.ts +2584 -0
- package/src/runtime/version.ts +6 -0
- package/src/security/audit-log.ts +222 -0
- package/src/security/network-policy.ts +91 -0
- package/src/server/index.ts +6 -0
- package/src/services/agent-export.ts +976 -0
- package/src/services/app-manager.ts +755 -0
- package/src/services/browser-capture.ts +215 -0
- package/src/services/coding-agent-context.ts +355 -0
- package/src/services/fallback-training-service.ts +196 -0
- package/src/services/index.ts +17 -0
- package/src/services/mcp-marketplace.ts +327 -0
- package/src/services/plugin-manager-types.ts +185 -0
- package/src/services/privy-wallets.ts +352 -0
- package/src/services/registry-client-app-meta.ts +201 -0
- package/src/services/registry-client-endpoints.ts +253 -0
- package/src/services/registry-client-local.ts +485 -0
- package/src/services/registry-client-network.ts +173 -0
- package/src/services/registry-client-queries.ts +176 -0
- package/src/services/registry-client-types.ts +104 -0
- package/src/services/registry-client.ts +366 -0
- package/src/services/remote-signing-service.ts +261 -0
- package/src/services/sandbox-engine.ts +753 -0
- package/src/services/sandbox-manager.ts +503 -0
- package/src/services/self-updater.ts +213 -0
- package/src/services/signal-pairing.ts +189 -0
- package/src/services/signing-policy.ts +230 -0
- package/src/services/skill-catalog-client.ts +195 -0
- package/src/services/skill-marketplace.ts +909 -0
- package/src/services/stream-manager.ts +707 -0
- package/src/services/tts-stream-bridge.ts +465 -0
- package/src/services/update-checker.ts +163 -0
- package/src/services/version-compat.ts +367 -0
- package/src/services/whatsapp-pairing.ts +279 -0
- package/src/shared/ui-catalog-prompt.ts +1158 -0
- package/src/test-support/process-helpers.ts +35 -0
- package/src/test-support/route-test-helpers.ts +113 -0
- package/src/test-support/test-helpers.ts +304 -0
- package/src/testing/index.ts +3 -0
- package/src/triggers/action.ts +342 -0
- package/src/triggers/runtime.ts +432 -0
- package/src/triggers/scheduling.ts +472 -0
- package/src/triggers/types.ts +133 -0
- package/src/types/app-hyperscape-routes-shim.d.ts +29 -0
- package/src/types/external-modules.d.ts +7 -0
- package/src/utils/exec-safety.ts +23 -0
- package/src/utils/number-parsing.ts +112 -0
- package/src/utils/spoken-text.ts +65 -0
- package/src/version-resolver.ts +60 -0
- package/test/api/agent-admin-routes.test.ts +160 -0
- package/test/api/agent-lifecycle-routes.test.ts +164 -0
- package/test/api/agent-transfer-routes.test.ts +136 -0
- package/test/api/apps-routes.test.ts +140 -0
- package/test/api/auth-routes.test.ts +160 -0
- package/test/api/bug-report-routes.test.ts +88 -0
- package/test/api/knowledge-routes.test.ts +73 -0
- package/test/api/lifecycle.test.ts +342 -0
- package/test/api/memory-routes.test.ts +74 -0
- package/test/api/models-routes.test.ts +112 -0
- package/test/api/nfa-routes.test.ts +78 -0
- package/test/api/permissions-routes.test.ts +185 -0
- package/test/api/registry-routes.test.ts +157 -0
- package/test/api/signal-routes.test.ts +113 -0
- package/test/api/subscription-routes.test.ts +90 -0
- package/test/api/trigger-routes.test.ts +87 -0
- package/test/api/wallet-routes.observability.test.ts +191 -0
- package/test/api/wallet-routes.test.ts +502 -0
- package/test/diagnostics/integration-observability.test.ts +135 -0
- package/test/security/audit-log.test.ts +229 -0
- package/test/security/network-policy.test.ts +143 -0
- package/test/services/version-compat.test.ts +127 -0
- package/tsconfig.build.json +21 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,714 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trajectory API routes for the Milady Control UI.
|
|
3
|
+
*
|
|
4
|
+
* Provides endpoints for:
|
|
5
|
+
* - Listing and searching trajectories
|
|
6
|
+
* - Viewing trajectory details with LLM calls and provider accesses
|
|
7
|
+
* - Exporting trajectories to JSON, CSV, or ZIP
|
|
8
|
+
* - Deleting trajectories
|
|
9
|
+
* - Getting trajectory statistics
|
|
10
|
+
* - Enabling/disabling trajectory logging
|
|
11
|
+
*
|
|
12
|
+
* Uses the @elizaos/plugin-trajectory-logger service for data access.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type http from "node:http";
|
|
16
|
+
import type { AgentRuntime } from "@elizaos/core";
|
|
17
|
+
import {
|
|
18
|
+
readJsonBody as parseJsonBody,
|
|
19
|
+
sendJson,
|
|
20
|
+
sendJsonError,
|
|
21
|
+
} from "./http-helpers";
|
|
22
|
+
import { createZipArchive } from "./zip-utils";
|
|
23
|
+
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// Types
|
|
26
|
+
// ============================================================================
|
|
27
|
+
|
|
28
|
+
type TrajectoryStatus = "active" | "completed" | "error" | "timeout";
|
|
29
|
+
|
|
30
|
+
interface TrajectoryListOptions {
|
|
31
|
+
limit?: number;
|
|
32
|
+
offset?: number;
|
|
33
|
+
source?: string;
|
|
34
|
+
status?: TrajectoryStatus;
|
|
35
|
+
startDate?: string;
|
|
36
|
+
endDate?: string;
|
|
37
|
+
search?: string;
|
|
38
|
+
scenarioId?: string;
|
|
39
|
+
batchId?: string;
|
|
40
|
+
isTrainingData?: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface TrajectoryListItem {
|
|
44
|
+
id: string;
|
|
45
|
+
agentId: string;
|
|
46
|
+
source: string;
|
|
47
|
+
status: TrajectoryStatus;
|
|
48
|
+
startTime: number;
|
|
49
|
+
endTime: number | null;
|
|
50
|
+
durationMs: number | null;
|
|
51
|
+
llmCallCount: number;
|
|
52
|
+
totalPromptTokens: number;
|
|
53
|
+
totalCompletionTokens: number;
|
|
54
|
+
createdAt: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface TrajectoryLlmCall {
|
|
58
|
+
callId?: string;
|
|
59
|
+
timestamp?: number;
|
|
60
|
+
model?: string;
|
|
61
|
+
systemPrompt?: string;
|
|
62
|
+
userPrompt?: string;
|
|
63
|
+
response?: string;
|
|
64
|
+
temperature?: number;
|
|
65
|
+
maxTokens?: number;
|
|
66
|
+
purpose?: string;
|
|
67
|
+
actionType?: string;
|
|
68
|
+
latencyMs?: number;
|
|
69
|
+
promptTokens?: number;
|
|
70
|
+
completionTokens?: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface TrajectoryProviderAccess {
|
|
74
|
+
providerId?: string;
|
|
75
|
+
providerName?: string;
|
|
76
|
+
purpose?: string;
|
|
77
|
+
data?: Record<string, unknown>;
|
|
78
|
+
query?: Record<string, unknown>;
|
|
79
|
+
timestamp?: number;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
interface TrajectoryStep {
|
|
83
|
+
stepId?: string;
|
|
84
|
+
timestamp: number;
|
|
85
|
+
llmCalls?: TrajectoryLlmCall[];
|
|
86
|
+
providerAccesses?: TrajectoryProviderAccess[];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface Trajectory {
|
|
90
|
+
trajectoryId: string;
|
|
91
|
+
agentId: string;
|
|
92
|
+
startTime: number;
|
|
93
|
+
endTime?: number;
|
|
94
|
+
durationMs?: number;
|
|
95
|
+
steps?: TrajectoryStep[];
|
|
96
|
+
metrics?: { finalStatus?: string };
|
|
97
|
+
metadata?: Record<string, unknown>;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface TrajectoryListResult {
|
|
101
|
+
trajectories: TrajectoryListItem[];
|
|
102
|
+
total: number;
|
|
103
|
+
offset: number;
|
|
104
|
+
limit: number;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
type TrajectoryExportFormat = "json" | "csv" | "art";
|
|
108
|
+
|
|
109
|
+
interface TrajectoryExportOptions {
|
|
110
|
+
format: TrajectoryExportFormat;
|
|
111
|
+
includePrompts?: boolean;
|
|
112
|
+
trajectoryIds?: string[];
|
|
113
|
+
startDate?: string;
|
|
114
|
+
endDate?: string;
|
|
115
|
+
scenarioId?: string;
|
|
116
|
+
batchId?: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
interface TrajectoryExportResult {
|
|
120
|
+
filename: string;
|
|
121
|
+
data: string | Uint8Array;
|
|
122
|
+
mimeType: string;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
interface TrajectoryLoggerApi {
|
|
126
|
+
isEnabled(): boolean;
|
|
127
|
+
setEnabled(enabled: boolean): void;
|
|
128
|
+
listTrajectories(
|
|
129
|
+
options: TrajectoryListOptions,
|
|
130
|
+
): Promise<TrajectoryListResult>;
|
|
131
|
+
getTrajectoryDetail(trajectoryId: string): Promise<Trajectory | null>;
|
|
132
|
+
getStats(): Promise<unknown>;
|
|
133
|
+
deleteTrajectories(trajectoryIds: string[]): Promise<number>;
|
|
134
|
+
clearAllTrajectories(): Promise<number>;
|
|
135
|
+
exportTrajectories(
|
|
136
|
+
options: TrajectoryExportOptions,
|
|
137
|
+
): Promise<TrajectoryExportResult>;
|
|
138
|
+
exportTrajectoriesZip?: (
|
|
139
|
+
options: TrajectoryZipExportOptions,
|
|
140
|
+
) => Promise<TrajectoryZipExportResult>;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
type TrajectoryZipExportOptions = {
|
|
144
|
+
includePrompts?: boolean;
|
|
145
|
+
trajectoryIds?: string[];
|
|
146
|
+
startDate?: string;
|
|
147
|
+
endDate?: string;
|
|
148
|
+
scenarioId?: string;
|
|
149
|
+
batchId?: string;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
type TrajectoryZipExportResult = {
|
|
153
|
+
filename: string;
|
|
154
|
+
entries: Array<{ name: string; data: string }>;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// UI Compatible Types
|
|
158
|
+
|
|
159
|
+
interface UITrajectoryRecord {
|
|
160
|
+
id: string;
|
|
161
|
+
agentId: string;
|
|
162
|
+
roomId: string | null;
|
|
163
|
+
entityId: string | null;
|
|
164
|
+
conversationId: string | null;
|
|
165
|
+
source: string;
|
|
166
|
+
status: "active" | "completed" | "error";
|
|
167
|
+
startTime: number;
|
|
168
|
+
endTime: number | null;
|
|
169
|
+
durationMs: number | null;
|
|
170
|
+
llmCallCount: number;
|
|
171
|
+
providerAccessCount: number;
|
|
172
|
+
totalPromptTokens: number;
|
|
173
|
+
totalCompletionTokens: number;
|
|
174
|
+
metadata: Record<string, unknown>;
|
|
175
|
+
createdAt: string;
|
|
176
|
+
updatedAt: string;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
interface UILlmCall {
|
|
180
|
+
id: string;
|
|
181
|
+
trajectoryId: string;
|
|
182
|
+
stepId: string;
|
|
183
|
+
model: string;
|
|
184
|
+
systemPrompt: string;
|
|
185
|
+
userPrompt: string;
|
|
186
|
+
response: string;
|
|
187
|
+
temperature: number;
|
|
188
|
+
maxTokens: number;
|
|
189
|
+
purpose: string;
|
|
190
|
+
actionType: string;
|
|
191
|
+
latencyMs: number;
|
|
192
|
+
promptTokens?: number;
|
|
193
|
+
completionTokens?: number;
|
|
194
|
+
timestamp: number;
|
|
195
|
+
createdAt: string;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
interface UIProviderAccess {
|
|
199
|
+
id: string;
|
|
200
|
+
trajectoryId: string;
|
|
201
|
+
stepId: string;
|
|
202
|
+
providerName: string;
|
|
203
|
+
purpose: string;
|
|
204
|
+
data: Record<string, unknown>;
|
|
205
|
+
query?: Record<string, unknown>;
|
|
206
|
+
timestamp: number;
|
|
207
|
+
createdAt: string;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
interface UITrajectoryDetailResult {
|
|
211
|
+
trajectory: UITrajectoryRecord;
|
|
212
|
+
llmCalls: UILlmCall[];
|
|
213
|
+
providerAccesses: UIProviderAccess[];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ============================================================================
|
|
217
|
+
// Helpers
|
|
218
|
+
// ============================================================================
|
|
219
|
+
|
|
220
|
+
function isRouteCompatibleTrajectoryLogger(
|
|
221
|
+
candidate: unknown,
|
|
222
|
+
): candidate is TrajectoryLoggerApi {
|
|
223
|
+
if (!candidate || typeof candidate !== "object") return false;
|
|
224
|
+
const logger = candidate as Partial<TrajectoryLoggerApi>;
|
|
225
|
+
|
|
226
|
+
return (
|
|
227
|
+
typeof logger.isEnabled === "function" &&
|
|
228
|
+
typeof logger.setEnabled === "function" &&
|
|
229
|
+
typeof logger.listTrajectories === "function" &&
|
|
230
|
+
typeof logger.getTrajectoryDetail === "function" &&
|
|
231
|
+
typeof logger.getStats === "function" &&
|
|
232
|
+
typeof logger.deleteTrajectories === "function" &&
|
|
233
|
+
typeof logger.clearAllTrajectories === "function" &&
|
|
234
|
+
typeof logger.exportTrajectories === "function"
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function getTrajectoryLogger(
|
|
239
|
+
runtime: AgentRuntime,
|
|
240
|
+
): TrajectoryLoggerApi | null {
|
|
241
|
+
const runtimeLike = runtime as AgentRuntime & {
|
|
242
|
+
getServicesByType?: (serviceType: string) => unknown;
|
|
243
|
+
getService?: (serviceType: string) => unknown;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const seen = new Set<unknown>();
|
|
247
|
+
const candidates: unknown[] = [];
|
|
248
|
+
const addCandidate = (candidate: unknown): void => {
|
|
249
|
+
if (!candidate || seen.has(candidate)) return;
|
|
250
|
+
seen.add(candidate);
|
|
251
|
+
candidates.push(candidate);
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
if (typeof runtimeLike.getServicesByType === "function") {
|
|
255
|
+
const byType = runtimeLike.getServicesByType("trajectory_logger");
|
|
256
|
+
if (Array.isArray(byType)) {
|
|
257
|
+
for (const candidate of byType) {
|
|
258
|
+
addCandidate(candidate);
|
|
259
|
+
}
|
|
260
|
+
} else {
|
|
261
|
+
addCandidate(byType);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (typeof runtimeLike.getService === "function") {
|
|
266
|
+
addCandidate(runtimeLike.getService("trajectory_logger"));
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
for (const candidate of candidates) {
|
|
270
|
+
if (isRouteCompatibleTrajectoryLogger(candidate)) {
|
|
271
|
+
return candidate;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function toNullableString(value: unknown): string | null {
|
|
279
|
+
return typeof value === "string" ? value : null;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function listItemToUIRecord(item: TrajectoryListItem): UITrajectoryRecord {
|
|
283
|
+
const status =
|
|
284
|
+
item.status === "timeout" || item.status === "error"
|
|
285
|
+
? "error"
|
|
286
|
+
: item.status;
|
|
287
|
+
return {
|
|
288
|
+
id: item.id,
|
|
289
|
+
agentId: item.agentId,
|
|
290
|
+
roomId: null,
|
|
291
|
+
entityId: null,
|
|
292
|
+
conversationId: null,
|
|
293
|
+
source: item.source,
|
|
294
|
+
status: status as "active" | "completed" | "error",
|
|
295
|
+
startTime: item.startTime,
|
|
296
|
+
endTime: item.endTime,
|
|
297
|
+
durationMs: item.durationMs,
|
|
298
|
+
llmCallCount: item.llmCallCount,
|
|
299
|
+
providerAccessCount: 0,
|
|
300
|
+
totalPromptTokens: item.totalPromptTokens,
|
|
301
|
+
totalCompletionTokens: item.totalCompletionTokens,
|
|
302
|
+
metadata: {},
|
|
303
|
+
createdAt: item.createdAt,
|
|
304
|
+
updatedAt: item.createdAt,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function trajectoryToUIDetail(traj: Trajectory): UITrajectoryDetailResult {
|
|
309
|
+
const finalStatus = (traj.metrics?.finalStatus as string) ?? "completed";
|
|
310
|
+
const normalizedEndTime =
|
|
311
|
+
typeof traj.endTime === "number" && traj.endTime > 0 ? traj.endTime : null;
|
|
312
|
+
const status: "active" | "completed" | "error" =
|
|
313
|
+
finalStatus === "timeout" ||
|
|
314
|
+
finalStatus === "terminated" ||
|
|
315
|
+
finalStatus === "error"
|
|
316
|
+
? "error"
|
|
317
|
+
: finalStatus === "completed"
|
|
318
|
+
? "completed"
|
|
319
|
+
: normalizedEndTime
|
|
320
|
+
? "completed"
|
|
321
|
+
: "active";
|
|
322
|
+
|
|
323
|
+
const llmCalls: UILlmCall[] = [];
|
|
324
|
+
const providerAccesses: UIProviderAccess[] = [];
|
|
325
|
+
|
|
326
|
+
let totalPromptTokens = 0;
|
|
327
|
+
let totalCompletionTokens = 0;
|
|
328
|
+
|
|
329
|
+
const steps = traj.steps || [];
|
|
330
|
+
const trajectoryId = String(traj.trajectoryId);
|
|
331
|
+
|
|
332
|
+
for (let i = 0; i < steps.length; i++) {
|
|
333
|
+
const step = steps[i];
|
|
334
|
+
const stepId = typeof step.stepId === "string" ? step.stepId : `step-${i}`;
|
|
335
|
+
|
|
336
|
+
// Process LLM Calls
|
|
337
|
+
const calls = step.llmCalls || [];
|
|
338
|
+
for (let j = 0; j < calls.length; j++) {
|
|
339
|
+
const call = calls[j];
|
|
340
|
+
llmCalls.push({
|
|
341
|
+
id: call.callId || `${stepId}-call-${j}`,
|
|
342
|
+
trajectoryId,
|
|
343
|
+
stepId,
|
|
344
|
+
model: call.model || "unknown",
|
|
345
|
+
systemPrompt: call.systemPrompt || "",
|
|
346
|
+
userPrompt: call.userPrompt || "",
|
|
347
|
+
response: call.response || "",
|
|
348
|
+
temperature:
|
|
349
|
+
typeof call.temperature === "number" ? call.temperature : 0,
|
|
350
|
+
maxTokens: typeof call.maxTokens === "number" ? call.maxTokens : 0,
|
|
351
|
+
purpose: call.purpose || "",
|
|
352
|
+
actionType: call.actionType || "",
|
|
353
|
+
latencyMs: call.latencyMs || 0,
|
|
354
|
+
promptTokens: call.promptTokens,
|
|
355
|
+
completionTokens: call.completionTokens,
|
|
356
|
+
timestamp: call.timestamp || step.timestamp,
|
|
357
|
+
createdAt: new Date(call.timestamp || step.timestamp).toISOString(),
|
|
358
|
+
});
|
|
359
|
+
totalPromptTokens += call.promptTokens || 0;
|
|
360
|
+
totalCompletionTokens += call.completionTokens || 0;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Process Provider Accesses
|
|
364
|
+
const accesses = step.providerAccesses || [];
|
|
365
|
+
for (let k = 0; k < accesses.length; k++) {
|
|
366
|
+
const access = accesses[k];
|
|
367
|
+
providerAccesses.push({
|
|
368
|
+
id: access.providerId || `${stepId}-provider-${k}`,
|
|
369
|
+
trajectoryId,
|
|
370
|
+
stepId,
|
|
371
|
+
providerName: access.providerName || "unknown",
|
|
372
|
+
purpose: access.purpose || "",
|
|
373
|
+
data: access.data || {},
|
|
374
|
+
query: access.query,
|
|
375
|
+
timestamp: access.timestamp || step.timestamp,
|
|
376
|
+
createdAt: new Date(access.timestamp || step.timestamp).toISOString(),
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const metadata = (traj.metadata ?? {}) as Record<string, unknown>;
|
|
382
|
+
const normalizedDurationMs =
|
|
383
|
+
status === "active"
|
|
384
|
+
? null
|
|
385
|
+
: typeof traj.durationMs === "number"
|
|
386
|
+
? traj.durationMs
|
|
387
|
+
: null;
|
|
388
|
+
const updatedAtMs = normalizedEndTime ?? (traj.startTime || Date.now());
|
|
389
|
+
|
|
390
|
+
const trajectory: UITrajectoryRecord = {
|
|
391
|
+
id: trajectoryId,
|
|
392
|
+
agentId: String(traj.agentId),
|
|
393
|
+
roomId: toNullableString(metadata.roomId),
|
|
394
|
+
entityId: toNullableString(metadata.entityId),
|
|
395
|
+
conversationId: toNullableString(metadata.conversationId),
|
|
396
|
+
source: toNullableString(metadata.source) ?? "chat",
|
|
397
|
+
status,
|
|
398
|
+
startTime: traj.startTime,
|
|
399
|
+
endTime: normalizedEndTime,
|
|
400
|
+
durationMs: normalizedDurationMs,
|
|
401
|
+
llmCallCount: llmCalls.length,
|
|
402
|
+
providerAccessCount: providerAccesses.length,
|
|
403
|
+
totalPromptTokens,
|
|
404
|
+
totalCompletionTokens,
|
|
405
|
+
metadata,
|
|
406
|
+
createdAt: new Date(traj.startTime).toISOString(),
|
|
407
|
+
updatedAt: new Date(updatedAtMs).toISOString(),
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
return { trajectory, llmCalls, providerAccesses };
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// ============================================================================
|
|
414
|
+
// Handlers
|
|
415
|
+
// ============================================================================
|
|
416
|
+
|
|
417
|
+
async function handleGetTrajectories(
|
|
418
|
+
req: http.IncomingMessage,
|
|
419
|
+
res: http.ServerResponse,
|
|
420
|
+
runtime: AgentRuntime,
|
|
421
|
+
): Promise<void> {
|
|
422
|
+
const logger = getTrajectoryLogger(runtime);
|
|
423
|
+
if (!logger) {
|
|
424
|
+
sendJsonError(res, "Trajectory logger service not available", 503);
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const url = new URL(
|
|
429
|
+
req.url ?? "/",
|
|
430
|
+
`http://${req.headers.host ?? "localhost"}`,
|
|
431
|
+
);
|
|
432
|
+
|
|
433
|
+
const options: TrajectoryListOptions = {
|
|
434
|
+
limit: Math.min(
|
|
435
|
+
500,
|
|
436
|
+
Math.max(1, Number(url.searchParams.get("limit")) || 50),
|
|
437
|
+
),
|
|
438
|
+
offset: Math.max(0, Number(url.searchParams.get("offset")) || 0),
|
|
439
|
+
source: url.searchParams.get("source") || undefined,
|
|
440
|
+
status:
|
|
441
|
+
(url.searchParams.get("status") as
|
|
442
|
+
| "active"
|
|
443
|
+
| "completed"
|
|
444
|
+
| "error"
|
|
445
|
+
| "timeout") || undefined,
|
|
446
|
+
startDate: url.searchParams.get("startDate") || undefined,
|
|
447
|
+
endDate: url.searchParams.get("endDate") || undefined,
|
|
448
|
+
search: url.searchParams.get("search") || undefined,
|
|
449
|
+
scenarioId: url.searchParams.get("scenarioId") || undefined,
|
|
450
|
+
batchId: url.searchParams.get("batchId") || undefined,
|
|
451
|
+
isTrainingData: url.searchParams.has("isTrainingData")
|
|
452
|
+
? url.searchParams.get("isTrainingData") === "true"
|
|
453
|
+
: undefined,
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
const result = await logger.listTrajectories(options);
|
|
457
|
+
|
|
458
|
+
const uiResult = {
|
|
459
|
+
trajectories: result.trajectories.map(listItemToUIRecord),
|
|
460
|
+
total: result.total,
|
|
461
|
+
offset: result.offset,
|
|
462
|
+
limit: result.limit,
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
sendJson(res, uiResult);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
async function handleGetTrajectoryDetail(
|
|
469
|
+
_req: http.IncomingMessage,
|
|
470
|
+
res: http.ServerResponse,
|
|
471
|
+
runtime: AgentRuntime,
|
|
472
|
+
trajectoryId: string,
|
|
473
|
+
): Promise<void> {
|
|
474
|
+
const logger = getTrajectoryLogger(runtime);
|
|
475
|
+
if (!logger) {
|
|
476
|
+
sendJsonError(res, "Trajectory logger service not available", 503);
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
const trajectory = await logger.getTrajectoryDetail(trajectoryId);
|
|
481
|
+
if (!trajectory) {
|
|
482
|
+
sendJsonError(res, `Trajectory "${trajectoryId}" not found`, 404);
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const uiDetail = trajectoryToUIDetail(trajectory);
|
|
487
|
+
sendJson(res, uiDetail);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
async function handleGetStats(
|
|
491
|
+
_req: http.IncomingMessage,
|
|
492
|
+
res: http.ServerResponse,
|
|
493
|
+
runtime: AgentRuntime,
|
|
494
|
+
): Promise<void> {
|
|
495
|
+
const logger = getTrajectoryLogger(runtime);
|
|
496
|
+
if (!logger) {
|
|
497
|
+
sendJsonError(res, "Trajectory logger service not available", 503);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const stats = await logger.getStats();
|
|
502
|
+
sendJson(res, stats);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
async function handleGetConfig(
|
|
506
|
+
_req: http.IncomingMessage,
|
|
507
|
+
res: http.ServerResponse,
|
|
508
|
+
runtime: AgentRuntime,
|
|
509
|
+
): Promise<void> {
|
|
510
|
+
const logger = getTrajectoryLogger(runtime);
|
|
511
|
+
if (!logger) {
|
|
512
|
+
sendJsonError(res, "Trajectory logger service not available", 503);
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
sendJson(res, {
|
|
517
|
+
enabled: logger.isEnabled(),
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
async function handlePutConfig(
|
|
522
|
+
req: http.IncomingMessage,
|
|
523
|
+
res: http.ServerResponse,
|
|
524
|
+
runtime: AgentRuntime,
|
|
525
|
+
): Promise<void> {
|
|
526
|
+
const logger = getTrajectoryLogger(runtime);
|
|
527
|
+
if (!logger) {
|
|
528
|
+
sendJsonError(res, "Trajectory logger service not available", 503);
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
const body = await parseJsonBody<{ enabled?: boolean }>(req, res);
|
|
533
|
+
if (!body) return;
|
|
534
|
+
|
|
535
|
+
if (typeof body.enabled === "boolean") {
|
|
536
|
+
logger.setEnabled(body.enabled);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
sendJson(res, {
|
|
540
|
+
enabled: logger.isEnabled(),
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
async function handleExportTrajectories(
|
|
545
|
+
req: http.IncomingMessage,
|
|
546
|
+
res: http.ServerResponse,
|
|
547
|
+
runtime: AgentRuntime,
|
|
548
|
+
): Promise<void> {
|
|
549
|
+
const logger = getTrajectoryLogger(runtime);
|
|
550
|
+
if (!logger) {
|
|
551
|
+
sendJsonError(res, "Trajectory logger service not available", 503);
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
const body = await parseJsonBody<{
|
|
556
|
+
format?: string;
|
|
557
|
+
includePrompts?: boolean;
|
|
558
|
+
trajectoryIds?: string[];
|
|
559
|
+
startDate?: string;
|
|
560
|
+
endDate?: string;
|
|
561
|
+
scenarioId?: string;
|
|
562
|
+
batchId?: string;
|
|
563
|
+
}>(req, res);
|
|
564
|
+
if (!body) return;
|
|
565
|
+
|
|
566
|
+
if (body.format === "zip") {
|
|
567
|
+
if (typeof logger.exportTrajectoriesZip !== "function") {
|
|
568
|
+
sendJsonError(
|
|
569
|
+
res,
|
|
570
|
+
"Trajectory ZIP export is unavailable in the active logger",
|
|
571
|
+
503,
|
|
572
|
+
);
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
const zipOptions: TrajectoryZipExportOptions = {
|
|
577
|
+
includePrompts: body.includePrompts,
|
|
578
|
+
trajectoryIds: body.trajectoryIds,
|
|
579
|
+
startDate: body.startDate,
|
|
580
|
+
endDate: body.endDate,
|
|
581
|
+
scenarioId: body.scenarioId,
|
|
582
|
+
batchId: body.batchId,
|
|
583
|
+
};
|
|
584
|
+
const zipResult = await logger.exportTrajectoriesZip(zipOptions);
|
|
585
|
+
const archive = createZipArchive(zipResult.entries);
|
|
586
|
+
|
|
587
|
+
res.statusCode = 200;
|
|
588
|
+
res.setHeader("Content-Type", "application/zip");
|
|
589
|
+
res.setHeader(
|
|
590
|
+
"Content-Disposition",
|
|
591
|
+
`attachment; filename="${zipResult.filename}"`,
|
|
592
|
+
);
|
|
593
|
+
res.end(archive);
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if (
|
|
598
|
+
body.format !== "json" &&
|
|
599
|
+
body.format !== "csv" &&
|
|
600
|
+
body.format !== "art"
|
|
601
|
+
) {
|
|
602
|
+
sendJsonError(res, "Format must be 'json', 'csv', 'art', or 'zip'", 400);
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
const result = await logger.exportTrajectories({
|
|
607
|
+
format: body.format,
|
|
608
|
+
includePrompts: body.includePrompts,
|
|
609
|
+
trajectoryIds: body.trajectoryIds,
|
|
610
|
+
startDate: body.startDate,
|
|
611
|
+
endDate: body.endDate,
|
|
612
|
+
scenarioId: body.scenarioId,
|
|
613
|
+
batchId: body.batchId,
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
res.statusCode = 200;
|
|
617
|
+
res.setHeader("Content-Type", result.mimeType);
|
|
618
|
+
res.setHeader(
|
|
619
|
+
"Content-Disposition",
|
|
620
|
+
`attachment; filename="${result.filename}"`,
|
|
621
|
+
);
|
|
622
|
+
res.end(result.data);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
async function handleDeleteTrajectories(
|
|
626
|
+
req: http.IncomingMessage,
|
|
627
|
+
res: http.ServerResponse,
|
|
628
|
+
runtime: AgentRuntime,
|
|
629
|
+
): Promise<void> {
|
|
630
|
+
const logger = getTrajectoryLogger(runtime);
|
|
631
|
+
if (!logger) {
|
|
632
|
+
sendJsonError(res, "Trajectory logger service not available", 503);
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const body = await parseJsonBody<{
|
|
637
|
+
trajectoryIds?: string[];
|
|
638
|
+
all?: boolean;
|
|
639
|
+
}>(req, res);
|
|
640
|
+
if (!body) return;
|
|
641
|
+
|
|
642
|
+
if (body.all) {
|
|
643
|
+
const deletedCount = await logger.clearAllTrajectories();
|
|
644
|
+
sendJson(res, { deleted: deletedCount });
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
if (Array.isArray(body.trajectoryIds) && body.trajectoryIds.length > 0) {
|
|
649
|
+
const deletedCount = await logger.deleteTrajectories(body.trajectoryIds);
|
|
650
|
+
sendJson(res, { deleted: deletedCount });
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
sendJson(res, { deleted: 0 });
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// ============================================================================
|
|
658
|
+
// Main Router
|
|
659
|
+
// ============================================================================
|
|
660
|
+
|
|
661
|
+
export async function handleTrajectoryRoute(
|
|
662
|
+
req: http.IncomingMessage,
|
|
663
|
+
res: http.ServerResponse,
|
|
664
|
+
runtime: AgentRuntime,
|
|
665
|
+
pathname: string,
|
|
666
|
+
method: string,
|
|
667
|
+
): Promise<boolean> {
|
|
668
|
+
if (!pathname.startsWith("/api/trajectories")) return false;
|
|
669
|
+
|
|
670
|
+
// GET /api/trajectories/config
|
|
671
|
+
if (pathname === "/api/trajectories/config" && method === "GET") {
|
|
672
|
+
await handleGetConfig(req, res, runtime);
|
|
673
|
+
return true;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// PUT /api/trajectories/config
|
|
677
|
+
if (pathname === "/api/trajectories/config" && method === "PUT") {
|
|
678
|
+
await handlePutConfig(req, res, runtime);
|
|
679
|
+
return true;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// POST /api/trajectories/export
|
|
683
|
+
if (pathname === "/api/trajectories/export" && method === "POST") {
|
|
684
|
+
await handleExportTrajectories(req, res, runtime);
|
|
685
|
+
return true;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// DELETE /api/trajectories
|
|
689
|
+
if (pathname === "/api/trajectories" && method === "DELETE") {
|
|
690
|
+
await handleDeleteTrajectories(req, res, runtime);
|
|
691
|
+
return true;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// GET /api/trajectories/stats
|
|
695
|
+
if (pathname === "/api/trajectories/stats" && method === "GET") {
|
|
696
|
+
await handleGetStats(req, res, runtime);
|
|
697
|
+
return true;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// GET /api/trajectories/:id
|
|
701
|
+
const detailMatch = pathname.match(/^\/api\/trajectories\/([^/]+)$/);
|
|
702
|
+
if (detailMatch && method === "GET") {
|
|
703
|
+
await handleGetTrajectoryDetail(req, res, runtime, detailMatch[1]);
|
|
704
|
+
return true;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// GET /api/trajectories
|
|
708
|
+
if (pathname === "/api/trajectories" && method === "GET") {
|
|
709
|
+
await handleGetTrajectories(req, res, runtime);
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
return false;
|
|
714
|
+
}
|