@vaultgraph/sdk 0.1.6 → 0.1.8

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 CHANGED
@@ -122,6 +122,56 @@ const { receipt, signature } = createSignedReceipt({
122
122
  });
123
123
  ```
124
124
 
125
+ ### Manage agents via the API (server-only)
126
+
127
+ ```ts
128
+ import { createAgentsClient } from "@vaultgraph/sdk";
129
+
130
+ const agents = createAgentsClient({
131
+ apiKey: process.env.VAULTGRAPH_VENDOR_API_KEY!,
132
+ });
133
+
134
+ const created = await agents.create({
135
+ name: "Support Bot",
136
+ description: "Handles tier-1 support workflows.",
137
+ });
138
+
139
+ const list = await agents.list();
140
+ const detail = await agents.get(created.id);
141
+
142
+ const updated = await agents.update(created.id, {
143
+ name: "Support Bot v2",
144
+ description: "Now with escalation scoring.",
145
+ });
146
+
147
+ await agents.delete(updated.id);
148
+ ```
149
+
150
+ ### Manage consumers via the API (server-only)
151
+
152
+ ```ts
153
+ import { createConsumersClient } from "@vaultgraph/sdk";
154
+
155
+ const consumers = createConsumersClient({
156
+ apiKey: process.env.VAULTGRAPH_VENDOR_API_KEY!,
157
+ });
158
+
159
+ const created = await consumers.create({
160
+ name: "Acme Holdings",
161
+ description: "Primary customer record.",
162
+ });
163
+
164
+ const list = await consumers.list();
165
+ const detail = await consumers.get(created.id);
166
+
167
+ const updated = await consumers.update(created.id, {
168
+ name: "Acme Holdings v2",
169
+ description: "Updated customer record.",
170
+ });
171
+
172
+ await consumers.delete(updated.id);
173
+ ```
174
+
125
175
  ## API surface
126
176
 
127
177
  - `hashContext(value, options?)` → sha256 hash of canonical JSON/bytes
@@ -132,9 +182,10 @@ const { receipt, signature } = createSignedReceipt({
132
182
  - `createSignedReceipt(options)` → `{ receipt, signature }`
133
183
  - `submitSignedReceipt(options)` → creates, signs, and submits; defaults `apiUrl` to portal base
134
184
  - `submitReceipt(options)` → POSTs to `/api/receipts` (requires `apiKey`)
135
- - `submitReceipt(options)` → POSTs to `/api/receipts` (requires `apiKey`)
185
+ - `createAgentsClient(options)` → CRUD helper for `/api/agents`
186
+ - `createConsumersClient(options)` → CRUD helper for `/api/consumers`
136
187
  - `generateKeyPair()` → returns PEM-encoded Ed25519 keypair
137
- - Types: `CreateReceiptInput`, `JobReceipt`, `JobReceiptV0`, `JobResolution`, `ReceiptVersion`, `SubmitReceiptOptions`, `SubmitReceiptResponse`
188
+ - Types: `CreateReceiptInput`, `JobReceipt`, `JobReceiptV0`, `JobResolution`, `ReceiptVersion`, `SubmitReceiptOptions`, `SubmitReceiptResponse`, `AgentRecord`, `AgentCreateInput`, `AgentUpdateInput`, `AgentsClientOptions`, `AgentsClient`, `ConsumerRecord`, `ConsumerCreateInput`, `ConsumerUpdateInput`, `ConsumersClientOptions`, `ConsumersClient`
138
189
 
139
190
  ## Notes
140
191
 
package/dist/index.d.ts CHANGED
@@ -1,18 +1,133 @@
1
- import { KeyLike, BinaryToTextEncoding } from 'crypto';
2
1
  import { CreateReceiptInput, JobReceipt } from '@repo/lib/job-receipt';
3
2
  export { CreateReceiptInput, JOB_RESOLUTIONS, JobReceipt, JobReceiptV0, JobResolution, ReceiptVersion, canonicalJSONStringify, createReceipt, hashContext, jobReceiptV0Schema, serializeReceipt, signReceipt, verifyReceipt } from '@repo/lib/job-receipt';
4
3
  import { SubmitReceiptResponse } from '@repo/lib/submit-receipt';
5
4
  export { SubmitReceiptOptions, SubmitReceiptResponse, submitReceipt } from '@repo/lib/submit-receipt';
5
+ import { KeyLike, BinaryToTextEncoding } from 'crypto';
6
+
7
+ /**
8
+ * Agent record returned by the API.
9
+ */
10
+ interface AgentRecord {
11
+ id: string;
12
+ name: string;
13
+ description: string | null;
14
+ created_at: string;
15
+ updated_at: string;
16
+ }
17
+ /**
18
+ * Payload for creating agents.
19
+ */
20
+ interface AgentCreateInput {
21
+ name: string;
22
+ description?: string | null;
23
+ }
24
+ /**
25
+ * Payload for updating agents.
26
+ */
27
+ interface AgentUpdateInput {
28
+ name: string;
29
+ description?: string | null;
30
+ }
31
+ /**
32
+ * Configuration for `createAgentsClient`.
33
+ */
34
+ interface AgentsClientOptions {
35
+ apiKey: string;
36
+ /** API base URL; defaults to the portal URL (app.vaultgraph.com in prod). */
37
+ apiUrl?: string;
38
+ fetchImpl?: typeof fetch;
39
+ }
40
+ /**
41
+ * Client interface for the agent API.
42
+ */
43
+ interface AgentsClient {
44
+ list: () => Promise<AgentRecord[]>;
45
+ get: (id: string) => Promise<AgentRecord>;
46
+ create: (input: AgentCreateInput) => Promise<AgentRecord>;
47
+ update: (id: string, input: AgentUpdateInput) => Promise<AgentRecord>;
48
+ delete: (id: string) => Promise<{
49
+ id: string;
50
+ }>;
51
+ }
52
+
53
+ /**
54
+ * Creates a minimal API client for managing agents.
55
+ */
56
+ declare function createAgentsClient(options: AgentsClientOptions): AgentsClient;
57
+
58
+ /**
59
+ * Consumer record returned by the API.
60
+ */
61
+ interface ConsumerRecord {
62
+ id: string;
63
+ name: string;
64
+ description: string | null;
65
+ linked_consumer_org_id: string | null;
66
+ linked_at: string | null;
67
+ created_at: string;
68
+ updated_at: string;
69
+ }
70
+ /**
71
+ * Payload for creating consumers.
72
+ */
73
+ interface ConsumerCreateInput {
74
+ name: string;
75
+ description?: string | null;
76
+ }
77
+ /**
78
+ * Payload for updating consumers.
79
+ */
80
+ interface ConsumerUpdateInput {
81
+ name: string;
82
+ description?: string | null;
83
+ }
84
+ /**
85
+ * Configuration for `createConsumersClient`.
86
+ */
87
+ interface ConsumersClientOptions {
88
+ apiKey: string;
89
+ /** API base URL; defaults to the portal URL (app.vaultgraph.com in prod). */
90
+ apiUrl?: string;
91
+ fetchImpl?: typeof fetch;
92
+ }
93
+ /**
94
+ * Client interface for the consumer API.
95
+ */
96
+ interface ConsumersClient {
97
+ list: () => Promise<ConsumerRecord[]>;
98
+ get: (id: string) => Promise<ConsumerRecord>;
99
+ create: (input: ConsumerCreateInput) => Promise<ConsumerRecord>;
100
+ update: (id: string, input: ConsumerUpdateInput) => Promise<ConsumerRecord>;
101
+ delete: (id: string) => Promise<{
102
+ id: string;
103
+ }>;
104
+ }
6
105
 
106
+ /**
107
+ * Creates a minimal API client for managing consumers.
108
+ */
109
+ declare function createConsumersClient(options: ConsumersClientOptions): ConsumersClient;
110
+
111
+ /**
112
+ * Input for `createSignedReceipt`.
113
+ */
7
114
  interface CreateSignedReceiptOptions extends CreateReceiptInput {
115
+ /** PEM-encoded private key used to sign the receipt. */
8
116
  privateKey: KeyLike;
117
+ /** Optional signing algorithm; defaults to Ed25519 when null. */
9
118
  algorithm?: string | null;
119
+ /** Encoding for the resulting signature. */
10
120
  encoding?: BinaryToTextEncoding;
11
121
  }
122
+ /**
123
+ * Input for `submitSignedReceipt`.
124
+ */
12
125
  interface SubmitSignedReceiptOptions extends CreateSignedReceiptOptions {
13
126
  /** API base URL; defaults to the portal URL (app.vaultgraph.com in prod). */
14
127
  apiUrl?: string;
128
+ /** Vendor API key for authentication. */
15
129
  apiKey: string;
130
+ /** Public key matching the signing private key. */
16
131
  publicKey: KeyLike;
17
132
  /** Optional fetch implementation for custom transports or tests. */
18
133
  fetchImpl?: typeof fetch;
@@ -40,4 +155,4 @@ declare function generateKeyPair(): {
40
155
  publicKey: string;
41
156
  };
42
157
 
43
- export { type CreateSignedReceiptOptions, type SubmitSignedReceiptOptions, createSignedReceipt, generateKeyPair, submitSignedReceipt };
158
+ export { type AgentCreateInput, type AgentRecord, type AgentUpdateInput, type AgentsClient, type AgentsClientOptions, type ConsumerCreateInput, type ConsumerRecord, type ConsumerUpdateInput, type ConsumersClient, type ConsumersClientOptions, type CreateSignedReceiptOptions, type SubmitSignedReceiptOptions, createAgentsClient, createConsumersClient, createSignedReceipt, generateKeyPair, submitSignedReceipt };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createHash, sign, verify, createPrivateKey, createPublicKey, generateKeyPairSync } from 'crypto';
2
2
 
3
- // src/index.ts
3
+ // ../lib/src/job-receipt.ts
4
4
  var JOB_RESOLUTIONS = ["resolved", "partial", "failed"];
5
5
  var VALID_JOB_RESOLUTIONS = JOB_RESOLUTIONS;
6
6
  var jobReceiptV0Schema = {
@@ -217,7 +217,232 @@ function getPortalURL() {
217
217
  return process.env.NEXT_PUBLIC_PORTAL_URL || process.env.NODE_ENV === "development" && "http://localhost:3001" || "https://app.vaultgraph.com";
218
218
  }
219
219
 
220
- // src/index.ts
220
+ // src/shared/api.ts
221
+ function assertNonEmpty(value, name) {
222
+ if (!value || !value.trim()) {
223
+ throw new Error(`${name} is required`);
224
+ }
225
+ }
226
+ function extractApiError(payload, fallback) {
227
+ if (!payload || typeof payload !== "object") {
228
+ return fallback || "Request failed";
229
+ }
230
+ const { detail, error } = payload;
231
+ return detail || error || fallback || "Request failed";
232
+ }
233
+ async function requestJson(options) {
234
+ const { apiUrl, apiKey, path, method, body, fetchImpl, headers } = options;
235
+ assertNonEmpty(apiUrl, "apiUrl");
236
+ assertNonEmpty(apiKey, "apiKey");
237
+ assertNonEmpty(path, "path");
238
+ const url = new URL(path, apiUrl).toString();
239
+ const fetcher = fetchImpl ?? fetch;
240
+ const res = await fetcher(url, {
241
+ method,
242
+ headers: {
243
+ "content-type": "application/json",
244
+ "x-api-key": apiKey,
245
+ ...headers ?? {}
246
+ },
247
+ body: body === void 0 ? void 0 : JSON.stringify(body)
248
+ });
249
+ const payload = await safeParseJson2(res);
250
+ if (!res.ok) {
251
+ throw new Error(extractApiError(payload, res.statusText));
252
+ }
253
+ return payload;
254
+ }
255
+ async function safeParseJson2(response) {
256
+ try {
257
+ return await response.json();
258
+ } catch {
259
+ return null;
260
+ }
261
+ }
262
+
263
+ // src/shared/records.ts
264
+ function extractDataArray(payload, label) {
265
+ if (!payload || typeof payload !== "object") {
266
+ throw new Error(`Invalid ${label} response payload`);
267
+ }
268
+ const data = payload.data;
269
+ if (!Array.isArray(data)) {
270
+ throw new Error(`Invalid ${label} response data`);
271
+ }
272
+ return data;
273
+ }
274
+ function extractDataRecord(payload, label) {
275
+ if (!payload || typeof payload !== "object") {
276
+ throw new Error(`Invalid ${label} response payload`);
277
+ }
278
+ const data = payload.data;
279
+ if (!data || typeof data !== "object") {
280
+ throw new Error(`Invalid ${label} response data`);
281
+ }
282
+ return data;
283
+ }
284
+ function extractDeleteResponse(payload) {
285
+ if (!payload || typeof payload !== "object") {
286
+ throw new Error("Invalid delete response payload");
287
+ }
288
+ const id = payload.id;
289
+ if (!id) {
290
+ throw new Error("Invalid delete response data");
291
+ }
292
+ return { id };
293
+ }
294
+
295
+ // src/agents/client.ts
296
+ function createAgentsClient(options) {
297
+ const { apiKey, apiUrl, fetchImpl } = options;
298
+ const targetApiUrl = apiUrl ?? getPortalURL();
299
+ assertNonEmpty(apiKey, "apiKey");
300
+ assertNonEmpty(targetApiUrl, "apiUrl");
301
+ return {
302
+ list: async () => {
303
+ const payload = await requestJson({
304
+ apiUrl: targetApiUrl,
305
+ apiKey,
306
+ path: "/api/agents",
307
+ method: "GET",
308
+ fetchImpl
309
+ });
310
+ return extractDataArray(payload, "agents");
311
+ },
312
+ get: async (id) => {
313
+ assertNonEmpty(id, "id");
314
+ const encodedId = encodeURIComponent(id);
315
+ const payload = await requestJson({
316
+ apiUrl: targetApiUrl,
317
+ apiKey,
318
+ path: `/api/agents/${encodedId}`,
319
+ method: "GET",
320
+ fetchImpl
321
+ });
322
+ return extractDataRecord(payload, "agent");
323
+ },
324
+ create: async (input) => {
325
+ assertNonEmpty(input.name, "name");
326
+ const payload = await requestJson({
327
+ apiUrl: targetApiUrl,
328
+ apiKey,
329
+ path: "/api/agents",
330
+ method: "POST",
331
+ body: {
332
+ name: input.name,
333
+ description: input.description ?? null
334
+ },
335
+ fetchImpl
336
+ });
337
+ return extractDataRecord(payload, "agent");
338
+ },
339
+ update: async (id, input) => {
340
+ assertNonEmpty(id, "id");
341
+ assertNonEmpty(input.name, "name");
342
+ const encodedId = encodeURIComponent(id);
343
+ const payload = await requestJson({
344
+ apiUrl: targetApiUrl,
345
+ apiKey,
346
+ path: `/api/agents/${encodedId}`,
347
+ method: "PUT",
348
+ body: {
349
+ name: input.name,
350
+ description: input.description ?? null
351
+ },
352
+ fetchImpl
353
+ });
354
+ return extractDataRecord(payload, "agent");
355
+ },
356
+ delete: async (id) => {
357
+ assertNonEmpty(id, "id");
358
+ const encodedId = encodeURIComponent(id);
359
+ const payload = await requestJson({
360
+ apiUrl: targetApiUrl,
361
+ apiKey,
362
+ path: `/api/agents/${encodedId}`,
363
+ method: "DELETE",
364
+ fetchImpl
365
+ });
366
+ return extractDeleteResponse(payload);
367
+ }
368
+ };
369
+ }
370
+
371
+ // src/consumers/client.ts
372
+ function createConsumersClient(options) {
373
+ const { apiKey, apiUrl, fetchImpl } = options;
374
+ const targetApiUrl = apiUrl ?? getPortalURL();
375
+ assertNonEmpty(apiKey, "apiKey");
376
+ assertNonEmpty(targetApiUrl, "apiUrl");
377
+ return {
378
+ list: async () => {
379
+ const payload = await requestJson({
380
+ apiUrl: targetApiUrl,
381
+ apiKey,
382
+ path: "/api/consumers",
383
+ method: "GET",
384
+ fetchImpl
385
+ });
386
+ return extractDataArray(payload, "consumers");
387
+ },
388
+ get: async (id) => {
389
+ assertNonEmpty(id, "id");
390
+ const encodedId = encodeURIComponent(id);
391
+ const payload = await requestJson({
392
+ apiUrl: targetApiUrl,
393
+ apiKey,
394
+ path: `/api/consumers/${encodedId}`,
395
+ method: "GET",
396
+ fetchImpl
397
+ });
398
+ return extractDataRecord(payload, "consumer");
399
+ },
400
+ create: async (input) => {
401
+ assertNonEmpty(input.name, "name");
402
+ const payload = await requestJson({
403
+ apiUrl: targetApiUrl,
404
+ apiKey,
405
+ path: "/api/consumers",
406
+ method: "POST",
407
+ body: {
408
+ name: input.name,
409
+ description: input.description ?? null
410
+ },
411
+ fetchImpl
412
+ });
413
+ return extractDataRecord(payload, "consumer");
414
+ },
415
+ update: async (id, input) => {
416
+ assertNonEmpty(id, "id");
417
+ assertNonEmpty(input.name, "name");
418
+ const encodedId = encodeURIComponent(id);
419
+ const payload = await requestJson({
420
+ apiUrl: targetApiUrl,
421
+ apiKey,
422
+ path: `/api/consumers/${encodedId}`,
423
+ method: "PUT",
424
+ body: {
425
+ name: input.name,
426
+ description: input.description ?? null
427
+ },
428
+ fetchImpl
429
+ });
430
+ return extractDataRecord(payload, "consumer");
431
+ },
432
+ delete: async (id) => {
433
+ assertNonEmpty(id, "id");
434
+ const encodedId = encodeURIComponent(id);
435
+ const payload = await requestJson({
436
+ apiUrl: targetApiUrl,
437
+ apiKey,
438
+ path: `/api/consumers/${encodedId}`,
439
+ method: "DELETE",
440
+ fetchImpl
441
+ });
442
+ return extractDeleteResponse(payload);
443
+ }
444
+ };
445
+ }
221
446
  function createSignedReceipt(options) {
222
447
  const { privateKey, algorithm, encoding, ...receiptInput } = options;
223
448
  const receipt = createReceipt(receiptInput);
@@ -251,4 +476,4 @@ function generateKeyPair() {
251
476
  return { privateKey, publicKey };
252
477
  }
253
478
 
254
- export { JOB_RESOLUTIONS, canonicalJSONStringify, createReceipt, createSignedReceipt, generateKeyPair, hashContext, jobReceiptV0Schema, serializeReceipt, signReceipt, submitReceipt, submitSignedReceipt, verifyReceipt };
479
+ export { JOB_RESOLUTIONS, canonicalJSONStringify, createAgentsClient, createConsumersClient, createReceipt, createSignedReceipt, generateKeyPair, hashContext, jobReceiptV0Schema, serializeReceipt, signReceipt, submitReceipt, submitSignedReceipt, verifyReceipt };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaultgraph/sdk",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",