mirror of
https://github.com/stablyai/orca.git
synced 2026-10-17 08:03:14 +00:00
Add shared helper to abbreviate orchestration task specs for brief listi
- Normalizes whitespace and caps spec length at 160 chars, flagging truncation separately from whitespace-only changes - Truncates on UTF-16 code point boundaries to avoid splitting surrogate pairs and emitting malformed strings
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { abbreviateOrchestrationTasks } from './orchestration-task-summary'
|
||||
|
||||
describe('abbreviateOrchestrationTasks', () => {
|
||||
it('collapses whitespace and caps long task specs', () => {
|
||||
const [task] = abbreviateOrchestrationTasks([
|
||||
{ id: 'task_1', spec: `First line\n\n${'detail '.repeat(40)}` }
|
||||
])
|
||||
|
||||
expect(task.id).toBe('task_1')
|
||||
expect(task.spec).not.toContain('\n')
|
||||
expect(task.spec).toHaveLength(160)
|
||||
expect(task.spec.endsWith('…')).toBe(true)
|
||||
expect(task.spec_truncated).toBe(true)
|
||||
})
|
||||
|
||||
it('preserves a short one-line spec', () => {
|
||||
const [task] = abbreviateOrchestrationTasks([{ spec: 'Short task' }])
|
||||
|
||||
expect(task).toEqual({ spec: 'Short task', spec_truncated: false })
|
||||
})
|
||||
|
||||
it('does not report whitespace normalization as truncation', () => {
|
||||
const [task] = abbreviateOrchestrationTasks([{ spec: 'Short\n\n task' }])
|
||||
|
||||
expect(task).toEqual({ spec: 'Short task', spec_truncated: false })
|
||||
})
|
||||
|
||||
it('does not split a surrogate pair at the truncation boundary', () => {
|
||||
// 158 chars + an astral emoji spanning UTF-16 units 158-159: a naive
|
||||
// slice(0, 159) would cut the pair and leave a lone high surrogate.
|
||||
const [task] = abbreviateOrchestrationTasks([{ spec: `${'a'.repeat(158)}😀${'b'.repeat(40)}` }])
|
||||
|
||||
expect(task.spec_truncated).toBe(true)
|
||||
expect(task.spec.isWellFormed()).toBe(true)
|
||||
expect(task.spec.endsWith('…')).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,25 @@
|
||||
const TASK_SPEC_BRIEF_LENGTH = 160
|
||||
|
||||
export function abbreviateOrchestrationTasks<T extends { spec: string }>(
|
||||
tasks: readonly T[]
|
||||
): (T & { spec_truncated: boolean })[] {
|
||||
return tasks.map((task) => {
|
||||
const spec = task.spec.replace(/\s+/g, ' ').trim()
|
||||
const truncated = spec.length > TASK_SPEC_BRIEF_LENGTH
|
||||
return {
|
||||
...task,
|
||||
spec: truncated ? `${truncateAtCodePoint(spec).trimEnd()}…` : spec,
|
||||
// Why: whitespace normalization alone is not truncation; flagging it
|
||||
// would make agents re-fetch full specs that --brief already shows.
|
||||
spec_truncated: truncated
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function truncateAtCodePoint(spec: string): string {
|
||||
const sliced = spec.slice(0, TASK_SPEC_BRIEF_LENGTH - 1)
|
||||
// Why: a cut through a surrogate pair leaves a lone high surrogate that
|
||||
// strict JSON consumers reject; drop it rather than emit malformed UTF-16.
|
||||
const lastUnit = sliced.charCodeAt(sliced.length - 1)
|
||||
return lastUnit >= 0xd800 && lastUnit <= 0xdbff ? sliced.slice(0, -1) : sliced
|
||||
}
|
||||
Reference in New Issue
Block a user