tila-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,2168 @@
1
+ 'use strict';
2
+
3
+ var module$1 = require('module');
4
+ var zod = require('zod');
5
+
6
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
7
+ // src/client.ts
8
+ zod.z.object({
9
+ id: zod.z.string(),
10
+ type: zod.z.string(),
11
+ schema_version: zod.z.number().int(),
12
+ data: zod.z.record(zod.z.unknown()),
13
+ archived: zod.z.number().int().default(0),
14
+ created_at: zod.z.number().int(),
15
+ updated_at: zod.z.number().int(),
16
+ created_by: zod.z.string()
17
+ });
18
+ var ClaimModeSchema = zod.z.enum(["exclusive", "owner", "presence"]);
19
+ zod.z.object({
20
+ resource: zod.z.string(),
21
+ machine: zod.z.string(),
22
+ user: zod.z.string(),
23
+ mode: ClaimModeSchema,
24
+ fence: zod.z.number().int(),
25
+ acquired_at: zod.z.number().int(),
26
+ expires_at: zod.z.number().int(),
27
+ metadata: zod.z.record(zod.z.unknown()).optional()
28
+ });
29
+ var JournalEventKindSchema = zod.z.enum([
30
+ "entity.created",
31
+ "entity.updated",
32
+ "entity.archived",
33
+ "claim.acquired",
34
+ "claim.renewed",
35
+ "claim.released",
36
+ "artifact.produced",
37
+ "artifact.expired",
38
+ "artifact.tombstoned",
39
+ "artifact.reconciled",
40
+ "artifact.search.rebuilt",
41
+ "schema.applied",
42
+ "artifact.relationship.added",
43
+ "entity.artifact.referenced",
44
+ "gate.created",
45
+ "gate.resolved",
46
+ "gate.timed_out",
47
+ "gate.cancelled",
48
+ "template.instantiated",
49
+ "record.created",
50
+ "record.updated",
51
+ "record.archived",
52
+ "record.unarchived"
53
+ ]);
54
+ zod.z.object({
55
+ seq: zod.z.number().int(),
56
+ t: zod.z.number().int(),
57
+ kind: JournalEventKindSchema,
58
+ resource: zod.z.string(),
59
+ actor: zod.z.string(),
60
+ token_id: zod.z.string().nullable().optional(),
61
+ fence: zod.z.number().int().nullable(),
62
+ data: zod.z.record(zod.z.unknown()),
63
+ source: zod.z.string().nullable().optional(),
64
+ source_version: zod.z.string().nullable().optional()
65
+ });
66
+ zod.z.object({
67
+ r2_key: zod.z.string(),
68
+ resource: zod.z.string().nullable(),
69
+ kind: zod.z.string(),
70
+ // open set, config-defined per tila.schema.toml
71
+ sha256: zod.z.string(),
72
+ bytes: zod.z.number().int(),
73
+ fence: zod.z.number().int().nullable(),
74
+ mime_type: zod.z.string(),
75
+ produced_at: zod.z.number().int(),
76
+ produced_by: zod.z.string(),
77
+ expires_at: zod.z.number().int().nullable(),
78
+ tombstoned: zod.z.number().int().default(0)
79
+ });
80
+ zod.z.object({
81
+ entity_id: zod.z.string(),
82
+ artifact_key: zod.z.string(),
83
+ slot: zod.z.string(),
84
+ metadata: zod.z.record(zod.z.unknown()).default({}),
85
+ created_at: zod.z.number().int()
86
+ });
87
+ var ArtifactRelationshipTypeSchema = zod.z.enum([
88
+ "references",
89
+ "supersedes",
90
+ "derived-from",
91
+ "index-of",
92
+ "entry-of"
93
+ ]);
94
+ zod.z.object({
95
+ from_key: zod.z.string(),
96
+ to_key: zod.z.string().nullable(),
97
+ to_uri: zod.z.string().nullable(),
98
+ type: ArtifactRelationshipTypeSchema,
99
+ metadata: zod.z.record(zod.z.unknown()).default({}),
100
+ created_at: zod.z.number().int()
101
+ });
102
+ var ArtifactSearchResultSchema = zod.z.object({
103
+ r2_key: zod.z.string(),
104
+ kind: zod.z.string(),
105
+ resource: zod.z.string().nullable(),
106
+ mime_type: zod.z.string(),
107
+ produced_at: zod.z.number().int(),
108
+ title: zod.z.string().nullable(),
109
+ snippet: zod.z.string().nullable(),
110
+ indexed_at: zod.z.number().int()
111
+ });
112
+ var EntitySearchResultSchema = zod.z.object({
113
+ entity_id: zod.z.string(),
114
+ entity_type: zod.z.string(),
115
+ name: zod.z.string().nullable(),
116
+ snippet: zod.z.string().nullable(),
117
+ indexed_at: zod.z.number().int()
118
+ });
119
+ zod.z.object({
120
+ resource: zod.z.string(),
121
+ current_fence: zod.z.number().int()
122
+ });
123
+ zod.z.object({
124
+ machine: zod.z.string(),
125
+ last_seen: zod.z.number().int(),
126
+ info: zod.z.record(zod.z.unknown())
127
+ });
128
+ var EntityRelationshipTypeSchema = zod.z.enum([
129
+ "parent-child",
130
+ "blocks",
131
+ "soft-blocks",
132
+ "related",
133
+ "discovered-from"
134
+ ]);
135
+ var EntityRelationshipSchema = zod.z.object({
136
+ from_id: zod.z.string(),
137
+ to_id: zod.z.string(),
138
+ type: EntityRelationshipTypeSchema,
139
+ schema_version: zod.z.number().int(),
140
+ created_at: zod.z.number().int()
141
+ });
142
+ var SignalKindSchema = zod.z.enum([
143
+ "conflict",
144
+ "ready",
145
+ "info",
146
+ "request"
147
+ ]);
148
+ var SignalSchema = zod.z.object({
149
+ id: zod.z.string(),
150
+ target: zod.z.string(),
151
+ kind: SignalKindSchema,
152
+ resource: zod.z.string().nullish(),
153
+ payload: zod.z.unknown(),
154
+ created_by: zod.z.string(),
155
+ created_at: zod.z.number(),
156
+ expires_at: zod.z.number(),
157
+ acked_at: zod.z.number().nullable()
158
+ });
159
+ zod.z.object({
160
+ target: zod.z.string().min(1),
161
+ kind: SignalKindSchema,
162
+ resource: zod.z.string().optional(),
163
+ payload: zod.z.unknown().optional(),
164
+ ttl_ms: zod.z.number().int().min(1e3).max(864e5).optional()
165
+ });
166
+ zod.z.object({
167
+ ok: zod.z.literal(true),
168
+ id: zod.z.string()
169
+ });
170
+ zod.z.object({
171
+ ok: zod.z.literal(true),
172
+ signals: zod.z.array(SignalSchema)
173
+ });
174
+ zod.z.object({
175
+ ok: zod.z.literal(true)
176
+ });
177
+ zod.z.object({
178
+ version: zod.z.number().int(),
179
+ definition: zod.z.string(),
180
+ // TOML content as string; SQL column is `definition TEXT NOT NULL`
181
+ applied_at: zod.z.number().int(),
182
+ applied_by: zod.z.string()
183
+ });
184
+ zod.z.enum(["relax", "force"]);
185
+ zod.z.object({
186
+ project_id: zod.z.string(),
187
+ display_name: zod.z.string().nullable(),
188
+ created_at: zod.z.number().int(),
189
+ created_by: zod.z.string(),
190
+ cloudflare_account_id: zod.z.string(),
191
+ schema_version: zod.z.number().int(),
192
+ archived: zod.z.number().int().default(0)
193
+ });
194
+ zod.z.object({
195
+ token_hash: zod.z.string(),
196
+ project_id: zod.z.string(),
197
+ name: zod.z.string(),
198
+ note: zod.z.string().nullable(),
199
+ scopes: zod.z.string(),
200
+ // "full" in v0.1
201
+ created_at: zod.z.number().int(),
202
+ created_by: zod.z.string(),
203
+ last_used_at: zod.z.number().int().nullable(),
204
+ revoked_at: zod.z.number().int().nullable(),
205
+ revoked_by: zod.z.string().nullable()
206
+ });
207
+ zod.z.object({
208
+ key: zod.z.string(),
209
+ project_id: zod.z.string(),
210
+ created_at: zod.z.number().int(),
211
+ response_json: zod.z.string(),
212
+ status_code: zod.z.number().int(),
213
+ request_hash: zod.z.string().nullable().optional()
214
+ });
215
+ zod.z.object({
216
+ project_id: zod.z.string(),
217
+ backend: zod.z.enum(["cloudflare", "local"]).optional(),
218
+ worker_url: zod.z.string().url().optional(),
219
+ custom_domain: zod.z.string().optional(),
220
+ schema_version: zod.z.number().int(),
221
+ tila_version: zod.z.string(),
222
+ created_at: zod.z.string(),
223
+ // ISO-8601 string from TOML
224
+ cloudflare: zod.z.object({
225
+ account_id: zod.z.string()
226
+ }).optional(),
227
+ backends: zod.z.object({
228
+ entity: zod.z.string().default("do-sqlite"),
229
+ coordination: zod.z.string().default("do-sqlite"),
230
+ artifact: zod.z.string().default("r2"),
231
+ auth: zod.z.string().default("d1")
232
+ }).optional(),
233
+ local: zod.z.object({
234
+ db_path: zod.z.string(),
235
+ artifacts_path: zod.z.string(),
236
+ org: zod.z.string().optional()
237
+ }).optional(),
238
+ auth: zod.z.object({
239
+ mode: zod.z.enum(["tila-token", "github-repo"]).default("tila-token")
240
+ }).optional(),
241
+ github: zod.z.object({
242
+ host: zod.z.string().default("github.com"),
243
+ owner: zod.z.string(),
244
+ repo: zod.z.string(),
245
+ repo_id: zod.z.number().int().optional()
246
+ }).optional()
247
+ });
248
+ function arrayToRecord(val) {
249
+ if (!Array.isArray(val))
250
+ return val;
251
+ const entries = val.map((f) => [f.name, f]);
252
+ return Object.fromEntries(entries);
253
+ }
254
+ var FieldDeclarationSchema = zod.z.object({
255
+ type: zod.z.string(),
256
+ required: zod.z.boolean().default(false),
257
+ default: zod.z.unknown().optional(),
258
+ default_for_legacy: zod.z.unknown().optional(),
259
+ name: zod.z.string().optional(),
260
+ values: zod.z.array(zod.z.string()).optional()
261
+ });
262
+ var ReferenceSlotSchema = zod.z.object({
263
+ name: zod.z.string(),
264
+ multiple: zod.z.boolean().default(false),
265
+ kinds: zod.z.array(zod.z.string())
266
+ });
267
+ var WorkUnitSchema = zod.z.object({
268
+ fields: zod.z.preprocess(arrayToRecord, zod.z.record(FieldDeclarationSchema)).default({}),
269
+ parents: zod.z.array(zod.z.string()).default([]),
270
+ required_parent: zod.z.boolean().default(false),
271
+ references: zod.z.array(ReferenceSlotSchema).optional()
272
+ });
273
+ var ArtifactKindSchema = zod.z.object({
274
+ mime_types: zod.z.array(zod.z.string().min(1)).default([]),
275
+ retention_days: zod.z.number().int().min(0).default(0),
276
+ requires_reference_to: zod.z.array(zod.z.string()).optional(),
277
+ searchable: zod.z.boolean().default(false),
278
+ search_mode: zod.z.enum(["none", "full_text"]).default("none"),
279
+ auto_supersedes: zod.z.boolean().default(false)
280
+ });
281
+ var TemplateEntitySchema = zod.z.object({
282
+ id_suffix: zod.z.string().default(""),
283
+ type: zod.z.string(),
284
+ data: zod.z.record(zod.z.unknown()).default({})
285
+ });
286
+ var TemplateRelationshipSchema = zod.z.object({
287
+ from: zod.z.string(),
288
+ to: zod.z.string(),
289
+ type: zod.z.string()
290
+ });
291
+ var TemplateDefinitionSchema = zod.z.object({
292
+ description: zod.z.string().optional(),
293
+ entities: zod.z.record(TemplateEntitySchema),
294
+ relationships: zod.z.array(TemplateRelationshipSchema).default([])
295
+ });
296
+ var RecordDefinitionFieldsSchema = zod.z.preprocess(arrayToRecord, zod.z.record(FieldDeclarationSchema)).default({});
297
+ var RecordDefinitionSchema = zod.z.object({
298
+ format: zod.z.enum(["json", "yaml"]).default("json"),
299
+ history: zod.z.enum(["revision", "snapshot"]).default("revision"),
300
+ key_description: zod.z.string().optional(),
301
+ writers: zod.z.array(zod.z.enum(["human", "agent"])).optional(),
302
+ mcp_resource: zod.z.boolean().default(false),
303
+ schema_ref: zod.z.string().optional(),
304
+ fields: RecordDefinitionFieldsSchema
305
+ });
306
+ zod.z.object({
307
+ schema_version: zod.z.number().int().positive(),
308
+ work_units: zod.z.record(WorkUnitSchema).default({}),
309
+ hierarchy: zod.z.object({
310
+ levels: zod.z.array(zod.z.string()).default([]),
311
+ max_depth: zod.z.number().int().positive().optional()
312
+ }).optional(),
313
+ artifacts: zod.z.record(ArtifactKindSchema).optional(),
314
+ artifact_relationships: zod.z.object({
315
+ types: zod.z.array(zod.z.string()).optional()
316
+ }).optional(),
317
+ entity_artifact_references: zod.z.object({
318
+ slots: zod.z.array(zod.z.string()).optional()
319
+ }).optional(),
320
+ templates: zod.z.record(TemplateDefinitionSchema).optional(),
321
+ records: zod.z.record(RecordDefinitionSchema).default({})
322
+ });
323
+ zod.z.object({
324
+ account_id: zod.z.string(),
325
+ account_name: zod.z.string(),
326
+ d1_database_id: zod.z.string(),
327
+ worker_url: zod.z.string().url().optional(),
328
+ r2_bucket_name: zod.z.string().optional(),
329
+ hmac_key: zod.z.string().optional(),
330
+ sweep_secret: zod.z.string().optional(),
331
+ github_app: zod.z.object({
332
+ app_id: zod.z.number().int().positive(),
333
+ installation_id: zod.z.number().int().positive()
334
+ }).optional(),
335
+ pages_project_name: zod.z.string().optional(),
336
+ infra_slug: zod.z.string().optional()
337
+ });
338
+ 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
+ var RecordKeySchema = zod.z.string().superRefine((val, ctx) => {
340
+ if (val.length === 0) {
341
+ ctx.addIssue({
342
+ code: zod.z.ZodIssueCode.custom,
343
+ message: "Record key must not be empty"
344
+ });
345
+ return;
346
+ }
347
+ if (val.length > 256) {
348
+ ctx.addIssue({
349
+ code: zod.z.ZodIssueCode.custom,
350
+ message: "Record key must not exceed 256 characters"
351
+ });
352
+ return;
353
+ }
354
+ const segments = val.split("/");
355
+ if (segments.some((s) => s === "")) {
356
+ ctx.addIssue({
357
+ code: zod.z.ZodIssueCode.custom,
358
+ message: "Record key must not have empty segments (no leading slash, trailing slash, or consecutive slashes)"
359
+ });
360
+ return;
361
+ }
362
+ if (segments.length > 8) {
363
+ ctx.addIssue({
364
+ code: zod.z.ZodIssueCode.custom,
365
+ message: "Record key must not exceed 8 segments"
366
+ });
367
+ return;
368
+ }
369
+ for (const seg of segments) {
370
+ if (seg.length > 64) {
371
+ ctx.addIssue({
372
+ code: zod.z.ZodIssueCode.custom,
373
+ message: `Segment "${seg}" exceeds 64 characters`
374
+ });
375
+ return;
376
+ }
377
+ if (seg === "." || seg === "..") {
378
+ ctx.addIssue({
379
+ code: zod.z.ZodIssueCode.custom,
380
+ message: `Segment "${seg}" is reserved`
381
+ });
382
+ return;
383
+ }
384
+ if (seg.startsWith(".") || seg.startsWith("_")) {
385
+ ctx.addIssue({
386
+ code: zod.z.ZodIssueCode.custom,
387
+ message: `Segment "${seg}" must not start with '.' or '_'`
388
+ });
389
+ return;
390
+ }
391
+ if (seg.includes("~")) {
392
+ ctx.addIssue({
393
+ code: zod.z.ZodIssueCode.custom,
394
+ message: `Segment "${seg}" must not contain '~'`
395
+ });
396
+ return;
397
+ }
398
+ if (seg.includes(":")) {
399
+ ctx.addIssue({
400
+ code: zod.z.ZodIssueCode.custom,
401
+ message: `Segment "${seg}" must not contain ':'`
402
+ });
403
+ return;
404
+ }
405
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(seg)) {
406
+ ctx.addIssue({
407
+ code: zod.z.ZodIssueCode.custom,
408
+ message: `Segment "${seg}" contains invalid characters`
409
+ });
410
+ return;
411
+ }
412
+ }
413
+ });
414
+ var RecordTagSchema = zod.z.array(zod.z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_:.-]{0,63}$/, "Invalid tag format")).transform((tags) => {
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");
426
+ function sortKeysDeep(v) {
427
+ if (Array.isArray(v))
428
+ return v.map(sortKeysDeep);
429
+ if (v !== null && typeof v === "object") {
430
+ const sorted = {};
431
+ for (const k of Object.keys(v).sort()) {
432
+ sorted[k] = sortKeysDeep(v[k]);
433
+ }
434
+ return sorted;
435
+ }
436
+ return v;
437
+ }
438
+ function canonicalJson(value) {
439
+ return JSON.stringify(sortKeysDeep(value));
440
+ }
441
+ var MAX_RECORD_VALUE_BYTES = 65536;
442
+ zod.z.record(zod.z.unknown()).refine((value) => {
443
+ const canonical = canonicalJson(value);
444
+ return new TextEncoder().encode(canonical).length <= MAX_RECORD_VALUE_BYTES;
445
+ }, "Record value exceeds 64 KiB canonical JSON limit");
446
+
447
+ // ../schemas/dist/api.js
448
+ var ErrorEnvelopeSchema = zod.z.object({
449
+ ok: zod.z.literal(false),
450
+ error: zod.z.object({
451
+ code: zod.z.string(),
452
+ message: zod.z.string(),
453
+ retryable: zod.z.boolean(),
454
+ gateIds: zod.z.array(zod.z.string()).optional()
455
+ })
456
+ });
457
+ zod.z.object({
458
+ resource: zod.z.string(),
459
+ mode: ClaimModeSchema,
460
+ ttl_ms: zod.z.number().int().positive(),
461
+ idempotency_key: zod.z.string().optional(),
462
+ metadata: zod.z.record(zod.z.unknown()).optional()
463
+ });
464
+ zod.z.object({
465
+ ok: zod.z.literal(true),
466
+ fence: zod.z.number().int(),
467
+ expires_at: zod.z.number().int()
468
+ });
469
+ zod.z.object({
470
+ resource: zod.z.string(),
471
+ fence: zod.z.number().int(),
472
+ ttl_ms: zod.z.number().int().positive()
473
+ });
474
+ zod.z.object({
475
+ ok: zod.z.literal(true),
476
+ expires_at: zod.z.number().int()
477
+ });
478
+ zod.z.object({
479
+ resource: zod.z.string(),
480
+ fence: zod.z.number().int()
481
+ });
482
+ zod.z.object({
483
+ ok: zod.z.literal(true)
484
+ });
485
+ zod.z.object({
486
+ ok: zod.z.literal(true),
487
+ claim: zod.z.object({
488
+ resource: zod.z.string(),
489
+ machine: zod.z.string(),
490
+ user: zod.z.string(),
491
+ mode: ClaimModeSchema,
492
+ fence: zod.z.number().int(),
493
+ acquired_at: zod.z.number().int(),
494
+ expires_at: zod.z.number().int(),
495
+ metadata: zod.z.record(zod.z.unknown()).optional()
496
+ }).nullable()
497
+ });
498
+ zod.z.object({
499
+ ok: zod.z.literal(true),
500
+ claims: zod.z.array(zod.z.object({
501
+ resource: zod.z.string(),
502
+ machine: zod.z.string(),
503
+ user: zod.z.string(),
504
+ mode: ClaimModeSchema,
505
+ fence: zod.z.number().int(),
506
+ acquired_at: zod.z.number().int(),
507
+ expires_at: zod.z.number().int(),
508
+ metadata: zod.z.record(zod.z.unknown()).optional()
509
+ }))
510
+ });
511
+ zod.z.object({
512
+ id: zod.z.string(),
513
+ type: zod.z.string(),
514
+ data: zod.z.record(zod.z.unknown()).default({})
515
+ });
516
+ zod.z.object({
517
+ data: zod.z.record(zod.z.unknown()),
518
+ fence: zod.z.number().int()
519
+ });
520
+ zod.z.object({
521
+ fence: zod.z.number().int()
522
+ });
523
+ zod.z.object({
524
+ ok: zod.z.literal(true),
525
+ entity: zod.z.object({
526
+ id: zod.z.string(),
527
+ type: zod.z.string(),
528
+ schema_version: zod.z.number().int(),
529
+ data: zod.z.record(zod.z.unknown()),
530
+ archived: zod.z.number().int(),
531
+ created_at: zod.z.number().int(),
532
+ updated_at: zod.z.number().int(),
533
+ created_by: zod.z.string()
534
+ })
535
+ });
536
+ zod.z.object({
537
+ ok: zod.z.literal(true),
538
+ entities: zod.z.array(zod.z.object({
539
+ id: zod.z.string(),
540
+ type: zod.z.string(),
541
+ schema_version: zod.z.number().int(),
542
+ data: zod.z.record(zod.z.unknown()),
543
+ archived: zod.z.number().int(),
544
+ created_at: zod.z.number().int(),
545
+ updated_at: zod.z.number().int(),
546
+ created_by: zod.z.string()
547
+ }))
548
+ });
549
+ zod.z.object({
550
+ ok: zod.z.literal(true),
551
+ entities: zod.z.array(zod.z.object({
552
+ id: zod.z.string(),
553
+ type: zod.z.string(),
554
+ schema_version: zod.z.number().int(),
555
+ data: zod.z.record(zod.z.unknown()),
556
+ archived: zod.z.number().int(),
557
+ created_at: zod.z.number().int(),
558
+ updated_at: zod.z.number().int(),
559
+ created_by: zod.z.string()
560
+ })),
561
+ total: zod.z.number().int(),
562
+ limit: zod.z.number().int().nullable(),
563
+ offset: zod.z.number().int(),
564
+ has_more: zod.z.boolean()
565
+ });
566
+ zod.z.object({
567
+ ok: zod.z.literal(true),
568
+ entities: zod.z.array(zod.z.object({
569
+ id: zod.z.string(),
570
+ type: zod.z.string(),
571
+ schema_version: zod.z.number().int(),
572
+ data: zod.z.record(zod.z.unknown()),
573
+ archived: zod.z.number().int(),
574
+ created_at: zod.z.number().int(),
575
+ updated_at: zod.z.number().int(),
576
+ created_by: zod.z.string()
577
+ }))
578
+ });
579
+ var CompactEntitySchema = zod.z.object({
580
+ id: zod.z.string(),
581
+ type: zod.z.string(),
582
+ title: zod.z.string().nullable(),
583
+ status: zod.z.string().nullable(),
584
+ claimed_by: zod.z.string().nullable(),
585
+ blockers: zod.z.number().int().nonnegative(),
586
+ artifacts: zod.z.number().int().nonnegative()
587
+ });
588
+ zod.z.object({
589
+ ok: zod.z.literal(true),
590
+ entities: zod.z.array(CompactEntitySchema)
591
+ });
592
+ zod.z.object({
593
+ ok: zod.z.literal(true),
594
+ entity: CompactEntitySchema
595
+ });
596
+ zod.z.object({
597
+ ok: zod.z.literal(true),
598
+ entities: zod.z.array(CompactEntitySchema),
599
+ total: zod.z.number().int(),
600
+ limit: zod.z.number().int().nullable(),
601
+ offset: zod.z.number().int(),
602
+ has_more: zod.z.boolean()
603
+ });
604
+ zod.z.object({
605
+ ok: zod.z.literal(true),
606
+ project: zod.z.object({
607
+ entity_count: zod.z.number().int(),
608
+ entity_counts: zod.z.record(zod.z.number().int()),
609
+ status_counts: zod.z.record(zod.z.number().int()),
610
+ active_claims: zod.z.number().int(),
611
+ ready_count: zod.z.number().int(),
612
+ online_machines: zod.z.array(zod.z.string()),
613
+ token_estimate: zod.z.number().int(),
614
+ recent_events: zod.z.array(zod.z.object({
615
+ seq: zod.z.number().int(),
616
+ t: zod.z.number().int(),
617
+ kind: zod.z.string(),
618
+ resource: zod.z.string(),
619
+ actor: zod.z.string()
620
+ }))
621
+ })
622
+ });
623
+ zod.z.object({
624
+ ok: zod.z.literal(true),
625
+ entity: zod.z.object({
626
+ id: zod.z.string(),
627
+ type: zod.z.string(),
628
+ schema_version: zod.z.number().int(),
629
+ data: zod.z.record(zod.z.unknown()),
630
+ archived: zod.z.number().int(),
631
+ created_at: zod.z.number().int(),
632
+ updated_at: zod.z.number().int(),
633
+ created_by: zod.z.string()
634
+ }),
635
+ relationships: zod.z.array(EntityRelationshipSchema).default([])
636
+ });
637
+ zod.z.object({
638
+ ok: zod.z.literal(true)
639
+ });
640
+ zod.z.object({
641
+ from_id: zod.z.string().min(1),
642
+ to_id: zod.z.string().min(1),
643
+ type: EntityRelationshipTypeSchema
644
+ });
645
+ zod.z.object({
646
+ ok: zod.z.literal(true),
647
+ created: zod.z.boolean().default(true)
648
+ });
649
+ zod.z.object({
650
+ from_id: zod.z.string().min(1).optional(),
651
+ to_id: zod.z.string().min(1).optional(),
652
+ type: EntityRelationshipTypeSchema.optional()
653
+ });
654
+ zod.z.object({
655
+ ok: zod.z.literal(true),
656
+ relationships: zod.z.array(EntityRelationshipSchema)
657
+ });
658
+ zod.z.object({
659
+ from_id: zod.z.string().min(1),
660
+ to_id: zod.z.string().min(1),
661
+ type: EntityRelationshipTypeSchema
662
+ });
663
+ zod.z.object({
664
+ ok: zod.z.literal(true),
665
+ removed: zod.z.boolean()
666
+ });
667
+ zod.z.object({
668
+ resource: zod.z.string().optional(),
669
+ kind: JournalEventKindSchema.optional(),
670
+ source: zod.z.string().optional(),
671
+ after_seq: zod.z.number().int().optional(),
672
+ limit: zod.z.number().int().positive().default(100)
673
+ });
674
+ zod.z.object({
675
+ ok: zod.z.literal(true),
676
+ events: zod.z.array(zod.z.object({
677
+ seq: zod.z.number().int(),
678
+ t: zod.z.number().int(),
679
+ kind: zod.z.string(),
680
+ resource: zod.z.string(),
681
+ actor: zod.z.string(),
682
+ token_id: zod.z.string().nullable(),
683
+ fence: zod.z.number().int().nullable(),
684
+ data: zod.z.record(zod.z.unknown()),
685
+ source: zod.z.string().nullable(),
686
+ source_version: zod.z.string().nullable()
687
+ }))
688
+ });
689
+ zod.z.object({
690
+ machine: zod.z.string(),
691
+ info: zod.z.record(zod.z.unknown()).default({})
692
+ });
693
+ zod.z.object({
694
+ ok: zod.z.literal(true),
695
+ machines: zod.z.array(zod.z.object({
696
+ machine: zod.z.string(),
697
+ last_seen: zod.z.number().int(),
698
+ info: zod.z.record(zod.z.unknown())
699
+ }))
700
+ });
701
+ zod.z.object({
702
+ ok: zod.z.literal(true),
703
+ machines: zod.z.array(zod.z.object({
704
+ machine: zod.z.string(),
705
+ last_seen: zod.z.number().int(),
706
+ info: zod.z.record(zod.z.unknown()),
707
+ active: zod.z.boolean()
708
+ }))
709
+ });
710
+ zod.z.object({
711
+ ok: zod.z.literal(true)
712
+ });
713
+ zod.z.object({
714
+ ok: zod.z.literal(true),
715
+ version: zod.z.string(),
716
+ apiVersion: zod.z.number().int(),
717
+ minCliVersion: zod.z.string(),
718
+ project_id: zod.z.string().optional()
719
+ });
720
+ zod.z.object({
721
+ ok: zod.z.literal(true),
722
+ project_id: zod.z.string(),
723
+ token_name: zod.z.string(),
724
+ scopes: zod.z.string(),
725
+ auth_kind: zod.z.enum(["d1-token", "session", "cookie-session"]).optional(),
726
+ github_login: zod.z.string().optional(),
727
+ permission: zod.z.string().optional(),
728
+ expires_at: zod.z.number().optional()
729
+ });
730
+ var DOHealthResponseSchema = zod.z.object({
731
+ ok: zod.z.literal(true),
732
+ expiredClaimsCount: zod.z.number(),
733
+ journalRows: zod.z.number(),
734
+ maxSeq: zod.z.number()
735
+ });
736
+ zod.z.object({
737
+ ok: zod.z.literal(true),
738
+ doRttMs: zod.z.number(),
739
+ doHealth: DOHealthResponseSchema,
740
+ r2Reachable: zod.z.boolean()
741
+ });
742
+ var SqliteColumnInfoSchema = zod.z.object({
743
+ cid: zod.z.number(),
744
+ name: zod.z.string(),
745
+ type: zod.z.string(),
746
+ notnull: zod.z.number(),
747
+ dflt_value: zod.z.string().nullable(),
748
+ pk: zod.z.number()
749
+ });
750
+ var SchemaMigrationRecordSchema = zod.z.object({
751
+ version: zod.z.number(),
752
+ applied_at: zod.z.number()
753
+ });
754
+ var DoctorSchemaSuccessResponseSchema = zod.z.object({
755
+ ok: zod.z.literal(true),
756
+ do_code_version: zod.z.string().optional(),
757
+ sqlite_version: zod.z.string(),
758
+ migrations: zod.z.array(SchemaMigrationRecordSchema),
759
+ tables: zod.z.array(zod.z.string()),
760
+ columns: zod.z.record(zod.z.array(SqliteColumnInfoSchema)),
761
+ claims_columns: zod.z.array(SqliteColumnInfoSchema).optional()
762
+ });
763
+ var DoctorSchemaStaleResponseSchema = zod.z.object({
764
+ ok: zod.z.literal(true),
765
+ stale_do: zod.z.literal(true),
766
+ message: zod.z.string(),
767
+ probe_result: zod.z.unknown()
768
+ });
769
+ zod.z.union([
770
+ DoctorSchemaSuccessResponseSchema,
771
+ DoctorSchemaStaleResponseSchema
772
+ ]);
773
+ var SearchDriftCheckNameSchema = zod.z.enum([
774
+ "search-missing-doc",
775
+ "search-orphan-doc",
776
+ "search-tombstone-leak",
777
+ "search-unsupported-kind",
778
+ "search-stale-index"
779
+ ]);
780
+ var SearchDriftFindingSchema = zod.z.object({
781
+ check: SearchDriftCheckNameSchema,
782
+ status: zod.z.enum(["pass", "warn", "fail"]),
783
+ count: zod.z.number().int().nonnegative(),
784
+ detail: zod.z.string(),
785
+ examples: zod.z.array(zod.z.string()).max(5)
786
+ });
787
+ zod.z.object({
788
+ ok: zod.z.literal(true),
789
+ findings: zod.z.array(SearchDriftFindingSchema),
790
+ checkedAt: zod.z.number().int()
791
+ });
792
+ zod.z.object({
793
+ name: zod.z.string().min(1).max(64).regex(/^[a-z0-9-]+$/),
794
+ note: zod.z.string().max(256).optional()
795
+ });
796
+ zod.z.object({
797
+ ok: zod.z.literal(true),
798
+ token: zod.z.string(),
799
+ name: zod.z.string(),
800
+ created_at: zod.z.number().int()
801
+ });
802
+ zod.z.object({
803
+ ok: zod.z.literal(true),
804
+ name: zod.z.string(),
805
+ revoked_at: zod.z.number().int()
806
+ });
807
+ var TokenListItemSchema = zod.z.object({
808
+ name: zod.z.string(),
809
+ note: zod.z.string().nullable(),
810
+ scopes: zod.z.string(),
811
+ created_at: zod.z.number().int(),
812
+ created_by: zod.z.string(),
813
+ last_used_at: zod.z.number().int().nullable(),
814
+ revoked_at: zod.z.number().int().nullable(),
815
+ revoked_by: zod.z.string().nullable()
816
+ });
817
+ zod.z.object({
818
+ ok: zod.z.literal(true),
819
+ tokens: zod.z.array(TokenListItemSchema)
820
+ });
821
+ var ReconcileDetailSchema = zod.z.object({
822
+ key: zod.z.string(),
823
+ status: zod.z.enum(["recovered", "skipped", "unrecoverable"]),
824
+ reason: zod.z.string().optional()
825
+ });
826
+ zod.z.object({
827
+ ok: zod.z.literal(true),
828
+ orphans_found: zod.z.number().int(),
829
+ orphans_recovered: zod.z.number().int(),
830
+ orphans_unrecoverable: zod.z.number().int(),
831
+ details: zod.z.array(ReconcileDetailSchema)
832
+ });
833
+ var SearchRebuildDetailSchema = zod.z.object({
834
+ artifact_key: zod.z.string(),
835
+ status: zod.z.enum(["written", "tombstoned", "skipped", "unrecoverable"]),
836
+ reason: zod.z.string().optional()
837
+ });
838
+ zod.z.object({
839
+ ok: zod.z.literal(true),
840
+ candidates_found: zod.z.number().int(),
841
+ written: zod.z.number().int(),
842
+ tombstoned: zod.z.number().int(),
843
+ skipped: zod.z.number().int(),
844
+ unrecoverable: zod.z.number().int(),
845
+ details: zod.z.array(SearchRebuildDetailSchema)
846
+ });
847
+ zod.z.object({
848
+ artifact_key: zod.z.string().min(1),
849
+ slot: zod.z.string().min(1),
850
+ metadata: zod.z.record(zod.z.unknown()).default({})
851
+ });
852
+ zod.z.object({
853
+ ok: zod.z.literal(true),
854
+ references: zod.z.array(zod.z.object({
855
+ entity_id: zod.z.string(),
856
+ artifact_key: zod.z.string(),
857
+ slot: zod.z.string(),
858
+ metadata: zod.z.record(zod.z.unknown()),
859
+ created_at: zod.z.number().int()
860
+ }))
861
+ });
862
+ zod.z.object({
863
+ ok: zod.z.literal(true),
864
+ results: zod.z.array(ArtifactSearchResultSchema),
865
+ total: zod.z.number().int()
866
+ });
867
+ zod.z.object({
868
+ q: zod.z.string().min(1).max(200),
869
+ kind: zod.z.string().optional(),
870
+ resource: zod.z.string().optional(),
871
+ 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))
873
+ });
874
+ var ArtifactGrepLineSchema = zod.z.object({
875
+ line: zod.z.number().int(),
876
+ // 1-based line number
877
+ text: zod.z.string(),
878
+ // matching line, truncated to GREP_MAX_LINE_TEXT chars
879
+ col: zod.z.number().int()
880
+ // 1-based column of first match in the line
881
+ });
882
+ var ArtifactGrepResultSchema = zod.z.object({
883
+ key: zod.z.string(),
884
+ kind: zod.z.string(),
885
+ resource: zod.z.string().nullable(),
886
+ lines: zod.z.array(ArtifactGrepLineSchema),
887
+ truncated: zod.z.boolean().optional()
888
+ // this blob hit the per-blob byte cap
889
+ });
890
+ zod.z.object({
891
+ ok: zod.z.literal(true),
892
+ results: zod.z.array(ArtifactGrepResultSchema),
893
+ scanned: zod.z.number().int(),
894
+ // candidates actually scanned
895
+ skipped: zod.z.number().int(),
896
+ // candidates skipped (blob missing/expired)
897
+ truncated: zod.z.boolean()
898
+ // request-level cap hit (candidate/byte/match cap)
899
+ });
900
+ zod.z.object({
901
+ pattern: zod.z.string().min(1).max(200),
902
+ kind: zod.z.string().optional(),
903
+ resource: zod.z.string().optional(),
904
+ regex: zod.z.string().optional().default("false").transform((v) => v === "true").pipe(zod.z.boolean()),
905
+ limit: zod.z.string().optional().default("50").transform((v) => Number.parseInt(v, 10)).pipe(zod.z.number().int().min(1).max(100))
906
+ // candidate cap, hard ceiling SWEEP_BATCH_SIZE
907
+ });
908
+ var RecordSearchResultSchema = zod.z.object({
909
+ record_type: zod.z.string(),
910
+ record_key: zod.z.string(),
911
+ snippet: zod.z.string().nullable(),
912
+ indexed_at: zod.z.number().int()
913
+ });
914
+ var UnifiedSearchResultSchema = zod.z.discriminatedUnion("type", [
915
+ zod.z.object({ type: zod.z.literal("entity") }).merge(EntitySearchResultSchema),
916
+ zod.z.object({ type: zod.z.literal("artifact") }).merge(ArtifactSearchResultSchema),
917
+ zod.z.object({ type: zod.z.literal("record") }).merge(RecordSearchResultSchema)
918
+ ]);
919
+ zod.z.object({
920
+ ok: zod.z.literal(true),
921
+ results: zod.z.array(UnifiedSearchResultSchema),
922
+ total: zod.z.number().int()
923
+ });
924
+ zod.z.object({
925
+ 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))
927
+ });
928
+ zod.z.object({
929
+ content: zod.z.string().min(1),
930
+ kind: zod.z.string().min(1),
931
+ mime_type: zod.z.string().default("text/markdown"),
932
+ resource: zod.z.string().optional(),
933
+ fence: zod.z.number().int().optional()
934
+ });
935
+ zod.z.object({
936
+ ok: zod.z.literal(true),
937
+ key: zod.z.string(),
938
+ bytes: zod.z.number(),
939
+ deduplicated: zod.z.boolean()
940
+ });
941
+ zod.z.object({
942
+ ok: zod.z.literal(true),
943
+ pointers: zod.z.array(zod.z.object({
944
+ r2_key: zod.z.string(),
945
+ resource: zod.z.string().nullable(),
946
+ kind: zod.z.string(),
947
+ sha256: zod.z.string(),
948
+ bytes: zod.z.number(),
949
+ fence: zod.z.number().nullable(),
950
+ mime_type: zod.z.string(),
951
+ produced_at: zod.z.number(),
952
+ produced_by: zod.z.string(),
953
+ expires_at: zod.z.number().nullable(),
954
+ tombstoned: zod.z.number()
955
+ }))
956
+ });
957
+ zod.z.object({
958
+ ok: zod.z.literal(true)
959
+ });
960
+ zod.z.object({
961
+ ok: zod.z.literal(true),
962
+ relationships: zod.z.array(zod.z.object({
963
+ from_key: zod.z.string(),
964
+ to_key: zod.z.string().nullable(),
965
+ to_uri: zod.z.string().nullable(),
966
+ type: zod.z.string(),
967
+ metadata: zod.z.record(zod.z.unknown()),
968
+ created_at: zod.z.number()
969
+ }))
970
+ });
971
+ zod.z.object({
972
+ template_name: zod.z.string(),
973
+ root_id: zod.z.string(),
974
+ vars: zod.z.record(zod.z.string()).default({})
975
+ });
976
+ zod.z.object({
977
+ ok: zod.z.literal(true),
978
+ created_entities: zod.z.array(zod.z.string()),
979
+ created_relationships: zod.z.number().int(),
980
+ journal_seq: zod.z.number().int()
981
+ });
982
+ zod.z.object({
983
+ owner: zod.z.string().min(1).max(100),
984
+ repo: zod.z.string().min(1).max(100),
985
+ github_host: zod.z.string().optional().default("github.com"),
986
+ github_token: zod.z.string().optional(),
987
+ min_read_permission: zod.z.string().optional(),
988
+ min_write_permission: zod.z.string().optional()
989
+ });
990
+ zod.z.object({
991
+ ok: zod.z.literal(true),
992
+ github_repo_id: zod.z.number().int(),
993
+ full_name: zod.z.string(),
994
+ registered_at: zod.z.number().int()
995
+ });
996
+ zod.z.object({
997
+ ok: zod.z.literal(true),
998
+ github_repo_id: zod.z.number().int(),
999
+ removed_at: zod.z.number().int()
1000
+ });
1001
+ zod.z.object({
1002
+ key: RecordKeySchema,
1003
+ value: zod.z.record(zod.z.unknown()),
1004
+ tags: RecordTagSchema.optional(),
1005
+ message: zod.z.string().optional(),
1006
+ source_artifact_key: zod.z.string().nullable().optional()
1007
+ });
1008
+ zod.z.object({
1009
+ value: zod.z.record(zod.z.unknown()),
1010
+ fence: zod.z.number().int(),
1011
+ tags: RecordTagSchema.optional(),
1012
+ message: zod.z.string().optional(),
1013
+ source_artifact_key: zod.z.string().nullable().optional()
1014
+ });
1015
+ zod.z.object({
1016
+ patch: zod.z.record(zod.z.unknown()),
1017
+ fence: zod.z.number().int(),
1018
+ message: zod.z.string().optional()
1019
+ });
1020
+ zod.z.object({
1021
+ fence: zod.z.number().int(),
1022
+ message: zod.z.string().optional()
1023
+ });
1024
+ zod.z.object({
1025
+ fence: zod.z.number().int(),
1026
+ message: zod.z.string().optional()
1027
+ });
1028
+ var RecordItemSchema = zod.z.object({
1029
+ type: RecordTypeSchema,
1030
+ key: RecordKeySchema,
1031
+ schema_version: zod.z.number().int(),
1032
+ value: zod.z.record(zod.z.unknown()),
1033
+ value_sha256: zod.z.string(),
1034
+ revision: zod.z.number().int(),
1035
+ archived: zod.z.number().int(),
1036
+ created_at: zod.z.number().int(),
1037
+ updated_at: zod.z.number().int(),
1038
+ updated_by: zod.z.string(),
1039
+ tags: zod.z.array(zod.z.string())
1040
+ });
1041
+ zod.z.object({
1042
+ ok: zod.z.literal(true),
1043
+ record: RecordItemSchema,
1044
+ fence: zod.z.number().int()
1045
+ });
1046
+ zod.z.object({
1047
+ ok: zod.z.literal(true),
1048
+ record: RecordItemSchema,
1049
+ fence: zod.z.number().int(),
1050
+ revision: zod.z.number().int()
1051
+ });
1052
+ var RecordListItemSchema = zod.z.object({
1053
+ type: RecordTypeSchema,
1054
+ key: RecordKeySchema,
1055
+ revision: zod.z.number().int(),
1056
+ updated_at: zod.z.number().int(),
1057
+ updated_by: zod.z.string(),
1058
+ archived: zod.z.number().int(),
1059
+ tags: zod.z.array(zod.z.string())
1060
+ });
1061
+ zod.z.object({
1062
+ ok: zod.z.literal(true),
1063
+ items: zod.z.array(RecordListItemSchema),
1064
+ meta: zod.z.object({
1065
+ total: zod.z.number().int(),
1066
+ limit: zod.z.number().int(),
1067
+ next_cursor: zod.z.string().nullable()
1068
+ })
1069
+ });
1070
+ var RecordHistoryItemSchema = zod.z.object({
1071
+ type: RecordTypeSchema,
1072
+ key: RecordKeySchema,
1073
+ revision: zod.z.number().int(),
1074
+ operation: zod.z.enum(["created", "set", "patch", "archived", "unarchived"]),
1075
+ schema_version: zod.z.number().int(),
1076
+ value_sha256: zod.z.string(),
1077
+ canonical_artifact_key: zod.z.string().nullable(),
1078
+ source_artifact_key: zod.z.string().nullable(),
1079
+ actor: zod.z.string(),
1080
+ created_at: zod.z.number().int(),
1081
+ message: zod.z.string().nullable()
1082
+ });
1083
+ zod.z.object({
1084
+ ok: zod.z.literal(true),
1085
+ items: zod.z.array(RecordHistoryItemSchema),
1086
+ meta: zod.z.object({
1087
+ total: zod.z.number().int(),
1088
+ limit: zod.z.number().int(),
1089
+ next_cursor: zod.z.string().nullable()
1090
+ })
1091
+ });
1092
+ zod.z.object({
1093
+ ok: zod.z.literal(true),
1094
+ types: zod.z.array(zod.z.string())
1095
+ });
1096
+ zod.z.object({
1097
+ title: zod.z.string().nullable(),
1098
+ body_text: zod.z.string()
1099
+ });
1100
+ var SessionPermissionSchema = zod.z.enum(["read", "write", "admin"]);
1101
+ zod.z.object({
1102
+ project_id: zod.z.string().min(1),
1103
+ github_host: zod.z.string().min(1),
1104
+ github_repo_id: zod.z.number().int(),
1105
+ github_login: zod.z.string().min(1),
1106
+ github_user_id: zod.z.number().int(),
1107
+ permission: SessionPermissionSchema,
1108
+ expires_at: zod.z.number().int(),
1109
+ issued_at: zod.z.number().int(),
1110
+ /**
1111
+ * JWT ID — a random nonce added to every newly minted session token (C9).
1112
+ * Optional for backward compatibility with tokens minted before this field
1113
+ * was added. Tokens without jti are not revocable via the revocation store.
1114
+ */
1115
+ jti: zod.z.string().optional()
1116
+ });
1117
+ zod.z.object({
1118
+ project_id: zod.z.string().min(1),
1119
+ github_token: zod.z.string().min(1)
1120
+ });
1121
+ zod.z.object({
1122
+ ok: zod.z.literal(true),
1123
+ session_token: zod.z.string(),
1124
+ expires_at: zod.z.number().int(),
1125
+ project_id: zod.z.string(),
1126
+ github_login: zod.z.string(),
1127
+ github_repo_id: zod.z.number().int(),
1128
+ permission: SessionPermissionSchema
1129
+ });
1130
+ zod.z.object({
1131
+ project_id: zod.z.string().min(1),
1132
+ installation_id: zod.z.number().int().positive()
1133
+ });
1134
+ zod.z.object({
1135
+ project_id: zod.z.string().min(1),
1136
+ user_token: zod.z.string().min(1),
1137
+ auth_method: zod.z.literal("user_token")
1138
+ });
1139
+ zod.z.object({
1140
+ app_id: zod.z.number().int(),
1141
+ client_id: zod.z.string().min(1)
1142
+ });
1143
+ zod.z.object({
1144
+ project_id: zod.z.string().min(1),
1145
+ oidc_token: zod.z.string().min(1)
1146
+ });
1147
+ zod.z.object({
1148
+ token: zod.z.string().min(1),
1149
+ project_id: zod.z.string().min(1)
1150
+ });
1151
+ zod.z.object({ ok: zod.z.literal(true) });
1152
+ zod.z.object({
1153
+ ok: zod.z.literal(true),
1154
+ projectId: zod.z.string()
1155
+ });
1156
+ var GateAwaitTypeSchema = zod.z.enum([
1157
+ "ci",
1158
+ "pr",
1159
+ "timer",
1160
+ "human",
1161
+ "webhook"
1162
+ ]);
1163
+ var GateStatusSchema = zod.z.enum([
1164
+ "pending",
1165
+ "resolved",
1166
+ "timed_out",
1167
+ "cancelled"
1168
+ ]);
1169
+ var GateSchema = zod.z.object({
1170
+ id: zod.z.string(),
1171
+ resource: zod.z.string(),
1172
+ await_type: GateAwaitTypeSchema,
1173
+ status: GateStatusSchema,
1174
+ fence: zod.z.number().int(),
1175
+ timeout_at: zod.z.number().int().nullable(),
1176
+ resolved_at: zod.z.number().int().nullable(),
1177
+ resolution: zod.z.string().nullable(),
1178
+ created_at: zod.z.number().int(),
1179
+ created_by: zod.z.string(),
1180
+ token_id: zod.z.string().nullable().optional(),
1181
+ data: zod.z.record(zod.z.unknown())
1182
+ });
1183
+ zod.z.object({
1184
+ resource: zod.z.string(),
1185
+ await_type: GateAwaitTypeSchema,
1186
+ fence: zod.z.number().int(),
1187
+ timeout_at: zod.z.number().int().optional(),
1188
+ data: zod.z.record(zod.z.unknown()).optional()
1189
+ });
1190
+ zod.z.object({
1191
+ resolution: zod.z.string().optional()
1192
+ });
1193
+ zod.z.object({
1194
+ ok: zod.z.literal(true),
1195
+ gate: GateSchema
1196
+ });
1197
+ zod.z.object({
1198
+ ok: zod.z.literal(true),
1199
+ gates: zod.z.array(GateSchema)
1200
+ });
1201
+
1202
+ // src/client.ts
1203
+ var require2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
1204
+ var SDK_VERSION = require2("../package.json").version;
1205
+ var TilaClient = class _TilaClient {
1206
+ baseUrl;
1207
+ token;
1208
+ validate;
1209
+ timeoutMs;
1210
+ extraHeaders;
1211
+ constructor(opts) {
1212
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
1213
+ this.token = opts.token;
1214
+ this.validate = opts.validate ?? false;
1215
+ this.timeoutMs = opts.timeoutMs ?? 3e4;
1216
+ this.extraHeaders = {
1217
+ "X-Tila-Source": `sdk/${SDK_VERSION}`,
1218
+ ...opts.extraHeaders
1219
+ };
1220
+ }
1221
+ /**
1222
+ * Creates an AbortSignal that fires after this.timeoutMs.
1223
+ * Uses AbortSignal.timeout() when available (Node 18.8+, Bun 0.5+, browsers),
1224
+ * falls back to manual setTimeout + AbortController for older runtimes.
1225
+ *
1226
+ * Note: Cloudflare Workers has supported AbortSignal.timeout() since 2023;
1227
+ * the fallback branch will never execute there.
1228
+ */
1229
+ createAbortSignal() {
1230
+ if (typeof AbortSignal.timeout === "function") {
1231
+ return AbortSignal.timeout(this.timeoutMs);
1232
+ }
1233
+ const controller = new AbortController();
1234
+ setTimeout(
1235
+ () => controller.abort(
1236
+ new DOMException(
1237
+ "The operation was aborted due to timeout",
1238
+ "TimeoutError"
1239
+ )
1240
+ ),
1241
+ this.timeoutMs
1242
+ );
1243
+ return controller.signal;
1244
+ }
1245
+ static fromConfig(config, token) {
1246
+ if (!config.worker_url) {
1247
+ throw new Error(
1248
+ `Cannot create TilaClient: config has no worker_url. Use 'tila project create' or set backend = "cloudflare" in .tila/config.toml.`
1249
+ );
1250
+ }
1251
+ return new _TilaClient({ baseUrl: config.worker_url, token });
1252
+ }
1253
+ async request(method, path, opts) {
1254
+ const url = new URL(path, `${this.baseUrl}/`);
1255
+ if (opts?.query) {
1256
+ for (const [key, value] of Object.entries(opts.query)) {
1257
+ if (value !== void 0) {
1258
+ url.searchParams.set(key, value);
1259
+ }
1260
+ }
1261
+ }
1262
+ const headers = {
1263
+ Authorization: `Bearer ${this.token}`,
1264
+ Accept: "application/json",
1265
+ ...this.extraHeaders
1266
+ };
1267
+ const init = {
1268
+ method,
1269
+ headers,
1270
+ signal: this.createAbortSignal()
1271
+ };
1272
+ if (opts?.body !== void 0) {
1273
+ headers["Content-Type"] = "application/json";
1274
+ init.body = JSON.stringify(opts.body);
1275
+ }
1276
+ let res;
1277
+ try {
1278
+ res = await fetch(url.toString(), init);
1279
+ } catch (err) {
1280
+ if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
1281
+ throw new Error(
1282
+ `Request to ${url.origin} timed out after ${this.timeoutMs}ms`
1283
+ );
1284
+ }
1285
+ throw new Error(
1286
+ `Network error connecting to ${url.origin}: ${err instanceof Error ? err.message : String(err)}`
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
+ }
1349
+ }
1350
+ const headers = {
1351
+ Authorization: `Bearer ${this.token}`,
1352
+ ...this.extraHeaders
1353
+ };
1354
+ let res;
1355
+ try {
1356
+ res = await fetch(url.toString(), {
1357
+ method,
1358
+ headers,
1359
+ signal: this.createAbortSignal()
1360
+ });
1361
+ } catch (err) {
1362
+ if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
1363
+ throw new Error(
1364
+ `Request to ${url.origin} timed out after ${this.timeoutMs}ms`
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()
1390
+ });
1391
+ } catch (err) {
1392
+ if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
1393
+ throw new Error(
1394
+ `Request to ${url.origin} timed out after ${this.timeoutMs}ms`
1395
+ );
1396
+ }
1397
+ throw new Error(
1398
+ `Network error connecting to ${url.origin}: ${err instanceof Error ? err.message : String(err)}`
1399
+ );
1400
+ }
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
+ };
1499
+ }
1500
+
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
+ // src/entities.ts
1569
+ function _createMethods(client, base) {
1570
+ return {
1571
+ async create(id, type, data) {
1572
+ return client.post(base, { id, type, data });
1573
+ },
1574
+ async get(id) {
1575
+ return client.get(`${base}/${id}`);
1576
+ },
1577
+ async list(query) {
1578
+ return client.get(base, { query });
1579
+ },
1580
+ async update(id, data, fence) {
1581
+ return client.patch(`${base}/${id}`, { data, fence });
1582
+ },
1583
+ async archive(id, fence) {
1584
+ return client.post(`${base}/${id}/archive`, {
1585
+ fence
1586
+ });
1587
+ },
1588
+ async addRelationship(fromId, toId, type) {
1589
+ return client.post(
1590
+ `${base}/${fromId}/relationships`,
1591
+ {
1592
+ to_id: toId,
1593
+ type
1594
+ }
1595
+ );
1596
+ },
1597
+ async addArtifactRef(entityId, artifactKey, slot, metadata) {
1598
+ return client.post(`${base}/${entityId}/artifact-refs`, {
1599
+ artifact_key: artifactKey,
1600
+ slot,
1601
+ metadata
1602
+ });
1603
+ },
1604
+ async listArtifactRefs(entityId) {
1605
+ return client.get(
1606
+ `${base}/${entityId}/artifact-refs`
1607
+ );
1608
+ }
1609
+ };
1610
+ }
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
+ }
1620
+
1621
+ // src/claims.ts
1622
+ function createClaimMethods(client, projectId) {
1623
+ const base = `/projects/${projectId}/claims`;
1624
+ return {
1625
+ async acquire(resource, mode, ttlMs, opts) {
1626
+ return client.post(`${base}/acquire`, {
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
+ });
1639
+ },
1640
+ async release(resource, fence) {
1641
+ return client.post(`${base}/release`, {
1642
+ resource,
1643
+ fence
1644
+ });
1645
+ },
1646
+ async list() {
1647
+ return client.get(base);
1648
+ },
1649
+ async get(resource) {
1650
+ return client.get(
1651
+ `${base}/${encodeURIComponent(resource)}`
1652
+ );
1653
+ }
1654
+ };
1655
+ }
1656
+
1657
+ // src/artifacts.ts
1658
+ function createArtifactMethods(client, projectId) {
1659
+ const base = `/projects/${projectId}/artifacts`;
1660
+ return {
1661
+ upload: Object.assign(
1662
+ function upload(input, opts) {
1663
+ if (input instanceof ReadableStream) {
1664
+ if (!opts.mimeType) {
1665
+ throw new TypeError(
1666
+ "mimeType is required when uploading a ReadableStream. Pass opts.mimeType explicitly."
1667
+ );
1668
+ }
1669
+ return new Response(input).arrayBuffer().then((bytes) => {
1670
+ const uploadFile = new Blob([bytes], {
1671
+ type: opts.mimeType
1672
+ });
1673
+ const formData2 = new FormData();
1674
+ formData2.append("file", uploadFile);
1675
+ formData2.append("kind", opts.kind);
1676
+ formData2.append("mime_type", opts.mimeType);
1677
+ if (opts.resource) formData2.append("resource", opts.resource);
1678
+ if (opts.fence !== void 0)
1679
+ formData2.append("fence", String(opts.fence));
1680
+ if (opts.flavor) formData2.append("flavor", opts.flavor);
1681
+ return client.postFormData(base, formData2);
1682
+ });
1683
+ }
1684
+ const contentType = opts.mimeType || (input instanceof File ? input.type : "") || "";
1685
+ if (!contentType) {
1686
+ throw new TypeError(
1687
+ "contentType is required for uploads when file.type is absent. Pass opts.mimeType explicitly."
1688
+ );
1689
+ }
1690
+ const formData = new FormData();
1691
+ formData.append("file", input);
1692
+ formData.append("kind", opts.kind);
1693
+ formData.append("mime_type", contentType);
1694
+ if (opts.resource) formData.append("resource", opts.resource);
1695
+ if (opts.fence !== void 0)
1696
+ formData.append("fence", String(opts.fence));
1697
+ if (opts.flavor) formData.append("flavor", opts.flavor);
1698
+ return client.postFormData(base, formData);
1699
+ },
1700
+ {}
1701
+ ),
1702
+ async download(key) {
1703
+ const res = await client.requestRaw(
1704
+ "GET",
1705
+ `${base}/${encodeURIComponent(key)}`
1706
+ );
1707
+ return {
1708
+ body: res.body ?? new ReadableStream(),
1709
+ contentType: res.headers.get("content-type") || "application/octet-stream",
1710
+ contentLength: res.headers.has("content-length") ? Number(res.headers.get("content-length")) : null
1711
+ };
1712
+ },
1713
+ async list(query) {
1714
+ return client.get(base, { query });
1715
+ },
1716
+ async search(q, opts) {
1717
+ return client.get(`${base}/search`, {
1718
+ query: { q, ...opts }
1719
+ });
1720
+ },
1721
+ async grep(pattern, opts) {
1722
+ const query = { pattern };
1723
+ if (opts?.kind) query.kind = opts.kind;
1724
+ if (opts?.resource) query.resource = opts.resource;
1725
+ if (opts?.regex) query.regex = "true";
1726
+ if (opts?.limit != null) query.limit = String(opts.limit);
1727
+ return client.get(`${base}/grep`, { query });
1728
+ },
1729
+ async addRelationship(fromKey, toKeyOrUri, type, metadata) {
1730
+ const isUri = toKeyOrUri.includes("://");
1731
+ return client.post(
1732
+ `${base}/${encodeURIComponent(fromKey)}/relationships`,
1733
+ {
1734
+ [isUri ? "to_uri" : "to_key"]: toKeyOrUri,
1735
+ type,
1736
+ metadata
1737
+ }
1738
+ );
1739
+ },
1740
+ async listRelationships(key) {
1741
+ return client.get(
1742
+ `${base}/${encodeURIComponent(key)}/relationships`
1743
+ );
1744
+ },
1745
+ async getLatest(kind, resource) {
1746
+ const res = await client.requestRaw("GET", `${base}/latest`, {
1747
+ query: { kind, resource }
1748
+ });
1749
+ if (res.status === 404) return null;
1750
+ if (!res.ok) {
1751
+ const body2 = await res.json().catch(() => ({}));
1752
+ throw new Error(
1753
+ `getLatest failed with status ${res.status}: ${JSON.stringify(body2)}`
1754
+ );
1755
+ }
1756
+ const body = await res.json();
1757
+ return body.pointer;
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)}`
1772
+ );
1773
+ const contentType = res.headers.get("content-type") || "application/octet-stream";
1774
+ if (!contentType.startsWith("text/")) {
1775
+ throw new TypeError(
1776
+ `Artifact ${key} has MIME type ${contentType} \u2014 readText only supports text/* artifacts`
1777
+ );
1778
+ }
1779
+ const text = await res.text();
1780
+ return { content: text, mimeType: contentType };
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)}`
1795
+ );
1796
+ },
1797
+ async list() {
1798
+ return client.get(base);
1799
+ }
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 });
1809
+ }
1810
+ };
1811
+ }
1812
+
1813
+ // src/presence.ts
1814
+ function createPresenceMethods(client, projectId) {
1815
+ const base = `/projects/${projectId}/presence`;
1816
+ return {
1817
+ async heartbeat(machine, ttlMs) {
1818
+ return client.post(base, {
1819
+ machine,
1820
+ ttl_ms: ttlMs
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`);
1832
+ }
1833
+ };
1834
+ }
1835
+
1836
+ // src/records.ts
1837
+ function encodeKey(key) {
1838
+ return key.split("/").map(encodeURIComponent).join("/");
1839
+ }
1840
+ function createRecordMethods(client, projectId) {
1841
+ const base = `/projects/${projectId}/records`;
1842
+ return {
1843
+ async create(type, req) {
1844
+ return client.post(`${base}/${type}`, req);
1845
+ },
1846
+ async set(type, key, req) {
1847
+ return client.put(
1848
+ `${base}/${type}/${encodeKey(key)}`,
1849
+ req
1850
+ );
1851
+ },
1852
+ async get(type, key) {
1853
+ return client.get(`${base}/${type}/${encodeKey(key)}`);
1854
+ },
1855
+ async patch(type, key, req) {
1856
+ return client.patch(
1857
+ `${base}/${type}/${encodeKey(key)}`,
1858
+ req
1859
+ );
1860
+ },
1861
+ async archive(type, key, req) {
1862
+ return client.post(
1863
+ `${base}/${type}/~/archive/${encodeKey(key)}`,
1864
+ req
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 ?? [] };
1891
+ }
1892
+ };
1893
+ }
1894
+
1895
+ // src/schema.ts
1896
+ function createSchemaMethods(client, projectId) {
1897
+ const base = `/projects/${projectId}/schema`;
1898
+ return {
1899
+ async get() {
1900
+ return client.get(base);
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
+ }
1908
+ };
1909
+ }
1910
+
1911
+ // src/signals.ts
1912
+ function createSignalMethods(client, projectId) {
1913
+ const base = `/projects/${projectId}/signals`;
1914
+ return {
1915
+ /** Fetch the signal inbox for the current token. GET /projects/:id/signals */
1916
+ async inbox() {
1917
+ return client.get(base);
1918
+ },
1919
+ /** Send a signal to a target. POST /projects/:id/signals/send */
1920
+ async send(req) {
1921
+ return client.post(`${base}/send`, req);
1922
+ },
1923
+ /** Acknowledge a signal. POST /projects/:id/signals/:signalId/ack */
1924
+ async ack(signalId) {
1925
+ return client.post(`${base}/${signalId}/ack`, {});
1926
+ }
1927
+ };
1928
+ }
1929
+
1930
+ // src/gates.ts
1931
+ function createGateMethods(client, projectId) {
1932
+ const base = `/projects/${projectId}/gates`;
1933
+ return {
1934
+ /** List gates with optional filters. GET /projects/:id/gates */
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}`);
1949
+ }
1950
+ };
1951
+ }
1952
+
1953
+ // src/templates.ts
1954
+ function createTemplateMethods(client, projectId) {
1955
+ const base = `/projects/${projectId}/templates`;
1956
+ return {
1957
+ /** Instantiate an entity template. POST /projects/:id/templates/instantiate */
1958
+ async instantiate(req) {
1959
+ return client.post(
1960
+ `${base}/instantiate`,
1961
+ req
1962
+ );
1963
+ },
1964
+ /** List available templates from the project schema. GET /projects/:id/templates */
1965
+ async list() {
1966
+ return client.get(base);
1967
+ }
1968
+ };
1969
+ }
1970
+
1971
+ // src/indexes.ts
1972
+ function createIndexMethods(client, projectId) {
1973
+ const base = `/projects/${projectId}/artifacts`;
1974
+ return {
1975
+ /**
1976
+ * Create an index artifact. Uploads file content with flavor=index.
1977
+ * Returns the artifact key and byte count.
1978
+ */
1979
+ async create(input, opts) {
1980
+ const mimeType = opts?.mimeType || (input instanceof File ? input.type : "") || "application/octet-stream";
1981
+ const formData = new FormData();
1982
+ formData.append("file", input);
1983
+ formData.append("kind", opts?.kind ?? "index");
1984
+ formData.append("mime_type", mimeType);
1985
+ formData.append("flavor", opts?.flavor ?? "index");
1986
+ if (opts?.resource) formData.append("resource", opts.resource);
1987
+ return client.postFormData(base, formData);
1988
+ },
1989
+ /**
1990
+ * Add an entry artifact to an index. Records the relationship
1991
+ * entry_key -> index_key with type "entry-of".
1992
+ */
1993
+ async addEntry(entryKey, indexKey) {
1994
+ return client.post(
1995
+ `${base}/${encodeURIComponent(entryKey)}/relationships`,
1996
+ { to_key: indexKey, type: "entry-of" }
1997
+ );
1998
+ },
1999
+ /**
2000
+ * List relationships FROM the given index key. Note: this returns
2001
+ * forward relationships (what the index points to), not a reverse
2002
+ * lookup of entries pointing to this index. The HTTP API does not
2003
+ * expose a reverse-lookup endpoint; for that, use the CLI's
2004
+ * `tila index list-entries` which queries ops-sqlite directly.
2005
+ */
2006
+ async listEntries(indexKey) {
2007
+ return client.get(
2008
+ `${base}/${encodeURIComponent(indexKey)}/relationships`
2009
+ );
2010
+ }
2011
+ };
2012
+ }
2013
+
2014
+ // src/summary.ts
2015
+ function createSummaryMethods(client, projectId) {
2016
+ return {
2017
+ /** Get project summary. GET /projects/:id/summary */
2018
+ async get() {
2019
+ return client.get(`/projects/${projectId}/summary`);
2020
+ }
2021
+ };
2022
+ }
2023
+
2024
+ // src/search.ts
2025
+ function createSearchMethods(client, projectId) {
2026
+ const base = `/projects/${projectId}`;
2027
+ return {
2028
+ async search(q, opts) {
2029
+ const query = { q };
2030
+ if (opts?.limit !== void 0) query.limit = String(opts.limit);
2031
+ return client.get(`${base}/search`, { query });
2032
+ }
2033
+ };
2034
+ }
2035
+
2036
+ // src/claim-handle.ts
2037
+ var ClaimHandle = class {
2038
+ resource;
2039
+ fence;
2040
+ expiresAt;
2041
+ client;
2042
+ projectId;
2043
+ errorListeners = [];
2044
+ constructor(opts) {
2045
+ this.client = opts.client;
2046
+ this.projectId = opts.projectId;
2047
+ this.resource = opts.resource;
2048
+ this.fence = opts.fence;
2049
+ this.expiresAt = opts.expiresAt;
2050
+ }
2051
+ on(event, listener) {
2052
+ if (event === "error") {
2053
+ this.errorListeners.push(listener);
2054
+ }
2055
+ }
2056
+ emitError(err) {
2057
+ for (const listener of this.errorListeners) {
2058
+ listener(err);
2059
+ }
2060
+ }
2061
+ async updateEntity(id, data) {
2062
+ const entities = createEntityMethods(this.client, this.projectId);
2063
+ return entities.update(id, data, this.fence);
2064
+ }
2065
+ async uploadArtifact(input, opts) {
2066
+ const artifacts = createArtifactMethods(this.client, this.projectId);
2067
+ return artifacts.upload(input, { ...opts, fence: this.fence });
2068
+ }
2069
+ async addArtifactRef(entityId, artifactKey, slot) {
2070
+ const entities = createEntityMethods(this.client, this.projectId);
2071
+ await entities.addArtifactRef(entityId, artifactKey, slot);
2072
+ }
2073
+ startHeartbeat(ttlMs, opts) {
2074
+ const intervalMs = opts?.intervalMs ?? Math.floor(ttlMs * 0.4);
2075
+ const timer = setInterval(async () => {
2076
+ try {
2077
+ await this.client.post(`/projects/${this.projectId}/claims/renew`, {
2078
+ resource: this.resource,
2079
+ fence: this.fence,
2080
+ ttl_ms: ttlMs
2081
+ });
2082
+ } catch (err) {
2083
+ if (err instanceof TilaApiError && (err.status === 409 || err.status === 401)) {
2084
+ this.emitError(err);
2085
+ } else if (err instanceof Error) {
2086
+ this.emitError(err);
2087
+ }
2088
+ }
2089
+ }, intervalMs);
2090
+ return {
2091
+ stop() {
2092
+ clearInterval(timer);
2093
+ }
2094
+ };
2095
+ }
2096
+ onClaimExpiring(leadMs, callback) {
2097
+ const delay = this.expiresAt - Date.now() - leadMs;
2098
+ if (delay <= 0) {
2099
+ callback();
2100
+ return { stop() {
2101
+ } };
2102
+ }
2103
+ const timer = setTimeout(callback, delay);
2104
+ return {
2105
+ stop() {
2106
+ clearTimeout(timer);
2107
+ }
2108
+ };
2109
+ }
2110
+ /** @internal Release the claim. Errors are swallowed by withClaim's finally. */
2111
+ async _release() {
2112
+ await this.client.post(`/projects/${this.projectId}/claims/release`, {
2113
+ resource: this.resource,
2114
+ fence: this.fence
2115
+ });
2116
+ }
2117
+ };
2118
+ async function withClaim(client, projectId, resource, mode, ttlMs, callback) {
2119
+ const result = await client.post(`/projects/${projectId}/claims/acquire`, {
2120
+ resource,
2121
+ mode,
2122
+ ttl_ms: ttlMs
2123
+ });
2124
+ const handle = new ClaimHandle({
2125
+ client,
2126
+ projectId,
2127
+ resource,
2128
+ fence: result.fence,
2129
+ expiresAt: result.expires_at
2130
+ });
2131
+ try {
2132
+ return await callback(handle);
2133
+ } finally {
2134
+ try {
2135
+ await handle._release();
2136
+ } catch (err) {
2137
+ console.warn(
2138
+ `[tila-sdk] Failed to release claim on ${resource} (fence=${handle.fence}):`,
2139
+ err instanceof Error ? err.message : String(err)
2140
+ );
2141
+ }
2142
+ }
2143
+ }
2144
+
2145
+ exports.ClaimHandle = ClaimHandle;
2146
+ exports.TILA_ERRORS = TILA_ERRORS;
2147
+ exports.TilaApiError = TilaApiError;
2148
+ exports.TilaClient = TilaClient;
2149
+ exports.createArtifactMethods = createArtifactMethods;
2150
+ exports.createClaimMethods = createClaimMethods;
2151
+ exports.createEntityMethods = createEntityMethods;
2152
+ exports.createGateMethods = createGateMethods;
2153
+ exports.createIndexMethods = createIndexMethods;
2154
+ exports.createJournalMethods = createJournalMethods;
2155
+ exports.createPresenceMethods = createPresenceMethods;
2156
+ exports.createRecordMethods = createRecordMethods;
2157
+ exports.createSchemaMethods = createSchemaMethods;
2158
+ exports.createSearchMethods = createSearchMethods;
2159
+ exports.createSignalMethods = createSignalMethods;
2160
+ exports.createSummaryMethods = createSummaryMethods;
2161
+ exports.createTaskMethods = createTaskMethods;
2162
+ exports.createTemplateMethods = createTemplateMethods;
2163
+ exports.createTokenMethods = createTokenMethods;
2164
+ exports.createWorkUnitMethods = createWorkUnitMethods;
2165
+ exports.exchangeGitHubToken = exchangeGitHubToken;
2166
+ exports.isTilaApiError = isTilaApiError;
2167
+ exports.withClaim = withClaim;
2168
+ exports.withRetry = withRetry;