@cleocode/contracts 2026.6.12 → 2026.6.13

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.
Files changed (136) hide show
  1. package/dist/__tests__/operation-def.test.js +2 -1
  2. package/dist/__tests__/operation-def.test.js.map +1 -1
  3. package/dist/__tests__/sealed-credential.test.d.ts +19 -0
  4. package/dist/__tests__/sealed-credential.test.d.ts.map +1 -0
  5. package/dist/__tests__/sealed-credential.test.js +74 -0
  6. package/dist/__tests__/sealed-credential.test.js.map +1 -0
  7. package/dist/__tests__/skill-executor-contract.test.js +3 -0
  8. package/dist/__tests__/skill-executor-contract.test.js.map +1 -1
  9. package/dist/acceptance-gate.d.ts +2 -3
  10. package/dist/acceptance-gate.d.ts.map +1 -1
  11. package/dist/boundary.d.ts.map +1 -1
  12. package/dist/boundary.js +1 -19
  13. package/dist/boundary.js.map +1 -1
  14. package/dist/config.d.ts +102 -0
  15. package/dist/config.d.ts.map +1 -1
  16. package/dist/data-accessor.d.ts +21 -1
  17. package/dist/data-accessor.d.ts.map +1 -1
  18. package/dist/data-accessor.js.map +1 -1
  19. package/dist/dispatch/identity.d.ts +1 -1
  20. package/dist/dispatch/identity.d.ts.map +1 -1
  21. package/dist/dispatch/identity.js +5 -0
  22. package/dist/dispatch/identity.js.map +1 -1
  23. package/dist/dispatch/operations-registry.d.ts.map +1 -1
  24. package/dist/dispatch/operations-registry.js +46 -168
  25. package/dist/dispatch/operations-registry.js.map +1 -1
  26. package/dist/docs/read.d.ts +2 -2
  27. package/dist/index.d.ts +12 -7
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +3 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/lease-ipc/__tests__/freeze.test.d.ts +15 -0
  32. package/dist/lease-ipc/__tests__/freeze.test.d.ts.map +1 -0
  33. package/dist/lease-ipc/__tests__/freeze.test.js +221 -0
  34. package/dist/lease-ipc/__tests__/freeze.test.js.map +1 -0
  35. package/dist/lease-ipc/index.d.ts +17 -0
  36. package/dist/lease-ipc/index.d.ts.map +1 -0
  37. package/dist/lease-ipc/index.js +16 -0
  38. package/dist/lease-ipc/index.js.map +1 -0
  39. package/dist/lease-ipc/messages.d.ts +754 -0
  40. package/dist/lease-ipc/messages.d.ts.map +1 -0
  41. package/dist/lease-ipc/messages.js +383 -0
  42. package/dist/lease-ipc/messages.js.map +1 -0
  43. package/dist/lease-ipc/version.d.ts +41 -0
  44. package/dist/lease-ipc/version.d.ts.map +1 -0
  45. package/dist/lease-ipc/version.js +43 -0
  46. package/dist/lease-ipc/version.js.map +1 -0
  47. package/dist/llm/interfaces.d.ts +23 -0
  48. package/dist/llm/interfaces.d.ts.map +1 -1
  49. package/dist/llm/sealed-credential.d.ts +164 -0
  50. package/dist/llm/sealed-credential.d.ts.map +1 -0
  51. package/dist/llm/sealed-credential.js +43 -0
  52. package/dist/llm/sealed-credential.js.map +1 -0
  53. package/dist/llm/system-of-use.d.ts +383 -0
  54. package/dist/llm/system-of-use.d.ts.map +1 -0
  55. package/dist/llm/system-of-use.js +238 -0
  56. package/dist/llm/system-of-use.js.map +1 -0
  57. package/dist/llm/system-resolver.d.ts +45 -11
  58. package/dist/llm/system-resolver.d.ts.map +1 -1
  59. package/dist/llm/system-resolver.js +14 -7
  60. package/dist/llm/system-resolver.js.map +1 -1
  61. package/dist/operations/__tests__/ensures-schema-registry.test.d.ts +17 -0
  62. package/dist/operations/__tests__/ensures-schema-registry.test.d.ts.map +1 -0
  63. package/dist/operations/__tests__/ensures-schema-registry.test.js +113 -0
  64. package/dist/operations/__tests__/ensures-schema-registry.test.js.map +1 -0
  65. package/dist/operations/ensures-schema-registry.d.ts +172 -0
  66. package/dist/operations/ensures-schema-registry.d.ts.map +1 -0
  67. package/dist/operations/ensures-schema-registry.js +226 -0
  68. package/dist/operations/ensures-schema-registry.js.map +1 -0
  69. package/dist/operations/llm.d.ts +101 -9
  70. package/dist/operations/llm.d.ts.map +1 -1
  71. package/dist/operations/validate.d.ts +1 -12
  72. package/dist/operations/validate.d.ts.map +1 -1
  73. package/dist/operations/validate.js +1 -1
  74. package/dist/playbook.d.ts +60 -0
  75. package/dist/playbook.d.ts.map +1 -1
  76. package/dist/session.d.ts +11 -0
  77. package/dist/session.d.ts.map +1 -1
  78. package/dist/session.js.map +1 -1
  79. package/dist/templates/manifest.d.ts +1 -1
  80. package/dist/tools/agent-tools.d.ts +231 -0
  81. package/dist/tools/agent-tools.d.ts.map +1 -0
  82. package/dist/tools/agent-tools.js +25 -0
  83. package/dist/tools/agent-tools.js.map +1 -0
  84. package/dist/tools/atomic.d.ts +19 -0
  85. package/dist/tools/atomic.d.ts.map +1 -1
  86. package/dist/tools/atomic.js +17 -0
  87. package/dist/tools/atomic.js.map +1 -1
  88. package/dist/tools/index.d.ts +2 -0
  89. package/dist/tools/index.d.ts.map +1 -1
  90. package/dist/tools/skill-executor.d.ts +7 -0
  91. package/dist/tools/skill-executor.d.ts.map +1 -1
  92. package/dist/tools/web-tools.d.ts +217 -0
  93. package/dist/tools/web-tools.d.ts.map +1 -0
  94. package/dist/tools/web-tools.js +31 -0
  95. package/dist/tools/web-tools.js.map +1 -0
  96. package/package.json +6 -2
  97. package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
  98. package/src/__tests__/operation-def.test.ts +2 -1
  99. package/src/__tests__/sealed-credential.test.ts +100 -0
  100. package/src/__tests__/skill-executor-contract.test.ts +3 -0
  101. package/src/acceptance-gate.ts +2 -3
  102. package/src/boundary.ts +1 -20
  103. package/src/config.ts +104 -0
  104. package/src/data-accessor.ts +22 -1
  105. package/src/dispatch/identity.ts +5 -0
  106. package/src/dispatch/operations-registry.ts +51 -170
  107. package/src/index.ts +103 -24
  108. package/src/lease-ipc/__tests__/freeze.test.ts +246 -0
  109. package/src/lease-ipc/index.ts +63 -0
  110. package/src/lease-ipc/messages.ts +471 -0
  111. package/src/lease-ipc/version.ts +46 -0
  112. package/src/llm/interfaces.ts +23 -0
  113. package/src/llm/sealed-credential.ts +166 -0
  114. package/src/llm/system-of-use.ts +503 -0
  115. package/src/llm/system-resolver.ts +46 -11
  116. package/src/operations/__tests__/ensures-schema-registry.test.ts +169 -0
  117. package/src/operations/ensures-schema-registry.ts +260 -0
  118. package/src/operations/llm.ts +105 -8
  119. package/src/operations/validate.ts +1 -14
  120. package/src/playbook.ts +61 -0
  121. package/src/session.ts +11 -0
  122. package/src/tools/agent-tools.ts +270 -0
  123. package/src/tools/atomic.ts +21 -0
  124. package/src/tools/index.ts +46 -0
  125. package/src/tools/skill-executor.ts +7 -0
  126. package/src/tools/web-tools.ts +247 -0
  127. package/dist/tessera.d.ts +0 -32
  128. package/dist/tessera.d.ts.map +0 -1
  129. package/dist/tessera.js +0 -11
  130. package/dist/tessera.js.map +0 -1
  131. package/dist/warp-chain.d.ts +0 -129
  132. package/dist/warp-chain.d.ts.map +0 -1
  133. package/dist/warp-chain.js +0 -13
  134. package/dist/warp-chain.js.map +0 -1
  135. package/src/tessera.ts +0 -35
  136. package/src/warp-chain.ts +0 -185
