This commit is contained in:
_Kerman 2026-06-29 15:39:39 +08:00
parent 206950ab95
commit 13838fa144
8 changed files with 25 additions and 21 deletions

View file

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

View file

@ -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,

View file

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

View file

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

View file

@ -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,

View file

@ -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', () => {

View file

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

View file

@ -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', () => {