@runfusion/fusion 0.44.0 → 0.45.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 (240) hide show
  1. package/README.md +2 -1
  2. package/dist/bin.js +6902 -2143
  3. package/dist/client/.vite/manifest.json +1115 -328
  4. package/dist/client/assets/AgentDetailView-CgbB51Iw.css +1 -0
  5. package/dist/client/assets/AgentDetailView-DJTi6hKC.js +18 -0
  6. package/dist/client/assets/{AgentPermissionPolicyEditor--YS4iMUY.js → AgentPermissionPolicyEditor-C5DR9dUS.js} +2 -2
  7. package/dist/client/assets/AgentsView-BNd90PSx.js +29 -0
  8. package/dist/client/assets/AgentsView-CzMa5Olf.css +1 -0
  9. package/dist/client/assets/ChatView-B7JaZCL_.js +19 -0
  10. package/dist/client/assets/ChatView-BtjkE0V7.css +1 -0
  11. package/dist/client/assets/CommandCenter-CHO21xEW.js +74 -0
  12. package/dist/client/assets/CommandCenter-Xs5Ftv8s.css +1 -0
  13. package/dist/client/assets/DevServerView-B_p91Mj_.css +1 -0
  14. package/dist/client/assets/DevServerView-H9OkT1ld.js +1 -0
  15. package/dist/client/assets/DirectoryPicker-DegxT8ia.js +1 -0
  16. package/dist/client/assets/DocumentsView-kVVQYISc.js +1 -0
  17. package/dist/client/assets/EvalsView-C9-iTSat.js +1 -0
  18. package/dist/client/assets/EvalsView-CTbgPUne.css +1 -0
  19. package/dist/client/assets/ExperimentalAgentOnboardingModal-3ZEFv8sr.css +1 -0
  20. package/dist/client/assets/ExperimentalAgentOnboardingModal-DjP_xNkc.js +1 -0
  21. package/dist/client/assets/GoalsView-CUh8JBnJ.css +1 -0
  22. package/dist/client/assets/GoalsView-VoIHJJ5l.js +2 -0
  23. package/dist/client/assets/InsightsView-BIZaUcpd.js +11 -0
  24. package/dist/client/assets/InsightsView-C7yRTMPn.css +1 -0
  25. package/dist/client/assets/MemoryView-7v7rv6ns.js +2 -0
  26. package/dist/client/assets/MemoryView-CBDUr2Jy.css +1 -0
  27. package/dist/client/assets/PiExtensionsManager-CB89rV4U.js +11 -0
  28. package/dist/client/assets/PluginManager-BNSuW_R4.js +1 -0
  29. package/dist/client/assets/PullRequestView-CI5jdKBL.js +6 -0
  30. package/dist/client/assets/PullRequestView-CpdE3Yo_.css +1 -0
  31. package/dist/client/assets/ResearchView-BT5dR_m8.js +1 -0
  32. package/dist/client/assets/ResearchView-DIVNQF4_.css +1 -0
  33. package/dist/client/assets/SecretsView-CvFioX7R.css +1 -0
  34. package/dist/client/assets/SecretsView-WPYI58Uo.js +1 -0
  35. package/dist/client/assets/SessionTerminal-C6gyOWLt.js +2 -0
  36. package/dist/client/assets/SessionTerminal-D4R3ScvQ.css +1 -0
  37. package/dist/client/assets/SettingsModal-BESN59Ao.css +1 -0
  38. package/dist/client/assets/SettingsModal-BZokaNyx.css +1 -0
  39. package/dist/client/assets/SettingsModal-Bq_3AbaB.js +1 -0
  40. package/dist/client/assets/SettingsModal-JHACoQJe.js +21 -0
  41. package/dist/client/assets/SetupWizardModal-CrgbnR_d.js +2 -0
  42. package/dist/client/assets/ShadcnColorPicker-1icHuwhC.js +11 -0
  43. package/dist/client/assets/ShadcnColorPicker-pqVWCC5-.css +1 -0
  44. package/dist/client/assets/SkillsView-CJ8snrma.css +1 -0
  45. package/dist/client/assets/SkillsView-byuSe3e0.js +1 -0
  46. package/dist/client/assets/TodoView-CIsL_uvQ.css +1 -0
  47. package/dist/client/assets/TodoView-CQ9GjYBg.js +6 -0
  48. package/dist/client/assets/WorkflowNodeEditor-DW7sJZUX.js +8 -0
  49. package/dist/client/assets/WorkflowNodeEditor-f_XPV5Jd.css +1 -0
  50. package/dist/client/assets/{addon-fit-SnYDEvGm.js → addon-fit-C1WQXRvu.js} +1 -1
  51. package/dist/client/assets/{addon-unicode11-s5GoZCpi.js → addon-unicode11-BVmNDUBM.js} +1 -1
  52. package/dist/client/assets/{addon-web-links-jjt2f_oV.js → addon-web-links-CkVew5xs.js} +1 -1
  53. package/dist/client/assets/{addon-webgl-Icn-RnEx.js → addon-webgl-uLc0RKcC.js} +1 -1
  54. package/dist/client/assets/agentSkills-CeytXLHF.js +1 -0
  55. package/dist/client/assets/{ExperimentalAgentOnboardingModal-CZ_jbgep.css → agentSkills-bQJ4X1gH.css} +1 -1
  56. package/dist/client/assets/agentsOrgChartLayout-BMvyuaLA.js +1 -0
  57. package/dist/client/assets/app-3wbZ08YC.js +13 -0
  58. package/dist/client/assets/app-7-5DWLtg.js +13 -0
  59. package/dist/client/assets/app-CSvE5Noc.js +13 -0
  60. package/dist/client/assets/app-CZ2LTFce.js +13 -0
  61. package/dist/client/assets/app-Cv9xEnll.js +13 -0
  62. package/dist/client/assets/app-x_yPcO5Y.js +13 -0
  63. package/dist/client/assets/arc-cxkkNsnK.js +1 -0
  64. package/dist/client/assets/architectureDiagram-3BPJPVTR-BRI0QwDf.js +36 -0
  65. package/dist/client/assets/band-CquvqAHh.js +1 -0
  66. package/dist/client/assets/blockDiagram-GPEHLZMM-BXkN8Hv_.js +132 -0
  67. package/dist/client/assets/c4Diagram-AAUBKEIU-C_Kcokep.js +10 -0
  68. package/dist/client/assets/channel-Clzpzu32.js +1 -0
  69. package/dist/client/assets/chunk-2J33WTMH-BGeuCz9C.js +1 -0
  70. package/dist/client/assets/chunk-4BX2VUAB-DcVdctr0.js +1 -0
  71. package/dist/client/assets/chunk-55IACEB6-Dg6gDigQ.js +1 -0
  72. package/dist/client/assets/chunk-727SXJPM-B9B-vlEb.js +206 -0
  73. package/dist/client/assets/chunk-AQP2D5EJ-LrWQ-2yi.js +231 -0
  74. package/dist/client/assets/chunk-FMBD7UC4-Bnd6hAED.js +15 -0
  75. package/dist/client/assets/chunk-ND2GUHAM-nAw93UB5.js +1 -0
  76. package/dist/client/assets/chunk-QZHKN3VN-CgprKcZo.js +1 -0
  77. package/dist/client/assets/classDiagram-4FO5ZUOK-CzYHP-af.js +1 -0
  78. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CzYHP-af.js +1 -0
  79. package/dist/client/assets/common-BDp2y6CF.js +1 -0
  80. package/dist/client/assets/common-BnEo5fLN.js +1 -0
  81. package/dist/client/assets/common-Bzr_Y8h4.js +1 -0
  82. package/dist/client/assets/common-CvwyFzfv.js +1 -0
  83. package/dist/client/assets/common-CztCXRkz.js +1 -0
  84. package/dist/client/assets/common-DPe2mbb7.js +1 -0
  85. package/dist/client/assets/cose-bilkent-S5V4N54A-Bhn0g_iK.js +1 -0
  86. package/dist/client/assets/cytoscape.esm-OyMbaexL.js +331 -0
  87. package/dist/client/assets/dagre-BM42HDAG-CP4kfwqd.js +4 -0
  88. package/dist/client/assets/{dashboard-view-B4LXCv5H.js → dashboard-view-CM6Xin_H.js} +1680 -1620
  89. package/dist/client/assets/dashboard-view-DV1nEhh9.js +1 -0
  90. package/dist/client/assets/dashboard-view-D_zsA-kz.css +1 -0
  91. package/dist/client/assets/defaultLocale-DX6XiGOO.js +1 -0
  92. package/dist/client/assets/diagram-2AECGRRQ-DPhzVEUf.js +43 -0
  93. package/dist/client/assets/diagram-5GNKFQAL-8QOC3K_L.js +10 -0
  94. package/dist/client/assets/diagram-KO2AKTUF-C1twgEch.js +3 -0
  95. package/dist/client/assets/diagram-LMA3HP47-3bEegSuf.js +24 -0
  96. package/dist/client/assets/diagram-OG6HWLK6-BJ_x0rm6.js +24 -0
  97. package/dist/client/assets/erDiagram-TEJ5UH35-DNiiS5q6.js +85 -0
  98. package/dist/client/assets/flowDiagram-I6XJVG4X-DoouPklt.js +162 -0
  99. package/dist/client/assets/{folder-open-33WGVnbp.js → folder-open-CuUs2W7f.js} +1 -1
  100. package/dist/client/assets/ganttDiagram-6RSMTGT7-BrR6VnP5.js +292 -0
  101. package/dist/client/assets/gitGraphDiagram-PVQCEYII-BV8_J6Ee.js +106 -0
  102. package/dist/client/assets/graph--OzhPTMs.js +1 -0
  103. package/dist/client/assets/index-BZBQ_KsL.css +1 -0
  104. package/dist/client/assets/index-CZcWjLAb.js +1459 -0
  105. package/dist/client/assets/infoDiagram-5YYISTIA-DGwIIFkR.js +2 -0
  106. package/dist/client/assets/init-Dmth1JHB.js +1 -0
  107. package/dist/client/assets/ishikawaDiagram-YF4QCWOH-D5dEH4RE.js +70 -0
  108. package/dist/client/assets/journeyDiagram-JHISSGLW-BuuSWPw5.js +139 -0
  109. package/dist/client/assets/kanban-definition-UN3LZRKU-DA34uUla.js +89 -0
  110. package/dist/client/assets/katex-HP8lGamR.js +257 -0
  111. package/dist/client/assets/layout-SsrduOYp.js +1 -0
  112. package/dist/client/assets/linear-dXivciGL.js +1 -0
  113. package/dist/client/assets/mermaid.core-Ch4HatqA.js +309 -0
  114. package/dist/client/assets/mindmap-definition-RKZ34NQL-DUCG-qD3.js +96 -0
  115. package/dist/client/assets/ordinal-DILIJJjt.js +1 -0
  116. package/dist/client/assets/pieDiagram-4H26LBE5-DWvFGiLa.js +30 -0
  117. package/dist/client/assets/quadrantDiagram-W4KKPZXB-OPTVW3WT.js +7 -0
  118. package/dist/client/assets/requirementDiagram-4Y6WPE33-D7feZvlU.js +84 -0
  119. package/dist/client/assets/sankeyDiagram-5OEKKPKP-AtnSsEX1.js +40 -0
  120. package/dist/client/assets/sequenceDiagram-3UESZ5HK-BZjHUeI5.js +162 -0
  121. package/dist/client/assets/{shield-alert-CqeGWBUK.js → shield-alert-CzaF9ROV.js} +1 -1
  122. package/dist/client/assets/stateDiagram-AJRCARHV-C8j23Pvn.js +1 -0
  123. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-CiZR_S5-.js +1 -0
  124. package/dist/client/assets/step-yuy0qJer.js +1 -0
  125. package/dist/client/assets/time-DoDTxsna.js +1 -0
  126. package/dist/client/assets/timeline-definition-PNZ67QCA-DvfNz25n.js +120 -0
  127. package/dist/client/assets/{upload-C11J2diI.js → upload-DTsYywhN.js} +1 -1
  128. package/dist/client/assets/{users-a-ELbyyZ.js → users-yAd09tKP.js} +1 -1
  129. package/dist/client/assets/{vendor-i18n-DYlSUfot.js → vendor-i18n-GF3RlKbq.js} +2 -2
  130. package/dist/client/assets/{vendor-react-BTgM5bbZ.js → vendor-react-SZ_qB27O.js} +1 -1
  131. package/dist/client/assets/vendor-reactflow-Bg-Qjzh8.js +15 -0
  132. package/dist/client/assets/{vendor-xterm-ea7-K05z.js → vendor-xterm-BNq00GSj.js} +1 -1
  133. package/dist/client/assets/vennDiagram-CIIHVFJN-CG2aMt3v.js +34 -0
  134. package/dist/client/assets/wardley-L42UT6IY-BnhBteen.js +173 -0
  135. package/dist/client/assets/wardleyDiagram-YWT4CUSO-DwqTzM3T.js +78 -0
  136. package/dist/client/assets/xychartDiagram-2RQKCTM6-5Cv2ZKMV.js +7 -0
  137. package/dist/client/assets/zoom-out-NWbVkreR.js +41 -0
  138. package/dist/client/index.html +30 -10
  139. package/dist/client/sw.js +1 -1
  140. package/dist/client/theme-data.css +3082 -206
  141. package/dist/client/version.json +1 -1
  142. package/dist/droid-cli/index.ts +56 -40
  143. package/dist/droid-cli/package.json +1 -1
  144. package/dist/droid-cli/src/__tests__/index.test.ts +47 -21
  145. package/dist/droid-cli/src/__tests__/process-manager.test.ts +50 -33
  146. package/dist/extension.js +4935 -827
  147. package/dist/pi-claude-cli/package.json +1 -1
  148. package/dist/pi-claude-cli/src/__tests__/process-manager.test.ts +25 -0
  149. package/dist/pi-claude-cli/src/process-manager.ts +11 -1
  150. package/dist/plugin-sdk/index.d.ts +126 -4
  151. package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
  152. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  153. package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
  154. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  155. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  156. package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +68 -44
  157. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  158. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  159. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  160. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  161. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  162. package/dist/plugins/fusion-plugin-roadmap/bundled.js +5 -11
  163. package/dist/plugins/fusion-plugin-roadmap/manifest.json +1 -11
  164. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  165. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  166. package/package.json +3 -3
  167. package/skill/fusion/SKILL.md +1 -1
  168. package/skill/fusion/references/cli-commands.md +2 -1
  169. package/skill/fusion/references/extension-tools.md +10 -0
  170. package/skill/fusion/references/fusion-capabilities.md +3 -1
  171. package/dist/client/assets/AgentDetailView-CanIeYHg.css +0 -1
  172. package/dist/client/assets/AgentDetailView-DxV8pFHX.js +0 -18
  173. package/dist/client/assets/AgentsView-BVILQjdS.css +0 -1
  174. package/dist/client/assets/AgentsView-CTzbcvhK.js +0 -29
  175. package/dist/client/assets/ChatView-COygcnyk.js +0 -6
  176. package/dist/client/assets/ChatView-DwJAd5G1.css +0 -1
  177. package/dist/client/assets/CommandCenter-CTaopaC0.css +0 -1
  178. package/dist/client/assets/CommandCenter-DoKX2HWm.js +0 -56
  179. package/dist/client/assets/DevServerView-Cyevyvqx.js +0 -1
  180. package/dist/client/assets/DevServerView-VTQY28P7.css +0 -1
  181. package/dist/client/assets/DirectoryPicker-DBdyXEhR.js +0 -1
  182. package/dist/client/assets/DocumentsView-BzSMyrns.js +0 -1
  183. package/dist/client/assets/DocumentsView-WfVoTZt8.css +0 -1
  184. package/dist/client/assets/EvalsView-CUNJ1TLc.css +0 -1
  185. package/dist/client/assets/EvalsView-ikz00o9g.js +0 -1
  186. package/dist/client/assets/ExperimentalAgentOnboardingModal-D-rzCCET.js +0 -499
  187. package/dist/client/assets/GoalsView-Bfu1Oy2-.js +0 -2
  188. package/dist/client/assets/GoalsView-rg9VSIza.css +0 -1
  189. package/dist/client/assets/InsightsView-Cgmf5nES.js +0 -11
  190. package/dist/client/assets/InsightsView-LMv1M1dU.css +0 -1
  191. package/dist/client/assets/MemoryView-DkEuDKQs.js +0 -2
  192. package/dist/client/assets/MemoryView-zaXewZzi.css +0 -1
  193. package/dist/client/assets/NodesView-7VInxyf_.css +0 -1
  194. package/dist/client/assets/NodesView-B_KYfS4o.js +0 -14
  195. package/dist/client/assets/PiExtensionsManager-Dz69kkKs.js +0 -11
  196. package/dist/client/assets/PluginManager-LHCVcduP.js +0 -1
  197. package/dist/client/assets/PullRequestView-3AdbS2a1.css +0 -1
  198. package/dist/client/assets/PullRequestView-DBJutLLl.js +0 -6
  199. package/dist/client/assets/ResearchView-DTh8FLUm.css +0 -1
  200. package/dist/client/assets/ResearchView-gpn1XcVy.js +0 -1
  201. package/dist/client/assets/SecretsView-B7YqIowt.js +0 -1
  202. package/dist/client/assets/SecretsView-Djo1rahi.css +0 -1
  203. package/dist/client/assets/SessionTerminal-9l4bdKcn.js +0 -2
  204. package/dist/client/assets/SessionTerminal-BNgtmXb3.css +0 -1
  205. package/dist/client/assets/SettingsModal-BGEK9_9A.js +0 -31
  206. package/dist/client/assets/SettingsModal-CKv0TJfM.css +0 -1
  207. package/dist/client/assets/SettingsModal-CXogw-Er.css +0 -1
  208. package/dist/client/assets/SettingsModal-DIIoHGUH.js +0 -1
  209. package/dist/client/assets/SetupWizardModal-BcVeMxeX.js +0 -1
  210. package/dist/client/assets/SetupWizardModal-CIqFbkrD.css +0 -1
  211. package/dist/client/assets/SkillsView-3bhGyWs1.css +0 -1
  212. package/dist/client/assets/SkillsView-BxSJ4PHL.js +0 -1
  213. package/dist/client/assets/StashRecoveryView-B_8WIQEo.css +0 -1
  214. package/dist/client/assets/StashRecoveryView-BhFQ2FsP.js +0 -1
  215. package/dist/client/assets/TodoView-7xIh-Fmi.css +0 -1
  216. package/dist/client/assets/TodoView-BZpewjy0.js +0 -6
  217. package/dist/client/assets/WorkflowNodeEditor-Yn1FRF2v.css +0 -1
  218. package/dist/client/assets/WorkflowNodeEditor-tWsgCdVt.js +0 -8
  219. package/dist/client/assets/app-BmGA0Hiz.js +0 -13
  220. package/dist/client/assets/app-CEVYlVuJ.js +0 -13
  221. package/dist/client/assets/app-CbBFax2C.js +0 -13
  222. package/dist/client/assets/app-DORKrGAz.js +0 -13
  223. package/dist/client/assets/app-DQibuQ9z.js +0 -13
  224. package/dist/client/assets/app-k76GrQP0.js +0 -13
  225. package/dist/client/assets/common-BRyX4VxB.js +0 -1
  226. package/dist/client/assets/common-CN9QPI2d.js +0 -1
  227. package/dist/client/assets/common-CNbjPELi.js +0 -1
  228. package/dist/client/assets/common-DFDqu_n0.js +0 -1
  229. package/dist/client/assets/common-DgWWKG8Z.js +0 -1
  230. package/dist/client/assets/common-X6PzBnVA.js +0 -1
  231. package/dist/client/assets/createLucideIcon-DmVITl5d.js +0 -21
  232. package/dist/client/assets/dashboard-view-BFoyhTYF.js +0 -3
  233. package/dist/client/assets/dashboard-view-Cxzm_eqc.js +0 -1
  234. package/dist/client/assets/dashboard-view-DdGlfuu-.css +0 -1
  235. package/dist/client/assets/dashboard-view-_8yfNwju.css +0 -1
  236. package/dist/client/assets/index-Bglw05rM.js +0 -791
  237. package/dist/client/assets/index-FYgnflWD.css +0 -1
  238. package/dist/client/assets/vendor-reactflow-ZasuEfF9.js +0 -15
  239. package/dist/client/assets/x-PItWc-wQ.js +0 -61
  240. package/dist/client/assets/zoom-out-CzlHv0Kj.js +0 -21
