promptloom 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,611 @@
1
+ /**
2
+ * promptloom — Core type definitions
3
+ *
4
+ * The type system for a prompt compiler:
5
+ * - Sections with conditional inclusion
6
+ * - Multi-zone cache scoping
7
+ * - Tools with deferred loading
8
+ * - Token budgeting
9
+ * - Multi-provider output
10
+ */
11
+ /**
12
+ * Context passed to compile() for conditional section evaluation.
13
+ *
14
+ * In Claude Code, sections are gated on feature flags, model capabilities,
15
+ * and user type. CompileContext is the generic equivalent.
16
+ */
17
+ interface CompileContext {
18
+ /** Current model name (e.g., 'claude-opus-4-6') */
19
+ model?: string;
20
+ /** API provider (e.g., 'anthropic', 'bedrock', 'vertex', 'openai') */
21
+ provider?: string;
22
+ /** Allow arbitrary user-defined context */
23
+ [key: string]: unknown;
24
+ }
25
+ /** A compute function that returns a section's content, or null to skip */
26
+ type ComputeFn = () => string | null | Promise<string | null>;
27
+ /** Predicate for conditional section inclusion */
28
+ type WhenPredicate = (ctx: CompileContext) => boolean;
29
+ /** Cache scope for prompt blocks, matching Anthropic API semantics */
30
+ type CacheScope = 'global' | 'org' | null;
31
+ /**
32
+ * Options for section creation.
33
+ */
34
+ interface SectionOptions {
35
+ /**
36
+ * Conditional predicate. Section is only included when this returns true.
37
+ *
38
+ * In Claude Code, this maps to `feature('FLAG')` and `process.env.USER_TYPE` checks
39
+ * that gate sections like TOKEN_BUDGET, KAIROS, VERIFICATION_AGENT.
40
+ */
41
+ when?: WhenPredicate;
42
+ }
43
+ /**
44
+ * A prompt section — the atomic unit of prompt assembly.
45
+ *
46
+ * Sections can be:
47
+ * - Static: content is computed once and cached for the session
48
+ * - Dynamic (cacheBreak: true): recomputed every time compile() is called
49
+ * - Conditional: only included when `when(context)` returns true
50
+ */
51
+ interface Section {
52
+ /** Unique identifier for this section */
53
+ name: string;
54
+ /** Function that computes the section content */
55
+ compute: ComputeFn;
56
+ /** If true, this section is recomputed every compile() call */
57
+ cacheBreak: boolean;
58
+ /** If provided, section is only included when predicate returns true */
59
+ when?: WhenPredicate;
60
+ }
61
+ /**
62
+ * A zone marker in the entry list.
63
+ *
64
+ * Zones create cache block boundaries. All sections between two zone markers
65
+ * are compiled into a single CacheBlock with the zone's scope.
66
+ *
67
+ * In Claude Code, this is implemented via `SYSTEM_PROMPT_DYNAMIC_BOUNDARY`
68
+ * (a single boundary producing 2 zones). promptloom generalizes to N zones.
69
+ */
70
+ interface ZoneMarker {
71
+ readonly __type: 'zone';
72
+ scope: CacheScope;
73
+ }
74
+ /** An entry in the compiler's internal list */
75
+ type Entry = Section | ZoneMarker;
76
+ /**
77
+ * A compiled prompt block with cache scope annotation.
78
+ *
79
+ * When sent to the Anthropic API, blocks with a non-null cacheScope
80
+ * get a `cache_control` field, enabling prompt caching.
81
+ */
82
+ interface CacheBlock {
83
+ /** The text content of this block */
84
+ text: string;
85
+ /** Cache scope: 'global' (cross-org), 'org' (org-level), or null (no cache) */
86
+ cacheScope: CacheScope;
87
+ }
88
+ /** JSON Schema for tool input parameters */
89
+ type JsonSchema = Record<string, unknown>;
90
+ /**
91
+ * A tool definition with an embedded prompt.
92
+ *
93
+ * In Claude Code, each tool carries its own "user manual" for the LLM.
94
+ * The prompt is injected into the tool's description field in the API request.
95
+ */
96
+ interface ToolDef {
97
+ /** Tool name (e.g., 'bash', 'read_file') */
98
+ name: string;
99
+ /**
100
+ * Tool prompt — the LLM-facing description.
101
+ * Can be a static string or an async function for dynamic prompts.
102
+ */
103
+ prompt: string | (() => string | Promise<string>);
104
+ /** JSON Schema defining the tool's input parameters */
105
+ inputSchema: JsonSchema;
106
+ /** If true, safe to call concurrently with other tools */
107
+ concurrencySafe?: boolean;
108
+ /** If true, this tool only reads and never writes */
109
+ readOnly?: boolean;
110
+ /**
111
+ * If true, the tool schema is deferred (not loaded until model requests it).
112
+ *
113
+ * In Claude Code, deferred tools get `defer_loading: true` in their schema
114
+ * and are discovered via ToolSearchTool on demand. This reduces system prompt
115
+ * token cost when you have many tools.
116
+ */
117
+ deferred?: boolean;
118
+ /**
119
+ * Explicit ordering for cache stability.
120
+ * Lower numbers come first. Tools without order use insertion order.
121
+ *
122
+ * In Claude Code, tool order is kept stable to maximize prompt cache hits —
123
+ * reordering tools changes the serialized bytes, breaking the cache.
124
+ */
125
+ order?: number;
126
+ }
127
+ /**
128
+ * A compiled tool schema ready for the API.
129
+ */
130
+ interface CompiledTool {
131
+ name: string;
132
+ description: string;
133
+ input_schema: JsonSchema;
134
+ cache_control?: {
135
+ type: 'ephemeral';
136
+ scope?: CacheScope;
137
+ };
138
+ /** When true, the model must explicitly request this tool via tool search */
139
+ defer_loading?: true;
140
+ }
141
+ interface TokenEstimate {
142
+ /** Total estimated tokens for system prompt */
143
+ systemPrompt: number;
144
+ /** Total estimated tokens for inline (non-deferred) tool schemas */
145
+ tools: number;
146
+ /** Total estimated tokens for deferred tool schemas */
147
+ deferredTools: number;
148
+ /** Combined total (systemPrompt + tools, deferred excluded) */
149
+ total: number;
150
+ }
151
+ interface TokenBudgetConfig {
152
+ /** Total token budget for the conversation turn */
153
+ budget: number;
154
+ /** Stop at this fraction of budget (default: 0.9) */
155
+ completionThreshold?: number;
156
+ /** Minimum delta to avoid diminishing returns detection (default: 500) */
157
+ diminishingThreshold?: number;
158
+ }
159
+ interface CompilerOptions {
160
+ /** Default cache scope for the initial zone (default: 'org') */
161
+ defaultCacheScope?: CacheScope;
162
+ /** Cache scope used by boundary() for the dynamic zone (default: null) */
163
+ dynamicCacheScope?: CacheScope;
164
+ /** Bytes per token for rough estimation (default: 4) */
165
+ bytesPerToken?: number;
166
+ /**
167
+ * When true, the initial zone scope is upgraded to 'global'.
168
+ * Only effective for 1P Anthropic API usage.
169
+ */
170
+ enableGlobalCache?: boolean;
171
+ }
172
+ interface CompileResult {
173
+ /** Prompt blocks with cache annotations, one per zone */
174
+ blocks: CacheBlock[];
175
+ /** Inline tool schemas (non-deferred) with resolved prompts */
176
+ tools: CompiledTool[];
177
+ /** Deferred tool schemas (loaded on demand) */
178
+ deferredTools: CompiledTool[];
179
+ /** Token estimates */
180
+ tokens: TokenEstimate;
181
+ /** The full system prompt as a single string (blocks joined) */
182
+ text: string;
183
+ }
184
+ type ProviderFormat = 'anthropic' | 'openai' | 'bedrock';
185
+
186
+ /**
187
+ * promptloom — The Prompt Compiler
188
+ *
189
+ * Implements Claude Code's prompt assembly pattern, generalized:
190
+ *
191
+ * 1. Multi-zone cache scoping (N blocks, not just 2)
192
+ * 2. Conditional section inclusion (when predicates)
193
+ * 3. Static/dynamic section caching
194
+ * 4. Tool schemas with embedded prompts and deferred loading
195
+ * 5. Stable tool ordering for cache hits
196
+ * 6. Token estimation and budget tracking
197
+ *
198
+ * Usage:
199
+ *
200
+ * const pc = new PromptCompiler()
201
+ *
202
+ * // Zone 1: no-cache header
203
+ * pc.zone(null)
204
+ * pc.static('attribution', 'x-model: claude')
205
+ *
206
+ * // Zone 2: globally cacheable
207
+ * pc.zone('global')
208
+ * pc.static('identity', 'You are a coding assistant.')
209
+ * pc.static('rules', () => loadRules())
210
+ *
211
+ * // Zone 3: session-specific
212
+ * pc.zone(null)
213
+ * pc.dynamic('git', async () => gitStatus())
214
+ * pc.static('opus_only', 'Use extended thinking.', {
215
+ * when: (ctx) => ctx.model?.includes('opus'),
216
+ * })
217
+ *
218
+ * // Tools
219
+ * pc.tool({ name: 'bash', prompt: '...', inputSchema: {...} })
220
+ * pc.tool({ name: 'rare_tool', prompt: '...', inputSchema: {...}, deferred: true })
221
+ *
222
+ * const result = await pc.compile({ model: 'claude-opus-4-6' })
223
+ */
224
+
225
+ declare class PromptCompiler {
226
+ private entries;
227
+ private tools;
228
+ private sectionCache;
229
+ private toolCache;
230
+ private options;
231
+ constructor(options?: CompilerOptions);
232
+ /**
233
+ * Start a new cache zone. All sections after this marker are compiled
234
+ * into a single CacheBlock with the specified scope.
235
+ *
236
+ * Generalizes Claude Code's `SYSTEM_PROMPT_DYNAMIC_BOUNDARY` to support
237
+ * N zones instead of just 2.
238
+ *
239
+ * @example
240
+ * pc.zone(null) // no-cache zone (attribution, headers)
241
+ * pc.zone('global') // globally cacheable (identity, rules)
242
+ * pc.zone('org') // org-level cacheable
243
+ * pc.zone(null) // session-specific (dynamic context)
244
+ */
245
+ zone(scope: CacheScope): this;
246
+ /**
247
+ * Insert a cache boundary. Shorthand for starting a new zone with
248
+ * `dynamicCacheScope` (default: null).
249
+ *
250
+ * Equivalent to Claude Code's `SYSTEM_PROMPT_DYNAMIC_BOUNDARY`.
251
+ * Only effective when `enableGlobalCache` is true (otherwise a no-op
252
+ * since there's no scope difference to split on).
253
+ *
254
+ * For explicit multi-zone control, use `zone()` instead.
255
+ */
256
+ boundary(): this;
257
+ /**
258
+ * Add a static section. Computed once and cached for the session.
259
+ *
260
+ * Equivalent to Claude Code's `systemPromptSection()`.
261
+ *
262
+ * @param options.when - Conditional predicate. Section is skipped when false.
263
+ */
264
+ static(name: string, content: string | ComputeFn, options?: SectionOptions): this;
265
+ /**
266
+ * Add a dynamic section. Recomputed every compile() call.
267
+ *
268
+ * Equivalent to Claude Code's `DANGEROUS_uncachedSystemPromptSection()`.
269
+ *
270
+ * @param options.when - Conditional predicate. Section is skipped when false.
271
+ */
272
+ dynamic(name: string, compute: ComputeFn, options?: SectionOptions): this;
273
+ /**
274
+ * Register a tool with an embedded prompt.
275
+ *
276
+ * Tools with `deferred: true` are compiled separately and excluded
277
+ * from the main tool list. They can be discovered on demand.
278
+ *
279
+ * Tools with `order` fields are sorted for stable serialization
280
+ * (cache hit optimization).
281
+ */
282
+ tool(def: ToolDef): this;
283
+ /**
284
+ * Compile the prompt: resolve sections per zone, compile tools,
285
+ * separate deferred tools, and estimate tokens.
286
+ *
287
+ * @param context - Optional context for conditional section evaluation.
288
+ * Sections with `when` predicates are evaluated against this.
289
+ */
290
+ compile(context?: CompileContext): Promise<CompileResult>;
291
+ /** Clear all caches. Call on `/clear` or `/compact`. */
292
+ clearCache(): void;
293
+ /** Clear only section cache (tools stay cached) */
294
+ clearSectionCache(): void;
295
+ /** Clear only tool cache (forces prompt re-resolution) */
296
+ clearToolCache(): void;
297
+ /** Get the number of registered sections */
298
+ get sectionCount(): number;
299
+ /** Get the number of registered tools (inline + deferred) */
300
+ get toolCount(): number;
301
+ /** List registered section names with their types */
302
+ listSections(): Array<{
303
+ name: string;
304
+ type: 'static' | 'dynamic' | 'zone';
305
+ }>;
306
+ /** List registered tool names */
307
+ listTools(): string[];
308
+ /**
309
+ * Group entries into zones.
310
+ *
311
+ * Entries before any zone marker belong to the "initial zone" whose
312
+ * scope is determined by `enableGlobalCache` and `defaultCacheScope`.
313
+ */
314
+ private groupIntoZones;
315
+ private estimateToolTokens;
316
+ }
317
+
318
+ /**
319
+ * promptloom — Section management
320
+ *
321
+ * Implements the two-tier section system from Claude Code:
322
+ * - `section()`: cached within session, computed once
323
+ * - `dynamicSection()`: recomputed every compile() call (cacheBreak: true)
324
+ *
325
+ * Extended with conditional inclusion via `when` predicates,
326
+ * mirroring Claude Code's `feature()` and `process.env.USER_TYPE` gates.
327
+ */
328
+
329
+ /**
330
+ * Create a static section. Content is computed once and cached.
331
+ *
332
+ * Use for: identity prompts, rules, style guides — anything that
333
+ * doesn't change between turns.
334
+ */
335
+ declare function section(name: string, compute: ComputeFn, options?: SectionOptions): Section;
336
+ /**
337
+ * Create a dynamic section. Content is recomputed every compile() call.
338
+ *
339
+ * Claude Code calls this `DANGEROUS_uncachedSystemPromptSection` —
340
+ * the naming reflects that dynamic sections break prompt cache stability.
341
+ *
342
+ * Use for: MCP server instructions, real-time status, anything that
343
+ * changes between turns.
344
+ */
345
+ declare function dynamicSection(name: string, compute: ComputeFn, options?: SectionOptions): Section;
346
+ /**
347
+ * In-memory section cache.
348
+ *
349
+ * Mirrors `STATE.systemPromptSectionCache` from Claude Code.
350
+ * Static sections are computed once per session and cached here.
351
+ * Dynamic sections (cacheBreak: true) bypass the cache entirely.
352
+ */
353
+ declare class SectionCache {
354
+ private cache;
355
+ get(name: string): string | null | undefined;
356
+ has(name: string): boolean;
357
+ set(name: string, value: string | null): void;
358
+ clear(): void;
359
+ get size(): number;
360
+ }
361
+ /**
362
+ * Resolve an array of sections, using cache for static ones.
363
+ *
364
+ * Mirrors `resolveSystemPromptSections()` from Claude Code:
365
+ * - Sections with a `when` predicate are filtered by compile context
366
+ * - Static sections: check cache first, compute if missing
367
+ * - Dynamic sections: always recompute
368
+ * - All sections resolved in parallel via Promise.all
369
+ */
370
+ declare function resolveSections(sections: Section[], cache: SectionCache, context?: CompileContext): Promise<(string | null)[]>;
371
+
372
+ /**
373
+ * promptloom — Cache boundary splitting
374
+ *
375
+ * Implements Claude Code's cache boundary mechanism:
376
+ * - A sentinel string divides the prompt into static (cacheable) and dynamic zones
377
+ * - Content before the boundary gets `cacheScope: 'global'` (cross-org cache)
378
+ * - Content after gets `cacheScope: null` (session-specific)
379
+ *
380
+ * This directly maps to Claude API's `cache_control` field on text blocks.
381
+ */
382
+
383
+ /** The sentinel string used to mark the cache boundary */
384
+ declare const CACHE_BOUNDARY = "__PROMPTLOOM_CACHE_BOUNDARY__";
385
+ interface SplitOptions {
386
+ /** Cache scope for content before the boundary (default: 'global') */
387
+ staticScope?: CacheScope;
388
+ /** Cache scope for content after the boundary (default: null) */
389
+ dynamicScope?: CacheScope;
390
+ /** Fallback scope when no boundary is found (default: 'org') */
391
+ fallbackScope?: CacheScope;
392
+ }
393
+ /**
394
+ * Split a prompt string at the cache boundary into annotated blocks.
395
+ *
396
+ * Mirrors Claude Code's `splitSysPromptPrefix()`:
397
+ *
398
+ * - If boundary found:
399
+ * [static content → staticScope] + [dynamic content → dynamicScope]
400
+ *
401
+ * - If no boundary:
402
+ * [entire content → fallbackScope]
403
+ */
404
+ declare function splitAtBoundary(prompt: string, options?: SplitOptions): CacheBlock[];
405
+
406
+ /**
407
+ * promptloom — Multi-provider output formatting
408
+ *
409
+ * Claude Code supports multiple API providers:
410
+ * - Anthropic (1P): cache_control with scope on text blocks
411
+ * - AWS Bedrock: cache_control without scope
412
+ * - Google Vertex: cache_control without scope
413
+ * - OpenAI: single string system prompt, no caching API
414
+ *
415
+ * This module formats CompileResult for each provider.
416
+ */
417
+
418
+ interface AnthropicCacheControl {
419
+ type: 'ephemeral';
420
+ ttl?: '5m' | '1h';
421
+ }
422
+ interface AnthropicTextBlock {
423
+ type: 'text';
424
+ text: string;
425
+ cache_control?: AnthropicCacheControl;
426
+ }
427
+ interface AnthropicTool {
428
+ name: string;
429
+ description: string;
430
+ input_schema: Record<string, unknown>;
431
+ cache_control?: AnthropicCacheControl;
432
+ defer_loading?: true;
433
+ }
434
+ /**
435
+ * Format compile result for Anthropic Messages API.
436
+ *
437
+ * Mirrors Claude Code's `buildSystemPromptBlocks()`.
438
+ * Blocks with a non-null cacheScope get `cache_control: { type: 'ephemeral' }`.
439
+ */
440
+ declare function toAnthropic(result: CompileResult): {
441
+ system: AnthropicTextBlock[];
442
+ tools: AnthropicTool[];
443
+ };
444
+ interface OpenAITool {
445
+ type: 'function';
446
+ function: {
447
+ name: string;
448
+ description: string;
449
+ parameters: Record<string, unknown>;
450
+ };
451
+ }
452
+ /**
453
+ * Format compile result for OpenAI Chat Completions API.
454
+ *
455
+ * OpenAI uses a single string for system prompt (no block-level caching).
456
+ * Tools are wrapped in the `{ type: 'function', function: {...} }` format.
457
+ */
458
+ declare function toOpenAI(result: CompileResult): {
459
+ system: string;
460
+ tools: OpenAITool[];
461
+ };
462
+ type BedrockSystemBlock = {
463
+ text: string;
464
+ } | {
465
+ cachePoint: {
466
+ type: 'default';
467
+ };
468
+ };
469
+ interface BedrockTool {
470
+ toolSpec: {
471
+ name: string;
472
+ description: string;
473
+ inputSchema: {
474
+ jsonSchema: Record<string, unknown>;
475
+ };
476
+ };
477
+ }
478
+ /**
479
+ * Format compile result for AWS Bedrock Converse API.
480
+ *
481
+ * Bedrock uses `cachePoint: { type: 'default' }` instead of Anthropic's
482
+ * `cache_control: { type: 'ephemeral' }`. Tools use `toolSpec` wrapper.
483
+ */
484
+ declare function toBedrock(result: CompileResult): {
485
+ system: BedrockSystemBlock[];
486
+ toolConfig: {
487
+ tools: BedrockTool[];
488
+ };
489
+ };
490
+ /**
491
+ * Convert cache blocks to Anthropic API text block format.
492
+ *
493
+ * @deprecated Use `toAnthropic(result).system` instead for full formatting.
494
+ * Kept for backward compatibility.
495
+ */
496
+ declare function toAnthropicBlocks(blocks: CacheBlock[], enableCaching?: boolean): AnthropicTextBlock[];
497
+
498
+ /**
499
+ * promptloom — Tool prompt management
500
+ *
501
+ * In Claude Code, every tool has its own `prompt.ts` — a "user manual"
502
+ * written for the LLM. Tool prompts are:
503
+ * - Computed once per session and cached (avoids mid-session drift)
504
+ * - Injected into the tool's `description` field in the API request
505
+ * - Can be static strings or async functions
506
+ * - Optionally deferred (loaded on demand via ToolSearchTool)
507
+ *
508
+ * This module provides the tool registry and compilation logic.
509
+ */
510
+
511
+ /**
512
+ * Cache for resolved tool prompts.
513
+ *
514
+ * Mirrors Claude Code's `getToolSchemaCache()`:
515
+ * "Prevents mid-session GrowthBook flips from churning serialized tools array.
516
+ * One generation per session unless cache is cleared."
517
+ */
518
+ declare class ToolCache {
519
+ private cache;
520
+ get(key: string): CompiledTool | undefined;
521
+ set(key: string, tool: CompiledTool): void;
522
+ has(key: string): boolean;
523
+ clear(): void;
524
+ }
525
+ /**
526
+ * Compile a single tool definition into API-ready format.
527
+ *
528
+ * Uses session-level cache: first call computes, subsequent calls return cached.
529
+ * Deferred tools get `defer_loading: true` in their schema.
530
+ */
531
+ declare function compileTool(def: ToolDef, cache: ToolCache, cacheScope?: CacheScope): Promise<CompiledTool>;
532
+ /**
533
+ * Compile all tool definitions, resolving prompts in parallel.
534
+ *
535
+ * Tools are sorted by explicit `order` field first, then by insertion order.
536
+ * This ensures stable serialization for prompt cache hits.
537
+ */
538
+ declare function compileTools(defs: ToolDef[], cache: ToolCache, cacheScope?: CacheScope): Promise<CompiledTool[]>;
539
+ /**
540
+ * Create a tool definition with safe defaults.
541
+ */
542
+ declare function defineTool(def: ToolDef): ToolDef;
543
+
544
+ /**
545
+ * promptloom — Token estimation and budget utilities
546
+ *
547
+ * Mirrors Claude Code's token counting strategy:
548
+ * - Rough estimation based on byte length (fast, no API call)
549
+ * - File-type-aware estimation (JSON is denser → 2 bytes/token)
550
+ * - Budget tracking with diminishing returns detection
551
+ * - Natural language budget parsing (+500k, spend 2M tokens)
552
+ */
553
+
554
+ /**
555
+ * Estimate token count from a string using byte-length heuristic.
556
+ *
557
+ * Claude Code uses 4 bytes/token as default, 2 for dense formats like JSON.
558
+ * This is intentionally approximate — accurate counting requires an API call.
559
+ */
560
+ declare function estimateTokens(content: string, bytesPerToken?: number): number;
561
+ /**
562
+ * Estimate tokens with file-type awareness.
563
+ * JSON/XML are denser (more tokens per byte) than natural language.
564
+ */
565
+ declare function estimateTokensForFileType(content: string, extension: string): number;
566
+ interface BudgetTracker {
567
+ continuationCount: number;
568
+ lastDeltaTokens: number;
569
+ lastGlobalTurnTokens: number;
570
+ startedAt: number;
571
+ }
572
+ type BudgetDecision = {
573
+ action: 'continue';
574
+ nudgeMessage: string;
575
+ pct: number;
576
+ } | {
577
+ action: 'stop';
578
+ reason: 'budget_reached' | 'diminishing_returns' | 'no_budget';
579
+ pct: number;
580
+ };
581
+ declare function createBudgetTracker(): BudgetTracker;
582
+ /**
583
+ * Check token budget and decide whether to continue.
584
+ *
585
+ * Mirrors Claude Code's `checkTokenBudget()`:
586
+ * - Continue if below completion threshold (default 90%)
587
+ * - Detect diminishing returns (3+ continuations with tiny deltas)
588
+ * - Return nudge messages to keep the model working
589
+ */
590
+ declare function checkBudget(tracker: BudgetTracker, currentTokens: number, config: TokenBudgetConfig): BudgetDecision;
591
+ /**
592
+ * Parse a token budget from natural language.
593
+ *
594
+ * Mirrors Claude Code's `parseTokenBudget()` from `src/utils/tokenBudget.ts`.
595
+ *
596
+ * Supported syntaxes:
597
+ * - Shorthand at start: "+500k", "+2M", "+1.5b"
598
+ * - Shorthand at end: "do this task. +500k."
599
+ * - Verbose: "use 500k tokens", "spend 2M tokens"
600
+ *
601
+ * @returns The parsed budget in tokens, or null if no budget found.
602
+ *
603
+ * @example
604
+ * parseTokenBudget('+500k') // 500_000
605
+ * parseTokenBudget('spend 2M tokens') // 2_000_000
606
+ * parseTokenBudget('+1.5b') // 1_500_000_000
607
+ * parseTokenBudget('hello world') // null
608
+ */
609
+ declare function parseTokenBudget(text: string): number | null;
610
+
611
+ export { type AnthropicCacheControl, type AnthropicTextBlock, type AnthropicTool, type BedrockSystemBlock, type BedrockTool, type BudgetDecision, type BudgetTracker, CACHE_BOUNDARY, type CacheBlock, type CacheScope, type CompileContext, type CompileResult, type CompiledTool, type CompilerOptions, type ComputeFn, type Entry, type JsonSchema, type OpenAITool, PromptCompiler, type ProviderFormat, type Section, SectionCache, type SectionOptions, type SplitOptions, type TokenBudgetConfig, type TokenEstimate, ToolCache, type ToolDef, type WhenPredicate, type ZoneMarker, checkBudget, compileTool, compileTools, createBudgetTracker, defineTool, dynamicSection, estimateTokens, estimateTokensForFileType, parseTokenBudget, resolveSections, section, splitAtBoundary, toAnthropic, toAnthropicBlocks, toBedrock, toOpenAI };