chainlesschain 0.162.124 → 0.162.126

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.
Files changed (260) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/AIOps-BrTOcqIJ.js +1 -0
  4. package/src/assets/web-panel/assets/{ActionButton-COjZZKWG.js → ActionButton-na9cocmf.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-4ZDZE7lc.js → Analytics-BtDygkpt.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-CYH5k2Rp.js → AppLayout-D_t5CS18.js} +5 -5
  7. package/src/assets/web-panel/assets/Audit-BYMZccCy.js +1 -0
  8. package/src/assets/web-panel/assets/{Backup-CiX61Qc2.js → Backup-D2qDfAdL.js} +1 -1
  9. package/src/assets/web-panel/assets/{BaseInput-CDxIQokd.js → BaseInput-kj456Ju9.js} +1 -1
  10. package/src/assets/web-panel/assets/{Chat-CaKgdRab.js → Chat-BY0A0ZLE.js} +4 -4
  11. package/src/assets/web-panel/assets/ChatBubbleRenderer-D1VvrOPQ.js +1 -0
  12. package/src/assets/web-panel/assets/{Checkbox-CjiWfu4s.js → Checkbox-DiBhtXsh.js} +1 -1
  13. package/src/assets/web-panel/assets/Codegen-B1ER0L0j.js +1 -0
  14. package/src/assets/web-panel/assets/{Col-ZKWREyNs.js → Col-CjLmza7D.js} +1 -1
  15. package/src/assets/web-panel/assets/Community-BNId05U7.js +1 -0
  16. package/src/assets/web-panel/assets/{Compact-DqknM98n.js → Compact-BuuMj7K1.js} +1 -1
  17. package/src/assets/web-panel/assets/Compliance-DUuDycaJ.js +1 -0
  18. package/src/assets/web-panel/assets/{Cowork-Dp29kHsC.js → Cowork-BKHiF6uL.js} +2 -2
  19. package/src/assets/web-panel/assets/{Cron-zmEJAetz.js → Cron-C7p-lHnC.js} +2 -2
  20. package/src/assets/web-panel/assets/Crosschain-BvSOx8a6.js +1 -0
  21. package/src/assets/web-panel/assets/{DID-D_UFNzJ5.js → DID-D1k9jgHv.js} +2 -2
  22. package/src/assets/web-panel/assets/Dashboard-B9mCCnqY.js +3 -0
  23. package/src/assets/web-panel/assets/{Dropdown-CH7l3KCs.js → Dropdown-ge9UHSXF.js} +1 -1
  24. package/src/assets/web-panel/assets/{EmailListRenderer-Bud2M3XX.js → EmailListRenderer-TZO7ppXi.js} +1 -1
  25. package/src/assets/web-panel/assets/{FamilyGuardDashboard-Bd2_8uME.js → FamilyGuardDashboard-DkhLJmzx.js} +1 -1
  26. package/src/assets/web-panel/assets/Federation-JLuA_8zp.js +1 -0
  27. package/src/assets/web-panel/assets/{FormItemContext-CpSH464Y.js → FormItemContext-C4w-rzNg.js} +1 -1
  28. package/src/assets/web-panel/assets/{GenericCardRenderer-CANo8O-y.js → GenericCardRenderer-Btns4sV9.js} +1 -1
  29. package/src/assets/web-panel/assets/{Git-hvuZVoD3.js → Git-BheXMjzC.js} +2 -2
  30. package/src/assets/web-panel/assets/Governance-D9rLlatH.js +1 -0
  31. package/src/assets/web-panel/assets/Inference-DiklIMcd.js +1 -0
  32. package/src/assets/web-panel/assets/KnowledgeGraph-C70EWL03.js +1 -0
  33. package/src/assets/web-panel/assets/{Logs-DDkTnedu.js → Logs-Zt_MLI10.js} +2 -2
  34. package/src/assets/web-panel/assets/Marketplace-suQxES99.js +1 -0
  35. package/src/assets/web-panel/assets/{McpTools-Qx78XyOT.js → McpTools-CclpCDpY.js} +3 -3
  36. package/src/assets/web-panel/assets/{Memory-CXYDO1oT.js → Memory-B2lHOUwF.js} +2 -2
  37. package/src/assets/web-panel/assets/MobileBridge-BMXKoDAD.js +1 -0
  38. package/src/assets/web-panel/assets/{MobileProjects-DEDbWNIk.js → MobileProjects-a6mWVdBV.js} +1 -1
  39. package/src/assets/web-panel/assets/{Mtc-Dwa_vlR8.js → Mtc-BFpM4Fkj.js} +2 -2
  40. package/src/assets/web-panel/assets/{MtcAudit-DAVkxhJv.js → MtcAudit-DDQkxkbS.js} +4 -4
  41. package/src/assets/web-panel/assets/{Multisig-C3upmgPN.js → Multisig-Crkd_zKQ.js} +3 -3
  42. package/src/assets/web-panel/assets/NLProgramming-Dpk5An7B.js +1 -0
  43. package/src/assets/web-panel/assets/{Notes-B1Oy3FbC.js → Notes-BrFnOMNz.js} +4 -4
  44. package/src/assets/web-panel/assets/{NotificationSettings-Bs4-Fc6b.js → NotificationSettings-CM0iApFM.js} +1 -1
  45. package/src/assets/web-panel/assets/{OrderTableRenderer-CEy1pIeq.js → OrderTableRenderer-XXjeqkdz.js} +1 -1
  46. package/src/assets/web-panel/assets/{Organization-D4cJ1UNo.js → Organization-CHFW_38T.js} +2 -2
  47. package/src/assets/web-panel/assets/{Overflow-fdzvlF7x.js → Overflow-C-vl3EjV.js} +1 -1
  48. package/src/assets/web-panel/assets/{P2P-Y13PwXBA.js → P2P-BT7Slavq.js} +2 -2
  49. package/src/assets/web-panel/assets/{PdhVaultBrowser-Ck1zCLe6.js → PdhVaultBrowser-DRUaULap.js} +3 -3
  50. package/src/assets/web-panel/assets/{Permissions-CvEXP6LC.js → Permissions-DkhOAvMz.js} +2 -2
  51. package/src/assets/web-panel/assets/{PersonalDataHub-JeP7IWMW.js → PersonalDataHub-Dl7dSOvV.js} +3 -3
  52. package/src/assets/web-panel/assets/Pipeline-B3nVI4p6.js +1 -0
  53. package/src/assets/web-panel/assets/Privacy-Dv1SXx1Q.js +1 -0
  54. package/src/assets/web-panel/assets/{ProjectInit-DeWd9UcS.js → ProjectInit-DrAhVi5p.js} +2 -2
  55. package/src/assets/web-panel/assets/{ProjectSettings-DUpVuU9F.js → ProjectSettings-h-ggCYN_.js} +2 -2
  56. package/src/assets/web-panel/assets/Projects-CM91hYdr.js +1 -0
  57. package/src/assets/web-panel/assets/{Providers-DECW00ek.js → Providers-rfkZel3N.js} +1 -1
  58. package/src/assets/web-panel/assets/{QuickAsk-Dl-pK9Io.js → QuickAsk-XepZB7h_.js} +1 -1
  59. package/src/assets/web-panel/assets/Recommend-DzQWsh1a.js +1 -0
  60. package/src/assets/web-panel/assets/Reputation-CDeaal0j.js +1 -0
  61. package/src/assets/web-panel/assets/Row-BN4aKhFH.js +1 -0
  62. package/src/assets/web-panel/assets/{RssFeed-iyQT5q9l.js → RssFeed-INP6VYAA.js} +3 -3
  63. package/src/assets/web-panel/assets/Search-ChPbwatu.js +1 -0
  64. package/src/assets/web-panel/assets/{Security-c4Jxf5Ih.js → Security-C97ZCY8N.js} +4 -4
  65. package/src/assets/web-panel/assets/{Services-CRuisolj.js → Services-Cbtl2Ajs.js} +2 -2
  66. package/src/assets/web-panel/assets/{Skeleton-CCnzJkb-.js → Skeleton-B13sFxBQ.js} +1 -1
  67. package/src/assets/web-panel/assets/{Skills-CZURCwZg.js → Skills-vI9zSIKX.js} +1 -1
  68. package/src/assets/web-panel/assets/Sla-Cr3oBH39.js +1 -0
  69. package/src/assets/web-panel/assets/SpeechSettings-BwemqPPV.js +1 -0
  70. package/src/assets/web-panel/assets/{SyncSettings-CJWVtd87.js → SyncSettings-CLA78P-Z.js} +2 -2
  71. package/src/assets/web-panel/assets/{Tasks-61lrQ_lS.js → Tasks-DBjQ_DOM.js} +1 -1
  72. package/src/assets/web-panel/assets/Templates-BkSLDkBs.js +1 -0
  73. package/src/assets/web-panel/assets/Tenant-Dn0nSlib.js +1 -0
  74. package/src/assets/web-panel/assets/{Terminal-CP15hcNS.js → Terminal-C8f4boru.js} +2 -2
  75. package/src/assets/web-panel/assets/{TimelineRenderer-Sl5uXrkN.js → TimelineRenderer-DW_rMtJR.js} +1 -1
  76. package/src/assets/web-panel/assets/Tokens-BdffrKYV.js +1 -0
  77. package/src/assets/web-panel/assets/{Trigger-BLCQEOF2.js → Trigger-CX4CUg-Q.js} +1 -1
  78. package/src/assets/web-panel/assets/Trust-Cq9Bl7Od.js +1 -0
  79. package/src/assets/web-panel/assets/{UkeySign-Dwp0zXQ6.js → UkeySign-BQy18_VY.js} +1 -1
  80. package/src/assets/web-panel/assets/{VideoEditing-CIHA55Sx.js → VideoEditing-h5hzK7Vw.js} +1 -1
  81. package/src/assets/web-panel/assets/{Wallet-Hjajvnto.js → Wallet-BLotT3gw.js} +3 -3
  82. package/src/assets/web-panel/assets/{WebAuthn-DqSURUvI.js → WebAuthn-8cCANYLE.js} +4 -4
  83. package/src/assets/web-panel/assets/{WorkflowEditor-B5bHRwUG.js → WorkflowEditor-Db6NwtAv.js} +1 -1
  84. package/src/assets/web-panel/assets/{chat-DsheLKkG.js → chat-BPk1LbpL.js} +1 -1
  85. package/src/assets/web-panel/assets/{colors-CST2UkgL.js → colors-BnNal71p.js} +1 -1
  86. package/src/assets/web-panel/assets/{compact-item-yqEoy1L7.js → compact-item-W2VC0tcy.js} +1 -1
  87. package/src/assets/web-panel/assets/{createContext-Jwp78HFY.js → createContext-DceVsgnZ.js} +1 -1
  88. package/src/assets/web-panel/assets/devWarning--rwFDBhx.js +1 -0
  89. package/src/assets/web-panel/assets/{hasIn-CVS5mFEP.js → hasIn-BEq6EDcp.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-BLTUVd0V.js → index-5gIBUFBn.js} +2 -2
  91. package/src/assets/web-panel/assets/index-APCHxOkM.js +3 -0
  92. package/src/assets/web-panel/assets/index-B2dMhwZi.js +1 -0
  93. package/src/assets/web-panel/assets/{index-C0FZScMe.js → index-B8cPjrEH.js} +4 -4
  94. package/src/assets/web-panel/assets/{index-CjfN2CpJ.js → index-BDC5HsxZ.js} +1 -1
  95. package/src/assets/web-panel/assets/index-BPFuPGKi.js +1 -0
  96. package/src/assets/web-panel/assets/{index-SjxCCf5h.js → index-BUkDcIwJ.js} +2 -2
  97. package/src/assets/web-panel/assets/{index-Cjig5i3a.js → index-BWcCyH6-.js} +28 -26
  98. package/src/assets/web-panel/assets/{index-AnW25bEq.js → index-BgZikQoh.js} +1 -1
  99. package/src/assets/web-panel/assets/index-Bwjus13Y.js +1 -0
  100. package/src/assets/web-panel/assets/index-BzSzRWsw.js +55 -0
  101. package/src/assets/web-panel/assets/index-C1K9CsGr.js +1 -0
  102. package/src/assets/web-panel/assets/{index-DDAigsel.js → index-CBZVISK6.js} +2 -2
  103. package/src/assets/web-panel/assets/index-CEJN-R2L.js +1 -0
  104. package/src/assets/web-panel/assets/index-CG5dGC9E.js +1 -0
  105. package/src/assets/web-panel/assets/{index-DxaU_lza.js → index-CMGLpstm.js} +1 -1
  106. package/src/assets/web-panel/assets/index-CWrGCndd.js +1 -0
  107. package/src/assets/web-panel/assets/index-CbcvfpCV.js +1 -0
  108. package/src/assets/web-panel/assets/{index-De600Jjm.js → index-Ceqv4lI2.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Cy0dNzkp.js → index-CsT6frT8.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CDAPnZUs.js → index-D8PQKsDT.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Crk4KWLW.js → index-DGncdA-j.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-R-VGFpi6.js → index-DHanQHO0.js} +3 -3
  113. package/src/assets/web-panel/assets/index-DaUBk28E.js +12 -0
  114. package/src/assets/web-panel/assets/{index-BzetOasL.js → index-Di2J4b4V.js} +1 -1
  115. package/src/assets/web-panel/assets/index-DtuLvWZN.js +21 -0
  116. package/src/assets/web-panel/assets/{index-Dgyn8-wN.js → index-DvS1J8xc.js} +2 -2
  117. package/src/assets/web-panel/assets/{index-CtyEOGuj.js → index-DxePJdwP.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CzsKK0tQ.js → index-Et4XvL49.js} +2 -2
  119. package/src/assets/web-panel/assets/{index-BuI27WSx.js → index-GlFxgcj4.js} +2 -2
  120. package/src/assets/web-panel/assets/index-HV119Oui.js +1 -0
  121. package/src/assets/web-panel/assets/index-InGW87pj.js +13 -0
  122. package/src/assets/web-panel/assets/{index-Dxljh9Fu.js → index-P1-s8JR7.js} +2 -2
  123. package/src/assets/web-panel/assets/{index-CSBPc-sI.js → index-SdABCNoi.js} +2 -2
  124. package/src/assets/web-panel/assets/{index-BCHAUdel.js → index-WTAZbN-c.js} +1 -1
  125. package/src/assets/web-panel/assets/index-_2I-KzOj.js +1 -0
  126. package/src/assets/web-panel/assets/index-m1sVaWVU.js +1 -0
  127. package/src/assets/web-panel/assets/index-s37wwyeN.js +1 -0
  128. package/src/assets/web-panel/assets/{index-CRBbVS43.js → index-tyWABqp9.js} +1 -1
  129. package/src/assets/web-panel/assets/{initDefaultProps-ClAjrsQ-.js → initDefaultProps-DzrCDb3j.js} +1 -1
  130. package/src/assets/web-panel/assets/motion-BQERVnE3.js +11 -0
  131. package/src/assets/web-panel/assets/{move-DMelzIW-.js → move-I9ACA5XJ.js} +1 -1
  132. package/src/assets/web-panel/assets/mtc-parser-Dd2Pw-tr.js +1 -0
  133. package/src/assets/web-panel/assets/{omit-oxecfU3b.js → omit-DwzYRzWV.js} +1 -1
  134. package/src/assets/web-panel/assets/{pickAttrs-DJ5F5M6x.js → pickAttrs-BSGULyIL.js} +1 -1
  135. package/src/assets/web-panel/assets/{placementArrow-DdbKsant.js → placementArrow-tSYYjAts.js} +1 -1
  136. package/src/assets/web-panel/assets/{responsiveObserve-BUuM5cmS.js → responsiveObserve-Dy2lqikT.js} +1 -1
  137. package/src/assets/web-panel/assets/{slide-DSV0ccvR.js → slide-RaB4Uq0c.js} +1 -1
  138. package/src/assets/web-panel/assets/{statusUtils-B-6oLAXf.js → statusUtils-CBpC_wZg.js} +1 -1
  139. package/src/assets/web-panel/assets/{styleChecker-DdCAHtsZ.js → styleChecker-BEKwPWt5.js} +1 -1
  140. package/src/assets/web-panel/assets/{useFlexGapSupport-ZORkcoZd.js → useFlexGapSupport-C4CnYJH1.js} +1 -1
  141. package/src/assets/web-panel/assets/{useFs-BFp46LoP.js → useFs-n24jutw5.js} +1 -1
  142. package/src/assets/web-panel/assets/{usePersonalDataHub-H7rxgbdW.js → usePersonalDataHub-DMgS8F6G.js} +1 -1
  143. package/src/assets/web-panel/assets/{vnode-eIq4Tk0J.js → vnode-BSp2KYcj.js} +1 -1
  144. package/src/assets/web-panel/assets/{zoom-CTNrv8-H.js → zoom-7UfQtTPh.js} +1 -1
  145. package/src/assets/web-panel/index.html +1 -1
  146. package/src/commands/agent.js +51 -2
  147. package/src/commands/compliance.js +3 -1
  148. package/src/commands/ide.js +60 -5
  149. package/src/commands/incentive.js +22 -22
  150. package/src/commands/mtc.js +5 -1
  151. package/src/commands/review.js +47 -17
  152. package/src/commands/session.js +11 -2
  153. package/src/gateways/ws/message-dispatcher.js +149 -166
  154. package/src/gateways/ws/ws-session-gateway.js +95 -9
  155. package/src/harness/background-task-manager.js +5 -1
  156. package/src/harness/jsonl-session-store.js +90 -12
  157. package/src/harness/mcp-client.js +62 -21
  158. package/src/harness/prompt-compressor.js +24 -5
  159. package/src/harness/worktree-isolator.js +10 -1
  160. package/src/lib/agent-core.js +2 -0
  161. package/src/lib/audit-logger.js +3 -1
  162. package/src/lib/autonomous-agent.js +29 -0
  163. package/src/lib/chat-core.js +5 -2
  164. package/src/lib/chat-intent-service.js +82 -23
  165. package/src/lib/checkpoint-store.js +31 -4
  166. package/src/lib/claude-code-bridge.js +48 -3
  167. package/src/lib/config-manager.js +25 -1
  168. package/src/lib/cost-budget.js +13 -2
  169. package/src/lib/credential-guard.js +81 -1
  170. package/src/lib/git-integration.js +16 -2
  171. package/src/lib/goal-store.js +11 -0
  172. package/src/lib/hook-manager.js +4 -0
  173. package/src/lib/interaction-adapter.js +32 -11
  174. package/src/lib/jetbrains-bridge.js +147 -0
  175. package/src/lib/jsonl-session-store.js +2 -0
  176. package/src/lib/llm-config-defaults.js +37 -0
  177. package/src/lib/llm-pricing.js +11 -4
  178. package/src/lib/llm-providers.js +11 -1
  179. package/src/lib/mcp-oauth.js +88 -10
  180. package/src/lib/mcp-serve.js +29 -0
  181. package/src/lib/orchestrator.js +38 -2
  182. package/src/lib/permission-engine.js +4 -1
  183. package/src/lib/pipeline-orchestrator.js +20 -2
  184. package/src/lib/project-instructions.js +13 -0
  185. package/src/lib/repl-bang-memorize.js +9 -1
  186. package/src/lib/repl-denials.js +137 -0
  187. package/src/lib/runnable-provider.js +7 -1
  188. package/src/lib/safe-json.js +22 -0
  189. package/src/lib/sandbox-v2.js +7 -6
  190. package/src/lib/search-command.js +65 -0
  191. package/src/lib/session-insights.js +13 -6
  192. package/src/lib/session-usage.js +21 -3
  193. package/src/lib/settings-hooks.cjs +133 -0
  194. package/src/lib/settings-loader.cjs +16 -7
  195. package/src/lib/social-graph.js +3 -1
  196. package/src/lib/status-line.cjs +4 -1
  197. package/src/lib/stream-retry.js +27 -0
  198. package/src/lib/sub-agent-context.js +9 -0
  199. package/src/lib/turn-context.js +15 -5
  200. package/src/repl/agent-repl.js +110 -8
  201. package/src/runtime/__tests__/message-roles.test.js +36 -3
  202. package/src/runtime/agent-core.js +179 -52
  203. package/src/runtime/coding-agent-contract-shared.cjs +9 -2
  204. package/src/runtime/coding-agent-shell-policy.cjs +23 -2
  205. package/src/runtime/file-ref-expander.js +51 -7
  206. package/src/runtime/headless-runner.js +96 -2
  207. package/src/runtime/headless-stream.js +78 -3
  208. package/src/runtime/mcp-config.js +114 -4
  209. package/src/runtime/message-roles.js +14 -1
  210. package/src/runtime/pipe-safety.js +51 -0
  211. package/src/runtime/policies/agent-policy.js +3 -0
  212. package/src/assets/web-panel/assets/AIOps-BsDJlD_l.js +0 -1
  213. package/src/assets/web-panel/assets/Audit-BKlFbLdl.js +0 -1
  214. package/src/assets/web-panel/assets/ChatBubbleRenderer-DgvpwU5o.js +0 -1
  215. package/src/assets/web-panel/assets/Codegen-tKWGzajw.js +0 -1
  216. package/src/assets/web-panel/assets/Community-CmLuPBUU.js +0 -1
  217. package/src/assets/web-panel/assets/Compliance-PZw0aBLI.js +0 -1
  218. package/src/assets/web-panel/assets/Crosschain-Sb-uM7Ty.js +0 -1
  219. package/src/assets/web-panel/assets/Dashboard-Btag698v.js +0 -3
  220. package/src/assets/web-panel/assets/Federation-1jhstF5P.js +0 -1
  221. package/src/assets/web-panel/assets/Governance-BQrWksKt.js +0 -1
  222. package/src/assets/web-panel/assets/Inference-jEBTp12v.js +0 -1
  223. package/src/assets/web-panel/assets/KnowledgeGraph-tDiV2taf.js +0 -1
  224. package/src/assets/web-panel/assets/Marketplace-9Yi32avt.js +0 -1
  225. package/src/assets/web-panel/assets/MobileBridge-MfUfkHA0.js +0 -1
  226. package/src/assets/web-panel/assets/NLProgramming-DO3CZ0_z.js +0 -1
  227. package/src/assets/web-panel/assets/Pipeline-BZ7wRzG1.js +0 -1
  228. package/src/assets/web-panel/assets/Privacy-BJ6qj9Hv.js +0 -1
  229. package/src/assets/web-panel/assets/Projects-y1WbI337.js +0 -1
  230. package/src/assets/web-panel/assets/Recommend-Bju04wTd.js +0 -1
  231. package/src/assets/web-panel/assets/Reputation-BUPa3nEk.js +0 -1
  232. package/src/assets/web-panel/assets/Row-WYqqaq_5.js +0 -1
  233. package/src/assets/web-panel/assets/Search-CrfwJF0R.js +0 -1
  234. package/src/assets/web-panel/assets/Sla-CrMzaEi2.js +0 -1
  235. package/src/assets/web-panel/assets/SpeechSettings-jTDOM5eY.js +0 -1
  236. package/src/assets/web-panel/assets/Templates-Cg-iF2g1.js +0 -1
  237. package/src/assets/web-panel/assets/Tenant-DrDv1FFc.js +0 -1
  238. package/src/assets/web-panel/assets/Tokens-yRIZTVsR.js +0 -1
  239. package/src/assets/web-panel/assets/Trust-D5xq8z6s.js +0 -1
  240. package/src/assets/web-panel/assets/community-parser-Cuyslaku.js +0 -3
  241. package/src/assets/web-panel/assets/devWarning-C8to6gQk.js +0 -1
  242. package/src/assets/web-panel/assets/index-BeblNJDH.js +0 -1
  243. package/src/assets/web-panel/assets/index-C130LLPq.js +0 -1
  244. package/src/assets/web-panel/assets/index-C8rq85gu.js +0 -1
  245. package/src/assets/web-panel/assets/index-CIE2n8k_.js +0 -1
  246. package/src/assets/web-panel/assets/index-CTd3lDxp.js +0 -13
  247. package/src/assets/web-panel/assets/index-CUWj5L2s.js +0 -1
  248. package/src/assets/web-panel/assets/index-ChRL6rgA.js +0 -3
  249. package/src/assets/web-panel/assets/index-CrlRa054.js +0 -1
  250. package/src/assets/web-panel/assets/index-Cu6Ql64n.js +0 -1
  251. package/src/assets/web-panel/assets/index-Cx_t5rWw.js +0 -12
  252. package/src/assets/web-panel/assets/index-DZfnYE6e.js +0 -1
  253. package/src/assets/web-panel/assets/index-D_1b7uh6.js +0 -55
  254. package/src/assets/web-panel/assets/index-D_e9gwfn.js +0 -1
  255. package/src/assets/web-panel/assets/index-DbxAlpPC.js +0 -21
  256. package/src/assets/web-panel/assets/index-DiK4vSZa.js +0 -1
  257. package/src/assets/web-panel/assets/index-DpYn5v2k.js +0 -1
  258. package/src/assets/web-panel/assets/index-diWkx2Wq.js +0 -1
  259. package/src/assets/web-panel/assets/motion-BalXv_60.js +0 -11
  260. package/src/assets/web-panel/assets/mtc-parser-CEQffxds.js +0 -1
