@danypops/jittor 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -7
- package/docs/BENCHMARK_SOURCES.md +32 -0
- package/docs/OUTPUT_CHANNELS.md +31 -0
- package/docs/PROVIDER_RESEARCH.md +38 -0
- package/extension/src/benchmark-tui.ts +103 -0
- package/extension/src/footer.ts +43 -3
- package/extension/src/index.ts +196 -33
- package/extension/src/tui.ts +32 -7
- package/extension/src/usage.ts +147 -38
- package/package.json +1 -1
- package/src/adapters/metric-benchmark-store.ts +99 -0
- package/src/adapters/openrouter-benchmark-index-source.ts +93 -0
- package/src/adapters/openrouter-benchmark-source.ts +109 -0
- package/src/cli.ts +531 -9
- package/src/constants.ts +38 -1
- package/src/daemon.ts +23 -2
- package/src/domain/benchmark.ts +264 -0
- package/src/domain/context-telemetry.ts +31 -0
- package/src/domain/metric.ts +46 -5
- package/src/domain/model-observation.ts +181 -0
- package/src/domain/model-ranking-service.ts +40 -0
- package/src/domain/model-ranking.ts +213 -0
- package/src/domain/usage.ts +84 -7
- package/src/ports/benchmark-controller.ts +11 -0
- package/src/ports/benchmark-source.ts +7 -0
- package/src/ports/benchmark-store.ts +7 -0
- package/src/ports/router-controller.ts +1 -0
- package/src/providers/anthropic-contracts.ts +116 -0
- package/src/providers/google-vertex-contracts.ts +104 -0
- package/src/router.ts +12 -0
- package/src/service.ts +60 -3
package/src/cli.ts
CHANGED
|
@@ -4,16 +4,39 @@ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { dirname, join } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import {
|
|
8
|
-
|
|
7
|
+
import {
|
|
8
|
+
BENCHMARK_MAX_QUERY_LIMIT,
|
|
9
|
+
CLI_AVAILABLE_ROUTES_MAX,
|
|
10
|
+
CLI_METRICS_HUMAN_MAX_ROWS,
|
|
11
|
+
HUMAN_TEXT_FIELD_MAX_CHARACTERS,
|
|
12
|
+
MAX_QUERY_LIMIT,
|
|
13
|
+
MODEL_RANKING_DEFAULT_CONTEXT_WEIGHT,
|
|
14
|
+
MODEL_RANKING_DEFAULT_COST_WEIGHT,
|
|
15
|
+
MODEL_RANKING_DEFAULT_LATENCY_WEIGHT,
|
|
16
|
+
MODEL_RANKING_DEFAULT_QUALITY_WEIGHT,
|
|
17
|
+
MODEL_RANKING_DEFAULT_RELIABILITY_WEIGHT,
|
|
18
|
+
MODEL_RANKING_MAX_SOURCES,
|
|
19
|
+
SYSTEMD_UNIT_NAME,
|
|
20
|
+
} from "./constants.ts";
|
|
21
|
+
import { connectJittorClient, type JittorClient } from "./client.ts";
|
|
9
22
|
import { serveMain } from "./daemon.ts";
|
|
23
|
+
import type { BenchmarkQuery, BenchmarkQueryResult, BenchmarkRefreshResult } from "./domain/benchmark.ts";
|
|
24
|
+
import type { ModelRecommendationInput } from "./domain/model-ranking-service.ts";
|
|
25
|
+
import type { ModelCandidate, ModelRankingResult, ScopeAuthority, UtilityWeights } from "./domain/model-ranking.ts";
|
|
26
|
+
import { TASK_CLASSES, type ModelTaskClass } from "./domain/model-observation.ts";
|
|
10
27
|
import type { ContextAssessment } from "./domain/context-telemetry.ts";
|
|
28
|
+
import { METRIC_UNITS, type MetricObservation, type MetricQuery, type MetricUnit, type StoredMetricObservation } from "./domain/metric.ts";
|
|
29
|
+
import type { CompactionDurationEstimate } from "./domain/context-telemetry.ts";
|
|
30
|
+
import type { PolicyDecision, Route } from "./policy.ts";
|
|
31
|
+
import type { RouteOverride, RouterStatus, TelemetryPollResult } from "./ports/router-controller.ts";
|
|
32
|
+
import { EXPECTED_OPERATION_NAMES, type OperationInputs, type OperationName, type OperationOutputs } from "./service.ts";
|
|
11
33
|
import { resolveJittorPaths } from "./state.ts";
|
|
12
34
|
|
|
13
35
|
export interface SystemdUnitOptions {
|
|
14
36
|
bunBin: string;
|
|
15
37
|
cliPath: string;
|
|
16
38
|
codexAuthFile?: string;
|
|
39
|
+
openRouterBenchmarks?: boolean;
|
|
17
40
|
}
|
|
18
41
|
|
|
19
42
|
export function renderSystemdUnit(options: SystemdUnitOptions): string {
|
|
@@ -25,7 +48,7 @@ Wants=network-online.target
|
|
|
25
48
|
[Service]
|
|
26
49
|
Type=simple
|
|
27
50
|
ExecStart=${options.bunBin} ${options.cliPath} serve
|
|
28
|
-
${options.codexAuthFile ? `Environment="JITTOR_CODEX_AUTH_FILE=${options.codexAuthFile.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"\n` : ""}Restart=always
|
|
51
|
+
${options.codexAuthFile ? `Environment="JITTOR_CODEX_AUTH_FILE=${options.codexAuthFile.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"\n` : ""}${options.openRouterBenchmarks ? "Environment=JITTOR_OPENROUTER_BENCHMARKS=1\n" : ""}Restart=always
|
|
29
52
|
RestartSec=2
|
|
30
53
|
NoNewPrivileges=true
|
|
31
54
|
PrivateTmp=true
|
|
@@ -35,12 +58,8 @@ WantedBy=default.target
|
|
|
35
58
|
`;
|
|
36
59
|
}
|
|
37
60
|
|
|
38
|
-
interface ContextClient {
|
|
39
|
-
call(operation: "context.assess", input: { since?: number; until?: number }): Promise<ContextAssessment>;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
61
|
export interface CliDependencies {
|
|
43
|
-
client:
|
|
62
|
+
client: Pick<JittorClient, "call">;
|
|
44
63
|
stdout(line: string): void;
|
|
45
64
|
stderr(line: string): void;
|
|
46
65
|
systemctl(...args: string[]): void;
|
|
@@ -60,6 +79,7 @@ function installService(): void {
|
|
|
60
79
|
bunBin: process.execPath,
|
|
61
80
|
cliPath: fileURLToPath(import.meta.url),
|
|
62
81
|
...(existsSync(codexAuthFile) ? { codexAuthFile } : {}),
|
|
82
|
+
openRouterBenchmarks: process.env["JITTOR_OPENROUTER_BENCHMARKS"] === "1",
|
|
63
83
|
}));
|
|
64
84
|
systemctl("daemon-reload");
|
|
65
85
|
systemctl("enable", SYSTEMD_UNIT_NAME);
|
|
@@ -76,7 +96,23 @@ const DEFAULT_DEPENDENCIES: CliDependencies = {
|
|
|
76
96
|
};
|
|
77
97
|
|
|
78
98
|
function usage(stderr: (line: string) => void): number {
|
|
79
|
-
stderr(
|
|
99
|
+
stderr([
|
|
100
|
+
"Usage: jittor <command> [options]",
|
|
101
|
+
" serve",
|
|
102
|
+
" service <install|start|stop|restart|status|checkpoint>",
|
|
103
|
+
" context [--since <ms>] [--until <ms>] [--json]",
|
|
104
|
+
" benchmarks <status|refresh|list|rank> [options] [--json]",
|
|
105
|
+
" metrics record --source <s> --scope <s> --metric <s> --value <number|null> --unit <unit> [--observed-at <ms>] [--attributes <json>] [--json]",
|
|
106
|
+
" metrics query [--source <s>] [--scope <s>] [--metric <s>] [--since <ms>] [--until <ms>] [--limit <n>] [--order asc|desc] [--json]",
|
|
107
|
+
" metrics prune --before <ms> [--json]",
|
|
108
|
+
" telemetry poll [--json]",
|
|
109
|
+
" compaction estimate [--json]",
|
|
110
|
+
" router <status|decide|pause|resume|clear-override> [--json]",
|
|
111
|
+
" router override --route <provider/model@thinking> [--expires-at <ms>] [--json]",
|
|
112
|
+
" router current-route --route <provider/model@thinking> [--json]",
|
|
113
|
+
" router available-routes [--route <provider/model@thinking> ...] [--json]",
|
|
114
|
+
" op <operation> [--input <json>]",
|
|
115
|
+
].join("\n"));
|
|
80
116
|
return 2;
|
|
81
117
|
}
|
|
82
118
|
|
|
@@ -97,10 +133,313 @@ function parseContextArgs(args: string[]): { input: { since?: number; until?: nu
|
|
|
97
133
|
return { input, json };
|
|
98
134
|
}
|
|
99
135
|
|
|
136
|
+
function parseRoute(raw: string | undefined): Route | null {
|
|
137
|
+
if (raw === undefined) return null;
|
|
138
|
+
return parseCandidate(raw);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
interface MetricsRecordArgs { input: MetricObservation; json: boolean }
|
|
142
|
+
|
|
143
|
+
function parseMetricsRecordArgs(args: string[]): MetricsRecordArgs | null {
|
|
144
|
+
let json = false;
|
|
145
|
+
let source: string | undefined;
|
|
146
|
+
let scope: string | undefined;
|
|
147
|
+
let metric: string | undefined;
|
|
148
|
+
let value: number | null | undefined;
|
|
149
|
+
let unit: MetricUnit | undefined;
|
|
150
|
+
let observedAt: number | undefined;
|
|
151
|
+
let attributes: Record<string, unknown> | undefined;
|
|
152
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
153
|
+
const argument = args[index];
|
|
154
|
+
if (argument === "--json") { json = true; continue; }
|
|
155
|
+
if (!["--source", "--scope", "--metric", "--value", "--unit", "--observed-at", "--attributes"].includes(argument ?? "")) return null;
|
|
156
|
+
const raw = args[++index];
|
|
157
|
+
if (raw === undefined || raw.length === 0) return null;
|
|
158
|
+
if (argument === "--source") source = raw;
|
|
159
|
+
else if (argument === "--scope") scope = raw;
|
|
160
|
+
else if (argument === "--metric") metric = raw;
|
|
161
|
+
else if (argument === "--value") {
|
|
162
|
+
if (raw.toLowerCase() === "null") value = null;
|
|
163
|
+
else {
|
|
164
|
+
const parsed = Number(raw);
|
|
165
|
+
if (!Number.isFinite(parsed)) return null;
|
|
166
|
+
value = parsed;
|
|
167
|
+
}
|
|
168
|
+
} else if (argument === "--unit") {
|
|
169
|
+
if (!METRIC_UNITS.includes(raw as MetricUnit)) return null;
|
|
170
|
+
unit = raw as MetricUnit;
|
|
171
|
+
} else if (argument === "--observed-at") {
|
|
172
|
+
const parsed = Number(raw);
|
|
173
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0) return null;
|
|
174
|
+
observedAt = parsed;
|
|
175
|
+
} else {
|
|
176
|
+
try {
|
|
177
|
+
const parsed = JSON.parse(raw);
|
|
178
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return null;
|
|
179
|
+
attributes = parsed as Record<string, unknown>;
|
|
180
|
+
} catch {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (source === undefined || scope === undefined || metric === undefined || value === undefined || unit === undefined) return null;
|
|
186
|
+
return {
|
|
187
|
+
json,
|
|
188
|
+
input: {
|
|
189
|
+
source, scope, metric, value, unit,
|
|
190
|
+
observedAt: observedAt ?? Date.now(),
|
|
191
|
+
...(attributes ? { attributes } : {}),
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
interface MetricsQueryArgs { input: MetricQuery; json: boolean }
|
|
197
|
+
|
|
198
|
+
function parseMetricsQueryArgs(args: string[]): MetricsQueryArgs | null {
|
|
199
|
+
let json = false;
|
|
200
|
+
const input: MetricQuery = {};
|
|
201
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
202
|
+
const argument = args[index];
|
|
203
|
+
if (argument === "--json") { json = true; continue; }
|
|
204
|
+
if (!["--source", "--scope", "--metric", "--since", "--until", "--limit", "--order"].includes(argument ?? "")) return null;
|
|
205
|
+
const raw = args[++index];
|
|
206
|
+
if (raw === undefined || raw.length === 0) return null;
|
|
207
|
+
if (argument === "--source") input.source = raw;
|
|
208
|
+
else if (argument === "--scope") input.scope = raw;
|
|
209
|
+
else if (argument === "--metric") input.metric = raw;
|
|
210
|
+
else if (argument === "--order") {
|
|
211
|
+
if (raw !== "asc" && raw !== "desc") return null;
|
|
212
|
+
input.order = raw;
|
|
213
|
+
} else {
|
|
214
|
+
const parsed = Number(raw);
|
|
215
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0) return null;
|
|
216
|
+
if (argument === "--since") input.since = parsed;
|
|
217
|
+
else if (argument === "--until") input.until = parsed;
|
|
218
|
+
else {
|
|
219
|
+
if (parsed < 1 || parsed > MAX_QUERY_LIMIT) return null;
|
|
220
|
+
input.limit = parsed;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (input.since !== undefined && input.until !== undefined && input.until < input.since) return null;
|
|
225
|
+
return { input, json };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
interface MetricsPruneArgs { input: { before: number }; json: boolean }
|
|
229
|
+
|
|
230
|
+
function parseMetricsPruneArgs(args: string[]): MetricsPruneArgs | null {
|
|
231
|
+
let json = false;
|
|
232
|
+
let before: number | undefined;
|
|
233
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
234
|
+
const argument = args[index];
|
|
235
|
+
if (argument === "--json") { json = true; continue; }
|
|
236
|
+
if (argument !== "--before") return null;
|
|
237
|
+
const raw = args[++index];
|
|
238
|
+
const parsed = Number(raw);
|
|
239
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0) return null;
|
|
240
|
+
before = parsed;
|
|
241
|
+
}
|
|
242
|
+
if (before === undefined) return null;
|
|
243
|
+
return { input: { before }, json };
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
interface RouterOverrideArgs { input: RouteOverride; json: boolean }
|
|
247
|
+
|
|
248
|
+
function parseRouterOverrideArgs(args: string[]): RouterOverrideArgs | null {
|
|
249
|
+
let json = false;
|
|
250
|
+
let route: Route | null = null;
|
|
251
|
+
let expiresAt: number | null = null;
|
|
252
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
253
|
+
const argument = args[index];
|
|
254
|
+
if (argument === "--json") { json = true; continue; }
|
|
255
|
+
if (!["--route", "--expires-at"].includes(argument ?? "")) return null;
|
|
256
|
+
const raw = args[++index];
|
|
257
|
+
if (raw === undefined || raw.length === 0) return null;
|
|
258
|
+
if (argument === "--route") {
|
|
259
|
+
route = parseRoute(raw);
|
|
260
|
+
if (!route) return null;
|
|
261
|
+
} else {
|
|
262
|
+
const parsed = Number(raw);
|
|
263
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0) return null;
|
|
264
|
+
expiresAt = parsed;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (!route) return null;
|
|
268
|
+
return { input: { route, expiresAt }, json };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
interface RouterRouteArgs { input: Route; json: boolean }
|
|
272
|
+
|
|
273
|
+
function parseRouterRouteArgs(args: string[]): RouterRouteArgs | null {
|
|
274
|
+
let json = false;
|
|
275
|
+
let route: Route | null = null;
|
|
276
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
277
|
+
const argument = args[index];
|
|
278
|
+
if (argument === "--json") { json = true; continue; }
|
|
279
|
+
if (argument !== "--route") return null;
|
|
280
|
+
const raw = args[++index];
|
|
281
|
+
if (raw === undefined) return null;
|
|
282
|
+
route = parseRoute(raw);
|
|
283
|
+
if (!route) return null;
|
|
284
|
+
}
|
|
285
|
+
if (!route) return null;
|
|
286
|
+
return { input: route, json };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
interface RouterAvailableRoutesArgs { input: { routes: Route[] }; json: boolean }
|
|
290
|
+
|
|
291
|
+
function parseRouterAvailableRoutesArgs(args: string[]): RouterAvailableRoutesArgs | null {
|
|
292
|
+
let json = false;
|
|
293
|
+
const routes: Route[] = [];
|
|
294
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
295
|
+
const argument = args[index];
|
|
296
|
+
if (argument === "--json") { json = true; continue; }
|
|
297
|
+
if (argument !== "--route") return null;
|
|
298
|
+
const raw = args[++index];
|
|
299
|
+
if (raw === undefined) return null;
|
|
300
|
+
const route = parseRoute(raw);
|
|
301
|
+
if (!route) return null;
|
|
302
|
+
if (routes.length >= CLI_AVAILABLE_ROUTES_MAX) return null;
|
|
303
|
+
routes.push(route);
|
|
304
|
+
}
|
|
305
|
+
return { input: { routes }, json };
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function parseJsonOnlyArgs(args: string[]): { json: boolean } | null {
|
|
309
|
+
let json = false;
|
|
310
|
+
for (const argument of args) {
|
|
311
|
+
if (argument !== "--json") return null;
|
|
312
|
+
json = true;
|
|
313
|
+
}
|
|
314
|
+
return { json };
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function parseOpArgs(args: string[]): { operation: OperationName; input: Record<string, unknown> } | null {
|
|
318
|
+
const [operation, ...rest] = args;
|
|
319
|
+
if (operation === undefined || !EXPECTED_OPERATION_NAMES.includes(operation as OperationName)) return null;
|
|
320
|
+
let input: Record<string, unknown> = {};
|
|
321
|
+
for (let index = 0; index < rest.length; index += 1) {
|
|
322
|
+
if (rest[index] !== "--input") return null;
|
|
323
|
+
const raw = rest[++index];
|
|
324
|
+
if (raw === undefined) return null;
|
|
325
|
+
try {
|
|
326
|
+
const parsed = JSON.parse(raw);
|
|
327
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return null;
|
|
328
|
+
input = parsed as Record<string, unknown>;
|
|
329
|
+
} catch {
|
|
330
|
+
return null;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return { operation: operation as OperationName, input };
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
interface BenchmarkArgs {
|
|
337
|
+
action: "status" | "refresh" | "list" | "rank";
|
|
338
|
+
json: boolean;
|
|
339
|
+
force: boolean;
|
|
340
|
+
query?: BenchmarkQuery;
|
|
341
|
+
recommendation?: ModelRecommendationInput;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function parseCandidate(raw: string): ModelCandidate | null {
|
|
345
|
+
const separator = raw.indexOf("/");
|
|
346
|
+
const thinkingSeparator = raw.lastIndexOf("@");
|
|
347
|
+
if (separator <= 0 || thinkingSeparator <= separator + 1 || thinkingSeparator === raw.length - 1) return null;
|
|
348
|
+
return { provider: raw.slice(0, separator), model: raw.slice(separator + 1, thinkingSeparator), thinking: raw.slice(thinkingSeparator + 1) };
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function parseBenchmarkArgs(action: string | undefined, args: string[]): BenchmarkArgs | null {
|
|
352
|
+
if (action !== "status" && action !== "refresh" && action !== "list" && action !== "rank") return null;
|
|
353
|
+
let json = false;
|
|
354
|
+
let force = false;
|
|
355
|
+
const query: Partial<BenchmarkQuery> = {};
|
|
356
|
+
const candidates: ModelCandidate[] = [];
|
|
357
|
+
const sourceIds: string[] = [];
|
|
358
|
+
let scopeAuthority: ScopeAuthority = "available-models";
|
|
359
|
+
let taskClass: ModelTaskClass = "general";
|
|
360
|
+
let budgetPressure = 0;
|
|
361
|
+
const weights: UtilityWeights = {
|
|
362
|
+
quality: MODEL_RANKING_DEFAULT_QUALITY_WEIGHT, cost: MODEL_RANKING_DEFAULT_COST_WEIGHT,
|
|
363
|
+
latency: MODEL_RANKING_DEFAULT_LATENCY_WEIGHT, context: MODEL_RANKING_DEFAULT_CONTEXT_WEIGHT,
|
|
364
|
+
reliability: MODEL_RANKING_DEFAULT_RELIABILITY_WEIGHT,
|
|
365
|
+
};
|
|
366
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
367
|
+
const argument = args[index];
|
|
368
|
+
if (argument === "--json") { json = true; continue; }
|
|
369
|
+
if (argument === "--force" && action === "refresh") { force = true; continue; }
|
|
370
|
+
const allowed = action === "list" ? ["--source", "--model", "--dimension", "--limit"]
|
|
371
|
+
: action === "rank" ? ["--candidate", "--source", "--task", "--scope", "--budget", "--weight-quality", "--weight-cost", "--weight-latency", "--weight-context", "--weight-reliability"] : [];
|
|
372
|
+
if (!allowed.includes(argument ?? "")) return null;
|
|
373
|
+
const raw = args[++index];
|
|
374
|
+
if (raw === undefined || raw.length === 0) return null;
|
|
375
|
+
if (action === "list") {
|
|
376
|
+
if (argument === "--limit") {
|
|
377
|
+
const limit = Number(raw);
|
|
378
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > BENCHMARK_MAX_QUERY_LIMIT) return null;
|
|
379
|
+
query.limit = limit;
|
|
380
|
+
} else if (argument === "--source") query.sourceId = raw;
|
|
381
|
+
else if (argument === "--model") query.model = raw;
|
|
382
|
+
else query.dimension = raw;
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
if (argument === "--candidate") {
|
|
386
|
+
const candidate = parseCandidate(raw);
|
|
387
|
+
if (!candidate) return null;
|
|
388
|
+
candidates.push(candidate);
|
|
389
|
+
} else if (argument === "--source") sourceIds.push(raw);
|
|
390
|
+
else if (argument === "--task") {
|
|
391
|
+
if (!TASK_CLASSES.includes(raw as ModelTaskClass)) return null;
|
|
392
|
+
taskClass = raw as ModelTaskClass;
|
|
393
|
+
} else if (argument === "--scope") {
|
|
394
|
+
if (raw !== "exact-session" && raw !== "available-models") return null;
|
|
395
|
+
scopeAuthority = raw;
|
|
396
|
+
} else if (argument === "--budget") budgetPressure = Number(raw);
|
|
397
|
+
else {
|
|
398
|
+
const weight = Number(raw);
|
|
399
|
+
if (!Number.isFinite(weight) || weight < 0 || weight > 10) return null;
|
|
400
|
+
weights[argument!.slice("--weight-".length) as keyof UtilityWeights] = weight;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
if (action === "list" && query.sourceId === undefined) return null;
|
|
404
|
+
if (action === "rank" && (candidates.length === 0 || sourceIds.length > MODEL_RANKING_MAX_SOURCES || !Number.isFinite(budgetPressure) || budgetPressure < 0 || budgetPressure > 2)) return null;
|
|
405
|
+
return {
|
|
406
|
+
action, json, force,
|
|
407
|
+
...(action === "list" ? { query: query as BenchmarkQuery } : {}),
|
|
408
|
+
...(action === "rank" ? { recommendation: { candidates, sourceIds: [...new Set(sourceIds)], scopeAuthority, taskClass, budgetPressure, weights } } : {}),
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
|
|
100
412
|
function value(value: number | null, suffix = ""): string {
|
|
101
413
|
return value === null ? "unknown" : `${Math.round(value).toLocaleString()}${suffix}`;
|
|
102
414
|
}
|
|
103
415
|
|
|
416
|
+
export function formatBenchmarkStatus(result: BenchmarkRefreshResult): string {
|
|
417
|
+
if (result.sources.length === 0) return "Benchmark sources: none configured";
|
|
418
|
+
return ["Benchmark sources:", ...result.sources.map((source) => {
|
|
419
|
+
const state = source.ok === null ? "not refreshed" : source.ok ? "ready" : "refresh failed";
|
|
420
|
+
return `- ${source.id}: ${state} · ${source.observations.toLocaleString()} observations · ${source.hasEvidence ? "evidence retained" : "no evidence"}`;
|
|
421
|
+
})].join("\n");
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function humanField(value: string): string {
|
|
425
|
+
return value.length <= HUMAN_TEXT_FIELD_MAX_CHARACTERS ? value : `${value.slice(0, HUMAN_TEXT_FIELD_MAX_CHARACTERS - 1)}…`;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
export function formatBenchmarkQuery(result: BenchmarkQueryResult): string {
|
|
429
|
+
return [
|
|
430
|
+
`Benchmark evidence: ${humanField(result.sourceId)} · ${result.completeness} · ${result.freshness} · ${result.observations.length.toLocaleString()} observations`,
|
|
431
|
+
...result.observations.map((observation) => `- ${humanField(observation.model.canonical)} · ${humanField(observation.dimension)} ${observation.value.toLocaleString()} ${observation.unit} · ${humanField(observation.provenance.publisher)} · confidence ${(observation.provenance.confidence * 100).toFixed(0)}%`),
|
|
432
|
+
].join("\n");
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export function formatModelRanking(result: ModelRankingResult): string {
|
|
436
|
+
return [
|
|
437
|
+
`Model ranking: ${result.completeness} · scope ${result.scopeAuthority}${result.scopeWarning ? " · advisory only" : ""}`,
|
|
438
|
+
...result.ranked.map((item, index) => `${index + 1}. ${humanField(item.identity)} · utility ${item.utility === null ? "unknown" : item.utility.toFixed(3)} · confidence ${(item.confidence * 100).toFixed(0)}%`),
|
|
439
|
+
...(result.scopeWarning ? [result.scopeWarning] : []),
|
|
440
|
+
].join("\n");
|
|
441
|
+
}
|
|
442
|
+
|
|
104
443
|
export function formatContextAssessment(summary: ContextAssessment): string {
|
|
105
444
|
return [
|
|
106
445
|
`Context assessment: ${summary.completeness}`,
|
|
@@ -112,9 +451,187 @@ export function formatContextAssessment(summary: ContextAssessment): string {
|
|
|
112
451
|
].join("\n");
|
|
113
452
|
}
|
|
114
453
|
|
|
454
|
+
function formatRoute(route: Route): string {
|
|
455
|
+
return `${humanField(route.provider)}/${humanField(route.model)} · ${humanField(route.thinking)}`;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
export function formatMetricsQuery(rows: StoredMetricObservation[]): string {
|
|
459
|
+
if (rows.length === 0) return "Metrics: no observations matched";
|
|
460
|
+
const shown = rows.slice(0, CLI_METRICS_HUMAN_MAX_ROWS);
|
|
461
|
+
const lines = [
|
|
462
|
+
`Metrics: ${rows.length.toLocaleString()} observation(s)${rows.length > shown.length ? ` (showing first ${shown.length})` : ""}`,
|
|
463
|
+
...shown.map((row) => `- ${humanField(row.source)}/${humanField(row.scope)}/${humanField(row.metric)} = ${row.value === null ? "null" : row.value} ${row.unit} @ ${new Date(row.observedAt).toISOString()}`),
|
|
464
|
+
];
|
|
465
|
+
return lines.join("\n");
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export function formatTelemetryPoll(result: TelemetryPollResult): string {
|
|
469
|
+
if (result.sources.length === 0) return "Telemetry: no sources configured";
|
|
470
|
+
return ["Telemetry:", ...result.sources.map((source) => {
|
|
471
|
+
const freshness = !source.ok ? `failed${source.error ? ` (${humanField(source.error)})` : ""}` : "ok";
|
|
472
|
+
return `- ${humanField(source.id)} (${humanField(source.provider)}): ${freshness} · ${source.metrics} metric(s)`;
|
|
473
|
+
})].join("\n");
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
export function formatRouterStatus(status: RouterStatus): string {
|
|
477
|
+
const lines = [
|
|
478
|
+
`Router: ${status.ready ? "ready" : "not ready"}${status.paused ? " · paused" : ""}`,
|
|
479
|
+
`Current route: ${status.currentRoute ? formatRoute(status.currentRoute) : "none"}`,
|
|
480
|
+
`Available routes: ${status.availableRoutes.length.toLocaleString()}`,
|
|
481
|
+
`Override: ${status.override ? `${formatRoute(status.override.route)}${status.override.expiresAt === null ? "" : ` (expires ${new Date(status.override.expiresAt).toISOString()})`}` : "none"}`,
|
|
482
|
+
];
|
|
483
|
+
if (status.lastDecision) lines.push(`Last decision: ${status.lastDecision.action} · pressure ${Number.isFinite(status.lastDecision.pressure) ? status.lastDecision.pressure.toFixed(3) : "∞"} · ${humanField(status.lastDecision.reason)}`);
|
|
484
|
+
lines.push(formatTelemetryPoll({ sources: status.sources, observedAt: Date.now() }));
|
|
485
|
+
return lines.join("\n");
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
export function formatCompactionEstimate(estimate: CompactionDurationEstimate): string {
|
|
489
|
+
if (estimate.confidence === "cold-start" || estimate.ms === null) {
|
|
490
|
+
return `Compaction duration: cold-start (${estimate.sampleSize.toLocaleString()} sample(s), not enough evidence yet)`;
|
|
491
|
+
}
|
|
492
|
+
return `Compaction duration: ~${estimate.ms.toLocaleString()}ms learned from ${estimate.sampleSize.toLocaleString()} sample(s)`;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
export function formatPolicyDecision(decision: PolicyDecision): string {
|
|
496
|
+
const lines = [`Decision: ${decision.action} · pressure ${Number.isFinite(decision.pressure) ? decision.pressure.toFixed(3) : "∞"} · ${humanField(decision.reason)}`];
|
|
497
|
+
if (decision.route) lines.push(`Route: ${formatRoute(decision.route)}`);
|
|
498
|
+
if (decision.delayMs !== undefined) lines.push(`Delay: ${decision.delayMs}ms`);
|
|
499
|
+
return lines.join("\n");
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
async function callAndPrint<Name extends OperationName>(
|
|
503
|
+
deps: CliDependencies,
|
|
504
|
+
operation: Name,
|
|
505
|
+
input: OperationInputs[Name],
|
|
506
|
+
json: boolean,
|
|
507
|
+
formatHuman: (result: OperationOutputs[Name]) => string,
|
|
508
|
+
): Promise<number> {
|
|
509
|
+
try {
|
|
510
|
+
const result = await deps.client.call(operation, input);
|
|
511
|
+
deps.stdout(json ? JSON.stringify(result) : formatHuman(result));
|
|
512
|
+
return 0;
|
|
513
|
+
} catch (error) {
|
|
514
|
+
deps.stderr(error instanceof Error ? error.message : String(error));
|
|
515
|
+
return 1;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
115
519
|
export async function runCli(args: string[], deps: CliDependencies = DEFAULT_DEPENDENCIES): Promise<number> {
|
|
116
520
|
const [command, action, ...rest] = args;
|
|
117
521
|
if (command === "serve") { deps.serve(); return 0; }
|
|
522
|
+
if (command === "metrics") {
|
|
523
|
+
if (action === "record") {
|
|
524
|
+
const parsed = parseMetricsRecordArgs(rest);
|
|
525
|
+
if (!parsed) return usage(deps.stderr);
|
|
526
|
+
return callAndPrint(deps, "metrics.record", parsed.input, parsed.json, (row) => formatMetricsQuery([row]));
|
|
527
|
+
}
|
|
528
|
+
if (action === "query") {
|
|
529
|
+
const parsed = parseMetricsQueryArgs(rest);
|
|
530
|
+
if (!parsed) return usage(deps.stderr);
|
|
531
|
+
return callAndPrint(deps, "metrics.query", parsed.input, parsed.json, formatMetricsQuery);
|
|
532
|
+
}
|
|
533
|
+
if (action === "prune") {
|
|
534
|
+
const parsed = parseMetricsPruneArgs(rest);
|
|
535
|
+
if (!parsed) return usage(deps.stderr);
|
|
536
|
+
return callAndPrint(deps, "metrics.prune", parsed.input, parsed.json, (result) => `Pruned ${result.deleted.toLocaleString()} observation(s)`);
|
|
537
|
+
}
|
|
538
|
+
return usage(deps.stderr);
|
|
539
|
+
}
|
|
540
|
+
if (command === "telemetry") {
|
|
541
|
+
if (action !== "poll") return usage(deps.stderr);
|
|
542
|
+
const parsed = parseJsonOnlyArgs(rest);
|
|
543
|
+
if (!parsed) return usage(deps.stderr);
|
|
544
|
+
return callAndPrint(deps, "telemetry.poll", {}, parsed.json, formatTelemetryPoll);
|
|
545
|
+
}
|
|
546
|
+
if (command === "compaction") {
|
|
547
|
+
if (action !== "estimate") return usage(deps.stderr);
|
|
548
|
+
const parsed = parseJsonOnlyArgs(rest);
|
|
549
|
+
if (!parsed) return usage(deps.stderr);
|
|
550
|
+
return callAndPrint(deps, "compaction.estimate", {}, parsed.json, formatCompactionEstimate);
|
|
551
|
+
}
|
|
552
|
+
if (command === "router") {
|
|
553
|
+
switch (action) {
|
|
554
|
+
case "status": {
|
|
555
|
+
const parsed = parseJsonOnlyArgs(rest);
|
|
556
|
+
if (!parsed) return usage(deps.stderr);
|
|
557
|
+
return callAndPrint(deps, "router.status", {}, parsed.json, formatRouterStatus);
|
|
558
|
+
}
|
|
559
|
+
case "decide": {
|
|
560
|
+
const parsed = parseJsonOnlyArgs(rest);
|
|
561
|
+
if (!parsed) return usage(deps.stderr);
|
|
562
|
+
return callAndPrint(deps, "router.decide", {}, parsed.json, formatPolicyDecision);
|
|
563
|
+
}
|
|
564
|
+
case "pause": {
|
|
565
|
+
const parsed = parseJsonOnlyArgs(rest);
|
|
566
|
+
if (!parsed) return usage(deps.stderr);
|
|
567
|
+
return callAndPrint(deps, "router.pause", {}, parsed.json, formatRouterStatus);
|
|
568
|
+
}
|
|
569
|
+
case "resume": {
|
|
570
|
+
const parsed = parseJsonOnlyArgs(rest);
|
|
571
|
+
if (!parsed) return usage(deps.stderr);
|
|
572
|
+
return callAndPrint(deps, "router.resume", {}, parsed.json, formatRouterStatus);
|
|
573
|
+
}
|
|
574
|
+
case "clear-override": {
|
|
575
|
+
const parsed = parseJsonOnlyArgs(rest);
|
|
576
|
+
if (!parsed) return usage(deps.stderr);
|
|
577
|
+
return callAndPrint(deps, "router.clear_override", {}, parsed.json, formatRouterStatus);
|
|
578
|
+
}
|
|
579
|
+
case "override": {
|
|
580
|
+
const parsed = parseRouterOverrideArgs(rest);
|
|
581
|
+
if (!parsed) return usage(deps.stderr);
|
|
582
|
+
return callAndPrint(deps, "router.override", parsed.input, parsed.json, formatRouterStatus);
|
|
583
|
+
}
|
|
584
|
+
case "current-route": {
|
|
585
|
+
const parsed = parseRouterRouteArgs(rest);
|
|
586
|
+
if (!parsed) return usage(deps.stderr);
|
|
587
|
+
return callAndPrint(deps, "router.current_route", parsed.input, parsed.json, formatRouterStatus);
|
|
588
|
+
}
|
|
589
|
+
case "available-routes": {
|
|
590
|
+
const parsed = parseRouterAvailableRoutesArgs(rest);
|
|
591
|
+
if (!parsed) return usage(deps.stderr);
|
|
592
|
+
return callAndPrint(deps, "router.available_routes", parsed.input, parsed.json, formatRouterStatus);
|
|
593
|
+
}
|
|
594
|
+
default: return usage(deps.stderr);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
if (command === "op") {
|
|
598
|
+
const parsed = parseOpArgs(action === undefined ? [] : [action, ...rest]);
|
|
599
|
+
if (!parsed) return usage(deps.stderr);
|
|
600
|
+
try {
|
|
601
|
+
// The escape hatch dispatches a dynamically named operation; OperationInputs/OperationOutputs
|
|
602
|
+
// are only known statically per literal operation name, so this one call site is intentionally
|
|
603
|
+
// untyped at the boundary. parseOpArgs already restricts `operation` to EXPECTED_OPERATION_NAMES.
|
|
604
|
+
const call = deps.client.call as (operation: OperationName, input: Record<string, unknown>) => Promise<unknown>;
|
|
605
|
+
const result = await call(parsed.operation, parsed.input);
|
|
606
|
+
deps.stdout(JSON.stringify(result));
|
|
607
|
+
return 0;
|
|
608
|
+
} catch (error) {
|
|
609
|
+
deps.stderr(error instanceof Error ? error.message : String(error));
|
|
610
|
+
return 1;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if (command === "benchmarks") {
|
|
614
|
+
const parsed = parseBenchmarkArgs(action, rest);
|
|
615
|
+
if (!parsed) return usage(deps.stderr);
|
|
616
|
+
try {
|
|
617
|
+
if (parsed.action === "list") {
|
|
618
|
+
const result = await deps.client.call("benchmark.query", parsed.query!);
|
|
619
|
+
deps.stdout(parsed.json ? JSON.stringify(result) : formatBenchmarkQuery(result));
|
|
620
|
+
} else if (parsed.action === "rank") {
|
|
621
|
+
const result = await deps.client.call("models.rank", parsed.recommendation!);
|
|
622
|
+
deps.stdout(parsed.json ? JSON.stringify(result) : formatModelRanking(result));
|
|
623
|
+
} else {
|
|
624
|
+
const result = parsed.action === "refresh"
|
|
625
|
+
? await deps.client.call("benchmark.refresh", { force: parsed.force })
|
|
626
|
+
: await deps.client.call("benchmark.status", {});
|
|
627
|
+
deps.stdout(parsed.json ? JSON.stringify(result) : formatBenchmarkStatus(result));
|
|
628
|
+
}
|
|
629
|
+
return 0;
|
|
630
|
+
} catch (error) {
|
|
631
|
+
deps.stderr(error instanceof Error ? error.message : String(error));
|
|
632
|
+
return 1;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
118
635
|
if (command === "context") {
|
|
119
636
|
const parsed = parseContextArgs([...(action === undefined ? [] : [action]), ...rest]);
|
|
120
637
|
if (!parsed) return usage(deps.stderr);
|
|
@@ -134,6 +651,11 @@ export async function runCli(args: string[], deps: CliDependencies = DEFAULT_DEP
|
|
|
134
651
|
case "stop": deps.systemctl("stop", SYSTEMD_UNIT_NAME); return 0;
|
|
135
652
|
case "restart": deps.systemctl("restart", SYSTEMD_UNIT_NAME); return 0;
|
|
136
653
|
case "status": deps.systemctl("status", SYSTEMD_UNIT_NAME); return 0;
|
|
654
|
+
case "checkpoint": {
|
|
655
|
+
const parsed = parseJsonOnlyArgs(rest);
|
|
656
|
+
if (!parsed) return usage(deps.stderr);
|
|
657
|
+
return callAndPrint(deps, "service.checkpoint", {}, parsed.json, () => "Checkpoint complete");
|
|
658
|
+
}
|
|
137
659
|
default: return usage(deps.stderr);
|
|
138
660
|
}
|
|
139
661
|
}
|
package/src/constants.ts
CHANGED
|
@@ -3,6 +3,32 @@ export const SQLITE_BUSY_TIMEOUT_MS = 5_000;
|
|
|
3
3
|
export const DEFAULT_QUERY_LIMIT = 1_000;
|
|
4
4
|
export const MAX_QUERY_LIMIT = 10_000;
|
|
5
5
|
export const SERVICE_MAX_BODY_BYTES = 1_048_576;
|
|
6
|
+
export const SERVICE_MAX_RESPONSE_BYTES = 4_194_304;
|
|
7
|
+
export const METRIC_IDENTITY_MAX_CHARACTERS = 160;
|
|
8
|
+
export const METRIC_ATTRIBUTES_MAX_SERIALIZED_CHARACTERS = 16_384;
|
|
9
|
+
export const METRIC_ATTRIBUTES_MAX_DEPTH = 12;
|
|
10
|
+
export const BENCHMARK_IDENTITY_MAX_CHARACTERS = 160;
|
|
11
|
+
export const BENCHMARK_MAX_TEXT_CHARACTERS = 2_048;
|
|
12
|
+
export const BENCHMARK_MAX_MODELS_PER_SOURCE = 250;
|
|
13
|
+
export const BENCHMARK_MAX_OBSERVATIONS_PER_SNAPSHOT = 2_000;
|
|
14
|
+
export const BENCHMARK_STORE_QUERY_LIMIT = (BENCHMARK_MAX_OBSERVATIONS_PER_SNAPSHOT * 2) + 1;
|
|
15
|
+
export const BENCHMARK_DEFAULT_QUERY_LIMIT = 100;
|
|
16
|
+
export const BENCHMARK_TUI_MAX_CANDIDATES = 20;
|
|
17
|
+
export const BENCHMARK_TUI_MAX_PROVENANCE_PER_CANDIDATE = 2;
|
|
18
|
+
export const BENCHMARK_MAX_QUERY_LIMIT = 500;
|
|
19
|
+
export const BENCHMARK_SOURCE_MAX_RESPONSE_BYTES = 2_097_152;
|
|
20
|
+
export const BENCHMARK_SOURCE_MAX_TOTAL_RESPONSE_BYTES = 6_291_456;
|
|
21
|
+
export const BENCHMARK_REFRESH_INTERVAL_MS = 24 * 60 * 60 * 1_000;
|
|
22
|
+
export const MODEL_OBSERVATION_IDENTITY_MAX_CHARACTERS = 160;
|
|
23
|
+
export const MODEL_AGGREGATE_MAX_ROWS = 10_000;
|
|
24
|
+
export const MODEL_AGGREGATE_MAX_GROUPS = 500;
|
|
25
|
+
export const MODEL_RANKING_MAX_SOURCES = 4;
|
|
26
|
+
export const MODEL_RANKING_DEFAULT_QUALITY_WEIGHT = 3;
|
|
27
|
+
export const MODEL_RANKING_DEFAULT_COST_WEIGHT = 2;
|
|
28
|
+
export const MODEL_RANKING_DEFAULT_LATENCY_WEIGHT = 1;
|
|
29
|
+
export const MODEL_RANKING_DEFAULT_CONTEXT_WEIGHT = 1;
|
|
30
|
+
export const MODEL_RANKING_DEFAULT_RELIABILITY_WEIGHT = 2;
|
|
31
|
+
export const MODEL_OBSERVATION_FRESH_MS = 7 * 24 * 60 * 60 * 1_000;
|
|
6
32
|
export const MAINTENANCE_INTERVAL_MS = 15 * 60 * 1_000;
|
|
7
33
|
export const TELEMETRY_POLL_INTERVAL_MS = 60_000;
|
|
8
34
|
export const TELEMETRY_STALE_AFTER_MS = 120_000;
|
|
@@ -12,8 +38,10 @@ export const FOOTER_CONTEXT_ERROR_FRACTION = 0.9;
|
|
|
12
38
|
export const FOOTER_BAR_MIN_WIDTH = 4;
|
|
13
39
|
export const FOOTER_BAR_MAX_WIDTH = 8;
|
|
14
40
|
export const FOOTER_WIDE_TERMINAL_WIDTH = 100;
|
|
15
|
-
export const FOOTER_COMPACTION_RENDER_INTERVAL_MS =
|
|
41
|
+
export const FOOTER_COMPACTION_RENDER_INTERVAL_MS = 500;
|
|
16
42
|
export const FOOTER_COMPACTION_DRAIN_STEP_MS = 3_000;
|
|
43
|
+
/** Half-period of the compacting liveness indicator; equal to the render tick so it visibly alternates every repaint. */
|
|
44
|
+
export const FOOTER_COMPACTION_BLINK_HALF_PERIOD_MS = 500;
|
|
17
45
|
export const MILLISECONDS_PER_SECOND = 1_000;
|
|
18
46
|
export const MILLISECONDS_PER_MINUTE = 60 * MILLISECONDS_PER_SECOND;
|
|
19
47
|
export const MILLISECONDS_PER_HOUR = 60 * MILLISECONDS_PER_MINUTE;
|
|
@@ -35,6 +63,15 @@ export const SYSTEMD_UNIT_NAME = "jittor.service";
|
|
|
35
63
|
export const USAGE_CHART_HEIGHT = 8;
|
|
36
64
|
export const USAGE_Y_AXIS_WIDTH = 7;
|
|
37
65
|
export const USAGE_TOKEN_QUERY_LIMIT = 10_000;
|
|
66
|
+
export const USAGE_RENDER_MAX_SERIES = 20;
|
|
67
|
+
export const HUMAN_STATUS_MAX_SOURCES = 20;
|
|
68
|
+
export const HUMAN_TEXT_FIELD_MAX_CHARACTERS = 160;
|
|
69
|
+
export const CLI_METRICS_HUMAN_MAX_ROWS = 50;
|
|
70
|
+
export const CLI_AVAILABLE_ROUTES_MAX = 200;
|
|
71
|
+
/** Bounded rolling window for the compaction duration estimator; older samples are never fetched. */
|
|
72
|
+
export const COMPACTION_DURATION_ESTIMATE_MAX_SAMPLES = 20;
|
|
73
|
+
/** Below this many samples the estimate stays explicit cold-start uncertainty rather than a guess. */
|
|
74
|
+
export const COMPACTION_DURATION_ESTIMATE_MIN_SAMPLES = 3;
|
|
38
75
|
export const MAX_USAGE_BUCKETS = 120;
|
|
39
76
|
export const MAX_DYNAMIC_ROUTES = 100;
|
|
40
77
|
export const CODEX_ERROR_MESSAGE_LIMIT = 160;
|