@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocorograph/hub-agent",
3
- "version": "0.7.34",
3
+ "version": "0.7.36",
4
4
  "description": "Hub Hosted Cockpit のローカル常駐 agent。Hub と outbound WSS で接続し、ローカルの tmux/pty を中継する。",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -235,8 +235,23 @@ export class CodexStreamBridge extends EventEmitter {
235
235
  })
236
236
  }
237
237
 
238
- /** @returns {Promise<void>} */
239
- async input({ stream_id, message }) {
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
- await session.client.request("turn/start", { threadId: session.threadId, input })
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
- if (typeof msg?.claude_model !== "string" && typeof msg?.claude_permission_mode !== "string") {
1702
- return
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
- if (nextModel === prevModel && nextMode === prevMode) return
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
- { claude_model: nextModel, claude_permission_mode: nextMode },
1721
- "claude settings synced from hub",
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({ stream_id: msg.stream_id, message: msg.message })
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: typeof msg.model === "string" ? msg.model : undefined,
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: typeof msg.effort === "string" ? msg.effort : undefined,
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: typeof msg.model === "string" ? msg.model : undefined,
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: typeof msg.effort === "string" ? msg.effort : undefined,
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,