@elizaos/training 2.0.0-alpha.13 → 2.0.0-alpha.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/package.json +2 -2
  2. package/research-output/training-runs/training-run-1773726941205.json +38 -0
  3. package/scripts/rank_trajectories.ts +0 -1
  4. package/scripts/run_task_benchmark.ts +4 -11
  5. package/src/adapter.ts +96 -49
  6. package/src/archetypes/ArchetypeConfigService.ts +188 -185
  7. package/src/archetypes/derive-archetype.ts +47 -47
  8. package/src/archetypes/index.ts +2 -2
  9. package/src/benchmark/ArchetypeMatchupBenchmark.ts +70 -70
  10. package/src/benchmark/BenchmarkChartGenerator.ts +70 -69
  11. package/src/benchmark/BenchmarkDataGenerator.ts +136 -136
  12. package/src/benchmark/BenchmarkDataViewer.ts +32 -30
  13. package/src/benchmark/BenchmarkHistoryService.ts +13 -12
  14. package/src/benchmark/BenchmarkRunner.ts +87 -83
  15. package/src/benchmark/BenchmarkValidator.ts +48 -46
  16. package/src/benchmark/FastEvalRunner.ts +17 -16
  17. package/src/benchmark/MetricsValidator.ts +20 -21
  18. package/src/benchmark/MetricsVisualizer.ts +92 -85
  19. package/src/benchmark/ModelBenchmarkService.ts +90 -82
  20. package/src/benchmark/ModelRegistry.ts +44 -44
  21. package/src/benchmark/RulerBenchmarkIntegration.ts +24 -24
  22. package/src/benchmark/SimulationA2AInterface.ts +118 -118
  23. package/src/benchmark/SimulationEngine.ts +51 -51
  24. package/src/benchmark/TaskRunner.ts +87 -79
  25. package/src/benchmark/__tests__/BenchmarkRunner.test.ts +80 -80
  26. package/src/benchmark/__tests__/HeadToHead.test.ts +26 -26
  27. package/src/benchmark/index.ts +27 -27
  28. package/src/benchmark/parseSimulationMetrics.ts +32 -32
  29. package/src/benchmark/simulation-types.ts +10 -10
  30. package/src/dependencies.ts +34 -34
  31. package/src/generation/TrajectoryGenerator.ts +39 -37
  32. package/src/generation/index.ts +1 -1
  33. package/src/huggingface/HuggingFaceDatasetUploader.ts +72 -72
  34. package/src/huggingface/HuggingFaceIntegrationService.ts +59 -53
  35. package/src/huggingface/HuggingFaceModelUploader.ts +60 -59
  36. package/src/huggingface/index.ts +6 -6
  37. package/src/huggingface/shared/HuggingFaceUploadUtil.ts +32 -32
  38. package/src/index.ts +27 -27
  39. package/src/init-training.ts +6 -6
  40. package/src/metrics/TrajectoryMetricsExtractor.ts +70 -71
  41. package/src/metrics/__tests__/TrajectoryMetricsExtractor.test.ts +182 -182
  42. package/src/metrics/index.ts +2 -2
  43. package/src/rubrics/__tests__/index.test.ts +73 -73
  44. package/src/rubrics/ass-kisser.ts +6 -6
  45. package/src/rubrics/degen.ts +6 -6
  46. package/src/rubrics/goody-twoshoes.ts +6 -6
  47. package/src/rubrics/index.ts +50 -50
  48. package/src/rubrics/information-trader.ts +6 -6
  49. package/src/rubrics/infosec.ts +6 -6
  50. package/src/rubrics/liar.ts +6 -6
  51. package/src/rubrics/perps-trader.ts +6 -6
  52. package/src/rubrics/researcher.ts +6 -6
  53. package/src/rubrics/scammer.ts +6 -6
  54. package/src/rubrics/social-butterfly.ts +7 -7
  55. package/src/rubrics/super-predictor.ts +6 -6
  56. package/src/rubrics/trader.ts +5 -5
  57. package/src/scoring/ArchetypeScoringService.ts +56 -54
  58. package/src/scoring/JudgePromptBuilder.ts +96 -96
  59. package/src/scoring/LLMJudgeCache.ts +26 -23
  60. package/src/scoring/index.ts +3 -3
  61. package/src/training/AutomationPipeline.ts +149 -140
  62. package/src/training/BenchmarkService.ts +49 -45
  63. package/src/training/ConfigValidator.ts +38 -32
  64. package/src/training/MarketOutcomesTracker.ts +22 -12
  65. package/src/training/ModelDeployer.ts +15 -15
  66. package/src/training/ModelFetcher.ts +7 -7
  67. package/src/training/ModelSelectionService.ts +32 -32
  68. package/src/training/ModelUsageVerifier.ts +31 -24
  69. package/src/training/MultiModelOrchestrator.ts +44 -44
  70. package/src/training/RLModelConfig.ts +57 -57
  71. package/src/training/RewardBackpropagationService.ts +18 -17
  72. package/src/training/RulerScoringService.ts +73 -72
  73. package/src/training/TrainingMonitor.ts +29 -29
  74. package/src/training/TrajectoryRecorder.ts +25 -27
  75. package/src/training/__tests__/TrajectoryRecorder.test.ts +105 -105
  76. package/src/training/index.ts +36 -36
  77. package/src/training/logRLConfig.ts +7 -7
  78. package/src/training/pipeline.ts +13 -16
  79. package/src/training/storage/ModelStorageService.ts +32 -32
  80. package/src/training/storage/TrainingDataArchiver.ts +21 -21
  81. package/src/training/storage/index.ts +2 -2
  82. package/src/training/types.ts +6 -6
  83. package/src/training/window-utils.ts +14 -14
  84. package/src/utils/index.ts +7 -7
  85. package/src/utils/logger.ts +5 -5
  86. package/src/utils/snowflake.ts +1 -1
  87. package/src/utils/synthetic-detector.ts +7 -7
