@infinityi/engine-lib 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.
- package/LICENSE +21 -0
- package/README.md +488 -0
- package/dist/agent/agent-registry.d.ts +46 -0
- package/dist/agent/as-tool.d.ts +64 -0
- package/dist/agent/define.d.ts +35 -0
- package/dist/agent/handoff.d.ts +39 -0
- package/dist/agent/index.d.ts +20 -0
- package/dist/agent/index.js +38 -0
- package/dist/agent/registry.d.ts +27 -0
- package/dist/agent/types.d.ts +109 -0
- package/dist/context/index.d.ts +11 -0
- package/dist/context/index.js +21 -0
- package/dist/context/providers.d.ts +25 -0
- package/dist/context/types.d.ts +63 -0
- package/dist/context/window.d.ts +41 -0
- package/dist/errors.d.ts +93 -0
- package/dist/errors.js +24 -0
- package/dist/events/hub.d.ts +15 -0
- package/dist/events/index.d.ts +26 -0
- package/dist/events/index.js +24 -0
- package/dist/events/subscribers.d.ts +57 -0
- package/dist/events/telemetry.d.ts +61 -0
- package/dist/events/types.d.ts +39 -0
- package/dist/execution/index.d.ts +11 -0
- package/dist/execution/index.js +22 -0
- package/dist/execution/run.d.ts +35 -0
- package/dist/execution/types.d.ts +203 -0
- package/dist/execution/usage.d.ts +14 -0
- package/dist/index-02s1fjxr.js +226 -0
- package/dist/index-19pwq79t.js +0 -0
- package/dist/index-1p6mb2vz.js +32 -0
- package/dist/index-64tt9696.js +1796 -0
- package/dist/index-7690reng.js +96 -0
- package/dist/index-bqg01r42.js +354 -0
- package/dist/index-d4xz3abn.js +0 -0
- package/dist/index-dexgmwg6.js +148 -0
- package/dist/index-fkr3rcq9.js +97 -0
- package/dist/index-jg19te9v.js +0 -0
- package/dist/index-jp2b31xs.js +101 -0
- package/dist/index-jxgj4z08.js +68 -0
- package/dist/index-kte2h4k2.js +0 -0
- package/dist/index-pwr8179t.js +492 -0
- package/dist/index-rentvdpp.js +27 -0
- package/dist/index-vnby35rm.js +84 -0
- package/dist/index-w34cbktd.js +14 -0
- package/dist/index-xsv43c5j.js +39 -0
- package/dist/index-yrqrxwjt.js +148 -0
- package/dist/index-zfgr4xx3.js +90 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +117 -0
- package/dist/lifecycle/component.d.ts +74 -0
- package/dist/lifecycle/index.d.ts +12 -0
- package/dist/lifecycle/index.js +72 -0
- package/dist/messages/factory.d.ts +24 -0
- package/dist/messages/index.d.ts +8 -0
- package/dist/messages/index.js +17 -0
- package/dist/messages/types.d.ts +52 -0
- package/dist/providers/adapter.d.ts +42 -0
- package/dist/providers/anthropic/index.d.ts +31 -0
- package/dist/providers/anthropic/map.d.ts +12 -0
- package/dist/providers/anthropic/stream.d.ts +9 -0
- package/dist/providers/google/index.d.ts +29 -0
- package/dist/providers/google/map.d.ts +13 -0
- package/dist/providers/google/stream.d.ts +11 -0
- package/dist/providers/http.d.ts +61 -0
- package/dist/providers/index.d.ts +32 -0
- package/dist/providers/index.js +35 -0
- package/dist/providers/openai/index.d.ts +34 -0
- package/dist/providers/openai/map.d.ts +10 -0
- package/dist/providers/openai/stream.d.ts +9 -0
- package/dist/providers/openai-compatible/index.d.ts +37 -0
- package/dist/providers/openai-compatible/map.d.ts +13 -0
- package/dist/providers/openai-compatible/stream.d.ts +11 -0
- package/dist/providers/shared.d.ts +34 -0
- package/dist/providers/sse.d.ts +19 -0
- package/dist/providers/stream.d.ts +69 -0
- package/dist/providers/types.d.ts +137 -0
- package/dist/runtime/index.d.ts +11 -0
- package/dist/runtime/index.js +11 -0
- package/dist/runtime/secret.d.ts +12 -0
- package/dist/runtime/types.d.ts +27 -0
- package/dist/schema/builder.d.ts +70 -0
- package/dist/schema/index.d.ts +13 -0
- package/dist/schema/index.js +15 -0
- package/dist/schema/json-schema.d.ts +19 -0
- package/dist/schema/types.d.ts +70 -0
- package/dist/schema/validate.d.ts +19 -0
- package/dist/session/index.d.ts +11 -0
- package/dist/session/index.js +8 -0
- package/dist/session/session.d.ts +31 -0
- package/dist/session/store.d.ts +20 -0
- package/dist/session/types.d.ts +55 -0
- package/dist/testing/conformance.d.ts +106 -0
- package/dist/testing/conformance.js +132 -0
- package/dist/testing/index.d.ts +84 -0
- package/dist/testing/index.js +31 -0
- package/dist/tools/define.d.ts +42 -0
- package/dist/tools/index.d.ts +11 -0
- package/dist/tools/index.js +15 -0
- package/dist/tools/result.d.ts +36 -0
- package/dist/tools/types.d.ts +85 -0
- package/docs/README.md +36 -0
- package/examples/README.md +24 -0
- package/examples/incident-analysis.ts +100 -0
- package/examples/lifecycle.ts +53 -0
- package/examples/multi-agent.ts +93 -0
- package/examples/terminal-coder.ts +80 -0
- package/package.json +114 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// src/lifecycle/component.ts
|
|
2
|
+
var DEFAULT_NAME = "agent-runtime";
|
|
3
|
+
function validateProviders(providers) {
|
|
4
|
+
const seen = new Set;
|
|
5
|
+
for (const provider of providers) {
|
|
6
|
+
if (typeof provider.name !== "string" || provider.name.trim() === "") {
|
|
7
|
+
throw new Error("agentRuntimeComponent: every provider must have a non-empty name");
|
|
8
|
+
}
|
|
9
|
+
if (seen.has(provider.name)) {
|
|
10
|
+
throw new Error(`agentRuntimeComponent: duplicate provider name "${provider.name}"`);
|
|
11
|
+
}
|
|
12
|
+
seen.add(provider.name);
|
|
13
|
+
if (typeof provider.defaultModel !== "string" || provider.defaultModel.trim() === "") {
|
|
14
|
+
throw new Error(`agentRuntimeComponent: provider "${provider.name}" has an empty defaultModel`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async function probeAll(providers, probe, signal) {
|
|
19
|
+
const failures = [];
|
|
20
|
+
for (const provider of providers) {
|
|
21
|
+
try {
|
|
22
|
+
await probe(provider, signal);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
failures.push({ name: provider.name, error });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return failures;
|
|
28
|
+
}
|
|
29
|
+
function agentRuntimeComponent(opts) {
|
|
30
|
+
const name = opts.name ?? DEFAULT_NAME;
|
|
31
|
+
const providers = opts.providers ?? [];
|
|
32
|
+
const { probe, onStop } = opts;
|
|
33
|
+
return {
|
|
34
|
+
name,
|
|
35
|
+
async start(ctx) {
|
|
36
|
+
validateProviders(providers);
|
|
37
|
+
if (opts.probeOnStart === true && probe !== undefined) {
|
|
38
|
+
const failures = await probeAll(providers, probe, ctx.signal);
|
|
39
|
+
if (failures.length > 0) {
|
|
40
|
+
const names = failures.map((f) => f.name).join(", ");
|
|
41
|
+
throw new Error(`agentRuntimeComponent: provider probe failed on start for: ${names}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
ctx.logger.info("agent runtime started", {
|
|
45
|
+
providers: providers.length,
|
|
46
|
+
sessionStore: opts.sessionStore !== undefined
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
async stop(ctx) {
|
|
50
|
+
if (onStop !== undefined)
|
|
51
|
+
await onStop(ctx.signal);
|
|
52
|
+
ctx.logger.info("agent runtime stopped");
|
|
53
|
+
},
|
|
54
|
+
async healthcheck(ctx) {
|
|
55
|
+
if (probe === undefined || providers.length === 0) {
|
|
56
|
+
return { status: "healthy", data: { providers: providers.length } };
|
|
57
|
+
}
|
|
58
|
+
const failures = await probeAll(providers, probe, ctx.signal);
|
|
59
|
+
const status = failures.length === 0 ? "healthy" : failures.length < providers.length ? "degraded" : "unhealthy";
|
|
60
|
+
const result = {
|
|
61
|
+
status,
|
|
62
|
+
data: { providers: providers.length, unhealthy: failures.length }
|
|
63
|
+
};
|
|
64
|
+
if (failures.length === 0)
|
|
65
|
+
return result;
|
|
66
|
+
return { ...result, detail: `provider probe failed: ${failures.map((f) => f.name).join(", ")}` };
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
agentRuntimeComponent
|
|
72
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constructors and normalization helpers for the message model.
|
|
3
|
+
*
|
|
4
|
+
* {@link normalizeContent} is the single seam that coerces a bare string
|
|
5
|
+
* into `[text(string)]`, so every other factory and (later) provider
|
|
6
|
+
* adapter can assume `content` is always an array of parts.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import type { ContentPart, Message, TextPart } from "./types";
|
|
11
|
+
/** A {@link TextPart}. */
|
|
12
|
+
export declare function text(value: string): TextPart;
|
|
13
|
+
/** Coerce `string` → `[text(string)]`; pass part arrays through unchanged. */
|
|
14
|
+
export declare function normalizeContent(content: string | ContentPart[]): ContentPart[];
|
|
15
|
+
/** A `system` message. */
|
|
16
|
+
export declare function system(content: string): Message;
|
|
17
|
+
/** A `user` message. */
|
|
18
|
+
export declare function user(content: string | ContentPart[]): Message;
|
|
19
|
+
/** An `assistant` message. */
|
|
20
|
+
export declare function assistant(content: string | ContentPart[]): Message;
|
|
21
|
+
/** A `tool` message carrying the result of a single tool call. */
|
|
22
|
+
export declare function toolResult(toolCallId: string, output: string | TextPart[], opts?: {
|
|
23
|
+
isError?: boolean;
|
|
24
|
+
}): Message;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@infinityi/engine-lib/messages` — the provider-neutral conversation model and its
|
|
3
|
+
* constructors.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
export { assistant, normalizeContent, system, text, toolResult, user, } from "./factory";
|
|
8
|
+
export type { ContentPart, ImagePart, Message, Role, TextPart, ToolCallPart, ToolResultPart, } from "./types";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The provider-neutral conversation model.
|
|
3
|
+
*
|
|
4
|
+
* Messages and their content parts are normalized so that history is
|
|
5
|
+
* portable across providers (Phase 2 adapters translate to/from each
|
|
6
|
+
* provider's native shape). `content` is *always* an array of parts.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
/** Who authored a message. */
|
|
11
|
+
export type Role = "system" | "user" | "assistant" | "tool";
|
|
12
|
+
/** Plain text. */
|
|
13
|
+
export interface TextPart {
|
|
14
|
+
readonly type: "text";
|
|
15
|
+
readonly text: string;
|
|
16
|
+
}
|
|
17
|
+
/** An assistant request to invoke a tool. `arguments` is the raw (unvalidated) model output. */
|
|
18
|
+
export interface ToolCallPart {
|
|
19
|
+
readonly type: "tool_call";
|
|
20
|
+
readonly id: string;
|
|
21
|
+
readonly name: string;
|
|
22
|
+
readonly arguments: unknown;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The outcome of a tool invocation, fed back to the model.
|
|
26
|
+
*
|
|
27
|
+
* Phase 3's structured `ToolResult` schema maps *into* this part; kept
|
|
28
|
+
* minimal here so Phase 1 carries no forward dependency.
|
|
29
|
+
*/
|
|
30
|
+
export interface ToolResultPart {
|
|
31
|
+
readonly type: "tool_result";
|
|
32
|
+
readonly toolCallId: string;
|
|
33
|
+
readonly content: TextPart[];
|
|
34
|
+
readonly isError?: boolean;
|
|
35
|
+
}
|
|
36
|
+
/** Image input. `data` is a base64 payload or a URL. */
|
|
37
|
+
export interface ImagePart {
|
|
38
|
+
readonly type: "image";
|
|
39
|
+
readonly mimeType: string;
|
|
40
|
+
readonly data: string;
|
|
41
|
+
}
|
|
42
|
+
/** Any content part a message may carry. */
|
|
43
|
+
export type ContentPart = TextPart | ToolCallPart | ToolResultPart | ImagePart;
|
|
44
|
+
/** A single normalized message. */
|
|
45
|
+
export interface Message {
|
|
46
|
+
readonly role: Role;
|
|
47
|
+
readonly content: ContentPart[];
|
|
48
|
+
/** Optional author/tool name (e.g. for `role: "tool"`). */
|
|
49
|
+
readonly name?: string;
|
|
50
|
+
/** Free-form, host-defined metadata (never sent to providers). */
|
|
51
|
+
readonly metadata?: Record<string, unknown>;
|
|
52
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared adapter scaffolding for custom providers.
|
|
3
|
+
*
|
|
4
|
+
* {@link createProvider} turns a small per-vendor {@link AdapterSpec} (how to
|
|
5
|
+
* build the request body, where to POST it, how to parse the response, and how
|
|
6
|
+
* to translate the SSE stream) into a full {@link Provider}, centralizing the
|
|
7
|
+
* forge HTTP/resilience plumbing so each adapter stays focused on mapping.
|
|
8
|
+
*
|
|
9
|
+
* This is an advanced extension surface exported from `@infinityi/engine-lib/providers`;
|
|
10
|
+
* ordinary application code should prefer the built-in provider factories.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import type { ProviderHttpOptions } from "./http";
|
|
15
|
+
import type { SseMessage } from "./sse";
|
|
16
|
+
import type { StreamEvent } from "./stream";
|
|
17
|
+
import type { CompletionRequest, CompletionResult, Provider, ProviderCapabilities } from "./types";
|
|
18
|
+
/** Per-vendor behavior consumed by {@link createProvider}. */
|
|
19
|
+
export interface AdapterSpec {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly defaultModel: string;
|
|
22
|
+
readonly capabilities: ProviderCapabilities;
|
|
23
|
+
/** Base transport options (baseUrl, headers, timeout, resilience, fetch). */
|
|
24
|
+
readonly http: ProviderHttpOptions;
|
|
25
|
+
/** Path for a buffered completion, resolved against `baseUrl`. */
|
|
26
|
+
completePath(model: string, req: CompletionRequest): string;
|
|
27
|
+
/** Path for a streaming completion, resolved against `baseUrl`. */
|
|
28
|
+
streamPath(model: string, req: CompletionRequest): string;
|
|
29
|
+
/** Build the provider-native request body. */
|
|
30
|
+
buildBody(req: CompletionRequest, model: string, stream: boolean): unknown;
|
|
31
|
+
/** Parse a buffered provider response into the normalized result. */
|
|
32
|
+
parseResponse(raw: unknown, model: string): CompletionResult;
|
|
33
|
+
/** Translate the provider's SSE messages into unified {@link StreamEvent}s. */
|
|
34
|
+
translateStream(messages: AsyncIterable<SseMessage>, model: string): AsyncIterable<StreamEvent>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build a {@link Provider} from an {@link AdapterSpec}.
|
|
38
|
+
*
|
|
39
|
+
* Use this for third-party adapters that want engine-lib's normalized
|
|
40
|
+
* completion/streaming shape plus Forge-backed HTTP, resilience, and telemetry.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createProvider(spec: AdapterSpec): Provider;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic provider adapter — the **Messages** API
|
|
3
|
+
* (`POST {baseUrl}/messages`).
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import type { Secret } from "@infinityi/forge/config";
|
|
8
|
+
import type { FetchLike, PipelineLike } from "@infinityi/forge/http/client";
|
|
9
|
+
import type { Provider } from "../types";
|
|
10
|
+
/** Construction options for the Anthropic adapter. */
|
|
11
|
+
export interface AnthropicOptions {
|
|
12
|
+
readonly apiKey: string | Secret<string>;
|
|
13
|
+
/** Model used when a request omits `model`. Default `"claude-opus-4-7"`. */
|
|
14
|
+
readonly model?: string;
|
|
15
|
+
/** Override the API base URL. Default `"https://api.anthropic.com/v1"`. */
|
|
16
|
+
readonly baseUrl?: string;
|
|
17
|
+
/** `anthropic-version` header. Default `"2023-06-01"`. */
|
|
18
|
+
readonly version?: string;
|
|
19
|
+
readonly timeoutMs?: number;
|
|
20
|
+
readonly resilience?: PipelineLike;
|
|
21
|
+
readonly fetch?: FetchLike;
|
|
22
|
+
readonly defaultHeaders?: Record<string, string>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create an Anthropic (Messages API) {@link Provider}.
|
|
26
|
+
*
|
|
27
|
+
* `apiKey` may be a raw string or Forge `Secret`. `model` becomes the
|
|
28
|
+
* provider's `defaultModel`; callers can still override `CompletionRequest.model`
|
|
29
|
+
* per request.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createAnthropic(opts: AnthropicOptions): Provider;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mapping between the Phase-1 message model and the Anthropic **Messages** API.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { CompletionRequest, CompletionResult, FinishReason } from "../types";
|
|
7
|
+
/** Build an Anthropic `POST /messages` request body. */
|
|
8
|
+
export declare function buildAnthropicBody(req: CompletionRequest, model: string, stream: boolean): unknown;
|
|
9
|
+
/** Map an Anthropic `stop_reason` to a normalized {@link FinishReason}. */
|
|
10
|
+
export declare function mapStopReason(stopReason: string | null | undefined, hadToolCalls: boolean): FinishReason;
|
|
11
|
+
/** Parse an Anthropic message response into a {@link CompletionResult}. */
|
|
12
|
+
export declare function parseAnthropicResponse(raw: unknown, model: string): CompletionResult;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate Anthropic Messages SSE events into the unified stream.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { SseMessage } from "../sse";
|
|
7
|
+
import type { StreamEvent } from "../stream";
|
|
8
|
+
/** Translate Anthropic SSE messages into {@link StreamEvent}s. */
|
|
9
|
+
export declare function translateAnthropicStream(messages: AsyncIterable<SseMessage>, model: string): AsyncIterable<StreamEvent>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Gemini provider adapter — the **generateContent** API
|
|
3
|
+
* (`POST {baseUrl}/models/{model}:generateContent`).
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import type { Secret } from "@infinityi/forge/config";
|
|
8
|
+
import type { FetchLike, PipelineLike } from "@infinityi/forge/http/client";
|
|
9
|
+
import type { Provider } from "../types";
|
|
10
|
+
/** Construction options for the Google Gemini adapter. */
|
|
11
|
+
export interface GoogleOptions {
|
|
12
|
+
readonly apiKey: string | Secret<string>;
|
|
13
|
+
/** Model used when a request omits `model`. Default `"gemini-2.5-pro"`. */
|
|
14
|
+
readonly model?: string;
|
|
15
|
+
/** Override the API base URL. Default `"https://generativelanguage.googleapis.com/v1beta"`. */
|
|
16
|
+
readonly baseUrl?: string;
|
|
17
|
+
readonly timeoutMs?: number;
|
|
18
|
+
readonly resilience?: PipelineLike;
|
|
19
|
+
readonly fetch?: FetchLike;
|
|
20
|
+
readonly defaultHeaders?: Record<string, string>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Create a Google Gemini (generateContent API) {@link Provider}.
|
|
24
|
+
*
|
|
25
|
+
* `apiKey` may be a raw string or Forge `Secret`. `model` becomes the
|
|
26
|
+
* provider's `defaultModel`; callers can still override `CompletionRequest.model`
|
|
27
|
+
* per request.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createGoogle(opts: GoogleOptions): Provider;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mapping between the Phase-1 message model and the Google Gemini
|
|
3
|
+
* **generateContent** API.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import type { CompletionRequest, CompletionResult, FinishReason } from "../types";
|
|
8
|
+
/** Build a Gemini generateContent request body. */
|
|
9
|
+
export declare function buildGoogleBody(req: CompletionRequest, _model: string, _stream: boolean): unknown;
|
|
10
|
+
/** Map a Gemini `finishReason` to a normalized {@link FinishReason}. */
|
|
11
|
+
export declare function mapGoogleFinish(reason: string | undefined, hadToolCalls: boolean): FinishReason;
|
|
12
|
+
/** Parse a Gemini generateContent response into a {@link CompletionResult}. */
|
|
13
|
+
export declare function parseGoogleResponse(raw: unknown, model: string): CompletionResult;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate Gemini `streamGenerateContent?alt=sse` chunks into the unified
|
|
3
|
+
* stream. Gemini delivers whole `functionCall`s per chunk (no incremental
|
|
4
|
+
* argument deltas), so each is emitted as a start/delta/end triple.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import type { SseMessage } from "../sse";
|
|
9
|
+
import type { StreamEvent } from "../stream";
|
|
10
|
+
/** Translate Gemini SSE chunks into {@link StreamEvent}s. */
|
|
11
|
+
export declare function translateGoogleStream(messages: AsyncIterable<SseMessage>, model: string): AsyncIterable<StreamEvent>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider HTTP transport, built on `forge/http/client` + `forge/resilience`.
|
|
3
|
+
*
|
|
4
|
+
* Adapters call {@link createProviderHttp} to get a `fetch` wrapper that is
|
|
5
|
+
* resilient (retry + timeout) and traced (via the {@link EngineContext}
|
|
6
|
+
* telemetry handle) by composition — exactly the forge pattern. Non-2xx
|
|
7
|
+
* responses are parsed into errors and re-thrown as {@link ProviderError} by
|
|
8
|
+
* {@link toProviderError}.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
import type { FetchLike, HttpClient, PipelineLike } from "@infinityi/forge/http/client";
|
|
13
|
+
import { ProviderError } from "../errors";
|
|
14
|
+
import type { EngineContext } from "../runtime/types";
|
|
15
|
+
/** Default per-request timeout for provider calls. */
|
|
16
|
+
export declare const DEFAULT_TIMEOUT_MS = 60000;
|
|
17
|
+
/** Construction options for a provider's HTTP transport. */
|
|
18
|
+
export interface ProviderHttpOptions {
|
|
19
|
+
/** Provider base URL (e.g. `https://api.openai.com/v1`). */
|
|
20
|
+
readonly baseUrl: string;
|
|
21
|
+
/** Headers merged into every request (auth + version), already resolved. */
|
|
22
|
+
readonly headers: Record<string, string>;
|
|
23
|
+
/** Per-request timeout. Default {@link DEFAULT_TIMEOUT_MS}. */
|
|
24
|
+
readonly timeoutMs?: number;
|
|
25
|
+
/** Override the default resilience pipeline. */
|
|
26
|
+
readonly resilience?: PipelineLike;
|
|
27
|
+
/** Inject a `fetch` implementation (tests / pre-wrapped fetch). */
|
|
28
|
+
readonly fetch?: FetchLike;
|
|
29
|
+
/** Allow request URLs to resolve to a different origin than `baseUrl`. */
|
|
30
|
+
readonly allowAbsoluteUrls?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The default provider resilience pipeline: up to 3 attempts with exponential
|
|
34
|
+
* backoff, each bounded by `timeoutMs`. Only transient failures are retried.
|
|
35
|
+
*/
|
|
36
|
+
export declare function defaultProviderResilience(timeoutMs: number): PipelineLike;
|
|
37
|
+
/**
|
|
38
|
+
* Build a forge {@link HttpClient} for a provider, wiring telemetry/logger from
|
|
39
|
+
* the {@link EngineContext} and a default resilience pipeline.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createProviderHttp(opts: ProviderHttpOptions, ctx?: EngineContext): HttpClient;
|
|
42
|
+
/** A streaming request the adapter wants to open. */
|
|
43
|
+
export interface SseRequest {
|
|
44
|
+
/** Request path, resolved against `baseUrl`. */
|
|
45
|
+
readonly path: string;
|
|
46
|
+
/** JSON request body (serialized here). */
|
|
47
|
+
readonly body: unknown;
|
|
48
|
+
/** Caller cancellation signal. */
|
|
49
|
+
readonly signal?: AbortSignal;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Open a streaming (SSE) provider request and return the raw body stream.
|
|
53
|
+
*
|
|
54
|
+
* The connection attempt is wrapped in the resilience pipeline (retry +
|
|
55
|
+
* timeout bound *time-to-headers*; once the response resolves the timeout is
|
|
56
|
+
* settled and never aborts the in-flight body). Non-2xx responses are mapped
|
|
57
|
+
* to {@link ProviderError}.
|
|
58
|
+
*/
|
|
59
|
+
export declare function openSseStream(provider: string, opts: ProviderHttpOptions, req: SseRequest, ctx?: EngineContext): Promise<ReadableStream<Uint8Array>>;
|
|
60
|
+
/** Wrap any thrown HTTP/transport error as a {@link ProviderError}. */
|
|
61
|
+
export declare function toProviderError(provider: string, error: unknown): ProviderError;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@infinityi/engine-lib/providers` — the unified LLM provider surface.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the normalized {@link Provider} contract, the streaming model, the
|
|
5
|
+
* four shipped adapters ({@link createOpenAI}, {@link createAnthropic},
|
|
6
|
+
* {@link createGoogle}, {@link createOpenAICompatible}), and advanced adapter
|
|
7
|
+
* plumbing.
|
|
8
|
+
*
|
|
9
|
+
* Most applications should import provider factories from the root package or
|
|
10
|
+
* from this subpath. `createProvider`, HTTP/SSE helpers, and stream
|
|
11
|
+
* accumulation utilities are for custom provider adapters and conformance
|
|
12
|
+
* tests; they are intentionally not re-exported from the root barrel.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
export type { CompletionRequest, CompletionResult, FinishReason, Provider, ProviderCapabilities, ProviderTool, ResponseSchema, ToolCall, ToolChoice, Usage, } from "./types";
|
|
17
|
+
export type { StreamEvent } from "./stream";
|
|
18
|
+
export { collectStream, StreamAccumulator } from "./stream";
|
|
19
|
+
export { createProviderHttp, defaultProviderResilience, openSseStream, toProviderError, DEFAULT_TIMEOUT_MS, } from "./http";
|
|
20
|
+
export type { ProviderHttpOptions, SseRequest } from "./http";
|
|
21
|
+
export { parseSse } from "./sse";
|
|
22
|
+
export type { SseMessage } from "./sse";
|
|
23
|
+
export { createProvider } from "./adapter";
|
|
24
|
+
export type { AdapterSpec } from "./adapter";
|
|
25
|
+
export { createOpenAI } from "./openai/index";
|
|
26
|
+
export type { OpenAIOptions } from "./openai/index";
|
|
27
|
+
export { createAnthropic } from "./anthropic/index";
|
|
28
|
+
export type { AnthropicOptions } from "./anthropic/index";
|
|
29
|
+
export { createGoogle } from "./google/index";
|
|
30
|
+
export type { GoogleOptions } from "./google/index";
|
|
31
|
+
export { createOpenAICompatible } from "./openai-compatible/index";
|
|
32
|
+
export type { OpenAICompatibleOptions } from "./openai-compatible/index";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_TIMEOUT_MS,
|
|
3
|
+
createAnthropic,
|
|
4
|
+
createGoogle,
|
|
5
|
+
createOpenAI,
|
|
6
|
+
createOpenAICompatible,
|
|
7
|
+
createProvider,
|
|
8
|
+
createProviderHttp,
|
|
9
|
+
defaultProviderResilience,
|
|
10
|
+
openSseStream,
|
|
11
|
+
parseSse,
|
|
12
|
+
toProviderError
|
|
13
|
+
} from "../index-64tt9696.js";
|
|
14
|
+
import"../index-bqg01r42.js";
|
|
15
|
+
import"../index-xsv43c5j.js";
|
|
16
|
+
import {
|
|
17
|
+
StreamAccumulator,
|
|
18
|
+
collectStream
|
|
19
|
+
} from "../index-zfgr4xx3.js";
|
|
20
|
+
import"../index-7690reng.js";
|
|
21
|
+
export {
|
|
22
|
+
toProviderError,
|
|
23
|
+
parseSse,
|
|
24
|
+
openSseStream,
|
|
25
|
+
defaultProviderResilience,
|
|
26
|
+
createProviderHttp,
|
|
27
|
+
createProvider,
|
|
28
|
+
createOpenAICompatible,
|
|
29
|
+
createOpenAI,
|
|
30
|
+
createGoogle,
|
|
31
|
+
createAnthropic,
|
|
32
|
+
collectStream,
|
|
33
|
+
StreamAccumulator,
|
|
34
|
+
DEFAULT_TIMEOUT_MS
|
|
35
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI provider adapter — the **Responses** API
|
|
3
|
+
* (`POST {baseUrl}/responses`).
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import type { Secret } from "@infinityi/forge/config";
|
|
8
|
+
import type { PipelineLike, FetchLike } from "@infinityi/forge/http/client";
|
|
9
|
+
import type { Provider } from "../types";
|
|
10
|
+
/** Construction options shared by the OpenAI adapter. */
|
|
11
|
+
export interface OpenAIOptions {
|
|
12
|
+
/** API key (raw string or a forge `Secret`). */
|
|
13
|
+
readonly apiKey: string | Secret<string>;
|
|
14
|
+
/** Model used when a request omits `model`. Default `"gpt-5"`. */
|
|
15
|
+
readonly model?: string;
|
|
16
|
+
/** Override the API base URL. Default `"https://api.openai.com/v1"`. */
|
|
17
|
+
readonly baseUrl?: string;
|
|
18
|
+
/** Per-request timeout (ms). */
|
|
19
|
+
readonly timeoutMs?: number;
|
|
20
|
+
/** Override the resilience pipeline. */
|
|
21
|
+
readonly resilience?: PipelineLike;
|
|
22
|
+
/** Inject a `fetch` implementation (tests). */
|
|
23
|
+
readonly fetch?: FetchLike;
|
|
24
|
+
/** Extra headers merged into every request. */
|
|
25
|
+
readonly defaultHeaders?: Record<string, string>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create an OpenAI (Responses API) {@link Provider}.
|
|
29
|
+
*
|
|
30
|
+
* `apiKey` may be a raw string or Forge `Secret`. `model` becomes the
|
|
31
|
+
* provider's `defaultModel`; callers can still override `CompletionRequest.model`
|
|
32
|
+
* per request.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createOpenAI(opts: OpenAIOptions): Provider;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mapping between the Phase-1 message model and the OpenAI **Responses** API.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { CompletionRequest, CompletionResult } from "../types";
|
|
7
|
+
/** Build a Responses `POST /responses` request body. */
|
|
8
|
+
export declare function buildOpenAIBody(req: CompletionRequest, model: string, stream: boolean): unknown;
|
|
9
|
+
/** Parse a Responses response object into a {@link CompletionResult}. */
|
|
10
|
+
export declare function parseOpenAIResponse(raw: unknown, model: string): CompletionResult;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate OpenAI Responses SSE events into the unified stream.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { SseMessage } from "../sse";
|
|
7
|
+
import type { StreamEvent } from "../stream";
|
|
8
|
+
/** Translate Responses SSE messages into {@link StreamEvent}s. */
|
|
9
|
+
export declare function translateOpenAIStream(messages: AsyncIterable<SseMessage>, model: string): AsyncIterable<StreamEvent>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic OpenAI-compatible provider adapter — the **Chat Completions** API
|
|
3
|
+
* (`POST {baseUrl}/chat/completions`). Targets vLLM, Together, Groq,
|
|
4
|
+
* OpenRouter, LM Studio, and anything else speaking that wire format.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import type { Secret } from "@infinityi/forge/config";
|
|
9
|
+
import type { FetchLike, PipelineLike } from "@infinityi/forge/http/client";
|
|
10
|
+
import type { Provider, ProviderCapabilities } from "../types";
|
|
11
|
+
/** Construction options for the OpenAI-compatible adapter. */
|
|
12
|
+
export interface OpenAICompatibleOptions {
|
|
13
|
+
/** Required base URL for the OpenAI-compatible server (e.g. `https://api.together.xyz/v1`). */
|
|
14
|
+
readonly baseUrl: string;
|
|
15
|
+
/** API key (raw string or a forge `Secret`). Optional for keyless local servers. */
|
|
16
|
+
readonly apiKey?: string | Secret<string>;
|
|
17
|
+
/** Adapter name, surfaced on the {@link Provider} and in errors. Default `"openai-compatible"`. */
|
|
18
|
+
readonly name?: string;
|
|
19
|
+
/** Model used when a request omits `model`. */
|
|
20
|
+
readonly model: string;
|
|
21
|
+
readonly timeoutMs?: number;
|
|
22
|
+
readonly resilience?: PipelineLike;
|
|
23
|
+
readonly fetch?: FetchLike;
|
|
24
|
+
readonly defaultHeaders?: Record<string, string>;
|
|
25
|
+
/** Override the declared capabilities (servers vary in tool/stream support). */
|
|
26
|
+
readonly capabilities?: Partial<ProviderCapabilities>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create a generic OpenAI-compatible (Chat Completions) {@link Provider}.
|
|
30
|
+
*
|
|
31
|
+
* `apiKey` may be omitted for local/keyless servers or supplied as a raw string
|
|
32
|
+
* or Forge `Secret`. `model` becomes the provider's `defaultModel`; callers can
|
|
33
|
+
* still override `CompletionRequest.model` per request. Use `capabilities` to
|
|
34
|
+
* honestly describe the target server when it lacks tool, stream, multimodal,
|
|
35
|
+
* parallel-tool, or structured-output support.
|
|
36
|
+
*/
|
|
37
|
+
export declare function createOpenAICompatible(opts: OpenAICompatibleOptions): Provider;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mapping between the Phase-1 message model and the OpenAI-compatible
|
|
3
|
+
* **Chat Completions** API (vLLM, Together, Groq, OpenRouter, …).
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import type { CompletionRequest, CompletionResult, FinishReason } from "../types";
|
|
8
|
+
/** Build a Chat Completions request body. */
|
|
9
|
+
export declare function buildChatBody(req: CompletionRequest, model: string, stream: boolean): unknown;
|
|
10
|
+
/** Map a Chat Completions `finish_reason` to a normalized {@link FinishReason}. */
|
|
11
|
+
export declare function mapChatFinish(reason: string | undefined, hadToolCalls: boolean): FinishReason;
|
|
12
|
+
/** Parse a Chat Completions response into a {@link CompletionResult}. */
|
|
13
|
+
export declare function parseChatResponse(raw: unknown, model: string): CompletionResult;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate OpenAI-compatible Chat Completions SSE chunks into the unified
|
|
3
|
+
* stream. Tool-call arguments arrive incrementally and are keyed by the
|
|
4
|
+
* provider's `tool_calls[].index`.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import type { SseMessage } from "../sse";
|
|
9
|
+
import type { StreamEvent } from "../stream";
|
|
10
|
+
/** Translate Chat Completions SSE chunks into {@link StreamEvent}s. */
|
|
11
|
+
export declare function translateChatStream(messages: AsyncIterable<SseMessage>, model: string): AsyncIterable<StreamEvent>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Small mapping helpers shared by the provider adapters.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { ImagePart, Message, TextPart, ToolCallPart, ToolResultPart } from "../messages/types";
|
|
7
|
+
import type { FinishReason } from "./types";
|
|
8
|
+
/**
|
|
9
|
+
* Resolve an {@link ImagePart} to a value usable in an `image_url`-style field:
|
|
10
|
+
* an `http(s)` URL is passed through, raw base64 is wrapped as a `data:` URI.
|
|
11
|
+
*/
|
|
12
|
+
export declare function imageDataUrl(part: ImagePart): string;
|
|
13
|
+
/** Concatenated text of every `system` message, or `undefined` if none. */
|
|
14
|
+
export declare function systemText(messages: readonly Message[]): string | undefined;
|
|
15
|
+
/** Messages excluding `system` (which providers carry out-of-band). */
|
|
16
|
+
export declare function withoutSystem(messages: readonly Message[]): Message[];
|
|
17
|
+
/** Join the text of a tool-result's content parts. */
|
|
18
|
+
export declare function toolResultText(part: ToolResultPart): string;
|
|
19
|
+
/** Type guards for content parts. */
|
|
20
|
+
export declare const isText: (p: {
|
|
21
|
+
type: string;
|
|
22
|
+
}) => p is TextPart;
|
|
23
|
+
export declare const isToolCall: (p: {
|
|
24
|
+
type: string;
|
|
25
|
+
}) => p is ToolCallPart;
|
|
26
|
+
export declare const isToolResult: (p: {
|
|
27
|
+
type: string;
|
|
28
|
+
}) => p is ToolResultPart;
|
|
29
|
+
/** Parse a JSON arguments string, tolerating empty/invalid input. */
|
|
30
|
+
export declare function parseJsonArguments(text: string): unknown;
|
|
31
|
+
/** Serialize tool-call arguments to the JSON string providers expect. */
|
|
32
|
+
export declare function stringifyArguments(value: unknown): string;
|
|
33
|
+
/** A `finish`-style normalization shared where vendors use the same buckets. */
|
|
34
|
+
export declare function defaultFinish(hadToolCalls: boolean, base: FinishReason): FinishReason;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal Server-Sent Events reader for provider streaming endpoints.
|
|
3
|
+
*
|
|
4
|
+
* Decodes a `ReadableStream<Uint8Array>` (the `res.raw.body` of a streaming
|
|
5
|
+
* provider response) into `{ event?, data }` records, handling multi-line
|
|
6
|
+
* `data:` fields, `event:` names, comment lines, and CRLF/LF newlines per the
|
|
7
|
+
* SSE spec. Adapters parse each record's `data` as the provider's JSON event.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
/** One dispatched SSE message. */
|
|
12
|
+
export interface SseMessage {
|
|
13
|
+
/** The `event:` name, if the stream set one. */
|
|
14
|
+
readonly event?: string;
|
|
15
|
+
/** The concatenated `data:` payload (lines joined with `\n`). */
|
|
16
|
+
readonly data: string;
|
|
17
|
+
}
|
|
18
|
+
/** Decode an SSE byte stream into dispatched {@link SseMessage}s. */
|
|
19
|
+
export declare function parseSse(stream: ReadableStream<Uint8Array>, signal?: AbortSignal): AsyncGenerator<SseMessage>;
|