fix(agent): preserve sent message identity

This commit is contained in:
_Kerman
2026-07-28 18:07:28 +08:00
parent 46665f8af7
commit 7127528b7f
3 changed files with 4 additions and 4 deletions

View File

@@ -101,10 +101,9 @@ export class ReactLoopAgent implements Agent {
/** Accept and route one unified send item. */ /** Accept and route one unified send item. */
send( send(
input: UserMessage, message: UserMessage,
options: SendOptions, options: SendOptions,
): void { ): void {
const message = freezeMessage(input)
const { target, wakeup } = options const { target, wakeup } = options
if (target === 'next-step' && !wakeup) { if (target === 'next-step' && !wakeup) {
if (this.acceptsNextStep) { if (this.acceptsNextStep) {

View File

@@ -79,7 +79,7 @@ describe('agent/prompt-submit', () => {
expect(userMsg?.type === 'user/message' && userMsg.data.content).toEqual([{ type: 'text', text: 'hello' }]) expect(userMsg?.type === 'user/message' && userMsg.data.content).toEqual([{ type: 'text', text: 'hello' }])
}) })
it('snapshots and freezes input before publishing or awaiting admission', async () => { it('publishes frozen input without replacing its identity', async () => {
const adapter = new MockAdapter([textResponse('ok')]) const adapter = new MockAdapter([textResponse('ok')])
const ctx = await harness(adapter) const ctx = await harness(adapter)
const agent = ctx.agentLoop.create(SessionId('owned-input'), { provider: 'mock', model: 'mock' }) const agent = ctx.agentLoop.create(SessionId('owned-input'), { provider: 'mock', model: 'mock' })
@@ -123,6 +123,7 @@ describe('agent/prompt-submit', () => {
await idle await idle
expect(observed).toHaveLength(1) expect(observed).toHaveLength(1)
expect(observed[0]).toBe(input)
expect(observed[0]).toMatchObject({ expect(observed[0]).toMatchObject({
content: [{ type: 'text', text: 'accepted text' }], content: [{ type: 'text', text: 'accepted text' }],
source: { kind: 'plugin', plugin: 'accepted source' }, source: { kind: 'plugin', plugin: 'accepted source' },

View File

@@ -148,7 +148,7 @@ export interface Agent {
* immediately without opening a turn. If admission closes without a turn, * immediately without opening a turn. If admission closes without a turn,
* a context-only boundary appends immediately; context staged beside * a context-only boundary appends immediately; context staged beside
* steering remains pending with it. * steering remains pending with it.
* The agent snapshots and freezes the identified message before publishing or queueing it. * The agent publishes or queues the identified frozen message as-is.
* @param message - identified model-facing content and its producer provenance. * @param message - identified model-facing content and its producer provenance.
* @param options - target queue and wakeup decision. * @param options - target queue and wakeup decision.
*/ */