nuabase 1.0.1 → 1.2.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 +32 -25
- package/dist/cjs/index.cjs +195 -26
- package/dist/esm/index.mjs +195 -26
- package/dist/types/lib/api-client.d.ts +11 -3
- package/dist/types/lib/env.d.ts +1 -0
- package/dist/types/nua/cast_array/response-schema.d.ts +3 -1
- package/dist/types/nua/cast_array/types.d.ts +18 -3
- package/dist/types/nua/cast_value/response-schema.d.ts +2 -0
- package/dist/types/nua/cast_value/types.d.ts +2 -2
- package/dist/types/nua/common/normalized-usage.d.ts +7 -0
- package/dist/types/nua/core.d.ts +2 -0
- package/dist/types/nua/get-request/index.d.ts +6 -0
- package/dist/types/nua/get-request/types.d.ts +34 -0
- package/dist/types/nua/index.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,9 +46,9 @@ const classifyLeads = new Nua().createArrayFn({
|
|
|
46
46
|
**4. Invoke.** Call it like any other async function:
|
|
47
47
|
|
|
48
48
|
```ts
|
|
49
|
-
const result = await classifyLeads
|
|
49
|
+
const result = await classifyLeads(leads, 'id');
|
|
50
50
|
if (result.isError) throw new Error(result.error);
|
|
51
|
-
console.log(result.data[0].
|
|
51
|
+
console.log(result.data[0].leadInsights);
|
|
52
52
|
// -> { industry: 'Software', company_size: 'Mid-market' }
|
|
53
53
|
```
|
|
54
54
|
|
|
@@ -107,34 +107,35 @@ const rows = [
|
|
|
107
107
|
},
|
|
108
108
|
];
|
|
109
109
|
|
|
110
|
-
const response = await enrichLeads
|
|
110
|
+
const response = await enrichLeads(rows, 'leadId'); // `leadId` is the primary key field
|
|
111
111
|
|
|
112
112
|
if (response.isError) {
|
|
113
113
|
console.error(response.error);
|
|
114
114
|
return;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
response.data.forEach(({
|
|
117
|
+
response.data.forEach(({ leadId, leadInsights }) => {
|
|
118
118
|
// leadInsights satisfies the LeadInsights schema
|
|
119
|
-
console.log(
|
|
119
|
+
console.log(leadId, leadInsights.company_name, leadInsights.industry, leadInsights.company_size);
|
|
120
120
|
});
|
|
121
121
|
|
|
122
122
|
console.log(response.data);
|
|
123
123
|
// -> [
|
|
124
124
|
// {
|
|
125
|
-
//
|
|
125
|
+
// leadId: 'lead-101',
|
|
126
126
|
// leadInsights: {
|
|
127
127
|
// company_name: 'Acme Analytics',
|
|
128
128
|
// industry: 'Software',
|
|
129
129
|
// company_size: 'Mid-market',
|
|
130
130
|
// recommended_follow_up: 'Call',
|
|
131
131
|
// },
|
|
132
|
+
// sourceRow: { leadId: 'lead-101', name: 'Acme Analytics', notes: '...' },
|
|
132
133
|
// },
|
|
133
134
|
// // ...
|
|
134
135
|
// ];
|
|
135
136
|
```
|
|
136
137
|
|
|
137
|
-
|
|
138
|
+
The default invocation waits for completion and returns the full result. Use `.queue(data, primaryKey)` to submit an asynchronous job and receive streaming updates via SSE.
|
|
138
139
|
|
|
139
140
|
## Why Nuabase
|
|
140
141
|
|
|
@@ -149,14 +150,15 @@ Every call returns a discriminated union. When `isError` is `true`, you get a fl
|
|
|
149
150
|
|
|
150
151
|
**Success**
|
|
151
152
|
|
|
152
|
-
| Field | Type
|
|
153
|
-
| ------------------- |
|
|
154
|
-
| `isSuccess` | `true`
|
|
155
|
-
| `data` | `Array<{ [primaryKey]: unknown; [outputName]: z.infer<typeof output
|
|
156
|
-
| `llmRequestId` | `string`
|
|
157
|
-
| `
|
|
158
|
-
| `
|
|
159
|
-
| `
|
|
153
|
+
| Field | Type | Description |
|
|
154
|
+
| ------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
155
|
+
| `isSuccess` | `true` | Indicates that the request completed successfully. |
|
|
156
|
+
| `data` | `Array<{ [primaryKey]: unknown; [outputName]: z.infer<typeof output>; sourceRow: InputRow }>` | Rows that merged the original primary key with the validated schema output, plus the full `sourceRow` for convenience. |
|
|
157
|
+
| `llmRequestId` | `string` | Unique identifier for tracing each Nuabase LLM execution. |
|
|
158
|
+
| `usage` | `{ promptTokens: number; completionTokens: number; totalTokens: number }` | Token usage statistics for the LLM request. |
|
|
159
|
+
| `cacheHits` | `number` | Count of input rows served from Nuabase response cache. |
|
|
160
|
+
| `rowsWithNoResults` | `string[]` | Primary keys that could not be resolved by the model. |
|
|
161
|
+
| `isError` | `false \| undefined` | Absent on success; included for type narrowing. |
|
|
160
162
|
|
|
161
163
|
**Error**
|
|
162
164
|
|
|
@@ -173,28 +175,33 @@ Creates a client bound to your Nuabase account. Provide:
|
|
|
173
175
|
- `apiKey?: string` – API key for authentication. Defaults to `process.env.NUABASE_API_KEY`.
|
|
174
176
|
- `baseUrl?: string` – Override the API host. Defaults to `https://api.nuabase.com`.
|
|
175
177
|
|
|
176
|
-
**`nua.
|
|
177
|
-
Declares a typed mapping function backed by Nuabase. Parameters:
|
|
178
|
+
**`nua.createArrayFn({ prompt, output })`**
|
|
179
|
+
Declares a typed array mapping function backed by Nuabase. Parameters:
|
|
178
180
|
|
|
179
|
-
- `name: string` – Label applied to the enriched payload in each response row (e.g., `result.data[i][name]`).
|
|
180
181
|
- `prompt: string` – Natural-language instructions sent to the LLM.
|
|
181
|
-
- `output:
|
|
182
|
+
- `output: { name: string; schema: ZodSchema }` – Output configuration with a name and Zod schema describing the output shape.
|
|
182
183
|
|
|
183
|
-
Returns a callable
|
|
184
|
+
Returns a callable function with two modes:
|
|
184
185
|
|
|
185
|
-
- `
|
|
186
|
-
- `
|
|
186
|
+
- `fn(data, primaryKey)` – Default mode. Runs the job and waits until the full enriched result set is ready.
|
|
187
|
+
- `fn.queue(data, primaryKey)` – Submits the job asynchronously and returns streaming metadata via SSE.
|
|
187
188
|
|
|
188
|
-
Both
|
|
189
|
+
Both modes expect:
|
|
189
190
|
|
|
190
191
|
- `data: Array<Record<string, unknown>>` – Rows you want Nuabase to enrich. Each row must include the primary key.
|
|
191
192
|
- `primaryKey: string` – Field name that uniquely identifies each row within `data`. The SDK throws if the field is missing on any item.
|
|
192
193
|
|
|
193
|
-
Both
|
|
194
|
+
Both modes resolve to either:
|
|
194
195
|
|
|
195
|
-
- **Success** – `{ isSuccess: true, data, llmRequestId, cacheHits, rowsWithNoResults }`.
|
|
196
|
+
- **Success** – `{ isSuccess: true, data, llmRequestId, usage, cacheHits, rowsWithNoResults }`.
|
|
196
197
|
- **Error** – `{ isError: true, error }`.
|
|
197
198
|
|
|
199
|
+
**`nua.createFn({ prompt, output })`**
|
|
200
|
+
Declares a typed single-value function backed by Nuabase. Similar to `createArrayFn` but for processing a single input value instead of an array. Returns a function that accepts a single input value.
|
|
201
|
+
|
|
202
|
+
**`nua.getRequest(llmRequestId)`**
|
|
203
|
+
Retrieves request details for a completed LLM execution using its request ID.
|
|
204
|
+
|
|
198
205
|
## Next Steps
|
|
199
206
|
|
|
200
207
|
- Create an API key or inspect request logs in the [Nuabase Console](https://console.nuabase.com/).
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
var zod = require('zod');
|
|
4
4
|
|
|
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
|
+
}
|
|
12
|
+
return void 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
5
15
|
async function parseErrorResponse(response, urlPath) {
|
|
6
16
|
const fallbackMessage = `Request to ${urlPath} failed with status ${response.status}${response.statusText ? ` ${response.statusText}` : ""}`;
|
|
7
17
|
let responseBody = "";
|
|
@@ -45,27 +55,69 @@ function getErrorMessageFromException(error) {
|
|
|
45
55
|
return String(error);
|
|
46
56
|
}
|
|
47
57
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.
|
|
52
|
-
|
|
58
|
+
const isBrowserEnvironment = () => typeof window !== "undefined" && !!window.document;
|
|
59
|
+
class NuabaseAuthTokenManager {
|
|
60
|
+
constructor(config) {
|
|
61
|
+
this.apiKey = resolveConfigValue(config, "apiKey", "NUABASE_API_KEY") || void 0;
|
|
62
|
+
this.fetchToken = config.fetchToken;
|
|
63
|
+
if (this.apiKey && this.fetchToken) {
|
|
64
|
+
throw new Error("Provide either an apiKey or a fetchToken function, but not both.");
|
|
65
|
+
}
|
|
66
|
+
if (!this.apiKey && !this.fetchToken) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
"Authentication is required. Provide config.apiKey/NUABASE_API_KEY or a fetchToken function."
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
if (this.apiKey && isBrowserEnvironment()) {
|
|
53
72
|
throw new Error(
|
|
54
|
-
"
|
|
73
|
+
"found config.apiKey. It is a private secret that must only be used in server environments."
|
|
55
74
|
);
|
|
56
75
|
}
|
|
57
76
|
}
|
|
58
|
-
async
|
|
77
|
+
async getToken() {
|
|
78
|
+
if (this.apiKey) {
|
|
79
|
+
return this.apiKey;
|
|
80
|
+
}
|
|
81
|
+
if (!this.fetchToken) {
|
|
82
|
+
throw new Error("Unable to resolve API token because no fetchToken function is configured.");
|
|
83
|
+
}
|
|
84
|
+
if (this.apiToken) {
|
|
85
|
+
return this.apiToken;
|
|
86
|
+
}
|
|
87
|
+
if (!this.pendingTokenPromise) {
|
|
88
|
+
this.pendingTokenPromise = this.fetchToken().then((token) => {
|
|
89
|
+
if (!token) {
|
|
90
|
+
throw new Error("fetchToken must resolve a non-empty API token.");
|
|
91
|
+
}
|
|
92
|
+
this.apiToken = token;
|
|
93
|
+
return token;
|
|
94
|
+
}).finally(() => {
|
|
95
|
+
this.pendingTokenPromise = void 0;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return this.pendingTokenPromise;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
class NuabaseAPIClient {
|
|
102
|
+
constructor(config = {}) {
|
|
103
|
+
this.baseUrl = resolveConfigValue(config, "baseUrl", "NUABASE_API_URL") || "https://api.nuabase.com";
|
|
104
|
+
this.authTokenManager = new NuabaseAuthTokenManager(config);
|
|
105
|
+
}
|
|
106
|
+
async request(method, urlPath, params) {
|
|
59
107
|
const url = `${this.baseUrl}/${urlPath}`;
|
|
60
108
|
let response;
|
|
109
|
+
const hasBody = method !== "GET" && params !== void 0;
|
|
110
|
+
const headers = {
|
|
111
|
+
Authorization: `Bearer ${await this.authTokenManager.getToken()}`
|
|
112
|
+
};
|
|
113
|
+
if (hasBody) {
|
|
114
|
+
headers["Content-Type"] = "application/json";
|
|
115
|
+
}
|
|
61
116
|
try {
|
|
62
117
|
response = await fetch(url, {
|
|
63
|
-
method
|
|
64
|
-
headers
|
|
65
|
-
|
|
66
|
-
Authorization: `Bearer ${this.apiKey}`
|
|
67
|
-
},
|
|
68
|
-
body: JSON.stringify(params)
|
|
118
|
+
method,
|
|
119
|
+
headers,
|
|
120
|
+
body: hasBody ? JSON.stringify(params) : void 0
|
|
69
121
|
});
|
|
70
122
|
} catch (e) {
|
|
71
123
|
return { error: `Error calling Nuabase API: ${getErrorMessageFromException(e)}` };
|
|
@@ -105,6 +157,12 @@ const validateArrayRequestParams = (data, primaryKeyName) => {
|
|
|
105
157
|
});
|
|
106
158
|
};
|
|
107
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
|
+
|
|
108
166
|
const zs_ResponseRecord = (primaryKeyName, outputKey, outputSchema) => {
|
|
109
167
|
const primaryKeySchema = zod.z.any();
|
|
110
168
|
const shape = {
|
|
@@ -127,7 +185,8 @@ const createNuaApiResponseCastArray = (primaryKeyName, outputKey, outputSchema)
|
|
|
127
185
|
cacheHits: zod.z.number(),
|
|
128
186
|
rowsWithNoResults: zod.z.array(zod.z.string()),
|
|
129
187
|
isSuccess: zod.z.literal(true),
|
|
130
|
-
isError: zod.z.optional(zod.z.literal(false))
|
|
188
|
+
isError: zod.z.optional(zod.z.literal(false)),
|
|
189
|
+
usage: zs_NormalizedUsage
|
|
131
190
|
}).strict();
|
|
132
191
|
};
|
|
133
192
|
const zs_NuaApiResponse_CastArray = createNuaApiResponseCastArray;
|
|
@@ -151,6 +210,25 @@ const validateArrayFnDef = (fnDef) => {
|
|
|
151
210
|
return parsed.data;
|
|
152
211
|
};
|
|
153
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);
|
|
217
|
+
}
|
|
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
|
+
);
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
...row,
|
|
228
|
+
sourceRow
|
|
229
|
+
};
|
|
230
|
+
});
|
|
231
|
+
}
|
|
154
232
|
const toCastArrayApiRequest = (prompt, data, primaryKeyName, outputName, outputSchema) => ({
|
|
155
233
|
input: {
|
|
156
234
|
prompt,
|
|
@@ -170,9 +248,10 @@ const createArrayFn = (client, inputFnDef) => {
|
|
|
170
248
|
return { error: String(response.error), isError: true };
|
|
171
249
|
return void 0;
|
|
172
250
|
};
|
|
173
|
-
const
|
|
251
|
+
const queueFn = async (data, primaryKeyName) => {
|
|
174
252
|
validateArrayRequestParams(data, primaryKeyName);
|
|
175
253
|
const response = await client.request(
|
|
254
|
+
"POST",
|
|
176
255
|
"cast/array",
|
|
177
256
|
toCastArrayApiRequest(
|
|
178
257
|
fnDef.prompt,
|
|
@@ -191,9 +270,10 @@ const createArrayFn = (client, inputFnDef) => {
|
|
|
191
270
|
}
|
|
192
271
|
return parsedResponse.data;
|
|
193
272
|
};
|
|
194
|
-
const
|
|
273
|
+
const baseNowFn = async (data, primaryKeyName) => {
|
|
195
274
|
validateArrayRequestParams(data, primaryKeyName);
|
|
196
275
|
const response = await client.request(
|
|
276
|
+
"POST",
|
|
197
277
|
"cast/array/now",
|
|
198
278
|
toCastArrayApiRequest(
|
|
199
279
|
fnDef.prompt,
|
|
@@ -216,13 +296,18 @@ const createArrayFn = (client, inputFnDef) => {
|
|
|
216
296
|
isSuccess: true,
|
|
217
297
|
llmRequestId: parsedResponse.data.llmRequestId,
|
|
218
298
|
kind: parsedResponse.data.kind,
|
|
219
|
-
data:
|
|
299
|
+
data: addOriginalInputRows(
|
|
300
|
+
data,
|
|
301
|
+
parsedResponse.data.data,
|
|
302
|
+
primaryKeyName
|
|
303
|
+
),
|
|
220
304
|
rowsWithNoResults: parsedResponse.data.rowsWithNoResults,
|
|
221
|
-
cacheHits: parsedResponse.data.cacheHits
|
|
305
|
+
cacheHits: parsedResponse.data.cacheHits,
|
|
306
|
+
usage: parsedResponse.data.usage
|
|
222
307
|
};
|
|
223
308
|
};
|
|
224
|
-
return Object.assign(
|
|
225
|
-
|
|
309
|
+
return Object.assign(baseNowFn, {
|
|
310
|
+
queue: queueFn
|
|
226
311
|
});
|
|
227
312
|
};
|
|
228
313
|
|
|
@@ -233,7 +318,8 @@ const createNuaApiResponseCastValue = (outputKey, outputSchema) => {
|
|
|
233
318
|
data: outputSchema,
|
|
234
319
|
isCacheHit: zod.z.boolean(),
|
|
235
320
|
isSuccess: zod.z.literal(true),
|
|
236
|
-
isError: zod.z.optional(zod.z.literal(false))
|
|
321
|
+
isError: zod.z.optional(zod.z.literal(false)),
|
|
322
|
+
usage: zs_NormalizedUsage
|
|
237
323
|
}).strict();
|
|
238
324
|
};
|
|
239
325
|
const zs_NuaApiResponse_CastValue = createNuaApiResponseCastValue;
|
|
@@ -276,10 +362,11 @@ const createValueFn = (client, inputFnDef) => {
|
|
|
276
362
|
return void 0;
|
|
277
363
|
};
|
|
278
364
|
const sendRequest = async (path, data) => client.request(
|
|
365
|
+
"POST",
|
|
279
366
|
path,
|
|
280
367
|
toCastValueApiRequest(fnDef.prompt, data, fnDef.output.name, outputJsonSchema)
|
|
281
368
|
);
|
|
282
|
-
const
|
|
369
|
+
const queueFn = async (data) => {
|
|
283
370
|
const response = await sendRequest("cast/value", data);
|
|
284
371
|
const error = toNuabaseError(response);
|
|
285
372
|
if (error) return error;
|
|
@@ -290,7 +377,7 @@ const createValueFn = (client, inputFnDef) => {
|
|
|
290
377
|
}
|
|
291
378
|
return parsedResponse.data;
|
|
292
379
|
};
|
|
293
|
-
const
|
|
380
|
+
const baseNowFn = async (data) => {
|
|
294
381
|
const response = await sendRequest("cast/value/now", data);
|
|
295
382
|
const error = toNuabaseError(response);
|
|
296
383
|
if (error) return error;
|
|
@@ -309,14 +396,93 @@ const createValueFn = (client, inputFnDef) => {
|
|
|
309
396
|
llmRequestId: parsedResponse.data.llmRequestId,
|
|
310
397
|
kind: parsedResponse.data.kind,
|
|
311
398
|
data: parsedResponse.data.data,
|
|
312
|
-
isCacheHit: parsedResponse.data.isCacheHit
|
|
399
|
+
isCacheHit: parsedResponse.data.isCacheHit,
|
|
400
|
+
usage: parsedResponse.data.usage
|
|
313
401
|
};
|
|
314
402
|
};
|
|
315
|
-
return Object.assign(
|
|
316
|
-
|
|
403
|
+
return Object.assign(baseNowFn, {
|
|
404
|
+
queue: queueFn
|
|
317
405
|
});
|
|
318
406
|
};
|
|
319
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
|
+
|
|
320
486
|
class Nua {
|
|
321
487
|
constructor(config) {
|
|
322
488
|
this.apiClient = new NuabaseAPIClient(config);
|
|
@@ -327,6 +493,9 @@ class Nua {
|
|
|
327
493
|
createFn(fnDef) {
|
|
328
494
|
return createValueFn(this.apiClient, fnDef);
|
|
329
495
|
}
|
|
496
|
+
async getRequest(llmRequestId) {
|
|
497
|
+
return getRequest(this.apiClient, llmRequestId);
|
|
498
|
+
}
|
|
330
499
|
}
|
|
331
500
|
|
|
332
501
|
exports.Nua = Nua;
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
+
function resolveConfigValue(config, key, envVar) {
|
|
4
|
+
if (config[key]) return config[key];
|
|
5
|
+
const pe = globalThis.process;
|
|
6
|
+
const isNode = !!pe?.versions?.node;
|
|
7
|
+
if (isNode) {
|
|
8
|
+
return pe?.env?.[envVar];
|
|
9
|
+
}
|
|
10
|
+
return void 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
3
13
|
async function parseErrorResponse(response, urlPath) {
|
|
4
14
|
const fallbackMessage = `Request to ${urlPath} failed with status ${response.status}${response.statusText ? ` ${response.statusText}` : ""}`;
|
|
5
15
|
let responseBody = "";
|
|
@@ -43,27 +53,69 @@ function getErrorMessageFromException(error) {
|
|
|
43
53
|
return String(error);
|
|
44
54
|
}
|
|
45
55
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
this.
|
|
50
|
-
|
|
56
|
+
const isBrowserEnvironment = () => typeof window !== "undefined" && !!window.document;
|
|
57
|
+
class NuabaseAuthTokenManager {
|
|
58
|
+
constructor(config) {
|
|
59
|
+
this.apiKey = resolveConfigValue(config, "apiKey", "NUABASE_API_KEY") || void 0;
|
|
60
|
+
this.fetchToken = config.fetchToken;
|
|
61
|
+
if (this.apiKey && this.fetchToken) {
|
|
62
|
+
throw new Error("Provide either an apiKey or a fetchToken function, but not both.");
|
|
63
|
+
}
|
|
64
|
+
if (!this.apiKey && !this.fetchToken) {
|
|
65
|
+
throw new Error(
|
|
66
|
+
"Authentication is required. Provide config.apiKey/NUABASE_API_KEY or a fetchToken function."
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
if (this.apiKey && isBrowserEnvironment()) {
|
|
51
70
|
throw new Error(
|
|
52
|
-
"
|
|
71
|
+
"found config.apiKey. It is a private secret that must only be used in server environments."
|
|
53
72
|
);
|
|
54
73
|
}
|
|
55
74
|
}
|
|
56
|
-
async
|
|
75
|
+
async getToken() {
|
|
76
|
+
if (this.apiKey) {
|
|
77
|
+
return this.apiKey;
|
|
78
|
+
}
|
|
79
|
+
if (!this.fetchToken) {
|
|
80
|
+
throw new Error("Unable to resolve API token because no fetchToken function is configured.");
|
|
81
|
+
}
|
|
82
|
+
if (this.apiToken) {
|
|
83
|
+
return this.apiToken;
|
|
84
|
+
}
|
|
85
|
+
if (!this.pendingTokenPromise) {
|
|
86
|
+
this.pendingTokenPromise = this.fetchToken().then((token) => {
|
|
87
|
+
if (!token) {
|
|
88
|
+
throw new Error("fetchToken must resolve a non-empty API token.");
|
|
89
|
+
}
|
|
90
|
+
this.apiToken = token;
|
|
91
|
+
return token;
|
|
92
|
+
}).finally(() => {
|
|
93
|
+
this.pendingTokenPromise = void 0;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return this.pendingTokenPromise;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
class NuabaseAPIClient {
|
|
100
|
+
constructor(config = {}) {
|
|
101
|
+
this.baseUrl = resolveConfigValue(config, "baseUrl", "NUABASE_API_URL") || "https://api.nuabase.com";
|
|
102
|
+
this.authTokenManager = new NuabaseAuthTokenManager(config);
|
|
103
|
+
}
|
|
104
|
+
async request(method, urlPath, params) {
|
|
57
105
|
const url = `${this.baseUrl}/${urlPath}`;
|
|
58
106
|
let response;
|
|
107
|
+
const hasBody = method !== "GET" && params !== void 0;
|
|
108
|
+
const headers = {
|
|
109
|
+
Authorization: `Bearer ${await this.authTokenManager.getToken()}`
|
|
110
|
+
};
|
|
111
|
+
if (hasBody) {
|
|
112
|
+
headers["Content-Type"] = "application/json";
|
|
113
|
+
}
|
|
59
114
|
try {
|
|
60
115
|
response = await fetch(url, {
|
|
61
|
-
method
|
|
62
|
-
headers
|
|
63
|
-
|
|
64
|
-
Authorization: `Bearer ${this.apiKey}`
|
|
65
|
-
},
|
|
66
|
-
body: JSON.stringify(params)
|
|
116
|
+
method,
|
|
117
|
+
headers,
|
|
118
|
+
body: hasBody ? JSON.stringify(params) : void 0
|
|
67
119
|
});
|
|
68
120
|
} catch (e) {
|
|
69
121
|
return { error: `Error calling Nuabase API: ${getErrorMessageFromException(e)}` };
|
|
@@ -103,6 +155,12 @@ const validateArrayRequestParams = (data, primaryKeyName) => {
|
|
|
103
155
|
});
|
|
104
156
|
};
|
|
105
157
|
|
|
158
|
+
const zs_NormalizedUsage = z.object({
|
|
159
|
+
promptTokens: z.number(),
|
|
160
|
+
completionTokens: z.number(),
|
|
161
|
+
totalTokens: z.number()
|
|
162
|
+
}).strict();
|
|
163
|
+
|
|
106
164
|
const zs_ResponseRecord = (primaryKeyName, outputKey, outputSchema) => {
|
|
107
165
|
const primaryKeySchema = z.any();
|
|
108
166
|
const shape = {
|
|
@@ -125,7 +183,8 @@ const createNuaApiResponseCastArray = (primaryKeyName, outputKey, outputSchema)
|
|
|
125
183
|
cacheHits: z.number(),
|
|
126
184
|
rowsWithNoResults: z.array(z.string()),
|
|
127
185
|
isSuccess: z.literal(true),
|
|
128
|
-
isError: z.optional(z.literal(false))
|
|
186
|
+
isError: z.optional(z.literal(false)),
|
|
187
|
+
usage: zs_NormalizedUsage
|
|
129
188
|
}).strict();
|
|
130
189
|
};
|
|
131
190
|
const zs_NuaApiResponse_CastArray = createNuaApiResponseCastArray;
|
|
@@ -149,6 +208,25 @@ const validateArrayFnDef = (fnDef) => {
|
|
|
149
208
|
return parsed.data;
|
|
150
209
|
};
|
|
151
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);
|
|
215
|
+
}
|
|
216
|
+
return outputRows.map((row) => {
|
|
217
|
+
const primaryKeyValue = row[primaryKeyName];
|
|
218
|
+
const sourceRow = lookup.get(primaryKeyValue);
|
|
219
|
+
if (!sourceRow) {
|
|
220
|
+
throw new Error(
|
|
221
|
+
`Unable to locate source row for primary key "${String(primaryKeyValue)}" in cast array response.`
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
...row,
|
|
226
|
+
sourceRow
|
|
227
|
+
};
|
|
228
|
+
});
|
|
229
|
+
}
|
|
152
230
|
const toCastArrayApiRequest = (prompt, data, primaryKeyName, outputName, outputSchema) => ({
|
|
153
231
|
input: {
|
|
154
232
|
prompt,
|
|
@@ -168,9 +246,10 @@ const createArrayFn = (client, inputFnDef) => {
|
|
|
168
246
|
return { error: String(response.error), isError: true };
|
|
169
247
|
return void 0;
|
|
170
248
|
};
|
|
171
|
-
const
|
|
249
|
+
const queueFn = async (data, primaryKeyName) => {
|
|
172
250
|
validateArrayRequestParams(data, primaryKeyName);
|
|
173
251
|
const response = await client.request(
|
|
252
|
+
"POST",
|
|
174
253
|
"cast/array",
|
|
175
254
|
toCastArrayApiRequest(
|
|
176
255
|
fnDef.prompt,
|
|
@@ -189,9 +268,10 @@ const createArrayFn = (client, inputFnDef) => {
|
|
|
189
268
|
}
|
|
190
269
|
return parsedResponse.data;
|
|
191
270
|
};
|
|
192
|
-
const
|
|
271
|
+
const baseNowFn = async (data, primaryKeyName) => {
|
|
193
272
|
validateArrayRequestParams(data, primaryKeyName);
|
|
194
273
|
const response = await client.request(
|
|
274
|
+
"POST",
|
|
195
275
|
"cast/array/now",
|
|
196
276
|
toCastArrayApiRequest(
|
|
197
277
|
fnDef.prompt,
|
|
@@ -214,13 +294,18 @@ const createArrayFn = (client, inputFnDef) => {
|
|
|
214
294
|
isSuccess: true,
|
|
215
295
|
llmRequestId: parsedResponse.data.llmRequestId,
|
|
216
296
|
kind: parsedResponse.data.kind,
|
|
217
|
-
data:
|
|
297
|
+
data: addOriginalInputRows(
|
|
298
|
+
data,
|
|
299
|
+
parsedResponse.data.data,
|
|
300
|
+
primaryKeyName
|
|
301
|
+
),
|
|
218
302
|
rowsWithNoResults: parsedResponse.data.rowsWithNoResults,
|
|
219
|
-
cacheHits: parsedResponse.data.cacheHits
|
|
303
|
+
cacheHits: parsedResponse.data.cacheHits,
|
|
304
|
+
usage: parsedResponse.data.usage
|
|
220
305
|
};
|
|
221
306
|
};
|
|
222
|
-
return Object.assign(
|
|
223
|
-
|
|
307
|
+
return Object.assign(baseNowFn, {
|
|
308
|
+
queue: queueFn
|
|
224
309
|
});
|
|
225
310
|
};
|
|
226
311
|
|
|
@@ -231,7 +316,8 @@ const createNuaApiResponseCastValue = (outputKey, outputSchema) => {
|
|
|
231
316
|
data: outputSchema,
|
|
232
317
|
isCacheHit: z.boolean(),
|
|
233
318
|
isSuccess: z.literal(true),
|
|
234
|
-
isError: z.optional(z.literal(false))
|
|
319
|
+
isError: z.optional(z.literal(false)),
|
|
320
|
+
usage: zs_NormalizedUsage
|
|
235
321
|
}).strict();
|
|
236
322
|
};
|
|
237
323
|
const zs_NuaApiResponse_CastValue = createNuaApiResponseCastValue;
|
|
@@ -274,10 +360,11 @@ const createValueFn = (client, inputFnDef) => {
|
|
|
274
360
|
return void 0;
|
|
275
361
|
};
|
|
276
362
|
const sendRequest = async (path, data) => client.request(
|
|
363
|
+
"POST",
|
|
277
364
|
path,
|
|
278
365
|
toCastValueApiRequest(fnDef.prompt, data, fnDef.output.name, outputJsonSchema)
|
|
279
366
|
);
|
|
280
|
-
const
|
|
367
|
+
const queueFn = async (data) => {
|
|
281
368
|
const response = await sendRequest("cast/value", data);
|
|
282
369
|
const error = toNuabaseError(response);
|
|
283
370
|
if (error) return error;
|
|
@@ -288,7 +375,7 @@ const createValueFn = (client, inputFnDef) => {
|
|
|
288
375
|
}
|
|
289
376
|
return parsedResponse.data;
|
|
290
377
|
};
|
|
291
|
-
const
|
|
378
|
+
const baseNowFn = async (data) => {
|
|
292
379
|
const response = await sendRequest("cast/value/now", data);
|
|
293
380
|
const error = toNuabaseError(response);
|
|
294
381
|
if (error) return error;
|
|
@@ -307,14 +394,93 @@ const createValueFn = (client, inputFnDef) => {
|
|
|
307
394
|
llmRequestId: parsedResponse.data.llmRequestId,
|
|
308
395
|
kind: parsedResponse.data.kind,
|
|
309
396
|
data: parsedResponse.data.data,
|
|
310
|
-
isCacheHit: parsedResponse.data.isCacheHit
|
|
397
|
+
isCacheHit: parsedResponse.data.isCacheHit,
|
|
398
|
+
usage: parsedResponse.data.usage
|
|
311
399
|
};
|
|
312
400
|
};
|
|
313
|
-
return Object.assign(
|
|
314
|
-
|
|
401
|
+
return Object.assign(baseNowFn, {
|
|
402
|
+
queue: queueFn
|
|
315
403
|
});
|
|
316
404
|
};
|
|
317
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
|
+
|
|
318
484
|
class Nua {
|
|
319
485
|
constructor(config) {
|
|
320
486
|
this.apiClient = new NuabaseAPIClient(config);
|
|
@@ -325,6 +491,9 @@ class Nua {
|
|
|
325
491
|
createFn(fnDef) {
|
|
326
492
|
return createValueFn(this.apiClient, fnDef);
|
|
327
493
|
}
|
|
494
|
+
async getRequest(llmRequestId) {
|
|
495
|
+
return getRequest(this.apiClient, llmRequestId);
|
|
496
|
+
}
|
|
328
497
|
}
|
|
329
498
|
|
|
330
499
|
export { Nua };
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { NuabaseError } from './error-response';
|
|
2
|
-
|
|
2
|
+
type NuabaseApiKeyConfig = {
|
|
3
3
|
apiKey?: string;
|
|
4
|
+
fetchToken?: never;
|
|
4
5
|
baseUrl?: string;
|
|
5
6
|
};
|
|
7
|
+
type NuabaseTokenConfig = {
|
|
8
|
+
fetchToken: () => Promise<string>;
|
|
9
|
+
apiKey?: never;
|
|
10
|
+
baseUrl?: string;
|
|
11
|
+
};
|
|
12
|
+
export type NuabaseConfig = NuabaseApiKeyConfig | NuabaseTokenConfig;
|
|
6
13
|
export declare class NuabaseAPIClient {
|
|
7
|
-
private readonly apiKey;
|
|
8
14
|
private readonly baseUrl;
|
|
15
|
+
private readonly authTokenManager;
|
|
9
16
|
constructor(config?: NuabaseConfig);
|
|
10
|
-
request(urlPath: string, params
|
|
17
|
+
request(method: 'GET' | 'POST', urlPath: string, params?: object): Promise<NuabaseError | unknown>;
|
|
11
18
|
}
|
|
19
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function resolveConfigValue<T extends Record<string, any>>(config: T, key: keyof T, envVar: string): string | undefined;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NormalizedUsage } from '../common/normalized-usage';
|
|
1
2
|
import { z } from 'zod';
|
|
2
3
|
export type UserDataPKValue = string | number;
|
|
3
4
|
export type PrimaryKeyedInputRecord<PrimaryKeyName extends string> = Record<PrimaryKeyName, UserDataPKValue> & Record<string, unknown>;
|
|
@@ -7,9 +8,10 @@ type NuaApiResponseShape<OutputZodSchema extends z.ZodTypeAny, OutputName extend
|
|
|
7
8
|
kind: 'cast/array';
|
|
8
9
|
data: Array<ResponseRow<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>>;
|
|
9
10
|
cacheHits: number;
|
|
10
|
-
rowsWithNoResults:
|
|
11
|
+
rowsWithNoResults: UserDataPKValue[];
|
|
11
12
|
isSuccess: true;
|
|
12
13
|
isError?: false;
|
|
14
|
+
usage: NormalizedUsage;
|
|
13
15
|
};
|
|
14
16
|
type NuaApiResponseCastArrayBuilder = <OutputZodSchema extends z.ZodTypeAny, OutputName extends string, PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>>(primaryKeyName: PrimaryKeyName, outputKey: OutputName, outputSchema: OutputZodSchema) => z.ZodType<NuaApiResponseShape<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>>;
|
|
15
17
|
export declare const zs_NuaApiResponse_CastArray: NuaApiResponseCastArrayBuilder;
|
|
@@ -10,9 +10,24 @@ export type ArrayFnDef<OutputName extends string, OutputZodSchema extends z.ZodT
|
|
|
10
10
|
};
|
|
11
11
|
};
|
|
12
12
|
export declare const validateArrayFnDef: <OutputName extends string, OutputZodSchema extends z.ZodTypeAny>(fnDef: ArrayFnDef<OutputName, OutputZodSchema>) => ArrayFnDef<OutputName, OutputZodSchema>;
|
|
13
|
-
|
|
13
|
+
type CastArraySuccessFromApi<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>> = NuaApiResponse_CastArray<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>;
|
|
14
|
+
type CastArraySourceRowAugmentation<PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>> = {
|
|
15
|
+
/**
|
|
16
|
+
* SDK-added field containing the full input row for convenience; not returned by the API.
|
|
17
|
+
*/
|
|
18
|
+
sourceRow: InputRecord;
|
|
19
|
+
};
|
|
20
|
+
type CastArraySuccessRowWithSource<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>> = CastArraySuccessFromApi<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>['data'][number] & CastArraySourceRowAugmentation<PrimaryKeyName, InputRecord>;
|
|
21
|
+
export type CastArraySuccessWithSource<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>> = Omit<CastArraySuccessFromApi<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>, 'data'> & {
|
|
22
|
+
/**
|
|
23
|
+
* Each row mirrors the API payload and includes the SDK-provided `sourceRow`.
|
|
24
|
+
*/
|
|
25
|
+
data: CastArraySuccessRowWithSource<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>[];
|
|
26
|
+
};
|
|
27
|
+
export type ArrayFnResult<OutputZodSchema extends z.ZodTypeAny, OutputName extends string, PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>> = NuabaseError | CastArraySuccessWithSource<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>;
|
|
14
28
|
export type ArrayFnQueuedResult = NuabaseError | NuaQueuedResponse;
|
|
15
29
|
export type ArrayFn<OutputZodSchema extends z.ZodTypeAny, OutputName extends string> = {
|
|
16
|
-
<PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>>(data: InputRecord[], primaryKeyName: PrimaryKeyName): Promise<
|
|
17
|
-
|
|
30
|
+
<PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>>(data: InputRecord[], primaryKeyName: PrimaryKeyName): Promise<ArrayFnResult<OutputZodSchema, OutputName, PrimaryKeyName, InputRecord>>;
|
|
31
|
+
queue: <PrimaryKeyName extends string, InputRecord extends PrimaryKeyedInputRecord<PrimaryKeyName>>(data: InputRecord[], primaryKeyName: PrimaryKeyName) => Promise<ArrayFnQueuedResult>;
|
|
18
32
|
};
|
|
33
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NormalizedUsage } from '../common/normalized-usage';
|
|
1
2
|
import { z } from 'zod';
|
|
2
3
|
type NuaApiResponseShape<OutputZodSchema extends z.ZodTypeAny> = {
|
|
3
4
|
llmRequestId: string;
|
|
@@ -6,6 +7,7 @@ type NuaApiResponseShape<OutputZodSchema extends z.ZodTypeAny> = {
|
|
|
6
7
|
isCacheHit: boolean;
|
|
7
8
|
isSuccess: true;
|
|
8
9
|
isError?: false;
|
|
10
|
+
usage: NormalizedUsage;
|
|
9
11
|
};
|
|
10
12
|
type NuaApiResponseCastValueBuilder = <OutputZodSchema extends z.ZodTypeAny, OutputName extends string>(outputKey: OutputName, outputSchema: OutputZodSchema) => z.ZodType<NuaApiResponseShape<OutputZodSchema>>;
|
|
11
13
|
export declare const zs_NuaApiResponse_CastValue: NuaApiResponseCastValueBuilder;
|
|
@@ -13,6 +13,6 @@ export declare const validateValueFnDef: <OutputName extends string, OutputZodSc
|
|
|
13
13
|
export type ValueFnResult<OutputZodSchema extends z.ZodTypeAny, OutputName extends string> = NuabaseError | NuaApiResponse_CastValue<OutputZodSchema, OutputName>;
|
|
14
14
|
export type ValueFnQueuedResult = NuabaseError | NuaQueuedResponse;
|
|
15
15
|
export type ValueFn<OutputZodSchema extends z.ZodTypeAny, OutputName extends string> = {
|
|
16
|
-
(data: unknown): Promise<
|
|
17
|
-
|
|
16
|
+
(data: unknown): Promise<ValueFnResult<OutputZodSchema, OutputName>>;
|
|
17
|
+
queue: (data: unknown) => Promise<ValueFnQueuedResult>;
|
|
18
18
|
};
|
package/dist/types/nua/core.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { NuabaseAPIClient, NuabaseConfig } from '../lib/api-client';
|
|
2
2
|
import { ArrayFn, ArrayFnDef } from './cast_array/types';
|
|
3
3
|
import { ValueFn, ValueFnDef } from './cast_value/types';
|
|
4
|
+
import { GetRequestResult } from './get-request';
|
|
4
5
|
import { z } from 'zod';
|
|
5
6
|
export declare class Nua {
|
|
6
7
|
apiClient: NuabaseAPIClient;
|
|
7
8
|
constructor(config?: NuabaseConfig);
|
|
8
9
|
createArrayFn<OutputName extends string, OutputZodSchema extends z.ZodTypeAny>(fnDef: ArrayFnDef<OutputName, OutputZodSchema>): ArrayFn<OutputZodSchema, OutputName>;
|
|
9
10
|
createFn<OutputName extends string, OutputZodSchema extends z.ZodTypeAny>(fnDef: ValueFnDef<OutputName, OutputZodSchema>): ValueFn<OutputZodSchema, OutputName>;
|
|
11
|
+
getRequest(llmRequestId: string): Promise<GetRequestResult>;
|
|
10
12
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { NuabaseAPIClient } from '../../lib/api-client';
|
|
2
|
+
import { NuabaseError } from '../../lib/error-response';
|
|
3
|
+
import { ApiResponseLlmRequest, NuaInternalError } from './types';
|
|
4
|
+
export type GetRequestResult = ApiResponseLlmRequest | NuaInternalError | NuabaseError;
|
|
5
|
+
export declare function getRequest(client: NuabaseAPIClient, llmRequestId: string): Promise<GetRequestResult>;
|
|
6
|
+
export type { ApiResponseLlmRequest, LlmRequestStatus, NuaInternalError, SseRequestStatus, WebhookRequestStatus, } from './types';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type LlmRequestType = string;
|
|
2
|
+
export type LlmRequestStatus = 'pending' | 'processing' | 'success' | 'failed';
|
|
3
|
+
export type SseRequestStatus = 'n/a' | 'pending' | 'sent' | 'failed';
|
|
4
|
+
export type WebhookRequestStatus = 'n/a' | 'pending' | 'sent' | 'failed';
|
|
5
|
+
export type NuaInternalError = {
|
|
6
|
+
kind: 'internal-error';
|
|
7
|
+
message: string;
|
|
8
|
+
};
|
|
9
|
+
export type ApiResponseLlmRequest = {
|
|
10
|
+
id: string;
|
|
11
|
+
requestType: LlmRequestType;
|
|
12
|
+
llmStatus: LlmRequestStatus;
|
|
13
|
+
sseStatus: SseRequestStatus;
|
|
14
|
+
webhookStatus: WebhookRequestStatus;
|
|
15
|
+
input: {
|
|
16
|
+
prompt: string | null;
|
|
17
|
+
data: string | null;
|
|
18
|
+
primaryKey: string | null;
|
|
19
|
+
};
|
|
20
|
+
output: {
|
|
21
|
+
name: string;
|
|
22
|
+
schema: string;
|
|
23
|
+
effectiveSchema: string;
|
|
24
|
+
};
|
|
25
|
+
result?: Record<string, unknown> | null;
|
|
26
|
+
error: string | null;
|
|
27
|
+
fullPrompt: string;
|
|
28
|
+
model: string;
|
|
29
|
+
provider: string;
|
|
30
|
+
startedAt: Date | null;
|
|
31
|
+
finishedAt: Date | null;
|
|
32
|
+
createdAt: Date;
|
|
33
|
+
updatedAt: Date;
|
|
34
|
+
};
|
|
@@ -2,3 +2,4 @@ export { Nua } from './core';
|
|
|
2
2
|
export { createArrayFn } from './cast_array/factory';
|
|
3
3
|
export { validateArrayRequestParams } from './cast_array/request-validation';
|
|
4
4
|
export type { ArrayFn, ArrayFnDef } from './cast_array/types';
|
|
5
|
+
export type { ApiResponseLlmRequest, GetRequestResult, LlmRequestStatus, NuaInternalError, SseRequestStatus, WebhookRequestStatus, } from './get-request';
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "nuabase",
|
|
3
3
|
"description": "Nuabase TypeScript client to create typed functions from LLM prompts",
|
|
4
4
|
"packageManager": "yarn@4.10.3+sha512.c38cafb5c7bb273f3926d04e55e1d8c9dfa7d9c3ea1f36a4868fa028b9e5f72298f0b7f401ad5eb921749eb012eb1c3bb74bf7503df3ee43fd600d14a018266f",
|
|
5
|
-
"version": "1.0
|
|
5
|
+
"version": "1.2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"author": "Jasim A Basheer <jasim@nuabase.com>",
|
|
8
8
|
"engines": {
|