wauldo 0.6.0 → 0.7.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 +9 -36
- package/dist/index.d.mts +39 -176
- package/dist/index.d.ts +39 -176
- package/dist/index.js +44 -278
- package/dist/index.mjs +41 -277
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -864,16 +864,6 @@ async function* parseSSEStream(body) {
|
|
|
864
864
|
}
|
|
865
865
|
|
|
866
866
|
// src/http_client.ts
|
|
867
|
-
function concatUint8Arrays(arrays) {
|
|
868
|
-
const total = arrays.reduce((n, a) => n + a.length, 0);
|
|
869
|
-
const result = new Uint8Array(total);
|
|
870
|
-
let offset = 0;
|
|
871
|
-
for (const a of arrays) {
|
|
872
|
-
result.set(a, offset);
|
|
873
|
-
offset += a.length;
|
|
874
|
-
}
|
|
875
|
-
return result;
|
|
876
|
-
}
|
|
877
867
|
function validateResponse(data, typeName) {
|
|
878
868
|
if (data === null || data === void 0) {
|
|
879
869
|
throw new ServerError(`Invalid ${typeName}: response is null`, 0);
|
|
@@ -1008,51 +998,6 @@ var HttpClient = class {
|
|
|
1008
998
|
);
|
|
1009
999
|
return validateResponse(data, "RagUploadResponse");
|
|
1010
1000
|
}
|
|
1011
|
-
/**
|
|
1012
|
-
* POST /v1/upload-file — Upload a file (PDF, DOCX, text, image) for RAG indexing.
|
|
1013
|
-
*
|
|
1014
|
-
* @param file - File content as Buffer/Uint8Array
|
|
1015
|
-
* @param filename - The filename (determines content type detection)
|
|
1016
|
-
* @param options - Optional title, tags, timeoutMs
|
|
1017
|
-
* @returns Upload confirmation with quality scoring
|
|
1018
|
-
*/
|
|
1019
|
-
async uploadFile(file, filename, options) {
|
|
1020
|
-
const boundary = "----WauldoSDKBoundary";
|
|
1021
|
-
const parts = [];
|
|
1022
|
-
const enc = new TextEncoder();
|
|
1023
|
-
parts.push(enc.encode(`--${boundary}\r
|
|
1024
|
-
Content-Disposition: form-data; name="file"; filename="${filename}"\r
|
|
1025
|
-
Content-Type: application/octet-stream\r
|
|
1026
|
-
\r
|
|
1027
|
-
`));
|
|
1028
|
-
parts.push(file instanceof Uint8Array ? file : new Uint8Array(file));
|
|
1029
|
-
parts.push(enc.encode("\r\n"));
|
|
1030
|
-
if (options?.title) {
|
|
1031
|
-
parts.push(enc.encode(`--${boundary}\r
|
|
1032
|
-
Content-Disposition: form-data; name="title"\r
|
|
1033
|
-
\r
|
|
1034
|
-
${options.title}\r
|
|
1035
|
-
`));
|
|
1036
|
-
}
|
|
1037
|
-
if (options?.tags) {
|
|
1038
|
-
parts.push(enc.encode(`--${boundary}\r
|
|
1039
|
-
Content-Disposition: form-data; name="tags"\r
|
|
1040
|
-
\r
|
|
1041
|
-
${options.tags}\r
|
|
1042
|
-
`));
|
|
1043
|
-
}
|
|
1044
|
-
parts.push(enc.encode(`--${boundary}--\r
|
|
1045
|
-
`));
|
|
1046
|
-
const body = concatUint8Arrays(parts);
|
|
1047
|
-
const data = await fetchWithRetry(
|
|
1048
|
-
{ ...this.retryConfig, headers: { ...this.retryConfig.headers, "Content-Type": `multipart/form-data; boundary=${boundary}` } },
|
|
1049
|
-
"POST",
|
|
1050
|
-
"/v1/upload-file",
|
|
1051
|
-
body,
|
|
1052
|
-
options?.timeoutMs
|
|
1053
|
-
);
|
|
1054
|
-
return validateResponse(data, "UploadFileResponse");
|
|
1055
|
-
}
|
|
1056
1001
|
/** POST /v1/query — Query RAG knowledge base */
|
|
1057
1002
|
async ragQuery(query, topK = 5, options) {
|
|
1058
1003
|
const body = { query, top_k: topK };
|
|
@@ -1095,122 +1040,59 @@ ${options.tags}\r
|
|
|
1095
1040
|
const result = await this.ragQuery(question, 3);
|
|
1096
1041
|
return result.answer ?? JSON.stringify(result.sources);
|
|
1097
1042
|
}
|
|
1098
|
-
// ──
|
|
1099
|
-
/** POST /v1/orchestrator/execute — Route to best specialist agent */
|
|
1100
|
-
async orchestrate(prompt) {
|
|
1101
|
-
const data = await fetchWithRetry(
|
|
1102
|
-
this.retryConfig,
|
|
1103
|
-
"POST",
|
|
1104
|
-
"/v1/orchestrator/execute",
|
|
1105
|
-
{ prompt }
|
|
1106
|
-
);
|
|
1107
|
-
return validateResponse(data, "OrchestratorResponse");
|
|
1108
|
-
}
|
|
1109
|
-
/** POST /v1/orchestrator/parallel — Run all 4 specialists in parallel */
|
|
1110
|
-
async orchestrateParallel(prompt) {
|
|
1111
|
-
const data = await fetchWithRetry(
|
|
1112
|
-
this.retryConfig,
|
|
1113
|
-
"POST",
|
|
1114
|
-
"/v1/orchestrator/parallel",
|
|
1115
|
-
{ prompt }
|
|
1116
|
-
);
|
|
1117
|
-
return validateResponse(data, "OrchestratorResponse");
|
|
1118
|
-
}
|
|
1119
|
-
// ── Fact-Check endpoints ──────────────────────────────────────────────
|
|
1043
|
+
// ── Guard (Fact-Check) ─────────────────────────────────────────────
|
|
1120
1044
|
/**
|
|
1121
|
-
* POST /v1/fact-check — Verify claims against source context.
|
|
1045
|
+
* POST /v1/fact-check — Verify text claims against source context.
|
|
1046
|
+
*
|
|
1047
|
+
* Guard is a hallucination firewall: checks whether LLM output is supported
|
|
1048
|
+
* by source documents. Blocks wrong answers before they reach users.
|
|
1122
1049
|
*
|
|
1123
|
-
* @param
|
|
1124
|
-
* @
|
|
1050
|
+
* @param text - The LLM-generated text to verify
|
|
1051
|
+
* @param sourceContext - The ground-truth source document(s)
|
|
1052
|
+
* @param mode - "lexical" (<1ms), "hybrid" (~50ms), or "semantic" (~500ms)
|
|
1053
|
+
* @param options - Optional per-request overrides
|
|
1125
1054
|
*
|
|
1126
1055
|
* @example
|
|
1127
1056
|
* ```typescript
|
|
1128
|
-
* const result = await client.
|
|
1129
|
-
*
|
|
1130
|
-
*
|
|
1131
|
-
*
|
|
1132
|
-
*
|
|
1133
|
-
*
|
|
1057
|
+
* const result = await client.guard(
|
|
1058
|
+
* 'Returns accepted within 60 days',
|
|
1059
|
+
* 'Our return policy: 14 days.',
|
|
1060
|
+
* );
|
|
1061
|
+
* if (result.action === 'block') {
|
|
1062
|
+
* console.log('Hallucination caught:', result.claims[0]?.reason);
|
|
1063
|
+
* }
|
|
1134
1064
|
* ```
|
|
1135
1065
|
*/
|
|
1136
|
-
async
|
|
1066
|
+
async guard(text, sourceContext, mode = "lexical", options) {
|
|
1137
1067
|
const data = await fetchWithRetry(
|
|
1138
1068
|
this.retryConfig,
|
|
1139
1069
|
"POST",
|
|
1140
1070
|
"/v1/fact-check",
|
|
1141
|
-
|
|
1071
|
+
{ text, source_context: sourceContext, mode },
|
|
1072
|
+
options?.timeoutMs
|
|
1142
1073
|
);
|
|
1143
|
-
return validateResponse(data, "
|
|
1074
|
+
return validateResponse(data, "GuardResponse");
|
|
1144
1075
|
}
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
* @example
|
|
1149
|
-
* ```ts
|
|
1150
|
-
* const result = await client.verifyCitation({
|
|
1151
|
-
* text: 'Rust was released in 2010 [Source: rust_book].',
|
|
1152
|
-
* sources: [{ name: 'rust_book', content: 'Rust was first released in 2010.' }],
|
|
1153
|
-
* });
|
|
1154
|
-
* console.log(result.phantom_count); // 0
|
|
1155
|
-
* ```
|
|
1156
|
-
*/
|
|
1157
|
-
async verifyCitation(request) {
|
|
1076
|
+
// ── Orchestrator endpoints ───────────────────────────────────────────
|
|
1077
|
+
/** POST /v1/orchestrator/execute — Route to best specialist agent */
|
|
1078
|
+
async orchestrate(prompt) {
|
|
1158
1079
|
const data = await fetchWithRetry(
|
|
1159
1080
|
this.retryConfig,
|
|
1160
1081
|
"POST",
|
|
1161
|
-
"/v1/
|
|
1162
|
-
|
|
1163
|
-
);
|
|
1164
|
-
return validateResponse(data, "VerifyCitationResponse");
|
|
1165
|
-
}
|
|
1166
|
-
/**
|
|
1167
|
-
* Verify an LLM output against a source document.
|
|
1168
|
-
* Convenience wrapper around factCheck(). Returns a simple safe/unsafe result.
|
|
1169
|
-
*/
|
|
1170
|
-
async guard(text, source, mode = "lexical") {
|
|
1171
|
-
const result = await this.factCheck({ text, source_context: source, mode });
|
|
1172
|
-
const claim = result.claims?.[0];
|
|
1173
|
-
return {
|
|
1174
|
-
safe: claim?.verdict === "verified",
|
|
1175
|
-
verdict: claim?.verdict ?? "rejected",
|
|
1176
|
-
action: claim?.action ?? "block",
|
|
1177
|
-
reason: claim?.reason ?? "no_claims",
|
|
1178
|
-
confidence: claim?.confidence ?? 0
|
|
1179
|
-
};
|
|
1180
|
-
}
|
|
1181
|
-
// ── Analytics & Insights endpoints ───────────────────────────────────
|
|
1182
|
-
/**
|
|
1183
|
-
* GET /v1/insights — ROI metrics for your API key
|
|
1184
|
-
*/
|
|
1185
|
-
async getInsights() {
|
|
1186
|
-
const data = await fetchWithRetry(
|
|
1187
|
-
this.retryConfig,
|
|
1188
|
-
"GET",
|
|
1189
|
-
"/v1/insights"
|
|
1190
|
-
);
|
|
1191
|
-
return validateResponse(data, "InsightsResponse");
|
|
1192
|
-
}
|
|
1193
|
-
/**
|
|
1194
|
-
* GET /v1/analytics — Usage analytics and cache performance
|
|
1195
|
-
*/
|
|
1196
|
-
async getAnalytics(minutes = 60) {
|
|
1197
|
-
const data = await fetchWithRetry(
|
|
1198
|
-
this.retryConfig,
|
|
1199
|
-
"GET",
|
|
1200
|
-
`/v1/analytics?minutes=${minutes}`
|
|
1082
|
+
"/v1/orchestrator/execute",
|
|
1083
|
+
{ prompt }
|
|
1201
1084
|
);
|
|
1202
|
-
return validateResponse(data, "
|
|
1085
|
+
return validateResponse(data, "OrchestratorResponse");
|
|
1203
1086
|
}
|
|
1204
|
-
/**
|
|
1205
|
-
|
|
1206
|
-
*/
|
|
1207
|
-
async getAnalyticsTraffic() {
|
|
1087
|
+
/** POST /v1/orchestrator/parallel — Run all 4 specialists in parallel */
|
|
1088
|
+
async orchestrateParallel(prompt) {
|
|
1208
1089
|
const data = await fetchWithRetry(
|
|
1209
1090
|
this.retryConfig,
|
|
1210
|
-
"
|
|
1211
|
-
"/v1/
|
|
1091
|
+
"POST",
|
|
1092
|
+
"/v1/orchestrator/parallel",
|
|
1093
|
+
{ prompt }
|
|
1212
1094
|
);
|
|
1213
|
-
return validateResponse(data, "
|
|
1095
|
+
return validateResponse(data, "OrchestratorResponse");
|
|
1214
1096
|
}
|
|
1215
1097
|
};
|
|
1216
1098
|
|
|
@@ -1315,132 +1197,6 @@ var MockHttpClient = class {
|
|
|
1315
1197
|
this.record("conversation", options);
|
|
1316
1198
|
return new Conversation(this, options);
|
|
1317
1199
|
}
|
|
1318
|
-
async uploadFile(_file, filename, options) {
|
|
1319
|
-
this.record("uploadFile", filename, options);
|
|
1320
|
-
return {
|
|
1321
|
-
document_id: "mock-doc-file-1",
|
|
1322
|
-
chunks_count: 5,
|
|
1323
|
-
indexed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1324
|
-
content_type: "application/pdf",
|
|
1325
|
-
trace_id: "mock-trace-1",
|
|
1326
|
-
quality: {
|
|
1327
|
-
score: 0.85,
|
|
1328
|
-
label: "good",
|
|
1329
|
-
word_count: 1200,
|
|
1330
|
-
line_density: 8.5,
|
|
1331
|
-
avg_line_length: 72,
|
|
1332
|
-
paragraph_count: 15
|
|
1333
|
-
}
|
|
1334
|
-
};
|
|
1335
|
-
}
|
|
1336
|
-
async factCheck(request) {
|
|
1337
|
-
this.record("factCheck", request);
|
|
1338
|
-
const hasConflict = request.text !== request.source_context;
|
|
1339
|
-
return {
|
|
1340
|
-
verdict: hasConflict ? "rejected" : "verified",
|
|
1341
|
-
action: hasConflict ? "block" : "allow",
|
|
1342
|
-
hallucination_rate: hasConflict ? 1 : 0,
|
|
1343
|
-
mode: request.mode ?? "lexical",
|
|
1344
|
-
total_claims: 1,
|
|
1345
|
-
supported_claims: hasConflict ? 0 : 1,
|
|
1346
|
-
confidence: hasConflict ? 0.25 : 0.92,
|
|
1347
|
-
claims: [{
|
|
1348
|
-
text: request.text,
|
|
1349
|
-
claim_type: "factual",
|
|
1350
|
-
supported: !hasConflict,
|
|
1351
|
-
confidence: hasConflict ? 0.25 : 0.92,
|
|
1352
|
-
confidence_label: hasConflict ? "low" : "high",
|
|
1353
|
-
verdict: hasConflict ? "rejected" : "verified",
|
|
1354
|
-
action: hasConflict ? "block" : "allow",
|
|
1355
|
-
reason: hasConflict ? "numerical_mismatch" : null,
|
|
1356
|
-
evidence: request.source_context
|
|
1357
|
-
}],
|
|
1358
|
-
processing_time_ms: 1
|
|
1359
|
-
};
|
|
1360
|
-
}
|
|
1361
|
-
async guard(text, source, mode = "lexical") {
|
|
1362
|
-
this.record("guard", text, source, mode);
|
|
1363
|
-
return {
|
|
1364
|
-
safe: true,
|
|
1365
|
-
verdict: "verified",
|
|
1366
|
-
action: "allow",
|
|
1367
|
-
reason: null,
|
|
1368
|
-
confidence: 0.95
|
|
1369
|
-
};
|
|
1370
|
-
}
|
|
1371
|
-
async verifyCitation(request) {
|
|
1372
|
-
this.record("verifyCitation", request);
|
|
1373
|
-
const citations = request.text.match(/\[(?:Source:\s*[^\]]+|\d+|Ref:\s*[^\]]+)\]/g) ?? [];
|
|
1374
|
-
const sentences = request.text.split(/[.!?]+/).filter((s) => s.trim().length > 0);
|
|
1375
|
-
const citedSentences = sentences.filter((s) => /\[(?:Source:\s*[^\]]+|\d+|Ref:\s*[^\]]+)\]/.test(s));
|
|
1376
|
-
const ratio = sentences.length > 0 ? citedSentences.length / sentences.length : 0;
|
|
1377
|
-
return {
|
|
1378
|
-
citation_ratio: ratio,
|
|
1379
|
-
has_sufficient_citations: ratio >= (request.threshold ?? 0.5),
|
|
1380
|
-
sentence_count: sentences.length,
|
|
1381
|
-
citation_count: citations.length,
|
|
1382
|
-
uncited_sentences: sentences.filter((s) => !/\[(?:Source:\s*[^\]]+|\d+|Ref:\s*[^\]]+)\]/.test(s)).map((s) => s.trim()),
|
|
1383
|
-
citations: citations.map((c) => ({
|
|
1384
|
-
citation: c,
|
|
1385
|
-
source_name: c.replace(/[\[\]]/g, "").replace("Source: ", ""),
|
|
1386
|
-
is_valid: (request.sources ?? []).some((src) => c.includes(src.name))
|
|
1387
|
-
})),
|
|
1388
|
-
phantom_count: 0,
|
|
1389
|
-
processing_time_ms: 1
|
|
1390
|
-
};
|
|
1391
|
-
}
|
|
1392
|
-
async getInsights() {
|
|
1393
|
-
this.record("getInsights");
|
|
1394
|
-
return {
|
|
1395
|
-
tig_key: "mock-tig-key",
|
|
1396
|
-
total_requests: 1250,
|
|
1397
|
-
intelligence_requests: 980,
|
|
1398
|
-
fallback_requests: 270,
|
|
1399
|
-
tokens: {
|
|
1400
|
-
baseline_total: 5e5,
|
|
1401
|
-
real_total: 325e3,
|
|
1402
|
-
saved_total: 175e3,
|
|
1403
|
-
saved_percent_avg: 35
|
|
1404
|
-
},
|
|
1405
|
-
cost: {
|
|
1406
|
-
estimated_usd_saved: 12.5
|
|
1407
|
-
}
|
|
1408
|
-
};
|
|
1409
|
-
}
|
|
1410
|
-
async getAnalytics(minutes = 60) {
|
|
1411
|
-
this.record("getAnalytics", minutes);
|
|
1412
|
-
return {
|
|
1413
|
-
cache: {
|
|
1414
|
-
total_requests: 450,
|
|
1415
|
-
cache_hit_rate: 0.42,
|
|
1416
|
-
avg_latency_ms: 180,
|
|
1417
|
-
p95_latency_ms: 850
|
|
1418
|
-
},
|
|
1419
|
-
tokens: {
|
|
1420
|
-
total_baseline: 12e4,
|
|
1421
|
-
total_real: 78e3,
|
|
1422
|
-
total_saved: 42e3,
|
|
1423
|
-
avg_savings_percent: 35
|
|
1424
|
-
},
|
|
1425
|
-
uptime_secs: 86400
|
|
1426
|
-
};
|
|
1427
|
-
}
|
|
1428
|
-
async getAnalyticsTraffic() {
|
|
1429
|
-
this.record("getAnalyticsTraffic");
|
|
1430
|
-
return {
|
|
1431
|
-
total_requests_today: 3200,
|
|
1432
|
-
total_tokens_today: 15e5,
|
|
1433
|
-
top_tenants: [
|
|
1434
|
-
{ tenant_id: "tenant-alpha", requests_today: 1200, tokens_used: 58e4, success_rate: 0.98, avg_latency_ms: 220 },
|
|
1435
|
-
{ tenant_id: "tenant-beta", requests_today: 850, tokens_used: 42e4, success_rate: 0.96, avg_latency_ms: 310 },
|
|
1436
|
-
{ tenant_id: "tenant-gamma", requests_today: 600, tokens_used: 28e4, success_rate: 0.99, avg_latency_ms: 150 }
|
|
1437
|
-
],
|
|
1438
|
-
error_rate: 0.02,
|
|
1439
|
-
avg_latency_ms: 240,
|
|
1440
|
-
p95_latency_ms: 890,
|
|
1441
|
-
uptime_secs: 86400
|
|
1442
|
-
};
|
|
1443
|
-
}
|
|
1444
1200
|
async ragAsk(question, text, source = "document") {
|
|
1445
1201
|
this.record("ragAsk", question, text, source);
|
|
1446
1202
|
await this.ragUpload(text, source);
|
|
@@ -1456,6 +1212,12 @@ var MockHttpClient = class {
|
|
|
1456
1212
|
function chatContent(response) {
|
|
1457
1213
|
return response.choices[0]?.message?.content ?? "";
|
|
1458
1214
|
}
|
|
1215
|
+
function guardIsSafe(response) {
|
|
1216
|
+
return response.verdict === "verified";
|
|
1217
|
+
}
|
|
1218
|
+
function guardIsBlocked(response) {
|
|
1219
|
+
return response.action === "block";
|
|
1220
|
+
}
|
|
1459
1221
|
export {
|
|
1460
1222
|
AgentClient,
|
|
1461
1223
|
ConnectionError,
|
|
@@ -1467,5 +1229,7 @@ export {
|
|
|
1467
1229
|
ToolNotFoundError,
|
|
1468
1230
|
ValidationError,
|
|
1469
1231
|
WauldoError,
|
|
1470
|
-
chatContent
|
|
1232
|
+
chatContent,
|
|
1233
|
+
guardIsBlocked,
|
|
1234
|
+
guardIsSafe
|
|
1471
1235
|
};
|