paygate-mcp 10.12.0 → 10.13.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/dynamic-pricing.d.ts +144 -0
- package/dist/dynamic-pricing.d.ts.map +1 -0
- package/dist/dynamic-pricing.js +250 -0
- package/dist/dynamic-pricing.js.map +1 -0
- package/dist/event-ledger.d.ts +116 -0
- package/dist/event-ledger.d.ts.map +1 -0
- package/dist/event-ledger.js +203 -0
- package/dist/event-ledger.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/key-scoping.d.ts +124 -0
- package/dist/key-scoping.d.ts.map +1 -0
- package/dist/key-scoping.js +287 -0
- package/dist/key-scoping.js.map +1 -0
- package/dist/quota-rollover.d.ts +128 -0
- package/dist/quota-rollover.d.ts.map +1 -0
- package/dist/quota-rollover.js +231 -0
- package/dist/quota-rollover.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DynamicPricingEngine — Adjust tool pricing based on demand, time, and usage.
|
|
3
|
+
*
|
|
4
|
+
* Supports time-of-day multipliers, demand-based surge pricing,
|
|
5
|
+
* volume discounts, and per-key custom pricing. All pricing rules
|
|
6
|
+
* are composable and evaluated in priority order.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const engine = new DynamicPricingEngine();
|
|
11
|
+
*
|
|
12
|
+
* engine.setBasePrice('search', 10);
|
|
13
|
+
*
|
|
14
|
+
* engine.addRule({
|
|
15
|
+
* tool: 'search',
|
|
16
|
+
* type: 'time_of_day',
|
|
17
|
+
* config: { peakHours: [9,10,11,12,13,14,15,16,17], multiplier: 1.5 },
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* const price = engine.getPrice('search');
|
|
21
|
+
* // 15 during peak hours, 10 otherwise
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export type PricingRuleType = 'time_of_day' | 'demand' | 'volume_discount' | 'key_override' | 'custom';
|
|
25
|
+
export interface TimeOfDayConfig {
|
|
26
|
+
/** Hours (0-23) considered peak. */
|
|
27
|
+
peakHours: number[];
|
|
28
|
+
/** Multiplier during peak hours. */
|
|
29
|
+
multiplier: number;
|
|
30
|
+
}
|
|
31
|
+
export interface DemandConfig {
|
|
32
|
+
/** Calls in the window that trigger surge. */
|
|
33
|
+
threshold: number;
|
|
34
|
+
/** Time window in seconds. */
|
|
35
|
+
windowSeconds: number;
|
|
36
|
+
/** Max multiplier at full surge. */
|
|
37
|
+
maxMultiplier: number;
|
|
38
|
+
}
|
|
39
|
+
export interface VolumeDiscountConfig {
|
|
40
|
+
/** Tiers: [{ minCalls, discount }] — discount is 0-1 (e.g., 0.2 = 20% off). */
|
|
41
|
+
tiers: {
|
|
42
|
+
minCalls: number;
|
|
43
|
+
discount: number;
|
|
44
|
+
}[];
|
|
45
|
+
}
|
|
46
|
+
export interface KeyOverrideConfig {
|
|
47
|
+
/** Key → fixed price. */
|
|
48
|
+
keyPrices: Map<string, number>;
|
|
49
|
+
}
|
|
50
|
+
export interface CustomRuleConfig {
|
|
51
|
+
/** Custom function: (basePrice, context) => adjustedPrice. */
|
|
52
|
+
fn: (basePrice: number, context: PricingContext) => number;
|
|
53
|
+
}
|
|
54
|
+
export type PricingRuleConfig = TimeOfDayConfig | DemandConfig | VolumeDiscountConfig | KeyOverrideConfig | CustomRuleConfig;
|
|
55
|
+
export interface PricingRule {
|
|
56
|
+
id: string;
|
|
57
|
+
tool: string;
|
|
58
|
+
type: PricingRuleType;
|
|
59
|
+
config: PricingRuleConfig;
|
|
60
|
+
/** Higher priority rules evaluated first. Default 0. */
|
|
61
|
+
priority: number;
|
|
62
|
+
enabled: boolean;
|
|
63
|
+
createdAt: number;
|
|
64
|
+
}
|
|
65
|
+
export interface PricingRuleRegistration {
|
|
66
|
+
tool: string;
|
|
67
|
+
type: PricingRuleType;
|
|
68
|
+
config: PricingRuleConfig;
|
|
69
|
+
priority?: number;
|
|
70
|
+
}
|
|
71
|
+
export interface PricingContext {
|
|
72
|
+
tool: string;
|
|
73
|
+
key?: string;
|
|
74
|
+
timestamp: number;
|
|
75
|
+
recentCalls: number;
|
|
76
|
+
totalCalls: number;
|
|
77
|
+
}
|
|
78
|
+
export interface PriceResult {
|
|
79
|
+
tool: string;
|
|
80
|
+
basePrice: number;
|
|
81
|
+
finalPrice: number;
|
|
82
|
+
appliedRules: string[];
|
|
83
|
+
multiplier: number;
|
|
84
|
+
}
|
|
85
|
+
export interface DynamicPricingConfig {
|
|
86
|
+
/** Default base price for tools without explicit pricing. */
|
|
87
|
+
defaultBasePrice?: number;
|
|
88
|
+
/** Window for demand tracking in seconds. Default 300 (5 min). */
|
|
89
|
+
demandWindowSeconds?: number;
|
|
90
|
+
}
|
|
91
|
+
export interface DynamicPricingStats {
|
|
92
|
+
totalTools: number;
|
|
93
|
+
totalRules: number;
|
|
94
|
+
enabledRules: number;
|
|
95
|
+
totalPriceCalculations: number;
|
|
96
|
+
totalCallsTracked: number;
|
|
97
|
+
}
|
|
98
|
+
export declare class DynamicPricingEngine {
|
|
99
|
+
private basePrices;
|
|
100
|
+
private rules;
|
|
101
|
+
private ruleCounter;
|
|
102
|
+
private defaultBasePrice;
|
|
103
|
+
private demandWindowSeconds;
|
|
104
|
+
private callTimestamps;
|
|
105
|
+
private volumeTracker;
|
|
106
|
+
private totalCalculations;
|
|
107
|
+
private totalCallsTracked;
|
|
108
|
+
constructor(config?: DynamicPricingConfig);
|
|
109
|
+
/** Set the base credit price for a tool. */
|
|
110
|
+
setBasePrice(tool: string, price: number): void;
|
|
111
|
+
/** Get the base price for a tool. */
|
|
112
|
+
getBasePrice(tool: string): number;
|
|
113
|
+
/** Remove base price (falls back to default). */
|
|
114
|
+
removeBasePrice(tool: string): boolean;
|
|
115
|
+
/** Add a pricing rule. Returns the rule ID. */
|
|
116
|
+
addRule(reg: PricingRuleRegistration): string;
|
|
117
|
+
/** Remove a pricing rule. */
|
|
118
|
+
removeRule(id: string): boolean;
|
|
119
|
+
/** Enable or disable a rule. */
|
|
120
|
+
setRuleEnabled(id: string, enabled: boolean): boolean;
|
|
121
|
+
/** Get a specific rule. */
|
|
122
|
+
getRule(id: string): PricingRule | null;
|
|
123
|
+
/** List all rules for a tool. */
|
|
124
|
+
getToolRules(tool: string): PricingRule[];
|
|
125
|
+
/** Record a tool call for demand tracking. */
|
|
126
|
+
recordCall(tool: string, key?: string): void;
|
|
127
|
+
/** Get recent call count for a tool. */
|
|
128
|
+
getRecentCallCount(tool: string): number;
|
|
129
|
+
/** Get total calls for a key+tool combo. */
|
|
130
|
+
getKeyToolVolume(key: string, tool: string): number;
|
|
131
|
+
/** Calculate the current price for a tool call. */
|
|
132
|
+
getPrice(tool: string, key?: string): PriceResult;
|
|
133
|
+
getStats(): DynamicPricingStats;
|
|
134
|
+
/** Clear all data. */
|
|
135
|
+
destroy(): void;
|
|
136
|
+
private applyRule;
|
|
137
|
+
private applyTimeOfDay;
|
|
138
|
+
private applyDemand;
|
|
139
|
+
private applyVolumeDiscount;
|
|
140
|
+
private applyKeyOverride;
|
|
141
|
+
private applyCustom;
|
|
142
|
+
private pruneTimestamps;
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=dynamic-pricing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamic-pricing.d.ts","sourceRoot":"","sources":["../src/dynamic-pricing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,MAAM,MAAM,eAAe,GACvB,aAAa,GACb,QAAQ,GACR,iBAAiB,GACjB,cAAc,GACd,QAAQ,CAAC;AAEb,MAAM,WAAW,eAAe;IAC9B,oCAAoC;IACpC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,+EAA+E;IAC/E,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjD;AAED,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,EAAE,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,KAAK,MAAM,CAAC;CAC5D;AAED,MAAM,MAAM,iBAAiB,GACzB,eAAe,GACf,YAAY,GACZ,oBAAoB,GACpB,iBAAiB,GACjB,gBAAgB,CAAC;AAErB,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kEAAkE;IAClE,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAID,qBAAa,oBAAoB;IAE/B,OAAO,CAAC,UAAU,CAA6B;IAE/C,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,mBAAmB,CAAS;IAGpC,OAAO,CAAC,cAAc,CAA+B;IAErD,OAAO,CAAC,aAAa,CAA6B;IAGlD,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,iBAAiB,CAAK;gBAElB,MAAM,GAAE,oBAAyB;IAO7C,4CAA4C;IAC5C,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAK/C,qCAAqC;IACrC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIlC,iDAAiD;IACjD,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAMtC,+CAA+C;IAC/C,OAAO,CAAC,GAAG,EAAE,uBAAuB,GAAG,MAAM;IAe7C,6BAA6B;IAC7B,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI/B,gCAAgC;IAChC,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO;IAOrD,2BAA2B;IAC3B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAIvC,iCAAiC;IACjC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE;IAQzC,8CAA8C;IAC9C,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAkB5C,wCAAwC;IACxC,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAKxC,4CAA4C;IAC5C,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAMnD,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW;IA0CjD,QAAQ,IAAI,mBAAmB;IAW/B,sBAAsB;IACtB,OAAO,IAAI,IAAI;IAYf,OAAO,CAAC,SAAS;IAiBjB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,eAAe;CAOxB"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* DynamicPricingEngine — Adjust tool pricing based on demand, time, and usage.
|
|
4
|
+
*
|
|
5
|
+
* Supports time-of-day multipliers, demand-based surge pricing,
|
|
6
|
+
* volume discounts, and per-key custom pricing. All pricing rules
|
|
7
|
+
* are composable and evaluated in priority order.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const engine = new DynamicPricingEngine();
|
|
12
|
+
*
|
|
13
|
+
* engine.setBasePrice('search', 10);
|
|
14
|
+
*
|
|
15
|
+
* engine.addRule({
|
|
16
|
+
* tool: 'search',
|
|
17
|
+
* type: 'time_of_day',
|
|
18
|
+
* config: { peakHours: [9,10,11,12,13,14,15,16,17], multiplier: 1.5 },
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* const price = engine.getPrice('search');
|
|
22
|
+
* // 15 during peak hours, 10 otherwise
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.DynamicPricingEngine = void 0;
|
|
27
|
+
// ── Implementation ───────────────────────────────────────────────────
|
|
28
|
+
class DynamicPricingEngine {
|
|
29
|
+
// tool → base price
|
|
30
|
+
basePrices = new Map();
|
|
31
|
+
// ruleId → PricingRule
|
|
32
|
+
rules = new Map();
|
|
33
|
+
ruleCounter = 0;
|
|
34
|
+
defaultBasePrice;
|
|
35
|
+
demandWindowSeconds;
|
|
36
|
+
// Demand tracking: tool → timestamps of recent calls
|
|
37
|
+
callTimestamps = new Map();
|
|
38
|
+
// Volume tracking: key:tool → total calls
|
|
39
|
+
volumeTracker = new Map();
|
|
40
|
+
// Stats
|
|
41
|
+
totalCalculations = 0;
|
|
42
|
+
totalCallsTracked = 0;
|
|
43
|
+
constructor(config = {}) {
|
|
44
|
+
this.defaultBasePrice = config.defaultBasePrice ?? 1;
|
|
45
|
+
this.demandWindowSeconds = config.demandWindowSeconds ?? 300;
|
|
46
|
+
}
|
|
47
|
+
// ── Base Prices ───────────────────────────────────────────────────
|
|
48
|
+
/** Set the base credit price for a tool. */
|
|
49
|
+
setBasePrice(tool, price) {
|
|
50
|
+
if (price < 0)
|
|
51
|
+
throw new Error('Base price cannot be negative');
|
|
52
|
+
this.basePrices.set(tool, price);
|
|
53
|
+
}
|
|
54
|
+
/** Get the base price for a tool. */
|
|
55
|
+
getBasePrice(tool) {
|
|
56
|
+
return this.basePrices.get(tool) ?? this.defaultBasePrice;
|
|
57
|
+
}
|
|
58
|
+
/** Remove base price (falls back to default). */
|
|
59
|
+
removeBasePrice(tool) {
|
|
60
|
+
return this.basePrices.delete(tool);
|
|
61
|
+
}
|
|
62
|
+
// ── Rules ─────────────────────────────────────────────────────────
|
|
63
|
+
/** Add a pricing rule. Returns the rule ID. */
|
|
64
|
+
addRule(reg) {
|
|
65
|
+
const id = `rule_${++this.ruleCounter}`;
|
|
66
|
+
const rule = {
|
|
67
|
+
id,
|
|
68
|
+
tool: reg.tool,
|
|
69
|
+
type: reg.type,
|
|
70
|
+
config: reg.config,
|
|
71
|
+
priority: reg.priority ?? 0,
|
|
72
|
+
enabled: true,
|
|
73
|
+
createdAt: Date.now(),
|
|
74
|
+
};
|
|
75
|
+
this.rules.set(id, rule);
|
|
76
|
+
return id;
|
|
77
|
+
}
|
|
78
|
+
/** Remove a pricing rule. */
|
|
79
|
+
removeRule(id) {
|
|
80
|
+
return this.rules.delete(id);
|
|
81
|
+
}
|
|
82
|
+
/** Enable or disable a rule. */
|
|
83
|
+
setRuleEnabled(id, enabled) {
|
|
84
|
+
const rule = this.rules.get(id);
|
|
85
|
+
if (!rule)
|
|
86
|
+
return false;
|
|
87
|
+
rule.enabled = enabled;
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
/** Get a specific rule. */
|
|
91
|
+
getRule(id) {
|
|
92
|
+
return this.rules.get(id) ?? null;
|
|
93
|
+
}
|
|
94
|
+
/** List all rules for a tool. */
|
|
95
|
+
getToolRules(tool) {
|
|
96
|
+
return [...this.rules.values()]
|
|
97
|
+
.filter(r => r.tool === tool)
|
|
98
|
+
.sort((a, b) => b.priority - a.priority);
|
|
99
|
+
}
|
|
100
|
+
// ── Demand Tracking ────────────────────────────────────────────────
|
|
101
|
+
/** Record a tool call for demand tracking. */
|
|
102
|
+
recordCall(tool, key) {
|
|
103
|
+
// Track timestamps for demand pricing
|
|
104
|
+
if (!this.callTimestamps.has(tool)) {
|
|
105
|
+
this.callTimestamps.set(tool, []);
|
|
106
|
+
}
|
|
107
|
+
this.callTimestamps.get(tool).push(Date.now());
|
|
108
|
+
this.totalCallsTracked++;
|
|
109
|
+
// Track volume per key
|
|
110
|
+
if (key) {
|
|
111
|
+
const volumeKey = `${key}:${tool}`;
|
|
112
|
+
this.volumeTracker.set(volumeKey, (this.volumeTracker.get(volumeKey) ?? 0) + 1);
|
|
113
|
+
}
|
|
114
|
+
// Prune old timestamps
|
|
115
|
+
this.pruneTimestamps(tool);
|
|
116
|
+
}
|
|
117
|
+
/** Get recent call count for a tool. */
|
|
118
|
+
getRecentCallCount(tool) {
|
|
119
|
+
this.pruneTimestamps(tool);
|
|
120
|
+
return this.callTimestamps.get(tool)?.length ?? 0;
|
|
121
|
+
}
|
|
122
|
+
/** Get total calls for a key+tool combo. */
|
|
123
|
+
getKeyToolVolume(key, tool) {
|
|
124
|
+
return this.volumeTracker.get(`${key}:${tool}`) ?? 0;
|
|
125
|
+
}
|
|
126
|
+
// ── Price Calculation ─────────────────────────────────────────────
|
|
127
|
+
/** Calculate the current price for a tool call. */
|
|
128
|
+
getPrice(tool, key) {
|
|
129
|
+
this.totalCalculations++;
|
|
130
|
+
const basePrice = this.getBasePrice(tool);
|
|
131
|
+
const context = {
|
|
132
|
+
tool,
|
|
133
|
+
key,
|
|
134
|
+
timestamp: Date.now(),
|
|
135
|
+
recentCalls: this.getRecentCallCount(tool),
|
|
136
|
+
totalCalls: key ? this.getKeyToolVolume(key, tool) : 0,
|
|
137
|
+
};
|
|
138
|
+
// Get enabled rules for this tool, sorted by priority (highest first)
|
|
139
|
+
const rules = [...this.rules.values()]
|
|
140
|
+
.filter(r => r.tool === tool && r.enabled)
|
|
141
|
+
.sort((a, b) => b.priority - a.priority);
|
|
142
|
+
let price = basePrice;
|
|
143
|
+
const appliedRules = [];
|
|
144
|
+
for (const rule of rules) {
|
|
145
|
+
const newPrice = this.applyRule(rule, price, context);
|
|
146
|
+
if (newPrice !== price) {
|
|
147
|
+
price = newPrice;
|
|
148
|
+
appliedRules.push(rule.id);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Ensure price is non-negative
|
|
152
|
+
price = Math.max(0, Math.round(price));
|
|
153
|
+
return {
|
|
154
|
+
tool,
|
|
155
|
+
basePrice,
|
|
156
|
+
finalPrice: price,
|
|
157
|
+
appliedRules,
|
|
158
|
+
multiplier: basePrice > 0 ? price / basePrice : 1,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
// ── Stats ─────────────────────────────────────────────────────────
|
|
162
|
+
getStats() {
|
|
163
|
+
const enabledRules = [...this.rules.values()].filter(r => r.enabled).length;
|
|
164
|
+
return {
|
|
165
|
+
totalTools: this.basePrices.size,
|
|
166
|
+
totalRules: this.rules.size,
|
|
167
|
+
enabledRules,
|
|
168
|
+
totalPriceCalculations: this.totalCalculations,
|
|
169
|
+
totalCallsTracked: this.totalCallsTracked,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/** Clear all data. */
|
|
173
|
+
destroy() {
|
|
174
|
+
this.basePrices.clear();
|
|
175
|
+
this.rules.clear();
|
|
176
|
+
this.callTimestamps.clear();
|
|
177
|
+
this.volumeTracker.clear();
|
|
178
|
+
this.totalCalculations = 0;
|
|
179
|
+
this.totalCallsTracked = 0;
|
|
180
|
+
this.ruleCounter = 0;
|
|
181
|
+
}
|
|
182
|
+
// ── Private ───────────────────────────────────────────────────────
|
|
183
|
+
applyRule(rule, currentPrice, ctx) {
|
|
184
|
+
switch (rule.type) {
|
|
185
|
+
case 'time_of_day':
|
|
186
|
+
return this.applyTimeOfDay(rule.config, currentPrice, ctx);
|
|
187
|
+
case 'demand':
|
|
188
|
+
return this.applyDemand(rule.config, currentPrice, ctx);
|
|
189
|
+
case 'volume_discount':
|
|
190
|
+
return this.applyVolumeDiscount(rule.config, currentPrice, ctx);
|
|
191
|
+
case 'key_override':
|
|
192
|
+
return this.applyKeyOverride(rule.config, currentPrice, ctx);
|
|
193
|
+
case 'custom':
|
|
194
|
+
return this.applyCustom(rule.config, currentPrice, ctx);
|
|
195
|
+
default:
|
|
196
|
+
return currentPrice;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
applyTimeOfDay(config, price, ctx) {
|
|
200
|
+
const hour = new Date(ctx.timestamp).getHours();
|
|
201
|
+
if (config.peakHours.includes(hour)) {
|
|
202
|
+
return price * config.multiplier;
|
|
203
|
+
}
|
|
204
|
+
return price;
|
|
205
|
+
}
|
|
206
|
+
applyDemand(config, price, ctx) {
|
|
207
|
+
if (ctx.recentCalls < config.threshold)
|
|
208
|
+
return price;
|
|
209
|
+
// Linear surge: 1x at threshold, maxMultiplier at 2x threshold
|
|
210
|
+
const ratio = Math.min((ctx.recentCalls - config.threshold) / config.threshold, 1);
|
|
211
|
+
const multiplier = 1 + ratio * (config.maxMultiplier - 1);
|
|
212
|
+
return price * multiplier;
|
|
213
|
+
}
|
|
214
|
+
applyVolumeDiscount(config, price, ctx) {
|
|
215
|
+
if (!ctx.key)
|
|
216
|
+
return price;
|
|
217
|
+
// Sort tiers descending by minCalls, find the highest qualifying tier
|
|
218
|
+
const sorted = [...config.tiers].sort((a, b) => b.minCalls - a.minCalls);
|
|
219
|
+
for (const tier of sorted) {
|
|
220
|
+
if (ctx.totalCalls >= tier.minCalls) {
|
|
221
|
+
return price * (1 - tier.discount);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return price;
|
|
225
|
+
}
|
|
226
|
+
applyKeyOverride(config, _price, ctx) {
|
|
227
|
+
if (!ctx.key)
|
|
228
|
+
return _price;
|
|
229
|
+
const override = config.keyPrices.get(ctx.key);
|
|
230
|
+
return override !== undefined ? override : _price;
|
|
231
|
+
}
|
|
232
|
+
applyCustom(config, price, ctx) {
|
|
233
|
+
try {
|
|
234
|
+
return config.fn(price, ctx);
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
return price; // Fail-safe: return original price
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
pruneTimestamps(tool) {
|
|
241
|
+
const timestamps = this.callTimestamps.get(tool);
|
|
242
|
+
if (!timestamps)
|
|
243
|
+
return;
|
|
244
|
+
const cutoff = Date.now() - this.demandWindowSeconds * 1000;
|
|
245
|
+
const pruned = timestamps.filter(t => t >= cutoff);
|
|
246
|
+
this.callTimestamps.set(tool, pruned);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
exports.DynamicPricingEngine = DynamicPricingEngine;
|
|
250
|
+
//# sourceMappingURL=dynamic-pricing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamic-pricing.js","sourceRoot":"","sources":["../src/dynamic-pricing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EventLedger — Immutable event sourcing for full audit trail.
|
|
3
|
+
*
|
|
4
|
+
* Records every state change as an immutable event. Supports replay,
|
|
5
|
+
* projection, and time-travel queries for compliance and debugging.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const ledger = new EventLedger();
|
|
10
|
+
*
|
|
11
|
+
* ledger.append({
|
|
12
|
+
* type: 'credit.deducted',
|
|
13
|
+
* aggregateId: 'key_abc',
|
|
14
|
+
* payload: { amount: 50, tool: 'search', balance: 950 },
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* const events = ledger.query({ aggregateId: 'key_abc' });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export interface LedgerEvent {
|
|
21
|
+
id: string;
|
|
22
|
+
sequence: number;
|
|
23
|
+
type: string;
|
|
24
|
+
aggregateId: string;
|
|
25
|
+
aggregateType?: string;
|
|
26
|
+
payload: Record<string, unknown>;
|
|
27
|
+
metadata?: Record<string, string>;
|
|
28
|
+
timestamp: number;
|
|
29
|
+
version: number;
|
|
30
|
+
}
|
|
31
|
+
export interface AppendParams {
|
|
32
|
+
type: string;
|
|
33
|
+
aggregateId: string;
|
|
34
|
+
aggregateType?: string;
|
|
35
|
+
payload: Record<string, unknown>;
|
|
36
|
+
metadata?: Record<string, string>;
|
|
37
|
+
expectedVersion?: number;
|
|
38
|
+
}
|
|
39
|
+
export interface LedgerQuery {
|
|
40
|
+
aggregateId?: string;
|
|
41
|
+
aggregateType?: string;
|
|
42
|
+
type?: string;
|
|
43
|
+
types?: string[];
|
|
44
|
+
startTime?: number;
|
|
45
|
+
endTime?: number;
|
|
46
|
+
afterSequence?: number;
|
|
47
|
+
limit?: number;
|
|
48
|
+
offset?: number;
|
|
49
|
+
}
|
|
50
|
+
export interface LedgerQueryResult {
|
|
51
|
+
events: LedgerEvent[];
|
|
52
|
+
total: number;
|
|
53
|
+
hasMore: boolean;
|
|
54
|
+
}
|
|
55
|
+
export interface AggregateSnapshot {
|
|
56
|
+
aggregateId: string;
|
|
57
|
+
version: number;
|
|
58
|
+
eventCount: number;
|
|
59
|
+
firstEvent: number;
|
|
60
|
+
lastEvent: number;
|
|
61
|
+
types: string[];
|
|
62
|
+
}
|
|
63
|
+
export interface EventLedgerConfig {
|
|
64
|
+
maxEvents?: number;
|
|
65
|
+
enableConcurrencyCheck?: boolean;
|
|
66
|
+
}
|
|
67
|
+
export interface EventLedgerStats {
|
|
68
|
+
totalEvents: number;
|
|
69
|
+
totalAggregates: number;
|
|
70
|
+
eventTypes: number;
|
|
71
|
+
oldestEvent: number | null;
|
|
72
|
+
newestEvent: number | null;
|
|
73
|
+
}
|
|
74
|
+
export declare class EventLedger {
|
|
75
|
+
private events;
|
|
76
|
+
private sequence;
|
|
77
|
+
private maxEvents;
|
|
78
|
+
private enableConcurrencyCheck;
|
|
79
|
+
private aggregateVersions;
|
|
80
|
+
constructor(config?: EventLedgerConfig);
|
|
81
|
+
/** Append an event to the ledger. Returns the event ID. */
|
|
82
|
+
append(params: AppendParams): string;
|
|
83
|
+
/** Append multiple events atomically. */
|
|
84
|
+
appendBatch(params: AppendParams[]): string[];
|
|
85
|
+
/** Query events with filters. */
|
|
86
|
+
query(q?: LedgerQuery): LedgerQueryResult;
|
|
87
|
+
/** Get a single event by ID. */
|
|
88
|
+
getEvent(id: string): LedgerEvent | null;
|
|
89
|
+
/** Get all events for an aggregate in order. */
|
|
90
|
+
getAggregateEvents(aggregateId: string): LedgerEvent[];
|
|
91
|
+
/** Get the current version of an aggregate. */
|
|
92
|
+
getAggregateVersion(aggregateId: string): number;
|
|
93
|
+
/** Get a snapshot summary of an aggregate. */
|
|
94
|
+
getAggregateSnapshot(aggregateId: string): AggregateSnapshot | null;
|
|
95
|
+
/** List all aggregate IDs. */
|
|
96
|
+
listAggregates(): string[];
|
|
97
|
+
/**
|
|
98
|
+
* Replay events for an aggregate through a reducer function.
|
|
99
|
+
* Returns the final state.
|
|
100
|
+
*/
|
|
101
|
+
replay<T>(aggregateId: string, reducer: (state: T, event: LedgerEvent) => T, initialState: T): T;
|
|
102
|
+
/**
|
|
103
|
+
* Replay all events through a reducer (not scoped to aggregate).
|
|
104
|
+
* Useful for rebuilding read models / projections.
|
|
105
|
+
*/
|
|
106
|
+
replayAll<T>(reducer: (state: T, event: LedgerEvent) => T, initialState: T): T;
|
|
107
|
+
/** Get the state of an aggregate at a specific point in time. */
|
|
108
|
+
getEventsAsOf(aggregateId: string, asOfTimestamp: number): LedgerEvent[];
|
|
109
|
+
/** Get event count by type. */
|
|
110
|
+
getEventTypeCounts(): Map<string, number>;
|
|
111
|
+
getStats(): EventLedgerStats;
|
|
112
|
+
/** Clear all data. */
|
|
113
|
+
destroy(): void;
|
|
114
|
+
private applyFilters;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=event-ledger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-ledger.d.ts","sourceRoot":"","sources":["../src/event-ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAID,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,sBAAsB,CAAU;IAExC,OAAO,CAAC,iBAAiB,CAA6B;gBAE1C,MAAM,GAAE,iBAAsB;IAO1C,2DAA2D;IAC3D,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM;IAwCpC,yCAAyC;IACzC,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,EAAE;IAU7C,iCAAiC;IACjC,KAAK,CAAC,CAAC,GAAE,WAAgB,GAAG,iBAAiB;IAe7C,gCAAgC;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAIxC,gDAAgD;IAChD,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,EAAE;IAMtD,+CAA+C;IAC/C,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAIhD,8CAA8C;IAC9C,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI;IAenE,8BAA8B;IAC9B,cAAc,IAAI,MAAM,EAAE;IAM1B;;;OAGG;IACH,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC;IAShG;;;OAGG;IACH,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC;IAU9E,iEAAiE;IACjE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,WAAW,EAAE;IAMxE,+BAA+B;IAC/B,kBAAkB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAUzC,QAAQ,IAAI,gBAAgB;IAW5B,sBAAsB;IACtB,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,YAAY;CAarB"}
|