@agent-e/core 1.3.2 → 1.4.4

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/index.d.mts CHANGED
@@ -372,6 +372,8 @@ declare class AgentE {
372
372
  max: number;
373
373
  }): void;
374
374
  addPrinciple(principle: Principle): void;
375
+ setMode(mode: AgentEMode): void;
376
+ getMode(): AgentEMode;
375
377
  removePrinciple(id: string): void;
376
378
  registerCustomMetric(name: string, fn: (state: EconomyState) => number): void;
377
379
  getDecisions(filter?: Parameters<DecisionLog['query']>[0]): DecisionEntry[];
@@ -474,6 +476,23 @@ declare class PersonaTracker {
474
476
  private classify;
475
477
  }
476
478
 
479
+ interface ValidationError {
480
+ path: string;
481
+ expected: string;
482
+ received: string;
483
+ message: string;
484
+ }
485
+ interface ValidationWarning {
486
+ path: string;
487
+ message: string;
488
+ }
489
+ interface ValidationResult {
490
+ valid: boolean;
491
+ errors: ValidationError[];
492
+ warnings: ValidationWarning[];
493
+ }
494
+ declare function validateEconomyState(state: unknown): ValidationResult;
495
+
477
496
  declare const DEFAULT_THRESHOLDS: Thresholds;
