cascade-ai 0.75.0 → 0.76.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -136,6 +136,29 @@ declare class ResumeStore {
136
136
  */
137
137
  declare function summarizeCompleted(completed: readonly CompletedNode[], perNodeChars?: number): string;
138
138
 
139
+ /** One thing the reviewer says is missing. */
140
+ interface ReviewGap {
141
+ /** A single sentence naming the gap. */
142
+ title: string;
143
+ /** Optional elaboration, when the reviewer gave one. */
144
+ detail?: string;
145
+ /** Section titles this gap was found in, when the reviewer attributed it. */
146
+ sections?: string[];
147
+ }
148
+ /** What a review pass concluded. */
149
+ interface ReviewVerdict {
150
+ approved: boolean;
151
+ /** One line, safe to put in a status field. Absent when approved. */
152
+ summary?: string;
153
+ gaps: ReviewGap[];
154
+ /**
155
+ * The verdict as prose, for the correction prompt — which needs the full
156
+ * detail, not the summary. Assembled from the parts rather than kept
157
+ * separately so the two cannot disagree.
158
+ */
159
+ reason?: string;
160
+ }
161
+
139
162
  type ProviderType = 'anthropic' | 'openai' | 'gemini' | 'azure' | 'openai-compatible' | 'ollama';
140
163
  interface ModelInfo {
141
164
  id: string;
@@ -240,6 +263,13 @@ interface TokenUsage {
240
263
  */
241
264
  costUnknown?: boolean;
242
265
  }
266
+ /**
267
+ * The kind of work a prompt represents, as the heuristic analyser classifies
268
+ * it. Declared here rather than in the router because routing evidence, per-call
269
+ * options and the performance tracker all key on it; `task-analyzer.ts`
270
+ * re-exports it so existing imports keep working.
271
+ */
272
+ type TaskType = 'code' | 'analysis' | 'creative' | 'data' | 'mixed';
243
273
  interface GenerateOptions {
244
274
  messages: ConversationMessage[];
245
275
  systemPrompt?: string;
@@ -259,6 +289,13 @@ interface GenerateOptions {
259
289
  model?: ModelInfo;
260
290
  /** Name/tag of the current sub-feature (e.g. T2 section title) for cost accounting. */
261
291
  featureTag?: string;
292
+ /**
293
+ * The task type the per-call `model` was selected under, when Cascade Auto
294
+ * chose it. Carried so routing evidence lands on the exact selection that
295
+ * ran: a tier can select the same model for two kinds of work in one run,
296
+ * and only the one that reaches a provider should be credited.
297
+ */
298
+ selectionTaskType?: TaskType;
262
299
  /**
263
300
  * Privacy-tier constraint: when set, the call must resolve to a LOCAL model
264
301
  * (never a cloud provider). The router errors if no local model is available
@@ -271,6 +308,21 @@ interface GenerateResult {
271
308
  usage: TokenUsage;
272
309
  toolCalls?: ToolCall[];
273
310
  finishReason: 'stop' | 'length' | 'tool_use';
311
+ /**
312
+ * The model that actually produced this result.
313
+ *
314
+ * Not always the one that was asked for: the router fails over mid-call on a
315
+ * rate limit, a dead model id, or an exhausted account, and the caller has
316
+ * no other way to find out. Callers that REPORT a model — `tier:status`,
317
+ * which the hosted server persists onto the assistant message and which
318
+ * `/why` and thumbs feedback then read — must use this rather than the model
319
+ * they passed in, or the credit goes to a model that never ran and the
320
+ * performance history learns something untrue about both.
321
+ */
322
+ servedBy?: {
323
+ provider: ProviderType;
324
+ id: string;
325
+ };
274
326
  }
275
327
  interface ConversationMessage {
276
328
  role: 'user' | 'assistant' | 'system' | 'tool';
@@ -327,6 +379,21 @@ interface ToolCall {
327
379
  id: string;
328
380
  name: string;
329
381
  input: Record<string, unknown>;
382
+ /**
383
+ * An opaque token the provider attached to this call, to be echoed back
384
+ * verbatim when the call is replayed as history.
385
+ *
386
+ * Normalized types usually strip provider specifics, and this one cannot be:
387
+ * Gemini's thinking models sign each `functionCall` part, and a follow-up
388
+ * turn that replays the call without its signature is rejected outright —
389
+ * `400 Bad Request`, "missing thought signature". Dropping it therefore does
390
+ * not degrade a reply, it prevents one, and only on the multi-turn tool-use
391
+ * path where every worker lives.
392
+ *
393
+ * Opaque on purpose: nothing here may interpret it, and a provider that
394
+ * issues no such token simply leaves it unset.
395
+ */
396
+ signature?: string;
330
397
  }
331
398
  interface ToolResult {
332
399
  toolCallId: string;
@@ -464,6 +531,12 @@ interface StatusUpdate {
464
531
  currentAction: string;
465
532
  status: 'IN_PROGRESS' | 'BLOCKED' | 'ESCALATING';
466
533
  output?: string;
534
+ /**
535
+ * A review verdict, when this update is one. Carried as data rather than
536
+ * folded into `currentAction`, which is a one-line field every surface
537
+ * truncates — see core/tiers/review.ts.
538
+ */
539
+ review?: ReviewVerdict | null;
467
540
  }
468
541
  interface T2Result {
469
542
  sectionId: string;
@@ -1133,6 +1206,19 @@ declare class ModelSelector {
1133
1206
  * A model is usable for AUTO selection when its provider is available AND —
1134
1207
  * if that provider was validated — the id is one the provider confirmed.
1135
1208
  */
1209
+ /**
1210
+ * Per-MODEL exclusion, for verdicts finer-grained than a provider.
1211
+ *
1212
+ * `availableProviders` can only say "all of Azure is out", which is wrong
1213
+ * when each Azure deployment carries its own resource and key. The router
1214
+ * sets this to the failover manager's permanent-verdict check, so a
1215
+ * deployment that ran out of credit stops being selected while its healthy
1216
+ * siblings stay eligible. Routed through isUsable() so every selection path
1217
+ * — selectForTier, getNextFallback, the widening fallbacks — honours it,
1218
+ * rather than each having to remember.
1219
+ */
1220
+ private modelVeto?;
1221
+ setModelVeto(veto: (model: ModelInfo) => boolean): void;
1136
1222
  private isUsable;
1137
1223
  /**
1138
1224
  * Permanently drop a model from the available set for this session. Used by
@@ -1165,11 +1251,30 @@ declare class ModelSelector {
1165
1251
  private resolveDynamicModel;
1166
1252
  }
1167
1253
 
1254
+ /** Beta(α, β). α counts success-weight, β failure-weight, both incl. the prior. */
1255
+ interface BetaPosterior {
1256
+ alpha: number;
1257
+ beta: number;
1258
+ }
1259
+ /** Uniform source in [0,1). Injected so every test here is deterministic. */
1260
+ type Rng = () => number;
1261
+
1168
1262
  interface ModelStat {
1263
+ /**
1264
+ * Success and failure EVIDENCE, weighted — not observation counts.
1265
+ *
1266
+ * An explicit thumbs-up is worth more than "the HTTP call did not error",
1267
+ * and that difference is expressed here, in the evidence, where a Beta
1268
+ * posterior can read it. It used to be expressed by recording the same
1269
+ * observation three times, which also tripled `sampleCount` — so the one
1270
+ * number everything else treats as "how much do we know about this model"
1271
+ * was inflated by a factor of three every time somebody clicked a thumb.
1272
+ */
1169
1273
  successCount: number;
1170
1274
  failureCount: number;
1171
1275
  totalRetries: number;
1172
1276
  totalCostUsd: number;
1277
+ /** How many times this model was actually OBSERVED. Confidence, not score. */
1173
1278
  sampleCount: number;
1174
1279
  /** Sum of input/context tokens across samples — so we can see whether a
1175
1280
  * model tends to fail on larger contexts and route less to it accordingly. */
@@ -1197,19 +1302,97 @@ declare class ModelPerformanceTracker {
1197
1302
  });
1198
1303
  load(): Promise<void>;
1199
1304
  save(): Promise<void>;
1200
- record(modelId: string, taskType: TaskType, outcome: 'success' | 'failure', retries?: number, costUsd?: number, contextTokens?: number): void;
1305
+ record(modelId: string, taskType: TaskType, outcome: 'success' | 'failure', retries?: number, costUsd?: number, contextTokens?: number,
1306
+ /**
1307
+ * How much this observation counts as EVIDENCE. One for an automatic
1308
+ * outcome; more for a signal we trust further. It never touches
1309
+ * sampleCount: one thing happened, however much it tells us.
1310
+ */
1311
+ weight?: number): void;
1201
1312
  recordFeatureCost(featureTag: string, costUsd: number): void;
1202
1313
  /**
1203
- * Record an explicit user rating (good/bad). Counts as 3 automatic samples
1204
- * so user feedback carries significantly more weight than auto-detected outcomes.
1314
+ * Weight an explicit rating carries relative to an automatic outcome.
1315
+ *
1316
+ * An automatic outcome says only that the call completed; a person saying
1317
+ * "this was good" is about the thing routing actually cares about. Three is
1318
+ * the ratio this has always used — kept, now that it is expressed honestly.
1319
+ */
1320
+ static readonly EXPLICIT_RATING_WEIGHT = 3;
1321
+ /**
1322
+ * Record an explicit user rating (good/bad), worth EXPLICIT_RATING_WEIGHT
1323
+ * automatic outcomes.
1324
+ *
1325
+ * ONE observation carrying that weight, not three observations. Recording it
1326
+ * three times also tripled `sampleCount` — the count of how many times this
1327
+ * model was actually run, which the exploration note reports and the
1328
+ * lifecycle states will read. One click claimed three runs' worth of
1329
+ * history that never happened.
1330
+ *
1331
+ * The weight is spent on belief, relative to the evidence it competes with;
1332
+ * it does not buy confidence. A lone thumbs-up moves the score exactly as
1333
+ * far as a lone successful run (0.5 → 0.6) — what it buys is winning the
1334
+ * argument against automatic outcomes that disagree with it.
1205
1335
  */
1206
1336
  recordExplicit(modelId: string, taskType: TaskType, rating: 'good' | 'bad', costUsd?: number): void;
1207
1337
  /** Returns all stats keyed by "modelId:taskType" — used by `cascade stats`. */
1208
1338
  getAll(): Map<string, ModelStat>;
1209
1339
  getAllFeatures(): Map<string, FeatureStat>;
1210
1340
  /**
1211
- * Returns 0.05–1.0; defaults to 0.5 (neutral prior) when no history exists.
1212
- * High retry counts penalise the score.
1341
+ * Whether outcomes recorded here go anywhere.
1342
+ *
1343
+ * A read-only tracker (routing.learnFromOutcomes = false) reads the shared
1344
+ * scores but drops every observation — not just the write to disk, the
1345
+ * in-memory update too. Anything whose correctness depends on evidence
1346
+ * accumulating has to know that: see TaskAnalyzer.perfFor, where sampling a
1347
+ * posterior that can never narrow means exploring forever.
1348
+ */
1349
+ learnsFromOutcomes(): boolean;
1350
+ /**
1351
+ * The Beta posterior over this model's success rate for this task type.
1352
+ *
1353
+ * Exposed as the posterior rather than a number so callers can ask the two
1354
+ * different questions it answers: what we believe (the mean, for ranking)
1355
+ * and how little we know (the spread, for deciding whether to explore).
1356
+ * Collapsing it to a scalar here is what made those inseparable.
1357
+ */
1358
+ posteriorFor(modelId: string, taskType: TaskType): BetaPosterior;
1359
+ /**
1360
+ * The observed success rate, 0–1 — what actually happened, unshrunk.
1361
+ *
1362
+ * For display (`cascade stats`), not for routing: routing wants
1363
+ * `performanceScore`, which is shrunk toward 0.5 by how little is known.
1364
+ *
1365
+ * Lives here rather than at the call site because the denominator is not
1366
+ * obvious and getting it wrong is silent. It is the EVIDENCE total, not
1367
+ * `sampleCount`: an explicit rating contributes 3 units of evidence on 1
1368
+ * observation, so dividing by the observation count renders a single
1369
+ * thumbs-up as "300%" — and anything sorting on that column then ranks the
1370
+ * impossible rates first.
1371
+ */
1372
+ observedSuccessRate(modelId: string, taskType: TaskType): number;
1373
+ /** How many times this model was observed on this task type. */
1374
+ sampleCountFor(modelId: string, taskType: TaskType): number;
1375
+ /**
1376
+ * The retry cost as a multiplier in (0.6, 1] — 1.0 when a model never
1377
+ * retries, 0.6 when it retries three times or more on average.
1378
+ *
1379
+ * Exposed separately because it is genuinely a separate quantity from the
1380
+ * success rate, and because the alternative — recovering it by dividing
1381
+ * `performanceScore` by `posteriorMean` — silently stops being the retry
1382
+ * penalty at all once the score floor engages. See perfFor().
1383
+ */
1384
+ retryFactorFor(modelId: string, taskType: TaskType): number;
1385
+ /**
1386
+ * Believed success rate, 0–1, shrunk toward 0.5 by how little is known.
1387
+ *
1388
+ * Replaces a raw successCount/sampleCount. That rate read one failure as 0%
1389
+ * — floored to 0.05, a 10x penalty against a benchmark range spanning about
1390
+ * 1.5x — so a single bad moment outweighed every measured quality difference
1391
+ * in the catalogue, and with nothing exploring, the model was never tried
1392
+ * again to find out otherwise. See bayes.ts for the numbers.
1393
+ *
1394
+ * The retry penalty survives unchanged: retries are a real cost that a
1395
+ * success/failure verdict does not capture.
1213
1396
  */
1214
1397
  performanceScore(modelId: string, taskType: TaskType): number;
1215
1398
  /**
@@ -1236,9 +1419,28 @@ interface FeedbackCounts {
1236
1419
  */
1237
1420
  type FeedbackSource = (modelId: string) => FeedbackCounts | undefined;
1238
1421
 
1239
- type TaskType = 'code' | 'analysis' | 'creative' | 'data' | 'mixed';
1240
1422
  /** Cascade Auto cost/quality trade-off bias. See CascadeConfig.autoBias. */
1241
1423
  type AutoBias = 'balanced' | 'quality' | 'cost';
1424
+ /** Options shared by both selection entry points. */
1425
+ interface SelectOptions {
1426
+ requiresToolUse?: boolean;
1427
+ }
1428
+ /** A routing choice, plus why it might not be the obvious one. */
1429
+ interface Selection {
1430
+ model: ModelInfo | null;
1431
+ /**
1432
+ * The task type this choice was made under — the other half of the
1433
+ * selection's identity, since one tier can select the same model for two
1434
+ * different kinds of work in one run and only one of them may run.
1435
+ */
1436
+ taskType: TaskType;
1437
+ /**
1438
+ * Set only when the draw beat the belief — i.e. this is an experiment, not
1439
+ * the evidence's own answer. Null on an ordinary pick, so a caller can print
1440
+ * it unconditionally.
1441
+ */
1442
+ note: string | null;
1443
+ }
1242
1444
  interface TaskProfile {
1243
1445
  type: TaskType;
1244
1446
  /** 1 = trivial, 5 = research-grade */
@@ -1255,7 +1457,19 @@ declare class TaskAnalyzer {
1255
1457
  private feedback?;
1256
1458
  private bias;
1257
1459
  private lastProfile;
1258
- /** Models chosen by the run currently in flight. Cleared when it completes. */
1460
+ /**
1461
+ * Models used per tier this run — a LIST, each carrying its own task type.
1462
+ *
1463
+ * A tier can legitimately run several models now that selection samples: two
1464
+ * T3 subtasks in one run may draw differently. Every one of them has to
1465
+ * receive the run's outcome, or the explored model records nothing and
1466
+ * exploration cannot learn from its own experiment.
1467
+ *
1468
+ * And each carries the task type IT was chosen for, because subtasks within
1469
+ * one run are not all the same type. Crediting them all to the last
1470
+ * selection's profile teaches the router that whichever model happened to
1471
+ * write the closing paragraph is good at code.
1472
+ */
1259
1473
  private currentRunSelections;
1260
1474
  /**
1261
1475
  * Immutable snapshot of the last COMPLETED run: its selections AND the task
@@ -1273,7 +1487,14 @@ declare class TaskAnalyzer {
1273
1487
  * false: the 3x-weighted user signal never reached the tracker at all.
1274
1488
  */
1275
1489
  private lastCompletedRun?;
1490
+ /**
1491
+ * Uniform source for Thompson draws. Injectable so a test can pin the
1492
+ * exploration decision instead of asserting on chance.
1493
+ */
1494
+ private rng;
1276
1495
  constructor(tracker?: ModelPerformanceTracker, bias?: AutoBias);
1496
+ /** Replace the RNG behind exploration (tests). */
1497
+ setRng(rng: Rng): void;
1277
1498
  /**
1278
1499
  * Supply per-model rating counts. Optional by design: a host that collects no
1279
1500
  * feedback (the CLI, a fresh install) scores exactly as it did before, since
@@ -1295,9 +1516,39 @@ declare class TaskAnalyzer {
1295
1516
  * Scores tier-eligible models using cost efficiency + historical performance.
1296
1517
  * Falls back to the priority-list default when no candidates have history.
1297
1518
  */
1298
- selectModel(prompt: string, tier: TierRole, selector: ModelSelector, opts?: {
1299
- requiresToolUse?: boolean;
1300
- }): Promise<ModelInfo | null>;
1519
+ selectModel(prompt: string, tier: TierRole, selector: ModelSelector, opts?: SelectOptions): Promise<ModelInfo | null>;
1520
+ /**
1521
+ * Select a model AND say whether the choice was exploratory.
1522
+ *
1523
+ * The note is returned rather than left on the instance for the caller to
1524
+ * collect afterwards. That looks like an over-careful API for one string,
1525
+ * and it is not: `Cascade.run` selects every tier CONCURRENTLY
1526
+ * (`Promise.all` over the tiers in play, cascade.ts), all against this one
1527
+ * analyzer. A field would be written by three interleaved calls and read by
1528
+ * three continuations in an order nothing establishes — /why would attribute
1529
+ * one tier's exploration to another, and lose the rest. Clearing the field
1530
+ * per call does not fix that; it only removes the staleness across
1531
+ * SEQUENTIAL calls. Ownership is what is actually needed, and a return value
1532
+ * is what ownership looks like.
1533
+ */
1534
+ select(prompt: string, tier: TierRole, selector: ModelSelector, opts?: SelectOptions): Promise<Selection>;
1535
+ /**
1536
+ * Mark a selected model as having actually been sent a request on this tier.
1537
+ *
1538
+ * Called at the provider-call boundary, which is the only place that knows a
1539
+ * request was really made and which model made it. Everything upstream knows
1540
+ * only what was CHOSEN.
1541
+ *
1542
+ * Called BEFORE the request is awaited, deliberately. Hanging it off the
1543
+ * success path looks tidier and quietly discards every failure: a run that
1544
+ * died recorded nothing about the model that killed it, so its posterior
1545
+ * never moved and sampling kept picking it.
1546
+ *
1547
+ * A model that runs without having been selected here — an explicitly pinned
1548
+ * tier, a failover replacement — has no entry and is ignored, which matches
1549
+ * the existing contract that this analyzer rates only its own choices.
1550
+ */
1551
+ noteAttempted(tier: TierRole, modelId: string, taskType?: TaskType): void;
1301
1552
  /**
1302
1553
  * Record the outcome of a completed run across all tiers that were selected
1303
1554
  * during this session and persist stats to disk.
@@ -1317,7 +1568,23 @@ declare class TaskAnalyzer {
1317
1568
  * that reports false, which is what "rate this run" should mean.
1318
1569
  */
1319
1570
  recordExplicitRating(rating: 'good' | 'bad'): boolean;
1571
+ /**
1572
+ * @param perfMode `mean` scores on what we believe; `sample` draws from the
1573
+ * posterior. Everything else in the score is a deterministic lookup —
1574
+ * the benchmark, the price, the specialization match — so this is the
1575
+ * only term where exploration could live.
1576
+ */
1320
1577
  private scoreModel;
1578
+ /**
1579
+ * The one stochastic term in the score.
1580
+ *
1581
+ * The retry penalty is applied to a DRAW the same way performanceScore()
1582
+ * applies it to the mean, so exploring cannot smuggle a model past a cost it
1583
+ * has actually been shown to carry.
1584
+ */
1585
+ private perfFor;
1586
+ /** One line for /why, naming what was tried and how little is known about it. */
1587
+ private describeExploration;
1321
1588
  private costEfficiency;
1322
1589
  private taskMatchScore;
1323
1590
  /** Clear the analysis cache (call between sessions). */
@@ -1882,6 +2149,18 @@ declare class CascadeRouter extends EventEmitter {
1882
2149
  private liveData?;
1883
2150
  /** Snapshot of configured/default tier models, taken before Cascade Auto overrides them. */
1884
2151
  private originalTierModels?;
2152
+ /**
2153
+ * Tiers repointed because their model's credential went out for the run, and
2154
+ * the model each was displaced from.
2155
+ *
2156
+ * Clearing the verdict at the run boundary makes the provider SELECTABLE
2157
+ * again, which is not the same as being used: generate() resolves
2158
+ * `tierModels.get(tier)` before it ever consults the selector, so a tier
2159
+ * still holding the fallback keeps charging the fallback account for every
2160
+ * later default-routed run. Restoring the binding is what actually gives a
2161
+ * topped-up account its traffic back.
2162
+ */
2163
+ private permanentRepoints;
1885
2164
  /** The current run's abort signal — injected into every provider call so a cancel aborts in-flight requests. */
1886
2165
  private runSignal?;
1887
2166
  /** Thrown when the configured budget is exceeded. */
@@ -1974,7 +2253,7 @@ declare class CascadeRouter extends EventEmitter {
1974
2253
  * Used by TaskAnalyzer to inject task-optimal models before execution.
1975
2254
  * The override is valid for the current task only — restored by restoreTierModels().
1976
2255
  */
1977
- overrideTierModel(tier: TierRole, model: ModelInfo): void;
2256
+ overrideTierModel(tier: TierRole, model: ModelInfo, taskType?: TaskType): void;
1978
2257
  /**
1979
2258
  * Restore tier models to the configured/default baseline captured before the
1980
2259
  * first Cascade Auto override. Called at the end of each run so `/why`, the
@@ -2019,7 +2298,10 @@ declare class CascadeRouter extends EventEmitter {
2019
2298
  */
2020
2299
  selectModelForSubtask(tier: TierRole, text: string, opts?: {
2021
2300
  requiresToolUse?: boolean;
2022
- }): Promise<ModelInfo | null>;
2301
+ }): Promise<{
2302
+ model: ModelInfo;
2303
+ taskType?: TaskType;
2304
+ } | null>;
2023
2305
  getStats(): RouterStats;
2024
2306
  /**
2025
2307
  * What did delegation save? Compares actual spend against the
@@ -2094,6 +2376,74 @@ declare class CascadeRouter extends EventEmitter {
2094
2376
  private discoverOllamaModels;
2095
2377
  /** Returns true when at least one real model was discovered from the endpoint. */
2096
2378
  private discoverOpenAICompatibleModels;
2379
+ /**
2380
+ * The credential a failure on this model is actually about.
2381
+ *
2382
+ * Resolves an Azure deployment to its RESOURCE (endpoint), because that is
2383
+ * what the key and the bill belong to — see failureScopeOf. Everything else
2384
+ * is already one credential per provider.
2385
+ */
2386
+ /**
2387
+ * Note the tier's binding before a permanent verdict repoints it.
2388
+ *
2389
+ * Records `tierModels.get(tier)` — the tier's own baseline — and NOT the
2390
+ * model that happened to fail. Those differ whenever the call carried a
2391
+ * per-call override (Cascade Auto picks one per subtask), and saving the
2392
+ * override would have beginRun() install a one-off subtask model as the
2393
+ * tier's baseline, leaving every later default-routed call on a model the
2394
+ * tier was never configured to use.
2395
+ *
2396
+ * Nothing to restore if the tier had no binding, and the first repoint wins
2397
+ * so a second failover in the same run cannot overwrite the true baseline.
2398
+ */
2399
+ private rememberRepoint;
2400
+ /**
2401
+ * Both scopes a failure on this model could belong to, widest first.
2402
+ *
2403
+ * Azure needs two, because the two systemic failures have different blast
2404
+ * radii on the same deployment:
2405
+ *
2406
+ * · billing quota belongs to the RESOURCE — deployments on one endpoint
2407
+ * draw on the same subscription, so a spent quota covers all of them
2408
+ * even when they carry different keys;
2409
+ * · a rejected credential belongs to the KEY — two deployments on one
2410
+ * endpoint can be configured with separate keys, and a 401 on a rotated
2411
+ * one says nothing about the other.
2412
+ *
2413
+ * Recording uses whichever matches the failure (scopeForFailure); anything
2414
+ * asking "is this model out?" has to consult both, or a verdict filed under
2415
+ * one would be invisible to the other.
2416
+ */
2417
+ private scopesFor;
2418
+ /** True when ANY scope this model belongs to is out for the run. */
2419
+ private isModelOut;
2420
+ /** The first explanation among this model's scopes, for a refusal message. */
2421
+ private outReason;
2422
+ /**
2423
+ * The scope a failure of this KIND should be filed under. A credential
2424
+ * rejection is about the key; everything else about the resource.
2425
+ */
2426
+ private scopeForFailure;
2427
+ /** `azure:<resource>` for an Azure model, or undefined for anything else. */
2428
+ private azureScope;
2429
+ /**
2430
+ * `azure:<resource>#k<n>`, so two different keys on one resource differ.
2431
+ *
2432
+ * `n` is the position of the FIRST configured Azure entry using this same
2433
+ * key, which makes it stable for the run and identical for every deployment
2434
+ * sharing that credential — the grouping an auth verdict needs, since a 401
2435
+ * on one of them is a fact about all of them.
2436
+ *
2437
+ * Deliberately neither of the two obvious alternatives. credentialIdentity()
2438
+ * rotates to a fresh UUID after DISCOVERY_TTL_MS, so a long run would stop
2439
+ * finding its own verdict and go back to a credential it had just been told
2440
+ * was rejected. And hashing the key — even with a strong digest — is a
2441
+ * password hash by CodeQL's reading and by any reasonable one: there is no
2442
+ * reason to derive anything from a secret when its POSITION already
2443
+ * identifies it uniquely and reveals nothing.
2444
+ */
2445
+ private azureKeyScope;
2446
+ private scopeFor;
2097
2447
  private ensureProvider;
2098
2448
  private getProvider;
2099
2449
  private createProvider;
@@ -2111,6 +2461,25 @@ declare class CascadeRouter extends EventEmitter {
2111
2461
  * totals and a session-wide budget halt are deliberately preserved; only the
2112
2462
  * per-task ceiling is cleared so the next task starts with a fresh allowance.
2113
2463
  */
2464
+ /**
2465
+ * The task type each tier's Cascade Auto default was selected under.
2466
+ *
2467
+ * A call that does not carry its own `selectionTaskType` is using the tier
2468
+ * default, and its evidence belongs to the selection that established that
2469
+ * default rather than to any other selection of the same model.
2470
+ */
2471
+ private tierSelectionTaskTypes;
2472
+ /**
2473
+ * Exploration notes for selections that have not yet reached a provider,
2474
+ * keyed by the selection's identity.
2475
+ *
2476
+ * Held rather than emitted so /why only ever claims an experiment that was
2477
+ * actually run. Cleared by beginRun() along with everything else run-scoped;
2478
+ * a note whose call never happens is simply dropped, which is the point.
2479
+ */
2480
+ private pendingExplorationNotes;
2481
+ /** Announce an exploratory pick, once, at the moment its call goes out. */
2482
+ private flushExplorationNote;
2114
2483
  beginRun(): void;
2115
2484
  /**
2116
2485
  * Refuse a call whose input alone cannot fit what is left of the run budget.
@@ -2343,6 +2712,11 @@ declare class ToolRegistry extends EventEmitter {
2343
2712
  }
2344
2713
 
2345
2714
  declare abstract class BaseTier extends EventEmitter {
2715
+ /**
2716
+ * Declared here so generateTracked() can reach it. Each tier owns its own
2717
+ * instance; this only states that one exists.
2718
+ */
2719
+ protected abstract router: CascadeRouter;
2346
2720
  readonly id: string;
2347
2721
  readonly role: TierRole;
2348
2722
  protected status: TierStatus;
@@ -2419,6 +2793,32 @@ declare abstract class BaseTier extends EventEmitter {
2419
2793
  */
2420
2794
  getServingModel(): string | undefined;
2421
2795
  protected setServingModel(model: string | undefined): void;
2796
+ /**
2797
+ * Run a generation and record which model actually answered it.
2798
+ *
2799
+ * Tiers set servingModel from the model they SELECTED, before the call. The
2800
+ * router can fail over mid-call — a rate limit, a dead id, an exhausted
2801
+ * account — and then the tier's terminal status names a model that never
2802
+ * ran. cloud/server persists that value onto the assistant message, and
2803
+ * `/why` and thumbs feedback read it back, so the credit (or the blame) goes
2804
+ * to the wrong model and the performance history learns something untrue
2805
+ * about two models at once.
2806
+ *
2807
+ * Every tier call goes through here rather than `router.generate` directly,
2808
+ * so a new call site cannot quietly reintroduce the mis-attribution.
2809
+ */
2810
+ /**
2811
+ * Run a generation whose model must NOT become this tier's attribution.
2812
+ *
2813
+ * Graders, critics and extractors run beside the answer, often on a
2814
+ * deliberately different model — the T2 critic exists precisely so a model
2815
+ * is not marking its own work. Routing those through generateTracked() made
2816
+ * the last grading call overwrite servingModel, so the subtask's output, its
2817
+ * terminal status and the feedback history all named the grader rather than
2818
+ * the model that wrote the answer.
2819
+ */
2820
+ protected generateAuxiliary(...args: Parameters<CascadeRouter['generate']>): Promise<Awaited<ReturnType<CascadeRouter['generate']>>>;
2821
+ protected generateTracked(...args: Parameters<CascadeRouter['generate']>): Promise<Awaited<ReturnType<CascadeRouter['generate']>>>;
2422
2822
  protected setLabel(label: string): void;
2423
2823
  setSystemPromptOverride(prompt: string): void;
2424
2824
  setHierarchyContext(context: string): void;
@@ -2629,7 +3029,7 @@ interface PlanApprovalMeta {
2629
3029
  critique?: string;
2630
3030
  }
2631
3031
  declare class T1Administrator extends BaseTier {
2632
- private router;
3032
+ protected router: CascadeRouter;
2633
3033
  private toolRegistry;
2634
3034
  private config;
2635
3035
  private t2Managers;
@@ -2766,7 +3166,7 @@ declare class CurrentPageTool extends BaseTool {
2766
3166
  /** One entry in the per-run orchestration decision trail (see /why). */
2767
3167
  interface DecisionLogEntry {
2768
3168
  at: string;
2769
- kind: 'complexity' | 'model' | 'failover' | 'escalation' | 'context';
3169
+ kind: 'complexity' | 'model' | 'failover' | 'escalation' | 'context' | 'provider-exhausted';
2770
3170
  detail: string;
2771
3171
  }
2772
3172
  declare class Cascade extends EventEmitter {
@@ -3245,10 +3645,17 @@ declare class PeerBus extends EventEmitter {
3245
3645
  }
3246
3646
 
3247
3647
  declare class T2Manager extends BaseTier {
3248
- private router;
3648
+ protected router: CascadeRouter;
3249
3649
  private toolRegistry;
3250
3650
  private assignment?;
3251
3651
  private sectionModel?;
3652
+ /**
3653
+ * The task type `sectionModel` was selected under. Carried into every call
3654
+ * that uses it so routing evidence lands on this exact selection — one tier
3655
+ * can select the same model for two kinds of work in a run, and only the one
3656
+ * that reaches a provider should be credited.
3657
+ */
3658
+ private sectionTaskType?;
3252
3659
  private t3Workers;
3253
3660
  private escalations;
3254
3661
  private peerSyncBuffer;
@@ -3351,7 +3758,7 @@ declare class T2Manager extends BaseTier {
3351
3758
  }
3352
3759
 
3353
3760
  declare class T3Worker extends BaseTier {
3354
- private router;
3761
+ protected router: CascadeRouter;
3355
3762
  private toolRegistry;
3356
3763
  private context;
3357
3764
  private assignment?;
@@ -3644,11 +4051,35 @@ interface AcceptanceProbe {
3644
4051
  /** utf-8 contents, or null when unreadable (missing, binary, too large). */
3645
4052
  read(path: string): Promise<string | null>;
3646
4053
  }
4054
+ interface AcceptanceOptions {
4055
+ /**
4056
+ * Whether the worker being graded had ANY tool that could put a file on
4057
+ * disk. Defaults to true, which is every caller that does not say otherwise.
4058
+ *
4059
+ * When false, a file-shaped criterion is `undecidable` rather than `failed`.
4060
+ * `stat` still answers correctly — the file really is absent — but the
4061
+ * verdict is a judgement about the WORKER, and "you did not write the file"
4062
+ * is the wrong judgement when nothing in the run could write one. A hosted
4063
+ * chat run enables `web_search`/`web_fetch` only (cloud/server/src/runs.ts),
4064
+ * while T1 and T2 are asked for acceptance criteria phrased as "file exists
4065
+ * / contains X" — so the planner names a file, the worker answers in prose
4066
+ * because prose is all it can produce, and this rung failed it for that.
4067
+ * correctOutput then re-ran, the file was still absent, and the subtask
4068
+ * ESCALATED carrying a perfectly good answer.
4069
+ *
4070
+ * This is the same guard `shouldRequireArtifact()` applies one rung up (see
4071
+ * t3-worker.ts); the artifact rung got it in #151 and this rung, added
4072
+ * afterwards, never inherited it. Deferring keeps the module's governing
4073
+ * rule: the criterion still reaches selfTest(), which judges the OUTPUT and
4074
+ * can actually tell whether the work was done.
4075
+ */
4076
+ workerCanWriteFiles?: boolean;
4077
+ }
3647
4078
  /**
3648
4079
  * Evaluate acceptance criteria, deciding only the mechanically checkable ones.
3649
4080
  * Order and length of the result always match `criteria`.
3650
4081
  */
3651
- declare function evaluateAcceptance(criteria: readonly string[], ownedFiles: readonly string[], probe: AcceptanceProbe): Promise<AcceptanceResult[]>;
4082
+ declare function evaluateAcceptance(criteria: readonly string[], ownedFiles: readonly string[], probe: AcceptanceProbe, options?: AcceptanceOptions): Promise<AcceptanceResult[]>;
3652
4083
  /** The criteria that still need a model's judgement. */
3653
4084
  declare function undecided(results: readonly AcceptanceResult[]): string[];
3654
4085
  /** Failure messages, phrased so correctOutput can act on them directly. */
@@ -5361,6 +5792,16 @@ interface Slide {
5361
5792
  body: string[];
5362
5793
  images: ImageRef[];
5363
5794
  charts: ChartSpec[];
5795
+ /**
5796
+ * Real tables, laid out as a grid on the slide.
5797
+ *
5798
+ * PowerPoint holds a genuine table shape, so a Markdown table has somewhere
5799
+ * to go. Before this existed, `parseSlide` had no branch for a `|…|` line
5800
+ * and every row fell through to the bullet path — a deck rendered
5801
+ * `|---|---|` as literal text where Word, from the same Markdown, showed a
5802
+ * proper table.
5803
+ */
5804
+ tables: string[][][];
5364
5805
  }
5365
5806
  /** Split a Markdown deck into slides: on `---` rules, else on top-level headings. */
5366
5807
  declare function splitSlides(md: string): Slide[];
@@ -5380,6 +5821,23 @@ declare function extractCharts(source: string): {
5380
5821
  rest: string;
5381
5822
  };
5382
5823
 
5824
+ /** How a deck reveals itself. */
5825
+ interface AnimationScheme {
5826
+ /** Slide-to-slide transition. 'none' writes no `p:transition` at all. */
5827
+ transition: 'none' | 'fade' | 'push' | 'wipe' | 'split';
5828
+ /** How a slide's own shapes arrive. 'none' writes no `p:timing` at all. */
5829
+ entrance: 'none' | 'fade' | 'appear' | 'fly';
5830
+ /**
5831
+ * Whether shapes arrive on their own or wait for a click.
5832
+ *
5833
+ * Auto suits a deck that plays unattended; click suits a person presenting
5834
+ * and is what PowerPoint's own defaults do, so it is the default here.
5835
+ */
5836
+ advance: 'click' | 'auto';
5837
+ /** Entrance duration, milliseconds. Ignored when `entrance` is 'none'. */
5838
+ durationMs: number;
5839
+ }
5840
+
5383
5841
  /** Office formats we can render into a real binary. */
5384
5842
  type DocumentFormat = 'docx' | 'pptx' | 'xlsx';
5385
5843
  declare const DOCUMENT_MIME: Record<DocumentFormat, string>;
@@ -5395,6 +5853,12 @@ interface RenderOptions {
5395
5853
  loadImageBytes?: ImageByteLoader;
5396
5854
  /** Target file name — only used to pick the CSV vs TSV delimiter for xlsx. */
5397
5855
  name?: string;
5856
+ /**
5857
+ * Host-level animation defaults for `.pptx`. A deck's own `animation:`
5858
+ * directive overrides these, because it lives in the document the user is
5859
+ * looking at.
5860
+ */
5861
+ animation?: Partial<AnimationScheme>;
5398
5862
  }
5399
5863
  /**
5400
5864
  * CSV → a real `.xlsx` workbook.
@@ -5992,4 +6456,4 @@ declare function gatherSyncBundle(config: CascadeConfig): SyncBundle;
5992
6456
  /** Merge a pulled bundle into a config, returning the updated config to persist. */
5993
6457
  declare function applySyncBundle(bundle: SyncBundle, config: CascadeConfig, cleanup?: RetiredProviderCleanup): CascadeConfig;
5994
6458
 
5995
- export { AZURE_BASE_MODELS, AZURE_BASE_URL_TEMPLATE, type AcceptanceProbe, type AcceptanceResult, type AcceptanceVerdict, type ApprovalRequest, type ApprovalResponse, type AuditEntry, AuditLogger, type AzureDeploymentInput, type BenchmarksConfig, type Block, type BudgetConfig, CASCADE_AUDIT_FILE, CASCADE_CONFIG_DIR, CASCADE_CONFIG_FILE, CASCADE_DASHBOARD_SECRET_FILE, CASCADE_DB_FILE, CASCADE_IGNORE_FILE, CASCADE_KEYSTORE_FILE, CASCADE_MD_FILE, CASCADE_VERSION, CHARS_PER_TOKEN, COMPLEXITY_T2_COUNT, Cascade, CascadeCancelledError, type CascadeConfig, type CascadeEvent, type CascadeEventType, CascadeIgnore, type CascadeMessage, CascadeRouter, type CascadeRunOptions, type CascadeRunResult, type CascadeThemeName, CascadeToolError, type ChartSeries, type ChartSpec, type Chunk, type ChunkOptions, CloudClient, type CloudConversation, type CloudMessage, type CloudSession, type CloudSessionStore, type CloudTurnInput, type CloudUser, type CodeChunkOptions, type CodeChunker, CodeSearchTool, type CompileTaskGraphOptions, type CompiledTaskGraph, type CompleteFn, type CompletedNode, ConfigManager, type ConversationMessage, type CredentialDisposition, type CredentialEndpoint, type CredentialWriteOutcome, type CurrentPageProvider, type CurrentPageSnapshot, CurrentPageTool, DEFAULT_API_PORT, DEFAULT_APPROVAL_REQUIRED, DEFAULT_AUTO_SUMMARIZE_AT, DEFAULT_CLOUD_URL, DEFAULT_CONTEXT_LIMIT, DEFAULT_DASHBOARD_PORT, DEFAULT_MAX_SESSION_MESSAGES, DEFAULT_RETENTION_DAYS, DEFAULT_THEME, DOCUMENT_MIME, type DashboardConfig, DashboardServer, DependencyScheduler, type DeviceStart, type DiscoveredMcpTool, type DistilledFact, type ChartKind as DocumentChartKind, type DocumentFormat, type Embedder, type EncryptedBlob, type EscalationDecision, type EscalationPayload, type ExtendedContextConfig, type FileManifest, FileMcpOAuthStore, GLOBAL_CONFIG_DIR, GLOBAL_CREDENTIALS_FILE, GLOBAL_DB_FILE, GLOBAL_KEYSTORE_FILE, GLOBAL_RUNTIME_DB_FILE, GenerateDocumentTool, type GenerateOptions, type GenerateResult, type GraphFactSource, GraphRetriever, type GraphSearchOptions, GraphSearchTool, type HookDefinition, type HooksConfig, HooksRunner, type Identity, type ImageAttachment, type ImageByteLoader, type ImageInfo, type ImageRef, type InlineRun, Keystore, LLMReranker, LM_STUDIO_BASE_URL, type LegacyThemeName, type LoadedImage, MAX_PAGE_TEXT_CHARS, MCP_TOOL_PREFIX, MODELS, type ManifestDiff, McpClient, type McpDiscoveryResult, McpOAuthProvider, type McpOAuthState, type McpOAuthStore, type McpServerConfig$1 as McpServerConfig, type McpServerRename, type MemoryConfig, MemoryStore, type Message, type MessageContent, type MessagePayload, type MessageStatus, type MessageType, type ModelInfo, type ModelOverrides, type NativeProvider, OLLAMA_BASE_URL, OpenAICompatibleEmbedder, type OpenAIEmbedderOptions, PROVIDER_DISPLAY_NAMES, type PeerMessage, type PeerMessageEvent, type PeerSyncPayload, type PeerSyncType, type PermissionDecision, type PermissionDecisionPayload, type PermissionRequest, type PermissionTrailEntry, type PlanReviewConfig, type ProviderConfig, type ProviderType, RESUME_SCHEMA_VERSION, type RankedFact, type RefreshResult, type RenderOptions, type Reranker, type ResumeCheckpoint, type ResumeReason, ResumeStore, type ResumeStoreOptions, type RetrievalContext, type RetrievalMode, type RetrievalPlan, Retriever, type RetrieverSearchOptions, type RuntimeNode, type RuntimeNodeLog, type RuntimeRefreshPayload, type RuntimeScope, type RuntimeSession, type RuntimeSnapshotPayload, type ScheduledTask, type SchedulerExecutionMode, type SchedulerHooks, type SchedulerOptions, type SchedulerResult, type ScoredChunk, type SearchOptions, type Session, type SessionCheckpoint, type SessionMetadata, type SessionSubscriptionPayload, type SettingsCommitResult, type SettingsCredentialResult, type SettingsPayload, type SettingsSnapshot, type Slide, SqliteVectorStore, type StatusUpdate, type StoredMessage, type StreamChunk, type SyncBundle, T1Administrator, type T1ToT2Assignment, T1_MODEL_PRIORITY, T2Manager, type T2Result, type T2ToT3Assignment, T2_MODEL_PRIORITY, type T3Result, type T3ResultPayload, type T3SubtaskSpec, T3Worker, T3_MODEL_PRIORITY, THEME_NAMES, TOOL_NAMES, type TaskComplexity, type TaskGraph, type TaskGraphInputNode, type TaskGraphIssue, type TaskGraphIssueCode, type TaskGraphNode, type TaskGraphNodeKind, TaskGraphValidationError, type TaskGraphValidationMode, TaskScheduler, Telemetry, type TelemetryConfig, type Theme, type ThemeColors, type ThemeName, type TierConfig, type TierLimits, type TierRole, type TierStatus, type TokenUsage, type ToolCall, type ToolDefinition, type ToolExecuteOptions, ToolRegistry, type ToolResult, type ToolsConfig, VISION_MODEL_PRIORITY, type VectorStore, type WebSearchConfig, type WebhookConfig, type WorkspaceConfig, type WorkspaceFileReader, WorkspaceIndex, type WorkspaceIndexOptions, applyEndpointEdit, applyProviderApiKey, applyProviderCredential, applySettingsCredentials, applySettingsPayload, applySyncBundle, azureModelForDeployment, beginMcpOAuth, buildDocumentTools, buildManifest, buildSessionTranscript, bytesToBase64, cagCharBudget, chartKind, chartToTableRows, chatCompleterFromProviders, chunkCode, chunkText, commitSettings, compileSectionGraph, compileSubtaskGraph, compileTaskGraph, completeMcpOAuth, connectMcpWithLoopbackOAuth, createCascade, credentialDispositionForEdit, credentialEndpointIdentity, decryptJSON as decryptSyncBlob, diffManifest, disambiguateMcpServerNames, discoverMcpAuthServer, discoverMcpTools, distillSessionFacts, embedderFromProviders, encryptJSON as encryptSyncBlob, endpointFromSettingsPayload, evaluateAcceptance, explainRefusal, extractCharts, failures, fileExt, fileOAuthProvider, gatherSyncBundle, hasDefaultEndpoint, hasProviderCredential, hasUsableProvider, hashContent, heuristicCodeChunker, inferAzureBaseModel, inlineRuns, isDocumentFormat, isMcpToolName, matchImageLine, mcpServerPrefix, mcpToolName, nodeHttpFetch, normalizeEndpoint, parseBlocks, parseChartSpec, parseDelimited, parseRankOrder, parseSlide, planRetrieval, preferIpv4Host, priorAzureRow, reciprocalRankFusion, refreshMcpToken, removeMcpServerDenials, renderDocument, renderDocx, renderPptx, renderXlsx, runCascade, sameAzureEndpoint, sameCredentialEndpoint, sameEndpoint, sessionWorthRemembering, settingsSnapshot, sniffImage, splitSlides, streamCascade, stripInline, summarizeCompleted, undecided, uniqueMcpServerName };
6459
+ export { AZURE_BASE_MODELS, AZURE_BASE_URL_TEMPLATE, type AcceptanceOptions, type AcceptanceProbe, type AcceptanceResult, type AcceptanceVerdict, type ApprovalRequest, type ApprovalResponse, type AuditEntry, AuditLogger, type AzureDeploymentInput, type BenchmarksConfig, type Block, type BudgetConfig, CASCADE_AUDIT_FILE, CASCADE_CONFIG_DIR, CASCADE_CONFIG_FILE, CASCADE_DASHBOARD_SECRET_FILE, CASCADE_DB_FILE, CASCADE_IGNORE_FILE, CASCADE_KEYSTORE_FILE, CASCADE_MD_FILE, CASCADE_VERSION, CHARS_PER_TOKEN, COMPLEXITY_T2_COUNT, Cascade, CascadeCancelledError, type CascadeConfig, type CascadeEvent, type CascadeEventType, CascadeIgnore, type CascadeMessage, CascadeRouter, type CascadeRunOptions, type CascadeRunResult, type CascadeThemeName, CascadeToolError, type ChartSeries, type ChartSpec, type Chunk, type ChunkOptions, CloudClient, type CloudConversation, type CloudMessage, type CloudSession, type CloudSessionStore, type CloudTurnInput, type CloudUser, type CodeChunkOptions, type CodeChunker, CodeSearchTool, type CompileTaskGraphOptions, type CompiledTaskGraph, type CompleteFn, type CompletedNode, ConfigManager, type ConversationMessage, type CredentialDisposition, type CredentialEndpoint, type CredentialWriteOutcome, type CurrentPageProvider, type CurrentPageSnapshot, CurrentPageTool, DEFAULT_API_PORT, DEFAULT_APPROVAL_REQUIRED, DEFAULT_AUTO_SUMMARIZE_AT, DEFAULT_CLOUD_URL, DEFAULT_CONTEXT_LIMIT, DEFAULT_DASHBOARD_PORT, DEFAULT_MAX_SESSION_MESSAGES, DEFAULT_RETENTION_DAYS, DEFAULT_THEME, DOCUMENT_MIME, type DashboardConfig, DashboardServer, DependencyScheduler, type DeviceStart, type DiscoveredMcpTool, type DistilledFact, type ChartKind as DocumentChartKind, type DocumentFormat, type Embedder, type EncryptedBlob, type EscalationDecision, type EscalationPayload, type ExtendedContextConfig, type FileManifest, FileMcpOAuthStore, GLOBAL_CONFIG_DIR, GLOBAL_CREDENTIALS_FILE, GLOBAL_DB_FILE, GLOBAL_KEYSTORE_FILE, GLOBAL_RUNTIME_DB_FILE, GenerateDocumentTool, type GenerateOptions, type GenerateResult, type GraphFactSource, GraphRetriever, type GraphSearchOptions, GraphSearchTool, type HookDefinition, type HooksConfig, HooksRunner, type Identity, type ImageAttachment, type ImageByteLoader, type ImageInfo, type ImageRef, type InlineRun, Keystore, LLMReranker, LM_STUDIO_BASE_URL, type LegacyThemeName, type LoadedImage, MAX_PAGE_TEXT_CHARS, MCP_TOOL_PREFIX, MODELS, type ManifestDiff, McpClient, type McpDiscoveryResult, McpOAuthProvider, type McpOAuthState, type McpOAuthStore, type McpServerConfig$1 as McpServerConfig, type McpServerRename, type MemoryConfig, MemoryStore, type Message, type MessageContent, type MessagePayload, type MessageStatus, type MessageType, type ModelInfo, type ModelOverrides, type NativeProvider, OLLAMA_BASE_URL, OpenAICompatibleEmbedder, type OpenAIEmbedderOptions, PROVIDER_DISPLAY_NAMES, type PeerMessage, type PeerMessageEvent, type PeerSyncPayload, type PeerSyncType, type PermissionDecision, type PermissionDecisionPayload, type PermissionRequest, type PermissionTrailEntry, type PlanReviewConfig, type ProviderConfig, type ProviderType, RESUME_SCHEMA_VERSION, type RankedFact, type RefreshResult, type RenderOptions, type Reranker, type ResumeCheckpoint, type ResumeReason, ResumeStore, type ResumeStoreOptions, type RetrievalContext, type RetrievalMode, type RetrievalPlan, Retriever, type RetrieverSearchOptions, type RuntimeNode, type RuntimeNodeLog, type RuntimeRefreshPayload, type RuntimeScope, type RuntimeSession, type RuntimeSnapshotPayload, type ScheduledTask, type SchedulerExecutionMode, type SchedulerHooks, type SchedulerOptions, type SchedulerResult, type ScoredChunk, type SearchOptions, type Session, type SessionCheckpoint, type SessionMetadata, type SessionSubscriptionPayload, type SettingsCommitResult, type SettingsCredentialResult, type SettingsPayload, type SettingsSnapshot, type Slide, SqliteVectorStore, type StatusUpdate, type StoredMessage, type StreamChunk, type SyncBundle, T1Administrator, type T1ToT2Assignment, T1_MODEL_PRIORITY, T2Manager, type T2Result, type T2ToT3Assignment, T2_MODEL_PRIORITY, type T3Result, type T3ResultPayload, type T3SubtaskSpec, T3Worker, T3_MODEL_PRIORITY, THEME_NAMES, TOOL_NAMES, type TaskComplexity, type TaskGraph, type TaskGraphInputNode, type TaskGraphIssue, type TaskGraphIssueCode, type TaskGraphNode, type TaskGraphNodeKind, TaskGraphValidationError, type TaskGraphValidationMode, TaskScheduler, type TaskType, Telemetry, type TelemetryConfig, type Theme, type ThemeColors, type ThemeName, type TierConfig, type TierLimits, type TierRole, type TierStatus, type TokenUsage, type ToolCall, type ToolDefinition, type ToolExecuteOptions, ToolRegistry, type ToolResult, type ToolsConfig, VISION_MODEL_PRIORITY, type VectorStore, type WebSearchConfig, type WebhookConfig, type WorkspaceConfig, type WorkspaceFileReader, WorkspaceIndex, type WorkspaceIndexOptions, applyEndpointEdit, applyProviderApiKey, applyProviderCredential, applySettingsCredentials, applySettingsPayload, applySyncBundle, azureModelForDeployment, beginMcpOAuth, buildDocumentTools, buildManifest, buildSessionTranscript, bytesToBase64, cagCharBudget, chartKind, chartToTableRows, chatCompleterFromProviders, chunkCode, chunkText, commitSettings, compileSectionGraph, compileSubtaskGraph, compileTaskGraph, completeMcpOAuth, connectMcpWithLoopbackOAuth, createCascade, credentialDispositionForEdit, credentialEndpointIdentity, decryptJSON as decryptSyncBlob, diffManifest, disambiguateMcpServerNames, discoverMcpAuthServer, discoverMcpTools, distillSessionFacts, embedderFromProviders, encryptJSON as encryptSyncBlob, endpointFromSettingsPayload, evaluateAcceptance, explainRefusal, extractCharts, failures, fileExt, fileOAuthProvider, gatherSyncBundle, hasDefaultEndpoint, hasProviderCredential, hasUsableProvider, hashContent, heuristicCodeChunker, inferAzureBaseModel, inlineRuns, isDocumentFormat, isMcpToolName, matchImageLine, mcpServerPrefix, mcpToolName, nodeHttpFetch, normalizeEndpoint, parseBlocks, parseChartSpec, parseDelimited, parseRankOrder, parseSlide, planRetrieval, preferIpv4Host, priorAzureRow, reciprocalRankFusion, refreshMcpToken, removeMcpServerDenials, renderDocument, renderDocx, renderPptx, renderXlsx, runCascade, sameAzureEndpoint, sameCredentialEndpoint, sameEndpoint, sessionWorthRemembering, settingsSnapshot, sniffImage, splitSlides, streamCascade, stripInline, summarizeCompleted, undecided, uniqueMcpServerName };