mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-09 13:52:23 +00:00
Merge remote-tracking branch 'origin/feat/ifcchat-claude' into v0.8.0
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
|
||||
function parseArguments(argumentsText) {
|
||||
if (!argumentsText) return {};
|
||||
try {
|
||||
return JSON.parse(argumentsText);
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function toAnthropicTools(tools = []) {
|
||||
return tools.map((tool) => ({
|
||||
name: tool.function.name,
|
||||
description: tool.function.description,
|
||||
input_schema: tool.function.parameters,
|
||||
}));
|
||||
}
|
||||
|
||||
function toAnthropicAssistantContent(message) {
|
||||
const content = [];
|
||||
|
||||
if (message.content) {
|
||||
content.push({ type: "text", text: message.content });
|
||||
}
|
||||
|
||||
for (const toolCall of message.tool_calls ?? []) {
|
||||
content.push({
|
||||
type: "tool_use",
|
||||
id: toolCall.id,
|
||||
name: toolCall.function.name,
|
||||
input: parseArguments(toolCall.function.arguments),
|
||||
});
|
||||
}
|
||||
|
||||
if (content.length === 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return content.length === 1 && content[0].type === "text" ? content[0].text : content;
|
||||
}
|
||||
|
||||
function toAnthropicUserContent(message) {
|
||||
return typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? "");
|
||||
}
|
||||
|
||||
function toAnthropicToolResult(message) {
|
||||
return {
|
||||
type: "tool_result",
|
||||
tool_use_id: message.tool_call_id,
|
||||
content: typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? ""),
|
||||
};
|
||||
}
|
||||
|
||||
function splitSystemAndMessages(messages = []) {
|
||||
const system = [];
|
||||
const anthropicMessages = [];
|
||||
let pendingToolResults = [];
|
||||
|
||||
const flushToolResults = () => {
|
||||
if (pendingToolResults.length === 0) return;
|
||||
anthropicMessages.push({ role: "user", content: pendingToolResults });
|
||||
pendingToolResults = [];
|
||||
};
|
||||
|
||||
for (const message of messages) {
|
||||
if (message.role === "system") {
|
||||
if (message.content) {
|
||||
system.push(message.content);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (message.role === "tool") {
|
||||
pendingToolResults.push(toAnthropicToolResult(message));
|
||||
continue;
|
||||
}
|
||||
|
||||
flushToolResults();
|
||||
|
||||
if (message.role === "user") {
|
||||
anthropicMessages.push({
|
||||
role: "user",
|
||||
content: toAnthropicUserContent(message),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
if (message.role === "assistant") {
|
||||
anthropicMessages.push({
|
||||
role: "assistant",
|
||||
content: toAnthropicAssistantContent(message),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
flushToolResults();
|
||||
|
||||
return {
|
||||
system: system.join("\n\n"),
|
||||
messages: anthropicMessages,
|
||||
};
|
||||
}
|
||||
|
||||
function toChatCompletionResponse(response) {
|
||||
const text = [];
|
||||
const toolCalls = [];
|
||||
|
||||
for (const block of response.content ?? []) {
|
||||
if (block.type === "text") {
|
||||
text.push(block.text);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (block.type === "tool_use") {
|
||||
toolCalls.push({
|
||||
id: block.id,
|
||||
type: "function",
|
||||
function: {
|
||||
name: block.name,
|
||||
arguments: JSON.stringify(block.input ?? {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const message = { role: "assistant" };
|
||||
const content = text.join("\n").trim();
|
||||
|
||||
if (content) {
|
||||
message.content = content;
|
||||
}
|
||||
|
||||
if (toolCalls.length) {
|
||||
message.tool_calls = toolCalls;
|
||||
}
|
||||
|
||||
return {
|
||||
choices: [
|
||||
{
|
||||
message,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export async function chat({ apiKey, model, messages, tools }) {
|
||||
const request = splitSystemAndMessages(messages);
|
||||
const body = {
|
||||
model,
|
||||
max_tokens: 4096,
|
||||
messages: request.messages,
|
||||
tools: toAnthropicTools(tools),
|
||||
};
|
||||
|
||||
if (request.system) {
|
||||
body.system = request.system;
|
||||
}
|
||||
|
||||
const res = await fetch("https://api.anthropic.com/v1/messages", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": apiKey,
|
||||
"anthropic-version": "2023-06-01",
|
||||
"anthropic-dangerous-direct-browser-access": "true",
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const text = await res.text();
|
||||
throw new Error(`Anthropic error ${res.status}: ${text}`);
|
||||
}
|
||||
|
||||
return toChatCompletionResponse(await res.json());
|
||||
}
|
||||
Reference in New Issue
Block a user