@cerebriline/llms 0.0.0-stage → 4.100.241

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 (204) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +15 -2
  3. package/dist/catalog/catalog-cline-recommended.d.ts +14 -0
  4. package/dist/catalog/catalog-cline-recommended.d.ts.map +1 -0
  5. package/dist/catalog/catalog-live.d.ts +64 -0
  6. package/dist/catalog/catalog-live.d.ts.map +1 -0
  7. package/dist/catalog/catalog.generated-access.d.ts +5 -0
  8. package/dist/catalog/catalog.generated-access.d.ts.map +1 -0
  9. package/dist/catalog/catalog.generated.d.ts +17 -0
  10. package/dist/catalog/catalog.generated.d.ts.map +1 -0
  11. package/dist/catalog/model-filters.d.ts +9 -0
  12. package/dist/catalog/model-filters.d.ts.map +1 -0
  13. package/dist/catalog/model-id-aliases.d.ts +11 -0
  14. package/dist/catalog/model-id-aliases.d.ts.map +1 -0
  15. package/dist/catalog/model-operation.d.ts +27 -0
  16. package/dist/catalog/model-operation.d.ts.map +1 -0
  17. package/dist/catalog/types.d.ts +367 -0
  18. package/dist/catalog/types.d.ts.map +1 -0
  19. package/dist/index.browser.d.ts +12 -0
  20. package/dist/index.browser.d.ts.map +1 -0
  21. package/dist/index.browser.js +16 -0
  22. package/dist/index.d.ts +30 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +272 -0
  25. package/dist/models.d.ts +10 -0
  26. package/dist/models.d.ts.map +1 -0
  27. package/dist/models.js +241 -0
  28. package/dist/providers/agent-slots.d.ts +100 -0
  29. package/dist/providers/agent-slots.d.ts.map +1 -0
  30. package/dist/providers/ai-sdk.d.ts +158 -0
  31. package/dist/providers/ai-sdk.d.ts.map +1 -0
  32. package/dist/providers/async.d.ts +2 -0
  33. package/dist/providers/async.d.ts.map +1 -0
  34. package/dist/providers/billing.d.ts +5 -0
  35. package/dist/providers/billing.d.ts.map +1 -0
  36. package/dist/providers/builtin-types.d.ts +34 -0
  37. package/dist/providers/builtin-types.d.ts.map +1 -0
  38. package/dist/providers/builtins-runtime.d.ts +3 -0
  39. package/dist/providers/builtins-runtime.d.ts.map +1 -0
  40. package/dist/providers/builtins.d.ts +30 -0
  41. package/dist/providers/builtins.d.ts.map +1 -0
  42. package/dist/providers/compat.d.ts +75 -0
  43. package/dist/providers/compat.d.ts.map +1 -0
  44. package/dist/providers/config.d.ts +521 -0
  45. package/dist/providers/config.d.ts.map +1 -0
  46. package/dist/providers/error-classification.d.ts +23 -0
  47. package/dist/providers/error-classification.d.ts.map +1 -0
  48. package/dist/providers/errors.d.ts +33 -0
  49. package/dist/providers/errors.d.ts.map +1 -0
  50. package/dist/providers/factory-registry.d.ts +92 -0
  51. package/dist/providers/factory-registry.d.ts.map +1 -0
  52. package/dist/providers/format.d.ts +2 -0
  53. package/dist/providers/format.d.ts.map +1 -0
  54. package/dist/providers/gateway.d.ts +123 -0
  55. package/dist/providers/gateway.d.ts.map +1 -0
  56. package/dist/providers/handler.d.ts +75 -0
  57. package/dist/providers/handler.d.ts.map +1 -0
  58. package/dist/providers/http.d.ts +10 -0
  59. package/dist/providers/http.d.ts.map +1 -0
  60. package/dist/providers/ids.d.ts +77 -0
  61. package/dist/providers/ids.d.ts.map +1 -0
  62. package/dist/providers/messages.d.ts +5 -0
  63. package/dist/providers/messages.d.ts.map +1 -0
  64. package/dist/providers/middleware/backoff.d.ts +11 -0
  65. package/dist/providers/middleware/backoff.d.ts.map +1 -0
  66. package/dist/providers/middleware/retry-empty-response.d.ts +74 -0
  67. package/dist/providers/middleware/retry-empty-response.d.ts.map +1 -0
  68. package/dist/providers/middleware/retry-rate-limit.d.ts +49 -0
  69. package/dist/providers/middleware/retry-rate-limit.d.ts.map +1 -0
  70. package/dist/providers/middleware/split-tool-images.d.ts +32 -0
  71. package/dist/providers/middleware/split-tool-images.d.ts.map +1 -0
  72. package/dist/providers/middleware/stream-part-classification.d.ts +33 -0
  73. package/dist/providers/middleware/stream-part-classification.d.ts.map +1 -0
  74. package/dist/providers/model-capabilities.d.ts +15 -0
  75. package/dist/providers/model-capabilities.d.ts.map +1 -0
  76. package/dist/providers/model-facts.d.ts +115 -0
  77. package/dist/providers/model-facts.d.ts.map +1 -0
  78. package/dist/providers/model-operations.d.ts +78 -0
  79. package/dist/providers/model-operations.d.ts.map +1 -0
  80. package/dist/providers/model-registry.d.ts +25 -0
  81. package/dist/providers/model-registry.d.ts.map +1 -0
  82. package/dist/providers/model-tools.d.ts +22 -0
  83. package/dist/providers/model-tools.d.ts.map +1 -0
  84. package/dist/providers/openai-codex-models.d.ts +11 -0
  85. package/dist/providers/openai-codex-models.d.ts.map +1 -0
  86. package/dist/providers/provider-ids.generated.d.ts +13 -0
  87. package/dist/providers/provider-ids.generated.d.ts.map +1 -0
  88. package/dist/providers/provider-keys.d.ts +13 -0
  89. package/dist/providers/provider-keys.d.ts.map +1 -0
  90. package/dist/providers/provider-request-capture.d.ts +10 -0
  91. package/dist/providers/provider-request-capture.d.ts.map +1 -0
  92. package/dist/providers/providers.generated.d.ts +19 -0
  93. package/dist/providers/providers.generated.d.ts.map +1 -0
  94. package/dist/providers/reasoning-history.d.ts +140 -0
  95. package/dist/providers/reasoning-history.d.ts.map +1 -0
  96. package/dist/providers/registry.d.ts +19 -0
  97. package/dist/providers/registry.d.ts.map +1 -0
  98. package/dist/providers/request-headers.d.ts +30 -0
  99. package/dist/providers/request-headers.d.ts.map +1 -0
  100. package/dist/providers/request-timings.d.ts +20 -0
  101. package/dist/providers/request-timings.d.ts.map +1 -0
  102. package/dist/providers/routing/anthropic-compatible.d.ts +35 -0
  103. package/dist/providers/routing/anthropic-compatible.d.ts.map +1 -0
  104. package/dist/providers/routing/bedrock-cache-point.d.ts +26 -0
  105. package/dist/providers/routing/bedrock-cache-point.d.ts.map +1 -0
  106. package/dist/providers/routing/generic-compatible.d.ts +10 -0
  107. package/dist/providers/routing/generic-compatible.d.ts.map +1 -0
  108. package/dist/providers/routing/glm-thinking.d.ts +16 -0
  109. package/dist/providers/routing/glm-thinking.d.ts.map +1 -0
  110. package/dist/providers/routing/minimax-thinking.d.ts +6 -0
  111. package/dist/providers/routing/minimax-thinking.d.ts.map +1 -0
  112. package/dist/providers/routing/portable-reasoning.d.ts +11 -0
  113. package/dist/providers/routing/portable-reasoning.d.ts.map +1 -0
  114. package/dist/providers/routing/provider-option-rules.d.ts +13 -0
  115. package/dist/providers/routing/provider-option-rules.d.ts.map +1 -0
  116. package/dist/providers/routing/provider-options-types.d.ts +57 -0
  117. package/dist/providers/routing/provider-options-types.d.ts.map +1 -0
  118. package/dist/providers/routing/provider-options.d.ts +27 -0
  119. package/dist/providers/routing/provider-options.d.ts.map +1 -0
  120. package/dist/providers/routing/reasoning-codecs.d.ts +4 -0
  121. package/dist/providers/routing/reasoning-codecs.d.ts.map +1 -0
  122. package/dist/providers/routing/reasoning-options.d.ts +8 -0
  123. package/dist/providers/routing/reasoning-options.d.ts.map +1 -0
  124. package/dist/providers/routing/utils.d.ts +31 -0
  125. package/dist/providers/routing/utils.d.ts.map +1 -0
  126. package/dist/providers/sdk-warnings.d.ts +14 -0
  127. package/dist/providers/sdk-warnings.d.ts.map +1 -0
  128. package/dist/providers/server-health.d.ts +66 -0
  129. package/dist/providers/server-health.d.ts.map +1 -0
  130. package/dist/providers/stream.d.ts +124 -0
  131. package/dist/providers/stream.d.ts.map +1 -0
  132. package/dist/providers/types.d.ts +10 -0
  133. package/dist/providers/types.d.ts.map +1 -0
  134. package/dist/providers/url.d.ts +3 -0
  135. package/dist/providers/url.d.ts.map +1 -0
  136. package/dist/providers/utils.d.ts +2 -0
  137. package/dist/providers/utils.d.ts.map +1 -0
  138. package/dist/providers/vendors/anthropic.d.ts +4 -0
  139. package/dist/providers/vendors/anthropic.d.ts.map +1 -0
  140. package/dist/providers/vendors/bedrock.d.ts +24 -0
  141. package/dist/providers/vendors/bedrock.d.ts.map +1 -0
  142. package/dist/providers/vendors/cline.d.ts +37 -0
  143. package/dist/providers/vendors/cline.d.ts.map +1 -0
  144. package/dist/providers/vendors/community.d.ts +8 -0
  145. package/dist/providers/vendors/community.d.ts.map +1 -0
  146. package/dist/providers/vendors/google.d.ts +12 -0
  147. package/dist/providers/vendors/google.d.ts.map +1 -0
  148. package/dist/providers/vendors/llamacpp-sampling.d.ts +130 -0
  149. package/dist/providers/vendors/llamacpp-sampling.d.ts.map +1 -0
  150. package/dist/providers/vendors/llamacpp-timings.d.ts +33 -0
  151. package/dist/providers/vendors/llamacpp-timings.d.ts.map +1 -0
  152. package/dist/providers/vendors/minimax-thinking.d.ts +5 -0
  153. package/dist/providers/vendors/minimax-thinking.d.ts.map +1 -0
  154. package/dist/providers/vendors/mistral.d.ts +4 -0
  155. package/dist/providers/vendors/mistral.d.ts.map +1 -0
  156. package/dist/providers/vendors/ollama-account.d.ts +128 -0
  157. package/dist/providers/vendors/ollama-account.d.ts.map +1 -0
  158. package/dist/providers/vendors/ollama-reachability.d.ts +42 -0
  159. package/dist/providers/vendors/ollama-reachability.d.ts.map +1 -0
  160. package/dist/providers/vendors/ollama-stall-watchdog.d.ts +86 -0
  161. package/dist/providers/vendors/ollama-stall-watchdog.d.ts.map +1 -0
  162. package/dist/providers/vendors/ollama-tool-images.d.ts +67 -0
  163. package/dist/providers/vendors/ollama-tool-images.d.ts.map +1 -0
  164. package/dist/providers/vendors/ollama.d.ts +256 -0
  165. package/dist/providers/vendors/ollama.d.ts.map +1 -0
  166. package/dist/providers/vendors/openai-compatible.d.ts +16 -0
  167. package/dist/providers/vendors/openai-compatible.d.ts.map +1 -0
  168. package/dist/providers/vendors/openai.d.ts +4 -0
  169. package/dist/providers/vendors/openai.d.ts.map +1 -0
  170. package/dist/providers/vendors/opencoti-agent-window.d.ts +44 -0
  171. package/dist/providers/vendors/opencoti-agent-window.d.ts.map +1 -0
  172. package/dist/providers/vendors/opencoti-kv-pressure.d.ts +322 -0
  173. package/dist/providers/vendors/opencoti-kv-pressure.d.ts.map +1 -0
  174. package/dist/providers/vendors/opencoti-liveness.d.ts +177 -0
  175. package/dist/providers/vendors/opencoti-liveness.d.ts.map +1 -0
  176. package/dist/providers/vendors/opencoti-window.d.ts +56 -0
  177. package/dist/providers/vendors/opencoti-window.d.ts.map +1 -0
  178. package/dist/providers/vendors/opencoti.d.ts +335 -0
  179. package/dist/providers/vendors/opencoti.d.ts.map +1 -0
  180. package/dist/providers/vendors/polykv-lead.d.ts +94 -0
  181. package/dist/providers/vendors/polykv-lead.d.ts.map +1 -0
  182. package/dist/providers/vendors/polykv-swarm.d.ts +705 -0
  183. package/dist/providers/vendors/polykv-swarm.d.ts.map +1 -0
  184. package/dist/providers/vendors/polykv.d.ts +958 -0
  185. package/dist/providers/vendors/polykv.d.ts.map +1 -0
  186. package/dist/providers/vendors/types.d.ts +176 -0
  187. package/dist/providers/vendors/types.d.ts.map +1 -0
  188. package/dist/providers/vendors/vertex.d.ts +4 -0
  189. package/dist/providers/vendors/vertex.d.ts.map +1 -0
  190. package/dist/providers/vendors/xollama-engine.d.ts +57 -0
  191. package/dist/providers/vendors/xollama-engine.d.ts.map +1 -0
  192. package/dist/providers/vendors/xollama.d.ts +188 -0
  193. package/dist/providers/vendors/xollama.d.ts.map +1 -0
  194. package/dist/providers.browser.d.ts +3 -0
  195. package/dist/providers.browser.d.ts.map +1 -0
  196. package/dist/providers.browser.js +16 -0
  197. package/dist/providers.d.ts +12 -0
  198. package/dist/providers.d.ts.map +1 -0
  199. package/dist/providers.js +272 -0
  200. package/dist/services/langfuse-telemetry.d.ts +19 -0
  201. package/dist/services/langfuse-telemetry.d.ts.map +1 -0
  202. package/dist/transcription.d.ts +53 -0
  203. package/dist/transcription.d.ts.map +1 -0
  204. package/package.json +84 -5