@@ -1 +1 @@
1
- {"version":"c81899ba6-de439bf6"}
1
+ {"version":"192a2f2e9-7a1b1370"}
@@ -24,31 +24,27 @@ type StreamSimpleHandler = NonNullable<Parameters<ExtensionAPI["registerProvider
24
24
  function runCliValidationOnce(): Promise<void> {
25
25
  if (cliValidationPromise) return cliValidationPromise;
26
26
  cliValidationPromise = (async () => {
27
- const presence = await validateCliPresenceAsync();
28
- if (!presence.ok) {
29
- console.warn(`[droid-cli] ${presence.error.message}`);
30
- return;
27
+ try {
28
+ const presence = await validateCliPresenceAsync();
29
+ if (!presence.ok) {
30
+ console.warn(`[droid-cli] ${presence.error.message}`);
31
+ return;
32
+ }
33
+ await validateCliAuthAsync();
34
+ } catch (error) {
35
+ console.warn("[droid-cli] CLI validation failed; continuing without blocking the session", error);
31
36
  }
32
- await validateCliAuthAsync();
33
37
  })();
34
38
  return cliValidationPromise;
35
39
  }
36
40
 
37
- async function getDiscoveredModels() {
41
+ export async function discoverDroidProviderModels() {
38
42
  if (!discoveredModelsPromise) {
39
43
  discoveredModelsPromise = (async () => {
40
44
  try {
41
45
  const ids = Array.from(new Set(await discoverDroidModels()));
42
46
  if (ids.length === 0) return [];
43
- return ids.map((id) => ({
44
- id,
45
- name: id,
46
- reasoning: true,
47
- input: ["text", "image"] as Array<"text" | "image">,
48
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
49
- contextWindow: 200_000,
50
- maxTokens: 8_192,
51
- }));
47
+ return toProviderModels(ids);
52
48
  } catch (error) {
53
49
  console.warn("[droid-cli] model auto-discovery failed; registering provider with empty model list", error);
54
50
  return [];
@@ -60,6 +56,18 @@ async function getDiscoveredModels() {
60
56
 
61
57
  let cachedMcpConfig: { hash: string; configPath: string } | undefined;
62
58
 
59
+ function toProviderModels(ids: string[]): DiscoveredModel[] {
60
+ return ids.map((id) => ({
61
+ id,
62
+ name: id,
63
+ reasoning: true,
64
+ input: ["text", "image"] as Array<"text" | "image">,
65
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
66
+ contextWindow: 200_000,
67
+ maxTokens: 8_192,
68
+ }));
69
+ }
70
+
63
71
  function ensureMcpConfig(
64
72
  pi: ExtensionAPI,
65
73
  contextTools?: ReadonlyArray<{
@@ -93,8 +101,35 @@ function ensureMcpConfig(
93
101
  }
94
102
  }
95
103
 
104
+ function registerDroidProvider(pi: ExtensionAPI, models: DiscoveredModel[]) {
105
+ pi.registerProvider(PROVIDER_ID, {
106
+ baseUrl: "droid-cli",
107
+ apiKey: "unused",
108
+ api: "droid-cli",
109
+ models,
110
+ streamSimple: ((model, context, options) => {
111
+ void runCliValidationOnce();
112
+ const configPath = ensureMcpConfig(
113
+ pi,
114
+ (context as { tools?: ReadonlyArray<{ name: string; description: string; parameters: Record<string, unknown> }> }).tools,
115
+ );
116
+ return streamViaCli(
117
+ model,
118
+ context as never,
119
+ { ...(options ?? {}), mcpConfigPath: configPath } as never,
120
+ ) as unknown as ReturnType<StreamSimpleHandler>;
121
+ }) as StreamSimpleHandler,
122
+ });
123
+ }
124
+
96
125
  export default function (pi: ExtensionAPI) {
97
- void runCliValidationOnce();
126
+ /*
127
+ FNXC:CliRuntime 2026-06-21-18:43:
128
+ Engine and dashboard startup must not start the local Droid CLI merely because the optional extension loaded. Register the provider synchronously with an empty model list, defer validation until an actual droid stream starts, and leave model discovery to explicit picker/status callers so boot with `useDroidCli` enabled still performs zero `droid` spawns.
129
+
130
+ FNXC:CliRuntime 2026-06-21-12:00:
131
+ Engine and dashboard startup must not wait for local Droid CLI probes. Every surviving validation/discovery helper remains fire-and-forget, bounded, non-interactive, and resolve-only so a missing or wedged `droid` binary cannot stall extension loading or a session start.
132
+ */
98
133
 
99
134
  pi.on("session_start", async () => {
100
135
  const allTools = pi.getAllTools();
@@ -103,28 +138,9 @@ export default function (pi: ExtensionAPI) {
103
138
  }
104
139
  });
105
140
 
106
- void (async () => {
107
- const models = await getDiscoveredModels();
108
- try {
109
- pi.registerProvider(PROVIDER_ID, {
110
- baseUrl: "droid-cli",
111
- apiKey: "unused",
112
- api: "droid-cli",
113
- models,
114
- streamSimple: ((model, context, options) => {
115
- const configPath = ensureMcpConfig(
116
- pi,
117
- (context as { tools?: ReadonlyArray<{ name: string; description: string; parameters: Record<string, unknown> }> }).tools,
118
- );
119
- return streamViaCli(
120
- model,
121
- context as never,
122
- { ...(options ?? {}), mcpConfigPath: configPath } as never,
123
- ) as unknown as ReturnType<StreamSimpleHandler>;
124
- }) as StreamSimpleHandler,
125
- });
126
- } catch (err) {
127
- console.error("[droid-cli] Failed to register provider:", err);
128
- }
129
- })();
141
+ try {
142
+ registerDroidProvider(pi, []);
143
+ } catch (err) {
144
+ console.error("[droid-cli] Failed to register provider:", err);
145
+ }
130
146
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion/droid-cli",
3
- "version": "0.11.33",
3
+ "version": "0.11.34",
4
4
  "description": "First-party Fusion pi extension that routes LLM calls through the Droid CLI subprocess.",
5
5
  "license": "MIT",
6
6
  "private": true,
@@ -58,7 +58,7 @@ describe("droid-cli extension entrypoint", () => {
58
58
  vi.restoreAllMocks();
59
59
  });
60
60
 
61
- it("registers provider droid-cli with discovered model mapping and streamSimple", async () => {
61
+ it("registers provider droid-cli synchronously without starting droid probes or discovery", async () => {
62
62
  const registerProvider = vi.fn();
63
63
  const mockPi = {
64
64
  registerProvider,
@@ -68,19 +68,20 @@ describe("droid-cli extension entrypoint", () => {
68
68
  };
69
69
 
70
70
  const mod = await import("../../index");
71
- mod.default(mockPi as never);
71
+ const result = mod.default(mockPi as never);
72
72
  await flushAsyncRegistration();
73
73
 
74
- expect(runtimeMocks.validateCliPresenceAsync).toHaveBeenCalledTimes(1);
75
- expect(runtimeMocks.validateCliAuthAsync).toHaveBeenCalledTimes(1);
76
- expect(runtimeMocks.discoverDroidModels).toHaveBeenCalledTimes(1);
74
+ expect(result).toBeUndefined();
75
+ expect(runtimeMocks.validateCliPresenceAsync).not.toHaveBeenCalled();
76
+ expect(runtimeMocks.validateCliAuthAsync).not.toHaveBeenCalled();
77
+ expect(runtimeMocks.discoverDroidModels).not.toHaveBeenCalled();
77
78
 
78
79
  expect(registerProvider).toHaveBeenCalledTimes(1);
79
80
  const [providerId, config] = registerProvider.mock.calls[0] as [string, {
80
81
  baseUrl: string;
81
82
  api: string;
82
83
  apiKey: string;
83
- models: Array<{ id: string; name: string; contextWindow: number; maxTokens: number }>;
84
+ models: unknown[];
84
85
  streamSimple: Function;
85
86
  }];
86
87
 
@@ -88,11 +89,43 @@ describe("droid-cli extension entrypoint", () => {
88
89
  expect(config.baseUrl).toBe("droid-cli");
89
90
  expect(config.api).toBe("droid-cli");
90
91
  expect(config.apiKey).toBe("unused");
91
- expect(config.models).toEqual([
92
+ expect(config.models).toEqual([]);
93
+ expect(typeof config.streamSimple).toBe("function");
94
+ });
95
+
96
+ it("runs validation once when a droid stream is actually used", async () => {
97
+ const registerProvider = vi.fn();
98
+ const mockPi = {
99
+ registerProvider,
100
+ on: vi.fn(),
101
+ getAllTools: vi.fn(() => []),
102
+ setActiveTools: vi.fn(),
103
+ };
104
+
105
+ const mod = await import("../../index");
106
+ mod.default(mockPi as never);
107
+ const config = registerProvider.mock.calls[0]?.[1] as {
108
+ streamSimple: (model: unknown, context: unknown, options?: Record<string, unknown>) => unknown;
109
+ };
110
+
111
+ config.streamSimple({ id: "droid-pro" }, { messages: [] }, {});
112
+ config.streamSimple({ id: "droid-pro" }, { messages: [] }, {});
113
+ await flushAsyncRegistration();
114
+
115
+ expect(runtimeMocks.validateCliPresenceAsync).toHaveBeenCalledTimes(1);
116
+ expect(runtimeMocks.validateCliAuthAsync).toHaveBeenCalledTimes(1);
117
+ expect(runtimeMocks.discoverDroidModels).not.toHaveBeenCalled();
118
+ });
119
+
120
+ it("discovers provider models only when explicitly requested", async () => {
121
+ const mod = await import("../../index");
122
+
123
+ await expect(mod.discoverDroidProviderModels()).resolves.toEqual([
92
124
  expect.objectContaining({ id: "droid-pro", name: "droid-pro", contextWindow: 200_000, maxTokens: 8_192 }),
93
125
  expect.objectContaining({ id: "droid-max", name: "droid-max", contextWindow: 200_000, maxTokens: 8_192 }),
94
126
  ]);
95
- expect(typeof config.streamSimple).toBe("function");
127
+
128
+ expect(runtimeMocks.discoverDroidModels).toHaveBeenCalledTimes(1);
96
129
  });
97
130
 
98
131
  it("activates all registered tools on session_start", async () => {
@@ -132,31 +165,24 @@ describe("droid-cli extension entrypoint", () => {
132
165
 
133
166
  const mod = await import("../../index");
134
167
  mod.default(mockPi as never);
168
+ const config = mockPi.registerProvider.mock.calls[0]?.[1] as {
169
+ streamSimple: (model: unknown, context: unknown, options?: Record<string, unknown>) => unknown;
170
+ };
171
+ config.streamSimple({ id: "droid-pro" }, { messages: [] }, {});
135
172
  await flushAsyncRegistration();
136
173
 
137
174
  expect(warnSpy).toHaveBeenCalledWith("[droid-cli] droid CLI missing");
138
175
  expect(runtimeMocks.validateCliAuthAsync).not.toHaveBeenCalled();
139
- expect(mockPi.registerProvider).toHaveBeenCalledTimes(1);
176
+ expect(mockPi.registerProvider).toHaveBeenCalledWith("droid-cli", expect.objectContaining({ models: [] }));
140
177
  });
141
178
 
142
179
  it("falls back to empty models when discovery throws", async () => {
143
180
  const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
144
181
  runtimeMocks.discoverDroidModels.mockRejectedValue(new Error("boom"));
145
182
 
146
- const registerProvider = vi.fn();
147
- const mockPi = {
148
- registerProvider,
149
- on: vi.fn(),
150
- getAllTools: vi.fn(() => []),
151
- setActiveTools: vi.fn(),
152
- };
153
-
154
183
  const mod = await import("../../index");
155
- mod.default(mockPi as never);
156
- await flushAsyncRegistration();
184
+ await expect(mod.discoverDroidProviderModels()).resolves.toEqual([]);
157
185
 
158
- const config = registerProvider.mock.calls[0]?.[1] as { models: unknown[] };
159
- expect(config.models).toEqual([]);
160
186
  expect(warnSpy).toHaveBeenCalledWith(
161
187
  "[droid-cli] model auto-discovery failed; registering provider with empty model list",
162
188
  expect.any(Error),
@@ -415,6 +415,16 @@ describe("validateCliPresenceAsync", () => {
415
415
  const result = await validateCliPresenceAsync();
416
416
  expect(result.ok).toBe(false);
417
417
  });
418
+
419
+ it("resolves ok=false instead of rejecting when droid spawn throws synchronously", async () => {
420
+ (spawn as any).mockImplementationOnce(() => {
421
+ throw new Error("Real AI CLI launch blocked during tests: droid --version");
422
+ });
423
+
424
+ await expect(validateCliPresenceAsync()).resolves.toMatchObject({
425
+ ok: false,
426
+ });
427
+ });
418
428
  });
419
429
 
420
430
  describe("validateCliAuthAsync", () => {
@@ -452,6 +462,21 @@ describe("validateCliAuthAsync", () => {
452
462
  );
453
463
  warnSpy.mockRestore();
454
464
  });
465
+
466
+ it("resolves false instead of rejecting when droid auth spawn throws synchronously", async () => {
467
+ (spawn as any).mockImplementationOnce(() => {
468
+ throw new Error(
469
+ "Real AI CLI launch blocked during tests: droid auth status",
470
+ );
471
+ });
472
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
473
+
474
+ await expect(validateCliAuthAsync()).resolves.toBe(false);
475
+ expect(warnSpy).toHaveBeenCalledWith(
476
+ expect.stringContaining("not authenticated"),
477
+ );
478
+ warnSpy.mockRestore();
479
+ });
455
480
  });
456
481
 
457
482
  describe("CLI flags", () => {
@@ -723,52 +748,44 @@ describe("discoverDroidModels", () => {
723
748
  vi.clearAllMocks();
724
749
  });
725
750
 
726
- it("parses model ids from JSON output", async () => {
751
+ it("parses model ids from droid exec --help output", async () => {
727
752
  (spawn as any).mockImplementationOnce(() => {
728
753
  const EventEmitter = require("node:events");
729
754
  const proc = new EventEmitter();
730
755
  proc.stdout = new EventEmitter();
731
756
  proc.stderr = new EventEmitter();
732
757
  setTimeout(() => {
733
- proc.stdout.emit("data", Buffer.from('[{"id":"droid-pro"},{"name":"droid-max"}]'));
758
+ proc.stdout.emit("data", Buffer.from(`Usage: droid exec [options] [prompt]
759
+
760
+ Available Models:
761
+ droid-pro Droid Pro
762
+ droid-max Droid Max
763
+
764
+ Model details:
765
+ - Droid Pro: prose, not a model id
766
+ `));
734
767
  proc.emit("exit", 0);
735
768
  }, 0);
736
769
  return proc;
737
770
  });
738
771
 
739
772
  await expect(discoverDroidModels()).resolves.toEqual(["droid-pro", "droid-max"]);
773
+ expect(spawn).toHaveBeenCalledWith("droid", ["exec", "--help"], expect.anything());
740
774
  });
741
775
 
742
- it("falls back across attempts and parses newline output", async () => {
743
- (spawn as any)
744
- .mockImplementationOnce(() => {
745
- const EventEmitter = require("node:events");
746
- const proc = new EventEmitter();
747
- proc.stdout = new EventEmitter();
748
- proc.stderr = new EventEmitter();
749
- setTimeout(() => proc.emit("exit", 1), 0);
750
- return proc;
751
- })
752
- .mockImplementationOnce(() => {
753
- const EventEmitter = require("node:events");
754
- const proc = new EventEmitter();
755
- proc.stdout = new EventEmitter();
756
- proc.stderr = new EventEmitter();
757
- setTimeout(() => proc.emit("exit", 1), 0);
758
- return proc;
759
- })
760
- .mockImplementationOnce(() => {
761
- const EventEmitter = require("node:events");
762
- const proc = new EventEmitter();
763
- proc.stdout = new EventEmitter();
764
- proc.stderr = new EventEmitter();
765
- setTimeout(() => {
766
- proc.stdout.emit("data", Buffer.from("droid-lite\ndroid-lite\ndroid-pro\n"));
767
- proc.emit("exit", 0);
768
- }, 0);
769
- return proc;
770
- });
771
-
772
- await expect(discoverDroidModels()).resolves.toEqual(["droid-lite", "droid-pro"]);
776
+ it("returns [] when droid exec --help exits without a model section", async () => {
777
+ (spawn as any).mockImplementationOnce(() => {
778
+ const EventEmitter = require("node:events");
779
+ const proc = new EventEmitter();
780
+ proc.stdout = new EventEmitter();
781
+ proc.stderr = new EventEmitter();
782
+ setTimeout(() => {
783
+ proc.stdout.emit("data", Buffer.from("Usage: droid exec\n\nOptions:\n --help\n"));
784
+ proc.emit("exit", 0);
785
+ }, 0);
786
+ return proc;
787
+ });
788
+
789
+ await expect(discoverDroidModels()).resolves.toEqual([]);
773
790
  });
774
791
  });