@cocorograph/hub-agent 0.8.35 → 0.8.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.8.35",
3
+ "version": "0.8.36",
4
4
  "description": "Hub Hosted Cockpit のローカル常駐 agent。Hub と outbound WSS で接続し、ローカルの Claude / Codex チャットと tmux セッションを中継する。",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -390,6 +390,20 @@ function subagentFallbackName(agentPath) {
390
390
  return agentPath.split("/").filter(Boolean).at(-1) || "subagent"
391
391
  }
392
392
 
393
+ function explicitSubagentRoleFromThread(thread, expectedParentThreadId) {
394
+ const threadSpawn = thread?.source?.subAgent?.thread_spawn
395
+ if (
396
+ threadSpawn &&
397
+ (typeof threadSpawn.parent_thread_id !== "string" ||
398
+ threadSpawn.parent_thread_id !== expectedParentThreadId)
399
+ ) return null
400
+ const directRole = typeof thread?.agentRole === "string" ? thread.agentRole.trim() : ""
401
+ if (directRole) return directRole
402
+ const sourceRole = threadSpawn?.agent_role
403
+ const normalizedSourceRole = typeof sourceRole === "string" ? sourceRole.trim() : ""
404
+ return normalizedSourceRole || null
405
+ }
406
+
393
407
  function parseDynamicToolArguments(value) {
394
408
  if (value && typeof value === "object" && !Array.isArray(value)) return value
395
409
  if (typeof value !== "string") return null
@@ -749,7 +763,7 @@ export class CodexStreamBridge extends EventEmitter {
749
763
  * deliveryPromise: Promise<object>, settleDelivery: Function}>} */
750
764
  pendingInjectSources: [],
751
765
  /** 組み込み collaboration subagent の表示用台帳。検索キーは agentThreadId、
752
- * 外部へ出す安定した委譲 ID は spawn dynamicToolCall の item.id を保持する。 */
766
+ * 外部へ出す安定した委譲 ID は subAgentActivity の lifecycle ID を保持する。 */
753
767
  subagents: new Map(),
754
768
  /** dynamicToolCall(spawn_agent) の item.id -> 表示メタデータ。 */
755
769
  subagentSpawnMetadata: new Map(),
@@ -1593,6 +1607,7 @@ export class CodexStreamBridge extends EventEmitter {
1593
1607
  agentPath: record.agentPath,
1594
1608
  phase: record.phase,
1595
1609
  agent: record.agent,
1610
+ agentExplicit: record.agentExplicit === true,
1596
1611
  description: record.description,
1597
1612
  prompt: record.prompt,
1598
1613
  background: record.background === true,
@@ -1636,6 +1651,7 @@ export class CodexStreamBridge extends EventEmitter {
1636
1651
  agentPath,
1637
1652
  phase,
1638
1653
  agent: metadata?.agent || previous?.agent || subagentFallbackName(agentPath),
1654
+ agentExplicit: metadata?.agentExplicit === true || previous?.agentExplicit === true,
1639
1655
  description:
1640
1656
  metadata?.description || previous?.description || subagentFallbackName(agentPath),
1641
1657
  prompt: metadata?.prompt || previous?.prompt || "",
@@ -1673,8 +1689,11 @@ export class CodexStreamBridge extends EventEmitter {
1673
1689
  if (namespace !== "collaboration" || item.tool !== "spawn_agent" || !item.id) return
1674
1690
  const args = parseDynamicToolArguments(item.arguments)
1675
1691
  if (!args) return
1692
+ const agent = typeof args.agent_type === "string" ? args.agent_type.trim() : ""
1693
+ const agentExplicit = agent.length > 0
1676
1694
  const metadata = {
1677
- agent: typeof args.agent_type === "string" && args.agent_type ? args.agent_type : null,
1695
+ agent: agentExplicit ? agent : null,
1696
+ agentExplicit,
1678
1697
  description: typeof args.task_name === "string" && args.task_name ? args.task_name : null,
1679
1698
  prompt: typeof args.message === "string" ? args.message : null,
1680
1699
  background: args.background === true,
@@ -1769,6 +1788,7 @@ export class CodexStreamBridge extends EventEmitter {
1769
1788
  agentThreadId: record.agentThreadId,
1770
1789
  agentPath: record.agentPath,
1771
1790
  agent: record.agent,
1791
+ agentExplicit: record.agentExplicit === true,
1772
1792
  description: record.description,
1773
1793
  prompt: record.prompt,
1774
1794
  background: record.background === true,
@@ -1802,6 +1822,10 @@ export class CodexStreamBridge extends EventEmitter {
1802
1822
  // RPC 待ち中に live lifecycle が進んだ場合、stale read で上書き・削除しない。
1803
1823
  if (session.subagents.get(record.agentThreadId) !== record) continue
1804
1824
  const thread = result?.thread
1825
+ const explicitRole = explicitSubagentRoleFromThread(thread, session.threadId)
1826
+ const metadata = explicitRole
1827
+ ? { agent: explicitRole, agentExplicit: true }
1828
+ : null
1805
1829
  const turns = Array.isArray(thread?.turns) ? thread.turns : []
1806
1830
  const lastTurn = turns.at(-1)
1807
1831
  const phase = terminalSubagentPhase(lastTurn?.status)
@@ -1816,7 +1840,7 @@ export class CodexStreamBridge extends EventEmitter {
1816
1840
  session,
1817
1841
  record.agentThreadId,
1818
1842
  phase,
1819
- { agentPath: record.agentPath, atMs: lastTurnAtMs },
1843
+ { agentPath: record.agentPath, metadata, atMs: lastTurnAtMs },
1820
1844
  { emit: false },
1821
1845
  )
1822
1846
  } else if (
@@ -1829,6 +1853,7 @@ export class CodexStreamBridge extends EventEmitter {
1829
1853
  "started",
1830
1854
  {
1831
1855
  agentPath: record.agentPath,
1856
+ metadata,
1832
1857
  atMs: record.startedAtMs,
1833
1858
  },
1834
1859
  { emit: false },
package/src/main.mjs CHANGED
@@ -2076,6 +2076,7 @@ export function buildCodexReadyPayload(streamId, info, queueState) {
2076
2076
  agent_thread_id: subagent.agentThreadId,
2077
2077
  agent_path: subagent.agentPath,
2078
2078
  agent: subagent.agent,
2079
+ agent_explicit: subagent.agentExplicit === true,
2079
2080
  // description は spawn_agent.task_name の既存 alias(人物の表示名ではない)。
2080
2081
  description: subagent.description,
2081
2082
  prompt: subagent.prompt,