@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.
@@ -0,0 +1,46 @@
1
+ import type { AIChunk, AIProviderConfig, AIProviderMessage, AIProviderStreamParams } from "../../types/ai";
2
+ import { type AIInputCapacity } from "./inputCapacity";
3
+ /** Token budgets, never character approximations or guessed model limits. */
4
+ export type AIContextBudget = {
5
+ /** Optional working target below the model's hard input capacity. */
6
+ workingInputTokens?: number;
7
+ /** Default: 1% of available input, capped at 2,048 tokens. */
8
+ countingMarginTokens?: number;
9
+ /** Default with tools: 10% of available input, capped at 8,192 tokens. */
10
+ toolResultReserveTokens?: number;
11
+ };
12
+ export type AIContextCapacity = AIInputCapacity & {
13
+ workingInputTokens: number;
14
+ countingMarginTokens: number;
15
+ toolResultReserveTokens: number;
16
+ withinWorkingLimit: boolean;
17
+ };
18
+ export type AIContextRecoveryReason = "working_limit" | "provider_rejection";
19
+ export type AIContextEvent = {
20
+ type: "checked";
21
+ capacity: AIContextCapacity;
22
+ } | {
23
+ type: "recovered";
24
+ reason: AIContextRecoveryReason;
25
+ before: AIContextCapacity;
26
+ after: AIContextCapacity;
27
+ };
28
+ export type AIContextPolicy = AIContextBudget & {
29
+ /** Called at most once per model turn, before any output. Preserve originals
30
+ * in application storage; return compacted/retrieved messages, never effects.
31
+ * Tool IDs/inputs, signed thinking, media, provider data and system messages
32
+ * must remain intact. Tool result text may be replaced with saved-source notes. */
33
+ recover?: (input: {
34
+ params: AIProviderStreamParams;
35
+ capacity: AIContextCapacity;
36
+ reason: AIContextRecoveryReason;
37
+ }) => Promise<AIProviderMessage[]>;
38
+ onEvent?: (event: AIContextEvent) => void;
39
+ };
40
+ export declare const inspectAIContext: (provider: AIProviderConfig, params: AIProviderStreamParams, budget?: AIContextBudget) => Promise<AIContextCapacity>;
41
+ /** Only an explicit structured capacity rejection qualifies; arbitrary 400s,
42
+ * timeouts and provider outages do not. Provider adapters may add a classifier. */
43
+ export declare const isAIContextRejection: (error: unknown) => boolean;
44
+ /** Shared high-level dispatch. `false` deliberately opts into raw provider
45
+ * behavior. Recovery never replays emitted output or executes application tools. */
46
+ export declare const streamWithAIContext: (provider: AIProviderConfig, params: AIProviderStreamParams, policy?: AIContextPolicy | false, onPrepared?: (params: AIProviderStreamParams) => void) => AsyncGenerator<AIChunk>;
@@ -1,10 +1,12 @@
1
- import type { AICitationChunk, AIProviderConfig, AIProviderMessage, AIProviderResponseFormat, AIProviderToolChoice, AIProviderToolDefinition, AIResponseMetadata, AIToolMap, AIUsage, ReasoningConfig } from "../../types/ai";
1
+ import { type AIContextPolicy } from "./contextPolicy";
2
+ import type { AICitationChunk, AIProviderConfig, AIProviderContentBlock, AIProviderMessage, AIProviderResponseFormat, AIProviderToolChoice, AIProviderToolDefinition, AIResponseMetadata, AIToolMap, AIUsage, ReasoningConfig } from "../../types/ai";
2
3
  export type GenerateAIToolCall = {
3
4
  id: string;
4
5
  name: string;
5
6
  input: unknown;
6
7
  };
