chainlesschain 0.163.8 → 0.164.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 (228) hide show
  1. package/package.json +4 -1
  2. package/scripts/macos-mcp-launcher-build.mjs +317 -0
  3. package/scripts/macos-mcp-launcher-postinstall.sh +54 -0
  4. package/scripts/macos-mcp-launcher-preinstall.sh +61 -0
  5. package/src/assets/web-panel/assets/{AIOps-CavM7W3k.js → AIOps-D2MEn7fI.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-CUvZGabQ.js → ActionButton-lCW_4Gf0.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-DeBnWnbe.js → Analytics-Bs7i-nsS.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-DbI5kxvd.js → AppLayout-CK7B6S_j.js} +5 -5
  9. package/src/assets/web-panel/assets/{Artifacts-D93bigKm.js → Artifacts-C8ILjpyo.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-CBNvfUZa.js → Audit-Bb9cNaWc.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-CJLyh_YU.js → BackgroundAgents-sC9ooXIf.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-D_0yoehD.js → Backup-D-DrsplT.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-TJxmbObW.js → BaseInput-uCNZpwSK.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-CE0dto1q.js → Chat-CsDK1uE9.js} +6 -6
  15. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CZ5-yYiD.js → ChatBubbleRenderer-OqSDt50w.js} +1 -1
  16. package/src/assets/web-panel/assets/{Checkbox-Ck1RVIVo.js → Checkbox-JhTXM1-K.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-qpoyf6DK.js → Codegen-BbzZLnyD.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-DUyPWjIE.js → Col-D4VW4m4j.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-D_S1BemS.js → Community-BXrYawxV.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-BjxeK-Gc.js → Compact-DCihGy1u.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-Dd3CEJsu.js → Compliance-DlyZ-lk8.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-B4QG7-ad.js → Cowork-DvGZrhbO.js} +3 -3
  23. package/src/assets/web-panel/assets/{Cron-BtZnids5.js → Cron-DUncZi8h.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-CHPfCBFD.js → Crosschain-C_hLuUcm.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-DT8DCEOK.js → DID-b6YSUqxr.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-COQab5_U.js → Dashboard-uvM15Cfb.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-BY1PsQuU.js → Dropdown-D1-Nd4qY.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer-CsuAuaq3.js → EmailListRenderer-8ApvL6Zc.js} +1 -1
  29. package/src/assets/web-panel/assets/{FamilyGuardDashboard-BqpinD-j.js → FamilyGuardDashboard-LYJt8811.js} +1 -1
  30. package/src/assets/web-panel/assets/{Federation-D0gkfQFv.js → Federation-BbI3HGpv.js} +1 -1
  31. package/src/assets/web-panel/assets/{FormItemContext-BqgE-axK.js → FormItemContext-DSoEKuFu.js} +1 -1
  32. package/src/assets/web-panel/assets/{GenericCardRenderer-D0hJ2KvC.js → GenericCardRenderer-B0S9OWd5.js} +1 -1
  33. package/src/assets/web-panel/assets/{Git-CmMB0uPY.js → Git-DIs9Zhf3.js} +2 -2
  34. package/src/assets/web-panel/assets/{Governance-BnVEI0Dk.js → Governance-jzZXrxcl.js} +1 -1
  35. package/src/assets/web-panel/assets/{Inference-YTAMihRP.js → Inference-JUPjf2ZI.js} +1 -1
  36. package/src/assets/web-panel/assets/{KnowledgeGraph-0ax7VHop.js → KnowledgeGraph-DxnfJvlP.js} +1 -1
  37. package/src/assets/web-panel/assets/{Logs-B9TRcokL.js → Logs-iXiz8BEE.js} +2 -2
  38. package/src/assets/web-panel/assets/MarkdownRenderer-GmB6DOr6.js +1 -0
  39. package/src/assets/web-panel/assets/{Marketplace-B6CSuD_H.js → Marketplace-Y3Xch312.js} +1 -1
  40. package/src/assets/web-panel/assets/{McpTools-CjMXvOVU.js → McpTools-D7kGGbO7.js} +3 -3
  41. package/src/assets/web-panel/assets/{Memory-CXRF71U3.js → Memory-Do_hVxzh.js} +2 -2
  42. package/src/assets/web-panel/assets/{MobileBridge-DQgNp_oS.js → MobileBridge-CtrR0Tas.js} +1 -1
  43. package/src/assets/web-panel/assets/MobileProjects-BL0Czcoj.js +1 -0
  44. package/src/assets/web-panel/assets/{Mtc-6hDTRPe1.js → Mtc-qo5QCTGd.js} +2 -2
  45. package/src/assets/web-panel/assets/{MtcAudit-BlVHU1DS.js → MtcAudit-cq5mnjYj.js} +2 -2
  46. package/src/assets/web-panel/assets/{Multisig-DP9pzEbV.js → Multisig-Bq0MAQHw.js} +3 -3
  47. package/src/assets/web-panel/assets/{NLProgramming-Djorh8EV.js → NLProgramming-DdWE6Vi2.js} +1 -1
  48. package/src/assets/web-panel/assets/{Notes-oLZ-JkUg.js → Notes-BxMBFcIp.js} +4 -4
  49. package/src/assets/web-panel/assets/{NotificationSettings-Cg288VH3.js → NotificationSettings-RTrAcbUe.js} +1 -1
  50. package/src/assets/web-panel/assets/{OrderTableRenderer-Bb1O3Ofr.js → OrderTableRenderer-DJbpGqzT.js} +1 -1
  51. package/src/assets/web-panel/assets/{Organization-CBdo-bHs.js → Organization-SQzIPdqC.js} +2 -2
  52. package/src/assets/web-panel/assets/{Overflow-qZdnVumx.js → Overflow-02yECh22.js} +1 -1
  53. package/src/assets/web-panel/assets/{P2P-D4kNfGNQ.js → P2P-BNg4pNCM.js} +2 -2
  54. package/src/assets/web-panel/assets/{PdhVaultBrowser-DnlMemM7.js → PdhVaultBrowser-BxPJZsD3.js} +5 -5
  55. package/src/assets/web-panel/assets/{Permissions-DHucHFBJ.js → Permissions-CLnDnPAz.js} +3 -3
  56. package/src/assets/web-panel/assets/{PersonalDataHub-BovlOIPR.js → PersonalDataHub-C5m0AjGf.js} +4 -4
  57. package/src/assets/web-panel/assets/{Pipeline-Deru3CQY.js → Pipeline-VwOf5Dhv.js} +1 -1
  58. package/src/assets/web-panel/assets/{Privacy-Bq5oTTbU.js → Privacy-CC0W2hZd.js} +1 -1
  59. package/src/assets/web-panel/assets/{ProjectInit-BfzxVWAz.js → ProjectInit-Dz893Bob.js} +2 -2
  60. package/src/assets/web-panel/assets/{ProjectSettings-CKC6XBtH.js → ProjectSettings-CxQkvl0k.js} +2 -2
  61. package/src/assets/web-panel/assets/Projects-DDAjkUkT.js +1 -0
  62. package/src/assets/web-panel/assets/{Providers-C_jx4TWX.js → Providers-DeB9IkxK.js} +1 -1
  63. package/src/assets/web-panel/assets/{QrScannerModal-BdIHeVGC.js → QrScannerModal-OCeoaswn.js} +1 -1
  64. package/src/assets/web-panel/assets/{QuickAsk-BwZwAcPD.js → QuickAsk-DenotaAj.js} +1 -1
  65. package/src/assets/web-panel/assets/{Recommend-BNTt0L-m.js → Recommend-Cies_jjI.js} +1 -1
  66. package/src/assets/web-panel/assets/{RemoteSession-Biyn2-Ro.js → RemoteSession-Dxzl5n2T.js} +3 -3
  67. package/src/assets/web-panel/assets/{Reputation-D6VpG32B.js → Reputation-CW0mvxgZ.js} +1 -1
  68. package/src/assets/web-panel/assets/{Row-D_74OvQQ.js → Row-SEd32qZU.js} +1 -1
  69. package/src/assets/web-panel/assets/{RssFeed-BTr0a-BQ.js → RssFeed-BSwnJ3Lm.js} +3 -3
  70. package/src/assets/web-panel/assets/{Search-C3MCFoNU.js → Search-xe2m8bkC.js} +1 -1
  71. package/src/assets/web-panel/assets/{Security-CqW9aJ6s.js → Security-Mq2F9Nro.js} +3 -3
  72. package/src/assets/web-panel/assets/{Services-Cw5GNaHF.js → Services-BKGw2V3P.js} +2 -2
  73. package/src/assets/web-panel/assets/{Skeleton-DZps5qeY.js → Skeleton-DW95-Rxf.js} +1 -1
  74. package/src/assets/web-panel/assets/{Skills-C6NQ1znT.js → Skills-CHgChCv_.js} +1 -1
  75. package/src/assets/web-panel/assets/{Sla-DFP8G2Sh.js → Sla-tKh6k3R7.js} +1 -1
  76. package/src/assets/web-panel/assets/{SpeechSettings-ESt6MB6v.js → SpeechSettings-D6UL3dA5.js} +1 -1
  77. package/src/assets/web-panel/assets/{SyncSettings-BHnN98aM.js → SyncSettings-D0Fw8fVL.js} +2 -2
  78. package/src/assets/web-panel/assets/{Tasks-NiSCaOf-.js → Tasks-20x1GB3D.js} +1 -1
  79. package/src/assets/web-panel/assets/{Templates-DsKFhW2C.js → Templates-DJ-lts-a.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tenant-CQ0E0ze5.js → Tenant-BFdGpbs7.js} +1 -1
  81. package/src/assets/web-panel/assets/{Terminal-D_rBu_by.js → Terminal-Xpx61vHL.js} +2 -2
  82. package/src/assets/web-panel/assets/{TimelineRenderer-D3Vm4Po4.js → TimelineRenderer-C6UIvyZQ.js} +1 -1
  83. package/src/assets/web-panel/assets/{Tokens-DNTxRH6q.js → Tokens-Dellq08f.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trigger-Dgprz1ms.js → Trigger-VKw8d0J-.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trust-B2rUnVBD.js → Trust-DNftdKT5.js} +1 -1
  86. package/src/assets/web-panel/assets/{UkeySign-DEGQNc6_.js → UkeySign-DX9VAKJI.js} +1 -1
  87. package/src/assets/web-panel/assets/{VideoEditing-jlsAx3Eh.js → VideoEditing-B2h3jO8q.js} +1 -1
  88. package/src/assets/web-panel/assets/{Wallet-8jQih1ij.js → Wallet-CjGkof7f.js} +4 -4
  89. package/src/assets/web-panel/assets/{WebAuthn-XLeO6xIB.js → WebAuthn-2Zfcu55P.js} +4 -4
  90. package/src/assets/web-panel/assets/{WorkflowEditor-De_dgDAG.js → WorkflowEditor-B9eZ8UxZ.js} +1 -1
  91. package/src/assets/web-panel/assets/{chat-CI19R_Sk.js → chat-CQNfD-YO.js} +1 -1
  92. package/src/assets/web-panel/assets/{colors-DsYTOYN3.js → colors-D4usyFT2.js} +1 -1
  93. package/src/assets/web-panel/assets/{compact-item-CM3-t_Qr.js → compact-item-s4TpjvjX.js} +1 -1
  94. package/src/assets/web-panel/assets/{createContext-BjxlBRZv.js → createContext-BRCSvYxj.js} +1 -1
  95. package/src/assets/web-panel/assets/devWarning-DKJjSWRn.js +1 -0
  96. package/src/assets/web-panel/assets/{hasIn-RDaWX_4i.js → hasIn-AdkUbkV-.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BN6UPD2E.js → index--00U6vXZ.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CiECJi-Q.js → index-B2V-eKfK.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CnHH7bnD.js → index-B4JJCfQ2.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CjTrRt13.js → index-BIoG5yYf.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-Dxge-xWl.js → index-BMcimU-2.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-9R6BxAr0.js → index-BPhkFZ1I.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BHNYPO0b.js → index-BQ3DXBtD.js} +3 -3
  104. package/src/assets/web-panel/assets/{index-Cpqm1qfU.js → index-Bad4VNvz.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-B9O9YyWE.js → index-BgiXR_-_.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-B5REnKt8.js → index-BtobShro.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-D6sm5-Xq.js → index-Bw2MEnUk.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DcPFB8qJ.js → index-C1mJtE6q.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BKJr-TZp.js → index-C484EJiS.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Drlnwr8F.js → index-C5KAQFPQ.js} +1 -1
  111. package/src/assets/web-panel/assets/index-C61cnl3K.js +1 -0
  112. package/src/assets/web-panel/assets/{index-Dsij_KsN.js → index-C7Y8Aluc.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-IeiL9RKc.js → index-CCsM_Ybx.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-B-Z8eFUJ.js → index-CJCFe2Qf.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CyOGN6a5.js → index-CJVEOa4i.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-B0PMlbMs.js → index-CJdQrZth.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-nAH87mQP.js → index-CKC1t3Ic.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-BGqqJfL0.js → index-CQhAVU5t.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-Cd9OJhHG.js → index-CYdoQsa1.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-D0zcy54x.js → index-Cduu2Hhr.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DIUnNOjG.js → index-CkwiSLhU.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CVQMeiwH.js → index-Cvyt-zhm.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BlT2VAEK.js → index-D2GjI2oe.js} +1 -1
  124. package/src/assets/web-panel/assets/index-D4XFHxBr.js +1 -0
  125. package/src/assets/web-panel/assets/{index-C0yx-jtQ.js → index-DARsAyUp.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-Bi46Xu4u.js → index-DVKfQ0Ux.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-Cd3euP_4.js → index-DZT36ZYq.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BCnZyIMA.js → index-D_XBHopw.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-C4gkzxkw.js → index-DdCB70SS.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-B7WBt_4T.js → index-DzRjHxEv.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DX7tuWVJ.js → index-MMN9V6JF.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DoQA0-52.js → index-RfMr79MW.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DXXtGMUJ.js → index-_IRVsV9X.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-pPL66J85.js → index-nXyk8GZ9.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-DyIWssPC.js → index-s_buFMEG.js} +1 -1
  136. package/src/assets/web-panel/assets/{initDefaultProps-BTL88of4.js → initDefaultProps-Blmpk7HL.js} +1 -1
  137. package/src/assets/web-panel/assets/{motion-BUB2pXwB.js → motion-DPBJMv1n.js} +1 -1
  138. package/src/assets/web-panel/assets/{move-egCkkOMm.js → move-ButdzCM7.js} +1 -1
  139. package/src/assets/web-panel/assets/{mtc-parser-DAWhZC8c.js → mtc-parser-cyRC_QCe.js} +1 -1
  140. package/src/assets/web-panel/assets/{omit-CvOxe_6d.js → omit-1epSV7hz.js} +1 -1
  141. package/src/assets/web-panel/assets/{pickAttrs-DZUSLZ5Z.js → pickAttrs-DuPY8xJs.js} +1 -1
  142. package/src/assets/web-panel/assets/{placementArrow-BERxGNMY.js → placementArrow-6XZqarhe.js} +1 -1
  143. package/src/assets/web-panel/assets/{responsiveObserve-DZuDfZ9n.js → responsiveObserve-B40pXBWM.js} +1 -1
  144. package/src/assets/web-panel/assets/{slide-DO756sgI.js → slide-jbZ9Wu4n.js} +1 -1
  145. package/src/assets/web-panel/assets/{statusUtils-BRQlIz28.js → statusUtils-BKQQcVy4.js} +1 -1
  146. package/src/assets/web-panel/assets/{styleChecker-DCSfdybl.js → styleChecker-NiKfWjUT.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFlexGapSupport-LD8dWVve.js → useFlexGapSupport-bQUCvPeb.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFs-BX9uW2LK.js → useFs-CUGji7ph.js} +1 -1
  149. package/src/assets/web-panel/assets/{usePersonalDataHub-BPSlPuHU.js → usePersonalDataHub-4veyN2N2.js} +1 -1
  150. package/src/assets/web-panel/assets/{vnode-BmOILC9V.js → vnode-1-nLug-Z.js} +1 -1
  151. package/src/assets/web-panel/assets/{zoom-1iKowKGg.js → zoom-dhCeRDMo.js} +1 -1
  152. package/src/assets/web-panel/index.html +1 -1
  153. package/src/command-help-index.json +3 -3
  154. package/src/commands/cowork.js +174 -19
  155. package/src/commands/permissions.js +240 -16
  156. package/src/commands/plugin.js +1293 -56
  157. package/src/commands/session-location.js +276 -0
  158. package/src/commands/session.js +2 -0
  159. package/src/data/changelog.json +15 -2
  160. package/src/gateways/ws/action-protocol.js +35 -10
  161. package/src/gateways/ws/remote-session-protocol.js +24 -1
  162. package/src/gateways/ws/ws-agent-handler.js +12 -0
  163. package/src/gateways/ws/ws-server.js +48 -12
  164. package/src/harness/jsonl-session-store.js +341 -24
  165. package/src/harness/mcp-client.js +8 -1
  166. package/src/harness/remote-session-audit.js +1 -0
  167. package/src/harness/remote-session-crypto.js +210 -2
  168. package/src/harness/remote-session-registry.js +159 -6
  169. package/src/harness/session-list-index.js +233 -14
  170. package/src/lib/agent-authority.js +6 -0
  171. package/src/lib/background-agent-keeper-client.js +248 -0
  172. package/src/lib/background-agent-keeper-protocol.js +147 -0
  173. package/src/lib/background-agent-supervisor.js +520 -40
  174. package/src/lib/background-interaction-resolver.js +12 -0
  175. package/src/lib/background-turn-bootstrap-protocol.js +126 -0
  176. package/src/lib/cowork-workflow.js +336 -16
  177. package/src/lib/dynamic-workflow-facade.js +648 -0
  178. package/src/lib/execution-location-contract.js +551 -0
  179. package/src/lib/execution-location-runtime.js +130 -0
  180. package/src/lib/ide-context.js +94 -6
  181. package/src/lib/mcp-stdio-package-materialization.js +166 -14
  182. package/src/lib/packer/pkg-config-generator.js +2 -0
  183. package/src/lib/permission-authority.js +77 -0
  184. package/src/lib/permission-side-effect-center.js +495 -0
  185. package/src/lib/plugin-runtime/install.js +514 -13
  186. package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
  187. package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
  188. package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
  189. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
  190. package/src/lib/plugin-security.js +60 -3
  191. package/src/lib/process-execution-broker/index.js +1095 -57
  192. package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
  193. package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
  194. package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
  195. package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
  196. package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
  197. package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
  198. package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
  199. package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
  200. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  201. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  202. package/src/lib/process-execution-broker/windows-sandbox.cs +50 -4
  203. package/src/lib/public-ide-capability-manifest.js +3 -0
  204. package/src/lib/remote-approval-bridge.js +123 -17
  205. package/src/lib/remote-membership-authority.js +632 -0
  206. package/src/lib/remote-membership-coordinator.js +2409 -0
  207. package/src/lib/remote-membership-host-store.js +1750 -0
  208. package/src/lib/scoped-permission-store.js +369 -0
  209. package/src/lib/session-anti-rollback-anchor.js +262 -5
  210. package/src/lib/sub-agent-context.js +4 -0
  211. package/src/lib/workflow-definition-contract.js +149 -0
  212. package/src/repl/agent-repl.js +41 -7
  213. package/src/repl/chat-repl.js +2 -0
  214. package/src/repl/clipboard-image.js +735 -16
  215. package/src/repl/ide-status.js +1 -1
  216. package/src/repl/prompt-interactions.js +59 -6
  217. package/src/runtime/agent-core.js +83 -3
  218. package/src/runtime/headless-runner.js +30 -25
  219. package/src/runtime/headless-stream.js +32 -25
  220. package/src/workers/background-agent-keeper.js +498 -0
  221. package/src/workers/background-agent-worker.js +358 -13
  222. package/src/workers/background-turn-bootstrap.js +143 -0
  223. package/src/assets/web-panel/assets/MarkdownRenderer-yySN5YNM.js +0 -1
  224. package/src/assets/web-panel/assets/MobileProjects-DlPwcCbq.js +0 -1
  225. package/src/assets/web-panel/assets/Projects-CMolGhae.js +0 -1
  226. package/src/assets/web-panel/assets/devWarning-S1ld2LwU.js +0 -1
  227. package/src/assets/web-panel/assets/index-Drz6yq0m.js +0 -1
  228. package/src/assets/web-panel/assets/index-uWiUs7S_.js +0 -1
