tailii-host 0.11.1 → 0.13.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 (63) hide show
  1. package/dist/backend/herdr.js +1 -1
  2. package/dist/backend/herdr.js.map +1 -1
  3. package/dist/backend/sessionBackend.d.ts +3 -0
  4. package/dist/backend/sessionBackend.js +3 -0
  5. package/dist/backend/sessionBackend.js.map +1 -1
  6. package/dist/backend/tmux.d.ts +31 -4
  7. package/dist/backend/tmux.js +84 -4
  8. package/dist/backend/tmux.js.map +1 -1
  9. package/dist/chat/imageService.d.ts +34 -1
  10. package/dist/chat/imageService.js +136 -22
  11. package/dist/chat/imageService.js.map +1 -1
  12. package/dist/chat/transcriptTailer.js +19 -3
  13. package/dist/chat/transcriptTailer.js.map +1 -1
  14. package/dist/codex/codexAppServer.d.ts +6 -0
  15. package/dist/codex/codexAppServer.js +27 -0
  16. package/dist/codex/codexAppServer.js.map +1 -1
  17. package/dist/codex/codexRolloutTailer.d.ts +5 -0
  18. package/dist/codex/codexRolloutTailer.js +22 -4
  19. package/dist/codex/codexRolloutTailer.js.map +1 -1
  20. package/dist/codex/codexSessionStore.d.ts +11 -0
  21. package/dist/codex/codexSessionStore.js +51 -8
  22. package/dist/codex/codexSessionStore.js.map +1 -1
  23. package/dist/commands/setup.js +1 -1
  24. package/dist/commands/setup.js.map +1 -1
  25. package/dist/engine/context.d.ts +5 -0
  26. package/dist/engine/context.js.map +1 -1
  27. package/dist/engine/engine.d.ts +9 -0
  28. package/dist/engine/engine.js +61 -4
  29. package/dist/engine/engine.js.map +1 -1
  30. package/dist/engine/handlers/conversation.js +117 -6
  31. package/dist/engine/handlers/conversation.js.map +1 -1
  32. package/dist/engine/handlers/session.d.ts +6 -1
  33. package/dist/engine/handlers/session.js +58 -47
  34. package/dist/engine/handlers/session.js.map +1 -1
  35. package/dist/hub/historyPage.d.ts +22 -0
  36. package/dist/hub/historyPage.js +125 -0
  37. package/dist/hub/historyPage.js.map +1 -0
  38. package/dist/hub/hubDaemon.js +11 -3
  39. package/dist/hub/hubDaemon.js.map +1 -1
  40. package/dist/hub/hubProtocol.d.ts +32 -0
  41. package/dist/hub/hubProtocol.js +42 -0
  42. package/dist/hub/hubProtocol.js.map +1 -1
  43. package/dist/hub/panePreviewPump.d.ts +33 -0
  44. package/dist/hub/panePreviewPump.js +62 -3
  45. package/dist/hub/panePreviewPump.js.map +1 -1
  46. package/dist/hub/sessionHub.d.ts +26 -0
  47. package/dist/hub/sessionHub.js +235 -4
  48. package/dist/hub/sessionHub.js.map +1 -1
  49. package/dist/protocol/decode.d.ts +5 -0
  50. package/dist/protocol/decode.js +77 -2
  51. package/dist/protocol/decode.js.map +1 -1
  52. package/dist/protocol/messages.d.ts +78 -2
  53. package/dist/services/gitService.js +9 -4
  54. package/dist/services/gitService.js.map +1 -1
  55. package/dist/sessions/claudeSessionStore.d.ts +27 -0
  56. package/dist/sessions/claudeSessionStore.js +82 -1
  57. package/dist/sessions/claudeSessionStore.js.map +1 -1
  58. package/dist/sessions/conversationDelete.d.ts +32 -0
  59. package/dist/sessions/conversationDelete.js +168 -0
  60. package/dist/sessions/conversationDelete.js.map +1 -0
  61. package/dist/shared/clientBuild.d.ts +1 -1
  62. package/dist/shared/clientBuild.js +1 -1
  63. package/package.json +3 -3
