@lowire/loop 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +1 -0
- package/githubAuth.js +17 -0
- package/index.d.ts +18 -0
- package/index.js +17 -0
- package/index.mjs +17 -0
- package/lib/auth/githubAuth.d.ts +16 -0
- package/lib/auth/githubAuth.js +81 -0
- package/lib/cache.d.ts +18 -0
- package/lib/cache.js +58 -0
- package/lib/loop.d.ts +47 -0
- package/lib/loop.js +150 -0
- package/lib/providers/anthropic.d.ts +23 -0
- package/lib/providers/anthropic.js +179 -0
- package/lib/providers/github.d.ts +33 -0
- package/lib/providers/github.js +68 -0
- package/lib/providers/google.d.ts +23 -0
- package/lib/providers/google.js +186 -0
- package/lib/providers/openai.d.ts +23 -0
- package/lib/providers/openai.js +172 -0
- package/lib/providers/openaiCompletions.d.ts +33 -0
- package/lib/providers/openaiCompletions.js +174 -0
- package/lib/providers/registry.d.ts +17 -0
- package/lib/providers/registry.js +33 -0
- package/lib/types.d.ts +108 -0
- package/lib/types.js +17 -0
- package/package.json +54 -7
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import type * as types from '../types';
|
|
17
|
+
export declare class Anthropic implements types.Provider {
|
|
18
|
+
readonly name = "anthropic";
|
|
19
|
+
complete(conversation: types.Conversation, options: types.CompletionOptions): Promise<{
|
|
20
|
+
result: types.AssistantMessage;
|
|
21
|
+
usage: types.Usage;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Microsoft Corporation.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.Anthropic = void 0;
|
|
19
|
+
class Anthropic {
|
|
20
|
+
name = 'anthropic';
|
|
21
|
+
async complete(conversation, options) {
|
|
22
|
+
const response = await create({
|
|
23
|
+
model: options.model,
|
|
24
|
+
max_tokens: options.maxTokens ?? 32768,
|
|
25
|
+
temperature: options.temperature,
|
|
26
|
+
system: systemPrompt(conversation.systemPrompt),
|
|
27
|
+
messages: conversation.messages.map(toAnthropicMessagePart),
|
|
28
|
+
tools: conversation.tools.map(toAnthropicTool),
|
|
29
|
+
thinking: options.reasoning ? {
|
|
30
|
+
type: 'enabled',
|
|
31
|
+
budget_tokens: options.maxTokens ? Math.round(options.maxTokens / 10) : 1024,
|
|
32
|
+
} : undefined,
|
|
33
|
+
});
|
|
34
|
+
const result = toAssistantMessage(response);
|
|
35
|
+
const usage = {
|
|
36
|
+
input: response.usage.input_tokens,
|
|
37
|
+
output: response.usage.output_tokens,
|
|
38
|
+
};
|
|
39
|
+
return { result, usage };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.Anthropic = Anthropic;
|
|
43
|
+
async function create(body) {
|
|
44
|
+
const headers = {
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
'x-api-key': process.env.ANTHROPIC_API_KEY,
|
|
47
|
+
'anthropic-version': '2023-06-01',
|
|
48
|
+
};
|
|
49
|
+
const response = await fetch(`https://api.anthropic.com/v1/messages`, {
|
|
50
|
+
method: 'POST',
|
|
51
|
+
headers,
|
|
52
|
+
body: JSON.stringify(body)
|
|
53
|
+
});
|
|
54
|
+
if (!response.ok)
|
|
55
|
+
throw new Error(`API error: ${response.status} ${response.statusText} ${await response.text()}`);
|
|
56
|
+
return await response.json();
|
|
57
|
+
}
|
|
58
|
+
function toContentPart(block) {
|
|
59
|
+
if (block.type === 'text') {
|
|
60
|
+
return {
|
|
61
|
+
type: 'text',
|
|
62
|
+
text: block.text,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (block.type === 'tool_use') {
|
|
66
|
+
return {
|
|
67
|
+
type: 'tool_call',
|
|
68
|
+
name: block.name,
|
|
69
|
+
arguments: block.input,
|
|
70
|
+
id: block.id,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
if (block.type === 'thinking') {
|
|
74
|
+
return {
|
|
75
|
+
type: 'thinking',
|
|
76
|
+
thinking: block.thinking,
|
|
77
|
+
signature: block.signature,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
function toAnthropicResultParam(part) {
|
|
83
|
+
if (part.type === 'text') {
|
|
84
|
+
return {
|
|
85
|
+
type: 'text',
|
|
86
|
+
text: part.text,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (part.type === 'image') {
|
|
90
|
+
return {
|
|
91
|
+
type: 'image',
|
|
92
|
+
source: {
|
|
93
|
+
type: 'base64',
|
|
94
|
+
data: part.data,
|
|
95
|
+
media_type: part.mimeType
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
throw new Error(`Unsupported content part type: ${part.type}`);
|
|
100
|
+
}
|
|
101
|
+
function toAssistantMessage(message) {
|
|
102
|
+
return {
|
|
103
|
+
role: 'assistant',
|
|
104
|
+
content: message.content.map(toContentPart).filter(Boolean),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function toAnthropicTool(tool) {
|
|
108
|
+
return {
|
|
109
|
+
name: tool.name,
|
|
110
|
+
description: tool.description,
|
|
111
|
+
input_schema: tool.inputSchema,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function toAnthropicAssistantMessageParam(message) {
|
|
115
|
+
const content = [];
|
|
116
|
+
for (const part of message.content) {
|
|
117
|
+
if (part.type === 'text') {
|
|
118
|
+
content.push({ ...part, citations: [] });
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (part.type === 'tool_call') {
|
|
122
|
+
content.push({
|
|
123
|
+
type: 'tool_use',
|
|
124
|
+
id: part.id,
|
|
125
|
+
name: part.name,
|
|
126
|
+
input: part.arguments
|
|
127
|
+
});
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (part.type === 'thinking') {
|
|
131
|
+
content.push({
|
|
132
|
+
type: 'thinking',
|
|
133
|
+
thinking: part.thinking,
|
|
134
|
+
signature: part.signature,
|
|
135
|
+
});
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
role: 'assistant',
|
|
141
|
+
content
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function toAnthropicToolResultMessage(message) {
|
|
145
|
+
const toolResult = {
|
|
146
|
+
type: 'tool_result',
|
|
147
|
+
tool_use_id: message.toolCallId,
|
|
148
|
+
content: message.result.content.map(toAnthropicResultParam),
|
|
149
|
+
is_error: message.result.isError,
|
|
150
|
+
};
|
|
151
|
+
return {
|
|
152
|
+
role: 'user',
|
|
153
|
+
content: [toolResult]
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function toAnthropicMessagePart(message) {
|
|
157
|
+
if (message.role === 'user') {
|
|
158
|
+
return {
|
|
159
|
+
role: 'user',
|
|
160
|
+
content: message.content
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
if (message.role === 'assistant')
|
|
164
|
+
return toAnthropicAssistantMessageParam(message);
|
|
165
|
+
if (message.role === 'tool_result')
|
|
166
|
+
return toAnthropicToolResultMessage(message);
|
|
167
|
+
throw new Error(`Unsupported message role: ${message.role}`);
|
|
168
|
+
}
|
|
169
|
+
const systemPrompt = (prompt) => `
|
|
170
|
+
### System instructions
|
|
171
|
+
|
|
172
|
+
${prompt}
|
|
173
|
+
|
|
174
|
+
### Tool calling instructions
|
|
175
|
+
- Make sure every message contains a tool call.
|
|
176
|
+
- When you use a tool, you may provide a brief thought or explanation in the content field
|
|
177
|
+
immediately before the tool_call. Do not split this into separate messages.
|
|
178
|
+
- Every reply must include a tool call.
|
|
179
|
+
`;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { OpenAICompletions } from './openaiCompletions';
|
|
17
|
+
import type { Endpoint } from './openaiCompletions';
|
|
18
|
+
import type * as types from '../types';
|
|
19
|
+
export declare const kEditorHeaders: {
|
|
20
|
+
'Editor-Version': string;
|
|
21
|
+
'Editor-Plugin-Version': string;
|
|
22
|
+
'User-Agent': string;
|
|
23
|
+
Accept: string;
|
|
24
|
+
'Content-Type': string;
|
|
25
|
+
};
|
|
26
|
+
export declare class Github extends OpenAICompletions {
|
|
27
|
+
readonly name = "copilot";
|
|
28
|
+
connect(): Promise<Endpoint>;
|
|
29
|
+
complete(conversation: types.Conversation, options: types.CompletionOptions): Promise<{
|
|
30
|
+
result: types.AssistantMessage;
|
|
31
|
+
usage: types.Usage;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Microsoft Corporation.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.Github = exports.kEditorHeaders = void 0;
|
|
19
|
+
const openaiCompletions_1 = require("./openaiCompletions");
|
|
20
|
+
exports.kEditorHeaders = {
|
|
21
|
+
'Editor-Version': 'vscode/1.96.0',
|
|
22
|
+
'Editor-Plugin-Version': 'copilot-chat/0.24.0',
|
|
23
|
+
'User-Agent': 'GitHubCopilotChat/0.24.0',
|
|
24
|
+
'Accept': 'application/json',
|
|
25
|
+
'Content-Type': 'application/json'
|
|
26
|
+
};
|
|
27
|
+
// Copilot endpoint does not reply with content+tool_call, it instead
|
|
28
|
+
// replies with the content and expects continuation. I.e. instead of navigating
|
|
29
|
+
// to a page it will reply with "Navigating to <url>" w/o tool call. Mitigate it
|
|
30
|
+
// via injecting a tool call intent and then converting it into the assistant
|
|
31
|
+
// message content.
|
|
32
|
+
class Github extends openaiCompletions_1.OpenAICompletions {
|
|
33
|
+
name = 'copilot';
|
|
34
|
+
async connect() {
|
|
35
|
+
return {
|
|
36
|
+
baseUrl: 'https://api.githubcopilot.com',
|
|
37
|
+
apiKey: await getCopilotToken(),
|
|
38
|
+
headers: exports.kEditorHeaders
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async complete(conversation, options) {
|
|
42
|
+
const message = await super.complete(conversation, { ...options, injectIntent: true });
|
|
43
|
+
const textPart = message.result.content.find(part => part.type === 'text');
|
|
44
|
+
if (!textPart) {
|
|
45
|
+
const content = [];
|
|
46
|
+
const toolCalls = message.result.content.filter(part => part.type === 'tool_call');
|
|
47
|
+
for (const toolCall of toolCalls) {
|
|
48
|
+
content.push(toolCall.arguments?._intent ?? '');
|
|
49
|
+
delete toolCall.arguments._intent;
|
|
50
|
+
}
|
|
51
|
+
const text = content.join(' ').trim();
|
|
52
|
+
if (text.trim())
|
|
53
|
+
message.result.content.unshift({ type: 'text', text: content.join(' ') });
|
|
54
|
+
}
|
|
55
|
+
return message;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.Github = Github;
|
|
59
|
+
async function getCopilotToken() {
|
|
60
|
+
const response = await fetch('https://api.github.com/copilot_internal/v2/token', {
|
|
61
|
+
method: 'GET',
|
|
62
|
+
headers: { 'Authorization': `token ${process.env.COPILOT_API_KEY}`, ...exports.kEditorHeaders }
|
|
63
|
+
});
|
|
64
|
+
const data = await response.json();
|
|
65
|
+
if (data.token)
|
|
66
|
+
return data.token;
|
|
67
|
+
throw new Error('Failed to get Copilot token');
|
|
68
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import type * as types from '../types';
|
|
17
|
+
export declare class Google implements types.Provider {
|
|
18
|
+
readonly name = "google";
|
|
19
|
+
complete(conversation: types.Conversation, options: types.CompletionOptions): Promise<{
|
|
20
|
+
result: types.AssistantMessage;
|
|
21
|
+
usage: types.Usage;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Microsoft Corporation.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.Google = void 0;
|
|
19
|
+
class Google {
|
|
20
|
+
name = 'google';
|
|
21
|
+
async complete(conversation, options) {
|
|
22
|
+
const contents = conversation.messages.map(toGeminiContent).flat();
|
|
23
|
+
const response = await create(options.model ?? 'gemini-2.5-pro', {
|
|
24
|
+
systemInstruction: {
|
|
25
|
+
role: 'system',
|
|
26
|
+
parts: [
|
|
27
|
+
{ text: systemPrompt(conversation.systemPrompt) }
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
contents,
|
|
31
|
+
tools: conversation.tools.length > 0 ? [{ functionDeclarations: conversation.tools.map(toGeminiTool) }] : undefined,
|
|
32
|
+
generationConfig: { temperature: options.temperature },
|
|
33
|
+
});
|
|
34
|
+
const [candidate] = response.candidates ?? [];
|
|
35
|
+
if (!candidate)
|
|
36
|
+
throw new Error('No candidates in response');
|
|
37
|
+
const usage = {
|
|
38
|
+
input: response.usageMetadata?.promptTokenCount ?? 0,
|
|
39
|
+
output: response.usageMetadata?.candidatesTokenCount ?? 0,
|
|
40
|
+
};
|
|
41
|
+
const result = toAssistantMessage(candidate);
|
|
42
|
+
return { result, usage };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.Google = Google;
|
|
46
|
+
async function create(model, body) {
|
|
47
|
+
const apiKey = process.env.GEMINI_API_KEY ?? process.env.GOOGLE_API_KEY;
|
|
48
|
+
if (!apiKey)
|
|
49
|
+
throw new Error('GEMINI_API_KEY or GOOGLE_API_KEY environment variable is required');
|
|
50
|
+
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent`, {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: {
|
|
53
|
+
'Content-Type': 'application/json',
|
|
54
|
+
'x-goog-api-key': apiKey,
|
|
55
|
+
},
|
|
56
|
+
body: JSON.stringify(body)
|
|
57
|
+
});
|
|
58
|
+
if (!response.ok)
|
|
59
|
+
throw new Error(`API error: ${response.status} ${response.statusText} ${await response.text()}`);
|
|
60
|
+
return await response.json();
|
|
61
|
+
}
|
|
62
|
+
function toGeminiTool(tool) {
|
|
63
|
+
return {
|
|
64
|
+
name: tool.name,
|
|
65
|
+
description: tool.description,
|
|
66
|
+
parameters: stripUnsupportedSchemaFields(tool.inputSchema),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function stripUnsupportedSchemaFields(schema) {
|
|
70
|
+
if (!schema || typeof schema !== 'object')
|
|
71
|
+
return schema;
|
|
72
|
+
const cleaned = Array.isArray(schema) ? [...schema] : { ...schema };
|
|
73
|
+
delete cleaned.additionalProperties;
|
|
74
|
+
for (const key in cleaned) {
|
|
75
|
+
if (cleaned[key] && typeof cleaned[key] === 'object')
|
|
76
|
+
cleaned[key] = stripUnsupportedSchemaFields(cleaned[key]);
|
|
77
|
+
}
|
|
78
|
+
return cleaned;
|
|
79
|
+
}
|
|
80
|
+
function toAssistantMessage(candidate) {
|
|
81
|
+
return {
|
|
82
|
+
role: 'assistant',
|
|
83
|
+
content: candidate.content.parts.map(toContentPart).filter(Boolean),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function toContentPart(part) {
|
|
87
|
+
if (part.text) {
|
|
88
|
+
return {
|
|
89
|
+
type: 'text',
|
|
90
|
+
text: part.text,
|
|
91
|
+
googleThoughtSignature: part.thoughtSignature,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
if (part.functionCall) {
|
|
95
|
+
return {
|
|
96
|
+
type: 'tool_call',
|
|
97
|
+
name: part.functionCall.name,
|
|
98
|
+
arguments: part.functionCall.args,
|
|
99
|
+
id: `call_${Math.random().toString(36).substring(2, 15)}`,
|
|
100
|
+
googleThoughtSignature: part.thoughtSignature,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
function toGeminiContent(message) {
|
|
106
|
+
if (message.role === 'user') {
|
|
107
|
+
return [{
|
|
108
|
+
role: 'user',
|
|
109
|
+
parts: [{ text: message.content }]
|
|
110
|
+
}];
|
|
111
|
+
}
|
|
112
|
+
if (message.role === 'assistant') {
|
|
113
|
+
const parts = [];
|
|
114
|
+
for (const part of message.content) {
|
|
115
|
+
if (part.type === 'text') {
|
|
116
|
+
parts.push({
|
|
117
|
+
text: part.text,
|
|
118
|
+
thoughtSignature: part.googleThoughtSignature,
|
|
119
|
+
});
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (part.type === 'tool_call') {
|
|
123
|
+
parts.push({
|
|
124
|
+
functionCall: {
|
|
125
|
+
name: part.name,
|
|
126
|
+
args: part.arguments
|
|
127
|
+
},
|
|
128
|
+
thoughtSignature: part.googleThoughtSignature,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return [{
|
|
133
|
+
role: 'model',
|
|
134
|
+
parts
|
|
135
|
+
}];
|
|
136
|
+
}
|
|
137
|
+
if (message.role === 'tool_result') {
|
|
138
|
+
const responseContent = {};
|
|
139
|
+
const textParts = [];
|
|
140
|
+
const inlineDatas = [];
|
|
141
|
+
for (const part of message.result.content) {
|
|
142
|
+
if (part.type === 'text') {
|
|
143
|
+
textParts.push(part.text);
|
|
144
|
+
}
|
|
145
|
+
else if (part.type === 'image') {
|
|
146
|
+
// Store image data for inclusion in response
|
|
147
|
+
inlineDatas.push({
|
|
148
|
+
inline_data: {
|
|
149
|
+
mime_type: part.mimeType,
|
|
150
|
+
data: part.data
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (textParts.length > 0)
|
|
156
|
+
responseContent.result = textParts.join('\n');
|
|
157
|
+
const result = [{
|
|
158
|
+
role: 'function',
|
|
159
|
+
parts: [{
|
|
160
|
+
functionResponse: {
|
|
161
|
+
name: message.toolName,
|
|
162
|
+
response: responseContent
|
|
163
|
+
}
|
|
164
|
+
}]
|
|
165
|
+
}];
|
|
166
|
+
if (inlineDatas.length > 0) {
|
|
167
|
+
result.push({
|
|
168
|
+
role: 'user',
|
|
169
|
+
parts: inlineDatas
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
throw new Error(`Unsupported message role: ${message.role}`);
|
|
175
|
+
}
|
|
176
|
+
const systemPrompt = (prompt) => `
|
|
177
|
+
### System instructions
|
|
178
|
+
|
|
179
|
+
${prompt}
|
|
180
|
+
|
|
181
|
+
### Tool calling instructions
|
|
182
|
+
- Make sure every message contains a tool call.
|
|
183
|
+
- When you use a tool, you may provide a brief thought or explanation in the content field
|
|
184
|
+
immediately before the tool_call. Do not split this into separate messages.
|
|
185
|
+
- Every reply must include a tool call.
|
|
186
|
+
`;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import type * as types from '../types';
|
|
17
|
+
export declare class OpenAI implements types.Provider {
|
|
18
|
+
readonly name: string;
|
|
19
|
+
complete(conversation: types.Conversation, options: types.CompletionOptions): Promise<{
|
|
20
|
+
result: types.AssistantMessage;
|
|
21
|
+
usage: types.Usage;
|
|
22
|
+
}>;
|
|
23
|
+
}
|