pi-background-tasks 0.7.4 → 0.7.6

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.
@@ -3,12 +3,12 @@ import type { Usage } from '@earendil-works/pi-ai';
3
3
  export type FusionThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
4
4
 
5
5
  export const FUSION_MODEL_CONFIG_SCHEMA_VERSION = 'pi-background-tasks.fusion-models.v1';
6
- export const FUSION_INPUT_SCHEMA_VERSION = 'pi-background-tasks.fusion-input.v2';
6
+ export const FUSION_INPUT_SCHEMA_VERSION = 'pi-background-tasks.fusion-input.v3';
7
7
  export const FUSION_EVALUATION_SCHEMA_VERSION = 'pi-background-tasks.fusion-evaluation.v1';
8
8
  export const FUSION_RESULT_SCHEMA_VERSION = 'pi-background-tasks.fusion-result.v2';
9
9
  export const FUSION_MANIFEST_SCHEMA_VERSION = 'pi-background-tasks.fusion-manifest.v2';
10
- export const FUSION_CONTEXT_LEDGER_SCHEMA_VERSION = 'pi-background-tasks.fusion-context-ledger.v1';
11
- export const FUSION_BUDGET_PLAN_SCHEMA_VERSION = 'pi-background-tasks.fusion-budget-plan.v1';
10
+ export const FUSION_CONTEXT_LEDGER_SCHEMA_VERSION = 'pi-background-tasks.fusion-context-ledger.v2';
11
+ export const FUSION_BUDGET_PLAN_SCHEMA_VERSION = 'pi-background-tasks.fusion-budget-plan.v2';
12
12
 
13
13
  /**
14
14
  * Conversation-projection transform shared by every Fusion entry point.
@@ -18,12 +18,12 @@ export const FUSION_BUDGET_PLAN_SCHEMA_VERSION = 'pi-background-tasks.fusion-bud
18
18
  * hash-accounted omission receipts. It never truncates retained text and never
19
19
  * forwards raw image bytes.
20
20
  */
21
- export const FUSION_CONTEXT_TRANSFORM_ID = 'visible-conversation-ledger-v1';
21
+ export const FUSION_CONTEXT_TRANSFORM_ID = 'visible-conversation-ledger-v2';
22
22
  export const FUSION_BRANCH_FILTER_ID = 'exclude-active-fusion-subtree-v1';
23
23
 
24
24
  /** Entry-point specific context policies. Both use the same payload-exclusion transform. */
25
- export const FUSION_TOOL_CONTEXT_POLICY_ID = 'fusion-tool-explicit-v1';
26
- export const FUSION_COMMAND_CONTEXT_POLICY_ID = 'fusion-command-conversation-v1';
25
+ export const FUSION_TOOL_CONTEXT_POLICY_ID = 'fusion-tool-explicit-v2';
26
+ export const FUSION_COMMAND_CONTEXT_POLICY_ID = 'fusion-command-conversation-v2';
27
27
 
28
28
  export const FUSION_IMAGE_OMISSION_PREFIX = '[Image omitted from fusion text transcript: ';
29
29
 
