Skip to content

Commit da10f19

Browse files
feat: add support for response-healing plugin (#361)
* feat: add support for response-healing plugin Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai> * docs: enhance JSDoc for response-healing plugin with clearer streaming limitation Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent bd8794a commit da10f19

File tree

5 files changed

+114
-0
lines changed

5 files changed

+114
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
"@openrouter/ai-sdk-provider": minor
3+
---
4+
5+
Add support for the Response Healing plugin
6+
7+
The Response Healing plugin automatically validates and repairs malformed JSON responses from AI models. Enable it by adding `{ id: 'response-healing' }` to the plugins array when using structured outputs with `generateObject`.
8+
9+
```typescript
10+
const model = openrouter('openai/gpt-4o', {
11+
plugins: [{ id: 'response-healing' }],
12+
});
13+
14+
const { object } = await generateObject({
15+
model,
16+
schema: z.object({ name: z.string(), age: z.number() }),
17+
prompt: 'Generate a person.',
18+
});
19+
```
20+
21+
Note: Response Healing only works with non-streaming requests.

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,34 @@ for await (const partialComponent of result.partialObjectStream) {
307307

308308
## Use Cases
309309

310+
### Response Healing for Structured Outputs
311+
312+
The provider supports the [Response Healing plugin](https://openrouter.ai/docs/guides/features/plugins/response-healing), which automatically validates and repairs malformed JSON responses from AI models. This is particularly useful when using `generateObject` or structured outputs, as it can fix common issues like missing brackets, trailing commas, markdown wrappers, and mixed text.
313+
314+
```typescript
315+
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
316+
import { generateObject } from 'ai';
317+
import { z } from 'zod';
318+
319+
const openrouter = createOpenRouter({ apiKey: 'your-api-key' });
320+
const model = openrouter('openai/gpt-4o', {
321+
plugins: [{ id: 'response-healing' }],
322+
});
323+
324+
const { object } = await generateObject({
325+
model,
326+
schema: z.object({
327+
name: z.string(),
328+
age: z.number(),
329+
}),
330+
prompt: 'Generate a person with name and age.',
331+
});
332+
333+
console.log(object); // { name: "John", age: 30 }
334+
```
335+
336+
Note that Response Healing only works with non-streaming requests. When the model returns imperfect JSON formatting, the plugin attempts to repair the response so you receive valid, parseable JSON.
337+
310338
### Debugging API Requests
311339

312340
The provider supports a debug mode that echoes back the request body sent to the upstream provider. This is useful for troubleshooting and understanding how your requests are being processed. Note that debug mode only works with streaming requests.

src/chat/index.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,51 @@ describe('doGenerate', () => {
773773
});
774774
});
775775

776+
it('should pass response-healing plugin in request payload', async () => {
777+
prepareJsonResponse({ content: '{"name": "John", "age": 30}' });
778+
779+
const modelWithPlugin = provider.chat('anthropic/claude-3.5-sonnet', {
780+
plugins: [{ id: 'response-healing' }],
781+
});
782+
783+
await modelWithPlugin.doGenerate({
784+
prompt: TEST_PROMPT,
785+
responseFormat: {
786+
type: 'json',
787+
schema: {
788+
type: 'object',
789+
properties: {
790+
name: { type: 'string' },
791+
age: { type: 'number' },
792+
},
793+
required: ['name', 'age'],
794+
},
795+
name: 'PersonResponse',
796+
},
797+
});
798+
799+
expect(await server.calls[0]!.requestBodyJson).toStrictEqual({
800+
model: 'anthropic/claude-3.5-sonnet',
801+
messages: [{ role: 'user', content: 'Hello' }],
802+
plugins: [{ id: 'response-healing' }],
803+
response_format: {
804+
type: 'json_schema',
805+
json_schema: {
806+
schema: {
807+
type: 'object',
808+
properties: {
809+
name: { type: 'string' },
810+
age: { type: 'number' },
811+
},
812+
required: ['name', 'age'],
813+
},
814+
strict: true,
815+
name: 'PersonResponse',
816+
},
817+
},
818+
});
819+
});
820+
776821
it('should pass images', async () => {
777822
prepareJsonResponse({
778823
content: '',

src/types/openrouter-api-types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ export type IdFileParser = 'file-parser';
2828
*/
2929
export type IdModeration = 'moderation';
3030

31+
/**
32+
* Plugin identifier for response healing.
33+
* Automatically validates and repairs malformed JSON responses.
34+
* @see https://openrouter.ai/docs/guides/features/plugins/response-healing
35+
*/
36+
export type IdResponseHealing = 'response-healing';
37+
3138
/**
3239
* Search engine options for web search.
3340
* Open enum - accepts known values or any string for forward compatibility.

src/types/openrouter-chat-settings.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type {
44
Engine,
55
IdFileParser,
66
IdModeration,
7+
IdResponseHealing,
78
IdWeb,
89
PdfEngine,
910
ProviderSort,
@@ -74,6 +75,18 @@ monitor and detect abuse. Learn more.
7475
| {
7576
id: IdModeration;
7677
}
78+
| {
79+
/**
80+
* Response healing plugin - automatically validates and repairs malformed JSON responses.
81+
*
82+
* **Important:** This plugin only works with non-streaming requests (e.g., `generateObject`).
83+
* It has no effect when used with streaming methods like `streamObject` or `streamText`.
84+
* The plugin activates when using `response_format` with `json_schema` or `json_object`.
85+
*
86+
* @see https://openrouter.ai/docs/guides/features/plugins/response-healing
87+
*/
88+
id: IdResponseHealing;
89+
}
7790
>;
7891

7992
/**

0 commit comments

Comments
 (0)