|
@@ -350,6 +350,17 @@ export class ChatService {
|
|
|
* @param agentId 目标容器
|
|
* @param agentId 目标容器
|
|
|
* @returns 是否成功切换到该容器的空白态(容器连接失败时为 false)
|
|
* @returns 是否成功切换到该容器的空白态(容器连接失败时为 false)
|
|
|
*/
|
|
*/
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 是否处于「待建态」:用户点了新建对话、选好容器,但还没发出第一条消息。
|
|
|
|
|
+ *
|
|
|
|
|
+ * 🔴 与「该容器没有会话」是**两种不同状态**,界面提示必须分开:
|
|
|
|
|
+ * · 待建态 → 应该给输入框和欢迎引导,让用户直接开始;
|
|
|
|
|
+ * · 无会话 → 才提示「点击左侧新建对话」。
|
|
|
|
|
+ * 混为一谈会导致:用户点了新建,页面却还在提示「去点新建对话」(死循环)。
|
|
|
|
|
+ */
|
|
|
|
|
+ private readonly _pendingNew = signal(false);
|
|
|
|
|
+ readonly pendingNewSession = this._pendingNew.asReadonly();
|
|
|
|
|
+
|
|
|
async startBlank(agentId: string, workspaceId: string | null = null): Promise<boolean> {
|
|
async startBlank(agentId: string, workspaceId: string | null = null): Promise<boolean> {
|
|
|
await this.open(agentId);
|
|
await this.open(agentId);
|
|
|
if (this._agentId() !== agentId) return false;
|
|
if (this._agentId() !== agentId) return false;
|
|
@@ -364,6 +375,7 @@ export class ChatService {
|
|
|
this._error.set(null);
|
|
this._error.set(null);
|
|
|
this._hasMoreHistory.set(false);
|
|
this._hasMoreHistory.set(false);
|
|
|
this._blankWorkspace = workspaceId;
|
|
this._blankWorkspace = workspaceId;
|
|
|
|
|
+ this._pendingNew.set(true);
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -530,6 +542,8 @@ export class ChatService {
|
|
|
}
|
|
}
|
|
|
if (my !== this.seq) return;
|
|
if (my !== this.seq) return;
|
|
|
this._sessionId.set(sid);
|
|
this._sessionId.set(sid);
|
|
|
|
|
+ // 打开了真实会话 → 退出待建态(否则界面会一直按「还没开始」渲染)
|
|
|
|
|
+ this._pendingNew.set(false);
|
|
|
|
|
|
|
|
const all = this.mapTimeline(
|
|
const all = this.mapTimeline(
|
|
|
rawTimeline.filter((m) => this.belongsToSession(m, sid)),
|
|
rawTimeline.filter((m) => this.belongsToSession(m, sid)),
|
|
@@ -652,6 +666,9 @@ export class ChatService {
|
|
|
this._peerTyping.set(false);
|
|
this._peerTyping.set(false);
|
|
|
this._paginating.set(false);
|
|
this._paginating.set(false);
|
|
|
this._hasMoreHistory.set(false);
|
|
this._hasMoreHistory.set(false);
|
|
|
|
|
+ // 离开聊天页 → 待建态作废(下次进来是新的一次,不该继承上次的空白态)
|
|
|
|
|
+ this._pendingNew.set(false);
|
|
|
|
|
+ this._blankWorkspace = null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
setDraft(text: string): void {
|
|
setDraft(text: string): void {
|
|
@@ -701,7 +718,22 @@ export class ChatService {
|
|
|
*/
|
|
*/
|
|
|
if (!this._sessionId()) {
|
|
if (!this._sessionId()) {
|
|
|
const created = this.ensureSessionForSend();
|
|
const created = this.ensureSessionForSend();
|
|
|
- if (created) this._sessionId.set(created.id);
|
|
|
|
|
|
|
+ if (created) {
|
|
|
|
|
+ this._sessionId.set(created.id);
|
|
|
|
|
+ /*
|
|
|
|
|
+ * 🔴 必须同时把状态从 empty 切到 ready(2026-11-01 修复)。
|
|
|
|
|
+ *
|
|
|
|
|
+ * `startBlank()` 把 state 置为 `'empty'`,而消息区是按 state 分派的:
|
|
|
|
|
+ * `@case ('empty')` 里「没有 currentSession → 显示新建引导」。
|
|
|
|
|
+ * 发完第一条消息后 currentSession 有了,但 state 还是 empty ——
|
|
|
|
|
+ * 页面继续渲染新建流程区,看起来像「发出去没反应」(用户实测反馈)。
|
|
|
|
|
+ *
|
|
|
|
|
+ * 建出会话 = 这已经是正常会话了,状态必须跟着走。
|
|
|
|
|
+ */
|
|
|
|
|
+ this._state.set('ready');
|
|
|
|
|
+ // 会话已建出 → 不再是待建态
|
|
|
|
|
+ this._pendingNew.set(false);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
/*
|
|
/*
|
|
|
* 会话元信息(标题/预览/时间)随**用户发出的消息**推进。
|
|
* 会话元信息(标题/预览/时间)随**用户发出的消息**推进。
|