agent-bober 0.6.1 → 0.7.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 +159 -28
- package/dist/cli/commands/eval.d.ts +2 -0
- package/dist/cli/commands/eval.d.ts.map +1 -1
- package/dist/cli/commands/eval.js +10 -0
- package/dist/cli/commands/eval.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +181 -61
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/plan.d.ts +2 -0
- package/dist/cli/commands/plan.d.ts.map +1 -1
- package/dist/cli/commands/plan.js +10 -0
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/run.d.ts +2 -0
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +10 -0
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/sprint.d.ts +2 -0
- package/dist/cli/commands/sprint.d.ts.map +1 -1
- package/dist/cli/commands/sprint.js +10 -0
- package/dist/cli/commands/sprint.js.map +1 -1
- package/dist/cli/index.js +22 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/config/schema.d.ts +160 -43
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +11 -7
- package/dist/config/schema.js.map +1 -1
- package/dist/contracts/sprint-contract.d.ts +8 -8
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts +4 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +4 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/run-manager.d.ts +47 -0
- package/dist/mcp/run-manager.d.ts.map +1 -0
- package/dist/mcp/run-manager.js +79 -0
- package/dist/mcp/run-manager.js.map +1 -0
- package/dist/mcp/server.d.ts +15 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +107 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/config.d.ts +2 -0
- package/dist/mcp/tools/config.d.ts.map +1 -0
- package/dist/mcp/tools/config.js +153 -0
- package/dist/mcp/tools/config.js.map +1 -0
- package/dist/mcp/tools/contracts.d.ts +2 -0
- package/dist/mcp/tools/contracts.d.ts.map +1 -0
- package/dist/mcp/tools/contracts.js +61 -0
- package/dist/mcp/tools/contracts.js.map +1 -0
- package/dist/mcp/tools/eval.d.ts +2 -0
- package/dist/mcp/tools/eval.d.ts.map +1 -0
- package/dist/mcp/tools/eval.js +157 -0
- package/dist/mcp/tools/eval.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +20 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +47 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/init.d.ts +2 -0
- package/dist/mcp/tools/init.d.ts.map +1 -0
- package/dist/mcp/tools/init.js +121 -0
- package/dist/mcp/tools/init.js.map +1 -0
- package/dist/mcp/tools/plan.d.ts +2 -0
- package/dist/mcp/tools/plan.d.ts.map +1 -0
- package/dist/mcp/tools/plan.js +97 -0
- package/dist/mcp/tools/plan.js.map +1 -0
- package/dist/mcp/tools/principles.d.ts +2 -0
- package/dist/mcp/tools/principles.d.ts.map +1 -0
- package/dist/mcp/tools/principles.js +66 -0
- package/dist/mcp/tools/principles.js.map +1 -0
- package/dist/mcp/tools/registry.d.ts +45 -0
- package/dist/mcp/tools/registry.d.ts.map +1 -0
- package/dist/mcp/tools/registry.js +23 -0
- package/dist/mcp/tools/registry.js.map +1 -0
- package/dist/mcp/tools/run.d.ts +2 -0
- package/dist/mcp/tools/run.d.ts.map +1 -0
- package/dist/mcp/tools/run.js +66 -0
- package/dist/mcp/tools/run.js.map +1 -0
- package/dist/mcp/tools/spec.d.ts +2 -0
- package/dist/mcp/tools/spec.d.ts.map +1 -0
- package/dist/mcp/tools/spec.js +32 -0
- package/dist/mcp/tools/spec.js.map +1 -0
- package/dist/mcp/tools/sprint.d.ts +2 -0
- package/dist/mcp/tools/sprint.d.ts.map +1 -0
- package/dist/mcp/tools/sprint.js +243 -0
- package/dist/mcp/tools/sprint.js.map +1 -0
- package/dist/mcp/tools/status.d.ts +2 -0
- package/dist/mcp/tools/status.d.ts.map +1 -0
- package/dist/mcp/tools/status.js +76 -0
- package/dist/mcp/tools/status.js.map +1 -0
- package/dist/orchestrator/agentic-loop.d.ts +7 -6
- package/dist/orchestrator/agentic-loop.d.ts.map +1 -1
- package/dist/orchestrator/agentic-loop.js +33 -40
- package/dist/orchestrator/agentic-loop.js.map +1 -1
- package/dist/orchestrator/context-handoff.d.ts +20 -20
- package/dist/orchestrator/evaluator-agent.d.ts.map +1 -1
- package/dist/orchestrator/evaluator-agent.js +2 -2
- package/dist/orchestrator/evaluator-agent.js.map +1 -1
- package/dist/orchestrator/generator-agent.d.ts.map +1 -1
- package/dist/orchestrator/generator-agent.js +2 -2
- package/dist/orchestrator/generator-agent.js.map +1 -1
- package/dist/orchestrator/model-resolver.d.ts +35 -4
- package/dist/orchestrator/model-resolver.d.ts.map +1 -1
- package/dist/orchestrator/model-resolver.js +68 -15
- package/dist/orchestrator/model-resolver.js.map +1 -1
- package/dist/orchestrator/planner-agent.d.ts.map +1 -1
- package/dist/orchestrator/planner-agent.js +2 -2
- package/dist/orchestrator/planner-agent.js.map +1 -1
- package/dist/orchestrator/tools/index.d.ts +3 -4
- package/dist/orchestrator/tools/index.d.ts.map +1 -1
- package/dist/orchestrator/tools/index.js.map +1 -1
- package/dist/orchestrator/tools/schemas.d.ts +11 -12
- package/dist/orchestrator/tools/schemas.d.ts.map +1 -1
- package/dist/orchestrator/tools/schemas.js +3 -2
- package/dist/orchestrator/tools/schemas.js.map +1 -1
- package/dist/providers/anthropic.d.ts +15 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +133 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/factory.d.ts +37 -0
- package/dist/providers/factory.d.ts.map +1 -0
- package/dist/providers/factory.js +119 -0
- package/dist/providers/factory.js.map +1 -0
- package/dist/providers/google.d.ts +39 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +195 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +6 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai-compat.d.ts +39 -0
- package/dist/providers/openai-compat.d.ts.map +1 -0
- package/dist/providers/openai-compat.js +42 -0
- package/dist/providers/openai-compat.js.map +1 -0
- package/dist/providers/openai.d.ts +41 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +205 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/types.d.ts +144 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +8 -0
- package/dist/providers/types.js.map +1 -0
- package/package.json +26 -4
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Gemini provider adapter.
|
|
3
|
+
*
|
|
4
|
+
* Uses a dynamic import so the `@google/generative-ai` package is an optional
|
|
5
|
+
* peer dependency. If the package is not installed, a clear installation error
|
|
6
|
+
* is thrown at call-time rather than at module load time.
|
|
7
|
+
*
|
|
8
|
+
* All Gemini SDK types are inlined below so this file compiles without the
|
|
9
|
+
* `@google/generative-ai` package present in node_modules.
|
|
10
|
+
*/
|
|
11
|
+
// ── Conversion helpers ───────────────────────────────────────────────
|
|
12
|
+
/**
|
|
13
|
+
* Convert a provider-agnostic ToolDef to Gemini functionDeclarations format.
|
|
14
|
+
*/
|
|
15
|
+
function toGeminiTool(tools) {
|
|
16
|
+
return {
|
|
17
|
+
functionDeclarations: tools.map((tool) => ({
|
|
18
|
+
name: tool.name,
|
|
19
|
+
description: tool.description,
|
|
20
|
+
parameters: tool.input_schema,
|
|
21
|
+
})),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Normalize a Gemini finishReason to our StopReason type.
|
|
26
|
+
*/
|
|
27
|
+
function normalizeStopReason(finishReason) {
|
|
28
|
+
switch (finishReason) {
|
|
29
|
+
case "STOP":
|
|
30
|
+
return "end";
|
|
31
|
+
case "MAX_TOKENS":
|
|
32
|
+
return "max_tokens";
|
|
33
|
+
default:
|
|
34
|
+
return "end";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Convert a provider-agnostic Message to Gemini content format.
|
|
39
|
+
*
|
|
40
|
+
* Returns an array because ToolResultMessage may need special handling —
|
|
41
|
+
* Gemini uses role "function" with functionResponse parts for tool results.
|
|
42
|
+
*/
|
|
43
|
+
function toGeminiContents(message) {
|
|
44
|
+
// ToolResultMessage → role:"function" with functionResponse parts
|
|
45
|
+
if ("toolResults" in message) {
|
|
46
|
+
return message.toolResults.map((tr) => ({
|
|
47
|
+
role: "function",
|
|
48
|
+
parts: [
|
|
49
|
+
{
|
|
50
|
+
functionResponse: {
|
|
51
|
+
name: tr.toolUseId,
|
|
52
|
+
response: { content: tr.content },
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
// AssistantMessage (with tool calls) → role:"model" with functionCall parts
|
|
59
|
+
if ("toolCalls" in message && message.toolCalls.length > 0) {
|
|
60
|
+
const parts = [];
|
|
61
|
+
if (message.content) {
|
|
62
|
+
parts.push({ text: message.content });
|
|
63
|
+
}
|
|
64
|
+
for (const tc of message.toolCalls) {
|
|
65
|
+
parts.push({
|
|
66
|
+
functionCall: {
|
|
67
|
+
name: tc.name,
|
|
68
|
+
args: tc.input,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return [{ role: "model", parts }];
|
|
73
|
+
}
|
|
74
|
+
// TextMessage — map "user" → "user", "assistant" → "model"
|
|
75
|
+
const textMsg = message;
|
|
76
|
+
const geminiRole = textMsg.role === "assistant" ? "model" : "user";
|
|
77
|
+
return [{ role: geminiRole, parts: [{ text: textMsg.content }] }];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Extract normalized text and tool calls from Gemini response parts.
|
|
81
|
+
*/
|
|
82
|
+
function normalizeResponseParts(parts) {
|
|
83
|
+
let text = "";
|
|
84
|
+
const toolCalls = [];
|
|
85
|
+
for (const part of parts) {
|
|
86
|
+
if ("text" in part && typeof part.text === "string") {
|
|
87
|
+
text += part.text;
|
|
88
|
+
}
|
|
89
|
+
else if ("functionCall" in part) {
|
|
90
|
+
// Gemini does not provide a stable call ID — synthesize one from index
|
|
91
|
+
const callId = `gemini-call-${toolCalls.length}-${part.functionCall.name}`;
|
|
92
|
+
toolCalls.push({
|
|
93
|
+
id: callId,
|
|
94
|
+
name: part.functionCall.name,
|
|
95
|
+
input: part.functionCall.args ?? {},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return { text, toolCalls };
|
|
100
|
+
}
|
|
101
|
+
// ── GoogleAdapter ────────────────────────────────────────────────────
|
|
102
|
+
/**
|
|
103
|
+
* LLMClient implementation that wraps the Google Gemini API.
|
|
104
|
+
*
|
|
105
|
+
* The `@google/generative-ai` npm package is dynamically imported so it
|
|
106
|
+
* remains an optional peer dependency. If the package is absent a descriptive
|
|
107
|
+
* install error is thrown on the first call.
|
|
108
|
+
*
|
|
109
|
+
* Supports:
|
|
110
|
+
* - Function/tool calling via functionDeclarations format
|
|
111
|
+
* - System instruction passed via model config
|
|
112
|
+
* - Message history with user/model/function roles
|
|
113
|
+
*/
|
|
114
|
+
export class GoogleAdapter {
|
|
115
|
+
model;
|
|
116
|
+
apiKey;
|
|
117
|
+
/** Lazily initialised after the dynamic import succeeds. */
|
|
118
|
+
genAI = null;
|
|
119
|
+
constructor(model, apiKey) {
|
|
120
|
+
this.model = model;
|
|
121
|
+
this.apiKey = apiKey;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Lazily import the `@google/generative-ai` package and return the
|
|
125
|
+
* initialised GoogleGenerativeAI client.
|
|
126
|
+
*
|
|
127
|
+
* @throws If the `@google/generative-ai` package is not installed.
|
|
128
|
+
*/
|
|
129
|
+
async getGenAI() {
|
|
130
|
+
if (this.genAI) {
|
|
131
|
+
return this.genAI;
|
|
132
|
+
}
|
|
133
|
+
let GoogleGenerativeAI;
|
|
134
|
+
try {
|
|
135
|
+
// Construct the specifier at runtime so TypeScript does not attempt
|
|
136
|
+
// to statically resolve the optional peer dependency at compile time.
|
|
137
|
+
const specifier = "@google/generative-ai";
|
|
138
|
+
const mod = (await import(/* @vite-ignore */ specifier));
|
|
139
|
+
// Handle both ESM default export and CommonJS-style .default wrapping
|
|
140
|
+
GoogleGenerativeAI = (mod["GoogleGenerativeAI"] ?? mod["default"]);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
throw new Error('Google provider requires the "@google/generative-ai" package. Run: npm install @google/generative-ai');
|
|
144
|
+
}
|
|
145
|
+
const apiKey = this.apiKey ??
|
|
146
|
+
process.env["GOOGLE_API_KEY"] ??
|
|
147
|
+
process.env["GEMINI_API_KEY"];
|
|
148
|
+
if (!apiKey) {
|
|
149
|
+
throw new Error("Google provider requires an API key. Set GOOGLE_API_KEY or GEMINI_API_KEY environment variable.");
|
|
150
|
+
}
|
|
151
|
+
this.genAI = new GoogleGenerativeAI(apiKey);
|
|
152
|
+
return this.genAI;
|
|
153
|
+
}
|
|
154
|
+
async chat(params) {
|
|
155
|
+
const { model, system, messages, tools, maxTokens: _maxTokens = 16384 } = params;
|
|
156
|
+
const genAI = await this.getGenAI();
|
|
157
|
+
// Get the generative model — system instruction set at model config level
|
|
158
|
+
const generativeModel = genAI.getGenerativeModel({
|
|
159
|
+
model: model || this.model,
|
|
160
|
+
...(system ? { systemInstruction: system } : {}),
|
|
161
|
+
});
|
|
162
|
+
// Convert provider-agnostic Message[] to Gemini contents format
|
|
163
|
+
const contents = messages.flatMap(toGeminiContents);
|
|
164
|
+
// Convert ToolDef[] to Gemini tools format (all declarations in one tool)
|
|
165
|
+
const geminiTools = tools && tools.length > 0 ? [toGeminiTool(tools)] : undefined;
|
|
166
|
+
const result = await generativeModel.generateContent({
|
|
167
|
+
contents,
|
|
168
|
+
...(geminiTools ? { tools: geminiTools } : {}),
|
|
169
|
+
});
|
|
170
|
+
const candidate = result.response.candidates?.[0];
|
|
171
|
+
if (!candidate) {
|
|
172
|
+
return {
|
|
173
|
+
text: "",
|
|
174
|
+
toolCalls: [],
|
|
175
|
+
stopReason: "error",
|
|
176
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
const parts = candidate.content?.parts ?? [];
|
|
180
|
+
const { text, toolCalls } = normalizeResponseParts(parts);
|
|
181
|
+
const stopReason = normalizeStopReason(candidate.finishReason);
|
|
182
|
+
// Determine stopReason based on whether there are tool calls
|
|
183
|
+
const finalStopReason = toolCalls.length > 0 ? "tool_use" : stopReason;
|
|
184
|
+
return {
|
|
185
|
+
text,
|
|
186
|
+
toolCalls,
|
|
187
|
+
stopReason: finalStopReason,
|
|
188
|
+
usage: {
|
|
189
|
+
inputTokens: result.response.usageMetadata?.promptTokenCount ?? 0,
|
|
190
|
+
outputTokens: result.response.usageMetadata?.candidatesTokenCount ?? 0,
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=google.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.js","sourceRoot":"","sources":["../../src/providers/google.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { JsonSchemaProperty, JsonSchemaObject, ToolDef, ToolCall, ToolResult, TextMessage, AssistantMessage, ToolResultMessage, Message, ChatParams, ChatResponse, StopReason, LLMClient, } from "./types.js";
|
|
2
|
+
export { AnthropicAdapter } from "./anthropic.js";
|
|
3
|
+
export { OpenAIAdapter } from "./openai.js";
|
|
4
|
+
export { GoogleAdapter } from "./google.js";
|
|
5
|
+
export { OpenAICompatAdapter } from "./openai-compat.js";
|
|
6
|
+
export { createClient, type ProviderName } from "./factory.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,OAAO,EACP,QAAQ,EACR,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,OAAO,EACP,UAAU,EACV,YAAY,EACZ,UAAU,EACV,SAAS,GACV,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { AnthropicAdapter } from "./anthropic.js";
|
|
2
|
+
export { OpenAIAdapter } from "./openai.js";
|
|
3
|
+
export { GoogleAdapter } from "./google.js";
|
|
4
|
+
export { OpenAICompatAdapter } from "./openai-compat.js";
|
|
5
|
+
export { createClient } from "./factory.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAqB,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI-compatible provider adapter.
|
|
3
|
+
*
|
|
4
|
+
* Creates an OpenAI client pointed at a custom base URL, enabling use with
|
|
5
|
+
* any OpenAI-compatible API server (e.g. Ollama, LM Studio, vLLM, Together AI).
|
|
6
|
+
*
|
|
7
|
+
* Reuses all tool conversion, message conversion, and response normalisation
|
|
8
|
+
* logic from OpenAIAdapter by extending it with a custom base URL and a
|
|
9
|
+
* default API key of "not-needed" (required by the openai SDK but ignored
|
|
10
|
+
* by servers like Ollama that don't require authentication).
|
|
11
|
+
*/
|
|
12
|
+
import { OpenAIAdapter } from "./openai.js";
|
|
13
|
+
import type { LLMClient } from "./types.js";
|
|
14
|
+
/**
|
|
15
|
+
* LLMClient implementation for OpenAI-compatible endpoints.
|
|
16
|
+
*
|
|
17
|
+
* Extends OpenAIAdapter with a required `endpoint` (baseURL) parameter.
|
|
18
|
+
* All tool conversion and response normalisation is inherited from
|
|
19
|
+
* OpenAIAdapter — only the client configuration differs.
|
|
20
|
+
*
|
|
21
|
+
* Usage example (Ollama):
|
|
22
|
+
* ```ts
|
|
23
|
+
* const client = new OpenAICompatAdapter(
|
|
24
|
+
* "http://localhost:11434/v1",
|
|
25
|
+
* "llama3",
|
|
26
|
+
* );
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare class OpenAICompatAdapter extends OpenAIAdapter implements LLMClient {
|
|
30
|
+
/**
|
|
31
|
+
* @param endpoint - Required base URL of the OpenAI-compatible server
|
|
32
|
+
* (e.g. "http://localhost:11434/v1" for Ollama).
|
|
33
|
+
* @param model - Model identifier to use with this server.
|
|
34
|
+
* @param apiKey - Optional API key. Defaults to "not-needed" for servers
|
|
35
|
+
* that do not require authentication (e.g. Ollama).
|
|
36
|
+
*/
|
|
37
|
+
constructor(endpoint: string, model: string, apiKey?: string);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=openai-compat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-compat.d.ts","sourceRoot":"","sources":["../../src/providers/openai-compat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;;;;;;;;;;GAcG;AACH,qBAAa,mBAAoB,SAAQ,aAAc,YAAW,SAAS;IACzE;;;;;;OAMG;gBACS,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAK7D"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI-compatible provider adapter.
|
|
3
|
+
*
|
|
4
|
+
* Creates an OpenAI client pointed at a custom base URL, enabling use with
|
|
5
|
+
* any OpenAI-compatible API server (e.g. Ollama, LM Studio, vLLM, Together AI).
|
|
6
|
+
*
|
|
7
|
+
* Reuses all tool conversion, message conversion, and response normalisation
|
|
8
|
+
* logic from OpenAIAdapter by extending it with a custom base URL and a
|
|
9
|
+
* default API key of "not-needed" (required by the openai SDK but ignored
|
|
10
|
+
* by servers like Ollama that don't require authentication).
|
|
11
|
+
*/
|
|
12
|
+
import { OpenAIAdapter } from "./openai.js";
|
|
13
|
+
/**
|
|
14
|
+
* LLMClient implementation for OpenAI-compatible endpoints.
|
|
15
|
+
*
|
|
16
|
+
* Extends OpenAIAdapter with a required `endpoint` (baseURL) parameter.
|
|
17
|
+
* All tool conversion and response normalisation is inherited from
|
|
18
|
+
* OpenAIAdapter — only the client configuration differs.
|
|
19
|
+
*
|
|
20
|
+
* Usage example (Ollama):
|
|
21
|
+
* ```ts
|
|
22
|
+
* const client = new OpenAICompatAdapter(
|
|
23
|
+
* "http://localhost:11434/v1",
|
|
24
|
+
* "llama3",
|
|
25
|
+
* );
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export class OpenAICompatAdapter extends OpenAIAdapter {
|
|
29
|
+
/**
|
|
30
|
+
* @param endpoint - Required base URL of the OpenAI-compatible server
|
|
31
|
+
* (e.g. "http://localhost:11434/v1" for Ollama).
|
|
32
|
+
* @param model - Model identifier to use with this server.
|
|
33
|
+
* @param apiKey - Optional API key. Defaults to "not-needed" for servers
|
|
34
|
+
* that do not require authentication (e.g. Ollama).
|
|
35
|
+
*/
|
|
36
|
+
constructor(endpoint, model, apiKey) {
|
|
37
|
+
// Pass "not-needed" as apiKey default — the openai SDK requires a non-empty
|
|
38
|
+
// value but OpenAI-compat servers (like Ollama) typically ignore it.
|
|
39
|
+
super(model, apiKey ?? "not-needed", endpoint);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=openai-compat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-compat.js","sourceRoot":"","sources":["../../src/providers/openai-compat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,mBAAoB,SAAQ,aAAa;IACpD;;;;;;OAMG;IACH,YAAY,QAAgB,EAAE,KAAa,EAAE,MAAe;QAC1D,4EAA4E;QAC5E,qEAAqE;QACrE,KAAK,CAAC,KAAK,EAAE,MAAM,IAAI,YAAY,EAAE,QAAQ,CAAC,CAAC;IACjD,CAAC;CACF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI provider adapter.
|
|
3
|
+
*
|
|
4
|
+
* Uses a dynamic import so the `openai` package is an optional peer dependency.
|
|
5
|
+
* If the package is not installed, a clear installation error is thrown at
|
|
6
|
+
* call-time rather than at module load time.
|
|
7
|
+
*
|
|
8
|
+
* All OpenAI SDK types are inlined below so this file compiles without the
|
|
9
|
+
* `openai` package present in node_modules.
|
|
10
|
+
*/
|
|
11
|
+
import type { LLMClient, ChatParams, ChatResponse } from "./types.js";
|
|
12
|
+
/**
|
|
13
|
+
* LLMClient implementation that wraps the OpenAI chat completions API.
|
|
14
|
+
*
|
|
15
|
+
* The `openai` npm package is dynamically imported so it remains an optional
|
|
16
|
+
* peer dependency. If the package is absent a descriptive install error is
|
|
17
|
+
* thrown on the first call.
|
|
18
|
+
*
|
|
19
|
+
* Supports:
|
|
20
|
+
* - Function/tool calling via the tools array format
|
|
21
|
+
* - Parallel tool calls
|
|
22
|
+
* - Custom base URL for OpenAI-compatible endpoints
|
|
23
|
+
* - Optional provider-level configuration
|
|
24
|
+
*/
|
|
25
|
+
export declare class OpenAIAdapter implements LLMClient {
|
|
26
|
+
private readonly model;
|
|
27
|
+
private readonly apiKey;
|
|
28
|
+
private readonly baseURL;
|
|
29
|
+
private readonly providerConfig;
|
|
30
|
+
/** Lazily initialised after the dynamic import succeeds. */
|
|
31
|
+
private client;
|
|
32
|
+
constructor(model: string, apiKey?: string, endpoint?: string, providerConfig?: Record<string, unknown>);
|
|
33
|
+
/**
|
|
34
|
+
* Lazily import the `openai` package and return the initialised client.
|
|
35
|
+
*
|
|
36
|
+
* @throws If the `openai` package is not installed.
|
|
37
|
+
*/
|
|
38
|
+
private getClient;
|
|
39
|
+
chat(params: ChatParams): Promise<ChatResponse>;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,UAAU,EACV,YAAY,EAKb,MAAM,YAAY,CAAC;AA0MpB;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsC;IAErE,4DAA4D;IAC5D,OAAO,CAAC,MAAM,CAA8B;gBAG1C,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAQ1C;;;;OAIG;YACW,SAAS;IAqCjB,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;CA8CtD"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI provider adapter.
|
|
3
|
+
*
|
|
4
|
+
* Uses a dynamic import so the `openai` package is an optional peer dependency.
|
|
5
|
+
* If the package is not installed, a clear installation error is thrown at
|
|
6
|
+
* call-time rather than at module load time.
|
|
7
|
+
*
|
|
8
|
+
* All OpenAI SDK types are inlined below so this file compiles without the
|
|
9
|
+
* `openai` package present in node_modules.
|
|
10
|
+
*/
|
|
11
|
+
// ── Conversion helpers ──────────────────────────────────────────────
|
|
12
|
+
/**
|
|
13
|
+
* Convert a provider-agnostic ToolDef to OpenAI function calling format.
|
|
14
|
+
*/
|
|
15
|
+
function toOpenAITool(tool) {
|
|
16
|
+
return {
|
|
17
|
+
type: "function",
|
|
18
|
+
function: {
|
|
19
|
+
name: tool.name,
|
|
20
|
+
description: tool.description,
|
|
21
|
+
// input_schema is already a JSON Schema object; OpenAI uses `parameters`
|
|
22
|
+
parameters: tool.input_schema,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Normalize the OpenAI finish_reason to our StopReason type.
|
|
28
|
+
*/
|
|
29
|
+
function normalizeStopReason(finishReason) {
|
|
30
|
+
switch (finishReason) {
|
|
31
|
+
case "stop":
|
|
32
|
+
return "end";
|
|
33
|
+
case "tool_calls":
|
|
34
|
+
return "tool_use";
|
|
35
|
+
case "length":
|
|
36
|
+
return "max_tokens";
|
|
37
|
+
default:
|
|
38
|
+
return finishReason ?? "end";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Convert a provider-agnostic Message to one or more OpenAI request messages.
|
|
43
|
+
*
|
|
44
|
+
* Returns an array because ToolResultMessage expands into one OAI tool
|
|
45
|
+
* message per tool result (OpenAI requires separate messages per tool call).
|
|
46
|
+
*/
|
|
47
|
+
function toOpenAIMessages(message) {
|
|
48
|
+
// ToolResultMessage → one role:"tool" message per result
|
|
49
|
+
if ("toolResults" in message) {
|
|
50
|
+
return message.toolResults.map((tr) => ({
|
|
51
|
+
role: "tool",
|
|
52
|
+
tool_call_id: tr.toolUseId,
|
|
53
|
+
content: tr.content,
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
// AssistantMessage → role:"assistant" with optional tool_calls
|
|
57
|
+
if ("toolCalls" in message && message.toolCalls.length > 0) {
|
|
58
|
+
const oaiMsg = {
|
|
59
|
+
role: "assistant",
|
|
60
|
+
content: message.content || null,
|
|
61
|
+
tool_calls: message.toolCalls.map((tc) => ({
|
|
62
|
+
id: tc.id,
|
|
63
|
+
type: "function",
|
|
64
|
+
function: {
|
|
65
|
+
name: tc.name,
|
|
66
|
+
arguments: JSON.stringify(tc.input),
|
|
67
|
+
},
|
|
68
|
+
})),
|
|
69
|
+
};
|
|
70
|
+
return [oaiMsg];
|
|
71
|
+
}
|
|
72
|
+
// TextMessage (user or assistant without tool calls)
|
|
73
|
+
const textMsg = message;
|
|
74
|
+
if (textMsg.role === "user") {
|
|
75
|
+
return [{ role: "user", content: textMsg.content }];
|
|
76
|
+
}
|
|
77
|
+
// Plain assistant text message (no tool calls)
|
|
78
|
+
return [{ role: "assistant", content: textMsg.content }];
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Parse tool_calls from an OAI response message into ToolCall[].
|
|
82
|
+
*
|
|
83
|
+
* Guards against an empty array (treated as no tool calls) and handles
|
|
84
|
+
* JSON parse errors in arguments gracefully.
|
|
85
|
+
*/
|
|
86
|
+
function normalizeToolCalls(toolCalls) {
|
|
87
|
+
if (!toolCalls || toolCalls.length === 0) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
return toolCalls.map((tc) => {
|
|
91
|
+
let input = {};
|
|
92
|
+
try {
|
|
93
|
+
const parsed = JSON.parse(tc.function.arguments);
|
|
94
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
95
|
+
input = parsed;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Malformed JSON from the model — fall back to empty input
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
id: tc.id,
|
|
103
|
+
name: tc.function.name,
|
|
104
|
+
input,
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
// ── OpenAIAdapter ────────────────────────────────────────────────────
|
|
109
|
+
/**
|
|
110
|
+
* LLMClient implementation that wraps the OpenAI chat completions API.
|
|
111
|
+
*
|
|
112
|
+
* The `openai` npm package is dynamically imported so it remains an optional
|
|
113
|
+
* peer dependency. If the package is absent a descriptive install error is
|
|
114
|
+
* thrown on the first call.
|
|
115
|
+
*
|
|
116
|
+
* Supports:
|
|
117
|
+
* - Function/tool calling via the tools array format
|
|
118
|
+
* - Parallel tool calls
|
|
119
|
+
* - Custom base URL for OpenAI-compatible endpoints
|
|
120
|
+
* - Optional provider-level configuration
|
|
121
|
+
*/
|
|
122
|
+
export class OpenAIAdapter {
|
|
123
|
+
model;
|
|
124
|
+
apiKey;
|
|
125
|
+
baseURL;
|
|
126
|
+
providerConfig;
|
|
127
|
+
/** Lazily initialised after the dynamic import succeeds. */
|
|
128
|
+
client = null;
|
|
129
|
+
constructor(model, apiKey, endpoint, providerConfig) {
|
|
130
|
+
this.model = model;
|
|
131
|
+
this.apiKey = apiKey;
|
|
132
|
+
this.baseURL = endpoint;
|
|
133
|
+
this.providerConfig = providerConfig;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Lazily import the `openai` package and return the initialised client.
|
|
137
|
+
*
|
|
138
|
+
* @throws If the `openai` package is not installed.
|
|
139
|
+
*/
|
|
140
|
+
async getClient() {
|
|
141
|
+
if (this.client) {
|
|
142
|
+
return this.client;
|
|
143
|
+
}
|
|
144
|
+
let OpenAI;
|
|
145
|
+
try {
|
|
146
|
+
// Construct the specifier at runtime so TypeScript does not attempt
|
|
147
|
+
// to statically resolve the optional peer dependency at compile time.
|
|
148
|
+
const specifier = "openai";
|
|
149
|
+
const mod = (await import(/* @vite-ignore */ specifier));
|
|
150
|
+
// Handle both ESM default export and CommonJS-style .default wrapping
|
|
151
|
+
OpenAI = (mod["default"] ?? mod);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
throw new Error('OpenAI provider requires the "openai" package. Run: npm install openai');
|
|
155
|
+
}
|
|
156
|
+
const apiKey = this.apiKey ??
|
|
157
|
+
(typeof this.providerConfig?.["apiKey"] === "string"
|
|
158
|
+
? this.providerConfig["apiKey"]
|
|
159
|
+
: process.env["OPENAI_API_KEY"]);
|
|
160
|
+
this.client = new OpenAI({
|
|
161
|
+
apiKey,
|
|
162
|
+
...(this.baseURL ? { baseURL: this.baseURL } : {}),
|
|
163
|
+
});
|
|
164
|
+
return this.client;
|
|
165
|
+
}
|
|
166
|
+
async chat(params) {
|
|
167
|
+
const { model, system, messages, tools, maxTokens = 16384 } = params;
|
|
168
|
+
const client = await this.getClient();
|
|
169
|
+
// Build the messages array: system message first, then conversation
|
|
170
|
+
const oaiMessages = [
|
|
171
|
+
{ role: "system", content: system },
|
|
172
|
+
...messages.flatMap(toOpenAIMessages),
|
|
173
|
+
];
|
|
174
|
+
// Convert ToolDef[] to OpenAI tools format
|
|
175
|
+
const oaiTools = tools && tools.length > 0 ? tools.map(toOpenAITool) : undefined;
|
|
176
|
+
const response = await client.chat.completions.create({
|
|
177
|
+
model: model || this.model,
|
|
178
|
+
messages: oaiMessages,
|
|
179
|
+
...(oaiTools ? { tools: oaiTools } : {}),
|
|
180
|
+
max_tokens: maxTokens,
|
|
181
|
+
});
|
|
182
|
+
const choice = response.choices[0];
|
|
183
|
+
if (!choice) {
|
|
184
|
+
return {
|
|
185
|
+
text: "",
|
|
186
|
+
toolCalls: [],
|
|
187
|
+
stopReason: "error",
|
|
188
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
const text = choice.message.content ?? "";
|
|
192
|
+
const toolCalls = normalizeToolCalls(choice.message.tool_calls);
|
|
193
|
+
const stopReason = normalizeStopReason(choice.finish_reason);
|
|
194
|
+
return {
|
|
195
|
+
text,
|
|
196
|
+
toolCalls,
|
|
197
|
+
stopReason,
|
|
198
|
+
usage: {
|
|
199
|
+
inputTokens: response.usage?.prompt_tokens ?? 0,
|
|
200
|
+
outputTokens: response.usage?.completion_tokens ?? 0,
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"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"}
|