chainlesschain 0.157.9 → 0.159.0

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 (184) hide show
  1. package/bin/chainlesschain.js +0 -0
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-C4XQxptM.js → AIOps-ztGJppiG.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-CvKbykKA.js → ActionButton-DCuat-R-.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-DFMAWKUR.js → Analytics-m_EtU-RR.js} +2 -2
  7. package/src/assets/web-panel/assets/AppLayout-8HizVjee.css +1 -0
  8. package/src/assets/web-panel/assets/AppLayout-Crz8jbEC.js +1 -0
  9. package/src/assets/web-panel/assets/Audit-CNLWjMXN.js +1 -0
  10. package/src/assets/web-panel/assets/Audit-kU7vbN-D.css +1 -0
  11. package/src/assets/web-panel/assets/Backup-CggaSq9O.js +1 -0
  12. package/src/assets/web-panel/assets/Backup-DxLiJzmk.css +1 -0
  13. package/src/assets/web-panel/assets/{BaseInput-CvAa9Hm_.js → BaseInput-BssiYvl6.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-3Kj2JQP4.js → Chat-tuVfpQUO.js} +1 -1
  15. package/src/assets/web-panel/assets/{Checkbox-YsCNWg9S.js → Checkbox-BUUkXdQg.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-DDiVk21N.js → Codegen-CHu-7YGr.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-Dpb7Eik4.js → Col-2IaMFwmX.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-Bglv8oIv.js → Community-CYL7Fvjq.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-DC8UsEAe.js → Compact-5yRVELhA.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-DzVghx7L.js → Compliance-CKuIDJHK.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-pgKzBNDo.js → Cowork-CFkkMMDK.js} +4 -4
  22. package/src/assets/web-panel/assets/{Cron-I81HiCa1.js → Cron-DIfkI7vf.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-48CdkgQf.js → Crosschain-BkjY-lst.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-CVYxjLQn.js → DID-ChzRkgNy.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-sqj42zKx.js → Dashboard-DKrbXVNn.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-DBfZJHBI.js → Dropdown-BYGoxH1z.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-BT-pF1wN.js → Federation-B8QX-IaA.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-B-sn9E_W.js → FormItemContext-Be6TSNxz.js} +1 -1
  29. package/src/assets/web-panel/assets/{Git-DTh2i-Qk.js → Git-BBnGgbBR.js} +2 -2
  30. package/src/assets/web-panel/assets/{Governance-D788Lws6.js → Governance-CxUHZMsp.js} +1 -1
  31. package/src/assets/web-panel/assets/{Inference-CnFa6Se9.js → Inference-BlnOG71q.js} +1 -1
  32. package/src/assets/web-panel/assets/{KnowledgeGraph-DHaMxawn.js → KnowledgeGraph-vkVq38kC.js} +1 -1
  33. package/src/assets/web-panel/assets/{Logs-B39LUZs9.js → Logs-Bxx7WARH.js} +2 -2
  34. package/src/assets/web-panel/assets/{Marketplace-BdOCF2RA.js → Marketplace-Bh8ExT9_.js} +1 -1
  35. package/src/assets/web-panel/assets/McpTools-CTQrNVAQ.css +1 -0
  36. package/src/assets/web-panel/assets/McpTools-Djj_a3ko.js +5 -0
  37. package/src/assets/web-panel/assets/{Memory-Vl_lYCs2.js → Memory-DlgNgAov.js} +2 -2
  38. package/src/assets/web-panel/assets/NLProgramming-BN3jaoen.js +1 -0
  39. package/src/assets/web-panel/assets/Notes-DKkPfXlY.css +1 -0
  40. package/src/assets/web-panel/assets/Notes-De7mIkkV.js +7 -0
  41. package/src/assets/web-panel/assets/{Organization-Cxhhw4aD.js → Organization-B-98mdK2.js} +4 -4
  42. package/src/assets/web-panel/assets/{Overflow-L_28D41_.js → Overflow-G0I8IlY3.js} +1 -1
  43. package/src/assets/web-panel/assets/{OverrideContext-DEW2m7K6.js → OverrideContext-GHsJf9ok.js} +1 -1
  44. package/src/assets/web-panel/assets/{P2P-BflX74Hm.js → P2P-DIUgHZ1z.js} +2 -2
  45. package/src/assets/web-panel/assets/{Permissions-ByLhEAbz.js → Permissions-B8XycCVk.js} +4 -4
  46. package/src/assets/web-panel/assets/{Pipeline-CnZJNdgt.js → Pipeline-cUpETlXS.js} +1 -1
  47. package/src/assets/web-panel/assets/Portal-SsPhn64D.js +1 -0
  48. package/src/assets/web-panel/assets/Privacy-B6J89UBw.js +1 -0
  49. package/src/assets/web-panel/assets/{ProjectSettings-N0r_mtec.js → ProjectSettings-2Ftw0zt_.js} +2 -2
  50. package/src/assets/web-panel/assets/{Projects-DLvUzeIB.js → Projects-CcOdFpgr.js} +2 -2
  51. package/src/assets/web-panel/assets/{Providers-B2A35VhD.js → Providers-D0r2qSf-.js} +2 -2
  52. package/src/assets/web-panel/assets/QuickAsk-CwsPpfkq.js +1 -0
  53. package/src/assets/web-panel/assets/{Recommend-DYb61WNp.js → Recommend-BYEDetJm.js} +1 -1
  54. package/src/assets/web-panel/assets/{Reputation-C9BfnI0z.js → Reputation-Bli4hBGH.js} +1 -1
  55. package/src/assets/web-panel/assets/{Row-CpPHVi7H.js → Row-DTW9_BYi.js} +1 -1
  56. package/src/assets/web-panel/assets/{RssFeed-CbqJDErh.js → RssFeed-kwj_himl.js} +3 -3
  57. package/src/assets/web-panel/assets/{Search-C0gd765-.js → Search-DymcqASO.js} +1 -1
  58. package/src/assets/web-panel/assets/{Security-DsYWAhpE.js → Security-Bh3yvyNN.js} +3 -3
  59. package/src/assets/web-panel/assets/{Services-7Blny0Jc.js → Services-O4UZaYur.js} +2 -2
  60. package/src/assets/web-panel/assets/{Skeleton-TzxE-JJt.js → Skeleton-B82oQZTz.js} +1 -1
  61. package/src/assets/web-panel/assets/Skills-BfkrC05g.js +1 -0
  62. package/src/assets/web-panel/assets/{Sla-mftEtvGn.js → Sla-DEs5XCIf.js} +1 -1
  63. package/src/assets/web-panel/assets/SpeechSettings-BWMhb10j.js +1 -0
  64. package/src/assets/web-panel/assets/SpeechSettings-CiKvsIyV.css +1 -0
  65. package/src/assets/web-panel/assets/{Tasks-Db9TRjE7.js → Tasks-CIBUb9M1.js} +1 -1
  66. package/src/assets/web-panel/assets/Templates-DAkzr0xS.css +1 -0
  67. package/src/assets/web-panel/assets/Templates-iqSuJY-O.js +1 -0
  68. package/src/assets/web-panel/assets/{Tenant-BB-LLJMZ.js → Tenant-CLqZjkVq.js} +1 -1
  69. package/src/assets/web-panel/assets/{Tokens-DHOkHNur.js → Tokens-Bwz8aQtK.js} +1 -1
  70. package/src/assets/web-panel/assets/Trigger-CxnChVoS.js +1 -0
  71. package/src/assets/web-panel/assets/{Trust-BpC4gDis.js → Trust-Bp23lyZl.js} +1 -1
  72. package/src/assets/web-panel/assets/UkeySign-_VAMquoh.js +1 -0
  73. package/src/assets/web-panel/assets/{VideoEditing-CeDFfKrq.js → VideoEditing-Bxqwg4zW.js} +1 -1
  74. package/src/assets/web-panel/assets/{Wallet-CcNCVaor.js → Wallet-Cvht6Yrh.js} +4 -4
  75. package/src/assets/web-panel/assets/{WebAuthn-BbIPA6Ca.js → WebAuthn-DD4EomJu.js} +4 -4
  76. package/src/assets/web-panel/assets/WorkflowEditor-CEKNTS5G.css +1 -0
  77. package/src/assets/web-panel/assets/WorkflowEditor-CJy5e0fl.js +1 -0
  78. package/src/assets/web-panel/assets/{chat-CVn-r3oV.js → chat-DY27mJje.js} +1 -1
  79. package/src/assets/web-panel/assets/{collapseMotion-D3P4mRvK.js → collapseMotion-CyadT_6x.js} +1 -1
  80. package/src/assets/web-panel/assets/{colors-2MPUdPu2.js → colors-B7fDvuJc.js} +1 -1
  81. package/src/assets/web-panel/assets/{compact-item-B4vcKR0x.js → compact-item-DgthOVXi.js} +1 -1
  82. package/src/assets/web-panel/assets/{createContext-Div8Cl0F.js → createContext-Blw2vgkG.js} +1 -1
  83. package/src/assets/web-panel/assets/{hasIn-9c9xldOR.js → hasIn-BfL1HJZl.js} +1 -1
  84. package/src/assets/web-panel/assets/{icons-ukMaZ3tx.js → icons-CJACPYXu.js} +4 -4
  85. package/src/assets/web-panel/assets/{index-D1JeOKve.js → index-00RNC3ZQ.js} +2 -2
  86. package/src/assets/web-panel/assets/{index-DJAPu9VF.js → index-B9B9Zbf3.js} +1 -1
  87. package/src/assets/web-panel/assets/index-BAsMNMbh.js +1 -0
  88. package/src/assets/web-panel/assets/{index-BbqCdQXU.js → index-BB5y5Y0z.js} +3 -3
  89. package/src/assets/web-panel/assets/{index-CtM3tjRj.js → index-BHnaIQEm.js} +1 -1
  90. package/src/assets/web-panel/assets/index-BVjDIZQ4.js +1 -0
  91. package/src/assets/web-panel/assets/index-BZeRnzuY.js +55 -0
  92. package/src/assets/web-panel/assets/{index-OhUZFfxQ.js → index-BZfoAtZC.js} +1 -1
  93. package/src/assets/web-panel/assets/index-Bl2nXm2J.js +13 -0
  94. package/src/assets/web-panel/assets/{index-COJ-mQYg.js → index-BsleJWGy.js} +2 -2
  95. package/src/assets/web-panel/assets/{index-BuVNDnn8.js → index-BuEOhTAw.js} +5 -5
  96. package/src/assets/web-panel/assets/{index-BfoYep3e.js → index-Bw1dwHWm.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BCfVA9mJ.js → index-Bw_UV2ez.js} +1 -1
  98. package/src/assets/web-panel/assets/index-C8GYpC65.js +1 -0
  99. package/src/assets/web-panel/assets/{index-CVYrm1az.js → index-CBHlKa-J.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-IzAqu_OK.js → index-CL-7KCFI.js} +2 -2
  101. package/src/assets/web-panel/assets/{index-BntG0RJO.js → index-CiN4NEAa.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-B4hcllQg.js → index-CqjUUbil.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-D-0g6tCK.js → index-Cqtt1N0F.js} +1 -1
  104. package/src/assets/web-panel/assets/index-D1QP9Ue1.js +1 -0
  105. package/src/assets/web-panel/assets/index-D6BUjL6I.js +1 -0
  106. package/src/assets/web-panel/assets/{index-C1GXp5YD.js → index-DN7ywgBJ.js} +1 -1
  107. package/src/assets/web-panel/assets/index-DasW8LIs.js +1 -0
  108. package/src/assets/web-panel/assets/{index-C-CTCrAH.js → index-Dd9McFt_.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-COdKVelL.js → index-DdzLEdL6.js} +1 -1
  110. package/src/assets/web-panel/assets/index-DhML6F3z.js +1 -0
  111. package/src/assets/web-panel/assets/{index-DogHNcyC.js → index-DjN0nHiV.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-ZW72ov7W.js → index-DjhWpiZW.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-B65KFSc3.js → index-DouFuKIR.js} +1 -1
  114. package/src/assets/web-panel/assets/{index--tOLU2ID.js → index-DyRzaN4b.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-B58J4NxK.js → index-DzWwjWYN.js} +1 -1
  116. package/src/assets/web-panel/assets/index-Dza_w3kG.js +1 -0
  117. package/src/assets/web-panel/assets/{index-dV8k_pMc.js → index-Q4qgOtOe.js} +1 -1
  118. package/src/assets/web-panel/assets/index-Vit9TJBu.js +36 -0
  119. package/src/assets/web-panel/assets/{index-3KbT-bG7.js → index-lkJllVbJ.js} +3 -3
  120. package/src/assets/web-panel/assets/{index-Ca3iTiXs.js → index-uMWaXVtR.js} +2 -2
  121. package/src/assets/web-panel/assets/{index-BjGOthNv.js → index-uwh_ikIt.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-D0GALIQZ.js → index-x8iHfZRd.js} +3 -3
  123. package/src/assets/web-panel/assets/{initDefaultProps--L8bzddm.js → initDefaultProps-BeWIEzBr.js} +1 -1
  124. package/src/assets/web-panel/assets/{motion-BR7NF0vx.js → motion-CIQOKmi6.js} +3 -3
  125. package/src/assets/web-panel/assets/{move-BpyQMRtF.js → move-ZgRPlBji.js} +1 -1
  126. package/src/assets/web-panel/assets/{omit-RkKN6uqw.js → omit-BS0H_YEP.js} +1 -1
  127. package/src/assets/web-panel/assets/{pickAttrs-Bk8_mKGY.js → pickAttrs-BOGgGau8.js} +1 -1
  128. package/src/assets/web-panel/assets/{placementArrow-CBAaXBxj.js → placementArrow--c5TQkDQ.js} +1 -1
  129. package/src/assets/web-panel/assets/{responsiveObserve-BzrPInK7.js → responsiveObserve-CrHOX7jp.js} +1 -1
  130. package/src/assets/web-panel/assets/{slide-CXFBsLyp.js → slide-Dd2mJUD0.js} +1 -1
  131. package/src/assets/web-panel/assets/{statusUtils-6TeOuUzQ.js → statusUtils-5QFvAofV.js} +1 -1
  132. package/src/assets/web-panel/assets/{styleChecker-CQt4HHRm.js → styleChecker-CiDrXnbi.js} +1 -1
  133. package/src/assets/web-panel/assets/{transition-CGYDOK3N.js → transition-CVd2ueaJ.js} +1 -1
  134. package/src/assets/web-panel/assets/{useConfigInject-BKqJUQaF.js → useConfigInject-DIkkDpt1.js} +2 -2
  135. package/src/assets/web-panel/assets/useFlexGapSupport-rrtj6f1h.js +1 -0
  136. package/src/assets/web-panel/assets/useFs-CK8VYPus.js +1 -0
  137. package/src/assets/web-panel/assets/{useMergedState-DbHXwBgv.js → useMergedState-CLY-UHry.js} +1 -1
  138. package/src/assets/web-panel/assets/{useRefs-DRyTVik7.js → useRefs-HzOoMkZk.js} +1 -1
  139. package/src/assets/web-panel/assets/useShellMode-CgR0wCYM.js +1 -0
  140. package/src/assets/web-panel/assets/{useState-DoAhV80c.js → useState-yWVBuz1S.js} +1 -1
  141. package/src/assets/web-panel/assets/{vendor-BVetwVfk.js → vendor-D0Qjn73K.js} +1 -1
  142. package/src/assets/web-panel/assets/vnode-xRp-KMjS.js +1 -0
  143. package/src/assets/web-panel/assets/ws-4ur1fGsk.js +1 -0
  144. package/src/assets/web-panel/assets/{zoom-BNV3xYvt.js → zoom-CrI_kdTW.js} +1 -1
  145. package/src/assets/web-panel/index.html +3 -3
  146. package/src/commands/nlprog.js +25 -15
  147. package/src/gateways/ws/ws-server.js +12 -1
  148. package/src/gateways/ws/ws-session-gateway.js +12 -1
  149. package/src/lib/listen-with-port-fallback.js +103 -0
  150. package/src/lib/web-ui-server.js +33 -0
  151. package/src/runtime/agent-runtime.js +80 -18
  152. package/src/assets/web-panel/assets/AppLayout-BkNdtTbn.js +0 -1
  153. package/src/assets/web-panel/assets/AppLayout-CKMl4NLf.css +0 -1
  154. package/src/assets/web-panel/assets/Audit-Bw7KSJD_.js +0 -1
  155. package/src/assets/web-panel/assets/Audit-L4_ApS01.css +0 -1
  156. package/src/assets/web-panel/assets/Backup-D46qSgzQ.js +0 -1
  157. package/src/assets/web-panel/assets/Backup-fZqtfC1m.css +0 -1
  158. package/src/assets/web-panel/assets/McpTools-CyhSLDwf.css +0 -1
  159. package/src/assets/web-panel/assets/McpTools-DbwkdBUE.js +0 -4
  160. package/src/assets/web-panel/assets/NLProgramming-CgD2H0Pc.js +0 -1
  161. package/src/assets/web-panel/assets/Notes-BG69sJKi.css +0 -1
  162. package/src/assets/web-panel/assets/Notes-BvC5_V2H.js +0 -2
  163. package/src/assets/web-panel/assets/Portal-CHsntPCQ.js +0 -1
  164. package/src/assets/web-panel/assets/Privacy-BJIajCGG.js +0 -1
  165. package/src/assets/web-panel/assets/Skills-DfaRaffm.js +0 -1
  166. package/src/assets/web-panel/assets/Templates-DOY_oZnm.css +0 -1
  167. package/src/assets/web-panel/assets/Templates-DgonVRQJ.js +0 -1
  168. package/src/assets/web-panel/assets/Trigger-BV4JPD3z.js +0 -1
  169. package/src/assets/web-panel/assets/WorkflowEditor-D5bX6woe.css +0 -1
  170. package/src/assets/web-panel/assets/WorkflowEditor-DxkitXpf.js +0 -1
  171. package/src/assets/web-panel/assets/index-BcnQrVVZ.js +0 -1
  172. package/src/assets/web-panel/assets/index-BzBaZFuT.js +0 -1
  173. package/src/assets/web-panel/assets/index-CDoxJ9Cl.js +0 -1
  174. package/src/assets/web-panel/assets/index-CIE6ht2b.js +0 -1
  175. package/src/assets/web-panel/assets/index-CIWKlZ1X.js +0 -13
  176. package/src/assets/web-panel/assets/index-D--EKCHy.js +0 -1
  177. package/src/assets/web-panel/assets/index-DIe3dY84.js +0 -1
  178. package/src/assets/web-panel/assets/index-DdHPswKn.js +0 -1
  179. package/src/assets/web-panel/assets/index-DgWftysw.js +0 -1
  180. package/src/assets/web-panel/assets/index-Dk3ZySO2.js +0 -55
  181. package/src/assets/web-panel/assets/index-ZZ_4A9um.js +0 -36
  182. package/src/assets/web-panel/assets/useFlexGapSupport--RuYYIc6.js +0 -1
  183. package/src/assets/web-panel/assets/vnode-I9keNa_U.js +0 -1
  184. package/src/assets/web-panel/assets/ws-Bv7YH0VB.js +0 -1
