-
Notifications
You must be signed in to change notification settings - Fork 152
feat: pursue a goal autonomously #270
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
+6,874
−137
Merged
Changes from all commits
Commits
Show all changes
65 commits
Select commit
Hold shift + click to select a range
29bee63
docs: add goal implementation plans
chengluyu 040a06c
Phase 1a: add SessionGoalStore durable goal state, session/agent wiri…
chengluyu 70ee3c6
Phase 1b: add goal.* audit records, audit sink/queue, normalizeMetada…
chengluyu c14b025
Phase 2: expose goal lifecycle via SDK and wire the /goal slash comma…
chengluyu c5d8a90
Phase 3: add CreateGoal, GetGoal, and UpdateGoal main-agent tools gat…
chengluyu 687654c
Phase 4a: inject active-goal guidance into the main agent context wit…
chengluyu aea58a5
Phase 4b: account goal token usage from every session agent step in T…
chengluyu 0899188
Phase 4c: add GoalContinuationController for autonomous continuation …
chengluyu d0dc822
Phase 4d: add independent GoalEvaluator and make goal completion eval…
chengluyu 674b2c1
Phase 5: add end-to-end goal session harness, dispatch integration te…
chengluyu abb938d
Phase 6: add headless /goal prompt mode with exit codes and summary, …
chengluyu a8e7054
Fix: treat goal maxStepsPerTurn as a per-segment continuation checkpo…
chengluyu b6b0922
Fix: stop goal turn gracefully when step cap is hit after a budget wr…
chengluyu aee3c9c
Fix: inject goal context at continuation boundaries, not per step (ca…
chengluyu 8047fa2
Fix: active goal completion self-audit prompt and one-time terminal-g…
chengluyu 5e60773
Phase 7.1: generic slash subcommand autocomplete, wired for /goal
chengluyu 0f2d5f0
Phase 7.2: drop default turn cap, surface goal counters to the evaluator
chengluyu cabe174
Phase 7.4: goal status footer badge and goal.updated event spine
chengluyu 8bd0e1e
Phase 7.4: record commit hashes in tracker
chengluyu 2cf71c7
Phase 7.5: render /goal status as a boxed panel like /usage
chengluyu 3091451
Phase 7.6a: goal.updated change payload and terminal stats on goal.up…
chengluyu 80db56b
Phase 7.6b: live transcript markers and completion card for goal loop
chengluyu a0b046c
Phase 7: defer 6c (resume reconstruction) with decided stats-only-car…
chengluyu ac9604c
Pause on interrupt instead of terminal `interrupted`
chengluyu b1ce03b
Consolidate lifecycle to active/paused/blocked/complete
chengluyu 51dbe3d
Deterministic completion message (replaces the live card)
chengluyu 5a018be
Phase 8: docs + tracker for goal state consolidation
chengluyu bc590fa
Fix resume to reset stuck streaks; show blocked in the badge
chengluyu 57c193f
Make `cancel` the sole discard; rename GoalChange.kind terminal→compl…
chengluyu bca52e2
Drop the stale over-budget injection guidance
chengluyu 27ff684
Paused goals inject nothing; blocked keeps a light note
chengluyu 4b50e0c
Three /goal UX fixes (autocomplete, hint, evaluator phase)
chengluyu f7ee407
Remove the UpdateGoal tool and its model-report plumbing
chengluyu c071f87
Rotate the evaluator spinner label from a pool of ten
chengluyu 6ba1c01
Drop the --max-* budget flags and the "no stop condition" notice
chengluyu 86aae27
Sequential-turn driver, minimal UpdateGoal, + UI fixes
chengluyu f447988
Remove dead evaluator spinner; consistent no-goal messages
chengluyu 5fdb513
Document `/goal` command
chengluyu 10ccf44
fix: preserve headless goal completion summary
chengluyu df3d359
fix: sync goal badge on session resume
chengluyu a49005e
Warn before starting goals in Manual mode
chengluyu 9c85b9b
Merge origin/main
chengluyu bf46229
Remove stray agent-code package file
chengluyu 27b05c9
Highlight goal status messages
chengluyu 0f052f9
Keep goal timer running in footer
chengluyu 77e0735
Avoid Anthropic goal completion prefill
chengluyu 38f55a4
Simplify goal completion replay parsing
chengluyu 833e0c3
Fix stale evaluator/continuation-controller references
chengluyu dd866b6
Restore regex goal completion replay parsing
chengluyu a9f6271
Remove dead no-progress/failure guard scaffolding from goal mode
chengluyu d838e15
Remove dead goal evidence plumbing
chengluyu e68378e
Tighten goal lifecycle guidance
chengluyu 25ae673
Make goal set notice a marker
chengluyu 73adbb2
Space goal status panel
chengluyu b0815f5
Add goal budget tool
chengluyu 64fd482
Refresh goal changeset
chengluyu 2a9ef5a
Pause goals on rate limits
chengluyu 9100def
Address goal review feedback
chengluyu 4d82148
Merge origin/main
chengluyu b7f34e1
Fix goal flag test lint
chengluyu 734b1d4
Address more goal review feedback
chengluyu e7e6879
Mention the goal is experimental
chengluyu 5e68ee6
Track goal lifecycle usage
chengluyu c0aacc0
Update goal changeset
chengluyu a22a66c
Refine goal changeset wording
chengluyu 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,15 @@ | ||
| --- | ||
| "@moonshot-ai/agent-core": minor | ||
| "@moonshot-ai/kimi-code-sdk": minor | ||
| "@moonshot-ai/kimi-code": minor | ||
| --- | ||
|
|
||
| Add experimental goal mode for longer tasks that need more than one turn. Turn it on with `KIMI_CODE_EXPERIMENTAL_GOAL_COMMAND=1` before you start Kimi. | ||
|
|
||
| Use `/goal <objective>` in the TUI when you want Kimi to keep working on one task across turns. For example: | ||
|
|
||
| ```text | ||
| /goal Fix the failing checkout test | ||
| ``` | ||
|
|
||
| Kimi shows the goal in the TUI and keeps progress visible while it works. Use `/goal status`, `/goal pause`, `/goal resume`, `/goal cancel`, and `/goal replace <objective>` to manage the goal. This feature is still experimental. Try it and tell us what would make it more useful. |
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,102 @@ | ||
| import type { GoalSnapshot } from '@moonshot-ai/kimi-code-sdk'; | ||
|
|
||
| import { parseGoalCommand } from '#/tui/commands/index'; | ||
|
|
||
| /** | ||
| * Headless goal-mode support for the `kimi -p "/goal <objective>"` prompt path. | ||
| * | ||
| * The goal driver keeps the prompt's turn-run alive across continuation turns | ||
| * until the goal reaches a terminal state, so the existing prompt-turn waiter | ||
| * already blocks until then. This module adds the create-on-entry parsing, a | ||
| * machine-readable summary, and the terminal-status → exit-code mapping. | ||
| */ | ||
|
|
||
| export interface HeadlessGoalCreate { | ||
| readonly objective: string; | ||
| readonly replace: boolean; | ||
| } | ||
|
|
||
| /** | ||
| * Exit codes by final goal status. The lifecycle has only one success outcome | ||
| * (`complete` → 0) and two resumable stopped states: `blocked` (the system | ||
| * stopped pursuing — the model's UpdateGoal, a budget, or an error) and `paused` | ||
| * (a turn abort / SIGINT). Both are non-zero — the goal did not complete. An absent goal | ||
| * (should not happen on the create path) maps to success. | ||
| */ | ||
| export const GOAL_EXIT_CODES = { | ||
| complete: 0, | ||
| blocked: 3, | ||
| paused: 6, | ||
| } as const; | ||
|
|
||
| export function goalExitCode(status: string | undefined): number { | ||
| switch (status) { | ||
| case 'blocked': | ||
| return GOAL_EXIT_CODES.blocked; | ||
| case 'paused': | ||
| return GOAL_EXIT_CODES.paused; | ||
| default: | ||
| return GOAL_EXIT_CODES.complete; | ||
| } | ||
| } | ||
|
|
||
| const GOAL_PREFIX = /^\/goal(\s|$)/; | ||
|
|
||
| /** | ||
| * Parses a headless prompt into a goal-create request, or `undefined` when the | ||
| * prompt is not a `/goal` create command (so the caller runs it as a normal | ||
| * prompt). Non-create goal subcommands are not supported headless and fall | ||
| * through to normal prompt handling. | ||
| */ | ||
| export function parseHeadlessGoalCreate( | ||
| prompt: string, | ||
| flagEnabled: boolean, | ||
| ): HeadlessGoalCreate | undefined { | ||
| if (!flagEnabled) return undefined; | ||
| const trimmed = prompt.trim(); | ||
| if (!GOAL_PREFIX.test(trimmed)) return undefined; | ||
| const args = trimmed.replace(/^\/goal/, '').trim(); | ||
| const parsed = parseGoalCommand(args); | ||
| if (parsed.kind !== 'create') return undefined; | ||
| return { objective: parsed.objective, replace: parsed.replace }; | ||
| } | ||
|
|
||
| export interface GoalSummary { | ||
| readonly type: 'goal.summary'; | ||
| readonly goalId: string | null; | ||
| readonly status: string | null; | ||
| readonly reason: string | null; | ||
| readonly turnsUsed: number | null; | ||
| readonly tokensUsed: number | null; | ||
| readonly wallClockMs: number | null; | ||
| } | ||
|
|
||
| export function goalSummaryJson(goal: GoalSnapshot | null): GoalSummary { | ||
| if (goal === null) { | ||
| return { | ||
| type: 'goal.summary', | ||
| goalId: null, | ||
| status: null, | ||
| reason: null, | ||
| turnsUsed: null, | ||
| tokensUsed: null, | ||
| wallClockMs: null, | ||
| }; | ||
| } | ||
| return { | ||
| type: 'goal.summary', | ||
| goalId: goal.goalId, | ||
| status: goal.status, | ||
| reason: goal.terminalReason ?? null, | ||
| turnsUsed: goal.turnsUsed, | ||
| tokensUsed: goal.tokensUsed, | ||
| wallClockMs: goal.wallClockMs, | ||
| }; | ||
| } | ||
|
|
||
| export function formatGoalSummaryText(goal: GoalSnapshot | null): string { | ||
| if (goal === null) return 'Goal: no goal found.'; | ||
| const parts = [`Goal [${goal.status}]`]; | ||
| if (goal.terminalReason !== undefined) parts.push(goal.terminalReason); | ||
| return `${parts.join(': ')} (turns: ${goal.turnsUsed}, tokens: ${goal.tokensUsed})`; | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import type { AutocompleteItem } from '@earendil-works/pi-tui'; | ||
|
|
||
| /** | ||
| * A completable token (subcommand or flag) for a slash command's argument | ||
| * position. Generic across commands — any `KimiSlashCommand` can build a | ||
| * `getArgumentCompletions` from a list of these via {@link completeLeadingArg}. | ||
| */ | ||
| export interface ArgCompletionSpec { | ||
| /** The token inserted on completion, e.g. `pause` or `resume`. */ | ||
| readonly value: string; | ||
| /** Short description shown in the autocomplete menu. */ | ||
| readonly description: string; | ||
| } | ||
|
|
||
| /** | ||
| * Generic leading-token completer for slash-command arguments. | ||
| * | ||
| * pi-tui passes `argumentPrefix` = everything typed after `/<command> `. We only | ||
| * complete the *first* token: once the user has typed a space after it (moved on | ||
| * to an objective, a flag value, etc.) we return `null` so completion never | ||
| * clobbers free text. Matching is case-insensitive prefix match on `value`. | ||
| */ | ||
| export function completeLeadingArg( | ||
| specs: readonly ArgCompletionSpec[], | ||
| argumentPrefix: string, | ||
| ): AutocompleteItem[] | null { | ||
| if (argumentPrefix.includes(' ')) return null; | ||
| const lower = argumentPrefix.toLowerCase(); | ||
| const items = specs | ||
| .filter((spec) => spec.value.toLowerCase().startsWith(lower)) | ||
| .map((spec) => ({ value: spec.value, label: spec.value, description: spec.description })); | ||
| // Nothing left to complete: the user has finished typing a token that is the | ||
| // sole remaining match (e.g. `status`). Keeping the menu open here would make | ||
| // Enter confirm the no-op completion instead of submitting the command, so we | ||
| // suppress it. (A space after the token already returns null above.) | ||
| const [only] = items; | ||
| if (items.length === 1 && only !== undefined && only.value.toLowerCase() === lower) { | ||
| return null; | ||
| } | ||
| return items.length > 0 ? items : null; | ||
| } |
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.
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.