tekimax-ts 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -1
- package/dist/index.cjs +248 -123
- package/dist/index.d.cts +57 -23
- package/dist/index.d.ts +57 -23
- package/dist/index.js +245 -123
- package/dist/react/index.cjs +37 -2
- package/dist/react/index.d.cts +7 -5
- package/dist/react/index.d.ts +7 -5
- package/dist/react/index.js +37 -2
- package/dist/tekimax-DIIjg64-.d.cts +450 -0
- package/dist/tekimax-DIIjg64-.d.ts +450 -0
- package/package.json +12 -11
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ npm install tekimax-ts
|
|
|
18
18
|
## 🌟 Features
|
|
19
19
|
|
|
20
20
|
- **Universal API**: One interface for all providers. Switch from OpenAI to Ollama with a single config change.
|
|
21
|
-
- **Type Safety**: End-to-end TypeScript support. Zod schemas for runtime validation.
|
|
21
|
+
- **Strict Modality Type Safety**: End-to-end TypeScript support. Strong capability interfaces ensure compile-time safety (e.g., your code won't compile if you call `.images.generate()` on a provider missing the `ImageGenerationCapability`). Zod schemas for runtime validation.
|
|
22
22
|
- **Zero Latency**: Lightweight adapter pattern with zero runtime overhead.
|
|
23
23
|
- **Zero CVEs**: Hardened supply chain using Chainguard images.
|
|
24
24
|
- **Redis Adapter** _(optional)_: Response caching, rate limiting, token budgets, and session storage with any Redis client.
|
|
@@ -53,6 +53,60 @@ const claude = new Tekimax({
|
|
|
53
53
|
const local = new Tekimax({
|
|
54
54
|
provider: new OllamaProvider({ baseUrl: 'http://localhost:11434' })
|
|
55
55
|
})
|
|
56
|
+
|
|
57
|
+
// Custom Model Proxies (e.g. Internal API gateways)
|
|
58
|
+
const proxyClient = new Tekimax({
|
|
59
|
+
provider: new OpenAIProvider({
|
|
60
|
+
apiKey: process.env.CUSTOM_PROXY_KEY,
|
|
61
|
+
baseURL: 'https://api.my-custom-proxy.internal/v1'
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
### Streaming
|
|
66
|
+
|
|
67
|
+
Tekimax-TS uses standard Javascript Async Iterables for real-time streaming:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
const stream = await client.text.generateStream({
|
|
71
|
+
model: "gpt-4o",
|
|
72
|
+
messages: [{ role: "user", content: "Tell me a story" }]
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
for await (const chunk of stream) {
|
|
76
|
+
process.stdout.write(chunk.delta)
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## 🔌 Plugin Architecture (Lifecycle Hooks)
|
|
81
|
+
|
|
82
|
+
The SDK provides a robust middleware architecture via `plugins`. You can snap in pre-built plugins for Security, Scalability, and Telemetry, or build your own.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { Tekimax, OpenAIProvider, PIIFilterPlugin, LoggerPlugin, MaxContextOverflowPlugin } from 'tekimax-ts'
|
|
86
|
+
|
|
87
|
+
const client = new Tekimax({
|
|
88
|
+
provider: new OpenAIProvider({ apiKey: 'sk-...' }),
|
|
89
|
+
plugins: [
|
|
90
|
+
new LoggerPlugin(), // Telemetry
|
|
91
|
+
new PIIFilterPlugin(), // Security: Redacts emails and SSNs
|
|
92
|
+
new MaxContextOverflowPlugin(15) // Scalability: Prevents context bloat in long loops
|
|
93
|
+
]
|
|
94
|
+
})
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Building Custom Plugins
|
|
98
|
+
Implement the `TekimaxPlugin` interface to hook into the request/response lifecycle:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
export interface TekimaxPlugin {
|
|
102
|
+
name: string
|
|
103
|
+
onInit?: (client: Tekimax) => void
|
|
104
|
+
beforeRequest?: (context: PluginContext) => Promise<void | PluginContext>
|
|
105
|
+
afterResponse?: (context: PluginContext, result: ChatResult) => Promise<void>
|
|
106
|
+
onStreamChunk?: (context: PluginContext, chunk: StreamChunk) => void
|
|
107
|
+
beforeToolExecute?: (toolName: string, args: unknown) => Promise<void>
|
|
108
|
+
afterToolExecute?: (toolName: string, result: unknown) => Promise<void>
|
|
109
|
+
}
|
|
56
110
|
```
|
|
57
111
|
|
|
58
112
|
### 2. Multi-Modal Interfaces
|
package/dist/index.cjs
CHANGED
|
@@ -36,9 +36,12 @@ __export(index_exports, {
|
|
|
36
36
|
FallbackProvider: () => FallbackProvider,
|
|
37
37
|
GeminiProvider: () => GeminiProvider,
|
|
38
38
|
GrokProvider: () => GrokProvider,
|
|
39
|
+
LoggerPlugin: () => LoggerPlugin,
|
|
40
|
+
MaxContextOverflowPlugin: () => MaxContextOverflowPlugin,
|
|
39
41
|
OllamaProvider: () => OllamaProvider,
|
|
40
42
|
OpenAIProvider: () => OpenAIProvider,
|
|
41
43
|
OpenRouterProvider: () => OpenRouterProvider,
|
|
44
|
+
PIIFilterPlugin: () => PIIFilterPlugin,
|
|
42
45
|
RateLimiter: () => RateLimiter,
|
|
43
46
|
ResponseCache: () => ResponseCache,
|
|
44
47
|
SessionStore: () => SessionStore,
|
|
@@ -1084,7 +1087,7 @@ var OpenAIProvider = class {
|
|
|
1084
1087
|
this.name = "openai";
|
|
1085
1088
|
this.client = new import_openai.default({
|
|
1086
1089
|
apiKey: options.apiKey,
|
|
1087
|
-
|
|
1090
|
+
baseURL: options.baseURL
|
|
1088
1091
|
});
|
|
1089
1092
|
}
|
|
1090
1093
|
async generateSpeech(options) {
|
|
@@ -1985,22 +1988,41 @@ function tool(def) {
|
|
|
1985
1988
|
// src/core/generate.ts
|
|
1986
1989
|
async function generateText({
|
|
1987
1990
|
adapter,
|
|
1991
|
+
plugins = [],
|
|
1988
1992
|
...options
|
|
1989
1993
|
}) {
|
|
1990
1994
|
const { model, tools, maxSteps = 1, temperature, maxTokens, signal } = options;
|
|
1991
|
-
|
|
1995
|
+
let currentMessages = [...options.messages];
|
|
1996
|
+
let currentModel = model;
|
|
1992
1997
|
let steps = 0;
|
|
1993
1998
|
const toolDefinitions = tools ? Object.values(tools) : void 0;
|
|
1994
1999
|
while (steps < maxSteps) {
|
|
1995
2000
|
steps++;
|
|
2001
|
+
let context = {
|
|
2002
|
+
model: currentModel,
|
|
2003
|
+
messages: [...currentMessages],
|
|
2004
|
+
timestamp: Date.now(),
|
|
2005
|
+
requestOptions: { ...options }
|
|
2006
|
+
};
|
|
2007
|
+
for (const plugin of plugins) {
|
|
2008
|
+
if (plugin.beforeRequest) {
|
|
2009
|
+
const updated = await plugin.beforeRequest(context);
|
|
2010
|
+
if (updated) context = updated;
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
currentMessages = context.messages;
|
|
2014
|
+
currentModel = context.model;
|
|
1996
2015
|
const result = await adapter.chat({
|
|
1997
|
-
model,
|
|
2016
|
+
model: currentModel,
|
|
1998
2017
|
messages: currentMessages,
|
|
1999
2018
|
tools: toolDefinitions,
|
|
2000
2019
|
temperature,
|
|
2001
2020
|
maxTokens,
|
|
2002
2021
|
signal
|
|
2003
2022
|
});
|
|
2023
|
+
for (const plugin of plugins) {
|
|
2024
|
+
if (plugin.afterResponse) await plugin.afterResponse(context, result);
|
|
2025
|
+
}
|
|
2004
2026
|
const { message } = result;
|
|
2005
2027
|
currentMessages.push(message);
|
|
2006
2028
|
if (!message.toolCalls || message.toolCalls.length === 0) {
|
|
@@ -2014,25 +2036,23 @@ async function generateText({
|
|
|
2014
2036
|
}
|
|
2015
2037
|
const toolResults = await Promise.all(
|
|
2016
2038
|
message.toolCalls.map(async (call) => {
|
|
2017
|
-
const
|
|
2039
|
+
const toolName = call.function.name;
|
|
2040
|
+
const tool2 = tools?.[toolName];
|
|
2018
2041
|
if (!tool2) {
|
|
2019
|
-
return {
|
|
2020
|
-
id: call.id,
|
|
2021
|
-
result: `Error: Tool ${call.function.name} not found`
|
|
2022
|
-
};
|
|
2042
|
+
return { id: call.id, result: `Error: Tool ${toolName} not found` };
|
|
2023
2043
|
}
|
|
2024
2044
|
try {
|
|
2025
|
-
|
|
2045
|
+
let args = JSON.parse(call.function.arguments);
|
|
2046
|
+
for (const plugin of plugins) {
|
|
2047
|
+
if (plugin.beforeToolExecute) await plugin.beforeToolExecute(toolName, args);
|
|
2048
|
+
}
|
|
2026
2049
|
const output = await tool2.execute(args);
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
};
|
|
2050
|
+
for (const plugin of plugins) {
|
|
2051
|
+
if (plugin.afterToolExecute) await plugin.afterToolExecute(toolName, output);
|
|
2052
|
+
}
|
|
2053
|
+
return { id: call.id, result: output };
|
|
2031
2054
|
} catch (error) {
|
|
2032
|
-
return {
|
|
2033
|
-
id: call.id,
|
|
2034
|
-
result: `Error executing tool: ${error.message}`
|
|
2035
|
-
};
|
|
2055
|
+
return { id: call.id, result: `Error executing tool: ${error.message}` };
|
|
2036
2056
|
}
|
|
2037
2057
|
})
|
|
2038
2058
|
);
|
|
@@ -2050,7 +2070,6 @@ async function generateText({
|
|
|
2050
2070
|
toolCalls: [],
|
|
2051
2071
|
toolResults: [],
|
|
2052
2072
|
finishReason: "length",
|
|
2053
|
-
// or 'tool_calls' if strictly ending on tools
|
|
2054
2073
|
usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
|
|
2055
2074
|
warnings: ["Max steps reached"]
|
|
2056
2075
|
};
|
|
@@ -2306,69 +2325,80 @@ async function withRetry(fn, options = {}) {
|
|
|
2306
2325
|
throw lastError || new Error("withRetry: unexpected exit");
|
|
2307
2326
|
}
|
|
2308
2327
|
function createRetryProvider(provider, options = {}) {
|
|
2309
|
-
return {
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2328
|
+
return new Proxy(provider, {
|
|
2329
|
+
get(target, prop, receiver) {
|
|
2330
|
+
const value = Reflect.get(target, prop, receiver);
|
|
2331
|
+
if (typeof value === "function" && typeof prop === "string") {
|
|
2332
|
+
if (prop === "chatStream") {
|
|
2333
|
+
return function(chatOptions) {
|
|
2334
|
+
const iterable = {
|
|
2335
|
+
[Symbol.asyncIterator]() {
|
|
2336
|
+
let innerIterator = null;
|
|
2337
|
+
return {
|
|
2338
|
+
async next() {
|
|
2339
|
+
if (!innerIterator) {
|
|
2340
|
+
const stream = await withRetry(
|
|
2341
|
+
async () => value.call(target, chatOptions),
|
|
2342
|
+
{ ...options, signal: chatOptions.signal || options.signal }
|
|
2343
|
+
);
|
|
2344
|
+
innerIterator = stream[Symbol.asyncIterator]();
|
|
2345
|
+
}
|
|
2346
|
+
return innerIterator.next();
|
|
2347
|
+
},
|
|
2348
|
+
async return() {
|
|
2349
|
+
if (innerIterator?.return) {
|
|
2350
|
+
return innerIterator.return();
|
|
2351
|
+
}
|
|
2352
|
+
return { value: void 0, done: true };
|
|
2353
|
+
}
|
|
2354
|
+
};
|
|
2336
2355
|
}
|
|
2337
|
-
|
|
2338
|
-
|
|
2356
|
+
};
|
|
2357
|
+
return iterable;
|
|
2339
2358
|
};
|
|
2340
2359
|
}
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2360
|
+
const promiseMethods = [
|
|
2361
|
+
"chat",
|
|
2362
|
+
"generateImage",
|
|
2363
|
+
"editImage",
|
|
2364
|
+
"analyzeImage",
|
|
2365
|
+
"generateSpeech",
|
|
2366
|
+
"transcribeAudio",
|
|
2367
|
+
"generateVideo",
|
|
2368
|
+
"analyzeVideo",
|
|
2369
|
+
"embed"
|
|
2370
|
+
];
|
|
2371
|
+
if (promiseMethods.includes(prop)) {
|
|
2372
|
+
return function(...args) {
|
|
2373
|
+
const callOpts = args[0] || {};
|
|
2374
|
+
const sig = callOpts.signal || options.signal;
|
|
2375
|
+
return withRetry(() => value.apply(target, args), { ...options, signal: sig });
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
if (typeof value === "function") {
|
|
2380
|
+
return value.bind(target);
|
|
2381
|
+
}
|
|
2382
|
+
return value;
|
|
2383
|
+
}
|
|
2384
|
+
});
|
|
2353
2385
|
}
|
|
2354
2386
|
|
|
2355
2387
|
// src/core/middleware.ts
|
|
2356
2388
|
function wrapProvider(provider, middlewares) {
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
analyzeVideo: provider.analyzeVideo?.bind(provider)
|
|
2371
|
-
};
|
|
2389
|
+
const wrappedChat = createWrappedChat(provider, middlewares);
|
|
2390
|
+
const wrappedChatStream = createWrappedChatStream(provider, middlewares);
|
|
2391
|
+
return new Proxy(provider, {
|
|
2392
|
+
get(target, prop, receiver) {
|
|
2393
|
+
if (prop === "chat") return wrappedChat;
|
|
2394
|
+
if (prop === "chatStream") return wrappedChatStream;
|
|
2395
|
+
const value = Reflect.get(target, prop, receiver);
|
|
2396
|
+
if (typeof value === "function") {
|
|
2397
|
+
return value.bind(target);
|
|
2398
|
+
}
|
|
2399
|
+
return value;
|
|
2400
|
+
}
|
|
2401
|
+
});
|
|
2372
2402
|
}
|
|
2373
2403
|
function createWrappedChat(provider, middlewares) {
|
|
2374
2404
|
return async (options) => {
|
|
@@ -2517,35 +2547,35 @@ var FallbackProvider = class {
|
|
|
2517
2547
|
}
|
|
2518
2548
|
// --- Multi-modal: delegate to first provider that supports the capability ---
|
|
2519
2549
|
get generateImage() {
|
|
2520
|
-
const provider = this.providers.find((p) => p.generateImage);
|
|
2550
|
+
const provider = this.providers.find((p) => typeof p.generateImage === "function");
|
|
2521
2551
|
return provider?.generateImage?.bind(provider);
|
|
2522
2552
|
}
|
|
2523
2553
|
get editImage() {
|
|
2524
|
-
const provider = this.providers.find((p) => p.editImage);
|
|
2554
|
+
const provider = this.providers.find((p) => typeof p.editImage === "function");
|
|
2525
2555
|
return provider?.editImage?.bind(provider);
|
|
2526
2556
|
}
|
|
2527
2557
|
get analyzeImage() {
|
|
2528
|
-
const provider = this.providers.find((p) => p.analyzeImage);
|
|
2558
|
+
const provider = this.providers.find((p) => typeof p.analyzeImage === "function");
|
|
2529
2559
|
return provider?.analyzeImage?.bind(provider);
|
|
2530
2560
|
}
|
|
2531
2561
|
get generateSpeech() {
|
|
2532
|
-
const provider = this.providers.find((p) => p.generateSpeech);
|
|
2562
|
+
const provider = this.providers.find((p) => typeof p.generateSpeech === "function");
|
|
2533
2563
|
return provider?.generateSpeech?.bind(provider);
|
|
2534
2564
|
}
|
|
2535
2565
|
get transcribeAudio() {
|
|
2536
|
-
const provider = this.providers.find((p) => p.transcribeAudio);
|
|
2566
|
+
const provider = this.providers.find((p) => typeof p.transcribeAudio === "function");
|
|
2537
2567
|
return provider?.transcribeAudio?.bind(provider);
|
|
2538
2568
|
}
|
|
2539
2569
|
get generateVideo() {
|
|
2540
|
-
const provider = this.providers.find((p) => p.generateVideo);
|
|
2570
|
+
const provider = this.providers.find((p) => typeof p.generateVideo === "function");
|
|
2541
2571
|
return provider?.generateVideo?.bind(provider);
|
|
2542
2572
|
}
|
|
2543
2573
|
get analyzeVideo() {
|
|
2544
|
-
const provider = this.providers.find((p) => p.analyzeVideo);
|
|
2574
|
+
const provider = this.providers.find((p) => typeof p.analyzeVideo === "function");
|
|
2545
2575
|
return provider?.analyzeVideo?.bind(provider);
|
|
2546
2576
|
}
|
|
2547
2577
|
get embed() {
|
|
2548
|
-
const provider = this.providers.find((p) => p.embed);
|
|
2578
|
+
const provider = this.providers.find((p) => typeof p.embed === "function");
|
|
2549
2579
|
return provider?.embed?.bind(provider);
|
|
2550
2580
|
}
|
|
2551
2581
|
/**
|
|
@@ -2573,7 +2603,6 @@ var FallbackProvider = class {
|
|
|
2573
2603
|
};
|
|
2574
2604
|
|
|
2575
2605
|
// src/core/convex.ts
|
|
2576
|
-
var import_child_process = require("child_process");
|
|
2577
2606
|
var MANAGEMENT_API = "https://api.convex.dev/v1";
|
|
2578
2607
|
var ConvexManager = class {
|
|
2579
2608
|
constructor(options = {}) {
|
|
@@ -2656,20 +2685,17 @@ var ConvexManager = class {
|
|
|
2656
2685
|
}
|
|
2657
2686
|
/**
|
|
2658
2687
|
* Push Convex functions and schema to a deployment.
|
|
2659
|
-
*
|
|
2688
|
+
* Use the Convex CLI directly to run this command.
|
|
2660
2689
|
*/
|
|
2661
2690
|
deploy(deployKey, options = {}) {
|
|
2662
2691
|
const cwd = options.projectDir || process.cwd();
|
|
2663
2692
|
const flags = options.flags?.join(" ") || "";
|
|
2664
|
-
const cmd = `npx convex deploy --cmd-url-env-var-name CONVEX_URL ${flags}`.trim();
|
|
2665
|
-
|
|
2666
|
-
cwd
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
CONVEX_DEPLOY_KEY: deployKey
|
|
2671
|
-
}
|
|
2672
|
-
});
|
|
2693
|
+
const cmd = `CONVEX_DEPLOY_KEY=${deployKey} npx convex deploy --cmd-url-env-var-name CONVEX_URL ${flags}`.trim();
|
|
2694
|
+
throw new Error(
|
|
2695
|
+
`Deploys must be executed via the CLI. Run the following command in your terminal from ${cwd}:
|
|
2696
|
+
|
|
2697
|
+
${cmd}`
|
|
2698
|
+
);
|
|
2673
2699
|
}
|
|
2674
2700
|
// ─── Discovery ──────────────────────────────────────────────────────
|
|
2675
2701
|
/**
|
|
@@ -2691,10 +2717,7 @@ var ConvexManager = class {
|
|
|
2691
2717
|
}
|
|
2692
2718
|
/**
|
|
2693
2719
|
* Generate an OpenAPI specification from a Convex deployment.
|
|
2694
|
-
*
|
|
2695
|
-
* Uses `npx convex-helpers open-api-spec` to introspect the deployment
|
|
2696
|
-
* and produce a `convex-spec.yaml` file. You can then use tools like
|
|
2697
|
-
* openapi-generator-cli to create type-safe clients in Go, Java, etc.
|
|
2720
|
+
* Use the Convex CLI directly to run this command.
|
|
2698
2721
|
*
|
|
2699
2722
|
* @see https://docs.convex.dev/client/open-api
|
|
2700
2723
|
*/
|
|
@@ -2703,10 +2726,11 @@ var ConvexManager = class {
|
|
|
2703
2726
|
const output = options.output || "convex-spec.yaml";
|
|
2704
2727
|
const extraFlags = options.flags?.join(" ") || "";
|
|
2705
2728
|
const cmd = `npx convex-helpers open-api-spec --output ${output} ${extraFlags}`.trim();
|
|
2706
|
-
|
|
2707
|
-
cwd
|
|
2708
|
-
|
|
2709
|
-
|
|
2729
|
+
throw new Error(
|
|
2730
|
+
`OpenAPI generation must be executed via the CLI. Run the following command in your terminal from ${cwd}:
|
|
2731
|
+
|
|
2732
|
+
${cmd}`
|
|
2733
|
+
);
|
|
2710
2734
|
}
|
|
2711
2735
|
// ─── Internal Helpers ───────────────────────────────────────────────
|
|
2712
2736
|
async resolveTeamId() {
|
|
@@ -2739,7 +2763,6 @@ var ConvexManager = class {
|
|
|
2739
2763
|
};
|
|
2740
2764
|
|
|
2741
2765
|
// src/core/cache.ts
|
|
2742
|
-
var import_crypto = require("crypto");
|
|
2743
2766
|
var ResponseCache = class {
|
|
2744
2767
|
constructor(redis, options = {}) {
|
|
2745
2768
|
this.redis = redis;
|
|
@@ -2762,7 +2785,11 @@ var ResponseCache = class {
|
|
|
2762
2785
|
}
|
|
2763
2786
|
defaultKeyFn(model, messages) {
|
|
2764
2787
|
const payload = JSON.stringify({ model, messages });
|
|
2765
|
-
|
|
2788
|
+
let hash = 5381;
|
|
2789
|
+
for (let i = 0; i < payload.length; i++) {
|
|
2790
|
+
hash = (hash << 5) + hash + payload.charCodeAt(i);
|
|
2791
|
+
}
|
|
2792
|
+
return (hash >>> 0).toString(16);
|
|
2766
2793
|
}
|
|
2767
2794
|
};
|
|
2768
2795
|
var RateLimiter = class {
|
|
@@ -2859,28 +2886,55 @@ var SessionStore = class {
|
|
|
2859
2886
|
|
|
2860
2887
|
// src/namespaces/text.ts
|
|
2861
2888
|
var TextNamespace = class {
|
|
2862
|
-
constructor(provider) {
|
|
2889
|
+
constructor(provider, plugins = []) {
|
|
2863
2890
|
this.provider = provider;
|
|
2891
|
+
this.plugins = plugins;
|
|
2892
|
+
}
|
|
2893
|
+
async runBeforeRequest(options) {
|
|
2894
|
+
let context = {
|
|
2895
|
+
model: options.model,
|
|
2896
|
+
messages: [...options.messages],
|
|
2897
|
+
timestamp: Date.now(),
|
|
2898
|
+
requestOptions: { ...options }
|
|
2899
|
+
};
|
|
2900
|
+
for (const plugin of this.plugins) {
|
|
2901
|
+
if (plugin.beforeRequest) {
|
|
2902
|
+
const updated = await plugin.beforeRequest(context);
|
|
2903
|
+
if (updated) context = updated;
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
return context;
|
|
2864
2907
|
}
|
|
2865
2908
|
/**
|
|
2866
2909
|
* Generate text from a prompt (Chat Completion).
|
|
2867
2910
|
*/
|
|
2868
2911
|
async generate(options) {
|
|
2869
|
-
|
|
2912
|
+
const context = await this.runBeforeRequest(options);
|
|
2913
|
+
const activeOptions = { ...options, messages: context.messages, model: context.model };
|
|
2914
|
+
const result = await this.provider.chat(activeOptions);
|
|
2915
|
+
for (const plugin of this.plugins) {
|
|
2916
|
+
if (plugin.afterResponse) await plugin.afterResponse(context, result);
|
|
2917
|
+
}
|
|
2918
|
+
return result;
|
|
2870
2919
|
}
|
|
2871
2920
|
/**
|
|
2872
2921
|
* Stream text generation.
|
|
2873
2922
|
*/
|
|
2874
2923
|
async *generateStream(options) {
|
|
2875
|
-
|
|
2924
|
+
const context = await this.runBeforeRequest(options);
|
|
2925
|
+
const activeOptions = { ...options, messages: context.messages, model: context.model };
|
|
2926
|
+
for await (const chunk of this.provider.chatStream(activeOptions)) {
|
|
2927
|
+
for (const plugin of this.plugins) {
|
|
2928
|
+
if (plugin.onStreamChunk) plugin.onStreamChunk(context, chunk);
|
|
2929
|
+
}
|
|
2876
2930
|
yield chunk;
|
|
2877
2931
|
}
|
|
2878
2932
|
}
|
|
2879
2933
|
/**
|
|
2880
|
-
* Generate embeddings for text input(s).
|
|
2934
|
+
* Generate embeddings for text input(s). Only available if the provider supports embeddings.
|
|
2881
2935
|
*/
|
|
2882
2936
|
async embed(options) {
|
|
2883
|
-
if (!this.provider
|
|
2937
|
+
if (!("embed" in this.provider)) {
|
|
2884
2938
|
throw new Error(`Provider '${this.provider.name}' does not support embeddings`);
|
|
2885
2939
|
}
|
|
2886
2940
|
return this.provider.embed(options);
|
|
@@ -2902,28 +2956,28 @@ var ImagesNamespace = class {
|
|
|
2902
2956
|
this.provider = provider;
|
|
2903
2957
|
}
|
|
2904
2958
|
/**
|
|
2905
|
-
* Generate images from a prompt.
|
|
2959
|
+
* Generate images from a prompt. Only available if the provider supports image generation.
|
|
2906
2960
|
*/
|
|
2907
2961
|
async generate(options) {
|
|
2908
|
-
if (!this.provider
|
|
2962
|
+
if (!("generateImage" in this.provider)) {
|
|
2909
2963
|
throw new Error(`Provider '${this.provider.name}' does not support image generation`);
|
|
2910
2964
|
}
|
|
2911
2965
|
return this.provider.generateImage(options);
|
|
2912
2966
|
}
|
|
2913
2967
|
/**
|
|
2914
|
-
* Edit an image with a prompt.
|
|
2968
|
+
* Edit an image with a prompt. Only available if the provider supports image editing.
|
|
2915
2969
|
*/
|
|
2916
2970
|
async edit(options) {
|
|
2917
|
-
if (!this.provider
|
|
2971
|
+
if (!("editImage" in this.provider)) {
|
|
2918
2972
|
throw new Error(`Provider '${this.provider.name}' does not support image editing`);
|
|
2919
2973
|
}
|
|
2920
2974
|
return this.provider.editImage(options);
|
|
2921
2975
|
}
|
|
2922
2976
|
/**
|
|
2923
|
-
* Analyze an image (Vision).
|
|
2977
|
+
* Analyze an image (Vision). Only available if the provider supports vision analytics.
|
|
2924
2978
|
*/
|
|
2925
2979
|
async analyze(options) {
|
|
2926
|
-
if (!this.provider
|
|
2980
|
+
if (!("analyzeImage" in this.provider)) {
|
|
2927
2981
|
throw new Error(`Provider '${this.provider.name}' does not support image analysis`);
|
|
2928
2982
|
}
|
|
2929
2983
|
return this.provider.analyzeImage(options);
|
|
@@ -2936,19 +2990,19 @@ var AudioNamespace = class {
|
|
|
2936
2990
|
this.provider = provider;
|
|
2937
2991
|
}
|
|
2938
2992
|
/**
|
|
2939
|
-
* Convert text to speech.
|
|
2993
|
+
* Convert text to speech. Only available if the provider supports TTS.
|
|
2940
2994
|
*/
|
|
2941
2995
|
async speak(options) {
|
|
2942
|
-
if (!this.provider
|
|
2996
|
+
if (!("generateSpeech" in this.provider)) {
|
|
2943
2997
|
throw new Error(`Provider '${this.provider.name}' does not support speech generation`);
|
|
2944
2998
|
}
|
|
2945
2999
|
return this.provider.generateSpeech(options);
|
|
2946
3000
|
}
|
|
2947
3001
|
/**
|
|
2948
|
-
* Transcribe audio to text.
|
|
3002
|
+
* Transcribe audio to text. Only available if the provider supports STT.
|
|
2949
3003
|
*/
|
|
2950
3004
|
async transcribe(options) {
|
|
2951
|
-
if (!this.provider
|
|
3005
|
+
if (!("transcribeAudio" in this.provider)) {
|
|
2952
3006
|
throw new Error(`Provider '${this.provider.name}' does not support audio transcription`);
|
|
2953
3007
|
}
|
|
2954
3008
|
return this.provider.transcribeAudio(options);
|
|
@@ -2961,19 +3015,19 @@ var VideosNamespace = class {
|
|
|
2961
3015
|
this.provider = provider;
|
|
2962
3016
|
}
|
|
2963
3017
|
/**
|
|
2964
|
-
* Generate a video from a prompt.
|
|
3018
|
+
* Generate a video from a prompt. Only available if the provider supports video generation.
|
|
2965
3019
|
*/
|
|
2966
3020
|
async generate(options) {
|
|
2967
|
-
if (!this.provider
|
|
3021
|
+
if (!("generateVideo" in this.provider)) {
|
|
2968
3022
|
throw new Error(`Provider '${this.provider.name}' does not support video generation`);
|
|
2969
3023
|
}
|
|
2970
3024
|
return this.provider.generateVideo(options);
|
|
2971
3025
|
}
|
|
2972
3026
|
/**
|
|
2973
|
-
* Analyze a video (Video-to-Text).
|
|
3027
|
+
* Analyze a video (Video-to-Text). Only available if the provider supports video analysis.
|
|
2974
3028
|
*/
|
|
2975
3029
|
async analyze(options) {
|
|
2976
|
-
if (!this.provider
|
|
3030
|
+
if (!("analyzeVideo" in this.provider)) {
|
|
2977
3031
|
throw new Error(`Provider '${this.provider.name}' does not support video analysis`);
|
|
2978
3032
|
}
|
|
2979
3033
|
return this.provider.analyzeVideo(options);
|
|
@@ -2984,7 +3038,11 @@ var VideosNamespace = class {
|
|
|
2984
3038
|
var Tekimax = class {
|
|
2985
3039
|
constructor(options) {
|
|
2986
3040
|
this.provider = options.provider;
|
|
2987
|
-
this.
|
|
3041
|
+
this.plugins = options.plugins || [];
|
|
3042
|
+
for (const plugin of this.plugins) {
|
|
3043
|
+
if (plugin.onInit) plugin.onInit(this);
|
|
3044
|
+
}
|
|
3045
|
+
this.text = new TextNamespace(this.provider, this.plugins);
|
|
2988
3046
|
this.images = new ImagesNamespace(this.provider);
|
|
2989
3047
|
this.audio = new AudioNamespace(this.provider);
|
|
2990
3048
|
this.videos = new VideosNamespace(this.provider);
|
|
@@ -2996,6 +3054,70 @@ var Tekimax = class {
|
|
|
2996
3054
|
return this.text.chat;
|
|
2997
3055
|
}
|
|
2998
3056
|
};
|
|
3057
|
+
|
|
3058
|
+
// src/plugins/index.ts
|
|
3059
|
+
var PIIFilterPlugin = class {
|
|
3060
|
+
constructor() {
|
|
3061
|
+
this.name = "PIIFilterPlugin";
|
|
3062
|
+
this.patterns = {
|
|
3063
|
+
email: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,
|
|
3064
|
+
ssn: /\b\d{3}-\d{2}-\d{4}\b/g
|
|
3065
|
+
};
|
|
3066
|
+
}
|
|
3067
|
+
async beforeRequest(context) {
|
|
3068
|
+
context.messages = context.messages.map((msg) => {
|
|
3069
|
+
if (typeof msg.content === "string") {
|
|
3070
|
+
let safeContent = msg.content;
|
|
3071
|
+
safeContent = safeContent.replace(this.patterns.email, "[REDACTED EMAIL]");
|
|
3072
|
+
safeContent = safeContent.replace(this.patterns.ssn, "[REDACTED SSN]");
|
|
3073
|
+
return { ...msg, content: safeContent };
|
|
3074
|
+
}
|
|
3075
|
+
return msg;
|
|
3076
|
+
});
|
|
3077
|
+
return context;
|
|
3078
|
+
}
|
|
3079
|
+
};
|
|
3080
|
+
var MaxContextOverflowPlugin = class {
|
|
3081
|
+
constructor(maxMessages = 20) {
|
|
3082
|
+
this.maxMessages = maxMessages;
|
|
3083
|
+
this.name = "MaxContextOverflowPlugin";
|
|
3084
|
+
}
|
|
3085
|
+
async beforeRequest(context) {
|
|
3086
|
+
if (context.messages.length > this.maxMessages) {
|
|
3087
|
+
const hasSystem = context.messages[0]?.role === "system";
|
|
3088
|
+
const systemMsg = hasSystem ? context.messages[0] : null;
|
|
3089
|
+
const recentMsgs = context.messages.slice(-(this.maxMessages - (hasSystem ? 1 : 0)));
|
|
3090
|
+
context.messages = hasSystem && systemMsg ? [systemMsg, ...recentMsgs] : recentMsgs;
|
|
3091
|
+
console.warn(`[MaxContextOverflowPlugin] Truncated chat history to ${this.maxMessages} messages to preserve context limits.`);
|
|
3092
|
+
}
|
|
3093
|
+
return context;
|
|
3094
|
+
}
|
|
3095
|
+
};
|
|
3096
|
+
var LoggerPlugin = class {
|
|
3097
|
+
constructor() {
|
|
3098
|
+
this.name = "LoggerPlugin";
|
|
3099
|
+
}
|
|
3100
|
+
onInit() {
|
|
3101
|
+
console.log("[LoggerPlugin] Tekimax SDK initialized with Logger Plugin active.");
|
|
3102
|
+
}
|
|
3103
|
+
async beforeRequest(context) {
|
|
3104
|
+
console.log(`[LoggerPlugin] Sending request to model: ${context.model} (${context.messages.length} messages)`);
|
|
3105
|
+
}
|
|
3106
|
+
async afterResponse(context, result) {
|
|
3107
|
+
console.log(`[LoggerPlugin] Received completion from ${context.model}. Usage:`, result.usage);
|
|
3108
|
+
}
|
|
3109
|
+
onStreamChunk(context, chunk) {
|
|
3110
|
+
if (chunk.usage) {
|
|
3111
|
+
console.log(`[LoggerPlugin] Stream completed. Final usage:`, chunk.usage);
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3114
|
+
async beforeToolExecute(toolName, args) {
|
|
3115
|
+
console.log(`[LoggerPlugin] Executing tool '${toolName}' with args:`, args);
|
|
3116
|
+
}
|
|
3117
|
+
async afterToolExecute(toolName, result) {
|
|
3118
|
+
console.log(`[LoggerPlugin] Tool '${toolName}' returned successfully.`);
|
|
3119
|
+
}
|
|
3120
|
+
};
|
|
2999
3121
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3000
3122
|
0 && (module.exports = {
|
|
3001
3123
|
AnthropicProvider,
|
|
@@ -3004,9 +3126,12 @@ var Tekimax = class {
|
|
|
3004
3126
|
FallbackProvider,
|
|
3005
3127
|
GeminiProvider,
|
|
3006
3128
|
GrokProvider,
|
|
3129
|
+
LoggerPlugin,
|
|
3130
|
+
MaxContextOverflowPlugin,
|
|
3007
3131
|
OllamaProvider,
|
|
3008
3132
|
OpenAIProvider,
|
|
3009
3133
|
OpenRouterProvider,
|
|
3134
|
+
PIIFilterPlugin,
|
|
3010
3135
|
RateLimiter,
|
|
3011
3136
|
ResponseCache,
|
|
3012
3137
|
SessionStore,
|