wip: context-meter + model-label UI and provider/inference tweaks

Checkpoint of in-flight work so the orchestrator branch can rebase onto a
clean main: ContextBar → ContextMeter, model-label helper, model/agent picker
+ provider-snapshot/registry changes, inference payload + message-columns.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-03 14:55:38 +00:00
parent 5f4c7a9050
commit 163b5b86f7
21 changed files with 471 additions and 233 deletions

View File

@@ -111,6 +111,42 @@ describe('buildMessagesPayload', async () => {
expect(result[4]).toMatchObject({ role: 'assistant', content: 'great' });
});
it('does NOT annotate models when the chat uses a single model', async () => {
const session = makeSession();
const project = makeProject();
const history: Message[] = [
makeMessage('user', 'hi'),
makeMessage('assistant', 'hello', { model: 'qwen3.6-35b-a3b-mxfp4' }),
makeMessage('user', 'again'),
makeMessage('assistant', 'world', { model: 'qwen3.6-35b-a3b-mxfp4' }),
];
const result = await buildMessagesPayload(session, project, history);
// 1 system + 4 history — no extra attribution system note.
expect(result).toHaveLength(5);
expect(result.filter((m) => m.role === 'system')).toHaveLength(1);
expect(result[2]).toMatchObject({ role: 'assistant', content: 'hello' });
expect(result[4]).toMatchObject({ role: 'assistant', content: 'world' });
});
it('annotates each assistant turn with its model when the chat mixes models', async () => {
const session = makeSession();
const project = makeProject();
const history: Message[] = [
makeMessage('user', 'hi'),
makeMessage('assistant', 'opus reply', { model: 'claude-opus-4-8' }),
makeMessage('user', 'switch'),
makeMessage('assistant', 'qwen reply', { model: 'qwen3.6-35b-a3b-mxfp4' }),
];
const result = await buildMessagesPayload(session, project, history);
// 1 system prompt + 1 attribution note + 4 history rows.
const systems = result.filter((m) => m.role === 'system');
expect(systems).toHaveLength(2);
expect(systems[1]!.content).toContain('square brackets');
const assistants = result.filter((m) => m.role === 'assistant');
expect(assistants[0]!.content).toBe('[claude-opus-4-8] opus reply');
expect(assistants[1]!.content).toBe('[qwen3.6-35b-a3b-mxfp4] qwen reply');
});
it('starts from the latest compact marker, emitting it as a system message', async () => {
const session = makeSession();
const project = makeProject();