windmill-components 1.677.1 → 1.687.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 (354) hide show
  1. package/package/components/AppConnectInner.svelte +6 -0
  2. package/package/components/CiTestResults.svelte +64 -0
  3. package/package/components/CiTestResults.svelte.d.ts +7 -0
  4. package/package/components/CompareWorkspaces.svelte +626 -418
  5. package/package/components/DBManager.svelte +35 -4
  6. package/package/components/DBManager.svelte.d.ts +2 -0
  7. package/package/components/DBManagerContent.svelte +3 -1
  8. package/package/components/DBManagerContent.svelte.d.ts +3 -0
  9. package/package/components/DBManagerDrawer.svelte +145 -3
  10. package/package/components/DBTableEditor.svelte +14 -4
  11. package/package/components/DatatablePicker.svelte +2 -5
  12. package/package/components/DatatableSchemaDiff.svelte +531 -0
  13. package/package/components/DatatableSchemaDiff.svelte.d.ts +29 -0
  14. package/package/components/DedicatedWorkersSelector.svelte +4 -2
  15. package/package/components/DefaultTagsInner.svelte +42 -2
  16. package/package/components/DeployWorkspaceDrawer.svelte +1 -1
  17. package/package/components/Dev.svelte +20 -3
  18. package/package/components/Editor.svelte +1 -1
  19. package/package/components/EditorBar.svelte +1 -1
  20. package/package/components/EditorBar.svelte.d.ts +1 -1
  21. package/package/components/FlowStatusViewerInner.svelte +269 -220
  22. package/package/components/FlowTimeline.svelte +1 -1
  23. package/package/components/FolderEditor.svelte +189 -4
  24. package/package/components/ForkWorkspaceBanner.svelte +82 -11
  25. package/package/components/GlobalUserOffboardingModal.svelte +293 -0
  26. package/package/components/GlobalUserOffboardingModal.svelte.d.ts +10 -0
  27. package/package/components/InstanceSettings.svelte +22 -3
  28. package/package/components/Login.svelte +22 -10
  29. package/package/components/ModuleTest.svelte +2 -1
  30. package/package/components/NoMainFuncBadge.svelte +1 -1
  31. package/package/components/OffboardItemsBox.svelte +56 -0
  32. package/package/components/OffboardItemsBox.svelte.d.ts +12 -0
  33. package/package/components/OffboardReassignControls.svelte +47 -0
  34. package/package/components/OffboardReassignControls.svelte.d.ts +20 -0
  35. package/package/components/OffboardWorkspaceSection.svelte +110 -0
  36. package/package/components/OffboardWorkspaceSection.svelte.d.ts +24 -0
  37. package/package/components/OnBehalfOfSelector.svelte +21 -3
  38. package/package/components/OnBehalfOfSelector.svelte.d.ts +7 -0
  39. package/package/components/QueueAlerts.svelte +10 -10
  40. package/package/components/ResourcePicker.svelte +2 -2
  41. package/package/components/ScriptBuilder.svelte +52 -11
  42. package/package/components/ScriptEditor.svelte +1 -3
  43. package/package/components/ScriptEditor.svelte.d.ts +1 -1
  44. package/package/components/ShareModal.svelte +236 -98
  45. package/package/components/SuperadminSettingsInner.svelte +362 -315
  46. package/package/components/UserOffboardingModal.svelte +238 -0
  47. package/package/components/UserOffboardingModal.svelte.d.ts +10 -0
  48. package/package/components/WorkspaceDeployLayout.svelte +3 -3
  49. package/package/components/WorkspaceDeployLayout.svelte.d.ts +1 -0
  50. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptRunnableByPath.svelte +4 -2
  51. package/package/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte +12 -0
  52. package/package/components/assets/AssetsDropdownButton.svelte +1 -1
  53. package/package/components/common/confirmationModal/ConfirmationModal.svelte +1 -1
  54. package/package/components/common/table/AppRow.svelte +3 -3
  55. package/package/components/common/table/FlowRow.svelte +3 -3
  56. package/package/components/common/table/RawAppRow.svelte +4 -4
  57. package/package/components/common/table/Row.svelte +6 -2
  58. package/package/components/common/table/ScriptRow.svelte +11 -3
  59. package/package/components/copilot/chat/AIChatManager.svelte.js +2 -2
  60. package/package/components/copilot/chat/anthropic.d.ts +7 -1
  61. package/package/components/copilot/chat/anthropic.js +5 -2
  62. package/package/components/copilot/chat/app/core.js +129 -1
  63. package/package/components/copilot/chat/app/core.test.js +192 -0
  64. package/package/components/copilot/chat/chatLoop.d.ts +3 -0
  65. package/package/components/copilot/chat/chatLoop.js +13 -5
  66. package/package/components/copilot/chat/flow/FlowAIChat.svelte +55 -76
  67. package/package/components/copilot/chat/flow/core.d.ts +13 -3
  68. package/package/components/copilot/chat/flow/core.js +467 -116
  69. package/package/components/copilot/chat/flow/helperUtils.d.ts +19 -0
  70. package/package/components/copilot/chat/flow/helperUtils.js +68 -0
  71. package/package/components/copilot/chat/flow/helperUtils.test.js +116 -0
  72. package/package/components/copilot/chat/flow/inlineScriptsUtils.d.ts +5 -24
  73. package/package/components/copilot/chat/flow/inlineScriptsUtils.js +30 -55
  74. package/package/components/copilot/chat/flow/utils.test.js +59 -0
  75. package/package/components/copilot/chat/openai-responses.d.ts +7 -1
  76. package/package/components/copilot/chat/openai-responses.js +5 -2
  77. package/package/components/copilot/chat/shared.d.ts +1 -2
  78. package/package/components/copilot/chat/shared.js +94 -52
  79. package/package/components/copilot/chat/tokenUsage.d.ts +23 -0
  80. package/package/components/copilot/chat/tokenUsage.js +42 -0
  81. package/package/components/copilot/lib.d.ts +5 -1
  82. package/package/components/copilot/lib.js +21 -5
  83. package/package/components/deploymentRequest/DeploymentRequestPanel.svelte +337 -0
  84. package/package/components/deploymentRequest/DeploymentRequestPanel.svelte.d.ts +15 -0
  85. package/package/components/details/CopyableCodeBlock.svelte +18 -8
  86. package/package/components/details/CopyableCodeBlock.svelte.d.ts +1 -0
  87. package/package/components/flows/FlowAssetsHandler.svelte +19 -21
  88. package/package/components/flows/agentToolTree.d.ts +17 -0
  89. package/package/components/flows/agentToolTree.js +114 -0
  90. package/package/components/flows/agentToolTree.test.d.ts +1 -0
  91. package/package/components/flows/agentToolTree.test.js +86 -0
  92. package/package/components/flows/agentToolUtils.d.ts +0 -5
  93. package/package/components/flows/agentToolUtils.js +0 -49
  94. package/package/components/flows/content/FlowLoop.svelte +7 -4
  95. package/package/components/flows/content/FlowModuleDeleteAfterUse.svelte +15 -7
  96. package/package/components/flows/content/FlowSettings.svelte +29 -0
  97. package/package/components/flows/dfs.d.ts +6 -2
  98. package/package/components/flows/dfs.js +19 -11
  99. package/package/components/flows/flowDeleteController.d.ts +32 -0
  100. package/package/components/flows/flowDeleteController.js +54 -0
  101. package/package/components/flows/flowDeleteController.test.d.ts +1 -0
  102. package/package/components/flows/flowDeleteController.test.js +121 -0
  103. package/package/components/flows/flowDeleteUtils.d.ts +48 -0
  104. package/package/components/flows/flowDeleteUtils.js +150 -0
  105. package/package/components/flows/flowDeleteUtils.test.d.ts +1 -0
  106. package/package/components/flows/flowDeleteUtils.test.js +131 -0
  107. package/package/components/flows/flowDiff.d.ts +2 -47
  108. package/package/components/flows/flowDiff.js +16 -293
  109. package/package/components/flows/flowDiff.testUtils.d.ts +8 -0
  110. package/package/components/flows/flowDiff.testUtils.js +26 -0
  111. package/package/components/flows/flowDiffManager.svelte.js +20 -75
  112. package/package/components/flows/flowDiffManager.svelte.test.js +103 -2
  113. package/package/components/flows/flowExplorer.d.ts +4 -0
  114. package/package/components/flows/flowExplorer.js +7 -30
  115. package/package/components/flows/flowState.d.ts +1 -0
  116. package/package/components/flows/flowStateUtils.svelte.js +6 -1
  117. package/package/components/flows/flowTree.d.ts +91 -0
  118. package/package/components/flows/flowTree.js +326 -0
  119. package/package/components/flows/flowTree.test.d.ts +1 -0
  120. package/package/components/flows/flowTree.test.js +236 -0
  121. package/package/components/flows/map/FlowJobsMenu.svelte +36 -30
  122. package/package/components/flows/map/FlowModuleSchemaItem.svelte +1 -1
  123. package/package/components/flows/map/FlowModuleSchemaMap.svelte +70 -227
  124. package/package/components/flows/map/FlowModuleSchemaMap.svelte.d.ts +0 -2
  125. package/package/components/flows/pickers/PickHubScriptQuick.svelte +2 -2
  126. package/package/components/flows/previousResults.js +13 -41
  127. package/package/components/flows/previousResults.test.d.ts +1 -0
  128. package/package/components/flows/previousResults.test.js +65 -0
  129. package/package/components/flows/propPicker/OutputPicker.svelte +2 -1
  130. package/package/components/flows/propPicker/OutputPickerInner.svelte +41 -4
  131. package/package/components/flows/propPicker/StepHistory.svelte +9 -1
  132. package/package/components/git_sync/GitSyncContext.svelte.js +11 -5
  133. package/package/components/git_sync/GitSyncRepositoryCard.svelte +2 -29
  134. package/package/components/git_sync/PullWorkspaceModal.svelte +6 -7
  135. package/package/components/graph/FlowGraphV2.svelte +2 -2
  136. package/package/components/graph/FlowGraphV2.svelte.d.ts +1 -0
  137. package/package/components/graph/groupedModulesProxy.svelte.d.ts +10 -0
  138. package/package/components/graph/groupedModulesProxy.svelte.js +17 -1
  139. package/package/components/graph/renderers/triggers/TriggersBadge.svelte +5 -2
  140. package/package/components/home/HomeConnectDrawer.svelte +125 -0
  141. package/package/components/home/HomeConnectDrawer.svelte.d.ts +5 -0
  142. package/package/components/icons/GithubIcon.svelte +4 -4
  143. package/package/components/icons/GithubIcon.svelte.d.ts +5 -2
  144. package/package/components/instanceSettings/ExternalJwtTokens.svelte +85 -0
  145. package/package/components/instanceSettings/ExternalJwtTokens.svelte.d.ts +12 -0
  146. package/package/components/instanceSettings/GhesAppSettings.svelte +17 -0
  147. package/package/components/instanceSettings/IndexerMemorySettings.svelte +56 -29
  148. package/package/components/instanceSettings/SecretBackendConfig.svelte +9 -2
  149. package/package/components/instanceSettings.d.ts +1 -0
  150. package/package/components/instanceSettings.js +42 -8
  151. package/package/components/offboarding-utils.d.ts +11 -0
  152. package/package/components/offboarding-utils.js +100 -0
  153. package/package/components/raw_apps/RawAppDataTableDrawer.svelte +1 -1
  154. package/package/components/raw_apps/RawAppEditor.svelte +27 -0
  155. package/package/components/raw_apps/RawAppEditorHeader.svelte +6 -1
  156. package/package/components/raw_apps/RawAppEditorHeader.svelte.d.ts +1 -0
  157. package/package/components/raw_apps/RawAppYamlEditor.svelte +81 -0
  158. package/package/components/raw_apps/RawAppYamlEditor.svelte.d.ts +20 -0
  159. package/package/components/raw_apps/datatableUtils.svelte.js +1 -1
  160. package/package/components/runs/runsFilter.d.ts +1 -1
  161. package/package/components/script_builder.d.ts +1 -1
  162. package/package/components/select/Select.svelte +2 -1
  163. package/package/components/select/Select.svelte.d.ts +1 -0
  164. package/package/components/settings/CreateToken.svelte +113 -64
  165. package/package/components/settings/CreateToken.svelte.d.ts +3 -0
  166. package/package/components/settings/WorkspaceUserSettings.svelte +34 -28
  167. package/package/components/sidebar/SidebarContent.svelte +58 -2
  168. package/package/components/sidebar/WorkspaceMenu.svelte +8 -4
  169. package/package/components/triggers/AddTriggersButton.svelte +11 -0
  170. package/package/components/triggers/PermissionedAsLine.svelte +37 -3
  171. package/package/components/triggers/PermissionedAsLine.svelte.d.ts +6 -0
  172. package/package/components/triggers/TriggersEditor.svelte +5 -1
  173. package/package/components/triggers/TriggersWrapper.svelte +10 -0
  174. package/package/components/triggers/email/EmailTriggerEditorInner.svelte +13 -11
  175. package/package/components/triggers/gcp/GcpTriggerEditorInner.svelte +13 -11
  176. package/package/components/triggers/http/RouteEditorConfigSection.svelte +15 -7
  177. package/package/components/triggers/http/RouteEditorInner.svelte +14 -14
  178. package/package/components/triggers/http/RoutesGenerator.svelte +6 -1
  179. package/package/components/triggers/http/RoutesPanel.svelte +1 -1
  180. package/package/components/triggers/http/utils.d.ts +1 -1
  181. package/package/components/triggers/http/utils.js +2 -2
  182. package/package/components/triggers/kafka/KafkaTriggerEditorInner.svelte +13 -11
  183. package/package/components/triggers/mqtt/MqttTriggerEditorInner.svelte +13 -11
  184. package/package/components/triggers/native/NativeTriggerEditor.svelte +3 -0
  185. package/package/components/triggers/native/services/github/GitHubTriggerForm.svelte +118 -0
  186. package/package/components/triggers/native/services/github/GitHubTriggerForm.svelte.d.ts +17 -0
  187. package/package/components/triggers/native/utils.js +14 -0
  188. package/package/components/triggers/nats/NatsTriggerEditor.svelte.d.ts +4 -3
  189. package/package/components/triggers/nats/NatsTriggerEditorInner.svelte +13 -11
  190. package/package/components/triggers/postgres/PostgresTriggerEditor.svelte.d.ts +4 -3
  191. package/package/components/triggers/postgres/PostgresTriggerEditorInner.svelte +13 -11
  192. package/package/components/triggers/schedules/ScheduleEditorInner.svelte +13 -11
  193. package/package/components/triggers/sqs/SqsTriggerEditor.svelte.d.ts +4 -3
  194. package/package/components/triggers/sqs/SqsTriggerEditorInner.svelte +13 -11
  195. package/package/components/triggers/triggers.svelte.js +1 -0
  196. package/package/components/triggers/utils.js +27 -6
  197. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +13 -11
  198. package/package/components/triggers.d.ts +1 -1
  199. package/package/components/useFolderDefaultPermissionedAs.svelte.d.ts +13 -0
  200. package/package/components/useFolderDefaultPermissionedAs.svelte.js +63 -0
  201. package/package/components/workspaceSettings/CreateWorkspace.svelte +16 -677
  202. package/package/components/workspaceSettings/CreateWorkspaceInner.svelte +604 -0
  203. package/package/components/workspaceSettings/CreateWorkspaceInner.svelte.d.ts +7 -0
  204. package/package/components/workspaceSettings/CustomInstanceDbSelect.svelte +27 -25
  205. package/package/components/workspaceSettings/CustomInstanceDbWizardModal.svelte +46 -8
  206. package/package/components/workspaceSettings/DataTableSettings.svelte +27 -22
  207. package/package/components/workspaceSettings/DucklakeSettings.svelte +1 -1
  208. package/package/components/workspaceSettings/ForkDatatableSection.svelte +228 -0
  209. package/package/components/workspaceSettings/ForkDatatableSection.svelte.d.ts +28 -0
  210. package/package/components/workspaceSettings/GitSyncFilterSettings.svelte +8 -2
  211. package/package/components/workspaceSettings/RulesetEditor.svelte +27 -2
  212. package/package/components/workspaceSettings/VolumeStorageSettings.svelte +1 -1
  213. package/package/components/workspaceSettings/WorkspaceIntegrations.svelte +17 -1
  214. package/package/consts.d.ts +3 -0
  215. package/package/consts.js +10 -0
  216. package/package/gen/core/OpenAPI.js +1 -1
  217. package/package/gen/schemas.gen.d.ts +485 -19
  218. package/package/gen/schemas.gen.js +489 -20
  219. package/package/gen/services.gen.d.ts +229 -2
  220. package/package/gen/services.gen.js +463 -1
  221. package/package/gen/types.gen.d.ts +866 -29
  222. package/package/githubApp.js +5 -1
  223. package/package/hubPaths.json +1 -4
  224. package/package/infer.js +13 -1
  225. package/package/infer.svelte.js +10 -1
  226. package/package/monaco_workers/sqlTypePlugin.worker.d.ts +10 -0
  227. package/package/monaco_workers/sqlTypePlugin.worker.js +39 -0
  228. package/package/script_helpers.d.ts +8 -2
  229. package/package/script_helpers.js +14 -0
  230. package/package/stores.d.ts +4 -0
  231. package/package/stores.js +1 -0
  232. package/package/system_prompts/prompts.d.ts +4 -3
  233. package/package/system_prompts/prompts.js +270 -20
  234. package/package/templates/ci_test_bun.ts.template +19 -0
  235. package/package/templates/ci_test_python.py.template +18 -0
  236. package/package/utils_workspace_deploy.d.ts +8 -8
  237. package/package/utils_workspace_deploy.js +86 -420
  238. package/package.json +3 -3
  239. package/package/components/copilot/chat/__tests__/app/appChat.eval.test.js +0 -153
  240. package/package/components/copilot/chat/__tests__/app/appEvalComparison.d.ts +0 -21
  241. package/package/components/copilot/chat/__tests__/app/appEvalComparison.js +0 -136
  242. package/package/components/copilot/chat/__tests__/app/appEvalHelpers.d.ts +0 -15
  243. package/package/components/copilot/chat/__tests__/app/appEvalHelpers.js +0 -107
  244. package/package/components/copilot/chat/__tests__/app/appEvalRunner.d.ts +0 -50
  245. package/package/components/copilot/chat/__tests__/app/appEvalRunner.js +0 -93
  246. package/package/components/copilot/chat/__tests__/app/appFixtureLoader.d.ts +0 -29
  247. package/package/components/copilot/chat/__tests__/app/appFixtureLoader.js +0 -134
  248. package/package/components/copilot/chat/__tests__/app/appResultsWriter.d.ts +0 -30
  249. package/package/components/copilot/chat/__tests__/app/appResultsWriter.js +0 -197
  250. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/createFolder/main.d.ts +0 -10
  251. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/createFolder/main.js +0 -9
  252. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/createFolder/meta.json +0 -4
  253. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/deleteItem/main.d.ts +0 -6
  254. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/deleteItem/main.js +0 -5
  255. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/deleteItem/meta.json +0 -4
  256. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/listFiles/main.d.ts +0 -12
  257. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/listFiles/main.js +0 -14
  258. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/listFiles/meta.json +0 -4
  259. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/listFolders/main.d.ts +0 -8
  260. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/listFolders/main.js +0 -25
  261. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/listFolders/meta.json +0 -4
  262. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/moveItem/main.d.ts +0 -7
  263. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/moveItem/main.js +0 -5
  264. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/moveItem/meta.json +0 -4
  265. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/renameItem/main.d.ts +0 -8
  266. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/renameItem/main.js +0 -5
  267. package/package/components/copilot/chat/__tests__/app/initial/file_manager/backend/renameItem/meta.json +0 -4
  268. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/Breadcrumb.d.ts +0 -10
  269. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/Breadcrumb.tsx +0 -26
  270. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/FileItem.d.ts +0 -10
  271. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/FileItem.tsx +0 -79
  272. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/FileList.d.ts +0 -10
  273. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/FileList.tsx +0 -46
  274. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/FolderTree.d.ts +0 -10
  275. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/FolderTree.tsx +0 -56
  276. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/Toolbar.d.ts +0 -6
  277. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/components/Toolbar.tsx +0 -59
  278. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/index.d.ts +0 -16
  279. package/package/components/copilot/chat/__tests__/app/initial/file_manager/frontend/index.tsx +0 -119
  280. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/addToCart/main.d.ts +0 -15
  281. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/addToCart/main.js +0 -14
  282. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/addToCart/meta.json +0 -4
  283. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/calculateTotal/main.d.ts +0 -14
  284. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/calculateTotal/main.js +0 -5
  285. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/calculateTotal/meta.json +0 -4
  286. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/getProducts/main.d.ts +0 -6
  287. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/getProducts/main.js +0 -41
  288. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/getProducts/meta.json +0 -4
  289. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/removeFromCart/main.d.ts +0 -15
  290. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/removeFromCart/main.js +0 -3
  291. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/backend/removeFromCart/meta.json +0 -4
  292. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/components/Cart.d.ts +0 -9
  293. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/components/Cart.tsx +0 -51
  294. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/components/ProductCard.d.ts +0 -8
  295. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/components/ProductCard.tsx +0 -27
  296. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/components/ProductList.d.ts +0 -8
  297. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/components/ProductList.tsx +0 -18
  298. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/index.d.ts +0 -12
  299. package/package/components/copilot/chat/__tests__/app/initial/shopping_cart/frontend/index.tsx +0 -81
  300. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/backend/decrementCounter/main.d.ts +0 -3
  301. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/backend/decrementCounter/main.js +0 -3
  302. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/backend/decrementCounter/meta.json +0 -4
  303. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/backend/incrementCounter/main.d.ts +0 -3
  304. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/backend/incrementCounter/main.js +0 -3
  305. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/backend/incrementCounter/meta.json +0 -4
  306. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/frontend/index.d.ts +0 -2
  307. package/package/components/copilot/chat/__tests__/app/initial/test1_counter_app/frontend/index.tsx +0 -38
  308. package/package/components/copilot/chat/__tests__/app/variants/baseline.d.ts +0 -6
  309. package/package/components/copilot/chat/__tests__/app/variants/baseline.js +0 -10
  310. package/package/components/copilot/chat/__tests__/app/variants/index.d.ts +0 -3
  311. package/package/components/copilot/chat/__tests__/app/variants/index.js +0 -3
  312. package/package/components/copilot/chat/__tests__/app/variants/streamlined.d.ts +0 -6
  313. package/package/components/copilot/chat/__tests__/app/variants/streamlined.js +0 -137
  314. package/package/components/copilot/chat/__tests__/flow/expected/test1.json +0 -134
  315. package/package/components/copilot/chat/__tests__/flow/expected/test2.json +0 -183
  316. package/package/components/copilot/chat/__tests__/flow/expected/test3.json +0 -204
  317. package/package/components/copilot/chat/__tests__/flow/expected/test4.json +0 -175
  318. package/package/components/copilot/chat/__tests__/flow/expected/test5_modify_simple.json +0 -68
  319. package/package/components/copilot/chat/__tests__/flow/expected/test6_modify_medium.json +0 -142
  320. package/package/components/copilot/chat/__tests__/flow/expected/test7_modify_complex.json +0 -136
  321. package/package/components/copilot/chat/__tests__/flow/flowChat.eval.test.js +0 -294
  322. package/package/components/copilot/chat/__tests__/flow/flowEvalComparison.d.ts +0 -17
  323. package/package/components/copilot/chat/__tests__/flow/flowEvalComparison.js +0 -49
  324. package/package/components/copilot/chat/__tests__/flow/flowEvalHelpers.d.ts +0 -12
  325. package/package/components/copilot/chat/__tests__/flow/flowEvalHelpers.js +0 -79
  326. package/package/components/copilot/chat/__tests__/flow/flowEvalRunner.d.ts +0 -50
  327. package/package/components/copilot/chat/__tests__/flow/flowEvalRunner.js +0 -102
  328. package/package/components/copilot/chat/__tests__/flow/initial/test5_initial.json +0 -53
  329. package/package/components/copilot/chat/__tests__/flow/initial/test6_initial.json +0 -68
  330. package/package/components/copilot/chat/__tests__/flow/initial/test7_initial.json +0 -120
  331. package/package/components/copilot/chat/__tests__/flow/variants/baseline.d.ts +0 -6
  332. package/package/components/copilot/chat/__tests__/flow/variants/baseline.js +0 -10
  333. package/package/components/copilot/chat/__tests__/flow/variants/index.d.ts +0 -3
  334. package/package/components/copilot/chat/__tests__/flow/variants/index.js +0 -3
  335. package/package/components/copilot/chat/__tests__/flow/variants/minimal-single-tool.d.ts +0 -15
  336. package/package/components/copilot/chat/__tests__/flow/variants/minimal-single-tool.js +0 -388
  337. package/package/components/copilot/chat/__tests__/shared/baseEvalRunner.d.ts +0 -45
  338. package/package/components/copilot/chat/__tests__/shared/baseEvalRunner.js +0 -121
  339. package/package/components/copilot/chat/__tests__/shared/baseLLMEvaluator.d.ts +0 -28
  340. package/package/components/copilot/chat/__tests__/shared/baseLLMEvaluator.js +0 -96
  341. package/package/components/copilot/chat/__tests__/shared/baseResultsWriter.d.ts +0 -32
  342. package/package/components/copilot/chat/__tests__/shared/baseResultsWriter.js +0 -130
  343. package/package/components/copilot/chat/__tests__/shared/baseVariants.d.ts +0 -45
  344. package/package/components/copilot/chat/__tests__/shared/baseVariants.js +0 -57
  345. package/package/components/copilot/chat/__tests__/shared/index.d.ts +0 -10
  346. package/package/components/copilot/chat/__tests__/shared/index.js +0 -5
  347. package/package/components/copilot/chat/__tests__/shared/types.d.ts +0 -105
  348. package/package/components/copilot/chat/__tests__/shared/types.js +0 -9
  349. package/package/components/copilot/chat/flow/utils.d.ts +0 -14
  350. package/package/components/copilot/chat/flow/utils.js +0 -108
  351. package/package/components/flows/agentToolUtils.test.js +0 -55
  352. /package/package/components/copilot/chat/{__tests__/app/appChat.eval.test.d.ts → app/core.test.d.ts} +0 -0
  353. /package/package/components/copilot/chat/{__tests__/flow/flowChat.eval.test.d.ts → flow/helperUtils.test.d.ts} +0 -0
  354. /package/package/components/{flows/agentToolUtils.test.d.ts → copilot/chat/flow/utils.test.d.ts} +0 -0
