TypeScript
const chat = async ({
messages,
model,
metaData = {},
params = {},
}: {
messages: TPromptMessage[];
apiKey?: string;
model: TLLMModels;
metaData?: Record<string, unknown>;
params?: {
tools?: OpenAI.Chat.Completions.ChatCompletionTool[];
} & Record<string, unknown>;
}) => {
const { chatStateManager, user }: TUnifiedPostwareRequestContext =
requestContext.get();
const modelConfig = getLLMModel(model);
const toolCalls = params.tools;
const toolCallTokens = await Promise.all(
toolCalls?.map((toolCall) => tokenizer.encode(JSON.stringify(toolCall))) ??
[],
);
const toolCallTokenCount = toolCallTokens.reduce(
(acc, token) => acc + (token?.length ?? 0),
0,
);
const inputSize =
messages.reduce((acc, message) => acc + (message.tokens ?? 0), 0) +
((metaData?.systemPromptTokens as number) ?? 0) +
toolCallTokenCount;
let serializedMessages = [];
for (let i = 0; i < messages.length; i++) {
if (i == messages.length - 1) {
messages[i].cache = true;
serializedMessages.push(messages[i].toJSON());
messages[i].cache = false;
} else {
serializedMessages.push(messages[i].toJSON());
}
}
serializedMessages = serializedMessages.flat();
const rawPayload: TProviderConfig = {
config: { messages: serializedMessages },
mode: "CHAT",
params: {
model: modelConfig.id,
...params,
},
metaData: {
systemPrompt: modelConfig.prompts.system,
apiKey: undefined,
...metaData,
},
};
const payload = getFinalProviderConfig({ config: rawPayload });
return {
payload,
stream: async () => {
try {
const config: AxiosRequestConfig = {
method: "POST",
maxBodyLength: Infinity,
url: RUNE.DOMAIN,
headers: {
"Content-Type": "application/json",
"x-rune-api-key": RUNE.AUTH_TOKEN,
"x-rune-config": modelConfig.runeConfig,
},
data: transformPayload(payload, true),
responseType: "stream",
};
const response = await axiosInstance.request(config);
return {
data: response.data,
usage: async (
chunks: string[],
options: { usage?: CompletionUsage; tools: TToolName[] },
) => {
const { usage, tools } = options;
if (!chunks) chunks = [""];
let effectiveCost = modelConfig.queryCost;
if (tools.includes("web_search_tool")) {
const count = tools.filter((t) => t === "web_search_tool").length;
effectiveCost *= count + 1;
}
if (
tools.includes("rag_tool") &&
chatStateManager.hasUsedMode("PROJECT") &&
chatStateManager.hasUsedMode("PRO_FINDER")
) {
effectiveCost += 250;
}
if (tools.includes("data_analysis_tool")) {
const count = tools.filter(
(t) => t === "data_analysis_tool",
).length;
effectiveCost += 15 * count;
}
const outputSize =
usage?.completion_tokens ??
(
await tokenizer.encode(
`<|start|>assistant\n${chunks.join("")}<|end|>\n`,
)
).length;
return {
queries: effectiveCost,
tokens: {
input: usage?.prompt_tokens ?? inputSize,
output: outputSize,
cached: usage?.prompt_tokens_details?.cached_tokens ?? 0,
reasoning:
usage?.completion_tokens_details?.reasoning_tokens ?? 0,
},
model,
} as TUsageConfig;
},
};
} catch (error) {
if (error instanceof AxiosError) {
const extractedError = await handleAxiosError(error);
logger.error(extractedError, "ERROR/RUNE/CHAT_FAILED");
throw error;
}
throw error;
}
},
normal: async () => {
const config = {
method: "POST",
maxBodyLength: Infinity,
url: RUNE.DOMAIN,
headers: {
"Content-Type": "application/json",
"x-rune-api-key": RUNE.AUTH_TOKEN,
"x-rune-config": modelConfig.runeConfig,
},
data: transformPayload(payload, false),
};
const response =
await axiosInstance.request<OpenAI.ChatCompletion>(config);
return {
data: {
data: {
content: response.data.choices[0].message.content ?? "",
raw: response.data,
},
},
usage: async (calcEffectiveCost: boolean = false) => {
const tokensUsed = messages.reduce(
(acc, msg) => (msg.tokens ?? 0) + acc,
0,
);
let effectiveCost = modelConfig.queryCost;
if (calcEffectiveCost) {
if (chatStateManager.hasUsedMode("WEB_SEARCH")) {
effectiveCost *= 2;
}
if (
chatStateManager.hasUsedMode("PROJECT") &&
chatStateManager.hasUsedMode("PRO_FINDER")
) {
effectiveCost += 250;
}
if (chatStateManager.hasUsedMode("DATA_ANALYSIS")) {
effectiveCost += 15;
}
if (chatStateManager.hasUsedMode("MCP")) {
effectiveCost += 30;
}
}
return {
queries: effectiveCost,
tokens: {
input: response.data.usage?.prompt_tokens ?? tokensUsed,
output:
response.data.usage?.completion_tokens ??
(
await tokenizer.encode(
`<|start|>assistant\n${response.data.choices[0].message.content ?? ""}<|end|>\n`,
)
).length,
cached:
response.data.usage?.prompt_tokens_details?.cached_tokens ?? 0,
reasoning:
response.data.usage?.completion_tokens_details
?.reasoning_tokens ?? 0,
},
model,
} as TUsageConfig;
},
};
},
fnCall: async ({
name,
functions,
}: {
name: string;
functions: FunctionDef[];
}) => {
const newPayload = {
...payload,
params: {
...payload.params,
model: "gpt-4o-mini",
functions,
function_call: { name },
},
};
const config = {
method: "POST",
maxBodyLength: Infinity,
url: RUNE.DOMAIN,
headers: {
"Content-Type": "application/json",
"x-rune-api-key": RUNE.AUTH_TOKEN,
"x-rune-config": modelConfig.runeConfig,
},
data: transformPayload(newPayload, false),
};
const response =
await axiosInstance.request<OpenAI.ChatCompletion>(config);
return {
data: {
data: {
content: {
arguments:
response.data.choices[0].message.function_call?.arguments ?? "",
},
},
},
};
},
};
};