Skip to content

feat(agents): input parameter parity with Vercel AI SDK#65

Open
zrosenbauer wants to merge 6 commits intomainfrom
fix/62
Open

feat(agents): input parameter parity with Vercel AI SDK#65
zrosenbauer wants to merge 6 commits intomainfrom
fix/62

Conversation

@zrosenbauer
Copy link
Member

Summary

Closes #62

  • Add CallSettings to AgentConfig and per-call overrides: temperature, maxOutputTokens, topP, topK, presencePenalty, frequencyPenalty, stopSequences, seed, maxRetries
  • Add granular timeout support — timeout now accepts number | { totalMs?, stepMs?, toolMs?, ... } forwarded to the AI SDK
  • Add telemetry (experimental_telemetry) on both config and per-call overrides
  • Add custom stop conditions (stopWhen) — combined with internal stepCountIs(maxSteps) safety ceiling
  • Add stream-only callbacks: onChunk, onStreamError (AI SDK's onError), onAbort
  • Re-export StopCondition and TelemetrySettings from the public API

All new fields are optional — no breaking changes.

Test plan

  • pnpm typecheck — all 22 tasks pass
  • pnpm build --filter=@funkai/agents — clean build
  • pnpm test --filter=@funkai/agents — 644/644 tests pass, no type errors
  • Manual verification with a real agent using new CallSettings (e.g. temperature, maxOutputTokens)
  • Manual verification of stopWhen with custom stop conditions
  • Manual verification of stream-only callbacks (onChunk, onStreamError, onAbort)

zrosenbauer and others added 2 commits March 25, 2026 18:25
Surface CallSettings (temperature, maxOutputTokens, topP, topK,
presencePenalty, frequencyPenalty, stopSequences, seed, maxRetries),
telemetry (experimental_telemetry), granular timeout objects, custom
stop conditions (stopWhen), and stream-only callbacks (onChunk,
onStreamError, onAbort) on both AgentConfig and per-call overrides.

Closes #62

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@changeset-bot
Copy link

changeset-bot bot commented Mar 25, 2026

🦋 Changeset detected

Latest commit: 1623a5d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@funkai/agents Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Mar 25, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
funkai Error Error Mar 25, 2026 11:48pm

Request Review

@coderabbitai
Copy link

coderabbitai bot commented Mar 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5c534973-fcd5-4add-9b1d-abd2403160ce

📥 Commits

Reviewing files that changed from the base of the PR and between 54020c5 and 1623a5d.

📒 Files selected for processing (4)
  • packages/agents/src/core/agents/base/agent.ts
  • packages/agents/src/core/agents/flow/steps/factory.ts
  • packages/agents/src/core/types.test-d.ts
  • packages/agents/src/core/types.ts

📝 Walkthrough

Walkthrough

This PR refactors StepFinishEvent construction by introducing factory functions stepFinishEventFromAIStep() and stepFinishEventFromFlow() to centralize event creation. It adds toolCalls and toolResults properties to StepFinishEvent type and updates usage sites in agent and flow step factories to use the new factory functions instead of inline object assembly.

Changes

Cohort / File(s) Summary
Type Definitions & Factories
packages/agents/src/core/types.ts
Added toolCalls and toolResults properties to exported StepFinishEvent type. Introduced two exported factory functions: stepFinishEventFromAIStep() (spreads full AI StepResult with extras) and stepFinishEventFromFlow() (creates event for flow steps with stubbed tool fields and optional AI overrides).
Type Tests
packages/agents/src/core/types.test-d.ts
New file with 52 lines of Vitest type assertions validating StepFinishEvent shape, verifying toolCalls/toolResults match AIStepResult fields, and confirming factory function return types conform to StepFinishEvent.
Event Construction Updates
packages/agents/src/core/agents/base/agent.ts, packages/agents/src/core/agents/flow/steps/factory.ts
Replaced inline StepFinishEvent object literals with factory function calls (stepFinishEventFromAIStep in agent.ts, stepFinishEventFromFlow in factory.ts). Centralized event shape assembly logic.
Changeset
.changeset/input-param-parity.md
Documents minor version bump for @funkai/agents covering input parameter parity alignment (CallSettings, telemetry, timeout configuration, stopWhen, stream callbacks).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

  • PR #50 — Modifies StepFinishEvent construction and type handling in agents package, directly overlaps with centralization of event creation logic introduced here.
  • PR #55 — Adds AIStepResult integration and updates step finish event handling to forward AI SDK fields, shares the same factory function pattern and type alignment goals.
  • PR #13 — Refactors step-finish hook invocation and event construction in agent base code, shares the same centralization pattern for onStepFinish event assembly.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main objective: adding input parameter parity with the Vercel AI SDK to the agents package.
Description check ✅ Passed The description is directly related to the changeset, covering CallSettings, timeout handling, telemetry, stop conditions, and stream callbacks as documented in the code changes.
Linked Issues check ✅ Passed The PR implements the core requirements from issue #62: CallSettings fields, granular timeout support, telemetry, custom stop conditions, and stream-only callbacks are all addressed in the changeset and type definitions.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #62 objectives. The StepFinishEvent enhancements (toolCalls/toolResults) are related to issue #66 (mentioned in objectives) and are necessary foundational changes for proper event typing.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/agents/src/core/agents/flow/flow-agent.ts (1)

296-315: ⚠️ Potential issue | 🟡 Minor

Fix nested ternary to comply with no-ternary rule.

Lines 301-303 use a nested ternary expression, which violates the project's no-ternary lint rule (flagged by static analysis). Use if/else blocks instead.

Proposed fix using if/else
 function resolveSignal(params: FlowGenerateParams): AbortSignal {
   const { timeout, signal } = params;

-  // Object timeout — use totalMs for the flow-level signal (stepMs/toolMs
-  // are forwarded to individual agent calls, not handled here)
-  const timeoutMs = typeof timeout === "number"
-    ? timeout
-    : (typeof timeout === "object" && isNotNil(timeout) ? timeout.totalMs : undefined);
+  // Object timeout — use totalMs for the flow-level signal (stepMs/toolMs
+  // are forwarded to individual agent calls, not handled here).
+  let timeoutMs: number | undefined;
+  if (typeof timeout === "number") {
+    timeoutMs = timeout;
+  } else if (typeof timeout === "object" && isNotNil(timeout)) {
+    timeoutMs = timeout.totalMs;
+  }

   if (signal && isNotNil(timeoutMs)) {
     return AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)]);
   }
   if (isNotNil(timeoutMs)) {
     return AbortSignal.timeout(timeoutMs);
   }
   if (signal) {
     return signal;
   }
   return new AbortController().signal;
 }

