tekimax-ts 0.2.0 → 0.2.3

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/dist/index.cjs CHANGED
@@ -32,13 +32,15 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  AnthropicProvider: () => AnthropicProvider,
34
34
  ApiTypes: () => types_exports,
35
- ConvexManager: () => ConvexManager,
36
35
  FallbackProvider: () => FallbackProvider,
37
36
  GeminiProvider: () => GeminiProvider,
38
37
  GrokProvider: () => GrokProvider,
38
+ LoggerPlugin: () => LoggerPlugin,
39
+ MaxContextOverflowPlugin: () => MaxContextOverflowPlugin,
39
40
  OllamaProvider: () => OllamaProvider,
40
41
  OpenAIProvider: () => OpenAIProvider,
41
42
  OpenRouterProvider: () => OpenRouterProvider,
43
+ PIIFilterPlugin: () => PIIFilterPlugin,
42
44
  RateLimiter: () => RateLimiter,
43
45
  ResponseCache: () => ResponseCache,
44
46
  SessionStore: () => SessionStore,
@@ -1084,7 +1086,7 @@ var OpenAIProvider = class {
1084
1086
  this.name = "openai";
1085
1087
  this.client = new import_openai.default({
1086
1088
  apiKey: options.apiKey,
1087
- dangerouslyAllowBrowser: options.dangerouslyAllowBrowser
1089
+ baseURL: options.baseURL
1088
1090
  });
1089
1091
  }