@@ -50,6 +50,11 @@ import { mergeConsecutiveMessages } from "./message-roles.js";
50
50
  import { isHeadlessConfigCommand } from "../lib/headless-config-command.js";
51
51
  import { withQuietStdout } from "./quiet-stdout.js";
52
52
  import { CostBudget } from "../lib/cost-budget.js";
53
+ import {
54
+ classifyDenial,
55
+ recordDenial,
56
+ formatDenials,
57
+ } from "../lib/repl-denials.js";
53
58
 
54
59
  /** Tools that cannot mutate the filesystem or run commands. */
55
60
  export const READ_ONLY_TOOLS = Object.freeze([
@@ -69,6 +74,11 @@ const VALID_PERMISSION_MODES = Object.freeze([
69
74
 
70
75
  const VALID_OUTPUT_FORMATS = Object.freeze(["text", "json", "stream-json"]);
71
76
 
77
+ // EPIPE guard for `cc agent -p … | head`. Lives in pipe-safety.js (shared with
78
+ // the stream-json driver + REPL); re-exported here for existing importers.
79
+ export { installPipeSafety } from "./pipe-safety.js";
80
+ import { installPipeSafety } from "./pipe-safety.js";
81
+
72
82
  /**
73
83
  * Resolve a --permission-mode string into the session-policy tier + a
74
84
  * non-interactive confirmer + whether to clamp tools to the read-only set.
@@ -289,17 +299,46 @@ export async function runAgentHeadless(options = {}, deps = {}) {
289
299
  let settingsHooks = options.settingsHooks || null;
290
300
  if (!settingsHooks) {
291
301
  try {
292
- const { loadHooks } = await import("../lib/settings-hooks.cjs");
302
+ const { loadHooks, projectHookTrustNotice } =
303
+ await import("../lib/settings-hooks.cjs");
293
304
  const loaded = loadHooks({ cwd, settingsFile: options.settingsFile });
294
305
  settingsHooks =
295
306
  loaded.hooks && Object.keys(loaded.hooks).length > 0
296
307
  ? loaded.hooks
297
308
  : null;
309
+ // First-run trust notice for an untrusted/cloned repo's shell-running
310
+ // hooks (Claude-Code 2.1.195 parity). Best-effort, stderr-only.
311
+ try {
312
+ const notice = projectHookTrustNotice({
313
+ cwd,
314
+ settingsFile: options.settingsFile,
315
+ });
316
+ if (notice) process.stderr.write(notice + "\n");
317
+ } catch {
318
+ /* trust notice is best-effort */
319
+ }
298
320
  } catch {
299
321
  settingsHooks = null; // fail-open
300
322
  }
301
323
  }
302
324
 
325
+ // autoMode.classifyAllShell (Claude-Code 2.1.193): route the built-in
326
+ // verification allowlist through the shell-policy classifier instead of
327
+ // fast-pathing it. Explicit option wins; otherwise read settings.json.
328
+ let classifyAllShell = options.classifyAllShell || false;
329
+ if (!classifyAllShell) {
330
+ try {
331
+ const { readBooleanSetting } = await import("../lib/settings-loader.cjs");
332
+ classifyAllShell =
333
+ readBooleanSetting("autoMode.classifyAllShell", {
334
+ cwd,
335
+ settingsFile: options.settingsFile,
336
+ }) === true;
337
+ } catch {
338
+ classifyAllShell = false; // fail-open
339
+ }
340
+ }
341
+
303
342
  const runLoop = deps.agentLoop || coreAgentLoop;
304
343
  const doBootstrap = deps.bootstrap || bootstrap;
305
344
  const getApprovalGate =
@@ -312,6 +351,12 @@ export async function runAgentHeadless(options = {}, deps = {}) {
312
351
  // trace so `cc agent -p ... > out.txt` keeps `out.txt` clean.
313
352
  const writeOut = deps.writeOut || ((s) => process.stdout.write(s));
314
353
  const writeErr = deps.writeErr || ((s) => process.stderr.write(s));
354
+ // Only when we own the real stdout/stderr (no injected seams = production,
355
+ // not tests): guard against a downstream `| head` closing the pipe, which
356
+ // would otherwise crash with an unhandled EPIPE. Idempotent across calls.
357
+ if (!deps.writeOut && !deps.writeErr) {
358
+ installPipeSafety();
359
+ }
315
360
  // Session persistence seam (file-based JSONL; DB-free, like the rest of
316
361
  // headless). Defaults to the real store; tests inject fakes.
317
362
  const store = {
@@ -667,6 +712,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
667
712
  strict: options.strictMcpConfig === true,
668
713
  ide: options.ide,
669
714
  pdh: options.pdh,
715
+ jetbrains: options.jetbrains,
670
716
  cwd: options.cwd || process.cwd(),
671
717
  // advertise the session id to spawned stdio MCP servers
672
718
  sessionId,
@@ -676,6 +722,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
676
722
  loadMcpConfig: deps.loadMcpConfig,
677
723
  loadRegisteredMcp: deps.loadRegisteredMcp,
678
724
  loadIdeMcp: deps.loadIdeMcp,
725
+ loadJetbrainsMcp: deps.loadJetbrainsMcp,
679
726
  },
680
727
  );
681
728
  if (mcp && isText) {
@@ -763,6 +810,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
763
810
  approvalGate,
764
811
  permissionRules,
765
812
  settingsHooks,
813
+ classifyAllShell,
766
814
  enabledToolNames,
767
815
  disabledTools,
768
816
  iterationBudget: budget,
@@ -834,6 +882,10 @@ export async function runAgentHeadless(options = {}, deps = {}) {
834
882
 
835
883
  const startedAt = deps.now ? deps.now() : Date.now();
836
884
  const toolCalls = [];
885
+ // Policy denials (blocked tool calls) collected for an end-of-run summary,
886
+ // so a non-interactive run surfaces what got blocked the way the REPL's
887
+ // `/permissions denials` does (Claude-Code 2.1.193 denial reasons).
888
+ const denials = [];
837
889
  const usage = {
838
890
  input_tokens: 0,
839
891
  output_tokens: 0,
@@ -911,6 +963,26 @@ export async function runAgentHeadless(options = {}, deps = {}) {
911
963
  if (toolCalls.length > 0) {
912
964
  toolCalls[toolCalls.length - 1].is_error = Boolean(err);
913
965
  }
966
+ // Track policy denials (not plain tool failures) for the end-of-run
967
+ // summary. The preceding tool-executing pushed the args.
968
+ if (err) {
969
+ const last = toolCalls[toolCalls.length - 1];
970
+ const denial = classifyDenial({
971
+ tool: event.tool,
972
+ result: event.result,
973
+ error: event.error,
974
+ argsSummary:
975
+ last && last.tool === event.tool
976
+ ? formatToolArgs(event.tool, last.args)
977
+ : "",
978
+ });
979
+ if (denial) {
980
+ recordDenial(denials, {
981
+ ...denial,
982
+ at: deps.now ? deps.now() : Date.now(),
983
+ });
984
+ }
985
+ }
914
986
  break;
915
987
  }
916
988
  case "token-usage": {
@@ -1000,6 +1072,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
1000
1072
  usage,
1001
1073
  numTurns: budget.consumed,
1002
1074
  durationMs: (deps.now ? deps.now() : Date.now()) - startedAt,
1075
+ denials,
1003
1076
  }),
1004
1077
  ) + "\n",
1005
1078
  );
@@ -1119,6 +1192,21 @@ export async function runAgentHeadless(options = {}, deps = {}) {
1119
1192
  }
1120
1193
  }
