@elizaos/plugin-training 2.0.3-beta.6 → 2.0.3-beta.7
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/backends/native.d.ts +96 -0
- package/dist/backends/native.d.ts.map +1 -0
- package/dist/backends/native.js +308 -0
- package/dist/backends/native.js.map +1 -0
- package/dist/cli/train.d.ts +22 -0
- package/dist/cli/train.d.ts.map +1 -0
- package/dist/cli/train.js +219 -0
- package/dist/cli/train.js.map +1 -0
- package/dist/core/action-benchmark-runner.d.ts +55 -0
- package/dist/core/action-benchmark-runner.d.ts.map +1 -0
- package/dist/core/action-benchmark-runner.js +341 -0
- package/dist/core/action-benchmark-runner.js.map +1 -0
- package/dist/core/artifact-store.d.ts +72 -0
- package/dist/core/artifact-store.d.ts.map +1 -0
- package/dist/core/artifact-store.js +50 -0
- package/dist/core/artifact-store.js.map +1 -0
- package/dist/core/benchmark-matrix-artifact.d.ts +102 -0
- package/dist/core/benchmark-matrix-artifact.d.ts.map +1 -0
- package/dist/core/benchmark-matrix-artifact.js +381 -0
- package/dist/core/benchmark-matrix-artifact.js.map +1 -0
- package/dist/core/benchmark-vs-cerebras-runner.d.ts +37 -0
- package/dist/core/benchmark-vs-cerebras-runner.d.ts.map +1 -0
- package/dist/core/benchmark-vs-cerebras-runner.js +151 -0
- package/dist/core/benchmark-vs-cerebras-runner.js.map +1 -0
- package/dist/core/cerebras-eval-model.d.ts +54 -0
- package/dist/core/cerebras-eval-model.d.ts.map +1 -0
- package/dist/core/cerebras-eval-model.js +249 -0
- package/dist/core/cerebras-eval-model.js.map +1 -0
- package/dist/core/cli.d.ts +15 -0
- package/dist/core/cli.d.ts.map +1 -0
- package/dist/core/cli.js +1003 -0
- package/dist/core/cli.js.map +1 -0
- package/dist/core/context-audit.d.ts +51 -0
- package/dist/core/context-audit.d.ts.map +1 -0
- package/dist/core/context-audit.js +166 -0
- package/dist/core/context-audit.js.map +1 -0
- package/dist/core/context-catalog.d.ts +47 -0
- package/dist/core/context-catalog.d.ts.map +1 -0
- package/dist/core/context-catalog.js +269 -0
- package/dist/core/context-catalog.js.map +1 -0
- package/dist/core/context-types.d.ts +3 -0
- package/dist/core/context-types.d.ts.map +1 -0
- package/dist/core/context-types.js +18 -0
- package/dist/core/context-types.js.map +1 -0
- package/dist/core/dataset-generator.d.ts +135 -0
- package/dist/core/dataset-generator.d.ts.map +1 -0
- package/dist/core/dataset-generator.js +895 -0
- package/dist/core/dataset-generator.js.map +1 -0
- package/dist/core/eliza1-benchmark-recipe.d.ts +18 -0
- package/dist/core/eliza1-benchmark-recipe.d.ts.map +1 -0
- package/dist/core/eliza1-benchmark-recipe.js +64 -0
- package/dist/core/eliza1-benchmark-recipe.js.map +1 -0
- package/dist/core/eliza1-bundle-stager.d.ts +57 -0
- package/dist/core/eliza1-bundle-stager.d.ts.map +1 -0
- package/dist/core/eliza1-bundle-stager.js +149 -0
- package/dist/core/eliza1-bundle-stager.js.map +1 -0
- package/dist/core/ensure-cron-job.d.ts +53 -0
- package/dist/core/ensure-cron-job.d.ts.map +1 -0
- package/dist/core/ensure-cron-job.js +51 -0
- package/dist/core/ensure-cron-job.js.map +1 -0
- package/dist/core/eval-comparison-artifact.d.ts +72 -0
- package/dist/core/eval-comparison-artifact.d.ts.map +1 -0
- package/dist/core/eval-comparison-artifact.js +281 -0
- package/dist/core/eval-comparison-artifact.js.map +1 -0
- package/dist/core/feed-generation-runner.d.ts +37 -0
- package/dist/core/feed-generation-runner.d.ts.map +1 -0
- package/dist/core/feed-generation-runner.js +232 -0
- package/dist/core/feed-generation-runner.js.map +1 -0
- package/dist/core/html-escape.d.ts +5 -0
- package/dist/core/html-escape.d.ts.map +1 -0
- package/dist/core/html-escape.js +11 -0
- package/dist/core/html-escape.js.map +1 -0
- package/dist/core/huggingface-dataset-ingest.d.ts +52 -0
- package/dist/core/huggingface-dataset-ingest.d.ts.map +1 -0
- package/dist/core/huggingface-dataset-ingest.js +134 -0
- package/dist/core/huggingface-dataset-ingest.js.map +1 -0
- package/dist/core/index.d.ts +29 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +204 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/privacy-filter.d.ts +95 -0
- package/dist/core/privacy-filter.d.ts.map +1 -0
- package/dist/core/privacy-filter.js +324 -0
- package/dist/core/privacy-filter.js.map +1 -0
- package/dist/core/promotion-gate.d.ts +117 -0
- package/dist/core/promotion-gate.d.ts.map +1 -0
- package/dist/core/promotion-gate.js +85 -0
- package/dist/core/promotion-gate.js.map +1 -0
- package/dist/core/promotion-persist.d.ts +116 -0
- package/dist/core/promotion-persist.d.ts.map +1 -0
- package/dist/core/promotion-persist.js +93 -0
- package/dist/core/promotion-persist.js.map +1 -0
- package/dist/core/prompt-compare.d.ts +99 -0
- package/dist/core/prompt-compare.d.ts.map +1 -0
- package/dist/core/prompt-compare.js +210 -0
- package/dist/core/prompt-compare.js.map +1 -0
- package/dist/core/replay-validator.d.ts +136 -0
- package/dist/core/replay-validator.d.ts.map +1 -0
- package/dist/core/replay-validator.js +312 -0
- package/dist/core/replay-validator.js.map +1 -0
- package/dist/core/roleplay-executor.d.ts +123 -0
- package/dist/core/roleplay-executor.d.ts.map +1 -0
- package/dist/core/roleplay-executor.js +675 -0
- package/dist/core/roleplay-executor.js.map +1 -0
- package/dist/core/roleplay-trajectories.d.ts +54 -0
- package/dist/core/roleplay-trajectories.d.ts.map +1 -0
- package/dist/core/roleplay-trajectories.js +88 -0
- package/dist/core/roleplay-trajectories.js.map +1 -0
- package/dist/core/scenario-blueprints.d.ts +62 -0
- package/dist/core/scenario-blueprints.d.ts.map +1 -0
- package/dist/core/scenario-blueprints.js +850 -0
- package/dist/core/scenario-blueprints.js.map +1 -0
- package/dist/core/scenario-runner.d.ts +36 -0
- package/dist/core/scenario-runner.d.ts.map +1 -0
- package/dist/core/scenario-runner.js +216 -0
- package/dist/core/scenario-runner.js.map +1 -0
- package/dist/core/skill-scoring-cron.d.ts +57 -0
- package/dist/core/skill-scoring-cron.d.ts.map +1 -0
- package/dist/core/skill-scoring-cron.js +180 -0
- package/dist/core/skill-scoring-cron.js.map +1 -0
- package/dist/core/test-trajectory-collector.d.ts +37 -0
- package/dist/core/test-trajectory-collector.d.ts.map +1 -0
- package/dist/core/test-trajectory-collector.js +225 -0
- package/dist/core/test-trajectory-collector.js.map +1 -0
- package/dist/core/track-c-queue-task.d.ts +37 -0
- package/dist/core/track-c-queue-task.d.ts.map +1 -0
- package/dist/core/track-c-queue-task.js +104 -0
- package/dist/core/track-c-queue-task.js.map +1 -0
- package/dist/core/training-analysis-index.d.ts +104 -0
- package/dist/core/training-analysis-index.d.ts.map +1 -0
- package/dist/core/training-analysis-index.js +3297 -0
- package/dist/core/training-analysis-index.js.map +1 -0
- package/dist/core/training-collection-runner.d.ts +508 -0
- package/dist/core/training-collection-runner.d.ts.map +1 -0
- package/dist/core/training-collection-runner.js +2299 -0
- package/dist/core/training-collection-runner.js.map +1 -0
- package/dist/core/training-config.d.ts +52 -0
- package/dist/core/training-config.d.ts.map +1 -0
- package/dist/core/training-config.js +117 -0
- package/dist/core/training-config.js.map +1 -0
- package/dist/core/training-orchestrator.d.ts +112 -0
- package/dist/core/training-orchestrator.d.ts.map +1 -0
- package/dist/core/training-orchestrator.js +729 -0
- package/dist/core/training-orchestrator.js.map +1 -0
- package/dist/core/training-readiness-report.d.ts +52 -0
- package/dist/core/training-readiness-report.d.ts.map +1 -0
- package/dist/core/training-readiness-report.js +765 -0
- package/dist/core/training-readiness-report.js.map +1 -0
- package/dist/core/trajectory-consumer.d.ts +15 -0
- package/dist/core/trajectory-consumer.d.ts.map +1 -0
- package/dist/core/trajectory-consumer.js +61 -0
- package/dist/core/trajectory-consumer.js.map +1 -0
- package/dist/core/trajectory-export-bundle.d.ts +95 -0
- package/dist/core/trajectory-export-bundle.d.ts.map +1 -0
- package/dist/core/trajectory-export-bundle.js +561 -0
- package/dist/core/trajectory-export-bundle.js.map +1 -0
- package/dist/core/trajectory-export-cron.d.ts +57 -0
- package/dist/core/trajectory-export-cron.d.ts.map +1 -0
- package/dist/core/trajectory-export-cron.js +170 -0
- package/dist/core/trajectory-export-cron.js.map +1 -0
- package/dist/core/trajectory-hf-upload.d.ts +50 -0
- package/dist/core/trajectory-hf-upload.d.ts.map +1 -0
- package/dist/core/trajectory-hf-upload.js +111 -0
- package/dist/core/trajectory-hf-upload.js.map +1 -0
- package/dist/core/trajectory-task-datasets.d.ts +62 -0
- package/dist/core/trajectory-task-datasets.d.ts.map +1 -0
- package/dist/core/trajectory-task-datasets.js +427 -0
- package/dist/core/trajectory-task-datasets.js.map +1 -0
- package/dist/core/wait-for-service.d.ts +25 -0
- package/dist/core/wait-for-service.d.ts.map +1 -0
- package/dist/core/wait-for-service.js +19 -0
- package/dist/core/wait-for-service.js.map +1 -0
- package/dist/core/workspace-runtime.d.ts +4 -0
- package/dist/core/workspace-runtime.d.ts.map +1 -0
- package/dist/core/workspace-runtime.js +25 -0
- package/dist/core/workspace-runtime.js.map +1 -0
- package/dist/dspy/artifact.d.ts +54 -0
- package/dist/dspy/artifact.d.ts.map +1 -0
- package/dist/dspy/artifact.js +61 -0
- package/dist/dspy/artifact.js.map +1 -0
- package/dist/dspy/chain-of-thought.d.ts +27 -0
- package/dist/dspy/chain-of-thought.d.ts.map +1 -0
- package/dist/dspy/chain-of-thought.js +43 -0
- package/dist/dspy/chain-of-thought.js.map +1 -0
- package/dist/dspy/examples.d.ts +72 -0
- package/dist/dspy/examples.d.ts.map +1 -0
- package/dist/dspy/examples.js +105 -0
- package/dist/dspy/examples.js.map +1 -0
- package/dist/dspy/index.d.ts +15 -0
- package/dist/dspy/index.d.ts.map +1 -0
- package/dist/dspy/index.js +40 -0
- package/dist/dspy/index.js.map +1 -0
- package/dist/dspy/lm-adapter.d.ts +100 -0
- package/dist/dspy/lm-adapter.d.ts.map +1 -0
- package/dist/dspy/lm-adapter.js +81 -0
- package/dist/dspy/lm-adapter.js.map +1 -0
- package/dist/dspy/optimizers/dspy-bootstrap-fewshot.d.ts +23 -0
- package/dist/dspy/optimizers/dspy-bootstrap-fewshot.d.ts.map +1 -0
- package/dist/dspy/optimizers/dspy-bootstrap-fewshot.js +85 -0
- package/dist/dspy/optimizers/dspy-bootstrap-fewshot.js.map +1 -0
- package/dist/dspy/optimizers/dspy-copro.d.ts +29 -0
- package/dist/dspy/optimizers/dspy-copro.d.ts.map +1 -0
- package/dist/dspy/optimizers/dspy-copro.js +141 -0
- package/dist/dspy/optimizers/dspy-copro.js.map +1 -0
- package/dist/dspy/optimizers/dspy-mipro.d.ts +37 -0
- package/dist/dspy/optimizers/dspy-mipro.d.ts.map +1 -0
- package/dist/dspy/optimizers/dspy-mipro.js +194 -0
- package/dist/dspy/optimizers/dspy-mipro.js.map +1 -0
- package/dist/dspy/optimizers/index.d.ts +5 -0
- package/dist/dspy/optimizers/index.d.ts.map +1 -0
- package/dist/dspy/optimizers/index.js +11 -0
- package/dist/dspy/optimizers/index.js.map +1 -0
- package/dist/dspy/optimizers/types.d.ts +39 -0
- package/dist/dspy/optimizers/types.d.ts.map +1 -0
- package/dist/dspy/optimizers/types.js +1 -0
- package/dist/dspy/optimizers/types.js.map +1 -0
- package/dist/dspy/predict.d.ts +49 -0
- package/dist/dspy/predict.d.ts.map +1 -0
- package/dist/dspy/predict.js +73 -0
- package/dist/dspy/predict.js.map +1 -0
- package/dist/dspy/signature.d.ts +88 -0
- package/dist/dspy/signature.d.ts.map +1 -0
- package/dist/dspy/signature.js +205 -0
- package/dist/dspy/signature.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/optimizers/bootstrap-fewshot.d.ts +42 -0
- package/dist/optimizers/bootstrap-fewshot.d.ts.map +1 -0
- package/dist/optimizers/bootstrap-fewshot.js +92 -0
- package/dist/optimizers/bootstrap-fewshot.js.map +1 -0
- package/dist/optimizers/gepa.d.ts +63 -0
- package/dist/optimizers/gepa.d.ts.map +1 -0
- package/dist/optimizers/gepa.js +232 -0
- package/dist/optimizers/gepa.js.map +1 -0
- package/dist/optimizers/index.d.ts +7 -0
- package/dist/optimizers/index.d.ts.map +1 -0
- package/dist/optimizers/index.js +51 -0
- package/dist/optimizers/index.js.map +1 -0
- package/dist/optimizers/instruction-search.d.ts +39 -0
- package/dist/optimizers/instruction-search.d.ts.map +1 -0
- package/dist/optimizers/instruction-search.js +108 -0
- package/dist/optimizers/instruction-search.js.map +1 -0
- package/dist/optimizers/prompt-evolution.d.ts +39 -0
- package/dist/optimizers/prompt-evolution.d.ts.map +1 -0
- package/dist/optimizers/prompt-evolution.js +101 -0
- package/dist/optimizers/prompt-evolution.js.map +1 -0
- package/dist/optimizers/scoring.d.ts +139 -0
- package/dist/optimizers/scoring.d.ts.map +1 -0
- package/dist/optimizers/scoring.js +299 -0
- package/dist/optimizers/scoring.js.map +1 -0
- package/dist/optimizers/types.d.ts +105 -0
- package/dist/optimizers/types.d.ts.map +1 -0
- package/dist/optimizers/types.js +1 -0
- package/dist/optimizers/types.js.map +1 -0
- package/dist/register-runtime.d.ts +3 -0
- package/dist/register-runtime.d.ts.map +1 -0
- package/dist/register-runtime.js +60 -0
- package/dist/register-runtime.js.map +1 -0
- package/dist/register-terminal-view.d.ts +15 -0
- package/dist/register-terminal-view.d.ts.map +1 -0
- package/dist/register-terminal-view.js +31 -0
- package/dist/register-terminal-view.js.map +1 -0
- package/dist/routes/experience-routes.d.ts +21 -0
- package/dist/routes/experience-routes.d.ts.map +1 -0
- package/dist/routes/experience-routes.js +513 -0
- package/dist/routes/experience-routes.js.map +1 -0
- package/dist/routes/index.d.ts +5 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +17 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/training-routes.d.ts +10 -0
- package/dist/routes/training-routes.d.ts.map +1 -0
- package/dist/routes/training-routes.js +1239 -0
- package/dist/routes/training-routes.js.map +1 -0
- package/dist/routes/training-vast-routes.d.ts +35 -0
- package/dist/routes/training-vast-routes.d.ts.map +1 -0
- package/dist/routes/training-vast-routes.js +249 -0
- package/dist/routes/training-vast-routes.js.map +1 -0
- package/dist/routes/trajectory-routes.d.ts +19 -0
- package/dist/routes/trajectory-routes.d.ts.map +1 -0
- package/dist/routes/trajectory-routes.js +1122 -0
- package/dist/routes/trajectory-routes.js.map +1 -0
- package/dist/services/index.d.ts +9 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +63 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/training-backend-check.d.ts +8 -0
- package/dist/services/training-backend-check.d.ts.map +1 -0
- package/dist/services/training-backend-check.js +31 -0
- package/dist/services/training-backend-check.js.map +1 -0
- package/dist/services/training-service-like.d.ts +40 -0
- package/dist/services/training-service-like.d.ts.map +1 -0
- package/dist/services/training-service-like.js +1 -0
- package/dist/services/training-service-like.js.map +1 -0
- package/dist/services/training-service-registry.d.ts +4 -0
- package/dist/services/training-service-registry.d.ts.map +1 -0
- package/dist/services/training-service-registry.js +12 -0
- package/dist/services/training-service-registry.js.map +1 -0
- package/dist/services/training-service.d.ts +59 -0
- package/dist/services/training-service.d.ts.map +1 -0
- package/dist/services/training-service.js +154 -0
- package/dist/services/training-service.js.map +1 -0
- package/dist/services/training-trigger.d.ts +177 -0
- package/dist/services/training-trigger.d.ts.map +1 -0
- package/dist/services/training-trigger.js +300 -0
- package/dist/services/training-trigger.js.map +1 -0
- package/dist/services/training-vast-service.d.ts +149 -0
- package/dist/services/training-vast-service.d.ts.map +1 -0
- package/dist/services/training-vast-service.js +648 -0
- package/dist/services/training-vast-service.js.map +1 -0
- package/dist/services/vast-inference-stats.d.ts +37 -0
- package/dist/services/vast-inference-stats.d.ts.map +1 -0
- package/dist/services/vast-inference-stats.js +81 -0
- package/dist/services/vast-inference-stats.js.map +1 -0
- package/dist/services/vast-job-store.d.ts +74 -0
- package/dist/services/vast-job-store.d.ts.map +1 -0
- package/dist/services/vast-job-store.js +194 -0
- package/dist/services/vast-job-store.js.map +1 -0
- package/dist/services/vast-subprocess.d.ts +27 -0
- package/dist/services/vast-subprocess.d.ts.map +1 -0
- package/dist/services/vast-subprocess.js +78 -0
- package/dist/services/vast-subprocess.js.map +1 -0
- package/dist/setup-routes.d.ts +17 -0
- package/dist/setup-routes.d.ts.map +1 -0
- package/dist/setup-routes.js +319 -0
- package/dist/setup-routes.js.map +1 -0
- package/dist/ui/FineTuningSpatialView.d.ts +49 -0
- package/dist/ui/FineTuningSpatialView.d.ts.map +1 -0
- package/dist/ui/FineTuningSpatialView.js +154 -0
- package/dist/ui/FineTuningSpatialView.js.map +1 -0
- package/dist/ui/FineTuningView.d.ts +7 -0
- package/dist/ui/FineTuningView.d.ts.map +1 -0
- package/dist/ui/FineTuningView.helpers.d.ts +17 -0
- package/dist/ui/FineTuningView.helpers.d.ts.map +1 -0
- package/dist/ui/FineTuningView.helpers.js +30 -0
- package/dist/ui/FineTuningView.helpers.js.map +1 -0
- package/dist/ui/FineTuningView.interact.d.ts +2 -0
- package/dist/ui/FineTuningView.interact.d.ts.map +1 -0
- package/dist/ui/FineTuningView.interact.js +300 -0
- package/dist/ui/FineTuningView.interact.js.map +1 -0
- package/dist/ui/FineTuningView.js +4653 -0
- package/dist/ui/FineTuningView.js.map +1 -0
- package/dist/ui/fine-tuning-panels.d.ts +100 -0
- package/dist/ui/fine-tuning-panels.d.ts.map +1 -0
- package/dist/ui/fine-tuning-panels.helpers.d.ts +19 -0
- package/dist/ui/fine-tuning-panels.helpers.d.ts.map +1 -0
- package/dist/ui/fine-tuning-panels.helpers.js +77 -0
- package/dist/ui/fine-tuning-panels.helpers.js.map +1 -0
- package/dist/ui/fine-tuning-panels.js +928 -0
- package/dist/ui/fine-tuning-panels.js.map +1 -0
- package/dist/ui/index.d.ts +5 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +5 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/training-view-bundle.d.ts +3 -0
- package/dist/ui/training-view-bundle.d.ts.map +1 -0
- package/dist/ui/training-view-bundle.js +7 -0
- package/dist/ui/training-view-bundle.js.map +1 -0
- package/dist/views/bundle.js +5312 -0
- package/dist/views/bundle.js.map +1 -0
- package/package.json +7 -7
|
@@ -0,0 +1,1122 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createZipArchive,
|
|
3
|
+
enrichTrajectoryLlmCall,
|
|
4
|
+
executeRawSql,
|
|
5
|
+
extractRows,
|
|
6
|
+
saveTrajectory
|
|
7
|
+
} from "@elizaos/agent";
|
|
8
|
+
import {
|
|
9
|
+
ELIZA_NATIVE_TRAJECTORY_FORMAT,
|
|
10
|
+
readJsonBody as parseJsonBody,
|
|
11
|
+
sendJson,
|
|
12
|
+
sendJsonError
|
|
13
|
+
} from "@elizaos/core";
|
|
14
|
+
import { listTrajectoryCallEntries } from "../core/trajectory-consumer.js";
|
|
15
|
+
function isRouteCompatibleTrajectoryLogger(candidate) {
|
|
16
|
+
if (!candidate || typeof candidate !== "object") return false;
|
|
17
|
+
const logger = candidate;
|
|
18
|
+
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";
|
|
19
|
+
}
|
|
20
|
+
function collectCandidates(runtimeLike) {
|
|
21
|
+
const seen = /* @__PURE__ */ new Set();
|
|
22
|
+
const candidates = [];
|
|
23
|
+
const add = (candidate) => {
|
|
24
|
+
if (!candidate || seen.has(candidate)) return;
|
|
25
|
+
seen.add(candidate);
|
|
26
|
+
candidates.push(candidate);
|
|
27
|
+
};
|
|
28
|
+
if (typeof runtimeLike.getServicesByType === "function") {
|
|
29
|
+
const byType = runtimeLike.getServicesByType("trajectories");
|
|
30
|
+
if (Array.isArray(byType)) {
|
|
31
|
+
for (const candidate of byType) {
|
|
32
|
+
add(candidate);
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
add(byType);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (typeof runtimeLike.getService === "function") {
|
|
39
|
+
add(runtimeLike.getService("trajectories"));
|
|
40
|
+
}
|
|
41
|
+
return candidates;
|
|
42
|
+
}
|
|
43
|
+
function findCompatibleLogger(candidates) {
|
|
44
|
+
for (const candidate of candidates) {
|
|
45
|
+
if (isRouteCompatibleTrajectoryLogger(candidate)) {
|
|
46
|
+
return candidate;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
async function getTrajectoryLogger(runtime) {
|
|
52
|
+
const runtimeLike = runtime;
|
|
53
|
+
const immediate = findCompatibleLogger(collectCandidates(runtimeLike));
|
|
54
|
+
if (immediate) return immediate;
|
|
55
|
+
const status = typeof runtimeLike.getServiceRegistrationStatus === "function" ? runtimeLike.getServiceRegistrationStatus("trajectories") : "unknown";
|
|
56
|
+
if ((status === "pending" || status === "registering") && typeof runtimeLike.getServiceLoadPromise === "function") {
|
|
57
|
+
try {
|
|
58
|
+
await Promise.race([
|
|
59
|
+
runtimeLike.getServiceLoadPromise("trajectories"),
|
|
60
|
+
new Promise((resolve) => setTimeout(resolve, 5e3))
|
|
61
|
+
]);
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
return findCompatibleLogger(collectCandidates(runtimeLike));
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
function toNullableString(value) {
|
|
69
|
+
return typeof value === "string" ? value : null;
|
|
70
|
+
}
|
|
71
|
+
function asRecord(value) {
|
|
72
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
73
|
+
}
|
|
74
|
+
function toFiniteNumber(value) {
|
|
75
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
79
|
+
const parsed = Number(value);
|
|
80
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
function toOptionalString(value) {
|
|
85
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
86
|
+
}
|
|
87
|
+
function toOptionalBoolean(value) {
|
|
88
|
+
return typeof value === "boolean" ? value : void 0;
|
|
89
|
+
}
|
|
90
|
+
function toCacheHit(value) {
|
|
91
|
+
if (typeof value === "boolean") return value;
|
|
92
|
+
if (typeof value === "string") {
|
|
93
|
+
const normalized = value.trim().toLowerCase();
|
|
94
|
+
if (normalized === "hit" || normalized === "true") return true;
|
|
95
|
+
if (normalized === "miss" || normalized === "false") return false;
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
function toToolCallStatus(value) {
|
|
100
|
+
if (typeof value !== "string") return void 0;
|
|
101
|
+
const normalized = value.trim().toLowerCase();
|
|
102
|
+
return normalized === "queued" || normalized === "running" || normalized === "completed" || normalized === "skipped" || normalized === "failed" ? normalized : void 0;
|
|
103
|
+
}
|
|
104
|
+
function normalizeCreatedAt(value, timestamp) {
|
|
105
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
106
|
+
return value;
|
|
107
|
+
}
|
|
108
|
+
if (typeof timestamp === "number" && Number.isFinite(timestamp)) {
|
|
109
|
+
return new Date(timestamp).toISOString();
|
|
110
|
+
}
|
|
111
|
+
return void 0;
|
|
112
|
+
}
|
|
113
|
+
function timestampFromRecord(record) {
|
|
114
|
+
const timestamp = toFiniteNumber(record.timestamp);
|
|
115
|
+
if (timestamp !== null) return timestamp;
|
|
116
|
+
const createdAt = toFiniteNumber(record.createdAt);
|
|
117
|
+
if (createdAt !== null) return createdAt;
|
|
118
|
+
if (typeof record.createdAt === "string") {
|
|
119
|
+
const parsed = Date.parse(record.createdAt);
|
|
120
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
121
|
+
}
|
|
122
|
+
return void 0;
|
|
123
|
+
}
|
|
124
|
+
function eventBaseFromRecord(record, trajectoryId, fallbackId) {
|
|
125
|
+
const timestamp = timestampFromRecord(record);
|
|
126
|
+
return {
|
|
127
|
+
id: toOptionalString(record.id) ?? fallbackId,
|
|
128
|
+
trajectoryId,
|
|
129
|
+
stepId: toOptionalString(record.stepId),
|
|
130
|
+
stage: toOptionalString(record.stage),
|
|
131
|
+
timestamp,
|
|
132
|
+
createdAt: normalizeCreatedAt(record.createdAt, timestamp),
|
|
133
|
+
metadata: asRecord(record.metadata) ?? void 0
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function normalizeContextEvent(event, index) {
|
|
137
|
+
const record = asRecord(event);
|
|
138
|
+
const type = toOptionalString(record?.type);
|
|
139
|
+
if (!record || !type) return null;
|
|
140
|
+
return {
|
|
141
|
+
...record,
|
|
142
|
+
id: toOptionalString(record.id) ?? `context-event-${index}`,
|
|
143
|
+
type,
|
|
144
|
+
metadata: asRecord(record.metadata) ?? void 0
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function hasV5ContextEvents(traj) {
|
|
148
|
+
const record = asRecord(traj);
|
|
149
|
+
const metadata = asRecord(traj.metadata);
|
|
150
|
+
return Boolean(
|
|
151
|
+
asRecord(record?.contextObject) || asRecord(metadata?.contextObject) || Array.isArray(record?.contextEvents) || Array.isArray(metadata?.contextEvents) || record?.contextObjectVersion === 5
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
function readContextEventsFromObject(value) {
|
|
155
|
+
const record = asRecord(value);
|
|
156
|
+
return Array.isArray(record?.events) ? record.events : null;
|
|
157
|
+
}
|
|
158
|
+
function extractContextEventsForRoute(traj) {
|
|
159
|
+
const record = asRecord(traj);
|
|
160
|
+
const metadata = asRecord(traj.metadata);
|
|
161
|
+
return readContextEventsFromObject(record?.contextObject) ?? readContextEventsFromObject(metadata?.contextObject) ?? (Array.isArray(record?.contextEvents) ? record.contextEvents : null) ?? (Array.isArray(metadata?.contextEvents) ? metadata.contextEvents : null) ?? (record?.contextObjectVersion === 5 && Array.isArray(record.events) ? record.events : null) ?? [];
|
|
162
|
+
}
|
|
163
|
+
function readRecordArray(record, key) {
|
|
164
|
+
const value = record?.[key];
|
|
165
|
+
if (!Array.isArray(value)) return [];
|
|
166
|
+
return value.filter(
|
|
167
|
+
(item) => Boolean(asRecord(item))
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
function normalizeToolEvent(record, trajectoryId, fallbackId) {
|
|
171
|
+
const type = toOptionalString(record.type);
|
|
172
|
+
if (type !== "tool_call" && type !== "tool_result" && type !== "tool_error") {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
const tool = asRecord(record.tool);
|
|
176
|
+
return {
|
|
177
|
+
...eventBaseFromRecord(record, trajectoryId, fallbackId),
|
|
178
|
+
type,
|
|
179
|
+
callId: toOptionalString(record.callId),
|
|
180
|
+
toolCallId: toOptionalString(record.toolCallId),
|
|
181
|
+
actionName: toOptionalString(record.actionName),
|
|
182
|
+
toolName: toOptionalString(record.toolName) ?? toOptionalString(tool?.name),
|
|
183
|
+
name: toOptionalString(record.name),
|
|
184
|
+
args: asRecord(record.args) ?? void 0,
|
|
185
|
+
input: asRecord(record.input) ?? void 0,
|
|
186
|
+
result: record.result,
|
|
187
|
+
output: record.output,
|
|
188
|
+
status: toToolCallStatus(record.status),
|
|
189
|
+
success: toOptionalBoolean(record.success),
|
|
190
|
+
durationMs: toFiniteNumber(record.durationMs) ?? void 0,
|
|
191
|
+
duration: toFiniteNumber(record.duration) ?? void 0,
|
|
192
|
+
error: toOptionalString(record.error)
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function normalizeEvaluationEvent(record, trajectoryId, fallbackId) {
|
|
196
|
+
const type = toOptionalString(record.type);
|
|
197
|
+
if (type !== "evaluation" && type !== "evaluator") return null;
|
|
198
|
+
return {
|
|
199
|
+
...eventBaseFromRecord(record, trajectoryId, fallbackId),
|
|
200
|
+
type,
|
|
201
|
+
evaluatorName: toOptionalString(record.evaluatorName),
|
|
202
|
+
name: toOptionalString(record.name),
|
|
203
|
+
status: toToolCallStatus(record.status),
|
|
204
|
+
success: toOptionalBoolean(record.success),
|
|
205
|
+
decision: toOptionalString(record.decision),
|
|
206
|
+
thought: toOptionalString(record.thought),
|
|
207
|
+
result: record.result,
|
|
208
|
+
durationMs: toFiniteNumber(record.durationMs) ?? void 0,
|
|
209
|
+
error: toOptionalString(record.error)
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function normalizeCacheObservation(record, trajectoryId, fallbackId) {
|
|
213
|
+
const type = toOptionalString(record.type);
|
|
214
|
+
if (type !== "cache_observation" && type !== "cache") return null;
|
|
215
|
+
const hit = toCacheHit(record.hit) ?? toCacheHit(record.cacheHit) ?? toCacheHit(record.result) ?? toCacheHit(record.status);
|
|
216
|
+
if (hit === null) return null;
|
|
217
|
+
return {
|
|
218
|
+
...eventBaseFromRecord(record, trajectoryId, fallbackId),
|
|
219
|
+
type,
|
|
220
|
+
cacheName: toOptionalString(record.cacheName) ?? toOptionalString(record.name),
|
|
221
|
+
key: toOptionalString(record.key),
|
|
222
|
+
scope: toOptionalString(record.scope),
|
|
223
|
+
hit,
|
|
224
|
+
reason: toOptionalString(record.reason),
|
|
225
|
+
ttlMs: toFiniteNumber(record.ttlMs) ?? void 0,
|
|
226
|
+
ageMs: toFiniteNumber(record.ageMs) ?? void 0,
|
|
227
|
+
sizeBytes: toFiniteNumber(record.sizeBytes) ?? void 0,
|
|
228
|
+
tokenCount: toFiniteNumber(record.tokenCount) ?? toFiniteNumber(record.cachedInputTokens) ?? toFiniteNumber(record.cacheReadInputTokens) ?? void 0
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function normalizeContextDiffChange(value) {
|
|
232
|
+
const record = asRecord(value);
|
|
233
|
+
const type = toOptionalString(record?.type);
|
|
234
|
+
if (!record || !type) return null;
|
|
235
|
+
return {
|
|
236
|
+
type,
|
|
237
|
+
path: toOptionalString(record.path) ?? toOptionalString(record.key),
|
|
238
|
+
before: record.before ?? record.previous,
|
|
239
|
+
after: record.after ?? record.current,
|
|
240
|
+
summary: toOptionalString(record.summary),
|
|
241
|
+
tokenDelta: toFiniteNumber(record.tokenDelta) ?? void 0
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function normalizeContextDiff(record, trajectoryId, fallbackId) {
|
|
245
|
+
if (toOptionalString(record.type) !== "context_diff") return null;
|
|
246
|
+
const summary = asRecord(record.summary);
|
|
247
|
+
const changes = Array.isArray(record.changes) ? record.changes.map((change) => normalizeContextDiffChange(change)).filter((change) => change !== null) : void 0;
|
|
248
|
+
return {
|
|
249
|
+
...eventBaseFromRecord(record, trajectoryId, fallbackId),
|
|
250
|
+
type: "context_diff",
|
|
251
|
+
label: toOptionalString(record.label),
|
|
252
|
+
beforeContextId: toOptionalString(record.beforeContextId),
|
|
253
|
+
afterContextId: toOptionalString(record.afterContextId),
|
|
254
|
+
added: toFiniteNumber(record.added) ?? toFiniteNumber(summary?.added) ?? void 0,
|
|
255
|
+
removed: toFiniteNumber(record.removed) ?? toFiniteNumber(summary?.removed) ?? void 0,
|
|
256
|
+
changed: toFiniteNumber(record.changed) ?? toFiniteNumber(summary?.changed) ?? void 0,
|
|
257
|
+
tokenDelta: toFiniteNumber(record.tokenDelta) ?? toFiniteNumber(summary?.tokenDelta) ?? void 0,
|
|
258
|
+
changes,
|
|
259
|
+
before: record.before,
|
|
260
|
+
after: record.after
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
function normalizeTrajectoryEvent(record, trajectoryId, fallbackId) {
|
|
264
|
+
const specialized = normalizeToolEvent(record, trajectoryId, fallbackId) ?? normalizeEvaluationEvent(record, trajectoryId, fallbackId) ?? normalizeCacheObservation(record, trajectoryId, fallbackId) ?? normalizeContextDiff(record, trajectoryId, fallbackId);
|
|
265
|
+
if (specialized) return specialized;
|
|
266
|
+
const type = toOptionalString(record.type);
|
|
267
|
+
if (!type) return null;
|
|
268
|
+
return {
|
|
269
|
+
...record,
|
|
270
|
+
...eventBaseFromRecord(record, trajectoryId, fallbackId),
|
|
271
|
+
type
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
function normalizeCacheStats(value) {
|
|
275
|
+
const record = asRecord(value);
|
|
276
|
+
if (!record) return null;
|
|
277
|
+
const hits = toFiniteNumber(record.hits);
|
|
278
|
+
const misses = toFiniteNumber(record.misses);
|
|
279
|
+
const total = toFiniteNumber(record.total);
|
|
280
|
+
if (hits === null || misses === null || total === null) return null;
|
|
281
|
+
return {
|
|
282
|
+
hits,
|
|
283
|
+
misses,
|
|
284
|
+
total,
|
|
285
|
+
hitRate: toFiniteNumber(record.hitRate) ?? hits / Math.max(total, 1),
|
|
286
|
+
tokenCount: toFiniteNumber(record.tokenCount) ?? void 0,
|
|
287
|
+
sizeBytes: toFiniteNumber(record.sizeBytes) ?? void 0
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function cacheStatsFromObservations(observations) {
|
|
291
|
+
if (observations.length === 0) return void 0;
|
|
292
|
+
const hits = observations.filter((observation) => observation.hit).length;
|
|
293
|
+
const total = observations.length;
|
|
294
|
+
const tokenCount = observations.reduce(
|
|
295
|
+
(sum, observation) => sum + (observation.tokenCount ?? 0),
|
|
296
|
+
0
|
|
297
|
+
);
|
|
298
|
+
const sizeBytes = observations.reduce(
|
|
299
|
+
(sum, observation) => sum + (observation.sizeBytes ?? 0),
|
|
300
|
+
0
|
|
301
|
+
);
|
|
302
|
+
return {
|
|
303
|
+
hits,
|
|
304
|
+
misses: total - hits,
|
|
305
|
+
total,
|
|
306
|
+
hitRate: hits / Math.max(total, 1),
|
|
307
|
+
...tokenCount > 0 ? { tokenCount } : {},
|
|
308
|
+
...sizeBytes > 0 ? { sizeBytes } : {}
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function contextEventToTrajectoryEvent(event, trajectoryId, index) {
|
|
312
|
+
const { createdAt: _createdAt, ...eventWithoutCreatedAt } = event;
|
|
313
|
+
const stage = event.type === "tool" ? "actions" : event.type === "cache" ? "cache" : "context";
|
|
314
|
+
const base = eventBaseFromRecord(
|
|
315
|
+
{ ...event, stage: event.stage ?? stage },
|
|
316
|
+
trajectoryId,
|
|
317
|
+
`context-event-${index}`
|
|
318
|
+
);
|
|
319
|
+
return {
|
|
320
|
+
...eventWithoutCreatedAt,
|
|
321
|
+
...base,
|
|
322
|
+
createdAt: base.createdAt,
|
|
323
|
+
type: event.type
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
function embeddedEventRecordsFromContextEvent(event) {
|
|
327
|
+
const metadata = asRecord(event.metadata);
|
|
328
|
+
const value = event.type === "metadata" ? asRecord(event.value) : null;
|
|
329
|
+
return [
|
|
330
|
+
asRecord(event.event),
|
|
331
|
+
asRecord(event.trajectoryEvent),
|
|
332
|
+
asRecord(event.toolEvent),
|
|
333
|
+
asRecord(event.cacheObservation),
|
|
334
|
+
asRecord(event.contextDiff),
|
|
335
|
+
asRecord(metadata?.event),
|
|
336
|
+
asRecord(metadata?.trajectoryEvent),
|
|
337
|
+
asRecord(metadata?.toolEvent),
|
|
338
|
+
asRecord(metadata?.cacheObservation),
|
|
339
|
+
asRecord(metadata?.contextDiff),
|
|
340
|
+
value && toOptionalString(event.key) === "toolEvent" ? { ...value, type: value.type ?? "tool_call" } : null,
|
|
341
|
+
value && toOptionalString(event.key) === "cacheObservation" ? { ...value, type: value.type ?? "cache_observation" } : null,
|
|
342
|
+
value && toOptionalString(event.key) === "contextDiff" ? { ...value, type: value.type ?? "context_diff" } : null
|
|
343
|
+
].filter((record) => record !== null);
|
|
344
|
+
}
|
|
345
|
+
function cacheStatsFromContextEvents(events) {
|
|
346
|
+
for (const event of events) {
|
|
347
|
+
if (event.type === "metadata" && (event.key === "cacheStats" || event.key === "cache_stats")) {
|
|
348
|
+
const stats2 = normalizeCacheStats(event.value);
|
|
349
|
+
if (stats2) return stats2;
|
|
350
|
+
}
|
|
351
|
+
const metadata = asRecord(event.metadata);
|
|
352
|
+
const stats = normalizeCacheStats(metadata?.cacheStats);
|
|
353
|
+
if (stats) return stats;
|
|
354
|
+
}
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
function dedupeTrajectoryEvents(events) {
|
|
358
|
+
const seen = /* @__PURE__ */ new Set();
|
|
359
|
+
const deduped = [];
|
|
360
|
+
for (const [index, event] of events.entries()) {
|
|
361
|
+
const key = `${event.type ?? "event"}:${event.id ?? index}`;
|
|
362
|
+
if (seen.has(key)) continue;
|
|
363
|
+
seen.add(key);
|
|
364
|
+
deduped.push(event);
|
|
365
|
+
}
|
|
366
|
+
return deduped;
|
|
367
|
+
}
|
|
368
|
+
function buildUIEventFields(traj, trajectoryId) {
|
|
369
|
+
const root = asRecord(traj);
|
|
370
|
+
const metadata = asRecord(traj.metadata);
|
|
371
|
+
const contextEvents = hasV5ContextEvents(traj) ? extractContextEventsForRoute(traj).map((event, index) => normalizeContextEvent(event, index)).filter((event) => event !== null) : [];
|
|
372
|
+
const explicitRecords = [
|
|
373
|
+
...readRecordArray(root, "events"),
|
|
374
|
+
...readRecordArray(metadata, "events"),
|
|
375
|
+
...readRecordArray(metadata, "trajectoryEvents"),
|
|
376
|
+
...contextEvents,
|
|
377
|
+
...contextEvents.flatMap(embeddedEventRecordsFromContextEvent)
|
|
378
|
+
];
|
|
379
|
+
const toolEvents = dedupeTrajectoryEvents(
|
|
380
|
+
[
|
|
381
|
+
...readRecordArray(root, "toolEvents"),
|
|
382
|
+
...readRecordArray(metadata, "toolEvents"),
|
|
383
|
+
...explicitRecords
|
|
384
|
+
].map(
|
|
385
|
+
(record, index) => normalizeToolEvent(record, trajectoryId, `tool-event-${index}`)
|
|
386
|
+
).filter((event) => event !== null)
|
|
387
|
+
);
|
|
388
|
+
const evaluationEvents = dedupeTrajectoryEvents(
|
|
389
|
+
[
|
|
390
|
+
...readRecordArray(root, "evaluationEvents"),
|
|
391
|
+
...readRecordArray(metadata, "evaluationEvents"),
|
|
392
|
+
...explicitRecords
|
|
393
|
+
].map(
|
|
394
|
+
(record, index) => normalizeEvaluationEvent(
|
|
395
|
+
record,
|
|
396
|
+
trajectoryId,
|
|
397
|
+
`evaluation-event-${index}`
|
|
398
|
+
)
|
|
399
|
+
).filter((event) => event !== null)
|
|
400
|
+
);
|
|
401
|
+
const cacheObservations = dedupeTrajectoryEvents(
|
|
402
|
+
[
|
|
403
|
+
...readRecordArray(root, "cacheObservations"),
|
|
404
|
+
...readRecordArray(metadata, "cacheObservations"),
|
|
405
|
+
...explicitRecords
|
|
406
|
+
].map(
|
|
407
|
+
(record, index) => normalizeCacheObservation(
|
|
408
|
+
record,
|
|
409
|
+
trajectoryId,
|
|
410
|
+
`cache-observation-${index}`
|
|
411
|
+
)
|
|
412
|
+
).filter((event) => event !== null)
|
|
413
|
+
);
|
|
414
|
+
const contextDiffs = dedupeTrajectoryEvents(
|
|
415
|
+
[
|
|
416
|
+
...readRecordArray(root, "contextDiffs"),
|
|
417
|
+
...readRecordArray(metadata, "contextDiffs"),
|
|
418
|
+
...explicitRecords
|
|
419
|
+
].map(
|
|
420
|
+
(record, index) => normalizeContextDiff(record, trajectoryId, `context-diff-${index}`)
|
|
421
|
+
).filter((event) => event !== null)
|
|
422
|
+
);
|
|
423
|
+
const events = dedupeTrajectoryEvents([
|
|
424
|
+
...explicitRecords.map(
|
|
425
|
+
(record, index) => normalizeTrajectoryEvent(record, trajectoryId, `event-${index}`)
|
|
426
|
+
).filter((event) => event !== null),
|
|
427
|
+
...contextEvents.map(
|
|
428
|
+
(event, index) => contextEventToTrajectoryEvent(event, trajectoryId, index)
|
|
429
|
+
),
|
|
430
|
+
...toolEvents,
|
|
431
|
+
...evaluationEvents,
|
|
432
|
+
...cacheObservations,
|
|
433
|
+
...contextDiffs
|
|
434
|
+
]);
|
|
435
|
+
const cacheStats = normalizeCacheStats(root?.cacheStats) ?? normalizeCacheStats(metadata?.cacheStats) ?? cacheStatsFromContextEvents(contextEvents) ?? cacheStatsFromObservations(cacheObservations);
|
|
436
|
+
return {
|
|
437
|
+
...events.length > 0 ? { events } : {},
|
|
438
|
+
...contextEvents.length > 0 ? { contextEvents } : {},
|
|
439
|
+
...toolEvents.length > 0 ? { toolEvents } : {},
|
|
440
|
+
...evaluationEvents.length > 0 ? { evaluationEvents } : {},
|
|
441
|
+
...cacheObservations.length > 0 ? { cacheObservations } : {},
|
|
442
|
+
...cacheStats ? { cacheStats } : {},
|
|
443
|
+
...contextDiffs.length > 0 ? { contextDiffs } : {}
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
function estimateTokenCount(text) {
|
|
447
|
+
return Math.max(1, Math.ceil(text.length / 4));
|
|
448
|
+
}
|
|
449
|
+
function buildDisplayMetadata(traj) {
|
|
450
|
+
const metadata = { ...asRecord(traj.metadata) ?? {} };
|
|
451
|
+
const calls = listTrajectoryCallEntries(traj).map((entry) => entry.call);
|
|
452
|
+
if (calls.length > 0 && !calls.every((call) => isSyntheticTrajectoryCall(call))) {
|
|
453
|
+
delete metadata.syntheticLlmCall;
|
|
454
|
+
delete metadata.syntheticLlmCallSource;
|
|
455
|
+
}
|
|
456
|
+
return metadata;
|
|
457
|
+
}
|
|
458
|
+
function normalizePersistedStatus(value) {
|
|
459
|
+
const normalized = String(value ?? "").trim().toLowerCase();
|
|
460
|
+
if (normalized === "active" || normalized === "completed" || normalized === "error" || normalized === "timeout") {
|
|
461
|
+
return normalized;
|
|
462
|
+
}
|
|
463
|
+
return normalized.length > 0 ? "completed" : "active";
|
|
464
|
+
}
|
|
465
|
+
function toPersistedTrajectory(traj) {
|
|
466
|
+
const metadata = buildDisplayMetadata(traj);
|
|
467
|
+
const status = normalizePersistedStatus(
|
|
468
|
+
traj.metrics?.finalStatus ?? (typeof traj.endTime === "number" ? "completed" : "active")
|
|
469
|
+
);
|
|
470
|
+
const persistedSteps = (traj.steps ?? []).map(
|
|
471
|
+
(step, index) => ({
|
|
472
|
+
stepId: typeof step.stepId === "string" && step.stepId.trim().length > 0 ? step.stepId.trim() : `${traj.trajectoryId}-step-${index + 1}`,
|
|
473
|
+
stepNumber: index,
|
|
474
|
+
timestamp: typeof step.timestamp === "number" && Number.isFinite(step.timestamp) ? step.timestamp : traj.startTime,
|
|
475
|
+
llmCalls: (step.llmCalls ?? []).map((call, callIndex) => {
|
|
476
|
+
const normalizedCall = enrichTrajectoryLlmCall(
|
|
477
|
+
call
|
|
478
|
+
);
|
|
479
|
+
return {
|
|
480
|
+
callId: typeof normalizedCall.callId === "string" && normalizedCall.callId.trim().length > 0 ? normalizedCall.callId.trim() : `${traj.trajectoryId}-call-${index + 1}-${callIndex + 1}`,
|
|
481
|
+
timestamp: typeof normalizedCall.timestamp === "number" && Number.isFinite(normalizedCall.timestamp) ? normalizedCall.timestamp : step.timestamp,
|
|
482
|
+
model: typeof normalizedCall.model === "string" ? normalizedCall.model : "unknown",
|
|
483
|
+
systemPrompt: typeof normalizedCall.systemPrompt === "string" ? normalizedCall.systemPrompt : "",
|
|
484
|
+
userPrompt: typeof normalizedCall.userPrompt === "string" ? normalizedCall.userPrompt : "",
|
|
485
|
+
response: typeof normalizedCall.response === "string" ? normalizedCall.response : "",
|
|
486
|
+
temperature: toFiniteNumber(normalizedCall.temperature) ?? 0,
|
|
487
|
+
maxTokens: toFiniteNumber(normalizedCall.maxTokens) ?? 0,
|
|
488
|
+
purpose: typeof normalizedCall.purpose === "string" ? normalizedCall.purpose : "",
|
|
489
|
+
actionType: typeof normalizedCall.actionType === "string" ? normalizedCall.actionType : "",
|
|
490
|
+
stepType: typeof normalizedCall.stepType === "string" ? normalizedCall.stepType : void 0,
|
|
491
|
+
tags: Array.isArray(normalizedCall.tags) ? normalizedCall.tags.filter(
|
|
492
|
+
(tag) => typeof tag === "string"
|
|
493
|
+
) : void 0,
|
|
494
|
+
latencyMs: toFiniteNumber(normalizedCall.latencyMs) ?? 0,
|
|
495
|
+
promptTokens: toFiniteNumber(normalizedCall.promptTokens) ?? void 0,
|
|
496
|
+
completionTokens: toFiniteNumber(normalizedCall.completionTokens) ?? void 0
|
|
497
|
+
};
|
|
498
|
+
}),
|
|
499
|
+
providerAccesses: (step.providerAccesses ?? []).map(
|
|
500
|
+
(access, accessIndex) => ({
|
|
501
|
+
providerId: typeof access.providerId === "string" && access.providerId.trim().length > 0 ? access.providerId.trim() : `${traj.trajectoryId}-provider-${index + 1}-${accessIndex + 1}`,
|
|
502
|
+
providerName: typeof access.providerName === "string" ? access.providerName : "unknown",
|
|
503
|
+
timestamp: typeof access.timestamp === "number" && Number.isFinite(access.timestamp) ? access.timestamp : step.timestamp,
|
|
504
|
+
data: asRecord(access.data) ?? {},
|
|
505
|
+
query: asRecord(access.query) ?? void 0,
|
|
506
|
+
purpose: typeof access.purpose === "string" ? access.purpose : ""
|
|
507
|
+
})
|
|
508
|
+
)
|
|
509
|
+
})
|
|
510
|
+
);
|
|
511
|
+
return {
|
|
512
|
+
id: traj.trajectoryId,
|
|
513
|
+
source: toNullableString(metadata.source) ?? "runtime",
|
|
514
|
+
status,
|
|
515
|
+
startTime: traj.startTime,
|
|
516
|
+
endTime: typeof traj.endTime === "number" ? traj.endTime : null,
|
|
517
|
+
scenarioId: typeof traj.scenarioId === "string" ? traj.scenarioId : void 0,
|
|
518
|
+
batchId: typeof traj.batchId === "string" ? traj.batchId : void 0,
|
|
519
|
+
steps: persistedSteps,
|
|
520
|
+
metadata,
|
|
521
|
+
totalReward: 0,
|
|
522
|
+
createdAt: new Date(traj.startTime).toISOString(),
|
|
523
|
+
updatedAt: new Date(
|
|
524
|
+
typeof traj.endTime === "number" ? traj.endTime : Date.now()
|
|
525
|
+
).toISOString()
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
function listItemToUIRecord(item) {
|
|
529
|
+
const status = item.status === "timeout" || item.status === "error" ? "error" : item.status;
|
|
530
|
+
return {
|
|
531
|
+
id: item.id,
|
|
532
|
+
agentId: item.agentId,
|
|
533
|
+
roomId: null,
|
|
534
|
+
entityId: null,
|
|
535
|
+
conversationId: null,
|
|
536
|
+
source: item.source,
|
|
537
|
+
status,
|
|
538
|
+
startTime: item.startTime,
|
|
539
|
+
endTime: item.endTime,
|
|
540
|
+
durationMs: item.durationMs,
|
|
541
|
+
llmCallCount: item.llmCallCount,
|
|
542
|
+
providerAccessCount: item.providerAccessCount,
|
|
543
|
+
totalPromptTokens: item.totalPromptTokens,
|
|
544
|
+
totalCompletionTokens: item.totalCompletionTokens,
|
|
545
|
+
...item.scenarioId ? { scenarioId: item.scenarioId } : {},
|
|
546
|
+
...item.batchId ? { batchId: item.batchId } : {},
|
|
547
|
+
metadata: {
|
|
548
|
+
...item.metadata ?? {},
|
|
549
|
+
...item.scenarioId ? { scenarioId: item.scenarioId } : {},
|
|
550
|
+
...item.batchId ? { batchId: item.batchId } : {}
|
|
551
|
+
},
|
|
552
|
+
createdAt: item.createdAt,
|
|
553
|
+
updatedAt: item.updatedAt ?? item.createdAt
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
function trajectoryToUIDetail(traj) {
|
|
557
|
+
const finalStatus = traj.metrics?.finalStatus ?? "completed";
|
|
558
|
+
const normalizedEndTime = typeof traj.endTime === "number" && traj.endTime > 0 ? traj.endTime : null;
|
|
559
|
+
const status = finalStatus === "timeout" || finalStatus === "terminated" || finalStatus === "error" ? "error" : finalStatus === "completed" ? "completed" : normalizedEndTime ? "completed" : "active";
|
|
560
|
+
const llmCalls = [];
|
|
561
|
+
const providerAccesses = [];
|
|
562
|
+
let totalPromptTokens = 0;
|
|
563
|
+
let totalCompletionTokens = 0;
|
|
564
|
+
const trajectoryId = String(traj.trajectoryId);
|
|
565
|
+
for (const entry of listTrajectoryCallEntries(traj)) {
|
|
566
|
+
const call = enrichTrajectoryLlmCall(
|
|
567
|
+
entry.call
|
|
568
|
+
);
|
|
569
|
+
llmCalls.push({
|
|
570
|
+
id: call.callId || `${entry.stepId}-call-${entry.callIndex}`,
|
|
571
|
+
trajectoryId,
|
|
572
|
+
stepId: entry.stepId,
|
|
573
|
+
model: call.model || "unknown",
|
|
574
|
+
systemPrompt: call.systemPrompt || "",
|
|
575
|
+
userPrompt: call.userPrompt || "",
|
|
576
|
+
response: call.response || "",
|
|
577
|
+
temperature: typeof call.temperature === "number" ? call.temperature : 0,
|
|
578
|
+
maxTokens: typeof call.maxTokens === "number" ? call.maxTokens : 0,
|
|
579
|
+
purpose: call.purpose || "",
|
|
580
|
+
actionType: call.actionType || "",
|
|
581
|
+
stepType: call.stepType || "",
|
|
582
|
+
tags: Array.isArray(call.tags) ? call.tags.filter((tag) => typeof tag === "string") : [],
|
|
583
|
+
latencyMs: call.latencyMs || 0,
|
|
584
|
+
promptTokens: call.promptTokens,
|
|
585
|
+
completionTokens: call.completionTokens,
|
|
586
|
+
timestamp: call.timestamp || entry.step.timestamp,
|
|
587
|
+
createdAt: new Date(call.timestamp || entry.step.timestamp).toISOString()
|
|
588
|
+
});
|
|
589
|
+
totalPromptTokens += call.promptTokens || 0;
|
|
590
|
+
totalCompletionTokens += call.completionTokens || 0;
|
|
591
|
+
}
|
|
592
|
+
for (let i = 0; i < (traj.steps || []).length; i++) {
|
|
593
|
+
const step = traj.steps?.[i];
|
|
594
|
+
if (!step) continue;
|
|
595
|
+
const stepId = typeof step.stepId === "string" ? step.stepId : `step-${i}`;
|
|
596
|
+
const providerAccessList = step.providerAccesses ?? [];
|
|
597
|
+
for (let k = 0; k < providerAccessList.length; k++) {
|
|
598
|
+
const access = providerAccessList[k];
|
|
599
|
+
providerAccesses.push({
|
|
600
|
+
id: access.providerId || `${stepId}-provider-${k}`,
|
|
601
|
+
trajectoryId,
|
|
602
|
+
stepId,
|
|
603
|
+
providerName: access.providerName || "unknown",
|
|
604
|
+
purpose: access.purpose || "",
|
|
605
|
+
data: access.data || {},
|
|
606
|
+
query: access.query,
|
|
607
|
+
timestamp: access.timestamp || step.timestamp,
|
|
608
|
+
createdAt: new Date(access.timestamp || step.timestamp).toISOString()
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
const metadata = buildDisplayMetadata(traj);
|
|
613
|
+
const normalizedDurationMs = status === "active" ? null : typeof traj.durationMs === "number" ? traj.durationMs : null;
|
|
614
|
+
const updatedAtMs = normalizedEndTime ?? (traj.startTime || Date.now());
|
|
615
|
+
const trajectory = {
|
|
616
|
+
id: trajectoryId,
|
|
617
|
+
agentId: String(traj.agentId),
|
|
618
|
+
roomId: toNullableString(metadata.roomId),
|
|
619
|
+
entityId: toNullableString(metadata.entityId),
|
|
620
|
+
conversationId: toNullableString(metadata.conversationId),
|
|
621
|
+
source: toNullableString(metadata.source) ?? "chat",
|
|
622
|
+
status,
|
|
623
|
+
startTime: traj.startTime,
|
|
624
|
+
endTime: normalizedEndTime,
|
|
625
|
+
durationMs: normalizedDurationMs,
|
|
626
|
+
llmCallCount: llmCalls.length,
|
|
627
|
+
providerAccessCount: providerAccesses.length,
|
|
628
|
+
totalPromptTokens,
|
|
629
|
+
totalCompletionTokens,
|
|
630
|
+
metadata,
|
|
631
|
+
createdAt: new Date(traj.startTime).toISOString(),
|
|
632
|
+
updatedAt: new Date(updatedAtMs).toISOString()
|
|
633
|
+
};
|
|
634
|
+
return {
|
|
635
|
+
trajectory,
|
|
636
|
+
llmCalls,
|
|
637
|
+
providerAccesses,
|
|
638
|
+
...buildUIEventFields(traj, trajectoryId)
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
const LEGACY_SYNTHETIC_RESPONSE_MARKER = "placeholder call inserted";
|
|
642
|
+
function isSyntheticTrajectoryCall(call) {
|
|
643
|
+
const model = String(call.model ?? "").toLowerCase();
|
|
644
|
+
const systemPrompt = String(call.systemPrompt ?? "").toLowerCase();
|
|
645
|
+
const response = String(call.response ?? "").toLowerCase();
|
|
646
|
+
return model.includes("synthetic") || systemPrompt.includes("[synthetic]") || response.includes(LEGACY_SYNTHETIC_RESPONSE_MARKER);
|
|
647
|
+
}
|
|
648
|
+
function needsConversationBackfill(traj) {
|
|
649
|
+
const calls = listTrajectoryCallEntries(traj).map((entry) => entry.call);
|
|
650
|
+
if (calls.length === 0) {
|
|
651
|
+
return true;
|
|
652
|
+
}
|
|
653
|
+
return calls.every((call) => isSyntheticTrajectoryCall(call));
|
|
654
|
+
}
|
|
655
|
+
function extractMessageText(memory) {
|
|
656
|
+
if (!memory || typeof memory !== "object") return "";
|
|
657
|
+
const content = memory.content;
|
|
658
|
+
return typeof content?.text === "string" ? content.text.trim() : "";
|
|
659
|
+
}
|
|
660
|
+
function isTextGenerationLogRow(type, body) {
|
|
661
|
+
if (!type.startsWith("useModel:")) return false;
|
|
662
|
+
const modelType = typeof body.modelType === "string" && body.modelType.trim().length > 0 ? body.modelType.trim().toUpperCase() : type.slice("useModel:".length).trim().toUpperCase();
|
|
663
|
+
return modelType === "TEXT_SMALL" || modelType === "TEXT_LARGE" || modelType === "TEXT_COMPLETION" || modelType === "REASONING_SMALL" || modelType === "REASONING_LARGE";
|
|
664
|
+
}
|
|
665
|
+
async function maybeBackfillTrajectoryFromUseModelLogs(runtime, traj) {
|
|
666
|
+
if (!needsConversationBackfill(traj)) {
|
|
667
|
+
return traj;
|
|
668
|
+
}
|
|
669
|
+
const metadata = traj.metadata ?? {};
|
|
670
|
+
const messageId = toNullableString(metadata.messageId);
|
|
671
|
+
const roomId = toNullableString(metadata.roomId);
|
|
672
|
+
if (!messageId && !roomId) {
|
|
673
|
+
return traj;
|
|
674
|
+
}
|
|
675
|
+
try {
|
|
676
|
+
const result = await executeRawSql(
|
|
677
|
+
runtime,
|
|
678
|
+
"SELECT type, body, room_id, created_at FROM logs ORDER BY created_at DESC LIMIT 500"
|
|
679
|
+
);
|
|
680
|
+
const rows = extractRows(result);
|
|
681
|
+
if (!Array.isArray(rows) || rows.length === 0) {
|
|
682
|
+
return traj;
|
|
683
|
+
}
|
|
684
|
+
const normalizedRows = rows.map((row) => {
|
|
685
|
+
const record = asRecord(row);
|
|
686
|
+
if (!record) return null;
|
|
687
|
+
const bodyValue = record.body;
|
|
688
|
+
const body = asRecord(bodyValue) ?? (typeof bodyValue === "string" ? asRecord(JSON.parse(bodyValue)) : null);
|
|
689
|
+
if (!body) return null;
|
|
690
|
+
return {
|
|
691
|
+
type: typeof record.type === "string" ? record.type : "",
|
|
692
|
+
roomId: toNullableString(record.room_id),
|
|
693
|
+
createdAt: typeof record.created_at === "string" ? record.created_at : null,
|
|
694
|
+
body
|
|
695
|
+
};
|
|
696
|
+
}).filter((row) => row !== null);
|
|
697
|
+
const runEventCandidates = normalizedRows.filter((row) => {
|
|
698
|
+
if (row.type !== "run_event") return false;
|
|
699
|
+
const body = row.body;
|
|
700
|
+
if (typeof body.runId !== "string" || body.runId.trim().length === 0) {
|
|
701
|
+
return false;
|
|
702
|
+
}
|
|
703
|
+
if (messageId && body.messageId === messageId) {
|
|
704
|
+
return true;
|
|
705
|
+
}
|
|
706
|
+
const loggedRoomId = toNullableString(body.roomId) ?? row.roomId;
|
|
707
|
+
const startTime = toFiniteNumber(body.startTime);
|
|
708
|
+
const endTime = toFiniteNumber(body.endTime) ?? startTime;
|
|
709
|
+
return !!roomId && loggedRoomId === roomId && startTime !== null && endTime !== null && endTime >= traj.startTime - 6e4 && startTime <= (traj.endTime ?? traj.startTime + 12e4) + 6e4;
|
|
710
|
+
});
|
|
711
|
+
if (runEventCandidates.length === 0) {
|
|
712
|
+
return traj;
|
|
713
|
+
}
|
|
714
|
+
runEventCandidates.sort((left, right) => {
|
|
715
|
+
const leftStart = toFiniteNumber(left.body.startTime) ?? 0;
|
|
716
|
+
const rightStart = toFiniteNumber(right.body.startTime) ?? 0;
|
|
717
|
+
return Math.abs(leftStart - traj.startTime) - Math.abs(rightStart - traj.startTime);
|
|
718
|
+
});
|
|
719
|
+
const runId = String(runEventCandidates[0].body.runId);
|
|
720
|
+
const useModelRows = normalizedRows.filter(
|
|
721
|
+
(row) => row.body.runId === runId && isTextGenerationLogRow(row.type, row.body)
|
|
722
|
+
).sort((left, right) => {
|
|
723
|
+
const leftTs = toFiniteNumber(left.body.timestamp) ?? Date.parse(left.createdAt ?? "");
|
|
724
|
+
const rightTs = toFiniteNumber(right.body.timestamp) ?? Date.parse(right.createdAt ?? "");
|
|
725
|
+
return leftTs - rightTs;
|
|
726
|
+
});
|
|
727
|
+
if (useModelRows.length === 0) {
|
|
728
|
+
return traj;
|
|
729
|
+
}
|
|
730
|
+
const baseSteps = traj.steps && traj.steps.length > 0 ? traj.steps.map((step) => ({
|
|
731
|
+
...step,
|
|
732
|
+
llmCalls: []
|
|
733
|
+
})) : [
|
|
734
|
+
{
|
|
735
|
+
stepId: traj.trajectoryId,
|
|
736
|
+
timestamp: traj.startTime,
|
|
737
|
+
llmCalls: [],
|
|
738
|
+
providerAccesses: []
|
|
739
|
+
}
|
|
740
|
+
];
|
|
741
|
+
const firstCallTimestamp = toFiniteNumber(useModelRows[0]?.body.timestamp) ?? traj.startTime;
|
|
742
|
+
baseSteps[0] = {
|
|
743
|
+
...baseSteps[0],
|
|
744
|
+
timestamp: typeof baseSteps[0].timestamp === "number" ? Math.min(baseSteps[0].timestamp, firstCallTimestamp) : firstCallTimestamp,
|
|
745
|
+
llmCalls: useModelRows.map((row, index) => {
|
|
746
|
+
const body = row.body;
|
|
747
|
+
const systemPrompt = typeof body.systemPrompt === "string" ? body.systemPrompt : "";
|
|
748
|
+
const userPrompt = typeof body.prompt === "string" ? body.prompt : "";
|
|
749
|
+
const response = typeof body.response === "string" ? body.response : "";
|
|
750
|
+
const modelKey = typeof body.modelKey === "string" && body.modelKey.trim().length > 0 ? body.modelKey.trim() : row.type.slice("useModel:".length);
|
|
751
|
+
const provider = typeof body.provider === "string" && body.provider.trim().length > 0 ? body.provider.trim() : "";
|
|
752
|
+
const model = provider && modelKey.toUpperCase().startsWith("TEXT_") ? `${provider}/${modelKey}` : modelKey || provider || "unknown";
|
|
753
|
+
return {
|
|
754
|
+
callId: `${traj.trajectoryId}-log-${index + 1}`,
|
|
755
|
+
timestamp: toFiniteNumber(body.timestamp) ?? Date.parse(row.createdAt ?? ""),
|
|
756
|
+
model,
|
|
757
|
+
systemPrompt,
|
|
758
|
+
userPrompt,
|
|
759
|
+
response,
|
|
760
|
+
temperature: toFiniteNumber(body.temperature) ?? 0,
|
|
761
|
+
maxTokens: toFiniteNumber(body.maxTokens) ?? 0,
|
|
762
|
+
purpose: "chat",
|
|
763
|
+
actionType: "runtime.useModel",
|
|
764
|
+
latencyMs: Math.max(
|
|
765
|
+
0,
|
|
766
|
+
Math.round(toFiniteNumber(body.executionTime) ?? 0)
|
|
767
|
+
),
|
|
768
|
+
promptTokens: estimateTokenCount(systemPrompt + userPrompt),
|
|
769
|
+
completionTokens: estimateTokenCount(response)
|
|
770
|
+
};
|
|
771
|
+
})
|
|
772
|
+
};
|
|
773
|
+
const nextMetadata = {
|
|
774
|
+
...metadata,
|
|
775
|
+
llmCallBackfillSource: "logs"
|
|
776
|
+
};
|
|
777
|
+
delete nextMetadata.syntheticLlmCall;
|
|
778
|
+
delete nextMetadata.syntheticLlmCallSource;
|
|
779
|
+
const enriched = {
|
|
780
|
+
...traj,
|
|
781
|
+
steps: baseSteps,
|
|
782
|
+
metadata: nextMetadata
|
|
783
|
+
};
|
|
784
|
+
try {
|
|
785
|
+
await saveTrajectory(runtime, toPersistedTrajectory(enriched));
|
|
786
|
+
} catch {
|
|
787
|
+
}
|
|
788
|
+
return enriched;
|
|
789
|
+
} catch {
|
|
790
|
+
return traj;
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
async function maybeBackfillTrajectoryFromConversationMemory(runtime, traj) {
|
|
794
|
+
const metadata = traj.metadata ?? {};
|
|
795
|
+
const roomId = toNullableString(metadata.roomId);
|
|
796
|
+
if (!roomId) {
|
|
797
|
+
return traj;
|
|
798
|
+
}
|
|
799
|
+
try {
|
|
800
|
+
const memories = await runtime.getMemories({
|
|
801
|
+
roomId,
|
|
802
|
+
tableName: "messages",
|
|
803
|
+
limit: 100
|
|
804
|
+
});
|
|
805
|
+
if (!Array.isArray(memories) || memories.length === 0) {
|
|
806
|
+
return traj;
|
|
807
|
+
}
|
|
808
|
+
const sortedMemories = [...memories].sort(
|
|
809
|
+
(a, b) => Number(a.createdAt ?? 0) - Number(b.createdAt ?? 0)
|
|
810
|
+
);
|
|
811
|
+
const endTime = typeof traj.endTime === "number" ? traj.endTime : traj.startTime + 12e4;
|
|
812
|
+
const userMemory = [...sortedMemories].reverse().find((memory) => {
|
|
813
|
+
const createdAt = Number(memory.createdAt ?? 0);
|
|
814
|
+
if (!Number.isFinite(createdAt)) return false;
|
|
815
|
+
if (createdAt < traj.startTime - 6e4 || createdAt > endTime + 5e3) {
|
|
816
|
+
return false;
|
|
817
|
+
}
|
|
818
|
+
return memory.entityId !== runtime.agentId && extractMessageText(memory).length > 0;
|
|
819
|
+
});
|
|
820
|
+
if (!userMemory) {
|
|
821
|
+
return traj;
|
|
822
|
+
}
|
|
823
|
+
const userCreatedAt = Number(userMemory.createdAt ?? traj.startTime);
|
|
824
|
+
const assistantMemory = sortedMemories.find((memory) => {
|
|
825
|
+
const createdAt = Number(memory.createdAt ?? 0);
|
|
826
|
+
if (!Number.isFinite(createdAt)) return false;
|
|
827
|
+
if (createdAt < userCreatedAt || createdAt > endTime + 3e4) {
|
|
828
|
+
return false;
|
|
829
|
+
}
|
|
830
|
+
return memory.entityId === runtime.agentId && extractMessageText(memory).length > 0;
|
|
831
|
+
});
|
|
832
|
+
if (!assistantMemory) {
|
|
833
|
+
return traj;
|
|
834
|
+
}
|
|
835
|
+
const userPrompt = extractMessageText(userMemory);
|
|
836
|
+
const response = extractMessageText(assistantMemory);
|
|
837
|
+
if (!userPrompt || !response) {
|
|
838
|
+
return traj;
|
|
839
|
+
}
|
|
840
|
+
const normalizedUserPrompt = userPrompt.toLowerCase();
|
|
841
|
+
const normalizedResponse = response.toLowerCase();
|
|
842
|
+
const existingCalls = (traj.steps ?? []).flatMap(
|
|
843
|
+
(step) => step.llmCalls ?? []
|
|
844
|
+
);
|
|
845
|
+
const alreadyCapturedConversation = existingCalls.some((call) => {
|
|
846
|
+
const callPrompt = String(call.userPrompt ?? "").trim().toLowerCase();
|
|
847
|
+
if (callPrompt && (callPrompt.includes(normalizedUserPrompt) || normalizedUserPrompt.includes(callPrompt))) {
|
|
848
|
+
return true;
|
|
849
|
+
}
|
|
850
|
+
const callResponse = String(call.response ?? "").trim().toLowerCase();
|
|
851
|
+
return callResponse.length > 0 && (callResponse.includes(normalizedResponse) || normalizedResponse.includes(callResponse));
|
|
852
|
+
});
|
|
853
|
+
if (alreadyCapturedConversation) {
|
|
854
|
+
return traj;
|
|
855
|
+
}
|
|
856
|
+
const baseSteps = traj.steps && traj.steps.length > 0 ? traj.steps.map((step) => ({
|
|
857
|
+
...step,
|
|
858
|
+
llmCalls: [...step.llmCalls ?? []]
|
|
859
|
+
})) : [
|
|
860
|
+
{
|
|
861
|
+
stepId: traj.trajectoryId,
|
|
862
|
+
timestamp: traj.startTime,
|
|
863
|
+
llmCalls: [],
|
|
864
|
+
providerAccesses: []
|
|
865
|
+
}
|
|
866
|
+
];
|
|
867
|
+
baseSteps[0] = {
|
|
868
|
+
...baseSteps[0],
|
|
869
|
+
timestamp: typeof baseSteps[0].timestamp === "number" ? baseSteps[0].timestamp : userCreatedAt,
|
|
870
|
+
llmCalls: [
|
|
871
|
+
{
|
|
872
|
+
callId: `${traj.trajectoryId}-conversation-memory`,
|
|
873
|
+
timestamp: userCreatedAt,
|
|
874
|
+
model: "eliza/conversation-memory-backfill",
|
|
875
|
+
systemPrompt: "[backfilled from conversation memory because the trajectory logger did not capture the live LLM call]",
|
|
876
|
+
userPrompt,
|
|
877
|
+
response,
|
|
878
|
+
temperature: 0,
|
|
879
|
+
maxTokens: 0,
|
|
880
|
+
purpose: "chat",
|
|
881
|
+
actionType: "conversation-memory-backfill",
|
|
882
|
+
latencyMs: Math.max(
|
|
883
|
+
0,
|
|
884
|
+
Number(assistantMemory.createdAt ?? endTime) - userCreatedAt
|
|
885
|
+
)
|
|
886
|
+
},
|
|
887
|
+
...baseSteps[0].llmCalls ?? []
|
|
888
|
+
]
|
|
889
|
+
};
|
|
890
|
+
const nextMetadata = {
|
|
891
|
+
...metadata,
|
|
892
|
+
llmCallBackfillSource: "conversation-memory"
|
|
893
|
+
};
|
|
894
|
+
delete nextMetadata.syntheticLlmCall;
|
|
895
|
+
delete nextMetadata.syntheticLlmCallSource;
|
|
896
|
+
const enriched = {
|
|
897
|
+
...traj,
|
|
898
|
+
steps: baseSteps,
|
|
899
|
+
metadata: nextMetadata
|
|
900
|
+
};
|
|
901
|
+
try {
|
|
902
|
+
await saveTrajectory(runtime, toPersistedTrajectory(enriched));
|
|
903
|
+
} catch {
|
|
904
|
+
}
|
|
905
|
+
return enriched;
|
|
906
|
+
} catch {
|
|
907
|
+
return traj;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
async function handleGetTrajectories(req, res, runtime) {
|
|
911
|
+
const logger = await getTrajectoryLogger(runtime);
|
|
912
|
+
if (!logger) {
|
|
913
|
+
sendJsonError(res, "Trajectories service not available", 503);
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
916
|
+
const url = new URL(
|
|
917
|
+
req.url ?? "/",
|
|
918
|
+
`http://${req.headers.host ?? "localhost"}`
|
|
919
|
+
);
|
|
920
|
+
const options = {
|
|
921
|
+
limit: Math.min(
|
|
922
|
+
500,
|
|
923
|
+
Math.max(1, Number(url.searchParams.get("limit")) || 50)
|
|
924
|
+
),
|
|
925
|
+
offset: Math.max(0, Number(url.searchParams.get("offset")) || 0),
|
|
926
|
+
source: url.searchParams.get("source") || void 0,
|
|
927
|
+
status: url.searchParams.get("status") || void 0,
|
|
928
|
+
startDate: url.searchParams.get("startDate") || void 0,
|
|
929
|
+
endDate: url.searchParams.get("endDate") || void 0,
|
|
930
|
+
search: url.searchParams.get("search") || void 0,
|
|
931
|
+
scenarioId: url.searchParams.get("scenarioId") || void 0,
|
|
932
|
+
batchId: url.searchParams.get("batchId") || void 0,
|
|
933
|
+
isTrainingData: url.searchParams.has("isTrainingData") ? url.searchParams.get("isTrainingData") === "true" : void 0
|
|
934
|
+
};
|
|
935
|
+
const limit = options.limit ?? 50;
|
|
936
|
+
const offset = options.offset ?? 0;
|
|
937
|
+
const result = await logger.listTrajectories(options);
|
|
938
|
+
const uiResult = {
|
|
939
|
+
trajectories: result.trajectories.map(listItemToUIRecord),
|
|
940
|
+
total: result.total,
|
|
941
|
+
offset,
|
|
942
|
+
limit
|
|
943
|
+
};
|
|
944
|
+
sendJson(res, uiResult);
|
|
945
|
+
}
|
|
946
|
+
async function handleGetTrajectoryDetail(_req, res, runtime, trajectoryId) {
|
|
947
|
+
const logger = await getTrajectoryLogger(runtime);
|
|
948
|
+
if (!logger) {
|
|
949
|
+
sendJsonError(res, "Trajectories service not available", 503);
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
const trajectory = await logger.getTrajectoryDetail(trajectoryId);
|
|
953
|
+
if (!trajectory) {
|
|
954
|
+
sendJsonError(res, `Trajectory "${trajectoryId}" not found`, 404);
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
const uiDetail = trajectoryToUIDetail(
|
|
958
|
+
await maybeBackfillTrajectoryFromConversationMemory(
|
|
959
|
+
runtime,
|
|
960
|
+
await maybeBackfillTrajectoryFromUseModelLogs(runtime, trajectory)
|
|
961
|
+
)
|
|
962
|
+
);
|
|
963
|
+
sendJson(res, uiDetail);
|
|
964
|
+
}
|
|
965
|
+
async function handleGetStats(_req, res, runtime) {
|
|
966
|
+
const logger = await getTrajectoryLogger(runtime);
|
|
967
|
+
if (!logger) {
|
|
968
|
+
sendJsonError(res, "Trajectories service not available", 503);
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
const stats = await logger.getStats();
|
|
972
|
+
sendJson(res, stats);
|
|
973
|
+
}
|
|
974
|
+
async function handleGetConfig(_req, res, runtime) {
|
|
975
|
+
const logger = await getTrajectoryLogger(runtime);
|
|
976
|
+
if (!logger) {
|
|
977
|
+
sendJsonError(res, "Trajectories service not available", 503);
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
sendJson(res, {
|
|
981
|
+
enabled: logger.isEnabled()
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
async function handlePutConfig(req, res, runtime) {
|
|
985
|
+
const logger = await getTrajectoryLogger(runtime);
|
|
986
|
+
if (!logger) {
|
|
987
|
+
sendJsonError(res, "Trajectories service not available", 503);
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
const body = await parseJsonBody(req, res);
|
|
991
|
+
if (!body) return;
|
|
992
|
+
if (typeof body.enabled === "boolean") {
|
|
993
|
+
logger.setEnabled(body.enabled);
|
|
994
|
+
}
|
|
995
|
+
sendJson(res, {
|
|
996
|
+
enabled: logger.isEnabled()
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
async function handleExportTrajectories(req, res, runtime) {
|
|
1000
|
+
const logger = await getTrajectoryLogger(runtime);
|
|
1001
|
+
if (!logger) {
|
|
1002
|
+
sendJsonError(res, "Trajectories service not available", 503);
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
const body = await parseJsonBody(req, res);
|
|
1006
|
+
if (!body) return;
|
|
1007
|
+
if (body.format === "zip") {
|
|
1008
|
+
if (typeof logger.exportTrajectoriesZip !== "function") {
|
|
1009
|
+
sendJsonError(
|
|
1010
|
+
res,
|
|
1011
|
+
"Trajectory ZIP export is unavailable in the active logger",
|
|
1012
|
+
503
|
|
1013
|
+
);
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
const zipOptions = {
|
|
1017
|
+
includePrompts: body.includePrompts,
|
|
1018
|
+
trajectoryIds: body.trajectoryIds,
|
|
1019
|
+
startDate: body.startDate,
|
|
1020
|
+
endDate: body.endDate,
|
|
1021
|
+
scenarioId: body.scenarioId,
|
|
1022
|
+
batchId: body.batchId
|
|
1023
|
+
};
|
|
1024
|
+
const zipResult = await logger.exportTrajectoriesZip(zipOptions);
|
|
1025
|
+
const archive = createZipArchive(zipResult.entries);
|
|
1026
|
+
res.statusCode = 200;
|
|
1027
|
+
res.setHeader("Content-Type", "application/zip");
|
|
1028
|
+
res.setHeader(
|
|
1029
|
+
"Content-Disposition",
|
|
1030
|
+
`attachment; filename="${zipResult.filename}"`
|
|
1031
|
+
);
|
|
1032
|
+
res.end(archive);
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
if (body.format !== "json" && body.format !== "jsonl" && body.format !== "csv" && body.format !== "art") {
|
|
1036
|
+
sendJsonError(
|
|
1037
|
+
res,
|
|
1038
|
+
"Format must be 'json', 'jsonl', 'csv', 'art', or 'zip'",
|
|
1039
|
+
400
|
|
1040
|
+
);
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
const jsonShape = body.jsonShape === ELIZA_NATIVE_TRAJECTORY_FORMAT ? body.jsonShape : void 0;
|
|
1044
|
+
if (body.jsonShape !== void 0 && !jsonShape) {
|
|
1045
|
+
sendJsonError(res, "jsonShape must be 'eliza_native_v1'", 400);
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
const result = await logger.exportTrajectories({
|
|
1049
|
+
format: body.format,
|
|
1050
|
+
includePrompts: body.includePrompts,
|
|
1051
|
+
trajectoryIds: body.trajectoryIds,
|
|
1052
|
+
startDate: body.startDate,
|
|
1053
|
+
endDate: body.endDate,
|
|
1054
|
+
scenarioId: body.scenarioId,
|
|
1055
|
+
batchId: body.batchId,
|
|
1056
|
+
...(body.format === "json" || body.format === "jsonl") && jsonShape ? { jsonShape } : {}
|
|
1057
|
+
});
|
|
1058
|
+
res.statusCode = 200;
|
|
1059
|
+
res.setHeader("Content-Type", result.mimeType);
|
|
1060
|
+
res.setHeader(
|
|
1061
|
+
"Content-Disposition",
|
|
1062
|
+
`attachment; filename="${result.filename}"`
|
|
1063
|
+
);
|
|
1064
|
+
res.end(result.data);
|
|
1065
|
+
}
|
|
1066
|
+
async function handleDeleteTrajectories(req, res, runtime) {
|
|
1067
|
+
const logger = await getTrajectoryLogger(runtime);
|
|
1068
|
+
if (!logger) {
|
|
1069
|
+
sendJsonError(res, "Trajectories service not available", 503);
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
const body = await parseJsonBody(req, res);
|
|
1073
|
+
if (!body) return;
|
|
1074
|
+
if (body.clearAll || body.all) {
|
|
1075
|
+
const deletedCount = await logger.clearAllTrajectories();
|
|
1076
|
+
sendJson(res, { deleted: deletedCount });
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
if (Array.isArray(body.trajectoryIds) && body.trajectoryIds.length > 0) {
|
|
1080
|
+
const deletedCount = await logger.deleteTrajectories(body.trajectoryIds);
|
|
1081
|
+
sendJson(res, { deleted: deletedCount });
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
1084
|
+
sendJson(res, { deleted: 0 });
|
|
1085
|
+
}
|
|
1086
|
+
async function handleTrajectoryRoute(req, res, runtime, pathname, method) {
|
|
1087
|
+
if (!pathname.startsWith("/api/trajectories")) return false;
|
|
1088
|
+
if (pathname === "/api/trajectories/config" && method === "GET") {
|
|
1089
|
+
await handleGetConfig(req, res, runtime);
|
|
1090
|
+
return true;
|
|
1091
|
+
}
|
|
1092
|
+
if (pathname === "/api/trajectories/config" && method === "PUT") {
|
|
1093
|
+
await handlePutConfig(req, res, runtime);
|
|
1094
|
+
return true;
|
|
1095
|
+
}
|
|
1096
|
+
if (pathname === "/api/trajectories/export" && method === "POST") {
|
|
1097
|
+
await handleExportTrajectories(req, res, runtime);
|
|
1098
|
+
return true;
|
|
1099
|
+
}
|
|
1100
|
+
if (pathname === "/api/trajectories" && method === "DELETE") {
|
|
1101
|
+
await handleDeleteTrajectories(req, res, runtime);
|
|
1102
|
+
return true;
|
|
1103
|
+
}
|
|
1104
|
+
if (pathname === "/api/trajectories/stats" && method === "GET") {
|
|
1105
|
+
await handleGetStats(req, res, runtime);
|
|
1106
|
+
return true;
|
|
1107
|
+
}
|
|
1108
|
+
const detailMatch = pathname.match(/^\/api\/trajectories\/([^/]+)$/);
|
|
1109
|
+
if (detailMatch && method === "GET") {
|
|
1110
|
+
await handleGetTrajectoryDetail(req, res, runtime, detailMatch[1]);
|
|
1111
|
+
return true;
|
|
1112
|
+
}
|
|
1113
|
+
if (pathname === "/api/trajectories" && method === "GET") {
|
|
1114
|
+
await handleGetTrajectories(req, res, runtime);
|
|
1115
|
+
return true;
|
|
1116
|
+
}
|
|
1117
|
+
return false;
|
|
1118
|
+
}
|
|
1119
|
+
export {
|
|
1120
|
+
handleTrajectoryRoute
|
|
1121
|
+
};
|
|
1122
|
+
//# sourceMappingURL=trajectory-routes.js.map
|