@loom-node/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.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/dist/anthropic/anthropic-provider.d.ts +21 -0
  3. package/dist/anthropic/anthropic-provider.d.ts.map +1 -0
  4. package/dist/anthropic/anthropic-provider.js +126 -0
  5. package/dist/anthropic/anthropic-provider.js.map +1 -0
  6. package/dist/anthropic/mappers.d.ts +16 -0
  7. package/dist/anthropic/mappers.d.ts.map +1 -0
  8. package/dist/anthropic/mappers.js +44 -0
  9. package/dist/anthropic/mappers.js.map +1 -0
  10. package/dist/base-provider.d.ts +31 -0
  11. package/dist/base-provider.d.ts.map +1 -0
  12. package/dist/base-provider.js +63 -0
  13. package/dist/base-provider.js.map +1 -0
  14. package/dist/google/gemini-provider.d.ts +21 -0
  15. package/dist/google/gemini-provider.d.ts.map +1 -0
  16. package/dist/google/gemini-provider.js +135 -0
  17. package/dist/google/gemini-provider.js.map +1 -0
  18. package/dist/google/mappers.d.ts +27 -0
  19. package/dist/google/mappers.d.ts.map +1 -0
  20. package/dist/google/mappers.js +44 -0
  21. package/dist/google/mappers.js.map +1 -0
  22. package/dist/index.d.ts +12 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +11 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/openai/index.d.ts +3 -0
  27. package/dist/openai/index.d.ts.map +1 -0
  28. package/dist/openai/index.js +2 -0
  29. package/dist/openai/index.js.map +1 -0
  30. package/dist/openai/mappers.d.ts +25 -0
  31. package/dist/openai/mappers.d.ts.map +1 -0
  32. package/dist/openai/mappers.js +45 -0
  33. package/dist/openai/mappers.js.map +1 -0
  34. package/dist/openai/openai-embedding.d.ts +17 -0
  35. package/dist/openai/openai-embedding.d.ts.map +1 -0
  36. package/dist/openai/openai-embedding.js +28 -0
  37. package/dist/openai/openai-embedding.js.map +1 -0
  38. package/dist/openai/openai-provider.d.ts +20 -0
  39. package/dist/openai/openai-provider.d.ts.map +1 -0
  40. package/dist/openai/openai-provider.js +121 -0
  41. package/dist/openai/openai-provider.js.map +1 -0
  42. package/dist/presets.d.ts +21 -0
  43. package/dist/presets.d.ts.map +1 -0
  44. package/dist/presets.js +30 -0
  45. package/dist/presets.js.map +1 -0
  46. package/package.json +31 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Loom Node Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,21 @@
