windmill-components 1.687.0 → 1.695.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 (264) hide show
  1. package/package/components/ArgInput.svelte +2 -0
  2. package/package/components/AutoscalingConfigEditor.svelte +18 -4
  3. package/package/components/CompareWorkspaces.svelte +206 -157
  4. package/package/components/DatatableSchemaDiff.svelte +2 -2
  5. package/package/components/Dev.svelte +401 -85
  6. package/package/components/EditableSchemaForm.svelte +4 -0
  7. package/package/components/ErrorOrRecoveryHandler.svelte +2 -2
  8. package/package/components/FlowPreviewContent.svelte +32 -30
  9. package/package/components/FlowRestartButton.svelte +143 -61
  10. package/package/components/FlowRestartButton.svelte.d.ts +37 -0
  11. package/package/components/FlowStatusViewer.svelte +15 -1
  12. package/package/components/FlowStatusViewer.svelte.d.ts +10 -2
  13. package/package/components/FlowStatusViewerInner.svelte +1 -2
  14. package/package/components/FlowStatusViewerInner.svelte.d.ts +6 -2
  15. package/package/components/ForkConflictModal.svelte +57 -0
  16. package/package/components/ForkConflictModal.svelte.d.ts +3 -0
  17. package/package/components/GitRepoViewer.svelte +251 -97
  18. package/package/components/InputTransformSchemaForm.svelte +1 -1
  19. package/package/components/InstanceSettings.svelte +36 -16
  20. package/package/components/Login.svelte +113 -28
  21. package/package/components/Login.svelte.d.ts +1 -0
  22. package/package/components/Path.svelte +7 -1
  23. package/package/components/Path.svelte.d.ts +1 -1
  24. package/package/components/RunsPage.svelte +2 -1
  25. package/package/components/S3FilePickerInner.svelte +89 -89
  26. package/package/components/ScriptEditor.svelte +18 -5
  27. package/package/components/ShareModal.svelte.d.ts +1 -1
  28. package/package/components/apps/components/helpers/RunnableComponent.svelte.d.ts +3 -0
  29. package/package/components/apps/components/helpers/executeRunnable.js +2 -1
  30. package/package/components/apps/editor/AppReportsDrawerInner.svelte +1 -1
  31. package/package/components/apps/editor/appPolicy.js +2 -1
  32. package/package/components/apps/editor/commonAppUtils.d.ts +3 -0
  33. package/package/components/apps/editor/inlineScriptsPanel/CacheTtlPopup.svelte +1 -1
  34. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +7 -0
  35. package/package/components/apps/editor/inlineScriptsPanel/TagPopup.svelte +49 -0
  36. package/package/components/apps/editor/inlineScriptsPanel/TagPopup.svelte.d.ts +9 -0
  37. package/package/components/apps/inputType.d.ts +1 -0
  38. package/package/components/apps/sharedTypes.d.ts +1 -0
  39. package/package/components/auditLogs/AuditLogsFilters.svelte +8 -3
  40. package/package/components/common/fileUpload/S3ArgInput.svelte +12 -10
  41. package/package/components/common/fileUpload/S3ArgInput.svelte.d.ts +2 -0
  42. package/package/components/copilot/chat/AIChatDisplay.svelte +5 -36
  43. package/package/components/copilot/chat/AIChatInput.svelte +56 -47
  44. package/package/components/copilot/chat/AIChatManager.svelte.js +48 -46
  45. package/package/components/copilot/chat/ContextElementBadge.svelte +6 -4
  46. package/package/components/copilot/chat/app/core.d.ts +12 -20
  47. package/package/components/copilot/chat/app/core.js +103 -160
  48. package/package/components/copilot/chat/app/core.test.js +234 -9
  49. package/package/components/copilot/chat/context.js +44 -0
  50. package/package/components/copilot/chat/flow/FlowAIChat.svelte +5 -3
  51. package/package/components/copilot/chat/flow/core.d.ts +2 -1
  52. package/package/components/copilot/chat/flow/core.js +48 -21
  53. package/package/components/copilot/chat/flow/helperUtils.d.ts +5 -2
  54. package/package/components/copilot/chat/flow/helperUtils.js +33 -1
  55. package/package/components/copilot/chat/flow/helperUtils.test.js +116 -1
  56. package/package/components/copilot/chat/flow/openFlow.json +1 -1
  57. package/package/components/copilot/chat/flow/openFlowZod.gen.js +24 -0
  58. package/package/components/copilot/chat/script/core.js +3 -0
  59. package/package/components/copilot/chat/shared.d.ts +6 -0
  60. package/package/components/copilot/chat/shared.js +22 -1
  61. package/package/components/copilot/chat/shared.test.d.ts +1 -0
  62. package/package/components/copilot/chat/shared.test.js +412 -0
  63. package/package/components/copilot/chat/workspaceTools.d.ts +7 -0
  64. package/package/components/copilot/chat/workspaceTools.js +239 -0
  65. package/package/components/copilot/chat/workspaceToolsZod.gen.d.ts +1295 -0
  66. package/package/components/copilot/chat/workspaceToolsZod.gen.js +424 -0
  67. package/package/components/copilot/lib.js +3 -1
  68. package/package/components/copilot/lib.test.d.ts +1 -0
  69. package/package/components/copilot/lib.test.js +19 -0
  70. package/package/components/copilot/modelConfig.d.ts +3 -0
  71. package/package/components/copilot/modelConfig.js +10 -0
  72. package/package/components/flows/FlowProgressBar.svelte +5 -2
  73. package/package/components/flows/content/FlowModuleComponent.svelte +636 -599
  74. package/package/components/flows/conversations/FlowChatManager.svelte.js +21 -10
  75. package/package/components/flows/flowStateUtils.svelte.js +5 -1
  76. package/package/components/flows/map/FlowModuleSchemaMap.svelte +3 -2
  77. package/package/components/flows/map/FlowModuleSchemaMap.svelte.d.ts +1 -0
  78. package/package/components/git_sync/GitSyncContext.svelte.js +0 -2
  79. package/package/components/graph/FlowGraphV2.svelte +7 -3
  80. package/package/components/graph/FlowGraphV2.svelte.d.ts +1 -0
  81. package/package/components/graph/renderers/triggers/TriggersBadge.svelte +3 -0
  82. package/package/components/home/deploy_ui.js +1 -1
  83. package/package/components/icons/AzureIcon.svelte +12 -25
  84. package/package/components/icons/AzureIcon.svelte.d.ts +3 -2
  85. package/package/components/instanceSettings.js +24 -0
  86. package/package/components/mcp/McpScopeSelector.svelte +119 -9
  87. package/package/components/mcp/McpScopeSelector.svelte.d.ts +1 -0
  88. package/package/components/offboarding-utils.js +2 -0
  89. package/package/components/progressBar/ProgressBar.svelte +9 -5
  90. package/package/components/progressBar/ProgressBar.svelte.d.ts +1 -0
  91. package/package/components/raw_apps/DeleteAfterUsePopup.svelte +52 -0
  92. package/package/components/raw_apps/DeleteAfterUsePopup.svelte.d.ts +9 -0
  93. package/package/components/raw_apps/RawAppBackgroundRunner.svelte +5 -1
  94. package/package/components/raw_apps/RawAppEditor.svelte +159 -102
  95. package/package/components/raw_apps/RawAppInlineScriptEditor.svelte +9 -3
  96. package/package/components/raw_apps/RawAppInlineScriptEditor.svelte.d.ts +2 -1
  97. package/package/components/raw_apps/RawAppInlineScriptRunnable.svelte +1 -0
  98. package/package/components/raw_apps/RawAppInlineScriptRunnable.svelte.d.ts +1 -0
  99. package/package/components/raw_apps/RawAppInputsSpecEditor.svelte +48 -5
  100. package/package/components/raw_apps/RawAppSharedUiDrawer.svelte +129 -0
  101. package/package/components/raw_apps/RawAppSharedUiDrawer.svelte.d.ts +5 -0
  102. package/package/components/raw_apps/RawAppSidebar.svelte +12 -0
  103. package/package/components/raw_apps/dataTableRefUtils.d.ts +7 -0
  104. package/package/components/raw_apps/dataTableRefUtils.js +34 -0
  105. package/package/components/raw_apps/dataTableRefUtils.test.d.ts +1 -0
  106. package/package/components/raw_apps/dataTableRefUtils.test.js +29 -0
  107. package/package/components/raw_apps/rawAppPolicy.d.ts +1 -0
  108. package/package/components/raw_apps/rawAppPolicy.js +17 -2
  109. package/package/components/resources/resourceTypesFilter.d.ts +19 -0
  110. package/package/components/resources/resourceTypesFilter.js +21 -0
  111. package/package/components/restartFromStepPath.d.ts +39 -0
  112. package/package/components/restartFromStepPath.js +89 -0
  113. package/package/components/runs/JobDetailFieldConfig.d.ts +1 -0
  114. package/package/components/runs/JobDetailFieldConfig.js +57 -10
  115. package/package/components/runs/JobDetailHeader.svelte +24 -3
  116. package/package/components/runs/runsFilter.d.ts +1 -1
  117. package/package/components/schema/FlowPropertyEditor.svelte +30 -1
  118. package/package/components/schema/FlowPropertyEditor.svelte.d.ts +5 -2
  119. package/package/components/search/GlobalSearchModal.svelte +8 -1
  120. package/package/components/select/Select.svelte +1 -1
  121. package/package/components/settings/CreateToken.svelte +48 -77
  122. package/package/components/settings/EditTokenScopesModal.svelte +57 -0
  123. package/package/components/settings/EditTokenScopesModal.svelte.d.ts +10 -0
  124. package/package/components/settings/ScopesPicker.svelte +43 -0
  125. package/package/components/settings/ScopesPicker.svelte.d.ts +11 -0
  126. package/package/components/settings/TokensTable.svelte +51 -15
  127. package/package/components/sidebar/OperatorMenu.svelte +6 -0
  128. package/package/components/sidebar/SidebarContent.svelte +11 -1
  129. package/package/components/triggers/AddTriggersButton.svelte +6 -0
  130. package/package/components/triggers/CaptureWrapper.svelte +19 -1
  131. package/package/components/triggers/TriggerEditorToolbar.svelte.d.ts +1 -1
  132. package/package/components/triggers/TriggerModeToggle.svelte +36 -7
  133. package/package/components/triggers/TriggerModeToggle.svelte.d.ts +1 -1
  134. package/package/components/triggers/TriggerSuspendedJobsModal.svelte.d.ts +1 -1
  135. package/package/components/triggers/TriggersEditor.svelte +5 -1
  136. package/package/components/triggers/TriggersWrapper.svelte +10 -0
  137. package/package/components/triggers/azure/AzureCapture.svelte +41 -0
  138. package/package/components/triggers/azure/AzureCapture.svelte.d.ts +44 -0
  139. package/package/components/triggers/azure/AzureTriggerEditor.svelte +20 -0
  140. package/package/components/triggers/azure/AzureTriggerEditor.svelte.d.ts +9 -0
  141. package/package/components/triggers/azure/AzureTriggerEditorConfigSection.svelte +301 -0
  142. package/package/components/triggers/azure/AzureTriggerEditorConfigSection.svelte.d.ts +16 -0
  143. package/package/components/triggers/azure/AzureTriggerEditorInner.svelte +422 -0
  144. package/package/components/triggers/azure/AzureTriggerEditorInner.svelte.d.ts +25 -0
  145. package/package/components/triggers/azure/AzureTriggerPanel.svelte +55 -0
  146. package/package/components/triggers/azure/AzureTriggerPanel.svelte.d.ts +10 -0
  147. package/{dist/sharedUtils/components/triggers/kafka → package/components/triggers/azure}/utils.d.ts +1 -1
  148. package/package/components/triggers/azure/utils.js +56 -0
  149. package/package/components/triggers/email/EmailTriggerEditorInner.svelte +2 -0
  150. package/package/components/triggers/gcp/GcpTriggerEditorInner.svelte +9 -3
  151. package/package/components/triggers/http/RouteEditorInner.svelte +2 -0
  152. package/package/components/triggers/kafka/KafkaTriggerEditorInner.svelte +9 -3
  153. package/package/components/triggers/mqtt/MqttTriggerEditorInner.svelte +9 -3
  154. package/package/components/triggers/nats/NatsTriggerEditorInner.svelte +9 -3
  155. package/package/components/triggers/postgres/PostgresTriggerEditorInner.svelte +9 -3
  156. package/package/components/triggers/schedules/ScheduleEditorInner.svelte +9 -3
  157. package/package/components/triggers/sqs/SqsTriggerEditorInner.svelte +9 -3
  158. package/package/components/triggers/triggers.svelte.d.ts +1 -0
  159. package/package/components/triggers/triggers.svelte.js +23 -1
  160. package/package/components/triggers/utils.js +20 -0
  161. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +9 -3
  162. package/package/components/triggers.d.ts +1 -1
  163. package/package/components/useNestedRestartState.svelte.d.ts +56 -0
  164. package/package/components/useNestedRestartState.svelte.js +320 -0
  165. package/package/components/workspaceSettings/SharedUiSettings.svelte +175 -0
  166. package/package/components/workspaceSettings/SharedUiSettings.svelte.d.ts +3 -0
  167. package/package/gen/core/OpenAPI.js +1 -1
  168. package/package/gen/schemas.gen.d.ts +294 -24
  169. package/package/gen/schemas.gen.js +297 -25
  170. package/package/gen/services.gen.d.ts +247 -4
  171. package/package/gen/services.gen.js +498 -7
  172. package/package/gen/types.gen.d.ts +990 -37
  173. package/package/hubPaths.json +2 -5
  174. package/package/infer.d.ts +1 -1
  175. package/package/infer.js +37 -51
  176. package/package/mcpEndpointTools.js +60 -4
  177. package/package/script_helpers.js +17 -0
  178. package/package/stores.d.ts +7 -0
  179. package/package/stores.js +6 -1
  180. package/package/system_prompts/index.d.ts +1 -0
  181. package/package/system_prompts/index.js +8 -0
  182. package/package/system_prompts/prompts.d.ts +16 -13
  183. package/package/system_prompts/prompts.js +653 -43
  184. package/package/templates/ci_test_bun.ts.template +8 -0
  185. package/package/templates/ci_test_python.py.template +8 -0
  186. package/package/utils/forkConflict.d.ts +26 -0
  187. package/package/utils/forkConflict.js +56 -0
  188. package/package/utils_deployable.d.ts +164 -121
  189. package/package/utils_deployable.js +61 -11
  190. package/package/utils_workspace_deploy.js +3 -1
  191. package/package.json +28 -4
  192. package/dist/sharedUtils/assets/tokens/colorTokensConfig.d.ts +0 -2
  193. package/dist/sharedUtils/base.d.ts +0 -1
  194. package/dist/sharedUtils/cloud.d.ts +0 -1
  195. package/dist/sharedUtils/common.d.ts +0 -111
  196. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/count.d.ts +0 -5
  197. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/delete.d.ts +0 -5
  198. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/insert.d.ts +0 -5
  199. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/select.d.ts +0 -13
  200. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/update.d.ts +0 -11
  201. package/dist/sharedUtils/components/apps/components/display/dbtable/utils.d.ts +0 -95
  202. package/dist/sharedUtils/components/apps/editor/appPolicy.d.ts +0 -6
  203. package/dist/sharedUtils/components/apps/editor/appUtilsCore.d.ts +0 -7
  204. package/dist/sharedUtils/components/apps/editor/appUtilsS3.d.ts +0 -33
  205. package/dist/sharedUtils/components/apps/editor/commonAppUtils.d.ts +0 -10
  206. package/dist/sharedUtils/components/apps/editor/component/components.d.ts +0 -5371
  207. package/dist/sharedUtils/components/apps/editor/component/default-codes.d.ts +0 -3
  208. package/dist/sharedUtils/components/apps/editor/component/index.d.ts +0 -3
  209. package/dist/sharedUtils/components/apps/editor/component/sets.d.ts +0 -7
  210. package/dist/sharedUtils/components/apps/editor/componentsPanel/componentDefaultProps.d.ts +0 -3
  211. package/dist/sharedUtils/components/apps/gridUtils.d.ts +0 -14
  212. package/dist/sharedUtils/components/apps/inputType.d.ts +0 -178
  213. package/dist/sharedUtils/components/apps/rx.d.ts +0 -29
  214. package/dist/sharedUtils/components/apps/sharedTypes.d.ts +0 -21
  215. package/dist/sharedUtils/components/apps/types.d.ts +0 -274
  216. package/dist/sharedUtils/components/assets/lib.d.ts +0 -25
  217. package/dist/sharedUtils/components/common/alert/model.d.ts +0 -2
  218. package/dist/sharedUtils/components/common/badge/model.d.ts +0 -8
  219. package/dist/sharedUtils/components/common/button/model.d.ts +0 -45
  220. package/dist/sharedUtils/components/common/fileInput/model.d.ts +0 -1
  221. package/dist/sharedUtils/components/common/index.d.ts +0 -24
  222. package/dist/sharedUtils/components/common/skeleton/model.d.ts +0 -21
  223. package/dist/sharedUtils/components/dbTypes.d.ts +0 -14
  224. package/dist/sharedUtils/components/diff_drawer.d.ts +0 -26
  225. package/dist/sharedUtils/components/ducklake.d.ts +0 -1
  226. package/dist/sharedUtils/components/flows/scheduleUtils.d.ts +0 -7
  227. package/dist/sharedUtils/components/icons/index.d.ts +0 -101
  228. package/dist/sharedUtils/components/random_positive_adjetive.d.ts +0 -1
  229. package/dist/sharedUtils/components/raw_apps/rawAppPolicy.d.ts +0 -10
  230. package/dist/sharedUtils/components/raw_apps/utils.d.ts +0 -15
  231. package/dist/sharedUtils/components/triggers/email/utils.d.ts +0 -4
  232. package/dist/sharedUtils/components/triggers/gcp/utils.d.ts +0 -2
  233. package/dist/sharedUtils/components/triggers/http/utils.d.ts +0 -11
  234. package/dist/sharedUtils/components/triggers/mqtt/utils.d.ts +0 -2
  235. package/dist/sharedUtils/components/triggers/nats/utils.d.ts +0 -2
  236. package/dist/sharedUtils/components/triggers/postgres/utils.d.ts +0 -8
  237. package/dist/sharedUtils/components/triggers/sqs/utils.d.ts +0 -2
  238. package/dist/sharedUtils/components/triggers/triggers.svelte.d.ts +0 -32
  239. package/dist/sharedUtils/components/triggers/utils.d.ts +0 -80
  240. package/dist/sharedUtils/components/triggers/websocket/utils.d.ts +0 -2
  241. package/dist/sharedUtils/components/triggers.d.ts +0 -20
  242. package/dist/sharedUtils/gen/core/ApiError.d.ts +0 -10
  243. package/dist/sharedUtils/gen/core/ApiRequestOptions.d.ts +0 -13
  244. package/dist/sharedUtils/gen/core/ApiResult.d.ts +0 -7
  245. package/dist/sharedUtils/gen/core/CancelablePromise.d.ts +0 -26
  246. package/dist/sharedUtils/gen/core/OpenAPI.d.ts +0 -27
  247. package/dist/sharedUtils/gen/core/request.d.ts +0 -29
  248. package/dist/sharedUtils/gen/index.d.ts +0 -6
  249. package/dist/sharedUtils/gen/schemas.gen.d.ts +0 -7036
  250. package/dist/sharedUtils/gen/services.gen.d.ts +0 -6047
  251. package/dist/sharedUtils/gen/types.gen.d.ts +0 -21881
  252. package/dist/sharedUtils/history.svelte.d.ts +0 -9
  253. package/dist/sharedUtils/hub.d.ts +0 -49
  254. package/dist/sharedUtils/jsr.json +0 -6
  255. package/dist/sharedUtils/lib.d.ts +0 -5
  256. package/dist/sharedUtils/lib.es.js +0 -1588
  257. package/dist/sharedUtils/package.json +0 -12
  258. package/dist/sharedUtils/schema.d.ts +0 -3
  259. package/dist/sharedUtils/stores.d.ts +0 -97
  260. package/dist/sharedUtils/svelte5Utils.svelte.d.ts +0 -80
  261. package/dist/sharedUtils/toast.d.ts +0 -8
  262. package/dist/sharedUtils/utils.d.ts +0 -265
  263. package/package/components/copilot/chat/flow/openFlowZod.js +0 -24
  264. /package/package/components/copilot/chat/flow/{openFlowZod.d.ts → openFlowZod.gen.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import type { ChatCompletionSystemMessageParam, ChatCompletionUserMessageParam } from 'openai/resources/chat/completions.mjs';
2
2
  import { type Tool } from '../shared';
3
- import type { ContextElement, AppCodeSelectionElement } from '../context';
3
+ import { type ContextElement, type AppCodeSelectionElement } from '../context';
4
4
  export type BackendRunnableType = 'script' | 'flow' | 'hubscript' | 'inline';
5
5
  export interface InlineScript {
6
6
  language: 'bun' | 'python3';
@@ -57,28 +57,12 @@ export interface InspectorElementInfo {
57
57
  /** Computed styles of the element */
58
58
  styles: Record<string, string>;
59
59
  }
60
- /** Context about the currently selected file or runnable in the app editor */
60
+ /** App editor context that is implicitly attached to app-mode AI messages. */
61
61
  export interface SelectedContext {
62
- /** Type of selection: 'frontend' for frontend files, 'backend' for backend runnables, or 'none' if nothing is selected */
63
- type: 'frontend' | 'backend' | 'none';
64
- /** The path of the selected frontend file (when type is 'frontend') */
65
- frontendPath?: string;
66
- /** The content of the selected frontend file */
67
- frontendContent?: string;
68
- /** The key of the selected backend runnable (when type is 'backend') */
69
- backendKey?: string;
70
- /** The configuration of the selected backend runnable */
71
- backendRunnable?: BackendRunnable;
72
62
  /** Inspector-selected element info (when user has used the inspector tool) */
73
63
  inspectorElement?: InspectorElementInfo;
74
- /** Whether the file/runnable selection is excluded from being sent to the AI prompt */
75
- selectionExcluded?: boolean;
76
- /** Function to toggle whether the selection is excluded from the prompt */
77
- toggleSelectionExcluded?: () => void;
78
64
  /** Function to clear the inspector selection */
79
65
  clearInspector?: () => void;
80
- /** Function to clear the runnable selection (go back to frontend view) */
81
- clearRunnable?: () => void;
82
66
  /** Code selection from the editor (either frontend or backend) */
83
67
  codeSelection?: AppCodeSelectionElement;
84
68
  /** Function to clear the code selection */
@@ -94,6 +78,12 @@ export interface DataTableSchema {
94
78
  schemas: Record<string, Record<string, Record<string, string>>>;
95
79
  error?: string;
96
80
  }
81
+ export interface AppDatatableMetadata {
82
+ datatable_name: string;
83
+ schemas: Record<string, string[]>;
84
+ tableCount: number;
85
+ error?: string;
86
+ }
97
87
  export interface AppAIChatHelpers {
98
88
  listFrontendFiles: () => string[];
99
89
  getFrontendFile: (path: string) => string | undefined;
@@ -116,8 +106,10 @@ export interface AppAIChatHelpers {
116
106
  revertToSnapshot: (id: number) => void;
117
107
  /** Lint all frontend files and backend runnables, returns errors and warnings */
118
108
  lint: () => LintResult;
119
- /** Get all datatables configured in the app with their schemas */
120
- getDatatables: () => Promise<DataTableSchema[]>;
109
+ /** List configured datatables with schema/table names only. */
110
+ listDatatableTables: () => Promise<AppDatatableMetadata[]>;
111
+ /** Get columns for one datatable table. */
112
+ getDatatableTableSchema: (datatableName: string, schemaName: string, tableName: string) => Promise<Record<string, string>>;
121
113
  /** Get unique datatable names configured in the app (for UI policy selector) */
122
114
  getAvailableDatatableNames: () => string[];
123
115
  /** Execute a SQL query on a datatable. Optionally specify newTable to register a newly created table. */
@@ -1,10 +1,8 @@
1
1
  import { z } from 'zod';
2
2
  import { createSearchHubScriptsTool, createToolDef, createSearchWorkspaceTool, createGetRunnableDetailsTool } from '../shared';
3
- import { getDatatableSdkReference } from '../../../../system_prompts';
4
3
  import { aiChatManager } from '../AIChatManager.svelte';
4
+ import { formatAppDatatableContextTitle } from '../context';
5
5
  // ============= Utility =============
6
- /** Maximum characters per file in get_files tool */
7
- const BATCH_FILE_SIZE_LIMIT = 2500;
8
6
  /** Memoize a factory function - the factory is only called once, on first access */
9
7
  const memo = (factory) => {
10
8
  let cached;
@@ -31,11 +29,11 @@ function replaceFirstExactMatch(content, search, replace) {
31
29
  }
32
30
  function resolveAppPatchTarget(rawPath) {
33
31
  const trimmedPath = rawPath.trim();
34
- const backendMatch = trimmedPath.match(/^\/?backend\/([^/]+)\/main\.(ts|py)$/);
32
+ const backendMatch = trimmedPath.match(/^backend\/([^/]+)\/main\.(ts|py)$/);
35
33
  if (backendMatch) {
36
34
  return {
37
35
  type: 'backend',
38
- path: trimmedPath.startsWith('/') ? trimmedPath.slice(1) : trimmedPath,
36
+ path: trimmedPath,
39
37
  key: backendMatch[1],
40
38
  extension: backendMatch[2]
41
39
  };
@@ -48,6 +46,15 @@ function resolveAppPatchTarget(rawPath) {
48
46
  function getBackendInlineScriptExtension(runnable) {
49
47
  return runnable.inlineScript?.language === 'python3' ? 'py' : 'ts';
50
48
  }
49
+ function getFileKind(path) {
50
+ const filename = path.split('/').pop() ?? path;
51
+ const extension = filename.includes('.') ? filename.split('.').pop() : undefined;
52
+ return extension || 'unknown';
53
+ }
54
+ function getStaticInputKeys(runnable) {
55
+ const keys = runnable.staticInputs ? Object.keys(runnable.staticInputs) : [];
56
+ return keys.length > 0 ? keys : undefined;
57
+ }
51
58
  // ============= Frontend File Tools =============
52
59
  const getGetFrontendFileSchema = memo(() => z.object({
53
60
  path: z
@@ -118,12 +125,17 @@ const getDeleteBackendRunnableToolDef = memo(() => createToolDef(getDeleteBacken
118
125
  // ============= Lint Tool =============
119
126
  const getLintSchema = memo(() => z.object({}));
120
127
  const getLintToolDef = memo(() => createToolDef(getLintSchema(), 'lint', 'Lint all frontend files and backend runnables. Returns errors and warnings grouped by frontend/backend. Use this to check for issues after making changes.'));
121
- // ============= Combined Files Tool =============
122
- const getGetFilesSchema = memo(() => z.object({}));
123
- const getGetFilesToolDef = memo(() => createToolDef(getGetFilesSchema(), 'get_files', 'Get an overview of all files in the app. Content may be truncated for large apps - use get_frontend_file or get_backend_runnable for full content of specific files.'));
128
+ const getListFilesSchema = memo(() => z.object({}));
129
+ const getListFilesToolDef = memo(() => createToolDef(getListFilesSchema(), 'list_files', 'List lightweight metadata for frontend files and backend runnables in the app. Does not include file or runnable content. Use get_frontend_file(path) or get_backend_runnable(key) to inspect specific content.'));
124
130
  // ============= Data Table Tools =============
125
- const getGetDatatablesSchema = memo(() => z.object({}));
126
- const getGetDatatablesToolDef = memo(() => createToolDef(getGetDatatablesSchema(), 'get_datatables', 'Get all datatables configured in this app with their full schemas. Returns datatable names, tables, and column definitions. Use this to understand the data layer available to the app.'));
131
+ const getListDatatablesSchema = memo(() => z.object({}));
132
+ const getListDatatablesToolDef = memo(() => createToolDef(getListDatatablesSchema(), 'list_datatables', 'List datatables configured in the app with schema and table names only. Does not include column definitions. Use this directly for table-list or available-tables summaries. Only call get_datatable_table_schema when column names/types are required.'));
133
+ const getGetDatatableTableSchemaSchema = memo(() => z.object({
134
+ datatable_name: z.string().describe('The datatable name to inspect, e.g. "main".'),
135
+ schema_name: z.string().describe('The schema name, e.g. "public".'),
136
+ table_name: z.string().describe('The table name to inspect.')
137
+ }));
138
+ const getGetDatatableTableSchemaToolDef = memo(() => createToolDef(getGetDatatableTableSchemaSchema(), 'get_datatable_table_schema', 'Get column definitions for one datatable table. Do not call this for row counts or table-list summaries; list_datatables is enough for those.'));
127
139
  const getExecDatatableSqlSchema = memo(() => z.object({
128
140
  datatable_name: z
129
141
  .string()
@@ -140,9 +152,6 @@ const getExecDatatableSqlSchema = memo(() => z.object({
140
152
  .describe('When executing a CREATE TABLE statement, provide this to register the new table in the app so it can be queried and its schema retrieved later.')
141
153
  }));
142
154
  const getExecDatatableSqlToolDef = memo(() => createToolDef(getExecDatatableSqlSchema(), 'exec_datatable_sql', 'Execute a SQL query on a datatable. Use this to explore data, test queries, create tables, or make changes. When creating a new table, pass new_table to register it in the app for future use.', { strict: false }));
143
- // ============= Selected Context Tool =============
144
- const getGetSelectedContextSchema = memo(() => z.object({}));
145
- const getGetSelectedContextToolDef = memo(() => createToolDef(getGetSelectedContextSchema(), 'get_selected_context', 'Get information about what is currently selected in the app editor. Returns the type of selection (frontend file or backend runnable) and the path/key of the selected item.'));
146
155
  // ============= Lint Result Formatting =============
147
156
  function formatLintMessages(messages) {
148
157
  let result = '';
@@ -191,68 +200,37 @@ function formatLintResultResponse(message, lintResult) {
191
200
  }
192
201
  // ============= Tools Array =============
193
202
  export const getAppTools = memo(() => [
194
- // Combined files tool (with per-file truncation for large apps)
203
+ // Lightweight file/runnable metadata tool (no source contents)
195
204
  {
196
- def: getGetFilesToolDef(),
205
+ def: getListFilesToolDef(),
197
206
  fn: async ({ helpers, toolId, toolCallbacks }) => {
198
- toolCallbacks.setToolStatus(toolId, { content: 'Getting all files...' });
207
+ toolCallbacks.setToolStatus(toolId, { content: 'Listing files...' });
199
208
  const files = helpers.getFiles();
200
- const frontendCount = Object.keys(files.frontend).length;
201
- const backendCount = Object.keys(files.backend).length;
202
- // Truncate each file individually to BATCH_FILE_SIZE_LIMIT
203
- let anyTruncated = false;
204
- const truncatedFiles = {
205
- frontend: {},
206
- backend: {}
209
+ const metadata = {
210
+ frontend: Object.entries(files.frontend).map(([path, content]) => ({
211
+ path,
212
+ size: content.length,
213
+ kind: getFileKind(path)
214
+ })),
215
+ backend: Object.entries(files.backend).map(([key, runnable]) => {
216
+ const staticInputKeys = getStaticInputKeys(runnable);
217
+ return {
218
+ key,
219
+ name: runnable.name,
220
+ type: runnable.type,
221
+ ...(runnable.path && { path: runnable.path }),
222
+ ...(runnable.inlineScript && {
223
+ language: runnable.inlineScript.language,
224
+ contentSize: runnable.inlineScript.content.length
225
+ }),
226
+ ...(staticInputKeys && { staticInputKeys })
227
+ };
228
+ })
207
229
  };
208
- for (const [path, content] of Object.entries(files.frontend)) {
209
- if (content.length > BATCH_FILE_SIZE_LIMIT) {
210
- truncatedFiles.frontend[path] =
211
- content.slice(0, BATCH_FILE_SIZE_LIMIT) + '\n... [TRUNCATED]';
212
- anyTruncated = true;
213
- }
214
- else {
215
- truncatedFiles.frontend[path] = content;
216
- }
217
- }
218
- for (const [key, runnable] of Object.entries(files.backend)) {
219
- const runnableCopy = { ...runnable };
220
- if (runnableCopy.inlineScript?.content) {
221
- const content = runnableCopy.inlineScript.content;
222
- if (content.length > BATCH_FILE_SIZE_LIMIT) {
223
- runnableCopy.inlineScript = {
224
- ...runnableCopy.inlineScript,
225
- content: content.slice(0, BATCH_FILE_SIZE_LIMIT) + '\n... [TRUNCATED]'
226
- };
227
- anyTruncated = true;
228
- }
229
- }
230
- truncatedFiles.backend[key] = runnableCopy;
231
- }
232
230
  toolCallbacks.setToolStatus(toolId, {
233
- content: `Retrieved ${frontendCount} frontend files and ${backendCount} backend runnables${anyTruncated ? ' (some truncated)' : ''}`
231
+ content: `Listed ${metadata.frontend.length} frontend files and ${metadata.backend.length} backend runnables`
234
232
  });
235
- let result = JSON.stringify(truncatedFiles, null, 2);
236
- if (anyTruncated) {
237
- result +=
238
- '\n\nNote: Some file contents were truncated. Use get_frontend_file(path) or get_backend_runnable(key) to get full content.';
239
- }
240
- return result;
241
- }
242
- },
243
- // Selected context tool
244
- {
245
- def: getGetSelectedContextToolDef(),
246
- fn: async ({ helpers, toolId, toolCallbacks }) => {
247
- toolCallbacks.setToolStatus(toolId, { content: 'Getting selected context...' });
248
- const context = helpers.getSelectedContext();
249
- const statusMsg = context.type === 'frontend'
250
- ? `Frontend file selected: ${context.frontendPath}`
251
- : context.type === 'backend'
252
- ? `Backend runnable selected: ${context.backendKey}`
253
- : 'No selection';
254
- toolCallbacks.setToolStatus(toolId, { content: statusMsg });
255
- return JSON.stringify(context, null, 2);
233
+ return JSON.stringify(metadata, null, 2);
256
234
  }
257
235
  },
258
236
  // Frontend tools
@@ -469,24 +447,49 @@ export const getAppTools = memo(() => [
469
447
  createSearchHubScriptsTool(false),
470
448
  // Data table tools
471
449
  {
472
- def: getGetDatatablesToolDef(),
450
+ def: getListDatatablesToolDef(),
473
451
  fn: async ({ helpers, toolId, toolCallbacks }) => {
474
- toolCallbacks.setToolStatus(toolId, { content: 'Getting datatables...' });
452
+ toolCallbacks.setToolStatus(toolId, { content: 'Listing datatables...' });
475
453
  try {
476
- const datatables = await helpers.getDatatables();
477
- if (datatables.length === 0) {
454
+ const metadata = await helpers.listDatatableTables();
455
+ if (metadata.length === 0) {
478
456
  toolCallbacks.setToolStatus(toolId, { content: 'No datatables configured' });
479
457
  return 'No datatables are configured in this app. Use the Data panel in the sidebar to add datatable references.';
480
458
  }
481
- const totalTables = datatables.reduce((acc, dt) => acc +
482
- Object.values(dt.schemas).reduce((schemaAcc, tables) => schemaAcc + Object.keys(tables).length, 0), 0);
459
+ const totalTables = metadata.reduce((acc, datatable) => acc + datatable.tableCount, 0);
460
+ toolCallbacks.setToolStatus(toolId, {
461
+ content: `Listed ${metadata.length} datatable(s) with ${totalTables} table(s)`
462
+ });
463
+ return JSON.stringify(metadata, null, 2);
464
+ }
465
+ catch (e) {
466
+ const errorMsg = `Error listing datatables: ${e instanceof Error ? e.message : String(e)}`;
467
+ toolCallbacks.setToolStatus(toolId, { content: errorMsg, error: errorMsg });
468
+ return errorMsg;
469
+ }
470
+ }
471
+ },
472
+ {
473
+ def: getGetDatatableTableSchemaToolDef(),
474
+ fn: async ({ args, helpers, toolId, toolCallbacks }) => {
475
+ const parsedArgs = getGetDatatableTableSchemaSchema().parse(args);
476
+ toolCallbacks.setToolStatus(toolId, {
477
+ content: `Getting schema for ${parsedArgs.datatable_name}.${parsedArgs.schema_name}.${parsedArgs.table_name}...`
478
+ });
479
+ try {
480
+ const columns = await helpers.getDatatableTableSchema(parsedArgs.datatable_name, parsedArgs.schema_name, parsedArgs.table_name);
483
481
  toolCallbacks.setToolStatus(toolId, {
484
- content: `Found ${datatables.length} datatable(s) with ${totalTables} table(s)`
482
+ content: `Retrieved schema for ${parsedArgs.schema_name}.${parsedArgs.table_name}`
485
483
  });
486
- return JSON.stringify(datatables, null, 2);
484
+ return JSON.stringify({
485
+ datatable_name: parsedArgs.datatable_name,
486
+ schema_name: parsedArgs.schema_name,
487
+ table_name: parsedArgs.table_name,
488
+ columns
489
+ }, null, 2);
487
490
  }
488
491
  catch (e) {
489
- const errorMsg = `Error getting datatables: ${e instanceof Error ? e.message : String(e)}`;
492
+ const errorMsg = `Error getting table schema: ${e instanceof Error ? e.message : String(e)}`;
490
493
  toolCallbacks.setToolStatus(toolId, { content: errorMsg, error: errorMsg });
491
494
  return errorMsg;
492
495
  }
@@ -589,7 +592,7 @@ For inline scripts, the code must have a \`main\` function as its entrypoint.
589
592
  ## Available Tools
590
593
 
591
594
  ### File Management
592
- - \`get_files()\`: Get an overview of all files (content may be truncated for large files)
595
+ - \`list_files()\`: List lightweight metadata for frontend files and backend runnables. It does not include file or runnable content.
593
596
  - \`get_frontend_file(path)\`: Get full content of a specific frontend file
594
597
  - \`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\`.
595
598
  - \`set_frontend_file(path, content)\`: Create or update a frontend file. Returns lint diagnostics.
@@ -616,7 +619,8 @@ Use \`patch_file\` for small, localized edits when you can copy an exact snippet
616
619
  - \`search_hub_scripts(query)\`: Search hub scripts
617
620
 
618
621
  ### Data Tables
619
- - \`get_datatables()\`: Get all datatables configured in the app with their schemas (tables, columns, types)
622
+ - \`list_datatables()\`: List configured datatables with schema and table names only. Does not include columns. Use this directly for table-list or available-tables summaries.
623
+ - \`get_datatable_table_schema(datatable_name, schema_name, table_name)\`: Get column definitions for one table. Do not call this for simple row counts or table-list summaries.
620
624
  - \`exec_datatable_sql(datatable_name, sql, new_table?)\`: Execute SQL query on a datatable. Use for data exploration or modifications. When creating a new table, pass \`new_table: { schema, name }\` to register it in the app.
621
625
 
622
626
  ## Data Storage with Data Tables
@@ -625,7 +629,7 @@ Use \`patch_file\` for small, localized edits when you can copy an exact snippet
625
629
 
626
630
  ### Key Principles
627
631
 
628
- 1. **Always check existing tables first**: Use \`get_datatables()\` to see what tables are already available. If a suitable table exists, **always reuse it** rather than creating a new one.
632
+ 1. **Always check existing tables first**: Use \`list_datatables()\` to see what tables are already available. If a suitable table exists, **always reuse it** rather than creating a new one. For dashboards that only show available tables or row counts, \`list_datatables()\` is enough. Only call \`get_datatable_table_schema()\` for tables whose column names/types you need.
629
633
 
630
634
  2. **CRITICAL: Create tables ONLY via exec_datatable_sql tool**: When you need to create a new table, you MUST use the \`exec_datatable_sql\` tool with the \`new_table\` parameter. **NEVER** create tables inside backend runnables using SQL queries - this will not register the table properly and it won't be available for future use.
631
635
  \`\`\`
@@ -669,9 +673,7 @@ def main(user_id: str):
669
673
  return user
670
674
  \`\`\`
671
675
 
672
- ### Datatable Client API Reference
673
-
674
- ${getDatatableSdkReference()}
676
+ Use these examples for normal datatable access.
675
677
 
676
678
  ### Schema Modifications (DDL) - Use exec_datatable_sql tool ONLY
677
679
 
@@ -746,12 +748,13 @@ When you are using the windmill-client, do not forget that as id for variables o
746
748
 
747
749
  ## Instructions
748
750
 
749
- 1. Start with \`get_files()\` to get an overview of all frontend files and backend runnables (content may be truncated for large files)
750
- 2. Use \`get_frontend_file(path)\` or \`get_backend_runnable(key)\` to get full content of specific files when needed
751
+ 1. Use the smallest context needed. If the target file or runnable is clear, inspect only that item with \`get_frontend_file(path)\` or \`get_backend_runnable(key)\`.
752
+ 2. Use \`list_files()\` only when the target is unclear or the request needs a broad app overview. \`list_files()\` returns metadata only, never file contents.
751
753
  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.
752
754
  4. Use \`lint()\` at the end to check for and fix any remaining errors
753
755
 
754
756
  When creating a new app, use \`search_workspace\` or \`search_hub_scripts\` to find existing scripts/flows to reuse.
757
+ When the user mentions frontend files or backend runnables in context, only their identifiers are included. Use \`get_frontend_file\` or \`get_backend_runnable\` to inspect their contents before editing them or relying on implementation details.
755
758
 
756
759
  `;
757
760
  // Add datatable creation policy context
@@ -786,50 +789,10 @@ const MAX_CONTEXT_CONTENT_LENGTH = 3000;
786
789
  export function prepareAppUserMessage(instructions, selectedContext, additionalContext) {
787
790
  let content = '';
788
791
  // Check if we have any context to add
789
- const hasSelectedContext = selectedContext && (selectedContext.type !== 'none' || selectedContext.inspectorElement);
792
+ const hasSelectedContext = selectedContext && (selectedContext.inspectorElement || selectedContext.codeSelection);
790
793
  const hasAdditionalContext = additionalContext && additionalContext.length > 0;
791
794
  if (hasSelectedContext || hasAdditionalContext) {
792
795
  content += `## SELECTED CONTEXT:\n`;
793
- // Add frontend file context with content (unless excluded)
794
- if (selectedContext &&
795
- selectedContext.type === 'frontend' &&
796
- selectedContext.frontendPath &&
797
- !selectedContext.selectionExcluded) {
798
- content += `The user is currently viewing the frontend file: **${selectedContext.frontendPath}**\n`;
799
- if (selectedContext.frontendContent) {
800
- const truncatedContent = selectedContext.frontendContent.length > MAX_CONTEXT_CONTENT_LENGTH
801
- ? selectedContext.frontendContent.slice(0, MAX_CONTEXT_CONTENT_LENGTH) +
802
- '\n... [TRUNCATED]'
803
- : selectedContext.frontendContent;
804
- content += `\n\`\`\`\n${truncatedContent}\n\`\`\`\n`;
805
- }
806
- }
807
- // Add backend runnable context with content (unless excluded)
808
- if (selectedContext &&
809
- selectedContext.type === 'backend' &&
810
- selectedContext.backendKey &&
811
- !selectedContext.selectionExcluded) {
812
- content += `The user is currently viewing the backend runnable: **${selectedContext.backendKey}**\n`;
813
- if (selectedContext.backendRunnable) {
814
- const runnable = selectedContext.backendRunnable;
815
- content += `- **Name**: ${runnable.name}\n`;
816
- content += `- **Type**: ${runnable.type}\n`;
817
- if (runnable.path) {
818
- content += `- **Path**: ${runnable.path}\n`;
819
- }
820
- if (runnable.inlineScript) {
821
- const truncatedCode = runnable.inlineScript.content.length > MAX_CONTEXT_CONTENT_LENGTH
822
- ? runnable.inlineScript.content.slice(0, MAX_CONTEXT_CONTENT_LENGTH) +
823
- '\n... [TRUNCATED]'
824
- : runnable.inlineScript.content;
825
- content += `- **Language**: ${runnable.inlineScript.language}\n`;
826
- content += `- **Code**:\n\`\`\`${runnable.inlineScript.language === 'bun' ? 'typescript' : 'python'}\n${truncatedCode}\n\`\`\`\n`;
827
- }
828
- if (runnable.staticInputs && Object.keys(runnable.staticInputs).length > 0) {
829
- content += `- **Static inputs**: ${JSON.stringify(runnable.staticInputs)}\n`;
830
- }
831
- }
832
- }
833
796
  // Add inspector element context if available
834
797
  if (selectedContext?.inspectorElement) {
835
798
  const el = selectedContext.inspectorElement;
@@ -862,49 +825,29 @@ export function prepareAppUserMessage(instructions, selectedContext, additionalC
862
825
  content += `\n### ADDITIONAL CONTEXT (mentioned by user):\n`;
863
826
  for (const ctx of additionalContext) {
864
827
  if (ctx.type === 'app_frontend_file') {
865
- const fileCtx = ctx;
866
- content += `\n**Frontend File: ${fileCtx.path}**\n`;
867
- const truncatedContent = fileCtx.content.length > MAX_CONTEXT_CONTENT_LENGTH
868
- ? fileCtx.content.slice(0, MAX_CONTEXT_CONTENT_LENGTH) + '\n... [TRUNCATED]'
869
- : fileCtx.content;
870
- content += `\`\`\`\n${truncatedContent}\n\`\`\`\n`;
828
+ content += `\n- Frontend file: ${ctx.path}\n`;
871
829
  }
872
830
  else if (ctx.type === 'app_backend_runnable') {
873
- const runnableCtx = ctx;
874
- const runnable = runnableCtx.runnable;
875
- content += `\n**Backend Runnable: ${runnableCtx.key}**\n`;
876
- content += `- **Name**: ${runnable.name}\n`;
877
- content += `- **Type**: ${runnable.type}\n`;
878
- if (runnable.path) {
879
- content += `- **Path**: ${runnable.path}\n`;
880
- }
881
- if (runnable.inlineScript) {
882
- const truncatedCode = runnable.inlineScript.content.length > MAX_CONTEXT_CONTENT_LENGTH
883
- ? runnable.inlineScript.content.slice(0, MAX_CONTEXT_CONTENT_LENGTH) +
884
- '\n... [TRUNCATED]'
885
- : runnable.inlineScript.content;
886
- content += `- **Language**: ${runnable.inlineScript.language}\n`;
887
- content += `- **Code**:\n\`\`\`${runnable.inlineScript.language === 'bun' ? 'typescript' : 'python'}\n${truncatedCode}\n\`\`\`\n`;
888
- }
889
- if (runnable.staticInputs && Object.keys(runnable.staticInputs).length > 0) {
890
- content += `- **Static inputs**: ${JSON.stringify(runnable.staticInputs)}\n`;
891
- }
831
+ content += `\n- Backend runnable: ${ctx.key}\n`;
892
832
  }
893
833
  else if (ctx.type === 'app_datatable') {
894
834
  const datatableCtx = ctx;
895
- const tableRef = datatableCtx.schemaName === 'public'
896
- ? `${datatableCtx.datatableName}/${datatableCtx.tableName}`
897
- : `${datatableCtx.datatableName}/${datatableCtx.schemaName}:${datatableCtx.tableName}`;
835
+ const tableRef = formatAppDatatableContextTitle(datatableCtx.datatableName, datatableCtx.schemaName, datatableCtx.tableName);
898
836
  content += `\n**Table: ${tableRef}**\n`;
899
837
  content += `- **Datatable**: ${datatableCtx.datatableName}\n`;
900
838
  content += `- **Schema**: ${datatableCtx.schemaName}\n`;
901
839
  content += `- **Table**: ${datatableCtx.tableName}\n`;
902
840
  // Format columns as column_name: type
903
- const columnsStr = JSON.stringify(datatableCtx.columns, null, 2);
904
- const truncatedColumns = columnsStr.length > MAX_CONTEXT_CONTENT_LENGTH
905
- ? columnsStr.slice(0, MAX_CONTEXT_CONTENT_LENGTH) + '\n... [TRUNCATED]'
906
- : columnsStr;
907
- content += `- **Columns** (column_name -> type):\n\`\`\`json\n${truncatedColumns}\n\`\`\`\n`;
841
+ if (datatableCtx.columns) {
842
+ const columnsStr = JSON.stringify(datatableCtx.columns, null, 2);
843
+ const truncatedColumns = columnsStr.length > MAX_CONTEXT_CONTENT_LENGTH
844
+ ? columnsStr.slice(0, MAX_CONTEXT_CONTENT_LENGTH) + '\n... [TRUNCATED]'
845
+ : columnsStr;
846
+ content += `- **Columns** (column_name -> type):\n\`\`\`json\n${truncatedColumns}\n\`\`\`\n`;
847
+ }
848
+ else {
849
+ content += `- **Columns**: not loaded. Use get_datatable_table_schema() if column names or types are needed.\n`;
850
+ }
908
851
  }
909
852
  }
910
853
  }