@granular-software/sdk 0.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.
- package/README.md +476 -0
- package/dist/adapters/anthropic.d.mts +64 -0
- package/dist/adapters/anthropic.d.ts +64 -0
- package/dist/adapters/anthropic.js +77 -0
- package/dist/adapters/anthropic.js.map +1 -0
- package/dist/adapters/anthropic.mjs +72 -0
- package/dist/adapters/anthropic.mjs.map +1 -0
- package/dist/adapters/langchain.d.mts +31 -0
- package/dist/adapters/langchain.d.ts +31 -0
- package/dist/adapters/langchain.js +49 -0
- package/dist/adapters/langchain.js.map +1 -0
- package/dist/adapters/langchain.mjs +46 -0
- package/dist/adapters/langchain.mjs.map +1 -0
- package/dist/adapters/mastra.d.mts +23 -0
- package/dist/adapters/mastra.d.ts +23 -0
- package/dist/adapters/mastra.js +26 -0
- package/dist/adapters/mastra.js.map +1 -0
- package/dist/adapters/mastra.mjs +24 -0
- package/dist/adapters/mastra.mjs.map +1 -0
- package/dist/adapters/openai.d.mts +76 -0
- package/dist/adapters/openai.d.ts +76 -0
- package/dist/adapters/openai.js +81 -0
- package/dist/adapters/openai.js.map +1 -0
- package/dist/adapters/openai.mjs +76 -0
- package/dist/adapters/openai.mjs.map +1 -0
- package/dist/index.d.mts +616 -0
- package/dist/index.d.ts +616 -0
- package/dist/index.js +1801 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1773 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types-D46q5WTh.d.mts +595 -0
- package/dist/types-D46q5WTh.d.ts +595 -0
- package/package.json +105 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,616 @@
|
|
|
1
|
+
import * as Automerge from '@automerge/automerge';
|
|
2
|
+
import { Doc } from '@automerge/automerge';
|
|
3
|
+
import { W as WSClientOptions, T as ToolWithHandler, P as PublishToolsResult, J as Job, a as ToolHandler, I as InstanceToolHandler, D as DomainState, G as GranularOptions, R as RecordUserOptions, U as User, C as ConnectOptions, E as EnvironmentData, b as GraphQLResult, c as DefineRelationshipOptions, d as RelationshipInfo, M as ModelRef, e as ManifestContent, f as RecordObjectOptions, g as RecordObjectResult, S as SandboxListResponse, h as Sandbox, i as CreateSandboxData, j as DeleteResponse, k as PermissionProfile, l as CreatePermissionProfileData, m as CreateEnvironmentData, n as Subject, A as AssignmentListResponse } from './types-D46q5WTh.js';
|
|
4
|
+
export { $ as APIError, r as Assignment, w as Build, x as BuildListResponse, B as BuildPolicy, v as BuildStatus, s as EnvironmentListResponse, y as JobStatus, z as JobSubmitResult, t as Manifest, Z as ManifestImport, u as ManifestListResponse, Y as ManifestOperation, V as ManifestPropertySpec, X as ManifestRelationshipDef, _ as ManifestVolume, q as PermissionProfileListResponse, p as PermissionRules, F as Prompt, H as RPCRequest, N as RPCRequestFromServer, K as RPCResponse, L as SyncMessage, O as ToolInvokeParams, Q as ToolResultParams, o as ToolSchema } from './types-D46q5WTh.js';
|
|
5
|
+
|
|
6
|
+
declare class WSClient {
|
|
7
|
+
private ws;
|
|
8
|
+
private url;
|
|
9
|
+
private sessionId;
|
|
10
|
+
private token;
|
|
11
|
+
private messageQueue;
|
|
12
|
+
private syncHandlers;
|
|
13
|
+
private rpcHandlers;
|
|
14
|
+
private eventHandlers;
|
|
15
|
+
private nextRpcId;
|
|
16
|
+
doc: Automerge.Doc<Record<string, unknown>>;
|
|
17
|
+
private syncState;
|
|
18
|
+
private reconnectTimer;
|
|
19
|
+
private isExplicitlyDisconnected;
|
|
20
|
+
constructor(options: WSClientOptions);
|
|
21
|
+
/**
|
|
22
|
+
* Connect to the WebSocket server
|
|
23
|
+
* @returns {Promise<void>} Resolves when connection is open
|
|
24
|
+
*/
|
|
25
|
+
connect(): Promise<void>;
|
|
26
|
+
private handleDisconnect;
|
|
27
|
+
private handleMessage;
|
|
28
|
+
/**
|
|
29
|
+
* Make an RPC call to the server
|
|
30
|
+
* @param {string} method - RPC method name
|
|
31
|
+
* @param {unknown} params - Request parameters
|
|
32
|
+
* @returns {Promise<unknown>} Response result
|
|
33
|
+
* @throws {Error} If connection is closed or timeout occurs
|
|
34
|
+
*/
|
|
35
|
+
call(method: string, params: unknown): Promise<unknown>;
|
|
36
|
+
private handleIncomingRpc;
|
|
37
|
+
/**
|
|
38
|
+
* Subscribe to client events
|
|
39
|
+
* @param {string} event - Event name
|
|
40
|
+
* @param {Function} handler - Event handler
|
|
41
|
+
*/
|
|
42
|
+
on(event: string, handler: (params: unknown) => void): void;
|
|
43
|
+
/**
|
|
44
|
+
* Register an RPC handler for incoming server requests
|
|
45
|
+
* @param {string} method - RPC method name
|
|
46
|
+
* @param {Function} handler - Handler function
|
|
47
|
+
*/
|
|
48
|
+
registerRpcHandler(method: string, handler: (params: unknown) => Promise<unknown>): void;
|
|
49
|
+
/**
|
|
50
|
+
* Unsubscribe from client events
|
|
51
|
+
* @param {string} event - Event name
|
|
52
|
+
* @param {Function} handler - Handler to remove
|
|
53
|
+
*/
|
|
54
|
+
off(event: string, handler: (params: unknown) => void): void;
|
|
55
|
+
/**
|
|
56
|
+
* Emit an event locally
|
|
57
|
+
* @param {string} event - Event name
|
|
58
|
+
* @param params - Event data
|
|
59
|
+
*/
|
|
60
|
+
emit(event: string, params: unknown): void;
|
|
61
|
+
/**
|
|
62
|
+
* Disconnect the WebSocket and clear state
|
|
63
|
+
*/
|
|
64
|
+
disconnect(): void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
declare class Session {
|
|
68
|
+
protected client: WSClient;
|
|
69
|
+
private clientId;
|
|
70
|
+
private jobsMap;
|
|
71
|
+
private eventListeners;
|
|
72
|
+
private toolHandlers;
|
|
73
|
+
/** Tracks which tools are instance methods (className set, not static) */
|
|
74
|
+
private instanceTools;
|
|
75
|
+
private currentDomainRevision;
|
|
76
|
+
constructor(client: WSClient, clientId?: string);
|
|
77
|
+
get document(): Doc<Record<string, unknown>>;
|
|
78
|
+
get domainRevision(): string | null;
|
|
79
|
+
/**
|
|
80
|
+
* Make a raw RPC call to the session's Durable Object.
|
|
81
|
+
*
|
|
82
|
+
* Use this when you need to call an RPC method that doesn't have a
|
|
83
|
+
* dedicated wrapper method on the Session/Environment class.
|
|
84
|
+
*
|
|
85
|
+
* @param method - RPC method name (e.g. 'domain.fetchPackagePart')
|
|
86
|
+
* @param params - Request parameters
|
|
87
|
+
* @returns The raw RPC response
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* const result = await env.rpc('domain.fetchPackagePart', {
|
|
92
|
+
* moduleSpecifier: '@sandbox/domain',
|
|
93
|
+
* part: 'types',
|
|
94
|
+
* });
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
rpc<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
|
|
98
|
+
/**
|
|
99
|
+
* Send client hello to establish the session
|
|
100
|
+
*/
|
|
101
|
+
hello(): Promise<{
|
|
102
|
+
ok: boolean;
|
|
103
|
+
environmentId?: string;
|
|
104
|
+
docId?: string;
|
|
105
|
+
}>;
|
|
106
|
+
/**
|
|
107
|
+
* Publish tools to the sandbox and register handlers for reverse-RPC.
|
|
108
|
+
*
|
|
109
|
+
* Tools can be:
|
|
110
|
+
* - **Instance methods**: set `className` (handler receives `(objectId, params)`)
|
|
111
|
+
* - **Static methods**: set `className` + `static: true` (handler receives `(params)`)
|
|
112
|
+
* - **Global tools**: omit `className` (handler receives `(params)`)
|
|
113
|
+
*
|
|
114
|
+
* Both `inputSchema` and `outputSchema` accept JSON Schema objects. The
|
|
115
|
+
* `outputSchema` drives the return type in the auto-generated TypeScript
|
|
116
|
+
* class declarations that sandbox code imports from `./sandbox-tools`.
|
|
117
|
+
*
|
|
118
|
+
* This method:
|
|
119
|
+
* 1. Extracts tool schemas (including `outputSchema`) from the provided tools
|
|
120
|
+
* 2. Publishes them via `client.publishRawToolCatalog` RPC
|
|
121
|
+
* 3. Registers handlers locally for `tool.invoke` RPC calls
|
|
122
|
+
* 4. Returns the `domainRevision` needed for job submission
|
|
123
|
+
*
|
|
124
|
+
* @param tools - Array of tools with handlers
|
|
125
|
+
* @param revision - Optional revision string (default: "1.0.0")
|
|
126
|
+
* @returns PublishToolsResult with domainRevision
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```typescript
|
|
130
|
+
* await env.publishTools([
|
|
131
|
+
* {
|
|
132
|
+
* name: 'get_bio',
|
|
133
|
+
* description: 'Get biography of an author',
|
|
134
|
+
* className: 'author',
|
|
135
|
+
* inputSchema: { type: 'object', properties: { detailed: { type: 'boolean' } } },
|
|
136
|
+
* outputSchema: { type: 'object', properties: { bio: { type: 'string' } }, required: ['bio'] },
|
|
137
|
+
* handler: async (id, params) => ({ bio: `Bio of ${id}` }),
|
|
138
|
+
* },
|
|
139
|
+
* ]);
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
publishTools(tools: ToolWithHandler[], revision?: string): Promise<PublishToolsResult>;
|
|
143
|
+
/**
|
|
144
|
+
* Submit a job to execute code in the sandbox.
|
|
145
|
+
*
|
|
146
|
+
* The code can import typed classes from `./sandbox-tools`:
|
|
147
|
+
* ```typescript
|
|
148
|
+
* import { Author, Book, global_search } from './sandbox-tools';
|
|
149
|
+
*
|
|
150
|
+
* const tolkien = await Author.find({ id: 'tolkien' });
|
|
151
|
+
* const bio = await tolkien.get_bio({ detailed: true });
|
|
152
|
+
* const books = await tolkien.get_books();
|
|
153
|
+
* ```
|
|
154
|
+
*
|
|
155
|
+
* Tool calls (instance methods, static methods, global functions) trigger
|
|
156
|
+
* `tool.invoke` RPC back to this client, where the registered handlers
|
|
157
|
+
* execute locally and return the result to the sandbox.
|
|
158
|
+
*/
|
|
159
|
+
submitJob(code: string, domainRevision?: string): Promise<Job>;
|
|
160
|
+
/**
|
|
161
|
+
* Register a handler for a specific tool.
|
|
162
|
+
* @param isInstance - If true, handler will receive (id, params) for instance method dispatch.
|
|
163
|
+
*/
|
|
164
|
+
registerToolHandler(name: string, handler: ToolHandler | InstanceToolHandler, isInstance?: boolean): void;
|
|
165
|
+
/**
|
|
166
|
+
* Respond to a prompt request from the sandbox
|
|
167
|
+
*/
|
|
168
|
+
answerPrompt(promptId: string, answer: unknown): Promise<void>;
|
|
169
|
+
/**
|
|
170
|
+
* Get the current domain state and available tools
|
|
171
|
+
*/
|
|
172
|
+
getDomain(): Promise<DomainState>;
|
|
173
|
+
/**
|
|
174
|
+
* Get auto-generated TypeScript class declarations for the current domain.
|
|
175
|
+
*
|
|
176
|
+
* Returns typed declarations including:
|
|
177
|
+
* - Classes with readonly properties (from manifest)
|
|
178
|
+
* - `static find(query: { id: string })` for each class
|
|
179
|
+
* - Instance methods with typed input/output (from `publishTools` with `className`)
|
|
180
|
+
* - Static methods (from `publishTools` with `className` + `static: true`)
|
|
181
|
+
* - Relationship accessors (`get_books()`, `get_author()`, etc.)
|
|
182
|
+
* - Global tool functions (from `publishTools` without `className`)
|
|
183
|
+
*
|
|
184
|
+
* Pass this documentation to LLMs so they can write correct typed code
|
|
185
|
+
* that imports from `./sandbox-tools`.
|
|
186
|
+
*
|
|
187
|
+
* Falls back to generating markdown docs from the domain summary if
|
|
188
|
+
* the synthesis server is unavailable.
|
|
189
|
+
*/
|
|
190
|
+
getDomainDocumentation(): Promise<string>;
|
|
191
|
+
/**
|
|
192
|
+
* Generate markdown documentation from the domain summary.
|
|
193
|
+
* Class-aware: groups tools by class with property/relationship info.
|
|
194
|
+
*/
|
|
195
|
+
private generateFallbackDocs;
|
|
196
|
+
/**
|
|
197
|
+
* Close the session and disconnect from the sandbox
|
|
198
|
+
*/
|
|
199
|
+
disconnect(): Promise<void>;
|
|
200
|
+
/**
|
|
201
|
+
* Subscribe to session events
|
|
202
|
+
*/
|
|
203
|
+
on(event: string, handler: (data: unknown) => void): void;
|
|
204
|
+
/**
|
|
205
|
+
* Unsubscribe from session events
|
|
206
|
+
*/
|
|
207
|
+
off(event: string, handler: (data: unknown) => void): void;
|
|
208
|
+
private setupToolInvokeHandler;
|
|
209
|
+
private setupEventHandlers;
|
|
210
|
+
private emit;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Environment represents a connected session to a sandbox for a specific user.
|
|
215
|
+
*
|
|
216
|
+
* After connecting, you can:
|
|
217
|
+
* 1. Define your domain ontology via `applyManifest()` (classes, properties, relationships)
|
|
218
|
+
* 2. Record object instances via `recordObject()` (with fields and relationship attachments)
|
|
219
|
+
* 3. Publish tools via `publishTools()` (instance methods, static methods, global tools — with typed I/O)
|
|
220
|
+
* 4. Submit jobs via `submitJob()` that import auto-generated typed classes from `./sandbox-tools`
|
|
221
|
+
* 5. Execute GraphQL queries via `graphql()` (authenticated automatically)
|
|
222
|
+
*
|
|
223
|
+
* Tool calls from the sandbox automatically invoke your handlers via reverse-RPC.
|
|
224
|
+
*
|
|
225
|
+
* Object IDs are unique per class. Internally, the graph path is `{className}_{id}`
|
|
226
|
+
* (e.g., `author_tolkien`). Use `Environment.toGraphPath()` and
|
|
227
|
+
* `Environment.extractIdFromGraphPath()` for conversions.
|
|
228
|
+
*/
|
|
229
|
+
declare class Environment extends Session {
|
|
230
|
+
private envData;
|
|
231
|
+
private _apiKey;
|
|
232
|
+
private _apiEndpoint;
|
|
233
|
+
constructor(client: WSClient, envData: EnvironmentData, clientId: string, apiKey: string, apiEndpoint: string);
|
|
234
|
+
/** The environment ID */
|
|
235
|
+
get environmentId(): string;
|
|
236
|
+
/** The sandbox ID */
|
|
237
|
+
get sandboxId(): string;
|
|
238
|
+
/** The subject ID */
|
|
239
|
+
get subjectId(): string;
|
|
240
|
+
/** The permission profile ID */
|
|
241
|
+
get permissionProfileId(): string;
|
|
242
|
+
/** The GraphQL API endpoint URL */
|
|
243
|
+
get apiEndpoint(): string;
|
|
244
|
+
/**
|
|
245
|
+
* Convert a class name + real-world ID into a unique graph path.
|
|
246
|
+
*
|
|
247
|
+
* Two objects of *different* classes may share the same real-world ID,
|
|
248
|
+
* so the graph path must incorporate the class to guarantee uniqueness.
|
|
249
|
+
*
|
|
250
|
+
* Format: `{className}_{id}` — deterministic, human-readable.
|
|
251
|
+
*
|
|
252
|
+
* **Convention**: class names should be simple identifiers without
|
|
253
|
+
* underscores (e.g. `author`, `book`). This ensures the prefix is
|
|
254
|
+
* unambiguously parseable by `extractIdFromGraphPath`.
|
|
255
|
+
*/
|
|
256
|
+
static toGraphPath(className: string, id: string): string;
|
|
257
|
+
/**
|
|
258
|
+
* Extract the real-world ID from a graph path, given the class name.
|
|
259
|
+
*
|
|
260
|
+
* Strips the `{className}_` prefix. Returns the raw path if the
|
|
261
|
+
* expected prefix is not found.
|
|
262
|
+
*/
|
|
263
|
+
static extractIdFromGraphPath(graphPath: string, className: string): string;
|
|
264
|
+
/**
|
|
265
|
+
* Execute a GraphQL query against the environment's graph.
|
|
266
|
+
*
|
|
267
|
+
* The query uses the Granular graph query language (based on Cypher/GraphQL).
|
|
268
|
+
* Authentication is handled automatically using the SDK's API key.
|
|
269
|
+
*
|
|
270
|
+
* @param query - The GraphQL query string
|
|
271
|
+
* @param variables - Optional variables for the query
|
|
272
|
+
* @returns The query result data
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```typescript
|
|
276
|
+
* // Read the workspace
|
|
277
|
+
* const result = await env.graphql(
|
|
278
|
+
* `query { model(path: "workspace") { path label submodels { path label } } }`
|
|
279
|
+
* );
|
|
280
|
+
* console.log(result.data);
|
|
281
|
+
*
|
|
282
|
+
* // Create a model
|
|
283
|
+
* const created = await env.graphql(
|
|
284
|
+
* `mutation { at(path: "workspace") { create_submodel(subpath: "my_node", label: "My Node", prototype: "Model") { model { path label } } } }`
|
|
285
|
+
* );
|
|
286
|
+
* ```
|
|
287
|
+
*/
|
|
288
|
+
graphql<T = any>(query: string, variables?: Record<string, any>): Promise<GraphQLResult<T>>;
|
|
289
|
+
/**
|
|
290
|
+
* Define a relationship between two model types.
|
|
291
|
+
*
|
|
292
|
+
* Creates both submodels (if they don't exist) and links them with
|
|
293
|
+
* a RelationshipDef node that encodes cardinality.
|
|
294
|
+
*
|
|
295
|
+
* @example
|
|
296
|
+
* ```typescript
|
|
297
|
+
* // Author has many Books, Book has one Author
|
|
298
|
+
* const rel = await env.defineRelationship({
|
|
299
|
+
* model: 'author',
|
|
300
|
+
* localSubmodel: 'books',
|
|
301
|
+
* localIsMany: true,
|
|
302
|
+
* foreignModel: 'book',
|
|
303
|
+
* foreignSubmodel: 'author',
|
|
304
|
+
* foreignIsMany: false,
|
|
305
|
+
* });
|
|
306
|
+
* console.log(rel.relationship_kind); // "one_to_many"
|
|
307
|
+
* ```
|
|
308
|
+
*/
|
|
309
|
+
defineRelationship(options: DefineRelationshipOptions): Promise<RelationshipInfo>;
|
|
310
|
+
/**
|
|
311
|
+
* Get all relationships for a model type.
|
|
312
|
+
*
|
|
313
|
+
* @param modelPath - The model type path (e.g., "author")
|
|
314
|
+
* @returns Array of relationships from this model's perspective
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```typescript
|
|
318
|
+
* const rels = await env.getRelationships('author');
|
|
319
|
+
* for (const rel of rels) {
|
|
320
|
+
* console.log(`${rel.local_submodel.path} -> ${rel.foreign_model.path} (${rel.relationship_kind})`);
|
|
321
|
+
* }
|
|
322
|
+
* ```
|
|
323
|
+
*/
|
|
324
|
+
getRelationships(modelPath: string): Promise<RelationshipInfo[]>;
|
|
325
|
+
/**
|
|
326
|
+
* Attach a target model to a relationship submodel.
|
|
327
|
+
*
|
|
328
|
+
* Handles cardinality automatically:
|
|
329
|
+
* - "One" side: sets/replaces the reference
|
|
330
|
+
* - "Many" side: adds the target to the collection
|
|
331
|
+
*
|
|
332
|
+
* If the target model doesn't exist, it's created as an instance of the foreign type.
|
|
333
|
+
* Bidirectional sync is automatic.
|
|
334
|
+
*
|
|
335
|
+
* @param modelPath - The model instance path (e.g., "tolkien")
|
|
336
|
+
* @param submodelPath - The relationship submodel (e.g., "books")
|
|
337
|
+
* @param targetPath - The target model to attach (e.g., "lord_of_the_rings")
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* ```typescript
|
|
341
|
+
* // Attach a book to an author (many side)
|
|
342
|
+
* await env.attach('tolkien', 'books', 'lord_of_the_rings');
|
|
343
|
+
* // This also automatically sets lord_of_the_rings:author -> tolkien
|
|
344
|
+
* ```
|
|
345
|
+
*/
|
|
346
|
+
attach(modelPath: string, submodelPath: string, targetPath: string): Promise<void>;
|
|
347
|
+
/**
|
|
348
|
+
* Detach a target model from a relationship submodel.
|
|
349
|
+
*
|
|
350
|
+
* Handles bidirectional cleanup automatically.
|
|
351
|
+
*
|
|
352
|
+
* @param modelPath - The model instance path
|
|
353
|
+
* @param submodelPath - The relationship submodel
|
|
354
|
+
* @param targetPath - The target to detach (optional for "one" side; omit on "many" side to detach all)
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```typescript
|
|
358
|
+
* // Detach a specific book
|
|
359
|
+
* await env.detach('tolkien', 'books', 'lord_of_the_rings');
|
|
360
|
+
*
|
|
361
|
+
* // Detach all books
|
|
362
|
+
* await env.detach('tolkien', 'books');
|
|
363
|
+
* ```
|
|
364
|
+
*/
|
|
365
|
+
detach(modelPath: string, submodelPath: string, targetPath?: string): Promise<void>;
|
|
366
|
+
/**
|
|
367
|
+
* List all related models through a relationship submodel.
|
|
368
|
+
*
|
|
369
|
+
* @param modelPath - The model instance path
|
|
370
|
+
* @param submodelPath - The relationship submodel
|
|
371
|
+
* @returns Array of related model references
|
|
372
|
+
*
|
|
373
|
+
* @example
|
|
374
|
+
* ```typescript
|
|
375
|
+
* const books = await env.listRelated('tolkien', 'books');
|
|
376
|
+
* console.log(books); // [{ path: "lord_of_the_rings", label: "Lord of the Rings" }, ...]
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
listRelated(modelPath: string, submodelPath: string): Promise<ModelRef[]>;
|
|
380
|
+
/**
|
|
381
|
+
* Apply a manifest to the current environment's graph.
|
|
382
|
+
*
|
|
383
|
+
* Translates each manifest operation into GraphQL mutations and executes them
|
|
384
|
+
* in order. This is the core mechanism for creating classes, fields, and
|
|
385
|
+
* relationships from a declarative manifest.
|
|
386
|
+
*
|
|
387
|
+
* @param manifest - The manifest content to apply
|
|
388
|
+
* @returns Summary of applied operations
|
|
389
|
+
*
|
|
390
|
+
* @example
|
|
391
|
+
* ```typescript
|
|
392
|
+
* await environment.applyManifest({
|
|
393
|
+
* schemaVersion: 2,
|
|
394
|
+
* name: 'my-app',
|
|
395
|
+
* volumes: [{
|
|
396
|
+
* name: 'schema',
|
|
397
|
+
* scope: 'sandbox',
|
|
398
|
+
* operations: [
|
|
399
|
+
* { create: 'author', extends: 'class', has: { name: { type: 'string' } } },
|
|
400
|
+
* { create: 'book', extends: 'class', has: { title: { type: 'string' } } },
|
|
401
|
+
* { defineRelationship: {
|
|
402
|
+
* left: 'author', right: 'book',
|
|
403
|
+
* leftSubmodel: 'books', rightSubmodel: 'author',
|
|
404
|
+
* leftIsMany: true, rightIsMany: false,
|
|
405
|
+
* }},
|
|
406
|
+
* ],
|
|
407
|
+
* }],
|
|
408
|
+
* });
|
|
409
|
+
* ```
|
|
410
|
+
*/
|
|
411
|
+
applyManifest(manifest: ManifestContent): Promise<{
|
|
412
|
+
applied: number;
|
|
413
|
+
errors: string[];
|
|
414
|
+
}>;
|
|
415
|
+
/**
|
|
416
|
+
* Resolve an alias reference like "@std/class" → "class"
|
|
417
|
+
* Strips the alias prefix, returning the bare model path.
|
|
418
|
+
*/
|
|
419
|
+
private _resolveAlias;
|
|
420
|
+
/**
|
|
421
|
+
* Apply a single manifest operation via GraphQL
|
|
422
|
+
*/
|
|
423
|
+
private _applyOperation;
|
|
424
|
+
/**
|
|
425
|
+
* Apply field definitions (has) to a model via GraphQL
|
|
426
|
+
*/
|
|
427
|
+
private _applyFields;
|
|
428
|
+
/**
|
|
429
|
+
* Create or update an instance of a class in the graph.
|
|
430
|
+
*
|
|
431
|
+
* Uses `instantiate` under the hood, which has find-or-create semantics:
|
|
432
|
+
* if an instance with the given `id` already exists for the class it is
|
|
433
|
+
* returned; otherwise a new instance is created. Fields are then set
|
|
434
|
+
* (overwriting previous values) and relationships are attached.
|
|
435
|
+
*
|
|
436
|
+
* The graph path is derived as `{className}_{id}` to ensure uniqueness
|
|
437
|
+
* across classes (two objects of different classes may share the same
|
|
438
|
+
* real-world ID). Relationship targets are also resolved automatically
|
|
439
|
+
* using the foreign class from the relationship definition.
|
|
440
|
+
*
|
|
441
|
+
* @param options - The object specification
|
|
442
|
+
* @returns The graph path, real-world ID, and creation status
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
* ```typescript
|
|
446
|
+
* // Create an author with fields
|
|
447
|
+
* const result = await env.recordObject({
|
|
448
|
+
* className: 'author',
|
|
449
|
+
* id: 'tolkien',
|
|
450
|
+
* label: 'J.R.R. Tolkien',
|
|
451
|
+
* fields: { name: 'J.R.R. Tolkien', birth_year: 1892 },
|
|
452
|
+
* relationships: { books: ['lotr', 'silmarillion'] },
|
|
453
|
+
* });
|
|
454
|
+
* // result.path → 'author_tolkien' (internal graph path)
|
|
455
|
+
* // result.id → 'tolkien' (real-world ID)
|
|
456
|
+
* // result.created → true
|
|
457
|
+
* ```
|
|
458
|
+
*/
|
|
459
|
+
recordObject(options: RecordObjectOptions): Promise<RecordObjectResult>;
|
|
460
|
+
/**
|
|
461
|
+
* Convenience method: publish tools and get back wrapped result.
|
|
462
|
+
* This is the main entry point for setting up tools.
|
|
463
|
+
*
|
|
464
|
+
* @example
|
|
465
|
+
* ```typescript
|
|
466
|
+
* const tools = [
|
|
467
|
+
* {
|
|
468
|
+
* name: 'get_weather',
|
|
469
|
+
* description: 'Get weather for a city',
|
|
470
|
+
* inputSchema: { type: 'object', properties: { city: { type: 'string' } } },
|
|
471
|
+
* handler: async ({ city }) => ({ temp: 22 }),
|
|
472
|
+
* },
|
|
473
|
+
* ];
|
|
474
|
+
*
|
|
475
|
+
* const { domainRevision } = await environment.publishTools(tools);
|
|
476
|
+
*
|
|
477
|
+
* // Now submit jobs that use those tools
|
|
478
|
+
* const job = await environment.submitJob(`
|
|
479
|
+
* import { Author } from './sandbox-tools';
|
|
480
|
+
* const weather = await Author.get_weather({ city: 'Paris' });
|
|
481
|
+
* return weather;
|
|
482
|
+
* `);
|
|
483
|
+
*
|
|
484
|
+
* const result = await job.result;
|
|
485
|
+
* ```
|
|
486
|
+
*/
|
|
487
|
+
publishTools(tools: ToolWithHandler[], revision?: string): Promise<PublishToolsResult>;
|
|
488
|
+
}
|
|
489
|
+
declare class Granular {
|
|
490
|
+
private apiKey;
|
|
491
|
+
private apiUrl;
|
|
492
|
+
private httpUrl;
|
|
493
|
+
/**
|
|
494
|
+
* Create a new Granular client
|
|
495
|
+
* @param options - Client configuration
|
|
496
|
+
*/
|
|
497
|
+
constructor(options: GranularOptions);
|
|
498
|
+
/**
|
|
499
|
+
* Records/upserts a user and prepares them for sandbox connections
|
|
500
|
+
*
|
|
501
|
+
* @param options - User options
|
|
502
|
+
* @returns The user object to pass to connect()
|
|
503
|
+
*
|
|
504
|
+
* @example
|
|
505
|
+
* ```typescript
|
|
506
|
+
* const user = await granular.recordUser({
|
|
507
|
+
* userId: 'user_123',
|
|
508
|
+
* name: 'John Doe',
|
|
509
|
+
* permissions: ['agent'],
|
|
510
|
+
* });
|
|
511
|
+
* ```
|
|
512
|
+
*/
|
|
513
|
+
recordUser(options: RecordUserOptions): Promise<User>;
|
|
514
|
+
/**
|
|
515
|
+
* Connect to a sandbox and establish a real-time environment session.
|
|
516
|
+
*
|
|
517
|
+
* After connecting, use `environment.publishTools()` to register tools,
|
|
518
|
+
* then `environment.submitJob()` to execute code that uses those tools.
|
|
519
|
+
*
|
|
520
|
+
* @param options - Connection options
|
|
521
|
+
* @returns An active environment session
|
|
522
|
+
*
|
|
523
|
+
* @example
|
|
524
|
+
* ```typescript
|
|
525
|
+
* const user = await granular.recordUser({
|
|
526
|
+
* userId: 'user_123',
|
|
527
|
+
* permissions: ['agent'],
|
|
528
|
+
* });
|
|
529
|
+
*
|
|
530
|
+
* const environment = await granular.connect({
|
|
531
|
+
* sandbox: 'my-sandbox',
|
|
532
|
+
* user,
|
|
533
|
+
* });
|
|
534
|
+
*
|
|
535
|
+
* // Publish tools
|
|
536
|
+
* await environment.publishTools([
|
|
537
|
+
* { name: 'greet', description: 'Say hello', inputSchema: {}, handler: async () => 'Hello!' },
|
|
538
|
+
* ]);
|
|
539
|
+
*
|
|
540
|
+
* // Submit job
|
|
541
|
+
* const job = await environment.submitJob(`
|
|
542
|
+
* import { tools } from './sandbox-tools';
|
|
543
|
+
* return await tools.greet({});
|
|
544
|
+
* `);
|
|
545
|
+
*
|
|
546
|
+
* console.log(await job.result); // 'Hello!'
|
|
547
|
+
* ```
|
|
548
|
+
*/
|
|
549
|
+
connect(options: ConnectOptions): Promise<Environment>;
|
|
550
|
+
/**
|
|
551
|
+
* Find a sandbox by name or create it if it doesn't exist
|
|
552
|
+
*/
|
|
553
|
+
private findOrCreateSandbox;
|
|
554
|
+
/**
|
|
555
|
+
* Ensure a permission profile exists for a sandbox, creating it if needed.
|
|
556
|
+
* If profileName matches an existing profile name, returns its ID.
|
|
557
|
+
* Otherwise, creates a new profile with default allow-all rules.
|
|
558
|
+
*/
|
|
559
|
+
private ensurePermissionProfile;
|
|
560
|
+
/**
|
|
561
|
+
* Ensure an assignment exists for a subject in a sandbox with a permission profile
|
|
562
|
+
*/
|
|
563
|
+
private ensureAssignment;
|
|
564
|
+
/**
|
|
565
|
+
* Sandbox management API
|
|
566
|
+
*/
|
|
567
|
+
get sandboxes(): {
|
|
568
|
+
list: () => Promise<SandboxListResponse>;
|
|
569
|
+
get: (id: string) => Promise<Sandbox>;
|
|
570
|
+
create: (data: CreateSandboxData) => Promise<Sandbox>;
|
|
571
|
+
update: (id: string, data: Partial<CreateSandboxData>) => Promise<Sandbox>;
|
|
572
|
+
delete: (id: string) => Promise<DeleteResponse>;
|
|
573
|
+
};
|
|
574
|
+
/**
|
|
575
|
+
* Permission Profile management for sandboxes
|
|
576
|
+
*/
|
|
577
|
+
get permissionProfiles(): {
|
|
578
|
+
list: (sandboxId: string) => Promise<PermissionProfile[]>;
|
|
579
|
+
get: (sandboxId: string, profileId: string) => Promise<PermissionProfile>;
|
|
580
|
+
create: (sandboxId: string, data: CreatePermissionProfileData) => Promise<PermissionProfile>;
|
|
581
|
+
delete: (sandboxId: string, profileId: string) => Promise<DeleteResponse>;
|
|
582
|
+
};
|
|
583
|
+
/**
|
|
584
|
+
* Environment management
|
|
585
|
+
*/
|
|
586
|
+
get environments(): {
|
|
587
|
+
list: (sandboxId: string) => Promise<EnvironmentData[]>;
|
|
588
|
+
get: (environmentId: string) => Promise<EnvironmentData>;
|
|
589
|
+
create: (sandboxId: string, data: CreateEnvironmentData) => Promise<EnvironmentData>;
|
|
590
|
+
delete: (environmentId: string) => Promise<DeleteResponse>;
|
|
591
|
+
};
|
|
592
|
+
/**
|
|
593
|
+
* Subject management
|
|
594
|
+
*/
|
|
595
|
+
get subjects(): {
|
|
596
|
+
get: (subjectId: string) => Promise<Subject>;
|
|
597
|
+
listAssignments: (subjectId: string) => Promise<AssignmentListResponse>;
|
|
598
|
+
};
|
|
599
|
+
/**
|
|
600
|
+
* @deprecated Use recordUser() instead
|
|
601
|
+
*/
|
|
602
|
+
get users(): {
|
|
603
|
+
create: (data: {
|
|
604
|
+
id: string;
|
|
605
|
+
name?: string;
|
|
606
|
+
email?: string;
|
|
607
|
+
}) => Promise<Subject>;
|
|
608
|
+
get: (id: string) => Promise<Subject>;
|
|
609
|
+
};
|
|
610
|
+
/**
|
|
611
|
+
* Make an authenticated API request
|
|
612
|
+
*/
|
|
613
|
+
private request;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
export { AssignmentListResponse, ConnectOptions, CreateEnvironmentData, CreatePermissionProfileData, CreateSandboxData, DefineRelationshipOptions, DeleteResponse, DomainState, Environment, EnvironmentData, Granular, GranularOptions, GraphQLResult, InstanceToolHandler, Job, ManifestContent, ModelRef, PermissionProfile, PublishToolsResult, RecordObjectOptions, RecordObjectResult, RecordUserOptions, RelationshipInfo, Sandbox, SandboxListResponse, Session, Subject, ToolHandler, ToolWithHandler, User, WSClient, WSClientOptions };
|