nuabase 1.2.0 → 2.1.0
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 +100 -58
- package/dist/cjs/index.cjs +1497 -405
- package/dist/esm/index.mjs +1493 -405
- package/dist/types/__tests__/helpers/client-factory.d.ts +17 -0
- package/dist/types/__tests__/helpers/index.d.ts +1 -0
- package/dist/types/backend/direct.d.ts +17 -0
- package/dist/types/backend/gateway.d.ts +23 -0
- package/dist/types/backend/types.d.ts +61 -0
- package/dist/types/index.d.cts +5 -2
- package/dist/types/index.d.mts +5 -2
- package/dist/types/lib/auth.d.ts +12 -0
- package/dist/types/nua.d.ts +34 -3
- package/package.json +25 -21
- package/dist/types/__tests__/utils/sse.d.ts +0 -12
- package/dist/types/lib/api-client.d.ts +0 -19
- package/dist/types/nua/cast_array/factory.d.ts +0 -4
- package/dist/types/nua/cast_array/request-validation.d.ts +0 -1
- package/dist/types/nua/cast_array/response-schema.d.ts +0 -19
- package/dist/types/nua/cast_array/types.d.ts +0 -33
- package/dist/types/nua/cast_value/factory.d.ts +0 -4
- package/dist/types/nua/cast_value/response-schema.d.ts +0 -15
- package/dist/types/nua/cast_value/types.d.ts +0 -18
- package/dist/types/nua/common/normalized-usage.d.ts +0 -7
- package/dist/types/nua/common/queued-response.d.ts +0 -6
- package/dist/types/nua/core.d.ts +0 -12
- package/dist/types/nua/get-request/index.d.ts +0 -6
- package/dist/types/nua/get-request/types.d.ts +0 -34
- package/dist/types/nua/index.d.ts +0 -5
package/dist/esm/index.mjs
CHANGED
|
@@ -1,60 +1,1289 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import require$$0 from 'ajv';
|
|
3
|
+
import require$$1 from 'ajv/dist/2019';
|
|
4
|
+
import require$$2 from 'ajv/dist/2020';
|
|
5
|
+
import require$$3 from 'ajv/dist/refs/json-schema-draft-07.json';
|
|
6
|
+
import require$$4 from 'ajv/dist/refs/json-schema-draft-06.json';
|
|
1
7
|
import { z } from 'zod';
|
|
8
|
+
export { z } from 'zod';
|
|
2
9
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
var dist = {};
|
|
11
|
+
|
|
12
|
+
var nuaLlmClient = {};
|
|
13
|
+
|
|
14
|
+
var logger = {};
|
|
15
|
+
|
|
16
|
+
const require$1 = createRequire(import.meta.url);
|
|
17
|
+
function __require() { return require$1("node:crypto"); }
|
|
18
|
+
|
|
19
|
+
var hasRequiredLogger;
|
|
20
|
+
function requireLogger() {
|
|
21
|
+
if (hasRequiredLogger) return logger;
|
|
22
|
+
hasRequiredLogger = 1;
|
|
23
|
+
Object.defineProperty(logger, "__esModule", { value: true });
|
|
24
|
+
logger.logLlmCallError = logger.logLlmCallComplete = logger.logLlmCallStart = logger.generateSpanId = logger.ConsoleLogger = void 0;
|
|
25
|
+
logger.truncateText = truncateText;
|
|
26
|
+
logger.pickHeaders = pickHeaders;
|
|
27
|
+
logger.normalizeError = normalizeError;
|
|
28
|
+
const node_crypto_1 = __require();
|
|
29
|
+
class ConsoleLogger {
|
|
30
|
+
debug(message, context) {
|
|
31
|
+
console.debug(`[DEBUG] ${message}`, context || "");
|
|
32
|
+
}
|
|
33
|
+
info(message, context) {
|
|
34
|
+
console.info(`[INFO] ${message}`, context || "");
|
|
35
|
+
}
|
|
36
|
+
warn(message, context) {
|
|
37
|
+
console.warn(`[WARN] ${message}`, context || "");
|
|
38
|
+
}
|
|
39
|
+
error(message, context) {
|
|
40
|
+
console.error(`[ERROR] ${message}`, context || "");
|
|
41
|
+
}
|
|
9
42
|
}
|
|
10
|
-
|
|
43
|
+
logger.ConsoleLogger = ConsoleLogger;
|
|
44
|
+
const generateSpanId = () => (0, node_crypto_1.randomUUID)();
|
|
45
|
+
logger.generateSpanId = generateSpanId;
|
|
46
|
+
function truncateText(text, limit = 500) {
|
|
47
|
+
const length = text.length;
|
|
48
|
+
if (length <= limit) {
|
|
49
|
+
return { preview: text, length };
|
|
50
|
+
}
|
|
51
|
+
return { preview: text.slice(0, limit), length };
|
|
52
|
+
}
|
|
53
|
+
function pickHeaders(headers, allowlist, redactSet) {
|
|
54
|
+
const result = {};
|
|
55
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
56
|
+
const lowerKey = key.toLowerCase();
|
|
57
|
+
if (redactSet?.has(lowerKey)) {
|
|
58
|
+
result[key] = "[REDACTED]";
|
|
59
|
+
} else if (allowlist.has(lowerKey)) {
|
|
60
|
+
result[key] = Array.isArray(value) ? value.join(", ") : value ?? "";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
function normalizeError(error) {
|
|
66
|
+
return error instanceof Error ? { message: error.message, stack: error.stack } : String(error);
|
|
67
|
+
}
|
|
68
|
+
const LLM_RESPONSE_HEADER_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
69
|
+
"x-request-id",
|
|
70
|
+
"x-ratelimit-limit-requests",
|
|
71
|
+
"x-ratelimit-limit-tokens",
|
|
72
|
+
"x-ratelimit-remaining-requests",
|
|
73
|
+
"x-ratelimit-remaining-tokens",
|
|
74
|
+
"x-groq-region"
|
|
75
|
+
]);
|
|
76
|
+
const logLlmCallStart = (logger2, spanId, service, method, request) => {
|
|
77
|
+
logger2.info("LLM call started", {
|
|
78
|
+
type: "llm_call_start",
|
|
79
|
+
span_id: spanId,
|
|
80
|
+
service,
|
|
81
|
+
method,
|
|
82
|
+
...request
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
logger.logLlmCallStart = logLlmCallStart;
|
|
86
|
+
const logLlmCallComplete = (logger2, spanId, service, method, response, duration) => {
|
|
87
|
+
const { headers, responseText, ...rest } = response;
|
|
88
|
+
const { preview: responsePreview, length: responseLength } = truncateText(responseText);
|
|
89
|
+
logger2.info("LLM call completed", {
|
|
90
|
+
type: "llm_call_complete",
|
|
91
|
+
span_id: spanId,
|
|
92
|
+
service,
|
|
93
|
+
method,
|
|
94
|
+
...rest,
|
|
95
|
+
responsePreview,
|
|
96
|
+
responseLength,
|
|
97
|
+
...pickHeaders(headers, LLM_RESPONSE_HEADER_ALLOWLIST),
|
|
98
|
+
duration_ms: duration
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
logger.logLlmCallComplete = logLlmCallComplete;
|
|
102
|
+
const logLlmCallError = (logger2, spanId, service, method, error, duration) => {
|
|
103
|
+
logger2.error("LLM call failed", {
|
|
104
|
+
type: "llm_call_error",
|
|
105
|
+
span_id: spanId,
|
|
106
|
+
service,
|
|
107
|
+
method,
|
|
108
|
+
error: normalizeError(error),
|
|
109
|
+
duration_ms: duration
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
logger.logLlmCallError = logLlmCallError;
|
|
113
|
+
return logger;
|
|
11
114
|
}
|
|
12
115
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
116
|
+
var validateMappableInputData = {};
|
|
117
|
+
|
|
118
|
+
var hasRequiredValidateMappableInputData;
|
|
119
|
+
function requireValidateMappableInputData() {
|
|
120
|
+
if (hasRequiredValidateMappableInputData) return validateMappableInputData;
|
|
121
|
+
hasRequiredValidateMappableInputData = 1;
|
|
122
|
+
Object.defineProperty(validateMappableInputData, "__esModule", { value: true });
|
|
123
|
+
validateMappableInputData.validateMappableInputData = validateMappableInputData$1;
|
|
124
|
+
function validateMappableInputData$1(data, primaryKey) {
|
|
125
|
+
if (!Array.isArray(data))
|
|
126
|
+
return {
|
|
127
|
+
kind: "validation-error",
|
|
128
|
+
message: "input.data must be an array"
|
|
129
|
+
};
|
|
130
|
+
if (typeof primaryKey !== "string" || primaryKey.trim() === "") {
|
|
131
|
+
return {
|
|
132
|
+
kind: "validation-error",
|
|
133
|
+
message: "input.primaryKey must be a non-empty string"
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
const invalidDataMessage = `Each item in 'data' must be an object with at least one key including the primary key '${primaryKey}'`;
|
|
137
|
+
for (let i = 0; i < data.length; i++) {
|
|
138
|
+
const item = data[i];
|
|
139
|
+
if (item === null || typeof item !== "object" || Array.isArray(item))
|
|
140
|
+
return {
|
|
141
|
+
kind: "validation-error",
|
|
142
|
+
message: invalidDataMessage
|
|
143
|
+
};
|
|
144
|
+
const keys = Object.keys(item);
|
|
145
|
+
if (keys.length < 2 || !keys.includes(primaryKey))
|
|
146
|
+
return {
|
|
147
|
+
kind: "validation-error",
|
|
148
|
+
message: invalidDataMessage
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return data;
|
|
20
152
|
}
|
|
21
|
-
|
|
22
|
-
|
|
153
|
+
return validateMappableInputData;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
var callLlmService = {};
|
|
157
|
+
|
|
158
|
+
var llmResponseExtraction = {};
|
|
159
|
+
|
|
160
|
+
var hasRequiredLlmResponseExtraction;
|
|
161
|
+
function requireLlmResponseExtraction() {
|
|
162
|
+
if (hasRequiredLlmResponseExtraction) return llmResponseExtraction;
|
|
163
|
+
hasRequiredLlmResponseExtraction = 1;
|
|
164
|
+
Object.defineProperty(llmResponseExtraction, "__esModule", { value: true });
|
|
165
|
+
llmResponseExtraction.extractThinkingFromResponse = extractThinkingFromResponse;
|
|
166
|
+
llmResponseExtraction.extractJsonFromMarkdown = extractJsonFromMarkdown;
|
|
167
|
+
function extractThinkingFromResponse(input) {
|
|
168
|
+
const startTag = "<think>";
|
|
169
|
+
const endTag = "</think>";
|
|
170
|
+
const thinkingParts = [];
|
|
171
|
+
const cleanedParts = [];
|
|
172
|
+
let cursor = 0;
|
|
173
|
+
while (cursor < input.length) {
|
|
174
|
+
const startIndex = input.indexOf(startTag, cursor);
|
|
175
|
+
if (startIndex === -1) {
|
|
176
|
+
cleanedParts.push(input.slice(cursor));
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
cleanedParts.push(input.slice(cursor, startIndex));
|
|
180
|
+
const contentStart = startIndex + startTag.length;
|
|
181
|
+
const endIndex = input.indexOf(endTag, contentStart);
|
|
182
|
+
if (endIndex === -1) {
|
|
183
|
+
cleanedParts.push(input.slice(startIndex));
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
thinkingParts.push(input.slice(contentStart, endIndex).trim());
|
|
187
|
+
cursor = endIndex + endTag.length;
|
|
188
|
+
}
|
|
189
|
+
const thinking = thinkingParts.join("\n\n");
|
|
190
|
+
const cleanedResponse = cleanedParts.join("").trim();
|
|
191
|
+
return {
|
|
192
|
+
thinking,
|
|
193
|
+
cleanedResponse
|
|
194
|
+
};
|
|
23
195
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
196
|
+
function extractJsonFromMarkdown(input) {
|
|
197
|
+
const trimmed = input.trim();
|
|
198
|
+
const codeFence = "```";
|
|
199
|
+
const jsonFence = "```json";
|
|
200
|
+
if (trimmed.startsWith(jsonFence)) {
|
|
201
|
+
const startIndex = jsonFence.length;
|
|
202
|
+
const endIndex = trimmed.lastIndexOf(codeFence);
|
|
203
|
+
if (endIndex > startIndex) {
|
|
204
|
+
return trimmed.substring(startIndex, endIndex).trim();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (trimmed.startsWith(codeFence) && !trimmed.startsWith(jsonFence)) {
|
|
208
|
+
const startIndex = codeFence.length;
|
|
209
|
+
const endIndex = trimmed.lastIndexOf(codeFence);
|
|
210
|
+
if (endIndex > startIndex) {
|
|
211
|
+
return trimmed.substring(startIndex, endIndex).trim();
|
|
212
|
+
}
|
|
29
213
|
}
|
|
214
|
+
return input;
|
|
30
215
|
}
|
|
31
|
-
return
|
|
216
|
+
return llmResponseExtraction;
|
|
32
217
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
218
|
+
|
|
219
|
+
var hasRequiredCallLlmService;
|
|
220
|
+
function requireCallLlmService() {
|
|
221
|
+
if (hasRequiredCallLlmService) return callLlmService;
|
|
222
|
+
hasRequiredCallLlmService = 1;
|
|
223
|
+
Object.defineProperty(callLlmService, "__esModule", { value: true });
|
|
224
|
+
callLlmService.callLLM = callLLM;
|
|
225
|
+
const llm_response_extraction_1 = requireLlmResponseExtraction();
|
|
226
|
+
const delay = (ms) => {
|
|
227
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
228
|
+
};
|
|
229
|
+
async function callLLM(llmClient, prompt, model, maxTokens, temperature, maxRetries, validationFunction) {
|
|
230
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
231
|
+
try {
|
|
232
|
+
const providerResponse = await llmClient.sendRequest(prompt, model, maxTokens);
|
|
233
|
+
const response = providerResponse.text;
|
|
234
|
+
let parsedResponse;
|
|
235
|
+
try {
|
|
236
|
+
let { thinking, cleanedResponse } = (0, llm_response_extraction_1.extractThinkingFromResponse)(response);
|
|
237
|
+
cleanedResponse = (0, llm_response_extraction_1.extractJsonFromMarkdown)(cleanedResponse);
|
|
238
|
+
parsedResponse = JSON.parse(cleanedResponse);
|
|
239
|
+
} catch (parseError) {
|
|
240
|
+
const errorMessage2 = `Failed to parse LLM response as JSON: ${parseError instanceof Error ? parseError.message : "Unknown parsing error"}`;
|
|
241
|
+
throw new Error(errorMessage2);
|
|
242
|
+
}
|
|
243
|
+
const validationResult = validationFunction(parsedResponse);
|
|
244
|
+
if (validationResult.success && validationResult.data) {
|
|
245
|
+
return {
|
|
246
|
+
data: validationResult.data,
|
|
247
|
+
usage: providerResponse.usage
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
const errorMessage = `Validation failed: ${validationResult.error || "Unknown validation error"}`;
|
|
251
|
+
throw new Error(errorMessage);
|
|
252
|
+
} catch (error) {
|
|
253
|
+
const isLastAttempt = attempt === maxRetries;
|
|
254
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
255
|
+
if (isLastAttempt) {
|
|
256
|
+
throw new Error(`LLM call failed after ${maxRetries} attempts. Last error: ${errorMessage}`);
|
|
257
|
+
}
|
|
258
|
+
const backoffDelay = Math.pow(2, attempt - 1) * 1e3;
|
|
259
|
+
console.warn(`LLM call attempt ${attempt} failed: ${errorMessage}. Retrying in ${backoffDelay}ms...`);
|
|
260
|
+
await delay(backoffDelay);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
throw new Error("Unexpected error: retry loop completed without success or failure");
|
|
38
264
|
}
|
|
265
|
+
return callLlmService;
|
|
39
266
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
267
|
+
|
|
268
|
+
var nuaJsonSchemaValueValidation = {};
|
|
269
|
+
|
|
270
|
+
var ajvInstances = {};
|
|
271
|
+
|
|
272
|
+
var hasRequiredAjvInstances;
|
|
273
|
+
function requireAjvInstances() {
|
|
274
|
+
if (hasRequiredAjvInstances) return ajvInstances;
|
|
275
|
+
hasRequiredAjvInstances = 1;
|
|
276
|
+
var __importDefault = ajvInstances && ajvInstances.__importDefault || function(mod) {
|
|
277
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
278
|
+
};
|
|
279
|
+
Object.defineProperty(ajvInstances, "__esModule", { value: true });
|
|
280
|
+
ajvInstances.ajvInstances = void 0;
|
|
281
|
+
const ajv_1 = __importDefault(require$$0);
|
|
282
|
+
const _2019_1 = __importDefault(require$$1);
|
|
283
|
+
const _2020_1 = __importDefault(require$$2);
|
|
284
|
+
const json_schema_draft_07_json_1 = __importDefault(require$$3);
|
|
285
|
+
const json_schema_draft_06_json_1 = __importDefault(require$$4);
|
|
286
|
+
const ajvOptions = {
|
|
287
|
+
allErrors: true,
|
|
288
|
+
strict: true,
|
|
289
|
+
strictSchema: true,
|
|
290
|
+
strictNumbers: true,
|
|
291
|
+
strictRequired: true
|
|
292
|
+
};
|
|
293
|
+
class AjvInstances {
|
|
294
|
+
constructor() {
|
|
295
|
+
this.draft07 = new ajv_1.default(ajvOptions);
|
|
296
|
+
this.draft2019 = new _2019_1.default(ajvOptions);
|
|
297
|
+
this.draft2019.addMetaSchema(json_schema_draft_07_json_1.default);
|
|
298
|
+
this.draft2019.addMetaSchema(json_schema_draft_06_json_1.default);
|
|
299
|
+
this.draft2020 = new _2020_1.default(ajvOptions);
|
|
300
|
+
}
|
|
301
|
+
getInstanceForSchema(schema) {
|
|
302
|
+
const schemaVersion = schema.$schema;
|
|
303
|
+
if (!schemaVersion) {
|
|
304
|
+
return this.draft07;
|
|
305
|
+
}
|
|
306
|
+
if (schemaVersion.includes("draft/2020-12") || schemaVersion.includes("draft-2020-12")) {
|
|
307
|
+
return this.draft2020;
|
|
308
|
+
}
|
|
309
|
+
if (schemaVersion.includes("draft/2019-09") || schemaVersion.includes("draft-2019-09")) {
|
|
310
|
+
return this.draft2019;
|
|
311
|
+
}
|
|
312
|
+
return this.draft07;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
ajvInstances.ajvInstances = new AjvInstances();
|
|
316
|
+
return ajvInstances;
|
|
44
317
|
}
|
|
45
318
|
|
|
46
|
-
|
|
47
|
-
|
|
319
|
+
var hasRequiredNuaJsonSchemaValueValidation;
|
|
320
|
+
function requireNuaJsonSchemaValueValidation() {
|
|
321
|
+
if (hasRequiredNuaJsonSchemaValueValidation) return nuaJsonSchemaValueValidation;
|
|
322
|
+
hasRequiredNuaJsonSchemaValueValidation = 1;
|
|
323
|
+
Object.defineProperty(nuaJsonSchemaValueValidation, "__esModule", { value: true });
|
|
324
|
+
nuaJsonSchemaValueValidation.buildNuaJsonSchemaValueValidation = buildNuaJsonSchemaValueValidation;
|
|
325
|
+
const ajv_instances_1 = requireAjvInstances();
|
|
326
|
+
function buildNuaJsonSchemaValueValidation(llmRequestId, parsedSchema) {
|
|
327
|
+
const ajv = ajv_instances_1.ajvInstances.getInstanceForSchema(parsedSchema);
|
|
328
|
+
const ajvValidation = ajv.compile(parsedSchema);
|
|
329
|
+
return (json) => {
|
|
330
|
+
if (ajvValidation(json)) {
|
|
331
|
+
return { success: true, data: json };
|
|
332
|
+
} else {
|
|
333
|
+
const errors = ajvValidation.errors;
|
|
334
|
+
if (errors) {
|
|
335
|
+
const errString = errors.map((err) => `${err.instancePath} ${err.message}`).join(", ");
|
|
336
|
+
return {
|
|
337
|
+
success: false,
|
|
338
|
+
error: errString
|
|
339
|
+
};
|
|
340
|
+
} else {
|
|
341
|
+
return { success: false, error: "Unknown validation error" };
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
return nuaJsonSchemaValueValidation;
|
|
48
347
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
348
|
+
|
|
349
|
+
var httpLlmClient = {};
|
|
350
|
+
|
|
351
|
+
var modelInfo = {};
|
|
352
|
+
|
|
353
|
+
var hasRequiredModelInfo;
|
|
354
|
+
function requireModelInfo() {
|
|
355
|
+
if (hasRequiredModelInfo) return modelInfo;
|
|
356
|
+
hasRequiredModelInfo = 1;
|
|
357
|
+
(function(exports$1) {
|
|
358
|
+
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
359
|
+
exports$1.SUPPORTED_MODELS = exports$1.CANONICAL_MODELS = void 0;
|
|
360
|
+
exports$1.parseCanonicalModelName = parseCanonicalModelName;
|
|
361
|
+
exports$1.CANONICAL_MODELS = [
|
|
362
|
+
"qwen3-30b-a3b-instruct-2507",
|
|
363
|
+
"claude-sonnet-4-5",
|
|
364
|
+
"qwen3-vl-235b-a22b-instruct",
|
|
365
|
+
"qwen3-max",
|
|
366
|
+
"gpt-5",
|
|
367
|
+
"gemini-2.5-flash-lite-preview-09-2025",
|
|
368
|
+
"qwen3-coder-flash",
|
|
369
|
+
"gpt-oss-120b",
|
|
370
|
+
"llama-3.3-70b-versatile",
|
|
371
|
+
"gpt-4o",
|
|
372
|
+
"llama-3.3-70b",
|
|
373
|
+
"gemini-2.0-flash"
|
|
374
|
+
];
|
|
375
|
+
const CANONICAL_SET = new Set(exports$1.CANONICAL_MODELS);
|
|
376
|
+
exports$1.SUPPORTED_MODELS = {
|
|
377
|
+
"gpt-oss-120b": [
|
|
378
|
+
{
|
|
379
|
+
provider: "cerebras",
|
|
380
|
+
providerModelName: "gpt-oss-120b"
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
provider: "openrouter",
|
|
384
|
+
providerModelName: "openai/gpt-oss-120b"
|
|
385
|
+
}
|
|
386
|
+
],
|
|
387
|
+
"qwen3-30b-a3b-instruct-2507": [
|
|
388
|
+
{
|
|
389
|
+
provider: "openrouter",
|
|
390
|
+
providerModelName: "qwen/qwen3-30b-a3b-instruct-2507"
|
|
391
|
+
}
|
|
392
|
+
],
|
|
393
|
+
"claude-sonnet-4-5": [
|
|
394
|
+
{
|
|
395
|
+
provider: "openrouter",
|
|
396
|
+
providerModelName: "anthropic/claude-sonnet-4.5"
|
|
397
|
+
}
|
|
398
|
+
],
|
|
399
|
+
"qwen3-vl-235b-a22b-instruct": [
|
|
400
|
+
{
|
|
401
|
+
provider: "openrouter",
|
|
402
|
+
providerModelName: "qwen/qwen3-vl-235b-a22b-instruct"
|
|
403
|
+
}
|
|
404
|
+
],
|
|
405
|
+
"qwen3-max": [
|
|
406
|
+
{
|
|
407
|
+
provider: "openrouter",
|
|
408
|
+
providerModelName: "qwen/qwen3-max"
|
|
409
|
+
}
|
|
410
|
+
],
|
|
411
|
+
"gpt-5": [
|
|
412
|
+
{
|
|
413
|
+
provider: "openrouter",
|
|
414
|
+
providerModelName: "openai/gpt-5"
|
|
415
|
+
}
|
|
416
|
+
],
|
|
417
|
+
"gemini-2.5-flash-lite-preview-09-2025": [
|
|
418
|
+
{
|
|
419
|
+
provider: "openrouter",
|
|
420
|
+
providerModelName: "google/gemini-2.5-flash-lite-preview-09-2025"
|
|
421
|
+
}
|
|
422
|
+
],
|
|
423
|
+
"qwen3-coder-flash": [
|
|
424
|
+
{
|
|
425
|
+
provider: "openrouter",
|
|
426
|
+
providerModelName: "qwen/qwen3-coder-flash"
|
|
427
|
+
}
|
|
428
|
+
],
|
|
429
|
+
"llama-3.3-70b-versatile": [
|
|
430
|
+
{
|
|
431
|
+
provider: "groq",
|
|
432
|
+
providerModelName: "llama-3.3-70b-versatile"
|
|
433
|
+
}
|
|
434
|
+
],
|
|
435
|
+
"gpt-4o": [
|
|
436
|
+
{
|
|
437
|
+
provider: "openrouter",
|
|
438
|
+
providerModelName: "openai/gpt-4o"
|
|
439
|
+
}
|
|
440
|
+
],
|
|
441
|
+
"llama-3.3-70b": [
|
|
442
|
+
{
|
|
443
|
+
provider: "cerebras",
|
|
444
|
+
providerModelName: "llama-3.3-70b"
|
|
445
|
+
}
|
|
446
|
+
],
|
|
447
|
+
"gemini-2.0-flash": [
|
|
448
|
+
{
|
|
449
|
+
provider: "gemini",
|
|
450
|
+
providerModelName: "gemini-2.0-flash"
|
|
451
|
+
}
|
|
452
|
+
]
|
|
453
|
+
};
|
|
454
|
+
function parseCanonicalModelName(requestedModel) {
|
|
455
|
+
let m = requestedModel || "fast";
|
|
456
|
+
if (CANONICAL_SET.has(m))
|
|
457
|
+
return m;
|
|
458
|
+
let m2;
|
|
459
|
+
switch (m) {
|
|
460
|
+
case "fast":
|
|
461
|
+
m2 = "gpt-oss-120b";
|
|
462
|
+
break;
|
|
463
|
+
case "qwen":
|
|
464
|
+
m2 = "qwen3-vl-235b-a22b-instruct";
|
|
465
|
+
break;
|
|
466
|
+
case "sonnet":
|
|
467
|
+
m2 = "claude-sonnet-4-5";
|
|
468
|
+
break;
|
|
469
|
+
case "gpt":
|
|
470
|
+
m2 = "gpt-5";
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
473
|
+
if (m2)
|
|
474
|
+
return m2;
|
|
475
|
+
return {
|
|
476
|
+
kind: "validation-error",
|
|
477
|
+
message: `Invalid model name: ${m ?? "null/undefined"}`
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
})(modelInfo);
|
|
481
|
+
return modelInfo;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
var providerConfig = {};
|
|
485
|
+
|
|
486
|
+
var hasRequiredProviderConfig;
|
|
487
|
+
function requireProviderConfig() {
|
|
488
|
+
if (hasRequiredProviderConfig) return providerConfig;
|
|
489
|
+
hasRequiredProviderConfig = 1;
|
|
490
|
+
(function(exports$1) {
|
|
491
|
+
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
492
|
+
exports$1.providerConfigs = exports$1.normalizedUsageZero = void 0;
|
|
493
|
+
exports$1.normalizedUsageZero = {
|
|
494
|
+
promptTokens: 0,
|
|
495
|
+
completionTokens: 0,
|
|
496
|
+
totalTokens: 0
|
|
497
|
+
};
|
|
498
|
+
const normalizeOpenAiUsage = (usage) => {
|
|
499
|
+
if (!usage) {
|
|
500
|
+
return exports$1.normalizedUsageZero;
|
|
501
|
+
}
|
|
502
|
+
if (typeof usage.prompt_tokens !== "number" || typeof usage.completion_tokens !== "number" || typeof usage.total_tokens !== "number") {
|
|
503
|
+
return exports$1.normalizedUsageZero;
|
|
504
|
+
}
|
|
505
|
+
return {
|
|
506
|
+
promptTokens: usage.prompt_tokens,
|
|
507
|
+
completionTokens: usage.completion_tokens,
|
|
508
|
+
totalTokens: usage.total_tokens
|
|
509
|
+
};
|
|
510
|
+
};
|
|
511
|
+
const normalizeGeminiUsage = (usage) => {
|
|
512
|
+
if (!usage) {
|
|
513
|
+
return exports$1.normalizedUsageZero;
|
|
514
|
+
}
|
|
515
|
+
if (typeof usage.promptTokenCount !== "number" || typeof usage.candidatesTokenCount !== "number" || typeof usage.totalTokenCount !== "number") {
|
|
516
|
+
return exports$1.normalizedUsageZero;
|
|
517
|
+
}
|
|
518
|
+
return {
|
|
519
|
+
promptTokens: usage.promptTokenCount,
|
|
520
|
+
completionTokens: usage.candidatesTokenCount,
|
|
521
|
+
totalTokens: usage.totalTokenCount
|
|
522
|
+
};
|
|
523
|
+
};
|
|
524
|
+
const buildOpenAiStyleRequest = (baseUrl) => ({ prompt, model, maxTokens, assistantPrefillPrompt }, apiKey) => {
|
|
525
|
+
const messages = [];
|
|
526
|
+
messages.push({ role: "user", content: prompt });
|
|
527
|
+
if (assistantPrefillPrompt) {
|
|
528
|
+
messages.push({ role: "assistant", content: assistantPrefillPrompt });
|
|
529
|
+
}
|
|
530
|
+
const body = {
|
|
531
|
+
messages,
|
|
532
|
+
model,
|
|
533
|
+
temperature: 0.6,
|
|
534
|
+
max_completion_tokens: maxTokens,
|
|
535
|
+
top_p: 1,
|
|
536
|
+
stream: false,
|
|
537
|
+
stop: null
|
|
538
|
+
};
|
|
539
|
+
const headers = {
|
|
540
|
+
"Content-Type": "application/json",
|
|
541
|
+
Authorization: `Bearer ${apiKey}`
|
|
542
|
+
};
|
|
543
|
+
return {
|
|
544
|
+
url: baseUrl,
|
|
545
|
+
method: "POST",
|
|
546
|
+
headers,
|
|
547
|
+
body,
|
|
548
|
+
loggableHeaders: {
|
|
549
|
+
...headers,
|
|
550
|
+
Authorization: "Bearer [REDACTED]"
|
|
551
|
+
},
|
|
552
|
+
loggableBody: body
|
|
553
|
+
};
|
|
554
|
+
};
|
|
555
|
+
const parseOpenAiStyleResponse = (errorLabel) => async (response) => {
|
|
556
|
+
if (response.status === 200) {
|
|
557
|
+
const responseBody = await response.json();
|
|
558
|
+
const responseText = responseBody.choices?.[0]?.message?.content;
|
|
559
|
+
if (responseText) {
|
|
560
|
+
return {
|
|
561
|
+
text: responseText,
|
|
562
|
+
usage: normalizeOpenAiUsage(responseBody.usage)
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
throw new Error(`${errorLabel} API error: Could not extract text from response. Body: ${JSON.stringify(responseBody)}`);
|
|
566
|
+
}
|
|
567
|
+
const errorBody = await response.text();
|
|
568
|
+
try {
|
|
569
|
+
const parsedError = JSON.parse(errorBody);
|
|
570
|
+
const message = parsedError.error?.message || errorBody;
|
|
571
|
+
throw new Error(`${errorLabel} API error: ${response.status} - ${message}`);
|
|
572
|
+
} catch {
|
|
573
|
+
throw new Error(`${errorLabel} API error: ${response.status} - ${errorBody}`);
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
const parseOpenAiGPT5ThinkingStyleResponse = (errorLabel) => async (response) => {
|
|
577
|
+
const normalize = (value) => {
|
|
578
|
+
if (typeof value !== "string") {
|
|
579
|
+
return void 0;
|
|
580
|
+
}
|
|
581
|
+
const trimmed = value.trim();
|
|
582
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
583
|
+
};
|
|
584
|
+
if (response.status === 200) {
|
|
585
|
+
const responseBody = await response.json();
|
|
586
|
+
const message = responseBody.choices?.[0]?.message;
|
|
587
|
+
const content = normalize(message?.content) ?? normalize(message?.reasoning) ?? normalize(message?.reasoning_details?.map((detail) => typeof detail === "object" && detail !== null ? "summary" in detail ? detail.summary : void 0 : void 0).find((summary) => summary !== void 0));
|
|
588
|
+
if (content) {
|
|
589
|
+
return {
|
|
590
|
+
text: content,
|
|
591
|
+
usage: normalizeOpenAiUsage(responseBody.usage)
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
throw new Error(`${errorLabel} API error: Could not extract text from thinking response. Body: ${JSON.stringify(responseBody)}`);
|
|
595
|
+
}
|
|
596
|
+
const errorBody = await response.text();
|
|
597
|
+
try {
|
|
598
|
+
const parsedError = JSON.parse(errorBody);
|
|
599
|
+
const message = parsedError.error?.message || errorBody;
|
|
600
|
+
throw new Error(`${errorLabel} API error: ${response.status} - ${message}`);
|
|
601
|
+
} catch {
|
|
602
|
+
throw new Error(`${errorLabel} API error: ${response.status} - ${errorBody}`);
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
const buildGeminiRequest = ({ prompt, model, maxTokens, assistantPrefillPrompt }, apiKey) => {
|
|
606
|
+
const contents = [];
|
|
607
|
+
contents.push({ role: "user", parts: [{ text: prompt }] });
|
|
608
|
+
if (assistantPrefillPrompt) {
|
|
609
|
+
contents.push({
|
|
610
|
+
role: "model",
|
|
611
|
+
parts: [{ text: assistantPrefillPrompt }]
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
const body = {
|
|
615
|
+
contents,
|
|
616
|
+
generationConfig: {
|
|
617
|
+
maxOutputTokens: maxTokens
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`;
|
|
621
|
+
return {
|
|
622
|
+
url,
|
|
623
|
+
method: "POST",
|
|
624
|
+
headers: {
|
|
625
|
+
"Content-Type": "application/json"
|
|
626
|
+
},
|
|
627
|
+
body,
|
|
628
|
+
loggableUrl: url.replace(/key=[^&]+/, "key=[REDACTED]"),
|
|
629
|
+
loggableBody: body
|
|
630
|
+
};
|
|
631
|
+
};
|
|
632
|
+
const parseGeminiResponse = async (response) => {
|
|
633
|
+
if (response.status === 200) {
|
|
634
|
+
const responseBody = await response.json();
|
|
635
|
+
const responseText = responseBody.candidates?.[0]?.content?.parts?.map((part) => part.text ?? "").join("");
|
|
636
|
+
if (responseText) {
|
|
637
|
+
return {
|
|
638
|
+
text: responseText,
|
|
639
|
+
usage: normalizeGeminiUsage(responseBody.usageMetadata)
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
throw new Error(`Gemini API error: Could not extract text from response. Body: ${JSON.stringify(responseBody)}`);
|
|
643
|
+
}
|
|
644
|
+
const errorBody = await response.text();
|
|
645
|
+
try {
|
|
646
|
+
const parsedError = JSON.parse(errorBody);
|
|
647
|
+
const message = parsedError.error?.message || errorBody;
|
|
648
|
+
throw new Error(`Gemini API error: ${response.status} - ${message}`);
|
|
649
|
+
} catch {
|
|
650
|
+
throw new Error(`Gemini API error: ${response.status} - ${errorBody}`);
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
exports$1.providerConfigs = {
|
|
654
|
+
groq: {
|
|
655
|
+
providerId: "groq",
|
|
656
|
+
apiOperation: "chat/completions",
|
|
657
|
+
errorLabel: "Groq",
|
|
658
|
+
buildRequest: buildOpenAiStyleRequest("https://api.groq.com/openai/v1/chat/completions"),
|
|
659
|
+
parseResponse: parseOpenAiStyleResponse("Groq")
|
|
660
|
+
},
|
|
661
|
+
cerebras: {
|
|
662
|
+
providerId: "cerebras",
|
|
663
|
+
apiOperation: "chat/completions",
|
|
664
|
+
errorLabel: "Cerebras",
|
|
665
|
+
buildRequest: buildOpenAiStyleRequest("https://api.cerebras.ai/v1/chat/completions"),
|
|
666
|
+
parseResponse: parseOpenAiStyleResponse("Cerebras")
|
|
667
|
+
},
|
|
668
|
+
gemini: {
|
|
669
|
+
providerId: "gemini",
|
|
670
|
+
apiOperation: "generateContent",
|
|
671
|
+
errorLabel: "Gemini",
|
|
672
|
+
buildRequest: buildGeminiRequest,
|
|
673
|
+
parseResponse: parseGeminiResponse
|
|
674
|
+
},
|
|
675
|
+
openrouter: {
|
|
676
|
+
providerId: "openrouter",
|
|
677
|
+
apiOperation: "chat/completions",
|
|
678
|
+
errorLabel: "OpenRouter",
|
|
679
|
+
buildRequest: buildOpenAiStyleRequest("https://openrouter.ai/api/v1/chat/completions"),
|
|
680
|
+
parseResponse: parseOpenAiGPT5ThinkingStyleResponse("OpenRouter")
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
})(providerConfig);
|
|
684
|
+
return providerConfig;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
var hasRequiredHttpLlmClient;
|
|
688
|
+
function requireHttpLlmClient() {
|
|
689
|
+
if (hasRequiredHttpLlmClient) return httpLlmClient;
|
|
690
|
+
hasRequiredHttpLlmClient = 1;
|
|
691
|
+
Object.defineProperty(httpLlmClient, "__esModule", { value: true });
|
|
692
|
+
httpLlmClient.HttpLlmClient = void 0;
|
|
693
|
+
const model_info_1 = requireModelInfo();
|
|
694
|
+
const logger_1 = requireLogger();
|
|
695
|
+
const provider_config_1 = requireProviderConfig();
|
|
696
|
+
class HttpLlmClient {
|
|
697
|
+
constructor(providerId, apiKey, logger) {
|
|
698
|
+
this.providerId = providerId;
|
|
699
|
+
this.apiKey = apiKey;
|
|
700
|
+
this.logger = logger;
|
|
701
|
+
}
|
|
702
|
+
async sendRequest(prompt, model, maxTokens, assistantPrefillPrompt) {
|
|
703
|
+
const provider = provider_config_1.providerConfigs[this.providerId];
|
|
704
|
+
if (!provider) {
|
|
705
|
+
throw new Error(`Unknown LLM provider: ${this.providerId}`);
|
|
706
|
+
}
|
|
707
|
+
const providerSpecificModelName = model_info_1.SUPPORTED_MODELS[model].find((pm) => pm.provider === this.providerId);
|
|
708
|
+
if (!providerSpecificModelName) {
|
|
709
|
+
throw new Error(`LLM Provider ${this.providerId} does not support model ${model}. If this is an error and the provider does support this model, please contact us to fix it`);
|
|
710
|
+
}
|
|
711
|
+
const requestOptions = provider.buildRequest({
|
|
712
|
+
prompt,
|
|
713
|
+
model: providerSpecificModelName.providerModelName,
|
|
714
|
+
maxTokens,
|
|
715
|
+
assistantPrefillPrompt
|
|
716
|
+
}, this.apiKey);
|
|
717
|
+
const method = requestOptions.method ?? "POST";
|
|
718
|
+
const headers = requestOptions.headers ?? {};
|
|
719
|
+
const bodyPayload = requestOptions.body;
|
|
720
|
+
const body = typeof bodyPayload === "string" ? bodyPayload : bodyPayload !== void 0 ? JSON.stringify(bodyPayload) : void 0;
|
|
721
|
+
const spanId = (0, logger_1.generateSpanId)();
|
|
722
|
+
const startTime = Date.now();
|
|
723
|
+
(0, logger_1.logLlmCallStart)(this.logger, spanId, provider.providerId, provider.apiOperation, {
|
|
724
|
+
url: requestOptions.loggableUrl ?? requestOptions.url,
|
|
725
|
+
httpMethod: method,
|
|
726
|
+
model,
|
|
727
|
+
maxTokens
|
|
728
|
+
});
|
|
729
|
+
try {
|
|
730
|
+
const response = await fetch(requestOptions.url, {
|
|
731
|
+
method,
|
|
732
|
+
headers,
|
|
733
|
+
body
|
|
734
|
+
});
|
|
735
|
+
const parsedResponse = await provider.parseResponse(response);
|
|
736
|
+
const duration = Date.now() - startTime;
|
|
737
|
+
(0, logger_1.logLlmCallComplete)(this.logger, spanId, provider.providerId, provider.apiOperation, {
|
|
738
|
+
status: response.status,
|
|
739
|
+
responseText: parsedResponse.text,
|
|
740
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
741
|
+
usage: parsedResponse.usage
|
|
742
|
+
}, duration);
|
|
743
|
+
return parsedResponse;
|
|
744
|
+
} catch (error) {
|
|
745
|
+
const duration = Date.now() - startTime;
|
|
746
|
+
(0, logger_1.logLlmCallError)(this.logger, spanId, provider.providerId, provider.apiOperation, error, duration);
|
|
747
|
+
throw new Error(`${provider.errorLabel} API request failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
52
750
|
}
|
|
53
|
-
|
|
751
|
+
httpLlmClient.HttpLlmClient = HttpLlmClient;
|
|
752
|
+
return httpLlmClient;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
var castArrayPromptBuilder = {};
|
|
756
|
+
|
|
757
|
+
var promptTemplateUtils = {};
|
|
758
|
+
|
|
759
|
+
var hasRequiredPromptTemplateUtils;
|
|
760
|
+
function requirePromptTemplateUtils() {
|
|
761
|
+
if (hasRequiredPromptTemplateUtils) return promptTemplateUtils;
|
|
762
|
+
hasRequiredPromptTemplateUtils = 1;
|
|
763
|
+
(function(exports$1) {
|
|
764
|
+
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
765
|
+
exports$1.replaceTemplateVarName = exports$1.templateVarName = void 0;
|
|
766
|
+
const templateVarName = (varName) => `<<{${varName}}>>`;
|
|
767
|
+
exports$1.templateVarName = templateVarName;
|
|
768
|
+
const replaceTemplateVarName = (str, varName, value) => str.replaceAll((0, exports$1.templateVarName)(varName), value);
|
|
769
|
+
exports$1.replaceTemplateVarName = replaceTemplateVarName;
|
|
770
|
+
})(promptTemplateUtils);
|
|
771
|
+
return promptTemplateUtils;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
var hasRequiredCastArrayPromptBuilder;
|
|
775
|
+
function requireCastArrayPromptBuilder() {
|
|
776
|
+
if (hasRequiredCastArrayPromptBuilder) return castArrayPromptBuilder;
|
|
777
|
+
hasRequiredCastArrayPromptBuilder = 1;
|
|
778
|
+
Object.defineProperty(castArrayPromptBuilder, "__esModule", { value: true });
|
|
779
|
+
const prompt_template_utils_1 = requirePromptTemplateUtils();
|
|
780
|
+
const builder = () => {
|
|
781
|
+
const BASE_SYSTEM_PROMPT_WHEN_OUTPUT_TYPE_NAME_PROVIDED = [
|
|
782
|
+
`Your task is to transform the provided <input-data> into a JSON array, that represents a list of`,
|
|
783
|
+
`${(0, prompt_template_utils_1.templateVarName)("OUTPUT_TYPE_NAME")}. The schema for this JSON array is defined below in <json-schema-spec> for you reference.`,
|
|
784
|
+
`It uses the JSON Schema spec.`,
|
|
785
|
+
`Respond with only the instance, not the schema. It should not be wrapped in any wrapper object -- return exactly what the JSON schema is expecting.`,
|
|
786
|
+
`Your entire response should be just the value of the JSON array containing objects with '${(0, prompt_template_utils_1.templateVarName)("OUTPUT_TYPE_NAME")}'`,
|
|
787
|
+
`and its primary key '${(0, prompt_template_utils_1.templateVarName)("PRIMARY_KEY")}', as valid JSON.`,
|
|
788
|
+
`We will validate the result with the AJV Node library, using ajv.parse, against the JSON schema, and we expect it to validate correctly.`,
|
|
789
|
+
`Note that the primary key of each element in the input-data is '${(0, prompt_template_utils_1.templateVarName)("PRIMARY_KEY")}'. In the output JSON array,`,
|
|
790
|
+
`each object should have the same key with the same value of the original data, so we can map the input element against the output element.`
|
|
791
|
+
].join(" ");
|
|
792
|
+
const buildSystemPrompt = (primaryKey, outputName) => {
|
|
793
|
+
let a = BASE_SYSTEM_PROMPT_WHEN_OUTPUT_TYPE_NAME_PROVIDED;
|
|
794
|
+
a = (0, prompt_template_utils_1.replaceTemplateVarName)(a, "PRIMARY_KEY", primaryKey);
|
|
795
|
+
a = (0, prompt_template_utils_1.replaceTemplateVarName)(a, "OUTPUT_TYPE_NAME", outputName);
|
|
796
|
+
return a;
|
|
797
|
+
};
|
|
798
|
+
const buildFullPrompt = (req, uncachedInputDataRows) => {
|
|
799
|
+
const prompt = req.input.prompt;
|
|
800
|
+
const fullPrompt = [
|
|
801
|
+
prompt || "Transform the provided data according to the schema.",
|
|
802
|
+
// user prompt
|
|
803
|
+
buildSystemPrompt(req.input.primaryKey, req.output.name),
|
|
804
|
+
`<json-schema-spec> ${JSON.stringify(req.output.effectiveSchema)} </json-schema-spec>`,
|
|
805
|
+
`<input-data>${JSON.stringify(uncachedInputDataRows)}</input-data>`
|
|
806
|
+
].join("\n");
|
|
807
|
+
return fullPrompt;
|
|
808
|
+
};
|
|
809
|
+
return {
|
|
810
|
+
buildSystemPrompt,
|
|
811
|
+
buildFullPrompt
|
|
812
|
+
};
|
|
813
|
+
};
|
|
814
|
+
const castArrayPromptBuilder$1 = builder();
|
|
815
|
+
castArrayPromptBuilder.default = castArrayPromptBuilder$1;
|
|
816
|
+
return castArrayPromptBuilder;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
var castPromptBuilder = {};
|
|
820
|
+
|
|
821
|
+
var hasRequiredCastPromptBuilder;
|
|
822
|
+
function requireCastPromptBuilder() {
|
|
823
|
+
if (hasRequiredCastPromptBuilder) return castPromptBuilder;
|
|
824
|
+
hasRequiredCastPromptBuilder = 1;
|
|
825
|
+
Object.defineProperty(castPromptBuilder, "__esModule", { value: true });
|
|
826
|
+
const prompt_template_utils_1 = requirePromptTemplateUtils();
|
|
827
|
+
const builder = () => {
|
|
828
|
+
const BASE_SYSTEM_PROMPT_WHEN_OUTPUT_TYPE_NAME_PROVIDED = [
|
|
829
|
+
`Please respond with a single JSON object that represents '${(0, prompt_template_utils_1.templateVarName)("OUTPUT_TYPE_NAME")}'.`,
|
|
830
|
+
`The schema for this object (which uses the JSON Schema spec), is defined below for your reference.`,
|
|
831
|
+
`Your task is to create an instance of this object. Respond with only the instance, not the schema.`,
|
|
832
|
+
`Your entire response should be just the value of '${(0, prompt_template_utils_1.templateVarName)("OUTPUT_TYPE_NAME")}', as valid JSON.`,
|
|
833
|
+
`And it should not be wrapped in any wrapper object -- return exactly what the JSON schema is expecting.`,
|
|
834
|
+
`We will validate the result with the AJV Node library, using ajv.parse, against the given schema, and we expect`,
|
|
835
|
+
`it to validate correctly.`
|
|
836
|
+
].join(" ");
|
|
837
|
+
const buildSystemPrompt = (reqParams) => {
|
|
838
|
+
let a = BASE_SYSTEM_PROMPT_WHEN_OUTPUT_TYPE_NAME_PROVIDED;
|
|
839
|
+
a = (0, prompt_template_utils_1.replaceTemplateVarName)(a, "OUTPUT_TYPE_NAME", reqParams.output.name);
|
|
840
|
+
return a;
|
|
841
|
+
};
|
|
842
|
+
const buildFullPrompt = (reqParams) => {
|
|
843
|
+
const { prompt, data } = reqParams.input;
|
|
844
|
+
const { effectiveSchema } = reqParams.output;
|
|
845
|
+
const fullPrompt = [
|
|
846
|
+
prompt || "Transform the provided data according to the schema.",
|
|
847
|
+
// user prompt
|
|
848
|
+
buildSystemPrompt(reqParams),
|
|
849
|
+
`<json-schema-spec> ${JSON.stringify(effectiveSchema)} </json-schema-spec>`,
|
|
850
|
+
data ? `<input-data>${JSON.stringify(data)}</input-data>` : ""
|
|
851
|
+
].join("\n");
|
|
852
|
+
return fullPrompt;
|
|
853
|
+
};
|
|
854
|
+
return {
|
|
855
|
+
buildSystemPrompt,
|
|
856
|
+
buildFullPrompt
|
|
857
|
+
};
|
|
858
|
+
};
|
|
859
|
+
const castPromptBuilder$1 = builder();
|
|
860
|
+
castPromptBuilder.default = castPromptBuilder$1;
|
|
861
|
+
return castPromptBuilder;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
var nuaErrors = {};
|
|
865
|
+
|
|
866
|
+
var hasRequiredNuaErrors;
|
|
867
|
+
function requireNuaErrors() {
|
|
868
|
+
if (hasRequiredNuaErrors) return nuaErrors;
|
|
869
|
+
hasRequiredNuaErrors = 1;
|
|
870
|
+
Object.defineProperty(nuaErrors, "__esModule", { value: true });
|
|
871
|
+
nuaErrors.isNuaError = nuaErrors.isNuaInternalError = nuaErrors.isNuaValidationError = void 0;
|
|
872
|
+
const isNuaValidationError = (a) => {
|
|
873
|
+
return typeof a == "object" && a != null && "kind" in a && a.kind == "validation-error";
|
|
874
|
+
};
|
|
875
|
+
nuaErrors.isNuaValidationError = isNuaValidationError;
|
|
876
|
+
const isNuaInternalError = (a) => {
|
|
877
|
+
return typeof a == "object" && a != null && "kind" in a && a.kind == "internal-error";
|
|
878
|
+
};
|
|
879
|
+
nuaErrors.isNuaInternalError = isNuaInternalError;
|
|
880
|
+
const isNuaError = (a) => {
|
|
881
|
+
return typeof a == "object" && a != null && "kind" in a && (a.kind == "internal-error" || a.kind == "validation-error");
|
|
882
|
+
};
|
|
883
|
+
nuaErrors.isNuaError = isNuaError;
|
|
884
|
+
return nuaErrors;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
var hasRequiredNuaLlmClient;
|
|
888
|
+
function requireNuaLlmClient() {
|
|
889
|
+
if (hasRequiredNuaLlmClient) return nuaLlmClient;
|
|
890
|
+
hasRequiredNuaLlmClient = 1;
|
|
891
|
+
var __importDefault = nuaLlmClient && nuaLlmClient.__importDefault || function(mod) {
|
|
892
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
893
|
+
};
|
|
894
|
+
Object.defineProperty(nuaLlmClient, "__esModule", { value: true });
|
|
895
|
+
nuaLlmClient.NuaLlmClient = void 0;
|
|
896
|
+
const logger_1 = requireLogger();
|
|
897
|
+
const validate_mappable_input_data_1 = requireValidateMappableInputData();
|
|
898
|
+
const call_llm_service_1 = requireCallLlmService();
|
|
899
|
+
const nua_json_schema_value_validation_1 = requireNuaJsonSchemaValueValidation();
|
|
900
|
+
const http_llm_client_1 = requireHttpLlmClient();
|
|
901
|
+
const model_info_1 = requireModelInfo();
|
|
902
|
+
const cast_array_prompt_builder_1 = __importDefault(requireCastArrayPromptBuilder());
|
|
903
|
+
const cast_prompt_builder_1 = __importDefault(requireCastPromptBuilder());
|
|
904
|
+
const nua_errors_1 = requireNuaErrors();
|
|
905
|
+
class NuaLlmClient {
|
|
906
|
+
constructor(config) {
|
|
907
|
+
this.logger = config.logger || new logger_1.ConsoleLogger();
|
|
908
|
+
this.clients = /* @__PURE__ */ new Map();
|
|
909
|
+
Object.entries(config.providers).forEach(([providerId, providerConfig]) => {
|
|
910
|
+
if (providerConfig?.apiKey) {
|
|
911
|
+
this.clients.set(providerId, new http_llm_client_1.HttpLlmClient(providerId, providerConfig.apiKey, this.logger));
|
|
912
|
+
}
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
getClientForModel(model) {
|
|
916
|
+
const supported = model_info_1.SUPPORTED_MODELS[model];
|
|
917
|
+
if (!supported || supported.length === 0) {
|
|
918
|
+
throw new Error(`Model ${model} is not supported or configuration is missing.`);
|
|
919
|
+
}
|
|
920
|
+
for (const option of supported) {
|
|
921
|
+
if (this.clients.has(option.provider)) {
|
|
922
|
+
return this.clients.get(option.provider);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
throw new Error(`No configured provider found for model ${model}. Please check your API keys.`);
|
|
926
|
+
}
|
|
927
|
+
resolveModel(modelName) {
|
|
928
|
+
const result = (0, model_info_1.parseCanonicalModelName)(modelName);
|
|
929
|
+
if ((0, nua_errors_1.isNuaValidationError)(result)) {
|
|
930
|
+
throw new Error(result.message);
|
|
931
|
+
}
|
|
932
|
+
return result;
|
|
933
|
+
}
|
|
934
|
+
async castValue(params) {
|
|
935
|
+
const model = this.resolveModel(params.model);
|
|
936
|
+
const client = this.getClientForModel(model);
|
|
937
|
+
const maxTokens = params.maxTokens || 4096;
|
|
938
|
+
const temperature = params.temperature ?? 0;
|
|
939
|
+
const prompt = cast_prompt_builder_1.default.buildFullPrompt(params);
|
|
940
|
+
const validationFn = (0, nua_json_schema_value_validation_1.buildNuaJsonSchemaValueValidation)("library-req", params.output.effectiveSchema);
|
|
941
|
+
try {
|
|
942
|
+
const result = await (0, call_llm_service_1.callLLM)(
|
|
943
|
+
client,
|
|
944
|
+
prompt,
|
|
945
|
+
model,
|
|
946
|
+
maxTokens,
|
|
947
|
+
temperature,
|
|
948
|
+
3,
|
|
949
|
+
// default retries
|
|
950
|
+
validationFn
|
|
951
|
+
);
|
|
952
|
+
return {
|
|
953
|
+
success: true,
|
|
954
|
+
data: result.data,
|
|
955
|
+
usage: result.usage,
|
|
956
|
+
prompt
|
|
957
|
+
};
|
|
958
|
+
} catch (e) {
|
|
959
|
+
return {
|
|
960
|
+
success: false,
|
|
961
|
+
error: e instanceof Error ? e.message : String(e)
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
async castArray(params) {
|
|
966
|
+
const model = this.resolveModel(params.model);
|
|
967
|
+
const client = this.getClientForModel(model);
|
|
968
|
+
const maxTokens = params.maxTokens || 4096;
|
|
969
|
+
const temperature = params.temperature ?? 0;
|
|
970
|
+
const validData = (0, validate_mappable_input_data_1.validateMappableInputData)(params.data, params.input.primaryKey);
|
|
971
|
+
if ((0, nua_errors_1.isNuaValidationError)(validData)) {
|
|
972
|
+
return {
|
|
973
|
+
success: false,
|
|
974
|
+
error: validData.message
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
const prompt = cast_array_prompt_builder_1.default.buildFullPrompt(params, validData);
|
|
978
|
+
const validationFn = (0, nua_json_schema_value_validation_1.buildNuaJsonSchemaValueValidation)("library-req", params.output.effectiveSchema);
|
|
979
|
+
try {
|
|
980
|
+
const result = await (0, call_llm_service_1.callLLM)(client, prompt, model, maxTokens, temperature, 3, validationFn);
|
|
981
|
+
return {
|
|
982
|
+
success: true,
|
|
983
|
+
data: result.data,
|
|
984
|
+
usage: result.usage,
|
|
985
|
+
prompt
|
|
986
|
+
};
|
|
987
|
+
} catch (e) {
|
|
988
|
+
return {
|
|
989
|
+
success: false,
|
|
990
|
+
error: e instanceof Error ? e.message : String(e)
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
nuaLlmClient.NuaLlmClient = NuaLlmClient;
|
|
996
|
+
return nuaLlmClient;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
var types = {};
|
|
1000
|
+
|
|
1001
|
+
var hasRequiredTypes;
|
|
1002
|
+
function requireTypes() {
|
|
1003
|
+
if (hasRequiredTypes) return types;
|
|
1004
|
+
hasRequiredTypes = 1;
|
|
1005
|
+
Object.defineProperty(types, "__esModule", { value: true });
|
|
1006
|
+
return types;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
var validateJsonSchema = {};
|
|
1010
|
+
|
|
1011
|
+
var errorUtils = {};
|
|
1012
|
+
|
|
1013
|
+
var hasRequiredErrorUtils;
|
|
1014
|
+
function requireErrorUtils() {
|
|
1015
|
+
if (hasRequiredErrorUtils) return errorUtils;
|
|
1016
|
+
hasRequiredErrorUtils = 1;
|
|
1017
|
+
Object.defineProperty(errorUtils, "__esModule", { value: true });
|
|
1018
|
+
errorUtils.getErrorMessageFromException = getErrorMessageFromException;
|
|
1019
|
+
function isErrorWithMessage(error) {
|
|
1020
|
+
return typeof error === "object" && error !== null && "message" in error && typeof error.message === "string";
|
|
1021
|
+
}
|
|
1022
|
+
function getErrorMessageFromException(error) {
|
|
1023
|
+
if (isErrorWithMessage(error)) {
|
|
1024
|
+
return error.message;
|
|
1025
|
+
}
|
|
1026
|
+
return String(error);
|
|
1027
|
+
}
|
|
1028
|
+
return errorUtils;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
var hasRequiredValidateJsonSchema;
|
|
1032
|
+
function requireValidateJsonSchema() {
|
|
1033
|
+
if (hasRequiredValidateJsonSchema) return validateJsonSchema;
|
|
1034
|
+
hasRequiredValidateJsonSchema = 1;
|
|
1035
|
+
Object.defineProperty(validateJsonSchema, "__esModule", { value: true });
|
|
1036
|
+
validateJsonSchema.validateJsonSchema = void 0;
|
|
1037
|
+
const error_utils_1 = requireErrorUtils();
|
|
1038
|
+
const ajv_instances_1 = requireAjvInstances();
|
|
1039
|
+
const validateJsonSchema$1 = (schema) => {
|
|
1040
|
+
if (!schema || typeof schema !== "object") {
|
|
1041
|
+
return {
|
|
1042
|
+
kind: "validation-error",
|
|
1043
|
+
message: "Schema must be a valid object"
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
const ajvInstance = ajv_instances_1.ajvInstances.getInstanceForSchema(schema);
|
|
1047
|
+
const isValidSchema = ajvInstance.validateSchema(schema);
|
|
1048
|
+
let errors = "";
|
|
1049
|
+
if (ajvInstance.errors) {
|
|
1050
|
+
errors = ajvInstance.errors.map((e) => JSON.stringify(e, null, 2)).join("; ");
|
|
1051
|
+
} else if (isValidSchema) {
|
|
1052
|
+
try {
|
|
1053
|
+
ajvInstance.compile(schema);
|
|
1054
|
+
return true;
|
|
1055
|
+
} catch (e) {
|
|
1056
|
+
errors = (0, error_utils_1.getErrorMessageFromException)(e);
|
|
1057
|
+
}
|
|
1058
|
+
} else {
|
|
1059
|
+
errors = "unexpected-situation-no-errors-found-for-invalid-schema";
|
|
1060
|
+
}
|
|
1061
|
+
return {
|
|
1062
|
+
kind: "validation-error",
|
|
1063
|
+
message: `Unable to validate JSON schema: ${errors}`
|
|
1064
|
+
};
|
|
1065
|
+
};
|
|
1066
|
+
validateJsonSchema.validateJsonSchema = validateJsonSchema$1;
|
|
1067
|
+
return validateJsonSchema;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
var stableStringify = {};
|
|
1071
|
+
|
|
1072
|
+
var hasRequiredStableStringify;
|
|
1073
|
+
function requireStableStringify() {
|
|
1074
|
+
if (hasRequiredStableStringify) return stableStringify;
|
|
1075
|
+
hasRequiredStableStringify = 1;
|
|
1076
|
+
Object.defineProperty(stableStringify, "__esModule", { value: true });
|
|
1077
|
+
stableStringify.stableStringify = stableStringify$1;
|
|
1078
|
+
function stableStringify$1(value) {
|
|
1079
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
1080
|
+
const sorter = (_key, currentValue) => {
|
|
1081
|
+
if (currentValue && typeof currentValue === "object" && !Array.isArray(currentValue)) {
|
|
1082
|
+
if (seen.has(currentValue)) {
|
|
1083
|
+
return currentValue;
|
|
1084
|
+
}
|
|
1085
|
+
seen.add(currentValue);
|
|
1086
|
+
return Object.keys(currentValue).sort().reduce((acc, key) => {
|
|
1087
|
+
acc[key] = currentValue[key];
|
|
1088
|
+
return acc;
|
|
1089
|
+
}, {});
|
|
1090
|
+
}
|
|
1091
|
+
return currentValue;
|
|
1092
|
+
};
|
|
1093
|
+
return JSON.stringify(value, sorter) ?? "";
|
|
1094
|
+
}
|
|
1095
|
+
return stableStringify;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
var schemaUtils = {};
|
|
1099
|
+
|
|
1100
|
+
var hasRequiredSchemaUtils;
|
|
1101
|
+
function requireSchemaUtils() {
|
|
1102
|
+
if (hasRequiredSchemaUtils) return schemaUtils;
|
|
1103
|
+
hasRequiredSchemaUtils = 1;
|
|
1104
|
+
Object.defineProperty(schemaUtils, "__esModule", { value: true });
|
|
1105
|
+
schemaUtils.wrapArraySchema = wrapArraySchema;
|
|
1106
|
+
schemaUtils.unwrapArraySchema = unwrapArraySchema;
|
|
1107
|
+
function wrapArraySchema(schema, options) {
|
|
1108
|
+
const { primaryKey, outputName } = options;
|
|
1109
|
+
const schemaVersion = typeof schema.$schema === "string" ? schema.$schema : void 0;
|
|
1110
|
+
const wrappedSchema = {
|
|
1111
|
+
type: "array",
|
|
1112
|
+
items: {
|
|
1113
|
+
type: "object",
|
|
1114
|
+
required: [primaryKey, outputName],
|
|
1115
|
+
properties: {
|
|
1116
|
+
[primaryKey]: {
|
|
1117
|
+
anyOf: [{ type: "string" }, { type: "number" }, { type: "integer" }]
|
|
1118
|
+
},
|
|
1119
|
+
[outputName]: schema
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
};
|
|
1123
|
+
if (schemaVersion) {
|
|
1124
|
+
wrappedSchema.$schema = schemaVersion;
|
|
1125
|
+
}
|
|
1126
|
+
return wrappedSchema;
|
|
1127
|
+
}
|
|
1128
|
+
function unwrapArraySchema(wrappedSchema, outputName) {
|
|
1129
|
+
const items = wrappedSchema.items;
|
|
1130
|
+
if (!items || typeof items !== "object") {
|
|
1131
|
+
return null;
|
|
1132
|
+
}
|
|
1133
|
+
const properties = items.properties;
|
|
1134
|
+
if (!properties || typeof properties !== "object") {
|
|
1135
|
+
return null;
|
|
1136
|
+
}
|
|
1137
|
+
return properties[outputName] ?? null;
|
|
1138
|
+
}
|
|
1139
|
+
return schemaUtils;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
var hasRequiredDist;
|
|
1143
|
+
function requireDist() {
|
|
1144
|
+
if (hasRequiredDist) return dist;
|
|
1145
|
+
hasRequiredDist = 1;
|
|
1146
|
+
(function(exports$1) {
|
|
1147
|
+
var __createBinding = dist && dist.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
1148
|
+
if (k2 === void 0) k2 = k;
|
|
1149
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
1150
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
1151
|
+
desc = { enumerable: true, get: function() {
|
|
1152
|
+
return m[k];
|
|
1153
|
+
} };
|
|
1154
|
+
}
|
|
1155
|
+
Object.defineProperty(o, k2, desc);
|
|
1156
|
+
}) : (function(o, m, k, k2) {
|
|
1157
|
+
if (k2 === void 0) k2 = k;
|
|
1158
|
+
o[k2] = m[k];
|
|
1159
|
+
}));
|
|
1160
|
+
var __exportStar = dist && dist.__exportStar || function(m, exports2) {
|
|
1161
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
|
|
1162
|
+
};
|
|
1163
|
+
var __importDefault = dist && dist.__importDefault || function(mod) {
|
|
1164
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
1165
|
+
};
|
|
1166
|
+
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
1167
|
+
exports$1.stableStringify = exports$1.validateJsonSchema = exports$1.providerConfigs = exports$1.normalizedUsageZero = exports$1.castArrayPromptBuilder = exports$1.castPromptBuilder = void 0;
|
|
1168
|
+
__exportStar(requireNuaLlmClient(), exports$1);
|
|
1169
|
+
__exportStar(requireLogger(), exports$1);
|
|
1170
|
+
__exportStar(requireTypes(), exports$1);
|
|
1171
|
+
__exportStar(requireNuaErrors(), exports$1);
|
|
1172
|
+
var cast_prompt_builder_1 = requireCastPromptBuilder();
|
|
1173
|
+
Object.defineProperty(exports$1, "castPromptBuilder", { enumerable: true, get: function() {
|
|
1174
|
+
return __importDefault(cast_prompt_builder_1).default;
|
|
1175
|
+
} });
|
|
1176
|
+
var cast_array_prompt_builder_1 = requireCastArrayPromptBuilder();
|
|
1177
|
+
Object.defineProperty(exports$1, "castArrayPromptBuilder", { enumerable: true, get: function() {
|
|
1178
|
+
return __importDefault(cast_array_prompt_builder_1).default;
|
|
1179
|
+
} });
|
|
1180
|
+
var provider_config_1 = requireProviderConfig();
|
|
1181
|
+
Object.defineProperty(exports$1, "normalizedUsageZero", { enumerable: true, get: function() {
|
|
1182
|
+
return provider_config_1.normalizedUsageZero;
|
|
1183
|
+
} });
|
|
1184
|
+
Object.defineProperty(exports$1, "providerConfigs", { enumerable: true, get: function() {
|
|
1185
|
+
return provider_config_1.providerConfigs;
|
|
1186
|
+
} });
|
|
1187
|
+
var validate_json_schema_1 = requireValidateJsonSchema();
|
|
1188
|
+
Object.defineProperty(exports$1, "validateJsonSchema", { enumerable: true, get: function() {
|
|
1189
|
+
return validate_json_schema_1.validateJsonSchema;
|
|
1190
|
+
} });
|
|
1191
|
+
var stable_stringify_1 = requireStableStringify();
|
|
1192
|
+
Object.defineProperty(exports$1, "stableStringify", { enumerable: true, get: function() {
|
|
1193
|
+
return stable_stringify_1.stableStringify;
|
|
1194
|
+
} });
|
|
1195
|
+
__exportStar(requireModelInfo(), exports$1);
|
|
1196
|
+
__exportStar(requireSchemaUtils(), exports$1);
|
|
1197
|
+
})(dist);
|
|
1198
|
+
return dist;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
var distExports = requireDist();
|
|
1202
|
+
|
|
1203
|
+
const normalizedUsageZero = {
|
|
1204
|
+
promptTokens: 0,
|
|
1205
|
+
completionTokens: 0,
|
|
1206
|
+
totalTokens: 0
|
|
1207
|
+
};
|
|
1208
|
+
class DirectBackend {
|
|
1209
|
+
constructor(config) {
|
|
1210
|
+
if (!config.model) {
|
|
1211
|
+
throw new Error("model is required for direct mode");
|
|
1212
|
+
}
|
|
1213
|
+
this.model = config.model;
|
|
1214
|
+
this.client = new distExports.NuaLlmClient({ providers: config.providers });
|
|
1215
|
+
}
|
|
1216
|
+
async castValue(params) {
|
|
1217
|
+
const startTime = Date.now();
|
|
1218
|
+
const result = await this.client.castValue({
|
|
1219
|
+
model: this.model,
|
|
1220
|
+
input: { prompt: params.prompt, data: params.data },
|
|
1221
|
+
output: { name: params.outputName, effectiveSchema: params.outputSchema }
|
|
1222
|
+
});
|
|
1223
|
+
const latencyMs = Date.now() - startTime;
|
|
1224
|
+
if (!result.success) {
|
|
1225
|
+
return {
|
|
1226
|
+
success: false,
|
|
1227
|
+
error: result.error || "Unknown error",
|
|
1228
|
+
source: "direct",
|
|
1229
|
+
latencyMs
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
return {
|
|
1233
|
+
success: true,
|
|
1234
|
+
data: result.data,
|
|
1235
|
+
usage: result.usage || normalizedUsageZero,
|
|
1236
|
+
model: this.model,
|
|
1237
|
+
latencyMs,
|
|
1238
|
+
source: "direct",
|
|
1239
|
+
meta: {}
|
|
1240
|
+
};
|
|
1241
|
+
}
|
|
1242
|
+
async castArray(params) {
|
|
1243
|
+
const startTime = Date.now();
|
|
1244
|
+
const wrappedSchema = distExports.wrapArraySchema(params.outputSchema, {
|
|
1245
|
+
primaryKey: params.primaryKey,
|
|
1246
|
+
outputName: params.outputName
|
|
1247
|
+
});
|
|
1248
|
+
const result = await this.client.castArray({
|
|
1249
|
+
model: this.model,
|
|
1250
|
+
data: params.data,
|
|
1251
|
+
input: { prompt: params.prompt, primaryKey: params.primaryKey },
|
|
1252
|
+
output: { name: params.outputName, effectiveSchema: wrappedSchema }
|
|
1253
|
+
});
|
|
1254
|
+
const latencyMs = Date.now() - startTime;
|
|
1255
|
+
if (!result.success) {
|
|
1256
|
+
return {
|
|
1257
|
+
success: false,
|
|
1258
|
+
error: result.error || "Unknown error",
|
|
1259
|
+
source: "direct",
|
|
1260
|
+
latencyMs
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1263
|
+
return {
|
|
1264
|
+
success: true,
|
|
1265
|
+
data: result.data,
|
|
1266
|
+
usage: result.usage || normalizedUsageZero,
|
|
1267
|
+
model: this.model,
|
|
1268
|
+
latencyMs,
|
|
1269
|
+
source: "direct",
|
|
1270
|
+
meta: {}
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
function resolveConfigValue(config, key, envVar) {
|
|
1276
|
+
if (config[key]) return config[key];
|
|
1277
|
+
const pe = globalThis.process;
|
|
1278
|
+
const isNode = !!pe?.versions?.node;
|
|
1279
|
+
if (isNode) {
|
|
1280
|
+
return pe?.env?.[envVar];
|
|
1281
|
+
}
|
|
1282
|
+
return void 0;
|
|
54
1283
|
}
|
|
55
1284
|
|
|
56
1285
|
const isBrowserEnvironment = () => typeof window !== "undefined" && !!window.document;
|
|
57
|
-
class
|
|
1286
|
+
class AuthTokenManager {
|
|
58
1287
|
constructor(config) {
|
|
59
1288
|
this.apiKey = resolveConfigValue(config, "apiKey", "NUABASE_API_KEY") || void 0;
|
|
60
1289
|
this.fetchToken = config.fetchToken;
|
|
@@ -96,403 +1325,262 @@ class NuabaseAuthTokenManager {
|
|
|
96
1325
|
return this.pendingTokenPromise;
|
|
97
1326
|
}
|
|
98
1327
|
}
|
|
99
|
-
|
|
100
|
-
|
|
1328
|
+
|
|
1329
|
+
async function parseErrorResponse(response, urlPath) {
|
|
1330
|
+
const fallbackMessage = `Request to ${urlPath} failed with status ${response.status}${response.statusText ? ` ${response.statusText}` : ""}`;
|
|
1331
|
+
let responseBody = "";
|
|
1332
|
+
try {
|
|
1333
|
+
responseBody = (await response.text()).trim();
|
|
1334
|
+
} catch {
|
|
1335
|
+
return { error: fallbackMessage, isError: true };
|
|
1336
|
+
}
|
|
1337
|
+
if (!responseBody) {
|
|
1338
|
+
return { error: fallbackMessage, isError: true };
|
|
1339
|
+
}
|
|
1340
|
+
const parsedBody = safeParseJson(responseBody);
|
|
1341
|
+
if (parsedBody && typeof parsedBody === "object") {
|
|
1342
|
+
const errorMessage = extractErrorMessage(parsedBody);
|
|
1343
|
+
if (errorMessage) {
|
|
1344
|
+
return { error: errorMessage, isError: true };
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
return { error: responseBody, isError: true };
|
|
1348
|
+
}
|
|
1349
|
+
function safeParseJson(payload) {
|
|
1350
|
+
try {
|
|
1351
|
+
return JSON.parse(payload);
|
|
1352
|
+
} catch {
|
|
1353
|
+
return void 0;
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
function extractErrorMessage(body) {
|
|
1357
|
+
const parts = [];
|
|
1358
|
+
const error = body["error"];
|
|
1359
|
+
if (typeof error === "string" && error.trim()) {
|
|
1360
|
+
parts.push(error.trim());
|
|
1361
|
+
}
|
|
1362
|
+
const message = body["message"];
|
|
1363
|
+
if (typeof message === "string" && message.trim()) {
|
|
1364
|
+
parts.push(message.trim());
|
|
1365
|
+
}
|
|
1366
|
+
if (parts.length === 0) return void 0;
|
|
1367
|
+
return parts.join(". ");
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
function isErrorWithMessage(error) {
|
|
1371
|
+
return typeof error === "object" && error !== null && "message" in error && typeof error.message === "string";
|
|
1372
|
+
}
|
|
1373
|
+
function getErrorMessageFromException(error) {
|
|
1374
|
+
if (isErrorWithMessage(error)) {
|
|
1375
|
+
return error.message;
|
|
1376
|
+
}
|
|
1377
|
+
return String(error);
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
function isErrorResponse(response) {
|
|
1381
|
+
return Boolean(response && typeof response === "object" && "error" in response);
|
|
1382
|
+
}
|
|
1383
|
+
class GatewayBackend {
|
|
1384
|
+
constructor(config) {
|
|
101
1385
|
this.baseUrl = resolveConfigValue(config, "baseUrl", "NUABASE_API_URL") || "https://api.nuabase.com";
|
|
102
|
-
this.
|
|
1386
|
+
this.authManager = new AuthTokenManager(config);
|
|
103
1387
|
}
|
|
104
|
-
async
|
|
105
|
-
const
|
|
1388
|
+
async castValue(params) {
|
|
1389
|
+
const startTime = Date.now();
|
|
1390
|
+
const response = await this.post("cast/value/now", {
|
|
1391
|
+
input: { prompt: params.prompt, data: params.data },
|
|
1392
|
+
output: { name: params.outputName, schema: params.outputSchema }
|
|
1393
|
+
});
|
|
1394
|
+
const latencyMs = Date.now() - startTime;
|
|
1395
|
+
if (isErrorResponse(response)) {
|
|
1396
|
+
return { success: false, error: response.error, source: "gateway", latencyMs };
|
|
1397
|
+
}
|
|
1398
|
+
const apiResponse = response;
|
|
1399
|
+
const usage = {
|
|
1400
|
+
promptTokens: apiResponse.llmUsage.promptTokens + apiResponse.cacheUsage.promptTokens,
|
|
1401
|
+
completionTokens: apiResponse.llmUsage.completionTokens + apiResponse.cacheUsage.completionTokens,
|
|
1402
|
+
totalTokens: apiResponse.llmUsage.totalTokens + apiResponse.cacheUsage.totalTokens
|
|
1403
|
+
};
|
|
1404
|
+
return {
|
|
1405
|
+
success: true,
|
|
1406
|
+
data: apiResponse.data,
|
|
1407
|
+
usage,
|
|
1408
|
+
model: apiResponse.model ?? "unknown",
|
|
1409
|
+
latencyMs,
|
|
1410
|
+
source: "gateway",
|
|
1411
|
+
meta: {
|
|
1412
|
+
requestId: apiResponse.llmRequestId,
|
|
1413
|
+
cached: apiResponse.isCacheHit,
|
|
1414
|
+
llmUsage: apiResponse.llmUsage,
|
|
1415
|
+
cacheUsage: apiResponse.cacheUsage
|
|
1416
|
+
}
|
|
1417
|
+
};
|
|
1418
|
+
}
|
|
1419
|
+
async castArray(params) {
|
|
1420
|
+
const startTime = Date.now();
|
|
1421
|
+
const response = await this.post("cast/array/now", {
|
|
1422
|
+
input: { prompt: params.prompt, data: params.data, primaryKey: params.primaryKey },
|
|
1423
|
+
output: { name: params.outputName, schema: params.outputSchema }
|
|
1424
|
+
});
|
|
1425
|
+
const latencyMs = Date.now() - startTime;
|
|
1426
|
+
if (isErrorResponse(response)) {
|
|
1427
|
+
return { success: false, error: response.error, source: "gateway", latencyMs };
|
|
1428
|
+
}
|
|
1429
|
+
const apiResponse = response;
|
|
1430
|
+
const usage = {
|
|
1431
|
+
promptTokens: apiResponse.llmUsage.promptTokens + apiResponse.cacheUsage.promptTokens,
|
|
1432
|
+
completionTokens: apiResponse.llmUsage.completionTokens + apiResponse.cacheUsage.completionTokens,
|
|
1433
|
+
totalTokens: apiResponse.llmUsage.totalTokens + apiResponse.cacheUsage.totalTokens
|
|
1434
|
+
};
|
|
1435
|
+
return {
|
|
1436
|
+
success: true,
|
|
1437
|
+
data: apiResponse.data,
|
|
1438
|
+
usage,
|
|
1439
|
+
model: apiResponse.model ?? "unknown",
|
|
1440
|
+
latencyMs,
|
|
1441
|
+
source: "gateway",
|
|
1442
|
+
meta: {
|
|
1443
|
+
requestId: apiResponse.llmRequestId,
|
|
1444
|
+
cached: apiResponse.cacheHits === apiResponse.data.length,
|
|
1445
|
+
llmUsage: apiResponse.llmUsage,
|
|
1446
|
+
cacheUsage: apiResponse.cacheUsage
|
|
1447
|
+
}
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
async queueCastValue(params) {
|
|
1451
|
+
const response = await this.post("cast/value", {
|
|
1452
|
+
input: { prompt: params.prompt, data: params.data },
|
|
1453
|
+
output: { name: params.outputName, schema: params.outputSchema }
|
|
1454
|
+
});
|
|
1455
|
+
if (isErrorResponse(response)) {
|
|
1456
|
+
return { success: false, error: response.error, source: "gateway" };
|
|
1457
|
+
}
|
|
1458
|
+
const apiResponse = response;
|
|
1459
|
+
return { success: true, jobId: apiResponse.jobId, source: "gateway" };
|
|
1460
|
+
}
|
|
1461
|
+
async queueCastArray(params) {
|
|
1462
|
+
const response = await this.post("cast/array", {
|
|
1463
|
+
input: { prompt: params.prompt, data: params.data, primaryKey: params.primaryKey },
|
|
1464
|
+
output: { name: params.outputName, schema: params.outputSchema }
|
|
1465
|
+
});
|
|
1466
|
+
if (isErrorResponse(response)) {
|
|
1467
|
+
return { success: false, error: response.error, source: "gateway" };
|
|
1468
|
+
}
|
|
1469
|
+
const apiResponse = response;
|
|
1470
|
+
return { success: true, jobId: apiResponse.jobId, source: "gateway" };
|
|
1471
|
+
}
|
|
1472
|
+
async post(path, body) {
|
|
1473
|
+
const url = `${this.baseUrl}/${path}`;
|
|
106
1474
|
let response;
|
|
107
|
-
const hasBody = method !== "GET" && params !== void 0;
|
|
108
1475
|
const headers = {
|
|
109
|
-
Authorization: `Bearer ${await this.
|
|
1476
|
+
Authorization: `Bearer ${await this.authManager.getToken()}`,
|
|
1477
|
+
"Content-Type": "application/json"
|
|
110
1478
|
};
|
|
111
|
-
if (hasBody) {
|
|
112
|
-
headers["Content-Type"] = "application/json";
|
|
113
|
-
}
|
|
114
1479
|
try {
|
|
115
1480
|
response = await fetch(url, {
|
|
116
|
-
method,
|
|
1481
|
+
method: "POST",
|
|
117
1482
|
headers,
|
|
118
|
-
body:
|
|
1483
|
+
body: JSON.stringify(body)
|
|
119
1484
|
});
|
|
120
1485
|
} catch (e) {
|
|
121
1486
|
return { error: `Error calling Nuabase API: ${getErrorMessageFromException(e)}` };
|
|
122
1487
|
}
|
|
123
|
-
let result;
|
|
124
1488
|
if (!response.ok) {
|
|
125
|
-
return await parseErrorResponse(response,
|
|
1489
|
+
return await parseErrorResponse(response, path);
|
|
126
1490
|
}
|
|
127
1491
|
try {
|
|
128
|
-
|
|
1492
|
+
return await response.json();
|
|
129
1493
|
} catch {
|
|
130
1494
|
return { error: "Invalid response received from Nuabase API call, unable to parse" };
|
|
131
1495
|
}
|
|
132
|
-
return result;
|
|
133
1496
|
}
|
|
134
1497
|
}
|
|
135
1498
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}).strict();
|
|
140
|
-
|
|
141
|
-
const validateArrayRequestParams = (data, primaryKeyName) => {
|
|
142
|
-
if (!Array.isArray(data)) {
|
|
143
|
-
throw new Error("`data` must be an array of objects.");
|
|
1499
|
+
class Nua {
|
|
1500
|
+
constructor(backend) {
|
|
1501
|
+
this.backend = backend;
|
|
144
1502
|
}
|
|
145
|
-
|
|
146
|
-
|
|
1503
|
+
static gateway(config) {
|
|
1504
|
+
return new Nua(new GatewayBackend(config));
|
|
147
1505
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
1506
|
+
static direct(config) {
|
|
1507
|
+
return new Nua(new DirectBackend(config));
|
|
1508
|
+
}
|
|
1509
|
+
// Implementation
|
|
1510
|
+
async get(prompt, options) {
|
|
1511
|
+
if (typeof prompt !== "string" || prompt.trim() === "") {
|
|
1512
|
+
throw new TypeError("Prompt must be a non-empty string");
|
|
154
1513
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const zs_ResponseRecord = (primaryKeyName, outputKey, outputSchema) => {
|
|
165
|
-
const primaryKeySchema = z.any();
|
|
166
|
-
const shape = {
|
|
167
|
-
[primaryKeyName]: primaryKeySchema,
|
|
168
|
-
[outputKey]: outputSchema
|
|
169
|
-
};
|
|
170
|
-
return z.object(shape).strict();
|
|
171
|
-
};
|
|
172
|
-
const createNuaApiResponseCastArray = (primaryKeyName, outputKey, outputSchema) => {
|
|
173
|
-
const recordSchema = zs_ResponseRecord(
|
|
174
|
-
primaryKeyName,
|
|
175
|
-
outputKey,
|
|
176
|
-
outputSchema
|
|
177
|
-
);
|
|
178
|
-
const dataSchema = z.array(recordSchema);
|
|
179
|
-
return z.object({
|
|
180
|
-
llmRequestId: z.string(),
|
|
181
|
-
kind: z.literal("cast/array"),
|
|
182
|
-
data: dataSchema,
|
|
183
|
-
cacheHits: z.number(),
|
|
184
|
-
rowsWithNoResults: z.array(z.string()),
|
|
185
|
-
isSuccess: z.literal(true),
|
|
186
|
-
isError: z.optional(z.literal(false)),
|
|
187
|
-
usage: zs_NormalizedUsage
|
|
188
|
-
}).strict();
|
|
189
|
-
};
|
|
190
|
-
const zs_NuaApiResponse_CastArray = createNuaApiResponseCastArray;
|
|
191
|
-
|
|
192
|
-
const zs_ArrayFnDef = z.object({
|
|
193
|
-
prompt: z.string(),
|
|
194
|
-
output: z.object({
|
|
195
|
-
name: z.string(),
|
|
196
|
-
schema: z.custom(
|
|
197
|
-
(value) => value instanceof z.ZodType,
|
|
198
|
-
"Expected a Zod schema"
|
|
199
|
-
)
|
|
200
|
-
})
|
|
201
|
-
});
|
|
202
|
-
const validateArrayFnDef = (fnDef) => {
|
|
203
|
-
const parsed = zs_ArrayFnDef.safeParse(fnDef);
|
|
204
|
-
if (!parsed.success) {
|
|
205
|
-
const message = z.prettifyError(parsed.error);
|
|
206
|
-
throw new TypeError(`Invalid array function definition: ${message}`);
|
|
207
|
-
}
|
|
208
|
-
return parsed.data;
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
function addOriginalInputRows(inputRows, outputRows, primaryKeyName) {
|
|
212
|
-
const lookup = /* @__PURE__ */ new Map();
|
|
213
|
-
for (const row of inputRows) {
|
|
214
|
-
lookup.set(row[primaryKeyName], row);
|
|
1514
|
+
const outputSchema = options?.output?.schema ?? z.string();
|
|
1515
|
+
const outputName = options?.output?.name ?? "result";
|
|
1516
|
+
const jsonSchema = z.toJSONSchema(outputSchema);
|
|
1517
|
+
return this.backend.castValue({
|
|
1518
|
+
prompt,
|
|
1519
|
+
data: options?.input ?? null,
|
|
1520
|
+
outputName,
|
|
1521
|
+
outputSchema: jsonSchema
|
|
1522
|
+
});
|
|
215
1523
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
throw new Error(
|
|
221
|
-
`Unable to locate source row for primary key "${String(primaryKeyValue)}" in cast array response.`
|
|
222
|
-
);
|
|
1524
|
+
// ========== list() - Array Operations ==========
|
|
1525
|
+
async list(prompt, options) {
|
|
1526
|
+
if (typeof prompt !== "string" || prompt.trim() === "") {
|
|
1527
|
+
throw new TypeError("Prompt must be a non-empty string");
|
|
223
1528
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
sourceRow
|
|
227
|
-
};
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
const toCastArrayApiRequest = (prompt, data, primaryKeyName, outputName, outputSchema) => ({
|
|
231
|
-
input: {
|
|
232
|
-
prompt,
|
|
233
|
-
data,
|
|
234
|
-
primaryKey: primaryKeyName
|
|
235
|
-
},
|
|
236
|
-
output: {
|
|
237
|
-
schema: outputSchema,
|
|
238
|
-
name: outputName
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
const createArrayFn = (client, inputFnDef) => {
|
|
242
|
-
const fnDef = validateArrayFnDef(inputFnDef);
|
|
243
|
-
const outputJsonSchema = z.toJSONSchema(fnDef.output.schema);
|
|
244
|
-
const toNuabaseError = (response) => {
|
|
245
|
-
if (response && typeof response === "object" && "error" in response)
|
|
246
|
-
return { error: String(response.error), isError: true };
|
|
247
|
-
return void 0;
|
|
248
|
-
};
|
|
249
|
-
const queueFn = async (data, primaryKeyName) => {
|
|
250
|
-
validateArrayRequestParams(data, primaryKeyName);
|
|
251
|
-
const response = await client.request(
|
|
252
|
-
"POST",
|
|
253
|
-
"cast/array",
|
|
254
|
-
toCastArrayApiRequest(
|
|
255
|
-
fnDef.prompt,
|
|
256
|
-
data,
|
|
257
|
-
primaryKeyName,
|
|
258
|
-
fnDef.output.name,
|
|
259
|
-
outputJsonSchema
|
|
260
|
-
)
|
|
261
|
-
);
|
|
262
|
-
const error = toNuabaseError(response);
|
|
263
|
-
if (error) return error;
|
|
264
|
-
const parsedResponse = zs_NuaQueuedResponse.safeParse(response);
|
|
265
|
-
if (!parsedResponse.success) {
|
|
266
|
-
const emsg = z.prettifyError(parsedResponse.error);
|
|
267
|
-
return { error: `Invalid queued response received from Nuabase API: ${emsg}`, isError: true };
|
|
268
|
-
}
|
|
269
|
-
return parsedResponse.data;
|
|
270
|
-
};
|
|
271
|
-
const baseNowFn = async (data, primaryKeyName) => {
|
|
272
|
-
validateArrayRequestParams(data, primaryKeyName);
|
|
273
|
-
const response = await client.request(
|
|
274
|
-
"POST",
|
|
275
|
-
"cast/array/now",
|
|
276
|
-
toCastArrayApiRequest(
|
|
277
|
-
fnDef.prompt,
|
|
278
|
-
data,
|
|
279
|
-
primaryKeyName,
|
|
280
|
-
fnDef.output.name,
|
|
281
|
-
outputJsonSchema
|
|
282
|
-
)
|
|
283
|
-
);
|
|
284
|
-
const error = toNuabaseError(response);
|
|
285
|
-
if (error) return error;
|
|
286
|
-
const outputKey = fnDef.output.name;
|
|
287
|
-
const successSchema = zs_NuaApiResponse_CastArray(primaryKeyName, outputKey, fnDef.output.schema);
|
|
288
|
-
const parsedResponse = successSchema.safeParse(response);
|
|
289
|
-
if (!parsedResponse.success) {
|
|
290
|
-
const emsg = z.prettifyError(parsedResponse.error);
|
|
291
|
-
return { error: `Invalid data received from Nuabase API: ${emsg}`, isError: true };
|
|
1529
|
+
if (!Array.isArray(options.input)) {
|
|
1530
|
+
throw new TypeError("Input must be an array for list()");
|
|
292
1531
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
llmRequestId: parsedResponse.data.llmRequestId,
|
|
296
|
-
kind: parsedResponse.data.kind,
|
|
297
|
-
data: addOriginalInputRows(
|
|
298
|
-
data,
|
|
299
|
-
parsedResponse.data.data,
|
|
300
|
-
primaryKeyName
|
|
301
|
-
),
|
|
302
|
-
rowsWithNoResults: parsedResponse.data.rowsWithNoResults,
|
|
303
|
-
cacheHits: parsedResponse.data.cacheHits,
|
|
304
|
-
usage: parsedResponse.data.usage
|
|
305
|
-
};
|
|
306
|
-
};
|
|
307
|
-
return Object.assign(baseNowFn, {
|
|
308
|
-
queue: queueFn
|
|
309
|
-
});
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
const createNuaApiResponseCastValue = (outputKey, outputSchema) => {
|
|
313
|
-
return z.object({
|
|
314
|
-
llmRequestId: z.string(),
|
|
315
|
-
kind: z.literal("cast/value"),
|
|
316
|
-
data: outputSchema,
|
|
317
|
-
isCacheHit: z.boolean(),
|
|
318
|
-
isSuccess: z.literal(true),
|
|
319
|
-
isError: z.optional(z.literal(false)),
|
|
320
|
-
usage: zs_NormalizedUsage
|
|
321
|
-
}).strict();
|
|
322
|
-
};
|
|
323
|
-
const zs_NuaApiResponse_CastValue = createNuaApiResponseCastValue;
|
|
324
|
-
|
|
325
|
-
const zs_ValueFnDef = z.object({
|
|
326
|
-
prompt: z.string(),
|
|
327
|
-
output: z.object({
|
|
328
|
-
name: z.string(),
|
|
329
|
-
schema: z.custom(
|
|
330
|
-
(value) => value instanceof z.ZodType,
|
|
331
|
-
"Expected a Zod schema for `output.schema`"
|
|
332
|
-
)
|
|
333
|
-
})
|
|
334
|
-
});
|
|
335
|
-
const validateValueFnDef = (fnDef) => {
|
|
336
|
-
const parsed = zs_ValueFnDef.safeParse(fnDef);
|
|
337
|
-
if (!parsed.success) {
|
|
338
|
-
const message = z.prettifyError(parsed.error);
|
|
339
|
-
throw new TypeError(`Invalid value function definition: ${message}`);
|
|
340
|
-
}
|
|
341
|
-
return parsed.data;
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
const toCastValueApiRequest = (prompt, data, outputName, outputSchema) => ({
|
|
345
|
-
input: {
|
|
346
|
-
prompt,
|
|
347
|
-
data
|
|
348
|
-
},
|
|
349
|
-
output: {
|
|
350
|
-
schema: outputSchema,
|
|
351
|
-
name: outputName
|
|
352
|
-
}
|
|
353
|
-
});
|
|
354
|
-
const createValueFn = (client, inputFnDef) => {
|
|
355
|
-
const fnDef = validateValueFnDef(inputFnDef);
|
|
356
|
-
const outputJsonSchema = z.toJSONSchema(fnDef.output.schema);
|
|
357
|
-
const toNuabaseError = (response) => {
|
|
358
|
-
if (response && typeof response === "object" && "error" in response)
|
|
359
|
-
return { error: String(response.error), isError: true };
|
|
360
|
-
return void 0;
|
|
361
|
-
};
|
|
362
|
-
const sendRequest = async (path, data) => client.request(
|
|
363
|
-
"POST",
|
|
364
|
-
path,
|
|
365
|
-
toCastValueApiRequest(fnDef.prompt, data, fnDef.output.name, outputJsonSchema)
|
|
366
|
-
);
|
|
367
|
-
const queueFn = async (data) => {
|
|
368
|
-
const response = await sendRequest("cast/value", data);
|
|
369
|
-
const error = toNuabaseError(response);
|
|
370
|
-
if (error) return error;
|
|
371
|
-
const parsedResponse = zs_NuaQueuedResponse.safeParse(response);
|
|
372
|
-
if (!parsedResponse.success) {
|
|
373
|
-
const emsg = z.prettifyError(parsedResponse.error);
|
|
374
|
-
return { error: `Invalid queued response received from Nuabase API: ${emsg}`, isError: true };
|
|
375
|
-
}
|
|
376
|
-
return parsedResponse.data;
|
|
377
|
-
};
|
|
378
|
-
const baseNowFn = async (data) => {
|
|
379
|
-
const response = await sendRequest("cast/value/now", data);
|
|
380
|
-
const error = toNuabaseError(response);
|
|
381
|
-
if (error) return error;
|
|
382
|
-
const outputKey = fnDef.output.name;
|
|
383
|
-
const successSchema = zs_NuaApiResponse_CastValue(
|
|
384
|
-
outputKey,
|
|
385
|
-
fnDef.output.schema
|
|
386
|
-
);
|
|
387
|
-
const parsedResponse = successSchema.safeParse(response);
|
|
388
|
-
if (!parsedResponse.success) {
|
|
389
|
-
const emsg = z.prettifyError(parsedResponse.error);
|
|
390
|
-
return { error: `Invalid data received from Nuabase API: ${emsg}`, isError: true };
|
|
1532
|
+
if (typeof options.primaryKey !== "string" || options.primaryKey.trim() === "") {
|
|
1533
|
+
throw new TypeError("primaryKey must be a non-empty string");
|
|
391
1534
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
};
|
|
400
|
-
};
|
|
401
|
-
return Object.assign(baseNowFn, {
|
|
402
|
-
queue: queueFn
|
|
403
|
-
});
|
|
404
|
-
};
|
|
405
|
-
|
|
406
|
-
const errorParseFailed = {
|
|
407
|
-
kind: "internal-error",
|
|
408
|
-
message: "Unable to parse stored LLM result"
|
|
409
|
-
};
|
|
410
|
-
const dateFromIso = z.preprocess(
|
|
411
|
-
(value) => {
|
|
412
|
-
if (value == null) return null;
|
|
413
|
-
if (value instanceof Date) return value;
|
|
414
|
-
if (typeof value === "string") {
|
|
415
|
-
const parsed = new Date(value);
|
|
416
|
-
if (!Number.isNaN(parsed.getTime())) return parsed;
|
|
417
|
-
}
|
|
418
|
-
return z.NEVER;
|
|
419
|
-
},
|
|
420
|
-
z.union([z.date(), z.null()])
|
|
421
|
-
);
|
|
422
|
-
const mandatoryDateFromIso = z.preprocess((value) => {
|
|
423
|
-
if (value instanceof Date) return value;
|
|
424
|
-
if (typeof value === "string") {
|
|
425
|
-
const parsed = new Date(value);
|
|
426
|
-
if (!Number.isNaN(parsed.getTime())) return parsed;
|
|
427
|
-
}
|
|
428
|
-
return z.NEVER;
|
|
429
|
-
}, z.date());
|
|
430
|
-
const apiResponseSchema = z.object({
|
|
431
|
-
id: z.string(),
|
|
432
|
-
requestType: z.string(),
|
|
433
|
-
llmStatus: z.union([
|
|
434
|
-
z.literal("pending"),
|
|
435
|
-
z.literal("processing"),
|
|
436
|
-
z.literal("success"),
|
|
437
|
-
z.literal("failed")
|
|
438
|
-
]),
|
|
439
|
-
sseStatus: z.union([
|
|
440
|
-
z.literal("n/a"),
|
|
441
|
-
z.literal("pending"),
|
|
442
|
-
z.literal("sent"),
|
|
443
|
-
z.literal("failed")
|
|
444
|
-
]),
|
|
445
|
-
webhookStatus: z.union([
|
|
446
|
-
z.literal("n/a"),
|
|
447
|
-
z.literal("pending"),
|
|
448
|
-
z.literal("sent"),
|
|
449
|
-
z.literal("failed")
|
|
450
|
-
]),
|
|
451
|
-
input: z.object({
|
|
452
|
-
prompt: z.union([z.string(), z.null()]),
|
|
453
|
-
data: z.union([z.string(), z.null()]),
|
|
454
|
-
primaryKey: z.union([z.string(), z.null()])
|
|
455
|
-
}),
|
|
456
|
-
output: z.object({
|
|
457
|
-
name: z.string(),
|
|
458
|
-
schema: z.string(),
|
|
459
|
-
effectiveSchema: z.string()
|
|
460
|
-
}),
|
|
461
|
-
result: z.union([z.record(z.string(), z.unknown()), z.null()]).optional(),
|
|
462
|
-
error: z.union([z.string(), z.null()]),
|
|
463
|
-
fullPrompt: z.string(),
|
|
464
|
-
model: z.string(),
|
|
465
|
-
provider: z.string(),
|
|
466
|
-
startedAt: dateFromIso,
|
|
467
|
-
finishedAt: dateFromIso,
|
|
468
|
-
createdAt: mandatoryDateFromIso,
|
|
469
|
-
updatedAt: mandatoryDateFromIso
|
|
470
|
-
});
|
|
471
|
-
const isNuabaseError = (value) => Boolean(value && typeof value === "object" && "isError" in value && value.isError);
|
|
472
|
-
async function getRequest(client, llmRequestId) {
|
|
473
|
-
const response = await client.request("GET", `requests/${encodeURIComponent(llmRequestId)}`);
|
|
474
|
-
if (isNuabaseError(response)) {
|
|
475
|
-
return response;
|
|
476
|
-
}
|
|
477
|
-
const parsedResponse = apiResponseSchema.safeParse(response);
|
|
478
|
-
if (!parsedResponse.success) {
|
|
479
|
-
return errorParseFailed;
|
|
480
|
-
}
|
|
481
|
-
return parsedResponse.data;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
class Nua {
|
|
485
|
-
constructor(config) {
|
|
486
|
-
this.apiClient = new NuabaseAPIClient(config);
|
|
1535
|
+
const jsonSchema = z.toJSONSchema(options.output.schema);
|
|
1536
|
+
return this.backend.castArray({
|
|
1537
|
+
prompt,
|
|
1538
|
+
data: options.input,
|
|
1539
|
+
primaryKey: options.primaryKey,
|
|
1540
|
+
outputName: options.output.name,
|
|
1541
|
+
outputSchema: jsonSchema
|
|
1542
|
+
});
|
|
487
1543
|
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
1544
|
+
// Implementation
|
|
1545
|
+
async queueGet(prompt, options) {
|
|
1546
|
+
if (typeof prompt !== "string" || prompt.trim() === "") {
|
|
1547
|
+
throw new TypeError("Prompt must be a non-empty string");
|
|
1548
|
+
}
|
|
1549
|
+
if (!this.backend.queueCastValue) {
|
|
1550
|
+
throw new Error("Queue operations are only supported in gateway mode");
|
|
1551
|
+
}
|
|
1552
|
+
const outputSchema = options?.output?.schema ?? z.string();
|
|
1553
|
+
const outputName = options?.output?.name ?? "result";
|
|
1554
|
+
const jsonSchema = z.toJSONSchema(outputSchema);
|
|
1555
|
+
return this.backend.queueCastValue({
|
|
1556
|
+
prompt,
|
|
1557
|
+
data: options?.input ?? null,
|
|
1558
|
+
outputName,
|
|
1559
|
+
outputSchema: jsonSchema
|
|
1560
|
+
});
|
|
493
1561
|
}
|
|
494
|
-
|
|
495
|
-
|
|
1562
|
+
// ========== queueList() - Async Array Operations ==========
|
|
1563
|
+
async queueList(prompt, options) {
|
|
1564
|
+
if (typeof prompt !== "string" || prompt.trim() === "") {
|
|
1565
|
+
throw new TypeError("Prompt must be a non-empty string");
|
|
1566
|
+
}
|
|
1567
|
+
if (!this.backend.queueCastArray) {
|
|
1568
|
+
throw new Error("Queue operations are only supported in gateway mode");
|
|
1569
|
+
}
|
|
1570
|
+
if (!Array.isArray(options.input)) {
|
|
1571
|
+
throw new TypeError("Input must be an array for queueList()");
|
|
1572
|
+
}
|
|
1573
|
+
if (typeof options.primaryKey !== "string" || options.primaryKey.trim() === "") {
|
|
1574
|
+
throw new TypeError("primaryKey must be a non-empty string");
|
|
1575
|
+
}
|
|
1576
|
+
const jsonSchema = z.toJSONSchema(options.output.schema);
|
|
1577
|
+
return this.backend.queueCastArray({
|
|
1578
|
+
prompt,
|
|
1579
|
+
data: options.input,
|
|
1580
|
+
primaryKey: options.primaryKey,
|
|
1581
|
+
outputName: options.output.name,
|
|
1582
|
+
outputSchema: jsonSchema
|
|
1583
|
+
});
|
|
496
1584
|
}
|
|
497
1585
|
}
|
|
498
1586
|
|