llaminate 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.
Files changed (72) hide show
  1. package/.gitattributes +2 -0
  2. package/LICENSE +21 -0
  3. package/README.md +95 -0
  4. package/assets/llaminate-256.webp +0 -0
  5. package/assets/llaminate.jpg +0 -0
  6. package/assets/llaminate.webp +0 -0
  7. package/dist/build-info.json +5 -0
  8. package/dist/config.schema.json +126 -0
  9. package/dist/llaminate.d.ts +202 -0
  10. package/dist/llaminate.min.js +9 -0
  11. package/dist/llaminate.min.js.map +1 -0
  12. package/dist/ratelimiter.d.ts +33 -0
  13. package/dist/ratelimiter.min.js +7 -0
  14. package/dist/ratelimiter.min.js.map +1 -0
  15. package/dist/system.hbs +3 -0
  16. package/docs/LICENSE +21 -0
  17. package/docs/Llaminate.html +1040 -0
  18. package/docs/Llaminate.module_Endpoints.html +278 -0
  19. package/docs/Llaminate.module_Llaminate.html +200 -0
  20. package/docs/Llaminate.module_MimeTypes.html +275 -0
  21. package/docs/LlaminateConfig.html +667 -0
  22. package/docs/LlaminateMessage.html +328 -0
  23. package/docs/LlaminateResponse.html +253 -0
  24. package/docs/assets/llaminate-256.webp +0 -0
  25. package/docs/fonts/OpenSans-Bold-webfont.eot +0 -0
  26. package/docs/fonts/OpenSans-Bold-webfont.svg +1830 -0
  27. package/docs/fonts/OpenSans-Bold-webfont.woff +0 -0
  28. package/docs/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  29. package/docs/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
  30. package/docs/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  31. package/docs/fonts/OpenSans-Italic-webfont.eot +0 -0
  32. package/docs/fonts/OpenSans-Italic-webfont.svg +1830 -0
  33. package/docs/fonts/OpenSans-Italic-webfont.woff +0 -0
  34. package/docs/fonts/OpenSans-Light-webfont.eot +0 -0
  35. package/docs/fonts/OpenSans-Light-webfont.svg +1831 -0
  36. package/docs/fonts/OpenSans-Light-webfont.woff +0 -0
  37. package/docs/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  38. package/docs/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
  39. package/docs/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  40. package/docs/fonts/OpenSans-Regular-webfont.eot +0 -0
  41. package/docs/fonts/OpenSans-Regular-webfont.svg +1831 -0
  42. package/docs/fonts/OpenSans-Regular-webfont.woff +0 -0
  43. package/docs/index.html +142 -0
  44. package/docs/scripts/linenumber.js +25 -0
  45. package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
  46. package/docs/scripts/prettify/lang-css.js +2 -0
  47. package/docs/scripts/prettify/prettify.js +28 -0
  48. package/docs/styles/jsdoc-default.css +358 -0
  49. package/docs/styles/prettify-jsdoc.css +111 -0
  50. package/docs/styles/prettify-tomorrow.css +132 -0
  51. package/jsdoc.json +23 -0
  52. package/package.json +38 -0
  53. package/scripts/build.sh +21 -0
  54. package/scripts/docs.sh +28 -0
  55. package/scripts/prebuild.js +43 -0
  56. package/scripts/prepare.sh +11 -0
  57. package/scripts/pretest.js +14 -0
  58. package/src/config.schema.json +126 -0
  59. package/src/llaminate.d.ts +99 -0
  60. package/src/llaminate.ts +1326 -0
  61. package/src/llaminate.types.js +176 -0
  62. package/src/ratelimiter.ts +95 -0
  63. package/src/system.hbs +3 -0
  64. package/tests/attachments.test.js +66 -0
  65. package/tests/common/base64.js +13 -0
  66. package/tests/common/matches.js +69 -0
  67. package/tests/common/setup.js +45 -0
  68. package/tests/complete.test.js +27 -0
  69. package/tests/extensions/toMatchSchema.js +20 -0
  70. package/tests/history.test.js +86 -0
  71. package/tests/stream.test.js +67 -0
  72. package/tsconfig.json +12 -0
