Compare commits
3 Commits
folder-dep
...
consolidat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f31c68e8be | ||
|
|
31975aaa55 | ||
|
|
2e0a727553 |
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,17 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## [1.672.0](https://github.com/windmill-labs/windmill/compare/v1.671.0...v1.672.0) (2026-04-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add R language support ([#8263](https://github.com/windmill-labs/windmill/issues/8263)) ([a46aa64](https://github.com/windmill-labs/windmill/commit/a46aa641f9d72809c52a0eb11a877a0f2d587c32))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* approval page freeze, stale state, and missing approval link ([#8653](https://github.com/windmill-labs/windmill/issues/8653)) ([7069202](https://github.com/windmill-labs/windmill/commit/70692021909443b86ed61fa621fe49f28742fb54))
|
||||
|
||||
## [1.671.0](https://github.com/windmill-labs/windmill/compare/v1.670.0...v1.671.0) (2026-03-31)
|
||||
|
||||
|
||||
|
||||
153
backend/Cargo.lock
generated
153
backend/Cargo.lock
generated
@@ -15941,7 +15941,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-nats",
|
||||
@@ -16019,7 +16019,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-alerting"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"chrono",
|
||||
@@ -16032,7 +16032,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argon2",
|
||||
@@ -16173,7 +16173,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-agent-workers"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"chrono",
|
||||
@@ -16196,7 +16196,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-assets"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"chrono",
|
||||
@@ -16209,7 +16209,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-auth"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum 0.8.4",
|
||||
@@ -16235,7 +16235,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-client"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"reqwest 0.12.28",
|
||||
"serde",
|
||||
@@ -16245,7 +16245,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-configs"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"chrono",
|
||||
@@ -16262,7 +16262,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-debug"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"base64 0.22.1",
|
||||
@@ -16285,7 +16285,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-embeddings"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum 0.8.4",
|
||||
@@ -16308,7 +16308,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-flow-conversations"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"chrono",
|
||||
@@ -16324,7 +16324,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-flows"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"chrono",
|
||||
@@ -16344,7 +16344,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-groups"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"chrono",
|
||||
@@ -16364,7 +16364,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-inputs"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"chrono",
|
||||
@@ -16378,7 +16378,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-integration-tests"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-nats",
|
||||
@@ -16409,7 +16409,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-jobs"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum 0.8.4",
|
||||
@@ -16434,7 +16434,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-npm-proxy"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"flate2",
|
||||
@@ -16452,7 +16452,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-openapi"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum 0.8.4",
|
||||
@@ -16474,7 +16474,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-schedule"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"chrono",
|
||||
@@ -16494,7 +16494,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-scripts"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"chrono",
|
||||
@@ -16524,7 +16524,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-settings"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum 0.8.4",
|
||||
@@ -16551,7 +16551,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-sse"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"serde",
|
||||
@@ -16563,12 +16563,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-users"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"axum 0.8.4",
|
||||
"chrono",
|
||||
"dashmap 6.1.0",
|
||||
"http 1.4.0",
|
||||
"hyper 1.9.0",
|
||||
"lazy_static",
|
||||
@@ -16588,7 +16587,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-workers"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"chrono",
|
||||
@@ -16602,7 +16601,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-workspaces"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"axum 0.8.4",
|
||||
"chrono",
|
||||
@@ -16634,7 +16633,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-audit"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"lazy_static",
|
||||
@@ -16648,7 +16647,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-autoscaling"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum 0.8.4",
|
||||
@@ -16667,7 +16666,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-common"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"aho-corasick",
|
||||
@@ -16769,7 +16768,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-dep-map"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"itertools 0.14.0",
|
||||
@@ -16788,7 +16787,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-git-sync"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"regex",
|
||||
"serde",
|
||||
@@ -16803,7 +16802,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-indexer"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"astral-tokio-tar",
|
||||
@@ -16827,7 +16826,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-jseval"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"futures",
|
||||
@@ -16844,7 +16843,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-macros"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"itertools 0.14.0",
|
||||
"lazy_static",
|
||||
@@ -16860,7 +16859,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-mcp"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -16881,7 +16880,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-native-triggers"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -16912,7 +16911,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-oauth"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-oauth2",
|
||||
@@ -16936,7 +16935,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-object-store"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
@@ -16970,7 +16969,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-operator"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"futures",
|
||||
@@ -16988,7 +16987,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"convert_case 0.6.0",
|
||||
"serde",
|
||||
@@ -16997,7 +16996,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-bash"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -17009,7 +17008,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-csharp"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde_json",
|
||||
@@ -17021,7 +17020,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-go"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"gosyn",
|
||||
@@ -17033,7 +17032,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-graphql"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -17045,7 +17044,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-java"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde_json",
|
||||
@@ -17057,7 +17056,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-nu"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"nu-parser",
|
||||
@@ -17068,7 +17067,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-php"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.14.0",
|
||||
@@ -17079,7 +17078,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.14.0",
|
||||
@@ -17091,7 +17090,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py-asset"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"rustpython-ast",
|
||||
@@ -17102,7 +17101,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py-imports"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -17124,7 +17123,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-r"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde_json",
|
||||
@@ -17136,7 +17135,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-ruby"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -17150,7 +17149,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-rust"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"convert_case 0.6.0",
|
||||
@@ -17167,7 +17166,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-sql"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -17180,7 +17179,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-sql-asset"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
@@ -17192,7 +17191,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-ts"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -17210,7 +17209,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-ts-asset"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde-wasm-bindgen",
|
||||
@@ -17226,7 +17225,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-wac"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"rustpython-ast",
|
||||
@@ -17242,7 +17241,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-yaml"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
@@ -17253,7 +17252,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-queue"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -17290,7 +17289,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-runtime-nativets"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"const_format",
|
||||
@@ -17328,7 +17327,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-sql-datatype-parser-wasm"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"wasm-bindgen",
|
||||
@@ -17339,7 +17338,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-store"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -17368,7 +17367,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-test-utils"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -17392,7 +17391,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-trigger"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -17425,7 +17424,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-trigger-email"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -17445,7 +17444,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-trigger-gcp"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -17479,7 +17478,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-trigger-http"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -17515,7 +17514,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-trigger-kafka"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -17538,7 +17537,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-trigger-mqtt"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -17562,7 +17561,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-trigger-nats"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-nats",
|
||||
@@ -17586,7 +17585,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-trigger-postgres"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -17621,7 +17620,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-trigger-sqs"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -17649,7 +17648,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-trigger-websocket"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -17672,7 +17671,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-types"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.9.4",
|
||||
@@ -17691,7 +17690,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-worker"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-once-cell",
|
||||
@@ -17801,7 +17800,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-worker-volumes"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "windmill"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
@@ -85,7 +85,7 @@ members = [
|
||||
exclude = ["./windmill-duckdb-ffi-internal", "./parsers/windmill-parser-wasm"]
|
||||
|
||||
[workspace.package]
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
|
||||
edition = "2021"
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
-- No-op: this migration is a data fixup and cannot be reversed.
|
||||
@@ -1,48 +0,0 @@
|
||||
-- Pre-fix: before permissioned_as migration drops the email column, update edited_by
|
||||
-- for triggers where the user (edited_by) is not in the workspace but is a superadmin.
|
||||
-- This ensures the subsequent 20260318000000 migration stores the raw email as permissioned_as
|
||||
-- (via the `edited_by LIKE '%@%'` branch).
|
||||
-- For instances that already applied 20260318000000, this is a no-op (email column is gone);
|
||||
-- the 20260401000000 migration handles those as a fallback.
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
trigger_table TEXT;
|
||||
has_email BOOLEAN;
|
||||
BEGIN
|
||||
FOREACH trigger_table IN ARRAY ARRAY[
|
||||
'http_trigger',
|
||||
'websocket_trigger',
|
||||
'postgres_trigger',
|
||||
'mqtt_trigger',
|
||||
'kafka_trigger',
|
||||
'nats_trigger',
|
||||
'sqs_trigger',
|
||||
'gcp_trigger',
|
||||
'email_trigger'
|
||||
]
|
||||
LOOP
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name = trigger_table AND column_name = 'email'
|
||||
) INTO has_email;
|
||||
|
||||
IF has_email THEN
|
||||
EXECUTE format($q$
|
||||
UPDATE %I t
|
||||
SET edited_by = t.email
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM usr u
|
||||
WHERE u.username = t.edited_by
|
||||
AND u.workspace_id = t.workspace_id
|
||||
)
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM password p
|
||||
WHERE p.email = t.email
|
||||
AND p.super_admin = true
|
||||
)
|
||||
$q$, trigger_table);
|
||||
END IF;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
@@ -84,7 +84,7 @@ fi
|
||||
|
||||
if [ "$REVERT" == "YES" ]; then
|
||||
backend_dirpath="${root_dirpath}/backend/"
|
||||
for ce_file in $(find "${root_dirpath}/backend" \( -name "*_ee.rs" -o -name "ee.rs" \)); do
|
||||
for ce_file in $(find "${root_dirpath}/backend" -name "*_ee.rs"); do
|
||||
if [ -L "${ce_file}" ]; then
|
||||
rm "${ce_file}"
|
||||
echo "Deleted symlink '${ce_file}'"
|
||||
|
||||
@@ -21,7 +21,6 @@ windmill-api-auth.workspace = true
|
||||
windmill-audit.workspace = true
|
||||
windmill-git-sync.workspace = true
|
||||
|
||||
dashmap.workspace = true
|
||||
argon2.workspace = true
|
||||
axum.workspace = true
|
||||
chrono.workspace = true
|
||||
|
||||
@@ -12,7 +12,6 @@ use sqlx::{Postgres, Transaction};
|
||||
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
use std::sync::LazyLock;
|
||||
use std::time::Duration;
|
||||
|
||||
use windmill_api_auth::ApiAuthed;
|
||||
@@ -61,43 +60,6 @@ use windmill_git_sync::handle_deployment_metadata;
|
||||
|
||||
pub const COOKIE_PATH: &str = "/";
|
||||
|
||||
const TOKEN_CREATE_LIMIT_PER_MINUTE: i32 = 10;
|
||||
|
||||
struct TokenRateLimitEntry {
|
||||
count: i32,
|
||||
minute_bucket: i64,
|
||||
}
|
||||
|
||||
static TOKEN_CREATE_RATE_LIMIT: LazyLock<dashmap::DashMap<String, TokenRateLimitEntry>> =
|
||||
LazyLock::new(dashmap::DashMap::new);
|
||||
|
||||
fn check_token_create_rate_limit(username: &str) -> Result<()> {
|
||||
if !*CLOUD_HOSTED {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let current_minute = chrono::Utc::now().timestamp() / 60;
|
||||
|
||||
let mut entry = TOKEN_CREATE_RATE_LIMIT
|
||||
.entry(username.to_string())
|
||||
.or_insert(TokenRateLimitEntry { count: 0, minute_bucket: current_minute });
|
||||
|
||||
if entry.minute_bucket != current_minute {
|
||||
entry.count = 0;
|
||||
entry.minute_bucket = current_minute;
|
||||
}
|
||||
|
||||
if entry.count >= TOKEN_CREATE_LIMIT_PER_MINUTE {
|
||||
return Err(Error::Generic(
|
||||
StatusCode::TOO_MANY_REQUESTS,
|
||||
"Too many token creation requests. Please try again later.".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
entry.count += 1;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn workspaced_service() -> Router {
|
||||
Router::new()
|
||||
.route("/list", get(list_users))
|
||||
@@ -2013,8 +1975,6 @@ async fn create_token(
|
||||
authed: ApiAuthed,
|
||||
Json(token_config): Json<NewToken>,
|
||||
) -> Result<(StatusCode, String)> {
|
||||
check_token_create_rate_limit(&authed.username)?;
|
||||
|
||||
let mut tx = db.begin().await?;
|
||||
|
||||
let token = create_token_internal(&mut *tx, &db, &authed, token_config).await?;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
version: 1.672.0
|
||||
version: 1.671.0
|
||||
title: Windmill API
|
||||
|
||||
contact:
|
||||
|
||||
@@ -2,7 +2,7 @@ import { sleep } from "https://deno.land/x/sleep@v1.2.1/mod.ts";
|
||||
import * as windmill from "https://deno.land/x/windmill@v1.174.0/mod.ts";
|
||||
import * as api from "https://deno.land/x/windmill@v1.174.0/windmill-api/index.ts";
|
||||
|
||||
export const VERSION = "v1.672.0";
|
||||
export const VERSION = "v1.671.0";
|
||||
|
||||
export async function login(email: string, password: string): Promise<string> {
|
||||
return await windmill.UserService.login({
|
||||
|
||||
@@ -2801,32 +2801,9 @@ export async function push(
|
||||
}
|
||||
}
|
||||
for (const folderName of folderNames) {
|
||||
const basePath = path.join("f", folderName, "folder.meta.yaml");
|
||||
const branchPath = getBranchSpecificPath(
|
||||
`f/${folderName}/folder.meta.yaml`,
|
||||
specificItems,
|
||||
opts.branch,
|
||||
);
|
||||
let found = false;
|
||||
// Check branch-specific variant first (e.g. folder.dev.meta.yaml)
|
||||
if (branchPath) {
|
||||
try {
|
||||
await stat(branchPath);
|
||||
found = true;
|
||||
} catch {
|
||||
// fall through to base path check
|
||||
}
|
||||
}
|
||||
// Then check base path
|
||||
if (!found) {
|
||||
try {
|
||||
await stat(basePath);
|
||||
found = true;
|
||||
} catch {
|
||||
// not found
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
try {
|
||||
await stat(path.join("f", folderName, "folder.meta.yaml"));
|
||||
} catch {
|
||||
missingFolders.push(folderName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ export {
|
||||
token,
|
||||
};
|
||||
|
||||
export const VERSION = "1.672.0";
|
||||
export const VERSION = "1.671.0";
|
||||
|
||||
// Re-exported from constants.ts to maintain backwards compatibility
|
||||
export { WM_FORK_PREFIX } from "./core/constants.ts";
|
||||
|
||||
@@ -397,39 +397,4 @@ describe("sync push missing folder detection", () => {
|
||||
expect(output).not.toContain("Missing folder.meta.yaml");
|
||||
});
|
||||
});
|
||||
|
||||
test("no warning when branch-specific folder.meta.yaml exists", async () => {
|
||||
await withIsolatedWorkspace(async ({ tempDir, runCLICommand }) => {
|
||||
const uniqueId = Date.now();
|
||||
const folderName = `branchmeta${uniqueId}`;
|
||||
|
||||
// wmill.yaml with branch-specific folders configured
|
||||
await writeFile(
|
||||
join(tempDir, "wmill.yaml"),
|
||||
`defaultTs: bun\nincludes:\n - "**"\nexcludes: []\ngitBranches:\n dev:\n specificItems:\n folders:\n - "f/${folderName}"\n`,
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
// Create folder with branch-specific meta only (no base folder.meta.yaml)
|
||||
await mkdir(join(tempDir, "f", folderName), { recursive: true });
|
||||
await writeFile(
|
||||
join(tempDir, "f", folderName, "folder.dev.meta.yaml"),
|
||||
`summary: ""\ndisplay_name: "${folderName}"\nowners: []\nextra_perms: {}\n`,
|
||||
"utf-8"
|
||||
);
|
||||
await writeFile(
|
||||
join(tempDir, "f", folderName, "test_script.ts"),
|
||||
'export async function main() { return "hello"; }',
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
const result = await runCLICommand(
|
||||
["sync", "push", "--yes", "--branch", "dev", "--includes", `f/${folderName}/**`],
|
||||
);
|
||||
|
||||
expect(result.code).toEqual(0);
|
||||
const output = result.stdout + result.stderr;
|
||||
expect(output).not.toContain("Missing folder.meta.yaml");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
56
frontend/package-lock.json
generated
56
frontend/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "windmill-components",
|
||||
"version": "1.672.0",
|
||||
"version": "1.671.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "windmill-components",
|
||||
"version": "1.672.0",
|
||||
"version": "1.671.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
@@ -83,7 +83,7 @@
|
||||
"windmill-parser-wasm-nu": "1.510.1",
|
||||
"windmill-parser-wasm-php": "1.647.1",
|
||||
"windmill-parser-wasm-py": "1.657.2",
|
||||
"windmill-parser-wasm-r": "1.668.1",
|
||||
"windmill-parser-wasm-r": "^1.668.1",
|
||||
"windmill-parser-wasm-regex": "1.653.0",
|
||||
"windmill-parser-wasm-ruby": "1.526.1",
|
||||
"windmill-parser-wasm-rust": "1.647.1",
|
||||
@@ -844,7 +844,6 @@
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.0.tgz",
|
||||
"integrity": "sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
@@ -856,7 +855,6 @@
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.0.tgz",
|
||||
"integrity": "sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
@@ -867,7 +865,6 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz",
|
||||
"integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
@@ -1357,7 +1354,6 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz",
|
||||
"integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
@@ -1514,7 +1510,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1531,7 +1526,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1548,7 +1542,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1565,7 +1558,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1582,7 +1574,6 @@
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1599,7 +1590,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1616,7 +1606,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1633,7 +1622,6 @@
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1650,7 +1638,6 @@
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1667,7 +1654,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1684,7 +1670,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1701,7 +1686,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1718,7 +1702,6 @@
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
@@ -1735,7 +1718,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -1752,7 +1734,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -2058,7 +2039,6 @@
|
||||
"version": "0.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
|
||||
"integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
@@ -6867,7 +6847,7 @@
|
||||
"version": "1.21.7",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
|
||||
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"jiti": "bin/jiti.js"
|
||||
@@ -7366,7 +7346,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -7387,7 +7366,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -7408,7 +7386,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -7429,7 +7406,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -7450,7 +7426,6 @@
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -7471,7 +7446,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -7492,7 +7466,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -7513,7 +7486,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -7534,7 +7506,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -7555,7 +7526,6 @@
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -7576,7 +7546,6 @@
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -12152,21 +12121,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-check/node_modules/picomatch": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-eslint-parser": {
|
||||
"version": "0.43.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.43.0.tgz",
|
||||
@@ -12897,7 +12851,7 @@
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "windmill-components",
|
||||
"version": "1.672.0",
|
||||
"version": "1.671.0",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
const app = await AppService.getAppByPath({ workspace, path })
|
||||
return app.summary
|
||||
} else if (kind === 'folder') {
|
||||
const folder = await FolderService.getFolder({ workspace, name: path.replace(/^f\//, '') })
|
||||
const folder = await FolderService.getFolder({ workspace, name: path.slice(2) })
|
||||
return folder.summary
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -361,14 +361,7 @@
|
||||
|
||||
const parent = parentWorkspaceId
|
||||
const current = currentWorkspaceId
|
||||
const sortedItems = [...selectedItems].sort((a, b) => {
|
||||
const aIsFolder = a.startsWith('folder:')
|
||||
const bIsFolder = b.startsWith('folder:')
|
||||
if (aIsFolder && !bIsFolder) return -1
|
||||
if (!aIsFolder && bIsFolder) return 1
|
||||
return 0
|
||||
})
|
||||
for (const itemKey of sortedItems) {
|
||||
for (const itemKey of selectedItems) {
|
||||
const diff = selectableDiffs.find((d) => itemKey == getItemKey(d))
|
||||
|
||||
if (!diff) {
|
||||
|
||||
@@ -132,14 +132,10 @@
|
||||
}
|
||||
})
|
||||
for (const dep of sortedSet) {
|
||||
try {
|
||||
allAlreadyExists[computeStatusPath(dep.kind, dep.path)] = await checkAlreadyExists(
|
||||
dep.kind,
|
||||
dep.path
|
||||
)
|
||||
} catch {
|
||||
allAlreadyExists[computeStatusPath(dep.kind, dep.path)] = false
|
||||
}
|
||||
allAlreadyExists[computeStatusPath(dep.kind, dep.path)] = await checkAlreadyExists(
|
||||
dep.kind,
|
||||
dep.path
|
||||
)
|
||||
}
|
||||
dependencies = sortedSet.map((x) => ({
|
||||
...x,
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
import Skeleton from './common/skeleton/Skeleton.svelte'
|
||||
import Button from './common/button/Button.svelte'
|
||||
import { sameTopDomainOrigin } from '$lib/cookies'
|
||||
import { isValidLogoutRedirect } from '$lib/logoutRedirect'
|
||||
|
||||
interface Props {
|
||||
rd?: string | undefined
|
||||
@@ -135,11 +134,7 @@
|
||||
|
||||
async function redirectUser() {
|
||||
if (rd?.startsWith('http')) {
|
||||
if (isValidLogoutRedirect(rd)) {
|
||||
window.location.href = rd
|
||||
return
|
||||
}
|
||||
goto('/')
|
||||
window.location.href = rd
|
||||
return
|
||||
}
|
||||
if ($workspaceStore) {
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
import WorkspaceFlowList from './WorkspaceFlowList.svelte'
|
||||
import { createEventDispatcher, untrack } from 'svelte'
|
||||
import type { Schema } from '$lib/common'
|
||||
import { emptySchema } from '$lib/utils'
|
||||
import { schemaToInputsSpec } from '$lib/components/apps/utils'
|
||||
import { defaultIfEmptyString, emptySchema } from '$lib/utils'
|
||||
import { loadSchema } from '$lib/infer'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { buildPathRunnableSelection } from './runnableSelectorUtils'
|
||||
|
||||
type TabType = 'hubscripts' | 'workspacescripts' | 'workspaceflows' | 'inlinescripts'
|
||||
|
||||
@@ -62,44 +62,51 @@
|
||||
}
|
||||
|
||||
async function pickScript(path: string) {
|
||||
const selection = buildPathRunnableSelection(
|
||||
const schema = await loadSchemaFromTriggerable(path, 'script')
|
||||
const fields = schemaToInputsSpec(schema.schema, defaultUserInput)
|
||||
const runnable = {
|
||||
type: 'path',
|
||||
path,
|
||||
'script',
|
||||
await loadSchemaFromTriggerable(path, 'script'),
|
||||
defaultUserInput,
|
||||
rawApps
|
||||
)
|
||||
runType: 'script',
|
||||
schema: schema.schema,
|
||||
name: defaultIfEmptyString(schema.summary, path)
|
||||
} as const
|
||||
|
||||
dispatch('pick', {
|
||||
runnable: selection.runnable,
|
||||
fields: selection.fields
|
||||
runnable,
|
||||
fields
|
||||
})
|
||||
}
|
||||
|
||||
async function pickFlow(path: string) {
|
||||
const selection = buildPathRunnableSelection(
|
||||
const schema = await loadSchemaFromTriggerable(path, 'flow')
|
||||
const fields = schemaToInputsSpec(schema.schema, defaultUserInput)
|
||||
const runnable = {
|
||||
type: 'path',
|
||||
path,
|
||||
'flow',
|
||||
await loadSchemaFromTriggerable(path, 'flow'),
|
||||
defaultUserInput,
|
||||
rawApps
|
||||
)
|
||||
runType: 'flow',
|
||||
schema,
|
||||
name: defaultIfEmptyString(schema.summary, path)
|
||||
} as const
|
||||
dispatch('pick', {
|
||||
runnable: selection.runnable,
|
||||
fields: selection.fields
|
||||
runnable,
|
||||
fields
|
||||
})
|
||||
}
|
||||
|
||||
async function pickHubScript(path: string) {
|
||||
const selection = buildPathRunnableSelection(
|
||||
const schema = await loadSchemaFromTriggerable(path, 'hubscript')
|
||||
const fields = schemaToInputsSpec(schema.schema, defaultUserInput)
|
||||
const runnable = {
|
||||
type: 'path',
|
||||
path,
|
||||
'hubscript',
|
||||
await loadSchemaFromTriggerable(path, 'hubscript'),
|
||||
defaultUserInput,
|
||||
rawApps
|
||||
)
|
||||
runType: 'hubscript',
|
||||
schema: schema.schema,
|
||||
name: defaultIfEmptyString(schema.summary, path)
|
||||
} as const
|
||||
dispatch('pick', {
|
||||
runnable: selection.runnable,
|
||||
fields: selection.fields
|
||||
runnable,
|
||||
fields
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import type { LoadedRunnableSchema } from './runnableSelectorUtils'
|
||||
import { buildPathRunnableSelection } from './runnableSelectorUtils'
|
||||
|
||||
const loadedSchema: LoadedRunnableSchema = {
|
||||
summary: 'My flow',
|
||||
schema: {
|
||||
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
||||
type: 'object',
|
||||
required: ['string_input'],
|
||||
properties: {
|
||||
string_input: {
|
||||
type: 'string',
|
||||
default: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe('buildPathRunnableSelection', () => {
|
||||
it('keeps the actual schema object and defaults raw-app fields to user mode', () => {
|
||||
const selection = buildPathRunnableSelection(
|
||||
'u/dev/my_flow',
|
||||
'flow',
|
||||
loadedSchema,
|
||||
false,
|
||||
true
|
||||
)
|
||||
|
||||
expect(selection.runnable).toMatchObject({
|
||||
type: 'path',
|
||||
path: 'u/dev/my_flow',
|
||||
runType: 'flow',
|
||||
schema: loadedSchema.schema,
|
||||
name: 'My flow'
|
||||
})
|
||||
expect(selection.fields.string_input.type).toBe('user')
|
||||
expect(selection.fields.string_input.value).toBe('')
|
||||
})
|
||||
|
||||
it('preserves static defaults for non-raw-app pickers', () => {
|
||||
const selection = buildPathRunnableSelection(
|
||||
'u/dev/my_flow',
|
||||
'flow',
|
||||
loadedSchema,
|
||||
false,
|
||||
false
|
||||
)
|
||||
|
||||
expect(selection.fields.string_input.type).toBe('static')
|
||||
})
|
||||
})
|
||||
@@ -1,31 +0,0 @@
|
||||
import type { Schema } from '$lib/common'
|
||||
import type { Runnable, StaticAppInput } from '$lib/components/apps/inputType'
|
||||
import { schemaToInputsSpec } from '$lib/components/apps/utils'
|
||||
import { defaultIfEmptyString } from '$lib/utils'
|
||||
|
||||
export type LoadedRunnableSchema = {
|
||||
schema: Schema
|
||||
summary: string | undefined
|
||||
}
|
||||
|
||||
export function buildPathRunnableSelection(
|
||||
path: string,
|
||||
runType: 'script' | 'flow' | 'hubscript',
|
||||
loadedSchema: LoadedRunnableSchema,
|
||||
defaultUserInput: boolean,
|
||||
rawApps: boolean
|
||||
): {
|
||||
runnable: Runnable
|
||||
fields: Record<string, StaticAppInput>
|
||||
} {
|
||||
return {
|
||||
runnable: {
|
||||
type: 'path',
|
||||
path,
|
||||
runType,
|
||||
schema: loadedSchema.schema,
|
||||
name: defaultIfEmptyString(loadedSchema.summary, path)
|
||||
},
|
||||
fields: schemaToInputsSpec(loadedSchema.schema, defaultUserInput || rawApps)
|
||||
}
|
||||
}
|
||||
@@ -98,9 +98,7 @@
|
||||
() => aiChatManager.contextManager.getSelectedContext(),
|
||||
(sc) => aiChatManager.contextManager.setSelectedContext(sc)
|
||||
}
|
||||
availableContext={aiChatManager.mode === AIMode.APP
|
||||
? aiChatManager.getAppAvailableContext()
|
||||
: aiChatManager.contextManager.getAvailableContext()}
|
||||
availableContext={aiChatManager.contextManager.getAvailableContext()}
|
||||
messages={aiChatManager.currentReply
|
||||
? [
|
||||
...aiChatManager.displayMessages,
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
import { type Snippet } from 'svelte'
|
||||
import {
|
||||
CheckIcon,
|
||||
Code2,
|
||||
FileCode,
|
||||
HistoryIcon,
|
||||
Loader2,
|
||||
MousePointer2,
|
||||
@@ -26,7 +24,7 @@
|
||||
import { aiChatManager, AIMode } from './AIChatManager.svelte'
|
||||
import AIChatInput from './AIChatInput.svelte'
|
||||
import { getModifierKey } from '$lib/utils'
|
||||
import type { SelectedContext } from './app/core'
|
||||
import type { AppTransientContext } from './app/core'
|
||||
|
||||
let {
|
||||
messages,
|
||||
@@ -103,11 +101,11 @@
|
||||
)
|
||||
|
||||
// Get app context for display when in APP mode
|
||||
const appContext = $derived.by((): SelectedContext | undefined => {
|
||||
const appContext = $derived.by((): AppTransientContext | undefined => {
|
||||
if (aiChatManager.mode !== AIMode.APP || !aiChatManager.appAiChatHelpers) {
|
||||
return undefined
|
||||
}
|
||||
return aiChatManager.appAiChatHelpers.getSelectedContext()
|
||||
return aiChatManager.appAiChatHelpers.getTransientContext()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -293,38 +291,7 @@
|
||||
{/if}
|
||||
<ProviderModelSelector />
|
||||
|
||||
{#if aiChatManager.mode === AIMode.APP && appContext && (appContext.type !== 'none' || appContext.inspectorElement || appContext.codeSelection)}
|
||||
{#if appContext.type === 'frontend' && appContext.frontendPath && !appContext.selectionExcluded}
|
||||
<div
|
||||
class="inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 text-2xs"
|
||||
title={appContext.frontendPath}
|
||||
>
|
||||
<FileCode class="w-3 h-3" />
|
||||
<span class="truncate max-w-[80px]">{appContext.frontendPath}</span>
|
||||
<button
|
||||
class="hover:bg-blue-200 dark:hover:bg-blue-800/50 rounded p-0.5 -mr-0.5"
|
||||
onclick={() => appContext.toggleSelectionExcluded?.()}
|
||||
title="Exclude from prompt"
|
||||
>
|
||||
<X class="w-2.5 h-2.5" />
|
||||
</button>
|
||||
</div>
|
||||
{:else if appContext.type === 'backend' && appContext.backendKey && !appContext.selectionExcluded}
|
||||
<div
|
||||
class="inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300 text-2xs"
|
||||
title={appContext.backendKey}
|
||||
>
|
||||
<Code2 class="w-3 h-3" />
|
||||
<span class="truncate max-w-[80px]">{appContext.backendKey}</span>
|
||||
<button
|
||||
class="hover:bg-green-200 dark:hover:bg-green-800/50 rounded p-0.5 -mr-0.5"
|
||||
onclick={() => appContext.toggleSelectionExcluded?.()}
|
||||
title="Exclude from prompt"
|
||||
>
|
||||
<X class="w-2.5 h-2.5" />
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
{#if aiChatManager.mode === AIMode.APP && appContext && (appContext.inspectorElement || appContext.codeSelection)}
|
||||
{#if appContext.inspectorElement}
|
||||
<div
|
||||
class="inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300 text-2xs"
|
||||
|
||||
@@ -11,7 +11,8 @@ import {
|
||||
getAppTools,
|
||||
prepareAppSystemMessage,
|
||||
prepareAppUserMessage,
|
||||
type AppAIChatHelpers
|
||||
type AppAIChatHelpers,
|
||||
type AppSelection
|
||||
} from './app/core'
|
||||
import ContextManager from './ContextManager.svelte'
|
||||
import HistoryManager from './HistoryManager.svelte'
|
||||
@@ -445,10 +446,7 @@ class AIChatManager {
|
||||
if (!pendingPrompt) return undefined
|
||||
this.pendingPrompt = ''
|
||||
if (this.mode === AIMode.SCRIPT) {
|
||||
return prepareScriptUserMessage(
|
||||
pendingPrompt,
|
||||
this.contextManager.getSelectedContext()
|
||||
)
|
||||
return prepareScriptUserMessage(pendingPrompt, this.contextManager.getSelectedContext())
|
||||
} else if (this.mode === AIMode.FLOW) {
|
||||
return prepareFlowUserMessage(
|
||||
pendingPrompt,
|
||||
@@ -627,7 +625,7 @@ class AIChatManager {
|
||||
role: 'user',
|
||||
content: this.instructions,
|
||||
contextElements:
|
||||
this.mode === AIMode.SCRIPT || this.mode === AIMode.FLOW
|
||||
this.mode === AIMode.SCRIPT || this.mode === AIMode.FLOW || this.mode === AIMode.APP
|
||||
? oldSelectedContext
|
||||
: undefined,
|
||||
snapshot,
|
||||
@@ -668,7 +666,7 @@ class AIChatManager {
|
||||
case AIMode.APP:
|
||||
userMessage = prepareAppUserMessage(
|
||||
oldInstructions,
|
||||
this.appAiChatHelpers?.getSelectedContext(),
|
||||
this.appAiChatHelpers?.getTransientContext(),
|
||||
oldSelectedContext
|
||||
)
|
||||
break
|
||||
@@ -903,6 +901,11 @@ class AIChatManager {
|
||||
!copilotSessionModel?.model.endsWith('/thinking'),
|
||||
untrack(() => this.contextManager.getSelectedContext())
|
||||
)
|
||||
} else if (this.mode === AIMode.APP) {
|
||||
this.contextManager.updateAvailableContextForApp(
|
||||
this.getAppAvailableContext(),
|
||||
untrack(() => this.contextManager.getSelectedContext())
|
||||
)
|
||||
}
|
||||
|
||||
if (this.scriptEditorOptions) {
|
||||
@@ -910,6 +913,15 @@ class AIChatManager {
|
||||
}
|
||||
}
|
||||
|
||||
syncAppSelection = (selectedContext: AppSelection | undefined) => {
|
||||
const availableContext = this.getAppAvailableContext()
|
||||
this.contextManager.updateAvailableContextForApp(
|
||||
availableContext,
|
||||
untrack(() => this.contextManager.getSelectedContext())
|
||||
)
|
||||
this.contextManager.setSelectedAppContext(selectedContext, availableContext)
|
||||
}
|
||||
|
||||
listenForDbSchemasChanges = (dbSchemas: DBSchemas) => {
|
||||
this.displayMessages = ContextManager.updateDisplayMessages(
|
||||
untrack(() => this.displayMessages),
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { FlowModule } from '$lib/gen'
|
||||
import type { DisplayMessage } from './shared'
|
||||
import { langToExt } from '$lib/editorLangUtils'
|
||||
import type { ExtendedOpenFlow } from '$lib/components/flows/types'
|
||||
import type { AppSelection } from './app/core'
|
||||
|
||||
export interface ScriptOptions {
|
||||
lang: ScriptLang | 'bunnative'
|
||||
@@ -285,6 +286,40 @@ export default class ContextManager {
|
||||
return this.availableContext
|
||||
}
|
||||
|
||||
updateAvailableContextForApp(
|
||||
availableContext: ContextElement[],
|
||||
currentlySelectedContext: ContextElement[]
|
||||
) {
|
||||
const newSelectedContext: ContextElement[] = []
|
||||
|
||||
for (const context of currentlySelectedContext) {
|
||||
if (context.type === 'app_code_selection') {
|
||||
newSelectedContext.push(context)
|
||||
continue
|
||||
}
|
||||
|
||||
if (
|
||||
context.type === 'app_frontend_file' ||
|
||||
context.type === 'app_backend_runnable' ||
|
||||
context.type === 'app_datatable'
|
||||
) {
|
||||
const refreshedContext = availableContext.find(
|
||||
(available) => available.type === context.type && available.title === context.title
|
||||
)
|
||||
|
||||
if (refreshedContext) {
|
||||
newSelectedContext.push({
|
||||
...refreshedContext,
|
||||
activeSelection: context.activeSelection
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.availableContext = availableContext
|
||||
this.selectedContext = newSelectedContext
|
||||
}
|
||||
|
||||
setScriptOptions(scriptOptions: ScriptOptions) {
|
||||
this.scriptOptions = scriptOptions
|
||||
}
|
||||
@@ -422,6 +457,47 @@ export default class ContextManager {
|
||||
}
|
||||
}
|
||||
|
||||
setSelectedAppContext(
|
||||
selectedContext: AppSelection | undefined,
|
||||
availableContext: ContextElement[] | undefined
|
||||
) {
|
||||
this.selectedContext = this.selectedContext.filter(
|
||||
(context) =>
|
||||
!(
|
||||
context.activeSelection &&
|
||||
(context.type === 'app_frontend_file' || context.type === 'app_backend_runnable')
|
||||
)
|
||||
)
|
||||
|
||||
if (!availableContext) {
|
||||
return
|
||||
}
|
||||
|
||||
const selectedAppContext =
|
||||
selectedContext?.type === 'frontend' && selectedContext.frontendPath
|
||||
? availableContext.find(
|
||||
(context) =>
|
||||
context.type === 'app_frontend_file' && context.title === selectedContext.frontendPath
|
||||
)
|
||||
: selectedContext?.type === 'backend' && selectedContext.backendKey
|
||||
? availableContext.find(
|
||||
(context) =>
|
||||
context.type === 'app_backend_runnable' &&
|
||||
context.title === selectedContext.backendKey
|
||||
)
|
||||
: undefined
|
||||
|
||||
if (selectedAppContext) {
|
||||
this.selectedContext = [
|
||||
{ ...selectedAppContext, activeSelection: true },
|
||||
...this.selectedContext.filter(
|
||||
(context) =>
|
||||
context.type !== selectedAppContext.type || context.title !== selectedAppContext.title
|
||||
)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
clearContext() {
|
||||
this.selectedContext = []
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import type {
|
||||
AppFiles,
|
||||
BackendRunnable,
|
||||
LintResult,
|
||||
SelectedContext
|
||||
AppTransientContext
|
||||
} from '../../app/core'
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,10 @@ export function createAppEvalHelpers(
|
||||
let frontend: Record<string, string> = { ...initialFrontend }
|
||||
let backend: Record<string, BackendRunnable> = { ...initialBackend }
|
||||
let snapshotId = 0
|
||||
const snapshots: Map<number, { frontend: Record<string, string>; backend: Record<string, BackendRunnable> }> = new Map()
|
||||
const snapshots: Map<
|
||||
number,
|
||||
{ frontend: Record<string, string>; backend: Record<string, BackendRunnable> }
|
||||
> = new Map()
|
||||
|
||||
const helpers: AppAIChatHelpers = {
|
||||
// Frontend file operations
|
||||
@@ -78,9 +81,7 @@ export function createAppEvalHelpers(
|
||||
backend: { ...backend }
|
||||
}),
|
||||
|
||||
getSelectedContext: (): SelectedContext => ({
|
||||
type: 'none'
|
||||
}),
|
||||
getTransientContext: (): AppTransientContext => ({}),
|
||||
|
||||
// Snapshot management
|
||||
snapshot: () => {
|
||||
@@ -126,11 +127,7 @@ export function createAppEvalHelpers(
|
||||
return { success: true, result: [] }
|
||||
},
|
||||
|
||||
addTableToWhitelist: (
|
||||
_datatableName: string,
|
||||
_schemaName: string,
|
||||
_tableName: string
|
||||
) => {
|
||||
addTableToWhitelist: (_datatableName: string, _schemaName: string, _tableName: string) => {
|
||||
// No-op for eval testing - tables are not tracked in test context
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ export async function runAppEval(
|
||||
const model = resolveModel(options?.variant, options?.model)
|
||||
|
||||
// Build user message
|
||||
const userMessage = prepareAppUserMessage(userPrompt, helpers.getSelectedContext())
|
||||
const userMessage = prepareAppUserMessage(userPrompt, helpers.getTransientContext(), [])
|
||||
|
||||
// Run the base evaluation
|
||||
const rawResult = await runEval({
|
||||
|
||||
@@ -82,28 +82,26 @@ export interface InspectorElementInfo {
|
||||
styles: Record<string, string>
|
||||
}
|
||||
|
||||
/** Context about the currently selected file or runnable in the app editor */
|
||||
export interface SelectedContext {
|
||||
/** Type of selection: 'frontend' for frontend files, 'backend' for backend runnables, or 'none' if nothing is selected */
|
||||
type: 'frontend' | 'backend' | 'none'
|
||||
/** The path of the selected frontend file (when type is 'frontend') */
|
||||
frontendPath?: string
|
||||
/** The content of the selected frontend file */
|
||||
frontendContent?: string
|
||||
/** The key of the selected backend runnable (when type is 'backend') */
|
||||
backendKey?: string
|
||||
/** The configuration of the selected backend runnable */
|
||||
backendRunnable?: BackendRunnable
|
||||
/** Current file or runnable selected in the app editor */
|
||||
export type AppSelection =
|
||||
| {
|
||||
type: 'frontend'
|
||||
frontendPath: string
|
||||
}
|
||||
| {
|
||||
type: 'backend'
|
||||
backendKey: string
|
||||
}
|
||||
| {
|
||||
type: 'none'
|
||||
}
|
||||
|
||||
/** Transient app context that does not live in the shared ContextManager selection list */
|
||||
export interface AppTransientContext {
|
||||
/** Inspector-selected element info (when user has used the inspector tool) */
|
||||
inspectorElement?: InspectorElementInfo
|
||||
/** Whether the file/runnable selection is excluded from being sent to the AI prompt */
|
||||
selectionExcluded?: boolean
|
||||
/** Function to toggle whether the selection is excluded from the prompt */
|
||||
toggleSelectionExcluded?: () => void
|
||||
/** Function to clear the inspector selection */
|
||||
clearInspector?: () => void
|
||||
/** Function to clear the runnable selection (go back to frontend view) */
|
||||
clearRunnable?: () => void
|
||||
/** Code selection from the editor (either frontend or backend) */
|
||||
codeSelection?: AppCodeSelectionElement
|
||||
/** Function to clear the code selection */
|
||||
@@ -138,7 +136,7 @@ export interface AppAIChatHelpers {
|
||||
deleteBackendRunnable: (key: string) => void
|
||||
// Combined view
|
||||
getFiles: () => AppFiles
|
||||
getSelectedContext: () => SelectedContext
|
||||
getTransientContext: () => AppTransientContext
|
||||
snapshot: () => number
|
||||
revertToSnapshot: (id: number) => void
|
||||
// Linting
|
||||
@@ -488,12 +486,22 @@ export const getAppTools = memo((): Tool<AppAIChatHelpers>[] => [
|
||||
def: getGetSelectedContextToolDef(),
|
||||
fn: async ({ helpers, toolId, toolCallbacks }) => {
|
||||
toolCallbacks.setToolStatus(toolId, { content: 'Getting selected context...' })
|
||||
const context = helpers.getSelectedContext()
|
||||
const currentSelection = getCurrentAppSelection(
|
||||
aiChatManager.contextManager.getSelectedContext()
|
||||
)
|
||||
const transientContext = helpers.getTransientContext()
|
||||
const context = {
|
||||
...currentSelection,
|
||||
...(transientContext.inspectorElement
|
||||
? { inspectorElement: transientContext.inspectorElement }
|
||||
: {}),
|
||||
...(transientContext.codeSelection ? { codeSelection: transientContext.codeSelection } : {})
|
||||
}
|
||||
const statusMsg =
|
||||
context.type === 'frontend'
|
||||
? `Frontend file selected: ${context.frontendPath}`
|
||||
: context.type === 'backend'
|
||||
? `Backend runnable selected: ${context.backendKey}`
|
||||
currentSelection.type === 'frontend'
|
||||
? `Frontend file selected: ${currentSelection.frontendPath}`
|
||||
: currentSelection.type === 'backend'
|
||||
? `Backend runnable selected: ${currentSelection.backendKey}`
|
||||
: 'No selection'
|
||||
toolCallbacks.setToolStatus(toolId, { content: statusMsg })
|
||||
return JSON.stringify(context, null, 2)
|
||||
@@ -981,73 +989,130 @@ ${policy.schema ? `\n**IMPORTANT**: Always use the schema prefix \`${schemaPrefi
|
||||
|
||||
/** Maximum characters for file content in context */
|
||||
const MAX_CONTEXT_CONTENT_LENGTH = 3000
|
||||
type AppContextElement = (
|
||||
| AppFrontendFileElement
|
||||
| AppBackendRunnableElement
|
||||
| AppDatatableElement
|
||||
) & { activeSelection?: boolean }
|
||||
type ActiveAppContextElement = (AppFrontendFileElement | AppBackendRunnableElement) & {
|
||||
activeSelection?: boolean
|
||||
}
|
||||
|
||||
function truncateContextContent(content: string, maxLength = MAX_CONTEXT_CONTENT_LENGTH): string {
|
||||
return content.length > maxLength ? content.slice(0, maxLength) + '\n... [TRUNCATED]' : content
|
||||
}
|
||||
|
||||
function formatAppContextElement(
|
||||
context: AppContextElement,
|
||||
options: { activeSelection?: boolean } = {}
|
||||
): string {
|
||||
if (context.type === 'app_frontend_file') {
|
||||
const truncatedContent = truncateContextContent(context.content)
|
||||
return options.activeSelection
|
||||
? `The user is currently viewing the frontend file: **${context.path}**\n\n\`\`\`\n${truncatedContent}\n\`\`\`\n`
|
||||
: `\n**Frontend File: ${context.path}**\n\`\`\`\n${truncatedContent}\n\`\`\`\n`
|
||||
}
|
||||
|
||||
if (context.type === 'app_backend_runnable') {
|
||||
const runnable = context.runnable
|
||||
let formattedContext = options.activeSelection
|
||||
? `The user is currently viewing the backend runnable: **${context.key}**\n`
|
||||
: `\n**Backend Runnable: ${context.key}**\n`
|
||||
|
||||
formattedContext += `- **Name**: ${runnable.name}\n`
|
||||
formattedContext += `- **Type**: ${runnable.type}\n`
|
||||
if (runnable.path) {
|
||||
formattedContext += `- **Path**: ${runnable.path}\n`
|
||||
}
|
||||
if (runnable.inlineScript) {
|
||||
formattedContext += `- **Language**: ${runnable.inlineScript.language}\n`
|
||||
formattedContext += `- **Code**:\n\`\`\`${runnable.inlineScript.language === 'bun' ? 'typescript' : 'python'}\n${truncateContextContent(runnable.inlineScript.content)}\n\`\`\`\n`
|
||||
}
|
||||
if (runnable.staticInputs && Object.keys(runnable.staticInputs).length > 0) {
|
||||
formattedContext += `- **Static inputs**: ${JSON.stringify(runnable.staticInputs)}\n`
|
||||
}
|
||||
return formattedContext
|
||||
}
|
||||
|
||||
const tableRef =
|
||||
context.schemaName === 'public'
|
||||
? `${context.datatableName}/${context.tableName}`
|
||||
: `${context.datatableName}/${context.schemaName}:${context.tableName}`
|
||||
return (
|
||||
`\n**Table: ${tableRef}**\n` +
|
||||
`- **Datatable**: ${context.datatableName}\n` +
|
||||
`- **Schema**: ${context.schemaName}\n` +
|
||||
`- **Table**: ${context.tableName}\n` +
|
||||
`- **Columns** (column_name -> type):\n\`\`\`json\n${truncateContextContent(JSON.stringify(context.columns, null, 2))}\n\`\`\`\n`
|
||||
)
|
||||
}
|
||||
|
||||
function getCurrentAppSelection(selectedContext: ContextElement[]): AppSelection {
|
||||
const activeContextElement = selectedContext.find(
|
||||
(context) =>
|
||||
context.activeSelection &&
|
||||
(context.type === 'app_frontend_file' || context.type === 'app_backend_runnable')
|
||||
) as ActiveAppContextElement | undefined
|
||||
|
||||
if (!activeContextElement) {
|
||||
return { type: 'none' }
|
||||
}
|
||||
|
||||
return activeContextElement.type === 'app_frontend_file'
|
||||
? {
|
||||
type: 'frontend',
|
||||
frontendPath: activeContextElement.path
|
||||
}
|
||||
: {
|
||||
type: 'backend',
|
||||
backendKey: activeContextElement.key
|
||||
}
|
||||
}
|
||||
|
||||
function getSelectedAppContextElement(
|
||||
selectedContext: ContextElement[]
|
||||
): ActiveAppContextElement | undefined {
|
||||
return selectedContext.find(
|
||||
(context) =>
|
||||
context.activeSelection &&
|
||||
(context.type === 'app_frontend_file' || context.type === 'app_backend_runnable')
|
||||
) as ActiveAppContextElement | undefined
|
||||
}
|
||||
|
||||
function getAdditionalAppContextElements(selectedContext: ContextElement[]): AppContextElement[] {
|
||||
return selectedContext.filter(
|
||||
(context) =>
|
||||
!context.activeSelection &&
|
||||
(context.type === 'app_frontend_file' ||
|
||||
context.type === 'app_backend_runnable' ||
|
||||
context.type === 'app_datatable')
|
||||
) as AppContextElement[]
|
||||
}
|
||||
|
||||
export function prepareAppUserMessage(
|
||||
instructions: string,
|
||||
selectedContext?: SelectedContext,
|
||||
additionalContext?: ContextElement[]
|
||||
transientContext?: AppTransientContext,
|
||||
selectedContext: ContextElement[] = []
|
||||
): ChatCompletionUserMessageParam {
|
||||
let content = ''
|
||||
const activeContextElement = getSelectedAppContextElement(selectedContext)
|
||||
const additionalContextElements = getAdditionalAppContextElements(selectedContext)
|
||||
|
||||
// Check if we have any context to add
|
||||
const hasSelectedContext =
|
||||
selectedContext && (selectedContext.type !== 'none' || selectedContext.inspectorElement)
|
||||
const hasAdditionalContext = additionalContext && additionalContext.length > 0
|
||||
!!activeContextElement ||
|
||||
!!transientContext?.inspectorElement ||
|
||||
!!transientContext?.codeSelection
|
||||
const hasAdditionalContext = additionalContextElements.length > 0
|
||||
|
||||
if (hasSelectedContext || hasAdditionalContext) {
|
||||
content += `## SELECTED CONTEXT:\n`
|
||||
|
||||
// Add frontend file context with content (unless excluded)
|
||||
if (
|
||||
selectedContext &&
|
||||
selectedContext.type === 'frontend' &&
|
||||
selectedContext.frontendPath &&
|
||||
!selectedContext.selectionExcluded
|
||||
) {
|
||||
content += `The user is currently viewing the frontend file: **${selectedContext.frontendPath}**\n`
|
||||
if (selectedContext.frontendContent) {
|
||||
const truncatedContent =
|
||||
selectedContext.frontendContent.length > MAX_CONTEXT_CONTENT_LENGTH
|
||||
? selectedContext.frontendContent.slice(0, MAX_CONTEXT_CONTENT_LENGTH) +
|
||||
'\n... [TRUNCATED]'
|
||||
: selectedContext.frontendContent
|
||||
content += `\n\`\`\`\n${truncatedContent}\n\`\`\`\n`
|
||||
}
|
||||
if (activeContextElement) {
|
||||
content += formatAppContextElement(activeContextElement, { activeSelection: true })
|
||||
}
|
||||
|
||||
// Add backend runnable context with content (unless excluded)
|
||||
if (
|
||||
selectedContext &&
|
||||
selectedContext.type === 'backend' &&
|
||||
selectedContext.backendKey &&
|
||||
!selectedContext.selectionExcluded
|
||||
) {
|
||||
content += `The user is currently viewing the backend runnable: **${selectedContext.backendKey}**\n`
|
||||
if (selectedContext.backendRunnable) {
|
||||
const runnable = selectedContext.backendRunnable
|
||||
content += `- **Name**: ${runnable.name}\n`
|
||||
content += `- **Type**: ${runnable.type}\n`
|
||||
if (runnable.path) {
|
||||
content += `- **Path**: ${runnable.path}\n`
|
||||
}
|
||||
if (runnable.inlineScript) {
|
||||
const truncatedCode =
|
||||
runnable.inlineScript.content.length > MAX_CONTEXT_CONTENT_LENGTH
|
||||
? runnable.inlineScript.content.slice(0, MAX_CONTEXT_CONTENT_LENGTH) +
|
||||
'\n... [TRUNCATED]'
|
||||
: runnable.inlineScript.content
|
||||
content += `- **Language**: ${runnable.inlineScript.language}\n`
|
||||
content += `- **Code**:\n\`\`\`${runnable.inlineScript.language === 'bun' ? 'typescript' : 'python'}\n${truncatedCode}\n\`\`\`\n`
|
||||
}
|
||||
if (runnable.staticInputs && Object.keys(runnable.staticInputs).length > 0) {
|
||||
content += `- **Static inputs**: ${JSON.stringify(runnable.staticInputs)}\n`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add inspector element context if available
|
||||
if (selectedContext?.inspectorElement) {
|
||||
const el = selectedContext.inspectorElement
|
||||
if (transientContext?.inspectorElement) {
|
||||
const el = transientContext.inspectorElement
|
||||
content += `\nThe user has selected an element in the app preview using the inspector tool:\n`
|
||||
content += `- **Element**: ${el.tagName}${el.id ? `#${el.id}` : ''}${el.className ? `.${el.className.split(' ').join('.')}` : ''}\n`
|
||||
content += `- **Selector path**: ${el.path}\n`
|
||||
@@ -1057,77 +1122,24 @@ export function prepareAppUserMessage(
|
||||
el.textContent.length > 100 ? el.textContent.slice(0, 100) + '...' : el.textContent
|
||||
content += `- **Text content**: "${truncatedText}"\n`
|
||||
}
|
||||
// Include HTML (truncated) for more context
|
||||
const truncatedHtml = el.html.length > 500 ? el.html.slice(0, 500) + '...' : el.html
|
||||
content += `- **HTML**:\n\`\`\`html\n${truncatedHtml}\n\`\`\`\n`
|
||||
}
|
||||
|
||||
// Add code selection context if available
|
||||
if (selectedContext?.codeSelection) {
|
||||
const selection = selectedContext.codeSelection
|
||||
if (transientContext?.codeSelection) {
|
||||
const selection = transientContext.codeSelection
|
||||
content += `\n### CODE SELECTION:\n`
|
||||
content += `The user has selected code in the ${selection.sourceType} editor:\n`
|
||||
content += `- **File/Source**: ${selection.source}\n`
|
||||
content += `- **Lines**: ${selection.startLine}-${selection.endLine}\n`
|
||||
const truncatedCode =
|
||||
selection.content.length > MAX_CONTEXT_CONTENT_LENGTH
|
||||
? selection.content.slice(0, MAX_CONTEXT_CONTENT_LENGTH) + '\n... [TRUNCATED]'
|
||||
: selection.content
|
||||
content += `\`\`\`\n${truncatedCode}\n\`\`\`\n`
|
||||
content += `\`\`\`\n${truncateContextContent(selection.content)}\n\`\`\`\n`
|
||||
}
|
||||
|
||||
// Add additional context from @ mentions
|
||||
if (additionalContext && additionalContext.length > 0) {
|
||||
if (additionalContextElements.length > 0) {
|
||||
content += `\n### ADDITIONAL CONTEXT (mentioned by user):\n`
|
||||
|
||||
for (const ctx of additionalContext) {
|
||||
if (ctx.type === 'app_frontend_file') {
|
||||
const fileCtx = ctx as AppFrontendFileElement
|
||||
content += `\n**Frontend File: ${fileCtx.path}**\n`
|
||||
const truncatedContent =
|
||||
fileCtx.content.length > MAX_CONTEXT_CONTENT_LENGTH
|
||||
? fileCtx.content.slice(0, MAX_CONTEXT_CONTENT_LENGTH) + '\n... [TRUNCATED]'
|
||||
: fileCtx.content
|
||||
content += `\`\`\`\n${truncatedContent}\n\`\`\`\n`
|
||||
} else if (ctx.type === 'app_backend_runnable') {
|
||||
const runnableCtx = ctx as AppBackendRunnableElement
|
||||
const runnable = runnableCtx.runnable
|
||||
content += `\n**Backend Runnable: ${runnableCtx.key}**\n`
|
||||
content += `- **Name**: ${runnable.name}\n`
|
||||
content += `- **Type**: ${runnable.type}\n`
|
||||
if (runnable.path) {
|
||||
content += `- **Path**: ${runnable.path}\n`
|
||||
}
|
||||
if (runnable.inlineScript) {
|
||||
const truncatedCode =
|
||||
runnable.inlineScript.content.length > MAX_CONTEXT_CONTENT_LENGTH
|
||||
? runnable.inlineScript.content.slice(0, MAX_CONTEXT_CONTENT_LENGTH) +
|
||||
'\n... [TRUNCATED]'
|
||||
: runnable.inlineScript.content
|
||||
content += `- **Language**: ${runnable.inlineScript.language}\n`
|
||||
content += `- **Code**:\n\`\`\`${runnable.inlineScript.language === 'bun' ? 'typescript' : 'python'}\n${truncatedCode}\n\`\`\`\n`
|
||||
}
|
||||
if (runnable.staticInputs && Object.keys(runnable.staticInputs).length > 0) {
|
||||
content += `- **Static inputs**: ${JSON.stringify(runnable.staticInputs)}\n`
|
||||
}
|
||||
} else if (ctx.type === 'app_datatable') {
|
||||
const datatableCtx = ctx as AppDatatableElement
|
||||
const tableRef =
|
||||
datatableCtx.schemaName === 'public'
|
||||
? `${datatableCtx.datatableName}/${datatableCtx.tableName}`
|
||||
: `${datatableCtx.datatableName}/${datatableCtx.schemaName}:${datatableCtx.tableName}`
|
||||
content += `\n**Table: ${tableRef}**\n`
|
||||
content += `- **Datatable**: ${datatableCtx.datatableName}\n`
|
||||
content += `- **Schema**: ${datatableCtx.schemaName}\n`
|
||||
content += `- **Table**: ${datatableCtx.tableName}\n`
|
||||
// Format columns as column_name: type
|
||||
const columnsStr = JSON.stringify(datatableCtx.columns, null, 2)
|
||||
const truncatedColumns =
|
||||
columnsStr.length > MAX_CONTEXT_CONTENT_LENGTH
|
||||
? columnsStr.slice(0, MAX_CONTEXT_CONTENT_LENGTH) + '\n... [TRUNCATED]'
|
||||
: columnsStr
|
||||
content += `- **Columns** (column_name -> type):\n\`\`\`json\n${truncatedColumns}\n\`\`\`\n`
|
||||
}
|
||||
for (const ctx of additionalContextElements) {
|
||||
content += formatAppContextElement(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -173,4 +173,5 @@ export type ContextElement = (
|
||||
| WorkspaceFlowElement
|
||||
) & {
|
||||
deletable?: boolean
|
||||
activeSelection?: boolean
|
||||
}
|
||||
|
||||
@@ -18,7 +18,13 @@
|
||||
import { isRunnableByName, isRunnableByPath } from '../apps/inputType'
|
||||
import { aiChatManager, AIMode } from '../copilot/chat/AIChatManager.svelte'
|
||||
import { onMount, untrack } from 'svelte'
|
||||
import type { LintResult, DataTableSchema, InspectorElementInfo } from '../copilot/chat/app/core'
|
||||
import type {
|
||||
LintResult,
|
||||
DataTableSchema,
|
||||
InspectorElementInfo,
|
||||
AppSelection,
|
||||
AppTransientContext
|
||||
} from '../copilot/chat/app/core'
|
||||
import type { AppCodeSelectionElement } from '../copilot/chat/context'
|
||||
import { rawAppLintStore } from './lintStore'
|
||||
import { dbSchemas } from '$lib/stores'
|
||||
@@ -396,40 +402,7 @@
|
||||
backend: aiChatManager.appAiChatHelpers?.getBackendRunnables() ?? {}
|
||||
}
|
||||
},
|
||||
getSelectedContext: () => {
|
||||
const baseContext = {
|
||||
inspectorElement: inspectorElement,
|
||||
selectionExcluded: selectionExcludedFromPrompt,
|
||||
toggleSelectionExcluded: toggleSelectionExcluded,
|
||||
clearInspector: clearInspectorSelection,
|
||||
clearRunnable: handleClearRunnable,
|
||||
codeSelection: codeSelection,
|
||||
clearCodeSelection: () => {
|
||||
codeSelection = undefined
|
||||
}
|
||||
}
|
||||
if (selectedRunnable) {
|
||||
const runnable = convertToBackendRunnable(selectedRunnable, runnables[selectedRunnable])
|
||||
return {
|
||||
type: 'backend' as const,
|
||||
backendKey: selectedRunnable,
|
||||
backendRunnable: runnable,
|
||||
...baseContext
|
||||
}
|
||||
}
|
||||
if (selectedDocument) {
|
||||
return {
|
||||
type: 'frontend' as const,
|
||||
frontendPath: selectedDocument,
|
||||
frontendContent: files?.[selectedDocument],
|
||||
...baseContext
|
||||
}
|
||||
}
|
||||
return {
|
||||
type: 'none' as const,
|
||||
...baseContext
|
||||
}
|
||||
},
|
||||
getTransientContext: () => getAppTransientContext(),
|
||||
snapshot: () => {
|
||||
// Force create snapshot for AI - it needs a restore point
|
||||
return (
|
||||
@@ -589,15 +562,21 @@
|
||||
let selectedRunnable: string | undefined = $state(undefined)
|
||||
let selectedDocument: string | undefined = $state(undefined)
|
||||
let inspectorElement: InspectorElementInfo | undefined = $state(undefined)
|
||||
let selectionExcludedFromPrompt: boolean = $state(false)
|
||||
let codeSelection: AppCodeSelectionElement | undefined = $state(undefined)
|
||||
|
||||
function toggleSelectionExcluded() {
|
||||
selectionExcludedFromPrompt = !selectionExcludedFromPrompt
|
||||
}
|
||||
|
||||
let modules = $state({}) as Modules
|
||||
|
||||
function getAppTransientContext(): AppTransientContext {
|
||||
return {
|
||||
inspectorElement: inspectorElement,
|
||||
clearInspector: clearInspectorSelection,
|
||||
codeSelection: codeSelection,
|
||||
clearCodeSelection: () => {
|
||||
codeSelection = undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize Windows-style path separators to Linux-style
|
||||
function normalizeFilePaths(
|
||||
filesObj: Record<string, string> | undefined
|
||||
@@ -703,28 +682,34 @@
|
||||
)
|
||||
}
|
||||
|
||||
function handleClearRunnable() {
|
||||
selectedRunnable = undefined
|
||||
}
|
||||
|
||||
// Track previous values for change detection
|
||||
let prevSelectedRunnable: string | undefined = undefined
|
||||
let prevSelectedDocument: string | undefined = undefined
|
||||
|
||||
// Clear inspector and reset exclusion when selection changes
|
||||
// Clear inspector when the active file/runnable changes
|
||||
$effect(() => {
|
||||
if (selectedRunnable !== prevSelectedRunnable || selectedDocument !== prevSelectedDocument) {
|
||||
// Only clear if we're actually switching to something different
|
||||
if (prevSelectedRunnable !== undefined || prevSelectedDocument !== undefined) {
|
||||
clearInspectorSelection()
|
||||
}
|
||||
// Reset exclusion when switching files/runnables
|
||||
selectionExcludedFromPrompt = false
|
||||
prevSelectedRunnable = selectedRunnable
|
||||
prevSelectedDocument = selectedDocument
|
||||
}
|
||||
})
|
||||
|
||||
$effect(() => {
|
||||
const appSelection: AppSelection = selectedRunnable
|
||||
? { type: 'backend' as const, backendKey: selectedRunnable }
|
||||
: selectedDocument
|
||||
? { type: 'frontend' as const, frontendPath: selectedDocument }
|
||||
: { type: 'none' as const }
|
||||
|
||||
untrack(() => {
|
||||
aiChatManager.syncAppSelection(appSelection)
|
||||
})
|
||||
})
|
||||
|
||||
function handleUndo() {
|
||||
// Create a snapshot if we're at the latest position with pending changes
|
||||
if (historyManager.needsSnapshotBeforeNav) {
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { genWmillTs, type Runnable } from './utils'
|
||||
|
||||
const flowSchema = {
|
||||
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
||||
type: 'object',
|
||||
required: ['string_input'],
|
||||
properties: {
|
||||
string_input: {
|
||||
type: 'string',
|
||||
default: ''
|
||||
},
|
||||
count: {
|
||||
type: 'integer'
|
||||
}
|
||||
}
|
||||
} as const
|
||||
|
||||
describe('genWmillTs', () => {
|
||||
it('generates the correct flow args type for path runnables', () => {
|
||||
const runnables: Record<string, Runnable> = {
|
||||
myflow: {
|
||||
type: 'path',
|
||||
runType: 'flow',
|
||||
path: 'u/dev/my_flow',
|
||||
name: 'My flow',
|
||||
schema: flowSchema,
|
||||
fields: {
|
||||
count: {
|
||||
type: 'static',
|
||||
value: 1,
|
||||
fieldType: 'number'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const dts = genWmillTs(runnables)
|
||||
|
||||
expect(dts).toContain(
|
||||
'myflow: (args: { string_input: string }) => Promise<any>;'
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -108,7 +108,7 @@ function hiddenRunnableToTsType(runnable: Runnable) {
|
||||
}
|
||||
} else if (isRunnableByPath(runnable)) {
|
||||
if (runnable?.schema) {
|
||||
return schemaToTsType(removeStaticFields(runnable.schema as Schema, runnable?.fields ?? {}))
|
||||
return schemaToTsType(removeStaticFields(runnable.schema, runnable?.fields ?? {}))
|
||||
} else {
|
||||
return '{}'
|
||||
}
|
||||
|
||||
@@ -18,11 +18,6 @@ import {
|
||||
} from '$lib/utils_deployable'
|
||||
import type { TriggerKind } from './components/triggers'
|
||||
|
||||
/** Folder diff paths carry the `f/` prefix (e.g. `f/test`), but folder API endpoints expect just the name. */
|
||||
function folderName(path: string): string {
|
||||
return path.replace(/^f\//, '')
|
||||
}
|
||||
|
||||
export interface DeployItemParams {
|
||||
kind: Kind
|
||||
path: string
|
||||
@@ -259,32 +254,12 @@ export async function deployItem(params: DeployItemParams): Promise<DeployResult
|
||||
})
|
||||
}
|
||||
} else if (kind === 'folder') {
|
||||
const name = folderName(path)
|
||||
const folder = await FolderService.getFolder({
|
||||
workspace: workspaceFrom,
|
||||
name
|
||||
await FolderService.createFolder({
|
||||
workspace: workspaceTo,
|
||||
requestBody: {
|
||||
name: path
|
||||
}
|
||||
})
|
||||
if (alreadyExists) {
|
||||
await FolderService.updateFolder({
|
||||
workspace: workspaceTo,
|
||||
name,
|
||||
requestBody: {
|
||||
owners: folder.owners,
|
||||
extra_perms: folder.extra_perms as any,
|
||||
summary: folder.summary ?? undefined
|
||||
}
|
||||
})
|
||||
} else {
|
||||
await FolderService.createFolder({
|
||||
workspace: workspaceTo,
|
||||
requestBody: {
|
||||
name,
|
||||
owners: folder.owners,
|
||||
extra_perms: folder.extra_perms as any,
|
||||
summary: folder.summary ?? undefined
|
||||
}
|
||||
})
|
||||
}
|
||||
} else if (kind === 'trigger') {
|
||||
if (additionalInformation?.triggers) {
|
||||
const { data, createFn, updateFn } = await getTriggersDeployData(
|
||||
@@ -365,7 +340,7 @@ export async function checkItemExists(
|
||||
} else if (kind === 'folder') {
|
||||
return await FolderService.existsFolder({
|
||||
workspace: workspace,
|
||||
name: folderName(path)
|
||||
name: path
|
||||
})
|
||||
} else if (kind === 'trigger') {
|
||||
const triggersKind: TriggerKind[] = [
|
||||
@@ -460,13 +435,10 @@ export async function getItemValue(
|
||||
} else if (kind === 'folder') {
|
||||
const folder = await FolderService.getFolder({
|
||||
workspace: workspace,
|
||||
name: folderName(path)
|
||||
name: path
|
||||
})
|
||||
return {
|
||||
name: folder.name,
|
||||
owners: folder.owners,
|
||||
extra_perms: folder.extra_perms,
|
||||
summary: folder.summary
|
||||
name: folder.name
|
||||
}
|
||||
} else if (kind === 'trigger') {
|
||||
if (additionalInformation?.triggers) {
|
||||
|
||||
@@ -94,7 +94,6 @@
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import { isWorkflowAsCode } from '$lib/components/graph/wacToFlow'
|
||||
import WacDiagram from '$lib/components/graph/WacDiagram.svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
let script: Script | undefined = $state()
|
||||
let topHash: string | undefined = $state()
|
||||
@@ -740,12 +739,9 @@
|
||||
<NoDirectDeployAlert onUpdateCanEditStatus={(v) => (showEditButtons = v)} />
|
||||
</div>
|
||||
{#if script}
|
||||
<div class={twMerge('flex flex-col', isWac ? 'h-full divide-y' : '')}>
|
||||
<div class="flex flex-col h-full" class:divide-y={isWac}>
|
||||
<div
|
||||
class={twMerge(
|
||||
'p-8 w-full max-w-3xl overflow-y-auto mx-auto flex flex-col relative',
|
||||
isWac ? 'max-h-1/2' : ''
|
||||
)}
|
||||
class="p-8 w-full max-w-3xl mx-auto md:min-h-[300px] flex flex-col md:justify-center"
|
||||
>
|
||||
<div class="flex flex-col gap-0.5 mb-1">
|
||||
{#if script.lock_error_logs || topHash || script.archived || script.deleted}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
import Login from '$lib/components/Login.svelte'
|
||||
import { onMount } from 'svelte'
|
||||
import { refreshSuperadmin } from '$lib/refreshUser'
|
||||
import { isValidLogoutRedirect } from '$lib/logoutRedirect'
|
||||
|
||||
const email = page.url.searchParams.get('email') ?? ''
|
||||
const password = page.url.searchParams.get('password') ?? ''
|
||||
@@ -56,11 +55,7 @@
|
||||
|
||||
async function redirectUser() {
|
||||
if (rd?.startsWith('http')) {
|
||||
if (isValidLogoutRedirect(rd)) {
|
||||
window.location.href = rd
|
||||
return
|
||||
}
|
||||
goto('/')
|
||||
window.location.href = rd
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
import { userStore, usersWorkspaceStore, workspaceStore } from '$lib/stores'
|
||||
import { getUserExt } from '$lib/user'
|
||||
import { logoutWithRedirect } from '$lib/logoutKit'
|
||||
import { isValidLogoutRedirect } from '$lib/logoutRedirect'
|
||||
import { parseQueryParams } from '$lib/utils'
|
||||
import { page } from '$app/state'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
@@ -23,11 +22,10 @@
|
||||
onMount(async () => {
|
||||
// const closeCookie = getAndDeleteCookie('close')
|
||||
// console.log('closeCookie', closeCookie)
|
||||
const rawRd = localStorage.getItem('rd')
|
||||
if (rawRd) {
|
||||
const rd = localStorage.getItem('rd')
|
||||
if (rd) {
|
||||
localStorage.removeItem('rd')
|
||||
}
|
||||
const rd = rawRd?.startsWith('http') && !isValidLogoutRedirect(rawRd) ? null : rawRd
|
||||
const cookieCloseUponLogin = getCookie('close') == 'true'
|
||||
const closeUponLogin = cookieCloseUponLogin ?? localStorage.getItem('closeUponLogin') == 'true'
|
||||
if (error) {
|
||||
|
||||
@@ -4,7 +4,7 @@ verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
wmill = ">=1.672.0"
|
||||
wmill = ">=1.671.0"
|
||||
sendgrid = "*"
|
||||
mysql-connector-python = "*"
|
||||
pymongo = "*"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: '3.0.3'
|
||||
|
||||
info:
|
||||
version: 1.672.0
|
||||
version: 1.671.0
|
||||
title: OpenFlow Spec
|
||||
contact:
|
||||
name: Ruben Fiszel
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
RootModule = 'WindmillClient.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.672.0'
|
||||
ModuleVersion = '1.671.0'
|
||||
|
||||
# Supported PSEditions
|
||||
# CompatiblePSEditions = @()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "wmill"
|
||||
version = "1.672.0"
|
||||
version = "1.671.0"
|
||||
description = "A client library for accessing Windmill server wrapping the Windmill client API"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://windmill.dev"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@windmill/windmill",
|
||||
"version": "1.672.0",
|
||||
"version": "1.671.0",
|
||||
"exports": "./src/index.ts",
|
||||
"publish": {
|
||||
"exclude": ["!src", "./s3Types.ts", "./sqlUtils.ts", "./client.ts"]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "windmill-client",
|
||||
"description": "Windmill SDK client for browsers and Node.js",
|
||||
"version": "1.672.0",
|
||||
"version": "1.671.0",
|
||||
"author": "Ruben Fiszel",
|
||||
"license": "Apache 2.0",
|
||||
"sideEffects": false,
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.672.0
|
||||
1.671.0
|
||||
|
||||
Reference in New Issue
Block a user