@cocorograph/hub-agent 0.7.34 → 0.7.36
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/codex-stream-bridge.mjs +21 -3
- package/src/enroll.mjs +3 -0
- package/src/main.mjs +76 -13
package/package.json
CHANGED
|
@@ -235,8 +235,23 @@ export class CodexStreamBridge extends EventEmitter {
|
|
|
235
235
|
})
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
/**
|
|
239
|
-
|
|
238
|
+
/**
|
|
239
|
+
* @param {object} args
|
|
240
|
+
* @param {string} args.stream_id
|
|
241
|
+
* @param {object} args.message
|
|
242
|
+
* @param {string} [args.model] - 公式スキーマ `TurnStartParams.model`
|
|
243
|
+
* ("Override the model for this turn and subsequent turns")。turn/start でのみ有効。
|
|
244
|
+
* @param {string} [args.effort] - 公式スキーマ `TurnStartParams.effort`
|
|
245
|
+
* ("Override the reasoning effort for this turn and subsequent turns")。turn/start でのみ有効。
|
|
246
|
+
* @returns {Promise<void>}
|
|
247
|
+
*
|
|
248
|
+
* ⚠️ `turn/steer` (`TurnSteerParams`) には model/effort フィールドが存在しない
|
|
249
|
+
* (公式スキーマで未対応と確認済み、2026-07-03)。そのためターン実行中 (busy) に
|
|
250
|
+
* model/effort を渡しても turn/steer 経由では反映されず、次の非 busy な input()
|
|
251
|
+
* (= turn/start) から有効になる。呼び出し側 (main.mjs) はこれを承知の上で常に
|
|
252
|
+
* model/effort を渡してよい (steer 分岐では単に無視される)。
|
|
253
|
+
*/
|
|
254
|
+
async input({ stream_id, message, model, effort }) {
|
|
240
255
|
const session = this._require(stream_id)
|
|
241
256
|
const input = userInputFromMessage(message)
|
|
242
257
|
if (session.activeTurnId) {
|
|
@@ -247,7 +262,10 @@ export class CodexStreamBridge extends EventEmitter {
|
|
|
247
262
|
})
|
|
248
263
|
return
|
|
249
264
|
}
|
|
250
|
-
|
|
265
|
+
const params = { threadId: session.threadId, input }
|
|
266
|
+
if (model) params.model = model
|
|
267
|
+
if (effort) params.effort = effort
|
|
268
|
+
await session.client.request("turn/start", params)
|
|
251
269
|
}
|
|
252
270
|
|
|
253
271
|
/** @returns {Promise<void>} */
|
package/src/enroll.mjs
CHANGED
|
@@ -66,6 +66,9 @@ export async function enroll(enrollmentToken, opts = {}) {
|
|
|
66
66
|
claude_model: typeof data.claude_model === "string" ? data.claude_model : "",
|
|
67
67
|
claude_permission_mode:
|
|
68
68
|
typeof data.claude_permission_mode === "string" ? data.claude_permission_mode : "",
|
|
69
|
+
// Codex CLI 設定 (2026-07-04 追加、claude_model/claude_permission_mode と対称)。
|
|
70
|
+
codex_model: typeof data.codex_model === "string" ? data.codex_model : "",
|
|
71
|
+
codex_effort: typeof data.codex_effort === "string" ? data.codex_effort : "",
|
|
69
72
|
})
|
|
70
73
|
|
|
71
74
|
// Hub AI bundle を続けて同期する (CLAUDE.md / scripts / hooks / projects.json
|
package/src/main.mjs
CHANGED
|
@@ -173,6 +173,23 @@ function claudeCmdFromAgentConfig(config) {
|
|
|
173
173
|
return cmd
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
/**
|
|
177
|
+
* `~/.hub/agent.json` の Codex CLI 設定 (codex_model / codex_effort) から
|
|
178
|
+
* createTmuxSession の model/effort opts へのデフォルト値を取得する
|
|
179
|
+
* (claudeCmdFromAgentConfig の Codex 版)。
|
|
180
|
+
*
|
|
181
|
+
* tmux.create_session / worktree.create の browser 側 msg.model / msg.effort が
|
|
182
|
+
* 明示指定されていればそちらを優先し (呼び出し側で判定済み)、未指定のときだけ
|
|
183
|
+
* このデフォルトにフォールバックする。空文字は「未指定」として undefined を返す
|
|
184
|
+
* (buildCodexCmd 側は undefined を渡されても既定値へフォールバックするため安全)。
|
|
185
|
+
*/
|
|
186
|
+
function codexDefaultsFromAgentConfig(config) {
|
|
187
|
+
return {
|
|
188
|
+
model: (config?.codex_model || "").trim() || undefined,
|
|
189
|
+
effort: (config?.codex_effort || "").trim() || undefined,
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
176
193
|
/**
|
|
177
194
|
* プロファイル切替用: 全 tmux セッションを kill → 同名・同 cwd で再作成する。
|
|
178
195
|
*
|
|
@@ -1687,27 +1704,46 @@ export function startStateLoop({ client, plugins, logger, intervalMs, claudeBrid
|
|
|
1687
1704
|
* 渡す予定なので、現状は plugin hook chain だけ走らせて log に残す。
|
|
1688
1705
|
*/
|
|
1689
1706
|
/**
|
|
1690
|
-
* Hub から `ready` / `ack` で配信された Claude CLI 設定を agent.json と
|
|
1707
|
+
* Hub から `ready` / `ack` で配信された Claude/Codex CLI 設定を agent.json と
|
|
1691
1708
|
* in-memory config に反映する (Phase 3 live-sync)。
|
|
1692
1709
|
*
|
|
1693
1710
|
* 旧設計 (Phase 2) では enrollment 時のみ取得していたため、cockpit 管理画面で
|
|
1694
1711
|
* 設定を変更しても既存 agent には再 enroll しない限り反映されなかった。Phase 3 で
|
|
1695
1712
|
* 全 WS 接続/heartbeat 毎に最新値が同期されるようにした。
|
|
1696
1713
|
*
|
|
1714
|
+
* 2026-07-04: Codex turn/start 経由の model/effort 切替実装に伴い、codex_model/
|
|
1715
|
+
* codex_effort も同じ経路で同期する (claude_model/claude_permission_mode と対称)。
|
|
1716
|
+
*
|
|
1697
1717
|
* 値が変化していない場合は writeConfig を呼ばない (書込負荷軽減)。
|
|
1698
1718
|
* 失敗しても agent は止めず log だけ出して継続。
|
|
1699
1719
|
*/
|
|
1700
1720
|
export async function maybeSyncClaudeSettings(msg, ctx) {
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1721
|
+
const hasClaudeFields =
|
|
1722
|
+
typeof msg?.claude_model === "string" || typeof msg?.claude_permission_mode === "string"
|
|
1723
|
+
const hasCodexFields =
|
|
1724
|
+
typeof msg?.codex_model === "string" || typeof msg?.codex_effort === "string"
|
|
1725
|
+
if (!hasClaudeFields && !hasCodexFields) return
|
|
1726
|
+
|
|
1704
1727
|
const nextModel = typeof msg.claude_model === "string" ? msg.claude_model : ctx.config.claude_model || ""
|
|
1705
1728
|
const nextMode = typeof msg.claude_permission_mode === "string" ? msg.claude_permission_mode : ctx.config.claude_permission_mode || ""
|
|
1729
|
+
const nextCodexModel = typeof msg.codex_model === "string" ? msg.codex_model : ctx.config.codex_model || ""
|
|
1730
|
+
const nextCodexEffort = typeof msg.codex_effort === "string" ? msg.codex_effort : ctx.config.codex_effort || ""
|
|
1706
1731
|
const prevModel = ctx.config.claude_model || ""
|
|
1707
1732
|
const prevMode = ctx.config.claude_permission_mode || ""
|
|
1708
|
-
|
|
1733
|
+
const prevCodexModel = ctx.config.codex_model || ""
|
|
1734
|
+
const prevCodexEffort = ctx.config.codex_effort || ""
|
|
1735
|
+
if (
|
|
1736
|
+
nextModel === prevModel &&
|
|
1737
|
+
nextMode === prevMode &&
|
|
1738
|
+
nextCodexModel === prevCodexModel &&
|
|
1739
|
+
nextCodexEffort === prevCodexEffort
|
|
1740
|
+
) {
|
|
1741
|
+
return
|
|
1742
|
+
}
|
|
1709
1743
|
ctx.config.claude_model = nextModel
|
|
1710
1744
|
ctx.config.claude_permission_mode = nextMode
|
|
1745
|
+
ctx.config.codex_model = nextCodexModel
|
|
1746
|
+
ctx.config.codex_effort = nextCodexEffort
|
|
1711
1747
|
try {
|
|
1712
1748
|
await writeConfig({
|
|
1713
1749
|
agent_id: ctx.config.agent_id,
|
|
@@ -1715,13 +1751,20 @@ export async function maybeSyncClaudeSettings(msg, ctx) {
|
|
|
1715
1751
|
hub_url: ctx.config.hub_url,
|
|
1716
1752
|
claude_model: nextModel,
|
|
1717
1753
|
claude_permission_mode: nextMode,
|
|
1754
|
+
codex_model: nextCodexModel,
|
|
1755
|
+
codex_effort: nextCodexEffort,
|
|
1718
1756
|
})
|
|
1719
1757
|
ctx.logger.info(
|
|
1720
|
-
{
|
|
1721
|
-
|
|
1758
|
+
{
|
|
1759
|
+
claude_model: nextModel,
|
|
1760
|
+
claude_permission_mode: nextMode,
|
|
1761
|
+
codex_model: nextCodexModel,
|
|
1762
|
+
codex_effort: nextCodexEffort,
|
|
1763
|
+
},
|
|
1764
|
+
"claude/codex settings synced from hub",
|
|
1722
1765
|
)
|
|
1723
1766
|
} catch (err) {
|
|
1724
|
-
ctx.logger.warn({ err: err.message }, "failed to persist claude settings to agent.json")
|
|
1767
|
+
ctx.logger.warn({ err: err.message }, "failed to persist claude/codex settings to agent.json")
|
|
1725
1768
|
}
|
|
1726
1769
|
}
|
|
1727
1770
|
|
|
@@ -3201,9 +3244,17 @@ async function dispatch(msg, ctx) {
|
|
|
3201
3244
|
return
|
|
3202
3245
|
}
|
|
3203
3246
|
case "codex.input":
|
|
3247
|
+
// model/effort: turn/start (非 busy 時) にのみ反映される override。turn/steer
|
|
3248
|
+
// (busy 時) は公式スキーマ上 model/effort 非対応のため、その場合は
|
|
3249
|
+
// codex-stream-bridge.mjs 側で無視され次の非 busy な input() から効く。
|
|
3204
3250
|
if (!ctx.codexBridge) return
|
|
3205
3251
|
ctx.codexBridge
|
|
3206
|
-
.input({
|
|
3252
|
+
.input({
|
|
3253
|
+
stream_id: msg.stream_id,
|
|
3254
|
+
message: msg.message,
|
|
3255
|
+
model: msg.model || undefined,
|
|
3256
|
+
effort: msg.effort || undefined,
|
|
3257
|
+
})
|
|
3207
3258
|
.catch((err) => {
|
|
3208
3259
|
ctx.client.send({
|
|
3209
3260
|
type: "codex.error",
|
|
@@ -3571,11 +3622,17 @@ async function dispatch(msg, ctx) {
|
|
|
3571
3622
|
: claudeCmdFromAgentConfig(ctx.config),
|
|
3572
3623
|
codexCmd: typeof msg.codex_cmd === "string" ? msg.codex_cmd : undefined,
|
|
3573
3624
|
// codex 用設定 (claude 経路では claudeCmd を直接使うため無視される)。
|
|
3574
|
-
model:
|
|
3625
|
+
model:
|
|
3626
|
+
typeof msg.model === "string"
|
|
3627
|
+
? msg.model
|
|
3628
|
+
: codexDefaultsFromAgentConfig(ctx.config).model,
|
|
3575
3629
|
sandbox: typeof msg.sandbox === "string" ? msg.sandbox : undefined,
|
|
3576
3630
|
approvalPolicy:
|
|
3577
3631
|
typeof msg.approval_policy === "string" ? msg.approval_policy : undefined,
|
|
3578
|
-
effort:
|
|
3632
|
+
effort:
|
|
3633
|
+
typeof msg.effort === "string"
|
|
3634
|
+
? msg.effort
|
|
3635
|
+
: codexDefaultsFromAgentConfig(ctx.config).effort,
|
|
3579
3636
|
initialPrompt:
|
|
3580
3637
|
typeof msg.initial_prompt === "string" ? msg.initial_prompt : undefined,
|
|
3581
3638
|
logger: ctx.logger,
|
|
@@ -3631,11 +3688,17 @@ async function dispatch(msg, ctx) {
|
|
|
3631
3688
|
: claudeCmdFromAgentConfig(ctx.config),
|
|
3632
3689
|
codexCmd: typeof msg.codex_cmd === "string" ? msg.codex_cmd : undefined,
|
|
3633
3690
|
// codex 用設定 (claude 経路では無視される)。
|
|
3634
|
-
model:
|
|
3691
|
+
model:
|
|
3692
|
+
typeof msg.model === "string"
|
|
3693
|
+
? msg.model
|
|
3694
|
+
: codexDefaultsFromAgentConfig(ctx.config).model,
|
|
3635
3695
|
sandbox: typeof msg.sandbox === "string" ? msg.sandbox : undefined,
|
|
3636
3696
|
approvalPolicy:
|
|
3637
3697
|
typeof msg.approval_policy === "string" ? msg.approval_policy : undefined,
|
|
3638
|
-
effort:
|
|
3698
|
+
effort:
|
|
3699
|
+
typeof msg.effort === "string"
|
|
3700
|
+
? msg.effort
|
|
3701
|
+
: codexDefaultsFromAgentConfig(ctx.config).effort,
|
|
3639
3702
|
initialPrompt:
|
|
3640
3703
|
typeof msg.initial_prompt === "string" ? msg.initial_prompt : undefined,
|
|
3641
3704
|
logger: ctx.logger,
|