1090
1092
  async generateSpeech(options) {
@@ -1985,22 +1987,41 @@ function tool(def) {
1985
1987
  // src/core/generate.ts
1986
1988
  async function generateText({
1987
1989
  adapter,
1990
+ plugins = [],
1988
1991
  ...options
1989
1992
  }) {
1990
1993
  const { model, tools, maxSteps = 1, temperature, maxTokens, signal } = options;
1991
- const currentMessages = [...options.messages];
1994
+ let currentMessages = [...options.messages];
1995
+ let currentModel = model;
1992
1996
  let steps = 0;
1993
1997
  const toolDefinitions = tools ? Object.values(tools) : void 0;
1994
1998
  while (steps < maxSteps) {
1995
1999
  steps++;
2000
+ let context = {
2001
+ model: currentModel,
2002
+ messages: [...currentMessages],
2003
+ timestamp: Date.now(),
2004
+ requestOptions: { ...options }
2005
+ };
2006
+ for (const plugin of plugins) {
2007
+ if (plugin.beforeRequest) {
2008
+ const updated = await plugin.beforeRequest(context);
2009
+ if (updated) context = updated;
2010
+ }
2011
+ }
2012
+ currentMessages = context.messages;
2013
+ currentModel = context.model;
1996
2014
  const result = await adapter.chat({
1997
- model,
2015
+ model: currentModel,
1998
2016
  messages: currentMessages,
1999
2017
  tools: toolDefinitions,
2000
2018
  temperature,
2001
2019
  maxTokens,
2002
2020
  signal
2003
2021
  });
2022
+ for (const plugin of plugins) {
2023
+ if (plugin.afterResponse) await plugin.afterResponse(context, result);
2024
+ }
2004
2025
  const { message } = result;
2005
2026
  currentMessages.push(message);
2006
2027
  if (!message.toolCalls || message.toolCalls.length === 0) {
@@ -2014,25 +2035,23 @@ async function generateText({
2014
2035
  }
2015
2036
  const toolResults = await Promise.all(
2016
2037
  message.toolCalls.map(async (call) => {
2017
- const tool2 = tools?.[call.function.name];
2038
+ const toolName = call.function.name;
2039
+ const tool2 = tools?.[toolName];
2018
2040
  if (!tool2) {
2019
- return {
2020
- id: call.id,
2021
- result: `Error: Tool ${call.function.name} not found`
2022
- };
2041
+ return { id: call.id, result: `Error: Tool ${toolName} not found` };
2023
2042
  }
2024
2043
  try {
2025
- const args = JSON.parse(call.function.arguments);
2044
+ let args = JSON.parse(call.function.arguments);
2045
+ for (const plugin of plugins) {
2046
+ if (plugin.beforeToolExecute) await plugin.beforeToolExecute(toolName, args);
2047
+ }
2026
2048
  const output = await tool2.execute(args);
2027
- return {
2028
- id: call.id,
2029
- result: output
2030
- };
2049
+ for (const plugin of plugins) {
2050
+ if (plugin.afterToolExecute) await plugin.afterToolExecute(toolName, output);
2051
+ }
2052
+ return { id: call.id, result: output };
2031
2053
  } catch (error) {
2032
- return {
2033
- id: call.id,
2034
- result: `Error executing tool: ${error.message}`
2035
- };
2054
+ return { id: call.id, result: `Error executing tool: ${error.message}` };
2036
2055
  }
2037
2056
  })
2038
2057
  );
@@ -2050,7 +2069,6 @@ async function generateText({
2050
2069
  toolCalls: [],
2051
2070
  toolResults: [],
2052
2071
  finishReason: "length",
2053
- // or 'tool_calls' if strictly ending on tools
2054
2072
  usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
2055
2073
  warnings: ["Max steps reached"]
2056
2074
  };
@@ -2306,69 +2324,80 @@ async function withRetry(fn, options = {}) {
2306
2324
  throw lastError || new Error("withRetry: unexpected exit");
2307
2325
  }
2308
2326
  function createRetryProvider(provider, options = {}) {
2309
- return {
2310
- ...provider,
2311
- name: provider.name,
2312
- chat: (chatOptions) => {
2313
- return withRetry(
2314
- () => provider.chat(chatOptions),
2315
- { ...options, signal: chatOptions.signal || options.signal }
2316
- );
2317
- },
2318
- chatStream: (chatOptions) => {
2319
- const iterable = {
2320
- [Symbol.asyncIterator]() {
2321
- let innerIterator = null;
2322
- return {
2323
- async next() {
2324
- if (!innerIterator) {
2325
- const stream = await withRetry(
2326
- async () => provider.chatStream(chatOptions),
2327
- { ...options, signal: chatOptions.signal || options.signal }
2328
- );
2329
- innerIterator = stream[Symbol.asyncIterator]();
2330
- }
2331
- return innerIterator.next();
2332
- },
2333
- async return() {
2334
- if (innerIterator?.return) {
2335
- return innerIterator.return();
2327
+ return new Proxy(provider, {
2328
+ get(target, prop, receiver) {
2329
+ const value = Reflect.get(target, prop, receiver);
2330
+ if (typeof value === "function" && typeof prop === "string") {
2331
+ if (prop === "chatStream") {
2332
+ return function(chatOptions) {
2333
+ const iterable = {
2334
+ [Symbol.asyncIterator]() {
2335
+ let innerIterator = null;
2336
+ return {
2337
+ async next() {
2338
+ if (!innerIterator) {
2339
+ const stream = await withRetry(
2340
+ async () => value.call(target, chatOptions),
2341
+ { ...options, signal: chatOptions.signal || options.signal }
2342
+ );
2343
+ innerIterator = stream[Symbol.asyncIterator]();
2344
+ }
2345
+ return innerIterator.next();
2346
+ },
2347
+ async return() {
2348
+ if (innerIterator?.return) {
2349
+ return innerIterator.return();
2350
+ }
2351
+ return { value: void 0, done: true };
2352
+ }
2353
+ };
2336
2354
  }
2337
- return { value: void 0, done: true };
2338
- }
2355
+ };
2356
+ return iterable;
2339
2357
  };
2340
2358
  }
2341
- };
2342
- return iterable;
2343
- },
2344
- // Pass through multi-modal methods with retry
2345
- generateImage: provider.generateImage ? (opts) => withRetry(() => provider.generateImage(opts), options) : void 0,
2346
- editImage: provider.editImage ? (opts) => withRetry(() => provider.editImage(opts), options) : void 0,
2347
- analyzeImage: provider.analyzeImage ? (opts) => withRetry(() => provider.analyzeImage(opts), options) : void 0,
2348
- generateSpeech: provider.generateSpeech ? (opts) => withRetry(() => provider.generateSpeech(opts), options) : void 0,
2349
- transcribeAudio: provider.transcribeAudio ? (opts) => withRetry(() => provider.transcribeAudio(opts), options) : void 0,
2350
- generateVideo: provider.generateVideo ? (opts) => withRetry(() => provider.generateVideo(opts), options) : void 0,
2351
- analyzeVideo: provider.analyzeVideo ? (opts) => withRetry(() => provider.analyzeVideo(opts), options) : void 0
2352
- };
2359
+ const promiseMethods = [
2360
+ "chat",
2361
+ "generateImage",
2362
+ "editImage",
2363
+ "analyzeImage",
2364
+ "generateSpeech",
2365
+ "transcribeAudio",
2366
+ "generateVideo",
2367
+ "analyzeVideo",
2368
+ "embed"
2369
+ ];
2370
+ if (promiseMethods.includes(prop)) {
2371
+ return function(...args) {
2372
+ const callOpts = args[0] || {};
2373
+ const sig = callOpts.signal || options.signal;
2374
+ return withRetry(() => value.apply(target, args), { ...options, signal: sig });
2375
+ };
2376
+ }
2377
+ }
2378
+ if (typeof value === "function") {
2379
+ return value.bind(target);
2380
+ }
2381
+ return value;
2382
+ }
2383
+ });
2353
2384
  }
2354
2385
 
2355
2386
  // src/core/middleware.ts
2356
2387
  function wrapProvider(provider, middlewares) {
2357
- return {
2358
- ...provider,
2359
- name: provider.name,
2360
- chat: createWrappedChat(provider, middlewares),
2361
- chatStream: createWrappedChatStream(provider, middlewares),
2362
- // Multi-modal methods pass through unmodified.
2363
- // Middleware only applies to chat/chatStream for now.
2364
- generateImage: provider.generateImage?.bind(provider),
2365
- editImage: provider.editImage?.bind(provider),
2366
- analyzeImage: provider.analyzeImage?.bind(provider),
2367
- generateSpeech: provider.generateSpeech?.bind(provider),
2368
- transcribeAudio: provider.transcribeAudio?.bind(provider),
2369
- generateVideo: provider.generateVideo?.bind(provider),
2370
- analyzeVideo: provider.analyzeVideo?.bind(provider)
2371
- };
2388
+ const wrappedChat = createWrappedChat(provider, middlewares);
2389
+ const wrappedChatStream = createWrappedChatStream(provider, middlewares);
2390
+ return new Proxy(provider, {
2391
+ get(target, prop, receiver) {
2392
+ if (prop === "chat") return wrappedChat;
2393
+ if (prop === "chatStream") return wrappedChatStream;
2394
+ const value = Reflect.get(target, prop, receiver);
2395
+ if (typeof value === "function") {
2396
+ return value.bind(target);
2397
+ }
2398
+ return value;
2399
+ }
2400
+ });
2372
2401
  }
2373
2402
  function createWrappedChat(provider, middlewares) {
2374
2403
  return async (options) => {
@@ -2517,35 +2546,35 @@ var FallbackProvider = class {
2517
2546
  }
2518
2547
  // --- Multi-modal: delegate to first provider that supports the capability ---
2519
2548
  get generateImage() {
2520
- const provider = this.providers.find((p) => p.generateImage);
2549
+ const provider = this.providers.find((p) => typeof p.generateImage === "function");
2521
2550
  return provider?.generateImage?.bind(provider);
2522
2551
  }
2523
2552
  get editImage() {
2524
- const provider = this.providers.find((p) => p.editImage);
2553
+ const provider = this.providers.find((p) => typeof p.editImage === "function");
2525
2554
  return provider?.editImage?.bind(provider);
2526
2555
  }
2527
2556
  get analyzeImage() {
2528
- const provider = this.providers.find((p) => p.analyzeImage);
2557
+ const provider = this.providers.find((p) => typeof p.analyzeImage === "function");
2529
2558
  return provider?.analyzeImage?.bind(provider);
2530
2559
  }
2531
2560
  get generateSpeech() {
2532
- const provider = this.providers.find((p) => p.generateSpeech);
2561
+ const provider = this.providers.find((p) => typeof p.generateSpeech === "function");
2533
2562
  return provider?.generateSpeech?.bind(provider);
2534
2563
  }
2535
2564
  get transcribeAudio() {
2536
- const provider = this.providers.find((p) => p.transcribeAudio);
2565
+ const provider = this.providers.find((p) => typeof p.transcribeAudio === "function");
2537
2566
  return provider?.transcribeAudio?.bind(provider);
2538
2567
  }
2539
2568
  get generateVideo() {
2540
- const provider = this.providers.find((p) => p.generateVideo);
2569
+ const provider = this.providers.find((p) => typeof p.generateVideo === "function");
2541
2570
  return provider?.generateVideo?.bind(provider);
2542
2571
  }
2543
2572
  get analyzeVideo() {
2544
- const provider = this.providers.find((p) => p.analyzeVideo);
2573
+ const provider = this.providers.find((p) => typeof p.analyzeVideo === "function");
2545
2574
  return provider?.analyzeVideo?.bind(provider);
2546
2575
  }
2547
2576
  get embed() {
2548
- const provider = this.providers.find((p) => p.embed);
2577
+ const provider = this.providers.find((p) => typeof p.embed === "function");
2549
2578
  return provider?.embed?.bind(provider);
2550
2579
  }
2551
2580
  /**
@@ -2572,174 +2601,7 @@ var FallbackProvider = class {
2572
2601
  }
2573
2602
  };
2574
2603
 
2575
- // src/core/convex.ts
2576
- var import_child_process = require("child_process");
2577
- var MANAGEMENT_API = "https://api.convex.dev/v1";
2578
- var ConvexManager = class {
2579
- constructor(options = {}) {
2580
- this.accessToken = options.accessToken || process.env.CONVEX_ACCESS_TOKEN || "";
2581
- this.teamId = options.teamId || process.env.CONVEX_TEAM_ID;
2582
- if (!this.accessToken) {
2583
- throw new Error(
2584
- "ConvexManager requires an access token. Pass accessToken in options or set CONVEX_ACCESS_TOKEN env var."
2585
- );
2586
- }
2587
- }
2588
- // ─── Project Lifecycle ──────────────────────────────────────────────
2589
- /**
2590
- * Create a new Convex project (includes an initial deployment).
2591
- */
2592
- async createProject(name, options = {}) {
2593
- const teamId = await this.resolveTeamId();
2594
- const body = {
2595
- projectName: name,
2596
- deploymentType: options.deploymentType || "prod"
2597
- };
2598
- if (options.region) {
2599
- body.deploymentRegion = options.region;
2600
- }
2601
- return this.request(
2602
- `${MANAGEMENT_API}/teams/${teamId}/create_project`,
2603
- { method: "POST", body }
2604
- );
2605
- }
2606
- /**
2607
- * List all projects for the team.
2608
- */
2609
- async listProjects() {
2610
- const teamId = await this.resolveTeamId();
2611
- return this.request(
2612
- `${MANAGEMENT_API}/teams/${teamId}/list_projects`
2613
- );
2614
- }
2615
- /**
2616
- * Delete a project by ID.
2617
- */
2618
- async deleteProject(projectId) {
2619
- await this.request(
2620
- `${MANAGEMENT_API}/projects/${projectId}`,
2621
- { method: "DELETE" }
2622
- );
2623
- }
2624
- // ─── Deployment Management ──────────────────────────────────────────
2625
- /**
2626
- * Generate a deploy key for a deployment (needed for schema push / deploy).
2627
- */
2628
- async createDeployKey(deploymentName) {
2629
- const result = await this.request(
2630
- `${MANAGEMENT_API}/deployments/${deploymentName}/create_deploy_key`,
2631
- { method: "POST", body: { name: "sdk-provisioned" } }
2632
- );
2633
- return result.deployKey;
2634
- }
2635
- /**
2636
- * Set environment variables on a deployment (bulk upsert).
2637
- */
2638
- async setEnvVars(deploymentName, vars) {
2639
- await this.request(
2640
- `https://${deploymentName}.convex.cloud/api/v1/update_environment_variables`,
2641
- {
2642
- method: "POST",
2643
- body: { changes: vars },
2644
- authStyle: "deploy"
2645
- }
2646
- );
2647
- }
2648
- /**
2649
- * List environment variables on a deployment.
2650
- */
2651
- async getEnvVars(deploymentName) {
2652
- return this.request(
2653
- `https://${deploymentName}.convex.cloud/api/v1/list_environment_variables`,
2654
- { authStyle: "deploy" }
2655
- );
2656
- }
2657
- /**
2658
- * Push Convex functions and schema to a deployment.
2659
- * Shells out to `npx convex deploy` with the given deploy key.
2660
- */
2661
- deploy(deployKey, options = {}) {
2662
- const cwd = options.projectDir || process.cwd();
2663
- const flags = options.flags?.join(" ") || "";
2664
- const cmd = `npx convex deploy --cmd-url-env-var-name CONVEX_URL ${flags}`.trim();
2665
- (0, import_child_process.execSync)(cmd, {
2666
- cwd,
2667
- stdio: "inherit",
2668
- env: {
2669
- ...process.env,
2670
- CONVEX_DEPLOY_KEY: deployKey
2671
- }
2672
- });
2673
- }
2674
- // ─── Discovery ──────────────────────────────────────────────────────
2675
- /**
2676
- * Resolve token details (type, teamId, name) from the access token.
2677
- */
2678
- async getTokenDetails() {
2679
- return this.request(
2680
- `${MANAGEMENT_API}/token_details`
2681
- );
2682
- }
2683
- /**
2684
- * List available deployment regions.
2685
- */
2686
- async getRegions() {
2687
- const result = await this.request(
2688
- `${MANAGEMENT_API}/deployment_regions`
2689
- );
2690
- return result.items;
2691
- }
2692
- /**
2693
- * 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.
2698
- *
2699
- * @see https://docs.convex.dev/client/open-api
2700
- */
2701
- generateOpenAPISpec(options = {}) {
2702
- const cwd = options.projectDir || process.cwd();
2703
- const output = options.output || "convex-spec.yaml";
2704
- const extraFlags = options.flags?.join(" ") || "";
2705
- const cmd = `npx convex-helpers open-api-spec --output ${output} ${extraFlags}`.trim();
2706
- (0, import_child_process.execSync)(cmd, {
2707
- cwd,
2708
- stdio: "inherit"
2709
- });
2710
- }
2711
- // ─── Internal Helpers ───────────────────────────────────────────────
2712
- async resolveTeamId() {
2713
- if (this.teamId) return this.teamId;
2714
- const details = await this.getTokenDetails();
2715
- this.teamId = details.teamId;
2716
- return this.teamId;
2717
- }
2718
- async request(url, options = {}) {
2719
- const { method = "GET", body, authStyle = "bearer" } = options;
2720
- const headers = {
2721
- "Content-Type": "application/json",
2722
- Authorization: authStyle === "deploy" ? `Convex ${this.accessToken}` : `Bearer ${this.accessToken}`
2723
- };
2724
- const res = await fetch(url, {
2725
- method,
2726
- headers,
2727
- body: body ? JSON.stringify(body) : void 0
2728
- });
2729
- if (!res.ok) {
2730
- const text2 = await res.text().catch(() => "");
2731
- throw new Error(
2732
- `Convex API error (${res.status} ${res.statusText}): ${text2}`
2733
- );
2734
- }
2735
- const text = await res.text();
2736
- if (!text) return void 0;
2737
- return JSON.parse(text);
2738
- }
2739
- };
2740
-
2741
2604
  // src/core/cache.ts
2742
- var import_crypto = require("crypto");
2743
2605
  var ResponseCache = class {
2744
2606
  constructor(redis, options = {}) {
2745
2607
  this.redis = redis;
@@ -2762,7 +2624,11 @@ var ResponseCache = class {
2762
2624
  }
2763
2625
  defaultKeyFn(model, messages) {
2764
2626
  const payload = JSON.stringify({ model, messages });
2765
- return (0, import_crypto.createHash)("sha256").update(payload).digest("hex");
2627
+ let hash = 5381;
2628
+ for (let i = 0; i < payload.length; i++) {
2629
+ hash = (hash << 5) + hash + payload.charCodeAt(i);
2630
+ }
2631
+ return (hash >>> 0).toString(16);
2766
2632
  }
2767
2633
  };
2768
2634
  var RateLimiter = class {
@@ -2859,28 +2725,55 @@ var SessionStore = class {
2859
2725
 
2860
2726
  // src/namespaces/text.ts
2861
2727
  var TextNamespace = class {
2862
- constructor(provider) {
2728
+ constructor(provider, plugins = []) {
2863
2729
  this.provider = provider;
2730
+ this.plugins = plugins;
2731
+ }
2732
+ async runBeforeRequest(options) {
2733
+ let context = {
2734
+ model: options.model,
2735
+ messages: [...options.messages],
2736
+ timestamp: Date.now(),
2737
+ requestOptions: { ...options }
2738
+ };
2739
+ for (const plugin of this.plugins) {
2740
+ if (plugin.beforeRequest) {
2741
+ const updated = await plugin.beforeRequest(context);
2742
+ if (updated) context = updated;
2743
+ }
2744
+ }
2745
+ return context;
2864
2746
  }
2865
2747
  /**
2866
2748
  * Generate text from a prompt (Chat Completion).
2867
2749
  */
2868
2750
  async generate(options) {
2869
- return this.provider.chat(options);
2751
+ const context = await this.runBeforeRequest(options);
2752
+ const activeOptions = { ...options, messages: context.messages, model: context.model };
2753
+ const result = await this.provider.chat(activeOptions);
2754
+ for (const plugin of this.plugins) {
2755
+ if (plugin.afterResponse) await plugin.afterResponse(context, result);
2756
+ }
2757
+ return result;
2870
2758
  }
2871
2759
  /**
2872
2760
  * Stream text generation.
2873
2761
  */
2874
2762
  async *generateStream(options) {
2875
- for await (const chunk of this.provider.chatStream(options)) {
2763
+ const context = await this.runBeforeRequest(options);
2764
+ const activeOptions = { ...options, messages: context.messages, model: context.model };
2765
+ for await (const chunk of this.provider.chatStream(activeOptions)) {
2766
+ for (const plugin of this.plugins) {
2767
+ if (plugin.onStreamChunk) plugin.onStreamChunk(context, chunk);
2768
+ }
2876
2769
  yield chunk;
2877
2770
  }
2878
2771
  }
2879
2772
  /**
2880
- * Generate embeddings for text input(s).
2773
+ * Generate embeddings for text input(s). Only available if the provider supports embeddings.
2881
2774
  */
2882
2775
  async embed(options) {
2883
- if (!this.provider.embed) {
2776
+ if (!("embed" in this.provider)) {
2884
2777
  throw new Error(`Provider '${this.provider.name}' does not support embeddings`);
2885
2778
  }
2886
2779
  return this.provider.embed(options);
@@ -2902,28 +2795,28 @@ var ImagesNamespace = class {
2902
2795
  this.provider = provider;
2903
2796
  }
2904
2797
  /**
2905
- * Generate images from a prompt.
2798
+ * Generate images from a prompt. Only available if the provider supports image generation.
2906
2799
  */
2907
2800
  async generate(options) {
2908
- if (!this.provider.generateImage) {
2801
+ if (!("generateImage" in this.provider)) {
2909
2802
  throw new Error(`Provider '${this.provider.name}' does not support image generation`);
2910
2803
  }
2911
2804
  return this.provider.generateImage(options);
2912
2805
  }
2913
2806
  /**
2914
- * Edit an image with a prompt.
2807
+ * Edit an image with a prompt. Only available if the provider supports image editing.
2915
2808
  */
2916
2809
  async edit(options) {
2917
- if (!this.provider.editImage) {
2810
+ if (!("editImage" in this.provider)) {
2918
2811
  throw new Error(`Provider '${this.provider.name}' does not support image editing`);
2919
2812
  }
2920
2813
  return this.provider.editImage(options);
2921
2814
  }
2922
2815
  /**
2923
- * Analyze an image (Vision).
2816
+ * Analyze an image (Vision). Only available if the provider supports vision analytics.
2924
2817
  */
2925
2818
  async analyze(options) {
2926
- if (!this.provider.analyzeImage) {
2819
+ if (!("analyzeImage" in this.provider)) {
2927
2820
  throw new Error(`Provider '${this.provider.name}' does not support image analysis`);
2928
2821
  }
2929
2822
  return this.provider.analyzeImage(options);
@@ -2936,19 +2829,19 @@ var AudioNamespace = class {
2936
2829
  this.provider = provider;
2937
2830
  }
2938
2831
  /**
2939
- * Convert text to speech.
2832
+ * Convert text to speech. Only available if the provider supports TTS.
2940
2833
  */
2941
2834
  async speak(options) {
2942
- if (!this.provider.generateSpeech) {
2835
+ if (!("generateSpeech" in this.provider)) {
2943
2836
  throw new Error(`Provider '${this.provider.name}' does not support speech generation`);
2944
2837
  }
2945
2838
  return this.provider.generateSpeech(options);
2946
2839
  }
2947
2840
  /**
2948
- * Transcribe audio to text.
2841
+ * Transcribe audio to text. Only available if the provider supports STT.
2949
2842
  */
2950
2843
  async transcribe(options) {
2951
- if (!this.provider.transcribeAudio) {
2844
+ if (!("transcribeAudio" in this.provider)) {
2952
2845
  throw new Error(`Provider '${this.provider.name}' does not support audio transcription`);
2953
2846
  }
2954
2847
  return this.provider.transcribeAudio(options);
@@ -2961,19 +2854,19 @@ var VideosNamespace = class {
2961
2854
  this.provider = provider;
2962
2855
  }
2963
2856
  /**
2964
- * Generate a video from a prompt.
2857
+ * Generate a video from a prompt. Only available if the provider supports video generation.
2965
2858
  */
2966
2859
  async generate(options) {
2967
- if (!this.provider.generateVideo) {
2860
+ if (!("generateVideo" in this.provider)) {
2968
2861
  throw new Error(`Provider '${this.provider.name}' does not support video generation`);
2969
2862
  }
2970
2863
  return this.provider.generateVideo(options);
2971
2864
  }
2972
2865
  /**
2973
- * Analyze a video (Video-to-Text).
2866
+ * Analyze a video (Video-to-Text). Only available if the provider supports video analysis.
2974
2867
  */
2975
2868
  async analyze(options) {
2976
- if (!this.provider.analyzeVideo) {
2869
+ if (!("analyzeVideo" in this.provider)) {
2977
2870
  throw new Error(`Provider '${this.provider.name}' does not support video analysis`);
2978
2871
  }
2979
2872
  return this.provider.analyzeVideo(options);
@@ -2984,7 +2877,11 @@ var VideosNamespace = class {
2984
2877
  var Tekimax = class {
2985
2878
  constructor(options) {
2986
2879
  this.provider = options.provider;
2987
- this.text = new TextNamespace(this.provider);
2880
+ this.plugins = options.plugins || [];
2881
+ for (const plugin of this.plugins) {
2882
+ if (plugin.onInit) plugin.onInit(this);
2883
+ }
2884
+ this.text = new TextNamespace(this.provider, this.plugins);
2988
2885
  this.images = new ImagesNamespace(this.provider);
2989
2886
  this.audio = new AudioNamespace(this.provider);
2990
2887
  this.videos = new VideosNamespace(this.provider);
@@ -2996,17 +2893,87 @@ var Tekimax = class {
2996
2893
  return this.text.chat;
2997
2894
  }
2998
2895
  };
2896
+
2897
+ // src/plugins/logger.ts
2898
+ var LoggerPlugin = class {
2899
+ constructor() {
2900
+ this.name = "LoggerPlugin";
2901
+ }
2902
+ onInit() {
2903
+ console.log("[LoggerPlugin] Tekimax SDK initialized with Logger Plugin active.");
2904
+ }
2905
+ async beforeRequest(context) {
2906
+ console.log(`[LoggerPlugin] Sending request to model: ${context.model} (${context.messages.length} messages)`);
2907
+ }
2908
+ async afterResponse(context, result) {
2909
+ console.log(`[LoggerPlugin] Received completion from ${context.model}. Usage:`, result.usage);
2910
+ }
2911
+ onStreamChunk(context, chunk) {
2912
+ if (chunk.usage) {
2913
+ console.log(`[LoggerPlugin] Stream completed. Final usage:`, chunk.usage);
2914
+ }
2915
+ }
2916
+ async beforeToolExecute(toolName, args) {
2917
+ console.log(`[LoggerPlugin] Executing tool '${toolName}' with args:`, args);
2918
+ }
2919
+ async afterToolExecute(toolName, result) {
2920
+ console.log(`[LoggerPlugin] Tool '${toolName}' returned successfully.`);
2921
+ }
2922
+ };
2923
+
2924
+ // src/plugins/pii.ts
2925
+ var PIIFilterPlugin = class {
2926
+ constructor() {
2927
+ this.name = "PIIFilterPlugin";
2928
+ this.patterns = {
2929
+ email: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,
2930
+ ssn: /\b\d{3}-\d{2}-\d{4}\b/g
2931
+ };
2932
+ }
2933
+ async beforeRequest(context) {
2934
+ context.messages = context.messages.map((msg) => {
2935
+ if (typeof msg.content === "string") {
2936
+ let safeContent = msg.content;
2937
+ safeContent = safeContent.replace(this.patterns.email, "[REDACTED EMAIL]");
2938
+ safeContent = safeContent.replace(this.patterns.ssn, "[REDACTED SSN]");
2939
+ return { ...msg, content: safeContent };
2940
+ }
2941
+ return msg;
2942
+ });
2943
+ return context;
2944
+ }
2945
+ };
2946
+
2947
+ // src/plugins/context.ts
2948
+ var MaxContextOverflowPlugin = class {
2949
+ constructor(maxMessages = 20) {
2950
+ this.maxMessages = maxMessages;
2951
+ this.name = "MaxContextOverflowPlugin";
2952
+ }
2953
+ async beforeRequest(context) {
2954
+ if (context.messages.length > this.maxMessages) {
2955
+ const hasSystem = context.messages[0]?.role === "system";
2956
+ const systemMsg = hasSystem ? context.messages[0] : null;
2957
+ const recentMsgs = context.messages.slice(-(this.maxMessages - (hasSystem ? 1 : 0)));
2958
+ context.messages = hasSystem && systemMsg ? [systemMsg, ...recentMsgs] : recentMsgs;
2959
+ console.warn(`[MaxContextOverflowPlugin] Truncated chat history to ${this.maxMessages} messages to preserve context limits.`);
2960
+ }
2961
+ return context;
2962
+ }
2963
+ };
2999
2964
  // Annotate the CommonJS export names for ESM import in node:
3000
2965
  0 && (module.exports = {
3001
2966
  AnthropicProvider,
3002
2967
  ApiTypes,
3003
- ConvexManager,
3004
2968
  FallbackProvider,
3005
2969
  GeminiProvider,
3006
2970
  GrokProvider,
2971
+ LoggerPlugin,
2972
+ MaxContextOverflowPlugin,
3007
2973
  OllamaProvider,
3008
2974
  OpenAIProvider,
3009
2975
  OpenRouterProvider,
2976
+ PIIFilterPlugin,
3010
2977
  RateLimiter,
3011
2978
  ResponseCache,
3012
2979
  SessionStore,