diff --git a/packages/agent-core-v2/src/contextMemory/contextMemoryService.ts b/packages/agent-core-v2/src/contextMemory/contextMemoryService.ts index fbf5f9006..ae942a36d 100644 --- a/packages/agent-core-v2/src/contextMemory/contextMemoryService.ts +++ b/packages/agent-core-v2/src/contextMemory/contextMemoryService.ts @@ -81,6 +81,7 @@ export class ContextMemoryService extends Disposable implements IContextMemory { private applySplice(record: WireRecord<'context.splice'>): void { const messages = [...record.messages]; + this.history.splice(record.start, record.deleteCount, ...messages); for (const message of messages) { this.replayBuilder.push({ type: 'message', message }); } diff --git a/packages/agent-core-v2/src/llmRequester/llmRequesterService.ts b/packages/agent-core-v2/src/llmRequester/llmRequesterService.ts index f77555ffc..3f1bce0d3 100644 --- a/packages/agent-core-v2/src/llmRequester/llmRequesterService.ts +++ b/packages/agent-core-v2/src/llmRequester/llmRequesterService.ts @@ -144,7 +144,9 @@ export class LLMRequesterService implements ILLMRequester { usage, model: usageModel, }); - this.usage.record(usageModel, usage, request.usageContext); + if (request.usageContext === undefined) { + this.usage.record(usageModel, usage); + } queue.push({ type: 'finish', providerFinishReason: result.finishReason ?? undefined, diff --git a/packages/agent-core-v2/src/loop/turn-step.ts b/packages/agent-core-v2/src/loop/turn-step.ts index ab6b621a3..8571860ac 100644 --- a/packages/agent-core-v2/src/loop/turn-step.ts +++ b/packages/agent-core-v2/src/loop/turn-step.ts @@ -131,13 +131,14 @@ export async function executeLoopStep(deps: ExecuteLoopStepDeps): Promise<{ let effectiveStopReason: LoopStepStopReason = stopTurnAfterUsage && stopReason === 'tool_use' ? 'end_turn' : stopReason; if (effectiveStopReason === 'tool_use') { - const toolResults = await toolExecutor.execute(response.toolCalls, { - signal, - turnId, - stepNumber: currentStep, - dispatchEvent, - onProgress: (toolCallId, update) => { - void dispatchEvent({ type: 'tool.progress', toolCallId, update }); + const toolResults = await toolExecutor.execute(response.toolCalls, { + signal, + turnId, + stepNumber: currentStep, + stepUuid, + dispatchEvent, + onProgress: (toolCallId, update) => { + void dispatchEvent({ type: 'tool.progress', toolCallId, update }); }, }); if (toolResults.some((r) => r.stopTurn === true)) { diff --git a/packages/agent-core-v2/src/toolExecutor/toolExecutor.ts b/packages/agent-core-v2/src/toolExecutor/toolExecutor.ts index f6e57647b..f6beaba38 100644 --- a/packages/agent-core-v2/src/toolExecutor/toolExecutor.ts +++ b/packages/agent-core-v2/src/toolExecutor/toolExecutor.ts @@ -9,6 +9,7 @@ export interface ToolExecutorExecuteOptions { readonly signal?: AbortSignal; readonly turnId?: string; readonly stepNumber?: number; + readonly stepUuid?: string; readonly dispatchEvent?: LoopEventDispatcher | undefined; readonly onProgress?: ((toolCallId: string, update: ToolUpdate) => void) | undefined; } diff --git a/packages/agent-core-v2/src/toolExecutor/toolExecutorService.ts b/packages/agent-core-v2/src/toolExecutor/toolExecutorService.ts index 3f6f03c7d..6d83b28ec 100644 --- a/packages/agent-core-v2/src/toolExecutor/toolExecutorService.ts +++ b/packages/agent-core-v2/src/toolExecutor/toolExecutorService.ts @@ -476,7 +476,7 @@ async function dispatchToolCall( uuid: call.toolCall.id, turnId: options.turnId ?? '', step: options.stepNumber ?? 0, - stepUuid: '', + stepUuid: options.stepUuid ?? '', toolCallId: call.toolCall.id, name: call.toolName, args, diff --git a/packages/agent-core-v2/test/contextMemory/context.test.ts b/packages/agent-core-v2/test/contextMemory/context.test.ts index a9179084c..9fd7e6365 100644 --- a/packages/agent-core-v2/test/contextMemory/context.test.ts +++ b/packages/agent-core-v2/test/contextMemory/context.test.ts @@ -1,13 +1,12 @@ import type { Message } from '@moonshot-ai/kosong'; import { describe, expect, it } from 'vitest'; -import { estimateTokensForMessages } from '../../../src/utils/tokens'; -import { testAgent } from './harness'; -import { - project, - renderNotificationXml, - type ContextMessage, -} from '../../../src/services/agent'; +import { estimateTokensForMessages } from '#/_base/utils/tokens'; +import { project } from '#/contextProjector'; +import type { ContextMessage } from '#/contextMemory'; +import { renderNotificationXml } from '#/contextMemory/notification-xml'; + +import { testAgent } from '../harness'; describe('Agent context', () => { it('stores prompt origins without leaking them to LLM projection', () => { diff --git a/packages/agent-core-v2/test/loop/basic.test.ts b/packages/agent-core-v2/test/loop/basic.test.ts index 5607296c8..b848b90aa 100644 --- a/packages/agent-core-v2/test/loop/basic.test.ts +++ b/packages/agent-core-v2/test/loop/basic.test.ts @@ -1,14 +1,14 @@ import type { ToolCall } from '@moonshot-ai/kosong'; import { expect, it } from 'vitest'; -import { FLAG_DEFINITIONS, FlagResolver } from '../../../src/flags'; -import { testAgent } from './harness'; +import { IFlagService } from '#/flag'; + +import { testAgent } from '../harness'; it('creates an independent agent with a scoped experimental flag resolver', () => { - const flags = new FlagResolver({}, FLAG_DEFINITIONS); const ctx = testAgent({ - experimentalFlags: flags, }); + const flags = ctx.get(IFlagService); expect(flags.enabled('micro_compaction')).toBe(true); }); diff --git a/packages/agent-core-v2/test/usage/usage.test.ts b/packages/agent-core-v2/test/usage/usage.test.ts index 75d03b276..fda33e7c0 100644 --- a/packages/agent-core-v2/test/usage/usage.test.ts +++ b/packages/agent-core-v2/test/usage/usage.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; -import { testAgent } from './harness'; +import { testAgent } from '../harness'; describe('Agent usage', () => { it('accumulates usage by model', () => {