@runfusion/fusion 0.76.0-beta.3 → 0.77.0-beta.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 (175) hide show
  1. package/dist/bin.js +13802 -9587
  2. package/dist/child-process-worker.js +6472 -4028
  3. package/dist/client/.vite/manifest.json +280 -269
  4. package/dist/client/assets/AgentDetailView-0G9qFd4j.js +13 -0
  5. package/dist/client/assets/{AgentDetailView-Cc3ATg8a.css → AgentDetailView-jzgy1BAS.css} +1 -1
  6. package/dist/client/assets/{AgentPermissionPolicyEditor--u9jyUf2.js → AgentPermissionPolicyEditor-BM68g7wo.js} +1 -1
  7. package/dist/client/assets/AgentsView-DkOUZWw4.js +24 -0
  8. package/dist/client/assets/ChatView-BPSm2JIH.js +13 -0
  9. package/dist/client/assets/{CommandCenter-CSRYoveB.js → CommandCenter-DxRSFWNc.js} +26 -26
  10. package/dist/client/assets/CommandCenter-ilm-DbtI.css +1 -0
  11. package/dist/client/assets/{DevServerView-B9So_oYx.js → DevServerView-DO-bqJFE.js} +1 -1
  12. package/dist/client/assets/{DirectoryPicker-BhyDL_2m.js → DirectoryPicker-Cp2gddTE.js} +1 -1
  13. package/dist/client/assets/DocumentsView-D0E-3G96.js +1 -0
  14. package/dist/client/assets/EvalsView-BoFVq5hw.js +1 -0
  15. package/dist/client/assets/ExperimentalAgentOnboardingModal-CS1Sdogm.js +1 -0
  16. package/dist/client/assets/{GoalsView-B6X5_0Ve.js → GoalsView-sybf7JY4.js} +1 -1
  17. package/dist/client/assets/InsightsView-nHa7aShn.js +11 -0
  18. package/dist/client/assets/{MemoryView-DN_3IFmA.css → MemoryView-CdpQqPJJ.css} +1 -1
  19. package/dist/client/assets/MemoryView-D0IG44za.js +3 -0
  20. package/dist/client/assets/{PiExtensionsManager-B8At6fO8.js → PiExtensionsManager-CU76weJe.js} +2 -2
  21. package/dist/client/assets/PluginManager-DyT8XbcG.js +1 -0
  22. package/dist/client/assets/{PullRequestView-B1hZFrWo.js → PullRequestView-CnxWUSen.js} +2 -2
  23. package/dist/client/assets/{ReportModal-C46V_zEa.js → ReportModal-CMrmMQjD.js} +5 -5
  24. package/dist/client/assets/{ResearchView-D8G85BYN.js → ResearchView-BTytQSgy.js} +2 -2
  25. package/dist/client/assets/{SecretsView-CTri9LRK.js → SecretsView-BuSH5J87.js} +1 -1
  26. package/dist/client/assets/SessionTerminal-D04kYRrT.js +2 -0
  27. package/dist/client/assets/SettingsModal-C0FY8MPW.css +1 -0
  28. package/dist/client/assets/{SettingsModal-rUQcSTJp.js → SettingsModal-Dm-ngbRr.js} +1 -1
  29. package/dist/client/assets/{SettingsModal-DmfMotcd.css → SettingsModal-Ds0Yj47X.css} +1 -1
  30. package/dist/client/assets/SettingsModal-xSLhH7Tr.js +21 -0
  31. package/dist/client/assets/{SettingsTextareaRow-BirlBcem.js → SettingsTextareaRow-CHPgocEp.js} +1 -1
  32. package/dist/client/assets/{SetupWizardModal-xnCBM9EL.js → SetupWizardModal-y88aXNIQ.js} +2 -2
  33. package/dist/client/assets/{SkillsView-O5U0ep50.js → SkillsView-CYyQW1Hv.js} +1 -1
  34. package/dist/client/assets/{WorkflowNodeEditor-BX4d2qqF.js → WorkflowNodeEditor-hYeoz1X8.js} +3 -3
  35. package/dist/client/assets/{agent-import-generation-DnqVkPkz.js → agent-import-generation-CjiYXzCr.js} +1 -1
  36. package/dist/client/assets/agentsOrgChartLayout-C0UP_X3z.js +1 -0
  37. package/dist/client/assets/app-BgpuMvTU.js +13 -0
  38. package/dist/client/assets/app-BlexHhbW.js +13 -0
  39. package/dist/client/assets/app-BsuUOR0P.js +13 -0
  40. package/dist/client/assets/app-DQVOujmO.js +13 -0
  41. package/dist/client/assets/app-DjyTRx1N.js +5 -0
  42. package/dist/client/assets/app-Dniggype.js +13 -0
  43. package/dist/client/assets/app-EV-lyZ0T.js +5 -0
  44. package/dist/client/assets/{architectureDiagram-3BPJPVTR-gi467xY0.js → architectureDiagram-3BPJPVTR-Dd6GPcqM.js} +1 -1
  45. package/dist/client/assets/{blockDiagram-GPEHLZMM-B_gpcYiR.js → blockDiagram-GPEHLZMM-CC6pLxlz.js} +1 -1
  46. package/dist/client/assets/{c4Diagram-AAUBKEIU-DeylEYsQ.js → c4Diagram-AAUBKEIU-DxMP_l6y.js} +1 -1
  47. package/dist/client/assets/channel-DlCEMoEf.js +1 -0
  48. package/dist/client/assets/{chunk-2J33WTMH-BL2WY0HN.js → chunk-2J33WTMH-BKYToL43.js} +1 -1
  49. package/dist/client/assets/{chunk-4BX2VUAB-BkLExGMe.js → chunk-4BX2VUAB-Bg6rjQb3.js} +1 -1
  50. package/dist/client/assets/{chunk-55IACEB6-CSTvCF5T.js → chunk-55IACEB6-CPUwbbGa.js} +1 -1
  51. package/dist/client/assets/{chunk-727SXJPM-9J8pKk4x.js → chunk-727SXJPM-DScQBCvv.js} +1 -1
  52. package/dist/client/assets/{chunk-AQP2D5EJ-DXC1vPWr.js → chunk-AQP2D5EJ-DbX7uaXK.js} +1 -1
  53. package/dist/client/assets/{chunk-FMBD7UC4-CFRUb-zD.js → chunk-FMBD7UC4-DvYKea1c.js} +1 -1
  54. package/dist/client/assets/{chunk-ND2GUHAM-B87HFYS8.js → chunk-ND2GUHAM-CH-Tvw7w.js} +1 -1
  55. package/dist/client/assets/{chunk-QZHKN3VN-CTjHiGbd.js → chunk-QZHKN3VN-CbyEvOoM.js} +1 -1
  56. package/dist/client/assets/classDiagram-4FO5ZUOK-Bc92O8Ks.js +1 -0
  57. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Bc92O8Ks.js +1 -0
  58. package/dist/client/assets/{cose-bilkent-S5V4N54A-D3Edq3L9.js → cose-bilkent-S5V4N54A-BPB5fV3A.js} +1 -1
  59. package/dist/client/assets/{dagre-BM42HDAG-CwwbeQfN.js → dagre-BM42HDAG-CilYJ3rR.js} +1 -1
  60. package/dist/client/assets/{dashboard-view-QxQwJFLz.js → dashboard-view-BnGe8cWo.js} +1 -1
  61. package/dist/client/assets/{dashboard-view-BLAoW3D4.js → dashboard-view-DnVf3tmI.js} +1 -1
  62. package/dist/client/assets/{dashboard-view-DAlJxqiJ.js → dashboard-view-DoLU6FxZ.js} +1 -1
  63. package/dist/client/assets/{dashboard-view-aPzfv99T.js → dashboard-view-dChSM_So.js} +1 -1
  64. package/dist/client/assets/{diagram-2AECGRRQ-koJWWXE4.js → diagram-2AECGRRQ-m9u1Qhyx.js} +1 -1
  65. package/dist/client/assets/{diagram-5GNKFQAL-Yob5cOKT.js → diagram-5GNKFQAL-DVr7Kf0N.js} +1 -1
  66. package/dist/client/assets/{diagram-KO2AKTUF-DelvFSkK.js → diagram-KO2AKTUF-D7sgJDFx.js} +1 -1
  67. package/dist/client/assets/{diagram-LMA3HP47-CMput2h2.js → diagram-LMA3HP47-DNKNDS6r.js} +1 -1
  68. package/dist/client/assets/{diagram-OG6HWLK6-04VXDl79.js → diagram-OG6HWLK6-1Bff4FWn.js} +1 -1
  69. package/dist/client/assets/{erDiagram-TEJ5UH35-C9iP8Uyp.js → erDiagram-TEJ5UH35-DGua1UHN.js} +1 -1
  70. package/dist/client/assets/{flowDiagram-I6XJVG4X-DENQvu_t.js → flowDiagram-I6XJVG4X-UDfDtwsE.js} +1 -1
  71. package/dist/client/assets/{folder-open-D-554oji.js → folder-open-CteOypVk.js} +1 -1
  72. package/dist/client/assets/{ganttDiagram-6RSMTGT7-BqOttZAT.js → ganttDiagram-6RSMTGT7-COdmD328.js} +1 -1
  73. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CDcydi-5.js → gitGraphDiagram-PVQCEYII-SUSls7Kw.js} +1 -1
  74. package/dist/client/assets/index-0ovTXt3t.css +1 -0
  75. package/dist/client/assets/index-DpCHwyiD.js +2818 -0
  76. package/dist/client/assets/{infoDiagram-5YYISTIA-B5LQQnxt.js → infoDiagram-5YYISTIA-e_DloXj7.js} +1 -1
  77. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-DpFEt7D2.js → ishikawaDiagram-YF4QCWOH-DVWqihXg.js} +1 -1
  78. package/dist/client/assets/{journeyDiagram-JHISSGLW-MELtgu22.js → journeyDiagram-JHISSGLW-BcPY-XP0.js} +1 -1
  79. package/dist/client/assets/{kanban-definition-UN3LZRKU-h33PLATd.js → kanban-definition-UN3LZRKU-BCFG2Jle.js} +1 -1
  80. package/dist/client/assets/{mermaid.core-Dk2mUPOq.js → mermaid.core-5yPje9Bi.js} +4 -4
  81. package/dist/client/assets/{mindmap-definition-RKZ34NQL-B_T4O2-B.js → mindmap-definition-RKZ34NQL-DDApeT3K.js} +1 -1
  82. package/dist/client/assets/{pieDiagram-4H26LBE5-B1YIFkRl.js → pieDiagram-4H26LBE5-N61_jyeP.js} +1 -1
  83. package/dist/client/assets/{puzzle-hvecxlpJ.js → puzzle-BkaCP30D.js} +1 -1
  84. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-BoGQR_hO.js → quadrantDiagram-W4KKPZXB-C5qHiApF.js} +1 -1
  85. package/dist/client/assets/{requirementDiagram-4Y6WPE33-BSDmUBIx.js → requirementDiagram-4Y6WPE33-C71okgzt.js} +1 -1
  86. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-Dz_GqOa5.js → sankeyDiagram-5OEKKPKP-B2iKyLjB.js} +1 -1
  87. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-B6twjYUH.js → sequenceDiagram-3UESZ5HK-DfdoYKKk.js} +1 -1
  88. package/dist/client/assets/{shield-alert-BX4WRJOv.js → shield-alert-BNSeDB8l.js} +1 -1
  89. package/dist/client/assets/standing-instructions-template-pZtzo1lK.js +20 -0
  90. package/dist/client/assets/standing-instructions-template-w7Ouw_37.css +1 -0
  91. package/dist/client/assets/{stateDiagram-AJRCARHV-DuwqWLx-.js → stateDiagram-AJRCARHV-lS-sUi12.js} +1 -1
  92. package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-Bu8Sk187.js → stateDiagram-v2-BHNVJYJU-DXJNDrV9.js} +1 -1
  93. package/dist/client/assets/{timeline-definition-PNZ67QCA-BS6VnqSI.js → timeline-definition-PNZ67QCA-CCwvX81K.js} +1 -1
  94. package/dist/client/assets/{upload-CaDoyaMW.js → upload-CDovVbu2.js} +1 -1
  95. package/dist/client/assets/useDiscoveredSkillsCache-BYqP-afh.js +1 -0
  96. package/dist/client/assets/{users-C5uCLwVM.js → users-CTqECGLo.js} +1 -1
  97. package/dist/client/assets/{vennDiagram-CIIHVFJN-CUbzqT5Y.js → vennDiagram-CIIHVFJN-DaiR5nv9.js} +1 -1
  98. package/dist/client/assets/{wardley-L42UT6IY-Mv-NotFS.js → wardley-L42UT6IY-hA5IHyPW.js} +1 -1
  99. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DuYpvLZX.js → wardleyDiagram-YWT4CUSO-CILUNESc.js} +1 -1
  100. package/dist/client/assets/{xychartDiagram-2RQKCTM6-24_7QXdw.js → xychartDiagram-2RQKCTM6-72eNMmjz.js} +1 -1
  101. package/dist/client/index.html +2 -2
  102. package/dist/client/version.json +1 -1
  103. package/dist/droid-cli/package.json +1 -1
  104. package/dist/extension.js +10671 -6904
  105. package/dist/migrations/0059_fn_9037_tasks_source_agent_index.sql +3 -0
  106. package/dist/migrations/0060_fn_9059_workspace_coordination_leases.sql +10 -0
  107. package/dist/pi-claude-cli/package.json +1 -1
  108. package/dist/plugin-sdk/index.d.ts +190 -9
  109. package/dist/plugin-sdk/index.js +74 -28
  110. package/dist/plugins/fusion-plugin-acp-runtime/bundled.js +83 -29
  111. package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
  112. package/dist/plugins/fusion-plugin-claude-runtime/bundled.js +83 -29
  113. package/dist/plugins/fusion-plugin-claude-runtime/package.json +1 -1
  114. package/dist/plugins/fusion-plugin-cli-printing-press/bundled.js +74 -28
  115. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  116. package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +74 -28
  117. package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
  118. package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +1096 -73
  119. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  120. package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +74 -28
  121. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  122. package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +74 -28
  123. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  124. package/dist/plugins/fusion-plugin-grok-runtime/bundled.js +83 -29
  125. package/dist/plugins/fusion-plugin-grok-runtime/package.json +1 -1
  126. package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +302 -71
  127. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  128. package/dist/plugins/fusion-plugin-linear-import/bundled.js +74 -28
  129. package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
  130. package/dist/plugins/fusion-plugin-omp-runtime/bundled.js +83 -29
  131. package/dist/plugins/fusion-plugin-omp-runtime/package.json +1 -1
  132. package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +74 -28
  133. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  134. package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +74 -28
  135. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  136. package/dist/plugins/fusion-plugin-quality/bundled.js +176 -46
  137. package/dist/plugins/fusion-plugin-quality/package.json +1 -1
  138. package/dist/plugins/fusion-plugin-reports/bundled.js +74 -28
  139. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  140. package/dist/plugins/fusion-plugin-roadmap/bundled.js +74 -28
  141. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  142. package/dist/plugins/fusion-plugin-todos/bundled.js +74 -28
  143. package/dist/plugins/fusion-plugin-todos/package.json +1 -1
  144. package/dist/plugins/fusion-plugin-whatsapp-chat/bundled.js +74 -28
  145. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  146. package/package.json +1 -1
  147. package/skill/fusion/references/extension-tools.md +2 -0
  148. package/dist/client/assets/AgentDetailView-T767kKTg.js +0 -13
  149. package/dist/client/assets/AgentsView-6Ifu7qDr.js +0 -24
  150. package/dist/client/assets/ChatView-BV3lixQi.js +0 -13
  151. package/dist/client/assets/CommandCenter-CE4rYjHn.css +0 -1
  152. package/dist/client/assets/DocumentsView-pbERA7O-.js +0 -1
  153. package/dist/client/assets/EvalsView-DJQ4ltCg.js +0 -1
  154. package/dist/client/assets/ExperimentalAgentOnboardingModal-BwJuzkzB.js +0 -1
  155. package/dist/client/assets/InsightsView-CJgI0J7S.js +0 -11
  156. package/dist/client/assets/MemoryView-BHq1AHPu.js +0 -3
  157. package/dist/client/assets/PluginManager-k7hV7_9e.js +0 -1
  158. package/dist/client/assets/SessionTerminal-BRf6r4Vp.js +0 -2
  159. package/dist/client/assets/SettingsModal-B30rPfYC.css +0 -1
  160. package/dist/client/assets/SettingsModal-D0RBeZik.js +0 -21
  161. package/dist/client/assets/agentsOrgChartLayout-CKuzbhFf.js +0 -1
  162. package/dist/client/assets/app-B2FwULu2.js +0 -5
  163. package/dist/client/assets/app-B6nJaqAl.js +0 -13
  164. package/dist/client/assets/app-CGXZeIRc.js +0 -13
  165. package/dist/client/assets/app-CGtkeBF5.js +0 -13
  166. package/dist/client/assets/app-CNzN1Plu.js +0 -13
  167. package/dist/client/assets/app-DLs-f5yM.js +0 -13
  168. package/dist/client/assets/app-DsvtcRUG.js +0 -5
  169. package/dist/client/assets/channel-BoE8DeM4.js +0 -1
  170. package/dist/client/assets/classDiagram-4FO5ZUOK-qnbLX_9_.js +0 -1
  171. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-qnbLX_9_.js +0 -1
  172. package/dist/client/assets/index-CXTd3LAB.css +0 -1
  173. package/dist/client/assets/index-CtYRoouR.js +0 -2818
  174. package/dist/client/assets/standing-instructions-template-BJY317CC.js +0 -20
  175. package/dist/client/assets/standing-instructions-template-Ddi_4TIk.css +0 -1