@@ -4,24 +4,24 @@
4
4
  * Tools for uploading models and datasets to HuggingFace Hub.
5
5
  */
6
6
 
7
- export { HuggingFaceDatasetUploader } from './HuggingFaceDatasetUploader';
7
+ export { HuggingFaceDatasetUploader } from "./HuggingFaceDatasetUploader";
8
8
  export type {
9
9
  DatasetUploadOptions,
10
10
  WeeklyUploadResult,
11
- } from './HuggingFaceIntegrationService';
11
+ } from "./HuggingFaceIntegrationService";
12
12
  export {
13
13
  HuggingFaceIntegrationService,
14
14
  huggingFaceIntegration,
15
- } from './HuggingFaceIntegrationService';
15
+ } from "./HuggingFaceIntegrationService";
16
16
  export type {
17
17
  ModelCardBenchmarkResult,
18
18
  ModelUploadOptions,
19
19
  ModelUploadResult,
20
- } from './HuggingFaceModelUploader';
21
- export { HuggingFaceModelUploader } from './HuggingFaceModelUploader';
20
+ } from "./HuggingFaceModelUploader";
21
+ export { HuggingFaceModelUploader } from "./HuggingFaceModelUploader";
22
22
 
23
23
  export {
24
24
  getHuggingFaceToken,
25
25
  HuggingFaceUploadUtil,
26
26
  requireHuggingFaceToken,
27
- } from './shared/HuggingFaceUploadUtil';
27
+ } from "./shared/HuggingFaceUploadUtil";
@@ -5,21 +5,21 @@
5
5
  * Consolidates upload logic used across different services.
6
6
  */
7
7
 
8
- import { exec } from 'node:child_process';
9
- import { promisify } from 'node:util';
10
- import * as hubModule from '@huggingface/hub';
11
- import { promises as fs } from 'fs';
12
- import * as path from 'path';
13
- import { logger } from '../../utils/logger';
8
+ import { exec } from "node:child_process";
9
+ import { promises as fs } from "node:fs";
10
+ import * as path from "node:path";
11
+ import { promisify } from "node:util";
12
+ import * as hubModule from "@huggingface/hub";
13
+ import { logger } from "../../utils/logger";
14
14
 
15
15
  export interface UploadFileOptions {
16
- repo: { type: 'model' | 'dataset'; name: string };
16
+ repo: { type: "model" | "dataset"; name: string };
17
17
  file: { path: string; content: Blob };
18
18
  credentials: { accessToken: string };
19
19
  }