package/.gitattributes ADDED
@@ -0,0 +1,2 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright 2026 Oliver Moran <oliver.moran@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the “Software”), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
+ of the Software, and to permit persons to whom the Software is furnished to do
10
+ so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,95 @@
1
+ ![Llamina, the Llaminate mascot](./assets/llaminate-256.webp)
2
+
3
+ Llaminate is a simple but powerful library designed to abstract-away differences between chat completion APIs across LLM providers.
4
+
5
+ It's robust at managing prompts, message histories, token usage and integrating tools. Ideal for quickly building applications to interact with LLM services, that may need to switch between them.
6
+
7
+ ```bash
8
+ npm -i llaminate
9
+ ```
10
+
11
+ ```typescript
12
+ import { Llaminate } from "llaminate";
13
+ ```
14
+
15
+ ## Basic usage
16
+
17
+ ```typescript
18
+ const llaminate = new Llaminate({
19
+ endpoint: Llaminate.MISTRAL,
20
+ key: "12345-abcde-67890-fghij-klm",
21
+ model: "mistral-small-latest",
22
+ rpm: 720 // requests per minute (rater limiter)
23
+ });
24
+
25
+ const completion = await llaminate.complete("Hello, AI!");
26
+ console.log(completion.message);
27
+ ```
28
+
29
+ Streaming is made easy:
30
+
31
+ ```typescript
32
+ const stream = await llaminate.stream(
33
+ "How much wood would a woodchuck chuck if a woodchuck could chuck wood?"
34
+ );
35
+
36
+ for await (const sum of stream) {
37
+ console.log(sum);
38
+ }
39
+ ```
40
+
41
+ Llaminate is current an alpha release, but it is tested against:
42
+
43
+ * `Llaminate.ANTHROPIC`
44
+ * `Llaminate.DEEPSEEK`
45
+ * `Llaminate.GOOGLE`
46
+ * `Llaminate.MISTRAL`
47
+ * `Llaminate.OPENAI`
48
+
49
+ (Or you can use the URL to your provider.)
50
+
51
+ ## More features
52
+
53
+ Llaminate can handle tools, chat history, structured output, images and documents,
54
+ tracking your usage, and more:
55
+
56
+ ```typescript
57
+ const system = ["You are a sarcastic assistant who answers very briefly and bluntly."];
58
+
59
+ const attachments = [{
60
+ type: Llaminate.JPEG,
61
+ url: "https://live.staticflickr.com/7194/6964010157_9af8648f53.jpg"
62
+ }];
63
+
64
+ const schema = {
65
+ type: "object",
66
+ properties: {
67
+ reply: {
68
+ type: "string",
69
+ description: "Your response to the user's query."
70
+ },
71
+ thoughts: {
72
+ type: "string",
73
+ description: "Your internal thoughts about the user's query."
74
+ }
75
+ },
76
+ required: ["reply", "thoughts"]
77
+ };
78
+
79
+ const snarky = await mistral.complete("What do you see in this image?", {
80
+ system, attachments, schema
81
+ });
82
+
83
+ console.log(snarky.message.reply);
84
+ console.log(snarky.message.thoughts);
85
+ console.log(snarky.tokens.total);
86
+ ```
87
+
88
+ ## Documentation
89
+
90
+ Full [documentation is on the GitHub pages](Llaminate.html) website.
91
+
92
+ ---
93
+
94
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file
95
+ for details.
Binary file
Binary file
Binary file
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "llaminate",
3
+ "version": "0.1.0",
4
+ "date": "2026-03-26T10:25:32.393Z"
5
+ }
@@ -0,0 +1,126 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "properties": {
5
+ "endpoint": { "type": "string" },
6
+ "key": { "type": "string" },
7
+ "model": { "type": "string" },
8
+ "schema": {
9
+ "type": "object",
10
+ "properties": {
11
+ "type": { "type": "string" },
12
+ "properties": { "type": "object" },
13
+ "required": { "type": "array", "items": { "type": "string" } }
14
+ },
15
+ "additionalProperties": true
16
+ },
17
+ "system": {
18
+ "type": "array",
19
+ "items": { "type": "string" }
20
+ },
21
+ "history": {
22
+ "type": "array",
23
+ "items": {
24
+ "type": "object",
25
+ "properties": {
26
+ "role": { "type": "string", "enum": ["user", "assistant", "system", "tool", "developer"] },
27
+ "content": {},
28
+ "name": { "type": "string" },
29
+ "tool_calls": { "type": "array" },
30
+ "tool_call_id": { "type": "string" }
31
+ },
32
+ "required": ["role", "content"],
33
+ "additionalProperties": true
34
+ }
35
+ },
36
+ "attachments": {
37
+ "type": "array",
38
+ "items": {
39
+ "type": "object",
40
+ "properties": {
41
+ "type": { "type": "string" },
42
+ "url": { "type": "string" }
43
+ },
44
+ "required": ["type", "url"]
45
+ }
46
+ },
47
+ "window": {
48
+ "type": "integer",
49
+ "minimum": 1
50
+ },
51
+ "tools": {
52
+ "type": "array",
53
+ "items": {
54
+ "type": "object",
55
+ "properties": {
56
+ "function": {
57
+ "type": "object",
58
+ "properties": {
59
+ "name": { "type": "string" },
60
+ "description": { "type": "string" },
61
+ "parameters": { "type": "object" },
62
+ "strict": { "type": "boolean" }
63
+ },
64
+ "required": ["name"]
65
+ },
66
+ "handler": { "not": { "type": "null" } }
67
+ },
68
+ "required": ["function"]
69
+ }
70
+ },
71
+ "handler": { "not": { "type": "null" } },
72
+ "options": {
73
+ "type": "object",
74
+ "additionalProperties": true
75
+ },
76
+ "headers": {
77
+ "type": "object",
78
+ "additionalProperties": {
79
+ "type": "string"
80
+ }
81
+ },
82
+ "rpm": {
83
+ "type": "integer",
84
+ "minimum": 1
85
+ },
86
+ "quirks": {
87
+ "type": "object",
88
+ "properties": {
89
+ "attachments": {
90
+ "type": "object",
91
+ "properties": {
92
+ "document_url": { "type": "string", "enum": ["image_url"] },
93
+ "file": { "type": "boolean" },
94
+ "source": { "type": "boolean" }
95
+ },
96
+ "additionalProperties": true
97
+ },
98
+ "input_schema": { "type": "boolean" },
99
+ "json_schema": { "type": "boolean" },
100
+ "max_tokens": { "type": "integer", "minimum": 1 },
101
+ "output_config": { "type": "boolean" },
102
+ "role": {
103
+ "type": "object",
104
+ "properties": {
105
+ "system": { "type": "boolean" },
106
+ "tool": { "type": "boolean" }
107
+ },
108
+ "additionalProperties": true
109
+ },
110
+ "stream_options": { "type": "boolean" },
111
+ "tools": {
112
+ "type": "object",
113
+ "properties": {
114
+ "json_schema": { "type": "boolean" },
115
+ "json_object": { "type": "boolean" }
116
+ },
117
+ "additionalProperties": true
118
+ }
119
+ },
120
+ "additionalProperties": true
121
+ },
122
+ "fetch": { "not": { "type": "null" } }
123
+ },
124
+ "required": ["endpoint", "key", "model"],
125
+ "additionalProperties": false
126
+ }
@@ -0,0 +1,202 @@
1
+ /**
2
+ * @projectname Llaminate
3
+ * @author Oliver Moran <oliver.moran@gmail.com>
4
+ * @license
5
+ * Copyright 2026 Oliver Moran <oliver.moran@gmail.com>
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file at https://github.com/oliver-moran/llaminate
8
+ */
9
+ export type { LlaminateConfig, LlaminateResponse, LlaminateMessage } from "./llaminate.types.js";
10
+ /**
11
+ * @classdesc Represents the Llaminate service for managing and interacting with AI models.
12
+ */
13
+ export declare class Llaminate {
14
+ /**
15
+ * @property {string} Llaminate.GIF MIME type for GIF images (`image/gif`).
16
+ * @property {string} Llaminate.JPEG MIME type for JPEG images (`image/jpeg`).
17
+ * @property {string} Llaminate.PDF MIME type for PDF files (`application/pdf`).
18
+ * @property {string} Llaminate.PNG MIME type for PNG images (`image/png`).
19
+ * @property {string} Llaminate.WEBP MIME type for WEBP images (`image/webp`).
20
+ * @description Static MIME types for various file formats.
21
+ * @module MimeTypes
22
+ * @memberof Llaminate
23
+ * @example
24
+ * const response = await mistral.complete("Summarize the content of this image.", {
25
+ * attachments: [ { type: Llaminate.JPEG, url: "https://example.com/image.jpg" } ]
26
+ * });
27
+ */
28
+ static readonly PDF = "application/pdf";
29
+ static readonly JPEG = "image/jpeg";
30
+ static readonly PNG = "image/png";
31
+ static readonly GIF = "image/gif";
32
+ static readonly WEBP = "image/webp";
33
+ /**
34
+ * @property {string} Llaminate.USER_AGENT The User-Agent string used in API
35
+ * requests.
36
+ * @property {string} Llaminate.VERSION The version of the Llaminate library.
37
+ * @description Static property for the Llaminate library version.
38
+ * @module Llaminate
39
+ * @memberof Llaminate
40
+ */
41
+ static readonly VERSION: any;
42
+ static readonly USER_AGENT: string;
43
+ /**
44
+ * @property {string} Llaminate.ANTHROPIC Anthropic completions API endpoint.
45
+ * @property {string} Llaminate.DEEPSEEK Deepseek completions API endpoint.
46
+ * @property {string} Llaminate.GOOGLE Google completions API endpoint.
47
+ * @property {string} Llaminate.MISTRAL Mistral completions API endpoint.
48
+ * @property {string} Llaminate.OPENAI OpenAI completions API endpoint.
49
+ * @description Static properties for common LLM service endpoints, which
50
+ * can be used in the Llaminate configuration.
51
+ * @module Endpoints
52
+ * @memberof Llaminate
53
+ * @example
54
+ * const mistral = new Llaminate({
55
+ * endpoint: Llaminate.MISTRAL,
56
+ * key: "12345-abcde-67890-fghij-klm",
57
+ * model: "mistral-small-latest"
58
+ * });
59
+ */
60
+ static readonly MISTRAL = "https://api.mistral.ai/v1/chat/completions";
61
+ static readonly OPENAI = "https://api.openai.com/v1/chat/completions";
62
+ static readonly ANTHROPIC = "https://api.anthropic.com/v1/messages";
63
+ static readonly GOOGLE = "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions";
64
+ static readonly DEEPSEEK = "https://api.deepseek.com/chat/completions";
65
+ private history;
66
+ private readonly limiter;
67
+ private readonly config;
68
+ /**
69
+ * Constructs a new instance of the Llaminate class.
70
+ * @param {LlaminateConfig} config The configuration options for the
71
+ * Llaminate instance.
72
+ * @throws Will throw an error if the provided configuration is invalid.
73
+ * @example
74
+ * const mistral = new Llaminate({
75
+ * endpoint: Llaminate.MISTRAL,
76
+ * key: "12345-abcde-67890-fghij-klm",
77
+ * model: "mistral-small-latest",
78
+ * system: ["You are a sarcastic assistant who answers very briefly and bluntly."]
79
+ * rpm: 720
80
+ * });
81
+ */
82
+ constructor(config: LlaminateConfig);
83
+ /**
84
+ * Sends a prompt to the LLM service and returns a chat completion response.
85
+ * @param { string | LlaminateMessage[] } prompt The input prompt or
86
+ * messages to send to the service.
87
+ * @param { LlaminateConfig } [config] Optional configuration settings for
88
+ * this completion.
89
+ * @returns { Promise<LlaminateResponse> } A promise resolving to a
90
+ * LlaminateResponse from the service.
91
+ * @throws Will throw an error if the prompt is invalid, the response is
92
+ * unsuccessful, or if the response does not conform to the expected format.
93
+ * @example
94
+ * // EXAMPLE 1: Simple prompt with default configuration
95
+ * const response = await mistral.complete("What's the capital of France?");
96
+ * console.log(response.message); // "Paris"
97
+ * @example
98
+ * // EXAMPLE 2: System messages set through configuration
99
+ * const response = await mistral.complete("What's the capital of France?",
100
+ * { system: [
101
+ * "You are a children's geography tutor.",
102
+ * "Always reply as if you are explaining to a child."
103
+ * ] } );
104
+ * @example
105
+ * // EXAMPLE 3: An image attachment (supported depends on LLM model)
106
+ * const response = await mistral.complete(
107
+ * "Generate a helpful HTML `alt` tag for this image.", {
108
+ * attachments: [ { type: Llaminate.JPEG, url: "https://example.com/image.jpg" } ]
109
+ * });
110
+ * @example
111
+ * // EXAMPLE 4: Prompt with a pre-rolled conversation history
112
+ * const history = [
113
+ * { role: "user", content: "What's a good name for a houseplant?" },
114
+ * { role: "assistant", content: "How about Fernie Sanders?" },
115
+ * { role: "user", content: "Nice. Any other suggestions?" },
116
+ * { role: "assistant", content: "How about Leaf Erickson?" }
117
+ * ];
118
+ * const prompt = "Great. What could be its nickname?";
119
+ * const response = await mistral.complete(prompt, { history });
120
+ * @example
121
+ * // EXAMPLE 5: Rolling the conversation history into the prompt
122
+ * const messages = history.concat({ role: "user", content: prompt });
123
+ * const response = await mistral.complete(messages);
124
+ */
125
+ complete(prompt: string | LlaminateMessage[], config?: LlaminateConfig): Promise<LlaminateResponse>;
126
+ /**
127
+ * Sends a prompt to the LLM service and streams the response.
128
+ * @param { string | LlaminateMessage[] } prompt The input prompt or
129
+ * messages to send to the service.
130
+ * @param { LlaminateConfig } [config] Optional configuration settings for
131
+ * this completion.
132
+ * @yields { LlaminateResponse } An asynchronous generator yielding
133
+ * responses from the service.
134
+ * @throws Will throw an error if the prompt is invalid, the response is
135
+ * unsuccessful, or if the response does not conform to the expected format.
136
+ * @example
137
+ * // EXAMPLE 1: Streaming the response to a simple prompt
138
+ * const stream = mistral.stream("Tell me a joke and explain it.");
139
+ * for await (const response of stream) {
140
+ * console.log(response.message);
141
+ * }
142
+ * @example
143
+ * // EXAMPLE 2: Streaming a response with a structured output
144
+ * const stream = mistral.stream("Tell me a joke and explain it.", {
145
+ * schema: {
146
+ * type: "object",
147
+ * properties: {
148
+ * joke: {
149
+ * type: "string",
150
+ * description: "Your response to the user's query."
151
+ * },
152
+ * explanation: {
153
+ * type: "string",
154
+ * description: "Your internal thoughts about the user's query."
155
+ * },
156
+ * },
157
+ * required: ["joke", "explanation"],
158
+ * additionalProperties: false,
159
+ * }
160
+ * });
161
+ * for await (const response of stream) {
162
+ * // Initially streams as a string until the JSON schema can be validated
163
+ * console.log(response.message);
164
+ * console.log(response.message?.joke);
165
+ * console.log(response.message?.explanation);
166
+ * }
167
+ */
168
+ stream(prompt: string | LlaminateMessage[], config?: LlaminateConfig): AsyncGenerator<LlaminateResponse>;
169
+ /**
170
+ * Resets the chat history. This does not affect the configuration or any
171
+ * other settings.
172
+ * @returns void
173
+ * @example
174
+ * // EXAMPLE: Populating and then clearing the history
175
+ * mistral.complete("What's your name?"); // "John"
176
+ * mistral.complete("How do you spell that?"); // "J-O-H-N"
177
+ * mistral.clear();
178
+ * mistral.complete("Tell me again?"); // "Tell you what again?"
179
+ */
180
+ clear(): void;
181
+ /**
182
+ * Exports the chat history. By default, this exports the entire chat
183
+ * history. If a window is specified, only the most recent messages are
184
+ * returned. The window counts back each of the most recent user message, it
185
+ * includes assistant responses to these, and any system prompts set in the
186
+ * global configuration.
187
+ * @param { number } [window] The length of the window to retrieve.
188
+ * @returns { LlaminateMessage[] } An array of chat history messages.
189
+ * @example
190
+ * // EXAMPLE 1: Exporting the entire history of messages
191
+ * const history = mistral.export();
192
+ * localStorage.setItem('mistral-history', JSON.stringify(history));
193
+ * @example
194
+ * // EXAMPLE 2: Getting a window of recent messages
195
+ * // Returns the last 5 user-assistant interactions and all system prompts
196
+ * const history = mistral.export(5);
197
+ * console.log(history.length);
198
+ * // e.g. 14 = 5 user messages + 5 assistant replies (one that included a
199
+ * // tool call) + 2 system prompts
200
+ */
201
+ export(window?: number): LlaminateMessage[];
202
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /**
3
+ * @projectname Llaminate
4
+ * @author Oliver Moran <oliver.moran@gmail.com>
5
+ * @license
6
+ * Copyright 2026 Oliver Moran <oliver.moran@gmail.com>
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file at https://github.com/oliver-moran/llaminate
9
+ */Object.defineProperty(exports,"__esModule",{value:true});exports.Llaminate=void 0;const os=require("os");const ajv_1=require("ajv");const buffer_1=require("buffer");const ratelimiter_min_js_1=require("./ratelimiter.min.js");const ajv=new ajv_1.default;const validate={config:ajv.compile(require("./config.schema.json"))};const structuredClone=globalThis.structuredClone||(obj=>JSON.parse(JSON.stringify(obj)));const noop=()=>{};const SYSTEM_HBS=(()=>{const fs=require("fs");const Handlebars=require("handlebars");const template=Handlebars.compile(fs.readFileSync(require.resolve("./system.hbs"),"utf-8"));return schema=>template({schema:schema})})();const{version:LLAMINATE_VERSION}=require("./build-info.json");const NODE_TITLE=process.title||"Node.js";const NODE_VERSION=process.version;const OS_TYPE=os.type();const OS_ARCH=os.arch();const USER_AGENT=`Llaminate/${LLAMINATE_VERSION} (https://github.com/oliver-moran/llaminate; ${NODE_TITLE}/${NODE_VERSION}; ${OS_TYPE}/${OS_ARCH})`;const ROLES=["assistant","developer","system","user","tool"];class Llaminate{constructor(config){this.history=[];this.config={endpoint:null,key:null,model:null,tools:[],system:[],attachments:[],window:12,headers:{},options:{parallel_tool_calls:true,response_format:{type:"text"}},handler:async(name,args)=>{throw new Error(`No \`handler\` method provided for \`${name}\` was provided in the Llaminate configuration.`)},fetch:globalThis.fetch.bind(globalThis),rpm:Infinity};validateConfig(config);this.config.endpoint=config.endpoint;this.config.key=config.key;this.config.model=config.model;this.config.schema=config.schema;this.history=this.config.history||this.history;delete config.history;this.config.tools=config.tools||this.config.tools;this.config.system=config.system||this.config.system;this.config.window=config.window||this.config.window;this.config.headers=config.headers||this.config.headers;this.config.options={...this.config.options,...config.options};this.config.handler=config.handler||this.config.handler;this.config.fetch=config.fetch||this.config.fetch;const quirks=getQuirks(this.config);this.config.quirks={...quirks,...config.quirks};delete this.config.attachments;deepFreeze(this.config);this.limiter=new ratelimiter_min_js_1.RateLimiter(config.rpm)}async complete(prompt,config){const _config=generateCompletionConfig.call(this,config,false);const messages=prepareMessageWindow.call(this,prompt,_config);const result=[];const subtotal={input:0,output:0,total:0};return await _complete.call(this,messages);async function _complete(){var _a,_b,_c;const response=await this.limiter.queue(()=>sendMessages([...messages,...result],_config));if(!response.ok)throw new Error(`HTTP status ${response.status} from ${_config.endpoint}.\n\n${await response.text()}`);const completion=await response.json();const message=((_b=(_a=completion===null||completion===void 0?void 0:completion.choices)===null||_a===void 0?void 0:_a[0])===null||_b===void 0?void 0:_b.message)||((_c=completion===null||completion===void 0?void 0:completion.content)===null||_c===void 0?void 0:_c[0])||null;const tokens=getUsageFromCompletion(completion);subtotal.input+=tokens.input||0;subtotal.output+=tokens.output||0;subtotal.total+=tokens.total||subtotal.input+subtotal.output||0;const calls=message.tool_calls||transformAnthropicToolCalls(completion===null||completion===void 0?void 0:completion.content)||[];const role=message.role;const recursed=await handleTools.call(this,role,calls,{messages:messages,result:result,subtotal:subtotal,config:_config,recurse:_complete});if(recursed)return recursed;else{const content=validateResponse((message===null||message===void 0?void 0:message.content)||(message===null||message===void 0?void 0:message.text)||"",_config);result.push({role:role||"assistant",content:content});updateHistory.call(this,prompt,result);return generateOutputObject(content,result,subtotal,uuid_v4(),_config)}}}async*stream(prompt,config){const _config=generateCompletionConfig.call(this,config,true);const messages=prepareMessageWindow.call(this,prompt,_config);const result=[];const subtotal={input:0,output:0,total:0};const stream=await _stream.call(this,messages);for await(const result of stream)yield result;async function*_stream(){var _a,_b;const response=await this.limiter.queue(()=>sendMessages([...messages,...result],_config));if(!response.ok)throw new Error(`HTTP status ${response.status} from ${_config.endpoint}.\n\n${await response.text()}`);if(!response.body)throw new Error(`No readable stream from ${_config.endpoint}.\n\n${await response.text()}`);const reader=response.body.getReader();const decoder=new TextDecoder("utf-8");let buffer="";let content="";let role="";let tokens={input:0,output:0,total:0};let tools=[];const uuid=uuid_v4();while(true){const{value:value,done:done}=await reader.read();if(done)break;buffer+=decoder.decode(value,{stream:true});let lines=buffer.split("\n");buffer=lines.pop();for(const line of lines){if(line.startsWith("data: ")){try{const json=line.slice(6).trim();const completion=JSON.parse(json);const delta=((_b=(_a=completion.choices)===null||_a===void 0?void 0:_a[0])===null||_b===void 0?void 0:_b.delta)||completion.delta;content+=(delta===null||delta===void 0?void 0:delta.content)||(delta===null||delta===void 0?void 0:delta.text)||"";if(!ROLES.includes(role))role+=(delta===null||delta===void 0?void 0:delta.role)||"";tools=mergeToolsDeltas(tools,(delta===null||delta===void 0?void 0:delta.tool_calls)||transformAnthropicToolCalls(completion.content_block));const usage=getUsageFromCompletion(completion);tokens.input=usage.input||tokens.input;tokens.output=usage.output||tokens.output;tokens.total=usage.total||tokens.total;yield generateOutputObject(content,null,null,uuid)}catch(error){}}}}subtotal.input+=tokens.input||0;subtotal.output+=tokens.output||0;subtotal.total+=tokens.total||subtotal.input+subtotal.output||0;const recursed=await handleTools.call(this,role,tools,{messages:messages,result:result,subtotal:subtotal,config:_config,recurse:_stream});if(recursed)for await(const result of recursed)yield result;else{content=validateResponse(content,_config);result.push({role:role||"assistant",content:content});updateHistory.call(this,prompt,result);yield generateOutputObject(content,result,subtotal,uuid,_config)}}}clear(){this.history=[]}export(window=Infinity){if(window&&(isNaN(window)||window<1))window=1;const config={...this.config,window:window};const history=getWindowFromHistory(this.history,config);return structuredClone(history)}}exports.Llaminate=Llaminate;Llaminate.PDF="application/pdf";Llaminate.JPEG="image/jpeg";Llaminate.PNG="image/png";Llaminate.GIF="image/gif";Llaminate.WEBP="image/webp";Llaminate.VERSION=LLAMINATE_VERSION;Llaminate.USER_AGENT=USER_AGENT;Llaminate.MISTRAL="https://api.mistral.ai/v1/chat/completions";Llaminate.OPENAI="https://api.openai.com/v1/chat/completions";Llaminate.ANTHROPIC="https://api.anthropic.com/v1/messages";Llaminate.GOOGLE="https://generativelanguage.googleapis.com/v1beta/openai/chat/completions";Llaminate.DEEPSEEK="https://api.deepseek.com/chat/completions";function generateCompletionConfig(config,stream=false){var _a,_b;const _config={...this.config,...config,system:this.config.system.concat((config===null||config===void 0?void 0:config.system)||[]),options:{...(_a=this.config)===null||_a===void 0?void 0:_a.options,...config===null||config===void 0?void 0:config.options,stream:stream,stream_options:stream?{include_usage:true}:undefined}};const tools=(config===null||config===void 0?void 0:config.tools)||((_b=this.config)===null||_b===void 0?void 0:_b.tools)||[];if(tools.length>0){_config.options.tools=tools.map(tool=>({type:"function",function:tool.function}))}else{delete _config.options.tools;delete _config.options.parallel_tool_calls}delete _config.rpm;validateConfig(_config);if(_config.schema){_config.options.response_format={type:"json_schema",json_schema:{name:`schema_${uuid_v4()}`,schema:_config.schema}}}return _config}function validateConfig(config){if(!validate.config(config))throw new Error(`The \`config\` provided to Llaminate was not a valid configuration.\n\n${ajv.errorsText(validate.config.errors)}`)}async function sendMessages(messages,config){const headers={Authorization:`Bearer ${config.key}`,"X-Api-Key":`${config.key}`,"x-goog-api-key":`${config.key}`,"anthropic-version":"2023-06-01","User-Agent":USER_AGENT,"Content-Type":"application/json",Accept:"application/json, text/event-stream",Connection:"keep-alive",...config.headers};const body=await applyQuirks({...config.options,model:config.model,messages:messages},config);const json=JSON.stringify(body,null,2);return config.fetch(config.endpoint,{method:"POST",headers:headers,body:json})}async function applyQuirks(body,config){var _a,_b,_c,_d,_e,_f,_g,_h,_j,_k,_l,_m,_o,_p,_q,_r,_s,_t,_u,_v,_w,_x,_y,_z,_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12;const modified=structuredClone(body);const instructions=[];for(const message of(modified===null||modified===void 0?void 0:modified.messages)||[]){if(message.role==="tool"&&((_b=(_a=config.quirks)===null||_a===void 0?void 0:_a.role)===null||_b===void 0?void 0:_b.tool)===false){message.role="user";message.content=[{type:"tool_result",tool_use_id:message.tool_call_id,content:message.content}];delete message.name;delete message.tool_call_id}if(message.role==="assistant"&&message.tool_calls&&((_d=(_c=config.quirks)===null||_c===void 0?void 0:_c.role)===null||_d===void 0?void 0:_d.tool)===false){message.content=(_e=message.tool_calls)===null||_e===void 0?void 0:_e.map(call=>({type:"tool_use",id:call.id,name:call.function.name,input:JSON.parse(call.function.arguments)}));delete message.tool_calls}if(Array.isArray(message.content)){for(const content of(message===null||message===void 0?void 0:message.content)||[]){if(content.type==="image_url"&&isHttpUrl((_f=content.image_url)===null||_f===void 0?void 0:_f.url)&&((_h=(_g=config.quirks)===null||_g===void 0?void 0:_g.attachments)===null||_h===void 0?void 0:_h.source)===true){content.type="image";content.source={type:"url",url:content.image_url.url};delete content.image_url}if(content.type==="document_url"&&isHttpUrl(content.document_url)&&((_k=(_j=config.quirks)===null||_j===void 0?void 0:_j.attachments)===null||_k===void 0?void 0:_k.source)===true){content.type="document";content.source={type:"url",url:content.document_url};delete content.document_url}if(["image_url","document_url"].includes(content.type)&&isBase64DataUri(((_l=content[content.type])===null||_l===void 0?void 0:_l.url)||content[content.type])&&((_o=(_m=config.quirks)===null||_m===void 0?void 0:_m.attachments)===null||_o===void 0?void 0:_o.source)===true){const uri=((_p=content[content.type])===null||_p===void 0?void 0:_p.url)||content[content.type];const[meta,data]=uri.split(",");const mime=((_q=meta.match(/data:(.*);base64/))===null||_q===void 0?void 0:_q[1])||"application/octet-stream";content.type=mime===Llaminate.PDF?"document":"image";content.source={type:"base64",data:data,media_type:mime};delete content.image_url;delete content.document_url}if(content.type==="document_url"&&((_s=(_r=config.quirks)===null||_r===void 0?void 0:_r.attachments)===null||_s===void 0?void 0:_s.document_url)==="image_url"){content.type="image_url";content.image_url={type:"url",url:content.document_url};delete content.document_url}if(content.type==="document_url"&&((_u=(_t=config.quirks)===null||_t===void 0?void 0:_t.attachments)===null||_u===void 0?void 0:_u.file)===true){const data=isHttpUrl(content.document_url)?await fetchUrlAsBase64(content.document_url):content.document_url;content.type="file";content.file={file_data:data,filename:uuid_v4()};delete content.document_url}}}}(_v=modified.tools)===null||_v===void 0?void 0:_v.forEach((tool,i,tools)=>{var _a;if(((_a=config.quirks)===null||_a===void 0?void 0:_a.input_schema)===true){tools[i]={name:tool.function.name,description:tool.function.description,input_schema:tool.function.parameters,strict:tool.strict}}});if(["json_schema","json_object"].includes((_w=modified.response_format)===null||_w===void 0?void 0:_w.type)){if(((_x=modified.tools)===null||_x===void 0?void 0:_x.length)>0&&((_z=(_y=config.quirks)===null||_y===void 0?void 0:_y.tools)===null||_z===void 0?void 0:_z.json_schema)===false&&((_1=(_0=config.quirks)===null||_0===void 0?void 0:_0.tools)===null||_1===void 0?void 0:_1.json_object)===false){const schema=JSON.stringify(cleanse((_2=modified.response_format)===null||_2===void 0?void 0:_2.json_schema),null,2);instructions.push(SYSTEM_HBS(schema));modified.response_format.type="text";delete modified.response_format.json_schema}}if(((_3=modified.response_format)===null||_3===void 0?void 0:_3.type)==="json_schema"&&((_4=config.quirks)===null||_4===void 0?void 0:_4.json_schema)===false){const schema=JSON.stringify(cleanse((_5=modified.response_format)===null||_5===void 0?void 0:_5.json_schema),null,2);instructions.push(SYSTEM_HBS(schema));modified.response_format.type="json_object";delete modified.response_format.json_schema}if(((_6=config.quirks)===null||_6===void 0?void 0:_6.parallel_tool_calls)===false){delete modified.parallel_tool_calls}if(((_8=(_7=config.quirks)===null||_7===void 0?void 0:_7.role)===null||_8===void 0?void 0:_8.system)===false){modified.system=[...instructions.map(text=>({type:"text",text:text})),...modified.messages.filter(message=>message.role==="system").map(message=>({type:"text",text:message.content}))];modified.messages=modified.messages.filter(message=>message.role!=="system")}else{modified.messages=[...instructions.map(text=>({role:"system",content:text})),...modified.messages||[]]}if(typeof((_9=config.quirks)===null||_9===void 0?void 0:_9.max_tokens)==="number"){modified.max_tokens=modified.max_tokens||((_10=config.quirks)===null||_10===void 0?void 0:_10.max_tokens)}if(((_11=config.quirks)===null||_11===void 0?void 0:_11.output_config)===true){if(modified.response_format.type==="json_schema"){modified.output_config={format:{type:"json_schema",schema:modified.response_format.json_schema.schema}}}delete modified.response_format}if(((_12=config.quirks)===null||_12===void 0?void 0:_12.stream_options)===false){delete modified.stream_options}return cleanse(modified)}function transformAnthropicToolCalls(messages){if(!Array.isArray(messages))messages=[messages];return messages===null||messages===void 0?void 0:messages.map(message=>{if((message===null||message===void 0?void 0:message.type)=="tool_use")return{type:"function",function:{name:message.name,arguments:JSON.stringify(message.input)},id:message.id}}).filter(Boolean)}function mergeToolsDeltas(existing,incoming=[]){const merged=[...existing];incoming===null||incoming===void 0?void 0:incoming.forEach((delta,i)=>{var _a,_b;if(!delta.id)return;let found=existing.find(call=>call.id===delta.id);if(!found){found={type:"",function:{name:"",arguments:""},id:""};merged.push(found)}found.type+=delta.type||"";found.function.name+=((_a=delta.function)===null||_a===void 0?void 0:_a.name)||"";found.function.arguments+=((_b=delta.function)===null||_b===void 0?void 0:_b.arguments)||"";found.id+=delta.id||"";if(delta.extra_content){found.extra_content={...found.extra_content,...delta.extra_content}}});return merged}async function handleTools(role,calls,context){if(calls.length>0){context.result.push({role:role||"assistant",tool_calls:calls.map(call=>{const cleansed=cleanse(call);cleansed.type=cleansed.type||"function";cleansed.function.arguments=sanatiseJSON(cleansed.function.arguments);return cleansed})});for(const call of calls){const tool=context.config.tools.find(tool=>tool.function.name===call.function.name);if(tool){try{const args=JSON.parse(call.function.arguments);const response=await(tool.handler||context.config.handler||noop).call(globalThis,call.function.name,args);context.result.push({role:"tool",name:tool.function.name,content:serialize(response),tool_call_id:call.id})}catch(error){context.result.push({role:"tool",name:tool.function.name,content:JSON.stringify({error:error.message}),tool_call_id:call.id})}}else{throw new Error(`The LLM response included a tool call for a tool that isn't defined in the Llaminate configuration (${call.function.name}).`)}}return await context.recurse.call(this)}}function getUsageFromCompletion(completion){var _a,_b,_c,_d,_e;const input=((_a=completion===null||completion===void 0?void 0:completion.usage)===null||_a===void 0?void 0:_a.prompt_tokens)||((_b=completion===null||completion===void 0?void 0:completion.usage)===null||_b===void 0?void 0:_b.input_tokens)||null;const output=((_c=completion===null||completion===void 0?void 0:completion.usage)===null||_c===void 0?void 0:_c.completion_tokens)||((_d=completion===null||completion===void 0?void 0:completion.usage)===null||_d===void 0?void 0:_d.output_tokens)||null;const total=((_e=completion===null||completion===void 0?void 0:completion.usage)===null||_e===void 0?void 0:_e.total_tokens)||null;return{input:parseInt(input),output:parseInt(output),total:parseInt(total)}}function generateOutputObject(message,result,tokens,uuid,config){if(config===null||config===void 0?void 0:config.schema)return{message:JSON.parse(message),result:result,tokens:tokens,uuid:uuid};else return{message:message,result:result,tokens:tokens,uuid:uuid}}function prepareMessageWindow(prompt,config){let messages=[];if(Array.isArray(prompt))messages=getWindowFromHistory(prompt,config);else if(typeof prompt==="string")messages=getWindowFromHistory(this.history.concat({role:"user",content:prompt}),config);else throw new Error(`The \`prompt\` provided to Llaminate was not a string or an array of messages.`);if(config.attachments&&config.attachments.length>0){messages[messages.length-1].content=[{type:"text",text:messages[messages.length-1].content},...config.attachments.map(attachment=>{var _a;return((_a=attachment.type)===null||_a===void 0?void 0:_a.startsWith("image"))?{type:"image_url",image_url:{url:attachment.url}}:{type:"document_url",document_url:attachment.url}})]}return messages}function getWindowFromHistory(messages,config){let count=0;return[...(config.system||[]).map(content=>({role:"system",content:content})),...config.history||[],...messages.concat().reverse().map(message=>{if(message.role==="system")return message;if(count<config.window){if(message.role==="user")count++;return message}}).filter(Boolean).reverse()]}function updateHistory(prompt,result){if(Array.isArray(prompt))this.history=prompt.concat(result);else if(typeof prompt==="string")this.history.push({role:"user",content:prompt},...result)}function cleanse(obj){if(obj&&obj.constructor!==Object)return Object.entries(obj).reduce((acc,[key,value])=>{if(value===null){return acc}else if(typeof value==="object"&&!Array.isArray(value)&&value!==null){acc[key]=cleanse(value)}else{acc[key]=value}return acc},{});else return obj}function validateResponse(message,config){if(config.schema){const json=sanatiseJSON(message);const obj=JSON.parse(json);const schema=ajv.compile(config.schema);const valid=schema(obj);if(!valid)throw new Error(`The LLM response did not conform to the \`schema\` provided in the Llaminate configuration.\n\n${ajv.errorsText(schema.errors)}`);return JSON.stringify(obj)}else if(message)return message;else throw new Error("The LLM response was empty.")}function serialize(obj){try{return JSON.stringify(obj)}catch(error){try{if(obj&&typeof obj.toString==="function"){const str=obj.toString();if(typeof str==="string")return JSON.stringify(str)}}catch(error){}throw error}}function uuid_v4(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(c){const r=Math.random()*16|0,v=c==="x"?r:r&3|8;return v.toString(16)})}function deepFreeze(obj){const props=Object.getOwnPropertyNames(obj);for(const name of props){const value=obj[name];if(value&&typeof value==="object")deepFreeze(value)}return Object.freeze(obj)}function sanatiseJSON(json){var _a;try{const match=((_a=json.match(/{.*}/s))===null||_a===void 0?void 0:_a[0])||"{}";JSON.parse(match);return match}catch(error){throw new Error(`The LLM response could not be parsed as JSON.\n\n${json}`)}}function getQuirks(config){const endpoint=config.endpoint;const isMistral=endpoint.startsWith(Llaminate.MISTRAL);const isOpenAI=endpoint.startsWith(Llaminate.OPENAI);const isGoogle=endpoint.startsWith(Llaminate.GOOGLE);const isDeepSeek=endpoint.startsWith(Llaminate.DEEPSEEK);const isAnthropic=endpoint.startsWith(Llaminate.ANTHROPIC);return{attachments:{document_url:isGoogle?"image_url":undefined,source:isAnthropic,file:isOpenAI},input_schema:isAnthropic,json_schema:!isDeepSeek&&!isMistral,max_tokens:isAnthropic?64e3:undefined,output_config:isAnthropic,parallel_tool_calls:!isAnthropic,role:{system:!isAnthropic,tool:!isAnthropic},stream_options:!isAnthropic,tools:{json_schema:!isMistral,json_object:!isMistral}}}async function fetchUrlAsBase64(url){const response=await fetch(url,{headers:{"User-Agent":USER_AGENT}});if(!response.ok){throw new Error(`HTTP status ${response.status} from ${url}.\n\n${await response.text()}`)}try{const buffer=await response.arrayBuffer();const base64=buffer_1.Buffer.from(buffer).toString("base64");const type=response.headers.get("content-type")||"application/octet-stream";return`data:${type};base64,${base64}`}catch(error){throw new Error(`Failed to encode from ${url} as base64.\n\n${error.message}`)}}function isHttpUrl(url){try{const parsed=new URL(url);return["http:","https:"].includes(parsed.protocol)}catch(error){return false}}function isBase64DataUri(uri){return/^data:.*;base64,/.test(uri)}
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Object","defineProperty","exports","value","Llaminate","os","require","ajv_1","buffer_1","ratelimiter_min_js_1","ajv","default","validate","config","compile","structuredClone","globalThis","obj","JSON","parse","stringify","noop","SYSTEM_HBS","fs","Handlebars","template","readFileSync","resolve","schema","version","LLAMINATE_VERSION","NODE_TITLE","process","title","NODE_VERSION","OS_TYPE","type","OS_ARCH","arch","USER_AGENT","ROLES","constructor","this","history","endpoint","key","model","tools","system","attachments","window","headers","options","parallel_tool_calls","response_format","handler","async","name","args","Error","fetch","bind","rpm","Infinity","validateConfig","quirks","getQuirks","deepFreeze","limiter","RateLimiter","complete","prompt","_config","generateCompletionConfig","call","messages","prepareMessageWindow","result","subtotal","input","output","total","_complete","_a","_b","_c","response","queue","sendMessages","ok","status","text","completion","json","message","choices","content","tokens","getUsageFromCompletion","calls","tool_calls","transformAnthropicToolCalls","role","recursed","handleTools","recurse","validateResponse","push","updateHistory","generateOutputObject","uuid_v4","stream","_stream","body","reader","getReader","decoder","TextDecoder","buffer","uuid","done","read","decode","lines","split","pop","line","startsWith","slice","trim","delta","includes","mergeToolsDeltas","content_block","usage","error","clear","isNaN","getWindowFromHistory","PDF","JPEG","PNG","GIF","WEBP","VERSION","MISTRAL","OPENAI","ANTHROPIC","GOOGLE","DEEPSEEK","concat","stream_options","include_usage","undefined","length","map","tool","function","json_schema","errorsText","errors","Authorization","Accept","Connection","applyQuirks","method","_d","_e","_f","_g","_h","_j","_k","_l","_m","_o","_p","_q","_r","_s","_t","_u","_v","_w","_x","_y","_z","_0","_1","_2","_3","_4","_5","_6","_7","_8","_9","_10","_11","_12","modified","instructions","tool_use_id","tool_call_id","id","arguments","Array","isArray","isHttpUrl","image_url","url","source","document_url","isBase64DataUri","uri","meta","data","mime","match","media_type","file","fetchUrlAsBase64","file_data","filename","forEach","i","input_schema","description","parameters","strict","json_object","cleanse","filter","max_tokens","output_config","format","Boolean","existing","incoming","merged","found","find","extra_content","context","cleansed","sanatiseJSON","serialize","prompt_tokens","input_tokens","completion_tokens","output_tokens","total_tokens","parseInt","attachment","count","reverse","entries","reduce","acc","valid","toString","str","replace","c","r","Math","random","v","props","getOwnPropertyNames","freeze","isMistral","isOpenAI","isGoogle","isDeepSeek","isAnthropic","arrayBuffer","base64","Buffer","from","get","parsed","URL","protocol","test"],"sources":["dist/llaminate.js"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Oliver Moran <oliver.moran@gmail.com>
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file at https://github.com/oliver-moran/llaminate
6
+ */
7
+ export declare class RateLimiter {
8
+ private readonly rpm;
9
+ private readonly bucket;
10
+ /**
11
+ * Creates a new RateLimiter instance with the specified RPM (requests per minute). If no RPM is provided, it defaults to Infinity (no rate limiting).
12
+ * @param rpm The number of requests allowed per minute for each unique endpoint. Must be a number. If not provided, defaults to Infinity (no rate limiting).
13
+ * @throws Will throw an error if the RPM is not a number.
14
+ * @example
15
+ * const limiter = new RateLimiter(60);
16
+ */
17
+ constructor(rpm?: number);
18
+ /**
19
+ * Adds a function to the appropriate queue, ensuring that it is executed according to the specified RPM.
20
+ * @param fn The function to be executed
21
+ * @returns A promise that resolves with the result of the function
22
+ * @throws Will throw an error if the first argument is not a function.
23
+ * @example
24
+ * const result = await limiter.queue(() => fetch("https://api.example.com/chat/completions", { method: "POST", body: JSON.stringify({ model: "llm-model-name", messages: [...] }) }));
25
+ */
26
+ queue(fn: Function): Promise<any>;
27
+ /**
28
+ * Clears the bucket for the given endpoint, removing all queued functions and stopping the interval.
29
+ * @example
30
+ * limiter.clear();
31
+ */
32
+ clear(): void;
33
+ }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Oliver Moran <oliver.moran@gmail.com>
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file at https://github.com/oliver-moran/llaminate
7
+ */Object.defineProperty(exports,"__esModule",{value:true});exports.RateLimiter=void 0;class RateLimiter{constructor(rpm){if(rpm&&(isNaN(rpm)||rpm<1))throw new Error("RPM must be a number greater than or equal to 1");this.rpm=rpm||Infinity;this.bucket={queue:[],interval:null}}async queue(fn){if(typeof fn!=="function"){throw new Error("First argument must be a function")}const bucket=this.bucket;return new Promise(async(resolve,reject)=>{const task={resolve:resolve,reject:reject,fn:fn};bucket.queue.push(task);const next=_next.bind(this);if(bucket.interval===null){next();bucket.interval=setInterval(next,6e4/this.rpm)}async function _next(){const task=bucket.queue.shift();if(task)_execute(task);else this.clear()}async function _execute(task){if(task){try{task.resolve(await task.fn())}catch(err){task.reject(err)}}}})}clear(){const bucket=this.bucket;if(bucket){bucket.queue=[];clearInterval(bucket.interval);bucket.interval=null}}}exports.RateLimiter=RateLimiter;
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Object","defineProperty","exports","value","RateLimiter","constructor","rpm","isNaN","Error","this","Infinity","bucket","queue","interval","fn","Promise","async","resolve","reject","task","push","next","_next","bind","setInterval","shift","_execute","clear","err","clearInterval"],"sources":["dist/ratelimiter.js"],"mappings":"AAAA;;;;;;GAOAA,OAAOC,eAAeC,QAAS,aAAc,CAAEC,MAAO,OACtDD,QAAQE,iBAAmB,EAC3B,MAAMA,YAQF,WAAAC,CAAYC,KACR,GAAIA,MAAQC,MAAMD,MAAQA,IAAM,GAC5B,MAAM,IAAIE,MAAM,mDACpBC,KAAKH,IAAMA,KAAOI,SAClBD,KAAKE,OAAS,CAAEC,MAAO,GAAIC,SAAU,KACzC,CASA,WAAMD,CAAME,IACR,UAAWA,KAAO,WAAY,CAC1B,MAAM,IAAIN,MAAM,oCACpB,CAEA,MAAMG,OAASF,KAAKE,OAEpB,OAAO,IAAII,QAAQC,MAAOC,QAASC,UAE/B,MAAMC,KAAO,CAAEF,gBAASC,cAAQJ,OAChCH,OAAOC,MAAMQ,KAAKD,MAElB,MAAME,KAAOC,MAAMC,KAAKd,MACxB,GAAIE,OAAOE,WAAa,KAAM,CAC1BQ,OACAV,OAAOE,SAAWW,YAAYH,KAAM,IAAQZ,KAAKH,IACrD,CAEAU,eAAeM,QACX,MAAMH,KAAOR,OAAOC,MAAMa,QAC1B,GAAIN,KACAO,SAASP,WAETV,KAAKkB,OACb,CAEAX,eAAeU,SAASP,MACpB,GAAIA,KAAM,CACN,IACIA,KAAKF,cAAcE,KAAKL,KAC5B,CACA,MAAOc,KACHT,KAAKD,OAAOU,IAChB,CACJ,CACJ,GAER,CAMA,KAAAD,GACI,MAAMhB,OAASF,KAAKE,OACpB,GAAIA,OAAQ,CACRA,OAAOC,MAAQ,GACfiB,cAAclB,OAAOE,UACrBF,OAAOE,SAAW,IACtB,CACJ,EAEJX,QAAQE,YAAcA","ignoreList":[]}
@@ -0,0 +1,3 @@
1
+ IMPORTANT: Respond to the user in JSON format and adhere to the following schema:
2
+
3
+ {{{schema}}}