@@ -5,6 +5,9 @@ var __export = (target, all) => {
5
5
  __defProp(target, name, { get: all[name], enumerable: true });
6
6
  };
7
7
 
8
+ // src/plugin-sdk-core-runtime-shim.mjs
9
+ import { spawn } from "node:child_process";
10
+
8
11
  // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@opentelemetry+api@1.9.0_better-sqlite3@12.9.0_pg@8.22.0_postgres@3.4.9/node_modules/drizzle-orm/entity.js
9
12
  var entityKind = Symbol.for("drizzle:entityKind");
10
13
  var hasOwnEntityKind = Symbol.for("drizzle:hasOwnEntityKind");
@@ -5776,7 +5779,9 @@ __export(project_exports, {
5776
5779
  workflowSettings: () => workflowSettings,
5777
5780
  workflowSteps: () => workflowSteps,
5778
5781
  workflowWorkItems: () => workflowWorkItems,
5779
- workflows: () => workflows
5782
+ workflows: () => workflows,
5783
+ workspaceCoordinationLeases: () => workspaceCoordinationLeases,
5784
+ workspaceLandIntents: () => workspaceLandIntents
5780
5785
  });
5781
5786
  var projectSchema = pgSchema(PROJECT_SCHEMA);
5782
5787
  var tasks = projectSchema.table("tasks", {
@@ -6043,6 +6048,9 @@ var tasks = projectSchema.table("tasks", {
6043
6048
  the gate is a full tasks-table scan. Sparse: most rows have NULL parent.
6044
6049
  */
6045
6050
  index("idxTasksSourceParentTaskId").on(t.sourceParentTaskId),
6051
+ /* FNXC:TaskRecommendations 2026-08-13-22:23: duplicate intake filters source
6052
+ * lineage on recommendation/agent creates; this sparse index avoids a task-table scan. */
6053
+ index("idxTasksProjectSourceAgentId").on(t.projectId, t.sourceAgentId).where(sql`${t.sourceAgentId} IS NOT NULL`),
6046
6054
  // FNXC:EphemeralAgentTaskCreation 2026-07-30-12:00: proposal retries share one stable key, so the database—not a read-before-create race—enforces at-most-once materialization.
6047
6055
  uniqueIndex("uqTasksProjectProposalClaimId").on(t.projectId, t.proposalClaimId).where(sql`${t.proposalClaimId} IS NOT NULL`),
6048
6056
  /*
@@ -6277,6 +6285,52 @@ var distributedTaskIdReservations = projectSchema.table("distributed_task_id_res
6277
6285
  index("idxDistributedTaskIdReservationsPrefixStatus").on(t.prefix, t.status),
6278
6286
  index("idxDistributedTaskIdReservationsExpiry").on(t.status, t.expiresAt)
6279
6287
  ]);
6288
+ var workspaceCoordinationLeases = projectSchema.table("workspace_coordination_leases", {
6289
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
6290
+ leaseKey: text("lease_key").notNull(),
6291
+ kind: text("kind").notNull(),
6292
+ ownerTaskId: text("owner_task_id").notNull(),
6293
+ ownerNodeId: text("owner_node_id").notNull(),
6294
+ ownerIncarnationId: text("owner_incarnation_id").notNull(),
6295
+ ownerRunId: text("owner_run_id"),
6296
+ fenceToken: bigint("fence_token", { mode: "bigint" }).notNull().default(sql`0`),
6297
+ fenceRefName: text("fence_ref_name"),
6298
+ fenceRefSha: text("fence_ref_sha"),
6299
+ status: text("status").notNull(),
6300
+ acquiredAt: text("acquired_at").notNull(),
6301
+ renewedAt: text("renewed_at").notNull(),
6302
+ expiresAt: text("expires_at").notNull(),
6303
+ createdAt: text("created_at").notNull(),
6304
+ updatedAt: text("updated_at").notNull()
6305
+ }, (t) => [
6306
+ primaryKey({ columns: [t.projectId, t.leaseKey] }),
6307
+ check("workspace_coordination_leases_kind_check", sql`${t.kind} IN ('acquire', 'land', 'merge-dispatch')`),
6308
+ check("workspace_coordination_leases_status_check", sql`${t.status} IN ('held', 'released', 'expired')`),
6309
+ index("idxWorkspaceCoordinationLeasesOwnerTask").on(t.projectId, t.ownerTaskId),
6310
+ index("idxWorkspaceCoordinationLeasesOwnerNode").on(t.projectId, t.ownerNodeId),
6311
+ index("idxWorkspaceCoordinationLeasesExpiry").on(t.status, t.expiresAt)
6312
+ ]);
6313
+ var workspaceLandIntents = projectSchema.table("workspace_land_intents", {
6314
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
6315
+ taskId: text("task_id").notNull(),
6316
+ repoRelPath: text("repo_rel_path").notNull(),
6317
+ remoteUrl: text("remote_url").notNull(),
6318
+ integrationRef: text("integration_ref").notNull(),
6319
+ intendedSha: text("intended_sha").notNull(),
6320
+ expectedTip: text("expected_tip").notNull(),
6321
+ fenceRefName: text("fence_ref_name").notNull(),
6322
+ fenceRefSha: text("fence_ref_sha").notNull(),
6323
+ ownerTaskId: text("owner_task_id").notNull(),
6324
+ ownerNodeId: text("owner_node_id").notNull(),
6325
+ ownerIncarnationId: text("owner_incarnation_id").notNull(),
6326
+ fenceToken: bigint("fence_token", { mode: "bigint" }).notNull(),
6327
+ status: text("status").notNull(),
6328
+ resolvedSha: text("resolved_sha"),
6329
+ resolution: text("resolution"),
6330
+ createdAt: text("created_at").notNull(),
6331
+ updatedAt: text("updated_at").notNull(),
6332
+ resolvedAt: text("resolved_at")
6333
+ }, (t) => [primaryKey({ columns: [t.projectId, t.taskId, t.repoRelPath] }), check("workspace_land_intents_status_check", sql`${t.status} IN ('pending', 'recorded', 'abandoned')`), check("workspace_land_intents_resolution_check", sql`${t.resolution} IS NULL OR ${t.resolution} IN ('landed', 'not-landed')`), index("idxWorkspaceLandIntentsStatus").on(t.projectId, t.status)]);
6280
6334
  var symbolLocks = projectSchema.table("symbol_locks", {
6281
6335
  projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
6282
6336
  symbolKey: text("symbol_key").notNull(),
@@ -8851,6 +8905,11 @@ var DEFAULT_GLOBAL_SETTINGS = {
8851
8905
  Critical-action confirmation dialogs stay enabled by default. This global-only preference may opt an operator into primary/default auto-approval, but project settings cannot enable it for collaborators.
8852
8906
  */
8853
8907
  skipConfirmationDialogs: false,
8908
+ /*
8909
+ FNXC:QuickEntry 2026-08-16-03:15:
8910
+ Quick Add keeps its historical Enter-to-submit behavior by default; only an operator's global preference may opt into newline-first entry.
8911
+ */
8912
+ quickAddSubmitOnEnter: true,
8854
8913
  language: void 0,
8855
8914
  defaultProvider: void 0,
8856
8915
  defaultCredentialInstanceId: void 0,
@@ -9313,9 +9372,6 @@ var DEFAULT_PROJECT_SETTINGS = {
9313
9372
  * New and unconfigured projects default AI merge to sync a dirty checked-out integration branch, restoring the legacy stash → fast-forward → restore landing behavior. Explicit persisted merger.allowDirtyLocalCheckoutSync values still win, and no existing-project migration stamps this default into storage.
9314
9373
  */
9315
9374
  merger: { mode: "ai", maxReviewPasses: 3, allowDirtyLocalCheckoutSync: true },
9316
- mergeDiffVolumeMinLines: void 0,
9317
- mergeDiffVolumeThreshold: void 0,
9318
- mergeDiffVolumeAllowlist: void 0,
9319
9375
  requiredChecks: void 0,
9320
9376
  mergeStrategyOverlapBehavior: "flip-to-prefer-branch",
9321
9377
  postMergeAuditMode: "warn",
@@ -16059,8 +16115,8 @@ async function resolveWorkflowIrById(store, workflowId, irCache) {
16059
16115
  } catch {
16060
16116
  projectId = void 0;
16061
16117
  }
16062
- const cacheKey = projectId ? `${workflowId}\0${projectId}` : workflowId;
16063
- const cached = irCache?.get(cacheKey);
16118
+ const cacheKey2 = projectId ? `${workflowId}\0${projectId}` : workflowId;
16119
+ const cached = irCache?.get(cacheKey2);
16064
16120
  if (cached) return cached;
16065
16121
  if (isBuiltinWorkflowId(workflowId)) {
16066
16122
  const builtin = getBuiltinWorkflow(workflowId);
@@ -16070,14 +16126,14 @@ async function resolveWorkflowIrById(store, workflowId, irCache) {
16070
16126
  const overrides = projectId ? await (store.getWorkflowPromptOverridesAsync?.(workflowId, projectId) ?? store.getWorkflowPromptOverrides?.(workflowId, projectId)) : void 0;
16071
16127
  const effective = applyPromptOverridesToIr(resolved, overrides);
16072
16128
  const answer = fellBackToDefault ? markFellBack(effective) : effective;
16073
- irCache?.set(cacheKey, answer);
16129
+ irCache?.set(cacheKey2, answer);
16074
16130
  return answer;
16075
16131
  }
16076
16132
  try {
16077
16133
  const def = await store.getWorkflowDefinition(workflowId);
16078
16134
  if (!def) return markFellBack(defaultCodingWorkflowIr());
16079
16135
  const ir = typeof def.ir === "string" ? parseWorkflowIr(def.ir) : def.ir;
16080
- irCache?.set(cacheKey, ir);
16136
+ irCache?.set(cacheKey2, ir);
16081
16137
  return ir;
16082
16138
  } catch {
16083
16139
  return markFellBack(defaultCodingWorkflowIr());
@@ -17966,10 +18022,6 @@ var AgentStore = class _AgentStore extends EventEmitter {
17966
18022
  };
17967
18023
  await this.writeAgent(updated);
17968
18024
  this.emit("agent:stateChanged", agentId, currentState, newState);
17969
- if (this.asyncLayer) try {
17970
- await appendAgentActivityEvent(this.asyncLayer, { type: "agent:state-changed", attributionClaim: resolveAgentActivityAttribution([{ id: agentId, provenance: "roster" }], "executor"), taskId: updated.taskId, occurredAt: updated.updatedAt, discriminator: updated.updatedAt, metadata: { fromState: currentState, toState: newState, source: "update" } });
17971
- } catch {
17972
- }
17973
18025
  this.emit("agent:updated", updated, currentState);
17974
18026
  return updated;
17975
18027
  });
@@ -18461,10 +18513,10 @@ var AgentStore = class _AgentStore extends EventEmitter {
18461
18513
  return agents2;
18462
18514
  }
18463
18515
  /*
18464
- FNXC:MemoryAgent 2026-08-11-09:41:
18465
- Memory Keeper is custom because it is not a workflow-stage principal. Unlike the four routed
18466
- owners its heartbeat is enabled, while auto-claim remains off because it only maintains memory.
18467
- This runs during init, where createAgent name collisions would abort startup; preflight probes,
18516
+ FNXC:MemoryAgent 2026-08-16-02:31:
18517
+ Memory Keeper is custom because it is not a workflow-stage principal. Its heartbeat defaults off
18518
+ until an operator opts in, while auto-claim remains off because it only maintains memory. This
18519
+ runs during init, where createAgent name collisions would abort startup; preflight probes,
18468
18520
  a fallback name, a null degraded result, and the init-side catch keep an operator's same-named
18469
18521
  agent untouched and the project runnable.
18470
18522
  */
@@ -18490,7 +18542,13 @@ var AgentStore = class _AgentStore extends EventEmitter {
18490
18542
  roles: [...BUILTIN_MEMORY_AGENT_DEFAULT.roles],
18491
18543
  title: BUILTIN_MEMORY_AGENT_DEFAULT.title,
18492
18544
  metadata: { [BUILTIN_MEMORY_AGENT_PROVENANCE_KEY]: true },
18493
- runtimeConfig: { enabled: true, autoClaimRelevantTasks: false, heartbeatIntervalMs: 36e5 },
18545
+ /*
18546
+ FNXC:MemoryAgent 2026-08-16-02:31:
18547
+ Memory consolidation is opt-in: newly provisioned Memory Keepers must not begin
18548
+ hourly autonomous heartbeats until an operator enables the existing heartbeat toggle.
18549
+ Keep auto-claim off and the one-hour interval ready for that later opt-in.
18550
+ */
18551
+ runtimeConfig: { enabled: false, autoClaimRelevantTasks: false, heartbeatIntervalMs: 36e5 },
18494
18552
  instructionsText: BUILTIN_MEMORY_AGENT_DEFAULT.instructionsText,
18495
18553
  soul: BUILTIN_MEMORY_AGENT_DEFAULT.soul,
18496
18554
  bundleConfig: { ...BUILTIN_MEMORY_AGENT_DEFAULT.bundleConfig, files: [...BUILTIN_MEMORY_AGENT_DEFAULT.bundleConfig.files] }
@@ -18505,7 +18563,9 @@ var AgentStore = class _AgentStore extends EventEmitter {
18505
18563
  return owner;
18506
18564
  }
18507
18565
  const metadata = { ...owner.metadata ?? {}, [BUILTIN_MEMORY_AGENT_PROVENANCE_KEY]: true };
18508
- const runtimeConfig = { ...owner.runtimeConfig ?? {}, enabled: true, autoClaimRelevantTasks: false, heartbeatIntervalMs: 36e5 };
18566
+ const currentRuntimeConfig = owner.runtimeConfig ?? {};
18567
+ const enabled = typeof currentRuntimeConfig.enabled === "boolean" ? currentRuntimeConfig.enabled : false;
18568
+ const runtimeConfig = currentRuntimeConfig.enabled === enabled && currentRuntimeConfig.autoClaimRelevantTasks === false && currentRuntimeConfig.heartbeatIntervalMs === DEFAULT_AGENT_HEARTBEAT_INTERVAL_MS ? currentRuntimeConfig : { ...currentRuntimeConfig, enabled, autoClaimRelevantTasks: false, heartbeatIntervalMs: DEFAULT_AGENT_HEARTBEAT_INTERVAL_MS };
18509
18569
  const updates = {
18510
18570
  roles: [...BUILTIN_MEMORY_AGENT_DEFAULT.roles],
18511
18571
  role: "custom",
@@ -18515,7 +18575,9 @@ var AgentStore = class _AgentStore extends EventEmitter {
18515
18575
  instructionsText: owner.instructionsText?.trim() ? owner.instructionsText : BUILTIN_MEMORY_AGENT_DEFAULT.instructionsText,
18516
18576
  soul: owner.soul?.trim() ? owner.soul : BUILTIN_MEMORY_AGENT_DEFAULT.soul
18517
18577
  };
18518
- owner = { ...owner, ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
18578
+ const nextOwner = { ...owner, ...updates };
18579
+ if (JSON.stringify(nextOwner) === JSON.stringify(owner)) return owner;
18580
+ owner = { ...nextOwner, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
18519
18581
  await this.writeAgent(owner, executor);
18520
18582
  return owner;
18521
18583
  };
@@ -19387,19 +19449,6 @@ var AgentStore = class _AgentStore extends EventEmitter {
19387
19449
  this.agentSnapshotCache.set(agent.id, this.watchSnapshotOf(agent));
19388
19450
  if (stateChanged) {
19389
19451
  this.emit("agent:stateChanged", agent.id, previousState, agent.state);
19390
- if (this.asyncLayer) {
19391
- try {
19392
- await appendAgentActivityEvent(this.asyncLayer, {
19393
- type: "agent:state-changed",
19394
- attributionClaim: resolveAgentActivityAttribution([{ id: agent.id, provenance: "roster" }], "executor"),
19395
- taskId: agent.taskId,
19396
- occurredAt: agent.updatedAt,
19397
- discriminator: agent.updatedAt,
19398
- metadata: { fromState: previousState, toState: agent.state, source: "reconciliation" }
19399
- });
19400
- } catch {
19401
- }
19402
- }
19403
19452
  this.emit("agent:updated", agent, previousState);
19404
19453
  } else {
19405
19454
  this.emit("agent:updated", agent);
@@ -19458,36 +19507,204 @@ var AgentStore = class _AgentStore extends EventEmitter {
19458
19507
  }
19459
19508
  };
19460
19509
 
19510
+ // src/plugin-sdk-core-runtime-shim.mjs
19511
+ function superviseSpawn(command, args = [], options = {}) {
19512
+ const killGraceMs = options.killGraceMs ?? 2e3;
19513
+ const maxLifetimeMs = options.maxLifetimeMs;
19514
+ const spawnOptions = { ...options };
19515
+ delete spawnOptions.killGraceMs;
19516
+ delete spawnOptions.maxLifetimeMs;
19517
+ const processGroup = globalThis.process.platform !== "win32";
19518
+ const child = spawn(command, [...args], { ...spawnOptions, detached: processGroup });
19519
+ const pgid = processGroup && typeof child.pid === "number" ? child.pid : null;
19520
+ let settled = false;
19521
+ let resolveExit;
19522
+ const waitExit = new Promise((resolve3) => {
19523
+ resolveExit = resolve3;
19524
+ });
19525
+ const killProcess = (signal = "SIGTERM") => {
19526
+ if (typeof child.pid !== "number") return;
19527
+ try {
19528
+ if (pgid != null) globalThis.process.kill(-pgid, signal);
19529
+ else child.kill(signal);
19530
+ } catch {
19531
+ try {
19532
+ child.kill(signal);
19533
+ } catch {
19534
+ }
19535
+ }
19536
+ };
19537
+ let lifetimeTimer = null;
19538
+ if (typeof maxLifetimeMs === "number" && Number.isFinite(maxLifetimeMs) && maxLifetimeMs > 0) {
19539
+ lifetimeTimer = globalThis.setTimeout(() => {
19540
+ if (settled) return;
19541
+ killProcess("SIGTERM");
19542
+ const escalationTimer = globalThis.setTimeout(() => {
19543
+ if (!settled) killProcess("SIGKILL");
19544
+ }, killGraceMs);
19545
+ escalationTimer.unref?.();
19546
+ }, maxLifetimeMs);
19547
+ lifetimeTimer.unref?.();
19548
+ }
19549
+ child.once("close", (code, signal) => {
19550
+ settled = true;
19551
+ if (lifetimeTimer) globalThis.clearTimeout(lifetimeTimer);
19552
+ resolveExit?.({ code, signal });
19553
+ });
19554
+ child.on("error", () => {
19555
+ });
19556
+ return {
19557
+ pid: child.pid,
19558
+ pgid,
19559
+ child,
19560
+ kill(signal = "SIGTERM") {
19561
+ if (settled) return;
19562
+ killProcess(signal);
19563
+ if (signal === "SIGTERM") {
19564
+ const escalationTimer = globalThis.setTimeout(() => {
19565
+ if (!settled) killProcess("SIGKILL");
19566
+ }, killGraceMs);
19567
+ escalationTimer.unref?.();
19568
+ }
19569
+ },
19570
+ waitExit() {
19571
+ return waitExit;
19572
+ }
19573
+ };
19574
+ }
19575
+
19461
19576
  // ../plugin-sdk/src/index.ts
19462
19577
  function definePlugin(plugin2) {
19463
19578
  return plugin2;
19464
19579
  }
19465
19580
 
19466
19581
  // ../../plugins/fusion-plugin-hermes-runtime/src/cli-spawn.ts
19467
- import { spawn, spawnSync } from "node:child_process";
19582
+ import { spawn as spawn3 } from "node:child_process";
19468
19583
  import os from "node:os";
19469
- import path, { sep as PATH_SEP } from "node:path";
19470
- var resolvedBinaryCache = /* @__PURE__ */ new Map();
19471
- function resolveBinaryForSpawn(binary) {
19472
- if (process.platform !== "win32") return binary;
19473
- if (binary.includes(PATH_SEP) || binary.includes("/") || /\.[a-z]{2,4}$/i.test(binary)) {
19474
- return binary;
19475
- }
19476
- const cached = resolvedBinaryCache.get(binary);
19477
- if (cached) return cached;
19478
- try {
19479
- const result = spawnSync("where", [binary], { encoding: "utf-8" });
19480
- if (result.status === 0) {
19481
- const first = (result.stdout ?? "").trim().split(/\r?\n/)[0];
19482
- if (first?.length) {
19483
- resolvedBinaryCache.set(binary, first);
19484
- return first;
19485
- }
19584
+ import path from "node:path";
19585
+
19586
+ // ../../plugins/fusion-plugin-hermes-runtime/src/windows-binary-launch.ts
19587
+ import { spawn as spawn2 } from "node:child_process";
19588
+ import { win32 } from "node:path";
19589
+ var DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD";
19590
+ var NEGATIVE_RESULT_TTL_MS = 3e4;
19591
+ var MAX_CACHE_ENTRIES = 32;
19592
+ var resolutionCache = /* @__PURE__ */ new Map();
19593
+ function effectivePathExt(env) {
19594
+ const raw = env.PATHEXT?.trim() || DEFAULT_PATHEXT;
19595
+ return raw.split(";").map((entry) => entry.trim()).filter(Boolean).map((entry) => (entry.startsWith(".") ? entry : `.${entry}`).toLowerCase());
19596
+ }
19597
+ function isWindowsPath(value) {
19598
+ return value.includes("\\") || value.includes("/") || /^[A-Za-z]:/.test(value) || /^\\\\/.test(value);
19599
+ }
19600
+ function cacheKey(binary, platform, env) {
19601
+ return `${platform}|${binary.toLowerCase()}|${env.PATH ?? ""}|${env.PATHEXT ?? ""}`;
19602
+ }
19603
+ function evictOldestIfNeeded() {
19604
+ while (resolutionCache.size >= MAX_CACHE_ENTRIES) {
19605
+ const oldest = resolutionCache.keys().next().value;
19606
+ if (!oldest) return;
19607
+ resolutionCache.delete(oldest);
19608
+ }
19609
+ }
19610
+ async function defaultRunWhere(binary, env) {
19611
+ return new Promise((resolve3) => {
19612
+ let child;
19613
+ try {
19614
+ child = spawn2("where", [binary], {
19615
+ env,
19616
+ windowsHide: true,
19617
+ stdio: ["ignore", "pipe", "ignore"]
19618
+ });
19619
+ } catch {
19620
+ resolve3(void 0);
19621
+ return;
19486
19622
  }
19487
- } catch {
19623
+ let stdout = "";
19624
+ child.stdout?.on("data", (chunk) => {
19625
+ stdout += chunk.toString("utf8");
19626
+ });
19627
+ child.once("error", () => resolve3(void 0));
19628
+ child.once("close", (code) => resolve3(code === 0 && stdout.trim() ? stdout : void 0));
19629
+ });
19630
+ }
19631
+ function chooseWhereCandidate(stdout, env) {
19632
+ const directories = [];
19633
+ const byDirectory = /* @__PURE__ */ new Map();
19634
+ for (const entry of stdout.split(/\r?\n/).map((line2) => line2.trim()).filter(Boolean)) {
19635
+ const directory = win32.dirname(entry).replace(/[\\/]+$/, "").toLowerCase();
19636
+ const group = byDirectory.get(directory) ?? { entries: [] };
19637
+ if (!byDirectory.has(directory)) {
19638
+ byDirectory.set(directory, group);
19639
+ directories.push(group);
19640
+ }
19641
+ group.entries.push(entry);
19642
+ }
19643
+ const firstDirectory = directories[0];
19644
+ if (!firstDirectory) return void 0;
19645
+ const pathExt = effectivePathExt(env);
19646
+ return [...firstDirectory.entries].sort((left, right) => {
19647
+ const leftIndex = pathExt.indexOf(win32.extname(left).toLowerCase());
19648
+ const rightIndex = pathExt.indexOf(win32.extname(right).toLowerCase());
19649
+ const normalizedLeft = leftIndex === -1 ? Number.MAX_SAFE_INTEGER : leftIndex;
19650
+ const normalizedRight = rightIndex === -1 ? Number.MAX_SAFE_INTEGER : rightIndex;
19651
+ return normalizedLeft - normalizedRight;
19652
+ })[0];
19653
+ }
19654
+ async function resolveHermesBinaryPath(binary, deps = {}) {
19655
+ const platform = deps.platform ?? process.platform;
19656
+ const env = deps.env ?? process.env;
19657
+ if (platform !== "win32" || isWindowsPath(binary)) return platform === "win32" && isWindowsPath(binary) ? binary : void 0;
19658
+ const lookup = async () => {
19659
+ const output = await (deps.runWhere ?? defaultRunWhere)(binary, env);
19660
+ return output ? chooseWhereCandidate(output, env) : void 0;
19661
+ };
19662
+ if (deps.runWhere) return lookup();
19663
+ const key = cacheKey(binary, platform, env);
19664
+ const cached = resolutionCache.get(key);
19665
+ if (cached) {
19666
+ const result = await cached.promise;
19667
+ if (result !== void 0 || Date.now() - cached.createdAt < NEGATIVE_RESULT_TTL_MS) return result;
19668
+ resolutionCache.delete(key);
19669
+ }
19670
+ evictOldestIfNeeded();
19671
+ const entry = { promise: lookup(), createdAt: Date.now() };
19672
+ resolutionCache.set(key, entry);
19673
+ entry.promise.catch(() => {
19674
+ if (resolutionCache.get(key) === entry) resolutionCache.delete(key);
19675
+ });
19676
+ return entry.promise;
19677
+ }
19678
+ function escapeWindowsShellCommand(command) {
19679
+ return command.replace(/([()%!^<>&|;,\s])/g, "^$1");
19680
+ }
19681
+ function escapeWindowsShellArgument(arg) {
19682
+ const quoted = arg.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\*)$/g, "$1$1");
19683
+ return `"${quoted}"`.replace(/([()%!^<>&|;,])/g, "^$1");
19684
+ }
19685
+ async function resolveHermesLaunch(binary, args, deps = {}) {
19686
+ const platform = deps.platform ?? process.platform;
19687
+ if (platform !== "win32") return { command: binary, args: [...args] };
19688
+ const env = deps.env ?? process.env;
19689
+ const resolved = await resolveHermesBinaryPath(binary, { ...deps, platform, env });
19690
+ const executable = resolved ?? binary;
19691
+ const extension = win32.extname(executable).toLowerCase();
19692
+ if (extension === ".cmd" || extension === ".bat") {
19693
+ const commandLine = `"${escapeWindowsShellCommand(executable)} ${args.map(escapeWindowsShellArgument).join(" ")}"`;
19694
+ return {
19695
+ command: env.ComSpec ?? "cmd.exe",
19696
+ args: ["/d", "/s", "/c", commandLine],
19697
+ windowsVerbatimArguments: true,
19698
+ resolvedBinaryPath: resolved
19699
+ };
19488
19700
  }
19489
- return binary;
19701
+ return { command: executable, args: [...args], resolvedBinaryPath: resolved };
19702
+ }
19703
+ function __resetHermesLaunchCacheForTests() {
19704
+ resolutionCache.clear();
19490
19705
  }
19706
+
19707
+ // ../../plugins/fusion-plugin-hermes-runtime/src/cli-spawn.ts
19491
19708
  var ANSI_RE = /\x1b\[[0-9;]*[A-Za-z]/g;
19492
19709
  var SESSION_ID_RE = /^session_id:\s+([0-9]{8}_[0-9]{6}_[0-9a-f]{6})\s*$/m;
19493
19710
  var CHROME_LINE_RES = [
@@ -19534,13 +19751,16 @@ function hermesProfileHome(profileName) {
19534
19751
  return path.join(base, "profiles", profileName);
19535
19752
  }
19536
19753
  async function listHermesProfiles(opts) {
19537
- const binary = resolveBinaryForSpawn(opts?.binaryPath ?? "hermes");
19754
+ const binary = opts?.binaryPath ?? "hermes";
19538
19755
  const timeoutMs = opts?.timeoutMs ?? 5e3;
19756
+ const spawnEnv = { ...process.env };
19757
+ const launch = await resolveHermesLaunch(binary, ["profile", "list"], { env: spawnEnv });
19539
19758
  return new Promise((resolve3, reject) => {
19540
19759
  let settled = false;
19541
- const child = spawn(binary, ["profile", "list"], {
19760
+ const child = spawn3(launch.command, launch.args, {
19542
19761
  stdio: ["ignore", "pipe", "pipe"],
19543
- env: { ...process.env }
19762
+ env: spawnEnv,
19763
+ windowsVerbatimArguments: launch.windowsVerbatimArguments
19544
19764
  });
19545
19765
  const timer = setTimeout(() => {
19546
19766
  if (settled) return;
@@ -19652,22 +19872,26 @@ function buildHermesArgs(prompt, settings, resumeSessionId) {
19652
19872
  }
19653
19873
  async function invokeHermesCli(prompt, settings, resumeSessionId, signal) {
19654
19874
  const args = buildHermesArgs(prompt, settings, resumeSessionId);
19655
- const binary = resolveBinaryForSpawn(settings.binaryPath);
19875
+ const spawnEnv = { ...process.env, PYTHONUNBUFFERED: "1" };
19876
+ if (settings.profile) {
19877
+ spawnEnv.HERMES_HOME = hermesProfileHome(settings.profile);
19878
+ }
19879
+ const launch = await resolveHermesLaunch(settings.binaryPath, args, { env: spawnEnv });
19656
19880
  return new Promise((resolve3, reject) => {
19657
19881
  let settled = false;
19658
- const spawnEnv = { ...process.env, PYTHONUNBUFFERED: "1" };
19659
- if (settings.profile) {
19660
- spawnEnv.HERMES_HOME = hermesProfileHome(settings.profile);
19661
- }
19662
- const child = spawn(binary, args, {
19882
+ const supervised = superviseSpawn(launch.command, launch.args, {
19663
19883
  stdio: ["ignore", "pipe", "pipe"],
19664
- env: spawnEnv
19884
+ env: spawnEnv,
19885
+ windowsVerbatimArguments: launch.windowsVerbatimArguments,
19886
+ maxLifetimeMs: settings.cliTimeoutMs + 2100,
19887
+ killGraceMs: 2e3
19665
19888
  });
19889
+ const child = supervised.child;
19666
19890
  const hardKillTimer = setTimeout(() => {
19667
19891
  if (settled) return;
19668
19892
  settled = true;
19669
19893
  try {
19670
- child.kill("SIGKILL");
19894
+ supervised.kill("SIGKILL");
19671
19895
  } catch {
19672
19896
  }
19673
19897
  reject(new Error(`hermes: process timed out after ${settings.cliTimeoutMs}ms`));
@@ -19677,7 +19901,7 @@ async function invokeHermesCli(prompt, settings, resumeSessionId, signal) {
19677
19901
  settled = true;
19678
19902
  clearTimeout(hardKillTimer);
19679
19903
  try {
19680
- child.kill("SIGTERM");
19904
+ supervised.kill("SIGTERM");
19681
19905
  } catch {
19682
19906
  }
19683
19907
  reject(new Error("hermes: invocation aborted"));
@@ -19961,20 +20185,22 @@ ${prompt}`;
19961
20185
  };
19962
20186
 
19963
20187
  // ../../plugins/fusion-plugin-hermes-runtime/src/probe.ts
19964
- import { spawn as spawn2 } from "node:child_process";
20188
+ import { spawn as spawn4 } from "node:child_process";
19965
20189
  var DEFAULT_PROBE_TIMEOUT_MS = 2e3;
19966
20190
  async function probeHermesBinary(opts) {
19967
20191
  const startedAt = Date.now();
19968
20192
  const binary = typeof opts?.binaryPath === "string" && opts.binaryPath.trim().length > 0 ? opts.binaryPath.trim() : "hermes";
19969
20193
  const timeoutMs = opts?.timeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS;
19970
- const resolvedPath = await tryResolveBinaryPath(binary);
20194
+ const launch = await resolveHermesLaunch(binary, ["--version"], { env: process.env });
20195
+ const resolvedPath = launch.resolvedBinaryPath ?? await tryResolvePosixBinaryPath(binary);
19971
20196
  return new Promise((resolvePromise) => {
19972
20197
  const finish = (result) => {
19973
20198
  resolvePromise({ ...result, probeDurationMs: Date.now() - startedAt });
19974
20199
  };
19975
20200
  let settled = false;
19976
- const child = spawn2(resolvedPath ?? binary, ["--version"], {
19977
- stdio: ["ignore", "pipe", "pipe"]
20201
+ const child = spawn4(launch.command, launch.args, {
20202
+ stdio: ["ignore", "pipe", "pipe"],
20203
+ windowsVerbatimArguments: launch.windowsVerbatimArguments
19978
20204
  });
19979
20205
  const timer = setTimeout(() => {
19980
20206
  if (settled) return;
@@ -20028,10 +20254,10 @@ async function probeHermesBinary(opts) {
20028
20254
  });
20029
20255
  });
20030
20256
  }
20031
- async function tryResolveBinaryPath(binary) {
20257
+ async function tryResolvePosixBinaryPath(binary) {
20258
+ if (process.platform === "win32") return void 0;
20032
20259
  return new Promise((resolvePromise) => {
20033
- const which = process.platform === "win32" ? "where" : "which";
20034
- const child = spawn2(which, [binary], { stdio: ["ignore", "pipe", "ignore"] });
20260
+ const child = spawn4("which", [binary], { stdio: ["ignore", "pipe", "ignore"] });
20035
20261
  let out = "";
20036
20262
  child.stdout?.on("data", (chunk) => {
20037
20263
  out += chunk.toString("utf-8");
@@ -20111,8 +20337,11 @@ export {
20111
20337
  COMPUTER_USE_SKILL_NAME,
20112
20338
  HERMES_RUNTIME_ID,
20113
20339
  HermesRuntimeAdapter,
20340
+ __resetHermesLaunchCacheForTests,
20114
20341
  buildHermesArgs,
20115
20342
  index_default as default,
20343
+ escapeWindowsShellArgument,
20344
+ escapeWindowsShellCommand,
20116
20345
  getComputerUseSkillSourceCandidates,
20117
20346
  hermesRuntimeFactory,
20118
20347
  hermesRuntimeMetadata,
@@ -20125,6 +20354,8 @@ export {
20125
20354
  resolveBundledComputerUseSkillSource,
20126
20355
  resolveBundledFusionSkillSource,
20127
20356
  resolveCliSettings,
20357
+ resolveHermesBinaryPath,
20128
20358
  resolveHermesHome,
20359
+ resolveHermesLaunch,
20129
20360
  shouldInstallComputerUseSkill
20130
20361
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion-plugin-examples/hermes-runtime",
3
- "version": "0.2.85-beta.3",
3
+ "version": "0.2.86-beta.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {