-
Notifications
You must be signed in to change notification settings - Fork 1.3k
fix(agent-runtime): stop run after local prompt config errors #1199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| import { TEST_USER_ID } from '@codebuff/common/old-constants' | ||
| import { createTestAgentRuntimeParams } from '@codebuff/common/testing/fixtures/agent-runtime' | ||
| import { getInitialSessionState } from '@codebuff/common/types/session-state' | ||
| import { afterEach, describe, expect, it, mock, spyOn } from 'bun:test' | ||
|
|
||
| import { callMainPrompt } from '../main-prompt' | ||
| import * as agentRegistry from '../templates/agent-registry' | ||
|
|
||
| import type { ProjectFileContext } from '@codebuff/common/util/file' | ||
|
|
||
| describe('callMainPrompt', () => { | ||
| afterEach(() => { | ||
| mock.restore() | ||
| }) | ||
|
|
||
| const mockFileContext: ProjectFileContext = { | ||
| projectRoot: '/test', | ||
| cwd: '/test', | ||
| fileTree: [], | ||
| fileTokenScores: {}, | ||
| knowledgeFiles: {}, | ||
| gitChanges: { | ||
| status: '', | ||
| diff: '', | ||
| diffCached: '', | ||
| lastCommitMessages: '', | ||
| }, | ||
| changesSinceLastChat: {}, | ||
| shellConfigFiles: {}, | ||
| agentTemplates: {}, | ||
| customToolDefinitions: {}, | ||
| systemInfo: { | ||
| platform: 'test', | ||
| shell: 'test', | ||
| nodeVersion: 'test', | ||
| arch: 'test', | ||
| homedir: '/home/test', | ||
| cpus: 1, | ||
| chromeAvailable: false, | ||
| }, | ||
| } | ||
|
|
||
| it('returns early without calling mainPrompt when agent config validation fails', async () => { | ||
| const sentActions: Array<{ type: string }> = [] | ||
| const sendAction = ({ action }: { action: { type: string } }) => { | ||
| sentActions.push(action) | ||
| } | ||
|
|
||
|
Comment on lines
+43
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This test replaces AGENTS.md reference: AGENTS.md:L28-L28 Useful? React with 👍 / 👎. |
||
| spyOn(agentRegistry, 'assembleLocalAgentTemplates').mockReturnValue({ | ||
| agentTemplates: {}, | ||
| validationErrors: [ | ||
| { message: 'bad agent config', agentId: 'test-agent' }, | ||
| ] as any, | ||
| }) | ||
|
|
||
| const sessionState = getInitialSessionState(mockFileContext) | ||
| const baseParams = createTestAgentRuntimeParams() | ||
|
|
||
| const result = await callMainPrompt({ | ||
| ...baseParams, | ||
| promptId: 'test-prompt', | ||
| sendAction, | ||
| logger: baseParams.logger, | ||
| signal: new AbortController().signal, | ||
| action: { | ||
| type: 'prompt' as const, | ||
| prompt: 'Hello', | ||
| sessionState, | ||
| fingerprintId: 'test', | ||
| costMode: 'normal' as const, | ||
| promptId: 'test-prompt', | ||
| toolResults: [], | ||
| }, | ||
| repoUrl: undefined, | ||
| repoId: undefined, | ||
| clientSessionId: 'test-session', | ||
| userId: TEST_USER_ID, | ||
| } as any) | ||
|
|
||
| const actionTypes = sentActions.map((a) => a.type) | ||
| expect(actionTypes).toContain('prompt-error') | ||
| expect(actionTypes).toContain('prompt-response') | ||
| expect(actionTypes).not.toContain('response-chunk') | ||
| expect(result.output.type).toBe('error') | ||
| }) | ||
| }) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -171,13 +171,32 @@ export async function callMainPrompt( | |
| assembleLocalAgentTemplates({ fileContext, logger }) | ||
|
|
||
| if (validationErrors.length > 0) { | ||
| const errorMessage = `Invalid agent config: ${validationErrors.map((err) => err.message).join('\n')}` | ||
| sendAction({ | ||
| action: { | ||
| type: 'prompt-error', | ||
| message: `Invalid agent config: ${validationErrors.map((err) => err.message).join('\n')}`, | ||
| message: errorMessage, | ||
| userInputId: promptId, | ||
| }, | ||
| }) | ||
|
|
||
| const errorResult = { | ||
| sessionState: action.sessionState, | ||
| output: { type: 'error' as const, message: errorMessage }, | ||
|
Comment on lines
+183
to
+185
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When validation fails before Useful? React with 👍 / 👎.
Comment on lines
+183
to
+185
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When validation fails before Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| sendAction({ | ||
| action: { | ||
| type: 'prompt-response', | ||
|
Comment on lines
+188
to
+190
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When local validation fails in Useful? React with 👍 / 👎.
Comment on lines
+188
to
+190
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When local validation fails in Useful? React with 👍 / 👎. |
||
| promptId, | ||
| sessionState: errorResult.sessionState, | ||
| toolCalls: [], | ||
| toolResults: [], | ||
| output: errorResult.output, | ||
| }, | ||
| }) | ||
|
|
||
| return errorResult | ||
| } | ||
|
|
||
| sendAction({ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test replaces
assembleLocalAgentTemplatesthrough an ES-module spy even though the validation path can be exercised directly by placing an invalid template inmockFileContext.agentTemplates. That unnecessarily couples the regression test to module-binding behavior and conflicts with the repository convention to prefer dependency injection over module mocking; use a real invalid fixture here, or inject the assembler if isolation is required.AGENTS.md reference: AGENTS.md:L28-L28
Useful? React with 👍 / 👎.