mirror of
https://github.com/langgenius/dify.git
synced 2026-07-21 02:28:30 +08:00
test(e2e): stabilize agent build draft note scenario (#38571)
This commit is contained in:
parent
23b936aeb5
commit
9416d04163
@ -10,18 +10,20 @@ Feature: Agent v2 build draft
|
||||
Then Agent v2 Build chat should be blocked until a model is configured
|
||||
And the Agent v2 Build draft should not be checked out
|
||||
|
||||
@external-model @agent-backend-runtime @stable-model
|
||||
Scenario: Generating a Build draft leaves the normal Agent configuration unchanged
|
||||
@external-model @agent-backend-runtime @agent-decision-model
|
||||
Scenario: Generating a Build note draft leaves the normal Agent configuration unchanged
|
||||
Given I am signed in as the default E2E admin
|
||||
And the Agent Builder stable chat model is available
|
||||
And the Agent Builder agent-decision chat model is available
|
||||
And the Agent v2 runtime backend is available
|
||||
And a runnable Agent v2 test agent has been created via API
|
||||
And a runnable Agent v2 test agent using the agent-decision model has been created via API
|
||||
When I open the Agent v2 configure page
|
||||
And I generate an Agent v2 Build draft from the fixed instruction
|
||||
Then I should see the Agent v2 Build draft pending changes
|
||||
And I should see the Agent v2 Build mode confirmation state
|
||||
And the Agent v2 Build draft should include the generated build note
|
||||
And I should see the generated Agent v2 build note in Configure
|
||||
And the normal Agent v2 draft should still use the normal E2E prompt
|
||||
And the normal Agent v2 draft should not include the e2e-summary-skill Skill
|
||||
And the normal Agent v2 draft should not include the generated build note
|
||||
|
||||
@core
|
||||
Scenario: Discarding a Build draft keeps the original Agent configuration
|
||||
|
||||
@ -54,6 +54,18 @@ export async function agentBuildDraftExists(agentId: string): Promise<boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
export async function getAgentBuildDraft(agentId: string): Promise<AgentBuildDraftResponse> {
|
||||
const ctx = await createApiContext()
|
||||
try {
|
||||
const response = await ctx.get(`/console/api/agent/${agentId}/build-draft`)
|
||||
await expectApiResponseOK(response, `Get Agent v2 build draft for ${agentId}`)
|
||||
return (await response.json()) as AgentBuildDraftResponse
|
||||
}
|
||||
finally {
|
||||
await ctx.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
export async function applyAgentBuildDraft(agentId: string): Promise<void> {
|
||||
const ctx = await createApiContext()
|
||||
try {
|
||||
|
||||
@ -10,6 +10,7 @@ import {
|
||||
import {
|
||||
agentBuildDraftExists,
|
||||
applyAgentBuildDraft,
|
||||
getAgentBuildDraft,
|
||||
saveAgentBuildDraft,
|
||||
} from '../../agent-v2/support/agent-build-draft'
|
||||
import { agentBuilderFixedInputs, agentBuilderPreseededResources } from '../../agent-v2/support/agent-builder-resources'
|
||||
@ -33,10 +34,22 @@ import {
|
||||
} from './configure-helpers'
|
||||
|
||||
const BUILD_DRAFT_RUNTIME_STEP_TIMEOUT_MS = 180_000
|
||||
const BUILD_NOTE_FILE_NAME = 'build_note.md'
|
||||
const BUILD_NOTE_MARKER = 'E2E_BUILD_DRAFT_PASS'
|
||||
const BUILD_NOTE_GENERATED_BADGE = 'Generated'
|
||||
|
||||
const getBuildDraftBar = (page: Page) =>
|
||||
page.getByRole('group', { name: 'Build draft' })
|
||||
|
||||
const getBuildNoteFileButton = (page: Page) =>
|
||||
page.getByRole('region', { name: 'Files' })
|
||||
.getByRole('button')
|
||||
.filter({ hasText: BUILD_NOTE_FILE_NAME })
|
||||
.filter({ hasText: BUILD_NOTE_GENERATED_BADGE })
|
||||
|
||||
const getConfigNote = (value: Awaited<ReturnType<typeof getAgentBuildDraft>>) =>
|
||||
value.agent_soul?.config_note ?? ''
|
||||
|
||||
Given(
|
||||
'an Agent v2 Build draft adds the supported E2E files, skills, and env',
|
||||
async function (this: DifyWorld) {
|
||||
@ -274,6 +287,20 @@ Then('I should see the Agent v2 Build mode confirmation state', async function (
|
||||
await expect(page.getByText('Shape this setup through the chat on the right, then Apply.')).toBeVisible()
|
||||
})
|
||||
|
||||
Then(
|
||||
'the Agent v2 Build draft should include the generated build note',
|
||||
async function (this: DifyWorld) {
|
||||
await expect.poll(
|
||||
async () => getConfigNote(await getAgentBuildDraft(getCurrentAgentId(this))),
|
||||
{ timeout: 30_000 },
|
||||
).toContain(BUILD_NOTE_MARKER)
|
||||
},
|
||||
)
|
||||
|
||||
Then('I should see the generated Agent v2 build note in Configure', async function (this: DifyWorld) {
|
||||
await expect(getBuildNoteFileButton(this.getPage())).toBeVisible()
|
||||
})
|
||||
|
||||
Then('Agent v2 Build chat should be blocked until a model is configured', async function (this: DifyWorld) {
|
||||
await expectAgentModelRequiredFeedback(this.getPage())
|
||||
})
|
||||
@ -331,6 +358,16 @@ Then(
|
||||
},
|
||||
)
|
||||
|
||||
Then(
|
||||
'the normal Agent v2 draft should not include the generated build note',
|
||||
async function (this: DifyWorld) {
|
||||
await expect.poll(
|
||||
async () => (await getAgentComposerDraft(getCurrentAgentId(this))).agent_soul?.config_note ?? '',
|
||||
{ timeout: 30_000 },
|
||||
).not.toContain(BUILD_NOTE_MARKER)
|
||||
},
|
||||
)
|
||||
|
||||
Then(
|
||||
'the normal Agent v2 draft should not include the Agent Builder JSON Replace tool',
|
||||
async function (this: DifyWorld) {
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
Update only the Agent instructions.
|
||||
After applying, every response should briefly mention E2E_BUILD_DRAFT_PASS.
|
||||
Do not add files, skills, tools, knowledge, environment variables, or other capabilities.
|
||||
Update only the Agent build note for this Build draft.
|
||||
The build note should record this durable context exactly: E2E_BUILD_DRAFT_PASS.
|
||||
Do not update Agent instructions, prompt, files, skills, tools, knowledge, environment variables, or other capabilities.
|
||||
|
||||
@ -38,8 +38,10 @@ const shellctlPort = Number(process.env.E2E_SHELLCTL_PORT || 5004)
|
||||
const shellctlContainerName = process.env.E2E_SHELLCTL_CONTAINER_NAME || 'dify-agent-e2e-shellctl'
|
||||
const shellctlImage = process.env.E2E_SHELLCTL_IMAGE || 'dify-agent-local-sandbox:e2e'
|
||||
const shellctlUrl = `http://${shellctlHost}:${shellctlPort}`
|
||||
const agentStubApiBaseUrl = `http://host.docker.internal:${agentBackendPort}/agent-stub`
|
||||
const defaultPluginDaemonKey = 'lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi'
|
||||
const defaultInnerApiKeyForPlugin = 'QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1'
|
||||
const defaultAgentServerSecretKey = 'MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY'
|
||||
|
||||
const middlewareDataPaths = [
|
||||
path.join(dockerDir, 'volumes', 'db', 'data'),
|
||||
@ -104,6 +106,12 @@ const getAgentBackendEnvironment = async () => {
|
||||
|| apiEnv.INNER_API_KEY_FOR_PLUGIN
|
||||
|| defaultInnerApiKeyForPlugin,
|
||||
DIFY_AGENT_INNER_API_URL: process.env.DIFY_AGENT_INNER_API_URL || `http://${apiHost}:${apiPort}`,
|
||||
DIFY_AGENT_SERVER_SECRET_KEY:
|
||||
process.env.DIFY_AGENT_SERVER_SECRET_KEY
|
||||
|| defaultAgentServerSecretKey,
|
||||
DIFY_AGENT_STUB_API_BASE_URL:
|
||||
process.env.DIFY_AGENT_STUB_API_BASE_URL
|
||||
|| agentStubApiBaseUrl,
|
||||
DIFY_AGENT_PLUGIN_DAEMON_API_KEY:
|
||||
process.env.DIFY_AGENT_PLUGIN_DAEMON_API_KEY
|
||||
|| process.env.PLUGIN_DAEMON_KEY
|
||||
@ -420,6 +428,7 @@ export const startShellctlSandbox = async () => {
|
||||
'--rm',
|
||||
'--name',
|
||||
shellctlContainerName,
|
||||
...(process.platform === 'linux' ? ['--add-host', 'host.docker.internal:host-gateway'] : []),
|
||||
'-p',
|
||||
`${shellctlHost}:${shellctlPort}:5004`,
|
||||
...(process.env.E2E_SHELLCTL_AUTH_TOKEN
|
||||
|
||||
Loading…
Reference in New Issue
Block a user