@pstdio/pocketcoder-sdk 0.5.0 → 0.6.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +370 -190
  2. package/dist/index.js +497 -372
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,6 +1,220 @@
1
1
  import { z } from "zod";
2
2
  import { isIP } from "node:net";
3
- //#region ../contracts/src/pagination.ts
3
+ //#region ../contracts/src/attachments/attachment.ts
4
+ const ATTACHMENT_MAX_FILE_BYTES = 26214400;
5
+ const ATTACHMENT_CHUNK_BYTES = 524288;
6
+ const AttachmentMediaTypeSchema = z.string().regex(/^[\w.+-]+\/[\w.+-]+$/).max(255);
7
+ const AttachmentDescriptorSchema = z.object({
8
+ id: z.uuid(),
9
+ name: z.string().min(1).max(255),
10
+ path: z.string().min(1),
11
+ media_type: AttachmentMediaTypeSchema,
12
+ size_bytes: z.number().int().min(0).max(ATTACHMENT_MAX_FILE_BYTES),
13
+ sha256: z.string().regex(/^[0-9a-f]{64}$/)
14
+ });
15
+ z.looseObject({
16
+ type: z.literal("user"),
17
+ content: z.string(),
18
+ attachment_ids: z.array(z.uuid()).min(1).max(10).refine((ids) => new Set(ids).size === ids.length, "attachment_ids must be unique").optional()
19
+ });
20
+ const MANIFEST_OPEN = "<pocketcoder-attachments>";
21
+ const MANIFEST_CLOSE = "</pocketcoder-attachments>";
22
+ function splitAttachmentManifest(content) {
23
+ const open = content.lastIndexOf(MANIFEST_OPEN);
24
+ if (open < 0 || !content.trimEnd().endsWith(MANIFEST_CLOSE)) return {
25
+ text: content,
26
+ attachments: null
27
+ };
28
+ const close = content.lastIndexOf(MANIFEST_CLOSE);
29
+ const parsed = z.array(AttachmentDescriptorSchema).safeParse(safeJson(content.slice(open + 25, close)));
30
+ if (!parsed.success) return {
31
+ text: content,
32
+ attachments: null
33
+ };
34
+ return {
35
+ text: content.slice(0, open).trimEnd(),
36
+ attachments: parsed.data
37
+ };
38
+ }
39
+ function safeJson(value) {
40
+ try {
41
+ return JSON.parse(value);
42
+ } catch {
43
+ return;
44
+ }
45
+ }
46
+ const AttachmentStartPayload = z.object({
47
+ operation_id: z.uuid(),
48
+ attachment_id: z.uuid(),
49
+ name: z.string().min(1).max(255),
50
+ media_type: AttachmentMediaTypeSchema,
51
+ size_bytes: z.number().int().min(0).max(ATTACHMENT_MAX_FILE_BYTES)
52
+ });
53
+ const AttachmentChunkPayload = z.object({
54
+ operation_id: z.uuid(),
55
+ seq: z.number().int().nonnegative(),
56
+ content_b64: z.string().max(Math.ceil(ATTACHMENT_CHUNK_BYTES / 3) * 4 + 4)
57
+ });
58
+ const AttachmentFinishPayload = z.object({ operation_id: z.uuid() });
59
+ const AttachmentAbortPayload = z.object({
60
+ operation_id: z.uuid(),
61
+ reason: z.string().max(512)
62
+ });
63
+ const AttachmentResolvePayload = z.object({
64
+ operation_id: z.uuid(),
65
+ attachment_ids: z.array(z.uuid()).min(1).max(10)
66
+ });
67
+ const AttachmentAckPayload = z.object({
68
+ operation_id: z.uuid(),
69
+ seq: z.number().int().nonnegative(),
70
+ received_bytes: z.number().int().nonnegative()
71
+ });
72
+ const AttachmentResultPayload = z.object({
73
+ operation_id: z.uuid(),
74
+ status: z.enum([
75
+ "created",
76
+ "existing",
77
+ "conflict",
78
+ "failed"
79
+ ]),
80
+ descriptor: AttachmentDescriptorSchema.optional(),
81
+ failure_code: z.enum([
82
+ "invalid",
83
+ "too_large",
84
+ "sequence",
85
+ "io",
86
+ "interrupted"
87
+ ]).optional(),
88
+ detail: z.string().max(512).optional()
89
+ });
90
+ const AttachmentResolvedPayload = z.object({
91
+ operation_id: z.uuid(),
92
+ descriptors: z.array(AttachmentDescriptorSchema).optional(),
93
+ missing_id: z.uuid().optional()
94
+ });
95
+ //#endregion
96
+ //#region ../contracts/src/common/scopes.ts
97
+ const SCOPES = [
98
+ "templates:read",
99
+ "workspaces:create",
100
+ "workspaces:read",
101
+ "workspaces:cancel",
102
+ "workspaces:purge",
103
+ "workspaces:recover",
104
+ "keys:read",
105
+ "keys:write",
106
+ "workspaces:preserve",
107
+ "workspaces:restore",
108
+ "checkpoints:read",
109
+ "checkpoints:delete",
110
+ "outputs:read",
111
+ "conversations:read",
112
+ "conversations:delete",
113
+ "services:relay",
114
+ "attachments:write",
115
+ "logs:read",
116
+ "network:read",
117
+ "terminal:attach",
118
+ "terminal:read",
119
+ "admin"
120
+ ];
121
+ z.strictObject({
122
+ request_id: z.string().min(1).max(128).regex(/^[A-Za-z0-9._:-]+$/),
123
+ scopes: z.array(z.enum(SCOPES)).min(1).max(SCOPES.length),
124
+ expires_at: z.iso.datetime()
125
+ });
126
+ const KeyResourceSchema = z.object({
127
+ id: z.uuid(),
128
+ principal_id: z.uuid(),
129
+ scopes: z.array(z.string()),
130
+ effective_scopes: z.array(z.string()),
131
+ managed_principal_ids: z.array(z.uuid()),
132
+ issuance_request_id: z.string().nullable(),
133
+ created_at: z.iso.datetime(),
134
+ expires_at: z.iso.datetime().nullable(),
135
+ revoked_at: z.iso.datetime().nullable(),
136
+ last_used_at: z.iso.datetime().nullable()
137
+ });
138
+ const KeyIssueResponseSchema = z.object({
139
+ key: KeyResourceSchema,
140
+ token: z.string().nullable()
141
+ });
142
+ const KeyListResponseSchema = z.object({
143
+ items: z.array(KeyResourceSchema),
144
+ next_cursor: z.uuid().nullable()
145
+ });
146
+ //#endregion
147
+ //#region ../contracts/src/common/duration.ts
148
+ const DURATION_RE = /^(\d+)(ms|s|m|h)$/;
149
+ function isDuration(value) {
150
+ return DURATION_RE.test(value);
151
+ }
152
+ //#endregion
153
+ //#region ../contracts/src/common/errors.ts
154
+ const ERROR_CODES = {
155
+ "auth.invalid_key": 401,
156
+ "auth.missing_scope": 403,
157
+ "auth.disabled_principal": 403,
158
+ "principal.not_found": 404,
159
+ "key.not_found": 404,
160
+ "validation.invalid": 400,
161
+ "idempotency.conflict": 409,
162
+ "capacity.queue_full": 429,
163
+ "capacity.waiters_full": 429,
164
+ "template.not_found": 404,
165
+ "template.version_not_found": 404,
166
+ "template.not_authorized": 403,
167
+ "workspace.not_found": 404,
168
+ "workspace.external_id_conflict": 409,
169
+ "workspace.not_ready": 409,
170
+ "workspace.terminal": 410,
171
+ "workspace.disconnected": 503,
172
+ "terminal.not_declared": 422,
173
+ "terminal.session_limit": 409,
174
+ "terminal.session_not_found": 404,
175
+ "terminal.session_closed": 409,
176
+ "terminal.protocol_unsupported": 426,
177
+ "workspace.persistence_not_enabled": 409,
178
+ "workspace.preserving": 409,
179
+ "checkpoint.not_found": 404,
180
+ "checkpoint.not_ready": 409,
181
+ "checkpoint.none_ready": 409,
182
+ "checkpoint.corrupt": 409,
183
+ "checkpoint.quota_exceeded": 413,
184
+ "checkpoint.in_use": 409,
185
+ "restore.template_not_authorized": 403,
186
+ "restore.image_unavailable": 409,
187
+ "restore.incompatible": 409,
188
+ "resume.unsupported": 409,
189
+ "conversation.expired": 410,
190
+ "conversation.deleted": 410,
191
+ "operation.conflict": 409,
192
+ "source.not_allowed": 422,
193
+ "source.invalid_revision": 422,
194
+ "secret.unavailable": 503,
195
+ "storage.capacity_exhausted": 507,
196
+ "relay.body_too_large": 413,
197
+ "relay.route_not_allowed": 422,
198
+ "relay.streaming_unsupported": 409,
199
+ "relay.deadline_exceeded": 504,
200
+ "relay.upstream_error": 502,
201
+ "attachment.invalid": 400,
202
+ "attachment.too_large": 413,
203
+ "attachment.not_found": 404,
204
+ "attachment.conflict": 409,
205
+ "attachment.unsupported": 409,
206
+ "attachment.interrupted": 503,
207
+ "internal.error": 500
208
+ };
209
+ const errorCodes = Object.keys(ERROR_CODES);
210
+ const ErrorEnvelopeSchema = z.object({ error: z.object({
211
+ code: z.enum(errorCodes),
212
+ message: z.string().min(1),
213
+ request_id: z.string().min(1),
214
+ details: z.record(z.string(), z.unknown()).optional()
215
+ }) });
216
+ //#endregion
217
+ //#region ../contracts/src/common/pagination.ts
4
218
  const CursorSchema = z.string().min(1).max(2048);
