tila-sdk 0.1.2 → 0.2.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/dist/index.js CHANGED
@@ -9,7 +9,8 @@ z.object({
9
9
  archived: z.number().int().default(0),
10
10
  created_at: z.number().int(),
11
11
  updated_at: z.number().int(),
12
- created_by: z.string()
12
+ created_by: z.string(),
13
+ tags: z.array(z.string()).default([])
13
14
  });
14
15
  var ClaimModeSchema = z.enum(["exclusive", "owner", "presence"]);
15
16
  z.object({
@@ -71,7 +72,8 @@ z.object({
71
72
  produced_at: z.number().int(),
72
73
  produced_by: z.string(),
73
74
  expires_at: z.number().int().nullable(),
74
- tombstoned: z.number().int().default(0)
75
+ tombstoned: z.number().int().default(0),
76
+ tags: z.array(z.string()).default([])
75
77
  });
76
78
  z.object({
77
79
  entity_id: z.string(),
@@ -159,15 +161,15 @@ z.object({
159
161
  payload: z.unknown().optional(),
160
162
  ttl_ms: z.number().int().min(1e3).max(864e5).optional()
161
163
  });
162
- z.object({
164
+ var SendSignalResponseSchema = z.object({
163
165
  ok: z.literal(true),
164
166
  id: z.string()
165
167
  });
166
- z.object({
168
+ var InboxResponseSchema = z.object({
167
169
  ok: z.literal(true),
168
170
  signals: z.array(SignalSchema)
169
171
  });
170
- z.object({
172
+ var AckSignalResponseSchema = z.object({
171
173
  ok: z.literal(true)
172
174
  });
173
175
  z.object({
@@ -331,6 +333,21 @@ z.object({
331
333
  pages_project_name: z.string().optional(),
332
334
  infra_slug: z.string().optional()
333
335
  });
336
+ var TagSchema = z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_:.-]{0,63}$/, "Invalid tag format");
337
+ var TagsSchema = z.array(TagSchema).transform((tags) => {
338
+ const seen = /* @__PURE__ */ new Set();
339
+ const result = [];
340
+ for (const tag of tags) {
341
+ const lower = tag.toLowerCase();
342
+ if (!seen.has(lower)) {
343
+ seen.add(lower);
344
+ result.push(lower);
345
+ }
346
+ }
347
+ return result;
348
+ }).refine((tags) => tags.length <= 20, "may not have more than 20 tags");
349
+
350
+ // ../schemas/dist/record.js
334
351
  var RecordTypeSchema = z.string().regex(/^[a-z][a-z0-9_-]*$/, "Record type must start with lowercase letter and contain only lowercase letters, digits, underscores, and hyphens");
335
352
  var RecordKeySchema = z.string().superRefine((val, ctx) => {
336
353
  if (val.length === 0) {
@@ -407,18 +424,7 @@ var RecordKeySchema = z.string().superRefine((val, ctx) => {
407
424
  }
408
425
  }
409
426
  });
410
- var RecordTagSchema = z.array(z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_:.-]{0,63}$/, "Invalid tag format")).transform((tags) => {
411
- const seen = /* @__PURE__ */ new Set();
412
- const result = [];
413
- for (const tag of tags) {
414
- const lower = tag.toLowerCase();
415
- if (!seen.has(lower)) {
416
- seen.add(lower);
417
- result.push(lower);
418
- }
419
- }
420
- return result;
421
- }).refine((tags) => tags.length <= 20, "Record may not have more than 20 tags");
427
+ var RecordTagSchema = TagsSchema;
422
428
  function sortKeysDeep(v) {
423
429
  if (Array.isArray(v))
424
430
  return v.map(sortKeysDeep);
@@ -457,7 +463,7 @@ z.object({
457
463
  idempotency_key: z.string().optional(),
458
464
  metadata: z.record(z.unknown()).optional()
459
465
  });
460
- z.object({
466
+ var AcquireSuccessResponseSchema = z.object({
461
467
  ok: z.literal(true),
462
468
  fence: z.number().int(),
463
469
  expires_at: z.number().int()
@@ -467,7 +473,7 @@ z.object({
467
473
  fence: z.number().int(),
468
474
  ttl_ms: z.number().int().positive()
469
475
  });
470
- z.object({
476
+ var RenewSuccessResponseSchema = z.object({
471
477
  ok: z.literal(true),
472
478
  expires_at: z.number().int()
473
479
  });
@@ -475,10 +481,10 @@ z.object({
475
481
  resource: z.string(),
476
482
  fence: z.number().int()
477
483
  });
478
- z.object({
484
+ var ReleaseSuccessResponseSchema = z.object({
479
485
  ok: z.literal(true)
480
486
  });
481
- z.object({
487
+ var StateResponseSchema = z.object({
482
488
  ok: z.literal(true),
483
489
  claim: z.object({
484
490
  resource: z.string(),
@@ -507,16 +513,18 @@ z.object({
507
513
  z.object({
508
514
  id: z.string(),
509
515
  type: z.string(),
510
- data: z.record(z.unknown()).default({})
516
+ data: z.record(z.unknown()).default({}),
517
+ tags: TagsSchema.optional()
511
518
  });
512
519
  z.object({
513
520
  data: z.record(z.unknown()),
514
- fence: z.number().int()
521
+ fence: z.number().int(),
522
+ tags: TagsSchema.optional()
515
523
  });
516
524
  z.object({
517
525
  fence: z.number().int()
518
526
  });
519
- z.object({
527
+ var EntityResponseSchema = z.object({
520
528
  ok: z.literal(true),
521
529
  entity: z.object({
522
530
  id: z.string(),
@@ -526,7 +534,8 @@ z.object({
526
534
  archived: z.number().int(),
527
535
  created_at: z.number().int(),
528
536
  updated_at: z.number().int(),
529
- created_by: z.string()
537
+ created_by: z.string(),
538
+ tags: z.array(z.string())
530
539
  })
531
540
  });
532
541
  z.object({
@@ -539,10 +548,11 @@ z.object({
539
548
  archived: z.number().int(),
540
549
  created_at: z.number().int(),
541
550
  updated_at: z.number().int(),
542
- created_by: z.string()
551
+ created_by: z.string(),
552
+ tags: z.array(z.string())
543
553
  }))
544
554
  });
545
- z.object({
555
+ var PaginatedEntityListResponseSchema = z.object({
546
556
  ok: z.literal(true),
547
557
  entities: z.array(z.object({
548
558
  id: z.string(),
@@ -552,14 +562,15 @@ z.object({
552
562
  archived: z.number().int(),
553
563
  created_at: z.number().int(),
554
564
  updated_at: z.number().int(),
555
- created_by: z.string()
565
+ created_by: z.string(),
566
+ tags: z.array(z.string())
556
567
  })),
557
568
  total: z.number().int(),
558
569
  limit: z.number().int().nullable(),
559
570
  offset: z.number().int(),
560
571
  has_more: z.boolean()
561
572
  });
562
- z.object({
573
+ var ListReadyEntitiesResponseSchema = z.object({
563
574
  ok: z.literal(true),
564
575
  entities: z.array(z.object({
565
576
  id: z.string(),
@@ -589,7 +600,7 @@ z.object({
589
600
  ok: z.literal(true),
590
601
  entity: CompactEntitySchema
591
602
  });
592
- z.object({
603
+ var PaginatedCompactEntityListResponseSchema = z.object({
593
604
  ok: z.literal(true),
594
605
  entities: z.array(CompactEntitySchema),
595
606
  total: z.number().int(),
@@ -597,7 +608,7 @@ z.object({
597
608
  offset: z.number().int(),
598
609
  has_more: z.boolean()
599
610
  });
600
- z.object({
611
+ var SummaryResponseSchema = z.object({
601
612
  ok: z.literal(true),
602
613
  project: z.object({
603
614
  entity_count: z.number().int(),
@@ -616,7 +627,7 @@ z.object({
616
627
  }))
617
628
  })
618
629
  });
619
- z.object({
630
+ var EntityDetailResponseSchema = z.object({
620
631
  ok: z.literal(true),
621
632
  entity: z.object({
622
633
  id: z.string(),
@@ -626,11 +637,12 @@ z.object({
626
637
  archived: z.number().int(),
627
638
  created_at: z.number().int(),
628
639
  updated_at: z.number().int(),
629
- created_by: z.string()
640
+ created_by: z.string(),
641
+ tags: z.array(z.string())
630
642
  }),
631
643
  relationships: z.array(EntityRelationshipSchema).default([])
632
644
  });
633
- z.object({
645
+ var ArchiveSuccessResponseSchema = z.object({
634
646
  ok: z.literal(true)
635
647
  });
636
648
  z.object({
@@ -638,7 +650,7 @@ z.object({
638
650
  to_id: z.string().min(1),
639
651
  type: EntityRelationshipTypeSchema
640
652
  });
641
- z.object({
653
+ var CreateEntityRelationshipResponseSchema = z.object({
642
654
  ok: z.literal(true),
643
655
  created: z.boolean().default(true)
644
656
  });
@@ -647,7 +659,7 @@ z.object({
647
659
  to_id: z.string().min(1).optional(),
648
660
  type: EntityRelationshipTypeSchema.optional()
649
661
  });
650
- z.object({
662
+ var ListEntityRelationshipsResponseSchema = z.object({
651
663
  ok: z.literal(true),
652
664
  relationships: z.array(EntityRelationshipSchema)
653
665
  });
@@ -656,7 +668,7 @@ z.object({
656
668
  to_id: z.string().min(1),
657
669
  type: EntityRelationshipTypeSchema
658
670
  });
659
- z.object({
671
+ var DeleteEntityRelationshipResponseSchema = z.object({
660
672
  ok: z.literal(true),
661
673
  removed: z.boolean()
662
674
  });
@@ -667,7 +679,7 @@ z.object({
667
679
  after_seq: z.number().int().optional(),
668
680
  limit: z.number().int().positive().default(100)
669
681
  });
670
- z.object({
682
+ var JournalResponseSchema = z.object({
671
683
  ok: z.literal(true),
672
684
  events: z.array(z.object({
673
685
  seq: z.number().int(),
@@ -694,7 +706,7 @@ z.object({
694
706
  info: z.record(z.unknown())
695
707
  }))
696
708
  });
697
- z.object({
709
+ var PresenceAllListResponseSchema = z.object({
698
710
  ok: z.literal(true),
699
711
  machines: z.array(z.object({
700
712
  machine: z.string(),
@@ -703,7 +715,7 @@ z.object({
703
715
  active: z.boolean()
704
716
  }))
705
717
  });
706
- z.object({
718
+ var PresenceHeartbeatSuccessResponseSchema = z.object({
707
719
  ok: z.literal(true)
708
720
  });
709
721
  z.object({
@@ -845,7 +857,7 @@ z.object({
845
857
  slot: z.string().min(1),
846
858
  metadata: z.record(z.unknown()).default({})
847
859
  });
848
- z.object({
860
+ var EntityArtifactReferenceListResponseSchema = z.object({
849
861
  ok: z.literal(true),
850
862
  references: z.array(z.object({
851
863
  entity_id: z.string(),
@@ -855,6 +867,46 @@ z.object({
855
867
  created_at: z.number().int()
856
868
  }))
857
869
  });
870
+ function parseTagFilter(raw) {
871
+ if (!raw)
872
+ return void 0;
873
+ const parts = raw.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
874
+ if (parts.length === 0)
875
+ return void 0;
876
+ for (const part of parts) {
877
+ TagSchema.parse(part);
878
+ }
879
+ const unique = [...new Set(parts)];
880
+ if (unique.length > 20) {
881
+ throw new z.ZodError([
882
+ {
883
+ code: z.ZodIssueCode.too_big,
884
+ maximum: 20,
885
+ type: "array",
886
+ inclusive: true,
887
+ exact: false,
888
+ message: "tag_filter may not have more than 20 tags",
889
+ path: ["tag_filter"]
890
+ }
891
+ ]);
892
+ }
893
+ return unique;
894
+ }
895
+ var tagFilterQueryParam = z.string().optional().superRefine((v, ctx) => {
896
+ if (!v)
897
+ return;
898
+ try {
899
+ parseTagFilter(v);
900
+ } catch (err) {
901
+ if (err instanceof z.ZodError) {
902
+ for (const issue of err.issues) {
903
+ ctx.addIssue(issue);
904
+ }
905
+ } else {
906
+ throw err;
907
+ }
908
+ }
909
+ }).transform((v) => parseTagFilter(v));
858
910
  z.object({
859
911
  ok: z.literal(true),
860
912
  results: z.array(ArtifactSearchResultSchema),
@@ -865,7 +917,8 @@ z.object({
865
917
  kind: z.string().optional(),
866
918
  resource: z.string().optional(),
867
919
  source_only: z.string().optional().transform((v) => v === "true").pipe(z.boolean()),
868
- limit: z.string().optional().default("20").transform((v) => Number.parseInt(v, 10)).pipe(z.number().int().min(1).max(100))
920
+ limit: z.string().optional().default("20").transform((v) => Number.parseInt(v, 10)).pipe(z.number().int().min(1).max(100)),
921
+ tag_filter: tagFilterQueryParam
869
922
  });
870
923
  var ArtifactGrepLineSchema = z.object({
871
924
  line: z.number().int(),
@@ -883,7 +936,7 @@ var ArtifactGrepResultSchema = z.object({
883
936
  truncated: z.boolean().optional()
884
937
  // this blob hit the per-blob byte cap
885
938
  });
886
- z.object({
939
+ var ArtifactGrepResponseSchema = z.object({
887
940
  ok: z.literal(true),
888
941
  results: z.array(ArtifactGrepResultSchema),
889
942
  scanned: z.number().int(),
@@ -919,16 +972,18 @@ z.object({
919
972
  });
920
973
  z.object({
921
974
  q: z.string().min(1).max(200),
922
- limit: z.string().optional().default("20").transform((v) => Number.parseInt(v, 10)).pipe(z.number().int().min(1).max(100))
975
+ limit: z.string().optional().default("20").transform((v) => Number.parseInt(v, 10)).pipe(z.number().int().min(1).max(100)),
976
+ tag_filter: tagFilterQueryParam
923
977
  });
924
978
  z.object({
925
979
  content: z.string().min(1),
926
980
  kind: z.string().min(1),
927
981
  mime_type: z.string().default("text/markdown"),
928
982
  resource: z.string().optional(),
929
- fence: z.number().int().optional()
983
+ fence: z.number().int().optional(),
984
+ tags: TagsSchema.optional()
930
985
  });
931
- z.object({
986
+ var ArtifactPutResponseSchema = z.object({
932
987
  ok: z.literal(true),
933
988
  key: z.string(),
934
989
  bytes: z.number(),
@@ -947,7 +1002,8 @@ z.object({
947
1002
  produced_at: z.number(),
948
1003
  produced_by: z.string(),
949
1004
  expires_at: z.number().nullable(),
950
- tombstoned: z.number()
1005
+ tombstoned: z.number(),
1006
+ tags: z.array(z.string())
951
1007
  }))
952
1008
  });
953
1009
  z.object({
@@ -1034,12 +1090,15 @@ var RecordItemSchema = z.object({
1034
1090
  updated_by: z.string(),
1035
1091
  tags: z.array(z.string())
1036
1092
  });
1037
- z.object({
1093
+ RecordItemSchema.extend({
1094
+ fence: z.number().int()
1095
+ });
1096
+ var RecordGetResponseSchema = z.object({
1038
1097
  ok: z.literal(true),
1039
1098
  record: RecordItemSchema,
1040
1099
  fence: z.number().int()
1041
1100
  });
1042
- z.object({
1101
+ var RecordMutateResponseSchema = z.object({
1043
1102
  ok: z.literal(true),
1044
1103
  record: RecordItemSchema,
1045
1104
  fence: z.number().int(),
@@ -1054,7 +1113,7 @@ var RecordListItemSchema = z.object({
1054
1113
  archived: z.number().int(),
1055
1114
  tags: z.array(z.string())
1056
1115
  });
1057
- z.object({
1116
+ var RecordListResponseSchema = z.object({
1058
1117
  ok: z.literal(true),
1059
1118
  items: z.array(RecordListItemSchema),
1060
1119
  meta: z.object({
@@ -1074,9 +1133,12 @@ var RecordHistoryItemSchema = z.object({
1074
1133
  source_artifact_key: z.string().nullable(),
1075
1134
  actor: z.string(),
1076
1135
  created_at: z.number().int(),
1077
- message: z.string().nullable()
1136
+ message: z.string().nullable(),
1137
+ // Populated only when the history is requested with `includeValues=true`
1138
+ // (wire: `?values=true`). Optional so existing parsers stay compatible.
1139
+ value: z.record(z.unknown()).optional()
1078
1140
  });
1079
- z.object({
1141
+ var RecordHistoryResponseSchema = z.object({
1080
1142
  ok: z.literal(true),
1081
1143
  items: z.array(RecordHistoryItemSchema),
1082
1144
  meta: z.object({
@@ -1186,393 +1248,208 @@ z.object({
1186
1248
  z.object({
1187
1249
  resolution: z.string().optional()
1188
1250
  });
1189
- z.object({
1251
+ var GateResponseSchema = z.object({
1190
1252
  ok: z.literal(true),
1191
1253
  gate: GateSchema
1192
1254
  });
1193
- z.object({
1255
+ var GateListResponseSchema = z.object({
1194
1256
  ok: z.literal(true),
1195
1257
  gates: z.array(GateSchema)
1196
1258
  });
1197
1259
 
1198
- // src/version.ts
1199
- var SDK_VERSION = "0.1.2";
1200
-
1201
- // src/client.ts
1202
- var TilaClient = class _TilaClient {
1203
- baseUrl;
1204
- token;
1205
- validate;
1206
- timeoutMs;
1207
- extraHeaders;
1208
- constructor(opts) {
1209
- this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
1210
- this.token = opts.token;
1211
- this.validate = opts.validate ?? false;
1212
- this.timeoutMs = opts.timeoutMs ?? 3e4;
1213
- this.extraHeaders = {
1214
- "X-Tila-Source": `sdk/${SDK_VERSION}`,
1215
- ...opts.extraHeaders
1216
- };
1217
- }
1218
- /**
1219
- * Creates an AbortSignal that fires after this.timeoutMs.
1220
- * Uses AbortSignal.timeout() when available (Node 18.8+, Bun 0.5+, browsers),
1221
- * falls back to manual setTimeout + AbortController for older runtimes.
1222
- *
1223
- * Note: Cloudflare Workers has supported AbortSignal.timeout() since 2023;
1224
- * the fallback branch will never execute there.
1225
- */
1226
- createAbortSignal() {
1227
- if (typeof AbortSignal.timeout === "function") {
1228
- return AbortSignal.timeout(this.timeoutMs);
1229
- }
1230
- const controller = new AbortController();
1231
- setTimeout(
1232
- () => controller.abort(
1233
- new DOMException(
1234
- "The operation was aborted due to timeout",
1235
- "TimeoutError"
1236
- )
1237
- ),
1238
- this.timeoutMs
1239
- );
1240
- return controller.signal;
1241
- }
1242
- static fromConfig(config, token) {
1243
- if (!config.worker_url) {
1244
- throw new Error(
1245
- `Cannot create TilaClient: config has no worker_url. Use 'tila project create' or set backend = "cloudflare" in .tila/config.toml.`
1260
+ // src/artifacts.ts
1261
+ function createArtifactMethods(client, projectId) {
1262
+ const base = `/projects/${projectId}/artifacts`;
1263
+ return {
1264
+ upload: Object.assign(
1265
+ function upload(input, opts) {
1266
+ if (input instanceof ReadableStream) {
1267
+ if (!opts.mimeType) {
1268
+ throw new TypeError(
1269
+ "mimeType is required when uploading a ReadableStream. Pass opts.mimeType explicitly."
1270
+ );
1271
+ }
1272
+ return new Response(input).arrayBuffer().then((bytes) => {
1273
+ const uploadFile = new Blob([bytes], {
1274
+ type: opts.mimeType
1275
+ });
1276
+ const formData2 = new FormData();
1277
+ formData2.append("file", uploadFile);
1278
+ formData2.append("kind", opts.kind);
1279
+ formData2.append("mime_type", opts.mimeType);
1280
+ if (opts.resource) formData2.append("resource", opts.resource);
1281
+ if (opts.fence !== void 0)
1282
+ formData2.append("fence", String(opts.fence));
1283
+ if (opts.flavor) formData2.append("flavor", opts.flavor);
1284
+ if (opts.tags !== void 0)
1285
+ formData2.append("tags", JSON.stringify(opts.tags));
1286
+ return client.postFormData(base, formData2);
1287
+ });
1288
+ }
1289
+ const contentType = opts.mimeType || (input instanceof File ? input.type : "") || "";
1290
+ if (!contentType) {
1291
+ throw new TypeError(
1292
+ "contentType is required for uploads when file.type is absent. Pass opts.mimeType explicitly."
1293
+ );
1294
+ }
1295
+ const formData = new FormData();
1296
+ formData.append("file", input);
1297
+ formData.append("kind", opts.kind);
1298
+ formData.append("mime_type", contentType);
1299
+ if (opts.resource) formData.append("resource", opts.resource);
1300
+ if (opts.fence !== void 0)
1301
+ formData.append("fence", String(opts.fence));
1302
+ if (opts.flavor) formData.append("flavor", opts.flavor);
1303
+ if (opts.tags !== void 0)
1304
+ formData.append("tags", JSON.stringify(opts.tags));
1305
+ return client.postFormData(base, formData);
1306
+ },
1307
+ {}
1308
+ ),
1309
+ async download(key) {
1310
+ const res = await client.requestRaw(
1311
+ "GET",
1312
+ `${base}/${encodeURIComponent(key)}`
1246
1313
  );
1247
- }
1248
- return new _TilaClient({ baseUrl: config.worker_url, token });
1249
- }
1250
- async request(method, path, opts) {
1251
- const url = new URL(path, `${this.baseUrl}/`);
1252
- if (opts?.query) {
1253
- for (const [key, value] of Object.entries(opts.query)) {
1254
- if (value !== void 0) {
1255
- url.searchParams.set(key, value);
1314
+ return {
1315
+ body: res.body ?? new ReadableStream(),
1316
+ contentType: res.headers.get("content-type") || "application/octet-stream",
1317
+ contentLength: res.headers.has("content-length") ? Number(res.headers.get("content-length")) : null
1318
+ };
1319
+ },
1320
+ async list(query) {
1321
+ const { tagFilter, ...rest } = query ?? {};
1322
+ const q = { ...rest };
1323
+ if (tagFilter?.length) q.tag_filter = tagFilter.join(",");
1324
+ return client.get(base, { query: q });
1325
+ },
1326
+ async search(q, opts) {
1327
+ const { tagFilter, ...rest } = opts ?? {};
1328
+ const query = { q, ...rest };
1329
+ if (tagFilter?.length) query.tag_filter = tagFilter.join(",");
1330
+ return client.get(`${base}/search`, { query });
1331
+ },
1332
+ async grep(pattern, opts) {
1333
+ const query = { pattern };
1334
+ if (opts?.kind) query.kind = opts.kind;
1335
+ if (opts?.resource) query.resource = opts.resource;
1336
+ if (opts?.regex) query.regex = "true";
1337
+ if (opts?.limit != null) query.limit = String(opts.limit);
1338
+ return client.get(`${base}/grep`, { query });
1339
+ },
1340
+ async addRelationship(fromKey, toKeyOrUri, type, metadata) {
1341
+ const isUri = toKeyOrUri.includes("://");
1342
+ return client.post(
1343
+ `${base}/${encodeURIComponent(fromKey)}/relationships`,
1344
+ {
1345
+ [isUri ? "to_uri" : "to_key"]: toKeyOrUri,
1346
+ type,
1347
+ metadata
1256
1348
  }
1349
+ );
1350
+ },
1351
+ async listRelationships(key) {
1352
+ return client.get(
1353
+ `${base}/${encodeURIComponent(key)}/relationships`
1354
+ );
1355
+ },
1356
+ async getLatest(kind, resource) {
1357
+ let res;
1358
+ try {
1359
+ res = await client.requestRaw("GET", `${base}/latest`, {
1360
+ query: { kind, resource }
1361
+ });
1362
+ } catch (err) {
1363
+ if (err instanceof TilaApiError && err.status === 404) return null;
1364
+ throw err;
1257
1365
  }
1258
- }
1259
- const headers = {
1260
- Authorization: `Bearer ${this.token}`,
1261
- Accept: "application/json",
1262
- ...this.extraHeaders
1263
- };
1264
- const init = {
1265
- method,
1266
- headers,
1267
- signal: this.createAbortSignal()
1268
- };
1269
- if (opts?.body !== void 0) {
1270
- headers["Content-Type"] = "application/json";
1271
- init.body = JSON.stringify(opts.body);
1272
- }
1273
- let res;
1274
- try {
1275
- res = await fetch(url.toString(), init);
1276
- } catch (err) {
1277
- if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
1278
- throw new Error(
1279
- `Request to ${url.origin} timed out after ${this.timeoutMs}ms`
1366
+ const body = await res.json();
1367
+ return body.pointer;
1368
+ },
1369
+ async writeText(content, opts) {
1370
+ const body = {
1371
+ content,
1372
+ kind: opts.kind,
1373
+ mime_type: opts.mimeType ?? "text/markdown",
1374
+ resource: opts.resource,
1375
+ fence: opts.fence
1376
+ };
1377
+ if (opts.tags !== void 0) body.tags = opts.tags;
1378
+ return client.post(`${base}/text`, body);
1379
+ },
1380
+ async readText(key) {
1381
+ const res = await client.requestRaw(
1382
+ "GET",
1383
+ `${base}/${encodeURIComponent(key)}`
1384
+ );
1385
+ const contentType = res.headers.get("content-type") || "application/octet-stream";
1386
+ if (!contentType.startsWith("text/")) {
1387
+ throw new TypeError(
1388
+ `Artifact ${key} has MIME type ${contentType} \u2014 readText only supports text/* artifacts`
1280
1389
  );
1281
1390
  }
1282
- throw new Error(
1283
- `Network error connecting to ${url.origin}: ${err instanceof Error ? err.message : String(err)}`
1284
- );
1285
- }
1286
- if (!res.ok) {
1287
- await this.throwApiError(res);
1288
- }
1289
- const body = await res.json();
1290
- const shouldValidate = opts?.validate ?? this.validate;
1291
- if (shouldValidate && opts?.schema) {
1292
- const result = opts.schema.safeParse(body);
1293
- if (!result.success) {
1294
- const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
1295
- throw new Error(
1296
- `Unexpected response shape from ${method} ${path}:
1297
- ${issues}`
1298
- );
1299
- }
1300
- return result.data;
1301
- }
1302
- return body;
1303
- }
1304
- async get(path, opts) {
1305
- return this.request("GET", path, {
1306
- schema: opts?.schema,
1307
- query: opts?.query,
1308
- validate: opts?.validate
1309
- });
1310
- }
1311
- async post(path, body, opts) {
1312
- return this.request("POST", path, {
1313
- body,
1314
- schema: opts?.schema,
1315
- validate: opts?.validate
1316
- });
1317
- }
1318
- async put(path, body, opts) {
1319
- return this.request("PUT", path, {
1320
- body,
1321
- schema: opts?.schema,
1322
- validate: opts?.validate
1323
- });
1324
- }
1325
- async patch(path, body, opts) {
1326
- return this.request("PATCH", path, {
1327
- body,
1328
- schema: opts?.schema,
1329
- validate: opts?.validate
1330
- });
1331
- }
1332
- async delete(path, opts) {
1333
- return this.request("DELETE", path, {
1334
- schema: opts?.schema,
1335
- validate: opts?.validate
1336
- });
1337
- }
1338
- async requestRaw(method, path, opts) {
1339
- const url = new URL(path, `${this.baseUrl}/`);
1340
- if (opts?.query) {
1341
- for (const [key, value] of Object.entries(opts.query)) {
1342
- if (value !== void 0) {
1343
- url.searchParams.set(key, value);
1344
- }
1345
- }
1391
+ const text = await res.text();
1392
+ return { content: text, mimeType: contentType };
1346
1393
  }
1347
- const headers = {
1348
- Authorization: `Bearer ${this.token}`,
1349
- ...this.extraHeaders
1350
- };
1351
- let res;
1352
- try {
1353
- res = await fetch(url.toString(), {
1354
- method,
1355
- headers,
1356
- signal: this.createAbortSignal()
1394
+ };
1395
+ }
1396
+
1397
+ // src/claims.ts
1398
+ function createClaimMethods(client, projectId) {
1399
+ const base = `/projects/${projectId}/claims`;
1400
+ return {
1401
+ async acquire(resource, mode, ttlMs, opts) {
1402
+ return client.post(`${base}/acquire`, {
1403
+ resource,
1404
+ mode,
1405
+ ttl_ms: ttlMs,
1406
+ ...opts
1357
1407
  });
1358
- } catch (err) {
1359
- if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
1360
- throw new Error(
1361
- `Request to ${url.origin} timed out after ${this.timeoutMs}ms`
1362
- );
1363
- }
1364
- throw new Error(
1365
- `Network error connecting to ${url.origin}: ${err instanceof Error ? err.message : String(err)}`
1366
- );
1367
- }
1368
- if (!res.ok) {
1369
- await this.throwApiError(res);
1370
- }
1371
- return res;
1372
- }
1373
- async postFormData(path, formData, opts) {
1374
- const url = new URL(path, `${this.baseUrl}/`);
1375
- const headers = {
1376
- Authorization: `Bearer ${this.token}`,
1377
- Accept: "application/json",
1378
- ...this.extraHeaders
1379
- };
1380
- let res;
1381
- try {
1382
- res = await fetch(url.toString(), {
1383
- method: "POST",
1384
- headers,
1385
- body: formData,
1386
- signal: this.createAbortSignal()
1408
+ },
1409
+ async renew(resource, fence, ttlMs) {
1410
+ return client.post(`${base}/renew`, {
1411
+ resource,
1412
+ fence,
1413
+ ttl_ms: ttlMs
1387
1414
  });
1388
- } catch (err) {
1389
- if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
1390
- throw new Error(
1391
- `Request to ${url.origin} timed out after ${this.timeoutMs}ms`
1392
- );
1393
- }
1394
- throw new Error(
1395
- `Network error connecting to ${url.origin}: ${err instanceof Error ? err.message : String(err)}`
1415
+ },
1416
+ async release(resource, fence) {
1417
+ return client.post(`${base}/release`, {
1418
+ resource,
1419
+ fence
1420
+ });
1421
+ },
1422
+ async list() {
1423
+ return client.get(base);
1424
+ },
1425
+ async get(resource) {
1426
+ return client.get(
1427
+ `${base}/${encodeURIComponent(resource)}`
1396
1428
  );
1397
1429
  }
1398
- if (!res.ok) {
1399
- await this.throwApiError(res);
1400
- }
1401
- const body = await res.json();
1402
- const shouldValidate = opts?.validate ?? this.validate;
1403
- if (shouldValidate && opts?.schema) {
1404
- const result = opts.schema.safeParse(body);
1405
- if (!result.success) {
1406
- const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
1407
- throw new Error(
1408
- `Unexpected response shape from POST ${path}:
1409
- ${issues}`
1410
- );
1411
- }
1412
- return result.data;
1413
- }
1414
- return body;
1415
- }
1416
- async throwApiError(res) {
1417
- try {
1418
- const body = await res.json();
1419
- const parsed = ErrorEnvelopeSchema.safeParse(body);
1420
- if (parsed.success) {
1421
- const { code, message, retryable } = parsed.data.error;
1422
- throw new TilaApiError(res.status, code, message, retryable);
1423
- }
1424
- } catch (err) {
1425
- if (err instanceof TilaApiError) throw err;
1426
- }
1427
- throw new TilaApiError(
1428
- res.status,
1429
- "UNKNOWN",
1430
- `HTTP ${res.status}: ${res.statusText}`,
1431
- false
1432
- );
1433
- }
1434
- };
1435
- var TilaApiError = class extends Error {
1436
- constructor(status, code, message, retryable) {
1437
- super(message);
1438
- this.status = status;
1439
- this.code = code;
1440
- this.retryable = retryable;
1441
- this.name = "TilaApiError";
1442
- }
1443
- status;
1444
- code;
1445
- retryable;
1446
- };
1447
- function isTilaApiError(err) {
1448
- return err instanceof TilaApiError;
1449
- }
1450
- async function exchangeGitHubToken(baseUrl, projectId, githubToken) {
1451
- const url = `${baseUrl.replace(/\/+$/, "")}/api/auth/github/exchange`;
1452
- let res;
1453
- try {
1454
- res = await fetch(url, {
1455
- method: "POST",
1456
- headers: { "Content-Type": "application/json" },
1457
- body: JSON.stringify({
1458
- project_id: projectId,
1459
- github_token: githubToken
1460
- })
1461
- });
1462
- } catch (err) {
1463
- throw new Error(
1464
- `Network error during GitHub token exchange: ${err instanceof Error ? err.message : String(err)}`
1465
- );
1466
- }
1467
- if (!res.ok) {
1468
- try {
1469
- const body2 = await res.json();
1470
- const parsed = ErrorEnvelopeSchema.safeParse(body2);
1471
- if (parsed.success) {
1472
- const { code, message, retryable } = parsed.data.error;
1473
- throw new TilaApiError(res.status, code, message, retryable);
1474
- }
1475
- } catch (err) {
1476
- if (err instanceof TilaApiError) throw err;
1477
- }
1478
- throw new TilaApiError(
1479
- res.status,
1480
- "UNKNOWN",
1481
- `HTTP ${res.status}: ${res.statusText}`,
1482
- false
1483
- );
1484
- }
1485
- const body = await res.json();
1486
- if (!body.session_token || typeof body.expires_at !== "number") {
1487
- throw new TypeError(
1488
- "Exchange returned unexpected response shape: missing session_token or expires_at"
1489
- );
1490
- }
1491
- return {
1492
- sessionToken: body.session_token,
1493
- expiresAt: body.expires_at,
1494
- permission: body.permission ?? "read"
1495
1430
  };
1496
1431
  }
1497
1432
 
1498
- // src/retry.ts
1499
- async function withRetry(fn, opts) {
1500
- const maxRetries = opts?.maxRetries ?? 3;
1501
- const baseDelayMs = opts?.baseDelayMs ?? 200;
1502
- const maxDelayMs = opts?.maxDelayMs ?? 3e4;
1503
- const jitter = opts?.jitter ?? true;
1504
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
1505
- try {
1506
- return await fn();
1507
- } catch (err) {
1508
- if (isTilaApiError(err) && err.retryable === false) {
1509
- throw err;
1510
- }
1511
- if (attempt === maxRetries) {
1512
- throw err;
1513
- }
1514
- const cap = Math.min(maxDelayMs, baseDelayMs * 2 ** attempt);
1515
- const sleepMs = jitter ? Math.random() * cap : cap;
1516
- await new Promise((resolve) => setTimeout(resolve, sleepMs));
1517
- }
1518
- }
1519
- throw new Error("withRetry: unreachable");
1520
- }
1521
-
1522
- // src/error-codes.ts
1523
- var TILA_ERRORS = {
1524
- // Auth / middleware (worker layer — SCREAMING_SNAKE_CASE wire values)
1525
- UNAUTHORIZED: "UNAUTHORIZED",
1526
- SESSION_EXPIRED: "SESSION_EXPIRED",
1527
- RATE_LIMITED: "RATE_LIMITED",
1528
- PERMISSION_DENIED: "PERMISSION_DENIED",
1529
- PROJECT_MISMATCH: "PROJECT_MISMATCH",
1530
- CSRF_MISSING_ORIGIN: "CSRF_MISSING_ORIGIN",
1531
- CSRF_ORIGIN_MISMATCH: "CSRF_ORIGIN_MISMATCH",
1532
- INTERNAL_ERROR: "INTERNAL_ERROR",
1533
- DO_UNREACHABLE: "do-unreachable",
1534
- // Auth endpoint specific
1535
- REPO_NOT_ALLOWED: "REPO_NOT_ALLOWED",
1536
- GITHUB_AUTH_FAILED: "GITHUB_AUTH_FAILED",
1537
- HMAC_NOT_CONFIGURED: "HMAC_NOT_CONFIGURED",
1538
- // Token endpoint specific
1539
- TOKEN_NAME_CONFLICT: "TOKEN_NAME_CONFLICT",
1540
- TOKEN_AUTHZ_DENIED: "TOKEN_AUTHZ_DENIED",
1541
- TOKEN_NOT_FOUND: "TOKEN_NOT_FOUND",
1542
- // Validation (worker layer uses SCREAMING_SNAKE for this code)
1543
- VALIDATION_ERROR: "VALIDATION_ERROR",
1544
- // DO errors (project-do-router — kebab-case wire values)
1545
- STALE_FENCE: "stale-fence",
1546
- NOT_FOUND: "not-found",
1547
- GATE_ALREADY_SETTLED: "gate-already-settled",
1548
- NO_FENCE: "no-fence",
1549
- INTERNAL: "internal",
1550
- CONSTRAINT_VIOLATION: "constraint-violation",
1551
- IDEMPOTENCY_KEY_CONFLICT: "idempotency-key-conflict",
1552
- // DO-layer validation uses kebab-case (distinct from VALIDATION_ERROR above)
1553
- VALIDATION_ERROR_DO: "validation-error",
1554
- ALREADY_HELD: "already-held",
1555
- RENEW_FAILED: "renew-failed",
1556
- BAD_REQUEST: "bad-request",
1557
- MISSING_QUERY: "missing-query",
1558
- INVALID_QUERY: "invalid-query",
1559
- INVALID_SLOT: "invalid-slot",
1560
- INVALID_RELATIONSHIP_TYPE: "invalid-relationship-type",
1561
- // Fallback (SDK-generated when response is unparseable)
1562
- UNKNOWN: "UNKNOWN"
1563
- };
1564
-
1565
1433
  // src/entities.ts
1566
1434
  function _createMethods(client, base) {
1567
1435
  return {
1568
- async create(id, type, data) {
1569
- return client.post(base, { id, type, data });
1436
+ async create(id, type, data, tags) {
1437
+ return client.post(base, {
1438
+ id,
1439
+ type,
1440
+ data,
1441
+ ...tags !== void 0 ? { tags } : {}
1442
+ });
1570
1443
  },
1571
1444
  async get(id) {
1572
1445
  return client.get(`${base}/${id}`);
1573
1446
  },
1574
1447
  async list(query) {
1575
- return client.get(base, { query });
1448
+ const { tagFilter, compact, ...rest } = query ?? {};
1449
+ const q = { ...rest };
1450
+ if (tagFilter?.length) q.tag_filter = tagFilter.join(",");
1451
+ if (compact) q.compact = "true";
1452
+ return client.get(base, { query: q });
1576
1453
  },
1577
1454
  async update(id, data, fence) {
1578
1455
  return client.patch(`${base}/${id}`, { data, fence });
@@ -1584,13 +1461,34 @@ function _createMethods(client, base) {
1584
1461
  },
1585
1462
  async addRelationship(fromId, toId, type) {
1586
1463
  return client.post(
1587
- `${base}/${fromId}/relationships`,
1464
+ `${base}/relationships`,
1588
1465
  {
1466
+ from_id: fromId,
1589
1467
  to_id: toId,
1590
1468
  type
1591
1469
  }
1592
1470
  );
1593
1471
  },
1472
+ async listRelationships(filter) {
1473
+ const query = {
1474
+ from_id: filter?.fromId,
1475
+ to_id: filter?.toId,
1476
+ type: filter?.type
1477
+ };
1478
+ return client.get(
1479
+ `${base}/relationships`,
1480
+ { query }
1481
+ );
1482
+ },
1483
+ async ready(query) {
1484
+ const q = {
1485
+ type: query?.type,
1486
+ parent: query?.parent,
1487
+ limit: query?.limit !== void 0 ? String(query.limit) : void 0
1488
+ };
1489
+ if (query?.includeSoftBlocked) q["include-soft-blocked"] = "true";
1490
+ return client.get(`${base}/ready`, { query: q });
1491
+ },
1594
1492
  async addArtifactRef(entityId, artifactKey, slot, metadata) {
1595
1493
  return client.post(`${base}/${entityId}/artifact-refs`, {
1596
1494
  artifact_key: artifactKey,
@@ -1605,366 +1503,663 @@ function _createMethods(client, base) {
1605
1503
  }
1606
1504
  };
1607
1505
  }
1608
- function createTaskMethods(client, projectId) {
1609
- return _createMethods(client, `/projects/${projectId}/tasks`);
1610
- }
1611
- function createEntityMethods(client, projectId) {
1612
- return _createMethods(client, `/projects/${projectId}/entities`);
1613
- }
1614
- function createWorkUnitMethods(client, projectId) {
1615
- return _createMethods(client, `/projects/${projectId}/work-units`);
1616
- }
1506
+ function createTaskMethods(client, projectId) {
1507
+ return _createMethods(client, `/projects/${projectId}/tasks`);
1508
+ }
1509
+ function createEntityMethods(client, projectId) {
1510
+ return _createMethods(client, `/projects/${projectId}/entities`);
1511
+ }
1512
+ function createWorkUnitMethods(client, projectId) {
1513
+ return _createMethods(client, `/projects/${projectId}/work-units`);
1514
+ }
1515
+
1516
+ // src/gates.ts
1517
+ function createGateMethods(client, projectId) {
1518
+ const base = `/projects/${projectId}/gates`;
1519
+ return {
1520
+ /** List gates with optional filters. GET /projects/:id/gates */
1521
+ async list(query) {
1522
+ return client.get(base, { query });
1523
+ },
1524
+ /** Create a new gate. POST /projects/:id/gates */
1525
+ async create(req) {
1526
+ return client.post(base, req);
1527
+ },
1528
+ /** Resolve a gate. POST /projects/:id/gates/:gateId/resolve */
1529
+ async resolve(gateId, req) {
1530
+ return client.post(`${base}/${gateId}/resolve`, req ?? {});
1531
+ },
1532
+ /** Delete a gate. DELETE /projects/:id/gates/:gateId */
1533
+ async remove(gateId) {
1534
+ return client.delete(`${base}/${gateId}`);
1535
+ }
1536
+ };
1537
+ }
1538
+
1539
+ // src/journal.ts
1540
+ function createJournalMethods(client, projectId) {
1541
+ const base = `/projects/${projectId}/journal`;
1542
+ return {
1543
+ async query(opts) {
1544
+ return client.get(base, {
1545
+ query: {
1546
+ resource: opts?.resource,
1547
+ kind: opts?.kind,
1548
+ after_seq: opts?.after_seq,
1549
+ limit: opts?.limit
1550
+ }
1551
+ });
1552
+ }
1553
+ };
1554
+ }
1555
+
1556
+ // src/presence.ts
1557
+ function createPresenceMethods(client, projectId) {
1558
+ const base = `/projects/${projectId}/presence`;
1559
+ return {
1560
+ async heartbeat(machine, info) {
1561
+ return client.post(
1562
+ `${base}/heartbeat`,
1563
+ {
1564
+ machine,
1565
+ info: info ?? {}
1566
+ }
1567
+ );
1568
+ },
1569
+ async list() {
1570
+ return client.get(base);
1571
+ },
1572
+ /**
1573
+ * List all presence records across all machines, including whether each is active.
1574
+ * Hits GET /projects/:projectId/presence/all
1575
+ */
1576
+ async listAll() {
1577
+ return client.get(`${base}/all`);
1578
+ }
1579
+ };
1580
+ }
1581
+
1582
+ // src/records.ts
1583
+ function encodeKey(key) {
1584
+ return key.split("/").map(encodeURIComponent).join("/");
1585
+ }
1586
+ function createRecordMethods(client, projectId) {
1587
+ const base = `/projects/${projectId}/records`;
1588
+ return {
1589
+ async create(type, req) {
1590
+ return client.post(`${base}/${type}`, req);
1591
+ },
1592
+ async set(type, key, req) {
1593
+ return client.put(
1594
+ `${base}/${type}/${encodeKey(key)}`,
1595
+ req
1596
+ );
1597
+ },
1598
+ async get(type, key) {
1599
+ return client.get(`${base}/${type}/${encodeKey(key)}`);
1600
+ },
1601
+ async patch(type, key, req) {
1602
+ return client.patch(
1603
+ `${base}/${type}/${encodeKey(key)}`,
1604
+ req
1605
+ );
1606
+ },
1607
+ async archive(type, key, req) {
1608
+ return client.post(
1609
+ `${base}/${type}/~/archive/${encodeKey(key)}`,
1610
+ req
1611
+ );
1612
+ },
1613
+ async unarchive(type, key, req) {
1614
+ return client.post(
1615
+ `${base}/${type}/~/unarchive/${encodeKey(key)}`,
1616
+ req
1617
+ );
1618
+ },
1619
+ async history(type, key, opts) {
1620
+ const query = {};
1621
+ if (opts?.limit !== void 0) query.limit = String(opts.limit);
1622
+ if (opts?.values !== void 0) query.values = String(opts.values);
1623
+ return client.get(
1624
+ `${base}/${type}/~/history/${encodeKey(key)}`,
1625
+ { query }
1626
+ );
1627
+ },
1628
+ async list(type, query) {
1629
+ const { tagFilter, ...rest } = query ?? {};
1630
+ const q = { ...rest };
1631
+ if (tagFilter?.length) q.tag_filter = tagFilter.join(",");
1632
+ return client.get(`${base}/${type}`, { query: q });
1633
+ },
1634
+ async types() {
1635
+ return client.get(`${base}/_types`);
1636
+ },
1637
+ async typesInUse() {
1638
+ const raw = await client.get(`${base}/_types`);
1639
+ return { ok: true, types: raw.in_use_types ?? [] };
1640
+ }
1641
+ };
1642
+ }
1643
+
1644
+ // src/schema.ts
1645
+ function createSchemaMethods(client, projectId) {
1646
+ const base = `/projects/${projectId}/schema`;
1647
+ return {
1648
+ async get() {
1649
+ return client.get(base);
1650
+ },
1651
+ async apply(schema, strategy) {
1652
+ const definition = typeof schema === "string" ? schema : JSON.stringify(schema);
1653
+ return client.post(base, { definition, strategy });
1654
+ },
1655
+ async history(opts) {
1656
+ return client.get(`${base}/history`, { query: opts });
1657
+ }
1658
+ };
1659
+ }
1660
+
1661
+ // src/search.ts
1662
+ function createSearchMethods(client, projectId) {
1663
+ const base = `/projects/${projectId}`;
1664
+ return {
1665
+ async search(q, opts) {
1666
+ const query = { q };
1667
+ if (opts?.limit !== void 0) query.limit = String(opts.limit);
1668
+ if (opts?.tagFilter?.length) query.tag_filter = opts.tagFilter.join(",");
1669
+ return client.get(`${base}/search`, { query });
1670
+ }
1671
+ };
1672
+ }
1673
+
1674
+ // src/signals.ts
1675
+ function createSignalMethods(client, projectId) {
1676
+ const base = `/projects/${projectId}/signals`;
1677
+ return {
1678
+ /** Fetch the signal inbox for the current token. GET /projects/:id/signals */
1679
+ async inbox() {
1680
+ return client.get(base);
1681
+ },
1682
+ /** Send a signal to a target. POST /projects/:id/signals/send */
1683
+ async send(req) {
1684
+ return client.post(`${base}/send`, req);
1685
+ },
1686
+ /** Acknowledge a signal. POST /projects/:id/signals/:signalId/ack */
1687
+ async ack(signalId) {
1688
+ return client.post(`${base}/${signalId}/ack`, {});
1689
+ }
1690
+ };
1691
+ }
1692
+
1693
+ // src/summary.ts
1694
+ function createSummaryMethods(client, projectId) {
1695
+ return {
1696
+ /** Get project summary. GET /projects/:id/summary */
1697
+ async get() {
1698
+ return client.get(`/projects/${projectId}/summary`);
1699
+ }
1700
+ };
1701
+ }
1702
+
1703
+ // src/templates.ts
1704
+ function createTemplateMethods(client, projectId) {
1705
+ const base = `/projects/${projectId}/templates`;
1706
+ return {
1707
+ /** Instantiate an entity template. POST /projects/:id/templates/instantiate */
1708
+ async instantiate(req) {
1709
+ return client.post(
1710
+ `${base}/instantiate`,
1711
+ req
1712
+ );
1713
+ },
1714
+ /** List available templates from the project schema. GET /projects/:id/templates */
1715
+ async list() {
1716
+ return client.get(base);
1717
+ }
1718
+ };
1719
+ }
1617
1720
 
1618
- // src/claims.ts
1619
- function createClaimMethods(client, projectId) {
1620
- const base = `/projects/${projectId}/claims`;
1721
+ // src/tokens.ts
1722
+ function createTokenMethods(client) {
1723
+ const base = "/api/tokens";
1621
1724
  return {
1622
- async acquire(resource, mode, ttlMs, opts) {
1623
- return client.post(`${base}/acquire`, {
1624
- resource,
1625
- mode,
1626
- ttl_ms: ttlMs,
1627
- ...opts
1628
- });
1629
- },
1630
- async renew(resource, fence, ttlMs) {
1631
- return client.post(`${base}/renew`, {
1632
- resource,
1633
- fence,
1634
- ttl_ms: ttlMs
1635
- });
1725
+ async issue(name, note) {
1726
+ return client.post(base, { name, note });
1636
1727
  },
1637
- async release(resource, fence) {
1638
- return client.post(`${base}/release`, {
1639
- resource,
1640
- fence
1641
- });
1728
+ async revoke(name) {
1729
+ return client.delete(
1730
+ `${base}/${encodeURIComponent(name)}`
1731
+ );
1642
1732
  },
1643
1733
  async list() {
1644
1734
  return client.get(base);
1645
- },
1646
- async get(resource) {
1647
- return client.get(
1648
- `${base}/${encodeURIComponent(resource)}`
1649
- );
1650
1735
  }
1651
1736
  };
1652
1737
  }
1653
1738
 
1654
- // src/artifacts.ts
1655
- function createArtifactMethods(client, projectId) {
1656
- const base = `/projects/${projectId}/artifacts`;
1657
- return {
1658
- upload: Object.assign(
1659
- function upload(input, opts) {
1660
- if (input instanceof ReadableStream) {
1661
- if (!opts.mimeType) {
1662
- throw new TypeError(
1663
- "mimeType is required when uploading a ReadableStream. Pass opts.mimeType explicitly."
1664
- );
1665
- }
1666
- return new Response(input).arrayBuffer().then((bytes) => {
1667
- const uploadFile = new Blob([bytes], {
1668
- type: opts.mimeType
1669
- });
1670
- const formData2 = new FormData();
1671
- formData2.append("file", uploadFile);
1672
- formData2.append("kind", opts.kind);
1673
- formData2.append("mime_type", opts.mimeType);
1674
- if (opts.resource) formData2.append("resource", opts.resource);
1675
- if (opts.fence !== void 0)
1676
- formData2.append("fence", String(opts.fence));
1677
- if (opts.flavor) formData2.append("flavor", opts.flavor);
1678
- return client.postFormData(base, formData2);
1679
- });
1680
- }
1681
- const contentType = opts.mimeType || (input instanceof File ? input.type : "") || "";
1682
- if (!contentType) {
1683
- throw new TypeError(
1684
- "contentType is required for uploads when file.type is absent. Pass opts.mimeType explicitly."
1685
- );
1739
+ // src/version.ts
1740
+ var SDK_VERSION = "0.2.0";
1741
+
1742
+ // src/client.ts
1743
+ var TilaClient = class _TilaClient {
1744
+ baseUrl;
1745
+ token;
1746
+ validate;
1747
+ timeoutMs;
1748
+ extraHeaders;
1749
+ constructor(opts) {
1750
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
1751
+ this.token = opts.token;
1752
+ this.validate = opts.validate ?? false;
1753
+ this.timeoutMs = opts.timeoutMs ?? 3e4;
1754
+ this.extraHeaders = {
1755
+ "X-Tila-Source": `sdk/${SDK_VERSION}`,
1756
+ ...opts.extraHeaders
1757
+ };
1758
+ }
1759
+ /**
1760
+ * Creates an AbortSignal that fires after this.timeoutMs.
1761
+ * Uses AbortSignal.timeout() when available (Node 18.8+, Bun 0.5+, browsers),
1762
+ * falls back to manual setTimeout + AbortController for older runtimes.
1763
+ *
1764
+ * Note: Cloudflare Workers has supported AbortSignal.timeout() since 2023;
1765
+ * the fallback branch will never execute there.
1766
+ */
1767
+ createAbortSignal() {
1768
+ if (typeof AbortSignal.timeout === "function") {
1769
+ return AbortSignal.timeout(this.timeoutMs);
1770
+ }
1771
+ const controller = new AbortController();
1772
+ setTimeout(
1773
+ () => controller.abort(
1774
+ new DOMException(
1775
+ "The operation was aborted due to timeout",
1776
+ "TimeoutError"
1777
+ )
1778
+ ),
1779
+ this.timeoutMs
1780
+ );
1781
+ return controller.signal;
1782
+ }
1783
+ static fromConfig(config, token, opts) {
1784
+ if (config.backend === "local") {
1785
+ throw new Error(
1786
+ `Cannot create an HTTP TilaClient for a local backend (backend = "local"). The local backend runs in-process on SQLite \u2014 use createTila(config) (which routes to the in-process backend) or import createTilaLocal from 'tila-sdk/local' directly.`
1787
+ );
1788
+ }
1789
+ if (!config.worker_url) {
1790
+ throw new Error(
1791
+ `Cannot create TilaClient: config has no worker_url. Use 'tila project create' or set backend = "cloudflare" in .tila/config.toml.`
1792
+ );
1793
+ }
1794
+ return new _TilaClient({
1795
+ baseUrl: config.worker_url,
1796
+ token,
1797
+ // Optional caller attribution (e.g. mcp-server/<version>). When omitted,
1798
+ // the constructor's default X-Tila-Source (sdk/<version>) applies.
1799
+ ...opts?.extraHeaders ? { extraHeaders: opts.extraHeaders } : {}
1800
+ });
1801
+ }
1802
+ async request(method, path, opts) {
1803
+ const url = new URL(path, `${this.baseUrl}/`);
1804
+ if (opts?.query) {
1805
+ for (const [key, value] of Object.entries(opts.query)) {
1806
+ if (value !== void 0) {
1807
+ url.searchParams.set(key, value);
1686
1808
  }
1687
- const formData = new FormData();
1688
- formData.append("file", input);
1689
- formData.append("kind", opts.kind);
1690
- formData.append("mime_type", contentType);
1691
- if (opts.resource) formData.append("resource", opts.resource);
1692
- if (opts.fence !== void 0)
1693
- formData.append("fence", String(opts.fence));
1694
- if (opts.flavor) formData.append("flavor", opts.flavor);
1695
- return client.postFormData(base, formData);
1696
- },
1697
- {}
1698
- ),
1699
- async download(key) {
1700
- const res = await client.requestRaw(
1701
- "GET",
1702
- `${base}/${encodeURIComponent(key)}`
1809
+ }
1810
+ }
1811
+ const headers = {
1812
+ Authorization: `Bearer ${this.token}`,
1813
+ Accept: "application/json",
1814
+ ...this.extraHeaders
1815
+ };
1816
+ const init = {
1817
+ method,
1818
+ headers,
1819
+ signal: this.createAbortSignal()
1820
+ };
1821
+ if (opts?.body !== void 0) {
1822
+ headers["Content-Type"] = "application/json";
1823
+ init.body = JSON.stringify(opts.body);
1824
+ }
1825
+ let res;
1826
+ try {
1827
+ res = await fetch(url.toString(), init);
1828
+ } catch (err) {
1829
+ if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
1830
+ throw new Error(
1831
+ `Request to ${url.origin} timed out after ${this.timeoutMs}ms`
1832
+ );
1833
+ }
1834
+ throw new Error(
1835
+ `Network error connecting to ${url.origin}: ${err instanceof Error ? err.message : String(err)}`
1703
1836
  );
1704
- return {
1705
- body: res.body ?? new ReadableStream(),
1706
- contentType: res.headers.get("content-type") || "application/octet-stream",
1707
- contentLength: res.headers.has("content-length") ? Number(res.headers.get("content-length")) : null
1708
- };
1709
- },
1710
- async list(query) {
1711
- return client.get(base, { query });
1712
- },
1713
- async search(q, opts) {
1714
- return client.get(`${base}/search`, {
1715
- query: { q, ...opts }
1716
- });
1717
- },
1718
- async grep(pattern, opts) {
1719
- const query = { pattern };
1720
- if (opts?.kind) query.kind = opts.kind;
1721
- if (opts?.resource) query.resource = opts.resource;
1722
- if (opts?.regex) query.regex = "true";
1723
- if (opts?.limit != null) query.limit = String(opts.limit);
1724
- return client.get(`${base}/grep`, { query });
1725
- },
1726
- async addRelationship(fromKey, toKeyOrUri, type, metadata) {
1727
- const isUri = toKeyOrUri.includes("://");
1728
- return client.post(
1729
- `${base}/${encodeURIComponent(fromKey)}/relationships`,
1730
- {
1731
- [isUri ? "to_uri" : "to_key"]: toKeyOrUri,
1732
- type,
1733
- metadata
1837
+ }
1838
+ if (!res.ok) {
1839
+ await this.throwApiError(res);
1840
+ }
1841
+ const body = await res.json();
1842
+ const shouldValidate = opts?.validate ?? this.validate;
1843
+ if (shouldValidate && opts?.schema) {
1844
+ const result = opts.schema.safeParse(body);
1845
+ if (!result.success) {
1846
+ const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
1847
+ throw new Error(
1848
+ `Unexpected response shape from ${method} ${path}:
1849
+ ${issues}`
1850
+ );
1851
+ }
1852
+ return result.data;
1853
+ }
1854
+ return body;
1855
+ }
1856
+ async get(path, opts) {
1857
+ return this.request("GET", path, {
1858
+ schema: opts?.schema,
1859
+ query: opts?.query,
1860
+ validate: opts?.validate
1861
+ });
1862
+ }
1863
+ async post(path, body, opts) {
1864
+ return this.request("POST", path, {
1865
+ body,
1866
+ schema: opts?.schema,
1867
+ validate: opts?.validate
1868
+ });
1869
+ }
1870
+ async put(path, body, opts) {
1871
+ return this.request("PUT", path, {
1872
+ body,
1873
+ schema: opts?.schema,
1874
+ validate: opts?.validate
1875
+ });
1876
+ }
1877
+ async patch(path, body, opts) {
1878
+ return this.request("PATCH", path, {
1879
+ body,
1880
+ schema: opts?.schema,
1881
+ validate: opts?.validate
1882
+ });
1883
+ }
1884
+ async delete(path, opts) {
1885
+ return this.request("DELETE", path, {
1886
+ schema: opts?.schema,
1887
+ validate: opts?.validate
1888
+ });
1889
+ }
1890
+ async requestRaw(method, path, opts) {
1891
+ const url = new URL(path, `${this.baseUrl}/`);
1892
+ if (opts?.query) {
1893
+ for (const [key, value] of Object.entries(opts.query)) {
1894
+ if (value !== void 0) {
1895
+ url.searchParams.set(key, value);
1734
1896
  }
1735
- );
1736
- },
1737
- async listRelationships(key) {
1738
- return client.get(
1739
- `${base}/${encodeURIComponent(key)}/relationships`
1740
- );
1741
- },
1742
- async getLatest(kind, resource) {
1743
- const res = await client.requestRaw("GET", `${base}/latest`, {
1744
- query: { kind, resource }
1897
+ }
1898
+ }
1899
+ const headers = {
1900
+ Authorization: `Bearer ${this.token}`,
1901
+ ...this.extraHeaders
1902
+ };
1903
+ let res;
1904
+ try {
1905
+ res = await fetch(url.toString(), {
1906
+ method,
1907
+ headers,
1908
+ signal: this.createAbortSignal()
1745
1909
  });
1746
- if (res.status === 404) return null;
1747
- if (!res.ok) {
1748
- const body2 = await res.json().catch(() => ({}));
1910
+ } catch (err) {
1911
+ if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
1749
1912
  throw new Error(
1750
- `getLatest failed with status ${res.status}: ${JSON.stringify(body2)}`
1913
+ `Request to ${url.origin} timed out after ${this.timeoutMs}ms`
1751
1914
  );
1752
1915
  }
1753
- const body = await res.json();
1754
- return body.pointer;
1755
- },
1756
- async writeText(content, opts) {
1757
- return client.post(`${base}/text`, {
1758
- content,
1759
- kind: opts.kind,
1760
- mime_type: opts.mimeType ?? "text/markdown",
1761
- resource: opts.resource,
1762
- fence: opts.fence
1763
- });
1764
- },
1765
- async readText(key) {
1766
- const res = await client.requestRaw(
1767
- "GET",
1768
- `${base}/${encodeURIComponent(key)}`
1916
+ throw new Error(
1917
+ `Network error connecting to ${url.origin}: ${err instanceof Error ? err.message : String(err)}`
1769
1918
  );
1770
- const contentType = res.headers.get("content-type") || "application/octet-stream";
1771
- if (!contentType.startsWith("text/")) {
1772
- throw new TypeError(
1773
- `Artifact ${key} has MIME type ${contentType} \u2014 readText only supports text/* artifacts`
1919
+ }
1920
+ if (!res.ok) {
1921
+ await this.throwApiError(res);
1922
+ }
1923
+ return res;
1924
+ }
1925
+ async postFormData(path, formData, opts) {
1926
+ const url = new URL(path, `${this.baseUrl}/`);
1927
+ const headers = {
1928
+ Authorization: `Bearer ${this.token}`,
1929
+ Accept: "application/json",
1930
+ ...this.extraHeaders
1931
+ };
1932
+ let res;
1933
+ try {
1934
+ res = await fetch(url.toString(), {
1935
+ method: "POST",
1936
+ headers,
1937
+ body: formData,
1938
+ signal: this.createAbortSignal()
1939
+ });
1940
+ } catch (err) {
1941
+ if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
1942
+ throw new Error(
1943
+ `Request to ${url.origin} timed out after ${this.timeoutMs}ms`
1774
1944
  );
1775
1945
  }
1776
- const text = await res.text();
1777
- return { content: text, mimeType: contentType };
1778
- }
1779
- };
1780
- }
1781
-
1782
- // src/tokens.ts
1783
- function createTokenMethods(client) {
1784
- const base = "/api/tokens";
1785
- return {
1786
- async issue(name, note) {
1787
- return client.post(base, { name, note });
1788
- },
1789
- async revoke(name) {
1790
- return client.delete(
1791
- `${base}/${encodeURIComponent(name)}`
1946
+ throw new Error(
1947
+ `Network error connecting to ${url.origin}: ${err instanceof Error ? err.message : String(err)}`
1792
1948
  );
1793
- },
1794
- async list() {
1795
- return client.get(base);
1796
1949
  }
1797
- };
1798
- }
1799
-
1800
- // src/journal.ts
1801
- function createJournalMethods(client, projectId) {
1802
- const base = `/projects/${projectId}/journal`;
1803
- return {
1804
- async query(opts) {
1805
- return client.get(base, { query: opts });
1950
+ if (!res.ok) {
1951
+ await this.throwApiError(res);
1806
1952
  }
1807
- };
1808
- }
1809
-
1810
- // src/presence.ts
1811
- function createPresenceMethods(client, projectId) {
1812
- const base = `/projects/${projectId}/presence`;
1813
- return {
1814
- async heartbeat(machine, ttlMs) {
1815
- return client.post(base, {
1816
- machine,
1817
- ttl_ms: ttlMs
1818
- });
1819
- },
1820
- async list() {
1821
- return client.get(base);
1822
- },
1823
- /**
1824
- * List all presence records across all machines, including whether each is active.
1825
- * Hits GET /projects/:projectId/presence/all
1826
- */
1827
- async listAll() {
1828
- return client.get(`${base}/all`);
1953
+ const body = await res.json();
1954
+ const shouldValidate = opts?.validate ?? this.validate;
1955
+ if (shouldValidate && opts?.schema) {
1956
+ const result = opts.schema.safeParse(body);
1957
+ if (!result.success) {
1958
+ const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
1959
+ throw new Error(
1960
+ `Unexpected response shape from POST ${path}:
1961
+ ${issues}`
1962
+ );
1963
+ }
1964
+ return result.data;
1829
1965
  }
1830
- };
1831
- }
1832
-
1833
- // src/records.ts
1834
- function encodeKey(key) {
1835
- return key.split("/").map(encodeURIComponent).join("/");
1966
+ return body;
1967
+ }
1968
+ async throwApiError(res) {
1969
+ try {
1970
+ const body = await res.json();
1971
+ const parsed = ErrorEnvelopeSchema.safeParse(body);
1972
+ if (parsed.success) {
1973
+ const { code, message, retryable } = parsed.data.error;
1974
+ throw new TilaApiError(res.status, code, message, retryable);
1975
+ }
1976
+ } catch (err) {
1977
+ if (err instanceof TilaApiError) throw err;
1978
+ }
1979
+ throw new TilaApiError(
1980
+ res.status,
1981
+ "UNKNOWN",
1982
+ `HTTP ${res.status}: ${res.statusText}`,
1983
+ false
1984
+ );
1985
+ }
1986
+ };
1987
+ var TilaApiError = class extends Error {
1988
+ constructor(status, code, message, retryable) {
1989
+ super(message);
1990
+ this.status = status;
1991
+ this.code = code;
1992
+ this.retryable = retryable;
1993
+ this.name = "TilaApiError";
1994
+ }
1995
+ status;
1996
+ code;
1997
+ retryable;
1998
+ };
1999
+ function isTilaApiError(err) {
2000
+ return err instanceof TilaApiError;
1836
2001
  }
1837
- function createRecordMethods(client, projectId) {
1838
- const base = `/projects/${projectId}/records`;
1839
- return {
1840
- async create(type, req) {
1841
- return client.post(`${base}/${type}`, req);
1842
- },
1843
- async set(type, key, req) {
1844
- return client.put(
1845
- `${base}/${type}/${encodeKey(key)}`,
1846
- req
1847
- );
1848
- },
1849
- async get(type, key) {
1850
- return client.get(`${base}/${type}/${encodeKey(key)}`);
1851
- },
1852
- async patch(type, key, req) {
1853
- return client.patch(
1854
- `${base}/${type}/${encodeKey(key)}`,
1855
- req
1856
- );
1857
- },
1858
- async archive(type, key, req) {
1859
- return client.post(
1860
- `${base}/${type}/~/archive/${encodeKey(key)}`,
1861
- req
1862
- );
1863
- },
1864
- async unarchive(type, key, req) {
1865
- return client.post(
1866
- `${base}/${type}/~/unarchive/${encodeKey(key)}`,
1867
- req
1868
- );
1869
- },
1870
- async history(type, key, opts) {
1871
- const query = {};
1872
- if (opts?.limit !== void 0) query.limit = String(opts.limit);
1873
- if (opts?.values !== void 0) query.values = String(opts.values);
1874
- return client.get(
1875
- `${base}/${type}/~/history/${encodeKey(key)}`,
1876
- { query }
1877
- );
1878
- },
1879
- async list(type, query) {
1880
- return client.get(`${base}/${type}`, { query });
1881
- },
1882
- async types() {
1883
- return client.get(`${base}/_types`);
1884
- },
1885
- async typesInUse() {
1886
- const raw = await client.get(`${base}/_types`);
1887
- return { ok: true, types: raw.in_use_types ?? [] };
2002
+ async function exchangeGitHubToken(baseUrl, projectId, githubToken) {
2003
+ const url = `${baseUrl.replace(/\/+$/, "")}/api/auth/github/exchange`;
2004
+ let res;
2005
+ try {
2006
+ res = await fetch(url, {
2007
+ method: "POST",
2008
+ headers: { "Content-Type": "application/json" },
2009
+ body: JSON.stringify({
2010
+ project_id: projectId,
2011
+ github_token: githubToken
2012
+ })
2013
+ });
2014
+ } catch (err) {
2015
+ throw new Error(
2016
+ `Network error during GitHub token exchange: ${err instanceof Error ? err.message : String(err)}`
2017
+ );
2018
+ }
2019
+ if (!res.ok) {
2020
+ try {
2021
+ const body2 = await res.json();
2022
+ const parsed = ErrorEnvelopeSchema.safeParse(body2);
2023
+ if (parsed.success) {
2024
+ const { code, message, retryable } = parsed.data.error;
2025
+ throw new TilaApiError(res.status, code, message, retryable);
2026
+ }
2027
+ } catch (err) {
2028
+ if (err instanceof TilaApiError) throw err;
1888
2029
  }
1889
- };
1890
- }
1891
-
1892
- // src/schema.ts
1893
- function createSchemaMethods(client, projectId) {
1894
- const base = `/projects/${projectId}/schema`;
2030
+ throw new TilaApiError(
2031
+ res.status,
2032
+ "UNKNOWN",
2033
+ `HTTP ${res.status}: ${res.statusText}`,
2034
+ false
2035
+ );
2036
+ }
2037
+ const body = await res.json();
2038
+ if (!body.session_token || typeof body.expires_at !== "number") {
2039
+ throw new TypeError(
2040
+ "Exchange returned unexpected response shape: missing session_token or expires_at"
2041
+ );
2042
+ }
1895
2043
  return {
1896
- async get() {
1897
- return client.get(base);
1898
- },
1899
- async apply(schema, strategy) {
1900
- return client.post(`${base}/apply`, { schema, strategy });
1901
- },
1902
- async history(opts) {
1903
- return client.get(`${base}/history`, { query: opts });
1904
- }
2044
+ sessionToken: body.session_token,
2045
+ expiresAt: body.expires_at,
2046
+ permission: body.permission ?? "read"
1905
2047
  };
1906
2048
  }
1907
-
1908
- // src/signals.ts
1909
- function createSignalMethods(client, projectId) {
1910
- const base = `/projects/${projectId}/signals`;
2049
+ function buildHttpFacade(client, projectId) {
1911
2050
  return {
1912
- /** Fetch the signal inbox for the current token. GET /projects/:id/signals */
1913
- async inbox() {
1914
- return client.get(base);
1915
- },
1916
- /** Send a signal to a target. POST /projects/:id/signals/send */
1917
- async send(req) {
1918
- return client.post(`${base}/send`, req);
1919
- },
1920
- /** Acknowledge a signal. POST /projects/:id/signals/:signalId/ack */
1921
- async ack(signalId) {
1922
- return client.post(`${base}/${signalId}/ack`, {});
2051
+ tasks: createTaskMethods(client, projectId),
2052
+ records: createRecordMethods(client, projectId),
2053
+ claims: createClaimMethods(client, projectId),
2054
+ artifacts: createArtifactMethods(client, projectId),
2055
+ gates: createGateMethods(client, projectId),
2056
+ signals: createSignalMethods(client, projectId),
2057
+ journal: createJournalMethods(client, projectId),
2058
+ presence: createPresenceMethods(client, projectId),
2059
+ schema: createSchemaMethods(client, projectId),
2060
+ summary: createSummaryMethods(client, projectId),
2061
+ search: createSearchMethods(client, projectId),
2062
+ templates: createTemplateMethods(client, projectId),
2063
+ tokens: createTokenMethods(client),
2064
+ close: () => {
1923
2065
  }
1924
2066
  };
1925
2067
  }
1926
-
1927
- // src/gates.ts
1928
- function createGateMethods(client, projectId) {
1929
- const base = `/projects/${projectId}/gates`;
1930
- return {
1931
- /** List gates with optional filters. GET /projects/:id/gates */
1932
- async list(query) {
1933
- return client.get(base, { query });
1934
- },
1935
- /** Create a new gate. POST /projects/:id/gates */
1936
- async create(req) {
1937
- return client.post(base, req);
1938
- },
1939
- /** Resolve a gate. POST /projects/:id/gates/:gateId/resolve */
1940
- async resolve(gateId, req) {
1941
- return client.post(`${base}/${gateId}/resolve`, req ?? {});
1942
- },
1943
- /** Delete a gate. DELETE /projects/:id/gates/:gateId */
1944
- async remove(gateId) {
1945
- return client.delete(`${base}/${gateId}`);
2068
+ async function createTila(config, token, opts) {
2069
+ if (config.backend === "local") {
2070
+ if (!config.local) {
2071
+ throw new Error(
2072
+ 'createTila: backend = "local" requires a [local] config section with db_path and artifacts_path.'
2073
+ );
1946
2074
  }
1947
- };
2075
+ const { createTilaLocal, buildLocalResources } = await import('./local.js');
2076
+ const { project, artifacts, close } = await createTilaLocal({
2077
+ dbPath: config.local.db_path,
2078
+ artifactsPath: config.local.artifacts_path,
2079
+ org: config.local.org,
2080
+ project: config.project_id
2081
+ });
2082
+ const resources = buildLocalResources(project, artifacts);
2083
+ return { ...resources, close };
2084
+ }
2085
+ if (token === void 0) {
2086
+ throw new Error(
2087
+ 'createTila: the Cloudflare backend requires a token. Pass createTila(config, token), or set backend = "local".'
2088
+ );
2089
+ }
2090
+ const client = TilaClient.fromConfig(config, token, {
2091
+ extraHeaders: opts?.extraHeaders
2092
+ });
2093
+ return buildHttpFacade(client, config.project_id);
1948
2094
  }
1949
2095
 
1950
- // src/templates.ts
1951
- function createTemplateMethods(client, projectId) {
1952
- const base = `/projects/${projectId}/templates`;
1953
- return {
1954
- /** Instantiate an entity template. POST /projects/:id/templates/instantiate */
1955
- async instantiate(req) {
1956
- return client.post(
1957
- `${base}/instantiate`,
1958
- req
1959
- );
1960
- },
1961
- /** List available templates from the project schema. GET /projects/:id/templates */
1962
- async list() {
1963
- return client.get(base);
2096
+ // src/retry.ts
2097
+ async function withRetry(fn, opts) {
2098
+ const maxRetries = opts?.maxRetries ?? 3;
2099
+ const baseDelayMs = opts?.baseDelayMs ?? 200;
2100
+ const maxDelayMs = opts?.maxDelayMs ?? 3e4;
2101
+ const jitter = opts?.jitter ?? true;
2102
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
2103
+ try {
2104
+ return await fn();
2105
+ } catch (err) {
2106
+ if (isTilaApiError(err) && err.retryable === false) {
2107
+ throw err;
2108
+ }
2109
+ if (attempt === maxRetries) {
2110
+ throw err;
2111
+ }
2112
+ const cap = Math.min(maxDelayMs, baseDelayMs * 2 ** attempt);
2113
+ const sleepMs = jitter ? Math.random() * cap : cap;
2114
+ await new Promise((resolve) => setTimeout(resolve, sleepMs));
1964
2115
  }
1965
- };
2116
+ }
2117
+ throw new Error("withRetry: unreachable");
1966
2118
  }
1967
2119
 
2120
+ // src/error-codes.ts
2121
+ var TILA_ERRORS = {
2122
+ // Auth / middleware (worker layer — SCREAMING_SNAKE_CASE wire values)
2123
+ UNAUTHORIZED: "UNAUTHORIZED",
2124
+ SESSION_EXPIRED: "SESSION_EXPIRED",
2125
+ RATE_LIMITED: "RATE_LIMITED",
2126
+ PERMISSION_DENIED: "PERMISSION_DENIED",
2127
+ PROJECT_MISMATCH: "PROJECT_MISMATCH",
2128
+ CSRF_MISSING_ORIGIN: "CSRF_MISSING_ORIGIN",
2129
+ CSRF_ORIGIN_MISMATCH: "CSRF_ORIGIN_MISMATCH",
2130
+ INTERNAL_ERROR: "INTERNAL_ERROR",
2131
+ DO_UNREACHABLE: "do-unreachable",
2132
+ // Auth endpoint specific
2133
+ REPO_NOT_ALLOWED: "REPO_NOT_ALLOWED",
2134
+ GITHUB_AUTH_FAILED: "GITHUB_AUTH_FAILED",
2135
+ HMAC_NOT_CONFIGURED: "HMAC_NOT_CONFIGURED",
2136
+ // Token endpoint specific
2137
+ TOKEN_NAME_CONFLICT: "TOKEN_NAME_CONFLICT",
2138
+ TOKEN_AUTHZ_DENIED: "TOKEN_AUTHZ_DENIED",
2139
+ TOKEN_NOT_FOUND: "TOKEN_NOT_FOUND",
2140
+ // Validation (worker layer uses SCREAMING_SNAKE for this code)
2141
+ VALIDATION_ERROR: "VALIDATION_ERROR",
2142
+ // DO errors (project-do-router — kebab-case wire values)
2143
+ STALE_FENCE: "stale-fence",
2144
+ NOT_FOUND: "not-found",
2145
+ GATE_ALREADY_SETTLED: "gate-already-settled",
2146
+ NO_FENCE: "no-fence",
2147
+ INTERNAL: "internal",
2148
+ CONSTRAINT_VIOLATION: "constraint-violation",
2149
+ IDEMPOTENCY_KEY_CONFLICT: "idempotency-key-conflict",
2150
+ // DO-layer validation uses kebab-case (distinct from VALIDATION_ERROR above)
2151
+ VALIDATION_ERROR_DO: "validation-error",
2152
+ ALREADY_HELD: "already-held",
2153
+ RENEW_FAILED: "renew-failed",
2154
+ BAD_REQUEST: "bad-request",
2155
+ MISSING_QUERY: "missing-query",
2156
+ INVALID_QUERY: "invalid-query",
2157
+ INVALID_SLOT: "invalid-slot",
2158
+ INVALID_RELATIONSHIP_TYPE: "invalid-relationship-type",
2159
+ // Fallback (SDK-generated when response is unparseable)
2160
+ UNKNOWN: "UNKNOWN"
2161
+ };
2162
+
1968
2163
  // src/indexes.ts
1969
2164
  function createIndexMethods(client, projectId) {
1970
2165
  const base = `/projects/${projectId}/artifacts`;
@@ -2007,26 +2202,240 @@ function createIndexMethods(client, projectId) {
2007
2202
  }
2008
2203
  };
2009
2204
  }
2010
-
2011
- // src/summary.ts
2012
- function createSummaryMethods(client, projectId) {
2205
+
2206
+ // src/namespace-prefix.ts
2207
+ function validateNamespace(ns) {
2208
+ if (!/^[a-z][a-z0-9_-]*$/.test(ns)) {
2209
+ throw new TypeError(
2210
+ `Invalid namespace "${ns}": must match /^[a-z][a-z0-9_-]*$/ (lowercase letter start, then lowercase letters, digits, underscores, or hyphens).`
2211
+ );
2212
+ }
2213
+ }
2214
+ function applyPrefix(ns, name) {
2215
+ if (name.startsWith(`${ns}_`)) {
2216
+ throw new Error(
2217
+ `Namespace collision: "${name}" already starts with prefix "${ns}_". Call the raw factory if this name is intentional.`
2218
+ );
2219
+ }
2220
+ return `${ns}_${name}`;
2221
+ }
2222
+ function stripPrefix(ns, name) {
2223
+ const prefix = `${ns}_`;
2224
+ if (name.startsWith(prefix)) {
2225
+ return name.slice(prefix.length);
2226
+ }
2227
+ return name;
2228
+ }
2229
+
2230
+ // src/namespace.ts
2231
+ function namespacedTaskMethods(client, projectId, ns) {
2232
+ const inner = createTaskMethods(client, projectId);
2233
+ return {
2234
+ ...inner,
2235
+ async create(id, type, data) {
2236
+ const result = await inner.create(id, applyPrefix(ns, type), data);
2237
+ return {
2238
+ ...result,
2239
+ entity: { ...result.entity, type: stripPrefix(ns, result.entity.type) }
2240
+ };
2241
+ },
2242
+ async get(id) {
2243
+ const result = await inner.get(id);
2244
+ return {
2245
+ ...result,
2246
+ entity: { ...result.entity, type: stripPrefix(ns, result.entity.type) }
2247
+ };
2248
+ },
2249
+ async update(id, data, fence) {
2250
+ const result = await inner.update(id, data, fence);
2251
+ return {
2252
+ ...result,
2253
+ entity: { ...result.entity, type: stripPrefix(ns, result.entity.type) }
2254
+ };
2255
+ },
2256
+ async list(query) {
2257
+ const prefixedQuery = query ? {
2258
+ ...query,
2259
+ type: query.type !== void 0 ? applyPrefix(ns, query.type) : void 0
2260
+ } : void 0;
2261
+ const result = await inner.list(prefixedQuery);
2262
+ return {
2263
+ ...result,
2264
+ entities: result.entities.map((e) => ({
2265
+ ...e,
2266
+ type: stripPrefix(ns, e.type)
2267
+ }))
2268
+ };
2269
+ }
2270
+ };
2271
+ }
2272
+ function namespacedRecordMethods(client, projectId, ns) {
2273
+ const inner = createRecordMethods(client, projectId);
2274
+ function stripRecordType(result) {
2275
+ return {
2276
+ ...result,
2277
+ record: { ...result.record, type: stripPrefix(ns, result.record.type) }
2278
+ };
2279
+ }
2280
+ return {
2281
+ async create(type, req) {
2282
+ return stripRecordType(await inner.create(applyPrefix(ns, type), req));
2283
+ },
2284
+ async set(type, key, req) {
2285
+ return stripRecordType(await inner.set(applyPrefix(ns, type), key, req));
2286
+ },
2287
+ async get(type, key) {
2288
+ return stripRecordType(await inner.get(applyPrefix(ns, type), key));
2289
+ },
2290
+ async patch(type, key, req) {
2291
+ return stripRecordType(
2292
+ await inner.patch(applyPrefix(ns, type), key, req)
2293
+ );
2294
+ },
2295
+ async archive(type, key, req) {
2296
+ return stripRecordType(
2297
+ await inner.archive(applyPrefix(ns, type), key, req)
2298
+ );
2299
+ },
2300
+ async unarchive(type, key, req) {
2301
+ return stripRecordType(
2302
+ await inner.unarchive(applyPrefix(ns, type), key, req)
2303
+ );
2304
+ },
2305
+ async history(type, key, opts) {
2306
+ const result = await inner.history(applyPrefix(ns, type), key, opts);
2307
+ return {
2308
+ ...result,
2309
+ items: result.items.map((item) => ({
2310
+ ...item,
2311
+ type: stripPrefix(ns, item.type)
2312
+ }))
2313
+ };
2314
+ },
2315
+ async list(type, query) {
2316
+ const result = await inner.list(applyPrefix(ns, type), query);
2317
+ return {
2318
+ ...result,
2319
+ items: result.items.map((item) => ({
2320
+ ...item,
2321
+ type: stripPrefix(ns, item.type)
2322
+ }))
2323
+ };
2324
+ },
2325
+ async types() {
2326
+ const result = await inner.types();
2327
+ return {
2328
+ ...result,
2329
+ types: result.types.map((t) => stripPrefix(ns, t))
2330
+ };
2331
+ },
2332
+ async typesInUse() {
2333
+ const result = await inner.typesInUse();
2334
+ return {
2335
+ ...result,
2336
+ types: result.types.map((t) => stripPrefix(ns, t))
2337
+ };
2338
+ }
2339
+ };
2340
+ }
2341
+ function namespacedArtifactMethods(client, projectId, ns) {
2342
+ const inner = createArtifactMethods(client, projectId);
2343
+ return {
2344
+ ...inner,
2345
+ upload(input, opts) {
2346
+ return inner.upload(input, { ...opts, kind: applyPrefix(ns, opts.kind) });
2347
+ },
2348
+ async writeText(content, opts) {
2349
+ return inner.writeText(content, {
2350
+ ...opts,
2351
+ kind: applyPrefix(ns, opts.kind)
2352
+ });
2353
+ },
2354
+ async list(query) {
2355
+ const prefixedQuery = query ? {
2356
+ ...query,
2357
+ kind: query.kind !== void 0 ? applyPrefix(ns, query.kind) : void 0
2358
+ } : void 0;
2359
+ const result = await inner.list(prefixedQuery);
2360
+ return {
2361
+ ...result,
2362
+ pointers: result.pointers.map((p) => ({
2363
+ ...p,
2364
+ kind: stripPrefix(ns, p.kind)
2365
+ }))
2366
+ };
2367
+ },
2368
+ async search(q, opts) {
2369
+ const prefixedOpts = opts ? {
2370
+ ...opts,
2371
+ kind: opts.kind !== void 0 ? applyPrefix(ns, opts.kind) : void 0
2372
+ } : void 0;
2373
+ const result = await inner.search(q, prefixedOpts);
2374
+ return {
2375
+ ...result,
2376
+ results: result.results.map((r) => ({
2377
+ ...r,
2378
+ kind: stripPrefix(ns, r.kind)
2379
+ }))
2380
+ };
2381
+ },
2382
+ async grep(pattern, opts) {
2383
+ const prefixedOpts = opts ? {
2384
+ ...opts,
2385
+ kind: opts.kind !== void 0 ? applyPrefix(ns, opts.kind) : void 0
2386
+ } : void 0;
2387
+ const result = await inner.grep(pattern, prefixedOpts);
2388
+ return {
2389
+ ...result,
2390
+ results: result.results.map((r) => ({
2391
+ ...r,
2392
+ kind: stripPrefix(ns, r.kind)
2393
+ }))
2394
+ };
2395
+ },
2396
+ async getLatest(kind, resource) {
2397
+ let pointer;
2398
+ try {
2399
+ pointer = await inner.getLatest(applyPrefix(ns, kind), resource);
2400
+ } catch (err) {
2401
+ if (err instanceof TilaApiError && err.status === 404) return null;
2402
+ throw err;
2403
+ }
2404
+ if (pointer === null) return null;
2405
+ return { ...pointer, kind: stripPrefix(ns, pointer.kind) };
2406
+ }
2407
+ };
2408
+ }
2409
+ function namespacedTemplateMethods(client, projectId, ns) {
2410
+ const inner = createTemplateMethods(client, projectId);
2013
2411
  return {
2014
- /** Get project summary. GET /projects/:id/summary */
2015
- async get() {
2016
- return client.get(`/projects/${projectId}/summary`);
2412
+ ...inner,
2413
+ async instantiate(req) {
2414
+ return inner.instantiate({
2415
+ ...req,
2416
+ template_name: applyPrefix(ns, req.template_name)
2417
+ });
2418
+ },
2419
+ async list() {
2420
+ const result = await inner.list();
2421
+ return {
2422
+ ...result,
2423
+ templates: result.templates.map((t) => ({
2424
+ ...t,
2425
+ name: stripPrefix(ns, t.name),
2426
+ type: stripPrefix(ns, t.type)
2427
+ }))
2428
+ };
2017
2429
  }
2018
2430
  };
2019
2431
  }
2020
-
2021
- // src/search.ts
2022
- function createSearchMethods(client, projectId) {
2023
- const base = `/projects/${projectId}`;
2432
+ function createNamespace(client, projectId, ns) {
2433
+ validateNamespace(ns);
2024
2434
  return {
2025
- async search(q, opts) {
2026
- const query = { q };
2027
- if (opts?.limit !== void 0) query.limit = String(opts.limit);
2028
- return client.get(`${base}/search`, { query });
2029
- }
2435
+ tasks: namespacedTaskMethods(client, projectId, ns),
2436
+ records: namespacedRecordMethods(client, projectId, ns),
2437
+ artifacts: namespacedArtifactMethods(client, projectId, ns),
2438
+ templates: namespacedTemplateMethods(client, projectId, ns)
2030
2439
  };
2031
2440
  }
2032
2441
 
@@ -2138,5 +2547,867 @@ async function withClaim(client, projectId, resource, mode, ttlMs, callback) {
2138
2547
  }
2139
2548
  }
2140
2549
  }
2550
+ var ArtifactPointerInternalSchema = z.object({
2551
+ r2_key: z.string(),
2552
+ resource: z.string().nullable(),
2553
+ kind: z.string(),
2554
+ sha256: z.string(),
2555
+ bytes: z.number(),
2556
+ mime_type: z.string(),
2557
+ produced_at: z.number(),
2558
+ produced_by: z.string(),
2559
+ expires_at: z.number().nullable(),
2560
+ tombstoned: z.number()
2561
+ }).passthrough();
2562
+ var ArtifactListInternalSchema = z.object({
2563
+ ok: z.literal(true),
2564
+ pointers: z.array(ArtifactPointerInternalSchema)
2565
+ });
2566
+ var OkSchema = z.object({ ok: z.literal(true) }).passthrough();
2567
+ var RecordTypesInternalSchema = z.object({
2568
+ ok: z.literal(true),
2569
+ types: z.array(z.string()),
2570
+ in_use_types: z.array(z.string()).optional()
2571
+ });
2572
+ var SchemaShowResponseSchema = z.object({
2573
+ ok: z.literal(true),
2574
+ schema: z.record(z.unknown()).nullable(),
2575
+ version: z.number().int().nullable()
2576
+ });
2577
+ var SchemaApplyLenientSchema = z.object({
2578
+ ok: z.literal(true),
2579
+ version: z.number().int().nullable().optional(),
2580
+ changes: z.array(z.string()).optional(),
2581
+ noChange: z.boolean().optional()
2582
+ });
2583
+ var StateListInternalSchema = z.object({
2584
+ ok: z.literal(true),
2585
+ claims: z.array(
2586
+ z.object({
2587
+ resource: z.string(),
2588
+ machine: z.string(),
2589
+ user: z.string(),
2590
+ mode: z.enum(["exclusive", "owner", "presence"]),
2591
+ fence: z.number(),
2592
+ acquired_at: z.number(),
2593
+ expires_at: z.number(),
2594
+ metadata: z.record(z.unknown()).optional()
2595
+ })
2596
+ )
2597
+ });
2598
+ var ArtifactSearchResponseSchema2 = z.object({
2599
+ ok: z.literal(true),
2600
+ results: z.array(
2601
+ z.object({
2602
+ r2_key: z.string(),
2603
+ kind: z.string(),
2604
+ title: z.string().nullable(),
2605
+ snippet: z.string().nullable()
2606
+ }).passthrough()
2607
+ )
2608
+ });
2609
+ var RelListResponseSchema = z.object({
2610
+ ok: z.literal(true),
2611
+ relationships: z.array(
2612
+ z.object({
2613
+ from_key: z.string(),
2614
+ to_key: z.string().nullable(),
2615
+ to_uri: z.string().nullable(),
2616
+ type: z.string(),
2617
+ created_at: z.number()
2618
+ }).passthrough()
2619
+ )
2620
+ });
2621
+ var IndexEntriesResponseSchema = z.object({
2622
+ ok: z.literal(true),
2623
+ entries: z.array(
2624
+ z.object({
2625
+ r2_key: z.string(),
2626
+ resource: z.string().nullable(),
2627
+ kind: z.string(),
2628
+ sha256: z.string(),
2629
+ bytes: z.number(),
2630
+ mime_type: z.string(),
2631
+ produced_at: z.number(),
2632
+ produced_by: z.string(),
2633
+ expires_at: z.number().nullable(),
2634
+ tombstoned: z.number(),
2635
+ exists: z.boolean()
2636
+ })
2637
+ )
2638
+ });
2639
+ var RemoteBackend = class {
2640
+ constructor(client, projectId) {
2641
+ this.client = client;
2642
+ this.projectId = projectId;
2643
+ }
2644
+ client;
2645
+ projectId;
2646
+ // --- EntityBackend ---
2647
+ async create(input) {
2648
+ const body = {
2649
+ id: input.id,
2650
+ type: input.type,
2651
+ data: input.data,
2652
+ created_by: input.created_by
2653
+ };
2654
+ if (input.tags !== void 0) body.tags = input.tags;
2655
+ const result = await this.client.post(
2656
+ `/projects/${this.projectId}/tasks`,
2657
+ body,
2658
+ { schema: EntityResponseSchema, validate: true }
2659
+ );
2660
+ return result.entity;
2661
+ }
2662
+ async get(id) {
2663
+ try {
2664
+ const result = await this.client.get(
2665
+ `/projects/${this.projectId}/tasks/${encodeURIComponent(id)}`,
2666
+ { schema: EntityDetailResponseSchema, validate: true }
2667
+ );
2668
+ return result.entity;
2669
+ } catch (err) {
2670
+ if (err instanceof TilaApiError && err.status === 404) {
2671
+ return null;
2672
+ }
2673
+ throw err;
2674
+ }
2675
+ }
2676
+ async list(filter) {
2677
+ const query = {};
2678
+ if (filter?.type) query.type = filter.type;
2679
+ if (filter?.archived !== void 0)
2680
+ query.archived = String(filter.archived);
2681
+ const DATA_FIELD_TO_QUERY_PARAM = {
2682
+ parent_id: "parent"
2683
+ };
2684
+ if (filter?.dataFilter) {
2685
+ for (const [key, value] of Object.entries(filter.dataFilter)) {
2686
+ if (value !== void 0 && value !== null) {
2687
+ const param = DATA_FIELD_TO_QUERY_PARAM[key] ?? key;
2688
+ query[param] = String(value);
2689
+ }
2690
+ }
2691
+ }
2692
+ if (filter?.tagFilter?.length)
2693
+ query.tag_filter = filter.tagFilter.join(",");
2694
+ if (filter?.sort) query.sort = filter.sort;
2695
+ if (filter?.order) query.order = filter.order;
2696
+ if (filter?.limit !== void 0) query.limit = String(filter.limit);
2697
+ if (filter?.offset !== void 0) query.offset = String(filter.offset);
2698
+ const result = await this.client.get(`/projects/${this.projectId}/tasks`, {
2699
+ schema: PaginatedEntityListResponseSchema,
2700
+ validate: true,
2701
+ query
2702
+ });
2703
+ return result.entities;
2704
+ }
2705
+ async update(id, data) {
2706
+ const acquired = await this.acquire(id, "cli", "cli", "exclusive", 3e4);
2707
+ try {
2708
+ const result = await this.client.patch(
2709
+ `/projects/${this.projectId}/tasks/${encodeURIComponent(id)}`,
2710
+ { data, fence: acquired.fence },
2711
+ { schema: EntityResponseSchema, validate: true }
2712
+ );
2713
+ return result.entity;
2714
+ } finally {
2715
+ try {
2716
+ await this.release(id, acquired.fence);
2717
+ } catch {
2718
+ }
2719
+ }
2720
+ }
2721
+ async archive(id) {
2722
+ const acquired = await this.acquire(id, "cli", "cli", "exclusive", 3e4);
2723
+ await this.client.post(
2724
+ `/projects/${this.projectId}/tasks/${encodeURIComponent(id)}/archive`,
2725
+ { fence: acquired.fence },
2726
+ { schema: ArchiveSuccessResponseSchema, validate: true }
2727
+ );
2728
+ }
2729
+ async addRelationship(input) {
2730
+ const result = await this.client.post(
2731
+ `/projects/${this.projectId}/tasks/relationships`,
2732
+ { from_id: input.from_id, to_id: input.to_id, type: input.type },
2733
+ { schema: CreateEntityRelationshipResponseSchema, validate: true }
2734
+ );
2735
+ return { created: result.created ?? true };
2736
+ }
2737
+ async listRelationships(filter) {
2738
+ const query = {};
2739
+ if (filter?.from_id) query.from_id = filter.from_id;
2740
+ if (filter?.to_id) query.to_id = filter.to_id;
2741
+ if (filter?.type) query.type = filter.type;
2742
+ const result = await this.client.get(
2743
+ `/projects/${this.projectId}/tasks/relationships`,
2744
+ { schema: ListEntityRelationshipsResponseSchema, validate: true, query }
2745
+ );
2746
+ return result.relationships;
2747
+ }
2748
+ async removeRelationship(input) {
2749
+ const params = new URLSearchParams({
2750
+ from_id: input.from_id,
2751
+ to_id: input.to_id,
2752
+ type: input.type
2753
+ });
2754
+ const result = await this.client.delete(
2755
+ `/projects/${this.projectId}/tasks/relationships?${params.toString()}`,
2756
+ { schema: DeleteEntityRelationshipResponseSchema, validate: true }
2757
+ );
2758
+ return { removed: result.removed };
2759
+ }
2760
+ // GET /projects/:projectId/tasks/ready (worker entities.ts ~129 -> DO /entity/ready)
2761
+ async listReady(filter) {
2762
+ const query = {};
2763
+ if (filter?.type) query.type = filter.type;
2764
+ if (filter?.parent) query.parent = filter.parent;
2765
+ if (filter?.limit !== void 0) query.limit = String(filter.limit);
2766
+ if (filter?.includeSoftBlocked) query["include-soft-blocked"] = "true";
2767
+ const result = await this.client.get(
2768
+ `/projects/${this.projectId}/tasks/ready`,
2769
+ { schema: ListReadyEntitiesResponseSchema, validate: true, query }
2770
+ );
2771
+ return result.entities.map((e) => ({ ...e, tags: [] }));
2772
+ }
2773
+ // Tree = compact list (GET /tasks?compact=true) + parent-child edges
2774
+ // (GET /tasks/relationships?type=parent-child). The Worker has no dedicated
2775
+ // tree endpoint; these are the two routes the DO/worker already expose.
2776
+ async tree(_rootId) {
2777
+ const listResult = await this.client.get(
2778
+ `/projects/${this.projectId}/tasks`,
2779
+ {
2780
+ schema: PaginatedCompactEntityListResponseSchema,
2781
+ validate: true,
2782
+ query: { compact: "true" }
2783
+ }
2784
+ );
2785
+ const relResult = await this.client.get(
2786
+ `/projects/${this.projectId}/tasks/relationships`,
2787
+ {
2788
+ schema: ListEntityRelationshipsResponseSchema,
2789
+ validate: true,
2790
+ query: { type: "parent-child" }
2791
+ }
2792
+ );
2793
+ return { nodes: listResult.entities, edges: relResult.relationships };
2794
+ }
2795
+ // PATCH /projects/:projectId/tasks/:id with a caller-supplied fence.
2796
+ // Unlike update() (which auto-acquires), the caller owns the fence here, so a
2797
+ // stale fence surfaces the Worker's fence-conflict error verbatim.
2798
+ async updateWithFence(id, data, fence) {
2799
+ const result = await this.client.patch(
2800
+ `/projects/${this.projectId}/tasks/${encodeURIComponent(id)}`,
2801
+ { data, fence },
2802
+ { schema: EntityResponseSchema, validate: true }
2803
+ );
2804
+ return result.entity;
2805
+ }
2806
+ // POST /projects/:projectId/tasks/:entityId/artifact-refs (worker entities.ts ~264)
2807
+ async addArtifactRef(input) {
2808
+ const body = {
2809
+ artifact_key: input.artifact_key,
2810
+ slot: input.slot
2811
+ };
2812
+ if (input.metadata !== void 0) body.metadata = input.metadata;
2813
+ await this.client.post(
2814
+ `/projects/${this.projectId}/tasks/${encodeURIComponent(input.entity_id)}/artifact-refs`,
2815
+ body,
2816
+ { schema: OkSchema, validate: true }
2817
+ );
2818
+ }
2819
+ // GET /projects/:projectId/tasks/:entityId/artifact-refs (worker entities.ts ~340)
2820
+ async listArtifactRefs(entityId) {
2821
+ const result = await this.client.get(
2822
+ `/projects/${this.projectId}/tasks/${encodeURIComponent(entityId)}/artifact-refs`,
2823
+ { schema: EntityArtifactReferenceListResponseSchema, validate: true }
2824
+ );
2825
+ return result.references;
2826
+ }
2827
+ // --- CoordinationBackend ---
2828
+ async acquire(resource, machine, user, mode, ttlMs) {
2829
+ const result = await this.client.post(
2830
+ `/projects/${this.projectId}/claims/acquire`,
2831
+ { resource, mode, ttl_ms: ttlMs },
2832
+ { schema: AcquireSuccessResponseSchema, validate: true }
2833
+ );
2834
+ return {
2835
+ acquired: true,
2836
+ fence: result.fence,
2837
+ expires_at: result.expires_at
2838
+ };
2839
+ }
2840
+ async renew(resource, _machine, _user, fence, ttlMs) {
2841
+ const result = await this.client.post(
2842
+ `/projects/${this.projectId}/claims/renew`,
2843
+ { resource, fence, ttl_ms: ttlMs },
2844
+ { schema: RenewSuccessResponseSchema, validate: true }
2845
+ );
2846
+ return { renewed: true, expires_at: result.expires_at };
2847
+ }
2848
+ async release(resource, fence) {
2849
+ await this.client.post(
2850
+ `/projects/${this.projectId}/claims/release`,
2851
+ { resource, fence },
2852
+ { schema: ReleaseSuccessResponseSchema, validate: true }
2853
+ );
2854
+ }
2855
+ async state(resource) {
2856
+ const result = await this.client.get(
2857
+ `/projects/${this.projectId}/claims/state/${encodeURIComponent(resource)}`,
2858
+ { schema: StateResponseSchema, validate: true }
2859
+ );
2860
+ return result.claim ?? null;
2861
+ }
2862
+ async heartbeat(machine, info) {
2863
+ await this.client.post(
2864
+ `/projects/${this.projectId}/presence/heartbeat`,
2865
+ { machine, info: info ?? {} },
2866
+ { schema: PresenceHeartbeatSuccessResponseSchema, validate: true }
2867
+ );
2868
+ }
2869
+ async listPresence() {
2870
+ const result = await this.client.get(
2871
+ `/projects/${this.projectId}/presence/all`,
2872
+ { schema: PresenceAllListResponseSchema, validate: true }
2873
+ );
2874
+ return result.machines.map(({ machine, last_seen, info }) => ({
2875
+ machine,
2876
+ last_seen,
2877
+ info
2878
+ }));
2879
+ }
2880
+ async listClaims() {
2881
+ const result = await this.client.get(`/projects/${this.projectId}/claims`, {
2882
+ schema: StateListInternalSchema,
2883
+ validate: true
2884
+ });
2885
+ return result.claims.map((c) => ({
2886
+ resource: c.resource,
2887
+ machine: c.machine,
2888
+ user: c.user,
2889
+ mode: c.mode,
2890
+ fence: c.fence,
2891
+ acquired_at: c.acquired_at,
2892
+ expires_at: c.expires_at,
2893
+ metadata: c.metadata ?? {}
2894
+ }));
2895
+ }
2896
+ // --- JournalBackend ---
2897
+ async listJournal(query) {
2898
+ const result = await this.client.get(
2899
+ `/projects/${this.projectId}/journal`,
2900
+ {
2901
+ schema: JournalResponseSchema,
2902
+ validate: true,
2903
+ query: {
2904
+ resource: query.resource,
2905
+ kind: query.kind,
2906
+ limit: query.limit !== void 0 ? String(query.limit) : void 0
2907
+ }
2908
+ }
2909
+ );
2910
+ return result.events.map((ev) => ({
2911
+ seq: ev.seq,
2912
+ t: ev.t,
2913
+ kind: ev.kind,
2914
+ resource: ev.resource,
2915
+ actor: ev.actor,
2916
+ fence: ev.fence
2917
+ }));
2918
+ }
2919
+ // --- GateBackend ---
2920
+ async createGate(resource, awaitType, fence, timeoutAt) {
2921
+ const body = {
2922
+ resource,
2923
+ await_type: awaitType,
2924
+ fence
2925
+ };
2926
+ if (timeoutAt !== void 0) body.timeout_at = timeoutAt;
2927
+ const result = await this.client.post(
2928
+ `/projects/${this.projectId}/gates`,
2929
+ body,
2930
+ { schema: GateResponseSchema, validate: true }
2931
+ );
2932
+ return {
2933
+ id: result.gate.id,
2934
+ resource: result.gate.resource,
2935
+ await_type: result.gate.await_type,
2936
+ status: result.gate.status,
2937
+ fence: result.gate.fence,
2938
+ timeout_at: result.gate.timeout_at,
2939
+ resolved_at: result.gate.resolved_at,
2940
+ resolution: result.gate.resolution,
2941
+ created_at: result.gate.created_at,
2942
+ created_by: result.gate.created_by
2943
+ };
2944
+ }
2945
+ async listGates(filter) {
2946
+ const params = new URLSearchParams();
2947
+ if (filter?.resource) params.set("resource", filter.resource);
2948
+ if (filter?.status) params.set("status", filter.status);
2949
+ const qs = params.toString();
2950
+ const url = `/projects/${this.projectId}/gates${qs ? `?${qs}` : ""}`;
2951
+ const result = await this.client.get(url, {
2952
+ schema: GateListResponseSchema,
2953
+ validate: true
2954
+ });
2955
+ return result.gates.map((g) => ({
2956
+ id: g.id,
2957
+ resource: g.resource,
2958
+ await_type: g.await_type,
2959
+ status: g.status,
2960
+ fence: g.fence,
2961
+ timeout_at: g.timeout_at,
2962
+ resolved_at: g.resolved_at,
2963
+ resolution: g.resolution,
2964
+ created_at: g.created_at,
2965
+ created_by: g.created_by
2966
+ }));
2967
+ }
2968
+ async resolveGate(gateId, resolution) {
2969
+ const body = {};
2970
+ if (resolution) body.resolution = resolution;
2971
+ await this.client.post(
2972
+ `/projects/${this.projectId}/gates/${gateId}/resolve`,
2973
+ body,
2974
+ { schema: OkSchema, validate: true }
2975
+ );
2976
+ }
2977
+ async cancelGate(gateId) {
2978
+ await this.client.delete(`/projects/${this.projectId}/gates/${gateId}`, {
2979
+ schema: OkSchema,
2980
+ validate: true
2981
+ });
2982
+ }
2983
+ // --- SignalBackend ---
2984
+ async sendSignal(input, _createdBy) {
2985
+ const body = {
2986
+ target: input.target,
2987
+ kind: input.kind
2988
+ };
2989
+ if (input.resource) body.resource = input.resource;
2990
+ if (input.payload !== void 0) body.payload = input.payload;
2991
+ if (input.ttl_ms !== void 0) body.ttl_ms = input.ttl_ms;
2992
+ const result = await this.client.post(
2993
+ `/projects/${this.projectId}/signals/send`,
2994
+ body,
2995
+ { schema: SendSignalResponseSchema, validate: true }
2996
+ );
2997
+ return { id: result.id };
2998
+ }
2999
+ async listSignals(_tokenName) {
3000
+ const result = await this.client.get(
3001
+ `/projects/${this.projectId}/signals`,
3002
+ { schema: InboxResponseSchema, validate: true }
3003
+ );
3004
+ return result.signals.map((s) => ({
3005
+ id: s.id,
3006
+ target: s.target,
3007
+ kind: s.kind,
3008
+ resource: s.resource ?? null,
3009
+ payload: s.payload,
3010
+ created_by: s.created_by,
3011
+ created_at: s.created_at,
3012
+ expires_at: s.expires_at,
3013
+ acked_at: s.acked_at
3014
+ }));
3015
+ }
3016
+ async ackSignal(signalId) {
3017
+ await this.client.post(
3018
+ `/projects/${this.projectId}/signals/${signalId}/ack`,
3019
+ {},
3020
+ { schema: AckSignalResponseSchema, validate: true }
3021
+ );
3022
+ return { found: true };
3023
+ }
3024
+ // --- SchemaBackend ---
3025
+ async getCurrentSchema() {
3026
+ const result = await this.client.get(`/projects/${this.projectId}/schema`, {
3027
+ schema: SchemaShowResponseSchema,
3028
+ validate: true
3029
+ });
3030
+ return {
3031
+ version: result.version,
3032
+ definition: result.schema ? JSON.stringify(result.schema) : null
3033
+ };
3034
+ }
3035
+ async applySchema(input) {
3036
+ const body = {
3037
+ definition: input.definition
3038
+ };
3039
+ if (input.strategy) body.strategy = input.strategy;
3040
+ const result = await this.client.post(
3041
+ `/projects/${this.projectId}/schema`,
3042
+ body,
3043
+ { schema: SchemaApplyLenientSchema, validate: true }
3044
+ );
3045
+ return {
3046
+ ok: true,
3047
+ version: result.version ?? null,
3048
+ changes: result.changes ?? [],
3049
+ noChange: result.noChange ?? false
3050
+ };
3051
+ }
3052
+ // --- SummaryBackend ---
3053
+ async getSummary() {
3054
+ const result = await this.client.get(
3055
+ `/projects/${this.projectId}/summary`,
3056
+ { schema: SummaryResponseSchema, validate: true }
3057
+ );
3058
+ return result.project;
3059
+ }
3060
+ };
3061
+ var RemoteArtifactBackend = class {
3062
+ constructor(client, projectId) {
3063
+ this.client = client;
3064
+ this.projectId = projectId;
3065
+ }
3066
+ client;
3067
+ projectId;
3068
+ // --- ArtifactBackend ---
3069
+ async put(options) {
3070
+ let bodyBlob;
3071
+ if (typeof options.body === "string") {
3072
+ bodyBlob = new Blob([options.body], { type: options.contentType });
3073
+ } else if (options.body instanceof ArrayBuffer) {
3074
+ bodyBlob = new Blob([options.body], { type: options.contentType });
3075
+ } else {
3076
+ const arrayBuf = await new Response(options.body).arrayBuffer();
3077
+ bodyBlob = new Blob([arrayBuf], { type: options.contentType });
3078
+ }
3079
+ const formData = new FormData();
3080
+ formData.append("file", bodyBlob, options.key.split("/").pop() ?? "file");
3081
+ if (options.kind) formData.append("kind", options.kind);
3082
+ if (options.resource) formData.append("resource", options.resource);
3083
+ if (options.fence !== void 0)
3084
+ formData.append("fence", String(options.fence));
3085
+ if (options.flavor) formData.append("flavor", options.flavor);
3086
+ const result = await this.client.postFormData(
3087
+ `/projects/${this.projectId}/artifacts`,
3088
+ formData,
3089
+ { schema: ArtifactPutResponseSchema, validate: true }
3090
+ );
3091
+ return { key: result.key, bytes: result.bytes };
3092
+ }
3093
+ async get(key) {
3094
+ let response;
3095
+ try {
3096
+ response = await this.client.requestRaw(
3097
+ "GET",
3098
+ `/projects/${this.projectId}/artifacts/${encodeURIComponent(key)}`
3099
+ );
3100
+ } catch (err) {
3101
+ if (err instanceof TilaApiError && err.status === 404) {
3102
+ return null;
3103
+ }
3104
+ throw err;
3105
+ }
3106
+ if (response.status === 404) return null;
3107
+ if (!response.ok) {
3108
+ throw new TilaApiError(
3109
+ response.status,
3110
+ "artifact-get-failed",
3111
+ `GET artifact ${key} failed: ${response.statusText}`,
3112
+ false
3113
+ );
3114
+ }
3115
+ return {
3116
+ body: response.body,
3117
+ contentType: response.headers.get("Content-Type") ?? "application/octet-stream",
3118
+ metadata: {}
3119
+ };
3120
+ }
3121
+ async list(prefix) {
3122
+ const result = await this.client.get(
3123
+ `/projects/${this.projectId}/artifacts`,
3124
+ {
3125
+ schema: ArtifactListInternalSchema,
3126
+ validate: true,
3127
+ query: { resource: prefix }
3128
+ }
3129
+ );
3130
+ return result.pointers.map((p) => ({
3131
+ key: p.r2_key,
3132
+ size: p.bytes
3133
+ }));
3134
+ }
3135
+ async delete(key) {
3136
+ await this.client.delete(
3137
+ `/projects/${this.projectId}/artifacts/${encodeURIComponent(key)}`,
3138
+ {
3139
+ schema: OkSchema,
3140
+ validate: true
3141
+ }
3142
+ );
3143
+ }
3144
+ async listPointers(query) {
3145
+ const q = {};
3146
+ if (query.resource) q.resource = query.resource;
3147
+ if (query.kind) q.kind = query.kind;
3148
+ const result = await this.client.get(
3149
+ `/projects/${this.projectId}/artifacts`,
3150
+ {
3151
+ schema: ArtifactListInternalSchema,
3152
+ validate: true,
3153
+ query: q
3154
+ }
3155
+ );
3156
+ return result.pointers;
3157
+ }
3158
+ async addRelationship(fromKey, toKeyOrUri, type) {
3159
+ const body = {
3160
+ from_key: fromKey,
3161
+ type
3162
+ };
3163
+ if (toKeyOrUri.to_key) body.to_key = toKeyOrUri.to_key;
3164
+ if (toKeyOrUri.to_uri) body.to_uri = toKeyOrUri.to_uri;
3165
+ await this.client.post(
3166
+ `/projects/${this.projectId}/artifacts/relationship`,
3167
+ body,
3168
+ { schema: OkSchema, validate: true }
3169
+ );
3170
+ }
3171
+ async listRelationships(key) {
3172
+ const result = await this.client.get(
3173
+ `/projects/${this.projectId}/artifacts/${encodeURIComponent(key)}/relationships`,
3174
+ { schema: RelListResponseSchema, validate: true }
3175
+ );
3176
+ return result.relationships;
3177
+ }
3178
+ async searchArtifacts(query) {
3179
+ const q = {
3180
+ q: query.q
3181
+ };
3182
+ if (query.kind) q.kind = query.kind;
3183
+ if (query.resource) q.resource = query.resource;
3184
+ if (query.limit !== void 0) q.limit = String(query.limit);
3185
+ const result = await this.client.get(
3186
+ `/projects/${this.projectId}/artifacts/search`,
3187
+ { schema: ArtifactSearchResponseSchema2, validate: true, query: q }
3188
+ );
3189
+ return result.results;
3190
+ }
3191
+ async grepArtifacts(query) {
3192
+ const q = { pattern: query.pattern };
3193
+ if (query.kind) q.kind = query.kind;
3194
+ if (query.resource) q.resource = query.resource;
3195
+ if (query.regex) q.regex = "true";
3196
+ if (query.limit != null) q.limit = String(query.limit);
3197
+ const result = await this.client.get(
3198
+ `/projects/${this.projectId}/artifacts/grep`,
3199
+ { schema: ArtifactGrepResponseSchema, validate: true, query: q }
3200
+ );
3201
+ return result;
3202
+ }
3203
+ async listIndexEntries(indexKey) {
3204
+ const result = await this.client.get(
3205
+ `/projects/${this.projectId}/artifacts/index/entries`,
3206
+ {
3207
+ schema: IndexEntriesResponseSchema,
3208
+ validate: true,
3209
+ query: { index_key: indexKey }
3210
+ }
3211
+ );
3212
+ return result.entries;
3213
+ }
3214
+ async getLatest(kind, resource) {
3215
+ let response;
3216
+ try {
3217
+ response = await this.client.requestRaw(
3218
+ "GET",
3219
+ `/projects/${this.projectId}/artifacts/latest`,
3220
+ { query: { kind, resource } }
3221
+ );
3222
+ } catch (err) {
3223
+ if (err instanceof TilaApiError && err.status === 404) {
3224
+ return null;
3225
+ }
3226
+ throw err;
3227
+ }
3228
+ if (response.status === 404) return null;
3229
+ if (!response.ok) {
3230
+ throw new TilaApiError(
3231
+ response.status,
3232
+ "artifact-get-latest-failed",
3233
+ `GET artifact latest failed: ${response.statusText}`,
3234
+ false
3235
+ );
3236
+ }
3237
+ const body = await response.json();
3238
+ return body.pointer;
3239
+ }
3240
+ async writeText(content, opts) {
3241
+ const result = await this.client.post(
3242
+ `/projects/${this.projectId}/artifacts/text`,
3243
+ {
3244
+ content,
3245
+ kind: opts.kind,
3246
+ mime_type: opts.mimeType ?? "text/markdown",
3247
+ resource: opts.resource,
3248
+ fence: opts.fence
3249
+ },
3250
+ { schema: ArtifactPutResponseSchema, validate: true }
3251
+ );
3252
+ return { key: result.key, bytes: result.bytes };
3253
+ }
3254
+ async readText(key) {
3255
+ let response;
3256
+ try {
3257
+ response = await this.client.requestRaw(
3258
+ "GET",
3259
+ `/projects/${this.projectId}/artifacts/${encodeURIComponent(key)}`
3260
+ );
3261
+ } catch (err) {
3262
+ if (err instanceof TilaApiError && err.status === 404) {
3263
+ return null;
3264
+ }
3265
+ throw err;
3266
+ }
3267
+ if (response.status === 404) return null;
3268
+ const contentType = response.headers.get("content-type") || "application/octet-stream";
3269
+ if (!contentType.startsWith("text/")) {
3270
+ throw new TypeError(
3271
+ `Artifact ${key} has MIME type ${contentType} \u2014 readText only supports text/* artifacts`
3272
+ );
3273
+ }
3274
+ const text = await response.text();
3275
+ return { content: text, mimeType: contentType };
3276
+ }
3277
+ };
3278
+ var RemoteRecordBackend = class {
3279
+ constructor(client, projectId) {
3280
+ this.client = client;
3281
+ this.projectId = projectId;
3282
+ }
3283
+ client;
3284
+ projectId;
3285
+ base() {
3286
+ return `/projects/${this.projectId}/records`;
3287
+ }
3288
+ /** Encode a record key per-segment so embedded `/` separators are preserved. */
3289
+ encodeKey(key) {
3290
+ return key.split("/").map(encodeURIComponent).join("/");
3291
+ }
3292
+ async createRecord(input) {
3293
+ const body = {
3294
+ key: input.key,
3295
+ value: input.value
3296
+ };
3297
+ if (input.tags) body.tags = input.tags;
3298
+ if (input.message != null) body.message = input.message;
3299
+ if (input.sourceArtifactKey != null)
3300
+ body.source_artifact_key = input.sourceArtifactKey;
3301
+ const result = await this.client.post(
3302
+ `${this.base()}/${input.type}`,
3303
+ body,
3304
+ { schema: RecordMutateResponseSchema, validate: true }
3305
+ );
3306
+ return { ...result.record, fence: result.fence };
3307
+ }
3308
+ async setRecord(input) {
3309
+ const body = {
3310
+ value: input.value,
3311
+ fence: input.fence
3312
+ };
3313
+ if (input.tags) body.tags = input.tags;
3314
+ if (input.message != null) body.message = input.message;
3315
+ if (input.sourceArtifactKey != null)
3316
+ body.source_artifact_key = input.sourceArtifactKey;
3317
+ const result = await this.client.put(
3318
+ `${this.base()}/${input.type}/${this.encodeKey(input.key)}`,
3319
+ body,
3320
+ { schema: RecordMutateResponseSchema, validate: true }
3321
+ );
3322
+ return { ...result.record, fence: result.fence };
3323
+ }
3324
+ async getRecord(type, key) {
3325
+ try {
3326
+ const result = await this.client.get(
3327
+ `${this.base()}/${type}/${this.encodeKey(key)}`,
3328
+ { schema: RecordGetResponseSchema, validate: true }
3329
+ );
3330
+ return { ...result.record, fence: result.fence };
3331
+ } catch (err) {
3332
+ if (err instanceof TilaApiError && err.status === 404) {
3333
+ return null;
3334
+ }
3335
+ throw err;
3336
+ }
3337
+ }
3338
+ async patchRecord(input) {
3339
+ const body = {
3340
+ patch: input.patch,
3341
+ fence: input.fence
3342
+ };
3343
+ if (input.message != null) body.message = input.message;
3344
+ const result = await this.client.patch(
3345
+ `${this.base()}/${input.type}/${this.encodeKey(input.key)}`,
3346
+ body,
3347
+ { schema: RecordMutateResponseSchema, validate: true }
3348
+ );
3349
+ return { ...result.record, fence: result.fence };
3350
+ }
3351
+ async archiveRecord(input) {
3352
+ const body = { fence: input.fence };
3353
+ if (input.message != null) body.message = input.message;
3354
+ const result = await this.client.post(
3355
+ `${this.base()}/${input.type}/~/archive/${this.encodeKey(input.key)}`,
3356
+ body,
3357
+ { schema: RecordMutateResponseSchema, validate: true }
3358
+ );
3359
+ return { ...result.record, fence: result.fence };
3360
+ }
3361
+ async unarchiveRecord(input) {
3362
+ const body = { fence: input.fence };
3363
+ if (input.message != null) body.message = input.message;
3364
+ const result = await this.client.post(
3365
+ `${this.base()}/${input.type}/~/unarchive/${this.encodeKey(input.key)}`,
3366
+ body,
3367
+ { schema: RecordMutateResponseSchema, validate: true }
3368
+ );
3369
+ return { ...result.record, fence: result.fence };
3370
+ }
3371
+ async listRecords(filter) {
3372
+ const query = {};
3373
+ if (filter.tag) query.tag = filter.tag;
3374
+ if (filter.includeArchived) query["include-archived"] = "true";
3375
+ if (filter.tagFilter?.length) query.tag_filter = filter.tagFilter.join(",");
3376
+ if (filter.dataFilter) query.filter = JSON.stringify(filter.dataFilter);
3377
+ if (filter.limit !== void 0) query.limit = String(filter.limit);
3378
+ const result = await this.client.get(`${this.base()}/${filter.type}`, {
3379
+ schema: RecordListResponseSchema,
3380
+ validate: true,
3381
+ query
3382
+ });
3383
+ return {
3384
+ items: result.items,
3385
+ total: result.meta.total,
3386
+ next_cursor: result.meta.next_cursor
3387
+ };
3388
+ }
3389
+ async listRecordHistory(type, key, opts) {
3390
+ const query = {};
3391
+ if (opts?.limit !== void 0) query.limit = String(opts.limit);
3392
+ if (opts?.includeValues !== void 0)
3393
+ query.values = String(opts.includeValues);
3394
+ const result = await this.client.get(
3395
+ `${this.base()}/${type}/~/history/${this.encodeKey(key)}`,
3396
+ { schema: RecordHistoryResponseSchema, validate: true, query }
3397
+ );
3398
+ return {
3399
+ items: result.items,
3400
+ total: result.meta.total,
3401
+ next_cursor: result.meta.next_cursor
3402
+ };
3403
+ }
3404
+ async listRecordTypesInUse() {
3405
+ const result = await this.client.get(`${this.base()}/_types`, {
3406
+ schema: RecordTypesInternalSchema,
3407
+ validate: true
3408
+ });
3409
+ return result.in_use_types ?? [];
3410
+ }
3411
+ };
2141
3412
 
2142
- export { ClaimHandle, TILA_ERRORS, TilaApiError, TilaClient, createArtifactMethods, createClaimMethods, createEntityMethods, createGateMethods, createIndexMethods, createJournalMethods, createPresenceMethods, createRecordMethods, createSchemaMethods, createSearchMethods, createSignalMethods, createSummaryMethods, createTaskMethods, createTemplateMethods, createTokenMethods, createWorkUnitMethods, exchangeGitHubToken, isTilaApiError, withClaim, withRetry };
3413
+ export { ClaimHandle, RemoteArtifactBackend, RemoteBackend, RemoteRecordBackend, TILA_ERRORS, TilaApiError, TilaClient, applyPrefix, createArtifactMethods, createClaimMethods, createEntityMethods, createGateMethods, createIndexMethods, createJournalMethods, createNamespace, createPresenceMethods, createRecordMethods, createSchemaMethods, createSearchMethods, createSignalMethods, createSummaryMethods, createTaskMethods, createTemplateMethods, createTila, createTokenMethods, createWorkUnitMethods, exchangeGitHubToken, isTilaApiError, stripPrefix, validateNamespace, withClaim, withRetry };