✨ feat(vscode): 问 AI 和重写注释各用各的 profile,设置里加重写注释默认模型

This commit is contained in:
cruldra committed 2026-10-12 16:30:41 +11:00
1 parent 925f1ed39a
commit b83c445dd0
25 files changed
+363 -111

No files matched your search

+79 -7
View File
@@ -91,10 +91,10 @@ describe('问这个文件实际使用设置的默认模型', () => {
await saveSettings(ctx, { defaultAskProfilePath: '/p/sonnet.json' })
vi.mocked(listClaudeProfiles).mockResolvedValue(AVAILABLE.filter(item => item.name !== 'offical'))
const { qa, runner } = service(ctx)
await qa.profiles.select('')
await qa.profiles.ask.select('')
vi.mocked(listClaudeProfiles).mockResolvedValue(AVAILABLE)
const shown = vi.fn()
qa.profiles.subscribe(shown)
qa.profiles.ask.subscribe(shown)
await saveSettings(ctx, { webhookPort: 9000 })
await vi.waitFor(() => expect(shown).toHaveBeenLastCalledWith(expect.objectContaining({ selected: '' })))
await qa.askPath(uri, 'file', { askId: '1', question: '这是什么', images: [] })
@@ -114,7 +114,7 @@ describe('问这个文件实际使用设置的默认模型', () => {
await qa.askPath(uri, 'file', { askId: '1', question: '这是什么', images: [] })
expect(runner.mock.calls[0]?.[0].profilePath).toBe('/p/dsflash.json')
qa.stop('1')
await qa.profiles.select('sonnet')
await qa.profiles.ask.select('sonnet')
await qa.askPath(uri, 'file', { askId: '2', question: '这是什么', images: [] })
expect(runner.mock.calls[1]?.[0].profilePath).toBe('/p/sonnet.json')
expect(getSettings(ctx).defaultAskProfilePath).toBe('/p/dsflash.json')
@@ -126,9 +126,9 @@ describe('问这个文件实际使用设置的默认模型', () => {
it('保存新默认后所有现有预览收到新选择,下一个问题和界面使用同一个模型', async () => {
const ctx = context()
const { qa, runner } = service(ctx)
await qa.profiles.select('sonnet')
await qa.profiles.ask.select('sonnet')
const shown = vi.fn()
qa.profiles.subscribe(shown)
qa.profiles.ask.subscribe(shown)
await saveSettings(ctx, { defaultAskProfilePath: '/p/dsflash.json' })
await vi.waitFor(() => expect(shown).toHaveBeenLastCalledWith(expect.objectContaining({ selected: 'dsflash' })))
await qa.askPath(uri, 'file', { askId: '1', question: '这是什么', images: [] })
@@ -139,12 +139,84 @@ describe('问这个文件实际使用设置的默认模型', () => {
const ctx = context()
await saveSettings(ctx, { defaultAskProfilePath: '/p/deleted.json' })
const { qa, runner } = service(ctx)
expect(await qa.askPath(uri, 'file', { askId: '1', question: '这是什么', images: [] })).toContain('文件问答模型不可用')
expect(await qa.ask(uri, { askId: '2', anchor: 'a', question: '问题', prompt: '问题', followUp: '继续', images: [] })).toContain('文件问答模型不可用')
expect(await qa.askPath(uri, 'file', { askId: '1', question: '这是什么', images: [] })).toMatch(/^问答模型不可用:\/p\/deleted\.json。/)
expect(await qa.ask(uri, { askId: '2', anchor: 'a', question: '问题', prompt: '问题', followUp: '继续', images: [] })).toMatch(/^问答模型不可用:\/p\/deleted\.json。/)
expect(runner).not.toHaveBeenCalled()
})
})
describe('问 AI 和重写注释各用各的 profile', () => {
const SKILL = '/ecc:writing-code-comments a.ts:1-3'
const asking = (askId: string) => ({ askId, anchor: 'function f', question: '为什么', prompt: '完整的', followUp: '短的', images: [] })
const rewriting = (askId: string): RewriteRequest => ({ askId, anchor: 'function f', question: SKILL, prompt: SKILL, images: [], writeBack: async () => undefined })
it('各按设置里自己的默认模型起步:块下面问、顶部问、了解一块代码用问答的,重写注释用重写的', async () => {
const ctx = context()
await saveSettings(ctx, { defaultAskProfilePath: '/p/sonnet.json', defaultRewriteProfilePath: '/p/dsflash.json' })
const { qa, runner, rewriter } = service(ctx)
rewriter.mockResolvedValue({ body: '新的。', sessionId: 'r1' })
await qa.ask(uri, asking('1'))
await qa.askPath(uri, 'file', { askId: '2', question: '这是什么', images: [] })
qa.stop('2')
await qa.askTop(uri, { askId: '3', question: '用户登录', images: [] }, { prompt: '找', followUp: '接着找' }, async answer => ({ text: answer.text }))
await qa.rewrite(uri, rewriting('4'))
expect(runner.mock.calls.map(([run]) => run.profilePath)).toEqual(['/p/sonnet.json', '/p/sonnet.json', '/p/sonnet.json'])
expect(rewriter.mock.calls[0]?.[0].profilePath).toBe('/p/dsflash.json')
})
it('都没配时两套都用默认的那个', async () => {
const { qa, runner, rewriter } = service(context())
rewriter.mockResolvedValue({ body: '新的。', sessionId: 'r1' })
await qa.ask(uri, asking('1'))
await qa.rewrite(uri, rewriting('2'))
expect(runner.mock.calls[0]?.[0].profilePath).toBe('/p/offical.json')
expect(rewriter.mock.calls[0]?.[0].profilePath).toBe('/p/offical.json')
})
it('临时切换只改自己那一套、只通知自己那一套的下拉,不写进设置', async () => {
const ctx = context()
const { qa, runner, rewriter } = service(ctx)
rewriter.mockResolvedValue({ body: '新的。', sessionId: 'r1' })
const askShown = vi.fn()
const rewriteShown = vi.fn()
qa.profiles.ask.subscribe(askShown)
qa.profiles.rewrite.subscribe(rewriteShown)
await qa.profiles.rewrite.select('dsflash')
expect(rewriteShown).toHaveBeenLastCalledWith(expect.objectContaining({ selected: 'dsflash' }))
expect(askShown).not.toHaveBeenCalled()
await qa.profiles.ask.select('sonnet')
expect(askShown).toHaveBeenLastCalledWith(expect.objectContaining({ selected: 'sonnet' }))
expect(rewriteShown).toHaveBeenCalledTimes(1)
await qa.ask(uri, asking('1'))
await qa.rewrite(uri, rewriting('2'))
expect(runner.mock.calls[0]?.[0].profilePath).toBe('/p/sonnet.json')
expect(rewriter.mock.calls[0]?.[0].profilePath).toBe('/p/dsflash.json')
expect(getSettings(ctx)).toMatchObject({ defaultAskProfilePath: '', defaultRewriteProfilePath: '' })
})
it('改了重写注释的默认模型只清掉重写那一套的临时选择,问答那一套的留着', async () => {
const ctx = context()
const { qa } = service(ctx)
await qa.profiles.ask.select('sonnet')
await qa.profiles.rewrite.select('sonnet')
const rewriteShown = vi.fn()
qa.profiles.rewrite.subscribe(rewriteShown)
await saveSettings(ctx, { defaultRewriteProfilePath: '/p/dsflash.json' })
await vi.waitFor(() => expect(rewriteShown).toHaveBeenLastCalledWith(expect.objectContaining({ selected: 'dsflash' })))
expect((await qa.profiles.ask.choice()).selected).toBe('sonnet')
})
it('重写注释用的模型删掉了:报重写注释的错、不启动模型;问答照常', async () => {
const ctx = context()
await saveSettings(ctx, { defaultRewriteProfilePath: '/p/deleted.json' })
const { qa, runner, rewriter } = service(ctx)
expect(await qa.rewrite(uri, rewriting('1'))).toMatch(/^重写注释模型不可用:\/p\/deleted\.json。/)
expect(rewriter).not.toHaveBeenCalled()
expect(await qa.ask(uri, asking('2'))).toBeUndefined()
expect(runner).toHaveBeenCalledTimes(1)
})
})
describe('重写注释的记录', () => {
const SKILL = '/ecc:writing-code-comments a.ts:1-3'