mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-08 08:29:42 +02:00
fix: improve history prompt extraction — filter expanded commands, add tail scan fallback
Skip /init expansions, slash commands, orchestrator prompts, ANSI codes, secrets, and short/vague messages. When head scan finds no usable prompt (e.g. /init sessions), read last 32KB of transcript to find a recent meaningful user message. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -984,14 +984,25 @@ export function registerSessionRoutes(
|
|||||||
if (textBlock) text = textBlock.text;
|
if (textBlock) text = textBlock.text;
|
||||||
}
|
}
|
||||||
if (!text) continue;
|
if (!text) continue;
|
||||||
// Strip XML-like system/command tags that Claude Code injects into transcripts
|
// Strip XML-like system/command tags and ANSI escapes from transcripts
|
||||||
text = text
|
text = text
|
||||||
.replace(/<[^>]+>/g, '')
|
.replace(/<[^>]+>/g, '')
|
||||||
|
.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '')
|
||||||
.trim()
|
.trim()
|
||||||
.replace(/\s+/g, ' ');
|
.replace(/\s+/g, ' ');
|
||||||
if (!text) continue;
|
if (!text) continue;
|
||||||
// Skip system-injected messages and slash command artifacts (not real user prompts)
|
// Skip system-injected messages, slash command artifacts, and expanded skill prompts
|
||||||
if (/^(Caveat:|init\b|clear\b|\/\w+ \w+$|You are a )/i.test(text)) continue;
|
if (
|
||||||
|
/^(Caveat:|init\b|clear\b|resume\b|\/[a-z][\w-]*\b|You are a |\[Request |Set model to )/i.test(text) ||
|
||||||
|
/^(Please )?(analyze|review) this codebase/i.test(text) ||
|
||||||
|
/^(Read|Implement the following) .+, then (search|list|check) /i.test(text) ||
|
||||||
|
/^\d+ vulnerabilit/i.test(text) ||
|
||||||
|
/\btoolu_/.test(text) ||
|
||||||
|
/^[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]+/.test(text) ||
|
||||||
|
/\b(sk-ant-|ANTHROPIC_API_KEY|API_KEY=|SECRET|TOKEN=)/i.test(text) ||
|
||||||
|
text.length < 8
|
||||||
|
)
|
||||||
|
continue;
|
||||||
return text.length > MAX_PROMPT_LEN ? text.slice(0, MAX_PROMPT_LEN) + '…' : text;
|
return text.length > MAX_PROMPT_LEN ? text.slice(0, MAX_PROMPT_LEN) + '…' : text;
|
||||||
} catch {
|
} catch {
|
||||||
// Malformed line — skip
|
// Malformed line — skip
|
||||||
@@ -1012,6 +1023,25 @@ export function registerSessionRoutes(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Read the last `buf.length` bytes of a file (for tail-scanning user prompts). */
|
||||||
|
async function readFileTail(path: string, buf: Buffer, fileSize: number): Promise<string | null> {
|
||||||
|
try {
|
||||||
|
const fd = await fs.open(path, 'r');
|
||||||
|
const offset = Math.max(0, fileSize - buf.length);
|
||||||
|
const { bytesRead } = await fd.read(buf, 0, buf.length, offset);
|
||||||
|
await fd.close();
|
||||||
|
const text = buf.toString('utf8', 0, bytesRead);
|
||||||
|
// Skip first partial line when we didn't read from the start
|
||||||
|
if (offset > 0) {
|
||||||
|
const nl = text.indexOf('\n');
|
||||||
|
return nl >= 0 ? text.slice(nl + 1) : null;
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
app.get('/api/history/sessions', async () => {
|
app.get('/api/history/sessions', async () => {
|
||||||
const projectsDir = join(process.env.HOME || '/tmp', '.claude', 'projects');
|
const projectsDir = join(process.env.HOME || '/tmp', '.claude', 'projects');
|
||||||
const results: Array<{
|
const results: Array<{
|
||||||
@@ -1074,6 +1104,14 @@ export function registerSessionRoutes(
|
|||||||
}
|
}
|
||||||
if (head) firstPrompt = extractFirstUserPrompt(head);
|
if (head) firstPrompt = extractFirstUserPrompt(head);
|
||||||
|
|
||||||
|
// If head scan found no usable prompt (e.g. session started with /init),
|
||||||
|
// try reading the tail for a recent user message.
|
||||||
|
if (!firstPrompt && fileStat.size > 65536) {
|
||||||
|
const tailBuf = Buffer.alloc(32768);
|
||||||
|
const tail = await readFileTail(filePath, tailBuf, fileStat.size);
|
||||||
|
if (tail) firstPrompt = extractFirstUserPrompt(tail);
|
||||||
|
}
|
||||||
|
|
||||||
results.push({
|
results.push({
|
||||||
sessionId,
|
sessionId,
|
||||||
workingDir,
|
workingDir,
|
||||||
|
|||||||
Reference in New Issue
Block a user