20
20
 
21
21
  export interface CreateRepoOptions {
22
- repo: { type: 'model' | 'dataset'; name: string };
22
+ repo: { type: "model" | "dataset"; name: string };
23
23
  credentials: { accessToken: string };
24
24
  private?: boolean;
25
25
  }
@@ -46,7 +46,7 @@ export function requireHuggingFaceToken(): string {
46
46
  const token = getHuggingFaceToken();
47
47
  if (!token) {
48
48
  throw new Error(
49
- 'HuggingFace token not configured. Set HUGGING_FACE_TOKEN or HF_TOKEN environment variable.'
49
+ "HuggingFace token not configured. Set HUGGING_FACE_TOKEN or HF_TOKEN environment variable.",
50
50
  );
51
51
  }
52
52
  return token;
@@ -58,10 +58,10 @@ export class HuggingFaceUploadUtil {
58
58
  */
59
59
  static async uploadFile(
60
60
  repoName: string,
61
- repoType: 'model' | 'dataset',
61
+ repoType: "model" | "dataset",
62
62
  filePath: string,
63
63
  fileContent: string,
64
- token: string
64
+ token: string,
65
65
  ): Promise<void> {
66
66
  const uploadFile = hubModule.uploadFile;
67
67
 
@@ -87,9 +87,9 @@ export class HuggingFaceUploadUtil {
87
87
  */
88
88
  static async uploadDirectory(
89
89
  repoName: string,
90
- repoType: 'model' | 'dataset',
90
+ repoType: "model" | "dataset",
91
91
  localDir: string,
92
- token: string
92
+ token: string,
93
93
  ): Promise<number> {
94
94
  const files = await fs.readdir(localDir);
95
95
  let uploadCount = 0;
@@ -99,14 +99,14 @@ export class HuggingFaceUploadUtil {
99
99
  const stats = await fs.stat(filePath);
100
100
 
101
101
  if (stats.isFile()) {
102
- const content = await fs.readFile(filePath, 'utf-8');
102
+ const content = await fs.readFile(filePath, "utf-8");
103
103
 
104
104
  await HuggingFaceUploadUtil.uploadFile(
105
105
  repoName,
106
106
  repoType,
107
107
  file,
108
108
  content,
109
- token
109
+ token,
110
110
  );
111
111
  uploadCount++;
112
112
  }
@@ -125,9 +125,9 @@ export class HuggingFaceUploadUtil {
125
125
  */
126
126
  static async ensureRepository(
127
127
  repoName: string,
128
- repoType: 'model' | 'dataset',
128
+ repoType: "model" | "dataset",
129
129
  token: string,
130
- isPrivate = false
130
+ isPrivate = false,
131
131
  ): Promise<void> {
132
132
  const createRepo = hubModule.createRepo;
133
133
 
@@ -137,19 +137,19 @@ export class HuggingFaceUploadUtil {
137
137
  credentials: { accessToken: token },
138
138
  private: isPrivate,
139
139
  });
140
- logger.info('Created new repository', { repo: repoName, type: repoType });
140
+ logger.info("Created new repository", { repo: repoName, type: repoType });
141
141
  } catch (error) {
142
142
  // Repository might already exist, which is fine
143
143
  if (
144
144
  error instanceof Error &&
145
- (error.message.includes('already exists') ||
146
- error.message.includes('Repository not found'))
145
+ (error.message.includes("already exists") ||
146
+ error.message.includes("Repository not found"))
147
147
  ) {
148
- logger.info('Repository already exists or accessible', {
148
+ logger.info("Repository already exists or accessible", {
149
149
  repo: repoName,
150
150
  });
151
151
  } else {
152
- logger.warn('Could not ensure repository exists', {
152
+ logger.warn("Could not ensure repository exists", {
153
153
  error,
154
154
  repo: repoName,
155
155
  });
@@ -162,9 +162,9 @@ export class HuggingFaceUploadUtil {
162
162
  */
163
163
  static async uploadViaCLI(
164
164
  repoName: string,
165
- repoType: 'model' | 'dataset',
165
+ repoType: "model" | "dataset",
166
166
  localDir: string,
167
- token: string
167
+ token: string,
168
168
  ): Promise<void> {
169
169
  try {
170
170
  const execAsync = promisify(exec);
@@ -173,18 +173,18 @@ export class HuggingFaceUploadUtil {
173
173
  process.env.HUGGINGFACE_HUB_TOKEN = token;
174
174
 
175
175
  console.log(
176
- `Uploading ${localDir} to ${repoName} via huggingface-cli...`
176
+ `Uploading ${localDir} to ${repoName} via huggingface-cli...`,
177
177
  );
178
178
 
179
179
  await execAsync(
180
- `huggingface-cli upload ${repoName} ${localDir} --repo-type ${repoType}`
180
+ `huggingface-cli upload ${repoName} ${localDir} --repo-type ${repoType}`,
181
181
  );
182
182
 
183
- logger.info('Successfully uploaded via huggingface-cli', {
183
+ logger.info("Successfully uploaded via huggingface-cli", {
184
184
  repo: repoName,
185
185
  });
186
186
  } catch (error) {
187
- logger.error('CLI upload failed', { error });
187
+ logger.error("CLI upload failed", { error });
188
188
  throw error;
189
189
  }
190
190
  }
@@ -194,12 +194,12 @@ export class HuggingFaceUploadUtil {
194
194
  */
195
195
  static getManualUploadInstructions(
196
196
  repoName: string,
197
- repoType: 'model' | 'dataset',
198
- localDir: string
197
+ repoType: "model" | "dataset",
198
+ localDir: string,
199
199
  ): string[] {
200
200
  return [
201
- '1. Install huggingface-cli: pip install huggingface_hub',
202
- '2. Login: huggingface-cli login',
201
+ "1. Install huggingface-cli: pip install huggingface_hub",
202
+ "2. Login: huggingface-cli login",
203
203
  `3. Upload: huggingface-cli upload ${repoName} ${localDir} --repo-type ${repoType}`,
204
204
  ];
205
205
  }
package/src/index.ts CHANGED
@@ -19,17 +19,6 @@
19
19
  * @packageDocumentation
20
20
  */
21
21
 
22
- // Data adapter (must be registered before DB-dependent operations)
23
- export {
24
- getTrainingDataAdapter,
25
- getMarketDataAdapter,
26
- getLlmLogAdapter,
27
- isDataAdapterRegistered,
28
- resetAdapters,
29
- setLlmLogAdapter,
30
- setMarketDataAdapter,
31
- setTrainingDataAdapter,
32
- } from './adapter';
33
22
  export type {
34
23
  BenchmarkResultRecord,
35
24
  ILlmLogAdapter,
@@ -40,14 +29,25 @@ export type {
40
29
  TrainedModelRecord,
41
30
  TrainingBatchRecord,
42
31
  TrajectoryRecord,
43
- UUID,
44
32
  UserRecord,
45
- } from './adapter';
33
+ UUID,
34
+ } from "./adapter";
35
+ // Data adapter (must be registered before DB-dependent operations)
36
+ export {
37
+ getLlmLogAdapter,
38
+ getMarketDataAdapter,
39
+ getTrainingDataAdapter,
40
+ isDataAdapterRegistered,
41
+ resetAdapters,
42
+ setLlmLogAdapter,
43
+ setMarketDataAdapter,
44
+ setTrainingDataAdapter,
45
+ } from "./adapter";
46
46
 
47
47
  // Archetypes
48
- export * from './archetypes';
48
+ export * from "./archetypes";
49
49
  // Re-export all sub-modules
50
- export * from './benchmark';
50
+ export * from "./benchmark";
51
51
  export type {
52
52
  CreateAgentParams,
53
53
  ExportGroupedForGRPOFn,
@@ -60,7 +60,7 @@ export type {
60
60
  TrainingMessage,
61
61
  TrajectoryForTraining,
62
62
  TrajectoryStepForTraining,
63
- } from './dependencies';
63
+ } from "./dependencies";
64
64
  // Dependencies configuration
65
65
  export {
66
66
  areAgentDependenciesConfigured,
@@ -73,16 +73,21 @@ export {
73
73
  getExportToHuggingFace,
74
74
  getLLMCaller,
75
75
  getToTrainingMessages,
76
- } from './dependencies';
76
+ } from "./dependencies";
77
77
  // Generation
78
- export * from './generation';
79
- export * from './huggingface';
78
+ export * from "./generation";
79
+ export * from "./huggingface";
80
80
  // Training initialization
81
81
  export {
82
82
  initializeTrainingPackage,
83
83
  isTrainingInitialized,
84
84
  resetTrainingInitialization,
85
- } from './init-training';
85
+ } from "./init-training";
86
+ // Metrics (re-export for backwards compatibility, prefer import from './metrics')
87
+ export * from "./metrics";
88
+ export * from "./rubrics";
89
+ export * from "./scoring";
90
+ export * from "./training";
86
91
  export {
87
92
  benchmarkAndMaybeDeployModel,
88
93
  checkTrainingReadiness,
@@ -92,11 +97,6 @@ export {
92
97
  monitorTrainingJob,
93
98
  rollbackModelVersion,
94
99
  triggerTraining,
95
- } from './training/pipeline';
96
- // Metrics (re-export for backwards compatibility, prefer import from './metrics')
97
- export * from './metrics';
98
- export * from './rubrics';
99
- export * from './scoring';
100
- export * from './training';
100
+ } from "./training/pipeline";
101
101
  // Utilities
102
- export * from './utils';
102
+ export * from "./utils";
@@ -10,8 +10,8 @@
10
10
  * await initializeTrainingPackage();
11
11
  */
12
12
 
13
- import { areDependenciesConfigured } from './dependencies';
14
- import { logger } from './utils/logger';
13
+ import { areDependenciesConfigured } from "./dependencies";
14
+ import { logger } from "./utils/logger";
15
15
 
16
16
  let initialized = false;
17
17
 
@@ -22,20 +22,20 @@ let initialized = false;
22
22
  */
23
23
  export async function initializeTrainingPackage(): Promise<void> {
24
24
  if (initialized) {
25
- logger.debug('Training package already initialized', {}, 'TrainingInit');
25
+ logger.debug("Training package already initialized", {}, "TrainingInit");
26
26
  return;
27
27
  }
28
28
 
29
- logger.info('Initializing training package...', {}, 'TrainingInit');
29
+ logger.info("Initializing training package...", {}, "TrainingInit");
30
30
 
31
31
  if (!areDependenciesConfigured()) {
32
32
  throw new Error(
33
- 'Training dependencies not configured. Call configureTrainingDependencies() first.'
33
+ "Training dependencies not configured. Call configureTrainingDependencies() first.",
34
34
  );
35
35
  }
36
36
 
37
37
  initialized = true;
38
- logger.info('Training package initialized successfully', {}, 'TrainingInit');
38
+ logger.info("Training package initialized successfully", {}, "TrainingInit");
39
39
  }
40
40
 
41
41
  /**
@@ -14,8 +14,8 @@
14
14
  * @packageDocumentation
15
15
  */
16
16
 
17
- import type { TrajectoryStep } from '../training/types';
18
- import { logger } from '../utils/logger';
17
+ import type { TrajectoryStep } from "../training/types";
18
+ import { logger } from "../utils/logger";
19
19
  import type {
20
20
  BehavioralMetrics,
21
21
  BehaviorMetrics,
@@ -23,43 +23,43 @@ import type {
23
23
  InformationMetrics,
24
24
  SocialMetrics,
25
25
  TradingMetrics,
26
- } from './types';
26
+ } from "./types";
27
27
 
28
28
  /**
29
29
  * Action types that count as social interactions
30
30
  */
31
31
  const SOCIAL_ACTION_TYPES = new Set([
32
- 'join_group_chat',
33
- 'create_group_chat',
34
- 'leave_group_chat',
35
- 'post_group_message',
36
- 'send_dm',
37
- 'reply_dm',
38
- 'create_post',
39
- 'comment',
40
- 'like',
41
- 'follow',
42
- 'unfollow',
43
- 'mention',
44
- 'invite',
45
- 'react',
46
- 'share',
32
+ "join_group_chat",
33
+ "create_group_chat",
34
+ "leave_group_chat",
35
+ "post_group_message",
36
+ "send_dm",
37
+ "reply_dm",
38
+ "create_post",
39
+ "comment",
40
+ "like",
41
+ "follow",
42
+ "unfollow",
43
+ "mention",
44
+ "invite",
45
+ "react",
46
+ "share",
47
47
  ]);
48
48
 
49
49
  /**
50
50
  * Action types that count as trading actions
51
51
  */
52
52
  const TRADING_ACTION_TYPES = new Set([
53
- 'trade',
54
- 'buy',
55
- 'sell',
56
- 'place_order',
57
- 'cancel_order',
58
- 'close_position',
59
- 'open_position',
60
- 'predict',
61
- 'bet',
62
- 'swap',
53
+ "trade",
54
+ "buy",
55
+ "sell",
56
+ "place_order",
57
+ "cancel_order",
58
+ "close_position",
59
+ "open_position",
60
+ "predict",
61
+ "bet",
62
+ "swap",
63
63
  ]);
64
64
 
65
65
  export class TrajectoryMetricsExtractor {
@@ -107,7 +107,7 @@ export class TrajectoryMetricsExtractor {
107
107
  */
108
108
  private extractSocialMetrics(
109
109
  steps: TrajectoryStep[],
110
- agentId: string
110
+ agentId: string,
111
111
  ): SocialMetrics {
112
112
  const metrics: SocialMetrics = {
113
113
  groupChatsJoined: 0,
@@ -135,13 +135,13 @@ export class TrajectoryMetricsExtractor {
135
135
  const params = action.parameters || {};
136
136
 
137
137
  // Group chat actions
138
- if (actionType === 'join_group_chat') {
138
+ if (actionType === "join_group_chat") {
139
139
  metrics.groupChatsJoined++;
140
- } else if (actionType === 'create_group_chat') {
140
+ } else if (actionType === "create_group_chat") {
141
141
  metrics.groupChatsCreated++;
142
142
  } else if (
143
- actionType === 'post_group_message' ||
144
- actionType === 'group_message'
143
+ actionType === "post_group_message" ||
144
+ actionType === "group_message"
145
145
  ) {
146
146
  metrics.groupMessagesSent++;
147
147
  if (params.groupId) {
@@ -150,7 +150,7 @@ export class TrajectoryMetricsExtractor {
150
150
  }
151
151
 
152
152
  // DM actions
153
- else if (actionType === 'send_dm' || actionType === 'dm') {
153
+ else if (actionType === "send_dm" || actionType === "dm") {
154
154
  const isInitiator =
155
155
  params.initiator === agentId || params.fromAgent === agentId;
156
156
  if (isInitiator) {
@@ -159,14 +159,14 @@ export class TrajectoryMetricsExtractor {
159
159
  if (params.toUserId || params.recipientId) {
160
160
  usersInteracted.add(String(params.toUserId || params.recipientId));
161
161
  }
162
- } else if (actionType === 'reply_dm') {
162
+ } else if (actionType === "reply_dm") {
163
163
  dmsReplied++;
164
164
  }
165
165
 
166
166
  // Post/comment actions
167
- else if (actionType === 'create_post' || actionType === 'post') {
167
+ else if (actionType === "create_post" || actionType === "post") {
168
168
  metrics.postsCreated++;
169
- } else if (actionType === 'comment' || actionType === 'reply') {
169
+ } else if (actionType === "comment" || actionType === "reply") {
170
170
  metrics.commentsMade++;
171
171
  if (params.authorId) {
172
172
  usersInteracted.add(String(params.authorId));
@@ -174,12 +174,12 @@ export class TrajectoryMetricsExtractor {
174
174
  }
175
175
 
176
176
  // Mention/invite actions
177
- else if (actionType === 'mention') {
177
+ else if (actionType === "mention") {
178
178
  metrics.mentionsGiven++;
179
179
  if (params.mentionedUserId) {
180
180
  usersInteracted.add(String(params.mentionedUserId));
181
181
  }
182
- } else if (actionType === 'invite') {
182
+ } else if (actionType === "invite") {
183
183
  metrics.invitationsSent++;
184
184
  if (params.invitedUserId) {
185
185
  usersInteracted.add(String(params.invitedUserId));
@@ -211,7 +211,7 @@ export class TrajectoryMetricsExtractor {
211
211
  private extractTradingMetrics(
212
212
  steps: TrajectoryStep[],
213
213
  startBalance?: number,
214
- endBalance?: number
214
+ endBalance?: number,
215
215
  ): TradingMetrics {
216
216
  const metrics: TradingMetrics = {
217
217
  tradesExecuted: 0,
@@ -249,15 +249,15 @@ export class TrajectoryMetricsExtractor {
249
249
 
250
250
  // Track buy/sell
251
251
  if (
252
- actionType === 'buy' ||
253
- params.side === 'buy' ||
254
- params.direction === 'long'
252
+ actionType === "buy" ||
253
+ params.side === "buy" ||
254
+ params.direction === "long"
255
255
  ) {
256
256
  metrics.buyTrades++;
257
257
  } else if (
258
- actionType === 'sell' ||
259
- params.side === 'sell' ||
260
- params.direction === 'short'
258
+ actionType === "sell" ||
259
+ params.side === "sell" ||
260
+ params.direction === "short"
261
261
  ) {
262
262
  metrics.sellTrades++;
263
263
  }
@@ -270,7 +270,7 @@ export class TrajectoryMetricsExtractor {
270
270
 
271
271
  // Track position size
272
272
  const size = Number(
273
- params.amount || params.size || params.quantity || 0
273
+ params.amount || params.size || params.quantity || 0,
274
274
  );
275
275
  if (size > 0) {
276
276
  positionSizes.push(size);
@@ -278,7 +278,7 @@ export class TrajectoryMetricsExtractor {
278
278
 
279
279
  // Track P&L from result
280
280
  const tradePnL = Number(
281
- result.pnl || result.profit || result.return || 0
281
+ result.pnl || result.profit || result.return || 0,
282
282
  );
283
283
  if (tradePnL !== 0) {
284
284
  tradePnLs.push(tradePnL);
@@ -333,7 +333,7 @@ export class TrajectoryMetricsExtractor {
333
333
  const mean =
334
334
  tradePnLs.reduce((sum, pnl) => sum + pnl, 0) / tradePnLs.length;
335
335
  const variance =
336
- tradePnLs.reduce((sum, pnl) => sum + Math.pow(pnl - mean, 2), 0) /
336
+ tradePnLs.reduce((sum, pnl) => sum + (pnl - mean) ** 2, 0) /
337
337
  tradePnLs.length;
338
338
  const stdDev = Math.sqrt(variance);
339
339
  if (stdDev > 0) {
@@ -370,7 +370,7 @@ export class TrajectoryMetricsExtractor {
370
370
 
371
371
  // Track reputation changes
372
372
  const reputation = Number(
373
- envState.reputation || envState.agentReputation || 0
373
+ envState.reputation || envState.agentReputation || 0,
374
374
  );
375
375
  if (reputation !== 0) {
376
376
  if (startReputation === null) {
@@ -390,7 +390,7 @@ export class TrajectoryMetricsExtractor {
390
390
 
391
391
  // Track follower changes
392
392
  const followers = Number(
393
- envState.followers || envState.followerCount || 0
393
+ envState.followers || envState.followerCount || 0,
394
394
  );
395
395
  if (followers !== 0) {
396
396
  if (startFollowers === null) {
@@ -405,17 +405,17 @@ export class TrajectoryMetricsExtractor {
405
405
  const result = action.result;
406
406
  if (result.likes || result.upvotes) {
407
407
  metrics.positiveReactions += Number(
408
- result.likes || result.upvotes || 0
408
+ result.likes || result.upvotes || 0,
409
409
  );
410
410
  }
411
411
  if (result.dislikes || result.downvotes) {
412
412
  metrics.negativeReactions += Number(
413
- result.dislikes || result.downvotes || 0
413
+ result.dislikes || result.downvotes || 0,
414
414
  );
415
415
  }
416
416
  if (result.shares || result.reshares) {
417
417
  metrics.informationSpread += Number(
418
- result.shares || result.reshares || 0
418
+ result.shares || result.reshares || 0,
419
419
  );
420
420
  }
421
421
  }
@@ -456,7 +456,7 @@ export class TrajectoryMetricsExtractor {
456
456
  actionSuccessRate: 0,
457
457
  episodeLength: steps.length,
458
458
  actionTypesUsed: [],
459
- dominantActionType: '',
459
+ dominantActionType: "",
460
460
  };
461
461
 
462
462
  const actionTypeCounts = new Map<string, number>();
@@ -477,7 +477,7 @@ export class TrajectoryMetricsExtractor {
477
477
  // Count action types
478
478
  actionTypeCounts.set(
479
479
  actionType,
480
- (actionTypeCounts.get(actionType) || 0) + 1
480
+ (actionTypeCounts.get(actionType) || 0) + 1,
481
481
  );
482
482
 
483
483
  // Categorize actions
@@ -524,8 +524,7 @@ export class TrajectoryMetricsExtractor {
524
524
  const counts = Array.from(actionTypeCounts.values());
525
525
  const mean = counts.reduce((sum, c) => sum + c, 0) / counts.length;
526
526
  const variance =
527
- counts.reduce((sum, c) => sum + Math.pow(c - mean, 2), 0) /
528
- counts.length;
527
+ counts.reduce((sum, c) => sum + (c - mean) ** 2, 0) / counts.length;
529
528
  // Normalize to 0-1 range (higher = more consistent)
530
529
  metrics.consistencyScore = 1 / (1 + Math.sqrt(variance) / mean);
531
530
  } else {
@@ -539,7 +538,7 @@ export class TrajectoryMetricsExtractor {
539
538
  * Extract information gathering metrics
540
539
  */
541
540
  private extractInformationMetrics(
542
- steps: TrajectoryStep[]
541
+ steps: TrajectoryStep[],
543
542
  ): InformationMetrics {
544
543
  const metrics: InformationMetrics = {
545
544
  researchActions: 0,
@@ -558,21 +557,21 @@ export class TrajectoryMetricsExtractor {
558
557
 
559
558
  const actionType = action.actionType.toLowerCase();
560
559
 
561
- if (actionType === 'research' || actionType === 'analyze') {
560
+ if (actionType === "research" || actionType === "analyze") {
562
561
  metrics.researchActions++;
563
- } else if (actionType === 'read_news' || actionType === 'consume_news') {
562
+ } else if (actionType === "read_news" || actionType === "consume_news") {
564
563
  metrics.newsConsumed++;
565
564
  } else if (
566
- actionType === 'query_market' ||
567
- actionType === 'check_price' ||
568
- actionType === 'get_quote'
565
+ actionType === "query_market" ||
566
+ actionType === "check_price" ||
567
+ actionType === "get_quote"
569
568
  ) {
570
569
  metrics.marketDataQueries++;
571
- } else if (actionType === 'request_info' || actionType === 'ask') {
570
+ } else if (actionType === "request_info" || actionType === "ask") {
572
571
  metrics.infoRequestsSent++;
573
- } else if (actionType === 'share_info' || actionType === 'share') {
572
+ } else if (actionType === "share_info" || actionType === "share") {
574
573
  metrics.infoShared++;
575
- } else if (actionType === 'predict' || actionType === 'bet') {
574
+ } else if (actionType === "predict" || actionType === "bet") {
576
575
  metrics.predictionsMade++;
577
576
 
578
577
  // Check if prediction was correct
@@ -606,9 +605,9 @@ export class TrajectoryMetricsExtractor {
606
605
 
607
606
  if (!Array.isArray(steps) || steps.length === 0) {
608
607
  logger.warn(
609
- 'Invalid or empty steps array',
608
+ "Invalid or empty steps array",
610
609
  { trajectoryId: params.trajectoryId },
611
- 'MetricsExtractor'
610
+ "MetricsExtractor",
612
611
  );
613
612
  return null;
614
613
  }
@@ -635,12 +634,12 @@ export class TrajectoryMetricsExtractor {
635
634
  });
636
635
  } catch (error) {
637
636
  logger.error(
638
- 'Failed to extract metrics',
637
+ "Failed to extract metrics",
639
638
  {
640
639
  trajectoryId: params.trajectoryId,
641
640
  error: error instanceof Error ? error.message : String(error),
642
641
  },
643
- 'MetricsExtractor'
642
+ "MetricsExtractor",
644
643
  );
645
644
  return null;
646
645
  }