Commit d01cf20
feat: add tool/function calling support (#52)
* feat: add tool/function calling support (closes #50)
Adds OpenAI-style function tools, Anthropic tools, and Gemini function
declarations across all four API surfaces (/v1/chat/completions,
/v1/responses, /v1/messages, /v1beta/models/:model:generateContent),
both streaming and non-streaming.
OpenCode's own agent loop always executes tools itself, server-side,
and has no concept of a 'client-executed' tool call to hand off to a
caller. To bridge that gap:
- When a request includes tools, the proxy dynamically registers a
small local MCP server (mcp-tool-bridge.js) whose tool list is
exactly the caller's declared tool schemas, reused from a small
fixed-size pool of slot names (OpenCode's server API has no endpoint
to deregister an MCP server once added).
- Only those tools are enabled for that one prompt call via the
existing tools enable/disable map; every built-in OpenCode tool
stays disabled, same as before.
- As soon as the model proposes calling one of the bridge tools, the
full call (name + arguments) is already present on OpenCode's event
stream (ToolStatePending includes the parsed input even before
execution starts) - the proxy captures it and immediately aborts the
session before the bridge's no-op tools/call handler would ever be
consulted, then translates the call into the caller's expected
tool_calls / tool_use / functionCall shape instead of a text answer.
Also extends the OpenAI/Anthropic/Gemini/Responses message normalizers
to render prior tool_calls/tool_use/functionCall and their
results/tool_result/functionResponse as descriptive text when replaying
conversation history, so multi-turn tool use works end-to-end even
though sessions are stateless per-request.
- index.js: parseOpenAITools/parseAnthropicTools/parseGeminiTools +
applyOpenAIToolChoice/applyAnthropicToolChoice/applyGeminiToolChoice,
sanitizeToolName, tool bridge pool + registerToolBridge, unified
runAgentTurn (event-driven turn execution shared by executePrompt
and executePromptStreaming when tools are present), tool-call
branches in all four response builders and SSE emitters.
- mcp-tool-bridge.js: minimal MCP stdio JSON-RPC server exposing
caller-supplied tool schemas; tools/call is a harmless no-op since
the proxy aborts the session before it would ever be consulted.
- index.test.js: unit tests for the new parse/tool_choice helpers and
history round-tripping, plus end-to-end tool-calling tests for all
four API formats (stream + non-stream).
- README.md: documents the new tools/tool_choice/toolConfig request
fields, how the bridge mechanism works, its current limitations, and
the new OPENCODE_LLM_PROXY_TOOL_BRIDGE_POOL_SIZE env var.
Testing:
- npm test — 138 passed (116 existing + 22 new)
- npm run lint — clean
* docs: feature tool calling prominently in README, expand discoverability keywords
- Move the Tool calling section up (right after Configuration) and add a
runnable curl request/response example, instead of burying it near the
bottom after How it works.
- Add a Contents section now that the README has grown to 10+ sections.
- Call out tool calling in the top-level tagline, architecture diagram,
supported-formats table, and Why section (coding agents are now a
first-class use case, not just chat clients).
- Note in Install that copying just index.js doesn't get you tool calling
(needs mcp-tool-bridge.js alongside it) - use the npm plugin instead.
- package.json: mention tool/function calling in the description and add
tool-calling/function-calling/tools/mcp/model-context-protocol/
coding-agent/ai-agent/agentic keywords for npm search discoverability.
---------
Co-authored-by: Framewrk CI <ci@framewrklabs.ai>1 parent b7402ca commit d01cf20
5 files changed
Lines changed: 1307 additions & 119 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
22 | | - | |
| 22 | + | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
31 | 49 | | |
32 | 50 | | |
33 | 51 | | |
| |||
41 | 59 | | |
42 | 60 | | |
43 | 61 | | |
| 62 | + | |
44 | 63 | | |
45 | 64 | | |
46 | 65 | | |
| |||
110 | 129 | | |
111 | 130 | | |
112 | 131 | | |
| 132 | + | |
| 133 | + | |
113 | 134 | | |
114 | 135 | | |
115 | 136 | | |
| |||
120 | 141 | | |
121 | 142 | | |
122 | 143 | | |
| 144 | + | |
123 | 145 | | |
124 | 146 | | |
125 | 147 | | |
| |||
129 | 151 | | |
130 | 152 | | |
131 | 153 | | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
132 | 215 | | |
133 | 216 | | |
134 | 217 | | |
| |||
310 | 393 | | |
311 | 394 | | |
312 | 395 | | |
313 | | - | |
| 396 | + | |
314 | 397 | | |
315 | 398 | | |
316 | | - | |
| 399 | + | |
317 | 400 | | |
318 | 401 | | |
319 | | - | |
| 402 | + | |
320 | 403 | | |
321 | 404 | | |
322 | 405 | | |
323 | 406 | | |
324 | | - | |
| 407 | + | |
325 | 408 | | |
326 | 409 | | |
327 | 410 | | |
| |||
345 | 428 | | |
346 | 429 | | |
347 | 430 | | |
348 | | - | |
349 | 431 | | |
350 | 432 | | |
| 433 | + | |
351 | 434 | | |
352 | 435 | | |
353 | 436 | | |
| |||
0 commit comments