@@ -29,6 +29,14 @@ export class PanePreviewPump {
29
29
  lastUsageLimitWait = null;
30
30
  log;
31
31
  emitInitialIf;
32
+ holdActiveIf;
33
+ jumpToLatest;
34
+ jumpToLatestIf;
35
+ /** iPhone が会話を開いてから、最新位置へ戻す判定をまだ終えていないか。 */
36
+ jumpArmed = false;
37
+ lastJumpAt = 0;
38
+ /** 今回の準備で送った回数。 */
39
+ jumpAttempts = 0;
32
40
  captureSuggestion;
33
41
  suggestionIntervalMs;
34
42
  /** 直近に配信した提案文(null=未配信・"" =提案なし)。変化時だけ流す。 */
@@ -38,6 +46,14 @@ export class PanePreviewPump {
38
46
  lastEmittedDialog = false;
39
47
  emitInitial = false;
40
48
  static minEmitIntervalMs = 500;
49
+ /**
50
+ * 静止中も処理中とみなすフレーム(`holdActiveIf`)を送り直す間隔。iOS の完了触覚の取り消し猶予
51
+ * (1.5 秒)に収まるよう 1 秒(前面購読の 250ms 周期と合わせて最大 1.25 秒で点き直す)。
52
+ */
53
+ static holdResendIntervalMs = 1000;
54
+ /** 最新位置へ戻すキーを送る最小間隔と、戻らないときに諦めるまでの回数(jump-to-latest)。 */
55
+ static jumpIntervalMs = 5000;
56
+ static maxJumpAttempts = 3;
41
57
  constructor(options) {
42
58
  this.writer = options.writer;
43
59
  this.capture = options.capture;
@@ -49,6 +65,9 @@ export class PanePreviewPump {
49
65
  this.onUsageLimitWait = options.onUsageLimitWait ?? null;
50
66
  this.log = options.log ?? null;
51
67
  this.emitInitialIf = options.emitInitialIf ?? null;
68
+ this.holdActiveIf = options.holdActiveIf ?? null;
69
+ this.jumpToLatest = options.jumpToLatest ?? null;
70
+ this.jumpToLatestIf = options.jumpToLatestIf ?? null;
52
71
  this.captureSuggestion = options.captureSuggestion ?? null;
53
72
  this.suggestionIntervalMs = options.suggestionIntervalMs ?? 1000;
54
73
  }
@@ -90,6 +109,9 @@ export class PanePreviewPump {
90
109
  this.inactiveSent = false;
91
110
  this.lastSuggestion = null;
92
111
  this.lastSuggestionAt = 0;
112
+ this.jumpArmed = false;
113
+ this.lastJumpAt = 0;
114
+ this.jumpAttempts = 0;
93
115
  const ac = new AbortController();
94
116
  this.abortController = ac;
95
117
  this.task = this.run(session, mode, ac.signal);
@@ -156,6 +178,8 @@ export class PanePreviewPump {
156
178
  }
157
179
  }
158
180
  const now = Date.now();
181
+ if (text !== null && mode === "claude_status")
182
+ this.maybeJumpToLatest(session, text, now);
159
183
  if (text !== null && text !== this.lastText) {
160
184
  if (this.lastText === null) {
161
185
  this.lastText = text;
@@ -187,9 +211,19 @@ export class PanePreviewPump {
187
211
  this.hasEmitted &&
188
212
  this.lastChangeAt > 0 &&
189
213
  now - this.lastChangeAt >= this.quietThresholdMs) {
190
- this.emit(session, false, "");
191
- this.inactiveSent = true;
192
- this.active = false;
214
+ if (this.lastText !== null && this.holdActiveIf !== null && this.holdActiveIf(this.lastText)) {
215
+ // 静止していても処理中(scroll-pill)。消灯せず、直前のフレームを間隔を空けて送り直す:
216
+ // iOS は確定応答(assistant eof)で表示を消すため、画面が動かないままだと次の変化まで
217
+ // 点かない。
218
+ if (now - this.lastEmitAt >= PanePreviewPump.holdResendIntervalMs) {
219
+ this.emitActive(session, this.lastText, now, mode);
220
+ }
221
+ }
222
+ else {
223
+ this.emit(session, false, "");
224
+ this.inactiveSent = true;
225
+ this.active = false;
226
+ }
193
227
  }
194
228
  // プロンプト提案(薄字ゴースト)の抽出・配信(claude_status のみ・低頻度・変化時だけ)。
195
229
  if (mode === "claude_status" &&
@@ -217,6 +251,31 @@ export class PanePreviewPump {
217
251
  await abortableSleep(this.pollIntervalMs(), signal);
218
252
  }
219
253
  }
254
+ /** iPhone が会話を開いた。次のフレームで上へスクロールされていれば 1 回だけ最新位置へ戻す。 */
255
+ armJumpToLatest() {
256
+ if (this.jumpToLatest === null || this.jumpToLatestIf === null)
257
+ return;
258
+ this.jumpArmed = true;
259
+ this.jumpAttempts = 0;
260
+ this.lastJumpAt = 0;
261
+ }
262
+ maybeJumpToLatest(session, text, now) {
263
+ if (!this.jumpArmed || this.jumpToLatest === null || this.jumpToLatestIf === null)
264
+ return;
265
+ // 案内が無い(最初から最新位置・戻せた)なら終わり。以後は次に開くまで送らない。
266
+ if (!this.jumpToLatestIf(text) || this.jumpAttempts >= PanePreviewPump.maxJumpAttempts) {
267
+ this.jumpArmed = false;
268
+ return;
269
+ }
270
+ if (now - this.lastJumpAt < PanePreviewPump.jumpIntervalMs)
271
+ return;
272
+ this.lastJumpAt = now;
273
+ this.jumpAttempts += 1;
274
+ this.log?.(`audit jump-to-latest session=${session} attempt=${this.jumpAttempts}`);
275
+ this.jumpToLatest(session).catch((error) => {
276
+ this.log?.(`audit jump-to-latest-failed session=${session} error=${String(error)}`);
277
+ });
278
+ }
220
279
  emitSuggestion(session, text) {
221
280
  const v = this.protocolVersion();
222
281
  if (v < PROTOCOL_V2)
@@ -1 +1 @@
1
- {"version":3,"file":"panePreviewPump.js","sourceRoot":"","sources":["../../src/hub/panePreviewPump.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"panePreviewPump.js","sourceRoot":"","sources":["../../src/hub/panePreviewPump.ts"],"names":[],"mappings":"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"}
@@ -27,6 +27,11 @@ export interface HubPreviewPump {
27
27
  stop(): void;
28
28
  /** 前面購読者の参加時に、直近の入力待ちフレームを再送する(任意実装)。 */
29
29
  resendLastIfInteractive?(): void;
30
+ /**
31
+ * iPhone が会話を開いた(前面購読が始まった)ときに 1 回だけ、端末側で上へスクロールされた画面を
32
+ * 最新位置へ戻す準備をする(任意実装, jump-to-latest)。以後は次に開くまで Mac 側のスクロールを尊重する。
33
+ */
34
+ armJumpToLatest?(): void;
30
35
  }
31
36
  /**
32
37
  * chat 注入(chatInjector)へ渡す会話文脈。backend の sendTextSubmit が入力欄の残存テキストの
@@ -295,6 +300,13 @@ export declare class SessionHub {
295
300
  private codexStartsInFlight;
296
301
  private modePushSeq;
297
302
  private chatReceiptsDirty;
303
+ /**
304
+ * 片付け(retire)・世代不一致で actor ごと消えた会話の Claude 配送済み receipt(clientMessageId →
305
+ * 配送時刻)。clientMessageId は UUID で会話をまたいで一意なので、actor が消えても「配送済み」の
306
+ * 事実は変わらない。`chat_receipt_query` がこれを見て、ACK を取りこぼした iOS の Outbox を
307
+ * 安全に解決できるようにする(restored-receipt-probe)。保持は通常の receipt と同じ 30 日。
308
+ */
309
+ private retiredChatDeliveries;
298
310
  private readonly activeCodexTurns;
299
311
  private codexTurnController;
300
312
  constructor(options: SessionHubOptions);
@@ -357,6 +369,13 @@ export declare class SessionHub {
357
369
  private publishCodexContent;
358
370
  private publishConversationEvent;
359
371
  private startBackfill;
372
+ /** 直近に読んだ会話の全履歴(ページを遡るたびに transcript を頭から読み直さない)。 */
373
+ private readonly historyPageCache;
374
+ /** 会話ごとの読み取り中の Promise(同じ会話の全履歴を並行して二重に読まない)。 */
375
+ private readonly historyPageReads;
376
+ private answerHistoryPage;
377
+ /** 全履歴の再送と同じ tail で transcript を最後まで読み、出力を集める(購読者へは流さない)。 */
378
+ private readFullHistory;
360
379
  private canReplay;
361
380
  /** watch 状態・処理中遷移で全 actor の pump 要否を見直す(対象は疎なので全走査で足りる)。 */
362
381
  private syncAllPreviews;
@@ -441,6 +460,13 @@ export declare class SessionHub {
441
460
  private persistPendingQuestions;
442
461
  private readPendingQuestions;
443
462
  private persistChatReceipts;
463
+ private readRetiredChatDeliveries;
464
+ /**
465
+ * Claude 発話の配送状態を、何も登録せずに答える(`chat_receipt_query`, restored-receipt-probe)。
466
+ * `chat_send` と違い、どの記録にも無い ID を新規として受け付けない(unknown を返すだけ)。
467
+ * 会話が片付いた後も配送済みは台帳から答える。actor が無ければ作らない。
468
+ */
469
+ private chatReceiptStatus;
444
470
  private readChatReceipts;
445
471
  }
446
472
  export {};
@@ -5,8 +5,10 @@ import * as fs from "node:fs";
5
5
  import * as path from "node:path";
6
6
  import { bumpHeartbeat, listHeartbeatSessions, readHeartbeat, writeHeartbeat } from "../sessions/heartbeat.js";
7
7
  import { ensureDirectory0700 } from "../shared/paths.js";
8
+ import { encodeControlMessage } from "../protocol.js";
8
9
  import { decodeHubClientLine, encodeHubMessage, } from "./hubProtocol.js";
9
10
  import { HISTORY_DONE_STREAM_ID, findTrailingTurnEndMarkerMs, findTrailingUserPromptText, } from "../chat/transcriptTailer.js";
11
+ import { sliceHistoryPage } from "./historyPage.js";
10
12
  import { sameUsageLimitWait } from "../shared/usageLimitWait.js";
11
13
  import { PROTOCOL_V1, PROTOCOL_V2 } from "../protocol.js";
12
14
  import { ChatInjectionRejectedError, LoginCodeError, SEND_NOW_BLOCKED_BY_DIALOG, SEND_NOW_EXPIRED_IN_QUEUE, } from "../backend/tmux.js";
@@ -20,6 +22,12 @@ import { claudeTranscriptPathFor } from "../sessions/transcriptPath.js";
20
22
  * ければ強制的に live へ切り替える。進捗があるうちは延長するので、巨大な transcript の再生を
21
23
  * 途中で打ち切ることはない。
22
24
  */
25
+ /** 履歴ページ用に transcript を読み切るまでの上限(画像の多い巨大な会話でも返事を返す)。 */
26
+ const HISTORY_PAGE_READ_TIMEOUT_MS = 20_000;
27
+ /** 履歴ページ用に全履歴を覚えておく会話の数。 */
28
+ const HISTORY_PAGE_CACHE_LIMIT = 3;
29
+ /** 履歴ページ用に覚えた全履歴を使い回す期間(遡り中の連続要求だけを速くし、メモリに長く残さない)。 */
30
+ const HISTORY_PAGE_CACHE_TTL_MS = 10 * 60_000;
23
31
  const BACKFILL_STALL_TIMEOUT_MS = 15_000;
24
32
  const DELIVERED_RECEIPT_TTL_MS = 30 * 24 * 60 * 60 * 1_000;
25
33
  const MAX_DELIVERED_RECEIPTS_PER_SESSION = 10_000;
@@ -59,6 +67,13 @@ export class SessionHub {
59
67
  codexStartsInFlight = 0;
60
68
  modePushSeq = 0;
61
69
  chatReceiptsDirty = false;
70
+ /**
71
+ * 片付け(retire)・世代不一致で actor ごと消えた会話の Claude 配送済み receipt(clientMessageId →
72
+ * 配送時刻)。clientMessageId は UUID で会話をまたいで一意なので、actor が消えても「配送済み」の
73
+ * 事実は変わらない。`chat_receipt_query` がこれを見て、ACK を取りこぼした iOS の Outbox を
74
+ * 安全に解決できるようにする(restored-receipt-probe)。保持は通常の receipt と同じ 30 日。
75
+ */
76
+ retiredChatDeliveries = new Map();
62
77
  activeCodexTurns = new Set();
63
78
  codexTurnController = null;
64
79
  constructor(options) {
@@ -176,12 +191,19 @@ export class SessionHub {
176
191
  /** daemon 再起動前に durable enqueue 済みだった chat_send と receipt を復元する。 */
177
192
  restoreChatReceipts() {
178
193
  const persisted = this.readChatReceipts();
194
+ const restoredLedgerAt = Date.now();
195
+ for (const [clientMessageId, deliveredAt] of Object.entries(this.readRetiredChatDeliveries())) {
196
+ this.retiredChatDeliveries.set(clientMessageId, deliveredAt);
197
+ }
198
+ compactRetiredChatDeliveries(this.retiredChatDeliveries, restoredLedgerAt);
179
199
  let discardedStaleSession = false;
180
200
  for (const [session, state] of Object.entries(persisted)) {
181
201
  const currentSessionIdentity = receiptSessionIdentity(this.options.metadataStore.get(session));
182
202
  if (state.sessionIdentity !== undefined && state.sessionIdentity !== currentSessionIdentity) {
183
203
  // session 名は再利用される。旧世代の durable queue を同名の新 pane へ注入しない。
184
204
  // metadata が消失・破損した場合も identity を証明できないため安全側で破棄する。
205
+ // 配送済みの事実(UUID の clientMessageId)だけは照会用の台帳へ残す。
206
+ adoptRetiredChatDeliveries(this.retiredChatDeliveries, new Map(state.delivered.map((id) => [id, state.deliveredAtMs?.[id] ?? restoredLedgerAt])), restoredLedgerAt);
185
207
  discardedStaleSession = true;
186
208
  this.options.log?.(`stale chat receipt 破棄 session=${session}`);
187
209
  continue;
@@ -335,6 +357,10 @@ export class SessionHub {
335
357
  }
336
358
  return;
337
359
  }
360
+ if (message.type === "conversation_history_page_request") {
361
+ void this.answerHistoryPage(client, message);
362
+ return;
363
+ }
338
364
  if (message.type === "conversation_subagent_transcript_request") {
339
365
  const actor = this.actors.get(message.session);
340
366
  const transcript = actor?.tail?.subagentTranscript?.(message.nodeId) ?? {
@@ -444,7 +470,7 @@ export class SessionHub {
444
470
  else {
445
471
  // publishCodexMarker は名前こそ codex 由来だが、実体は汎用の
446
472
  // chat_output(system) マーカー発行なのでそのまま使う。
447
- this.publishCodexMarker(message.session, `question-inject-error-${restoreSnapshot.id}`, "⚠️ 設問回答の反映に失敗しました。会話を開き直して再回答するか、Mac 側の画面で回答してください。");
473
+ this.publishCodexMarker(message.session, `question-inject-error-${restoreSnapshot.id}`, "⚠️ 設問回答の反映に失敗しました。会話を開き直して再回答するか、ホスト側の画面で回答してください。");
448
474
  }
449
475
  }
450
476
  })
@@ -678,6 +704,13 @@ export class SessionHub {
678
704
  void this.runSendNow(message.session, actor);
679
705
  return;
680
706
  }
707
+ if (message.type === "chat_receipt_query") {
708
+ this.sendTo(client, {
709
+ type: "chat_receipt_query_result", id: message.id,
710
+ status: this.chatReceiptStatus(message.session, message.clientMessageId),
711
+ });
712
+ return;
713
+ }
681
714
  if (message.type === "pending_message_delete") {
682
715
  // 対象不在も成功だが、client 保存前 crash で同じ Outbox が復元されても実行しないよう
683
716
  // 削除 tombstone は durable に残す。actor 不在でもここだけは軽量 actor を作る。
@@ -827,6 +860,7 @@ export class SessionHub {
827
860
  }
828
861
  // drain が injector / App Server の await 中でも、復帰後に同じ actor 参照から次の旧入力へ
829
862
  // 進めないよう durable queue の実体も空にする。現在実行中の1件は復帰時のidentity検査で捨てる。
863
+ adoptRetiredChatDeliveries(this.retiredChatDeliveries, actor.deliveredChatMessageIds);
830
864
  actor.chatQueue.length = 0;
831
865
  actor.chatOrder.length = 0;
832
866
  actor.pendingChatMessages.clear();
@@ -886,8 +920,26 @@ export class SessionHub {
886
920
  }
887
921
  // 会話を開き直したとき(pump は一覧 watch で稼働中)、静止した入力待ちダイアログの
888
922
  // フレームは変化しないので再送しないと転写カードが出ない。
889
- if (preview && !wasPreview)
923
+ if (preview && !wasPreview) {
890
924
  actor.previewPump?.resendLastIfInteractive?.();
925
+ actor.previewPump?.armJumpToLatest?.();
926
+ }
927
+ // 開き直し(reattach-since)は iOS のキャッシュが追いついていた時刻以降を transcript から
928
+ // 読み直す。背景購読の replay buffer だけでは履歴完了マーカーが届かず、iOS の
929
+ // 「最新分を取り込み中」が解けない。
930
+ if (!existing.backfilling && newerThanMs !== undefined) {
931
+ if (this.options.tailFactory === undefined || this.options.metadataStore.get(session) === null) {
932
+ // 読み直せない会話でも完了を知らせる(iOS の「最新分を取り込み中」と遡りの待ちを解く)。
933
+ this.sendTo(client, {
934
+ type: "conversation_event", session, serverSeq: 0,
935
+ payload: { type: "chat_output", v: PROTOCOL_V1, streamId: "pc:history-cancelled",
936
+ role: "system", text: "", eof: true },
937
+ });
938
+ return;
939
+ }
940
+ this.startBackfill(client, session, actor, newerThanMs);
941
+ return;
942
+ }
891
943
  // preview=false 中に engine が route できなかった image/subagent event を、同じ
892
944
  // subscriber の前面昇格時にも afterSeq から回収する。既存購読だからと no-op にしない。
893
945
  if (!existing.backfilling && afterSeq !== undefined) {
@@ -912,8 +964,10 @@ export class SessionHub {
912
964
  }
913
965
  // 初回 backfill が同期的に多数の行を生成する前に pane capture を開始する。
914
966
  this.syncPreview(session, actor);
915
- if (preview)
967
+ if (preview) {
916
968
  actor.previewPump?.resendLastIfInteractive?.();
969
+ actor.previewPump?.armJumpToLatest?.();
970
+ }
917
971
  if (first) {
918
972
  this.startSharedTail(session, actor, newerThanMs ?? null);
919
973
  // processing 完了で一度 unsubscribe された後も、actor の replay buffer が残る間は
@@ -1459,6 +1513,114 @@ export class SessionHub {
1459
1513
  if (!finished)
1460
1514
  armStallTimer(BACKFILL_STALL_TIMEOUT_MS);
1461
1515
  }
1516
+ // ---- 履歴ページ(history-page) ----
1517
+ /** 直近に読んだ会話の全履歴(ページを遡るたびに transcript を頭から読み直さない)。 */
1518
+ historyPageCache = new Map();
1519
+ /** 会話ごとの読み取り中の Promise(同じ会話の全履歴を並行して二重に読まない)。 */
1520
+ historyPageReads = new Map();
1521
+ async answerHistoryPage(client, message) {
1522
+ const anchor = message.beforeStreamId !== undefined || message.beforeToolId !== undefined
1523
+ ? { ...(message.beforeStreamId !== undefined ? { streamId: message.beforeStreamId } : {}),
1524
+ ...(message.beforeToolId !== undefined ? { toolId: message.beforeToolId } : {}) }
1525
+ : null;
1526
+ let response;
1527
+ try {
1528
+ // 最新のページは常に読み直す(新しい行が増えている)。遡るページは直近の読み取りを使い、
1529
+ // 終端の行がそこに無いときだけ読み直す。
1530
+ // 期限切れの全履歴は要求のたびに捨てる(常駐 daemon に base64 サムネごと残し続けない)。
1531
+ for (const [session, cached] of this.historyPageCache) {
1532
+ if (Date.now() - cached.hostNowMs > HISTORY_PAGE_CACHE_TTL_MS)
1533
+ this.historyPageCache.delete(session);
1534
+ }
1535
+ let history = anchor === null ? undefined : this.historyPageCache.get(message.session);
1536
+ let slice = history === undefined ? null : sliceHistoryPage(history.events, anchor, message.limit);
1537
+ if (slice === null || !slice.anchorFound) {
1538
+ history = await this.readFullHistory(message.session);
1539
+ slice = sliceHistoryPage(history.events, anchor, message.limit);
1540
+ }
1541
+ response = {
1542
+ type: "conversation_history_page_response", id: message.id, session: message.session,
1543
+ lines: slice.events.map((event) => encodeControlMessage(event)),
1544
+ hasMore: slice.hasMore, hostNowMs: history.hostNowMs,
1545
+ ...(slice.anchorFound ? {} : { anchorMissing: true }),
1546
+ };
1547
+ }
1548
+ catch (error) {
1549
+ this.options.log?.(`audit history-page-failed session=${message.session} error=${String(error)}`);
1550
+ response = {
1551
+ type: "conversation_history_page_response", id: message.id, session: message.session,
1552
+ lines: [], hasMore: false, hostNowMs: Date.now(), failed: true,
1553
+ };
1554
+ }
1555
+ this.sendTo(client, response);
1556
+ }
1557
+ /** 全履歴の再送と同じ tail で transcript を最後まで読み、出力を集める(購読者へは流さない)。 */
1558
+ readFullHistory(session) {
1559
+ const inFlight = this.historyPageReads.get(session);
1560
+ if (inFlight !== undefined)
1561
+ return inFlight;
1562
+ const read = new Promise((resolve, reject) => {
1563
+ const factory = this.options.tailFactory;
1564
+ const meta = this.options.metadataStore.get(session);
1565
+ if (factory === undefined || meta === null) {
1566
+ reject(new Error(factory === undefined ? "tail unavailable" : "session metadata not found"));
1567
+ return;
1568
+ }
1569
+ const hostNowMs = Date.now();
1570
+ const events = [];
1571
+ let settled = false;
1572
+ let tail = null;
1573
+ let timer = null;
1574
+ const settle = (error) => {
1575
+ if (settled)
1576
+ return;
1577
+ settled = true;
1578
+ if (timer !== null)
1579
+ clearTimeout(timer);
1580
+ tail?.stop();
1581
+ if (error !== null) {
1582
+ reject(error);
1583
+ return;
1584
+ }
1585
+ const history = { events, hostNowMs };
1586
+ // 直近数件だけ持つ(会話を行き来しても読み直しを減らし、メモリは際限なく持たない)。
1587
+ this.historyPageCache.delete(session);
1588
+ this.historyPageCache.set(session, history);
1589
+ while (this.historyPageCache.size > HISTORY_PAGE_CACHE_LIMIT) {
1590
+ this.historyPageCache.delete(this.historyPageCache.keys().next().value);
1591
+ }
1592
+ resolve(history);
1593
+ };
1594
+ tail = factory((payload) => {
1595
+ if (settled)
1596
+ return;
1597
+ if (payload.type === "chat_output" && payload.streamId === HISTORY_DONE_STREAM_ID) {
1598
+ settle(null);
1599
+ return;
1600
+ }
1601
+ events.push(payload);
1602
+ });
1603
+ if (settled) {
1604
+ tail.stop();
1605
+ return;
1606
+ }
1607
+ timer = setTimeout(() => settle(new Error("history read timed out")), HISTORY_PAGE_READ_TIMEOUT_MS);
1608
+ timer.unref();
1609
+ try {
1610
+ tail.open(meta.cwd, meta.providerSessionId ?? meta.claudeSessionId ?? null, null, meta.agent ?? "claude");
1611
+ }
1612
+ catch (error) {
1613
+ settle(error instanceof Error ? error : new Error(String(error)));
1614
+ }
1615
+ });
1616
+ this.historyPageReads.set(session, read);
1617
+ const clear = () => {
1618
+ if (this.historyPageReads.get(session) === read)
1619
+ this.historyPageReads.delete(session);
1620
+ };
1621
+ read.then(clear, clear);
1622
+ return read;
1623
+ }
1462
1624
  canReplay(actor, afterSeq) {
1463
1625
  const first = actor.replayBuffer[0]?.serverSeq ?? actor.nextServerSeq;
1464
1626
  const last = actor.nextServerSeq - 1;
@@ -2487,7 +2649,12 @@ export class SessionHub {
2487
2649
  };
2488
2650
  }
2489
2651
  try {
2490
- const contents = JSON.stringify({ version: 1, sessions });
2652
+ compactRetiredChatDeliveries(this.retiredChatDeliveries);
2653
+ const contents = JSON.stringify({
2654
+ version: 1, sessions,
2655
+ ...(this.retiredChatDeliveries.size > 0
2656
+ ? { retiredChatDeliveredAtMs: Object.fromEntries(this.retiredChatDeliveries) } : {}),
2657
+ });
2491
2658
  if (this.options.chatReceiptsWriter !== undefined) {
2492
2659
  this.options.chatReceiptsWriter(target, contents);
2493
2660
  }
@@ -2506,6 +2673,49 @@ export class SessionHub {
2506
2673
  return false;
2507
2674
  }
2508
2675
  }
2676
+ readRetiredChatDeliveries() {
2677
+ const target = this.options.chatReceiptsPath;
2678
+ if (target === undefined)
2679
+ return {};
2680
+ try {
2681
+ const parsed = JSON.parse(fs.readFileSync(target, "utf8"));
2682
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
2683
+ return {};
2684
+ const ledger = parsed["retiredChatDeliveredAtMs"];
2685
+ if (typeof ledger !== "object" || ledger === null || Array.isArray(ledger))
2686
+ return {};
2687
+ const result = {};
2688
+ for (const [clientMessageId, deliveredAt] of Object.entries(ledger)) {
2689
+ if (typeof deliveredAt === "number" && Number.isFinite(deliveredAt))
2690
+ result[clientMessageId] = deliveredAt;
2691
+ }
2692
+ return result;
2693
+ }
2694
+ catch {
2695
+ return {};
2696
+ }
2697
+ }
2698
+ /**
2699
+ * Claude 発話の配送状態を、何も登録せずに答える(`chat_receipt_query`, restored-receipt-probe)。
2700
+ * `chat_send` と違い、どの記録にも無い ID を新規として受け付けない(unknown を返すだけ)。
2701
+ * 会話が片付いた後も配送済みは台帳から答える。actor が無ければ作らない。
2702
+ */
2703
+ chatReceiptStatus(session, clientMessageId) {
2704
+ const actor = this.actors.get(session);
2705
+ if (actor !== undefined) {
2706
+ if (hasDeliveredReceipt(actor.deletedChatMessageIds, clientMessageId))
2707
+ return "deleted";
2708
+ if (hasDeliveredReceipt(actor.deliveredChatMessageIds, clientMessageId))
2709
+ return "delivered";
2710
+ if (actor.uncertainChatMessages.has(clientMessageId))
2711
+ return "uncertain";
2712
+ if (actor.pendingChatMessages.has(clientMessageId))
2713
+ return "pending";
2714
+ }
2715
+ if (hasDeliveredReceipt(this.retiredChatDeliveries, clientMessageId))
2716
+ return "delivered";
2717
+ return "unknown";
2718
+ }
2509
2719
  readChatReceipts() {
2510
2720
  const target = this.options.chatReceiptsPath;
2511
2721
  if (target === undefined)
@@ -2673,6 +2883,27 @@ function compactDeliveredReceipts(receipts, now = Date.now()) {
2673
2883
  receipts.delete(oldest);
2674
2884
  }
2675
2885
  }
2886
+ /** 片付けた会話の配送済み receipt の上限(全会話合計)。 */
2887
+ const MAX_RETIRED_CHAT_DELIVERIES = 20_000;
2888
+ function adoptRetiredChatDeliveries(ledger, delivered, now = Date.now()) {
2889
+ for (const [clientMessageId, deliveredAt] of delivered) {
2890
+ ledger.delete(clientMessageId);
2891
+ ledger.set(clientMessageId, deliveredAt);
2892
+ }
2893
+ compactRetiredChatDeliveries(ledger, now);
2894
+ }
2895
+ function compactRetiredChatDeliveries(ledger, now = Date.now()) {
2896
+ for (const [id, deliveredAt] of ledger) {
2897
+ if (now - deliveredAt > DELIVERED_RECEIPT_TTL_MS)
2898
+ ledger.delete(id);
2899
+ }
2900
+ while (ledger.size > MAX_RETIRED_CHAT_DELIVERIES) {
2901
+ const oldest = ledger.keys().next().value;
2902
+ if (oldest === undefined)
2903
+ break;
2904
+ ledger.delete(oldest);
2905
+ }
2906
+ }
2676
2907
  function removeOrderedID(order, id) {
2677
2908
  const index = order.indexOf(id);
2678
2909
  if (index >= 0)