@gatesai/providers 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.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,97 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { Effect } from "effect";
3
+ import { makeAnthropicProvider } from "../anthropic/index.js";
4
+ // Intercept fetch to verify request format without hitting the API
5
+ const mockFetch = vi.fn();
6
+ vi.stubGlobal("fetch", mockFetch);
7
+ const makeOkResponse = (body) => Promise.resolve({
8
+ ok: true,
9
+ json: () => Promise.resolve(body),
10
+ text: () => Promise.resolve(""),
11
+ });
12
+ const provider = makeAnthropicProvider({ apiKey: "test-key" });
13
+ describe("Anthropic provider", () => {
14
+ it("sends tools in input_schema format", async () => {
15
+ mockFetch.mockResolvedValueOnce(makeOkResponse({
16
+ content: [{ type: "text", text: "ok" }],
17
+ usage: { input_tokens: 10, output_tokens: 5 },
18
+ stop_reason: "end_turn",
19
+ }));
20
+ await Effect.runPromise(provider.chat([{ role: "user", content: "hello", timestamp: 0 }], [{ name: "bash", description: "Run bash", parameters: { type: "object", properties: { command: { type: "string" } }, required: ["command"] } }]));
21
+ const body = JSON.parse(mockFetch.mock.lastCall[1].body);
22
+ expect(body.tools[0]).toEqual({
23
+ name: "bash",
24
+ description: "Run bash",
25
+ input_schema: { type: "object", properties: { command: { type: "string" } }, required: ["command"] },
26
+ });
27
+ expect(body.tool_choice).toEqual({ type: "auto" });
28
+ });
29
+ it("parses tool_use blocks into toolCalls", async () => {
30
+ mockFetch.mockResolvedValueOnce(makeOkResponse({
31
+ content: [
32
+ { type: "text", text: "let me check" },
33
+ { type: "tool_use", id: "call_1", name: "bash", input: { command: "ls" } },
34
+ ],
35
+ usage: { input_tokens: 20, output_tokens: 15 },
36
+ stop_reason: "tool_use",
37
+ }));
38
+ const result = await Effect.runPromise(provider.chat([{ role: "user", content: "list files", timestamp: 0 }], []));
39
+ expect(result.content).toBe("let me check");
40
+ expect(result.toolCalls).toHaveLength(1);
41
+ expect(result.toolCalls[0]).toEqual({ id: "call_1", name: "bash", arguments: '{"command":"ls"}' });
42
+ });
43
+ it("converts tool result messages to tool_result blocks", async () => {
44
+ mockFetch.mockResolvedValueOnce(makeOkResponse({
45
+ content: [{ type: "text", text: "done" }],
46
+ usage: { input_tokens: 30, output_tokens: 10 },
47
+ stop_reason: "end_turn",
48
+ }));
49
+ const messages = [
50
+ { role: "user", content: "list files", timestamp: 0 },
51
+ {
52
+ role: "assistant",
53
+ content: "let me check",
54
+ timestamp: 1,
55
+ toolCalls: [{ id: "call_1", name: "bash", arguments: '{"command":"ls"}' }],
56
+ },
57
+ {
58
+ role: "user",
59
+ content: "",
60
+ timestamp: 2,
61
+ toolResults: [{ toolCallId: "call_1", content: "file.ts\nREADME.md" }],
62
+ },
63
+ ];
64
+ await Effect.runPromise(provider.chat(messages));
65
+ const body = JSON.parse(mockFetch.mock.lastCall[1].body);
66
+ const sentMessages = body.messages;
67
+ // User with tool_result block
68
+ const toolResultMsg = sentMessages[2];
69
+ expect(toolResultMsg.role).toBe("user");
70
+ expect(toolResultMsg.content[0]).toEqual({
71
+ type: "tool_result",
72
+ tool_use_id: "call_1",
73
+ content: "file.ts\nREADME.md",
74
+ });
75
+ // Assistant with tool_use block
76
+ const assistantMsg = sentMessages[1];
77
+ expect(assistantMsg.role).toBe("assistant");
78
+ expect(assistantMsg.content).toContainEqual({
79
+ type: "tool_use",
80
+ id: "call_1",
81
+ name: "bash",
82
+ input: { command: "ls" },
83
+ });
84
+ });
85
+ it("handles stop_reason tool_use with no text content", async () => {
86
+ mockFetch.mockResolvedValueOnce(makeOkResponse({
87
+ content: [{ type: "tool_use", id: "x", name: "read", input: { path: "foo.ts" } }],
88
+ usage: { input_tokens: 10, output_tokens: 8 },
89
+ stop_reason: "tool_use",
90
+ }));
91
+ const result = await Effect.runPromise(provider.chat([{ role: "user", content: "read foo.ts", timestamp: 0 }]));
92
+ expect(result.content).toBe("");
93
+ expect(result.toolCalls).toHaveLength(1);
94
+ expect(result.toolCalls[0].name).toBe("read");
95
+ });
96
+ });
97
+ //# sourceMappingURL=anthropic.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.test.js","sourceRoot":"","sources":["../../src/__tests__/anthropic.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,62 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { Effect } from "effect";
3
+ import { makeMiniMaxProvider } from "../minimax/index.js";
4
+ const mockFetch = vi.fn();
5
+ beforeEach(() => {
6
+ vi.clearAllMocks();
7
+ global.fetch = mockFetch;
8
+ });
9
+ describe("MiniMax Provider", () => {
10
+ it("should return provider with correct id", () => {
11
+ const provider = makeMiniMaxProvider({ apiKey: "test-key" });
12
+ expect(provider.id).toBe("minimax");
13
+ });
14
+ it("should handle successful response", async () => {
15
+ const mockResponse = {
16
+ ok: true,
17
+ json: vi.fn().mockResolvedValue({
18
+ id: "test-id",
19
+ object: "chat.completion",
20
+ created: 1234567890,
21
+ model: "MiniMax-Text-01",
22
+ choices: [
23
+ {
24
+ index: 0,
25
+ message: {
26
+ role: "assistant",
27
+ content: "Hello from MiniMax",
28
+ },
29
+ finish_reason: "stop",
30
+ },
31
+ ],
32
+ usage: {
33
+ prompt_tokens: 10,
34
+ completion_tokens: 20,
35
+ total_tokens: 30,
36
+ },
37
+ }),
38
+ };
39
+ mockFetch.mockResolvedValue(mockResponse);
40
+ const provider = makeMiniMaxProvider({ apiKey: "test-key" });
41
+ const result = await Effect.runPromise(provider.chat([{ role: "user", content: "Hi", timestamp: Date.now() }]));
42
+ expect(result.content).toBe("Hello from MiniMax");
43
+ expect(result.usage.inputTokens).toBe(10);
44
+ expect(result.usage.outputTokens).toBe(20);
45
+ expect(result.usage.totalTokens).toBe(30);
46
+ });
47
+ it("should handle API error", async () => {
48
+ const mockResponse = {
49
+ ok: false,
50
+ status: 401,
51
+ text: vi.fn().mockResolvedValue("Unauthorized"),
52
+ };
53
+ mockFetch.mockResolvedValue(mockResponse);
54
+ const provider = makeMiniMaxProvider({ apiKey: "bad-key" });
55
+ const result = await Effect.runPromise(Effect.result(provider.chat([{ role: "user", content: "Hi", timestamp: Date.now() }])));
56
+ expect(result._tag).toBe("Failure");
57
+ if (result._tag === "Failure") {
58
+ expect(result.failure.code).toBe("MINIMAX_ERROR");
59
+ }
60
+ });
61
+ });
62
+ //# sourceMappingURL=minimax.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minimax.test.js","sourceRoot":"","sources":["../../src/__tests__/minimax.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,94 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { Effect } from "effect";
3
+ import { makeOpenAIProvider } from "../openai/index.js";
4
+ const mockFetch = vi.fn();
5
+ vi.stubGlobal("fetch", mockFetch);
6
+ const ok = (body) => Promise.resolve({ ok: true, json: () => Promise.resolve(body), text: () => Promise.resolve("") });
7
+ const usage = { prompt_tokens: 10, completion_tokens: 5, total_tokens: 15 };
8
+ const provider = makeOpenAIProvider({ apiKey: "test" });
9
+ describe("OpenAI provider", () => {
10
+ it("sends tools in function format with tool_choice auto", async () => {
11
+ mockFetch.mockResolvedValueOnce(ok({
12
+ choices: [{ message: { role: "assistant", content: "ok" }, finish_reason: "stop" }],
13
+ usage,
14
+ }));
15
+ await Effect.runPromise(provider.chat([{ role: "user", content: "hi", timestamp: 0 }], [{ name: "bash", description: "Run bash", parameters: { type: "object", properties: { command: { type: "string" } }, required: ["command"] } }]));
16
+ const body = JSON.parse(mockFetch.mock.lastCall[1].body);
17
+ expect(body.tools[0]).toEqual({
18
+ type: "function",
19
+ function: {
20
+ name: "bash",
21
+ description: "Run bash",
22
+ parameters: { type: "object", properties: { command: { type: "string" } }, required: ["command"] },
23
+ },
24
+ });
25
+ expect(body.tool_choice).toBe("auto");
26
+ });
27
+ it("parses tool_calls from response into toolCalls", async () => {
28
+ mockFetch.mockResolvedValueOnce(ok({
29
+ choices: [{
30
+ message: {
31
+ role: "assistant",
32
+ content: null,
33
+ tool_calls: [{ id: "call_1", type: "function", function: { name: "bash", arguments: '{"command":"ls"}' } }],
34
+ },
35
+ finish_reason: "tool_calls",
36
+ }],
37
+ usage,
38
+ }));
39
+ const result = await Effect.runPromise(provider.chat([{ role: "user", content: "list files", timestamp: 0 }]));
40
+ expect(result.content).toBe("");
41
+ expect(result.toolCalls).toHaveLength(1);
42
+ expect(result.toolCalls[0]).toEqual({ id: "call_1", name: "bash", arguments: '{"command":"ls"}' });
43
+ });
44
+ it("converts tool results to separate 'tool' role messages", async () => {
45
+ mockFetch.mockResolvedValueOnce(ok({
46
+ choices: [{ message: { role: "assistant", content: "done" }, finish_reason: "stop" }],
47
+ usage,
48
+ }));
49
+ const messages = [
50
+ { role: "user", content: "list files", timestamp: 0 },
51
+ {
52
+ role: "assistant",
53
+ content: "",
54
+ timestamp: 1,
55
+ toolCalls: [
56
+ { id: "call_1", name: "bash", arguments: '{"command":"ls"}' },
57
+ { id: "call_2", name: "read", arguments: '{"path":"foo.ts"}' },
58
+ ],
59
+ },
60
+ {
61
+ role: "user",
62
+ content: "",
63
+ timestamp: 2,
64
+ toolResults: [
65
+ { toolCallId: "call_1", content: "file.ts" },
66
+ { toolCallId: "call_2", content: "const x = 1" },
67
+ ],
68
+ },
69
+ ];
70
+ await Effect.runPromise(provider.chat(messages));
71
+ const body = JSON.parse(mockFetch.mock.lastCall[1].body);
72
+ const sent = body.messages;
73
+ // Assistant message has tool_calls
74
+ expect(sent[1].role).toBe("assistant");
75
+ expect(sent[1].tool_calls).toHaveLength(2);
76
+ // Each tool result becomes a separate "tool" message
77
+ expect(sent[2]).toEqual({ role: "tool", tool_call_id: "call_1", content: "file.ts" });
78
+ expect(sent[3]).toEqual({ role: "tool", tool_call_id: "call_2", content: "const x = 1" });
79
+ expect(sent).toHaveLength(4);
80
+ });
81
+ it("passes context role as system message", async () => {
82
+ mockFetch.mockResolvedValueOnce(ok({
83
+ choices: [{ message: { role: "assistant", content: "hi" }, finish_reason: "stop" }],
84
+ usage,
85
+ }));
86
+ await Effect.runPromise(provider.chat([
87
+ { role: "context", content: "You are helpful.", timestamp: 0 },
88
+ { role: "user", content: "hello", timestamp: 1 },
89
+ ]));
90
+ const body = JSON.parse(mockFetch.mock.lastCall[1].body);
91
+ expect(body.messages[0]).toEqual({ role: "system", content: "You are helpful." });
92
+ });
93
+ });
94
+ //# sourceMappingURL=openai.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.test.js","sourceRoot":"","sources":["../../src/__tests__/openai.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { Provider } from "../types.js";
2
+ export interface AnthropicThinking {
3
+ /** Enable extended thinking. Requires model claude-3-7-sonnet or later. */
4
+ readonly enabled: boolean;
5
+ /** Token budget for thinking (default: 10000). Must be < max_tokens. */
6
+ readonly budgetTokens?: number;
7
+ }
8
+ export interface AnthropicConfig {
9
+ readonly apiKey: string;
10
+ readonly model?: string;
11
+ readonly baseUrl?: string;
12
+ readonly thinking?: AnthropicThinking;
13
+ }
14
+ export declare const makeAnthropicProvider: (config: AnthropicConfig) => Provider;
@@ -0,0 +1,128 @@
1
+ import { Effect } from "effect";
2
+ // ── Message conversion ──────────────────────────────────────────────────────
3
+ const toAnthropicMessage = (msg) => {
4
+ if (msg.role === "system" || msg.role === "context")
5
+ return null;
6
+ // User message carrying tool results — converted to tool_result blocks
7
+ if (msg.toolResults && msg.toolResults.length > 0) {
8
+ const blocks = msg.toolResults.map((tr) => ({
9
+ type: "tool_result",
10
+ tool_use_id: tr.toolCallId,
11
+ content: tr.content,
12
+ ...(tr.isError ? { is_error: true } : {}),
13
+ }));
14
+ if (msg.content)
15
+ blocks.unshift({ type: "text", text: msg.content });
16
+ return { role: "user", content: blocks };
17
+ }
18
+ // Assistant message with tool calls — converted to tool_use blocks
19
+ if (msg.role === "assistant" && msg.toolCalls && msg.toolCalls.length > 0) {
20
+ const blocks = [];
21
+ if (msg.content)
22
+ blocks.push({ type: "text", text: msg.content });
23
+ for (const tc of msg.toolCalls) {
24
+ let input = {};
25
+ try {
26
+ input = JSON.parse(tc.arguments);
27
+ }
28
+ catch {
29
+ input = { args: tc.arguments };
30
+ }
31
+ blocks.push({ type: "tool_use", id: tc.id, name: tc.name, input });
32
+ }
33
+ return { role: "assistant", content: blocks };
34
+ }
35
+ return {
36
+ role: msg.role === "assistant" ? "assistant" : "user",
37
+ content: msg.content,
38
+ };
39
+ };
40
+ const toAnthropicTool = (tool) => ({
41
+ name: tool.name,
42
+ description: tool.description,
43
+ input_schema: tool.parameters,
44
+ });
45
+ // ── Provider ────────────────────────────────────────────────────────────────
46
+ export const makeAnthropicProvider = (config) => {
47
+ const model = config.model ?? "claude-sonnet-4-6";
48
+ const baseUrl = config.baseUrl ?? "https://api.anthropic.com/v1";
49
+ return {
50
+ id: "anthropic",
51
+ chat: (messages, tools) => Effect.tryPromise({
52
+ try: async () => {
53
+ const systemMessage = messages.find((m) => m.role === "system" || m.role === "context");
54
+ const conversationMessages = messages
55
+ .filter((m) => m.role !== "system" && m.role !== "context")
56
+ .map(toAnthropicMessage)
57
+ .filter((m) => m !== null);
58
+ const thinkingEnabled = config.thinking?.enabled;
59
+ const budgetTokens = config.thinking?.budgetTokens ?? 10000;
60
+ // Thinking requires max_tokens > budget_tokens
61
+ const maxTokens = thinkingEnabled ? Math.max(16000, budgetTokens + 1000) : 4096;
62
+ const body = {
63
+ model,
64
+ messages: conversationMessages,
65
+ max_tokens: maxTokens,
66
+ };
67
+ if (thinkingEnabled) {
68
+ body.thinking = { type: "enabled", budget_tokens: budgetTokens };
69
+ }
70
+ if (systemMessage) {
71
+ body.system = systemMessage.content;
72
+ }
73
+ if (tools && tools.length > 0) {
74
+ body.tools = tools.map(toAnthropicTool);
75
+ body.tool_choice = { type: "auto" };
76
+ }
77
+ const response = await fetch(`${baseUrl}/messages`, {
78
+ method: "POST",
79
+ headers: {
80
+ "Content-Type": "application/json",
81
+ "x-api-key": config.apiKey,
82
+ "anthropic-version": "2023-06-01",
83
+ },
84
+ body: JSON.stringify(body),
85
+ });
86
+ if (!response.ok) {
87
+ const error = await response.text();
88
+ throw new Error(`Anthropic API error: ${response.status} - ${error}`);
89
+ }
90
+ const data = (await response.json());
91
+ const thinkingContent = data.content
92
+ .filter((c) => c.type === "thinking")
93
+ .map((c) => c.thinking)
94
+ .join("\n");
95
+ const textContent = data.content
96
+ .filter((c) => c.type === "text")
97
+ .map((c) => c.text)
98
+ .join("\n");
99
+ const toolUseBlocks = data.content.filter((c) => c.type === "tool_use");
100
+ const toolCalls = toolUseBlocks.length > 0
101
+ ? toolUseBlocks.map((block) => ({
102
+ id: block.id,
103
+ name: block.name,
104
+ arguments: JSON.stringify(block.input),
105
+ }))
106
+ : undefined;
107
+ const inputCost = data.usage.input_tokens * 0.000003;
108
+ const outputCost = data.usage.output_tokens * 0.000015;
109
+ return {
110
+ content: textContent,
111
+ toolCalls,
112
+ usage: {
113
+ inputTokens: data.usage.input_tokens,
114
+ outputTokens: data.usage.output_tokens,
115
+ totalTokens: data.usage.input_tokens + data.usage.output_tokens,
116
+ },
117
+ cost: inputCost + outputCost,
118
+ ...(thinkingContent ? { reasoningDetails: thinkingContent } : {}),
119
+ };
120
+ },
121
+ catch: (error) => ({
122
+ code: "ANTHROPIC_ERROR",
123
+ message: error instanceof Error ? error.message : String(error),
124
+ }),
125
+ }),
126
+ };
127
+ };
128
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/anthropic/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from "./types.js";
2
+ export * from "./minimax/index.js";
3
+ export * from "./anthropic/index.js";
4
+ export * from "./openai/index.js";
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from "./types.js";
2
+ export * from "./minimax/index.js";
3
+ export * from "./anthropic/index.js";
4
+ export * from "./openai/index.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { Provider } from "../types.js";
2
+ export interface MiniMaxConfig {
3
+ readonly apiKey: string;
4
+ readonly model?: string;
5
+ readonly baseUrl?: string;
6
+ }
7
+ export declare const makeMiniMaxProvider: (config: MiniMaxConfig) => Provider;
@@ -0,0 +1,81 @@
1
+ import { Effect } from "effect";
2
+ export const makeMiniMaxProvider = (config) => {
3
+ const model = config.model ?? "MiniMax-M2.7";
4
+ const baseUrl = config.baseUrl ?? "https://api.minimax.io/v1";
5
+ return {
6
+ id: "minimax",
7
+ chat: (messages, tools) => Effect.tryPromise({
8
+ try: async () => {
9
+ const body = {
10
+ model,
11
+ messages: messages.map((m) => {
12
+ const msg = {
13
+ role: m.role,
14
+ content: m.content,
15
+ };
16
+ if (m.role === "assistant" && m.toolCalls) {
17
+ msg.content = m.content || "";
18
+ }
19
+ return msg;
20
+ }),
21
+ temperature: 0.7,
22
+ max_tokens: 4096,
23
+ };
24
+ if (tools && tools.length > 0) {
25
+ body.tools = tools.map((t) => ({
26
+ type: "function",
27
+ function: {
28
+ name: t.name,
29
+ description: t.description,
30
+ parameters: t.parameters,
31
+ },
32
+ }));
33
+ body.extra_body = { reasoning_split: true };
34
+ }
35
+ const response = await fetch(`${baseUrl}/chat/completions`, {
36
+ method: "POST",
37
+ headers: {
38
+ "Content-Type": "application/json",
39
+ Authorization: `Bearer ${config.apiKey}`,
40
+ },
41
+ body: JSON.stringify(body),
42
+ });
43
+ if (!response.ok) {
44
+ const error = await response.text();
45
+ throw new Error(`MiniMax API error: ${response.status} - ${error}`);
46
+ }
47
+ const data = (await response.json());
48
+ const choice = data.choices[0];
49
+ if (!choice) {
50
+ throw new Error("No response from MiniMax");
51
+ }
52
+ const inputCost = (data.usage.prompt_tokens * 0.000) + (data.usage.completion_tokens * 0.001);
53
+ const outputCost = data.usage.completion_tokens * 0.000;
54
+ const toolCalls = choice.message.tool_calls?.map((tc) => ({
55
+ id: tc.id,
56
+ name: tc.function.name,
57
+ arguments: tc.function.arguments,
58
+ }));
59
+ const reasoningDetails = data.reasoning_details
60
+ ?.map((r) => r.text)
61
+ .join("\n");
62
+ return {
63
+ content: choice.message.content || "",
64
+ toolCalls,
65
+ usage: {
66
+ inputTokens: data.usage.prompt_tokens,
67
+ outputTokens: data.usage.completion_tokens,
68
+ totalTokens: data.usage.total_tokens,
69
+ },
70
+ cost: inputCost + outputCost,
71
+ reasoningDetails,
72
+ };
73
+ },
74
+ catch: (error) => ({
75
+ code: "MINIMAX_ERROR",
76
+ message: error instanceof Error ? error.message : String(error),
77
+ }),
78
+ }),
79
+ };
80
+ };
81
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/minimax/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { Provider } from "../types.js";
2
+ export interface OpenAIConfig {
3
+ readonly apiKey: string;
4
+ readonly model?: string;
5
+ readonly baseUrl?: string;
6
+ /**
7
+ * Reasoning effort for o1/o3 models.
8
+ * @see https://platform.openai.com/docs/guides/reasoning
9
+ */
10
+ readonly reasoningEffort?: "low" | "medium" | "high";
11
+ }
12
+ export declare const makeOpenAIProvider: (config: OpenAIConfig) => Provider;
@@ -0,0 +1,110 @@
1
+ import { Effect } from "effect";
2
+ // ── Message conversion ──────────────────────────────────────────────────────
3
+ // Returns one or more OpenAI messages — tool results expand into separate "tool" role messages
4
+ const toOpenAIMessages = (msg) => {
5
+ if (msg.role === "context")
6
+ return { role: "system", content: msg.content };
7
+ // Tool results → one "tool" message per result (OpenAI requires separate messages)
8
+ if (msg.toolResults && msg.toolResults.length > 0) {
9
+ return msg.toolResults.map((tr) => ({
10
+ role: "tool",
11
+ tool_call_id: tr.toolCallId,
12
+ content: tr.content,
13
+ }));
14
+ }
15
+ // Assistant message with tool calls
16
+ if (msg.role === "assistant" && msg.toolCalls && msg.toolCalls.length > 0) {
17
+ return {
18
+ role: "assistant",
19
+ content: msg.content || null,
20
+ tool_calls: msg.toolCalls.map((tc) => ({
21
+ id: tc.id,
22
+ type: "function",
23
+ function: { name: tc.name, arguments: tc.arguments },
24
+ })),
25
+ };
26
+ }
27
+ return { role: msg.role, content: msg.content };
28
+ };
29
+ const toOpenAITool = (tool) => ({
30
+ type: "function",
31
+ function: {
32
+ name: tool.name,
33
+ description: tool.description,
34
+ parameters: tool.parameters,
35
+ },
36
+ });
37
+ // ── Provider ────────────────────────────────────────────────────────────────
38
+ export const makeOpenAIProvider = (config) => {
39
+ const model = config.model ?? "gpt-4o";
40
+ const baseUrl = config.baseUrl ?? "https://api.openai.com/v1";
41
+ return {
42
+ id: "openai",
43
+ chat: (messages, tools) => Effect.tryPromise({
44
+ try: async () => {
45
+ const openAIMessages = messages
46
+ .filter((m) => m.role !== "system" || true) // keep system
47
+ .flatMap((m) => {
48
+ // system/context → system role
49
+ if (m.role === "system")
50
+ return [{ role: "system", content: m.content }];
51
+ const converted = toOpenAIMessages(m);
52
+ return Array.isArray(converted) ? converted : [converted];
53
+ });
54
+ // o1/o3 models don't support temperature or max_tokens; use reasoning_effort
55
+ const isReasoningModel = model.startsWith("o1") || model.startsWith("o3");
56
+ const body = {
57
+ model,
58
+ messages: openAIMessages,
59
+ ...(isReasoningModel
60
+ ? { reasoning_effort: config.reasoningEffort ?? "medium" }
61
+ : { temperature: 0.7, max_tokens: 4096 }),
62
+ };
63
+ if (tools && tools.length > 0) {
64
+ body.tools = tools.map(toOpenAITool);
65
+ body.tool_choice = "auto";
66
+ }
67
+ const response = await fetch(`${baseUrl}/chat/completions`, {
68
+ method: "POST",
69
+ headers: {
70
+ "Content-Type": "application/json",
71
+ Authorization: `Bearer ${config.apiKey}`,
72
+ },
73
+ body: JSON.stringify(body),
74
+ });
75
+ if (!response.ok) {
76
+ const error = await response.text();
77
+ throw new Error(`OpenAI API error: ${response.status} - ${error}`);
78
+ }
79
+ const data = (await response.json());
80
+ const choice = data.choices[0];
81
+ if (!choice)
82
+ throw new Error("No response from OpenAI");
83
+ const toolCalls = choice.message.tool_calls && choice.message.tool_calls.length > 0
84
+ ? choice.message.tool_calls.map((tc) => ({
85
+ id: tc.id,
86
+ name: tc.function.name,
87
+ arguments: tc.function.arguments,
88
+ }))
89
+ : undefined;
90
+ const inputCost = data.usage.prompt_tokens * 0.000003;
91
+ const outputCost = data.usage.completion_tokens * 0.000015;
92
+ return {
93
+ content: choice.message.content ?? "",
94
+ toolCalls,
95
+ usage: {
96
+ inputTokens: data.usage.prompt_tokens,
97
+ outputTokens: data.usage.completion_tokens,
98
+ totalTokens: data.usage.total_tokens,
99
+ },
100
+ cost: inputCost + outputCost,
101
+ };
102
+ },
103
+ catch: (error) => ({
104
+ code: "OPENAI_ERROR",
105
+ message: error instanceof Error ? error.message : String(error),
106
+ }),
107
+ }),
108
+ };
109
+ };
110
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/openai/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { Effect } from "effect";
2
+ export interface Tool {
3
+ readonly name: string;
4
+ readonly description: string;
5
+ readonly parameters: Record<string, unknown>;
6
+ }
7
+ export interface ToolCall {
8
+ readonly id: string;
9
+ readonly name: string;
10
+ readonly arguments: string;
11
+ }
12
+ export interface ToolResult {
13
+ readonly toolCallId: string;
14
+ readonly content: string;
15
+ readonly isError?: boolean;
16
+ }
17
+ export interface Message {
18
+ readonly role: "user" | "assistant" | "system" | "context";
19
+ readonly content: string;
20
+ readonly timestamp: number;
21
+ readonly toolCalls?: ToolCall[];
22
+ readonly toolResults?: ToolResult[];
23
+ }
24
+ export interface ChatResponse {
25
+ readonly content: string;
26
+ readonly toolCalls?: ToolCall[];
27
+ readonly usage: {
28
+ readonly inputTokens: number;
29
+ readonly outputTokens: number;
30
+ readonly totalTokens: number;
31
+ };
32
+ readonly cost?: number;
33
+ readonly reasoningDetails?: string;
34
+ }
35
+ export interface ProviderError {
36
+ readonly code: string;
37
+ readonly message: string;
38
+ }
39
+ export interface Provider {
40
+ readonly id: string;
41
+ readonly chat: (messages: Message[], tools?: Tool[]) => Effect.Effect<ChatResponse, ProviderError>;
42
+ }
43
+ export interface StreamingChunk {
44
+ readonly content: string;
45
+ readonly toolCalls?: ToolCall[];
46
+ readonly done: boolean;
47
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@gatesai/providers",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "types": "./dist/index.d.ts",
6
+ "exports": {
7
+ ".": "./dist/index.js",
8
+ "./minimax": "./dist/minimax/index.js",
9
+ "./anthropic": "./dist/anthropic/index.js",
10
+ "./openai": "./dist/openai/index.js"
11
+ },
12
+ "dependencies": {
13
+ "effect": "4.0.0-beta.64"
14
+ },
15
+ "devDependencies": {
16
+ "typescript": "^5.4.0",
17
+ "vitest": "^1.0.0"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "main": "./dist/index.js",
26
+ "scripts": {
27
+ "build": "tsc",
28
+ "test": "vitest run",
29
+ "lint": "echo \"No lint\"",
30
+ "typecheck": "tsc --noEmit"
31
+ }
32
+ }