diff --git a/.gitignore b/.gitignore
index 7ae3e83..c51e801 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,13 +45,15 @@ logs/
# macOS
.DS_Store
+# Node
+node_modules/
+
# OTHER
.just/
journalapp.exe
Journal.App/node_modules.old/@rollup/.rollup-win32-x64-msvc-IjiZshxL/rollup.win32-x64-msvc.node
journalapp(1).exe
.cache/
-Journal.DevTool/node_modules/
scripts/__pycache__/
.sdt/
devtool.backup.json
@@ -61,5 +63,3 @@ sdt.exe
sdt.pdb
sdt.runtimeconfig.json
Spectre.Console.dll
-Journal.DevTool/devtool.generated.workflows.json
-Journal.DevTool/sdt-workspace.json
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..43790c8
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,7 @@
+
+
+ net10.0
+ enable
+ enable
+
+
\ No newline at end of file
diff --git a/Directory.Packages.props b/Directory.Packages.props
new file mode 100644
index 0000000..9845347
--- /dev/null
+++ b/Directory.Packages.props
@@ -0,0 +1,16 @@
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Journal.AI/Journal.AI.csproj b/Journal.AI/Journal.AI.csproj
index 97186d9..32ff915 100644
--- a/Journal.AI/Journal.AI.csproj
+++ b/Journal.AI/Journal.AI.csproj
@@ -1,14 +1,8 @@
-
- net10.0
- enable
- enable
-
-
-
-
+
+
diff --git a/Journal.App/package-lock.json b/Journal.App/package-lock.json
deleted file mode 100644
index 0407a46..0000000
--- a/Journal.App/package-lock.json
+++ /dev/null
@@ -1,1926 +0,0 @@
-{
- "name": "journalapp",
- "version": "0.1.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "journalapp",
- "version": "0.1.0",
- "license": "MIT",
- "dependencies": {
- "@tauri-apps/api": "^2",
- "@tauri-apps/plugin-dialog": "^2.6.0",
- "@tauri-apps/plugin-opener": "^2",
- "tauri-plugin-mic-recorder-api": "^2.0.0"
- },
- "devDependencies": {
- "@sveltejs/adapter-static": "^3.0.6",
- "@sveltejs/kit": "^2.9.0",
- "@sveltejs/vite-plugin-svelte": "^5.0.0",
- "@tauri-apps/cli": "^2",
- "prettier": "^3.8.1",
- "prettier-plugin-svelte": "^3.5.0",
- "svelte": "^5.0.0",
- "svelte-check": "^4.0.0",
- "typescript": "~5.6.2",
- "vite": "^6.0.3"
- }
- },
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
- "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
- "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
- "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
- "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
- "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
- "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
- "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
- "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
- "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
- "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
- "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
- "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
- "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
- "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
- "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
- "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
- "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
- "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
- "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
- "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
- "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openharmony-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
- "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
- "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
- "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
- "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
- "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.13",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
- "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/remapping": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
- "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
- "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.31",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
- "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@polka/url": {
- "version": "1.0.0-next.29",
- "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
- "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
- "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-android-arm64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
- "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
- "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
- "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
- "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
- "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
- "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
- "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
- "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
- "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-loong64-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
- "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-loong64-musl": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
- "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-ppc64-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
- "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-ppc64-musl": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
- "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
- "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
- "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
- "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
- "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
- "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-openbsd-x64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
- "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ]
- },
- "node_modules/@rollup/rollup-openharmony-arm64": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
- "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ]
- },
- "node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
- "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
- "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-gnu": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
- "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
- "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@standard-schema/spec": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
- "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@sveltejs/acorn-typescript": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.9.tgz",
- "integrity": "sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "acorn": "^8.9.0"
- }
- },
- "node_modules/@sveltejs/adapter-static": {
- "version": "3.0.10",
- "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.10.tgz",
- "integrity": "sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "@sveltejs/kit": "^2.0.0"
- }
- },
- "node_modules/@sveltejs/kit": {
- "version": "2.53.1",
- "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.53.1.tgz",
- "integrity": "sha512-NXsZLvalgI3HrHG6ogoEVzjyV7bSFQNqQeekfU7nNufQFrRyV3EBDfQKEwxx50peu7spZR42JuC1PFhwxuvBrg==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@standard-schema/spec": "^1.0.0",
- "@sveltejs/acorn-typescript": "^1.0.5",
- "@types/cookie": "^0.6.0",
- "acorn": "^8.14.1",
- "cookie": "^0.6.0",
- "devalue": "^5.6.3",
- "esm-env": "^1.2.2",
- "kleur": "^4.1.5",
- "magic-string": "^0.30.5",
- "mrmime": "^2.0.0",
- "set-cookie-parser": "^3.0.0",
- "sirv": "^3.0.0"
- },
- "bin": {
- "svelte-kit": "svelte-kit.js"
- },
- "engines": {
- "node": ">=18.13"
- },
- "peerDependencies": {
- "@opentelemetry/api": "^1.0.0",
- "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0",
- "svelte": "^4.0.0 || ^5.0.0-next.0",
- "typescript": "^5.3.3",
- "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0"
- },
- "peerDependenciesMeta": {
- "@opentelemetry/api": {
- "optional": true
- },
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@sveltejs/vite-plugin-svelte": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-5.1.1.tgz",
- "integrity": "sha512-Y1Cs7hhTc+a5E9Va/xwKlAJoariQyHY+5zBgCZg4PFWNYQ1nMN9sjK1zhw1gK69DuqVP++sht/1GZg1aRwmAXQ==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1",
- "debug": "^4.4.1",
- "deepmerge": "^4.3.1",
- "kleur": "^4.1.5",
- "magic-string": "^0.30.17",
- "vitefu": "^1.0.6"
- },
- "engines": {
- "node": "^18.0.0 || ^20.0.0 || >=22"
- },
- "peerDependencies": {
- "svelte": "^5.0.0",
- "vite": "^6.0.0"
- }
- },
- "node_modules/@sveltejs/vite-plugin-svelte-inspector": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-4.0.1.tgz",
- "integrity": "sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "debug": "^4.3.7"
- },
- "engines": {
- "node": "^18.0.0 || ^20.0.0 || >=22"
- },
- "peerDependencies": {
- "@sveltejs/vite-plugin-svelte": "^5.0.0",
- "svelte": "^5.0.0",
- "vite": "^6.0.0"
- }
- },
- "node_modules/@tauri-apps/api": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.10.1.tgz",
- "integrity": "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==",
- "license": "Apache-2.0 OR MIT",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/tauri"
- }
- },
- "node_modules/@tauri-apps/cli": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.10.0.tgz",
- "integrity": "sha512-ZwT0T+7bw4+DPCSWzmviwq5XbXlM0cNoleDKOYPFYqcZqeKY31KlpoMW/MOON/tOFBPgi31a2v3w9gliqwL2+Q==",
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "bin": {
- "tauri": "tauri.js"
- },
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/tauri"
- },
- "optionalDependencies": {
- "@tauri-apps/cli-darwin-arm64": "2.10.0",
- "@tauri-apps/cli-darwin-x64": "2.10.0",
- "@tauri-apps/cli-linux-arm-gnueabihf": "2.10.0",
- "@tauri-apps/cli-linux-arm64-gnu": "2.10.0",
- "@tauri-apps/cli-linux-arm64-musl": "2.10.0",
- "@tauri-apps/cli-linux-riscv64-gnu": "2.10.0",
- "@tauri-apps/cli-linux-x64-gnu": "2.10.0",
- "@tauri-apps/cli-linux-x64-musl": "2.10.0",
- "@tauri-apps/cli-win32-arm64-msvc": "2.10.0",
- "@tauri-apps/cli-win32-ia32-msvc": "2.10.0",
- "@tauri-apps/cli-win32-x64-msvc": "2.10.0"
- }
- },
- "node_modules/@tauri-apps/cli-darwin-arm64": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.10.0.tgz",
- "integrity": "sha512-avqHD4HRjrMamE/7R/kzJPcAJnZs0IIS+1nkDP5b+TNBn3py7N2aIo9LIpy+VQq0AkN8G5dDpZtOOBkmWt/zjA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tauri-apps/cli-darwin-x64": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.10.0.tgz",
- "integrity": "sha512-keDmlvJRStzVFjZTd0xYkBONLtgBC9eMTpmXnBXzsHuawV2q9PvDo2x6D5mhuoMVrJ9QWjgaPKBBCFks4dK71Q==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.10.0.tgz",
- "integrity": "sha512-e5u0VfLZsMAC9iHaOEANumgl6lfnJx0Dtjkd8IJpysZ8jp0tJ6wrIkto2OzQgzcYyRCKgX72aKE0PFgZputA8g==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tauri-apps/cli-linux-arm64-gnu": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.10.0.tgz",
- "integrity": "sha512-YrYYk2dfmBs5m+OIMCrb+JH/oo+4FtlpcrTCgiFYc7vcs6m3QDd1TTyWu0u01ewsCtK2kOdluhr/zKku+KP7HA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tauri-apps/cli-linux-arm64-musl": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.10.0.tgz",
- "integrity": "sha512-GUoPdVJmrJRIXFfW3Rkt+eGK9ygOdyISACZfC/bCSfOnGt8kNdQIQr5WRH9QUaTVFIwxMlQyV3m+yXYP+xhSVA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tauri-apps/cli-linux-riscv64-gnu": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.10.0.tgz",
- "integrity": "sha512-JO7s3TlSxshwsoKNCDkyvsx5gw2QAs/Y2GbR5UE2d5kkU138ATKoPOtxn8G1fFT1aDW4LH0rYAAfBpGkDyJJnw==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tauri-apps/cli-linux-x64-gnu": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.10.0.tgz",
- "integrity": "sha512-Uvh4SUUp4A6DVRSMWjelww0GnZI3PlVy7VS+DRF5napKuIehVjGl9XD0uKoCoxwAQBLctvipyEK+pDXpJeoHng==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tauri-apps/cli-linux-x64-musl": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.10.0.tgz",
- "integrity": "sha512-AP0KRK6bJuTpQ8kMNWvhIpKUkQJfcPFeba7QshOQZjJ8wOS6emwTN4K5g/d3AbCMo0RRdnZWwu67MlmtJyxC1Q==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tauri-apps/cli-win32-arm64-msvc": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.10.0.tgz",
- "integrity": "sha512-97DXVU3dJystrq7W41IX+82JEorLNY+3+ECYxvXWqkq7DBN6FsA08x/EFGE8N/b0LTOui9X2dvpGGoeZKKV08g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tauri-apps/cli-win32-ia32-msvc": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.10.0.tgz",
- "integrity": "sha512-EHyQ1iwrWy1CwMalEm9z2a6L5isQ121pe7FcA2xe4VWMJp+GHSDDGvbTv/OPdkt2Lyr7DAZBpZHM6nvlHXEc4A==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tauri-apps/cli-win32-x64-msvc": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.10.0.tgz",
- "integrity": "sha512-NTpyQxkpzGmU6ceWBTY2xRIEaS0ZLbVx1HE1zTA3TY/pV3+cPoPPOs+7YScr4IMzXMtOw7tLw5LEXo5oIG3qaQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0 OR MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tauri-apps/plugin-dialog": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.6.0.tgz",
- "integrity": "sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==",
- "license": "MIT OR Apache-2.0",
- "dependencies": {
- "@tauri-apps/api": "^2.8.0"
- }
- },
- "node_modules/@tauri-apps/plugin-opener": {
- "version": "2.5.3",
- "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.3.tgz",
- "integrity": "sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ==",
- "license": "MIT OR Apache-2.0",
- "dependencies": {
- "@tauri-apps/api": "^2.8.0"
- }
- },
- "node_modules/@types/cookie": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
- "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/estree": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
- "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/trusted-types": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
- "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/acorn": {
- "version": "8.16.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
- "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/aria-query": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz",
- "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/axobject-query": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
- "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/chokidar": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
- "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "readdirp": "^4.0.1"
- },
- "engines": {
- "node": ">= 14.16.0"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/clsx": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
- "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/cookie": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
- "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/deepmerge": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
- "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/devalue": {
- "version": "5.6.3",
- "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.3.tgz",
- "integrity": "sha512-nc7XjUU/2Lb+SvEFVGcWLiKkzfw8+qHI7zn8WYXKkLMgfGSHbgCEaR6bJpev8Cm6Rmrb19Gfd/tZvGqx9is3wg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/esbuild": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
- "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.25.12",
- "@esbuild/android-arm": "0.25.12",
- "@esbuild/android-arm64": "0.25.12",
- "@esbuild/android-x64": "0.25.12",
- "@esbuild/darwin-arm64": "0.25.12",
- "@esbuild/darwin-x64": "0.25.12",
- "@esbuild/freebsd-arm64": "0.25.12",
- "@esbuild/freebsd-x64": "0.25.12",
- "@esbuild/linux-arm": "0.25.12",
- "@esbuild/linux-arm64": "0.25.12",
- "@esbuild/linux-ia32": "0.25.12",
- "@esbuild/linux-loong64": "0.25.12",
- "@esbuild/linux-mips64el": "0.25.12",
- "@esbuild/linux-ppc64": "0.25.12",
- "@esbuild/linux-riscv64": "0.25.12",
- "@esbuild/linux-s390x": "0.25.12",
- "@esbuild/linux-x64": "0.25.12",
- "@esbuild/netbsd-arm64": "0.25.12",
- "@esbuild/netbsd-x64": "0.25.12",
- "@esbuild/openbsd-arm64": "0.25.12",
- "@esbuild/openbsd-x64": "0.25.12",
- "@esbuild/openharmony-arm64": "0.25.12",
- "@esbuild/sunos-x64": "0.25.12",
- "@esbuild/win32-arm64": "0.25.12",
- "@esbuild/win32-ia32": "0.25.12",
- "@esbuild/win32-x64": "0.25.12"
- }
- },
- "node_modules/esm-env": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
- "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/esrap": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.3.tgz",
- "integrity": "sha512-8fOS+GIGCQZl/ZIlhl59htOlms6U8NvX6ZYgYHpRU/b6tVSh3uHkOHZikl3D4cMbYM0JlpBe+p/BkZEi8J9XIQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.4.15"
- }
- },
- "node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/is-reference": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
- "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/estree": "^1.0.6"
- }
- },
- "node_modules/kleur": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
- "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/locate-character": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
- "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/magic-string": {
- "version": "0.30.21",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
- "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.5"
- }
- },
- "node_modules/mri": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
- "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/mrmime": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
- "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/nanoid": {
- "version": "3.3.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/picocolors": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/postcss": {
- "version": "8.5.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
- "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.11",
- "picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/prettier": {
- "version": "3.8.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz",
- "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "bin": {
- "prettier": "bin/prettier.cjs"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/prettier/prettier?sponsor=1"
- }
- },
- "node_modules/prettier-plugin-svelte": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.5.0.tgz",
- "integrity": "sha512-2lLO/7EupnjO/95t+XZesXs8Bf3nYLIDfCo270h5QWbj/vjLqmrQ1LiRk9LPggxSDsnVYfehamZNf+rgQYApZg==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "prettier": "^3.0.0",
- "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
- }
- },
- "node_modules/readdirp": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
- "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 14.18.0"
- },
- "funding": {
- "type": "individual",
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/rollup": {
- "version": "4.59.0",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
- "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/estree": "1.0.8"
- },
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=18.0.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.59.0",
- "@rollup/rollup-android-arm64": "4.59.0",
- "@rollup/rollup-darwin-arm64": "4.59.0",
- "@rollup/rollup-darwin-x64": "4.59.0",
- "@rollup/rollup-freebsd-arm64": "4.59.0",
- "@rollup/rollup-freebsd-x64": "4.59.0",
- "@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
- "@rollup/rollup-linux-arm-musleabihf": "4.59.0",
- "@rollup/rollup-linux-arm64-gnu": "4.59.0",
- "@rollup/rollup-linux-arm64-musl": "4.59.0",
- "@rollup/rollup-linux-loong64-gnu": "4.59.0",
- "@rollup/rollup-linux-loong64-musl": "4.59.0",
- "@rollup/rollup-linux-ppc64-gnu": "4.59.0",
- "@rollup/rollup-linux-ppc64-musl": "4.59.0",
- "@rollup/rollup-linux-riscv64-gnu": "4.59.0",
- "@rollup/rollup-linux-riscv64-musl": "4.59.0",
- "@rollup/rollup-linux-s390x-gnu": "4.59.0",
- "@rollup/rollup-linux-x64-gnu": "4.59.0",
- "@rollup/rollup-linux-x64-musl": "4.59.0",
- "@rollup/rollup-openbsd-x64": "4.59.0",
- "@rollup/rollup-openharmony-arm64": "4.59.0",
- "@rollup/rollup-win32-arm64-msvc": "4.59.0",
- "@rollup/rollup-win32-ia32-msvc": "4.59.0",
- "@rollup/rollup-win32-x64-gnu": "4.59.0",
- "@rollup/rollup-win32-x64-msvc": "4.59.0",
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/sade": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
- "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mri": "^1.1.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/set-cookie-parser": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.0.1.tgz",
- "integrity": "sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/sirv": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz",
- "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@polka/url": "^1.0.0-next.24",
- "mrmime": "^2.0.0",
- "totalist": "^3.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/svelte": {
- "version": "5.53.3",
- "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.53.3.tgz",
- "integrity": "sha512-pRUBr6j6uQDgBi208gHnGRMykw0Rf2Yr1HmLyRucsvcaYgIUxswJkT93WZJflsmezu5s8Lq+q78EoyLv2yaFCg==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@jridgewell/remapping": "^2.3.4",
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@sveltejs/acorn-typescript": "^1.0.5",
- "@types/estree": "^1.0.5",
- "@types/trusted-types": "^2.0.7",
- "acorn": "^8.12.1",
- "aria-query": "5.3.1",
- "axobject-query": "^4.1.0",
- "clsx": "^2.1.1",
- "devalue": "^5.6.3",
- "esm-env": "^1.2.1",
- "esrap": "^2.2.2",
- "is-reference": "^3.0.3",
- "locate-character": "^3.0.0",
- "magic-string": "^0.30.11",
- "zimmerframe": "^1.1.2"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/svelte-check": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.4.3.tgz",
- "integrity": "sha512-4HtdEv2hOoLCEsSXI+RDELk9okP/4sImWa7X02OjMFFOWeSdFF3NFy3vqpw0z+eH9C88J9vxZfUXz/Uv2A1ANw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/trace-mapping": "^0.3.25",
- "chokidar": "^4.0.1",
- "fdir": "^6.2.0",
- "picocolors": "^1.0.0",
- "sade": "^1.7.4"
- },
- "bin": {
- "svelte-check": "bin/svelte-check"
- },
- "engines": {
- "node": ">= 18.0.0"
- },
- "peerDependencies": {
- "svelte": "^4.0.0 || ^5.0.0-next.0",
- "typescript": ">=5.0.0"
- }
- },
- "node_modules/tauri-plugin-mic-recorder-api": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/tauri-plugin-mic-recorder-api/-/tauri-plugin-mic-recorder-api-2.0.0.tgz",
- "integrity": "sha512-04wqYCX4WIlYd6KUY7aS3+W4B5RtnSoVczaQCBSXKpQkEx9XdaaBN05XCee2unxGva0btSXBItFqQSdosnS4jQ==",
- "license": "MIT",
- "dependencies": {
- "@tauri-apps/api": ">=2.0.0-beta.6"
- }
- },
- "node_modules/tinyglobby": {
- "version": "0.2.15",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
- "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fdir": "^6.5.0",
- "picomatch": "^4.0.3"
- },
- "engines": {
- "node": ">=12.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/SuperchupuDev"
- }
- },
- "node_modules/totalist": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
- "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/typescript": {
- "version": "5.6.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
- "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
- "dev": true,
- "license": "Apache-2.0",
- "peer": true,
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/vite": {
- "version": "6.4.1",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
- "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "esbuild": "^0.25.0",
- "fdir": "^6.4.4",
- "picomatch": "^4.0.2",
- "postcss": "^8.5.3",
- "rollup": "^4.34.9",
- "tinyglobby": "^0.2.13"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- },
- "peerDependencies": {
- "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
- "jiti": ">=1.21.0",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "sass-embedded": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.16.0",
- "tsx": "^4.8.1",
- "yaml": "^2.4.2"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "jiti": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "sass-embedded": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- },
- "tsx": {
- "optional": true
- },
- "yaml": {
- "optional": true
- }
- }
- },
- "node_modules/vitefu": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.2.tgz",
- "integrity": "sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw==",
- "dev": true,
- "license": "MIT",
- "workspaces": [
- "tests/deps/*",
- "tests/projects/*",
- "tests/projects/workspace/packages/*"
- ],
- "peerDependencies": {
- "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0"
- },
- "peerDependenciesMeta": {
- "vite": {
- "optional": true
- }
- }
- },
- "node_modules/zimmerframe": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz",
- "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==",
- "dev": true,
- "license": "MIT"
- }
- }
-}
diff --git a/Journal.Core/Journal.Core.csproj b/Journal.Core/Journal.Core.csproj
index 7e67750..60a9a1f 100644
--- a/Journal.Core/Journal.Core.csproj
+++ b/Journal.Core/Journal.Core.csproj
@@ -1,15 +1,9 @@
-
- net10.0
- enable
- enable
-
-
-
-
-
+
+
+
diff --git a/Journal.DevTool/.gitignore b/Journal.DevTool/.gitignore
deleted file mode 100644
index d148d21..0000000
--- a/Journal.DevTool/.gitignore
+++ /dev/null
@@ -1,15 +0,0 @@
-bin/
-obj/
-__pycache__/
-.cache/
-.vscode/
-.idea/
-.vs/
-.git/
-.pip
-.tmp
-.venv
-.dotnet_home
-.nuget
-publish-test/
-
diff --git a/Journal.DevTool/.gitkeep b/Journal.DevTool/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/Journal.DevTool/Config/ConfigBootstrapper.cs b/Journal.DevTool/Config/ConfigBootstrapper.cs
deleted file mode 100644
index 2b65e39..0000000
--- a/Journal.DevTool/Config/ConfigBootstrapper.cs
+++ /dev/null
@@ -1,626 +0,0 @@
-using System.Text.Json;
-
-namespace Sdt.Config;
-
-public sealed record BootstrapScanResult(
- string ProjectRoot,
- string ProjectName,
- IReadOnlyList ToolFamilies,
- string? NodeWorkingDir,
- string? PythonRequirementsFile,
- bool HasDockerCompose,
- IReadOnlyList RootHints);
-
-public static class ConfigBootstrapper
-{
- private const int MaxScanDepth = 4;
-
- private static readonly HashSet ExcludedDirectories = new(StringComparer.OrdinalIgnoreCase)
- {
- ".git",
- "node_modules",
- ".venv",
- "venv",
- "bin",
- "obj",
- ".idea",
- ".vscode",
- "dist",
- "build",
- ".sdt",
- };
-
- private static readonly string[] RequirementCandidates =
- [
- "requirements.txt",
- "requirements-dev.txt",
- "requirements_cpu_only.txt",
- "requirements_gpu.txt",
- ];
-
- private static readonly JsonSerializerOptions JsonOptions = new()
- {
- PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
- WriteIndented = true
- };
-
- public static BootstrapScanResult Scan(string startDir)
- {
- var root = FindProjectRoot(startDir);
- var toolFamilies = new HashSet(StringComparer.OrdinalIgnoreCase);
- var rootHints = new HashSet(StringComparer.OrdinalIgnoreCase);
-
- if (Directory.Exists(Path.Combine(root, ".git")))
- {
- toolFamilies.Add("git");
- rootHints.Add(".git");
- }
-
- var hasTopLevelSln = Directory.EnumerateFiles(root, "*.sln", SearchOption.TopDirectoryOnly).Any();
- var hasCsproj = hasTopLevelSln || EnumerateFilesBounded(root, "*.csproj", MaxScanDepth).Any();
- if (hasCsproj)
- {
- toolFamilies.Add("dotnet");
- rootHints.Add("*.sln");
- }
-
- var topLevelPackageJson = Path.Combine(root, "package.json");
- var packageJson = File.Exists(topLevelPackageJson)
- ? topLevelPackageJson
- : EnumerateFilesBounded(root, "package.json", MaxScanDepth)
- .OrderBy(p => p.Length)
- .FirstOrDefault();
- string? nodeWorkingDir = null;
- if (packageJson is not null)
- {
- toolFamilies.Add("node");
- toolFamilies.Add("npm");
- nodeWorkingDir = Path.GetRelativePath(root, Path.GetDirectoryName(packageJson)!);
- rootHints.Add("package.json");
- }
-
- string? requirements = RequirementCandidates
- .Select(name => Path.Combine(root, name))
- .FirstOrDefault(File.Exists);
- if (requirements is null)
- {
- var pyproject = Path.Combine(root, "pyproject.toml");
- if (File.Exists(pyproject))
- {
- toolFamilies.Add("python");
- rootHints.Add("pyproject.toml");
- }
- }
- else
- {
- toolFamilies.Add("python");
- rootHints.Add(Path.GetFileName(requirements)!);
- }
-
- var hasCargo = File.Exists(Path.Combine(root, "Cargo.toml")) ||
- EnumerateFilesBounded(root, "Cargo.toml", MaxScanDepth).Any();
- if (hasCargo)
- {
- toolFamilies.Add("cargo");
- rootHints.Add("Cargo.toml");
- }
-
- var hasTauri = File.Exists(Path.Combine(root, "tauri.conf.json")) ||
- EnumerateFilesBounded(root, "tauri.conf.json", MaxScanDepth).Any();
- if (hasTauri)
- {
- toolFamilies.Add("tauri");
- toolFamilies.Add("cargo");
- toolFamilies.Add("node");
- toolFamilies.Add("npm");
- rootHints.Add("tauri.conf.json");
- }
-
- var hasDockerCompose = File.Exists(Path.Combine(root, "docker-compose.yml")) ||
- File.Exists(Path.Combine(root, "docker-compose.yaml"));
- if (hasDockerCompose || File.Exists(Path.Combine(root, "Dockerfile")))
- {
- toolFamilies.Add("docker");
- rootHints.Add(hasDockerCompose ? "docker-compose.yml" : "Dockerfile");
- }
-
- var scriptsDir = Path.Combine(root, "scripts");
- if (Directory.Exists(scriptsDir) &&
- Directory.EnumerateFiles(scriptsDir, "*.py", SearchOption.TopDirectoryOnly).Any())
- {
- toolFamilies.Add("python");
- rootHints.Add("scripts");
- }
-
- if (rootHints.Count == 0)
- rootHints.Add("devtool.json");
-
- return new BootstrapScanResult(
- ProjectRoot: root,
- ProjectName: new DirectoryInfo(root).Name,
- ToolFamilies: toolFamilies.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).ToList(),
- NodeWorkingDir: nodeWorkingDir,
- PythonRequirementsFile: requirements is null ? null : Path.GetRelativePath(root, requirements),
- HasDockerCompose: hasDockerCompose,
- RootHints: rootHints.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).ToList());
- }
-
- public static DevToolConfig BuildDefaultConfig(BootstrapScanResult scan)
- {
- var workflows = BuildWorkflows(scan).ToList();
-
- var toolingTools = scan.ToolFamilies
- .Select(t => new ToolInstallDefinition { Tool = t, PreferredInstallCommands = [] })
- .ToList();
-
- var toolchains = new ToolchainConfig
- {
- Python = scan.ToolFamilies.Contains("python", StringComparer.OrdinalIgnoreCase)
- ? new PythonToolchain
- {
- Executable = "python",
- WindowsExecutable = "py",
- VenvDir = ".venv",
- Profiles = []
- }
- : null,
- Node = scan.ToolFamilies.Contains("node", StringComparer.OrdinalIgnoreCase)
- ? new NodeToolchain
- {
- PackageManager = "npm",
- WorkingDir = string.IsNullOrWhiteSpace(scan.NodeWorkingDir) ? "." : scan.NodeWorkingDir
- }
- : null
- };
-
- var debugProfiles = BuildDebugProfiles(scan).ToList();
-
- return new DevToolConfig
- {
- Name = scan.ProjectName,
- Version = "0.1.0",
- Project = new ProjectMetadata
- {
- Type = "generic",
- RootHints = scan.RootHints.ToList(),
- Artifacts = ["bin", "obj", ".sdt/debug"]
- },
- Toolchains = toolchains,
- Tooling = new ToolingConfig { Tools = toolingTools },
- Workflows = workflows,
- Debug = new DebugConfig
- {
- Profiles = debugProfiles,
- Diagnostics = new DebugDiagnosticsOptions
- {
- Enabled = true,
- OutputDir = ".sdt/debug",
- IncludeAllEnv = false,
- CaptureEnvKeys =
- [
- "SDT_LOG_LEVEL",
- "DOTNET_CLI_HOME",
- "NUGET_PACKAGES",
- "PIP_CACHE_DIR",
- "NVM_HOME",
- "NVM_SYMLINK",
- ],
- BundleOnFailure = true
- }
- },
- Env =
- [
- new EnvVarDef
- {
- Key = "SDT_LOG_LEVEL",
- Description = "CLI log verbosity",
- DefaultValue = "information",
- Options = ["trace", "debug", "information", "warning", "error", "critical"]
- }
- ]
- };
- }
-
- public static string ToJson(DevToolConfig config) => JsonSerializer.Serialize(config, JsonOptions) + Environment.NewLine;
-
- public static string WriteDefaultConfig(string projectRoot, DevToolConfig config, bool overwrite = false)
- {
- var path = Path.Combine(projectRoot, "devtool.json");
- if (File.Exists(path) && !overwrite)
- throw new InvalidOperationException($"devtool.json already exists at {path}");
-
- File.WriteAllText(path, ToJson(config));
- return path;
- }
-
- private static IEnumerable BuildWorkflows(BootstrapScanResult scan)
- {
- var has = new Func(tool => scan.ToolFamilies.Contains(tool, StringComparer.OrdinalIgnoreCase));
- var scripts = DetectScriptHelpers(scan.ProjectRoot);
-
- if (scripts.Contains("publish-sidecar.py") ||
- scripts.Contains("publish-app.py") ||
- scripts.Contains("publish-webgateway.py") ||
- scripts.Contains("publish-output.py") ||
- scripts.Contains("sync-output.py") ||
- scripts.Contains("run-webgateway.py"))
- {
- foreach (var workflow in BuildScriptDrivenWorkflows(scripts))
- yield return workflow;
- }
-
- var buildSteps = new List();
- if (has("dotnet")) buildSteps.Add(StepAction("dotnet-build", "dotnet build", "dotnet-build"));
- if (has("npm")) buildSteps.Add(StepAction("npm-build", "npm run build", "npm-build", scan.NodeWorkingDir));
- if (has("cargo")) buildSteps.Add(StepAction("cargo-build", "cargo build", "cargo-build"));
- if (has("tauri")) buildSteps.Add(StepAction("tauri-build", "tauri build", "tauri-build", scan.NodeWorkingDir ?? "."));
- if (buildSteps.Count > 0)
- {
- yield return new WorkflowDefinition
- {
- Id = "build",
- Label = "Build",
- Description = "Build detected project stacks",
- Group = "Build",
- Steps = buildSteps
- };
- }
-
- var depsSteps = new List();
- if (has("dotnet")) depsSteps.Add(StepAction("dotnet-restore", "dotnet restore", "dotnet-restore"));
- if (has("npm")) depsSteps.Add(StepAction("npm-ci", "npm ci", "npm-ci", scan.NodeWorkingDir));
- if (has("python") && !string.IsNullOrWhiteSpace(scan.PythonRequirementsFile))
- {
- depsSteps.Add(StepAction("python-pip-sync", "python pip sync", "python-pip-sync", ".", ["--requirements", scan.PythonRequirementsFile!]));
- }
- if (depsSteps.Count > 0)
- {
- yield return new WorkflowDefinition
- {
- Id = "deps-refresh",
- Label = "Refresh Dependencies",
- Description = "Restore/install dependency stacks",
- Group = "Deps",
- Steps = depsSteps
- };
- }
-
- var testSteps = new List();
- if (has("dotnet")) testSteps.Add(StepAction("dotnet-test", "dotnet test", "dotnet-test"));
- if (has("npm")) testSteps.Add(StepAction("npm-test", "npm test", "npm-test", scan.NodeWorkingDir));
- if (has("python")) testSteps.Add(StepAction("python-pytest", "python -m pytest", "python-pytest"));
- if (has("cargo")) testSteps.Add(StepAction("cargo-test", "cargo test", "cargo-test"));
- if (testSteps.Count > 0)
- {
- yield return new WorkflowDefinition
- {
- Id = "test",
- Label = "Run Tests",
- Description = "Run detected test stacks",
- Group = "Test",
- Steps = testSteps
- };
- }
-
- if (has("git"))
- {
- yield return new WorkflowDefinition
- {
- Id = "repo-health",
- Label = "Repo Health",
- Description = "Check repo status and fetch remotes",
- Group = "Repo",
- Steps =
- [
- StepAction("git-status", "git status", "git-status"),
- StepAction("git-fetch", "git fetch", "git-fetch")
- ]
- };
- }
-
- if (has("docker"))
- {
- yield return new WorkflowDefinition
- {
- Id = "containers",
- Label = "Containers",
- Description = scan.HasDockerCompose ? "Manage docker compose stack" : "Build docker image",
- Group = "Containers",
- Steps = scan.HasDockerCompose
- ? [StepAction("docker-compose-up", "docker compose up -d", "docker-compose-up")]
- : [StepAction("docker-build", "docker build .", "docker-build")]
- };
- }
- }
-
- private static IEnumerable BuildDebugProfiles(BootstrapScanResult scan)
- {
- var has = new Func(tool => scan.ToolFamilies.Contains(tool, StringComparer.OrdinalIgnoreCase));
- if (has("dotnet"))
- {
- yield return new DebugProfileDefinition
- {
- Id = "dotnet-run",
- Label = "Run .NET app",
- Type = "dotnet",
- Command = "dotnet",
- Args = ["run"],
- WorkingDir = ".",
- Requires = [new ToolRequirement { Tool = "dotnet", InstallPolicy = InstallPolicy.Prompt }],
- Attach = new DebugAttachConfig
- {
- Kind = "manual",
- Note = "Attach your IDE debugger to the running dotnet process."
- }
- };
- }
-
- if (has("npm"))
- {
- yield return new DebugProfileDefinition
- {
- Id = "npm-dev",
- Label = "Run npm dev server",
- Type = "node",
- Command = "npm",
- Args = ["run", "dev"],
- WorkingDir = string.IsNullOrWhiteSpace(scan.NodeWorkingDir) ? "." : scan.NodeWorkingDir!,
- Requires =
- [
- new ToolRequirement { Tool = "node", InstallPolicy = InstallPolicy.Prompt },
- new ToolRequirement { Tool = "npm", InstallPolicy = InstallPolicy.Prompt }
- ]
- };
- }
- }
-
- private static WorkflowStep StepAction(
- string id,
- string label,
- string action,
- string? workingDir = null,
- IReadOnlyList? actionArgs = null)
- {
- return new WorkflowStep
- {
- Id = id,
- Label = label,
- Action = action,
- ActionArgs = actionArgs?.ToList() ?? [],
- WorkingDir = string.IsNullOrWhiteSpace(workingDir) ? "." : workingDir
- };
- }
-
- private static HashSet DetectScriptHelpers(string projectRoot)
- {
- var scriptsDir = Path.Combine(projectRoot, "scripts");
- if (!Directory.Exists(scriptsDir))
- return new HashSet(StringComparer.OrdinalIgnoreCase);
-
- return Directory.EnumerateFiles(scriptsDir, "*.py", SearchOption.TopDirectoryOnly)
- .Select(Path.GetFileName)
- .Where(f => !string.IsNullOrWhiteSpace(f))
- .Cast()
- .ToHashSet(StringComparer.OrdinalIgnoreCase);
- }
-
- private static IEnumerable BuildScriptDrivenWorkflows(HashSet scripts)
- {
- static WorkflowStep ScriptStep(string id, string label, params string[] scriptArgs) => new()
- {
- Id = id,
- Label = label,
- Command = "python",
- Args = scriptArgs.ToList(),
- WorkingDir = ".",
- Requires = [new ToolRequirement { Tool = "python", InstallPolicy = InstallPolicy.Prompt }]
- };
-
- if (scripts.Contains("publish-sidecar.py"))
- {
- yield return new WorkflowDefinition
- {
- Id = "sidecar",
- Label = "Publish Sidecar",
- Description = "Publish sidecar service",
- Group = "Build",
- Steps = [ScriptStep("sidecar:run", "python scripts/publish-sidecar.py", "scripts/publish-sidecar.py")]
- };
- }
-
- if (scripts.Contains("publish-app.py"))
- {
- yield return new WorkflowDefinition
- {
- Id = "web",
- Label = "Build Web UI",
- Description = "Build frontend assets",
- Group = "Build",
- Steps =
- [
- ScriptStep("web:run", "python scripts/publish-app.py --target web", "scripts/publish-app.py", "--target", "web")
- ]
- };
-
- yield return new WorkflowDefinition
- {
- Id = "tauri",
- Label = "Build Tauri Desktop App",
- Description = "Build desktop binary",
- Group = "Build",
- DependsOn = scripts.Contains("publish-sidecar.py") ? ["sidecar"] : [],
- Steps =
- [
- ScriptStep("tauri:run", "python scripts/publish-app.py --target tauri --tauri-bundles none",
- "scripts/publish-app.py", "--target", "tauri", "--tauri-bundles", "none")
- ]
- };
- }
-
- if (scripts.Contains("publish-webgateway.py"))
- {
- yield return new WorkflowDefinition
- {
- Id = "webgateway",
- Label = "Publish WebGateway",
- Description = "Publish ASP.NET gateway",
- Group = "Build",
- DependsOn = scripts.Contains("publish-app.py") ? ["web"] : [],
- Steps = [ScriptStep("webgateway:run", "python scripts/publish-webgateway.py", "scripts/publish-webgateway.py")]
- };
- }
-
- if (scripts.Contains("sync-output.py"))
- {
- yield return new WorkflowDefinition
- {
- Id = "sync-output",
- Label = "Sync Output",
- Description = "Sync newest artifacts to output",
- Group = "Build",
- Steps = [ScriptStep("sync-output:run", "python scripts/sync-output.py", "scripts/sync-output.py")]
- };
- }
-
- if (scripts.Contains("publish-output.py"))
- {
- yield return new WorkflowDefinition
- {
- Id = "stage-output",
- Label = "Stage Output Bundle",
- Description = "Publish and stage distributable output",
- Group = "Build",
- Steps = [ScriptStep("stage-output:run", "python scripts/publish-output.py", "scripts/publish-output.py")]
- };
- }
-
- if (scripts.Contains("run-webgateway.py"))
- {
- yield return new WorkflowDefinition
- {
- Id = "run-gateway-dev",
- Label = "Run WebGateway Server (Dev)",
- Description = "Run gateway in development mode",
- Group = "Dev",
- Steps =
- [
- ScriptStep("run-gateway-dev:run", "python scripts/run-webgateway.py --mode Dev",
- "scripts/run-webgateway.py", "--mode", "Dev")
- ]
- };
- }
- }
-
- private static string FindProjectRoot(string startDir)
- {
- var start = Path.GetFullPath(startDir);
- var gitRoot = TryGetGitRoot(start);
- if (!string.IsNullOrWhiteSpace(gitRoot))
- return gitRoot!;
-
- var best = start;
- var bestScore = ScoreRoot(start);
- var cursor = new DirectoryInfo(start);
- while (cursor.Parent is not null)
- {
- cursor = cursor.Parent;
- var score = ScoreRoot(cursor.FullName);
- if (score > bestScore)
- {
- best = cursor.FullName;
- bestScore = score;
- }
- }
-
- return best;
- }
-
- private static int ScoreRoot(string path)
- {
- var score = 0;
- if (File.Exists(Path.Combine(path, "package.json"))) score += 2;
- if (File.Exists(Path.Combine(path, "pyproject.toml"))) score += 2;
- if (File.Exists(Path.Combine(path, "Cargo.toml"))) score += 2;
- if (File.Exists(Path.Combine(path, "docker-compose.yml")) ||
- File.Exists(Path.Combine(path, "docker-compose.yaml")) ||
- File.Exists(Path.Combine(path, "Dockerfile"))) score += 1;
- if (Directory.EnumerateFiles(path, "*.sln", SearchOption.TopDirectoryOnly).Any()) score += 3;
- if (Directory.Exists(Path.Combine(path, ".git"))) score += 1;
- return score;
- }
-
- private static string? TryGetGitRoot(string start)
- {
- try
- {
- var psi = new System.Diagnostics.ProcessStartInfo
- {
- FileName = "git",
- UseShellExecute = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- CreateNoWindow = true,
- WorkingDirectory = start
- };
- psi.ArgumentList.Add("rev-parse");
- psi.ArgumentList.Add("--show-toplevel");
- using var process = System.Diagnostics.Process.Start(psi);
- if (process is null)
- return null;
- var stdout = process.StandardOutput.ReadToEnd();
- process.WaitForExit(2000);
- if (process.ExitCode == 0 && !string.IsNullOrWhiteSpace(stdout))
- return stdout.Trim();
- return null;
- }
- catch
- {
- return null;
- }
- }
-
- private static IEnumerable EnumerateFilesBounded(string root, string pattern, int maxDepth)
- {
- var queue = new Queue<(string Dir, int Depth)>();
- queue.Enqueue((root, 0));
-
- while (queue.Count > 0)
- {
- var (dir, depth) = queue.Dequeue();
- IEnumerable files = [];
- try
- {
- files = Directory.EnumerateFiles(dir, pattern, SearchOption.TopDirectoryOnly);
- }
- catch
- {
- // Ignore unreadable directories.
- }
-
- foreach (var file in files)
- yield return file;
-
- if (depth >= maxDepth)
- continue;
-
- IEnumerable subdirs = [];
- try
- {
- subdirs = Directory.EnumerateDirectories(dir, "*", SearchOption.TopDirectoryOnly);
- }
- catch
- {
- // Ignore unreadable directories.
- }
-
- foreach (var subdir in subdirs)
- {
- var name = Path.GetFileName(subdir);
- if (ExcludedDirectories.Contains(name))
- continue;
-
- queue.Enqueue((subdir, depth + 1));
- }
- }
- }
-}
diff --git a/Journal.DevTool/Config/ConfigLoader.cs b/Journal.DevTool/Config/ConfigLoader.cs
deleted file mode 100644
index 507c9d6..0000000
--- a/Journal.DevTool/Config/ConfigLoader.cs
+++ /dev/null
@@ -1,223 +0,0 @@
-using System.Text.Json;
-using System.Text.Json.Nodes;
-using Sdt.Core;
-
-namespace Sdt.Config;
-
-public sealed record LoadedProjectConfig(
- DevToolConfig Config,
- string ProjectRoot,
- IReadOnlyList Warnings);
-
-public sealed record LegacyMigrationApplyResult(
- bool Success,
- string Message,
- string? BackupPath = null,
- string? ConfigPath = null);
-
-public static class ConfigLoader
-{
- public const string WorkspaceDefaultsFileName = "sdt-defaults.json";
-
- private static readonly JsonSerializerOptions JsonOptions = new()
- {
- PropertyNameCaseInsensitive = true,
- PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
- AllowTrailingCommas = true,
- ReadCommentHandling = JsonCommentHandling.Skip,
- };
-
- ///
- /// Walks up from (or CWD) until it finds devtool.json.
- /// Returns null if not found.
- ///
- public static string? FindConfigPath(string? startDir = null)
- {
- var dir = new DirectoryInfo(startDir ?? Directory.GetCurrentDirectory());
- while (dir is not null)
- {
- var candidate = Path.Combine(dir.FullName, "devtool.json");
- if (File.Exists(candidate))
- return candidate;
- dir = dir.Parent!;
- }
- return null;
- }
-
- public static LoadedProjectConfig? FindAndLoad(string? startDir = null)
- {
- var configPath = FindConfigPath(startDir);
- if (configPath is null)
- return null;
-
- var projectRoot = Path.GetDirectoryName(configPath)
- ?? throw new InvalidOperationException($"Could not resolve project root from {configPath}");
-
- try
- {
- var effectiveConfig = LoadEffectiveConfig(projectRoot, configPath, out var defaultsPath);
- var warnings = new List();
- if (!string.IsNullOrWhiteSpace(defaultsPath))
- warnings.Add($"Applied workspace defaults from {defaultsPath}.");
-
- var legacyMode = ResolveLegacyMode();
- if (legacyMode == LegacyMode.Strict && effectiveConfig.Workflows.Count == 0 && effectiveConfig.Targets.Count > 0)
- {
- var previewPath = Path.Combine(projectRoot, "devtool.generated.workflows.json");
- try
- {
- var previewConfig = WorkflowModelBuilder.BuildMigrationPreviewConfig(effectiveConfig, new RequirementResolver());
- File.WriteAllText(previewPath, ConfigBootstrapper.ToJson(previewConfig));
- }
- catch
- {
- // Keep strict failure even if preview generation fails.
- }
-
- throw new InvalidOperationException(
- $"Legacy targets-only config detected at {configPath}. Strict mode requires workflows. " +
- "Use migration preview file 'devtool.generated.workflows.json' and migrate devtool.json. " +
- "Temporary rollback: set SDT_LEGACY_MODE=compat.");
- }
-
- var normalized = WorkflowModelBuilder.Normalize(effectiveConfig, legacyMode, new RequirementResolver());
- warnings.AddRange(normalized.Warnings);
- return new LoadedProjectConfig(effectiveConfig, projectRoot, warnings);
- }
- catch (Exception ex)
- {
- throw new InvalidOperationException(
- $"Failed to parse devtool.json at {configPath}: {ex.Message}", ex);
- }
- }
-
- public static LegacyMigrationApplyResult ApplyLegacyTargetMigration(
- string configPath,
- bool createBackup = true)
- {
- try
- {
- if (!File.Exists(configPath))
- return new LegacyMigrationApplyResult(false, $"Config file not found: {configPath}");
-
- var json = File.ReadAllText(configPath);
- var config = JsonSerializer.Deserialize(json, JsonOptions)
- ?? throw new InvalidOperationException("devtool.json deserialized to null.");
-
- if (config.Targets.Count == 0)
- return new LegacyMigrationApplyResult(false, "No legacy targets found to migrate.", ConfigPath: configPath);
-
- var migrated = WorkflowModelBuilder.BuildMigrationPreviewConfig(config, new RequirementResolver());
- var backupPath = (string?)null;
- if (createBackup)
- {
- backupPath = configPath + $".bak-{DateTimeOffset.Now:yyyyMMdd-HHmmss}";
- File.Copy(configPath, backupPath, overwrite: false);
- }
-
- File.WriteAllText(configPath, ConfigBootstrapper.ToJson(migrated));
- return new LegacyMigrationApplyResult(
- true,
- "Legacy targets migrated to workflows.",
- BackupPath: backupPath,
- ConfigPath: configPath);
- }
- catch (Exception ex)
- {
- return new LegacyMigrationApplyResult(false, ex.Message, ConfigPath: configPath);
- }
- }
-
- private static LegacyMode ResolveLegacyMode()
- {
- var raw = Environment.GetEnvironmentVariable("SDT_LEGACY_MODE");
- return string.Equals(raw, "compat", StringComparison.OrdinalIgnoreCase)
- ? LegacyMode.Compat
- : LegacyMode.Strict;
- }
-
- private static DevToolConfig LoadEffectiveConfig(
- string projectRoot,
- string projectConfigPath,
- out string? defaultsPath)
- {
- defaultsPath = FindWorkspaceDefaultsPath(projectRoot);
- var projectObj = LoadJsonObject(projectConfigPath, "project config");
- if (string.IsNullOrWhiteSpace(defaultsPath))
- return DeserializeConfig(projectObj, projectConfigPath);
-
- var defaultsObj = LoadJsonObject(defaultsPath!, "workspace defaults");
- var merged = MergeObjects(defaultsObj, projectObj);
- return DeserializeConfig(merged, projectConfigPath);
- }
-
- private static string? FindWorkspaceDefaultsPath(string startDir)
- {
- var workspaceBoundary = FindWorkspaceBoundary(startDir);
- var dir = new DirectoryInfo(startDir);
- while (dir is not null)
- {
- var candidate = Path.Combine(dir.FullName, WorkspaceDefaultsFileName);
- if (File.Exists(candidate))
- return candidate;
- if (workspaceBoundary is not null &&
- string.Equals(dir.FullName, workspaceBoundary, StringComparison.OrdinalIgnoreCase))
- {
- break;
- }
- if (workspaceBoundary is null)
- break;
- dir = dir.Parent;
- }
-
- return null;
- }
-
- private static string? FindWorkspaceBoundary(string startDir)
- {
- var dir = new DirectoryInfo(startDir);
- while (dir is not null)
- {
- var workspacePath = Path.Combine(dir.FullName, WorkspaceLoader.FileName);
- if (File.Exists(workspacePath))
- return dir.FullName;
- dir = dir.Parent;
- }
-
- return null;
- }
-
- private static JsonObject LoadJsonObject(string path, string label)
- {
- var json = File.ReadAllText(path);
- var node = JsonNode.Parse(json)
- ?? throw new InvalidOperationException($"{label} at {path} deserialized to null.");
- if (node is not JsonObject obj)
- throw new InvalidOperationException($"{label} at {path} must be a JSON object.");
- return obj;
- }
-
- private static DevToolConfig DeserializeConfig(JsonObject obj, string sourcePath)
- {
- return obj.Deserialize(JsonOptions)
- ?? throw new InvalidOperationException($"devtool.json at {sourcePath} deserialized to null.");
- }
-
- private static JsonObject MergeObjects(JsonObject baseObj, JsonObject overlayObj)
- {
- var result = (JsonObject)baseObj.DeepClone();
- foreach (var kv in overlayObj)
- {
- if (kv.Value is JsonObject overlayChild &&
- result[kv.Key] is JsonObject baseChild)
- {
- result[kv.Key] = MergeObjects(baseChild, overlayChild);
- continue;
- }
-
- result[kv.Key] = kv.Value?.DeepClone();
- }
-
- return result;
- }
-}
diff --git a/Journal.DevTool/Config/DevToolConfig.cs b/Journal.DevTool/Config/DevToolConfig.cs
deleted file mode 100644
index 4a4c108..0000000
--- a/Journal.DevTool/Config/DevToolConfig.cs
+++ /dev/null
@@ -1,185 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace Sdt.Config;
-
-public sealed class DevToolConfig
-{
- public string Name { get; init; } = "SDT Project";
- public string Version { get; init; } = "0.1.0";
- public List Targets { get; init; } = [];
- public List Workflows { get; init; } = [];
- public List Env { get; init; } = [];
- public ToolchainConfig? Toolchains { get; init; }
- public ToolingConfig? Tooling { get; init; }
- public ProjectMetadata? Project { get; init; }
- public DebugConfig? Debug { get; init; }
-}
-
-public sealed class BuildTarget
-{
- public string Id { get; init; } = "";
- public string Label { get; init; } = "";
- public string Description { get; init; } = "";
- public string Group { get; init; } = "General";
-
- /// Executable name. Null = virtual aggregator (runs DependsOn only).
- public string? Command { get; init; }
-
- public List Args { get; init; } = [];
-
- /// Working directory relative to project root.
- public string WorkingDir { get; init; } = ".";
-
- public List DependsOn { get; init; } = [];
-}
-
-public sealed class EnvVarDef
-{
- public string Key { get; init; } = "";
- public string Description { get; init; } = "";
-
- [System.Text.Json.Serialization.JsonPropertyName("default")]
- public string DefaultValue { get; init; } = "";
-
- /// If non-empty, shown as a dropdown. Otherwise free-text input.
- public List Options { get; init; } = [];
-}
-
-public sealed class WorkflowDefinition
-{
- public string Id { get; init; } = "";
- public string Label { get; init; } = "";
- public string Description { get; init; } = "";
- public string Group { get; init; } = "General";
- public List DependsOn { get; init; } = [];
- public List Steps { get; init; } = [];
-}
-
-public sealed class WorkflowStep
-{
- public string Id { get; init; } = "";
- public string Label { get; init; } = "";
- public string? Command { get; init; }
- public List Args { get; init; } = [];
- public string WorkingDir { get; init; } = ".";
- public string? Action { get; init; }
- public List ActionArgs { get; init; } = [];
- public List Requires { get; init; } = [];
-}
-
-public sealed class ToolRequirement
-{
- public string Tool { get; init; } = "";
-
- [JsonConverter(typeof(JsonStringEnumConverter))]
- public InstallPolicy InstallPolicy { get; init; } = InstallPolicy.Prompt;
-}
-
-[JsonConverter(typeof(JsonStringEnumConverter))]
-public enum InstallPolicy
-{
- Prompt,
- Auto,
- Never,
-}
-
-public sealed class ToolingConfig
-{
- public List Tools { get; init; } = [];
-}
-
-public sealed class ToolInstallDefinition
-{
- public string Tool { get; init; } = "";
- public List PreferredInstallCommands { get; init; } = [];
- public List Executables { get; init; } = [];
-}
-
-public sealed class ProjectMetadata
-{
- public string Type { get; init; } = "";
- public List RootHints { get; init; } = [];
- public List Artifacts { get; init; } = [];
-}
-
-public sealed class DebugConfig
-{
- public List Profiles { get; init; } = [];
- public DebugDiagnosticsOptions Diagnostics { get; init; } = new();
-}
-
-public sealed class DebugProfileDefinition
-{
- public string Id { get; init; } = "";
- public string Label { get; init; } = "";
- public string Type { get; init; } = "generic";
- public string Command { get; init; } = "";
- public List Args { get; init; } = [];
- public string WorkingDir { get; init; } = ".";
- public Dictionary Env { get; init; } = new(StringComparer.OrdinalIgnoreCase);
- public List Requires { get; init; } = [];
- public DebugAttachConfig? Attach { get; init; }
-}
-
-public sealed class DebugAttachConfig
-{
- public string Kind { get; init; } = "";
- public int? Port { get; init; }
- public string? ProcessName { get; init; }
- public string? Note { get; init; }
-}
-
-public sealed class DebugDiagnosticsOptions
-{
- public bool Enabled { get; init; } = true;
- public string OutputDir { get; init; } = ".sdt/debug";
- public bool IncludeAllEnv { get; init; } = false;
- public List CaptureEnvKeys { get; init; } = [];
- public bool BundleOnFailure { get; init; } = true;
-}
-
-// ── Toolchain config ──────────────────────────────────────────────────────────
-
-public sealed class ToolchainConfig
-{
- public PythonToolchain? Python { get; init; }
- public NodeToolchain? Node { get; init; }
-}
-
-public sealed class PythonToolchain
-{
- /// Python executable (e.g. "python3.14", "python").
- public string Executable { get; init; } = "python";
-
- /// Windows-specific override (e.g. "py" when using the launcher).
- public string? WindowsExecutable { get; init; }
-
- /// Optional version flag to pass (e.g. "-3.14" for py launcher).
- public string? LauncherVersion { get; init; }
-
- /// Venv directory relative to project root.
- public string VenvDir { get; init; } = ".venv";
-
- public List Profiles { get; init; } = [];
-
- /// Optional path to a pip wrapper script (relative to project root).
- public string? PipScript { get; init; }
-}
-
-public sealed class PythonProfile
-{
- public string Id { get; init; } = "";
- public string Label { get; init; } = "";
- public string RequirementsFile { get; init; } = "";
- public string? ExtraIndexUrl { get; init; }
- public List PostInstallCommands { get; init; } = [];
-}
-
-public sealed class NodeToolchain
-{
- /// Package manager: "npm", "pnpm", or "yarn".
- public string PackageManager { get; init; } = "npm";
-
- /// Working directory for the frontend (relative to project root).
- public string WorkingDir { get; init; } = ".";
-}
diff --git a/Journal.DevTool/Config/WorkflowModelBuilder.cs b/Journal.DevTool/Config/WorkflowModelBuilder.cs
deleted file mode 100644
index 6501835..0000000
--- a/Journal.DevTool/Config/WorkflowModelBuilder.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-using Sdt.Core;
-
-namespace Sdt.Config;
-
-public enum LegacyMode
-{
- Strict,
- Compat,
-}
-
-public sealed record WorkflowNormalizationResult(
- IReadOnlyList Workflows,
- IReadOnlyList Warnings);
-
-public static class WorkflowModelBuilder
-{
- public static WorkflowNormalizationResult Normalize(
- DevToolConfig config,
- LegacyMode legacyMode = LegacyMode.Strict,
- IRequirementResolver? requirementResolver = null)
- {
- requirementResolver ??= new RequirementResolver();
- var warnings = new List();
-
- if (config.Workflows.Count > 0)
- {
- if (config.Targets.Count > 0)
- {
- warnings.Add("Both 'workflows' and legacy 'targets' are present. SDT will use 'workflows'.");
- }
-
- return new WorkflowNormalizationResult(config.Workflows, warnings);
- }
-
- if (config.Targets.Count == 0)
- {
- warnings.Add("No 'workflows' or legacy 'targets' were found.");
- return new WorkflowNormalizationResult([], warnings);
- }
-
- if (legacyMode == LegacyMode.Strict)
- {
- throw new InvalidOperationException(
- "Legacy 'targets' are not allowed in strict mode. Migrate to 'workflows' or set SDT_LEGACY_MODE=compat temporarily.");
- }
-
- warnings.Add("Using legacy 'targets' schema. Migrate to 'workflows' for v1+ features.");
- return new WorkflowNormalizationResult(ConvertLegacyTargets(config.Targets, requirementResolver), warnings);
- }
-
- public static DevToolConfig BuildMigrationPreviewConfig(DevToolConfig config, IRequirementResolver? requirementResolver = null)
- {
- requirementResolver ??= new RequirementResolver();
- return new DevToolConfig
- {
- Name = config.Name,
- Version = config.Version,
- Targets = [],
- Workflows = ConvertLegacyTargets(config.Targets, requirementResolver),
- Env = config.Env,
- Toolchains = config.Toolchains,
- Tooling = config.Tooling,
- Project = config.Project,
- Debug = config.Debug,
- };
- }
-
- private static List ConvertLegacyTargets(
- IReadOnlyList targets,
- IRequirementResolver requirementResolver)
- {
- var workflows = new List(targets.Count);
- foreach (var target in targets)
- {
- var step = target.Command is null
- ? null
- : new WorkflowStep
- {
- Id = $"{target.Id}:run",
- Label = string.IsNullOrWhiteSpace(target.Label) ? target.Id : target.Label,
- Command = target.Command,
- Args = target.Args,
- WorkingDir = target.WorkingDir,
- Requires = requirementResolver.Resolve(target),
- };
-
- workflows.Add(new WorkflowDefinition
- {
- Id = target.Id,
- Label = target.Label,
- Description = target.Description,
- Group = target.Group,
- DependsOn = target.DependsOn,
- Steps = step is null ? [] : [step],
- });
- }
-
- return workflows;
- }
-}
diff --git a/Journal.DevTool/Config/WorkspaceConfig.cs b/Journal.DevTool/Config/WorkspaceConfig.cs
deleted file mode 100644
index 92c9b57..0000000
--- a/Journal.DevTool/Config/WorkspaceConfig.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace Sdt.Config;
-
-public sealed class WorkspaceConfig
-{
- public string Name { get; init; } = "SDT Workspace";
- public List Projects { get; init; } = [];
-}
-
-public sealed class WorkspaceProject
-{
- public string Name { get; init; } = "";
- public string Description { get; init; } = "";
-
- ///
- /// Relative or absolute path to the project root
- /// (the directory containing devtool.json).
- ///
- public string Path { get; init; } = "";
- public List Tags { get; init; } = [];
- public List ToolFamilies { get; init; } = [];
- public bool Disabled { get; init; } = false;
-}
diff --git a/Journal.DevTool/Config/WorkspaceLoader.cs b/Journal.DevTool/Config/WorkspaceLoader.cs
deleted file mode 100644
index 90cc7a5..0000000
--- a/Journal.DevTool/Config/WorkspaceLoader.cs
+++ /dev/null
@@ -1,170 +0,0 @@
-using System.Text.Json;
-
-namespace Sdt.Config;
-
-public static class WorkspaceLoader
-{
- public const string FileName = "sdt-workspace.json";
-
- private static readonly JsonSerializerOptions JsonOptions = new()
- {
- PropertyNameCaseInsensitive = true,
- PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
- AllowTrailingCommas = true,
- ReadCommentHandling = JsonCommentHandling.Skip,
- };
-
- ///
- /// Walks up from (or CWD) to find sdt-workspace.json.
- /// Returns null if not found.
- ///
- public static (WorkspaceConfig Config, string WorkspaceRoot)? FindAndLoad(string? startDir = null)
- {
- var dir = new DirectoryInfo(startDir ?? Directory.GetCurrentDirectory());
- while (dir is not null)
- {
- var candidate = Path.Combine(dir.FullName, FileName);
- if (File.Exists(candidate))
- {
- try
- {
- var json = File.ReadAllText(candidate);
- var config = JsonSerializer.Deserialize(json, JsonOptions)
- ?? throw new InvalidOperationException($"{FileName} deserialized to null.");
- return (config, dir.FullName);
- }
- catch (Exception ex)
- {
- throw new InvalidOperationException(
- $"Failed to parse {FileName} at {candidate}: {ex.Message}", ex);
- }
- }
- dir = dir.Parent!;
- }
-
- // No workspace file found; synthesize one by scanning nearby project roots.
- return TryAutoDiscover(startDir ?? Directory.GetCurrentDirectory());
- }
-
- ///
- /// Resolves the absolute project root for a workspace project entry.
- ///
- public static string ResolveProjectRoot(string workspaceRoot, WorkspaceProject project)
- => Path.GetFullPath(Path.IsPathRooted(project.Path)
- ? project.Path
- : Path.Combine(workspaceRoot, project.Path));
-
- public static string GetWorkspaceFilePath(string workspaceRoot)
- => Path.Combine(workspaceRoot, FileName);
-
- public static void Save(string workspaceRoot, WorkspaceConfig workspace)
- {
- var path = GetWorkspaceFilePath(workspaceRoot);
- var saveOptions = new JsonSerializerOptions(JsonOptions)
- {
- WriteIndented = true
- };
- var json = JsonSerializer.Serialize(workspace, saveOptions);
- File.WriteAllText(path, json + Environment.NewLine);
- }
-
- private static (WorkspaceConfig Config, string WorkspaceRoot)? TryAutoDiscover(string startDir)
- {
- LoadedProjectConfig? loaded;
- try
- {
- loaded = ConfigLoader.FindAndLoad(startDir);
- }
- catch
- {
- return null;
- }
-
- if (loaded is null)
- return null;
-
- var currentRoot = loaded.ProjectRoot;
- var parent = Directory.GetParent(currentRoot);
- var workspaceRoot = parent?.FullName ?? currentRoot;
-
- var roots = DiscoverProjectRoots(workspaceRoot, currentRoot);
- if (roots.Count == 0)
- return null;
-
- var projects = new List();
- foreach (var root in roots)
- {
- LoadedProjectConfig? cfg;
- try
- {
- cfg = ConfigLoader.FindAndLoad(root);
- }
- catch
- {
- continue;
- }
-
- var name = cfg?.Config.Name;
- projects.Add(new WorkspaceProject
- {
- Name = string.IsNullOrWhiteSpace(name) ? new DirectoryInfo(root).Name : name!,
- Description = $"Auto-discovered at {root}",
- Path = Path.GetRelativePath(workspaceRoot, root),
- });
- }
-
- return (
- new WorkspaceConfig
- {
- Name = "SDT Auto Workspace",
- Projects = projects
- },
- workspaceRoot);
- }
-
- private static List DiscoverProjectRoots(string workspaceRoot, string currentRoot)
- {
- var set = new HashSet(StringComparer.OrdinalIgnoreCase);
- var excluded = new HashSet(StringComparer.OrdinalIgnoreCase)
- {
- "bin",
- "obj",
- ".git",
- ".venv",
- "node_modules",
- };
-
- void AddIfProject(string path)
- {
- var full = Path.GetFullPath(path);
- if (File.Exists(Path.Combine(full, "devtool.json")))
- set.Add(full);
- }
-
- AddIfProject(currentRoot);
- AddIfProject(workspaceRoot);
-
- try
- {
- foreach (var dir in Directory.EnumerateDirectories(workspaceRoot))
- {
- if (excluded.Contains(Path.GetFileName(dir)))
- continue;
-
- AddIfProject(dir);
- foreach (var sub in Directory.EnumerateDirectories(dir))
- {
- if (excluded.Contains(Path.GetFileName(sub)))
- continue;
- AddIfProject(sub);
- }
- }
- }
- catch
- {
- // Ignore inaccessible directories during auto-discovery.
- }
-
- return set.OrderBy(p => p, StringComparer.OrdinalIgnoreCase).ToList();
- }
-}
diff --git a/Journal.DevTool/Core/ActionRunner.cs b/Journal.DevTool/Core/ActionRunner.cs
deleted file mode 100644
index 735415b..0000000
--- a/Journal.DevTool/Core/ActionRunner.cs
+++ /dev/null
@@ -1,207 +0,0 @@
-using Sdt.Config;
-using Sdt.Runner;
-
-namespace Sdt.Core;
-
-public sealed class ActionRunner : IActionRunner
-{
- public async Task RunStepAsync(
- WorkflowStep step,
- string projectRoot,
- Action onOutput,
- CancellationToken cancellationToken = default)
- {
- if (!string.IsNullOrWhiteSpace(step.Action))
- {
- var scriptPath = ScriptLocator.FindHelperScript(projectRoot, "build.py");
- if (scriptPath is null)
- throw new InvalidOperationException("build.py not found in bundled scripts or project scripts directory.");
-
- var actionArgs = new List
- {
- scriptPath,
- step.Action,
- "--project-root",
- projectRoot,
- };
- actionArgs.AddRange(step.ActionArgs);
-
- return await ProcessRunner.RunAsync(
- PythonResolver.ResolveExecutable(),
- actionArgs,
- projectRoot,
- onOutput,
- cancellationToken: cancellationToken).ConfigureAwait(false);
- }
-
- if (string.IsNullOrWhiteSpace(step.Command))
- return new RunResult(0, TimeSpan.Zero);
-
- var workingDir = Path.GetFullPath(Path.Combine(projectRoot, step.WorkingDir));
-
- var pwshReroute = await TryRunLegacyPwshScriptViaPythonAsync(
- step,
- projectRoot,
- workingDir,
- onOutput,
- cancellationToken).ConfigureAwait(false);
- if (pwshReroute is not null)
- return pwshReroute;
-
- return await ProcessRunner.RunAsync(
- step.Command,
- step.Args,
- workingDir,
- onOutput,
- cancellationToken: cancellationToken).ConfigureAwait(false);
- }
-
- private static async Task TryRunLegacyPwshScriptViaPythonAsync(
- WorkflowStep step,
- string projectRoot,
- string workingDir,
- Action onOutput,
- CancellationToken cancellationToken)
- {
- if (!IsPowerShellCommand(step.Command))
- return null;
-
- var args = step.Args;
- var fileIndex = FindArgIndex(args, "-File");
- if (fileIndex < 0 || fileIndex + 1 >= args.Count)
- return null;
-
- var psScriptArg = args[fileIndex + 1];
- if (!psScriptArg.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase))
- return null;
-
- var pyScriptPath = ResolvePythonScriptPath(projectRoot, workingDir, psScriptArg);
- if (pyScriptPath is null)
- return null;
-
- var translated = TranslatePowerShellArgsToPython(args.Skip(fileIndex + 2));
- var pythonArgs = new List { pyScriptPath };
- pythonArgs.AddRange(translated);
-
- onOutput($"Legacy PowerShell target detected. Trying Python script first: {Path.GetFileName(pyScriptPath)}", false);
-
- var pyRun = await ProcessRunner.RunAsync(
- PythonResolver.ResolveExecutable(),
- pythonArgs,
- workingDir,
- onOutput,
- cancellationToken: cancellationToken).ConfigureAwait(false);
-
- if (pyRun.Success)
- return pyRun;
-
- var psScriptPath = ResolveScriptPath(workingDir, psScriptArg);
- if (psScriptPath is null || !File.Exists(psScriptPath))
- return pyRun;
-
- onOutput(
- $"Python script failed (exit {pyRun.ExitCode}). Falling back to legacy PowerShell script: {psScriptArg}",
- true);
- return null;
- }
-
- private static string? ResolvePythonScriptPath(string projectRoot, string workingDir, string psScriptArg)
- {
- var pyArg = Path.ChangeExtension(psScriptArg, ".py");
- var candidate = ResolveScriptPath(workingDir, pyArg);
- if (candidate is not null && File.Exists(candidate))
- return candidate;
-
- var fileName = Path.GetFileName(pyArg);
- return ScriptLocator.FindHelperScript(projectRoot, fileName);
- }
-
- private static string? ResolveScriptPath(string workingDir, string scriptArg)
- {
- if (Path.IsPathRooted(scriptArg))
- return scriptArg;
- return Path.GetFullPath(Path.Combine(workingDir, scriptArg));
- }
-
- private static bool IsPowerShellCommand(string? command)
- {
- if (string.IsNullOrWhiteSpace(command))
- return false;
-
- var normalized = Path.GetFileNameWithoutExtension(command).ToLowerInvariant();
- return normalized is "pwsh" or "powershell";
- }
-
- private static int FindArgIndex(IReadOnlyList args, string name)
- {
- for (var i = 0; i < args.Count; i++)
- {
- if (string.Equals(args[i], name, StringComparison.OrdinalIgnoreCase))
- return i;
- }
- return -1;
- }
-
- private static List TranslatePowerShellArgsToPython(IEnumerable inputArgs)
- {
- var result = new List();
- var list = inputArgs.ToList();
-
- for (var i = 0; i < list.Count; i++)
- {
- var token = list[i];
- if (!token.StartsWith("-", StringComparison.Ordinal) || token == "-")
- {
- result.Add(token);
- continue;
- }
-
- var key = token.TrimStart('-');
- if (key.Length == 0)
- continue;
-
- var mapped = MapPowerShellParameter(key);
- var nextIsValue = (i + 1) < list.Count && !list[i + 1].StartsWith("-", StringComparison.Ordinal);
- result.Add(mapped);
- if (nextIsValue)
- {
- result.Add(list[i + 1]);
- i++;
- }
- }
-
- return result;
- }
-
- private static string MapPowerShellParameter(string key)
- {
- return key.ToLowerInvariant() switch
- {
- "tauribundles" => "--tauri-bundles",
- "projectroot" => "--project-root",
- "reporoot" => "--repo-root",
- "outputzip" => "--output-zip",
- "inputzip" => "--input-zip",
- "workingdir" => "--working-dir",
- "outputdir" => "--output-dir",
- _ => "--" + ToKebabCase(key)
- };
- }
-
- private static string ToKebabCase(string value)
- {
- if (string.IsNullOrWhiteSpace(value))
- return value.ToLowerInvariant();
-
- var chars = new List(value.Length + 4);
- for (var i = 0; i < value.Length; i++)
- {
- var c = value[i];
- if (char.IsUpper(c) && i > 0 && value[i - 1] != '-')
- chars.Add('-');
- chars.Add(char.ToLowerInvariant(c));
- }
-
- return new string(chars.ToArray());
- }
-}
diff --git a/Journal.DevTool/Core/CommandResolver.cs b/Journal.DevTool/Core/CommandResolver.cs
deleted file mode 100644
index 262b6fa..0000000
--- a/Journal.DevTool/Core/CommandResolver.cs
+++ /dev/null
@@ -1,173 +0,0 @@
-namespace Sdt.Core;
-
-public enum CommandResolutionSource
-{
- Exact,
- Path,
- Shim,
- NodeAdjacentShim,
- ConfiguredOverride,
- Fallback,
-}
-
-public sealed record CommandResolutionResult(
- string Requested,
- string Resolved,
- CommandResolutionSource Source);
-
-public static class CommandResolver
-{
- public static CommandResolutionResult ResolveWithTrace(string command, Config.DevToolConfig? config = null, string? tool = null)
- {
- if (string.IsNullOrWhiteSpace(command))
- return new CommandResolutionResult(command, command, CommandResolutionSource.Exact);
-
- if (!OperatingSystem.IsWindows())
- return new CommandResolutionResult(command, command, CommandResolutionSource.Exact);
-
- if (command.Contains(Path.DirectorySeparatorChar) || command.Contains(Path.AltDirectorySeparatorChar))
- return new CommandResolutionResult(command, command, CommandResolutionSource.Exact);
-
- var normalized = command.ToLowerInvariant();
- if (Path.HasExtension(command))
- {
- var extensionResolved = ResolveFromPath(command);
- return extensionResolved is null
- ? new CommandResolutionResult(command, command, CommandResolutionSource.Fallback)
- : new CommandResolutionResult(command, extensionResolved, CommandResolutionSource.Path);
- }
-
- var overrideTool = string.IsNullOrWhiteSpace(tool) ? normalized : tool.ToLowerInvariant();
- var configuredCandidates = config?.Tooling?.Tools
- .FirstOrDefault(t => string.Equals(t.Tool, overrideTool, StringComparison.OrdinalIgnoreCase))
- ?.Executables
- ?.Where(x => !string.IsNullOrWhiteSpace(x))
- .ToList();
-
- if (configuredCandidates is not null)
- {
- foreach (var configured in configuredCandidates)
- {
- var resolvedConfigured = ResolveFromPath(configured!) ?? configured!;
- if (IsUsableExecutable(resolvedConfigured))
- return new CommandResolutionResult(command, resolvedConfigured, CommandResolutionSource.ConfiguredOverride);
- }
- }
-
- foreach (var candidate in BuildWindowsCandidates(command, normalized))
- {
- var resolved = ResolveFromPath(candidate);
- if (!string.IsNullOrWhiteSpace(resolved))
- {
- var source = candidate.EndsWith(".cmd", StringComparison.OrdinalIgnoreCase) ||
- candidate.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) ||
- candidate.EndsWith(".bat", StringComparison.OrdinalIgnoreCase)
- ? CommandResolutionSource.Shim
- : CommandResolutionSource.Path;
- return new CommandResolutionResult(command, resolved!, source);
- }
- }
-
- if (normalized is "npm" or "npx" or "pnpm" or "yarn")
- {
- var nodePath = ResolveFromPath("node.exe") ?? ResolveFromPath("node");
- if (!string.IsNullOrWhiteSpace(nodePath))
- {
- var nodeDir = Path.GetDirectoryName(nodePath);
- if (!string.IsNullOrWhiteSpace(nodeDir))
- {
- var shim = Path.Combine(nodeDir, normalized + ".cmd");
- if (File.Exists(shim))
- return new CommandResolutionResult(command, shim, CommandResolutionSource.NodeAdjacentShim);
- }
- }
- }
-
- var fallback = BuildWindowsCandidates(command, normalized).LastOrDefault() ?? command;
- return new CommandResolutionResult(command, fallback, CommandResolutionSource.Fallback);
- }
-
- public static string Resolve(string command)
- {
- return ResolveWithTrace(command).Resolved;
- }
-
- private static string? ResolveFromPath(string executable)
- {
- var pathValue = Environment.GetEnvironmentVariable("PATH");
- if (string.IsNullOrWhiteSpace(pathValue))
- return null;
-
- foreach (var segment in pathValue.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries))
- {
- try
- {
- var expandedSegment = ExpandWindowsPathTokens(segment.Trim());
- var candidate = Path.Combine(expandedSegment, executable);
- if (File.Exists(candidate))
- {
- // If PATH lookup hit extensionless npm but npm.cmd exists beside it, prefer npm.cmd.
- var fileName = Path.GetFileName(candidate).ToLowerInvariant();
- if (fileName is "npm" or "npx" or "pnpm" or "yarn" or "tauri")
- {
- var shim = candidate + ".cmd";
- if (File.Exists(shim))
- return shim;
- }
- return candidate;
- }
- }
- catch
- {
- // Ignore malformed PATH segments.
- }
- }
-
- return null;
- }
-
- private static string ExpandWindowsPathTokens(string segment)
- {
- if (string.IsNullOrWhiteSpace(segment) || !OperatingSystem.IsWindows())
- return segment;
-
- var expanded = segment;
- for (var i = 0; i < 4; i++)
- {
- var next = Environment.ExpandEnvironmentVariables(expanded);
- if (string.Equals(next, expanded, StringComparison.Ordinal))
- break;
- expanded = next;
- }
- return expanded;
- }
-
- private static List BuildWindowsCandidates(string command, string normalized)
- {
- var candidates = new List();
- if (normalized is "npm" or "npx" or "pnpm" or "yarn" or "tauri")
- {
- candidates.Add(command + ".cmd");
- candidates.Add(command + ".exe");
- candidates.Add(command + ".bat");
- candidates.Add(command);
- }
- else
- {
- candidates.Add(command);
- }
-
- return candidates;
- }
-
- private static bool IsUsableExecutable(string resolved)
- {
- if (string.IsNullOrWhiteSpace(resolved))
- return false;
-
- if (Path.IsPathRooted(resolved))
- return File.Exists(resolved);
-
- return ResolveFromPath(resolved) is not null;
- }
-}
diff --git a/Journal.DevTool/Core/ConfigDoctorAutoFixService.cs b/Journal.DevTool/Core/ConfigDoctorAutoFixService.cs
deleted file mode 100644
index d7bca94..0000000
--- a/Journal.DevTool/Core/ConfigDoctorAutoFixService.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using Sdt.Config;
-
-namespace Sdt.Core;
-
-public sealed record DoctorAutoFixResult(
- bool Success,
- string Message,
- int CreatedDirectories = 0,
- string? BackupPath = null);
-
-public sealed class ConfigDoctorAutoFixService
-{
- public IReadOnlyList FindMissingWorkingDirectories(DevToolConfig config, string projectRoot)
- {
- var missing = new HashSet(StringComparer.OrdinalIgnoreCase);
- foreach (var workflow in config.Workflows)
- {
- foreach (var step in workflow.Steps)
- {
- if (string.IsNullOrWhiteSpace(step.WorkingDir))
- continue;
- var path = Path.GetFullPath(Path.Combine(projectRoot, step.WorkingDir));
- if (!Directory.Exists(path))
- missing.Add(path);
- }
- }
-
- return missing.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).ToList();
- }
-
- public DoctorAutoFixResult CreateMissingWorkingDirectories(IReadOnlyList directories)
- {
- var created = 0;
- try
- {
- foreach (var dir in directories)
- {
- if (Directory.Exists(dir))
- continue;
- Directory.CreateDirectory(dir);
- created++;
- }
-
- return new DoctorAutoFixResult(
- Success: true,
- Message: created == 0 ? "No directories needed creation." : $"Created {created} missing working director{(created == 1 ? "y" : "ies")}.",
- CreatedDirectories: created);
- }
- catch (Exception ex)
- {
- return new DoctorAutoFixResult(false, ex.Message, CreatedDirectories: created);
- }
- }
-
- public DoctorAutoFixResult ApplyLegacyMigration(string projectRoot)
- {
- var configPath = ConfigLoader.FindConfigPath(projectRoot);
- if (string.IsNullOrWhiteSpace(configPath))
- return new DoctorAutoFixResult(false, "Could not find devtool.json for migration.");
-
- var migration = ConfigLoader.ApplyLegacyTargetMigration(configPath, createBackup: true);
- return new DoctorAutoFixResult(
- Success: migration.Success,
- Message: migration.Message,
- BackupPath: migration.BackupPath);
- }
-}
diff --git a/Journal.DevTool/Core/ConfigDoctorService.cs b/Journal.DevTool/Core/ConfigDoctorService.cs
deleted file mode 100644
index 2b6fe91..0000000
--- a/Journal.DevTool/Core/ConfigDoctorService.cs
+++ /dev/null
@@ -1,270 +0,0 @@
-using Sdt.Config;
-
-namespace Sdt.Core;
-
-public enum DoctorStatus
-{
- Pass,
- Warn,
- Fail,
-}
-
-public sealed record DoctorCheck(
- string Name,
- DoctorStatus Status,
- string Detail,
- string? Fix = null);
-
-public sealed record DoctorReport(
- IReadOnlyList Checks)
-{
- public bool HasFailures => Checks.Any(c => c.Status == DoctorStatus.Fail);
- public bool HasWarnings => Checks.Any(c => c.Status == DoctorStatus.Warn);
-}
-
-public sealed class ConfigDoctorService(
- IToolProbe? toolProbe = null,
- IRequirementResolver? requirementResolver = null)
-{
- private readonly IToolProbe _toolProbe = toolProbe ?? new ToolProbeService();
- private readonly IRequirementResolver _requirementResolver = requirementResolver ?? new RequirementResolver();
-
- public async Task RunAsync(
- DevToolConfig config,
- string projectRoot,
- CancellationToken cancellationToken = default)
- {
- var checks = new List();
- var workflowMap = config.Workflows.ToDictionary(w => w.Id, StringComparer.OrdinalIgnoreCase);
-
- AddSchemaChecks(config, checks);
- AddWorkflowChecks(config.Workflows, workflowMap, projectRoot, checks);
- AddPathChecks(config, projectRoot, checks);
- await AddToolProbeChecksAsync(config, projectRoot, checks, cancellationToken).ConfigureAwait(false);
-
- return new DoctorReport(checks);
- }
-
- private static void AddSchemaChecks(DevToolConfig config, List checks)
- {
- if (config.Workflows.Count == 0 && config.Targets.Count == 0)
- {
- checks.Add(new DoctorCheck(
- "Config schema",
- DoctorStatus.Fail,
- "No workflows or legacy targets found.",
- "Add workflows or run SDT init/bootstrap."));
- return;
- }
-
- if (config.Workflows.Count == 0 && config.Targets.Count > 0)
- {
- checks.Add(new DoctorCheck(
- "Legacy schema",
- DoctorStatus.Fail,
- "Targets-only config detected (strict mode will block execution).",
- "Use SYSTEM -> Migrate legacy targets -> workflows."));
- return;
- }
-
- if (config.Targets.Count > 0)
- {
- checks.Add(new DoctorCheck(
- "Legacy schema",
- DoctorStatus.Warn,
- "Both workflows and legacy targets are present.",
- "Prefer workflows-only config and remove legacy targets once migrated."));
- }
- else
- {
- checks.Add(new DoctorCheck("Config schema", DoctorStatus.Pass, "Workflow-first config detected."));
- }
- }
-
- private static void AddWorkflowChecks(
- IReadOnlyList workflows,
- IReadOnlyDictionary workflowMap,
- string projectRoot,
- List checks)
- {
- var duplicateIds = workflows
- .GroupBy(w => w.Id, StringComparer.OrdinalIgnoreCase)
- .Where(g => g.Count() > 1)
- .Select(g => g.Key)
- .ToList();
-
- if (duplicateIds.Count > 0)
- {
- checks.Add(new DoctorCheck(
- "Workflow IDs",
- DoctorStatus.Fail,
- $"Duplicate workflow IDs: {string.Join(", ", duplicateIds)}",
- "Ensure each workflow has a unique id."));
- }
- else
- {
- checks.Add(new DoctorCheck("Workflow IDs", DoctorStatus.Pass, "No duplicate workflow IDs."));
- }
-
- var brokenDeps = new List();
- foreach (var workflow in workflows)
- {
- foreach (var dep in workflow.DependsOn)
- {
- if (!workflowMap.ContainsKey(dep))
- brokenDeps.Add($"{workflow.Id} -> {dep}");
- }
- }
-
- if (brokenDeps.Count > 0)
- {
- checks.Add(new DoctorCheck(
- "Workflow dependencies",
- DoctorStatus.Fail,
- $"Missing dependencies: {string.Join("; ", brokenDeps)}",
- "Fix dependsOn IDs to reference existing workflows."));
- }
- else
- {
- checks.Add(new DoctorCheck("Workflow dependencies", DoctorStatus.Pass, "All workflow dependencies are valid."));
- }
-
- var invalidSteps = new List();
- var missingWorkingDirs = new List();
- foreach (var workflow in workflows)
- {
- foreach (var step in workflow.Steps)
- {
- if (string.IsNullOrWhiteSpace(step.Command) && string.IsNullOrWhiteSpace(step.Action))
- invalidSteps.Add($"{workflow.Id}/{step.Id}");
-
- var stepDir = Path.GetFullPath(Path.Combine(projectRoot, step.WorkingDir));
- if (!Directory.Exists(stepDir))
- missingWorkingDirs.Add($"{workflow.Id}/{step.Id} -> {step.WorkingDir}");
- }
- }
-
- if (invalidSteps.Count > 0)
- {
- checks.Add(new DoctorCheck(
- "Step definitions",
- DoctorStatus.Fail,
- $"Steps missing command/action: {string.Join(", ", invalidSteps)}",
- "Each step must define either action or command."));
- }
- else
- {
- checks.Add(new DoctorCheck("Step definitions", DoctorStatus.Pass, "All steps define an action or command."));
- }
-
- if (missingWorkingDirs.Count > 0)
- {
- checks.Add(new DoctorCheck(
- "Working directories",
- DoctorStatus.Warn,
- $"Missing directories: {string.Join("; ", missingWorkingDirs)}",
- "Create missing directories or fix step workingDir values."));
- }
- else
- {
- checks.Add(new DoctorCheck("Working directories", DoctorStatus.Pass, "All referenced working directories exist."));
- }
- }
-
- private static void AddPathChecks(DevToolConfig config, string projectRoot, List checks)
- {
- var configPath = Path.Combine(projectRoot, "devtool.json");
- checks.Add(File.Exists(configPath)
- ? new DoctorCheck("Project root", DoctorStatus.Pass, $"Config found at {configPath}")
- : new DoctorCheck("Project root", DoctorStatus.Fail, $"devtool.json not found at {configPath}", "Run SDT init/bootstrap."));
-
- if (OperatingSystem.IsWindows())
- {
- var pathValue = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
- var unresolvedSegments = pathValue
- .Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries)
- .Where(s => s.Contains('%') && Environment.ExpandEnvironmentVariables(s) == s)
- .Take(4)
- .ToList();
-
- if (unresolvedSegments.Count > 0)
- {
- checks.Add(new DoctorCheck(
- "PATH expansion",
- DoctorStatus.Warn,
- $"Unresolved PATH tokens: {string.Join(" | ", unresolvedSegments)}",
- "Set referenced env vars or remove invalid PATH segments."));
- }
- else
- {
- checks.Add(new DoctorCheck("PATH expansion", DoctorStatus.Pass, "No unresolved PATH token segments detected."));
- }
- }
-
- if (config.Project?.RootHints.Count > 0)
- {
- checks.Add(new DoctorCheck("Root hints", DoctorStatus.Pass, $"Configured root hints: {string.Join(", ", config.Project.RootHints)}"));
- }
- else
- {
- checks.Add(new DoctorCheck(
- "Root hints",
- DoctorStatus.Warn,
- "No project.rootHints configured.",
- "Add rootHints markers (for example .git, *.sln, package.json)."));
- }
- }
-
- private async Task AddToolProbeChecksAsync(
- DevToolConfig config,
- string projectRoot,
- List checks,
- CancellationToken cancellationToken)
- {
- var requiredTools = new HashSet(StringComparer.OrdinalIgnoreCase);
- foreach (var workflow in config.Workflows)
- {
- foreach (var step in workflow.Steps)
- {
- foreach (var req in _requirementResolver.Resolve(step))
- requiredTools.Add(req.Tool);
- }
- }
-
- foreach (var profile in config.Debug?.Profiles ?? [])
- {
- foreach (var req in profile.Requires)
- requiredTools.Add(req.Tool);
- }
-
- foreach (var toolDef in config.Tooling?.Tools ?? [])
- requiredTools.Add(toolDef.Tool);
-
- if (requiredTools.Count == 0)
- {
- checks.Add(new DoctorCheck("Tool probes", DoctorStatus.Warn, "No tools discovered from workflows/debug/tooling."));
- return;
- }
-
- foreach (var tool in requiredTools.OrderBy(t => t, StringComparer.OrdinalIgnoreCase))
- {
- var probe = await _toolProbe.ProbeAsync(tool, projectRoot, config, cancellationToken).ConfigureAwait(false);
- if (probe.IsAvailable)
- {
- checks.Add(new DoctorCheck(
- $"Tool: {tool}",
- DoctorStatus.Pass,
- string.IsNullOrWhiteSpace(probe.Version) ? "available" : probe.Version!,
- probe.Details));
- }
- else
- {
- checks.Add(new DoctorCheck(
- $"Tool: {tool}",
- DoctorStatus.Fail,
- string.IsNullOrWhiteSpace(probe.Details) ? "not available" : probe.Details!,
- $"Install/configure {tool} or set tooling.tools[].executables for non-standard paths."));
- }
- }
- }
-}
diff --git a/Journal.DevTool/Core/Contracts.cs b/Journal.DevTool/Core/Contracts.cs
deleted file mode 100644
index eb19cd0..0000000
--- a/Journal.DevTool/Core/Contracts.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-using Sdt.Config;
-using Sdt.Runner;
-
-namespace Sdt.Core;
-
-public sealed record ProbeResult(
- string Tool,
- bool IsAvailable,
- string? Version = null,
- string? Details = null);
-
-public sealed record InstallCommand(
- string Command,
- IReadOnlyList Args);
-
-public sealed record InstallPlan(
- string Tool,
- bool Supported,
- string Summary,
- IReadOnlyList Commands);
-
-public sealed record WorkflowStepResult(
- string WorkflowId,
- string StepId,
- string StepLabel,
- RunResult Result);
-
-public enum ExecutionStopReason
-{
- MissingPrereq,
- InstallFailed,
- CommandFailed,
- ValidationFailed,
- UserDeclined,
-}
-
-public sealed record WorkflowExecutionResult(
- bool Success,
- ExecutionStopReason? StopReason,
- string Message,
- IReadOnlyList Steps);
-
-public interface IToolProbe
-{
- Task ProbeAsync(
- string tool,
- string projectRoot,
- DevToolConfig? config = null,
- CancellationToken cancellationToken = default);
-}
-
-public interface IPrereqInstaller
-{
- Task GetInstallPlanAsync(
- string tool,
- string projectRoot,
- DevToolConfig? config = null,
- CancellationToken cancellationToken = default);
-
- Task RunInstallAsync(
- InstallCommand command,
- string projectRoot,
- Action onOutput,
- CancellationToken cancellationToken = default);
-}
-
-public interface IActionRunner
-{
- Task RunStepAsync(
- WorkflowStep step,
- string projectRoot,
- Action onOutput,
- CancellationToken cancellationToken = default);
-}
-
-public interface IWorkflowPlanner
-{
- List ResolvePlan(
- WorkflowDefinition workflow,
- IReadOnlyDictionary allWorkflows);
-}
-
-public interface IRequirementResolver
-{
- List Resolve(WorkflowStep step);
- List Resolve(BuildTarget target);
-}
diff --git a/Journal.DevTool/Core/Debug/DebugContracts.cs b/Journal.DevTool/Core/Debug/DebugContracts.cs
deleted file mode 100644
index c4c57fa..0000000
--- a/Journal.DevTool/Core/Debug/DebugContracts.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using Sdt.Config;
-using Sdt.Runner;
-
-namespace Sdt.Core.Debug;
-
-public sealed record DebugRunResult(
- bool Success,
- ExecutionStopReason? StopReason,
- string Message,
- DebugProfileDefinition Profile,
- RunResult? RunResult,
- IReadOnlyList OutputLines,
- IReadOnlyList Probes);
-
-public sealed record DiagnosticsBundleResult(
- bool Success,
- string BundleDirectory,
- string? ZipPath,
- string Message);
-
-public sealed record DiagnosticsBundleRequest(
- string Category,
- string ProjectRoot,
- string SummaryMessage,
- IReadOnlyList OutputLines,
- IReadOnlyList WorkflowSteps,
- IReadOnlyList Probes,
- DebugDiagnosticsOptions DiagnosticsOptions,
- DevToolConfig Config,
- ExecutionStopReason? StopReason = null,
- RunResult? DebugRun = null,
- DebugProfileDefinition? DebugProfile = null);
-
-public interface IDebugProfileRunner
-{
- Task RunAsync(
- DebugProfileDefinition profile,
- DevToolConfig config,
- string projectRoot,
- bool verbose,
- Func> confirmInstallAsync,
- Action onOutput,
- Action? onEvent = null,
- CancellationToken cancellationToken = default);
-}
-
-public interface IDiagnosticsBundleService
-{
- Task WriteBundleAsync(
- DiagnosticsBundleRequest request,
- CancellationToken cancellationToken = default);
-}
diff --git a/Journal.DevTool/Core/Debug/DebugProfileRunner.cs b/Journal.DevTool/Core/Debug/DebugProfileRunner.cs
deleted file mode 100644
index 06e3b0c..0000000
--- a/Journal.DevTool/Core/Debug/DebugProfileRunner.cs
+++ /dev/null
@@ -1,185 +0,0 @@
-using Sdt.Config;
-using Sdt.Runner;
-
-namespace Sdt.Core.Debug;
-
-public sealed class DebugProfileRunner(
- IToolProbe toolProbe,
- IPrereqInstaller installer) : IDebugProfileRunner
-{
- private readonly IToolProbe _toolProbe = toolProbe;
- private readonly IPrereqInstaller _installer = installer;
-
- public async Task RunAsync(
- DebugProfileDefinition profile,
- DevToolConfig config,
- string projectRoot,
- bool verbose,
- Func> confirmInstallAsync,
- Action onOutput,
- Action? onEvent = null,
- CancellationToken cancellationToken = default)
- {
- var probes = new List();
- var output = new List();
- onEvent?.Invoke(new RunEvent(
- Category: "debug",
- Type: RunEventType.DebugStarted,
- Message: $"Debug profile '{profile.Id}' started."));
- var requires = profile.Requires.Count > 0
- ? profile.Requires
- : InferRequirements(profile);
-
- foreach (var req in requires)
- {
- var probe = await _toolProbe.ProbeAsync(req.Tool, projectRoot, config, cancellationToken).ConfigureAwait(false);
- probes.Add(probe);
- if (probe.IsAvailable)
- continue;
-
- if (!string.IsNullOrWhiteSpace(probe.Details))
- {
- var line = $"Probe detail [{req.Tool}]: {probe.Details}";
- output.Add("OUT: " + line);
- if (verbose)
- onOutput(line, false);
- }
-
- if (req.InstallPolicy == InstallPolicy.Never)
- {
- onEvent?.Invoke(new RunEvent(
- Category: "debug",
- Type: RunEventType.DebugCompleted,
- Message: $"Missing prerequisite '{req.Tool}'.",
- Tool: req.Tool,
- Success: false));
- return new DebugRunResult(
- Success: false,
- StopReason: ExecutionStopReason.MissingPrereq,
- Message: $"Missing prerequisite '{req.Tool}' for debug profile '{profile.Label}'.",
- Profile: profile,
- RunResult: null,
- OutputLines: output,
- Probes: probes);
- }
-
- var installPlan = await _installer.GetInstallPlanAsync(req.Tool, projectRoot, config, cancellationToken).ConfigureAwait(false);
- if (!installPlan.Supported || installPlan.Commands.Count == 0)
- {
- onEvent?.Invoke(new RunEvent(
- Category: "debug",
- Type: RunEventType.DebugCompleted,
- Message: $"No installer plan available for '{req.Tool}'.",
- Tool: req.Tool,
- Success: false));
- return new DebugRunResult(
- Success: false,
- StopReason: ExecutionStopReason.MissingPrereq,
- Message: $"Missing prerequisite '{req.Tool}' and no installer plan is available.",
- Profile: profile,
- RunResult: null,
- OutputLines: output,
- Probes: probes);
- }
-
- var approved = req.InstallPolicy == InstallPolicy.Auto
- ? true
- : await confirmInstallAsync(req.Tool, installPlan).ConfigureAwait(false);
- if (!approved)
- {
- onEvent?.Invoke(new RunEvent(
- Category: "debug",
- Type: RunEventType.InstallDeclined,
- Message: $"Install declined for '{req.Tool}'.",
- Tool: req.Tool,
- Success: false));
- return new DebugRunResult(
- Success: false,
- StopReason: ExecutionStopReason.UserDeclined,
- Message: $"Install declined for missing prerequisite '{req.Tool}'.",
- Profile: profile,
- RunResult: null,
- OutputLines: output,
- Probes: probes);
- }
-
- foreach (var cmd in installPlan.Commands)
- {
- var installResult = await _installer.RunInstallAsync(cmd, projectRoot, onOutput, cancellationToken).ConfigureAwait(false);
- if (!installResult.Success)
- {
- onEvent?.Invoke(new RunEvent(
- Category: "debug",
- Type: RunEventType.DebugCompleted,
- Message: $"Install failed for '{req.Tool}'.",
- Tool: req.Tool,
- Success: false,
- ExitCode: installResult.ExitCode));
- return new DebugRunResult(
- Success: false,
- StopReason: ExecutionStopReason.InstallFailed,
- Message: $"Failed to install prerequisite '{req.Tool}'.",
- Profile: profile,
- RunResult: installResult,
- OutputLines: output,
- Probes: probes);
- }
- }
- }
-
- var cwd = Path.GetFullPath(Path.Combine(projectRoot, profile.WorkingDir));
- var mergedEnv = profile.Env.Count > 0 ? profile.Env : null;
- onEvent?.Invoke(new RunEvent(
- Category: "debug",
- Type: RunEventType.DebugCommandStarted,
- Message: $"{profile.Command} {string.Join(" ", profile.Args)}"));
- var run = await ProcessRunner.RunAsync(
- profile.Command,
- profile.Args,
- cwd,
- (line, isErr) =>
- {
- output.Add((isErr ? "ERR: " : "OUT: ") + line);
- if (verbose)
- onOutput(line, isErr);
- },
- mergedEnv,
- cancellationToken).ConfigureAwait(false);
- onEvent?.Invoke(new RunEvent(
- Category: "debug",
- Type: RunEventType.DebugCommandCompleted,
- Message: $"Debug command exited {run.ExitCode}.",
- Success: run.Success,
- ExitCode: run.ExitCode));
- onEvent?.Invoke(new RunEvent(
- Category: "debug",
- Type: RunEventType.DebugCompleted,
- Message: run.Success ? "Debug run completed." : "Debug run failed.",
- Success: run.Success,
- ExitCode: run.ExitCode));
-
- return new DebugRunResult(
- Success: run.Success,
- StopReason: run.Success ? null : ExecutionStopReason.CommandFailed,
- Message: run.Success
- ? $"Debug profile '{profile.Label}' completed."
- : $"Debug profile '{profile.Label}' exited with code {run.ExitCode}.",
- Profile: profile,
- RunResult: run,
- OutputLines: output,
- Probes: probes);
- }
-
- private static List InferRequirements(DebugProfileDefinition profile)
- {
- return profile.Type.ToLowerInvariant() switch
- {
- "dotnet" => [new ToolRequirement { Tool = "dotnet" }],
- "node" => [new ToolRequirement { Tool = "node" }, new ToolRequirement { Tool = "npm" }],
- "python" => [new ToolRequirement { Tool = "python" }],
- _ => string.IsNullOrWhiteSpace(profile.Command)
- ? []
- : [new ToolRequirement { Tool = profile.Command }],
- };
- }
-}
diff --git a/Journal.DevTool/Core/Debug/DiagnosticsBundleService.cs b/Journal.DevTool/Core/Debug/DiagnosticsBundleService.cs
deleted file mode 100644
index 0056912..0000000
--- a/Journal.DevTool/Core/Debug/DiagnosticsBundleService.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-using System.Security.Cryptography;
-using System.Text;
-using System.Text.Json;
-using Sdt.Config;
-
-namespace Sdt.Core.Debug;
-
-public sealed class DiagnosticsBundleService : IDiagnosticsBundleService
-{
- private static readonly JsonSerializerOptions JsonOptions = new()
- {
- WriteIndented = true
- };
-
- public async Task WriteBundleAsync(
- DiagnosticsBundleRequest request,
- CancellationToken cancellationToken = default)
- {
- try
- {
- var timestamp = DateTimeOffset.Now.ToString("yyyyMMdd-HHmmss");
- var root = Path.GetFullPath(Path.Combine(request.ProjectRoot, request.DiagnosticsOptions.OutputDir));
- var bundleDir = Path.Combine(root, $"{request.Category}-{timestamp}");
- Directory.CreateDirectory(bundleDir);
-
- var stepsPath = Path.Combine(bundleDir, "steps.json");
- var toolsPath = Path.Combine(bundleDir, "tools.json");
- var envPath = Path.Combine(bundleDir, "env.json");
- var outputPath = Path.Combine(bundleDir, "output.log");
- var summaryPath = Path.Combine(bundleDir, "summary.json");
-
- await File.WriteAllTextAsync(stepsPath, JsonSerializer.Serialize(request.WorkflowSteps, JsonOptions), cancellationToken);
- await File.WriteAllTextAsync(toolsPath, JsonSerializer.Serialize(request.Probes, JsonOptions), cancellationToken);
- await File.WriteAllTextAsync(envPath, JsonSerializer.Serialize(CaptureEnvironment(request.DiagnosticsOptions), JsonOptions), cancellationToken);
- await File.WriteAllLinesAsync(outputPath, request.OutputLines, cancellationToken);
-
- var summary = new
- {
- category = request.Category,
- stopReason = request.StopReason?.ToString(),
- message = request.SummaryMessage,
- createdAt = DateTimeOffset.Now,
- configHash = HashConfig(request.Config),
- debugProfile = request.DebugProfile?.Id,
- debugExitCode = request.DebugRun?.ExitCode,
- envCapture = BuildEnvCaptureSummary(request.DiagnosticsOptions),
- };
- await File.WriteAllTextAsync(summaryPath, JsonSerializer.Serialize(summary, JsonOptions), cancellationToken);
-
- return new DiagnosticsBundleResult(
- Success: true,
- BundleDirectory: bundleDir,
- ZipPath: null,
- Message: "Diagnostics bundle generated.");
- }
- catch (Exception ex)
- {
- return new DiagnosticsBundleResult(
- Success: false,
- BundleDirectory: string.Empty,
- ZipPath: null,
- Message: ex.Message);
- }
- }
-
- private static Dictionary CaptureEnvironment(DebugDiagnosticsOptions options)
- {
- if (options.IncludeAllEnv)
- {
- return Environment.GetEnvironmentVariables()
- .Cast()
- .ToDictionary(e => e.Key?.ToString() ?? "", e => e.Value?.ToString() ?? "", StringComparer.OrdinalIgnoreCase);
- }
-
- if (options.CaptureEnvKeys.Count == 0)
- return new Dictionary(StringComparer.OrdinalIgnoreCase);
-
- var captured = new Dictionary(StringComparer.OrdinalIgnoreCase);
- foreach (var key in options.CaptureEnvKeys)
- captured[key] = Environment.GetEnvironmentVariable(key) ?? "";
- return captured;
- }
-
- private static string BuildEnvCaptureSummary(DebugDiagnosticsOptions options)
- {
- if (options.IncludeAllEnv)
- return "full";
- if (options.CaptureEnvKeys.Count == 0)
- return "allowlist-empty (intentional minimal capture)";
- return $"allowlist ({options.CaptureEnvKeys.Count} keys)";
- }
-
- private static string HashConfig(object config)
- {
- var json = JsonSerializer.Serialize(config);
- var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(json));
- return Convert.ToHexString(bytes);
- }
-}
diff --git a/Journal.DevTool/Core/LegacyScriptRequirementResolver.cs b/Journal.DevTool/Core/LegacyScriptRequirementResolver.cs
deleted file mode 100644
index 39057de..0000000
--- a/Journal.DevTool/Core/LegacyScriptRequirementResolver.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using Sdt.Config;
-
-namespace Sdt.Core;
-
-internal static class LegacyScriptRequirementResolver
-{
- public static List InferForPowerShellArgs(IReadOnlyList args)
- {
- var script = FindScriptArg(args);
- if (string.IsNullOrWhiteSpace(script))
- return [];
-
- static ToolRequirement Req(string tool) => new() { Tool = tool, InstallPolicy = InstallPolicy.Prompt };
-
- var file = Path.GetFileName(script).ToLowerInvariant();
- var lowerArgs = args.Select(a => a.ToLowerInvariant()).ToList();
-
- return file switch
- {
- "publish-app.ps1" => IsTauriTarget(lowerArgs)
- ? [Req("python"), Req("node"), Req("npm"), Req("cargo")]
- : [Req("python"), Req("node"), Req("npm")],
- "publish-sidecar.ps1" => [Req("python"), Req("dotnet")],
- "publish-webgateway.ps1" => [Req("python"), Req("dotnet"), Req("node"), Req("npm")],
- "run-webgateway.ps1" => [Req("python"), Req("dotnet")],
- "migration-gate.ps1" => [Req("python"), Req("dotnet")],
- "nuget-export-cache.ps1" => [Req("python"), Req("dotnet")],
- "nuget-import-cache.ps1" => [Req("python"), Req("dotnet")],
- "npm-clean.ps1" => [Req("python"), Req("node"), Req("npm")],
- "publish-output.ps1" => [Req("python"), Req("dotnet"), Req("node"), Req("npm"), Req("cargo")],
- "sync-output.ps1" => [Req("python")],
- "dotnet-min.ps1" => [Req("python"), Req("dotnet")],
- "pip-min.ps1" => [Req("python")],
- _ => [Req("python")]
- };
- }
-
- private static string? FindScriptArg(IReadOnlyList args)
- {
- for (var i = 0; i < args.Count - 1; i++)
- {
- if (string.Equals(args[i], "-File", StringComparison.OrdinalIgnoreCase))
- return args[i + 1];
- }
-
- return args.FirstOrDefault(a => a.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase));
- }
-
- private static bool IsTauriTarget(IReadOnlyList lowerArgs)
- {
- for (var i = 0; i < lowerArgs.Count - 1; i++)
- {
- if (lowerArgs[i] is "-target" or "--target" && lowerArgs[i + 1] == "tauri")
- return true;
- }
-
- return false;
- }
-}
diff --git a/Journal.DevTool/Core/PrereqInstallerService.cs b/Journal.DevTool/Core/PrereqInstallerService.cs
deleted file mode 100644
index 8f87f0f..0000000
--- a/Journal.DevTool/Core/PrereqInstallerService.cs
+++ /dev/null
@@ -1,303 +0,0 @@
-using System.Diagnostics;
-using System.Text.Json;
-using System.Text.RegularExpressions;
-using Sdt.Config;
-using Sdt.Runner;
-
-namespace Sdt.Core;
-
-public sealed class PrereqInstallerService : IPrereqInstaller
-{
- public async Task GetInstallPlanAsync(
- string tool,
- string projectRoot,
- DevToolConfig? config = null,
- CancellationToken cancellationToken = default)
- {
- var fromConfig = TryGetPlanFromConfig(tool, config);
- if (fromConfig is not null)
- return fromConfig;
-
- var scriptPath = ScriptLocator.FindHelperScript(projectRoot, "diag.py");
- if (scriptPath is null)
- return FallbackPlan(tool);
-
- try
- {
- var psi = new ProcessStartInfo
- {
- FileName = PythonResolver.ResolveExecutable(),
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- UseShellExecute = false,
- CreateNoWindow = true,
- WorkingDirectory = projectRoot,
- };
- psi.ArgumentList.Add(scriptPath);
- psi.ArgumentList.Add("install-plan");
- psi.ArgumentList.Add("--tool");
- psi.ArgumentList.Add(tool);
- psi.ArgumentList.Add("--json");
-
- using var process = new Process { StartInfo = psi };
- process.Start();
- var stdout = await process.StandardOutput.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
- var stderr = await process.StandardError.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
- await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false);
-
- if (process.ExitCode != 0)
- {
- var fallback = FallbackPlan(tool);
- return fallback with
- {
- Summary = $"diag.py install-plan failed for {tool}; using fallback templates. " +
- $"{(string.IsNullOrWhiteSpace(stderr) ? "No stderr output." : stderr.Trim())}"
- };
- }
-
- var parsed = JsonSerializer.Deserialize(stdout);
- if (parsed is null)
- {
- var fallback = FallbackPlan(tool);
- return fallback with { Summary = $"diag.py returned invalid JSON for {tool}; using fallback templates." };
- }
-
- var commands = parsed.Commands
- .Select(c => new InstallCommand(c.Command ?? "", c.Args ?? []))
- .Where(c => !string.IsNullOrWhiteSpace(c.Command))
- .ToList();
- if (!parsed.Supported || commands.Count == 0)
- {
- var fallback = FallbackPlan(tool);
- return fallback with { Summary = $"diag.py returned no usable commands for {tool}; using fallback templates." };
- }
-
- return new InstallPlan(
- parsed.Tool ?? tool,
- parsed.Supported,
- parsed.Summary ?? $"Install {tool}",
- commands);
- }
- catch (Exception ex)
- {
- var fallback = FallbackPlan(tool);
- return fallback with { Summary = $"diag.py install-plan exception for {tool}; using fallback templates. {ex.Message}" };
- }
- }
-
- public Task RunInstallAsync(
- InstallCommand command,
- string projectRoot,
- Action onOutput,
- CancellationToken cancellationToken = default)
- => ProcessRunner.RunAsync(command.Command, command.Args, projectRoot, onOutput, cancellationToken: cancellationToken);
-
- private static InstallPlan FallbackPlan(string tool)
- {
- var isWindows = OperatingSystem.IsWindows();
- var normalized = tool.ToLowerInvariant();
- if (normalized == "tauri")
- return BuildTauriFallbackPlan();
-
- var installCommand = normalized switch
- {
- "dotnet" => isWindows
- ? new InstallCommand("winget", ["install", "Microsoft.DotNet.SDK.10"])
- : new InstallCommand("sh", ["-c", "echo Install dotnet SDK from your distro package manager"]),
- "node" => isWindows
- ? new InstallCommand("winget", ["install", "OpenJS.NodeJS.LTS"])
- : new InstallCommand("sh", ["-c", "echo Install nodejs via package manager"]),
- "npm" => isWindows
- ? new InstallCommand("winget", ["install", "OpenJS.NodeJS.LTS"])
- : new InstallCommand("sh", ["-c", "echo Install npm via package manager"]),
- "cargo" => isWindows
- ? new InstallCommand("winget", ["install", "Rustlang.Rustup"])
- : new InstallCommand("sh", ["-c", "curl https://sh.rustup.rs -sSf | sh"]),
- "git" => isWindows
- ? new InstallCommand("winget", ["install", "Git.Git"])
- : new InstallCommand("sh", ["-c", "echo Install git via package manager"]),
- "docker" => isWindows
- ? new InstallCommand("winget", ["install", "Docker.DockerDesktop"])
- : new InstallCommand("sh", ["-c", "echo Install docker engine via package manager"]),
- "python" => isWindows
- ? new InstallCommand("winget", ["install", "Python.Python.3.12"])
- : new InstallCommand("sh", ["-c", "echo Install python3 via package manager"]),
- _ => new InstallCommand("sh", ["-c", $"echo No installer template for '{tool}'"]),
- };
-
- return new InstallPlan(
- tool,
- Supported: true,
- Summary: $"Fallback install plan for {tool}",
- Commands: [installCommand]);
- }
-
- private static InstallPlan BuildTauriFallbackPlan()
- {
- if (OperatingSystem.IsWindows())
- {
- return new InstallPlan(
- "tauri",
- Supported: true,
- Summary: "Fallback tauri plan (Windows): install Node.js, Rust toolchain, and Tauri CLI. Visual Studio C++ build tools/WebView2 may also be required.",
- Commands:
- [
- new InstallCommand("winget", ["install", "OpenJS.NodeJS.LTS"]),
- new InstallCommand("winget", ["install", "Rustlang.Rustup"]),
- new InstallCommand("npm", ["install", "-g", "@tauri-apps/cli"]),
- ]);
- }
-
- if (OperatingSystem.IsMacOS())
- {
- return new InstallPlan(
- "tauri",
- Supported: true,
- Summary: "Fallback tauri plan (macOS): install Xcode command line tools, Rust toolchain, and Tauri CLI.",
- Commands:
- [
- new InstallCommand("sh", ["-c", "xcode-select --install || true"]),
- new InstallCommand("sh", ["-c", "curl https://sh.rustup.rs -sSf | sh -s -- -y"]),
- new InstallCommand("npm", ["install", "-g", "@tauri-apps/cli"]),
- ]);
- }
-
- var linuxPlan = BuildLinuxTauriPrereqCommand();
- return new InstallPlan(
- "tauri",
- Supported: true,
- Summary: $"Fallback tauri plan (Linux): detected package manager `{linuxPlan.PackageManager}` for system deps, then install Rust toolchain and Tauri CLI.",
- Commands:
- [
- new InstallCommand("sh", ["-c", linuxPlan.Command]),
- new InstallCommand("sh", ["-c", "curl https://sh.rustup.rs -sSf | sh -s -- -y"]),
- new InstallCommand("npm", ["install", "-g", "@tauri-apps/cli"]),
- ]);
- }
-
- private static (string PackageManager, string Command) BuildLinuxTauriPrereqCommand()
- {
- if (CommandExists("apt-get"))
- {
- return ("apt-get",
- "sudo apt-get update && sudo apt-get install -y build-essential libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev");
- }
-
- if (CommandExists("dnf"))
- {
- return ("dnf",
- "sudo dnf install -y gcc gcc-c++ make webkit2gtk4.1-devel gtk3-devel libappindicator-gtk3 librsvg2-devel");
- }
-
- if (CommandExists("pacman"))
- {
- return ("pacman",
- "sudo pacman -S --needed base-devel webkit2gtk gtk3 libappindicator-gtk3 librsvg");
- }
-
- if (CommandExists("zypper"))
- {
- return ("zypper",
- "sudo zypper install -y gcc gcc-c++ make webkit2gtk3-devel gtk3-devel libappindicator3-devel librsvg-devel");
- }
-
- if (CommandExists("apk"))
- {
- return ("apk",
- "sudo apk add build-base webkit2gtk-dev gtk+3.0-dev libayatana-appindicator-dev librsvg-dev");
- }
-
- return ("unknown",
- "echo Install tauri system dependencies using your distro package manager, then rerun SDT.");
- }
-
- private static bool CommandExists(string command)
- {
- try
- {
- var psi = new ProcessStartInfo
- {
- FileName = OperatingSystem.IsWindows() ? "where" : "which",
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- UseShellExecute = false,
- CreateNoWindow = true,
- };
- psi.ArgumentList.Add(command);
- using var process = Process.Start(psi);
- if (process is null)
- return false;
- process.WaitForExit(1500);
- return process.ExitCode == 0;
- }
- catch
- {
- return false;
- }
- }
-
- private static InstallPlan? TryGetPlanFromConfig(string tool, DevToolConfig? config)
- {
- var preferred = config?.Tooling?.Tools
- .FirstOrDefault(t => string.Equals(t.Tool, tool, StringComparison.OrdinalIgnoreCase))
- ?.PreferredInstallCommands;
-
- if (preferred is null || preferred.Count == 0)
- return null;
-
- var commands = new List();
- foreach (var line in preferred)
- {
- var parts = SplitShellLike(line);
- if (parts.Count == 0)
- continue;
-
- commands.Add(new InstallCommand(parts[0], parts.Skip(1).ToList()));
- }
-
- if (commands.Count == 0)
- return null;
-
- return new InstallPlan(
- tool,
- Supported: true,
- Summary: $"Configured install commands for {tool}",
- Commands: commands);
- }
-
- private static List SplitShellLike(string input)
- {
- if (string.IsNullOrWhiteSpace(input))
- return [];
-
- var tokens = new List();
- var matches = Regex.Matches(input, "\"([^\"]*)\"|'([^']*)'|\\S+");
- foreach (Match match in matches)
- {
- var value = match.Value.Trim();
- if (value.Length >= 2 && (
- (value.StartsWith("\"", StringComparison.Ordinal) && value.EndsWith("\"", StringComparison.Ordinal)) ||
- (value.StartsWith("'", StringComparison.Ordinal) && value.EndsWith("'", StringComparison.Ordinal))))
- {
- value = value[1..^1];
- }
- if (!string.IsNullOrWhiteSpace(value))
- tokens.Add(value);
- }
- return tokens;
- }
-
- private sealed class InstallPlanJson
- {
- public string? Tool { get; init; }
- public bool Supported { get; init; }
- public string? Summary { get; init; }
- public List Commands { get; init; } = [];
- }
-
- private sealed class InstallCommandJson
- {
- public string? Command { get; init; }
- public List? Args { get; init; }
- }
-}
diff --git a/Journal.DevTool/Core/PythonResolver.cs b/Journal.DevTool/Core/PythonResolver.cs
deleted file mode 100644
index 928c79a..0000000
--- a/Journal.DevTool/Core/PythonResolver.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using System.Diagnostics;
-
-namespace Sdt.Core;
-
-internal static class PythonResolver
-{
- public static string ResolveExecutable()
- {
- var candidates = OperatingSystem.IsWindows()
- ? new[] { "python", "py" }
- : new[] { "python3", "python" };
-
- foreach (var candidate in candidates)
- {
- if (CanRun(candidate))
- return candidate;
- }
-
- return "python";
- }
-
- private static bool CanRun(string exe)
- {
- try
- {
- var psi = new ProcessStartInfo
- {
- FileName = exe,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- UseShellExecute = false,
- CreateNoWindow = true,
- };
- psi.ArgumentList.Add("--version");
-
- using var p = new Process { StartInfo = psi };
- p.Start();
- p.WaitForExit(2000);
- return p.ExitCode == 0;
- }
- catch
- {
- return false;
- }
- }
-}
diff --git a/Journal.DevTool/Core/RequirementResolver.cs b/Journal.DevTool/Core/RequirementResolver.cs
deleted file mode 100644
index 169d070..0000000
--- a/Journal.DevTool/Core/RequirementResolver.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using Sdt.Config;
-
-namespace Sdt.Core;
-
-public sealed class RequirementResolver : IRequirementResolver
-{
- public List Resolve(WorkflowStep step)
- {
- if (step.Requires.Count > 0)
- return step.Requires.ToList();
-
- if (!string.IsNullOrWhiteSpace(step.Action))
- return InferActionRequirements(step.Action);
-
- if (string.IsNullOrWhiteSpace(step.Command))
- return [];
-
- return InferCommandRequirements(step.Command, step.Args);
- }
-
- public List Resolve(BuildTarget target)
- {
- if (string.IsNullOrWhiteSpace(target.Command))
- return [];
-
- return InferCommandRequirements(target.Command, target.Args);
- }
-
- private static List InferActionRequirements(string action)
- {
- return action.ToLowerInvariant() switch
- {
- "dotnet-restore" or "dotnet-build" or "dotnet-test" or "dotnet-publish" => [Req("dotnet")],
- "npm-install" or "npm-ci" or "npm-build" or "npm-test" or "npm-audit" => [Req("node"), Req("npm")],
- "python-venv-create" or "python-pip-install" or "python-pip-sync" or "python-pytest" => [Req("python")],
- "cargo-build" or "cargo-test" => [Req("cargo")],
- "tauri-build" => [Req("cargo"), Req("node"), Req("npm")],
- "git-status" or "git-fetch" or "git-pull" or "git-clean" => [Req("git")],
- "docker-build" or "docker-compose-up" or "docker-compose-down" => [Req("docker")],
- _ => [],
- };
- }
-
- private static List InferCommandRequirements(string command, IReadOnlyList args)
- {
- return command.ToLowerInvariant() switch
- {
- "dotnet" => [Req("dotnet")],
- "npm" => [Req("node"), Req("npm")],
- "pnpm" => [Req("node"), Req("pnpm")],
- "yarn" => [Req("node"), Req("yarn")],
- "python" or "py" => [Req("python")],
- "cargo" => [Req("cargo")],
- "tauri" => [Req("cargo"), Req("node"), Req("npm")],
- "git" => [Req("git")],
- "docker" => [Req("docker")],
- "pwsh" or "powershell" => LegacyScriptRequirementResolver.InferForPowerShellArgs(args),
- _ => [],
- };
- }
-
- private static ToolRequirement Req(string tool) => new()
- {
- Tool = tool,
- InstallPolicy = InstallPolicy.Prompt,
- };
-}
diff --git a/Journal.DevTool/Core/RunEventJsonlRecorder.cs b/Journal.DevTool/Core/RunEventJsonlRecorder.cs
deleted file mode 100644
index 526255e..0000000
--- a/Journal.DevTool/Core/RunEventJsonlRecorder.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace Sdt.Core;
-
-public sealed class RunEventJsonlRecorder : IDisposable
-{
- private static readonly JsonSerializerOptions JsonOptions = new()
- {
- PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
- WriteIndented = false
- };
-
- static RunEventJsonlRecorder()
- {
- JsonOptions.Converters.Add(new JsonStringEnumConverter());
- }
-
- private readonly StreamWriter _writer;
- private readonly object _gate = new();
- private bool _disposed;
-
- public string FilePath { get; }
-
- private RunEventJsonlRecorder(string filePath, StreamWriter writer)
- {
- FilePath = filePath;
- _writer = writer;
- }
-
- public static RunEventJsonlRecorder Create(string projectRoot, string category)
- {
- var root = Path.Combine(projectRoot, ".sdt", "events");
- Directory.CreateDirectory(root);
- var fileName = $"{category}-{DateTimeOffset.Now:yyyyMMdd-HHmmss}.jsonl";
- var path = Path.Combine(root, fileName);
- var writer = new StreamWriter(new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
- {
- AutoFlush = true
- };
- return new RunEventJsonlRecorder(path, writer);
- }
-
- public void Write(RunEvent evt)
- {
- lock (_gate)
- {
- if (_disposed)
- return;
- var line = JsonSerializer.Serialize(evt, JsonOptions);
- _writer.WriteLine(line);
- }
- }
-
- public void Dispose()
- {
- lock (_gate)
- {
- if (_disposed)
- return;
- _disposed = true;
- _writer.Dispose();
- }
- }
-}
diff --git a/Journal.DevTool/Core/RunEventLogReader.cs b/Journal.DevTool/Core/RunEventLogReader.cs
deleted file mode 100644
index f2c223a..0000000
--- a/Journal.DevTool/Core/RunEventLogReader.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-using System.Text.Json;
-
-namespace Sdt.Core;
-
-public sealed record RunEventLogFile(
- string Path,
- string Name,
- DateTimeOffset LastWriteTime,
- long SizeBytes);
-
-public sealed class RunEventLogReader
-{
- public IReadOnlyList ListEventFiles(string projectRoot)
- {
- var eventsRoot = Path.Combine(projectRoot, ".sdt", "events");
- if (!Directory.Exists(eventsRoot))
- return [];
-
- return Directory.EnumerateFiles(eventsRoot, "*.jsonl", SearchOption.TopDirectoryOnly)
- .Select(path =>
- {
- var info = new FileInfo(path);
- return new RunEventLogFile(
- Path: path,
- Name: info.Name,
- LastWriteTime: info.LastWriteTime,
- SizeBytes: info.Length);
- })
- .OrderByDescending(f => f.LastWriteTime)
- .ToList();
- }
-
- public IReadOnlyList ReadEvents(string filePath)
- {
- var results = new List();
- if (!File.Exists(filePath))
- return results;
-
- foreach (var line in File.ReadLines(filePath))
- {
- if (string.IsNullOrWhiteSpace(line))
- continue;
-
- if (TryParseLine(line, out var evt))
- results.Add(evt!);
- }
-
- return results;
- }
-
- internal static bool TryParseLine(string jsonLine, out RunEvent? evt)
- {
- evt = null;
- try
- {
- using var doc = JsonDocument.Parse(jsonLine);
- var root = doc.RootElement;
-
- var category = root.TryGetProperty("category", out var c) ? c.GetString() : null;
- var typeRaw = root.TryGetProperty("type", out var t) ? t.GetString() : null;
- var message = root.TryGetProperty("message", out var m) ? m.GetString() : null;
- var workflowId = root.TryGetProperty("workflowId", out var wf) ? wf.GetString() : null;
- var stepId = root.TryGetProperty("stepId", out var st) ? st.GetString() : null;
- var tool = root.TryGetProperty("tool", out var tl) ? tl.GetString() : null;
- var success = root.TryGetProperty("success", out var s) && s.ValueKind != JsonValueKind.Null ? s.GetBoolean() : (bool?)null;
- var exitCode = root.TryGetProperty("exitCode", out var ec) && ec.ValueKind != JsonValueKind.Null ? ec.GetInt32() : (int?)null;
- DateTimeOffset? occurred = null;
- if (root.TryGetProperty("occurredAt", out var ts) && ts.ValueKind == JsonValueKind.String &&
- DateTimeOffset.TryParse(ts.GetString(), out var parsed))
- {
- occurred = parsed;
- }
-
- if (string.IsNullOrWhiteSpace(category) ||
- string.IsNullOrWhiteSpace(typeRaw) ||
- string.IsNullOrWhiteSpace(message) ||
- !Enum.TryParse(typeRaw, ignoreCase: true, out var type))
- {
- return false;
- }
-
- evt = new RunEvent(
- Category: category!,
- Type: type,
- Message: message!,
- WorkflowId: workflowId,
- StepId: stepId,
- Tool: tool,
- Success: success,
- ExitCode: exitCode,
- Timestamp: occurred);
- return true;
- }
- catch
- {
- return false;
- }
- }
-}
diff --git a/Journal.DevTool/Core/RunEvents.cs b/Journal.DevTool/Core/RunEvents.cs
deleted file mode 100644
index 582b52b..0000000
--- a/Journal.DevTool/Core/RunEvents.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-namespace Sdt.Core;
-
-public enum RunEventType
-{
- WorkflowStarted,
- WorkflowPlanned,
- WorkflowStepStarted,
- WorkflowStepCompleted,
- ProbeChecked,
- ProbeFailed,
- InstallPlanPrepared,
- InstallDeclined,
- InstallCommandStarted,
- InstallCommandCompleted,
- WorkflowCompleted,
- DebugStarted,
- DebugCommandStarted,
- DebugCommandCompleted,
- DebugCompleted,
-}
-
-public sealed record RunEvent(
- string Category,
- RunEventType Type,
- string Message,
- string? WorkflowId = null,
- string? StepId = null,
- string? Tool = null,
- bool? Success = null,
- int? ExitCode = null,
- DateTimeOffset? Timestamp = null)
-{
- public DateTimeOffset OccurredAt { get; init; } = Timestamp ?? DateTimeOffset.Now;
-}
diff --git a/Journal.DevTool/Core/ScriptLocator.cs b/Journal.DevTool/Core/ScriptLocator.cs
deleted file mode 100644
index 953da1e..0000000
--- a/Journal.DevTool/Core/ScriptLocator.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace Sdt.Core;
-
-internal static class ScriptLocator
-{
- public static string? FindHelperScript(string projectRoot, string scriptFileName)
- {
- // Packaged location: alongside executable in ./scripts
- var bundled = Path.Combine(AppContext.BaseDirectory, "scripts", scriptFileName);
- if (File.Exists(bundled))
- return bundled;
-
- // Source/project location fallback
- var project = Path.Combine(projectRoot, "scripts", scriptFileName);
- if (File.Exists(project))
- return project;
-
- return null;
- }
-}
diff --git a/Journal.DevTool/Core/ToolProbeService.cs b/Journal.DevTool/Core/ToolProbeService.cs
deleted file mode 100644
index d2e6b98..0000000
--- a/Journal.DevTool/Core/ToolProbeService.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-using System.Diagnostics;
-using System.Text.Json;
-using Sdt.Config;
-
-namespace Sdt.Core;
-
-public sealed class ToolProbeService : IToolProbe
-{
- public async Task ProbeAsync(
- string tool,
- string projectRoot,
- DevToolConfig? config = null,
- CancellationToken cancellationToken = default)
- {
- var direct = await ProbeDirectAsync(tool, config, cancellationToken).ConfigureAwait(false);
- if (direct.IsAvailable)
- return direct;
-
- var scriptPath = ScriptLocator.FindHelperScript(projectRoot, "diag.py");
- if (scriptPath is null)
- return direct;
-
- if (!(await ProbeDirectAsync("python", config, cancellationToken).ConfigureAwait(false)).IsAvailable)
- return direct;
-
- try
- {
- var psi = new ProcessStartInfo
- {
- FileName = PythonResolver.ResolveExecutable(),
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- UseShellExecute = false,
- CreateNoWindow = true,
- WorkingDirectory = projectRoot,
- };
- psi.ArgumentList.Add(scriptPath);
- psi.ArgumentList.Add("probe");
- psi.ArgumentList.Add("--tool");
- psi.ArgumentList.Add(tool);
- psi.ArgumentList.Add("--json");
-
- using var process = new Process { StartInfo = psi };
- process.Start();
- var stdout = await process.StandardOutput.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
- var stderr = await process.StandardError.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
- await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false);
- if (process.ExitCode != 0)
- return new ProbeResult(tool, false, Details: stderr.Trim());
-
- var parsed = JsonSerializer.Deserialize(stdout);
- if (parsed is null)
- return new ProbeResult(tool, false, Details: "diag.py returned invalid JSON");
-
- return new ProbeResult(parsed.Tool ?? tool, parsed.Available, parsed.Version, parsed.Details);
- }
- catch (Exception ex)
- {
- return new ProbeResult(tool, false, Details: ex.Message);
- }
- }
-
- private static async Task ProbeDirectAsync(string tool, DevToolConfig? config, CancellationToken cancellationToken)
- {
- var command = tool.ToLowerInvariant() switch
- {
- "python" => PythonResolver.ResolveExecutable(),
- "dotnet" => "dotnet",
- "node" => "node",
- "npm" => "npm",
- "cargo" => "cargo",
- "tauri" => "tauri",
- "git" => "git",
- "docker" => "docker",
- _ => tool,
- };
- var resolution = CommandResolver.ResolveWithTrace(command, config, tool);
- command = resolution.Resolved;
-
- var versionArg = command is "python" ? "--version" : "--version";
- try
- {
- var psi = new ProcessStartInfo
- {
- FileName = command,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- UseShellExecute = false,
- CreateNoWindow = true,
- };
- psi.ArgumentList.Add(versionArg);
-
- using var process = new Process { StartInfo = psi };
- process.Start();
- var stdout = await process.StandardOutput.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
- var stderr = await process.StandardError.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
- await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false);
-
- if (process.ExitCode != 0)
- {
- var failDetails = string.IsNullOrWhiteSpace(stderr) ? stdout.Trim() : stderr.Trim();
- var trace = $"{resolution.Source}: {resolution.Resolved}";
- return new ProbeResult(tool, false, Details: string.IsNullOrWhiteSpace(failDetails) ? trace : $"{trace} | {failDetails}");
- }
-
- var version = string.IsNullOrWhiteSpace(stdout) ? stderr.Trim() : stdout.Trim();
- return new ProbeResult(tool, true, Version: version, Details: $"{resolution.Source}: {resolution.Resolved}");
- }
- catch (Exception ex)
- {
- return new ProbeResult(tool, false, Details: $"{resolution.Source}: {resolution.Resolved} | {ex.Message}");
- }
- }
-
- private sealed class DiagProbeJson
- {
- public string? Tool { get; init; }
- public bool Available { get; init; }
- public string? Version { get; init; }
- public string? Details { get; init; }
- }
-}
diff --git a/Journal.DevTool/Core/WorkflowExecutor.cs b/Journal.DevTool/Core/WorkflowExecutor.cs
deleted file mode 100644
index 55c08e6..0000000
--- a/Journal.DevTool/Core/WorkflowExecutor.cs
+++ /dev/null
@@ -1,273 +0,0 @@
-using Sdt.Config;
-
-namespace Sdt.Core;
-
-public sealed class WorkflowExecutor(
- IWorkflowPlanner planner,
- IToolProbe toolProbe,
- IPrereqInstaller installer,
- IActionRunner actionRunner,
- IRequirementResolver requirementResolver)
-{
- private readonly IWorkflowPlanner _planner = planner;
- private readonly IToolProbe _toolProbe = toolProbe;
- private readonly IPrereqInstaller _installer = installer;
- private readonly IActionRunner _actionRunner = actionRunner;
- private readonly IRequirementResolver _requirementResolver = requirementResolver;
-
- public async Task ExecuteAsync(
- WorkflowDefinition rootWorkflow,
- IReadOnlyDictionary allWorkflows,
- DevToolConfig config,
- string projectRoot,
- Func> confirmInstallAsync,
- Action onOutput,
- Action? onEvent = null,
- CancellationToken cancellationToken = default)
- {
- var results = new List();
- var plan = _planner.ResolvePlan(rootWorkflow, allWorkflows);
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.WorkflowStarted,
- Message: $"Workflow '{rootWorkflow.Id}' started.",
- WorkflowId: rootWorkflow.Id));
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.WorkflowPlanned,
- Message: $"Execution plan contains {plan.Count} workflow(s).",
- WorkflowId: rootWorkflow.Id));
-
- if (plan.Count == 0)
- {
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.WorkflowCompleted,
- Message: "No executable workflow steps were found.",
- WorkflowId: rootWorkflow.Id,
- Success: false));
- return new WorkflowExecutionResult(
- Success: false,
- StopReason: ExecutionStopReason.ValidationFailed,
- Message: "This workflow has no executable steps.",
- Steps: results);
- }
-
- foreach (var workflow in plan)
- {
- foreach (var step in workflow.Steps)
- {
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.WorkflowStepStarted,
- Message: $"Step '{step.Label}' started.",
- WorkflowId: workflow.Id,
- StepId: step.Id));
-
- var requires = _requirementResolver.Resolve(step);
- foreach (var req in requires)
- {
- var probe = await _toolProbe.ProbeAsync(req.Tool, projectRoot, config, cancellationToken).ConfigureAwait(false);
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.ProbeChecked,
- Message: probe.IsAvailable
- ? $"Tool '{req.Tool}' is available."
- : $"Tool '{req.Tool}' is missing.",
- WorkflowId: workflow.Id,
- StepId: step.Id,
- Tool: req.Tool,
- Success: probe.IsAvailable));
- if (probe.IsAvailable)
- continue;
-
- if (!string.IsNullOrWhiteSpace(probe.Details))
- {
- onOutput($"Probe detail [{req.Tool}]: {probe.Details}", false);
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.ProbeFailed,
- Message: probe.Details,
- WorkflowId: workflow.Id,
- StepId: step.Id,
- Tool: req.Tool,
- Success: false));
- }
-
- if (req.InstallPolicy == InstallPolicy.Never)
- {
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.WorkflowCompleted,
- Message: $"Missing prerequisite '{req.Tool}'.",
- WorkflowId: rootWorkflow.Id,
- Tool: req.Tool,
- Success: false));
- return new WorkflowExecutionResult(
- Success: false,
- StopReason: ExecutionStopReason.MissingPrereq,
- Message: $"Missing prerequisite '{req.Tool}' for step '{step.Label}'.",
- Steps: results);
- }
-
- var installPlan = await _installer.GetInstallPlanAsync(
- req.Tool,
- projectRoot,
- config,
- cancellationToken).ConfigureAwait(false);
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.InstallPlanPrepared,
- Message: installPlan.Summary,
- WorkflowId: workflow.Id,
- StepId: step.Id,
- Tool: req.Tool,
- Success: installPlan.Supported));
- if (!installPlan.Supported || installPlan.Commands.Count == 0)
- {
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.WorkflowCompleted,
- Message: $"No installer plan available for '{req.Tool}'.",
- WorkflowId: rootWorkflow.Id,
- Tool: req.Tool,
- Success: false));
- return new WorkflowExecutionResult(
- Success: false,
- StopReason: ExecutionStopReason.MissingPrereq,
- Message: $"Missing prerequisite '{req.Tool}' and no installer plan is available.",
- Steps: results);
- }
-
- var approved = req.InstallPolicy == InstallPolicy.Auto
- ? true
- : await confirmInstallAsync(req.Tool, installPlan).ConfigureAwait(false);
-
- if (!approved)
- {
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.InstallDeclined,
- Message: $"Install declined for '{req.Tool}'.",
- WorkflowId: workflow.Id,
- StepId: step.Id,
- Tool: req.Tool,
- Success: false));
- return new WorkflowExecutionResult(
- Success: false,
- StopReason: ExecutionStopReason.UserDeclined,
- Message: $"Install declined for missing prerequisite '{req.Tool}'.",
- Steps: results);
- }
-
- foreach (var installCommand in installPlan.Commands)
- {
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.InstallCommandStarted,
- Message: $"{installCommand.Command} {string.Join(" ", installCommand.Args)}",
- WorkflowId: workflow.Id,
- StepId: step.Id,
- Tool: req.Tool));
-
- var installResult = await _installer.RunInstallAsync(
- installCommand,
- projectRoot,
- onOutput,
- cancellationToken).ConfigureAwait(false);
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.InstallCommandCompleted,
- Message: $"Install command exited {installResult.ExitCode}.",
- WorkflowId: workflow.Id,
- StepId: step.Id,
- Tool: req.Tool,
- Success: installResult.Success,
- ExitCode: installResult.ExitCode));
-
- if (!installResult.Success)
- {
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.WorkflowCompleted,
- Message: $"Install failed for '{req.Tool}'.",
- WorkflowId: rootWorkflow.Id,
- Tool: req.Tool,
- Success: false));
- return new WorkflowExecutionResult(
- Success: false,
- StopReason: ExecutionStopReason.InstallFailed,
- Message: $"Failed to install prerequisite '{req.Tool}'.",
- Steps: results);
- }
- }
-
- var verifyProbe = await _toolProbe.ProbeAsync(req.Tool, projectRoot, config, cancellationToken).ConfigureAwait(false);
- if (!verifyProbe.IsAvailable)
- {
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.WorkflowCompleted,
- Message: $"Tool '{req.Tool}' still missing after install.",
- WorkflowId: rootWorkflow.Id,
- Tool: req.Tool,
- Success: false));
- return new WorkflowExecutionResult(
- Success: false,
- StopReason: ExecutionStopReason.InstallFailed,
- Message: $"Prerequisite '{req.Tool}' is still missing after install attempt.",
- Steps: results);
- }
- }
-
- var runResult = await _actionRunner.RunStepAsync(
- step,
- projectRoot,
- onOutput,
- cancellationToken).ConfigureAwait(false);
-
- results.Add(new WorkflowStepResult(
- workflow.Id,
- step.Id,
- string.IsNullOrWhiteSpace(step.Label) ? step.Id : step.Label,
- runResult));
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.WorkflowStepCompleted,
- Message: $"Step '{step.Label}' exited {runResult.ExitCode}.",
- WorkflowId: workflow.Id,
- StepId: step.Id,
- Success: runResult.Success,
- ExitCode: runResult.ExitCode));
-
- if (!runResult.Success)
- {
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.WorkflowCompleted,
- Message: $"Step '{step.Label}' failed.",
- WorkflowId: rootWorkflow.Id,
- Success: false,
- ExitCode: runResult.ExitCode));
- return new WorkflowExecutionResult(
- Success: false,
- StopReason: ExecutionStopReason.CommandFailed,
- Message: $"Step '{step.Label}' failed with exit code {runResult.ExitCode}.",
- Steps: results);
- }
- }
- }
-
- onEvent?.Invoke(new RunEvent(
- Category: "workflow",
- Type: RunEventType.WorkflowCompleted,
- Message: "Workflow completed successfully.",
- WorkflowId: rootWorkflow.Id,
- Success: true));
- return new WorkflowExecutionResult(
- Success: true,
- StopReason: null,
- Message: "Workflow completed successfully.",
- Steps: results);
- }
-}
diff --git a/Journal.DevTool/Core/WorkflowPlanner.cs b/Journal.DevTool/Core/WorkflowPlanner.cs
deleted file mode 100644
index d677df6..0000000
--- a/Journal.DevTool/Core/WorkflowPlanner.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using Sdt.Config;
-
-namespace Sdt.Core;
-
-public sealed class WorkflowPlanner : IWorkflowPlanner
-{
- public List ResolvePlan(
- WorkflowDefinition workflow,
- IReadOnlyDictionary allWorkflows)
- {
- var visited = new HashSet(StringComparer.OrdinalIgnoreCase);
- var plan = new List();
- Visit(workflow, allWorkflows, visited, plan);
- return plan;
- }
-
- private static void Visit(
- WorkflowDefinition workflow,
- IReadOnlyDictionary allWorkflows,
- HashSet visited,
- List plan)
- {
- if (!visited.Add(workflow.Id))
- return;
-
- foreach (var depId in workflow.DependsOn)
- {
- if (allWorkflows.TryGetValue(depId, out var dep))
- Visit(dep, allWorkflows, visited, plan);
- }
-
- if (workflow.Steps.Count > 0)
- plan.Add(workflow);
- }
-}
diff --git a/Journal.DevTool/DevTool.csproj b/Journal.DevTool/DevTool.csproj
deleted file mode 100644
index 9bd6978..0000000
--- a/Journal.DevTool/DevTool.csproj
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
- Exe
- net10.0
- enable
- enable
- sdt
- Sdt
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
- scripts\%(Filename)%(Extension)
- scripts\%(Filename)%(Extension)
- PreserveNewest
- PreserveNewest
-
-
- scripts\%(Filename)%(Extension)
- scripts\%(Filename)%(Extension)
- PreserveNewest
- PreserveNewest
-
-
-
-
diff --git a/Journal.DevTool/Journal.DevTool.csproj b/Journal.DevTool/Journal.DevTool.csproj
deleted file mode 100644
index 5d8f248..0000000
--- a/Journal.DevTool/Journal.DevTool.csproj
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
- Exe
- net10.0
- enable
- enable
- sdt
- Sdt
- false
-
-
-
-
-
-
-
diff --git a/Journal.DevTool/Program.cs b/Journal.DevTool/Program.cs
deleted file mode 100644
index a6b938a..0000000
--- a/Journal.DevTool/Program.cs
+++ /dev/null
@@ -1,143 +0,0 @@
-using Sdt.Config;
-using Sdt.Tui;
-using Spectre.Console;
-
-try
-{
- // ── Workspace + project discovery ────────────────────────────────────────
-
- var workspaceResult = WorkspaceLoader.FindAndLoad();
- var projectResult = ConfigLoader.FindAndLoad();
- var cliArgs = Environment.GetCommandLineArgs().Skip(1).ToArray();
- var forceInit = cliArgs.Any(a => string.Equals(a, "init", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(a, "--init", StringComparison.OrdinalIgnoreCase));
-
- if (forceInit)
- {
- var scan = ConfigBootstrapper.Scan(Directory.GetCurrentDirectory());
- var generated = ConfigBootstrapper.BuildDefaultConfig(scan);
- var path = ConfigBootstrapper.WriteDefaultConfig(scan.ProjectRoot, generated, overwrite: false);
- AnsiConsole.MarkupLine(Theme.Ok($"Initialized config at {path}"));
- projectResult = ConfigLoader.FindAndLoad(scan.ProjectRoot);
- }
-
- if (projectResult is null)
- {
- AnsiConsole.MarkupLine($"[bold {Theme.Red}]SDT:[/] [{Theme.Amber}]No devtool.json found[/] in current directory or any parent.");
- var bootstrap = AnsiConsole.Confirm(
- $"[{Theme.Amber}]Generate a default devtool.json for this project now?[/]",
- defaultValue: true);
- if (!bootstrap)
- {
- AnsiConsole.MarkupLine(Theme.Faint("Create a devtool.json in your project root to get started."));
- return 1;
- }
-
- var scan = ConfigBootstrapper.Scan(Directory.GetCurrentDirectory());
- AnsiConsole.MarkupLine(Theme.Faint($"Detected project root: {scan.ProjectRoot}"));
- if (scan.ToolFamilies.Count > 0)
- AnsiConsole.MarkupLine(Theme.Faint($"Detected tool families: {string.Join(", ", scan.ToolFamilies)}"));
-
- var generated = ConfigBootstrapper.BuildDefaultConfig(scan);
- var preview = ConfigBootstrapper.ToJson(generated);
- AnsiConsole.Write(new Panel(Markup.Escape(preview)).Header("Generated devtool.json preview").BorderStyle(Theme.DimStyle));
-
- var confirmWrite = AnsiConsole.Confirm(
- $"[{Theme.Amber}]Write generated devtool.json to {scan.ProjectRoot}?[/]",
- defaultValue: true);
- if (!confirmWrite)
- return 1;
-
- var path = ConfigBootstrapper.WriteDefaultConfig(scan.ProjectRoot, generated, overwrite: false);
- AnsiConsole.MarkupLine(Theme.Ok($"Created {path}"));
- projectResult = ConfigLoader.FindAndLoad(scan.ProjectRoot);
- if (projectResult is null)
- {
- AnsiConsole.MarkupLine(Theme.Fail("Generated config could not be reloaded."));
- return 1;
- }
- }
-
- // ── Main run loop (handles workspace project switching) ────────────────
-
- var currentLoaded = projectResult;
- var (workspace, workspaceRoot) = workspaceResult.HasValue
- ? (workspaceResult.Value.Config, workspaceResult.Value.WorkspaceRoot)
- : ((WorkspaceConfig?)null, (string?)null);
-
- while (true)
- {
- var app = new App(currentLoaded.Config, currentLoaded.ProjectRoot, currentLoaded.Warnings, workspace, workspaceRoot);
- var result = await app.RunAsync();
-
- if (result.Reason == AppExitReason.Quit)
- break;
-
- // User switched projects — reload config from new root
- if (result.Reason == AppExitReason.SwitchProject && result.NewProjectRoot is not null)
- {
- LoadedProjectConfig? loaded;
- try
- {
- loaded = ConfigLoader.FindAndLoad(result.NewProjectRoot);
- }
- catch (Exception ex)
- {
- AnsiConsole.MarkupLine(Theme.Fail(ex.Message));
- AnsiConsole.MarkupLine(Theme.Faint("Press any key to stay on current project..."));
- Console.ReadKey(intercept: true);
- continue;
- }
- if (loaded is null)
- {
- AnsiConsole.MarkupLine(Theme.Fail($"No devtool.json found at: {result.NewProjectRoot}"));
- AnsiConsole.MarkupLine(Theme.Faint("Press any key to stay on current project..."));
- Console.ReadKey(intercept: true);
- continue; // go back to current app
- }
-
- currentLoaded = loaded;
- }
- }
-
- return 0;
-}
-catch (Exception ex)
-{
- var message = ex.Message;
- var isExpectedMigrationError =
- ex is InvalidOperationException &&
- message.Contains("Legacy targets-only config detected", StringComparison.OrdinalIgnoreCase);
-
- AnsiConsole.MarkupLine(Theme.Fail($"Fatal: {message}"));
- if (isExpectedMigrationError)
- {
- var configPath = ConfigLoader.FindConfigPath();
- if (!string.IsNullOrWhiteSpace(configPath))
- {
- var migrate = AnsiConsole.Confirm(
- $"[{Theme.Amber}]Apply automatic migration now (creates backup + converts targets -> workflows)?[/]",
- defaultValue: true);
- if (migrate)
- {
- var result = ConfigLoader.ApplyLegacyTargetMigration(configPath, createBackup: true);
- if (result.Success)
- {
- AnsiConsole.MarkupLine(Theme.Ok("Migration applied successfully."));
- if (!string.IsNullOrWhiteSpace(result.BackupPath))
- AnsiConsole.MarkupLine(Theme.Faint($"Backup: {result.BackupPath}"));
- AnsiConsole.MarkupLine(Theme.Faint("Run sdt.exe again in strict mode."));
- }
- else
- {
- AnsiConsole.MarkupLine(Theme.Fail($"Migration failed: {result.Message}"));
- }
- }
- }
- }
-
- if (!isExpectedMigrationError)
- AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything);
-
- return 1;
-}
diff --git a/Journal.DevTool/README.md b/Journal.DevTool/README.md
deleted file mode 100644
index f36acd4..0000000
--- a/Journal.DevTool/README.md
+++ /dev/null
@@ -1,200 +0,0 @@
-# SDT (Stan's Dev Tools)
-
-Cross-platform terminal orchestrator for project workflows, toolchain checks, and prerequisite gating.
-
-## Current State
-
-- Standalone `.NET` TUI app (`net10.0`)
-- Workflow-first config model in `devtool.json`
-- Strict-by-default legacy migration (`targets`-only configs fail unless compat mode is enabled)
-- Python-first diagnostics/build script layer under `scripts/`
-- Fail-fast execution with install prompt gating for missing prerequisites
-- Debug profiles with attach metadata and diagnostics bundle generation
-- Workspace-first project switching with support for external project paths
-- Workspace-level defaults layering via `sdt-defaults.json` (ancestor defaults merged, project config wins)
-- Project status tracking is maintained in `ROADMAP.md`
-- Core run-event stream (`RunEvent`) shared by workflow + debug execution (TUI consumes it; GUI-ready)
-- Run events are persisted to JSONL at `.sdt/events/` for external tooling/GUI consumers
-- TUI includes `SYSTEM -> View run events` to inspect persisted JSONL event logs
-- `SYSTEM -> Run config doctor` can apply common autofixes (missing working dirs, legacy migration)
-
-## Run
-
-```powershell
-dotnet run --project DevTool.csproj
-```
-
-Run from any subdirectory inside a project; SDT walks up to find `devtool.json`.
-
-If `devtool.json` is missing, SDT now offers to scan the repo and generate a default config.
-
-Explicit bootstrap command:
-
-```powershell
-dotnet run --project DevTool.csproj -- init
-```
-
-Bootstrap detects common stacks (`dotnet`, `npm/node`, `python`, `cargo/tauri`, `git`, `docker`) and generates:
-
-- default workflows
-- toolchain/tooling defaults
-- debug profiles + diagnostics defaults
-
-## Config Model
-
-SDT supports both:
-
-- `workflows` (preferred)
-- `targets` (legacy; compat mode only)
-
-### Legacy Migration Mode (v1.2)
-
-- Default: strict mode
-- Behavior: `targets`-only config fails early with migration instructions
-- Preview file: SDT writes `devtool.generated.workflows.json` for migration help
-- Temporary rollback: set `SDT_LEGACY_MODE=compat`
-
-Permanent fix (recommended):
-
-1. Open `devtool.generated.workflows.json`
-2. Copy its `workflows` into `devtool.json`
-3. Remove or empty legacy `targets`
-4. Run `sdt.exe` again in strict mode
-
-### Workflow shape (preferred)
-
-```json
-{
- "id": "build",
- "label": "Build",
- "description": "Build project",
- "group": "Build",
- "dependsOn": [],
- "steps": [
- {
- "id": "dotnet-build",
- "label": "dotnet build",
- "action": "dotnet-build",
- "actionArgs": [],
- "workingDir": ".",
- "requires": [
- { "tool": "dotnet", "installPolicy": "Prompt" }
- ]
- }
- ]
-}
-```
-
-### Extra sections
-
-- `tooling.tools[].preferredInstallCommands`: preferred install commands per tool
-- `tooling.tools[].executables`: explicit executable candidates for non-standard PATH setups
-- `project.rootHints`: files/folders that identify project root
-- `env`: session-level environment variable editor values
-- `debug.profiles[]`: run/attach debug profiles
-- `debug.diagnostics`: diagnostics bundle policy (`.sdt/debug` by default)
- - secure default: allowlist-only environment capture
- - set `includeAllEnv=true` to opt into full environment capture
-
-### Workspace Defaults Layering
-
-If SDT finds `sdt-defaults.json` in the project directory tree (current project root or an ancestor), it merges it into the effective config before runtime:
-
-- base layer: `sdt-defaults.json`
-- override layer: project `devtool.json` (project values win)
-
-Merge behavior:
-
-- objects merge recursively
-- arrays/scalars are replaced when project provides the property
-
-This is useful for shared defaults like toolchains, diagnostics policies, and baseline env definitions across multiple projects in one workspace.
-
-## Execution Behavior
-
-For each workflow step:
-
-1. Resolve dependencies (topological order)
-2. Probe required tools
-3. If missing, show install commands and prompt (`Prompt` policy)
-4. On decline/install failure/step failure, stop immediately
-5. Render step summary table with exit code + elapsed time
-6. On workflow/debug failure, generate diagnostics bundle when enabled
-
-Installer command precedence:
-
-1. `tooling.tools[].preferredInstallCommands`
-2. `scripts/diag.py install-plan`
-3. built-in C# fallback templates (used automatically if script planning fails)
-
-When a tool probe fails, SDT now prints probe diagnostics (including command resolution source/path) in run output before prompting for installs.
-
-## Scripts
-
-See [scripts/README.md](/e:/stansshit/csharp/DevTool-master/scripts/README.md).
-
-Primary Python entrypoints:
-
-- `scripts/diag.py`
-- `scripts/build.py`
-- `scripts/dotnet-min.py`
-- `scripts/pip-min.py`
-- `scripts/publish-*.py`
-
-## Workspace Support
-
-- Uses `sdt-workspace.json` when present
-- If missing, can auto-discover nearby projects containing `devtool.json`
-- Workspace screen can add external project roots (absolute paths supported)
-- `projects[].disabled`, `projects[].tags`, and `projects[].toolFamilies` are supported
-
-## Dev Shell Bootstrap
-
-Python-first cross-shell dev environment bootstrap:
-
-```powershell
-# PowerShell
-. ./scripts/dev-shell.ps1
-
-# cmd
-scripts\dev-shell.cmd
-```
-
-```bash
-# bash/zsh
-source ./scripts/dev-shell.sh
-```
-
-Underlying implementation is `scripts/dev_shell.py`:
-
-- `python scripts/dev_shell.py export --shell pwsh --json`
-- `python scripts/dev_shell.py doctor`
-
-## Legacy PowerShell Compatibility
-
-Legacy `.ps1` scripts remain for migration compatibility only. New functionality is implemented in Python scripts first. `script-common.ps1` is legacy-only.
-
-Legacy runtime behavior in v1.2:
-
-- strict mode rejects `targets`-only configs by default
-- compat mode (`SDT_LEGACY_MODE=compat`) temporarily allows legacy execution
-- TUI `SYSTEM` includes `Migrate legacy targets -> workflows` to apply migration in place (with backup)
-
-Deprecation target:
-
-- v1.x: compatibility only (no new behavior guarantees)
-- v2.0: remove legacy `.ps1` scripts from default SDT workflows and docs
-
-## Testing
-
-Run unit/integration tests:
-
-```powershell
-dotnet test tests/DevTool.Tests/DevTool.Tests.csproj
-```
-
-Run Python script smoke checks:
-
-```powershell
-python -m py_compile scripts/*.py
-```
diff --git a/Journal.DevTool/ROADMAP.md b/Journal.DevTool/ROADMAP.md
deleted file mode 100644
index bb3044d..0000000
--- a/Journal.DevTool/ROADMAP.md
+++ /dev/null
@@ -1,50 +0,0 @@
-# SDT Roadmap / Kanban
-
-## Done (v1.2 Stabilization)
-
-- [x] Python-first runtime for diagnostics/build wrappers
-- [x] Config bootstrap generator for missing `devtool.json`
-- [x] Workflow-first execution + dual schema support
-- [x] Strict legacy mode default (`targets`-only blocked)
-- [x] Compatibility escape hatch (`SDT_LEGACY_MODE=compat`)
-- [x] Auto-generated migration preview (`devtool.generated.workflows.json`)
-- [x] In-app migration action: `Migrate legacy targets -> workflows`
-- [x] Centralized requirement inference (`RequirementResolver`)
-- [x] Installer planning precedence + fallback resilience
-- [x] Windows resolver hardening (`%VAR%` PATH expansion)
-- [x] Resolver tracing surfaced in probe details
-- [x] Secure diagnostics default (allowlist-only env capture)
-- [x] Workspace external project add flow
-- [x] Shared run event stream (`RunEvent`) across workflow + debug execution
-- [x] TUI event rendering layer wired on top of core run events (GUI-readiness slice)
-- [x] Persist run-event stream to JSONL for external GUI/client consumption (`.sdt/events/*.jsonl`)
-- [x] TUI events viewer for persisted run-event logs (`SYSTEM -> View run events`)
-- [x] Config doctor (`SYSTEM -> Run config doctor`)
-- [x] Doctor autofix actions (create missing working dirs + invoke legacy migration)
-- [x] Rich probe diagnostics panel in workflow failure summary
-- [x] Enhanced Tauri fallback guidance (Windows/macOS/Linux package manager aware)
-- [x] Workspace-level defaults file layering (`sdt-defaults.json`) above per-project `devtool.json`
-
-## In Progress (next focus)
-
-- [x] Add dedicated TUI "Events" viewer for last run
-- [x] Add doctor autofix actions for common issues (missing dirs, legacy schema migration)
-
-## Next (v1.3 candidates)
-
-- [ ] Setup wizard for first run (bootstrap + tool fixes)
-- [ ] Env profiles (`dev`, `ci`, `release`) with deterministic merge order
-- [ ] Managed secrets redaction policy for diagnostics bundles
-- [ ] Favorites/quick actions across projects
-
-## Later
-
-- [ ] JSON event stream for GUI integration
-- [ ] Native GUI shell over headless core services
-- [ ] Remove legacy PowerShell wrappers in v2
-
-## Current Milestone Status
-
-- Robustness Sprint v1.2: **complete**
-- v1.1 expansion items shipped partially (debug profiles + diagnostics + workspace add external)
-- Remaining gaps for broader AIO vision are mainly UX/workspace scale and advanced env orchestration
diff --git a/Journal.DevTool/Runner/ProcessRunner.cs b/Journal.DevTool/Runner/ProcessRunner.cs
deleted file mode 100644
index 3dbb3a5..0000000
--- a/Journal.DevTool/Runner/ProcessRunner.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-using System.Diagnostics;
-
-namespace Sdt.Runner;
-
-public sealed record RunResult(int ExitCode, TimeSpan Elapsed)
-{
- public bool Success => ExitCode == 0;
-}
-
-public static class ProcessRunner
-{
- ///
- /// Runs a command with the given args, streaming stdout/stderr via .
- /// onOutput receives (line, isStderr).
- ///
- public static async Task RunAsync(
- string command,
- IEnumerable args,
- string workingDir,
- Action onOutput,
- IReadOnlyDictionary? envOverrides = null,
- CancellationToken cancellationToken = default)
- {
- var psi = new ProcessStartInfo
- {
- FileName = Core.CommandResolver.Resolve(command),
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- UseShellExecute = false,
- CreateNoWindow = true,
- WorkingDirectory = workingDir,
- };
-
- if (envOverrides is not null)
- {
- foreach (var kvp in envOverrides)
- psi.Environment[kvp.Key] = kvp.Value;
- }
-
- foreach (var arg in args)
- psi.ArgumentList.Add(arg);
-
- var sw = Stopwatch.StartNew();
-
- using var process = new Process { StartInfo = psi };
-
- void OnCancel(object? sender, ConsoleCancelEventArgs e)
- {
- e.Cancel = true; // Prevent SDT from exiting immediately
- try { process.Kill(entireProcessTree: true); } catch { }
- }
-
- Console.CancelKeyPress += OnCancel;
-
- try
- {
- process.Start();
-
- var stdoutTask = DrainAsync(process.StandardOutput, line => onOutput(line, false), cancellationToken);
- var stderrTask = DrainAsync(process.StandardError, line => onOutput(line, true), cancellationToken);
-
- await Task.WhenAll(stdoutTask, stderrTask).ConfigureAwait(false);
- await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false);
- }
- finally
- {
- Console.CancelKeyPress -= OnCancel;
- }
-
- sw.Stop();
- return new RunResult(process.ExitCode, sw.Elapsed);
- }
-
- private static async Task DrainAsync(StreamReader reader, Action emit, CancellationToken ct)
- {
- string? line;
- while ((line = await reader.ReadLineAsync(ct).ConfigureAwait(false)) is not null
- && !ct.IsCancellationRequested)
- {
- emit(line);
- }
- }
-}
diff --git a/Journal.DevTool/Runner/TargetRunner.cs b/Journal.DevTool/Runner/TargetRunner.cs
deleted file mode 100644
index b4c670e..0000000
--- a/Journal.DevTool/Runner/TargetRunner.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using Sdt.Config;
-
-namespace Sdt.Runner;
-
-public static class TargetRunner
-{
- ///
- /// Returns the ordered list of real (non-virtual) steps needed to execute ,
- /// respecting DependsOn chains. Each step appears at most once.
- ///
- public static List ResolvePlan(
- BuildTarget target,
- IReadOnlyDictionary allTargets)
- {
- var visited = new HashSet(StringComparer.OrdinalIgnoreCase);
- var plan = new List();
- Visit(target, allTargets, visited, plan);
- return plan;
- }
-
- private static void Visit(
- BuildTarget target,
- IReadOnlyDictionary allTargets,
- HashSet visited,
- List plan)
- {
- if (!visited.Add(target.Id))
- return;
-
- // Recurse into dependencies first (topological order)
- foreach (var depId in target.DependsOn)
- {
- if (allTargets.TryGetValue(depId, out var dep))
- Visit(dep, allTargets, visited, plan);
- }
-
- // Virtual aggregator targets (null Command) are just dependency collectors
- if (target.Command is not null)
- plan.Add(target);
- }
-}
diff --git a/Journal.DevTool/Tui/App.cs b/Journal.DevTool/Tui/App.cs
deleted file mode 100644
index 97f5461..0000000
--- a/Journal.DevTool/Tui/App.cs
+++ /dev/null
@@ -1,800 +0,0 @@
-using Sdt.Config;
-using Sdt.Core;
-using Sdt.Core.Debug;
-using Spectre.Console;
-
-namespace Sdt.Tui;
-
-internal sealed record MenuItem(string Display, string Value);
-
-public enum AppExitReason { Quit, SwitchProject }
-public sealed record AppResult(AppExitReason Reason, string? NewProjectRoot = null);
-
-public sealed class App
-{
- private DevToolConfig _config;
- private string _projectRoot;
- private readonly WorkspaceConfig? _workspace;
- private readonly string? _workspaceRoot;
- private List _workflows;
- private readonly List _warnings;
- private readonly IDebugProfileRunner _debugRunner;
- private readonly IDiagnosticsBundleService _diagnostics;
- private readonly IRequirementResolver _requirementResolver = new RequirementResolver();
-
- private readonly WorkflowExecutor _executor = new(
- new WorkflowPlanner(),
- new ToolProbeService(),
- new PrereqInstallerService(),
- new ActionRunner(),
- new RequirementResolver());
-
- private IReadOnlyDictionary WorkflowMap =>
- _workflows.ToDictionary(t => t.Id, StringComparer.OrdinalIgnoreCase);
-
- public App(
- DevToolConfig config,
- string projectRoot,
- IReadOnlyList? warnings = null,
- WorkspaceConfig? workspace = null,
- string? workspaceRoot = null)
- {
- _config = config;
- _projectRoot = projectRoot;
- _workspace = workspace;
- _workspaceRoot = workspaceRoot;
- var normalized = WorkflowModelBuilder.Normalize(config, ResolveLegacyMode(), _requirementResolver);
- _workflows = normalized.Workflows.ToList();
- _warnings = [];
- _debugRunner = new DebugProfileRunner(new ToolProbeService(), new PrereqInstallerService());
- _diagnostics = new DiagnosticsBundleService();
- if (warnings is not null)
- _warnings.AddRange(warnings);
- _warnings.AddRange(normalized.Warnings);
- }
-
- private static LegacyMode ResolveLegacyMode()
- {
- var raw = Environment.GetEnvironmentVariable("SDT_LEGACY_MODE");
- return string.Equals(raw, "compat", StringComparison.OrdinalIgnoreCase)
- ? LegacyMode.Compat
- : LegacyMode.Strict;
- }
-
- public async Task RunAsync()
- {
- while (true)
- {
- AnsiConsole.Clear();
- RenderBanner();
-
- if (_warnings.Count > 0)
- {
- foreach (var warning in _warnings.Distinct(StringComparer.OrdinalIgnoreCase))
- AnsiConsole.MarkupLine(Theme.Warn("Config warning: " + warning));
- AnsiConsole.WriteLine();
- }
-
- var choice = ShowMainMenu();
- switch (choice)
- {
- case "__env__":
- EditEnvironment();
- break;
-
- case "__toolchains__":
- await new ToolchainScreen(_config, _projectRoot).RunAsync();
- break;
-
- case "__doctor__":
- await RunConfigDoctorAsync();
- break;
-
- case "__events__":
- new EventsScreen(_projectRoot, _config.Name, _config.Version).Run();
- break;
-
- case "__workspace__":
- if (_workspace is not null && _workspaceRoot is not null)
- {
- var switcher = new WorkspaceScreen(_workspace, _workspaceRoot, _projectRoot);
- var newRoot = switcher.SelectProject();
- if (newRoot is not null)
- return new AppResult(AppExitReason.SwitchProject, newRoot);
- }
- break;
-
- case "__migrate_legacy__":
- ApplyLegacyMigration();
- break;
-
- case "__quit__":
- AnsiConsole.MarkupLine("\n" + Theme.Faint("Later.") + "\n");
- return new AppResult(AppExitReason.Quit);
-
- default:
- if (choice.StartsWith("__debugattach__:", StringComparison.Ordinal))
- {
- var profileId = choice["__debugattach__:".Length..];
- ShowAttachInstructions(profileId);
- break;
- }
-
- if (choice.StartsWith("__debug__:", StringComparison.Ordinal))
- {
- var parts = choice.Split(':', 3, StringSplitOptions.None);
- if (parts.Length == 3)
- await RunDebugProfileAsync(parts[1], string.Equals(parts[2], "verbose", StringComparison.OrdinalIgnoreCase));
- break;
- }
-
- var workflowMap = WorkflowMap;
- if (workflowMap.TryGetValue(choice, out var workflow))
- await RunWorkflowAsync(workflow, workflowMap);
- break;
- }
-
- if (choice != "__quit__")
- {
- AnsiConsole.MarkupLine("\n" + Theme.Faint("Press any key to return to the menu..."));
- Console.ReadKey(intercept: true);
- }
- }
- }
-
- private void RenderBanner()
- {
- AnsiConsole.Write(new FigletText("SDT").Color(Theme.GreenColor));
- var wsInfo = _workspace is not null
- ? $" [{Theme.GreenDim}]∙ {Markup.Escape(_workspace.Name)}[/]"
- : string.Empty;
-
- AnsiConsole.Write(
- new Rule($"[bold {Theme.GreenBold}]{Markup.Escape(_config.Name)}[/] [{Theme.GreenDim}]v{Markup.Escape(_config.Version)}[/]{wsInfo}")
- .RuleStyle(Theme.DimStyle));
- AnsiConsole.MarkupLine(Theme.Faint($"root: {_projectRoot}") + "\n");
- }
-
- private string ShowMainMenu()
- {
- var prompt = new SelectionPrompt
-
-
-
-
+
+
+
+
diff --git a/Journal.SmokeTests/Journal.SmokeTests.csproj b/Journal.SmokeTests/Journal.SmokeTests.csproj
index a81680c..0b5dedd 100644
--- a/Journal.SmokeTests/Journal.SmokeTests.csproj
+++ b/Journal.SmokeTests/Journal.SmokeTests.csproj
@@ -2,9 +2,6 @@
Exe
- net10.0
- enable
- enable
diff --git a/Journal.WebGateway/Journal.WebGateway.csproj b/Journal.WebGateway/Journal.WebGateway.csproj
index f4e284d..1d28321 100644
--- a/Journal.WebGateway/Journal.WebGateway.csproj
+++ b/Journal.WebGateway/Journal.WebGateway.csproj
@@ -1,10 +1,5 @@
-
- net10.0
- enable
- enable
-
diff --git a/Journal.slnx b/Journal.slnx
index 10b89d0..7f1be05 100644
--- a/Journal.slnx
+++ b/Journal.slnx
@@ -3,6 +3,6 @@
-
+
diff --git a/package-lock.json b/package-lock.json
index 1a303e4..8d53e23 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2,5 +2,1936 @@
"name": "journal",
"lockfileVersion": 3,
"requires": true,
- "packages": {}
+ "packages": {
+ "": {
+ "name": "journal",
+ "workspaces": [
+ "Journal.App",
+ "Journal.DevTool"
+ ]
+ },
+ "Journal.App": {
+ "name": "journalapp",
+ "version": "0.1.0",
+ "license": "MIT",
+ "dependencies": {
+ "@tauri-apps/api": "^2",
+ "@tauri-apps/plugin-dialog": "^2.6.0",
+ "@tauri-apps/plugin-opener": "^2",
+ "tauri-plugin-mic-recorder-api": "^2.0.0"
+ },
+ "devDependencies": {
+ "@sveltejs/adapter-static": "^3.0.6",
+ "@sveltejs/kit": "^2.9.0",
+ "@sveltejs/vite-plugin-svelte": "^5.0.0",
+ "@tauri-apps/cli": "^2",
+ "prettier": "^3.8.1",
+ "prettier-plugin-svelte": "^3.5.0",
+ "svelte": "^5.0.0",
+ "svelte-check": "^4.0.0",
+ "typescript": "~5.6.2",
+ "vite": "^6.0.3"
+ }
+ },
+ "Journal.DevTool": {
+ "dependencies": {
+ "tauri-plugin-mic-recorder-api": "^2.0.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
+ "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
+ "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
+ "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
+ "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
+ "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
+ "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
+ "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
+ "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
+ "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
+ "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
+ "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
+ "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
+ "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
+ "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
+ "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
+ "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
+ "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
+ "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
+ "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
+ "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
+ "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@polka/url": {
+ "version": "1.0.0-next.29",
+ "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
+ "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
+ "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
+ "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
+ "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
+ "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
+ "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
+ "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
+ "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
+ "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
+ "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
+ "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
+ "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
+ "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
+ "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
+ "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
+ "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
+ "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
+ "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
+ "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
+ "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
+ "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
+ "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
+ "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
+ "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
+ "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
+ "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@standard-schema/spec": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
+ "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sveltejs/acorn-typescript": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.9.tgz",
+ "integrity": "sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^8.9.0"
+ }
+ },
+ "node_modules/@sveltejs/adapter-static": {
+ "version": "3.0.10",
+ "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.10.tgz",
+ "integrity": "sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@sveltejs/kit": "^2.0.0"
+ }
+ },
+ "node_modules/@sveltejs/kit": {
+ "version": "2.53.4",
+ "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.53.4.tgz",
+ "integrity": "sha512-iAIPEahFgDJJyvz8g0jP08KvqnM6JvdW8YfsygZ+pMeMvyM2zssWMltcsotETvjSZ82G3VlitgDtBIvpQSZrTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@standard-schema/spec": "^1.0.0",
+ "@sveltejs/acorn-typescript": "^1.0.5",
+ "@types/cookie": "^0.6.0",
+ "acorn": "^8.14.1",
+ "cookie": "^0.6.0",
+ "devalue": "^5.6.3",
+ "esm-env": "^1.2.2",
+ "kleur": "^4.1.5",
+ "magic-string": "^0.30.5",
+ "mrmime": "^2.0.0",
+ "set-cookie-parser": "^3.0.0",
+ "sirv": "^3.0.0"
+ },
+ "bin": {
+ "svelte-kit": "svelte-kit.js"
+ },
+ "engines": {
+ "node": ">=18.13"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0",
+ "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0",
+ "svelte": "^4.0.0 || ^5.0.0-next.0",
+ "typescript": "^5.3.3",
+ "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@sveltejs/vite-plugin-svelte": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-5.1.1.tgz",
+ "integrity": "sha512-Y1Cs7hhTc+a5E9Va/xwKlAJoariQyHY+5zBgCZg4PFWNYQ1nMN9sjK1zhw1gK69DuqVP++sht/1GZg1aRwmAXQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1",
+ "debug": "^4.4.1",
+ "deepmerge": "^4.3.1",
+ "kleur": "^4.1.5",
+ "magic-string": "^0.30.17",
+ "vitefu": "^1.0.6"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22"
+ },
+ "peerDependencies": {
+ "svelte": "^5.0.0",
+ "vite": "^6.0.0"
+ }
+ },
+ "node_modules/@sveltejs/vite-plugin-svelte-inspector": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-4.0.1.tgz",
+ "integrity": "sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.7"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22"
+ },
+ "peerDependencies": {
+ "@sveltejs/vite-plugin-svelte": "^5.0.0",
+ "svelte": "^5.0.0",
+ "vite": "^6.0.0"
+ }
+ },
+ "node_modules/@tauri-apps/api": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.10.1.tgz",
+ "integrity": "sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==",
+ "license": "Apache-2.0 OR MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/tauri"
+ }
+ },
+ "node_modules/@tauri-apps/cli": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.10.0.tgz",
+ "integrity": "sha512-ZwT0T+7bw4+DPCSWzmviwq5XbXlM0cNoleDKOYPFYqcZqeKY31KlpoMW/MOON/tOFBPgi31a2v3w9gliqwL2+Q==",
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "bin": {
+ "tauri": "tauri.js"
+ },
+ "engines": {
+ "node": ">= 10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/tauri"
+ },
+ "optionalDependencies": {
+ "@tauri-apps/cli-darwin-arm64": "2.10.0",
+ "@tauri-apps/cli-darwin-x64": "2.10.0",
+ "@tauri-apps/cli-linux-arm-gnueabihf": "2.10.0",
+ "@tauri-apps/cli-linux-arm64-gnu": "2.10.0",
+ "@tauri-apps/cli-linux-arm64-musl": "2.10.0",
+ "@tauri-apps/cli-linux-riscv64-gnu": "2.10.0",
+ "@tauri-apps/cli-linux-x64-gnu": "2.10.0",
+ "@tauri-apps/cli-linux-x64-musl": "2.10.0",
+ "@tauri-apps/cli-win32-arm64-msvc": "2.10.0",
+ "@tauri-apps/cli-win32-ia32-msvc": "2.10.0",
+ "@tauri-apps/cli-win32-x64-msvc": "2.10.0"
+ }
+ },
+ "node_modules/@tauri-apps/cli-darwin-arm64": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.10.0.tgz",
+ "integrity": "sha512-avqHD4HRjrMamE/7R/kzJPcAJnZs0IIS+1nkDP5b+TNBn3py7N2aIo9LIpy+VQq0AkN8G5dDpZtOOBkmWt/zjA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-darwin-x64": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.10.0.tgz",
+ "integrity": "sha512-keDmlvJRStzVFjZTd0xYkBONLtgBC9eMTpmXnBXzsHuawV2q9PvDo2x6D5mhuoMVrJ9QWjgaPKBBCFks4dK71Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.10.0.tgz",
+ "integrity": "sha512-e5u0VfLZsMAC9iHaOEANumgl6lfnJx0Dtjkd8IJpysZ8jp0tJ6wrIkto2OzQgzcYyRCKgX72aKE0PFgZputA8g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-linux-arm64-gnu": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.10.0.tgz",
+ "integrity": "sha512-YrYYk2dfmBs5m+OIMCrb+JH/oo+4FtlpcrTCgiFYc7vcs6m3QDd1TTyWu0u01ewsCtK2kOdluhr/zKku+KP7HA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-linux-arm64-musl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.10.0.tgz",
+ "integrity": "sha512-GUoPdVJmrJRIXFfW3Rkt+eGK9ygOdyISACZfC/bCSfOnGt8kNdQIQr5WRH9QUaTVFIwxMlQyV3m+yXYP+xhSVA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-linux-riscv64-gnu": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.10.0.tgz",
+ "integrity": "sha512-JO7s3TlSxshwsoKNCDkyvsx5gw2QAs/Y2GbR5UE2d5kkU138ATKoPOtxn8G1fFT1aDW4LH0rYAAfBpGkDyJJnw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-linux-x64-gnu": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.10.0.tgz",
+ "integrity": "sha512-Uvh4SUUp4A6DVRSMWjelww0GnZI3PlVy7VS+DRF5napKuIehVjGl9XD0uKoCoxwAQBLctvipyEK+pDXpJeoHng==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-linux-x64-musl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.10.0.tgz",
+ "integrity": "sha512-AP0KRK6bJuTpQ8kMNWvhIpKUkQJfcPFeba7QshOQZjJ8wOS6emwTN4K5g/d3AbCMo0RRdnZWwu67MlmtJyxC1Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-win32-arm64-msvc": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.10.0.tgz",
+ "integrity": "sha512-97DXVU3dJystrq7W41IX+82JEorLNY+3+ECYxvXWqkq7DBN6FsA08x/EFGE8N/b0LTOui9X2dvpGGoeZKKV08g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-win32-ia32-msvc": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.10.0.tgz",
+ "integrity": "sha512-EHyQ1iwrWy1CwMalEm9z2a6L5isQ121pe7FcA2xe4VWMJp+GHSDDGvbTv/OPdkt2Lyr7DAZBpZHM6nvlHXEc4A==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/cli-win32-x64-msvc": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.10.0.tgz",
+ "integrity": "sha512-NTpyQxkpzGmU6ceWBTY2xRIEaS0ZLbVx1HE1zTA3TY/pV3+cPoPPOs+7YScr4IMzXMtOw7tLw5LEXo5oIG3qaQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 OR MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tauri-apps/plugin-dialog": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.6.0.tgz",
+ "integrity": "sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==",
+ "license": "MIT OR Apache-2.0",
+ "dependencies": {
+ "@tauri-apps/api": "^2.8.0"
+ }
+ },
+ "node_modules/@tauri-apps/plugin-opener": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.3.tgz",
+ "integrity": "sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ==",
+ "license": "MIT OR Apache-2.0",
+ "dependencies": {
+ "@tauri-apps/api": "^2.8.0"
+ }
+ },
+ "node_modules/@types/cookie": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/acorn": {
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz",
+ "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/devalue": {
+ "version": "5.6.3",
+ "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.3.tgz",
+ "integrity": "sha512-nc7XjUU/2Lb+SvEFVGcWLiKkzfw8+qHI7zn8WYXKkLMgfGSHbgCEaR6bJpev8Cm6Rmrb19Gfd/tZvGqx9is3wg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/esbuild": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
+ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.12",
+ "@esbuild/android-arm": "0.25.12",
+ "@esbuild/android-arm64": "0.25.12",
+ "@esbuild/android-x64": "0.25.12",
+ "@esbuild/darwin-arm64": "0.25.12",
+ "@esbuild/darwin-x64": "0.25.12",
+ "@esbuild/freebsd-arm64": "0.25.12",
+ "@esbuild/freebsd-x64": "0.25.12",
+ "@esbuild/linux-arm": "0.25.12",
+ "@esbuild/linux-arm64": "0.25.12",
+ "@esbuild/linux-ia32": "0.25.12",
+ "@esbuild/linux-loong64": "0.25.12",
+ "@esbuild/linux-mips64el": "0.25.12",
+ "@esbuild/linux-ppc64": "0.25.12",
+ "@esbuild/linux-riscv64": "0.25.12",
+ "@esbuild/linux-s390x": "0.25.12",
+ "@esbuild/linux-x64": "0.25.12",
+ "@esbuild/netbsd-arm64": "0.25.12",
+ "@esbuild/netbsd-x64": "0.25.12",
+ "@esbuild/openbsd-arm64": "0.25.12",
+ "@esbuild/openbsd-x64": "0.25.12",
+ "@esbuild/openharmony-arm64": "0.25.12",
+ "@esbuild/sunos-x64": "0.25.12",
+ "@esbuild/win32-arm64": "0.25.12",
+ "@esbuild/win32-ia32": "0.25.12",
+ "@esbuild/win32-x64": "0.25.12"
+ }
+ },
+ "node_modules/esm-env": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
+ "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/esrap": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.3.tgz",
+ "integrity": "sha512-8fOS+GIGCQZl/ZIlhl59htOlms6U8NvX6ZYgYHpRU/b6tVSh3uHkOHZikl3D4cMbYM0JlpBe+p/BkZEi8J9XIQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.4.15"
+ }
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/is-reference": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
+ "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.6"
+ }
+ },
+ "node_modules/Journal.DevTool": {
+ "resolved": "Journal.DevTool",
+ "link": true
+ },
+ "node_modules/journalapp": {
+ "resolved": "Journal.App",
+ "link": true
+ },
+ "node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/locate-character": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
+ "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/mri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mrmime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
+ "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.8",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
+ "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz",
+ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-plugin-svelte": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.5.0.tgz",
+ "integrity": "sha512-2lLO/7EupnjO/95t+XZesXs8Bf3nYLIDfCo270h5QWbj/vjLqmrQ1LiRk9LPggxSDsnVYfehamZNf+rgQYApZg==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "prettier": "^3.0.0",
+ "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
+ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.18.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
+ "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.59.0",
+ "@rollup/rollup-android-arm64": "4.59.0",
+ "@rollup/rollup-darwin-arm64": "4.59.0",
+ "@rollup/rollup-darwin-x64": "4.59.0",
+ "@rollup/rollup-freebsd-arm64": "4.59.0",
+ "@rollup/rollup-freebsd-x64": "4.59.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.59.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.59.0",
+ "@rollup/rollup-linux-arm64-musl": "4.59.0",
+ "@rollup/rollup-linux-loong64-gnu": "4.59.0",
+ "@rollup/rollup-linux-loong64-musl": "4.59.0",
+ "@rollup/rollup-linux-ppc64-gnu": "4.59.0",
+ "@rollup/rollup-linux-ppc64-musl": "4.59.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.59.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.59.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.59.0",
+ "@rollup/rollup-linux-x64-gnu": "4.59.0",
+ "@rollup/rollup-linux-x64-musl": "4.59.0",
+ "@rollup/rollup-openbsd-x64": "4.59.0",
+ "@rollup/rollup-openharmony-arm64": "4.59.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.59.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.59.0",
+ "@rollup/rollup-win32-x64-gnu": "4.59.0",
+ "@rollup/rollup-win32-x64-msvc": "4.59.0",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/sade": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
+ "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mri": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/set-cookie-parser": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.0.1.tgz",
+ "integrity": "sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/sirv": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz",
+ "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@polka/url": "^1.0.0-next.24",
+ "mrmime": "^2.0.0",
+ "totalist": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/svelte": {
+ "version": "5.53.6",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.53.6.tgz",
+ "integrity": "sha512-lP5DGF3oDDI9fhHcSpaBiJEkFLuS16h92DhM1L5K1lFm0WjOmUh1i2sNkBBk8rkxJRpob0dBE75jRfUzGZUOGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/remapping": "^2.3.4",
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@sveltejs/acorn-typescript": "^1.0.5",
+ "@types/estree": "^1.0.5",
+ "@types/trusted-types": "^2.0.7",
+ "acorn": "^8.12.1",
+ "aria-query": "5.3.1",
+ "axobject-query": "^4.1.0",
+ "clsx": "^2.1.1",
+ "devalue": "^5.6.3",
+ "esm-env": "^1.2.1",
+ "esrap": "^2.2.2",
+ "is-reference": "^3.0.3",
+ "locate-character": "^3.0.0",
+ "magic-string": "^0.30.11",
+ "zimmerframe": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/svelte-check": {
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.4.4.tgz",
+ "integrity": "sha512-F1pGqXc710Oi/wTI4d/x7d6lgPwwfx1U6w3Q35n4xsC2e8C/yN2sM1+mWxjlMcpAfWucjlq4vPi+P4FZ8a14sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "chokidar": "^4.0.1",
+ "fdir": "^6.2.0",
+ "picocolors": "^1.0.0",
+ "sade": "^1.7.4"
+ },
+ "bin": {
+ "svelte-check": "bin/svelte-check"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ },
+ "peerDependencies": {
+ "svelte": "^4.0.0 || ^5.0.0-next.0",
+ "typescript": ">=5.0.0"
+ }
+ },
+ "node_modules/tauri-plugin-mic-recorder-api": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/tauri-plugin-mic-recorder-api/-/tauri-plugin-mic-recorder-api-2.0.0.tgz",
+ "integrity": "sha512-04wqYCX4WIlYd6KUY7aS3+W4B5RtnSoVczaQCBSXKpQkEx9XdaaBN05XCee2unxGva0btSXBItFqQSdosnS4jQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@tauri-apps/api": ">=2.0.0-beta.6"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/totalist": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
+ "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.6.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
+ "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/vite": {
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
+ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.25.0",
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2",
+ "postcss": "^8.5.3",
+ "rollup": "^4.34.9",
+ "tinyglobby": "^0.2.13"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "jiti": ">=1.21.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vitefu": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.2.tgz",
+ "integrity": "sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw==",
+ "dev": true,
+ "license": "MIT",
+ "workspaces": [
+ "tests/deps/*",
+ "tests/projects/*",
+ "tests/projects/workspace/packages/*"
+ ],
+ "peerDependencies": {
+ "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0"
+ },
+ "peerDependenciesMeta": {
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/zimmerframe": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz",
+ "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==",
+ "dev": true,
+ "license": "MIT"
+ }
+ }
}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..470bab3
--- /dev/null
+++ b/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "journal",
+ "private": true,
+ "workspaces": [
+ "Journal.App"
+ ]
+}
\ No newline at end of file