MCPcopy Create free account
hub / github.com/IAmUnbounded/devctx / callAI

Function callAI

devctx/src/core/ai.ts:17–73  ·  view source on GitHub ↗
(
    messages: ChatMessage[],
    options?: { maxTokens?: number; temperature?: number }
)

Source from the content-addressed store, hash-verified

15 * Works with OpenAI, Ollama, LM Studio, together.ai, etc.
16 */
17export async function callAI(
18 messages: ChatMessage[],
19 options?: { maxTokens?: number; temperature?: number }
20): Promise<AIResponse> {
21 const config = await loadConfig();
22 const apiKey = process.env.DEVCTX_AI_KEY || config.aiApiKey;
23 const baseUrl = process.env.DEVCTX_AI_PROVIDER || config.aiProvider;
24 const model = process.env.DEVCTX_AI_MODEL || config.aiModel;
25
26 if (!apiKey && baseUrl.includes("openai.com")) {
27 return {
28 content: "",
29 error:
30 "No API key configured. Set DEVCTX_AI_KEY env var or run: devctx config set aiApiKey <key>",
31 };
32 }
33
34 try {
35 const url = `${baseUrl.replace(/\/+$/, "")}/chat/completions`;
36
37 const headers: Record<string, string> = {
38 "Content-Type": "application/json",
39 };
40 if (apiKey) {
41 headers["Authorization"] = `Bearer ${apiKey}`;
42 }
43
44 const response = await fetch(url, {
45 method: "POST",
46 headers,
47 body: JSON.stringify({
48 model,
49 messages,
50 max_tokens: options?.maxTokens || 1024,
51 temperature: options?.temperature ?? 0.3,
52 }),
53 });
54
55 if (!response.ok) {
56 const errorText = await response.text();
57 return {
58 content: "",
59 error: `AI API error (${response.status}): ${errorText.slice(0, 200)}`,
60 };
61 }
62
63 const data = (await response.json()) as any;
64 const content = data.choices?.[0]?.message?.content || "";
65
66 return { content };
67 } catch (err: any) {
68 return {
69 content: "",
70 error: `AI request failed: ${err.message}`,
71 };
72 }
73}

Callers 3

compressCommandFunction · 0.90
summarizeCommandFunction · 0.90
suggestCommandFunction · 0.90

Calls 1

loadConfigFunction · 0.90

Tested by

no test coverage detected