@granular-software/sdk 0.4.19 → 0.4.20
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 +10 -0
- package/dist/agent-evals.d.mts +1 -1
- package/dist/agent-evals.d.ts +1 -1
- package/dist/agent-evals.js +116 -17
- package/dist/agent-evals.js.map +1 -1
- package/dist/agent-evals.mjs +116 -17
- package/dist/agent-evals.mjs.map +1 -1
- package/dist/cli/index.js +114 -14
- package/dist/{client-BQw_gUK3.d.mts → client-DWYdWpS-.d.mts} +61 -5
- package/dist/{client-BQw_gUK3.d.ts → client-DWYdWpS-.d.ts} +61 -5
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +110 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +110 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -11229,6 +11229,28 @@ var STANDARD_MODULES_OPERATIONS = [
|
|
|
11229
11229
|
var BUILTIN_MODULES = {
|
|
11230
11230
|
"standard_modules": STANDARD_MODULES_OPERATIONS
|
|
11231
11231
|
};
|
|
11232
|
+
var DEFAULT_DIRECT_RECORD_OBJECTS_REQUEST_BATCH_SIZE = 100;
|
|
11233
|
+
var MAX_RECORD_OBJECTS_CONCURRENCY = 16;
|
|
11234
|
+
var DEFAULT_DIRECT_RECORD_OBJECTS_RETRY_COUNT = 3;
|
|
11235
|
+
var DEFAULT_DIRECT_RECORD_OBJECTS_RETRY_DELAY_MS = 1e3;
|
|
11236
|
+
function planRecordObjectsChunks(records, batchSize) {
|
|
11237
|
+
const total = records.length;
|
|
11238
|
+
const size = Math.max(1, Math.min(batchSize, total));
|
|
11239
|
+
const chunkCount = Math.ceil(total / size);
|
|
11240
|
+
const plans = [];
|
|
11241
|
+
for (let offset = 0, chunkIndex = 0; offset < total; offset += size, chunkIndex += 1) {
|
|
11242
|
+
const slice = records.slice(offset, offset + size);
|
|
11243
|
+
plans.push({ chunkIndex, chunkCount, offset, slice });
|
|
11244
|
+
}
|
|
11245
|
+
return plans;
|
|
11246
|
+
}
|
|
11247
|
+
function sleep(ms) {
|
|
11248
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11249
|
+
}
|
|
11250
|
+
function isRetryableRecordObjectsError(error) {
|
|
11251
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
11252
|
+
return /worker restarted mid-request|econnreset|network|socket connection was closed unexpectedly|timed out/i.test(message);
|
|
11253
|
+
}
|
|
11232
11254
|
function computeEffectKey2(effect) {
|
|
11233
11255
|
const attachedClass = effect.className?.trim();
|
|
11234
11256
|
if (!attachedClass) {
|
|
@@ -12186,24 +12208,101 @@ var Environment = class extends Session {
|
|
|
12186
12208
|
/**
|
|
12187
12209
|
* Batch version of `recordObject()`.
|
|
12188
12210
|
*
|
|
12189
|
-
* Sends
|
|
12190
|
-
*
|
|
12211
|
+
* Sends rows through the control-plane **`/records/batch`** endpoint in **chunks** (default
|
|
12212
|
+
* **100** records per HTTP request) so individual requests stay bounded and gateway timeouts are
|
|
12213
|
+
* unlikely. Each chunk is retried on transient network / worker errors.
|
|
12214
|
+
*
|
|
12215
|
+
* Use the optional second argument to:
|
|
12216
|
+
* - **`batchSize`** — rows per POST (smaller = more progress events; larger = fewer round trips).
|
|
12217
|
+
* - **`concurrency`** — run up to N chunk POSTs in parallel (capped at 16) when you want lower wall time.
|
|
12218
|
+
* - **`onChunkComplete`** — hook for UIs after each chunk succeeds (row order in the returned array
|
|
12219
|
+
* always matches `records`; chunk **completion** order may differ when `concurrency > 1`).
|
|
12220
|
+
*
|
|
12221
|
+
* For **asynchronous** ingestion with worker-side batching and aggregate counters (`queued`,
|
|
12222
|
+
* `completed`, …), use **`enqueueRecordImport`** and poll **`getRecordImport`** /
|
|
12223
|
+
* **`getRecordImportSummary`** — best for very large fire-and-forget loads when immediate
|
|
12224
|
+
* synchronous commit of every row is not required.
|
|
12191
12225
|
*/
|
|
12192
|
-
async recordObjects(records) {
|
|
12226
|
+
async recordObjects(records, options) {
|
|
12193
12227
|
if (!Array.isArray(records) || records.length === 0) {
|
|
12194
12228
|
return [];
|
|
12195
12229
|
}
|
|
12196
|
-
const
|
|
12197
|
-
|
|
12198
|
-
|
|
12199
|
-
|
|
12200
|
-
|
|
12201
|
-
|
|
12230
|
+
const batchSize = Math.max(
|
|
12231
|
+
1,
|
|
12232
|
+
Math.min(
|
|
12233
|
+
records.length,
|
|
12234
|
+
options?.batchSize ?? DEFAULT_DIRECT_RECORD_OBJECTS_REQUEST_BATCH_SIZE
|
|
12235
|
+
)
|
|
12202
12236
|
);
|
|
12203
|
-
|
|
12237
|
+
const concurrency = Math.min(
|
|
12238
|
+
MAX_RECORD_OBJECTS_CONCURRENCY,
|
|
12239
|
+
Math.max(1, options?.concurrency ?? 1)
|
|
12240
|
+
);
|
|
12241
|
+
const plans = planRecordObjectsChunks(records, batchSize);
|
|
12242
|
+
const total = records.length;
|
|
12243
|
+
const results = new Array(total);
|
|
12244
|
+
const onChunk = options?.onChunkComplete;
|
|
12245
|
+
for (let waveStart = 0; waveStart < plans.length; waveStart += concurrency) {
|
|
12246
|
+
const wave = plans.slice(waveStart, waveStart + concurrency);
|
|
12247
|
+
await Promise.all(
|
|
12248
|
+
wave.map(async (plan) => {
|
|
12249
|
+
const { items, durationMs } = await this.executeRecordObjectsChunk(plan.slice);
|
|
12250
|
+
if (items.length !== plan.slice.length) {
|
|
12251
|
+
throw new Error(
|
|
12252
|
+
`recordObjects: chunk ${plan.chunkIndex + 1} returned ${items.length} results, expected ${plan.slice.length}`
|
|
12253
|
+
);
|
|
12254
|
+
}
|
|
12255
|
+
for (let index = 0; index < items.length; index += 1) {
|
|
12256
|
+
results[plan.offset + index] = items[index];
|
|
12257
|
+
}
|
|
12258
|
+
if (onChunk) {
|
|
12259
|
+
const info = {
|
|
12260
|
+
chunkIndex: plan.chunkIndex,
|
|
12261
|
+
totalChunks: plan.chunkCount,
|
|
12262
|
+
offset: plan.offset,
|
|
12263
|
+
recordCount: plan.slice.length,
|
|
12264
|
+
durationMs,
|
|
12265
|
+
results: items
|
|
12266
|
+
};
|
|
12267
|
+
await onChunk(info);
|
|
12268
|
+
}
|
|
12269
|
+
})
|
|
12270
|
+
);
|
|
12271
|
+
}
|
|
12272
|
+
return results;
|
|
12273
|
+
}
|
|
12274
|
+
async executeRecordObjectsChunk(chunk) {
|
|
12275
|
+
const wallStart = Date.now();
|
|
12276
|
+
let lastError;
|
|
12277
|
+
for (let attempt = 1; attempt <= DEFAULT_DIRECT_RECORD_OBJECTS_RETRY_COUNT; attempt += 1) {
|
|
12278
|
+
try {
|
|
12279
|
+
const response = await this.controlPlaneRequest(
|
|
12280
|
+
`/control/environments/${this.environmentId}/records/batch`,
|
|
12281
|
+
{
|
|
12282
|
+
method: "POST",
|
|
12283
|
+
body: JSON.stringify({ records: chunk })
|
|
12284
|
+
}
|
|
12285
|
+
);
|
|
12286
|
+
const items = Array.isArray(response.items) ? response.items : [];
|
|
12287
|
+
return { items, durationMs: Date.now() - wallStart };
|
|
12288
|
+
} catch (error) {
|
|
12289
|
+
lastError = error;
|
|
12290
|
+
if (!isRetryableRecordObjectsError(error) || attempt === DEFAULT_DIRECT_RECORD_OBJECTS_RETRY_COUNT) {
|
|
12291
|
+
throw error;
|
|
12292
|
+
}
|
|
12293
|
+
await sleep(DEFAULT_DIRECT_RECORD_OBJECTS_RETRY_DELAY_MS * attempt);
|
|
12294
|
+
}
|
|
12295
|
+
}
|
|
12296
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
12204
12297
|
}
|
|
12205
12298
|
/**
|
|
12206
|
-
* Queue a background record import for this environment.
|
|
12299
|
+
* Queue a background record import for this environment (async worker pipeline).
|
|
12300
|
+
*
|
|
12301
|
+
* **vs `recordObjects`:** this path accepts the full payload in one request, returns an
|
|
12302
|
+
* **`importId`**, and processes rows in the background — use **`getRecordImport`** /
|
|
12303
|
+
* **`getRecordImportSummary`** for progress. Choose it for large bulk loads where you do not
|
|
12304
|
+
* need every row committed before the HTTP call returns. Use **`recordObjects`** when you need
|
|
12305
|
+
* synchronous upserts and fine-grained chunk progress via **`onChunkComplete`**.
|
|
12207
12306
|
*/
|
|
12208
12307
|
async enqueueRecordImport(records, options = {}) {
|
|
12209
12308
|
return this.controlPlaneRequest(
|