@flink-app/fake-llm-adapter 2.0.0-alpha.100
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/LICENSE +21 -0
- package/README.md +440 -0
- package/dist/FakeLLMAdapter.d.ts +21 -0
- package/dist/FakeLLMAdapter.d.ts.map +1 -0
- package/dist/FakeLLMAdapter.js +134 -0
- package/dist/FakeLLMAdapter.js.map +1 -0
- package/dist/ResponseGenerator.d.ts +14 -0
- package/dist/ResponseGenerator.d.ts.map +1 -0
- package/dist/ResponseGenerator.js +96 -0
- package/dist/ResponseGenerator.js.map +1 -0
- package/dist/SeededRandom.d.ts +9 -0
- package/dist/SeededRandom.d.ts.map +1 -0
- package/dist/SeededRandom.js +24 -0
- package/dist/SeededRandom.js.map +1 -0
- package/dist/TokenEstimator.d.ts +8 -0
- package/dist/TokenEstimator.d.ts.map +1 -0
- package/dist/TokenEstimator.js +28 -0
- package/dist/TokenEstimator.js.map +1 -0
- package/dist/ToolCallDecider.d.ts +22 -0
- package/dist/ToolCallDecider.d.ts.map +1 -0
- package/dist/ToolCallDecider.js +159 -0
- package/dist/ToolCallDecider.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +21 -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 +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Frost Experience AB https://www.frost.se
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all 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
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
# @flink-app/fake-llm-adapter
|
|
2
|
+
|
|
3
|
+
A fake LLM adapter for the Flink AI framework - perfect for demos, development, and testing without requiring real LLM API connections.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `FakeLLMAdapter` implements the `LLMAdapter` interface and generates contextually relevant responses with intelligent tool calling decisions. Unlike simple mocks, it:
|
|
8
|
+
|
|
9
|
+
- **Intelligently decides when to call tools** based on user messages and available tools
|
|
10
|
+
- **Generates realistic tool inputs** by analyzing tool schemas and extracting values from user messages
|
|
11
|
+
- **Provides contextually relevant text responses** using customizable templates
|
|
12
|
+
- **Simulates realistic token usage** for testing cost/performance scenarios
|
|
13
|
+
- **Supports reproducible randomness** via seeding for deterministic testing
|
|
14
|
+
- **Configurable behavior modes** from text-only to tool-heavy
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add @flink-app/fake-llm-adapter
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { FlinkApp } from "@flink-app/flink";
|
|
26
|
+
import { FakeLLMAdapter } from "@flink-app/fake-llm-adapter";
|
|
27
|
+
|
|
28
|
+
const app = new FlinkApp({
|
|
29
|
+
ai: {
|
|
30
|
+
llms: {
|
|
31
|
+
fake: new FakeLLMAdapter()
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Creating an Agent with Fake Adapter
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { createAgent } from "@flink-app/flink/ai";
|
|
41
|
+
import { FakeLLMAdapter } from "@flink-app/fake-llm-adapter";
|
|
42
|
+
|
|
43
|
+
const weatherAgent = createAgent({
|
|
44
|
+
llm: new FakeLLMAdapter({
|
|
45
|
+
mode: "tool-heavy", // Prefer calling tools
|
|
46
|
+
preferredTools: ["get_weather"], // Prioritize weather tool
|
|
47
|
+
}),
|
|
48
|
+
instructions: "You are a helpful weather assistant.",
|
|
49
|
+
tools: [
|
|
50
|
+
{
|
|
51
|
+
name: "get_weather",
|
|
52
|
+
description: "Get weather for a location",
|
|
53
|
+
input_schema: {
|
|
54
|
+
type: "object",
|
|
55
|
+
properties: {
|
|
56
|
+
city: { type: "string" },
|
|
57
|
+
unit: { type: "string", enum: ["celsius", "fahrenheit"] }
|
|
58
|
+
},
|
|
59
|
+
required: ["city"]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const result = await weatherAgent.execute("What's the weather in Stockholm?");
|
|
66
|
+
// Likely calls get_weather tool with { city: "Stockholm", unit: "celsius" }
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Configuration
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
export interface FakeLLMAdapterConfig {
|
|
73
|
+
// Response behavior
|
|
74
|
+
mode?: AdapterMode; // "balanced" | "tool-heavy" | "text-only" | "random"
|
|
75
|
+
|
|
76
|
+
// Tool calling configuration
|
|
77
|
+
toolCallProbability?: number; // 0.0 to 1.0 (default: 0.3)
|
|
78
|
+
maxToolCallsPerTurn?: number; // default: 3
|
|
79
|
+
|
|
80
|
+
// Randomness control
|
|
81
|
+
seed?: number; // For reproducible responses
|
|
82
|
+
|
|
83
|
+
// Timing simulation
|
|
84
|
+
responseDelay?: number; // milliseconds (default: 0)
|
|
85
|
+
|
|
86
|
+
// Response customization
|
|
87
|
+
templates?: ResponseTemplate[];
|
|
88
|
+
personality?: PersonalityPreset; // "professional" | "friendly" | "technical" | "concise" | "verbose"
|
|
89
|
+
|
|
90
|
+
// Token simulation
|
|
91
|
+
tokenMultiplier?: number; // Adjust token counts (default: 1.0)
|
|
92
|
+
|
|
93
|
+
// Advanced options
|
|
94
|
+
debugMode?: boolean; // Log decision-making process
|
|
95
|
+
preferredTools?: string[]; // Prioritize these tool names
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Modes Explained
|
|
100
|
+
|
|
101
|
+
### `balanced` (Default)
|
|
102
|
+
Mix of text responses and tool calls. Base 30% probability of calling tools, adjusted based on context.
|
|
103
|
+
|
|
104
|
+
**Use when:** General development and testing
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
new FakeLLMAdapter({ mode: "balanced" })
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### `tool-heavy`
|
|
111
|
+
Strongly prefers tool calls. Base 70% probability of calling tools.
|
|
112
|
+
|
|
113
|
+
**Use when:** Testing tool calling flows, demos showcasing tools
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
new FakeLLMAdapter({ mode: "tool-heavy" })
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### `text-only`
|
|
120
|
+
Never calls tools. Always returns text responses.
|
|
121
|
+
|
|
122
|
+
**Use when:** Testing pure conversation flows, UI without tool interactions
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
new FakeLLMAdapter({ mode: "text-only" })
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### `random`
|
|
129
|
+
Completely unpredictable behavior.
|
|
130
|
+
|
|
131
|
+
**Use when:** Stress testing agent error handling
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
new FakeLLMAdapter({ mode: "random" })
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Context-Aware Tool Calling
|
|
138
|
+
|
|
139
|
+
The adapter intelligently decides when to call tools based on:
|
|
140
|
+
|
|
141
|
+
1. **Action verbs** in user message ("get", "find", "search", "calculate", etc.) → +20% probability
|
|
142
|
+
2. **Tool name matches** message content → +25% probability
|
|
143
|
+
3. **Temperature setting** < 0.5 → +10% probability (more deterministic)
|
|
144
|
+
4. **Preferred tools** configuration → Prioritized in selection
|
|
145
|
+
|
|
146
|
+
### Example: Intelligent Tool Selection
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
const adapter = new FakeLLMAdapter({
|
|
150
|
+
mode: "balanced",
|
|
151
|
+
preferredTools: ["search_database"]
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// "Find user John" → Likely calls tool (has "find" action verb)
|
|
155
|
+
// "What's the weather?" → May or may not call tool (depends on available tools)
|
|
156
|
+
// "Hello!" → Unlikely to call tool (no action verbs)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Custom Response Templates
|
|
160
|
+
|
|
161
|
+
Define domain-specific responses:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
const adapter = new FakeLLMAdapter({
|
|
165
|
+
templates: [
|
|
166
|
+
{
|
|
167
|
+
pattern: /order|purchase|buy/i,
|
|
168
|
+
responses: [
|
|
169
|
+
"I'll help you with that order.",
|
|
170
|
+
"Let me process your purchase.",
|
|
171
|
+
"I can assist with buying that."
|
|
172
|
+
]
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
pattern: /cancel|refund/i,
|
|
176
|
+
responses: [
|
|
177
|
+
"I'll help you with the cancellation.",
|
|
178
|
+
"Let me process that refund request."
|
|
179
|
+
],
|
|
180
|
+
toolTrigger: "process_refund" // Prefer this tool when pattern matches
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Reproducible Testing with Seeds
|
|
187
|
+
|
|
188
|
+
Use seeds for deterministic output in tests:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import { FakeLLMAdapter } from "@flink-app/fake-llm-adapter";
|
|
192
|
+
|
|
193
|
+
describe("Agent tests", () => {
|
|
194
|
+
it("should handle weather query consistently", async () => {
|
|
195
|
+
const adapter1 = new FakeLLMAdapter({ seed: 42 });
|
|
196
|
+
const adapter2 = new FakeLLMAdapter({ seed: 42 });
|
|
197
|
+
|
|
198
|
+
const agent1 = createAgent({ llm: adapter1, tools: weatherTools });
|
|
199
|
+
const agent2 = createAgent({ llm: adapter2, tools: weatherTools });
|
|
200
|
+
|
|
201
|
+
const result1 = await agent1.execute("Weather in Paris?");
|
|
202
|
+
const result2 = await agent2.execute("Weather in Paris?");
|
|
203
|
+
|
|
204
|
+
// Same seed = same behavior
|
|
205
|
+
expect(result1).toEqual(result2);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Simulating Network Delays
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
const adapter = new FakeLLMAdapter({
|
|
214
|
+
responseDelay: 500 // 500ms delay per response
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// Useful for:
|
|
218
|
+
// - Testing loading states in UI
|
|
219
|
+
// - Simulating production latency
|
|
220
|
+
// - Demo scenarios with realistic pacing
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Token Usage Simulation
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
const adapter = new FakeLLMAdapter({
|
|
227
|
+
tokenMultiplier: 2.0 // Double all token counts
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Useful for:
|
|
231
|
+
// - Testing token limit handling
|
|
232
|
+
// - Cost estimation in development
|
|
233
|
+
// - Performance testing with large contexts
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Personality Presets
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
// Professional (default)
|
|
240
|
+
new FakeLLMAdapter({ personality: "professional" })
|
|
241
|
+
// → "I can assist with that request."
|
|
242
|
+
|
|
243
|
+
// Friendly
|
|
244
|
+
new FakeLLMAdapter({ personality: "friendly" })
|
|
245
|
+
// → "Sure thing! Let me help you out!"
|
|
246
|
+
|
|
247
|
+
// Technical
|
|
248
|
+
new FakeLLMAdapter({ personality: "technical" })
|
|
249
|
+
// → "Processing query. Executing tool call."
|
|
250
|
+
|
|
251
|
+
// Concise
|
|
252
|
+
new FakeLLMAdapter({ personality: "concise" })
|
|
253
|
+
// → "Processing."
|
|
254
|
+
|
|
255
|
+
// Verbose
|
|
256
|
+
new FakeLLMAdapter({ personality: "verbose" })
|
|
257
|
+
// → "I understand your request and I'll be happy to assist you with that. Let me process..."
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Debug Mode
|
|
261
|
+
|
|
262
|
+
Enable logging to understand decision-making:
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
const adapter = new FakeLLMAdapter({
|
|
266
|
+
debugMode: true
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// Logs:
|
|
270
|
+
// [FakeLLMAdapter] Processing message: What's the weather?
|
|
271
|
+
// [FakeLLMAdapter] Generated tool calls: [{ name: "get_weather", ... }]
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Tool Input Generation
|
|
275
|
+
|
|
276
|
+
The adapter generates realistic tool inputs by:
|
|
277
|
+
|
|
278
|
+
1. **Extracting from message**: Searches for cities, numbers, dates in user message
|
|
279
|
+
2. **Schema-based defaults**: Generates appropriate values based on property types
|
|
280
|
+
3. **Smart field matching**: Recognizes common field names (email, city, name, date)
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
// Tool schema:
|
|
284
|
+
{
|
|
285
|
+
name: "create_user",
|
|
286
|
+
input_schema: {
|
|
287
|
+
properties: {
|
|
288
|
+
email: { type: "string" },
|
|
289
|
+
city: { type: "string" },
|
|
290
|
+
age: { type: "number" }
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Message: "Create user in Stockholm"
|
|
296
|
+
// Generated input:
|
|
297
|
+
{
|
|
298
|
+
email: "user@example.com", // Smart default for email field
|
|
299
|
+
city: "Stockholm", // Extracted from message
|
|
300
|
+
age: 42 // Random number
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Comparison: fake-llm-adapter vs mockLLMAdapter
|
|
305
|
+
|
|
306
|
+
| Feature | `FakeLLMAdapter` | `mockLLMAdapter` (test-utils) |
|
|
307
|
+
|---------|------------------|-------------------------------|
|
|
308
|
+
| **Purpose** | Development & demos | Unit testing only |
|
|
309
|
+
| **Tool calling** | Intelligent, context-aware | Always returns predefined responses |
|
|
310
|
+
| **Responses** | Dynamic, template-based | Static, hard-coded |
|
|
311
|
+
| **Configuration** | Highly configurable modes | Minimal config |
|
|
312
|
+
| **Reproducibility** | Seeded randomness | Fully deterministic |
|
|
313
|
+
| **Use case** | Running app without APIs | Mocking in tests |
|
|
314
|
+
|
|
315
|
+
**Rule of thumb:**
|
|
316
|
+
- Use `FakeLLMAdapter` for running your app, demos, and development
|
|
317
|
+
- Use `mockLLMAdapter` for unit tests where you need exact, predictable outputs
|
|
318
|
+
|
|
319
|
+
## Use Cases
|
|
320
|
+
|
|
321
|
+
### 1. Development Without API Keys
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
// Develop AI features without spending money or setting up API keys
|
|
325
|
+
const app = new FlinkApp({
|
|
326
|
+
ai: {
|
|
327
|
+
llms: {
|
|
328
|
+
default: new FakeLLMAdapter()
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### 2. Demos and Presentations
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
// Reliable demos that don't depend on external APIs
|
|
338
|
+
const demoAdapter = new FakeLLMAdapter({
|
|
339
|
+
mode: "tool-heavy",
|
|
340
|
+
responseDelay: 800, // Realistic pacing
|
|
341
|
+
seed: 12345 // Same demo every time
|
|
342
|
+
});
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### 3. Testing Tool Calling Logic
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
// Test your agent's tool handling without real LLM
|
|
349
|
+
const testAdapter = new FakeLLMAdapter({
|
|
350
|
+
toolCallProbability: 1.0, // Always call tools
|
|
351
|
+
maxToolCallsPerTurn: 5
|
|
352
|
+
});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### 4. UI Development
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
// Test loading states and UI behavior
|
|
359
|
+
const uiTestAdapter = new FakeLLMAdapter({
|
|
360
|
+
responseDelay: 1500,
|
|
361
|
+
personality: "verbose" // Longer responses to test text wrapping
|
|
362
|
+
});
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### 5. Integration Tests
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
// Consistent behavior across test runs
|
|
369
|
+
describe("Agent integration", () => {
|
|
370
|
+
const adapter = new FakeLLMAdapter({ seed: 999 });
|
|
371
|
+
|
|
372
|
+
it("should handle multi-turn conversation", async () => {
|
|
373
|
+
// Test logic here - same results every run
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Advanced Example: Custom E-commerce Agent
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
const ecommerceAdapter = new FakeLLMAdapter({
|
|
382
|
+
mode: "tool-heavy",
|
|
383
|
+
preferredTools: ["search_products", "get_order_status"],
|
|
384
|
+
templates: [
|
|
385
|
+
{
|
|
386
|
+
pattern: /track|status|where.*order/i,
|
|
387
|
+
responses: ["Let me check your order status."],
|
|
388
|
+
toolTrigger: "get_order_status"
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
pattern: /find|search|looking for/i,
|
|
392
|
+
responses: ["I'll search our catalog for you."],
|
|
393
|
+
toolTrigger: "search_products"
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
pattern: /return|refund/i,
|
|
397
|
+
responses: ["I'll help you process that return."],
|
|
398
|
+
toolTrigger: "process_return"
|
|
399
|
+
}
|
|
400
|
+
],
|
|
401
|
+
personality: "friendly",
|
|
402
|
+
debugMode: true
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
const agent = createAgent({
|
|
406
|
+
llm: ecommerceAdapter,
|
|
407
|
+
instructions: "You are a helpful e-commerce assistant.",
|
|
408
|
+
tools: [searchProducts, getOrderStatus, processReturn]
|
|
409
|
+
});
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## Limitations (Phase 1)
|
|
413
|
+
|
|
414
|
+
- **No streaming support**: `stream()` method throws an error. Use `execute()` instead.
|
|
415
|
+
- **Simple tool input generation**: Uses heuristics, may not handle complex nested schemas
|
|
416
|
+
- **Template matching**: Basic regex patterns, not semantic understanding
|
|
417
|
+
|
|
418
|
+
Future phases may add streaming and more sophisticated input generation.
|
|
419
|
+
|
|
420
|
+
## TypeScript Types
|
|
421
|
+
|
|
422
|
+
All types are fully exported:
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
import {
|
|
426
|
+
FakeLLMAdapter,
|
|
427
|
+
FakeLLMAdapterConfig,
|
|
428
|
+
AdapterMode,
|
|
429
|
+
PersonalityPreset,
|
|
430
|
+
ResponseTemplate
|
|
431
|
+
} from "@flink-app/fake-llm-adapter";
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
## License
|
|
435
|
+
|
|
436
|
+
MIT
|
|
437
|
+
|
|
438
|
+
## Contributing
|
|
439
|
+
|
|
440
|
+
Issues and PRs welcome at https://github.com/FrostDigital/flink-framework
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { LLMAdapter, LLMMessage, LLMStreamChunk } from "@flink-app/flink/ai";
|
|
2
|
+
import { FakeLLMAdapterConfig } from "./types";
|
|
3
|
+
export declare class FakeLLMAdapter implements LLMAdapter {
|
|
4
|
+
private config;
|
|
5
|
+
private random;
|
|
6
|
+
private responseGenerator;
|
|
7
|
+
private toolCallDecider;
|
|
8
|
+
private tokenEstimator;
|
|
9
|
+
constructor(config?: FakeLLMAdapterConfig);
|
|
10
|
+
stream(params: {
|
|
11
|
+
instructions: string;
|
|
12
|
+
messages: LLMMessage[];
|
|
13
|
+
tools: any[];
|
|
14
|
+
maxTokens: number;
|
|
15
|
+
temperature: number;
|
|
16
|
+
}): AsyncGenerator<LLMStreamChunk>;
|
|
17
|
+
private getLastUserMessage;
|
|
18
|
+
private truncateToMaxTokens;
|
|
19
|
+
private sleep;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=FakeLLMAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FakeLLMAdapter.d.ts","sourceRoot":"","sources":["../src/FakeLLMAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAM/C,qBAAa,cAAe,YAAW,UAAU;IAC/C,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,cAAc,CAAiB;gBAE3B,MAAM,GAAE,oBAAyB;IAsBtC,MAAM,CAAC,MAAM,EAAE;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,KAAK,EAAE,GAAG,EAAE,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;KACrB,GAAG,cAAc,CAAC,cAAc,CAAC;IAiHlC,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FakeLLMAdapter = void 0;
|
|
4
|
+
const ResponseGenerator_1 = require("./ResponseGenerator");
|
|
5
|
+
const ToolCallDecider_1 = require("./ToolCallDecider");
|
|
6
|
+
const TokenEstimator_1 = require("./TokenEstimator");
|
|
7
|
+
const SeededRandom_1 = require("./SeededRandom");
|
|
8
|
+
class FakeLLMAdapter {
|
|
9
|
+
constructor(config = {}) {
|
|
10
|
+
this.config = {
|
|
11
|
+
mode: "balanced",
|
|
12
|
+
toolCallProbability: 0.3,
|
|
13
|
+
maxToolCallsPerTurn: 3,
|
|
14
|
+
responseDelay: 0,
|
|
15
|
+
personality: "professional",
|
|
16
|
+
tokenMultiplier: 1.0,
|
|
17
|
+
debugMode: false,
|
|
18
|
+
...config
|
|
19
|
+
};
|
|
20
|
+
this.random = new SeededRandom_1.SeededRandom(config.seed);
|
|
21
|
+
this.responseGenerator = new ResponseGenerator_1.ResponseGenerator(config.templates, this.config.personality, this.random);
|
|
22
|
+
this.toolCallDecider = new ToolCallDecider_1.ToolCallDecider(this.random);
|
|
23
|
+
this.tokenEstimator = new TokenEstimator_1.TokenEstimator(this.config.tokenMultiplier);
|
|
24
|
+
}
|
|
25
|
+
async *stream(params) {
|
|
26
|
+
// Simulate delay if configured
|
|
27
|
+
if (this.config.responseDelay) {
|
|
28
|
+
await this.sleep(this.config.responseDelay);
|
|
29
|
+
}
|
|
30
|
+
// Get last user message
|
|
31
|
+
const lastMessage = this.getLastUserMessage(params.messages);
|
|
32
|
+
if (this.config.debugMode) {
|
|
33
|
+
console.log("[FakeLLMAdapter] Processing message:", lastMessage);
|
|
34
|
+
}
|
|
35
|
+
// Decide whether to call tools
|
|
36
|
+
const shouldCall = this.toolCallDecider.shouldCallTool(lastMessage, params.tools, this.config, params.temperature);
|
|
37
|
+
let textContent;
|
|
38
|
+
let toolCalls = [];
|
|
39
|
+
let stopReason;
|
|
40
|
+
if (shouldCall && params.tools.length > 0) {
|
|
41
|
+
// Generate tool calls
|
|
42
|
+
toolCalls = this.toolCallDecider.generateToolCalls(lastMessage, params.tools, this.config);
|
|
43
|
+
// Optional thinking text before tool call (50% chance)
|
|
44
|
+
if (this.random.random() < 0.5) {
|
|
45
|
+
textContent = this.responseGenerator.generateThinkingText(lastMessage, toolCalls);
|
|
46
|
+
}
|
|
47
|
+
stopReason = "tool_use";
|
|
48
|
+
if (this.config.debugMode) {
|
|
49
|
+
console.log("[FakeLLMAdapter] Generated tool calls:", toolCalls);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// Generate text response
|
|
54
|
+
textContent = this.responseGenerator.generateResponse(lastMessage, params.instructions, params.temperature);
|
|
55
|
+
// Check if response would exceed maxTokens
|
|
56
|
+
const estimatedTokens = this.tokenEstimator.estimateTextTokens(textContent);
|
|
57
|
+
if (estimatedTokens > params.maxTokens) {
|
|
58
|
+
textContent = this.truncateToMaxTokens(textContent, params.maxTokens);
|
|
59
|
+
stopReason = "max_tokens";
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
stopReason = "end_turn";
|
|
63
|
+
}
|
|
64
|
+
if (this.config.debugMode) {
|
|
65
|
+
console.log("[FakeLLMAdapter] Generated text:", textContent);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Calculate token usage
|
|
69
|
+
const inputTokens = this.tokenEstimator.calculateInputTokens(params.instructions, params.messages);
|
|
70
|
+
// Stream text content character by character (or chunk by chunk)
|
|
71
|
+
if (textContent) {
|
|
72
|
+
const text = textContent;
|
|
73
|
+
const chunkSize = Math.max(1, Math.floor(text.length / 10)); // ~10 chunks
|
|
74
|
+
for (let i = 0; i < text.length; i += chunkSize) {
|
|
75
|
+
const delta = text.slice(i, i + chunkSize);
|
|
76
|
+
yield { type: "text", delta };
|
|
77
|
+
// Simulate network latency (configurable)
|
|
78
|
+
if (this.config.simulateStreamDelay) {
|
|
79
|
+
await this.sleep(50);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Emit tool calls (if any)
|
|
84
|
+
for (const toolCall of toolCalls) {
|
|
85
|
+
yield { type: "tool_call", toolCall };
|
|
86
|
+
}
|
|
87
|
+
// Calculate output tokens
|
|
88
|
+
const outputTokens = this.tokenEstimator.estimateTextTokens(textContent || "") +
|
|
89
|
+
toolCalls.length * 50; // Rough estimate for tool calls
|
|
90
|
+
// Emit usage
|
|
91
|
+
yield {
|
|
92
|
+
type: "usage",
|
|
93
|
+
usage: {
|
|
94
|
+
inputTokens,
|
|
95
|
+
outputTokens
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
// Emit done
|
|
99
|
+
yield {
|
|
100
|
+
type: "done",
|
|
101
|
+
stopReason: stopReason,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
getLastUserMessage(messages) {
|
|
105
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
106
|
+
if (messages[i].role === "user") {
|
|
107
|
+
const content = messages[i].content;
|
|
108
|
+
if (typeof content === "string") {
|
|
109
|
+
return content;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Extract text from content blocks
|
|
113
|
+
const textBlocks = content.filter(block => block.type === "text");
|
|
114
|
+
return textBlocks.map(block => block.text).join(" ");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return "";
|
|
119
|
+
}
|
|
120
|
+
truncateToMaxTokens(text, maxTokens) {
|
|
121
|
+
// Rough approximation: 1.3 words per token
|
|
122
|
+
const maxWords = Math.floor(maxTokens / 1.3);
|
|
123
|
+
const words = text.split(/\s+/);
|
|
124
|
+
if (words.length <= maxWords) {
|
|
125
|
+
return text;
|
|
126
|
+
}
|
|
127
|
+
return words.slice(0, maxWords).join(" ") + "...";
|
|
128
|
+
}
|
|
129
|
+
sleep(ms) {
|
|
130
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
exports.FakeLLMAdapter = FakeLLMAdapter;
|
|
134
|
+
//# sourceMappingURL=FakeLLMAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FakeLLMAdapter.js","sourceRoot":"","sources":["../src/FakeLLMAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ResponseTemplate, PersonalityPreset } from "./types";
|
|
2
|
+
import { SeededRandom } from "./SeededRandom";
|
|
3
|
+
export declare class ResponseGenerator {
|
|
4
|
+
private templates;
|
|
5
|
+
private personality;
|
|
6
|
+
private random;
|
|
7
|
+
constructor(templates: ResponseTemplate[] | undefined, personality: PersonalityPreset, random: SeededRandom);
|
|
8
|
+
generateResponse(userMessage: string, systemInstructions: string, temperature: number): string;
|
|
9
|
+
generateThinkingText(userMessage: string, toolCalls: any[]): string;
|
|
10
|
+
private findMatchingTemplate;
|
|
11
|
+
private expandResponse;
|
|
12
|
+
private getDefaultTemplates;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=ResponseGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponseGenerator.d.ts","sourceRoot":"","sources":["../src/ResponseGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,MAAM,CAAe;gBAG3B,SAAS,EAAE,gBAAgB,EAAE,GAAG,SAAS,EACzC,WAAW,EAAE,iBAAiB,EAC9B,MAAM,EAAE,YAAY;IAQtB,gBAAgB,CACd,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,MAAM,EAC1B,WAAW,EAAE,MAAM,GAClB,MAAM;IAcT,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,MAAM;IAWnE,OAAO,CAAC,oBAAoB;IAW5B,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,mBAAmB;CA8C5B"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ResponseGenerator = void 0;
|
|
4
|
+
class ResponseGenerator {
|
|
5
|
+
constructor(templates, personality, random) {
|
|
6
|
+
this.templates = templates || this.getDefaultTemplates();
|
|
7
|
+
this.personality = personality;
|
|
8
|
+
this.random = random;
|
|
9
|
+
}
|
|
10
|
+
// Generate main response text
|
|
11
|
+
generateResponse(userMessage, systemInstructions, temperature) {
|
|
12
|
+
// Find matching template
|
|
13
|
+
const template = this.findMatchingTemplate(userMessage);
|
|
14
|
+
const baseResponse = this.random.choice(template.responses);
|
|
15
|
+
// Adjust length based on temperature
|
|
16
|
+
const shouldBeVerbose = temperature > 0.7 || this.personality === "verbose";
|
|
17
|
+
return shouldBeVerbose
|
|
18
|
+
? this.expandResponse(baseResponse, userMessage)
|
|
19
|
+
: baseResponse;
|
|
20
|
+
}
|
|
21
|
+
// Generate thinking text before tool call
|
|
22
|
+
generateThinkingText(userMessage, toolCalls) {
|
|
23
|
+
const thinkingPhrases = [
|
|
24
|
+
"Let me help you with that.",
|
|
25
|
+
"I'll check that for you.",
|
|
26
|
+
"I understand. Let me process that.",
|
|
27
|
+
"Sure, I can assist with that request.",
|
|
28
|
+
];
|
|
29
|
+
return this.random.choice(thinkingPhrases);
|
|
30
|
+
}
|
|
31
|
+
findMatchingTemplate(message) {
|
|
32
|
+
for (const template of this.templates) {
|
|
33
|
+
if (template.pattern.test(message)) {
|
|
34
|
+
return template;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Fallback to generic template
|
|
38
|
+
return this.templates[this.templates.length - 1];
|
|
39
|
+
}
|
|
40
|
+
expandResponse(base, userMessage) {
|
|
41
|
+
const expansions = [
|
|
42
|
+
` Based on your request, I'll provide you with the information you need.`,
|
|
43
|
+
` I have processed your query and here's what I found.`,
|
|
44
|
+
` I've analyzed your input and can provide assistance.`,
|
|
45
|
+
];
|
|
46
|
+
return base + this.random.choice(expansions);
|
|
47
|
+
}
|
|
48
|
+
getDefaultTemplates() {
|
|
49
|
+
return [
|
|
50
|
+
{
|
|
51
|
+
pattern: /weather|temperature|forecast|climate/i,
|
|
52
|
+
responses: [
|
|
53
|
+
"Let me check the weather for you.",
|
|
54
|
+
"I'll look up the current weather conditions.",
|
|
55
|
+
"I can help you with weather information.",
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
pattern: /calculate|compute|sum|total|math/i,
|
|
60
|
+
responses: [
|
|
61
|
+
"I'll calculate that for you.",
|
|
62
|
+
"Let me run those numbers.",
|
|
63
|
+
"I can help with that calculation.",
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
pattern: /search|find|look|locate/i,
|
|
68
|
+
responses: [
|
|
69
|
+
"I'll search for that information.",
|
|
70
|
+
"Let me find that for you.",
|
|
71
|
+
"I can help you locate that.",
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
pattern: /create|make|generate|build/i,
|
|
76
|
+
responses: [
|
|
77
|
+
"I'll create that for you.",
|
|
78
|
+
"Let me generate that.",
|
|
79
|
+
"I can help build that.",
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
// Generic fallback (must be last)
|
|
83
|
+
{
|
|
84
|
+
pattern: /.*/,
|
|
85
|
+
responses: [
|
|
86
|
+
"I understand. Let me help you with that.",
|
|
87
|
+
"I can assist with that request.",
|
|
88
|
+
"I'll process that information for you.",
|
|
89
|
+
"Let me handle that for you.",
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.ResponseGenerator = ResponseGenerator;
|
|
96
|
+
//# sourceMappingURL=ResponseGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponseGenerator.js","sourceRoot":"","sources":["../src/ResponseGenerator.ts"],"names":[],"mappings":";;;AAGA,MAAa,iBAAiB;IAK5B,YACE,SAAyC,EACzC,WAA8B,EAC9B,MAAoB;QAEpB,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzD,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,8BAA8B;IAC9B,gBAAgB,CACd,WAAmB,EACnB,kBAA0B,EAC1B,WAAmB;QAEnB,yBAAyB;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC;QACxD,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAE5D,qCAAqC;QACrC,MAAM,eAAe,GAAG,WAAW,GAAG,GAAG,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC;QAE5E,OAAO,eAAe;YACpB,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,YAAY,EAAE,WAAW,CAAC;YAChD,CAAC,CAAC,YAAY,CAAC;IACnB,CAAC;IAED,0CAA0C;IAC1C,oBAAoB,CAAC,WAAmB,EAAE,SAAgB;QACxD,MAAM,eAAe,GAAG;YACtB,4BAA4B;YAC5B,0BAA0B;YAC1B,oCAAoC;YACpC,uCAAuC;SACxC,CAAC;QAEF,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IAC7C,CAAC;IAEO,oBAAoB,CAAC,OAAe;QAC1C,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBACnC,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QAED,+BAA+B;QAC/B,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACnD,CAAC;IAEO,cAAc,CAAC,IAAY,EAAE,WAAmB;QACtD,MAAM,UAAU,GAAG;YACjB,yEAAyE;YACzE,uDAAuD;YACvD,uDAAuD;SACxD,CAAC;QAEF,OAAO,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IAEO,mBAAmB;QACzB,OAAO;YACL;gBACE,OAAO,EAAE,uCAAuC;gBAChD,SAAS,EAAE;oBACT,mCAAmC;oBACnC,8CAA8C;oBAC9C,0CAA0C;iBAC3C;aACF;YACD;gBACE,OAAO,EAAE,mCAAmC;gBAC5C,SAAS,EAAE;oBACT,8BAA8B;oBAC9B,2BAA2B;oBAC3B,mCAAmC;iBACpC;aACF;YACD;gBACE,OAAO,EAAE,0BAA0B;gBACnC,SAAS,EAAE;oBACT,mCAAmC;oBACnC,2BAA2B;oBAC3B,6BAA6B;iBAC9B;aACF;YACD;gBACE,OAAO,EAAE,6BAA6B;gBACtC,SAAS,EAAE;oBACT,2BAA2B;oBAC3B,uBAAuB;oBACvB,wBAAwB;iBACzB;aACF;YACD,kCAAkC;YAClC;gBACE,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE;oBACT,0CAA0C;oBAC1C,iCAAiC;oBACjC,wCAAwC;oBACxC,6BAA6B;iBAC9B;aACF;SACF,CAAC;IACJ,CAAC;CACF;AAhHD,8CAgHC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SeededRandom.d.ts","sourceRoot":"","sources":["../src/SeededRandom.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAY;IACvB,OAAO,CAAC,IAAI,CAAS;gBAET,IAAI,CAAC,EAAE,MAAM;IAKzB,MAAM,IAAI,MAAM;IAKhB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC;IAIxB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAIzC,OAAO,IAAI,OAAO;CAGnB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SeededRandom = void 0;
|
|
4
|
+
class SeededRandom {
|
|
5
|
+
constructor(seed) {
|
|
6
|
+
this.seed = seed ?? Date.now();
|
|
7
|
+
}
|
|
8
|
+
// Linear congruential generator for reproducibility
|
|
9
|
+
random() {
|
|
10
|
+
this.seed = (this.seed * 9301 + 49297) % 233280;
|
|
11
|
+
return this.seed / 233280;
|
|
12
|
+
}
|
|
13
|
+
choice(array) {
|
|
14
|
+
return array[Math.floor(this.random() * array.length)];
|
|
15
|
+
}
|
|
16
|
+
integer(min, max) {
|
|
17
|
+
return Math.floor(this.random() * (max - min + 1)) + min;
|
|
18
|
+
}
|
|
19
|
+
boolean() {
|
|
20
|
+
return this.random() < 0.5;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.SeededRandom = SeededRandom;
|
|
24
|
+
//# sourceMappingURL=SeededRandom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SeededRandom.js","sourceRoot":"","sources":["../src/SeededRandom.ts"],"names":[],"mappings":";;;AAAA,MAAa,YAAY;IAGvB,YAAY,IAAa;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IACjC,CAAC;IAED,oDAAoD;IACpD,MAAM;QACJ,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC,GAAG,MAAM,CAAC;QAChD,OAAO,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC;IAC5B,CAAC;IAED,MAAM,CAAI,KAAU;QAClB,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,CAAC,GAAW,EAAE,GAAW;QAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IAC3D,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC;IAC7B,CAAC;CACF;AAxBD,oCAwBC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { LLMMessage } from "@flink-app/flink/ai";
|
|
2
|
+
export declare class TokenEstimator {
|
|
3
|
+
private tokenMultiplier;
|
|
4
|
+
constructor(tokenMultiplier?: number);
|
|
5
|
+
estimateTextTokens(text: string): number;
|
|
6
|
+
calculateInputTokens(instructions: string, messages: LLMMessage[]): number;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=TokenEstimator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TokenEstimator.d.ts","sourceRoot":"","sources":["../src/TokenEstimator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,qBAAa,cAAc;IACzB,OAAO,CAAC,eAAe,CAAS;gBAEpB,eAAe,GAAE,MAAY;IAKzC,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAMxC,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM;CAa3E"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TokenEstimator = void 0;
|
|
4
|
+
class TokenEstimator {
|
|
5
|
+
constructor(tokenMultiplier = 1.0) {
|
|
6
|
+
this.tokenMultiplier = tokenMultiplier;
|
|
7
|
+
}
|
|
8
|
+
// Estimate tokens from text using word count * 1.3 ratio
|
|
9
|
+
estimateTextTokens(text) {
|
|
10
|
+
const words = text.split(/\s+/).filter(w => w.length > 0).length;
|
|
11
|
+
return Math.ceil(words * 1.3 * this.tokenMultiplier);
|
|
12
|
+
}
|
|
13
|
+
// Calculate input tokens from instructions and messages
|
|
14
|
+
calculateInputTokens(instructions, messages) {
|
|
15
|
+
let tokens = this.estimateTextTokens(instructions);
|
|
16
|
+
for (const message of messages) {
|
|
17
|
+
if (typeof message.content === "string") {
|
|
18
|
+
tokens += this.estimateTextTokens(message.content);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
tokens += this.estimateTextTokens(JSON.stringify(message.content));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return Math.ceil(tokens * this.tokenMultiplier);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.TokenEstimator = TokenEstimator;
|
|
28
|
+
//# sourceMappingURL=TokenEstimator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TokenEstimator.js","sourceRoot":"","sources":["../src/TokenEstimator.ts"],"names":[],"mappings":";;;AAEA,MAAa,cAAc;IAGzB,YAAY,kBAA0B,GAAG;QACvC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;IACzC,CAAC;IAED,yDAAyD;IACzD,kBAAkB,CAAC,IAAY;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;QACjE,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC;IACvD,CAAC;IAED,wDAAwD;IACxD,oBAAoB,CAAC,YAAoB,EAAE,QAAsB;QAC/D,IAAI,MAAM,GAAG,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;QAEnD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACxC,MAAM,IAAI,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACrD,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC;IAClD,CAAC;CACF;AA3BD,wCA2BC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FakeLLMAdapterConfig } from "./types";
|
|
2
|
+
import { SeededRandom } from "./SeededRandom";
|
|
3
|
+
export declare class ToolCallDecider {
|
|
4
|
+
private random;
|
|
5
|
+
constructor(random: SeededRandom);
|
|
6
|
+
shouldCallTool(message: string, tools: any[], config: FakeLLMAdapterConfig, temperature: number): boolean;
|
|
7
|
+
generateToolCalls(message: string, tools: any[], config: FakeLLMAdapterConfig): Array<{
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
input: any;
|
|
11
|
+
}>;
|
|
12
|
+
private getBaseProbability;
|
|
13
|
+
private hasActionVerbs;
|
|
14
|
+
private hasMatchingTools;
|
|
15
|
+
private selectTools;
|
|
16
|
+
private scoreToolMatch;
|
|
17
|
+
private generateToolInput;
|
|
18
|
+
private generateValueForProperty;
|
|
19
|
+
private extractFromMessage;
|
|
20
|
+
private generateStringValue;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=ToolCallDecider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolCallDecider.d.ts","sourceRoot":"","sources":["../src/ToolCallDecider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,EAAE,YAAY;IAKhC,cAAc,CACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,GAAG,EAAE,EACZ,MAAM,EAAE,oBAAoB,EAC5B,WAAW,EAAE,MAAM,GAClB,OAAO;IAmCV,iBAAiB,CACf,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,GAAG,EAAE,EACZ,MAAM,EAAE,oBAAoB,GAC3B,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC;IAclD,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,WAAW;IAmBnB,OAAO,CAAC,cAAc;IAqBtB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,wBAAwB;IAyBhC,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,mBAAmB;CAqB5B"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ToolCallDecider = void 0;
|
|
4
|
+
class ToolCallDecider {
|
|
5
|
+
constructor(random) {
|
|
6
|
+
this.random = random;
|
|
7
|
+
}
|
|
8
|
+
// Decide whether to call tools based on context
|
|
9
|
+
shouldCallTool(message, tools, config, temperature) {
|
|
10
|
+
if (tools.length === 0)
|
|
11
|
+
return false;
|
|
12
|
+
// text-only mode never calls tools
|
|
13
|
+
if (config.mode === "text-only") {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
// Mode-based baseline probability
|
|
17
|
+
let probability = this.getBaseProbability(config.mode || "balanced");
|
|
18
|
+
if (config.toolCallProbability !== undefined) {
|
|
19
|
+
probability = config.toolCallProbability;
|
|
20
|
+
}
|
|
21
|
+
// Context-based adjustments
|
|
22
|
+
if (this.hasActionVerbs(message)) {
|
|
23
|
+
probability += 0.2;
|
|
24
|
+
}
|
|
25
|
+
if (this.hasMatchingTools(message, tools)) {
|
|
26
|
+
probability += 0.25;
|
|
27
|
+
}
|
|
28
|
+
if (temperature < 0.5) {
|
|
29
|
+
probability += 0.1; // More deterministic = more tool usage
|
|
30
|
+
}
|
|
31
|
+
// Cap at 95%
|
|
32
|
+
probability = Math.min(probability, 0.95);
|
|
33
|
+
return this.random.random() < probability;
|
|
34
|
+
}
|
|
35
|
+
// Generate tool calls with realistic inputs
|
|
36
|
+
generateToolCalls(message, tools, config) {
|
|
37
|
+
const maxCalls = config.maxToolCallsPerTurn || 3;
|
|
38
|
+
const numCalls = this.random.integer(1, Math.min(maxCalls, tools.length));
|
|
39
|
+
// Select tools (prefer matching tools, then preferred, then random)
|
|
40
|
+
const selectedTools = this.selectTools(message, tools, config, numCalls);
|
|
41
|
+
return selectedTools.map((tool, index) => ({
|
|
42
|
+
id: `call_${Date.now()}_${index}`,
|
|
43
|
+
name: tool.name,
|
|
44
|
+
input: this.generateToolInput(tool, message)
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
getBaseProbability(mode) {
|
|
48
|
+
switch (mode) {
|
|
49
|
+
case "tool-heavy": return 0.7;
|
|
50
|
+
case "text-only": return 0.0;
|
|
51
|
+
case "random": return this.random.random();
|
|
52
|
+
case "balanced":
|
|
53
|
+
default: return 0.3;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
hasActionVerbs(message) {
|
|
57
|
+
return /\b(get|find|search|check|create|update|delete|calculate|fetch|retrieve)\b/i.test(message);
|
|
58
|
+
}
|
|
59
|
+
hasMatchingTools(message, tools) {
|
|
60
|
+
const messageLower = message.toLowerCase();
|
|
61
|
+
return tools.some(tool => tool?.name && messageLower.includes(tool.name.replace(/_/g, ' ').toLowerCase()));
|
|
62
|
+
}
|
|
63
|
+
selectTools(message, tools, config, count) {
|
|
64
|
+
const messageLower = message.toLowerCase();
|
|
65
|
+
// Score each tool
|
|
66
|
+
const scored = tools.map(tool => ({
|
|
67
|
+
tool,
|
|
68
|
+
score: this.scoreToolMatch(tool, messageLower, config.preferredTools)
|
|
69
|
+
}));
|
|
70
|
+
// Sort by score and take top N
|
|
71
|
+
scored.sort((a, b) => b.score - a.score);
|
|
72
|
+
return scored.slice(0, count).map(s => s.tool);
|
|
73
|
+
}
|
|
74
|
+
scoreToolMatch(tool, message, preferredTools) {
|
|
75
|
+
let score = this.random.random(); // Base randomness
|
|
76
|
+
// Safety check for tool.name
|
|
77
|
+
if (!tool?.name) {
|
|
78
|
+
return score;
|
|
79
|
+
}
|
|
80
|
+
// Boost if tool name matches message
|
|
81
|
+
if (message.includes(tool.name.replace(/_/g, ' ').toLowerCase())) {
|
|
82
|
+
score += 2;
|
|
83
|
+
}
|
|
84
|
+
// Boost if preferred
|
|
85
|
+
if (preferredTools?.includes(tool.name)) {
|
|
86
|
+
score += 1.5;
|
|
87
|
+
}
|
|
88
|
+
return score;
|
|
89
|
+
}
|
|
90
|
+
generateToolInput(tool, message) {
|
|
91
|
+
// Try to extract schema from tool definition
|
|
92
|
+
const schema = tool.inputSchema || {};
|
|
93
|
+
const properties = schema.properties || {};
|
|
94
|
+
const input = {};
|
|
95
|
+
// Generate value for each required property
|
|
96
|
+
for (const [key, propSchema] of Object.entries(properties)) {
|
|
97
|
+
input[key] = this.generateValueForProperty(key, propSchema, message);
|
|
98
|
+
}
|
|
99
|
+
return input;
|
|
100
|
+
}
|
|
101
|
+
generateValueForProperty(name, schema, message) {
|
|
102
|
+
const type = schema.type;
|
|
103
|
+
// Try to extract from message first
|
|
104
|
+
const extracted = this.extractFromMessage(name, type, message);
|
|
105
|
+
if (extracted !== null)
|
|
106
|
+
return extracted;
|
|
107
|
+
// Generate plausible default
|
|
108
|
+
switch (type) {
|
|
109
|
+
case "string":
|
|
110
|
+
return this.generateStringValue(name);
|
|
111
|
+
case "number":
|
|
112
|
+
case "integer":
|
|
113
|
+
return this.random.integer(1, 100);
|
|
114
|
+
case "boolean":
|
|
115
|
+
return this.random.boolean();
|
|
116
|
+
case "array":
|
|
117
|
+
return [this.generateValueForProperty(name, schema.items || { type: "string" }, message)];
|
|
118
|
+
case "object":
|
|
119
|
+
return {};
|
|
120
|
+
default:
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
extractFromMessage(name, type, message) {
|
|
125
|
+
// Simple extraction patterns
|
|
126
|
+
if (type === "number" || type === "integer") {
|
|
127
|
+
const match = message.match(/\b(\d+)\b/);
|
|
128
|
+
if (match)
|
|
129
|
+
return parseInt(match[1], 10);
|
|
130
|
+
}
|
|
131
|
+
if (name.toLowerCase().includes("city") || name.toLowerCase().includes("location")) {
|
|
132
|
+
const cities = ["Stockholm", "London", "New York", "Paris", "Tokyo"];
|
|
133
|
+
for (const city of cities) {
|
|
134
|
+
if (message.toLowerCase().includes(city.toLowerCase())) {
|
|
135
|
+
return city;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
generateStringValue(fieldName) {
|
|
142
|
+
const lower = fieldName.toLowerCase();
|
|
143
|
+
if (lower.includes("city") || lower.includes("location")) {
|
|
144
|
+
return this.random.choice(["Stockholm", "London", "New York", "Paris", "Tokyo"]);
|
|
145
|
+
}
|
|
146
|
+
if (lower.includes("email")) {
|
|
147
|
+
return "user@example.com";
|
|
148
|
+
}
|
|
149
|
+
if (lower.includes("name")) {
|
|
150
|
+
return this.random.choice(["Alice", "Bob", "Charlie", "Diana"]);
|
|
151
|
+
}
|
|
152
|
+
if (lower.includes("date")) {
|
|
153
|
+
return new Date().toISOString().split('T')[0];
|
|
154
|
+
}
|
|
155
|
+
return `value_${this.random.integer(1, 100)}`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
exports.ToolCallDecider = ToolCallDecider;
|
|
159
|
+
//# sourceMappingURL=ToolCallDecider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolCallDecider.js","sourceRoot":"","sources":["../src/ToolCallDecider.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":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./FakeLLMAdapter"), exports);
|
|
18
|
+
__exportStar(require("./types"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC;AACjC,0CAAwB"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface ResponseTemplate {
|
|
2
|
+
pattern: RegExp;
|
|
3
|
+
responses: string[];
|
|
4
|
+
toolTrigger?: string;
|
|
5
|
+
}
|
|
6
|
+
export type PersonalityPreset = "professional" | "friendly" | "technical" | "concise" | "verbose";
|
|
7
|
+
export type AdapterMode = "balanced" | "tool-heavy" | "text-only" | "random";
|
|
8
|
+
export interface FakeLLMAdapterConfig {
|
|
9
|
+
mode?: AdapterMode;
|
|
10
|
+
toolCallProbability?: number;
|
|
11
|
+
maxToolCallsPerTurn?: number;
|
|
12
|
+
seed?: number;
|
|
13
|
+
responseDelay?: number;
|
|
14
|
+
simulateStreamDelay?: boolean;
|
|
15
|
+
templates?: ResponseTemplate[];
|
|
16
|
+
personality?: PersonalityPreset;
|
|
17
|
+
tokenMultiplier?: number;
|
|
18
|
+
debugMode?: boolean;
|
|
19
|
+
preferredTools?: string[];
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,iBAAiB,GACzB,cAAc,GACd,UAAU,GACV,WAAW,GACX,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,MAAM,WAAW,GACnB,UAAU,GACV,YAAY,GACZ,WAAW,GACX,QAAQ,CAAC;AAEb,MAAM,WAAW,oBAAoB;IAEnC,IAAI,CAAC,EAAE,WAAW,CAAC;IAGnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAG7B,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAG9B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAGhC,eAAe,CAAC,EAAE,MAAM,CAAC;IAGzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flink-app/fake-llm-adapter",
|
|
3
|
+
"version": "2.0.0-alpha.100",
|
|
4
|
+
"description": "Fake LLM adapter for Flink AI framework - perfect for demos and testing",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"flink",
|
|
9
|
+
"ai",
|
|
10
|
+
"llm",
|
|
11
|
+
"adapter",
|
|
12
|
+
"fake",
|
|
13
|
+
"mock",
|
|
14
|
+
"testing",
|
|
15
|
+
"demo"
|
|
16
|
+
],
|
|
17
|
+
"author": "Frost Digital",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"@flink-app/flink": ">=2.0.0-alpha.100"
|
|
21
|
+
},
|
|
22
|
+
"peerDependenciesMeta": {
|
|
23
|
+
"@flink-app/flink": {
|
|
24
|
+
"optional": false
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/jasmine": "^3.7.1",
|
|
29
|
+
"@types/node": "22.13.10",
|
|
30
|
+
"jasmine": "^3.10.0",
|
|
31
|
+
"jasmine-ts": "^0.3.3",
|
|
32
|
+
"ts-node": "^10.9.2",
|
|
33
|
+
"typescript": "^5.6.2",
|
|
34
|
+
"@flink-app/flink": "2.0.0-alpha.100"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"README.md"
|
|
39
|
+
],
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/FrostDigital/flink-framework.git",
|
|
43
|
+
"directory": "packages/fake-llm-adapter"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsc --project tsconfig.dist.json",
|
|
47
|
+
"watch": "tsc --project tsconfig.dist.json --watch",
|
|
48
|
+
"test": "jasmine-ts --config=./spec/support/jasmine.json",
|
|
49
|
+
"clean": "rm -rf dist"
|
|
50
|
+
}
|
|
51
|
+
}
|