mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-20 09:09:35 +02:00
fix(#592): a rule inside a Copilot answer stays part of it in agent read
The pane segmenter ended the response block at every full-width rule, so an answer that draws one (a markdown `---`, a passage quoted between two rules) read as only its last section: `Summary / ──── / Details` came back as "Details", and the existing test pinned that by expecting the quoted passage without its "Here it is:" lead-in. Inside an open response a rule is now held and written into the text as `---` once more of the same answer follows, so a rule that only separates the answer from the footer never trails it. The composer's own two rules (the last rule/❯/rule triple) are still boundaries. The old test now expects both parts, and a new one pins a Summary/rule/Details answer as one block; both fail without the change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
007ea8cfb3
commit
d170ad2295
2 files changed
+39
-1
No files matched your search
@@ -360,17 +360,28 @@ function parseDialectTranscript(cleaned: string, dialect: PaneDialect): Response
|
||||
}
|
||||
}
|
||||
const isComposerRow = (i: number) => i === composerIndex;
|
||||
const isComposerRule = (i: number) => composerIndex !== -1 && (i === composerIndex - 1 || i === composerIndex + 1);
|
||||
const hasPrompt = rows.some((row, i) => dialect.prompt.test(row) && !isComposerRow(i));
|
||||
const startupVisible = rows.some((row) => dialect.startup.some((re) => re.test(row)));
|
||||
let sawPrompt = !hasPrompt && !startupVisible;
|
||||
// A rule drawn INSIDE an answer (a markdown `---`, a quoted passage between two rules) is part
|
||||
// of the answer, so it must not end the block, or `agent read` returns only the text after the
|
||||
// last rule. It is held until more of the same answer follows, so a rule that only separates
|
||||
// the answer from the footer never trails it. The composer's own two rules stay boundaries.
|
||||
let pendingRule = false;
|
||||
|
||||
const flush = () => {
|
||||
if (sawPrompt) pushBlock(blocks, kind, current);
|
||||
kind = null;
|
||||
current = [];
|
||||
pendingRule = false;
|
||||
};
|
||||
|
||||
for (const [index, line] of rows.entries()) {
|
||||
if (kind === 'response' && isDividerOnlyLine(line) && !isComposerRule(index)) {
|
||||
pendingRule = true;
|
||||
continue;
|
||||
}
|
||||
if (isDividerOnlyLine(line) || isComposerRow(index) || dialect.ignore.some((re) => re.test(line))) {
|
||||
flush();
|
||||
continue;
|
||||
@@ -407,6 +418,10 @@ function parseDialectTranscript(cleaned: string, dialect: PaneDialect): Response
|
||||
continue;
|
||||
}
|
||||
if (!kind) kind = 'response';
|
||||
if (pendingRule) {
|
||||
current.push('', '---', '');
|
||||
pendingRule = false;
|
||||
}
|
||||
current.push(line);
|
||||
}
|
||||
flush();
|
||||
|
||||
@@ -551,10 +551,33 @@ describe('GitHub Copilot pane dialect', () => {
|
||||
...tail,
|
||||
].join('\n');
|
||||
expect(getLastTranscriptResponse(parseExternalCliTranscript(screen, 'copilot'))).toBe(
|
||||
'Quoted passage between two rules.'
|
||||
'Here it is:\n\n---\n\nQuoted passage between two rules.'
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps an answer whole across a rule inside it, so agent read never returns only its tail', () => {
|
||||
const screen = [
|
||||
' ❯ summarize the change 11:22',
|
||||
' ● Summary',
|
||||
'',
|
||||
' One line of summary.',
|
||||
rule,
|
||||
' Details',
|
||||
'',
|
||||
' The longer explanation.',
|
||||
...tail,
|
||||
].join('\n');
|
||||
const blocks = parseExternalCliTranscript(screen, 'copilot');
|
||||
expect(blocks.filter((b) => b.kind === 'response')).toHaveLength(1);
|
||||
const answer = getLastTranscriptResponse(blocks);
|
||||
expect(answer).toContain('Summary');
|
||||
expect(answer).toContain('One line of summary.');
|
||||
expect(answer).toContain('Details');
|
||||
expect(answer).toContain('The longer explanation.');
|
||||
// The rule before the footer separates the answer from the chrome and never trails it.
|
||||
expect(answer.endsWith('---')).toBe(false);
|
||||
});
|
||||
|
||||
it('answers nothing for a session that has only drawn its banner or a trust dialog', () => {
|
||||
const banner = pane.split('\n').slice(0, 9).join('\n');
|
||||
expect(getLastTranscriptResponse(parseExternalCliTranscript(banner, 'copilot'))).toBe('');
|
||||
|
||||
Reference in new issue
Block a user