478
497
  declare const PERSONA_HEALTHY_RANGES: Record<string, {
479
498
  min: number;
@@ -573,4 +592,4 @@ declare const LIVEOPS_PRINCIPLES: Principle[];
573
592
  /** All 60 built-in principles in priority order (supply chain → liveops) */
574
593
  declare const ALL_PRINCIPLES: Principle[];
575
594
 
576
- export { ALL_PRINCIPLES, type ActionPlan, AgentE, type AgentEConfig, type AgentEMode, BOOTSTRAP_PRINCIPLES, CURRENCY_FLOW_PRINCIPLES, DEFAULT_THRESHOLDS, type DecisionEntry, DecisionLog, type DecisionResult, Diagnoser, type Diagnosis, type EconomicEvent, type EconomicEventType, type EconomyAdapter, type EconomyMetrics, type EconomyState, Executor, FEEDBACK_LOOP_PRINCIPLES, INCENTIVE_PRINCIPLES, LIVEOPS_PRINCIPLES, MARKET_DYNAMICS_PRINCIPLES, MEASUREMENT_PRINCIPLES, type MetricQuery, type MetricQueryResult, type MetricResolution, MetricStore, OPEN_ECONOMY_PRINCIPLES, Observer, P10_SpawnWeightingUsesInversePopulation, P11_TwoTierPressure, P12_OnePrimaryFaucet, P13_PotsAreZeroSumAndSelfRegulate, P14_TrackActualInjection, P15_PoolsNeedCapAndDecay, P16_WithdrawalPenaltyScales, P17_GracePeriodBeforeIntervention, P18_FirstProducerNeedsStartingInventory, P19_StartingSupplyExceedsDemand, P1_ProductionMatchesConsumption, P20_DecayPreventsAccumulation, P21_PriceFromGlobalSupply, P22_MarketAwarenessPreventsSurplus, P23_ProfitabilityFactorsFeasibility, P24_BlockedAgentsDecayFaster, P25_CorrectLeversForCorrectProblems, P26_ContinuousPressureBeatsThresholdCuts, P27_AdjustmentsNeedCooldowns, P28_StructuralDominanceIsNotPathological, P29_PinchPoint, P2_ClosedLoopsNeedDirectHandoff, P30_MovingPinchPoint, P31_AnchorValueTracking, P32_VelocityAboveSupply, P33_FairNotEqual, P34_ExtractionRatio, P35_DestructionCreatesValue, P36_MechanicFrictionDetector, P37_LatecommerProblem, P38_CommunicationPreventsRevolt, P39_TheLagPrinciple, P3_BootstrapCapitalCoversFirstTransaction, P40_ReplacementRate, P41_MultiResolutionMonitoring, P42_TheMedianPrinciple, P43_SimulationMinimum, P44_ComplexityBudget, P45_TimeBudget, P46_PersonaDiversity, P47_SmokeTest, P48_CurrencyInsulation, P49_IdleAssetTax, P4_MaterialsFlowFasterThanCooldown, P50_PayPowerRatio, P51_SharkTooth, P52_EndowmentEffect, P53_EventCompletionRate, P54_LiveOpsCadence, P55_ArbitrageThermometer, P56_ContentDropShock, P57_CombinatorialPriceSpace, P58_NoNaturalNumeraire, P59_GiftEconomyNoise, P5_ProfitabilityIsCompetitive, P60_SurplusDisposalAsymmetry, P6_CrowdingMultiplierOnAllRoles, P7_NonSpecialistsSubsidiseSpecialists, P8_RegulatorCannotFightDesign, P9_RoleSwitchingNeedsFriction, PERSONA_HEALTHY_RANGES, PLAYER_EXPERIENCE_PRINCIPLES, POPULATION_PRINCIPLES, type PersonaProfile, PersonaTracker, type PersonaType, type PinchPointStatus, Planner, type Principle, type PrincipleCategory, type PrincipleOk, type PrincipleResult, type PrincipleViolation, REGULATOR_PRINCIPLES, RESOURCE_MGMT_PRINCIPLES, type RollbackCondition, STATISTICAL_PRINCIPLES, SUPPLY_CHAIN_PRINCIPLES, SYSTEM_DYNAMICS_PRINCIPLES, type SimulationOutcome, type SimulationResult, Simulator, type SuggestedAction, type Thresholds, type TickConfig, emptyMetrics };
595
+ export { ALL_PRINCIPLES, type ActionPlan, AgentE, type AgentEConfig, type AgentEMode, BOOTSTRAP_PRINCIPLES, CURRENCY_FLOW_PRINCIPLES, DEFAULT_THRESHOLDS, type DecisionEntry, DecisionLog, type DecisionResult, Diagnoser, type Diagnosis, type EconomicEvent, type EconomicEventType, type EconomyAdapter, type EconomyMetrics, type EconomyState, Executor, FEEDBACK_LOOP_PRINCIPLES, INCENTIVE_PRINCIPLES, LIVEOPS_PRINCIPLES, MARKET_DYNAMICS_PRINCIPLES, MEASUREMENT_PRINCIPLES, type MetricQuery, type MetricQueryResult, type MetricResolution, MetricStore, OPEN_ECONOMY_PRINCIPLES, Observer, P10_SpawnWeightingUsesInversePopulation, P11_TwoTierPressure, P12_OnePrimaryFaucet, P13_PotsAreZeroSumAndSelfRegulate, P14_TrackActualInjection, P15_PoolsNeedCapAndDecay, P16_WithdrawalPenaltyScales, P17_GracePeriodBeforeIntervention, P18_FirstProducerNeedsStartingInventory, P19_StartingSupplyExceedsDemand, P1_ProductionMatchesConsumption, P20_DecayPreventsAccumulation, P21_PriceFromGlobalSupply, P22_MarketAwarenessPreventsSurplus, P23_ProfitabilityFactorsFeasibility, P24_BlockedAgentsDecayFaster, P25_CorrectLeversForCorrectProblems, P26_ContinuousPressureBeatsThresholdCuts, P27_AdjustmentsNeedCooldowns, P28_StructuralDominanceIsNotPathological, P29_PinchPoint, P2_ClosedLoopsNeedDirectHandoff, P30_MovingPinchPoint, P31_AnchorValueTracking, P32_VelocityAboveSupply, P33_FairNotEqual, P34_ExtractionRatio, P35_DestructionCreatesValue, P36_MechanicFrictionDetector, P37_LatecommerProblem, P38_CommunicationPreventsRevolt, P39_TheLagPrinciple, P3_BootstrapCapitalCoversFirstTransaction, P40_ReplacementRate, P41_MultiResolutionMonitoring, P42_TheMedianPrinciple, P43_SimulationMinimum, P44_ComplexityBudget, P45_TimeBudget, P46_PersonaDiversity, P47_SmokeTest, P48_CurrencyInsulation, P49_IdleAssetTax, P4_MaterialsFlowFasterThanCooldown, P50_PayPowerRatio, P51_SharkTooth, P52_EndowmentEffect, P53_EventCompletionRate, P54_LiveOpsCadence, P55_ArbitrageThermometer, P56_ContentDropShock, P57_CombinatorialPriceSpace, P58_NoNaturalNumeraire, P59_GiftEconomyNoise, P5_ProfitabilityIsCompetitive, P60_SurplusDisposalAsymmetry, P6_CrowdingMultiplierOnAllRoles, P7_NonSpecialistsSubsidiseSpecialists, P8_RegulatorCannotFightDesign, P9_RoleSwitchingNeedsFriction, PERSONA_HEALTHY_RANGES, PLAYER_EXPERIENCE_PRINCIPLES, POPULATION_PRINCIPLES, type PersonaProfile, PersonaTracker, type PersonaType, type PinchPointStatus, Planner, type Principle, type PrincipleCategory, type PrincipleOk, type PrincipleResult, type PrincipleViolation, REGULATOR_PRINCIPLES, RESOURCE_MGMT_PRINCIPLES, type RollbackCondition, STATISTICAL_PRINCIPLES, SUPPLY_CHAIN_PRINCIPLES, SYSTEM_DYNAMICS_PRINCIPLES, type SimulationOutcome, type SimulationResult, Simulator, type SuggestedAction, type Thresholds, type TickConfig, type ValidationError, type ValidationResult, type ValidationWarning, emptyMetrics, validateEconomyState };
package/dist/index.d.ts CHANGED
@@ -372,6 +372,8 @@ declare class AgentE {
372
372
  max: number;
373
373
  }): void;
