perf: defer agent output classification
Defers meaningful-output classification in AgentDetector until an active or starting agent session needs it.
This commit is contained in:
parent
dce1ce1bdd
commit
2049d16bd5
|
|
@ -19,6 +19,35 @@ describe('AgentDetector', () => {
|
|||
expect(stats.onAgentStop).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not inspect unknown non-agent output for meaningful content', () => {
|
||||
const stats = {
|
||||
onAgentStart: vi.fn(),
|
||||
onAgentStop: vi.fn()
|
||||
}
|
||||
const detectMeaningfulContent = vi.fn(() => true)
|
||||
const detector = new AgentDetector(stats as never, detectMeaningfulContent)
|
||||
|
||||
detector.onData('pty-1', '\x1b[2K\x1b[1G'.repeat(100), 100)
|
||||
|
||||
expect(detectMeaningfulContent).not.toHaveBeenCalled()
|
||||
expect(stats.onAgentStart).not.toHaveBeenCalled()
|
||||
expect(stats.onAgentStop).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('inspects content once when an agent title starts a session', () => {
|
||||
const stats = {
|
||||
onAgentStart: vi.fn(),
|
||||
onAgentStop: vi.fn()
|
||||
}
|
||||
const detectMeaningfulContent = vi.fn(() => true)
|
||||
const detector = new AgentDetector(stats as never, detectMeaningfulContent)
|
||||
|
||||
detector.onData('pty-1', `${oscTitle('⠂ Writing patch')}real output`, 100)
|
||||
|
||||
expect(detectMeaningfulContent).toHaveBeenCalledTimes(1)
|
||||
expect(stats.onAgentStart).toHaveBeenCalledWith('pty-1', 100)
|
||||
})
|
||||
|
||||
it('stops a session on working to idle transition using the last meaningful output time', () => {
|
||||
const stats = {
|
||||
onAgentStart: vi.fn(),
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ type PtyRecord = {
|
|||
lastMeaningfulOutputAt: number | null
|
||||
}
|
||||
|
||||
type MeaningfulContentDetector = (chunk: string) => boolean
|
||||
|
||||
/**
|
||||
* Lightweight normalization to detect whether a PTY data chunk contains
|
||||
* meaningful (non-ANSI, non-OSC) output. Mirrors the regex passes in
|
||||
|
|
@ -72,9 +74,11 @@ function hasMeaningfulContent(chunk: string): boolean {
|
|||
export class AgentDetector {
|
||||
private ptys = new Map<string, PtyRecord>()
|
||||
private stats: StatsCollector
|
||||
private meaningfulContentDetector: MeaningfulContentDetector
|
||||
|
||||
constructor(stats: StatsCollector) {
|
||||
constructor(stats: StatsCollector, meaningfulContentDetector = hasMeaningfulContent) {
|
||||
this.stats = stats
|
||||
this.meaningfulContentDetector = meaningfulContentDetector
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -99,8 +103,13 @@ export class AgentDetector {
|
|||
return
|
||||
}
|
||||
|
||||
const hasMeaningfulOutput = hasMeaningfulContent(rawData)
|
||||
if (record.sessionOpen && hasMeaningfulOutput) {
|
||||
let hasMeaningfulOutput: boolean | null = null
|
||||
const getHasMeaningfulOutput = (): boolean => {
|
||||
hasMeaningfulOutput ??= this.meaningfulContentDetector(rawData)
|
||||
return hasMeaningfulOutput
|
||||
}
|
||||
|
||||
if (record.sessionOpen && getHasMeaningfulOutput()) {
|
||||
record.lastMeaningfulOutputAt = at
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +128,7 @@ export class AgentDetector {
|
|||
record.lastStatus = status
|
||||
record.sessionOpen = true
|
||||
record.sessionStartAt = at
|
||||
record.lastMeaningfulOutputAt = hasMeaningfulOutput ? at : null
|
||||
record.lastMeaningfulOutputAt = getHasMeaningfulOutput() ? at : null
|
||||
this.stats.onAgentStart(ptyId, at)
|
||||
return
|
||||
}
|
||||
|
|
@ -139,7 +148,7 @@ export class AgentDetector {
|
|||
// title is the start boundary for the next tracked session.
|
||||
record.sessionOpen = true
|
||||
record.sessionStartAt = at
|
||||
record.lastMeaningfulOutputAt = hasMeaningfulOutput ? at : null
|
||||
record.lastMeaningfulOutputAt = getHasMeaningfulOutput() ? at : null
|
||||
this.stats.onAgentStart(ptyId, at)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue