chainlesschain 0.166.105 → 0.166.107

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 (211) hide show
  1. package/README.md +182 -8
  2. package/package.json +2 -2
  3. package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
  4. package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
  5. package/src/assets/web-panel/assets/{AIOps-CcD-AVDw.js → AIOps-DCx6L_HW.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-CYy-g36A.js → ActionButton-DYm1CN3Z.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-DPFDNaBL.js → Analytics-D5ItUS_y.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-PVIuRdgN.js → AppLayout-Cb7XeRdH.js} +5 -5
  9. package/src/assets/web-panel/assets/{Artifacts-BXGD3bM-.js → Artifacts-DDDeqCDQ.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-Bu5s_4tu.js → Audit-BRt3x13w.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-BHmgpnzo.js → BackgroundAgents-C_oNALMd.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-C872jURx.js → Backup-PSU2p6CR.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-Bh7xO30H.js → BaseInput-G3oL4hcX.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-DaacK53T.js → Chat-C2cLI10b.js} +6 -6
  15. package/src/assets/web-panel/assets/{ChatBubbleRenderer-PYrSKMM_.js → ChatBubbleRenderer-KX1OITf8.js} +1 -1
  16. package/src/assets/web-panel/assets/{Checkbox-Cnt7_8I2.js → Checkbox-CHLnEgFD.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-AZRz6kmW.js → Codegen-DZm9g_Bc.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-BtOXzMFt.js → Col-D5Z4zSay.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-BFmFygS7.js → Community-DHw69NSk.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-2z5CfKpR.js → Compact-B-vjYNWz.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-B5hKrPVF.js → Compliance-DaIYVZQY.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-CxEyp2ww.js → Cowork-CoA9U-gF.js} +3 -3
  23. package/src/assets/web-panel/assets/{Cron-B-8f9_qF.js → Cron-DXqmxlRC.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-XARMOcc4.js → Crosschain-Cdkc3ue1.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-DwLtEKAe.js → DID-oKfYyNSR.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-Cjw0L_iA.js → Dashboard-n_ycvgWu.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-BBGWIP7l.js → Dropdown-D38rZ8WY.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer-DG4kZFkm.js → EmailListRenderer-BjreeBQ1.js} +1 -1
  29. package/src/assets/web-panel/assets/{EvolutionSettings-D8vuNDde.js → EvolutionSettings-CTxA_SIq.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-COXCzDXI.js → FamilyGuardDashboard-DmECNwV5.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-Btb-aMhW.js → Federation-B2IaaDmQ.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-TO-E6l6e.js → FormItemContext-DgcgqUIk.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-BWXdJCT0.js → GenericCardRenderer-B1-du6Qm.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-B6icGhEv.js → Git-XceM21Il.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-C5Y__K6S.js → Governance-CV97iz3z.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-DZGEKnbN.js → Inference-CI7fj305.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph--Kga5yvm.js → KnowledgeGraph-B5mekWRy.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-BXs3EPKj.js → Logs-BlxFA0xY.js} +2 -2
  39. package/src/assets/web-panel/assets/MarkdownRenderer-rDE-XyMY.js +1 -0
  40. package/src/assets/web-panel/assets/{Marketplace-JSEAu0su.js → Marketplace-DL1BVCiX.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-BUBifkKP.js → McpTools-BPtwrO3c.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-Cb7sE4a-.js → Memory-DuSNw4E-.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-BOzmmNV2.js → MobileBridge-DTgY9ywI.js} +1 -1
  44. package/src/assets/web-panel/assets/MobileProjects-CTpVHJMa.js +1 -0
  45. package/src/assets/web-panel/assets/{Mtc-DmMWErG1.js → Mtc-h4fCLjXw.js} +2 -2
  46. package/src/assets/web-panel/assets/{MtcAudit-DnGkRVXF.js → MtcAudit-fqMDY3-w.js} +2 -2
  47. package/src/assets/web-panel/assets/{Multisig-C3mzascL.js → Multisig-Do3FehBL.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-CrmMZZ1t.js → NLProgramming-CQVY0kQF.js} +1 -1
  49. package/src/assets/web-panel/assets/Notes-4c3oNvWh.js +7 -0
  50. package/src/assets/web-panel/assets/{NotificationSettings-gn3UrWwW.js → NotificationSettings-BKr2JD4k.js} +1 -1
  51. package/src/assets/web-panel/assets/OrderTableRenderer-Bq4jgzRt.js +1 -0
  52. package/src/assets/web-panel/assets/{Organization-fMlkdgpW.js → Organization-Dy3XidyA.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-DGwCUPU1.js → Overflow-DFF0qN5K.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-BDGcpPmf.js → P2P-DAgYYykd.js} +2 -2
  55. package/src/assets/web-panel/assets/{PdhVaultBrowser-CccRPAB9.js → PdhVaultBrowser-DgNHa8b1.js} +3 -3
  56. package/src/assets/web-panel/assets/{Permissions-C33dNECx.js → Permissions-Cev6uSBc.js} +3 -3
  57. package/src/assets/web-panel/assets/{PersonalDataHub-BeqbCStc.js → PersonalDataHub-DJzbN06K.js} +4 -4
  58. package/src/assets/web-panel/assets/{Pipeline-CTmasgbQ.js → Pipeline-CoJWvbQ5.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-ktd37BSp.js → Privacy-DZxV6etm.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-KOGvQtBX.js → ProjectInit-BFW87JnM.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-CUvH_hC6.js → ProjectSettings-LBrRT27p.js} +2 -2
  62. package/src/assets/web-panel/assets/Projects-O3uz76R1.js +1 -0
  63. package/src/assets/web-panel/assets/{Providers-C-hmLXlO.js → Providers-CnRbjOYk.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-DzG_rbSL.js → QrScannerModal-BVFnIS3r.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-ShwiATg4.js → QuickAsk-DrcHx5f1.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-DkV8Ruep.js → Recommend-CbRgrSJm.js} +1 -1
  67. package/src/assets/web-panel/assets/{RemoteSession-Ca2dOx_G.js → RemoteSession-B2Uz_ElB.js} +2 -2
  68. package/src/assets/web-panel/assets/{Reputation-DYA5BJ6A.js → Reputation-DS0ljTxL.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-DvGDgxLS.js → Row-ClLobFht.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-DbwTBSPw.js → RssFeed-DxxcTD0x.js} +3 -3
  71. package/src/assets/web-panel/assets/{Search-C5XAMQ9T.js → Search-BbHN0Fik.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-CKWT60Qt.js → Security-BAVU_EcY.js} +3 -3
  73. package/src/assets/web-panel/assets/{Services-CZvASlWL.js → Services-CtqRSVq_.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-DFkMVqws.js → Skeleton-IJ8ZKdSZ.js} +1 -1
  75. package/src/assets/web-panel/assets/{Skills-hslZ_GyP.js → Skills-DXxcznnO.js} +1 -1
  76. package/src/assets/web-panel/assets/{Sla-BLW5rmZ5.js → Sla-fRkhnA3i.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-Cn4ffCi5.js → SpeechSettings-Bi8sYJ-I.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-D1K0nJuo.js → SyncSettings-CjeplUtS.js} +2 -2
  79. package/src/assets/web-panel/assets/{Tasks-CCRu0xoN.js → Tasks-D4KB2Hbx.js} +1 -1
  80. package/src/assets/web-panel/assets/{Templates-L19GYuS4.js → Templates-BwVugi8n.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-CZ6HE3PF.js → Tenant-CsPuu5xK.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-BiAwzaBT.js → Terminal-DuaeOPjY.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-DRHSWQT5.js → TimelineRenderer-D-PMrFxO.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-Cm-XATgh.js → Tokens-BXZuiQPZ.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-BVXtx3kn.js → Trigger-DgpTaHL3.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-Bb0TmkLJ.js → Trust-Bn7lEGRY.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-Dbt9R7l0.js → UkeySign-zz-8JAAQ.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-z0-Ti8eJ.js → VideoEditing-DCzfQGTc.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-BZh31tI-.js → Wallet-BiRHM_zB.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-DQ0yIr5K.js → WebAuthn-QmPo2JwU.js} +5 -5
  91. package/src/assets/web-panel/assets/{WorkflowEditor-DCt_yuWG.js → WorkflowEditor-gL7SsPnY.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-BLgtmFeS.js → chat-BysvK4hk.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-xU4UH8M1.js → colors-CQq20vqN.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-C4w4v16T.js → compact-item-CAHlOf1X.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-CZM9hAaj.js → createContext-BeF3ESj_.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-D-Iugqxv.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-DvHqEpE7.js → hasIn-CiqnRf-U.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BkTKWAgq.js → index-4a0Lmz_y.js} +1 -1
  99. package/src/assets/web-panel/assets/index-B0Oz2_rQ.js +1 -0
  100. package/src/assets/web-panel/assets/{index-B0IvKEVO.js → index-B2AOvjgR.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-BaQZvM4m.js → index-B2xbtl_c.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BRhD9RMV.js → index-B5941vyo.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-CqDiY-jl.js → index-BHpHGGmB.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CQEzxnYS.js → index-BOiyW31p.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BTxhDCtg.js → index-BcVmt6u_.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CPDw21XY.js → index-BfJabF_8.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CExiTobS.js → index-Br5tGVbC.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-QHmhwgfc.js → index-BsnLkZjz.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BlN5KPq6.js → index-BtWchYfW.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-SNV95Zen.js → index-Bvkbj3x-.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BHK3CQHq.js → index-CCX0daFQ.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CPC7OGCe.js → index-CImCEo8S.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CKugxsw3.js → index-CTp89vmg.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-55Rkd1KA.js → index-CcccefJc.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-Ds6wKTMh.js → index-CeIL3-nY.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DifMvnMQ.js → index-CgkUkmEJ.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Bf8Wm4ks.js → index-CowbNBJs.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Cm00787d.js → index-Cp3IRTDK.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-C9YnZFv2.js → index-D7q5VH2n.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BHg9NoJ5.js → index-DBmGQHEz.js} +3 -3
  121. package/src/assets/web-panel/assets/{index-B6AQ2b5U.js → index-DHGtFwwR.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CYrQnkqA.js → index-DKYbru3i.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CyV8fNBg.js → index-DTPUVm71.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-B4jIcYSv.js → index-DXT7MKkD.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-B64Vf-8H.js → index-DXsXhR7p.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CpiuuIww.js → index-Dqkls2_6.js} +1 -1
  127. package/src/assets/web-panel/assets/index-DwoycEQa.js +1 -0
  128. package/src/assets/web-panel/assets/{index-DGdLkss8.js → index-QALafVsT.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-Ds1tM734.js → index-TdVEaJfk.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Bh14b1k0.js → index-ZBuJ6O6g.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-C6ZrTSw5.js → index-i9aJV9qk.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-CF9ebAIB.js → index-jJhemX1R.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-BIWumeQl.js → index-qjaCk1Mj.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-n6SAUmmI.js → index-xwtRrgVY.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-CRLP56-W.js → index-yFQWSRoW.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-wYRjvvbl.js → index-zNkw0IY7.js} +1 -1
  137. package/src/assets/web-panel/assets/{initDefaultProps-C44ZER6c.js → initDefaultProps-BQR2HnKb.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-DbNzzScd.js → motion-gAz6l-nZ.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-BrRrDH2u.js → move-Cy5TN856.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-DZ_T_Pw8.js → mtc-parser-BeT7VrGi.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-5QHHk_V3.js → omit-BLN3mlgK.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-BdxEl0G2.js → pickAttrs-DtwZ8u2d.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-CGyD615D.js → placementArrow-ViMwQSa-.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-QqcWAQmN.js → responsiveObserve-dEL3u4E7.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-BumQrJ5R.js → slide-l05us-Gz.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-Pf64olM7.js → statusUtils-Bk-Qn2Og.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-DNwm5SQZ.js → styleChecker-Bn186qeY.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-c3gLKs6e.js → useFlexGapSupport-WP-ugR3H.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-TzTd6NDM.js → useFs-1SvoeSCL.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-BP5E_0Fe.js → usePersonalDataHub-CfNU8N3z.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-CVEkRfZU.js → vnode-Bd2Ya101.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-C18X_8TJ.js → zoom-Def_MeZv.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/command-help-index.json +2 -2
  155. package/src/commands/agent.js +20 -20
  156. package/src/commands/goal.js +299 -1
  157. package/src/commands/plugin.js +129 -68
  158. package/src/constants.js +2 -2
  159. package/src/data/changelog.json +26 -0
  160. package/src/lib/cli-goal-catalog.js +129 -0
  161. package/src/lib/cli-goal-source.js +119 -0
  162. package/src/lib/coding-task-guidance.js +3 -1
  163. package/src/lib/config-schema.js +1 -1
  164. package/src/lib/eval/stream-terminal.js +27 -2
  165. package/src/lib/evolution/evolution-artifact-ports.js +22 -11
  166. package/src/lib/evolution/evolution-file-witness.js +86 -63
  167. package/src/lib/evolution/evolution-ledger-file-backend.js +22 -0
  168. package/src/lib/evolution/evolution-ledger-file-manifest-catalog.js +34 -35
  169. package/src/lib/evolution/evolution-ledger-file-manifest-head-store.js +32 -39
  170. package/src/lib/evolution/evolution-ledger.js +367 -169
  171. package/src/lib/evolution/evolution-manifest-state-reader.js +58 -0
  172. package/src/lib/evolution/evolution-physical-state-reader.js +308 -0
  173. package/src/lib/evolution/evolution-witness-segments.js +12 -13
  174. package/src/lib/evolution/governed-wiki-pruning-ledger-adapter.js +82 -56
  175. package/src/lib/evolution/rrsi-observed-text-index.js +17 -1
  176. package/src/lib/evolution/rrsi-tenant-index-anchor-history.js +5 -0
  177. package/src/lib/execution-location-failure-site.js +20 -3
  178. package/src/lib/goal-store.js +8 -1
  179. package/src/lib/image-input.js +43 -14
  180. package/src/lib/llm-providers.js +1 -0
  181. package/src/lib/plugin-runtime/capabilities.js +10 -0
  182. package/src/lib/plugin-runtime/cli-goal-draft-request.js +138 -0
  183. package/src/lib/plugin-runtime/cli-goal-drafts.js +413 -0
  184. package/src/lib/plugin-runtime/cli-goal-extension-host.js +234 -0
  185. package/src/lib/plugin-runtime/examples/goal-description-drafter/plugin.json +17 -0
  186. package/src/lib/plugin-runtime/examples/goal-evidence-viewer/plugin.json +25 -0
  187. package/src/lib/plugin-runtime/examples/goal-progress-viewer/plugin.json +21 -0
  188. package/src/lib/plugin-runtime/examples/project-delivery-assistant/plugin.json +38 -0
  189. package/src/lib/plugin-runtime/goal-extension-contract.js +190 -0
  190. package/src/lib/plugin-runtime/goal-extensions.js +277 -0
  191. package/src/lib/plugin-runtime/install.js +40 -40
  192. package/src/lib/plugin-runtime/manifest.js +12 -0
  193. package/src/lib/plugin-runtime/policy.js +1 -0
  194. package/src/lib/project-goal-connection.js +225 -0
  195. package/src/lib/project-goal-draft-connection.js +217 -0
  196. package/src/lib/provider-http-error.js +4 -5
  197. package/src/lib/task-model-selector.js +1 -1
  198. package/src/repl/agent-repl.js +14 -7
  199. package/src/repl/config-summary.js +1 -1
  200. package/src/runtime/agent-core.js +1 -1
  201. package/src/runtime/coding-agent-contract-shared.cjs +3 -2
  202. package/src/runtime/headless-stream.js +4 -6
  203. package/src/runtime/policies/agent-policy.js +1 -0
  204. package/src/assets/web-panel/assets/MarkdownRenderer-BsSiyE-A.js +0 -1
  205. package/src/assets/web-panel/assets/MobileProjects-ClRlavdF.js +0 -1
  206. package/src/assets/web-panel/assets/Notes-4S6uts9Q.js +0 -7
  207. package/src/assets/web-panel/assets/OrderTableRenderer-CDVAlBUf.js +0 -1
  208. package/src/assets/web-panel/assets/Projects-BvP_Os-1.js +0 -1
  209. package/src/assets/web-panel/assets/devWarning-BZUZgMkO.js +0 -1
  210. package/src/assets/web-panel/assets/index--_-pNhk0.js +0 -1
  211. package/src/assets/web-panel/assets/index-ftwO31cp.js +0 -1
@@ -27,6 +27,7 @@
27
27
  import fs from "fs";
28
28
  import path from "path";
29
29
  import semver from "semver";
30
+ import { normalizeGoalExtension } from "./goal-extension-contract.js";
30
31
  import {
31
32
  normalizeCapabilities,
32
33
  normalizeOptionsSchema,
@@ -89,6 +90,8 @@ export function parsePluginManifest(root) {
89
90
  // actual audit) from a legacy one that declared nothing (unrestricted).
90
91
  capabilities: normalizeCapabilities(null),
91
92
  capabilitiesDeclared: false,
93
+ goalExtensionDeclared: false,
94
+ goalExtension: null,
92
95
  optionsSchema: {},
93
96
  errors,
94
97
  warnings,
@@ -219,6 +222,15 @@ export function parsePluginManifest(root) {
219
222
  result.capabilities = normalizeCapabilities(manifest.permissions);
220
223
  result.capabilitiesDeclared = Boolean(hasPermissions);
221
224
  result.optionsSchema = normalizeOptionsSchema(manifest.optionsSchema);
225
+ result.goalExtensionDeclared = Object.hasOwn(manifest, "goalExtension");
226
+ try {
227
+ result.goalExtension = normalizeGoalExtension(
228
+ manifest.goalExtension,
229
+ manifest.permissions,
230
+ );
231
+ } catch (err) {
232
+ errors.push(err.message);
233
+ }
222
234
  // Declared-vs-actual audit runs ONLY when a permissions block is present — a
223
235
  // legacy plugin that declares nothing is unrestricted by design, so it never
224
236
  // gets these warnings (keeps existing manifests warning-free).
@@ -45,6 +45,7 @@ export function loadManagedPluginPolicy(opts = {}) {
45
45
  const key = String(
46
46
  opts.managedSettingsFile || env.CC_MANAGED_SETTINGS || "<default>",
47
47
  );
48
+ if (opts.fresh === true) _cache.delete(key);
48
49
  if (_cache.has(key)) {
49
50
  const cached = _cache.get(key);
50
51
  // A cached failure sentinel must re-throw on EVERY call — otherwise the
@@ -0,0 +1,225 @@
1
+ /** Explicit short-lived desktop connection. No DB path or client-supplied actor. */
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import http from "node:http";
5
+ import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
6
+ import { inspectPrivatePath } from "@chainlesschain/session-core/private-storage";
7
+ import { goalExtensionRef } from "@chainlesschain/session-core/goal-extension-proposal-contract";
8
+ import { validateGoalEvidenceProjection } from "@chainlesschain/session-core/goal-evidence-contract";
9
+ import { validateGoalDraftDescriptor } from "@chainlesschain/session-core/goal-draft-connection-contract";
10
+ import { createProjectGoalDraftClient } from "./project-goal-draft-connection.js";
11
+ function fail() {
12
+ throw new Error("CLI_GOAL_CONNECTION_UNAVAILABLE");
13
+ }
14
+ const sameFile = (a, b) =>
15
+ a.dev === b.dev &&
16
+ a.ino === b.ino &&
17
+ a.size === b.size &&
18
+ a.mtimeMs === b.mtimeMs &&
19
+ a.ctimeMs === b.ctimeMs;
20
+ export function createProjectGoalConnection(file) {
21
+ let fd;
22
+ try {
23
+ if (
24
+ typeof file !== "string" ||
25
+ !file ||
26
+ file.length > 4096 ||
27
+ /[\u0000-\u001f]/u.test(file)
28
+ )
29
+ fail();
30
+ const target = path.resolve(file);
31
+ const before = fs.lstatSync(target);
32
+ if (
33
+ !before.isFile() ||
34
+ before.isSymbolicLink() ||
35
+ before.nlink !== 1 ||
36
+ before.size > 4096 ||
37
+ !inspectPrivatePath(target).ok
38
+ )
39
+ fail();
40
+ fd = fs.openSync(
41
+ target,
42
+ fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW || 0),
43
+ );
44
+ const opened = fs.fstatSync(fd);
45
+ if (!sameFile(before, opened)) fail();
46
+ const raw = Buffer.alloc(4097);
47
+ const count = fs.readSync(fd, raw, 0, raw.length, 0);
48
+ if (count > 4096 || !sameFile(opened, fs.fstatSync(fd))) fail();
49
+ const descriptor = JSON.parse(raw.subarray(0, count).toString("utf8"));
50
+ if (descriptor.schema === "chainlesschain.project-goal-connection/v3") {
51
+ const verified = validateGoalDraftDescriptor(descriptor);
52
+ return createProjectGoalDraftClient(verified, () => {
53
+ if (
54
+ Date.now() >= verified.expiresAt ||
55
+ !sameFile(opened, fs.lstatSync(target))
56
+ )
57
+ fail();
58
+ });
59
+ }
60
+ const evidence =
61
+ descriptor.schema === "chainlesschain.project-goal-connection/v2";
62
+ const endpointPath = evidence ? "/goal-evidence" : "/goal-summary";
63
+ if (
64
+ Object.keys(descriptor).sort().join() !==
65
+ (evidence
66
+ ? "capability,endpoint,expiresAt,goalRef,key,schema"
67
+ : "endpoint,expiresAt,goalRef,key,schema") ||
68
+ (evidence
69
+ ? descriptor.capability !== "goal.evidence"
70
+ : descriptor.schema !== "chainlesschain.project-goal-connection/v1") ||
71
+ typeof descriptor.endpoint !== "string" ||
72
+ !/^http:\/\/127\.0\.0\.1:[1-9][0-9]{0,4}\/goal-(?:summary|evidence)$/.test(
73
+ descriptor.endpoint,
74
+ ) ||
75
+ new URL(descriptor.endpoint).pathname !== endpointPath ||
76
+ Number(new URL(descriptor.endpoint).port) > 65535 ||
77
+ typeof descriptor.key !== "string" ||
78
+ !/^[a-f0-9]{64}$/.test(descriptor.key) ||
79
+ !Number.isSafeInteger(descriptor.expiresAt) ||
80
+ descriptor.expiresAt <= Date.now() ||
81
+ descriptor.expiresAt > Date.now() + 15 * 60 * 1000 + 5000
82
+ )
83
+ fail();
84
+ const ref = goalExtensionRef(descriptor.goalRef);
85
+ function validate() {
86
+ if (
87
+ Date.now() >= descriptor.expiresAt ||
88
+ !sameFile(opened, fs.lstatSync(target))
89
+ )
90
+ fail();
91
+ }
92
+ const mac = (value) =>
93
+ createHmac("sha256", Buffer.from(descriptor.key, "hex"))
94
+ .update(value)
95
+ .digest("hex");
96
+ async function read(id = ref.id) {
97
+ validate();
98
+ if (id !== ref.id) fail();
99
+ const nonce = randomBytes(32).toString("hex");
100
+ try {
101
+ const result = await new Promise((resolve, reject) => {
102
+ const request = http.get(
103
+ descriptor.endpoint,
104
+ {
105
+ agent: false,
106
+ maxHeaderSize: 4096,
107
+ headers: {
108
+ "X-CC-Nonce": nonce,
109
+ "X-CC-Signature": mac(
110
+ `request\nGET\n${endpointPath}\n${nonce}`,
111
+ ),
112
+ },
113
+ },
114
+ (response) => {
115
+ const chunks = [];
116
+ let bytes = 0;
117
+ response.on("error", reject);
118
+ response.on("data", (chunk) => {
119
+ bytes += chunk.length;
120
+ if (bytes > 16 * 1024) response.destroy(new Error("limit"));
121
+ else chunks.push(chunk);
122
+ });
123
+ response.on("end", () => {
124
+ const body = Buffer.concat(chunks).toString("utf8"),
125
+ signature = response.headers["x-cc-signature"];
126
+ if (
127
+ response.statusCode !== 200 ||
128
+ typeof signature !== "string" ||
129
+ !/^[a-f0-9]{64}$/.test(signature) ||
130
+ !timingSafeEqual(
131
+ Buffer.from(signature),
132
+ Buffer.from(mac(`response\n${nonce}\n${body}`)),
133
+ )
134
+ ) {
135
+ reject(new Error("signature"));
136
+ return;
137
+ }
138
+ try {
139
+ resolve(JSON.parse(body));
140
+ } catch {
141
+ reject(new Error("json"));
142
+ }
143
+ });
144
+ },
145
+ );
146
+ request.setTimeout(5000, () => request.destroy(new Error("timeout")));
147
+ const deadline = setTimeout(
148
+ () => request.destroy(new Error("timeout")),
149
+ 5000,
150
+ );
151
+ request.once("close", () => clearTimeout(deadline));
152
+ request.on("error", reject);
153
+ });
154
+ validate();
155
+ if (
156
+ Object.keys(result).sort().join() !==
157
+ (evidence
158
+ ? "goalRef,objective,receipts,risk,schema,status"
159
+ : "goalRef,objective,schema,status") ||
160
+ result.schema !==
161
+ (evidence
162
+ ? "chainlesschain.project-goal-evidence/v1"
163
+ : "chainlesschain.project-goal-summary/v1") ||
164
+ JSON.stringify(goalExtensionRef(result.goalRef)) !==
165
+ JSON.stringify(ref) ||
166
+ typeof result.objective !== "string" ||
167
+ result.objective.length > 4096 ||
168
+ result.status !== "active"
169
+ )
170
+ fail();
171
+ if (evidence)
172
+ validateGoalEvidenceProjection({
173
+ risk: result.risk,
174
+ receipts: result.receipts,
175
+ });
176
+ return { ...result, goalRef: ref };
177
+ } catch {
178
+ fail();
179
+ }
180
+ }
181
+ validate();
182
+ return Object.freeze({ goalRef: ref, evidence, read });
183
+ } catch {
184
+ fail();
185
+ } finally {
186
+ if (fd !== undefined) fs.closeSync(fd);
187
+ }
188
+ }
189
+
190
+ export async function readProjectGoalCatalog(options = {}) {
191
+ if (
192
+ options.after !== undefined ||
193
+ !Number.isSafeInteger(options.limit ?? 20) ||
194
+ (options.limit ?? 20) < 1 ||
195
+ (options.limit ?? 20) > 20
196
+ )
197
+ fail();
198
+ const source = createProjectGoalConnection(options.connection);
199
+ const goal = await source.read();
200
+ return {
201
+ schema: "chainlesschain.goal-catalog.v1",
202
+ source: "desktop-project",
203
+ snapshot: true,
204
+ storeId: source.goalRef.storeId,
205
+ observedAt: new Date().toISOString(),
206
+ entries: [
207
+ {
208
+ id: source.goalRef.id,
209
+ title: goal.objective
210
+ .replace(
211
+ /[\u0000-\u001f\u007f-\u009f\u200e\u200f\u202a-\u202e\u2066-\u2069]/gu,
212
+ " ",
213
+ )
214
+ .slice(0, 160),
215
+ status: goal.status,
216
+ revision: source.goalRef.revision,
217
+ controlGeneration: source.goalRef.controlGeneration,
218
+ },
219
+ ],
220
+ scannedCount: 1,
221
+ skippedCount: 0,
222
+ invalidNameCount: 0,
223
+ nextCursor: null,
224
+ };
225
+ }
@@ -0,0 +1,217 @@
1
+ import http from "node:http";
2
+ import {
3
+ createHash,
4
+ createHmac,
5
+ randomBytes,
6
+ timingSafeEqual,
7
+ } from "node:crypto";
8
+ import { digestBusinessObjectContent as digest } from "@chainlesschain/session-core/business-object-contract";
9
+ import {
10
+ validateGoalDraftSources,
11
+ validateGoalDraftReceipt,
12
+ validateGoalDraftProposal,
13
+ } from "@chainlesschain/session-core/goal-draft-connection-contract";
14
+ function unavailable() {
15
+ return new Error("CLI_GOAL_CONNECTION_UNAVAILABLE");
16
+ }
17
+ function exact(raw, keys) {
18
+ if (
19
+ !raw ||
20
+ typeof raw !== "object" ||
21
+ Array.isArray(raw) ||
22
+ Object.keys(raw).length !== keys.length ||
23
+ keys.some((key) => !Object.hasOwn(raw, key))
24
+ )
25
+ throw unavailable();
26
+ }
27
+ /** Constructed only after the shared private-file reader verifies the descriptor. */
28
+ export function createProjectGoalDraftClient(descriptor, validate) {
29
+ const ref = Object.freeze({ ...descriptor.goalRef }),
30
+ grant = Object.freeze({
31
+ id: descriptor.grantRef.id,
32
+ epoch: descriptor.grantRef.epoch,
33
+ plugin: Object.freeze({ ...descriptor.plugin }),
34
+ declarationDigest: descriptor.declarationDigest,
35
+ });
36
+ const mac = (text) =>
37
+ createHmac("sha256", Buffer.from(descriptor.key, "hex"))
38
+ .update(text)
39
+ .digest("hex");
40
+ async function exchange(method, payload, writing = false) {
41
+ validate();
42
+ const bytes =
43
+ payload === undefined
44
+ ? Buffer.alloc(0)
45
+ : Buffer.from(JSON.stringify(payload));
46
+ if (bytes.length > 16384) throw unavailable();
47
+ const nonce = randomBytes(32).toString("hex"),
48
+ bodyHash = createHash("sha256").update(bytes).digest("hex");
49
+ let sent = false;
50
+ try {
51
+ const result = await new Promise((resolve, reject) => {
52
+ const request = http.request(
53
+ descriptor.endpoint,
54
+ {
55
+ method,
56
+ agent: false,
57
+ maxHeaderSize: 4096,
58
+ headers: {
59
+ "X-CC-Nonce": nonce,
60
+ "X-CC-Signature": mac(
61
+ `request-v3\n${method}\n/goal-drafts\n${nonce}\n${bodyHash}`,
62
+ ),
63
+ ...(method === "POST"
64
+ ? {
65
+ "Content-Type": "application/json",
66
+ "Content-Length": bytes.length,
67
+ }
68
+ : {}),
69
+ },
70
+ },
71
+ (response) => {
72
+ const chunks = [];
73
+ let size = 0;
74
+ response.on("error", reject);
75
+ response.on("data", (chunk) => {
76
+ size += chunk.length;
77
+ if (size > 16384) response.destroy(unavailable());
78
+ else chunks.push(chunk);
79
+ });
80
+ response.on("end", () => {
81
+ try {
82
+ const text = new TextDecoder("utf-8", { fatal: true }).decode(
83
+ Buffer.concat(chunks),
84
+ ),
85
+ signature = response.headers["x-cc-signature"];
86
+ if (
87
+ typeof signature !== "string" ||
88
+ !/^[a-f0-9]{64}$/u.test(signature) ||
89
+ !timingSafeEqual(
90
+ Buffer.from(signature),
91
+ Buffer.from(
92
+ mac(
93
+ `response-v3\n${nonce}\n${response.statusCode}\n${text}`,
94
+ ),
95
+ ),
96
+ )
97
+ )
98
+ throw unavailable();
99
+ if (response.statusCode !== 200) throw unavailable();
100
+ resolve(JSON.parse(text));
101
+ } catch (error) {
102
+ reject(error);
103
+ }
104
+ });
105
+ },
106
+ );
107
+ const timer = setTimeout(() => request.destroy(unavailable()), 5000);
108
+ request.once("close", () => clearTimeout(timer));
109
+ request.on("error", reject);
110
+ request.setTimeout(5000, () => request.destroy(unavailable()));
111
+ sent = writing;
112
+ request.end(bytes);
113
+ });
114
+ validate();
115
+ if (digest(result.goalRef) !== digest(ref)) throw unavailable();
116
+ return result;
117
+ } catch {
118
+ const error = unavailable();
119
+ if (sent) {
120
+ error.code = "CLI_GOAL_DRAFT_OUTCOME_UNKNOWN";
121
+ error.outcomeUnknown = true;
122
+ }
123
+ throw error;
124
+ }
125
+ }
126
+ async function read(id = ref.id) {
127
+ if (id !== ref.id) throw unavailable();
128
+ const result = await exchange("GET");
129
+ exact(result, [
130
+ "schema",
131
+ "goalRef",
132
+ "objective",
133
+ "status",
134
+ "grant",
135
+ "sources",
136
+ ]);
137
+ if (
138
+ result.schema !== "chainlesschain.project-goal-drafts/v1" ||
139
+ typeof result.objective !== "string" ||
140
+ result.objective.length > 4096 ||
141
+ result.status !== "active" ||
142
+ digest(result.grant) !== digest(grant)
143
+ )
144
+ throw unavailable();
145
+ validateGoalDraftSources(result.sources);
146
+ return { ...result, goalRef: ref };
147
+ }
148
+ async function sources(afterId) {
149
+ const result = await exchange("POST", {
150
+ operation: "sources",
151
+ ...(afterId !== undefined ? { afterId } : {}),
152
+ });
153
+ exact(result, ["schema", "goalRef", "sources"]);
154
+ if (result.schema !== "chainlesschain.goal-draft-sources/v1")
155
+ throw unavailable();
156
+ return validateGoalDraftSources(result.sources);
157
+ }
158
+ async function receipt({ requestId, inputDigest }) {
159
+ const result = await exchange("POST", {
160
+ operation: "receipt",
161
+ requestId,
162
+ inputDigest,
163
+ });
164
+ exact(result, ["schema", "goalRef", "receipt"]);
165
+ if (result.schema !== "chainlesschain.goal-draft-receipt/v1")
166
+ throw unavailable();
167
+ const value = validateGoalDraftReceipt(result.receipt);
168
+ if (value.requestId !== requestId || value.inputDigest !== inputDigest)
169
+ throw unavailable();
170
+ return value;
171
+ }
172
+ async function enqueue(raw) {
173
+ const proposal = validateGoalDraftProposal(raw),
174
+ inputDigest = digest(proposal);
175
+ let received = false;
176
+ try {
177
+ const result = await exchange(
178
+ "POST",
179
+ { operation: "enqueue", proposal },
180
+ true,
181
+ );
182
+ received = true;
183
+ exact(result, ["schema", "goalRef", "receipt"]);
184
+ if (result.schema !== "chainlesschain.goal-draft-submit/v1")
185
+ throw unavailable();
186
+ const value = validateGoalDraftReceipt(result.receipt);
187
+ if (
188
+ value.state !== "saved" ||
189
+ value.requestId !== proposal.requestId ||
190
+ value.inputDigest !== inputDigest
191
+ )
192
+ throw unavailable();
193
+ return value;
194
+ } catch (error) {
195
+ // Once HTTP may have dispatched, an invalid/absent response is not proof
196
+ // that no native draft was saved. Preserve this exact request identity.
197
+ if (received || error.outcomeUnknown) {
198
+ error.code = "CLI_GOAL_DRAFT_OUTCOME_UNKNOWN";
199
+ error.outcomeUnknown = true;
200
+ }
201
+ throw error;
202
+ }
203
+ }
204
+ validate();
205
+ return Object.freeze({
206
+ goalRef: ref,
207
+ evidence: false,
208
+ drafts: true,
209
+ plugin: grant.plugin,
210
+ declarationDigest: grant.declarationDigest,
211
+ grantRef: Object.freeze({ ...descriptor.grantRef }),
212
+ read,
213
+ sources,
214
+ enqueue,
215
+ receipt,
216
+ });
217
+ }
@@ -84,11 +84,10 @@ export function formatProviderHttpError(
84
84
  );
85
85
  }
86
86
  if (status === 403) {
87
- return (
88
- `${base} — access forbidden` +
89
- (detailSentence ? `: ${detailSentence}` : "") +
90
- ". Check the API key, model access permissions, and account status/balance."
91
- );
87
+ // Gateways can use 403 for request/output policy failures. An explicit
88
+ // reason without auth/billing evidence must not imply a credential fix.
89
+ if (detailSentence) return `${base} — ${detailSentence}.`;
90
+ return `${base} — access forbidden. Check the API key, model access permissions, and account status/balance.`;
92
91
  }
93
92
  if (status === 429) return `${base} — rate limited; please retry shortly.`;
94
93
  return detailSentence ? `${base} — ${detailSentence}` : base;
@@ -24,7 +24,7 @@ export const TaskType = {
24
24
  */
25
25
  const TASK_MODEL_MAP = {
26
26
  [TaskType.CHAT]: {
27
- volcengine: "deepseek-v4-flash-ga-260731",
27
+ volcengine: "deepseek-v4-1-flash-260910",
28
28
  openai: "gpt-4o-mini",
29
29
  anthropic: "claude-sonnet-4-6",
30
30
  deepseek: "deepseek-chat",
@@ -9504,12 +9504,18 @@ async function startAgentReplInWorkspaceOwned(
9504
9504
  let _userMessageContent = userContent;
9505
9505
  if (process.env.CC_AUTO_IMAGE !== "0") {
9506
9506
  try {
9507
- const turn = prepareVisionTurn(userContent, {
9508
- provider,
9509
- baseUrl,
9510
- apiKey,
9511
- visionModel: _visionModel,
9512
- });
9507
+ const turn = prepareVisionTurn(
9508
+ userContent,
9509
+ {
9510
+ provider,
9511
+ model,
9512
+ baseUrl,
9513
+ apiKey,
9514
+ visionModel: _visionModel,
9515
+ },
9516
+ {},
9517
+ { visionModel: options.visionModel },
9518
+ );
9513
9519
  if (turn.visionLlm) {
9514
9520
  _userMessageContent = turn.content;
9515
9521
  _visionLlm = turn.visionLlm;
@@ -9549,9 +9555,10 @@ async function startAgentReplInWorkspaceOwned(
9549
9555
  if (!_visionLlm) {
9550
9556
  _visionLlm = resolveVisionLlm({
9551
9557
  hasImage: true,
9552
- flags: {},
9558
+ flags: { visionModel: options.visionModel },
9553
9559
  llm: {
9554
9560
  provider,
9561
+ model,
9555
9562
  baseUrl,
9556
9563
  apiKey,
9557
9564
  visionModel: _visionModel,
@@ -34,7 +34,7 @@ export function parseConfigCommand(argStr) {
34
34
  export const COMMON_CONFIG_KEYS = Object.freeze([
35
35
  ["llm.provider", "LLM provider id"],
36
36
  ["llm.model", "default text model id"],
37
- ["llm.visionModel", "model used for image turns"],
37
+ ["llm.visionModel", "image fallback for a main model without vision"],
38
38
  ["llm.baseUrl", "provider API base URL"],
39
39
  ["llm.apiKey", "provider API key (use cc config set-secret)"],
40
40
  ["webSearch.provider", "web-search backend"],
@@ -12412,7 +12412,7 @@ export async function chatWithTools(rawMessages, options) {
12412
12412
  dashscope: "qwen-turbo",
12413
12413
  mistral: "mistral-large-latest",
12414
12414
  gemini: "gemini-2.0-flash",
12415
- volcengine: "deepseek-v4-flash-ga-260731",
12415
+ volcengine: "deepseek-v4-1-flash-260910",
12416
12416
  };
12417
12417
  const effectiveModel = model || defaultModels[provider] || "gpt-4o-mini";
12418
12418
  const modelProfile = resolveModelCapabilityProfile({
@@ -77,7 +77,8 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
77
77
  title: "Write File",
78
78
  kind: "filesystem",
79
79
  tier: "mvp",
80
- description: "Write content to a file (create or overwrite)",
80
+ description:
81
+ "Write content to a file (create or overwrite). For a large new file, write a small complete section first, then extend it with edit_file using a unique existing anchor. Aim for a few thousand characters of new content per call and wait for the result before continuing; each write_file call replaces the whole file.",
81
82
  inputSchema: {
82
83
  type: "object",
83
84
  properties: {
@@ -200,7 +201,7 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
200
201
  kind: "filesystem",
201
202
  tier: "mvp",
202
203
  description:
203
- "Replace a string in a file. old_string must match EXACTLY ONE place — include enough surrounding context to make it unique, or the edit is rejected. Pass replace_all:true to change every occurrence instead.",
204
+ "Replace a string in a file. old_string must match EXACTLY ONE place — include enough surrounding context to make it unique, or the edit is rejected. To extend a file in small complete sections, use a unique existing anchor as old_string and retain that anchor plus the new section in new_string; do not resend the whole growing file. Wait for each edit result before continuing. Pass replace_all:true to change every occurrence instead.",
204
205
  inputSchema: {
205
206
  type: "object",
206
207
  properties: {
@@ -2079,10 +2079,8 @@ async function runAgentHeadlessStreamInWorkspace(
2079
2079
  return { exitCode: 1, turns: 0 };
2080
2080
  }
2081
2081
  }
2082
- // Vision model (config.llm.visionModel) — image turns switch to it for that
2083
- // turn only (resolveVisionLlm falls back to the default when unset), so a
2084
- // pasted/typed image is read by a vision-capable model even though the
2085
- // session's default model is text-only.
2082
+ // Vision fallback for a text-only main model. Multimodal main models keep
2083
+ // handling both image turns and follow-ups themselves.
2086
2084
  let visionModel = options.visionModel;
2087
2085
  if (!visionModel) {
2088
2086
  try {
@@ -5313,8 +5311,8 @@ async function runAgentHeadlessStreamInWorkspace(
5313
5311
  if (conversationHasImages) {
5314
5312
  turnVisionLlm = resolveVisionLlm({
5315
5313
  hasImage: true,
5316
- flags: {},
5317
- llm: { provider, baseUrl, apiKey, visionModel },
5314
+ flags: { visionModel: options.visionModel },
5315
+ llm: { provider, model, baseUrl, apiKey, visionModel },
5318
5316
  });
5319
5317
  if (parsed.images && parsed.images.length) {
5320
5318
  writeErr(
@@ -10,6 +10,7 @@ export function resolveAgentPolicy({
10
10
 
11
11
  return {
12
12
  model: overrides.model || llm.model || defaults.model || "qwen2:7b",
13
+ visionModel: overrides.visionModel,
13
14
  provider:
14
15
  overrides.provider || llm.provider || defaults.provider || "ollama",
15
16
  baseUrl:
@@ -1 +0,0 @@
1
- import{P as a,J as p,b as c}from"./vendor-Bn1JzzAn.js";import{r as s}from"./markdown-Yo_c6Krv.js";import{_ as d}from"./index-BHg9NoJ5.js";const _={__name:"MarkdownRenderer",props:{content:{type:String,default:""}},setup(t,{expose:o}){o();const e=t,r=c(()=>s(e.content||"")),n={props:e,rendered:r,computed:c,get renderMarkdown(){return s}};return Object.defineProperty(n,"__isScriptSetup",{enumerable:!1,value:!0}),n}},i=["innerHTML"];function m(t,o,e,r,n,u){return a(),p("div",{class:"markdown-content",innerHTML:r.rendered},null,8,i)}const w=d(_,[["render",m],["__scopeId","data-v-0b0b9f63"],["__file","/tmp/cc-web-panel-OeGoRc/repo/packages/web-panel/src/components/MarkdownRenderer.vue"]]);export{w as M};
@@ -1 +0,0 @@
1
- import{I as c,J as g,c as l,K as r,N as u,P as h,U as o,R as t,Q as b}from"./vendor-Bn1JzzAn.js";import{_ as v,b as m}from"./index-BHg9NoJ5.js";import{a8 as y,M}from"./icons-DG5UD-6K.js";const B={__name:"MobileProjects",setup(p,{expose:i}){i();const n=u(),{t:e}=m();function a(){n.push("/projects")}function _(){n.push("/mobile-bridge")}const s={router:n,t:e,goToProjects:a,goToMobileBridge:_,get useRouter(){return u},get useI18n(){return m},get MobileOutlined(){return M},get FolderOutlined(){return y}};return Object.defineProperty(s,"__isScriptSetup",{enumerable:!1,value:!0}),s}},O={class:"mobile-projects-placeholder"},x={class:"title"},k={class:"subtitle"},w={class:"explainer"};function T(p,i,n,e,a,_){const s=c("a-alert"),d=c("a-button"),f=c("a-space"),P=c("a-empty"),j=c("a-card");return h(),g("div",O,[l(j,null,{default:r(()=>[l(P,{description:!1},{image:r(()=>[l(e.MobileOutlined,{style:{fontSize:"64px",color:"#bfbfbf"}})]),default:r(()=>[o("h2",x,t(e.t("mobileProjects.title")),1),o("p",k,t(e.t("mobileProjects.subtitle")),1),l(s,{message:e.t("mobileProjects.v02Banner"),type:"info","show-icon":"",class:"banner"},null,8,["message"]),o("div",w,[o("h3",null,t(e.t("mobileProjects.currentDirection")),1),o("p",null,t(e.t("mobileProjects.currentDirectionBody")),1),o("ul",null,[o("li",null,t(e.t("mobileProjects.stepPhone")),1),o("li",null,t(e.t("mobileProjects.stepTap")),1),o("li",null,t(e.t("mobileProjects.stepPull")),1)]),o("h3",null,t(e.t("mobileProjects.reverseDirection")),1),o("p",null,t(e.t("mobileProjects.reverseDirectionBody")),1)]),l(f,{class:"actions"},{default:r(()=>[l(d,{type:"primary",onClick:e.goToProjects},{default:r(()=>[l(e.FolderOutlined),b(" "+t(e.t("mobileProjects.viewLocalProjects")),1)]),_:1}),l(d,{onClick:e.goToMobileBridge},{default:r(()=>[l(e.MobileOutlined),b(" "+t(e.t("mobileProjects.checkBridge")),1)]),_:1})]),_:1})]),_:1})]),_:1})])}const N=v(B,[["render",T],["__scopeId","data-v-9262cc45"],["__file","/tmp/cc-web-panel-OeGoRc/repo/packages/web-panel/src/views/MobileProjects.vue"]]);export{N as default};