Skip to content

Commit 4fb674f

Browse files
minpeterCopilotsijawara
authored
Add community XML tools and reorganize parsers (#85)
* Add community XML tools and reorganize parsers * Update middleware references from `xmlToolMiddleware` to `morphXmlToolMiddleware` across documentation and examples for consistency and clarity. * Update packages/parser/src/community/index.ts Co-authored-by: Copilot <[email protected]> * Fix typo in middleware reference from `sijawaraConsiseXmlToolMiddleware` to `sijawaraConciseXmlToolMiddleware` in example and community index files for consistency. * fix: update morphXmlProtocol to enhance HTML tag handling - Disabled self-closing tag behavior for HTML elements in the morphXmlProtocol, ensuring they are treated as regular tags. - This change improves the parsing accuracy of XML tool calls by accommodating standard HTML tag structures. * chore: attribute co-author Co-authored-by: sijawara <[email protected]> --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: sijawara <[email protected]>
1 parent d71b229 commit 4fb674f

File tree

23 files changed

+213
-82
lines changed

23 files changed

+213
-82
lines changed

.changeset/twenty-turkeys-open.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@ai-sdk-tool/parser": patch
3+
---
4+
5+
Add community XML tools and reorganize parsers

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ This project provides middleware for AI SDK to enable tool calling with models t
3030
**@ai-sdk-tool/parser** (`packages/parser/`):
3131

3232
- Main middleware package for tool call parsing
33-
- Exports pre-configured middlewares: `gemmaToolMiddleware`, `hermesToolMiddleware`, `xmlToolMiddleware`
33+
- Exports pre-configured middlewares: `gemmaToolMiddleware`, `hermesToolMiddleware`, `morphXmlToolMiddleware`
3434
- Core factory function: `createToolMiddleware()` for custom protocols
3535
- Protocol system with pluggable parsers for different model formats (JSON-mix, XML, etc.)
3636

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Note: Requires AI SDK v5. For AI SDK v4, use `@ai-sdk-tool/[email protected]`.
1515

1616
## Packages
1717

18-
- `packages/parser` — core tool‑call parsing middleware and prebuilt middlewares (`gemmaToolMiddleware`, `hermesToolMiddleware`, `xmlToolMiddleware`).
18+
- `packages/parser` — core tool‑call parsing middleware and prebuilt middlewares (`gemmaToolMiddleware`, `hermesToolMiddleware`, `morphXmlToolMiddleware`).
1919
- Quickstarts: [packages/parser/README.md](packages/parser/README.md)
2020
- Official docs reference: [Custom tool call parser](https://ai-sdk.dev/docs/ai-sdk-core/middleware#custom-tool-call-parser)
2121
- `packages/eval` — evaluation utilities (BFCL, JSON generation).
@@ -24,7 +24,7 @@ Note: Requires AI SDK v5. For AI SDK v4, use `@ai-sdk-tool/[email protected]`.
2424
### Choose a middleware (at a glance)
2525

2626
- **gemmaToolMiddleware**: JSON tool calls inside markdown fences. Best for Gemma-like models.
27-
- **xmlToolMiddleware**: Plain XML tool calls. Good fit for GLM/GLM-like models.
27+
- **morphXmlToolMiddleware**: Plain XML tool calls. Good fit for GLM/GLM-like models.
2828
- **hermesToolMiddleware**: JSON payload wrapped in `<tool_call>` XML tags. Hermes/Llama-style prompts.
2929

3030
## Install (per package)

docs/concepts/middleware.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ See concrete implementations in `packages/parser/src/protocols/json-mix-protocol
8383
- Preconfigured:
8484
- `gemmaToolMiddleware` — JSON-mix with fenced code blocks for Gemma-style models.
8585
- `hermesToolMiddleware` — JSON-mix with XML-tag wrapping of tool calls.
86-
- `xmlToolMiddleware` — Morph-XML protocol for XML-native formats.
86+
- `morphXmlToolMiddleware` — Morph-XML protocol for XML-native formats.
8787
- Protocol factories: `jsonMixProtocol`, `morphXmlProtocol`.
8888

8989
Defined in `packages/parser/src/index.ts`.

docs/concepts/protocols.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ Preconfigured middlewares exported from `packages/parser/src/index.ts`:
101101

102102
- `gemmaToolMiddleware` — Uses `jsonMixProtocol` with markdown code fences labeled `tool_call` and a prompt tailored for Gemma.
103103
- `hermesToolMiddleware``jsonMixProtocol` with `<tool_call>` tags and a Hermes-style prompt.
104-
- `xmlToolMiddleware``morphXmlProtocol` with an XML-oriented prompt.
104+
- `morphXmlToolMiddleware``morphXmlProtocol` with an XML-oriented prompt.
105105

106106
## Implementing a Custom Protocol
107107

docs/examples.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,6 @@ cd examples/eval-core && pnpm dlx tsx src/json-generation.ts
3838

3939
### [dev] Notes
4040

41-
- **Middleware switch**: parser examples show how to swap between `xmlToolMiddleware` and `gemmaToolMiddleware` via commented lines. Choose a provider/model your account can access.
41+
- **Middleware switch**: parser examples show how to swap between `morphXmlToolMiddleware` and `gemmaToolMiddleware` via commented lines. Choose a provider/model your account can access.
4242
- **Providers**: OpenRouter base URL is `https://openrouter.ai/api/v1`. Friendli serverless base URL is `https://api.friendli.ai/serverless/v1`.
4343
- **Streaming vs non‑streaming**: `00-stream-tool-call.ts` uses streaming (`streamText`), while `00-tool-call.ts` is non‑streaming (`generateText`).

docs/getting-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ main().catch(console.error);
119119
## Choose a middleware (protocol)
120120

121121
- **gemmaToolMiddleware**: JSON tool calls inside markdown fences. Best for Gemma-like models.
122-
- **xmlToolMiddleware**: XML tool calls. Works well with GLM-style models.
122+
- **morphXmlToolMiddleware**: XML tool calls. Works well with GLM-style models.
123123
- **hermesToolMiddleware**: JSON payload wrapped in XML tags. For Hermes/Llama-style prompts.
124124

125125
Swap by importing a different middleware; your tool definitions stay the same.

docs/guides/tool-calling.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Use the middleware to enable tool calls on models without native `tools` support
66

77
- `gemmaToolMiddleware` — JSON-mix in markdown fences (```tool_call)
88
- `hermesToolMiddleware` — JSON-mix with XML wrappers (<tool_call>)
9-
- `xmlToolMiddleware` — Morph-XML protocol (native XML elements per tool name)
9+
- `morphXmlToolMiddleware` — Morph-XML protocol (native XML elements per tool name)
1010

1111
## Generate mode
1212

@@ -112,7 +112,7 @@ Set env variables:
112112
- `hermesToolMiddleware` (JSON-mix with `<tool_call>`):
113113
- System prompt describes `<tools>` block and requires returning JSON inside `<tool_call> ... </tool_call>` tags.
114114
- Tool responses are formatted with `<tool_response>` tags.
115-
- `xmlToolMiddleware` (Morph-XML):
115+
- `morphXmlToolMiddleware` (Morph-XML):
116116
- Tool call must be an XML element named after the tool (e.g., `<get_weather>...</get_weather>`).
117117
- Arguments are parsed by RXML (Robust XML) via `RXML.parse` and then coerced via JSON Schema. On parse/coercion issues, the protocol falls back to emitting the original text and reports via `options.onError`.
118118
- To improve coercion accuracy, pass `originalToolSchemas` under `providerOptions.toolCallMiddleware`.

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Monorepo documentation for AI SDK tool-calling middleware and evaluation utiliti
66
- Prebuilt Middlewares (choose one):
77
- **gemmaToolMiddleware**: JSON tool calls in markdown fences — Gemma-like models
88
- **hermesToolMiddleware**: JSON payload wrapped in XML tags — Hermes/Llama-style
9-
- **xmlToolMiddleware**: XML elements per tool — GLM/XML-friendly models
9+
- **morphXmlToolMiddleware**: XML elements per tool — GLM/XML-friendly models
1010
- Guides
1111
- [dev] Tool Calling: [guides/tool-calling.md](guides/tool-calling.md)
1212
- [dev] Handlers Overview: [guides/handlers.md](guides/handlers.md)

examples/eval-core/src/bfcl-simple.ts

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@ import {
77
evaluate,
88
type ReporterType,
99
} from "@ai-sdk-tool/eval";
10-
import { createToolMiddleware, morphXmlProtocol } from "@ai-sdk-tool/parser";
10+
import {
11+
hermesToolMiddleware,
12+
morphXmlToolMiddleware,
13+
} from "@ai-sdk-tool/parser";
14+
import {
15+
sijawaraConciseXmlToolMiddleware,
16+
sijawaraDetailedXmlToolMiddleware,
17+
} from "@ai-sdk-tool/parser/community";
1118
import { wrapLanguageModel } from "ai";
1219

1320
const friendli = createOpenAICompatible({
@@ -16,34 +23,10 @@ const friendli = createOpenAICompatible({
1623
baseURL: "https://api.friendli.ai/serverless/v1",
1724
});
1825

19-
const morphExpToolMiddleware = createToolMiddleware({
20-
protocol: morphXmlProtocol,
21-
toolSystemPromptTemplate(tools: string) {
22-
return `You are a function calling AI model.
23-
24-
Available functions are listed inside <tools></tools>.
25-
<tools>${tools}</tools>
26-
27-
# Rules
28-
- Use exactly one XML element whose tag name is the function name.
29-
- Put each parameter as a child element.
30-
- Values must follow the schema exactly (numbers, arrays, objects, enums → copy as-is).
31-
- Do not add or remove functions or parameters.
32-
- Each required parameter must appear once.
33-
- Output nothing before or after the function call.
34-
35-
# Example
36-
<get_weather>
37-
<location>New York</location>
38-
<unit>celsius</unit>
39-
</get_weather>`;
40-
},
41-
});
42-
4326
// const xmlGemma27b = wrapLanguageModel({
4427
// model: friendli("google/gemma-3-27b-it"),
4528
// // model: openrouter("z-ai/glm-4.5-air"),
46-
// middleware: xmlToolMiddleware,
29+
// middleware: morphXmlToolMiddleware,
4730
// });
4831

4932
// const jsonGemma27b = wrapLanguageModel({
@@ -52,23 +35,42 @@ Available functions are listed inside <tools></tools>.
5235
// middleware: gemmaToolMiddleware,
5336
// });
5437

55-
// const morphExpGemma27b = wrapLanguageModel({
38+
// const morphXmlGemma27b = wrapLanguageModel({
5639
// model: friendli("google/gemma-3-27b-it"),
57-
// middleware: morphExpToolMiddleware,
40+
// middleware: morphXmlToolMiddleware,
5841
// });
5942

60-
// const compareDifferentMiddlewares = { xml: xmlGemma27b, morphExp: morphExpGemma27b, json: jsonGemma27b };
43+
// const compareDifferentMiddlewares = { xml: xmlGemma27b, morphXml: morphXmlGemma27b, json: jsonGemma27b };
44+
45+
const testTargetModel = friendli(
46+
"meta-llama/Llama-4-Maverick-17B-128E-Instruct"
47+
);
48+
const hermes = wrapLanguageModel({
49+
model: testTargetModel,
50+
middleware: hermesToolMiddleware,
51+
});
52+
53+
const morphXml = wrapLanguageModel({
54+
model: testTargetModel,
55+
middleware: morphXmlToolMiddleware,
56+
});
6157

62-
const morphExp = wrapLanguageModel({
63-
model: friendli("LGAI-EXAONE/EXAONE-4.0.1-32B"),
64-
middleware: morphExpToolMiddleware,
58+
const sijawaraDetailed = wrapLanguageModel({
59+
model: testTargetModel,
60+
middleware: sijawaraDetailedXmlToolMiddleware,
6561
});
6662

67-
const original = friendli("LGAI-EXAONE/EXAONE-4.0.1-32B");
63+
const sijawaraConcise = wrapLanguageModel({
64+
model: testTargetModel,
65+
middleware: sijawaraConciseXmlToolMiddleware,
66+
});
6867

6968
const compareWithNativeToolCalling = {
70-
morphExp: morphExp,
71-
original: original,
69+
hermes: hermes,
70+
morphXml: morphXml,
71+
sijawaraDetailed: sijawaraDetailed,
72+
sijawaraConcise: sijawaraConcise,
73+
original: testTargetModel,
7274
};
7375

7476
async function main() {

0 commit comments

Comments
 (0)