@chainfuse/ai-tools 0.3.1 → 0.3.2

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.
@@ -105,46 +105,72 @@ export class AiCustomProviders extends AiBase {
105
105
  // @ts-expect-error override for types
106
106
  acc[model] = wrapLanguageModel({
107
107
  model: (await raw.restWorkersAi(args))(model),
108
- middleware: {
109
- wrapStream: async ({ doStream }) => {
110
- const { stream, ...rest } = await doStream();
111
- const transformStream = new TransformStream({
112
- transform(chunk, controller) {
113
- if (chunk.type === 'error') {
114
- if (TypeValidationError.isInstance(chunk.error) && chunk.error.cause instanceof ZodError) {
115
- if (chunk.error.cause.issues.filter((issues) => issues.code === 'invalid_union')) {
116
- // Verify the specific error instead of assuming all errors
117
- const missingIndexPropertyError = chunk.error.cause.issues
118
- .filter((issues) => issues.code === 'invalid_union')
119
- .flatMap((issue) => issue.unionErrors)
120
- .flatMap((issue) => issue.issues)
121
- .filter((issue) => issue.code === 'invalid_type' && Helpers.areArraysEqual(issue.path, ['choices', 0, 'index']));
122
- if (missingIndexPropertyError.length > 0) {
123
- const newChunk = chunk.error.value;
124
- newChunk.choices
125
- .filter((choice) => choice.delta.content)
126
- .forEach((choice) => {
127
- controller.enqueue({
128
- type: 'text-delta',
129
- textDelta: choice.delta.content,
108
+ middleware: [
109
+ {
110
+ wrapStream: async ({ doStream }) => {
111
+ const { stream, ...rest } = await doStream();
112
+ const transformStream = new TransformStream({
113
+ transform(chunk, controller) {
114
+ if (chunk.type === 'error') {
115
+ if (TypeValidationError.isInstance(chunk.error) && chunk.error.cause instanceof ZodError) {
116
+ if (chunk.error.cause.issues.filter((issues) => issues.code === 'invalid_union')) {
117
+ // Verify the specific error instead of assuming all errors
118
+ const missingIndexPropertyError = chunk.error.cause.issues
119
+ .filter((issues) => issues.code === 'invalid_union')
120
+ .flatMap((issue) => issue.unionErrors)
121
+ .flatMap((issue) => issue.issues)
122
+ .filter((issue) => issue.code === 'invalid_type' && Helpers.areArraysEqual(issue.path, ['choices', 0, 'index']));
123
+ if (missingIndexPropertyError.length > 0) {
124
+ const newChunk = chunk.error.value;
125
+ newChunk.choices
126
+ .filter((choice) => choice.delta.content)
127
+ .forEach((choice) => {
128
+ controller.enqueue({
129
+ type: 'text-delta',
130
+ textDelta: choice.delta.content,
131
+ });
130
132
  });
131
- });
133
+ }
132
134
  }
133
135
  }
134
136
  }
135
- }
136
- else {
137
- // Passthrough untouched
138
- controller.enqueue(chunk);
139
- }
140
- },
141
- });
142
- return {
143
- stream: stream.pipeThrough(transformStream),
144
- ...rest,
145
- };
137
+ else {
138
+ // Passthrough untouched
139
+ controller.enqueue(chunk);
140
+ }
141
+ },
142
+ });
143
+ return {
144
+ stream: stream.pipeThrough(transformStream),
145
+ ...rest,
146
+ };
147
+ },
146
148
  },
147
- },
149
+ // Fix output generation where it's correct, but encapsulated in a code fence
150
+ {
151
+ wrapGenerate: async ({ doGenerate, model }) => {
152
+ const result = await doGenerate();
153
+ /**
154
+ * `chunkSchema` is undocumented but always present in `model` regardless of model
155
+ * Can't use `responseFormat` (in `params`) because it isn't always present because some models don't support that part of openai api spec.
156
+ */
157
+ if ('chunkSchema' in model) {
158
+ const codeFenceStart = new RegExp(/^`{1,3}\w*\s*(?=[\[{])/i);
159
+ const codefenceEnd = new RegExp(/(?![\]}])\s*`{1,3}$/i);
160
+ return {
161
+ ...result,
162
+ /**
163
+ * 1. trim initially to remove any leading/trailing whitespace
164
+ * 2. Remove start and end
165
+ * 3. Trim again to remove any leading/trailing whitespace
166
+ */
167
+ text: result.text?.trim().replace(codeFenceStart, '').replace(codefenceEnd, '').trim(),
168
+ };
169
+ }
170
+ return result;
171
+ },
172
+ },
173
+ ],
148
174
  });
149
175
  return acc;
150
176
  }, Promise.resolve({})),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chainfuse/ai-tools",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "",
5
5
  "author": "ChainFuse",
6
6
  "homepage": "https://github.com/ChainFuse/packages/tree/main/packages/ai-tools#readme",
@@ -64,5 +64,5 @@
64
64
  "@cloudflare/workers-types": "^4.20250129.0",
65
65
  "openai": "^4.82.0"
66
66
  },
67
- "gitHead": "5798b5c3f0920b026ba9e4fc0f3d3eac8ea3fe7f"
67
+ "gitHead": "2ec2a5ba79ac9ecb2008ecd993d786fd753a1e1d"
68
68
  }