fix(autofix-pr): extractBetween 支持 latest tag 截断时回溯到更早完整对
如果远端 agent 重试时写了完整 <autofix-result> 后又开了一个被截断的 第二个 tag, 旧实现只看 lastIndexOf(open) 然后找不到 close 就返回 null, 导致前面那个完整结果被丢弃。改为从尾向首遍历所有 open tag, 返回第一个 能配对的 open/close 对。 附带: - docs/features/remote-agent-completion-analysis.md: 9 处裸 fenced block 补 language tag (text/http), 修复 markdownlint MD040 警告 - 同文件: 两处"三选项" → "三个选项" 符合中文量词习惯
This commit is contained in:
parent
873f0a03ac
commit
ae7f3e2232
|
|
@ -89,6 +89,16 @@ describe('extractAutofixResultFromLog', () => {
|
|||
expect(extractAutofixResultFromLog(log)).toBeNull()
|
||||
})
|
||||
|
||||
test('returns earlier complete tag when latest open tag is truncated within the same block', () => {
|
||||
// Retry scenario: a full result was emitted, then a second result tag
|
||||
// started but got cut off. We should surface the earlier complete pair
|
||||
// rather than dropping the whole block.
|
||||
const complete = sampleTag('earlier complete result')
|
||||
const truncated = `<${AUTOFIX_RESULT_TAG}>\n<summary>truncated retry...`
|
||||
const log = [assistantTextMessage(`${complete}\n${truncated}`)]
|
||||
expect(extractAutofixResultFromLog(log)).toBe(complete)
|
||||
})
|
||||
|
||||
test('walks backwards so hook stdout from later in log wins over earlier assistant text', () => {
|
||||
const earlier = sampleTag('via assistant first')
|
||||
const later = sampleTag('via hook later')
|
||||
|
|
|
|||
|
|
@ -71,14 +71,22 @@ export function extractAutofixResultFromLog(log: SDKMessage[]): string | null {
|
|||
return null
|
||||
}
|
||||
|
||||
// Walks open tags from latest to earliest, returning the first complete
|
||||
// open/close pair. Guards against a truncated final tag shadowing an
|
||||
// earlier complete pair within the same text block (e.g., a retry wrote a
|
||||
// full result, then the model started a second tag that got cut off).
|
||||
function extractBetween(
|
||||
text: string,
|
||||
open: string,
|
||||
close: string,
|
||||
): string | null {
|
||||
const start = text.lastIndexOf(open)
|
||||
if (start === -1) return null
|
||||
const end = text.indexOf(close, start + open.length)
|
||||
if (end === -1) return null
|
||||
return text.slice(start, end + close.length)
|
||||
let searchFrom = text.length
|
||||
while (searchFrom >= 0) {
|
||||
const start = text.lastIndexOf(open, searchFrom)
|
||||
if (start === -1) return null
|
||||
const end = text.indexOf(close, start + open.length)
|
||||
if (end !== -1) return text.slice(start, end + close.length)
|
||||
searchFrom = start - 1
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user