@elizaos/plugin-training 2.0.3-beta.5 → 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,1239 @@
|
|
|
1
|
+
import { parsePositiveInteger } from "@elizaos/shared";
|
|
2
|
+
import { runActionBenchmark } from "../core/action-benchmark-runner.js";
|
|
3
|
+
import {
|
|
4
|
+
writeBenchmarkMatrixArtifact,
|
|
5
|
+
writeBenchmarkMatrixArtifactFromArtifacts
|
|
6
|
+
} from "../core/benchmark-matrix-artifact.js";
|
|
7
|
+
import { runBenchmarkVsCerebras } from "../core/benchmark-vs-cerebras-runner.js";
|
|
8
|
+
import { AGENT_CONTEXTS } from "../core/context-types.js";
|
|
9
|
+
import { stageEliza1Bundle } from "../core/eliza1-bundle-stager.js";
|
|
10
|
+
import {
|
|
11
|
+
runLocalEvalComparison,
|
|
12
|
+
writeEvalComparisonArtifact
|
|
13
|
+
} from "../core/eval-comparison-artifact.js";
|
|
14
|
+
import { runFeedGeneration } from "../core/feed-generation-runner.js";
|
|
15
|
+
import { ingestHuggingFaceDataset } from "../core/huggingface-dataset-ingest.js";
|
|
16
|
+
import { createHashAnonymizer } from "../core/privacy-filter.js";
|
|
17
|
+
import { runScenarios } from "../core/scenario-runner.js";
|
|
18
|
+
import { buildTrainingAnalysisIndex } from "../core/training-analysis-index.js";
|
|
19
|
+
import {
|
|
20
|
+
buildTrainingCollectionPreflightWithProbes,
|
|
21
|
+
listTrainingCollections,
|
|
22
|
+
runTrainingCollection
|
|
23
|
+
} from "../core/training-collection-runner.js";
|
|
24
|
+
import {
|
|
25
|
+
ALL_TRAINING_BACKENDS,
|
|
26
|
+
ALL_TRAINING_TASKS,
|
|
27
|
+
loadTrainingConfig,
|
|
28
|
+
normalizeTrainingConfig,
|
|
29
|
+
saveTrainingConfig
|
|
30
|
+
} from "../core/training-config.js";
|
|
31
|
+
import {
|
|
32
|
+
listRuns,
|
|
33
|
+
loadRun,
|
|
34
|
+
triggerTraining
|
|
35
|
+
} from "../core/training-orchestrator.js";
|
|
36
|
+
import { writeTrainingReadinessReport } from "../core/training-readiness-report.js";
|
|
37
|
+
import { resolveHfUploadConfig } from "../core/trajectory-hf-upload.js";
|
|
38
|
+
import {
|
|
39
|
+
buildTaskRecord
|
|
40
|
+
} from "../core/trajectory-task-datasets.js";
|
|
41
|
+
import { detectAvailableBackends } from "../services/training-backend-check.js";
|
|
42
|
+
import { isNotImplementedError } from "../services/training-service.js";
|
|
43
|
+
import {
|
|
44
|
+
TRAINING_TRIGGER_SERVICE
|
|
45
|
+
} from "../services/training-trigger.js";
|
|
46
|
+
function resolveStringSetting(value) {
|
|
47
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
48
|
+
}
|
|
49
|
+
function resolveBooleanSetting(value) {
|
|
50
|
+
return typeof value === "boolean" ? value : void 0;
|
|
51
|
+
}
|
|
52
|
+
function sendServiceError(error, res, err, status = 400) {
|
|
53
|
+
if (isNotImplementedError(err)) {
|
|
54
|
+
error(res, err.message, 501);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
error(res, String(err), status);
|
|
58
|
+
}
|
|
59
|
+
function emptyTaskCounters() {
|
|
60
|
+
return buildTaskRecord(() => 0);
|
|
61
|
+
}
|
|
62
|
+
function getTriggerEntry(runtime) {
|
|
63
|
+
if (!runtime) return null;
|
|
64
|
+
const services = runtime.services;
|
|
65
|
+
if (!services) return null;
|
|
66
|
+
const entries = services.get(TRAINING_TRIGGER_SERVICE);
|
|
67
|
+
if (!Array.isArray(entries) || entries.length === 0) return null;
|
|
68
|
+
const candidate = entries[0];
|
|
69
|
+
if (candidate && typeof candidate === "object" && typeof candidate.notifyTrajectoryCompleted === "function") {
|
|
70
|
+
return candidate;
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const AGENT_DECISIONS = ["RESPOND", "IGNORE", "STOP"];
|
|
75
|
+
function narrowAgentContexts(input) {
|
|
76
|
+
if (!Array.isArray(input)) return void 0;
|
|
77
|
+
const out = [];
|
|
78
|
+
for (const entry of input) {
|
|
79
|
+
if (typeof entry === "string" && AGENT_CONTEXTS.includes(entry)) {
|
|
80
|
+
out.push(entry);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return out.length > 0 ? out : void 0;
|
|
84
|
+
}
|
|
85
|
+
function narrowAgentDecisions(input) {
|
|
86
|
+
if (!Array.isArray(input)) return void 0;
|
|
87
|
+
const out = [];
|
|
88
|
+
for (const entry of input) {
|
|
89
|
+
if (typeof entry === "string" && AGENT_DECISIONS.includes(entry)) {
|
|
90
|
+
out.push(entry);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return out.length > 0 ? out : void 0;
|
|
94
|
+
}
|
|
95
|
+
function narrowTrainingTasks(input) {
|
|
96
|
+
if (!Array.isArray(input)) return void 0;
|
|
97
|
+
const out = [];
|
|
98
|
+
for (const entry of input) {
|
|
99
|
+
if (typeof entry === "string" && ALL_TRAINING_TASKS.includes(entry)) {
|
|
100
|
+
out.push(entry);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return out.length > 0 ? out : void 0;
|
|
104
|
+
}
|
|
105
|
+
function normalizeRunId(input) {
|
|
106
|
+
return typeof input === "string" && input.trim().length > 0 ? input.trim() : void 0;
|
|
107
|
+
}
|
|
108
|
+
function trajectoryHasRunId(trajectory, runId) {
|
|
109
|
+
const record = trajectory;
|
|
110
|
+
if (normalizeRunId(record.runId) === runId) return true;
|
|
111
|
+
if (normalizeRunId(record.metadata?.runId) === runId) return true;
|
|
112
|
+
if (normalizeRunId(record.metadata?.appRunId) === runId) return true;
|
|
113
|
+
for (const step of trajectory.steps ?? []) {
|
|
114
|
+
for (const call of step.llmCalls ?? []) {
|
|
115
|
+
if (normalizeRunId(call.runId) === runId) return true;
|
|
116
|
+
}
|
|
117
|
+
for (const access of step.providerAccesses ?? []) {
|
|
118
|
+
if (normalizeRunId(access.runId) === runId) return true;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
function parseTaskOrNull(input) {
|
|
124
|
+
if (input === void 0 || input === null || input === "") return {};
|
|
125
|
+
if (typeof input !== "string") {
|
|
126
|
+
return { error: "task must be a string" };
|
|
127
|
+
}
|
|
128
|
+
if (!ALL_TRAINING_TASKS.includes(input)) {
|
|
129
|
+
return {
|
|
130
|
+
error: `task must be one of: ${ALL_TRAINING_TASKS.join(", ")}`
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return { value: input };
|
|
134
|
+
}
|
|
135
|
+
function parseBackendOrNull(input) {
|
|
136
|
+
if (input === void 0 || input === null || input === "") return {};
|
|
137
|
+
if (typeof input !== "string") {
|
|
138
|
+
return { error: "backend must be a string" };
|
|
139
|
+
}
|
|
140
|
+
if (!ALL_TRAINING_BACKENDS.includes(input)) {
|
|
141
|
+
return {
|
|
142
|
+
error: `backend must be one of: ${ALL_TRAINING_BACKENDS.join(", ")}`
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return { value: input };
|
|
146
|
+
}
|
|
147
|
+
function resolveOllamaUrlRejection(rawUrl, isLoopbackHost) {
|
|
148
|
+
const trimmed = rawUrl.trim();
|
|
149
|
+
if (!trimmed) return null;
|
|
150
|
+
let parsed;
|
|
151
|
+
try {
|
|
152
|
+
parsed = new URL(trimmed);
|
|
153
|
+
} catch {
|
|
154
|
+
return "ollamaUrl must be a valid URL";
|
|
155
|
+
}
|
|
156
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
157
|
+
return "ollamaUrl must use http:// or https://";
|
|
158
|
+
}
|
|
159
|
+
if (!isLoopbackHost(parsed.hostname)) {
|
|
160
|
+
return "ollamaUrl must target a loopback host (localhost, 127.0.0.1, or ::1)";
|
|
161
|
+
}
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
async function handleTrainingRoutes(ctx) {
|
|
165
|
+
const {
|
|
166
|
+
req,
|
|
167
|
+
res,
|
|
168
|
+
method,
|
|
169
|
+
pathname,
|
|
170
|
+
runtime,
|
|
171
|
+
trainingService,
|
|
172
|
+
json,
|
|
173
|
+
error,
|
|
174
|
+
readJsonBody,
|
|
175
|
+
isLoopbackHost
|
|
176
|
+
} = ctx;
|
|
177
|
+
if (!pathname.startsWith("/api/training")) return false;
|
|
178
|
+
if (method === "GET" && pathname === "/api/training/status") {
|
|
179
|
+
const status = trainingService.getStatus();
|
|
180
|
+
const trigger = getTriggerEntry(runtime);
|
|
181
|
+
const triggerStatus = trigger?.getStatus() ?? null;
|
|
182
|
+
json(res, {
|
|
183
|
+
...status,
|
|
184
|
+
runtimeAvailable: runtime !== null,
|
|
185
|
+
autoTrain: triggerStatus
|
|
186
|
+
});
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
if (method === "GET" && pathname === "/api/training/auto/status") {
|
|
190
|
+
const trigger = getTriggerEntry(runtime);
|
|
191
|
+
if (!trigger) {
|
|
192
|
+
const config = loadTrainingConfig();
|
|
193
|
+
json(res, {
|
|
194
|
+
autoTrainEnabled: config.autoTrain,
|
|
195
|
+
triggerThreshold: config.triggerThreshold,
|
|
196
|
+
cooldownHours: config.triggerCooldownHours,
|
|
197
|
+
counters: emptyTaskCounters(),
|
|
198
|
+
lastTrain: {},
|
|
199
|
+
perTaskThresholds: emptyTaskCounters(),
|
|
200
|
+
perTaskCooldownMs: emptyTaskCounters(),
|
|
201
|
+
serviceRegistered: false
|
|
202
|
+
});
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
const snapshot = trigger.getStatus();
|
|
206
|
+
json(res, { ...snapshot, serviceRegistered: true });
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
if (method === "POST" && pathname === "/api/training/auto/trigger") {
|
|
210
|
+
const body = await readJsonBody(req, res);
|
|
211
|
+
if (!body) return true;
|
|
212
|
+
const taskRejection = parseTaskOrNull(body.task);
|
|
213
|
+
if (taskRejection.error) {
|
|
214
|
+
error(res, taskRejection.error, 400);
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
const backendRejection = parseBackendOrNull(body.backend);
|
|
218
|
+
if (backendRejection.error) {
|
|
219
|
+
error(res, backendRejection.error, 400);
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
if (!runtime) {
|
|
223
|
+
error(res, "Runtime is required to trigger training", 503);
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
const trigger = getTriggerEntry(runtime);
|
|
227
|
+
const record = trigger ? await trigger.runManually({
|
|
228
|
+
task: taskRejection.value,
|
|
229
|
+
backend: backendRejection.value,
|
|
230
|
+
dryRun: body.dryRun === true
|
|
231
|
+
}) : await triggerTraining(runtime, {
|
|
232
|
+
task: taskRejection.value,
|
|
233
|
+
backend: backendRejection.value,
|
|
234
|
+
source: "manual",
|
|
235
|
+
dryRun: body.dryRun === true
|
|
236
|
+
});
|
|
237
|
+
json(res, { runId: record.runId, status: record.status, run: record }, 201);
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
if (method === "GET" && pathname === "/api/training/auto/runs") {
|
|
241
|
+
const url = new URL(
|
|
242
|
+
req.url ?? "/",
|
|
243
|
+
`http://${req.headers.host ?? "localhost"}`
|
|
244
|
+
);
|
|
245
|
+
const limit = parsePositiveInteger(url.searchParams.get("limit"), 20);
|
|
246
|
+
const runs = await listRuns(limit);
|
|
247
|
+
json(res, { runs });
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
const runMatch = /^\/api\/training\/auto\/runs\/([^/]+)$/.exec(pathname);
|
|
251
|
+
if (method === "GET" && runMatch) {
|
|
252
|
+
const runId = decodeURIComponent(runMatch[1]);
|
|
253
|
+
const run = await loadRun(runId);
|
|
254
|
+
if (!run) {
|
|
255
|
+
error(res, "Run not found", 404);
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
json(res, { run });
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
if (method === "GET" && pathname === "/api/training/auto/config") {
|
|
262
|
+
json(res, { config: loadTrainingConfig() });
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
if (method === "POST" && pathname === "/api/training/auto/config") {
|
|
266
|
+
const body = await readJsonBody(req, res);
|
|
267
|
+
if (!body) return true;
|
|
268
|
+
const merged = normalizeTrainingConfig({
|
|
269
|
+
...loadTrainingConfig(),
|
|
270
|
+
...body
|
|
271
|
+
});
|
|
272
|
+
saveTrainingConfig(merged);
|
|
273
|
+
json(res, { config: merged });
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
if (method === "POST" && pathname === "/api/training/analysis/index") {
|
|
277
|
+
const body = await readJsonBody(req, res);
|
|
278
|
+
if (!body) return true;
|
|
279
|
+
const roots = Array.isArray(body.roots) ? body.roots.filter(
|
|
280
|
+
(root) => typeof root === "string" && root.trim().length > 0
|
|
281
|
+
) : void 0;
|
|
282
|
+
const outputDir = typeof body.outputDir === "string" && body.outputDir.trim().length > 0 ? body.outputDir.trim() : void 0;
|
|
283
|
+
const maxDepth = typeof body.maxDepth === "number" && Number.isFinite(body.maxDepth) ? Math.max(0, Math.floor(body.maxDepth)) : void 0;
|
|
284
|
+
try {
|
|
285
|
+
const index = await buildTrainingAnalysisIndex({
|
|
286
|
+
roots,
|
|
287
|
+
outputDir,
|
|
288
|
+
maxDepth
|
|
289
|
+
});
|
|
290
|
+
json(
|
|
291
|
+
res,
|
|
292
|
+
{
|
|
293
|
+
outputDir: index.outputDir,
|
|
294
|
+
indexHtmlPath: index.indexHtmlPath,
|
|
295
|
+
manifestPath: index.manifestPath,
|
|
296
|
+
manifest: index.manifest
|
|
297
|
+
},
|
|
298
|
+
201
|
|
299
|
+
);
|
|
300
|
+
} catch (err) {
|
|
301
|
+
error(res, `Training analysis index failed: ${String(err)}`, 500);
|
|
302
|
+
}
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
if (method === "POST" && pathname === "/api/training/analysis/readiness") {
|
|
306
|
+
const body = await readJsonBody(req, res);
|
|
307
|
+
if (!body) return true;
|
|
308
|
+
const roots = Array.isArray(body.roots) ? body.roots.filter(
|
|
309
|
+
(entry) => typeof entry === "string" && entry.trim().length > 0
|
|
310
|
+
) : void 0;
|
|
311
|
+
try {
|
|
312
|
+
const index = await buildTrainingAnalysisIndex({
|
|
313
|
+
roots,
|
|
314
|
+
outputDir: resolveStringSetting(body.outputDir),
|
|
315
|
+
maxDepth: typeof body.maxDepth === "number" && Number.isFinite(body.maxDepth) ? Math.max(1, Math.floor(body.maxDepth)) : void 0
|
|
316
|
+
});
|
|
317
|
+
const result = await writeTrainingReadinessReport(index, {
|
|
318
|
+
outputDir: resolveStringSetting(body.reportOutputDir),
|
|
319
|
+
reportPath: resolveStringSetting(body.reportPath)
|
|
320
|
+
});
|
|
321
|
+
json(res, result, 201);
|
|
322
|
+
} catch (err) {
|
|
323
|
+
error(res, `Training readiness report failed: ${String(err)}`, 500);
|
|
324
|
+
}
|
|
325
|
+
return true;
|
|
326
|
+
}
|
|
327
|
+
if (method === "POST" && pathname === "/api/training/datasets/ingest-hf") {
|
|
328
|
+
const body = await readJsonBody(req, res);
|
|
329
|
+
if (!body) return true;
|
|
330
|
+
try {
|
|
331
|
+
const result = await ingestHuggingFaceDataset({
|
|
332
|
+
repoId: resolveStringSetting(body.repoId),
|
|
333
|
+
revision: resolveStringSetting(body.revision),
|
|
334
|
+
files: Array.isArray(body.files) ? body.files.filter(
|
|
335
|
+
(file) => typeof file === "string" && file.trim().length > 0
|
|
336
|
+
) : void 0,
|
|
337
|
+
outputDir: resolveStringSetting(body.outputDir),
|
|
338
|
+
token: resolveStringSetting(body.token),
|
|
339
|
+
dryRun: body.dryRun === true
|
|
340
|
+
});
|
|
341
|
+
json(res, result, 201);
|
|
342
|
+
} catch (err) {
|
|
343
|
+
error(res, `Hugging Face dataset ingest failed: ${String(err)}`, 500);
|
|
344
|
+
}
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
if (method === "POST" && pathname === "/api/training/feed/generate") {
|
|
348
|
+
const body = await readJsonBody(req, res);
|
|
349
|
+
if (!body) return true;
|
|
350
|
+
try {
|
|
351
|
+
const result = await runFeedGeneration({
|
|
352
|
+
workspaceRoot: resolveStringSetting(body.workspaceRoot),
|
|
353
|
+
bun: resolveStringSetting(body.bun),
|
|
354
|
+
archetypes: resolveStringSetting(body.archetypes),
|
|
355
|
+
numAgents: typeof body.numAgents === "number" && Number.isFinite(body.numAgents) ? Math.max(1, Math.floor(body.numAgents)) : void 0,
|
|
356
|
+
ticks: typeof body.ticks === "number" && Number.isFinite(body.ticks) ? Math.max(1, Math.floor(body.ticks)) : void 0,
|
|
357
|
+
parallel: typeof body.parallel === "number" && Number.isFinite(body.parallel) ? Math.max(1, Math.floor(body.parallel)) : void 0,
|
|
358
|
+
managerId: resolveStringSetting(body.managerId),
|
|
359
|
+
cleanup: body.cleanup === true,
|
|
360
|
+
dryRun: body.dryRun === true,
|
|
361
|
+
outputDir: resolveStringSetting(body.outputDir)
|
|
362
|
+
});
|
|
363
|
+
json(res, result, 201);
|
|
364
|
+
} catch (err) {
|
|
365
|
+
error(res, `Feed generation failed: ${String(err)}`, 500);
|
|
366
|
+
}
|
|
367
|
+
return true;
|
|
368
|
+
}
|
|
369
|
+
if (method === "POST" && pathname === "/api/training/scenarios/run") {
|
|
370
|
+
const body = await readJsonBody(req, res);
|
|
371
|
+
if (!body) return true;
|
|
372
|
+
try {
|
|
373
|
+
const result = await runScenarios({
|
|
374
|
+
workspaceRoot: resolveStringSetting(body.workspaceRoot),
|
|
375
|
+
bun: resolveStringSetting(body.bun),
|
|
376
|
+
scenarioDir: resolveStringSetting(body.scenarioDir),
|
|
377
|
+
outputDir: resolveStringSetting(body.outputDir),
|
|
378
|
+
runId: resolveStringSetting(body.runId),
|
|
379
|
+
scenario: resolveStringSetting(body.scenario),
|
|
380
|
+
fileGlobs: Array.isArray(body.fileGlobs) ? body.fileGlobs.filter(
|
|
381
|
+
(glob) => typeof glob === "string"
|
|
382
|
+
) : void 0,
|
|
383
|
+
exportNative: typeof body.exportNative === "boolean" ? body.exportNative : void 0,
|
|
384
|
+
useDeterministicProxy: typeof body.useDeterministicProxy === "boolean" ? body.useDeterministicProxy : void 0,
|
|
385
|
+
dryRun: body.dryRun === true
|
|
386
|
+
});
|
|
387
|
+
json(res, result, 201);
|
|
388
|
+
} catch (err) {
|
|
389
|
+
error(res, `Scenario run failed: ${String(err)}`, 500);
|
|
390
|
+
}
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
if (method === "GET" && pathname === "/api/training/collections") {
|
|
394
|
+
const url = new URL(
|
|
395
|
+
req.url ?? "/",
|
|
396
|
+
`http://${req.headers.host ?? "localhost"}`
|
|
397
|
+
);
|
|
398
|
+
const limit = parsePositiveInteger(url.searchParams.get("limit"), 20);
|
|
399
|
+
const root = resolveStringSetting(url.searchParams.get("root"));
|
|
400
|
+
try {
|
|
401
|
+
const result = await listTrainingCollections({ root, limit });
|
|
402
|
+
json(res, result);
|
|
403
|
+
} catch (err) {
|
|
404
|
+
error(res, `Training collection listing failed: ${String(err)}`, 500);
|
|
405
|
+
}
|
|
406
|
+
return true;
|
|
407
|
+
}
|
|
408
|
+
if (method === "POST" && pathname === "/api/training/collect") {
|
|
409
|
+
const body = await readJsonBody(req, res);
|
|
410
|
+
if (!body) return true;
|
|
411
|
+
const objectSetting = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
412
|
+
const objectArraySetting = (value) => Array.isArray(value) ? value.filter(
|
|
413
|
+
(item) => item !== null && typeof item === "object" && !Array.isArray(item)
|
|
414
|
+
) : void 0;
|
|
415
|
+
const actionBenchmarkPairsSetting = (value) => typeof value === "string" ? value : objectArraySetting(value);
|
|
416
|
+
const naturalTrajectoryOptions = objectSetting(body.naturalTrajectories);
|
|
417
|
+
const naturalTrajectoryIds = Array.isArray(
|
|
418
|
+
naturalTrajectoryOptions?.trajectoryIds
|
|
419
|
+
) ? naturalTrajectoryOptions.trajectoryIds.filter(
|
|
420
|
+
(id) => typeof id === "string" && id.trim().length > 0
|
|
421
|
+
) : [];
|
|
422
|
+
const naturalRunId = resolveStringSetting(naturalTrajectoryOptions?.runId);
|
|
423
|
+
const naturalLimit = typeof naturalTrajectoryOptions?.limit === "number" && Number.isFinite(naturalTrajectoryOptions.limit) ? Math.max(1, Math.floor(naturalTrajectoryOptions.limit)) : 100;
|
|
424
|
+
try {
|
|
425
|
+
let naturalTrajectories = naturalTrajectoryOptions;
|
|
426
|
+
if (body.includeNaturalTrajectories === true && body.preflightOnly !== true && !naturalTrajectoryOptions?.sanitizedJsonlPath && !naturalTrajectoryOptions?.rawJsonlPath) {
|
|
427
|
+
const listedTrajectories = naturalTrajectoryIds.length > 0 ? null : await trainingService.listTrajectories({
|
|
428
|
+
limit: naturalLimit,
|
|
429
|
+
offset: 0,
|
|
430
|
+
runId: naturalRunId
|
|
431
|
+
});
|
|
432
|
+
const ids = naturalTrajectoryIds.length > 0 ? naturalTrajectoryIds : (listedTrajectories?.trajectories ?? []).map((item) => item.id).filter((id) => id.length > 0);
|
|
433
|
+
const details = (await Promise.all(
|
|
434
|
+
ids.map(
|
|
435
|
+
(trajectoryId) => trainingService.getTrajectoryById(trajectoryId)
|
|
436
|
+
)
|
|
437
|
+
)).filter((trajectory) => trajectory !== null);
|
|
438
|
+
naturalTrajectories = {
|
|
439
|
+
...naturalTrajectoryOptions ?? {},
|
|
440
|
+
trajectories: naturalRunId ? details.filter(
|
|
441
|
+
(trajectory) => trajectoryHasRunId(trajectory, naturalRunId)
|
|
442
|
+
) : details,
|
|
443
|
+
source: {
|
|
444
|
+
kind: "training_collection_natural_trajectories",
|
|
445
|
+
...objectSetting(naturalTrajectoryOptions?.source),
|
|
446
|
+
runId: naturalRunId,
|
|
447
|
+
metadata: {
|
|
448
|
+
...objectSetting(
|
|
449
|
+
objectSetting(naturalTrajectoryOptions?.source)?.metadata
|
|
450
|
+
),
|
|
451
|
+
requestedLimit: naturalLimit,
|
|
452
|
+
requestedRunId: naturalRunId ?? null,
|
|
453
|
+
explicitTrajectoryIds: naturalTrajectoryIds.length,
|
|
454
|
+
selectedTrajectoryIds: ids.length,
|
|
455
|
+
loadedTrajectories: details.length
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
const collectionOptions = {
|
|
461
|
+
preflightOnly: body.preflightOnly === true,
|
|
462
|
+
preflightProbe: body.preflightProbe === true,
|
|
463
|
+
outputDir: resolveStringSetting(body.outputDir),
|
|
464
|
+
workspaceRoot: resolveStringSetting(body.workspaceRoot),
|
|
465
|
+
includeHuggingFace: typeof body.includeHuggingFace === "boolean" ? body.includeHuggingFace : void 0,
|
|
466
|
+
includeFeed: typeof body.includeFeed === "boolean" ? body.includeFeed : void 0,
|
|
467
|
+
includeNaturalTrajectories: typeof body.includeNaturalTrajectories === "boolean" ? body.includeNaturalTrajectories : void 0,
|
|
468
|
+
includeTestTrajectories: typeof body.includeTestTrajectories === "boolean" ? body.includeTestTrajectories : void 0,
|
|
469
|
+
includeScenarios: typeof body.includeScenarios === "boolean" ? body.includeScenarios : void 0,
|
|
470
|
+
includeEvalComparison: typeof body.includeEvalComparison === "boolean" ? body.includeEvalComparison : void 0,
|
|
471
|
+
includeActionBenchmark: typeof body.includeActionBenchmark === "boolean" ? body.includeActionBenchmark : void 0,
|
|
472
|
+
includeBenchmarkVsCerebras: typeof body.includeBenchmarkVsCerebras === "boolean" ? body.includeBenchmarkVsCerebras : void 0,
|
|
473
|
+
includeEliza1ModelRegistry: typeof body.includeEliza1ModelRegistry === "boolean" ? body.includeEliza1ModelRegistry : void 0,
|
|
474
|
+
includeEliza1BundleStage: typeof body.includeEliza1BundleStage === "boolean" ? body.includeEliza1BundleStage : void 0,
|
|
475
|
+
includeBenchmarkMatrix: typeof body.includeBenchmarkMatrix === "boolean" ? body.includeBenchmarkMatrix : void 0,
|
|
476
|
+
huggingFace: objectSetting(body.huggingFace),
|
|
477
|
+
feed: objectSetting(body.feed),
|
|
478
|
+
naturalTrajectories,
|
|
479
|
+
testTrajectories: objectSetting(body.testTrajectories),
|
|
480
|
+
scenarios: objectSetting(body.scenarios),
|
|
481
|
+
evalComparison: objectSetting(body.evalComparison),
|
|
482
|
+
actionBenchmark: objectSetting(body.actionBenchmark),
|
|
483
|
+
actionBenchmarkPair: objectSetting(body.actionBenchmarkPair),
|
|
484
|
+
actionBenchmarkPairs: actionBenchmarkPairsSetting(
|
|
485
|
+
body.actionBenchmarkPairs
|
|
486
|
+
),
|
|
487
|
+
benchmarkVsCerebras: objectSetting(body.benchmarkVsCerebras),
|
|
488
|
+
eliza1BundleStage: objectSetting(body.eliza1BundleStage),
|
|
489
|
+
benchmarkMatrix: objectSetting(body.benchmarkMatrix),
|
|
490
|
+
analysis: objectSetting(body.analysis)
|
|
491
|
+
};
|
|
492
|
+
if (body.preflightOnly === true) {
|
|
493
|
+
json(
|
|
494
|
+
res,
|
|
495
|
+
{
|
|
496
|
+
preflight: await buildTrainingCollectionPreflightWithProbes({
|
|
497
|
+
options: collectionOptions,
|
|
498
|
+
workspaceRoot: collectionOptions.workspaceRoot,
|
|
499
|
+
trainingRoot: collectionOptions.workspaceRoot ? `${collectionOptions.workspaceRoot}/packages/training` : void 0
|
|
500
|
+
})
|
|
501
|
+
},
|
|
502
|
+
200
|
|
503
|
+
);
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
506
|
+
const result = await runTrainingCollection(collectionOptions);
|
|
507
|
+
json(res, result, 201);
|
|
508
|
+
} catch (err) {
|
|
509
|
+
error(res, `Training collection failed: ${String(err)}`, 500);
|
|
510
|
+
}
|
|
511
|
+
return true;
|
|
512
|
+
}
|
|
513
|
+
if (method === "POST" && pathname === "/api/training/benchmarks/action-selection/run") {
|
|
514
|
+
const body = await readJsonBody(req, res);
|
|
515
|
+
if (!body) return true;
|
|
516
|
+
try {
|
|
517
|
+
const result = await runActionBenchmark({
|
|
518
|
+
workspaceRoot: resolveStringSetting(body.workspaceRoot),
|
|
519
|
+
bun: resolveStringSetting(body.bun),
|
|
520
|
+
outputDir: resolveStringSetting(body.outputDir),
|
|
521
|
+
useMocks: resolveBooleanSetting(body.useMocks),
|
|
522
|
+
forceTrajectoryCapture: body.forceTrajectoryCapture === false ? false : void 0,
|
|
523
|
+
filter: resolveStringSetting(body.filter),
|
|
524
|
+
runsPerCase: typeof body.runsPerCase === "number" && Number.isFinite(body.runsPerCase) ? Math.max(1, Math.floor(body.runsPerCase)) : void 0,
|
|
525
|
+
provider: resolveStringSetting(body.provider),
|
|
526
|
+
modelId: resolveStringSetting(body.modelId),
|
|
527
|
+
runtimeModel: resolveStringSetting(body.runtimeModel),
|
|
528
|
+
smallModel: resolveStringSetting(body.smallModel),
|
|
529
|
+
largeModel: resolveStringSetting(body.largeModel),
|
|
530
|
+
baseUrl: resolveStringSetting(body.baseUrl),
|
|
531
|
+
variant: body.variant === "reference" || body.variant === "base" || body.variant === "trained" ? body.variant : void 0,
|
|
532
|
+
tier: resolveStringSetting(body.tier),
|
|
533
|
+
benchmark: resolveStringSetting(body.benchmark),
|
|
534
|
+
datasetVersion: resolveStringSetting(body.datasetVersion),
|
|
535
|
+
codeCommit: resolveStringSetting(body.codeCommit),
|
|
536
|
+
dryRun: body.dryRun === true
|
|
537
|
+
});
|
|
538
|
+
json(res, result, 201);
|
|
539
|
+
} catch (err) {
|
|
540
|
+
error(res, `Action benchmark failed: ${String(err)}`, 500);
|
|
541
|
+
}
|
|
542
|
+
return true;
|
|
543
|
+
}
|
|
544
|
+
if (method === "POST" && pathname === "/api/training/evals/record-comparison") {
|
|
545
|
+
const body = await readJsonBody(req, res);
|
|
546
|
+
if (!body) return true;
|
|
547
|
+
if (!body.report || typeof body.report !== "object" || Array.isArray(body.report)) {
|
|
548
|
+
error(res, "report must be a JSON object", 400);
|
|
549
|
+
return true;
|
|
550
|
+
}
|
|
551
|
+
try {
|
|
552
|
+
const result = await writeEvalComparisonArtifact({
|
|
553
|
+
report: body.report,
|
|
554
|
+
reportPath: resolveStringSetting(body.reportPath),
|
|
555
|
+
outputDir: resolveStringSetting(body.outputDir),
|
|
556
|
+
source: body.source && typeof body.source === "object" && !Array.isArray(body.source) ? body.source : void 0
|
|
557
|
+
});
|
|
558
|
+
json(res, result, 201);
|
|
559
|
+
} catch (err) {
|
|
560
|
+
error(res, `Eval comparison artifact failed: ${String(err)}`, 500);
|
|
561
|
+
}
|
|
562
|
+
return true;
|
|
563
|
+
}
|
|
564
|
+
if (method === "POST" && pathname === "/api/training/evals/run-local-comparison") {
|
|
565
|
+
const body = await readJsonBody(req, res);
|
|
566
|
+
if (!body) return true;
|
|
567
|
+
const backend = body.backend === "mlx" || body.backend === "cuda" || body.backend === "cpu" ? body.backend : void 0;
|
|
568
|
+
try {
|
|
569
|
+
const result = await runLocalEvalComparison({
|
|
570
|
+
trainingRoot: resolveStringSetting(body.trainingRoot),
|
|
571
|
+
python: resolveStringSetting(body.python),
|
|
572
|
+
manifestPath: resolveStringSetting(body.manifestPath),
|
|
573
|
+
model: resolveStringSetting(body.model),
|
|
574
|
+
trainedModelPath: resolveStringSetting(body.trainedModelPath),
|
|
575
|
+
backend,
|
|
576
|
+
promptFile: resolveStringSetting(body.promptFile),
|
|
577
|
+
maxTokens: typeof body.maxTokens === "number" && Number.isFinite(body.maxTokens) ? Math.max(1, Math.floor(body.maxTokens)) : void 0,
|
|
578
|
+
systemPrompt: resolveStringSetting(body.systemPrompt),
|
|
579
|
+
outputPath: resolveStringSetting(body.outputPath),
|
|
580
|
+
outputDir: resolveStringSetting(body.outputDir),
|
|
581
|
+
dryRun: body.dryRun === true
|
|
582
|
+
});
|
|
583
|
+
json(res, result, 201);
|
|
584
|
+
} catch (err) {
|
|
585
|
+
error(res, `Local eval comparison failed: ${String(err)}`, 500);
|
|
586
|
+
}
|
|
587
|
+
return true;
|
|
588
|
+
}
|
|
589
|
+
if (method === "POST" && pathname === "/api/training/benchmarks/matrix") {
|
|
590
|
+
const body = await readJsonBody(req, res);
|
|
591
|
+
if (!body) return true;
|
|
592
|
+
if (!Array.isArray(body.rows)) {
|
|
593
|
+
error(res, "rows must be an array", 400);
|
|
594
|
+
return true;
|
|
595
|
+
}
|
|
596
|
+
const rows = body.rows.filter(
|
|
597
|
+
(row) => row !== null && typeof row === "object" && !Array.isArray(row) && typeof row.modelId === "string" && typeof row.benchmark === "string" && typeof row.score === "number" && (row.variant === "reference" || row.variant === "base" || row.variant === "trained")
|
|
598
|
+
);
|
|
599
|
+
if (rows.length !== body.rows.length) {
|
|
600
|
+
error(
|
|
601
|
+
res,
|
|
602
|
+
"each row must include modelId, benchmark, numeric score, and variant reference|base|trained",
|
|
603
|
+
400
|
|
604
|
+
);
|
|
605
|
+
return true;
|
|
606
|
+
}
|
|
607
|
+
try {
|
|
608
|
+
const result = await writeBenchmarkMatrixArtifact({
|
|
609
|
+
rows,
|
|
610
|
+
outputDir: resolveStringSetting(body.outputDir),
|
|
611
|
+
generatedAt: resolveStringSetting(body.generatedAt),
|
|
612
|
+
referenceModelId: resolveStringSetting(body.referenceModelId),
|
|
613
|
+
source: body.source && typeof body.source === "object" && !Array.isArray(body.source) ? body.source : void 0
|
|
614
|
+
});
|
|
615
|
+
json(res, result, 201);
|
|
616
|
+
} catch (err) {
|
|
617
|
+
error(res, `Benchmark matrix artifact failed: ${String(err)}`, 500);
|
|
618
|
+
}
|
|
619
|
+
return true;
|
|
620
|
+
}
|
|
621
|
+
if (method === "POST" && pathname === "/api/training/benchmarks/matrix/from-artifacts") {
|
|
622
|
+
const body = await readJsonBody(req, res);
|
|
623
|
+
if (!body) return true;
|
|
624
|
+
if (!Array.isArray(body.artifacts)) {
|
|
625
|
+
error(res, "artifacts must be an array", 400);
|
|
626
|
+
return true;
|
|
627
|
+
}
|
|
628
|
+
const artifacts = body.artifacts.filter(
|
|
629
|
+
(artifact) => artifact !== null && typeof artifact === "object" && !Array.isArray(artifact) && typeof artifact.path === "string" && (artifact.variant === void 0 || artifact.variant === "reference" || artifact.variant === "base" || artifact.variant === "trained")
|
|
630
|
+
);
|
|
631
|
+
if (artifacts.length !== body.artifacts.length) {
|
|
632
|
+
error(
|
|
633
|
+
res,
|
|
634
|
+
"each artifact must include path and optional variant reference|base|trained",
|
|
635
|
+
400
|
|
636
|
+
);
|
|
637
|
+
return true;
|
|
638
|
+
}
|
|
639
|
+
try {
|
|
640
|
+
const result = await writeBenchmarkMatrixArtifactFromArtifacts({
|
|
641
|
+
artifacts,
|
|
642
|
+
outputDir: resolveStringSetting(body.outputDir),
|
|
643
|
+
generatedAt: resolveStringSetting(body.generatedAt),
|
|
644
|
+
referenceModelId: resolveStringSetting(body.referenceModelId),
|
|
645
|
+
source: body.source && typeof body.source === "object" && !Array.isArray(body.source) ? body.source : void 0
|
|
646
|
+
});
|
|
647
|
+
json(res, result, 201);
|
|
648
|
+
} catch (err) {
|
|
649
|
+
error(res, `Benchmark matrix from artifacts failed: ${String(err)}`, 500);
|
|
650
|
+
}
|
|
651
|
+
return true;
|
|
652
|
+
}
|
|
653
|
+
if (method === "POST" && pathname === "/api/training/benchmarks/run-vs-cerebras") {
|
|
654
|
+
const body = await readJsonBody(req, res);
|
|
655
|
+
if (!body) return true;
|
|
656
|
+
const benchmark = body.benchmark === "clawbench" || body.benchmark === "eliza_harness_action_selection" || body.benchmark === "hermes" || body.benchmark === "all" ? body.benchmark : void 0;
|
|
657
|
+
const variants = body.variants === "trained" || body.variants === "base" || body.variants === "both" ? body.variants : void 0;
|
|
658
|
+
try {
|
|
659
|
+
const result = await runBenchmarkVsCerebras({
|
|
660
|
+
trainingRoot: resolveStringSetting(body.trainingRoot),
|
|
661
|
+
python: resolveStringSetting(body.python),
|
|
662
|
+
tiers: resolveStringSetting(body.tiers),
|
|
663
|
+
benchmark,
|
|
664
|
+
variants,
|
|
665
|
+
cerebrasModel: resolveStringSetting(body.cerebrasModel),
|
|
666
|
+
maxSamples: typeof body.maxSamples === "number" && Number.isFinite(body.maxSamples) ? Math.max(1, Math.floor(body.maxSamples)) : void 0,
|
|
667
|
+
outputDir: resolveStringSetting(body.outputDir),
|
|
668
|
+
checkpointsDir: resolveStringSetting(body.checkpointsDir),
|
|
669
|
+
trainedModelPath: resolveStringSetting(body.trainedModelPath),
|
|
670
|
+
dryRun: body.dryRun === true,
|
|
671
|
+
resultsDb: resolveStringSetting(body.resultsDb),
|
|
672
|
+
datasetVersion: resolveStringSetting(body.datasetVersion),
|
|
673
|
+
codeCommit: resolveStringSetting(body.codeCommit),
|
|
674
|
+
matrixOutputDir: resolveStringSetting(body.matrixOutputDir)
|
|
675
|
+
});
|
|
676
|
+
json(res, result, 201);
|
|
677
|
+
} catch (err) {
|
|
678
|
+
error(res, `Benchmark vs Cerebras failed: ${String(err)}`, 500);
|
|
679
|
+
}
|
|
680
|
+
return true;
|
|
681
|
+
}
|
|
682
|
+
if (method === "POST" && pathname === "/api/training/models/stage-eliza1-bundle") {
|
|
683
|
+
const body = await readJsonBody(req, res);
|
|
684
|
+
if (!body) return true;
|
|
685
|
+
try {
|
|
686
|
+
const result = await stageEliza1Bundle({
|
|
687
|
+
trainingRoot: resolveStringSetting(body.trainingRoot),
|
|
688
|
+
python: resolveStringSetting(body.python),
|
|
689
|
+
repoId: resolveStringSetting(body.repoId),
|
|
690
|
+
tier: resolveStringSetting(body.tier),
|
|
691
|
+
localDir: resolveStringSetting(body.localDir),
|
|
692
|
+
outputDir: resolveStringSetting(body.outputDir),
|
|
693
|
+
maxBytes: typeof body.maxBytes === "number" && Number.isFinite(body.maxBytes) ? Math.max(1, Math.floor(body.maxBytes)) : void 0,
|
|
694
|
+
apply: body.apply === true
|
|
695
|
+
});
|
|
696
|
+
json(res, result, 201);
|
|
697
|
+
} catch (err) {
|
|
698
|
+
error(res, `Eliza-1 bundle staging failed: ${String(err)}`, 500);
|
|
699
|
+
}
|
|
700
|
+
return true;
|
|
701
|
+
}
|
|
702
|
+
if (method === "GET" && pathname === "/api/training/trajectories") {
|
|
703
|
+
const url = new URL(
|
|
704
|
+
req.url ?? "/",
|
|
705
|
+
`http://${req.headers.host ?? "localhost"}`
|
|
706
|
+
);
|
|
707
|
+
const limit = parsePositiveInteger(url.searchParams.get("limit"), 100);
|
|
708
|
+
const offset = Math.max(0, Number(url.searchParams.get("offset") ?? "0"));
|
|
709
|
+
const result = await trainingService.listTrajectories({ limit, offset });
|
|
710
|
+
json(res, result);
|
|
711
|
+
return true;
|
|
712
|
+
}
|
|
713
|
+
const trajectoryMatch = /^\/api\/training\/trajectories\/([^/]+)$/.exec(
|
|
714
|
+
pathname
|
|
715
|
+
);
|
|
716
|
+
if (method === "GET" && trajectoryMatch) {
|
|
717
|
+
const trajectoryId = decodeURIComponent(trajectoryMatch[1]);
|
|
718
|
+
const detail = await trainingService.getTrajectoryById(trajectoryId);
|
|
719
|
+
if (!detail) {
|
|
720
|
+
error(res, "Trajectory not found", 404);
|
|
721
|
+
return true;
|
|
722
|
+
}
|
|
723
|
+
json(res, { trajectory: detail });
|
|
724
|
+
return true;
|
|
725
|
+
}
|
|
726
|
+
if (method === "GET" && pathname === "/api/training/datasets") {
|
|
727
|
+
json(res, { datasets: trainingService.listDatasets() });
|
|
728
|
+
return true;
|
|
729
|
+
}
|
|
730
|
+
if (method === "POST" && pathname === "/api/training/datasets/build") {
|
|
731
|
+
const body = await readJsonBody(req, res);
|
|
732
|
+
if (!body) return true;
|
|
733
|
+
try {
|
|
734
|
+
const dataset = await trainingService.buildDataset({
|
|
735
|
+
limit: body.limit,
|
|
736
|
+
minLlmCallsPerTrajectory: body.minLlmCallsPerTrajectory
|
|
737
|
+
});
|
|
738
|
+
json(res, { dataset }, 201);
|
|
739
|
+
} catch (err) {
|
|
740
|
+
sendServiceError(error, res, err, 500);
|
|
741
|
+
}
|
|
742
|
+
return true;
|
|
743
|
+
}
|
|
744
|
+
if (method === "GET" && pathname === "/api/training/backends") {
|
|
745
|
+
const backends = await detectAvailableBackends();
|
|
746
|
+
json(res, { backends });
|
|
747
|
+
return true;
|
|
748
|
+
}
|
|
749
|
+
if (method === "GET" && pathname === "/api/training/jobs") {
|
|
750
|
+
json(res, { jobs: trainingService.listJobs() });
|
|
751
|
+
return true;
|
|
752
|
+
}
|
|
753
|
+
if (method === "POST" && pathname === "/api/training/jobs") {
|
|
754
|
+
const body = await readJsonBody(req, res);
|
|
755
|
+
if (!body) return true;
|
|
756
|
+
if (body.backend && body.backend !== "cpu") {
|
|
757
|
+
const backends = await detectAvailableBackends();
|
|
758
|
+
if (!backends[body.backend]) {
|
|
759
|
+
const available = Object.entries(backends).filter(([, ok]) => ok).map(([name]) => name).join(", ");
|
|
760
|
+
error(
|
|
761
|
+
res,
|
|
762
|
+
`Backend '${body.backend}' is not available on this system. Available backends: ${available}`,
|
|
763
|
+
400
|
|
764
|
+
);
|
|
765
|
+
return true;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
try {
|
|
769
|
+
const job = await trainingService.startTrainingJob({
|
|
770
|
+
datasetId: body.datasetId,
|
|
771
|
+
maxTrajectories: body.maxTrajectories,
|
|
772
|
+
backend: body.backend,
|
|
773
|
+
model: body.model,
|
|
774
|
+
iterations: body.iterations,
|
|
775
|
+
batchSize: body.batchSize,
|
|
776
|
+
learningRate: body.learningRate
|
|
777
|
+
});
|
|
778
|
+
json(res, { job }, 201);
|
|
779
|
+
} catch (err) {
|
|
780
|
+
sendServiceError(error, res, err, 400);
|
|
781
|
+
}
|
|
782
|
+
return true;
|
|
783
|
+
}
|
|
784
|
+
const jobMatch = /^\/api\/training\/jobs\/([^/]+)$/.exec(pathname);
|
|
785
|
+
if (method === "GET" && jobMatch) {
|
|
786
|
+
const jobId = decodeURIComponent(jobMatch[1]);
|
|
787
|
+
const job = trainingService.getJob(jobId);
|
|
788
|
+
if (!job) {
|
|
789
|
+
error(res, "Training job not found", 404);
|
|
790
|
+
return true;
|
|
791
|
+
}
|
|
792
|
+
json(res, { job });
|
|
793
|
+
return true;
|
|
794
|
+
}
|
|
795
|
+
const cancelMatch = /^\/api\/training\/jobs\/([^/]+)\/cancel$/.exec(pathname);
|
|
796
|
+
if (method === "POST" && cancelMatch) {
|
|
797
|
+
const jobId = decodeURIComponent(cancelMatch[1]);
|
|
798
|
+
try {
|
|
799
|
+
const job = await trainingService.cancelJob(jobId);
|
|
800
|
+
json(res, { job });
|
|
801
|
+
} catch (err) {
|
|
802
|
+
sendServiceError(error, res, err, 404);
|
|
803
|
+
}
|
|
804
|
+
return true;
|
|
805
|
+
}
|
|
806
|
+
if (method === "GET" && pathname === "/api/training/models") {
|
|
807
|
+
json(res, { models: trainingService.listModels() });
|
|
808
|
+
return true;
|
|
809
|
+
}
|
|
810
|
+
const importMatch = /^\/api\/training\/models\/([^/]+)\/import-ollama$/.exec(
|
|
811
|
+
pathname
|
|
812
|
+
);
|
|
813
|
+
if (method === "POST" && importMatch) {
|
|
814
|
+
const modelId = decodeURIComponent(importMatch[1]);
|
|
815
|
+
const body = await readJsonBody(req, res);
|
|
816
|
+
if (!body) return true;
|
|
817
|
+
if (body.ollamaUrl !== void 0 && typeof body.ollamaUrl !== "string") {
|
|
818
|
+
error(res, "ollamaUrl must be a string", 400);
|
|
819
|
+
return true;
|
|
820
|
+
}
|
|
821
|
+
if (typeof body.ollamaUrl === "string") {
|
|
822
|
+
const ollamaUrlRejection = resolveOllamaUrlRejection(
|
|
823
|
+
body.ollamaUrl,
|
|
824
|
+
isLoopbackHost
|
|
825
|
+
);
|
|
826
|
+
if (ollamaUrlRejection) {
|
|
827
|
+
error(res, ollamaUrlRejection, 400);
|
|
828
|
+
return true;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
try {
|
|
832
|
+
const model = await trainingService.importModelToOllama(modelId, body);
|
|
833
|
+
json(res, { model });
|
|
834
|
+
} catch (err) {
|
|
835
|
+
sendServiceError(error, res, err, 400);
|
|
836
|
+
}
|
|
837
|
+
return true;
|
|
838
|
+
}
|
|
839
|
+
const activateMatch = /^\/api\/training\/models\/([^/]+)\/activate$/.exec(
|
|
840
|
+
pathname
|
|
841
|
+
);
|
|
842
|
+
if (method === "POST" && activateMatch) {
|
|
843
|
+
const modelId = decodeURIComponent(activateMatch[1]);
|
|
844
|
+
const body = await readJsonBody(req, res);
|
|
845
|
+
if (!body) return true;
|
|
846
|
+
try {
|
|
847
|
+
const result = await trainingService.activateModel(
|
|
848
|
+
modelId,
|
|
849
|
+
body.providerModel
|
|
850
|
+
);
|
|
851
|
+
json(res, result);
|
|
852
|
+
} catch (err) {
|
|
853
|
+
sendServiceError(error, res, err, 400);
|
|
854
|
+
}
|
|
855
|
+
return true;
|
|
856
|
+
}
|
|
857
|
+
const benchmarkMatch = /^\/api\/training\/models\/([^/]+)\/benchmark$/.exec(
|
|
858
|
+
pathname
|
|
859
|
+
);
|
|
860
|
+
if (method === "POST" && benchmarkMatch) {
|
|
861
|
+
const modelId = decodeURIComponent(benchmarkMatch[1]);
|
|
862
|
+
try {
|
|
863
|
+
const result = await trainingService.benchmarkModel(modelId);
|
|
864
|
+
json(res, result);
|
|
865
|
+
} catch (err) {
|
|
866
|
+
sendServiceError(error, res, err, 400);
|
|
867
|
+
}
|
|
868
|
+
return true;
|
|
869
|
+
}
|
|
870
|
+
if (method === "GET" && pathname === "/api/training/blueprints") {
|
|
871
|
+
const { ALL_BLUEPRINTS, BLUEPRINT_STATS } = await import("../core/scenario-blueprints.js");
|
|
872
|
+
json(res, {
|
|
873
|
+
count: ALL_BLUEPRINTS.length,
|
|
874
|
+
stats: BLUEPRINT_STATS,
|
|
875
|
+
blueprints: ALL_BLUEPRINTS.map((b) => ({
|
|
876
|
+
id: b.id,
|
|
877
|
+
decision: b.decision,
|
|
878
|
+
primaryContext: b.primaryContext,
|
|
879
|
+
pattern: b.pattern,
|
|
880
|
+
description: b.description
|
|
881
|
+
}))
|
|
882
|
+
});
|
|
883
|
+
return true;
|
|
884
|
+
}
|
|
885
|
+
if (method === "GET" && pathname === "/api/training/context-catalog") {
|
|
886
|
+
const { ACTION_CONTEXT_MAP, PROVIDER_CONTEXT_MAP, ALL_CONTEXTS } = await import("../core/context-catalog.js");
|
|
887
|
+
json(res, {
|
|
888
|
+
contexts: ALL_CONTEXTS,
|
|
889
|
+
actions: ACTION_CONTEXT_MAP,
|
|
890
|
+
providers: PROVIDER_CONTEXT_MAP
|
|
891
|
+
});
|
|
892
|
+
return true;
|
|
893
|
+
}
|
|
894
|
+
if (method === "GET" && pathname === "/api/training/context-audit") {
|
|
895
|
+
if (!runtime || !Array.isArray(runtime.plugins)) {
|
|
896
|
+
error(
|
|
897
|
+
res,
|
|
898
|
+
"Runtime with loaded plugins is required for context audit",
|
|
899
|
+
503
|
|
900
|
+
);
|
|
901
|
+
return true;
|
|
902
|
+
}
|
|
903
|
+
const { auditRuntimeContextCoverage, hasContextAuditGaps } = await import("../core/context-audit.js");
|
|
904
|
+
const audit = auditRuntimeContextCoverage(
|
|
905
|
+
runtime
|
|
906
|
+
);
|
|
907
|
+
json(res, {
|
|
908
|
+
audit,
|
|
909
|
+
hasGaps: hasContextAuditGaps(audit)
|
|
910
|
+
});
|
|
911
|
+
return true;
|
|
912
|
+
}
|
|
913
|
+
if (method === "POST" && pathname === "/api/training/generate-dataset") {
|
|
914
|
+
const body = await readJsonBody(req, res);
|
|
915
|
+
if (!body) return true;
|
|
916
|
+
const cerebrasKey = process.env.CEREBRAS_API_KEY;
|
|
917
|
+
const trainProvider = process.env.TRAIN_MODEL_PROVIDER?.trim() ?? process.env.TRAINING_PROVIDER?.trim();
|
|
918
|
+
const anthropicKey = resolveStringSetting(runtime?.getSetting?.("ANTHROPIC_API_KEY")) ?? process.env.ANTHROPIC_API_KEY;
|
|
919
|
+
const openaiKey = resolveStringSetting(runtime?.getSetting?.("OPENAI_API_KEY")) ?? process.env.OPENAI_API_KEY;
|
|
920
|
+
if (!cerebrasKey && !anthropicKey && !openaiKey) {
|
|
921
|
+
error(
|
|
922
|
+
res,
|
|
923
|
+
"No teacher model API key found. Set CEREBRAS_API_KEY (preferred), ANTHROPIC_API_KEY, or OPENAI_API_KEY.",
|
|
924
|
+
400
|
|
925
|
+
);
|
|
926
|
+
return true;
|
|
927
|
+
}
|
|
928
|
+
const {
|
|
929
|
+
generateDataset,
|
|
930
|
+
exportToElizaNativeJSONL,
|
|
931
|
+
createAnthropicTeacher,
|
|
932
|
+
createCerebrasTeacher,
|
|
933
|
+
createOpenAITeacher
|
|
934
|
+
} = await import("../core/dataset-generator.js");
|
|
935
|
+
const { buildRoleplayEpisodes, exportRoleplayEpisodes } = await import("../core/roleplay-trajectories.js");
|
|
936
|
+
const teacher = trainProvider === "cerebras" && cerebrasKey ? createCerebrasTeacher(runtime ?? void 0) : anthropicKey ? createAnthropicTeacher(anthropicKey, runtime ?? void 0) : createOpenAITeacher(openaiKey, runtime ?? void 0);
|
|
937
|
+
const outputDir = `.tmp/training-data-${Date.now()}`;
|
|
938
|
+
try {
|
|
939
|
+
const samples = await generateDataset({
|
|
940
|
+
variantsPerBlueprint: body.variantsPerBlueprint ?? 5,
|
|
941
|
+
teacher,
|
|
942
|
+
outputDir,
|
|
943
|
+
concurrency: body.concurrency ?? 5,
|
|
944
|
+
limitBlueprints: body.limitBlueprints,
|
|
945
|
+
filterContexts: narrowAgentContexts(body.filterContexts),
|
|
946
|
+
filterDecisions: narrowAgentDecisions(body.filterDecisions)
|
|
947
|
+
});
|
|
948
|
+
const { validateDataset } = await import("../core/replay-validator.js");
|
|
949
|
+
const report = validateDataset(samples);
|
|
950
|
+
const paths = await exportToElizaNativeJSONL(samples, outputDir);
|
|
951
|
+
const roleplayPaths = body.includeRoleplay === false ? void 0 : await exportRoleplayEpisodes(
|
|
952
|
+
buildRoleplayEpisodes(samples),
|
|
953
|
+
samples,
|
|
954
|
+
outputDir
|
|
955
|
+
);
|
|
956
|
+
json(
|
|
957
|
+
res,
|
|
958
|
+
{
|
|
959
|
+
samplesGenerated: samples.length,
|
|
960
|
+
report,
|
|
961
|
+
paths,
|
|
962
|
+
roleplayPaths,
|
|
963
|
+
outputDir
|
|
964
|
+
},
|
|
965
|
+
201
|
|
966
|
+
);
|
|
967
|
+
} catch (err) {
|
|
968
|
+
error(res, `Dataset generation failed: ${String(err)}`, 500);
|
|
969
|
+
}
|
|
970
|
+
return true;
|
|
971
|
+
}
|
|
972
|
+
if (method === "POST" && pathname === "/api/training/generate-roleplay") {
|
|
973
|
+
const body = await readJsonBody(req, res);
|
|
974
|
+
if (!body) return true;
|
|
975
|
+
const cerebrasKey = process.env.CEREBRAS_API_KEY;
|
|
976
|
+
const trainProvider = process.env.TRAIN_MODEL_PROVIDER?.trim() ?? process.env.TRAINING_PROVIDER?.trim();
|
|
977
|
+
const anthropicKey = resolveStringSetting(runtime?.getSetting?.("ANTHROPIC_API_KEY")) ?? process.env.ANTHROPIC_API_KEY;
|
|
978
|
+
const openaiKey = resolveStringSetting(runtime?.getSetting?.("OPENAI_API_KEY")) ?? process.env.OPENAI_API_KEY;
|
|
979
|
+
if (!cerebrasKey && !anthropicKey && !openaiKey) {
|
|
980
|
+
error(
|
|
981
|
+
res,
|
|
982
|
+
"No teacher model API key found. Set CEREBRAS_API_KEY (preferred), ANTHROPIC_API_KEY, or OPENAI_API_KEY.",
|
|
983
|
+
400
|
|
984
|
+
);
|
|
985
|
+
return true;
|
|
986
|
+
}
|
|
987
|
+
const {
|
|
988
|
+
generateDataset,
|
|
989
|
+
createAnthropicTeacher,
|
|
990
|
+
createCerebrasTeacher,
|
|
991
|
+
createOpenAITeacher
|
|
992
|
+
} = await import("../core/dataset-generator.js");
|
|
993
|
+
const { buildRoleplayEpisodes, exportRoleplayEpisodes } = await import("../core/roleplay-trajectories.js");
|
|
994
|
+
const teacher = trainProvider === "cerebras" && cerebrasKey ? createCerebrasTeacher(runtime ?? void 0) : anthropicKey ? createAnthropicTeacher(anthropicKey, runtime ?? void 0) : createOpenAITeacher(openaiKey, runtime ?? void 0);
|
|
995
|
+
const outputDir = `.tmp/training-roleplay-${Date.now()}`;
|
|
996
|
+
try {
|
|
997
|
+
const samples = await generateDataset({
|
|
998
|
+
variantsPerBlueprint: body.variantsPerBlueprint ?? 3,
|
|
999
|
+
teacher,
|
|
1000
|
+
outputDir,
|
|
1001
|
+
concurrency: body.concurrency ?? 5,
|
|
1002
|
+
limitBlueprints: body.limitBlueprints,
|
|
1003
|
+
filterContexts: narrowAgentContexts(body.filterContexts),
|
|
1004
|
+
filterDecisions: narrowAgentDecisions(body.filterDecisions)
|
|
1005
|
+
});
|
|
1006
|
+
const episodes = buildRoleplayEpisodes(samples);
|
|
1007
|
+
const paths = await exportRoleplayEpisodes(episodes, samples, outputDir);
|
|
1008
|
+
json(
|
|
1009
|
+
res,
|
|
1010
|
+
{
|
|
1011
|
+
samplesGenerated: samples.length,
|
|
1012
|
+
episodesGenerated: episodes.length,
|
|
1013
|
+
outputDir,
|
|
1014
|
+
paths
|
|
1015
|
+
},
|
|
1016
|
+
201
|
|
1017
|
+
);
|
|
1018
|
+
} catch (err) {
|
|
1019
|
+
error(res, `Roleplay generation failed: ${String(err)}`, 500);
|
|
1020
|
+
}
|
|
1021
|
+
return true;
|
|
1022
|
+
}
|
|
1023
|
+
if (method === "POST" && pathname === "/api/training/roleplay/execute") {
|
|
1024
|
+
const body = await readJsonBody(req, res);
|
|
1025
|
+
if (!body) return true;
|
|
1026
|
+
if (!runtime) {
|
|
1027
|
+
error(res, "Runtime is required to execute roleplay episodes", 503);
|
|
1028
|
+
return true;
|
|
1029
|
+
}
|
|
1030
|
+
const inputPath = body.episodesPath ?? body.manifestPath;
|
|
1031
|
+
if (!inputPath) {
|
|
1032
|
+
error(res, "episodesPath or manifestPath is required", 400);
|
|
1033
|
+
return true;
|
|
1034
|
+
}
|
|
1035
|
+
const {
|
|
1036
|
+
buildRoleplayExecutionReport,
|
|
1037
|
+
executeRoleplayEpisodes,
|
|
1038
|
+
exportRoleplayExecutionResults,
|
|
1039
|
+
loadRoleplayEpisodesFromPath
|
|
1040
|
+
} = await import("../core/roleplay-executor.js");
|
|
1041
|
+
try {
|
|
1042
|
+
const episodes = await loadRoleplayEpisodesFromPath(inputPath);
|
|
1043
|
+
const executions = await executeRoleplayEpisodes(episodes, {
|
|
1044
|
+
runtime,
|
|
1045
|
+
timeoutMs: body.timeoutMs,
|
|
1046
|
+
executeAllParticipantTurns: body.executeAllParticipantTurns ?? false
|
|
1047
|
+
});
|
|
1048
|
+
const outputDir = body.outputDir ?? `.tmp/training-roleplay-execution-${Date.now()}`;
|
|
1049
|
+
const paths = await exportRoleplayExecutionResults(executions, outputDir);
|
|
1050
|
+
const report = buildRoleplayExecutionReport(
|
|
1051
|
+
executions,
|
|
1052
|
+
paths.trajectoryDataset?.summary ?? null
|
|
1053
|
+
);
|
|
1054
|
+
json(
|
|
1055
|
+
res,
|
|
1056
|
+
{
|
|
1057
|
+
episodesExecuted: executions.length,
|
|
1058
|
+
report,
|
|
1059
|
+
outputDir,
|
|
1060
|
+
paths
|
|
1061
|
+
},
|
|
1062
|
+
201
|
|
1063
|
+
);
|
|
1064
|
+
} catch (err) {
|
|
1065
|
+
error(res, `Roleplay execution failed: ${String(err)}`, 500);
|
|
1066
|
+
}
|
|
1067
|
+
return true;
|
|
1068
|
+
}
|
|
1069
|
+
if (method === "POST" && pathname === "/api/training/trajectories/export") {
|
|
1070
|
+
const body = await readJsonBody(req, res);
|
|
1071
|
+
if (!body) return true;
|
|
1072
|
+
if (body.runId !== void 0 && !normalizeRunId(body.runId)) {
|
|
1073
|
+
error(res, "runId must be a non-empty string", 400);
|
|
1074
|
+
return true;
|
|
1075
|
+
}
|
|
1076
|
+
const outputPath = body.outputPath ?? `.tmp/training-trajectory-export-${Date.now()}.jsonl`;
|
|
1077
|
+
try {
|
|
1078
|
+
const explicitIds = Array.isArray(body.trajectoryIds) ? body.trajectoryIds.filter((id) => typeof id === "string" && id.trim()) : [];
|
|
1079
|
+
const listedTrajectories = explicitIds.length > 0 ? null : await trainingService.listTrajectories({
|
|
1080
|
+
limit: body.limit ?? 100,
|
|
1081
|
+
offset: 0,
|
|
1082
|
+
runId: normalizeRunId(body.runId)
|
|
1083
|
+
});
|
|
1084
|
+
const trajectoryIds = explicitIds.length > 0 ? explicitIds : (listedTrajectories?.trajectories ?? []).map((item) => item.id).filter((id) => id.length > 0);
|
|
1085
|
+
const details = (await Promise.all(
|
|
1086
|
+
trajectoryIds.map(
|
|
1087
|
+
(trajectoryId) => trainingService.getTrajectoryById(trajectoryId)
|
|
1088
|
+
)
|
|
1089
|
+
)).filter((t) => t !== null);
|
|
1090
|
+
if (body.bundle || body.exportBundle) {
|
|
1091
|
+
const requestedRunId = normalizeRunId(body.runId);
|
|
1092
|
+
const bundleTrajectories = requestedRunId ? details.filter(
|
|
1093
|
+
(trajectory) => trajectoryHasRunId(trajectory, requestedRunId)
|
|
1094
|
+
) : details;
|
|
1095
|
+
const { buildTrajectoryExportBundle } = await import("../core/trajectory-export-bundle.js");
|
|
1096
|
+
const bundle = await buildTrajectoryExportBundle({
|
|
1097
|
+
trajectories: bundleTrajectories,
|
|
1098
|
+
outputDir: body.outputDir ?? `.tmp/training-trajectory-bundle-${Date.now()}`,
|
|
1099
|
+
includeRawJsonl: body.includeRawJsonl === true || body.includeRaw === true,
|
|
1100
|
+
tasks: narrowTrainingTasks(body.tasks),
|
|
1101
|
+
source: {
|
|
1102
|
+
kind: "training-trajectories-export-route",
|
|
1103
|
+
runId: requestedRunId,
|
|
1104
|
+
metadata: {
|
|
1105
|
+
requestedLimit: body.limit ?? 100,
|
|
1106
|
+
requestedRunId: requestedRunId ?? null,
|
|
1107
|
+
explicitTrajectoryIds: explicitIds.length,
|
|
1108
|
+
selectedTrajectoryIds: trajectoryIds.length,
|
|
1109
|
+
loadedTrajectories: details.length,
|
|
1110
|
+
bundledTrajectories: bundleTrajectories.length
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
});
|
|
1114
|
+
json(
|
|
1115
|
+
res,
|
|
1116
|
+
{
|
|
1117
|
+
trajectoriesConsidered: trajectoryIds.length,
|
|
1118
|
+
trajectoriesBundled: bundleTrajectories.length,
|
|
1119
|
+
outputDir: bundle.outputDir,
|
|
1120
|
+
manifestPath: bundle.manifestPath,
|
|
1121
|
+
bundle: bundle.manifest
|
|
1122
|
+
},
|
|
1123
|
+
201
|
|
1124
|
+
);
|
|
1125
|
+
return true;
|
|
1126
|
+
}
|
|
1127
|
+
let exported = 0;
|
|
1128
|
+
let taskDataset;
|
|
1129
|
+
if (body.splitByTask || body.outputDir || body.tasks?.length) {
|
|
1130
|
+
const { exportTrajectoryTaskDatasets } = await import("../core/trajectory-task-datasets.js");
|
|
1131
|
+
const dataset = await exportTrajectoryTaskDatasets(
|
|
1132
|
+
details,
|
|
1133
|
+
body.outputDir ?? `.tmp/training-trajectory-export-${Date.now()}`,
|
|
1134
|
+
narrowTrainingTasks(body.tasks)
|
|
1135
|
+
);
|
|
1136
|
+
exported = dataset.counts.should_respond + dataset.counts.context_routing + dataset.counts.action_planner + dataset.counts.response + dataset.counts.media_description;
|
|
1137
|
+
taskDataset = {
|
|
1138
|
+
counts: dataset.counts,
|
|
1139
|
+
paths: dataset.paths,
|
|
1140
|
+
summary: dataset.summary
|
|
1141
|
+
};
|
|
1142
|
+
} else {
|
|
1143
|
+
const { exportTrajectoriesAsTraining } = await import("../core/dataset-generator.js");
|
|
1144
|
+
exported = await exportTrajectoriesAsTraining(
|
|
1145
|
+
details,
|
|
1146
|
+
body.agentName ?? runtime?.character?.name ?? "Agent",
|
|
1147
|
+
outputPath
|
|
1148
|
+
);
|
|
1149
|
+
}
|
|
1150
|
+
json(
|
|
1151
|
+
res,
|
|
1152
|
+
{
|
|
1153
|
+
exportedExamples: exported,
|
|
1154
|
+
trajectoriesConsidered: trajectoryIds.length,
|
|
1155
|
+
outputPath,
|
|
1156
|
+
taskDataset
|
|
1157
|
+
},
|
|
1158
|
+
201
|
|
1159
|
+
);
|
|
1160
|
+
} catch (err) {
|
|
1161
|
+
error(res, `Trajectory export failed: ${String(err)}`, 500);
|
|
1162
|
+
}
|
|
1163
|
+
return true;
|
|
1164
|
+
}
|
|
1165
|
+
if (method === "POST" && pathname === "/api/training/trajectories/publish") {
|
|
1166
|
+
const hfConfig = resolveHfUploadConfig();
|
|
1167
|
+
if (!hfConfig) {
|
|
1168
|
+
error(
|
|
1169
|
+
res,
|
|
1170
|
+
"HuggingFace publishing is not configured. Set ELIZA_TRAJECTORY_HF_REPO and an HF token (HF_TOKEN, with HUGGINGFACE_HUB_TOKEN / HUGGING_FACE_HUB_TOKEN accepted as fallbacks).",
|
|
1171
|
+
409
|
|
1172
|
+
);
|
|
1173
|
+
return true;
|
|
1174
|
+
}
|
|
1175
|
+
const body = await readJsonBody(req, res);
|
|
1176
|
+
if (!body) return true;
|
|
1177
|
+
try {
|
|
1178
|
+
const explicitIds = Array.isArray(body.trajectoryIds) ? body.trajectoryIds.filter((id) => typeof id === "string" && id.trim()) : [];
|
|
1179
|
+
const listed = explicitIds.length > 0 ? null : await trainingService.listTrajectories({
|
|
1180
|
+
limit: body.limit ?? 500,
|
|
1181
|
+
offset: 0
|
|
1182
|
+
});
|
|
1183
|
+
const trajectoryIds = explicitIds.length > 0 ? explicitIds : (listed?.trajectories ?? []).map((item) => item.id).filter((id) => id.length > 0);
|
|
1184
|
+
const details = (await Promise.all(
|
|
1185
|
+
trajectoryIds.map(
|
|
1186
|
+
(trajectoryId) => trainingService.getTrajectoryById(trajectoryId)
|
|
1187
|
+
)
|
|
1188
|
+
)).filter((t) => t !== null);
|
|
1189
|
+
const { buildTrajectoryExportBundle } = await import("../core/trajectory-export-bundle.js");
|
|
1190
|
+
const bundle = await buildTrajectoryExportBundle({
|
|
1191
|
+
trajectories: details,
|
|
1192
|
+
outputDir: body.outputDir ?? `.tmp/training-trajectory-publish-${Date.now()}`,
|
|
1193
|
+
tasks: narrowTrainingTasks(body.tasks),
|
|
1194
|
+
// Privacy filter forced on with the default hash anonymizer.
|
|
1195
|
+
privacy: {
|
|
1196
|
+
apply: true,
|
|
1197
|
+
options: { anonymizer: createHashAnonymizer() }
|
|
1198
|
+
},
|
|
1199
|
+
uploadToHuggingFace: hfConfig,
|
|
1200
|
+
source: {
|
|
1201
|
+
kind: "training-trajectories-publish-route",
|
|
1202
|
+
metadata: {
|
|
1203
|
+
requestedLimit: body.limit ?? 500,
|
|
1204
|
+
explicitTrajectoryIds: explicitIds.length,
|
|
1205
|
+
selectedTrajectoryIds: trajectoryIds.length,
|
|
1206
|
+
loadedTrajectories: details.length
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
});
|
|
1210
|
+
if (!bundle.manifest.cloudUpload.uploadedToHuggingFace) {
|
|
1211
|
+
error(
|
|
1212
|
+
res,
|
|
1213
|
+
`HuggingFace upload failed: ${bundle.manifest.cloudUpload.huggingFaceError ?? "unknown error"}`,
|
|
1214
|
+
502
|
|
1215
|
+
);
|
|
1216
|
+
return true;
|
|
1217
|
+
}
|
|
1218
|
+
json(
|
|
1219
|
+
res,
|
|
1220
|
+
{
|
|
1221
|
+
trajectoriesConsidered: trajectoryIds.length,
|
|
1222
|
+
trajectoriesPublished: bundle.manifest.counts.sanitizedTrajectoryRows,
|
|
1223
|
+
outputDir: bundle.outputDir,
|
|
1224
|
+
manifestPath: bundle.manifestPath,
|
|
1225
|
+
cloudUpload: bundle.manifest.cloudUpload
|
|
1226
|
+
},
|
|
1227
|
+
201
|
|
1228
|
+
);
|
|
1229
|
+
} catch (err) {
|
|
1230
|
+
error(res, `Trajectory publish failed: ${String(err)}`, 500);
|
|
1231
|
+
}
|
|
1232
|
+
return true;
|
|
1233
|
+
}
|
|
1234
|
+
return false;
|
|
1235
|
+
}
|
|
1236
|
+
export {
|
|
1237
|
+
handleTrainingRoutes
|
|
1238
|
+
};
|
|
1239
|
+
//# sourceMappingURL=training-routes.js.map
|