tila-sdk 0.1.0 → 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 +2028 -750
- package/dist/index.d.cts +941 -249
- package/dist/index.d.ts +941 -249
- package/dist/index.js +2021 -750
- 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 +29 -4
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var module$1 = require('module');
|
|
4
3
|
var zod = require('zod');
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
// src/client.ts
|
|
5
|
+
// ../schemas/dist/entity.js
|
|
8
6
|
zod.z.object({
|
|
9
7
|
id: zod.z.string(),
|
|
10
8
|
type: zod.z.string(),
|
|
@@ -13,7 +11,8 @@ zod.z.object({
|
|
|
13
11
|
archived: zod.z.number().int().default(0),
|
|
14
12
|
created_at: zod.z.number().int(),
|
|
15
13
|
updated_at: zod.z.number().int(),
|
|
16
|
-
created_by: zod.z.string()
|
|
14
|
+
created_by: zod.z.string(),
|
|
15
|
+
tags: zod.z.array(zod.z.string()).default([])
|
|
17
16
|
});
|
|
18
17
|
var ClaimModeSchema = zod.z.enum(["exclusive", "owner", "presence"]);
|
|
19
18
|
zod.z.object({
|
|
@@ -75,7 +74,8 @@ zod.z.object({
|
|
|
75
74
|
produced_at: zod.z.number().int(),
|
|
76
75
|
produced_by: zod.z.string(),
|
|
77
76
|
expires_at: zod.z.number().int().nullable(),
|
|
78
|
-
tombstoned: zod.z.number().int().default(0)
|
|
77
|
+
tombstoned: zod.z.number().int().default(0),
|
|
78
|
+
tags: zod.z.array(zod.z.string()).default([])
|
|
79
79
|
});
|
|
80
80
|
zod.z.object({
|
|
81
81
|
entity_id: zod.z.string(),
|
|
@@ -163,15 +163,15 @@ zod.z.object({
|
|
|
163
163
|
payload: zod.z.unknown().optional(),
|
|
164
164
|
ttl_ms: zod.z.number().int().min(1e3).max(864e5).optional()
|
|
165
165
|
});
|
|
166
|
-
zod.z.object({
|
|
166
|
+
var SendSignalResponseSchema = zod.z.object({
|
|
167
167
|
ok: zod.z.literal(true),
|
|
168
168
|
id: zod.z.string()
|
|
169
169
|
});
|
|
170
|
-
zod.z.object({
|
|
170
|
+
var InboxResponseSchema = zod.z.object({
|
|
171
171
|
ok: zod.z.literal(true),
|
|
172
172
|
signals: zod.z.array(SignalSchema)
|
|
173
173
|
});
|
|
174
|
-
zod.z.object({
|
|
174
|
+
var AckSignalResponseSchema = zod.z.object({
|
|
175
175
|
ok: zod.z.literal(true)
|
|
176
176
|
});
|
|
177
177
|
zod.z.object({
|
|
@@ -335,6 +335,21 @@ zod.z.object({
|
|
|
335
335
|
pages_project_name: zod.z.string().optional(),
|
|
336
336
|
infra_slug: zod.z.string().optional()
|
|
337
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
|
|
338
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");
|
|
339
354
|
var RecordKeySchema = zod.z.string().superRefine((val, ctx) => {
|
|
340
355
|
if (val.length === 0) {
|
|
@@ -411,18 +426,7 @@ var RecordKeySchema = zod.z.string().superRefine((val, ctx) => {
|
|
|
411
426
|
}
|
|
412
427
|
}
|
|
413
428
|
});
|
|
414
|
-
var RecordTagSchema =
|
|
415
|
-
const seen = /* @__PURE__ */ new Set();
|
|
416
|
-
const result = [];
|
|
417
|
-
for (const tag of tags) {
|
|
418
|
-
const lower = tag.toLowerCase();
|
|
419
|
-
if (!seen.has(lower)) {
|
|
420
|
-
seen.add(lower);
|
|
421
|
-
result.push(lower);
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
return result;
|
|
425
|
-
}).refine((tags) => tags.length <= 20, "Record may not have more than 20 tags");
|
|
429
|
+
var RecordTagSchema = TagsSchema;
|
|
426
430
|
function sortKeysDeep(v) {
|
|
427
431
|
if (Array.isArray(v))
|
|
428
432
|
return v.map(sortKeysDeep);
|
|
@@ -461,7 +465,7 @@ zod.z.object({
|
|
|
461
465
|
idempotency_key: zod.z.string().optional(),
|
|
462
466
|
metadata: zod.z.record(zod.z.unknown()).optional()
|
|
463
467
|
});
|
|
464
|
-
zod.z.object({
|
|
468
|
+
var AcquireSuccessResponseSchema = zod.z.object({
|
|
465
469
|
ok: zod.z.literal(true),
|
|
466
470
|
fence: zod.z.number().int(),
|
|
467
471
|
expires_at: zod.z.number().int()
|
|
@@ -471,7 +475,7 @@ zod.z.object({
|
|
|
471
475
|
fence: zod.z.number().int(),
|
|
472
476
|
ttl_ms: zod.z.number().int().positive()
|
|
473
477
|
});
|
|
474
|
-
zod.z.object({
|
|
478
|
+
var RenewSuccessResponseSchema = zod.z.object({
|
|
475
479
|
ok: zod.z.literal(true),
|
|
476
480
|
expires_at: zod.z.number().int()
|
|
477
481
|
});
|
|
@@ -479,10 +483,10 @@ zod.z.object({
|
|
|
479
483
|
resource: zod.z.string(),
|
|
480
484
|
fence: zod.z.number().int()
|
|
481
485
|
});
|
|
482
|
-
zod.z.object({
|
|
486
|
+
var ReleaseSuccessResponseSchema = zod.z.object({
|
|
483
487
|
ok: zod.z.literal(true)
|
|
484
488
|
});
|
|
485
|
-
zod.z.object({
|
|
489
|
+
var StateResponseSchema = zod.z.object({
|
|
486
490
|
ok: zod.z.literal(true),
|
|
487
491
|
claim: zod.z.object({
|
|
488
492
|
resource: zod.z.string(),
|
|
@@ -511,16 +515,18 @@ zod.z.object({
|
|
|
511
515
|
zod.z.object({
|
|
512
516
|
id: zod.z.string(),
|
|
513
517
|
type: zod.z.string(),
|
|
514
|
-
data: zod.z.record(zod.z.unknown()).default({})
|
|
518
|
+
data: zod.z.record(zod.z.unknown()).default({}),
|
|
519
|
+
tags: TagsSchema.optional()
|
|
515
520
|
});
|
|
516
521
|
zod.z.object({
|
|
517
522
|
data: zod.z.record(zod.z.unknown()),
|
|
518
|
-
fence: zod.z.number().int()
|
|
523
|
+
fence: zod.z.number().int(),
|
|
524
|
+
tags: TagsSchema.optional()
|
|
519
525
|
});
|
|
520
526
|
zod.z.object({
|
|
521
527
|
fence: zod.z.number().int()
|
|
522
528
|
});
|
|
523
|
-
zod.z.object({
|
|
529
|
+
var EntityResponseSchema = zod.z.object({
|
|
524
530
|
ok: zod.z.literal(true),
|
|
525
531
|
entity: zod.z.object({
|
|
526
532
|
id: zod.z.string(),
|
|
@@ -530,7 +536,8 @@ zod.z.object({
|
|
|
530
536
|
archived: zod.z.number().int(),
|
|
531
537
|
created_at: zod.z.number().int(),
|
|
532
538
|
updated_at: zod.z.number().int(),
|
|
533
|
-
created_by: zod.z.string()
|
|
539
|
+
created_by: zod.z.string(),
|
|
540
|
+
tags: zod.z.array(zod.z.string())
|
|
534
541
|
})
|
|
535
542
|
});
|
|
536
543
|
zod.z.object({
|
|
@@ -543,10 +550,11 @@ zod.z.object({
|
|
|
543
550
|
archived: zod.z.number().int(),
|
|
544
551
|
created_at: zod.z.number().int(),
|
|
545
552
|
updated_at: zod.z.number().int(),
|
|
546
|
-
created_by: zod.z.string()
|
|
553
|
+
created_by: zod.z.string(),
|
|
554
|
+
tags: zod.z.array(zod.z.string())
|
|
547
555
|
}))
|
|
548
556
|
});
|
|
549
|
-
zod.z.object({
|
|
557
|
+
var PaginatedEntityListResponseSchema = zod.z.object({
|
|
550
558
|
ok: zod.z.literal(true),
|
|
551
559
|
entities: zod.z.array(zod.z.object({
|
|
552
560
|
id: zod.z.string(),
|
|
@@ -556,14 +564,15 @@ zod.z.object({
|
|
|
556
564
|
archived: zod.z.number().int(),
|
|
557
565
|
created_at: zod.z.number().int(),
|
|
558
566
|
updated_at: zod.z.number().int(),
|
|
559
|
-
created_by: zod.z.string()
|
|
567
|
+
created_by: zod.z.string(),
|
|
568
|
+
tags: zod.z.array(zod.z.string())
|
|
560
569
|
})),
|
|
561
570
|
total: zod.z.number().int(),
|
|
562
571
|
limit: zod.z.number().int().nullable(),
|
|
563
572
|
offset: zod.z.number().int(),
|
|
564
573
|
has_more: zod.z.boolean()
|
|
565
574
|
});
|
|
566
|
-
zod.z.object({
|
|
575
|
+
var ListReadyEntitiesResponseSchema = zod.z.object({
|
|
567
576
|
ok: zod.z.literal(true),
|
|
568
577
|
entities: zod.z.array(zod.z.object({
|
|
569
578
|
id: zod.z.string(),
|
|
@@ -593,7 +602,7 @@ zod.z.object({
|
|
|
593
602
|
ok: zod.z.literal(true),
|
|
594
603
|
entity: CompactEntitySchema
|
|
595
604
|
});
|
|
596
|
-
zod.z.object({
|
|
605
|
+
var PaginatedCompactEntityListResponseSchema = zod.z.object({
|
|
597
606
|
ok: zod.z.literal(true),
|
|
598
607
|
entities: zod.z.array(CompactEntitySchema),
|
|
599
608
|
total: zod.z.number().int(),
|
|
@@ -601,7 +610,7 @@ zod.z.object({
|
|
|
601
610
|
offset: zod.z.number().int(),
|
|
602
611
|
has_more: zod.z.boolean()
|
|
603
612
|
});
|
|
604
|
-
zod.z.object({
|
|
613
|
+
var SummaryResponseSchema = zod.z.object({
|
|
605
614
|
ok: zod.z.literal(true),
|
|
606
615
|
project: zod.z.object({
|
|
607
616
|
entity_count: zod.z.number().int(),
|
|
@@ -620,7 +629,7 @@ zod.z.object({
|
|
|
620
629
|
}))
|
|
621
630
|
})
|
|
622
631
|
});
|
|
623
|
-
zod.z.object({
|
|
632
|
+
var EntityDetailResponseSchema = zod.z.object({
|
|
624
633
|
ok: zod.z.literal(true),
|
|
625
634
|
entity: zod.z.object({
|
|
626
635
|
id: zod.z.string(),
|
|
@@ -630,11 +639,12 @@ zod.z.object({
|
|
|
630
639
|
archived: zod.z.number().int(),
|
|
631
640
|
created_at: zod.z.number().int(),
|
|
632
641
|
updated_at: zod.z.number().int(),
|
|
633
|
-
created_by: zod.z.string()
|
|
642
|
+
created_by: zod.z.string(),
|
|
643
|
+
tags: zod.z.array(zod.z.string())
|
|
634
644
|
}),
|
|
635
645
|
relationships: zod.z.array(EntityRelationshipSchema).default([])
|
|
636
646
|
});
|
|
637
|
-
zod.z.object({
|
|
647
|
+
var ArchiveSuccessResponseSchema = zod.z.object({
|
|
638
648
|
ok: zod.z.literal(true)
|
|
639
649
|
});
|
|
640
650
|
zod.z.object({
|
|
@@ -642,7 +652,7 @@ zod.z.object({
|
|
|
642
652
|
to_id: zod.z.string().min(1),
|
|
643
653
|
type: EntityRelationshipTypeSchema
|
|
644
654
|
});
|
|
645
|
-
zod.z.object({
|
|
655
|
+
var CreateEntityRelationshipResponseSchema = zod.z.object({
|
|
646
656
|
ok: zod.z.literal(true),
|
|
647
657
|
created: zod.z.boolean().default(true)
|
|
648
658
|
});
|
|
@@ -651,7 +661,7 @@ zod.z.object({
|
|
|
651
661
|
to_id: zod.z.string().min(1).optional(),
|
|
652
662
|
type: EntityRelationshipTypeSchema.optional()
|
|
653
663
|
});
|
|
654
|
-
zod.z.object({
|
|
664
|
+
var ListEntityRelationshipsResponseSchema = zod.z.object({
|
|
655
665
|
ok: zod.z.literal(true),
|
|
656
666
|
relationships: zod.z.array(EntityRelationshipSchema)
|
|
657
667
|
});
|
|
@@ -660,7 +670,7 @@ zod.z.object({
|
|
|
660
670
|
to_id: zod.z.string().min(1),
|
|
661
671
|
type: EntityRelationshipTypeSchema
|
|
662
672
|
});
|
|
663
|
-
zod.z.object({
|
|
673
|
+
var DeleteEntityRelationshipResponseSchema = zod.z.object({
|
|
664
674
|
ok: zod.z.literal(true),
|
|
665
675
|
removed: zod.z.boolean()
|
|
666
676
|
});
|
|
@@ -671,7 +681,7 @@ zod.z.object({
|
|
|
671
681
|
after_seq: zod.z.number().int().optional(),
|
|
672
682
|
limit: zod.z.number().int().positive().default(100)
|
|
673
683
|
});
|
|
674
|
-
zod.z.object({
|
|
684
|
+
var JournalResponseSchema = zod.z.object({
|
|
675
685
|
ok: zod.z.literal(true),
|
|
676
686
|
events: zod.z.array(zod.z.object({
|
|
677
687
|
seq: zod.z.number().int(),
|
|
@@ -698,7 +708,7 @@ zod.z.object({
|
|
|
698
708
|
info: zod.z.record(zod.z.unknown())
|
|
699
709
|
}))
|
|
700
710
|
});
|
|
701
|
-
zod.z.object({
|
|
711
|
+
var PresenceAllListResponseSchema = zod.z.object({
|
|
702
712
|
ok: zod.z.literal(true),
|
|
703
713
|
machines: zod.z.array(zod.z.object({
|
|
704
714
|
machine: zod.z.string(),
|
|
@@ -707,7 +717,7 @@ zod.z.object({
|
|
|
707
717
|
active: zod.z.boolean()
|
|
708
718
|
}))
|
|
709
719
|
});
|
|
710
|
-
zod.z.object({
|
|
720
|
+
var PresenceHeartbeatSuccessResponseSchema = zod.z.object({
|
|
711
721
|
ok: zod.z.literal(true)
|
|
712
722
|
});
|
|
713
723
|
zod.z.object({
|
|
@@ -849,7 +859,7 @@ zod.z.object({
|
|
|
849
859
|
slot: zod.z.string().min(1),
|
|
850
860
|
metadata: zod.z.record(zod.z.unknown()).default({})
|
|
851
861
|
});
|
|
852
|
-
zod.z.object({
|
|
862
|
+
var EntityArtifactReferenceListResponseSchema = zod.z.object({
|
|
853
863
|
ok: zod.z.literal(true),
|
|
854
864
|
references: zod.z.array(zod.z.object({
|
|
855
865
|
entity_id: zod.z.string(),
|
|
@@ -859,6 +869,46 @@ zod.z.object({
|
|
|
859
869
|
created_at: zod.z.number().int()
|
|
860
870
|
}))
|
|
861
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));
|
|
862
912
|
zod.z.object({
|
|
863
913
|
ok: zod.z.literal(true),
|
|
864
914
|
results: zod.z.array(ArtifactSearchResultSchema),
|
|
@@ -869,7 +919,8 @@ zod.z.object({
|
|
|
869
919
|
kind: zod.z.string().optional(),
|
|
870
920
|
resource: zod.z.string().optional(),
|
|
871
921
|
source_only: zod.z.string().optional().transform((v) => v === "true").pipe(zod.z.boolean()),
|
|
872
|
-
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
|
|
873
924
|
});
|
|
874
925
|
var ArtifactGrepLineSchema = zod.z.object({
|
|
875
926
|
line: zod.z.number().int(),
|
|
@@ -887,7 +938,7 @@ var ArtifactGrepResultSchema = zod.z.object({
|
|
|
887
938
|
truncated: zod.z.boolean().optional()
|
|
888
939
|
// this blob hit the per-blob byte cap
|
|
889
940
|
});
|
|
890
|
-
zod.z.object({
|
|
941
|
+
var ArtifactGrepResponseSchema = zod.z.object({
|
|
891
942
|
ok: zod.z.literal(true),
|
|
892
943
|
results: zod.z.array(ArtifactGrepResultSchema),
|
|
893
944
|
scanned: zod.z.number().int(),
|
|
@@ -923,16 +974,18 @@ zod.z.object({
|
|
|
923
974
|
});
|
|
924
975
|
zod.z.object({
|
|
925
976
|
q: zod.z.string().min(1).max(200),
|
|
926
|
-
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
|
|
927
979
|
});
|
|
928
980
|
zod.z.object({
|
|
929
981
|
content: zod.z.string().min(1),
|
|
930
982
|
kind: zod.z.string().min(1),
|
|
931
983
|
mime_type: zod.z.string().default("text/markdown"),
|
|
932
984
|
resource: zod.z.string().optional(),
|
|
933
|
-
fence: zod.z.number().int().optional()
|
|
985
|
+
fence: zod.z.number().int().optional(),
|
|
986
|
+
tags: TagsSchema.optional()
|
|
934
987
|
});
|
|
935
|
-
zod.z.object({
|
|
988
|
+
var ArtifactPutResponseSchema = zod.z.object({
|
|
936
989
|
ok: zod.z.literal(true),
|
|
937
990
|
key: zod.z.string(),
|
|
938
991
|
bytes: zod.z.number(),
|
|
@@ -951,7 +1004,8 @@ zod.z.object({
|
|
|
951
1004
|
produced_at: zod.z.number(),
|
|
952
1005
|
produced_by: zod.z.string(),
|
|
953
1006
|
expires_at: zod.z.number().nullable(),
|
|
954
|
-
tombstoned: zod.z.number()
|
|
1007
|
+
tombstoned: zod.z.number(),
|
|
1008
|
+
tags: zod.z.array(zod.z.string())
|
|
955
1009
|
}))
|
|
956
1010
|
});
|
|
957
1011
|
zod.z.object({
|
|
@@ -1038,12 +1092,15 @@ var RecordItemSchema = zod.z.object({
|
|
|
1038
1092
|
updated_by: zod.z.string(),
|
|
1039
1093
|
tags: zod.z.array(zod.z.string())
|
|
1040
1094
|
});
|
|
1041
|
-
|
|
1095
|
+
RecordItemSchema.extend({
|
|
1096
|
+
fence: zod.z.number().int()
|
|
1097
|
+
});
|
|
1098
|
+
var RecordGetResponseSchema = zod.z.object({
|
|
1042
1099
|
ok: zod.z.literal(true),
|
|
1043
1100
|
record: RecordItemSchema,
|
|
1044
1101
|
fence: zod.z.number().int()
|
|
1045
1102
|
});
|
|
1046
|
-
zod.z.object({
|
|
1103
|
+
var RecordMutateResponseSchema = zod.z.object({
|
|
1047
1104
|
ok: zod.z.literal(true),
|
|
1048
1105
|
record: RecordItemSchema,
|
|
1049
1106
|
fence: zod.z.number().int(),
|
|
@@ -1058,7 +1115,7 @@ var RecordListItemSchema = zod.z.object({
|
|
|
1058
1115
|
archived: zod.z.number().int(),
|
|
1059
1116
|
tags: zod.z.array(zod.z.string())
|
|
1060
1117
|
});
|
|
1061
|
-
zod.z.object({
|
|
1118
|
+
var RecordListResponseSchema = zod.z.object({
|
|
1062
1119
|
ok: zod.z.literal(true),
|
|
1063
1120
|
items: zod.z.array(RecordListItemSchema),
|
|
1064
1121
|
meta: zod.z.object({
|
|
@@ -1078,9 +1135,12 @@ var RecordHistoryItemSchema = zod.z.object({
|
|
|
1078
1135
|
source_artifact_key: zod.z.string().nullable(),
|
|
1079
1136
|
actor: zod.z.string(),
|
|
1080
1137
|
created_at: zod.z.number().int(),
|
|
1081
|
-
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()
|
|
1082
1142
|
});
|
|
1083
|
-
zod.z.object({
|
|
1143
|
+
var RecordHistoryResponseSchema = zod.z.object({
|
|
1084
1144
|
ok: zod.z.literal(true),
|
|
1085
1145
|
items: zod.z.array(RecordHistoryItemSchema),
|
|
1086
1146
|
meta: zod.z.object({
|
|
@@ -1190,392 +1250,208 @@ zod.z.object({
|
|
|
1190
1250
|
zod.z.object({
|
|
1191
1251
|
resolution: zod.z.string().optional()
|
|
1192
1252
|
});
|
|
1193
|
-
zod.z.object({
|
|
1253
|
+
var GateResponseSchema = zod.z.object({
|
|
1194
1254
|
ok: zod.z.literal(true),
|
|
1195
1255
|
gate: GateSchema
|
|
1196
1256
|
});
|
|
1197
|
-
zod.z.object({
|
|
1257
|
+
var GateListResponseSchema = zod.z.object({
|
|
1198
1258
|
ok: zod.z.literal(true),
|
|
1199
1259
|
gates: zod.z.array(GateSchema)
|
|
1200
1260
|
});
|
|
1201
1261
|
|
|
1202
|
-
// src/
|
|
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
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
)
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
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)}`
|
|
1249
1315
|
);
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
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
|
|
1259
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;
|
|
1260
1367
|
}
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
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`
|
|
1283
1391
|
);
|
|
1284
1392
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
);
|
|
1288
|
-
}
|
|
1289
|
-
if (!res.ok) {
|
|
1290
|
-
await this.throwApiError(res);
|
|
1291
|
-
}
|
|
1292
|
-
const body = await res.json();
|
|
1293
|
-
const shouldValidate = opts?.validate ?? this.validate;
|
|
1294
|
-
if (shouldValidate && opts?.schema) {
|
|
1295
|
-
const result = opts.schema.safeParse(body);
|
|
1296
|
-
if (!result.success) {
|
|
1297
|
-
const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
1298
|
-
throw new Error(
|
|
1299
|
-
`Unexpected response shape from ${method} ${path}:
|
|
1300
|
-
${issues}`
|
|
1301
|
-
);
|
|
1302
|
-
}
|
|
1303
|
-
return result.data;
|
|
1304
|
-
}
|
|
1305
|
-
return body;
|
|
1306
|
-
}
|
|
1307
|
-
async get(path, opts) {
|
|
1308
|
-
return this.request("GET", path, {
|
|
1309
|
-
schema: opts?.schema,
|
|
1310
|
-
query: opts?.query,
|
|
1311
|
-
validate: opts?.validate
|
|
1312
|
-
});
|
|
1313
|
-
}
|
|
1314
|
-
async post(path, body, opts) {
|
|
1315
|
-
return this.request("POST", path, {
|
|
1316
|
-
body,
|
|
1317
|
-
schema: opts?.schema,
|
|
1318
|
-
validate: opts?.validate
|
|
1319
|
-
});
|
|
1320
|
-
}
|
|
1321
|
-
async put(path, body, opts) {
|
|
1322
|
-
return this.request("PUT", path, {
|
|
1323
|
-
body,
|
|
1324
|
-
schema: opts?.schema,
|
|
1325
|
-
validate: opts?.validate
|
|
1326
|
-
});
|
|
1327
|
-
}
|
|
1328
|
-
async patch(path, body, opts) {
|
|
1329
|
-
return this.request("PATCH", path, {
|
|
1330
|
-
body,
|
|
1331
|
-
schema: opts?.schema,
|
|
1332
|
-
validate: opts?.validate
|
|
1333
|
-
});
|
|
1334
|
-
}
|
|
1335
|
-
async delete(path, opts) {
|
|
1336
|
-
return this.request("DELETE", path, {
|
|
1337
|
-
schema: opts?.schema,
|
|
1338
|
-
validate: opts?.validate
|
|
1339
|
-
});
|
|
1340
|
-
}
|
|
1341
|
-
async requestRaw(method, path, opts) {
|
|
1342
|
-
const url = new URL(path, `${this.baseUrl}/`);
|
|
1343
|
-
if (opts?.query) {
|
|
1344
|
-
for (const [key, value] of Object.entries(opts.query)) {
|
|
1345
|
-
if (value !== void 0) {
|
|
1346
|
-
url.searchParams.set(key, value);
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1393
|
+
const text = await res.text();
|
|
1394
|
+
return { content: text, mimeType: contentType };
|
|
1349
1395
|
}
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
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
|
|
1360
1409
|
});
|
|
1361
|
-
}
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
throw new Error(
|
|
1368
|
-
`Network error connecting to ${url.origin}: ${err instanceof Error ? err.message : String(err)}`
|
|
1369
|
-
);
|
|
1370
|
-
}
|
|
1371
|
-
if (!res.ok) {
|
|
1372
|
-
await this.throwApiError(res);
|
|
1373
|
-
}
|
|
1374
|
-
return res;
|
|
1375
|
-
}
|
|
1376
|
-
async postFormData(path, formData, opts) {
|
|
1377
|
-
const url = new URL(path, `${this.baseUrl}/`);
|
|
1378
|
-
const headers = {
|
|
1379
|
-
Authorization: `Bearer ${this.token}`,
|
|
1380
|
-
Accept: "application/json",
|
|
1381
|
-
...this.extraHeaders
|
|
1382
|
-
};
|
|
1383
|
-
let res;
|
|
1384
|
-
try {
|
|
1385
|
-
res = await fetch(url.toString(), {
|
|
1386
|
-
method: "POST",
|
|
1387
|
-
headers,
|
|
1388
|
-
body: formData,
|
|
1389
|
-
signal: this.createAbortSignal()
|
|
1410
|
+
},
|
|
1411
|
+
async renew(resource, fence, ttlMs) {
|
|
1412
|
+
return client.post(`${base}/renew`, {
|
|
1413
|
+
resource,
|
|
1414
|
+
fence,
|
|
1415
|
+
ttl_ms: ttlMs
|
|
1390
1416
|
});
|
|
1391
|
-
}
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
|
|
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)}`
|
|
1399
1430
|
);
|
|
1400
1431
|
}
|
|
1401
|
-
if (!res.ok) {
|
|
1402
|
-
await this.throwApiError(res);
|
|
1403
|
-
}
|
|
1404
|
-
const body = await res.json();
|
|
1405
|
-
const shouldValidate = opts?.validate ?? this.validate;
|
|
1406
|
-
if (shouldValidate && opts?.schema) {
|
|
1407
|
-
const result = opts.schema.safeParse(body);
|
|
1408
|
-
if (!result.success) {
|
|
1409
|
-
const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
1410
|
-
throw new Error(
|
|
1411
|
-
`Unexpected response shape from POST ${path}:
|
|
1412
|
-
${issues}`
|
|
1413
|
-
);
|
|
1414
|
-
}
|
|
1415
|
-
return result.data;
|
|
1416
|
-
}
|
|
1417
|
-
return body;
|
|
1418
|
-
}
|
|
1419
|
-
async throwApiError(res) {
|
|
1420
|
-
try {
|
|
1421
|
-
const body = await res.json();
|
|
1422
|
-
const parsed = ErrorEnvelopeSchema.safeParse(body);
|
|
1423
|
-
if (parsed.success) {
|
|
1424
|
-
const { code, message, retryable } = parsed.data.error;
|
|
1425
|
-
throw new TilaApiError(res.status, code, message, retryable);
|
|
1426
|
-
}
|
|
1427
|
-
} catch (err) {
|
|
1428
|
-
if (err instanceof TilaApiError) throw err;
|
|
1429
|
-
}
|
|
1430
|
-
throw new TilaApiError(
|
|
1431
|
-
res.status,
|
|
1432
|
-
"UNKNOWN",
|
|
1433
|
-
`HTTP ${res.status}: ${res.statusText}`,
|
|
1434
|
-
false
|
|
1435
|
-
);
|
|
1436
|
-
}
|
|
1437
|
-
};
|
|
1438
|
-
var TilaApiError = class extends Error {
|
|
1439
|
-
constructor(status, code, message, retryable) {
|
|
1440
|
-
super(message);
|
|
1441
|
-
this.status = status;
|
|
1442
|
-
this.code = code;
|
|
1443
|
-
this.retryable = retryable;
|
|
1444
|
-
this.name = "TilaApiError";
|
|
1445
|
-
}
|
|
1446
|
-
status;
|
|
1447
|
-
code;
|
|
1448
|
-
retryable;
|
|
1449
|
-
};
|
|
1450
|
-
function isTilaApiError(err) {
|
|
1451
|
-
return err instanceof TilaApiError;
|
|
1452
|
-
}
|
|
1453
|
-
async function exchangeGitHubToken(baseUrl, projectId, githubToken) {
|
|
1454
|
-
const url = `${baseUrl.replace(/\/+$/, "")}/api/auth/github/exchange`;
|
|
1455
|
-
let res;
|
|
1456
|
-
try {
|
|
1457
|
-
res = await fetch(url, {
|
|
1458
|
-
method: "POST",
|
|
1459
|
-
headers: { "Content-Type": "application/json" },
|
|
1460
|
-
body: JSON.stringify({
|
|
1461
|
-
project_id: projectId,
|
|
1462
|
-
github_token: githubToken
|
|
1463
|
-
})
|
|
1464
|
-
});
|
|
1465
|
-
} catch (err) {
|
|
1466
|
-
throw new Error(
|
|
1467
|
-
`Network error during GitHub token exchange: ${err instanceof Error ? err.message : String(err)}`
|
|
1468
|
-
);
|
|
1469
|
-
}
|
|
1470
|
-
if (!res.ok) {
|
|
1471
|
-
try {
|
|
1472
|
-
const body2 = await res.json();
|
|
1473
|
-
const parsed = ErrorEnvelopeSchema.safeParse(body2);
|
|
1474
|
-
if (parsed.success) {
|
|
1475
|
-
const { code, message, retryable } = parsed.data.error;
|
|
1476
|
-
throw new TilaApiError(res.status, code, message, retryable);
|
|
1477
|
-
}
|
|
1478
|
-
} catch (err) {
|
|
1479
|
-
if (err instanceof TilaApiError) throw err;
|
|
1480
|
-
}
|
|
1481
|
-
throw new TilaApiError(
|
|
1482
|
-
res.status,
|
|
1483
|
-
"UNKNOWN",
|
|
1484
|
-
`HTTP ${res.status}: ${res.statusText}`,
|
|
1485
|
-
false
|
|
1486
|
-
);
|
|
1487
|
-
}
|
|
1488
|
-
const body = await res.json();
|
|
1489
|
-
if (!body.session_token || typeof body.expires_at !== "number") {
|
|
1490
|
-
throw new TypeError(
|
|
1491
|
-
"Exchange returned unexpected response shape: missing session_token or expires_at"
|
|
1492
|
-
);
|
|
1493
|
-
}
|
|
1494
|
-
return {
|
|
1495
|
-
sessionToken: body.session_token,
|
|
1496
|
-
expiresAt: body.expires_at,
|
|
1497
|
-
permission: body.permission ?? "read"
|
|
1498
1432
|
};
|
|
1499
1433
|
}
|
|
1500
1434
|
|
|
1501
|
-
// src/retry.ts
|
|
1502
|
-
async function withRetry(fn, opts) {
|
|
1503
|
-
const maxRetries = opts?.maxRetries ?? 3;
|
|
1504
|
-
const baseDelayMs = opts?.baseDelayMs ?? 200;
|
|
1505
|
-
const maxDelayMs = opts?.maxDelayMs ?? 3e4;
|
|
1506
|
-
const jitter = opts?.jitter ?? true;
|
|
1507
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
1508
|
-
try {
|
|
1509
|
-
return await fn();
|
|
1510
|
-
} catch (err) {
|
|
1511
|
-
if (isTilaApiError(err) && err.retryable === false) {
|
|
1512
|
-
throw err;
|
|
1513
|
-
}
|
|
1514
|
-
if (attempt === maxRetries) {
|
|
1515
|
-
throw err;
|
|
1516
|
-
}
|
|
1517
|
-
const cap = Math.min(maxDelayMs, baseDelayMs * 2 ** attempt);
|
|
1518
|
-
const sleepMs = jitter ? Math.random() * cap : cap;
|
|
1519
|
-
await new Promise((resolve) => setTimeout(resolve, sleepMs));
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
throw new Error("withRetry: unreachable");
|
|
1523
|
-
}
|
|
1524
|
-
|
|
1525
|
-
// src/error-codes.ts
|
|
1526
|
-
var TILA_ERRORS = {
|
|
1527
|
-
// Auth / middleware (worker layer — SCREAMING_SNAKE_CASE wire values)
|
|
1528
|
-
UNAUTHORIZED: "UNAUTHORIZED",
|
|
1529
|
-
SESSION_EXPIRED: "SESSION_EXPIRED",
|
|
1530
|
-
RATE_LIMITED: "RATE_LIMITED",
|
|
1531
|
-
PERMISSION_DENIED: "PERMISSION_DENIED",
|
|
1532
|
-
PROJECT_MISMATCH: "PROJECT_MISMATCH",
|
|
1533
|
-
CSRF_MISSING_ORIGIN: "CSRF_MISSING_ORIGIN",
|
|
1534
|
-
CSRF_ORIGIN_MISMATCH: "CSRF_ORIGIN_MISMATCH",
|
|
1535
|
-
INTERNAL_ERROR: "INTERNAL_ERROR",
|
|
1536
|
-
DO_UNREACHABLE: "do-unreachable",
|
|
1537
|
-
// Auth endpoint specific
|
|
1538
|
-
REPO_NOT_ALLOWED: "REPO_NOT_ALLOWED",
|
|
1539
|
-
GITHUB_AUTH_FAILED: "GITHUB_AUTH_FAILED",
|
|
1540
|
-
HMAC_NOT_CONFIGURED: "HMAC_NOT_CONFIGURED",
|
|
1541
|
-
// Token endpoint specific
|
|
1542
|
-
TOKEN_NAME_CONFLICT: "TOKEN_NAME_CONFLICT",
|
|
1543
|
-
TOKEN_AUTHZ_DENIED: "TOKEN_AUTHZ_DENIED",
|
|
1544
|
-
TOKEN_NOT_FOUND: "TOKEN_NOT_FOUND",
|
|
1545
|
-
// Validation (worker layer uses SCREAMING_SNAKE for this code)
|
|
1546
|
-
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
1547
|
-
// DO errors (project-do-router — kebab-case wire values)
|
|
1548
|
-
STALE_FENCE: "stale-fence",
|
|
1549
|
-
NOT_FOUND: "not-found",
|
|
1550
|
-
GATE_ALREADY_SETTLED: "gate-already-settled",
|
|
1551
|
-
NO_FENCE: "no-fence",
|
|
1552
|
-
INTERNAL: "internal",
|
|
1553
|
-
CONSTRAINT_VIOLATION: "constraint-violation",
|
|
1554
|
-
IDEMPOTENCY_KEY_CONFLICT: "idempotency-key-conflict",
|
|
1555
|
-
// DO-layer validation uses kebab-case (distinct from VALIDATION_ERROR above)
|
|
1556
|
-
VALIDATION_ERROR_DO: "validation-error",
|
|
1557
|
-
ALREADY_HELD: "already-held",
|
|
1558
|
-
RENEW_FAILED: "renew-failed",
|
|
1559
|
-
BAD_REQUEST: "bad-request",
|
|
1560
|
-
MISSING_QUERY: "missing-query",
|
|
1561
|
-
INVALID_QUERY: "invalid-query",
|
|
1562
|
-
INVALID_SLOT: "invalid-slot",
|
|
1563
|
-
INVALID_RELATIONSHIP_TYPE: "invalid-relationship-type",
|
|
1564
|
-
// Fallback (SDK-generated when response is unparseable)
|
|
1565
|
-
UNKNOWN: "UNKNOWN"
|
|
1566
|
-
};
|
|
1567
|
-
|
|
1568
1435
|
// src/entities.ts
|
|
1569
1436
|
function _createMethods(client, base) {
|
|
1570
1437
|
return {
|
|
1571
|
-
async create(id, type, data) {
|
|
1572
|
-
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
|
+
});
|
|
1573
1445
|
},
|
|
1574
1446
|
async get(id) {
|
|
1575
1447
|
return client.get(`${base}/${id}`);
|
|
1576
1448
|
},
|
|
1577
1449
|
async list(query) {
|
|
1578
|
-
|
|
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 });
|
|
1579
1455
|
},
|
|
1580
1456
|
async update(id, data, fence) {
|
|
1581
1457
|
return client.patch(`${base}/${id}`, { data, fence });
|
|
@@ -1587,13 +1463,34 @@ function _createMethods(client, base) {
|
|
|
1587
1463
|
},
|
|
1588
1464
|
async addRelationship(fromId, toId, type) {
|
|
1589
1465
|
return client.post(
|
|
1590
|
-
`${base}
|
|
1466
|
+
`${base}/relationships`,
|
|
1591
1467
|
{
|
|
1468
|
+
from_id: fromId,
|
|
1592
1469
|
to_id: toId,
|
|
1593
1470
|
type
|
|
1594
1471
|
}
|
|
1595
1472
|
);
|
|
1596
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
|
+
},
|
|
1597
1494
|
async addArtifactRef(entityId, artifactKey, slot, metadata) {
|
|
1598
1495
|
return client.post(`${base}/${entityId}/artifact-refs`, {
|
|
1599
1496
|
artifact_key: artifactKey,
|
|
@@ -1608,366 +1505,663 @@ function _createMethods(client, base) {
|
|
|
1608
1505
|
}
|
|
1609
1506
|
};
|
|
1610
1507
|
}
|
|
1611
|
-
function createTaskMethods(client, projectId) {
|
|
1612
|
-
return _createMethods(client, `/projects/${projectId}/tasks`);
|
|
1613
|
-
}
|
|
1614
|
-
function createEntityMethods(client, projectId) {
|
|
1615
|
-
return _createMethods(client, `/projects/${projectId}/entities`);
|
|
1616
|
-
}
|
|
1617
|
-
function createWorkUnitMethods(client, projectId) {
|
|
1618
|
-
return _createMethods(client, `/projects/${projectId}/work-units`);
|
|
1619
|
-
}
|
|
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
|
+
}
|
|
1620
1722
|
|
|
1621
|
-
// src/
|
|
1622
|
-
function
|
|
1623
|
-
const base =
|
|
1723
|
+
// src/tokens.ts
|
|
1724
|
+
function createTokenMethods(client) {
|
|
1725
|
+
const base = "/api/tokens";
|
|
1624
1726
|
return {
|
|
1625
|
-
async
|
|
1626
|
-
return client.post(
|
|
1627
|
-
resource,
|
|
1628
|
-
mode,
|
|
1629
|
-
ttl_ms: ttlMs,
|
|
1630
|
-
...opts
|
|
1631
|
-
});
|
|
1632
|
-
},
|
|
1633
|
-
async renew(resource, fence, ttlMs) {
|
|
1634
|
-
return client.post(`${base}/renew`, {
|
|
1635
|
-
resource,
|
|
1636
|
-
fence,
|
|
1637
|
-
ttl_ms: ttlMs
|
|
1638
|
-
});
|
|
1727
|
+
async issue(name, note) {
|
|
1728
|
+
return client.post(base, { name, note });
|
|
1639
1729
|
},
|
|
1640
|
-
async
|
|
1641
|
-
return client.
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
});
|
|
1730
|
+
async revoke(name) {
|
|
1731
|
+
return client.delete(
|
|
1732
|
+
`${base}/${encodeURIComponent(name)}`
|
|
1733
|
+
);
|
|
1645
1734
|
},
|
|
1646
1735
|
async list() {
|
|
1647
1736
|
return client.get(base);
|
|
1648
|
-
},
|
|
1649
|
-
async get(resource) {
|
|
1650
|
-
return client.get(
|
|
1651
|
-
`${base}/${encodeURIComponent(resource)}`
|
|
1652
|
-
);
|
|
1653
1737
|
}
|
|
1654
1738
|
};
|
|
1655
1739
|
}
|
|
1656
1740
|
|
|
1657
|
-
// src/
|
|
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
|
-
|
|
1688
|
-
|
|
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);
|
|
1689
1810
|
}
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
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)}`
|
|
1706
1838
|
);
|
|
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
|
-
|
|
1736
|
-
|
|
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);
|
|
1737
1898
|
}
|
|
1738
|
-
|
|
1739
|
-
}
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
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()
|
|
1748
1911
|
});
|
|
1749
|
-
|
|
1750
|
-
if (
|
|
1751
|
-
const body2 = await res.json().catch(() => ({}));
|
|
1912
|
+
} catch (err) {
|
|
1913
|
+
if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
|
|
1752
1914
|
throw new Error(
|
|
1753
|
-
`
|
|
1915
|
+
`Request to ${url.origin} timed out after ${this.timeoutMs}ms`
|
|
1754
1916
|
);
|
|
1755
1917
|
}
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
},
|
|
1759
|
-
async writeText(content, opts) {
|
|
1760
|
-
return client.post(`${base}/text`, {
|
|
1761
|
-
content,
|
|
1762
|
-
kind: opts.kind,
|
|
1763
|
-
mime_type: opts.mimeType ?? "text/markdown",
|
|
1764
|
-
resource: opts.resource,
|
|
1765
|
-
fence: opts.fence
|
|
1766
|
-
});
|
|
1767
|
-
},
|
|
1768
|
-
async readText(key) {
|
|
1769
|
-
const res = await client.requestRaw(
|
|
1770
|
-
"GET",
|
|
1771
|
-
`${base}/${encodeURIComponent(key)}`
|
|
1918
|
+
throw new Error(
|
|
1919
|
+
`Network error connecting to ${url.origin}: ${err instanceof Error ? err.message : String(err)}`
|
|
1772
1920
|
);
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
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`
|
|
1777
1946
|
);
|
|
1778
1947
|
}
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
}
|
|
1782
|
-
};
|
|
1783
|
-
}
|
|
1784
|
-
|
|
1785
|
-
// src/tokens.ts
|
|
1786
|
-
function createTokenMethods(client) {
|
|
1787
|
-
const base = "/api/tokens";
|
|
1788
|
-
return {
|
|
1789
|
-
async issue(name, note) {
|
|
1790
|
-
return client.post(base, { name, note });
|
|
1791
|
-
},
|
|
1792
|
-
async revoke(name) {
|
|
1793
|
-
return client.delete(
|
|
1794
|
-
`${base}/${encodeURIComponent(name)}`
|
|
1948
|
+
throw new Error(
|
|
1949
|
+
`Network error connecting to ${url.origin}: ${err instanceof Error ? err.message : String(err)}`
|
|
1795
1950
|
);
|
|
1796
|
-
},
|
|
1797
|
-
async list() {
|
|
1798
|
-
return client.get(base);
|
|
1799
1951
|
}
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
// src/journal.ts
|
|
1804
|
-
function createJournalMethods(client, projectId) {
|
|
1805
|
-
const base = `/projects/${projectId}/journal`;
|
|
1806
|
-
return {
|
|
1807
|
-
async query(opts) {
|
|
1808
|
-
return client.get(base, { query: opts });
|
|
1952
|
+
if (!res.ok) {
|
|
1953
|
+
await this.throwApiError(res);
|
|
1809
1954
|
}
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
},
|
|
1823
|
-
async list() {
|
|
1824
|
-
return client.get(base);
|
|
1825
|
-
},
|
|
1826
|
-
/**
|
|
1827
|
-
* List all presence records across all machines, including whether each is active.
|
|
1828
|
-
* Hits GET /projects/:projectId/presence/all
|
|
1829
|
-
*/
|
|
1830
|
-
async listAll() {
|
|
1831
|
-
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;
|
|
1832
1967
|
}
|
|
1833
|
-
|
|
1834
|
-
}
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
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;
|
|
1839
2003
|
}
|
|
1840
|
-
function
|
|
1841
|
-
const
|
|
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
|
-
|
|
1867
|
-
async unarchive(type, key, req) {
|
|
1868
|
-
return client.post(
|
|
1869
|
-
`${base}/${type}/~/unarchive/${encodeKey(key)}`,
|
|
1870
|
-
req
|
|
1871
|
-
);
|
|
1872
|
-
},
|
|
1873
|
-
async history(type, key, opts) {
|
|
1874
|
-
const query = {};
|
|
1875
|
-
if (opts?.limit !== void 0) query.limit = String(opts.limit);
|
|
1876
|
-
if (opts?.values !== void 0) query.values = String(opts.values);
|
|
1877
|
-
return client.get(
|
|
1878
|
-
`${base}/${type}/~/history/${encodeKey(key)}`,
|
|
1879
|
-
{ query }
|
|
1880
|
-
);
|
|
1881
|
-
},
|
|
1882
|
-
async list(type, query) {
|
|
1883
|
-
return client.get(`${base}/${type}`, { query });
|
|
1884
|
-
},
|
|
1885
|
-
async types() {
|
|
1886
|
-
return client.get(`${base}/_types`);
|
|
1887
|
-
},
|
|
1888
|
-
async typesInUse() {
|
|
1889
|
-
const raw = await client.get(`${base}/_types`);
|
|
1890
|
-
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;
|
|
1891
2031
|
}
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
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
|
+
}
|
|
1898
2045
|
return {
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
async apply(schema, strategy) {
|
|
1903
|
-
return client.post(`${base}/apply`, { schema, strategy });
|
|
1904
|
-
},
|
|
1905
|
-
async history(opts) {
|
|
1906
|
-
return client.get(`${base}/history`, { query: opts });
|
|
1907
|
-
}
|
|
2046
|
+
sessionToken: body.session_token,
|
|
2047
|
+
expiresAt: body.expires_at,
|
|
2048
|
+
permission: body.permission ?? "read"
|
|
1908
2049
|
};
|
|
1909
2050
|
}
|
|
1910
|
-
|
|
1911
|
-
// src/signals.ts
|
|
1912
|
-
function createSignalMethods(client, projectId) {
|
|
1913
|
-
const base = `/projects/${projectId}/signals`;
|
|
2051
|
+
function buildHttpFacade(client, projectId) {
|
|
1914
2052
|
return {
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
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: () => {
|
|
1926
2067
|
}
|
|
1927
2068
|
};
|
|
1928
2069
|
}
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
async list(query) {
|
|
1936
|
-
return client.get(base, { query });
|
|
1937
|
-
},
|
|
1938
|
-
/** Create a new gate. POST /projects/:id/gates */
|
|
1939
|
-
async create(req) {
|
|
1940
|
-
return client.post(base, req);
|
|
1941
|
-
},
|
|
1942
|
-
/** Resolve a gate. POST /projects/:id/gates/:gateId/resolve */
|
|
1943
|
-
async resolve(gateId, req) {
|
|
1944
|
-
return client.post(`${base}/${gateId}/resolve`, req ?? {});
|
|
1945
|
-
},
|
|
1946
|
-
/** Delete a gate. DELETE /projects/:id/gates/:gateId */
|
|
1947
|
-
async remove(gateId) {
|
|
1948
|
-
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
|
+
);
|
|
1949
2076
|
}
|
|
1950
|
-
|
|
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);
|
|
1951
2096
|
}
|
|
1952
2097
|
|
|
1953
|
-
// src/
|
|
1954
|
-
function
|
|
1955
|
-
const
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
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));
|
|
1967
2117
|
}
|
|
1968
|
-
}
|
|
2118
|
+
}
|
|
2119
|
+
throw new Error("withRetry: unreachable");
|
|
1969
2120
|
}
|
|
1970
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
|
+
|
|
1971
2165
|
// src/indexes.ts
|
|
1972
2166
|
function createIndexMethods(client, projectId) {
|
|
1973
2167
|
const base = `/projects/${projectId}/artifacts`;
|
|
@@ -2010,26 +2204,240 @@ function createIndexMethods(client, projectId) {
|
|
|
2010
2204
|
}
|
|
2011
2205
|
};
|
|
2012
2206
|
}
|
|
2013
|
-
|
|
2014
|
-
// src/
|
|
2015
|
-
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);
|
|
2016
2413
|
return {
|
|
2017
|
-
|
|
2018
|
-
async
|
|
2019
|
-
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
|
+
};
|
|
2020
2431
|
}
|
|
2021
2432
|
};
|
|
2022
2433
|
}
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
function createSearchMethods(client, projectId) {
|
|
2026
|
-
const base = `/projects/${projectId}`;
|
|
2434
|
+
function createNamespace(client, projectId, ns) {
|
|
2435
|
+
validateNamespace(ns);
|
|
2027
2436
|
return {
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
}
|
|
2437
|
+
tasks: namespacedTaskMethods(client, projectId, ns),
|
|
2438
|
+
records: namespacedRecordMethods(client, projectId, ns),
|
|
2439
|
+
artifacts: namespacedArtifactMethods(client, projectId, ns),
|
|
2440
|
+
templates: namespacedTemplateMethods(client, projectId, ns)
|
|
2033
2441
|
};
|
|
2034
2442
|
}
|
|
2035
2443
|
|
|
@@ -2141,17 +2549,884 @@ async function withClaim(client, projectId, resource, mode, ttlMs, callback) {
|
|
|
2141
2549
|
}
|
|
2142
2550
|
}
|
|
2143
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
|
+
};
|
|
2144
3414
|
|
|
2145
3415
|
exports.ClaimHandle = ClaimHandle;
|
|
3416
|
+
exports.RemoteArtifactBackend = RemoteArtifactBackend;
|
|
3417
|
+
exports.RemoteBackend = RemoteBackend;
|
|
3418
|
+
exports.RemoteRecordBackend = RemoteRecordBackend;
|
|
2146
3419
|
exports.TILA_ERRORS = TILA_ERRORS;
|
|
2147
3420
|
exports.TilaApiError = TilaApiError;
|
|
2148
3421
|
exports.TilaClient = TilaClient;
|
|
3422
|
+
exports.applyPrefix = applyPrefix;
|
|
2149
3423
|
exports.createArtifactMethods = createArtifactMethods;
|
|
2150
3424
|
exports.createClaimMethods = createClaimMethods;
|
|
2151
3425
|
exports.createEntityMethods = createEntityMethods;
|
|
2152
3426
|
exports.createGateMethods = createGateMethods;
|
|
2153
3427
|
exports.createIndexMethods = createIndexMethods;
|
|
2154
3428
|
exports.createJournalMethods = createJournalMethods;
|
|
3429
|
+
exports.createNamespace = createNamespace;
|
|
2155
3430
|
exports.createPresenceMethods = createPresenceMethods;
|
|
2156
3431
|
exports.createRecordMethods = createRecordMethods;
|
|
2157
3432
|
exports.createSchemaMethods = createSchemaMethods;
|
|
@@ -2160,9 +3435,12 @@ exports.createSignalMethods = createSignalMethods;
|
|
|
2160
3435
|
exports.createSummaryMethods = createSummaryMethods;
|
|
2161
3436
|
exports.createTaskMethods = createTaskMethods;
|
|
2162
3437
|
exports.createTemplateMethods = createTemplateMethods;
|
|
3438
|
+
exports.createTila = createTila;
|
|
2163
3439
|
exports.createTokenMethods = createTokenMethods;
|
|
2164
3440
|
exports.createWorkUnitMethods = createWorkUnitMethods;
|
|
2165
3441
|
exports.exchangeGitHubToken = exchangeGitHubToken;
|
|
2166
3442
|
exports.isTilaApiError = isTilaApiError;
|
|
3443
|
+
exports.stripPrefix = stripPrefix;
|
|
3444
|
+
exports.validateNamespace = validateNamespace;
|
|
2167
3445
|
exports.withClaim = withClaim;
|
|
2168
3446
|
exports.withRetry = withRetry;
|