79 lines
1.9 KiB
TypeScript
79 lines
1.9 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { messageNeedsPhaseReplay, phaseReplayKey } from './taskPhaseReplay';
|
|
|
|
test('running bubble without phases needs replay', () => {
|
|
assert.equal(
|
|
messageNeedsPhaseReplay({
|
|
role: 'assistant',
|
|
taskRunId: 'run-1',
|
|
status: 'streaming_status',
|
|
}),
|
|
true,
|
|
);
|
|
});
|
|
|
|
test('interrupted bubble without phases needs replay', () => {
|
|
assert.equal(
|
|
messageNeedsPhaseReplay({
|
|
role: 'assistant',
|
|
taskRunId: 'run-1',
|
|
status: 'failed',
|
|
errorInfo: {
|
|
userMessage: '中断',
|
|
code: 'TASK_INTERRUPTED',
|
|
class: 'resumable',
|
|
actions: ['continue', 'restart'],
|
|
},
|
|
}),
|
|
true,
|
|
);
|
|
});
|
|
|
|
test('bubble that already has phases is not replayed', () => {
|
|
assert.equal(
|
|
messageNeedsPhaseReplay({
|
|
role: 'assistant',
|
|
taskRunId: 'run-1',
|
|
status: 'streaming_status',
|
|
phaseEvents: [{ step: 'squad_assembly', icon: '👥', label: '组建小队', status: 'running' }],
|
|
}),
|
|
false,
|
|
);
|
|
});
|
|
|
|
test('completed bubble without snapshot needs replay for legacy rows', () => {
|
|
assert.equal(
|
|
messageNeedsPhaseReplay({
|
|
role: 'assistant',
|
|
taskRunId: 'run-legacy',
|
|
status: 'completed',
|
|
}),
|
|
true,
|
|
);
|
|
});
|
|
|
|
test('completed bubble with snapshot is not replayed', () => {
|
|
assert.equal(
|
|
messageNeedsPhaseReplay({
|
|
role: 'assistant',
|
|
taskRunId: 'run-new',
|
|
status: 'completed',
|
|
phaseSnapshot: {
|
|
steps: [{ step: 'squad_assembly', icon: '👥', label: '组建小队', status: 'completed' }],
|
|
},
|
|
}),
|
|
false,
|
|
);
|
|
});
|
|
|
|
test('phase replay key ignores completed chatter', () => {
|
|
assert.equal(
|
|
phaseReplayKey([
|
|
{ id: 'a', role: 'user', status: 'completed' },
|
|
{ id: 'b', role: 'assistant', taskRunId: 'run-9', status: 'streaming_status' },
|
|
]),
|
|
'b:run-9:streaming_status',
|
|
);
|
|
});
|