@steel-dev/atlas 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +219 -0
- package/dist/agent.d.ts +34 -0
- package/dist/agent.js +133 -0
- package/dist/async.d.ts +19 -0
- package/dist/async.js +172 -0
- package/dist/atlas.d.ts +19 -0
- package/dist/atlas.js +69 -0
- package/dist/budget.d.ts +64 -0
- package/dist/budget.js +336 -0
- package/dist/checklist.d.ts +115 -0
- package/dist/checklist.js +297 -0
- package/dist/cli.js +38700 -0
- package/dist/config.d.ts +80 -0
- package/dist/config.js +109 -0
- package/dist/context.d.ts +26 -0
- package/dist/context.js +250 -0
- package/dist/custom-tools.d.ts +26 -0
- package/dist/custom-tools.js +33 -0
- package/dist/defaults.d.ts +10 -0
- package/dist/defaults.js +37 -0
- package/dist/economy.d.ts +12 -0
- package/dist/economy.js +6 -0
- package/dist/env.d.ts +1 -0
- package/dist/env.js +8 -0
- package/dist/errors.d.ts +6 -0
- package/dist/errors.js +11 -0
- package/dist/event-hub.d.ts +11 -0
- package/dist/event-hub.js +83 -0
- package/dist/events.d.ts +105 -0
- package/dist/events.js +1 -0
- package/dist/html-extract.d.ts +21 -0
- package/dist/html-extract.js +459 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +26 -0
- package/dist/memory.d.ts +2 -0
- package/dist/memory.js +38 -0
- package/dist/model.d.ts +49 -0
- package/dist/model.js +630 -0
- package/dist/orchestrate.d.ts +5 -0
- package/dist/orchestrate.js +277 -0
- package/dist/pdf-extract.d.ts +5 -0
- package/dist/pdf-extract.js +20 -0
- package/dist/prompts.d.ts +2 -0
- package/dist/prompts.js +6 -0
- package/dist/providers/domain/arxiv.d.ts +6 -0
- package/dist/providers/domain/arxiv.js +83 -0
- package/dist/providers/domain/clinicaltrials.d.ts +6 -0
- package/dist/providers/domain/clinicaltrials.js +104 -0
- package/dist/providers/domain/edgar.d.ts +10 -0
- package/dist/providers/domain/edgar.js +92 -0
- package/dist/providers/domain/index.d.ts +14 -0
- package/dist/providers/domain/index.js +7 -0
- package/dist/providers/domain/openalex.d.ts +7 -0
- package/dist/providers/domain/openalex.js +128 -0
- package/dist/providers/domain/pubmed.d.ts +8 -0
- package/dist/providers/domain/pubmed.js +123 -0
- package/dist/providers/domain/semantic-scholar.d.ts +6 -0
- package/dist/providers/domain/semantic-scholar.js +112 -0
- package/dist/providers/domain/shared.d.ts +12 -0
- package/dist/providers/domain/shared.js +39 -0
- package/dist/providers/domain/wikipedia.d.ts +6 -0
- package/dist/providers/domain/wikipedia.js +71 -0
- package/dist/providers/exa-agent.d.ts +9 -0
- package/dist/providers/exa-agent.js +67 -0
- package/dist/providers/fetch.d.ts +66 -0
- package/dist/providers/fetch.js +675 -0
- package/dist/providers/parallel-agent.d.ts +11 -0
- package/dist/providers/parallel-agent.js +100 -0
- package/dist/providers/perplexity-agent.d.ts +17 -0
- package/dist/providers/perplexity-agent.js +86 -0
- package/dist/providers/search.d.ts +65 -0
- package/dist/providers/search.js +433 -0
- package/dist/providers/store.d.ts +48 -0
- package/dist/providers/store.js +217 -0
- package/dist/researcher.d.ts +20 -0
- package/dist/researcher.js +3 -0
- package/dist/robots.d.ts +16 -0
- package/dist/robots.js +146 -0
- package/dist/roles.d.ts +6 -0
- package/dist/roles.js +4 -0
- package/dist/run.d.ts +65 -0
- package/dist/run.js +371 -0
- package/dist/safe-dispatcher.d.ts +16 -0
- package/dist/safe-dispatcher.js +32 -0
- package/dist/safety.d.ts +23 -0
- package/dist/safety.js +206 -0
- package/dist/sandbox.d.ts +22 -0
- package/dist/sandbox.js +228 -0
- package/dist/search-normalize.d.ts +2 -0
- package/dist/search-normalize.js +13 -0
- package/dist/source-documents.d.ts +77 -0
- package/dist/source-documents.js +421 -0
- package/dist/sources.d.ts +57 -0
- package/dist/sources.js +1 -0
- package/dist/spine.d.ts +19 -0
- package/dist/spine.js +722 -0
- package/dist/state.d.ts +90 -0
- package/dist/state.js +27 -0
- package/dist/structured.d.ts +7 -0
- package/dist/structured.js +18 -0
- package/dist/tools.d.ts +33 -0
- package/dist/tools.js +1187 -0
- package/dist/trace-digest.d.ts +11 -0
- package/dist/trace-digest.js +309 -0
- package/dist/trace.d.ts +225 -0
- package/dist/trace.js +278 -0
- package/dist/trail.d.ts +15 -0
- package/dist/trail.js +74 -0
- package/dist/url.d.ts +1 -0
- package/dist/url.js +25 -0
- package/package.json +107 -0
package/dist/budget.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export interface ModelPricing {
|
|
2
|
+
inputPerMTok: number;
|
|
3
|
+
outputPerMTok: number;
|
|
4
|
+
cacheReadPerMTok?: number;
|
|
5
|
+
cacheWritePerMTok?: number;
|
|
6
|
+
}
|
|
7
|
+
export type PricingTable = Record<string, ModelPricing>;
|
|
8
|
+
export declare const DEFAULT_PRICING: PricingTable;
|
|
9
|
+
export interface TokenUsage {
|
|
10
|
+
input: number;
|
|
11
|
+
output: number;
|
|
12
|
+
cacheRead: number;
|
|
13
|
+
cacheWrite: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function emptyTokenUsage(): TokenUsage;
|
|
16
|
+
export declare function addTokenUsage(target: TokenUsage, delta: TokenUsage): void;
|
|
17
|
+
export declare function resolvePricing(modelId: string | undefined, table: PricingTable): {
|
|
18
|
+
pricing: ModelPricing;
|
|
19
|
+
known: boolean;
|
|
20
|
+
};
|
|
21
|
+
export declare function usageCostUSD(usage: TokenUsage, pricing: ModelPricing): number;
|
|
22
|
+
export interface GrantOptions {
|
|
23
|
+
fraction?: number;
|
|
24
|
+
maxUSD?: number;
|
|
25
|
+
minUSD?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface BudgetHold {
|
|
28
|
+
settle(actualUSD: number): void;
|
|
29
|
+
release(): void;
|
|
30
|
+
}
|
|
31
|
+
export interface BudgetGrant {
|
|
32
|
+
readonly limitUSD: number;
|
|
33
|
+
spentUSD(): number;
|
|
34
|
+
remainingUSD(): number;
|
|
35
|
+
floored(): boolean;
|
|
36
|
+
charge(usd: number): void;
|
|
37
|
+
reserve(usd: number): BudgetHold | null;
|
|
38
|
+
grant(opts?: GrantOptions): BudgetGrant | null;
|
|
39
|
+
release(): void;
|
|
40
|
+
}
|
|
41
|
+
export interface BudgetMeter extends BudgetGrant {
|
|
42
|
+
readonly totalUSD: number;
|
|
43
|
+
totalSpentUSD(): number;
|
|
44
|
+
exhausted(): boolean;
|
|
45
|
+
}
|
|
46
|
+
export declare function createBudgetMeter(totalUSD: number): BudgetMeter;
|
|
47
|
+
export declare function withGrant<T>(reserve: BudgetGrant, opts: GrantOptions, fn: (grant: BudgetGrant) => Promise<T>): Promise<T | null>;
|
|
48
|
+
export type SpineScope = "single_fact" | "broad";
|
|
49
|
+
export interface BudgetPlanInput {
|
|
50
|
+
budgetUSD: number;
|
|
51
|
+
maxTokens: number;
|
|
52
|
+
maxReportTokens: number;
|
|
53
|
+
scope: SpineScope;
|
|
54
|
+
researchPricing: ModelPricing;
|
|
55
|
+
}
|
|
56
|
+
export interface BudgetPlan {
|
|
57
|
+
feasible: boolean;
|
|
58
|
+
reason?: string;
|
|
59
|
+
effectiveTokens: number;
|
|
60
|
+
draftReserveTokens: number;
|
|
61
|
+
gatherCeilingTokens: number;
|
|
62
|
+
}
|
|
63
|
+
export declare function resolveBudgetPlan(input: BudgetPlanInput): BudgetPlan;
|
|
64
|
+
export declare function minViableSubtaskUSD(scope: SpineScope, maxReportTokens: number, researchPricing: ModelPricing): number;
|
package/dist/budget.js
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import { ECONOMY } from "./economy.js";
|
|
2
|
+
export const DEFAULT_PRICING = {
|
|
3
|
+
"claude-fable-5": { inputPerMTok: 10, outputPerMTok: 50 },
|
|
4
|
+
"claude-opus-4-8": { inputPerMTok: 5, outputPerMTok: 25 },
|
|
5
|
+
"claude-opus-4-7": { inputPerMTok: 5, outputPerMTok: 25 },
|
|
6
|
+
"claude-opus-4-6": { inputPerMTok: 5, outputPerMTok: 25 },
|
|
7
|
+
"claude-opus-4-5": { inputPerMTok: 5, outputPerMTok: 25 },
|
|
8
|
+
"claude-opus-4-1": { inputPerMTok: 15, outputPerMTok: 75 },
|
|
9
|
+
"claude-sonnet-4-6": { inputPerMTok: 3, outputPerMTok: 15 },
|
|
10
|
+
"claude-sonnet-4-5": { inputPerMTok: 3, outputPerMTok: 15 },
|
|
11
|
+
"claude-haiku-4-5": { inputPerMTok: 1, outputPerMTok: 5 },
|
|
12
|
+
"gpt-5.5": { inputPerMTok: 1.25, outputPerMTok: 10 },
|
|
13
|
+
"gpt-5.1": { inputPerMTok: 1.25, outputPerMTok: 10 },
|
|
14
|
+
"gpt-5": { inputPerMTok: 1.25, outputPerMTok: 10 },
|
|
15
|
+
"gpt-5-mini": { inputPerMTok: 0.25, outputPerMTok: 2 },
|
|
16
|
+
"gpt-5-nano": { inputPerMTok: 0.05, outputPerMTok: 0.4 },
|
|
17
|
+
"gpt-4o": { inputPerMTok: 2.5, outputPerMTok: 10 },
|
|
18
|
+
"gpt-4o-mini": { inputPerMTok: 0.15, outputPerMTok: 0.6 },
|
|
19
|
+
"o4-mini-deep-research": { inputPerMTok: 2, outputPerMTok: 8 },
|
|
20
|
+
"gemini-2.5-pro": { inputPerMTok: 1.25, outputPerMTok: 10 },
|
|
21
|
+
"gemini-2.5-flash": { inputPerMTok: 0.3, outputPerMTok: 2.5 },
|
|
22
|
+
"gemini-3-flash-preview": { inputPerMTok: 0.5, outputPerMTok: 3 },
|
|
23
|
+
"gemini-3.1-flash-lite": { inputPerMTok: 0.25, outputPerMTok: 1.5 },
|
|
24
|
+
"gemini-3.5-flash": { inputPerMTok: 1.5, outputPerMTok: 9 },
|
|
25
|
+
"GLM-5.2": {
|
|
26
|
+
inputPerMTok: 1.4,
|
|
27
|
+
cacheReadPerMTok: 0.26,
|
|
28
|
+
cacheWritePerMTok: 0,
|
|
29
|
+
outputPerMTok: 4.4,
|
|
30
|
+
},
|
|
31
|
+
"GLM-5.1": {
|
|
32
|
+
inputPerMTok: 1.4,
|
|
33
|
+
cacheReadPerMTok: 0.26,
|
|
34
|
+
cacheWritePerMTok: 0,
|
|
35
|
+
outputPerMTok: 4.4,
|
|
36
|
+
},
|
|
37
|
+
"GLM-5": {
|
|
38
|
+
inputPerMTok: 1,
|
|
39
|
+
cacheReadPerMTok: 0.2,
|
|
40
|
+
cacheWritePerMTok: 0,
|
|
41
|
+
outputPerMTok: 3.2,
|
|
42
|
+
},
|
|
43
|
+
"GLM-5-Turbo": {
|
|
44
|
+
inputPerMTok: 1.2,
|
|
45
|
+
cacheReadPerMTok: 0.24,
|
|
46
|
+
cacheWritePerMTok: 0,
|
|
47
|
+
outputPerMTok: 4,
|
|
48
|
+
},
|
|
49
|
+
"GLM-4.7": {
|
|
50
|
+
inputPerMTok: 0.6,
|
|
51
|
+
cacheReadPerMTok: 0.11,
|
|
52
|
+
cacheWritePerMTok: 0,
|
|
53
|
+
outputPerMTok: 2.2,
|
|
54
|
+
},
|
|
55
|
+
"GLM-4.7-FlashX": {
|
|
56
|
+
inputPerMTok: 0.07,
|
|
57
|
+
cacheReadPerMTok: 0.01,
|
|
58
|
+
cacheWritePerMTok: 0,
|
|
59
|
+
outputPerMTok: 0.4,
|
|
60
|
+
},
|
|
61
|
+
"GLM-4.6": {
|
|
62
|
+
inputPerMTok: 0.6,
|
|
63
|
+
cacheReadPerMTok: 0.11,
|
|
64
|
+
cacheWritePerMTok: 0,
|
|
65
|
+
outputPerMTok: 2.2,
|
|
66
|
+
},
|
|
67
|
+
"GLM-4.5": {
|
|
68
|
+
inputPerMTok: 0.6,
|
|
69
|
+
cacheReadPerMTok: 0.11,
|
|
70
|
+
cacheWritePerMTok: 0,
|
|
71
|
+
outputPerMTok: 2.2,
|
|
72
|
+
},
|
|
73
|
+
"GLM-4.5-X": {
|
|
74
|
+
inputPerMTok: 2.2,
|
|
75
|
+
cacheReadPerMTok: 0.45,
|
|
76
|
+
cacheWritePerMTok: 0,
|
|
77
|
+
outputPerMTok: 8.9,
|
|
78
|
+
},
|
|
79
|
+
"GLM-4.5-Air": {
|
|
80
|
+
inputPerMTok: 0.2,
|
|
81
|
+
cacheReadPerMTok: 0.03,
|
|
82
|
+
cacheWritePerMTok: 0,
|
|
83
|
+
outputPerMTok: 1.1,
|
|
84
|
+
},
|
|
85
|
+
"GLM-4.5-AirX": {
|
|
86
|
+
inputPerMTok: 1.1,
|
|
87
|
+
cacheReadPerMTok: 0.22,
|
|
88
|
+
cacheWritePerMTok: 0,
|
|
89
|
+
outputPerMTok: 4.5,
|
|
90
|
+
},
|
|
91
|
+
"GLM-4-32B-0414-128K": {
|
|
92
|
+
inputPerMTok: 0.1,
|
|
93
|
+
outputPerMTok: 0.1,
|
|
94
|
+
},
|
|
95
|
+
"GLM-4.7-Flash": { inputPerMTok: 0, outputPerMTok: 0 },
|
|
96
|
+
"GLM-4.5-Flash": { inputPerMTok: 0, outputPerMTok: 0 },
|
|
97
|
+
};
|
|
98
|
+
for (const pricing of Object.values(DEFAULT_PRICING)) {
|
|
99
|
+
Object.freeze(pricing);
|
|
100
|
+
}
|
|
101
|
+
Object.freeze(DEFAULT_PRICING);
|
|
102
|
+
const UNKNOWN_MODEL_PRICING = {
|
|
103
|
+
inputPerMTok: 3,
|
|
104
|
+
outputPerMTok: 15,
|
|
105
|
+
};
|
|
106
|
+
const CACHE_READ_FACTOR = 0.1;
|
|
107
|
+
const CACHE_WRITE_FACTOR = 1.25;
|
|
108
|
+
export function emptyTokenUsage() {
|
|
109
|
+
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
110
|
+
}
|
|
111
|
+
export function addTokenUsage(target, delta) {
|
|
112
|
+
target.input += delta.input;
|
|
113
|
+
target.output += delta.output;
|
|
114
|
+
target.cacheRead += delta.cacheRead;
|
|
115
|
+
target.cacheWrite += delta.cacheWrite;
|
|
116
|
+
}
|
|
117
|
+
export function resolvePricing(modelId, table) {
|
|
118
|
+
if (!modelId)
|
|
119
|
+
return { pricing: UNKNOWN_MODEL_PRICING, known: false };
|
|
120
|
+
const lookup = (candidate) => {
|
|
121
|
+
const direct = table[candidate];
|
|
122
|
+
if (direct)
|
|
123
|
+
return direct;
|
|
124
|
+
const caseInsensitiveKey = Object.keys(table).find((key) => key.toLowerCase() === candidate.toLowerCase());
|
|
125
|
+
return caseInsensitiveKey ? table[caseInsensitiveKey] : undefined;
|
|
126
|
+
};
|
|
127
|
+
const direct = lookup(modelId);
|
|
128
|
+
if (direct)
|
|
129
|
+
return { pricing: direct, known: true };
|
|
130
|
+
const undated = modelId
|
|
131
|
+
.replace(/-\d{4}-\d{2}-\d{2}$/, "")
|
|
132
|
+
.replace(/-\d{8}$/, "");
|
|
133
|
+
const undatedPricing = lookup(undated);
|
|
134
|
+
if (undatedPricing)
|
|
135
|
+
return { pricing: undatedPricing, known: true };
|
|
136
|
+
const parts = undated.split(".");
|
|
137
|
+
for (let i = 1; i < parts.length; i++) {
|
|
138
|
+
const candidate = lookup(parts.slice(i).join("."));
|
|
139
|
+
if (candidate)
|
|
140
|
+
return { pricing: candidate, known: true };
|
|
141
|
+
}
|
|
142
|
+
const haystack = undated.toLowerCase();
|
|
143
|
+
let bestKey;
|
|
144
|
+
for (const key of Object.keys(table)) {
|
|
145
|
+
const needle = key.toLowerCase();
|
|
146
|
+
if (haystack.startsWith(`${needle}-`) || haystack.endsWith(`.${needle}`)) {
|
|
147
|
+
if (bestKey === undefined || key.length > bestKey.length)
|
|
148
|
+
bestKey = key;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (bestKey)
|
|
152
|
+
return { pricing: table[bestKey], known: true };
|
|
153
|
+
return { pricing: UNKNOWN_MODEL_PRICING, known: false };
|
|
154
|
+
}
|
|
155
|
+
export function usageCostUSD(usage, pricing) {
|
|
156
|
+
const cacheRead = pricing.cacheReadPerMTok ?? pricing.inputPerMTok * CACHE_READ_FACTOR;
|
|
157
|
+
const cacheWrite = pricing.cacheWritePerMTok ?? pricing.inputPerMTok * CACHE_WRITE_FACTOR;
|
|
158
|
+
return ((usage.input * pricing.inputPerMTok +
|
|
159
|
+
usage.output * pricing.outputPerMTok +
|
|
160
|
+
usage.cacheRead * cacheRead +
|
|
161
|
+
usage.cacheWrite * cacheWrite) /
|
|
162
|
+
1_000_000);
|
|
163
|
+
}
|
|
164
|
+
const GRANT_FLOOR_USD = ECONOMY.grantFloorUSD;
|
|
165
|
+
const DEFAULT_GRANT_FRACTION = ECONOMY.defaultGrantFraction;
|
|
166
|
+
const METER_EXHAUSTION_EPSILON_USD = 0.01;
|
|
167
|
+
class GrantNode {
|
|
168
|
+
shared;
|
|
169
|
+
parent;
|
|
170
|
+
limitUSD;
|
|
171
|
+
used = 0;
|
|
172
|
+
childReserved = 0;
|
|
173
|
+
held = 0;
|
|
174
|
+
active = true;
|
|
175
|
+
constructor(limitUSD, shared, parent) {
|
|
176
|
+
this.shared = shared;
|
|
177
|
+
this.parent = parent;
|
|
178
|
+
this.limitUSD = limitUSD;
|
|
179
|
+
}
|
|
180
|
+
spentUSD() {
|
|
181
|
+
return this.used;
|
|
182
|
+
}
|
|
183
|
+
remainingUSD() {
|
|
184
|
+
return Math.max(0, this.limitUSD - this.used - this.childReserved - this.held);
|
|
185
|
+
}
|
|
186
|
+
floored() {
|
|
187
|
+
return this.remainingUSD() < GRANT_FLOOR_USD;
|
|
188
|
+
}
|
|
189
|
+
charge(usd) {
|
|
190
|
+
if (!Number.isFinite(usd) || usd <= 0)
|
|
191
|
+
return;
|
|
192
|
+
this.used += usd;
|
|
193
|
+
this.shared.spent += usd;
|
|
194
|
+
}
|
|
195
|
+
reserve(usd) {
|
|
196
|
+
if (!Number.isFinite(usd) || usd <= 0)
|
|
197
|
+
return null;
|
|
198
|
+
const amount = Math.min(usd, this.remainingUSD());
|
|
199
|
+
if (amount <= 0)
|
|
200
|
+
return null;
|
|
201
|
+
this.held += amount;
|
|
202
|
+
let open = true;
|
|
203
|
+
const free = () => {
|
|
204
|
+
if (!open)
|
|
205
|
+
return false;
|
|
206
|
+
open = false;
|
|
207
|
+
this.held = Math.max(0, this.held - amount);
|
|
208
|
+
return true;
|
|
209
|
+
};
|
|
210
|
+
return {
|
|
211
|
+
settle: (actualUSD) => {
|
|
212
|
+
if (free())
|
|
213
|
+
this.charge(actualUSD);
|
|
214
|
+
},
|
|
215
|
+
release: () => {
|
|
216
|
+
free();
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
grant(opts = {}) {
|
|
221
|
+
const remaining = this.remainingUSD();
|
|
222
|
+
if (remaining < GRANT_FLOOR_USD)
|
|
223
|
+
return null;
|
|
224
|
+
const fraction = clampFraction(opts.fraction);
|
|
225
|
+
let want = opts.maxUSD ?? remaining * fraction;
|
|
226
|
+
want = Math.max(want, opts.minUSD ?? GRANT_FLOOR_USD);
|
|
227
|
+
const amount = Math.min(want, remaining);
|
|
228
|
+
if (amount < GRANT_FLOOR_USD)
|
|
229
|
+
return null;
|
|
230
|
+
this.childReserved += amount;
|
|
231
|
+
return new GrantNode(amount, this.shared, this);
|
|
232
|
+
}
|
|
233
|
+
release() {
|
|
234
|
+
if (!this.active || !this.parent)
|
|
235
|
+
return;
|
|
236
|
+
this.active = false;
|
|
237
|
+
this.parent.absorbChild(this.limitUSD, this.used);
|
|
238
|
+
}
|
|
239
|
+
absorbChild(limit, used) {
|
|
240
|
+
this.childReserved = Math.max(0, this.childReserved - limit);
|
|
241
|
+
this.used += used;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
class RootMeter extends GrantNode {
|
|
245
|
+
totalUSD;
|
|
246
|
+
constructor(totalUSD, shared) {
|
|
247
|
+
super(totalUSD, shared, null);
|
|
248
|
+
this.totalUSD = totalUSD;
|
|
249
|
+
}
|
|
250
|
+
totalSpentUSD() {
|
|
251
|
+
return this.shared.spent;
|
|
252
|
+
}
|
|
253
|
+
exhausted() {
|
|
254
|
+
return this.totalSpentUSD() >= this.totalUSD - METER_EXHAUSTION_EPSILON_USD;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
function clampFraction(fraction) {
|
|
258
|
+
if (fraction === undefined || !Number.isFinite(fraction)) {
|
|
259
|
+
return DEFAULT_GRANT_FRACTION;
|
|
260
|
+
}
|
|
261
|
+
return Math.min(1, Math.max(0.01, fraction));
|
|
262
|
+
}
|
|
263
|
+
export function createBudgetMeter(totalUSD) {
|
|
264
|
+
if (!Number.isFinite(totalUSD) || totalUSD <= 0) {
|
|
265
|
+
throw new Error(`budget: totalUSD must be > 0 (got ${totalUSD})`);
|
|
266
|
+
}
|
|
267
|
+
return new RootMeter(totalUSD, { spent: 0 });
|
|
268
|
+
}
|
|
269
|
+
export async function withGrant(reserve, opts, fn) {
|
|
270
|
+
const grant = reserve.grant(opts);
|
|
271
|
+
if (!grant)
|
|
272
|
+
return null;
|
|
273
|
+
try {
|
|
274
|
+
return await fn(grant);
|
|
275
|
+
}
|
|
276
|
+
finally {
|
|
277
|
+
grant.release();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const PLAN_RESERVE_TOKENS = 2_000;
|
|
281
|
+
const DRAFT_CONTEXT_TOKENS_BROAD = 48_000;
|
|
282
|
+
const DRAFT_CONTEXT_TOKENS_SINGLE = 8_000;
|
|
283
|
+
const SINGLE_FACT_REPORT_TOKENS = 2_000;
|
|
284
|
+
const GATHER_MIN_TOKENS_BROAD = 60_000;
|
|
285
|
+
const GATHER_MIN_TOKENS_SINGLE = 24_000;
|
|
286
|
+
const TOKEN_BLEND_INPUT = 0.85;
|
|
287
|
+
const TOKEN_BLEND_OUTPUT = 0.15;
|
|
288
|
+
function blendedUsdPerToken(pricing) {
|
|
289
|
+
return ((TOKEN_BLEND_INPUT * pricing.inputPerMTok +
|
|
290
|
+
TOKEN_BLEND_OUTPUT * pricing.outputPerMTok) /
|
|
291
|
+
1_000_000);
|
|
292
|
+
}
|
|
293
|
+
export function resolveBudgetPlan(input) {
|
|
294
|
+
const single = input.scope === "single_fact";
|
|
295
|
+
const reportTokens = single
|
|
296
|
+
? Math.min(input.maxReportTokens, SINGLE_FACT_REPORT_TOKENS)
|
|
297
|
+
: input.maxReportTokens;
|
|
298
|
+
const draftReserveTokens = (single ? DRAFT_CONTEXT_TOKENS_SINGLE : DRAFT_CONTEXT_TOKENS_BROAD) +
|
|
299
|
+
reportTokens;
|
|
300
|
+
const usdPerToken = blendedUsdPerToken(input.researchPricing);
|
|
301
|
+
const budgetTokens = usdPerToken > 0 ? Math.floor(input.budgetUSD / usdPerToken) : Infinity;
|
|
302
|
+
const effectiveTokens = Math.min(input.maxTokens, budgetTokens);
|
|
303
|
+
const gatherCeilingTokens = Math.max(0, effectiveTokens - PLAN_RESERVE_TOKENS - draftReserveTokens);
|
|
304
|
+
const minGather = single ? GATHER_MIN_TOKENS_SINGLE : GATHER_MIN_TOKENS_BROAD;
|
|
305
|
+
const feasible = gatherCeilingTokens >= minGather;
|
|
306
|
+
if (feasible) {
|
|
307
|
+
return {
|
|
308
|
+
feasible,
|
|
309
|
+
effectiveTokens,
|
|
310
|
+
draftReserveTokens,
|
|
311
|
+
gatherCeilingTokens,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
const minTokens = PLAN_RESERVE_TOKENS + draftReserveTokens + minGather;
|
|
315
|
+
const reason = usdPerToken > 0
|
|
316
|
+
? `budget.maxUSD $${input.budgetUSD} is too low for this model on a ${input.scope} question — about $${(minTokens * usdPerToken).toFixed(2)} is needed for one fetch and a written report. Raise budget.maxUSD, set models.research to a cheaper model, or use a cheaper lead model.`
|
|
317
|
+
: `budget.maxTokens ${input.maxTokens} is too low for a ${input.scope} question — about ${minTokens} tokens are needed for one fetch and a written report. Raise budget.maxTokens.`;
|
|
318
|
+
return {
|
|
319
|
+
feasible,
|
|
320
|
+
reason,
|
|
321
|
+
effectiveTokens,
|
|
322
|
+
draftReserveTokens,
|
|
323
|
+
gatherCeilingTokens,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
export function minViableSubtaskUSD(scope, maxReportTokens, researchPricing) {
|
|
327
|
+
const single = scope === "single_fact";
|
|
328
|
+
const reportTokens = single
|
|
329
|
+
? Math.min(maxReportTokens, SINGLE_FACT_REPORT_TOKENS)
|
|
330
|
+
: maxReportTokens;
|
|
331
|
+
const draftReserveTokens = (single ? DRAFT_CONTEXT_TOKENS_SINGLE : DRAFT_CONTEXT_TOKENS_BROAD) +
|
|
332
|
+
reportTokens;
|
|
333
|
+
const minGather = single ? GATHER_MIN_TOKENS_SINGLE : GATHER_MIN_TOKENS_BROAD;
|
|
334
|
+
const minTokens = PLAN_RESERVE_TOKENS + draftReserveTokens + minGather;
|
|
335
|
+
return minTokens * blendedUsdPerToken(researchPricing);
|
|
336
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { BudgetGrant } from "./budget.js";
|
|
3
|
+
import type { RunCtx } from "./state.js";
|
|
4
|
+
export type SlotShape = "value" | "range" | "split" | "causal" | "matrix" | "verdict";
|
|
5
|
+
export type SlotKind = "fact" | "analysis";
|
|
6
|
+
export type SlotImportance = "central" | "peripheral";
|
|
7
|
+
export type SlotStatus = "open" | "filled" | "exhausted";
|
|
8
|
+
export type LedgerScope = "single_fact" | "short_answer" | "broad";
|
|
9
|
+
export type Fill = {
|
|
10
|
+
kind: "grounded";
|
|
11
|
+
value: string;
|
|
12
|
+
quote: string;
|
|
13
|
+
source: string;
|
|
14
|
+
} | {
|
|
15
|
+
kind: "computed";
|
|
16
|
+
value: string;
|
|
17
|
+
computedFrom: string[];
|
|
18
|
+
} | {
|
|
19
|
+
kind: "given";
|
|
20
|
+
value: string;
|
|
21
|
+
} | {
|
|
22
|
+
kind: "stated";
|
|
23
|
+
} | {
|
|
24
|
+
kind: "exhausted";
|
|
25
|
+
reason: string;
|
|
26
|
+
};
|
|
27
|
+
export interface Slot {
|
|
28
|
+
id: string;
|
|
29
|
+
ask: string;
|
|
30
|
+
shape: SlotShape;
|
|
31
|
+
kind: SlotKind;
|
|
32
|
+
importance: SlotImportance;
|
|
33
|
+
parent?: string;
|
|
34
|
+
fill: Fill | null;
|
|
35
|
+
}
|
|
36
|
+
export interface Ledger {
|
|
37
|
+
slots: Slot[];
|
|
38
|
+
nextId: number;
|
|
39
|
+
scope: LedgerScope;
|
|
40
|
+
}
|
|
41
|
+
export interface NewSlotSpec {
|
|
42
|
+
ask: string;
|
|
43
|
+
shape: SlotShape;
|
|
44
|
+
kind: SlotKind;
|
|
45
|
+
importance: SlotImportance;
|
|
46
|
+
parent?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface CoverageUpdate {
|
|
49
|
+
closedIds: string[];
|
|
50
|
+
newItems: NewSlotSpec[];
|
|
51
|
+
exhaustedIds?: string[];
|
|
52
|
+
}
|
|
53
|
+
export declare const newSlotSchema: z.ZodObject<{
|
|
54
|
+
ask: z.ZodString;
|
|
55
|
+
shape: z.ZodEnum<{
|
|
56
|
+
split: "split";
|
|
57
|
+
value: "value";
|
|
58
|
+
range: "range";
|
|
59
|
+
causal: "causal";
|
|
60
|
+
matrix: "matrix";
|
|
61
|
+
verdict: "verdict";
|
|
62
|
+
}>;
|
|
63
|
+
kind: z.ZodEnum<{
|
|
64
|
+
fact: "fact";
|
|
65
|
+
analysis: "analysis";
|
|
66
|
+
}>;
|
|
67
|
+
importance: z.ZodEnum<{
|
|
68
|
+
central: "central";
|
|
69
|
+
peripheral: "peripheral";
|
|
70
|
+
}>;
|
|
71
|
+
}, z.core.$strip>;
|
|
72
|
+
export declare const draftCoverageSchema: z.ZodObject<{
|
|
73
|
+
groundedIds: z.ZodArray<z.ZodString>;
|
|
74
|
+
exhaustedIds: z.ZodArray<z.ZodString>;
|
|
75
|
+
newItems: z.ZodArray<z.ZodObject<{
|
|
76
|
+
ask: z.ZodString;
|
|
77
|
+
shape: z.ZodEnum<{
|
|
78
|
+
split: "split";
|
|
79
|
+
value: "value";
|
|
80
|
+
range: "range";
|
|
81
|
+
causal: "causal";
|
|
82
|
+
matrix: "matrix";
|
|
83
|
+
verdict: "verdict";
|
|
84
|
+
}>;
|
|
85
|
+
kind: z.ZodEnum<{
|
|
86
|
+
fact: "fact";
|
|
87
|
+
analysis: "analysis";
|
|
88
|
+
}>;
|
|
89
|
+
importance: z.ZodEnum<{
|
|
90
|
+
central: "central";
|
|
91
|
+
peripheral: "peripheral";
|
|
92
|
+
}>;
|
|
93
|
+
}, z.core.$strip>>;
|
|
94
|
+
gaps: z.ZodArray<z.ZodObject<{
|
|
95
|
+
id: z.ZodString;
|
|
96
|
+
directive: z.ZodString;
|
|
97
|
+
needsFetch: z.ZodBoolean;
|
|
98
|
+
candidateUrl: z.ZodOptional<z.ZodString>;
|
|
99
|
+
}, z.core.$strip>>;
|
|
100
|
+
}, z.core.$strip>;
|
|
101
|
+
export declare function stripGuessedValues(ask: string): string;
|
|
102
|
+
export declare function seedLedger(rctx: RunCtx, grant: BudgetGrant): Promise<Ledger | null>;
|
|
103
|
+
export declare function ledgerFromSubQuestions(subQuestions: string[]): Ledger | null;
|
|
104
|
+
export declare function findSlot(ledger: Ledger, id: string): Slot | undefined;
|
|
105
|
+
export declare function addSlot(ledger: Ledger, spec: NewSlotSpec): Slot;
|
|
106
|
+
export declare function applyCoverageUpdate(ledger: Ledger, update: CoverageUpdate): void;
|
|
107
|
+
export declare function slotStatus(slot: Slot): SlotStatus;
|
|
108
|
+
export declare function openItems(ledger: Ledger): Slot[];
|
|
109
|
+
export declare function isAnswered(ledger: Ledger): boolean;
|
|
110
|
+
export declare function centralFactsAllFilled(ledger: Ledger): boolean;
|
|
111
|
+
export declare function renderGatherContract(ledger: Ledger): string;
|
|
112
|
+
export declare function renderLedgerAudit(ledger: Ledger): string;
|
|
113
|
+
export declare function renderOpenSlots(ledger: Ledger): string;
|
|
114
|
+
export declare function renderDeliverableContract(ledger: Ledger): string;
|
|
115
|
+
export declare function renderDeliverableShape(ledger: Ledger): string;
|