@agent-e/core 1.3.1 → 1.4.0

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.mjs CHANGED
@@ -3528,6 +3528,12 @@ var AgentE = class {
3528
3528
  addPrinciple(principle) {
3529
3529
  this.diagnoser.addPrinciple(principle);
3530
3530
  }
3531
+ setMode(mode) {
3532
+ this.mode = mode;
3533
+ }
3534
+ getMode() {
3535
+ return this.mode;
3536
+ }
3531
3537
  removePrinciple(id) {
3532
3538
  this.diagnoser.removePrinciple(id);
3533
3539
  }
@@ -3587,6 +3593,340 @@ var AgentE = class {
3587
3593
  this.eventBuffer.push(event);
3588
3594
  }
3589
3595
  };
3596
+
3597
+ // src/StateValidator.ts
3598
+ function validateEconomyState(state) {
3599
+ const errors = [];
3600
+ const warnings = [];
3601
+ if (state === null || state === void 0 || typeof state !== "object") {
3602
+ errors.push({
3603
+ path: "",
3604
+ expected: "object",
3605
+ received: state === null ? "null" : typeof state,
3606
+ message: "State must be a non-null object"
3607
+ });
3608
+ return { valid: false, errors, warnings };
3609
+ }
3610
+ const s = state;
3611
+ if (!isNonNegativeInteger(s["tick"])) {
3612
+ errors.push({
3613
+ path: "tick",
3614
+ expected: "non-negative integer",
3615
+ received: describeValue(s["tick"]),
3616
+ message: "tick must be a non-negative integer"
3617
+ });
3618
+ }
3619
+ if (!isNonEmptyStringArray(s["roles"])) {
3620
+ errors.push({
3621
+ path: "roles",
3622
+ expected: "non-empty string[]",
3623
+ received: describeValue(s["roles"]),
3624
+ message: "roles must be a non-empty array of strings"
3625
+ });
3626
+ }
3627
+ const roles = new Set(Array.isArray(s["roles"]) ? s["roles"].filter((r) => typeof r === "string") : []);
3628
+ if (!isStringArray(s["resources"])) {
3629
+ errors.push({
3630
+ path: "resources",
3631
+ expected: "string[]",
3632
+ received: describeValue(s["resources"]),
3633
+ message: "resources must be an array of strings (can be empty)"
3634
+ });
3635
+ }
3636
+ const resources = new Set(Array.isArray(s["resources"]) ? s["resources"].filter((r) => typeof r === "string") : []);
3637
+ if (!isNonEmptyStringArray(s["currencies"])) {
3638
+ errors.push({
3639
+ path: "currencies",
3640
+ expected: "non-empty string[]",
3641
+ received: describeValue(s["currencies"]),
3642
+ message: "currencies must be a non-empty array of strings"
3643
+ });
3644
+ }
3645
+ const currencies = new Set(
3646
+ Array.isArray(s["currencies"]) ? s["currencies"].filter((r) => typeof r === "string") : []
3647
+ );
3648
+ if (isRecord(s["agentBalances"])) {
3649
+ const balances = s["agentBalances"];
3650
+ for (const [agentId, currencyMap] of Object.entries(balances)) {
3651
+ if (!isRecord(currencyMap)) {
3652
+ errors.push({
3653
+ path: `agentBalances.${agentId}`,
3654
+ expected: "Record<string, number>",
3655
+ received: describeValue(currencyMap),
3656
+ message: `agentBalances.${agentId} must be a Record<string, number>`
3657
+ });
3658
+ continue;
3659
+ }
3660
+ for (const [currency, value] of Object.entries(currencyMap)) {
3661
+ if (typeof value !== "number" || value < 0) {
3662
+ errors.push({
3663
+ path: `agentBalances.${agentId}.${currency}`,
3664
+ expected: "number >= 0",
3665
+ received: describeValue(value),
3666
+ message: `agentBalances.${agentId}.${currency} must be a non-negative number`
3667
+ });
3668
+ }
3669
+ if (currencies.size > 0 && !currencies.has(currency)) {
3670
+ errors.push({
3671
+ path: `agentBalances.${agentId}.${currency}`,
3672
+ expected: `one of [${[...currencies].join(", ")}]`,
3673
+ received: currency,
3674
+ message: `agentBalances currency key "${currency}" is not in currencies`
3675
+ });
3676
+ }
3677
+ }
3678
+ }
3679
+ } else {
3680
+ errors.push({
3681
+ path: "agentBalances",
3682
+ expected: "Record<string, Record<string, number>>",
3683
+ received: describeValue(s["agentBalances"]),
3684
+ message: "agentBalances must be a nested Record<string, Record<string, number>>"
3685
+ });
3686
+ }
3687
+ if (isRecord(s["agentRoles"])) {
3688
+ const agentRoles = s["agentRoles"];
3689
+ for (const [agentId, role] of Object.entries(agentRoles)) {
3690
+ if (typeof role !== "string") {
3691
+ errors.push({
3692
+ path: `agentRoles.${agentId}`,
3693
+ expected: "string",
3694
+ received: describeValue(role),
3695
+ message: `agentRoles.${agentId} must be a string`
3696
+ });
3697
+ } else if (roles.size > 0 && !roles.has(role)) {
3698
+ errors.push({
3699
+ path: `agentRoles.${agentId}`,
3700
+ expected: `one of [${[...roles].join(", ")}]`,
3701
+ received: role,
3702
+ message: `agentRoles value "${role}" is not in roles`
3703
+ });
3704
+ }
3705
+ }
3706
+ } else {
3707
+ errors.push({
3708
+ path: "agentRoles",
3709
+ expected: "Record<string, string>",
3710
+ received: describeValue(s["agentRoles"]),
3711
+ message: "agentRoles must be a Record<string, string>"
3712
+ });
3713
+ }
3714
+ if (isRecord(s["agentInventories"])) {
3715
+ const inventories = s["agentInventories"];
3716
+ for (const [agentId, inv] of Object.entries(inventories)) {
3717
+ if (!isRecord(inv)) {
3718
+ errors.push({
3719
+ path: `agentInventories.${agentId}`,
3720
+ expected: "Record<string, number>",
3721
+ received: describeValue(inv),
3722
+ message: `agentInventories.${agentId} must be a Record<string, number>`
3723
+ });
3724
+ continue;
3725
+ }
3726
+ for (const [resource, qty] of Object.entries(inv)) {
3727
+ if (typeof qty !== "number" || qty < 0) {
3728
+ errors.push({
3729
+ path: `agentInventories.${agentId}.${resource}`,
3730
+ expected: "number >= 0",
3731
+ received: describeValue(qty),
3732
+ message: `agentInventories.${agentId}.${resource} must be a non-negative number`
3733
+ });
3734
+ }
3735
+ }
3736
+ }
3737
+ } else {
3738
+ errors.push({
3739
+ path: "agentInventories",
3740
+ expected: "Record<string, Record<string, number>>",
3741
+ received: describeValue(s["agentInventories"]),
3742
+ message: "agentInventories must be a Record<string, Record<string, number>>"
3743
+ });
3744
+ }
3745
+ if (isRecord(s["marketPrices"])) {
3746
+ const marketPrices = s["marketPrices"];
3747
+ for (const [currency, resourcePrices] of Object.entries(marketPrices)) {
3748
+ if (currencies.size > 0 && !currencies.has(currency)) {
3749
+ errors.push({
3750
+ path: `marketPrices.${currency}`,
3751
+ expected: `one of [${[...currencies].join(", ")}]`,
3752
+ received: currency,
3753
+ message: `marketPrices outer key "${currency}" is not in currencies`
3754
+ });
3755
+ }
3756
+ if (!isRecord(resourcePrices)) {
3757
+ errors.push({
3758
+ path: `marketPrices.${currency}`,
3759
+ expected: "Record<string, number>",
3760
+ received: describeValue(resourcePrices),
3761
+ message: `marketPrices.${currency} must be a Record<string, number>`
3762
+ });
3763
+ continue;
3764
+ }
3765
+ for (const [resource, price] of Object.entries(resourcePrices)) {
3766
+ if (typeof price !== "number" || price < 0) {
3767
+ errors.push({
3768
+ path: `marketPrices.${currency}.${resource}`,
3769
+ expected: "number >= 0",
3770
+ received: describeValue(price),
3771
+ message: `marketPrices.${currency}.${resource} must be a non-negative number`
3772
+ });
3773
+ }
3774
+ }
3775
+ }
3776
+ } else {
3777
+ errors.push({
3778
+ path: "marketPrices",
3779
+ expected: "Record<string, Record<string, number>>",
3780
+ received: describeValue(s["marketPrices"]),
3781
+ message: "marketPrices must be a nested Record<string, Record<string, number>>"
3782
+ });
3783
+ }
3784
+ if (!Array.isArray(s["recentTransactions"])) {
3785
+ errors.push({
3786
+ path: "recentTransactions",
3787
+ expected: "array",
3788
+ received: describeValue(s["recentTransactions"]),
3789
+ message: "recentTransactions must be an array"
3790
+ });
3791
+ }
3792
+ if (s["agentSatisfaction"] !== void 0) {
3793
+ if (isRecord(s["agentSatisfaction"])) {
3794
+ const satisfaction = s["agentSatisfaction"];
3795
+ for (const [agentId, value] of Object.entries(satisfaction)) {
3796
+ if (typeof value !== "number" || value < 0 || value > 100) {
3797
+ errors.push({
3798
+ path: `agentSatisfaction.${agentId}`,
3799
+ expected: "number 0-100",
3800
+ received: describeValue(value),
3801
+ message: `agentSatisfaction.${agentId} must be a number between 0 and 100`
3802
+ });
3803
+ }
3804
+ }
3805
+ } else {
3806
+ errors.push({
3807
+ path: "agentSatisfaction",
3808
+ expected: "Record<string, number> | undefined",
3809
+ received: describeValue(s["agentSatisfaction"]),
3810
+ message: "agentSatisfaction must be a Record<string, number> if provided"
3811
+ });
3812
+ }
3813
+ }
3814
+ if (s["poolSizes"] !== void 0) {
3815
+ if (isRecord(s["poolSizes"])) {
3816
+ const pools = s["poolSizes"];
3817
+ for (const [currency, poolMap] of Object.entries(pools)) {
3818
+ if (!isRecord(poolMap)) {
3819
+ errors.push({
3820
+ path: `poolSizes.${currency}`,
3821
+ expected: "Record<string, number>",
3822
+ received: describeValue(poolMap),
3823
+ message: `poolSizes.${currency} must be a Record<string, number>`
3824
+ });
3825
+ continue;
3826
+ }
3827
+ for (const [poolName, size] of Object.entries(poolMap)) {
3828
+ if (typeof size !== "number" || size < 0) {
3829
+ errors.push({
3830
+ path: `poolSizes.${currency}.${poolName}`,
3831
+ expected: "number >= 0",
3832
+ received: describeValue(size),
3833
+ message: `poolSizes.${currency}.${poolName} must be a non-negative number`
3834
+ });
3835
+ }
3836
+ }
3837
+ }
3838
+ } else {
3839
+ errors.push({
3840
+ path: "poolSizes",
3841
+ expected: "Record<string, Record<string, number>> | undefined",
3842
+ received: describeValue(s["poolSizes"]),
3843
+ message: "poolSizes must be a nested Record if provided"
3844
+ });
3845
+ }
3846
+ }
3847
+ if (currencies.size > 0 && isRecord(s["agentBalances"])) {
3848
+ const heldCurrencies = /* @__PURE__ */ new Set();
3849
+ const balances = s["agentBalances"];
3850
+ for (const currencyMap of Object.values(balances)) {
3851
+ if (isRecord(currencyMap)) {
3852
+ for (const key of Object.keys(currencyMap)) {
3853
+ heldCurrencies.add(key);
3854
+ }
3855
+ }
3856
+ }
3857
+ for (const currency of currencies) {
3858
+ if (!heldCurrencies.has(currency)) {
3859
+ warnings.push({
3860
+ path: `currencies`,
3861
+ message: `Currency "${currency}" is declared but no agent holds it`
3862
+ });
3863
+ }
3864
+ }
3865
+ }
3866
+ if (isRecord(s["agentBalances"]) && isRecord(s["agentRoles"])) {
3867
+ const agentRoles = s["agentRoles"];
3868
+ const agentBalances = s["agentBalances"];
3869
+ for (const agentId of Object.keys(agentBalances)) {
3870
+ if (!(agentId in agentRoles)) {
3871
+ warnings.push({
3872
+ path: `agentBalances.${agentId}`,
3873
+ message: `Agent "${agentId}" has balances but no role assigned`
3874
+ });
3875
+ }
3876
+ }
3877
+ }
3878
+ if (resources.size === 0 && isRecord(s["agentInventories"])) {
3879
+ const inventories = s["agentInventories"];
3880
+ let hasItems = false;
3881
+ for (const inv of Object.values(inventories)) {
3882
+ if (isRecord(inv) && Object.keys(inv).length > 0) {
3883
+ hasItems = true;
3884
+ break;
3885
+ }
3886
+ }
3887
+ if (hasItems) {
3888
+ warnings.push({
3889
+ path: "resources",
3890
+ message: "resources is empty but agents have non-empty inventories"
3891
+ });
3892
+ }
3893
+ }
3894
+ if (Array.isArray(s["recentTransactions"]) && currencies.size > 0) {
3895
+ for (const event of s["recentTransactions"]) {
3896
+ if (isRecord(event)) {
3897
+ const e = event;
3898
+ if (typeof e["metadata"] === "object" && e["metadata"] !== null) {
3899
+ const meta = e["metadata"];
3900
+ if (typeof meta["currency"] === "string" && !currencies.has(meta["currency"])) {
3901
+ warnings.push({
3902
+ path: "recentTransactions",
3903
+ message: `Event references unknown currency "${meta["currency"]}"`
3904
+ });
3905
+ }
3906
+ }
3907
+ }
3908
+ }
3909
+ }
3910
+ return { valid: errors.length === 0, errors, warnings };
3911
+ }
3912
+ function isRecord(value) {
3913
+ return value !== null && typeof value === "object" && !Array.isArray(value);
3914
+ }
3915
+ function isStringArray(value) {
3916
+ return Array.isArray(value) && value.every((v) => typeof v === "string");
3917
+ }
3918
+ function isNonEmptyStringArray(value) {
3919
+ return isStringArray(value) && value.length > 0;
3920
+ }
3921
+ function isNonNegativeInteger(value) {
3922
+ return typeof value === "number" && Number.isInteger(value) && value >= 0;
3923
+ }
3924
+ function describeValue(value) {
3925
+ if (value === null) return "null";
3926
+ if (value === void 0) return "undefined";
3927
+ if (Array.isArray(value)) return `array(${value.length})`;
3928
+ return typeof value;
3929
+ }
3590
3930
  export {
3591
3931
  ALL_PRINCIPLES,
3592
3932
  AgentE,
@@ -3675,6 +4015,7 @@ export {
3675
4015
  SUPPLY_CHAIN_PRINCIPLES,
3676
4016
  SYSTEM_DYNAMICS_PRINCIPLES,
3677
4017
  Simulator,
3678
- emptyMetrics
4018
+ emptyMetrics,
4019
+ validateEconomyState
3679
4020
  };
3680
4021
  //# sourceMappingURL=index.mjs.map