@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.d.mts +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +344 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +342 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|