-
Notifications
You must be signed in to change notification settings - Fork 253
feat(goal): let the user arm a Goal from the composer #3199
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
Merged
Astro-Han
merged 12 commits into
apache:main
from
Astro-Han:feat/goal-arm-from-composer
Aug 20, 2026
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
29c3dee
feat(goal): let the user arm a Goal from the composer
Astro-Han c2affdf
fix(goal): trim the Goal condition where it is persisted
Astro-Han 6950736
fix(desktop): reuse the arm operation's own shape and bounds
Astro-Han efc52af
fix(desktop): drop the previous Session's Goal on a Session switch
Astro-Han 2fda1a7
fix(runtime-host): retire epoch 28 for the new Goal arm operation
Astro-Han 7068401
fix(goal): leave a Goal no Turn has carried for the next Turn, not fo…
Astro-Han 361a1a9
refactor(goal): drop the Goal token baseline nobody could set
Astro-Han 7f1c046
fix(desktop): arm the Goal budgets the form is showing
Astro-Han bd51570
fix(goal): tell an armed Goal from one a Turn already carries
Astro-Han e06bb9e
fix(runtime-host): refuse an arm that outlived the composition
Astro-Han fa0dc52
test(runtime-host): drop the retired backend input from the new Goal …
Astro-Han 3410efa
fix(goal): resume a Goal the user armed instead of leaving it inert
Astro-Han File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| import { test, expect, COMPOSER_INPUT } from './fixtures'; | ||
|
|
||
| /** | ||
| * Arming a Goal starts unattended token spending, and the two budgets in this | ||
| * dialog are what stops it. A budget the form shows but does not send is | ||
| * therefore the one failure this dialog must not have — most sharply when the | ||
| * value is dropped rather than altered, because an absent token budget is not | ||
| * a smaller ceiling but no ceiling at all. | ||
| * | ||
| * The assertions read the Goal back from the Host rather than watching the | ||
| * bridge call, so they answer what was actually armed. | ||
| */ | ||
| test('an unsendable budget blocks Start instead of arming a different one', async ({ | ||
| window: page, | ||
| }) => { | ||
| // The + menu only offers a Goal for a Session that exists, so seed one and | ||
| // let its Turn settle first — a live Turn disables the entry too. | ||
| const composer = page.locator(COMPOSER_INPUT); | ||
| await composer.fill('seed session'); | ||
| await composer.press('Enter'); | ||
| await expect(page.getByRole('log').getByText(/Fake backend received: seed session/)).toBeVisible(); | ||
| await expect(page.getByRole('button', { name: '重新生成' })).toHaveCount(1, { timeout: 20_000 }); | ||
|
|
||
| const sessionId = await page.evaluate(async () => (await window.maka.sessions.list())[0]?.id); | ||
| expect(sessionId).toBeTruthy(); | ||
| const armedGoal = () => | ||
| page.evaluate(async (id: string) => await window.maka.goal.get(id), sessionId as string); | ||
|
|
||
| await page.getByRole('button', { name: '添加上下文' }).click(); | ||
| await page.getByRole('menuitem', { name: '设定 Goal…' }).click(); | ||
|
|
||
| const dialog = page.getByRole('dialog'); | ||
| await dialog.getByLabel(/达成条件/).fill('所有测试通过'); | ||
| const start = dialog.getByRole('button', { name: '开始' }); | ||
| await expect(start).toBeEnabled(); | ||
|
|
||
| // Below the Host's own minimum. The field this replaced kept such text to | ||
| // itself and left the sent budget null, so Start stayed enabled and armed no | ||
| // ceiling at all. | ||
| await dialog.getByLabel(/Token 预算/).fill('500'); | ||
| await expect(start).toBeDisabled(); | ||
| await expect(dialog.getByText(/请填不小于 1000 的整数/)).toBeVisible(); | ||
|
|
||
| await dialog.getByLabel(/Token 预算/).fill('5000'); | ||
| await expect(start).toBeEnabled(); | ||
|
|
||
| // Above the Host's ceiling on turns; the same rule from the other side. | ||
| await dialog.getByLabel(/最多轮数/).fill('250'); | ||
| await expect(start).toBeDisabled(); | ||
| await expect(await armedGoal()).toBeNull(); | ||
|
|
||
| await dialog.getByLabel(/最多轮数/).fill('25'); | ||
| await expect(start).toBeEnabled(); | ||
| await start.click(); | ||
|
|
||
| await expect | ||
| .poll(async () => { | ||
| const goal = await armedGoal(); | ||
| return goal && { | ||
| condition: goal.condition, | ||
| maxIterations: goal.maxIterations, | ||
| tokenBudget: goal.tokenBudget, | ||
| }; | ||
| }) | ||
| .toEqual({ condition: '所有测试通过', maxIterations: 25, tokenBudget: 5000 }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.