As per coding guidelines: "No ternaries — use match(), if/else, or early returns."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/agents/src/core/agents/flow/flow-agent.ts` around lines 296 - 315,
The nested ternary in resolveSignal that computes timeoutMs from
FlowGenerateParams (using timeout and isNotNil) violates the no-ternary rule;
replace it with a clear if/else block: declare let timeoutMs: number |
undefined, then if typeof timeout === "number" set timeoutMs = timeout, else if
typeof timeout === "object" && isNotNil(timeout) set timeoutMs =
timeout.totalMs, else leave undefined; keep the rest of resolveSignal logic that
uses signal, AbortSignal.timeout and AbortSignal.any unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/agents/src/core/agents/flow/flow-agent.ts`:
- Around line 296-315: The nested ternary in resolveSignal that computes
timeoutMs from FlowGenerateParams (using timeout and isNotNil) violates the
no-ternary rule; replace it with a clear if/else block: declare let timeoutMs:
number | undefined, then if typeof timeout === "number" set timeoutMs = timeout,
else if typeof timeout === "object" && isNotNil(timeout) set timeoutMs =
timeout.totalMs, else leave undefined; keep the rest of resolveSignal logic that
uses signal, AbortSignal.timeout and AbortSignal.any unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: abd7dcf4-a9f7-4a71-a344-077826049389

