@pentoshi/clai 0.2.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.
- package/README.md +287 -0
- package/bin/clai.mjs +2 -0
- package/dist/agent/runner.d.ts +12 -0
- package/dist/agent/runner.js +249 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/commands/doctor.d.ts +1 -0
- package/dist/commands/doctor.js +29 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/providers.d.ts +13 -0
- package/dist/commands/providers.js +137 -0
- package/dist/commands/providers.js.map +1 -0
- package/dist/commands/update.d.ts +5 -0
- package/dist/commands/update.js +123 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +172 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/anthropic.d.ts +2 -0
- package/dist/llm/anthropic.js +127 -0
- package/dist/llm/anthropic.js.map +1 -0
- package/dist/llm/gemini.d.ts +2 -0
- package/dist/llm/gemini.js +109 -0
- package/dist/llm/gemini.js.map +1 -0
- package/dist/llm/groq.d.ts +2 -0
- package/dist/llm/groq.js +49 -0
- package/dist/llm/groq.js.map +1 -0
- package/dist/llm/http.d.ts +35 -0
- package/dist/llm/http.js +112 -0
- package/dist/llm/http.js.map +1 -0
- package/dist/llm/ollama.d.ts +2 -0
- package/dist/llm/ollama.js +95 -0
- package/dist/llm/ollama.js.map +1 -0
- package/dist/llm/openai.d.ts +2 -0
- package/dist/llm/openai.js +49 -0
- package/dist/llm/openai.js.map +1 -0
- package/dist/llm/openrouter.d.ts +2 -0
- package/dist/llm/openrouter.js +55 -0
- package/dist/llm/openrouter.js.map +1 -0
- package/dist/llm/provider.d.ts +23 -0
- package/dist/llm/provider.js +58 -0
- package/dist/llm/provider.js.map +1 -0
- package/dist/llm/router.d.ts +8 -0
- package/dist/llm/router.js +103 -0
- package/dist/llm/router.js.map +1 -0
- package/dist/modes/agent.d.ts +17 -0
- package/dist/modes/agent.js +6 -0
- package/dist/modes/agent.js.map +1 -0
- package/dist/modes/ask.d.ts +8 -0
- package/dist/modes/ask.js +46 -0
- package/dist/modes/ask.js.map +1 -0
- package/dist/os/detect.d.ts +10 -0
- package/dist/os/detect.js +17 -0
- package/dist/os/detect.js.map +1 -0
- package/dist/os/pkgmgr.d.ts +6 -0
- package/dist/os/pkgmgr.js +32 -0
- package/dist/os/pkgmgr.js.map +1 -0
- package/dist/prompts/index.d.ts +2 -0
- package/dist/prompts/index.js +60 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/repl.d.ts +7 -0
- package/dist/repl.js +216 -0
- package/dist/repl.js.map +1 -0
- package/dist/safety/classifier.d.ts +8 -0
- package/dist/safety/classifier.js +118 -0
- package/dist/safety/classifier.js.map +1 -0
- package/dist/safety/patterns.d.ts +5 -0
- package/dist/safety/patterns.js +45 -0
- package/dist/safety/patterns.js.map +1 -0
- package/dist/store/config.d.ts +20 -0
- package/dist/store/config.js +46 -0
- package/dist/store/config.js.map +1 -0
- package/dist/store/history.d.ts +24 -0
- package/dist/store/history.js +145 -0
- package/dist/store/history.js.map +1 -0
- package/dist/store/keys.d.ts +10 -0
- package/dist/store/keys.js +115 -0
- package/dist/store/keys.js.map +1 -0
- package/dist/store/logs.d.ts +2 -0
- package/dist/store/logs.js +31 -0
- package/dist/store/logs.js.map +1 -0
- package/dist/store/project.d.ts +2 -0
- package/dist/store/project.js +14 -0
- package/dist/store/project.js.map +1 -0
- package/dist/tools/fs.d.ts +5 -0
- package/dist/tools/fs.js +82 -0
- package/dist/tools/fs.js.map +1 -0
- package/dist/tools/http.d.ts +6 -0
- package/dist/tools/http.js +14 -0
- package/dist/tools/http.js.map +1 -0
- package/dist/tools/registry.d.ts +5 -0
- package/dist/tools/registry.js +79 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/shell.d.ts +7 -0
- package/dist/tools/shell.js +16 -0
- package/dist/tools/shell.js.map +1 -0
- package/dist/types.d.ts +40 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/banner.d.ts +12 -0
- package/dist/ui/banner.js +55 -0
- package/dist/ui/banner.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { defaultModels, } from "./provider.js";
|
|
2
|
+
import { readJson } from "./http.js";
|
|
3
|
+
function geminiContents(messages) {
|
|
4
|
+
return messages
|
|
5
|
+
.filter((message) => message.role !== "system")
|
|
6
|
+
.map((message) => ({
|
|
7
|
+
role: message.role === "assistant" ? "model" : "user",
|
|
8
|
+
parts: [{ text: message.content }],
|
|
9
|
+
}));
|
|
10
|
+
}
|
|
11
|
+
function systemInstruction(messages) {
|
|
12
|
+
const system = messages.find((message) => message.role === "system");
|
|
13
|
+
return system ? { parts: [{ text: system.content }] } : undefined;
|
|
14
|
+
}
|
|
15
|
+
function geminiBody(request) {
|
|
16
|
+
return JSON.stringify({
|
|
17
|
+
systemInstruction: systemInstruction(request.messages),
|
|
18
|
+
contents: geminiContents(request.messages),
|
|
19
|
+
generationConfig: {
|
|
20
|
+
temperature: request.temperature ?? 0.2,
|
|
21
|
+
maxOutputTokens: request.maxTokens ?? 1_024,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export const geminiProvider = {
|
|
26
|
+
id: "gemini",
|
|
27
|
+
displayName: "Google Gemini",
|
|
28
|
+
defaultModel: defaultModels.gemini,
|
|
29
|
+
envVar: "GEMINI_API_KEY",
|
|
30
|
+
validateKey: (key) => /^AIza[0-9A-Za-z_-]{12,}$/.test(key),
|
|
31
|
+
async ping(auth) {
|
|
32
|
+
if (!auth.apiKey)
|
|
33
|
+
throw new Error("Gemini API key is required");
|
|
34
|
+
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models?key=${encodeURIComponent(auth.apiKey)}`);
|
|
35
|
+
await readJson(response);
|
|
36
|
+
},
|
|
37
|
+
async complete(request, auth) {
|
|
38
|
+
if (!auth.apiKey)
|
|
39
|
+
throw new Error("Gemini API key is required");
|
|
40
|
+
const model = request.model ?? defaultModels.gemini;
|
|
41
|
+
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${encodeURIComponent(model)}:generateContent?key=${encodeURIComponent(auth.apiKey)}`, {
|
|
42
|
+
method: "POST",
|
|
43
|
+
signal: request.signal ?? null,
|
|
44
|
+
headers: { "content-type": "application/json" },
|
|
45
|
+
body: geminiBody(request),
|
|
46
|
+
});
|
|
47
|
+
const data = await readJson(response);
|
|
48
|
+
const text = data.candidates?.[0]?.content?.parts
|
|
49
|
+
?.map((part) => part.text ?? "")
|
|
50
|
+
.join("")
|
|
51
|
+
.trim();
|
|
52
|
+
if (!text) {
|
|
53
|
+
throw new Error("Gemini returned no completion text");
|
|
54
|
+
}
|
|
55
|
+
return { text, provider: "gemini", model };
|
|
56
|
+
},
|
|
57
|
+
async stream(request, auth, onToken) {
|
|
58
|
+
if (!auth.apiKey)
|
|
59
|
+
throw new Error("Gemini API key is required");
|
|
60
|
+
const model = request.model ?? defaultModels.gemini;
|
|
61
|
+
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${encodeURIComponent(model)}:streamGenerateContent?alt=sse&key=${encodeURIComponent(auth.apiKey)}`, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
signal: request.signal ?? null,
|
|
64
|
+
headers: { "content-type": "application/json" },
|
|
65
|
+
body: geminiBody(request),
|
|
66
|
+
});
|
|
67
|
+
if (!response.ok) {
|
|
68
|
+
await readJson(response);
|
|
69
|
+
}
|
|
70
|
+
if (!response.body) {
|
|
71
|
+
throw new Error("Gemini returned no stream body");
|
|
72
|
+
}
|
|
73
|
+
const decoder = new TextDecoder();
|
|
74
|
+
const reader = response.body.getReader();
|
|
75
|
+
let buffer = "";
|
|
76
|
+
let full = "";
|
|
77
|
+
while (true) {
|
|
78
|
+
const { done, value } = await reader.read();
|
|
79
|
+
if (done)
|
|
80
|
+
break;
|
|
81
|
+
buffer += decoder.decode(value, { stream: true });
|
|
82
|
+
const lines = buffer.split("\n");
|
|
83
|
+
buffer = lines.pop() ?? "";
|
|
84
|
+
for (const line of lines) {
|
|
85
|
+
const trimmed = line.trim();
|
|
86
|
+
if (!trimmed.startsWith("data:"))
|
|
87
|
+
continue;
|
|
88
|
+
const payload = trimmed.slice(5).trim();
|
|
89
|
+
if (payload === "[DONE]")
|
|
90
|
+
return { text: full, provider: "gemini", model };
|
|
91
|
+
try {
|
|
92
|
+
const parsed = JSON.parse(payload);
|
|
93
|
+
const token = parsed.candidates?.[0]?.content?.parts
|
|
94
|
+
?.map((p) => p.text ?? "")
|
|
95
|
+
.join("");
|
|
96
|
+
if (token) {
|
|
97
|
+
full += token;
|
|
98
|
+
onToken(token);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// Ignore malformed keepalive lines.
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return { text: full, provider: "gemini", model };
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/llm/gemini.ts"],"names":[],"mappings":"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"}
|
package/dist/llm/groq.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { defaultModels, } from "./provider.js";
|
|
2
|
+
import { openAiCompatibleComplete, openAiCompatiblePing, openAiCompatibleStream, } from "./http.js";
|
|
3
|
+
const baseUrl = "https://api.groq.com/openai/v1";
|
|
4
|
+
export const groqProvider = {
|
|
5
|
+
id: "groq",
|
|
6
|
+
displayName: "Groq",
|
|
7
|
+
defaultModel: defaultModels.groq,
|
|
8
|
+
envVar: "GROQ_API_KEY",
|
|
9
|
+
validateKey: (key) => /^gsk_[A-Za-z0-9_-]{8,}$/.test(key),
|
|
10
|
+
async ping(auth) {
|
|
11
|
+
if (!auth.apiKey)
|
|
12
|
+
throw new Error("Groq API key is required");
|
|
13
|
+
await openAiCompatiblePing(baseUrl, auth.apiKey);
|
|
14
|
+
},
|
|
15
|
+
async complete(request, auth) {
|
|
16
|
+
if (!auth.apiKey)
|
|
17
|
+
throw new Error("Groq API key is required");
|
|
18
|
+
const model = request.model ?? defaultModels.groq;
|
|
19
|
+
const text = await openAiCompatibleComplete({
|
|
20
|
+
provider: "Groq",
|
|
21
|
+
baseUrl,
|
|
22
|
+
apiKey: auth.apiKey,
|
|
23
|
+
model,
|
|
24
|
+
messages: request.messages,
|
|
25
|
+
maxTokens: request.maxTokens,
|
|
26
|
+
temperature: request.temperature,
|
|
27
|
+
signal: request.signal,
|
|
28
|
+
});
|
|
29
|
+
return { text, provider: "groq", model };
|
|
30
|
+
},
|
|
31
|
+
async stream(request, auth, onToken) {
|
|
32
|
+
if (!auth.apiKey)
|
|
33
|
+
throw new Error("Groq API key is required");
|
|
34
|
+
const model = request.model ?? defaultModels.groq;
|
|
35
|
+
const text = await openAiCompatibleStream({
|
|
36
|
+
provider: "Groq",
|
|
37
|
+
baseUrl,
|
|
38
|
+
apiKey: auth.apiKey,
|
|
39
|
+
model,
|
|
40
|
+
messages: request.messages,
|
|
41
|
+
maxTokens: request.maxTokens,
|
|
42
|
+
temperature: request.temperature,
|
|
43
|
+
signal: request.signal,
|
|
44
|
+
onToken,
|
|
45
|
+
});
|
|
46
|
+
return { text, provider: "groq", model };
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=groq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groq.js","sourceRoot":"","sources":["../../src/llm/groq.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,GAGd,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AAEnB,MAAM,OAAO,GAAG,gCAAgC,CAAC;AAEjD,MAAM,CAAC,MAAM,YAAY,GAAgB;IACvC,EAAE,EAAE,MAAM;IACV,WAAW,EAAE,MAAM;IACnB,YAAY,EAAE,aAAa,CAAC,IAAI;IAChC,MAAM,EAAE,cAAc;IACtB,WAAW,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,GAAG,CAAC;IACjE,KAAK,CAAC,IAAI,CAAC,IAAkB;QAC3B,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9D,MAAM,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACnD,CAAC;IACD,KAAK,CAAC,QAAQ,CACZ,OAA0B,EAC1B,IAAkB;QAElB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,CAAC,IAAI,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC;YAC1C,QAAQ,EAAE,MAAM;YAChB,OAAO;YACP,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK;YACL,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC3C,CAAC;IACD,KAAK,CAAC,MAAM,CACV,OAA0B,EAC1B,IAAkB,EAClB,OAAgC;QAEhC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,CAAC,IAAI,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,sBAAsB,CAAC;YACxC,QAAQ,EAAE,MAAM;YAChB,OAAO;YACP,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK;YACL,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO;SACR,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC3C,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ChatMessage } from "../types.js";
|
|
2
|
+
export declare class ProviderError extends Error {
|
|
3
|
+
readonly status?: number | undefined;
|
|
4
|
+
readonly body?: string | undefined;
|
|
5
|
+
constructor(message: string, status?: number | undefined, body?: string | undefined);
|
|
6
|
+
}
|
|
7
|
+
export declare function readJson<T>(response: Response): Promise<T>;
|
|
8
|
+
export declare function toOpenAiMessages(messages: ChatMessage[]): Array<{
|
|
9
|
+
role: string;
|
|
10
|
+
content: string;
|
|
11
|
+
}>;
|
|
12
|
+
export declare function openAiCompatibleComplete(options: {
|
|
13
|
+
provider: string;
|
|
14
|
+
baseUrl: string;
|
|
15
|
+
apiKey: string;
|
|
16
|
+
model: string;
|
|
17
|
+
messages: ChatMessage[];
|
|
18
|
+
maxTokens?: number | undefined;
|
|
19
|
+
temperature?: number | undefined;
|
|
20
|
+
headers?: Record<string, string> | undefined;
|
|
21
|
+
signal?: AbortSignal | undefined;
|
|
22
|
+
}): Promise<string>;
|
|
23
|
+
export declare function openAiCompatibleStream(options: {
|
|
24
|
+
provider: string;
|
|
25
|
+
baseUrl: string;
|
|
26
|
+
apiKey: string;
|
|
27
|
+
model: string;
|
|
28
|
+
messages: ChatMessage[];
|
|
29
|
+
maxTokens?: number | undefined;
|
|
30
|
+
temperature?: number | undefined;
|
|
31
|
+
headers?: Record<string, string> | undefined;
|
|
32
|
+
signal?: AbortSignal | undefined;
|
|
33
|
+
onToken: (token: string) => void;
|
|
34
|
+
}): Promise<string>;
|
|
35
|
+
export declare function openAiCompatiblePing(baseUrl: string, apiKey: string, headers?: Record<string, string> | undefined): Promise<void>;
|
package/dist/llm/http.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
export class ProviderError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
body;
|
|
4
|
+
constructor(message, status, body) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.body = body;
|
|
8
|
+
this.name = "ProviderError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export async function readJson(response) {
|
|
12
|
+
const text = await response.text();
|
|
13
|
+
if (!response.ok) {
|
|
14
|
+
throw new ProviderError(`Provider request failed with HTTP ${response.status}`, response.status, text.slice(0, 1_000));
|
|
15
|
+
}
|
|
16
|
+
return JSON.parse(text);
|
|
17
|
+
}
|
|
18
|
+
export function toOpenAiMessages(messages) {
|
|
19
|
+
return messages.map((message) => ({
|
|
20
|
+
role: message.role === "tool" ? "user" : message.role,
|
|
21
|
+
content: message.content,
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
export async function openAiCompatibleComplete(options) {
|
|
25
|
+
const response = await fetch(`${options.baseUrl}/chat/completions`, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
signal: options.signal ?? null,
|
|
28
|
+
headers: {
|
|
29
|
+
"content-type": "application/json",
|
|
30
|
+
authorization: `Bearer ${options.apiKey}`,
|
|
31
|
+
...options.headers,
|
|
32
|
+
},
|
|
33
|
+
body: JSON.stringify({
|
|
34
|
+
model: options.model,
|
|
35
|
+
messages: toOpenAiMessages(options.messages),
|
|
36
|
+
max_tokens: options.maxTokens ?? 1_024,
|
|
37
|
+
temperature: options.temperature ?? 0.2,
|
|
38
|
+
stream: false,
|
|
39
|
+
}),
|
|
40
|
+
});
|
|
41
|
+
const data = await readJson(response);
|
|
42
|
+
const text = data.choices?.[0]?.message?.content;
|
|
43
|
+
if (!text) {
|
|
44
|
+
throw new ProviderError(`${options.provider} returned no completion text`);
|
|
45
|
+
}
|
|
46
|
+
return text;
|
|
47
|
+
}
|
|
48
|
+
export async function openAiCompatibleStream(options) {
|
|
49
|
+
const response = await fetch(`${options.baseUrl}/chat/completions`, {
|
|
50
|
+
method: "POST",
|
|
51
|
+
signal: options.signal ?? null,
|
|
52
|
+
headers: {
|
|
53
|
+
"content-type": "application/json",
|
|
54
|
+
authorization: `Bearer ${options.apiKey}`,
|
|
55
|
+
...options.headers,
|
|
56
|
+
},
|
|
57
|
+
body: JSON.stringify({
|
|
58
|
+
model: options.model,
|
|
59
|
+
messages: toOpenAiMessages(options.messages),
|
|
60
|
+
max_tokens: options.maxTokens ?? 1_024,
|
|
61
|
+
temperature: options.temperature ?? 0.2,
|
|
62
|
+
stream: true,
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
await readJson(response);
|
|
67
|
+
}
|
|
68
|
+
if (!response.body)
|
|
69
|
+
throw new ProviderError(`${options.provider} returned no stream body`);
|
|
70
|
+
const decoder = new TextDecoder();
|
|
71
|
+
const reader = response.body.getReader();
|
|
72
|
+
let buffer = "";
|
|
73
|
+
let full = "";
|
|
74
|
+
while (true) {
|
|
75
|
+
const { done, value } = await reader.read();
|
|
76
|
+
if (done)
|
|
77
|
+
break;
|
|
78
|
+
buffer += decoder.decode(value, { stream: true });
|
|
79
|
+
const lines = buffer.split("\n");
|
|
80
|
+
buffer = lines.pop() ?? "";
|
|
81
|
+
for (const line of lines) {
|
|
82
|
+
const trimmed = line.trim();
|
|
83
|
+
if (!trimmed.startsWith("data:"))
|
|
84
|
+
continue;
|
|
85
|
+
const payload = trimmed.slice(5).trim();
|
|
86
|
+
if (payload === "[DONE]")
|
|
87
|
+
return full;
|
|
88
|
+
try {
|
|
89
|
+
const parsed = JSON.parse(payload);
|
|
90
|
+
const token = parsed.choices?.[0]?.delta?.content;
|
|
91
|
+
if (token) {
|
|
92
|
+
full += token;
|
|
93
|
+
options.onToken(token);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Ignore malformed keepalive lines.
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return full;
|
|
102
|
+
}
|
|
103
|
+
export async function openAiCompatiblePing(baseUrl, apiKey, headers) {
|
|
104
|
+
const response = await fetch(`${baseUrl}/models`, {
|
|
105
|
+
headers: {
|
|
106
|
+
authorization: `Bearer ${apiKey}`,
|
|
107
|
+
...headers,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
await readJson(response);
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/llm/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { defaultModels, } from "./provider.js";
|
|
2
|
+
import { readJson } from "./http.js";
|
|
3
|
+
function base(auth) {
|
|
4
|
+
return (auth.baseUrl ?? auth.apiKey ?? "http://localhost:11434").replace(/\/$/, "");
|
|
5
|
+
}
|
|
6
|
+
export const ollamaProvider = {
|
|
7
|
+
id: "ollama",
|
|
8
|
+
displayName: "Ollama",
|
|
9
|
+
defaultModel: defaultModels.ollama,
|
|
10
|
+
envVar: "OLLAMA_HOST",
|
|
11
|
+
validateKey: (key) => /^https?:\/\/.+/.test(key),
|
|
12
|
+
async ping(auth) {
|
|
13
|
+
const response = await fetch(`${base(auth)}/api/tags`);
|
|
14
|
+
await readJson(response);
|
|
15
|
+
},
|
|
16
|
+
async complete(request, auth) {
|
|
17
|
+
const model = request.model ?? defaultModels.ollama;
|
|
18
|
+
const response = await fetch(`${base(auth)}/api/chat`, {
|
|
19
|
+
method: "POST",
|
|
20
|
+
signal: request.signal ?? null,
|
|
21
|
+
headers: { "content-type": "application/json" },
|
|
22
|
+
body: JSON.stringify({
|
|
23
|
+
model,
|
|
24
|
+
messages: request.messages.map((message) => ({
|
|
25
|
+
role: message.role === "tool" ? "user" : message.role,
|
|
26
|
+
content: message.content,
|
|
27
|
+
})),
|
|
28
|
+
stream: false,
|
|
29
|
+
options: { temperature: request.temperature ?? 0.2 },
|
|
30
|
+
}),
|
|
31
|
+
});
|
|
32
|
+
const data = await readJson(response);
|
|
33
|
+
const text = data.message?.content?.trim();
|
|
34
|
+
if (!text) {
|
|
35
|
+
throw new Error("Ollama returned no completion text");
|
|
36
|
+
}
|
|
37
|
+
return { text, provider: "ollama", model };
|
|
38
|
+
},
|
|
39
|
+
async stream(request, auth, onToken) {
|
|
40
|
+
const model = request.model ?? defaultModels.ollama;
|
|
41
|
+
const response = await fetch(`${base(auth)}/api/chat`, {
|
|
42
|
+
method: "POST",
|
|
43
|
+
signal: request.signal ?? null,
|
|
44
|
+
headers: { "content-type": "application/json" },
|
|
45
|
+
body: JSON.stringify({
|
|
46
|
+
model,
|
|
47
|
+
messages: request.messages.map((message) => ({
|
|
48
|
+
role: message.role === "tool" ? "user" : message.role,
|
|
49
|
+
content: message.content,
|
|
50
|
+
})),
|
|
51
|
+
stream: true,
|
|
52
|
+
options: { temperature: request.temperature ?? 0.2 },
|
|
53
|
+
}),
|
|
54
|
+
});
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
await readJson(response);
|
|
57
|
+
}
|
|
58
|
+
if (!response.body) {
|
|
59
|
+
throw new Error("Ollama returned no stream body");
|
|
60
|
+
}
|
|
61
|
+
const decoder = new TextDecoder();
|
|
62
|
+
const reader = response.body.getReader();
|
|
63
|
+
let buffer = "";
|
|
64
|
+
let full = "";
|
|
65
|
+
while (true) {
|
|
66
|
+
const { done, value } = await reader.read();
|
|
67
|
+
if (done)
|
|
68
|
+
break;
|
|
69
|
+
buffer += decoder.decode(value, { stream: true });
|
|
70
|
+
const lines = buffer.split("\n");
|
|
71
|
+
buffer = lines.pop() ?? "";
|
|
72
|
+
for (const line of lines) {
|
|
73
|
+
const trimmed = line.trim();
|
|
74
|
+
if (!trimmed)
|
|
75
|
+
continue;
|
|
76
|
+
try {
|
|
77
|
+
const parsed = JSON.parse(trimmed);
|
|
78
|
+
const token = parsed.message?.content;
|
|
79
|
+
if (token) {
|
|
80
|
+
full += token;
|
|
81
|
+
onToken(token);
|
|
82
|
+
}
|
|
83
|
+
if (parsed.done) {
|
|
84
|
+
return { text: full, provider: "ollama", model };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Ignore malformed lines.
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return { text: full, provider: "ollama", model };
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=ollama.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/llm/ollama.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { defaultModels, } from "./provider.js";
|
|
2
|
+
import { openAiCompatibleComplete, openAiCompatiblePing, openAiCompatibleStream, } from "./http.js";
|
|
3
|
+
const baseUrl = "https://api.openai.com/v1";
|
|
4
|
+
export const openaiProvider = {
|
|
5
|
+
id: "openai",
|
|
6
|
+
displayName: "OpenAI",
|
|
7
|
+
defaultModel: defaultModels.openai,
|
|
8
|
+
envVar: "OPENAI_API_KEY",
|
|
9
|
+
validateKey: (key) => /^sk-[A-Za-z0-9_-]{12,}$/.test(key),
|
|
10
|
+
async ping(auth) {
|
|
11
|
+
if (!auth.apiKey)
|
|
12
|
+
throw new Error("OpenAI API key is required");
|
|
13
|
+
await openAiCompatiblePing(baseUrl, auth.apiKey);
|
|
14
|
+
},
|
|
15
|
+
async complete(request, auth) {
|
|
16
|
+
if (!auth.apiKey)
|
|
17
|
+
throw new Error("OpenAI API key is required");
|
|
18
|
+
const model = request.model ?? defaultModels.openai;
|
|
19
|
+
const text = await openAiCompatibleComplete({
|
|
20
|
+
provider: "OpenAI",
|
|
21
|
+
baseUrl,
|
|
22
|
+
apiKey: auth.apiKey,
|
|
23
|
+
model,
|
|
24
|
+
messages: request.messages,
|
|
25
|
+
maxTokens: request.maxTokens,
|
|
26
|
+
temperature: request.temperature,
|
|
27
|
+
signal: request.signal,
|
|
28
|
+
});
|
|
29
|
+
return { text, provider: "openai", model };
|
|
30
|
+
},
|
|
31
|
+
async stream(request, auth, onToken) {
|
|
32
|
+
if (!auth.apiKey)
|
|
33
|
+
throw new Error("OpenAI API key is required");
|
|
34
|
+
const model = request.model ?? defaultModels.openai;
|
|
35
|
+
const text = await openAiCompatibleStream({
|
|
36
|
+
provider: "OpenAI",
|
|
37
|
+
baseUrl,
|
|
38
|
+
apiKey: auth.apiKey,
|
|
39
|
+
model,
|
|
40
|
+
messages: request.messages,
|
|
41
|
+
maxTokens: request.maxTokens,
|
|
42
|
+
temperature: request.temperature,
|
|
43
|
+
signal: request.signal,
|
|
44
|
+
onToken,
|
|
45
|
+
});
|
|
46
|
+
return { text, provider: "openai", model };
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/llm/openai.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,GAGd,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AAEnB,MAAM,OAAO,GAAG,2BAA2B,CAAC;AAE5C,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,EAAE,EAAE,QAAQ;IACZ,WAAW,EAAE,QAAQ;IACrB,YAAY,EAAE,aAAa,CAAC,MAAM;IAClC,MAAM,EAAE,gBAAgB;IACxB,WAAW,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,GAAG,CAAC;IACjE,KAAK,CAAC,IAAI,CAAC,IAAkB;QAC3B,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChE,MAAM,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACnD,CAAC;IACD,KAAK,CAAC,QAAQ,CACZ,OAA0B,EAC1B,IAAkB;QAElB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,CAAC,MAAM,CAAC;QACpD,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC;YAC1C,QAAQ,EAAE,QAAQ;YAClB,OAAO;YACP,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK;YACL,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7C,CAAC;IACD,KAAK,CAAC,MAAM,CACV,OAA0B,EAC1B,IAAkB,EAClB,OAAgC;QAEhC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,CAAC,MAAM,CAAC;QACpD,MAAM,IAAI,GAAG,MAAM,sBAAsB,CAAC;YACxC,QAAQ,EAAE,QAAQ;YAClB,OAAO;YACP,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK;YACL,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO;SACR,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7C,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { defaultModels, } from "./provider.js";
|
|
2
|
+
import { openAiCompatibleComplete, openAiCompatiblePing, openAiCompatibleStream, } from "./http.js";
|
|
3
|
+
const baseUrl = "https://openrouter.ai/api/v1";
|
|
4
|
+
const headers = {
|
|
5
|
+
"HTTP-Referer": "https://github.com/clai/clai",
|
|
6
|
+
"X-Title": "clai",
|
|
7
|
+
};
|
|
8
|
+
export const openrouterProvider = {
|
|
9
|
+
id: "openrouter",
|
|
10
|
+
displayName: "OpenRouter",
|
|
11
|
+
defaultModel: defaultModels.openrouter,
|
|
12
|
+
envVar: "OPENROUTER_API_KEY",
|
|
13
|
+
validateKey: (key) => /^(sk-or-|or-)[A-Za-z0-9_-]{12,}$/.test(key),
|
|
14
|
+
async ping(auth) {
|
|
15
|
+
if (!auth.apiKey)
|
|
16
|
+
throw new Error("OpenRouter API key is required");
|
|
17
|
+
await openAiCompatiblePing(baseUrl, auth.apiKey, headers);
|
|
18
|
+
},
|
|
19
|
+
async complete(request, auth) {
|
|
20
|
+
if (!auth.apiKey)
|
|
21
|
+
throw new Error("OpenRouter API key is required");
|
|
22
|
+
const model = request.model ?? defaultModels.openrouter;
|
|
23
|
+
const text = await openAiCompatibleComplete({
|
|
24
|
+
provider: "OpenRouter",
|
|
25
|
+
baseUrl,
|
|
26
|
+
apiKey: auth.apiKey,
|
|
27
|
+
model,
|
|
28
|
+
messages: request.messages,
|
|
29
|
+
maxTokens: request.maxTokens,
|
|
30
|
+
temperature: request.temperature,
|
|
31
|
+
headers,
|
|
32
|
+
signal: request.signal,
|
|
33
|
+
});
|
|
34
|
+
return { text, provider: "openrouter", model };
|
|
35
|
+
},
|
|
36
|
+
async stream(request, auth, onToken) {
|
|
37
|
+
if (!auth.apiKey)
|
|
38
|
+
throw new Error("OpenRouter API key is required");
|
|
39
|
+
const model = request.model ?? defaultModels.openrouter;
|
|
40
|
+
const text = await openAiCompatibleStream({
|
|
41
|
+
provider: "OpenRouter",
|
|
42
|
+
baseUrl,
|
|
43
|
+
apiKey: auth.apiKey,
|
|
44
|
+
model,
|
|
45
|
+
messages: request.messages,
|
|
46
|
+
maxTokens: request.maxTokens,
|
|
47
|
+
temperature: request.temperature,
|
|
48
|
+
headers,
|
|
49
|
+
signal: request.signal,
|
|
50
|
+
onToken,
|
|
51
|
+
});
|
|
52
|
+
return { text, provider: "openrouter", model };
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=openrouter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../../src/llm/openrouter.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,GAGd,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AAEnB,MAAM,OAAO,GAAG,8BAA8B,CAAC;AAC/C,MAAM,OAAO,GAAG;IACd,cAAc,EAAE,8BAA8B;IAC9C,SAAS,EAAE,MAAM;CAClB,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAgB;IAC7C,EAAE,EAAE,YAAY;IAChB,WAAW,EAAE,YAAY;IACzB,YAAY,EAAE,aAAa,CAAC,UAAU;IACtC,MAAM,EAAE,oBAAoB;IAC5B,WAAW,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,kCAAkC,CAAC,IAAI,CAAC,GAAG,CAAC;IAC1E,KAAK,CAAC,IAAI,CAAC,IAAkB;QAC3B,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpE,MAAM,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;IACD,KAAK,CAAC,QAAQ,CACZ,OAA0B,EAC1B,IAAkB;QAElB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,CAAC,UAAU,CAAC;QACxD,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC;YAC1C,QAAQ,EAAE,YAAY;YACtB,OAAO;YACP,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK;YACL,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,OAAO;YACP,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACjD,CAAC;IACD,KAAK,CAAC,MAAM,CACV,OAA0B,EAC1B,IAAkB,EAClB,OAAgC;QAEhC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,CAAC,UAAU,CAAC;QACxD,MAAM,IAAI,GAAG,MAAM,sBAAsB,CAAC;YACxC,QAAQ,EAAE,YAAY;YACtB,OAAO;YACP,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK;YACL,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,OAAO;YACP,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO;SACR,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACjD,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CompletionRequest, CompletionResult, ProviderId } from "../types.js";
|
|
2
|
+
export interface LlmProvider {
|
|
3
|
+
id: ProviderId;
|
|
4
|
+
displayName: string;
|
|
5
|
+
defaultModel: string;
|
|
6
|
+
envVar?: string | undefined;
|
|
7
|
+
validateKey(key: string): boolean;
|
|
8
|
+
ping(options: ProviderAuth): Promise<void>;
|
|
9
|
+
complete(request: CompletionRequest, auth: ProviderAuth): Promise<CompletionResult>;
|
|
10
|
+
stream?(request: CompletionRequest, auth: ProviderAuth, onToken: (token: string) => void): Promise<CompletionResult>;
|
|
11
|
+
}
|
|
12
|
+
export interface ProviderAuth {
|
|
13
|
+
apiKey?: string | undefined;
|
|
14
|
+
baseUrl?: string | undefined;
|
|
15
|
+
}
|
|
16
|
+
export declare const providerAliases: Record<string, ProviderId>;
|
|
17
|
+
export declare const defaultModels: Record<ProviderId, string>;
|
|
18
|
+
export declare const envVars: Record<ProviderId, string | undefined>;
|
|
19
|
+
export declare function normalizeProvider(value: string): ProviderId | undefined;
|
|
20
|
+
export declare function assertProvider(value: string): ProviderId;
|
|
21
|
+
export declare function getDefaultModel(provider: ProviderId): string;
|
|
22
|
+
export declare function maskSecret(secret: string): string;
|
|
23
|
+
export declare function redactSecrets(value: string): string;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { providerIds } from "../types.js";
|
|
2
|
+
export const providerAliases = {
|
|
3
|
+
groq: "groq",
|
|
4
|
+
gemini: "gemini",
|
|
5
|
+
google: "gemini",
|
|
6
|
+
openrouter: "openrouter",
|
|
7
|
+
openai: "openai",
|
|
8
|
+
anthropic: "anthropic",
|
|
9
|
+
claude: "anthropic",
|
|
10
|
+
ollama: "ollama",
|
|
11
|
+
local: "ollama",
|
|
12
|
+
};
|
|
13
|
+
export const defaultModels = {
|
|
14
|
+
groq: "llama-3.3-70b-versatile",
|
|
15
|
+
gemini: "gemini-2.0-flash",
|
|
16
|
+
openrouter: "meta-llama/llama-3.3-70b-instruct:free",
|
|
17
|
+
openai: "gpt-4o-mini",
|
|
18
|
+
anthropic: "claude-3-5-haiku-latest",
|
|
19
|
+
ollama: "llama3.1:8b",
|
|
20
|
+
};
|
|
21
|
+
export const envVars = {
|
|
22
|
+
groq: "GROQ_API_KEY",
|
|
23
|
+
gemini: "GEMINI_API_KEY",
|
|
24
|
+
openrouter: "OPENROUTER_API_KEY",
|
|
25
|
+
openai: "OPENAI_API_KEY",
|
|
26
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
27
|
+
ollama: "OLLAMA_HOST",
|
|
28
|
+
};
|
|
29
|
+
export function normalizeProvider(value) {
|
|
30
|
+
return providerAliases[value.trim().toLowerCase()];
|
|
31
|
+
}
|
|
32
|
+
export function assertProvider(value) {
|
|
33
|
+
const provider = normalizeProvider(value);
|
|
34
|
+
if (!provider) {
|
|
35
|
+
throw new Error(`Unsupported provider "${value}". Supported providers: ${providerIds.join(", ")}`);
|
|
36
|
+
}
|
|
37
|
+
return provider;
|
|
38
|
+
}
|
|
39
|
+
export function getDefaultModel(provider) {
|
|
40
|
+
return defaultModels[provider];
|
|
41
|
+
}
|
|
42
|
+
export function maskSecret(secret) {
|
|
43
|
+
if (secret.length <= 4) {
|
|
44
|
+
return "••••";
|
|
45
|
+
}
|
|
46
|
+
const knownPrefix = ["gsk_", "AIza", "sk-or-", "sk-ant-", "sk-"].find((prefix) => secret.startsWith(prefix)) ?? "";
|
|
47
|
+
const suffix = secret.slice(-4);
|
|
48
|
+
return `${knownPrefix}••••••${suffix}`;
|
|
49
|
+
}
|
|
50
|
+
export function redactSecrets(value) {
|
|
51
|
+
return value
|
|
52
|
+
.replace(/gsk_[A-Za-z0-9_-]+/g, "gsk_••••••")
|
|
53
|
+
.replace(/AIza[0-9A-Za-z_-]+/g, "AIza••••••")
|
|
54
|
+
.replace(/sk-[A-Za-z0-9_-]+/g, "sk-••••••")
|
|
55
|
+
.replace(/sk-or-[A-Za-z0-9_-]+/g, "sk-or-••••••")
|
|
56
|
+
.replace(/sk-ant-[A-Za-z0-9_-]+/g, "sk-ant-••••••");
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/llm/provider.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAyB1C,MAAM,CAAC,MAAM,eAAe,GAA+B;IACzD,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,YAAY;IACxB,MAAM,EAAE,QAAQ;IAChB,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,QAAQ;CAChB,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAA+B;IACvD,IAAI,EAAE,yBAAyB;IAC/B,MAAM,EAAE,kBAAkB;IAC1B,UAAU,EAAE,wCAAwC;IACpD,MAAM,EAAE,aAAa;IACrB,SAAS,EAAE,yBAAyB;IACpC,MAAM,EAAE,aAAa;CACtB,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAA2C;IAC7D,IAAI,EAAE,cAAc;IACpB,MAAM,EAAE,gBAAgB;IACxB,UAAU,EAAE,oBAAoB;IAChC,MAAM,EAAE,gBAAgB;IACxB,SAAS,EAAE,mBAAmB;IAC9B,MAAM,EAAE,aAAa;CACtB,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,yBAAyB,KAAK,2BAA2B,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAClF,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAoB;IAClD,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,WAAW,GACf,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAC3D,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAC1B,IAAI,EAAE,CAAC;IACV,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,OAAO,GAAG,WAAW,SAAS,MAAM,EAAE,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,KAAK;SACT,OAAO,CAAC,qBAAqB,EAAE,YAAY,CAAC;SAC5C,OAAO,CAAC,qBAAqB,EAAE,YAAY,CAAC;SAC5C,OAAO,CAAC,oBAAoB,EAAE,WAAW,CAAC;SAC1C,OAAO,CAAC,uBAAuB,EAAE,cAAc,CAAC;SAChD,OAAO,CAAC,wBAAwB,EAAE,eAAe,CAAC,CAAC;AACxD,CAAC"}
|