5
219
  function CursorPageSchema(item) {
6
220
  return z.object({
@@ -15,7 +229,7 @@ function CursorQuerySchema(maxLimit, defaultLimit) {
15
229
  });
16
230
  }
17
231
  //#endregion
18
- //#region ../contracts/src/conversation.ts
232
+ //#region ../contracts/src/conversations/conversation.ts
19
233
  const CONVERSATION_ROLES = [
20
234
  "user",
21
235
  "assistant",
@@ -43,13 +257,61 @@ const ConversationResumeOutcomeSchema = z.object({
43
257
  checkpoint_id: z.uuid()
44
258
  });
45
259
  //#endregion
46
- //#region ../contracts/src/duration.ts
47
- const DURATION_RE = /^(\d+)(ms|s|m|h)$/;
48
- function isDuration(value) {
49
- return DURATION_RE.test(value);
260
+ //#region ../contracts/src/network/network.ts
261
+ const DOMAIN_LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
262
+ function isDomain(value) {
263
+ const domain = value.startsWith("*.") ? value.slice(2) : value;
264
+ return domain.length <= 253 && !domain.endsWith(".") && isIP(domain) === 0 && domain.split(".").length >= 2 && domain.split(".").every((label) => DOMAIN_LABEL.test(label));
50
265
  }
266
+ const NetworkRuleSchema = z.object({
267
+ domain: z.string().refine(isDomain, "expected a lowercase ASCII domain or leading *. wildcard"),
268
+ ports: z.array(z.number().int().min(1).max(65535)).min(1).max(32).default([80, 443]),
269
+ allowPrivate: z.boolean().default(false)
270
+ }).superRefine((rule, ctx) => {
271
+ if (new Set(rule.ports).size !== rule.ports.length) ctx.addIssue({
272
+ code: "custom",
273
+ path: ["ports"],
274
+ message: "ports must be unique"
275
+ });
276
+ });
277
+ const UnrestrictedNetworkPolicySchema = z.object({ mode: z.literal("unrestricted") });
278
+ const RestrictedNetworkPolicySchema = z.object({
279
+ mode: z.literal("restricted"),
280
+ allow: z.array(NetworkRuleSchema).max(256).default([])
281
+ });
282
+ const NetworkPolicySchema = z.preprocess((value) => value ?? { mode: "unrestricted" }, z.discriminatedUnion("mode", [UnrestrictedNetworkPolicySchema, RestrictedNetworkPolicySchema]));
283
+ const NETWORK_STATES = [
284
+ "disabled",
285
+ "starting",
286
+ "ready",
287
+ "degraded"
288
+ ];
289
+ const NetworkEventInputSchema = z.object({
290
+ source_seq: z.number().int().positive(),
291
+ occurred_at: z.iso.datetime(),
292
+ decision: z.enum(["allow", "deny"]),
293
+ transport: z.enum(["http", "https"]),
294
+ host: z.string().min(1).max(253),
295
+ port: z.number().int().min(1).max(65535),
296
+ method: z.string().max(32).nullable().default(null),
297
+ path: z.string().max(2048).refine((path) => !path.includes("?") && !path.includes("#"), "path cannot contain query or fragment").nullable().default(null),
298
+ matched_rule: z.string().max(512).nullable().default(null),
299
+ reason: z.string().min(1).max(128)
300
+ });
301
+ z.object({
302
+ source_session_id: z.uuid(),
303
+ events: z.array(NetworkEventInputSchema).min(1).max(100)
304
+ });
305
+ const NetworkEventSchema = NetworkEventInputSchema.omit({ source_seq: true }).extend({
306
+ seq: z.number().int().positive(),
307
+ workspace_id: z.uuid(),
308
+ source_session_id: z.uuid(),
309
+ source_seq: z.number().int().positive()
310
+ });
311
+ CursorQuerySchema(200, 100);
312
+ const NetworkEventPageSchema = CursorPageSchema(NetworkEventSchema);
51
313
  //#endregion
52
- //#region ../contracts/src/persistence.ts
314
+ //#region ../contracts/src/persistence/persistence.ts
53
315
  const DurationValueSchema = z.string().refine(isDuration, { message: "expected a duration like 15s, 20m, or 2h" });
54
316
  const LAUNCH_MODES = ["create", "restore"];
55
317
  const CONVERSATION_RESTORE_CAPABILITIES = [
@@ -117,7 +379,8 @@ const OPERATION_KINDS = [
117
379
  "preserve",
118
380
  "restore",
119
381
  "verify",
120
- "delete"
382
+ "delete",
383
+ "purge"
121
384
  ];
122
385
  const OPERATION_STATES = [
123
386
  "pending",
@@ -194,61 +457,7 @@ z.object({
194
457
  file_count: z.number().int().nonnegative()
195
458
  });
196
459
  //#endregion
197
- //#region ../contracts/src/network.ts
198
- const DOMAIN_LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
199
- function isDomain(value) {
200
- const domain = value.startsWith("*.") ? value.slice(2) : value;
201
- return domain.length <= 253 && !domain.endsWith(".") && isIP(domain) === 0 && domain.split(".").length >= 2 && domain.split(".").every((label) => DOMAIN_LABEL.test(label));
202
- }
203
- const NetworkRuleSchema = z.object({
204
- domain: z.string().refine(isDomain, "expected a lowercase ASCII domain or leading *. wildcard"),
205
- ports: z.array(z.number().int().min(1).max(65535)).min(1).max(32).default([80, 443]),
206
- allowPrivate: z.boolean().default(false)
207
- }).superRefine((rule, ctx) => {
208
- if (new Set(rule.ports).size !== rule.ports.length) ctx.addIssue({
209
- code: "custom",
210
- path: ["ports"],
211
- message: "ports must be unique"
212
- });
213
- });
214
- const UnrestrictedNetworkPolicySchema = z.object({ mode: z.literal("unrestricted") });
215
- const RestrictedNetworkPolicySchema = z.object({
216
- mode: z.literal("restricted"),
217
- allow: z.array(NetworkRuleSchema).max(256).default([])
218
- });
219
- const NetworkPolicySchema = z.preprocess((value) => value ?? { mode: "unrestricted" }, z.discriminatedUnion("mode", [UnrestrictedNetworkPolicySchema, RestrictedNetworkPolicySchema]));
220
- const NETWORK_STATES = [
221
- "disabled",
222
- "starting",
223
- "ready",
224
- "degraded"
225
- ];
226
- const NetworkEventInputSchema = z.object({
227
- source_seq: z.number().int().positive(),
228
- occurred_at: z.iso.datetime(),
229
- decision: z.enum(["allow", "deny"]),
230
- transport: z.enum(["http", "https"]),
231
- host: z.string().min(1).max(253),
232
- port: z.number().int().min(1).max(65535),
233
- method: z.string().max(32).nullable().default(null),
234
- path: z.string().max(2048).refine((path) => !path.includes("?") && !path.includes("#"), "path cannot contain query or fragment").nullable().default(null),
235
- matched_rule: z.string().max(512).nullable().default(null),
236
- reason: z.string().min(1).max(128)
237
- });
238
- z.object({
239
- source_session_id: z.uuid(),
240
- events: z.array(NetworkEventInputSchema).min(1).max(100)
241
- });
242
- const NetworkEventSchema = NetworkEventInputSchema.omit({ source_seq: true }).extend({
243
- seq: z.number().int().positive(),
244
- workspace_id: z.uuid(),
245
- source_session_id: z.uuid(),
246
- source_seq: z.number().int().positive()
247
- });
248
- CursorQuerySchema(200, 100);
249
- const NetworkEventPageSchema = CursorPageSchema(NetworkEventSchema);
250
- //#endregion
251
- //#region ../contracts/src/workspace.ts
460
+ //#region ../contracts/src/workspaces/workspace.ts
252
461
  const WORKSPACE_STATES = [
253
462
  "queued",
254
463
  "provisioning",
@@ -377,7 +586,7 @@ z.object({
377
586
  cursor: z.string().optional()
378
587
  });
379
588
  //#endregion
380
- //#region ../contracts/src/api.ts
589
+ //#region ../contracts/src/protocol/api.ts
381
590
  const TemplatePageSchema = CursorPageSchema(z.object({
382
591
  name: z.string(),
383
592
  version: z.string(),
@@ -438,161 +647,6 @@ const StoragePruneResultSchema = z.object({
438
647
  skipped: z.number().int().nonnegative(),
439
648
  transcripts_deleted: z.number().int().nonnegative()
440
649
  });
441
- //#endregion
442
- //#region ../contracts/src/attachment.ts
443
- const ATTACHMENT_MAX_FILE_BYTES = 26214400;
444
- const ATTACHMENT_CHUNK_BYTES = 524288;
445
- const AttachmentMediaTypeSchema = z.string().regex(/^[\w.+-]+\/[\w.+-]+$/).max(255);
446
- const AttachmentDescriptorSchema = z.object({
447
- id: z.uuid(),
448
- name: z.string().min(1).max(255),
449
- path: z.string().min(1),
450
- media_type: AttachmentMediaTypeSchema,
451
- size_bytes: z.number().int().min(0).max(ATTACHMENT_MAX_FILE_BYTES),
452
- sha256: z.string().regex(/^[0-9a-f]{64}$/)
453
- });
454
- z.looseObject({
455
- type: z.literal("user"),
456
- content: z.string(),
457
- attachment_ids: z.array(z.uuid()).min(1).max(10).refine((ids) => new Set(ids).size === ids.length, "attachment_ids must be unique").optional()
458
- });
459
- const MANIFEST_OPEN = "<pocketcoder-attachments>";
460
- const MANIFEST_CLOSE = "</pocketcoder-attachments>";
461
- function splitAttachmentManifest(content) {
462
- const open = content.lastIndexOf(MANIFEST_OPEN);
463
- if (open < 0 || !content.trimEnd().endsWith(MANIFEST_CLOSE)) return {
464
- text: content,
465
- attachments: null
466
- };
467
- const close = content.lastIndexOf(MANIFEST_CLOSE);
468
- const parsed = z.array(AttachmentDescriptorSchema).safeParse(safeJson(content.slice(open + 25, close)));
469
- if (!parsed.success) return {
470
- text: content,
471
- attachments: null
472
- };
473
- return {
474
- text: content.slice(0, open).trimEnd(),
475
- attachments: parsed.data
476
- };
477
- }
478
- function safeJson(value) {
479
- try {
480
- return JSON.parse(value);
481
- } catch {
482
- return;
483
- }
484
- }
485
- const AttachmentStartPayload = z.object({
486
- operation_id: z.uuid(),
487
- attachment_id: z.uuid(),
488
- name: z.string().min(1).max(255),
489
- media_type: AttachmentMediaTypeSchema,
490
- size_bytes: z.number().int().min(0).max(ATTACHMENT_MAX_FILE_BYTES)
491
- });
492
- const AttachmentChunkPayload = z.object({
493
- operation_id: z.uuid(),
494
- seq: z.number().int().nonnegative(),
495
- content_b64: z.string().max(Math.ceil(ATTACHMENT_CHUNK_BYTES / 3) * 4 + 4)
496
- });
497
- const AttachmentFinishPayload = z.object({ operation_id: z.uuid() });
498
- const AttachmentAbortPayload = z.object({
499
- operation_id: z.uuid(),
500
- reason: z.string().max(512)
501
- });
502
- const AttachmentResolvePayload = z.object({
503
- operation_id: z.uuid(),
504
- attachment_ids: z.array(z.uuid()).min(1).max(10)
505
- });
506
- const AttachmentAckPayload = z.object({
507
- operation_id: z.uuid(),
508
- seq: z.number().int().nonnegative(),
509
- received_bytes: z.number().int().nonnegative()
510
- });
511
- const AttachmentResultPayload = z.object({
512
- operation_id: z.uuid(),
513
- status: z.enum([
514
- "created",
515
- "existing",
516
- "conflict",
517
- "failed"
518
- ]),
519
- descriptor: AttachmentDescriptorSchema.optional(),
520
- failure_code: z.enum([
521
- "invalid",
522
- "too_large",
523
- "sequence",
524
- "io",
525
- "interrupted"
526
- ]).optional(),
527
- detail: z.string().max(512).optional()
528
- });
529
- const AttachmentResolvedPayload = z.object({
530
- operation_id: z.uuid(),
531
- descriptors: z.array(AttachmentDescriptorSchema).optional(),
532
- missing_id: z.uuid().optional()
533
- });
534
- //#endregion
535
- //#region ../contracts/src/errors.ts
536
- const ERROR_CODES = {
537
- "auth.invalid_key": 401,
538
- "auth.missing_scope": 403,
539
- "auth.disabled_principal": 403,
540
- "validation.invalid": 400,
541
- "idempotency.conflict": 409,
542
- "capacity.queue_full": 429,
543
- "capacity.waiters_full": 429,
544
- "template.not_found": 404,
545
- "template.version_not_found": 404,
546
- "template.not_authorized": 403,
547
- "workspace.not_found": 404,
548
- "workspace.external_id_conflict": 409,
549
- "workspace.not_ready": 409,
550
- "workspace.terminal": 410,
551
- "workspace.disconnected": 503,
552
- "terminal.not_declared": 422,
553
- "terminal.session_limit": 409,
554
- "terminal.session_not_found": 404,
555
- "terminal.session_closed": 409,
556
- "terminal.protocol_unsupported": 426,
557
- "workspace.persistence_not_enabled": 409,
558
- "workspace.preserving": 409,
559
- "checkpoint.not_found": 404,
560
- "checkpoint.not_ready": 409,
561
- "checkpoint.none_ready": 409,
562
- "checkpoint.corrupt": 409,
563
- "checkpoint.quota_exceeded": 413,
564
- "checkpoint.in_use": 409,
565
- "restore.template_not_authorized": 403,
566
- "restore.image_unavailable": 409,
567
- "restore.incompatible": 409,
568
- "resume.unsupported": 409,
569
- "conversation.expired": 410,
570
- "conversation.deleted": 410,
571
- "operation.conflict": 409,
572
- "source.not_allowed": 422,
573
- "source.invalid_revision": 422,
574
- "secret.unavailable": 503,
575
- "storage.capacity_exhausted": 507,
576
- "relay.body_too_large": 413,
577
- "relay.route_not_allowed": 422,
578
- "relay.streaming_unsupported": 409,
579
- "relay.deadline_exceeded": 504,
580
- "relay.upstream_error": 502,
581
- "attachment.invalid": 400,
582
- "attachment.too_large": 413,
583
- "attachment.not_found": 404,
584
- "attachment.conflict": 409,
585
- "attachment.unsupported": 409,
586
- "attachment.interrupted": 503,
587
- "internal.error": 500
588
- };
589
- const errorCodes = Object.keys(ERROR_CODES);
590
- const ErrorEnvelopeSchema = z.object({ error: z.object({
591
- code: z.enum(errorCodes),
592
- message: z.string().min(1),
593
- request_id: z.string().min(1),
594
- details: z.record(z.string(), z.unknown()).optional()
595
- }) });
596
650
  WORKSPACE_STATES.map((s) => `workspace.${s}`);
597
651
  z.object({
598
652
  id: z.uuid(),
@@ -624,7 +678,7 @@ z.object({
624
678
  })
625
679
  });
626
680
  //#endregion
627
- //#region ../contracts/src/logs.ts
681
+ //#region ../contracts/src/protocol/logs.ts
628
682
  const LogChunkSchema = z.object({
629
683
  seq: z.number().int().positive(),
630
684
  stream: z.string(),
@@ -634,47 +688,14 @@ const LogChunkSchema = z.object({
634
688
  CursorQuerySchema(1e3, 200);
635
689
  const LogPageSchema = CursorPageSchema(LogChunkSchema);
636
690
  //#endregion
637
- //#region ../contracts/src/protocol-stream.ts
638
- const ProxyStreamStartPayload = z.object({
639
- request_id: z.uuid(),
640
- status: z.number().int().min(100).max(599),
641
- headers: z.record(z.string(), z.string())
642
- });
643
- const ProxyStreamChunkPayload = z.object({
644
- request_id: z.uuid(),
645
- seq: z.number().int().nonnegative(),
646
- content_b64: z.string().max(87400)
647
- });
648
- const ProxyStreamEndPayload = z.object({
649
- request_id: z.uuid(),
650
- error_code: z.enum([
651
- "unreachable",
652
- "deadline",
653
- "too_large"
654
- ]).optional()
655
- });
656
- const ProxyStreamAckPayload = z.object({
657
- request_id: z.uuid(),
658
- seq: z.number().int().nonnegative()
659
- });
660
- const ProxyStreamCancelPayload = z.object({
661
- request_id: z.uuid(),
662
- reason: z.enum([
663
- "downstream_closed",
664
- "deadline",
665
- "too_large",
666
- "workspace_disconnected"
667
- ])
668
- });
669
- //#endregion
670
- //#region ../contracts/src/template-constants.ts
691
+ //#region ../contracts/src/templates/template-constants.ts
671
692
  function isAbsolutePath(value) {
672
693
  return value.startsWith("/") && ![...value].some((character) => character.codePointAt(0) === 0);
673
694
  }
674
695
  const SECRET_ENV_PATTERN = /(SECRET|TOKEN|PASSWORD|PASSWD|API_?KEY|PRIVATE_?KEY|CREDENTIAL)/i;
675
696
  const SECRET_REFERENCE_PREFIX = "secretRef:";
676
697
  //#endregion
677
- //#region ../contracts/src/template-schema.ts
698
+ //#region ../contracts/src/templates/template-schema.ts
678
699
  const NAME_RE = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
679
700
  const SEMVER_RE = /^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?$/;
680
701
  const IMAGE_DIGEST_RE = /^[^\s@]+@sha256:[0-9a-f]{64}$/;
@@ -864,7 +885,7 @@ const TemplateManifestBaseSchema = z.object({
864
885
  spec: TemplateSpecSchema
865
886
  });
866
887
  //#endregion
867
- //#region ../contracts/src/template-runtime.ts
888
+ //#region ../contracts/src/templates/template-runtime.ts
868
889
  const LEGACY_AGENTAPI_SERVICE = ServiceSchema.parse({
869
890
  baseUrl: "http://127.0.0.1:3284",
870
891
  routes: [
@@ -920,7 +941,7 @@ function templateServices(spec) {
920
941
  return isAgentApiNative(spec) ? { agent: AGENTAPI_SERVICE } : spec.services;
921
942
  }
922
943
  //#endregion
923
- //#region ../contracts/src/template-validation.ts
944
+ //#region ../contracts/src/templates/template-validation.ts
924
945
  function envSources(spec) {
925
946
  const sources = [[["spec", "env"], spec.env], [isAgentApiNative(spec) ? [
926
947
  "spec",
@@ -1259,12 +1280,14 @@ TemplateManifestBaseSchema.superRefine((manifest, ctx) => {
1259
1280
  validateTemplateSpec(manifest.spec, ctx);
1260
1281
  });
1261
1282
  //#endregion
1262
- //#region ../contracts/src/terminal.ts
1283
+ //#region ../contracts/src/terminals/terminal.ts
1263
1284
  const TERMINAL_CHUNK_BYTES = 32768;
1264
1285
  const TERMINAL_REPLAY_BUFFER_BYTES = 65536;
1265
1286
  function base64Schema(maxBytes) {
1266
1287
  return z.string().regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/).refine((value) => {
1267
- const padding = value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0;
1288
+ let padding = 0;
1289
+ if (value.endsWith("==")) padding = 2;
1290
+ else if (value.endsWith("=")) padding = 1;
1268
1291
  return value.length / 4 * 3 - padding <= maxBytes;
1269
1292
  }, `decoded payload must not exceed ${maxBytes} bytes`);
1270
1293
  }
@@ -1368,8 +1391,41 @@ const TerminalSessionSchema = z.object({
1368
1391
  bytes_in: z.number().int().nonnegative(),
1369
1392
  bytes_out: z.number().int().nonnegative()
1370
1393
  });
1371
- CursorQuerySchema(200, 50);
1372
- const TerminalSessionPageSchema = CursorPageSchema(TerminalSessionSchema);
1394
+ CursorQuerySchema(200, 50);
1395
+ const TerminalSessionPageSchema = CursorPageSchema(TerminalSessionSchema);
1396
+ //#endregion
1397
+ //#region ../contracts/src/protocol/protocol-stream.ts
1398
+ const ProxyStreamStartPayload = z.object({
1399
+ request_id: z.uuid(),
1400
+ status: z.number().int().min(100).max(599),
1401
+ headers: z.record(z.string(), z.string())
1402
+ });
1403
+ const ProxyStreamChunkPayload = z.object({
1404
+ request_id: z.uuid(),
1405
+ seq: z.number().int().nonnegative(),
1406
+ content_b64: z.string().max(87400)
1407
+ });
1408
+ const ProxyStreamEndPayload = z.object({
1409
+ request_id: z.uuid(),
1410
+ error_code: z.enum([
1411
+ "unreachable",
1412
+ "deadline",
1413
+ "too_large"
1414
+ ]).optional()
1415
+ });
1416
+ const ProxyStreamAckPayload = z.object({
1417
+ request_id: z.uuid(),
1418
+ seq: z.number().int().nonnegative()
1419
+ });
1420
+ const ProxyStreamCancelPayload = z.object({
1421
+ request_id: z.uuid(),
1422
+ reason: z.enum([
1423
+ "downstream_closed",
1424
+ "deadline",
1425
+ "too_large",
1426
+ "workspace_disconnected"
1427
+ ])
1428
+ });
1373
1429
  const ProviderInputSchema = z.object({
1374
1430
  workspace_id: z.uuid(),
1375
1431
  server_url: z.string(),
@@ -1779,7 +1835,7 @@ z.discriminatedUnion("type", [
1779
1835
  })
1780
1836
  ]);
1781
1837
  //#endregion
1782
- //#region src/admin.ts
1838
+ //#region src/resources/admin/admin.ts
1783
1839
  var AdministrationApi = class {
1784
1840
  transport;
1785
1841
  constructor(transport) {
@@ -1799,7 +1855,7 @@ var AdministrationApi = class {
1799
1855
  }
1800
1856
  };
1801
1857
  //#endregion
1802
- //#region src/errors.ts
1858
+ //#region src/transport/errors.ts
1803
1859
  z.enum(["client.non_json_response", "client.invalid_response"]);
1804
1860
  var PocketCoderError = class extends Error {
1805
1861
  code;
@@ -1856,7 +1912,7 @@ function responseError(response, body) {
1856
1912
  });
1857
1913
  }
1858
1914
  //#endregion
1859
- //#region src/attachments.ts
1915
+ //#region src/resources/attachments/attachments.ts
1860
1916
  const DEFAULT_READY_TIMEOUT_MS = 12e4;
1861
1917
  function contentDisposition(name) {
1862
1918
  const clean = name.replace(/[\r\n]/g, "");
@@ -1929,7 +1985,7 @@ var AgentApi = class {
1929
1985
  }
1930
1986
  };
1931
1987
  //#endregion
1932
- //#region src/common.ts
1988
+ //#region src/transport/common.ts
1933
1989
  function queryString(values) {
1934
1990
  const params = new URLSearchParams();
1935
1991
  for (const [key, value] of Object.entries(values)) if (value !== void 0) params.set(key, String(value));
@@ -1942,7 +1998,7 @@ function page(body) {
1942
1998
  };
1943
1999
  }
1944
2000
  //#endregion
1945
- //#region src/checkpoints.ts
2001
+ //#region src/resources/checkpoints/checkpoints.ts
1946
2002
  var CheckpointsApi = class {
1947
2003
  transport;
1948
2004
  constructor(transport) {
@@ -1990,7 +2046,7 @@ var OperationsApi = class {
1990
2046
  }
1991
2047
  };
1992
2048
  //#endregion
1993
- //#region src/conversations.ts
2049
+ //#region src/resources/conversations/conversations.ts
1994
2050
  var ConversationsApi = class {
1995
2051
  transport;
1996
2052
  constructor(transport) {
@@ -2004,7 +2060,7 @@ var ConversationsApi = class {
2004
2060
  }
2005
2061
  };
2006
2062
  //#endregion
2007
- //#region src/diagnostics.ts
2063
+ //#region src/resources/diagnostics/diagnostics.ts
2008
2064
  var WorkspaceCursorApi = class {
2009
2065
  transport;
2010
2066
  resource;
@@ -2037,7 +2093,69 @@ var OutputsApi = class extends WorkspaceCursorApi {
2037
2093
  }
2038
2094
  };
2039
2095
  //#endregion
2040
- //#region src/templates.ts
2096
+ //#region src/resources/keys/keys.ts
2097
+ var KeysApi = class {
2098
+ transport;
2099
+ constructor(transport) {
2100
+ this.transport = transport;
2101
+ }
2102
+ list(principalId, query = {}, options = {}) {
2103
+ return this.transport.request(`/v1/principals/${encodeURIComponent(principalId)}/keys?${queryString({
2104
+ limit: query.limit,
2105
+ cursor: query.cursor,
2106
+ request_id: query.requestId
2107
+ })}`, KeyListResponseSchema, options);
2108
+ }
2109
+ async *all(principalId, query = {}, options = {}) {
2110
+ let cursor;
2111
+ do {
2112
+ const page = await this.list(principalId, {
2113
+ ...query,
2114
+ cursor
2115
+ }, options);
2116
+ yield* page.items;
2117
+ cursor = page.next_cursor ?? void 0;
2118
+ } while (cursor);
2119
+ }
2120
+ issue(principalId, input, options = {}) {
2121
+ return this.transport.request(`/v1/principals/${encodeURIComponent(principalId)}/keys`, KeyIssueResponseSchema, {
2122
+ method: "POST",
2123
+ body: JSON.stringify(input),
2124
+ signal: options.signal
2125
+ });
2126
+ }
2127
+ revoke(principalId, keyId, options = {}) {
2128
+ return this.transport.request(`/v1/principals/${encodeURIComponent(principalId)}/keys/${encodeURIComponent(keyId)}`, z.object({ revoked: z.literal(true) }), {
2129
+ method: "DELETE",
2130
+ signal: options.signal
2131
+ });
2132
+ }
2133
+ revokeAll(principalId, options = {}) {
2134
+ return this.transport.request(`/v1/principals/${encodeURIComponent(principalId)}/keys`, z.object({ revoked: z.literal(true) }), {
2135
+ method: "DELETE",
2136
+ signal: options.signal
2137
+ });
2138
+ }
2139
+ };
2140
+ var RecoveryApi = class {
2141
+ transport;
2142
+ constructor(transport) {
2143
+ this.transport = transport;
2144
+ }
2145
+ purge(principalId, workspaceId, executionKey, options = {}) {
2146
+ return this.transport.request(`/v1/principals/${encodeURIComponent(principalId)}/workspaces/${encodeURIComponent(workspaceId)}/purge`, OperationResourceSchema, {
2147
+ method: "POST",
2148
+ headers: { "Idempotency-Key": executionKey },
2149
+ body: "{}",
2150
+ signal: options.signal
2151
+ });
2152
+ }
2153
+ operation(principalId, operationId, options = {}) {
2154
+ return this.transport.request(`/v1/principals/${encodeURIComponent(principalId)}/operations/${encodeURIComponent(operationId)}`, OperationResourceSchema, options);
2155
+ }
2156
+ };
2157
+ //#endregion
2158
+ //#region src/resources/templates/templates.ts
2041
2159
  var TemplatesApi = class {
2042
2160
  transport;
2043
2161
  constructor(transport) {
@@ -2054,7 +2172,7 @@ var TemplatesApi = class {
2054
2172
  }
2055
2173
  };
2056
2174
  //#endregion
2057
- //#region src/terminals.ts
2175
+ //#region src/resources/terminals/terminals.ts
2058
2176
  var TerminalConnection = class {
2059
2177
  socket;
2060
2178
  messageListeners = /* @__PURE__ */ new Set();
@@ -2156,7 +2274,109 @@ var TerminalsApi = class {
2156
2274
  }
2157
2275
  };
2158
2276
  //#endregion
2159
- //#region src/transport.ts
2277
+ //#region src/resources/workspaces/workspaces.ts
2278
+ const TERMINAL_WORKSPACE_STATES = new Set(TERMINAL_STATES);
2279
+ var WorkspacesApi = class {
2280
+ transport;
2281
+ constructor(transport) {
2282
+ this.transport = transport;
2283
+ }
2284
+ async list(query = {}, options = {}) {
2285
+ return page(await this.transport.request(`/v1/workspaces?${queryString({
2286
+ state: query.state,
2287
+ template: query.template,
2288
+ external_id: query.externalId,
2289
+ limit: query.limit ?? 50,
2290
+ cursor: query.cursor
2291
+ })}`, WorkspacePageSchema, options));
2292
+ }
2293
+ async *all(query = {}, options = {}) {
2294
+ let cursor;
2295
+ do {
2296
+ const current = await this.list({
2297
+ ...query,
2298
+ cursor
2299
+ }, options);
2300
+ for (const workspace of current.items) yield workspace;
2301
+ cursor = current.nextCursor ?? void 0;
2302
+ } while (cursor);
2303
+ }
2304
+ get(id, options = {}) {
2305
+ return this.transport.request(`/v1/workspaces/${encodeURIComponent(id)}`, WorkspaceResourceSchema, options);
2306
+ }
2307
+ create(input, options = {}) {
2308
+ const body = {
2309
+ external_id: input.externalId,
2310
+ template: {
2311
+ name: input.templateName,
2312
+ ...input.templateVersion ? { version: input.templateVersion } : {}
2313
+ },
2314
+ ...input.launchInput ? { launch_input: input.launchInput } : {},
2315
+ ...input.metadata ? { metadata: input.metadata } : {},
2316
+ ...input.source ? { source: input.source } : {}
2317
+ };
2318
+ return this.transport.request("/v1/workspaces", WorkspaceResourceSchema, {
2319
+ method: "POST",
2320
+ signal: options.signal,
2321
+ headers: { "Idempotency-Key": input.idempotencyKey ?? input.externalId },
2322
+ body: JSON.stringify(body)
2323
+ });
2324
+ }
2325
+ cancel(id, options = {}) {
2326
+ return this.transport.request(`/v1/workspaces/${encodeURIComponent(id)}/cancel`, WorkspaceResourceSchema, {
2327
+ method: "POST",
2328
+ signal: options.signal
2329
+ });
2330
+ }
2331
+ change(id, after, wait, options = {}) {
2332
+ return this.transport.request(`/v1/workspaces/${encodeURIComponent(id)}/changes?after=${after}&wait=${wait}`, WorkspaceChangeSchema, options);
2333
+ }
2334
+ async waitForReady(initial, timeoutMs, options = {}) {
2335
+ const deadline = Date.now() + timeoutMs;
2336
+ let workspace = initial;
2337
+ while (workspace.state !== "ready") {
2338
+ if (TERMINAL_STATES.includes(workspace.state)) throw new WorkspaceTerminalError(workspace);
2339
+ const remainingMs = deadline - Date.now();
2340
+ if (remainingMs <= 0) throw new Error(`workspace ${workspace.id} did not become ready within ${timeoutMs}ms`);
2341
+ workspace = (await this.change(workspace.id, workspace.change_cursor, Math.max(1, Math.min(30, Math.ceil(remainingMs / 1e3))), options)).workspace;
2342
+ options.onTick?.(workspace);
2343
+ }
2344
+ return workspace;
2345
+ }
2346
+ async waitForAgentInput(id, timeoutMs, options = {}) {
2347
+ const deadline = Date.now() + timeoutMs;
2348
+ let workspace = await this.get(id, options);
2349
+ while (workspace.agent_state !== "stable") {
2350
+ if (TERMINAL_STATES.includes(workspace.state)) throw new WorkspaceTerminalError(workspace);
2351
+ const remainingMs = deadline - Date.now();
2352
+ if (remainingMs <= 0) throw new AgentNotReadyError(workspace.id, workspace.agent_state, timeoutMs);
2353
+ workspace = (await this.change(workspace.id, workspace.change_cursor, Math.max(1, Math.min(30, Math.ceil(remainingMs / 1e3))), options)).workspace;
2354
+ }
2355
+ return workspace;
2356
+ }
2357
+ preserve(id, input, key, options = {}) {
2358
+ return this.jsonOperation(`/v1/workspaces/${encodeURIComponent(id)}/preserve`, input, key, PreserveResponseSchema, options);
2359
+ }
2360
+ purge(id, key, options = {}) {
2361
+ return this.jsonOperation(`/v1/workspaces/${encodeURIComponent(id)}/purge`, {}, key, OperationResourceSchema, options);
2362
+ }
2363
+ recreate(id, input, key, options = {}) {
2364
+ return this.jsonOperation(`/v1/workspaces/${encodeURIComponent(id)}/recreate`, input, key, RestoreResponseSchema, options);
2365
+ }
2366
+ resume(id, input, key, options = {}) {
2367
+ return this.jsonOperation(`/v1/workspaces/${encodeURIComponent(id)}/resume`, input, key, ResumeResponseSchema, options);
2368
+ }
2369
+ jsonOperation(path, input, key, schema, options) {
2370
+ return this.transport.request(path, schema, {
2371
+ method: "POST",
2372
+ signal: options.signal,
2373
+ headers: { "Idempotency-Key": key },
2374
+ body: JSON.stringify(input)
2375
+ });
2376
+ }
2377
+ };
2378
+ //#endregion
2379
+ //#region src/transport/transport.ts
2160
2380
  function baseUrlOf(value) {
2161
2381
  let url;
2162
2382
  try {
@@ -2273,105 +2493,6 @@ async function delay(milliseconds, signal) {
2273
2493
  });
2274
2494
  }
2275
2495
  //#endregion
2276
- //#region src/workspaces.ts
2277
- const TERMINAL_WORKSPACE_STATES = new Set(TERMINAL_STATES);
2278
- var WorkspacesApi = class {
2279
- transport;
2280
- constructor(transport) {
2281
- this.transport = transport;
2282
- }
2283
- async list(query = {}, options = {}) {
2284
- return page(await this.transport.request(`/v1/workspaces?${queryString({
2285
- state: query.state,
2286
- template: query.template,
2287
- external_id: query.externalId,
2288
- limit: query.limit ?? 50,
2289
- cursor: query.cursor
2290
- })}`, WorkspacePageSchema, options));
2291
- }
2292
- async *all(query = {}, options = {}) {
2293
- let cursor;
2294
- do {
2295
- const current = await this.list({
2296
- ...query,
2297
- cursor
2298
- }, options);
2299
- for (const workspace of current.items) yield workspace;
2300
- cursor = current.nextCursor ?? void 0;
2301
- } while (cursor);
2302
- }
2303
- get(id, options = {}) {
2304
- return this.transport.request(`/v1/workspaces/${encodeURIComponent(id)}`, WorkspaceResourceSchema, options);
2305
- }
2306
- create(input, options = {}) {
2307
- const body = {
2308
- external_id: input.externalId,
2309
- template: {
2310
- name: input.templateName,
2311
- ...input.templateVersion ? { version: input.templateVersion } : {}
2312
- },
2313
- ...input.launchInput ? { launch_input: input.launchInput } : {},
2314
- ...input.metadata ? { metadata: input.metadata } : {},
2315
- ...input.source ? { source: input.source } : {}
2316
- };
2317
- return this.transport.request("/v1/workspaces", WorkspaceResourceSchema, {
2318
- method: "POST",
2319
- signal: options.signal,
2320
- headers: { "Idempotency-Key": input.idempotencyKey ?? input.externalId },
2321
- body: JSON.stringify(body)
2322
- });
2323
- }
2324
- cancel(id, options = {}) {
2325
- return this.transport.request(`/v1/workspaces/${encodeURIComponent(id)}/cancel`, WorkspaceResourceSchema, {
2326
- method: "POST",
2327
- signal: options.signal
2328
- });
2329
- }
2330
- change(id, after, wait, options = {}) {
2331
- return this.transport.request(`/v1/workspaces/${encodeURIComponent(id)}/changes?after=${after}&wait=${wait}`, WorkspaceChangeSchema, options);
2332
- }
2333
- async waitForReady(initial, timeoutMs, options = {}) {
2334
- const deadline = Date.now() + timeoutMs;
2335
- let workspace = initial;
2336
- while (workspace.state !== "ready") {
2337
- if (TERMINAL_STATES.includes(workspace.state)) throw new WorkspaceTerminalError(workspace);
2338
- const remainingMs = deadline - Date.now();
2339
- if (remainingMs <= 0) throw new Error(`workspace ${workspace.id} did not become ready within ${timeoutMs}ms`);
2340
- workspace = (await this.change(workspace.id, workspace.change_cursor, Math.max(1, Math.min(30, Math.ceil(remainingMs / 1e3))), options)).workspace;
2341
- options.onTick?.(workspace);
2342
- }
2343
- return workspace;
2344
- }
2345
- async waitForAgentInput(id, timeoutMs, options = {}) {
2346
- const deadline = Date.now() + timeoutMs;
2347
- let workspace = await this.get(id, options);
2348
- while (workspace.agent_state !== "stable") {
2349
- if (TERMINAL_STATES.includes(workspace.state)) throw new WorkspaceTerminalError(workspace);
2350
- const remainingMs = deadline - Date.now();
2351
- if (remainingMs <= 0) throw new AgentNotReadyError(workspace.id, workspace.agent_state, timeoutMs);
2352
- workspace = (await this.change(workspace.id, workspace.change_cursor, Math.max(1, Math.min(30, Math.ceil(remainingMs / 1e3))), options)).workspace;
2353
- }
2354
- return workspace;
2355
- }
2356
- preserve(id, input, key, options = {}) {
2357
- return this.jsonOperation(`/v1/workspaces/${encodeURIComponent(id)}/preserve`, input, key, PreserveResponseSchema, options);
2358
- }
2359
- recreate(id, input, key, options = {}) {
2360
- return this.jsonOperation(`/v1/workspaces/${encodeURIComponent(id)}/recreate`, input, key, RestoreResponseSchema, options);
2361
- }
2362
- resume(id, input, key, options = {}) {
2363
- return this.jsonOperation(`/v1/workspaces/${encodeURIComponent(id)}/resume`, input, key, ResumeResponseSchema, options);
2364
- }
2365
- jsonOperation(path, input, key, schema, options) {
2366
- return this.transport.request(path, schema, {
2367
- method: "POST",
2368
- signal: options.signal,
2369
- headers: { "Idempotency-Key": key },
2370
- body: JSON.stringify(input)
2371
- });
2372
- }
2373
- };
2374
- //#endregion
2375
2496
  //#region src/client.ts
2376
2497
  var PocketCoderClient = class {
2377
2498
  transport;
@@ -2387,6 +2508,8 @@ var PocketCoderClient = class {
2387
2508
  outputs;
2388
2509
  administration;
2389
2510
  terminals;
2511
+ keys;
2512
+ recovery;
2390
2513
  constructor(config, fetchImpl = fetch) {
2391
2514
  this.transport = new PocketCoderTransport(config, fetchImpl);
2392
2515
  this.templates = new TemplatesApi(this.transport);
@@ -2401,13 +2524,15 @@ var PocketCoderClient = class {
2401
2524
  this.outputs = new OutputsApi(this.transport);
2402
2525
  this.administration = new AdministrationApi(this.transport);
2403
2526
  this.terminals = new TerminalsApi(this.transport);
2527
+ this.keys = new KeysApi(this.transport);
2528
+ this.recovery = new RecoveryApi(this.transport);
2404
2529
  }
2405
2530
  raw(path, init = {}) {
2406
2531
  return this.transport.raw(path, init);
2407
2532
  }
2408
2533
  };
2409
2534
  //#endregion
2410
- //#region src/workspace-turn-resolver.ts
2535
+ //#region src/resources/workspaces/workspace-turn-resolver.ts
2411
2536
  const ERROR_MESSAGES = {
2412
2537
  not_resumable: "workspace cannot be resumed",
2413
2538
  resume_handler_missing: "workspace resume handler is not configured",
@@ -2551,4 +2676,4 @@ var WorkspaceTurnResolver = class {
2551
2676
  }
2552
2677
  };
2553
2678
  //#endregion
2554
- export { AdministrationApi, AgentApi, AgentNotReadyError, AttachmentsApi, CheckpointsApi, ConversationGoneError, ConversationsApi, LogsApi, NetworkEventsApi, OperationsApi, OutputsApi, PocketCoderClient, PocketCoderError, TERMINAL_WORKSPACE_STATES, TemplatesApi, TerminalConnection, TerminalsApi, WorkspaceTerminalError, WorkspaceTurnResolutionError, WorkspaceTurnResolver, WorkspacesApi, isPocketCoderErrorCode, splitAttachmentManifest };
2679
+ export { AdministrationApi, AgentApi, AgentNotReadyError, AttachmentsApi, CheckpointsApi, ConversationGoneError, ConversationsApi, KeysApi, LogsApi, NetworkEventsApi, OperationsApi, OutputsApi, PocketCoderClient, PocketCoderError, RecoveryApi, TERMINAL_WORKSPACE_STATES, TemplatesApi, TerminalConnection, TerminalsApi, WorkspaceTerminalError, WorkspaceTurnResolutionError, WorkspaceTurnResolver, WorkspacesApi, isPocketCoderErrorCode, splitAttachmentManifest };