tailii-host 0.7.1 → 0.8.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.
- package/dist/chat/subagentTranscript.d.ts +7 -0
- package/dist/chat/subagentTranscript.js +44 -0
- package/dist/chat/subagentTranscript.js.map +1 -1
- package/dist/chat/transcriptTailer.d.ts +18 -0
- package/dist/chat/transcriptTailer.js +167 -8
- package/dist/chat/transcriptTailer.js.map +1 -1
- package/dist/commands/launch.d.ts +58 -1
- package/dist/commands/launch.js +161 -4
- package/dist/commands/launch.js.map +1 -1
- package/dist/engine/handlers/claudeModels.js +5 -1
- package/dist/engine/handlers/claudeModels.js.map +1 -1
- package/dist/engine/handlers/conversation.js +38 -0
- package/dist/engine/handlers/conversation.js.map +1 -1
- package/dist/engine/handlers/mode.js +9 -1
- package/dist/engine/handlers/mode.js.map +1 -1
- package/dist/engine/handlers/session.js +11 -2
- package/dist/engine/handlers/session.js.map +1 -1
- package/dist/hub/hubDaemon.js +8 -2
- package/dist/hub/hubDaemon.js.map +1 -1
- package/dist/hub/panePreviewPump.d.ts +8 -0
- package/dist/hub/panePreviewPump.js +15 -0
- package/dist/hub/panePreviewPump.js.map +1 -1
- package/dist/hub/sessionHub.d.ts +35 -1
- package/dist/hub/sessionHub.js +145 -4
- package/dist/hub/sessionHub.js.map +1 -1
- package/dist/protocol/decode.d.ts +4 -0
- package/dist/protocol/decode.js +50 -2
- package/dist/protocol/decode.js.map +1 -1
- package/dist/protocol/encode.js +2 -0
- package/dist/protocol/encode.js.map +1 -1
- package/dist/protocol/messages.d.ts +39 -0
- package/dist/push/approvalPushNotifier.d.ts +19 -0
- package/dist/push/approvalPushNotifier.js +26 -2
- package/dist/push/approvalPushNotifier.js.map +1 -1
- package/dist/push/pushTypes.d.ts +4 -1
- package/dist/push/pushTypes.js +4 -2
- package/dist/push/pushTypes.js.map +1 -1
- package/dist/services/claudeModelCatalog.d.ts +14 -0
- package/dist/services/claudeModelCatalog.js +47 -0
- package/dist/services/claudeModelCatalog.js.map +1 -1
- package/dist/services/peerSessions.d.ts +36 -0
- package/dist/services/peerSessions.js +114 -0
- package/dist/services/peerSessions.js.map +1 -0
- package/dist/shared/clientBuild.d.ts +1 -1
- package/dist/shared/clientBuild.js +1 -1
- package/dist/shared/systemNotice.js +9 -0
- package/dist/shared/systemNotice.js.map +1 -1
- package/dist/shared/usageLimitWait.d.ts +18 -0
- package/dist/shared/usageLimitWait.js +72 -0
- package/dist/shared/usageLimitWait.js.map +1 -0
- package/package.json +3 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// panePreviewPump.ts
|
|
2
2
|
// tailii (TS host) — foreground tmux pane のライブプレビュー配信。
|
|
3
3
|
import { parsePermissionMode } from "../shared/permissionMode.js";
|
|
4
|
+
import { parseUsageLimitWait, sameUsageLimitWait } from "../shared/usageLimitWait.js";
|
|
4
5
|
import { extractInputBoxSuggestion } from "../backend/tmux.js";
|
|
5
6
|
import { PROTOCOL_V2 } from "../protocol.js";
|
|
6
7
|
import { abortableSleep } from "../shared/sleep.js";
|
|
@@ -24,6 +25,8 @@ export class PanePreviewPump {
|
|
|
24
25
|
session = null;
|
|
25
26
|
mode = "claude_status";
|
|
26
27
|
onPermissionMode;
|
|
28
|
+
onUsageLimitWait;
|
|
29
|
+
lastUsageLimitWait = null;
|
|
27
30
|
log;
|
|
28
31
|
emitInitialIf;
|
|
29
32
|
captureSuggestion;
|
|
@@ -43,6 +46,7 @@ export class PanePreviewPump {
|
|
|
43
46
|
this.quietThresholdMs = options.quietThresholdMs ?? 2500;
|
|
44
47
|
this.protocolVersion = options.protocolVersion ?? (() => PROTOCOL_V2);
|
|
45
48
|
this.onPermissionMode = options.onPermissionMode ?? null;
|
|
49
|
+
this.onUsageLimitWait = options.onUsageLimitWait ?? null;
|
|
46
50
|
this.log = options.log ?? null;
|
|
47
51
|
this.emitInitialIf = options.emitInitialIf ?? null;
|
|
48
52
|
this.captureSuggestion = options.captureSuggestion ?? null;
|
|
@@ -143,6 +147,14 @@ export class PanePreviewPump {
|
|
|
143
147
|
this.onPermissionMode(permissionMode);
|
|
144
148
|
}
|
|
145
149
|
}
|
|
150
|
+
if (text !== null && mode === "claude_status" && this.onUsageLimitWait !== null) {
|
|
151
|
+
// 使用量制限の待機フッター(usage-limit-wait)。遷移したフレームでだけ通知する。
|
|
152
|
+
const wait = parseUsageLimitWait(text);
|
|
153
|
+
if (!sameUsageLimitWait(wait, this.lastUsageLimitWait)) {
|
|
154
|
+
this.lastUsageLimitWait = wait;
|
|
155
|
+
this.onUsageLimitWait(wait);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
146
158
|
const now = Date.now();
|
|
147
159
|
if (text !== null && text !== this.lastText) {
|
|
148
160
|
if (this.lastText === null) {
|
|
@@ -182,6 +194,9 @@ export class PanePreviewPump {
|
|
|
182
194
|
// プロンプト提案(薄字ゴースト)の抽出・配信(claude_status のみ・低頻度・変化時だけ)。
|
|
183
195
|
if (mode === "claude_status" &&
|
|
184
196
|
this.captureSuggestion !== null &&
|
|
197
|
+
// 低頻度の見張り(制限待ち, usage-limit-wait)中は提案抽出を行わない(数時間の静止画面で毎周回
|
|
198
|
+
// 2 回 capture しない)。
|
|
199
|
+
this.pollIntervalMs() < 5000 &&
|
|
185
200
|
now - this.lastSuggestionAt >= this.suggestionIntervalMs) {
|
|
186
201
|
this.lastSuggestionAt = now;
|
|
187
202
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"panePreviewPump.js","sourceRoot":"","sources":["../../src/hub/panePreviewPump.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,uDAAuD;AAGvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"panePreviewPump.js","sourceRoot":"","sources":["../../src/hub/panePreviewPump.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,uDAAuD;AAGvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAA4B,MAAM,6BAA6B,CAAC;AAChH,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AA8CpD,iDAAiD;AACjD,MAAM,OAAO,eAAe;IACT,MAAM,CAAa;IACnB,OAAO,CAAqB;IAC5B,cAAc,CAAe;IAC7B,gBAAgB,CAAS;IACzB,eAAe,CAAe;IACvC,eAAe,GAA2B,IAAI,CAAC;IAC/C,IAAI,GAAyB,IAAI,CAAC;IAClC,GAAG,GAAG,CAAC,CAAC;IACR,QAAQ,GAAkB,IAAI,CAAC;IAC/B,YAAY,GAAG,CAAC,CAAC;IACjB,UAAU,GAAG,CAAC,CAAC;IACf,WAAW,GAAkB,IAAI,CAAC;IAClC,UAAU,GAAG,KAAK,CAAC;IACnB,MAAM,GAAG,KAAK,CAAC;IACf,YAAY,GAAG,KAAK,CAAC;IACrB,OAAO,GAAkB,IAAI,CAAC;IAC9B,IAAI,GAAoB,eAAe,CAAC;IAC/B,gBAAgB,CAAkC;IAClD,gBAAgB,CAAuD;IAChF,kBAAkB,GAA+B,IAAI,CAAC;IAC7C,GAAG,CAAqC;IACxC,aAAa,CAAqC;IAClD,iBAAiB,CAAgD;IACjE,oBAAoB,CAAS;IAC9C,6CAA6C;IACrC,cAAc,GAAkB,IAAI,CAAC;IACrC,gBAAgB,GAAG,CAAC,CAAC;IACrB,kBAAkB,GAAkB,IAAI,CAAC;IACzC,iBAAiB,GAAG,KAAK,CAAC;IAC1B,WAAW,GAAG,KAAK,CAAC;IACpB,MAAM,CAAU,iBAAiB,GAAG,GAAG,CAAC;IAEhD,YAAY,OAA+B;QACzC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,GAAG,CAAC;QACrD,IAAI,CAAC,cAAc,GAAG,OAAO,cAAc,KAAK,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC;QACnG,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;QACzD,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC;QACtE,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;QACzD,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;QACzD,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC;QAC/B,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,IAAI,CAAC;QACnD,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,IAAI,IAAI,CAAC;QAC3D,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,IAAI,IAAI,CAAC;IACnE,CAAC;IAED;;;;OAIG;IACH,uBAAuB;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC3B,IAAI,OAAO,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI;YAAE,OAAO;QAC7E,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YAAE,OAAO;QACtC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACxD,CAAC;IAED;;;;OAIG;IACH,KAAK,CACH,OAAe,EACf,IAAI,GAAoB,eAAe,EACvC,IAAgC;QAEhC,IAAI,IAAI,CAAC,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO;QACjF,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,WAAW,GAAG,IAAI,EAAE,WAAW,IAAI,KAAK,CAAC;QAC9C,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC;QAC1B,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC5B,CAAC;IAED,8DAA8D;IAC9D,IAAI;QACF,IAAI,CAAC,eAAe,EAAE,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,mCAAmC;QACnC,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,IAAI,IAAI,CAAC,cAAc,KAAK,EAAE,EAAE,CAAC;YACxF,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC;QAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC5B,CAAC;IAEO,KAAK,CAAC,GAAG,CAAC,OAAe,EAAE,IAAqB,EAAE,MAAmB;QAC3E,iDAAiD;QACjD,4CAA4C;QAC5C,IAAI,mBAAmB,GAAG,CAAC,CAAC;QAC5B,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,IAAI,GAAkB,IAAI,CAAC;YAC/B,IAAI,CAAC;gBACH,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACnC,mBAAmB,GAAG,CAAC,CAAC;YAC1B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,mBAAmB,IAAI,CAAC,CAAC;gBACzB,IAAI,mBAAmB,KAAK,CAAC,IAAI,mBAAmB,GAAG,GAAG,KAAK,CAAC,EAAE,CAAC;oBACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,8CAA8C;wBAC5C,CAAC,mBAAmB,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,mBAAmB,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC/D,KAAK,MAAM,CAAC,KAAK,CAAC,IAAI,CACzB,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,eAAe,IAAI,IAAI,CAAC,gBAAgB,KAAK,IAAI,EAAE,CAAC;gBAChF,+CAA+C;gBAC/C,MAAM,cAAc,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;gBACjD,IAAI,cAAc,KAAK,IAAI,IAAI,cAAc,KAAK,IAAI,CAAC,kBAAkB,EAAE,CAAC;oBAC1E,IAAI,CAAC,kBAAkB,GAAG,cAAc,CAAC;oBACzC,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;gBACxC,CAAC;YACH,CAAC;YACD,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,eAAe,IAAI,IAAI,CAAC,gBAAgB,KAAK,IAAI,EAAE,CAAC;gBAChF,kDAAkD;gBAClD,MAAM,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;gBACvC,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC;oBACvD,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;oBAC/B,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;YAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC5C,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;oBAC3B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;oBACrB,oCAAoC;oBACpC,oDAAoD;oBACpD,4BAA4B;oBAC5B,oDAAoD;oBACpD,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,KAAK,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;oBAC5E,IAAI,CAAC,IAAI,KAAK,gBAAgB,IAAI,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC7F,IAAI,CAAC,YAAY,GAAG,GAAG,CAAC;wBACxB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;wBAC1B,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;oBAC7C,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;oBACrB,IAAI,CAAC,YAAY,GAAG,GAAG,CAAC;oBACxB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;oBAC1B,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;YAED,IACE,IAAI,CAAC,WAAW,KAAK,IAAI;gBACzB,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,eAAe,CAAC,iBAAiB,EAC1D,CAAC;gBACD,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YACxD,CAAC;iBAAM,IACL,IAAI,KAAK,gBAAgB;gBACzB,IAAI,CAAC,MAAM;gBACX,CAAC,IAAI,CAAC,YAAY;gBAClB,IAAI,CAAC,UAAU;gBACf,IAAI,CAAC,YAAY,GAAG,CAAC;gBACrB,GAAG,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,gBAAgB,EAChD,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;gBAC9B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;gBACzB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACtB,CAAC;YAED,qDAAqD;YACrD,IACE,IAAI,KAAK,eAAe;gBACxB,IAAI,CAAC,iBAAiB,KAAK,IAAI;gBAC/B,0DAA0D;gBAC1D,oBAAoB;gBACpB,IAAI,CAAC,cAAc,EAAE,GAAG,IAAI;gBAC5B,GAAG,GAAG,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,oBAAoB,EACxD,CAAC;gBACD,IAAI,CAAC,gBAAgB,GAAG,GAAG,CAAC;gBAC5B,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;oBACnD,MAAM,UAAU,GAAG,yBAAyB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;oBACzD,oDAAoD;oBACpD,4CAA4C;oBAC5C,MAAM,kBAAkB,GAAG,IAAI,CAAC,cAAc,KAAK,IAAI,IAAI,UAAU,KAAK,EAAE,CAAC;oBAC7E,IAAI,UAAU,KAAK,IAAI,CAAC,cAAc,IAAI,CAAC,kBAAkB,EAAE,CAAC;wBAC9D,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;oBAC3C,CAAC;oBACD,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC;gBACnC,CAAC;gBAAC,MAAM,CAAC;oBACP,2CAA2C;gBAC7C,CAAC;YACH,CAAC;YAED,MAAM,cAAc,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,MAAM,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAEO,cAAc,CAAC,OAAe,EAAE,IAAY;QAClD,MAAM,CAAC,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QACjC,IAAI,CAAC,GAAG,WAAW;YAAE,OAAO;QAC5B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,CAAC;IAEO,WAAW,CAAC,OAAe,EAAE,IAAY,EAAE,GAAW,EAAE,IAAqB;QACnF,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,eAAe,CAAC,iBAAiB,EAAE,CAAC;YACnF,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAC1C,OAAO;QACT,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;IAEO,UAAU,CAAC,OAAe,EAAE,IAAY,EAAE,GAAW,EAAE,IAAqB;QAClF,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,yCAAyC;QACzC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;QACrD,IAAI,WAAW,KAAK,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3C,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC;YACrC,IAAI,CAAC,GAAG,EAAE,CACR,6BAA6B,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,YAAY,OAAO,UAAU,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CACrH,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACvC,CAAC;IAEO,IAAI,CACV,OAAe,EACf,MAAe,EACf,IAAY,EACZ,IAAI,GAAoB,IAAI,CAAC,IAAI;QAEjC,MAAM,CAAC,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QACjC,IAAI,CAAC,GAAG,WAAW;YAAE,OAAO;QAC5B,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACd,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;YAChB,IAAI,EAAE,cAAc;YACpB,CAAC;YACD,OAAO;YACP,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,MAAM;YACN,IAAI;YACJ,GAAG,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/C,CAAC,CAAC;IACL,CAAC;CACF"}
|
package/dist/hub/sessionHub.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { type ClaudeTurnLifecycleEvent } from "../chat/transcriptTailer.js";
|
|
|
6
6
|
import type { ChatAgent } from "../chat/chatTailController.js";
|
|
7
7
|
import type { ImageService } from "../chat/imageService.js";
|
|
8
8
|
import type { PanePreviewMode } from "./panePreviewPump.js";
|
|
9
|
+
import { type UsageLimitWaitState } from "../shared/usageLimitWait.js";
|
|
9
10
|
import type { QuestionAnswer } from "../protocol.js";
|
|
10
11
|
import { type CodexAppServerThreadRuntime, type CodexNativeTurnControllerOptions, type CodexTurnControllerRuntime } from "../codex/codexNativeTurnController.js";
|
|
11
12
|
import { type CodexTurnLifecycleEvent } from "../codex/codexRolloutTailer.js";
|
|
@@ -37,7 +38,9 @@ export interface ChatInjectContext {
|
|
|
37
38
|
export type HubTailFactory = (write: (payload: ControlMessage) => void, onCodexTurnLifecycle?: (event: CodexTurnLifecycleEvent) => void, onClaudeTurnLifecycle?: (event: ClaudeTurnLifecycleEvent) => void) => HubTail;
|
|
38
39
|
export type HubPreviewPumpFactory = (write: (payload: ControlMessage) => void, onPermissionMode?: (mode: string) => void,
|
|
39
40
|
/** 毎周期評価するポーリング間隔(ms)。前面購読あり=高頻度 / 一覧 watch のみ=低頻度。 */
|
|
40
|
-
pollIntervalMs?: () => number
|
|
41
|
+
pollIntervalMs?: () => number,
|
|
42
|
+
/** 使用量制限の自動再開待ち(pane フッター)の遷移通知(usage-limit-wait)。 */
|
|
43
|
+
onUsageLimitWait?: (state: UsageLimitWaitState | null) => void) => HubPreviewPump;
|
|
41
44
|
export type SessionHubOptions = Omit<ReaperTickOptions, "now"> & {
|
|
42
45
|
/** Unix 秒。テストでは固定時計を注入する。 */
|
|
43
46
|
now?: () => number;
|
|
@@ -57,6 +60,14 @@ export type SessionHubOptions = Omit<ReaperTickOptions, "now"> & {
|
|
|
57
60
|
previewPumpFactory?: HubPreviewPumpFactory;
|
|
58
61
|
replayLimit?: number;
|
|
59
62
|
questionInjector?: (answers: QuestionAnswer[], session: string) => Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* 使用量制限の自動再開待ちの遷移を利用者へ知らせる(APNs push, usage-limit-wait)。制限到達
|
|
65
|
+
* (`api_error` の `rate_limit`)後は購読者が居なくても pane を低頻度で見張り、待機表示の出現・
|
|
66
|
+
* Enter 待ち・停止・再開を 1 回ずつ通知する。省略時は通知しない(テスト / push 未設定)。
|
|
67
|
+
*/
|
|
68
|
+
usageLimitNotify?: (session: string, state: UsageLimitWaitState | {
|
|
69
|
+
kind: "resumed";
|
|
70
|
+
}) => void;
|
|
60
71
|
chatInjector?: (text: string, session: string, context: ChatInjectContext) => Promise<void>;
|
|
61
72
|
codexAppServerFactory?: () => CodexAppServerThreadRuntime;
|
|
62
73
|
codexTurnControllerFactory?: (options: CodexNativeTurnControllerOptions) => CodexTurnControllerRuntime;
|
|
@@ -170,6 +181,16 @@ interface SessionActor {
|
|
|
170
181
|
tail: HubTail | null;
|
|
171
182
|
tailRetryTimer: ReturnType<typeof setTimeout> | null;
|
|
172
183
|
previewPump: HubPreviewPump | null;
|
|
184
|
+
/**
|
|
185
|
+
* 使用量制限の自動再開待ちの見張り(usage-limit-wait)。制限到達で武装し、待機表示が消える
|
|
186
|
+
* (再開 / キャンセル)か期限で解除する。武装中は購読者が居なくても pump を低頻度で回す。
|
|
187
|
+
*/
|
|
188
|
+
usageLimitWatch: {
|
|
189
|
+
state: UsageLimitWaitState | null;
|
|
190
|
+
timer: ReturnType<typeof setTimeout> | null;
|
|
191
|
+
/** 待機表示が消えたフレームからの猶予(再描画の過渡で 1 フレーム写らないだけの消失で畳まない)。 */
|
|
192
|
+
missingTimer: ReturnType<typeof setTimeout> | null;
|
|
193
|
+
} | null;
|
|
173
194
|
backfillTails: Map<object, HubTail>;
|
|
174
195
|
seenClientMessageIds: Set<string>;
|
|
175
196
|
deliveredChatMessageIds: Map<string, number>;
|
|
@@ -307,6 +328,19 @@ export declare class SessionHub {
|
|
|
307
328
|
* その dismiss と chat queue の drain)。中断はターン終了なので Stop 後と同じ振る舞い。
|
|
308
329
|
*/
|
|
309
330
|
private handleClaudeTurnLifecycle;
|
|
331
|
+
/** 見張りを武装する制限到達マーカーの新しさ(履歴再生の古い rate_limit では武装しない)。 */
|
|
332
|
+
private static readonly USAGE_LIMIT_ARM_RECENT_MS;
|
|
333
|
+
/** 待機表示が現れないまま見張りを畳む猶予(制限到達直後に TUI がフッターを描くまでの窓 + 余裕)。 */
|
|
334
|
+
private static readonly USAGE_LIMIT_ARM_GRACE_MS;
|
|
335
|
+
/** 待機表示の消失から見張りを畳むまでの猶予(過渡フレームの取りこぼしを吸収。5s poll の数周)。 */
|
|
336
|
+
private static readonly USAGE_LIMIT_MISSING_GRACE_MS;
|
|
337
|
+
/** 待機表示を観測した後の見張り上限(週次制限のリセットでも一晩は見張る)。 */
|
|
338
|
+
private static readonly USAGE_LIMIT_WATCH_MAX_MS;
|
|
339
|
+
/** 使用量制限の自動再開待ちの見張りを武装する(usage-limit-wait)。既に武装中なら猶予を延ばすだけ。 */
|
|
340
|
+
private armUsageLimitWatch;
|
|
341
|
+
private disarmUsageLimitWatch;
|
|
342
|
+
/** pump からの待機フッターの遷移(null = 表示なし)。通知は遷移ごとに 1 回。 */
|
|
343
|
+
private handleUsageLimitWait;
|
|
310
344
|
/** 遅着 hook が直書きした active の heartbeat を idle へ戻す(その hook の書込のままのときだけ)。 */
|
|
311
345
|
private revertLateHookHeartbeat;
|
|
312
346
|
/**
|
package/dist/hub/sessionHub.js
CHANGED
|
@@ -7,6 +7,7 @@ import { bumpHeartbeat, listHeartbeatSessions, readHeartbeat, writeHeartbeat } f
|
|
|
7
7
|
import { ensureDirectory0700 } from "../shared/paths.js";
|
|
8
8
|
import { decodeHubClientLine, encodeHubMessage, } from "./hubProtocol.js";
|
|
9
9
|
import { HISTORY_DONE_STREAM_ID, findTrailingTurnEndMarkerMs, findTrailingUserPromptText, } from "../chat/transcriptTailer.js";
|
|
10
|
+
import { sameUsageLimitWait } from "../shared/usageLimitWait.js";
|
|
10
11
|
import { PROTOCOL_V1, PROTOCOL_V2 } from "../protocol.js";
|
|
11
12
|
import { LoginCodeError } from "../backend/tmux.js";
|
|
12
13
|
import { CodexAppServerManager } from "../codex/codexAppServer.js";
|
|
@@ -319,6 +320,12 @@ export class SessionHub {
|
|
|
319
320
|
if (changed) {
|
|
320
321
|
this.options.log?.(`audit preview-watch ${message.enabled ? "start" : "stop"} watchers=${this.previewWatchers.size}`);
|
|
321
322
|
this.syncAllPreviews();
|
|
323
|
+
// 静止した画面(制限待ちフッター / 入力待ちダイアログ)は変化フレームが出ないため、watch 開始時に
|
|
324
|
+
// 稼働中 pump の直近フレームを再送する(usage-limit-wait の一覧ピル)。
|
|
325
|
+
if (message.enabled) {
|
|
326
|
+
for (const actor of this.actors.values())
|
|
327
|
+
actor.previewPump?.resendLastIfInteractive?.();
|
|
328
|
+
}
|
|
322
329
|
}
|
|
323
330
|
return;
|
|
324
331
|
}
|
|
@@ -647,6 +654,11 @@ export class SessionHub {
|
|
|
647
654
|
this.bumpSafe(session, "hub-processing", "active");
|
|
648
655
|
if (actor.pendingQuestion !== null)
|
|
649
656
|
this.bumpSafe(session, "hub-question", "active");
|
|
657
|
+
// 使用量制限の自動再開待ち(usage-limit-wait): Claude Code は入力待ちで静止したまま数時間待つ。
|
|
658
|
+
// 放置すると reaper が 30 分で pane ごと kill して自動再開が永久に起きないため、見張り中は
|
|
659
|
+
// 利用中とみなして heartbeat を進める。
|
|
660
|
+
if (actor.usageLimitWatch !== null)
|
|
661
|
+
this.bumpSafe(session, "hub-usage-limit-wait");
|
|
650
662
|
}
|
|
651
663
|
const result = await reaperTick({ ...this.options, now: this.now() });
|
|
652
664
|
// reaper の判定と actor の処理中フラグを同期する。demote(プロセス死亡)や kill 後も
|
|
@@ -704,6 +716,13 @@ export class SessionHub {
|
|
|
704
716
|
actor.tail = null;
|
|
705
717
|
actor.previewPump?.stop();
|
|
706
718
|
actor.previewPump = null;
|
|
719
|
+
if (actor.usageLimitWatch !== null) {
|
|
720
|
+
if (actor.usageLimitWatch.timer !== null)
|
|
721
|
+
clearTimeout(actor.usageLimitWatch.timer);
|
|
722
|
+
if (actor.usageLimitWatch.missingTimer !== null)
|
|
723
|
+
clearTimeout(actor.usageLimitWatch.missingTimer);
|
|
724
|
+
actor.usageLimitWatch = null;
|
|
725
|
+
}
|
|
707
726
|
for (const tail of actor.backfillTails.values())
|
|
708
727
|
tail.stop();
|
|
709
728
|
actor.backfillTails.clear();
|
|
@@ -1347,7 +1366,9 @@ export class SessionHub {
|
|
|
1347
1366
|
const wantsForeground = [...actor.subscribers.values()].some((state) => state.preview);
|
|
1348
1367
|
// 一覧 Mission Control: watcher がいる間、処理中会話は前面購読が無くても pump する。
|
|
1349
1368
|
const wantsWatch = this.previewWatchers.size > 0 && actor.processingSince !== null;
|
|
1350
|
-
|
|
1369
|
+
// 使用量制限の自動再開待ちの見張り(usage-limit-wait): 購読者が居なくても低頻度で回す。
|
|
1370
|
+
const wantsLimitWatch = actor.usageLimitWatch !== null;
|
|
1371
|
+
if (!wantsForeground && !wantsWatch && !wantsLimitWatch) {
|
|
1351
1372
|
if (actor.previewPump !== null)
|
|
1352
1373
|
this.options.log?.(`audit preview-pump stop session=${session}`);
|
|
1353
1374
|
actor.previewPump?.stop();
|
|
@@ -1373,7 +1394,8 @@ export class SessionHub {
|
|
|
1373
1394
|
// watcher へは処理中の会話だけ流す(前面都合で動く pump のアイドル画面は一覧に不要)。
|
|
1374
1395
|
// 消灯フレーム(active=false)だけは処理完了直後でも届け、一覧側の表示を確実に落とす。
|
|
1375
1396
|
const inactiveFrame = outgoingPayload.type === "pane_preview" && !outgoingPayload.active;
|
|
1376
|
-
|
|
1397
|
+
// 制限待ちの見張り中(usage-limit-wait)も一覧へ流す(一覧の「制限待ち」ピル用)。
|
|
1398
|
+
if (actor.processingSince !== null || inactiveFrame || actor.usageLimitWatch !== null) {
|
|
1377
1399
|
for (const watcher of this.previewWatchers) {
|
|
1378
1400
|
if (!delivered.has(watcher)) {
|
|
1379
1401
|
this.sendTo(watcher, {
|
|
@@ -1397,7 +1419,18 @@ export class SessionHub {
|
|
|
1397
1419
|
}
|
|
1398
1420
|
},
|
|
1399
1421
|
// 前面購読が無い(一覧 watch だけの)間は低頻度で capture し、多重 pump のコストを抑える。
|
|
1400
|
-
|
|
1422
|
+
// 制限待ちの見張りだけの間はさらに低頻度(5s)。
|
|
1423
|
+
() => {
|
|
1424
|
+
if ([...actor.subscribers.values()].some((state) => state.preview))
|
|
1425
|
+
return 250;
|
|
1426
|
+
if (this.previewWatchers.size > 0 && actor.processingSince !== null)
|
|
1427
|
+
return 1000;
|
|
1428
|
+
// 制限待ちの見張り: 数時間の静止画面を 5s で見る(再開は処理中遷移 = hook が権威なので、
|
|
1429
|
+
// 再開中の過渡表示を取りこぼしても構わない)。
|
|
1430
|
+
if (actor.usageLimitWatch !== null)
|
|
1431
|
+
return 5000;
|
|
1432
|
+
return 1000;
|
|
1433
|
+
}, (state) => this.handleUsageLimitWait(session, actor, state));
|
|
1401
1434
|
actor.previewPump = pump;
|
|
1402
1435
|
pump.start(session, this.options.metadataStore.get(session)?.agent === "codex" ? "codex_terminal" : "claude_status",
|
|
1403
1436
|
// 処理中の pump 起動(=一覧 watch 起因が典型)は初回フレームから送る。静止 pane
|
|
@@ -1411,7 +1444,7 @@ export class SessionHub {
|
|
|
1411
1444
|
lastTurnEndMs: null, turnStartFiredAtMs: null, lastTurnStartMs: null,
|
|
1412
1445
|
focusedBy: new Set(), subscribers: new Map(),
|
|
1413
1446
|
nextServerSeq: 1, replayBuffer: [], tail: null, tailRetryTimer: null,
|
|
1414
|
-
previewPump: null, backfillTails: new Map(),
|
|
1447
|
+
previewPump: null, usageLimitWatch: null, backfillTails: new Map(),
|
|
1415
1448
|
seenClientMessageIds: new Set(), deliveredChatMessageIds: new Map(),
|
|
1416
1449
|
deliveredCodexMessageIds: new Map(),
|
|
1417
1450
|
deletedChatMessageIds: new Map(), deletedCodexMessageIds: new Map(),
|
|
@@ -1851,6 +1884,13 @@ export class SessionHub {
|
|
|
1851
1884
|
}
|
|
1852
1885
|
if (event.kind !== "interrupted" && event.kind !== "api_error")
|
|
1853
1886
|
return;
|
|
1887
|
+
// 使用量制限(rate_limit): Claude Code 2.1.234〜は待機して自動再開する。pane の待機フッターを
|
|
1888
|
+
// 見張り、遷移を push で知らせる(usage-limit-wait)。処理中判定とは独立に武装する。
|
|
1889
|
+
// 履歴再生の古いマーカーでは武装しない(直近 10 分以内の live な制限到達だけ)。
|
|
1890
|
+
if (event.kind === "api_error" && event.errorKind === "rate_limit" &&
|
|
1891
|
+
this.nowMs() - event.atMs <= SessionHub.USAGE_LIMIT_ARM_RECENT_MS) {
|
|
1892
|
+
this.armUsageLimitWatch(session, actor);
|
|
1893
|
+
}
|
|
1854
1894
|
if (actor.processingSince === null) {
|
|
1855
1895
|
// 処理中でなくても終端の時刻は覚える: 終端より前に発火した hook(別プロセス起動 + relay で遅着する
|
|
1856
1896
|
// UserPromptSubmit / Pre・PostToolUse)は既に終わったターンの残響として無視する
|
|
@@ -1872,6 +1912,99 @@ export class SessionHub {
|
|
|
1872
1912
|
this.applyProcessing(session, "done");
|
|
1873
1913
|
this.broadcast({ type: "session_processing", session, state: "done" });
|
|
1874
1914
|
}
|
|
1915
|
+
/** 見張りを武装する制限到達マーカーの新しさ(履歴再生の古い rate_limit では武装しない)。 */
|
|
1916
|
+
static USAGE_LIMIT_ARM_RECENT_MS = 10 * 60 * 1000;
|
|
1917
|
+
/** 待機表示が現れないまま見張りを畳む猶予(制限到達直後に TUI がフッターを描くまでの窓 + 余裕)。 */
|
|
1918
|
+
static USAGE_LIMIT_ARM_GRACE_MS = 120_000;
|
|
1919
|
+
/** 待機表示の消失から見張りを畳むまでの猶予(過渡フレームの取りこぼしを吸収。5s poll の数周)。 */
|
|
1920
|
+
static USAGE_LIMIT_MISSING_GRACE_MS = 30_000;
|
|
1921
|
+
/** 待機表示を観測した後の見張り上限(週次制限のリセットでも一晩は見張る)。 */
|
|
1922
|
+
static USAGE_LIMIT_WATCH_MAX_MS = 12 * 60 * 60 * 1000;
|
|
1923
|
+
/** 使用量制限の自動再開待ちの見張りを武装する(usage-limit-wait)。既に武装中なら猶予を延ばすだけ。 */
|
|
1924
|
+
armUsageLimitWatch(session, actor) {
|
|
1925
|
+
const existing = actor.usageLimitWatch;
|
|
1926
|
+
// 待機表示を観測済みの見張りは上限タイマーのまま触らない(繰り返し到達で猶予タイマーに差し替えると、
|
|
1927
|
+
// 猶予発火時に state があるため何もせずタイマーだけ消え、見張りが永久化する)。
|
|
1928
|
+
if (existing !== null && existing.state !== null)
|
|
1929
|
+
return;
|
|
1930
|
+
if (existing !== null && existing.timer !== null)
|
|
1931
|
+
clearTimeout(existing.timer);
|
|
1932
|
+
const watch = existing ?? { state: null, timer: null, missingTimer: null };
|
|
1933
|
+
watch.timer = setTimeout(() => {
|
|
1934
|
+
if (this.actors.get(session) !== actor || actor.usageLimitWatch !== watch)
|
|
1935
|
+
return;
|
|
1936
|
+
if (watch.state === null) {
|
|
1937
|
+
this.options.log?.(`usage-limit-watch 待機表示なしで解除 session=${session}`);
|
|
1938
|
+
this.disarmUsageLimitWatch(session, actor);
|
|
1939
|
+
}
|
|
1940
|
+
}, SessionHub.USAGE_LIMIT_ARM_GRACE_MS);
|
|
1941
|
+
watch.timer.unref?.();
|
|
1942
|
+
actor.usageLimitWatch = watch;
|
|
1943
|
+
this.options.log?.(`usage-limit-watch 武装 session=${session}`);
|
|
1944
|
+
this.syncPreview(session, actor);
|
|
1945
|
+
}
|
|
1946
|
+
disarmUsageLimitWatch(session, actor) {
|
|
1947
|
+
const watch = actor.usageLimitWatch;
|
|
1948
|
+
if (watch === null)
|
|
1949
|
+
return;
|
|
1950
|
+
if (watch.timer !== null)
|
|
1951
|
+
clearTimeout(watch.timer);
|
|
1952
|
+
if (watch.missingTimer !== null)
|
|
1953
|
+
clearTimeout(watch.missingTimer);
|
|
1954
|
+
actor.usageLimitWatch = null;
|
|
1955
|
+
this.syncPreview(session, actor);
|
|
1956
|
+
}
|
|
1957
|
+
/** pump からの待機フッターの遷移(null = 表示なし)。通知は遷移ごとに 1 回。 */
|
|
1958
|
+
handleUsageLimitWait(session, actor, state) {
|
|
1959
|
+
if (this.actors.get(session) !== actor)
|
|
1960
|
+
return;
|
|
1961
|
+
const watch = actor.usageLimitWatch;
|
|
1962
|
+
// 武装外(直近の rate_limit 到達が無い)の観測は無視する。前ターンの待機行が pane に残っている
|
|
1963
|
+
// だけの処理中フレームで push しない(10 分 recency gate の迂回を塞ぐ)。
|
|
1964
|
+
if (watch === null)
|
|
1965
|
+
return;
|
|
1966
|
+
const previous = watch.state;
|
|
1967
|
+
this.options.log?.(`usage-limit-wait session=${session} ${previous?.kind ?? "none"} -> ${state?.kind ?? "none"}` +
|
|
1968
|
+
(state?.kind === "waiting" && state.resumeAt !== null ? ` at=${state.resumeAt}` : ""));
|
|
1969
|
+
// 前面で見ている購読者が居る間は push しない(承認 push の presence ゲートと同じ考え方)。
|
|
1970
|
+
const unattended = actor.subscribers.size === 0;
|
|
1971
|
+
if (state !== null) {
|
|
1972
|
+
// 再観測: 消失猶予中なら取り消す(過渡フレームで 1 回写らなかっただけ)。
|
|
1973
|
+
if (watch.missingTimer !== null) {
|
|
1974
|
+
clearTimeout(watch.missingTimer);
|
|
1975
|
+
watch.missingTimer = null;
|
|
1976
|
+
}
|
|
1977
|
+
// 同じ状態への戻り(猶予中の再観測)は再通知しない。
|
|
1978
|
+
if (unattended && !sameUsageLimitWait(previous, state))
|
|
1979
|
+
this.options.usageLimitNotify?.(session, state);
|
|
1980
|
+
watch.state = state;
|
|
1981
|
+
if (watch.timer !== null)
|
|
1982
|
+
clearTimeout(watch.timer);
|
|
1983
|
+
watch.timer = setTimeout(() => {
|
|
1984
|
+
if (this.actors.get(session) === actor && actor.usageLimitWatch === watch) {
|
|
1985
|
+
this.options.log?.(`usage-limit-watch 上限で解除 session=${session}`);
|
|
1986
|
+
this.disarmUsageLimitWatch(session, actor);
|
|
1987
|
+
}
|
|
1988
|
+
}, SessionHub.USAGE_LIMIT_WATCH_MAX_MS);
|
|
1989
|
+
watch.timer.unref?.();
|
|
1990
|
+
return;
|
|
1991
|
+
}
|
|
1992
|
+
// 待機表示が消えた。再描画途中の capture で 1 フレーム写らないだけの消失で畳むと、以後 reaper 保護が
|
|
1993
|
+
// 外れて 30 分後に kill される。猶予を置き、その間に再観測が無ければ解除する(再開中からの消失は
|
|
1994
|
+
// 「作業を再開した」= 処理中遷移が先に来ていれば applyProcessing 側で既に畳まれている)。
|
|
1995
|
+
if (previous === null || watch.missingTimer !== null)
|
|
1996
|
+
return;
|
|
1997
|
+
watch.missingTimer = setTimeout(() => {
|
|
1998
|
+
if (this.actors.get(session) !== actor || actor.usageLimitWatch !== watch)
|
|
1999
|
+
return;
|
|
2000
|
+
this.options.log?.(`usage-limit-wait 消失で解除 session=${session} last=${previous.kind}`);
|
|
2001
|
+
if (previous.kind === "resuming" && actor.subscribers.size === 0) {
|
|
2002
|
+
this.options.usageLimitNotify?.(session, { kind: "resumed" });
|
|
2003
|
+
}
|
|
2004
|
+
this.disarmUsageLimitWatch(session, actor);
|
|
2005
|
+
}, SessionHub.USAGE_LIMIT_MISSING_GRACE_MS);
|
|
2006
|
+
watch.missingTimer.unref?.();
|
|
2007
|
+
}
|
|
1875
2008
|
/** 遅着 hook が直書きした active の heartbeat を idle へ戻す(その hook の書込のままのときだけ)。 */
|
|
1876
2009
|
revertLateHookHeartbeat(session, event, reason) {
|
|
1877
2010
|
// 別の書込(新ターンの UserPromptSubmit 等)に置き換わっていれば触らない(生きたターンの reaper
|
|
@@ -1924,6 +2057,14 @@ export class SessionHub {
|
|
|
1924
2057
|
return false;
|
|
1925
2058
|
}
|
|
1926
2059
|
actor.processingSince = this.now();
|
|
2060
|
+
// 使用量制限の待機中に処理へ戻った = 自動再開(usage-limit-wait)。pane の過渡表示を取りこぼしても
|
|
2061
|
+
// 処理中遷移を権威に「再開した」を知らせ、見張りを畳む。
|
|
2062
|
+
if (actor.usageLimitWatch !== null && actor.usageLimitWatch.state !== null) {
|
|
2063
|
+
this.options.log?.(`usage-limit-wait 処理再開で解除 session=${session}`);
|
|
2064
|
+
if (actor.subscribers.size === 0)
|
|
2065
|
+
this.options.usageLimitNotify?.(session, { kind: "resumed" });
|
|
2066
|
+
this.disarmUsageLimitWatch(session, actor);
|
|
2067
|
+
}
|
|
1927
2068
|
// ターン開始は UserPromptSubmit で確定し、継続 hook では進めない(未確定なら今)。
|
|
1928
2069
|
if (event === "UserPromptSubmit")
|
|
1929
2070
|
actor.turnStartFiredAtMs = atMs ?? null;
|