@absolutejs/ai 0.0.58 → 0.1.1

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/CHANGELOG.md CHANGED
@@ -6,6 +6,31 @@ This file is generated by `absolute-changelog` from the entries in
6
6
  `changelog/`. Edit an entry, not this file — and add new ones under
7
7
  `changelog/unreleased/`.
8
8
 
9
+ ## 0.1.1 — 2026-09-16
10
+
11
+ ### Added
12
+
13
+ - **Allow a separate preparation model with its own verified capacity while preserving the final answer model and invalidating notes when the preparation model changes** (`PrepareAITextInputOptions`, `prepareAITextInput`, `prepareAITextInputStep`)
14
+
15
+ ### Fixed
16
+
17
+ - **Fill preparation sections with bounded tokenizer-checked refinement, avoid duplicate final counting, and honor cancellation before generation** (`prepareAITextInput`, `prepareAITextInputStep`)
18
+
19
+ ## 0.1.0 — 2026-09-16
20
+
21
+ ### Added
22
+
23
+ - **Add one-section text preparation steps for durable workers, with explicit pending/ready outcomes and checkpoint persistence before yielding** (`prepareAITextInputStep`, `AITextPreparationStep`)
24
+ - **Budget final retrieval instructions and tools before compacting text, with matching checkpoint invalidation** (`PrepareAITextInputOptions`, `prepareAITextInput`)
25
+
26
+ ### Changed
27
+
28
+ - **Validate model capacity by default across generation, structured output, WebSocket and SSE entry points; reserve token headroom and support one protocol-preserving context recovery attempt. Providers without counting capability now fail explicitly; contextPolicy: false opts into raw behavior.** (`generateAI`, `generateAIWithTools`, `generateObjectAI`, `streamAI`, `streamAIToSSE`, `streamAIWithTools`, `inspectAIContext`, `createAIStoredToolResultRecovery`, `StreamAIWithToolsOptions`, `GenerateAIOptions`, `GenerateAIResult`, `GenerateObjectAIOptions`, `AIProviderConfig`, `StreamAIOptions`, `AIChatPluginConfig`)
29
+
30
+ ### Fixed
31
+
32
+ - **Preserve conversation origin across long-text preparation sections, distinguish source facts from embedded instructions, reserve more of the available context for factual notes, and invalidate checkpoints from the previous preparation policy** (`prepareAITextInput`, `prepareAITextInputStep`)
33
+
9
34
  ## 0.0.58 — 2026-09-15
10
35
 
11
36
  ### Added
package/README.md CHANGED
@@ -343,6 +343,20 @@ unchanged. Oversized text is read in counted sections into rolling notes; the
343
343
  final request is counted again before being returned. Summaries can lose detail,
344
344
  so persist the original source first and retain it for download and resume.
345
345
 
346
+ Section sizing uses bounded tokenizer checks to fill available context more
347
+ closely before generating notes. This reduces repeated note generation when
348
+ halving alone would leave sections underfilled. Every generated section still
349
+ passes the provider's token count and capacity checks; no character-to-token
350
+ ratio is assumed. Existing checkpoints remain resumable.
351
+
352
+ Use `preparationModel` to select a different model on the same provider for
353
+ reading source sections into notes. Its own token capacity is checked; the
354
+ returned final request keeps the original model and output budget. Changing
355
+ this option invalidates saved notes. The default uses the original model.
356
+ Evaluate factual coverage and original-source evidence with your workload
357
+ before choosing a cheaper preparation model. Usage callbacks still report each
358
+ preparation call, and provider instrumentation sees its actual model.
359
+
346
360
  ```ts
347
361
  import { prepareAITextInput } from "@absolutejs/ai";
348
362
 
@@ -358,6 +372,14 @@ for await (const chunk of provider.stream(prepared.params)) {
358
372
  }
359
373
  ```
360
374
 
375
+ When compacted requests need extra retrieval tools or different instructions,
376
+ pass them as `options.compactedContext` (`systemPrompt` and/or `tools`). These
377
+ replace the corresponding fields only on the compacted path. Preparation checks
378
+ that final context before reading the source and budgets the notes against it;
379
+ send the returned `params` without adding uncounted tools afterward. Changing the
380
+ compacted context invalidates a saved preparation checkpoint. Already-fitting
381
+ requests retain their original tools and instructions.
382
+
361
383
  Anthropic and Gemini retrieve native model metadata and count using their native
362
384
  APIs. OpenAI uses its input-token counting API and an exact, documented model
363
385
  catalog because its model-list API does not expose context limits. OpenAI
@@ -403,3 +425,74 @@ and run `bun scripts/eval-text-source.ts`. It uses synthetic text, simulates a
403
425
  small context, and verifies that original-source lookups recover later budget
404
426
  and deadline corrections omitted from the notes. It makes real, billed model
405
427
  calls; the ordinary test suite uses deterministic local providers instead.
