@cocorograph/hub-agent 0.6.84 → 0.6.85
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/state.mjs +55 -22
package/package.json
CHANGED
package/src/state.mjs
CHANGED
|
@@ -132,34 +132,67 @@ function footerRegion(text, lines = 8) {
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
* 現行 claude TUI の生成中フッターは語が毎ターン変わる (実機採取 2026-06-15):
|
|
135
|
+
* 作業スピナー行 (ライブステータス行) の構造パターン。実機採取 (2026-06-15):
|
|
138
136
|
* "· Blanching… (2m 4s · ↓ 7.5k tokens)" (出力中)
|
|
139
137
|
* "✽ Scurrying… (16m 55s · ↓ 66.8k tokens)" (出力中)
|
|
140
138
|
* "· Puzzling… (11m 12s · thinking)" (思考中・tokens 語が無い)
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
139
|
+
* = 行頭グリフ (·/✻/✽/✶… 1 文字) + 語 + 省略記号 + 括弧で囲まれたライブ経過タイマー。
|
|
140
|
+
* 語 (Blanching/Puzzling/Orbiting…) は無数にあり版で増減するため語リストにしない。行頭は
|
|
141
|
+
* 英数字・空白・本文の箇条書き記号 (-*>#|) を除く 1 文字に限定し、本文プローズ (英字始まり)
|
|
142
|
+
* や箇条書きへの誤マッチを防ぐ。完了サマリー "✻ Brewed for 2m 52s" は省略記号も括弧タイマー
|
|
143
|
+
* も持たないので一致しない。
|
|
144
|
+
*/
|
|
145
|
+
const SPINNER_LINE_RE =
|
|
146
|
+
/^\s{0,4}[^\sA-Za-z0-9\-*>#|]\s*[A-Za-z]+(?:…|\.\.\.)\s*\(\s*(?:\d+\s*m\s*)?\d+\s*s\b/
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* スピナー行 i の「下」が入力欄チロム (空行/罫線/❯ プロンプト/tips/字下げ継続/権限バナー)
|
|
150
|
+
* のみかを判定する。ライブのスピナーはペイン最下部の入力欄直上に描かれ、下には本文行が
|
|
151
|
+
* 来ない。一方、本文中に書かれた「スピナー行の引用」(解説テキスト・表セル・コードブロック等)
|
|
152
|
+
* は下に列 0 の本文行が続く。これを使って「未生成なのにローダーが点灯する」誤検出を防ぐ。
|
|
153
|
+
* 列 0 の本文行が下に在れば引用とみなし false。
|
|
154
|
+
*/
|
|
155
|
+
function _belowIsOnlyChrome(lines, i) {
|
|
156
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
157
|
+
const ln = lines[j]
|
|
158
|
+
if (ln.trim() === "") continue // 空行
|
|
159
|
+
if (/^\s*─{3,}\s*$/.test(ln)) continue // 入力欄の罫線
|
|
160
|
+
if (/^\s*[❯>]/.test(ln)) continue // 入力プロンプト
|
|
161
|
+
if (/^\s*⎿/.test(ln)) continue // tips / ツリー装飾行
|
|
162
|
+
if (/^\s{4,}\S/.test(ln)) continue // tips 折り返し等の字下げ継続
|
|
163
|
+
if (
|
|
164
|
+
/shift\+tab|← for|for shortcuts|accept edits|plan mode|auto mode|bypass permissions|new task\?|to save|auto-compact|context left/i.test(
|
|
165
|
+
ln,
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
continue // 権限バナー / フッターのヒント
|
|
169
|
+
return false // 列 0 の本文行 = スピナー行の引用とみなす
|
|
170
|
+
}
|
|
171
|
+
return true
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 作業スピナーのフッター行を検出する (生成中=processing の補助シグナル)。
|
|
146
176
|
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
177
|
+
* 現行版は "esc to interrupt" をフッターに出さない (主シグナルが実機で死んでいる) ため、
|
|
178
|
+
* これが生成中検出の実効シグナルになる。フッター領域 (末尾 12 行) を下から走査し、次の
|
|
179
|
+
* いずれかに一致しかつ「下が入力欄チロムのみ (本文行の引用でない)」行があれば生成中とみなす:
|
|
180
|
+
* (a) スピナー構造行 (SPINNER_LINE_RE)。tokens の有無に依存しないので thinking も拾う。
|
|
181
|
+
* (b) "tokens" 語 + 経過秒の同一行同居 (回帰防止。"(↑ 3.4k tokens · 7s)" の語順も拾う)。
|
|
182
|
+
*
|
|
183
|
+
* 下チロム判定 (_belowIsOnlyChrome) が肝: スピナー行の構造は、本文に「生成中フッターは
|
|
184
|
+
* … (Ns) です」と書いた引用や表セルにも現れ得る。それらは下に本文行が続くため除外し、
|
|
185
|
+
* ペイン最下部の入力欄直上にあるライブのスピナーだけを生成中と判定する (誤点灯防止)。
|
|
154
186
|
*/
|
|
155
187
|
function detectWorkingSpinner(text) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
188
|
+
const lines = text.split("\n")
|
|
189
|
+
const start = Math.max(0, lines.length - 12)
|
|
190
|
+
for (let i = lines.length - 1; i >= start; i--) {
|
|
191
|
+
const line = lines[i]
|
|
192
|
+
const isSpinner = SPINNER_LINE_RE.test(line)
|
|
193
|
+
const isTokenFooter =
|
|
194
|
+
/\btokens\b/i.test(line) && /(?:^|[\s(])\d+\s*s\b/.test(line)
|
|
195
|
+
if ((isSpinner || isTokenFooter) && _belowIsOnlyChrome(lines, i)) return true
|
|
163
196
|
}
|
|
164
197
|
return false
|
|
165
198
|
}
|