-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat(agent-core-v2): rework the title generation excerpts #3109
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
Changes from all commits
abfc065
86959db
8068f00
f90c3e1
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,5 @@ | ||
| --- | ||
| "@moonshot-ai/agent-core-v2": patch | ||
| --- | ||
|
|
||
| Rework the session title excerpts: rebalance the segment budgets toward user prompts (400 chars each, assistant 300), cap each prompt in the `user_prompts` excerpt, and compose the `digest` excerpt from the full conversation arc — every natural-language user prompt in the live window paired with its own turn's final assistant text, interleaved chronologically, within per-segment caps and a 3000-char total budget (middle turns elided). | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,11 +31,15 @@ const MAX_TITLE_INPUT_LENGTH = 1000; | |
|
|
||
| const MAX_TITLE_PROMPTS = 3; | ||
|
|
||
| const MAX_TITLE_USER_SEGMENT = 300; | ||
| const MAX_TITLE_USER_SEGMENT = 400; | ||
|
|
||
| const MAX_TITLE_FIRST_TURN_ASSISTANT = 600; | ||
| const MAX_TITLE_FIRST_TURN_ASSISTANT = 300; | ||
|
|
||
| const MAX_TITLE_DIGEST_ASSISTANT = 400; | ||
| const MAX_TITLE_DIGEST_USER_SEGMENT = 200; | ||
|
|
||
| const MAX_TITLE_DIGEST_ASSISTANT = 200; | ||
|
|
||
| const MAX_TITLE_DIGEST_INPUT_LENGTH = 3000; | ||
|
|
||
| export class SessionTitleService implements ISessionTitleService { | ||
| declare readonly _serviceBrand: undefined; | ||
|
|
@@ -161,7 +165,7 @@ export class SessionTitleService implements ISessionTitleService { | |
| function titleInputFromPrompts(prompts: readonly string[]): string | undefined { | ||
| if (prompts.length === 0) return undefined; | ||
| return prompts | ||
| .map((prompt) => `user: ${prompt}`) | ||
| .map((prompt) => `user: ${prompt.slice(0, MAX_TITLE_USER_SEGMENT)}`) | ||
| .join('\n') | ||
| .slice(0, MAX_TITLE_INPUT_LENGTH); | ||
| } | ||
|
|
@@ -180,21 +184,43 @@ async function composeTitleInput( | |
| } | ||
| if (source === 'digest') { | ||
| const excerpt = await promptSource.digestExcerpt(); | ||
| const lines: string[] = []; | ||
| if (excerpt.firstUser !== undefined) { | ||
| lines.push(`user: ${excerpt.firstUser.slice(0, MAX_TITLE_USER_SEGMENT)}`); | ||
| } | ||
| if (excerpt.lastUser !== undefined) { | ||
| lines.push(`user: ${excerpt.lastUser.slice(0, MAX_TITLE_USER_SEGMENT)}`); | ||
| } | ||
| if (excerpt.assistant !== undefined) { | ||
| lines.push(`assistant: ${excerpt.assistant.slice(0, MAX_TITLE_DIGEST_ASSISTANT)}`); | ||
| const turns: string[][] = []; | ||
| for (const turn of excerpt.turns) { | ||
| const group = [`user: ${turn.user.slice(0, MAX_TITLE_DIGEST_USER_SEGMENT)}`]; | ||
|
Comment on lines
186
to
+189
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.
The exported Useful? React with 👍 / 👎. |
||
| if (turn.assistant !== undefined) { | ||
| group.push(`assistant: ${turn.assistant.slice(0, MAX_TITLE_DIGEST_ASSISTANT)}`); | ||
| } | ||
| turns.push(group); | ||
| } | ||
| return lines.length === 0 ? undefined : lines.join('\n'); | ||
| return elideTitleDigestTurns(turns); | ||
| } | ||
| return titleInputFromPrompts(await promptSource.firstUserPrompts(MAX_TITLE_PROMPTS)); | ||
| } | ||
|
|
||
| const TITLE_DIGEST_ELISION_MARKER = '...'; | ||
|
|
||
| function elideTitleDigestTurns(turns: readonly (readonly string[])[]): string | undefined { | ||
| if (turns.length === 0) return undefined; | ||
| const joined = turns.flat().join('\n'); | ||
| if (joined.length <= MAX_TITLE_DIGEST_INPUT_LENGTH) return joined; | ||
| let budget = MAX_TITLE_DIGEST_INPUT_LENGTH - TITLE_DIGEST_ELISION_MARKER.length - 2; | ||
| const head: string[] = []; | ||
| for (const line of turns[0]!) { | ||
| if (budget < line.length + 1) break; | ||
| head.push(line); | ||
| budget -= line.length + 1; | ||
| } | ||
| const tail: string[] = []; | ||
| for (let index = turns.length - 1; index >= 1; index--) { | ||
| const group = turns[index]!; | ||
| const cost = group.reduce((sum, line) => sum + line.length + 1, 0); | ||
| if (budget < cost) break; | ||
| tail.unshift(...group); | ||
| budget -= cost; | ||
| } | ||
| return [...head, TITLE_DIGEST_ELISION_MARKER, ...tail].join('\n'); | ||
| } | ||
|
|
||
| registerScopedService( | ||
| LifecycleScope.Session, | ||
| ISessionTitleService, | ||
|
|
||
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.
When this changeset is incorporated into release notes, its roughly 60-word sentence exposes internal excerpt names, per-segment limits, and elision mechanics instead of providing the required short user-facing summary. Reduce it to one concise sentence describing the title-quality improvement.
AGENTS.md reference: AGENTS.md:L85-L86
Useful? React with 👍 / 👎.