📥 Commits

Reviewing files that changed from the base of the PR and between 675aae8 and 4daf688.

📒 Files selected for processing (5)
  • .changeset/input-param-parity.md
  • packages/agents/src/core/agents/base/agent.ts
  • packages/agents/src/core/agents/flow/flow-agent.ts
  • packages/agents/src/core/agents/types.ts
  • packages/agents/src/index.ts

Merge duplicate ai import, replace nested ternary with if/else in
flow-agent resolveSignal, capitalize comment.

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/agents/src/core/agents/base/agent.ts`:
- Around line 814-821: Change the stopWhen types to accept either a single
StopCondition or an array and update buildStopConditions to accept and normalize
both forms: update GenerateParams.stopWhen and AgentGenerateOverrides.stopWhen
to the widened type StopCondition<ToolSet> | StopCondition<ToolSet>[] |
undefined, and change buildStopConditions(maxSteps, userConditions) to accept
userConditions: StopCondition<ToolSet> | StopCondition<ToolSet>[] | undefined;
implement logic so if userConditions is nil return stepCountIs(maxSteps), if
it's an array return [...userConditions, stepCountIs(maxSteps)], and if it's a
single StopCondition return [userConditions, stepCountIs(maxSteps)] so the
stepCountIs is always enforced.

In `@packages/agents/src/core/agents/flow/flow-agent.ts`:
- Around line 299-311: The resolveSignal logic in flow-agent.ts only reads
timeout.totalMs and silently drops stepMs/chunkMs, so update resolveSignal (the
function that extracts timeoutMs) to either narrow the accepted timeout type to
number | { totalMs?: number } or validate the passed object and throw when
unsupported keys (stepMs, chunkMs, etc.) are present; ensure callers like
flowAgent.generate and flowAgent.stream cannot pass nested timeout objects with
stepMs/chunkMs that will be ignored by: 1) adjusting the TypeScript type for the
timeout parameter to remove stepMs/chunkMs, or 2) adding a runtime check inside
resolveSignal that inspects the timeout object and throws a clear error if any
unknown keys (e.g., "stepMs", "chunkMs") are found, otherwise continue to use
totalMs to build the AbortSignal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b36fdb41-2291-40c6-a68b-44596649b252

📥 Commits

Reviewing files that changed from the base of the PR and between 4daf688 and 7472f3a.

📒 Files selected for processing (3)
  • packages/agents/src/core/agents/base/agent.ts
  • packages/agents/src/core/agents/flow/flow-agent.ts
  • packages/agents/src/core/agents/types.ts

Address PR review feedback: the AI SDK accepts `StopCondition |
StopCondition[]` for `stopWhen`. Widen the type on AgentGenerateOverrides
and update buildStopConditions() to normalize both forms.

Co-Authored-By: Claude <noreply@anthropic.com>
@zrosenbauer
Copy link
Member Author

Re: flow agent timeout object handling — created #67 to track this as a follow-up. The flow agent currently only supports totalMs from timeout objects; stepMs/toolMs/per-tool keys are silently dropped. Will address with either a warning, type narrowing, or runtime validation in a separate PR.

Make toolCalls and toolResults required fields on StepFinishEvent
instead of hiding them behind Partial<AIStepResult>. Add factory
functions (stepFinishEventFromAIStep, stepFinishEventFromFlow) so
event construction is centralized and flow steps stub empty arrays.

Add type tests ensuring StepFinishEvent.toolCalls and toolResults
match the AI SDK's StepResult types.

Closes #66

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(agents): achieve 100% input parameter parity with Vercel AI SDK generateText/streamText

1 participant