@cocorograph/hub-agent 0.8.81 → 0.8.83
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/chat-sessions-snapshot.mjs +10 -4
- package/src/chat-signals.mjs +81 -247
- package/src/claude-stream-bridge.mjs +30 -7
- package/src/codex-stream-bridge.mjs +30 -4
- package/src/dispatch-scheduler.mjs +5 -0
- package/src/main.mjs +206 -558
- package/src/tmux.mjs +7 -3
- package/src/usage.mjs +8 -3
package/src/tmux.mjs
CHANGED
|
@@ -23,7 +23,7 @@ import { expandTilde, hubProjectsBase, prepareChatWorkspace } from "./chat-works
|
|
|
23
23
|
export { expandTilde, isUnderHubProjectsBase, projectInstructionDir } from "./chat-workspace.mjs"
|
|
24
24
|
import { detectSessionState, getSessionCwd } from "./state.mjs"
|
|
25
25
|
import { shouldLaunchPaneCli } from "./pane-cli-flag.mjs"
|
|
26
|
-
import { baseSessionName, sessionNameFor } from "./session-names.mjs"
|
|
26
|
+
import { baseSessionName, cliKindForSessionName, sessionNameFor } from "./session-names.mjs"
|
|
27
27
|
import { boundSessionId, getSessionUsages, isFreshUnboundBind, jsonlContextForCwd } from "./usage.mjs"
|
|
28
28
|
import { quotePosixShellArg, requireCodexBinary } from "./codex-binary.mjs"
|
|
29
29
|
|
|
@@ -676,12 +676,16 @@ export async function listSessions(opts = {}) {
|
|
|
676
676
|
// tmux 上の bind 台帳が無いため、これが無いと cold-start (session.state snapshot 未取得)
|
|
677
677
|
// の poll 応答で cwd の別アクティビティ jsonl を「最新」と取り違える cross-activity 汚染が
|
|
678
678
|
// 起き得る (2026-07 発覚。TUI 版は本行の boundSessions 解決で既に根治済みだった)。
|
|
679
|
-
|
|
679
|
+
// Codex 行には Claude の bind / live ID 由来の使用率を載せない。
|
|
680
|
+
// 代表会話の値は送信側の readRowChatState に委ねる。
|
|
681
|
+
const allowClaudeUsage = cliKindForSessionName(s.name) !== "codex"
|
|
682
|
+
const boundValue = allowClaudeUsage ? opts.boundSessions?.get(s.name) : null
|
|
680
683
|
const freshUnbound = isFreshUnboundBind(boundValue)
|
|
681
|
-
const boundId =
|
|
684
|
+
const boundId = allowClaudeUsage ? (
|
|
682
685
|
boundSessionId(opts.boundSessions, s.name) ||
|
|
683
686
|
(cwd && opts.claudeBridge?.liveSessionIdForCwd?.(cwd)) ||
|
|
684
687
|
null
|
|
688
|
+
) : null
|
|
685
689
|
// cwd だけでは同じリポジトリで並走する別 Claude / subagent / 過去会話を区別できない。
|
|
686
690
|
// bound ID が無い状態で statusLine/jsonl の「cwd 最新値」を使うと、再起動後や未オープンの
|
|
687
691
|
// tmux セッションへ別会話の 98〜100% が混入する。実際に値の帰属先を示せる bound session
|
package/src/usage.mjs
CHANGED
|
@@ -802,7 +802,7 @@ export function isFreshUnboundBind(boundVal) {
|
|
|
802
802
|
* @param {string} cwd
|
|
803
803
|
* @returns {Promise<{ percent: number | null, uuid: string | null, isReset: boolean }>}
|
|
804
804
|
*/
|
|
805
|
-
export async function jsonlContextForCwd(cwd, sessionId = null) {
|
|
805
|
+
export async function jsonlContextForCwd(cwd, sessionId = null, { contextWindow } = {}) {
|
|
806
806
|
const empty = { percent: null, uuid: null, isReset: false }
|
|
807
807
|
if (!cwd) return empty
|
|
808
808
|
const dirName = encodeCwdToDirName(cwd)
|
|
@@ -817,12 +817,12 @@ export async function jsonlContextForCwd(cwd, sessionId = null) {
|
|
|
817
817
|
|
|
818
818
|
// 末尾 assistant.usage を探す。`_jsonlCtxMemo` は fp+mtime+size をキーにしているので
|
|
819
819
|
// 同 jsonl の連続呼び出しは I/O ゼロでヒットする。
|
|
820
|
+
const windowSize = typeof contextWindow === "number" && contextWindow > 0 ? contextWindow : await contextWindowSize()
|
|
820
821
|
const memo = _jsonlCtxMemo.get(newest.fp)
|
|
821
822
|
let percent = null
|
|
822
|
-
if (memo && memo.mtimeMs === newest.mtimeMs && memo.size === newest.size) {
|
|
823
|
+
if (memo && memo.mtimeMs === newest.mtimeMs && memo.size === newest.size && memo.windowSize === windowSize) {
|
|
823
824
|
percent = memo.result ? memo.result.percent : null
|
|
824
825
|
} else {
|
|
825
|
-
const windowSize = await contextWindowSize()
|
|
826
826
|
const scan = (text) => {
|
|
827
827
|
const lines = text.split("\n")
|
|
828
828
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -857,6 +857,7 @@ export async function jsonlContextForCwd(cwd, sessionId = null) {
|
|
|
857
857
|
_jsonlCtxMemo.set(newest.fp, {
|
|
858
858
|
mtimeMs: newest.mtimeMs,
|
|
859
859
|
size: newest.size,
|
|
860
|
+
windowSize,
|
|
860
861
|
result,
|
|
861
862
|
})
|
|
862
863
|
}
|
|
@@ -2188,6 +2189,10 @@ export function codexContextPercentFromTokenUsage(tokenUsage) {
|
|
|
2188
2189
|
/** producer(session.seq) の live context%(App Server 正本)。呼び出し側は cwd の権威 producer
|
|
2189
2190
|
* (liveSessionForCwd の seq) を渡す。live tokenUsage 未取得 / 算出不能なら null(呼び出し側が
|
|
2190
2191
|
* rollout へフォールバックする)。 */
|
|
2192
|
+
export function hasCodexLiveTokenUsage(producerSeq) {
|
|
2193
|
+
return _codexLiveTokenUsageByProducer.has(producerSeq)
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2191
2196
|
export function codexLiveContextForProducer(producerSeq) {
|
|
2192
2197
|
if (typeof producerSeq !== "number") return null
|
|
2193
2198
|
const e = _codexLiveTokenUsageByProducer.get(producerSeq)
|