Compare commits

..

175 Commits

Author SHA1 Message Date
Alexander Petric
af4e9e6a22 fix: batch job runner empty job kind 2025-10-07 23:06:26 +00:00
Ruben Fiszel
50a6106436 fix: fix runnable inputs not being retriggered on change in some rare cases 2025-10-07 15:15:49 +00:00
Diego Imbert
6806f2193d Fix Ctrl C in app right panel Copying component (#6766) 2025-10-07 12:35:54 +00:00
Diego Imbert
7d5196170c Remove click-to-insert prop feature (#6765)
* Remove click-to-insert prop feature

* CI
2025-10-07 12:03:30 +00:00
centdix
7b9e2c2d68 internal: fix flake and cli dev usage (#6761)
* fix flake

* fix cli build

* fix deno_ffi
2025-10-07 08:07:47 +00:00
Diego Imbert
258b275f9b fix: better ducklake setup (#6763)
* stash

* Much better ducklake setup UX

* nits

* mistake

* sqlx prepare
2025-10-07 07:00:00 +00:00
Ruben Fiszel
f2070e9d9c chore(main): release 1.555.2 (#6758)
* chore(main): release 1.555.2

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-10-06 15:20:47 +00:00
centdix
820437c897 chore(flow): clean flow conversation code (#6755)
* use own folder for memory

* fixes

* better chat interface

* fix export tab

* move in folder

* dont show flow graph if chat mode

* fix

* fix too long title

* fix user message

* fix

* fix

* remove from server

* cleaner

* cleaning

* cleaning

* cleaning
2025-10-06 15:10:29 +00:00
Diego Imbert
686cf8dd69 Timestamp input in db manager (#6754)
* nullable by default

* unrelated nits

* native timezone input postgres

* Fix timestamptz NaiveDateTime conversion is pg_executor

* remove consolelog
2025-10-06 15:10:17 +00:00
Ruben Fiszel
ac27cdc16e update monaco (#6759) 2025-10-06 13:56:02 +00:00
Diego Imbert
9f7250c9f0 Nit mistake in expression helper text (#6756)
* nit helper mistake

* nit border color

* fill inputs styling nits

* nit bg color
2025-10-06 13:36:48 +00:00
hugocasa
7c757b68f6 fix(backend): use correct ai tool job dir (#6757) 2025-10-06 13:35:59 +00:00
Ruben Fiszel
a12d124871 chore(main): release 1.555.1 (#6752)
* chore(main): release 1.555.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-10-04 17:11:37 +00:00
Ruben Fiszel
abb813c019 nit publish 2025-10-04 17:00:28 +00:00
Ruben Fiszel
75ceba81d9 nits disableAi 2025-10-04 16:54:59 +00:00
Ruben Fiszel
4e171d0aa6 flow inputs nits 2025-10-04 15:31:14 +00:00
Ruben Fiszel
46c49072de improve insert module button menu caching 2025-10-04 15:21:20 +00:00
Ruben Fiszel
9ddde9aa94 split store and aiStore 2025-10-04 09:59:10 +00:00
Ruben Fiszel
1df18a912c use smaller ui builder 2025-10-04 00:04:32 +00:00
Alexander Petric
d9c01e0c03 fix: init git repo preview save (#6753) 2025-10-03 21:48:11 +00:00
Alexander Petric
605c5526f8 fix: app button tooltip also when disabled + audit log filters (#6751)
* also show tooltip on disabled button

* fix: audit log filters
2025-10-03 20:12:05 +00:00
Ruben Fiszel
116c420326 chore(main): release 1.555.0 (#6744)
* chore(main): release 1.555.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-10-03 17:34:09 +00:00
Ruben Fiszel
0bc822dd10 warn for slow queries in push scheduled job 2025-10-03 17:30:40 +00:00
hugocasa
3907c9f951 feat: end user email env var (#6750)
* feat: end user email env var

* nit

* nits
2025-10-03 17:27:58 +00:00
Ruben Fiszel
3c7a12da57 raw app storage on db + s3 (#6749) 2025-10-03 16:30:06 +00:00
Diego Imbert
7c39aa6f6f Fix CI failing due to missing feature flag (#6747) 2025-10-03 16:26:01 +00:00
Alexander Petric
c658f321d6 fix: show that user is disabled in workspacelist (#6748)
* fix: show that user is disabled in workspacelist

* Update SQLx metadata

---------

Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2025-10-03 16:25:48 +00:00
centdix
1913979012 fix build (#6746) 2025-10-03 16:13:28 +00:00
Diego Imbert
06b152b295 fix: top level assigment doesn't propagate to setContext (#6745) 2025-10-03 14:53:10 +00:00
centdix
047420e5ad feat(flow): add option to turn flow into chat (#6658)
* add toggle option + chat interface

* backend impl

* draft

* put info in schema

* Revert "backend impl"

This reverts commit c534eeb49986424e2c12e2c5642be4e17ba380d1.

* chat interface in flow input

* cleaning

* add logic for running flow + styling

* handle historic args

* fix frontend changes

* add tables

* add conv list

* add endpoints

* adapt frontend

* list message logic

* save message in db

* save response in db

* cleaning

* better migrations

* refresh on new conv

* better logic for messages

* nit

* genere conversation uuid from frontend

* store chat mode info in flow status

* better ui for chat

* collapse chat

* ui

* infinite scroll on convs

* infinite scroll on messages

* fix ui

* new chat entry on new

* cleaning

* change setting logic

* fix test logic from flow input

* move toggle to input

* add warning modal when enabling chat mode

* add summary and explanation on inline script

* add hint for chat mode on user_message desc

* show chat message instead of input in graph

* add warning for triggers

* one logo when not expanded

* use infinitelist for conversations

* add warning when deployment in progress

* full width button

* better icon for menu

* better input + nits

* put toggle in action

* use waitjob

* cleaning

* cleaning

* scroll on new + cleaning

* use enum

* fix logic

* full screen

* cleaning

* exit on updatesqlx error

* Update SQLx metadata

* fix

* cleaning

* add for wait result endpoint

* add missing drop

* delete cascade

* fix: use macro version of query_as in flow_conversations.rs

Use sqlx::query_as! macro instead of query_as function for compile-time
SQL validation and better type safety

Co-authored-by: centdix <centdix@users.noreply.github.com>

* fix: update comment to clarify conversation message update condition

The comment now accurately reflects that the update happens when
it's a flow and it's done (flow_is_done)

Co-authored-by: centdix <centdix@users.noreply.github.com>

* fix: only parse chat_input_enabled if conditions are met

Move the parse_chat_input_enabled() call inside the condition check
to avoid unnecessary parsing when the flow is not done or unsuccessful

Co-authored-by: centdix <centdix@users.noreply.github.com>

* fix: use the same transaction for conversation creation

Pass transaction to get_or_create_conversation_with_id instead of
creating a new one, ensuring all operations are atomic

Co-authored-by: centdix <centdix@users.noreply.github.com>

* fix: remove update trigger and handle updated_at in application code

Remove the database trigger that automatically updates conversation
timestamp and instead update it explicitly when creating messages.
This gives better control and consistency.

Co-authored-by: centdix <centdix@users.noreply.github.com>

* Update SQLx metadata

* cleaning

* feat(aiagent): handle memory (#6719)

* implement memory

* s3 logic for memory

* fix typo

* much cleaner

* cleaning

* cleaning

* only if chat

* display nit

* nit

* fix stack overflow

* cleaning

* use len arg from input

* cleaning

* change order

* delete memory when conv deleted

* cleaning

* nit

* show description in expr mode

* opti

* opti

* updatee ref

* store string as simple string

* use markdown

* do not wait for deletion

* add delete loading

* fix logic

* fix markdown

* Update ee-repo-ref.txt

* Update SQLx metadata

* fix in test interface

* nit

* nit

* fix layout

* use memory_id to store memory

* shorter description

* rls + grant

* fix text overflow

* extract output from res

* cleaning

* handle streaming

* cleaning

* fix tool error

* nit

* update ref

* fix

* Update SQLx metadata

* nit

---------

Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: centdix <centdix@users.noreply.github.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2025-10-03 14:04:21 +00:00
hugocasa
6d436d7459 fix(backend): prevent s3 file upload infinite loop (#6742)
* fix(backend): prevent s3 file upload infinite loop

* update ref
2025-10-03 14:01:43 +00:00
Diego Imbert
0b5a2425ae improve dark mode readability monaco (#6741)
* improve dark mode readability monaco

* revert color transition
2025-10-03 11:07:22 +00:00
Diego Imbert
f35c9ffe63 S3 Proxy better errors + DuckDB S3 fix (#6740)
* Support for MinIO and other S3 impls in S3 Proxy

* Nice S3 Proxy error messages in DuckDB executor

* nit

* useless code

* super nit

* ee repo ref
2025-10-03 11:06:46 +00:00
Ruben Fiszel
6aaae00d54 chore(main): release 1.554.1 (#6738)
* chore(main): release 1.554.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-10-02 21:15:51 +00:00
hugocasa
cdb7524118 fix(backend): concurrency limits preprocessor (#6727)
* fix(backend): concurrency limits preprocessor

* refactor

* fix concurrency on agent workers

* nit

* nit

* update ref

* fix ci

* chore: update ee ref
2025-10-02 20:31:31 +00:00
Diego Imbert
9f40ce2da9 SelectDropdown reverse animation + ui nits (#6733)
* text-secondary nit

* Select Dropdown reverse animation

* nit misalignment
2025-10-02 20:31:05 +00:00
Diego Imbert
7cd5f26f70 Clarify Ducklake manual setup instructions (#6737) 2025-10-02 20:30:52 +00:00
Diego Imbert
f545b1d572 Fix ducklake instance DB + Add manual instructions (#6736)
* same auth method than worker for tokio_postgres

* Add manual setup instructions for Ducklake

* clarify instruction
2025-10-02 16:15:22 +00:00
Diego Imbert
49f5023fa5 exclude postgres BIGSERIAL / auto generated columns (#6734) 2025-10-02 15:27:13 +00:00
Diego Imbert
a00991a293 Fix save btn disabled on deletion (#6735) 2025-10-02 14:26:12 +00:00
centdix
a0bc0ee318 fix path assigner for nested calls (#6732) 2025-10-02 10:56:37 +00:00
Diego Imbert
36f2ab4715 UI nits (#6731)
* Fix JSON editor resource styling

* fix Edit resource type Object json editor

* oneOfSelected not auto selecting
2025-10-02 10:11:41 +00:00
Diego Imbert
59cdb141c3 NULL Toggle in InsertRow drawer (#6729)
* NULL toggle in InsertRow

* fix long type parsing in postgres

* nits

* graphite catch

* lazy_static

* support for time/timestamp/tz long forms in pg parser

* graphite suggestion
2025-10-02 10:10:53 +00:00
Diego Imbert
ae45a50eb2 Fix app tutorials (#6728)
* Fix tutorial basic

* fix other tutorials

* nit fix bug with button shrinking

* tutorial works backwards

* nit delete field on prev

* remove empty app duplication and magic code

* fix norefreshbar auto binding to false, making app dirty

* fix and improve app tutorial

* fix background runnable tutorial scroll

* fix connection tutorial

* mistake

* isCurrentlyInTutorial global state

* disable component navigation when in tutorial

* ci
2025-10-02 10:09:30 +00:00
Diego Imbert
12a2b58704 misalignment fix (#6726) 2025-10-01 16:16:15 +00:00
Ruben Fiszel
45be618c25 chore(main): release 1.554.0 (#6720)
* chore(main): release 1.554.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-10-01 16:05:35 +00:00
claude[bot]
c7f6ff14af correct typos in user-facing text (#6725)
- Fixed 'occured' -> 'occurred' (10 instances)
- Fixed 'commited' -> 'committed' (2 instances)

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2025-10-01 16:04:15 +00:00
Diego Imbert
8eb6c13c19 Fix flow tutorials (#6722)
* Fix tutorial basic

* fix other tutorials

* nit fix bug with button shrinking

* tutorial works backwards

* nit delete field on prev
2025-10-01 16:00:46 +00:00
Ruben Fiszel
e2e3ae9f02 fix: fix job duration unwrap crash 2025-10-01 15:35:09 +00:00
Alexander Petric
9e6cebac55 feat(cli): allow skipping branch validation (#6721) 2025-10-01 15:04:06 +00:00
Ruben Fiszel
ee0ffa47e2 improve json inputs rendering 2025-10-01 13:46:12 +00:00
Ruben Fiszel
74a75431c0 fix: allow running scripts in json view 2025-10-01 13:37:51 +00:00
Diego Imbert
67325abcbb fix slight offset on hover togglebutton (#6717) 2025-10-01 09:57:36 +00:00
Ruben Fiszel
ee00964a06 nit 2025-10-01 09:57:24 +00:00
Ruben Fiszel
5689411199 nit exit status 2025-10-01 09:18:43 +00:00
Ruben Fiszel
3306ee1718 chore(main): release 1.553.0 (#6711)
* chore(main): release 1.553.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-30 21:18:09 +00:00
Ruben Fiszel
be63a69649 nit 2025-09-30 21:11:08 +00:00
hugocasa
526dfd7237 feat(backend): allow multiple workspaces in jwt (#6714)
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2025-09-30 20:56:52 +00:00
Alexander Petric
e92a99a101 don't include drafts in workspace exports tarball (#6710)
* don't include drafts in workspace exports tarball

* sqlx

* ee repo ref

---------

Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2025-09-30 19:32:34 +00:00
Ruben Fiszel
8be898e5a2 nit 2025-09-30 19:32:00 +00:00
Ruben Fiszel
d92d6c8f84 fix toggle design 2025-09-30 19:10:12 +00:00
Ruben Fiszel
d382ea7c8b feat: support esm mode for codebase bundles (#6709)
* rawAppsS3

* make fn common

* all

* merge

* nit

* fix ingress

* all

* all

* all

* all
2025-09-30 14:45:30 +00:00
Ruben Fiszel
0ba5e3e9c7 nits 2025-09-30 12:25:36 +00:00
hugocasa
898eb6231b feat(backend): array and object params support in pwsh (#6706)
* feat(backend): array and object params support in pwsh

* add bool and improve arg conversion

* fix bash

* update parser

* sqlx
2025-09-30 12:25:12 +00:00
Ruben Fiszel
5aeb3fa0b7 fix: multiselect + jsoneditor nits 2025-09-30 08:48:28 +00:00
Ruben Fiszel
53fd4ccb82 chore(main): release 1.552.1 (#6705)
* chore(main): release 1.552.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-29 17:57:52 +00:00
hugocasa
ce653f8a05 fix(frontend): allow dates before 2000 in date picker (#6707)
* fix(frontend): allow dates before 2000 in date picker

* meh
2025-09-29 17:36:24 +00:00
Ruben Fiszel
2055e536a7 fix: fix c# with nsjail 2025-09-29 16:34:29 +00:00
Ruben Fiszel
727314cd44 chore(main): release 1.552.0 (#6700)
* chore(main): release 1.552.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-29 13:36:08 +00:00
Ruben Fiszel
7da0548b30 sqlx 2025-09-29 13:31:40 +00:00
Ruben Fiszel
e2608f9aac fix: external links in critical alert 2025-09-29 13:29:43 +00:00
hugocasa
4bbbeb956f feat: powershell private repo support (#6684)
* feat: powershell private repo support

* nits
2025-09-29 13:24:41 +00:00
Ruben Fiszel
d56dea4969 fix: show more autoscaling events (#6704)
* all

* all
2025-09-29 13:24:10 +00:00
Ruben Fiszel
74e9cffe58 min-w-nits 2025-09-29 13:12:30 +00:00
Ruben Fiszel
481c877537 fix: fix app schema form rendering 2025-09-29 13:10:07 +00:00
centdix
2b7ad0e2ef use base internal url (#6703) 2025-09-29 12:42:02 +00:00
Pyra
5f63ce6dd8 fix(uv): log stdout on uv pip install error (#6702)
Signed-off-by: pyranota <pyra@duck.com>
2025-09-29 12:12:06 +00:00
hugocasa
c751a5d6aa fix(frontend): prevent label interference with monaco editor in instance settings (#6701) 2025-09-29 12:04:52 +00:00
centdix
cc2afdb264 fix(mcp): filter out tools with long names (#6692)
* filter out tools with too long names

* do not advertise tool change ability

* add comment

* use id for names

* Revert "use id for names"

This reverts commit 40958cd861.

* use trunc suffix

* cleaning
2025-09-29 10:42:02 +00:00
Ruben Fiszel
9dad8e7e10 chore(main): release 1.551.4 (#6699)
* chore(main): release 1.551.4

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-29 09:57:50 +00:00
Ruben Fiszel
cfec8e99fb fix: migrate dotnet from msft images to script install 2025-09-29 09:44:04 +00:00
Ruben Fiszel
8266fb84b0 chore(main): release 1.551.3 (#6698)
* chore(main): release 1.551.3

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-29 09:02:42 +00:00
Ruben Fiszel
5ae525a9f1 fix: migrate dotnet from bitnami to microsoft images 2025-09-29 08:55:45 +00:00
Ruben Fiszel
c066ab56fa chore(main): release 1.551.2 (#6697)
* chore(main): release 1.551.2

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-29 07:38:34 +00:00
Osman Mesut OZCAN
629a378320 Fix typo (#6696) 2025-09-29 07:38:15 +00:00
Ruben Fiszel
81616cbe1e fix: fix copy first step input 2025-09-29 07:34:38 +00:00
Ruben Fiszel
4bc0283994 chore(main): release 1.551.1 (#6691)
* chore(main): release 1.551.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-28 20:05:31 +00:00
Ruben Fiszel
5d2a79e12b improve tests 2025-09-28 19:47:02 +00:00
Ruben Fiszel
d59b9f5216 improve tests 2025-09-28 19:40:26 +00:00
Ruben Fiszel
2047073c03 improve tests 2025-09-28 19:30:50 +00:00
Ruben Fiszel
477ec7773f improve tests 2025-09-28 19:28:38 +00:00
Ruben Fiszel
14780e49f2 nits 2025-09-28 11:00:15 +00:00
Ruben Fiszel
abf823e85b nits 2025-09-28 10:47:29 +00:00
Ruben Fiszel
a4138e037f nits 2025-09-28 10:46:38 +00:00
Ruben Fiszel
bdd36c0b4d fix: buttons are back to semi-bold 2025-09-28 10:20:46 +00:00
Ruben Fiszel
fe6199a867 nit check 2025-09-28 10:00:36 +00:00
Ruben Fiszel
b71e5c5adc move jobs ee in private 2025-09-28 09:39:06 +00:00
Ruben Fiszel
924891b644 chore(main): release 1.551.0 (#6690)
* chore(main): release 1.551.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-27 22:44:41 +00:00
Ruben Fiszel
b76cfa3881 nit UI 2025-09-27 22:37:40 +00:00
Ruben Fiszel
5b2ae8ea43 nit UI 2025-09-27 22:35:01 +00:00
Ruben Fiszel
cd90d0e1ef nit UI 2025-09-27 22:34:33 +00:00
Ruben Fiszel
452fb2b90a nit UI 2025-09-27 22:33:37 +00:00
Ruben Fiszel
86254d89e8 nit UI 2025-09-27 22:31:34 +00:00
Ruben Fiszel
6b907c8823 nit UI 2025-09-27 22:24:12 +00:00
Ruben Fiszel
70d1b99a02 nit UI 2025-09-27 22:21:13 +00:00
Ruben Fiszel
ef7af5a7b8 nit UI 2025-09-27 22:17:49 +00:00
Ruben Fiszel
439b6da720 nit UI 2025-09-27 22:05:46 +00:00
Diego Imbert
72b744c4e1 feat: UX improvements (all inputs)
* Monaco transparent bg

* started improving input transform form

* always show static/f selector

* fix connecting btn changing size

* pretty Fill Inputs button

* ResizeTransitionWrapper

* Prettier TemplateEditor

* prevent double onpointerdown when clicking button to close

* text hint

* force focus border for TemplateEditor

* styling in js mode

* update select style

* fix jittery fake monaco placeholder

* select nits

* aiproviderpicker + nits

* smaller ${...} badge

* no-default-style

* select dropdown slide

* nit

* Refresh button in flow picker quick

* jsonEditor pretty

* ai provider toggle button more

* change resource edit button pos

* ResourcePicker Add and Refresh btn

* fix scrollbar

* Fix FileInput and S3 Arg Input

* fix textarea styling

* nicer refresh button in Test This Step

* fix togglebutton border in darkmode

* rounded nit

* Fix multiselect styling

* Prevent crash when selecting dyn-multiselect

* missing $derived and $state => reactivity issue when switching between DynSelect and DynMultiselect

* forgot $effect.pre

* fix nested objects

* nits

* prettier json toggle and array inputs

* array input nits

* nit

* fix json toggle appearing in fileinputs

* nit

* started updating PropertyEditor

* (stash) fix select dropdown animation teleporting from bottom to top

* nit

* nit

* resize transition in schemaform

* nit

* nit typo

* nit enableFlyTransition

* shadow nit

* small consistency changes

* user setting nit

* resize transition in module preview form

* more space

* nit readability on hover

* DateTimeInput new style

* nit fix

* remove yPadding in template and simple editor

* nits

* Revert "remove yPadding in template and simple editor"

This reverts commit 8f27c8d0b8.

* nit

* Fix proppicker border

* fix inconsistent spacing btw arginput and input transform form field headers

* consistent add item button

* nit

* s3 settings nits

* RunsFilter fix

* gray ${...} badge

* border fix darkmode

* nit

* nit app editor consistency

* fix step input gen style

* nit fix

* nits

* toggle border

* nit toggle button

* nit font-medium

* nit font-medium

* nit font-medium

* nit font-medium

* nit

---------

Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2025-09-27 21:52:13 +00:00
Ruben Fiszel
d6d5fad83b nit customUI AIAgent 2025-09-27 12:01:01 +00:00
Ruben Fiszel
a9c114c4f8 chore(main): release 1.550.0 (#6685)
* chore(main): release 1.550.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-27 11:41:15 +00:00
Ruben Fiszel
ad32c940cb nit flow viewer right sidebar layout 2025-09-27 11:36:24 +00:00
Ruben Fiszel
15731e7726 nit 2025-09-27 11:23:54 +00:00
Ruben Fiszel
7df13b3e7b fix: restore set_progress feature with sse 2025-09-27 11:19:58 +00:00
Ruben Fiszel
9b13dd99ba nit perf 2025-09-27 10:15:38 +00:00
Ruben Fiszel
a1db857be4 nit perf 2025-09-27 10:10:27 +00:00
Ruben Fiszel
2a62f8ff8f nit 2025-09-27 09:50:58 +00:00
Ruben Fiszel
2421bdb839 nit 2025-09-27 09:45:31 +00:00
Ruben Fiszel
f28ed9a5f5 fix: limit auto data tables to tables of col < 100 2025-09-27 09:40:33 +00:00
Ruben Fiszel
311b410f2f fix: improve performance of flow viewer 2025-09-27 08:48:01 +00:00
Ruben Fiszel
7add57499c fix: improve graph rendering performances 2025-09-27 08:23:09 +00:00
Ruben Fiszel
dff499484b nit svelte 5 2025-09-27 08:04:17 +00:00
Ruben Fiszel
0ad5618aae nit dynamic enums 2025-09-27 08:02:26 +00:00
Ruben Fiszel
ec9e5a9acb fix: support label + value for dynamic enums of selects 2025-09-27 08:00:48 +00:00
Alexander Petric
ca4f9ee8c1 fix: scim group/users audit logs (#6682)
* scim group/users audit logs

* fixing tailwind class

* ee-repo-ref
2025-09-27 07:06:24 +00:00
dieriba
6ece0ac575 fix: improve dyn select as flow input
* fix lang

* remove print

* fix
2025-09-26 19:19:13 +00:00
Ruben Fiszel
6cc85d78d7 sqlx 2025-09-26 18:12:05 +00:00
Ruben Fiszel
87861301f2 fix: make schedule more resilient in case of pg clock shifts 2025-09-26 18:02:34 +00:00
Ruben Fiszel
341cdcf66e fix: improve behavior for already completed jobs when doing immediate cancels 2025-09-26 17:19:40 +00:00
hugocasa
f990107c45 feat: ai agent streaming (#6644)
* feat: ai agent step streaming

* refactor

* all

* nits

* fix other providers

* nits

* adapt to new streaming process
2025-09-26 17:09:34 +00:00
Ruben Fiszel
bce25bc283 chore(main): release 1.549.1 (#6681)
* chore(main): release 1.549.1

* Apply automatic changes

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
Co-authored-by: windmill-internal-app[bot] <217088191+windmill-internal-app[bot]@users.noreply.github.com>
2025-09-26 15:32:45 +00:00
Ruben Fiszel
db4bc7ee69 fix: fix agent_workers completed job back-compatibility deserialization 2025-09-26 15:27:21 +00:00
Ruben Fiszel
02692111a1 fix: do not request unecessarily get_scheduled_for 2025-09-26 15:06:42 +00:00
Ruben Fiszel
aae0919535 chore(main): release 1.549.0 (#6678)
* chore(main): release 1.549.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-26 14:02:17 +00:00
Diego Imbert
4828926be6 Fix SEGFAULT with duckdb and jemalloc (#6680) 2025-09-26 13:57:28 +00:00
hugocasa
8f4fef9804 feat(backend): job result stream optimization (#6673)
* feat(backend): job result stream optimization

* get offset locally instead of from db

* fix: agent worker result stream

* update ref

* nit

* remove foreign key on job

* fix build
2025-09-26 11:26:50 +00:00
Alexander Petric
4205e83cfd fix: scim group handling when deleting instance user + conversion (#6677)
* fix: scim group handling when deleting instance user + conversion

* sqlx + compilation
2025-09-26 11:25:44 +00:00
Ruben Fiszel
78c0bea6b4 chore(main): release 1.548.3 (#6676)
* chore(main): release 1.548.3

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-25 10:36:22 +00:00
Ruben Fiszel
b47c21f299 nit 2025-09-25 10:30:44 +00:00
Ruben Fiszel
f5d238edcf fix: fix job loader token initialization 2025-09-25 10:29:08 +00:00
dieriba
a308782bcf fix: websocket runnable #6675 2025-09-24 19:47:52 +00:00
Ruben Fiszel
6f15459d3b chore(main): release 1.548.2 (#6674)
* chore(main): release 1.548.2

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-24 19:06:31 +00:00
Ruben Fiszel
4117342d46 nit runs page reset 2025-09-24 19:05:35 +00:00
Ruben Fiszel
0f5de6837b nit 2025-09-24 18:48:00 +00:00
Ruben Fiszel
afa8104cb0 fix(ui): workers button on navbar require a single click only 2025-09-24 18:39:52 +00:00
Ruben Fiszel
3e5057d122 chore(main): release 1.548.1 (#6671)
* chore(main): release 1.548.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-24 18:16:02 +00:00
Ruben Fiszel
6e2ccebf37 nit 2025-09-24 18:13:57 +00:00
Ruben Fiszel
90d055afc6 nit 2025-09-24 18:13:32 +00:00
Ruben Fiszel
eda985df1c fix: improve vscode dev mode for flows 2025-09-24 18:12:37 +00:00
Ruben Fiszel
574364af05 fix: improve vscode dev mode layout for scripts 2025-09-24 18:07:26 +00:00
Ruben Fiszel
aff2ef936e chore(main): release 1.548.0 (#6667)
* chore(main): release 1.548.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-24 16:56:34 +00:00
centdix
f66f131fed fix(aichat): in script mode use diff based edits for good providers only (#6665)
* Revert "use diffs based edits"

This reverts commit 4ef6bce562.

* feat(aichat): use diff-based edits for OpenAI/Anthropic providers, whole code for others

- Check the current model provider at runtime
- Use diff-based approach (with diffs array) for OpenAI and Anthropic
- Use whole code replacement for all other providers
- Update tool definition to support both parameters
- Update system prompt with conditional instructions based on provider

Co-authored-by: centdix <centdix@users.noreply.github.com>

* fix

* cleaning

* cleaning

* cleaning

* cleaning

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: centdix <centdix@users.noreply.github.com>
2025-09-24 16:51:51 +00:00
Alexander Petric
6b61262603 feat: app button run in background option (#6670)
* feat: app button, run in background

* show brief loading when in background mode
2025-09-24 16:49:03 +00:00
Ruben Fiszel
31c2e3662f fix: fix vscode extension dev mode 2025-09-24 16:47:50 +00:00
Pyra
ed806bf9d0 fix(backend): rework dependency_map handling (#6598)
* v0

Signed-off-by: pyranota <pyra@duck.com>

* optimize relocks

* make it work with relative relative imports

Signed-off-by: pyranota <pyra@duck.com>

* use fallback

Signed-off-by: pyranota <pyra@duck.com>

* remove dbg and todos

Signed-off-by: pyranota <pyra@duck.com>

* future proof a bit

Signed-off-by: pyranota <pyra@duck.com>

* cleanup

Signed-off-by: pyranota <pyra@duck.com>

* more cleanup

Signed-off-by: pyranota <pyra@duck.com>

* remove final TODO

Signed-off-by: pyranota <pyra@duck.com>

* do not use bytemuck

Signed-off-by: pyranota <pyra@duck.com>

* optimize hashing

Signed-off-by: pyranota <pyra@duck.com>

* implementation 1

Signed-off-by: pyranota <pyra@duck.com>

* almost v0

Signed-off-by: pyranota <pyra@duck.com>

* v0

Signed-off-by: pyranota <pyra@duck.com>

* add comments and use fallback

Signed-off-by: pyranota <pyra@duck.com>

* call dissolve for apps

Signed-off-by: pyranota <pyra@duck.com>

* add comms

Signed-off-by: pyranota <pyra@duck.com>

* refactor v0 (partially tested + dirty)

Signed-off-by: pyranota <pyra@duck.com>

* finishing

Signed-off-by: pyranota <pyra@duck.com>

* remove TODO

Signed-off-by: pyranota <pyra@duck.com>

* Update SQLx metadata

* silence unused argument

Signed-off-by: pyranota <pyra@duck.com>

* cleanup

Signed-off-by: pyranota <pyra@duck.com>

* implement rebuild_map endpoint

Signed-off-by: pyranota <pyra@duck.com>

* update windmill api client

Signed-off-by: pyranota <pyra@duck.com>

* almost finish with tests

Signed-off-by: pyranota <pyra@duck.com>

* add proper testing

Signed-off-by: pyranota <pyra@duck.com>

* remove unused fixtures

Signed-off-by: pyranota <pyra@duck.com>

* Update SQLx metadata

* partial cleanup

Signed-off-by: pyranota <pyra@duck.com>

* Update backend/windmill-worker/src/scoped_dependency_map.rs

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* Update backend/windmill-common/src/scripts.rs

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* evil doings

Signed-off-by: pyranota <pyra@duck.com>

* more cleanup

* Update SQLx metadata

* more cleanup

Signed-off-by: pyranota <pyra@duck.com>

* fixing CI

Signed-off-by: pyranota <pyra@duck.com>

* remove python from default features

Signed-off-by: pyranota <pyra@duck.com>

---------

Signed-off-by: pyranota <pyra@duck.com>
Co-authored-by: Pyra <92104930+pyranye@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-09-24 13:40:39 +00:00
dieriba
ef75ed3df7 feat: websocket trigger send runnable result even if error (#6664)
* done

* nits

* update sqlx

---------

Co-authored-by: hugocasa <hugo@casademont.ch>
2025-09-23 19:22:54 +00:00
Diego Imbert
b0e7577955 fix: flow quick picker refresh (#6666)
* Fix Broken flow quick picker refresh button

* 60s Cache invalidation
2025-09-23 19:40:30 +02:00
Ruben Fiszel
55546971a8 chore(main): release 1.547.0 (#6663)
* chore(main): release 1.547.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-23 19:31:07 +02:00
Ruben Fiszel
a7cbc289af fix(cli): improve result printing of the CLI 2025-09-23 15:31:10 +00:00
Ruben Fiszel
2de7134b85 fix: improve scripts duplicity error in global search 2025-09-23 15:03:41 +00:00
dieriba
b64e509e60 feat: add dyn select for flow step #6662 2025-09-23 12:09:58 +00:00
Diego Imbert
064303e126 forgot $effect.pre (#6661) 2025-09-23 11:58:15 +00:00
Diego Imbert
580d6b613c Fix UI crash with Dynamic Multiselect (#6660)
* Prevent crash when selecting dyn-multiselect

* missing $derived and $state => reactivity issue when switching between DynSelect and DynMultiselect
2025-09-23 13:18:05 +02:00
Ruben Fiszel
11c9c3548a make it impossible to update folder with ill-defined extra_perms 2025-09-23 10:30:37 +00:00
Ruben Fiszel
27271eead6 chore(main): release 1.546.1 (#6659)
* chore(main): release 1.546.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-23 10:22:23 +00:00
centdix
389b692523 fix(mcp): use stateless mode for openai sdk compatibility (#6656)
* update crate

* use non stateful mode

* fix

* fix
2025-09-23 10:16:26 +00:00
Ruben Fiszel
3f66314419 chore(main): release 1.546.0 (#6648)
* chore(main): release 1.546.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2025-09-23 06:36:20 +02:00
Alexander Petric
6ba3a4397e fix: cli path on windows + error_handler_muted_on_cancel (#6657)
* fix: cli path on windows + error_handler_muted_on_cancel

* prefix eq path

* sqlx
2025-09-23 06:32:51 +02:00
Alexander Petric
de7251d857 feat: dynamically hide tabs in app builder (#6653)
* feat: dynamically hide tabs in app builder

* claude code comments
2025-09-22 16:29:34 +00:00
Alexander Petric
e0671a30f1 require refresh_token in oauth api spec (#6654) 2025-09-22 16:22:34 +00:00
Ruben Fiszel
30b4ef9044 nit compile 2025-09-22 16:22:03 +00:00
Ruben Fiszel
ad38298840 nit compile 2025-09-22 15:05:13 +00:00
Alexander Petric
08952c6c6e feat: app builder button tooltip (#6652) 2025-09-22 15:03:54 +00:00
Ruben Fiszel
90549c13bd add more debug logs for event triggers 2025-09-22 14:51:46 +00:00
Ruben Fiszel
7a13e9e988 feat: split RUST_LOG into RUST_LOG and RUST_LOG_STDOUT 2025-09-22 14:36:15 +00:00
centdix
c7f8222a89 nit prompt (#6651) 2025-09-22 13:23:20 +00:00
445 changed files with 15892 additions and 7935 deletions

View File

@@ -57,8 +57,12 @@ RUN apt-get update \
RUN rustup component add rustfmt
# C#
COPY --from=bitnami/dotnet-sdk:9.0.101-debian-12-r0 /opt/bitnami/dotnet-sdk /opt/dotnet-sdk
RUN ln -s /opt/dotnet-sdk/bin/dotnet /usr/bin/dotnet
RUN wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh \
&& chmod +x dotnet-install.sh \
&& ./dotnet-install.sh --channel 9.0 --install-dir /usr/share/dotnet \
&& ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet \
&& rm dotnet-install.sh
# Nushell
COPY --from=ghcr.io/nushell/nushell:0.101.0-bookworm /usr/bin/nu /usr/bin/nu

View File

@@ -51,7 +51,22 @@ jobs:
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
cache-workspaces: backend
toolchain: 1.85.0
toolchain: 1.90.0
- name: Read EE repo commit hash
run: |
echo "ee_repo_ref=$(cat ./ee-repo-ref.txt)" >> "$GITHUB_ENV"
- uses: actions/checkout@v4
with:
repository: windmill-labs/windmill-ee-private
path: ./windmill-ee-private
ref: ${{ env.ee_repo_ref }}
token: ${{ secrets.WINDMILL_EE_PRIVATE_ACCESS }}
fetch-depth: 0
- name: Substitute EE code (EE logic is behind feature flag)
run: |
./substitute_ee_code.sh --copy --dir ./windmill-ee-private
- name: cargo test
timeout-minutes: 16
run:
@@ -61,5 +76,5 @@ jobs:
DISABLE_EMBEDDING=true RUST_LOG=info
DENO_PATH=$(which deno) BUN_PATH=$(which bun) GO_PATH=$(which go)
UV_PATH=$(which uv) cargo test --features
enterprise,deno_core,license,python,rust,scoped_cache --all --
enterprise,deno_core,license,python,rust,scoped_cache,private --all --
--nocapture

View File

@@ -142,7 +142,7 @@ jobs:
1. Extract the Cloudflare preview URL from the cloudflare-workers-and-pages bot comment in this PR
2. Analyze the PR changes to understand what feature was added/modified
3. Create detailed demo instructions showing how to showcase the new feature
3. Create detailed instructions to give to an AI agent that will click and interact with buttons and inputs to showcase the new feature. Only include the instructions, nothing else.
4. Create a demo.json file with a valid JSON object containing:
- instructions: the demo instructions
- url: the preview URL
@@ -151,7 +151,7 @@ jobs:
Example demo.json:
{
"instructions": "Instructions here",
"instructions": "Click on settings, then account settings, then 'generate new token'",
"url": "https://example.pages.dev"
}

View File

@@ -1,5 +1,244 @@
# Changelog
## [1.555.2](https://github.com/windmill-labs/windmill/compare/v1.555.1...v1.555.2) (2025-10-06)
### Bug Fixes
* **backend:** use correct ai tool job dir ([#6757](https://github.com/windmill-labs/windmill/issues/6757)) ([7c757b6](https://github.com/windmill-labs/windmill/commit/7c757b68f64bf3cf770cd080c5025f202d40201c))
## [1.555.1](https://github.com/windmill-labs/windmill/compare/v1.555.0...v1.555.1) (2025-10-04)
### Bug Fixes
* app button tooltip also when disabled + audit log filters ([#6751](https://github.com/windmill-labs/windmill/issues/6751)) ([605c552](https://github.com/windmill-labs/windmill/commit/605c5526f83d3b985f04570039bb4671cc5912f4))
* init git repo preview save ([#6753](https://github.com/windmill-labs/windmill/issues/6753)) ([d9c01e0](https://github.com/windmill-labs/windmill/commit/d9c01e0c0392f13e52ad92f87c4216e64e89a3bc))
## [1.555.0](https://github.com/windmill-labs/windmill/compare/v1.554.1...v1.555.0) (2025-10-03)
### Features
* end user email env var ([#6750](https://github.com/windmill-labs/windmill/issues/6750)) ([3907c9f](https://github.com/windmill-labs/windmill/commit/3907c9f9512ebd73daf0a2f3ee2e8db6fb9f4df6))
* **flow:** add option to turn flow into chat ([#6658](https://github.com/windmill-labs/windmill/issues/6658)) ([047420e](https://github.com/windmill-labs/windmill/commit/047420e5ad7b6178291bc7ed75d029794760d18b))
### Bug Fixes
* **backend:** prevent s3 file upload infinite loop ([#6742](https://github.com/windmill-labs/windmill/issues/6742)) ([6d436d7](https://github.com/windmill-labs/windmill/commit/6d436d745994f954a37f33ca2cc2e9f0801b16b9))
* show that user is disabled in workspacelist ([#6748](https://github.com/windmill-labs/windmill/issues/6748)) ([c658f32](https://github.com/windmill-labs/windmill/commit/c658f321d68e2d72622d9d167b20cac67364651c))
* top level assigment doesn't propagate to setContext ([#6745](https://github.com/windmill-labs/windmill/issues/6745)) ([06b152b](https://github.com/windmill-labs/windmill/commit/06b152b295cd4892d7309651d382a05cdcf7d378))
## [1.554.1](https://github.com/windmill-labs/windmill/compare/v1.554.0...v1.554.1) (2025-10-02)
### Bug Fixes
* **backend:** concurrency limits preprocessor ([#6727](https://github.com/windmill-labs/windmill/issues/6727)) ([cdb7524](https://github.com/windmill-labs/windmill/commit/cdb75241188ee0a6d7bc62ca6dd639606eef426a))
## [1.554.0](https://github.com/windmill-labs/windmill/compare/v1.553.0...v1.554.0) (2025-10-01)
### Features
* **cli:** allow skipping branch validation ([#6721](https://github.com/windmill-labs/windmill/issues/6721)) ([9e6ceba](https://github.com/windmill-labs/windmill/commit/9e6cebac557fd9a8530df54c227e915435fd2de5))
### Bug Fixes
* allow running scripts in json view ([74a7543](https://github.com/windmill-labs/windmill/commit/74a75431c072e9f084a43b8d8f195ca7757faf07))
* fix job duration unwrap crash ([e2e3ae9](https://github.com/windmill-labs/windmill/commit/e2e3ae9f0280d4369f77064ed85e5fde7e9d5a0d))
## [1.553.0](https://github.com/windmill-labs/windmill/compare/v1.552.1...v1.553.0) (2025-09-30)
### Features
* **backend:** allow multiple workspaces in jwt ([#6714](https://github.com/windmill-labs/windmill/issues/6714)) ([526dfd7](https://github.com/windmill-labs/windmill/commit/526dfd72377b90fb47b9c2c3924a1377e2715ae1))
* **backend:** array and object params support in pwsh ([#6706](https://github.com/windmill-labs/windmill/issues/6706)) ([898eb62](https://github.com/windmill-labs/windmill/commit/898eb6231beb5ca45d59da069f458f7828f427f0))
* support esm mode for codebase bundles ([#6709](https://github.com/windmill-labs/windmill/issues/6709)) ([d382ea7](https://github.com/windmill-labs/windmill/commit/d382ea7c8b372471dd3393720ff93749fde898f5))
### Bug Fixes
* multiselect + jsoneditor nits ([5aeb3fa](https://github.com/windmill-labs/windmill/commit/5aeb3fa0b74fb0d72f0439ce540baf224654f1ae))
## [1.552.1](https://github.com/windmill-labs/windmill/compare/v1.552.0...v1.552.1) (2025-09-29)
### Bug Fixes
* fix c# with nsjail ([2055e53](https://github.com/windmill-labs/windmill/commit/2055e536a7fcb9cfe155c0fa67de6ae49d925f97))
* **frontend:** allow dates before 2000 in date picker ([#6707](https://github.com/windmill-labs/windmill/issues/6707)) ([ce653f8](https://github.com/windmill-labs/windmill/commit/ce653f8a0538fcc88ef78f6c50960a7340648b0f))
## [1.552.0](https://github.com/windmill-labs/windmill/compare/v1.551.4...v1.552.0) (2025-09-29)
### Features
* powershell private repo support ([#6684](https://github.com/windmill-labs/windmill/issues/6684)) ([4bbbeb9](https://github.com/windmill-labs/windmill/commit/4bbbeb956f8f09ea5a8af241912a1bead1e06520))
### Bug Fixes
* external links in critical alert ([e2608f9](https://github.com/windmill-labs/windmill/commit/e2608f9aacd30e2a7aeb5b850802514f64a41380))
* fix app schema form rendering ([481c877](https://github.com/windmill-labs/windmill/commit/481c8775377f7f01ad01b5db85a98ccffadada91))
* **frontend:** prevent label interference with monaco editor in instance settings ([#6701](https://github.com/windmill-labs/windmill/issues/6701)) ([c751a5d](https://github.com/windmill-labs/windmill/commit/c751a5d6aa49e4bc0970f87b3f1e975e8ee58479))
* **mcp:** filter out tools with long names ([#6692](https://github.com/windmill-labs/windmill/issues/6692)) ([cc2afdb](https://github.com/windmill-labs/windmill/commit/cc2afdb264b0eaa353e5f2736c98e475337b71f7))
* show more autoscaling events ([#6704](https://github.com/windmill-labs/windmill/issues/6704)) ([d56dea4](https://github.com/windmill-labs/windmill/commit/d56dea4969ed5c6eec30c72cf9f1171889444007))
* **uv:** log stdout on `uv pip install` error ([#6702](https://github.com/windmill-labs/windmill/issues/6702)) ([5f63ce6](https://github.com/windmill-labs/windmill/commit/5f63ce6dd8697533de1e0af786e463f3224912c2))
## [1.551.4](https://github.com/windmill-labs/windmill/compare/v1.551.3...v1.551.4) (2025-09-29)
### Bug Fixes
* migrate dotnet from msft images to script install ([cfec8e9](https://github.com/windmill-labs/windmill/commit/cfec8e99fb55928dfed3b7e80fb63cc279553dec))
## [1.551.3](https://github.com/windmill-labs/windmill/compare/v1.551.2...v1.551.3) (2025-09-29)
### Bug Fixes
* migrate dotnet from bitnami to microsoft images ([5ae525a](https://github.com/windmill-labs/windmill/commit/5ae525a9f14de20d45e6075baa979eb4aaac4850))
## [1.551.2](https://github.com/windmill-labs/windmill/compare/v1.551.1...v1.551.2) (2025-09-29)
### Bug Fixes
* fix copy first step input ([81616cb](https://github.com/windmill-labs/windmill/commit/81616cbe1e27bc3f45cfa35cd359ce9a0f493f35))
## [1.551.1](https://github.com/windmill-labs/windmill/compare/v1.551.0...v1.551.1) (2025-09-28)
### Bug Fixes
* buttons are back to semi-bold ([bdd36c0](https://github.com/windmill-labs/windmill/commit/bdd36c0b4d5c590e66bf471c8e4b5f681b9464aa))
## [1.551.0](https://github.com/windmill-labs/windmill/compare/v1.550.0...v1.551.0) (2025-09-27)
### Features
* UX improvements (all inputs) ([72b744c](https://github.com/windmill-labs/windmill/commit/72b744c4e1bc3c1f3098f4d6de6c9474d7a8fb84))
## [1.550.0](https://github.com/windmill-labs/windmill/compare/v1.549.1...v1.550.0) (2025-09-27)
### Features
* ai agent streaming ([#6644](https://github.com/windmill-labs/windmill/issues/6644)) ([f990107](https://github.com/windmill-labs/windmill/commit/f990107c45fbb2e955ef67439e92328976091eb0))
### Bug Fixes
* improve behavior for already completed jobs when doing immediate cancels ([341cdcf](https://github.com/windmill-labs/windmill/commit/341cdcf66efdfd504492be32d9b4f5cb9db2df2a))
* improve dyn select as flow input ([6ece0ac](https://github.com/windmill-labs/windmill/commit/6ece0ac5758d4f5e8c0d55ee78a524e454ad264b))
* improve graph rendering performances ([7add574](https://github.com/windmill-labs/windmill/commit/7add57499c02ac53a7f7adbabbb279d7c41ab275))
* improve performance of flow viewer ([311b410](https://github.com/windmill-labs/windmill/commit/311b410f2f65c3bdfc483c80cc5ef72b6864118a))
* limit auto data tables to tables of col &lt; 100 ([f28ed9a](https://github.com/windmill-labs/windmill/commit/f28ed9a5f5c6032c49734e6770c2f2c9e2e4a001))
* make schedule more resilient in case of pg clock shifts ([8786130](https://github.com/windmill-labs/windmill/commit/87861301f28cab136fe7af094690539e3daa613f))
* restore set_progress feature with sse ([7df13b3](https://github.com/windmill-labs/windmill/commit/7df13b3e7bb095475d0fe54b7f635e3861fb0f73))
* scim group/users audit logs ([#6682](https://github.com/windmill-labs/windmill/issues/6682)) ([ca4f9ee](https://github.com/windmill-labs/windmill/commit/ca4f9ee8c12f01fc7c3bcedf5d41e59dc28eb1f2))
* support label + value for dynamic enums of selects ([ec9e5a9](https://github.com/windmill-labs/windmill/commit/ec9e5a9acbd352b20399d403be55361c73084aff))
## [1.549.1](https://github.com/windmill-labs/windmill/compare/v1.549.0...v1.549.1) (2025-09-26)
### Bug Fixes
* do not request unecessarily get_scheduled_for ([0269211](https://github.com/windmill-labs/windmill/commit/02692111a1a8eefb2675b14d53f109a66c1b9a78))
* fix agent_workers completed job back-compatibility deserialization ([db4bc7e](https://github.com/windmill-labs/windmill/commit/db4bc7ee6963955abc7e290bd67ea913b0f5e2ad))
## [1.549.0](https://github.com/windmill-labs/windmill/compare/v1.548.3...v1.549.0) (2025-09-26)
### Features
* **backend:** job result stream optimization ([#6673](https://github.com/windmill-labs/windmill/issues/6673)) ([8f4fef9](https://github.com/windmill-labs/windmill/commit/8f4fef98042c49346c89bdf5e0b9b1f2d52e371f))
### Bug Fixes
* scim group handling when deleting instance user + conversion ([#6677](https://github.com/windmill-labs/windmill/issues/6677)) ([4205e83](https://github.com/windmill-labs/windmill/commit/4205e83cfde453827eab23c31e76a0f0490d31b7))
## [1.548.3](https://github.com/windmill-labs/windmill/compare/v1.548.2...v1.548.3) (2025-09-25)
### Bug Fixes
* fix job loader token initialization ([f5d238e](https://github.com/windmill-labs/windmill/commit/f5d238edcfed6b0f066d459cdc718679a7b51187))
* websocket runnable [#6675](https://github.com/windmill-labs/windmill/issues/6675) ([a308782](https://github.com/windmill-labs/windmill/commit/a308782bcf7ef9913887521d74796b490619d0c8))
## [1.548.2](https://github.com/windmill-labs/windmill/compare/v1.548.1...v1.548.2) (2025-09-24)
### Bug Fixes
* **ui:** workers button on navbar require a single click only ([afa8104](https://github.com/windmill-labs/windmill/commit/afa8104cb0c1a8f1a6fe124a6e01c1d32f049afa))
## [1.548.1](https://github.com/windmill-labs/windmill/compare/v1.548.0...v1.548.1) (2025-09-24)
### Bug Fixes
* improve vscode dev mode for flows ([eda985d](https://github.com/windmill-labs/windmill/commit/eda985df1cce70ea3ce4117577c889a3dbc47c6a))
* improve vscode dev mode layout for scripts ([574364a](https://github.com/windmill-labs/windmill/commit/574364af050f2cc66c986fed8001409aa48f3530))
## [1.548.0](https://github.com/windmill-labs/windmill/compare/v1.547.0...v1.548.0) (2025-09-24)
### Features
* app button run in background option ([#6670](https://github.com/windmill-labs/windmill/issues/6670)) ([6b61262](https://github.com/windmill-labs/windmill/commit/6b61262603b247da717d9fd188746078ea779c34))
* websocket trigger send runnable result even if error ([#6664](https://github.com/windmill-labs/windmill/issues/6664)) ([ef75ed3](https://github.com/windmill-labs/windmill/commit/ef75ed3df7bf99e735a579291078f4ea9db4fcf6))
### Bug Fixes
* **aichat:** in script mode use diff based edits for good providers only ([#6665](https://github.com/windmill-labs/windmill/issues/6665)) ([f66f131](https://github.com/windmill-labs/windmill/commit/f66f131fed88a71f00d2cadb404ed4fa7698deb6))
* **backend:** rework `dependency_map` handling ([#6598](https://github.com/windmill-labs/windmill/issues/6598)) ([ed806bf](https://github.com/windmill-labs/windmill/commit/ed806bf9d07de9f22c8a00260984e94eafd6ddf8))
* fix vscode extension dev mode ([31c2e36](https://github.com/windmill-labs/windmill/commit/31c2e3662f53e6acb6b290f8128cec4a9a98bf73))
* flow quick picker refresh ([#6666](https://github.com/windmill-labs/windmill/issues/6666)) ([b0e7577](https://github.com/windmill-labs/windmill/commit/b0e7577955c954fef68d0a9d7218f5891100e1ab))
## [1.547.0](https://github.com/windmill-labs/windmill/compare/v1.546.1...v1.547.0) (2025-09-23)
### Features
* add dyn select for flow step [#6662](https://github.com/windmill-labs/windmill/issues/6662) ([b64e509](https://github.com/windmill-labs/windmill/commit/b64e509e60fadc631ccd6090654d523d08c06e35))
### Bug Fixes
* **cli:** improve result printing of the CLI ([a7cbc28](https://github.com/windmill-labs/windmill/commit/a7cbc289af1eaacbb50d53f2bcb4a14f50d420ef))
* improve scripts duplicity error in global search ([2de7134](https://github.com/windmill-labs/windmill/commit/2de7134b85d8249f661e3db34ff43c29b13fa0aa))
## [1.546.1](https://github.com/windmill-labs/windmill/compare/v1.546.0...v1.546.1) (2025-09-23)
### Bug Fixes
* **mcp:** use stateless mode for openai sdk compatibility ([#6656](https://github.com/windmill-labs/windmill/issues/6656)) ([389b692](https://github.com/windmill-labs/windmill/commit/389b692523507a28916e96b481c60f3c49cd31da))
## [1.546.0](https://github.com/windmill-labs/windmill/compare/v1.545.0...v1.546.0) (2025-09-23)
### Features
* app builder button tooltip ([#6652](https://github.com/windmill-labs/windmill/issues/6652)) ([08952c6](https://github.com/windmill-labs/windmill/commit/08952c6c6e0afdde8fc941f9f1d17870fe25878a))
* dynamically hide tabs in app builder ([#6653](https://github.com/windmill-labs/windmill/issues/6653)) ([de7251d](https://github.com/windmill-labs/windmill/commit/de7251d85734757a1f3e222c715f807ba167d535))
* split RUST_LOG into RUST_LOG and RUST_LOG_STDOUT ([7a13e9e](https://github.com/windmill-labs/windmill/commit/7a13e9e98840a456ef6625cea838e3e82def5c4b))
### Bug Fixes
* add settable poll delay for sse streams ([0392103](https://github.com/windmill-labs/windmill/commit/039210369383bcc3a15d95cba9efb591ee8e9891))
* cli path on windows + error_handler_muted_on_cancel ([#6657](https://github.com/windmill-labs/windmill/issues/6657)) ([6ba3a43](https://github.com/windmill-labs/windmill/commit/6ba3a4397e439d40079d524de15507257442c5e1))
* improve reliability of exits in case graceful handler didn't exit as expected ([f6dd78c](https://github.com/windmill-labs/windmill/commit/f6dd78cb11ee73408f66b4670c395ade99beedbe))
## [1.545.0](https://github.com/windmill-labs/windmill/compare/v1.544.2...v1.545.0) (2025-09-20)

3
backend/.gitignore vendored
View File

@@ -9,4 +9,5 @@ windmill-api/openapi-*.*
.duckdb/*
*ee.rs
generate_mcp_endpoints_tools/venv
bacon.toml
bacon.toml
libwindmill_duckdb_ffi_internal.so

View File

@@ -0,0 +1,24 @@
{
"db_name": "PostgreSQL",
"query": "SELECT data FROM app_bundles WHERE app_version_id = $1 AND file_type = $2 AND w_id = $3",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "data",
"type_info": "Bytea"
}
],
"parameters": {
"Left": [
"Int8",
"Text",
"Text"
]
},
"nullable": [
false
]
},
"hash": "01050e7057f3d1971ad9e47ac83bf6a3c3c9f41689c3607f0b264437ae6b3324"
}

View File

@@ -0,0 +1,28 @@
{
"db_name": "PostgreSQL",
"query": "SELECT path, versions[array_upper(versions, 1)] as version FROM flow WHERE workspace_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "version",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
null
]
},
"hash": "094587579285fc5656f6104716dca1805e3a1530fc64bf95eaee5b645e885251"
}

View File

@@ -0,0 +1,46 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT workspace_id, importer_path, importer_kind::text, imported_path, importer_node_id\n FROM dependency_map WHERE workspace_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "importer_path",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "importer_kind",
"type_info": "Text"
},
{
"ordinal": 3,
"name": "imported_path",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "importer_node_id",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
false,
null,
false,
false
]
},
"hash": "13297889361ac6839d6c4bd0b8ae121305d63cfcd88f69700125d17fb2c56a1f"
}

View File

@@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "SELECT value FROM app_version WHERE id = $1 LIMIT 1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "value",
"type_info": "Json"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
false
]
},
"hash": "1492b88c75722465b1a5c138729e6bb2782e1f8ef5f9fe752b356927a8605100"
}

View File

@@ -0,0 +1,29 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT\n eig.igroup as group_name,\n ws.auto_add_instance_groups_roles\n FROM email_to_igroup eig\n INNER JOIN workspace_settings ws ON ws.workspace_id = $1\n WHERE eig.email = $2\n AND eig.igroup = ANY(ws.auto_add_instance_groups)\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "group_name",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "auto_add_instance_groups_roles",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false,
true
]
},
"hash": "1ff185d8b8b897a72180cd0002e0f7e9858eef249577ce23969522793c6b5608"
}

View File

@@ -0,0 +1,15 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE flow_conversation_message\n SET content = $1\n WHERE job_id = $2\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Uuid"
]
},
"nullable": []
},
"hash": "20888e946a5597989488e2a54e354e4ce2872f2bc3af7b26fcaafe8703ba70bf"
}

View File

@@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "SELECT EXISTS(SELECT 1 FROM v2_job_completed WHERE id = $1)",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": [
null
]
},
"hash": "25b7c964336321fa10ea988831526b391cc1f02185ee87dbbda3d8a388cc858a"
}

View File

@@ -0,0 +1,23 @@
{
"db_name": "PostgreSQL",
"query": "SELECT draft_only FROM app WHERE path = $1 AND workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "draft_only",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
true
]
},
"hash": "27b0c827467cc92979f094620957bc0edfa295d6c2292e509a5536765d120bd8"
}

View File

@@ -0,0 +1,23 @@
{
"db_name": "PostgreSQL",
"query": "SELECT draft_only FROM flow WHERE path = $1 AND workspace_id = $2 AND archived = false",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "draft_only",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
true
]
},
"hash": "28f1ecca40c8b81cc59dffb75e2913c889b374999ece04173b2e67dc74005f60"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT \n v2_job_queue.workspace_id,\n v2_job_queue.id,\n v2_job.args as \"args: sqlx::types::Json<HashMap<String, Box<RawValue>>>\",\n v2_job.parent_job,\n v2_job.created_by,\n v2_job_queue.started_at,\n scheduled_for,\n runnable_path,\n kind as \"kind: JobKind\",\n runnable_id as \"runnable_id: ScriptHash\",\n canceled_reason,\n canceled_by,\n permissioned_as,\n permissioned_as_email,\n flow_status as \"flow_status: sqlx::types::Json<Box<RawValue>>\",\n v2_job.tag,\n script_lang as \"script_lang: ScriptLang\",\n same_worker,\n pre_run_error,\n concurrent_limit,\n concurrency_time_window_s,\n flow_innermost_root_job,\n root_job,\n timeout,\n flow_step_id,\n cache_ttl,\n v2_job_queue.priority,\n preprocessed,\n script_entrypoint_override,\n trigger,\n trigger_kind as \"trigger_kind: JobTriggerKind\",\n visible_to_owner\n FROM v2_job_queue INNER JOIN v2_job ON v2_job.id = v2_job_queue.id LEFT JOIN v2_job_status ON v2_job_status.id = v2_job_queue.id WHERE v2_job_queue.id = $1",
"query": "SELECT \n v2_job_queue.workspace_id,\n v2_job_queue.id,\n v2_job.args as \"args: sqlx::types::Json<HashMap<String, Box<RawValue>>>\",\n v2_job.parent_job,\n v2_job.created_by,\n v2_job_queue.started_at,\n scheduled_for,\n runnable_path,\n kind as \"kind: JobKind\",\n runnable_id as \"runnable_id: ScriptHash\",\n canceled_reason,\n canceled_by,\n permissioned_as,\n permissioned_as_email,\n flow_status as \"flow_status: sqlx::types::Json<Box<RawValue>>\",\n v2_job.tag,\n script_lang as \"script_lang: ScriptLang\",\n same_worker,\n pre_run_error,\n concurrent_limit,\n concurrency_time_window_s,\n flow_innermost_root_job,\n root_job,\n timeout,\n flow_step_id,\n cache_ttl,\n v2_job_queue.priority,\n preprocessed,\n script_entrypoint_override,\n trigger,\n trigger_kind as \"trigger_kind: JobTriggerKind\",\n visible_to_owner,\n NULL as permissioned_as_end_user_email\n FROM v2_job_queue INNER JOIN v2_job ON v2_job.id = v2_job_queue.id LEFT JOIN v2_job_status ON v2_job_status.id = v2_job_queue.id WHERE v2_job_queue.id = $1",
"describe": {
"columns": [
{
@@ -241,6 +241,11 @@
"ordinal": 31,
"name": "visible_to_owner",
"type_info": "Bool"
},
{
"ordinal": 32,
"name": "permissioned_as_end_user_email",
"type_info": "Text"
}
],
"parameters": {
@@ -280,8 +285,9 @@
true,
true,
true,
false
false,
null
]
},
"hash": "f3f96e066716e61042519a645d487b578bc63792cdb0f7ddaeb82e9771287c22"
"hash": "3162ec92bb32af47a71cc41172cc740b5dea1304ce4dfdb4d3d0efa4266f38c5"
}

View File

@@ -0,0 +1,18 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE usr SET added_via = $1, is_admin = $2, operator = $3 WHERE username = $4 AND workspace_id = $5",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Jsonb",
"Bool",
"Bool",
"Text",
"Text"
]
},
"nullable": []
},
"hash": "326fd614ebd965b9bb6f3e578f75a54d80812ff144e711100e6ac659785c991d"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM dependency_map WHERE workspace_id = 'test-workspace'",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "3c5b6001aac7fb58ec9bfad1bfd7418c16f96f307bafa926a18316055b7c90c4"
}

View File

@@ -1,101 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT\n c.id IS NOT NULL AS completed,\n CASE\n WHEN q.id IS NOT NULL THEN (CASE WHEN NOT $5 AND q.running THEN true ELSE null END)\n ELSE false\n END AS running,\n CASE WHEN $7::BOOLEAN THEN NULL ELSE SUBSTR(logs, GREATEST($1 - log_offset, 0)) END AS logs,\n SUBSTR(rs.stream, $8) AS new_result_stream,\n COALESCE(r.memory_peak, c.memory_peak) AS mem_peak,\n COALESCE(c.flow_status, f.flow_status) AS \"flow_status: sqlx::types::Json<Box<RawValue>>\",\n (COALESCE(c.flow_status, f.flow_status)->>'stream_job')::uuid AS stream_job,\n COALESCE(c.workflow_as_code_status, f.workflow_as_code_status) AS \"workflow_as_code_status: sqlx::types::Json<Box<RawValue>>\",\n CASE WHEN $7::BOOLEAN THEN NULL ELSE job_logs.log_offset + CHAR_LENGTH(job_logs.logs) + 1 END AS log_offset,\n CHAR_LENGTH(rs.stream) + 1 AS stream_offset,\n created_by AS \"created_by!\",\n CASE WHEN $4::BOOLEAN THEN (\n SELECT scalar_int FROM job_stats WHERE job_id = $3 AND metric_id = 'progress_perc'\n ) END AS progress,\n rs.stream AS \"result_stream: Option<String>\"\n FROM v2_job j\n LEFT JOIN v2_job_queue q USING (id)\n LEFT JOIN v2_job_runtime r USING (id)\n LEFT JOIN v2_job_status f USING (id)\n LEFT JOIN v2_job_completed c USING (id)\n LEFT JOIN job_result_stream rs ON rs.job_id = $3\n LEFT JOIN job_logs ON job_logs.job_id = $3\n WHERE j.workspace_id = $2 AND j.id = $3\n AND ($6::text[] IS NULL OR j.tag = ANY($6))",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "completed",
"type_info": "Bool"
},
{
"ordinal": 1,
"name": "running",
"type_info": "Bool"
},
{
"ordinal": 2,
"name": "logs",
"type_info": "Text"
},
{
"ordinal": 3,
"name": "new_result_stream",
"type_info": "Text"
},
{
"ordinal": 4,
"name": "mem_peak",
"type_info": "Int4"
},
{
"ordinal": 5,
"name": "flow_status: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
},
{
"ordinal": 6,
"name": "stream_job",
"type_info": "Uuid"
},
{
"ordinal": 7,
"name": "workflow_as_code_status: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
},
{
"ordinal": 8,
"name": "log_offset",
"type_info": "Int4"
},
{
"ordinal": 9,
"name": "stream_offset",
"type_info": "Int4"
},
{
"ordinal": 10,
"name": "created_by!",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "progress",
"type_info": "Int4"
},
{
"ordinal": 12,
"name": "result_stream: Option<String>",
"type_info": "Text"
}
],
"parameters": {
"Left": [
"Int4",
"Text",
"Uuid",
"Bool",
"Bool",
"TextArray",
"Bool",
"Int4"
]
},
"nullable": [
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
false,
null,
false
]
},
"hash": "40999264f09a781c4393b50c2c41ae5a5e64086198cb67aba72345bb3cdf7773"
}

View File

@@ -0,0 +1,49 @@
{
"db_name": "PostgreSQL",
"query": "\n WITH result_stream AS (\n SELECT \n string_agg(stream, '' order by idx asc) as stream, \n job_id, \n max(idx) + 1 as offset \n FROM job_result_stream_v2\n WHERE job_id = $2 AND idx >= $3\n GROUP BY job_id\n )\n SELECT\n COALESCE(jc.result, NULL) as \"result: sqlx::types::Json<Box<RawValue>>\",\n rs.stream AS \"result_stream: Option<String>\",\n rs.offset AS stream_offset,\n COALESCE(js.flow_status, jc.flow_status) as \"flow_status: sqlx::types::Json<Box<RawValue>>\",\n CASE WHEN $4 THEN NULL ELSE (COALESCE(js.flow_status, jc.flow_status)->>'stream_job')::uuid END as stream_job\n FROM (\n SELECT $2::uuid as job_id, $1::text as workspace_id\n ) base\n LEFT JOIN v2_job_completed jc ON jc.id = base.job_id AND jc.workspace_id = base.workspace_id\n LEFT JOIN v2_job_status js ON js.id = base.job_id\n LEFT JOIN result_stream rs ON rs.job_id = base.job_id\n WHERE base.job_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "result: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
},
{
"ordinal": 1,
"name": "result_stream: Option<String>",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "stream_offset",
"type_info": "Int4"
},
{
"ordinal": 3,
"name": "flow_status: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
},
{
"ordinal": 4,
"name": "stream_job",
"type_info": "Uuid"
}
],
"parameters": {
"Left": [
"Text",
"Uuid",
"Int4",
"Bool"
]
},
"nullable": [
null,
null,
null,
null,
null
]
},
"hash": "4b056d33215b3a1e9849bb66ce84e96c69d10e3970e38151c97d1fca0cb7388d"
}

View File

@@ -1,16 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO job_result_stream (workspace_id, job_id, stream)\n VALUES ($1, $2, $3)\n ON CONFLICT (job_id) DO UPDATE SET stream = job_result_stream.stream || $3\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Uuid",
"Text"
]
},
"nullable": []
},
"hash": "4bc533074c720820cebff8d97a203df52520b7606378ecca267e88383a45b49b"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE\n workspace_settings\n SET\n error_handler = NULL,\n error_handler_extra_args = NULL,\n error_handler_muted_on_cancel = NULL\n WHERE\n workspace_id = $1\n ",
"query": "\n UPDATE\n workspace_settings\n SET\n error_handler = NULL,\n error_handler_extra_args = NULL,\n error_handler_muted_on_cancel = false\n WHERE\n workspace_id = $1\n ",
"describe": {
"columns": [],
"parameters": {
@@ -10,5 +10,5 @@
},
"nullable": []
},
"hash": "0fa105c49c8345916716514444bd3616ae4d114216c659233fbbc3c047e6b30a"
"hash": "5ad2c883d26f39f3c141806428a329951ef19a1cb3e1b429fcd1abe0e2db45b5"
}

View File

@@ -0,0 +1,14 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM job_result_stream_v2 WHERE job_id = ANY($1)",
"describe": {
"columns": [],
"parameters": {
"Left": [
"UuidArray"
]
},
"nullable": []
},
"hash": "5adeb6989648ca42431c96069c4de88d2615e7e6f1267f2fb12ccc325d4e4148"
}

View File

@@ -0,0 +1,64 @@
{
"db_name": "PostgreSQL",
"query": "SELECT id, conversation_id, message_type as \"message_type: MessageType\", content, job_id, created_at\n FROM (\n SELECT id, conversation_id, message_type, content, job_id, created_at\n FROM flow_conversation_message\n WHERE conversation_id = $1\n ORDER BY created_at DESC, CASE WHEN message_type = 'user' THEN 0 ELSE 1 END\n LIMIT $2 OFFSET $3\n ) AS messages\n ORDER BY created_at ASC, CASE WHEN message_type = 'user' THEN 0 ELSE 1 END\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Uuid"
},
{
"ordinal": 1,
"name": "conversation_id",
"type_info": "Uuid"
},
{
"ordinal": 2,
"name": "message_type: MessageType",
"type_info": {
"Custom": {
"name": "message_type",
"kind": {
"Enum": [
"user",
"assistant"
]
}
}
}
},
{
"ordinal": 3,
"name": "content",
"type_info": "Text"
},
{
"ordinal": 4,
"name": "job_id",
"type_info": "Uuid"
},
{
"ordinal": 5,
"name": "created_at",
"type_info": "Timestamptz"
}
],
"parameters": {
"Left": [
"Uuid",
"Int8",
"Int8"
]
},
"nullable": [
false,
false,
false,
false,
true,
false
]
},
"hash": "5f57ec3330a6576f4017fd469848a1c214896dc5abbf2b898ac9a68810fd89dd"
}

View File

@@ -0,0 +1,20 @@
{
"db_name": "PostgreSQL",
"query": "SELECT value->>'ducklake_user_pg_pwd' FROM global_settings WHERE name = 'ducklake_settings';",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "?column?",
"type_info": "Text"
}
],
"parameters": {
"Left": []
},
"nullable": [
null
]
},
"hash": "5fdfc9427f455a4c1bc8f6ca41ddfd426bc0c2ac126792c926f3cf1182ded981"
}

View File

@@ -0,0 +1,27 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO flow_conversation_message (conversation_id, message_type, content, job_id)\n VALUES ($1, $2, $3, $4)",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Uuid",
{
"Custom": {
"name": "message_type",
"kind": {
"Enum": [
"user",
"assistant"
]
}
}
},
"Text",
"Uuid"
]
},
"nullable": []
},
"hash": "69606859fe08d24f0306b866f9f50ad766d56a0d5aa8f0784f79aa5e211b00e4"
}

View File

@@ -0,0 +1,62 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO flow_conversation (id, workspace_id, flow_path, created_by, title)\n VALUES ($1, $2, $3, $4, $5)\n RETURNING id, workspace_id, flow_path, title, created_at, updated_at, created_by",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Uuid"
},
{
"ordinal": 1,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "flow_path",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "title",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "created_at",
"type_info": "Timestamptz"
},
{
"ordinal": 5,
"name": "updated_at",
"type_info": "Timestamptz"
},
{
"ordinal": 6,
"name": "created_by",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Uuid",
"Varchar",
"Varchar",
"Varchar",
"Varchar"
]
},
"nullable": [
false,
false,
false,
true,
false,
false,
false
]
},
"hash": "6bd23a98838e3eec309e6b696edc776bd56fc9dae1238b3272557d1562400dbe"
}

View File

@@ -1,16 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM dependency_map\n WHERE importer_path = $1 AND importer_kind = $3::text::IMPORTER_KIND\n AND workspace_id = $2",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text",
"Text"
]
},
"nullable": []
},
"hash": "6c962f9471b0b1fe385a93789ec46bee53a07c8d1264eeb44bc94233bc06bbfd"
}

View File

@@ -0,0 +1,23 @@
{
"db_name": "PostgreSQL",
"query": "SELECT draft_only FROM script WHERE path = $1 AND workspace_id = $2 AND archived = false",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "draft_only",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
true
]
},
"hash": "71c945f93c0a1b561a85e8462b1687a54bd098cf6e84f57e5755eb84e1552345"
}

View File

@@ -0,0 +1,20 @@
{
"db_name": "PostgreSQL",
"query": "SELECT value->'instance_catalog_db_status' FROM global_settings WHERE name = 'ducklake_settings'",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "?column?",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": []
},
"nullable": [
null
]
},
"hash": "73c1c88bdf26ea0559b83314fed7a67d850e4e4dd60f4424ffb0b6f472acc8d5"
}

View File

@@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "SELECT (flow_status->>'memory_id')::uuid as memory_id \n FROM v2_job_status \n WHERE id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "memory_id",
"type_info": "Uuid"
}
],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": [
null
]
},
"hash": "7628e7690aaf6da3dba3cf78dc9e78fe32c3a001c08920e02fb850695afdb7ec"
}

View File

@@ -0,0 +1,28 @@
{
"db_name": "PostgreSQL",
"query": "SELECT path, hash FROM script WHERE workspace_id = $1 AND archived = false",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "hash",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
false
]
},
"hash": "79624ae15f909bd6ab4f015e32345bd1c24f93db32970d9c06623b1e335138ba"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT\n result AS \"result: sqlx::types::Json<Box<RawValue>>\",\n result_columns,\n status = 'success' AS \"success!\"\n FROM v2_job_completed\n WHERE id = $1 AND workspace_id = $2",
"query": "\n SELECT\n result AS \"result: sqlx::types::Json<Box<RawValue>>\",\n result_columns,\n status = 'success' AS \"success!\"\n FROM \n v2_job_completed\n WHERE \n id = $1 AND \n workspace_id = $2\n ",
"describe": {
"columns": [
{
@@ -31,5 +31,5 @@
null
]
},
"hash": "d6f62e25faf271876874fc09ee460313159bb6ad91227f5dec37cd28006e2add"
"hash": "79d6b757c9556cfcf0c98f52035b5f1a9036b6005764b79c415373a5d39c3211"
}

View File

@@ -0,0 +1,101 @@
{
"db_name": "PostgreSQL",
"query": "\n WITH result_stream AS (\n SELECT \n string_agg(stream, '' order by idx asc) as stream, \n job_id, \n max(idx) + 1 as offset \n FROM job_result_stream_v2\n WHERE job_id = $3 AND idx >= $8\n GROUP BY job_id\n )\n SELECT\n c.id IS NOT NULL AS completed,\n CASE\n WHEN q.id IS NOT NULL THEN (CASE WHEN NOT $5 AND q.running THEN true ELSE null END)\n ELSE false\n END AS running,\n CASE WHEN $7::BOOLEAN THEN NULL ELSE SUBSTR(logs, GREATEST($1 - log_offset, 0)) END AS logs,\n rs.stream AS new_result_stream,\n COALESCE(r.memory_peak, c.memory_peak) AS mem_peak,\n COALESCE(c.flow_status, f.flow_status) AS \"flow_status: sqlx::types::Json<Box<RawValue>>\",\n (COALESCE(c.flow_status, f.flow_status)->>'stream_job')::uuid AS stream_job,\n COALESCE(c.workflow_as_code_status, f.workflow_as_code_status) AS \"workflow_as_code_status: sqlx::types::Json<Box<RawValue>>\",\n CASE WHEN $7::BOOLEAN THEN NULL ELSE job_logs.log_offset + CHAR_LENGTH(job_logs.logs) + 1 END AS log_offset,\n rs.offset AS stream_offset,\n created_by AS \"created_by!\",\n CASE WHEN $4::BOOLEAN THEN (\n SELECT scalar_int FROM job_stats WHERE job_id = $3 AND metric_id = 'progress_perc'\n ) END AS progress,\n rs.stream AS \"result_stream: Option<String>\"\n FROM v2_job j\n LEFT JOIN v2_job_queue q USING (id)\n LEFT JOIN v2_job_runtime r USING (id)\n LEFT JOIN v2_job_status f USING (id)\n LEFT JOIN v2_job_completed c USING (id)\n LEFT JOIN result_stream rs ON rs.job_id = $3\n LEFT JOIN job_logs ON job_logs.job_id = $3\n WHERE j.workspace_id = $2 AND j.id = $3\n AND ($6::text[] IS NULL OR j.tag = ANY($6))",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "completed",
"type_info": "Bool"
},
{
"ordinal": 1,
"name": "running",
"type_info": "Bool"
},
{
"ordinal": 2,
"name": "logs",
"type_info": "Text"
},
{
"ordinal": 3,
"name": "new_result_stream",
"type_info": "Text"
},
{
"ordinal": 4,
"name": "mem_peak",
"type_info": "Int4"
},
{
"ordinal": 5,
"name": "flow_status: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
},
{
"ordinal": 6,
"name": "stream_job",
"type_info": "Uuid"
},
{
"ordinal": 7,
"name": "workflow_as_code_status: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
},
{
"ordinal": 8,
"name": "log_offset",
"type_info": "Int4"
},
{
"ordinal": 9,
"name": "stream_offset",
"type_info": "Int4"
},
{
"ordinal": 10,
"name": "created_by!",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "progress",
"type_info": "Int4"
},
{
"ordinal": 12,
"name": "result_stream: Option<String>",
"type_info": "Text"
}
],
"parameters": {
"Left": [
"Int4",
"Text",
"Uuid",
"Bool",
"Bool",
"TextArray",
"Bool",
"Int4"
]
},
"nullable": [
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
false,
null,
null
]
},
"hash": "7b524ee24bb78e494a93c5ea205259bd989a9d769a6a300d37ab116960438882"
}

View File

@@ -1,12 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "VACUUM v2_job, v2_job_completed, job_result_stream, job_stats, job_logs, concurrency_key, log_file, metrics",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "807c920bff25f56b10e88900d879cf5e8484c147e457044d6b075323b163ebaa"
}

View File

@@ -1,49 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT\n COALESCE(jc.result, NULL) as \"result: sqlx::types::Json<Box<RawValue>>\",\n SUBSTR(rs.stream, $3) AS \"result_stream: Option<String>\",\n CHAR_LENGTH(rs.stream) + 1 AS stream_offset,\n COALESCE(js.flow_status, jc.flow_status) as \"flow_status: sqlx::types::Json<Box<RawValue>>\",\n CASE WHEN $4 THEN NULL ELSE (COALESCE(js.flow_status, jc.flow_status)->>'stream_job')::uuid END as stream_job\n FROM (\n SELECT $2::uuid as job_id, $1::text as workspace_id\n ) base\n LEFT JOIN v2_job_completed jc ON jc.id = base.job_id AND jc.workspace_id = base.workspace_id\n LEFT JOIN v2_job_status js ON js.id = base.job_id\n LEFT JOIN job_result_stream rs ON rs.job_id = base.job_id\n WHERE base.job_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "result: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
},
{
"ordinal": 1,
"name": "result_stream: Option<String>",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "stream_offset",
"type_info": "Int4"
},
{
"ordinal": 3,
"name": "flow_status: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
},
{
"ordinal": 4,
"name": "stream_job",
"type_info": "Uuid"
}
],
"parameters": {
"Left": [
"Text",
"Uuid",
"Int4",
"Bool"
]
},
"nullable": [
null,
null,
null,
null,
null
]
},
"hash": "80809d397cf84f7278ebb276078871b371663257a127eb35512695c487066fd7"
}

View File

@@ -1,55 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT \n jc.result as \"result: sqlx::types::Json<Box<RawValue>>\",\n v2_job.tag,\n v2_job_queue.running as \"running: Option<bool>\",\n SUBSTR(rs.stream, $3) AS \"result_stream: Option<String>\",\n CHAR_LENGTH(rs.stream) AS stream_offset,\n CASE WHEN $4 THEN NULL ELSE (COALESCE(js.flow_status, jc.flow_status)->>'stream_job')::uuid END as stream_job\n FROM v2_job\n LEFT JOIN v2_job_queue USING (id)\n LEFT JOIN v2_job_completed jc USING (id)\n LEFT JOIN v2_job_status js USING (id)\n LEFT JOIN job_result_stream rs ON rs.job_id = $2\n WHERE v2_job.id = $2 AND v2_job.workspace_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "result: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
},
{
"ordinal": 1,
"name": "tag",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "running: Option<bool>",
"type_info": "Bool"
},
{
"ordinal": 3,
"name": "result_stream: Option<String>",
"type_info": "Text"
},
{
"ordinal": 4,
"name": "stream_offset",
"type_info": "Int4"
},
{
"ordinal": 5,
"name": "stream_job",
"type_info": "Uuid"
}
],
"parameters": {
"Left": [
"Text",
"Uuid",
"Int4",
"Bool"
]
},
"nullable": [
true,
false,
false,
null,
null,
null
]
},
"hash": "8126b118704341846e88bd289f1afe83c07b7a8b422f48022994370b3e433f34"
}

View File

@@ -0,0 +1,23 @@
{
"db_name": "PostgreSQL",
"query": "SELECT EXISTS(SELECT 1 FROM flow_conversation WHERE id = $1 AND workspace_id = $2)",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Uuid",
"Text"
]
},
"nullable": [
null
]
},
"hash": "81e997576319ae1d6d9a91f76465f6fa53892ff223f3b9d9ad3f4a1d2e720cc8"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "WITH inserted_job AS (\n INSERT INTO v2_job (id, workspace_id, raw_code, raw_lock, raw_flow, tag, parent_job,\n created_by, permissioned_as, runnable_id, runnable_path, args, kind, trigger,\n script_lang, same_worker, pre_run_error, permissioned_as_email, visible_to_owner,\n flow_innermost_root_job, root_job, concurrent_limit, concurrency_time_window_s, timeout, flow_step_id,\n cache_ttl, priority, trigger_kind, script_entrypoint_override, preprocessed)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18,\n $19, $20, $38, $21, $22, $23, $24, $25, $26, $39::job_trigger_kind,\n ($12::JSONB)->>'_ENTRYPOINT_OVERRIDE', $27)\n ),\n inserted_runtime AS (\n INSERT INTO v2_job_runtime (id, ping) VALUES ($1, null)\n ),\n inserted_job_perms AS (\n INSERT INTO job_perms (job_id, email, username, is_admin, is_operator, folders, groups, workspace_id) \n values ($1, $32, $33, $34, $35, $36, $37, $2) \n ON CONFLICT (job_id) DO UPDATE SET email = $32, username = $33, is_admin = $34, is_operator = $35, folders = $36, groups = $37, workspace_id = $2\n )\n INSERT INTO v2_job_queue\n (workspace_id, id, running, scheduled_for, started_at, tag, priority)\n VALUES ($2, $1, $28, COALESCE($29, now()), CASE WHEN $27 OR $40 THEN now() END, $30, $31)",
"query": "WITH inserted_job AS (\n INSERT INTO v2_job (id, workspace_id, raw_code, raw_lock, raw_flow, tag, parent_job,\n created_by, permissioned_as, runnable_id, runnable_path, args, kind, trigger,\n script_lang, same_worker, pre_run_error, permissioned_as_email, visible_to_owner,\n flow_innermost_root_job, root_job, concurrent_limit, concurrency_time_window_s, timeout, flow_step_id,\n cache_ttl, priority, trigger_kind, script_entrypoint_override, preprocessed)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18,\n $19, $20, $38, $21, $22, $23, $24, $25, $26, $39::job_trigger_kind,\n ($12::JSONB)->>'_ENTRYPOINT_OVERRIDE', $27)\n ),\n inserted_runtime AS (\n INSERT INTO v2_job_runtime (id, ping) VALUES ($1, null)\n ),\n inserted_job_perms AS (\n INSERT INTO job_perms (job_id, email, username, is_admin, is_operator, folders, groups, workspace_id, end_user_email) \n values ($1, $32, $33, $34, $35, $36, $37, $2, $41) \n ON CONFLICT (job_id) DO UPDATE SET email = $32, username = $33, is_admin = $34, is_operator = $35, folders = $36, groups = $37, workspace_id = $2\n )\n INSERT INTO v2_job_queue\n (workspace_id, id, running, scheduled_for, started_at, tag, priority)\n VALUES ($2, $1, $28, COALESCE($29, now()), CASE WHEN $27 OR $40 THEN now() END, $30, $31)",
"describe": {
"columns": [],
"parameters": {
@@ -123,10 +123,11 @@
}
}
},
"Bool"
"Bool",
"Varchar"
]
},
"nullable": []
},
"hash": "193d292c5ed44bf5266ad52c83704c3a36aa284fab3b7e638dbca12ac846b82b"
"hash": "8d67ed8e1271a27b072a8e8ae9973e372949f5ec7d71b80d1ba3eaddf851adce"
}

View File

@@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "SELECT EXISTS (SELECT 1 FROM pg_catalog.pg_database WHERE datname = $1)",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Name"
]
},
"nullable": [
null
]
},
"hash": "97e3a1439202e13e739ad2e3f22b3a21d0c9b0e57d7d35326753e8f6a804d4f8"
}

View File

@@ -0,0 +1,17 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO job_result_stream_v2 (workspace_id, job_id, stream, idx)\n VALUES (\n $1, \n $2,\n $3, \n $4\n )\n ON CONFLICT (job_id, idx) DO UPDATE SET stream = job_result_stream_v2.stream || $3\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Uuid",
"Text",
"Int4"
]
},
"nullable": []
},
"hash": "9bfc2a821b25641af48b0e3954163078922340294f1c6515400fb2c896666fde"
}

View File

@@ -0,0 +1,55 @@
{
"db_name": "PostgreSQL",
"query": "\n WITH result_stream AS (\n SELECT \n string_agg(stream, '' order by idx asc) as stream, \n job_id, \n max(idx) + 1 as offset \n FROM job_result_stream_v2\n WHERE job_id = $2 AND idx >= $3\n GROUP BY job_id\n )\n SELECT \n jc.result as \"result: sqlx::types::Json<Box<RawValue>>\",\n v2_job.tag,\n v2_job_queue.running as \"running: Option<bool>\",\n rs.stream AS \"result_stream: Option<String>\",\n rs.offset AS stream_offset,\n CASE WHEN $4 THEN NULL ELSE (COALESCE(js.flow_status, jc.flow_status)->>'stream_job')::uuid END as stream_job\n FROM v2_job\n LEFT JOIN v2_job_queue USING (id)\n LEFT JOIN v2_job_completed jc USING (id)\n LEFT JOIN v2_job_status js USING (id)\n LEFT JOIN result_stream rs ON rs.job_id = $2\n WHERE v2_job.id = $2 AND v2_job.workspace_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "result: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
},
{
"ordinal": 1,
"name": "tag",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "running: Option<bool>",
"type_info": "Bool"
},
{
"ordinal": 3,
"name": "result_stream: Option<String>",
"type_info": "Text"
},
{
"ordinal": 4,
"name": "stream_offset",
"type_info": "Int4"
},
{
"ordinal": 5,
"name": "stream_job",
"type_info": "Uuid"
}
],
"parameters": {
"Left": [
"Text",
"Uuid",
"Int4",
"Bool"
]
},
"nullable": [
true,
false,
false,
null,
null,
null
]
},
"hash": "9c0bbd44902d8eee393236f7c2372b273d14a093bb29ec12dda8bbfaecd49a35"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT workspace_id as workspace, path, summary, description, schema FROM script as o \n WHERE created_at = (select max(created_at) from script where o.path = path and workspace_id = $1 AND archived = false) \n AND workspace_id = $1 and archived = false",
"query": "SELECT workspace_id as workspace, path, summary, description, schema FROM script as o\n WHERE created_at = (select max(created_at) from script where o.path = path and workspace_id = $1 AND archived = false)\n AND workspace_id = $1 and archived = false",
"describe": {
"columns": [
{
@@ -42,5 +42,5 @@
true
]
},
"hash": "2d5f58dd2aff3bd49f3891ae76df23e2aa39891931516426f65b229314a0cee1"
"hash": "9c3ddb90295db7d6afcbdb077f017950620e753dde97c8d2d88cd60ff8c3f339"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO websocket_trigger (\n workspace_id,\n path,\n url,\n script_path,\n is_flow,\n enabled,\n filters,\n initial_messages,\n url_runnable_args,\n edited_by,\n can_return_message,\n email,\n edited_at,\n error_handler_path,\n error_handler_args,\n retry\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, now(), $13, $14, $15\n )\n ",
"query": "\n INSERT INTO websocket_trigger (\n workspace_id,\n path,\n url,\n script_path,\n is_flow,\n enabled,\n filters,\n initial_messages,\n url_runnable_args,\n edited_by,\n can_return_message,\n can_return_error_result,\n email,\n edited_at,\n error_handler_path,\n error_handler_args,\n retry\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, now(), $14, $15, $16\n )\n ",
"describe": {
"columns": [],
"parameters": {
@@ -16,6 +16,7 @@
"Jsonb",
"Varchar",
"Bool",
"Bool",
"Varchar",
"Varchar",
"Jsonb",
@@ -24,5 +25,5 @@
},
"nullable": []
},
"hash": "23eb4d45bf2df21e22fc6c9590b96b0a7dbdd27f85c7d886eded79b3af83731a"
"hash": "9ebf262393fc4a29e8f09b304dd99e786fe78dd21721e8f54dc943dd571a7e08"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT id, worker_group, event_type::text, desired_workers, reason, applied_at FROM autoscaling_event WHERE worker_group = $1 ORDER BY applied_at DESC LIMIT 5",
"query": "SELECT id, worker_group, event_type::text, desired_workers, reason, applied_at FROM autoscaling_event WHERE worker_group = $1 ORDER BY applied_at DESC LIMIT $2 OFFSET $3",
"describe": {
"columns": [
{
@@ -36,7 +36,9 @@
],
"parameters": {
"Left": [
"Text"
"Text",
"Int8",
"Int8"
]
},
"nullable": [
@@ -48,5 +50,5 @@
false
]
},
"hash": "6d134b137ae81534e145fc5b6474cf963ee26a3ad3a0a3d8dc064cb14c8fd9a6"
"hash": "a38df5d7dc4577c715d9acdaf87c38535ad388b1948a95efafd71135cfe5e3a6"
}

View File

@@ -1,49 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT\n COALESCE(jc.result, jc.result) as \"result: sqlx::types::Json<Box<RawValue>>\",\n jq.running as \"running: Option<bool>\",\n SUBSTR(rs.stream, $3) AS \"result_stream: Option<String>\",\n CHAR_LENGTH(rs.stream) + 1 AS stream_offset,\n CASE WHEN $4 THEN NULL ELSE (COALESCE(js.flow_status, jc.flow_status)->>'stream_job')::uuid END as stream_job\n FROM (\n SELECT $1::uuid as job_id, $2::text as workspace_id\n ) base\n LEFT JOIN v2_job_completed jc ON jc.id = base.job_id AND jc.workspace_id = base.workspace_id\n LEFT JOIN v2_job_queue jq ON jq.id = base.job_id AND jq.workspace_id = base.workspace_id\n LEFT JOIN v2_job_status js ON js.id = base.job_id\n LEFT JOIN job_result_stream rs ON rs.job_id = base.job_id\n WHERE base.job_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "result: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
},
{
"ordinal": 1,
"name": "running: Option<bool>",
"type_info": "Bool"
},
{
"ordinal": 2,
"name": "result_stream: Option<String>",
"type_info": "Text"
},
{
"ordinal": 3,
"name": "stream_offset",
"type_info": "Int4"
},
{
"ordinal": 4,
"name": "stream_job",
"type_info": "Uuid"
}
],
"parameters": {
"Left": [
"Uuid",
"Text",
"Int4",
"Bool"
]
},
"nullable": [
null,
false,
null,
null,
null
]
},
"hash": "a58a345f7082181f89e7f88929b7149791de48bc2e489edb55d63f67702cce05"
}

View File

@@ -0,0 +1,49 @@
{
"db_name": "PostgreSQL",
"query": "\n WITH result_stream AS (\n SELECT \n string_agg(stream, '' order by idx asc) as stream, \n job_id, \n max(idx) + 1 as offset \n FROM job_result_stream_v2\n WHERE job_id = $1 AND idx >= $3\n GROUP BY job_id\n )\n SELECT\n COALESCE(jc.result, jc.result) as \"result: sqlx::types::Json<Box<RawValue>>\",\n jq.running as \"running: Option<bool>\",\n rs.stream AS \"result_stream: Option<String>\",\n rs.offset AS stream_offset,\n CASE WHEN $4 THEN NULL ELSE (COALESCE(js.flow_status, jc.flow_status)->>'stream_job')::uuid END as stream_job\n FROM (\n SELECT $1::uuid as job_id, $2::text as workspace_id\n ) base\n LEFT JOIN v2_job_completed jc ON jc.id = base.job_id AND jc.workspace_id = base.workspace_id\n LEFT JOIN v2_job_queue jq ON jq.id = base.job_id AND jq.workspace_id = base.workspace_id\n LEFT JOIN v2_job_status js ON js.id = base.job_id\n LEFT JOIN result_stream rs ON rs.job_id = base.job_id\n WHERE base.job_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "result: sqlx::types::Json<Box<RawValue>>",
"type_info": "Jsonb"
},
{
"ordinal": 1,
"name": "running: Option<bool>",
"type_info": "Bool"
},
{
"ordinal": 2,
"name": "result_stream: Option<String>",
"type_info": "Text"
},
{
"ordinal": 3,
"name": "stream_offset",
"type_info": "Int4"
},
{
"ordinal": 4,
"name": "stream_job",
"type_info": "Uuid"
}
],
"parameters": {
"Left": [
"Uuid",
"Text",
"Int4",
"Bool"
]
},
"nullable": [
null,
false,
null,
null,
null
]
},
"hash": "a76eec5797ca8f97e63ed5542bf03873e7dfd1cf9fe984c769afb5a8bdb48d49"
}

View File

@@ -0,0 +1,17 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO app_bundles (app_version_id, w_id, file_type, data) VALUES ($1, $2, $3, $4)",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Int8",
"Varchar",
"Varchar",
"Bytea"
]
},
"nullable": []
},
"hash": "abaae3dde751a41b2dbb7856ece1c840d0ea8d59346ed9e88f6f609edb543d7e"
}

View File

@@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT ws.ducklake->'ducklakes' AS ducklake_name\n FROM workspace_settings ws\n WHERE ws.workspace_id = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "ducklake_name",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
null
]
},
"hash": "b344ba5a32ec873181390e205e16356f1b79bd994a4bd1a8655dbe17bd1e4a30"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE \n websocket_trigger\n SET\n url = $1,\n script_path = $2,\n path = $3,\n is_flow = $4,\n filters = $5,\n initial_messages = $6,\n url_runnable_args = $7,\n edited_by = $8,\n email = $9,\n can_return_message = $10,\n edited_at = now(),\n server_id = NULL,\n error = NULL,\n error_handler_path = $13,\n error_handler_args = $14,\n retry = $15\n WHERE\n workspace_id = $11 AND path = $12\n ",
"query": "\n UPDATE \n websocket_trigger\n SET\n url = $1,\n script_path = $2,\n path = $3,\n is_flow = $4,\n filters = $5,\n initial_messages = $6,\n url_runnable_args = $7,\n edited_by = $8,\n email = $9,\n can_return_message = $10,\n can_return_error_result = $11,\n edited_at = now(),\n server_id = NULL,\n error = NULL,\n error_handler_path = $14,\n error_handler_args = $15,\n retry = $16\n WHERE\n workspace_id = $12 AND path = $13\n ",
"describe": {
"columns": [],
"parameters": {
@@ -15,6 +15,7 @@
"Varchar",
"Varchar",
"Bool",
"Bool",
"Text",
"Text",
"Varchar",
@@ -24,5 +25,5 @@
},
"nullable": []
},
"hash": "35b211d19e53da4b64b0bd097284de3236ab939e47a1fc2b15ffc9607b552f8d"
"hash": "b5f6870444fc97d8beab3cf61c91e58936138d80a97b423c17338ba069b6a3aa"
}

View File

@@ -0,0 +1,14 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM job_result_stream_v2 WHERE job_id = $1",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": []
},
"hash": "bb46e5dcf5490ef3511faa131ad5693dedf34366e51044ddf30695995d194090"
}

View File

@@ -0,0 +1,14 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM autoscaling_event WHERE applied_at <= now() - ($1::bigint::text || ' s')::interval",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": []
},
"hash": "bd1b62a6435cfa7d8235bcb3cb104ef01831f400ba9bd1c3433412770d1d2a82"
}

View File

@@ -0,0 +1,14 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE flow_conversation SET updated_at = NOW() WHERE id = $1",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": []
},
"hash": "bdb1ece5c233f242cf341c089a2f2b785dfa5cc14d9be224c0707e10247ed8b7"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT workspace.id, workspace.name, usr.username, workspace_settings.color, workspace.parent_workspace_id,\n CASE WHEN usr.operator THEN workspace_settings.operator_settings ELSE NULL END as operator_settings\n FROM workspace\n JOIN usr ON usr.workspace_id = workspace.id\n JOIN workspace_settings ON workspace_settings.workspace_id = workspace.id\n WHERE usr.email = $1 AND workspace.deleted = false",
"query": "SELECT workspace.id, workspace.name, usr.username, workspace_settings.color, workspace.parent_workspace_id,\n CASE WHEN usr.operator THEN workspace_settings.operator_settings ELSE NULL END as operator_settings,\n usr.disabled\n FROM workspace\n JOIN usr ON usr.workspace_id = workspace.id\n JOIN workspace_settings ON workspace_settings.workspace_id = workspace.id\n WHERE usr.email = $1 AND workspace.deleted = false",
"describe": {
"columns": [
{
@@ -32,6 +32,11 @@
"ordinal": 5,
"name": "operator_settings",
"type_info": "Jsonb"
},
{
"ordinal": 6,
"name": "disabled",
"type_info": "Bool"
}
],
"parameters": {
@@ -45,8 +50,9 @@
false,
true,
true,
null
null,
false
]
},
"hash": "d0037961e8e787c4277afc3eb79f3b72e3323f878387de8b6fa31493f1215a77"
"hash": "c095a9658c542efc9f0255a1b536d2fd8a25fe4cd57c223db7d744493f8470c6"
}

View File

@@ -0,0 +1,59 @@
{
"db_name": "PostgreSQL",
"query": "SELECT id, workspace_id, flow_path, title, created_at, updated_at, created_by\n FROM flow_conversation\n WHERE id = $1 AND workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Uuid"
},
{
"ordinal": 1,
"name": "workspace_id",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "flow_path",
"type_info": "Varchar"
},
{
"ordinal": 3,
"name": "title",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "created_at",
"type_info": "Timestamptz"
},
{
"ordinal": 5,
"name": "updated_at",
"type_info": "Timestamptz"
},
{
"ordinal": 6,
"name": "created_by",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Uuid",
"Text"
]
},
"nullable": [
false,
false,
false,
true,
false,
false,
false
]
},
"hash": "c383cc023714b361d10c10e8fef1fc148ab1da942951ee9ffdddaecee76a6be9"
}

View File

@@ -0,0 +1,29 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT \n string_agg(stream, '' order by idx asc) as stream, \n max(idx) + 1 as offset \n FROM job_result_stream_v2\n WHERE job_id = $2 AND idx >= $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "stream",
"type_info": "Text"
},
{
"ordinal": 1,
"name": "offset",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Int4",
"Uuid"
]
},
"nullable": [
null,
null
]
},
"hash": "dd92bce0ddbfbf06834807aab4d589fc104647cae7abf37ddce3ef7109726261"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT tag, dedicated_worker, flow_version.value->>'early_return' as early_return, flow_version.value->>'preprocessor_module' IS NOT NULL as has_preprocessor, on_behalf_of_email, edited_by, flow_version.id AS version\n FROM flow\n INNER JOIN flow_version\n ON flow_version.id = $3\n WHERE flow.path = $1 and flow.workspace_id = $2",
"query": "SELECT tag, dedicated_worker, flow_version.value->>'early_return' as early_return, flow_version.value->>'preprocessor_module' IS NOT NULL as has_preprocessor, (flow_version.value->>'chat_input_enabled')::boolean as chat_input_enabled, on_behalf_of_email, edited_by, flow_version.id AS version\n FROM flow\n INNER JOIN flow_version\n ON flow_version.id = $3\n WHERE flow.path = $1 and flow.workspace_id = $2",
"describe": {
"columns": [
{
@@ -25,16 +25,21 @@
},
{
"ordinal": 4,
"name": "chat_input_enabled",
"type_info": "Bool"
},
{
"ordinal": 5,
"name": "on_behalf_of_email",
"type_info": "Text"
},
{
"ordinal": 5,
"ordinal": 6,
"name": "edited_by",
"type_info": "Varchar"
},
{
"ordinal": 6,
"ordinal": 7,
"name": "version",
"type_info": "Int8"
}
@@ -51,10 +56,11 @@
true,
null,
null,
null,
true,
false,
false
]
},
"hash": "9b60fa8a1003015bc5a7cdbee9a4486b313d45347dfd9d4793d60e2760763ca3"
"hash": "e1409c67b93881cf68f6ac9c8bae0856cf426c7e7860c8b5b799972baa8e6945"
}

View File

@@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "SELECT EXISTS(SELECT 1 FROM flow_conversation_message WHERE job_id = $1 AND message_type = 'assistant')",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": [
null
]
},
"hash": "e2f4eeb896c22e3215370ed30ed5cc890503e4197b0fdb3a906504eba166aa97"
}

View File

@@ -1,18 +1,18 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO dependency_map (workspace_id, importer_path, importer_kind, imported_path, importer_node_id)\n VALUES ($1, $2, $4::text::IMPORTER_KIND, $3, $5) ON CONFLICT DO NOTHING",
"query": "INSERT INTO dependency_map (workspace_id, importer_path, importer_kind, imported_path, importer_node_id)\n VALUES ($1, $2, $3::text::IMPORTER_KIND, $4, $5) ON CONFLICT DO NOTHING",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Varchar",
"Text",
"Varchar",
"Varchar"
]
},
"nullable": []
},
"hash": "958ed17dafffdd37e636ccd244dc4ca60cbf562e6f6a371d5f9a9943fb30254c"
"hash": "e32d6c6ae4e0d824c4cf19128182d67f36d1fd87fe4cf4f002e18367088c497c"
}

View File

@@ -0,0 +1,15 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM flow_conversation WHERE id = $1 AND workspace_id = $2",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Uuid",
"Text"
]
},
"nullable": []
},
"hash": "e6c4454e552dc82db1af2d6b887ebb4b78eb58600cc21e3ffb12dd9e5a0a6f08"
}

View File

@@ -0,0 +1,18 @@
{
"db_name": "PostgreSQL",
"query": "\n DELETE FROM dependency_map\n WHERE workspace_id = $1\n AND importer_path = $2\n AND importer_kind = $3::text::IMPORTER_KIND\n AND importer_node_id = $4\n AND imported_path = $5\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text",
"Text",
"Text",
"Text",
"Text"
]
},
"nullable": []
},
"hash": "ead84a63cb965e36155605434c9e3670e50344f39b0d61eef8e60c2cdb57ae1f"
}

View File

@@ -0,0 +1,41 @@
{
"db_name": "PostgreSQL",
"query": "SELECT email, is_admin, operator, added_via FROM usr WHERE username = $1 AND workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "is_admin",
"type_info": "Bool"
},
{
"ordinal": 2,
"name": "operator",
"type_info": "Bool"
},
{
"ordinal": 3,
"name": "added_via",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
false,
false,
false,
true
]
},
"hash": "eb110e722ba8ac32d9d69010dc7e5f5763c55a5ac255f939f1fda8d3f9200f8d"
}

View File

@@ -0,0 +1,20 @@
{
"db_name": "PostgreSQL",
"query": "SELECT value::text FROM app_version WHERE id = 0 AND app_id = 2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "value",
"type_info": "Text"
}
],
"parameters": {
"Left": []
},
"nullable": [
null
]
},
"hash": "f03d52c091d10d27a274cebaf370a4665a518da0560fd9ed7add05c66da3898f"
}

View File

@@ -1,29 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT SUBSTR(rs.stream, $1) AS new_result_stream, CHAR_LENGTH(rs.stream) + 1 AS stream_offset FROM job_result_stream rs WHERE rs.job_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "new_result_stream",
"type_info": "Text"
},
{
"ordinal": 1,
"name": "stream_offset",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Int4",
"Uuid"
]
},
"nullable": [
null,
null
]
},
"hash": "f17f914d2522bf7cb5de9d7ba5557ee0dce940039ab42fd39bf079d87b6cad8a"
}

View File

@@ -0,0 +1,15 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE v2_job_status \n SET flow_status = jsonb_set(\n flow_status,\n '{memory_id}',\n to_jsonb($2::uuid)\n )\n WHERE id = $1",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Uuid",
"Uuid"
]
},
"nullable": []
},
"hash": "f5568a691ec5931634cf986f806f5eae7bb8ed0f5c6e54ca3f49a991c53ed50d"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "PostgreSQL",
"query": "VACUUM v2_job, v2_job_completed, job_result_stream_v2, job_stats, job_logs, concurrency_key, log_file, metrics",
"describe": {
"columns": [],
"parameters": {
"Left": []
},
"nullable": []
},
"hash": "f8ac5379ecfbff7b8ae75c821680737b249a64c8d9e8f7dbcc46fce98e874571"
}

View File

@@ -0,0 +1,23 @@
{
"db_name": "PostgreSQL",
"query": "SELECT app.versions[array_upper(app.versions, 1)] FROM app\n WHERE app.path = $1 AND app.workspace_id = $2",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "versions",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
null
]
},
"hash": "fad966db585b91c9ce143c9aa26a826aec1ddb193a7f4988c5f12b1a2d8ce071"
}

View File

@@ -0,0 +1,28 @@
{
"db_name": "PostgreSQL",
"query": "SELECT path, versions[array_upper(versions, 1)] as version FROM app WHERE workspace_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "path",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "version",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
null
]
},
"hash": "fd403acc343182fdab100263f8ef8067c1b43a97ea96845d92e2cbf85fbd6311"
}

View File

@@ -0,0 +1,14 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE global_settings SET value = jsonb_set(value, '{instance_catalog_db_status}', (COALESCE(value->'instance_catalog_db_status', '{}'::jsonb) || to_jsonb($1::json))) WHERE name = 'ducklake_settings'",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Json"
]
},
"nullable": []
},
"hash": "fd55112d55995ab08d2c275aa6430cdec1cacebdf2f2b3dd6f678b434643eb50"
}

733
backend/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[package]
name = "windmill"
version = "1.545.0"
version = "1.555.2"
authors.workspace = true
edition.workspace = true
@@ -34,7 +34,7 @@ members = [
exclude = ["./windmill-duckdb-ffi-internal"]
[workspace.package]
version = "1.545.0"
version = "1.555.2"
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
edition = "2021"
@@ -207,7 +207,7 @@ reqwest-middleware = { version = "^0", features = ["json"] }
bitflags = "2.9.4"
memchr = "2.7.4"
axum = { version = "^0.7", features = ["multipart"] }
axum = { version = "^0.7", features = ["multipart", "macros"] }
headers = "^0"
hyper = { version = "^1", features = ["full"] }
tokio = { version = "=1.46.1", features = ["full", "tracing", "time"] }

View File

@@ -1,8 +1,8 @@
#!/bin/bash
# This script outputs all features except private. Usage :
# > cargo build --features $(./all_features_oss.sh)
#!/bin/bash
# Path to the Cargo.toml file
CARGO_TOML_PATH="./Cargo.toml"

View File

@@ -1 +1 @@
aa4c7936b99d0de2f7af31cde79dfc7b1b482c29
33bdef405c678616b12084cf779a68a62d1f477e

View File

@@ -0,0 +1,2 @@
-- Add down migration script here
ALTER TABLE websocket_trigger DROP COLUMN can_return_error_result;

View File

@@ -0,0 +1,2 @@
-- Add up migration script here
ALTER TABLE websocket_trigger ADD COLUMN can_return_error_result BOOLEAN NOT NULL DEFAULT FALSE;

View File

@@ -0,0 +1,4 @@
-- Add down migration script here
DROP TABLE job_result_stream_v2;
ALTER TABLE job_result_stream ADD CONSTRAINT fk_job_result_stream_job_id FOREIGN KEY (job_id) REFERENCES v2_job_queue(id) ON DELETE CASCADE;

View File

@@ -0,0 +1,13 @@
-- Add up migration script here
CREATE TABLE job_result_stream_v2 (
job_id UUID NOT NULL,
workspace_id TEXT NOT NULL,
stream TEXT NOT NULL,
idx INT NOT NULL,
PRIMARY KEY (job_id, idx)
);
GRANT ALL ON TABLE job_result_stream_v2 TO windmill_admin;
GRANT ALL ON TABLE job_result_stream_v2 TO windmill_user;
ALTER TABLE job_result_stream DROP CONSTRAINT fk_job_result_stream_job_id;

View File

@@ -0,0 +1,12 @@
-- Add down migration script here
-- Drop indexes
DROP INDEX IF EXISTS idx_conversation_message_conversation_time;
DROP INDEX IF EXISTS idx_flow_conversation_workspace_path;
-- Drop tables (order matters due to foreign keys)
DROP TABLE IF EXISTS flow_conversation_message;
DROP TABLE IF EXISTS flow_conversation;
-- Drop enum
DROP TYPE IF EXISTS MESSAGE_TYPE;

View File

@@ -0,0 +1,57 @@
-- Add up migration script here
-- Create message_type enum
CREATE TYPE MESSAGE_TYPE AS ENUM ('user', 'assistant');
-- Create flow_conversation table
CREATE TABLE flow_conversation (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
workspace_id VARCHAR(50) NOT NULL REFERENCES workspace(id),
flow_path VARCHAR(255) NOT NULL,
title VARCHAR(255),
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
created_by VARCHAR(50) NOT NULL
);
-- Create flow_conversation_message table
CREATE TABLE flow_conversation_message (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
conversation_id UUID NOT NULL REFERENCES flow_conversation(id) ON DELETE CASCADE,
message_type MESSAGE_TYPE NOT NULL,
content TEXT NOT NULL,
job_id UUID REFERENCES v2_job(id) ON DELETE CASCADE,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);
-- Basic indexes for performance
CREATE INDEX idx_flow_conversation_workspace_path ON flow_conversation(workspace_id, flow_path, updated_at DESC);
CREATE INDEX idx_conversation_message_conversation_time ON flow_conversation_message(conversation_id, created_at DESC);
-- Grant permissions
GRANT ALL ON flow_conversation TO windmill_admin;
GRANT ALL ON flow_conversation TO windmill_user;
GRANT ALL ON flow_conversation_message TO windmill_admin;
GRANT ALL ON flow_conversation_message TO windmill_user;
-- RLS policies
ALTER TABLE flow_conversation ENABLE ROW LEVEL SECURITY;
ALTER TABLE flow_conversation_message ENABLE ROW LEVEL SECURITY;
-- Admin policies - admins can access all conversations
CREATE POLICY admin_policy ON flow_conversation FOR ALL TO windmill_admin USING (true);
CREATE POLICY admin_policy ON flow_conversation_message FOR ALL TO windmill_admin USING (true);
-- User policies - users can only access their own conversations
CREATE POLICY see_own ON flow_conversation FOR ALL TO windmill_user
USING (flow_conversation.created_by = current_setting('session.user'));
-- Users can see messages of conversations they own
CREATE POLICY see_own ON flow_conversation_message FOR ALL TO windmill_user
USING (
EXISTS (
SELECT 1 FROM flow_conversation
WHERE flow_conversation.id = flow_conversation_message.conversation_id
AND flow_conversation.created_by = current_setting('session.user')
)
);

View File

@@ -0,0 +1,2 @@
-- Add down migration script here
DROP TABLE app_bundles;

View File

@@ -0,0 +1,8 @@
-- Add up migration script here
CREATE TABLE app_bundles (
app_version_id BIGINT NOT NULL,
w_id VARCHAR(255) NOT NULL,
file_type VARCHAR(10) NOT NULL,
data BYTEA NOT NULL,
PRIMARY KEY (app_version_id, file_type)
);

View File

@@ -0,0 +1,2 @@
-- Add down migration script here
ALTER TABLE job_perms DROP COLUMN end_user_email;

View File

@@ -0,0 +1,2 @@
-- Add up migration script here
ALTER TABLE job_perms ADD COLUMN end_user_email VARCHAR(255);

View File

@@ -0,0 +1,6 @@
INSERT INTO global_settings (name, value) VALUES (
'ducklake_user_pg_pwd',
(SELECT g2.value->'ducklake_user_pg_pwd' FROM global_settings g2 WHERE g2.name = 'ducklake_settings')
);
DELETE FROM global_settings WHERE name = 'ducklake_settings';

View File

@@ -0,0 +1,9 @@
INSERT INTO global_settings (name, value) VALUES (
'ducklake_settings',
(SELECT json_build_object(
'ducklake_user_pg_pwd', g2.value,
'instance_catalog_db_status', '{}'::json
) FROM global_settings g2 WHERE g2.name = 'ducklake_user_pg_pwd')
);
DELETE FROM global_settings WHERE name = 'ducklake_user_pg_pwd';

View File

@@ -10,7 +10,7 @@ use regex_lite::Regex;
use serde_json::json;
use std::{collections::HashMap, str::FromStr};
use windmill_parser::{Arg, MainArgSignature, Typ};
use windmill_parser::{Arg, MainArgSignature, ObjectType, Typ};
pub fn parse_bash_sig(code: &str) -> anyhow::Result<MainArgSignature> {
let parsed = parse_bash_file(&code)?;
@@ -48,7 +48,7 @@ lazy_static::lazy_static! {
static ref RE_BASH: Regex = Regex::new(r#"(?m)^(\w+)="\$(?:(\d+)|\{(\d+)\}|\{(\d+):-(.*)\})"(?:[\t ]*)?(?:#.*)?$"#).unwrap();
pub static ref RE_POWERSHELL_PARAM: Regex = Regex::new(r#"(?m)param[\t ]*\(([^)]*)\)"#).unwrap();
static ref RE_POWERSHELL_ARGS: Regex = Regex::new(r#"(?:\[(\w+)\])?\$(\w+)[\t ]*(?:=[\t ]*(?:(?:(?:"|')([^"\n\r\$]*)(?:"|'))|([\d.]+)))?"#).unwrap();
static ref RE_POWERSHELL_ARGS: Regex = Regex::new(r#"(?:\[([\w\[\]]+)\])?\$(\w+)[\t ]*(?:=[\t ]*(?:(?:(?:"|')([^"\n\r\$]*)(?:"|'))|([\d.]+)))?"#).unwrap();
}
fn parse_bash_file(code: &str) -> anyhow::Result<Option<Vec<Arg>>> {
@@ -124,6 +124,18 @@ fn split_pwsh_args(code: &str) -> Vec<&str> {
splits
}
fn parse_powershell_single_typ(typ: &str) -> Typ {
match typ.to_lowercase().as_str() {
"string" => Typ::Str(None),
"int" | "long" => Typ::Int,
"decimal" | "double" | "single" => Typ::Float,
"datetime" => Typ::Datetime,
"bool" => Typ::Bool,
"pscustomobject" => Typ::Object(ObjectType::new(None, None)),
_ => Typ::Str(None),
}
}
fn parse_powershell_file(code: &str) -> anyhow::Result<Option<Vec<Arg>>> {
let param_wrapper = RE_POWERSHELL_PARAM.captures(code);
let mut args = vec![];
@@ -136,12 +148,12 @@ fn parse_powershell_file(code: &str) -> anyhow::Result<Option<Vec<Arg>>> {
let name = cap.get(2).unwrap().as_str().to_string();
let mut parsed_typ = if let Some(typ) = typ {
match typ.as_str() {
"string" => Some(Typ::Str(None)),
"int" | "long" => Some(Typ::Int),
"decimal" | "double" | "single" => Some(Typ::Float),
"datetime" | "DateTime" => Some(Typ::Datetime),
_ => None,
if typ.as_str().ends_with("[]") {
Some(Typ::List(Box::new(parse_powershell_single_typ(
typ.as_str().strip_suffix("[]").unwrap(),
))))
} else {
Some(parse_powershell_single_typ(typ.as_str()))
}
} else {
None
@@ -254,7 +266,7 @@ non_required="${5:-}"
#[test]
fn test_parse_powershell_sig() -> anyhow::Result<()> {
let code = r#"param($Msg, [string]$Msg2, $Dflt = "default value, with comma", [int]$Nb = 3 , $Nb2 = 5.0, $Nb3 = 5, $Wahoo = $env:WAHOO)"#;
let code = r#"param($Msg, [string]$Msg2, $Dflt = "default value, with comma", [int]$Nb = 3 , $Nb2 = 5.0, $Nb3 = 5, $Wahoo = $env:WAHOO, [PSCustomObject]$Obj, [string[]]$Arr)"#;
assert_eq!(
parse_powershell_sig(code)?,
MainArgSignature {
@@ -316,6 +328,22 @@ non_required="${5:-}"
default: None,
has_default: false,
oidx: None
},
Arg {
otyp: None,
name: "Obj".to_string(),
typ: Typ::Object(ObjectType::new(None, None)),
default: None,
has_default: false,
oidx: None
},
Arg {
otyp: None,
name: "Arr".to_string(),
typ: Typ::List(Box::new(Typ::Str(None))),
default: None,
has_default: false,
oidx: None
}
],
no_main_func: None,

View File

@@ -2,6 +2,7 @@
use anyhow::anyhow;
use lazy_static::lazy_static;
#[cfg(not(target_arch = "wasm32"))]
use regex::Regex;
#[cfg(target_arch = "wasm32")]
@@ -491,13 +492,15 @@ fn parse_pg_file(code: &str) -> anyhow::Result<Option<Vec<Arg>>> {
let mut args = vec![];
let mut hm: HashMap<i32, String> = HashMap::new();
for cap in RE_CODE_PGSQL.captures_iter(code) {
let typ = cap
.get(2)
.map(|cap| transform_types_with_spaces(&cap, &code))
.unwrap_or("text");
hm.insert(
cap.get(1)
.and_then(|x| x.as_str().parse::<i32>().ok())
.ok_or_else(|| anyhow!("Impossible to parse arg digit"))?,
cap.get(2)
.map(|x| x.as_str().to_string())
.unwrap_or_else(|| "text".to_string()),
typ.to_string(),
);
}
for (i, v) in hm.iter() {
@@ -543,6 +546,37 @@ fn parse_pg_file(code: &str) -> anyhow::Result<Option<Vec<Arg>>> {
Ok(Some(args))
}
// The regex doesn't parse types with space such as "character varying"
// So we look for them manually and replace them with their shorter counterpart
fn transform_types_with_spaces<'a>(cap: &regex::Match<'a>, code: &str) -> &'a str {
lazy_static! {
static ref TYPES: [(&'static str, &'static str); 6] = [
("character varying", "varchar"),
("double precision", "double"),
("time with time zone", "timetz"),
("time without time zone", "time"),
("timestamp with time zone", "timestamptz"),
("timestamp without time zone", "timestamp"),
];
}
let typ = &code[cap.start()..];
for (long_type, alias) in TYPES.iter() {
let mut typ = typ;
let mut found_mismatch = false;
for token in long_type.split(' ') {
if typ.len() < token.len() || !typ[..token.len()].eq_ignore_ascii_case(token) {
found_mismatch = true;
break;
}
typ = typ[token.len()..].trim_start();
}
if !found_mismatch {
return alias;
}
}
cap.as_str()
}
pub fn parse_sql_statement_named_params(code: &str, prefix: char) -> HashSet<String> {
let mut arg_names = HashSet::new();
run_on_sql_statement_matches(

View File

@@ -10,9 +10,10 @@ use monitor::{
load_base_url, load_otel, reload_critical_alerts_on_db_oversize,
reload_delete_logs_periodically_setting, reload_indexer_config,
reload_instance_python_version_setting, reload_maven_repos_setting,
reload_no_default_maven_setting, reload_nuget_config_setting, reload_ruby_repos_setting,
reload_timeout_wait_result_setting, send_current_log_file_to_object_store,
send_logs_to_object_store, WORKERS_NAMES,
reload_no_default_maven_setting, reload_nuget_config_setting,
reload_powershell_repo_pat_setting, reload_powershell_repo_url_setting,
reload_ruby_repos_setting, reload_timeout_wait_result_setting,
send_current_log_file_to_object_store, send_logs_to_object_store, WORKERS_NAMES,
};
use rand::Rng;
use sqlx::postgres::PgListener;
@@ -45,7 +46,8 @@ use windmill_common::{
JOB_DEFAULT_TIMEOUT_SECS_SETTING, JWT_SECRET_SETTING, KEEP_JOB_DIR_SETTING,
LICENSE_KEY_SETTING, MAVEN_REPOS_SETTING, MONITOR_LOGS_ON_OBJECT_STORE_SETTING,
NO_DEFAULT_MAVEN_SETTING, NPM_CONFIG_REGISTRY_SETTING, NUGET_CONFIG_SETTING, OAUTH_SETTING,
OTEL_SETTING, PIP_INDEX_URL_SETTING, REQUEST_SIZE_LIMIT_SETTING,
OTEL_SETTING, PIP_INDEX_URL_SETTING, POWERSHELL_REPO_PAT_SETTING,
POWERSHELL_REPO_URL_SETTING, REQUEST_SIZE_LIMIT_SETTING,
REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RETENTION_PERIOD_SECS_SETTING,
RUBY_REPOS_SETTING, SAML_METADATA_SETTING, SCIM_TOKEN_SETTING, SMTP_SETTING, TEAMS_SETTING,
TIMEOUT_WAIT_RESULT_SETTING,
@@ -1054,6 +1056,12 @@ Windmill Community Edition {GIT_VERSION}
NUGET_CONFIG_SETTING => {
reload_nuget_config_setting(&conn).await
},
POWERSHELL_REPO_URL_SETTING => {
reload_powershell_repo_url_setting(&conn).await
},
POWERSHELL_REPO_PAT_SETTING => {
reload_powershell_repo_pat_setting(&conn).await
},
MAVEN_REPOS_SETTING => {
reload_maven_repos_setting(&conn).await
},
@@ -1295,7 +1303,6 @@ Windmill Community Edition {GIT_VERSION}
}
}
std::process::exit(0);
Ok(())
}
async fn listen_pg(url: &str) -> Option<PgListener> {

View File

@@ -53,7 +53,8 @@ use windmill_common::{
HUB_BASE_URL_SETTING, INSTANCE_PYTHON_VERSION_SETTING, JOB_DEFAULT_TIMEOUT_SECS_SETTING,
JWT_SECRET_SETTING, KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING,
MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NPM_CONFIG_REGISTRY_SETTING, NUGET_CONFIG_SETTING,
OTEL_SETTING, PIP_INDEX_URL_SETTING, REQUEST_SIZE_LIMIT_SETTING,
OTEL_SETTING, PIP_INDEX_URL_SETTING, POWERSHELL_REPO_PAT_SETTING,
POWERSHELL_REPO_URL_SETTING, REQUEST_SIZE_LIMIT_SETTING,
REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RETENTION_PERIOD_SECS_SETTING,
SAML_METADATA_SETTING, SCIM_TOKEN_SETTING, TIMEOUT_WAIT_RESULT_SETTING,
},
@@ -83,7 +84,8 @@ use windmill_queue::{cancel_job, MiniPulledJob, SameWorkerPayload};
use windmill_worker::{
handle_job_error, JobCompletedSender, SameWorkerSender, BUNFIG_INSTALL_SCOPES,
INSTANCE_PYTHON_VERSION, JOB_DEFAULT_TIMEOUT, KEEP_JOB_DIR, MAVEN_REPOS, NO_DEFAULT_MAVEN,
NPM_CONFIG_REGISTRY, NUGET_CONFIG, PIP_EXTRA_INDEX_URL, PIP_INDEX_URL,
NPM_CONFIG_REGISTRY, NUGET_CONFIG, PIP_EXTRA_INDEX_URL, PIP_INDEX_URL, POWERSHELL_REPO_PAT,
POWERSHELL_REPO_URL,
};
#[cfg(feature = "parquet")]
@@ -298,6 +300,8 @@ pub async fn initial_load(
reload_bunfig_install_scopes_setting(&conn).await;
reload_instance_python_version_setting(&conn).await;
reload_nuget_config_setting(&conn).await;
reload_powershell_repo_url_setting(&conn).await;
reload_powershell_repo_pat_setting(&conn).await;
reload_maven_repos_setting(&conn).await;
reload_no_default_maven_setting(&conn).await;
reload_ruby_repos_setting(&conn).await;
@@ -867,6 +871,16 @@ pub async fn delete_expired_items(db: &DB) -> () {
tracing::error!("Error deleting audit log on CE: {:?}", e);
}
if let Err(e) = sqlx::query_scalar!(
"DELETE FROM autoscaling_event WHERE applied_at <= now() - ($1::bigint::text || ' s')::interval",
30 * 24 * 60 * 60, // 30 days
)
.fetch_all(db)
.await
{
tracing::error!("Error deleting autoscaling event on CE: {:?}", e);
}
match sqlx::query_scalar!(
"DELETE FROM agent_token_blacklist WHERE expires_at <= now() RETURNING token",
)
@@ -950,6 +964,17 @@ pub async fn delete_expired_items(db: &DB) -> () {
{
tracing::error!("Error deleting job: {:?}", e);
}
// should already be deleted but just in case
if let Err(e) = sqlx::query!(
"DELETE FROM job_result_stream_v2 WHERE job_id = ANY($1)",
&deleted_jobs
)
.execute(&mut *tx)
.await
{
tracing::error!("Error deleting job result stream: {:?}", e);
}
}
}
Err(e) => {
@@ -1104,6 +1129,26 @@ pub async fn reload_nuget_config_setting(conn: &Connection) {
.await;
}
pub async fn reload_powershell_repo_url_setting(conn: &Connection) {
reload_option_setting_with_tracing(
conn,
POWERSHELL_REPO_URL_SETTING,
"POWERSHELL_REPO_URL",
POWERSHELL_REPO_URL.clone(),
)
.await;
}
pub async fn reload_powershell_repo_pat_setting(conn: &Connection) {
reload_option_setting_with_tracing(
conn,
POWERSHELL_REPO_PAT_SETTING,
"POWERSHELL_REPO_PAT",
POWERSHELL_REPO_PAT.clone(),
)
.await;
}
pub async fn reload_maven_repos_setting(conn: &Connection) {
reload_option_setting_with_tracing(
conn,
@@ -1654,7 +1699,7 @@ pub async fn monitor_db(
}
async fn vacuuming_tables(db: &Pool<Postgres>) -> error::Result<()> {
sqlx::query!("VACUUM v2_job, v2_job_completed, job_result_stream, job_stats, job_logs, concurrency_key, log_file, metrics")
sqlx::query!("VACUUM v2_job, v2_job_completed, job_result_stream_v2, job_stats, job_logs, concurrency_key, log_file, metrics")
.execute(db)
.await?;
Ok(())

View File

@@ -156,6 +156,7 @@ impl RunJob {
None,
None,
false,
None,
)
.await
.expect("push has to succeed");

File diff suppressed because one or more lines are too long

View File

@@ -22,7 +22,6 @@ def main():
'',
'f/system_relative/different_folder_script', 12347, 'python3', '');
INSERT INTO public.script(workspace_id, created_by, content, schema, summary, description, path, hash, language, lock) VALUES (
'test-workspace',
'test-user',
@@ -38,4 +37,4 @@ def main():
'{"$schema":"https://json-schema.org/draft/2020-12/schema","properties":{},"required":[],"type":"object"}',
'',
'',
'f/system_relative/nested_script', 12348, 'python3', '');
'f/system_relative/nested_script', 12348, 'python3', '');

View File

@@ -1,8 +1,8 @@
mod common;
use crate::common::*;
use sqlx::Pool;
use sqlx::postgres::Postgres;
use windmill_common::scripts::{ ScriptLang};
use sqlx::Pool;
use windmill_common::scripts::ScriptLang;
#[cfg(feature = "python")]
#[sqlx::test(fixtures("base", "lockfile_python"))]
@@ -162,7 +162,6 @@ use windmill_common::jobs::RawCode;
#[cfg(feature = "python")]
#[sqlx::test(fixtures("base"))]
async fn test_python_job(db: Pool<Postgres>) -> anyhow::Result<()> {
initialize_tracing().await;
let server = ApiServer::start(db.clone()).await?;
let port = server.addr.port();
@@ -211,7 +210,6 @@ async fn test_python_global_site_packages(db: Pool<Postgres>) -> anyhow::Result<
// 3.12
{
let content = r#"# py: ==3.12
#requirements:
#
@@ -355,7 +353,6 @@ def main():
Ok(())
}
#[cfg(feature = "python")]
#[sqlx::test(fixtures("base", "relative_python"))]
async fn test_relative_imports_python(db: Pool<Postgres>) -> anyhow::Result<()> {
@@ -391,4 +388,3 @@ def main():
run_preview_relative_imports(&db, content, ScriptLang::Python3).await?;
Ok(())
}

View File

@@ -0,0 +1,549 @@
// TODO: move all related logic here (if anything left anywhere in codebase)
mod common;
mod dependency_map {
use sqlx::{Pool, Postgres};
use tokio_stream::StreamExt;
use windmill_api_client::types::NewScript;
use crate::common::{in_test_worker, listen_for_completed_jobs, ApiServer};
pub async fn initialize_tracing() {
use std::sync::Once;
static ONCE: Once = Once::new();
ONCE.call_once(|| {
let _ = windmill_common::tracing_init::initialize_tracing(
"test",
&windmill_common::utils::Mode::Standalone,
"test",
);
});
}
async fn rebuild_dmap(client: &windmill_api_client::Client) -> bool {
client
.client()
.post(format!(
"{}/w/test-workspace/workspaces/rebuild_dependency_map",
client.baseurl()
))
.send()
.await
.unwrap()
.status()
.is_success()
}
async fn init(db: Pool<Postgres>) -> (windmill_api_client::Client, u16, ApiServer) {
initialize_tracing().await;
let server = ApiServer::start(db).await.unwrap();
let port = server.addr.port();
let client = windmill_api_client::create_client(
&format!("http://localhost:{port}"),
"SECRET_TOKEN".to_string(),
);
(client, port, server)
}
async fn _clear_dmap(db: &Pool<Postgres>) {
sqlx::query!("DELETE FROM dependency_map WHERE workspace_id = 'test-workspace'")
.execute(db)
.await
.unwrap();
}
/// Corrects map according to provided replacements.
/// Only changes importer_path and/or id
/// Does not affect imported_path nor kind!
fn corrected_dmap(replacements: Vec<(&str, &str)>) -> Vec<(String, String, String, String)> {
CORRECT_DMAP
.clone()
.into_iter()
.map(|e| {
let mut r = (
e.0.to_owned(),
e.1.to_owned(),
e.2.to_owned(),
e.3.to_owned(),
);
for (from, to) in &replacements {
r = (
r.0.replace(from, to),
r.1, // Kind should be immutable
r.2, // Imported path should be immutable
// We do not modify script contents in test, so we can assume scripts always import the same path
// Modification of kind or imported path considered to be incorrect.
r.3.replace(from, to),
);
}
r
})
.collect()
}
async fn assert_dmap(
db: &Pool<Postgres>,
importer: Option<String>,
expected: Vec<(
impl Into<String>,
impl Into<String>,
impl Into<String>,
impl Into<String>,
)>,
) {
let dmap = sqlx::query_as::<_, (String, String, String, String)>(
"SELECT importer_path, importer_kind::text, imported_path, importer_node_id FROM dependency_map WHERE workspace_id = 'test-workspace' AND ($1::text IS NULL OR importer_path = $1::text)",
)
.bind(importer)
.fetch_all(db)
.await
.unwrap();
assert_eq!(
dmap,
expected
.into_iter()
.map(|(f, s, t, fo)| (f.into(), s.into(), t.into(), fo.into()))
.collect::<Vec<(String, String, String, String)>>()
);
}
fn quick_ns(
content: &str,
language: windmill_api_client::types::ScriptLang,
path: &str,
lock: Option<String>,
parent_hash: Option<String>,
) -> NewScript {
NewScript {
content: content.into(),
language,
lock,
parent_hash,
path: path.into(),
concurrent_limit: None,
concurrency_time_window_s: None,
cache_ttl: None,
dedicated_worker: None,
description: "".to_string(),
draft_only: None,
envs: vec![],
is_template: None,
kind: None,
summary: "".to_string(),
tag: None,
schema: std::collections::HashMap::new(),
ws_error_handler_muted: Some(false),
priority: None,
delete_after_use: None,
timeout: None,
restart_unless_cancelled: None,
deployment_message: None,
concurrency_key: None,
visible_to_runner_only: None,
no_main_func: None,
codebase: None,
has_preprocessor: None,
on_behalf_of_email: None,
assets: vec![],
}
}
lazy_static::lazy_static! {
pub static ref CORRECT_DMAP: Vec<(&'static str, &'static str, &'static str, &'static str)> = vec![
("f/rel/branch", "script", "f/rel/leaf_1", ""),
("f/rel/root_script", "script", "f/rel/branch", ""),
("f/rel/root_script", "script", "f/rel/leaf_1", ""),
("f/rel/root_script", "script", "f/rel/leaf_2", ""),
("f/rel/root_app", "app", "f/rel/leaf_2", "dontpressmeplz"),
("f/rel/root_flow", "flow", "f/rel/branch", "nstep1"),
("f/rel/root_flow", "flow", "f/rel/leaf_1", "nstep1"),
("f/rel/root_flow", "flow", "f/rel/leaf_2", "nstep1"),
("f/rel/root_flow", "flow", "f/rel/leaf_2", "nstep2_2"),
("f/rel/root_flow", "flow", "f/rel/branch", "nstep4_1"),
("f/rel/root_flow", "flow", "f/rel/branch", "nstep5_1"),
("f/rel/root_flow", "flow", "f/rel/leaf_1", "nstep5_1"),
("f/rel/root_flow", "flow", "f/rel/leaf_2", "nstep5_1"),
("f/rel/root_app", "app", "f/rel/branch", "pressmeplz"),
("f/rel/root_app", "app", "f/rel/leaf_1", "pressmeplz"),
("f/rel/root_app", "app", "f/rel/leaf_2", "pressmeplz"),
("f/rel/root_app", "app", "f/rel/branch", "youcanpressme")];
}
#[cfg(feature = "python")]
#[sqlx::test(fixtures("base", "dependency_map"))]
async fn relative_imports_test_rebuild_correctness(db: Pool<Postgres>) -> anyhow::Result<()> {
let (client, _port, _s) = init(db.clone()).await;
assert_dmap(&db, None, CORRECT_DMAP.clone()).await;
// rebuild map
assert!(rebuild_dmap(&client).await);
assert_dmap(&db, None, CORRECT_DMAP.clone()).await;
Ok(())
}
#[cfg(feature = "python")]
#[sqlx::test(fixtures("base", "dependency_map"))]
async fn relative_imports_test_rebuild_lock(db: Pool<Postgres>) -> anyhow::Result<()> {
let (client, _port, _s) = init(db.clone()).await;
// Spawn first rebuild
let handle = {
let client = client.clone();
tokio::spawn(async move { rebuild_dmap(&client).await })
};
// Immidiately spawn another
let res = client
.client()
.post(format!(
"{}/w/test-workspace/workspaces/rebuild_dependency_map",
client.baseurl()
))
.send()
.await
.unwrap()
.text()
.await
.unwrap();
// Should tell us there is already rebuilt in progress
// Or if it is too fast we will be able to trigger it second time
assert!(&res == "There is already one task pending, try again later." || &res == "Success");
assert!(handle.await.unwrap());
Ok(())
}
// If you deploy from cli and you use raw requirements you don't want the script be included in dmap
// Otherwise script will be overwritten once any relative import is updated
#[cfg(feature = "python")]
#[sqlx::test(fixtures("base", "dependency_map"))]
async fn relative_imports_test_with_requirements_txt(db: Pool<Postgres>) -> anyhow::Result<()> {
let (client, _port, _s) = init(db.clone()).await;
client
.create_script(
"test-workspace",
&quick_ns(
"
from f.rel.branch import main as br;
from f.rel.leaf_1 import main as lf_1;
from f.rel.leaf_2 import main as lf_2;
def main():
return [br(), lf_1(), lf_2];
",
windmill_api_client::types::ScriptLang::Python3,
"f/rel/root_script",
Some(format!("# from requirements.txt")),
Some("000000000005165B".into()),
),
)
.await
.unwrap();
assert_dmap(
&db,
Some("f/rel/root_script".into()),
vec![
("f/rel/root_script", "script", "f/rel/branch", ""),
("f/rel/root_script", "script", "f/rel/leaf_1", ""),
("f/rel/root_script", "script", "f/rel/leaf_2", ""),
],
)
.await;
tokio::time::sleep(std::time::Duration::from_secs(13)).await;
assert_dmap(
&db,
Some("f/rel/root_script".into()),
Vec::<(String, String, String, String)>::new(),
)
.await;
Ok(())
}
#[cfg(feature = "python")]
#[sqlx::test(fixtures("base", "dependency_map"))]
async fn relative_imports_test_without_requirements_txt(
db: Pool<Postgres>,
) -> anyhow::Result<()> {
let (client, _port, _s) = init(db.clone()).await;
client
.create_script(
"test-workspace",
&quick_ns(
"
from f.rel.branch import main as br;
from f.rel.leaf_1 import main as lf_1;
from f.rel.leaf_2 import main as lf_2;
def main():
return [br(), lf_1(), lf_2];
",
windmill_api_client::types::ScriptLang::Python3,
"f/rel/root_script",
// We still want to pass lock to it.
Some(format!("# py311")),
Some("000000000005165B".into()),
),
)
.await
.unwrap();
assert_dmap(&db, None, CORRECT_DMAP.clone()).await;
tokio::time::sleep(std::time::Duration::from_secs(13)).await;
assert_dmap(&db, None, CORRECT_DMAP.clone()).await;
Ok(())
}
// Consider simple one. Only referenced directly. No deep connections
#[cfg(feature = "python")]
#[sqlx::test(fixtures("base", "dependency_map"))]
async fn relative_imports_test_rename_leaf_2(db: Pool<Postgres>) -> anyhow::Result<()> {
let (client, port, _s) = init(db.clone()).await;
client
.create_script(
"test-workspace",
&quick_ns(
"
def main():
return 'leaf3';
",
windmill_api_client::types::ScriptLang::Python3,
"f/rel/leaf_2_renamed",
None,
Some("0000000000051659".into()),
),
)
.await
.unwrap();
let mut completed = listen_for_completed_jobs(&db).await;
in_test_worker(&db, completed.next(), port).await;
// Changing leafs should not change dependency map
assert_dmap(&db, None, CORRECT_DMAP.clone()).await;
Ok(())
}
// Consider hard one. Referenced deeply and exists in double references.
#[cfg(feature = "python")]
#[sqlx::test(fixtures("base", "dependency_map"))]
async fn relative_imports_test_rename_leaf_1(db: Pool<Postgres>) -> anyhow::Result<()> {
let (client, port, _s) = init(db.clone()).await;
client
.create_script(
"test-workspace",
&quick_ns(
"
def main():
return 'leaf1';
",
windmill_api_client::types::ScriptLang::Python3,
"f/rel/leaf_1_renamed",
None,
Some("0000000000051658".into()),
),
)
.await
.unwrap();
let mut completed = listen_for_completed_jobs(&db).await;
in_test_worker(&db, completed.next(), port).await;
// Changing leafs should not change dependency map
assert_dmap(&db, None, CORRECT_DMAP.clone()).await;
Ok(())
}
#[cfg(feature = "python")]
#[sqlx::test(fixtures("base", "dependency_map"))]
async fn relative_imports_test_rename_branch(db: Pool<Postgres>) -> anyhow::Result<()> {
let (client, port, _s) = init(db.clone()).await;
client
.create_script(
"test-workspace",
&quick_ns(
"
from f.rel.leaf_1 import main as lf_1;
def main():
return lf_1();
",
windmill_api_client::types::ScriptLang::Python3,
"f/rel/branch_renamed",
None,
Some("000000000005165A".into()),
),
)
.await
.unwrap();
let mut completed = listen_for_completed_jobs(&db).await;
in_test_worker(&db, completed.next(), port).await;
// Changing branches SHOULD change dependency map
// Though it should only change branch item in dmap when it is importer.
// All entries when branch is imported should not change.
let mut corrected_dmap = CORRECT_DMAP.clone();
// Corresponds to importer path of branch entry
corrected_dmap[0].0 = "f/rel/branch_renamed";
assert_dmap(&db, None, corrected_dmap).await;
Ok(())
}
#[cfg(feature = "python")]
#[sqlx::test(fixtures("base", "dependency_map"))]
async fn relative_imports_test_rename_primary_script(db: Pool<Postgres>) -> anyhow::Result<()> {
let (client, port, _s) = init(db.clone()).await;
client
.create_script(
"test-workspace",
&quick_ns(
"
from f.rel.branch import main as br;
from f.rel.leaf_1 import main as lf_1;
from f.rel.leaf_2 import main as lf_2;
def main():
return [br(), lf_1(), lf_2];
",
windmill_api_client::types::ScriptLang::Python3,
"f/rel/root_script_renamed",
None,
Some("000000000005165B".into()),
),
)
.await
.unwrap();
let corrected_dmap = corrected_dmap(vec![("root_script", "root_script_renamed")]);
let mut completed = listen_for_completed_jobs(&db).await;
in_test_worker(&db, completed.next(), port).await;
assert_dmap(&db, None, corrected_dmap.clone()).await;
Ok(())
}
#[cfg(feature = "python")]
#[sqlx::test(fixtures("base", "dependency_map"))]
async fn relative_imports_test_rename_primary_flow(db: Pool<Postgres>) -> anyhow::Result<()> {
use windmill_common::{cache::flow::fetch_version, flows::NewFlow};
let (client, port, _s) = init(db.clone()).await;
let flow = fetch_version(&db, 1443253234253454).await.unwrap();
let res = client
.client()
.post(format!(
"{}/w/test-workspace/flows/update/{}",
client.baseurl(),
"f/rel/root_flow" // encode_path()
))
.json(&NewFlow {
path: "f/rel/root_flow_renamed".into(),
summary: "".into(),
description: None,
value: serde_json::from_str(
&serde_json::to_string(flow.value())
.unwrap()
.replace("nstep1", "Foxes")
.replace("nstep2_2", "like")
.replace("nstep_4_1", "Emeralds"),
)
.unwrap(),
schema: None,
draft_only: None,
tag: None,
dedicated_worker: None,
timeout: None,
deployment_message: None,
visible_to_runner_only: None,
on_behalf_of_email: None,
})
.send()
.await
.unwrap();
assert_eq!(res.text().await.unwrap(), "f/rel/root_flow_renamed");
let mut completed = listen_for_completed_jobs(&db).await;
in_test_worker(&db, completed.next(), port).await;
assert_dmap(
&db,
None,
corrected_dmap(vec![
("f/rel/root_flow", "f/rel/root_flow_renamed"),
("nstep1", "Foxes"),
("nstep2_2", "like"),
("nstep_4_1", "Emeralds"),
]),
)
.await;
Ok(())
}
#[cfg(feature = "python")]
#[sqlx::test(fixtures("base", "dependency_map"))]
async fn relative_imports_test_rename_primary_app(db: Pool<Postgres>) -> anyhow::Result<()> {
let (client, port, _s) = init(db.clone()).await;
let app_value: String =
sqlx::query_scalar!("SELECT value::text FROM app_version WHERE id = 0 AND app_id = 2")
.fetch_one(&db)
.await
.unwrap()
.unwrap();
// TODO: There is:
// 1. update app
// 2. create app
// 3. update app raw
// Ideally all of them should be handled
let res = client
.client()
.post(format!(
"{}/w/test-workspace/apps/update/{}",
client.baseurl(),
"f/rel/root_app" // encode_path()
))
.json(&windmill_api::EditApp {
path: Some("f/rel/root_app_renamed".into()),
summary: None,
value: serde_json::from_str(
&app_value
.replace("dontpressmeplz", "Apps")
.replace("youcanpressme", "Work"),
)
.unwrap(),
policy: None,
deployment_message: None,
custom_path: None,
})
.send()
.await
.unwrap();
assert_eq!(
res.text().await.unwrap(),
"app f/rel/root_app updated (npath: \"f/rel/root_app_renamed\")"
);
let mut completed = listen_for_completed_jobs(&db).await;
in_test_worker(&db, completed.next(), port).await;
assert_dmap(
&db,
None,
corrected_dmap(vec![
("f/rel/root_app", "f/rel/root_app_renamed"),
("dontpressmeplz", "Apps"),
("youcanpressme", "Work"),
]),
)
.await;
Ok(())
}
}

View File

@@ -1,6 +1,5 @@
use serde::de::DeserializeOwned;
#[cfg(feature = "enterprise")]
use chrono::Timelike;
@@ -20,13 +19,12 @@ use windmill_api_client::types::{EditSchedule, NewSchedule, ScriptArgs};
use windmill_common::flows::InputTransform;
#[cfg(any(feature = "python", feature = "deno_core"))]
use windmill_common::flow_status::{RestartedFrom};
use windmill_common::flow_status::RestartedFrom;
use windmill_common::{
flows::{ FlowValue},
jobs::{ JobPayload, RawCode},
scripts::{ScriptLang},
flows::FlowValue,
jobs::{JobPayload, RawCode},
scripts::ScriptLang,
};
mod common;
use common::*;
@@ -34,7 +32,6 @@ use common::*;
#[cfg(feature = "enterprise")]
use futures::StreamExt;
// async fn _print_job(id: Uuid, db: &Pool<Postgres>) -> Result<(), anyhow::Error> {
// tracing::info!(
// "{:#?}",
@@ -45,7 +42,6 @@ use futures::StreamExt;
// Ok(())
// }
#[cfg(feature = "deno_core")]
#[sqlx::test(fixtures("base"))]
async fn test_iteration(db: Pool<Postgres>) -> anyhow::Result<()> {
@@ -167,8 +163,6 @@ async fn test_iteration_parallel(db: Pool<Postgres>) -> anyhow::Result<()> {
Ok(())
}
#[cfg(feature = "deno_core")]
#[sqlx::test(fixtures("base"))]
async fn test_deno_flow(db: Pool<Postgres>) -> anyhow::Result<()> {
@@ -341,7 +335,6 @@ use windmill_common::flows::FlowModuleValue;
#[cfg(feature = "deno_core")]
#[sqlx::test(fixtures("base"))]
async fn test_deno_flow_same_worker(db: Pool<Postgres>) -> anyhow::Result<()> {
initialize_tracing().await;
let server = ApiServer::start(db.clone()).await?;
@@ -1138,8 +1131,6 @@ public class Main {
Ok(())
}
#[sqlx::test(fixtures("base"))]
async fn test_bun_job_datetime(db: Pool<Postgres>) -> anyhow::Result<()> {
initialize_tracing().await;
@@ -2311,7 +2302,7 @@ async fn test_rust_client(db: Pool<Postgres>) -> anyhow::Result<()> {
Ok(())
}
#[cfg(feature = "enterprise")]
#[cfg(all(feature = "enterprise", feature = "private"))]
#[sqlx::test(fixtures("base", "schedule"))]
async fn test_script_schedule_handlers(db: Pool<Postgres>) -> anyhow::Result<()> {
initialize_tracing().await;
@@ -2468,7 +2459,7 @@ async fn test_script_schedule_handlers(db: Pool<Postgres>) -> anyhow::Result<()>
Ok(())
}
#[cfg(feature = "enterprise")]
#[cfg(all(feature = "enterprise", feature = "private"))]
#[sqlx::test(fixtures("base", "schedule"))]
async fn test_flow_schedule_handlers(db: Pool<Postgres>) -> anyhow::Result<()> {
initialize_tracing().await;
@@ -2627,7 +2618,6 @@ async fn test_flow_schedule_handlers(db: Pool<Postgres>) -> anyhow::Result<()> {
Ok(())
}
#[sqlx::test(fixtures("base", "relative_bun"))]
async fn test_relative_imports_bun(db: Pool<Postgres>) -> anyhow::Result<()> {
let content = r#"
@@ -2699,8 +2689,6 @@ export async function main() {
Ok(())
}
#[sqlx::test(fixtures("base", "result_format"))]
async fn test_result_format(db: Pool<Postgres>) -> anyhow::Result<()> {
let ordered_result_job_id = "1eecb96a-c8b0-4a3d-b1b6-087878c55e41";
@@ -2929,4 +2917,3 @@ async fn test_workflow_as_code(db: Pool<Postgres>) -> anyhow::Result<()> {
.await;
Ok(())
}

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env bash
set -e
# Default directory
EE_DIR="../windmill-ee-private"
@@ -21,9 +23,17 @@ if [[ "$(uname)" == "Darwin" ]]; then
sed -i '' 's/^samael = { version="0.0.14", features = \["xmlsec"\] }/#samael = { version="0.0.14", features = ["xmlsec"] }/' Cargo.toml
# Uncomment the git-based samael dependency
sed -i '' 's/^# \(samael = { git="https:\/\/github.com\/njaremko\/samael", rev="464d015e3ae393e4b5dd00b4d6baa1b617de0dd6", features = \["xmlsec"\] }\)/\1/' Cargo.toml
# Run cargo sqlx prepare with deno_core_mac
echo "Running cargo sqlx prepare with deno_core_mac..."
cargo sqlx prepare --workspace -- --all-targets --features all_sqlx_features,private,deno_core_mac
else
# Run cargo sqlx prepare
echo "Running cargo sqlx prepare..."
cargo sqlx prepare --workspace -- --all-targets --features all_sqlx_features,private
fi
cargo sqlx prepare --workspace -- --all-targets --features all_sqlx_features,private
# Undo the samael changes on macOS
if [[ "$(uname)" == "Darwin" ]]; then

View File

@@ -8,9 +8,80 @@ pub mod types {
#[allow(unused_imports)]
use std::convert::TryFrom;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AiAgent {
pub input_transforms: std::collections::HashMap<String, InputTransform>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parallel: Option<bool>,
pub tools: Vec<FlowModule>,
#[serde(rename = "type")]
pub type_: AiAgentType,
}
impl From<&AiAgent> for AiAgent {
fn from(value: &AiAgent) -> Self {
value.clone()
}
}
#[derive(
Clone,
Copy,
Debug,
Deserialize,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize
)]
pub enum AiAgentType {
#[serde(rename = "aiagent")]
Aiagent,
}
impl From<&AiAgentType> for AiAgentType {
fn from(value: &AiAgentType) -> Self {
value.clone()
}
}
impl ToString for AiAgentType {
fn to_string(&self) -> String {
match *self {
Self::Aiagent => "aiagent".to_string(),
}
}
}
impl std::str::FromStr for AiAgentType {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, &'static str> {
match value {
"aiagent" => Ok(Self::Aiagent),
_ => Err("invalid value"),
}
}
}
impl std::convert::TryFrom<&str> for AiAgentType {
type Error = &'static str;
fn try_from(value: &str) -> Result<Self, &'static str> {
value.parse()
}
}
impl std::convert::TryFrom<&String> for AiAgentType {
type Error = &'static str;
fn try_from(value: &String) -> Result<Self, &'static str> {
value.parse()
}
}
impl std::convert::TryFrom<String> for AiAgentType {
type Error = &'static str;
fn try_from(value: String) -> Result<Self, &'static str> {
value.parse()
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AiConfig {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub code_completion_model: Option<AiProviderModel>,
#[serde(default, skip_serializing_if = "std::collections::HashMap::is_empty")]
pub custom_prompts: std::collections::HashMap<String, String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub default_model: Option<AiProviderModel>,
#[serde(default, skip_serializing_if = "std::collections::HashMap::is_empty")]
@@ -1295,8 +1366,8 @@ pub mod types {
Websocket,
#[serde(rename = "kafka")]
Kafka,
#[serde(rename = "email")]
Email,
#[serde(rename = "default_email")]
DefaultEmail,
#[serde(rename = "nats")]
Nats,
#[serde(rename = "postgres")]
@@ -1307,6 +1378,8 @@ pub mod types {
Mqtt,
#[serde(rename = "gcp")]
Gcp,
#[serde(rename = "email")]
Email,
}
impl From<&CaptureTriggerKind> for CaptureTriggerKind {
fn from(value: &CaptureTriggerKind) -> Self {
@@ -1320,12 +1393,13 @@ pub mod types {
Self::Http => "http".to_string(),
Self::Websocket => "websocket".to_string(),
Self::Kafka => "kafka".to_string(),
Self::Email => "email".to_string(),
Self::DefaultEmail => "default_email".to_string(),
Self::Nats => "nats".to_string(),
Self::Postgres => "postgres".to_string(),
Self::Sqs => "sqs".to_string(),
Self::Mqtt => "mqtt".to_string(),
Self::Gcp => "gcp".to_string(),
Self::Email => "email".to_string(),
}
}
}
@@ -1337,12 +1411,13 @@ pub mod types {
"http" => Ok(Self::Http),
"websocket" => Ok(Self::Websocket),
"kafka" => Ok(Self::Kafka),
"email" => Ok(Self::Email),
"default_email" => Ok(Self::DefaultEmail),
"nats" => Ok(Self::Nats),
"postgres" => Ok(Self::Postgres),
"sqs" => Ok(Self::Sqs),
"mqtt" => Ok(Self::Mqtt),
"gcp" => Ok(Self::Gcp),
"email" => Ok(Self::Email),
_ => Err("invalid value"),
}
}
@@ -1493,6 +1568,8 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
Flownode,
#[serde(rename = "appscript")]
Appscript,
#[serde(rename = "aiagent")]
Aiagent,
}
impl From<&CompletedJobJobKind> for CompletedJobJobKind {
fn from(value: &CompletedJobJobKind) -> Self {
@@ -1516,6 +1593,7 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
Self::Flowscript => "flowscript".to_string(),
Self::Flownode => "flownode".to_string(),
Self::Appscript => "appscript".to_string(),
Self::Aiagent => "aiagent".to_string(),
}
}
}
@@ -1537,6 +1615,7 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
"flowscript" => Ok(Self::Flowscript),
"flownode" => Ok(Self::Flownode),
"appscript" => Ok(Self::Appscript),
"aiagent" => Ok(Self::Aiagent),
_ => Err("invalid value"),
}
}
@@ -1705,6 +1784,21 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CreateWorkspaceFork {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub color: Option<String>,
pub id: String,
pub name: String,
pub parent_workspace_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub username: Option<String>,
}
impl From<&CreateWorkspaceFork> for CreateWorkspaceFork {
fn from(value: &CreateWorkspaceFork) -> Self {
value.clone()
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CriticalAlert {
///Acknowledgment status of the alert, can be true, false, or null if not set
#[serde(default, skip_serializing_if = "Option::is_none")]
@@ -1799,6 +1893,24 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DependencyMap {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub imported_path: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub importer_kind: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub importer_node_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub importer_path: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub workspace_id: Option<String>,
}
impl From<&DependencyMap> for DependencyMap {
fn from(value: &DependencyMap) -> Self {
value.clone()
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DucklakeSettings {
pub ducklakes: std::collections::HashMap<String, DucklakeSettingsDucklakesValue>,
}
@@ -1909,6 +2021,27 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EditEmailTrigger {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error_handler_args: Option<ScriptArgs>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error_handler_path: Option<String>,
pub is_flow: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub local_part: Option<String>,
pub path: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub retry: Option<Retry>,
pub script_path: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub workspaced_local_part: Option<bool>,
}
impl From<&EditEmailTrigger> for EditEmailTrigger {
fn from(value: &EditEmailTrigger) -> Self {
value.clone()
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EditHttpTrigger {
pub authentication_method: AuthenticationMethod,
#[serde(default, skip_serializing_if = "Option::is_none")]
@@ -2234,6 +2367,23 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EmailTrigger {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error_handler_args: Option<ScriptArgs>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error_handler_path: Option<String>,
pub local_part: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub retry: Option<Retry>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub workspaced_local_part: Option<bool>,
}
impl From<&EmailTrigger> for EmailTrigger {
fn from(value: &EmailTrigger) -> Self {
value.clone()
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EndpointTool {
///JSON schema for request body
#[serde(default, skip_serializing_if = "Option::is_none")]
@@ -2481,7 +2631,7 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
#[serde(default, skip_serializing_if = "Option::is_none")]
pub suspend: Option<FlowModuleSuspend>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub timeout: Option<f64>,
pub timeout: Option<InputTransform>,
pub value: FlowModuleValue,
}
impl From<&FlowModule> for FlowModule {
@@ -2555,6 +2705,7 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
BranchOne(BranchOne),
BranchAll(BranchAll),
Identity(Identity),
AiAgent(AiAgent),
}
impl From<&FlowModuleValue> for FlowModuleValue {
fn from(value: &FlowModuleValue) -> Self {
@@ -2601,6 +2752,11 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
Self::Identity(value)
}
}
impl From<AiAgent> for FlowModuleValue {
fn from(value: AiAgent) -> Self {
Self::AiAgent(value)
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FlowPreview {
pub args: ScriptArgs,
@@ -2648,6 +2804,10 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FlowStatusModule {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub agent_actions: Vec<std::collections::HashMap<String, serde_json::Value>>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub agent_actions_success: Vec<bool>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub approvers: Vec<FlowStatusModuleApproversItem>,
#[serde(default, skip_serializing_if = "Option::is_none")]
@@ -4810,6 +4970,26 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NewEmailTrigger {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error_handler_args: Option<ScriptArgs>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error_handler_path: Option<String>,
pub is_flow: bool,
pub local_part: String,
pub path: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub retry: Option<Retry>,
pub script_path: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub workspaced_local_part: Option<bool>,
}
impl From<&NewEmailTrigger> for NewEmailTrigger {
fn from(value: &NewEmailTrigger) -> Self {
value.clone()
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NewHttpTrigger {
pub authentication_method: AuthenticationMethod,
#[serde(default, skip_serializing_if = "Option::is_none")]
@@ -5907,6 +6087,7 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Preview {
pub args: ScriptArgs,
///The code to run
#[serde(default, skip_serializing_if = "Option::is_none")]
pub content: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
@@ -5917,8 +6098,10 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
pub language: Option<ScriptLang>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub lock: Option<String>,
///The path to the script
#[serde(default, skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
///The hash of the script
#[serde(default, skip_serializing_if = "Option::is_none")]
pub script_hash: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
@@ -6127,6 +6310,8 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
Flownode,
#[serde(rename = "appscript")]
Appscript,
#[serde(rename = "aiagent")]
Aiagent,
}
impl From<&QueuedJobJobKind> for QueuedJobJobKind {
fn from(value: &QueuedJobJobKind) -> Self {
@@ -6150,6 +6335,7 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
Self::Flowscript => "flowscript".to_string(),
Self::Flownode => "flownode".to_string(),
Self::Appscript => "appscript".to_string(),
Self::Aiagent => "aiagent".to_string(),
}
}
}
@@ -6171,6 +6357,7 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
"flowscript" => Ok(Self::Flowscript),
"flownode" => Ok(Self::Flownode),
"appscript" => Ok(Self::Appscript),
"aiagent" => Ok(Self::Aiagent),
_ => Err("invalid value"),
}
}
@@ -6676,6 +6863,8 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
pub constant: Option<RetryConstant>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub exponential: Option<RetryExponential>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub retry_if: Option<RetryRetryIf>,
}
impl From<&Retry> for Retry {
fn from(value: &Retry) -> Self {
@@ -6710,6 +6899,15 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
value.clone()
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RetryRetryIf {
pub expr: String,
}
impl From<&RetryRetryIf> for RetryRetryIf {
fn from(value: &RetryRetryIf) -> Self {
value.clone()
}
}
#[derive(
Clone,
Copy,
@@ -7861,6 +8059,8 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TriggersCount {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub default_email_count: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub email_count: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
@@ -8069,10 +8269,14 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct UserWorkspaceListWorkspacesItem {
pub color: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub created_by: Option<String>,
pub id: String,
pub name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub operator_settings: Option<OperatorSettings>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent_workspace_id: Option<String>,
pub username: String,
}
impl From<&UserWorkspaceListWorkspacesItem> for UserWorkspaceListWorkspacesItem {
@@ -8479,6 +8683,8 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
pub id: String,
pub name: String,
pub owner: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent_workspace_id: Option<String>,
}
impl From<&Workspace> for Workspace {
fn from(value: &Workspace) -> Self {
@@ -8550,6 +8756,8 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
pub email: String,
pub is_admin: bool,
pub operator: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent_workspace_id: Option<String>,
pub workspace_id: String,
}
impl From<&WorkspaceInvite> for WorkspaceInvite {
@@ -8561,7 +8769,7 @@ the execution of this script will be permissioned_as and by extension its DT_TOK
#[derive(Clone, Debug)]
/**Client for Windmill API
Version: 1.526.1*/
Version: 1.543.0*/
pub struct Client {
pub(crate) baseurl: String,
pub(crate) client: reqwest::Client,
@@ -8607,7 +8815,7 @@ impl Client {
/// This string is pulled directly from the source OpenAPI
/// document and may be in any format the API selects.
pub fn api_version(&self) -> &'static str {
"1.526.1"
"1.543.0"
}
}
impl Client {

View File

@@ -40,7 +40,7 @@ mcp = ["dep:rmcp"]
python = []
[dependencies]
rmcp = { version = "0.2.1", features=["transport-streamable-http-server", "transport-streamable-http-server-session", "transport-worker"], optional = true }
rmcp = { version = "0.6.4", features=["transport-streamable-http-server", "transport-streamable-http-server-session", "transport-worker"], optional = true }
windmill-queue.workspace = true
windmill-common = { workspace = true, default-features = false }
windmill-audit.workspace = true

View File

@@ -1,7 +1,7 @@
openapi: "3.0.3"
info:
version: 1.545.0
version: 1.555.2
title: Windmill API
contact:
@@ -575,6 +575,27 @@ paths:
text/plain:
schema:
type: string
/w/{workspace}/users/convert_to_group/{username}:
post:
summary: convert manual user to group user (require admin privilege)
operationId: convertUserToGroup
tags:
- user
- admin
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- name: username
in: path
required: true
schema:
type: string
responses:
"200":
description: convert user to group user
content:
text/plain:
schema:
type: string
/github_app/connected_repositories:
get:
@@ -749,34 +770,26 @@ paths:
schema:
type: boolean
/settings/databases_exist:
/settings/get_ducklake_instance_catalog_db_status:
post:
summary: checks that all given databases exist or else return the ones that don't
operationId: databasesExist
summary: Returns the set-up statuses of ducklake instance catalog dbs
operationId: getDucklakeInstanceCatalogDbStatus
tags:
- setting
requestBody:
required: true
content:
application/json:
schema:
type: array
items:
type: string
responses:
"200":
description: databases that do not exist
description: Statuses of all ducklake instance catalog dbs
content:
application/json:
schema:
type: array
items:
type: string
type: object
additionalProperties:
$ref: "#/components/schemas/DucklakeInstanceCatalogDbStatus"
/settings/create_ducklake_database/{name}:
/settings/setup_ducklake_catalog_db/{name}:
post:
summary: Runs CREATE DATABASE on the Windmill Postgres and grants access to the ducklake_user
operationId: createDucklakeDatabase
operationId: setupDucklakeCatalogDb
tags:
- setting
parameters:
@@ -791,7 +804,8 @@ paths:
description: status
content:
application/json:
schema: {}
schema:
$ref: "#/components/schemas/DucklakeInstanceCatalogDbStatus"
/settings/global/{key}:
get:
@@ -2134,6 +2148,40 @@ paths:
schema:
type: string
/w/{workspace}/workspaces/rebuild_dependency_map:
post:
summary: rebuild dependency map
operationId: rebuildDependencyMap
tags:
- workspace
parameters:
- $ref: "#/components/parameters/WorkspaceId"
responses:
"200":
description: status
content:
text/plain:
schema:
type: string
/w/{workspace}/workspaces/get_dependency_map:
get:
summary: get dependency map
operationId: getDependencyMap
tags:
- workspace
parameters:
- $ref: "#/components/parameters/WorkspaceId"
responses:
"200":
description: dmap
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/DependencyMap"
/w/{workspace}/workspaces/edit_slack_command:
post:
summary: edit slack command
@@ -2251,7 +2299,6 @@ paths:
channel_id:
type: string
/w/{workspace}/workspaces/connect_teams:
post:
summary: connect teams
@@ -3684,6 +3731,7 @@ paths:
properties:
refresh_token:
type: string
description: "OAuth refresh token. For authorization_code flow, this contains the actual refresh token. For client_credentials flow, this must be set to an empty string."
expires_in:
type: integer
client:
@@ -3701,6 +3749,7 @@ paths:
type: string
description: "OAuth token URL override for resource-level authentication (client_credentials flow only)"
required:
- refresh_token
- expires_in
- client
responses:
@@ -3912,7 +3961,6 @@ paths:
items:
type: string
/teams/activities:
post:
summary: send update to Microsoft Teams activity
@@ -5672,6 +5720,12 @@ paths:
- $ref: "#/components/parameters/QueueLimit"
- $ref: "#/components/parameters/NewJobId"
- $ref: "#/components/parameters/SkipPreprocessor"
- name: memory_id
description: memory ID for chat-enabled flows
in: query
schema:
type: string
format: uuid
requestBody:
description: script args
@@ -5688,6 +5742,230 @@ paths:
application/json:
schema: {}
/w/{workspace}/jobs/run_and_stream/f/{path}:
post:
summary: run flow by path and stream updates via SSE
operationId: runAndStreamFlowByPath
tags:
- job
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/ScriptPath"
- $ref: "#/components/parameters/IncludeHeader"
- $ref: "#/components/parameters/QueueLimit"
- $ref: "#/components/parameters/NewJobId"
- $ref: "#/components/parameters/SkipPreprocessor"
- name: memory_id
description: memory ID for chat-enabled flows
in: query
schema:
type: string
format: uuid
- name: poll_delay_ms
description: delay between polling for job updates in milliseconds
in: query
schema:
type: integer
format: int64
requestBody:
description: flow args
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ScriptArgs"
responses:
"200":
description: server-sent events stream of job updates
content:
text/event-stream:
schema:
type: string
get:
summary: run flow by path with GET and stream updates via SSE
operationId: runAndStreamFlowByPathGet
tags:
- job
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/ScriptPath"
- $ref: "#/components/parameters/IncludeHeader"
- $ref: "#/components/parameters/QueueLimit"
- $ref: "#/components/parameters/Payload"
- $ref: "#/components/parameters/NewJobId"
- $ref: "#/components/parameters/SkipPreprocessor"
- name: memory_id
description: memory ID for chat-enabled flows
in: query
schema:
type: string
format: uuid
- name: poll_delay_ms
description: delay between polling for job updates in milliseconds
in: query
schema:
type: integer
format: int64
responses:
"200":
description: server-sent events stream of job updates
content:
text/event-stream:
schema:
type: string
/w/{workspace}/jobs/run_and_stream/p/{path}:
post:
summary: run script by path and stream updates via SSE
operationId: runAndStreamScriptByPath
tags:
- job
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/ScriptPath"
- $ref: "#/components/parameters/ParentJob"
- $ref: "#/components/parameters/WorkerTag"
- $ref: "#/components/parameters/CacheTtl"
- $ref: "#/components/parameters/NewJobId"
- $ref: "#/components/parameters/IncludeHeader"
- $ref: "#/components/parameters/QueueLimit"
- $ref: "#/components/parameters/SkipPreprocessor"
- name: poll_delay_ms
description: delay between polling for job updates in milliseconds
in: query
schema:
type: integer
format: int64
requestBody:
description: script args
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ScriptArgs"
responses:
"200":
description: server-sent events stream of job updates
content:
text/event-stream:
schema:
type: string
get:
summary: run script by path with GET and stream updates via SSE
operationId: runAndStreamScriptByPathGet
tags:
- job
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/ScriptPath"
- $ref: "#/components/parameters/ParentJob"
- $ref: "#/components/parameters/WorkerTag"
- $ref: "#/components/parameters/CacheTtl"
- $ref: "#/components/parameters/NewJobId"
- $ref: "#/components/parameters/IncludeHeader"
- $ref: "#/components/parameters/QueueLimit"
- $ref: "#/components/parameters/Payload"
- $ref: "#/components/parameters/SkipPreprocessor"
- name: poll_delay_ms
description: delay between polling for job updates in milliseconds
in: query
schema:
type: integer
format: int64
responses:
"200":
description: server-sent events stream of job updates
content:
text/event-stream:
schema:
type: string
/w/{workspace}/jobs/run_and_stream/h/{hash}:
post:
summary: run script by hash and stream updates via SSE
operationId: runAndStreamScriptByHash
tags:
- job
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- name: hash
in: path
required: true
schema:
type: string
- $ref: "#/components/parameters/ParentJob"
- $ref: "#/components/parameters/WorkerTag"
- $ref: "#/components/parameters/CacheTtl"
- $ref: "#/components/parameters/NewJobId"
- $ref: "#/components/parameters/IncludeHeader"
- $ref: "#/components/parameters/QueueLimit"
- $ref: "#/components/parameters/SkipPreprocessor"
- name: poll_delay_ms
description: delay between polling for job updates in milliseconds
in: query
schema:
type: integer
format: int64
requestBody:
description: script args
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ScriptArgs"
responses:
"200":
description: server-sent events stream of job updates
content:
text/event-stream:
schema:
type: string
get:
summary: run script by hash with GET and stream updates via SSE
operationId: runAndStreamScriptByHashGet
tags:
- job
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- name: hash
in: path
required: true
schema:
type: string
- $ref: "#/components/parameters/ParentJob"
- $ref: "#/components/parameters/WorkerTag"
- $ref: "#/components/parameters/CacheTtl"
- $ref: "#/components/parameters/NewJobId"
- $ref: "#/components/parameters/IncludeHeader"
- $ref: "#/components/parameters/QueueLimit"
- $ref: "#/components/parameters/Payload"
- $ref: "#/components/parameters/SkipPreprocessor"
- name: poll_delay_ms
description: delay between polling for job updates in milliseconds
in: query
schema:
type: integer
format: int64
responses:
"200":
description: server-sent events stream of job updates
content:
text/event-stream:
schema:
type: string
/w/{workspace}/jobs/result_by_id/{flow_job_id}/{node_id}:
get:
summary: get job result by id
@@ -6195,6 +6473,81 @@ paths:
schema:
type: string
/w/{workspace}/flow_conversations/list:
get:
summary: list flow conversations
operationId: listFlowConversations
tags:
- flow_conversation
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PerPage"
- name: flow_path
description: filter conversations by flow path
in: query
schema:
type: string
responses:
"200":
description: flow conversations list
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/FlowConversation"
/w/{workspace}/flow_conversations/delete/{conversation_id}:
delete:
summary: delete flow conversation
operationId: deleteFlowConversation
tags:
- flow_conversation
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- name: conversation_id
description: conversation id
in: path
required: true
schema:
type: string
format: uuid
responses:
"200":
description: flow conversation deleted
content:
text/plain:
schema:
type: string
/w/{workspace}/flow_conversations/{conversation_id}/messages:
get:
summary: list conversation messages
operationId: listConversationMessages
tags:
- flow_conversation
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- name: conversation_id
description: conversation id
in: path
required: true
schema:
type: string
format: uuid
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PerPage"
responses:
"200":
description: conversation messages
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/FlowConversationMessage"
/w/{workspace}/raw_apps/list:
get:
summary: list all raw apps
@@ -6643,6 +6996,23 @@ paths:
schema:
type: string
/w/{workspace}/apps/secret_of_latest_version/{path}:
get:
summary: get public secret of latest version of an app bundle
operationId: getPublicSecretOfLatestVersionOfApp
tags:
- app
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/Path"
responses:
"200":
description: app secret
content:
text/plain:
schema:
type: string
/w/{workspace}/apps/get/v/{id}:
get:
summary: get app by version
@@ -7067,6 +7437,12 @@ paths:
in: query
schema:
type: boolean
- name: memory_id
description: memory ID for chat-enabled flows
in: query
schema:
type: string
format: uuid
requestBody:
description: flow args
required: true
@@ -12022,6 +12398,8 @@ paths:
required: true
schema:
type: string
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PerPage"
responses:
"200":
description: List of autoscaling events
@@ -14382,6 +14760,66 @@ components:
# -- INLINE END --
# Do not change line above
FlowConversation:
type: object
required:
[id, workspace_id, flow_path, created_at, updated_at, created_by]
properties:
id:
type: string
format: uuid
description: Unique identifier for the conversation
workspace_id:
type: string
description: The workspace ID where the conversation belongs
flow_path:
type: string
description: Path of the flow this conversation is for
title:
type: string
description: Optional title for the conversation
nullable: true
created_at:
type: string
format: date-time
description: When the conversation was created
updated_at:
type: string
format: date-time
description: When the conversation was last updated
created_by:
type: string
description: Username who created the conversation
FlowConversationMessage:
type: object
required: [id, conversation_id, message_type, content, created_at]
properties:
id:
type: string
format: uuid
description: Unique identifier for the message
conversation_id:
type: string
format: uuid
description: The conversation this message belongs to
message_type:
type: string
enum: [user, assistant, system]
description: Type of the message
content:
type: string
description: The message content
job_id:
type: string
format: uuid
nullable: true
description: Associated job ID if this message came from a flow run
created_at:
type: string
format: date-time
description: When the message was created
EndpointTool:
type: object
required: [name, description, instructions, path, method]
@@ -15317,6 +15755,8 @@ components:
AuditLog:
type: object
properties:
workspace_id:
type: string
id:
type: integer
timestamp:
@@ -15422,6 +15862,7 @@ components:
span:
type: string
required:
- workspace_id
- id
- timestamp
- username
@@ -16424,6 +16865,8 @@ components:
$ref: "#/components/schemas/ScriptArgs"
can_return_message:
type: boolean
can_return_error_result:
type: boolean
error_handler_path:
type: string
error_handler_args:
@@ -16436,6 +16879,7 @@ components:
- enabled
- filters
- can_return_message
- can_return_error_result
NewWebsocketTrigger:
type: object
@@ -16469,6 +16913,8 @@ components:
$ref: "#/components/schemas/ScriptArgs"
can_return_message:
type: boolean
can_return_error_result:
type: boolean
error_handler_path:
type: string
error_handler_args:
@@ -16483,6 +16929,7 @@ components:
- is_flow
- filters
- can_return_message
- can_return_error_result
EditWebsocketTrigger:
type: object
@@ -16514,6 +16961,8 @@ components:
$ref: "#/components/schemas/ScriptArgs"
can_return_message:
type: boolean
can_return_error_result:
type: boolean
error_handler_path:
type: string
error_handler_args:
@@ -16528,6 +16977,7 @@ components:
- is_flow
- filters
- can_return_message
- can_return_error_result
WebsocketTriggerInitialMessage:
anyOf:
- type: object
@@ -16876,6 +17326,49 @@ components:
- enabled
- aws_auth_resource_type
LoggedWizardStatus:
type: string
enum:
- OK
- SKIP
- FAIL
DucklakeInstanceCatalogDbStatusLogs:
type: object
properties:
super_admin:
$ref: "#/components/schemas/LoggedWizardStatus"
database_credentials:
$ref: "#/components/schemas/LoggedWizardStatus"
valid_dbname:
$ref: "#/components/schemas/LoggedWizardStatus"
created_database:
$ref: "#/components/schemas/LoggedWizardStatus"
description: Created database status log
db_connect:
$ref: "#/components/schemas/LoggedWizardStatus"
grant_permissions:
$ref: "#/components/schemas/LoggedWizardStatus"
DucklakeInstanceCatalogDbStatus:
type: object
required:
- logs
- success
properties:
logs:
$ref: "#/components/schemas/DucklakeInstanceCatalogDbStatusLogs"
success:
type: boolean
description: Whether the operation completed successfully
example: true
error:
type: string
nullable: true
description: Error message if the operation failed
example: "Connection timeout"
NewSqsTrigger:
type: object
properties:
@@ -17570,11 +18063,14 @@ components:
created_by:
type: string
nullable: true
disabled:
type: boolean
required:
- id
- name
- username
- color
- disabled
required:
- email
- workspaces
@@ -17634,6 +18130,25 @@ components:
- owner
- created_at
DependencyMap:
type: object
properties:
workspace_id:
type: string
nullable: true
importer_path:
type: string
nullable: true
importer_kind:
type: string
nullable: true
imported_path:
type: string
nullable: true
importer_node_id:
type: string
nullable: true
WorkspaceInvite:
type: object
properties:

View File

@@ -17,7 +17,7 @@ use crate::db::DB;
use axum::Router;
#[cfg(not(feature = "private"))]
pub fn global_service() -> Router {
pub fn global_service(_job_completed_tx: windmill_worker::JobCompletedSender) -> Router {
Router::new()
}

View File

@@ -88,6 +88,10 @@ pub fn workspaced_service() -> Router {
.route("/get/lite/*path", get(get_app_lite))
.route("/get/draft/*path", get(get_app_w_draft))
.route("/secret_of/*path", get(get_secret_id))
.route(
"/secret_of_latest_version/*path",
get(get_latest_version_secret_id),
)
.route("/get/v/*id", get(get_app_by_id))
.route("/get_data/v/*id", get(get_raw_app_data))
.route("/exists/*path", get(exists_app))
@@ -268,7 +272,7 @@ pub struct CreateApp {
pub custom_path: Option<String>,
}
#[derive(Deserialize)]
#[derive(Serialize, Deserialize)]
pub struct EditApp {
pub path: Option<String>,
pub summary: Option<String>,
@@ -389,19 +393,83 @@ async fn list_apps(
Ok(Json(rows))
}
async fn get_raw_app_data(Path((w_id, version_id)): Path<(String, String)>) -> Result<Response> {
let file_path = format!("/tmp/wmill/{}/{}", w_id, version_id);
let file = tokio::fs::File::open(file_path).await?;
let stream = tokio_util::io::ReaderStream::new(file);
let res = Response::builder().header(
http::header::CONTENT_TYPE,
if version_id.ends_with(".css") {
"text/css"
} else {
"text/javascript"
},
);
Ok(res.body(Body::from_stream(stream)).unwrap())
async fn get_raw_app_data(
Path((w_id, secret_with_ext)): Path<(String, String)>,
Extension(db): Extension<DB>,
) -> Result<Response> {
#[cfg(all(feature = "enterprise", feature = "parquet"))]
let object_store = windmill_common::s3_helpers::get_object_store().await;
// tracing::info!("secret_with_ext: {}", secret_with_ext);
let mut splitted = secret_with_ext.split('.');
let secret_id = splitted.next().unwrap_or("");
if secret_id.is_empty() {
return Err(Error::BadRequest("Invalid secret".to_string()));
}
let id = get_id_from_secret(
&db,
&w_id,
secret_id.to_string(),
Some(BUNDLE_SECRET_PREFIX),
)
.await?;
let file_type = splitted.next().unwrap_or("");
let file_type = if file_type == "css" {
"css"
} else if file_type == "js" {
"js"
} else {
return Err(Error::BadRequest(
"Invalid file type, only .css and .js are supported".to_string(),
));
};
// tracing::info!("file_type: {}", file_type);
#[allow(unused_assignments)]
let mut body: Option<Body> = None;
#[cfg(all(feature = "enterprise", feature = "parquet"))]
if let Some(os) = object_store {
let path = format!("/app_bundles/{}/{}.{}", w_id, id, file_type);
let stream = os
.get(&object_store::path::Path::from(path))
.await?
.bytes()
.await?;
tracing::info!("stream: {}", stream.len());
body = Some(Body::from(stream));
}
if body.is_none() {
let get_raw_app_file = sqlx::query_scalar!(
"SELECT data FROM app_bundles WHERE app_version_id = $1 AND file_type = $2 AND w_id = $3",
id,
file_type,
&w_id,
)
.fetch_optional(&db)
.await?;
if let Some(file) = get_raw_app_file {
body = Some(Body::from(file));
}
}
if let Some(body) = body {
// let stream = tokio_util::io::ReaderStream::new(file);
let res = Response::builder().header(
http::header::CONTENT_TYPE,
if file_type == "css" {
"text/css"
} else {
"text/javascript"
},
);
Ok(res.body(body).unwrap())
} else {
return Err(Error::NotFound("File not found".to_string()));
}
}
// async fn get_app_version(
@@ -692,14 +760,7 @@ async fn get_public_app_by_secret(
Extension(db): Extension<DB>,
Path((w_id, secret)): Path<(String, String)>,
) -> JsonResult<AppWithLastVersion> {
let mc = build_crypt(&db, &w_id).await?;
let decrypted = mc
.decrypt_bytes_to_bytes(&(hex::decode(secret)?))
.map_err(|e| Error::internal_err(e.to_string()))?;
let bytes = str::from_utf8(&decrypted).map_err(to_anyhow)?;
let id: i64 = bytes.parse().map_err(to_anyhow)?;
let id = get_id_from_secret(&db, &w_id, secret, None).await?;
let app_o = sqlx::query_as::<_, AppWithLastVersion>(
"SELECT app.id, app.path, app.summary, app.versions, app.policy, app.custom_path,
@@ -747,6 +808,27 @@ async fn get_public_app_by_secret(
Ok(Json(app))
}
async fn get_id_from_secret(
db: &DB,
w_id: &str,
secret: String,
prefix: Option<&str>,
) -> Result<i64> {
let mc = build_crypt(db, w_id).await?;
let decrypted = mc
.decrypt_bytes_to_bytes(&(hex::decode(secret)?))
.map_err(|e| Error::internal_err(e.to_string()))?;
let mut bytes = str::from_utf8(&decrypted).map_err(to_anyhow)?;
if let Some(prefix) = prefix {
if !bytes.starts_with(prefix) {
return Err(Error::BadRequest("Invalid secret".to_string()));
}
bytes = bytes.strip_prefix(prefix).unwrap_or("");
}
let id: i64 = bytes.parse().map_err(to_anyhow)?;
Ok(id)
}
async fn get_public_resource(
Extension(db): Extension<DB>,
Path((w_id, path)): Path<(String, StripPath)>,
@@ -803,16 +885,85 @@ async fn get_secret_id(
Ok(hx)
}
const BUNDLE_SECRET_PREFIX: &str = "bundle_";
async fn get_latest_version_secret_id(
authed: ApiAuthed,
Extension(user_db): Extension<UserDB>,
Extension(db): Extension<DB>,
Path((w_id, path)): Path<(String, StripPath)>,
) -> Result<String> {
let path = path.to_path();
check_scopes(&authed, || format!("apps:read:{}", path))?;
let mut tx = user_db.begin(&authed).await?;
let id_o = sqlx::query_scalar!(
"SELECT app.versions[array_upper(app.versions, 1)] FROM app
WHERE app.path = $1 AND app.workspace_id = $2",
path,
&w_id
)
.fetch_optional(&mut *tx)
.await?
.flatten();
tx.commit().await?;
let id = not_found_if_none(id_o, "App", path.to_string())?;
let mc = build_crypt(&db, &w_id).await?;
let hx = hex::encode(mc.encrypt_str_to_bytes(format!("{}{}", BUNDLE_SECRET_PREFIX, id)));
Ok(hx)
}
async fn store_raw_app_file<'a>(
w_id: &str,
id: &i64,
file_type: &str,
data: bytes::Bytes,
tx: &mut sqlx::Transaction<'a, sqlx::Postgres>,
) -> Result<()> {
#[cfg(all(feature = "enterprise", feature = "parquet"))]
{
let object_store = windmill_common::s3_helpers::get_object_store().await;
let path: String = format!("/app_bundles/{}/{}.{}", w_id, id, file_type);
if let Some(os) = object_store {
if let Err(e) = os
.put(&object_store::path::Path::from(path.clone()), data.into())
.await
{
tracing::error!("Failed to put snapshot to s3 at {path}: {:?}", e);
return Err(windmill_common::error::Error::ExecutionErr(format!(
"Failed to put {path} to s3"
)));
}
tracing::info!("Successfully put snapshot to s3 at {path}");
return Ok(());
}
}
sqlx::query!(
"INSERT INTO app_bundles (app_version_id, w_id, file_type, data) VALUES ($1, $2, $3, $4)",
id,
w_id,
file_type,
data.to_vec()
)
.execute(&mut **tx)
.await?;
Ok(())
}
macro_rules! process_app_multipart {
($authed:expr, $user_db:expr, $db:expr, $w_id:expr, $path:expr, $multipart:expr, $internal_fn:expr) => {
async {
let mut saved_app = None;
let mut uploaded_js = false;
//todo: use s3 instead
let file_path = format!("/tmp/wmill/{}", $w_id);
std::fs::create_dir_all(&file_path).unwrap();
let mut multipart = $multipart;
while let Some(field) = multipart.next_field().await.unwrap() {
let name = field.name().unwrap().to_string();
@@ -831,9 +982,8 @@ macro_rules! process_app_multipart {
.await?;
saved_app = Some((npath, nid, ntx));
} else if name == "js" {
if let Some((_npath, id, _tx)) = saved_app.as_ref() {
let file_path = format!("{}/{}.js", file_path, id);
std::fs::write(file_path, data).unwrap();
if let Some((_npath, id, tx)) = saved_app.as_mut() {
store_raw_app_file($w_id, &id, "js", data, tx).await?;
uploaded_js = true;
} else {
return Err(Error::BadRequest(
@@ -841,9 +991,8 @@ macro_rules! process_app_multipart {
));
}
} else if name == "css" {
if let Some((_npath, id, _tx)) = saved_app.as_ref() {
let file_path = format!("{}/{}.css", file_path, id);
std::fs::write(file_path, data).unwrap();
if let Some((_npath, id, tx)) = saved_app.as_mut() {
store_raw_app_file($w_id, &id, "css", data, tx).await?;
} else {
return Err(Error::BadRequest(
"App payload need to be created first".to_string(),
@@ -1090,6 +1239,7 @@ async fn create_app_internal<'a>(
None,
Some(&authed.clone().into()),
false,
None,
)
.await?;
tracing::info!("Pushed app dependency job {}", dependency_job_uuid);
@@ -1469,6 +1619,7 @@ async fn update_app_internal<'a>(
None,
Some(&authed.clone().into()),
false,
None,
)
.await?;
tracing::info!("Pushed app dependency job {}", dependency_job_uuid);
@@ -1755,6 +1906,8 @@ async fn execute_component(
(email.as_str(), permissioned_as)
};
let end_user_email = opt_authed.as_ref().map(|a| a.email.clone());
let (uuid, tx) = push(
&db,
tx,
@@ -1784,6 +1937,7 @@ async fn execute_component(
None,
None,
false,
end_user_email,
)
.await?;
tx.commit().await?;

Some files were not shown because too many files have changed in this diff Show More