Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/markform/scripts/test-live-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { parseForm } from '../src/engine/parse.js';
import { serializeSession } from '../src/engine/session.js';
import type { SessionTranscript, SessionTurn, Patch } from '../src/engine/coreTypes.js';
import { createMarkformTools, MarkformSessionStore } from '../src/integrations/vercelAiSdkTools.js';
import { CLI_DEFAULT_MAX_RETRIES } from '../src/settings.js';

// Get the directory of this script
const __filename = fileURLToPath(import.meta.url);
Expand Down Expand Up @@ -352,6 +353,7 @@ If a field asks for specific format (email, date, etc.), use the correct format.
prompt,
tools: tools as unknown as Parameters<typeof generateText>[0]['tools'],
maxSteps: 5,
maxRetries: CLI_DEFAULT_MAX_RETRIES,
} as Parameters<typeof generateText>[0]);

console.log(`Model response: ${result.text || '(tool calls only)'}`);
Expand Down
10 changes: 10 additions & 0 deletions packages/markform/src/cli/commands/fill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import { createLiveAgent, buildMockWireFormat } from '../../harness/liveAgent.js
import { createMockAgent } from '../../harness/mockAgent.js';
import { fillForm } from '../../harness/programmaticFill.js';
import {
CLI_DEFAULT_MAX_RETRIES,
DEFAULT_MAX_ISSUES_PER_TURN,
DEFAULT_MAX_PATCHES_PER_TURN,
DEFAULT_MAX_TURNS,
Expand Down Expand Up @@ -159,6 +160,11 @@ export function registerFillCommand(program: Command): void {
`Maximum issues shown per turn (default: ${DEFAULT_MAX_ISSUES_PER_TURN})`,
String(DEFAULT_MAX_ISSUES_PER_TURN),
)
.option(
'--max-retries <n>',
`Maximum retries for transient API errors (default: ${CLI_DEFAULT_MAX_RETRIES})`,
String(CLI_DEFAULT_MAX_RETRIES),
)
.option('--max-fields <n>', 'Maximum unique fields per turn (applied before --max-issues)')
.option('--max-groups <n>', 'Maximum unique groups per turn (applied before --max-issues)')
.option(
Expand Down Expand Up @@ -197,6 +203,7 @@ export function registerFillCommand(program: Command): void {
maxTurns?: string;
maxPatches?: string;
maxIssues?: string;
maxRetries?: string;
maxFields?: string;
maxGroups?: string;
roles?: string;
Expand Down Expand Up @@ -388,13 +395,15 @@ export function registerFillCommand(program: Command): void {
}

// Run programmatic fill with parallel enabled
const maxRetries = parseInt(options.maxRetries!, 10);
const result = await fillForm({
form,
model: options.model!,
enableParallel: true,
enableWebSearch: true,
captureWireFormat: false,
recordFill: true,
maxRetries,
targetRoles,
fillMode,
maxTurnsTotal: options.maxTurns ? parseInt(options.maxTurns, 10) : undefined,
Expand Down Expand Up @@ -641,6 +650,7 @@ export function registerFillCommand(program: Command): void {
systemPromptAddition: systemPrompt,
targetRole,
enableWebSearch: true,
maxRetries: parseInt(options.maxRetries!, 10),
callbacks,
});
agent = liveAgent;
Expand Down
8 changes: 8 additions & 0 deletions packages/markform/src/cli/commands/research.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
} from '../../llms.js';
import {
AGENT_ROLE,
CLI_DEFAULT_MAX_RETRIES,
DEFAULT_MAX_TURNS,
DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN,
DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN,
Expand Down Expand Up @@ -78,6 +79,11 @@ export function registerResearchCommand(program: Command): void {
`Maximum issues per turn (default: ${DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN})`,
String(DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN),
)
.option(
'--max-retries <n>',
`Maximum retries for transient API errors (default: ${CLI_DEFAULT_MAX_RETRIES})`,
String(CLI_DEFAULT_MAX_RETRIES),
)
.option('--transcript', 'Save session transcript')
.action(async (input: string, options: Record<string, unknown>, cmd: Command) => {
const ctx = getCommandContext(cmd);
Expand Down Expand Up @@ -158,6 +164,7 @@ export function registerResearchCommand(program: Command): void {
const maxTurns = parseInt(options.maxTurns as string, 10);
const maxPatchesPerTurn = parseInt(options.maxPatches as string, 10);
const maxIssuesPerTurn = parseInt(options.maxIssues as string, 10);
const maxRetries = parseInt(options.maxRetries as string, 10);

// Log research start
logInfo(ctx, `Research fill with model: ${modelId}`);
Expand All @@ -184,6 +191,7 @@ export function registerResearchCommand(program: Command): void {
enableWebSearch: true,
captureWireFormat: false,
recordFill: false,
maxRetries,
maxTurnsTotal: maxTurns,
maxPatchesPerTurn,
maxIssuesPerTurn,
Expand Down
2 changes: 2 additions & 0 deletions packages/markform/src/cli/commands/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
AGENT_ROLE,
USER_ROLE,
MAX_FORMS_IN_MENU,
CLI_DEFAULT_MAX_RETRIES,
DEFAULT_MAX_TURNS,
DEFAULT_MAX_PATCHES_PER_TURN,
DEFAULT_MAX_ISSUES_PER_TURN,
Expand Down Expand Up @@ -243,6 +244,7 @@ async function runAgentFillWorkflow(
maxTurnsTotal: maxTurns,
maxPatchesPerTurn,
maxIssuesPerTurn,
maxRetries: CLI_DEFAULT_MAX_RETRIES,
targetRoles: [AGENT_ROLE],
fillMode: overwrite ? 'overwrite' : 'continue',
enableWebSearch: isResearch,
Expand Down
12 changes: 8 additions & 4 deletions packages/markform/src/harness/harnessTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,11 @@ export interface LiveAgentConfig {
* Uses the Vercel AI SDK's built-in exponential backoff with jitter.
* Set to 0 to disable retries (useful for fast tests).
*
* @default 3
* **Required** — must be set explicitly.
* The Vercel AI SDK's own default is 2. Common values: 0 (no retries / tests),
* 2–3 (production).
*/
maxRetries?: number;
maxRetries: number;

/**
* AbortSignal for cancelling in-flight LLM calls.
Expand Down Expand Up @@ -549,9 +551,11 @@ export interface FillOptions {
* Set to 0 to disable AI SDK retries and handle retries externally
* (recommended for production harnesses that need full control over retry behavior).
*
* @default 3 (DEFAULT_MAX_RETRIES from settings.ts)
* **Required** — must be set explicitly.
* The Vercel AI SDK's own default is 2. Common values: 0 (no retries / tests),
* 2–3 (production).
*/
maxRetries?: number;
maxRetries: number;
}

/**
Expand Down
9 changes: 2 additions & 7 deletions packages/markform/src/harness/liveAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,7 @@ import type {
} from '../engine/coreTypes.js';
import { PatchSchema } from '../engine/coreTypes.js';
import { serializeForm } from '../engine/serialize.js';
import {
DEFAULT_ROLE_INSTRUCTIONS,
AGENT_ROLE,
DEFAULT_MAX_STEPS_PER_TURN,
DEFAULT_MAX_RETRIES,
} from '../settings.js';
import { DEFAULT_ROLE_INSTRUCTIONS, AGENT_ROLE, DEFAULT_MAX_STEPS_PER_TURN } from '../settings.js';
import { getWebSearchConfig } from '../llms.js';
import { wrapApiError } from '../errors.js';
import type {
Expand Down Expand Up @@ -85,7 +80,7 @@ export class LiveAgent implements Agent {
this.additionalTools = config.additionalTools ?? {};
this.callbacks = config.callbacks;
this.executionId = config.executionId ?? '0-serial';
this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
this.maxRetries = config.maxRetries;
this.signal = config.signal;
// TODO: Make toolChoice configurable per-model or per-form in the future.
// For now, 'required' is always safe since Markform agents must use tools.
Expand Down
4 changes: 2 additions & 2 deletions packages/markform/src/harness/programmaticFill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ export async function fillForm(options: FillOptions): Promise<FillResult> {
maxStepsPerTurn: options.maxStepsPerTurn,
toolChoice: options.toolChoice,
signal: options.signal,
...(options.maxRetries !== undefined && { maxRetries: options.maxRetries }),
maxRetries: options.maxRetries,
});

// 7. Run harness loop
Expand Down Expand Up @@ -901,7 +901,7 @@ async function fillFormParallel(
executionId,
toolChoice: options.toolChoice,
signal: options.signal,
...(options.maxRetries !== undefined && { maxRetries: options.maxRetries }),
maxRetries: options.maxRetries,
})
);
};
Expand Down
1 change: 1 addition & 0 deletions packages/markform/src/research/runResearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export async function runResearch(
targetRole: config.targetRoles?.[0] ?? AGENT_ROLE,
enableWebSearch: options.enableWebSearch,
additionalTools: options.additionalTools,
maxRetries: options.maxRetries,
});

// Get available tools for logging
Expand Down
17 changes: 10 additions & 7 deletions packages/markform/src/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,20 +223,23 @@ export const DEFAULT_MAX_ISSUES_PER_TURN = 10;
*/
export const DEFAULT_MAX_PARALLEL_AGENTS = 4;

/**
* Default maximum AI SDK retries for transient API errors (429, 503, etc.).
* The Vercel AI SDK handles retry with exponential backoff automatically.
* Set to 0 to disable retries (useful for fast tests).
*/
export const DEFAULT_MAX_RETRIES = 3;

/**
* Default maximum AI SDK steps (tool call rounds) per harness turn.
* Matches AI SDK's ToolLoopAgent default of 20.
* @see https://ai-sdk.dev/docs/agents/loop-control
*/
export const DEFAULT_MAX_STEPS_PER_TURN = 20;

/**
* Default maximum retries for transient API errors in CLI commands.
*
* This is the single source of truth for the CLI retry default.
* The Vercel AI SDK's own default is 2; we use 3 for slightly more resilience
* in CLI usage. The TypeScript API (`FillOptions`, `LiveAgentConfig`) has no
* default — callers must provide `maxRetries` explicitly.
*/
export const CLI_DEFAULT_MAX_RETRIES = 3;

// =============================================================================
// Research Defaults
// =============================================================================
Expand Down
Loading