@framers/agentos 0.1.192 → 0.1.194
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/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
3
|
<a href="https://agentos.sh">
|
|
4
|
-
<img src="https://raw.githubusercontent.com/framersai/agentos/master/assets/agentos-primary-transparent-2x.png" alt="AgentOS" height="
|
|
4
|
+
<img src="https://raw.githubusercontent.com/framersai/agentos/master/assets/agentos-primary-no-tagline-transparent-2x.png" alt="AgentOS" height="100" />
|
|
5
5
|
</a>
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
<br />
|
|
8
8
|
|
|
9
9
|
**Build autonomous AI agents with adaptive intelligence, cognitive memory, and emergent behaviors. Open-source TypeScript runtime.**
|
|
10
10
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/providers/ApiKeyPool
|
|
3
|
+
*
|
|
4
|
+
* Weighted round-robin API key pool with quota-exhaustion cooldown.
|
|
5
|
+
*
|
|
6
|
+
* Accepts a single key or comma-separated keys. The first key gets
|
|
7
|
+
* higher rotation weight (configurable). Exhausted keys are temporarily
|
|
8
|
+
* removed from rotation and re-enter after a cooldown period.
|
|
9
|
+
*
|
|
10
|
+
* This is a core AgentOS primitive -- every provider that accepts an
|
|
11
|
+
* API key can use it for automatic multi-key rotation and failover.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* // Single key (backward compatible, zero overhead):
|
|
16
|
+
* const pool = new ApiKeyPool('sk_abc');
|
|
17
|
+
* pool.next(); // 'sk_abc'
|
|
18
|
+
*
|
|
19
|
+
* // Multiple keys with round-robin + first-key priority:
|
|
20
|
+
* const pool = new ApiKeyPool('sk_primary,sk_backup,sk_overflow');
|
|
21
|
+
* pool.next(); // weighted rotation, primary selected ~2x more
|
|
22
|
+
*
|
|
23
|
+
* // Mark exhausted on quota error:
|
|
24
|
+
* pool.markExhausted(key); // skipped for 15min cooldown
|
|
25
|
+
* pool.next(); // returns next available key
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
/** Configuration for an ApiKeyPool instance. */
|
|
29
|
+
export interface ApiKeyPoolConfig {
|
|
30
|
+
/** Cooldown before retrying an exhausted key. Default: 15 minutes. */
|
|
31
|
+
cooldownMs?: number;
|
|
32
|
+
/** Weight multiplier for the first key. Default: 2. Set to 1 for equal weighting. */
|
|
33
|
+
primaryWeight?: number;
|
|
34
|
+
}
|
|
35
|
+
export declare class ApiKeyPool {
|
|
36
|
+
private readonly keys;
|
|
37
|
+
private readonly weightedSlots;
|
|
38
|
+
private slotIndex;
|
|
39
|
+
private readonly cooldownMs;
|
|
40
|
+
constructor(keys: string | string[], config?: ApiKeyPoolConfig);
|
|
41
|
+
/** Number of keys in the pool (including temporarily exhausted ones). */
|
|
42
|
+
get size(): number;
|
|
43
|
+
/** Whether any key exists at all. */
|
|
44
|
+
get hasKeys(): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Get the next available key via weighted round-robin.
|
|
47
|
+
* Skips keys currently in cooldown. Returns empty string if pool is empty.
|
|
48
|
+
*/
|
|
49
|
+
next(): string;
|
|
50
|
+
/**
|
|
51
|
+
* Mark a key as quota-exhausted. It will be skipped during
|
|
52
|
+
* rotation until the cooldown expires.
|
|
53
|
+
*/
|
|
54
|
+
markExhausted(key: string): void;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=ApiKeyPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiKeyPool.d.ts","sourceRoot":"","sources":["../../../src/core/providers/ApiKeyPool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAUD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAW;IACzC,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,gBAAgB;IAoB9D,yEAAyE;IACzE,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,qCAAqC;IACrC,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;OAGG;IACH,IAAI,IAAI,MAAM;IAsBd;;;OAGG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAMjC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/providers/ApiKeyPool
|
|
3
|
+
*
|
|
4
|
+
* Weighted round-robin API key pool with quota-exhaustion cooldown.
|
|
5
|
+
*
|
|
6
|
+
* Accepts a single key or comma-separated keys. The first key gets
|
|
7
|
+
* higher rotation weight (configurable). Exhausted keys are temporarily
|
|
8
|
+
* removed from rotation and re-enter after a cooldown period.
|
|
9
|
+
*
|
|
10
|
+
* This is a core AgentOS primitive -- every provider that accepts an
|
|
11
|
+
* API key can use it for automatic multi-key rotation and failover.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* // Single key (backward compatible, zero overhead):
|
|
16
|
+
* const pool = new ApiKeyPool('sk_abc');
|
|
17
|
+
* pool.next(); // 'sk_abc'
|
|
18
|
+
*
|
|
19
|
+
* // Multiple keys with round-robin + first-key priority:
|
|
20
|
+
* const pool = new ApiKeyPool('sk_primary,sk_backup,sk_overflow');
|
|
21
|
+
* pool.next(); // weighted rotation, primary selected ~2x more
|
|
22
|
+
*
|
|
23
|
+
* // Mark exhausted on quota error:
|
|
24
|
+
* pool.markExhausted(key); // skipped for 15min cooldown
|
|
25
|
+
* pool.next(); // returns next available key
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
const DEFAULT_COOLDOWN_MS = 15 * 60000;
|
|
29
|
+
const DEFAULT_PRIMARY_WEIGHT = 2;
|
|
30
|
+
export class ApiKeyPool {
|
|
31
|
+
constructor(keys, config) {
|
|
32
|
+
this.slotIndex = 0;
|
|
33
|
+
this.cooldownMs = config?.cooldownMs ?? DEFAULT_COOLDOWN_MS;
|
|
34
|
+
const primaryWeight = config?.primaryWeight ?? DEFAULT_PRIMARY_WEIGHT;
|
|
35
|
+
const keyList = Array.isArray(keys)
|
|
36
|
+
? keys
|
|
37
|
+
: keys.split(',').map((k) => k.trim()).filter((k) => k.length > 0);
|
|
38
|
+
this.keys = keyList.map((key) => ({ key, exhaustedUntil: 0 }));
|
|
39
|
+
// Build weighted slot array: first key appears `primaryWeight` times, rest once each.
|
|
40
|
+
this.weightedSlots = [];
|
|
41
|
+
for (let i = 0; i < this.keys.length; i++) {
|
|
42
|
+
const times = i === 0 ? primaryWeight : 1;
|
|
43
|
+
for (let t = 0; t < times; t++) {
|
|
44
|
+
this.weightedSlots.push(i);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** Number of keys in the pool (including temporarily exhausted ones). */
|
|
49
|
+
get size() {
|
|
50
|
+
return this.keys.length;
|
|
51
|
+
}
|
|
52
|
+
/** Whether any key exists at all. */
|
|
53
|
+
get hasKeys() {
|
|
54
|
+
return this.keys.length > 0;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get the next available key via weighted round-robin.
|
|
58
|
+
* Skips keys currently in cooldown. Returns empty string if pool is empty.
|
|
59
|
+
*/
|
|
60
|
+
next() {
|
|
61
|
+
if (this.keys.length === 0)
|
|
62
|
+
return '';
|
|
63
|
+
if (this.keys.length === 1)
|
|
64
|
+
return this.keys[0].key;
|
|
65
|
+
const now = Date.now();
|
|
66
|
+
const totalSlots = this.weightedSlots.length;
|
|
67
|
+
for (let i = 0; i < totalSlots; i++) {
|
|
68
|
+
const slotIdx = (this.slotIndex + i) % totalSlots;
|
|
69
|
+
const keyIdx = this.weightedSlots[slotIdx];
|
|
70
|
+
const state = this.keys[keyIdx];
|
|
71
|
+
if (state.exhaustedUntil <= now) {
|
|
72
|
+
this.slotIndex = (slotIdx + 1) % totalSlots;
|
|
73
|
+
return state.key;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// All keys exhausted -- return the one whose cooldown expires soonest.
|
|
77
|
+
const sorted = [...this.keys].sort((a, b) => a.exhaustedUntil - b.exhaustedUntil);
|
|
78
|
+
return sorted[0].key;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Mark a key as quota-exhausted. It will be skipped during
|
|
82
|
+
* rotation until the cooldown expires.
|
|
83
|
+
*/
|
|
84
|
+
markExhausted(key) {
|
|
85
|
+
const state = this.keys.find((k) => k.key === key);
|
|
86
|
+
if (state) {
|
|
87
|
+
state.exhaustedUntil = Date.now() + this.cooldownMs;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=ApiKeyPool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiKeyPool.js","sourceRoot":"","sources":["../../../src/core/providers/ApiKeyPool.ts"],"names":[],"mappings":"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"}
|