@optima-chat/agentic-sdk 0.37.0 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/client/gateway-client.d.ts +8 -0
  2. package/dist/client/gateway-client.d.ts.map +1 -1
  3. package/dist/client/gateway-client.js +7 -1
  4. package/dist/client/gateway-client.js.map +1 -1
  5. package/dist/client/outbound-queue.d.ts +119 -0
  6. package/dist/client/outbound-queue.d.ts.map +1 -0
  7. package/dist/client/outbound-queue.js +383 -0
  8. package/dist/client/outbound-queue.js.map +1 -0
  9. package/dist/client/processing-events.d.ts +1 -1
  10. package/dist/hooks/use-abort-with-escape-hatch.d.ts +13 -2
  11. package/dist/hooks/use-abort-with-escape-hatch.d.ts.map +1 -1
  12. package/dist/hooks/use-abort-with-escape-hatch.js +14 -3
  13. package/dist/hooks/use-abort-with-escape-hatch.js.map +1 -1
  14. package/dist/hooks/use-connection-state.d.ts.map +1 -1
  15. package/dist/hooks/use-connection-state.js +5 -2
  16. package/dist/hooks/use-connection-state.js.map +1 -1
  17. package/dist/hooks/use-current-chat.d.ts +24 -0
  18. package/dist/hooks/use-current-chat.d.ts.map +1 -1
  19. package/dist/hooks/use-current-chat.js +73 -15
  20. package/dist/hooks/use-current-chat.js.map +1 -1
  21. package/dist/index.d.ts +3 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/provider/chat-context.d.ts +6 -0
  26. package/dist/provider/chat-context.d.ts.map +1 -1
  27. package/dist/provider/chat-context.js.map +1 -1
  28. package/dist/provider/chat-provider.d.ts +13 -0
  29. package/dist/provider/chat-provider.d.ts.map +1 -1
  30. package/dist/provider/chat-provider.js +42 -2
  31. package/dist/provider/chat-provider.js.map +1 -1
  32. package/dist/store/chat-store.d.ts +32 -0
  33. package/dist/store/chat-store.d.ts.map +1 -1
  34. package/dist/store/chat-store.js +72 -0
  35. package/dist/store/chat-store.js.map +1 -1
  36. package/dist/types.d.ts +13 -0
  37. package/dist/types.d.ts.map +1 -1
  38. package/dist/version.d.ts +1 -1
  39. package/dist/version.js +1 -1
  40. package/package.json +1 -1