@@ -112,7 +112,7 @@ export interface ResolvedFusionModels {
112
112
 
113
113
  export type FusionRequestAuthority = 'explicit_text' | 'directive_over_projected_conversation';
114
114
 
115
- export interface FusionCanonicalRequestV2 {
115
+ export interface FusionCanonicalRequestV3 {
116
116
  /** Entry point that produced this request. */
117
117
  source: FusionSource;
118
118
  /** How children must weigh `text` against the projected conversation. */
@@ -144,11 +144,29 @@ export interface FusionOmittedEventRecord {
144
144
  mime_type?: string;
145
145
  }
146
146
 
147
- export interface FusionContextOmissionLedgerV1 {
147
+ export interface FusionOmittedActivityProjectionMapEntry {
148
+ canonical_entry_index: number;
149
+ entry_kind: 'omitted_activity';
150
+ ledger_index_first: number;
151
+ ledger_index_last: number;
152
+ }
153
+
154
+ export interface FusionLedgerOnlyImageProjectionMapEntry {
155
+ entry_kind: 'ledger_only_tool_result_image';
156
+ ledger_index_first: number;
157
+ ledger_index_last: number;
158
+ }
159
+
160
+ export type FusionContextProjectionMapEntry =
161
+ | FusionOmittedActivityProjectionMapEntry
162
+ | FusionLedgerOnlyImageProjectionMapEntry;
163
+
164
+ export interface FusionContextOmissionLedgerV2 {
148
165
  schema_version: typeof FUSION_CONTEXT_LEDGER_SCHEMA_VERSION;
149
166
  policy_id: string;
150
167
  transform: typeof FUSION_CONTEXT_TRANSFORM_ID;
151
168
  entries: readonly FusionOmittedEventRecord[];
169
+ projection_map: readonly FusionContextProjectionMapEntry[];
152
170
  root_sha256: string;
153
171
  }
154
172
 
@@ -169,26 +187,13 @@ export interface FusionOmittedRunCounts {
169
187
  assistant_thinking?: number;
170
188
  tool_calls?: number;
171
189
  tool_result_texts?: number;
172
- tool_result_images?: number;
173
- }
174
-
175
- /** Byte totals for one omitted run, using the same omit-when-zero rule. */
176
- export interface FusionOmittedRunBytes {
177
- assistant_thinking?: number;
178
- tool_call_arguments?: number;
179
- tool_result_text?: number;
180
- tool_result_image?: number;
181
190
  }
182
191
 
183
192
  export interface FusionProjectionOmissionEntry {
184
193
  kind: 'omitted_activity';
185
- source_ordinal_first: number;
186
- source_ordinal_last: number;
187
- ledger_index_first: number;
188
- ledger_index_last: number;
194
+ at: readonly [number, number];
195
+ bytes: number;
189
196
  counts: FusionOmittedRunCounts;
190
- payload_bytes: FusionOmittedRunBytes;
191
- ledger_run_sha256: string;
192
197
  }
193
198
 
194
199
  export type FusionProjectionEntry = FusionProjectionTextEntry | FusionProjectionOmissionEntry;
@@ -196,7 +201,8 @@ export type FusionProjectionEntry = FusionProjectionTextEntry | FusionProjection
196
201
  export interface FusionContextPolicyDescriptor {
197
202
  id: string;
198
203
  transform: typeof FUSION_CONTEXT_TRANSFORM_ID;
199
- version: 1;
204
+ version: 2;
205
+ receipt_format: 'omitted_activity.v2';
200
206
  user_text: 'verbatim';
201
207
  assistant_text: 'verbatim';
202
208
  assistant_thinking: 'ledger_only';
@@ -238,21 +244,22 @@ export interface FusionProjectionAccounting {
238
244
  tool_call_names: readonly FusionToolCallNameCount[];
239
245
  ledger_entry_count: number;
240
246
  ledger_root_sha256: string;
247
+ omission_receipt_utf8_bytes: number;
241
248
  }
242
249
 
243
- export interface FusionConversationProjectionV2 {
250
+ export interface FusionConversationProjectionV3 {
244
251
  policy: FusionContextPolicyDescriptor;
245
252
  branch_filter: FusionBranchFilterDescriptor;
246
253
  entries: readonly FusionProjectionEntry[];
247
254
  accounting: FusionProjectionAccounting;
248
255
  }
249
256
 
250
- export interface FusionCanonicalInputV2 {
257
+ export interface FusionCanonicalInputV3 {
251
258
  schema_version: typeof FUSION_INPUT_SCHEMA_VERSION;
252
259
  cwd: string;
253
260
  system_prompt: string;
254
- request: FusionCanonicalRequestV2;
255
- conversation_projection: FusionConversationProjectionV2;
261
+ request: FusionCanonicalRequestV3;
262
+ conversation_projection: FusionConversationProjectionV3;
256
263
  }
257
264
 
258
265
  export interface CandidateAssessment {
@@ -370,6 +377,7 @@ export type FusionProgressEvent =
370
377
  | { type: 'candidate_completed'; slot: 1 | 2 | 3; completed: number; total: 3 }
371
378
  | { type: 'evaluation_started'; attempt: 1 | 2; repair: boolean }
372
379
  | { type: 'evaluation_retry'; errors: readonly string[] }
380
+ | { type: 'budget_warning'; warnings: readonly FusionBudgetWarning[]; error: string }
373
381
  | { type: 'merge_started' }
374
382
  | { type: 'completed'; runId: string; artifactDir: string }
375
383
  | { type: 'failed'; runId: string; artifactDir: string; error: string }
@@ -395,14 +403,11 @@ export type FusionErrorCode =
395
403
  | 'state_transition_invalid'
396
404
  | 'orchestration_failed';
397
405
 
398
- /**
399
- * Structured detail attached to a `prompt_budget_exceeded` failure so the caller
400
- * can see exactly which stage, which measured size, which allowed size, and
401
- * which configured model was the limiting participant.
402
- */
406
+ /** Structured detail attached to a `prompt_budget_exceeded` failure. */
403
407
  export interface FusionBudgetErrorDetail {
404
408
  budget_stage: FusionBudgetStage;
405
- measurement_kind: 'worst_case_envelope' | 'rendered_prompt';
409
+ slot?: 1 | 2 | 3;
410
+ measurement_kind: 'stage_forecast' | 'rendered_prompt';
406
411
  measured_utf8_bytes: number;
407
412
  measured_input_tokens_upper_bound: number;
408
413
  allowed_input_tokens: number;
@@ -414,6 +419,8 @@ export interface FusionBudgetErrorDetail {
414
419
  };
415
420
  context_policy_id: string;
416
421
  remediation: readonly string[];
422
+ blockers: readonly FusionBudgetBlocker[];
423
+ artifact_dir: string;
417
424
  }
418
425
 
419
426
  export interface FusionErrorDetails {
@@ -535,48 +542,67 @@ export interface FusionRouteCapacity {
535
542
  allowed_input_tokens: number;
536
543
  }
537
544
 
545
+ export interface FusionBudgetStageComposition {
546
+ visible_text_bytes: number;
547
+ omission_receipt_bytes: number;
548
+ projection_metadata_bytes: number;
549
+ request_bytes: number;
550
+ static_stage_framing_bytes: number;
551
+ upstream_output_contract_bytes: number;
552
+ }
553
+
538
554
  export interface FusionStageBudgetPlanEntry {
539
555
  budget_stage: FusionBudgetStage;
540
- measurement_kind: 'worst_case_envelope';
541
- measured_utf8_bytes: number;
542
- measured_input_tokens_upper_bound: number;
556
+ slot?: 1 | 2 | 3;
557
+ route: FusionRouteCapacity;
558
+ conditional: boolean;
559
+ forecast_utf8_bytes: number;
560
+ forecast_input_tokens_upper_bound: number;
543
561
  allowed_input_tokens: number;
544
- limiting_qualified_id: string;
545
- slack_tokens: number;
562
+ signed_headroom_tokens: number;
563
+ utilization: number;
564
+ fits: boolean;
565
+ }
566
+
567
+ export interface FusionBudgetBlocker extends FusionStageBudgetPlanEntry {
568
+ overage_tokens: number;
569
+ }
570
+
571
+ export interface FusionBudgetWarning extends FusionStageBudgetPlanEntry {
572
+ threshold: 0.8;
573
+ }
574
+
575
+ export interface FusionBudgetEmptyRequestVerdict {
576
+ request_utf8_bytes: number;
577
+ still_fails_with_empty_request: boolean;
578
+ shortening_request_can_help: boolean;
579
+ minimum_request_byte_reduction: number;
580
+ maximum_safe_request_utf8_bytes: number;
581
+ blockers_with_empty_request: readonly FusionBudgetBlocker[];
546
582
  }
547
583
 
548
584
  export interface FusionBudgetPlanV1 {
549
585
  schema_version: typeof FUSION_BUDGET_PLAN_SCHEMA_VERSION;
550
586
  policy: FusionBudgetPolicyDescriptor;
551
587
  routes: readonly FusionRouteCapacity[];
552
- limiting_qualified_id: string;
553
- /** Base-context feasibility check performed before the first candidate spawns. */
554
- base_context: FusionStageBudgetPlanEntry;
588
+ stages: readonly FusionStageBudgetPlanEntry[];
589
+ blockers: readonly FusionBudgetBlocker[];
590
+ primary_blocker?: FusionBudgetBlocker;
591
+ primary_blocker_composition?: FusionBudgetStageComposition;
592
+ empty_request: FusionBudgetEmptyRequestVerdict;
593
+ warnings: readonly FusionBudgetWarning[];
555
594
  }
556
595
 
557
- /**
558
- * Documented, versioned budget policy.
559
- *
560
- * `bytes_per_token_divisor` is a conservative lower bound on UTF-8 bytes per
561
- * token: token upper bound = ceil(utf8Bytes / divisor). It is deliberately far
562
- * below the smallest ratio measured across real Fusion prompts so dense
563
- * non-ASCII input cannot silently exceed a route's window.
564
- *
565
- * `downstream_reserve_bytes` is withheld from the canonical input so the
566
- * evaluator, evaluation-repair, and merger prompts provably have room for the
567
- * child outputs they embed. It is derived from the enforced per-stage output
568
- * byte contracts, so it is a guarantee rather than an estimate: a response over
569
- * its contract fails loudly instead of being embedded. `downstream_reserve_tokens`
570
- * converts it with the same `bytes_per_token_divisor` used to measure prompts,
571
- * because reserving output tokens directly would understate the cost of
572
- * re-embedding those bytes. Neither value is adjusted to fit a particular input.
573
- */
596
+ /** Documented, versioned budget policy. */
574
597
  export interface FusionBudgetPolicyDescriptor {
575
- id: 'fusion-budget-policy-v1';
598
+ id: 'fusion-budget-policy-v2';
576
599
  bytes_per_token_divisor: number;
577
600
  reserved_output_tokens: number;
578
601
  framing_reserve_tokens: number;
579
602
  safety_reserve_tokens: number;
580
- downstream_reserve_bytes: number;
581
- downstream_reserve_tokens: number;
603
+ candidate_output_contract_bytes: number;
604
+ evaluation_output_contract_bytes: number;
605
+ merge_output_contract_bytes: number;
606
+ diagnostics_contract_bytes: number;
607
+ utilization_warning_threshold: 0.8;
582
608
  }
@@ -148,6 +148,8 @@ function progressText(event: FusionProgressEvent): string {
148
148
  return event.repair ? 'fusion: repairing evaluator JSON' : 'fusion: evaluating candidates';
149
149
  if (event.type === 'evaluation_retry')
150
150
  return `fusion: evaluator schema retry (${String(event.errors.length)} issue${event.errors.length === 1 ? '' : 's'})`;
151
+ if (event.type === 'budget_warning')
152
+ return `fusion: budget warning (${String(event.warnings.length)} stage${event.warnings.length === 1 ? '' : 's'} at or above 80%)`;
151
153
  if (event.type === 'merge_started') return 'fusion: merging final answer';
152
154
  if (event.type === 'completed') return 'fusion: completed';
153
155
  if (event.type === 'cancelled') return `fusion: cancelled (${event.reason})`;