@@ -10,6 +10,44 @@ const memo = (factory) => {
10
10
  let cached;
11
11
  return () => (cached ??= factory());
12
12
  };
13
+ function countExactMatches(content, search) {
14
+ if (search.length === 0) {
15
+ return 0;
16
+ }
17
+ let count = 0;
18
+ let index = 0;
19
+ while ((index = content.indexOf(search, index)) !== -1) {
20
+ count += 1;
21
+ index += search.length;
22
+ }
23
+ return count;
24
+ }
25
+ function replaceFirstExactMatch(content, search, replace) {
26
+ const index = content.indexOf(search);
27
+ if (index === -1) {
28
+ return content;
29
+ }
30
+ return content.slice(0, index) + replace + content.slice(index + search.length);
31
+ }
32
+ function resolveAppPatchTarget(rawPath) {
33
+ const trimmedPath = rawPath.trim();
34
+ const backendMatch = trimmedPath.match(/^\/?backend\/([^/]+)\/main\.(ts|py)$/);
35
+ if (backendMatch) {
36
+ return {
37
+ type: 'backend',
38
+ path: trimmedPath.startsWith('/') ? trimmedPath.slice(1) : trimmedPath,
39
+ key: backendMatch[1],
40
+ extension: backendMatch[2]
41
+ };
42
+ }
43
+ return {
44
+ type: 'frontend',
45
+ path: trimmedPath.startsWith('/') ? trimmedPath : `/${trimmedPath}`
46
+ };
47
+ }
48
+ function getBackendInlineScriptExtension(runnable) {
49
+ return runnable.inlineScript?.language === 'python3' ? 'py' : 'ts';
50
+ }
13
51
  // ============= Frontend File Tools =============
