blob: 0b92eeda2526d8e5dbf17dfef4b4e27be2956ee9 [file]
import assert from 'node:assert/strict';
import { describe, test } from 'node:test';
import {
fallbackSessionTitle,
generateSessionTitle,
sessionTitleSource,
} from '../session-title.js';
describe('session title helper', () => {
test('uses display text, strips system reminders, and truncates input on a UTF-8 boundary', () => {
const source = sessionTitleSource({
text: 'model envelope',
displayText: `<system-reminder>secret</system-reminder>\n${'🦊'.repeat(3_000)}`,
});
assert.equal(source.includes('secret'), false);
assert.equal(new TextEncoder().encode(source).length <= 8 * 1024, true);
assert.equal(source.endsWith('�'), false);
});
test('extracts the user message from a raw skill envelope', () => {
assert.equal(
sessionTitleSource({
text: 'Skills loaded below.\n<invoked-skill id="research">\nSECRET INSTRUCTIONS\n</invoked-skill>\n<user-message>\nAnalyze this code\n</user-message>',
}),
'Analyze this code',
);
});
test('builds fallback from the first non-empty line without splitting Unicode code points', () => {
const line = `${'🦊'.repeat(42)}tail`;
assert.equal(fallbackSessionTitle(`\n \n${line}\nignored`), '🦊'.repeat(42));
assert.equal(fallbackSessionTitle(' \n\t'), undefined);
});
test('cleans model reasoning, prefixes, quotes, and extra lines', async () => {
let request: Record<string, unknown> | undefined;
const title = await generateSessionTitle({
model: {} as never,
sourceText: 'Analyze the production logs',
providerOptions: { provider: { required: true } },
generateText: async (options) => {
request = options;
return {
text: '<think>reasoning</think>\nTitle: "Production log analysis"\nextra',
finishReason: 'stop',
};
},
});
assert.equal(title, 'Production log analysis');
assert.equal(request?.maxOutputTokens, 1024);
assert.deepEqual(request?.providerOptions, { provider: { required: true } });
assert.equal('tools' in (request ?? {}), false);
});
test('returns undefined for empty, truncated, invalid, or failed model output', async () => {
const model = {} as never;
assert.equal(
await generateSessionTitle({
model,
sourceText: '',
generateText: async () => ({ text: 'unused', finishReason: 'stop' }),
}),
undefined,
);
assert.equal(
await generateSessionTitle({
model,
sourceText: 'hello',
generateText: async () => ({ text: 'Title', finishReason: 'length' }),
}),
undefined,
);
assert.equal(
await generateSessionTitle({
model,
sourceText: 'hello',
generateText: async () => ({ text: '<think>x</think>', finishReason: 'stop' }),
}),
undefined,
);
assert.equal(
await generateSessionTitle({
model,
sourceText: 'hello',
generateText: async () => {
throw new Error('offline');
},
}),
undefined,
);
});
test('aborts title generation when the provider exceeds its deadline', async () => {
let signal: AbortSignal | undefined;
let watchdog: ReturnType<typeof setTimeout> | undefined;
try {
const result = await Promise.race([
generateSessionTitle({
model: {} as never,
sourceText: 'hello',
timeoutMs: 10,
generateText: (options: Record<string, unknown>) => {
signal = options.abortSignal as AbortSignal;
// Never settles: verifies the internal deadline, not provider cooperation.
return new Promise<never>(() => {});
},
}),
new Promise<never>((_resolve, reject) => {
watchdog = setTimeout(
() => reject(new Error('title generation did not respect its deadline')),
250,
);
}),
]);
assert.equal(result, undefined);
assert.equal(signal?.aborted, true);
} finally {
if (watchdog) clearTimeout(watchdog);
}
});
});