Commit 338a54a
committed
fix: address Round 1 cr-loop findings (subject-scope bucket-a)
Six-agent unbiased review surfaced behavioural and audit-hygiene
regressions across the extracted base classes. Fixes:
openai-base/adapters/chat-completions-text.ts
- Defer RUN_FINISHED until end-of-stream so the trailing usage-only
chunk that OpenAI emits AFTER finish_reason (when
stream_options.include_usage is on) is captured. Previous fix emitted
RUN_FINISHED with usage: undefined and dropped the trailing chunk.
- Forward upstream finish_reason ('length', 'content_filter', etc.)
instead of collapsing all non-tool reasons to 'stop'.
- Surface tool-args JSON parse failures via logger.errors so a model
emitting malformed JSON for tool arguments is debuggable instead of
silently invoking the tool with input: {}.
- Fix mapOptionsToRequest precedence: `{...modelOptions, temperature:
options.temperature, ...}` clobbered `modelOptions.temperature` with
undefined whenever the caller didn't set the top-level option. Now
spreads top-level fields only when defined.
- Throw on user message with zero content parts instead of silently
sending content: '' (a paid request with no input).
openai-base/adapters/responses-text.ts
- Only reset accumulators on response.created. Previous code reset on
response.failed/incomplete too, which left TEXT_MESSAGE_START events
unbalanced when a response failed mid-stream. On terminal failure
events we now emit TEXT_MESSAGE_END before RUN_ERROR.
- Synthesize a terminal RUN_FINISHED if the stream ends without
response.completed (truncated upstream connection), matching the
chat-completions adapter's behavior so consumers always see a
terminal event for every started run.
- Surface tool-args JSON parse failures via logger.errors (parallel to
chat-completions fix).
- Distinguish refusals from unsupported content_part types in
handleContentPart instead of always reporting 'Unknown refusal'.
- Fix mapOptionsToRequest precedence: previously `...modelOptions` was
spread LAST, silently shadowing the canonical top-level fields. Now
matches the chat-completions adapter (modelOptions first, then
defined top-level options), so callers tuning either backend see
identical behaviour.
- extractTextFromResponse now throws a distinct refusal error instead
of returning '' and letting JSON.parse('') produce a confusing
'Failed to parse structured output as JSON. Content: ' message.
openai-base/adapters/summarize.ts
- generateId(this.name) for the result id (was hard-coded to '').
- Throw when chatStream emits RUN_ERROR instead of pretending a failed
run succeeded with summary: ''.
openai-base/adapters/{image,transcription,tts}.ts
- Wrap SDK calls in try/catch + logger.errors with toRunErrorPayload
so raw SDK errors (which can carry request metadata including auth
headers) never reach user-supplied loggers. Matches the audit
hygiene main #465 applied to ai-openai/text.ts before the
extraction.
- tts.ts: cross-runtime ArrayBuffer→base64 helper so the adapter works
in browser/edge runtimes that lack Buffer.
- transcription.ts: confidence calculation no longer treats
avg_logprob === 0 (perfect-confidence) as missing.
openai-base/tools/file-search-tool.ts
- validateMaxNumResults(0) now correctly throws (was skipped because
`if (maxNumResults && ...)` short-circuited on falsy zero).
ai-openai/adapters/transcription.ts
- shouldDefaultToVerbose returns true ONLY for whisper-1. The
gpt-4o-transcribe* models reject 'verbose_json' with HTTP 400, so
defaulting them to verbose was a guaranteed-failure regression. The
previous logic was inverted.
ai-openai/tools/{file-search,image-generation}-tool.ts
- Drop locally duplicated validators; import from openai-base. The
local copy of validateMaxNumResults had the same falsy-zero bug.
ai-openai/tools/computer-use-tool.ts
- Document that the brand discriminator ('computer_use') intentionally
differs from the runtime tool name ('computer_use_preview'). The
brand matches the model-meta capability union; the runtime name
matches the OpenAI SDK literal that the special-tool dispatcher
switches on.
ai-utils/src/transforms.ts
- Document transformNullsToUndefined's actual behavior (object keys
are removed, top-level null becomes undefined, arrays preserve
positional null). Restrict scope to JSON-shaped values; class
instances/Date/Map/Set are not preserved by Object.entries recursion.
ai-elevenlabs/src/utils/client.ts
- Wire getElevenLabsApiKeyFromEnv and generateId through
@tanstack/ai-utils so the dependency added during the merge is
actually consumed (was unused after main's #504 SDK migration).
ai-openrouter/package.json
- Move @tanstack/ai from dependencies to devDependencies (it's
already declared as a peerDependency). Avoids dual-instance hazards
where the workspace package gets installed twice. Also bump the
peer range to workspace:^ to match every other adapter.
.changeset/refactor-providers-to-shared-packages.md
- Correct the description: only ai-openai/ai-grok/ai-groq inherit
from @tanstack/openai-base; the other six providers only consume
@tanstack/ai-utils. Previous wording implied all nine adapters
delegated to openai-base.
Verification:
- pnpm test:lib : 31 projects pass (116+ unit tests)
- pnpm test:types : 32 projects pass
- pnpm test:eslint : 31 projects pass
- pnpm build : 33 projects pass1 parent ff0c683 commit 338a54a
16 files changed
Lines changed: 384 additions & 159 deletions
File tree
- .changeset
- packages/typescript
- ai-elevenlabs/src/utils
- ai-openai/src
- adapters
- tools
- ai-openrouter
- ai-utils/src
- openai-base/src
- adapters
- tools
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
2 | 6 | | |
3 | 7 | | |
4 | 8 | | |
| |||
39 | 43 | | |
40 | 44 | | |
41 | 45 | | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
| 46 | + | |
50 | 47 | | |
51 | 48 | | |
52 | 49 | | |
| |||
80 | 77 | | |
81 | 78 | | |
82 | 79 | | |
83 | | - | |
84 | | - | |
85 | | - | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
86 | 83 | | |
87 | 84 | | |
88 | 85 | | |
| |||
Lines changed: 4 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
38 | | - | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
39 | 42 | | |
40 | 43 | | |
41 | 44 | | |
| |||
Lines changed: 6 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
10 | 16 | | |
11 | 17 | | |
12 | 18 | | |
| |||
Lines changed: 1 addition & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
1 | 2 | | |
2 | 3 | | |
3 | 4 | | |
| |||
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
10 | | - | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | 11 | | |
17 | 12 | | |
18 | 13 | | |
| |||
Lines changed: 1 addition & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
1 | 2 | | |
2 | 3 | | |
3 | 4 | | |
| |||
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | 16 | | |
22 | 17 | | |
23 | 18 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
47 | | - | |
48 | 47 | | |
49 | 48 | | |
50 | 49 | | |
| 50 | + | |
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
56 | | - | |
| 56 | + | |
57 | 57 | | |
58 | 58 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
3 | | - | |
4 | | - | |
5 | | - | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
6 | 20 | | |
7 | 21 | | |
8 | 22 | | |
| |||
Lines changed: 87 additions & 51 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
242 | 242 | | |
243 | 243 | | |
244 | 244 | | |
| 245 | + | |
245 | 246 | | |
246 | 247 | | |
247 | 248 | | |
248 | | - | |
249 | | - | |
250 | | - | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
251 | 252 | | |
252 | 253 | | |
253 | 254 | | |
254 | | - | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
255 | 258 | | |
256 | 259 | | |
257 | 260 | | |
| |||
271 | 274 | | |
272 | 275 | | |
273 | 276 | | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
274 | 280 | | |
275 | 281 | | |
276 | 282 | | |
| |||
373 | 379 | | |
374 | 380 | | |
375 | 381 | | |
376 | | - | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
377 | 388 | | |
378 | 389 | | |
379 | 390 | | |
380 | 391 | | |
381 | 392 | | |
382 | 393 | | |
383 | 394 | | |
384 | | - | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
385 | 398 | | |
386 | | - | |
387 | | - | |
388 | | - | |
389 | | - | |
390 | | - | |
391 | | - | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
392 | 418 | | |
393 | 419 | | |
394 | 420 | | |
| |||
404 | 430 | | |
405 | 431 | | |
406 | 432 | | |
407 | | - | |
408 | | - | |
409 | | - | |
410 | | - | |
411 | | - | |
412 | | - | |
413 | 433 | | |
414 | 434 | | |
415 | 435 | | |
| |||
418 | 438 | | |
419 | 439 | | |
420 | 440 | | |
| 441 | + | |
421 | 442 | | |
422 | 443 | | |
423 | | - | |
424 | | - | |
425 | | - | |
426 | | - | |
427 | | - | |
428 | | - | |
429 | | - | |
430 | | - | |
431 | | - | |
432 | | - | |
433 | | - | |
434 | | - | |
435 | | - | |
436 | | - | |
437 | | - | |
438 | | - | |
439 | | - | |
440 | | - | |
441 | | - | |
442 | | - | |
443 | | - | |
444 | | - | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
445 | 447 | | |
446 | 448 | | |
447 | 449 | | |
448 | | - | |
449 | | - | |
450 | | - | |
451 | | - | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
452 | 458 | | |
453 | 459 | | |
454 | 460 | | |
455 | 461 | | |
456 | | - | |
| 462 | + | |
457 | 463 | | |
458 | 464 | | |
459 | 465 | | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
460 | 476 | | |
461 | 477 | | |
462 | 478 | | |
463 | | - | |
| 479 | + | |
464 | 480 | | |
465 | 481 | | |
466 | 482 | | |
| |||
469 | 485 | | |
470 | 486 | | |
471 | 487 | | |
472 | | - | |
| 488 | + | |
473 | 489 | | |
474 | 490 | | |
475 | 491 | | |
| |||
528 | 544 | | |
529 | 545 | | |
530 | 546 | | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
531 | 552 | | |
532 | 553 | | |
533 | 554 | | |
534 | 555 | | |
535 | | - | |
536 | | - | |
537 | | - | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
538 | 563 | | |
539 | 564 | | |
540 | 565 | | |
| |||
609 | 634 | | |
610 | 635 | | |
611 | 636 | | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
612 | 648 | | |
613 | 649 | | |
614 | | - | |
| 650 | + | |
615 | 651 | | |
616 | 652 | | |
617 | 653 | | |
| |||
0 commit comments