@@ -0,0 +1,383 @@
1
+ /** 每会话队列上限(🅳5)。 */
2
+ export const QUEUE_LIMIT = 5;
3
+ const EMPTY_QUEUE = Object.freeze([]);
4
+ const EMPTY_IDS = Object.freeze([]);
5
+ const queueOf = (s, conv) => s.outbound.queue[conv] ?? EMPTY_QUEUE;
6
+ const outstandingOf = (s, conv) => s.outbound.outstanding[conv] ?? EMPTY_IDS;
7
+ /** 服务端事件说 C 在跑(processing 集合)。 */
8
+ const busy = (s, conv) => s.processingConversationIds.has(conv);
9
+ /** 别的会话在跑(放 C 会撞 `CONCURRENT_CONVERSATION_BLOCKED`)。 */
10
+ const anyOtherBusy = (s, conv) => [...s.processingConversationIds].some((c) => c !== conv);
11
+ /** C 是当前会话且全局 flag 举着(派发即置 thinking,首个事件未到时 processing 还没有它)。 */
12
+ const isCurrentActive = (s, conv) => conv === s.currentConversationId && (s.isStreaming || s.isThinking);
13
+ /**
14
+ * 新消息是否必须入队(plan v1.2 裁定 5)。在途项受 Δ10 门控:本 session 从未见过带
15
+ * `clientMsgId` 的 finish(老 gateway)时忽略原始账本 —— 否则 id 永不删除 ⇒ 空闲也入队。
16
+ */
17
+ export function selectMustQueue(s, conv) {
18
+ return (queueOf(s, conv).length > 0 ||
19
+ busy(s, conv) ||
20
+ isCurrentActive(s, conv) ||
21
+ (s.outbound.turnCmidSupported && outstandingOf(s, conv).length > 0));
22
+ }
23
+ /** hook 暴露的在途数(Δ10 门控后的值;停止键 / 逃生口 busy 都读它)。 */
24
+ export function selectOutstandingCount(s, conv) {
25
+ return s.outbound.turnCmidSupported ? outstandingOf(s, conv).length : 0;
26
+ }
27
+ /**
28
+ * 「这个会话的队列会不会自己放」(Δ12:⛔ 含 `turnCmidSupported` 合取项 —— 新 session 首个
29
+ * 回合里入队的条目**会**被首条带 cmid 的 finish 放出)。四个合取项各挡一种「标签撒谎」:
30
+ * 账空(结构上已无边沿)/ 抑制位在场(下一个边沿只删不放)/ 他会话在忙(边沿不放)/
31
+ * 本会话既不忙也不活跃(幻影账:服务端其实没在跑)。
32
+ */
33
+ export function selectWillAutoDrain(s, conv) {
34
+ return (outstandingOf(s, conv).length > 0 &&
35
+ s.outbound.localAbortPending[conv] !== true &&
36
+ !anyOtherBusy(s, conv) &&
37
+ (busy(s, conv) || isCurrentActive(s, conv)));
38
+ }
39
+ /** terminatedIds 每会话保留条数(LRU)。 */
40
+ const TERMINATED_LRU = 50;
41
+ /** outbox `failed` 的这四种 cause 出账(plan v1.2 裁定 6);arm_timeout / disarm 会被再武装自动复活重投,不处理。 */
42
+ const DELIVERY_FAILED_CAUSES = new Set(['timeout_exhaust', 'transient_exhaust', 'terminal', 'conn_terminal']);
43
+ /** Δ3:只发 error、不跟 finish 的两种终止(spec v1.6.1 F17)。 */
44
+ const ERROR_ONLY_TERMINATION_CODES = new Set(['RESPONSE_TIMEOUT', 'CONTAINER_RECYCLED']);
45
+ /** Δ15:token 类 error 抑制下一个边沿。 */
46
+ const TOKEN_ERROR_CODES = new Set(['TOKEN_ROTATED', 'TOKEN_POOL_DRY']);
47
+ export class OutboundQueue {
48
+ deps;
49
+ /** 已观察到回合终态(R2 的 `∈` 删)的 id,每会话 LRU —— 只拦「已终结 id 被 outbox 重投复活」。 */
50
+ terminatedIds = new Map();
51
+ /** `track()` 过的 id → 会话。R1 / E3 只认它们;任何出账都**不**从这里移除。 */
52
+ tracked = new Map();
53
+ constructor(deps) {
54
+ this.deps = deps;
55
+ }
56
+ st() {
57
+ return this.deps.store.getState();
58
+ }
59
+ // ── 查询 ──
60
+ mustQueue(conv) {
61
+ return selectMustQueue(this.st(), conv);
62
+ }
63
+ list(conv) {
64
+ return queueOf(this.st(), conv);
65
+ }
66
+ outstandingCount(conv) {
67
+ return selectOutstandingCount(this.st(), conv);
68
+ }
69
+ willAutoDrain(conv) {
70
+ return selectWillAutoDrain(this.st(), conv);
71
+ }
72
+ // ── 用户出口 ──
73
+ /** 追加到队尾(I6);满 ⇒ `'queue_full'`、队列不变。 */
74
+ enqueue(entry) {
75
+ const conv = entry.conversationId;
76
+ const cur = this.list(conv);
77
+ if (cur.length >= QUEUE_LIMIT)
78
+ return 'queue_full';
79
+ this.track(entry.messageId, conv);
80
+ this.st().setOutboundQueue(conv, [...cur, entry]);
81
+ return 'queued';
82
+ }
83
+ /** 按 id 出队(任意位置);不在队里 ⇒ false。 */
84
+ cancel(id) {
85
+ const entry = this.findQueued(id);
86
+ if (!entry)
87
+ return false;
88
+ this.dequeue(entry.conversationId, id);
89
+ return true;
90
+ }
91
+ /**
92
+ * 用户「立即发送」:放出**该条**(不必是队头),不看谓词。起新回合(放出前本会话空闲)才写
93
+ * `lastRelease`(Δ6 第②写点)—— 空闲判定**必须在放出之前快照**:真 provider 里 `send()`
94
+ * 入 outbox 后同步派发、经 `onMessageDispatched` 置 `isThinking`,放出后再判恒为「不空闲」。
95
+ */
96
+ sendNow(id) {
97
+ const entry = this.findQueued(id);
98
+ if (!entry)
99
+ return false;
100
+ const conv = entry.conversationId;
101
+ const s = this.st();
102
+ const wasIdle = !busy(s, conv) && !isCurrentActive(s, conv);
103
+ const ok = this.releaseOne(entry);
104
+ if (ok && wasIdle)
105
+ this.writeLastRelease(conv);
106
+ return ok;
107
+ }
108
+ // ── R1 记账 ──
109
+ track(id, conv) {
110
+ this.tracked.set(id, conv);
111
+ }
112
+ /** R1:`send()` 入 outbox 时与每次 dispatch 各调一次 ⇒ 幂等(已在账不重复追加)。 */
113
+ onMessageAccepted(id, conv) {
114
+ if (id === '' || !this.tracked.has(id))
115
+ return;
116
+ if (this.isTerminated(conv, id))
117
+ return;
118
+ const ids = outstandingOf(this.st(), conv);
119
+ if (ids.includes(id))
120
+ return;
121
+ this.st().setOutstanding(conv, [...ids, id]);
122
+ }
123
+ /** outbox `failed`:四种 cause 出账(⛔ 记 terminatedIds —— 该消息仍可能被 retry 重投;⛔ 评估)。 */
124
+ onDeliveryFailed(id, cause) {
125
+ if (cause === undefined || !DELIVERY_FAILED_CAUSES.has(cause))
126
+ return;
127
+ this.dropFromAnyLedger(id);
128
+ }
129
+ // ── 入站事件(provider 定序:handleServerEvent → coordinator → 本方法) ──
130
+ onServerEvent(event) {
131
+ const f = (event ?? {});
132
+ if (f.type === 'finish')
133
+ this.onFinish(f);
134
+ else if (f.type === 'error')
135
+ this.onError(f);
136
+ else if (f.type === 'billing_error')
137
+ this.onBillingError(f);
138
+ else if (f.type === 'session_ready')
139
+ this.onSessionReady(f.session ?? {});
140
+ }
141
+ // ── 收尾 ──
142
+ /** 逃生口(`settleStuckTurn(C,'escape_hatch')` 的队列腿):清账、⛔ 评估、⛔ 动抑制位。 */
143
+ onSettle(conv) {
144
+ this.st().setOutstanding(conv, []);
145
+ }
146
+ /** 会话删除 / 重置:清该会话的三张 store 表与两张私有表。 */
147
+ onConversationGone(conv) {
148
+ this.st().clearOutbound(conv);
149
+ this.terminatedIds.delete(conv);
150
+ for (const [id, c] of this.tracked)
151
+ if (c === conv)
152
+ this.tracked.delete(id);
153
+ }
154
+ /** `startNewSession`:清全部(含 `turnCmidSupported`)。 */
155
+ onSessionReset() {
156
+ this.st().clearOutbound();
157
+ this.terminatedIds.clear();
158
+ this.tracked.clear();
159
+ }
160
+ // ── 内部 ──
161
+ /**
162
+ * Δ17 / R2 / R3 / R5 / Δ14。唯一的自动放帧边沿:带 `finish.clientMsgId` 的 finish,该 id ∈ 本会话
163
+ * 在途账,删除使账**恰好变空**,且两道守卫都不成立。
164
+ */
165
+ onFinish(f) {
166
+ const conv = typeof f.conversation_id === 'string' ? f.conversation_id : undefined;
167
+ if (f.finish?.reason === 'duplicate') {
168
+ // Δ17(spec v1.6.6,取代旧 R2 的 duplicate 腿):gateway 只在原回合**不在飞**时发 dup finish,且只带
169
+ // 顶层 client_msg_id ⇒ 按 id 在所有会话的账里出账(同 Δ13);⛔ 记 terminatedIds、⛔ 评估、⛔ 动抑制位、
170
+ // ⛔ 翻 turnCmidSupported。不在账 / 无 id ⇒ 什么都不做。整条排在 R3 与 Δ14 之前(真实 dup 帧过不了 R3)。
171
+ const dupId = typeof f.client_msg_id === 'string' ? f.client_msg_id : f.finish.clientMsgId;
172
+ if (typeof dupId === 'string')
173
+ this.dropFromAnyLedger(dupId);
174
+ return;
175
+ }
176
+ const cmid = f.finish?.clientMsgId;
177
+ if (typeof cmid !== 'string')
178
+ return; // R3:不带 clientMsgId 的 finish 不动集合、不评估、不消费抑制位
179
+ let droppedPreFlip = false;
180
+ if (!this.st().outbound.turnCmidSupported) {
181
+ droppedPreFlip = this.dropPreFlip(conv, cmid); // Δ14:先丢翻转前的账,再按 R2 处理本条
182
+ this.st().setTurnCmidSupported(true);
183
+ }
184
+ if (conv === undefined)
185
+ return;
186
+ const ids = outstandingOf(this.st(), conv);
187
+ if (!ids.includes(cmid))
188
+ return; // ∉(别的 tab / 已清掉后迟到):什么都不做
189
+ const rest = ids.filter((x) => x !== cmid);
190
+ this.st().setOutstanding(conv, rest);
191
+ this.markTerminated(conv, cmid); // 只有这里记 terminatedIds
192
+ if (rest.length > 0)
193
+ return; // 未使账恰好变空:不是边沿候选(⛔ 消费抑制位)
194
+ if (this.st().outbound.localAbortPending[conv] === true) {
195
+ this.st().setLocalAbortPending(conv, false); // R5 消费点 + 守卫①
196
+ return;
197
+ }
198
+ if (f.finish?.reason === 'abort')
199
+ return; // 守卫②:非本地的 abort 终态(watchdog / 回收等)
200
+ if (droppedPreFlip)
201
+ return; // Δ14:触发会话确有 id 被丢 ⇒ 本次不评估
202
+ this.evaluate(conv);
203
+ }
204
+ /**
205
+ * Δ14:`turnCmidSupported` 由假翻真时丢弃翻转前的账(⛔ 记 terminatedIds)。触发会话只丢排在
206
+ * `cmid` 之前入账的(之后入账的是真在途);`cmid` 不在触发会话账里 ⇒ 该会话一条不丢;
207
+ * 其它会话全部丢弃。返回「触发会话里确有 id 被丢」。
208
+ */
209
+ dropPreFlip(conv, cmid) {
210
+ let droppedInTrigger = false;
211
+ for (const [c, ids] of Object.entries(this.st().outbound.outstanding)) {
212
+ if (c !== conv) {
213
+ this.st().setOutstanding(c, []);
214
+ continue;
215
+ }
216
+ const at = ids.indexOf(cmid);
217
+ if (at <= 0)
218
+ continue; // -1:不在账 ⇒ 一条不丢;0:之前没有
219
+ this.st().setOutstanding(c, ids.slice(at));
220
+ droppedInTrigger = true;
221
+ }
222
+ return droppedInTrigger;
223
+ }
224
+ onError(f) {
225
+ const conv = typeof f.conversation_id === 'string' ? f.conversation_id : undefined;
226
+ const code = f.error?.code;
227
+ if (f.client_msg_id !== undefined) {
228
+ // Δ13:带顶层 cmid 的拒绝 error ⇒ 按 id 在所有会话的账里出账(⛔ 记 terminatedIds、⛔ 评估、⛔ 动抑制位)
229
+ if (typeof f.client_msg_id === 'string')
230
+ this.dropFromAnyLedger(f.client_msg_id);
231
+ }
232
+ else if (conv !== undefined && typeof code === 'string' && ERROR_ONLY_TERMINATION_CODES.has(code)) {
233
+ // Δ3:error-only 终止 ⇒ 清该会话的账(同 settle)
234
+ this.st().setOutstanding(conv, []);
235
+ }
236
+ // Δ15:token 类 error ⇒ 下一个使账恰好变空的 ∈ 删只删不放
237
+ if (conv !== undefined && typeof code === 'string' && TOKEN_ERROR_CODES.has(code)) {
238
+ this.st().setLocalAbortPending(conv, true);
239
+ }
240
+ }
241
+ /** Δ13 的 billing_error 腿:只认 outbox 按 transient 重试的那类(= delivery-outbox `billingIsTransient`)。 */
242
+ onBillingError(f) {
243
+ if (typeof f.client_msg_id !== 'string')
244
+ return;
245
+ if (f.billing?.reason !== 'rate_limited')
246
+ return;
247
+ this.dropFromAnyLedger(f.client_msg_id);
248
+ }
249
+ /**
250
+ * `session_ready`:**先 E3、后 Δ16**,都 ⛔ 评估。E3 只补 pending、Δ16 只删 delivered,正确实现下
251
+ * 作用对象不相交;定死先后是为了让「Δ16 连 pending 也删」这种错写法不被 E3 当场补回而隐身。
252
+ */
253
+ onSessionReady(session) {
254
+ // E3:把 tracked 且未终结的 pending 消息补回账(outbox 会重投它们)
255
+ const s = this.st();
256
+ for (const [conv, msgs] of Object.entries(s.messages)) {
257
+ const ids = outstandingOf(this.st(), conv);
258
+ const add = msgs
259
+ .filter((m) => m.deliveryState === 'pending' && this.tracked.has(m.id) && !this.isTerminated(conv, m.id))
260
+ .map((m) => m.id)
261
+ .filter((id) => !ids.includes(id));
262
+ if (add.length > 0)
263
+ this.st().setOutstanding(conv, [...ids, ...add]);
264
+ }
265
+ // Δ16:服务端说它不在飞 ⇒ 删已送达的幻影(键缺席 ⇒ 整条不做;豁免同 reconcileInFlightTurn)
266
+ if (!('inFlightTurnConversationId' in session))
267
+ return;
268
+ const inFlight = session['inFlightTurnConversationId'] ?? null;
269
+ const active = session['activeConversation']?.conversationId ?? null;
270
+ for (const [conv, ids] of Object.entries(this.st().outbound.outstanding)) {
271
+ if (conv === inFlight)
272
+ continue;
273
+ if (conv === active)
274
+ continue;
275
+ const msgs = this.st().messages[conv] ?? [];
276
+ const delivered = new Set(msgs.filter((m) => m.deliveryState === 'delivered').map((m) => m.id));
277
+ const rest = ids.filter((id) => !delivered.has(id));
278
+ if (rest.length !== ids.length)
279
+ this.st().setOutstanding(conv, rest);
280
+ }
281
+ }
282
+ /**
283
+ * canDrain:队列非空 ∧ 账空 ∧ 本会话不在 processing ∧ 他会话都不在 processing ∧ 本会话没有
284
+ * tracked 且仍 pending 的消息(Δ13 配套:正在 outbox 重试的消息不在账里,⛔ 被越过)。
285
+ */
286
+ canDrain(conv) {
287
+ const s = this.st();
288
+ return (queueOf(s, conv).length > 0 &&
289
+ outstandingOf(s, conv).length === 0 &&
290
+ !busy(s, conv) &&
291
+ !anyOtherBusy(s, conv) &&
292
+ !this.hasTrackedPending(conv));
293
+ }
294
+ /** 评估:只评估触发边沿的那个会话,最多放一条(队头);放出即写 lastRelease(Δ6 第①写点)。 */
295
+ evaluate(conv) {
296
+ if (!this.canDrain(conv))
297
+ return;
298
+ const head = queueOf(this.st(), conv)[0];
299
+ if (head && this.releaseOne(head))
300
+ this.writeLastRelease(conv);
301
+ }
302
+ /**
303
+ * 放出一条:`addMessage` → `send(structuredClone(frame))`(disarmed 分支会原地剥 cmid)→ 返 false 撤回留队。
304
+ * 克隆或出网抛错(如 `metadata` 里有函数 ⇒ `DataCloneError`)同「返 false」:撤回气泡、留队、⛔ 抛出
305
+ * (自动边沿跑在 provider 的 `onEvent` 里,抛出会逃出 `ws.onmessage` 并留下气泡 + 队列条目两份)。
306
+ */
307
+ releaseOne(entry) {
308
+ const conv = entry.conversationId;
309
+ this.st().addMessage(conv, {
310
+ id: entry.messageId,
311
+ conversationId: conv,
312
+ role: 'user',
313
+ content: entry.content,
314
+ toolCalls: [],
315
+ ...(entry.attachments && entry.attachments.length > 0 ? { attachments: entry.attachments } : {}),
316
+ status: 'complete',
317
+ createdAt: this.deps.now(),
318
+ });
319
+ let ok;
320
+ try {
321
+ ok = this.deps.send(structuredClone(entry.frame));
322
+ }
323
+ catch {
324
+ ok = false;
325
+ }
326
+ if (!ok) {
327
+ this.st().removeMessage(conv, entry.messageId);
328
+ return false;
329
+ }
330
+ this.dequeue(conv, entry.messageId);
331
+ return true;
332
+ }
333
+ writeLastRelease(conv) {
334
+ const prev = this.st().outbound.lastRelease;
335
+ this.st().setLastRelease({ seq: (prev?.seq ?? 0) + 1, conversationId: conv, at: this.deps.now() });
336
+ }
337
+ findQueued(id) {
338
+ for (const list of Object.values(this.st().outbound.queue)) {
339
+ const hit = list.find((e) => e.messageId === id);
340
+ if (hit)
341
+ return hit;
342
+ }
343
+ return undefined;
344
+ }
345
+ dequeue(conv, id) {
346
+ const cur = queueOf(this.st(), conv);
347
+ if (!cur.some((e) => e.messageId === id))
348
+ return;
349
+ this.st().setOutboundQueue(conv, cur.filter((e) => e.messageId !== id));
350
+ }
351
+ /** 按 id 在所有会话的账里出账(⛔ 记 terminatedIds、⛔ 评估)。 */
352
+ dropFromAnyLedger(id) {
353
+ for (const [conv, ids] of Object.entries(this.st().outbound.outstanding)) {
354
+ if (ids.includes(id))
355
+ this.st().setOutstanding(conv, ids.filter((x) => x !== id));
356
+ }
357
+ }
358
+ hasTrackedPending(conv) {
359
+ return (this.st().messages[conv] ?? []).some((m) => m.deliveryState === 'pending' && this.tracked.has(m.id));
360
+ }
361
+ isTerminated(conv, id) {
362
+ return this.terminatedIds.get(conv)?.includes(id) ?? false;
363
+ }
364
+ markTerminated(conv, id) {
365
+ const next = (this.terminatedIds.get(conv) ?? []).filter((x) => x !== id);
366
+ next.push(id);
367
+ if (next.length > TERMINATED_LRU)
368
+ next.splice(0, next.length - TERMINATED_LRU);
369
+ this.terminatedIds.set(conv, next);
370
+ }
371
+ }
372
+ /**
373
+ * provider 用:`getClient` 惰性(读 `clientRef.current`)—— 队列在 `useMemo` 里先于
374
+ * `new GatewayClient` 创建;client 为 null 时 `send` 退化成「发不出去」(放出失败 ⇒ 撤回留队)。
375
+ */
376
+ export function createOutboundQueue(store, getClient) {
377
+ return new OutboundQueue({
378
+ store,
379
+ send: (frame) => getClient()?.send(frame) ?? false,
380
+ now: () => Date.now(),
381
+ });
382
+ }
383
+ //# sourceMappingURL=outbound-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound-queue.js","sourceRoot":"","sources":["../../src/client/outbound-queue.ts"],"names":[],"mappings":"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"}
@@ -3,5 +3,5 @@
3
3
  * When any of these arrives with a `conversation_id`, the id joins
