@cocorograph/hub-agent 0.7.6 → 0.7.7
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/main.mjs +14 -13
- package/src/state.mjs +29 -1
package/package.json
CHANGED
package/src/main.mjs
CHANGED
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
detectSessionState,
|
|
40
40
|
invalidateSessionCache,
|
|
41
41
|
listSessionStates,
|
|
42
|
+
resolveBindSnapshotStatus,
|
|
42
43
|
StallTracker,
|
|
43
44
|
} from "./state.mjs"
|
|
44
45
|
import {
|
|
@@ -2335,25 +2336,25 @@ async function dispatch(msg, ctx) {
|
|
|
2335
2336
|
noCache: true,
|
|
2336
2337
|
logger,
|
|
2337
2338
|
})
|
|
2338
|
-
//
|
|
2339
|
-
//
|
|
2340
|
-
//
|
|
2341
|
-
//
|
|
2342
|
-
//
|
|
2343
|
-
//
|
|
2344
|
-
//
|
|
2345
|
-
//
|
|
2346
|
-
//
|
|
2339
|
+
// 【問題1 根治 2026-06-22】配る status はプロセス実体の busy を権威に解決する
|
|
2340
|
+
// (resolveBindSnapshotStatus)。capture(SPINNER_LINE_RE)の偽陽性に勝たせる。
|
|
2341
|
+
// - busy=true (ターン進行中): capture gap で snap.status が waiting に化けても
|
|
2342
|
+
// processing を強制 = 症状C(再マウントで生成中の三点リーダーが消える偽陰性)の masking。
|
|
2343
|
+
// - busy=false (プロセス実体 idle): snap.status が processing でも、それは静的完了行の
|
|
2344
|
+
// 偽陽性(無生成時の誤点灯=問題1)なので processing を配らず waiting へ降格する。bind は
|
|
2345
|
+
// noCache 単発読みで freeze 履歴が無く偽陽性を弾けないため、ここで busy を権威にする。
|
|
2346
|
+
// generating(capture 由来)でなく busy(isArmed + 子孫数>baseline)を使うのが肝。
|
|
2347
|
+
// proc_busy は配らない: outputActive(出力残り火)を含み真 idle でも true になり高速消灯
|
|
2348
|
+
// (症状B)を再発させるため。
|
|
2349
|
+
const snapStatus = resolveBindSnapshotStatus(busy, snap.status)
|
|
2347
2350
|
ctx.client.send({
|
|
2348
2351
|
type: "session.state",
|
|
2349
2352
|
session_name: sessionName,
|
|
2350
|
-
status:
|
|
2353
|
+
status: snapStatus,
|
|
2351
2354
|
context_pct: snap.context_pct,
|
|
2352
2355
|
permission_mode: snap.permission_mode,
|
|
2353
2356
|
stable:
|
|
2354
|
-
!
|
|
2355
|
-
snap.status !== "processing" &&
|
|
2356
|
-
snap.stable === true,
|
|
2357
|
+
!busy && snapStatus !== "processing" && snap.stable === true,
|
|
2357
2358
|
})
|
|
2358
2359
|
} catch (err) {
|
|
2359
2360
|
logger?.warn(
|
package/src/state.mjs
CHANGED
|
@@ -243,8 +243,13 @@ function workingSpinnerLine(text) {
|
|
|
243
243
|
* 不変」なら凍結とみなす。閾値は capture キャッシュ TTL (2.5s) と state loop 周期 (5s) を跨ぐ
|
|
244
244
|
* 6s に取り、ライブタイマーの 1 サンプル取りこぼしでは誤判定しないようにする。
|
|
245
245
|
*/
|
|
246
|
+
// 静的な完了行 (● Updated…/⏺ Ran tool (2s) 等、ターン終了後もアイドル画面に残る) を
|
|
247
|
+
// SPINNER_LINE_RE が誤検出して processing に張り付く「無生成時の三点リーダー誤点灯」(問題1) の
|
|
248
|
+
// 滞留時間を短縮するため 6000→3500 に下げた (2026-06-22)。実スピナーは経過秒 (Ns) かグリフ
|
|
249
|
+
// アニメで毎秒変化するため frozen には絶対ならず、閾値短縮で偽陰性(生成中の消失)は再発しない
|
|
250
|
+
// (3500ms ≫ 1s アニメ周期で十分な余裕)。env で上書き可。
|
|
246
251
|
const SPINNER_FREEZE_CONFIRM_MS = Number(
|
|
247
|
-
process.env.HUB_AGENT_SPINNER_FREEZE_MS ??
|
|
252
|
+
process.env.HUB_AGENT_SPINNER_FREEZE_MS ?? 3500,
|
|
248
253
|
)
|
|
249
254
|
/** @type {Map<string, {line: string, at: number}>} session名 → 最初にその行を見た時刻 */
|
|
250
255
|
const _spinnerFreezeByName = new Map()
|
|
@@ -277,6 +282,29 @@ export function detectStatusFromText(text) {
|
|
|
277
282
|
return "idle"
|
|
278
283
|
}
|
|
279
284
|
|
|
285
|
+
/**
|
|
286
|
+
* 【問題1 根治 2026-06-22】bind 時の即時ステータススナップショットで配る status を、
|
|
287
|
+
* プロセス実体の busy を権威として解決する。capture (SPINNER_LINE_RE) の偽陽性に勝たせる。
|
|
288
|
+
*
|
|
289
|
+
* - busy=true (isArmed or pane_pid 子孫数 > baseline = ターン進行中): capture gap で
|
|
290
|
+
* capturedStatus が waiting に化けても processing を強制 (症状C=再マウントで生成中の三点
|
|
291
|
+
* リーダーが消える偽陰性の masking)。
|
|
292
|
+
* - busy=false (プロセス実体 idle): capturedStatus が processing でも、それは静的完了行の
|
|
293
|
+
* SPINNER_LINE_RE 偽陽性であって生成中ではないので processing を配らない (= waiting へ降格)。
|
|
294
|
+
* bind は noCache 単発読みで freeze 履歴が無く偽陽性を弾けないため、ここで busy を権威にする。
|
|
295
|
+
* 万一 no-hook セッションの無音生成中だった場合も、次の state loop tick(≤5s)が outputActive で
|
|
296
|
+
* processing に復帰させるので実害は限定的。
|
|
297
|
+
*
|
|
298
|
+
* @param {boolean} busy プロセス実体の busy (isArmed or 子孫数>baseline)
|
|
299
|
+
* @param {string} capturedStatus detectSessionState の status
|
|
300
|
+
* @returns {string}
|
|
301
|
+
*/
|
|
302
|
+
export function resolveBindSnapshotStatus(busy, capturedStatus) {
|
|
303
|
+
if (busy) return "processing"
|
|
304
|
+
if (capturedStatus === "processing") return "waiting"
|
|
305
|
+
return capturedStatus
|
|
306
|
+
}
|
|
307
|
+
|
|
280
308
|
export function detectContextPctFromText(text) {
|
|
281
309
|
for (const re of CONTEXT_PATTERNS) {
|
|
282
310
|
const m = text.match(re)
|