agentHost: propagate steering for cli sessions (#306488)

* agentHost: propagate steering for cli sessions

Closes #305323

* comments
This commit is contained in:
Connor Peet
2026-03-30 15:38:09 -07:00
committed by GitHub
parent 7836a50b57
commit eca37987be
6 changed files with 85 additions and 19 deletions

View File

@@ -390,8 +390,9 @@ suite('AgentSideEffects', () => {
assert.strictEqual(state?.queuedMessages?.[0].id, 'q-wait');
});
test('dispatches SessionPendingMessageRemoved for steering messages', () => {
test('dispatches SessionPendingMessageRemoved for steering messages on steering_consumed', () => {
setupSession();
disposables.add(sideEffects.registerProgressListener(agent));
const envelopes: IActionEnvelope[] = [];
disposables.add(stateManager.onDidEmitEnvelope(e => envelopes.push(e)));
@@ -406,7 +407,21 @@ suite('AgentSideEffects', () => {
stateManager.dispatchClientAction(action, { clientId: 'test', clientSeq: 1 });
sideEffects.handleAction(action);
const removal = envelopes.find(e =>
// Removal is not dispatched synchronously; it waits for the agent
let removal = envelopes.find(e =>
e.action.type === ActionType.SessionPendingMessageRemoved &&
(e.action as { kind: PendingMessageKind }).kind === PendingMessageKind.Steering
);
assert.strictEqual(removal, undefined, 'should not dispatch removal until steering_consumed');
// Simulate the agent consuming the steering message
agent.fireProgress({
session: sessionUri,
type: 'steering_consumed',
id: 'steer-rm',
});
removal = envelopes.find(e =>
e.action.type === ActionType.SessionPendingMessageRemoved &&
(e.action as { kind: PendingMessageKind }).kind === PendingMessageKind.Steering
);

View File

@@ -207,6 +207,32 @@ suite('CopilotAgentSession', () => {
});
});
// ---- sendSteering ----
suite('sendSteering', () => {
test('fires steering_consumed after send resolves', async () => {
const { session, progressEvents } = await createAgentSession(disposables);
await session.sendSteering({ id: 'steer-1', userMessage: { text: 'focus on tests' } });
const consumed = progressEvents.find(e => e.type === 'steering_consumed');
assert.ok(consumed, 'should fire steering_consumed event');
assert.strictEqual((consumed as { id: string }).id, 'steer-1');
});
test('does not fire steering_consumed when send fails', async () => {
const { session, mockSession, progressEvents } = await createAgentSession(disposables);
mockSession.send = async () => { throw new Error('send failed'); };
await session.sendSteering({ id: 'steer-fail', userMessage: { text: 'will fail' } });
const consumed = progressEvents.find(e => e.type === 'steering_consumed');
assert.strictEqual(consumed, undefined, 'should not fire steering_consumed on failure');
});
});
// ---- event mapping ----
suite('event mapping', () => {