1121
1194
 
1195
+ // End-of-run policy-denial summary so a non-interactive run surfaces what was
1196
+ // blocked (mirrors the REPL's `/permissions denials`). Text → stderr lines;
1197
+ // stream → a `denials_summary` event before the final result.
1198
+ if (denials.length) {
1199
+ if (isText) {
1200
+ writeErr(
1201
+ `\n ${denials.length} tool call(s) were denied by policy this run:\n` +
1202
+ formatDenials(denials, { now: deps.now ? deps.now() : Date.now() }) +
1203
+ "\n",
1204
+ );
1205
+ } else if (isStream) {
1206
+ emitStream({ type: "denials_summary", count: denials.length, denials });
1207
+ }
1208
+ }
1209
+
1122
1210
  if (isStream) {
1123
1211
  emitStream({
1124
1212
  type: "result",
@@ -1142,6 +1230,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
1142
1230
  usage,
1143
1231
  numTurns: budget.consumed,
1144
1232
  durationMs,
1233
+ denials,
1145
1234
  }),
1146
1235
  ) + "\n",
1147
1236
  );
@@ -1162,8 +1251,9 @@ function buildResultEnvelope({
1162
1251
  usage,
1163
1252
  numTurns,
1164
1253
  durationMs,
1254
+ denials,
1165
1255
  }) {
1166
- return {
1256
+ const env = {
1167
1257
  type: "result",
1168
1258
  subtype,
1169
1259
  is_error: isError,
@@ -1174,4 +1264,8 @@ function buildResultEnvelope({
1174
1264
  tool_calls: toolCalls,
1175
1265
  usage,
1176
1266
  };
1267
+ // Only present when something was blocked — keeps the no-denial envelope
1268
+ // byte-identical to before (Claude-Code 2.1.193 denial reasons, json mode).
1269
+ if (Array.isArray(denials) && denials.length) env.denials = denials;
1270
+ return env;
1177
1271
  }
@@ -35,6 +35,7 @@ import {
35
35
  resolvePermissionMode,
36
36
  resolveEnabledTools,
37
37
  parseToolList,
38
+ installPipeSafety,
38
39
  } from "./headless-runner.js";
39
40
  import {
40
41
  startSession as jsonlStartSession,
@@ -317,9 +318,26 @@ export function sanitizeLlmHint(raw) {
317
318
  /**
318
319
  * Yield NDJSON lines from a byte/string stream (stdin). Splits on "\n" and
319
320
  * flushes any trailing partial line when the stream ends.
321
+ *
322
+ * A single line with no terminating "\n" must never accumulate without bound:
323
+ * a stuck / garbage producer (or a runaway multi-MB inline payload) that never
324
+ * emits a newline would otherwise grow `buf` unbounded and OOM this long-lived
325
+ * stream process. When a line exceeds the cap, a short head is yielded (so the
326
+ * caller surfaces it as an invalid-JSON error rather than dropping it silently)
327
+ * and the rest of that monster line is discarded until its newline — the stream
328
+ * resyncs cleanly to the next well-formed line. Cap precedence:
329
+ * `opts.maxLineLength` > `CC_MAX_INPUT_LINE_BYTES` env > 16 MB default.
320
330
  */
321
- export async function* readJsonLines(input) {
331
+ export async function* readJsonLines(input, opts = {}) {
332
+ const envCap = Number(process.env.CC_MAX_INPUT_LINE_BYTES);
333
+ const maxLineLength =
334
+ Number.isFinite(opts.maxLineLength) && opts.maxLineLength > 0
335
+ ? opts.maxLineLength
336
+ : Number.isFinite(envCap) && envCap > 0
337
+ ? envCap
338
+ : 16 * 1024 * 1024;
322
339
  let buf = "";
340
+ let overflow = false; // discarding the tail of an over-long line until its \n
323
341
  // Reuse ONE streaming decoder across chunks so a multi-byte UTF-8 character
324
342
  // (e.g. a 3-byte Chinese char) split across two Buffer chunks is reassembled
325
343
  // rather than corrupted. process.stdin yields Buffers with no setEncoding, so
@@ -331,14 +349,34 @@ export async function* readJsonLines(input) {
331
349
  typeof chunk === "string"
332
350
  ? chunk
333
351
  : decoder.decode(chunk, { stream: true });
352
+ // Still skipping past an over-long line: drop everything up to (and
353
+ // including) the next newline, then resume normal line parsing. While no
354
+ // newline has arrived, keep `buf` empty so we don't re-grow it.
355
+ if (overflow) {
356
+ const nl = buf.indexOf("\n");
357
+ if (nl < 0) {
358
+ buf = "";
359
+ continue;
360
+ }
361
+ buf = buf.slice(nl + 1);
362
+ overflow = false;
363
+ }
334
364
  let idx;
335
365
  while ((idx = buf.indexOf("\n")) >= 0) {
336
366
  yield buf.slice(0, idx);
337
367
  buf = buf.slice(idx + 1);
338
368
  }
369
+ // No newline in the remaining buffer and it has blown past the cap — this is
370
+ // a pathological unterminated line. Yield a short head (an invalid-JSON
371
+ // error for the caller) and discard the rest until the next newline.
372
+ if (buf.length > maxLineLength) {
373
+ yield buf.slice(0, 200);
374
+ buf = "";
375
+ overflow = true;
376
+ }
339
377
  }
340
378
  buf += decoder.decode(); // flush any bytes held from a final partial char
341
- if (buf.trim()) yield buf;
379
+ if (!overflow && buf.trim()) yield buf;
342
380
  }
343
381
 
344
382
  /**
@@ -496,23 +534,57 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
496
534
  let settingsHooks = options.settingsHooks || null;
497
535
  if (!settingsHooks) {
498
536
  try {
499
- const { loadHooks } = await import("../lib/settings-hooks.cjs");
537
+ const { loadHooks, projectHookTrustNotice } =
538
+ await import("../lib/settings-hooks.cjs");
500
539
  const loaded = loadHooks({ cwd, settingsFile: options.settingsFile });
501
540
  settingsHooks =
502
541
  loaded.hooks && Object.keys(loaded.hooks).length > 0
503
542
  ? loaded.hooks
504
543
  : null;
544
+ // First-run trust notice for an untrusted/cloned repo's shell-running
545
+ // hooks (Claude-Code 2.1.195 parity). stderr keeps the NDJSON stdout clean.
546
+ try {
547
+ const notice = projectHookTrustNotice({
548
+ cwd,
549
+ settingsFile: options.settingsFile,
550
+ });
551
+ if (notice) process.stderr.write(notice + "\n");
552
+ } catch {
553
+ /* trust notice is best-effort */
554
+ }
505
555
  } catch {
506
556
  settingsHooks = null; // fail-open
507
557
  }
508
558
  }
509
559
 
560
+ // autoMode.classifyAllShell (Claude-Code 2.1.193): classify the built-in
561
+ // verification allowlist through the shell-policy instead of fast-pathing it.
562
+ let classifyAllShell = options.classifyAllShell || false;
563
+ if (!classifyAllShell) {
564
+ try {
565
+ const { readBooleanSetting } = await import("../lib/settings-loader.cjs");
566
+ classifyAllShell =
567
+ readBooleanSetting("autoMode.classifyAllShell", {
568
+ cwd,
569
+ settingsFile: options.settingsFile,
570
+ }) === true;
571
+ } catch {
572
+ classifyAllShell = false; // fail-open
573
+ }
574
+ }
575
+
510
576
  const input = deps.input || process.stdin;
511
577
  const runLoop = deps.agentLoop || coreAgentLoop;
512
578
  const doBootstrap = deps.bootstrap || bootstrap;
513
579
  const doExpand = deps.expandFileRefs || expandFileRefsAsync;
514
580
  const writeOut = deps.writeOut || ((s) => process.stdout.write(s));
515
581
  const writeErr = deps.writeErr || ((s) => process.stderr.write(s));
582
+ // Guard the real stdout/stderr against a downstream `| head` closing the pipe
583
+ // (unhandled async EPIPE → crash). Only when we own the streams (no injected
584
+ // seams = production, not tests). Idempotent; shared with the -p runner.
585
+ if (!deps.writeOut && !deps.writeErr) {
586
+ installPipeSafety();
587
+ }
516
588
  // Batch consecutive partial-message text/thinking deltas into one stream_event
517
589
  // line (Claude-Code 2.1.191 streaming-CPU optimization). `emit` flushes any
518
590
  // pending deltas before writing a non-delta line, so ordering is preserved;
@@ -832,6 +904,7 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
832
904
  strict: options.strictMcpConfig === true,
833
905
  ide: options.ide,
834
906
  pdh: options.pdh,
907
+ jetbrains: options.jetbrains,
835
908
  cwd: options.cwd || process.cwd(),
836
909
  // advertise the session id to spawned stdio MCP servers
837
910
  sessionId,
@@ -841,6 +914,7 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
841
914
  loadMcpConfig: deps.loadMcpConfig,
842
915
  loadRegisteredMcp: deps.loadRegisteredMcp,
843
916
  loadIdeMcp: deps.loadIdeMcp,
917
+ loadJetbrainsMcp: deps.loadJetbrainsMcp,
844
918
  },
845
919
  );
846
920
  } catch (err) {
@@ -905,6 +979,7 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
905
979
  approvalGate,
906
980
  permissionRules,
907
981
  settingsHooks,
982
+ classifyAllShell,
908
983
  enabledToolNames,
909
984
  disabledTools,
910
985
  // --interactive-approvals: settings/hook `ask` (and, with an IDE bridge,
@@ -28,6 +28,11 @@ import {
28
28
  pdhServerToMcpConfig,
29
29
  isInPdhTerminal,
30
30
  } from "../lib/pdh-bridge.js";
31
+ import {
32
+ discoverJetbrainsServer,
33
+ jetbrainsServerToMcpConfig,
34
+ isInJetbrainsContext,
35
+ } from "../lib/jetbrains-bridge.js";
31
36
 
32
37
  /**
33
38
  * Normalize a parsed config object into a `{ name: serverConfig }` map.
@@ -60,6 +65,22 @@ export function mcpToolName(server, tool) {
60
65
  return `mcp__${server}__${tool}`;
61
66
  }
62
67
 
68
+ /**
69
+ * Case-insensitive "does this header map already carry `name`?". HTTP header
70
+ * names are case-insensitive, so a caller-supplied `AUTHORIZATION` must count
71
+ * the same as `Authorization` — otherwise the OAuth-injection guard below would
72
+ * not see it and would add a SECOND, conflicting auth header, leaking our
73
+ * stored token where the user explicitly pinned their own credential.
74
+ */
75
+ export function hasHeaderInsensitive(headers, name) {
76
+ if (!headers || typeof headers !== "object") return false;
77
+ const want = String(name).toLowerCase();
78
+ for (const k of Object.keys(headers)) {
79
+ if (k.toLowerCase() === want) return true;
80
+ }
81
+ return false;
82
+ }
83
+
63
84
  /**
64
85
  * When an MCP connect fails with an authentication error (HTTP 401/403, or an
65
86
  * explicit Unauthorized/Forbidden) on a URL-based server, return an actionable
@@ -138,7 +159,7 @@ export async function setupMcpFromConfig(servers, deps = {}) {
138
159
  // unless the config already supplies an Authorization header. Best-effort:
139
160
  // no token / a refresh failure just connects unauthenticated.
140
161
  let connectCfg = cfg;
141
- if (cfg.url && !cfg.headers?.Authorization && !cfg.headers?.authorization) {
162
+ if (cfg.url && !hasHeaderInsensitive(cfg.headers, "Authorization")) {
142
163
  try {
143
164
  const { ensureValidToken } = await import("../lib/mcp-oauth.js");
144
165
  const token = await ensureValidToken(cfg.url);
@@ -147,6 +168,31 @@ export async function setupMcpFromConfig(servers, deps = {}) {
147
168
  ...cfg,
148
169
  headers: { ...cfg.headers, Authorization: `Bearer ${token}` },
149
170
  };
171
+ // Auto-recover from a mid-session 401/403 (server-side token rotation
172
+ // / revocation while the locally-stored copy still looks unexpired):
173
+ // register a reconnector that force-refreshes the bearer, so the
174
+ // mcp-client's callTool retry path reconnects and re-runs the call
175
+ // once with a fresh token (Claude-Code 2.1.193: "MCP auth re-runs and
176
+ // reconnects automatically on 401/403"). Best-effort, and skipped for
177
+ // a server whose config carries its own Authorization header (handled
178
+ // by the guard above) — an explicit IDE-bridge reconnector registered
179
+ // after setup still wins on any name clash.
180
+ if (typeof mcpClient.setReconnector === "function") {
181
+ const baseCfg = cfg;
182
+ mcpClient.setReconnector(name, async () => {
183
+ const { ensureValidToken: reauth } =
184
+ await import("../lib/mcp-oauth.js");
185
+ const fresh = await reauth(baseCfg.url, { forceRefresh: true });
186
+ if (!fresh) return null;
187
+ return {
188
+ ...baseCfg,
189
+ headers: {
190
+ ...baseCfg.headers,
191
+ Authorization: `Bearer ${fresh}`,
192
+ },
193
+ };
194
+ });
195
+ }
150
196
  }
151
197
  } catch {
152
198
  // OAuth wiring is best-effort
@@ -463,6 +509,47 @@ export async function loadPdhMcp(opts = {}, deps = {}) {
463
509
  return out;
464
510
  }
465
511
 
512
+ /**
513
+ * Connect IntelliJ IDEA's built-in MCP server (IDEA >= 2025.2) as the reserved
514
+ * server `idea` -> tools `mcp__idea__*`. The ChainlessChain JetBrains plugin
515
+ * injects the exact endpoint (CHAINLESSCHAIN_JETBRAINS_MCP_URL + optional
516
+ * _TOKEN) into the cc it spawns ONLY when the IDE actually supports + enables
517
+ * MCP; absent that, this is a no-op (we never scan/guess/spawn a proxy — if
518
+ * the IDE's MCP is unsupported, we don't connect). Best-effort: returns
519
+ * `deps.into` (or null) on nothing found / bad config, never throws. An explicit
520
+ * user registration of a server named `idea` wins (yield + one-line warning).
521
+ *
522
+ * @param {object} opts { env? }
523
+ * @param {object} [deps] { writeErr, into, discoverJetbrainsServer, jetbrainsServerToMcpConfig }
524
+ */
525
+ export async function loadJetbrainsMcp(opts = {}, deps = {}) {
526
+ const discover = deps.discoverJetbrainsServer || discoverJetbrainsServer;
527
+ const toCfg = deps.jetbrainsServerToMcpConfig || jetbrainsServerToMcpConfig;
528
+ const found = discover({ env: opts.env });
529
+ if (!found) return deps.into || null;
530
+ if (deps.into?.mcpClient?.servers?.has?.("idea")) {
531
+ (deps.writeErr || (() => {}))(
532
+ ` idea: server "idea" already registered explicitly — ` +
533
+ `skipping IDEA built-in MCP auto-connect\n`,
534
+ );
535
+ return deps.into;
536
+ }
537
+ const cfg = toCfg(found);
538
+ if (!cfg) return deps.into || null;
539
+ const out = await setupMcpFromConfig({ idea: cfg }, deps);
540
+ // Hot reconnect: re-read the injected env on a failed mcp__idea__* call (the
541
+ // IDE may have restarted its MCP server on a new port/token, and the plugin
542
+ // re-injects a fresh CHAINLESSCHAIN_JETBRAINS_MCP_URL into the next spawn —
543
+ // though within one run the env is fixed, so this just re-validates it).
544
+ if (out?.mcpClient?.setReconnector) {
545
+ out.mcpClient.setReconnector("idea", () => {
546
+ const fresh = discover({ env: opts.env });
547
+ return fresh ? toCfg(fresh) : null;
548
+ });
549
+ }
550
+ return out;
551
+ }
552
+
466
553
  /**
467
554
  * Discover + connect a project-scoped `.mcp.json` (Claude-Code parity). Reads a
468
555
  * `.mcp.json` from the git project root (walked up from cwd, same as the
@@ -534,10 +621,13 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
534
621
  * there's nothing. Throws only on a bad `--mcp-config` file (explicit request).
535
622
  *
536
623
  * IDE discovery: default ON only inside an IDE integrated terminal; `ide:true`
537
- * (`--ide`) forces it; `ide:false` (`--no-ide`) disables it.
624
+ * (`--ide`) forces it; `ide:false` (`--no-ide`) disables it. IDEA built-in MCP
625
+ * (reserved `idea`): default ON only when the JetBrains plugin injected
626
+ * `CHAINLESSCHAIN_JETBRAINS_MCP_URL`; `jetbrains:true` (`--jetbrains`) forces;
627
+ * `jetbrains:false` (`--no-jetbrains`) disables.
538
628
  *
539
- * @param {object} args { mcpConfigPath?, db?, includeRegistered=true, allRegistered=false, ide?, pdh?, cwd?, env? }
540
- * @param {object} [deps] { writeErr, loadMcpConfig, loadRegisteredMcp, loadIdeMcp, loadPdhMcp, isInIdeTerminal, isInPdhTerminal }
629
+ * @param {object} args { mcpConfigPath?, db?, includeRegistered=true, allRegistered=false, ide?, pdh?, jetbrains?, cwd?, env? }
630
+ * @param {object} [deps] { writeErr, loadMcpConfig, loadRegisteredMcp, loadIdeMcp, loadPdhMcp, loadJetbrainsMcp, isInIdeTerminal, isInPdhTerminal, isInJetbrainsContext }
541
631
  */
542
632
  export async function resolveAgentMcp(args = {}, deps = {}) {
543
633
  const doFile = deps.loadMcpConfig || loadMcpConfig;
@@ -545,6 +635,7 @@ export async function resolveAgentMcp(args = {}, deps = {}) {
545
635
  const doProject = deps.loadProjectMcp || loadProjectMcp;
546
636
  const doIde = deps.loadIdeMcp || loadIdeMcp;
547
637
  const doPdh = deps.loadPdhMcp || loadPdhMcp;
638
+ const doJetbrains = deps.loadJetbrainsMcp || loadJetbrainsMcp;
548
639
  // Thread the agent session id down to setupMcpFromConfig so spawned stdio MCP
549
640
  // servers get CC_SESSION_ID / CLAUDE_CODE_SESSION_ID (Claude-Code parity).
550
641
  const fwd =
@@ -601,6 +692,25 @@ export async function resolveAgentMcp(args = {}, deps = {}) {
601
692
  );
602
693
  }
603
694
  }
695
+ // IntelliJ IDEA built-in MCP (IDEA >= 2025.2), reserved name `idea` ->
696
+ // mcp__idea__*. Scoped to the JetBrains plugin context: the plugin injects
697
+ // CHAINLESSCHAIN_JETBRAINS_MCP_URL only when the IDE supports + enables MCP,
698
+ // so default-ON is gated on that env being present (isInJetbrainsContext).
699
+ // `jetbrains:true` (--jetbrains) forces the attempt; `jetbrains:false`
700
+ // (--no-jetbrains) disables it. No URL = no connect (unsupported IDE).
701
+ // Skipped under --strict-mcp-config (returned above).
702
+ if (args.jetbrains !== false) {
703
+ const env = args.env || process.env;
704
+ const inJetbrains = (deps.isInJetbrainsContext || isInJetbrainsContext)(
705
+ env,
706
+ );
707
+ if (args.jetbrains === true || inJetbrains) {
708
+ result = await doJetbrains(
709
+ { env },
710
+ { ...fwd, into: result || undefined },
711
+ );
712
+ }
713
+ }
604
714
  return result;
605
715
  }
