@lleverage-ai/agent-sdk 0.0.1

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.
Files changed (327) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2321 -0
  3. package/dist/agent.d.ts +52 -0
  4. package/dist/agent.d.ts.map +1 -0
  5. package/dist/agent.js +2122 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/backend.d.ts +378 -0
  8. package/dist/backend.d.ts.map +1 -0
  9. package/dist/backend.js +71 -0
  10. package/dist/backend.js.map +1 -0
  11. package/dist/backends/composite.d.ts +258 -0
  12. package/dist/backends/composite.d.ts.map +1 -0
  13. package/dist/backends/composite.js +437 -0
  14. package/dist/backends/composite.js.map +1 -0
  15. package/dist/backends/filesystem.d.ts +268 -0
  16. package/dist/backends/filesystem.d.ts.map +1 -0
  17. package/dist/backends/filesystem.js +623 -0
  18. package/dist/backends/filesystem.js.map +1 -0
  19. package/dist/backends/index.d.ts +14 -0
  20. package/dist/backends/index.d.ts.map +1 -0
  21. package/dist/backends/index.js +14 -0
  22. package/dist/backends/index.js.map +1 -0
  23. package/dist/backends/persistent.d.ts +312 -0
  24. package/dist/backends/persistent.d.ts.map +1 -0
  25. package/dist/backends/persistent.js +519 -0
  26. package/dist/backends/persistent.js.map +1 -0
  27. package/dist/backends/sandbox.d.ts +315 -0
  28. package/dist/backends/sandbox.d.ts.map +1 -0
  29. package/dist/backends/sandbox.js +490 -0
  30. package/dist/backends/sandbox.js.map +1 -0
  31. package/dist/backends/state.d.ts +225 -0
  32. package/dist/backends/state.d.ts.map +1 -0
  33. package/dist/backends/state.js +396 -0
  34. package/dist/backends/state.js.map +1 -0
  35. package/dist/checkpointer/file-saver.d.ts +182 -0
  36. package/dist/checkpointer/file-saver.d.ts.map +1 -0
  37. package/dist/checkpointer/file-saver.js +298 -0
  38. package/dist/checkpointer/file-saver.js.map +1 -0
  39. package/dist/checkpointer/index.d.ts +40 -0
  40. package/dist/checkpointer/index.d.ts.map +1 -0
  41. package/dist/checkpointer/index.js +40 -0
  42. package/dist/checkpointer/index.js.map +1 -0
  43. package/dist/checkpointer/kv-saver.d.ts +142 -0
  44. package/dist/checkpointer/kv-saver.d.ts.map +1 -0
  45. package/dist/checkpointer/kv-saver.js +176 -0
  46. package/dist/checkpointer/kv-saver.js.map +1 -0
  47. package/dist/checkpointer/memory-saver.d.ts +158 -0
  48. package/dist/checkpointer/memory-saver.d.ts.map +1 -0
  49. package/dist/checkpointer/memory-saver.js +222 -0
  50. package/dist/checkpointer/memory-saver.js.map +1 -0
  51. package/dist/checkpointer/types.d.ts +353 -0
  52. package/dist/checkpointer/types.d.ts.map +1 -0
  53. package/dist/checkpointer/types.js +159 -0
  54. package/dist/checkpointer/types.js.map +1 -0
  55. package/dist/context-manager.d.ts +627 -0
  56. package/dist/context-manager.d.ts.map +1 -0
  57. package/dist/context-manager.js +1039 -0
  58. package/dist/context-manager.js.map +1 -0
  59. package/dist/context.d.ts +57 -0
  60. package/dist/context.d.ts.map +1 -0
  61. package/dist/context.js +76 -0
  62. package/dist/context.js.map +1 -0
  63. package/dist/errors/index.d.ts +611 -0
  64. package/dist/errors/index.d.ts.map +1 -0
  65. package/dist/errors/index.js +1023 -0
  66. package/dist/errors/index.js.map +1 -0
  67. package/dist/generation-helpers.d.ts +126 -0
  68. package/dist/generation-helpers.d.ts.map +1 -0
  69. package/dist/generation-helpers.js +181 -0
  70. package/dist/generation-helpers.js.map +1 -0
  71. package/dist/hooks/audit.d.ts +210 -0
  72. package/dist/hooks/audit.d.ts.map +1 -0
  73. package/dist/hooks/audit.js +305 -0
  74. package/dist/hooks/audit.js.map +1 -0
  75. package/dist/hooks/cache.d.ts +180 -0
  76. package/dist/hooks/cache.d.ts.map +1 -0
  77. package/dist/hooks/cache.js +273 -0
  78. package/dist/hooks/cache.js.map +1 -0
  79. package/dist/hooks/guardrails.d.ts +145 -0
  80. package/dist/hooks/guardrails.d.ts.map +1 -0
  81. package/dist/hooks/guardrails.js +326 -0
  82. package/dist/hooks/guardrails.js.map +1 -0
  83. package/dist/hooks/index.d.ts +18 -0
  84. package/dist/hooks/index.d.ts.map +1 -0
  85. package/dist/hooks/index.js +32 -0
  86. package/dist/hooks/index.js.map +1 -0
  87. package/dist/hooks/logging.d.ts +193 -0
  88. package/dist/hooks/logging.d.ts.map +1 -0
  89. package/dist/hooks/logging.js +345 -0
  90. package/dist/hooks/logging.js.map +1 -0
  91. package/dist/hooks/parallel-guardrails.d.ts +268 -0
  92. package/dist/hooks/parallel-guardrails.d.ts.map +1 -0
  93. package/dist/hooks/parallel-guardrails.js +416 -0
  94. package/dist/hooks/parallel-guardrails.js.map +1 -0
  95. package/dist/hooks/rate-limit.d.ts +305 -0
  96. package/dist/hooks/rate-limit.d.ts.map +1 -0
  97. package/dist/hooks/rate-limit.js +372 -0
  98. package/dist/hooks/rate-limit.js.map +1 -0
  99. package/dist/hooks/retry.d.ts +144 -0
  100. package/dist/hooks/retry.d.ts.map +1 -0
  101. package/dist/hooks/retry.js +210 -0
  102. package/dist/hooks/retry.js.map +1 -0
  103. package/dist/hooks/secrets.d.ts +174 -0
  104. package/dist/hooks/secrets.d.ts.map +1 -0
  105. package/dist/hooks/secrets.js +306 -0
  106. package/dist/hooks/secrets.js.map +1 -0
  107. package/dist/hooks.d.ts +229 -0
  108. package/dist/hooks.d.ts.map +1 -0
  109. package/dist/hooks.js +352 -0
  110. package/dist/hooks.js.map +1 -0
  111. package/dist/index.d.ts +97 -0
  112. package/dist/index.d.ts.map +1 -0
  113. package/dist/index.js +182 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/mcp/env.d.ts +25 -0
  116. package/dist/mcp/env.d.ts.map +1 -0
  117. package/dist/mcp/env.js +18 -0
  118. package/dist/mcp/env.js.map +1 -0
  119. package/dist/mcp/index.d.ts +16 -0
  120. package/dist/mcp/index.d.ts.map +1 -0
  121. package/dist/mcp/index.js +17 -0
  122. package/dist/mcp/index.js.map +1 -0
  123. package/dist/mcp/manager.d.ts +184 -0
  124. package/dist/mcp/manager.d.ts.map +1 -0
  125. package/dist/mcp/manager.js +446 -0
  126. package/dist/mcp/manager.js.map +1 -0
  127. package/dist/mcp/types.d.ts +58 -0
  128. package/dist/mcp/types.d.ts.map +1 -0
  129. package/dist/mcp/types.js +7 -0
  130. package/dist/mcp/types.js.map +1 -0
  131. package/dist/mcp/validation.d.ts +119 -0
  132. package/dist/mcp/validation.d.ts.map +1 -0
  133. package/dist/mcp/validation.js +407 -0
  134. package/dist/mcp/validation.js.map +1 -0
  135. package/dist/mcp/virtual-server.d.ts +78 -0
  136. package/dist/mcp/virtual-server.d.ts.map +1 -0
  137. package/dist/mcp/virtual-server.js +137 -0
  138. package/dist/mcp/virtual-server.js.map +1 -0
  139. package/dist/memory/filesystem-store.d.ts +217 -0
  140. package/dist/memory/filesystem-store.d.ts.map +1 -0
  141. package/dist/memory/filesystem-store.js +343 -0
  142. package/dist/memory/filesystem-store.js.map +1 -0
  143. package/dist/memory/index.d.ts +46 -0
  144. package/dist/memory/index.d.ts.map +1 -0
  145. package/dist/memory/index.js +46 -0
  146. package/dist/memory/index.js.map +1 -0
  147. package/dist/memory/loader.d.ts +396 -0
  148. package/dist/memory/loader.d.ts.map +1 -0
  149. package/dist/memory/loader.js +419 -0
  150. package/dist/memory/loader.js.map +1 -0
  151. package/dist/memory/permissions.d.ts +282 -0
  152. package/dist/memory/permissions.d.ts.map +1 -0
  153. package/dist/memory/permissions.js +297 -0
  154. package/dist/memory/permissions.js.map +1 -0
  155. package/dist/memory/rules.d.ts +249 -0
  156. package/dist/memory/rules.d.ts.map +1 -0
  157. package/dist/memory/rules.js +362 -0
  158. package/dist/memory/rules.js.map +1 -0
  159. package/dist/memory/store.d.ts +286 -0
  160. package/dist/memory/store.d.ts.map +1 -0
  161. package/dist/memory/store.js +263 -0
  162. package/dist/memory/store.js.map +1 -0
  163. package/dist/middleware/apply.d.ts +73 -0
  164. package/dist/middleware/apply.d.ts.map +1 -0
  165. package/dist/middleware/apply.js +219 -0
  166. package/dist/middleware/apply.js.map +1 -0
  167. package/dist/middleware/context.d.ts +33 -0
  168. package/dist/middleware/context.d.ts.map +1 -0
  169. package/dist/middleware/context.js +176 -0
  170. package/dist/middleware/context.js.map +1 -0
  171. package/dist/middleware/index.d.ts +31 -0
  172. package/dist/middleware/index.d.ts.map +1 -0
  173. package/dist/middleware/index.js +32 -0
  174. package/dist/middleware/index.js.map +1 -0
  175. package/dist/middleware/logging.d.ts +137 -0
  176. package/dist/middleware/logging.d.ts.map +1 -0
  177. package/dist/middleware/logging.js +374 -0
  178. package/dist/middleware/logging.js.map +1 -0
  179. package/dist/middleware/types.d.ts +183 -0
  180. package/dist/middleware/types.d.ts.map +1 -0
  181. package/dist/middleware/types.js +11 -0
  182. package/dist/middleware/types.js.map +1 -0
  183. package/dist/observability/events.d.ts +183 -0
  184. package/dist/observability/events.d.ts.map +1 -0
  185. package/dist/observability/events.js +305 -0
  186. package/dist/observability/events.js.map +1 -0
  187. package/dist/observability/index.d.ts +55 -0
  188. package/dist/observability/index.d.ts.map +1 -0
  189. package/dist/observability/index.js +87 -0
  190. package/dist/observability/index.js.map +1 -0
  191. package/dist/observability/logger.d.ts +318 -0
  192. package/dist/observability/logger.d.ts.map +1 -0
  193. package/dist/observability/logger.js +436 -0
  194. package/dist/observability/logger.js.map +1 -0
  195. package/dist/observability/metrics.d.ts +341 -0
  196. package/dist/observability/metrics.d.ts.map +1 -0
  197. package/dist/observability/metrics.js +490 -0
  198. package/dist/observability/metrics.js.map +1 -0
  199. package/dist/observability/preset.d.ts +161 -0
  200. package/dist/observability/preset.d.ts.map +1 -0
  201. package/dist/observability/preset.js +133 -0
  202. package/dist/observability/preset.js.map +1 -0
  203. package/dist/observability/streaming.d.ts +113 -0
  204. package/dist/observability/streaming.d.ts.map +1 -0
  205. package/dist/observability/streaming.js +114 -0
  206. package/dist/observability/streaming.js.map +1 -0
  207. package/dist/observability/tracing.d.ts +378 -0
  208. package/dist/observability/tracing.d.ts.map +1 -0
  209. package/dist/observability/tracing.js +539 -0
  210. package/dist/observability/tracing.js.map +1 -0
  211. package/dist/plugins.d.ts +55 -0
  212. package/dist/plugins.d.ts.map +1 -0
  213. package/dist/plugins.js +63 -0
  214. package/dist/plugins.js.map +1 -0
  215. package/dist/presets/index.d.ts +7 -0
  216. package/dist/presets/index.d.ts.map +1 -0
  217. package/dist/presets/index.js +7 -0
  218. package/dist/presets/index.js.map +1 -0
  219. package/dist/presets/production.d.ts +262 -0
  220. package/dist/presets/production.d.ts.map +1 -0
  221. package/dist/presets/production.js +295 -0
  222. package/dist/presets/production.js.map +1 -0
  223. package/dist/security/index.d.ts +179 -0
  224. package/dist/security/index.d.ts.map +1 -0
  225. package/dist/security/index.js +323 -0
  226. package/dist/security/index.js.map +1 -0
  227. package/dist/subagents/advanced.d.ts +413 -0
  228. package/dist/subagents/advanced.d.ts.map +1 -0
  229. package/dist/subagents/advanced.js +396 -0
  230. package/dist/subagents/advanced.js.map +1 -0
  231. package/dist/subagents/index.d.ts +14 -0
  232. package/dist/subagents/index.d.ts.map +1 -0
  233. package/dist/subagents/index.js +15 -0
  234. package/dist/subagents/index.js.map +1 -0
  235. package/dist/subagents.d.ts +73 -0
  236. package/dist/subagents.d.ts.map +1 -0
  237. package/dist/subagents.js +213 -0
  238. package/dist/subagents.js.map +1 -0
  239. package/dist/task-store/file-store.d.ts +76 -0
  240. package/dist/task-store/file-store.d.ts.map +1 -0
  241. package/dist/task-store/file-store.js +190 -0
  242. package/dist/task-store/file-store.js.map +1 -0
  243. package/dist/task-store/index.d.ts +11 -0
  244. package/dist/task-store/index.d.ts.map +1 -0
  245. package/dist/task-store/index.js +10 -0
  246. package/dist/task-store/index.js.map +1 -0
  247. package/dist/task-store/kv-store.d.ts +140 -0
  248. package/dist/task-store/kv-store.d.ts.map +1 -0
  249. package/dist/task-store/kv-store.js +169 -0
  250. package/dist/task-store/kv-store.js.map +1 -0
  251. package/dist/task-store/memory-store.d.ts +66 -0
  252. package/dist/task-store/memory-store.d.ts.map +1 -0
  253. package/dist/task-store/memory-store.js +125 -0
  254. package/dist/task-store/memory-store.js.map +1 -0
  255. package/dist/task-store/types.d.ts +235 -0
  256. package/dist/task-store/types.d.ts.map +1 -0
  257. package/dist/task-store/types.js +110 -0
  258. package/dist/task-store/types.js.map +1 -0
  259. package/dist/testing/assertions.d.ts +401 -0
  260. package/dist/testing/assertions.d.ts.map +1 -0
  261. package/dist/testing/assertions.js +630 -0
  262. package/dist/testing/assertions.js.map +1 -0
  263. package/dist/testing/index.d.ts +343 -0
  264. package/dist/testing/index.d.ts.map +1 -0
  265. package/dist/testing/index.js +360 -0
  266. package/dist/testing/index.js.map +1 -0
  267. package/dist/testing/mock-agent.d.ts +214 -0
  268. package/dist/testing/mock-agent.d.ts.map +1 -0
  269. package/dist/testing/mock-agent.js +448 -0
  270. package/dist/testing/mock-agent.js.map +1 -0
  271. package/dist/testing/recorder.d.ts +288 -0
  272. package/dist/testing/recorder.d.ts.map +1 -0
  273. package/dist/testing/recorder.js +499 -0
  274. package/dist/testing/recorder.js.map +1 -0
  275. package/dist/tools/execute.d.ts +104 -0
  276. package/dist/tools/execute.d.ts.map +1 -0
  277. package/dist/tools/execute.js +191 -0
  278. package/dist/tools/execute.js.map +1 -0
  279. package/dist/tools/factory.d.ts +260 -0
  280. package/dist/tools/factory.d.ts.map +1 -0
  281. package/dist/tools/factory.js +241 -0
  282. package/dist/tools/factory.js.map +1 -0
  283. package/dist/tools/filesystem.d.ts +215 -0
  284. package/dist/tools/filesystem.d.ts.map +1 -0
  285. package/dist/tools/filesystem.js +311 -0
  286. package/dist/tools/filesystem.js.map +1 -0
  287. package/dist/tools/index.d.ts +33 -0
  288. package/dist/tools/index.d.ts.map +1 -0
  289. package/dist/tools/index.js +33 -0
  290. package/dist/tools/index.js.map +1 -0
  291. package/dist/tools/search.d.ts +59 -0
  292. package/dist/tools/search.d.ts.map +1 -0
  293. package/dist/tools/search.js +94 -0
  294. package/dist/tools/search.js.map +1 -0
  295. package/dist/tools/skills.d.ts +354 -0
  296. package/dist/tools/skills.d.ts.map +1 -0
  297. package/dist/tools/skills.js +413 -0
  298. package/dist/tools/skills.js.map +1 -0
  299. package/dist/tools/task.d.ts +272 -0
  300. package/dist/tools/task.d.ts.map +1 -0
  301. package/dist/tools/task.js +521 -0
  302. package/dist/tools/task.js.map +1 -0
  303. package/dist/tools/todos.d.ts +131 -0
  304. package/dist/tools/todos.d.ts.map +1 -0
  305. package/dist/tools/todos.js +120 -0
  306. package/dist/tools/todos.js.map +1 -0
  307. package/dist/tools/tool-registry.d.ts +424 -0
  308. package/dist/tools/tool-registry.d.ts.map +1 -0
  309. package/dist/tools/tool-registry.js +607 -0
  310. package/dist/tools/tool-registry.js.map +1 -0
  311. package/dist/tools/user-interaction.d.ts +116 -0
  312. package/dist/tools/user-interaction.d.ts.map +1 -0
  313. package/dist/tools/user-interaction.js +147 -0
  314. package/dist/tools/user-interaction.js.map +1 -0
  315. package/dist/tools/utils.d.ts +124 -0
  316. package/dist/tools/utils.d.ts.map +1 -0
  317. package/dist/tools/utils.js +189 -0
  318. package/dist/tools/utils.js.map +1 -0
  319. package/dist/tools.d.ts +74 -0
  320. package/dist/tools.d.ts.map +1 -0
  321. package/dist/tools.js +73 -0
  322. package/dist/tools.js.map +1 -0
  323. package/dist/types.d.ts +2421 -0
  324. package/dist/types.d.ts.map +1 -0
  325. package/dist/types.js +55 -0
  326. package/dist/types.js.map +1 -0
  327. package/package.json +81 -0
