@cocorograph/hub-agent 0.6.29 → 0.6.31
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.
- package/package.json +1 -1
- package/src/claude-history.mjs +13 -4
- package/src/claude-stream-bridge.mjs +14 -3
package/package.json
CHANGED
package/src/claude-history.mjs
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* - 上限 MAX_HISTORY_LINES (デフォルト 500) で末尾から切る
|
|
14
14
|
* - ファイル不在 (新規セッション) なら空配列を返す (エラーにしない)
|
|
15
15
|
*/
|
|
16
|
-
import { readFile, readdir, stat } from "node:fs/promises"
|
|
16
|
+
import { open, readFile, readdir, stat } from "node:fs/promises"
|
|
17
17
|
import os from "node:os"
|
|
18
18
|
import path from "node:path"
|
|
19
19
|
|
|
@@ -150,13 +150,22 @@ export async function fetchSessionHistory({ cwd, session_id, maxLines, projectsR
|
|
|
150
150
|
* @returns {Promise<string>} 先頭 user メッセージの冒頭 (最大 80 文字)、無ければ ""
|
|
151
151
|
*/
|
|
152
152
|
async function extractPreview(filePath) {
|
|
153
|
+
// P-perf: ファイル全体を readFile してから 64KB に slice すると、肥大化した jsonl で
|
|
154
|
+
// listSessions がセッション数分フル読み込みして重くなる。fd で先頭 64KB だけ読む。
|
|
155
|
+
// preview (最初の user メッセージ冒頭 80 文字) は必ず先頭付近にあるので十分。
|
|
156
|
+
// 64KB 境界でマルチバイト文字 / 行が切れても、末尾の壊れた行は JSON.parse 失敗で
|
|
157
|
+
// skip されるため実害はない。
|
|
153
158
|
let text
|
|
159
|
+
let handle
|
|
154
160
|
try {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
161
|
+
handle = await open(filePath, "r")
|
|
162
|
+
const buf = Buffer.allocUnsafe(65536)
|
|
163
|
+
const { bytesRead } = await handle.read(buf, 0, buf.length, 0)
|
|
164
|
+
text = buf.toString("utf-8", 0, bytesRead)
|
|
158
165
|
} catch {
|
|
159
166
|
return ""
|
|
167
|
+
} finally {
|
|
168
|
+
await handle?.close()
|
|
160
169
|
}
|
|
161
170
|
for (const line of text.split("\n")) {
|
|
162
171
|
if (!line) continue
|
|
@@ -338,6 +338,12 @@ class ClaudeStreamSession {
|
|
|
338
338
|
this._idleTimer = null
|
|
339
339
|
}
|
|
340
340
|
if (opts) this.applyRuntimeOptions(opts)
|
|
341
|
+
// キュー再表示バグ修正 (0.6.30): 再アタッチした端末は queue_state のライブ配信を
|
|
342
|
+
// 取りこぼしている (jsonl hydrate にはキュー状態が含まれない)。現在の pending を
|
|
343
|
+
// force で再 emit し、再表示端末・後から接続した端末の送信待ちチップを復元する。
|
|
344
|
+
// started=[] なのでバブル昇格は起きずチップ更新のみ (冪等)。onEvent は新しい
|
|
345
|
+
// stream_id 宛の stream_group relay で確実に届き、session_group fanout で他端末にも届く。
|
|
346
|
+
this._emitQueueState([], { force: true })
|
|
341
347
|
}
|
|
342
348
|
|
|
343
349
|
/** B11: 端末の最終アクティビティ時刻を更新する (死端末 GC の生存判定に使う)。 */
|
|
@@ -711,13 +717,18 @@ class ClaudeStreamSession {
|
|
|
711
717
|
* @param {string[]} [started] このタイミングで pending から取り出して実行開始した
|
|
712
718
|
* メッセージ本文。drain 由来の emit でのみ渡す。frontend はこれを user バブルへ
|
|
713
719
|
* 昇格させる。キャンセル / 追加由来の emit では空 (昇格させない)。これにより
|
|
714
|
-
* 「先頭の pending をキャンセルした」のを「実行開始した」と誤認しなくなる (0.6.26)。
|
|
715
|
-
|
|
720
|
+
* 「先頭の pending をキャンセルした」のを「実行開始した」と誤認しなくなる (0.6.26)。
|
|
721
|
+
* @param {{force?: boolean}} [opts] force=true のとき署名重複チェックを無視して必ず
|
|
722
|
+
* emit する。再アタッチ時のキュー snapshot 再送 (キュー再表示バグ修正, 0.6.30) に使う。
|
|
723
|
+
* 署名が前回と同一でも browser がライブ配信を取りこぼしている可能性があるため。 */
|
|
724
|
+
_emitQueueState(started = [], opts = undefined) {
|
|
725
|
+
const force = opts?.force === true
|
|
716
726
|
const count = this._pendingMessages.length
|
|
717
727
|
// 署名 = 件数 + id 列。件数が同じでもキャンセルで中身が変われば通知する。
|
|
718
728
|
const sig = `${count}:${this._pendingMessages.map((m) => m.id).join(",")}`
|
|
719
729
|
// started があるときは drain なので、sig 変化が無くても (理論上起きないが) 通知する。
|
|
720
|
-
|
|
730
|
+
// force のときは再アタッチ snapshot なので重複チェックを完全にバイパスする。
|
|
731
|
+
if (!force && started.length === 0 && sig === this._lastEmittedQueueSig) return
|
|
721
732
|
this._lastEmittedQueueSig = sig
|
|
722
733
|
try {
|
|
723
734
|
// messages は全文を載せる。frontend は実行開始 (drain) 時にこれを user バブルへ
|