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