14
52
  const getGetFrontendFileSchema = memo(() => z.object({
15
53
  path: z
@@ -24,6 +62,19 @@ const getSetFrontendFileSchema = memo(() => z.object({
24
62
  content: z.string().describe('The content of the file')
25
63
  }));
26
64
  const getSetFrontendFileToolDef = memo(() => createToolDef(getSetFrontendFileSchema(), 'set_frontend_file', 'Create or update a frontend file in the raw app. Returns lint diagnostics (errors and warnings).'));
65
+ const getPatchFileSchema = memo(() => z.object({
66
+ path: z
67
+ .string()
68
+ .describe('Path of the file to patch. Use frontend paths like /index.tsx or inline backend paths like backend/listRecipes/main.ts.'),
69
+ old_string: z.string().min(1).describe('Exact text to find in the current file content'),
70
+ new_string: z.string().describe('Replacement text'),
71
+ replace_all: z
72
+ .boolean()
73
+ .optional()
74
+ .default(false)
75
+ .describe('When true, replace every exact match. When false, old_string must match exactly once.')
76
+ }));
77
+ const getPatchFileToolDef = memo(() => createToolDef(getPatchFileSchema(), 'patch_file', 'Make a quick exact text edit in an existing frontend file or inline backend file. Prefer this for small localized changes instead of rewriting the whole file.'));
27
78
  const getDeleteFrontendFileSchema = memo(() => z.object({
28
79
  path: z.string().describe('The path of the frontend file to delete')
29
80
  }));
@@ -245,6 +296,73 @@ export const getAppTools = memo(() => [
245
296
  showDetails: true,
246
297
  showFade: true
247
298
  },
299
+ {
300
+ def: getPatchFileToolDef(),
301
+ streamArguments: true,
302
+ showDetails: true,
303
+ showFade: true,
304
+ fn: async ({ args, helpers, toolId, toolCallbacks }) => {
305
+ const parsedArgs = getPatchFileSchema().parse(args);
306
+ const { old_string: oldString, new_string: newString, replace_all: replaceAll } = parsedArgs;
307
+ const target = resolveAppPatchTarget(parsedArgs.path);
308
+ let currentContent = '';
309
+ let backendRunnable;
310
+ if (target.type === 'frontend') {
311
+ if (target.path === '/wmill.d.ts') {
312
+ throw new Error("'/wmill.d.ts' is generated automatically. Edit backend runnables instead.");
313
+ }
314
+ const frontendContent = helpers.getFrontendFile(target.path);
315
+ if (frontendContent === undefined) {
316
+ throw new Error(`Frontend file '${target.path}' not found.`);
317
+ }
318
+ currentContent = frontendContent;
319
+ }
320
+ else {
321
+ backendRunnable = helpers.getBackendRunnable(target.key);
322
+ if (!backendRunnable) {
323
+ throw new Error(`Backend runnable '${target.key}' not found.`);
324
+ }
325
+ if (backendRunnable.type !== 'inline' || !backendRunnable.inlineScript) {
326
+ throw new Error(`'${target.path}' points to backend runnable '${target.key}', but only inline runnables can be patched as files.`);
327
+ }
328
+ const expectedExtension = getBackendInlineScriptExtension(backendRunnable);
329
+ if (target.extension !== expectedExtension) {
330
+ throw new Error(`'${target.path}' does not match runnable '${target.key}' language. Use backend/${target.key}/main.${expectedExtension}.`);
331
+ }
332
+ currentContent = backendRunnable.inlineScript.content ?? '';
333
+ }
334
+ const matchCount = countExactMatches(currentContent, oldString);
335
+ if (matchCount === 0) {
336
+ throw new Error('old_string was not found in the current file content.');
337
+ }
338
+ if (!replaceAll && matchCount !== 1) {
339
+ throw new Error(`old_string matched ${matchCount} locations. Make it more specific or set replace_all to true.`);
340
+ }
341
+ const updatedContent = replaceAll
342
+ ? currentContent.split(oldString).join(newString)
343
+ : replaceFirstExactMatch(currentContent, oldString, newString);
344
+ toolCallbacks.setToolStatus(toolId, {
345
+ content: `Patching '${target.path}'...`
346
+ });
347
+ const lintResult = target.type === 'frontend'
348
+ ? helpers.setFrontendFile(target.path, updatedContent)
349
+ : await helpers.setBackendRunnable(target.key, {
350
+ ...backendRunnable,
351
+ inlineScript: {
352
+ ...backendRunnable.inlineScript,
353
+ content: updatedContent
354
+ }
355
+ });
356
+ toolCallbacks.setToolStatus(toolId, {
357
+ content: `Patched '${target.path}'`,
358
+ result: 'Success'
359
+ });
360
+ return formatLintResultResponse(`Patched '${target.path}' successfully.`, lintResult);
361
+ },
362
+ preAction: ({ toolCallbacks, toolId }) => {
363
+ toolCallbacks.setToolStatus(toolId, { content: 'Patching file...' });
364
+ }
365
+ },
248
366
  {
249
367
  def: getDeleteFrontendFileToolDef(),
250
368
  fn: async ({ args, helpers, toolId, toolCallbacks }) => {
@@ -473,6 +591,7 @@ For inline scripts, the code must have a \`main\` function as its entrypoint.
473
591
  ### File Management
474
592
  - \`get_files()\`: Get an overview of all files (content may be truncated for large files)
475
593
  - \`get_frontend_file(path)\`: Get full content of a specific frontend file
594
+ - \`patch_file(path, old_string, new_string, replace_all?)\`: Make a quick exact text edit to an existing file. Use frontend paths like \`/index.tsx\` and inline backend paths like \`backend/listRecipes/main.ts\`.
476
595
  - \`set_frontend_file(path, content)\`: Create or update a frontend file. Returns lint diagnostics.
477
596
  - \`delete_frontend_file(path)\`: Delete a frontend file
478
597
  - \`get_backend_runnable(key)\`: Get full configuration of a specific backend runnable
@@ -482,6 +601,15 @@ For inline scripts, the code must have a \`main\` function as its entrypoint.
482
601
  ### Linting
483
602
  - \`lint()\`: Lint all files. Returns errors/warnings grouped by frontend/backend. Use this to check for issues after making changes.
484
603
 
604
+ ## Quick Edits with patch_file
605
+
606
+ Use \`patch_file\` for small, localized edits when you can copy an exact snippet from the current file contents.
607
+
608
+ - \`old_string\` must be copied exactly from the current file contents
609
+ - Leave \`replace_all\` as false unless you intentionally want to update every exact match
610
+ - Never patch \`/wmill.d.ts\`; it is generated automatically from backend runnables
611
+ - Use \`set_frontend_file\` or \`set_backend_runnable\` instead for large rewrites, new files, or new runnables
612
+
485
613
  ### Discovery
486
614
  - \`search_workspace(query, type)\`: Search workspace scripts and flows
487
615
  - \`get_runnable_details(path, type)\`: Get details (summary, description, schema, content) of a specific script or flow
@@ -620,7 +748,7 @@ When you are using the windmill-client, do not forget that as id for variables o
620
748
 
621
749
  1. Start with \`get_files()\` to get an overview of all frontend files and backend runnables (content may be truncated for large files)
622
750
  2. Use \`get_frontend_file(path)\` or \`get_backend_runnable(key)\` to get full content of specific files when needed
623
- 3. Make changes using \`set_frontend_file\` and \`set_backend_runnable\`. These return lint diagnostics.
751
+ 3. For small localized edits, prefer \`patch_file\`. Use \`set_frontend_file\` and \`set_backend_runnable\` for larger rewrites, new files, or new runnables. These return lint diagnostics.
624
752
  4. Use \`lint()\` at the end to check for and fix any remaining errors
625
753
 
626
754
  When creating a new app, use \`search_workspace\` or \`search_hub_scripts\` to find existing scripts/flows to reuse.
@@ -0,0 +1,192 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { getAppTools } from './core';
3
+ vi.mock('../shared', () => ({
4
+ createToolDef: (_schema, name, description) => ({
5
+ type: 'function',
6
+ function: {
7
+ name,
8
+ description,
9
+ parameters: {}
10
+ }
11
+ }),
12
+ createSearchWorkspaceTool: () => ({
13
+ def: {
14
+ type: 'function',
15
+ function: {
16
+ name: 'search_workspace',
17
+ description: 'search workspace',
18
+ parameters: {}
19
+ }
20
+ },
21
+ fn: async () => ''
22
+ }),
23
+ createGetRunnableDetailsTool: () => ({
24
+ def: {
25
+ type: 'function',
26
+ function: {
27
+ name: 'get_runnable_details',
28
+ description: 'get runnable details',
29
+ parameters: {}
30
+ }
31
+ },
32
+ fn: async () => ''
33
+ }),
34
+ createSearchHubScriptsTool: () => ({
35
+ def: {
36
+ type: 'function',
37
+ function: {
38
+ name: 'search_hub_scripts',
39
+ description: 'search hub scripts',
40
+ parameters: {}
41
+ }
42
+ },
43
+ fn: async () => ''
44
+ })
45
+ }));
46
+ vi.mock('../AIChatManager.svelte', () => ({
47
+ aiChatManager: {
48
+ datatableCreationPolicy: {
49
+ enabled: false,
50
+ datatable: undefined,
51
+ schema: undefined
52
+ }
53
+ }
54
+ }));
55
+ vi.mock('$system_prompts', () => ({
56
+ getDatatableSdkReference: () => 'Datatable SDK reference'
57
+ }));
58
+ const EMPTY_LINT_RESULT = {
59
+ errorCount: 0,
60
+ warningCount: 0,
61
+ errors: {
62
+ frontend: {},
63
+ backend: {}
64
+ },
65
+ warnings: {
66
+ frontend: {},
67
+ backend: {}
68
+ }
69
+ };
70
+ function createHelpers(overrides = {}) {
71
+ return {
72
+ listFrontendFiles: () => [],
73
+ getFrontendFile: () => undefined,
74
+ getFrontendFiles: () => ({}),
75
+ setFrontendFile: () => EMPTY_LINT_RESULT,
76
+ deleteFrontendFile: () => undefined,
77
+ listBackendRunnables: () => [],
78
+ getBackendRunnable: () => undefined,
79
+ getBackendRunnables: () => ({}),
80
+ setBackendRunnable: async () => EMPTY_LINT_RESULT,
81
+ deleteBackendRunnable: () => undefined,
82
+ getFiles: () => ({ frontend: {}, backend: {} }),
83
+ getSelectedContext: () => ({ type: 'none' }),
84
+ snapshot: () => 1,
85
+ revertToSnapshot: () => undefined,
86
+ lint: () => EMPTY_LINT_RESULT,
87
+ getDatatables: async () => [],
88
+ getAvailableDatatableNames: () => [],
89
+ execDatatableSql: async () => ({ success: true }),
90
+ addTableToWhitelist: () => undefined,
91
+ ...overrides
92
+ };
93
+ }
94
+ function createToolCallbacks() {
95
+ return {
96
+ setToolStatus: vi.fn(),
97
+ removeToolStatus: vi.fn()
98
+ };
99
+ }
100
+ function getPatchFileTool() {
101
+ const tool = getAppTools().find((entry) => entry.def.function.name === 'patch_file');
102
+ if (!tool) {
103
+ throw new Error('patch_file tool not found');
104
+ }
105
+ return tool;
106
+ }
107
+ describe('app patch_file tool', () => {
108
+ it('patches frontend files with an exact replacement', async () => {
109
+ const setFrontendFile = vi.fn(() => EMPTY_LINT_RESULT);
110
+ const tool = getPatchFileTool();
111
+ const result = await tool.fn({
112
+ args: {
113
+ path: '/index.tsx',
114
+ old_string: 'Hello recipe book',
115
+ new_string: 'Hello cookbook'
116
+ },
117
+ workspace: 'test-workspace',
118
+ helpers: createHelpers({
119
+ getFrontendFile: () => 'export const title = "Hello recipe book"\n',
120
+ setFrontendFile
121
+ }),
122
+ toolCallbacks: createToolCallbacks(),
123
+ toolId: 'tool-1'
124
+ });
125
+ expect(setFrontendFile).toHaveBeenCalledWith('/index.tsx', 'export const title = "Hello cookbook"\n');
126
+ expect(result).toContain("Patched '/index.tsx' successfully.");
127
+ });
128
+ it('rejects ambiguous matches unless replace_all is set', async () => {
129
+ const tool = getPatchFileTool();
130
+ await expect(tool.fn({
131
+ args: {
132
+ path: '/index.tsx',
133
+ old_string: 'recipe',
134
+ new_string: 'meal'
135
+ },
136
+ workspace: 'test-workspace',
137
+ helpers: createHelpers({
138
+ getFrontendFile: () => 'recipe\nrecipe\n'
139
+ }),
140
+ toolCallbacks: createToolCallbacks(),
141
+ toolId: 'tool-2'
142
+ })).rejects.toThrow('old_string matched 2 locations');
143
+ });
144
+ it('patches inline backend runnables through backend/<key>/main.ts paths', async () => {
145
+ const runnable = {
146
+ name: 'Delete recipe',
147
+ type: 'inline',
148
+ inlineScript: {
149
+ language: 'bun',
150
+ content: 'export async function main() {\n\treturn "recipe"\n}\n'
151
+ }
152
+ };
153
+ const setBackendRunnable = vi.fn(async () => EMPTY_LINT_RESULT);
154
+ const tool = getPatchFileTool();
155
+ const result = await tool.fn({
156
+ args: {
157
+ path: 'backend/deleteRecipe/main.ts',
158
+ old_string: '"recipe"',
159
+ new_string: '"meal"'
160
+ },
161
+ workspace: 'test-workspace',
162
+ helpers: createHelpers({
163
+ getBackendRunnable: () => runnable,
164
+ setBackendRunnable
165
+ }),
166
+ toolCallbacks: createToolCallbacks(),
167
+ toolId: 'tool-3'
168
+ });
169
+ expect(setBackendRunnable).toHaveBeenCalledWith('deleteRecipe', expect.objectContaining({
170
+ inlineScript: expect.objectContaining({
171
+ content: 'export async function main() {\n\treturn "meal"\n}\n'
172
+ })
173
+ }));
174
+ expect(result).toContain("Patched 'backend/deleteRecipe/main.ts' successfully.");
175
+ });
176
+ it('rejects edits to generated wmill types', async () => {
177
+ const tool = getPatchFileTool();
178
+ await expect(tool.fn({
179
+ args: {
180
+ path: '/wmill.d.ts',
181
+ old_string: 'backend',
182
+ new_string: 'backendAsync'
183
+ },
184
+ workspace: 'test-workspace',
185
+ helpers: createHelpers({
186
+ getFrontendFile: () => 'generated'
187
+ }),
188
+ toolCallbacks: createToolCallbacks(),
189
+ toolId: 'tool-4'
190
+ })).rejects.toThrow('generated automatically');
191
+ });
192
+ });
@@ -3,6 +3,7 @@ import Anthropic from '@anthropic-ai/sdk';
3
3
  import type { ChatCompletionMessageParam, ChatCompletionSystemMessageParam, ChatCompletionUserMessageParam } from 'openai/resources/chat/completions.mjs';
4
4
  import type { AIProviderModel } from '../../../gen';
5
5
  import type { Tool, ToolCallbacks } from './shared';
6
+ import { type ChatTokenUsage } from './tokenUsage';
6
7
  export interface ChatClients {
7
8
  openai: OpenAI;
8
9
  anthropic: Anthropic;
@@ -36,5 +37,7 @@ export interface ChatLoopConfig {
36
37
  }
37
38
  export interface ChatLoopResult {
38
39
  addedMessages: ChatCompletionMessageParam[];
40
+ tokenUsage: ChatTokenUsage;
41
+ hitMaxIterations: boolean;
39
42
  }
40
43
  export declare function runChatLoop(config: ChatLoopConfig): Promise<ChatLoopResult>;
@@ -3,13 +3,17 @@ import Anthropic from '@anthropic-ai/sdk';
3
3
  import { getCompletion, parseOpenAICompletion } from '../lib';
4
4
  import { getAnthropicCompletion, parseAnthropicCompletion } from './anthropic';
5
5
  import { getOpenAIResponsesCompletion, parseOpenAIResponsesCompletion } from './openai-responses';
6
+ import { addChatTokenUsage, emptyChatTokenUsage } from './tokenUsage';
6
7
  export async function runChatLoop(config) {
7
8
  const { messages, abortController, callbacks, clients, workspace, maxIterations, onSkipResponsesApi, getPendingUserMessage, onBeforeIteration } = config;
8
9
  let skipResponsesApi = config.skipResponsesApi ?? false;
9
10
  const addedMessages = [];
11
+ let tokenUsage = emptyChatTokenUsage();
10
12
  let iterations = 0;
13
+ let hitMaxIterations = false;
11
14
  while (true) {
12
15
  if (maxIterations !== undefined && iterations >= maxIterations) {
16
+ hitMaxIterations = true;
13
17
  break;
14
18
  }
15
19
  iterations++;
@@ -42,7 +46,8 @@ export async function runChatLoop(config) {
42
46
  openaiClient: clients.openai
43
47
  });
44
48
  const continueCompletion = await parseOpenAIResponsesCompletion(completion, callbacks, messages, addedMessages, tools, helpers, parseOptions);
45
- if (!continueCompletion) {
49
+ tokenUsage = addChatTokenUsage(tokenUsage, continueCompletion.tokenUsage);
50
+ if (!continueCompletion.shouldContinue) {
46
51
  break;
47
52
  }
48
53
  }
@@ -63,7 +68,8 @@ export async function runChatLoop(config) {
63
68
  openaiClient: clients.openai
64
69
  });
65
70
  const continueCompletion = await parseOpenAICompletion(completion, callbacks, messages, addedMessages, tools, helpers, undefined, parseOptions);
66
- if (!continueCompletion) {
71
+ tokenUsage = addChatTokenUsage(tokenUsage, continueCompletion.tokenUsage);
72
+ if (!continueCompletion.shouldContinue) {
67
73
  break;
68
74
  }
69
75
  }
@@ -75,7 +81,8 @@ export async function runChatLoop(config) {
75
81
  });
76
82
  if (completion) {
77
83
  const continueCompletion = await parseAnthropicCompletion(completion, callbacks, messages, addedMessages, tools, helpers, abortController, parseOptions);
78
- if (!continueCompletion) {
84
+ tokenUsage = addChatTokenUsage(tokenUsage, continueCompletion.tokenUsage);
85
+ if (!continueCompletion.shouldContinue) {
79
86
  break;
80
87
  }
81
88
  }
@@ -87,11 +94,12 @@ export async function runChatLoop(config) {
87
94
  });
88
95
  if (completion) {
89
96
  const continueCompletion = await parseOpenAICompletion(completion, callbacks, messages, addedMessages, tools, helpers, undefined, parseOptions);
90
- if (!continueCompletion) {
97
+ tokenUsage = addChatTokenUsage(tokenUsage, continueCompletion.tokenUsage);
98
+ if (!continueCompletion.shouldContinue) {
91
99
  break;
92
100
  }
93
101
  }
94
102
  }
95
103
  }
96
- return { addedMessages };
104
+ return { addedMessages, tokenUsage, hitMaxIterations };
97
105
  }
@@ -1,29 +1,18 @@
1
1
  <script lang="ts">import FlowModuleSchemaMap from '../../../flows/map/FlowModuleSchemaMap.svelte';
2
2
  import { getContext, untrack } from 'svelte';
3
- import { dfs } from '../../../flows/previousResults';
4
- import { restoreInlineScriptReferences } from './inlineScriptsUtils';
3
+ import { createInlineScriptSession } from './inlineScriptsUtils';
5
4
  import { loadSchemaFromModule } from '../../../flows/flowInfers';
6
5
  import { aiChatManager } from '../AIChatManager.svelte';
7
6
  import { refreshStateStore } from '../../../../svelte5Utils.svelte';
8
- import { getSubModules } from '../../../flows/flowExplorer';
9
- import { SPECIAL_MODULE_IDS } from '../shared';
7
+ import { applyFlowJsonUpdate, updateRawScriptModuleContent } from './helperUtils';
8
+ import { findModuleInFlow } from '../../../flows/flowTree';
10
9
  let { flowModuleSchemaMap, onTestFlow } = $props();
11
10
  const { flowStore, flowStateStore, selectionManager, currentEditor, previewArgs } = getContext('FlowEditorContext');
12
11
  const selectedId = $derived(selectionManager.getSelectedId());
13
12
  const { exprsToSet } = getContext('FlowCopilotContext') ?? {};
13
+ const inlineScriptSession = createInlineScriptSession();
14
14
  // Get diffManager from the graph
15
15
  const diffManager = $derived(flowModuleSchemaMap?.getDiffManager());
16
- function getModule(id, flow = flowStore.val) {
17
- if (id === SPECIAL_MODULE_IDS.PREPROCESSOR) {
18
- return flow.value.preprocessor_module;
19
- }
20
- else if (id === SPECIAL_MODULE_IDS.FAILURE) {
21
- return flow.value.failure_module;
22
- }
23
- else {
24
- return dfs(id, flow, false)[0];
25
- }
26
- }
27
16
  const flowHelpers = {
28
17
  // flow context
29
18
  getFlowAndSelectedId: () => {
@@ -33,16 +22,10 @@ const flowHelpers = {
33
22
  selectedId: selectedId === 'settings-metadata' ? '' : selectedId
34
23
  };
35
24
  },
36
- getModules: (id) => {
37
- if (id) {
38
- const module = getModule(id);
39
- if (!module) {
40
- throw new Error('Module not found');
41
- }
42
- return getSubModules(module).flat();
43
- }
25
+ getRootModules: () => {
44
26
  return flowStore.val.value.modules;
45
27
  },
28
+ inlineScriptSession,
46
29
  setSnapshot: (snapshot) => {
47
30
  diffManager?.setBeforeFlow(snapshot);
48
31
  },
@@ -54,7 +37,7 @@ const flowHelpers = {
54
37
  // Update current editor if needed
55
38
  const targetSnapshot = snapshot ?? diffManager.beforeFlow;
56
39
  if ($currentEditor && targetSnapshot) {
57
- const module = getModule($currentEditor.stepId, targetSnapshot);
40
+ const module = findModuleInFlow(targetSnapshot.value, $currentEditor.stepId) ?? undefined;
58
41
  if (module) {
59
42
  if ($currentEditor.type === 'script' && module.value.type === 'rawscript') {
60
43
  $currentEditor.editor.setCode(module.value.content);
@@ -67,48 +50,43 @@ const flowHelpers = {
67
50
  },
68
51
  // ai chat tools
69
52
  setCode: async (id, code) => {
70
- const module = getModule(id);
53
+ // 1. Take snapshot only if none exists (preserves baseline for cumulative changes)
54
+ if (!diffManager?.beforeFlow) {
55
+ const snapshot = $state.snapshot(flowStore).val;
56
+ diffManager?.setBeforeFlow(snapshot);
57
+ diffManager?.setEditMode(true);
58
+ }
59
+ // 2. Apply the code change
60
+ const module = updateRawScriptModuleContent(flowStore.val, id, code);
71
61
  if (!module) {
72
- throw new Error('Module not found');
62
+ throw new Error('Module not found or is not a rawscript');
73
63
  }
74
- if (module.value.type === 'rawscript') {
75
- // 1. Take snapshot only if none exists (preserves baseline for cumulative changes)
76
- if (!diffManager?.beforeFlow) {
77
- const snapshot = $state.snapshot(flowStore).val;
78
- diffManager?.setBeforeFlow(snapshot);
79
- diffManager?.setEditMode(true);
80
- }
81
- // 2. Apply the code change
82
- module.value.content = code;
83
- const { input_transforms, schema } = await loadSchemaFromModule(module);
84
- module.value.input_transforms = input_transforms;
85
- refreshStateStore(flowStore);
86
- // Update exprsToSet if this module is currently selected
87
- if (id === selectedId && exprsToSet) {
88
- exprsToSet.set(input_transforms);
89
- }
90
- if (flowStateStore.val[id]) {
91
- flowStateStore.val[id].schema = schema;
92
- }
93
- else {
94
- flowStateStore.val[id] = {
95
- schema
96
- };
97
- }
98
- // 3. Manually add to moduleActions, preserving existing action types
99
- // Note: currentFlow is auto-synced by FlowGraphV2's effect after refreshStateStore
100
- const currentAction = diffManager?.moduleActions[id];
101
- if (!currentAction) {
102
- diffManager?.setModuleActions({
103
- ...diffManager?.moduleActions,
104
- [id]: { action: 'modified', pending: true }
105
- });
106
- }
107
- // If already tracked (e.g., 'added' from setFlowJson), keep that status
64
+ inlineScriptSession.set(id, code);
65
+ const { input_transforms, schema } = await loadSchemaFromModule(module);
66
+ module.value.input_transforms = input_transforms;
67
+ refreshStateStore(flowStore);
68
+ // Update exprsToSet if this module is currently selected
69
+ if (id === selectedId && exprsToSet) {
70
+ exprsToSet.set(input_transforms);
71
+ }
72
+ if (flowStateStore.val[id]) {
73
+ flowStateStore.val[id].schema = schema;
108
74
  }
109
75
  else {
110
- throw new Error('Module is not a rawscript or script');
76
+ flowStateStore.val[id] = {
77
+ schema
78
+ };
79
+ }
80
+ // 3. Manually add to moduleActions, preserving existing action types
81
+ // Note: currentFlow is auto-synced by FlowGraphV2's effect after refreshStateStore
82
+ const currentAction = diffManager?.moduleActions[id];
83
+ if (!currentAction) {
84
+ diffManager?.setModuleActions({
85
+ ...diffManager?.moduleActions,
86
+ [id]: { action: 'modified', pending: true }
87
+ });
111
88
  }
89
+ // If already tracked (e.g., 'added' from setFlowJson), keep that status
112
90
  if ($currentEditor && $currentEditor.type === 'script' && $currentEditor.stepId === id) {
113
91
  $currentEditor.editor.setCode(code);
114
92
  }
@@ -143,7 +121,7 @@ const flowHelpers = {
143
121
  return await onTestFlow?.(conversationId);
144
122
  },
145
123
  getLintErrors: async (moduleId) => {
146
- const module = getModule(moduleId);
124
+ const module = findModuleInFlow(flowStore.val.value, moduleId) ?? undefined;
147
125
  if (!module || module.value.type !== 'rawscript') {
148
126
  return { errorCount: 0, warningCount: 0, errors: [], warnings: [] };
149
127
  }
@@ -164,9 +142,12 @@ const flowHelpers = {
164
142
  }
165
143
  return { errorCount: 0, warningCount: 0, errors: [], warnings: [] };
166
144
  },
167
- setFlowJson: async (modules, schema) => {
145
+ setFlowJson: async ({ modules, schema, preprocessorModule, failureModule }) => {
168
146
  try {
169
- if (modules || schema) {
147
+ if (modules !== undefined ||
148
+ schema !== undefined ||
149
+ preprocessorModule !== undefined ||
150
+ failureModule !== undefined) {
170
151
  // Take snapshot of current flowStore and set as beforeFlow
171
152
  if (!diffManager?.hasPendingChanges) {
172
153
  const snapshot = $state.snapshot(flowStore).val;
@@ -174,21 +155,17 @@ const flowHelpers = {
174
155
  diffManager?.setEditMode(true);
175
156
  }
176
157
  }
177
- if (modules) {
178
- // Restore inline script references back to full content
179
- const restoredModules = restoreInlineScriptReferences(modules);
180
- // Directly modify flowStore (immediate effect)
181
- flowStore.val.value.modules = restoredModules;
182
- }
183
- // Update schema if provided
184
- if (schema !== undefined) {
185
- flowStore.val.schema = schema;
186
- }
158
+ const result = applyFlowJsonUpdate(flowStore.val, inlineScriptSession, {
159
+ modules,
160
+ schema,
161
+ preprocessorModule,
162
+ failureModule
163
+ });
187
164
  // Refresh the state store to update UI
188
165
  refreshStateStore(flowStore);
166
+ return result;
189
167
  }
190
168
  catch (error) {
191
- console.error('setFlowJson error:', error);
192
169
  throw new Error(`Failed to parse or apply JSON: ${error instanceof Error ? error.message : String(error)}`);
193
170
  }
194
171
  }
@@ -198,7 +175,9 @@ $effect(() => {
198
175
  selectedId &&
199
176
  diffManager?.moduleActions[selectedId]?.pending &&
200
177
  $currentEditor.editor.getAiChatEditorHandler()) {
201
- const moduleLastSnapshot = getModule(selectedId, diffManager.beforeFlow);
178
+ const moduleLastSnapshot = diffManager.beforeFlow
179
+ ? (findModuleInFlow(diffManager.beforeFlow.value, selectedId) ?? undefined)
180
+ : undefined;
202
181
  const content = moduleLastSnapshot?.value.type === 'rawscript' ? moduleLastSnapshot.value.content : '';
203
182
  if (content.length > 0) {
204
183
  untrack(() => $currentEditor.editor.reviewAppliedCode(content, {