4
4
  * `processingConversationIds`. See Spec 2.9.
5
5
  */
6
- export declare const PROCESSING_ADD_EVENTS: Set<"finish" | "error" | "info" | "warning" | "content" | "progress" | "session_ready" | "message_receipt" | "token_refresh_needed" | "billing_error" | "restore_conversations" | "init" | "ready" | "thinking" | "text_delta" | "tool_call" | "tool_result" | "tool_progress" | "ask_question" | "approval_request" | "conversation_update" | "session_recovering" | "session_recovered" | "pong" | "conversation_title_updated" | "skills_synced" | "skills_sync_error" | "restore_started" | "restore_complete" | "restore_failed" | "client_upgrade_required" | "resigned" | "adopted" | "permission_decision" | "subagent_progress" | "task_started" | "task_completed" | "task_failed" | "task_schedule_updated" | "briefing_published">;
6
+ export declare const PROCESSING_ADD_EVENTS: Set<"finish" | "error" | "info" | "warning" | "session_ready" | "message_receipt" | "token_refresh_needed" | "billing_error" | "restore_conversations" | "init" | "content" | "ready" | "thinking" | "text_delta" | "tool_call" | "tool_result" | "tool_progress" | "ask_question" | "approval_request" | "progress" | "conversation_update" | "session_recovering" | "session_recovered" | "pong" | "conversation_title_updated" | "skills_synced" | "skills_sync_error" | "restore_started" | "restore_complete" | "restore_failed" | "client_upgrade_required" | "resigned" | "adopted" | "permission_decision" | "subagent_progress" | "task_started" | "task_completed" | "task_failed" | "task_schedule_updated" | "briefing_published">;
7
7
  //# sourceMappingURL=processing-events.d.ts.map