@@ -0,0 +1,305 @@
1
+ /**
2
+ * Rate limiting hook utilities.
3
+ *
4
+ * Provides rate limiting hooks that track token usage and enforce limits
5
+ * using the unified hook system.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ import type { HookCallback, PostGenerateInput } from "../types.js";
10
+ /**
11
+ * Server-provided rate limit information from response headers.
12
+ *
13
+ * @category Hooks
14
+ */
15
+ export interface ServerRateLimitInfo {
16
+ /**
17
+ * Maximum requests allowed in the current window.
18
+ * Typically from `x-ratelimit-limit` or `ratelimit-limit` header.
19
+ */
20
+ limit?: number;
21
+ /**
22
+ * Number of requests remaining in the current window.
23
+ * Typically from `x-ratelimit-remaining` or `ratelimit-remaining` header.
24
+ */
25
+ remaining?: number;
26
+ /**
27
+ * Timestamp when the rate limit window resets (Unix seconds).
28
+ * Typically from `x-ratelimit-reset` or `ratelimit-reset` header.
29
+ */
30
+ reset?: number;
31
+ /**
32
+ * Number of seconds until the rate limit window resets.
33
+ * Typically from `retry-after` header when rate limited.
34
+ */
35
+ retryAfter?: number;
36
+ }
37
+ /**
38
+ * Options for creating rate limit hooks.
39
+ *
40
+ * @category Hooks
41
+ */
42
+ export interface RateLimitHooksOptions {
43
+ /**
44
+ * Maximum tokens per time window.
45
+ * @defaultValue 100000
46
+ */
47
+ maxTokensPerWindow?: number;
48
+ /**
49
+ * Time window in milliseconds for token counting.
50
+ * @defaultValue 60000 (1 minute)
51
+ */
52
+ windowMs?: number;
53
+ /**
54
+ * Message to show when rate limit is exceeded.
55
+ * @defaultValue "Rate limit exceeded. Please try again later."
56
+ */
57
+ limitMessage?: string;
58
+ /**
59
+ * Custom function to determine if a request should be rate limited.
60
+ * Return true to allow, false to deny.
61
+ * @defaultValue Check token count against limit
62
+ */
63
+ shouldAllow?: (tokensUsed: number, maxTokens: number) => boolean;
64
+ /**
65
+ * Enable server rate limit integration.
66
+ * When enabled, hooks will attempt to extract rate limit information
67
+ * from model response headers (e.g., x-ratelimit-* headers) and use
68
+ * server-provided limits in addition to client-side tracking.
69
+ *
70
+ * @defaultValue false
71
+ */
72
+ enableServerLimits?: boolean;
73
+ /**
74
+ * Custom function to extract server rate limit info from response metadata.
75
+ * Use this if your provider uses non-standard header names or formats.
76
+ *
77
+ * @param result - The generation result which may contain response metadata
78
+ * @returns Server rate limit information, or undefined if not available
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * extractServerLimits: (result) => {
83
+ * const headers = result.rawResponse?.headers;
84
+ * if (!headers) return undefined;
85
+ * return {
86
+ * limit: parseInt(headers['x-custom-limit'] || '0'),
87
+ * remaining: parseInt(headers['x-custom-remaining'] || '0'),
88
+ * reset: parseInt(headers['x-custom-reset'] || '0'),
89
+ * };
90
+ * }
91
+ * ```
92
+ */
93
+ extractServerLimits?: (result: PostGenerateInput) => ServerRateLimitInfo | undefined;
94
+ /**
95
+ * Enable per-tool quota tracking.
96
+ * When enabled, tracks token usage separately for each tool,
97
+ * allowing different tools to have independent rate limits.
98
+ *
99
+ * **Note**: This feature is designed for future tool-based rate limiting hooks
100
+ * (PreToolUse/PostToolUse). The current generation-based hooks (PreGenerate/PostGenerate)
101
+ * track overall token usage, not per-tool usage.
102
+ *
103
+ * @defaultValue false
104
+ * @experimental
105
+ */
106
+ perToolQuota?: boolean;
107
+ /**
108
+ * Per-tool token limits when perToolQuota is enabled.
109
+ * Maps tool names to their maximum tokens per window.
110
+ *
111
+ * **Note**: This feature is designed for future tool-based rate limiting hooks.
112
+ * Current generation-based hooks do not use this configuration.
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * {
117
+ * 'Write': 10000, // Write tool limited to 10k tokens per window
118
+ * 'Bash': 5000, // Bash tool limited to 5k tokens per window
119
+ * 'Read': 20000, // Read tool limited to 20k tokens per window
120
+ * }
121
+ * ```
122
+ * @experimental
123
+ */
124
+ toolLimits?: Record<string, number>;
125
+ }
126
+ /**
127
+ * Token bucket rate limiter implementation.
128
+ *
129
+ * Tracks token usage in a sliding window with automatic cleanup of old entries.
130
+ * Supports per-tool quota tracking and server-provided rate limit integration.
131
+ *
132
+ * @category Hooks
133
+ */
134
+ export declare class TokenBucketRateLimiter {
135
+ private usage;
136
+ private maxTokens;
137
+ private windowMs;
138
+ private serverLimitInfo?;
139
+ private perToolQuota;
140
+ private toolLimits;
141
+ constructor(maxTokensPerWindow: number, windowMs: number, perToolQuota?: boolean, toolLimits?: Record<string, number>);
142
+ /**
143
+ * Try to acquire tokens. Returns true if allowed, false if would exceed limit.
144
+ * If tool is provided and per-tool quotas are enabled, checks against tool-specific limit.
145
+ */
146
+ tryAcquire(tool?: string): boolean;
147
+ /**
148
+ * Record token usage for a tool.
149
+ */
150
+ recordUsage(tokens: number, tool?: string): void;
151
+ /**
152
+ * Get current token usage in the window.
153
+ * If tool is provided and per-tool quotas are enabled, returns usage for that tool only.
154
+ */
155
+ getCurrentUsage(tool?: string): number;
156
+ /**
157
+ * Get remaining tokens in current window.
158
+ * Uses server limits if available, otherwise falls back to client-side tracking.
159
+ */
160
+ getRemainingTokens(tool?: string): number;
161
+ /**
162
+ * Update with server-provided rate limit information.
163
+ * This information takes precedence over client-side tracking.
164
+ */
165
+ updateServerLimits(info: ServerRateLimitInfo): void;
166
+ /**
167
+ * Get current server limit information if available.
168
+ */
169
+ getServerLimits(): ServerRateLimitInfo | undefined;
170
+ /**
171
+ * Get the effective limit for a tool (tool-specific or global).
172
+ */
173
+ private getEffectiveLimit;
174
+ /**
175
+ * Remove entries outside the current window.
176
+ */
177
+ private cleanup;
178
+ /**
179
+ * Reset all usage data and server limit info.
180
+ */
181
+ reset(): void;
182
+ }
183
+ /**
184
+ * Default server rate limit extractor.
185
+ *
186
+ * Attempts to extract rate limit information from common response header patterns:
187
+ * - `x-ratelimit-*` (OpenAI, Anthropic, etc.)
188
+ * - `ratelimit-*` (standard format)
189
+ * - `retry-after` (when rate limited)
190
+ *
191
+ * @param result - PostGenerate hook input containing the generation result
192
+ * @returns Server rate limit info if headers are present, undefined otherwise
193
+ *
194
+ * @category Hooks
195
+ */
196
+ export declare function extractStandardRateLimitHeaders(result: PostGenerateInput): ServerRateLimitInfo | undefined;
197
+ /**
198
+ * Creates rate limiting hooks for PreGenerate and PostGenerate events.
199
+ *
200
+ * The PreGenerate hook checks if the rate limit would be exceeded and denies
201
+ * the request if so. The PostGenerate hook records actual token usage.
202
+ *
203
+ * This replaces rate limiting middleware with hook-based rate limiting that
204
+ * works correctly with the unified hook system.
205
+ *
206
+ * @param options - Configuration options
207
+ * @returns Array of two hooks: [PreGenerate rate check, PostGenerate usage tracking]
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * const [rateCheck, usageTracker] = createRateLimitHooks({
212
+ * maxTokensPerWindow: 50000, // 50k tokens
213
+ * windowMs: 60000, // per minute
214
+ * });
215
+ *
216
+ * const agent = createAgent({
217
+ * model,
218
+ * hooks: {
219
+ * PreGenerate: [{ hooks: [rateCheck] }],
220
+ * PostGenerate: [{ hooks: [usageTracker] }],
221
+ * },
222
+ * });
223
+ * ```
224
+ *
225
+ * @example
226
+ * ```typescript
227
+ * // Custom rate limit logic
228
+ * const hooks = createRateLimitHooks({
229
+ * shouldAllow: (tokensUsed, maxTokens) => {
230
+ * // Allow if under 80% of limit
231
+ * return tokensUsed < maxTokens * 0.8;
232
+ * },
233
+ * });
234
+ * ```
235
+ *
236
+ * @example
237
+ * ```typescript
238
+ * // With server rate limit integration
239
+ * const hooks = createRateLimitHooks({
240
+ * maxTokensPerWindow: 100000,
241
+ * enableServerLimits: true, // Parse x-ratelimit-* headers
242
+ * });
243
+ * ```
244
+ *
245
+ * @example
246
+ * ```typescript
247
+ * // Custom server limit extraction for non-standard headers
248
+ * const hooks = createRateLimitHooks({
249
+ * enableServerLimits: true,
250
+ * extractServerLimits: (result) => {
251
+ * const headers = result.response?.headers;
252
+ * return {
253
+ * remaining: parseInt(headers?.['x-custom-remaining'] || '0'),
254
+ * reset: parseInt(headers?.['x-custom-reset'] || '0'),
255
+ * };
256
+ * },
257
+ * });
258
+ * ```
259
+ *
260
+ * @category Hooks
261
+ */
262
+ export declare function createRateLimitHooks(options?: RateLimitHooksOptions): [HookCallback, HookCallback];
263
+ /**
264
+ * Creates managed rate limit hooks with programmatic control.
265
+ *
266
+ * Returns hooks along with functions to get current usage, reset limits,
267
+ * and check remaining capacity.
268
+ *
269
+ * @param options - Configuration options
270
+ * @returns Object with hooks and rate limit control functions
271
+ *
272
+ * @example
273
+ * ```typescript
274
+ * const { hooks, getCurrentUsage, getRemainingTokens, reset } = createManagedRateLimitHooks({
275
+ * maxTokensPerWindow: 100000,
276
+ * windowMs: 60000,
277
+ * });
278
+ *
279
+ * const agent = createAgent({
280
+ * model,
281
+ * hooks: {
282
+ * PreGenerate: [{ hooks: [hooks[0]] }],
283
+ * PostGenerate: [{ hooks: [hooks[1]] }],
284
+ * },
285
+ * });
286
+ *
287
+ * // Check current usage
288
+ * const used = getCurrentUsage();
289
+ * const remaining = getRemainingTokens();
290
+ * console.log(`Token usage: ${used} / ${maxTokensPerWindow} (${remaining} remaining)`);
291
+ *
292
+ * // Reset limits (e.g., for testing or manual override)
293
+ * reset();
294
+ * ```
295
+ *
296
+ * @category Hooks
297
+ */
298
+ export declare function createManagedRateLimitHooks(options?: RateLimitHooksOptions): {
299
+ hooks: [HookCallback, HookCallback];
300
+ getCurrentUsage: () => number;
301
+ getRemainingTokens: () => number;
302
+ getServerLimits: () => ServerRateLimitInfo | undefined;
303
+ reset: () => void;
304
+ };
305
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/hooks/rate-limit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,372 @@
1
+ /**
2
+ * Rate limiting hook utilities.
3
+ *
4
+ * Provides rate limiting hooks that track token usage and enforce limits
5
+ * using the unified hook system.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ /**
10
+ * Token bucket rate limiter implementation.
11
+ *
12
+ * Tracks token usage in a sliding window with automatic cleanup of old entries.
13
+ * Supports per-tool quota tracking and server-provided rate limit integration.
14
+ *
15
+ * @category Hooks
16
+ */
17
+ export class TokenBucketRateLimiter {
18
+ usage = [];
19
+ maxTokens;
20
+ windowMs;
21
+ serverLimitInfo;
22
+ perToolQuota;
23
+ toolLimits;
24
+ constructor(maxTokensPerWindow, windowMs, perToolQuota = false, toolLimits = {}) {
25
+ this.maxTokens = maxTokensPerWindow;
26
+ this.windowMs = windowMs;
27
+ this.perToolQuota = perToolQuota;
28
+ this.toolLimits = toolLimits;
29
+ }
30
+ /**
31
+ * Try to acquire tokens. Returns true if allowed, false if would exceed limit.
32
+ * If tool is provided and per-tool quotas are enabled, checks against tool-specific limit.
33
+ */
34
+ tryAcquire(tool) {
35
+ this.cleanup();
36
+ // Check server limits first if available
37
+ if (this.serverLimitInfo?.remaining !== undefined) {
38
+ if (this.serverLimitInfo.remaining <= 0) {
39
+ return false;
40
+ }
41
+ }
42
+ // Check client-side limits
43
+ const currentUsage = this.getCurrentUsage(tool);
44
+ const limit = this.getEffectiveLimit(tool);
45
+ return currentUsage < limit;
46
+ }
47
+ /**
48
+ * Record token usage for a tool.
49
+ */
50
+ recordUsage(tokens, tool) {
51
+ this.cleanup();
52
+ this.usage.push({
53
+ timestamp: Date.now(),
54
+ tokens,
55
+ tool,
56
+ });
57
+ }
58
+ /**
59
+ * Get current token usage in the window.
60
+ * If tool is provided and per-tool quotas are enabled, returns usage for that tool only.
61
+ */
62
+ getCurrentUsage(tool) {
63
+ this.cleanup();
64
+ if (this.perToolQuota && tool) {
65
+ return this.usage
66
+ .filter((entry) => entry.tool === tool)
67
+ .reduce((sum, entry) => sum + entry.tokens, 0);
68
+ }
69
+ return this.usage.reduce((sum, entry) => sum + entry.tokens, 0);
70
+ }
71
+ /**
72
+ * Get remaining tokens in current window.
73
+ * Uses server limits if available, otherwise falls back to client-side tracking.
74
+ */
75
+ getRemainingTokens(tool) {
76
+ // Prefer server-provided remaining count if available
77
+ if (this.serverLimitInfo?.remaining !== undefined) {
78
+ return Math.max(0, this.serverLimitInfo.remaining);
79
+ }
80
+ const current = this.getCurrentUsage(tool);
81
+ const limit = this.getEffectiveLimit(tool);
82
+ return Math.max(0, limit - current);
83
+ }
84
+ /**
85
+ * Update with server-provided rate limit information.
86
+ * This information takes precedence over client-side tracking.
87
+ */
88
+ updateServerLimits(info) {
89
+ this.serverLimitInfo = info;
90
+ }
91
+ /**
92
+ * Get current server limit information if available.
93
+ */
94
+ getServerLimits() {
95
+ return this.serverLimitInfo;
96
+ }
97
+ /**
98
+ * Get the effective limit for a tool (tool-specific or global).
99
+ */
100
+ getEffectiveLimit(tool) {
101
+ if (this.perToolQuota && tool && this.toolLimits[tool]) {
102
+ return this.toolLimits[tool];
103
+ }
104
+ return this.maxTokens;
105
+ }
106
+ /**
107
+ * Remove entries outside the current window.
108
+ */
109
+ cleanup() {
110
+ const cutoff = Date.now() - this.windowMs;
111
+ this.usage = this.usage.filter((entry) => entry.timestamp > cutoff);
112
+ }
113
+ /**
114
+ * Reset all usage data and server limit info.
115
+ */
116
+ reset() {
117
+ this.usage = [];
118
+ this.serverLimitInfo = undefined;
119
+ }
120
+ }
121
+ /**
122
+ * Default server rate limit extractor.
123
+ *
124
+ * Attempts to extract rate limit information from common response header patterns:
125
+ * - `x-ratelimit-*` (OpenAI, Anthropic, etc.)
126
+ * - `ratelimit-*` (standard format)
127
+ * - `retry-after` (when rate limited)
128
+ *
129
+ * @param result - PostGenerate hook input containing the generation result
130
+ * @returns Server rate limit info if headers are present, undefined otherwise
131
+ *
132
+ * @category Hooks
133
+ */
134
+ export function extractStandardRateLimitHeaders(result) {
135
+ // AI SDK v6 may expose response metadata via result.response or result.rawResponse
136
+ // This is a best-effort extraction that handles common patterns
137
+ // biome-ignore lint/suspicious/noExplicitAny: AI SDK internal structure varies by version
138
+ const headers = result.response?.headers || result.rawResponse?.headers;
139
+ if (!headers)
140
+ return undefined;
141
+ // Normalize headers to lowercase for case-insensitive matching
142
+ const normalizedHeaders = {};
143
+ if (typeof headers === "object") {
144
+ for (const [key, value] of Object.entries(headers)) {
145
+ if (typeof value === "string") {
146
+ normalizedHeaders[key.toLowerCase()] = value;
147
+ }
148
+ }
149
+ }
150
+ // Try common header patterns
151
+ const limitStr = normalizedHeaders["x-ratelimit-limit"] || normalizedHeaders["ratelimit-limit"];
152
+ const remainingStr = normalizedHeaders["x-ratelimit-remaining"] || normalizedHeaders["ratelimit-remaining"];
153
+ const resetStr = normalizedHeaders["x-ratelimit-reset"] || normalizedHeaders["ratelimit-reset"];
154
+ const retryAfterStr = normalizedHeaders["retry-after"];
155
+ // Parse values
156
+ const limit = limitStr ? Number.parseInt(limitStr, 10) : undefined;
157
+ const remaining = remainingStr ? Number.parseInt(remainingStr, 10) : undefined;
158
+ const reset = resetStr ? Number.parseInt(resetStr, 10) : undefined;
159
+ const retryAfter = retryAfterStr ? Number.parseInt(retryAfterStr, 10) : undefined;
160
+ // Return undefined if no rate limit headers found
161
+ if (limit === undefined &&
162
+ remaining === undefined &&
163
+ reset === undefined &&
164
+ retryAfter === undefined) {
165
+ return undefined;
166
+ }
167
+ return {
168
+ limit: !Number.isNaN(limit) ? limit : undefined,
169
+ remaining: !Number.isNaN(remaining) ? remaining : undefined,
170
+ reset: !Number.isNaN(reset) ? reset : undefined,
171
+ retryAfter: !Number.isNaN(retryAfter) ? retryAfter : undefined,
172
+ };
173
+ }
174
+ /**
175
+ * Creates rate limiting hooks for PreGenerate and PostGenerate events.
176
+ *
177
+ * The PreGenerate hook checks if the rate limit would be exceeded and denies
178
+ * the request if so. The PostGenerate hook records actual token usage.
179
+ *
180
+ * This replaces rate limiting middleware with hook-based rate limiting that
181
+ * works correctly with the unified hook system.
182
+ *
183
+ * @param options - Configuration options
184
+ * @returns Array of two hooks: [PreGenerate rate check, PostGenerate usage tracking]
185
+ *
186
+ * @example
187
+ * ```typescript
188
+ * const [rateCheck, usageTracker] = createRateLimitHooks({
189
+ * maxTokensPerWindow: 50000, // 50k tokens
190
+ * windowMs: 60000, // per minute
191
+ * });
192
+ *
193
+ * const agent = createAgent({
194
+ * model,
195
+ * hooks: {
196
+ * PreGenerate: [{ hooks: [rateCheck] }],
197
+ * PostGenerate: [{ hooks: [usageTracker] }],
198
+ * },
199
+ * });
200
+ * ```
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * // Custom rate limit logic
205
+ * const hooks = createRateLimitHooks({
206
+ * shouldAllow: (tokensUsed, maxTokens) => {
207
+ * // Allow if under 80% of limit
208
+ * return tokensUsed < maxTokens * 0.8;
209
+ * },
210
+ * });
211
+ * ```
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * // With server rate limit integration
216
+ * const hooks = createRateLimitHooks({
217
+ * maxTokensPerWindow: 100000,
218
+ * enableServerLimits: true, // Parse x-ratelimit-* headers
219
+ * });
220
+ * ```
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * // Custom server limit extraction for non-standard headers
225
+ * const hooks = createRateLimitHooks({
226
+ * enableServerLimits: true,
227
+ * extractServerLimits: (result) => {
228
+ * const headers = result.response?.headers;
229
+ * return {
230
+ * remaining: parseInt(headers?.['x-custom-remaining'] || '0'),
231
+ * reset: parseInt(headers?.['x-custom-reset'] || '0'),
232
+ * };
233
+ * },
234
+ * });
235
+ * ```
236
+ *
237
+ * @category Hooks
238
+ */
239
+ export function createRateLimitHooks(options = {}) {
240
+ const { maxTokensPerWindow = 100000, windowMs = 60000, // 1 minute
241
+ limitMessage = "Rate limit exceeded. Please try again later.", shouldAllow = (tokensUsed, maxTokens) => tokensUsed < maxTokens, enableServerLimits = false, extractServerLimits = extractStandardRateLimitHeaders, perToolQuota = false, toolLimits = {}, } = options;
242
+ const rateLimiter = new TokenBucketRateLimiter(maxTokensPerWindow, windowMs, perToolQuota, toolLimits);
243
+ // PreGenerate: Check rate limit
244
+ const rateCheck = async (input) => {
245
+ if (input.hook_event_name !== "PreGenerate")
246
+ return {};
247
+ const currentUsage = rateLimiter.getCurrentUsage();
248
+ if (!shouldAllow(currentUsage, maxTokensPerWindow)) {
249
+ // Check if we have server reset time for better error message
250
+ const serverLimits = rateLimiter.getServerLimits();
251
+ let reason = limitMessage;
252
+ if (serverLimits?.reset) {
253
+ const resetDate = new Date(serverLimits.reset * 1000);
254
+ reason = `${limitMessage} Rate limit resets at ${resetDate.toISOString()}.`;
255
+ }
256
+ else if (serverLimits?.retryAfter) {
257
+ reason = `${limitMessage} Retry after ${serverLimits.retryAfter} seconds.`;
258
+ }
259
+ return {
260
+ hookSpecificOutput: {
261
+ hookEventName: "PreGenerate",
262
+ permissionDecision: "deny",
263
+ permissionDecisionReason: reason,
264
+ },
265
+ };
266
+ }
267
+ return {};
268
+ };
269
+ // PostGenerate: Record usage and update server limits
270
+ const usageTracker = async (input) => {
271
+ if (input.hook_event_name !== "PostGenerate")
272
+ return {};
273
+ const postGenInput = input;
274
+ const tokens = postGenInput.result.usage?.totalTokens ?? 0;
275
+ // Record client-side usage
276
+ rateLimiter.recordUsage(tokens);
277
+ // Update with server-provided limits if enabled
278
+ if (enableServerLimits) {
279
+ const serverLimits = extractServerLimits(postGenInput);
280
+ if (serverLimits) {
281
+ rateLimiter.updateServerLimits(serverLimits);
282
+ }
283
+ }
284
+ return {};
285
+ };
286
+ return [rateCheck, usageTracker];
287
+ }
288
+ /**
289
+ * Creates managed rate limit hooks with programmatic control.
290
+ *
291
+ * Returns hooks along with functions to get current usage, reset limits,
292
+ * and check remaining capacity.
293
+ *
294
+ * @param options - Configuration options
295
+ * @returns Object with hooks and rate limit control functions
296
+ *
297
+ * @example
298
+ * ```typescript
299
+ * const { hooks, getCurrentUsage, getRemainingTokens, reset } = createManagedRateLimitHooks({
300
+ * maxTokensPerWindow: 100000,
301
+ * windowMs: 60000,
302
+ * });
303
+ *
304
+ * const agent = createAgent({
305
+ * model,
306
+ * hooks: {
307
+ * PreGenerate: [{ hooks: [hooks[0]] }],
308
+ * PostGenerate: [{ hooks: [hooks[1]] }],
309
+ * },
310
+ * });
311
+ *
312
+ * // Check current usage
313
+ * const used = getCurrentUsage();
314
+ * const remaining = getRemainingTokens();
315
+ * console.log(`Token usage: ${used} / ${maxTokensPerWindow} (${remaining} remaining)`);
316
+ *
317
+ * // Reset limits (e.g., for testing or manual override)
318
+ * reset();
319
+ * ```
320
+ *
321
+ * @category Hooks
322
+ */
323
+ export function createManagedRateLimitHooks(options = {}) {
324
+ const { maxTokensPerWindow = 100000, windowMs = 60000, limitMessage = "Rate limit exceeded. Please try again later.", shouldAllow = (tokensUsed, maxTokens) => tokensUsed < maxTokens, enableServerLimits = false, extractServerLimits = extractStandardRateLimitHeaders, perToolQuota = false, toolLimits = {}, } = options;
325
+ const rateLimiter = new TokenBucketRateLimiter(maxTokensPerWindow, windowMs, perToolQuota, toolLimits);
326
+ const rateCheck = async (input) => {
327
+ if (input.hook_event_name !== "PreGenerate")
328
+ return {};
329
+ const currentUsage = rateLimiter.getCurrentUsage();
330
+ if (!shouldAllow(currentUsage, maxTokensPerWindow)) {
331
+ const serverLimits = rateLimiter.getServerLimits();
332
+ let reason = limitMessage;
333
+ if (serverLimits?.reset) {
334
+ const resetDate = new Date(serverLimits.reset * 1000);
335
+ reason = `${limitMessage} Rate limit resets at ${resetDate.toISOString()}.`;
336
+ }
337
+ else if (serverLimits?.retryAfter) {
338
+ reason = `${limitMessage} Retry after ${serverLimits.retryAfter} seconds.`;
339
+ }
340
+ return {
341
+ hookSpecificOutput: {
342
+ hookEventName: "PreGenerate",
343
+ permissionDecision: "deny",
344
+ permissionDecisionReason: reason,
345
+ },
346
+ };
347
+ }
348
+ return {};
349
+ };
350
+ const usageTracker = async (input) => {
351
+ if (input.hook_event_name !== "PostGenerate")
352
+ return {};
353
+ const postGenInput = input;
354
+ const tokens = postGenInput.result.usage?.totalTokens ?? 0;
355
+ rateLimiter.recordUsage(tokens);
356
+ if (enableServerLimits) {
357
+ const serverLimits = extractServerLimits(postGenInput);
358
+ if (serverLimits) {
359
+ rateLimiter.updateServerLimits(serverLimits);
360
+ }
361
+ }
362
+ return {};
363
+ };
364
+ return {
365
+ hooks: [rateCheck, usageTracker],
366
+ getCurrentUsage: () => rateLimiter.getCurrentUsage(),
367
+ getRemainingTokens: () => rateLimiter.getRemainingTokens(),
368
+ getServerLimits: () => rateLimiter.getServerLimits(),
369
+ reset: () => rateLimiter.reset(),
370
+ };
371
+ }
372
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/hooks/rate-limit.ts"],"names":[],"mappings":"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"}