@cocorograph/hub-agent 0.6.62 → 0.6.63
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 +34 -0
- package/src/tmux.mjs +53 -0
package/package.json
CHANGED
package/src/main.mjs
CHANGED
|
@@ -69,6 +69,7 @@ import {
|
|
|
69
69
|
removeWorktree as removeWorktreeDir,
|
|
70
70
|
resumeWithMessage,
|
|
71
71
|
setTmuxGlobalEnv,
|
|
72
|
+
setTuiEffort,
|
|
72
73
|
setTuiModel,
|
|
73
74
|
} from "./tmux.mjs"
|
|
74
75
|
import { TuiPermissionBridge } from "./tui-permission-bridge.mjs"
|
|
@@ -1419,6 +1420,39 @@ async function dispatch(msg, ctx) {
|
|
|
1419
1420
|
})()
|
|
1420
1421
|
return
|
|
1421
1422
|
}
|
|
1423
|
+
case "claude.tui.setEffort": {
|
|
1424
|
+
// effort バッジ選択 → 対話 claude TUI へ `/effort <level>` を送って reasoning effort を
|
|
1425
|
+
// 切り替える。setModel と同設計: agent が実キーを送出 → 全ブラウザへ claude.tui.effort を
|
|
1426
|
+
// broadcast し、実際に動いているターミナルの effort を正本として全端末に同期する。
|
|
1427
|
+
// effort は jsonl に記録されないため、この即時 broadcast が唯一の表示根拠になる。
|
|
1428
|
+
const cwd = typeof msg.cwd === "string" ? msg.cwd : ""
|
|
1429
|
+
const sessionName =
|
|
1430
|
+
typeof msg.session_name === "string" ? msg.session_name : ""
|
|
1431
|
+
if (!sessionName) return
|
|
1432
|
+
// effort="" は「auto」= `/effort auto`。frontend へはそのまま空で返し、バッジは auto 表示。
|
|
1433
|
+
const effort = typeof msg.effort === "string" ? msg.effort : ""
|
|
1434
|
+
;(async () => {
|
|
1435
|
+
try {
|
|
1436
|
+
await setTuiEffort(sessionName, effort || "auto", { logger })
|
|
1437
|
+
ctx.client.send({
|
|
1438
|
+
type: "claude.tui.effort",
|
|
1439
|
+
cwd: cwd || undefined,
|
|
1440
|
+
session_name: sessionName,
|
|
1441
|
+
effort,
|
|
1442
|
+
})
|
|
1443
|
+
logger.info(
|
|
1444
|
+
{ session: sessionName, cwd, effort: effort || "(auto)" },
|
|
1445
|
+
"tui effort switched → notified browser",
|
|
1446
|
+
)
|
|
1447
|
+
} catch (err) {
|
|
1448
|
+
logger.warn(
|
|
1449
|
+
{ err: err?.message, session: sessionName },
|
|
1450
|
+
"claude.tui.setEffort failed",
|
|
1451
|
+
)
|
|
1452
|
+
}
|
|
1453
|
+
})()
|
|
1454
|
+
return
|
|
1455
|
+
}
|
|
1422
1456
|
case "claude.tui.probePermission": {
|
|
1423
1457
|
// 読み取り専用の権限モード問い合わせ (cold-load seed)。キーは送らず、ペインを
|
|
1424
1458
|
// 読んで現在の実モードを claude.tui.permission として broadcast するだけ。
|
package/src/tmux.mjs
CHANGED
|
@@ -934,6 +934,59 @@ export async function setTuiModel(name, modelArg, opts = {}) {
|
|
|
934
934
|
}
|
|
935
935
|
}
|
|
936
936
|
|
|
937
|
+
/**
|
|
938
|
+
* 対話 claude TUI に `/effort <level>` を送って reasoning effort を切り替える。
|
|
939
|
+
*
|
|
940
|
+
* cockpit の effort バッジ選択 (claude.tui.setEffort) の書込側。モデル切替 (setTuiModel) と
|
|
941
|
+
* 同設計で、frontend は raw pty.data ではなく claude.tui.setEffort を送り、agent 側で本関数を
|
|
942
|
+
* 実行 → 全ブラウザへ claude.tui.effort を broadcast して全端末を実 effort に揃える。
|
|
943
|
+
*
|
|
944
|
+
* `/effort` は引数 (low/medium/high/xhigh/max/auto) を受理し即時反映する (確認プロンプトを
|
|
945
|
+
* 挟まない)。effort 非対応レベルを与えても CLI がモデルの対応上限へ自動フォールバックする。
|
|
946
|
+
* `auto` はモデル既定へリセット。copy-mode に入っているとキーが奪われるので先に抜ける。
|
|
947
|
+
* ベストエフォート。
|
|
948
|
+
*
|
|
949
|
+
* @param {string} name tmux セッション名
|
|
950
|
+
* @param {string} effortArg `/effort` 引数 (low/medium/high/xhigh/max または "auto")
|
|
951
|
+
* @param {{logger?:object,tmuxBin?:string}} [opts]
|
|
952
|
+
* @returns {Promise<{ok:boolean, error?:string}>}
|
|
953
|
+
*/
|
|
954
|
+
export async function setTuiEffort(name, effortArg, opts = {}) {
|
|
955
|
+
const bin = tmuxBin(opts)
|
|
956
|
+
const arg = String(effortArg || "auto").replace(/[\r\n]+/g, " ").trim()
|
|
957
|
+
if (!arg) return { ok: false, error: "empty effort arg" }
|
|
958
|
+
try {
|
|
959
|
+
// copy-mode 等に入っているとキーが奪われるので、入っている時だけ抜ける。
|
|
960
|
+
try {
|
|
961
|
+
const { stdout } = await execFileP(bin, [
|
|
962
|
+
"display-message",
|
|
963
|
+
"-p",
|
|
964
|
+
"-t",
|
|
965
|
+
`${name}:`,
|
|
966
|
+
"-F",
|
|
967
|
+
"#{pane_in_mode}",
|
|
968
|
+
])
|
|
969
|
+
if (stdout.trim() === "1") {
|
|
970
|
+
await execFileP(bin, ["send-keys", "-t", name, "-X", "cancel"])
|
|
971
|
+
}
|
|
972
|
+
} catch {
|
|
973
|
+
// pane_in_mode 取得失敗はベストエフォートで無視。
|
|
974
|
+
}
|
|
975
|
+
// `/effort <level>` をリテラルで送る (-l でキー名解釈・スラッシュ補完の暴発を避ける)。
|
|
976
|
+
await execFileP(bin, ["send-keys", "-t", name, "-l", `/effort ${arg}`])
|
|
977
|
+
await _delay(120)
|
|
978
|
+
// Enter で本文確定 (send-keys の離散イベントなので paste 吸収は起きにくい)。
|
|
979
|
+
await execFileP(bin, ["send-keys", "-t", name, "Enter"])
|
|
980
|
+
return { ok: true }
|
|
981
|
+
} catch (err) {
|
|
982
|
+
opts.logger?.warn(
|
|
983
|
+
{ session: name, effort: arg, err: err?.message },
|
|
984
|
+
"setTuiEffort failed",
|
|
985
|
+
)
|
|
986
|
+
return { ok: false, error: err?.message || String(err) }
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
|
|
937
990
|
/**
|
|
938
991
|
* 中断キャンセル後の入力欄復旧 (claude.tui.recoverInput / agent >= 0.6.57)。
|
|
939
992
|
*
|