1
+ import type { CompletionParams, CompletionResult, StreamChunk, StreamOptions } from '@loom-node/core';
2
+ import { BaseLLMProvider } from '../base-provider.js';
3
+ import type { BaseLLMProviderConfig } from '../base-provider.js';
4
+ export interface AnthropicProviderConfig extends Omit<BaseLLMProviderConfig, 'providerName'> {
5
+ apiKey: string;
6
+ model?: string;
7
+ baseUrl?: string;
8
+ }
9
+ export declare class AnthropicProvider extends BaseLLMProvider {
10
+ private readonly apiKey;
11
+ private readonly model;
12
+ private readonly baseUrl;
13
+ constructor(config: AnthropicProviderConfig);
14
+ private buildBody;
15
+ private post;
16
+ protected doComplete(params: CompletionParams): Promise<CompletionResult>;
17
+ private parseResponse;
18
+ protected doStream(params: CompletionParams, opts?: StreamOptions): AsyncGenerator<StreamChunk>;
19
+ private parseSSE;
20
+ }
21
+ //# sourceMappingURL=anthropic-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-provider.d.ts","sourceRoot":"","sources":["../../src/anthropic/anthropic-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,EAAE,aAAa,EAC3B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAGjE,MAAM,WAAW,uBAAwB,SAAQ,IAAI,CAAC,qBAAqB,EAAE,cAAc,CAAC;IAC1F,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,iBAAkB,SAAQ,eAAe;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,uBAAuB;IAO3C,OAAO,CAAC,SAAS;YAcH,IAAI;cAuBF,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAM/E,OAAO,CAAC,aAAa;cAqBJ,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,cAAc,CAAC,WAAW,CAAC;YAKvF,QAAQ;CA0CxB"}
@@ -0,0 +1,126 @@
1
+ import { LLMError, LLMRateLimitError, LLMAuthError } from '@loom-node/core';
2
+ import { BaseLLMProvider } from '../base-provider.js';
3
+ import { toAnthropicMessages, toAnthropicTools } from './mappers.js';
4
+ export class AnthropicProvider extends BaseLLMProvider {
5
+ apiKey;
6
+ model;
7
+ baseUrl;
8
+ constructor(config) {
9
+ super({ ...config, providerName: 'anthropic' });
10
+ this.apiKey = config.apiKey;
11
+ this.model = config.model ?? 'claude-sonnet-4-20250514';
12
+ this.baseUrl = config.baseUrl ?? 'https://api.anthropic.com';
13
+ }
14
+ buildBody(params, stream) {
15
+ const { system, messages } = toAnthropicMessages(params.messages);
16
+ const body = {
17
+ model: this.model,
18
+ messages,
19
+ max_tokens: params.maxTokens ?? 4096,
20
+ stream,
21
+ };
22
+ if (system)
23
+ body.system = system;
24
+ if (params.tools?.length)
25
+ body.tools = toAnthropicTools(params.tools);
26
+ if (params.temperature != null)
27
+ body.temperature = params.temperature;
28
+ return body;
29
+ }
30
+ async post(body, signal) {
31
+ const res = await fetch(`${this.baseUrl}/v1/messages`, {
32
+ method: 'POST',
33
+ headers: {
34
+ 'Content-Type': 'application/json',
35
+ 'x-api-key': this.apiKey,
36
+ 'anthropic-version': '2023-06-01',
37
+ },
38
+ body: JSON.stringify(body),
39
+ signal,
40
+ });
41
+ if (!res.ok) {
42
+ if (res.status === 401)
43
+ throw new LLMAuthError('anthropic');
44
+ if (res.status === 429) {
45
+ const retryAfter = res.headers.get('retry-after');
46
+ throw new LLMRateLimitError('anthropic', retryAfter ? Number(retryAfter) * 1000 : undefined);
47
+ }
48
+ const text = await res.text().catch(() => '');
49
+ throw new LLMError('LLM_ERROR', 'anthropic', `Anthropic API error ${res.status}: ${text}`, res.status);
50
+ }
51
+ return res;
52
+ }
53
+ async doComplete(params) {
54
+ const res = await this.post(this.buildBody(params, false));
55
+ const json = await res.json();
56
+ return this.parseResponse(json);
57
+ }
58
+ parseResponse(json) {
59
+ let content = '';
60
+ const toolCalls = [];
61
+ for (const block of json.content) {
62
+ if (block.type === 'text')
63
+ content += block.text;
64
+ if (block.type === 'tool_use') {
65
+ toolCalls.push({ id: block.id, name: block.name, arguments: JSON.stringify(block.input) });
66
+ }
67
+ }
68
+ return {
69
+ content,
70
+ toolCalls: toolCalls.length ? toolCalls : undefined,
71
+ finishReason: json.stop_reason === 'tool_use' ? 'tool_calls' : json.stop_reason === 'max_tokens' ? 'length' : 'stop',
72
+ usage: {
73
+ promptTokens: json.usage.input_tokens,
74
+ completionTokens: json.usage.output_tokens,
75
+ totalTokens: json.usage.input_tokens + json.usage.output_tokens,
76
+ },
77
+ };
78
+ }
79
+ async *doStream(params, opts) {
80
+ const res = await this.post(this.buildBody(params, true), opts?.signal);
81
+ yield* this.parseSSE(res);
82
+ }
83
+ async *parseSSE(res) {
84
+ const reader = res.body.getReader();
85
+ const decoder = new TextDecoder();
86
+ let buf = '';
87
+ let currentToolId = '';
88
+ try {
89
+ while (true) {
90
+ const { done, value } = await reader.read();
91
+ if (done)
92
+ break;
93
+ buf += decoder.decode(value, { stream: true });
94
+ const lines = buf.split('\n');
95
+ buf = lines.pop();
96
+ for (const line of lines) {
97
+ if (!line.startsWith('data: '))
98
+ continue;
99
+ const data = JSON.parse(line.slice(6));
100
+ if (data.type === 'content_block_start' && data.content_block?.type === 'tool_use') {
101
+ currentToolId = data.content_block.id ?? '';
102
+ yield { type: 'tool-call-delta', toolCallId: currentToolId, name: data.content_block.name, content: '' };
103
+ }
104
+ if (data.type === 'content_block_delta') {
105
+ if (data.delta?.type === 'text_delta') {
106
+ yield { type: 'text', content: data.delta.text };
107
+ }
108
+ if (data.delta?.type === 'input_json_delta') {
109
+ yield { type: 'tool-call-delta', toolCallId: currentToolId, content: data.delta.partial_json };
110
+ }
111
+ }
112
+ if (data.type === 'message_delta' && data.usage) {
113
+ yield { type: 'usage', usage: { completionTokens: data.usage.output_tokens } };
114
+ }
115
+ if (data.type === 'message_start' && data.message?.usage) {
116
+ yield { type: 'usage', usage: { promptTokens: data.message.usage.input_tokens } };
117
+ }
118
+ }
119
+ }
120
+ }
121
+ finally {
122
+ reader.releaseLock();
123
+ }
124
+ }
125
+ }
126
+ //# sourceMappingURL=anthropic-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-provider.js","sourceRoot":"","sources":["../../src/anthropic/anthropic-provider.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAQrE,MAAM,OAAO,iBAAkB,SAAQ,eAAe;IACnC,MAAM,CAAS;IACf,KAAK,CAAS;IACd,OAAO,CAAS;IAEjC,YAAY,MAA+B;QACzC,KAAK,CAAC,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,0BAA0B,CAAC;QACxD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,2BAA2B,CAAC;IAC/D,CAAC;IAEO,SAAS,CAAC,MAAwB,EAAE,MAAe;QACzD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAClE,MAAM,IAAI,GAA4B;YACpC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ;YACR,UAAU,EAAE,MAAM,CAAC,SAAS,IAAI,IAAI;YACpC,MAAM;SACP,CAAC;QACF,IAAI,MAAM;YAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACjC,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM;YAAE,IAAI,CAAC,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,IAAI,MAAM,CAAC,WAAW,IAAI,IAAI;YAAE,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QACtE,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,IAAa,EAAE,MAAoB;QACpD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,cAAc,EAAE;YACrD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,IAAI,CAAC,MAAM;gBACxB,mBAAmB,EAAE,YAAY;aAClC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAC1B,MAAM;SACP,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;gBAAE,MAAM,IAAI,YAAY,CAAC,WAAW,CAAC,CAAC;YAC5D,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACvB,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBAClD,MAAM,IAAI,iBAAiB,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAC/F,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,WAAW,EAAE,uBAAuB,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QACzG,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAES,KAAK,CAAC,UAAU,CAAC,MAAwB;QACjD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAuB,CAAC;QACnD,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAEO,aAAa,CAAC,IAAuB;QAC3C,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,MAAM,SAAS,GAAe,EAAE,CAAC;QACjC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;gBAAE,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC;YACjD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC9B,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAK,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC/F,CAAC;QACH,CAAC;QACD,OAAO;YACL,OAAO;YACP,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YACnD,YAAY,EAAE,IAAI,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM;YACpH,KAAK,EAAE;gBACL,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY;gBACrC,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa;gBAC1C,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa;aAChE;SACF,CAAC;IACJ,CAAC;IAES,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAwB,EAAE,IAAoB;QACtE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QACxE,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAEO,KAAK,CAAC,CAAC,QAAQ,CAAC,GAAa;QACnC,MAAM,MAAM,GAAG,GAAG,CAAC,IAAK,CAAC,SAAS,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,IAAI,GAAG,GAAG,EAAE,CAAC;QACb,IAAI,aAAa,GAAG,EAAE,CAAC;QAEvB,IAAI,CAAC;YACH,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5C,IAAI,IAAI;oBAAE,MAAM;gBAChB,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC9B,GAAG,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;gBAEnB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;wBAAE,SAAS;oBACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAyB,CAAC;oBAE/D,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAqB,IAAI,IAAI,CAAC,aAAa,EAAE,IAAI,KAAK,UAAU,EAAE,CAAC;wBACnF,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC;wBAC5C,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,UAAU,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;oBAC3G,CAAC;oBACD,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;wBACxC,IAAI,IAAI,CAAC,KAAK,EAAE,IAAI,KAAK,YAAY,EAAE,CAAC;4BACtC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,IAAK,EAAE,CAAC;wBACpD,CAAC;wBACD,IAAI,IAAI,CAAC,KAAK,EAAE,IAAI,KAAK,kBAAkB,EAAE,CAAC;4BAC5C,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,YAAa,EAAE,CAAC;wBAClG,CAAC;oBACH,CAAC;oBACD,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;wBAChD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,EAAE,CAAC;oBACjF,CAAC;oBACD,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;wBACzD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,CAAC;oBACpF,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ import type { Message, JsonToolDefinition } from '@loom-node/core';
2
+ export declare function toAnthropicMessages(messages: Message[]): {
3
+ system?: string;
4
+ messages: AnthropicMessage[];
5
+ };
6
+ export declare function toAnthropicTools(tools: JsonToolDefinition[]): AnthropicTool[];
7
+ export type AnthropicMessage = {
8
+ role: string;
9
+ content: unknown;
10
+ };
11
+ export type AnthropicTool = {
12
+ name: string;
13
+ description: string;
14
+ input_schema: unknown;
15
+ };
16
+ //# sourceMappingURL=mappers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mappers.d.ts","sourceRoot":"","sources":["../../src/anthropic/mappers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAe,MAAM,iBAAiB,CAAC;AAEhF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAuC1G;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG,aAAa,EAAE,CAE7E;AAED,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAClE,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,CAAC"}
@@ -0,0 +1,44 @@
1
+ export function toAnthropicMessages(messages) {
2
+ let system;
3
+ const out = [];
4
+ for (const msg of messages) {
5
+ switch (msg.role) {
6
+ case 'system':
7
+ system = msg.content;
8
+ break;
9
+ case 'user':
10
+ out.push({
11
+ role: 'user',
12
+ content: typeof msg.content === 'string'
13
+ ? msg.content
14
+ : msg.content.map((p) => p.type === 'text'
15
+ ? { type: 'text', text: p.text }
16
+ : { type: 'image', source: { type: 'url', url: p.imageUrl } }),
17
+ });
18
+ break;
19
+ case 'assistant': {
20
+ const content = [];
21
+ if (msg.content)
22
+ content.push({ type: 'text', text: msg.content });
23
+ if (msg.toolCalls?.length) {
24
+ for (const tc of msg.toolCalls) {
25
+ content.push({ type: 'tool_use', id: tc.id, name: tc.name, input: JSON.parse(tc.arguments) });
26
+ }
27
+ }
28
+ out.push({ role: 'assistant', content });
29
+ break;
30
+ }
31
+ case 'tool':
32
+ out.push({
33
+ role: 'user',
34
+ content: [{ type: 'tool_result', tool_use_id: msg.toolCallId, content: msg.content }],
35
+ });
36
+ break;
37
+ }
38
+ }
39
+ return { system, messages: out };
40
+ }
41
+ export function toAnthropicTools(tools) {
42
+ return tools.map(t => ({ name: t.name, description: t.description, input_schema: t.parameters }));
43
+ }
44
+ //# sourceMappingURL=mappers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mappers.js","sourceRoot":"","sources":["../../src/anthropic/mappers.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,mBAAmB,CAAC,QAAmB;IACrD,IAAI,MAA0B,CAAC;IAC/B,MAAM,GAAG,GAAuB,EAAE,CAAC;IACnC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,QAAQ;gBACX,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC;gBACrB,MAAM;YACR,KAAK,MAAM;gBACT,GAAG,CAAC,IAAI,CAAC;oBACP,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;wBACtC,CAAC,CAAC,GAAG,CAAC,OAAO;wBACb,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAc,EAAE,EAAE,CACjC,CAAC,CAAC,IAAI,KAAK,MAAM;4BACf,CAAC,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,CAAC,IAAK,EAAE;4BAC1C,CAAC,CAAC,EAAE,IAAI,EAAE,OAAgB,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAc,EAAE,GAAG,EAAE,CAAC,CAAC,QAAS,EAAE,EAAE,CAAC;iBAC1F,CAAC,CAAC;gBACH,MAAM;YACR,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,MAAM,OAAO,GAAc,EAAE,CAAC;gBAC9B,IAAI,GAAG,CAAC,OAAO;oBAAE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBACnE,IAAI,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;oBAC1B,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;wBAC/B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;oBAChG,CAAC;gBACH,CAAC;gBACD,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;gBACzC,MAAM;YACR,CAAC;YACD,KAAK,MAAM;gBACT,GAAG,CAAC,IAAI,CAAC;oBACP,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;iBACtF,CAAC,CAAC;gBACH,MAAM;QACV,CAAC;IACH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAA2B;IAC1D,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,YAAY,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;AACpG,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { LLMProvider, CompletionParams, CompletionResult, StreamChunk, StreamOptions } from '@loom-node/core';
2
+ export interface RetryConfig {
3
+ maxRetries: number;
4
+ baseDelayMs: number;
5
+ maxDelayMs: number;
6
+ }
7
+ export interface CircuitBreakerConfig {
8
+ failureThreshold: number;
9
+ resetTimeMs: number;
10
+ }
11
+ export interface BaseLLMProviderConfig {
12
+ providerName: string;
13
+ retry?: Partial<RetryConfig>;
14
+ circuitBreaker?: Partial<CircuitBreakerConfig>;
15
+ }
16
+ export declare abstract class BaseLLMProvider implements LLMProvider {
17
+ readonly providerName: string;
18
+ private readonly retryConfig;
19
+ private readonly cbConfig;
20
+ private failures;
21
+ private lastFailure;
22
+ constructor(config: BaseLLMProviderConfig);
23
+ protected abstract doComplete(params: CompletionParams): Promise<CompletionResult>;
24
+ protected abstract doStream(params: CompletionParams, opts?: StreamOptions): AsyncGenerator<StreamChunk>;
25
+ complete(params: CompletionParams): Promise<CompletionResult>;
26
+ stream(params: CompletionParams, opts?: StreamOptions): AsyncGenerator<StreamChunk>;
27
+ private checkCircuit;
28
+ private withRetry;
29
+ private backoff;
30
+ }
31
+ //# sourceMappingURL=base-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-provider.d.ts","sourceRoot":"","sources":["../src/base-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,aAAa,EACd,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7B,cAAc,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAChD;AAKD,8BAAsB,eAAgB,YAAW,WAAW;IAC1D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAChD,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,WAAW,CAAK;gBAEZ,MAAM,EAAE,qBAAqB;IAMzC,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAClF,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,cAAc,CAAC,WAAW,CAAC;IAElG,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAK5D,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,cAAc,CAAC,WAAW,CAAC;IAK1F,OAAO,CAAC,YAAY;YASN,SAAS;IAsBvB,OAAO,CAAC,OAAO;CAKhB"}
@@ -0,0 +1,63 @@
1
+ import { LLMError, LLMRateLimitError } from '@loom-node/core';
2
+ const DEFAULT_RETRY = { maxRetries: 3, baseDelayMs: 1000, maxDelayMs: 30_000 };
3
+ const DEFAULT_CB = { failureThreshold: 5, resetTimeMs: 60_000 };
4
+ export class BaseLLMProvider {
5
+ providerName;
6
+ retryConfig;
7
+ cbConfig;
8
+ failures = 0;
9
+ lastFailure = 0;
10
+ constructor(config) {
11
+ this.providerName = config.providerName;
12
+ this.retryConfig = { ...DEFAULT_RETRY, ...config.retry };
13
+ this.cbConfig = { ...DEFAULT_CB, ...config.circuitBreaker };
14
+ }
15
+ async complete(params) {
16
+ this.checkCircuit();
17
+ return this.withRetry(() => this.doComplete(params));
18
+ }
19
+ async *stream(params, opts) {
20
+ this.checkCircuit();
21
+ yield* this.doStream(params, opts);
22
+ }
23
+ checkCircuit() {
24
+ if (this.failures >= this.cbConfig.failureThreshold) {
25
+ if (Date.now() - this.lastFailure < this.cbConfig.resetTimeMs) {
26
+ throw new LLMError('LLM_CIRCUIT_OPEN', this.providerName, 'Circuit breaker open');
27
+ }
28
+ this.failures = 0;
29
+ }
30
+ }
31
+ async withRetry(fn) {
32
+ let lastErr;
33
+ for (let i = 0; i <= this.retryConfig.maxRetries; i++) {
34
+ try {
35
+ const result = await fn();
36
+ this.failures = 0;
37
+ return result;
38
+ }
39
+ catch (err) {
40
+ lastErr = err instanceof Error ? err : new Error(String(err));
41
+ this.failures++;
42
+ this.lastFailure = Date.now();
43
+ if (i === this.retryConfig.maxRetries)
44
+ break;
45
+ const rateErr = lastErr;
46
+ const delay = (lastErr instanceof LLMRateLimitError && rateErr.retryAfterMs)
47
+ ? rateErr.retryAfterMs
48
+ : this.backoff(i);
49
+ await sleep(delay);
50
+ }
51
+ }
52
+ throw lastErr;
53
+ }
54
+ backoff(attempt) {
55
+ const delay = this.retryConfig.baseDelayMs * 2 ** attempt;
56
+ const jitter = Math.random() * delay * 0.1;
57
+ return Math.min(delay + jitter, this.retryConfig.maxDelayMs);
58
+ }
59
+ }
60
+ function sleep(ms) {
61
+ return new Promise((r) => setTimeout(r, ms));
62
+ }
63
+ //# sourceMappingURL=base-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-provider.js","sourceRoot":"","sources":["../src/base-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { CompletionParams, CompletionResult, StreamChunk, StreamOptions } from '@loom-node/core';
2
+ import { BaseLLMProvider } from '../base-provider.js';
3
+ import type { BaseLLMProviderConfig } from '../base-provider.js';
4
+ export interface GeminiProviderConfig extends Omit<BaseLLMProviderConfig, 'providerName'> {
5
+ apiKey: string;
6
+ model?: string;
7
+ baseUrl?: string;
8
+ }
9
+ export declare class GeminiProvider extends BaseLLMProvider {
10
+ private readonly apiKey;
11
+ private readonly model;
12
+ private readonly baseUrl;
13
+ constructor(config: GeminiProviderConfig);
14
+ private buildBody;
15
+ private post;
16
+ protected doComplete(params: CompletionParams): Promise<CompletionResult>;
17
+ private parseResponse;
18
+ protected doStream(params: CompletionParams, opts?: StreamOptions): AsyncGenerator<StreamChunk>;
19
+ private parseSSE;
20
+ }
21
+ //# sourceMappingURL=gemini-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-provider.d.ts","sourceRoot":"","sources":["../../src/google/gemini-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,EAAE,aAAa,EAC3B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAGjE,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,qBAAqB,EAAE,cAAc,CAAC;IACvF,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,cAAe,SAAQ,eAAe;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,oBAAoB;IAOxC,OAAO,CAAC,SAAS;YAYH,IAAI;cAiBF,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAM/E,OAAO,CAAC,aAAa;cA6BJ,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,cAAc,CAAC,WAAW,CAAC;YAKvF,QAAQ;CA8CxB"}
@@ -0,0 +1,135 @@
1
+ import { LLMError, LLMRateLimitError, LLMAuthError } from '@loom-node/core';
2
+ import { BaseLLMProvider } from '../base-provider.js';
3
+ import { toGeminiContents, toGeminiTools } from './mappers.js';
4
+ export class GeminiProvider extends BaseLLMProvider {
5
+ apiKey;
6
+ model;
7
+ baseUrl;
8
+ constructor(config) {
9
+ super({ ...config, providerName: 'gemini' });
10
+ this.apiKey = config.apiKey;
11
+ this.model = config.model ?? 'gemini-2.0-flash';
12
+ this.baseUrl = config.baseUrl ?? 'https://generativelanguage.googleapis.com/v1beta';
13
+ }
14
+ buildBody(params) {
15
+ const { systemInstruction, contents } = toGeminiContents(params.messages);
16
+ const body = { contents };
17
+ if (systemInstruction)
18
+ body.systemInstruction = systemInstruction;
19
+ if (params.tools?.length)
20
+ body.tools = toGeminiTools(params.tools);
21
+ const config = {};
22
+ if (params.temperature != null)
23
+ config.temperature = params.temperature;
24
+ if (params.maxTokens != null)
25
+ config.maxOutputTokens = params.maxTokens;
26
+ if (Object.keys(config).length)
27
+ body.generationConfig = config;
28
+ return body;
29
+ }
30
+ async post(endpoint, body, signal) {
31
+ const url = `${this.baseUrl}/models/${this.model}:${endpoint}?key=${this.apiKey}`;
32
+ const res = await fetch(url, {
33
+ method: 'POST',
34
+ headers: { 'Content-Type': 'application/json' },
35
+ body: JSON.stringify(body),
36
+ signal,
37
+ });
38
+ if (!res.ok) {
39
+ if (res.status === 401 || res.status === 403)
40
+ throw new LLMAuthError('gemini');
41
+ if (res.status === 429)
42
+ throw new LLMRateLimitError('gemini');
43
+ const text = await res.text().catch(() => '');
44
+ throw new LLMError('LLM_ERROR', 'gemini', `Gemini API error ${res.status}: ${text}`, res.status);
45
+ }
46
+ return res;
47
+ }
48
+ async doComplete(params) {
49
+ const res = await this.post('generateContent', this.buildBody(params));
50
+ const json = await res.json();
51
+ return this.parseResponse(json);
52
+ }
53
+ parseResponse(json) {
54
+ const candidate = json.candidates?.[0];
55
+ let content = '';
56
+ const toolCalls = [];
57
+ if (candidate?.content?.parts) {
58
+ for (const part of candidate.content.parts) {
59
+ if (part.text)
60
+ content += part.text;
61
+ if (part.functionCall) {
62
+ toolCalls.push({
63
+ id: `call_${Math.random().toString(36).slice(2, 10)}`,
64
+ name: part.functionCall.name,
65
+ arguments: JSON.stringify(part.functionCall.args),
66
+ });
67
+ }
68
+ }
69
+ }
70
+ const reason = candidate?.finishReason;
71
+ return {
72
+ content,
73
+ toolCalls: toolCalls.length ? toolCalls : undefined,
74
+ finishReason: reason === 'MAX_TOKENS' ? 'length' : toolCalls.length ? 'tool_calls' : 'stop',
75
+ usage: {
76
+ promptTokens: json.usageMetadata?.promptTokenCount ?? 0,
77
+ completionTokens: json.usageMetadata?.candidatesTokenCount ?? 0,
78
+ totalTokens: json.usageMetadata?.totalTokenCount ?? 0,
79
+ },
80
+ };
81
+ }
82
+ async *doStream(params, opts) {
83
+ const res = await this.post('streamGenerateContent?alt=sse', this.buildBody(params), opts?.signal);
84
+ yield* this.parseSSE(res);
85
+ }
86
+ async *parseSSE(res) {
87
+ const reader = res.body.getReader();
88
+ const decoder = new TextDecoder();
89
+ let buf = '';
90
+ try {
91
+ while (true) {
92
+ const { done, value } = await reader.read();
93
+ if (done)
94
+ break;
95
+ buf += decoder.decode(value, { stream: true });
96
+ const lines = buf.split('\n');
97
+ buf = lines.pop();
98
+ for (const line of lines) {
99
+ if (!line.startsWith('data: '))
100
+ continue;
101
+ const chunk = JSON.parse(line.slice(6));
102
+ const parts = chunk.candidates?.[0]?.content?.parts;
103
+ if (parts) {
104
+ for (const part of parts) {
105
+ if (part.text)
106
+ yield { type: 'text', content: part.text };
107
+ if (part.functionCall) {
108
+ yield {
109
+ type: 'tool-call-delta',
110
+ toolCallId: `call_${Math.random().toString(36).slice(2, 10)}`,
111
+ name: part.functionCall.name,
112
+ content: JSON.stringify(part.functionCall.args),
113
+ };
114
+ }
115
+ }
116
+ }
117
+ if (chunk.usageMetadata) {
118
+ yield {
119
+ type: 'usage',
120
+ usage: {
121
+ promptTokens: chunk.usageMetadata.promptTokenCount,
122
+ completionTokens: chunk.usageMetadata.candidatesTokenCount,
123
+ totalTokens: chunk.usageMetadata.totalTokenCount,
124
+ },
125
+ };
126
+ }
127
+ }
128
+ }
129
+ }
130
+ finally {
131
+ reader.releaseLock();
132
+ }
133
+ }
134
+ }
135
+ //# sourceMappingURL=gemini-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-provider.js","sourceRoot":"","sources":["../../src/google/gemini-provider.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAQ/D,MAAM,OAAO,cAAe,SAAQ,eAAe;IAChC,MAAM,CAAS;IACf,KAAK,CAAS;IACd,OAAO,CAAS;IAEjC,YAAY,MAA4B;QACtC,KAAK,CAAC,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,kBAAkB,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,kDAAkD,CAAC;IACtF,CAAC;IAEO,SAAS,CAAC,MAAwB;QACxC,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1E,MAAM,IAAI,GAA4B,EAAE,QAAQ,EAAE,CAAC;QACnD,IAAI,iBAAiB;YAAE,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAClE,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM;YAAE,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnE,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,IAAI,MAAM,CAAC,WAAW,IAAI,IAAI;YAAE,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QACxE,IAAI,MAAM,CAAC,SAAS,IAAI,IAAI;YAAE,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,SAAS,CAAC;QACxE,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM;YAAE,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC;QAC/D,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,QAAgB,EAAE,IAAa,EAAE,MAAoB;QACtE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,WAAW,IAAI,CAAC,KAAK,IAAI,QAAQ,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QAClF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAC1B,MAAM;SACP,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;gBAAE,MAAM,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;YAC/E,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;gBAAE,MAAM,IAAI,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAC9D,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,QAAQ,EAAE,oBAAoB,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QACnG,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAES,KAAK,CAAC,UAAU,CAAC,MAAwB;QACjD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QACvE,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAoB,CAAC;QAChD,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAEO,aAAa,CAAC,IAAoB;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;QACvC,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,MAAM,SAAS,GAAe,EAAE,CAAC;QACjC,IAAI,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAC9B,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBAC3C,IAAI,IAAI,CAAC,IAAI;oBAAE,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC;gBACpC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;oBACtB,SAAS,CAAC,IAAI,CAAC;wBACb,EAAE,EAAE,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;wBACrD,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI;wBAC5B,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;qBAClD,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,SAAS,EAAE,YAAY,CAAC;QACvC,OAAO;YACL,OAAO;YACP,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YACnD,YAAY,EAAE,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM;YAC3F,KAAK,EAAE;gBACL,YAAY,EAAE,IAAI,CAAC,aAAa,EAAE,gBAAgB,IAAI,CAAC;gBACvD,gBAAgB,EAAE,IAAI,CAAC,aAAa,EAAE,oBAAoB,IAAI,CAAC;gBAC/D,WAAW,EAAE,IAAI,CAAC,aAAa,EAAE,eAAe,IAAI,CAAC;aACtD;SACF,CAAC;IACJ,CAAC;IAES,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAwB,EAAE,IAAoB;QACtE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,+BAA+B,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QACnG,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAEO,KAAK,CAAC,CAAC,QAAQ,CAAC,GAAa;QACnC,MAAM,MAAM,GAAG,GAAG,CAAC,IAAK,CAAC,SAAS,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,IAAI,GAAG,GAAG,EAAE,CAAC;QAEb,IAAI,CAAC;YACH,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5C,IAAI,IAAI;oBAAE,MAAM;gBAChB,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC9B,GAAG,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;gBAEnB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;wBAAE,SAAS;oBACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAmB,CAAC;oBAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC;oBACpD,IAAI,KAAK,EAAE,CAAC;wBACV,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;4BACzB,IAAI,IAAI,CAAC,IAAI;gCAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;4BAC1D,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gCACtB,MAAM;oCACJ,IAAI,EAAE,iBAAiB;oCACvB,UAAU,EAAE,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;oCAC7D,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI;oCAC5B,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;iCAChD,CAAC;4BACJ,CAAC;wBACH,CAAC;oBACH,CAAC;oBACD,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;wBACxB,MAAM;4BACJ,IAAI,EAAE,OAAO;4BACb,KAAK,EAAE;gCACL,YAAY,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAgB;gCAClD,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,oBAAoB;gCAC1D,WAAW,EAAE,KAAK,CAAC,aAAa,CAAC,eAAe;6BACjD;yBACF,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,27 @@
1
+ import type { Message, JsonToolDefinition } from '@loom-node/core';
2
+ export declare function toGeminiContents(messages: Message[]): {
3
+ systemInstruction?: GeminiContent;
4
+ contents: GeminiContent[];
5
+ };
6
+ export declare function toGeminiTools(tools: JsonToolDefinition[]): GeminiToolDecl[];
7
+ export type GeminiPart = {
8
+ text?: string;
9
+ inlineData?: unknown;
10
+ functionCall?: {
11
+ name: string;
12
+ args: unknown;
13
+ };
14
+ functionResponse?: unknown;
15
+ };
16
+ export type GeminiContent = {
17
+ role: string;
18
+ parts: GeminiPart[];
19
+ };
20
+ export type GeminiToolDecl = {
21
+ functionDeclarations: {
22
+ name: string;
23
+ description: string;
24
+ parameters: unknown;
25
+ }[];
26
+ };
27
+ //# sourceMappingURL=mappers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mappers.d.ts","sourceRoot":"","sources":["../../src/google/mappers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAe,MAAM,iBAAiB,CAAC;AAEhF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG;IAAE,iBAAiB,CAAC,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE,CAuCtH;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG,cAAc,EAAE,CAE3E;AAED,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAC7I,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC;AAClE,MAAM,MAAM,cAAc,GAAG;IAAE,oBAAoB,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC"}
@@ -0,0 +1,44 @@
1
+ export function toGeminiContents(messages) {
2
+ let systemInstruction;
3
+ const contents = [];
4
+ for (const msg of messages) {
5
+ switch (msg.role) {
6
+ case 'system':
7
+ systemInstruction = { role: 'user', parts: [{ text: msg.content }] };
8
+ break;
9
+ case 'user':
10
+ contents.push({
11
+ role: 'user',
12
+ parts: typeof msg.content === 'string'
13
+ ? [{ text: msg.content }]
14
+ : msg.content.map((p) => p.type === 'text'
15
+ ? { text: p.text }
16
+ : { inlineData: { mimeType: 'image/jpeg', data: p.imageUrl } }),
17
+ });
18
+ break;
19
+ case 'assistant': {
20
+ const parts = [];
21
+ if (msg.content)
22
+ parts.push({ text: msg.content });
23
+ if (msg.toolCalls?.length) {
24
+ for (const tc of msg.toolCalls) {
25
+ parts.push({ functionCall: { name: tc.name, args: JSON.parse(tc.arguments) } });
26
+ }
27
+ }
28
+ contents.push({ role: 'model', parts });
29
+ break;
30
+ }
31
+ case 'tool':
32
+ contents.push({
33
+ role: 'function',
34
+ parts: [{ functionResponse: { name: '', response: { result: msg.content } } }],
35
+ });
36
+ break;
37
+ }
38
+ }
39
+ return { systemInstruction, contents };
40
+ }
41
+ export function toGeminiTools(tools) {
42
+ return [{ functionDeclarations: tools.map(t => ({ name: t.name, description: t.description, parameters: t.parameters })) }];
43
+ }
44
+ //# sourceMappingURL=mappers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mappers.js","sourceRoot":"","sources":["../../src/google/mappers.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAAC,QAAmB;IAClD,IAAI,iBAA4C,CAAC;IACjD,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,QAAQ;gBACX,iBAAiB,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;gBACrE,MAAM;YACR,KAAK,MAAM;gBACT,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,MAAM;oBACZ,KAAK,EAAE,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;wBACpC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;wBACzB,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAc,EAAE,EAAE,CACjC,CAAC,CAAC,IAAI,KAAK,MAAM;4BACf,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAK,EAAE;4BACnB,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,QAAS,EAAE,EAAE,CAAC;iBACzE,CAAC,CAAC;gBACH,MAAM;YACR,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,MAAM,KAAK,GAAiB,EAAE,CAAC;gBAC/B,IAAI,GAAG,CAAC,OAAO;oBAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBACnD,IAAI,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;oBAC1B,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;wBAC/B,KAAK,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;oBAClF,CAAC;gBACH,CAAC;gBACD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;gBACxC,MAAM;YACR,CAAC;YACD,KAAK,MAAM;gBACT,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,UAAU;oBAChB,KAAK,EAAE,CAAC,EAAE,gBAAgB,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,EAAE,CAAC;iBAC/E,CAAC,CAAC;gBACH,MAAM;QACV,CAAC;IACH,CAAC;IACD,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAA2B;IACvD,OAAO,CAAC,EAAE,oBAAoB,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAC9H,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { BaseLLMProvider } from './base-provider.js';
2
+ export type { BaseLLMProviderConfig, RetryConfig, CircuitBreakerConfig } from './base-provider.js';
3
+ export { OpenAIProvider } from './openai/openai-provider.js';
4
+ export type { OpenAIProviderConfig } from './openai/openai-provider.js';
5
+ export { OpenAIEmbeddingProvider } from './openai/openai-embedding.js';
6
+ export type { OpenAIEmbeddingConfig } from './openai/openai-embedding.js';
7
+ export { AnthropicProvider } from './anthropic/anthropic-provider.js';
8
+ export type { AnthropicProviderConfig } from './anthropic/anthropic-provider.js';
9
+ export { GeminiProvider } from './google/gemini-provider.js';
10
+ export type { GeminiProviderConfig } from './google/gemini-provider.js';
11
+ export { createDeepSeek, createQwen, createZhipu, createMoonshot, createBaichuan, createYi, createDoubao } from './presets.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,YAAY,EAAE,qBAAqB,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAGnG,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,YAAY,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,YAAY,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAG1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,YAAY,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAGjF,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,YAAY,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGxE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ export { BaseLLMProvider } from './base-provider.js';
2
+ // OpenAI
3
+ export { OpenAIProvider } from './openai/openai-provider.js';
4
+ export { OpenAIEmbeddingProvider } from './openai/openai-embedding.js';
5
+ // Anthropic
6
+ export { AnthropicProvider } from './anthropic/anthropic-provider.js';
7
+ // Google Gemini
8
+ export { GeminiProvider } from './google/gemini-provider.js';
9
+ // Chinese LLM presets (OpenAI-compatible)
10
+ export { createDeepSeek, createQwen, createZhipu, createMoonshot, createBaichuan, createYi, createDoubao } from './presets.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,SAAS;AACT,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,YAAY;AACZ,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAGtE,gBAAgB;AAChB,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAG7D,0CAA0C;AAC1C,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { OpenAIProvider } from './openai-provider.js';
2
+ export type { OpenAIProviderConfig } from './openai-provider.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/openai/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { OpenAIProvider } from './openai-provider.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/openai/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { Message, JsonToolDefinition } from '@loom-node/core';
2
+ export declare function toOpenAIMessages(messages: Message[]): OpenAIMessage[];
3
+ export declare function toOpenAITools(tools: JsonToolDefinition[]): OpenAITool[];
4
+ export type OpenAIMessage = {
5
+ role: string;
6
+ content: unknown;
7
+ tool_calls?: {
8
+ id: string;
9
+ type: string;
10
+ function: {
11
+ name: string;
12
+ arguments: string;
13
+ };
14
+ }[];
15
+ tool_call_id?: string;
16
+ };
17
+ export type OpenAITool = {
18
+ type: 'function';
19
+ function: {
20
+ name: string;
21
+ description: string;
22
+ parameters: unknown;
23
+ };
24
+ };
25
+ //# sourceMappingURL=mappers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mappers.d.ts","sourceRoot":"","sources":["../../src/openai/mappers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAGnE,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAqCrE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG,UAAU,EAAE,CAKvE;AAGD,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,EAAE,CAAC;IAC3F,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC;CACtE,CAAC"}
@@ -0,0 +1,45 @@
1
+ // Convert our Message to OpenAI API format
2
+ export function toOpenAIMessages(messages) {
3
+ const result = [];
4
+ for (const msg of messages) {
5
+ switch (msg.role) {
6
+ case 'system':
7
+ result.push({ role: 'system', content: msg.content });
8
+ break;
9
+ case 'user':
10
+ result.push({
11
+ role: 'user',
12
+ content: typeof msg.content === 'string'
13
+ ? msg.content
14
+ : msg.content.map((p) => p.type === 'text'
15
+ ? { type: 'text', text: p.text }
16
+ : { type: 'image_url', image_url: { url: p.imageUrl } }),
17
+ });
18
+ break;
19
+ case 'assistant':
20
+ result.push({
21
+ role: 'assistant',
22
+ content: msg.content,
23
+ ...(msg.toolCalls?.length ? {
24
+ tool_calls: msg.toolCalls.map((tc) => ({
25
+ id: tc.id,
26
+ type: 'function',
27
+ function: { name: tc.name, arguments: tc.arguments },
28
+ })),
29
+ } : {}),
30
+ });
31
+ break;
32
+ case 'tool':
33
+ result.push({ role: 'tool', tool_call_id: msg.toolCallId, content: msg.content });
34
+ break;
35
+ }
36
+ }
37
+ return result;
38
+ }
39
+ export function toOpenAITools(tools) {
40
+ return tools.map((t) => ({
41
+ type: 'function',
42
+ function: { name: t.name, description: t.description, parameters: t.parameters },
43
+ }));
44
+ }
45
+ //# sourceMappingURL=mappers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mappers.js","sourceRoot":"","sources":["../../src/openai/mappers.ts"],"names":[],"mappings":"AAEA,2CAA2C;AAC3C,MAAM,UAAU,gBAAgB,CAAC,QAAmB;IAClD,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,QAAQ;gBACX,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBACtD,MAAM;YACR,KAAK,MAAM;gBACT,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;wBACtC,CAAC,CAAC,GAAG,CAAC,OAAO;wBACb,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAwC,EAAE,EAAE,CAC3D,CAAC,CAAC,IAAI,KAAK,MAAM;4BACf,CAAC,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,CAAC,IAAK,EAAE;4BAC1C,CAAC,CAAC,EAAE,IAAI,EAAE,WAAoB,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,QAAS,EAAE,EAAE,CAAC;iBAC3E,CAAC,CAAC;gBACH,MAAM;YACR,KAAK,WAAW;gBACd,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;wBAC1B,UAAU,EAAE,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAsC,EAAE,EAAE,CAAC,CAAC;4BACzE,EAAE,EAAE,EAAE,CAAC,EAAE;4BACT,IAAI,EAAE,UAAmB;4BACzB,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE;yBACrD,CAAC,CAAC;qBACJ,CAAC,CAAC,CAAC,EAAE,CAAC;iBACR,CAAC,CAAC;gBACH,MAAM;YACR,KAAK,MAAM;gBACT,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBAClF,MAAM;QACV,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAA2B;IACvD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvB,IAAI,EAAE,UAAmB;QACzB,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE;KACjF,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { EmbeddingProvider } from '@loom-node/core';
2
+ export interface OpenAIEmbeddingConfig {
3
+ apiKey: string;
4
+ model?: string;
5
+ baseUrl?: string;
6
+ dimensions?: number;
7
+ }
8
+ export declare class OpenAIEmbeddingProvider implements EmbeddingProvider {
9
+ private readonly apiKey;
10
+ private readonly model;
11
+ private readonly baseUrl;
12
+ readonly dimensions: number;
13
+ constructor(config: OpenAIEmbeddingConfig);
14
+ embed(text: string): Promise<number[]>;
15
+ embedBatch(texts: string[]): Promise<number[][]>;
16
+ }
17
+ //# sourceMappingURL=openai-embedding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-embedding.d.ts","sourceRoot":"","sources":["../../src/openai/openai-embedding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,uBAAwB,YAAW,iBAAiB;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,MAAM,EAAE,qBAAqB;IAOnC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAKtC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;CAUvD"}
@@ -0,0 +1,28 @@
1
+ export class OpenAIEmbeddingProvider {
2
+ apiKey;
3
+ model;
4
+ baseUrl;
5
+ dimensions;
6
+ constructor(config) {
7
+ this.apiKey = config.apiKey;
8
+ this.model = config.model ?? 'text-embedding-3-small';
9
+ this.baseUrl = config.baseUrl ?? 'https://api.openai.com/v1';
10
+ this.dimensions = config.dimensions ?? 1536;
11
+ }
12
+ async embed(text) {
13
+ const [result] = await this.embedBatch([text]);
14
+ return result;
15
+ }
16
+ async embedBatch(texts) {
17
+ const res = await fetch(`${this.baseUrl}/embeddings`, {
18
+ method: 'POST',
19
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${this.apiKey}` },
20
+ body: JSON.stringify({ model: this.model, input: texts }),
21
+ });
22
+ if (!res.ok)
23
+ throw new Error(`Embedding API error ${res.status}: ${await res.text()}`);
24
+ const json = await res.json();
25
+ return json.data.map(d => d.embedding);
26
+ }
27
+ }
28
+ //# sourceMappingURL=openai-embedding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-embedding.js","sourceRoot":"","sources":["../../src/openai/openai-embedding.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,uBAAuB;IACjB,MAAM,CAAS;IACf,KAAK,CAAS;IACd,OAAO,CAAS;IACxB,UAAU,CAAS;IAE5B,YAAY,MAA6B;QACvC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,wBAAwB,CAAC;QACtD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,2BAA2B,CAAC;QAC7D,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,IAAI,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAY;QACtB,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,KAAe;QAC9B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,aAAa,EAAE;YACpD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE,EAAE;YACvF,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;SAC1D,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,CAAC,MAAM,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACvF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAyC,CAAC;QACrE,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ import type { CompletionParams, CompletionResult, StreamChunk, StreamOptions } from '@loom-node/core';
2
+ import { BaseLLMProvider } from '../base-provider.js';
3
+ import type { BaseLLMProviderConfig } from '../base-provider.js';
4
+ export interface OpenAIProviderConfig extends Omit<BaseLLMProviderConfig, 'providerName'> {
5
+ apiKey: string;
6
+ model?: string;
7
+ baseUrl?: string;
8
+ }
9
+ export declare class OpenAIProvider extends BaseLLMProvider {
10
+ private readonly apiKey;
11
+ private readonly model;
12
+ private readonly baseUrl;
13
+ constructor(config: OpenAIProviderConfig);
14
+ private buildBody;
15
+ private post;
16
+ protected doComplete(params: CompletionParams): Promise<CompletionResult>;
17
+ protected doStream(params: CompletionParams, opts?: StreamOptions): AsyncGenerator<StreamChunk>;
18
+ private parseSSE;
19
+ }
20
+ //# sourceMappingURL=openai-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-provider.d.ts","sourceRoot":"","sources":["../../src/openai/openai-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,aAAa,EAEd,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAGjE,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,qBAAqB,EAAE,cAAc,CAAC;IACvF,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,cAAe,SAAQ,eAAe;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,oBAAoB;IAOxC,OAAO,CAAC,SAAS;YAaH,IAAI;cAsBF,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;cAqB9D,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,cAAc,CAAC,WAAW,CAAC;YAKvF,QAAQ;CA6CxB"}
@@ -0,0 +1,121 @@
1
+ import { LLMError, LLMRateLimitError, LLMAuthError } from '@loom-node/core';
2
+ import { BaseLLMProvider } from '../base-provider.js';
3
+ import { toOpenAIMessages, toOpenAITools } from './mappers.js';
4
+ export class OpenAIProvider extends BaseLLMProvider {
5
+ apiKey;
6
+ model;
7
+ baseUrl;
8
+ constructor(config) {
9
+ super({ ...config, providerName: 'openai' });
10
+ this.apiKey = config.apiKey;
11
+ this.model = config.model ?? 'gpt-4o';
12
+ this.baseUrl = config.baseUrl ?? 'https://api.openai.com/v1';
13
+ }
14
+ buildBody(params, stream) {
15
+ const body = {
16
+ model: this.model,
17
+ messages: toOpenAIMessages(params.messages),
18
+ stream,
19
+ };
20
+ if (params.tools?.length)
21
+ body.tools = toOpenAITools(params.tools);
22
+ if (params.temperature != null)
23
+ body.temperature = params.temperature;
24
+ if (params.maxTokens != null)
25
+ body.max_tokens = params.maxTokens;
26
+ if (stream)
27
+ body.stream_options = { include_usage: true };
28
+ return body;
29
+ }
30
+ async post(body, signal) {
31
+ const res = await fetch(`${this.baseUrl}/chat/completions`, {
32
+ method: 'POST',
33
+ headers: {
34
+ 'Content-Type': 'application/json',
35
+ Authorization: `Bearer ${this.apiKey}`,
36
+ },
37
+ body: JSON.stringify(body),
38
+ signal,
39
+ });
40
+ if (!res.ok) {
41
+ if (res.status === 401)
42
+ throw new LLMAuthError('openai');
43
+ if (res.status === 429) {
44
+ const retryAfter = res.headers.get('retry-after');
45
+ throw new LLMRateLimitError('openai', retryAfter ? Number(retryAfter) * 1000 : undefined);
46
+ }
47
+ const text = await res.text().catch(() => '');
48
+ throw new LLMError('LLM_ERROR', 'openai', `OpenAI API error ${res.status}: ${text}`, res.status);
49
+ }
50
+ return res;
51
+ }
52
+ async doComplete(params) {
53
+ const res = await this.post(this.buildBody(params, false));
54
+ const json = await res.json();
55
+ const choice = json.choices[0];
56
+ const toolCalls = choice.message.tool_calls?.map((tc) => ({
57
+ id: tc.id,
58
+ name: tc.function.name,
59
+ arguments: tc.function.arguments,
60
+ }));
61
+ return {
62
+ content: choice.message.content ?? '',
63
+ toolCalls,
64
+ finishReason: choice.finish_reason === 'tool_calls' ? 'tool_calls' : choice.finish_reason === 'length' ? 'length' : 'stop',
65
+ usage: {
66
+ promptTokens: json.usage?.prompt_tokens ?? 0,
67
+ completionTokens: json.usage?.completion_tokens ?? 0,
68
+ totalTokens: json.usage?.total_tokens ?? 0,
69
+ },
70
+ };
71
+ }
72
+ async *doStream(params, opts) {
73
+ const res = await this.post(this.buildBody(params, true), opts?.signal);
74
+ yield* this.parseSSE(res);
75
+ }
76
+ async *parseSSE(res) {
77
+ const reader = res.body.getReader();
78
+ const decoder = new TextDecoder();
79
+ let buf = '';
80
+ try {
81
+ while (true) {
82
+ const { done, value } = await reader.read();
83
+ if (done)
84
+ break;
85
+ buf += decoder.decode(value, { stream: true });
86
+ const lines = buf.split('\n');
87
+ buf = lines.pop();
88
+ for (const line of lines) {
89
+ if (!line.startsWith('data: ') || line === 'data: [DONE]')
90
+ continue;
91
+ const chunk = JSON.parse(line.slice(6));
92
+ const delta = chunk.choices?.[0]?.delta;
93
+ if (delta?.content) {
94
+ yield { type: 'text', content: delta.content };
95
+ }
96
+ if (delta?.tool_calls) {
97
+ for (const tc of delta.tool_calls) {
98
+ if (tc.function?.arguments) {
99
+ yield { type: 'tool-call-delta', toolCallId: tc.id ?? '', content: tc.function.arguments };
100
+ }
101
+ }
102
+ }
103
+ if (chunk.usage) {
104
+ yield {
105
+ type: 'usage',
106
+ usage: {
107
+ promptTokens: chunk.usage.prompt_tokens,
108
+ completionTokens: chunk.usage.completion_tokens,
109
+ totalTokens: chunk.usage.total_tokens,
110
+ },
111
+ };
112
+ }
113
+ }
114
+ }
115
+ }
116
+ finally {
117
+ reader.releaseLock();
118
+ }
119
+ }
120
+ }
121
+ //# sourceMappingURL=openai-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-provider.js","sourceRoot":"","sources":["../../src/openai/openai-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { OpenAIProvider } from './openai/openai-provider.js';
2
+ import type { OpenAIProviderConfig } from './openai/openai-provider.js';
3
+ type PresetConfig = Omit<OpenAIProviderConfig, 'baseUrl' | 'model'> & {
4
+ model?: string;
5
+ };
6
+ /** DeepSeek — deepseek-chat / deepseek-reasoner */
7
+ export declare function createDeepSeek(config: PresetConfig): OpenAIProvider;
8
+ /** 通义千问 Qwen (Alibaba DashScope) */
9
+ export declare function createQwen(config: PresetConfig): OpenAIProvider;
10
+ /** 智谱 GLM (Zhipu AI) */
11
+ export declare function createZhipu(config: PresetConfig): OpenAIProvider;
12
+ /** 月之暗面 Moonshot (Kimi) */
13
+ export declare function createMoonshot(config: PresetConfig): OpenAIProvider;
14
+ /** 百川 Baichuan */
15
+ export declare function createBaichuan(config: PresetConfig): OpenAIProvider;
16
+ /** 零一万物 Yi */
17
+ export declare function createYi(config: PresetConfig): OpenAIProvider;
18
+ /** 豆包 Doubao (ByteDance Volcano Ark) */
19
+ export declare function createDoubao(config: PresetConfig): OpenAIProvider;
20
+ export {};
21
+ //# sourceMappingURL=presets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE,KAAK,YAAY,GAAG,IAAI,CAAC,oBAAoB,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzF,mDAAmD;AACnD,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAEnE;AAED,oCAAoC;AACpC,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAE/D;AAED,wBAAwB;AACxB,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAEhE;AAED,2BAA2B;AAC3B,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAEnE;AAED,kBAAkB;AAClB,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAEnE;AAED,cAAc;AACd,wBAAgB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAE7D;AAED,wCAAwC;AACxC,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAEjE"}
@@ -0,0 +1,30 @@
1
+ import { OpenAIProvider } from './openai/openai-provider.js';
2
+ /** DeepSeek — deepseek-chat / deepseek-reasoner */
3
+ export function createDeepSeek(config) {
4
+ return new OpenAIProvider({ ...config, model: config.model ?? 'deepseek-chat', baseUrl: 'https://api.deepseek.com/v1' });
5
+ }
6
+ /** 通义千问 Qwen (Alibaba DashScope) */
7
+ export function createQwen(config) {
8
+ return new OpenAIProvider({ ...config, model: config.model ?? 'qwen-plus', baseUrl: 'https://dashscope.aliyuncs.com/compatible-mode/v1' });
9
+ }
10
+ /** 智谱 GLM (Zhipu AI) */
11
+ export function createZhipu(config) {
12
+ return new OpenAIProvider({ ...config, model: config.model ?? 'glm-4-flash', baseUrl: 'https://open.bigmodel.cn/api/paas/v4' });
13
+ }
14
+ /** 月之暗面 Moonshot (Kimi) */
15
+ export function createMoonshot(config) {
16
+ return new OpenAIProvider({ ...config, model: config.model ?? 'moonshot-v1-8k', baseUrl: 'https://api.moonshot.cn/v1' });
17
+ }
18
+ /** 百川 Baichuan */
19
+ export function createBaichuan(config) {
20
+ return new OpenAIProvider({ ...config, model: config.model ?? 'Baichuan4', baseUrl: 'https://api.baichuan-ai.com/v1' });
21
+ }
22
+ /** 零一万物 Yi */
23
+ export function createYi(config) {
24
+ return new OpenAIProvider({ ...config, model: config.model ?? 'yi-large', baseUrl: 'https://api.lingyiwanwu.com/v1' });
25
+ }
26
+ /** 豆包 Doubao (ByteDance Volcano Ark) */
27
+ export function createDoubao(config) {
28
+ return new OpenAIProvider({ ...config, model: config.model ?? 'doubao-pro-4k', baseUrl: 'https://ark.cn-beijing.volces.com/api/v3' });
29
+ }
30
+ //# sourceMappingURL=presets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presets.js","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAK7D,mDAAmD;AACnD,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,OAAO,IAAI,cAAc,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,eAAe,EAAE,OAAO,EAAE,6BAA6B,EAAE,CAAC,CAAC;AAC3H,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,UAAU,CAAC,MAAoB;IAC7C,OAAO,IAAI,cAAc,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,WAAW,EAAE,OAAO,EAAE,mDAAmD,EAAE,CAAC,CAAC;AAC7I,CAAC;AAED,wBAAwB;AACxB,MAAM,UAAU,WAAW,CAAC,MAAoB;IAC9C,OAAO,IAAI,cAAc,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,aAAa,EAAE,OAAO,EAAE,sCAAsC,EAAE,CAAC,CAAC;AAClI,CAAC;AAED,2BAA2B;AAC3B,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,OAAO,IAAI,cAAc,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,gBAAgB,EAAE,OAAO,EAAE,4BAA4B,EAAE,CAAC,CAAC;AAC3H,CAAC;AAED,kBAAkB;AAClB,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,OAAO,IAAI,cAAc,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,WAAW,EAAE,OAAO,EAAE,gCAAgC,EAAE,CAAC,CAAC;AAC1H,CAAC;AAED,cAAc;AACd,MAAM,UAAU,QAAQ,CAAC,MAAoB;IAC3C,OAAO,IAAI,cAAc,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,UAAU,EAAE,OAAO,EAAE,gCAAgC,EAAE,CAAC,CAAC;AACzH,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,YAAY,CAAC,MAAoB;IAC/C,OAAO,IAAI,cAAc,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,eAAe,EAAE,OAAO,EAAE,0CAA0C,EAAE,CAAC,CAAC;AACxI,CAAC"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@loom-node/providers",
3
+ "version": "0.1.0",
4
+ "description": "LLM providers for Loom-Node - OpenAI, Anthropic, Gemini, and more",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "license": "MIT",
21
+ "dependencies": {
22
+ "@loom-node/core": "0.1.0"
23
+ },
24
+ "devDependencies": {
25
+ "typescript": "^5.5.0"
26
+ },
27
+ "scripts": {
28
+ "build": "tsc -b",
29
+ "clean": "rm -rf dist .tsbuildinfo"
30
+ }
31
+ }