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

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions apps/cli/ai/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export interface AiAgentConfig {
prompt: string;
env?: Record< string, string >;
model?: AiModelId;
maxTurns?: number;
resume?: string;
activeSite?: SiteInfo | null;
wpcomAccessToken?: string;
Expand Down Expand Up @@ -58,7 +57,6 @@ export function startAiAgent( config: AiAgentConfig ): Query {
prompt,
env,
model = DEFAULT_MODEL,
maxTurns = 75,
resume,
activeSite,
wpcomAccessToken,
Expand Down Expand Up @@ -137,7 +135,6 @@ export function startAiAgent( config: AiAgentConfig ): Query {
append: buildSystemPrompt( systemPromptOptions ),
},
mcpServers,
maxTurns,
cwd: STUDIO_SITES_ROOT,
tools: { type: 'preset', preset: 'claude_code' },
permissionMode: 'auto',
Expand Down
3 changes: 0 additions & 3 deletions apps/cli/ai/eval-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import type { AiProviderId } from 'cli/ai/providers';

interface EvalRunnerInput {
prompt: string;
maxTurns?: number;
timeoutMs?: number;
}

Expand Down Expand Up @@ -134,7 +133,6 @@ function readInput(): EvalRunnerInput {

return {
prompt: ( vars.prompt as string ) ?? prompt,
maxTurns: typeof vars.maxTurns === 'number' ? vars.maxTurns : undefined,
timeoutMs: typeof vars.timeoutMs === 'number' ? vars.timeoutMs : undefined,
};
}
Expand Down Expand Up @@ -185,7 +183,6 @@ async function runEval( input: EvalRunnerInput ) {
const query = startAiAgent( {
prompt: input.prompt.trim(),
env,
maxTurns: input.maxTurns ?? 50,
} );
phaseTimingsMs.start_ai_agent_ms = Date.now() - phaseStartedAt;

Expand Down
17 changes: 6 additions & 11 deletions apps/cli/ai/output-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import type { SDKMessage } from '@anthropic-ai/claude-agent-sdk';
import type { AiProviderId } from 'cli/ai/providers';
import type { SiteInfo } from 'cli/ai/ui';

export type HandleMessageResult =
| { type: 'result'; sessionId: string; success: boolean; interrupted?: boolean }
| { type: 'max_turns'; sessionId: string; numTurns: number; costUsd?: number };
export type HandleMessageResult = {
type: 'result';
sessionId: string;
success: boolean;
interrupted?: boolean;
};

export interface AiOutputAdapter {
currentProvider: AiProviderId;
Expand Down Expand Up @@ -134,14 +137,6 @@ export class JsonAdapter implements AiOutputAdapter {

if ( message.type === 'result' ) {
this.sessionId = message.session_id;
if ( message.subtype === 'error_max_turns' ) {
return {
type: 'max_turns',
sessionId: message.session_id,
numTurns: message.num_turns,
costUsd: message.total_cost_usd,
};
}
return {
type: 'result',
sessionId: message.session_id,
Expand Down
9 changes: 0 additions & 9 deletions apps/cli/ai/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2219,15 +2219,6 @@ export class AiChatUI implements AiOutputAdapter {
case 'result': {
this.hideLoader();

// Max-turns exhaustion has dedicated upstream handling (prompts user to continue).
if ( message.subtype === 'error_max_turns' ) {
return {
type: 'max_turns',
sessionId: message.session_id,
numTurns: message.num_turns,
};
}

// When the cap message was surfaced earlier in this turn,
// the SDK still classifies the turn as successful (or returns
// is_error with the raw upstream body). Skip the "Done" /
Expand Down
39 changes: 4 additions & 35 deletions apps/cli/commands/ai/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { listAiSessions } from '@studio/common/ai/sessions/store';
import { type LoadedAiSession, type TurnStatus } from '@studio/common/ai/sessions/types';
import { buildSkillInvocationPrompt } from '@studio/common/ai/slash-commands';
import { readAuthToken } from '@studio/common/lib/shared-config';
import { __, _n, sprintf } from '@wordpress/i18n';
import { __, sprintf } from '@wordpress/i18n';
import { DEFAULT_MODEL, startAiAgent, type AiModelId, type AskUserQuestion } from 'cli/ai/agent';
import {
getAvailableAiProviders,
Expand Down Expand Up @@ -423,7 +423,7 @@ export async function runCommand( options: {
async function runAgentTurn(
prompt: string,
retryAttempt = 0
): Promise< { status: TurnStatus; usage?: { numTurns: number; costUsd?: number } } > {
): Promise< { status: TurnStatus } > {
await maybeAutoSwitchProvider();
const recorder = await ensureSessionRecorder();
const env = await resolveAiEnvironment( currentProvider, {
Expand Down Expand Up @@ -485,7 +485,6 @@ export async function runCommand( options: {
resolveInterrupt();
};

let maxTurnsResult: { numTurns: number } | undefined;
const turnState: { status: TurnStatus } = { status: 'interrupted' };

const consumeAgentTurn = async (): Promise< void > => {
Expand All @@ -500,12 +499,7 @@ export async function runCommand( options: {
sessionId = result.sessionId;
await persist( ( recorder ) => recorder.recordAgentSessionId( result.sessionId ) );

if ( result.type === 'max_turns' ) {
maxTurnsResult = {
numTurns: result.numTurns,
};
turnState.status = 'max_turns';
} else if ( result.interrupted ) {
if ( result.interrupted ) {
turnState.status = 'interrupted';
} else {
turnState.status = result.success ? 'success' : 'error';
Expand Down Expand Up @@ -546,30 +540,6 @@ export async function runCommand( options: {
ui.endAgentTurn();
}

if ( maxTurnsResult ) {
ui.showInfo(
sprintf(
/* translators: %d: number of turns used */
_n( 'Used %d turn', 'Used %d turns', maxTurnsResult.numTurns ),
maxTurnsResult.numTurns
)
);
const answer = await ui.askUser( [
{
question: __( 'Reached the turn limit. Continue?' ),
options: [
{ label: 'Yes', description: __( 'Resume where the agent left off' ) },
{ label: 'No', description: __( 'Stop here' ) },
],
},
] );
const choice = Object.values( answer )[ 0 ]?.toLowerCase();
if ( choice === 'yes' ) {
ui.addUserMessage( 'Continue' );
return runAgentTurn( 'Continue from where you left off.' );
}
}

// Skip the retry prompt when the UI has already surfaced a terminal
// error (e.g. AI usage cap). Retrying won't recover from a cap, and
// the user has already been told what to do next.
Expand Down Expand Up @@ -607,7 +577,6 @@ export async function runCommand( options: {

return {
status: turnState.status,
usage: maxTurnsResult,
};
}

Expand All @@ -617,7 +586,7 @@ export async function runCommand( options: {
ui.addUserMessage( options.initialMessage );
const result = await runAgentTurn( options.initialMessage );
const jsonStatus = result.status === 'interrupted' ? 'error' : result.status;
( ui as JsonAdapter ).emitTurnCompleted( jsonStatus, result.usage );
( ui as JsonAdapter ).emitTurnCompleted( jsonStatus );
} catch ( error ) {
process.exitCode = 1;
handleAgentTurnError( error );
Expand Down
3 changes: 0 additions & 3 deletions eval/promptfoo.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ tests:
- description: agent identifies as WordPress Studio AI
vars:
caseId: identity
maxTurns: 12
timeoutMs: 60000
prompt: In one short sentence, tell me who you are. Do not call any tools.
assert:
Expand All @@ -53,7 +52,6 @@ tests:
- description: agent calls site_create when asked to make a site
vars:
caseId: site-creation
maxTurns: 20
timeoutMs: 120000
askUserPolicy: allow_all
prompt: |
Expand Down Expand Up @@ -85,7 +83,6 @@ tests:
- description: single-page site build keeps every turn under 60s
vars:
caseId: single-page-build-turn-cadence
maxTurns: 80
timeoutMs: 600000
askUserPolicy: allow_all
prompt: |
Expand Down
Loading