fix(council-archive): handle literal tag mentions inside response content

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
ismeth
2026-03-01 16:59:47 +01:00
committed by YeonGyu-Kim
parent e8e64d9f56
commit b4dd379b38
2 changed files with 161 additions and 10 deletions
@@ -10,22 +10,104 @@ export interface CouncilResponseExtraction {
}
export function extractCouncilResponse(fullText: string): CouncilResponseExtraction {
const lastOpenIdx = fullText.lastIndexOf(OPENING_TAG)
if (lastOpenIdx === -1) {
return { has_response: false, response_complete: false, result: null }
}
const lastCloseIdx = findLastStructuralClose(fullText)
const contentStart = lastOpenIdx + OPENING_TAG.length
const closingAfterLastOpen = fullText.indexOf(CLOSING_TAG, contentStart)
if (closingAfterLastOpen === -1) {
const partial = fullText.slice(contentStart).trim()
if (lastCloseIdx === -1) {
const lastOpenIdx = findLastStructuralOpen(fullText)
if (lastOpenIdx === -1) {
return { has_response: false, response_complete: false, result: null }
}
const partial = fullText.slice(lastOpenIdx + OPENING_TAG.length).trim()
return { has_response: true, response_complete: false, result: partial || null }
}
const content = fullText.slice(contentStart, closingAfterLastOpen).trim()
const openAfterLastClose = findFirstStructuralOpenAfter(fullText, lastCloseIdx + CLOSING_TAG.length)
if (openAfterLastClose !== -1) {
const partial = fullText.slice(openAfterLastClose + OPENING_TAG.length).trim()
return { has_response: true, response_complete: false, result: partial || null }
}
const matchingOpenIdx = findLastStructuralOpenBefore(fullText, lastCloseIdx)
if (matchingOpenIdx === -1) {
return { has_response: false, response_complete: false, result: null }
}
const content = fullText.slice(matchingOpenIdx + OPENING_TAG.length, lastCloseIdx).trim()
if (content.length < MIN_RESPONSE_LENGTH) {
return { has_response: false, response_complete: true, result: content }
}
return { has_response: true, response_complete: true, result: content }
}
function isStructuralOpen(text: string, idx: number): boolean {
return idx === 0 || text[idx - 1] === "\n"
}
function isStructuralClose(text: string, idx: number): boolean {
const afterIdx = idx + CLOSING_TAG.length
return afterIdx === text.length || text[afterIdx] === "\n"
}
function findLastStructuralClose(text: string): number {
let searchFrom = text.length
while (searchFrom >= 0) {
const idx = text.lastIndexOf(CLOSING_TAG, searchFrom - 1)
if (idx === -1) return -1
if (isStructuralClose(text, idx)) return idx
searchFrom = idx
}
return -1
}
function findLastStructuralOpen(text: string): number {
let searchFrom = text.length
while (searchFrom >= 0) {
const idx = text.lastIndexOf(OPENING_TAG, searchFrom - 1)
if (idx === -1) return -1
if (isStructuralOpen(text, idx)) return idx
searchFrom = idx
}
return -1
}
function findFirstStructuralOpenAfter(text: string, fromIdx: number): number {
let searchFrom = fromIdx
while (searchFrom < text.length) {
const idx = text.indexOf(OPENING_TAG, searchFrom)
if (idx === -1) return -1
if (isStructuralOpen(text, idx)) return idx
searchFrom = idx + OPENING_TAG.length
}
return -1
}
function findLastStructuralOpenBefore(text: string, beforeIdx: number): number {
let searchFrom = beforeIdx
let nestedCloseCount = 0
while (searchFrom > 0) {
const openIdx = text.lastIndexOf(OPENING_TAG, searchFrom - 1)
const closeIdx = text.lastIndexOf(CLOSING_TAG, searchFrom - 1)
if (openIdx === -1 && closeIdx === -1) return -1
if (closeIdx > openIdx) {
if (isStructuralClose(text, closeIdx)) {
nestedCloseCount += 1
}
searchFrom = closeIdx
continue
}
if (!isStructuralOpen(text, openIdx)) {
searchFrom = openIdx
continue
}
if (nestedCloseCount === 0) return openIdx
nestedCloseCount -= 1
searchFrom = openIdx
}
return -1
}