Commit Graph
6 Commits
Author SHA1 Message Date
Jack Chen 5033842802 fix(core): make unsupported-video terminal and validate video URL sources (#566)
Follow-up to #548, which introduced VideoBlock. Two gaps were missed when that
PR was reviewed.

The four adapters that cannot map video threw a bare Error. isRetryableError
returns true for any Error without a status, so executeWithRetry treated a
deterministic capability gap as transient: it ran the full backoff ladder and
rewrote a checkpoint per attempt before failing the same way, and the failure
was recorded as retryable. UnsupportedContentBlockError makes that terminal,
names the adapter that rejected the block, and carries a code alongside the
existing UnsupportedToolResultContentError.

VideoBlock is the first top-level content block with a URL source, so it
inherited no validation. That source is dereferenced by the provider rather
than by OMA, and a file: path or a data URL pasted into the field was forwarded
verbatim; an unvalidated media_type could also alter the data URL built for
inline bytes. Public entry points now run video sources through the same
copyMediaSource rules already applied to tool-result media, so the documented
HTTP(S) constraint is enforced rather than aspirational. Provider-private
upload handles such as MiniMax's mm_file:// are rejected: supporting them needs
a source variant of its own, not an unchecked string.

Also from the same review:

- estimateTokens charged an inline video the 64-character fixed cost images
  get, hiding a multi-megabyte payload from every context strategy keyed off
  the estimate. It is now sized like rich tool-result media, so the attachment
  that needs compacting is the one that triggers compaction.
- stripImageBlocksForSummary handles video too, so it is now
  stripMediaBlocksForSummary.
- The two double casts in openai-common are narrowed to a single seam, and the
  video_url extension type now records that it is not an OpenAI part.
- docs/structured-input.md states the rule the adapters actually follow:
  OpenAI-shaped adapters forward and let the provider decide, adapters with a
  typed content union reject locally. Bedrock and Gemini support video
  upstream, so the gap there is OMA's mapping rather than theirs.
2026-09-03 12:05:03 +08:00
Jack Chen 8fa3bb8362 feat(release): add OMA-powered release bot (#483)
* feat(release): add OMA-powered release bot

* fix(release): harden bot execution boundaries

* chore(release): schedule bot for Friday evening
2026-08-10 17:18:29 +08:00
Jack Chen f14708b308 feat(core): support rich tool results (#479)
- separate application-owned data from model-visible text, image, and file content
- map rich results across built-in adapters and preserve them through recovery
- retain backward compatibility for string tools and text-only errors

Closes #466
2026-08-08 11:49:55 +08:00
Jack Chen c2b4b6f194 chore(deps)!: upgrade OpenAI SDK to v6 and require Node 20 (#453)
* chore(deps)!: upgrade OpenAI SDK to v7

Require Node.js 22 across packages, starters, and CI. Add real SDK boundary coverage and reject unsupported custom tool calls explicitly.

Refs #391

* fix(core): classify OpenAI user aborts as cancellation

Use the SDK error constructor name because OpenAI v7 APIUserAbortError retains the default Error name. Cover retry and observability classification with the real SDK class.

* chore(deps)!: target OpenAI v6 and retain Node 20

* docs: simplify Node runtime guidance
2026-07-29 11:21:27 +08:00
Jack Chen 0803bab9c8 fix(core): enforce task requirements globally 2026-07-26 11:21:17 +08:00
Jack Chen 0488362c0d feat(orchestrator): error-aware task retry (classify, jitter, honor abort) (#346)
Error-aware task retry (opt-in via maxRetries > 0):

- Skip retries on provably-terminal failures (4xx client errors except
  408/409/429, token-budget, invalid-message, aborted calls).
- Equal jitter on backoff to avoid lockstep retries against a rate-limited
  provider.
- Honor abortSignal between attempts (no full-backoff sleep or extra attempt
  after cancel).
- Non-streaming path preserves the structured error on AgentRunResult.error so
  classification works off the default runTeam path; test-covered.

Off by default; behavior changes only when retry is enabled.

Closes #337
2026-07-01 17:22:54 +08:00