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 +40 -1
- package/dist/api/knowledge.d.ts +4 -1
- package/dist/api/knowledge.js +36 -6
- package/dist/index.js +0 -5
- package/dist/utils/analytics.js +0 -5
- package/package.json +1 -1
- package/src/App.tsx +38 -0
- package/src/api/knowledge.ts +42 -7
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]"}'
|
package/dist/api/knowledge.d.ts
CHANGED
|
@@ -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<
|
|
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;
|
package/dist/api/knowledge.js
CHANGED
|
@@ -41,14 +41,44 @@ export async function checkKnowledge(folderPath = '.') {
|
|
|
41
41
|
}
|
|
42
42
|
export async function importKnowledge(agentId, knowledgeData) {
|
|
43
43
|
try {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
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
|
}
|
package/dist/utils/analytics.js
CHANGED
|
@@ -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
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') {
|
package/src/api/knowledge.ts
CHANGED
|
@@ -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
|
-
|
|
52
|
-
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|