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.
- package/package/components/ArgInput.svelte +2 -0
- package/package/components/AutoscalingConfigEditor.svelte +18 -4
- package/package/components/CompareWorkspaces.svelte +206 -157
- package/package/components/DatatableSchemaDiff.svelte +2 -2
- package/package/components/Dev.svelte +401 -85
- package/package/components/EditableSchemaForm.svelte +4 -0
- package/package/components/ErrorOrRecoveryHandler.svelte +2 -2
- package/package/components/FlowPreviewContent.svelte +32 -30
- package/package/components/FlowRestartButton.svelte +143 -61
- package/package/components/FlowRestartButton.svelte.d.ts +37 -0
- package/package/components/FlowStatusViewer.svelte +15 -1
- package/package/components/FlowStatusViewer.svelte.d.ts +10 -2
- package/package/components/FlowStatusViewerInner.svelte +1 -2
- package/package/components/FlowStatusViewerInner.svelte.d.ts +6 -2
- package/package/components/ForkConflictModal.svelte +57 -0
- package/package/components/ForkConflictModal.svelte.d.ts +3 -0
- package/package/components/GitRepoViewer.svelte +251 -97
- package/package/components/InputTransformSchemaForm.svelte +1 -1
- package/package/components/InstanceSettings.svelte +36 -16
- package/package/components/Login.svelte +113 -28
- package/package/components/Login.svelte.d.ts +1 -0
- package/package/components/Path.svelte +7 -1
- package/package/components/Path.svelte.d.ts +1 -1
- package/package/components/RunsPage.svelte +2 -1
- package/package/components/S3FilePickerInner.svelte +89 -89
- package/package/components/ScriptEditor.svelte +18 -5
- package/package/components/ShareModal.svelte.d.ts +1 -1
- package/package/components/apps/components/helpers/RunnableComponent.svelte.d.ts +3 -0
- package/package/components/apps/components/helpers/executeRunnable.js +2 -1
- package/package/components/apps/editor/AppReportsDrawerInner.svelte +1 -1
- package/package/components/apps/editor/appPolicy.js +2 -1
- package/package/components/apps/editor/commonAppUtils.d.ts +3 -0
- package/package/components/apps/editor/inlineScriptsPanel/CacheTtlPopup.svelte +1 -1
- package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +7 -0
- package/package/components/apps/editor/inlineScriptsPanel/TagPopup.svelte +49 -0
- package/package/components/apps/editor/inlineScriptsPanel/TagPopup.svelte.d.ts +9 -0
- package/package/components/apps/inputType.d.ts +1 -0
- package/package/components/apps/sharedTypes.d.ts +1 -0
- package/package/components/auditLogs/AuditLogsFilters.svelte +8 -3
- package/package/components/common/fileUpload/S3ArgInput.svelte +12 -10
- package/package/components/common/fileUpload/S3ArgInput.svelte.d.ts +2 -0
- package/package/components/copilot/chat/AIChatDisplay.svelte +5 -36
- package/package/components/copilot/chat/AIChatInput.svelte +56 -47
- package/package/components/copilot/chat/AIChatManager.svelte.js +48 -46
- package/package/components/copilot/chat/ContextElementBadge.svelte +6 -4
- package/package/components/copilot/chat/app/core.d.ts +12 -20
- package/package/components/copilot/chat/app/core.js +103 -160
- package/package/components/copilot/chat/app/core.test.js +234 -9
- package/package/components/copilot/chat/context.js +44 -0
- package/package/components/copilot/chat/flow/FlowAIChat.svelte +5 -3
- package/package/components/copilot/chat/flow/core.d.ts +2 -1
- package/package/components/copilot/chat/flow/core.js +48 -21
- package/package/components/copilot/chat/flow/helperUtils.d.ts +5 -2
- package/package/components/copilot/chat/flow/helperUtils.js +33 -1
- package/package/components/copilot/chat/flow/helperUtils.test.js +116 -1
- package/package/components/copilot/chat/flow/openFlow.json +1 -1
- package/package/components/copilot/chat/flow/openFlowZod.gen.js +24 -0
- package/package/components/copilot/chat/script/core.js +3 -0
- package/package/components/copilot/chat/shared.d.ts +6 -0
- package/package/components/copilot/chat/shared.js +22 -1
- package/package/components/copilot/chat/shared.test.d.ts +1 -0
- package/package/components/copilot/chat/shared.test.js +412 -0
- package/package/components/copilot/chat/workspaceTools.d.ts +7 -0
- package/package/components/copilot/chat/workspaceTools.js +239 -0
- package/package/components/copilot/chat/workspaceToolsZod.gen.d.ts +1295 -0
- package/package/components/copilot/chat/workspaceToolsZod.gen.js +424 -0
- package/package/components/copilot/lib.js +3 -1
- package/package/components/copilot/lib.test.d.ts +1 -0
- package/package/components/copilot/lib.test.js +19 -0
- package/package/components/copilot/modelConfig.d.ts +3 -0
- package/package/components/copilot/modelConfig.js +10 -0
- package/package/components/flows/FlowProgressBar.svelte +5 -2
- package/package/components/flows/content/FlowModuleComponent.svelte +636 -599
- package/package/components/flows/conversations/FlowChatManager.svelte.js +21 -10
- package/package/components/flows/flowStateUtils.svelte.js +5 -1
- package/package/components/flows/map/FlowModuleSchemaMap.svelte +3 -2
- package/package/components/flows/map/FlowModuleSchemaMap.svelte.d.ts +1 -0
- package/package/components/git_sync/GitSyncContext.svelte.js +0 -2
- package/package/components/graph/FlowGraphV2.svelte +7 -3
- package/package/components/graph/FlowGraphV2.svelte.d.ts +1 -0
- package/package/components/graph/renderers/triggers/TriggersBadge.svelte +3 -0
- package/package/components/home/deploy_ui.js +1 -1
- package/package/components/icons/AzureIcon.svelte +12 -25
- package/package/components/icons/AzureIcon.svelte.d.ts +3 -2
- package/package/components/instanceSettings.js +24 -0
- package/package/components/mcp/McpScopeSelector.svelte +119 -9
- package/package/components/mcp/McpScopeSelector.svelte.d.ts +1 -0
- package/package/components/offboarding-utils.js +2 -0
- package/package/components/progressBar/ProgressBar.svelte +9 -5
- package/package/components/progressBar/ProgressBar.svelte.d.ts +1 -0
- package/package/components/raw_apps/DeleteAfterUsePopup.svelte +52 -0
- package/package/components/raw_apps/DeleteAfterUsePopup.svelte.d.ts +9 -0
- package/package/components/raw_apps/RawAppBackgroundRunner.svelte +5 -1
- package/package/components/raw_apps/RawAppEditor.svelte +159 -102
- package/package/components/raw_apps/RawAppInlineScriptEditor.svelte +9 -3
- package/package/components/raw_apps/RawAppInlineScriptEditor.svelte.d.ts +2 -1
- package/package/components/raw_apps/RawAppInlineScriptRunnable.svelte +1 -0
- package/package/components/raw_apps/RawAppInlineScriptRunnable.svelte.d.ts +1 -0
- package/package/components/raw_apps/RawAppInputsSpecEditor.svelte +48 -5
- package/package/components/raw_apps/RawAppSharedUiDrawer.svelte +129 -0
- package/package/components/raw_apps/RawAppSharedUiDrawer.svelte.d.ts +5 -0
- package/package/components/raw_apps/RawAppSidebar.svelte +12 -0
- package/package/components/raw_apps/dataTableRefUtils.d.ts +7 -0
- package/package/components/raw_apps/dataTableRefUtils.js +34 -0
- package/package/components/raw_apps/dataTableRefUtils.test.d.ts +1 -0
- package/package/components/raw_apps/dataTableRefUtils.test.js +29 -0
- package/package/components/raw_apps/rawAppPolicy.d.ts +1 -0
- package/package/components/raw_apps/rawAppPolicy.js +17 -2
- package/package/components/resources/resourceTypesFilter.d.ts +19 -0
- package/package/components/resources/resourceTypesFilter.js +21 -0
- package/package/components/restartFromStepPath.d.ts +39 -0
- package/package/components/restartFromStepPath.js +89 -0
- package/package/components/runs/JobDetailFieldConfig.d.ts +1 -0
- package/package/components/runs/JobDetailFieldConfig.js +57 -10
- package/package/components/runs/JobDetailHeader.svelte +24 -3
- package/package/components/runs/runsFilter.d.ts +1 -1
- package/package/components/schema/FlowPropertyEditor.svelte +30 -1
- package/package/components/schema/FlowPropertyEditor.svelte.d.ts +5 -2
- package/package/components/search/GlobalSearchModal.svelte +8 -1
- package/package/components/select/Select.svelte +1 -1
- package/package/components/settings/CreateToken.svelte +48 -77
- package/package/components/settings/EditTokenScopesModal.svelte +57 -0
- package/package/components/settings/EditTokenScopesModal.svelte.d.ts +10 -0
- package/package/components/settings/ScopesPicker.svelte +43 -0
- package/package/components/settings/ScopesPicker.svelte.d.ts +11 -0
- package/package/components/settings/TokensTable.svelte +51 -15
- package/package/components/sidebar/OperatorMenu.svelte +6 -0
- package/package/components/sidebar/SidebarContent.svelte +11 -1
- package/package/components/triggers/AddTriggersButton.svelte +6 -0
- package/package/components/triggers/CaptureWrapper.svelte +19 -1
- package/package/components/triggers/TriggerEditorToolbar.svelte.d.ts +1 -1
- package/package/components/triggers/TriggerModeToggle.svelte +36 -7
- package/package/components/triggers/TriggerModeToggle.svelte.d.ts +1 -1
- package/package/components/triggers/TriggerSuspendedJobsModal.svelte.d.ts +1 -1
- package/package/components/triggers/TriggersEditor.svelte +5 -1
- package/package/components/triggers/TriggersWrapper.svelte +10 -0
- package/package/components/triggers/azure/AzureCapture.svelte +41 -0
- package/package/components/triggers/azure/AzureCapture.svelte.d.ts +44 -0
- package/package/components/triggers/azure/AzureTriggerEditor.svelte +20 -0
- package/package/components/triggers/azure/AzureTriggerEditor.svelte.d.ts +9 -0
- package/package/components/triggers/azure/AzureTriggerEditorConfigSection.svelte +301 -0
- package/package/components/triggers/azure/AzureTriggerEditorConfigSection.svelte.d.ts +16 -0
- package/package/components/triggers/azure/AzureTriggerEditorInner.svelte +422 -0
- package/package/components/triggers/azure/AzureTriggerEditorInner.svelte.d.ts +25 -0
- package/package/components/triggers/azure/AzureTriggerPanel.svelte +55 -0
- package/package/components/triggers/azure/AzureTriggerPanel.svelte.d.ts +10 -0
- package/{dist/sharedUtils/components/triggers/kafka → package/components/triggers/azure}/utils.d.ts +1 -1
- package/package/components/triggers/azure/utils.js +56 -0
- package/package/components/triggers/email/EmailTriggerEditorInner.svelte +2 -0
- package/package/components/triggers/gcp/GcpTriggerEditorInner.svelte +9 -3
- package/package/components/triggers/http/RouteEditorInner.svelte +2 -0
- package/package/components/triggers/kafka/KafkaTriggerEditorInner.svelte +9 -3
- package/package/components/triggers/mqtt/MqttTriggerEditorInner.svelte +9 -3
- package/package/components/triggers/nats/NatsTriggerEditorInner.svelte +9 -3
- package/package/components/triggers/postgres/PostgresTriggerEditorInner.svelte +9 -3
- package/package/components/triggers/schedules/ScheduleEditorInner.svelte +9 -3
- package/package/components/triggers/sqs/SqsTriggerEditorInner.svelte +9 -3
- package/package/components/triggers/triggers.svelte.d.ts +1 -0
- package/package/components/triggers/triggers.svelte.js +23 -1
- package/package/components/triggers/utils.js +20 -0
- package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +9 -3
- package/package/components/triggers.d.ts +1 -1
- package/package/components/useNestedRestartState.svelte.d.ts +56 -0
- package/package/components/useNestedRestartState.svelte.js +320 -0
- package/package/components/workspaceSettings/SharedUiSettings.svelte +175 -0
- package/package/components/workspaceSettings/SharedUiSettings.svelte.d.ts +3 -0
- package/package/gen/core/OpenAPI.js +1 -1
- package/package/gen/schemas.gen.d.ts +294 -24
- package/package/gen/schemas.gen.js +297 -25
- package/package/gen/services.gen.d.ts +247 -4
- package/package/gen/services.gen.js +498 -7
- package/package/gen/types.gen.d.ts +990 -37
- package/package/hubPaths.json +2 -5
- package/package/infer.d.ts +1 -1
- package/package/infer.js +37 -51
- package/package/mcpEndpointTools.js +60 -4
- package/package/script_helpers.js +17 -0
- package/package/stores.d.ts +7 -0
- package/package/stores.js +6 -1
- package/package/system_prompts/index.d.ts +1 -0
- package/package/system_prompts/index.js +8 -0
- package/package/system_prompts/prompts.d.ts +16 -13
- package/package/system_prompts/prompts.js +653 -43
- package/package/templates/ci_test_bun.ts.template +8 -0
- package/package/templates/ci_test_python.py.template +8 -0
- package/package/utils/forkConflict.d.ts +26 -0
- package/package/utils/forkConflict.js +56 -0
- package/package/utils_deployable.d.ts +164 -121
- package/package/utils_deployable.js +61 -11
- package/package/utils_workspace_deploy.js +3 -1
- package/package.json +28 -4
- package/dist/sharedUtils/assets/tokens/colorTokensConfig.d.ts +0 -2
- package/dist/sharedUtils/base.d.ts +0 -1
- package/dist/sharedUtils/cloud.d.ts +0 -1
- package/dist/sharedUtils/common.d.ts +0 -111
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/count.d.ts +0 -5
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/delete.d.ts +0 -5
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/insert.d.ts +0 -5
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/select.d.ts +0 -13
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/update.d.ts +0 -11
- package/dist/sharedUtils/components/apps/components/display/dbtable/utils.d.ts +0 -95
- package/dist/sharedUtils/components/apps/editor/appPolicy.d.ts +0 -6
- package/dist/sharedUtils/components/apps/editor/appUtilsCore.d.ts +0 -7
- package/dist/sharedUtils/components/apps/editor/appUtilsS3.d.ts +0 -33
- package/dist/sharedUtils/components/apps/editor/commonAppUtils.d.ts +0 -10
- package/dist/sharedUtils/components/apps/editor/component/components.d.ts +0 -5371
- package/dist/sharedUtils/components/apps/editor/component/default-codes.d.ts +0 -3
- package/dist/sharedUtils/components/apps/editor/component/index.d.ts +0 -3
- package/dist/sharedUtils/components/apps/editor/component/sets.d.ts +0 -7
- package/dist/sharedUtils/components/apps/editor/componentsPanel/componentDefaultProps.d.ts +0 -3
- package/dist/sharedUtils/components/apps/gridUtils.d.ts +0 -14
- package/dist/sharedUtils/components/apps/inputType.d.ts +0 -178
- package/dist/sharedUtils/components/apps/rx.d.ts +0 -29
- package/dist/sharedUtils/components/apps/sharedTypes.d.ts +0 -21
- package/dist/sharedUtils/components/apps/types.d.ts +0 -274
- package/dist/sharedUtils/components/assets/lib.d.ts +0 -25
- package/dist/sharedUtils/components/common/alert/model.d.ts +0 -2
- package/dist/sharedUtils/components/common/badge/model.d.ts +0 -8
- package/dist/sharedUtils/components/common/button/model.d.ts +0 -45
- package/dist/sharedUtils/components/common/fileInput/model.d.ts +0 -1
- package/dist/sharedUtils/components/common/index.d.ts +0 -24
- package/dist/sharedUtils/components/common/skeleton/model.d.ts +0 -21
- package/dist/sharedUtils/components/dbTypes.d.ts +0 -14
- package/dist/sharedUtils/components/diff_drawer.d.ts +0 -26
- package/dist/sharedUtils/components/ducklake.d.ts +0 -1
- package/dist/sharedUtils/components/flows/scheduleUtils.d.ts +0 -7
- package/dist/sharedUtils/components/icons/index.d.ts +0 -101
- package/dist/sharedUtils/components/random_positive_adjetive.d.ts +0 -1
- package/dist/sharedUtils/components/raw_apps/rawAppPolicy.d.ts +0 -10
- package/dist/sharedUtils/components/raw_apps/utils.d.ts +0 -15
- package/dist/sharedUtils/components/triggers/email/utils.d.ts +0 -4
- package/dist/sharedUtils/components/triggers/gcp/utils.d.ts +0 -2
- package/dist/sharedUtils/components/triggers/http/utils.d.ts +0 -11
- package/dist/sharedUtils/components/triggers/mqtt/utils.d.ts +0 -2
- package/dist/sharedUtils/components/triggers/nats/utils.d.ts +0 -2
- package/dist/sharedUtils/components/triggers/postgres/utils.d.ts +0 -8
- package/dist/sharedUtils/components/triggers/sqs/utils.d.ts +0 -2
- package/dist/sharedUtils/components/triggers/triggers.svelte.d.ts +0 -32
- package/dist/sharedUtils/components/triggers/utils.d.ts +0 -80
- package/dist/sharedUtils/components/triggers/websocket/utils.d.ts +0 -2
- package/dist/sharedUtils/components/triggers.d.ts +0 -20
- package/dist/sharedUtils/gen/core/ApiError.d.ts +0 -10
- package/dist/sharedUtils/gen/core/ApiRequestOptions.d.ts +0 -13
- package/dist/sharedUtils/gen/core/ApiResult.d.ts +0 -7
- package/dist/sharedUtils/gen/core/CancelablePromise.d.ts +0 -26
- package/dist/sharedUtils/gen/core/OpenAPI.d.ts +0 -27
- package/dist/sharedUtils/gen/core/request.d.ts +0 -29
- package/dist/sharedUtils/gen/index.d.ts +0 -6
- package/dist/sharedUtils/gen/schemas.gen.d.ts +0 -7036
- package/dist/sharedUtils/gen/services.gen.d.ts +0 -6047
- package/dist/sharedUtils/gen/types.gen.d.ts +0 -21881
- package/dist/sharedUtils/history.svelte.d.ts +0 -9
- package/dist/sharedUtils/hub.d.ts +0 -49
- package/dist/sharedUtils/jsr.json +0 -6
- package/dist/sharedUtils/lib.d.ts +0 -5
- package/dist/sharedUtils/lib.es.js +0 -1588
- package/dist/sharedUtils/package.json +0 -12
- package/dist/sharedUtils/schema.d.ts +0 -3
- package/dist/sharedUtils/stores.d.ts +0 -97
- package/dist/sharedUtils/svelte5Utils.svelte.d.ts +0 -80
- package/dist/sharedUtils/toast.d.ts +0 -8
- package/dist/sharedUtils/utils.d.ts +0 -265
- package/package/components/copilot/chat/flow/openFlowZod.js +0 -24
- /package/package/components/copilot/chat/flow/{openFlowZod.d.ts → openFlowZod.gen.d.ts} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { getAppTools } from './core';
|
|
2
|
+
import { getAppTools, prepareAppUserMessage } from './core';
|
|
3
3
|
vi.mock('../shared', () => ({
|
|
4
4
|
createToolDef: (_schema, name, description) => ({
|
|
5
5
|
type: 'function',
|
|
@@ -52,9 +52,6 @@ vi.mock('../AIChatManager.svelte', () => ({
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
}));
|
|
55
|
-
vi.mock('$system_prompts', () => ({
|
|
56
|
-
getDatatableSdkReference: () => 'Datatable SDK reference'
|
|
57
|
-
}));
|
|
58
55
|
const EMPTY_LINT_RESULT = {
|
|
59
56
|
errorCount: 0,
|
|
60
57
|
warningCount: 0,
|
|
@@ -80,11 +77,12 @@ function createHelpers(overrides = {}) {
|
|
|
80
77
|
setBackendRunnable: async () => EMPTY_LINT_RESULT,
|
|
81
78
|
deleteBackendRunnable: () => undefined,
|
|
82
79
|
getFiles: () => ({ frontend: {}, backend: {} }),
|
|
83
|
-
getSelectedContext: () => ({
|
|
80
|
+
getSelectedContext: () => ({}),
|
|
84
81
|
snapshot: () => 1,
|
|
85
82
|
revertToSnapshot: () => undefined,
|
|
86
83
|
lint: () => EMPTY_LINT_RESULT,
|
|
87
|
-
|
|
84
|
+
listDatatableTables: async () => [],
|
|
85
|
+
getDatatableTableSchema: async () => ({}),
|
|
88
86
|
getAvailableDatatableNames: () => [],
|
|
89
87
|
execDatatableSql: async () => ({ success: true }),
|
|
90
88
|
addTableToWhitelist: () => undefined,
|
|
@@ -97,13 +95,139 @@ function createToolCallbacks() {
|
|
|
97
95
|
removeToolStatus: vi.fn()
|
|
98
96
|
};
|
|
99
97
|
}
|
|
100
|
-
function
|
|
101
|
-
const tool = getAppTools().find((entry) => entry.def.function.name ===
|
|
98
|
+
function getTool(name) {
|
|
99
|
+
const tool = getAppTools().find((entry) => entry.def.function.name === name);
|
|
102
100
|
if (!tool) {
|
|
103
|
-
throw new Error(
|
|
101
|
+
throw new Error(`${name} tool not found`);
|
|
104
102
|
}
|
|
105
103
|
return tool;
|
|
106
104
|
}
|
|
105
|
+
function getListFilesTool() {
|
|
106
|
+
return getTool('list_files');
|
|
107
|
+
}
|
|
108
|
+
function getPatchFileTool() {
|
|
109
|
+
return getTool('patch_file');
|
|
110
|
+
}
|
|
111
|
+
describe('app list_files tool', () => {
|
|
112
|
+
it('returns lightweight metadata without file or runnable contents', async () => {
|
|
113
|
+
const tool = getListFilesTool();
|
|
114
|
+
const result = await tool.fn({
|
|
115
|
+
args: {},
|
|
116
|
+
workspace: 'test-workspace',
|
|
117
|
+
helpers: createHelpers({
|
|
118
|
+
getFiles: () => ({
|
|
119
|
+
frontend: {
|
|
120
|
+
'/index.tsx': 'const secretFrontendContent = true',
|
|
121
|
+
'/styles.css': '.secret-class { color: red; }'
|
|
122
|
+
},
|
|
123
|
+
backend: {
|
|
124
|
+
loadUsers: {
|
|
125
|
+
name: 'Load users',
|
|
126
|
+
type: 'inline',
|
|
127
|
+
staticInputs: { admin: true },
|
|
128
|
+
inlineScript: {
|
|
129
|
+
language: 'bun',
|
|
130
|
+
content: 'export async function main() { return "secretBackendContent" }'
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
workspaceFlow: {
|
|
134
|
+
name: 'Workspace flow',
|
|
135
|
+
type: 'flow',
|
|
136
|
+
path: 'f/flows/workspace_flow'
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
}),
|
|
141
|
+
toolCallbacks: createToolCallbacks(),
|
|
142
|
+
toolId: 'tool-list-files'
|
|
143
|
+
});
|
|
144
|
+
const parsed = JSON.parse(result);
|
|
145
|
+
expect(parsed).toEqual({
|
|
146
|
+
frontend: [
|
|
147
|
+
{ path: '/index.tsx', size: 34, kind: 'tsx' },
|
|
148
|
+
{ path: '/styles.css', size: 29, kind: 'css' }
|
|
149
|
+
],
|
|
150
|
+
backend: [
|
|
151
|
+
{
|
|
152
|
+
key: 'loadUsers',
|
|
153
|
+
name: 'Load users',
|
|
154
|
+
type: 'inline',
|
|
155
|
+
language: 'bun',
|
|
156
|
+
contentSize: 62,
|
|
157
|
+
staticInputKeys: ['admin']
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
key: 'workspaceFlow',
|
|
161
|
+
name: 'Workspace flow',
|
|
162
|
+
type: 'flow',
|
|
163
|
+
path: 'f/flows/workspace_flow'
|
|
164
|
+
}
|
|
165
|
+
]
|
|
166
|
+
});
|
|
167
|
+
expect(result).not.toContain('secretFrontendContent');
|
|
168
|
+
expect(result).not.toContain('secretBackendContent');
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
describe('app datatable tools', () => {
|
|
172
|
+
it('lists datatable metadata without column definitions', async () => {
|
|
173
|
+
const tool = getTool('list_datatables');
|
|
174
|
+
const result = await tool.fn({
|
|
175
|
+
args: {},
|
|
176
|
+
workspace: 'test-workspace',
|
|
177
|
+
helpers: createHelpers({
|
|
178
|
+
listDatatableTables: async () => [
|
|
179
|
+
{
|
|
180
|
+
datatable_name: 'main',
|
|
181
|
+
schemas: {
|
|
182
|
+
public: ['users', 'orders'],
|
|
183
|
+
analytics: ['events']
|
|
184
|
+
},
|
|
185
|
+
tableCount: 3
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
}),
|
|
189
|
+
toolCallbacks: createToolCallbacks(),
|
|
190
|
+
toolId: 'tool-list-datatables'
|
|
191
|
+
});
|
|
192
|
+
const parsed = JSON.parse(result);
|
|
193
|
+
expect(parsed).toEqual([
|
|
194
|
+
{
|
|
195
|
+
datatable_name: 'main',
|
|
196
|
+
schemas: {
|
|
197
|
+
public: ['users', 'orders'],
|
|
198
|
+
analytics: ['events']
|
|
199
|
+
},
|
|
200
|
+
tableCount: 3
|
|
201
|
+
}
|
|
202
|
+
]);
|
|
203
|
+
expect(result).not.toContain('email');
|
|
204
|
+
expect(result).not.toContain('jsonb');
|
|
205
|
+
});
|
|
206
|
+
it('gets one datatable table schema', async () => {
|
|
207
|
+
const tool = getTool('get_datatable_table_schema');
|
|
208
|
+
const result = await tool.fn({
|
|
209
|
+
args: {
|
|
210
|
+
datatable_name: 'main',
|
|
211
|
+
schema_name: 'public',
|
|
212
|
+
table_name: 'users'
|
|
213
|
+
},
|
|
214
|
+
workspace: 'test-workspace',
|
|
215
|
+
helpers: createHelpers({
|
|
216
|
+
getDatatableTableSchema: async () => ({ id: 'int4', email: 'text' })
|
|
217
|
+
}),
|
|
218
|
+
toolCallbacks: createToolCallbacks(),
|
|
219
|
+
toolId: 'tool-get-table-schema'
|
|
220
|
+
});
|
|
221
|
+
const parsed = JSON.parse(result);
|
|
222
|
+
expect(parsed).toEqual({
|
|
223
|
+
datatable_name: 'main',
|
|
224
|
+
schema_name: 'public',
|
|
225
|
+
table_name: 'users',
|
|
226
|
+
columns: { id: 'int4', email: 'text' }
|
|
227
|
+
});
|
|
228
|
+
expect(result).not.toContain('total');
|
|
229
|
+
});
|
|
230
|
+
});
|
|
107
231
|
describe('app patch_file tool', () => {
|
|
108
232
|
it('patches frontend files with an exact replacement', async () => {
|
|
109
233
|
const setFrontendFile = vi.fn(() => EMPTY_LINT_RESULT);
|
|
@@ -141,6 +265,26 @@ describe('app patch_file tool', () => {
|
|
|
141
265
|
toolId: 'tool-2'
|
|
142
266
|
})).rejects.toThrow('old_string matched 2 locations');
|
|
143
267
|
});
|
|
268
|
+
it('treats leading /backend paths as frontend files', async () => {
|
|
269
|
+
const setFrontendFile = vi.fn(() => EMPTY_LINT_RESULT);
|
|
270
|
+
const tool = getPatchFileTool();
|
|
271
|
+
const result = await tool.fn({
|
|
272
|
+
args: {
|
|
273
|
+
path: '/backend/deleteRecipe/main.ts',
|
|
274
|
+
old_string: 'frontend route',
|
|
275
|
+
new_string: 'frontend page'
|
|
276
|
+
},
|
|
277
|
+
workspace: 'test-workspace',
|
|
278
|
+
helpers: createHelpers({
|
|
279
|
+
getFrontendFile: () => 'export const title = "frontend route"\n',
|
|
280
|
+
setFrontendFile
|
|
281
|
+
}),
|
|
282
|
+
toolCallbacks: createToolCallbacks(),
|
|
283
|
+
toolId: 'tool-leading-backend-path'
|
|
284
|
+
});
|
|
285
|
+
expect(setFrontendFile).toHaveBeenCalledWith('/backend/deleteRecipe/main.ts', 'export const title = "frontend page"\n');
|
|
286
|
+
expect(result).toContain("Patched '/backend/deleteRecipe/main.ts' successfully.");
|
|
287
|
+
});
|
|
144
288
|
it('patches inline backend runnables through backend/<key>/main.ts paths', async () => {
|
|
145
289
|
const runnable = {
|
|
146
290
|
name: 'Delete recipe',
|
|
@@ -190,3 +334,84 @@ describe('app patch_file tool', () => {
|
|
|
190
334
|
})).rejects.toThrow('generated automatically');
|
|
191
335
|
});
|
|
192
336
|
});
|
|
337
|
+
describe('prepareAppUserMessage app context', () => {
|
|
338
|
+
it('still serializes inspector and code selections', () => {
|
|
339
|
+
const selectedContext = {
|
|
340
|
+
type: 'frontend',
|
|
341
|
+
frontendPath: '/index.tsx',
|
|
342
|
+
inspectorElement: {
|
|
343
|
+
path: 'body > button.primary',
|
|
344
|
+
tagName: 'button',
|
|
345
|
+
id: 'save',
|
|
346
|
+
className: 'primary action',
|
|
347
|
+
rect: { top: 10, left: 20, width: 120, height: 40 },
|
|
348
|
+
html: '<button id="save" class="primary action">Save</button>',
|
|
349
|
+
textContent: 'Save',
|
|
350
|
+
styles: {}
|
|
351
|
+
},
|
|
352
|
+
codeSelection: {
|
|
353
|
+
type: 'app_code_selection',
|
|
354
|
+
source: '/index.tsx',
|
|
355
|
+
sourceType: 'frontend',
|
|
356
|
+
title: '/index.tsx:3-4',
|
|
357
|
+
content: 'const selectedCode = true',
|
|
358
|
+
startLine: 3,
|
|
359
|
+
endLine: 4,
|
|
360
|
+
startColumn: 1,
|
|
361
|
+
endColumn: 25
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
const message = prepareAppUserMessage('Change this selected area', selectedContext);
|
|
365
|
+
const content = message.content;
|
|
366
|
+
expect(content).toContain('The user has selected an element in the app preview');
|
|
367
|
+
expect(content).toContain('body > button.primary');
|
|
368
|
+
expect(content).toContain('### CODE SELECTION:');
|
|
369
|
+
expect(content).toContain('const selectedCode = true');
|
|
370
|
+
});
|
|
371
|
+
it('serializes explicit mentions with lightweight file context', () => {
|
|
372
|
+
const additionalContext = [
|
|
373
|
+
{
|
|
374
|
+
type: 'app_frontend_file',
|
|
375
|
+
path: '/index.tsx',
|
|
376
|
+
title: '/index.tsx',
|
|
377
|
+
content: 'const fullFrontendContent = true'
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
type: 'app_backend_runnable',
|
|
381
|
+
key: 'loadUsers',
|
|
382
|
+
title: 'loadUsers',
|
|
383
|
+
runnable: {
|
|
384
|
+
name: 'Load users',
|
|
385
|
+
type: 'inline',
|
|
386
|
+
staticInputs: { admin: true },
|
|
387
|
+
inlineScript: {
|
|
388
|
+
language: 'bun',
|
|
389
|
+
content: 'export async function main() { return "secret" }'
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
type: 'app_datatable',
|
|
395
|
+
datatableName: 'main',
|
|
396
|
+
schemaName: 'public',
|
|
397
|
+
tableName: 'users',
|
|
398
|
+
title: 'main/users',
|
|
399
|
+
columns: {
|
|
400
|
+
id: 'int4',
|
|
401
|
+
email: 'text'
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
];
|
|
405
|
+
const message = prepareAppUserMessage('Wire these together', undefined, additionalContext);
|
|
406
|
+
const content = message.content;
|
|
407
|
+
expect(content).toContain('- Frontend file: /index.tsx');
|
|
408
|
+
expect(content).toContain('- Backend runnable: loadUsers');
|
|
409
|
+
expect(content).not.toContain('fullFrontendContent');
|
|
410
|
+
expect(content).not.toContain('export async function main');
|
|
411
|
+
expect(content).not.toContain('Static inputs');
|
|
412
|
+
expect(content).not.toContain('Load users');
|
|
413
|
+
expect(content).toContain('**Table: main/users**');
|
|
414
|
+
expect(content).toContain('"id": "int4"');
|
|
415
|
+
expect(content).toContain('"email": "text"');
|
|
416
|
+
});
|
|
417
|
+
});
|
|
@@ -16,3 +16,47 @@ export const ContextIconMap = {
|
|
|
16
16
|
workspace_flow: BarsStaggered
|
|
17
17
|
// flow_module type is handled with FlowModuleIcon
|
|
18
18
|
};
|
|
19
|
+
export function createAppSelectedContext(options = {}) {
|
|
20
|
+
return {
|
|
21
|
+
...options
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function createAppFrontendFileContextElement(path, content) {
|
|
25
|
+
return {
|
|
26
|
+
type: 'app_frontend_file',
|
|
27
|
+
path,
|
|
28
|
+
title: path,
|
|
29
|
+
content
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function createAppBackendRunnableContextElement(key, runnable) {
|
|
33
|
+
return {
|
|
34
|
+
type: 'app_backend_runnable',
|
|
35
|
+
key,
|
|
36
|
+
title: key,
|
|
37
|
+
runnable
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export function formatAppDatatableContextTitle(datatableName, schemaName, tableName) {
|
|
41
|
+
return schemaName === 'public'
|
|
42
|
+
? `${datatableName}/${tableName}`
|
|
43
|
+
: `${datatableName}/${schemaName}:${tableName}`;
|
|
44
|
+
}
|
|
45
|
+
export function createAppDatatableContextElement(datatableName, schemaName, tableName, columns) {
|
|
46
|
+
return {
|
|
47
|
+
type: 'app_datatable',
|
|
48
|
+
datatableName,
|
|
49
|
+
schemaName,
|
|
50
|
+
tableName,
|
|
51
|
+
title: formatAppDatatableContextTitle(datatableName, schemaName, tableName),
|
|
52
|
+
columns
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export function flattenDatatablesToAppContextElements(datatables) {
|
|
56
|
+
return datatables.flatMap((datatable) => {
|
|
57
|
+
if (datatable.error) {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
return Object.entries(datatable.schemas).flatMap(([schemaName, tables]) => tables.map((tableName) => createAppDatatableContextElement(datatable.datatable_name, schemaName, tableName)));
|
|
61
|
+
});
|
|
62
|
+
}
|
|
@@ -142,12 +142,13 @@ const flowHelpers = {
|
|
|
142
142
|
}
|
|
143
143
|
return { errorCount: 0, warningCount: 0, errors: [], warnings: [] };
|
|
144
144
|
},
|
|
145
|
-
setFlowJson: async ({ modules, schema, preprocessorModule, failureModule }) => {
|
|
145
|
+
setFlowJson: async ({ modules, schema, preprocessorModule, failureModule, groups }) => {
|
|
146
146
|
try {
|
|
147
147
|
if (modules !== undefined ||
|
|
148
148
|
schema !== undefined ||
|
|
149
149
|
preprocessorModule !== undefined ||
|
|
150
|
-
failureModule !== undefined
|
|
150
|
+
failureModule !== undefined ||
|
|
151
|
+
groups !== undefined) {
|
|
151
152
|
// Take snapshot of current flowStore and set as beforeFlow
|
|
152
153
|
if (!diffManager?.hasPendingChanges) {
|
|
153
154
|
const snapshot = $state.snapshot(flowStore).val;
|
|
@@ -159,7 +160,8 @@ const flowHelpers = {
|
|
|
159
160
|
modules,
|
|
160
161
|
schema,
|
|
161
162
|
preprocessorModule,
|
|
162
|
-
failureModule
|
|
163
|
+
failureModule,
|
|
164
|
+
groups
|
|
163
165
|
});
|
|
164
166
|
// Refresh the state store to update UI
|
|
165
167
|
refreshStateStore(flowStore);
|
|
@@ -4,12 +4,13 @@ import { type Tool, type ScriptLintResult } from '../shared';
|
|
|
4
4
|
import type { ContextElement } from '../context';
|
|
5
5
|
import type { ExtendedOpenFlow } from '../../../flows/types';
|
|
6
6
|
import { type InlineScriptSession } from './inlineScriptsUtils';
|
|
7
|
-
import type
|
|
7
|
+
import { type FlowGroup, type FlowJsonUpdateResult } from './helperUtils';
|
|
8
8
|
type FlowJsonUpdate = {
|
|
9
9
|
modules?: FlowModule[];
|
|
10
10
|
schema?: Record<string, any> | null;
|
|
11
11
|
preprocessorModule?: FlowModule | null;
|
|
12
12
|
failureModule?: FlowModule | null;
|
|
13
|
+
groups?: FlowGroup[] | null;
|
|
13
14
|
};
|
|
14
15
|
/**
|
|
15
16
|
* Helper interface for AI chat flow operations
|
|
@@ -2,9 +2,11 @@ import { ScriptService, JobService } from '../../../../gen';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { createDbSchemaTool, getFormattedResourceTypes, getLangContext, SUPPORTED_CHAT_SCRIPT_LANGUAGES } from '../script/core';
|
|
4
4
|
import { createSearchHubScriptsTool, createToolDef, executeTestRun, buildSchemaForTool, buildTestRunArgs, buildContextString, applyCodePiecesToFlowModules, SPECIAL_MODULE_IDS, formatScriptLintResult, createSearchWorkspaceTool, createGetRunnableDetailsTool } from '../shared';
|
|
5
|
+
import { createWorkspaceMutationTools } from '../workspaceTools';
|
|
5
6
|
import { findModuleInFlow, findModuleInModules } from '../../../flows/flowTree';
|
|
6
7
|
import { createInlineScriptSession } from './inlineScriptsUtils';
|
|
7
|
-
import {
|
|
8
|
+
import { validateFlowGroups } from './helperUtils';
|
|
9
|
+
import { flowModuleSchema, flowModulesSchema } from './openFlowZod.gen';
|
|
8
10
|
import { collectAllFlowModuleIdsFromModules } from '../../../flows/flowTree';
|
|
9
11
|
import { FLOW_CHAT_SPECIAL_MODULES, getFlowPrompt } from '../../../../system_prompts';
|
|
10
12
|
/**
|
|
@@ -280,11 +282,14 @@ function validateEditableFlowJson(rawFlow) {
|
|
|
280
282
|
const schema = validateFlowSchema(flow.schema);
|
|
281
283
|
const preprocessorModule = validateOptionalFlowModule(flow.preprocessor_module, 'preprocessor_module');
|
|
282
284
|
const failureModule = validateOptionalFlowModule(flow.failure_module, 'failure_module');
|
|
285
|
+
const groupModuleIds = new Set(collectAllFlowModuleIdsFromModules(modules));
|
|
286
|
+
const groups = validateFlowGroups(flow.groups, groupModuleIds);
|
|
283
287
|
if (preprocessorModule) {
|
|
284
288
|
if (preprocessorModule.id !== SPECIAL_MODULE_IDS.PREPROCESSOR) {
|
|
285
289
|
throw new Error(`Invalid preprocessor_module: id must be "${SPECIAL_MODULE_IDS.PREPROCESSOR}"`);
|
|
286
290
|
}
|
|
287
|
-
if (preprocessorModule.value.type !== 'rawscript' &&
|
|
291
|
+
if (preprocessorModule.value.type !== 'rawscript' &&
|
|
292
|
+
preprocessorModule.value.type !== 'script') {
|
|
288
293
|
throw new Error('Invalid preprocessor_module: only "rawscript" and "script" modules are supported');
|
|
289
294
|
}
|
|
290
295
|
}
|
|
@@ -310,7 +315,8 @@ function validateEditableFlowJson(rawFlow) {
|
|
|
310
315
|
modules,
|
|
311
316
|
schema,
|
|
312
317
|
preprocessor_module: preprocessorModule,
|
|
313
|
-
failure_module: failureModule
|
|
318
|
+
failure_module: failureModule,
|
|
319
|
+
groups
|
|
314
320
|
};
|
|
315
321
|
}
|
|
316
322
|
function buildEditableFlowJson(flow, inlineScriptSession, selectedContext = []) {
|
|
@@ -333,7 +339,9 @@ function buildEditableFlowJson(flow, inlineScriptSession, selectedContext = [])
|
|
|
333
339
|
};
|
|
334
340
|
}
|
|
335
341
|
let failureModule = flow.value.failure_module;
|
|
336
|
-
if (failureModule?.value?.type === 'rawscript' &&
|
|
342
|
+
if (failureModule?.value?.type === 'rawscript' &&
|
|
343
|
+
failureModule.value.content &&
|
|
344
|
+
inlineScriptSession) {
|
|
337
345
|
inlineScriptSession.set(failureModule.id, failureModule.value.content);
|
|
338
346
|
failureModule = {
|
|
339
347
|
...failureModule,
|
|
@@ -347,7 +355,8 @@ function buildEditableFlowJson(flow, inlineScriptSession, selectedContext = [])
|
|
|
347
355
|
modules,
|
|
348
356
|
schema: flow.schema ?? null,
|
|
349
357
|
preprocessor_module: preprocessorModule ?? null,
|
|
350
|
-
failure_module: failureModule ?? null
|
|
358
|
+
failure_module: failureModule ?? null,
|
|
359
|
+
groups: flow.value.groups ?? null
|
|
351
360
|
};
|
|
352
361
|
}
|
|
353
362
|
const langSchema = z.enum(SUPPORTED_CHAT_SCRIPT_LANGUAGES);
|
|
@@ -377,9 +386,14 @@ const setFlowJsonToolSchema = z.object({
|
|
|
377
386
|
.string()
|
|
378
387
|
.optional()
|
|
379
388
|
.nullable()
|
|
380
|
-
.describe('JSON string containing the optional failure module')
|
|
389
|
+
.describe('JSON string containing the optional failure module'),
|
|
390
|
+
groups: z
|
|
391
|
+
.string()
|
|
392
|
+
.optional()
|
|
393
|
+
.nullable()
|
|
394
|
+
.describe('JSON string containing the optional array of semantic flow groups (summary, note, autocollapse, start_id, end_id, color). Pass null to clear groups.')
|
|
381
395
|
});
|
|
382
|
-
const setFlowJsonToolDef = createToolDef(setFlowJsonToolSchema, 'set_flow_json', 'Set the complete flow modules array and optionally the flow input schema, preprocessor module, and
|
|
396
|
+
const setFlowJsonToolDef = createToolDef(setFlowJsonToolSchema, 'set_flow_json', 'Set the complete flow modules array and optionally the flow input schema, preprocessor module, failure module, and semantic groups.', { strict: false });
|
|
383
397
|
const setPreprocessorModuleToolSchema = z.object({
|
|
384
398
|
module: specialModuleToolArgSchema
|
|
385
399
|
});
|
|
@@ -427,10 +441,7 @@ function validateSpecialFlowModule(module, field) {
|
|
|
427
441
|
return parsedModule;
|
|
428
442
|
}
|
|
429
443
|
const patchFlowJsonSchema = z.object({
|
|
430
|
-
old_string: z
|
|
431
|
-
.string()
|
|
432
|
-
.min(1)
|
|
433
|
-
.describe('Exact text to find in the current compact flow JSON'),
|
|
444
|
+
old_string: z.string().min(1).describe('Exact text to find in the current compact flow JSON'),
|
|
434
445
|
new_string: z.string().describe('Replacement JSON text'),
|
|
435
446
|
replace_all: z
|
|
436
447
|
.boolean()
|
|
@@ -475,6 +486,7 @@ export const flowTools = [
|
|
|
475
486
|
createDbSchemaTool(),
|
|
476
487
|
createSearchWorkspaceTool(),
|
|
477
488
|
createGetRunnableDetailsTool(),
|
|
489
|
+
...createWorkspaceMutationTools(),
|
|
478
490
|
{
|
|
479
491
|
def: resourceTypeToolDef,
|
|
480
492
|
fn: async ({ args, toolId, workspace, toolCallbacks }) => {
|
|
@@ -726,7 +738,8 @@ export const flowTools = [
|
|
|
726
738
|
modules: parsedFlow.modules,
|
|
727
739
|
schema: parsedFlow.schema,
|
|
728
740
|
preprocessorModule: parsedFlow.preprocessor_module,
|
|
729
|
-
failureModule: parsedFlow.failure_module
|
|
741
|
+
failureModule: parsedFlow.failure_module,
|
|
742
|
+
groups: parsedFlow.groups
|
|
730
743
|
});
|
|
731
744
|
const warning = formatEmptyInlineScriptWarning(updateResult);
|
|
732
745
|
const selectedModule = findModuleInFlow(parsedFlow, selectedId) ?? undefined;
|
|
@@ -751,7 +764,9 @@ export const flowTools = [
|
|
|
751
764
|
const parsedArgs = setPreprocessorModuleToolSchema.parse(args);
|
|
752
765
|
const parsedModule = validateSpecialFlowModule(parseOptionalJsonArg(parsedArgs.module, 'module'), 'preprocessor_module');
|
|
753
766
|
toolCallbacks.setToolStatus(toolId, {
|
|
754
|
-
content: parsedModule === null
|
|
767
|
+
content: parsedModule === null
|
|
768
|
+
? 'Removing preprocessor module...'
|
|
769
|
+
: 'Setting preprocessor module...'
|
|
755
770
|
});
|
|
756
771
|
const updateResult = await helpers.setFlowJson({ preprocessorModule: parsedModule });
|
|
757
772
|
const warning = formatEmptyInlineScriptWarning(updateResult);
|
|
@@ -804,16 +819,18 @@ export const flowTools = [
|
|
|
804
819
|
showDetails: true,
|
|
805
820
|
showFade: true,
|
|
806
821
|
fn: async ({ args, helpers, toolId, toolCallbacks }) => {
|
|
807
|
-
const { modules, schema, preprocessor_module, failure_module } = args;
|
|
822
|
+
const { modules, schema, preprocessor_module, failure_module, groups } = args;
|
|
808
823
|
let parsedModules;
|
|
809
824
|
let parsedSchema;
|
|
810
825
|
let parsedPreprocessorModule;
|
|
811
826
|
let parsedFailureModule;
|
|
827
|
+
let parsedGroups;
|
|
812
828
|
// Parse JSON strings
|
|
813
829
|
parsedModules = parseOptionalJsonArg(modules, 'modules');
|
|
814
830
|
parsedSchema = parseOptionalJsonArg(schema, 'schema');
|
|
815
831
|
parsedPreprocessorModule = parseOptionalJsonArg(preprocessor_module, 'preprocessor_module');
|
|
816
832
|
parsedFailureModule = parseOptionalJsonArg(failure_module, 'failure_module');
|
|
833
|
+
parsedGroups = parseOptionalJsonArg(groups, 'groups');
|
|
817
834
|
if (parsedModules === null) {
|
|
818
835
|
parsedModules = undefined;
|
|
819
836
|
}
|
|
@@ -832,10 +849,16 @@ export const flowTools = [
|
|
|
832
849
|
}
|
|
833
850
|
parsedPreprocessorModule = validateSpecialFlowModule(parsedPreprocessorModule, 'preprocessor_module');
|
|
834
851
|
parsedFailureModule = validateSpecialFlowModule(parsedFailureModule, 'failure_module');
|
|
852
|
+
if (parsedGroups !== undefined) {
|
|
853
|
+
const effectiveModules = parsedModules ?? helpers.getFlowAndSelectedId().flow.value.modules ?? [];
|
|
854
|
+
const moduleIdsForGroups = new Set(collectAllFlowModuleIdsFromModules(effectiveModules));
|
|
855
|
+
parsedGroups = validateFlowGroups(parsedGroups, moduleIdsForGroups);
|
|
856
|
+
}
|
|
835
857
|
const ids = [
|
|
836
858
|
...(parsedModules ? collectAllFlowModuleIdsFromModules(parsedModules) : []),
|
|
837
|
-
...
|
|
838
|
-
.
|
|
859
|
+
...[parsedPreprocessorModule, parsedFailureModule]
|
|
860
|
+
.filter((module) => module !== undefined && module !== null)
|
|
861
|
+
.map((module) => module.id)
|
|
839
862
|
];
|
|
840
863
|
if (ids.length !== new Set(ids).size) {
|
|
841
864
|
throw new Error('Duplicate module IDs found in flow');
|
|
@@ -849,7 +872,8 @@ export const flowTools = [
|
|
|
849
872
|
...(parsedPreprocessorModule !== undefined
|
|
850
873
|
? { preprocessorModule: parsedPreprocessorModule }
|
|
851
874
|
: {}),
|
|
852
|
-
...(parsedFailureModule !== undefined ? { failureModule: parsedFailureModule } : {})
|
|
875
|
+
...(parsedFailureModule !== undefined ? { failureModule: parsedFailureModule } : {}),
|
|
876
|
+
...(parsedGroups !== undefined ? { groups: parsedGroups } : {})
|
|
853
877
|
});
|
|
854
878
|
const warning = formatEmptyInlineScriptWarning(updateResult);
|
|
855
879
|
// Update exprsToSet if the selected module has input_transforms
|
|
@@ -858,9 +882,9 @@ export const flowTools = [
|
|
|
858
882
|
parsedFailureModule !== undefined) {
|
|
859
883
|
const { selectedId } = helpers.getFlowAndSelectedId();
|
|
860
884
|
const selectedModule = selectedId === SPECIAL_MODULE_IDS.PREPROCESSOR
|
|
861
|
-
? parsedPreprocessorModule ?? undefined
|
|
885
|
+
? (parsedPreprocessorModule ?? undefined)
|
|
862
886
|
: selectedId === SPECIAL_MODULE_IDS.FAILURE
|
|
863
|
-
? parsedFailureModule ?? undefined
|
|
887
|
+
? (parsedFailureModule ?? undefined)
|
|
864
888
|
: parsedModules
|
|
865
889
|
? findModuleInModules(parsedModules, selectedId)
|
|
866
890
|
: undefined;
|
|
@@ -928,13 +952,15 @@ export function prepareFlowSystemMessage(customPrompt) {
|
|
|
928
952
|
**Resources & Schema:**
|
|
929
953
|
- **Search resource types** → \`resource_type\`
|
|
930
954
|
- **Get database schema** → \`get_db_schema\`
|
|
955
|
+
- **Create a schedule for the current flow** → \`create_schedule\`
|
|
956
|
+
- **Create a trigger for the current flow** → \`create_trigger\`
|
|
931
957
|
|
|
932
958
|
## Quick Edits with patch_flow_json
|
|
933
959
|
|
|
934
960
|
Use \`patch_flow_json\` for small, localized changes when you can target an exact snippet from the \`CURRENT FLOW JSON COMPACT\` block below.
|
|
935
961
|
|
|
936
962
|
Always copy the exact search text from the \`CURRENT FLOW JSON COMPACT\` block below.
|
|
937
|
-
The compact JSON is a single object with \`modules\`, \`schema\`, \`preprocessor_module\`, and \`
|
|
963
|
+
The compact JSON is a single object with \`modules\`, \`schema\`, \`preprocessor_module\`, \`failure_module\`, and \`groups\` keys.
|
|
938
964
|
|
|
939
965
|
**Parameters:**
|
|
940
966
|
- \`old_string\`: Exact JSON text to find
|
|
@@ -955,13 +981,14 @@ ${FLOW_CHAT_SPECIAL_MODULES}
|
|
|
955
981
|
|
|
956
982
|
## Flow Modification with set_flow_json
|
|
957
983
|
|
|
958
|
-
Use the \`set_flow_json\` tool to set the entire flow structure at once. Provide the complete modules array and optionally the flow input schema, \`preprocessor_module\`, and \`
|
|
984
|
+
Use the \`set_flow_json\` tool to set the entire flow structure at once. Provide the complete modules array and optionally the flow input schema, \`preprocessor_module\`, \`failure_module\`, and \`groups\`.
|
|
959
985
|
|
|
960
986
|
**Parameters:**
|
|
961
987
|
- \`modules\`: Array of flow modules (required)
|
|
962
988
|
- \`schema\`: Flow input schema in JSON Schema format (optional)
|
|
963
989
|
- \`preprocessor_module\`: Special module that runs before \`modules\` (optional, separate from \`modules\`)
|
|
964
990
|
- \`failure_module\`: Special module that runs on failure (optional, separate from \`modules\`)
|
|
991
|
+
- \`groups\`: Array of semantic groups for organizing modules in the editor (optional). Each group has \`summary\` (display name), \`note\` (markdown description shown below the group header — attached directly to the group, not a separate sticky note), \`autocollapse\`, \`start_id\`, \`end_id\`, and \`color\`. \`start_id\` and \`end_id\` must reference existing module IDs in the flow (not \`preprocessor\` or \`failure\`). Groups do not affect execution — they provide naming and collapsibility in the editor. Pass \`null\` to clear existing groups.
|
|
965
992
|
|
|
966
993
|
**Example - Simple flow:**
|
|
967
994
|
\`\`\`javascript
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import type { FlowModule, OpenFlow, RawScript } from '../../../../gen';
|
|
1
|
+
import type { FlowModule, FlowValue, OpenFlow, RawScript } from '../../../../gen';
|
|
2
2
|
import type { InlineScriptSession } from './inlineScriptsUtils';
|
|
3
3
|
type FlowLike = Pick<OpenFlow, 'value'> & {
|
|
4
4
|
schema?: Record<string, any>;
|
|
5
5
|
};
|
|
6
|
+
export type FlowGroup = NonNullable<FlowValue['groups']>[number];
|
|
6
7
|
export interface FlowJsonUpdate {
|
|
7
8
|
modules?: FlowModule[];
|
|
8
9
|
schema?: Record<string, any> | null;
|
|
9
10
|
preprocessorModule?: FlowModule | null;
|
|
10
11
|
failureModule?: FlowModule | null;
|
|
12
|
+
groups?: FlowGroup[] | null;
|
|
11
13
|
}
|
|
12
14
|
export interface FlowJsonUpdateResult {
|
|
13
15
|
emptyInlineScriptModuleIds: string[];
|
|
@@ -15,5 +17,6 @@ export interface FlowJsonUpdateResult {
|
|
|
15
17
|
export declare function updateRawScriptModuleContent(flow: FlowLike, id: string, code: string): (FlowModule & {
|
|
16
18
|
value: RawScript;
|
|
17
19
|
}) | undefined;
|
|
18
|
-
export declare function
|
|
20
|
+
export declare function validateFlowGroups(rawGroups: unknown, moduleIds?: Set<string>): FlowGroup[] | null;
|
|
21
|
+
export declare function applyFlowJsonUpdate(flow: FlowLike, inlineScriptSession: InlineScriptSession, { modules, schema, preprocessorModule, failureModule, groups }: FlowJsonUpdate): FlowJsonUpdateResult;
|
|
19
22
|
export {};
|
|
@@ -9,7 +9,36 @@ export function updateRawScriptModuleContent(flow, id, code) {
|
|
|
9
9
|
rawScriptModule.value.content = code;
|
|
10
10
|
return rawScriptModule;
|
|
11
11
|
}
|
|
12
|
-
export function
|
|
12
|
+
export function validateFlowGroups(rawGroups, moduleIds) {
|
|
13
|
+
if (rawGroups == null) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
if (!Array.isArray(rawGroups)) {
|
|
17
|
+
throw new Error('Flow groups must be an array');
|
|
18
|
+
}
|
|
19
|
+
return rawGroups.map((group, index) => {
|
|
20
|
+
if (!group || typeof group !== 'object' || Array.isArray(group)) {
|
|
21
|
+
throw new Error(`Invalid group at index ${index}: must be an object`);
|
|
22
|
+
}
|
|
23
|
+
const g = group;
|
|
24
|
+
if (typeof g.start_id !== 'string' || !g.start_id) {
|
|
25
|
+
throw new Error(`Invalid group at index ${index}: start_id must be a non-empty string`);
|
|
26
|
+
}
|
|
27
|
+
if (typeof g.end_id !== 'string' || !g.end_id) {
|
|
28
|
+
throw new Error(`Invalid group at index ${index}: end_id must be a non-empty string`);
|
|
29
|
+
}
|
|
30
|
+
if (moduleIds) {
|
|
31
|
+
if (!moduleIds.has(g.start_id)) {
|
|
32
|
+
throw new Error(`Invalid group at index ${index}: start_id "${g.start_id}" does not match any flow module`);
|
|
33
|
+
}
|
|
34
|
+
if (!moduleIds.has(g.end_id)) {
|
|
35
|
+
throw new Error(`Invalid group at index ${index}: end_id "${g.end_id}" does not match any flow module`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return g;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
export function applyFlowJsonUpdate(flow, inlineScriptSession, { modules, schema, preprocessorModule, failureModule, groups }) {
|
|
13
42
|
const emptyInlineScriptModuleIds = new Set();
|
|
14
43
|
if (modules !== undefined) {
|
|
15
44
|
flow.value.modules = restoreFlowModules(modules, inlineScriptSession, emptyInlineScriptModuleIds);
|
|
@@ -29,6 +58,9 @@ export function applyFlowJsonUpdate(flow, inlineScriptSession, { modules, schema
|
|
|
29
58
|
? undefined
|
|
30
59
|
: restoreFlowModule(failureModule, inlineScriptSession, emptyInlineScriptModuleIds);
|
|
31
60
|
}
|
|
61
|
+
if (groups !== undefined) {
|
|
62
|
+
flow.value.groups = groups == null || groups.length === 0 ? undefined : groups;
|
|
63
|
+
}
|
|
32
64
|
return {
|
|
33
65
|
emptyInlineScriptModuleIds: Array.from(emptyInlineScriptModuleIds)
|
|
34
66
|
};
|