@granular-software/sdk 0.4.5 → 0.4.7
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 -19
- package/dist/cli/index.js +43 -14
- package/dist/index.d.mts +45 -12
- package/dist/index.d.ts +45 -12
- package/dist/index.js +120 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +120 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ The official TypeScript SDK for Granular.
|
|
|
8
8
|
|
|
9
9
|
- 🏗️ **Domain Ontology** — Define classes, properties, and relationships as a typed graph
|
|
10
10
|
- 🔧 **Class-Based Tools** — Attach instance methods, static methods, and global tools with typed I/O
|
|
11
|
-
- 🤖 **Domain Synthesis** — Auto-generated TypeScript classes with `
|
|
11
|
+
- 🤖 **Domain Synthesis** — Auto-generated TypeScript classes with `get({ path })`, `list()`, relationship accessors, and typed methods
|
|
12
12
|
- 🔒 **Secure Execution** — Run AI-generated code in isolated sandboxes
|
|
13
13
|
- 👥 **User Permissions** — Control what each user can access
|
|
14
14
|
- ⚡ **Real-time** — WebSocket-based streaming and events
|
|
@@ -55,16 +55,16 @@ import { Granular, type ManifestContent } from '@granular-software/sdk';
|
|
|
55
55
|
|
|
56
56
|
const granular = new Granular({ apiKey: process.env.GRANULAR_API_KEY });
|
|
57
57
|
|
|
58
|
-
// 1.
|
|
59
|
-
const
|
|
58
|
+
// 1. Connect to sandbox for one of your app users
|
|
59
|
+
const env = await granular.connect({
|
|
60
|
+
sandbox: 'my-sandbox',
|
|
60
61
|
userId: 'user_123',
|
|
61
62
|
permissions: ['agent'],
|
|
63
|
+
name: 'Jane Doe', // optional
|
|
64
|
+
email: 'jane@example.com', // optional
|
|
62
65
|
});
|
|
63
66
|
|
|
64
|
-
// 2.
|
|
65
|
-
const env = await granular.connect({ sandbox: 'my-sandbox', user });
|
|
66
|
-
|
|
67
|
-
// 3. Define your domain ontology
|
|
67
|
+
// 2. Define your domain ontology
|
|
68
68
|
const manifest: ManifestContent = {
|
|
69
69
|
schemaVersion: 2,
|
|
70
70
|
name: 'my-app',
|
|
@@ -105,7 +105,7 @@ const manifest: ManifestContent = {
|
|
|
105
105
|
|
|
106
106
|
await env.applyManifest(manifest);
|
|
107
107
|
|
|
108
|
-
//
|
|
108
|
+
// 3. Record object instances
|
|
109
109
|
await env.recordObject({
|
|
110
110
|
className: 'customer',
|
|
111
111
|
id: 'cust_42',
|
|
@@ -113,7 +113,7 @@ await env.recordObject({
|
|
|
113
113
|
fields: { name: 'Acme Corp', email: 'billing@acme.com', tier: 'enterprise' },
|
|
114
114
|
});
|
|
115
115
|
|
|
116
|
-
//
|
|
116
|
+
// 4. Register live effect handlers for effects already declared in the build manifest
|
|
117
117
|
await granular.registerEffects(env.sandboxId, [
|
|
118
118
|
{
|
|
119
119
|
name: 'get_billing_summary',
|
|
@@ -147,8 +147,10 @@ await granular.registerEffects(env.sandboxId, [
|
|
|
147
147
|
const job = await env.submitJob(`
|
|
148
148
|
import { Customer } from './sandbox-tools';
|
|
149
149
|
|
|
150
|
-
//
|
|
151
|
-
const
|
|
150
|
+
// list() discovers instances; get({ path }) hydrates a specific graph object
|
|
151
|
+
const customers = await Customer.list();
|
|
152
|
+
const acme = customers.find((customer) => customer.name === 'Acme Corp');
|
|
153
|
+
if (!acme) throw new Error('Customer not found');
|
|
152
154
|
console.log(acme.name); // "Acme Corp"
|
|
153
155
|
console.log(acme.email); // "billing@acme.com"
|
|
154
156
|
|
|
@@ -170,11 +172,11 @@ Effects must be declared ahead of time in the sandbox build manifest with `withE
|
|
|
170
172
|
## Core Flow
|
|
171
173
|
|
|
172
174
|
```
|
|
173
|
-
declare effects in build manifest → connect() → recordObject() → registerEffects() → submitJob()
|
|
175
|
+
declare effects in build manifest → connect({ userId }) → recordObject() → registerEffects() → submitJob()
|
|
174
176
|
```
|
|
175
177
|
|
|
176
|
-
1. **`
|
|
177
|
-
2. **`
|
|
178
|
+
1. **`connect()`** — Connect to a sandbox for a given `userId`, returning an `Environment`
|
|
179
|
+
2. **`recordUser()`** — Optional explicit user upsert when you want the returned `granularId`
|
|
178
180
|
3. **`applyManifest()`** — Define your domain ontology (classes, properties, relationships)
|
|
179
181
|
4. **`recordObject()`** — Create/update instances of your classes with fields and relationships
|
|
180
182
|
5. **`granular.registerEffects()`** — Register sandbox-scoped live handlers for effects declared in the build manifest
|
|
@@ -230,9 +232,15 @@ await env.applyManifest(manifest);
|
|
|
230
232
|
|
|
231
233
|
## Recording Object Instances
|
|
232
234
|
|
|
233
|
-
After defining the ontology, populate it with data:
|
|
235
|
+
After defining the ontology, connect as a user and populate it with data:
|
|
234
236
|
|
|
235
237
|
```typescript
|
|
238
|
+
const env = await granular.connect({
|
|
239
|
+
sandbox: 'library-app',
|
|
240
|
+
userId: 'user_123',
|
|
241
|
+
permissions: ['agent'],
|
|
242
|
+
});
|
|
243
|
+
|
|
236
244
|
const tolkien = await env.recordObject({
|
|
237
245
|
className: 'author',
|
|
238
246
|
id: 'tolkien', // Real-world ID (unique per class)
|
|
@@ -340,8 +348,11 @@ export declare class Author {
|
|
|
340
348
|
|
|
341
349
|
constructor(id: string, fields?: Record<string, any>);
|
|
342
350
|
|
|
343
|
-
/**
|
|
344
|
-
static
|
|
351
|
+
/** Get a cached Author by graph path, hydrating from the graph when needed */
|
|
352
|
+
static get(query: { path: string; refresh?: boolean }): Promise<Author | null>;
|
|
353
|
+
|
|
354
|
+
/** List known Author instances */
|
|
355
|
+
static list(query?: { limit?: number; saveAs?: string; refresh?: boolean }): Promise<Author[]>;
|
|
345
356
|
|
|
346
357
|
/** Get biography of an author */
|
|
347
358
|
get_bio(input?: { detailed?: boolean }): Promise<{ bio: string; source?: string }>;
|
|
@@ -359,7 +370,9 @@ export declare class Book {
|
|
|
359
370
|
readonly isbn: string;
|
|
360
371
|
readonly published_year: number;
|
|
361
372
|
|
|
362
|
-
static
|
|
373
|
+
static get(query: { path: string; refresh?: boolean }): Promise<Book | null>;
|
|
374
|
+
|
|
375
|
+
static list(query?: { limit?: number; saveAs?: string; refresh?: boolean }): Promise<Book[]>;
|
|
363
376
|
|
|
364
377
|
/** Navigate to author (many_to_one) */
|
|
365
378
|
get_author(): Promise<Author | null>;
|
|
@@ -374,7 +387,9 @@ The LLM or user writes code against these typed classes:
|
|
|
374
387
|
```typescript
|
|
375
388
|
import { Author, Book, global_search } from './sandbox-tools';
|
|
376
389
|
|
|
377
|
-
const
|
|
390
|
+
const authors = await Author.list();
|
|
391
|
+
const tolkien = authors.find((author) => author.name === 'J.R.R. Tolkien');
|
|
392
|
+
if (!tolkien) throw new Error('Author not found');
|
|
378
393
|
console.log(tolkien.name); // "J.R.R. Tolkien"
|
|
379
394
|
|
|
380
395
|
const bio = await tolkien.get_bio({ detailed: true });
|
package/dist/cli/index.js
CHANGED
|
@@ -7771,7 +7771,31 @@ async function main() {
|
|
|
7771
7771
|
await granular.registerEffects(SANDBOX_ID, ${effectsArray});
|
|
7772
7772
|
|
|
7773
7773
|
log('Effects registered. Process kept alive for simulator. Press Ctrl+C to exit.');
|
|
7774
|
-
|
|
7774
|
+
|
|
7775
|
+
const keepAliveTimer = setInterval(() => {
|
|
7776
|
+
// Keep an active event-loop handle so Bun/Node does not exit immediately.
|
|
7777
|
+
}, 60_000);
|
|
7778
|
+
|
|
7779
|
+
await new Promise<void>((resolve) => {
|
|
7780
|
+
let shuttingDown = false;
|
|
7781
|
+
|
|
7782
|
+
const shutdown = async (signal: string) => {
|
|
7783
|
+
if (shuttingDown) return;
|
|
7784
|
+
shuttingDown = true;
|
|
7785
|
+
clearInterval(keepAliveTimer);
|
|
7786
|
+
log(\`Received \${signal}. Shutting down effects host...\`);
|
|
7787
|
+
try {
|
|
7788
|
+
await granular.disconnectEffects(SANDBOX_ID);
|
|
7789
|
+
} catch (error) {
|
|
7790
|
+
console.warn('[Effects] Failed to disconnect live effects cleanly:', error);
|
|
7791
|
+
}
|
|
7792
|
+
resolve();
|
|
7793
|
+
process.exit(0);
|
|
7794
|
+
};
|
|
7795
|
+
|
|
7796
|
+
process.once('SIGINT', () => { void shutdown('SIGINT'); });
|
|
7797
|
+
process.once('SIGTERM', () => { void shutdown('SIGTERM'); });
|
|
7798
|
+
});
|
|
7775
7799
|
}
|
|
7776
7800
|
|
|
7777
7801
|
main().catch((err) => {
|
|
@@ -8598,17 +8622,12 @@ const granular = new Granular({`);
|
|
|
8598
8622
|
lines.push(` ...(process.env.GRANULAR_TOKEN ? { token: process.env.GRANULAR_TOKEN } : { apiKey: process.env.GRANULAR_API_KEY! }),`);
|
|
8599
8623
|
lines.push(`});`);
|
|
8600
8624
|
lines.push(`
|
|
8601
|
-
// 1.
|
|
8602
|
-
lines.push(`const user = await granular.recordUser({`);
|
|
8603
|
-
lines.push(` userId: 'user_123', // Your internal ID`);
|
|
8604
|
-
lines.push(` email: 'user@example.com',`);
|
|
8605
|
-
lines.push(` permissions: ['default'], // Permission profile`);
|
|
8606
|
-
lines.push(`});`);
|
|
8607
|
-
lines.push(`
|
|
8608
|
-
// 2. Connect to the sandbox`);
|
|
8625
|
+
// 1. Connect to the sandbox for one of your app users`);
|
|
8609
8626
|
lines.push(`const env = await granular.connect({`);
|
|
8610
8627
|
lines.push(` sandbox: '${sandboxId}',`);
|
|
8611
|
-
lines.push(` user
|
|
8628
|
+
lines.push(` userId: 'user_123', // Your app's user ID`);
|
|
8629
|
+
lines.push(` email: 'user@example.com', // optional`);
|
|
8630
|
+
lines.push(` permissions: ['default'], // Permission profile`);
|
|
8612
8631
|
lines.push(`});`);
|
|
8613
8632
|
lines.push(`
|
|
8614
8633
|
console.log('Connected to:', env.environmentId);`);
|
|
@@ -8619,6 +8638,12 @@ console.log('Connected to:', env.environmentId);`);
|
|
|
8619
8638
|
if (classes.length > 0) {
|
|
8620
8639
|
lines.push(`
|
|
8621
8640
|
\`\`\`typescript`);
|
|
8641
|
+
lines.push(`const env = await granular.connect({`);
|
|
8642
|
+
lines.push(` sandbox: '${sandboxId}',`);
|
|
8643
|
+
lines.push(` userId: 'user_123',`);
|
|
8644
|
+
lines.push(` permissions: ['default'],`);
|
|
8645
|
+
lines.push(`});`);
|
|
8646
|
+
lines.push(``);
|
|
8622
8647
|
for (const cls of classes) {
|
|
8623
8648
|
const exampleFields = {};
|
|
8624
8649
|
for (const [k, v] of Object.entries(cls.fields)) {
|
|
@@ -8714,12 +8739,16 @@ console.log('Connected to:', env.environmentId);`);
|
|
|
8714
8739
|
if (classes.length > 0) {
|
|
8715
8740
|
const cls = classes[0];
|
|
8716
8741
|
const ClassName = cls.name.charAt(0).toUpperCase() + cls.name.slice(1);
|
|
8717
|
-
lines.push(` // 1.
|
|
8718
|
-
lines.push(` const
|
|
8719
|
-
lines.push(`
|
|
8742
|
+
lines.push(` // 1. List objects`);
|
|
8743
|
+
lines.push(` const items = await ${ClassName}.list({ limit: 10, saveAs: '${cls.name}_items' });`);
|
|
8744
|
+
lines.push(` const item = items[0] ?? null;`);
|
|
8745
|
+
lines.push(` console.log('Loaded:', item?.id);`);
|
|
8720
8746
|
lines.push(``);
|
|
8721
8747
|
lines.push(` // 2. Call instance method`);
|
|
8722
|
-
lines.push(`
|
|
8748
|
+
lines.push(` if (item) {`);
|
|
8749
|
+
lines.push(` const summary = await item.summarize({ maxLength: 100 });`);
|
|
8750
|
+
lines.push(` console.log(summary);`);
|
|
8751
|
+
lines.push(` }`);
|
|
8723
8752
|
lines.push(``);
|
|
8724
8753
|
lines.push(` // 3. Call static method`);
|
|
8725
8754
|
lines.push(` const results = await ${ClassName}.search({ query: 'test' });`);
|
package/dist/index.d.mts
CHANGED
|
@@ -40,9 +40,13 @@ type GranularAuth = string;
|
|
|
40
40
|
* A user/subject object returned from recordUser()
|
|
41
41
|
*/
|
|
42
42
|
interface User {
|
|
43
|
-
/** Internal
|
|
43
|
+
/** Internal Granular user identifier */
|
|
44
|
+
granularId: string;
|
|
45
|
+
/** External user identifier from your app */
|
|
46
|
+
userId: string;
|
|
47
|
+
/** @deprecated Use `granularId` instead */
|
|
44
48
|
subjectId: string;
|
|
45
|
-
/**
|
|
49
|
+
/** @deprecated Use `userId` instead */
|
|
46
50
|
identityId: string;
|
|
47
51
|
/** User's display name */
|
|
48
52
|
name?: string;
|
|
@@ -68,6 +72,10 @@ interface RecordUserOptions {
|
|
|
68
72
|
* Subject as returned from the API
|
|
69
73
|
*/
|
|
70
74
|
interface Subject {
|
|
75
|
+
/** Internal Granular user identifier */
|
|
76
|
+
granularId: string;
|
|
77
|
+
/** External user identifier from your app */
|
|
78
|
+
userId: string;
|
|
71
79
|
subjectId: string;
|
|
72
80
|
tenantId: string;
|
|
73
81
|
identityId: string;
|
|
@@ -83,8 +91,24 @@ interface Subject {
|
|
|
83
91
|
interface ConnectOptions {
|
|
84
92
|
/** The sandbox name or ID to connect to */
|
|
85
93
|
sandbox: string;
|
|
86
|
-
/**
|
|
87
|
-
|
|
94
|
+
/**
|
|
95
|
+
* External user identifier from your app. This is the primary input for
|
|
96
|
+
* connecting to a sandbox and the only required user field in the common case.
|
|
97
|
+
*/
|
|
98
|
+
userId?: string;
|
|
99
|
+
/**
|
|
100
|
+
* Internal Granular user identifier. Optional fallback when you only know
|
|
101
|
+
* the Granular-side ID for an existing subject.
|
|
102
|
+
*/
|
|
103
|
+
granularId?: string;
|
|
104
|
+
/** Optional display name used when upserting the user */
|
|
105
|
+
name?: string;
|
|
106
|
+
/** Optional email used when upserting the user */
|
|
107
|
+
email?: string;
|
|
108
|
+
/** Permission profile IDs or names to ensure before connecting */
|
|
109
|
+
permissions?: string[];
|
|
110
|
+
/** Backwards-compatible user object returned from recordUser() */
|
|
111
|
+
user?: User;
|
|
88
112
|
/** Optional stable client ID. Defaults to `client_${Date.now()}`. Use a fixed
|
|
89
113
|
* value for long-lived effect hosts so tool catalogs don't accumulate. */
|
|
90
114
|
clientId?: string;
|
|
@@ -274,6 +298,8 @@ interface EffectHandlerContext {
|
|
|
274
298
|
principalId?: string;
|
|
275
299
|
permissionProfileId?: string;
|
|
276
300
|
user: {
|
|
301
|
+
granularId?: string;
|
|
302
|
+
userId?: string;
|
|
277
303
|
subjectId: string;
|
|
278
304
|
identityId?: string;
|
|
279
305
|
principalId?: string;
|
|
@@ -904,7 +930,8 @@ declare class Session {
|
|
|
904
930
|
* ```typescript
|
|
905
931
|
* import { Author, Book, global_search } from './sandbox-tools';
|
|
906
932
|
*
|
|
907
|
-
* const
|
|
933
|
+
* const authors = await Author.list({ limit: 10, saveAs: 'recent_authors' });
|
|
934
|
+
* const tolkien = await Author.get({ path: 'author_tolkien' });
|
|
908
935
|
* const bio = await tolkien.get_bio({ detailed: true });
|
|
909
936
|
* const books = await tolkien.get_books();
|
|
910
937
|
* ```
|
|
@@ -1016,6 +1043,8 @@ declare class Environment extends Session {
|
|
|
1016
1043
|
get sandboxId(): string;
|
|
1017
1044
|
/** The subject ID */
|
|
1018
1045
|
get subjectId(): string;
|
|
1046
|
+
/** Internal Granular user identifier for this environment */
|
|
1047
|
+
get granularId(): string;
|
|
1019
1048
|
/** The permission profile ID */
|
|
1020
1049
|
get permissionProfileId(): string;
|
|
1021
1050
|
/** The GraphQL API endpoint URL */
|
|
@@ -1329,7 +1358,7 @@ declare class Granular {
|
|
|
1329
1358
|
* Records/upserts a user and prepares them for sandbox connections
|
|
1330
1359
|
*
|
|
1331
1360
|
* @param options - User options
|
|
1332
|
-
* @returns The user
|
|
1361
|
+
* @returns The recorded user with both `userId` and `granularId`
|
|
1333
1362
|
*
|
|
1334
1363
|
* @example
|
|
1335
1364
|
* ```typescript
|
|
@@ -1341,6 +1370,7 @@ declare class Granular {
|
|
|
1341
1370
|
* ```
|
|
1342
1371
|
*/
|
|
1343
1372
|
recordUser(options: RecordUserOptions): Promise<User>;
|
|
1373
|
+
private resolveConnectUser;
|
|
1344
1374
|
/**
|
|
1345
1375
|
* Connect to a sandbox and establish a real-time environment session.
|
|
1346
1376
|
*
|
|
@@ -1353,14 +1383,10 @@ declare class Granular {
|
|
|
1353
1383
|
*
|
|
1354
1384
|
* @example
|
|
1355
1385
|
* ```typescript
|
|
1356
|
-
* const user = await granular.recordUser({
|
|
1357
|
-
* userId: 'user_123',
|
|
1358
|
-
* permissions: ['agent'],
|
|
1359
|
-
* });
|
|
1360
|
-
*
|
|
1361
1386
|
* const environment = await granular.connect({
|
|
1362
1387
|
* sandbox: 'my-sandbox',
|
|
1363
|
-
*
|
|
1388
|
+
* userId: 'user_123',
|
|
1389
|
+
* permissions: ['agent'],
|
|
1364
1390
|
* });
|
|
1365
1391
|
*
|
|
1366
1392
|
* await granular.registerEffect('my-sandbox', {
|
|
@@ -1410,6 +1436,13 @@ declare class Granular {
|
|
|
1410
1436
|
* sandbox-scoped live catalog.
|
|
1411
1437
|
*/
|
|
1412
1438
|
unregisterEffect(sandboxNameOrId: string, name: string): Promise<void>;
|
|
1439
|
+
/**
|
|
1440
|
+
* Disconnect one sandbox-scoped effect host, or all of them when no sandbox is provided.
|
|
1441
|
+
*
|
|
1442
|
+
* This is primarily useful for long-lived helper processes such as generated
|
|
1443
|
+
* `granular-effects.ts` scripts that need to shut down cleanly on SIGINT/SIGTERM.
|
|
1444
|
+
*/
|
|
1445
|
+
disconnectEffects(sandboxNameOrId?: string): Promise<void>;
|
|
1413
1446
|
/**
|
|
1414
1447
|
* Unregister all effects for a sandbox.
|
|
1415
1448
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -40,9 +40,13 @@ type GranularAuth = string;
|
|
|
40
40
|
* A user/subject object returned from recordUser()
|
|
41
41
|
*/
|
|
42
42
|
interface User {
|
|
43
|
-
/** Internal
|
|
43
|
+
/** Internal Granular user identifier */
|
|
44
|
+
granularId: string;
|
|
45
|
+
/** External user identifier from your app */
|
|
46
|
+
userId: string;
|
|
47
|
+
/** @deprecated Use `granularId` instead */
|
|
44
48
|
subjectId: string;
|
|
45
|
-
/**
|
|
49
|
+
/** @deprecated Use `userId` instead */
|
|
46
50
|
identityId: string;
|
|
47
51
|
/** User's display name */
|
|
48
52
|
name?: string;
|
|
@@ -68,6 +72,10 @@ interface RecordUserOptions {
|
|
|
68
72
|
* Subject as returned from the API
|
|
69
73
|
*/
|
|
70
74
|
interface Subject {
|
|
75
|
+
/** Internal Granular user identifier */
|
|
76
|
+
granularId: string;
|
|
77
|
+
/** External user identifier from your app */
|
|
78
|
+
userId: string;
|
|
71
79
|
subjectId: string;
|
|
72
80
|
tenantId: string;
|
|
73
81
|
identityId: string;
|
|
@@ -83,8 +91,24 @@ interface Subject {
|
|
|
83
91
|
interface ConnectOptions {
|
|
84
92
|
/** The sandbox name or ID to connect to */
|
|
85
93
|
sandbox: string;
|
|
86
|
-
/**
|
|
87
|
-
|
|
94
|
+
/**
|
|
95
|
+
* External user identifier from your app. This is the primary input for
|
|
96
|
+
* connecting to a sandbox and the only required user field in the common case.
|
|
97
|
+
*/
|
|
98
|
+
userId?: string;
|
|
99
|
+
/**
|
|
100
|
+
* Internal Granular user identifier. Optional fallback when you only know
|
|
101
|
+
* the Granular-side ID for an existing subject.
|
|
102
|
+
*/
|
|
103
|
+
granularId?: string;
|
|
104
|
+
/** Optional display name used when upserting the user */
|
|
105
|
+
name?: string;
|
|
106
|
+
/** Optional email used when upserting the user */
|
|
107
|
+
email?: string;
|
|
108
|
+
/** Permission profile IDs or names to ensure before connecting */
|
|
109
|
+
permissions?: string[];
|
|
110
|
+
/** Backwards-compatible user object returned from recordUser() */
|
|
111
|
+
user?: User;
|
|
88
112
|
/** Optional stable client ID. Defaults to `client_${Date.now()}`. Use a fixed
|
|
89
113
|
* value for long-lived effect hosts so tool catalogs don't accumulate. */
|
|
90
114
|
clientId?: string;
|
|
@@ -274,6 +298,8 @@ interface EffectHandlerContext {
|
|
|
274
298
|
principalId?: string;
|
|
275
299
|
permissionProfileId?: string;
|
|
276
300
|
user: {
|
|
301
|
+
granularId?: string;
|
|
302
|
+
userId?: string;
|
|
277
303
|
subjectId: string;
|
|
278
304
|
identityId?: string;
|
|
279
305
|
principalId?: string;
|
|
@@ -904,7 +930,8 @@ declare class Session {
|
|
|
904
930
|
* ```typescript
|
|
905
931
|
* import { Author, Book, global_search } from './sandbox-tools';
|
|
906
932
|
*
|
|
907
|
-
* const
|
|
933
|
+
* const authors = await Author.list({ limit: 10, saveAs: 'recent_authors' });
|
|
934
|
+
* const tolkien = await Author.get({ path: 'author_tolkien' });
|
|
908
935
|
* const bio = await tolkien.get_bio({ detailed: true });
|
|
909
936
|
* const books = await tolkien.get_books();
|
|
910
937
|
* ```
|
|
@@ -1016,6 +1043,8 @@ declare class Environment extends Session {
|
|
|
1016
1043
|
get sandboxId(): string;
|
|
1017
1044
|
/** The subject ID */
|
|
1018
1045
|
get subjectId(): string;
|
|
1046
|
+
/** Internal Granular user identifier for this environment */
|
|
1047
|
+
get granularId(): string;
|
|
1019
1048
|
/** The permission profile ID */
|
|
1020
1049
|
get permissionProfileId(): string;
|
|
1021
1050
|
/** The GraphQL API endpoint URL */
|
|
@@ -1329,7 +1358,7 @@ declare class Granular {
|
|
|
1329
1358
|
* Records/upserts a user and prepares them for sandbox connections
|
|
1330
1359
|
*
|
|
1331
1360
|
* @param options - User options
|
|
1332
|
-
* @returns The user
|
|
1361
|
+
* @returns The recorded user with both `userId` and `granularId`
|
|
1333
1362
|
*
|
|
1334
1363
|
* @example
|
|
1335
1364
|
* ```typescript
|
|
@@ -1341,6 +1370,7 @@ declare class Granular {
|
|
|
1341
1370
|
* ```
|
|
1342
1371
|
*/
|
|
1343
1372
|
recordUser(options: RecordUserOptions): Promise<User>;
|
|
1373
|
+
private resolveConnectUser;
|
|
1344
1374
|
/**
|
|
1345
1375
|
* Connect to a sandbox and establish a real-time environment session.
|
|
1346
1376
|
*
|
|
@@ -1353,14 +1383,10 @@ declare class Granular {
|
|
|
1353
1383
|
*
|
|
1354
1384
|
* @example
|
|
1355
1385
|
* ```typescript
|
|
1356
|
-
* const user = await granular.recordUser({
|
|
1357
|
-
* userId: 'user_123',
|
|
1358
|
-
* permissions: ['agent'],
|
|
1359
|
-
* });
|
|
1360
|
-
*
|
|
1361
1386
|
* const environment = await granular.connect({
|
|
1362
1387
|
* sandbox: 'my-sandbox',
|
|
1363
|
-
*
|
|
1388
|
+
* userId: 'user_123',
|
|
1389
|
+
* permissions: ['agent'],
|
|
1364
1390
|
* });
|
|
1365
1391
|
*
|
|
1366
1392
|
* await granular.registerEffect('my-sandbox', {
|
|
@@ -1410,6 +1436,13 @@ declare class Granular {
|
|
|
1410
1436
|
* sandbox-scoped live catalog.
|
|
1411
1437
|
*/
|
|
1412
1438
|
unregisterEffect(sandboxNameOrId: string, name: string): Promise<void>;
|
|
1439
|
+
/**
|
|
1440
|
+
* Disconnect one sandbox-scoped effect host, or all of them when no sandbox is provided.
|
|
1441
|
+
*
|
|
1442
|
+
* This is primarily useful for long-lived helper processes such as generated
|
|
1443
|
+
* `granular-effects.ts` scripts that need to shut down cleanly on SIGINT/SIGTERM.
|
|
1444
|
+
*/
|
|
1445
|
+
disconnectEffects(sandboxNameOrId?: string): Promise<void>;
|
|
1413
1446
|
/**
|
|
1414
1447
|
* Unregister all effects for a sandbox.
|
|
1415
1448
|
*/
|