@heynixie/contract 0.0.0-stage → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1097 @@
1
+ // src/has-several-words.ts
2
+ function hasSeveralWords(text) {
3
+ return /\S\s+\S/u.test(text);
4
+ }
5
+
6
+ // src/pick-span-source.ts
7
+ var pastedInputTypes = new Set(["insertFromPaste", "insertFromPasteAsQuotation"]);
8
+ var typedInputTypes = new Set([
9
+ "insertCompositionText",
10
+ "insertLineBreak",
11
+ "insertParagraph",
12
+ "insertReplacementText",
13
+ "insertText"
14
+ ]);
15
+ var wordInputTypes = new Set(["insertCompositionText", "insertText"]);
16
+ function pickSpanSource(inputType, data) {
17
+ if (pastedInputTypes.has(inputType)) {
18
+ return "pasted";
19
+ }
20
+ if (inputType === "insertFromDrop") {
21
+ return "dropped";
22
+ }
23
+ if (wordInputTypes.has(inputType) && data !== null && hasSeveralWords(data)) {
24
+ return "unknown";
25
+ }
26
+ if (typedInputTypes.has(inputType)) {
27
+ return "typed";
28
+ }
29
+ return "unknown";
30
+ }
31
+
32
+ // src/build-pending-input.ts
33
+ function buildPendingInput(fields) {
34
+ const pending = {
35
+ selection: {
36
+ backward: fields.inputType.endsWith("Backward"),
37
+ end: fields.selectionEnd,
38
+ start: fields.selectionStart
39
+ },
40
+ source: pickSpanSource(fields.inputType, fields.data)
41
+ };
42
+ return fields.inputType === "insertText" && fields.data !== null && hasSeveralWords(fields.data) ? { ...pending, respacing: fields.data } : pending;
43
+ }
44
+ // src/build-query-utils.ts
45
+ import { createTanstackQueryUtils } from "@orpc/tanstack-query";
46
+ function buildQueryUtils(client) {
47
+ return createTanstackQueryUtils(client, { path: ["nixie"] });
48
+ }
49
+ // src/build-span-state.ts
50
+ function buildSpanState(state, pending, text) {
51
+ const pinned = planEdit(state.text, text, pending?.selection);
52
+ const fallback = pending === undefined || !isEditAtSelection(pinned, pending.selection);
53
+ const edit = fallback ? planEdit(state.text, text) : pinned;
54
+ const source = fallback ? "unknown" : pickEditSource(state.removed, pending, {
55
+ at: edit.at,
56
+ removed: edit.removed,
57
+ text: text.slice(edit.at, edit.at + edit.inserted)
58
+ });
59
+ const spans = state.spans.flatMap((span) => splitSpan(span, edit));
60
+ if (edit.inserted > 0) {
61
+ spans.push({ end: edit.at + edit.inserted, source, start: edit.at });
62
+ }
63
+ const removed = fallback ? undefined : findTypedRemoval(state, edit);
64
+ return removed === undefined ? { spans: mergeSpans(spans), text } : { removed, spans: mergeSpans(spans), text };
65
+ }
66
+ function planEdit(before, after, selection) {
67
+ const shorter = Math.min(before.length, after.length);
68
+ const prefixBound = Math.min(shorter, selection?.start ?? shorter);
69
+ const suffixBound = Math.min(shorter, before.length - (selection?.end ?? 0));
70
+ if (selection?.backward === true) {
71
+ const suffix = countSuffix(before, after, suffixBound);
72
+ return buildEdit(before, after, {
73
+ prefix: countPrefix(before, after, Math.min(prefixBound, shorter - suffix)),
74
+ suffix
75
+ });
76
+ }
77
+ const prefix = countPrefix(before, after, prefixBound);
78
+ return buildEdit(before, after, {
79
+ prefix,
80
+ suffix: countSuffix(before, after, Math.min(suffixBound, shorter - prefix))
81
+ });
82
+ }
83
+ function countSuffix(before, after, limit) {
84
+ let length = 0;
85
+ while (length < limit && before[before.length - 1 - length] === after[after.length - 1 - length]) {
86
+ length += 1;
87
+ }
88
+ return length > 0 && (isLowSurrogateAt(before, before.length - length) || isLowSurrogateAt(after, after.length - length)) ? length - 1 : length;
89
+ }
90
+ function isLowSurrogateAt(text, index) {
91
+ const code = text.codePointAt(index) ?? 0;
92
+ return code >= 56320 && code <= 57343;
93
+ }
94
+ function buildEdit(before, after, shared) {
95
+ return {
96
+ at: shared.prefix,
97
+ inserted: after.length - shared.prefix - shared.suffix,
98
+ removed: before.length - shared.prefix - shared.suffix
99
+ };
100
+ }
101
+ function countPrefix(before, after, limit) {
102
+ let length = 0;
103
+ while (length < limit && before[length] === after[length]) {
104
+ length += 1;
105
+ }
106
+ return length > 0 && (isLowSurrogateAt(before, length) || isLowSurrogateAt(after, length)) ? length - 1 : length;
107
+ }
108
+ function isEditAtSelection(edit, selection) {
109
+ return edit.inserted === 0 || edit.at === selection.start && edit.at + edit.removed === selection.end;
110
+ }
111
+ function pickEditSource(removed, pending, insertion) {
112
+ const respacing = pending.respacing;
113
+ const isRespaced = respacing !== undefined && removed !== undefined && insertion.at === removed.at && insertion.removed === 0 && insertion.text === respacing && stripWhitespace(respacing) === stripWhitespace(removed.text);
114
+ return isRespaced ? "typed" : pending.source;
115
+ }
116
+ function stripWhitespace(text) {
117
+ return text.replaceAll(/\s/gu, "");
118
+ }
119
+ function splitSpan(span, edit) {
120
+ const removedEnd = edit.at + edit.removed;
121
+ const shift = edit.inserted - edit.removed;
122
+ if (span.end <= edit.at) {
123
+ return [span];
124
+ }
125
+ if (span.start >= removedEnd) {
126
+ return [{ ...span, end: span.end + shift, start: span.start + shift }];
127
+ }
128
+ const head = span.start < edit.at ? [{ ...span, end: edit.at }] : [];
129
+ const tail = span.end > removedEnd ? [{ ...span, end: span.end + shift, start: edit.at + edit.inserted }] : [];
130
+ return [...head, ...tail];
131
+ }
132
+ function findTypedRemoval(state, edit) {
133
+ const end = edit.at + edit.removed;
134
+ const isTyped = state.spans.some((span) => span.source === "typed" && span.start <= edit.at && end <= span.end);
135
+ return edit.inserted === 0 && edit.removed > 0 && isTyped ? { at: edit.at, text: state.text.slice(edit.at, end) } : undefined;
136
+ }
137
+ function mergeSpans(spans) {
138
+ const merged = [];
139
+ for (const span of spans.toSorted((left, right) => left.start - right.start)) {
140
+ const last = merged.at(-1);
141
+ if (last?.source === span.source && last.end === span.start) {
142
+ last.end = span.end;
143
+ } else if (span.end > span.start) {
144
+ merged.push({ ...span });
145
+ }
146
+ }
147
+ return merged;
148
+ }
149
+ // src/client-header-name.ts
150
+ var clientHeaderName = "x-nixie-client";
151
+ // src/contract.ts
152
+ import { eventIterator as eventIterator2, oc as oc2 } from "@orpc/contract";
153
+ import { z as z9 } from "zod";
154
+
155
+ // src/image-limits.ts
156
+ var imageLimits = {
157
+ count: 4,
158
+ bytes: 5 * 1024 * 1024,
159
+ longEdge: 1568,
160
+ mediaTypes: ["image/jpeg", "image/png", "image/webp", "image/gif"]
161
+ };
162
+
163
+ // src/image-not-found-error.ts
164
+ var imageNotFoundError = {
165
+ message: "No readable image of a message has this position",
166
+ status: 404
167
+ };
168
+
169
+ // src/image-refused-error.ts
170
+ import { z } from "zod";
171
+ var imageRefusedDataSchema = z.object({
172
+ position: z.int().nonnegative().nullable(),
173
+ reason: z.enum(["too_many", "too_large", "unsupported_type"])
174
+ });
175
+ var imageRefusedError = {
176
+ message: "An image is too large, of a type nixie does not take, or one too many",
177
+ status: 422,
178
+ data: imageRefusedDataSchema
179
+ };
180
+
181
+ // src/memory-view-contract.ts
182
+ import { z as z5 } from "zod";
183
+
184
+ // src/memory-export-contract.ts
185
+ import { eventIterator } from "@orpc/contract";
186
+ import { z as z2 } from "zod";
187
+
188
+ // src/reused-id-errors.ts
189
+ var reusedIDErrors = {
190
+ CLIENT_ACTION_ID_REUSED: {
191
+ message: "The client action ID belongs to a different action",
192
+ status: 409
193
+ }
194
+ };
195
+
196
+ // src/signed-in.ts
197
+ import { oc } from "@orpc/contract";
198
+ var signedIn = oc.errors({
199
+ UNAUTHORIZED: { message: "The device session is missing, lapsed or revoked", status: 401 }
200
+ });
201
+
202
+ // src/memory-export-contract.ts
203
+ var checkedExport = signedIn.errors(reusedIDErrors).errors({
204
+ MEMORY_NOT_STARTED: { message: "The memory store has not started yet", status: 503 }
205
+ });
206
+ var exportEvent = z2.union([
207
+ z2.object({ chunk: z2.string() }),
208
+ z2.object({ isComplete: z2.literal(true) })
209
+ ]);
210
+ var exportEvents = eventIterator(exportEvent);
211
+ var memoryExportContract = {
212
+ export: checkedExport.input(z2.object({ clientActionID: z2.uuid() })).output(exportEvents)
213
+ };
214
+
215
+ // src/moment-contract.ts
216
+ import { z as z3 } from "zod";
217
+ var momentView = signedIn.errors({
218
+ MEMORY_NOT_STARTED: { message: "The memory store has not started yet", status: 503 },
219
+ MOMENT_NOT_FOUND: { message: "No moment has this ID", status: 404 },
220
+ STALE_VERSION: { message: "The moment has moved past that version", status: 409 }
221
+ });
222
+ var momentIDSchema = z3.string().min(1).max(200);
223
+ var momentTargetSchema = z3.object({ momentID: momentIDSchema, version: z3.int().positive() });
224
+ var reflectionSchema = z3.object({
225
+ model: z3.string(),
226
+ text: z3.string().nullable(),
227
+ writtenAt: z3.date()
228
+ });
229
+ var destroyPreviewSchema = z3.object({
230
+ keptAt: z3.date(),
231
+ keptBy: z3.enum(["owner", "model"]),
232
+ kept: z3.object({ records: z3.int().nonnegative() }),
233
+ lost: z3.object({ links: z3.int().nonnegative(), texts: z3.int().nonnegative() }),
234
+ momentID: z3.string(),
235
+ note: z3.string().nullable(),
236
+ reflections: z3.array(reflectionSchema),
237
+ shortID: z3.string(),
238
+ state: z3.enum(["active", "retired"]),
239
+ thread: z3.string(),
240
+ title: z3.string().nullable(),
241
+ version: z3.int().positive()
242
+ });
243
+ var momentKeep = signedIn.errors(reusedIDErrors).errors({
244
+ MEMORY_NOT_STARTED: { message: "The memory store has not started yet", status: 503 },
245
+ BAD_SPAN: {
246
+ message: "The span needs a first and a last record on the thread, in order",
247
+ status: 422
248
+ }
249
+ });
250
+ var titleSchema = z3.string().min(1).max(120).regex(/\S/u);
251
+ var keepSchema = z3.object({
252
+ clientActionID: z3.uuid(),
253
+ firstSequence: z3.int().nonnegative(),
254
+ lastSequence: z3.int().nonnegative(),
255
+ thread: z3.string().min(1).max(200),
256
+ title: titleSchema
257
+ });
258
+ var momentSummarySchema = z3.object({
259
+ editedAt: z3.date().nullable(),
260
+ keptAt: z3.date(),
261
+ keptBy: z3.enum(["owner", "model"]),
262
+ momentID: z3.string(),
263
+ shortID: z3.string(),
264
+ state: z3.enum(["active", "retired"]),
265
+ title: z3.string().nullable()
266
+ });
267
+ var momentListSchema = z3.object({
268
+ before: z3.int().nonnegative().optional(),
269
+ includeRetired: z3.boolean(),
270
+ query: z3.string().max(500).optional()
271
+ });
272
+ var linkSchema = z3.object({
273
+ itemID: z3.string(),
274
+ shortID: z3.string(),
275
+ text: z3.string().nullable()
276
+ });
277
+ var noteSchema = z3.object({ text: z3.string(), writtenAt: z3.date() });
278
+ var shownReflectionSchema = reflectionSchema.extend({ reflectionID: z3.string() });
279
+ var momentDetailSchema = momentSummarySchema.extend({
280
+ firstSequence: z3.int().nonnegative(),
281
+ lastSequence: z3.int().nonnegative(),
282
+ links: z3.array(linkSchema),
283
+ note: noteSchema.nullable(),
284
+ reflections: z3.array(shownReflectionSchema),
285
+ thread: z3.string(),
286
+ titleBy: z3.enum(["owner", "model"]),
287
+ version: z3.int().positive()
288
+ });
289
+ var spanRecordSchema = z3.object({
290
+ isGap: z3.boolean(),
291
+ kind: z3.string(),
292
+ recordedAt: z3.date(),
293
+ sequence: z3.int().nonnegative(),
294
+ text: z3.string().nullable(),
295
+ tool: z3.string().nullable()
296
+ });
297
+ var momentChangeSchema = z3.discriminatedUnion("kind", [
298
+ z3.object({ kind: z3.literal("title"), title: titleSchema }),
299
+ z3.object({
300
+ kind: z3.literal("edges"),
301
+ firstSequence: z3.int().nonnegative(),
302
+ lastSequence: z3.int().nonnegative()
303
+ }),
304
+ z3.object({ kind: z3.literal("note"), note: z3.string().min(1).max(4000).regex(/\S/u) }),
305
+ z3.object({ kind: z3.literal("reflection_removed"), reflectionID: z3.string().min(1).max(200) })
306
+ ]);
307
+ var momentChange = momentView.errors(reusedIDErrors);
308
+ var momentContract = {
309
+ keepMoment: momentKeep.input(keepSchema).output(z3.object({ momentID: z3.string(), shortID: z3.string() })),
310
+ listMoments: signedIn.errors({
311
+ MEMORY_NOT_STARTED: { message: "The memory store has not started yet", status: 503 }
312
+ }).input(momentListSchema).output(z3.object({ moments: z3.array(momentSummarySchema), next: z3.int().nonnegative().nullable() })),
313
+ readMoment: momentView.input(z3.object({ momentID: momentIDSchema })).output(momentDetailSchema),
314
+ readMomentSpan: momentView.input(z3.object({ momentID: momentIDSchema, after: z3.int().nonnegative().optional() })).output(z3.object({ records: z3.array(spanRecordSchema), next: z3.int().nonnegative().nullable() })),
315
+ editMoment: momentChange.errors({
316
+ BAD_SPAN: {
317
+ message: "The span needs a first and a last record on the thread, in order",
318
+ status: 422
319
+ },
320
+ REFLECTION_NOT_FOUND: { message: "The moment has no reflection with this ID", status: 404 }
321
+ }).input(momentTargetSchema.extend({ clientActionID: z3.uuid(), change: momentChangeSchema })).output(z3.object({ momentID: z3.string(), version: z3.int().positive() })),
322
+ linkMoment: momentChange.errors({
323
+ MEMORY_ITEM_NOT_FOUND: { message: "No memory item has this ID", status: 404 },
324
+ ALREADY_LINKED: { message: "The item is already linked to the moment", status: 409 },
325
+ NOT_LINKED: { message: "The item is not linked to the moment", status: 409 }
326
+ }).input(momentTargetSchema.extend({
327
+ clientActionID: z3.uuid(),
328
+ isLinked: z3.boolean(),
329
+ itemID: z3.string().min(1).max(200)
330
+ })).output(z3.object({ momentID: z3.string(), version: z3.int().positive() })),
331
+ previewMomentDestroy: momentView.input(momentTargetSchema).output(destroyPreviewSchema),
332
+ destroyMoment: momentView.errors(reusedIDErrors).input(momentTargetSchema.extend({ clientActionID: z3.uuid() })).output(z3.object({ momentID: z3.string() }))
333
+ };
334
+
335
+ // src/proposal-outcome-schema.ts
336
+ import { z as z4 } from "zod";
337
+ var closeMatchSchema = z4.object({
338
+ itemID: z4.string(),
339
+ text: z4.string(),
340
+ version: z4.int().positive()
341
+ });
342
+ var proposalOutcomeSchema = z4.discriminatedUnion("status", [
343
+ z4.object({ proposalID: z4.string(), status: z4.literal("applied") }),
344
+ z4.object({ proposalID: z4.string(), status: z4.literal("rejected") }),
345
+ z4.object({
346
+ item: closeMatchSchema,
347
+ proposalID: z4.string(),
348
+ status: z4.literal("close_match")
349
+ }),
350
+ z4.object({
351
+ cause: z4.enum(["lapsed", "answered", "moved", "changed", "gone"]),
352
+ proposalID: z4.string(),
353
+ status: z4.literal("stale")
354
+ }),
355
+ z4.object({
356
+ code: z4.enum([
357
+ "CLIENT_ACTION_ID_REUSED",
358
+ "PIN_EDIT",
359
+ "PINNED_CORE_FULL",
360
+ "RETIREMENT_EDIT",
361
+ "REVISION_TARGET",
362
+ "WRONG_STATE"
363
+ ]),
364
+ proposalID: z4.string(),
365
+ status: z4.literal("refused")
366
+ })
367
+ ]);
368
+
369
+ // src/memory-view-contract.ts
370
+ var memoryView = signedIn.errors({
371
+ MEMORY_NOT_STARTED: { message: "The memory store has not started yet", status: 503 }
372
+ });
373
+ var memoryChange = memoryView.errors(reusedIDErrors).errors({
374
+ MEMORY_ITEM_NOT_FOUND: { message: "No memory item has this ID", status: 404 },
375
+ STALE_VERSION: { message: "The memory item has moved past that version", status: 409 },
376
+ WRONG_STATE: { message: "The memory item is not in a state that change takes", status: 409 }
377
+ });
378
+ var itemIDSchema = z5.string().min(1).max(200);
379
+ var itemTextSchema = z5.string().max(2000).regex(/\S/u);
380
+ var proposalOriginSchema = z5.enum(["owner", "conversation", "task", "memory_writer"]);
381
+ var originSchema = z5.enum([...proposalOriginSchema.options, "lapse"]);
382
+ var sourceSchema = z5.enum(["owner", "owner_data", "untrusted"]);
383
+ var subjectSchema = z5.enum(["owner", "self", "shared"]);
384
+ var kindSchema = z5.enum(["fact", "self"]);
385
+ var memoryItemSchema = z5.object({
386
+ changedAt: z5.date(),
387
+ createdAt: z5.date(),
388
+ forgottenAt: z5.date().nullable(),
389
+ isPinned: z5.boolean(),
390
+ isSensitive: z5.boolean(),
391
+ itemID: z5.string(),
392
+ kind: kindSchema,
393
+ origin: originSchema,
394
+ shortID: z5.string(),
395
+ source: sourceSchema,
396
+ state: z5.enum(["active", "retired", "forgetting", "forgotten"]),
397
+ status: z5.enum(["readable", "shredded", "unreadable"]),
398
+ subject: subjectSchema,
399
+ text: z5.string().optional(),
400
+ until: z5.date().nullable(),
401
+ version: z5.int().positive()
402
+ });
403
+ var memoryMatchSchema = memoryItemSchema.extend({
404
+ score: z5.number().optional(),
405
+ similarity: z5.number().optional()
406
+ });
407
+ var evidenceSchema = z5.object({
408
+ end: z5.int().nonnegative(),
409
+ message: z5.object({
410
+ status: z5.enum(["readable", "shredded", "unreadable", "missing"]),
411
+ text: z5.string().optional()
412
+ }).nullable(),
413
+ sequence: z5.int().nonnegative(),
414
+ start: z5.int().nonnegative()
415
+ });
416
+ var ownerImageSchema = z5.object({
417
+ position: z5.int().nonnegative(),
418
+ sequence: z5.int().positive(),
419
+ thread: z5.string()
420
+ });
421
+ var memoryVersionSchema = z5.object({
422
+ change: z5.enum(["created", "edited", "retired", "restored", "undone"]),
423
+ checkerModel: z5.string().nullable(),
424
+ checks: z5.record(z5.string(), z5.unknown()).nullable(),
425
+ evidence: evidenceSchema.nullable(),
426
+ evidenceQuote: z5.string().nullable(),
427
+ image: ownerImageSchema.nullable(),
428
+ origin: originSchema,
429
+ proposalID: z5.string().nullable(),
430
+ recordedAt: z5.date(),
431
+ source: sourceSchema,
432
+ state: z5.enum(["active", "retired"]),
433
+ status: z5.enum(["readable", "shredded", "unreadable"]),
434
+ taskID: z5.string().nullable(),
435
+ text: z5.string().optional(),
436
+ version: z5.int().positive(),
437
+ writerModel: z5.string().nullable()
438
+ });
439
+ var reviewReasonSchema = z5.enum([
440
+ "no_quote",
441
+ "quote_not_typed",
442
+ "quote_in_quoted_block",
443
+ "invisible_character",
444
+ "token_missing",
445
+ "checker_not_asserted",
446
+ "checker_unsure",
447
+ "checker_unreachable",
448
+ "forgotten_evidence",
449
+ "ambiguous_target",
450
+ "pinned",
451
+ "other",
452
+ "self_note",
453
+ "from_photo",
454
+ "sensitive"
455
+ ]);
456
+ var proposalSourceSchema = z5.object({
457
+ origin: proposalOriginSchema,
458
+ proposedAt: z5.date(),
459
+ thread: z5.string().nullable()
460
+ });
461
+ var memoryProposalSchema = z5.object({
462
+ actionHash: z5.string(),
463
+ createdAt: z5.date(),
464
+ evidence: evidenceSchema.nullable(),
465
+ image: ownerImageSchema.nullable(),
466
+ isPinned: z5.boolean(),
467
+ isSensitive: z5.boolean(),
468
+ itemID: z5.string(),
469
+ kind: kindSchema,
470
+ lapseAt: z5.date(),
471
+ operation: z5.enum(["remember", "retire", "pin"]),
472
+ origin: proposalOriginSchema,
473
+ proposalID: z5.string(),
474
+ quote: z5.string().nullable(),
475
+ reason: reviewReasonSchema,
476
+ source: sourceSchema,
477
+ sources: z5.array(proposalSourceSchema),
478
+ subject: subjectSchema,
479
+ targetVersion: z5.int().positive().nullable(),
480
+ text: z5.string(),
481
+ until: z5.date().nullable()
482
+ });
483
+ var proposalAnswerSchema = z5.object({
484
+ actionHash: z5.string().min(1).max(200),
485
+ clientActionID: z5.uuid(),
486
+ proposalID: z5.string().min(1).max(200)
487
+ });
488
+ var revisionTargetSchema = z5.object({ itemID: itemIDSchema, version: z5.int().positive() });
489
+ var approvalAnswerSchema = proposalAnswerSchema.extend({
490
+ editedText: itemTextSchema.optional(),
491
+ ignoreCloseMatch: z5.boolean().optional(),
492
+ revisionOf: revisionTargetSchema.optional()
493
+ });
494
+ var rejectionReasonSchema = z5.string().max(500).regex(/\S/u);
495
+ var rejectionAnswerSchema = proposalAnswerSchema.extend({
496
+ reason: rejectionReasonSchema.optional()
497
+ });
498
+ var proposalOutcomesSchema = z5.object({ outcomes: z5.array(proposalOutcomeSchema) });
499
+ var memoryItemDetailSchema = memoryItemSchema.extend({ versions: z5.array(memoryVersionSchema) });
500
+ var forgetLossSchema = z5.object({
501
+ evidenceMessages: z5.int().nonnegative(),
502
+ proposals: z5.int().nonnegative()
503
+ });
504
+ var forgetPreviewSchema = memoryItemDetailSchema.extend({ lost: forgetLossSchema });
505
+ var retiredForgetPreviewSchema = z5.object({
506
+ hasMore: z5.boolean(),
507
+ items: z5.array(memoryItemSchema.extend({ lost: forgetLossSchema }))
508
+ });
509
+ var retiredForgetSchema = z5.object({
510
+ clientActionID: z5.uuid(),
511
+ targets: z5.array(revisionTargetSchema).min(1).max(100).refine((targets) => new Set(targets.map((target) => target.itemID)).size === targets.length, {
512
+ message: "Each item appears once"
513
+ })
514
+ });
515
+ var forgetStatusSchema = z5.object({
516
+ deleted: z5.array(z5.string()),
517
+ pending: z5.array(z5.string())
518
+ });
519
+ var versionTargetSchema = z5.object({
520
+ clientActionID: z5.uuid(),
521
+ itemID: itemIDSchema,
522
+ version: z5.int().positive()
523
+ });
524
+ var versionResultSchema = z5.object({ itemID: z5.string(), version: z5.int().positive() });
525
+ var noticeEntrySchema = z5.object({
526
+ change: z5.enum(["created", "edited", "retired", "restored", "undone", "proposed"]),
527
+ isKept: z5.boolean(),
528
+ item: memoryItemSchema.extend({ change: z5.enum(["created", "edited", "retired", "restored", "undone"]) }).nullable(),
529
+ itemID: z5.string(),
530
+ proposalID: z5.string().nullable(),
531
+ sequence: z5.int().nonnegative(),
532
+ version: z5.int().positive().nullable()
533
+ });
534
+ var memoryNoticeSchema = z5.object({
535
+ entries: z5.array(noticeEntrySchema),
536
+ kind: z5.enum(["turn", "batch", "catch_up", "run"]),
537
+ messageSequence: z5.int().nonnegative().nullable(),
538
+ noticeKey: z5.string(),
539
+ proposed: z5.int().nonnegative(),
540
+ remembered: z5.int().nonnegative(),
541
+ retired: z5.int().nonnegative(),
542
+ sequence: z5.int().nonnegative()
543
+ });
544
+ var memoryViewContract = {
545
+ listItems: memoryView.errors({ INVALID_CURSOR: { message: "No page returned this cursor", status: 400 } }).input(z5.object({
546
+ after: z5.string().max(20).optional(),
547
+ kind: kindSchema.optional(),
548
+ limit: z5.int().min(1).max(100).optional(),
549
+ state: z5.enum(["active", "retired", "forgotten"])
550
+ })).output(z5.object({ items: z5.array(memoryItemSchema), next: z5.string().nullable() })),
551
+ findItems: memoryView.input(z5.object({ query: z5.string().min(1).max(500) })).output(z5.object({
552
+ items: z5.array(memoryMatchSchema),
553
+ searchMode: z5.enum(["hybrid", "keyword", "keyword-fallback"])
554
+ })),
555
+ readPinnedCore: memoryView.output(z5.object({
556
+ budget: z5.int().nonnegative(),
557
+ items: z5.array(memoryItemSchema),
558
+ tokens: z5.int().nonnegative()
559
+ })),
560
+ readItem: memoryView.errors({ MEMORY_ITEM_NOT_FOUND: { message: "No memory item has this ID", status: 404 } }).input(z5.object({ itemID: itemIDSchema })).output(memoryItemDetailSchema),
561
+ retire: memoryChange.input(versionTargetSchema).output(versionResultSchema),
562
+ restore: memoryChange.input(versionTargetSchema).output(versionResultSchema),
563
+ listNotices: memoryView.input(z5.object({ thread: z5.string().min(1).max(200) })).output(z5.object({ notices: z5.array(memoryNoticeSchema) })),
564
+ undo: memoryChange.errors({
565
+ PINNED_CORE_FULL: { message: "The undo takes the pinned core past its budget", status: 409 }
566
+ }).input(versionTargetSchema).output(versionResultSchema),
567
+ keep: memoryChange.input(versionTargetSchema).output(versionResultSchema),
568
+ previewForget: memoryView.errors({
569
+ MEMORY_ITEM_NOT_FOUND: { message: "No memory item has this ID", status: 404 },
570
+ STALE_VERSION: { message: "The memory item has moved past that version", status: 409 }
571
+ }).input(z5.object({ itemID: itemIDSchema, version: z5.int().positive() })).output(forgetPreviewSchema),
572
+ forget: memoryChange.input(versionTargetSchema).output(z5.object({ itemID: z5.string() })),
573
+ previewForgetRetired: memoryView.output(retiredForgetPreviewSchema),
574
+ forgetRetired: memoryChange.input(retiredForgetSchema).output(forgetStatusSchema),
575
+ readForgetStatus: memoryView.input(z5.object({ itemIDs: z5.array(itemIDSchema).min(1).max(100) })).output(forgetStatusSchema),
576
+ pin: memoryChange.errors({
577
+ PINNED_CORE_FULL: { message: "The pin takes the pinned core past its budget", status: 409 }
578
+ }).input(versionTargetSchema.extend({ isPinned: z5.boolean() })).output(z5.object({ isPinned: z5.boolean(), itemID: z5.string() })),
579
+ markSensitive: memoryChange.input(z5.object({ clientActionID: z5.uuid(), isSensitive: z5.boolean(), itemID: itemIDSchema })).output(z5.object({ isSensitive: z5.boolean(), itemID: z5.string() })),
580
+ listProposals: memoryView.output(z5.object({ proposals: z5.array(memoryProposalSchema) })),
581
+ approveProposals: memoryView.input(z5.object({
582
+ answers: z5.array(approvalAnswerSchema).min(1).max(50)
583
+ })).output(proposalOutcomesSchema),
584
+ rejectProposals: memoryView.input(z5.object({
585
+ answers: z5.array(rejectionAnswerSchema).min(1).max(50)
586
+ })).output(proposalOutcomesSchema),
587
+ ...memoryExportContract,
588
+ ...momentContract
589
+ };
590
+
591
+ // src/span-schema.ts
592
+ import { z as z6 } from "zod";
593
+ var spanSchema = z6.object({
594
+ end: z6.int().nonnegative(),
595
+ source: z6.enum(["typed", "pasted", "dropped", "unknown"]),
596
+ start: z6.int().nonnegative()
597
+ });
598
+
599
+ // src/task-schema.ts
600
+ import { z as z7 } from "zod";
601
+ var taskSchema = z7.object({
602
+ error: z7.string().optional(),
603
+ errorLimit: z7.int().positive().optional(),
604
+ errors: z7.int().positive().optional(),
605
+ retryAt: z7.date().optional(),
606
+ stepKey: z7.string().optional(),
607
+ taskID: z7.string()
608
+ });
609
+
610
+ // src/tool-call-schema.ts
611
+ import { z as z8 } from "zod";
612
+ var jsonObjectSchema = z8.record(z8.string(), z8.unknown());
613
+ var toolCallSchema = z8.object({
614
+ callID: z8.string(),
615
+ content: jsonObjectSchema.optional(),
616
+ input: jsonObjectSchema.optional(),
617
+ outcome: z8.string().optional(),
618
+ tool: z8.string().optional()
619
+ });
620
+
621
+ // src/contract.ts
622
+ var clientActionIDSchema = z9.uuid();
623
+ var sequenceSchema = z9.int().nonnegative();
624
+ var threadSchema = z9.string().min(1).max(200);
625
+ var imageSchema = z9.object({ mediaType: z9.enum(imageLimits.mediaTypes) });
626
+ var imageFilesSchema = z9.array(z9.file());
627
+ var imageRefSchema = z9.object({
628
+ position: z9.int().nonnegative(),
629
+ sequence: sequenceSchema,
630
+ thread: threadSchema
631
+ });
632
+ var versionRefSchema = z9.object({
633
+ itemID: z9.string().min(1).max(200),
634
+ version: z9.int().nonnegative()
635
+ });
636
+ var recallItemSchema = versionRefSchema.extend({ score: z9.number().optional() });
637
+ var recallSchema = z9.object({ items: z9.array(recallItemSchema) });
638
+ var ratingItemSchema = versionRefSchema.extend({
639
+ hasNote: z9.boolean(),
640
+ verdict: z9.enum(["helpful", "noise", "misleading"])
641
+ });
642
+ var ratingSchema = z9.object({
643
+ items: z9.array(ratingItemSchema),
644
+ ratedBy: z9.string().optional(),
645
+ recalledSequence: sequenceSchema
646
+ });
647
+ var tokenCountSchema = z9.int().nonnegative();
648
+ var contextSchema = z9.object({ size: tokenCountSchema, window: z9.int().positive() });
649
+ var compactionSchema = z9.object({
650
+ postTokens: tokenCountSchema.optional(),
651
+ preTokens: tokenCountSchema,
652
+ trigger: z9.enum(["manual", "auto"])
653
+ });
654
+ var summarySchema = z9.object({
655
+ contextSize: tokenCountSchema.optional(),
656
+ summaryTokens: tokenCountSchema,
657
+ text: z9.string().optional(),
658
+ trigger: z9.enum(["threshold", "overflow"])
659
+ });
660
+ var compactionFailureSchema = z9.object({ failures: z9.int().positive() });
661
+ var ratingNoteRefSchema = z9.object({
662
+ itemID: z9.string().min(1).max(200),
663
+ sequence: sequenceSchema
664
+ });
665
+ var ratingNoteSchema = ratingNoteRefSchema.extend({
666
+ status: z9.enum(["readable", "shredded", "unreadable", "missing"]),
667
+ text: z9.string().optional()
668
+ });
669
+ var versionTextSchema = versionRefSchema.extend({
670
+ status: z9.enum(["readable", "shredded", "unreadable", "missing"]),
671
+ text: z9.string().optional()
672
+ });
673
+ var recordSchema = z9.object({
674
+ compaction: compactionSchema.optional(),
675
+ compactionFailure: compactionFailureSchema.optional(),
676
+ forget: z9.object({ sequence: sequenceSchema }).optional(),
677
+ context: contextSchema.optional(),
678
+ kind: z9.string(),
679
+ message: z9.object({
680
+ clientMessageId: z9.uuid().optional(),
681
+ images: z9.array(imageSchema).optional(),
682
+ spans: z9.array(spanSchema).optional(),
683
+ text: z9.string()
684
+ }).optional(),
685
+ moment: z9.object({ momentID: z9.string(), shortID: z9.string(), title: z9.string().optional() }).optional(),
686
+ rating: ratingSchema.optional(),
687
+ recall: recallSchema.optional(),
688
+ recordedAt: z9.date(),
689
+ sequence: sequenceSchema,
690
+ summary: summarySchema.optional(),
691
+ thread: threadSchema,
692
+ task: taskSchema.optional(),
693
+ toolCall: toolCallSchema.optional()
694
+ });
695
+ var writerErrorSchema = z9.object({ at: z9.date(), code: z9.string(), message: z9.string().nullable() }).nullable();
696
+ var sessionSchema = z9.object({
697
+ createdAt: z9.date(),
698
+ current: z9.boolean(),
699
+ deviceName: z9.string(),
700
+ lastUsedAt: z9.date(),
701
+ sessionID: z9.uuid()
702
+ });
703
+ var checkedAction = signedIn.errors(reusedIDErrors);
704
+ var followRecords = signedIn.input(z9.object({ afterSequence: sequenceSchema, thread: threadSchema.optional() })).output(eventIterator2(z9.object({ record: recordSchema })));
705
+ var contract = {
706
+ conversation: {
707
+ read: signedIn.errors({ THREAD_NOT_FOUND: { message: "No thread has this ID", status: 404 } }).input(z9.object({
708
+ beforeSequence: sequenceSchema.optional(),
709
+ limit: z9.int().min(1).max(200).optional(),
710
+ thread: threadSchema
711
+ })).output(z9.object({
712
+ hasEarlier: z9.boolean(),
713
+ readAtSequence: sequenceSchema,
714
+ records: z9.array(recordSchema),
715
+ lastStepEnd: recordSchema.nullable().optional()
716
+ })),
717
+ send: checkedAction.errors({
718
+ IMAGE_REFUSED: imageRefusedError,
719
+ THREAD_NOT_FOUND: { message: "No thread has this ID", status: 404 }
720
+ }).input(z9.object({
721
+ clientMessageId: clientActionIDSchema,
722
+ images: imageFilesSchema.optional(),
723
+ spans: z9.array(spanSchema).max(1e5),
724
+ text: z9.string().min(1).max(1e5),
725
+ thread: threadSchema,
726
+ timeZone: z9.string().min(1).max(100).optional(),
727
+ writtenAt: z9.iso.datetime().optional()
728
+ })).output(z9.object({ duplicate: z9.boolean(), sequence: sequenceSchema })),
729
+ readImage: signedIn.errors({ IMAGE_NOT_FOUND: imageNotFoundError }).input(imageRefSchema).output(z9.file()),
730
+ forget: checkedAction.errors({
731
+ RECORD_NOT_FOUND: {
732
+ message: "No message or reply on this thread has this sequence",
733
+ status: 404
734
+ }
735
+ }).input(z9.object({
736
+ clientActionID: clientActionIDSchema,
737
+ sequence: sequenceSchema,
738
+ thread: threadSchema
739
+ })).output(z9.object({ forgottenAt: z9.date() }))
740
+ },
741
+ memory: {
742
+ readVersions: signedIn.input(z9.object({ versions: z9.array(versionRefSchema).min(1).max(100) })).output(z9.object({ versions: z9.array(versionTextSchema) })),
743
+ readRatingNotes: signedIn.input(z9.object({ notes: z9.array(ratingNoteRefSchema).min(1).max(100) })).output(z9.object({ notes: z9.array(ratingNoteSchema) })),
744
+ writerStatus: signedIn.output(z9.object({
745
+ isEnabled: z9.boolean(),
746
+ backlog: z9.int().nonnegative(),
747
+ batches: z9.int().nonnegative(),
748
+ cursor: sequenceSchema,
749
+ failures: z9.int().nonnegative(),
750
+ isCatchingUp: z9.boolean(),
751
+ lastError: writerErrorSchema,
752
+ retryAt: z9.date().nullable()
753
+ })),
754
+ consolidatorStatus: signedIn.output(z9.object({ isEnabled: z9.boolean() })),
755
+ ...memoryViewContract
756
+ },
757
+ log: {
758
+ follow: followRecords.route({ deprecated: true })
759
+ },
760
+ records: {
761
+ follow: followRecords
762
+ },
763
+ sessions: {
764
+ enrol: oc2.errors(reusedIDErrors).errors({
765
+ ENROLMENT_CODE_INVALID: {
766
+ message: "The enrolment code is unknown, used or lapsed",
767
+ status: 400
768
+ }
769
+ }).input(z9.object({
770
+ clientActionID: clientActionIDSchema,
771
+ code: z9.string().min(1).max(100),
772
+ deviceName: z9.string().min(1).max(100),
773
+ tokenDelivery: z9.enum(["cookie", "bearer"])
774
+ })).output(z9.object({ sessionID: z9.uuid(), token: z9.string().optional() })),
775
+ issueCode: checkedAction.input(z9.object({ clientActionID: clientActionIDSchema })).output(z9.object({ code: z9.string(), expiresAt: z9.date() })),
776
+ list: signedIn.output(z9.object({ sessions: z9.array(sessionSchema) })),
777
+ revoke: checkedAction.errors({ SESSION_NOT_FOUND: { message: "No session has this ID", status: 404 } }).input(z9.object({ clientActionID: clientActionIDSchema, sessionID: z9.uuid() })).output(z9.object({ revokedAt: z9.date() }))
778
+ }
779
+ };
780
+ // src/host-contract.ts
781
+ import { oc as oc3 } from "@orpc/contract";
782
+ import { z as z10 } from "zod";
783
+ var versionRefSchema2 = z10.object({ itemID: z10.string(), version: z10.int().positive() });
784
+ var versionTargetSchema2 = z10.strictObject({
785
+ itemID: z10.string().min(1),
786
+ version: z10.int().positive()
787
+ });
788
+ var itemTextSchema2 = z10.string().max(2000).regex(/\S/u);
789
+ var proposalOriginSchema2 = z10.enum(["owner", "conversation", "task", "memory_writer"]);
790
+ var memoryOriginSchema = z10.enum([...proposalOriginSchema2.options, "lapse"]);
791
+ var contentSourceSchema = z10.enum(["owner", "owner_data", "untrusted"]);
792
+ var reviewReasonSchema2 = z10.enum([
793
+ "no_quote",
794
+ "quote_not_typed",
795
+ "quote_in_quoted_block",
796
+ "invisible_character",
797
+ "token_missing",
798
+ "checker_not_asserted",
799
+ "checker_unsure",
800
+ "checker_unreachable",
801
+ "forgotten_evidence",
802
+ "ambiguous_target",
803
+ "pinned",
804
+ "other",
805
+ "self_note",
806
+ "from_photo",
807
+ "sensitive"
808
+ ]);
809
+ var proposalSourceSchema2 = z10.object({
810
+ origin: proposalOriginSchema2,
811
+ thread: z10.string().nullable(),
812
+ proposedAt: z10.date()
813
+ });
814
+ var pendingProposalSchema = z10.object({
815
+ proposalID: z10.string(),
816
+ operation: z10.enum(["remember", "retire", "pin"]),
817
+ itemID: z10.string(),
818
+ targetVersion: z10.int().nullable(),
819
+ isPinned: z10.boolean(),
820
+ subject: z10.enum(["owner", "self", "shared"]),
821
+ isSensitive: z10.boolean(),
822
+ kind: z10.enum(["fact", "self"]),
823
+ reason: reviewReasonSchema2,
824
+ actionHash: z10.string(),
825
+ origin: proposalOriginSchema2,
826
+ source: contentSourceSchema,
827
+ createdAt: z10.date(),
828
+ lapseAt: z10.date(),
829
+ sources: z10.array(proposalSourceSchema2),
830
+ text: z10.string(),
831
+ quote: z10.string().nullable()
832
+ });
833
+ var closeMatchSchema2 = z10.object({ itemID: z10.string(), version: z10.int(), text: z10.string() });
834
+ var approvalResultSchema = z10.discriminatedUnion("status", [
835
+ z10.object({ status: z10.literal("applied"), itemID: z10.string(), version: z10.int() }),
836
+ z10.object({ status: z10.literal("close_match"), item: closeMatchSchema2 })
837
+ ]);
838
+ var historyVersionSchema = z10.object({
839
+ version: z10.int(),
840
+ change: z10.enum(["created", "edited", "retired", "restored", "undone"]),
841
+ state: z10.enum(["active", "retired"]),
842
+ origin: memoryOriginSchema,
843
+ source: contentSourceSchema,
844
+ recordedAt: z10.date(),
845
+ status: z10.enum(["readable", "shredded", "unreadable"]),
846
+ text: z10.string().nullable()
847
+ });
848
+ var itemHistorySchema = z10.object({
849
+ itemID: z10.string(),
850
+ subject: z10.enum(["owner", "self", "shared"]),
851
+ kind: z10.enum(["fact", "self"]),
852
+ state: z10.enum(["active", "retired", "forgetting", "forgotten"]),
853
+ versions: z10.array(historyVersionSchema)
854
+ });
855
+ var changeInputSchema = z10.object({
856
+ itemID: z10.string(),
857
+ version: z10.int(),
858
+ text: z10.string().nullable(),
859
+ isCurrent: z10.boolean()
860
+ });
861
+ var changeCommentSchema = z10.object({ text: z10.string(), at: z10.date() });
862
+ var consolidationChangeSchema = z10.object({
863
+ changeID: z10.string(),
864
+ shortID: z10.string(),
865
+ kind: z10.enum(["merge", "rewrite", "retire"]),
866
+ inputs: z10.array(changeInputSchema),
867
+ text: z10.string().nullable(),
868
+ reason: z10.string(),
869
+ source: contentSourceSchema,
870
+ actionHash: z10.string(),
871
+ lapseAt: z10.date(),
872
+ comment: changeCommentSchema.nullable()
873
+ });
874
+ var consolidationDiffSchema = z10.object({
875
+ diffID: z10.string(),
876
+ model: z10.string().nullable(),
877
+ createdAt: z10.date(),
878
+ changes: z10.array(consolidationChangeSchema),
879
+ summary: z10.string().nullable()
880
+ });
881
+ var changeOutcomeSchema = z10.discriminatedUnion("status", [
882
+ z10.object({
883
+ changeID: z10.string(),
884
+ status: z10.literal("applied"),
885
+ versions: z10.array(versionRefSchema2)
886
+ }),
887
+ z10.object({ changeID: z10.string(), status: z10.literal("refused"), code: z10.string() })
888
+ ]);
889
+ var changeAnswerSchema = z10.strictObject({
890
+ changeID: z10.string().min(1),
891
+ actionHash: z10.string().min(1)
892
+ });
893
+ var proposalAnswerSchema2 = z10.strictObject({
894
+ proposalID: z10.string().min(1),
895
+ actionHash: z10.string().min(1)
896
+ });
897
+ var hostSessionSchema = z10.object({
898
+ sessionID: z10.string(),
899
+ deviceName: z10.string(),
900
+ createdAt: z10.date(),
901
+ lastUsedAt: z10.date()
902
+ });
903
+ var subjectCountSchema = z10.object({
904
+ owner: z10.int().nonnegative(),
905
+ shared: z10.int().nonnegative(),
906
+ self: z10.int().nonnegative()
907
+ });
908
+ var memory = oc3.errors({
909
+ MEMORY_NOT_STARTED: { message: "the memory store has not started yet", status: 503 },
910
+ NOT_FOUND: { message: "nothing has that ID", status: 404 },
911
+ PROPOSAL_HASH: { message: "the action hash names another proposal", status: 409 },
912
+ PROPOSAL_CLOSED: { message: "the proposal is answered or lapsed", status: 409 },
913
+ STALE_VERSION: { message: "the item has moved past that version", status: 409 },
914
+ WRONG_STATE: { message: "the item is not in a state that change takes", status: 409 },
915
+ PINNED_CORE_FULL: { message: "the pinned core is full", status: 409 },
916
+ REVISION_TARGET: { message: "that item cannot take the revision", status: 400 },
917
+ RETIREMENT_EDIT: { message: "a retirement takes no edited text", status: 400 },
918
+ PIN_EDIT: { message: "a pin takes no edited text", status: 400 },
919
+ SELF_NOTE_REFUSED: { message: "a self-note never takes that change", status: 409 }
920
+ });
921
+ var skillFileSchema = z10.object({ path: z10.string(), text: z10.string() });
922
+ var pendingSkillProposalSchema = z10.object({
923
+ proposalID: z10.string(),
924
+ name: z10.string(),
925
+ skillHash: z10.string(),
926
+ baseHash: z10.string().nullable(),
927
+ files: z10.array(skillFileSchema),
928
+ inForce: z10.object({
929
+ skillHash: z10.string(),
930
+ origin: z10.enum(["definitions", "vendored", "nixie"]),
931
+ files: z10.array(skillFileSchema)
932
+ }).nullable(),
933
+ untypedToken: z10.object({ kind: z10.string(), raw: z10.string() }).nullable(),
934
+ thread: z10.string().nullable(),
935
+ provenance: z10.object({ runID: z10.string(), callID: z10.string(), profile: z10.string() }),
936
+ createdAt: z10.date(),
937
+ lapseAt: z10.date(),
938
+ isStale: z10.boolean()
939
+ });
940
+ var skillAnswerSchema = z10.strictObject({
941
+ proposalID: z10.string().min(1),
942
+ skillHash: z10.string().min(1)
943
+ });
944
+ var skills = oc3.errors({
945
+ NOT_FOUND: { message: "nothing has that ID", status: 404 },
946
+ PROPOSAL_HASH: { message: "the skill hash names other files", status: 409 },
947
+ PROPOSAL_CLOSED: { message: "the proposal is answered or lapsed", status: 409 },
948
+ STALE_BASE: { message: "the skill in force moved past the proposal", status: 409 },
949
+ SKILL_CHECK: { message: "the files fail the seed checks", status: 400 },
950
+ WRONG_STATE: { message: "the skill nixie wrote is no longer in force", status: 409 }
951
+ });
952
+ var definitionsSkillSchema = z10.object({ skillHash: z10.string(), origin: z10.enum(["definitions", "vendored"]) }).nullable();
953
+ var writtenSkillSchema = z10.object({
954
+ approvalID: z10.string(),
955
+ proposalID: z10.string(),
956
+ name: z10.string(),
957
+ skillHash: z10.string(),
958
+ base: definitionsSkillSchema,
959
+ definitions: definitionsSkillSchema,
960
+ isConflict: z10.boolean(),
961
+ pullRequestURL: z10.url().nullable(),
962
+ approvedAt: z10.date()
963
+ });
964
+ var promptPartFileSchema = z10.object({ path: z10.string(), text: z10.string() });
965
+ var promptEntrySchema = z10.record(z10.string(), z10.string());
966
+ var pendingPromptProposalSchema = z10.object({
967
+ proposalID: z10.string(),
968
+ promptID: z10.string(),
969
+ proposalHash: z10.string(),
970
+ baseHash: z10.string().nullable(),
971
+ entry: promptEntrySchema,
972
+ files: z10.array(promptPartFileSchema),
973
+ reason: z10.string(),
974
+ inForce: z10.object({ parts: promptEntrySchema, template: z10.string().nullable() }).nullable(),
975
+ thread: z10.string().nullable(),
976
+ provenance: z10.object({ runID: z10.string(), callID: z10.string(), profile: z10.string() }),
977
+ createdAt: z10.date(),
978
+ lapseAt: z10.date(),
979
+ isStale: z10.boolean()
980
+ });
981
+ var promptAnswerSchema = z10.strictObject({
982
+ proposalID: z10.string().min(1),
983
+ proposalHash: z10.string().min(1)
984
+ });
985
+ var prompts = oc3.errors({
986
+ NOT_FOUND: { message: "nothing has that ID", status: 404 },
987
+ PROPOSAL_HASH: { message: "the proposal hash names another override", status: 409 },
988
+ PROPOSAL_CLOSED: { message: "the proposal is answered or lapsed", status: 409 },
989
+ STALE_BASE: { message: "the override in force moved past the proposal", status: 409 },
990
+ PROMPT_CHECK: { message: "the override fails the definitions checks", status: 400 }
991
+ });
992
+ var forgottenItemsSchema = z10.object({ itemIDs: z10.array(z10.string()) });
993
+ var hostContract = {
994
+ reset: oc3.output(z10.object({
995
+ resetAt: z10.date(),
996
+ lastSequence: z10.int().nonnegative(),
997
+ keptSessions: z10.int().nonnegative()
998
+ })),
999
+ resetConversations: oc3.output(z10.object({
1000
+ resetAt: z10.date(),
1001
+ lastSequence: z10.int().nonnegative(),
1002
+ shreddedRecords: z10.int().nonnegative()
1003
+ })),
1004
+ sessions: {
1005
+ issueCode: oc3.output(z10.object({ code: z10.string(), expiresAt: z10.date() })),
1006
+ list: oc3.output(z10.array(hostSessionSchema)),
1007
+ label: oc3.errors({
1008
+ SESSION_NOT_FOUND: {
1009
+ message: "no device session that is still signed in has that ID",
1010
+ status: 404
1011
+ },
1012
+ LABEL_INVALID: { message: "a label holds 1 to 100 characters besides spaces", status: 400 }
1013
+ }).input(z10.strictObject({ sessionID: z10.string().min(1), label: z10.string() })).output(z10.object({ sessionID: z10.string(), label: z10.string() }))
1014
+ },
1015
+ memory: {
1016
+ proposals: {
1017
+ list: memory.output(z10.array(pendingProposalSchema)),
1018
+ approve: memory.input(proposalAnswerSchema2.extend({
1019
+ revisionOf: versionTargetSchema2.optional(),
1020
+ ignoreCloseMatch: z10.boolean().optional(),
1021
+ editedText: itemTextSchema2.optional()
1022
+ })).output(approvalResultSchema),
1023
+ reject: memory.input(proposalAnswerSchema2.extend({ reason: z10.string().max(500).regex(/\S/u).optional() })).output(z10.object({ proposalID: z10.string() }))
1024
+ },
1025
+ subjects: memory.output(z10.object({ items: subjectCountSchema, proposals: subjectCountSchema })),
1026
+ items: {
1027
+ read: memory.input(z10.strictObject({ itemID: z10.string().min(1) })).output(itemHistorySchema),
1028
+ edit: memory.input(versionTargetSchema2.extend({ text: itemTextSchema2 })).output(versionRefSchema2),
1029
+ retire: memory.input(versionTargetSchema2).output(versionRefSchema2),
1030
+ restore: memory.input(versionTargetSchema2).output(versionRefSchema2),
1031
+ forget: memory.input(versionTargetSchema2).output(z10.object({ itemID: z10.string() })),
1032
+ forgetAll: memory.output(forgottenItemsSchema),
1033
+ pin: memory.input(z10.strictObject({ itemID: z10.string().min(1), isPinned: z10.boolean() })).output(z10.object({ itemID: z10.string(), isPinned: z10.boolean() }))
1034
+ },
1035
+ consolidation: {
1036
+ read: memory.output(consolidationDiffSchema.nullable()),
1037
+ approve: memory.input(z10.strictObject({ answers: z10.array(changeAnswerSchema).min(1).max(30) })).output(z10.object({ outcomes: z10.array(changeOutcomeSchema) })),
1038
+ reject: memory.input(changeAnswerSchema).output(z10.object({ changeID: z10.string() }))
1039
+ }
1040
+ },
1041
+ skills: {
1042
+ proposals: {
1043
+ list: skills.output(z10.array(pendingSkillProposalSchema)),
1044
+ approve: skills.input(skillAnswerSchema.extend({ files: z10.array(skillFileSchema).min(1).optional() })).output(z10.object({ proposalID: z10.string(), approvalID: z10.string(), skillHash: z10.string() })),
1045
+ reject: skills.input(skillAnswerSchema.extend({ reason: z10.string().max(500).regex(/\S/u) })).output(z10.object({ proposalID: z10.string() }))
1046
+ },
1047
+ written: {
1048
+ list: skills.output(z10.array(writtenSkillSchema)),
1049
+ resolve: skills.input(z10.strictObject({
1050
+ approvalID: z10.string().min(1),
1051
+ keep: z10.enum(["nixie", "definitions"])
1052
+ })).output(z10.object({ approvalID: z10.string(), keep: z10.enum(["nixie", "definitions"]) }))
1053
+ }
1054
+ },
1055
+ prompts: {
1056
+ proposals: {
1057
+ list: prompts.output(z10.array(pendingPromptProposalSchema)),
1058
+ approve: prompts.input(promptAnswerSchema.extend({
1059
+ entry: promptEntrySchema.optional(),
1060
+ files: z10.array(promptPartFileSchema).optional()
1061
+ })).output(z10.object({ proposalID: z10.string(), approvalID: z10.string(), proposalHash: z10.string() })),
1062
+ reject: prompts.input(promptAnswerSchema.extend({ reason: z10.string().max(500).regex(/\S/u) })).output(z10.object({ proposalID: z10.string() }))
1063
+ }
1064
+ }
1065
+ };
1066
+ // src/is-time-zone.ts
1067
+ function isTimeZone(zone) {
1068
+ try {
1069
+ return new Intl.DateTimeFormat("en-US", { timeZone: zone }).resolvedOptions().timeZone !== "";
1070
+ } catch {
1071
+ return false;
1072
+ }
1073
+ }
1074
+ // src/session-cookie-name.ts
1075
+ var sessionCookieName = "nixie_session";
1076
+
1077
+ // src/render-session-cookie.ts
1078
+ var MAX_AGE_S = 400 * 24 * 60 * 60;
1079
+ function renderSessionCookie(token) {
1080
+ const maxAgeS = token === null ? 0 : MAX_AGE_S;
1081
+ return `${sessionCookieName}=${token ?? ""}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=${maxAgeS}`;
1082
+ }
1083
+ export {
1084
+ buildPendingInput,
1085
+ buildQueryUtils,
1086
+ buildSpanState,
1087
+ clientHeaderName,
1088
+ contract,
1089
+ hostContract,
1090
+ imageLimits,
1091
+ isTimeZone,
1092
+ pickSpanSource,
1093
+ proposalOutcomeSchema,
1094
+ renderSessionCookie,
1095
+ sessionCookieName,
1096
+ spanSchema
1097
+ };