@@ -49,6 +49,9 @@
49
49
  * 用户看到的是「前半段标着失败 + 后半段另起一条」。这一项在设计定稿时**漏登记了**,
50
50
  * 见 `composer-wedge-reconcile-917.test.ts` 的 X1 特征用例(钉的是已知边界,不是期望行为)。
51
51
  *
52
+ * sdk#158 起,帧未出网(`send()` 返 false)**不武装**:「10 秒拿不到回执」的推断只在帧确实
53
+ * 出网之后才成立;`abort()` 用返回值告诉消费方(false = 有会话且未出网)。
54
+ *
52
55
  * 窗口维持在 10 秒(拉长要连带改 toast 的出现时机,属 UX 改动)。
53
56
  *
54
57
  * ## 取消条件(两条,照搬今天 agentic-chat 里那个定时器的语义)
@@ -78,8 +81,16 @@ export interface UseAbortWithEscapeHatchOptions {
78
81
  onEscape?: (conversationId: string) => void;
79
82
  }
80
83
  export interface UseAbortWithEscapeHatchResult {
81
- /** 替代 `useCurrentChat().abort` 调用:发 abort 帧 + 武装逃生口定时器。 */
82
- abort: () => void;
84
+ /**
85
+ * 替代 `useCurrentChat().abort` 调用:发 abort 帧 + 武装逃生口定时器。
86
+ *
87
+ * 返回值(sdk#158):**返 false 当且仅当「有当前会话且 abort 帧未出网」**(`client.send()`
88
+ * 返 false:socket 非 OPEN、或 `onBeforeSend` 拦下)。此时**不武装**逃生口、不改任何本地态——
89
+ * 帧没到服务端,「10 秒没回执」不构成任何推断的前提;消费方拿它提示「未连接,请稍后重试」。
90
+ * 帧出网返 true;无当前会话时不发帧、不武装(既有行为),也返 true——那不是需要提示的失败
91
+ * (COO 的停止键常显,lazy-create 前也会调到这里)。
92
+ */
93
+ abort: () => boolean;
83
94
  /** 正在等待停止回执的会话 id;非空即「停止中」态,可用来置灰停止键。 */
84
95
  abortingConversationId: string | null;
85
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"use-abort-with-escape-hatch.d.ts","sourceRoot":"","sources":["../../src/hooks/use-abort-with-escape-hatch.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,6BAA6B;IAC5C,2DAA2D;IAC3D,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,yCAAyC;IACzC,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAED,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,8BAAmC,GAC3C,6BAA6B,CA+C/B"}
1
+ {"version":3,"file":"use-abort-with-escape-hatch.d.ts","sourceRoot":"","sources":["../../src/hooks/use-abort-with-escape-hatch.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqEG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,6BAA6B;IAC5C;;;;;;;;OAQG;IACH,KAAK,EAAE,MAAM,OAAO,CAAC;IACrB,yCAAyC;IACzC,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAED,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,8BAAmC,GAC3C,6BAA6B,CAwD/B"}
@@ -1,6 +1,7 @@
1
1
  import { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import { useStore } from 'zustand';
3
3
  import { useChatContext } from '../provider/chat-context.js';
4
+ import { selectOutstandingCount } from '../client/outbound-queue.js';
4
5
  export function useAbortWithEscapeHatch(options = {}) {
5
6
  const { timeoutMs = 10_000, onEscape } = options;
6
7
  const { store, client } = useChatContext();
@@ -8,10 +9,13 @@ export function useAbortWithEscapeHatch(options = {}) {
8
9
  const currentConversationId = useStore(store, (s) => s.currentConversationId);
9
10
  // 「这个会话还在跑吗」= 集合腿 ∪ 全局 flag 腿。两条都要看:wedge 的形态之一恰恰是
10
11
  // 集合已空而 flag 还举着(例:删除当前对话只清集合、不清 isThinking)。
12
+ // ac#1053 Δ4:再并上在途账腿(门控后的值,Δ10)—— 回合终态丢失留下的幻影 id 也要能靠
13
+ // 「停止 + 10 s」清掉;逃生口的 settle 经组合 sink 清账。COO 不记账 ⇒ 这条腿对它恒假。
11
14
  const isAbortingConvBusy = useStore(store, (s) => abortingConversationId === null
12
15
  ? false
13
16
  : s.processingConversationIds.has(abortingConversationId) ||
14
- (abortingConversationId === s.currentConversationId && (s.isStreaming || s.isThinking)));
17
+ (abortingConversationId === s.currentConversationId && (s.isStreaming || s.isThinking)) ||
18
+ selectOutstandingCount(s, abortingConversationId) > 0);
15
19
  // onEscape 存进 ref:消费方几乎必然传内联箭头函数,直接进 deps 会让定时器每次渲染重建、
16
20
  // 永远等不满 10 秒(本 hook 最容易踩的一个静默失效)。
17
21
  const onEscapeRef = useRef(onEscape);
@@ -21,9 +25,16 @@ export function useAbortWithEscapeHatch(options = {}) {
21
25
  const abort = useCallback(() => {
22
26
  const conversationId = store.getState().currentConversationId;
23
27
  if (!conversationId)
24
- return;
25
- client.send({ type: 'abort', conversation_id: conversationId });
28
+ return true;
29
+ // sdk#158:帧没出网就不武装——否则重连 gap 里按停止,10s 后会把仍在跑的回合判成「已停」
30
+ //(回复劈两条 + 撞并发锁 + #1021 下误发 E10)。abort 不入 outbox、不重投,丢了就是丢了。
31
+ const sent = client.send({ type: 'abort', conversation_id: conversationId });
32
+ if (!sent)
33
+ return false;
34
+ // ac#1053 Δ5:帧出网才置抑制位(下一个使在途账恰好变空的终态只删不放)。
35
+ store.getState().setLocalAbortPending(conversationId, true);
26
36
  setAbortingConversationId(conversationId);
37
+ return true;
27
38
  }, [store, client]);
28
39
  useEffect(() => {
29
40
  if (!abortingConversationId)
@@ -1 +1 @@
1
- {"version":3,"file":"use-abort-with-escape-hatch.js","sourceRoot":"","sources":["../../src/hooks/use-abort-with-escape-hatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAyF7D,MAAM,UAAU,uBAAuB,CACrC,UAA0C,EAAE;IAE5C,MAAM,EAAE,SAAS,GAAG,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IACjD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC3C,MAAM,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAE1F,MAAM,qBAAqB,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC;IAC9E,mDAAmD;IACnD,8CAA8C;IAC9C,MAAM,kBAAkB,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAC/C,sBAAsB,KAAK,IAAI;QAC7B,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,GAAG,CAAC,sBAAsB,CAAC;YACvD,CAAC,sBAAsB,KAAK,CAAC,CAAC,qBAAqB,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAC5F,CAAC;IAEF,uDAAuD;IACvD,kCAAkC;IAClC,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrC,SAAS,CAAC,GAAG,EAAE;QACb,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IACjC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,MAAM,cAAc,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,qBAAqB,CAAC;QAC9D,IAAI,CAAC,cAAc;YAAE,OAAO;QAC5B,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC,CAAC;QAChE,yBAAyB,CAAC,cAAc,CAAC,CAAC;IAC5C,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IAEpB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,sBAAsB;YAAE,OAAO;QACpC,oBAAoB;QACpB,IAAI,sBAAsB,KAAK,qBAAqB,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5E,yBAAyB,CAAC,IAAI,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,yBAAyB,CAAC,IAAI,CAAC,CAAC;YAChC,oEAAoE;YACpE,kDAAkD;YAClD,KAAK,CAAC,QAAQ,EAAE,CAAC,eAAe,CAAC,sBAAsB,EAAE,cAAc,CAAC,CAAC;YACzE,WAAW,CAAC,OAAO,EAAE,CAAC,sBAAsB,CAAC,CAAC;QAChD,CAAC,EAAE,SAAS,CAAC,CAAC;QACd,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,EAAE,CAAC,sBAAsB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;IAE1F,OAAO,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"use-abort-with-escape-hatch.js","sourceRoot":"","sources":["../../src/hooks/use-abort-with-escape-hatch.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-connection-state.d.ts","sourceRoot":"","sources":["../../src/hooks/use-connection-state.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D,kEAAkE;AAClE,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF,wBAAgB,kBAAkB,IAAI;IACpC,eAAe,EAAE,eAAe,CAAC;IACjC;;;;;;;OAOG;IACH,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,eAAe,EAAE,CAAC,IAAI,CAAC,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE,CA6CA"}
1
+ {"version":3,"file":"use-connection-state.d.ts","sourceRoot":"","sources":["../../src/hooks/use-connection-state.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D,kEAAkE;AAClE,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF,wBAAgB,kBAAkB,IAAI;IACpC,eAAe,EAAE,eAAe,CAAC;IACjC;;;;;;;OAOG;IACH,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,eAAe,EAAE,CAAC,IAAI,CAAC,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE,CAgDA"}
@@ -3,7 +3,7 @@ import { useStore } from 'zustand';
3
3
  import { useShallow } from 'zustand/react/shallow';
4
4
  import { useChatContext } from '../provider/chat-context.js';
5
5
  export function useConnectionState() {
6
- const { store, client } = useChatContext();
6
+ const { store, client, queue } = useChatContext();
7
7
  const state = useStore(store, useShallow((s) => ({
8
8
  connectionState: s.connectionState,
9
9
  isRecovering: s.isRecovering,
@@ -39,8 +39,11 @@ export function useConnectionState() {
39
39
  // per direction (#619 follow-up: COO ENTER passes resetConversation:true).
40
40
  if (opts?.resetConversation)
41
41
  s.setCurrentConversationId(null);
42
+ // ac#1053:新 session ⇒ 本地排队、在途账、抑制位与 `turnCmidSupported` 全部作废(旧 session
43
+ // 的回合终态永远不会来)。必须在 `client.startNewSession()` 之前(它要等新 socket 才 resolve)。
44
+ queue.onSessionReset();
42
45
  await client.startNewSession();
43
- }, [client, store]);
46
+ }, [client, store, queue]);
44
47
  return { ...state, reconnect, startNewSession };
45
48
  }
46
49
  //# sourceMappingURL=use-connection-state.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-connection-state.js","sourceRoot":"","sources":["../../src/hooks/use-connection-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAa7D,MAAM,UAAU,kBAAkB;IAoChC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAG,QAAQ,CACpB,KAAK,EACL,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjB,eAAe,EAAE,CAAC,CAAC,eAAe;QAClC,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,KAAK,EAAE,CAAC,CAAC,eAAe;QACxB,gBAAgB,EAAE,CAAC,CAAC,gBAAgB;KACrC,CAAC,CAAC,CACJ,CAAC;IACF,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;QACjC,KAAK,MAAM,CAAC,SAAS,EAAE,CAAC;IAC1B,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACb,MAAM,eAAe,GAAG,WAAW,CACjC,KAAK,EAAE,IAA6B,EAAE,EAAE;QACtC,6EAA6E;QAC7E,6EAA6E;QAC7E,2EAA2E;QAC3E,2EAA2E;QAC3E,gFAAgF;QAChF,+EAA+E;QAC/E,mEAAmE;QACnE,gBAAgB;QAChB,EAAE;QACF,sEAAsE;QACtE,sEAAsE;QACtE,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3B,CAAC,CAAC,4BAA4B,EAAE,CAAC;QACjC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACrB,+EAA+E;QAC/E,6EAA6E;QAC7E,6EAA6E;QAC7E,+EAA+E;QAC/E,6EAA6E;QAC7E,6EAA6E;QAC7E,6EAA6E;QAC7E,2EAA2E;QAC3E,IAAI,IAAI,EAAE,iBAAiB;YAAE,CAAC,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAC9D,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC;IACjC,CAAC,EACD,CAAC,MAAM,EAAE,KAAK,CAAC,CAChB,CAAC;IACF,OAAO,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AAClD,CAAC"}
1
+ {"version":3,"file":"use-connection-state.js","sourceRoot":"","sources":["../../src/hooks/use-connection-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAa7D,MAAM,UAAU,kBAAkB;IAoChC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,cAAc,EAAE,CAAC;IAClD,MAAM,KAAK,GAAG,QAAQ,CACpB,KAAK,EACL,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjB,eAAe,EAAE,CAAC,CAAC,eAAe;QAClC,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,KAAK,EAAE,CAAC,CAAC,eAAe;QACxB,gBAAgB,EAAE,CAAC,CAAC,gBAAgB;KACrC,CAAC,CAAC,CACJ,CAAC;IACF,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;QACjC,KAAK,MAAM,CAAC,SAAS,EAAE,CAAC;IAC1B,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACb,MAAM,eAAe,GAAG,WAAW,CACjC,KAAK,EAAE,IAA6B,EAAE,EAAE;QACtC,6EAA6E;QAC7E,6EAA6E;QAC7E,2EAA2E;QAC3E,2EAA2E;QAC3E,gFAAgF;QAChF,+EAA+E;QAC/E,mEAAmE;QACnE,gBAAgB;QAChB,EAAE;QACF,sEAAsE;QACtE,sEAAsE;QACtE,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3B,CAAC,CAAC,4BAA4B,EAAE,CAAC;QACjC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACrB,+EAA+E;QAC/E,6EAA6E;QAC7E,6EAA6E;QAC7E,+EAA+E;QAC/E,6EAA6E;QAC7E,6EAA6E;QAC7E,6EAA6E;QAC7E,2EAA2E;QAC3E,IAAI,IAAI,EAAE,iBAAiB;YAAE,CAAC,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAC9D,uEAAuE;QACvE,wEAAwE;QACxE,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC;IACjC,CAAC,EACD,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CACvB,CAAC;IACF,OAAO,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AAClD,CAAC"}
@@ -1,3 +1,5 @@
1
+ import type { QueuedEntry } from '../client/outbound-queue.js';
2
+ import type { OutboundRelease } from '../store/chat-store.js';
1
3
  import type { ChatError, Message, SendMessageOptions } from '../types.js';
2
4
  export declare function useCurrentChat(): {
3
5
  messages: Message[];
@@ -48,6 +50,13 @@ export declare function useCurrentChat(): {
48
50
  *
49
51
  * 发送失败时抛错、无返回值(`client.send()` 返 `false` ⇒ 本函数抛
50
52
  * `Error('Failed to send message')`),调用方本就要 catch。
53
+ *
54
+ * ac#1053(B 档 = `!(midTurnSteerSupported === true && 连接已武装)`;A 档下两个新 option 被忽略):
55
+ * - `queueWhileProcessing: true` 且本会话在飞 / 队列非空 / 有在途 id ⇒ **入本地队列、不出网**、
56
+ * ⛔ 进消息列表,返回的 id 即条目 id(`queuedMessages[i].messageId`);队列满抛
57
+ * `Error('queue_full')`(上传前预判,⛔ 上传;上传期间被别处填满则上传后抛)。
58
+ * - 带 option 但不需排队 ⇒ 照常直发并记账,且写 `lastRelease`(起了新回合)。
59
+ * - `trackOutstanding: true` ⇒ 照常发送并记账(它的终态构成放队列的边沿)。
51
60
  */
52
61
  sendMessage: (content: string, options?: SendMessageOptions) => Promise<string>;
53
62
  abort: () => void;
@@ -57,5 +66,20 @@ export declare function useCurrentChat(): {
57
66
  isLoadingHistory: boolean;
58
67
  /** gw#1587:重试 failed 消息(messageId = 消息 id = client_msg_id)。 */
59
68
  retryMessage: (messageId: string) => boolean;
69
+ /** ac#1053:当前会话的本地排队(按入队顺序;未出网、不在 `messages` 里)。只读:是 store 里的活数组,⛔ 就地修改。 */
70
+ queuedMessages: readonly QueuedEntry[];
71
+ /** ac#1053:按 id 出队(取消回填由宿主用条目的 `content`);不在队里 ⇒ false。 */
72
+ cancelQueuedMessage: (messageId: string) => boolean;
73
+ /**
74
+ * ac#1053:立即放出该条(不必是队头、不看边沿谓词)。空闲时放出会写 `lastRelease`;
75
+ * 发不出去(未连通 / 宿主拦截)⇒ false,条目留队。
76
+ */
77
+ sendQueuedMessageNow: (messageId: string) => boolean;
78
+ /** ac#1053:当前会话的在途数(Δ10:本 session 未见过带 `clientMsgId` 的 finish 时恒 0)。 */
79
+ outstandingCount: number;
80
+ /** ac#1053:当前会话的队列会不会在回合结束时自己放(Δ12;标签「排队中」/「等待发送」)。 */
81
+ willAutoDrain: boolean;
82
+ /** ac#1053:最近一次「起了新回合」的放出(全局单槽,`seq` 单调);宿主据此重置思考计时。 */
83
+ lastRelease: OutboundRelease | null;
60
84
  };
61
85
  //# sourceMappingURL=use-current-chat.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-current-chat.d.ts","sourceRoot":"","sources":["../../src/hooks/use-current-chat.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,SAAS,EACT,OAAO,EAEP,kBAAkB,EACnB,MAAM,aAAa,CAAC;AAQrB,wBAAgB,cAAc,IAAI;IAChC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4CG;IACH,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChF,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,+DAA+D;IAC/D,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CAC9C,CAgLA"}
1
+ {"version":3,"file":"use-current-chat.d.ts","sourceRoot":"","sources":["../../src/hooks/use-current-chat.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EACV,SAAS,EACT,OAAO,EAEP,kBAAkB,EACnB,MAAM,aAAa,CAAC;AAWrB,wBAAgB,cAAc,IAAI;IAChC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmDG;IACH,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChF,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,+DAA+D;IAC/D,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7C,4EAA4E;IAC5E,cAAc,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,2DAA2D;IAC3D,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IACpD;;;OAGG;IACH,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IACrD,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,aAAa,EAAE,OAAO,CAAC;IACvB,wDAAwD;IACxD,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;CACrC,CA4OA"}