@@ -0,0 +1 @@
1
+ import{k as Q,r as P,j as K}from"./vendor-D0Qjn73K.js";let V=0;const S=()=>`wp-${++V}`,W=new Set;function w(t,s={},o={}){return{type:t,kind:o.kind||"server",sessionId:o.sessionId||s.sessionId||null,timestamp:o.timestamp||Date.now(),payload:s}}function X(t){const s=t?.type,o=t?.payload||{};switch(s){case"task:notification":return w("task:notification",{task:t.task||o.task},{kind:"server"});case"session-created":case"session.started":return w("session:start",{sessionId:t.sessionId||o.sessionId,sessionType:t.sessionType||o.sessionType||null,record:t.record||o.record||{id:t.sessionId||o.sessionId,type:t.sessionType||o.sessionType||null,status:"created",history:[],messageCount:0}},{kind:"server",sessionId:t.sessionId||o.sessionId});case"session-resumed":case"session.resumed":{const f=t.sessionId||o.sessionId,c=t.history||o.history||[];return w("session:resume",{sessionId:f,history:c,historyCount:Array.isArray(c)?c.length:0,record:t.record||o.record||{id:f,type:null,status:"resumed",history:c,messageCount:Array.isArray(c)?c.length:0}},{kind:"server",sessionId:f})}case"worktree-diff":case"worktree.diff":return w("worktree:diff:ready",{requestId:t.requestId||t.id||null,record:t.record||o.record||{branch:t.branch||o.branch||null,summary:t.summary||o.summary||null,previewEntrypoints:[{type:"worktree-diff",branch:t.branch||o.branch||null}]}},{kind:"server"});case"worktree-merged":case"worktree.merged":return w("worktree:merge:completed",{requestId:t.requestId||t.id||null,record:t.record||o.record||{branch:t.branch||o.branch||null,summary:t.summary||o.summary||null,conflicts:t.conflicts||o.conflicts||[],previewEntrypoints:t.previewEntrypoints||o.previewEntrypoints||[]}},{kind:"server"});case"compression-stats":case"context.compaction.completed":return w("compression:summary",{requestId:t.requestId||t.id||null,summary:t.summary||o.summary||{}},{kind:"server"});default:return null}}function M(t,s=null){W.forEach(o=>o(t,s||t))}function Y(t){if(!t)return null;const s=t.record||{id:t.id||null,type:t.type||null,provider:t.provider||null,model:t.model||null,projectRoot:t.projectRoot||null,messageCount:t.messageCount??0,history:t.history||[],status:t.status||null};return{...t,id:t.id||s.id,type:t.type||s.type,provider:t.provider||s.provider,model:t.model||s.model,projectRoot:t.projectRoot||s.projectRoot,messageCount:t.messageCount??s.messageCount??0,status:t.status||s.status||null,record:s}}const g=Q("ws",()=>{const t=P(null),s=P("disconnected"),o=P(null),f=new Map,c=new Map;let m=null,b=1e3,I=!1;const k=window.__CC_CONFIG__||{},R=K(()=>`ws://${k.wsHost||"127.0.0.1"}:${k.wsPort||18800}`);function C(){if(!(t.value?.readyState===WebSocket.OPEN||t.value?.readyState===WebSocket.CONNECTING)){clearTimeout(m),m=null,I=!1,s.value="connecting",o.value=null;try{const e=new WebSocket(R.value);t.value=e,e.onopen=()=>{b=1e3,k.wsToken?v({type:"auth",id:S(),token:k.wsToken}).then(()=>{s.value="connected"}).catch(()=>{s.value="connected"}):s.value="connected"},e.onmessage=n=>{let r;try{r=JSON.parse(n.data)}catch{return}A(r)},e.onerror=()=>{o.value="WebSocket error",s.value="error"},e.onclose=()=>{if(s.value="disconnected",t.value=null,f.forEach(({reject:n})=>n(new Error("WebSocket closed"))),f.clear(),y.forEach(({reject:n,clear:r})=>{try{r()}catch{}n(new Error("WebSocket closed"))}),y.clear(),I){I=!1,m=null;return}m=setTimeout(()=>{b=Math.min(b*2,3e4),m=null,C()},b)}}catch(e){s.value="error",o.value=e.message}}}function q(){clearTimeout(m),m=null,I=!0,t.value?.close(),t.value=null,s.value="disconnected"}function J(e){if(!e.version&&!e.payload)return e;const n=e.payload||{};return{...e,...n,type:e.type,sessionId:e.sessionId||n.sessionId||null}}function A(e){const{type:n}=e,r=e.requestId||e.id;let i=!1;if(r&&y.has(r)&&typeof n=="string"){const u=y.get(r);if(n.endsWith(".chunk")){try{u.onChunk(e.chunk)}catch{}return u.rearm(),!0}if(n.endsWith(".result"))return y.delete(r),u.clear(),e.ok===!1?u.reject(new Error(e.error||"Stream error")):u.resolve(e.result??null),!0}if(r&&f.has(r)){const{resolve:u,reject:d,timeout:l}=f.get(r);clearTimeout(l),f.delete(r),i=!0;const h=J(e);h.id=r,n==="error"?d(new Error(h.message||"Unknown error")):u(h)}const a=e.sessionId||e.payload&&e.payload.sessionId||null;if(a&&c.has(a)){const u=J(e);c.get(a).forEach(l=>l(u))}O.forEach(u=>u(e));const p=X(e);return p&&M(p,e),i}const O=new Set;function $(e){return O.add(e),()=>O.delete(e)}function _(e){return W.add(e),()=>W.delete(e)}function j(e,n){return c.has(e)||c.set(e,new Set),c.get(e).add(n),()=>{c.get(e)?.delete(n),c.get(e)?.size===0&&c.delete(e)}}function v(e,n=15e3){return new Promise((r,i)=>{if(t.value?.readyState!==WebSocket.OPEN){i(new Error("WebSocket not connected"));return}const a=e.id||S(),p=setTimeout(()=>{f.delete(a),i(new Error("Request timeout"))},n);f.set(a,{resolve:r,reject:i,timeout:p}),t.value.send(JSON.stringify({...e,id:a}))})}const y=new Map;function D(e,n={}){return new Promise((r,i)=>{if(t.value?.readyState!==WebSocket.OPEN){i(new Error("WebSocket not connected"));return}const a=e.id||S(),p=n.idleMs??3e4,u=typeof n.onChunk=="function"?n.onChunk:()=>{},d=n.signal;if(d?.aborted){const N=d.reason instanceof Error?d.reason:new Error("aborted");i(N);return}let l=null;const h=()=>{p&&(l&&clearTimeout(l),l=setTimeout(()=>{y.has(a)&&(y.delete(a),i(new Error("Stream idle timeout")))},p))},T=()=>{if(!y.has(a))return;y.delete(a),l&&(clearTimeout(l),l=null);try{t.value?.readyState===WebSocket.OPEN&&t.value.send(JSON.stringify({type:`${e.type}.cancel`,id:a}))}catch{}const N=d?.reason instanceof Error?d.reason:new Error("aborted");i(N)};y.set(a,{onChunk:u,resolve:r,reject:i,clear:()=>{if(l&&clearTimeout(l),l=null,d&&T)try{d.removeEventListener("abort",T)}catch{}},rearm:h}),h(),d&&d.addEventListener("abort",T,{once:!0}),t.value.send(JSON.stringify({...e,id:a}))})}function E(e=8e3){return s.value==="connected"?Promise.resolve():new Promise((n,r)=>{const i=Date.now()+e,a=()=>{if(s.value==="connected")return n();if(s.value==="error"||Date.now()>=i)return r(new Error(`WS not ready: ${s.value}`));setTimeout(a,150)};s.value==="disconnected"&&C(),a()})}async function x(e,n=3e4){await E(8e3);const r=await v({type:"execute",command:e},n),i=r.output??r.stdout??"",a=r.stderr??"";return{output:i||a,exitCode:r.exitCode??0}}async function H(e,n=3e4){const{output:r,exitCode:i}=await x(e,n);if(i!==0)throw new Error(`Command failed: ${r}`);try{return JSON.parse(r.trim())}catch{const a=r.match(/\{[\s\S]*\}|\[[\s\S]*\]/);if(a)return JSON.parse(a[0]);throw new Error(`Invalid JSON output: ${r.slice(0,200)}`)}}async function z(e="chat",n=null,r={}){await E(8e3);const a={type:"session-create",id:S(),sessionType:e,projectRoot:n||k.projectRoot||null};return r.systemPromptExtension&&(a.systemPromptExtension=r.systemPromptExtension),Array.isArray(r.shellPolicyOverrides)&&r.shellPolicyOverrides.length&&(a.shellPolicyOverrides=r.shellPolicyOverrides),(await v(a)).sessionId}function G(e,n){t.value?.readyState===WebSocket.OPEN&&t.value.send(JSON.stringify({type:"session-message",id:S(),sessionId:e,content:n}))}function L(e,n,r){t.value?.readyState===WebSocket.OPEN&&t.value.send(JSON.stringify({type:"session-answer",id:S(),sessionId:e,requestId:n,answer:r}))}async function U(){return await E(8e3),((await v({type:"session-list"},1e4)).sessions||[]).map(Y).filter(Boolean)}async function B(e){try{await v({type:"session-close",sessionId:e},5e3),M(w("session:end",{sessionId:e},{kind:"server",sessionId:e}),{type:"result",sessionId:e,success:!0})}catch{}}async function F(e){return await E(8e3),await v({type:"session-resume",sessionId:e},1e4)}return{status:s,error:o,wsUrl:R,connect:C,disconnect:q,waitConnected:E,onMessage:$,onRuntimeEvent:_,onSession:j,sendRaw:v,sendStream:D,execute:x,executeJson:H,createSession:z,resumeSession:F,sendSessionMessage:G,answerQuestion:L,listSessions:U,closeSession:B}});export{g as u};
@@ -1,4 +1,4 @@
1
- import{K as o}from"./Keyframes-C7fCrnlS.js";import{i as f}from"./motion-BR7NF0vx.js";const c=new o("antZoomIn",{"0%":{transform:"scale(0.2)",opacity:0},"100%":{transform:"scale(1)",opacity:1}}),y=new o("antZoomOut",{"0%":{transform:"scale(1)"},"100%":{transform:"scale(0.2)",opacity:0}}),a=new o("antZoomBigIn",{"0%":{transform:"scale(0.8)",opacity:0},"100%":{transform:"scale(1)",opacity:1}}),s=new o("antZoomBigOut",{"0%":{transform:"scale(1)"},"100%":{transform:"scale(0.8)",opacity:0}}),g=new o("antZoomUpIn",{"0%":{transform:"scale(0.8)",transformOrigin:"50% 0%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"50% 0%"}}),O=new o("antZoomUpOut",{"0%":{transform:"scale(1)",transformOrigin:"50% 0%"},"100%":{transform:"scale(0.8)",transformOrigin:"50% 0%",opacity:0}}),l=new o("antZoomLeftIn",{"0%":{transform:"scale(0.8)",transformOrigin:"0% 50%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"0% 50%"}}),u=new o("antZoomLeftOut",{"0%":{transform:"scale(1)",transformOrigin:"0% 50%"},"100%":{transform:"scale(0.8)",transformOrigin:"0% 50%",opacity:0}}),p=new o("antZoomRightIn",{"0%":{transform:"scale(0.8)",transformOrigin:"100% 50%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"100% 50%"}}),z=new o("antZoomRightOut",{"0%":{transform:"scale(1)",transformOrigin:"100% 50%"},"100%":{transform:"scale(0.8)",transformOrigin:"100% 50%",opacity:0}}),K=new o("antZoomDownIn",{"0%":{transform:"scale(0.8)",transformOrigin:"50% 100%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"50% 100%"}}),w=new o("antZoomDownOut",{"0%":{transform:"scale(1)",transformOrigin:"50% 100%"},"100%":{transform:"scale(0.8)",transformOrigin:"50% 100%",opacity:0}}),I={zoom:{inKeyframes:c,outKeyframes:y},"zoom-big":{inKeyframes:a,outKeyframes:s},"zoom-big-fast":{inKeyframes:a,outKeyframes:s},"zoom-left":{inKeyframes:l,outKeyframes:u},"zoom-right":{inKeyframes:p,outKeyframes:z},"zoom-up":{inKeyframes:g,outKeyframes:O},"zoom-down":{inKeyframes:K,outKeyframes:w}},h=(n,r)=>{const{antCls:m}=n,t=`${m}-${r}`,{inKeyframes:i,outKeyframes:e}=I[r];return[f(t,i,e,r==="zoom-big-fast"?n.motionDurationFast:n.motionDurationMid),{[`
1
+ import{K as o}from"./Keyframes-C7fCrnlS.js";import{i as f}from"./motion-CIQOKmi6.js";const c=new o("antZoomIn",{"0%":{transform:"scale(0.2)",opacity:0},"100%":{transform:"scale(1)",opacity:1}}),y=new o("antZoomOut",{"0%":{transform:"scale(1)"},"100%":{transform:"scale(0.2)",opacity:0}}),a=new o("antZoomBigIn",{"0%":{transform:"scale(0.8)",opacity:0},"100%":{transform:"scale(1)",opacity:1}}),s=new o("antZoomBigOut",{"0%":{transform:"scale(1)"},"100%":{transform:"scale(0.8)",opacity:0}}),g=new o("antZoomUpIn",{"0%":{transform:"scale(0.8)",transformOrigin:"50% 0%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"50% 0%"}}),O=new o("antZoomUpOut",{"0%":{transform:"scale(1)",transformOrigin:"50% 0%"},"100%":{transform:"scale(0.8)",transformOrigin:"50% 0%",opacity:0}}),l=new o("antZoomLeftIn",{"0%":{transform:"scale(0.8)",transformOrigin:"0% 50%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"0% 50%"}}),u=new o("antZoomLeftOut",{"0%":{transform:"scale(1)",transformOrigin:"0% 50%"},"100%":{transform:"scale(0.8)",transformOrigin:"0% 50%",opacity:0}}),p=new o("antZoomRightIn",{"0%":{transform:"scale(0.8)",transformOrigin:"100% 50%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"100% 50%"}}),z=new o("antZoomRightOut",{"0%":{transform:"scale(1)",transformOrigin:"100% 50%"},"100%":{transform:"scale(0.8)",transformOrigin:"100% 50%",opacity:0}}),K=new o("antZoomDownIn",{"0%":{transform:"scale(0.8)",transformOrigin:"50% 100%",opacity:0},"100%":{transform:"scale(1)",transformOrigin:"50% 100%"}}),w=new o("antZoomDownOut",{"0%":{transform:"scale(1)",transformOrigin:"50% 100%"},"100%":{transform:"scale(0.8)",transformOrigin:"50% 100%",opacity:0}}),I={zoom:{inKeyframes:c,outKeyframes:y},"zoom-big":{inKeyframes:a,outKeyframes:s},"zoom-big-fast":{inKeyframes:a,outKeyframes:s},"zoom-left":{inKeyframes:l,outKeyframes:u},"zoom-right":{inKeyframes:p,outKeyframes:z},"zoom-up":{inKeyframes:g,outKeyframes:O},"zoom-down":{inKeyframes:K,outKeyframes:w}},h=(n,r)=>{const{antCls:m}=n,t=`${m}-${r}`,{inKeyframes:i,outKeyframes:e}=I[r];return[f(t,i,e,r==="zoom-big-fast"?n.motionDurationFast:n.motionDurationMid),{[`
2
2
  ${t}-enter,
3
3
  ${t}-appear
4
4
  `]:{transform:"scale(0)",opacity:0,animationTimingFunction:n.motionEaseOutCirc,"&-prepare":{transform:"none"}},[`${t}-leave`]:{animationTimingFunction:n.motionEaseInOutCirc}}]};export{h as i,c as z};
@@ -8,9 +8,9 @@
8
8
  // Injected by web-ui-server.js at serve time
9
9
  window.__CC_CONFIG__ = __CC_CONFIG_PLACEHOLDER__;
10
10
  </script>
11
- <script type="module" crossorigin src="./assets/index-ZZ_4A9um.js"></script>
12
- <link rel="modulepreload" crossorigin href="./assets/vendor-BVetwVfk.js">
13
- <link rel="modulepreload" crossorigin href="./assets/icons-ukMaZ3tx.js">
11
+ <script type="module" crossorigin src="./assets/index-Vit9TJBu.js"></script>
12
+ <link rel="modulepreload" crossorigin href="./assets/vendor-D0Qjn73K.js">
13
+ <link rel="modulepreload" crossorigin href="./assets/icons-CJACPYXu.js">
14
14
  <link rel="stylesheet" crossorigin href="./assets/index-CyGyEIVX.css">
15
15
  </head>
16
16
  <body>
@@ -74,6 +74,16 @@ function _dbFromCtx(cmd) {
74
74
  return root?._db;
75
75
  }
76
76
 
77
+ function _requireDb(cmd) {
78
+ const db = _dbFromCtx(cmd);
79
+ if (!db) {
80
+ throw new Error(
81
+ "No ChainlessChain project database in this directory. Run `cc init` first, or run from a project root.",
82
+ );
83
+ }
84
+ return db;
85
+ }
86
+
77
87
  export function registerNlProgCommand(program) {
78
88
  const nlp = new Command("nlprog")
79
89
  .description("Natural language programming system (Phase 28)")
@@ -164,7 +174,7 @@ export function registerNlProgCommand(program) {
164
174
  .option("-a, --ambiguities <json>", "Ambiguity list JSON")
165
175
  .option("--json", "JSON output")
166
176
  .action((text, opts) => {
167
- const db = _dbFromCtx(nlp);
177
+ const db = _requireDb(nlp);
168
178
  const result = translate(db, {
169
179
  text,
170
180
  intent: opts.intent,
@@ -184,7 +194,7 @@ export function registerNlProgCommand(program) {
184
194
  .description("Show translation details")
185
195
  .option("--json", "JSON output")
186
196
  .action((id, opts) => {
187
- const db = _dbFromCtx(nlp);
197
+ const db = _requireDb(nlp);
188
198
  const t = getTranslation(db, id);
189
199
  if (!t) return console.log("Translation not found.");
190
200
  if (opts.json) return console.log(JSON.stringify(t, null, 2));
@@ -207,7 +217,7 @@ export function registerNlProgCommand(program) {
207
217
  .option("--limit <n>", "Max results", parseInt)
208
218
  .option("--json", "JSON output")
209
219
  .action((opts) => {
210
- const db = _dbFromCtx(nlp);
220
+ const db = _requireDb(nlp);
211
221
  const results = listTranslations(db, {
212
222
  intent: opts.intent,
213
223
  status: opts.status,
@@ -227,7 +237,7 @@ export function registerNlProgCommand(program) {
227
237
  .description("Update translation status (draft/complete/refined)")
228
238
  .option("--json", "JSON output")
229
239
  .action((id, status, opts) => {
230
- const db = _dbFromCtx(nlp);
240
+ const db = _requireDb(nlp);
231
241
  const result = updateTranslationStatus(db, id, status);
232
242
  if (opts.json) return console.log(JSON.stringify(result, null, 2));
233
243
  console.log(
@@ -244,7 +254,7 @@ export function registerNlProgCommand(program) {
244
254
  .option("-a, --ambiguities <json>", "Updated ambiguities JSON")
245
255
  .option("--json", "JSON output")
246
256
  .action((id, opts) => {
247
- const db = _dbFromCtx(nlp);
257
+ const db = _requireDb(nlp);
248
258
  const result = refineTranslation(db, id, {
249
259
  spec: opts.spec,
250
260
  ambiguities: opts.ambiguities,
@@ -260,7 +270,7 @@ export function registerNlProgCommand(program) {
260
270
  .description("Remove a translation")
261
271
  .option("--json", "JSON output")
262
272
  .action((id, opts) => {
263
- const db = _dbFromCtx(nlp);
273
+ const db = _requireDb(nlp);
264
274
  const result = removeTranslation(db, id);
265
275
  if (opts.json) return console.log(JSON.stringify(result, null, 2));
266
276
  console.log(
@@ -283,7 +293,7 @@ export function registerNlProgCommand(program) {
283
293
  .option("-s, --source-files <json>", "Source files JSON")
284
294
  .option("--json", "JSON output")
285
295
  .action((opts) => {
286
- const db = _dbFromCtx(nlp);
296
+ const db = _requireDb(nlp);
287
297
  const result = addConvention(db, {
288
298
  category: opts.category,
289
299
  pattern: opts.pattern,
@@ -301,7 +311,7 @@ export function registerNlProgCommand(program) {
301
311
  .description("Show convention details")
302
312
  .option("--json", "JSON output")
303
313
  .action((id, opts) => {
304
- const db = _dbFromCtx(nlp);
314
+ const db = _requireDb(nlp);
305
315
  const c = getConvention(db, id);
306
316
  if (!c) return console.log("Convention not found.");
307
317
  if (opts.json) return console.log(JSON.stringify(c, null, 2));
@@ -319,7 +329,7 @@ export function registerNlProgCommand(program) {
319
329
  .option("--limit <n>", "Max results", parseInt)
320
330
  .option("--json", "JSON output")
321
331
  .action((opts) => {
322
- const db = _dbFromCtx(nlp);
332
+ const db = _requireDb(nlp);
323
333
  const results = listConventions(db, {
324
334
  category: opts.category,
325
335
  limit: opts.limit,
@@ -338,7 +348,7 @@ export function registerNlProgCommand(program) {
338
348
  .description("Remove a convention")
339
349
  .option("--json", "JSON output")
340
350
  .action((id, opts) => {
341
- const db = _dbFromCtx(nlp);
351
+ const db = _requireDb(nlp);
342
352
  const result = removeConvention(db, id);
343
353
  if (opts.json) return console.log(JSON.stringify(result, null, 2));
344
354
  console.log(
@@ -353,7 +363,7 @@ export function registerNlProgCommand(program) {
353
363
  .description("NL Programming statistics")
354
364
  .option("--json", "JSON output")
355
365
  .action((opts) => {
356
- const db = _dbFromCtx(nlp);
366
+ const db = _requireDb(nlp);
357
367
  const s = getNlProgrammingStats(db);
358
368
  if (opts.json) return console.log(JSON.stringify(s, null, 2));
359
369
  console.log(
@@ -473,7 +483,7 @@ export function registerNlProgCommand(program) {
473
483
  .option("-m, --metadata <json>", "Metadata JSON")
474
484
  .option("--json", "JSON output")
475
485
  .action((specId, opts) => {
476
- const db = _dbFromCtx(nlp);
486
+ const db = _requireDb(nlp);
477
487
  const rec = registerSpecV2(db, {
478
488
  specId,
479
489
  authorId: opts.author,
@@ -506,7 +516,7 @@ export function registerNlProgCommand(program) {
506
516
  .option("-r, --reason <text>", "Reason")
507
517
  .option("-m, --metadata <json>", "Metadata patch (JSON)")
508
518
  .action((id, status, opts) => {
509
- const db = _dbFromCtx(nlp);
519
+ const db = _requireDb(nlp);
510
520
  const rec = setSpecMaturityV2(db, id, status, {
511
521
  reason: opts.reason,
512
522
  metadata: _parseMetaV2(opts.metadata),
@@ -568,7 +578,7 @@ export function registerNlProgCommand(program) {
568
578
  .option("-m, --metadata <json>", "Metadata JSON")
569
579
  .option("--json", "JSON output")
570
580
  .action((turnId, opts) => {
571
- const db = _dbFromCtx(nlp);
581
+ const db = _requireDb(nlp);
572
582
  const rec = registerDialogueTurnV2(db, {
573
583
  turnId,
574
584
  specId: opts.spec,
@@ -603,7 +613,7 @@ export function registerNlProgCommand(program) {
603
613
  .option("-r, --reason <text>", "Reason")
604
614
  .option("-m, --metadata <json>", "Metadata patch (JSON)")
605
615
  .action((id, status, opts) => {
606
- const db = _dbFromCtx(nlp);
616
+ const db = _requireDb(nlp);
607
617
  const rec = setDialogueTurnStatusV2(db, id, status, {
608
618
  answer: opts.answer,
609
619
  reason: opts.reason,
@@ -168,7 +168,11 @@ export class ChainlessChainWSServer extends EventEmitter {
168
168
  */
169
169
  constructor(options = {}) {
170
170
  super();
171
- this.port = options.port || 18800;
171
+ // Use ?? so an explicit `port: 0` (OS-assigned, used by tests + the
172
+ // desktop web-shell bootstrap) is preserved instead of falling back to
173
+ // the hardcoded 18800. The address() readback after listen() updates
174
+ // this.port to the actual bound port — see start().
175
+ this.port = options.port ?? 18800;
172
176
  this.host = options.host || "127.0.0.1";
173
177
  this.token = options.token || null;
174
178
  this.maxConnections = options.maxConnections || 10;
@@ -558,6 +562,13 @@ export class ChainlessChainWSServer extends EventEmitter {
558
562
  ...process.env,
559
563
  FORCE_COLOR: "0",
560
564
  NO_SPINNER: "1",
565
+ // When this server runs inside Electron (e.g. desktop web-shell)
566
+ // process.execPath points at the Electron binary, not node. Setting
567
+ // ELECTRON_RUN_AS_NODE=1 makes Electron behave as a plain Node
568
+ // runtime for this child, so the CLI script runs normally instead
569
+ // of being interpreted as a packaged Electron app entry. No-op
570
+ // outside Electron.
571
+ ...(process.versions.electron ? { ELECTRON_RUN_AS_NODE: "1" } : {}),
561
572
  },
562
573
  stdio: ["pipe", "pipe", "pipe"],
563
574
  windowsHide: true,
@@ -581,13 +581,19 @@ export class WSSessionManager {
581
581
  });
582
582
  }
583
583
 
584
- // DB sessions (exclude already-listed in-memory ones)
584
+ // DB sessions (exclude already-listed in-memory ones AND closed ones —
585
+ // closeSession persists `status: "closed"` to metadata before deleting
586
+ // from in-memory; without this filter the closed session keeps showing
587
+ // up in `session-list`, contradicting the contract).
585
588
  if (this.db) {
586
589
  try {
587
590
  const dbSessions = dbListSessions(this.db, { limit: 20 });
588
591
  const inMemoryIds = new Set(this.sessions.keys());
589
592
  for (const dbs of dbSessions) {
590
593
  const metadata = this._normalizeSessionMetadata(dbs.metadata);
594
+ if (metadata && metadata.status === "closed") {
595
+ continue;
596
+ }
591
597
  if (!inMemoryIds.has(dbs.id)) {
592
598
  results.push({
593
599
  id: dbs.id,
@@ -1289,6 +1295,11 @@ export class WSSessionManager {
1289
1295
  return {
1290
1296
  version: 1,
1291
1297
  sessionType: session.type || "agent",
1298
+ // Persist status so listSessions can exclude closed sessions when
1299
+ // re-hydrating from DB. Without this, a closed session keeps
1300
+ // showing up in `session-list` because closeSession deletes from
1301
+ // in-memory map BEFORE the DB row is filtered.
1302
+ status: session.status || "active",
1292
1303
  projectRoot: session.projectRoot || null,
1293
1304
  baseProjectRoot: session.baseProjectRoot || session.projectRoot || null,
1294
1305
  baseUrl: session.baseUrl || null,
@@ -0,0 +1,103 @@
1
+ /**
2
+ * listen-with-port-fallback.js
3
+ *
4
+ * Try to bind a server on the preferred port. If that port is taken
5
+ * (EADDRINUSE), walk through adjacent ports up to `maxAttempts`. If
6
+ * every adjacent port is also taken, fall back once more to port 0
7
+ * (OS-assigned ephemeral). Surfaces the actually bound port so the
8
+ * caller can log it / propagate it to dependent servers (e.g. the
9
+ * HTTP server's `__CC_CONFIG__.wsPort` injection).
10
+ *
11
+ * Used by `cc ui`'s startUiServer for both the WS and HTTP servers
12
+ * — port collisions are common during development (multiple `cc ui`
13
+ * instances, prior crashes that left listeners orphaned, the desktop
14
+ * web-shell already running, etc.) and crashing on EADDRINUSE makes
15
+ * for poor UX.
16
+ */
17
+
18
+ /**
19
+ * @template T
20
+ * @param {(port: number) => Promise<T>} listenFn
21
+ * Per-attempt binder. Must reject with `err.code === "EADDRINUSE"` on
22
+ * conflict; any other error propagates immediately. Resolved value is
23
+ * passed through verbatim so the caller can pull the actual port from
24
+ * their server handle (the listenFn is expected to readback the bound
25
+ * port from `address()` after listen — see ws-server.js for the pattern).
26
+ *
27
+ * @param {number} preferred
28
+ * First port to attempt. Must be in [1, 65535]; pass 0 to skip the
29
+ * sequential walk and go straight to OS-assigned.
30
+ *
31
+ * @param {object} [opts]
32
+ * @param {number} [opts.maxAttempts=20]
33
+ * How many sequential adjacent ports to try after `preferred` (so the
34
+ * walk covers `preferred`, `preferred+1`, …, `preferred + maxAttempts - 1`).
35
+ * @param {(msg: string) => void} [opts.onFallback]
36
+ * Optional notifier called once when the preferred port is taken,
37
+ * with a human-readable message summarising the fallback decision.
38
+ *
39
+ * @returns {Promise<T>} the listenFn's resolved value for the port that bound.
40
+ */
41
+ export async function listenWithPortFallback(listenFn, preferred, opts = {}) {
42
+ const { maxAttempts = 20, onFallback } = opts;
43
+
44
+ if (typeof listenFn !== "function") {
45
+ throw new TypeError("listenWithPortFallback: listenFn must be a function");
46
+ }
47
+ if (!Number.isInteger(preferred) || preferred < 0 || preferred > 65535) {
48
+ throw new RangeError(
49
+ `listenWithPortFallback: preferred port out of range: ${preferred}`,
50
+ );
51
+ }
52
+
53
+ // preferred === 0 means caller already wants OS-assigned, no fallback needed.
54
+ if (preferred === 0) {
55
+ return listenFn(0);
56
+ }
57
+
58
+ const upper = Math.min(preferred + maxAttempts, 65536);
59
+ const tried = [];
60
+
61
+ for (let port = preferred; port < upper; port++) {
62
+ try {
63
+ const result = await listenFn(port);
64
+ if (port !== preferred && typeof onFallback === "function") {
65
+ try {
66
+ onFallback(
67
+ `Port ${preferred} in use; bound on ${port} instead (tried ${tried.join(", ")}).`,
68
+ );
69
+ } catch {
70
+ /* swallow — onFallback is informational */
71
+ }
72
+ }
73
+ return result;
74
+ } catch (err) {
75
+ if (err && err.code === "EADDRINUSE") {
76
+ tried.push(port);
77
+ continue;
78
+ }
79
+ throw err;
80
+ }
81
+ }
82
+
83
+ // All sequential ports busy — final fallback to OS-assigned.
84
+ if (typeof onFallback === "function") {
85
+ try {
86
+ onFallback(
87
+ `Ports ${tried.join(", ")} all in use; falling back to OS-assigned port.`,
88
+ );
89
+ } catch {
90
+ /* swallow */
91
+ }
92
+ }
93
+ try {
94
+ return await listenFn(0);
95
+ } catch (err) {
96
+ if (err && err.code === "EADDRINUSE") {
97
+ throw new Error(
98
+ `Could not bind any port. Tried: ${tried.join(", ")} and OS-assigned. Last error: ${err.message}`,
99
+ );
100
+ }
101
+ throw err;
102
+ }
103
+ }
@@ -1186,6 +1186,11 @@ function buildConfigJson(opts) {
1186
1186
  projectRoot: opts.projectRoot,
1187
1187
  projectName: opts.projectName,
1188
1188
  mode: opts.mode,
1189
+ // True only when the SPA is hosted by the desktop web-shell. Lets the
1190
+ // SPA prefer in-process custom WS topics (e.g. `skill.list`) over
1191
+ // `ws.execute(...)` which can't fork a real `cc` from inside Electron.
1192
+ // Default false so the CLI's own `cc serve` is unaffected.
1193
+ embeddedShell: opts.embeddedShell === true,
1189
1194
  })
1190
1195
  .replace(/</g, "\\u003c")
1191
1196
  .replace(/>/g, "\\u003e")
@@ -1365,6 +1370,34 @@ export function createWebUIServer(opts) {
1365
1370
  // '$&', '$`', "$'" etc. in configJson as special replacement patterns
1366
1371
  // (e.g. projectRoot="/path/$HOME" would corrupt the JSON otherwise).
1367
1372
  html = html.replace("__CC_CONFIG_PLACEHOLDER__", () => configJson);
1373
+ if (opts.embeddedShell) {
1374
+ // Electron's titleBarOverlay reserves the top-right ~138px for
1375
+ // native min/max/close buttons. Web-panel's `.app-header` lays
1376
+ // out a right-aligned cluster (status badge, version chip, action
1377
+ // icons) in the same region, so the OS controls visually cover
1378
+ // it. Push the cluster left by that amount only when the SPA is
1379
+ // hosted inside the desktop web-shell.
1380
+ //
1381
+ // We inject both a `<style>` block (covers selectors at first
1382
+ // paint) and a post-load script that sets the padding via inline
1383
+ // styles (specificity 1000+, beats anything Ant Design or page-
1384
+ // specific CSS sets later).
1385
+ const overlayPad = "158px"; // 138 native + 20 gap
1386
+ html = html.replace(
1387
+ "</head>",
1388
+ '<style id="cc-embedded-shell-overrides">' +
1389
+ "header.app-header,header.ant-layout-header.app-header,.app-header{" +
1390
+ `padding-right:${overlayPad} !important;` +
1391
+ "}" +
1392
+ "</style>" +
1393
+ "<script>(function(){function apply(){var els=document.querySelectorAll('.app-header,header.ant-layout-header');" +
1394
+ `for(var i=0;i<els.length;i++){els[i].style.setProperty('padding-right','${overlayPad}','important');}}` +
1395
+ "if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',apply);}else{apply();}" +
1396
+ "var mo=new MutationObserver(apply);mo.observe(document.body||document.documentElement,{childList:true,subtree:true});" +
1397
+ "})();</script>" +
1398
+ "</head>",
1399
+ );
1400
+ }
1368
1401
  res.writeHead(200, {
1369
1402
  "Content-Type": "text/html; charset=utf-8",
1370
1403
  "Cache-Control": "no-store",
@@ -9,6 +9,7 @@ import {
9
9
  import { createRuntimeContext } from "./runtime-context.js";
10
10
  import { createAgentTurnRecord } from "./contracts/agent-turn.js";
11
11
  import { logger } from "../lib/logger.js";
12
+ import { listenWithPortFallback } from "../lib/listen-with-port-fallback.js";
12
13
  import { bootstrap } from "./bootstrap.js";
13
14
  import { startAgentRepl } from "../gateways/repl/agent-repl.js";
14
15
  import { startChatRepl } from "../gateways/repl/chat-repl.js";
@@ -477,18 +478,55 @@ export class AgentRuntime {
477
478
  mcpServerRegistry: this.deps.mcpServerRegistry,
478
479
  });
479
480
 
480
- const wsServer = this.deps.createServer({
481
- port: wsPort,
482
- host,
483
- token: this.policy.token,
484
- maxConnections: 20,
485
- timeout: 60000,
486
- sessionManager,
487
- });
488
- await wsServer.start();
481
+ // Bind the WS server with port-fallback so multiple `cc ui` instances
482
+ // (or a desktop web-shell already running on 18800) don't crash this
483
+ // one. listenWithPortFallback walks preferred → +20 adjacent → OS-
484
+ // assigned. The WS server's listen handler updates `wsServer.port` to
485
+ // the actual bound port; we read that back for the HTTP injection.
486
+ let wsServer = null;
487
+ await listenWithPortFallback(
488
+ async (port) => {
489
+ const candidate = this.deps.createServer({
490
+ port,
491
+ host,
492
+ token: this.policy.token,
493
+ maxConnections: 20,
494
+ timeout: 60000,
495
+ sessionManager,
496
+ });
497
+ // ChainlessChainWSServer extends EventEmitter and emits "error"
498
+ // synchronously on bind failure (in addition to rejecting start()).
499
+ // Without a listener Node throws "Unhandled 'error' event" before
500
+ // our reject can settle — crashing the whole process before
501
+ // listenWithPortFallback can catch EADDRINUSE and try the next port.
502
+ // Attach a no-op so the rejection from start() is the single
503
+ // source of failure visibility.
504
+ candidate.on("error", () => {});
505
+ try {
506
+ await candidate.start();
507
+ } catch (err) {
508
+ // Best-effort cleanup so the failed candidate doesn't leak
509
+ // listeners before we retry on the next port.
510
+ try {
511
+ await candidate.stop();
512
+ } catch {
513
+ /* candidate never bound */
514
+ }
515
+ throw err;
516
+ }
517
+ wsServer = candidate;
518
+ return candidate;
519
+ },
520
+ wsPort,
521
+ {
522
+ onFallback: (msg) => runtimeLogger.log(chalk.yellow(` [WS] ${msg}`)),
523
+ },
524
+ );
525
+
526
+ const actualWsPort = wsServer.port;
489
527
 
490
528
  const httpServer = this.deps.createWebServer({
491
- wsPort,
529
+ wsPort: actualWsPort,
492
530
  wsToken: this.policy.token,
493
531
  wsHost: host === "0.0.0.0" ? "127.0.0.1" : host,
494
532
  projectRoot,
@@ -498,12 +536,34 @@ export class AgentRuntime {
498
536
  uiMode: this.policy.uiMode,
499
537
  });
500
538
 
501
- await new Promise((resolve, reject) => {
502
- httpServer.listen(httpPort, host, () => resolve());
503
- httpServer.on("error", reject);
504
- });
539
+ // Same fallback for HTTP. http.Server.listen takes (port, host, cb)
540
+ // and emits "error" once on bind failure; race them and surface the
541
+ // bound port back to the helper so it can decide whether to retry.
542
+ const actualHttpPort = await listenWithPortFallback(
543
+ (port) =>
544
+ new Promise((resolve, reject) => {
545
+ const onError = (err) => {
546
+ httpServer.removeListener("listening", onListening);
547
+ reject(err);
548
+ };
549
+ const onListening = () => {
550
+ httpServer.removeListener("error", onError);
551
+ const addr = httpServer.address();
552
+ const bound =
553
+ addr && typeof addr === "object" && addr.port ? addr.port : port;
554
+ resolve(bound);
555
+ };
556
+ httpServer.once("error", onError);
557
+ httpServer.once("listening", onListening);
558
+ httpServer.listen(port, host);
559
+ }),
560
+ httpPort,
561
+ {
562
+ onFallback: (msg) => runtimeLogger.log(chalk.yellow(` [HTTP] ${msg}`)),
563
+ },
564
+ );
505
565
 
506
- const uiUrl = `http://${host === "0.0.0.0" ? "127.0.0.1" : host}:${httpPort}`;
566
+ const uiUrl = `http://${host === "0.0.0.0" ? "127.0.0.1" : host}:${actualHttpPort}`;
507
567
 
508
568
  this.emit(RUNTIME_EVENTS.RUNTIME_START, {
509
569
  kind: this.kind,
@@ -511,8 +571,8 @@ export class AgentRuntime {
511
571
  });
512
572
  this.emit(RUNTIME_EVENTS.SERVER_START, {
513
573
  host,
514
- port: httpPort,
515
- wsPort,
574
+ port: actualHttpPort,
575
+ wsPort: actualWsPort,
516
576
  mode,
517
577
  projectRoot,
518
578
  });
@@ -531,7 +591,9 @@ export class AgentRuntime {
531
591
  runtimeLogger.log(` Mode: ${chalk.cyan("global")}`);
532
592
  }
533
593
  runtimeLogger.log(` UI: ${chalk.cyan(uiUrl)}`);
534
- runtimeLogger.log(` WS: ${chalk.dim(`ws://${host}:${wsPort}`)}`);
594
+ runtimeLogger.log(
595
+ ` WS: ${chalk.dim(`ws://${host}:${actualWsPort}`)}`,
596
+ );
535
597
  runtimeLogger.log(
536
598
  ` Auth: ${this.policy.token ? chalk.green("enabled") : chalk.yellow("disabled")}`,
537
599
  );
@@ -1 +0,0 @@
1
- import{r as D,w as ze,l as Je,m as g,x as t,q as u,B as He,C as Ye,v as a,c as e,D as i,E as S,u as n,F as y,G as B,H as A,I as v,J as l,K as qe,L as $e,j as m}from"./vendor-BVetwVfk.js";import{u as Qe}from"./ws-Bv7YH0VB.js";import{u as Xe,T as Ze}from"./index-ZZ_4A9um.js";import{_ as he}from"./_plugin-vue_export-helper-DlAUqK2U.js";import{F as O,G as N,D as j,M as E,R as F,C as G,A as M,N as V,a as W,b as z,c as J,d as H,B as Y,e as K,f as q,S as $,h as Q,i as X,j as Z,k as h,l as ee,P as te,m as oe,n as ne,o as L,p as se,I as le,L as ie,W as ae,q as de,r as ue,s as re,E as ye,t as pe,u as ke,v as ce,w as me,x as fe,y as _e,z as ge,U as ve,H as Oe,J as be,K as we,V as et,O as Ce,Q as Se,X as tt}from"./icons-ukMaZ3tx.js";const ot=["src"],nt={key:0,class:"logo-text"},st={key:0,class:"mode-banner project"},lt={class:"banner-info"},it={class:"banner-name"},at={key:1,class:"mode-banner global"},dt=["title"],ut={key:0,class:"footer-text"},rt={class:"header-left"},yt={class:"header-right"},pt={class:"theme-switcher"},kt=["data-theme-key","onClick"],ct={class:"version-tag"},Ae="cc.web-panel.sidebar.openKeys",mt={__name:"AppLayout",setup(ft){const je=He(),Ke=Ye(),b=Qe(),T=Xe(),r=D(!1),f=window.__CC_CONFIG__||{},c=m(()=>f.mode==="project"),Le="v5.0.3.1",Te=new URL(""+new URL("logo-DBCYUiWP.png",import.meta.url).href,import.meta.url).href,xe=m(()=>T.current),Be=m(()=>T.config.vars["--menu-mode"]),R=m(()=>{const d=Ke.name?.toLowerCase()||"dashboard";return[{mcptools:"mcp"}[d]||d]}),I=["g-overview","g-config","g-data","g-advanced","g-enterprise","g-social","g-media","g-extension"];function Ne(){try{const d=localStorage.getItem(Ae);if(d){const o=JSON.parse(d);if(Array.isArray(o))return o.filter(s=>I.includes(s))}}catch{}return[...I]}const x=D(Ne());ze(x,d=>{try{localStorage.setItem(Ae,JSON.stringify(d))}catch{}},{deep:!0});const w=m(()=>b.status),Re=m(()=>({connected:"success",connecting:"processing",error:"error",disconnected:"default"})[b.status]||"default"),Ie=m(()=>({connected:"已连接",connecting:"连接中...",error:"连接错误",disconnected:"未连接"})[b.status]||"未知");function Ue(d){T.setTheme(d)}function Pe({key:d}){je.push({mcp:"/mcp"}[d]||`/${d}`)}return Je(()=>b.connect()),(d,o)=>{const s=u("a-menu-item"),p=u("a-sub-menu"),_=u("a-menu-divider"),De=u("a-menu"),Ee=u("a-badge"),Fe=u("a-layout-sider"),U=u("a-tooltip"),Ge=u("a-tag"),Me=u("a-layout-header"),Ve=u("router-view"),We=u("a-layout-content"),P=u("a-layout");return a(),g(P,{class:"app-root"},{default:t(()=>[e(Fe,{collapsed:r.value,"onUpdate:collapsed":o[2]||(o[2]=k=>r.value=k),collapsible:"","collapsed-width":56,width:216,class:"sidebar"},{default:t(()=>[i("div",{class:S(["logo",{collapsed:r.value}])},[i("img",{src:n(Te),alt:"ChainlessChain",class:"logo-icon"},null,8,ot),r.value?B("",!0):(a(),y("span",nt,"ChainlessChain"))],2),r.value?(a(),y("div",{key:1,class:"mode-icon-sm",title:c.value?n(f).projectName:"全局模式"},[c.value?(a(),g(n(O),{key:0,style:{color:"#1677ff"}})):(a(),g(n(N),{key:1,style:{color:"#722ed1"}}))],8,dt)):(a(),y(A,{key:0},[c.value?(a(),y("div",st,[e(n(O),{class:"banner-icon"}),i("div",lt,[i("div",it,v(n(f).projectName||"项目"),1),o[3]||(o[3]=i("div",{class:"banner-sub"},"项目级面板",-1))])])):(a(),y("div",at,[e(n(N),{class:"banner-icon"}),o[4]||(o[4]=i("span",{class:"banner-name"},"全局模式",-1))]))],64)),e(De,{selectedKeys:R.value,"onUpdate:selectedKeys":o[0]||(o[0]=k=>R.value=k),openKeys:x.value,"onUpdate:openKeys":o[1]||(o[1]=k=>x.value=k),theme:Be.value,mode:"inline","inline-collapsed":r.value,class:"side-menu",onClick:Pe},{default:t(()=>[r.value?(a(),y(A,{key:1},[e(s,{key:"dashboard"},{icon:t(()=>[e(n(j))]),_:1}),e(s,{key:"chat"},{icon:t(()=>[e(n(E))]),_:1}),e(s,{key:"cowork"},{icon:t(()=>[e(n(F))]),_:1}),e(s,{key:"services"},{icon:t(()=>[e(n(G))]),_:1}),e(s,{key:"aiops"},{icon:t(()=>[e(n(M))]),_:1}),e(s,{key:"tokens"},{icon:t(()=>[e(n(V))]),_:1}),e(s,{key:"logs"},{icon:t(()=>[e(n(W))]),_:1}),e(_,{class:"divider-sm"}),e(s,{key:"skills"},{icon:t(()=>[e(n(z))]),_:1}),e(s,{key:"providers"},{icon:t(()=>[e(n(J))]),_:1}),e(s,{key:"mcp"},{icon:t(()=>[e(n(H))]),_:1}),e(s,{key:"project-settings"},{icon:t(()=>[e(n(O))]),_:1}),e(s,{key:"nlprog"},{icon:t(()=>[e(n(Y))]),_:1}),e(s,{key:"codegen"},{icon:t(()=>[e(n(K))]),_:1}),e(_,{class:"divider-sm"}),e(s,{key:"notes"},{icon:t(()=>[e(n(q))]),_:1}),e(s,{key:"search"},{icon:t(()=>[e(n($))]),_:1}),e(s,{key:"memory"},{icon:t(()=>[e(n(Q))]),_:1}),e(s,{key:"knowledge"},{icon:t(()=>[e(n(X))]),_:1}),e(s,{key:"marketplace"},{icon:t(()=>[e(n(Z))]),_:1}),e(s,{key:"cron"},{icon:t(()=>[e(n(h))]),_:1}),e(s,{key:"workflow"},{icon:t(()=>[e(n(ee))]),_:1}),e(s,{key:"pipeline"},{icon:t(()=>[e(n(te))]),_:1}),e(s,{key:"tasks"},{icon:t(()=>[e(n(oe))]),_:1}),e(_,{class:"divider-sm"}),e(s,{key:"security"},{icon:t(()=>[e(n(ne))]),_:1}),e(s,{key:"trust"},{icon:t(()=>[e(n(L))]),_:1}),e(s,{key:"audit"},{icon:t(()=>[e(n(se))]),_:1}),e(s,{key:"did"},{icon:t(()=>[e(n(le))]),_:1}),e(s,{key:"permissions"},{icon:t(()=>[e(n(ie))]),_:1}),e(s,{key:"p2p"},{icon:t(()=>[e(n(ae))]),_:1}),e(s,{key:"backup"},{icon:t(()=>[e(n(de))]),_:1}),e(s,{key:"git"},{icon:t(()=>[e(n(K))]),_:1}),e(s,{key:"projects"},{icon:t(()=>[e(n(ue))]),_:1}),e(s,{key:"crosschain"},{icon:t(()=>[e(n(re))]),_:1}),e(s,{key:"compliance"},{icon:t(()=>[e(n(L))]),_:1}),e(s,{key:"privacy"},{icon:t(()=>[e(n(ye))]),_:1}),e(s,{key:"inference"},{icon:t(()=>[e(n(pe))]),_:1}),e(s,{key:"federation"},{icon:t(()=>[e(n(ke))]),_:1}),e(_,{class:"divider-sm"}),e(s,{key:"wallet"},{icon:t(()=>[e(n(ce))]),_:1}),e(s,{key:"organization"},{icon:t(()=>[e(n(me))]),_:1}),e(s,{key:"tenant"},{icon:t(()=>[e(n(fe))]),_:1}),e(s,{key:"sla"},{icon:t(()=>[e(n(j))]),_:1}),e(s,{key:"analytics"},{icon:t(()=>[e(n(_e))]),_:1}),e(s,{key:"templates"},{icon:t(()=>[e(n(ge))]),_:1}),e(_,{class:"divider-sm"}),e(s,{key:"community"},{icon:t(()=>[e(n(ve))]),_:1}),e(s,{key:"governance"},{icon:t(()=>[e(n(Oe))]),_:1}),e(s,{key:"reputation"},{icon:t(()=>[e(n(be))]),_:1}),e(s,{key:"recommend"},{icon:t(()=>[e(n(we))]),_:1}),e(_,{class:"divider-sm"}),e(s,{key:"rssfeed"},{icon:t(()=>[e(n(Ce))]),_:1}),e(s,{key:"webauthn"},{icon:t(()=>[e(n(Se))]),_:1})],64)):(a(),y(A,{key:0},[e(p,{key:"g-overview"},{title:t(()=>[...o[5]||(o[5]=[i("span",{class:"group-label"},"概 览",-1)])]),default:t(()=>[e(s,{key:"dashboard"},{icon:t(()=>[e(n(j))]),default:t(()=>[o[6]||(o[6]=l("仪表板",-1))]),_:1}),e(s,{key:"chat"},{icon:t(()=>[e(n(E))]),default:t(()=>[o[7]||(o[7]=l("AI 对话",-1))]),_:1}),e(s,{key:"cowork"},{icon:t(()=>[e(n(F))]),default:t(()=>[o[8]||(o[8]=l("日常协作",-1))]),_:1}),e(s,{key:"services"},{icon:t(()=>[e(n(G))]),default:t(()=>[o[9]||(o[9]=l("服务管理",-1))]),_:1}),e(s,{key:"aiops"},{icon:t(()=>[e(n(M))]),default:t(()=>[o[10]||(o[10]=l("AIOps",-1))]),_:1}),e(s,{key:"tokens"},{icon:t(()=>[e(n(V))]),default:t(()=>[o[11]||(o[11]=l("Token 用量",-1))]),_:1}),e(s,{key:"logs"},{icon:t(()=>[e(n(W))]),default:t(()=>[o[12]||(o[12]=l("日志查看",-1))]),_:1})]),_:1}),e(p,{key:"g-config"},{title:t(()=>[...o[13]||(o[13]=[i("span",{class:"group-label"},"配 置",-1)])]),default:t(()=>[e(s,{key:"skills"},{icon:t(()=>[e(n(z))]),default:t(()=>[o[14]||(o[14]=l("技能管理",-1))]),_:1}),e(s,{key:"providers"},{icon:t(()=>[e(n(J))]),default:t(()=>[o[15]||(o[15]=l("LLM 配置",-1))]),_:1}),e(s,{key:"mcp"},{icon:t(()=>[e(n(H))]),default:t(()=>[o[16]||(o[16]=l("MCP 工具",-1))]),_:1}),e(s,{key:"project-settings"},{icon:t(()=>[e(n(O))]),default:t(()=>[o[17]||(o[17]=l("项目存储",-1))]),_:1}),e(s,{key:"nlprog"},{icon:t(()=>[e(n(Y))]),default:t(()=>[o[18]||(o[18]=l("自然语言编程",-1))]),_:1}),e(s,{key:"codegen"},{icon:t(()=>[e(n(K))]),default:t(()=>[o[19]||(o[19]=l("代码生成",-1))]),_:1})]),_:1}),e(p,{key:"g-data"},{title:t(()=>[...o[20]||(o[20]=[i("span",{class:"group-label"},"数 据",-1)])]),default:t(()=>[e(s,{key:"notes"},{icon:t(()=>[e(n(q))]),default:t(()=>[o[21]||(o[21]=l("笔记管理",-1))]),_:1}),e(s,{key:"search"},{icon:t(()=>[e(n($))]),default:t(()=>[o[22]||(o[22]=l("RAG 搜索",-1))]),_:1}),e(s,{key:"memory"},{icon:t(()=>[e(n(Q))]),default:t(()=>[o[23]||(o[23]=l("记忆文件",-1))]),_:1}),e(s,{key:"knowledge"},{icon:t(()=>[e(n(X))]),default:t(()=>[o[24]||(o[24]=l("知识图谱",-1))]),_:1}),e(s,{key:"marketplace"},{icon:t(()=>[e(n(Z))]),default:t(()=>[o[25]||(o[25]=l("技能市场",-1))]),_:1}),e(s,{key:"cron"},{icon:t(()=>[e(n(h))]),default:t(()=>[o[26]||(o[26]=l("定时任务",-1))]),_:1}),e(s,{key:"workflow"},{icon:t(()=>[e(n(ee))]),default:t(()=>[o[27]||(o[27]=l("工作流编辑",-1))]),_:1}),e(s,{key:"pipeline"},{icon:t(()=>[e(n(te))]),default:t(()=>[o[28]||(o[28]=l("开发流水线",-1))]),_:1}),e(s,{key:"tasks"},{icon:t(()=>[e(n(oe))]),default:t(()=>[o[29]||(o[29]=l("后台任务",-1))]),_:1})]),_:1}),e(p,{key:"g-advanced"},{title:t(()=>[...o[30]||(o[30]=[i("span",{class:"group-label"},"高 级",-1)])]),default:t(()=>[e(s,{key:"security"},{icon:t(()=>[e(n(ne))]),default:t(()=>[o[31]||(o[31]=l("安全中心",-1))]),_:1}),e(s,{key:"trust"},{icon:t(()=>[e(n(L))]),default:t(()=>[o[32]||(o[32]=l("信任与安全",-1))]),_:1}),e(s,{key:"audit"},{icon:t(()=>[e(n(se))]),default:t(()=>[o[33]||(o[33]=l("审计日志",-1))]),_:1}),e(s,{key:"did"},{icon:t(()=>[e(n(le))]),default:t(()=>[o[34]||(o[34]=l("DID 身份",-1))]),_:1}),e(s,{key:"permissions"},{icon:t(()=>[e(n(ie))]),default:t(()=>[o[35]||(o[35]=l("权限管理",-1))]),_:1}),e(s,{key:"p2p"},{icon:t(()=>[e(n(ae))]),default:t(()=>[o[36]||(o[36]=l("P2P 网络",-1))]),_:1}),e(s,{key:"backup"},{icon:t(()=>[e(n(de))]),default:t(()=>[o[37]||(o[37]=l("备份同步",-1))]),_:1}),e(s,{key:"git"},{icon:t(()=>[e(n(K))]),default:t(()=>[o[38]||(o[38]=l("Git 与数据",-1))]),_:1}),e(s,{key:"projects"},{icon:t(()=>[e(n(ue))]),default:t(()=>[o[39]||(o[39]=l("项目管理",-1))]),_:1}),e(s,{key:"crosschain"},{icon:t(()=>[e(n(re))]),default:t(()=>[o[40]||(o[40]=l("跨链桥",-1))]),_:1}),e(s,{key:"compliance"},{icon:t(()=>[e(n(L))]),default:t(()=>[o[41]||(o[41]=l("合规与情报",-1))]),_:1}),e(s,{key:"privacy"},{icon:t(()=>[e(n(ye))]),default:t(()=>[o[42]||(o[42]=l("隐私计算",-1))]),_:1}),e(s,{key:"inference"},{icon:t(()=>[e(n(pe))]),default:t(()=>[o[43]||(o[43]=l("推理网络",-1))]),_:1}),e(s,{key:"federation"},{icon:t(()=>[e(n(ke))]),default:t(()=>[o[44]||(o[44]=l("联邦强化",-1))]),_:1})]),_:1}),e(p,{key:"g-enterprise"},{title:t(()=>[...o[45]||(o[45]=[i("span",{class:"group-label"},"企 业",-1)])]),default:t(()=>[e(s,{key:"wallet"},{icon:t(()=>[e(n(ce))]),default:t(()=>[o[46]||(o[46]=l("钱包管理",-1))]),_:1}),e(s,{key:"organization"},{icon:t(()=>[e(n(me))]),default:t(()=>[o[47]||(o[47]=l("组织管理",-1))]),_:1}),e(s,{key:"tenant"},{icon:t(()=>[e(n(fe))]),default:t(()=>[o[48]||(o[48]=l("多租户 SaaS",-1))]),_:1}),e(s,{key:"sla"},{icon:t(()=>[e(n(j))]),default:t(()=>[o[49]||(o[49]=l("SLA 管理",-1))]),_:1}),e(s,{key:"analytics"},{icon:t(()=>[e(n(_e))]),default:t(()=>[o[50]||(o[50]=l("使用分析",-1))]),_:1}),e(s,{key:"templates"},{icon:t(()=>[e(n(ge))]),default:t(()=>[o[51]||(o[51]=l("模板中心",-1))]),_:1})]),_:1}),e(p,{key:"g-social"},{title:t(()=>[...o[52]||(o[52]=[i("span",{class:"group-label"},"社 交",-1)])]),default:t(()=>[e(s,{key:"community"},{icon:t(()=>[e(n(ve))]),default:t(()=>[o[53]||(o[53]=l("社区",-1))]),_:1}),e(s,{key:"governance"},{icon:t(()=>[e(n(Oe))]),default:t(()=>[o[54]||(o[54]=l("社区治理",-1))]),_:1}),e(s,{key:"reputation"},{icon:t(()=>[e(n(be))]),default:t(()=>[o[55]||(o[55]=l("声誉优化",-1))]),_:1}),e(s,{key:"recommend"},{icon:t(()=>[e(n(we))]),default:t(()=>[o[56]||(o[56]=l("智能推荐",-1))]),_:1})]),_:1}),e(p,{key:"g-media"},{title:t(()=>[...o[57]||(o[57]=[i("span",{class:"group-label"},"媒 体",-1)])]),default:t(()=>[e(s,{key:"video"},{icon:t(()=>[e(n(et))]),default:t(()=>[o[58]||(o[58]=l("视频剪辑",-1))]),_:1})]),_:1}),e(p,{key:"g-extension"},{title:t(()=>[...o[59]||(o[59]=[i("span",{class:"group-label"},"扩 展",-1)])]),default:t(()=>[e(s,{key:"rssfeed"},{icon:t(()=>[e(n(Ce))]),default:t(()=>[o[60]||(o[60]=l("RSS 订阅",-1))]),_:1}),e(s,{key:"webauthn"},{icon:t(()=>[e(n(Se))]),default:t(()=>[o[61]||(o[61]=l("身份认证",-1))]),_:1})]),_:1})],64))]),_:1},8,["selectedKeys","openKeys","theme","inline-collapsed"]),i("div",{class:S(["sidebar-footer",{collapsed:r.value}])},[e(Ee,{status:Re.value},null,8,["status"]),r.value?B("",!0):(a(),y("span",ut,v(Ie.value),1))],2)]),_:1},8,["collapsed"]),e(P,{class:"main-area"},{default:t(()=>[e(Me,{class:"app-header"},{default:t(()=>[i("div",rt,[i("div",{class:S(["scope-tag",c.value?"project":"global"])},[(a(),g(qe(c.value?n(O):n(N)))),i("span",null,v(c.value?n(f).projectName||"项目":"全局模式"),1),c.value&&n(f).projectRoot?(a(),g(U,{key:0,title:n(f).projectRoot},{default:t(()=>[e(n(tt),{class:"info-icon"})]),_:1},8,["title"])):B("",!0)],2)]),i("div",yt,[i("div",pt,[(a(!0),y(A,null,$e(n(Ze),(k,C)=>(a(),g(U,{key:C,title:k.label},{default:t(()=>[i("button",{class:S(["theme-btn",{active:xe.value===C}]),"data-theme-key":C,onClick:_t=>Ue(C)},v(k.icon),11,kt)]),_:2},1032,["title"]))),128))]),i("span",ct,v(n(Le)),1),e(Ge,{color:w.value==="connected"?"green":w.value==="connecting"?"orange":"red",class:"ws-tag"},{default:t(()=>[l(v(w.value==="connected"?"已连接":w.value==="connecting"?"连接中":"断开"),1)]),_:1},8,["color"])])]),_:1}),e(We,{class:"page-content"},{default:t(()=>[e(Ve)]),_:1})]),_:1})]),_:1})}}},Ct=he(mt,[["__scopeId","data-v-e0966d68"]]);export{Ct as default};
@@ -1 +0,0 @@
1
- .app-root[data-v-e0966d68]{height:100vh;background:var(--bg-base);overflow:hidden}.sidebar[data-v-e0966d68]{background:var(--bg-sidebar)!important;border-right:1px solid var(--border-color);transition:background .25s;height:100vh}[data-v-e0966d68] .ant-layout-sider-children{display:flex;flex-direction:column;overflow:hidden;height:100%}.main-area[data-v-e0966d68]{background:var(--bg-base);height:100vh;display:flex;flex-direction:column}.logo[data-v-e0966d68]{height:52px;display:flex;align-items:center;padding:0 18px;gap:10px;border-bottom:1px solid var(--border-color);overflow:hidden;white-space:nowrap;flex-shrink:0}.logo.collapsed[data-v-e0966d68]{padding:0;justify-content:center}.logo-icon[data-v-e0966d68]{width:24px;height:24px;flex-shrink:0;object-fit:contain}.logo-text[data-v-e0966d68]{color:var(--logo-text);font-weight:700;font-size:14px;letter-spacing:.01em}.mode-banner[data-v-e0966d68]{display:flex;align-items:center;gap:8px;padding:7px 10px;margin:8px 8px 4px;border-radius:7px;overflow:hidden}.mode-banner.project[data-v-e0966d68]{background:#1677ff1a;border:1px solid rgba(22,119,255,.2)}.mode-banner.global[data-v-e0966d68]{background:#722ed11a;border:1px solid rgba(114,46,209,.2)}.banner-icon[data-v-e0966d68]{font-size:13px;flex-shrink:0;color:#1677ff}.mode-banner.global .banner-icon[data-v-e0966d68]{color:#722ed1}.banner-info[data-v-e0966d68]{flex:1;min-width:0}.banner-name[data-v-e0966d68]{font-size:12px;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.banner-sub[data-v-e0966d68]{font-size:10px;color:#1677ff;margin-top:1px}.mode-banner.global .banner-name[data-v-e0966d68]{color:#c084fc}.mode-icon-sm[data-v-e0966d68]{display:flex;justify-content:center;padding:8px 0;font-size:14px}.side-menu[data-v-e0966d68]{border:none!important;margin-top:2px;-webkit-user-select:none;user-select:none;background:transparent!important;flex:1;overflow-y:auto;overflow-x:hidden}.group-label[data-v-e0966d68]{color:var(--group-title);font-size:10px;font-weight:700;letter-spacing:.12em;padding-left:6px}[data-v-e0966d68] .ant-menu-item-group-title{padding:8px 16px 2px!important}[data-v-e0966d68] .ant-menu-item{height:38px!important;line-height:38px!important;margin:1px 4px!important;border-radius:6px!important}.divider-sm[data-v-e0966d68]{margin:4px 0!important}.sidebar-footer[data-v-e0966d68]{flex-shrink:0;padding:8px 18px;display:flex;align-items:center;gap:8px;border-top:1px solid var(--border-color)}.sidebar-footer.collapsed[data-v-e0966d68]{justify-content:center;padding:8px 0}.footer-text[data-v-e0966d68]{color:var(--text-secondary);font-size:11px}.app-header[data-v-e0966d68]{background:var(--bg-header)!important;padding:0 20px!important;border-bottom:1px solid var(--border-color);height:50px!important;line-height:50px!important;display:flex!important;align-items:center!important;justify-content:space-between!important;box-shadow:0 1px 4px #0000000f}.header-left[data-v-e0966d68],.header-right[data-v-e0966d68]{display:flex;align-items:center;gap:10px}.scope-tag[data-v-e0966d68]{display:flex;align-items:center;gap:5px;padding:3px 10px;border-radius:5px;font-size:12px;font-weight:500}.scope-tag.project[data-v-e0966d68]{background:#1677ff1a;color:#1677ff;border:1px solid rgba(22,119,255,.2)}.scope-tag.global[data-v-e0966d68]{background:#722ed11a;color:#722ed1;border:1px solid rgba(114,46,209,.2)}.info-icon[data-v-e0966d68]{opacity:.45;cursor:help;margin-left:2px}.theme-switcher[data-v-e0966d68]{display:flex;align-items:center;gap:4px;background:var(--bg-card);border:1px solid var(--border-color);border-radius:20px;padding:3px 6px}.theme-btn[data-v-e0966d68]{width:26px;height:26px;border:none;border-radius:50%;cursor:pointer;background:transparent;font-size:14px;line-height:1;display:flex;align-items:center;justify-content:center;transition:background .15s,transform .15s;opacity:.55}.theme-btn[data-v-e0966d68]:hover{opacity:.9;transform:scale(1.15);background:var(--bg-card-hover)}.theme-btn.active[data-v-e0966d68]{opacity:1;transform:scale(1.1);background:var(--bg-card-hover);outline:2px solid var(--text-secondary)}.version-tag[data-v-e0966d68]{color:var(--text-muted);font-size:11px}.ws-tag[data-v-e0966d68]{margin:0!important;font-size:11px}.page-content[data-v-e0966d68]{padding:24px;overflow:auto;background:var(--bg-base);flex:1;min-height:0}