cascade-ai 0.48.0 → 0.49.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 +26 -5
- package/dist/cli.cjs +1904 -55
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1904 -55
- package/dist/cli.js.map +1 -1
- package/dist/desktop-core.cjs +1841 -51
- package/dist/index.cjs +1841 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +87 -0
- package/dist/index.d.ts +87 -0
- package/dist/index.js +1841 -51
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -17,6 +17,21 @@ interface ModelInfo {
|
|
|
17
17
|
maxOutputTokens: number;
|
|
18
18
|
supportsStreaming: boolean;
|
|
19
19
|
isLocal: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* True when Cascade has NO price for this model — the cost fields above are
|
|
22
|
+
* 0 only because there is nothing to put in them.
|
|
23
|
+
*
|
|
24
|
+
* This exists because 0 is ambiguous: a local Ollama model genuinely costs
|
|
25
|
+
* nothing, while a newly-released cloud preview model that isn't in the
|
|
26
|
+
* pricing dataset costs real money we can't quote. Treating the second like
|
|
27
|
+
* the first made unknown-priced models report $0.00 spend, put them outside
|
|
28
|
+
* the reach of the per-run cost cap, and gave them the best possible score in
|
|
29
|
+
* the value-based rankers. Anything that reads the cost fields must consult
|
|
30
|
+
* this flag first (see `isPricingUnknown` in core/router/pricing.ts).
|
|
31
|
+
*
|
|
32
|
+
* Never set on local models — their $0 is real.
|
|
33
|
+
*/
|
|
34
|
+
pricingUnknown?: boolean;
|
|
20
35
|
minSizeB?: number;
|
|
21
36
|
/** Tool-use capability. False for Ollama; true for all cloud providers. */
|
|
22
37
|
supportsToolUse?: boolean;
|
|
@@ -46,6 +61,25 @@ interface ProviderConfig {
|
|
|
46
61
|
authToken?: string;
|
|
47
62
|
/** Where an adopted credential came from, e.g. "Claude Code". Informational. */
|
|
48
63
|
credentialSource?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Local-vs-hosted toggle. `true` declares "this endpoint runs on hardware I
|
|
66
|
+
* already pay for, so inference genuinely costs $0"; `false` declares it is a
|
|
67
|
+
* paid hosted endpoint, so an unpriced model there reports "cost not tracked"
|
|
68
|
+
* rather than free.
|
|
69
|
+
*
|
|
70
|
+
* Only meaningful for `ollama` and `openai-compatible`, which can each point
|
|
71
|
+
* at either. Left unset, it defaults sensibly: ollama ⇒ local, and
|
|
72
|
+
* openai-compatible ⇒ local when `baseUrl` is loopback/LAN (llama.cpp, LM
|
|
73
|
+
* Studio, vLLM on your own box) and hosted otherwise (Together, Groq, …).
|
|
74
|
+
* See `isLocalEndpoint` in core/router/pricing.ts.
|
|
75
|
+
*/
|
|
76
|
+
local?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Deployment region for providers whose price varies by region (Azure lists
|
|
79
|
+
* different rates for `global`, `us` and `eu` deployments of the same model).
|
|
80
|
+
* Matched against the pricing dataset's per-region entries.
|
|
81
|
+
*/
|
|
82
|
+
region?: string;
|
|
49
83
|
}
|
|
50
84
|
interface StreamChunk {
|
|
51
85
|
text: string;
|
|
@@ -57,6 +91,13 @@ interface TokenUsage {
|
|
|
57
91
|
outputTokens: number;
|
|
58
92
|
totalTokens: number;
|
|
59
93
|
estimatedCostUsd: number;
|
|
94
|
+
/**
|
|
95
|
+
* True when `estimatedCostUsd` is 0 because the model's price is UNKNOWN, not
|
|
96
|
+
* because the call was free. Cost readouts must say "not tracked" for these
|
|
97
|
+
* rather than "$0.00", and budget code must know the spend it just recorded
|
|
98
|
+
* is an undercount.
|
|
99
|
+
*/
|
|
100
|
+
costUnknown?: boolean;
|
|
60
101
|
}
|
|
61
102
|
interface GenerateOptions {
|
|
62
103
|
messages: ConversationMessage[];
|
|
@@ -1095,6 +1136,25 @@ interface DelegationSavings {
|
|
|
1095
1136
|
|
|
1096
1137
|
type BenchmarkProfile = Partial<Record<Exclude<TaskType, 'mixed'>, number>>;
|
|
1097
1138
|
|
|
1139
|
+
interface PriceDisagreement {
|
|
1140
|
+
modelId: string;
|
|
1141
|
+
provider: string;
|
|
1142
|
+
/** Per-1k rates the bundled dataset asserts. */
|
|
1143
|
+
dataset: {
|
|
1144
|
+
input: number;
|
|
1145
|
+
output: number;
|
|
1146
|
+
};
|
|
1147
|
+
/** Per-1k rates the live source asserts. */
|
|
1148
|
+
live: {
|
|
1149
|
+
input: number;
|
|
1150
|
+
output: number;
|
|
1151
|
+
};
|
|
1152
|
+
/** live/dataset ratio on the blended rate; >1 means live is more expensive. */
|
|
1153
|
+
ratio: number;
|
|
1154
|
+
datasetAsOf: string;
|
|
1155
|
+
datasetSource: string;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1098
1158
|
type DataSource = 'live' | 'cache' | 'bundled';
|
|
1099
1159
|
interface PriceEntry {
|
|
1100
1160
|
input: number;
|
|
@@ -1126,6 +1186,8 @@ declare class LiveDataProvider {
|
|
|
1126
1186
|
private snapshot;
|
|
1127
1187
|
private prices;
|
|
1128
1188
|
private capabilities;
|
|
1189
|
+
/** Dataset-vs-live price mismatches, deduped by `provider:modelId`. */
|
|
1190
|
+
private disagreements;
|
|
1129
1191
|
private source;
|
|
1130
1192
|
private fetchedAt;
|
|
1131
1193
|
private loaded;
|
|
@@ -1156,8 +1218,25 @@ declare class LiveDataProvider {
|
|
|
1156
1218
|
/**
|
|
1157
1219
|
* Returns a price-corrected copy of each model when live pricing is known,
|
|
1158
1220
|
* leaving the original untouched (so the shared catalog is never mutated).
|
|
1221
|
+
*
|
|
1222
|
+
* Reconciliation policy (see reconcilePrice in pricing.ts): the bundled
|
|
1223
|
+
* dataset is the authoritative baseline, and a live quote overrides it
|
|
1224
|
+
* because it is fresher by construction — but the disagreement is RECORDED,
|
|
1225
|
+
* not swallowed. A dataset/live mismatch is the best signal available that
|
|
1226
|
+
* the committed prices have gone stale, so it must be visible rather than
|
|
1227
|
+
* silently resolved in either direction. A live quote of $0 for a non-local
|
|
1228
|
+
* model is rejected outright: that is the very failure mode this change
|
|
1229
|
+
* exists to prevent, and a marketplace's free-tier alias must never zero out
|
|
1230
|
+
* the price of the paid model Cascade is actually calling.
|
|
1159
1231
|
*/
|
|
1160
1232
|
applyLivePricing(models: ModelInfo[]): ModelInfo[];
|
|
1233
|
+
private recordDisagreement;
|
|
1234
|
+
/**
|
|
1235
|
+
* Dataset-vs-live price mismatches seen this session, newest-model-first
|
|
1236
|
+
* insertion order. Surfaced by `cascade models --verbose`; a non-empty list
|
|
1237
|
+
* means src/core/router/pricing-data.json is probably due a refresh.
|
|
1238
|
+
*/
|
|
1239
|
+
getPriceDisagreements(): PriceDisagreement[];
|
|
1161
1240
|
/** Current capability facts for a model id, or null when unknown. */
|
|
1162
1241
|
getCapability(modelId: string): CapabilityEntry | null;
|
|
1163
1242
|
/**
|
|
@@ -1345,6 +1424,14 @@ interface RouterStats {
|
|
|
1345
1424
|
outputTokensByTier: Record<string, number>;
|
|
1346
1425
|
/** Accumulated cost (USD) broken down by feature tag (e.g. T2 section names). */
|
|
1347
1426
|
costByFeature: Record<string, number>;
|
|
1427
|
+
/**
|
|
1428
|
+
* Calls made against models Cascade has no price for. Their spend is NOT in
|
|
1429
|
+
* `totalCostUsd` — it can't be — so a non-zero count here means the totals
|
|
1430
|
+
* above (and any budget check derived from them) are an undercount.
|
|
1431
|
+
*/
|
|
1432
|
+
untrackedCostCalls: number;
|
|
1433
|
+
/** Ids of the models responsible, for "cost not tracked for: …" readouts. */
|
|
1434
|
+
untrackedCostModels: string[];
|
|
1348
1435
|
}
|
|
1349
1436
|
declare class CascadeRouter extends EventEmitter {
|
|
1350
1437
|
private selector;
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,21 @@ interface ModelInfo {
|
|
|
17
17
|
maxOutputTokens: number;
|
|
18
18
|
supportsStreaming: boolean;
|
|
19
19
|
isLocal: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* True when Cascade has NO price for this model — the cost fields above are
|
|
22
|
+
* 0 only because there is nothing to put in them.
|
|
23
|
+
*
|
|
24
|
+
* This exists because 0 is ambiguous: a local Ollama model genuinely costs
|
|
25
|
+
* nothing, while a newly-released cloud preview model that isn't in the
|
|
26
|
+
* pricing dataset costs real money we can't quote. Treating the second like
|
|
27
|
+
* the first made unknown-priced models report $0.00 spend, put them outside
|
|
28
|
+
* the reach of the per-run cost cap, and gave them the best possible score in
|
|
29
|
+
* the value-based rankers. Anything that reads the cost fields must consult
|
|
30
|
+
* this flag first (see `isPricingUnknown` in core/router/pricing.ts).
|
|
31
|
+
*
|
|
32
|
+
* Never set on local models — their $0 is real.
|
|
33
|
+
*/
|
|
34
|
+
pricingUnknown?: boolean;
|
|
20
35
|
minSizeB?: number;
|
|
21
36
|
/** Tool-use capability. False for Ollama; true for all cloud providers. */
|
|
22
37
|
supportsToolUse?: boolean;
|
|
@@ -46,6 +61,25 @@ interface ProviderConfig {
|
|
|
46
61
|
authToken?: string;
|
|
47
62
|
/** Where an adopted credential came from, e.g. "Claude Code". Informational. */
|
|
48
63
|
credentialSource?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Local-vs-hosted toggle. `true` declares "this endpoint runs on hardware I
|
|
66
|
+
* already pay for, so inference genuinely costs $0"; `false` declares it is a
|
|
67
|
+
* paid hosted endpoint, so an unpriced model there reports "cost not tracked"
|
|
68
|
+
* rather than free.
|
|
69
|
+
*
|
|
70
|
+
* Only meaningful for `ollama` and `openai-compatible`, which can each point
|
|
71
|
+
* at either. Left unset, it defaults sensibly: ollama ⇒ local, and
|
|
72
|
+
* openai-compatible ⇒ local when `baseUrl` is loopback/LAN (llama.cpp, LM
|
|
73
|
+
* Studio, vLLM on your own box) and hosted otherwise (Together, Groq, …).
|
|
74
|
+
* See `isLocalEndpoint` in core/router/pricing.ts.
|
|
75
|
+
*/
|
|
76
|
+
local?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Deployment region for providers whose price varies by region (Azure lists
|
|
79
|
+
* different rates for `global`, `us` and `eu` deployments of the same model).
|
|
80
|
+
* Matched against the pricing dataset's per-region entries.
|
|
81
|
+
*/
|
|
82
|
+
region?: string;
|
|
49
83
|
}
|
|
50
84
|
interface StreamChunk {
|
|
51
85
|
text: string;
|
|
@@ -57,6 +91,13 @@ interface TokenUsage {
|
|
|
57
91
|
outputTokens: number;
|
|
58
92
|
totalTokens: number;
|
|
59
93
|
estimatedCostUsd: number;
|
|
94
|
+
/**
|
|
95
|
+
* True when `estimatedCostUsd` is 0 because the model's price is UNKNOWN, not
|
|
96
|
+
* because the call was free. Cost readouts must say "not tracked" for these
|
|
97
|
+
* rather than "$0.00", and budget code must know the spend it just recorded
|
|
98
|
+
* is an undercount.
|
|
99
|
+
*/
|
|
100
|
+
costUnknown?: boolean;
|
|
60
101
|
}
|
|
61
102
|
interface GenerateOptions {
|
|
62
103
|
messages: ConversationMessage[];
|
|
@@ -1095,6 +1136,25 @@ interface DelegationSavings {
|
|
|
1095
1136
|
|
|
1096
1137
|
type BenchmarkProfile = Partial<Record<Exclude<TaskType, 'mixed'>, number>>;
|
|
1097
1138
|
|
|
1139
|
+
interface PriceDisagreement {
|
|
1140
|
+
modelId: string;
|
|
1141
|
+
provider: string;
|
|
1142
|
+
/** Per-1k rates the bundled dataset asserts. */
|
|
1143
|
+
dataset: {
|
|
1144
|
+
input: number;
|
|
1145
|
+
output: number;
|
|
1146
|
+
};
|
|
1147
|
+
/** Per-1k rates the live source asserts. */
|
|
1148
|
+
live: {
|
|
1149
|
+
input: number;
|
|
1150
|
+
output: number;
|
|
1151
|
+
};
|
|
1152
|
+
/** live/dataset ratio on the blended rate; >1 means live is more expensive. */
|
|
1153
|
+
ratio: number;
|
|
1154
|
+
datasetAsOf: string;
|
|
1155
|
+
datasetSource: string;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1098
1158
|
type DataSource = 'live' | 'cache' | 'bundled';
|
|
1099
1159
|
interface PriceEntry {
|
|
1100
1160
|
input: number;
|
|
@@ -1126,6 +1186,8 @@ declare class LiveDataProvider {
|
|
|
1126
1186
|
private snapshot;
|
|
1127
1187
|
private prices;
|
|
1128
1188
|
private capabilities;
|
|
1189
|
+
/** Dataset-vs-live price mismatches, deduped by `provider:modelId`. */
|
|
1190
|
+
private disagreements;
|
|
1129
1191
|
private source;
|
|
1130
1192
|
private fetchedAt;
|
|
1131
1193
|
private loaded;
|
|
@@ -1156,8 +1218,25 @@ declare class LiveDataProvider {
|
|
|
1156
1218
|
/**
|
|
1157
1219
|
* Returns a price-corrected copy of each model when live pricing is known,
|
|
1158
1220
|
* leaving the original untouched (so the shared catalog is never mutated).
|
|
1221
|
+
*
|
|
1222
|
+
* Reconciliation policy (see reconcilePrice in pricing.ts): the bundled
|
|
1223
|
+
* dataset is the authoritative baseline, and a live quote overrides it
|
|
1224
|
+
* because it is fresher by construction — but the disagreement is RECORDED,
|
|
1225
|
+
* not swallowed. A dataset/live mismatch is the best signal available that
|
|
1226
|
+
* the committed prices have gone stale, so it must be visible rather than
|
|
1227
|
+
* silently resolved in either direction. A live quote of $0 for a non-local
|
|
1228
|
+
* model is rejected outright: that is the very failure mode this change
|
|
1229
|
+
* exists to prevent, and a marketplace's free-tier alias must never zero out
|
|
1230
|
+
* the price of the paid model Cascade is actually calling.
|
|
1159
1231
|
*/
|
|
1160
1232
|
applyLivePricing(models: ModelInfo[]): ModelInfo[];
|
|
1233
|
+
private recordDisagreement;
|
|
1234
|
+
/**
|
|
1235
|
+
* Dataset-vs-live price mismatches seen this session, newest-model-first
|
|
1236
|
+
* insertion order. Surfaced by `cascade models --verbose`; a non-empty list
|
|
1237
|
+
* means src/core/router/pricing-data.json is probably due a refresh.
|
|
1238
|
+
*/
|
|
1239
|
+
getPriceDisagreements(): PriceDisagreement[];
|
|
1161
1240
|
/** Current capability facts for a model id, or null when unknown. */
|
|
1162
1241
|
getCapability(modelId: string): CapabilityEntry | null;
|
|
1163
1242
|
/**
|
|
@@ -1345,6 +1424,14 @@ interface RouterStats {
|
|
|
1345
1424
|
outputTokensByTier: Record<string, number>;
|
|
1346
1425
|
/** Accumulated cost (USD) broken down by feature tag (e.g. T2 section names). */
|
|
1347
1426
|
costByFeature: Record<string, number>;
|
|
1427
|
+
/**
|
|
1428
|
+
* Calls made against models Cascade has no price for. Their spend is NOT in
|
|
1429
|
+
* `totalCostUsd` — it can't be — so a non-zero count here means the totals
|
|
1430
|
+
* above (and any budget check derived from them) are an undercount.
|
|
1431
|
+
*/
|
|
1432
|
+
untrackedCostCalls: number;
|
|
1433
|
+
/** Ids of the models responsible, for "cost not tracked for: …" readouts. */
|
|
1434
|
+
untrackedCostModels: string[];
|
|
1348
1435
|
}
|
|
1349
1436
|
declare class CascadeRouter extends EventEmitter {
|
|
1350
1437
|
private selector;
|