@granular-software/sdk 0.4.20 → 0.4.21
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 +34 -4
- package/dist/agent-evals.d.mts +1 -1
- package/dist/agent-evals.d.ts +1 -1
- package/dist/agent-evals.js +53 -19
- package/dist/agent-evals.js.map +1 -1
- package/dist/agent-evals.mjs +53 -19
- package/dist/agent-evals.mjs.map +1 -1
- package/dist/agent-harness.js +5 -2
- package/dist/agent-harness.js.map +1 -1
- package/dist/agent-harness.mjs +5 -2
- package/dist/agent-harness.mjs.map +1 -1
- package/dist/cli/index.js +48 -17
- package/dist/{client-DWYdWpS-.d.mts → client-DLGC0mJk.d.mts} +7 -2
- package/dist/{client-DWYdWpS-.d.ts → client-DLGC0mJk.d.ts} +7 -2
- package/dist/index.d.mts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.js +56 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +54 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -353,6 +353,14 @@ After applying the manifest and publishing tools, the sandbox gets **auto-genera
|
|
|
353
353
|
|
|
354
354
|
```typescript
|
|
355
355
|
// What the sandbox sees (auto-generated):
|
|
356
|
+
export interface SandboxPageResult<T> {
|
|
357
|
+
items: T[];
|
|
358
|
+
page: number;
|
|
359
|
+
perPage: number;
|
|
360
|
+
totalCount: number;
|
|
361
|
+
hasMore: boolean;
|
|
362
|
+
}
|
|
363
|
+
|
|
356
364
|
export declare class Author {
|
|
357
365
|
readonly id: string;
|
|
358
366
|
readonly name: string;
|
|
@@ -363,8 +371,17 @@ export declare class Author {
|
|
|
363
371
|
/** Get a cached Author by graph path, hydrating from the graph when needed */
|
|
364
372
|
static get(query: { path: string; refresh?: boolean }): Promise<Author | null>;
|
|
365
373
|
|
|
366
|
-
/**
|
|
367
|
-
static
|
|
374
|
+
/** Count Author instances without loading them into the heap */
|
|
375
|
+
static count(): Promise<number>;
|
|
376
|
+
|
|
377
|
+
/** Return one page of Author instances together with pagination metadata */
|
|
378
|
+
static page(query?: { page?: number; perPage?: number; limit?: number; saveAs?: string; refresh?: boolean }): Promise<SandboxPageResult<Author>>;
|
|
379
|
+
|
|
380
|
+
/** List one page of Author instances */
|
|
381
|
+
static list(query?: { page?: number; perPage?: number; limit?: number; saveAs?: string; refresh?: boolean }): Promise<Author[]>;
|
|
382
|
+
|
|
383
|
+
/** Stream Author instances page by page */
|
|
384
|
+
static iterate(query?: { page?: number; perPage?: number; limit?: number; maxItems?: number; refresh?: boolean }): AsyncIterable<Author>;
|
|
368
385
|
|
|
369
386
|
/** Get biography of an author */
|
|
370
387
|
get_bio(input?: { detailed?: boolean }): Promise<{ bio: string; source?: string }>;
|
|
@@ -384,7 +401,13 @@ export declare class Book {
|
|
|
384
401
|
|
|
385
402
|
static get(query: { path: string; refresh?: boolean }): Promise<Book | null>;
|
|
386
403
|
|
|
387
|
-
static
|
|
404
|
+
static count(): Promise<number>;
|
|
405
|
+
|
|
406
|
+
static page(query?: { page?: number; perPage?: number; limit?: number; saveAs?: string; refresh?: boolean }): Promise<SandboxPageResult<Book>>;
|
|
407
|
+
|
|
408
|
+
static list(query?: { page?: number; perPage?: number; limit?: number; saveAs?: string; refresh?: boolean }): Promise<Book[]>;
|
|
409
|
+
|
|
410
|
+
static iterate(query?: { page?: number; perPage?: number; limit?: number; maxItems?: number; refresh?: boolean }): AsyncIterable<Book>;
|
|
388
411
|
|
|
389
412
|
/** Navigate to author (many_to_one) */
|
|
390
413
|
get_author(): Promise<Author | null>;
|
|
@@ -399,11 +422,18 @@ The LLM or user writes code against these typed classes:
|
|
|
399
422
|
```typescript
|
|
400
423
|
import { Author, Book, global_search } from './sandbox-tools';
|
|
401
424
|
|
|
402
|
-
const
|
|
425
|
+
const totalAuthors = await Author.count();
|
|
426
|
+
const firstPage = await Author.page({ page: 1, perPage: 25 });
|
|
427
|
+
const authors = firstPage.items;
|
|
403
428
|
const tolkien = authors.find((author) => author.name === 'J.R.R. Tolkien');
|
|
404
429
|
if (!tolkien) throw new Error('Author not found');
|
|
430
|
+
console.log(totalAuthors, firstPage.hasMore);
|
|
405
431
|
console.log(tolkien.name); // "J.R.R. Tolkien"
|
|
406
432
|
|
|
433
|
+
for await (const author of Author.iterate({ perPage: 100, maxItems: 200 })) {
|
|
434
|
+
console.log(author.id);
|
|
435
|
+
}
|
|
436
|
+
|
|
407
437
|
const bio = await tolkien.get_bio({ detailed: true });
|
|
408
438
|
console.log(bio.bio); // typed as string
|
|
409
439
|
|
package/dist/agent-evals.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Prompt,
|
|
1
|
+
import { P as Prompt, d as Environment, c as SessionHeapSnapshot, a$ as ManifestContent, ax as RecordObjectOptions, T as ToolWithHandler, G as Granular, C as ConnectOptions, y as CreateEnvironmentData, i as GranularOptions } from './client-DLGC0mJk.mjs';
|
|
2
2
|
import { GeneratedJobCodeIssue, HarnessControllerBudgets } from './agent-harness.mjs';
|
|
3
3
|
import '@automerge/automerge';
|
|
4
4
|
import '@automerge/automerge/slim';
|
package/dist/agent-evals.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Prompt,
|
|
1
|
+
import { P as Prompt, d as Environment, c as SessionHeapSnapshot, a$ as ManifestContent, ax as RecordObjectOptions, T as ToolWithHandler, G as Granular, C as ConnectOptions, y as CreateEnvironmentData, i as GranularOptions } from './client-DLGC0mJk.js';
|
|
2
2
|
import { GeneratedJobCodeIssue, HarnessControllerBudgets } from './agent-harness.js';
|
|
3
3
|
import '@automerge/automerge';
|
|
4
4
|
import '@automerge/automerge/slim';
|
package/dist/agent-evals.js
CHANGED
|
@@ -4687,10 +4687,15 @@ var Session = class {
|
|
|
4687
4687
|
* ```typescript
|
|
4688
4688
|
* import { Author, Book, global_search } from './sandbox-tools';
|
|
4689
4689
|
*
|
|
4690
|
-
* const
|
|
4690
|
+
* const totalAuthors = await Author.count();
|
|
4691
|
+
* const firstAuthorsPage = await Author.page({ page: 1, perPage: 10, saveAs: 'recent_authors' });
|
|
4692
|
+
* const authors = firstAuthorsPage.items;
|
|
4691
4693
|
* const tolkien = await Author.get({ path: 'author_tolkien' });
|
|
4692
4694
|
* const bio = await tolkien.get_bio({ detailed: true });
|
|
4693
4695
|
* const books = await tolkien.get_books();
|
|
4696
|
+
* for await (const author of Author.iterate({ perPage: 100, maxItems: 500 })) {
|
|
4697
|
+
* console.log(author.id);
|
|
4698
|
+
* }
|
|
4694
4699
|
* ```
|
|
4695
4700
|
*
|
|
4696
4701
|
* Effect calls (instance methods, static methods, global functions) trigger
|
|
@@ -11248,9 +11253,9 @@ var STANDARD_MODULES_OPERATIONS = [
|
|
|
11248
11253
|
{ create: "class", extends: "entity", has: {} },
|
|
11249
11254
|
{ create: "user", extends: "entity", has: { email: { value: void 0 }, firstName: { value: void 0 }, lastName: { value: void 0 } } },
|
|
11250
11255
|
{ create: "company", extends: "entity", has: { name: { value: void 0 }, website: { value: void 0 } } },
|
|
11251
|
-
{ create: "string", has: {
|
|
11252
|
-
{ create: "number", has: {
|
|
11253
|
-
{ create: "boolean", has: {
|
|
11256
|
+
{ create: "string", has: {} },
|
|
11257
|
+
{ create: "number", has: {} },
|
|
11258
|
+
{ create: "boolean", has: {} },
|
|
11254
11259
|
{ create: "tool_parameter", has: { name: { value: void 0 }, type: { value: "string" }, description: { value: void 0 }, required: { value: false } } }
|
|
11255
11260
|
];
|
|
11256
11261
|
var BUILTIN_MODULES = {
|
|
@@ -11260,6 +11265,8 @@ var DEFAULT_DIRECT_RECORD_OBJECTS_REQUEST_BATCH_SIZE = 100;
|
|
|
11260
11265
|
var MAX_RECORD_OBJECTS_CONCURRENCY = 16;
|
|
11261
11266
|
var DEFAULT_DIRECT_RECORD_OBJECTS_RETRY_COUNT = 3;
|
|
11262
11267
|
var DEFAULT_DIRECT_RECORD_OBJECTS_RETRY_DELAY_MS = 1e3;
|
|
11268
|
+
var LOCAL_CONTROL_REQUEST_RETRY_COUNT = 4;
|
|
11269
|
+
var LOCAL_CONTROL_REQUEST_RETRY_DELAY_MS = 500;
|
|
11263
11270
|
function planRecordObjectsChunks(records, batchSize) {
|
|
11264
11271
|
const total = records.length;
|
|
11265
11272
|
const size = Math.max(1, Math.min(batchSize, total));
|
|
@@ -11274,6 +11281,17 @@ function planRecordObjectsChunks(records, batchSize) {
|
|
|
11274
11281
|
function sleep(ms) {
|
|
11275
11282
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11276
11283
|
}
|
|
11284
|
+
function isLocalControlUrl(url) {
|
|
11285
|
+
try {
|
|
11286
|
+
const parsed = new URL(url);
|
|
11287
|
+
return parsed.hostname === "127.0.0.1" || parsed.hostname === "localhost" || parsed.hostname === "::1";
|
|
11288
|
+
} catch {
|
|
11289
|
+
return false;
|
|
11290
|
+
}
|
|
11291
|
+
}
|
|
11292
|
+
function isRetryableLocalWorkerRestart(status, body, url) {
|
|
11293
|
+
return isLocalControlUrl(url) && (status === 503 && body.includes("Your worker restarted mid-request") || status === 500 && body.includes("Network connection lost"));
|
|
11294
|
+
}
|
|
11277
11295
|
function isRetryableRecordObjectsError(error) {
|
|
11278
11296
|
const message = error instanceof Error ? error.message : String(error);
|
|
11279
11297
|
return /worker restarted mid-request|econnreset|network|socket connection was closed unexpectedly|timed out/i.test(message);
|
|
@@ -13297,23 +13315,36 @@ var Granular = class _Granular {
|
|
|
13297
13315
|
if (this.debugHttp) {
|
|
13298
13316
|
console.log(`[SDK] Requesting: ${url}`);
|
|
13299
13317
|
}
|
|
13300
|
-
|
|
13301
|
-
|
|
13302
|
-
|
|
13303
|
-
|
|
13304
|
-
|
|
13305
|
-
|
|
13306
|
-
|
|
13318
|
+
for (let attempt = 1; attempt <= LOCAL_CONTROL_REQUEST_RETRY_COUNT; attempt += 1) {
|
|
13319
|
+
const response = await fetch(url, {
|
|
13320
|
+
...options,
|
|
13321
|
+
headers: {
|
|
13322
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
13323
|
+
"Content-Type": "application/json",
|
|
13324
|
+
"Connection": "close",
|
|
13325
|
+
...options.headers
|
|
13326
|
+
}
|
|
13327
|
+
});
|
|
13328
|
+
if (response.ok) {
|
|
13329
|
+
if (response.status === 204) {
|
|
13330
|
+
return { deleted: true };
|
|
13331
|
+
}
|
|
13332
|
+
return response.json();
|
|
13307
13333
|
}
|
|
13308
|
-
});
|
|
13309
|
-
if (!response.ok) {
|
|
13310
13334
|
const errorText = await response.text();
|
|
13335
|
+
const retryable = isRetryableLocalWorkerRestart(response.status, errorText, url);
|
|
13336
|
+
if (retryable && attempt < LOCAL_CONTROL_REQUEST_RETRY_COUNT) {
|
|
13337
|
+
if (this.debugHttp) {
|
|
13338
|
+
console.warn(
|
|
13339
|
+
`[SDK] Retrying local control request after worker restart (${attempt}/${LOCAL_CONTROL_REQUEST_RETRY_COUNT - 1} retries used): ${url}`
|
|
13340
|
+
);
|
|
13341
|
+
}
|
|
13342
|
+
await sleep(LOCAL_CONTROL_REQUEST_RETRY_DELAY_MS * attempt);
|
|
13343
|
+
continue;
|
|
13344
|
+
}
|
|
13311
13345
|
throw new Error(`Granular API Error (${response.status}): ${errorText}`);
|
|
13312
13346
|
}
|
|
13313
|
-
|
|
13314
|
-
return { deleted: true };
|
|
13315
|
-
}
|
|
13316
|
-
return response.json();
|
|
13347
|
+
throw new Error(`Granular API Error: exhausted retries for ${url}`);
|
|
13317
13348
|
}
|
|
13318
13349
|
};
|
|
13319
13350
|
|
|
@@ -14234,7 +14265,10 @@ ${loopBlock}
|
|
|
14234
14265
|
- Only use classes, methods, and parameter shapes that are explicitly declared in those typedefs.
|
|
14235
14266
|
- Never invent helper methods such as \`find(...)\` or unsupported parameters such as \`id\` when the typedefs require \`path\`.
|
|
14236
14267
|
- Use \`ClassName.get({ path })\` only when you already know an object's graph path.
|
|
14237
|
-
- Use \`ClassName.
|
|
14268
|
+
- Use \`ClassName.count()\` when you only need a total.
|
|
14269
|
+
- Use \`ClassName.page({ page, perPage, saveAs })\` when you need both records and pagination metadata like \`totalCount\` or \`hasMore\`.
|
|
14270
|
+
- Use \`ClassName.list({ page, perPage, saveAs })\` to load one typed page of records. \`limit\` is only a legacy alias for \`perPage\`.
|
|
14271
|
+
- Use \`for await (const item of ClassName.iterate({ perPage, maxItems }))\` for large batch jobs so you do not materialize the whole result set at once.
|
|
14238
14272
|
- Instance methods: \`await instance.method_name(params)\`.
|
|
14239
14273
|
- Static methods: \`await ClassName.static_method(params)\`.
|
|
14240
14274
|
- Global effects: \`await effect_name(params)\`.
|
|
@@ -14246,7 +14280,7 @@ ${loopBlock}
|
|
|
14246
14280
|
- Status fields are free-form operational strings, not strict enums. Normalize spelling mentally and do not rely on brittle hard-coded sets that miss variants like \`in-progress\`, \`in_progress\`, \`awaiting-part\`, or \`approval-submitted\`.
|
|
14247
14281
|
- Do not discard a case, work order, part request, or shipment only because its status string does not match your preferred "open" spelling. If the record is otherwise the clear match, inspect it.
|
|
14248
14282
|
- Reuse \`heap.getVar(name)\`, \`heap.setVar(name, value)\`, and \`heap.deleteVar(name)\` only when it clearly helps the next step. Do not mirror data into the heap just for completeness.
|
|
14249
|
-
- Prefer \`heap.setVar(name, value)\` for scalars or one selected instance. Prefer \`ClassName.list({ saveAs })\` for
|
|
14283
|
+
- Prefer \`heap.setVar(name, value)\` for scalars or one selected instance. Prefer \`ClassName.list({ page, perPage, saveAs })\` for reusable list pages instead of \`heap.setVar(name, array)\`.
|
|
14250
14284
|
- Never write an empty array into the heap. If a filtered list is empty, keep it local or clear the previous heap value with \`heap.deleteVar(name)\`.
|
|
14251
14285
|
- Prefer heap-backed state that represents the current choice or recommendation. Avoid storing extra scalar bookkeeping unless it is needed for the next concrete step.
|
|
14252
14286
|
- Only store true sandbox instances, typed lists of sandbox instances, or scalars in the heap. Results returned by static effects like availability/search helpers are often plain JSON, not sandbox instances.
|