refactor(agent-core-v2): rename loop context interfaces

This commit is contained in:
_Kerman 2026-07-07 18:59:38 +08:00
parent cf9bca54e4
commit 2a9e2194e4
9 changed files with 42 additions and 42 deletions

View file

@ -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<string | undefined> {
private async runStop(ctx: AfterStepContext): Promise<string | undefined> {
ctx.signal.throwIfAborted();
if (this.stopHookContinuationUsed) return undefined;

View file

@ -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<void>,
): Promise<void> {
if (!isContextOverflowError(context.error)) {

View file

@ -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<void> {
private async handleBeforeStep(ctx: BeforeStepContext): Promise<void> {
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) {

View file

@ -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<TurnResult>;
run(options: LoopRunOptions): Promise<LoopRunResult>;
readonly hooks: Hooks<{
beforeStep: TurnBeforeStepContext;
afterStep: TurnAfterStepContext;
onError: TurnErrorContext;
beforeStep: BeforeStepContext;
afterStep: AfterStepContext;
onError: LoopErrorContext;
}>;
}

View file

@ -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<TurnResult> {
async run(options: LoopRunOptions): Promise<LoopRunResult> {
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 {

View file

@ -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<void>;
readonly result: Promise<TurnResult>;
readonly result: Promise<LoopRunResult>;
}
export interface IAgentTurnService {

View file

@ -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);

View file

@ -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<boolean> {
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);

View file

@ -155,7 +155,7 @@ function afterStep(
step,
signal,
usage: ZERO_USAGE,
stopReason: 'completed',
finishReason: 'completed',
continue: false,
});
}