mirror of
https://github.com/stablyai/orca.git
synced 2026-09-23 08:02:31 +00:00
* fix(naming): remove identifier-first name post-processing Workspace display names and tab titles were being rewritten after generation by prompt-scanning heuristics from #8238 — a stray "#1" in prose became a workspace named "#1 - Fix", and the rewrite ran downstream of generation so user naming instructions couldn't override it. Per the same principle as #9088, naming defaults stay minimal and user overrides own the style. - Delete work-item-reference.ts and display-name-from-work.ts (+tests). - Auto-rename display names return to the humanized branch slug; tab titles return to the cleaned first prompt clause. - Explicit create-from-work-item naming returns to action-first ("Review PR 1234"). - Keep #8238's URL-before-markdown strip-order bugfix in tab titles, with regression tests adjusted to the natural expectations. * test(naming): pin incidental marker regression
89 lines
3.2 KiB
TypeScript
89 lines
3.2 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
import {
|
|
deriveGeneratedTabTitle,
|
|
GENERATED_TAB_TITLE_MAX_LENGTH,
|
|
GENERATED_TAB_TITLE_SOURCE_SCAN_LIMIT
|
|
} from './agent-tab-title'
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
describe('deriveGeneratedTabTitle', () => {
|
|
it('derives a short title from the first useful prompt clause', () => {
|
|
expect(
|
|
deriveGeneratedTabTitle('Can you please refactor the auth middleware to use JWT tokens?')
|
|
).toBe('Refactor the auth middleware to use JWT')
|
|
})
|
|
|
|
it('strips markup, links, emoji, and punctuation without promoting incidental markers', () => {
|
|
expect(
|
|
deriveGeneratedTabTitle(
|
|
'Please fix auth note #1 with `src/auth.ts`!!! https://example.com 🔥'
|
|
)
|
|
).toBe('Fix auth note 1 with src auth')
|
|
})
|
|
|
|
it('preserves non-ASCII title text while folding Unicode whitespace', () => {
|
|
expect(deriveGeneratedTabTitle('Please 修正\u00a0résumé\t検索\u3000123!!!')).toBe(
|
|
'修正 résumé 検索 123'
|
|
)
|
|
})
|
|
|
|
it('keeps useful text after common issue prefixes', () => {
|
|
expect(deriveGeneratedTabTitle('Issue #2056: Opt-in generated tab titles for agents')).toBe(
|
|
'Opt in generated tab titles for agents'
|
|
)
|
|
})
|
|
|
|
it('strips a URL containing underscores intact', () => {
|
|
expect(
|
|
deriveGeneratedTabTitle('inspect https://gitlab.com/g/p/-/work_items/9 then report')
|
|
).toBe('Inspect then report')
|
|
})
|
|
|
|
it('strips a URL wrapped in markdown emphasis without leaking fragments', () => {
|
|
const title = deriveGeneratedTabTitle('Review _https://github.com/o/r/pull/5_ now')
|
|
expect(title).toBe('Review now')
|
|
expect(title).not.toMatch(/https|pull/)
|
|
})
|
|
|
|
it('bounds titles to the maximum length without adding punctuation', () => {
|
|
const title = deriveGeneratedTabTitle(
|
|
'I want to replace the terminal reconnection hydration flow with a safer retry path'
|
|
)
|
|
|
|
expect(title).toBeTruthy()
|
|
expect(title!.length).toBeLessThanOrEqual(GENERATED_TAB_TITLE_MAX_LENGTH)
|
|
expect(title).toMatch(/^[\p{L}\p{N}\s]+$/u)
|
|
})
|
|
|
|
it('returns null when the prompt has no useful title text', () => {
|
|
expect(deriveGeneratedTabTitle('please!!!')).toBeNull()
|
|
})
|
|
|
|
it('bounds normalization work for paste-sized prompts before truncating the title', () => {
|
|
const replaceSpy = vi.spyOn(String.prototype, 'replace')
|
|
const splitSpy = vi.spyOn(String.prototype, 'split')
|
|
const prompt = `Please fix \`src/auth.ts\` ${'large pasted text '.repeat(5000)}`
|
|
|
|
const title = deriveGeneratedTabTitle(prompt)
|
|
|
|
expect(title).toBeTruthy()
|
|
expect(title!.length).toBeLessThanOrEqual(GENERATED_TAB_TITLE_MAX_LENGTH)
|
|
const replaceContextLengths = replaceSpy.mock.contexts.map((context) => String(context).length)
|
|
const splitContextLengths = splitSpy.mock.contexts.map((context) => String(context).length)
|
|
expect(Math.max(...replaceContextLengths)).toBeLessThanOrEqual(
|
|
GENERATED_TAB_TITLE_SOURCE_SCAN_LIMIT
|
|
)
|
|
expect(Math.max(...splitContextLengths)).toBeLessThanOrEqual(
|
|
GENERATED_TAB_TITLE_SOURCE_SCAN_LIMIT
|
|
)
|
|
expect(
|
|
replaceSpy.mock.calls.filter(
|
|
([pattern]) => pattern instanceof RegExp && pattern.source === '\\s+'
|
|
)
|
|
).toHaveLength(0)
|
|
})
|
|
})
|