@mce-bt/microagents-completion 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,13 @@
1
+ import type { CompletionAdapter, CompletionRequest, CompletionResponse, CompletionChunk, ProviderConfig } from './types.js';
2
+ /**
3
+ * Anthropic-native adapter using the Anthropic SDK.
4
+ */
5
+ export declare class AnthropicAdapter implements CompletionAdapter {
6
+ readonly provider = "anthropic";
7
+ private client;
8
+ private defaultModel;
9
+ constructor(config: ProviderConfig);
10
+ complete(request: CompletionRequest): Promise<CompletionResponse>;
11
+ stream(request: CompletionRequest): AsyncIterable<CompletionChunk>;
12
+ }
13
+ //# sourceMappingURL=anthropic-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-adapter.d.ts","sourceRoot":"","sources":["../src/anthropic-adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,cAAc,EAGf,MAAM,YAAY,CAAC;AAgCpB;;GAEG;AACH,qBAAa,gBAAiB,YAAW,iBAAiB;IACxD,QAAQ,CAAC,QAAQ,eAAe;IAChC,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,YAAY,CAAS;gBAEjB,MAAM,EAAE,cAAc;IAiB5B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAkEhE,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,aAAa,CAAC,eAAe,CAAC;CA4D1E"}
@@ -0,0 +1,170 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import { extractText } from './types.js';
3
+ /**
4
+ * Convert MessageContent to Anthropic's content block format.
5
+ */
6
+ function toAnthropicContent(content) {
7
+ if (typeof content === 'string')
8
+ return content;
9
+ return content.map((part) => {
10
+ switch (part.type) {
11
+ case 'text':
12
+ return { type: 'text', text: part.text };
13
+ case 'image':
14
+ return {
15
+ type: 'image',
16
+ source: {
17
+ type: 'base64',
18
+ media_type: part.mimeType,
19
+ data: part.data,
20
+ },
21
+ };
22
+ case 'image_url':
23
+ return { type: 'text', text: `[Image URL: ${part.url}]` };
24
+ case 'file':
25
+ return { type: 'text', text: `[File: ${part.name} (${part.mimeType})]` };
26
+ case 'audio':
27
+ return { type: 'text', text: `[Audio content (${part.mimeType})]` };
28
+ }
29
+ });
30
+ }
31
+ /**
32
+ * Anthropic-native adapter using the Anthropic SDK.
33
+ */
34
+ export class AnthropicAdapter {
35
+ provider = 'anthropic';
36
+ client;
37
+ defaultModel;
38
+ constructor(config) {
39
+ this.defaultModel = config.model;
40
+ // `||` not `??`: an empty string from a ${VAR:-} yaml default means "unset"
41
+ const apiKey = config.apiKey || process.env.ANTHROPIC_API_KEY;
42
+ if (!apiKey) {
43
+ throw new Error('Missing API key for provider "anthropic" — set ANTHROPIC_API_KEY (preferred) or pass apiKey in the provider config');
44
+ }
45
+ this.client = new Anthropic({
46
+ apiKey,
47
+ ...(config.baseURL ? { baseURL: config.baseURL } : {}),
48
+ });
49
+ }
50
+ async complete(request) {
51
+ // Separate system messages from conversation messages
52
+ const systemMessages = request.messages.filter((m) => m.role === 'system');
53
+ const conversationMessages = request.messages.filter((m) => m.role !== 'system');
54
+ const systemPrompt = systemMessages.map((m) => extractText(m.content)).join('\n\n');
55
+ // Map tools to Anthropic format
56
+ const tools = request.tools?.map((t) => ({
57
+ name: t.function.name,
58
+ description: t.function.description,
59
+ input_schema: t.function.parameters,
60
+ }));
61
+ const response = await this.client.messages.create({
62
+ model: request.model ?? this.defaultModel,
63
+ max_tokens: request.maxTokens ?? 4096,
64
+ ...(systemPrompt ? { system: systemPrompt } : {}),
65
+ messages: conversationMessages.map((m) => ({
66
+ role: m.role === 'tool' ? 'user' : m.role,
67
+ content: m.role === 'tool'
68
+ ? [{
69
+ type: 'tool_result',
70
+ tool_use_id: m.tool_call_id ?? '',
71
+ content: extractText(m.content),
72
+ }]
73
+ : toAnthropicContent(m.content),
74
+ })),
75
+ ...(tools && tools.length > 0 ? { tools } : {}),
76
+ ...(request.temperature !== undefined ? { temperature: request.temperature } : {}),
77
+ ...(request.stop ? { stop_sequences: request.stop } : {}),
78
+ });
79
+ // Extract text and tool use from content blocks
80
+ let textContent = '';
81
+ const toolCalls = [];
82
+ for (const block of response.content) {
83
+ if (block.type === 'text') {
84
+ textContent += block.text;
85
+ }
86
+ else if (block.type === 'tool_use') {
87
+ toolCalls.push({
88
+ id: block.id,
89
+ type: 'function',
90
+ function: {
91
+ name: block.name,
92
+ arguments: JSON.stringify(block.input),
93
+ },
94
+ });
95
+ }
96
+ }
97
+ return {
98
+ id: response.id,
99
+ content: textContent || null,
100
+ toolCalls,
101
+ usage: {
102
+ promptTokens: response.usage.input_tokens,
103
+ completionTokens: response.usage.output_tokens,
104
+ totalTokens: response.usage.input_tokens + response.usage.output_tokens,
105
+ },
106
+ model: response.model,
107
+ finishReason: response.stop_reason === 'tool_use' ? 'tool_calls' : response.stop_reason ?? 'stop',
108
+ };
109
+ }
110
+ async *stream(request) {
111
+ const systemMessages = request.messages.filter((m) => m.role === 'system');
112
+ const conversationMessages = request.messages.filter((m) => m.role !== 'system');
113
+ const systemPrompt = systemMessages.map((m) => extractText(m.content)).join('\n\n');
114
+ const tools = request.tools?.map((t) => ({
115
+ name: t.function.name,
116
+ description: t.function.description,
117
+ input_schema: t.function.parameters,
118
+ }));
119
+ const stream = this.client.messages.stream({
120
+ model: request.model ?? this.defaultModel,
121
+ max_tokens: request.maxTokens ?? 4096,
122
+ ...(systemPrompt ? { system: systemPrompt } : {}),
123
+ messages: conversationMessages.map((m) => ({
124
+ role: m.role === 'tool' ? 'user' : m.role,
125
+ content: m.role === 'tool'
126
+ ? [{
127
+ type: 'tool_result',
128
+ tool_use_id: m.tool_call_id ?? '',
129
+ content: extractText(m.content),
130
+ }]
131
+ : toAnthropicContent(m.content),
132
+ })),
133
+ ...(tools && tools.length > 0 ? { tools } : {}),
134
+ ...(request.temperature !== undefined ? { temperature: request.temperature } : {}),
135
+ ...(request.stop ? { stop_sequences: request.stop } : {}),
136
+ });
137
+ for await (const event of stream) {
138
+ if (event.type === 'content_block_delta') {
139
+ if (event.delta.type === 'text_delta') {
140
+ yield {
141
+ id: '',
142
+ delta: event.delta.text,
143
+ };
144
+ }
145
+ else if (event.delta.type === 'input_json_delta') {
146
+ yield {
147
+ id: '',
148
+ delta: '',
149
+ toolCalls: [{
150
+ id: '',
151
+ type: 'function',
152
+ function: {
153
+ name: '',
154
+ arguments: event.delta.partial_json,
155
+ },
156
+ }],
157
+ };
158
+ }
159
+ }
160
+ else if (event.type === 'message_stop') {
161
+ yield {
162
+ id: '',
163
+ delta: '',
164
+ finishReason: 'stop',
165
+ };
166
+ }
167
+ }
168
+ }
169
+ }
170
+ //# sourceMappingURL=anthropic-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-adapter.js","sourceRoot":"","sources":["../src/anthropic-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAU1C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC;;GAEG;AACH,SAAS,kBAAkB,CAAC,OAAuB;IACjD,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAEhD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAA+B,EAAE;QACvD,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;YAClB,KAAK,MAAM;gBACT,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;YAC3C,KAAK,OAAO;gBACV,OAAO;oBACL,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE;wBACN,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE,IAAI,CAAC,QAAmE;wBACpF,IAAI,EAAE,IAAI,CAAC,IAAI;qBAChB;iBACF,CAAC;YACJ,KAAK,WAAW;gBACd,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;YAC5D,KAAK,MAAM;gBACT,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;YAC3E,KAAK,OAAO;gBACV,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;QACxE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAClB,QAAQ,GAAG,WAAW,CAAC;IACxB,MAAM,CAAY;IAClB,YAAY,CAAS;IAE7B,YAAY,MAAsB;QAChC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC;QAEjC,4EAA4E;QAC5E,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC9D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,oHAAoH,CACrH,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,CAAC;YAC1B,MAAM;YACN,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvD,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAA0B;QACvC,sDAAsD;QACtD,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QAC3E,MAAM,oBAAoB,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QAEjF,MAAM,YAAY,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEpF,gCAAgC;QAChC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI;YACrB,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW;YACnC,YAAY,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAwC;SAClE,CAAC,CAAC,CAAC;QAEJ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YACjD,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY;YACzC,UAAU,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;YACrC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,QAAQ,EAAE,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACzC,IAAI,EAAE,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAe,CAAC,CAAC,CAAC,CAAC,CAAC,IAA4B;gBAC1E,OAAO,EAAE,CAAC,CAAC,IAAI,KAAK,MAAM;oBACxB,CAAC,CAAC,CAAC;4BACC,IAAI,EAAE,aAAsB;4BAC5B,WAAW,EAAE,CAAC,CAAC,YAAY,IAAI,EAAE;4BACjC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC;yBAChC,CAAC;oBACJ,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC;aAClC,CAAC,CAAC;YACH,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/C,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClF,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1D,CAAC,CAAC;QAEH,gDAAgD;QAChD,IAAI,WAAW,GAAG,EAAE,CAAC;QACrB,MAAM,SAAS,GAAoC,EAAE,CAAC;QAEtD,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC1B,WAAW,IAAI,KAAK,CAAC,IAAI,CAAC;YAC5B,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBACrC,SAAS,CAAC,IAAI,CAAC;oBACb,EAAE,EAAE,KAAK,CAAC,EAAE;oBACZ,IAAI,EAAE,UAAU;oBAChB,QAAQ,EAAE;wBACR,IAAI,EAAE,KAAK,CAAC,IAAI;wBAChB,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC;qBACvC;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO;YACL,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,OAAO,EAAE,WAAW,IAAI,IAAI;YAC5B,SAAS;YACT,KAAK,EAAE;gBACL,YAAY,EAAE,QAAQ,CAAC,KAAK,CAAC,YAAY;gBACzC,gBAAgB,EAAE,QAAQ,CAAC,KAAK,CAAC,aAAa;gBAC9C,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,aAAa;aACxE;YACD,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,YAAY,EAAE,QAAQ,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,IAAI,MAAM;SAClG,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,CAAC,MAAM,CAAC,OAA0B;QACtC,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QAC3E,MAAM,oBAAoB,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QACjF,MAAM,YAAY,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEpF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI;YACrB,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW;YACnC,YAAY,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAwC;SAClE,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YACzC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY;YACzC,UAAU,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;YACrC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,QAAQ,EAAE,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACzC,IAAI,EAAE,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAe,CAAC,CAAC,CAAC,CAAC,CAAC,IAA4B;gBAC1E,OAAO,EAAE,CAAC,CAAC,IAAI,KAAK,MAAM;oBACxB,CAAC,CAAC,CAAC;4BACC,IAAI,EAAE,aAAsB;4BAC5B,WAAW,EAAE,CAAC,CAAC,YAAY,IAAI,EAAE;4BACjC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC;yBAChC,CAAC;oBACJ,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC;aAClC,CAAC,CAAC;YACH,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/C,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClF,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1D,CAAC,CAAC;QAEH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACjC,IAAI,KAAK,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;gBACzC,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBACtC,MAAM;wBACJ,EAAE,EAAE,EAAE;wBACN,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI;qBACxB,CAAC;gBACJ,CAAC;qBAAM,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;oBACnD,MAAM;wBACJ,EAAE,EAAE,EAAE;wBACN,KAAK,EAAE,EAAE;wBACT,SAAS,EAAE,CAAC;gCACV,EAAE,EAAE,EAAE;gCACN,IAAI,EAAE,UAAU;gCAChB,QAAQ,EAAE;oCACR,IAAI,EAAE,EAAE;oCACR,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,YAAY;iCACpC;6BACF,CAAC;qBACH,CAAC;gBACJ,CAAC;YACH,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;gBACzC,MAAM;oBACJ,EAAE,EAAE,EAAE;oBACN,KAAK,EAAE,EAAE;oBACT,YAAY,EAAE,MAAM;iBACrB,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ export type { ContentPart, MessageContent, CompletionAdapter, CompletionRequest, CompletionResponse, CompletionChunk, CompletionMessage, ToolCall, ToolDefinition, TokenUsage, LLMCallRecord, EmbeddingRequest, EmbeddingResponse, ProviderConfig, } from './types.js';
2
+ export { ProviderConfigSchema, extractText } from './types.js';
3
+ export { OpenAIAdapter } from './openai-adapter.js';
4
+ export { AnthropicAdapter } from './anthropic-adapter.js';
5
+ export { CompletionManager, type CompletionManagerConfig } from './manager.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,QAAQ,EACR,cAAc,EACd,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { ProviderConfigSchema, extractText } from './types.js';
2
+ export { OpenAIAdapter } from './openai-adapter.js';
3
+ export { AnthropicAdapter } from './anthropic-adapter.js';
4
+ export { CompletionManager } from './manager.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAgC,MAAM,cAAc,CAAC"}
@@ -0,0 +1,75 @@
1
+ import type { CompletionRequest, CompletionResponse, CompletionChunk, EmbeddingResponse, ProviderConfig, TokenUsage, LLMCallRecord } from './types.js';
2
+ export interface CompletionManagerConfig {
3
+ default: ProviderConfig;
4
+ tiers?: Record<string, ProviderConfig>;
5
+ }
6
+ /**
7
+ * Completion Manager — orchestrates multiple adapters with model tiering.
8
+ *
9
+ * Usage:
10
+ * const manager = new CompletionManager(config);
11
+ * const response = await manager.complete('reasoning', messages);
12
+ * // Uses the 'reasoning' tier if configured, otherwise falls back to default.
13
+ */
14
+ export declare class CompletionManager {
15
+ private adapters;
16
+ private configs;
17
+ private totalUsage;
18
+ private callHistory;
19
+ constructor(config: CompletionManagerConfig);
20
+ private createAdapter;
21
+ private getAdapter;
22
+ /**
23
+ * Send a completion request using the specified tier (or default).
24
+ */
25
+ complete(tier: string, messages: CompletionRequest['messages'], options?: Omit<CompletionRequest, 'messages'>): Promise<CompletionResponse>;
26
+ /**
27
+ * Stream a completion request using the specified tier (or default).
28
+ */
29
+ stream(tier: string, messages: CompletionRequest['messages'], options?: Omit<CompletionRequest, 'messages'>): AsyncIterable<CompletionChunk>;
30
+ /**
31
+ * Generate embeddings using the default adapter (or specified tier).
32
+ */
33
+ embed(input: string | string[], options?: {
34
+ tier?: string;
35
+ model?: string;
36
+ }): Promise<EmbeddingResponse>;
37
+ /**
38
+ * Get total token usage across all calls.
39
+ */
40
+ getUsage(): TokenUsage;
41
+ /**
42
+ * Get per-call LLM history with model, tier, tokens, and duration.
43
+ */
44
+ getCallHistory(): LLMCallRecord[];
45
+ /**
46
+ * Get usage summary broken down by model and tier.
47
+ */
48
+ getUsageSummary(): {
49
+ total: TokenUsage;
50
+ callCount: number;
51
+ byModel: Record<string, {
52
+ promptTokens: number;
53
+ completionTokens: number;
54
+ totalTokens: number;
55
+ calls: number;
56
+ avgDurationMs: number;
57
+ }>;
58
+ byTier: Record<string, {
59
+ promptTokens: number;
60
+ completionTokens: number;
61
+ totalTokens: number;
62
+ calls: number;
63
+ }>;
64
+ };
65
+ /**
66
+ * Reset usage counters and call history.
67
+ */
68
+ resetUsage(): void;
69
+ /**
70
+ * Transcribe audio to text using the default adapter's whisper/transcription API.
71
+ * Returns null if the adapter doesn't support transcription.
72
+ */
73
+ transcribe(audio: Buffer, mimeType: string): Promise<string | null>;
74
+ }
75
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EAEf,iBAAiB,EACjB,cAAc,EACd,UAAU,EACV,aAAa,EACd,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACxC;AAED;;;;;;;GAOG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAA6C;IAC7D,OAAO,CAAC,OAAO,CAA0C;IACzD,OAAO,CAAC,UAAU,CAAwE;IAC1F,OAAO,CAAC,WAAW,CAAuB;gBAE9B,MAAM,EAAE,uBAAuB;IAY3C,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,UAAU;IAUlB;;OAEG;IACG,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,iBAAiB,CAAC,UAAU,CAAC,EACvC,OAAO,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,GAC5C,OAAO,CAAC,kBAAkB,CAAC;IA0B9B;;OAEG;IACI,MAAM,CACX,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,iBAAiB,CAAC,UAAU,CAAC,EACvC,OAAO,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,GAC5C,aAAa,CAAC,eAAe,CAAC;IAKjC;;OAEG;IACG,KAAK,CACT,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EACxB,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1C,OAAO,CAAC,iBAAiB,CAAC;IAQ7B;;OAEG;IACH,QAAQ,IAAI,UAAU;IAItB;;OAEG;IACH,cAAc,IAAI,aAAa,EAAE;IAIjC;;OAEG;IACH,eAAe,IAAI;QACjB,KAAK,EAAE,UAAU,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,YAAY,EAAE,MAAM,CAAC;YAAC,gBAAgB,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,aAAa,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACvI,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,YAAY,EAAE,MAAM,CAAC;YAAC,gBAAgB,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAChH;IA6CD;;OAEG;IACH,UAAU,IAAI,IAAI;IAKlB;;;OAGG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAK1E"}
@@ -0,0 +1,161 @@
1
+ import { OpenAIAdapter } from './openai-adapter.js';
2
+ import { AnthropicAdapter } from './anthropic-adapter.js';
3
+ /**
4
+ * Completion Manager — orchestrates multiple adapters with model tiering.
5
+ *
6
+ * Usage:
7
+ * const manager = new CompletionManager(config);
8
+ * const response = await manager.complete('reasoning', messages);
9
+ * // Uses the 'reasoning' tier if configured, otherwise falls back to default.
10
+ */
11
+ export class CompletionManager {
12
+ adapters = new Map();
13
+ configs = new Map();
14
+ totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
15
+ callHistory = [];
16
+ constructor(config) {
17
+ // Adapters are constructed lazily on first use: a missing API key must
18
+ // fail the request that needs the LLM, not the boot of an agent whose
19
+ // routes/tools never touch it.
20
+ this.configs.set('default', config.default);
21
+ if (config.tiers) {
22
+ for (const [tier, providerConfig] of Object.entries(config.tiers)) {
23
+ this.configs.set(tier, providerConfig);
24
+ }
25
+ }
26
+ }
27
+ createAdapter(config) {
28
+ switch (config.provider) {
29
+ case 'anthropic':
30
+ return new AnthropicAdapter(config);
31
+ case 'openai':
32
+ case 'openrouter':
33
+ default:
34
+ return new OpenAIAdapter(config);
35
+ }
36
+ }
37
+ getAdapter(tier) {
38
+ const key = tier && this.configs.has(tier) ? tier : 'default';
39
+ let adapter = this.adapters.get(key);
40
+ if (!adapter) {
41
+ adapter = this.createAdapter(this.configs.get(key));
42
+ this.adapters.set(key, adapter);
43
+ }
44
+ return adapter;
45
+ }
46
+ /**
47
+ * Send a completion request using the specified tier (or default).
48
+ */
49
+ async complete(tier, messages, options) {
50
+ const adapter = this.getAdapter(tier);
51
+ const start = Date.now();
52
+ const response = await adapter.complete({ messages, ...options });
53
+ const durationMs = Date.now() - start;
54
+ // Track usage
55
+ this.totalUsage.promptTokens += response.usage.promptTokens;
56
+ this.totalUsage.completionTokens += response.usage.completionTokens;
57
+ this.totalUsage.totalTokens += response.usage.totalTokens;
58
+ // Track per-call history
59
+ this.callHistory.push({
60
+ id: response.id,
61
+ model: response.model,
62
+ tier: tier ?? 'default',
63
+ promptTokens: response.usage.promptTokens,
64
+ completionTokens: response.usage.completionTokens,
65
+ totalTokens: response.usage.totalTokens,
66
+ durationMs,
67
+ timestamp: new Date().toISOString(),
68
+ });
69
+ return response;
70
+ }
71
+ /**
72
+ * Stream a completion request using the specified tier (or default).
73
+ */
74
+ async *stream(tier, messages, options) {
75
+ const adapter = this.getAdapter(tier);
76
+ yield* adapter.stream({ messages, ...options });
77
+ }
78
+ /**
79
+ * Generate embeddings using the default adapter (or specified tier).
80
+ */
81
+ async embed(input, options) {
82
+ const adapter = this.getAdapter(options?.tier);
83
+ if (!adapter.embed) {
84
+ throw new Error(`Provider "${adapter.provider}" does not support embeddings`);
85
+ }
86
+ return adapter.embed({ input, model: options?.model });
87
+ }
88
+ /**
89
+ * Get total token usage across all calls.
90
+ */
91
+ getUsage() {
92
+ return { ...this.totalUsage };
93
+ }
94
+ /**
95
+ * Get per-call LLM history with model, tier, tokens, and duration.
96
+ */
97
+ getCallHistory() {
98
+ return [...this.callHistory];
99
+ }
100
+ /**
101
+ * Get usage summary broken down by model and tier.
102
+ */
103
+ getUsageSummary() {
104
+ const byModel = {};
105
+ const byTier = {};
106
+ for (const call of this.callHistory) {
107
+ // By model
108
+ if (!byModel[call.model]) {
109
+ byModel[call.model] = { promptTokens: 0, completionTokens: 0, totalTokens: 0, calls: 0, totalDurationMs: 0 };
110
+ }
111
+ byModel[call.model].promptTokens += call.promptTokens;
112
+ byModel[call.model].completionTokens += call.completionTokens;
113
+ byModel[call.model].totalTokens += call.totalTokens;
114
+ byModel[call.model].calls += 1;
115
+ byModel[call.model].totalDurationMs += call.durationMs;
116
+ // By tier
117
+ if (!byTier[call.tier]) {
118
+ byTier[call.tier] = { promptTokens: 0, completionTokens: 0, totalTokens: 0, calls: 0 };
119
+ }
120
+ byTier[call.tier].promptTokens += call.promptTokens;
121
+ byTier[call.tier].completionTokens += call.completionTokens;
122
+ byTier[call.tier].totalTokens += call.totalTokens;
123
+ byTier[call.tier].calls += 1;
124
+ }
125
+ // Convert totalDurationMs to avgDurationMs
126
+ const byModelResult = {};
127
+ for (const [model, data] of Object.entries(byModel)) {
128
+ byModelResult[model] = {
129
+ promptTokens: data.promptTokens,
130
+ completionTokens: data.completionTokens,
131
+ totalTokens: data.totalTokens,
132
+ calls: data.calls,
133
+ avgDurationMs: Math.round(data.totalDurationMs / data.calls),
134
+ };
135
+ }
136
+ return {
137
+ total: { ...this.totalUsage },
138
+ callCount: this.callHistory.length,
139
+ byModel: byModelResult,
140
+ byTier,
141
+ };
142
+ }
143
+ /**
144
+ * Reset usage counters and call history.
145
+ */
146
+ resetUsage() {
147
+ this.totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
148
+ this.callHistory = [];
149
+ }
150
+ /**
151
+ * Transcribe audio to text using the default adapter's whisper/transcription API.
152
+ * Returns null if the adapter doesn't support transcription.
153
+ */
154
+ async transcribe(audio, mimeType) {
155
+ const adapter = this.getAdapter();
156
+ if (!adapter.transcribe)
157
+ return null;
158
+ return adapter.transcribe(audio, mimeType);
159
+ }
160
+ }
161
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { CompletionAdapter, CompletionRequest, CompletionResponse, CompletionChunk, EmbeddingRequest, EmbeddingResponse, ProviderConfig } from './types.js';
2
+ /**
3
+ * OpenAI-compatible adapter.
4
+ * Works with OpenAI, OpenRouter, and any OpenAI-compatible API.
5
+ */
6
+ export declare class OpenAIAdapter implements CompletionAdapter {
7
+ readonly provider: string;
8
+ private client;
9
+ private defaultModel;
10
+ private baseURL;
11
+ private apiKey;
12
+ constructor(config: ProviderConfig);
13
+ complete(request: CompletionRequest): Promise<CompletionResponse>;
14
+ stream(request: CompletionRequest): AsyncIterable<CompletionChunk>;
15
+ embed(request: EmbeddingRequest): Promise<EmbeddingResponse>;
16
+ transcribe(audio: Buffer, mimeType: string): Promise<string>;
17
+ }
18
+ //# sourceMappingURL=openai-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-adapter.d.ts","sourceRoot":"","sources":["../src/openai-adapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EAGf,MAAM,YAAY,CAAC;AAwDpB;;;GAGG;AACH,qBAAa,aAAc,YAAW,iBAAiB;IACrD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,cAAc;IAgC5B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAkChE,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,aAAa,CAAC,eAAe,CAAC;IAgCnE,KAAK,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAe5D,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CA+CnE"}
@@ -0,0 +1,211 @@
1
+ import OpenAI from 'openai';
2
+ /**
3
+ * Convert MessageContent to the format OpenAI expects.
4
+ * string → string (pass-through), ContentPart[] → ChatCompletionContentPart[].
5
+ */
6
+ function toOpenAIContent(content) {
7
+ if (typeof content === 'string')
8
+ return content;
9
+ return content.map((part) => {
10
+ switch (part.type) {
11
+ case 'text':
12
+ return { type: 'text', text: part.text };
13
+ case 'image':
14
+ return {
15
+ type: 'image_url',
16
+ image_url: { url: `data:${part.mimeType};base64,${part.data}` },
17
+ };
18
+ case 'image_url':
19
+ return {
20
+ type: 'image_url',
21
+ image_url: { url: part.url },
22
+ };
23
+ case 'file':
24
+ // Files sent as text description — OpenAI doesn't have a native file content part
25
+ return { type: 'text', text: `[File: ${part.name} (${part.mimeType})]` };
26
+ case 'audio':
27
+ // Audio sent as input_audio if supported, otherwise text fallback
28
+ return { type: 'text', text: `[Audio content (${part.mimeType})]` };
29
+ }
30
+ });
31
+ }
32
+ function toOpenAIMessages(messages) {
33
+ return messages.map((m) => {
34
+ switch (m.role) {
35
+ case 'system':
36
+ return { role: 'system', content: typeof m.content === 'string' ? m.content : m.content.filter((p) => p.type === 'text').map((p) => p.text).join('\n') };
37
+ case 'user':
38
+ return { role: 'user', content: toOpenAIContent(m.content) };
39
+ case 'assistant':
40
+ return {
41
+ role: 'assistant',
42
+ content: typeof m.content === 'string' ? m.content : m.content.filter((p) => p.type === 'text').map((p) => p.text).join('\n'),
43
+ ...(m.tool_calls ? { tool_calls: m.tool_calls } : {}),
44
+ };
45
+ case 'tool':
46
+ return {
47
+ role: 'tool',
48
+ content: typeof m.content === 'string' ? m.content : m.content.filter((p) => p.type === 'text').map((p) => p.text).join('\n'),
49
+ tool_call_id: m.tool_call_id ?? '',
50
+ };
51
+ }
52
+ });
53
+ }
54
+ /**
55
+ * OpenAI-compatible adapter.
56
+ * Works with OpenAI, OpenRouter, and any OpenAI-compatible API.
57
+ */
58
+ export class OpenAIAdapter {
59
+ provider;
60
+ client;
61
+ defaultModel;
62
+ baseURL;
63
+ apiKey;
64
+ constructor(config) {
65
+ this.provider = config.provider;
66
+ this.defaultModel = config.model;
67
+ // `||` not `??`: an empty string from a ${VAR:-} yaml default means "unset"
68
+ const apiKey = config.apiKey ||
69
+ (config.provider === 'openrouter'
70
+ ? process.env.OPENROUTER_API_KEY || process.env.OPENAI_API_KEY
71
+ : process.env.OPENAI_API_KEY || process.env.OPENROUTER_API_KEY);
72
+ if (!apiKey) {
73
+ const preferred = config.provider === 'openrouter' ? 'OPENROUTER_API_KEY' : 'OPENAI_API_KEY';
74
+ throw new Error(`Missing API key for provider "${config.provider}" — set ${preferred} (preferred), or pass apiKey in the provider config`);
75
+ }
76
+ this.apiKey = apiKey;
77
+ if (config.baseURL) {
78
+ this.baseURL = config.baseURL;
79
+ }
80
+ else if (config.provider === 'openrouter') {
81
+ this.baseURL = 'https://openrouter.ai/api/v1';
82
+ }
83
+ else {
84
+ this.baseURL = 'https://api.openai.com/v1';
85
+ }
86
+ this.client = new OpenAI({
87
+ apiKey: this.apiKey,
88
+ baseURL: this.baseURL,
89
+ });
90
+ }
91
+ async complete(request) {
92
+ const response = await this.client.chat.completions.create({
93
+ model: request.model ?? this.defaultModel,
94
+ messages: toOpenAIMessages(request.messages),
95
+ ...(request.temperature != null ? { temperature: request.temperature } : {}),
96
+ ...(request.maxTokens != null ? { max_tokens: request.maxTokens } : {}),
97
+ ...(request.tools ? { tools: request.tools } : {}),
98
+ ...(request.toolChoice ? { tool_choice: request.toolChoice } : {}),
99
+ ...(request.stop ? { stop: request.stop } : {}),
100
+ });
101
+ const choice = response.choices[0];
102
+ return {
103
+ id: response.id,
104
+ content: choice.message.content,
105
+ toolCalls: (choice.message.tool_calls ?? []).map((tc) => ({
106
+ id: tc.id,
107
+ type: tc.type,
108
+ function: {
109
+ name: tc.function.name,
110
+ arguments: tc.function.arguments,
111
+ },
112
+ })),
113
+ usage: {
114
+ promptTokens: response.usage?.prompt_tokens ?? 0,
115
+ completionTokens: response.usage?.completion_tokens ?? 0,
116
+ totalTokens: response.usage?.total_tokens ?? 0,
117
+ },
118
+ model: response.model,
119
+ finishReason: choice.finish_reason ?? 'stop',
120
+ };
121
+ }
122
+ async *stream(request) {
123
+ const stream = await this.client.chat.completions.create({
124
+ model: request.model ?? this.defaultModel,
125
+ messages: toOpenAIMessages(request.messages),
126
+ stream: true,
127
+ ...(request.temperature != null ? { temperature: request.temperature } : {}),
128
+ ...(request.maxTokens != null ? { max_tokens: request.maxTokens } : {}),
129
+ ...(request.tools ? { tools: request.tools } : {}),
130
+ ...(request.toolChoice ? { tool_choice: request.toolChoice } : {}),
131
+ ...(request.stop ? { stop: request.stop } : {}),
132
+ });
133
+ for await (const chunk of stream) {
134
+ const choice = chunk.choices[0];
135
+ if (!choice)
136
+ continue;
137
+ yield {
138
+ id: chunk.id,
139
+ delta: choice.delta?.content ?? '',
140
+ toolCalls: choice.delta?.tool_calls?.map((tc) => ({
141
+ id: tc.id ?? '',
142
+ type: 'function',
143
+ function: {
144
+ name: tc.function?.name ?? '',
145
+ arguments: tc.function?.arguments ?? '',
146
+ },
147
+ })),
148
+ finishReason: choice.finish_reason ?? undefined,
149
+ };
150
+ }
151
+ }
152
+ async embed(request) {
153
+ const response = await this.client.embeddings.create({
154
+ input: request.input,
155
+ model: request.model ?? 'text-embedding-3-small',
156
+ });
157
+ return {
158
+ embeddings: response.data.map((d) => d.embedding),
159
+ model: response.model,
160
+ usage: {
161
+ totalTokens: response.usage.total_tokens,
162
+ },
163
+ };
164
+ }
165
+ async transcribe(audio, mimeType) {
166
+ const model = process.env.TRANSCRIPTION_MODEL ?? 'google/gemini-2.5-flash';
167
+ const base64 = audio.toString('base64');
168
+ // Use direct fetch to send input_audio content part — avoids SDK type limitations
169
+ const response = await fetch(`${this.baseURL}/chat/completions`, {
170
+ method: 'POST',
171
+ headers: {
172
+ 'Authorization': `Bearer ${this.apiKey}`,
173
+ 'Content-Type': 'application/json',
174
+ },
175
+ body: JSON.stringify({
176
+ model,
177
+ messages: [
178
+ {
179
+ role: 'system',
180
+ content: 'You are a transcription assistant. Transcribe the audio exactly as spoken. Output ONLY the transcript text, nothing else. If the audio is not in English, transcribe in the original language.',
181
+ },
182
+ {
183
+ role: 'user',
184
+ content: [
185
+ {
186
+ type: 'input_audio',
187
+ input_audio: {
188
+ data: base64,
189
+ format: mimeType.includes('ogg') ? 'ogg'
190
+ : mimeType.includes('wav') ? 'wav'
191
+ : mimeType.includes('webm') ? 'webm'
192
+ : 'mp3',
193
+ },
194
+ },
195
+ ],
196
+ },
197
+ ],
198
+ }),
199
+ });
200
+ if (!response.ok) {
201
+ const error = await response.text();
202
+ throw new Error(`Transcription request failed (HTTP ${response.status}): ${error}`);
203
+ }
204
+ const data = await response.json();
205
+ const text = data.choices?.[0]?.message?.content?.trim();
206
+ if (!text)
207
+ throw new Error('Transcription returned empty result');
208
+ return text;
209
+ }
210
+ }
211
+ //# sourceMappingURL=openai-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-adapter.js","sourceRoot":"","sources":["../src/openai-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,141 @@
1
+ import { z } from 'zod';
2
+ export type ContentPart = {
3
+ type: 'text';
4
+ text: string;
5
+ } | {
6
+ type: 'image';
7
+ mimeType: string;
8
+ data: string;
9
+ } | {
10
+ type: 'image_url';
11
+ url: string;
12
+ } | {
13
+ type: 'file';
14
+ mimeType: string;
15
+ data: string;
16
+ name: string;
17
+ } | {
18
+ type: 'audio';
19
+ mimeType: string;
20
+ data: string;
21
+ };
22
+ /**
23
+ * Message content — plain string (backward-compatible) or array of content parts
24
+ * for multimodal messages (images, files, audio, etc.).
25
+ */
26
+ export type MessageContent = string | ContentPart[];
27
+ /**
28
+ * Extract text from MessageContent regardless of shape.
29
+ */
30
+ export declare function extractText(content: MessageContent): string;
31
+ export interface CompletionMessage {
32
+ role: 'system' | 'user' | 'assistant' | 'tool';
33
+ content: MessageContent;
34
+ name?: string;
35
+ tool_call_id?: string;
36
+ tool_calls?: ToolCall[];
37
+ }
38
+ export interface ToolCall {
39
+ id: string;
40
+ type: 'function';
41
+ function: {
42
+ name: string;
43
+ arguments: string;
44
+ };
45
+ }
46
+ export interface ToolDefinition {
47
+ type: 'function';
48
+ function: {
49
+ name: string;
50
+ description: string;
51
+ parameters: Record<string, unknown>;
52
+ };
53
+ }
54
+ export interface CompletionRequest {
55
+ messages: CompletionMessage[];
56
+ model?: string;
57
+ temperature?: number;
58
+ maxTokens?: number;
59
+ tools?: ToolDefinition[];
60
+ toolChoice?: 'auto' | 'none' | {
61
+ type: 'function';
62
+ function: {
63
+ name: string;
64
+ };
65
+ };
66
+ stop?: string[];
67
+ }
68
+ export interface CompletionResponse {
69
+ id: string;
70
+ content: string | null;
71
+ toolCalls: ToolCall[];
72
+ usage: TokenUsage;
73
+ model: string;
74
+ finishReason: 'stop' | 'tool_calls' | 'length' | 'content_filter' | string;
75
+ }
76
+ export interface CompletionChunk {
77
+ id: string;
78
+ delta: string;
79
+ toolCalls?: ToolCall[];
80
+ finishReason?: string;
81
+ }
82
+ export interface TokenUsage {
83
+ promptTokens: number;
84
+ completionTokens: number;
85
+ totalTokens: number;
86
+ }
87
+ export interface LLMCallRecord {
88
+ id: string;
89
+ model: string;
90
+ tier: string;
91
+ promptTokens: number;
92
+ completionTokens: number;
93
+ totalTokens: number;
94
+ durationMs: number;
95
+ timestamp: string;
96
+ }
97
+ export interface EmbeddingRequest {
98
+ input: string | string[];
99
+ model?: string;
100
+ }
101
+ export interface EmbeddingResponse {
102
+ embeddings: number[][];
103
+ model: string;
104
+ usage: {
105
+ totalTokens: number;
106
+ };
107
+ }
108
+ export declare const ProviderConfigSchema: z.ZodObject<{
109
+ provider: z.ZodEnum<["openrouter", "openai", "anthropic"]>;
110
+ model: z.ZodString;
111
+ apiKey: z.ZodOptional<z.ZodString>;
112
+ baseURL: z.ZodOptional<z.ZodString>;
113
+ maxTokens: z.ZodOptional<z.ZodNumber>;
114
+ temperature: z.ZodOptional<z.ZodNumber>;
115
+ }, "strip", z.ZodTypeAny, {
116
+ provider: "openrouter" | "openai" | "anthropic";
117
+ model: string;
118
+ apiKey?: string | undefined;
119
+ baseURL?: string | undefined;
120
+ maxTokens?: number | undefined;
121
+ temperature?: number | undefined;
122
+ }, {
123
+ provider: "openrouter" | "openai" | "anthropic";
124
+ model: string;
125
+ apiKey?: string | undefined;
126
+ baseURL?: string | undefined;
127
+ maxTokens?: number | undefined;
128
+ temperature?: number | undefined;
129
+ }>;
130
+ export type ProviderConfig = z.infer<typeof ProviderConfigSchema>;
131
+ /**
132
+ * Abstract adapter interface that all providers must implement.
133
+ */
134
+ export interface CompletionAdapter {
135
+ readonly provider: string;
136
+ complete(request: CompletionRequest): Promise<CompletionResponse>;
137
+ stream(request: CompletionRequest): AsyncIterable<CompletionChunk>;
138
+ embed?(request: EmbeddingRequest): Promise<EmbeddingResponse>;
139
+ transcribe?(audio: Buffer, mimeType: string): Promise<string>;
140
+ }
141
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,22 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Extract text from MessageContent regardless of shape.
4
+ */
5
+ export function extractText(content) {
6
+ if (typeof content === 'string')
7
+ return content;
8
+ return content
9
+ .filter((p) => p.type === 'text')
10
+ .map((p) => p.text)
11
+ .join('\n');
12
+ }
13
+ // ─── Provider Config ───
14
+ export const ProviderConfigSchema = z.object({
15
+ provider: z.enum(['openrouter', 'openai', 'anthropic']),
16
+ model: z.string(),
17
+ apiKey: z.string().optional(),
18
+ baseURL: z.string().optional(),
19
+ maxTokens: z.number().optional(),
20
+ temperature: z.number().optional(),
21
+ });
22
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiBxB;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAAuB;IACjD,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,OAAO,OAAO;SACX,MAAM,CAAC,CAAC,CAAC,EAA+C,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;SAC7E,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAClB,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAwFD,0BAA0B;AAE1B,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IACvD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACnC,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@mce-bt/microagents-completion",
3
+ "version": "0.1.0",
4
+ "description": "Provider-agnostic LLM completion layer with model tiering",
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
+ "scripts": {
15
+ "build": "tsc --build",
16
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
17
+ "test": "vitest run"
18
+ },
19
+ "dependencies": {
20
+ "openai": "^4.73.0",
21
+ "@anthropic-ai/sdk": "^0.35.0",
22
+ "zod": "^3.23.0"
23
+ },
24
+ "license": "MIT",
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/cavillo/microagents.git",
34
+ "directory": "packages/completion"
35
+ },
36
+ "homepage": "https://github.com/cavillo/microagents#readme",
37
+ "bugs": {
38
+ "url": "https://github.com/cavillo/microagents/issues"
39
+ },
40
+ "engines": {
41
+ "node": ">=20.0.0"
42
+ }
43
+ }