删掉聊天 reducer 里没人读的订阅身份与首屏锚点

- DirectThreadChatState 去掉 subscriptionId 与 lastCompletedItemId 两个只写不读的字段
- resolveDirectThreadBootstrap 只把 bootstrap 事件 reduce 进状态,不再顺带写入这两个字段
- directThreadChat 单测改成断言聊天状态里不再出现这两个字段(bootstrap 载荷本身不变)
This commit is contained in:
2026-09-17 00:05:57 +08:00
parent 098693636a
commit 1b40f030e7
2 changed files with 6 additions and 16 deletions
@@ -32,9 +32,6 @@ export type DirectChatEntry = {
}; };
export type DirectThreadChatState = { export type DirectThreadChatState = {
subscriptionId: string | null;
/** 首屏历史锚点:`subscribe` 给出的最后一条完成条目 id。 */
lastCompletedItemId: string | null;
/** 最新回合是否还在跑;只由生命周期事件的先后决定。 */ /** 最新回合是否还在跑;只由生命周期事件的先后决定。 */
turnRunning: boolean; turnRunning: boolean;
/** 历史切片条目,保持文件顺序。 */ /** 历史切片条目,保持文件顺序。 */
@@ -45,8 +42,6 @@ export type DirectThreadChatState = {
export function emptyDirectThreadChatState(): DirectThreadChatState { export function emptyDirectThreadChatState(): DirectThreadChatState {
return { return {
subscriptionId: null,
lastCompletedItemId: null,
turnRunning: false, turnRunning: false,
history: [], history: [],
live: [], live: [],
@@ -197,20 +192,14 @@ export function reduceDirectThreadEvents(
/** /**
* bootstrap 是运行态的唯一权威:游标已在队尾,返回的事件就是此刻要处理的事件。 * bootstrap 是运行态的唯一权威:游标已在队尾,返回的事件就是此刻要处理的事件。
* *
* 历史窗口保留:bootstrap 不重新回读历史切片,那是 `lastCompletedItemId` 的职责。 * 订阅身份与首屏历史锚点(`subscriptionId` / `lastCompletedItemId`)是订阅循环自己的局部
* 事实,不进聊天状态:这里只把 bootstrap 事件 reduce 进现有状态。
*/ */
export function resolveDirectThreadBootstrap( export function resolveDirectThreadBootstrap(
state: DirectThreadChatState, state: DirectThreadChatState,
bootstrap: DirectThreadSubscriptionBootstrap, bootstrap: DirectThreadSubscriptionBootstrap,
): DirectThreadChatState { ): DirectThreadChatState {
return reduceDirectThreadEvents( return reduceDirectThreadEvents(state, bootstrap.events);
{
...state,
subscriptionId: bootstrap.subscriptionId,
lastCompletedItemId: bootstrap.lastCompletedItemId ?? null,
},
bootstrap.events,
);
} }
/** 事件顺序 = 游标顺序;调用方只需要把 `consume` 的结果喂进来。 */ /** 事件顺序 = 游标顺序;调用方只需要把 `consume` 的结果喂进来。 */
@@ -80,8 +80,9 @@ describe('DirectProject 聊天 reducer', () => {
], ],
}, },
); );
expect(bootstrapped.subscriptionId).toBe('sub-1'); // 订阅身份与首屏锚点由订阅循环自己持有,不写进聊天 reducer 状态。
expect(bootstrapped.lastCompletedItemId).toBe('msg-9'); expect(bootstrapped).not.toHaveProperty('subscriptionId');
expect(bootstrapped).not.toHaveProperty('lastCompletedItemId');
expect(bootstrapped.turnRunning).toBe(true); expect(bootstrapped.turnRunning).toBe(true);
expect(selectDirectChatEntries(bootstrapped)).toHaveLength(1); expect(selectDirectChatEntries(bootstrapped)).toHaveLength(1);
}); });