7
8
  export type GenerateAIOptions = {
9
+ contextPolicy?: AIContextPolicy | false;
8
10
  provider: AIProviderConfig;
9
11
  model: string;
10
12
  messages: AIProviderMessage[];
@@ -26,6 +28,10 @@ export type GenerateAIOptions = {
26
28
  signal?: AbortSignal;
27
29
  };
28
30
  export type GenerateAIResult = {
31
+ /** Exact assistant blocks retained for protocol-safe tool/repair turns. */
32
+ contentBlocks?: AIProviderContentBlock[];
33
+ /** Actual request history after any context recovery. */
34
+ requestMessages?: AIProviderMessage[];
29
35
  citations: AICitationChunk[];
30
36
  metadata?: AIResponseMetadata;
31
37
  text: string;
@@ -67,6 +73,7 @@ export declare const toProviderTools: (tools: AIToolMap) => AIProviderToolDefini
67
73
  */
68
74
  export declare const generateAIWithTools: (options: GenerateAIWithToolsOptions) => Promise<GenerateAIWithToolsResult>;
69
75
  export type GenerateObjectAIOptions<T> = {
76
+ contextPolicy?: AIContextPolicy | false;
70
77
  provider: AIProviderConfig;
71
78
  model: string;
72
79
  messages: AIProviderMessage[];
@@ -39,8 +39,11 @@ export * from "../../types/ai";
39
39
  export type { SessionStore } from "../../types/session";
40
40
  export { AIInputError, inspectAIInput } from "./inputCapacity";
41
41
  export type { AIModelLimits, AIInputCapacity } from "./inputCapacity";
42
- export { prepareAITextInput } from "./prepareTextInput";
43
- export type { PreparedAITextInput, PrepareAITextInputOptions, } from "./prepareTextInput";
42
+ export { prepareAITextInput, prepareAITextInputStep } from "./prepareTextInput";
43
+ export type { PreparedAITextInput, AITextPreparationStep, PrepareAITextInputOptions, } from "./prepareTextInput";
44
44
  export { createAITextSource } from "./textSource";
45
45
  export type { AITextPassage, AITextSource } from "./textSource";
46
46
  export type { AITextPreparationCheckpoint } from "./prepareTextInput";
47
+ export { inspectAIContext, streamWithAIContext, isAIContextRejection, } from "./contextPolicy";
48
+ export type { AIContextBudget, AIContextCapacity, AIContextPolicy, AIContextEvent, AIContextRecoveryReason, } from "./contextPolicy";
49
+ export { createAIStoredToolResultRecovery } from "./storedToolResultRecovery";
@@ -1,3 +1,4 @@
1
+ import { type AIContextBudget } from "./contextPolicy";
1
2
  import type { AIProviderConfig, AIProviderStreamParams, AIUsage } from "../../types/ai";
2
3
  export type AITextPreparationCheckpoint = {
3
4
  version: 1;
@@ -13,6 +14,15 @@ export type PreparedAITextInput = {
13
14
  sectionsProcessed: number;
14
15
  };
15
16
  export type PrepareAITextInputOptions = {
17
+ contextBudget?: AIContextBudget;
18
+ /** Optional model on the same provider for source-note preparation only.
19
+ * The final request retains params.model. Validate quality for your workload
20
+ * before choosing a cheaper model; originals must remain available. */
21
+ preparationModel?: string;
22
+ /** Final instructions/tools used only after compaction, counted before reading
23
+ * the source. Retrieval tools must not be added after preparation has fitted
24
+ * the final request. The direct, already-fitting request is unchanged. */
25
+ compactedContext?: Pick<AIProviderStreamParams, "systemPrompt" | "tools">;
16
26
  /** Reuse only a server-owned checkpoint. Originals and task fingerprints are validated. */
17
27
  checkpoint?: AITextPreparationCheckpoint;
18
28
  /** Save after each finished section, before the next model call. Never accept client-supplied notes. */
@@ -26,8 +36,19 @@ export type PrepareAITextInputOptions = {
26
36
  /** Each section is a real model call; applications must meter its usage. */
27
37
  onUsage?: (usage: AIUsage) => void;
28
38
  };
29
- /** Fit text using this provider's tokenizer and model capacity. Never truncates source.
30
- * Oversized conversations are read sequentially into rolling notes, with every section
31
- * counted before generation. Originals and tool history are never mutated.
39
+ export type AITextPreparationStep = {
40
+ status: "ready";
41
+ prepared: PreparedAITextInput;
42
+ } | {
43
+ status: "pending";
44
+ checkpoint: AITextPreparationCheckpoint;
45
+ };
46
+ /** Process at most one source section. Persist the checkpoint and schedule a
47
+ * continuation when pending; never send partial notes as a completed request.
48
+ * A final continuation validates the assembled request without another model
49
+ * call. The caller owns durable scheduling, originals and attempt fencing.
32
50
  */
51
+ export declare const prepareAITextInputStep: (provider: AIProviderConfig, params: AIProviderStreamParams, options?: PrepareAITextInputOptions) => Promise<AITextPreparationStep>;
52
+ /** Prepare all sections in this invocation. Use prepareAITextInputStep for
53
+ * bounded durable workers; this convenience entrypoint retains its contract. */
33
54
  export declare const prepareAITextInput: (provider: AIProviderConfig, params: AIProviderStreamParams, options?: PrepareAITextInputOptions) => Promise<PreparedAITextInput>;
@@ -0,0 +1,7 @@
1
+ import type { AIContextPolicy } from "./contextPolicy";
2
+ /** Reclaim older results ONLY for tools that reread immutable saved sources.
3
+ * The caller guarantees these names can reproduce the original at the same
4
+ * authorized version. Other results, calls, thinking and the newest lookup stay
5
+ * intact. This does not delete originals, summarize facts, run tools, or truncate
6
+ * the latest evidence. If that is insufficient, the policy fails explicitly. */
7
+ export declare const createAIStoredToolResultRecovery: (toolNames: readonly string[]) => NonNullable<AIContextPolicy["recover"]>;
@@ -5,7 +5,7 @@ export type StreamAIWithToolsOptions = Omit<GenerateAIOptions, "tools" | "toolCh
5
5
  tools: AIToolMap;
6
6
  /** Stop immediately after one of these tools executes successfully; do not generate an extra reply. */
7
7
  stopAfterTools?: string[];
8
- /** Count every model request, including added tool results, against provider capacity. */
8
+ /** @deprecated Capacity validation is automatic. Use contextPolicy; false is the explicit raw opt-out. */
9
9
  validateInput?: boolean;
10
10
  /** Max model⇄tool round-trips before forcing a final answer. Default 8. */
11
11
  maxTurns?: number;
@@ -332,6 +332,8 @@ export type AIProviderToolDefinition = {
332
332
  };
333
333
  export type AIProviderConfig = {
334
334
  inputCapacity?: {
335
+ /** Recognize only genuine model-context rejections, never arbitrary 400s. */
336
+ isContextError?: (error: unknown) => boolean;
335
337
  outputTokens?: (params: AIProviderStreamParams) => number | undefined;
336
338
  getLimits: (params: AIProviderStreamParams) => Promise<import("../src/ai/inputCapacity").AIModelLimits>;
337
339
  countTokens: (params: AIProviderStreamParams) => Promise<number>;
@@ -604,6 +606,8 @@ export type AIConversationSummary = {
604
606
  lastMessageAt?: number;
605
607
  };
606
608
  export type StreamAIOptions = {
609
+ /** Automatic capacity checks; false explicitly selects raw provider behavior. */
610
+ contextPolicy?: import("../src/ai/contextPolicy").AIContextPolicy | false;
607
611
  provider: AIProviderConfig;
608
612
  model: string;
609
613
  messages?: AIProviderMessage[];
@@ -797,6 +801,7 @@ export type AIHTMXRenderConfig = {
797
801
  error?: (message: string) => string;
798
802
  };
799
803
  export type AIChatPluginConfig = {
804
+ contextPolicy?: import("../src/ai/contextPolicy").AIContextPolicy | false;
800
805
  path?: string;
801
806
  provider: (providerName: string) => AIProviderConfig;
802
807
  model?: string | ((providerName: string) => string);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/ai",
3
- "version": "0.0.58",
3
+ "version": "0.1.1",
4
4
  "homepage": "https://github.com/absolutejs/ai",
5
5
  "bugs": {
6
6
  "url": "https://github.com/absolutejs/ai/issues"
@@ -124,7 +124,7 @@
124
124
  "@absolutejs/absolute": "^0.20.0-beta.0",
125
125
  "@absolutejs/changelog": "^0.6.0",
126
126
  "@absolutejs/isolated-jsc": "0.6.0",
127
- "@absolutejs/sync": "2.9.1",
127
+ "@absolutejs/sync": "2.14.0",
128
128
  "@angular/core": "^21.0.0",
129
129
  "@eslint/js": "^10.0.1",
130
130
  "@types/bun": "1.3.9",
@@ -145,6 +145,7 @@
145
145
  "build": "bun run scripts/build.ts",
146
146
  "config": "absolute config",
147
147
  "typecheck": "tsc --noEmit --project tsconfig.json",
148
+ "test:built-context": "bun scripts/verifyBuiltContext.ts",
148
149
  "lint": "eslint . --max-warnings 0",
149
150
  "format": "prettier --write .",
150
151
  "release": "bun run format && bun run build && bun publish",