@absolutejs/ai 0.2.6 → 0.2.8
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 +12 -0
- package/README.md +2 -0
- package/changelog.json +297 -261
- package/dist/ai/index.js +11 -2
- package/dist/ai/index.js.map +5 -5
- package/dist/ai/models/index.js +315 -28
- package/dist/ai/models/index.js.map +7 -6
- package/dist/ai/providers/anthropic.js +9 -2
- package/dist/ai/providers/anthropic.js.map +4 -4
- package/dist/ai/providers/gemini.js +9 -2
- package/dist/ai/providers/gemini.js.map +4 -4
- package/dist/ai/providers/ollama.js +2 -2
- package/dist/ai/providers/ollama.js.map +3 -3
- package/dist/ai/providers/openai.js +9 -2
- package/dist/ai/providers/openai.js.map +4 -4
- package/dist/ai/providers/openaiCompatible.js +9 -2
- package/dist/ai/providers/openaiCompatible.js.map +4 -4
- package/dist/ai/providers/openaiResponses.js +9 -2
- package/dist/ai/providers/openaiResponses.js.map +4 -4
- package/dist/ai/providers/openrouter.js +9 -2
- package/dist/ai/providers/openrouter.js.map +4 -4
- package/dist/ai/research.js +84 -0
- package/dist/ai/research.js.map +10 -0
- package/dist/src/ai/generateAI.d.ts +2 -0
- package/dist/src/ai/models/catalog.d.ts +2 -1
- package/dist/src/ai/models/directory.d.ts +38 -0
- package/dist/src/ai/models/index.d.ts +1 -0
- package/dist/src/ai/models/reasoning.d.ts +2 -1
- package/dist/src/ai/research.d.ts +33 -0
- package/dist/src/ai/research.test.d.ts +1 -0
- package/dist/types/ai.d.ts +2 -0
- package/package.json +7 -2
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var __require = import.meta.require;
|
|
3
|
+
|
|
4
|
+
// src/ai/research.ts
|
|
5
|
+
import {
|
|
6
|
+
boundedQueries,
|
|
7
|
+
evidenceText,
|
|
8
|
+
sourceSupportsQuote
|
|
9
|
+
} from "@absolutejs/search";
|
|
10
|
+
var researchWithEvidence = async (input) => {
|
|
11
|
+
const requested = input.queries ?? boundedQueries(input.query);
|
|
12
|
+
const maxQueries = input.maxQueries ?? 2;
|
|
13
|
+
if (!Number.isInteger(maxQueries) || maxQueries < 1)
|
|
14
|
+
throw new Error("Research requires a positive query budget");
|
|
15
|
+
const searches = [];
|
|
16
|
+
const limitations = [];
|
|
17
|
+
const generatedAt = new Date().toISOString();
|
|
18
|
+
if (requested.length > maxQueries)
|
|
19
|
+
limitations.push("Query budget reached; some requested research was not performed");
|
|
20
|
+
for (const query of requested.slice(0, maxQueries)) {
|
|
21
|
+
input.signal?.throwIfAborted();
|
|
22
|
+
searches.push(await input.provider.search({
|
|
23
|
+
query,
|
|
24
|
+
mode: "context",
|
|
25
|
+
signal: input.signal,
|
|
26
|
+
maxTokens: input.maxTokens ?? 4096,
|
|
27
|
+
freshness: input.freshness
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
input.signal?.throwIfAborted();
|
|
31
|
+
const byUrl = new Map;
|
|
32
|
+
for (const search of searches) {
|
|
33
|
+
limitations.push(...search.limitations);
|
|
34
|
+
for (const source of search.sources) {
|
|
35
|
+
const previous = byUrl.get(source.url);
|
|
36
|
+
byUrl.set(source.url, previous ? {
|
|
37
|
+
...previous,
|
|
38
|
+
excerpts: [
|
|
39
|
+
...new Set([...previous.excerpts, ...source.excerpts])
|
|
40
|
+
]
|
|
41
|
+
} : source);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const normalize = (value) => value.normalize("NFKC").toLowerCase().replace(/\s+/gu, " ").trim();
|
|
45
|
+
const requiredPhrases = input.requiredPhrases ?? [...input.query.matchAll(/"([^"\n]+)"/gu)].map((match) => match[1]);
|
|
46
|
+
const sources = [...byUrl.values()].filter((source) => requiredPhrases.every((phrase) => normalize(`${source.title} ${source.excerpts.join(" ")}`).includes(normalize(phrase))));
|
|
47
|
+
if (sources.length < byUrl.size)
|
|
48
|
+
limitations.push("Sources that did not establish the required literal entity were excluded; similarly named entities are not substitutes.");
|
|
49
|
+
const complete = searches.length > 0 && searches.every((search) => search.status === "ok" || search.status === "empty") && requested.length <= maxQueries;
|
|
50
|
+
const base = { searches, sources, limitations, generatedAt };
|
|
51
|
+
if (!sources.length)
|
|
52
|
+
return {
|
|
53
|
+
...base,
|
|
54
|
+
status: complete ? "empty" : "unavailable",
|
|
55
|
+
text: "",
|
|
56
|
+
findings: []
|
|
57
|
+
};
|
|
58
|
+
input.signal?.throwIfAborted();
|
|
59
|
+
const synthesis = await input.synthesize(evidenceText(sources), input.signal);
|
|
60
|
+
const findings = synthesis.findings.filter((finding) => {
|
|
61
|
+
const source = sources.find((source2) => source2.id === finding.sourceId);
|
|
62
|
+
return typeof finding.claim === "string" && Boolean(finding.claim.trim()) && typeof finding.quote === "string" && source && sourceSupportsQuote(source, finding.quote);
|
|
63
|
+
});
|
|
64
|
+
if (findings.length !== synthesis.findings.length)
|
|
65
|
+
limitations.push("Unsupported source references or quotations were excluded");
|
|
66
|
+
limitations.push(...synthesis.limitations ?? []);
|
|
67
|
+
const text = findings.map((finding) => `${finding.claim}
|
|
68
|
+
Evidence: ${finding.quote}
|
|
69
|
+
Source: ${sources.find((source) => source.id === finding.sourceId).url}`).join(`
|
|
70
|
+
|
|
71
|
+
`);
|
|
72
|
+
return {
|
|
73
|
+
...base,
|
|
74
|
+
status: complete && findings.length > 0 && !limitations.length ? "grounded" : "partial",
|
|
75
|
+
text,
|
|
76
|
+
findings
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
export {
|
|
80
|
+
researchWithEvidence
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
//# debugId=0CBE93DA058E304664756E2164756E21
|
|
84
|
+
//# sourceMappingURL=research.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/ai/research.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import {\n boundedQueries,\n evidenceText,\n sourceSupportsQuote,\n type SearchProvider,\n type SearchResult,\n type SearchSource,\n} from \"@absolutejs/search\";\nexport type ResearchFinding = {\n claim: string;\n sourceId: string;\n quote: string;\n eventDate?: string;\n};\nexport type ResearchEvidence = {\n status: \"grounded\" | \"partial\" | \"empty\" | \"unavailable\";\n text: string;\n findings: ResearchFinding[];\n sources: SearchSource[];\n searches: SearchResult[];\n limitations: string[];\n generatedAt: string;\n};\nexport type ResearchSynthesis = {\n findings: ResearchFinding[];\n limitations?: string[];\n};\n/** Retrieval and synthesis are separate injected capabilities. No hosted search is enabled here. */\nexport const researchWithEvidence = async (input: {\n query: string;\n queries?: string[];\n provider: SearchProvider;\n signal?: AbortSignal;\n maxQueries?: number;\n maxTokens?: number;\n freshness?: string;\n /** Required literal entity phrases; defaults to quoted phrases in the question. */\n requiredPhrases?: string[];\n synthesize: (\n evidence: string,\n signal?: AbortSignal,\n ) => Promise<ResearchSynthesis>;\n}): Promise<ResearchEvidence> => {\n const requested = input.queries ?? boundedQueries(input.query);\n const maxQueries = input.maxQueries ?? 2;\n if (!Number.isInteger(maxQueries) || maxQueries < 1)\n throw new Error(\"Research requires a positive query budget\");\n const searches: SearchResult[] = [];\n const limitations: string[] = [];\n const generatedAt = new Date().toISOString();\n if (requested.length > maxQueries)\n limitations.push(\n \"Query budget reached; some requested research was not performed\",\n );\n for (const query of requested.slice(0, maxQueries)) {\n input.signal?.throwIfAborted();\n searches.push(\n await input.provider.search({\n query,\n mode: \"context\",\n signal: input.signal,\n maxTokens: input.maxTokens ?? 4096,\n freshness: input.freshness,\n }),\n );\n }\n input.signal?.throwIfAborted();\n const byUrl = new Map<string, SearchSource>();\n for (const search of searches) {\n limitations.push(...search.limitations);\n for (const source of search.sources) {\n const previous = byUrl.get(source.url);\n byUrl.set(\n source.url,\n previous\n ? {\n ...previous,\n excerpts: [\n ...new Set([...previous.excerpts, ...source.excerpts]),\n ],\n }\n : source,\n );\n }\n }\n const normalize = (value: string) =>\n value.normalize(\"NFKC\").toLowerCase().replace(/\\s+/gu, \" \").trim();\n const requiredPhrases =\n input.requiredPhrases ??\n [...input.query.matchAll(/\"([^\"\\n]+)\"/gu)].map((match) => match[1]!);\n const sources = [...byUrl.values()].filter((source) =>\n requiredPhrases.every((phrase) =>\n normalize(`${source.title} ${source.excerpts.join(\" \")}`).includes(\n normalize(phrase),\n ),\n ),\n );\n if (sources.length < byUrl.size)\n limitations.push(\n \"Sources that did not establish the required literal entity were excluded; similarly named entities are not substitutes.\",\n );\n const complete =\n searches.length > 0 &&\n searches.every(\n (search) => search.status === \"ok\" || search.status === \"empty\",\n ) &&\n requested.length <= maxQueries;\n const base = { searches, sources, limitations, generatedAt };\n if (!sources.length)\n return {\n ...base,\n status: complete ? \"empty\" : \"unavailable\",\n text: \"\",\n findings: [],\n };\n input.signal?.throwIfAborted();\n const synthesis = await input.synthesize(evidenceText(sources), input.signal);\n const findings = synthesis.findings.filter((finding) => {\n const source = sources.find((source) => source.id === finding.sourceId);\n return (\n typeof finding.claim === \"string\" &&\n Boolean(finding.claim.trim()) &&\n typeof finding.quote === \"string\" &&\n source &&\n sourceSupportsQuote(source, finding.quote)\n );\n });\n if (findings.length !== synthesis.findings.length)\n limitations.push(\n \"Unsupported source references or quotations were excluded\",\n );\n limitations.push(...(synthesis.limitations ?? []));\n const text = findings\n .map(\n (finding) =>\n `${finding.claim}\\nEvidence: ${finding.quote}\\nSource: ${sources.find((source) => source.id === finding.sourceId)!.url}`,\n )\n .join(\"\\n\\n\");\n // Quotation/source checks establish provenance, not semantic entailment. Host review remains necessary.\n return {\n ...base,\n status:\n complete && findings.length > 0 && !limitations.length\n ? \"grounded\"\n : \"partial\",\n text,\n findings,\n };\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "0CBE93DA058E304664756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -6,6 +6,7 @@ export type GenerateAIToolCall = {
|
|
|
6
6
|
input: unknown;
|
|
7
7
|
};
|
|
8
8
|
export type GenerateAIOptions = {
|
|
9
|
+
maxRetries?: number;
|
|
9
10
|
contextPolicy?: AIContextPolicy | false;
|
|
10
11
|
provider: AIProviderConfig;
|
|
11
12
|
model: string;
|
|
@@ -73,6 +74,7 @@ export declare const toProviderTools: (tools: AIToolMap) => AIProviderToolDefini
|
|
|
73
74
|
*/
|
|
74
75
|
export declare const generateAIWithTools: (options: GenerateAIWithToolsOptions) => Promise<GenerateAIWithToolsResult>;
|
|
75
76
|
export type GenerateObjectAIOptions<T> = {
|
|
77
|
+
maxRetries?: number;
|
|
76
78
|
contextPolicy?: AIContextPolicy | false;
|
|
77
79
|
provider: AIProviderConfig;
|
|
78
80
|
model: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ModelMetadata } from "./index";
|
|
2
|
-
/** Reviewed provider support, independent of application feature availability.
|
|
2
|
+
/** Reviewed provider support, independent of application feature availability.
|
|
3
|
+
* Anthropic entries come from the Models API (`max_input_tokens`, `capabilities`). */
|
|
3
4
|
export declare const MODEL_METADATA: Readonly<Record<string, ModelMetadata>>;
|
|
4
5
|
export declare const getModelMetadata: (provider: string, id: string) => ModelMetadata | undefined;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { modelCapabilities } from "./index";
|
|
2
|
+
/** Display names for the providers the directory covers. */
|
|
3
|
+
export declare const MODEL_PROVIDERS: Readonly<Record<string, string>>;
|
|
4
|
+
export type ModelDirectoryEntry = {
|
|
5
|
+
provider: string;
|
|
6
|
+
/** The exact model ID sent to the provider. */
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
/** One short, plain sentence for pickers. */
|
|
10
|
+
description: string;
|
|
11
|
+
/** A current flagship worth showing first. */
|
|
12
|
+
featured?: boolean;
|
|
13
|
+
/** Superseded by a newer model in the same line; hide by default. */
|
|
14
|
+
legacy?: boolean;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Human-facing model directory for pickers, newest first within each provider.
|
|
18
|
+
* Capabilities and context windows come from MODEL_METADATA, not from here.
|
|
19
|
+
* Anthropic entries were checked against the Models API on 2026-09-25.
|
|
20
|
+
*/
|
|
21
|
+
export declare const MODEL_DIRECTORY: readonly ModelDirectoryEntry[];
|
|
22
|
+
export declare const modelKey: (model: {
|
|
23
|
+
provider: string;
|
|
24
|
+
id: string;
|
|
25
|
+
}) => string;
|
|
26
|
+
export type ListedModel = ModelDirectoryEntry & {
|
|
27
|
+
key: string;
|
|
28
|
+
providerName: string;
|
|
29
|
+
capabilities: ReturnType<typeof modelCapabilities>;
|
|
30
|
+
contextWindow: number | null;
|
|
31
|
+
reasoningEfforts: readonly string[];
|
|
32
|
+
};
|
|
33
|
+
/** Directory entries joined with reviewed metadata, ready for a picker. */
|
|
34
|
+
export declare const listModels: (options?: {
|
|
35
|
+
providers?: readonly string[];
|
|
36
|
+
includeLegacy?: boolean;
|
|
37
|
+
}) => ListedModel[];
|
|
38
|
+
export declare const findModel: (provider: string, id: string) => ModelDirectoryEntry | undefined;
|
|
@@ -30,3 +30,4 @@ export type ModelCapability = keyof typeof MODEL_CAPABILITY_DESCRIPTIONS;
|
|
|
30
30
|
export declare const modelCapabilities: (metadata?: ModelMetadata) => ModelCapability[];
|
|
31
31
|
export { MODEL_METADATA, getModelMetadata } from "./catalog";
|
|
32
32
|
export { MODEL_REASONING, REASONING_EFFORTS, getModelReasoning, isReasoningSelection, supportsReasoningSelection, reasoningSelectionLabel, type ModelReasoning, type ReasoningSelection, } from "./reasoning";
|
|
33
|
+
export { MODEL_DIRECTORY, MODEL_PROVIDERS, findModel, listModels, modelKey, type ListedModel, type ModelDirectoryEntry, } from "./directory";
|
|
@@ -8,7 +8,8 @@ export type ModelReasoning = {
|
|
|
8
8
|
source: string;
|
|
9
9
|
};
|
|
10
10
|
export declare const isReasoningSelection: (value: unknown) => value is ReasoningSelection;
|
|
11
|
-
/** Exact reviewed IDs; unknown models expose only the provider default. Reviewed 2026-09-20
|
|
11
|
+
/** Exact reviewed IDs; unknown models expose only the provider default. Reviewed 2026-09-20;
|
|
12
|
+
* Anthropic effort levels re-checked against the Models API 2026-09-25. */
|
|
12
13
|
export declare const MODEL_REASONING: Readonly<Record<string, ModelReasoning>>;
|
|
13
14
|
export declare const getModelReasoning: (provider: string, model: string) => ModelReasoning | undefined;
|
|
14
15
|
export declare const supportsReasoningSelection: (provider: string, model: string, selection: ReasoningSelection) => boolean;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type SearchProvider, type SearchResult, type SearchSource } from "@absolutejs/search";
|
|
2
|
+
export type ResearchFinding = {
|
|
3
|
+
claim: string;
|
|
4
|
+
sourceId: string;
|
|
5
|
+
quote: string;
|
|
6
|
+
eventDate?: string;
|
|
7
|
+
};
|
|
8
|
+
export type ResearchEvidence = {
|
|
9
|
+
status: "grounded" | "partial" | "empty" | "unavailable";
|
|
10
|
+
text: string;
|
|
11
|
+
findings: ResearchFinding[];
|
|
12
|
+
sources: SearchSource[];
|
|
13
|
+
searches: SearchResult[];
|
|
14
|
+
limitations: string[];
|
|
15
|
+
generatedAt: string;
|
|
16
|
+
};
|
|
17
|
+
export type ResearchSynthesis = {
|
|
18
|
+
findings: ResearchFinding[];
|
|
19
|
+
limitations?: string[];
|
|
20
|
+
};
|
|
21
|
+
/** Retrieval and synthesis are separate injected capabilities. No hosted search is enabled here. */
|
|
22
|
+
export declare const researchWithEvidence: (input: {
|
|
23
|
+
query: string;
|
|
24
|
+
queries?: string[];
|
|
25
|
+
provider: SearchProvider;
|
|
26
|
+
signal?: AbortSignal;
|
|
27
|
+
maxQueries?: number;
|
|
28
|
+
maxTokens?: number;
|
|
29
|
+
freshness?: string;
|
|
30
|
+
/** Required literal entity phrases; defaults to quoted phrases in the question. */
|
|
31
|
+
requiredPhrases?: string[];
|
|
32
|
+
synthesize: (evidence: string, signal?: AbortSignal) => Promise<ResearchSynthesis>;
|
|
33
|
+
}) => Promise<ResearchEvidence>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/types/ai.d.ts
CHANGED
|
@@ -204,6 +204,8 @@ export type ReasoningConfig = {
|
|
|
204
204
|
effort?: ReasoningEffort;
|
|
205
205
|
};
|
|
206
206
|
export type AIProviderStreamParams = {
|
|
207
|
+
/** Override transport retries for operations whose host owns attempt accounting. */
|
|
208
|
+
maxRetries?: number;
|
|
207
209
|
/**
|
|
208
210
|
* Mark the system prompt as cacheable (Anthropic prompt caching). The system
|
|
209
211
|
* block is sent with `cache_control: ephemeral`, so repeated calls reusing the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@absolutejs/ai",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"homepage": "https://github.com/absolutejs/ai",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/absolutejs/ai/issues"
|
|
@@ -92,11 +92,16 @@
|
|
|
92
92
|
"./models": {
|
|
93
93
|
"import": "./dist/ai/models/index.js",
|
|
94
94
|
"types": "./dist/src/ai/models/index.d.ts"
|
|
95
|
+
},
|
|
96
|
+
"./research": {
|
|
97
|
+
"types": "./dist/src/ai/research.d.ts",
|
|
98
|
+
"import": "./dist/ai/research.js"
|
|
95
99
|
}
|
|
96
100
|
},
|
|
97
101
|
"dependencies": {
|
|
98
102
|
"@absolutejs/linked-providers": "0.0.2",
|
|
99
|
-
"@openrouter/sdk": "^1.2.47"
|
|
103
|
+
"@openrouter/sdk": "^1.2.47",
|
|
104
|
+
"@absolutejs/search": "^0.1.0"
|
|
100
105
|
},
|
|
101
106
|
"peerDependencies": {
|
|
102
107
|
"@absolutejs/isolated-jsc": ">= 0.4.0",
|