@@ -0,0 +1,958 @@
1
+ /**
2
+ * Client for opencoti-llamafile's PolyKV control plane.
3
+ *
4
+ * PolyKV is a tree of KV pools. A pool owns a token range `[D, L)` and shares
5
+ * everything before `D` with its parent, so the system prompt and tool
6
+ * definitions -- the part of an agent's context that never changes -- can be
7
+ * prefilled once, pinned, and attached by every later request instead of being
8
+ * re-sent and re-computed each turn.
9
+ *
10
+ * That is the whole reason this exists here. Measured on the Ollama path this
11
+ * session: 12,859 tokens of system prompt and tool schemas on every request,
12
+ * and a turn whose prefill ran past five minutes and killed the run. Under
13
+ * PolyKV that prefix is a pinned ancestor pool and the per-turn prefill is the
14
+ * suffix only.
15
+ *
16
+ * Two rules from the engine's own design (`docs/features/polykv_api.md`) are
17
+ * load-bearing for any caller:
18
+ *
19
+ * - **Compaction is a prompt rewrite, never an in-place KV op** (§13.2).
20
+ * Compacted text is new text; its tokens cannot match the old cells. The
21
+ * correct primitive is `fork(ancestor, D = D_sys, summary + recent tail)`,
22
+ * after which sessions migrate and the old subtree is released. Net cells go
23
+ * down rather than up.
24
+ * - **A pin left on an abandoned subtree is a leak** (§13.2). Discipline is
25
+ * unpin-after-migrate; the server reports orphans so they can be swept.
26
+ */
27
+ /** A pool's identity and how much of the prefix it carries. */
28
+ export interface PolykvPool {
29
+ pool_id: string;
30
+ parent?: string;
31
+ branch_pos?: number;
32
+ prefix_len: number;
33
+ /** A `shared: true` create found an existing root instead of making one. */
34
+ reused?: boolean;
35
+ /** Said, not refused: e.g. an owner that holds no live allocation. */
36
+ warning?: string;
37
+ /**
38
+ * The session whose window the pool lives in; `""` when it is unowned
39
+ * (charged server-wide). Absent on an engine that does not say.
40
+ */
41
+ owner?: string;
42
+ }
43
+ /** What `POST /sessions/{id}/close` did, in the engine's words. */
44
+ export interface PolykvCloseReport {
45
+ /** The session held a booking, now released (or deferred to its drain). */
46
+ found: boolean;
47
+ /** The session's idle slot KV was dropped (`kv-drop-on-close`). */
48
+ kvDropped: boolean;
49
+ }
50
+ /**
51
+ * What `GET /polykv/pools/{id}/capacity` answers.
52
+ *
53
+ * Transcribed from the engine's own response builder
54
+ * (`server-context.cpp:7047-7125`), not from the design document -- the two
55
+ * disagree, and the builder is the one that runs.
56
+ *
57
+ * **This is not a pollable endpoint on c7.** Every GET folds the settle and
58
+ * bias EWMAs the admission gate learns from, so a dashboard that polls it
59
+ * perturbs the thing it is reporting on. Call it once per admission decision
60
+ * and read live state from `/polykv/pools`, `/props` and `/polykv/tps`, which
61
+ * are served from a published snapshot and are safe to poll while the server
62
+ * is busy. c8 makes the fold explicit and the plain GET read-only.
63
+ *
64
+ * Several fields are deliberately `null` rather than `0` when the number would
65
+ * be a lie -- `vram_free_mib` with no GPU layers, every `swa_*` on a model
66
+ * without a sliding window. Absent must not be read as zero.
67
+ */
68
+ export interface PolykvCapacity {
69
+ pool_id?: string;
70
+ can_admit: boolean;
71
+ /**
72
+ * Why, in the engine's own words. Worth surfacing verbatim: the elastic
73
+ * refusal is kept distinct from `kv headroom exhausted` on purpose, because
74
+ * "raise --max-parallel" and "this context does not fit" need different
75
+ * answers and a merged string cannot carry which one it is.
76
+ */
77
+ reason?: string;
78
+ /** Whether this read folded the admission learner. c8 and later only. */
79
+ folded?: boolean;
80
+ /**
81
+ * Which window the `kv_*` and `headroom_*` figures above describe.
82
+ *
83
+ * **The field that stops this endpoint being misread.** Under guarantees a
84
+ * pool owned by a session reports them against the OWNER'S window rather
85
+ * than against the server, so a caller that takes them off the first pool it
86
+ * finds and calls the result "KV headroom" is stating one session's private
87
+ * occupancy as the machine's free capacity -- wrong in the most misleading
88
+ * direction there is, since a full server with one idle session then reads
89
+ * as nearly empty.
90
+ *
91
+ * `session` is that case. `unallocated` is an unowned pool, whose free cells
92
+ * are what admission can still grant and so genuinely are the server's.
93
+ * `cache` is a server without guarantees, where the distinction does not
94
+ * exist. Absent is a build from before the split, which has no per-session
95
+ * windows to confuse these with.
96
+ */
97
+ pressure_scope?: "session" | "unallocated" | "cache";
98
+ /** The session owning this pool, when one does. */
99
+ owner?: string | null;
100
+ /** Raw `used/window`, 0..1. Never a ramp. */
101
+ pressure?: number;
102
+ /** The denominator `pressure` is taken against. */
103
+ window_cells?: number;
104
+ headroom_sessions?: number;
105
+ kv_headroom_pct?: number;
106
+ kv_cells_free?: number;
107
+ kv_cells_total?: number;
108
+ marginal_tokens_mean?: number;
109
+ expected_tokens?: number;
110
+ mean_active_tps?: number;
111
+ n_active_sessions?: number;
112
+ projected_mean_tps_if_admitted?: number;
113
+ projected_mean_tps_model?: number;
114
+ projected_mean_tps_measured?: number;
115
+ projection_bias_ewma?: number;
116
+ drop_per_admit_ewma?: number;
117
+ /** The projection came from the last settled mean, not from live decode. */
118
+ projected_idle_estimate?: boolean;
119
+ settling?: boolean;
120
+ settle_remaining_ms?: number;
121
+ n_warming?: number;
122
+ n_pool_sessions?: number;
123
+ guaranteed?: boolean;
124
+ /** A continuation of a session the engine already knows, never a new admit. */
125
+ known_session?: boolean;
126
+ n_prefilling?: number;
127
+ prefill_backlog_tokens?: number;
128
+ n_soon_sessions?: number;
129
+ slots_live?: number;
130
+ slots_max?: number;
131
+ slots_free?: number;
132
+ vram_free_mib?: number | null;
133
+ elastic_reason?: string;
134
+ swa_active?: boolean;
135
+ swa_cells_total?: number | null;
136
+ swa_cells_free?: number | null;
137
+ swa_cells_needed?: number | null;
138
+ swa_seq_budget?: number | null;
139
+ swa_window?: number | null;
140
+ swa_capacity_sessions?: number | null;
141
+ kv_streams_total?: number | null;
142
+ kv_streams_free?: number | null;
143
+ kv_cells_per_stream?: number | null;
144
+ /**
145
+ * How close the pool is to exhausting context, measured by the engine.
146
+ *
147
+ * The reason to care: every compaction trigger on the Ollama path is an
148
+ * estimate, and the estimates were wrong in both directions on a single
149
+ * session -- a chars-per-token ratio swinging 3.16 to 5.42, an overhead
150
+ * term reading 53,323 tokens for a 12,700-token payload. This number is
151
+ * measured by the thing that owns the cells.
152
+ *
153
+ * **Superseded by `pressure` where the server offers it.** This one is a
154
+ * 0.70..1.0 ramp over the same denominator, kept for compatibility; a
155
+ * pre-scaled figure stops matching the threshold the user set, which is the
156
+ * number they are looking at. Take the raw ratio and own the policy here.
157
+ */
158
+ compaction_pressure?: number;
159
+ /** The policy in force, echoed back. */
160
+ admission?: {
161
+ set?: boolean;
162
+ target_tps_per_session?: number;
163
+ mode?: "advisory" | "enforced";
164
+ on_saturation?: "reject" | "warn";
165
+ guarantee_min_sessions?: number;
166
+ settle_tokens?: number;
167
+ settle_max_ms?: number;
168
+ prefill_max_slots?: number;
169
+ };
170
+ }
171
+ /** The body of `POST /polykv/pools/{id}/admission`, as the engine reads it. */
172
+ export interface PolykvAdmissionPolicy {
173
+ target_tps_per_session?: number;
174
+ mode?: "advisory" | "enforced";
175
+ on_saturation?: "reject" | "warn";
176
+ guarantee_min_sessions?: number;
177
+ settle_tokens?: number;
178
+ settle_max_ms?: number;
179
+ prefill_max_slots?: number;
180
+ }
181
+ /**
182
+ * The admission policy a profile's PolyKV section asks for, or nothing.
183
+ *
184
+ * A floor with no mode is sent as `enforced`. The engine's own default is
185
+ * `advisory`, which reports and refuses nothing, and the section's floor field
186
+ * promises the opposite: "a new session that would push the projected mean
187
+ * below this is refused rather than admitted". Before this was sent at all,
188
+ * a 15 tok/s floor on both of a user's nodes let 60 agents run at 5 tok/s --
189
+ * the server's own boot floor -- because no pool ever carried the policy.
190
+ */
191
+ export declare function polykvAdmissionPolicy(settings: {
192
+ targetTpsPerSession?: number;
193
+ mode?: "advisory" | "enforced";
194
+ onSaturation?: "reject" | "warn";
195
+ guaranteeMinSessions?: number;
196
+ settleTokens?: number;
197
+ settleMaxMs?: number;
198
+ prefillMaxSlots?: number;
199
+ } | undefined): PolykvAdmissionPolicy | undefined;
200
+ export interface PolykvClientOptions {
201
+ /** Server root, with or without a trailing `/v1`. */
202
+ baseUrl: string;
203
+ /**
204
+ * The fetch to use. Supply the one that honours an undici dispatcher when
205
+ * there is one: pool creation prefills, and prefill is exactly the thing
206
+ * that outlives undici's default five-minute header timeout.
207
+ */
208
+ fetch?: typeof fetch;
209
+ headers?: Record<string, string>;
210
+ signal?: AbortSignal;
211
+ }
212
+ /**
213
+ * Raised when the engine refuses a new session for want of capacity.
214
+ *
215
+ * Carries `retryAfterMs` because the server says how long to wait (RFC 9110)
216
+ * and a caller that ignores it is the reason saturation looks like a network
217
+ * fault.
218
+ */
219
+ export declare class PolykvSaturatedError extends Error {
220
+ readonly retryAfterMs: number | undefined;
221
+ readonly reason?: string | undefined;
222
+ /**
223
+ * The HTTP status line, which is the half that is right on both
224
+ * releases. c7 answers a `429` with a body that says
225
+ * `503`/`unavailable_error`, so a client that classified on the body
226
+ * would call every c7 refusal a failed capacity check.
227
+ */
228
+ readonly status: number;
229
+ constructor(message: string, retryAfterMs: number | undefined, reason?: string | undefined,
230
+ /**
231
+ * The HTTP status line, which is the half that is right on both
232
+ * releases. c7 answers a `429` with a body that says
233
+ * `503`/`unavailable_error`, so a client that classified on the body
234
+ * would call every c7 refusal a failed capacity check.
235
+ */
236
+ status?: number);
237
+ /**
238
+ * `--polykv-adm-on-error deny` refusing because the check itself failed.
239
+ *
240
+ * Distinct from pacing on purpose. A `429` means the server knows it is
241
+ * full and has said when to come back, so waiting works. A `503` means the
242
+ * server does not know whether it has room and would rather refuse than
243
+ * guess -- nothing about waiting fixes that, and retrying it on a timer
244
+ * turns one failed check into a loop.
245
+ */
246
+ get capacityCheckFailed(): boolean;
247
+ }
248
+ /** Strip a trailing `/v1` (and any trailing slash): the control plane sits at the root. */
249
+ export declare function polykvRoot(baseUrl: string): string;
250
+ /**
251
+ * How a pool's prefix is supplied. Exactly one of these, never two.
252
+ *
253
+ * `prompt` and `from_session` are the two that work. `tokens` is kept because
254
+ * the engine still accepts it, but it puts the caller in charge of reproducing
255
+ * the server's tokenization -- BOS, special tokens, and the chat template --
256
+ * and getting any of that wrong yields a pool that shares nothing while
257
+ * reporting success. `prompt` hands that job back to the server, and
258
+ * `from_session` removes the question entirely by never putting tokens on the
259
+ * wire.
260
+ */
261
+ export interface PolykvPoolOwner {
262
+ /**
263
+ * The session whose window this pool lives in.
264
+ *
265
+ * **What makes a worker free.** A request that attaches to a pool owned by
266
+ * a session is priced as a worker OF that session: it books nothing
267
+ * server-wide and is charged against the owner's free window. An unowned
268
+ * pool is charged to nobody, and every worker attaching to it books a
269
+ * guaranteed window of its own -- measured live on 8240, a 12-worker swarm
270
+ * under a 65,536-token lead took THIRTEEN allocations of 65,536, 82% of the
271
+ * server's cells, for a round that should have cost one.
272
+ *
273
+ * The server defaults it to `from_session`, or to the parent's owner on a
274
+ * fork; it is sent explicitly because the pools that matter most here --
275
+ * the root pool, built from a templated prompt -- have neither.
276
+ */
277
+ session_id?: string;
278
+ }
279
+ export interface PolykvPrefixSource {
280
+ /** Pre-tokenized ids. The caller owns the tokenization. Prefer the others. */
281
+ tokens?: number[];
282
+ /** Text the server tokenizes itself, the way it tokenizes a completion. */
283
+ prompt?: string;
284
+ /** Snapshot a live session's own token history, zero-copy. */
285
+ from_session?: string;
286
+ /** Snapshot a slot by index. `from_session` is the one a client should use. */
287
+ from_slot?: number;
288
+ }
289
+ export interface PolykvClient {
290
+ /**
291
+ * Create a root pool.
292
+ *
293
+ * `ephemeral` defaults to `true` for `from_session`/`from_slot` pools and
294
+ * `false` for `tokens`/`prompt` ones -- a server-side default worth knowing,
295
+ * because an ephemeral pool is swept once it has been attached, is an
296
+ * unpinned leaf, and goes 60s without a processing attach. Pin anything that
297
+ * has to outlive an idle gap.
298
+ */
299
+ createPool(body: PolykvPrefixSource & PolykvPoolOwner & {
300
+ pin?: boolean;
301
+ ephemeral?: boolean;
302
+ /** Declared expected prefix length, validated server-side. */
303
+ expect_len?: number;
304
+ /**
305
+ * Find-or-create (`polykv_shared_root_v1`): an unowned root with
306
+ * exactly these tokens and the same `ephemeral` is returned with
307
+ * `reused: true`. A 400 with an owner or a snapshot source.
308
+ */
309
+ shared?: boolean;
310
+ }): Promise<PolykvPool>;
311
+ /**
312
+ * Branch a pool at `branch_pos`.
313
+ *
314
+ * `branch_pos === parent.prefix_len` extends it; anything less is a
315
+ * copy-on-write branch, and it defaults to the parent's length.
316
+ *
317
+ * **The prefix given here is the child's FULL path `[0, L)`, never the
318
+ * suffix being added.** The engine validates it token-exact against the
319
+ * parent over `[0, branch_pos)` with `std::equal` and answers `400` on a
320
+ * mismatch -- so a caller that sends only the new tail has its every fork
321
+ * rejected, which looks from here like the feature being unavailable.
322
+ */
323
+ forkPool(poolId: string, body: PolykvPrefixSource & PolykvPoolOwner & {
324
+ branch_pos?: number;
325
+ pin?: boolean;
326
+ ephemeral?: boolean;
327
+ }): Promise<PolykvPool>;
328
+ /**
329
+ * Give a session's guaranteed window back, before its idle TTL does.
330
+ *
331
+ * Called on conversation end, always. Skipping it holds the whole booked
332
+ * allocation for the TTL -- five minutes on the build this was written
333
+ * against -- so a user who ends one 256k conversation and opens another
334
+ * waits out their own last session. The TTL is the crash net, not the
335
+ * mechanism.
336
+ *
337
+ * Answers whether anything was actually released. The server replies
338
+ * `200 {"found": false}` for a session it never held, so the status line
339
+ * says only that the request arrived; `found` says whether it did anything.
340
+ * A `false` for a session we believed we held means our id and the
341
+ * server's have diverged, which is worth knowing and not worth guessing at.
342
+ */
343
+ closeSession(sessionId: string): Promise<boolean>;
344
+ /**
345
+ * {@link closeSession}, with what the engine dropped. A session with slot
346
+ * affinity and no booking -- a pooled worker, a compaction critic -- answers
347
+ * `found: false, kv_dropped: true`: nothing was booked, and its resident
348
+ * cells are gone all the same.
349
+ *
350
+ * A close also ends the session's standing as a running one: the engine's
351
+ * admission gate lets a running session's next turn through as a
352
+ * continuation (bug-3670), and a closed session's next turn is gated as a
353
+ * new arrival. `keepRunning` is for a close whose session goes on -- a
354
+ * compaction giving back the booking its writer took -- and asks the
355
+ * engine to keep that standing. An engine without it ignores the field.
356
+ */
357
+ closeSessionReport(sessionId: string, options?: {
358
+ keepRunning?: boolean;
359
+ }): Promise<PolykvCloseReport>;
360
+ /**
361
+ * Drop the resident KV of the slot a session last ran in, keeping its
362
+ * booking (`POST /slots/{id}?action=erase`). `undefined` when no slot names
363
+ * the session; the number the engine says it erased otherwise.
364
+ */
365
+ eraseSessionSlot(sessionId: string): Promise<number | undefined>;
366
+ /**
367
+ * The ids of the pools the server holds now.
368
+ *
369
+ * How a client learns a pool it named is gone: the engine releases every
370
+ * pool a session owns when that session's window lapses, and a request
371
+ * naming a released pool is not refused -- it is a server-side warning and
372
+ * a full reprocess, invisible from here.
373
+ */
374
+ listPoolIds(): Promise<Set<string>>;
375
+ pin(poolId: string): Promise<void>;
376
+ unpin(poolId: string): Promise<void>;
377
+ /** Set a pool's admission policy (`POST /polykv/pools/{id}/admission`). */
378
+ setAdmission(poolId: string, policy: PolykvAdmissionPolicy): Promise<void>;
379
+ releasePool(poolId: string): Promise<void>;
380
+ /**
381
+ * Ask what the gate would say, optionally folding the learner.
382
+ *
383
+ * `fold` is the c8 half of a c7 hazard. On c7 every GET folds the settle
384
+ * and bias EWMAs whether you wanted it to or not, which is why the status
385
+ * panel may not poll this endpoint there. `capacity_readonly_v1` makes the
386
+ * plain GET read-only and moves the fold behind `?fold=1`, so an admission
387
+ * decision asks for it and a panel read does not.
388
+ *
389
+ * Asking for it on a c7 server is harmless: it folds either way, and the
390
+ * unknown query parameter is ignored. `folded` echoing back is how a caller
391
+ * learns which of the two it is talking to.
392
+ */
393
+ capacity(poolId: string, query?: {
394
+ expected_tokens?: number;
395
+ fold?: boolean;
396
+ }): Promise<PolykvCapacity>;
397
+ tokenize(content: string): Promise<number[]>;
398
+ /**
399
+ * Render messages through the server's own chat template.
400
+ *
401
+ * The engine prefills the *templated* token stream, so a prefix assembled
402
+ * here from the raw system prompt and a JSON dump of the tool schemas is a
403
+ * different sequence and matches nothing -- the pool reports success and
404
+ * shares zero tokens. Only the server knows which template it loaded
405
+ * (`/props.chat_template`) and how it renders tools, so it renders the
406
+ * prefix and we pin what comes back.
407
+ */
408
+ applyTemplate(body: {
409
+ messages: readonly unknown[];
410
+ tools?: readonly unknown[];
411
+ /**
412
+ * The rest of the chat request, as it will be sent: see
413
+ * `templateFieldsOf`. The server parses this body with the same code
414
+ * it parses a chat request with, so fields such as
415
+ * `reasoning_budget_tokens` change the rendering here exactly as they
416
+ * do there.
417
+ */
418
+ fields?: Readonly<Record<string, unknown>>;
419
+ }): Promise<string>;
420
+ }
421
+ /**
422
+ * Which pool each live conversation is currently attached to.
423
+ *
424
+ * A registry rather than a field on the provider config because the two move at
425
+ * different rates: the config is resolved once for a session, and the pool it
426
+ * points at is replaced every time a compaction re-roots the conversation.
427
+ * Compaction is a prompt rewrite -- the compacted text cannot match the old
428
+ * cells -- so the correct primitive is a fork with a new id, and a session that
429
+ * kept reading its pool from a frozen config would keep attaching to the pool
430
+ * that was just released.
431
+ *
432
+ * Keyed by the session id the host already has. Entries are cleared when the
433
+ * session ends; a leaked entry costs a lookup, a leaked *pin* costs the cells,
434
+ * which is why release is a separate and deliberate step.
435
+ */
436
+ export interface PolykvSessionState {
437
+ poolId: string;
438
+ /**
439
+ * Where this pool's own range begins -- the length of the prefix it shares
440
+ * with its ancestors, and the `branch_pos` a re-root forks at.
441
+ */
442
+ prefixTokens: number;
443
+ /**
444
+ * `"lead"`: the pool is the conversation's place in the server-wide lead
445
+ * tree (`polykv-lead.ts`) -- a shared root, or the conversation's own
446
+ * sub-pool of it. Not this session's to re-root or release by id: the root
447
+ * is every session's, and the lead tree releases what it made.
448
+ *
449
+ * `"borrowed"`: someone else's pool this session only attaches to -- a
450
+ * swarm worker on the lead's snapshot or borrowed root. Its to read, never
451
+ * its to re-root, unpin or release: that pool is the lead's, and every
452
+ * other worker of the round is attached to it.
453
+ */
454
+ layout?: "lead" | "borrowed";
455
+ /**
456
+ * Send this session's requests as continuations of the pool
457
+ * (`pool_continue_v1`): only the last `continueTail` messages go on the
458
+ * wire, as the turns that follow the pool's stored stream. Set only on a
459
+ * pool that ends where an assistant reply ends -- a `from_session` pool of
460
+ * a finished turn -- and only by a caller that knows the engine has it.
461
+ */
462
+ continueTail?: number;
463
+ /**
464
+ * The `templateSignature` of the request fields a session's own root was
465
+ * rendered with. A root rendered without the request's fields -- Gemma-4's
466
+ * `<|think|>` follows `reasoning_budget_tokens` -- diverges at token 4;
467
+ * the vendor renders it again with the fields of the first request that
468
+ * attaches it.
469
+ */
470
+ templateSignature?: string;
471
+ }
472
+ export declare function setPolykvSession(sessionId: string, state: PolykvSessionState): void;
473
+ export declare function getPolykvSession(sessionId: string | undefined): PolykvSessionState | undefined;
474
+ export declare function clearPolykvSession(sessionId: string): void;
475
+ /**
476
+ * The window a session was granted, and what it asked for when it was.
477
+ *
478
+ * `granted` and `asked` are the numbers on the wire: `num_ctx` and the
479
+ * `X-Context-Window` that answered it. Under `polykv_private_window_v1` both
480
+ * are the PRIVATE budget, and the shared prefix the conversation attached to
481
+ * rides above them -- `sharedTokens` -- so the window the conversation can
482
+ * actually fill is `granted + sharedTokens` ({@link polykvEffectiveWindow}).
483
+ */
484
+ export interface PolykvWindowGrant {
485
+ granted: number;
486
+ /**
487
+ * The window the conversation asked for when it was opened.
488
+ *
489
+ * Kept from the FIRST grant: every later admission of the session asks for
490
+ * exactly the granted window, so the ask on the wire stops saying what the
491
+ * user configured the moment the resume rule takes over.
492
+ */
493
+ asked?: number;
494
+ sharedTokens?: number;
495
+ }
496
+ /**
497
+ * Be told whenever a session's grant is first learned or changes.
498
+ *
499
+ * The host persists it from here, because the grant arrives on a response --
500
+ * long after the session record was written at start.
501
+ */
502
+ export declare function onPolykvWindowGrant(listener: (sessionId: string, grant: PolykvWindowGrant) => void): () => void;
503
+ /**
504
+ * Record what `X-Context-Window` reported for this session.
505
+ *
506
+ * `detail` describes the ask that produced it. It is taken only when the
507
+ * session has no grant yet -- see {@link PolykvWindowGrant.asked} -- so a
508
+ * hydrated record or a resumed ask can never overwrite the original ask with
509
+ * the granted one.
510
+ */
511
+ export declare function recordPolykvGrantedWindow(sessionId: string, window: number, detail?: {
512
+ asked?: number;
513
+ sharedTokens?: number;
514
+ }): void;
515
+ /** The window this conversation already holds, if we have seen one granted. */
516
+ export declare function getPolykvGrantedWindow(sessionId: string | undefined): number | undefined;
517
+ /** The whole grant record, for persisting and for the context bar. */
518
+ export declare function getPolykvWindowGrant(sessionId: string | undefined): PolykvWindowGrant | undefined;
519
+ /**
520
+ * The window the conversation can actually fill: the grant plus the shared
521
+ * prefix riding above it. `undefined` when no grant is known.
522
+ */
523
+ export declare function polykvEffectiveWindow(grant: PolykvWindowGrant | undefined): number | undefined;
524
+ /**
525
+ * Read a grant back from stored metadata, rejecting anything malformed.
526
+ *
527
+ * The shape is {@link PolykvWindowGrant}; a record that does not carry a
528
+ * positive `granted` is not a grant, and hydrating from it would pin a resumed
529
+ * conversation to a window nobody was ever given.
530
+ */
531
+ export declare function readPolykvWindowGrant(value: unknown): PolykvWindowGrant | undefined;
532
+ /**
533
+ * Forget a session's grant. A test seam and an explicit reset -- NOT called
534
+ * when a session closes, see {@link POLYKV_GRANTED_WINDOWS}.
535
+ */
536
+ export declare function clearPolykvGrantedWindow(sessionId: string): void;
537
+ /**
538
+ * What the LAST admitted response said about the window, per session.
539
+ *
540
+ * Separate from the grant on purpose. The grant is the booking, remembered for
541
+ * the resume rule; this is the per-response reading, and a response without
542
+ * `X-Context-Window` is not guaranteed -- an overcommit, or a server that is
543
+ * not enforcing -- so it reads as UNKNOWN (`granted: undefined`), never as
544
+ * "the same as last time".
545
+ */
546
+ export interface PolykvWindowObservation {
547
+ granted?: number;
548
+ asked?: number;
549
+ sharedTokens?: number;
550
+ }
551
+ export declare function recordPolykvWindowObservation(sessionId: string, observation: PolykvWindowObservation): void;
552
+ export declare function getPolykvWindowObservation(sessionId: string | undefined): PolykvWindowObservation | undefined;
553
+ export declare function resetPolykvSessions(): void;
554
+ /**
555
+ * What one `GET /props` tells us about a server, cached per root.
556
+ *
557
+ * Every branch in this provider keys off one of these, so they are read
558
+ * together, once, rather than probed separately at each call site.
559
+ */
560
+ export interface OpencotiProps {
561
+ /**
562
+ * The release, parsed from `build_info` (`opencoti-0.10.5-c7-...`).
563
+ *
564
+ * It decides which signals can be trusted, and the differences are not
565
+ * cosmetic: on c7 a `429` carries a body that says `503`, `GET /capacity`
566
+ * mutates the admission learner, the completion response does not say
567
+ * whether the pool attached, and `/polykv/tps` reports `-1` as the pool key.
568
+ * A client that assumes the c8 shapes misreads all four in silence.
569
+ *
570
+ * `undefined` when the server did not say -- which is every non-opencoti
571
+ * server, and is why nothing may branch on it being absent except to fall
572
+ * back to the conservative path.
573
+ */
574
+ release?: string;
575
+ /**
576
+ * Whether `/props` answered at all.
577
+ *
578
+ * The three other fields cannot carry this: a plain llama.cpp server and a
579
+ * server that is not there both report `poolsEnabled: false, elastic:
580
+ * false`, and the right thing to say about them is opposite -- one has a
581
+ * fixed `--parallel` count, the other was never asked. A panel that
582
+ * collapses them tells a user their server has neither controller on
583
+ * because the question failed, which is a guess wearing a fact's clothes.
584
+ */
585
+ reachable: boolean;
586
+ /** Pools are compiled in AND the server was launched with `--polykv-max-pools`. */
587
+ poolsEnabled: boolean;
588
+ /** The elastic slot controller is armed, so the slot count is not fixed. */
589
+ elastic: boolean;
590
+ /** `slots_live` at the time of the probe; the ceiling is `slotsMax`. */
591
+ slotsLive?: number;
592
+ slotsMax?: number;
593
+ /** The chat template the server will apply. The pool prefix must match it. */
594
+ chatTemplate?: string;
595
+ /** Advertised capabilities, e.g. `slots_nonblocking_v1`. */
596
+ features: readonly string[];
597
+ /**
598
+ * The temperature the server samples at when a request names none:
599
+ * `default_generation_settings.params.temperature` (or, on an older build,
600
+ * `default_generation_settings.temperature`). Read, never sent -- it is the
601
+ * model's own sampler, which a spawn's `temperature: "random"` jitters.
602
+ */
603
+ defaultTemperature?: number;
604
+ }
605
+ /**
606
+ * The advertised capabilities this client branches on.
607
+ *
608
+ * **These, and never a parsed release.** The published binary stamps no `c<N>`
609
+ * anywhere in `/props`, and the build that does stamp one carries `-c7-` on the
610
+ * artifact that ships the c8 behaviours -- so a version gate reads the wrong
611
+ * answer on both the server it was written for and the one it was written
612
+ * against. A flag is self-identifying; a version string that is not sent is
613
+ * not.
614
+ *
615
+ * Listed here rather than inlined at each branch so that the set is readable as
616
+ * a set, and so that a server advertising something we do not consume yet is
617
+ * visible as a gap rather than as nothing.
618
+ */
619
+ export declare const OPENCOTI_FEATURES: {
620
+ /** `GET /capacity` no longer folds the learner; `?fold=1` asks for it. */
621
+ readonly capacityReadonly: "capacity_readonly_v1";
622
+ /** The completion response carries `opencoti {pool_id, n_pool_shared}`. */
623
+ readonly attachInResponse: "attach_in_response_v1";
624
+ /** `X-PolyKV-Settle-Waived` tells a timer waiver from a measured admit. */
625
+ readonly settleWaivedHeader: "settle_waived_header_v1";
626
+ /** `/polykv/tps` reports the real pool binding, plus a stable `alloc_key`. */
627
+ readonly tpsRealPoolId: "tps_real_pool_id_v1";
628
+ /** An elastic slot is a guaranteed allocation booked by `num_ctx`. */
629
+ readonly guaranteedAlloc: "elastic_guaranteed_alloc_v1";
630
+ /** `GET /kv`: the pollable allocation snapshot. */
631
+ readonly kvStatus: "kv_status_v1";
632
+ /** Pools are sub-pools of their owning session, max 8 per session. */
633
+ readonly subpools: "polykv_subpools_v1";
634
+ /** `POST /sessions/{id}/close` releases a window before its TTL. */
635
+ readonly sessionClose: "session_close_v1";
636
+ /** `num_ctx_min`: the floor is negotiated server-side, in one admission. */
637
+ readonly ctxMinNegotiation: "ctx_min_negotiation_v1";
638
+ /** `/capacity` carries `pressure`, `window_cells`, `owner`, `pressure_scope`. */
639
+ readonly sessionPressure: "session_pressure_v1";
640
+ /** The tps floor is settable at runtime via `POST /elastic`. */
641
+ readonly elasticRw: "elastic_rw_v1";
642
+ /** `hold_ticks` -- how long a grow condition must hold -- is settable too. */
643
+ readonly elasticHoldRw: "elastic_hold_rw_v1";
644
+ /**
645
+ * A slot whose own cache covers a named pool's whole prefix is rebased onto
646
+ * the pool, so a continuation turn keeps its share (`n_pool_shared = P`).
647
+ */
648
+ readonly rebase: "polykv_rebase_v1";
649
+ /** Under the tps floor a busy top slot drains instead of taking new work. */
650
+ readonly elasticDrain: "elastic_drain_v1";
651
+ /**
652
+ * `num_ctx` is the PRIVATE budget: an attached pool's shared prefix rides
653
+ * above it, capped at the per-session maximum.
654
+ */
655
+ readonly privateWindow: "polykv_private_window_v1";
656
+ /** `POST /polykv/pools {shared: true}` is find-or-create for an unowned root. */
657
+ readonly sharedRoot: "polykv_shared_root_v1";
658
+ /** `POST /sessions/close {session_id}`: the close for ids the path cannot carry. */
659
+ readonly sessionCloseBody: "session_close_body_v1";
660
+ /** The response's `opencoti` block carries `pool_match` and `pool_len`. */
661
+ readonly poolMatchInResponse: "pool_match_in_response_v1";
662
+ /**
663
+ * `stream_options.keepalive`: the SSE stream opens at once and every silent
664
+ * period carries a `: keepalive <phase>` comment (`opencoti-liveness.ts`).
665
+ */
666
+ readonly streamKeepalive: "stream_keepalive_v1";
667
+ /** SO_KEEPALIVE on the server's sockets. Server-side only: nothing to send. */
668
+ readonly tcpKeepalive: "tcp_keepalive_v1";
669
+ /** `boot_id` / `started_at` on `/health` and `/props`, `X-OpenCoti-Boot-Id` on completions. */
670
+ readonly bootId: "boot_id_v1";
671
+ /** `opencoti.pool_unknown`: the named pool is not in this process. */
672
+ readonly poolUnknownInResponse: "pool_unknown_in_response_v1";
673
+ /**
674
+ * `GET /kv` carries `pressure` -- the server's refusals over the last
675
+ * `window_s` -- and every admission 429 carries it as `error.pressure`.
676
+ */
677
+ readonly kvPressure: "kv_pressure_v1";
678
+ /** `POST /kv/sessions/{id}/resize {num_ctx}`: a live booking can shrink and grow. */
679
+ readonly kvResize: "kv_resize_v1";
680
+ /**
681
+ * `{num_ctx, deferred: true}` on the resize route: a busy session's resize
682
+ * is queued (202) and applied at its idle moment; the `/kv` row carries
683
+ * `resize_pending` (b110, mail #306).
684
+ */
685
+ readonly kvResizeDeferred: "kv_resize_deferred_v1";
686
+ /**
687
+ * A busy session's resize applies while its requests run, when the new
688
+ * window still covers what is used and what the running requests were
689
+ * admitted with (patch 0422, b157, mail #460). Also learned per server
690
+ * from a resize answer that says `live` -- see `opencotiResizesLive`.
691
+ */
692
+ readonly kvResizeLive: "kv_resize_live_v1";
693
+ /**
694
+ * What the engine holds that nobody is charged for (b115, patch 0399,
695
+ * mail #316): `idle_resident` on `/kv.pressure` and on the resize result
696
+ * -- cells physically held by idle slots, a released worker's "ghost" --
697
+ * `error_kind: "evicted_kv_full"` on the partial eviction, and
698
+ * `resize_pending_refused_at` / `_s` on a `/kv` row whose queued resize
699
+ * was refused at its idle moment.
700
+ */
701
+ readonly kvObservable: "kv_observable_v1";
702
+ /**
703
+ * `unowned: true` on pool create and fork (b124, patch 0406, mail #342): a
704
+ * pool charged to nobody even when built `from_session` of a session that
705
+ * holds a booking; every attacher books its own window. A 400 together
706
+ * with `session_id`.
707
+ */
708
+ readonly poolUnowned: "pool_unowned_v1";
709
+ /**
710
+ * `continue_pool: true` + `pool_id` on a chat request (b124, patch 0406):
711
+ * the prompt is the pool's stored tokens followed by `messages` rendered as
712
+ * a continuation, so `cache_n == len(pool)` by construction. `messages` are
713
+ * only the new turns, and the pool must end where an assistant reply ends.
714
+ */
715
+ readonly poolContinue: "pool_continue_v1";
716
+ };
717
+ export type OpencotiFeature = (typeof OPENCOTI_FEATURES)[keyof typeof OPENCOTI_FEATURES];
718
+ /** Whether a server advertised a capability. Absent always means "no". */
719
+ export declare function hasOpencotiFeature(features: readonly string[] | undefined, feature: OpencotiFeature): boolean;
720
+ /**
721
+ * The server's default temperature, from a `/props` read that has already
722
+ * answered -- never a fetch. `undefined` when it was not read yet, did not
723
+ * answer, or states none.
724
+ */
725
+ export declare function readOpencotiDefaultTemperature(baseUrl: string | undefined): number | undefined;
726
+ /**
727
+ * Read a server's opencoti capabilities, once.
728
+ *
729
+ * `/props` rather than `/polykv/pools`: a server booted without
730
+ * `--polykv-max-pools` -- the default -- errors on every `/polykv/*` route, so
731
+ * probing there cannot tell "pools are off" from "the server is not there", and
732
+ * both were being reported as the latter. `/props` answers on every build, and
733
+ * carries the elastic state and the chat template in the same response.
734
+ *
735
+ * A server that cannot be reached, or that has no opencoti block, answers
736
+ * "not opencoti": the fixed slot count is the safe reading when the question
737
+ * cannot be asked.
738
+ */
739
+ export declare function probeOpencotiProps(baseUrl: string | undefined, fetchImpl?: typeof fetch): Promise<OpencotiProps>;
740
+ /**
741
+ * Whether this server has PolyKV turned on.
742
+ *
743
+ * It matters because PolyKV changes what a slot *is*. Without it a server has
744
+ * `--parallel N` slots and an N+1st request waits; with it agents attach to a
745
+ * pool and share a slot, and whether one more may start is decided by the
746
+ * engine's admission control against real KV headroom rather than by counting.
747
+ * Capping agents at the slot count in that case would refuse work the server
748
+ * would have taken.
749
+ */
750
+ export declare function probePolykvEnabled(baseUrl: string | undefined, fetchImpl?: typeof fetch): Promise<boolean>;
751
+ /** Test seam, and the way a changed server launch is picked up. */
752
+ export declare function resetPolykvAvailability(): void;
753
+ export declare function createPolykvClient(options: PolykvClientOptions): PolykvClient;
754
+ /** One pool in the tree, as the status panel shows it. */
755
+ export interface OpencotiStatusPool {
756
+ poolId: string;
757
+ /** The pool this one branches from, absent for a root. */
758
+ parent?: string;
759
+ /** Where the child's own tokens start; everything before is shared. */
760
+ branchPos?: number;
761
+ prefixLen?: number;
762
+ pinned: boolean;
763
+ ephemeral: boolean;
764
+ /**
765
+ * Pinned, childless, and referenced by no slot's current or last task.
766
+ *
767
+ * Typically left behind by a compaction re-root that did not unpin. It
768
+ * blocks reclaim forever, which is the leak this client's release and unpin
769
+ * fixes exist to stop, so it is named rather than counted.
770
+ */
771
+ orphanedPin: boolean;
772
+ /** The session a `from_session` snapshot was taken from. */
773
+ sourceSession?: string;
774
+ children: number;
775
+ /** The floor this pool's admission policy holds new sessions to, when set. */
776
+ admissionFloor?: number;
777
+ /** `enforced` refuses below the floor; `advisory` only reports. */
778
+ admissionMode?: string;
779
+ }
780
+ /** One live session, keyed the way the server allows. */
781
+ export interface OpencotiStatusSession {
782
+ sessionId: string;
783
+ /**
784
+ * The pool this session is bound to.
785
+ *
786
+ * Present only under `tps_real_pool_id_v1`. On c7 the field is on the wire
787
+ * but reports `-1` for every registry pool -- it is the legacy donor-slot
788
+ * key -- so it identifies nothing and grouping by it collapses every
789
+ * session into one. Absent is the honest reading there.
790
+ */
791
+ poolId?: string;
792
+ /**
793
+ * The allocation this session holds, stable across a slot move.
794
+ *
795
+ * Elastic growth can move a session to a different slot, so a slot index is
796
+ * not an identity over time and this is.
797
+ */
798
+ allocKey?: string;
799
+ /**
800
+ * The slot's throughput EWMA, absent while it is warming.
801
+ *
802
+ * A processing slot reporting `0` has not warmed its EWMA yet; it is not a
803
+ * slot producing nothing, and averaging its zero is what dragged the
804
+ * admission mean down after every spawn.
805
+ */
806
+ tps?: number;
807
+ active: boolean;
808
+ ctxUsed?: number;
809
+ ctxTotal?: number;
810
+ }
811
+ /**
812
+ * Everything the settings panel shows about a live server.
813
+ *
814
+ * Read from `/props`, `/polykv/pools` and `/polykv/tps`, which are served from
815
+ * a published snapshot and are safe to read while the server is busy -- and,
816
+ * **only when the server advertises `capacity_readonly_v1`**, from `/capacity`
817
+ * as well.
818
+ *
819
+ * That last condition is the whole of it. On the published c7 engine every GET
820
+ * of `/capacity` folds the settle and bias EWMAs, so a panel that refreshed
821
+ * would corrupt the admission projection it was drawing; `kv_headroom_pct` and
822
+ * the SWA arm live only there and were therefore simply absent. The flag says
823
+ * the plain GET is read-only and the fold has moved behind `?fold=1`, which is
824
+ * what makes the fourth read safe. Without it we do not ask, and the fields
825
+ * stay absent rather than being guessed at from somewhere else.
826
+ */
827
+ export interface OpencotiAllocation {
828
+ sessionId: string;
829
+ /** The window this session booked, in cells. */
830
+ window: number;
831
+ used: number;
832
+ free: number;
833
+ /**
834
+ * Raw `used/window`, 0..1, never a ramp.
835
+ *
836
+ * The compaction trigger. It is deliberately taken raw from the server and
837
+ * compared against a threshold we own, because the number the user set is
838
+ * the number they should see: a server-side ramp would make the figure in
839
+ * our UI stop matching the one in theirs.
840
+ */
841
+ pressure: number;
842
+ /** Sub-pools this session holds, of `poolsMaxPerSlot`. */
843
+ pools: number;
844
+ /**
845
+ * A resize queued for this session's idle moment (`kv_resize_deferred_v1`):
846
+ * the window it will be resized to.
847
+ */
848
+ resizePending?: number;
849
+ /**
850
+ * Why a queued resize has not applied at an idle moment -- the engine's
851
+ * resize refusal kind, e.g. `used_exceeds_window` for a shrink below what
852
+ * the session holds. It stays queued.
853
+ */
854
+ resizePendingReason?: string;
855
+ /**
856
+ * When the queued resize was last refused at an idle moment, epoch seconds
857
+ * on the server's clock (`kv_observable_v1`). Set only while it stays
858
+ * queued: the engine will try the same target again at the next idle
859
+ * moment, and a client that re-sends it adds nothing.
860
+ */
861
+ resizePendingRefusedAt?: number;
862
+ /** Seconds since that refusal, when the row was written. */
863
+ resizePendingRefusedS?: number;
864
+ }
865
+ export interface OpencotiStatus {
866
+ /** Whether `/props` answered at all. */
867
+ reachable: boolean;
868
+ release?: string;
869
+ /**
870
+ * KV headroom, and the SWA arm beside it.
871
+ *
872
+ * From `GET /kv` where the server offers it, which needs no pool to address
873
+ * and is server-wide by construction; otherwise from a pool's `/capacity`,
874
+ * which needs `capacity_readonly_v1` before it may be read at all.
875
+ *
876
+ * **`kvScope` says which window these describe** and must be read with
877
+ * them -- see `PolykvCapacity.pressure_scope`. `kvCells*` covers the BASE
878
+ * pool only: on an iSWA model the sliding-window ring is a separate
879
+ * account, so total occupancy is neither of them and is not their sum.
880
+ */
881
+ kvHeadroomPct?: number;
882
+ kvCellsFree?: number;
883
+ kvCellsTotal?: number;
884
+ kvCellsUsed?: number;
885
+ /** `server` or one session's private window. Never assumed. */
886
+ kvScope?: "server" | "session";
887
+ /** The session those figures belong to, when `kvScope` is `session`. */
888
+ kvScopeOwner?: string;
889
+ /** The largest window a new session could book right now. */
890
+ largestAdmissible?: number;
891
+ /** Whether the server is enforcing guaranteed allocations at all. */
892
+ guaranteed?: boolean;
893
+ /** Sub-pools one session may hold. */
894
+ poolsMaxPerSlot?: number;
895
+ /** How long an idle window is held before the server reclaims it. */
896
+ allocTtlSeconds?: number;
897
+ /** One row per session holding a window. Empty on a server without them. */
898
+ allocations: OpencotiAllocation[];
899
+ swaActive?: boolean;
900
+ swaCellsFree?: number | null;
901
+ swaCellsTotal?: number | null;
902
+ swaWindow?: number | null;
903
+ poolsEnabled: boolean;
904
+ elastic: boolean;
905
+ /**
906
+ * The elastic controller's own word for where it is.
907
+ *
908
+ * Surfaced verbatim because the engine keeps `saturated, hold` distinct
909
+ * from `kv headroom exhausted` deliberately: one says raise
910
+ * `--max-parallel`, the other says this context does not fit.
911
+ */
912
+ elasticReason?: string;
913
+ slotsLive?: number;
914
+ slotsMax?: number;
915
+ /**
916
+ * Free VRAM, when the engine can measure it.
917
+ *
918
+ * The engine sends `null`, not `0`, when the number would be a lie -- no
919
+ * GPU layers, or integrated memory where the device reports host RAM -- so
920
+ * this stays `undefined` there. A reader that saw `0` could not tell "no
921
+ * headroom" from "no measurement".
922
+ */
923
+ vramFreeMib?: number;
924
+ tpsFloor?: number;
925
+ grows?: number;
926
+ shrinks?: number;
927
+ poolsMax?: number;
928
+ treeDepth?: number;
929
+ pools: readonly OpencotiStatusPool[];
930
+ sessions: readonly OpencotiStatusSession[];
931
+ }
932
+ /** `GET /kv`'s `allocations[]`, one row per session holding a window. */
933
+ export declare function parseOpencotiAllocations(kv: Record<string, unknown> | undefined): OpencotiAllocation[];
934
+ /**
935
+ * The per-session allocations, and nothing else, off `GET /kv`.
936
+ *
937
+ * For the compaction trigger, which wants one session's raw `pressure` and
938
+ * none of the rest of the status read. `undefined` when the server does not
939
+ * offer the route (`kv_status_v1`) or did not answer: "cannot say" is not
940
+ * "no pressure", and the caller falls back to what it had.
941
+ */
942
+ export declare function readOpencotiAllocations(baseUrl: string | undefined, fetchImpl?: typeof fetch): Promise<OpencotiAllocation[] | undefined>;
943
+ /**
944
+ * Read a server's live PolyKV state for display.
945
+ *
946
+ * Nothing here may fail a caller: every read that does not answer leaves its
947
+ * part of the shape empty, and a server that cannot be reached at all reports
948
+ * itself as such rather than as a server with no pools -- those are different
949
+ * things and the panel says which.
950
+ *
951
+ * Pool timestamps are deliberately absent. On c7 `created_ts` and
952
+ * `last_access_ts` are `ggml_time_us()` monotonic stamps since boot, not epoch
953
+ * seconds, so rendering either as a wall-clock time shows a date in 1970 and
954
+ * rendering the difference from now shows an age of decades. c8 anchors them;
955
+ * until then the honest number is none.
956
+ */
957
+ export declare function readOpencotiStatus(baseUrl: string | undefined, fetchImpl?: typeof fetch): Promise<OpencotiStatus>;
958
+ //# sourceMappingURL=polykv.d.ts.map