@@ -52,6 +52,22 @@ import {
52
52
  withSessionHostDelegatedWriteAuthority,
53
53
  withSessionHostRecoveryLease,
54
54
  } from "../lib/session-host-lease.js";
55
+ import {
56
+ BACKGROUND_TURN_BOOTSTRAP_ENV,
57
+ BACKGROUND_TURN_BOOTSTRAP_READY,
58
+ BACKGROUND_TURN_BOOTSTRAP_RELEASE,
59
+ createBackgroundTurnBootstrapMessage,
60
+ matchesBackgroundTurnBootstrapMessage,
61
+ normalizeBackgroundTurnBootstrapAuthority,
62
+ normalizeBackgroundTurnBootstrapBinding,
63
+ } from "../lib/background-turn-bootstrap-protocol.js";
64
+ import { connectBackgroundAgentKeeper } from "../lib/background-agent-keeper-client.js";
65
+
66
+ const TURN_BOOTSTRAP_MODULE_URL = new URL(
67
+ "./background-turn-bootstrap.js",
68
+ import.meta.url,
69
+ ).href;
70
+ const TURN_BOOTSTRAP_IMPORT_ARGUMENT = `--import=${TURN_BOOTSTRAP_MODULE_URL}`;
55
71
 
56
72
  const jobFile = process.argv[2];