428
+
429
+ For durable workers, `prepareAITextInputStep(provider, params, options)` processes
430
+ at most one source section and returns either `{ status: "pending", checkpoint }`
431
+ or `{ status: "ready", prepared }`. Persist originals and the exact request,
432
+ save the checkpoint under the current job attempt, and enqueue another step when
433
+ pending. The final continuation validates the assembled request without another
434
+ model call. A pending checkpoint is not a completed model input. Persistence
435
+ errors propagate before a step reports success; the caller owns atomic scheduling,
436
+ retry limits and attempt fencing. `prepareAITextInput` retains its existing
437
+ all-sections convenience behavior.
438
+
439
+ ### Automatic context policy (next breaking release)
440
+
441
+ High-level generation, structured-output, streaming and chat-plugin entry points
442
+ now validate every final model request automatically, including requests after
443
+ local tools and structured-output repair. The provider owns model metadata and
444
+ counting; unknown models or providers without that capability raise
445
+ `AIInputError` with `code: "capacity_unavailable"`. A character count is never
446
+ used as a model limit. Counting can require an additional provider API request.
447
+
448
+ The shared `contextPolicy` reserves the provider's effective output budget, plus
449
+ 1% of available input (capped at 2,048 tokens) for counting margin and, when local
450
+ tools are enabled, 10% (capped at 8,192 tokens) for tool-result growth. These are
451
+ configurable working-budget defaults, not claimed model limits or quality-optimal
452
+ settings. `workingInputTokens` can set a lower application target.
453
+ `prepareAITextInput` and `prepareAITextInputStep` use the same budgets through
454
+ `contextBudget`, so preparation does not fill headroom reserved by generation.
455
+
456
+ ```ts
457
+ const contextPolicy = {
458
+ workingInputTokens: 80_000,
459
+ // Only tools backed by immutable, authorized saved originals:
460
+ recover: createAIStoredToolResultRecovery([
461
+ "search_text_source",
462
+ "read_text_source",
463
+ ]),
464
+ };
465
+ const result = await generateAIWithTools({
466
+ provider,
467
+ model,
468
+ messages,
469
+ tools,
470
+ contextPolicy,
471
+ });
472
+ ```
473
+
474
+ The saved-source recovery helper replaces only older lookup results with explicit
475
+ reread instructions. It keeps the newest lookup, source-call arguments and every
476
+ other tool result. It never deletes originals, runs tools, invents a summary or
477
+ truncates the newest passage. Callers must ensure listed tools can reread the same
478
+ immutable versions. If this cannot fit the budget, `input_too_large` is returned.
479
+ This helper is not appropriate for unsaved or changing external results.
480
+
481
+ A custom `recover({params, capacity, reason})` may instead return compacted or
482
+ retrieved messages after saving originals. It runs at most once per model turn,
483
+ receives an isolated snapshot, and must actually reduce token usage and fit the
484
+ working budget. Tool calls/results must keep their IDs and grouping; signed
485
+ thinking, media, provider data and system messages cannot change. The recovered
486
+ history is retained across later tool turns. Recovery never reexecutes a tool.
487
+ A second rejection, unsupported error, or error after any emitted chunk propagates
488
+ without a capacity retry. Recognized provider rejection formats are deliberately
489
+ narrow; other adapters may supply `inputCapacity.isContextError`.
490
+
491
+ Migration: supply provider capacity support, or explicitly use
492
+ `contextPolicy: false` to retain raw behavior. Direct `provider.stream(params)`
493
+ remains the raw seam. The old `streamAIWithTools.validateInput` flag is deprecated;
494
+ its explicit `false` remains an opt-out unless `contextPolicy` is supplied.
495
+ `contextPolicy` also passes through `aiChat` and the compatible RAG chat plugin.
496
+ Applications should surface typed failures with saved-input retry UI. These
497
+ changes do not guarantee detection of every provider-side accounting discrepancy
498
+ or provide exactly-once external execution after a process crash.
package/changelog.json CHANGED
@@ -1,47 +1,121 @@
1
1
  {
2
- "contract": 1,
3
- "name": "@absolutejs/ai",
4
- "releases": [
5
- {
6
- "changes": [
7
- {
8
- "kind": "added",
9
- "summary": "Keep compacted text useful with read-only original-source search, checkpointed ingestion, and capacity-checked terminal tool loops",
10
- "symbols": [
11
- "createAITextSource",
12
- "prepareAITextInput",
13
- "PrepareAITextInputOptions",
14
- "streamAIWithTools",
15
- "StreamAIWithToolsOptions"
16
- ]
17
- }
18
- ],
19
- "date": "2026-09-15",
20
- "version": "0.0.58"
21
- },
22
- {
23
- "changes": [
24
- {
25
- "kind": "internal",
26
- "summary": "Regenerate the OpenRouter client declaration with equivalent reordered response union types",
27
- "symbols": [
28
- "createOpenRouterClient"
29
- ]
30
- },
31
- {
32
- "kind": "added",
33
- "summary": "Add model-specific token capacity, optional provider capacity configuration, and recoverable long-text preparation",
34
- "symbols": [
35
- "inspectAIInput",
36
- "prepareAITextInput",
37
- "AIProviderConfig",
38
- "OpenAIConfig",
39
- "OpenAIResponsesConfig"
40
- ]
41
- }
42
- ],
43
- "date": "2026-09-15",
44
- "version": "0.0.57"
45
- }
46
- ]
2
+ "contract": 1,
3
+ "name": "@absolutejs/ai",
4
+ "releases": [
5
+ {
6
+ "changes": [
7
+ {
8
+ "kind": "added",
9
+ "summary": "Allow a separate preparation model with its own verified capacity while preserving the final answer model and invalidating notes when the preparation model changes",
10
+ "symbols": [
11
+ "PrepareAITextInputOptions",
12
+ "prepareAITextInput",
13
+ "prepareAITextInputStep"
14
+ ]
15
+ },
16
+ {
17
+ "kind": "fixed",
18
+ "summary": "Fill preparation sections with bounded tokenizer-checked refinement, avoid duplicate final counting, and honor cancellation before generation",
19
+ "symbols": [
20
+ "prepareAITextInput",
21
+ "prepareAITextInputStep"
22
+ ]
23
+ }
24
+ ],
25
+ "date": "2026-09-16",
26
+ "version": "0.1.1"
27
+ },
28
+ {
29
+ "changes": [
30
+ {
31
+ "kind": "changed",
32
+ "summary": "Validate model capacity by default across generation, structured output, WebSocket and SSE entry points; reserve token headroom and support one protocol-preserving context recovery attempt. Providers without counting capability now fail explicitly; contextPolicy: false opts into raw behavior.",
33
+ "symbols": [
34
+ "generateAI",
35
+ "generateAIWithTools",
36
+ "generateObjectAI",
37
+ "streamAI",
38
+ "streamAIToSSE",
39
+ "streamAIWithTools",
40
+ "inspectAIContext",
41
+ "createAIStoredToolResultRecovery",
42
+ "StreamAIWithToolsOptions",
43
+ "GenerateAIOptions",
44
+ "GenerateAIResult",
45
+ "GenerateObjectAIOptions",
46
+ "AIProviderConfig",
47
+ "StreamAIOptions",
48
+ "AIChatPluginConfig"
49
+ ]
50
+ },
51
+ {
52
+ "kind": "added",
53
+ "summary": "Add one-section text preparation steps for durable workers, with explicit pending/ready outcomes and checkpoint persistence before yielding",
54
+ "symbols": [
55
+ "prepareAITextInputStep",
56
+ "AITextPreparationStep"
57
+ ]
58
+ },
59
+ {
60
+ "kind": "added",
61
+ "summary": "Budget final retrieval instructions and tools before compacting text, with matching checkpoint invalidation",
62
+ "symbols": [
63
+ "PrepareAITextInputOptions",
64
+ "prepareAITextInput"
65
+ ]
66
+ },
67
+ {
68
+ "kind": "fixed",
69
+ "summary": "Preserve conversation origin across long-text preparation sections, distinguish source facts from embedded instructions, reserve more of the available context for factual notes, and invalidate checkpoints from the previous preparation policy",
70
+ "symbols": [
71
+ "prepareAITextInput",
72
+ "prepareAITextInputStep"
73
+ ]
74
+ }
75
+ ],
76
+ "date": "2026-09-16",
77
+ "version": "0.1.0"
78
+ },
79
+ {
80
+ "changes": [
81
+ {
82
+ "kind": "added",
83
+ "summary": "Keep compacted text useful with read-only original-source search, checkpointed ingestion, and capacity-checked terminal tool loops",
84
+ "symbols": [
85
+ "createAITextSource",
86
+ "prepareAITextInput",
87
+ "PrepareAITextInputOptions",
88
+ "streamAIWithTools",
89
+ "StreamAIWithToolsOptions"
90
+ ]
91
+ }
92
+ ],
93
+ "date": "2026-09-15",
94
+ "version": "0.0.58"
95
+ },
96
+ {
97
+ "changes": [
98
+ {
99
+ "kind": "internal",
100
+ "summary": "Regenerate the OpenRouter client declaration with equivalent reordered response union types",
101
+ "symbols": [
102
+ "createOpenRouterClient"
103
+ ]
104
+ },
105
+ {
106
+ "kind": "added",
107
+ "summary": "Add model-specific token capacity, optional provider capacity configuration, and recoverable long-text preparation",
108
+ "symbols": [
109
+ "inspectAIInput",
110
+ "prepareAITextInput",
111
+ "AIProviderConfig",
112
+ "OpenAIConfig",
113
+ "OpenAIResponsesConfig"
114
+ ]
115
+ }
116
+ ],
117
+ "date": "2026-09-15",
118
+ "version": "0.0.57"
119
+ }
120
+ ]
47
121
  }