mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-07-09 17:29:12 +00:00
fix: appendSystemReminder
This commit is contained in:
parent
bec0b085f2
commit
0d0bb736a8
3 changed files with 59 additions and 42 deletions
|
|
@ -16,7 +16,7 @@ import { createDecorator } from "#/_base/di";
|
|||
import type { ContextMessage, PromptOrigin } from '#/agent/contextMemory';
|
||||
|
||||
export type ContextAppendArgs = readonly ContextMessage[];
|
||||
export type ContextAppendSystemReminderArgs = [message: ContextMessage];
|
||||
export type ContextAppendSystemReminderArgs = [message: string, origin: PromptOrigin];
|
||||
export type ContextReplaceArgs = [index: number, message: ContextMessage];
|
||||
|
||||
/**
|
||||
|
|
@ -41,7 +41,7 @@ export interface IAgentContextOpsService {
|
|||
|
||||
/**
|
||||
* Append a `<system-reminder>` message to the end of the history.
|
||||
* Returns the raw message recorded by the wire operation.
|
||||
* Returns the message inserted into history.
|
||||
*/
|
||||
appendSystemReminder(content: string, origin: PromptOrigin): ContextMessage;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
* (Infinity start) and mirror each message into the replay read model;
|
||||
* `remove` splices out each resolved target and drops the matching replay
|
||||
* messages; `clear` drops the whole history and cuts a new replay segment;
|
||||
* legacy `replace` swaps one message in place for old migrated wire. Message
|
||||
* content is offloaded to the blob store through each operation's blob
|
||||
* selector. Bound at Agent scope.
|
||||
* legacy `replace` swaps one message in place for old migrated wire. Structured
|
||||
* message content is offloaded to the blob store through the operations that
|
||||
* carry full messages. Bound at Agent scope.
|
||||
*/
|
||||
|
||||
import { Disposable } from "#/_base/di";
|
||||
|
|
@ -63,17 +63,6 @@ function messageContentBlobTarget<T extends readonly unknown[]>(
|
|||
};
|
||||
}
|
||||
|
||||
function toSystemReminderMessage(message: ContextMessage): ContextMessage {
|
||||
return {
|
||||
...message,
|
||||
content: message.content.map((part) =>
|
||||
part.type === 'text'
|
||||
? { ...part, text: toSystemReminderText(part.text) }
|
||||
: part,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
function toSystemReminderText(content: string): string {
|
||||
const trimmed = content.trim();
|
||||
if (trimmed.startsWith('<system-reminder>') && trimmed.endsWith('</system-reminder>')) {
|
||||
|
|
@ -82,6 +71,20 @@ function toSystemReminderText(content: string): string {
|
|||
return `<system-reminder>\n${trimmed}\n</system-reminder>`;
|
||||
}
|
||||
|
||||
function toSystemReminderMessage(content: string, origin: PromptOrigin): ContextMessage {
|
||||
return ensureMessageId({
|
||||
role: 'user',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: toSystemReminderText(content),
|
||||
},
|
||||
],
|
||||
toolCalls: [],
|
||||
origin,
|
||||
});
|
||||
}
|
||||
|
||||
export class AgentContextOpsService extends Disposable implements IAgentContextOpsService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
|
|
@ -121,19 +124,15 @@ export class AgentContextOpsService extends Disposable implements IAgentContextO
|
|||
this.appendSystemReminderOperation =
|
||||
context.defineOperation<ContextAppendSystemReminderArgs>({
|
||||
type: 'append_system_reminder',
|
||||
apply: (splice, message) => {
|
||||
splice(Number.POSITIVE_INFINITY, 0, [toSystemReminderMessage(message)]);
|
||||
apply: (splice, message, origin) => {
|
||||
splice(Number.POSITIVE_INFINITY, 0, [toSystemReminderMessage(message, origin)]);
|
||||
},
|
||||
replay: (replay, message) => {
|
||||
replay.push({ type: 'message', message: toSystemReminderMessage(message) });
|
||||
replay: (replay, message, origin) => {
|
||||
replay.push({
|
||||
type: 'message',
|
||||
message: toSystemReminderMessage(message, origin),
|
||||
});
|
||||
},
|
||||
blobs: ([message]) => [
|
||||
messageContentBlobTarget<ContextAppendSystemReminderArgs>(
|
||||
message,
|
||||
(_current, next) => [next],
|
||||
([current]) => current,
|
||||
),
|
||||
],
|
||||
});
|
||||
|
||||
this.removeOperation = context.defineOperation<ContextRemoveArgs>({
|
||||
|
|
@ -187,19 +186,8 @@ export class AgentContextOpsService extends Disposable implements IAgentContextO
|
|||
}
|
||||
|
||||
appendSystemReminder(content: string, origin: PromptOrigin): ContextMessage {
|
||||
const message = ensureMessageId({
|
||||
role: 'user',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: content.trim(),
|
||||
},
|
||||
],
|
||||
toolCalls: [],
|
||||
origin,
|
||||
});
|
||||
this.appendSystemReminderOperation(message);
|
||||
return message;
|
||||
this.appendSystemReminderOperation(content.trim(), origin);
|
||||
return this.context.get().at(-1)!;
|
||||
}
|
||||
|
||||
remove(removals: readonly ContextRemovalTarget[]): void {
|
||||
|
|
|
|||
|
|
@ -310,6 +310,10 @@ describe('AgentWireRecordService persistence', () => {
|
|||
expect(context.get()[0]?.content).toEqual([
|
||||
{ type: 'text', text: '<system-reminder>\nRemember this.\n</system-reminder>' },
|
||||
]);
|
||||
expect(context.get()[0]?.origin).toEqual({
|
||||
kind: 'injection',
|
||||
variant: 'host',
|
||||
});
|
||||
|
||||
const records = await readPersistedWireRecords(storage);
|
||||
expect(records.map((record) => record.type)).toEqual([
|
||||
|
|
@ -318,9 +322,34 @@ describe('AgentWireRecordService persistence', () => {
|
|||
]);
|
||||
const record = records[1] as {
|
||||
type: 'context.append_system_reminder';
|
||||
args: readonly [ContextMessage];
|
||||
args: readonly [string, ContextMessage['origin']];
|
||||
};
|
||||
expect(record.args[0].content).toEqual([{ type: 'text', text: 'Remember this.' }]);
|
||||
expect(record.args).toEqual(['Remember this.', { kind: 'injection', variant: 'host' }]);
|
||||
});
|
||||
|
||||
it('restores string system reminder args with origin as wrapped context messages', async () => {
|
||||
const { wire, context } = await createWireHarness();
|
||||
|
||||
await wire.restore([
|
||||
{
|
||||
type: 'metadata',
|
||||
protocol_version: AGENT_WIRE_PROTOCOL_VERSION,
|
||||
created_at: 1,
|
||||
},
|
||||
{
|
||||
type: 'context.append_system_reminder',
|
||||
args: ['Remember this.', { kind: 'injection', variant: 'host' }],
|
||||
},
|
||||
]);
|
||||
|
||||
const message = context.get()[0];
|
||||
expect(message?.content).toEqual([
|
||||
{ type: 'text', text: '<system-reminder>\nRemember this.\n</system-reminder>' },
|
||||
]);
|
||||
expect(message?.origin).toEqual({
|
||||
kind: 'injection',
|
||||
variant: 'host',
|
||||
});
|
||||
});
|
||||
|
||||
it('offloads large content part data URIs to blobsDir during append', async () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue