@nirmos/sdk 0.1.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/README.md +62 -0
- package/dist/cjs/client.js +61 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/core/errors.js +143 -0
- package/dist/cjs/core/errors.js.map +1 -0
- package/dist/cjs/core/metadata.js +104 -0
- package/dist/cjs/core/metadata.js.map +1 -0
- package/dist/cjs/core/transport.js +276 -0
- package/dist/cjs/core/transport.js.map +1 -0
- package/dist/cjs/core/types.js +3 -0
- package/dist/cjs/core/types.js.map +1 -0
- package/dist/cjs/gateway/chat-stream.js +262 -0
- package/dist/cjs/gateway/chat-stream.js.map +1 -0
- package/dist/cjs/gateway/chat.js +102 -0
- package/dist/cjs/gateway/chat.js.map +1 -0
- package/dist/cjs/gateway/embeddings.js +33 -0
- package/dist/cjs/gateway/embeddings.js.map +1 -0
- package/dist/cjs/gateway/gateway.js +18 -0
- package/dist/cjs/gateway/gateway.js.map +1 -0
- package/dist/cjs/gateway/images.js +36 -0
- package/dist/cjs/gateway/images.js.map +1 -0
- package/dist/cjs/gateway/mappers.js +184 -0
- package/dist/cjs/gateway/mappers.js.map +1 -0
- package/dist/cjs/gateway/types.js +3 -0
- package/dist/cjs/gateway/types.js.map +1 -0
- package/dist/cjs/index.js +25 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/prompts/cache.js +48 -0
- package/dist/cjs/prompts/cache.js.map +1 -0
- package/dist/cjs/prompts/mappers.js +242 -0
- package/dist/cjs/prompts/mappers.js.map +1 -0
- package/dist/cjs/prompts/prompts.js +121 -0
- package/dist/cjs/prompts/prompts.js.map +1 -0
- package/dist/cjs/prompts/render.js +86 -0
- package/dist/cjs/prompts/render.js.map +1 -0
- package/dist/cjs/prompts/types.js +3 -0
- package/dist/cjs/prompts/types.js.map +1 -0
- package/dist/cjs/prompts/versions.js +51 -0
- package/dist/cjs/prompts/versions.js.map +1 -0
- package/dist/esm/client.d.ts +28 -0
- package/dist/esm/client.d.ts.map +1 -0
- package/dist/esm/client.js +58 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/core/errors.d.ts +72 -0
- package/dist/esm/core/errors.d.ts.map +1 -0
- package/dist/esm/core/errors.js +125 -0
- package/dist/esm/core/errors.js.map +1 -0
- package/dist/esm/core/metadata.d.ts +11 -0
- package/dist/esm/core/metadata.d.ts.map +1 -0
- package/dist/esm/core/metadata.js +95 -0
- package/dist/esm/core/metadata.js.map +1 -0
- package/dist/esm/core/transport.d.ts +28 -0
- package/dist/esm/core/transport.d.ts.map +1 -0
- package/dist/esm/core/transport.js +272 -0
- package/dist/esm/core/transport.js.map +1 -0
- package/dist/esm/core/types.d.ts +43 -0
- package/dist/esm/core/types.d.ts.map +1 -0
- package/dist/esm/core/types.js +2 -0
- package/dist/esm/core/types.js.map +1 -0
- package/dist/esm/gateway/chat-stream.d.ts +9 -0
- package/dist/esm/gateway/chat-stream.d.ts.map +1 -0
- package/dist/esm/gateway/chat-stream.js +258 -0
- package/dist/esm/gateway/chat-stream.js.map +1 -0
- package/dist/esm/gateway/chat.d.ts +12 -0
- package/dist/esm/gateway/chat.d.ts.map +1 -0
- package/dist/esm/gateway/chat.js +98 -0
- package/dist/esm/gateway/chat.js.map +1 -0
- package/dist/esm/gateway/embeddings.d.ts +9 -0
- package/dist/esm/gateway/embeddings.d.ts.map +1 -0
- package/dist/esm/gateway/embeddings.js +29 -0
- package/dist/esm/gateway/embeddings.js.map +1 -0
- package/dist/esm/gateway/gateway.d.ts +12 -0
- package/dist/esm/gateway/gateway.d.ts.map +1 -0
- package/dist/esm/gateway/gateway.js +14 -0
- package/dist/esm/gateway/gateway.js.map +1 -0
- package/dist/esm/gateway/images.d.ts +9 -0
- package/dist/esm/gateway/images.d.ts.map +1 -0
- package/dist/esm/gateway/images.js +32 -0
- package/dist/esm/gateway/images.js.map +1 -0
- package/dist/esm/gateway/mappers.d.ts +11 -0
- package/dist/esm/gateway/mappers.d.ts.map +1 -0
- package/dist/esm/gateway/mappers.js +174 -0
- package/dist/esm/gateway/mappers.js.map +1 -0
- package/dist/esm/gateway/types.d.ts +168 -0
- package/dist/esm/gateway/types.d.ts.map +1 -0
- package/dist/esm/gateway/types.js +2 -0
- package/dist/esm/gateway/types.js.map +1 -0
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/prompts/cache.d.ts +13 -0
- package/dist/esm/prompts/cache.d.ts.map +1 -0
- package/dist/esm/prompts/cache.js +44 -0
- package/dist/esm/prompts/cache.js.map +1 -0
- package/dist/esm/prompts/mappers.d.ts +8 -0
- package/dist/esm/prompts/mappers.d.ts.map +1 -0
- package/dist/esm/prompts/mappers.js +235 -0
- package/dist/esm/prompts/mappers.js.map +1 -0
- package/dist/esm/prompts/prompts.d.ts +17 -0
- package/dist/esm/prompts/prompts.d.ts.map +1 -0
- package/dist/esm/prompts/prompts.js +117 -0
- package/dist/esm/prompts/prompts.js.map +1 -0
- package/dist/esm/prompts/render.d.ts +3 -0
- package/dist/esm/prompts/render.d.ts.map +1 -0
- package/dist/esm/prompts/render.js +83 -0
- package/dist/esm/prompts/render.js.map +1 -0
- package/dist/esm/prompts/types.d.ts +119 -0
- package/dist/esm/prompts/types.d.ts.map +1 -0
- package/dist/esm/prompts/types.js +2 -0
- package/dist/esm/prompts/types.js.map +1 -0
- package/dist/esm/prompts/versions.d.ts +12 -0
- package/dist/esm/prompts/versions.d.ts.map +1 -0
- package/dist/esm/prompts/versions.js +47 -0
- package/dist/esm/prompts/versions.js.map +1 -0
- package/package.json +50 -0
- package/src/client.ts +89 -0
- package/src/core/errors.ts +160 -0
- package/src/core/metadata.ts +141 -0
- package/src/core/transport.ts +331 -0
- package/src/core/types.ts +51 -0
- package/src/gateway/chat-stream.ts +307 -0
- package/src/gateway/chat.ts +134 -0
- package/src/gateway/embeddings.ts +44 -0
- package/src/gateway/gateway.ts +17 -0
- package/src/gateway/images.ts +41 -0
- package/src/gateway/mappers.ts +234 -0
- package/src/gateway/types.ts +206 -0
- package/src/index.ts +83 -0
- package/src/prompts/cache.ts +50 -0
- package/src/prompts/mappers.ts +318 -0
- package/src/prompts/prompts.ts +188 -0
- package/src/prompts/render.ts +117 -0
- package/src/prompts/types.ts +148 -0
- package/src/prompts/versions.ts +80 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { ValidationError } from "../core/errors.js";
|
|
2
|
+
import type { RequestOptions } from "../core/types.js";
|
|
3
|
+
import type { HttpTransport } from "../core/transport.js";
|
|
4
|
+
import type { Prompts } from "../prompts/prompts.js";
|
|
5
|
+
import { ChatStream } from "./chat-stream.js";
|
|
6
|
+
import { normalizeChatCompletion, toWireMessage } from "./mappers.js";
|
|
7
|
+
import type {
|
|
8
|
+
ChatCompletion,
|
|
9
|
+
ChatCreateParams,
|
|
10
|
+
ChatMessage,
|
|
11
|
+
ResponseFormat,
|
|
12
|
+
RoutingStrategy,
|
|
13
|
+
} from "./types.js";
|
|
14
|
+
|
|
15
|
+
export class Chat {
|
|
16
|
+
readonly #transport: HttpTransport;
|
|
17
|
+
readonly #prompts: Prompts;
|
|
18
|
+
|
|
19
|
+
constructor(transport: HttpTransport, prompts: Prompts) {
|
|
20
|
+
this.#transport = transport;
|
|
21
|
+
this.#prompts = prompts;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async create(
|
|
25
|
+
params: ChatCreateParams,
|
|
26
|
+
options?: RequestOptions,
|
|
27
|
+
): Promise<ChatCompletion> {
|
|
28
|
+
const body = await this.#body(params, false);
|
|
29
|
+
const { data, response } = await this.#transport.request<unknown>({
|
|
30
|
+
method: "POST",
|
|
31
|
+
path: "/v1/chat/completions",
|
|
32
|
+
body,
|
|
33
|
+
options,
|
|
34
|
+
});
|
|
35
|
+
return normalizeChatCompletion(data, response);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async stream(
|
|
39
|
+
params: ChatCreateParams,
|
|
40
|
+
options?: RequestOptions,
|
|
41
|
+
): Promise<ChatStream> {
|
|
42
|
+
const body = await this.#body(params, true);
|
|
43
|
+
const response = await this.#transport.fetch({
|
|
44
|
+
method: "POST",
|
|
45
|
+
path: "/v1/chat/completions",
|
|
46
|
+
body,
|
|
47
|
+
options,
|
|
48
|
+
});
|
|
49
|
+
return new ChatStream(await this.#transport.ensureSuccess(response));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async #body(
|
|
53
|
+
params: ChatCreateParams,
|
|
54
|
+
stream: boolean,
|
|
55
|
+
): Promise<Record<string, unknown>> {
|
|
56
|
+
const messages = await this.#messages(params);
|
|
57
|
+
if (!params.model.trim()) {
|
|
58
|
+
throw localValidation("model", "Model is required.");
|
|
59
|
+
}
|
|
60
|
+
if (messages.length === 0) {
|
|
61
|
+
throw localValidation(
|
|
62
|
+
"messages",
|
|
63
|
+
"Provide messages, a managed prompt, or both.",
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
model: params.model,
|
|
69
|
+
messages: messages.map(toWireMessage),
|
|
70
|
+
stream,
|
|
71
|
+
temperature: params.temperature,
|
|
72
|
+
top_p: params.topP,
|
|
73
|
+
max_tokens: params.maxOutputTokens,
|
|
74
|
+
stop: params.stop,
|
|
75
|
+
tools: params.tools,
|
|
76
|
+
tool_choice: params.toolChoice,
|
|
77
|
+
response_format: toWireResponseFormat(params.responseFormat),
|
|
78
|
+
seed: params.seed,
|
|
79
|
+
user: params.user,
|
|
80
|
+
provider: params.provider,
|
|
81
|
+
fallback_models: params.fallbackModels,
|
|
82
|
+
routing_strategy: toWireRoutingStrategy(params.routingStrategy),
|
|
83
|
+
metadata: params.metadata,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async #messages(params: ChatCreateParams): Promise<readonly ChatMessage[]> {
|
|
88
|
+
const requestMessages = params.messages ?? [];
|
|
89
|
+
if (!params.prompt) return requestMessages;
|
|
90
|
+
|
|
91
|
+
const rendered = await this.#prompts.render(
|
|
92
|
+
{
|
|
93
|
+
id: params.prompt.id,
|
|
94
|
+
version: params.prompt.version,
|
|
95
|
+
cache: params.prompt.cache,
|
|
96
|
+
},
|
|
97
|
+
params.prompt.variables,
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
return params.prompt.position === "after"
|
|
101
|
+
? [...requestMessages, ...rendered.messages]
|
|
102
|
+
: [...rendered.messages, ...requestMessages];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function toWireResponseFormat(
|
|
107
|
+
format: ResponseFormat | undefined,
|
|
108
|
+
): Record<string, unknown> | undefined {
|
|
109
|
+
if (!format) return undefined;
|
|
110
|
+
if (format.type === "text") return { type: "text" };
|
|
111
|
+
if (format.type === "jsonObject") return { type: "json_object" };
|
|
112
|
+
return {
|
|
113
|
+
type: "json_schema",
|
|
114
|
+
json_schema: {
|
|
115
|
+
name: format.name,
|
|
116
|
+
schema: format.schema,
|
|
117
|
+
strict: format.strict,
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function toWireRoutingStrategy(
|
|
123
|
+
strategy: RoutingStrategy | undefined,
|
|
124
|
+
): string | undefined {
|
|
125
|
+
return strategy === "highestQuality" ? "highest_quality" : strategy;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function localValidation(field: string, message: string): ValidationError {
|
|
129
|
+
return new ValidationError(message, {
|
|
130
|
+
status: 400,
|
|
131
|
+
code: "SDK_VALIDATION_ERROR",
|
|
132
|
+
details: { field },
|
|
133
|
+
});
|
|
134
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { HttpTransport } from "../core/transport.js";
|
|
2
|
+
import type { RequestOptions } from "../core/types.js";
|
|
3
|
+
import { normalizeEmbeddingResponse } from "./mappers.js";
|
|
4
|
+
import type {
|
|
5
|
+
EmbeddingCreateParams,
|
|
6
|
+
EmbeddingResponse,
|
|
7
|
+
RoutingStrategy,
|
|
8
|
+
} from "./types.js";
|
|
9
|
+
|
|
10
|
+
export class Embeddings {
|
|
11
|
+
readonly #transport: HttpTransport;
|
|
12
|
+
|
|
13
|
+
constructor(transport: HttpTransport) {
|
|
14
|
+
this.#transport = transport;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async create(
|
|
18
|
+
params: EmbeddingCreateParams,
|
|
19
|
+
options?: RequestOptions,
|
|
20
|
+
): Promise<EmbeddingResponse> {
|
|
21
|
+
const { data, response } = await this.#transport.request<unknown>({
|
|
22
|
+
method: "POST",
|
|
23
|
+
path: "/v1/embeddings",
|
|
24
|
+
body: {
|
|
25
|
+
model: params.model,
|
|
26
|
+
input: params.input,
|
|
27
|
+
dimensions: params.dimensions,
|
|
28
|
+
encoding_format: params.encoding,
|
|
29
|
+
user: params.user,
|
|
30
|
+
provider: params.provider,
|
|
31
|
+
fallback_models: params.fallbackModels,
|
|
32
|
+
routing_strategy: toWireRoutingStrategy(params.routingStrategy),
|
|
33
|
+
},
|
|
34
|
+
options,
|
|
35
|
+
});
|
|
36
|
+
return normalizeEmbeddingResponse(data, response);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function toWireRoutingStrategy(
|
|
41
|
+
strategy: RoutingStrategy | undefined,
|
|
42
|
+
): string | undefined {
|
|
43
|
+
return strategy === "highestQuality" ? "highest_quality" : strategy;
|
|
44
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { HttpTransport } from "../core/transport.js";
|
|
2
|
+
import type { Prompts } from "../prompts/prompts.js";
|
|
3
|
+
import { Chat } from "./chat.js";
|
|
4
|
+
import { Embeddings } from "./embeddings.js";
|
|
5
|
+
import { Images } from "./images.js";
|
|
6
|
+
|
|
7
|
+
export class Gateway {
|
|
8
|
+
readonly chat: Chat;
|
|
9
|
+
readonly embeddings: Embeddings;
|
|
10
|
+
readonly images: Images;
|
|
11
|
+
|
|
12
|
+
constructor(transport: HttpTransport, prompts: Prompts) {
|
|
13
|
+
this.chat = new Chat(transport, prompts);
|
|
14
|
+
this.embeddings = new Embeddings(transport);
|
|
15
|
+
this.images = new Images(transport);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { HttpTransport } from "../core/transport.js";
|
|
2
|
+
import type { RequestOptions } from "../core/types.js";
|
|
3
|
+
import { normalizeImageGeneration } from "./mappers.js";
|
|
4
|
+
import type { ImageGenerateParams, ImageGeneration } from "./types.js";
|
|
5
|
+
|
|
6
|
+
export class Images {
|
|
7
|
+
readonly #transport: HttpTransport;
|
|
8
|
+
|
|
9
|
+
constructor(transport: HttpTransport) {
|
|
10
|
+
this.#transport = transport;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async generate(
|
|
14
|
+
params: ImageGenerateParams,
|
|
15
|
+
options?: RequestOptions,
|
|
16
|
+
): Promise<ImageGeneration> {
|
|
17
|
+
const { data, response } = await this.#transport.request<unknown>({
|
|
18
|
+
method: "POST",
|
|
19
|
+
path: "/v1/images/generations",
|
|
20
|
+
body: {
|
|
21
|
+
model: params.model,
|
|
22
|
+
prompt: params.prompt,
|
|
23
|
+
n: params.count,
|
|
24
|
+
size: params.size,
|
|
25
|
+
quality: params.quality,
|
|
26
|
+
style: params.style,
|
|
27
|
+
output_format: params.format,
|
|
28
|
+
response_format:
|
|
29
|
+
params.responseFormat === "base64"
|
|
30
|
+
? "b64_json"
|
|
31
|
+
: params.responseFormat,
|
|
32
|
+
background: params.background,
|
|
33
|
+
user: params.user,
|
|
34
|
+
provider: params.provider,
|
|
35
|
+
metadata: params.metadata,
|
|
36
|
+
},
|
|
37
|
+
options,
|
|
38
|
+
});
|
|
39
|
+
return normalizeImageGeneration(data, response);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import {
|
|
2
|
+
asUnknownRecord,
|
|
3
|
+
compactMetadata,
|
|
4
|
+
extractMetadata,
|
|
5
|
+
readArray,
|
|
6
|
+
readNumber,
|
|
7
|
+
readString,
|
|
8
|
+
} from "../core/metadata.js";
|
|
9
|
+
import type { Usage } from "../core/types.js";
|
|
10
|
+
import type {
|
|
11
|
+
ChatChoice,
|
|
12
|
+
ChatCompletion,
|
|
13
|
+
ChatContentPart,
|
|
14
|
+
ChatMessage,
|
|
15
|
+
EmbeddingResponse,
|
|
16
|
+
FunctionToolCall,
|
|
17
|
+
ImageGeneration,
|
|
18
|
+
} from "./types.js";
|
|
19
|
+
|
|
20
|
+
export function toWireMessage(message: ChatMessage): Record<string, unknown> {
|
|
21
|
+
return {
|
|
22
|
+
role: message.role,
|
|
23
|
+
content:
|
|
24
|
+
typeof message.content === "string"
|
|
25
|
+
? message.content
|
|
26
|
+
: message.content.map((part) => {
|
|
27
|
+
if (part.type === "text") return { type: "text", text: part.text };
|
|
28
|
+
if (part.type === "image") {
|
|
29
|
+
return {
|
|
30
|
+
type: "image_url",
|
|
31
|
+
image_url: { url: part.url, detail: part.detail },
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
type: "audio",
|
|
36
|
+
audio: { data: part.data, format: part.format },
|
|
37
|
+
};
|
|
38
|
+
}),
|
|
39
|
+
...(message.name ? { name: message.name } : {}),
|
|
40
|
+
...(message.toolCallId ? { tool_call_id: message.toolCallId } : {}),
|
|
41
|
+
...(message.toolCalls && message.toolCalls.length > 0
|
|
42
|
+
? { tool_calls: message.toolCalls }
|
|
43
|
+
: {}),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function normalizeUsage(value: unknown): Usage {
|
|
48
|
+
const usage = asUnknownRecord(value);
|
|
49
|
+
const inputTokens =
|
|
50
|
+
readNumber(
|
|
51
|
+
usage,
|
|
52
|
+
"input_tokens",
|
|
53
|
+
"inputTokens",
|
|
54
|
+
"prompt_tokens",
|
|
55
|
+
"promptTokens",
|
|
56
|
+
) ?? 0;
|
|
57
|
+
const outputTokens =
|
|
58
|
+
readNumber(
|
|
59
|
+
usage,
|
|
60
|
+
"output_tokens",
|
|
61
|
+
"outputTokens",
|
|
62
|
+
"completion_tokens",
|
|
63
|
+
"completionTokens",
|
|
64
|
+
) ?? 0;
|
|
65
|
+
return {
|
|
66
|
+
inputTokens,
|
|
67
|
+
outputTokens,
|
|
68
|
+
totalTokens:
|
|
69
|
+
readNumber(usage, "total_tokens", "totalTokens") ??
|
|
70
|
+
inputTokens + outputTokens,
|
|
71
|
+
cachedTokens: readNumber(usage, "cached_tokens", "cachedTokens"),
|
|
72
|
+
reasoningTokens: readNumber(usage, "reasoning_tokens", "reasoningTokens"),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function normalizeChatCompletion(
|
|
77
|
+
payload: unknown,
|
|
78
|
+
response: Response,
|
|
79
|
+
): ChatCompletion {
|
|
80
|
+
const root = asUnknownRecord(payload);
|
|
81
|
+
const choices = readArray(root, "choices").map(normalizeChoice);
|
|
82
|
+
const metadata = compactMetadata(extractMetadata(response, payload));
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
id: readString(root, "id") ?? metadata.requestId ?? "",
|
|
86
|
+
createdAt: readNumber(root, "created", "created_at", "createdAt") ?? 0,
|
|
87
|
+
model: readString(root, "model") ?? metadata.model ?? "",
|
|
88
|
+
choices,
|
|
89
|
+
outputText: choices
|
|
90
|
+
.map((choice) =>
|
|
91
|
+
typeof choice.message.content === "string"
|
|
92
|
+
? choice.message.content
|
|
93
|
+
: choice.message.content
|
|
94
|
+
.filter((part) => part.type === "text")
|
|
95
|
+
.map((part) => (part.type === "text" ? part.text : ""))
|
|
96
|
+
.join(""),
|
|
97
|
+
)
|
|
98
|
+
.join(""),
|
|
99
|
+
usage: normalizeUsage(root.usage),
|
|
100
|
+
metadata,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function normalizeEmbeddingResponse(
|
|
105
|
+
payload: unknown,
|
|
106
|
+
response: Response,
|
|
107
|
+
): EmbeddingResponse {
|
|
108
|
+
const root = asUnknownRecord(payload);
|
|
109
|
+
const metadata = compactMetadata(extractMetadata(response, payload));
|
|
110
|
+
return {
|
|
111
|
+
model: readString(root, "model") ?? metadata.model ?? "",
|
|
112
|
+
embeddings: readArray(root, "data", "embeddings").map((entry, position) => {
|
|
113
|
+
const item = asUnknownRecord(entry);
|
|
114
|
+
const index = readNumber(item, "index") ?? position;
|
|
115
|
+
const embedding = item.embedding ?? item.values ?? item.base64;
|
|
116
|
+
if (typeof embedding === "string") return { index, base64: embedding };
|
|
117
|
+
return {
|
|
118
|
+
index,
|
|
119
|
+
values: Array.isArray(embedding)
|
|
120
|
+
? embedding.filter(
|
|
121
|
+
(value): value is number => typeof value === "number",
|
|
122
|
+
)
|
|
123
|
+
: [],
|
|
124
|
+
};
|
|
125
|
+
}),
|
|
126
|
+
usage: normalizeUsage(root.usage),
|
|
127
|
+
metadata,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function normalizeImageGeneration(
|
|
132
|
+
payload: unknown,
|
|
133
|
+
response: Response,
|
|
134
|
+
): ImageGeneration {
|
|
135
|
+
const root = asUnknownRecord(payload);
|
|
136
|
+
const metadata = compactMetadata(extractMetadata(response, payload));
|
|
137
|
+
const usage =
|
|
138
|
+
root.usage === undefined ? undefined : normalizeUsage(root.usage);
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
id: readString(root, "id"),
|
|
142
|
+
createdAt: readNumber(root, "created", "created_at", "createdAt") ?? 0,
|
|
143
|
+
model: readString(root, "model") ?? metadata.model ?? "",
|
|
144
|
+
images: readArray(root, "data", "images").map((entry) => {
|
|
145
|
+
const image = asUnknownRecord(entry);
|
|
146
|
+
return {
|
|
147
|
+
url: readString(image, "url"),
|
|
148
|
+
base64: readString(image, "b64_json", "base64"),
|
|
149
|
+
revisedPrompt: readString(image, "revised_prompt", "revisedPrompt"),
|
|
150
|
+
mediaType: readString(image, "media_type", "mediaType"),
|
|
151
|
+
width: readNumber(image, "width"),
|
|
152
|
+
height: readNumber(image, "height"),
|
|
153
|
+
};
|
|
154
|
+
}),
|
|
155
|
+
usage,
|
|
156
|
+
metadata,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function normalizeChoice(value: unknown): ChatChoice {
|
|
161
|
+
const choice = asUnknownRecord(value);
|
|
162
|
+
const message = asUnknownRecord(choice.message);
|
|
163
|
+
return {
|
|
164
|
+
index: readNumber(choice, "index") ?? 0,
|
|
165
|
+
message: normalizeMessage(message),
|
|
166
|
+
finishReason: normalizeFinishReason(
|
|
167
|
+
readString(choice, "finish_reason", "finishReason"),
|
|
168
|
+
),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function normalizeMessage(value: unknown): ChatMessage {
|
|
173
|
+
const message = asUnknownRecord(value);
|
|
174
|
+
const content = message.content;
|
|
175
|
+
const toolCalls = readArray(message, "tool_calls", "toolCalls").map(
|
|
176
|
+
normalizeToolCall,
|
|
177
|
+
);
|
|
178
|
+
return {
|
|
179
|
+
role: (readString(message, "role") ?? "assistant") as ChatMessage["role"],
|
|
180
|
+
content: Array.isArray(content)
|
|
181
|
+
? content.map(normalizeContentPart)
|
|
182
|
+
: typeof content === "string"
|
|
183
|
+
? content
|
|
184
|
+
: "",
|
|
185
|
+
name: readString(message, "name"),
|
|
186
|
+
toolCallId: readString(message, "tool_call_id", "toolCallId"),
|
|
187
|
+
toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function normalizeToolCall(value: unknown): FunctionToolCall {
|
|
192
|
+
const call = asUnknownRecord(value);
|
|
193
|
+
const fn = asUnknownRecord(call.function);
|
|
194
|
+
return {
|
|
195
|
+
id: readString(call, "id") ?? "",
|
|
196
|
+
type: "function",
|
|
197
|
+
function: {
|
|
198
|
+
name: readString(fn, "name") ?? "",
|
|
199
|
+
arguments: readString(fn, "arguments") ?? "",
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function normalizeContentPart(value: unknown): ChatContentPart {
|
|
205
|
+
const part = asUnknownRecord(value);
|
|
206
|
+
const type = readString(part, "type");
|
|
207
|
+
if (type === "image" || type === "image_url") {
|
|
208
|
+
const image = asUnknownRecord(part.image_url);
|
|
209
|
+
return {
|
|
210
|
+
type: "image",
|
|
211
|
+
url: readString(part, "url") ?? readString(image, "url") ?? "",
|
|
212
|
+
detail: (readString(part, "detail") ?? readString(image, "detail")) as
|
|
213
|
+
"auto" | "low" | "high" | undefined,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
if (type === "audio" || type === "input_audio") {
|
|
217
|
+
const audio = asUnknownRecord(part.audio ?? part.input_audio);
|
|
218
|
+
return {
|
|
219
|
+
type: "audio",
|
|
220
|
+
data: readString(part, "data") ?? readString(audio, "data") ?? "",
|
|
221
|
+
format: readString(part, "format") ?? readString(audio, "format") ?? "",
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
return { type: "text", text: readString(part, "text") ?? "" };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function normalizeFinishReason(
|
|
228
|
+
value: string | undefined,
|
|
229
|
+
): ChatChoice["finishReason"] {
|
|
230
|
+
if (!value) return null;
|
|
231
|
+
if (value === "tool_calls") return "toolCalls";
|
|
232
|
+
if (value === "content_filter") return "contentFilter";
|
|
233
|
+
return value;
|
|
234
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ExtensibleString,
|
|
3
|
+
JsonValue,
|
|
4
|
+
RequestMetadata,
|
|
5
|
+
Usage,
|
|
6
|
+
} from "../core/types.js";
|
|
7
|
+
import type {
|
|
8
|
+
PromptCacheMode,
|
|
9
|
+
PromptIdentifier,
|
|
10
|
+
PromptVariableValues,
|
|
11
|
+
} from "../prompts/types.js";
|
|
12
|
+
|
|
13
|
+
export type ChatRole = "system" | "developer" | "user" | "assistant" | "tool";
|
|
14
|
+
|
|
15
|
+
export interface TextContentPart {
|
|
16
|
+
type: "text";
|
|
17
|
+
text: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ImageContentPart {
|
|
21
|
+
type: "image";
|
|
22
|
+
url: string;
|
|
23
|
+
detail?: "auto" | "low" | "high";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface AudioContentPart {
|
|
27
|
+
type: "audio";
|
|
28
|
+
data: string;
|
|
29
|
+
format: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type ChatContentPart =
|
|
33
|
+
TextContentPart | ImageContentPart | AudioContentPart;
|
|
34
|
+
|
|
35
|
+
export interface FunctionToolCall {
|
|
36
|
+
id: string;
|
|
37
|
+
type: "function";
|
|
38
|
+
function: {
|
|
39
|
+
name: string;
|
|
40
|
+
arguments: string;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface ChatMessage {
|
|
45
|
+
role: ChatRole;
|
|
46
|
+
content: string | readonly ChatContentPart[];
|
|
47
|
+
name?: string;
|
|
48
|
+
toolCallId?: string;
|
|
49
|
+
toolCalls?: readonly FunctionToolCall[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface FunctionTool {
|
|
53
|
+
type: "function";
|
|
54
|
+
function: {
|
|
55
|
+
name: string;
|
|
56
|
+
description?: string;
|
|
57
|
+
parameters?: Readonly<Record<string, unknown>>;
|
|
58
|
+
strict?: boolean;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type ToolChoice =
|
|
63
|
+
| "auto"
|
|
64
|
+
| "none"
|
|
65
|
+
| "required"
|
|
66
|
+
| {
|
|
67
|
+
type: "function";
|
|
68
|
+
function: { name: string };
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export type ResponseFormat =
|
|
72
|
+
| { type: "text" }
|
|
73
|
+
| { type: "jsonObject" }
|
|
74
|
+
| {
|
|
75
|
+
type: "jsonSchema";
|
|
76
|
+
name: string;
|
|
77
|
+
schema: Readonly<Record<string, unknown>>;
|
|
78
|
+
strict?: boolean;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export type RoutingStrategy = ExtensibleString<
|
|
82
|
+
"auto" | "cheapest" | "fastest" | "highestQuality" | "reasoning" | "specific"
|
|
83
|
+
>;
|
|
84
|
+
|
|
85
|
+
export interface PromptReference {
|
|
86
|
+
id: PromptIdentifier;
|
|
87
|
+
version?: number | "active" | "latest";
|
|
88
|
+
variables?: PromptVariableValues;
|
|
89
|
+
cache?: PromptCacheMode;
|
|
90
|
+
/** Prompt messages are inserted before request messages by default. */
|
|
91
|
+
position?: "before" | "after";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface ChatCreateParams {
|
|
95
|
+
model: string;
|
|
96
|
+
messages?: readonly ChatMessage[];
|
|
97
|
+
/** Resolve and render a managed prompt before sending the gateway request. */
|
|
98
|
+
prompt?: PromptReference;
|
|
99
|
+
temperature?: number;
|
|
100
|
+
topP?: number;
|
|
101
|
+
maxOutputTokens?: number;
|
|
102
|
+
stop?: string | readonly string[];
|
|
103
|
+
tools?: readonly FunctionTool[];
|
|
104
|
+
toolChoice?: ToolChoice;
|
|
105
|
+
responseFormat?: ResponseFormat;
|
|
106
|
+
seed?: number;
|
|
107
|
+
user?: string;
|
|
108
|
+
provider?: string;
|
|
109
|
+
fallbackModels?: readonly string[];
|
|
110
|
+
routingStrategy?: RoutingStrategy;
|
|
111
|
+
metadata?: Readonly<Record<string, JsonValue>>;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export type FinishReason = ExtensibleString<
|
|
115
|
+
"stop" | "length" | "toolCalls" | "contentFilter"
|
|
116
|
+
>;
|
|
117
|
+
|
|
118
|
+
export interface ChatChoice {
|
|
119
|
+
index: number;
|
|
120
|
+
message: ChatMessage;
|
|
121
|
+
finishReason: FinishReason | null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface ChatCompletion {
|
|
125
|
+
id: string;
|
|
126
|
+
createdAt: number;
|
|
127
|
+
model: string;
|
|
128
|
+
choices: readonly ChatChoice[];
|
|
129
|
+
outputText: string;
|
|
130
|
+
usage: Usage;
|
|
131
|
+
metadata: RequestMetadata;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface ChatStreamEvent {
|
|
135
|
+
type: ExtensibleString<
|
|
136
|
+
"content.delta" | "toolCall.delta" | "completion.completed"
|
|
137
|
+
>;
|
|
138
|
+
id: string;
|
|
139
|
+
model: string;
|
|
140
|
+
choiceIndex?: number;
|
|
141
|
+
delta?: string;
|
|
142
|
+
toolCall?: Partial<FunctionToolCall>;
|
|
143
|
+
completion?: ChatCompletion;
|
|
144
|
+
metadata: RequestMetadata;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface EmbeddingCreateParams {
|
|
148
|
+
model: string;
|
|
149
|
+
input: string | readonly string[];
|
|
150
|
+
dimensions?: number;
|
|
151
|
+
encoding?: "float" | "base64";
|
|
152
|
+
user?: string;
|
|
153
|
+
provider?: string;
|
|
154
|
+
fallbackModels?: readonly string[];
|
|
155
|
+
routingStrategy?: RoutingStrategy;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export type Embedding =
|
|
159
|
+
| { index: number; values: readonly number[]; base64?: never }
|
|
160
|
+
| { index: number; values?: never; base64: string };
|
|
161
|
+
|
|
162
|
+
export interface EmbeddingResponse {
|
|
163
|
+
model: string;
|
|
164
|
+
embeddings: readonly Embedding[];
|
|
165
|
+
usage: Usage;
|
|
166
|
+
metadata: RequestMetadata;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export type ImageSize = ExtensibleString<
|
|
170
|
+
"256x256" | "512x512" | "1024x1024" | "1024x1792" | "1792x1024" | "auto"
|
|
171
|
+
>;
|
|
172
|
+
|
|
173
|
+
export interface ImageGenerateParams {
|
|
174
|
+
model: string;
|
|
175
|
+
prompt: string;
|
|
176
|
+
count?: number;
|
|
177
|
+
size?: ImageSize;
|
|
178
|
+
quality?: ExtensibleString<
|
|
179
|
+
"standard" | "hd" | "low" | "medium" | "high" | "auto"
|
|
180
|
+
>;
|
|
181
|
+
style?: ExtensibleString<"natural" | "vivid">;
|
|
182
|
+
format?: ExtensibleString<"png" | "jpeg" | "webp">;
|
|
183
|
+
responseFormat?: "url" | "base64";
|
|
184
|
+
background?: ExtensibleString<"transparent" | "opaque" | "auto">;
|
|
185
|
+
user?: string;
|
|
186
|
+
provider?: string;
|
|
187
|
+
metadata?: Readonly<Record<string, JsonValue>>;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export interface GeneratedImage {
|
|
191
|
+
url?: string;
|
|
192
|
+
base64?: string;
|
|
193
|
+
revisedPrompt?: string;
|
|
194
|
+
mediaType?: string;
|
|
195
|
+
width?: number;
|
|
196
|
+
height?: number;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export interface ImageGeneration {
|
|
200
|
+
id?: string;
|
|
201
|
+
createdAt: number;
|
|
202
|
+
model: string;
|
|
203
|
+
images: readonly GeneratedImage[];
|
|
204
|
+
usage?: Usage;
|
|
205
|
+
metadata: RequestMetadata;
|
|
206
|
+
}
|