374
374
  addPrinciple(principle: Principle): void;
375
+ setMode(mode: AgentEMode): void;
376
+ getMode(): AgentEMode;
375
377
  removePrinciple(id: string): void;
376
378
  registerCustomMetric(name: string, fn: (state: EconomyState) => number): void;
377
379
  getDecisions(filter?: Parameters<DecisionLog['query']>[0]): DecisionEntry[];
@@ -474,6 +476,23 @@ declare class PersonaTracker {
474
476
  private classify;
475
477
  }
476
478
 
479
+ interface ValidationError {
480
+ path: string;
481
+ expected: string;
482
+ received: string;
483
+ message: string;
484
+ }
485
+ interface ValidationWarning {
486
+ path: string;
487
+ message: string;
488
+ }
489
+ interface ValidationResult {
490
+ valid: boolean;
491
+ errors: ValidationError[];
492
+ warnings: ValidationWarning[];
493
+ }
494
+ declare function validateEconomyState(state: unknown): ValidationResult;
495
+
477
496
  declare const DEFAULT_THRESHOLDS: Thresholds;
478
497
  declare const PERSONA_HEALTHY_RANGES: Record<string, {
479
498
  min: number;
@@ -573,4 +592,4 @@ declare const LIVEOPS_PRINCIPLES: Principle[];
573
592
  /** All 60 built-in principles in priority order (supply chain → liveops) */
574
593
  declare const ALL_PRINCIPLES: Principle[];
575
594
 
576
- export { ALL_PRINCIPLES, type ActionPlan, AgentE, type AgentEConfig, type AgentEMode, BOOTSTRAP_PRINCIPLES, CURRENCY_FLOW_PRINCIPLES, DEFAULT_THRESHOLDS, type DecisionEntry, DecisionLog, type DecisionResult, Diagnoser, type Diagnosis, type EconomicEvent, type EconomicEventType, type EconomyAdapter, type EconomyMetrics, type EconomyState, Executor, FEEDBACK_LOOP_PRINCIPLES, INCENTIVE_PRINCIPLES, LIVEOPS_PRINCIPLES, MARKET_DYNAMICS_PRINCIPLES, MEASUREMENT_PRINCIPLES, type MetricQuery, type MetricQueryResult, type MetricResolution, MetricStore, OPEN_ECONOMY_PRINCIPLES, Observer, P10_SpawnWeightingUsesInversePopulation, P11_TwoTierPressure, P12_OnePrimaryFaucet, P13_PotsAreZeroSumAndSelfRegulate, P14_TrackActualInjection, P15_PoolsNeedCapAndDecay, P16_WithdrawalPenaltyScales, P17_GracePeriodBeforeIntervention, P18_FirstProducerNeedsStartingInventory, P19_StartingSupplyExceedsDemand, P1_ProductionMatchesConsumption, P20_DecayPreventsAccumulation, P21_PriceFromGlobalSupply, P22_MarketAwarenessPreventsSurplus, P23_ProfitabilityFactorsFeasibility, P24_BlockedAgentsDecayFaster, P25_CorrectLeversForCorrectProblems, P26_ContinuousPressureBeatsThresholdCuts, P27_AdjustmentsNeedCooldowns, P28_StructuralDominanceIsNotPathological, P29_PinchPoint, P2_ClosedLoopsNeedDirectHandoff, P30_MovingPinchPoint, P31_AnchorValueTracking, P32_VelocityAboveSupply, P33_FairNotEqual, P34_ExtractionRatio, P35_DestructionCreatesValue, P36_MechanicFrictionDetector, P37_LatecommerProblem, P38_CommunicationPreventsRevolt, P39_TheLagPrinciple, P3_BootstrapCapitalCoversFirstTransaction, P40_ReplacementRate, P41_MultiResolutionMonitoring, P42_TheMedianPrinciple, P43_SimulationMinimum, P44_ComplexityBudget, P45_TimeBudget, P46_PersonaDiversity, P47_SmokeTest, P48_CurrencyInsulation, P49_IdleAssetTax, P4_MaterialsFlowFasterThanCooldown, P50_PayPowerRatio, P51_SharkTooth, P52_EndowmentEffect, P53_EventCompletionRate, P54_LiveOpsCadence, P55_ArbitrageThermometer, P56_ContentDropShock, P57_CombinatorialPriceSpace, P58_NoNaturalNumeraire, P59_GiftEconomyNoise, P5_ProfitabilityIsCompetitive, P60_SurplusDisposalAsymmetry, P6_CrowdingMultiplierOnAllRoles, P7_NonSpecialistsSubsidiseSpecialists, P8_RegulatorCannotFightDesign, P9_RoleSwitchingNeedsFriction, PERSONA_HEALTHY_RANGES, PLAYER_EXPERIENCE_PRINCIPLES, POPULATION_PRINCIPLES, type PersonaProfile, PersonaTracker, type PersonaType, type PinchPointStatus, Planner, type Principle, type PrincipleCategory, type PrincipleOk, type PrincipleResult, type PrincipleViolation, REGULATOR_PRINCIPLES, RESOURCE_MGMT_PRINCIPLES, type RollbackCondition, STATISTICAL_PRINCIPLES, SUPPLY_CHAIN_PRINCIPLES, SYSTEM_DYNAMICS_PRINCIPLES, type SimulationOutcome, type SimulationResult, Simulator, type SuggestedAction, type Thresholds, type TickConfig, emptyMetrics };
595
+ export { ALL_PRINCIPLES, type ActionPlan, AgentE, type AgentEConfig, type AgentEMode, BOOTSTRAP_PRINCIPLES, CURRENCY_FLOW_PRINCIPLES, DEFAULT_THRESHOLDS, type DecisionEntry, DecisionLog, type DecisionResult, Diagnoser, type Diagnosis, type EconomicEvent, type EconomicEventType, type EconomyAdapter, type EconomyMetrics, type EconomyState, Executor, FEEDBACK_LOOP_PRINCIPLES, INCENTIVE_PRINCIPLES, LIVEOPS_PRINCIPLES, MARKET_DYNAMICS_PRINCIPLES, MEASUREMENT_PRINCIPLES, type MetricQuery, type MetricQueryResult, type MetricResolution, MetricStore, OPEN_ECONOMY_PRINCIPLES, Observer, P10_SpawnWeightingUsesInversePopulation, P11_TwoTierPressure, P12_OnePrimaryFaucet, P13_PotsAreZeroSumAndSelfRegulate, P14_TrackActualInjection, P15_PoolsNeedCapAndDecay, P16_WithdrawalPenaltyScales, P17_GracePeriodBeforeIntervention, P18_FirstProducerNeedsStartingInventory, P19_StartingSupplyExceedsDemand, P1_ProductionMatchesConsumption, P20_DecayPreventsAccumulation, P21_PriceFromGlobalSupply, P22_MarketAwarenessPreventsSurplus, P23_ProfitabilityFactorsFeasibility, P24_BlockedAgentsDecayFaster, P25_CorrectLeversForCorrectProblems, P26_ContinuousPressureBeatsThresholdCuts, P27_AdjustmentsNeedCooldowns, P28_StructuralDominanceIsNotPathological, P29_PinchPoint, P2_ClosedLoopsNeedDirectHandoff, P30_MovingPinchPoint, P31_AnchorValueTracking, P32_VelocityAboveSupply, P33_FairNotEqual, P34_ExtractionRatio, P35_DestructionCreatesValue, P36_MechanicFrictionDetector, P37_LatecommerProblem, P38_CommunicationPreventsRevolt, P39_TheLagPrinciple, P3_BootstrapCapitalCoversFirstTransaction, P40_ReplacementRate, P41_MultiResolutionMonitoring, P42_TheMedianPrinciple, P43_SimulationMinimum, P44_ComplexityBudget, P45_TimeBudget, P46_PersonaDiversity, P47_SmokeTest, P48_CurrencyInsulation, P49_IdleAssetTax, P4_MaterialsFlowFasterThanCooldown, P50_PayPowerRatio, P51_SharkTooth, P52_EndowmentEffect, P53_EventCompletionRate, P54_LiveOpsCadence, P55_ArbitrageThermometer, P56_ContentDropShock, P57_CombinatorialPriceSpace, P58_NoNaturalNumeraire, P59_GiftEconomyNoise, P5_ProfitabilityIsCompetitive, P60_SurplusDisposalAsymmetry, P6_CrowdingMultiplierOnAllRoles, P7_NonSpecialistsSubsidiseSpecialists, P8_RegulatorCannotFightDesign, P9_RoleSwitchingNeedsFriction, PERSONA_HEALTHY_RANGES, PLAYER_EXPERIENCE_PRINCIPLES, POPULATION_PRINCIPLES, type PersonaProfile, PersonaTracker, type PersonaType, type PinchPointStatus, Planner, type Principle, type PrincipleCategory, type PrincipleOk, type PrincipleResult, type PrincipleViolation, REGULATOR_PRINCIPLES, RESOURCE_MGMT_PRINCIPLES, type RollbackCondition, STATISTICAL_PRINCIPLES, SUPPLY_CHAIN_PRINCIPLES, SYSTEM_DYNAMICS_PRINCIPLES, type SimulationOutcome, type SimulationResult, Simulator, type SuggestedAction, type Thresholds, type TickConfig, type ValidationError, type ValidationResult, type ValidationWarning, emptyMetrics, validateEconomyState };
package/dist/index.js CHANGED
@@ -107,7 +107,8 @@ __export(index_exports, {
107
107
  SUPPLY_CHAIN_PRINCIPLES: () => SUPPLY_CHAIN_PRINCIPLES,
108
108
  SYSTEM_DYNAMICS_PRINCIPLES: () => SYSTEM_DYNAMICS_PRINCIPLES,
109
109
  Simulator: () => Simulator,
110
- emptyMetrics: () => emptyMetrics
110
+ emptyMetrics: () => emptyMetrics,
111
+ validateEconomyState: () => validateEconomyState
111
112
  });
112
113
  module.exports = __toCommonJS(index_exports);
113
114
 
@@ -3641,6 +3642,12 @@ var AgentE = class {
3641
3642
  addPrinciple(principle) {
3642
3643
  this.diagnoser.addPrinciple(principle);
3643
3644
  }
3645
+ setMode(mode) {
3646
+ this.mode = mode;
3647
+ }
3648
+ getMode() {
3649
+ return this.mode;
3650
+ }
3644
3651
  removePrinciple(id) {
3645
3652
  this.diagnoser.removePrinciple(id);
3646
3653
  }
@@ -3700,6 +3707,340 @@ var AgentE = class {
3700
3707
  this.eventBuffer.push(event);
3701
3708
  }
3702
3709
  };
3710
+
3711
+ // src/StateValidator.ts
3712
+ function validateEconomyState(state) {
3713
+ const errors = [];
3714
+ const warnings = [];
3715
+ if (state === null || state === void 0 || typeof state !== "object") {
3716
+ errors.push({
3717
+ path: "",
3718
+ expected: "object",
3719
+ received: state === null ? "null" : typeof state,
3720
+ message: "State must be a non-null object"
3721
+ });
3722
+ return { valid: false, errors, warnings };
3723
+ }
3724
+ const s = state;
3725
+ if (!isNonNegativeInteger(s["tick"])) {
3726
+ errors.push({
3727
+ path: "tick",
3728
+ expected: "non-negative integer",
3729
+ received: describeValue(s["tick"]),
3730
+ message: "tick must be a non-negative integer"
3731
+ });
3732
+ }
3733
+ if (!isNonEmptyStringArray(s["roles"])) {
3734
+ errors.push({
3735
+ path: "roles",
3736
+ expected: "non-empty string[]",
3737
+ received: describeValue(s["roles"]),
3738
+ message: "roles must be a non-empty array of strings"
3739
+ });
3740
+ }
3741
+ const roles = new Set(Array.isArray(s["roles"]) ? s["roles"].filter((r) => typeof r === "string") : []);
3742
+ if (!isStringArray(s["resources"])) {
3743
+ errors.push({
3744
+ path: "resources",
3745
+ expected: "string[]",
3746
+ received: describeValue(s["resources"]),
3747
+ message: "resources must be an array of strings (can be empty)"
3748
+ });
3749
+ }
3750
+ const resources = new Set(Array.isArray(s["resources"]) ? s["resources"].filter((r) => typeof r === "string") : []);
3751
+ if (!isNonEmptyStringArray(s["currencies"])) {
3752
+ errors.push({
3753
+ path: "currencies",
3754
+ expected: "non-empty string[]",
3755
+ received: describeValue(s["currencies"]),
3756
+ message: "currencies must be a non-empty array of strings"
3757
+ });
3758
+ }
3759
+ const currencies = new Set(
3760
+ Array.isArray(s["currencies"]) ? s["currencies"].filter((r) => typeof r === "string") : []
3761
+ );
3762
+ if (isRecord(s["agentBalances"])) {
3763
+ const balances = s["agentBalances"];
3764
+ for (const [agentId, currencyMap] of Object.entries(balances)) {
3765
+ if (!isRecord(currencyMap)) {
3766
+ errors.push({
3767
+ path: `agentBalances.${agentId}`,
3768
+ expected: "Record<string, number>",
3769
+ received: describeValue(currencyMap),
3770
+ message: `agentBalances.${agentId} must be a Record<string, number>`
3771
+ });
3772
+ continue;
3773
+ }
3774
+ for (const [currency, value] of Object.entries(currencyMap)) {
3775
+ if (typeof value !== "number" || value < 0) {
3776
+ errors.push({
3777
+ path: `agentBalances.${agentId}.${currency}`,
3778
+ expected: "number >= 0",
3779
+ received: describeValue(value),
3780
+ message: `agentBalances.${agentId}.${currency} must be a non-negative number`
3781
+ });
3782
+ }
3783
+ if (currencies.size > 0 && !currencies.has(currency)) {
3784
+ errors.push({
3785
+ path: `agentBalances.${agentId}.${currency}`,
3786
+ expected: `one of [${[...currencies].join(", ")}]`,
3787
+ received: currency,
3788
+ message: `agentBalances currency key "${currency}" is not in currencies`
3789
+ });
3790
+ }
3791
+ }
3792
+ }
3793
+ } else {
3794
+ errors.push({
3795
+ path: "agentBalances",
3796
+ expected: "Record<string, Record<string, number>>",
3797
+ received: describeValue(s["agentBalances"]),
3798
+ message: "agentBalances must be a nested Record<string, Record<string, number>>"
3799
+ });
3800
+ }
3801
+ if (isRecord(s["agentRoles"])) {
3802
+ const agentRoles = s["agentRoles"];
3803
+ for (const [agentId, role] of Object.entries(agentRoles)) {
3804
+ if (typeof role !== "string") {
3805
+ errors.push({
3806
+ path: `agentRoles.${agentId}`,
3807
+ expected: "string",
3808
+ received: describeValue(role),
3809
+ message: `agentRoles.${agentId} must be a string`
3810
+ });
3811
+ } else if (roles.size > 0 && !roles.has(role)) {
3812
+ errors.push({
3813
+ path: `agentRoles.${agentId}`,
3814
+ expected: `one of [${[...roles].join(", ")}]`,
3815
+ received: role,
3816
+ message: `agentRoles value "${role}" is not in roles`
3817
+ });
3818
+ }
3819
+ }
3820
+ } else {
3821
+ errors.push({
3822
+ path: "agentRoles",
3823
+ expected: "Record<string, string>",
3824
+ received: describeValue(s["agentRoles"]),
3825
+ message: "agentRoles must be a Record<string, string>"
3826
+ });
3827
+ }
3828
+ if (isRecord(s["agentInventories"])) {
3829
+ const inventories = s["agentInventories"];
3830
+ for (const [agentId, inv] of Object.entries(inventories)) {
3831
+ if (!isRecord(inv)) {
3832
+ errors.push({
3833
+ path: `agentInventories.${agentId}`,
3834
+ expected: "Record<string, number>",
3835
+ received: describeValue(inv),
3836
+ message: `agentInventories.${agentId} must be a Record<string, number>`
3837
+ });
3838
+ continue;
3839
+ }
3840
+ for (const [resource, qty] of Object.entries(inv)) {
3841
+ if (typeof qty !== "number" || qty < 0) {
3842
+ errors.push({
3843
+ path: `agentInventories.${agentId}.${resource}`,
3844
+ expected: "number >= 0",
3845
+ received: describeValue(qty),
3846
+ message: `agentInventories.${agentId}.${resource} must be a non-negative number`
3847
+ });
3848
+ }
3849
+ }
3850
+ }
3851
+ } else {
3852
+ errors.push({
3853
+ path: "agentInventories",
3854
+ expected: "Record<string, Record<string, number>>",
3855
+ received: describeValue(s["agentInventories"]),
3856
+ message: "agentInventories must be a Record<string, Record<string, number>>"
3857
+ });
3858
+ }
3859
+ if (isRecord(s["marketPrices"])) {
3860
+ const marketPrices = s["marketPrices"];
3861
+ for (const [currency, resourcePrices] of Object.entries(marketPrices)) {
3862
+ if (currencies.size > 0 && !currencies.has(currency)) {
3863
+ errors.push({
3864
+ path: `marketPrices.${currency}`,
3865
+ expected: `one of [${[...currencies].join(", ")}]`,
3866
+ received: currency,
3867
+ message: `marketPrices outer key "${currency}" is not in currencies`
3868
+ });
3869
+ }
3870
+ if (!isRecord(resourcePrices)) {
3871
+ errors.push({
3872
+ path: `marketPrices.${currency}`,
3873
+ expected: "Record<string, number>",
3874
+ received: describeValue(resourcePrices),
3875
+ message: `marketPrices.${currency} must be a Record<string, number>`
3876
+ });
3877
+ continue;
3878
+ }
3879
+ for (const [resource, price] of Object.entries(resourcePrices)) {
3880
+ if (typeof price !== "number" || price < 0) {
3881
+ errors.push({
3882
+ path: `marketPrices.${currency}.${resource}`,
3883
+ expected: "number >= 0",
3884
+ received: describeValue(price),
3885
+ message: `marketPrices.${currency}.${resource} must be a non-negative number`
3886
+ });
3887
+ }
3888
+ }
3889
+ }
3890
+ } else {
3891
+ errors.push({
3892
+ path: "marketPrices",
3893
+ expected: "Record<string, Record<string, number>>",
3894
+ received: describeValue(s["marketPrices"]),
3895
+ message: "marketPrices must be a nested Record<string, Record<string, number>>"
3896
+ });
3897
+ }
3898
+ if (!Array.isArray(s["recentTransactions"])) {
3899
+ errors.push({
3900
+ path: "recentTransactions",
3901
+ expected: "array",
3902
+ received: describeValue(s["recentTransactions"]),
3903
+ message: "recentTransactions must be an array"
3904
+ });
3905
+ }
3906
+ if (s["agentSatisfaction"] !== void 0) {
3907
+ if (isRecord(s["agentSatisfaction"])) {
3908
+ const satisfaction = s["agentSatisfaction"];
3909
+ for (const [agentId, value] of Object.entries(satisfaction)) {
3910
+ if (typeof value !== "number" || value < 0 || value > 100) {
3911
+ errors.push({
3912
+ path: `agentSatisfaction.${agentId}`,
3913
+ expected: "number 0-100",
3914
+ received: describeValue(value),
3915
+ message: `agentSatisfaction.${agentId} must be a number between 0 and 100`
3916
+ });
3917
+ }
3918
+ }
3919
+ } else {
3920
+ errors.push({
3921
+ path: "agentSatisfaction",
3922
+ expected: "Record<string, number> | undefined",
3923
+ received: describeValue(s["agentSatisfaction"]),
3924
+ message: "agentSatisfaction must be a Record<string, number> if provided"
3925
+ });
3926
+ }
3927
+ }
3928
+ if (s["poolSizes"] !== void 0) {
3929
+ if (isRecord(s["poolSizes"])) {
3930
+ const pools = s["poolSizes"];
3931
+ for (const [currency, poolMap] of Object.entries(pools)) {
3932
+ if (!isRecord(poolMap)) {
3933
+ errors.push({
3934
+ path: `poolSizes.${currency}`,
3935
+ expected: "Record<string, number>",
3936
+ received: describeValue(poolMap),
3937
+ message: `poolSizes.${currency} must be a Record<string, number>`
3938
+ });
3939
+ continue;
3940
+ }
3941
+ for (const [poolName, size] of Object.entries(poolMap)) {
3942
+ if (typeof size !== "number" || size < 0) {
3943
+ errors.push({
3944
+ path: `poolSizes.${currency}.${poolName}`,
3945
+ expected: "number >= 0",
3946
+ received: describeValue(size),
3947
+ message: `poolSizes.${currency}.${poolName} must be a non-negative number`
3948
+ });
3949
+ }
3950
+ }
3951
+ }
3952
+ } else {
3953
+ errors.push({
3954
+ path: "poolSizes",
3955
+ expected: "Record<string, Record<string, number>> | undefined",
3956
+ received: describeValue(s["poolSizes"]),
3957
+ message: "poolSizes must be a nested Record if provided"
3958
+ });
3959
+ }
3960
+ }
3961
+ if (currencies.size > 0 && isRecord(s["agentBalances"])) {
3962
+ const heldCurrencies = /* @__PURE__ */ new Set();
3963
+ const balances = s["agentBalances"];
3964
+ for (const currencyMap of Object.values(balances)) {
3965
+ if (isRecord(currencyMap)) {
3966
+ for (const key of Object.keys(currencyMap)) {
3967
+ heldCurrencies.add(key);
3968
+ }
3969
+ }
3970
+ }
3971
+ for (const currency of currencies) {
3972
+ if (!heldCurrencies.has(currency)) {
3973
+ warnings.push({
3974
+ path: `currencies`,
3975
+ message: `Currency "${currency}" is declared but no agent holds it`
3976
+ });
3977
+ }
3978
+ }
3979
+ }
3980
+ if (isRecord(s["agentBalances"]) && isRecord(s["agentRoles"])) {
3981
+ const agentRoles = s["agentRoles"];
3982
+ const agentBalances = s["agentBalances"];
3983
+ for (const agentId of Object.keys(agentBalances)) {
3984
+ if (!(agentId in agentRoles)) {
3985
+ warnings.push({
3986
+ path: `agentBalances.${agentId}`,
3987
+ message: `Agent "${agentId}" has balances but no role assigned`
3988
+ });
3989
+ }
3990
+ }
3991
+ }
3992
+ if (resources.size === 0 && isRecord(s["agentInventories"])) {
3993
+ const inventories = s["agentInventories"];
3994
+ let hasItems = false;
3995
+ for (const inv of Object.values(inventories)) {
3996
+ if (isRecord(inv) && Object.keys(inv).length > 0) {
3997
+ hasItems = true;
3998
+ break;
3999
+ }
4000
+ }
4001
+ if (hasItems) {
4002
+ warnings.push({
4003
+ path: "resources",
4004
+ message: "resources is empty but agents have non-empty inventories"
4005
+ });
4006
+ }
4007
+ }
4008
+ if (Array.isArray(s["recentTransactions"]) && currencies.size > 0) {
4009
+ for (const event of s["recentTransactions"]) {
4010
+ if (isRecord(event)) {
4011
+ const e = event;
4012
+ if (typeof e["metadata"] === "object" && e["metadata"] !== null) {
4013
+ const meta = e["metadata"];
4014
+ if (typeof meta["currency"] === "string" && !currencies.has(meta["currency"])) {
4015
+ warnings.push({
4016
+ path: "recentTransactions",
4017
+ message: `Event references unknown currency "${meta["currency"]}"`
4018
+ });
4019
+ }
4020
+ }
4021
+ }
4022
+ }
4023
+ }
4024
+ return { valid: errors.length === 0, errors, warnings };
4025
+ }
4026
+ function isRecord(value) {
4027
+ return value !== null && typeof value === "object" && !Array.isArray(value);
4028
+ }
4029
+ function isStringArray(value) {
4030
+ return Array.isArray(value) && value.every((v) => typeof v === "string");
4031
+ }
4032
+ function isNonEmptyStringArray(value) {
4033
+ return isStringArray(value) && value.length > 0;
4034
+ }
4035
+ function isNonNegativeInteger(value) {
4036
+ return typeof value === "number" && Number.isInteger(value) && value >= 0;
4037
+ }
4038
+ function describeValue(value) {
4039
+ if (value === null) return "null";
4040
+ if (value === void 0) return "undefined";
4041
+ if (Array.isArray(value)) return `array(${value.length})`;
4042
+ return typeof value;
4043
+ }
3703
4044
  // Annotate the CommonJS export names for ESM import in node:
3704
4045
  0 && (module.exports = {
3705
4046
  ALL_PRINCIPLES,
@@ -3789,6 +4130,7 @@ var AgentE = class {
3789
4130
  SUPPLY_CHAIN_PRINCIPLES,
3790
4131
  SYSTEM_DYNAMICS_PRINCIPLES,
3791
4132
  Simulator,
3792
- emptyMetrics
4133
+ emptyMetrics,
4134
+ validateEconomyState
3793
4135
  });
3794
4136
  //# sourceMappingURL=index.js.map