@retrivora-ai/rag-engine 2.2.9 → 2.3.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.
@@ -7,6 +7,7 @@ import { IngestDocument, ChatResponse } from '../types';
7
7
  import { ChatMessage } from '../types';
8
8
  import { LicenseVerifier } from './LicenseVerifier';
9
9
  import { wrapError, RetrivoraErrorCode } from '../exceptions';
10
+ import { FreeTierLimitsGuard } from './FreeTierLimitsGuard';
10
11
 
11
12
  /**
12
13
  * VectorPlugin — main orchestrator class.
@@ -78,6 +79,13 @@ export class VectorPlugin {
78
79
  );
79
80
  }
80
81
 
82
+ private estimateInputTokens(message: string, history: ChatMessage[] = []): number {
83
+ const allContent =
84
+ message.length +
85
+ history.reduce((acc, m) => acc + ((m as any)?.content?.length || (m as any)?.text?.length || 0), 0);
86
+ return Math.ceil(allContent / 4);
87
+ }
88
+
81
89
  /**
82
90
  * Run a chat query.
83
91
  */
@@ -88,6 +96,14 @@ export class VectorPlugin {
88
96
  throw wrapError(err, 'CONFIGURATION_ERROR');
89
97
  }
90
98
  try {
99
+ const inputTokens = this.estimateInputTokens(message, history);
100
+ const tokenCheck = (FreeTierLimitsGuard as any).checkRequestAllowed({
101
+ operationType: 'chat',
102
+ inputTokens,
103
+ });
104
+ if (!tokenCheck.allowed && tokenCheck.reason?.toLowerCase().includes('token')) {
105
+ throw wrapError(new Error(tokenCheck.reason), 'RATE_LIMITED');
106
+ }
91
107
  return await this.pipeline.ask(message, history, namespace);
92
108
  } catch (err) {
93
109
  const msg = String(err);
@@ -95,6 +111,9 @@ export class VectorPlugin {
95
111
  if (msg.includes('Embed') || msg.includes('embed')) {
96
112
  defaultCode = 'EMBEDDING_FAILED';
97
113
  }
114
+ if (msg.toLowerCase().includes('token limit')) {
115
+ defaultCode = 'RATE_LIMITED';
116
+ }
98
117
  throw wrapError(err, defaultCode);
99
118
  }
100
119
  }
@@ -109,6 +128,14 @@ export class VectorPlugin {
109
128
  throw wrapError(err, 'CONFIGURATION_ERROR');
110
129
  }
111
130
  try {
131
+ const inputTokens = this.estimateInputTokens(message, history);
132
+ const tokenCheck = (FreeTierLimitsGuard as any).checkRequestAllowed({
133
+ operationType: 'chat_stream',
134
+ inputTokens,
135
+ });
136
+ if (!tokenCheck.allowed && tokenCheck.reason?.toLowerCase().includes('token')) {
137
+ throw wrapError(new Error(tokenCheck.reason), 'RATE_LIMITED');
138
+ }
112
139
  const stream = this.pipeline.askStream(message, history, namespace);
113
140
  for await (const chunk of stream) {
114
141
  yield chunk;
@@ -119,6 +146,9 @@ export class VectorPlugin {
119
146
  if (msg.includes('Embed') || msg.includes('embed')) {
120
147
  defaultCode = 'EMBEDDING_FAILED';
121
148
  }
149
+ if (msg.toLowerCase().includes('token limit')) {
150
+ defaultCode = 'RATE_LIMITED';
151
+ }
122
152
  throw wrapError(err, defaultCode);
123
153
  }
124
154
  }