rippletide 1.0.13 → 1.0.14

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/App.js CHANGED
@@ -299,6 +299,46 @@ export const App = ({ backendUrl, dashboardUrl, nonInteractive, agentEndpoint: i
299
299
  setCurrentAgentId(agentId);
300
300
  }
301
301
  setEvaluationProgress(30);
302
+ if (knowledgeSource === 'files') {
303
+ let knowledgeData = null;
304
+ if (templatePath) {
305
+ try {
306
+ const fs = await import('fs');
307
+ const path = await import('path');
308
+ const qandaPath = path.join(templatePath, 'qanda.json');
309
+ if (fs.existsSync(qandaPath)) {
310
+ knowledgeData = JSON.parse(fs.readFileSync(qandaPath, 'utf-8'));
311
+ }
312
+ }
313
+ catch (error) {
314
+ logger.debug('Error loading knowledge from template:', error);
315
+ }
316
+ }
317
+ else {
318
+ const knowledgeResult = await api.checkKnowledge();
319
+ if (knowledgeResult.found && knowledgeResult.path) {
320
+ try {
321
+ const fs = await import('fs');
322
+ knowledgeData = JSON.parse(fs.readFileSync(knowledgeResult.path, 'utf-8'));
323
+ }
324
+ catch (error) {
325
+ logger.debug('Error loading knowledge:', error);
326
+ }
327
+ }
328
+ }
329
+ if (knowledgeData) {
330
+ setEvaluationProgress(35);
331
+ try {
332
+ const importResult = await api.importKnowledge(agentId, knowledgeData);
333
+ logger.debug('Knowledge import result:', importResult);
334
+ await new Promise(resolve => setTimeout(resolve, 1000));
335
+ }
336
+ catch (error) {
337
+ logger.error('Failed to import knowledge:', error?.message || error);
338
+ logger.debug('Import error details:', error?.response?.data);
339
+ }
340
+ }
341
+ }
302
342
  setEvaluationProgress(40);
303
343
  let testPrompts = [];
304
344
  if (knowledgeSource === 'files') {
@@ -365,7 +405,6 @@ export const App = ({ backendUrl, dashboardUrl, nonInteractive, agentEndpoint: i
365
405
  }
366
406
  const createdPrompts = await api.addTestPrompts(agentId, testPrompts);
367
407
  setEvaluationProgress(50);
368
- // Ensure customConfig has the body template for evaluation
369
408
  const evalConfig = {
370
409
  ...customConfig,
371
410
  bodyTemplate: customConfig.bodyTemplate || '{"message": "[eval-question]"}'
@@ -7,7 +7,10 @@ export declare function checkKnowledge(folderPath?: string): Promise<{
7
7
  found: boolean;
8
8
  path?: undefined;
9
9
  }>;
10
- export declare function importKnowledge(agentId: string, knowledgeData: any): Promise<any>;
10
+ export declare function importKnowledge(agentId: string, knowledgeData: any): Promise<{
11
+ imported: number;
12
+ total: number;
13
+ } | null>;
11
14
  export declare function getTestResults(agentId: string): Promise<any>;
12
15
  export interface EvaluationConfig {
13
16
  agentEndpoint: string;
@@ -41,14 +41,44 @@ export async function checkKnowledge(folderPath = '.') {
41
41
  }
42
42
  export async function importKnowledge(agentId, knowledgeData) {
43
43
  try {
44
- const response = await client.post(`/api/agents/${agentId}/knowledge/import`, {
45
- data: knowledgeData,
46
- });
47
- return response.data;
44
+ logger.debug('Importing knowledge for agent:', agentId);
45
+ logger.debug('Knowledge data type:', Array.isArray(knowledgeData) ? 'array' : typeof knowledgeData);
46
+ logger.debug('Knowledge data length:', Array.isArray(knowledgeData) ? knowledgeData.length : 'N/A');
47
+ if (!Array.isArray(knowledgeData)) {
48
+ logger.warn('Knowledge data is not an array, skipping import');
49
+ return null;
50
+ }
51
+ let importedCount = 0;
52
+ for (const item of knowledgeData) {
53
+ try {
54
+ const question = item.question || item.prompt || item.input;
55
+ const answer = item.answer || item.response || item.expectedAnswer;
56
+ if (!question || !answer) {
57
+ logger.debug('Skipping item without question or answer:', item);
58
+ continue;
59
+ }
60
+ const response = await client.post(`/api/agents/${agentId}/config`, {
61
+ label: question,
62
+ description: answer,
63
+ type: 'knowledge'
64
+ });
65
+ importedCount++;
66
+ logger.debug(`Imported Q&A ${importedCount}/${knowledgeData.length}: ${question.substring(0, 50)}...`);
67
+ }
68
+ catch (error) {
69
+ logger.warn(`Failed to import Q&A pair: ${error?.message || error}`);
70
+ logger.debug('Q&A import error details:', error?.response?.data);
71
+ logger.debug('Q&A import error status:', error?.response?.status);
72
+ }
73
+ }
74
+ logger.info(`Knowledge imported successfully: ${importedCount}/${knowledgeData.length} Q&A pairs`);
75
+ return { imported: importedCount, total: knowledgeData.length };
48
76
  }
49
77
  catch (error) {
50
- logger.error('Error importing knowledge:', error);
51
- return null;
78
+ logger.error('Error importing knowledge:', error?.message || error);
79
+ logger.debug('Error details:', error?.response?.data);
80
+ logger.debug('Error status:', error?.response?.status);
81
+ throw error;
52
82
  }
53
83
  }
54
84
  export async function getTestResults(agentId) {
package/dist/index.js CHANGED
@@ -185,13 +185,11 @@ Examples:
185
185
  async function run() {
186
186
  try {
187
187
  const options = parseArgs();
188
- // Check if this is a new user
189
188
  const fs = await import('fs');
190
189
  const path = await import('path');
191
190
  const os = await import('os');
192
191
  const configPath = path.join(os.homedir(), '.rippletide', 'config.json');
193
192
  const isNewUser = !fs.existsSync(configPath);
194
- // Track start event and wait for it to be sent
195
193
  analytics.track('cli_started', {
196
194
  command: process.argv[2] || 'eval',
197
195
  has_template: !!options.templatePath,
@@ -199,19 +197,16 @@ async function run() {
199
197
  is_non_interactive: options.nonInteractive,
200
198
  is_new_user: isNewUser,
201
199
  });
202
- // Track new user activation separately
203
200
  if (isNewUser) {
204
201
  analytics.track('new_user_activated', {
205
202
  source: process.argv[2] || 'eval',
206
203
  activation_date: new Date().toISOString(),
207
204
  });
208
205
  }
209
- // Give PostHog a moment to send the event
210
206
  await new Promise(resolve => setTimeout(resolve, 100));
211
207
  process.stdout.write('\x1Bc');
212
208
  const { waitUntilExit } = render(React.createElement(App, { backendUrl: options.backendUrl, dashboardUrl: options.dashboardUrl, nonInteractive: options.nonInteractive, agentEndpoint: options.agentEndpoint, knowledgeSource: options.knowledgeSource, pineconeUrl: options.pineconeUrl, pineconeApiKey: options.pineconeApiKey, postgresqlConnection: options.postgresqlConnection, customHeaders: options.headers, customBodyTemplate: options.bodyTemplate, customResponseField: options.responseField, templatePath: options.templatePath, pdfPath: options.pdfPath }));
213
209
  await waitUntilExit();
214
- // Ensure all events are sent before exiting
215
210
  await analytics.shutdown();
216
211
  await new Promise(resolve => setTimeout(resolve, 500));
217
212
  }
@@ -33,7 +33,6 @@ class Analytics {
33
33
  if (process.env.DEBUG_ANALYTICS) {
34
34
  console.log('[Analytics] Client initialized with ID:', this.distinctId);
35
35
  }
36
- // Force flush on various exit events
37
36
  const cleanup = () => {
38
37
  if (this.client) {
39
38
  this.client.shutdown();
@@ -149,13 +148,11 @@ class Analytics {
149
148
  const config = this.getConfig();
150
149
  const firstSeen = config.first_seen || new Date().toISOString();
151
150
  const totalLaunches = (config.total_launches || 0) + 1;
152
- // Save first seen and increment launch count
153
151
  this.saveConfig({
154
152
  ...config,
155
153
  first_seen: firstSeen,
156
154
  total_launches: totalLaunches
157
155
  });
158
- // Identify the user with persistent properties
159
156
  this.client.identify({
160
157
  distinctId: this.distinctId,
161
158
  properties: {
@@ -168,7 +165,6 @@ class Analytics {
168
165
  hostname_hash: createHash('sha256').update(os.hostname()).digest('hex').substring(0, 8),
169
166
  },
170
167
  });
171
- // Also set these as super properties for all events
172
168
  this.client.capture({
173
169
  distinctId: this.distinctId,
174
170
  event: '$set',
@@ -200,7 +196,6 @@ class Analytics {
200
196
  });
201
197
  }
202
198
  catch (error) {
203
- // Silently fail
204
199
  }
205
200
  }
206
201
  async shutdown() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rippletide",
3
- "version": "1.0.13",
3
+ "version": "1.0.14",
4
4
  "description": "Rippletide Evaluation CLI",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/App.tsx CHANGED
@@ -368,6 +368,44 @@ export const App: React.FC<AppProps> = ({
368
368
 
369
369
  setEvaluationProgress(30);
370
370
 
371
+ if (knowledgeSource === 'files') {
372
+ let knowledgeData: any = null;
373
+ if (templatePath) {
374
+ try {
375
+ const fs = await import('fs');
376
+ const path = await import('path');
377
+ const qandaPath = path.join(templatePath, 'qanda.json');
378
+ if (fs.existsSync(qandaPath)) {
379
+ knowledgeData = JSON.parse(fs.readFileSync(qandaPath, 'utf-8'));
380
+ }
381
+ } catch (error) {
382
+ logger.debug('Error loading knowledge from template:', error);
383
+ }
384
+ } else {
385
+ const knowledgeResult = await api.checkKnowledge();
386
+ if (knowledgeResult.found && knowledgeResult.path) {
387
+ try {
388
+ const fs = await import('fs');
389
+ knowledgeData = JSON.parse(fs.readFileSync(knowledgeResult.path, 'utf-8'));
390
+ } catch (error) {
391
+ logger.debug('Error loading knowledge:', error);
392
+ }
393
+ }
394
+ }
395
+
396
+ if (knowledgeData) {
397
+ setEvaluationProgress(35);
398
+ try {
399
+ const importResult = await api.importKnowledge(agentId, knowledgeData);
400
+ logger.debug('Knowledge import result:', importResult);
401
+ await new Promise(resolve => setTimeout(resolve, 1000));
402
+ } catch (error: any) {
403
+ logger.error('Failed to import knowledge:', error?.message || error);
404
+ logger.debug('Import error details:', error?.response?.data);
405
+ }
406
+ }
407
+ }
408
+
371
409
  setEvaluationProgress(40);
372
410
  let testPrompts: Array<{question: string, answer?: string}> | string[] = [];
373
411
  if (knowledgeSource === 'files') {
@@ -48,14 +48,49 @@ export async function checkKnowledge(folderPath: string = '.') {
48
48
 
49
49
  export async function importKnowledge(agentId: string, knowledgeData: any) {
50
50
  try {
51
- const response = await client.post(`/api/agents/${agentId}/knowledge/import`, {
52
- data: knowledgeData,
53
- });
51
+ logger.debug('Importing knowledge for agent:', agentId);
52
+ logger.debug('Knowledge data type:', Array.isArray(knowledgeData) ? 'array' : typeof knowledgeData);
53
+ logger.debug('Knowledge data length:', Array.isArray(knowledgeData) ? knowledgeData.length : 'N/A');
54
54
 
55
- return response.data;
56
- } catch (error) {
57
- logger.error('Error importing knowledge:', error);
58
- return null;
55
+ if (!Array.isArray(knowledgeData)) {
56
+ logger.warn('Knowledge data is not an array, skipping import');
57
+ return null;
58
+ }
59
+
60
+ let importedCount = 0;
61
+ for (const item of knowledgeData) {
62
+ try {
63
+ const question = item.question || item.prompt || item.input;
64
+ const answer = item.answer || item.response || item.expectedAnswer;
65
+
66
+ if (!question || !answer) {
67
+ logger.debug('Skipping item without question or answer:', item);
68
+ continue;
69
+ }
70
+
71
+ const response = await client.post(`/api/agents/${agentId}/config`, {
72
+ label: question,
73
+ description: answer,
74
+ type: 'knowledge'
75
+ });
76
+
77
+ importedCount++;
78
+ logger.debug(`Imported Q&A ${importedCount}/${knowledgeData.length}: ${question.substring(0, 50)}...`);
79
+ } catch (error: any) {
80
+ logger.warn(`Failed to import Q&A pair: ${error?.message || error}`);
81
+ logger.debug('Q&A import error details:', error?.response?.data);
82
+ logger.debug('Q&A import error status:', error?.response?.status);
83
+ }
84
+ }
85
+
86
+ logger.info(`Knowledge imported successfully: ${importedCount}/${knowledgeData.length} Q&A pairs`);
87
+
88
+ return { imported: importedCount, total: knowledgeData.length };
89
+ } catch (error: any) {
90
+ logger.error('Error importing knowledge:', error?.message || error);
91
+ logger.debug('Error details:', error?.response?.data);
92
+ logger.debug('Error status:', error?.response?.status);
93
+ throw error;
59
94
  }
60
95
  }
61
96