@clutor/cli 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,615 @@
1
+ import { Receipt, MemoryPlan, LlmClient, GateResult, StreamMetrics, ModelLayout, GgufFile, ShadowWorkspace, AgentEvent, AgentResult, FileDiff } from '@clutor/core';
2
+ import { z } from 'zod';
3
+ import { Server } from 'node:http';
4
+ import { NodeProject } from '@clutor/core/node';
5
+ export { ConflictError } from '@clutor/core/node';
6
+
7
+ interface ParsedArgs {
8
+ positional: string[];
9
+ flags: Map<string, string | true>;
10
+ }
11
+ /** Tiny `--flag value` / `--flag=value` / `--bool` parser. `booleans` lists flags that never take a value. */
12
+ declare function parseArgs(argv: string[], booleans?: readonly string[]): ParsedArgs;
13
+ declare const flagString: (a: ParsedArgs, name: string) => string | undefined;
14
+ declare const flagBool: (a: ParsedArgs, name: string) => boolean;
15
+ declare function flagInt(a: ParsedArgs, name: string, min: number, max: number): number | undefined;
16
+ declare class UsageError extends Error {
17
+ constructor(message: string);
18
+ }
19
+
20
+ interface DecideEndpoint {
21
+ baseUrl: string;
22
+ model: string;
23
+ apiKey?: string;
24
+ }
25
+ interface DecideResult {
26
+ choice: string;
27
+ probabilities: Record<string, number>;
28
+ probabilityMassOnChoices: number;
29
+ latencyMs: number;
30
+ }
31
+ /** The request was wrong (400) or the model server could not answer it (502). */
32
+ declare class DecideError extends Error {
33
+ readonly status: 400 | 502;
34
+ constructor(status: 400 | 502, message: string);
35
+ }
36
+ /**
37
+ * One forward pass, one token: the model's own probability for each choice's letter, read from the first-token log-probabilities.
38
+ * Not calibrated. Shared by `clutor decide` and `POST /v1/decide`.
39
+ */
40
+ declare function runDecide(e: DecideEndpoint, prompt: string, choices: string[], f?: typeof fetch): Promise<DecideResult>;
41
+ /**
42
+ * Signs a decision into the project's receipt log, so it chains with the agent's receipts. The receipt records a SHA-256 of the prompt, not the
43
+ * prompt itself, because the log is meant to be shared for verification.
44
+ */
45
+ declare function sealDecision(root: string, model: string, prompt: string, choices: string[], r: DecideResult, startedAt: string): Promise<Receipt>;
46
+
47
+ declare function findLlamaServer(env?: NodeJS.ProcessEnv, extraDirs?: string[]): string | null;
48
+ interface LlamaCapabilities {
49
+ flags: Set<string>;
50
+ /** `--flash-attn on|off|auto` (newer builds) rather than a bare `--flash-attn` switch. */
51
+ flashAttnTakesValue: boolean;
52
+ helpText: string;
53
+ }
54
+ /** Runs `llama-server --help` and records which options this build knows, so unsupported flags are never passed. */
55
+ declare function probeLlamaServer(binary: string, timeoutMs?: number): Promise<LlamaCapabilities>;
56
+ interface LlamaArgsInput {
57
+ modelPath: string;
58
+ port: number;
59
+ contextTokens: number;
60
+ kvBits: 16 | 8 | 4;
61
+ threads?: number;
62
+ plan?: Pick<MemoryPlan, "strategy">;
63
+ caps: LlamaCapabilities;
64
+ extraArgs?: string[];
65
+ /** Where llama-server may save and restore KV-cache snapshots. */
66
+ slotSavePath?: string;
67
+ }
68
+ declare function buildLlamaArgs(i: LlamaArgsInput): {
69
+ args: string[];
70
+ notes: string[];
71
+ };
72
+ type BackendState = "stopped" | "starting" | "ready" | "failed";
73
+ declare class BackendManager {
74
+ readonly port: number;
75
+ private readonly fetchFn;
76
+ state: BackendState;
77
+ error: string | null;
78
+ private child;
79
+ private readonly log;
80
+ private readonly listeners;
81
+ constructor(port: number, fetchFn?: typeof globalThis.fetch);
82
+ get baseUrl(): string;
83
+ get recentLog(): string[];
84
+ onState(f: (s: BackendState) => void): () => void;
85
+ private set;
86
+ start(binary: string, args: string[], opts?: {
87
+ readyTimeoutMs?: number;
88
+ env?: NodeJS.ProcessEnv;
89
+ }): Promise<void>;
90
+ stop(): Promise<void>;
91
+ }
92
+ /**
93
+ * Saves and restores a llama-server slot's KV cache (POST /slots/<id>?action=save|restore). Used so the project map and instructions,
94
+ * which every agent step starts with, are not recomputed on the next run. Every call is best effort: a refusal just means a slower first step.
95
+ */
96
+ declare class SlotSnapshots {
97
+ private readonly baseUrl;
98
+ private readonly slot;
99
+ private readonly fetchFn;
100
+ readonly stats: {
101
+ restored: number;
102
+ saved: number;
103
+ restoreMisses: number;
104
+ failures: number;
105
+ };
106
+ constructor(baseUrl: string, slot?: number, fetchFn?: typeof globalThis.fetch);
107
+ private url;
108
+ private post;
109
+ restore(name: string): Promise<boolean>;
110
+ save(name: string): Promise<boolean>;
111
+ }
112
+ /** Wraps a model client so the shared prefix (instructions + project map) is restored before the first call and saved after it. */
113
+ declare function withPrefixSnapshots(inner: LlmClient, snaps: SlotSnapshots): LlmClient & {
114
+ snapshots: SlotSnapshots;
115
+ };
116
+
117
+ declare const CONFIG_FILE = "clutor.config.json";
118
+ declare const DEFAULT_PORT = 4320;
119
+ declare const ConfigSchema: z.ZodObject<{
120
+ port: z.ZodDefault<z.ZodNumber>;
121
+ host: z.ZodDefault<z.ZodString>;
122
+ models: z.ZodDefault<z.ZodString>;
123
+ backend: z.ZodDefault<z.ZodObject<{
124
+ kind: z.ZodDefault<z.ZodEnum<{
125
+ none: "none";
126
+ openai: "openai";
127
+ "llama-server": "llama-server";
128
+ }>>;
129
+ baseUrl: z.ZodOptional<z.ZodString>;
130
+ model: z.ZodOptional<z.ZodString>;
131
+ apiKeyEnv: z.ZodOptional<z.ZodString>;
132
+ llamaServer: z.ZodDefault<z.ZodObject<{
133
+ binary: z.ZodOptional<z.ZodString>;
134
+ model: z.ZodOptional<z.ZodString>;
135
+ port: z.ZodDefault<z.ZodNumber>;
136
+ threads: z.ZodOptional<z.ZodNumber>;
137
+ extraArgs: z.ZodDefault<z.ZodArray<z.ZodString>>;
138
+ }, z.core.$strict>>;
139
+ }, z.core.$strict>>;
140
+ memory: z.ZodDefault<z.ZodObject<{
141
+ ramCeilingGiB: z.ZodOptional<z.ZodNumber>;
142
+ osHeadroomGiB: z.ZodOptional<z.ZodNumber>;
143
+ contextTokens: z.ZodDefault<z.ZodNumber>;
144
+ kvBits: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<16>, z.ZodLiteral<8>, z.ZodLiteral<4>]>>;
145
+ diskGBps: z.ZodOptional<z.ZodNumber>;
146
+ }, z.core.$strict>>;
147
+ cache: z.ZodDefault<z.ZodObject<{
148
+ policy: z.ZodDefault<z.ZodEnum<{
149
+ lru: "lru";
150
+ wtinylfu: "wtinylfu";
151
+ adaptive: "adaptive";
152
+ }>>;
153
+ smartRoute: z.ZodDefault<z.ZodObject<{
154
+ enabled: z.ZodDefault<z.ZodBoolean>;
155
+ maxSubstitutions: z.ZodDefault<z.ZodNumber>;
156
+ candidates: z.ZodDefault<z.ZodNumber>;
157
+ maxDeltaP: z.ZodDefault<z.ZodNumber>;
158
+ }, z.core.$strict>>;
159
+ }, z.core.$strict>>;
160
+ agent: z.ZodDefault<z.ZodObject<{
161
+ toolMode: z.ZodDefault<z.ZodEnum<{
162
+ json: "json";
163
+ native: "native";
164
+ }>>;
165
+ maxSteps: z.ZodDefault<z.ZodNumber>;
166
+ verifyCommand: z.ZodOptional<z.ZodString>;
167
+ autoApproveProjectCommands: z.ZodDefault<z.ZodBoolean>;
168
+ commandTimeoutSeconds: z.ZodDefault<z.ZodNumber>;
169
+ constrainToolCalls: z.ZodDefault<z.ZodBoolean>;
170
+ prefixSnapshots: z.ZodDefault<z.ZodBoolean>;
171
+ }, z.core.$strict>>;
172
+ corsOrigins: z.ZodDefault<z.ZodArray<z.ZodString>>;
173
+ }, z.core.$strict>;
174
+ type ClutorConfig = z.infer<typeof ConfigSchema>;
175
+ declare class ConfigError extends Error {
176
+ constructor(message: string);
177
+ }
178
+ declare function loadConfig(dir: string, file?: string): {
179
+ config: ClutorConfig;
180
+ path: string | null;
181
+ root: string;
182
+ };
183
+
184
+ declare function table(rows: string[][], header?: string[]): string;
185
+ declare const pct: (x: number) => string;
186
+ declare const tps: (x: number) => string;
187
+ declare function formatPlan(name: string, quant: string | undefined, p: MemoryPlan): string;
188
+ declare function formatGates(g: GateResult[]): string;
189
+ declare function formatSimulation(base: StreamMetrics, c: StreamMetrics): string;
190
+
191
+ interface ResolvedModel {
192
+ id: string;
193
+ name: string;
194
+ source: "catalog" | "file";
195
+ path?: string;
196
+ layout: ModelLayout;
197
+ gguf?: GgufFile;
198
+ quant?: string;
199
+ }
200
+ declare class ModelError extends Error {
201
+ constructor(message: string);
202
+ }
203
+ /** `deepseek-v3`, `deepseek-v3@Q4_K_M`, or the path of a .gguf file. */
204
+ declare function resolveModel(ref: string, opts?: {
205
+ modelsDir?: string;
206
+ allowFiles?: boolean;
207
+ }): Promise<ResolvedModel>;
208
+ interface LocalModel {
209
+ file: string;
210
+ path: string;
211
+ bytes: number;
212
+ }
213
+ declare function listLocalModels(dir: string): Promise<LocalModel[]>;
214
+ /**
215
+ * Real models small enough to download and test with. Sizes are the file sizes Hugging Face reported on 2026-10-30; the download
216
+ * is checked against the size the server announces, and nothing is fetched unless you run `clutor pull`.
217
+ */
218
+ interface Download {
219
+ id: string;
220
+ catalogId: string;
221
+ repo: string;
222
+ file: string;
223
+ bytes: number;
224
+ note: string;
225
+ }
226
+ declare const DOWNLOADS: Download[];
227
+ declare const downloadUrl: (d: Download) => string;
228
+ declare class DownloadError extends Error {
229
+ constructor(message: string);
230
+ }
231
+ /** Downloads `url` to `dest` through a `.part` file, refusing to start without room for it and refusing a size the server did not announce. */
232
+ declare function downloadFile(url: string, dest: string, opts?: {
233
+ fetch?: typeof fetch;
234
+ expectedBytes?: number;
235
+ onProgress?: (done: number, total: number) => void;
236
+ }): Promise<number>;
237
+
238
+ /** Translation between the Ollama HTTP API and an OpenAI-compatible backend, so tools that speak Ollama can use whatever Clutor fronts. */
239
+ interface OllamaMessage {
240
+ role: string;
241
+ content: string;
242
+ }
243
+ interface OllamaChatRequest {
244
+ model?: string;
245
+ messages?: OllamaMessage[];
246
+ prompt?: string;
247
+ system?: string;
248
+ stream?: boolean;
249
+ options?: {
250
+ temperature?: number;
251
+ num_predict?: number;
252
+ top_p?: number;
253
+ stop?: string[];
254
+ };
255
+ }
256
+ declare function toOpenAiBody(req: OllamaChatRequest, model: string, kind: "chat" | "generate"): Record<string, unknown>;
257
+ /** Converts one non-streaming OpenAI reply into one Ollama reply. */
258
+ declare function fromOpenAiReply(kind: "chat" | "generate", model: string, body: {
259
+ choices?: Array<{
260
+ message?: {
261
+ content?: string | null;
262
+ };
263
+ finish_reason?: string;
264
+ }>;
265
+ usage?: {
266
+ prompt_tokens?: number;
267
+ completion_tokens?: number;
268
+ };
269
+ }): Record<string, unknown>;
270
+ /** Converts an OpenAI event stream into Ollama's newline-delimited JSON. */
271
+ declare function streamToOllama(kind: "chat" | "generate", model: string, body: ReadableStream<Uint8Array>): AsyncGenerator<string>;
272
+
273
+ /**
274
+ * One agent task, held in memory so a UI can watch it (events are kept and replayed to late subscribers), approve commands it wants to
275
+ * run, and then apply or discard what it did. Nothing reaches the project folder until `apply`.
276
+ */
277
+ type SessionEvent = AgentEvent | {
278
+ type: "approval";
279
+ requestId: string;
280
+ command: string;
281
+ network: boolean;
282
+ } | {
283
+ type: "approval_resolved";
284
+ requestId: string;
285
+ allowed: boolean;
286
+ } | {
287
+ type: "applied";
288
+ checkpointId: string;
289
+ files: number;
290
+ } | {
291
+ type: "rolled_back";
292
+ checkpointId: string;
293
+ };
294
+ interface SessionInfo {
295
+ id: string;
296
+ dir: string;
297
+ task: string;
298
+ status: "running" | "finished" | "max_steps" | "aborted" | "stuck" | "error";
299
+ startedAt: string;
300
+ result?: AgentResult;
301
+ diffs: FileDiff[];
302
+ pendingApprovals: Array<{
303
+ requestId: string;
304
+ command: string;
305
+ network: boolean;
306
+ }>;
307
+ checkpointId?: string;
308
+ gates: GateResult[];
309
+ }
310
+ declare class AgentSession {
311
+ readonly dir: string;
312
+ readonly task: string;
313
+ readonly project: NodeProject;
314
+ readonly ws: ShadowWorkspace;
315
+ private readonly cfg;
316
+ private readonly hostRamBytes;
317
+ readonly id: string;
318
+ readonly events: SessionEvent[];
319
+ readonly startedAt: string;
320
+ status: SessionInfo["status"];
321
+ result?: AgentResult;
322
+ checkpointId?: string;
323
+ private readonly subs;
324
+ private readonly pending;
325
+ private readonly abort;
326
+ private lastDiffs;
327
+ private done;
328
+ constructor(dir: string, task: string, project: NodeProject, ws: ShadowWorkspace, cfg: ClutorConfig, hostRamBytes: number);
329
+ private push;
330
+ /** Replays everything so far, then streams new events until the task ends. Returns a function that stops listening. */
331
+ subscribe(from: number, send: (e: SessionEvent) => void, onEnd: () => void): () => void;
332
+ start(llm: LlmClient): void;
333
+ wait(): Promise<void>;
334
+ private askApproval;
335
+ resolveApproval(requestId: string, allow: boolean): boolean;
336
+ stop(): void;
337
+ /** Writes the agent's changes to the project (after checking nothing changed under it), with a checkpoint to roll back to. */
338
+ apply(force?: boolean): Promise<{
339
+ checkpointId: string;
340
+ files: number;
341
+ }>;
342
+ rollback(force?: boolean): Promise<void>;
343
+ info(): Promise<SessionInfo>;
344
+ }
345
+
346
+ /** A project directory the server may work in: it must exist, be a directory, and is stored by its real path (links resolved). */
347
+ declare function normaliseRoot(dir: string): Promise<string>;
348
+ declare const isInside: (root: string, p: string) => boolean;
349
+
350
+ interface ServerOptions {
351
+ root: string;
352
+ config: ClutorConfig;
353
+ version: string;
354
+ backend?: BackendManager;
355
+ /** Starts the model (llama-server) on request. Provided by whoever owns the configuration. */
356
+ startBackend?: () => Promise<void>;
357
+ /** Folders the server may work in from the start (the CLI passes the current folder). */
358
+ roots?: string[];
359
+ /** Fixed token for tests; otherwise random. */
360
+ token?: string;
361
+ fetch?: typeof globalThis.fetch;
362
+ log?: (line: string) => void;
363
+ }
364
+ interface ClutorServer {
365
+ readonly http: Server;
366
+ readonly token: string;
367
+ listen(): Promise<{
368
+ host: string;
369
+ port: number;
370
+ }>;
371
+ close(): Promise<void>;
372
+ addRoot(dir: string): Promise<string>;
373
+ readonly sessions: Map<string, AgentSession>;
374
+ }
375
+ declare function createClutorServer(o: ServerOptions): ClutorServer;
376
+
377
+ /** Parses a text/event-stream body into the `data:` payloads, in order. */
378
+ declare function parseSse(body: ReadableStream<Uint8Array>): AsyncGenerator<string>;
379
+
380
+ /**
381
+ * A Model Context Protocol server (JSON-RPC 2.0 over HTTP) with read-only tools, so an editor or agent that speaks MCP can ask Clutor
382
+ * about a project and about whether a model fits. It cannot change files or run commands.
383
+ */
384
+ interface Rpc {
385
+ jsonrpc?: string;
386
+ id?: string | number | null;
387
+ method?: string;
388
+ params?: Record<string, unknown>;
389
+ }
390
+ declare function handleMcp(req: Rpc, ctx: {
391
+ isRoot(dir: string): Promise<string | null>;
392
+ }): Promise<{
393
+ status: number;
394
+ body: unknown;
395
+ }>;
396
+
397
+ interface Io {
398
+ out(line: string): void;
399
+ err(line: string): void;
400
+ cwd: string;
401
+ /** Asks the user a question and returns the answer. Absent when there is no terminal. */
402
+ prompt?(question: string): Promise<string>;
403
+ }
404
+ /** State that survives from one task to the next inside an interactive session (see repl.ts). One-shot commands run without it. */
405
+ interface SessionState {
406
+ /** The model server, started on the first task and kept for the rest of the session. */
407
+ backend?: BackendManager;
408
+ /** Check to run after each task; set with /verify. It is the user's own command, so it runs without asking. */
409
+ verify?: string;
410
+ /** Run commands without asking (/yes). */
411
+ auto: boolean;
412
+ /** Checkpoint of the last applied task, for /undo. */
413
+ lastCheckpoint?: {
414
+ id: string;
415
+ dir: string;
416
+ };
417
+ /** One line per finished task, given to the next task so the agent knows what already happened. */
418
+ notes: string[];
419
+ /** Tokens the model server reported, summed over the session (measured, not estimated). */
420
+ usage: {
421
+ promptTokens: number;
422
+ completionTokens: number;
423
+ };
424
+ }
425
+ declare const version: () => string;
426
+ declare function main(argv: string[], io: Io, session?: SessionState): Promise<number>;
427
+ /** Starts llama-server if the configuration asks for it, and returns the manager. */
428
+ declare function startBackendIfConfigured(config: ClutorConfig, io: Io, existing?: BackendManager): Promise<BackendManager | undefined>;
429
+
430
+ /**
431
+ * The interactive session that `clutor` opens when it is started with no command in a terminal. Text you type is a task for the coding
432
+ * agent (its changes are held aside until you approve them); a line starting with `/` is a command. Most commands are the ordinary
433
+ * clutor commands, so they behave exactly as they do outside the session.
434
+ */
435
+ type Run = (argv: string[], session: SessionState) => Promise<number>;
436
+ type EngineView = (config: ClutorConfig, what: "layers" | "cache") => Promise<void>;
437
+ /** Splits a line into words, honouring single and double quotes. */
438
+ declare function splitWords(line: string): string[];
439
+ declare function runRepl(io: Io, run: Run, engine: EngineView): Promise<number>;
440
+
441
+ /** Where llama-server saves KV-cache snapshots. They contain the project map the model read, so they stay in the user's own home folder. */
442
+ declare const slotDir: () => string;
443
+ /** llama-server refuses `--slot-save-path` for a folder that does not exist, so make it before starting. */
444
+ declare function ensureSlotDir(): string;
445
+ /**
446
+ * The model client the agent uses. Against a local llama-server it (1) constrains decoding to the tool-call JSON Schema, (2) keeps the
447
+ * conversation in one slot so the server reuses its cached prefix between steps, and (3) saves and restores that prefix between runs.
448
+ * Against any other OpenAI-compatible server only (1) is attempted, and dropped automatically if the server refuses it.
449
+ */
450
+ declare function agentLlm(config: ClutorConfig, ep: {
451
+ baseUrl: string;
452
+ model: string;
453
+ apiKey?: string;
454
+ local: boolean;
455
+ }, fetchFn?: typeof globalThis.fetch): LlmClient;
456
+
457
+ /**
458
+ * The native engine (c/): a C program that reads a GGUF file directly and streams its experts from disk through Clutor's cache.
459
+ * It does not run a transformer yet. What it measures is real (bytes read, time spent waiting for them, cache and prefetch behaviour);
460
+ * what it routes with is a synthetic router, and every report says so.
461
+ */
462
+ declare class EngineError extends Error {
463
+ constructor(message: string);
464
+ }
465
+ /** The `c/` folder of a source checkout (absent in an installed package). */
466
+ declare function engineSourceDir(): string;
467
+ declare function findEngine(env?: NodeJS.ProcessEnv): string | undefined;
468
+ declare function run(bin: string, args: string[], opts?: {
469
+ timeoutMs?: number;
470
+ cwd?: string;
471
+ }): Promise<{
472
+ code: number;
473
+ stdout: string;
474
+ stderr: string;
475
+ }>;
476
+ /** Compiles the engine from source with `make` (needs a C compiler). Returns the path of the binary. */
477
+ declare function buildEngine(): Promise<string>;
478
+ interface EngineInfo {
479
+ arch: string;
480
+ name: string;
481
+ layers: number;
482
+ experts: number;
483
+ expertsUsed: number;
484
+ moeLayers: number;
485
+ residentBytes: number;
486
+ maxDenseBytes: number;
487
+ maxExpertBytes: number;
488
+ totalBytes: number;
489
+ unsizedTensors: number;
490
+ layerTable: Array<{
491
+ denseBytes: number;
492
+ expertBytes: number;
493
+ routerBytes: number;
494
+ }>;
495
+ }
496
+ interface StreamOptions {
497
+ tokens?: number;
498
+ warmup?: number;
499
+ cacheMb?: number;
500
+ stage?: number;
501
+ policy?: "lru" | "wtinylfu" | "adaptive";
502
+ smart?: string;
503
+ prefetch?: boolean;
504
+ ioThreads?: number;
505
+ seed?: number;
506
+ locality?: number;
507
+ predictCorr?: number;
508
+ computeUs?: number;
509
+ windowPct?: number;
510
+ noOsCache?: boolean;
511
+ /** auto: keep the dense weights in RAM when they fit in a quarter of it; ring: re-read two layers at a time every token. */
512
+ dense?: "auto" | "resident" | "ring";
513
+ /** kernel: a Q4_0 x Q8_0 dot-product kernel over every loaded byte (default); checksum: a cheap hash, so the run measures I/O alone. */
514
+ compute?: "kernel" | "checksum";
515
+ /** Scenario: measured tokens [at, at+len) route uniformly at random (scan noise); all others use one fixed tight topic. */
516
+ shift?: {
517
+ at: number;
518
+ len: number;
519
+ };
520
+ /** Record hits and peak RSS every N measured tokens. */
521
+ window?: number;
522
+ }
523
+ interface StreamReport {
524
+ provenance: {
525
+ routing: string;
526
+ disk: string;
527
+ compute: string;
528
+ };
529
+ model: {
530
+ name: string;
531
+ arch: string;
532
+ layers: number;
533
+ experts: number;
534
+ expertsUsed: number;
535
+ expertBytes: number;
536
+ };
537
+ config: {
538
+ policy: string;
539
+ cacheSlots: number;
540
+ stageSlots: number;
541
+ smartRoute: boolean;
542
+ J: number;
543
+ M: number;
544
+ tau: number;
545
+ denseMode: "resident" | "ring";
546
+ densePreloadBytes: number;
547
+ computeMode: "kernel" | "checksum";
548
+ computeKernel: string;
549
+ prefetch: boolean;
550
+ ioThreads: number;
551
+ osCacheBypass: boolean;
552
+ tokens: number;
553
+ warmup: number;
554
+ seed: number;
555
+ locality: number;
556
+ predictCorr: number;
557
+ };
558
+ totals: {
559
+ accesses: number;
560
+ hits: number;
561
+ stageHits: number;
562
+ misses: number;
563
+ bypass: number;
564
+ hitRate: number;
565
+ substituted: number;
566
+ droppedMass: number;
567
+ maxDeltaP: number;
568
+ admitRejects: number;
569
+ evictions: number;
570
+ prefetchIssued: number;
571
+ prefetchLate: number;
572
+ prefetchWasted: number;
573
+ demandBytes: number;
574
+ prefetchBytes: number;
575
+ denseBytes: number;
576
+ wallSeconds: number;
577
+ ioWaitSeconds: number;
578
+ computeSeconds: number;
579
+ readSecondsTotal: number;
580
+ overlap: number;
581
+ tokensPerSecond: number;
582
+ gbPerToken: number;
583
+ missesPerToken: number;
584
+ checksum: string;
585
+ };
586
+ /** ru_maxrss of the engine process, bytes: before it allocated anything, and at the end of the run. */
587
+ rss: {
588
+ startBytes: number;
589
+ peakBytes: number; /** Process baseline plus every buffer and table the run allocates, all pages touched. */
590
+ predictedBytes: number;
591
+ };
592
+ scenario: {
593
+ shiftAt: number;
594
+ shiftLen: number;
595
+ };
596
+ windows: Array<{
597
+ tokEnd: number;
598
+ accesses: number;
599
+ hits: number;
600
+ peakRssBytes: number;
601
+ }>;
602
+ layers: Array<{
603
+ layer: number;
604
+ accesses: number;
605
+ hits: number;
606
+ misses: number;
607
+ substituted: number;
608
+ ioWaitSeconds: number;
609
+ }>;
610
+ }
611
+ declare function engineInfo(bin: string, file: string): Promise<EngineInfo>;
612
+ declare function engineStream(bin: string, file: string, o?: StreamOptions, timeoutMs?: number): Promise<StreamReport>;
613
+
614
+ export { AgentSession, BackendManager, CONFIG_FILE, ConfigError, ConfigSchema, DEFAULT_PORT, DOWNLOADS, DecideError, DownloadError, EngineError, ModelError, SlotSnapshots, UsageError, agentLlm, buildEngine, buildLlamaArgs, createClutorServer, downloadFile, downloadUrl, engineInfo, engineSourceDir, engineStream, ensureSlotDir, findEngine, findLlamaServer, flagBool, flagInt, flagString, formatGates, formatPlan, formatSimulation, fromOpenAiReply, handleMcp, isInside, listLocalModels, loadConfig, main, normaliseRoot, parseArgs, parseSse, pct, probeLlamaServer, resolveModel, run, runDecide, runRepl, sealDecision, slotDir, splitWords, startBackendIfConfigured, streamToOllama, table, toOpenAiBody, tps, version, withPrefixSnapshots };
615
+ export type { BackendState, ClutorConfig, ClutorServer, DecideEndpoint, DecideResult, Download, EngineInfo, Io, LlamaArgsInput, LlamaCapabilities, LocalModel, OllamaChatRequest, OllamaMessage, ParsedArgs, ResolvedModel, ServerOptions, SessionEvent, SessionInfo, SessionState, StreamOptions, StreamReport };