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