606
716
 
@@ -64,6 +64,17 @@ function joinContent(a, b) {
64
64
  */
65
65
  const MERGEABLE_ROLES = new Set(["user", "assistant"]);
66
66
 
67
+ /**
68
+ * Does this message carry tool calls? An assistant turn with `tool_calls` is a
69
+ * STRUCTURED turn whose calls must stay paired with their `tool` results —
70
+ * folding it loses one side's tool_calls (orphaning results / unanswered calls)
71
+ * and the strict-API 400s. Such turns are never merged (left to alternate; the
72
+ * tool-pair fix lives in sanitizeToolPairs, not here).
73
+ */
74
+ function hasToolCalls(msg) {
75
+ return Array.isArray(msg && msg.tool_calls) && msg.tool_calls.length > 0;
76
+ }
77
+
67
78
  /**
68
79
  * Merge consecutive same-role messages so the conversation alternates roles for
69
80
  * the provider. Only `user`/`assistant` turns fold; `tool` and `system` turns
@@ -85,7 +96,9 @@ export function mergeConsecutiveMessages(messages) {
85
96
  msg &&
86
97
  typeof msg.role === "string" &&
87
98
  MERGEABLE_ROLES.has(msg.role) &&
88
- prev.role === msg.role
99
+ prev.role === msg.role &&
100
+ !hasToolCalls(prev) && // never fold a structured tool-call turn — merging
101
+ !hasToolCalls(msg) // drops one side's tool_calls and breaks pairing
89
102
  ) {
90
103
  out[out.length - 1] = {
91
104
  ...prev,
@@ -0,0 +1,51 @@
1
+ /**
2
+ * pipe-safety — shared EPIPE guard for cc's stdout/stderr writers.
3
+ *
4
+ * A downstream consumer that closes the pipe (e.g. `cc agent -p … | head`)
5
+ * makes the next write fail ASYNCHRONOUSLY via the stream's `error` event,
6
+ * which the try/catch around a write call cannot catch. With no `error`
7
+ * listener that is an unhandled EPIPE → the process crashes with a stack trace
8
+ * instead of stopping cleanly. `installPipeSafety` adds an idempotent listener
9
+ * that treats EPIPE as "consumer done" (the Unix pipeline convention) and
10
+ * surfaces other stream errors best-effort.
11
+ *
12
+ * Used by the headless `-p` runner, the stream-json driver, and the REPL.
13
+ */
14
+
15
+ // Global-registry symbol so the guard is installed at most once per stream even
16
+ // across the modules that share it.
17
+ const _PIPE_SAFE = Symbol.for("cc.headless.pipeSafe");
18
+
19
+ /**
20
+ * Install an EPIPE-safe `error` listener on the given write streams (default:
21
+ * process.stdout + process.stderr). Idempotent. `onEpipe` defaults to a clean
22
+ * `process.exit(0)`; the REPL passes a graceful-shutdown callback instead.
23
+ *
24
+ * @param {Array<NodeJS.WriteStream>} [streams]
25
+ * @param {() => void} [onEpipe]
26
+ */
27
+ export function installPipeSafety(streams, onEpipe) {
28
+ const targets = streams || [process.stdout, process.stderr];
29
+ const handleEpipe = onEpipe || (() => process.exit(0));
30
+ for (const stream of targets) {
31
+ if (!stream || typeof stream.on !== "function" || stream[_PIPE_SAFE]) {
32
+ continue;
33
+ }
34
+ stream[_PIPE_SAFE] = true;
35
+ stream.on("error", (err) => {
36
+ if (err && err.code === "EPIPE") {
37
+ handleEpipe();
38
+ return;
39
+ }
40
+ // Non-EPIPE stream error: surface best-effort (never onto the stream that
41
+ // just errored, to avoid a loop) and otherwise swallow.
42
+ try {
43
+ if (stream !== process.stderr) {
44
+ process.stderr.write(`stream error: ${err?.message || err}\n`);
45
+ }
46
+ } catch {
47
+ /* nothing more we can do */
48
+ }
49
+ });
50
+ }
51
+ }
@@ -38,6 +38,9 @@ export function resolveAgentPolicy({
38
38
  // IDE bridge tri-state (undefined=auto / true=--ide / false=--no-ide); the
39
39
  // REPL forwards it to resolveAgentMcp so --ide/--no-ide work interactively.
40
40
  ide: overrides.ide,
41
+ // IDEA built-in MCP tri-state (undefined=auto when the JetBrains plugin
42
+ // injected the endpoint / true=--jetbrains / false=--no-jetbrains).
43
+ jetbrains: overrides.jetbrains,
41
44
  };
42
45
  }
43
46