@@ -0,0 +1,471 @@
1
+ /**
2
+ * `lease-ipc` v1.1 — PARALLEL message contract (Zod schemas) for the
3
+ * DbWriterLease IPC surface (T11627 ST-1).
4
+ *
5
+ * This is the byte-for-byte TypeScript mirror of the Rust serde types in
6
+ * `crates/cleo-supervisor/src/lease_ipc.rs`. The wire format is newline-delimited
7
+ * JSON (NDJSON): one {@link LeaseIpcEnvelope} per line — identical framing to the
8
+ * frozen `supervisor-ipc` v1.0 envelope, only the version string
9
+ * ({@link LEASE_IPC_PROTOCOL_VERSION}) and the inner union differ.
10
+ *
11
+ * Wire-shape contract (snake_case keys — matches serde defaults):
12
+ *
13
+ * ```jsonc
14
+ * // request
15
+ * { "protocol_version": "1.1.0", "id": "abc", "direction": "request",
16
+ * "request": { "kind": "lease_acquire", "scope": "project", "lane": "tasks",
17
+ * "holder_id": "pid-42:tasks", "priority": 0, "ttl_ms": 30000,
18
+ * "reentrant": true } }
19
+ * // response
20
+ * { "protocol_version": "1.1.0", "id": "abc", "direction": "response",
21
+ * "response": { "kind": "lease_granted", "scope": "project", "lane": "tasks",
22
+ * "holder_id": "pid-42:tasks", "epoch": 7, "ttl_ms": 30000,
23
+ * "expires_at_ms": 1000030000 } }
24
+ * ```
25
+ *
26
+ * Staged delivery: every kind is *declared* so the protocol freeze is stable,
27
+ * but `rate_check` / `tool_grant` handlers are deferred (return
28
+ * `E_LEASE_UNIMPLEMENTED`) until a follow-up task. This module (ST-1) ships the
29
+ * protocol surface with **no consumer** — zero behavior change.
30
+ *
31
+ * @task T11627
32
+ * @packageDocumentation
33
+ */
34
+
35
+ import { z } from 'zod';
36
+
37
+ // ─── Shared value types ───────────────────────────────────────────────────────
38
+
39
+ /**
40
+ * The cleo.db scope a lease is arbitrated within. Mirrors `DbScope` in Rust.
41
+ *
42
+ * Under the dual-cleo.db split, a `project` lease lives inside the project's
43
+ * `cleo.db` and a `global` lease inside the global `cleo.db` — different files,
44
+ * so they never serialize against each other (AC2).
45
+ */
46
+ export const LeaseScopeSchema = z.enum(['project', 'global']);
47
+
48
+ /** The cleo.db scope a lease is arbitrated within (inferred). */
49
+ export type LeaseScope = z.infer<typeof LeaseScopeSchema>;
50
+
51
+ /**
52
+ * The write lane a lease arbitrates within a single scope file. Mirrors
53
+ * `LeaseLane` in Rust.
54
+ *
55
+ * - `tasks` — the primary task-chokepoint write lane.
56
+ * - `brain` — the BRAIN memory write lane (gated separately — AC4).
57
+ * - `bulk` — the bulk / bypass-writer lane (conduit, telemetry, nexus graph).
58
+ */
59
+ export const LeaseLaneSchema = z.enum(['tasks', 'brain', 'bulk']);
60
+
61
+ /** The write lane a lease arbitrates within a scope (inferred). */
62
+ export type LeaseLane = z.infer<typeof LeaseLaneSchema>;
63
+
64
+ // ─── Requests (client → arbiter) ──────────────────────────────────────────────
65
+
66
+ /**
67
+ * Acquire (or re-enter) the writer lease for a (scope, lane). Mirrors
68
+ * `LeaseAcquireReq`. `[v1 core]`
69
+ */
70
+ export const LeaseAcquireRequestSchema = z
71
+ .object({
72
+ /** Tag discriminating this request variant. */
73
+ kind: z.literal('lease_acquire'),
74
+ /** The cleo.db scope being arbitrated. */
75
+ scope: LeaseScopeSchema,
76
+ /** The write lane within the scope. */
77
+ lane: LeaseLaneSchema,
78
+ /** Process+lane holder identity. */
79
+ holder_id: z.string().min(1),
80
+ /** Advisory priority — lower acquires sooner. `0` = highest. */
81
+ priority: z.number().int().min(0).max(255),
82
+ /** Lease time-to-live in milliseconds. */
83
+ ttl_ms: z.number().int().nonnegative(),
84
+ /** When true, a same-holder acquire re-enters (refcount++) rather than queuing. */
85
+ reentrant: z.boolean(),
86
+ })
87
+ .strict();
88
+
89
+ /** Acquire request payload (inferred from {@link LeaseAcquireRequestSchema}). */
90
+ export type LeaseAcquireRequest = z.infer<typeof LeaseAcquireRequestSchema>;
91
+
92
+ /**
93
+ * Release the held writer lease. Mirrors `LeaseReleaseReq`. `[v1 core]`
94
+ */
95
+ export const LeaseReleaseRequestSchema = z
96
+ .object({
97
+ /** Tag discriminating this request variant. */
98
+ kind: z.literal('lease_release'),
99
+ /** The cleo.db scope being arbitrated. */
100
+ scope: LeaseScopeSchema,
101
+ /** The write lane within the scope. */
102
+ lane: LeaseLaneSchema,
103
+ /** Process+lane holder identity. */
104
+ holder_id: z.string().min(1),
105
+ /** The epoch fence the holder acquired — a stale epoch no-ops. */
106
+ epoch: z.number().int().nonnegative(),
107
+ })
108
+ .strict();
109
+
110
+ /** Release request payload (inferred from {@link LeaseReleaseRequestSchema}). */
111
+ export type LeaseReleaseRequest = z.infer<typeof LeaseReleaseRequestSchema>;
112
+
113
+ /**
114
+ * Heartbeat / renew the held lease's TTL. Mirrors `LeaseRenewReq`. `[v1 core]`
115
+ */
116
+ export const LeaseRenewRequestSchema = z
117
+ .object({
118
+ /** Tag discriminating this request variant. */
119
+ kind: z.literal('lease_renew'),
120
+ /** The cleo.db scope being arbitrated. */
121
+ scope: LeaseScopeSchema,
122
+ /** The write lane within the scope. */
123
+ lane: LeaseLaneSchema,
124
+ /** Process+lane holder identity. */
125
+ holder_id: z.string().min(1),
126
+ /** The epoch fence the holder acquired (epoch-guarded renew). */
127
+ epoch: z.number().int().nonnegative(),
128
+ })
129
+ .strict();
130
+
131
+ /** Renew request payload (inferred from {@link LeaseRenewRequestSchema}). */
132
+ export type LeaseRenewRequest = z.infer<typeof LeaseRenewRequestSchema>;
133
+
134
+ /**
135
+ * Check the per-scope write rate budget. Mirrors `RateCheckReq`.
136
+ * `[declared; handler deferred — returns E_LEASE_UNIMPLEMENTED]`
137
+ */
138
+ export const RateCheckRequestSchema = z
139
+ .object({
140
+ /** Tag discriminating this request variant. */
141
+ kind: z.literal('rate_check'),
142
+ /** The cleo.db scope being checked. */
143
+ scope: LeaseScopeSchema,
144
+ /** The write lane within the scope. */
145
+ lane: LeaseLaneSchema,
146
+ /** Estimated bytes the caller intends to write. */
147
+ est_bytes: z.number().int().nonnegative(),
148
+ })
149
+ .strict();
150
+
151
+ /** Rate-check request payload (inferred from {@link RateCheckRequestSchema}). */
152
+ export type RateCheckRequest = z.infer<typeof RateCheckRequestSchema>;
153
+
154
+ /**
155
+ * Request a tool-use grant. Mirrors `ToolGrantReq`.
156
+ * `[declared; handler deferred — returns E_LEASE_UNIMPLEMENTED]`
157
+ */
158
+ export const ToolGrantRequestSchema = z
159
+ .object({
160
+ /** Tag discriminating this request variant. */
161
+ kind: z.literal('tool_grant'),
162
+ /** The tool name being requested. */
163
+ tool: z.string().min(1),
164
+ /** The requesting holder identity. */
165
+ holder_id: z.string().min(1),
166
+ })
167
+ .strict();
168
+
169
+ /** Tool-grant request payload (inferred from {@link ToolGrantRequestSchema}). */
170
+ export type ToolGrantRequest = z.infer<typeof ToolGrantRequestSchema>;
171
+
172
+ /**
173
+ * The discriminated union of all client → arbiter lease requests. The `kind`
174
+ * field selects the variant, matching the serde `#[serde(tag = "kind")]`
175
+ * tagging on the Rust `LeaseRequest` enum.
176
+ */
177
+ export const LeaseIpcRequestSchema = z.discriminatedUnion('kind', [
178
+ LeaseAcquireRequestSchema,
179
+ LeaseReleaseRequestSchema,
180
+ LeaseRenewRequestSchema,
181
+ RateCheckRequestSchema,
182
+ ToolGrantRequestSchema,
183
+ ]);
184
+
185
+ /** Any lease IPC request (inferred from {@link LeaseIpcRequestSchema}). */
186
+ export type LeaseIpcRequest = z.infer<typeof LeaseIpcRequestSchema>;
187
+
188
+ // ─── Responses (arbiter → client) ─────────────────────────────────────────────
189
+
190
+ /**
191
+ * The lease was granted to the caller. Mirrors `LeaseGranted`.
192
+ */
193
+ export const LeaseGrantedResponseSchema = z
194
+ .object({
195
+ /** Tag discriminating this response variant. */
196
+ kind: z.literal('lease_granted'),
197
+ /** The granted cleo.db scope. */
198
+ scope: LeaseScopeSchema,
199
+ /** The granted write lane. */
200
+ lane: LeaseLaneSchema,
201
+ /** The holder the lease was granted to. */
202
+ holder_id: z.string().min(1),
203
+ /** The monotonic epoch fence assigned to this grant. */
204
+ epoch: z.number().int().nonnegative(),
205
+ /** The lease TTL in milliseconds. */
206
+ ttl_ms: z.number().int().nonnegative(),
207
+ /** Absolute expiry timestamp (epoch ms) for this grant. */
208
+ expires_at_ms: z.number().int().nonnegative(),
209
+ })
210
+ .strict();
211
+
212
+ /** Lease-granted response payload (inferred from {@link LeaseGrantedResponseSchema}). */
213
+ export type LeaseGrantedResponse = z.infer<typeof LeaseGrantedResponseSchema>;
214
+
215
+ /**
216
+ * The caller was placed in the per-scope FIFO+priority queue. Mirrors
217
+ * `LeaseQueued`.
218
+ */
219
+ export const LeaseQueuedResponseSchema = z
220
+ .object({
221
+ /** Tag discriminating this response variant. */
222
+ kind: z.literal('lease_queued'),
223
+ /** The queued cleo.db scope. */
224
+ scope: LeaseScopeSchema,
225
+ /** The queued write lane. */
226
+ lane: LeaseLaneSchema,
227
+ /** The monotonic ticket assigned for FIFO tiebreak. */
228
+ ticket: z.number().int().nonnegative(),
229
+ /** Number of waiters ahead of this one. */
230
+ ahead: z.number().int().nonnegative(),
231
+ })
232
+ .strict();
233
+
234
+ /** Lease-queued response payload (inferred from {@link LeaseQueuedResponseSchema}). */
235
+ export type LeaseQueuedResponse = z.infer<typeof LeaseQueuedResponseSchema>;
236
+
237
+ /**
238
+ * The acquire was denied. Mirrors `LeaseDenied`.
239
+ */
240
+ export const LeaseDeniedResponseSchema = z
241
+ .object({
242
+ /** Tag discriminating this response variant. */
243
+ kind: z.literal('lease_denied'),
244
+ /** The denied cleo.db scope. */
245
+ scope: LeaseScopeSchema,
246
+ /** Machine-readable denial code (e.g. `E_LEASE_UNAVAILABLE`). */
247
+ code: z.string().min(1),
248
+ /** Human-readable denial message. */
249
+ message: z.string(),
250
+ })
251
+ .strict();
252
+
253
+ /** Lease-denied response payload (inferred from {@link LeaseDeniedResponseSchema}). */
254
+ export type LeaseDeniedResponse = z.infer<typeof LeaseDeniedResponseSchema>;
255
+
256
+ /**
257
+ * Reply to a deferred `rate_check`. Mirrors `RateResult`.
258
+ */
259
+ export const RateResultResponseSchema = z
260
+ .object({
261
+ /** Tag discriminating this response variant. */
262
+ kind: z.literal('rate_result'),
263
+ /** The checked cleo.db scope. */
264
+ scope: LeaseScopeSchema,
265
+ /** Whether the write is within budget. */
266
+ ok: z.boolean(),
267
+ /** Suggested back-off in milliseconds when `ok` is false. */
268
+ retry_after_ms: z.number().int().nonnegative(),
269
+ /** Remaining token budget for the scope. */
270
+ tokens_remaining: z.number().int().nonnegative(),
271
+ })
272
+ .strict();
273
+
274
+ /** Rate-result response payload (inferred from {@link RateResultResponseSchema}). */
275
+ export type RateResultResponse = z.infer<typeof RateResultResponseSchema>;
276
+
277
+ /**
278
+ * Reply to a deferred `tool_grant`. Mirrors `ToolGranted`.
279
+ */
280
+ export const ToolGrantedResponseSchema = z
281
+ .object({
282
+ /** Tag discriminating this response variant. */
283
+ kind: z.literal('tool_granted'),
284
+ /** The granted tool name. */
285
+ tool: z.string().min(1),
286
+ /** The holder the tool grant was issued to. */
287
+ holder_id: z.string().min(1),
288
+ })
289
+ .strict();
290
+
291
+ /** Tool-granted response payload (inferred from {@link ToolGrantedResponseSchema}). */
292
+ export type ToolGrantedResponse = z.infer<typeof ToolGrantedResponseSchema>;
293
+
294
+ /**
295
+ * Unsolicited event: a held lease was revoked. Mirrors `LeaseRevoked`.
296
+ */
297
+ export const LeaseRevokedResponseSchema = z
298
+ .object({
299
+ /** Tag discriminating this response variant. */
300
+ kind: z.literal('lease_revoked'),
301
+ /** The revoked cleo.db scope. */
302
+ scope: LeaseScopeSchema,
303
+ /** The revoked write lane. */
304
+ lane: LeaseLaneSchema,
305
+ /** The holder whose lease was revoked. */
306
+ holder_id: z.string().min(1),
307
+ /** Human-readable reason for the revocation. */
308
+ reason: z.string(),
309
+ })
310
+ .strict();
311
+
312
+ /** Lease-revoked event payload (inferred from {@link LeaseRevokedResponseSchema}). */
313
+ export type LeaseRevokedResponse = z.infer<typeof LeaseRevokedResponseSchema>;
314
+
315
+ /**
316
+ * Unsolicited event: a lease holder was killed for being unresponsive. Mirrors
317
+ * `ChildKilled` carried by the `child_killed_unresponsive` response variant.
318
+ */
319
+ export const ChildKilledUnresponsiveResponseSchema = z
320
+ .object({
321
+ /** Tag discriminating this response variant. */
322
+ kind: z.literal('child_killed_unresponsive'),
323
+ /** Logical id of the killed child. */
324
+ child_id: z.string().min(1),
325
+ /** The holder identity the killed child held the lease as. */
326
+ holder_id: z.string().min(1),
327
+ /** The cleo.db scope the killed child held the lease in. */
328
+ scope: LeaseScopeSchema,
329
+ /** Human-readable reason for the kill. */
330
+ reason: z.string(),
331
+ })
332
+ .strict();
333
+
334
+ /** Child-killed event payload (inferred from {@link ChildKilledUnresponsiveResponseSchema}). */
335
+ export type ChildKilledUnresponsiveResponse = z.infer<typeof ChildKilledUnresponsiveResponseSchema>;
336
+
337
+ /**
338
+ * An error response correlated to a request. Mirrors the v1.0
339
+ * `crate::ipc::ErrorResult` shape reused by the Rust `LeaseResponse::Error`
340
+ * variant — error framing is shared across protocol versions.
341
+ */
342
+ export const LeaseErrorResponseSchema = z
343
+ .object({
344
+ /** Tag discriminating this response variant. */
345
+ kind: z.literal('error'),
346
+ /** Machine-readable error code (e.g. `E_LEASE_BAD_VERSION`, `E_LEASE_UNIMPLEMENTED`). */
347
+ code: z.string().min(1),
348
+ /** Human-readable error message. */
349
+ message: z.string(),
350
+ })
351
+ .strict();
352
+
353
+ /** Lease error response payload (inferred from {@link LeaseErrorResponseSchema}). */
354
+ export type LeaseErrorResponse = z.infer<typeof LeaseErrorResponseSchema>;
355
+
356
+ /**
357
+ * The discriminated union of all arbiter → client lease responses and events.
358
+ * The `kind` field selects the variant, matching the serde
359
+ * `#[serde(tag = "kind")]` tagging on the Rust `LeaseResponse` enum.
360
+ */
361
+ export const LeaseIpcResponseSchema = z.discriminatedUnion('kind', [
362
+ LeaseGrantedResponseSchema,
363
+ LeaseQueuedResponseSchema,
364
+ LeaseDeniedResponseSchema,
365
+ RateResultResponseSchema,
366
+ ToolGrantedResponseSchema,
367
+ LeaseRevokedResponseSchema,
368
+ ChildKilledUnresponsiveResponseSchema,
369
+ LeaseErrorResponseSchema,
370
+ ]);
371
+
372
+ /** Any lease IPC response (inferred from {@link LeaseIpcResponseSchema}). */
373
+ export type LeaseIpcResponse = z.infer<typeof LeaseIpcResponseSchema>;
374
+
375
+ // ─── Envelope ──────────────────────────────────────────────────────────────────
376
+
377
+ /**
378
+ * A client → arbiter lease request envelope.
379
+ *
380
+ * The `direction` discriminator + flattened `request` payload mirror the serde
381
+ * `#[serde(tag = "direction")]` `LeasePayload::Request { request }` variant.
382
+ */
383
+ export const LeaseIpcRequestEnvelopeSchema = z
384
+ .object({
385
+ /** Parallel protocol version. */
386
+ protocol_version: z.string(),
387
+ /** Correlation id echoed back on the matching response. */
388
+ id: z.string().min(1),
389
+ /** Direction discriminator. */
390
+ direction: z.literal('request'),
391
+ /** The request body. */
392
+ request: LeaseIpcRequestSchema,
393
+ })
394
+ .strict();
395
+
396
+ /** Lease request envelope (inferred from {@link LeaseIpcRequestEnvelopeSchema}). */
397
+ export type LeaseIpcRequestEnvelope = z.infer<typeof LeaseIpcRequestEnvelopeSchema>;
398
+
399
+ /**
400
+ * An arbiter → client lease response/event envelope.
401
+ *
402
+ * The `direction` discriminator + flattened `response` payload mirror the serde
403
+ * `LeasePayload::Response { response }` variant.
404
+ */
405
+ export const LeaseIpcResponseEnvelopeSchema = z
406
+ .object({
407
+ /** Parallel protocol version. */
408
+ protocol_version: z.string(),
409
+ /** Correlation id echoed from the originating request (or a fresh id for events). */
410
+ id: z.string().min(1),
411
+ /** Direction discriminator. */
412
+ direction: z.literal('response'),
413
+ /** The response body. */
414
+ response: LeaseIpcResponseSchema,
415
+ })
416
+ .strict();
417
+
418
+ /** Lease response envelope (inferred from {@link LeaseIpcResponseEnvelopeSchema}). */
419
+ export type LeaseIpcResponseEnvelope = z.infer<typeof LeaseIpcResponseEnvelopeSchema>;
420
+
421
+ /**
422
+ * The top-level lease IPC envelope: a versioned, correlated wrapper that is
423
+ * either a request or a response, discriminated by `direction`. One envelope per
424
+ * NDJSON line. Mirrors the Rust `LeaseEnvelope`.
425
+ */
426
+ export const LeaseIpcEnvelopeSchema = z.discriminatedUnion('direction', [
427
+ LeaseIpcRequestEnvelopeSchema,
428
+ LeaseIpcResponseEnvelopeSchema,
429
+ ]);
430
+
431
+ /** Any lease IPC envelope (inferred from {@link LeaseIpcEnvelopeSchema}). */
432
+ export type LeaseIpcEnvelope = z.infer<typeof LeaseIpcEnvelopeSchema>;
433
+
434
+ // ─── Frozen message-set guard ──────────────────────────────────────────────────
435
+
436
+ /**
437
+ * The v1.1 request `kind` values, in declaration order. The schema-drift guard
438
+ * test pins this tuple; any addition/removal is a contract-breaking change
439
+ * requiring a coordinated dual (Rust + TS) edit.
440
+ */
441
+ export const LEASE_IPC_REQUEST_KINDS = [
442
+ 'lease_acquire',
443
+ 'lease_release',
444
+ 'lease_renew',
445
+ 'rate_check',
446
+ 'tool_grant',
447
+ ] as const;
448
+
449
+ /**
450
+ * The v1.1 response `kind` values, in declaration order. The schema-drift guard
451
+ * test pins this tuple.
452
+ */
453
+ export const LEASE_IPC_RESPONSE_KINDS = [
454
+ 'lease_granted',
455
+ 'lease_queued',
456
+ 'lease_denied',
457
+ 'rate_result',
458
+ 'tool_granted',
459
+ 'lease_revoked',
460
+ 'child_killed_unresponsive',
461
+ 'error',
462
+ ] as const;
463
+
464
+ /**
465
+ * The complete v1.1 message kind set (requests + responses), used by the drift
466
+ * guard on both the TS and Rust sides.
467
+ */
468
+ export const LEASE_IPC_MESSAGE_KINDS = [
469
+ ...LEASE_IPC_REQUEST_KINDS,
470
+ ...LEASE_IPC_RESPONSE_KINDS,
471
+ ] as const;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * PARALLEL protocol version for the `lease-ipc` v1.1 contract (T11627 ST-1).
3
+ *
4
+ * The Rust arbiter (`crates/cleo-supervisor/src/lease_ipc.rs`) and this
5
+ * TypeScript contract MUST agree on this value. It runs **in parallel** to the
6
+ * byte-frozen `supervisor-ipc` v1.0 contract: the two are distinguished on the
7
+ * wire purely by this version string, so a single accept loop can route
8
+ * `'1.0.0'` → the v1.0 union and `'1.1.0'` → the lease union. Bump only via a
9
+ * coordinated dual (Rust + TS) edit, never edit this value in place.
10
+ *
11
+ * @see {@link LEASE_IPC_MESSAGE_KINDS} for the v1.1 message set.
12
+ * @task T11627
13
+ * @packageDocumentation
14
+ */
15
+
16
+ /**
17
+ * The `lease-ipc` v1.1 protocol version string.
18
+ *
19
+ * Mirrors `cleo_supervisor::lease_ipc::LEASE_IPC_PROTOCOL_VERSION` on the Rust
20
+ * side. Both the Rust schema-drift guard (`lease_ipc::tests`) and the TS drift
21
+ * test (`__tests__/freeze.test.ts`) pin this exact value.
22
+ */
23
+ export const LEASE_IPC_PROTOCOL_VERSION = '1.1.0' as const;
24
+
25
+ /**
26
+ * Whether the given version string is the frozen `lease-ipc` v1.1 wire version.
27
+ *
28
+ * Used by an accept-loop version router to confirm a frame is a lease-protocol
29
+ * frame before dispatching it through the {@link LEASE_IPC_PROTOCOL_VERSION}
30
+ * union (rather than the v1.0 supervisor-ipc union).
31
+ *
32
+ * @param version - The `protocol_version` field read off an inbound envelope.
33
+ * @returns `true` iff `version` equals {@link LEASE_IPC_PROTOCOL_VERSION}.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * if (isFrozenLeaseIpcVersion(env.protocol_version)) {
38
+ * // dispatch through LeaseIpcEnvelopeSchema
39
+ * }
40
+ * ```
41
+ */
42
+ export function isFrozenLeaseIpcVersion(
43
+ version: string,
44
+ ): version is typeof LEASE_IPC_PROTOCOL_VERSION {
45
+ return version === LEASE_IPC_PROTOCOL_VERSION;
46
+ }
@@ -173,6 +173,29 @@ export interface SendOptions {
173
173
  * Transports MUST ignore flags they do not recognise.
174
174
  */
175
175
  readonly providerFlags?: Readonly<Record<string, unknown>>;
176
+ /**
177
+ * Tools the model may call on this call (OpenAI-format {@link TransportTool}[]).
178
+ *
179
+ * When supplied, the session forwards them onto the {@link TransportRequest.tools}
180
+ * surface so the wire-level transport advertises them to the model. This is the
181
+ * per-call hook the in-process Pi embed threads its `Context.tools` through — the
182
+ * registry's `toOpenAITools()` output reaches the model via `streamFn` →
183
+ * `SendOptions.tools` → `TransportRequest.tools`. Omit (or pass empty) for a
184
+ * tool-free call. Transports that do not support tools MUST ignore it.
185
+ */
186
+ readonly tools?: readonly TransportTool[];
187
+ /**
188
+ * Cancellation signal for this call.
189
+ *
190
+ * When supplied, a streaming consumer MUST stop iterating and tear the
191
+ * underlying iterator down once the signal aborts — even when the wire-level
192
+ * transport does not itself observe the signal. This is the per-call hook the
193
+ * in-process Pi embed threads its loop-abort through so a detached stream
194
+ * producer cannot outlive the call that started it (T11898). Transports that
195
+ * do not consume it MUST ignore it (matching the {@link providerFlags}
196
+ * "ignore-unknown" contract).
197
+ */
198
+ readonly signal?: AbortSignal;
176
199
  }
177
200
 
178
201
  // ---------------------------------------------------------------------------