@gatewaystack/limitabl-core 0.1.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/README.md +155 -0
- package/dist/agentGuard.d.ts +17 -0
- package/dist/agentGuard.d.ts.map +1 -0
- package/dist/agentGuard.js +88 -0
- package/dist/agentGuard.js.map +1 -0
- package/dist/budgetTracker.d.ts +22 -0
- package/dist/budgetTracker.d.ts.map +1 -0
- package/dist/budgetTracker.js +94 -0
- package/dist/budgetTracker.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/preflight.d.ts +34 -0
- package/dist/preflight.d.ts.map +1 -0
- package/dist/preflight.js +87 -0
- package/dist/preflight.js.map +1 -0
- package/dist/rateLimiter.d.ts +19 -0
- package/dist/rateLimiter.d.ts.map +1 -0
- package/dist/rateLimiter.js +86 -0
- package/dist/rateLimiter.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +24 -0
package/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# @gatewaystack/limitabl-core
|
|
2
|
+
|
|
3
|
+
Framework-agnostic rate limiting, budget tracking, and agent guard for AI gateways.
|
|
4
|
+
|
|
5
|
+
`@gatewaystack/limitabl-core` is the low-level engine behind [@gatewaystack/limitabl](https://www.npmjs.com/package/@gatewaystack/limitabl). Use it directly when you need usage controls without Express.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @gatewaystack/limitabl-core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Sliding-window rate limiter** — per-user/org/IP request throttling
|
|
16
|
+
- **Budget tracker** — per-user spend caps with preflight estimation
|
|
17
|
+
- **Agent guard** — tool call limits, workflow cost caps, and duration caps to prevent runaway agents
|
|
18
|
+
- **Unified preflight engine** — runs all checks in a single call
|
|
19
|
+
- **Key resolution** — automatic key priority: `sub` > `orgId` > `ip` > `anonymous`, with optional tenant prefix
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### Rate limiting
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { InMemoryRateLimiter } from "@gatewaystack/limitabl-core";
|
|
27
|
+
|
|
28
|
+
const limiter = new InMemoryRateLimiter({ windowMs: 60_000, maxRequests: 10 });
|
|
29
|
+
|
|
30
|
+
const result = limiter.check({ sub: "user1" });
|
|
31
|
+
// { allowed: true, remaining: 9, resetAt: 1738886400000 }
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Budget tracking
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { InMemoryBudgetTracker } from "@gatewaystack/limitabl-core";
|
|
38
|
+
|
|
39
|
+
const budget = new InMemoryBudgetTracker({ maxSpend: 100, periodMs: 86_400_000 });
|
|
40
|
+
|
|
41
|
+
// Pre-flight check with estimated cost
|
|
42
|
+
budget.check({ sub: "user1" }, 25);
|
|
43
|
+
// { allowed: true, currentSpend: 0, maxSpend: 100, percentUsed: 0 }
|
|
44
|
+
|
|
45
|
+
// Record actual usage after execution
|
|
46
|
+
budget.record({ sub: "user1" }, { timestamp: Date.now(), cost: 22, tokens: 1500 });
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Agent guard
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { AgentGuard } from "@gatewaystack/limitabl-core";
|
|
53
|
+
|
|
54
|
+
const guard = new AgentGuard({ maxToolCalls: 20, maxWorkflowCost: 500, maxDurationMs: 120_000 });
|
|
55
|
+
|
|
56
|
+
// Before each tool call
|
|
57
|
+
const result = guard.check("workflow-abc");
|
|
58
|
+
// { allowed: true, toolCallCount: 0, workflowCost: 0, durationMs: 3 }
|
|
59
|
+
|
|
60
|
+
// After each tool call
|
|
61
|
+
guard.recordToolCall("workflow-abc", 12); // cost = 12
|
|
62
|
+
|
|
63
|
+
// When workflow finishes
|
|
64
|
+
guard.endWorkflow("workflow-abc");
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Unified preflight
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { LimitablEngine } from "@gatewaystack/limitabl-core";
|
|
71
|
+
|
|
72
|
+
const engine = new LimitablEngine({
|
|
73
|
+
rateLimit: { windowMs: 60_000, maxRequests: 100 },
|
|
74
|
+
budget: { maxSpend: 1000, periodMs: 86_400_000 },
|
|
75
|
+
agentGuard: { maxToolCalls: 50 },
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const result = engine.preflight(
|
|
79
|
+
{ sub: "user1", tenantId: "tenant-a" },
|
|
80
|
+
{ estimatedCost: 5, workflowId: "wf-123" }
|
|
81
|
+
);
|
|
82
|
+
// { allowed: true, reason: "All checks passed", rateLimit: {...}, budget: {...}, agentGuard: {...} }
|
|
83
|
+
|
|
84
|
+
// Record usage post-execution
|
|
85
|
+
engine.recordUsage({
|
|
86
|
+
key: { sub: "user1" },
|
|
87
|
+
workflowId: "wf-123",
|
|
88
|
+
usage: { timestamp: Date.now(), cost: 4.5, tokens: 800 },
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Cleanup on shutdown
|
|
92
|
+
engine.destroy();
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## API
|
|
96
|
+
|
|
97
|
+
### `InMemoryRateLimiter`
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
new InMemoryRateLimiter(config: { windowMs: number, maxRequests: number })
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
| Method | Description |
|
|
104
|
+
|--------|-------------|
|
|
105
|
+
| `check(key)` | Check and record a request. Returns `{ allowed, remaining, resetAt, retryAfterSec? }` |
|
|
106
|
+
| `destroy()` | Stop the internal cleanup interval |
|
|
107
|
+
|
|
108
|
+
### `InMemoryBudgetTracker`
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
new InMemoryBudgetTracker(config: { maxSpend: number, periodMs: number })
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
| Method | Description |
|
|
115
|
+
|--------|-------------|
|
|
116
|
+
| `check(key, estimatedCost?)` | Pre-flight budget check. Returns `{ allowed, currentSpend, maxSpend, percentUsed }` |
|
|
117
|
+
| `record(key, usage)` | Record actual usage after execution |
|
|
118
|
+
| `getUsageSummary(key)` | Returns `{ totalSpend, totalTokens, requestCount }` |
|
|
119
|
+
| `destroy()` | Stop the internal cleanup interval |
|
|
120
|
+
|
|
121
|
+
### `AgentGuard`
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
new AgentGuard(config?: { maxToolCalls?, maxWorkflowCost?, maxDurationMs? })
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
| Method | Description |
|
|
128
|
+
|--------|-------------|
|
|
129
|
+
| `check(workflowId)` | Check if a tool call is allowed. Returns `{ allowed, toolCallCount, workflowCost, durationMs }` |
|
|
130
|
+
| `recordToolCall(workflowId, cost?)` | Record a tool call with optional cost |
|
|
131
|
+
| `endWorkflow(workflowId)` | Clean up workflow state |
|
|
132
|
+
|
|
133
|
+
### `LimitablEngine`
|
|
134
|
+
|
|
135
|
+
Orchestrates all three components. Configure any combination of rate limiting, budget tracking, and agent guard.
|
|
136
|
+
|
|
137
|
+
### `resolveKey(key)`
|
|
138
|
+
|
|
139
|
+
Resolves a `LimitKey` to a string: `sub` > `orgId` > `ip` > `anonymous`, with optional `tenantId` prefix.
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
resolveKey({ tenantId: "t1", sub: "u1" }) // "t:t1|u:u1"
|
|
143
|
+
resolveKey({ ip: "1.2.3.4" }) // "ip:1.2.3.4"
|
|
144
|
+
resolveKey({}) // "anonymous"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Related Packages
|
|
148
|
+
|
|
149
|
+
- [@gatewaystack/limitabl](https://www.npmjs.com/package/@gatewaystack/limitabl) — Express middleware wrapper
|
|
150
|
+
- [@gatewaystack/identifiabl-core](https://www.npmjs.com/package/@gatewaystack/identifiabl-core) — JWT identity (provides `sub`, `orgId`)
|
|
151
|
+
- [@gatewaystack/validatabl-core](https://www.npmjs.com/package/@gatewaystack/validatabl-core) — Policy enforcement
|
|
152
|
+
|
|
153
|
+
## License
|
|
154
|
+
|
|
155
|
+
MIT
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AgentGuardConfig, AgentGuardResult } from "./types.js";
|
|
2
|
+
export declare class AgentGuard {
|
|
3
|
+
private workflows;
|
|
4
|
+
private config;
|
|
5
|
+
constructor(config?: AgentGuardConfig);
|
|
6
|
+
/**
|
|
7
|
+
* Check if a tool call is allowed within the workflow constraints.
|
|
8
|
+
* Call this BEFORE executing each tool call.
|
|
9
|
+
*/
|
|
10
|
+
check(workflowId: string): AgentGuardResult;
|
|
11
|
+
/** Record a tool call after execution (updates counters). */
|
|
12
|
+
recordToolCall(workflowId: string, cost?: number): void;
|
|
13
|
+
/** End a workflow (clean up state). */
|
|
14
|
+
endWorkflow(workflowId: string): void;
|
|
15
|
+
private getOrCreate;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=agentGuard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentGuard.d.ts","sourceRoot":"","sources":["../src/agentGuard.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAYrE,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,MAAM,CAA6B;gBAE/B,MAAM,GAAE,gBAAqB;IAQzC;;;OAGG;IACH,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB;IA+C3C,6DAA6D;IAC7D,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAE,MAAU,GAAG,IAAI;IAM1D,uCAAuC;IACvC,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIrC,OAAO,CAAC,WAAW;CAQpB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// packages/limitabl-core/src/agentGuard.ts
|
|
2
|
+
//
|
|
3
|
+
// Prevents agentic runaway: tool call limits, workflow cost caps, duration caps.
|
|
4
|
+
//
|
|
5
|
+
// FUTURE WORK:
|
|
6
|
+
// - Recursion depth detection (detect A→B→A→B loops)
|
|
7
|
+
// - Duplicate tool call detection with configurable thresholds
|
|
8
|
+
// - Per-tool call limits (e.g., max 5 calls to expensive-tool per workflow)
|
|
9
|
+
// - Circuit breaker pattern (stop all tool calls after N consecutive failures)
|
|
10
|
+
const DEFAULT_MAX_TOOL_CALLS = 50;
|
|
11
|
+
const DEFAULT_MAX_WORKFLOW_COST = 1000; // $10 in cents
|
|
12
|
+
const DEFAULT_MAX_DURATION_MS = 300_000; // 5 minutes
|
|
13
|
+
export class AgentGuard {
|
|
14
|
+
workflows = new Map();
|
|
15
|
+
config;
|
|
16
|
+
constructor(config = {}) {
|
|
17
|
+
this.config = {
|
|
18
|
+
maxToolCalls: config.maxToolCalls ?? DEFAULT_MAX_TOOL_CALLS,
|
|
19
|
+
maxWorkflowCost: config.maxWorkflowCost ?? DEFAULT_MAX_WORKFLOW_COST,
|
|
20
|
+
maxDurationMs: config.maxDurationMs ?? DEFAULT_MAX_DURATION_MS,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Check if a tool call is allowed within the workflow constraints.
|
|
25
|
+
* Call this BEFORE executing each tool call.
|
|
26
|
+
*/
|
|
27
|
+
check(workflowId) {
|
|
28
|
+
const state = this.getOrCreate(workflowId);
|
|
29
|
+
const now = Date.now();
|
|
30
|
+
const durationMs = now - state.startedAt;
|
|
31
|
+
// Check duration
|
|
32
|
+
if (durationMs > this.config.maxDurationMs) {
|
|
33
|
+
return {
|
|
34
|
+
allowed: false,
|
|
35
|
+
reason: `Workflow exceeded max duration: ${durationMs}ms > ${this.config.maxDurationMs}ms`,
|
|
36
|
+
toolCallCount: state.toolCallCount,
|
|
37
|
+
workflowCost: state.totalCost,
|
|
38
|
+
durationMs,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
// Check tool call count
|
|
42
|
+
if (state.toolCallCount >= this.config.maxToolCalls) {
|
|
43
|
+
return {
|
|
44
|
+
allowed: false,
|
|
45
|
+
reason: `Workflow exceeded max tool calls: ${state.toolCallCount} >= ${this.config.maxToolCalls}`,
|
|
46
|
+
toolCallCount: state.toolCallCount,
|
|
47
|
+
workflowCost: state.totalCost,
|
|
48
|
+
durationMs,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Check cost
|
|
52
|
+
if (state.totalCost >= this.config.maxWorkflowCost) {
|
|
53
|
+
return {
|
|
54
|
+
allowed: false,
|
|
55
|
+
reason: `Workflow exceeded max cost: ${state.totalCost} >= ${this.config.maxWorkflowCost}`,
|
|
56
|
+
toolCallCount: state.toolCallCount,
|
|
57
|
+
workflowCost: state.totalCost,
|
|
58
|
+
durationMs,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
allowed: true,
|
|
63
|
+
reason: "Within workflow limits",
|
|
64
|
+
toolCallCount: state.toolCallCount,
|
|
65
|
+
workflowCost: state.totalCost,
|
|
66
|
+
durationMs,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** Record a tool call after execution (updates counters). */
|
|
70
|
+
recordToolCall(workflowId, cost = 0) {
|
|
71
|
+
const state = this.getOrCreate(workflowId);
|
|
72
|
+
state.toolCallCount++;
|
|
73
|
+
state.totalCost += cost;
|
|
74
|
+
}
|
|
75
|
+
/** End a workflow (clean up state). */
|
|
76
|
+
endWorkflow(workflowId) {
|
|
77
|
+
this.workflows.delete(workflowId);
|
|
78
|
+
}
|
|
79
|
+
getOrCreate(workflowId) {
|
|
80
|
+
let state = this.workflows.get(workflowId);
|
|
81
|
+
if (!state) {
|
|
82
|
+
state = { startedAt: Date.now(), toolCallCount: 0, totalCost: 0 };
|
|
83
|
+
this.workflows.set(workflowId, state);
|
|
84
|
+
}
|
|
85
|
+
return state;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=agentGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentGuard.js","sourceRoot":"","sources":["../src/agentGuard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { LimitKey, BudgetConfig, BudgetCheckResult, UsageRecord } from "./types.js";
|
|
2
|
+
export declare class InMemoryBudgetTracker {
|
|
3
|
+
private budgets;
|
|
4
|
+
private config;
|
|
5
|
+
private cleanupInterval;
|
|
6
|
+
constructor(config: BudgetConfig);
|
|
7
|
+
/** Check if a request is within budget (pre-flight). */
|
|
8
|
+
check(key: LimitKey, estimatedCost?: number): BudgetCheckResult;
|
|
9
|
+
/** Record usage after execution (post-execution / Phase 2). */
|
|
10
|
+
record(key: LimitKey, usage: UsageRecord): void;
|
|
11
|
+
/** Get current spend in the budget period. */
|
|
12
|
+
getCurrentSpend(keyStr: string): number;
|
|
13
|
+
/** Get usage summary for a key. */
|
|
14
|
+
getUsageSummary(key: LimitKey): {
|
|
15
|
+
totalSpend: number;
|
|
16
|
+
totalTokens: number;
|
|
17
|
+
requestCount: number;
|
|
18
|
+
};
|
|
19
|
+
private cleanup;
|
|
20
|
+
destroy(): void;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=budgetTracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budgetTracker.d.ts","sourceRoot":"","sources":["../src/budgetTracker.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACZ,MAAM,YAAY,CAAC;AAOpB,qBAAa,qBAAqB;IAChC,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,eAAe,CAA+C;gBAE1D,MAAM,EAAE,YAAY;IAShC,wDAAwD;IACxD,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,iBAAiB;IAwB/D,+DAA+D;IAC/D,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI;IAU/C,8CAA8C;IAC9C,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAUvC,mCAAmC;IACnC,eAAe,CAAC,GAAG,EAAE,QAAQ,GAAG;QAC9B,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;KACtB;IAeD,OAAO,CAAC,OAAO;IAQf,OAAO;CAMR"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// packages/limitabl-core/src/budgetTracker.ts
|
|
2
|
+
//
|
|
3
|
+
// Per-user and per-org budget tracking with spend caps.
|
|
4
|
+
// In-memory implementation.
|
|
5
|
+
//
|
|
6
|
+
// FUTURE WORK:
|
|
7
|
+
// - Persistent storage adapter (Firestore, Redis, DynamoDB)
|
|
8
|
+
// - Budget alerting (webhook when 80%, 90%, 100% thresholds hit)
|
|
9
|
+
// - Per-model budget tracking (e.g., limit GPT-4 spend separately)
|
|
10
|
+
// - Budget rollover (carry unused budget to next period)
|
|
11
|
+
// - Budget delegation (org admin allocates budget to users)
|
|
12
|
+
import { resolveKey } from "./rateLimiter.js";
|
|
13
|
+
export class InMemoryBudgetTracker {
|
|
14
|
+
budgets = new Map();
|
|
15
|
+
config;
|
|
16
|
+
cleanupInterval = null;
|
|
17
|
+
constructor(config) {
|
|
18
|
+
this.config = config;
|
|
19
|
+
this.cleanupInterval = setInterval(() => this.cleanup(), config.periodMs / 10);
|
|
20
|
+
if (this.cleanupInterval.unref)
|
|
21
|
+
this.cleanupInterval.unref();
|
|
22
|
+
}
|
|
23
|
+
/** Check if a request is within budget (pre-flight). */
|
|
24
|
+
check(key, estimatedCost) {
|
|
25
|
+
const k = resolveKey(key);
|
|
26
|
+
const currentSpend = this.getCurrentSpend(k);
|
|
27
|
+
const effectiveSpend = currentSpend + (estimatedCost ?? 0);
|
|
28
|
+
if (effectiveSpend > this.config.maxSpend) {
|
|
29
|
+
return {
|
|
30
|
+
allowed: false,
|
|
31
|
+
currentSpend,
|
|
32
|
+
maxSpend: this.config.maxSpend,
|
|
33
|
+
percentUsed: Math.round((currentSpend / this.config.maxSpend) * 100),
|
|
34
|
+
reason: `Budget exceeded: ${currentSpend} / ${this.config.maxSpend} (estimated +${estimatedCost ?? 0})`,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
allowed: true,
|
|
39
|
+
currentSpend,
|
|
40
|
+
maxSpend: this.config.maxSpend,
|
|
41
|
+
percentUsed: Math.round((currentSpend / this.config.maxSpend) * 100),
|
|
42
|
+
reason: "Within budget",
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** Record usage after execution (post-execution / Phase 2). */
|
|
46
|
+
record(key, usage) {
|
|
47
|
+
const k = resolveKey(key);
|
|
48
|
+
let entry = this.budgets.get(k);
|
|
49
|
+
if (!entry) {
|
|
50
|
+
entry = { records: [] };
|
|
51
|
+
this.budgets.set(k, entry);
|
|
52
|
+
}
|
|
53
|
+
entry.records.push(usage);
|
|
54
|
+
}
|
|
55
|
+
/** Get current spend in the budget period. */
|
|
56
|
+
getCurrentSpend(keyStr) {
|
|
57
|
+
const entry = this.budgets.get(keyStr);
|
|
58
|
+
if (!entry)
|
|
59
|
+
return 0;
|
|
60
|
+
const periodStart = Date.now() - this.config.periodMs;
|
|
61
|
+
return entry.records
|
|
62
|
+
.filter((r) => r.timestamp > periodStart)
|
|
63
|
+
.reduce((sum, r) => sum + r.cost, 0);
|
|
64
|
+
}
|
|
65
|
+
/** Get usage summary for a key. */
|
|
66
|
+
getUsageSummary(key) {
|
|
67
|
+
const k = resolveKey(key);
|
|
68
|
+
const entry = this.budgets.get(k);
|
|
69
|
+
if (!entry)
|
|
70
|
+
return { totalSpend: 0, totalTokens: 0, requestCount: 0 };
|
|
71
|
+
const periodStart = Date.now() - this.config.periodMs;
|
|
72
|
+
const inPeriod = entry.records.filter((r) => r.timestamp > periodStart);
|
|
73
|
+
return {
|
|
74
|
+
totalSpend: inPeriod.reduce((s, r) => s + r.cost, 0),
|
|
75
|
+
totalTokens: inPeriod.reduce((s, r) => s + (r.tokens ?? 0), 0),
|
|
76
|
+
requestCount: inPeriod.length,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
cleanup() {
|
|
80
|
+
const cutoff = Date.now() - this.config.periodMs;
|
|
81
|
+
for (const [key, entry] of this.budgets) {
|
|
82
|
+
entry.records = entry.records.filter((r) => r.timestamp > cutoff);
|
|
83
|
+
if (entry.records.length === 0)
|
|
84
|
+
this.budgets.delete(key);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
destroy() {
|
|
88
|
+
if (this.cleanupInterval) {
|
|
89
|
+
clearInterval(this.cleanupInterval);
|
|
90
|
+
this.cleanupInterval = null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=budgetTracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budgetTracker.js","sourceRoot":"","sources":["../src/budgetTracker.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,mBAAmB,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// packages/limitabl-core/src/index.ts
|
|
2
|
+
//
|
|
3
|
+
// Core rate-limiting, budget, and agent protection logic.
|
|
4
|
+
// No Express, no HTTP. Pure functions + in-memory stores.
|
|
5
|
+
//
|
|
6
|
+
// FUTURE WORK:
|
|
7
|
+
// - Redis adapter for distributed rate limiting across instances
|
|
8
|
+
// - Anomaly detection (spike detection, unusual patterns)
|
|
9
|
+
// - Fallback provider routing (route to cheaper model when budget low)
|
|
10
|
+
// - Recursion depth tracking and duplicate tool call detection
|
|
11
|
+
// - Configurable storage backends (Redis, DynamoDB, Firestore)
|
|
12
|
+
export * from "./rateLimiter.js";
|
|
13
|
+
export * from "./budgetTracker.js";
|
|
14
|
+
export * from "./agentGuard.js";
|
|
15
|
+
export * from "./preflight.js";
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,EAAE;AACF,0DAA0D;AAC1D,0DAA0D;AAC1D,EAAE;AACF,eAAe;AACf,iEAAiE;AACjE,0DAA0D;AAC1D,uEAAuE;AACvE,+DAA+D;AAC/D,+DAA+D;AAE/D,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { LimitKey, RateLimitConfig, BudgetConfig, AgentGuardConfig, PreflightResult, PostExecutionInput } from "./types.js";
|
|
2
|
+
export interface LimitablCoreConfig {
|
|
3
|
+
rateLimit?: RateLimitConfig;
|
|
4
|
+
budget?: BudgetConfig;
|
|
5
|
+
agentGuard?: AgentGuardConfig;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Orchestrates all limitabl checks.
|
|
9
|
+
*
|
|
10
|
+
* Phase 1 (pre-flight): call preflight() before executing a request.
|
|
11
|
+
* Phase 2 (post-execution): call recordUsage() after execution completes.
|
|
12
|
+
*/
|
|
13
|
+
export declare class LimitablEngine {
|
|
14
|
+
private rateLimiter?;
|
|
15
|
+
private budgetTracker?;
|
|
16
|
+
private agentGuard?;
|
|
17
|
+
constructor(config: LimitablCoreConfig);
|
|
18
|
+
/**
|
|
19
|
+
* Phase 1: Pre-flight check.
|
|
20
|
+
* Returns whether the request should proceed.
|
|
21
|
+
*/
|
|
22
|
+
preflight(key: LimitKey, opts?: {
|
|
23
|
+
workflowId?: string;
|
|
24
|
+
estimatedCost?: number;
|
|
25
|
+
}): PreflightResult;
|
|
26
|
+
/**
|
|
27
|
+
* Phase 2: Record usage after execution.
|
|
28
|
+
* Updates budget tracker and agent guard counters.
|
|
29
|
+
*/
|
|
30
|
+
recordUsage(input: PostExecutionInput): void;
|
|
31
|
+
/** Clean up (stop timers). */
|
|
32
|
+
destroy(): void;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=preflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../src/preflight.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,eAAe,EAEf,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAKpB,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAED;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAC,CAAsB;IAC1C,OAAO,CAAC,aAAa,CAAC,CAAwB;IAC9C,OAAO,CAAC,UAAU,CAAC,CAAa;gBAEpB,MAAM,EAAE,kBAAkB;IAYtC;;;OAGG;IACH,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,eAAe;IAwCjG;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAS5C,8BAA8B;IAC9B,OAAO,IAAI,IAAI;CAIhB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// packages/limitabl-core/src/preflight.ts
|
|
2
|
+
//
|
|
3
|
+
// Combined pre-flight check: runs rate limit + budget + agent guard
|
|
4
|
+
// and returns a single decision.
|
|
5
|
+
import { InMemoryRateLimiter } from "./rateLimiter.js";
|
|
6
|
+
import { InMemoryBudgetTracker } from "./budgetTracker.js";
|
|
7
|
+
import { AgentGuard } from "./agentGuard.js";
|
|
8
|
+
/**
|
|
9
|
+
* Orchestrates all limitabl checks.
|
|
10
|
+
*
|
|
11
|
+
* Phase 1 (pre-flight): call preflight() before executing a request.
|
|
12
|
+
* Phase 2 (post-execution): call recordUsage() after execution completes.
|
|
13
|
+
*/
|
|
14
|
+
export class LimitablEngine {
|
|
15
|
+
rateLimiter;
|
|
16
|
+
budgetTracker;
|
|
17
|
+
agentGuard;
|
|
18
|
+
constructor(config) {
|
|
19
|
+
if (config.rateLimit) {
|
|
20
|
+
this.rateLimiter = new InMemoryRateLimiter(config.rateLimit);
|
|
21
|
+
}
|
|
22
|
+
if (config.budget) {
|
|
23
|
+
this.budgetTracker = new InMemoryBudgetTracker(config.budget);
|
|
24
|
+
}
|
|
25
|
+
if (config.agentGuard) {
|
|
26
|
+
this.agentGuard = new AgentGuard(config.agentGuard);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Phase 1: Pre-flight check.
|
|
31
|
+
* Returns whether the request should proceed.
|
|
32
|
+
*/
|
|
33
|
+
preflight(key, opts) {
|
|
34
|
+
// Rate limit check
|
|
35
|
+
if (this.rateLimiter) {
|
|
36
|
+
const rl = this.rateLimiter.check(key);
|
|
37
|
+
if (!rl.allowed) {
|
|
38
|
+
return {
|
|
39
|
+
allowed: false,
|
|
40
|
+
reason: `Rate limited. Retry after ${rl.retryAfterSec}s`,
|
|
41
|
+
rateLimit: rl,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Budget check
|
|
46
|
+
if (this.budgetTracker) {
|
|
47
|
+
const budget = this.budgetTracker.check(key, opts?.estimatedCost);
|
|
48
|
+
if (!budget.allowed) {
|
|
49
|
+
return {
|
|
50
|
+
allowed: false,
|
|
51
|
+
reason: budget.reason,
|
|
52
|
+
budget,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Agent guard check
|
|
57
|
+
if (this.agentGuard && opts?.workflowId) {
|
|
58
|
+
const guard = this.agentGuard.check(opts.workflowId);
|
|
59
|
+
if (!guard.allowed) {
|
|
60
|
+
return {
|
|
61
|
+
allowed: false,
|
|
62
|
+
reason: guard.reason,
|
|
63
|
+
agentGuard: guard,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { allowed: true, reason: "All checks passed" };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Phase 2: Record usage after execution.
|
|
71
|
+
* Updates budget tracker and agent guard counters.
|
|
72
|
+
*/
|
|
73
|
+
recordUsage(input) {
|
|
74
|
+
if (this.budgetTracker) {
|
|
75
|
+
this.budgetTracker.record(input.key, input.usage);
|
|
76
|
+
}
|
|
77
|
+
if (this.agentGuard && input.workflowId) {
|
|
78
|
+
this.agentGuard.recordToolCall(input.workflowId, input.usage.cost);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Clean up (stop timers). */
|
|
82
|
+
destroy() {
|
|
83
|
+
this.rateLimiter?.destroy();
|
|
84
|
+
this.budgetTracker?.destroy();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.js","sourceRoot":"","sources":["../src/preflight.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { LimitKey, RateLimitConfig, RateLimitResult } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve a LimitKey to a string key.
|
|
4
|
+
* Priority: sub > orgId > ip > "anonymous".
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveKey(key: LimitKey): string;
|
|
7
|
+
export declare class InMemoryRateLimiter {
|
|
8
|
+
private windows;
|
|
9
|
+
private config;
|
|
10
|
+
private cleanupInterval;
|
|
11
|
+
constructor(config: RateLimitConfig);
|
|
12
|
+
/** Check if a request is allowed and record it if so. */
|
|
13
|
+
check(key: LimitKey): RateLimitResult;
|
|
14
|
+
/** Remove expired entries to prevent memory growth. */
|
|
15
|
+
private cleanup;
|
|
16
|
+
/** Stop the cleanup interval (for graceful shutdown / testing). */
|
|
17
|
+
destroy(): void;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=rateLimiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rateLimiter.d.ts","sourceRoot":"","sources":["../src/rateLimiter.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAM7E;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAQhD;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,eAAe,CAA+C;gBAE1D,MAAM,EAAE,eAAe;IAQnC,yDAAyD;IACzD,KAAK,CAAC,GAAG,EAAE,QAAQ,GAAG,eAAe;IAmCrC,uDAAuD;IACvD,OAAO,CAAC,OAAO;IAQf,mEAAmE;IACnE,OAAO;CAMR"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// packages/limitabl-core/src/rateLimiter.ts
|
|
2
|
+
//
|
|
3
|
+
// Sliding window rate limiter. In-memory implementation.
|
|
4
|
+
//
|
|
5
|
+
// FUTURE WORK:
|
|
6
|
+
// - Redis adapter: replace InMemoryRateLimiter with RedisRateLimiter
|
|
7
|
+
// that uses MULTI/EXEC for atomic window operations.
|
|
8
|
+
// - Token bucket algorithm option for burst-friendly workloads.
|
|
9
|
+
/**
|
|
10
|
+
* Resolve a LimitKey to a string key.
|
|
11
|
+
* Priority: sub > orgId > ip > "anonymous".
|
|
12
|
+
*/
|
|
13
|
+
export function resolveKey(key) {
|
|
14
|
+
const parts = [];
|
|
15
|
+
if (key.tenantId)
|
|
16
|
+
parts.push(`t:${key.tenantId}`);
|
|
17
|
+
if (key.sub)
|
|
18
|
+
parts.push(`u:${key.sub}`);
|
|
19
|
+
else if (key.orgId)
|
|
20
|
+
parts.push(`o:${key.orgId}`);
|
|
21
|
+
else if (key.ip)
|
|
22
|
+
parts.push(`ip:${key.ip}`);
|
|
23
|
+
else
|
|
24
|
+
parts.push("anonymous");
|
|
25
|
+
return parts.join("|");
|
|
26
|
+
}
|
|
27
|
+
export class InMemoryRateLimiter {
|
|
28
|
+
windows = new Map();
|
|
29
|
+
config;
|
|
30
|
+
cleanupInterval = null;
|
|
31
|
+
constructor(config) {
|
|
32
|
+
this.config = config;
|
|
33
|
+
// Periodically clean expired entries
|
|
34
|
+
this.cleanupInterval = setInterval(() => this.cleanup(), config.windowMs * 2);
|
|
35
|
+
// Allow process to exit even if interval is active
|
|
36
|
+
if (this.cleanupInterval.unref)
|
|
37
|
+
this.cleanupInterval.unref();
|
|
38
|
+
}
|
|
39
|
+
/** Check if a request is allowed and record it if so. */
|
|
40
|
+
check(key) {
|
|
41
|
+
const k = resolveKey(key);
|
|
42
|
+
const now = Date.now();
|
|
43
|
+
const windowStart = now - this.config.windowMs;
|
|
44
|
+
let entry = this.windows.get(k);
|
|
45
|
+
if (!entry) {
|
|
46
|
+
entry = { timestamps: [] };
|
|
47
|
+
this.windows.set(k, entry);
|
|
48
|
+
}
|
|
49
|
+
// Remove expired timestamps
|
|
50
|
+
entry.timestamps = entry.timestamps.filter((t) => t > windowStart);
|
|
51
|
+
if (entry.timestamps.length >= this.config.maxRequests) {
|
|
52
|
+
const oldestInWindow = entry.timestamps[0];
|
|
53
|
+
const resetAt = oldestInWindow + this.config.windowMs;
|
|
54
|
+
return {
|
|
55
|
+
allowed: false,
|
|
56
|
+
remaining: 0,
|
|
57
|
+
resetAt,
|
|
58
|
+
retryAfterSec: Math.ceil((resetAt - now) / 1000),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// Record this request
|
|
62
|
+
entry.timestamps.push(now);
|
|
63
|
+
return {
|
|
64
|
+
allowed: true,
|
|
65
|
+
remaining: this.config.maxRequests - entry.timestamps.length,
|
|
66
|
+
resetAt: now + this.config.windowMs,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** Remove expired entries to prevent memory growth. */
|
|
70
|
+
cleanup() {
|
|
71
|
+
const cutoff = Date.now() - this.config.windowMs;
|
|
72
|
+
for (const [key, entry] of this.windows) {
|
|
73
|
+
entry.timestamps = entry.timestamps.filter((t) => t > cutoff);
|
|
74
|
+
if (entry.timestamps.length === 0)
|
|
75
|
+
this.windows.delete(key);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** Stop the cleanup interval (for graceful shutdown / testing). */
|
|
79
|
+
destroy() {
|
|
80
|
+
if (this.cleanupInterval) {
|
|
81
|
+
clearInterval(this.cleanupInterval);
|
|
82
|
+
this.cleanupInterval = null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=rateLimiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rateLimiter.js","sourceRoot":"","sources":["../src/rateLimiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.es2021.d.ts","../../../node_modules/typescript/lib/lib.es2022.d.ts","../../../node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/typescript/lib/lib.dom.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../../node_modules/typescript/lib/lib.es2022.array.d.ts","../../../node_modules/typescript/lib/lib.es2022.error.d.ts","../../../node_modules/typescript/lib/lib.es2022.intl.d.ts","../../../node_modules/typescript/lib/lib.es2022.object.d.ts","../../../node_modules/typescript/lib/lib.es2022.string.d.ts","../../../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../../node_modules/typescript/lib/lib.decorators.d.ts","../../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../node_modules/@types/react/global.d.ts","../../../node_modules/csstype/index.d.ts","../../../node_modules/@types/react/index.d.ts","../../../node_modules/@types/react/jsx-runtime.d.ts","../src/types.ts","../src/agentguard.ts","../src/ratelimiter.ts","../src/budgettracker.ts","../src/preflight.ts","../src/index.ts","../../../node_modules/@types/node/compatibility/disposable.d.ts","../../../node_modules/@types/node/compatibility/indexable.d.ts","../../../node_modules/@types/node/compatibility/iterators.d.ts","../../../node_modules/@types/node/compatibility/index.d.ts","../../../node_modules/@types/node/globals.typedarray.d.ts","../../../node_modules/@types/node/buffer.buffer.d.ts","../../../node_modules/@types/node/globals.d.ts","../../../node_modules/@types/node/web-globals/abortcontroller.d.ts","../../../node_modules/@types/node/web-globals/domexception.d.ts","../../../node_modules/@types/node/web-globals/events.d.ts","../../../node_modules/undici-types/header.d.ts","../../../node_modules/undici-types/readable.d.ts","../../../node_modules/undici-types/file.d.ts","../../../node_modules/undici-types/fetch.d.ts","../../../node_modules/undici-types/formdata.d.ts","../../../node_modules/undici-types/connector.d.ts","../../../node_modules/undici-types/client.d.ts","../../../node_modules/undici-types/errors.d.ts","../../../node_modules/undici-types/dispatcher.d.ts","../../../node_modules/undici-types/global-dispatcher.d.ts","../../../node_modules/undici-types/global-origin.d.ts","../../../node_modules/undici-types/pool-stats.d.ts","../../../node_modules/undici-types/pool.d.ts","../../../node_modules/undici-types/handlers.d.ts","../../../node_modules/undici-types/balanced-pool.d.ts","../../../node_modules/undici-types/agent.d.ts","../../../node_modules/undici-types/mock-interceptor.d.ts","../../../node_modules/undici-types/mock-agent.d.ts","../../../node_modules/undici-types/mock-client.d.ts","../../../node_modules/undici-types/mock-pool.d.ts","../../../node_modules/undici-types/mock-errors.d.ts","../../../node_modules/undici-types/proxy-agent.d.ts","../../../node_modules/undici-types/env-http-proxy-agent.d.ts","../../../node_modules/undici-types/retry-handler.d.ts","../../../node_modules/undici-types/retry-agent.d.ts","../../../node_modules/undici-types/api.d.ts","../../../node_modules/undici-types/interceptors.d.ts","../../../node_modules/undici-types/util.d.ts","../../../node_modules/undici-types/cookies.d.ts","../../../node_modules/undici-types/patch.d.ts","../../../node_modules/undici-types/websocket.d.ts","../../../node_modules/undici-types/eventsource.d.ts","../../../node_modules/undici-types/filereader.d.ts","../../../node_modules/undici-types/diagnostics-channel.d.ts","../../../node_modules/undici-types/content-type.d.ts","../../../node_modules/undici-types/cache.d.ts","../../../node_modules/undici-types/index.d.ts","../../../node_modules/@types/node/web-globals/fetch.d.ts","../../../node_modules/@types/node/web-globals/navigator.d.ts","../../../node_modules/@types/node/web-globals/storage.d.ts","../../../node_modules/@types/node/assert.d.ts","../../../node_modules/@types/node/assert/strict.d.ts","../../../node_modules/@types/node/async_hooks.d.ts","../../../node_modules/@types/node/buffer.d.ts","../../../node_modules/@types/node/child_process.d.ts","../../../node_modules/@types/node/cluster.d.ts","../../../node_modules/@types/node/console.d.ts","../../../node_modules/@types/node/constants.d.ts","../../../node_modules/@types/node/crypto.d.ts","../../../node_modules/@types/node/dgram.d.ts","../../../node_modules/@types/node/diagnostics_channel.d.ts","../../../node_modules/@types/node/dns.d.ts","../../../node_modules/@types/node/dns/promises.d.ts","../../../node_modules/@types/node/domain.d.ts","../../../node_modules/@types/node/events.d.ts","../../../node_modules/@types/node/fs.d.ts","../../../node_modules/@types/node/fs/promises.d.ts","../../../node_modules/@types/node/http.d.ts","../../../node_modules/@types/node/http2.d.ts","../../../node_modules/@types/node/https.d.ts","../../../node_modules/@types/node/inspector.d.ts","../../../node_modules/@types/node/inspector.generated.d.ts","../../../node_modules/@types/node/module.d.ts","../../../node_modules/@types/node/net.d.ts","../../../node_modules/@types/node/os.d.ts","../../../node_modules/@types/node/path.d.ts","../../../node_modules/@types/node/perf_hooks.d.ts","../../../node_modules/@types/node/process.d.ts","../../../node_modules/@types/node/punycode.d.ts","../../../node_modules/@types/node/querystring.d.ts","../../../node_modules/@types/node/readline.d.ts","../../../node_modules/@types/node/readline/promises.d.ts","../../../node_modules/@types/node/repl.d.ts","../../../node_modules/@types/node/sea.d.ts","../../../node_modules/@types/node/sqlite.d.ts","../../../node_modules/@types/node/stream.d.ts","../../../node_modules/@types/node/stream/promises.d.ts","../../../node_modules/@types/node/stream/consumers.d.ts","../../../node_modules/@types/node/stream/web.d.ts","../../../node_modules/@types/node/string_decoder.d.ts","../../../node_modules/@types/node/test.d.ts","../../../node_modules/@types/node/timers.d.ts","../../../node_modules/@types/node/timers/promises.d.ts","../../../node_modules/@types/node/tls.d.ts","../../../node_modules/@types/node/trace_events.d.ts","../../../node_modules/@types/node/tty.d.ts","../../../node_modules/@types/node/url.d.ts","../../../node_modules/@types/node/util.d.ts","../../../node_modules/@types/node/v8.d.ts","../../../node_modules/@types/node/vm.d.ts","../../../node_modules/@types/node/wasi.d.ts","../../../node_modules/@types/node/worker_threads.d.ts","../../../node_modules/@types/node/zlib.d.ts","../../../node_modules/@types/node/index.d.ts"],"fileIdsList":[[75,120,121,123,140,141],[75,122,123,140,141],[123,140,141],[75,123,128,140,141,158],[75,123,124,129,134,140,141,143,155,166],[75,123,124,125,134,140,141,143],[75,123,140,141],[70,71,72,75,123,140,141],[75,123,126,140,141,167],[75,123,127,128,135,140,141,144],[75,123,128,140,141,155,163],[75,123,129,131,134,140,141,143],[75,122,123,130,140,141],[75,123,131,132,140,141],[75,123,133,134,140,141],[75,122,123,134,140,141],[75,123,134,135,136,140,141,155,166],[75,123,134,135,136,140,141,150,155,158],[75,116,123,131,134,137,140,141,143,155,166],[75,123,134,135,137,138,140,141,143,155,163,166],[75,123,137,139,140,141,155,163,166],[73,74,75,76,77,78,79,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172],[75,123,134,140,141],[75,123,140,141,142,166],[75,123,131,134,140,141,143,155],[75,123,140,141,144],[75,123,140,141,145],[75,122,123,140,141,146],[75,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172],[75,123,140,141,148],[75,123,140,141,149],[75,123,134,140,141,150,151],[75,123,140,141,150,152,167,169],[75,123,135,140,141],[75,123,134,140,141,155,156,158],[75,123,140,141,157,158],[75,123,140,141,155,156],[75,123,140,141,158],[75,123,140,141,159],[75,120,123,140,141,155,160],[75,123,134,140,141,161,162],[75,123,140,141,161,162],[75,123,128,140,141,143,155,163],[75,123,140,141,164],[75,123,140,141,143,165],[75,123,137,140,141,149,166],[75,123,128,140,141,167],[75,123,140,141,155,168],[75,123,140,141,142,169],[75,123,140,141,170],[75,116,123,140,141],[75,116,123,134,136,140,141,146,155,158,166,168,169,171],[75,123,140,141,155,172],[60,61,75,123,140,141],[62,75,123,140,141],[75,88,92,123,140,141,166],[75,88,123,140,141,155,166],[75,83,123,140,141],[75,85,88,123,140,141,163,166],[75,123,140,141,143,163],[75,123,140,141,173],[75,83,123,140,141,173],[75,85,88,123,140,141,143,166],[75,80,81,84,87,123,134,140,141,155,166],[75,88,95,123,140,141],[75,80,86,123,140,141],[75,88,109,110,123,140,141],[75,84,88,123,140,141,158,166,173],[75,109,123,140,141,173],[75,82,83,123,140,141,173],[75,88,123,140,141],[75,82,83,84,85,86,87,88,89,90,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,110,111,112,113,114,115,123,140,141],[75,88,103,123,140,141],[75,88,95,96,123,140,141],[75,86,88,96,97,123,140,141],[75,87,123,140,141],[75,80,83,88,123,140,141],[75,88,92,96,97,123,140,141],[75,92,123,140,141],[75,86,88,91,123,140,141,166],[75,80,85,88,95,123,140,141],[75,123,140,141,155],[75,83,88,109,123,140,141,171,173],[63,64,75,123,140,141],[63,64,66,75,123,140,141],[63,64,65,66,67,68,75,123,140,141],[63,64,65,66,67,75,123,140,141],[63,75,123,140,141]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2e80ee7a49e8ac312cc11b77f1475804bee36b3b2bc896bead8b6e1266befb43","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"170d4db14678c68178ee8a3d5a990d5afb759ecb6ec44dbd885c50f6da6204f6","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac51dd7d31333793807a6abaa5ae168512b6131bd41d9c5b98477fc3b7800f9f","impliedFormat":1},{"version":"5e76305d58bcdc924ff2bf14f6a9dc2aa5441ed06464b7e7bd039e611d66a89b","impliedFormat":1},{"version":"42c169fb8c2d42f4f668c624a9a11e719d5d07dacbebb63cbcf7ef365b0a75b3","impliedFormat":1},{"version":"33794c9a810b6fd1d450fd827c7ef2cc49255fc3f6bf271b4cd6314e30e87173","signature":"e248889ecee6474f7964a1fc7049688812d7a021c118dd81d930486d2dfff0ac"},{"version":"d54b20ad3dc2666e17e4b002c3245fdd061b71d372296c6f573b6f122e4321ad","signature":"62f0b841ce3f6e2b6b5a06e4af57681bdb49b8785d40f6ac4aab3aa2a6a688d9"},{"version":"b5dd8566da60fca8b3221d981c61ade56203e61de26b2133687ac2dca6d9b1c4","signature":"e80a16497a424b984f17bd7cacc49c46614bda5caa8774701c150b0fa18d66e2"},{"version":"e14bae7c47df944cdb6176bb5729c0a8685520b25bc308eac6a1085bc0f448bf","signature":"8c59bc43b4d0e42eea23a90559518227cce8466a1954277d28cb8a7641ae153b"},{"version":"a788d57499cb25974ddb4f89abba90deb8d10ce2c818aefb5346bb24feb3c10f","signature":"a8a4d64e9843f68f449422b6b83cb9cc4cf4ca8b48da8376c2825fa0f7e791ac"},{"version":"232ef7aee8e8f5d3f34c0798b7395e43623b14c41feaceabaf087fe9a7b2b4fc","signature":"9bae6ea8b79a90c927fe69d7294ab67c51922bd60ef95eaee225fe6c0f9c5db4"},{"version":"6c7176368037af28cb72f2392010fa1cef295d6d6744bca8cfb54985f3a18c3e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"437e20f2ba32abaeb7985e0afe0002de1917bc74e949ba585e49feba65da6ca1","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"3af97acf03cc97de58a3a4bc91f8f616408099bc4233f6d0852e72a8ffb91ac9","affectsGlobalScope":true,"impliedFormat":1},{"version":"808069bba06b6768b62fd22429b53362e7af342da4a236ed2d2e1c89fcca3b4a","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"2cbe0621042e2a68c7cbce5dfed3906a1862a16a7d496010636cdbdb91341c0f","affectsGlobalScope":true,"impliedFormat":1},{"version":"f9501cc13ce624c72b61f12b3963e84fad210fbdf0ffbc4590e08460a3f04eba","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0fa06ada475b910e2106c98c68b10483dc8811d0c14a8a8dd36efb2672485b29","impliedFormat":1},{"version":"33e5e9aba62c3193d10d1d33ae1fa75c46a1171cf76fef750777377d53b0303f","impliedFormat":1},{"version":"2b06b93fd01bcd49d1a6bd1f9b65ddcae6480b9a86e9061634d6f8e354c1468f","impliedFormat":1},{"version":"6a0cd27e5dc2cfbe039e731cf879d12b0e2dded06d1b1dedad07f7712de0d7f4","affectsGlobalScope":true,"impliedFormat":1},{"version":"13f5c844119c43e51ce777c509267f14d6aaf31eafb2c2b002ca35584cd13b29","impliedFormat":1},{"version":"e60477649d6ad21542bd2dc7e3d9ff6853d0797ba9f689ba2f6653818999c264","impliedFormat":1},{"version":"c2510f124c0293ab80b1777c44d80f812b75612f297b9857406468c0f4dafe29","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"4c829ab315f57c5442c6667b53769975acbf92003a66aef19bce151987675bd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"b2ade7657e2db96d18315694789eff2ddd3d8aea7215b181f8a0b303277cc579","impliedFormat":1},{"version":"9855e02d837744303391e5623a531734443a5f8e6e8755e018c41d63ad797db2","impliedFormat":1},{"version":"4d631b81fa2f07a0e63a9a143d6a82c25c5f051298651a9b69176ba28930756d","impliedFormat":1},{"version":"836a356aae992ff3c28a0212e3eabcb76dd4b0cc06bcb9607aeef560661b860d","impliedFormat":1},{"version":"1e0d1f8b0adfa0b0330e028c7941b5a98c08b600efe7f14d2d2a00854fb2f393","impliedFormat":1},{"version":"41670ee38943d9cbb4924e436f56fc19ee94232bc96108562de1a734af20dc2c","affectsGlobalScope":true,"impliedFormat":1},{"version":"c906fb15bd2aabc9ed1e3f44eb6a8661199d6c320b3aa196b826121552cb3695","impliedFormat":1},{"version":"22295e8103f1d6d8ea4b5d6211e43421fe4564e34d0dd8e09e520e452d89e659","impliedFormat":1},{"version":"bb45cd435da536500f1d9692a9b49d0c570b763ccbf00473248b777f5c1f353b","impliedFormat":1},{"version":"6b4e081d55ac24fc8a4631d5dd77fe249fa25900abd7d046abb87d90e3b45645","impliedFormat":1},{"version":"a10f0e1854f3316d7ee437b79649e5a6ae3ae14ffe6322b02d4987071a95362e","impliedFormat":1},{"version":"e208f73ef6a980104304b0d2ca5f6bf1b85de6009d2c7e404028b875020fa8f2","impliedFormat":1},{"version":"d163b6bc2372b4f07260747cbc6c0a6405ab3fbcea3852305e98ac43ca59f5bc","impliedFormat":1},{"version":"e6fa9ad47c5f71ff733744a029d1dc472c618de53804eae08ffc243b936f87ff","affectsGlobalScope":true,"impliedFormat":1},{"version":"83e63d6ccf8ec004a3bb6d58b9bb0104f60e002754b1e968024b320730cc5311","impliedFormat":1},{"version":"24826ed94a78d5c64bd857570fdbd96229ad41b5cb654c08d75a9845e3ab7dde","impliedFormat":1},{"version":"8b479a130ccb62e98f11f136d3ac80f2984fdc07616516d29881f3061f2dd472","impliedFormat":1},{"version":"928af3d90454bf656a52a48679f199f64c1435247d6189d1caf4c68f2eaf921f","affectsGlobalScope":true,"impliedFormat":1},{"version":"21145ce1c54e05ef9e52092b98a4ebfb326b92f52e76e47211c50cfcd2a2b4ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f16a7e4deafa527ed9995a772bb380eb7d3c2c0fd4ae178c5263ed18394db2c","impliedFormat":1},{"version":"933921f0bb0ec12ef45d1062a1fc0f27635318f4d294e4d99de9a5493e618ca2","impliedFormat":1},{"version":"71a0f3ad612c123b57239a7749770017ecfe6b66411488000aba83e4546fde25","impliedFormat":1},{"version":"77fbe5eecb6fac4b6242bbf6eebfc43e98ce5ccba8fa44e0ef6a95c945ff4d98","impliedFormat":1},{"version":"4f9d8ca0c417b67b69eeb54c7ca1bedd7b56034bb9bfd27c5d4f3bc4692daca7","impliedFormat":1},{"version":"814118df420c4e38fe5ae1b9a3bafb6e9c2aa40838e528cde908381867be6466","impliedFormat":1},{"version":"a3fc63c0d7b031693f665f5494412ba4b551fe644ededccc0ab5922401079c95","impliedFormat":1},{"version":"f27524f4bef4b6519c604bdb23bf4465bddcccbf3f003abb901acbd0d7404d99","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"dba28a419aec76ed864ef43e5f577a5c99a010c32e5949fe4e17a4d57c58dd11","affectsGlobalScope":true,"impliedFormat":1},{"version":"18fd40412d102c5564136f29735e5d1c3b455b8a37f920da79561f1fde068208","impliedFormat":1},{"version":"c959a391a75be9789b43c8468f71e3fa06488b4d691d5729dde1416dcd38225b","impliedFormat":1},{"version":"f0be1b8078cd549d91f37c30c222c2a187ac1cf981d994fb476a1adc61387b14","affectsGlobalScope":true,"impliedFormat":1},{"version":"0aaed1d72199b01234152f7a60046bc947f1f37d78d182e9ae09c4289e06a592","impliedFormat":1},{"version":"5ebe6f4cc3b803cbfc962bae0d954f9c80e5078ca41eb3f1de41d92e7193ef37","impliedFormat":1},{"version":"66ba1b2c3e3a3644a1011cd530fb444a96b1b2dfe2f5e837a002d41a1a799e60","impliedFormat":1},{"version":"7e514f5b852fdbc166b539fdd1f4e9114f29911592a5eb10a94bb3a13ccac3c4","impliedFormat":1},{"version":"5b7aa3c4c1a5d81b411e8cb302b45507fea9358d3569196b27eb1a27ae3a90ef","affectsGlobalScope":true,"impliedFormat":1},{"version":"5987a903da92c7462e0b35704ce7da94d7fdc4b89a984871c0e2b87a8aae9e69","affectsGlobalScope":true,"impliedFormat":1},{"version":"ea08a0345023ade2b47fbff5a76d0d0ed8bff10bc9d22b83f40858a8e941501c","impliedFormat":1},{"version":"47613031a5a31510831304405af561b0ffaedb734437c595256bb61a90f9311b","impliedFormat":1},{"version":"ae062ce7d9510060c5d7e7952ae379224fb3f8f2dd74e88959878af2057c143b","impliedFormat":1},{"version":"8a1a0d0a4a06a8d278947fcb66bf684f117bf147f89b06e50662d79a53be3e9f","affectsGlobalScope":true,"impliedFormat":1},{"version":"9f663c2f91127ef7024e8ca4b3b4383ff2770e5f826696005de382282794b127","impliedFormat":1},{"version":"9f55299850d4f0921e79b6bf344b47c420ce0f507b9dcf593e532b09ea7eeea1","impliedFormat":1}],"root":[[64,69]],"options":{"allowSyntheticDefaultImports":true,"composite":true,"declaration":true,"declarationMap":true,"esModuleInterop":true,"jsx":4,"jsxImportSource":"react","module":99,"outDir":"./","rootDir":"../src","skipLibCheck":true,"sourceMap":true,"strict":true,"target":9,"tsBuildInfoFile":"./tsconfig.tsbuildinfo"},"referencedMap":[[120,1],[121,1],[122,2],[75,3],[123,4],[124,5],[125,6],[70,7],[73,8],[71,7],[72,7],[126,9],[127,10],[128,11],[129,12],[130,13],[131,14],[132,14],[133,15],[134,16],[135,17],[136,18],[76,7],[74,7],[137,19],[138,20],[139,21],[173,22],[140,23],[141,7],[142,24],[143,25],[144,26],[145,27],[146,28],[147,29],[148,30],[149,31],[150,32],[151,32],[152,33],[153,7],[154,34],[155,35],[157,36],[156,37],[158,38],[159,39],[160,40],[161,41],[162,42],[163,43],[164,44],[165,45],[166,46],[167,47],[168,48],[169,49],[170,50],[77,7],[78,7],[79,7],[117,51],[118,7],[119,7],[171,52],[172,53],[60,7],[62,54],[63,55],[61,7],[58,7],[59,7],[10,7],[11,7],[13,7],[12,7],[2,7],[14,7],[15,7],[16,7],[17,7],[18,7],[19,7],[20,7],[21,7],[3,7],[22,7],[23,7],[4,7],[24,7],[28,7],[25,7],[26,7],[27,7],[29,7],[30,7],[31,7],[5,7],[32,7],[33,7],[34,7],[35,7],[6,7],[39,7],[36,7],[37,7],[38,7],[40,7],[7,7],[41,7],[46,7],[47,7],[42,7],[43,7],[44,7],[45,7],[8,7],[51,7],[48,7],[49,7],[50,7],[52,7],[9,7],[53,7],[54,7],[55,7],[57,7],[56,7],[1,7],[95,56],[105,57],[94,56],[115,58],[86,59],[85,60],[114,61],[108,62],[113,63],[88,64],[102,65],[87,66],[111,67],[83,68],[82,61],[112,69],[84,70],[89,71],[90,7],[93,71],[80,7],[116,72],[106,73],[97,74],[98,75],[100,76],[96,77],[99,78],[109,61],[91,79],[92,80],[101,81],[81,82],[104,73],[103,71],[107,7],[110,83],[65,84],[67,85],[69,86],[68,87],[66,84],[64,88]],"latestChangedDtsFile":"./index.d.ts","version":"5.9.3"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/** Identity key used for rate limiting and budget tracking. */
|
|
2
|
+
export interface LimitKey {
|
|
3
|
+
/** User ID (from JWT sub claim). */
|
|
4
|
+
sub?: string;
|
|
5
|
+
/** Organization ID (from JWT org_id claim). */
|
|
6
|
+
orgId?: string;
|
|
7
|
+
/** IP address (fallback). */
|
|
8
|
+
ip?: string;
|
|
9
|
+
/** Tenant ID (for multi-tenant deployments). */
|
|
10
|
+
tenantId?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Rate limit configuration. */
|
|
13
|
+
export interface RateLimitConfig {
|
|
14
|
+
/** Window size in milliseconds. */
|
|
15
|
+
windowMs: number;
|
|
16
|
+
/** Maximum requests per window. */
|
|
17
|
+
maxRequests: number;
|
|
18
|
+
}
|
|
19
|
+
/** Result of a rate limit check. */
|
|
20
|
+
export interface RateLimitResult {
|
|
21
|
+
allowed: boolean;
|
|
22
|
+
/** Requests remaining in current window. */
|
|
23
|
+
remaining: number;
|
|
24
|
+
/** When the current window resets (epoch ms). */
|
|
25
|
+
resetAt: number;
|
|
26
|
+
/** Retry-After value in seconds (if denied). */
|
|
27
|
+
retryAfterSec?: number;
|
|
28
|
+
}
|
|
29
|
+
/** Budget configuration for a single entity (user, org, tenant). */
|
|
30
|
+
export interface BudgetConfig {
|
|
31
|
+
/** Maximum spend in the budget period (in cents or smallest currency unit). */
|
|
32
|
+
maxSpend: number;
|
|
33
|
+
/** Budget period in milliseconds (e.g., 30 days). */
|
|
34
|
+
periodMs: number;
|
|
35
|
+
/** Optional per-model spend limits. */
|
|
36
|
+
modelLimits?: Record<string, number>;
|
|
37
|
+
}
|
|
38
|
+
/** A single usage record (post-execution). */
|
|
39
|
+
export interface UsageRecord {
|
|
40
|
+
/** When the usage occurred (epoch ms). */
|
|
41
|
+
timestamp: number;
|
|
42
|
+
/** Cost in cents or smallest currency unit. */
|
|
43
|
+
cost: number;
|
|
44
|
+
/** Token count (input + output). */
|
|
45
|
+
tokens?: number;
|
|
46
|
+
/** Model used. */
|
|
47
|
+
model?: string;
|
|
48
|
+
/** Tool invoked. */
|
|
49
|
+
tool?: string;
|
|
50
|
+
}
|
|
51
|
+
/** Result of a budget check. */
|
|
52
|
+
export interface BudgetCheckResult {
|
|
53
|
+
allowed: boolean;
|
|
54
|
+
/** Current spend in the budget period. */
|
|
55
|
+
currentSpend: number;
|
|
56
|
+
/** Maximum allowed spend. */
|
|
57
|
+
maxSpend: number;
|
|
58
|
+
/** Percentage of budget used (0-100+). */
|
|
59
|
+
percentUsed: number;
|
|
60
|
+
reason: string;
|
|
61
|
+
}
|
|
62
|
+
/** Agent guard configuration. */
|
|
63
|
+
export interface AgentGuardConfig {
|
|
64
|
+
/** Maximum tool calls per workflow/session. Default: 50. */
|
|
65
|
+
maxToolCalls?: number;
|
|
66
|
+
/** Maximum total cost per workflow (cents). Default: 1000 ($10). */
|
|
67
|
+
maxWorkflowCost?: number;
|
|
68
|
+
/** Maximum workflow duration in milliseconds. Default: 300000 (5 min). */
|
|
69
|
+
maxDurationMs?: number;
|
|
70
|
+
}
|
|
71
|
+
/** Result of an agent guard check. */
|
|
72
|
+
export interface AgentGuardResult {
|
|
73
|
+
allowed: boolean;
|
|
74
|
+
reason: string;
|
|
75
|
+
toolCallCount: number;
|
|
76
|
+
workflowCost: number;
|
|
77
|
+
durationMs: number;
|
|
78
|
+
}
|
|
79
|
+
/** Combined pre-flight check result. */
|
|
80
|
+
export interface PreflightResult {
|
|
81
|
+
allowed: boolean;
|
|
82
|
+
reason: string;
|
|
83
|
+
rateLimit?: RateLimitResult;
|
|
84
|
+
budget?: BudgetCheckResult;
|
|
85
|
+
agentGuard?: AgentGuardResult;
|
|
86
|
+
}
|
|
87
|
+
/** Post-execution recording input. */
|
|
88
|
+
export interface PostExecutionInput {
|
|
89
|
+
key: LimitKey;
|
|
90
|
+
usage: UsageRecord;
|
|
91
|
+
workflowId?: string;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,+DAA+D;AAC/D,MAAM,WAAW,QAAQ;IACvB,oCAAoC;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,gCAAgC;AAChC,MAAM,WAAW,eAAe;IAC9B,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,oEAAoE;AACpE,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAED,8CAA8C;AAC9C,MAAM,WAAW,WAAW;IAC1B,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,gCAAgC;AAChC,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,iCAAiC;AACjC,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,sCAAsC;AACtC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wCAAwC;AACxC,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAED,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,WAAW,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,sCAAsC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gatewaystack/limitabl-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc -p tsconfig.json",
|
|
19
|
+
"prepublishOnly": "npm run build"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"typescript": "^5.6.3"
|
|
23
|
+
}
|
|
24
|
+
}
|