57
73
  let job;
@@ -65,10 +81,14 @@ let turnCount = 0;
65
81
  let lastExit = { code: 0, signal: null };
66
82
  let transportState = null;
67
83
  let detachInteractionHandler = null;
84
+ let detachTurnBootstrapHandler = null;
85
+ let keeperClient = null;
86
+ let activeKeeperTurn = null;
68
87
  let interactionJournal = null;
69
88
  let interactionFinalSweep = null;
70
89
  let turnLaunchUncertainty = null;
71
90
  let turnLaunchSettlement = null;
91
+ let initialTurnStarted = false;
72
92
  const promptQueue = [];
73
93
  // P0-2: 保存 pending 的交互请求,等 attach 客户端连接后转发
74
94
  const pendingInteractions = new Map();
@@ -135,6 +155,109 @@ export function attachTurnChildTerminationSettlement(
135
155
  };
136
156
  }
137
157
 
158
+ /**
159
+ * Release a pre-main turn child only after its actual runtime PID is durably
160
+ * committed and every worker listener needed to supervise it is installed.
161
+ * The ChildProcess PID may name a Windows sandbox helper, so the actual Node
162
+ * PID arrives over the nonce-bound private IPC channel instead of being
163
+ * inferred from `child.pid`.
164
+ */
165
+ export function attachTurnChildBootstrapRelease(
166
+ childProcess,
167
+ authority,
168
+ commitReady,
169
+ onFailure = () => {},
170
+ ) {
171
+ if (!childProcess || typeof childProcess.on !== "function") {
172
+ throw new TypeError("turn bootstrap child must expose message events");
173
+ }
174
+ if (typeof childProcess.send !== "function") {
175
+ throw new TypeError("turn bootstrap child must expose dedicated IPC");
176
+ }
177
+ if (typeof commitReady !== "function") {
178
+ throw new TypeError("turn bootstrap durable commit callback is required");
179
+ }
180
+ if (typeof onFailure !== "function") {
181
+ throw new TypeError("turn bootstrap failure callback must be a function");
182
+ }
183
+ const expected = normalizeBackgroundTurnBootstrapAuthority(authority);
184
+ let releasedBinding = null;
185
+ let pendingBinding = null;
186
+ let failed = false;
187
+ let detached = false;
188
+
189
+ const failOnce = (error) => {
190
+ if (failed || detached) return;
191
+ failed = true;
192
+ onFailure(error instanceof Error ? error : new Error(String(error)));
193
+ };
194
+ const onMessage = (message) => {
195
+ if (message?.type !== BACKGROUND_TURN_BOOTSTRAP_READY) return;
196
+ if (
197
+ !matchesBackgroundTurnBootstrapMessage(
198
+ message,
199
+ BACKGROUND_TURN_BOOTSTRAP_READY,
200
+ expected,
201
+ )
202
+ ) {
203
+ failOnce(new Error("background turn bootstrap ready binding mismatch"));
204
+ return;
205
+ }
206
+ const readyBinding = normalizeBackgroundTurnBootstrapBinding(message);
207
+ if (releasedBinding) {
208
+ if (readyBinding.pid !== releasedBinding.pid) {
209
+ failOnce(new Error("background turn bootstrap runtime pid changed"));
210
+ }
211
+ // READY is retransmitted until the child observes RELEASE. Matching
212
+ // duplicates are idempotent; never answer with a second RELEASE.
213
+ return;
214
+ }
215
+ if (pendingBinding) {
216
+ if (readyBinding.pid !== pendingBinding.pid) {
217
+ failOnce(new Error("background turn bootstrap runtime pid changed"));
218
+ }
219
+ return;
220
+ }
221
+ pendingBinding = readyBinding;
222
+ Promise.resolve()
223
+ .then(() => commitReady(readyBinding))
224
+ .then((committed) => {
225
+ if (failed || detached) return;
226
+ if (committed !== true) {
227
+ failOnce(
228
+ new Error("background turn runtime pid commit was rejected"),
229
+ );
230
+ return;
231
+ }
232
+ releasedBinding = readyBinding;
233
+ try {
234
+ childProcess.send(
235
+ createBackgroundTurnBootstrapMessage(
236
+ BACKGROUND_TURN_BOOTSTRAP_RELEASE,
237
+ readyBinding,
238
+ ),
239
+ (error) => {
240
+ if (error) failOnce(error);
241
+ },
242
+ );
243
+ } catch (error) {
244
+ failOnce(error);
245
+ }
246
+ })
247
+ .catch(failOnce);
248
+ };
249
+ const detach = () => {
250
+ if (detached) return;
251
+ detached = true;
252
+ childProcess.off?.("message", onMessage);
253
+ };
254
+
255
+ childProcess.on("message", onMessage);
256
+ childProcess.once?.("exit", detach);
257
+ childProcess.once?.("disconnect", detach);
258
+ return detach;
259
+ }
260
+
138
261
  /**
139
262
  * Deliver an already-durable interaction outcome after best-effort cleanup of
140
263
  * the worker-state projection.
@@ -398,6 +521,8 @@ function finalize(code, signal, errorMessage) {
398
521
  }
399
522
  }
400
523
  const done = () => {
524
+ keeperClient?.close();
525
+ keeperClient = null;
401
526
  try {
402
527
  log?.close();
403
528
  } catch {
@@ -650,7 +775,20 @@ function startTurn(argv, promptText) {
650
775
  // Private spawn-generation binding for the dedicated child IPC channel.
651
776
  // It is never persisted in state or exposed through attach transports.
652
777
  const turnIpcToken = randomBytes(32).toString("hex");
778
+ const turnBootstrapNonce = randomBytes(32).toString("hex");
653
779
  let turnLaunchAttempt = 0;
780
+ let turnTerminated = false;
781
+ let keeperBootstrapStarted = false;
782
+ let keeperBootstrapOutcome = null;
783
+ let resolveKeeperBootstrap;
784
+ const keeperBootstrapSettled = new Promise((resolvePromise) => {
785
+ resolveKeeperBootstrap = resolvePromise;
786
+ });
787
+ const settleKeeperBootstrap = (outcome) => {
788
+ if (keeperBootstrapOutcome) return;
789
+ keeperBootstrapOutcome = outcome;
790
+ resolveKeeperBootstrap(outcome);
791
+ };
654
792
  let prepared;
655
793
  try {
656
794
  prepared = mutateBackgroundAgentState(job.id, (current) => {
@@ -723,13 +861,17 @@ function startTurn(argv, promptText) {
723
861
  agentStartedAt = Date.now();
724
862
  spawned = executionBroker.spawn(
725
863
  process.execPath,
726
- [job.cliEntry, ...argv],
864
+ [TURN_BOOTSTRAP_IMPORT_ARGUMENT, job.cliEntry, ...argv],
727
865
  {
728
866
  cwd: job.cwd,
729
867
  env: {
730
868
  ...process.env,
731
869
  CC_BACKGROUND_AGENT_ID: job.id,
732
870
  CC_BACKGROUND_TURN_IPC_NONCE: turnIpcToken,
871
+ [BACKGROUND_TURN_BOOTSTRAP_ENV.nonce]: turnBootstrapNonce,
872
+ [BACKGROUND_TURN_BOOTSTRAP_ENV.workerGeneration]:
873
+ job.workerGeneration,
874
+ [BACKGROUND_TURN_BOOTSTRAP_ENV.attempt]: String(turnLaunchAttempt),
733
875
  },
734
876
  stdio: ["ignore", log.fd, log.fd, "ipc"],
735
877
  windowsHide: true,
@@ -756,6 +898,17 @@ function startTurn(argv, promptText) {
756
898
  },
757
899
  agentPid: spawned.pid,
758
900
  agentStartedAt,
901
+ agentRuntimePid: null,
902
+ agentRuntimeStartedAt: null,
903
+ turnBootstrapStatus: "awaiting-ready",
904
+ turnBootstrapCommittedAt: null,
905
+ turnKeeperStatus: "waiting-for-runtime",
906
+ turnKeeperPid: null,
907
+ turnKeeperArmedAt: null,
908
+ turnKeeperCleanupReason: null,
909
+ turnKeeperCleanupRequestedAt: null,
910
+ turnKeeperCleanupConfirmedAt: null,
911
+ turnKeeperCleanupError: null,
759
912
  turnLaunchIntent: null,
760
913
  turnLaunchResolution: {
761
914
  token: turnLaunchToken,
@@ -982,38 +1135,190 @@ function startTurn(argv, promptText) {
982
1135
  },
983
1136
  );
984
1137
 
1138
+ detachTurnBootstrapHandler = attachTurnChildBootstrapRelease(
1139
+ child,
1140
+ {
1141
+ nonce: turnBootstrapNonce,
1142
+ workerGeneration: job.workerGeneration,
1143
+ attempt: turnLaunchAttempt,
1144
+ },
1145
+ async (readyBinding) => {
1146
+ keeperBootstrapStarted = true;
1147
+ const committedAt = Date.now();
1148
+ const commit = mutateBackgroundAgentState(job.id, (current) => {
1149
+ if (
1150
+ !current ||
1151
+ current.status !== "running" ||
1152
+ current.stopRequestedAt ||
1153
+ current.workerGeneration !== job.workerGeneration ||
1154
+ Number(current.workerClaimedPid) !== process.pid ||
1155
+ current.turnLaunchResolution?.token !== turnLaunchToken ||
1156
+ Number(current.turnLaunchResolution?.attempt) !== turnLaunchAttempt ||
1157
+ current.turnLaunchResolution?.outcome !== "spawned" ||
1158
+ Number(current.agentPid) !== Number(spawned.pid)
1159
+ ) {
1160
+ return null;
1161
+ }
1162
+ return {
1163
+ ...current,
1164
+ agentRuntimePid: readyBinding.pid,
1165
+ // The host timestamp immediately before native spawn is a positive
1166
+ // lower-bound anchor for the runtime creation window. Destructive
1167
+ // identity checks still require a fresh OS creation-time probe.
1168
+ agentRuntimeStartedAt: agentStartedAt,
1169
+ turnBootstrapStatus: "awaiting-keeper",
1170
+ turnBootstrapCommittedAt: null,
1171
+ turnKeeperStatus: "arming",
1172
+ };
1173
+ });
1174
+ if (!commit.applied || !keeperClient) {
1175
+ settleKeeperBootstrap("failed");
1176
+ return false;
1177
+ }
1178
+ if (turnTerminated || child !== spawned || turnLaunchSettlement) {
1179
+ settleKeeperBootstrap("retired");
1180
+ return false;
1181
+ }
1182
+ const keeperTurn = {
1183
+ id: job.id,
1184
+ workerGeneration: job.workerGeneration,
1185
+ turnLaunchToken,
1186
+ attempt: turnLaunchAttempt,
1187
+ agentPid: Number(spawned.pid),
1188
+ agentStartedAt,
1189
+ agentRuntimePid: readyBinding.pid,
1190
+ agentRuntimeStartedAt: agentStartedAt,
1191
+ };
1192
+ try {
1193
+ await keeperClient.arm(keeperTurn);
1194
+ } catch (error) {
1195
+ settleKeeperBootstrap("failed");
1196
+ throw error;
1197
+ }
1198
+ activeKeeperTurn = keeperTurn;
1199
+ if (turnTerminated || child !== spawned || turnLaunchSettlement) {
1200
+ await keeperClient.retire(keeperTurn);
1201
+ if (activeKeeperTurn === keeperTurn) activeKeeperTurn = null;
1202
+ settleKeeperBootstrap("retired");
1203
+ return false;
1204
+ }
1205
+ const released = mutateBackgroundAgentState(job.id, (current) => {
1206
+ if (
1207
+ !current ||
1208
+ current.status !== "running" ||
1209
+ current.stopRequestedAt ||
1210
+ current.workerGeneration !== job.workerGeneration ||
1211
+ Number(current.workerClaimedPid) !== process.pid ||
1212
+ current.turnLaunchResolution?.token !== turnLaunchToken ||
1213
+ Number(current.turnLaunchResolution?.attempt) !== turnLaunchAttempt ||
1214
+ current.turnLaunchResolution?.outcome !== "spawned" ||
1215
+ Number(current.agentPid) !== Number(spawned.pid) ||
1216
+ Number(current.agentRuntimePid) !== readyBinding.pid ||
1217
+ current.turnKeeperStatus !== "armed" ||
1218
+ Number(current.turnKeeperPid) !== Number(current.keeperPid)
1219
+ ) {
1220
+ return null;
1221
+ }
1222
+ return {
1223
+ ...current,
1224
+ turnBootstrapStatus: "released",
1225
+ turnBootstrapCommittedAt: committedAt,
1226
+ };
1227
+ });
1228
+ if (!released.applied) {
1229
+ await keeperClient.retire(keeperTurn);
1230
+ if (activeKeeperTurn === keeperTurn) activeKeeperTurn = null;
1231
+ settleKeeperBootstrap("failed");
1232
+ return false;
1233
+ }
1234
+ settleKeeperBootstrap("released");
1235
+ return true;
1236
+ },
1237
+ (error) => {
1238
+ settleKeeperBootstrap("failed");
1239
+ detachInteractionHandler?.();
1240
+ detachInteractionHandler = null;
1241
+ if (
1242
+ keeperBootstrapOutcome !== "retired" &&
1243
+ (child === spawned || turnTerminated) &&
1244
+ !turnLaunchSettlement
1245
+ ) {
1246
+ beginTurnLaunchSettlement({
1247
+ owned: spawned,
1248
+ error,
1249
+ turnLaunchToken,
1250
+ turnLaunchAttempt,
1251
+ agentStartedAt,
1252
+ });
1253
+ }
1254
+ },
1255
+ );
1256
+
985
1257
  attachTurnChildTerminationSettlement(
986
1258
  child,
987
1259
  ({ code, signal, errorMessage }) => {
1260
+ turnTerminated = true;
988
1261
  lastExit = {
989
1262
  code,
990
1263
  signal,
991
1264
  ...(errorMessage ? { errorMessage } : {}),
992
1265
  };
993
1266
  child = null;
1267
+ detachTurnBootstrapHandler?.();
1268
+ detachTurnBootstrapHandler = null;
994
1269
  // 清理交互处理器
995
1270
  detachInteractionHandler?.();
996
1271
  detachInteractionHandler = null;
997
1272
  // Reject any request that survived an abnormal child exit. Normal
998
1273
  // responses remove themselves from this map before the turn continues.
999
- for (const [requestId, pending] of pendingInteractions) {
1274
+ for (const pending of pendingInteractions.values()) {
1000
1275
  const error = new Error("Agent exited");
1001
1276
  error.code = "INTERACTION_CHILD_EXITED";
1002
1277
  pending.deliverRejected?.(error);
1003
1278
  }
1004
1279
  pendingInteractions.clear();
1005
- beginFinalInteractionSweep(() => {
1006
- server?.broadcast({
1007
- type: "turn-ended",
1008
- turn: turnCount,
1009
- exitCode: code,
1280
+ const finishTurn = () =>
1281
+ beginFinalInteractionSweep(() => {
1282
+ server?.broadcast({
1283
+ type: "turn-ended",
1284
+ turn: turnCount,
1285
+ exitCode: code,
1286
+ });
1287
+ if (lastExit.errorMessage) {
1288
+ finalize(1, signal, lastExit.errorMessage);
1289
+ } else {
1290
+ maybeContinue();
1291
+ }
1010
1292
  });
1011
- if (lastExit.errorMessage) {
1012
- finalize(1, signal, lastExit.errorMessage);
1013
- } else {
1014
- maybeContinue();
1293
+ void (async () => {
1294
+ if (keeperBootstrapStarted) {
1295
+ const outcome = await keeperBootstrapSettled;
1296
+ // The bootstrap failure callback owns process-tree settlement and
1297
+ // must not race a normal continuation into the next queued turn.
1298
+ if (outcome === "failed") return;
1015
1299
  }
1016
- });
1300
+ if (turnLaunchSettlement) return;
1301
+ const keeperTurn = activeKeeperTurn;
1302
+ if (!keeperTurn || !keeperClient) {
1303
+ finishTurn();
1304
+ return;
1305
+ }
1306
+ try {
1307
+ await keeperClient.retire(keeperTurn);
1308
+ if (activeKeeperTurn === keeperTurn) activeKeeperTurn = null;
1309
+ finishTurn();
1310
+ } catch (error) {
1311
+ if (!turnLaunchSettlement) {
1312
+ beginTurnLaunchSettlement({
1313
+ owned: spawned,
1314
+ error,
1315
+ turnLaunchToken,
1316
+ turnLaunchAttempt,
1317
+ agentStartedAt,
1318
+ });
1319
+ }
1320
+ }
1321
+ })();
1017
1322
  },
1018
1323
  );
1019
1324
  return true;
@@ -1059,6 +1364,17 @@ function maybeContinue() {
1059
1364
  uncertainSideEffects: 0,
1060
1365
  agentPid: null,
1061
1366
  agentStartedAt: null,
1367
+ agentRuntimePid: null,
1368
+ agentRuntimeStartedAt: null,
1369
+ turnBootstrapStatus: null,
1370
+ turnBootstrapCommittedAt: null,
1371
+ turnKeeperStatus: null,
1372
+ turnKeeperPid: null,
1373
+ turnKeeperArmedAt: null,
1374
+ turnKeeperCleanupReason: null,
1375
+ turnKeeperCleanupRequestedAt: null,
1376
+ turnKeeperCleanupConfirmedAt: null,
1377
+ turnKeeperCleanupError: null,
1062
1378
  heartbeatAt: Date.now(),
1063
1379
  });
1064
1380
  server.broadcast({ type: "idle", turn: turnCount });
@@ -1147,7 +1463,11 @@ async function main() {
1147
1463
  }
1148
1464
  promptQueue.push(text);
1149
1465
  const queued = promptQueue.length;
1150
- if (!child) maybeContinue();
1466
+ // The transport is intentionally published before keeper/bootstrap
1467
+ // readiness. Prompts arriving in that window belong behind turn 1;
1468
+ // consuming one immediately would skip the launch job and make the
1469
+ // queue cap timing-dependent.
1470
+ if (!child && initialTurnStarted) maybeContinue();
1151
1471
  return { queued };
1152
1472
  },
1153
1473
  onStop: () => {
@@ -1265,12 +1585,37 @@ async function main() {
1265
1585
  finalize(launchReadiness === "timeout" ? 1 : 0, null);
1266
1586
  return;
1267
1587
  }
1588
+ if (!job.keeper) {
1589
+ throw new Error("background agent keeper launch authority is missing");
1590
+ }
1591
+ keeperClient = await connectBackgroundAgentKeeper({
1592
+ id: job.id,
1593
+ workerGeneration: job.workerGeneration,
1594
+ workerPid: process.pid,
1595
+ pipePath: job.keeper.pipePath,
1596
+ token: job.keeper.token,
1597
+ onDisconnect(error, keeperTurn) {
1598
+ if (finalized || turnLaunchSettlement) return;
1599
+ if (child && keeperTurn) {
1600
+ beginTurnLaunchSettlement({
1601
+ owned: child,
1602
+ error,
1603
+ turnLaunchToken: keeperTurn.turnLaunchToken,
1604
+ turnLaunchAttempt: keeperTurn.attempt,
1605
+ agentStartedAt: keeperTurn.agentStartedAt,
1606
+ });
1607
+ return;
1608
+ }
1609
+ finalize(1, null, error?.message || "background keeper disconnected");
1610
+ },
1611
+ });
1268
1612
  // Launch finalization can take long enough for an external stop/remove to
1269
1613
  // win after bootstrap. Re-claim immediately before the first native turn.
1270
1614
  if (!writeHeartbeat()) {
1271
1615
  finalize(0, null);
1272
1616
  return;
1273
1617
  }
1618
+ initialTurnStarted = true;
1274
1619
  if (!startTurn(job.argv, null)) finalize(0, null);
1275
1620
  }
1276
1621
 
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Pre-main barrier for one background-agent turn.
3
+ *
4
+ * Node loads this module through `--import` before executing the real CLI
5
+ * entrypoint. Top-level await keeps both ESM and CommonJS entry semantics
6
+ * intact while making execution contingent on the worker's durable PID
7
+ * commit and listener installation.
8
+ */
9
+
10
+ import { writeSync } from "node:fs";
11
+ import {
12
+ BACKGROUND_TURN_BOOTSTRAP_ENV,
13
+ BACKGROUND_TURN_BOOTSTRAP_READY,
14
+ BACKGROUND_TURN_BOOTSTRAP_RELEASE,
15
+ backgroundTurnBootstrapBindingFromEnvironment,
16
+ clearBackgroundTurnBootstrapEnvironment,
17
+ createBackgroundTurnBootstrapMessage,
18
+ matchesBackgroundTurnBootstrapMessage,
19
+ removeBackgroundTurnBootstrapImport,
20
+ } from "../lib/background-turn-bootstrap-protocol.js";
21
+
22
+ const DEFAULT_RELEASE_TIMEOUT_MS = 30_000;
23
+ const TEST_RELEASE_TIMEOUT_MAX_MS = 2_000;
24
+
25
+ function releaseTimeoutMs() {
26
+ if (process.env.NODE_ENV !== "test") return DEFAULT_RELEASE_TIMEOUT_MS;
27
+ const requested = Number(
28
+ process.env[BACKGROUND_TURN_BOOTSTRAP_ENV.testTimeoutMs],
29
+ );
30
+ if (!Number.isFinite(requested)) return DEFAULT_RELEASE_TIMEOUT_MS;
31
+ return Math.max(10, Math.min(TEST_RELEASE_TIMEOUT_MAX_MS, requested));
32
+ }
33
+
34
+ function failClosed(message) {
35
+ try {
36
+ writeSync(2, `[background-turn-bootstrap] ${message}\n`);
37
+ } catch {
38
+ // The inherited diagnostic handle may already be closed.
39
+ }
40
+ process.exit(1);
41
+ }
42
+
43
+ let binding;
44
+ try {
45
+ binding = backgroundTurnBootstrapBindingFromEnvironment(
46
+ process.env,
47
+ process.pid,
48
+ );
49
+ } catch (error) {
50
+ failClosed(error?.message || String(error));
51
+ }
52
+
53
+ if (typeof process.send !== "function" || process.connected === false) {
54
+ failClosed("dedicated worker IPC is unavailable");
55
+ }
56
+
57
+ await new Promise((resolve) => {
58
+ let released = false;
59
+ let failed = false;
60
+ let timer = null;
61
+ let readyTimer = null;
62
+
63
+ const failOnce = (message) => {
64
+ if (failed) return;
65
+ failed = true;
66
+ if (timer) clearTimeout(timer);
67
+ if (readyTimer) clearInterval(readyTimer);
68
+ failClosed(message);
69
+ };
70
+
71
+ const onMessage = (message) => {
72
+ if (message?.type !== BACKGROUND_TURN_BOOTSTRAP_RELEASE) return;
73
+ if (released) {
74
+ failOnce("duplicate release rejected");
75
+ return;
76
+ }
77
+ if (
78
+ !matchesBackgroundTurnBootstrapMessage(
79
+ message,
80
+ BACKGROUND_TURN_BOOTSTRAP_RELEASE,
81
+ binding,
82
+ )
83
+ ) {
84
+ failOnce("release binding mismatch");
85
+ return;
86
+ }
87
+ released = true;
88
+ if (timer) clearTimeout(timer);
89
+ if (readyTimer) clearInterval(readyTimer);
90
+ try {
91
+ process.execArgv = removeBackgroundTurnBootstrapImport(
92
+ process.execArgv,
93
+ import.meta.url,
94
+ );
95
+ clearBackgroundTurnBootstrapEnvironment(process.env);
96
+ // Keep the disconnect listener as a fail-closed worker-death signal,
97
+ // but do not make this private bootstrap channel keep an otherwise
98
+ // completed Agent process alive. Interaction requests explicitly ref
99
+ // the same channel for the duration of a pending same-turn answer.
100
+ process.channel?.unref?.();
101
+ } catch (error) {
102
+ failOnce(error?.message || String(error));
103
+ return;
104
+ }
105
+ resolve();
106
+ };
107
+
108
+ // Keep both listeners after release. A repeated release or loss of the
109
+ // supervising worker remains fail-closed even after the real CLI starts.
110
+ process.on("message", onMessage);
111
+ process.once("disconnect", () =>
112
+ failOnce("worker IPC disconnected before turn completion"),
113
+ );
114
+ timer = setTimeout(
115
+ () => failOnce("timed out waiting for durable turn release"),
116
+ releaseTimeoutMs(),
117
+ );
118
+ timer.unref?.();
119
+
120
+ const sendReady = () => {
121
+ if (released || failed) return;
122
+ try {
123
+ process.send(
124
+ createBackgroundTurnBootstrapMessage(
125
+ BACKGROUND_TURN_BOOTSTRAP_READY,
126
+ binding,
127
+ ),
128
+ (error) => {
129
+ if (error) failOnce(`ready delivery failed: ${error.message}`);
130
+ },
131
+ );
132
+ } catch (error) {
133
+ failOnce(`ready delivery failed: ${error?.message || String(error)}`);
134
+ }
135
+ };
136
+ sendReady();
137
+ // A very fast preload can publish readiness while the worker is still
138
+ // fsyncing the PID commit. Repeat only READY (never RELEASE) until the
139
+ // post-commit listener answers, so an early unobserved event cannot strand
140
+ // the child. Matching duplicates are intentionally idempotent parent-side.
141
+ readyTimer = setInterval(sendReady, 100);
142
+ readyTimer.unref?.();
143
+ });
@@ -1 +0,0 @@
1
- import{P as c,J as p,b as s}from"./vendor-Bn1JzzAn.js";import{r as a}from"./markdown-Yo_c6Krv.js";import{_ as d}from"./index-BHNYPO0b.js";const _={__name:"MarkdownRenderer",props:{content:{type:String,default:""}},setup(t,{expose:o}){o();const e=t,r=s(()=>a(e.content||"")),n={props:e,rendered:r,computed:s,get renderMarkdown(){return a}};return Object.defineProperty(n,"__isScriptSetup",{enumerable:!1,value:!0}),n}},i=["innerHTML"];function l(t,o,e,r,n,m){return c(),p("div",{class:"markdown-content",innerHTML:r.rendered},null,8,i)}const b=d(_,[["render",l],["__scopeId","data-v-0b0b9f63"],["__file","/tmp/cc-web-panel-blIgp5/repo/packages/web-panel/src/components/MarkdownRenderer.vue"]]);export{b as M};
@@ -1 +0,0 @@
1
- import{I as n,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-BHNYPO0b.js";import{a8 as y,M}from"./icons-DG5UD-6K.js";const B={__name:"MobileProjects",setup(p,{expose:i}){i();const c=u(),{t:e}=m();function a(){c.push("/projects")}function _(){c.push("/mobile-bridge")}const s={router:c,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}},x={class:"mobile-projects-placeholder"},O={class:"title"},k={class:"subtitle"},w={class:"explainer"};function T(p,i,c,e,a,_){const s=n("a-alert"),d=n("a-button"),f=n("a-space"),P=n("a-empty"),j=n("a-card");return h(),g("div",x,[l(j,null,{default:r(()=>[l(P,{description:!1},{image:r(()=>[l(e.MobileOutlined,{style:{fontSize:"64px",color:"#bfbfbf"}})]),default:r(()=>[o("h2",O,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-blIgp5/repo/packages/web-panel/src/views/MobileProjects.vue"]]);export{N as default};
@@ -1 +0,0 @@
1
- import{I as i,J as A,U,R as s,Q as r,c as t,K as a,V as _,S as x,o as oe,b as ee,r as u,P as p,F as ne,a2 as ge}from"./vendor-Bn1JzzAn.js";import{_ as we,b as re,u as ie,d}from"./index-BHNYPO0b.js";import{u as de}from"./useShellMode-CgR0wCYM.js";import{aN as ke,aO as be,aP as Fe,f as je,a5 as Ce,a8 as xe,at as Oe,R as Se}from"./icons-DG5UD-6K.js";const Pe={__name:"Projects",setup(se,{expose:l}){l();const{t:te}=re(),e=ie(),{isEmbedded:W}=de();async function w(o,f,ye,ae=8e3){if(W){const Z=await e.sendRaw({...f,type:o},ae);if(!Z?.ok){const $=Z?.error;throw new Error(typeof $=="string"?$:$?.message||`${o} failed`)}return Z.result}return e.executeJson(ye,ae)}const B=u(!1),y=u([]),O=u(""),S=u(""),P=u(!1),v=u(null),h=u([]),k=u(!1),E=u(!1),L=u(!1),b=u({name:"",description:"",type:"document",rootPath:""}),z=[{title:"ID",key:"id",width:110},{title:"名称",key:"name"},{title:"类型",key:"project_type",width:120},{title:"状态",key:"status",width:100},{title:"同步",key:"sync_status",width:100},{title:"更新",key:"updated_at",width:160},{title:"操作",key:"actions",width:180,fixed:"right"}],V=ee(()=>{const o={active:0,draft:0,completed:0,archived:0};for(const f of y.value)o[f.status]!==void 0&&(o[f.status]+=1);return o}),J=ee(()=>y.value.filter(o=>!(O.value&&o.status!==O.value||S.value&&!o.name.toLowerCase().includes(S.value.toLowerCase()))));function g(o){switch(o){case"active":return"green";case"draft":return"default";case"completed":return"cyan";case"archived":return"gold";default:return"default"}}function K(o){switch(o){case"synced":return"green";case"pending":return"orange";case"conflict":return"red";case"error":return"red";default:return"default"}}function Q(o){return!o&&o!==0?"-":new Date(typeof o=="number"?o:parseInt(o,10)).toLocaleString("zh-CN",{hour12:!1})}async function C(){B.value=!0;try{const o=await w("project.list",{limit:500},"project list --limit 500 --json",1e4);y.value=Array.isArray(o?.projects)?o.projects:Array.isArray(o)?o:[]}catch(o){d.error("加载失败: "+(o.message||o)),y.value=[]}finally{B.value=!1}}function G(o){return{onClick:()=>M(o)}}async function M(o){v.value=o,P.value=!0,k.value=!0,h.value=[];try{const f=await w("project.listFiles",{projectId:o.id,limit:200},`project list-files ${o.id} --json`,8e3);h.value=Array.isArray(f?.files)?f.files:[]}catch{h.value=[]}finally{k.value=!1}}async function H(o){try{(await w("project.delete",{id:o.id},`project delete ${o.id} --json`,8e3))?.ok?(d.success(`已删除项目 '${o.name}'`),P.value=!1,await C()):d.error("删除失败")}catch(f){d.error(f.message||String(f))}}function X(){b.value={name:"",description:"",type:"document",rootPath:""},E.value=!0}async function T(){if(!b.value.name.trim()){d.warning("请输入项目名称");return}L.value=!0;try{const o=await w("project.init",{name:b.value.name.trim(),description:b.value.description||null,projectType:b.value.type,rootPath:b.value.rootPath||null},`project init "${b.value.name.trim()}" --type ${b.value.type} --json`,8e3);o?.id?(d.success(`已创建项目 '${o.name}'`),E.value=!1,await C()):d.error("创建失败")}catch(o){d.error(o.message||String(o))}finally{L.value=!1}}const F=u(!1),D=u(!1),j=u({path:"",content:""}),I=u(!1),m=u(!1),R=u({path:""}),n=u(!1),c=u(null),q=u(""),Y=u(!1);function ue(){j.value={path:"",content:""},F.value=!0}function ce(){R.value={path:""},I.value=!0}async function N(){if(v.value){k.value=!0;try{const o=await w("project.listFiles",{projectId:v.value.id,limit:200},`project list-files ${v.value.id} --json`,8e3);h.value=Array.isArray(o?.files)?o.files:[]}catch(o){d.error("刷新文件失败: "+(o.message||o))}finally{k.value=!1}}}async function fe(){if(!j.value.path.trim()){d.warning("请输入文件路径");return}if(v.value){D.value=!0;try{const o=await w("project.createFile",{projectId:v.value.id,filePath:j.value.path.trim(),content:j.value.content||""},`project create-file ${v.value.id} "${j.value.path.trim()}" --json`,8e3);o?.id?(d.success(`已创建文件 '${o.file_name}'`),F.value=!1,await N(),await C()):d.error("创建文件失败")}catch(o){d.error(o.message||String(o))}finally{D.value=!1}}}async function pe(){if(!R.value.path.trim()){d.warning("请输入文件夹路径");return}if(v.value){m.value=!0;try{const o=await w("project.createFolder",{projectId:v.value.id,folderPath:R.value.path.trim()},`project create-folder ${v.value.id} "${R.value.path.trim()}" --json`,8e3);o?.id?(d.success(`已创建文件夹 '${o.file_name}'`),I.value=!1,await N(),await C()):d.error("创建文件夹失败")}catch(o){d.error(o.message||String(o))}finally{m.value=!1}}}async function ve(o){try{(await w("project.deleteFile",{fileId:o.id},`project delete-file ${o.id} --json`,8e3))?.deleted?(d.success(`已删除 '${o.file_name}'`),await N(),await C()):d.error("删除失败")}catch(f){d.error(f.message||String(f))}}async function me(o){if(o.is_folder){d.info("文件夹无内容可编辑");return}try{const f=await w("project.getFile",{fileId:o.id},`project get-file ${o.id} --json`,8e3);c.value=o,q.value=f?.content||"",n.value=!0}catch(f){d.error("读取文件失败: "+(f.message||f))}}async function _e(){if(c.value){Y.value=!0;try{(await w("project.writeFile",{fileId:c.value.id,content:q.value},`project write-file ${c.value.id} --json`,8e3))?.id?(d.success("已保存"),n.value=!1,await N()):d.error("保存失败")}catch(o){d.error(o.message||String(o))}finally{Y.value=!1}}}oe(()=>{C()});const le={t:te,ws:e,isEmbedded:W,callProjectTopic:w,loading:B,projects:y,statusFilter:O,nameFilter:S,detailOpen:P,detail:v,files:h,filesLoading:k,createOpen:E,creating:L,newProject:b,columns:z,countByStatus:V,filteredProjects:J,statusColor:g,syncColor:K,formatTime:Q,loadAll:C,onRowClick:G,openDetail:M,onDelete:H,onShowCreate:X,onCreate:T,createFileOpen:F,creatingFile:D,newFile:j,createFolderOpen:I,creatingFolder:m,newFolder:R,editFileOpen:n,editingFile:c,editFileContent:q,savingFile:Y,openCreateFile:ue,openCreateFolder:ce,refreshFiles:N,onCreateFile:fe,onCreateFolder:pe,onDeleteFile:ve,openEditFile:me,onSaveFile:_e,ref:u,computed:ee,onMounted:oe,get ReloadOutlined(){return Se},get PlusOutlined(){return Oe},get FolderOutlined(){return xe},get FileTextOutlined(){return Ce},get CheckCircleOutlined(){return je},get CheckSquareOutlined(){return Fe},get FileAddOutlined(){return be},get FolderAddOutlined(){return ke},get message(){return d},get useI18n(){return re},get useWsStore(){return ie},get useShellMode(){return de}};return Object.defineProperty(le,"__isScriptSetup",{enumerable:!1,value:!0}),le}},ze={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},Ie={class:"page-title"},Ae={class:"page-sub"},Ue={class:"filter-bar",style:{"margin-bottom":"12px",display:"flex",gap:"12px","align-items":"center"}},he={key:0,style:{"font-size":"12px",color:"#888"}},De={key:0,style:{color:"#888","font-size":"12px"}},Re={key:0},Te={key:1,style:{color:"#888"}},Be=["onClick"],Ee={key:0,style:{color:"#888","font-size":"12px"}};function Le(se,l,te,e,W,w){const B=i("router-link"),y=i("a-button"),O=i("a-space"),S=i("a-statistic"),P=i("a-card"),v=i("a-col"),h=i("a-row"),k=i("a-radio-button"),E=i("a-radio-group"),L=i("a-input-search"),b=i("a-alert"),z=i("a-tag"),V=i("a-popconfirm"),J=i("a-table"),g=i("a-descriptions-item"),K=i("a-descriptions"),Q=i("a-divider"),C=i("a-empty"),G=i("a-list-item"),M=i("a-list"),H=i("a-spin"),X=i("a-drawer"),T=i("a-input"),F=i("a-form-item"),D=i("a-textarea"),j=i("a-form"),I=i("a-modal"),m=i("a-select-option"),R=i("a-select");return p(),A("div",null,[U("div",ze,[U("div",null,[U("h2",Ie,s(e.t("projects.title")),1),U("p",Ae,[l[17]||(l[17]=r("桌面 / CLI / 手机 三端共享同一份项目数据,Phase 3d sync 自动同步 (",-1)),t(B,{to:"/project-init"},{default:a(()=>[...l[16]||(l[16]=[r("项目初始化 / 环境设置",-1)])]),_:1}),l[18]||(l[18]=r(")",-1))])]),t(O,null,{default:a(()=>[t(y,{loading:e.loading,onClick:e.loadAll},{icon:a(()=>[t(e.ReloadOutlined)]),default:a(()=>[l[19]||(l[19]=r(" 刷新 ",-1))]),_:1},8,["loading"]),t(y,{type:"primary",onClick:e.onShowCreate},{icon:a(()=>[t(e.PlusOutlined)]),default:a(()=>[l[20]||(l[20]=r(" 新建项目 ",-1))]),_:1})]),_:1})]),_(" Stats "),t(h,{gutter:[16,16],style:{"margin-bottom":"20px"}},{default:a(()=>[t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"总项目",value:e.projects.length,"value-style":{color:"#1677ff",fontSize:"20px"}},{prefix:a(()=>[t(e.FolderOutlined)]),_:1},8,["value"])]),_:1})]),_:1}),t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"活跃",value:e.countByStatus.active,"value-style":{color:"#52c41a",fontSize:"20px"}},{prefix:a(()=>[t(e.CheckCircleOutlined)]),_:1},8,["value"])]),_:1})]),_:1}),t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"草稿",value:e.countByStatus.draft,"value-style":{color:"#8c8c8c",fontSize:"20px"}},{prefix:a(()=>[t(e.FileTextOutlined)]),_:1},8,["value"])]),_:1})]),_:1}),t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"已完成",value:e.countByStatus.completed,"value-style":{color:"#13c2c2",fontSize:"20px"}},{prefix:a(()=>[t(e.CheckSquareOutlined)]),_:1},8,["value"])]),_:1})]),_:1})]),_:1}),_(" Filter "),U("div",Ue,[t(E,{value:e.statusFilter,"onUpdate:value":l[0]||(l[0]=n=>e.statusFilter=n),size:"small","button-style":"solid"},{default:a(()=>[t(k,{value:""},{default:a(()=>[...l[21]||(l[21]=[r("全部",-1)])]),_:1}),t(k,{value:"active"},{default:a(()=>[...l[22]||(l[22]=[r("活跃",-1)])]),_:1}),t(k,{value:"draft"},{default:a(()=>[...l[23]||(l[23]=[r("草稿",-1)])]),_:1}),t(k,{value:"completed"},{default:a(()=>[...l[24]||(l[24]=[r("已完成",-1)])]),_:1}),t(k,{value:"archived"},{default:a(()=>[...l[25]||(l[25]=[r("已归档",-1)])]),_:1})]),_:1},8,["value"]),t(L,{value:e.nameFilter,"onUpdate:value":l[1]||(l[1]=n=>e.nameFilter=n),placeholder:"按名称过滤",style:{"max-width":"260px"},"allow-clear":""},null,8,["value"])]),!e.projects.length&&!e.loading?(p(),x(b,{key:0,type:"info",message:"还没有项目",description:'运行 `cc project init <name>` 或点击右上角"新建项目"按钮创建。桌面 / CLI / 手机三端共享同一份数据。',"show-icon":"",style:{"margin-bottom":"16px"}})):_("v-if",!0),e.projects.length||e.loading?(p(),x(J,{key:1,columns:e.columns,"data-source":e.filteredProjects,loading:e.loading,pagination:{pageSize:20,showSizeChanger:!0},"row-key":"id","custom-row":e.onRowClick},{bodyCell:a(({column:n,record:c})=>[n.key==="id"?(p(),A("code",he,s(c.id.slice(0,8))+"…",1)):n.key==="name"?(p(),A(ne,{key:1},[U("strong",null,s(c.name),1),c.description?(p(),A("div",De,s(c.description),1)):_("v-if",!0)],64)):n.key==="project_type"?(p(),x(z,{key:2},{default:a(()=>[r(s(c.project_type),1)]),_:2},1024)):n.key==="status"?(p(),x(z,{key:3,color:e.statusColor(c.status)},{default:a(()=>[r(s(c.status),1)]),_:2},1032,["color"])):n.key==="sync_status"?(p(),x(z,{key:4,color:e.syncColor(c.sync_status)},{default:a(()=>[r(s(c.sync_status||"unknown"),1)]),_:2},1032,["color"])):n.key==="updated_at"?(p(),A(ne,{key:5},[r(s(e.formatTime(c.updated_at)),1)],64)):n.key==="actions"?(p(),x(O,{key:6,onClick:l[2]||(l[2]=ge(()=>{},["stop"]))},{default:a(()=>[t(y,{size:"small",onClick:q=>e.openDetail(c)},{default:a(()=>[...l[26]||(l[26]=[r("详情",-1)])]),_:1},8,["onClick"]),t(V,{title:`删除项目 '${c.name}' ?`,"ok-text":"删除","ok-type":"danger","cancel-text":"取消",onConfirm:q=>e.onDelete(c)},{default:a(()=>[t(y,{size:"small",danger:""},{default:a(()=>[...l[27]||(l[27]=[r("删除",-1)])]),_:1})]),_:1},8,["title","onConfirm"])]),_:2},1024)):_("v-if",!0)]),_:1},8,["data-source","loading"])):_("v-if",!0),_(" Detail drawer "),t(X,{open:e.detailOpen,"onUpdate:open":l[3]||(l[3]=n=>e.detailOpen=n),title:e.detail?.name||"项目详情",width:"640",placement:"right"},{default:a(()=>[e.detail?(p(),x(K,{key:0,column:1,bordered:"",size:"small"},{default:a(()=>[t(g,{label:"ID"},{default:a(()=>[U("code",null,s(e.detail.id),1)]),_:1}),t(g,{label:"名称"},{default:a(()=>[r(s(e.detail.name),1)]),_:1}),t(g,{label:"描述"},{default:a(()=>[r(s(e.detail.description||"-"),1)]),_:1}),t(g,{label:"类型"},{default:a(()=>[t(z,null,{default:a(()=>[r(s(e.detail.project_type),1)]),_:1})]),_:1}),t(g,{label:"状态"},{default:a(()=>[t(z,{color:e.statusColor(e.detail.status)},{default:a(()=>[r(s(e.detail.status),1)]),_:1},8,["color"])]),_:1}),t(g,{label:"同步状态"},{default:a(()=>[t(z,{color:e.syncColor(e.detail.sync_status)},{default:a(()=>[r(s(e.detail.sync_status||"unknown"),1)]),_:1},8,["color"])]),_:1}),t(g,{label:"用户"},{default:a(()=>[r(s(e.detail.user_id),1)]),_:1}),t(g,{label:"根路径"},{default:a(()=>[e.detail.root_path?(p(),A("code",Re,s(e.detail.root_path),1)):(p(),A("span",Te,"(无)"))]),_:1}),t(g,{label:"文件数"},{default:a(()=>[r(s(e.detail.file_count||0),1)]),_:1}),t(g,{label:"创建"},{default:a(()=>[r(s(e.formatTime(e.detail.created_at)),1)]),_:1}),t(g,{label:"更新"},{default:a(()=>[r(s(e.formatTime(e.detail.updated_at)),1)]),_:1})]),_:1})):_("v-if",!0),t(Q,null,{default:a(()=>[...l[28]||(l[28]=[r("文件",-1)])]),_:1}),_(" Sub-phase 7.3 (2026-05-17): 文件 CRUD toolbar "),t(O,{style:{"margin-bottom":"12px"}},{default:a(()=>[t(y,{size:"small",type:"primary",disabled:!e.detail,onClick:e.openCreateFile},{default:a(()=>[t(e.FileAddOutlined),l[29]||(l[29]=r(" 新建文件 ",-1))]),_:1},8,["disabled"]),t(y,{size:"small",disabled:!e.detail,onClick:e.openCreateFolder},{default:a(()=>[t(e.FolderAddOutlined),l[30]||(l[30]=r(" 新建文件夹 ",-1))]),_:1},8,["disabled"])]),_:1}),t(H,{spinning:e.filesLoading},{default:a(()=>[!e.files.length&&!e.filesLoading?(p(),x(C,{key:0,description:"无文件 (点上方按钮新建)"})):(p(),x(M,{key:1,size:"small","data-source":e.files},{renderItem:a(({item:n})=>[t(G,null,{extra:a(()=>[t(O,null,{default:a(()=>[n.file_size?(p(),A("span",Ee,s(n.file_size)+" B",1)):_("v-if",!0),t(V,{title:`删除 ${n.is_folder?"文件夹":"文件"} '${n.file_name}' ?`,"ok-text":"删除","ok-type":"danger","cancel-text":"取消",onConfirm:c=>e.onDeleteFile(n)},{default:a(()=>[t(y,{size:"small",danger:""},{default:a(()=>[...l[31]||(l[31]=[r("×",-1)])]),_:1})]),_:1},8,["title","onConfirm"])]),_:2},1024)]),default:a(()=>[U("span",{style:{cursor:"pointer"},onClick:c=>e.openEditFile(n)},s(n.is_folder?"📁":"📄")+" "+s(n.file_path),9,Be)]),_:2},1024)]),_:1},8,["data-source"]))]),_:1},8,["spinning"])]),_:1},8,["open","title"]),_(" Sub-phase 7.3: Create file modal "),t(I,{open:e.createFileOpen,"onUpdate:open":l[6]||(l[6]=n=>e.createFileOpen=n),title:"新建文件","confirm-loading":e.creatingFile,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreateFile},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(F,{label:"文件路径(项目内)",required:""},{default:a(()=>[t(T,{value:e.newFile.path,"onUpdate:value":l[4]||(l[4]=n=>e.newFile.path=n),placeholder:"例如 README.md 或 src/main.kt"},null,8,["value"])]),_:1}),t(F,{label:"初始内容(可选)"},{default:a(()=>[t(D,{value:e.newFile.content,"onUpdate:value":l[5]||(l[5]=n=>e.newFile.content=n),rows:6,placeholder:"留空创建空文件"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"]),_(" Sub-phase 7.3: Create folder modal "),t(I,{open:e.createFolderOpen,"onUpdate:open":l[8]||(l[8]=n=>e.createFolderOpen=n),title:"新建文件夹","confirm-loading":e.creatingFolder,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreateFolder},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(F,{label:"文件夹路径(项目内)",required:""},{default:a(()=>[t(T,{value:e.newFolder.path,"onUpdate:value":l[7]||(l[7]=n=>e.newFolder.path=n),placeholder:"例如 src/utils"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"]),_(" Sub-phase 7.3: Edit file content modal "),t(I,{open:e.editFileOpen,"onUpdate:open":l[10]||(l[10]=n=>e.editFileOpen=n),title:`编辑 ${e.editingFile?.file_name||""}`,"confirm-loading":e.savingFile,"ok-text":"保存","cancel-text":"取消",onOk:e.onSaveFile,width:"720"},{default:a(()=>[t(D,{value:e.editFileContent,"onUpdate:value":l[9]||(l[9]=n=>e.editFileContent=n),rows:18,"auto-size":{minRows:12,maxRows:24},style:{"font-family":"monospace"}},null,8,["value"])]),_:1},8,["open","title","confirm-loading"]),_(" Create modal "),t(I,{open:e.createOpen,"onUpdate:open":l[15]||(l[15]=n=>e.createOpen=n),title:"新建项目","confirm-loading":e.creating,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreate},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(F,{label:"项目名称",required:""},{default:a(()=>[t(T,{value:e.newProject.name,"onUpdate:value":l[11]||(l[11]=n=>e.newProject.name=n),placeholder:"例如:旅行计划-上海"},null,8,["value"])]),_:1}),t(F,{label:"描述"},{default:a(()=>[t(D,{value:e.newProject.description,"onUpdate:value":l[12]||(l[12]=n=>e.newProject.description=n),rows:2},null,8,["value"])]),_:1}),t(F,{label:"类型"},{default:a(()=>[t(R,{value:e.newProject.type,"onUpdate:value":l[13]||(l[13]=n=>e.newProject.type=n)},{default:a(()=>[t(m,{value:"document"},{default:a(()=>[...l[32]||(l[32]=[r("文档 (document)",-1)])]),_:1}),t(m,{value:"data"},{default:a(()=>[...l[33]||(l[33]=[r("数据 (data)",-1)])]),_:1}),t(m,{value:"web"},{default:a(()=>[...l[34]||(l[34]=[r("Web",-1)])]),_:1}),t(m,{value:"app"},{default:a(()=>[...l[35]||(l[35]=[r("应用 (app)",-1)])]),_:1}),t(m,{value:"presentation"},{default:a(()=>[...l[36]||(l[36]=[r("演示文稿",-1)])]),_:1}),t(m,{value:"spreadsheet"},{default:a(()=>[...l[37]||(l[37]=[r("表格",-1)])]),_:1}),t(m,{value:"design"},{default:a(()=>[...l[38]||(l[38]=[r("设计",-1)])]),_:1}),t(m,{value:"code"},{default:a(()=>[...l[39]||(l[39]=[r("代码",-1)])]),_:1}),t(m,{value:"workflow"},{default:a(()=>[...l[40]||(l[40]=[r("工作流",-1)])]),_:1}),t(m,{value:"knowledge"},{default:a(()=>[...l[41]||(l[41]=[r("知识库",-1)])]),_:1})]),_:1},8,["value"])]),_:1}),t(F,{label:"根路径 (可选)"},{default:a(()=>[t(T,{value:e.newProject.rootPath,"onUpdate:value":l[14]||(l[14]=n=>e.newProject.rootPath=n),placeholder:"留空则仅元数据"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"])])}const We=we(Pe,[["render",Le],["__scopeId","data-v-019ac5aa"],["__file","/tmp/cc-web-panel-blIgp5/repo/packages/web-panel/src/views/Projects.vue"]]);export{We as default};