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/LICENSE +21 -0
- package/README.md +318 -0
- package/dist/index.cjs +2168 -0
- package/dist/index.d.cts +464 -0
- package/dist/index.d.ts +464 -0
- package/dist/index.js +2142 -0
- package/package.json +61 -0
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;
|