diff --git a/packages/agent-core-v2/src/agent/externalHooks/externalHooksService.ts b/packages/agent-core-v2/src/agent/externalHooks/externalHooksService.ts index 1a50dc652..8e937aabc 100644 --- a/packages/agent-core-v2/src/agent/externalHooks/externalHooksService.ts +++ b/packages/agent-core-v2/src/agent/externalHooks/externalHooksService.ts @@ -26,7 +26,7 @@ import { type FullCompactionTask, } from '#/agent/fullCompaction'; import type { CompactionResult, CompactionSource } from '#/agent/fullCompaction/types'; -import { IAgentLoopService, type TurnAfterStepContext } from '#/agent/loop'; +import { IAgentLoopService, type AfterStepContext } from '#/agent/loop'; import { IAgentPermissionGate, } from '#/agent/permissionGate'; @@ -188,8 +188,8 @@ export class AgentExternalHooksService extends Disposable implements IAgentExter loop.hooks.afterStep.register('externalHooks', async (ctx, next) => { await next(); if ( - ctx.stopReason === 'tool_calls' || - ctx.stopReason === 'filtered' || + ctx.finishReason === 'tool_calls' || + ctx.finishReason === 'filtered' || ctx.continue ) { return; @@ -355,7 +355,7 @@ export class AgentExternalHooksService extends Disposable implements IAgentExter ); } - private async runStop(ctx: TurnAfterStepContext): Promise { + private async runStop(ctx: AfterStepContext): Promise { ctx.signal.throwIfAborted(); if (this.stopHookContinuationUsed) return undefined; diff --git a/packages/agent-core-v2/src/agent/fullCompaction/fullCompactionService.ts b/packages/agent-core-v2/src/agent/fullCompaction/fullCompactionService.ts index b82a506e2..c7f5388aa 100644 --- a/packages/agent-core-v2/src/agent/fullCompaction/fullCompactionService.ts +++ b/packages/agent-core-v2/src/agent/fullCompaction/fullCompactionService.ts @@ -16,7 +16,7 @@ import { sleepForRetry, type LLMRequestFinish, } from '#/agent/llmRequester'; -import { IAgentLoopService, type TurnErrorContext } from '#/agent/loop'; +import { IAgentLoopService, type LoopErrorContext } from '#/agent/loop'; import { isAbortError, isContextOverflowError } from '#/agent/loop/errors'; import { IAgentProfileService } from '#/agent/profile'; import { IAgentTurnService } from '#/agent/turn'; @@ -225,7 +225,7 @@ export class AgentFullCompactionService extends Disposable implements IAgentFull } private async onLoopError( - context: TurnErrorContext, + context: LoopErrorContext, next: () => Promise, ): Promise { if (!isContextOverflowError(context.error)) { diff --git a/packages/agent-core-v2/src/agent/goal/goalService.ts b/packages/agent-core-v2/src/agent/goal/goalService.ts index 9c59e323d..b1db97c3b 100644 --- a/packages/agent-core-v2/src/agent/goal/goalService.ts +++ b/packages/agent-core-v2/src/agent/goal/goalService.ts @@ -38,8 +38,8 @@ import { } from '#/agent/goal/tools/outcome-prompts'; import { IAgentLoopService, - type TurnAfterStepContext, - type TurnBeforeStepContext, + type AfterStepContext, + type BeforeStepContext, } from '#/agent/loop'; import { IAgentSystemReminderService } from '#/agent/systemReminder'; import { IAgentTurnService, type TurnResult } from '#/agent/turn'; @@ -370,14 +370,14 @@ export class AgentGoalService extends Disposable implements IAgentGoalService { this.goalOutcomeContinuationTurns.delete(turnId); } - private async handleBeforeStep(ctx: TurnBeforeStepContext): Promise { + private async handleBeforeStep(ctx: BeforeStepContext): Promise { if (!this.goalDrivenTurns.has(ctx.turnId)) return; if (this.countedGoalTurns.has(ctx.turnId)) return; this.countedGoalTurns.add(ctx.turnId); await this.incrementTurn(); } - private handleAfterStep(ctx: TurnAfterStepContext): void { + private handleAfterStep(ctx: AfterStepContext): void { if (this.goalDrivenTurns.has(ctx.turnId)) { const snapshot = this.accountTokenUsage(tokenUsageTotal(ctx.usage)); if (snapshot?.budget.overBudget === true) { diff --git a/packages/agent-core-v2/src/agent/loop/loop.ts b/packages/agent-core-v2/src/agent/loop/loop.ts index b991d8511..f97b43894 100644 --- a/packages/agent-core-v2/src/agent/loop/loop.ts +++ b/packages/agent-core-v2/src/agent/loop/loop.ts @@ -4,19 +4,19 @@ import type { TokenUsage } from '#/app/llmProtocol/usage'; import type { Hooks } from '#/hooks'; import type { TurnEndReason } from '@moonshot-ai/protocol'; -export interface TurnBeforeStepContext { +export interface BeforeStepContext { readonly turnId: number; readonly step: number; readonly signal: AbortSignal; } -export interface TurnAfterStepContext extends TurnBeforeStepContext { +export interface AfterStepContext extends BeforeStepContext { readonly usage: TokenUsage; - readonly stopReason: FinishReason; + readonly finishReason: FinishReason; continue: boolean; } -export interface TurnErrorContext { +export interface LoopErrorContext { readonly turnId: number; /** The currently executing step, or undefined for turn-level failures. */ readonly step?: number; @@ -29,14 +29,14 @@ export interface TurnErrorContext { retry: boolean; } -export interface RunOptions { +export interface LoopRunOptions { readonly turnId: number; readonly signal?: AbortSignal; /** Fires on the first model response event for a step, or at step completion. */ readonly onStarted?: (step: number) => void; } -export interface TurnResult { +export interface LoopRunResult { readonly reason: TurnEndReason; readonly error?: unknown; readonly steps?: number; @@ -45,12 +45,12 @@ export interface TurnResult { export interface IAgentLoopService { readonly _serviceBrand: undefined; - run(options: RunOptions): Promise; + run(options: LoopRunOptions): Promise; readonly hooks: Hooks<{ - beforeStep: TurnBeforeStepContext; - afterStep: TurnAfterStepContext; - onError: TurnErrorContext; + beforeStep: BeforeStepContext; + afterStep: AfterStepContext; + onError: LoopErrorContext; }>; } diff --git a/packages/agent-core-v2/src/agent/loop/loopService.ts b/packages/agent-core-v2/src/agent/loop/loopService.ts index ce5ab15c8..f43a34946 100644 --- a/packages/agent-core-v2/src/agent/loop/loopService.ts +++ b/packages/agent-core-v2/src/agent/loop/loopService.ts @@ -32,9 +32,9 @@ import { } from './errors'; import { IAgentLoopService, - type RunOptions, - type TurnAfterStepContext, - type TurnResult, + type LoopRunOptions, + type AfterStepContext, + type LoopRunResult, } from './loop'; declare module '#/app/event/eventBus' { @@ -74,7 +74,7 @@ export class AgentLoopService implements IAgentLoopService { @IConfigService private readonly config: IConfigService, ) { } - async run(options: RunOptions): Promise { + async run(options: LoopRunOptions): Promise { const { turnId } = options; const signal = options.signal ?? new AbortController().signal; @@ -233,12 +233,12 @@ export class AgentLoopService implements IAgentLoopService { markStepStarted(); this.emitStepCompleted(turnId, currentStep, stepUuid, usage, finishReason, response); - const afterStepContext: TurnAfterStepContext = { + const afterStepContext: AfterStepContext = { turnId, step: currentStep, signal, usage, - stopReason: finishReason, + finishReason, continue: false, }; try { diff --git a/packages/agent-core-v2/src/agent/turn/turn.ts b/packages/agent-core-v2/src/agent/turn/turn.ts index adad5298c..45f47ab06 100644 --- a/packages/agent-core-v2/src/agent/turn/turn.ts +++ b/packages/agent-core-v2/src/agent/turn/turn.ts @@ -1,7 +1,7 @@ import { createDecorator } from "#/_base/di/instantiation"; -import type { TurnResult } from '#/agent/loop'; +import type { LoopRunResult } from '#/agent/loop'; -export type { TurnResult } from '#/agent/loop'; +export type { LoopRunResult as TurnResult } from '#/agent/loop'; export interface Turn { readonly id: number; @@ -11,7 +11,7 @@ export interface Turn { * step completion; rejects if the turn ends earlier. */ readonly ready: Promise; - readonly result: Promise; + readonly result: Promise; } export interface IAgentTurnService { diff --git a/packages/agent-core-v2/test/externalHooks/integration.test.ts b/packages/agent-core-v2/test/externalHooks/integration.test.ts index 0899f88c5..68fe48d1d 100644 --- a/packages/agent-core-v2/test/externalHooks/integration.test.ts +++ b/packages/agent-core-v2/test/externalHooks/integration.test.ts @@ -38,7 +38,7 @@ import { import { HookDefSchema, HOOKS_SECTION, hooksFromToml, hooksToToml } from '#/agent/externalHooks/configSection'; import { makeHookRunner } from './runner-stub'; import { IAgentFullCompactionService } from '#/agent/fullCompaction'; -import { IAgentLoopService, type TurnAfterStepContext } from '#/agent/loop'; +import { IAgentLoopService, type AfterStepContext } from '#/agent/loop'; import { IAgentPermissionGate } from '#/agent/permissionGate'; import { IAgentPromptService } from '#/agent/prompt'; import { IAgentToolExecutorService } from '#/agent/toolExecutor'; @@ -78,13 +78,13 @@ function stdinScript(body: string): string { ].join('\n')); } -function makeAfterStep(signal: AbortSignal): TurnAfterStepContext { +function makeAfterStep(signal: AbortSignal): AfterStepContext { return { turnId: 0, step: 1, signal, usage: emptyUsage(), - stopReason: 'completed', + finishReason: 'completed', continue: false, }; } @@ -290,9 +290,9 @@ describe('IExternalHooksRunnerService integration', () => { const eventBus = ix.get(IEventBus); const signal = new AbortController().signal; - const filtered: TurnAfterStepContext = { + const filtered: AfterStepContext = { ...makeAfterStep(signal), - stopReason: 'filtered', + finishReason: 'filtered', }; await loop.hooks.afterStep.run(filtered); expect(filtered.continue).toBe(false); diff --git a/packages/agent-core-v2/test/goal/goal.test.ts b/packages/agent-core-v2/test/goal/goal.test.ts index cd20ae3fc..4ade3024d 100644 --- a/packages/agent-core-v2/test/goal/goal.test.ts +++ b/packages/agent-core-v2/test/goal/goal.test.ts @@ -3,7 +3,7 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { IAgentContextMemoryService } from '#/agent/contextMemory'; import { IAgentEventSinkService } from '#/agent/eventSink'; import { IAgentGoalService, type AgentGoalService } from '#/agent/goal'; -import { IAgentLoopService, type TurnAfterStepContext } from '#/agent/loop'; +import { IAgentLoopService, type AfterStepContext } from '#/agent/loop'; import { IAgentTurnService, type Turn, type TurnResult } from '#/agent/turn'; import type { PersistedWireRecord, WireRecord } from '#/agent/wireRecord'; import type { TokenUsage } from '#/app/llmProtocol/usage'; @@ -62,12 +62,12 @@ async function runGoalStep(loopService: IAgentLoopService, turn: Turn): Promise< step: 1, signal: turn.abortController.signal, }; - const afterStep: TurnAfterStepContext = { + const afterStep: AfterStepContext = { turnId: turn.id, step: 1, signal: turn.abortController.signal, usage: zeroUsage, - stopReason: 'completed' as const, + finishReason: 'completed' as const, continue: false, }; await loopService.hooks.beforeStep.run(step); @@ -81,12 +81,12 @@ async function runStepUsageHooks( turn: Turn, usage: TokenUsage, ): Promise { - const afterStep: TurnAfterStepContext = { + const afterStep: AfterStepContext = { turnId: turn.id, step: 1, signal: turn.abortController.signal, usage, - stopReason: 'completed' as const, + finishReason: 'completed' as const, continue: false, }; await loopService.hooks.afterStep.run(afterStep); @@ -665,12 +665,12 @@ describe('AgentGoalService core workflow hooks', () => { step: 1, signal: turn.abortController.signal, }; - const afterStep: TurnAfterStepContext = { + const afterStep: AfterStepContext = { turnId: turn.id, step: 1, signal: turn.abortController.signal, usage: zeroUsage, - stopReason: 'completed' as const, + finishReason: 'completed' as const, continue: false, }; await loopService.hooks.beforeStep.run(step); diff --git a/packages/agent-core-v2/test/toolDedupe/tool-dedupe.test.ts b/packages/agent-core-v2/test/toolDedupe/tool-dedupe.test.ts index 8b5d9a60e..44678951e 100644 --- a/packages/agent-core-v2/test/toolDedupe/tool-dedupe.test.ts +++ b/packages/agent-core-v2/test/toolDedupe/tool-dedupe.test.ts @@ -155,7 +155,7 @@ function afterStep( step, signal, usage: ZERO_USAGE, - stopReason: 'completed', + finishReason: 'completed', continue: false, }); }