feat(*): Add AI agent feedback

This commit is contained in:
Josh Creek
2025-04-20 23:05:17 +01:00
parent 010a1b8e2b
commit 98ff117f73
8 changed files with 658 additions and 97 deletions
+4 -11
View File
@@ -1,11 +1,4 @@
# Example .env file for Automated Assessment Feedback Agent AI_FOUNDRY_PROJECT_CONNECTION_STRING=
# Copy this file to .env and fill in your Azure OpenAI credentials BING_GROUNDING_CONNECTION_ID=
AI_SEARCH_CONNECTION_ID=
# Your Azure OpenAI API key AI_MODEL=gpt-4o
AZURE_OPENAI_API_KEY=your-azure-openai-key-here
# Your Azure OpenAI endpoint (e.g., https://your-resource-name.openai.azure.com)
AZURE_OPENAI_ENDPOINT=https://your-resource-name.openai.azure.com
# The deployment name for your model (e.g., gpt-4, gpt-35-turbo)
AZURE_OPENAI_DEPLOYMENT=gpt-4
+6 -1
View File
@@ -21,6 +21,7 @@
"@sveltejs/vite-plugin-svelte": "^5.0.0", "@sveltejs/vite-plugin-svelte": "^5.0.0",
"@tailwindcss/typography": "^0.5.15", "@tailwindcss/typography": "^0.5.15",
"@tailwindcss/vite": "^4.0.0", "@tailwindcss/vite": "^4.0.0",
"@types/node": "^22.14.1",
"eslint": "^9.18.0", "eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1", "eslint-config-prettier": "^10.0.1",
"eslint-plugin-svelte": "^3.0.0", "eslint-plugin-svelte": "^3.0.0",
@@ -40,5 +41,9 @@
"esbuild" "esbuild"
] ]
}, },
"packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0" "packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0",
"dependencies": {
"@azure/ai-projects": "1.0.0-beta.4",
"@azure/identity": "^4.9.0"
}
} }
+417 -22
View File
@@ -7,6 +7,13 @@ settings:
importers: importers:
.: .:
dependencies:
'@azure/ai-projects':
specifier: 1.0.0-beta.4
version: 1.0.0-beta.4
'@azure/identity':
specifier: ^4.9.0
version: 4.9.0
devDependencies: devDependencies:
'@eslint/compat': '@eslint/compat':
specifier: ^1.2.5 specifier: ^1.2.5
@@ -16,19 +23,22 @@ importers:
version: 9.24.0 version: 9.24.0
'@sveltejs/adapter-auto': '@sveltejs/adapter-auto':
specifier: ^4.0.0 specifier: ^4.0.0
version: 4.0.0(@sveltejs/kit@2.20.7(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2))) version: 4.0.0(@sveltejs/kit@2.20.7(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)))
'@sveltejs/kit': '@sveltejs/kit':
specifier: ^2.16.0 specifier: ^2.16.0
version: 2.20.7(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)) version: 2.20.7(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2))
'@sveltejs/vite-plugin-svelte': '@sveltejs/vite-plugin-svelte':
specifier: ^5.0.0 specifier: ^5.0.0
version: 5.0.3(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)) version: 5.0.3(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2))
'@tailwindcss/typography': '@tailwindcss/typography':
specifier: ^0.5.15 specifier: ^0.5.15
version: 0.5.16(tailwindcss@4.1.4) version: 0.5.16(tailwindcss@4.1.4)
'@tailwindcss/vite': '@tailwindcss/vite':
specifier: ^4.0.0 specifier: ^4.0.0
version: 4.1.4(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)) version: 4.1.4(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2))
'@types/node':
specifier: ^22.14.1
version: 22.14.1
eslint: eslint:
specifier: ^9.18.0 specifier: ^9.18.0
version: 9.24.0(jiti@2.4.2) version: 9.24.0(jiti@2.4.2)
@@ -67,7 +77,7 @@ importers:
version: 8.30.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.8.3) version: 8.30.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.8.3)
vite: vite:
specifier: ^6.2.5 specifier: ^6.2.5
version: 6.3.0(jiti@2.4.2)(lightningcss@1.29.2) version: 6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)
packages: packages:
@@ -75,6 +85,70 @@ packages:
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
'@azure-rest/core-client@2.3.5':
resolution: {integrity: sha512-vC8sDkT1xH7jx9erJWQqznMhfPY9k+mrM+4R/rAeb+F+KQCohYYmOEAQmT9CEQxStJ3erjbtpN3GMjAS5tdiYg==}
engines: {node: '>=18.0.0'}
'@azure/abort-controller@2.1.2':
resolution: {integrity: sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==}
engines: {node: '>=18.0.0'}
'@azure/ai-projects@1.0.0-beta.4':
resolution: {integrity: sha512-+sRwbmNVQd/2atMF9lyfeIIhk7f0POyFiTUvdtiqRfqO6oeVOD4VhA3UaAFITD1JOIeAmRe4l+BwdX1Xy9FGzQ==}
engines: {node: '>=18.0.0'}
'@azure/core-auth@1.9.0':
resolution: {integrity: sha512-FPwHpZywuyasDSLMqJ6fhbOK3TqUdviZNF8OqRGA4W5Ewib2lEEZ+pBsYcBa88B2NGO/SEnYPGhyBqNlE8ilSw==}
engines: {node: '>=18.0.0'}
'@azure/core-client@1.9.3':
resolution: {integrity: sha512-/wGw8fJ4mdpJ1Cum7s1S+VQyXt1ihwKLzfabS1O/RDADnmzVc01dHn44qD0BvGH6KlZNzOMW95tEpKqhkCChPA==}
engines: {node: '>=18.0.0'}
'@azure/core-lro@3.2.0':
resolution: {integrity: sha512-SJEAe8fMDnjz2vw9dvEUi0DhAWe1sYkWQVTDc/HDcgNALaszGRopx3U+z1Pg/C9fsYiArp5pTBEcq29Ddph0WA==}
engines: {node: '>=18.0.0'}
'@azure/core-paging@1.6.2':
resolution: {integrity: sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==}
engines: {node: '>=18.0.0'}
'@azure/core-rest-pipeline@1.19.1':
resolution: {integrity: sha512-zHeoI3NCs53lLBbWNzQycjnYKsA1CVKlnzSNuSFcUDwBp8HHVObePxrM7HaX+Ha5Ks639H7chNC9HOaIhNS03w==}
engines: {node: '>=18.0.0'}
'@azure/core-sse@2.2.0':
resolution: {integrity: sha512-6Xg/CeW0jRyMoWt+puw2x6Qqkml3tr76Cn/oA9goIcUXtsi3ngmTwCVbwqkUWfhsOfo4F+78LGgiswSxTHN0sg==}
engines: {node: '>=18.0.0'}
'@azure/core-tracing@1.2.0':
resolution: {integrity: sha512-UKTiEJPkWcESPYJz3X5uKRYyOcJD+4nYph+KpfdPRnQJVrZfk0KJgdnaAWKfhsBBtAf/D58Az4AvCJEmWgIBAg==}
engines: {node: '>=18.0.0'}
'@azure/core-util@1.11.0':
resolution: {integrity: sha512-DxOSLua+NdpWoSqULhjDyAZTXFdP/LKkqtYuxxz1SCN289zk3OG8UOpnCQAz/tygyACBtWp/BoO72ptK7msY8g==}
engines: {node: '>=18.0.0'}
'@azure/identity@4.9.0':
resolution: {integrity: sha512-dz2ZvKxDFoTUmJgmkCBVcyuKckgqE1qVxrRPzUhyKN7FyvUbtNPUrGzqSllOAf1OL9TMGgYqZWbIyD0b/AE15g==}
engines: {node: '>=18.0.0'}
'@azure/logger@1.1.4':
resolution: {integrity: sha512-4IXXzcCdLdlXuCG+8UKEwLA1T1NHqUfanhXYHiQTn+6sfWCZXduqbtXDGceg3Ce5QxTGo7EqmbV6Bi+aqKuClQ==}
engines: {node: '>=18.0.0'}
'@azure/msal-browser@4.11.0':
resolution: {integrity: sha512-0p5Ut3wORMP+975AKvaSPIO4UytgsfAvJ7RxaTx+nkP+Hpkmm93AuiMkBWKI2x9tApU/SLgIyPz/ZwLYUIWb5Q==}
engines: {node: '>=0.8.0'}
'@azure/msal-common@15.5.1':
resolution: {integrity: sha512-oxK0khbc4Bg1bKQnqDr7ikULhVL2OHgSrIq0Vlh4b6+hm4r0lr6zPMQE8ZvmacJuh+ZZGKBM5iIObhF1q1QimQ==}
engines: {node: '>=0.8.0'}
'@azure/msal-node@3.5.1':
resolution: {integrity: sha512-dkgMYM5B6tI88r/oqf5bYd93WkenQpaWwiszJDk7avVjso8cmuKRTW97dA1RMi6RhihZFLtY1VtWxU9+sW2T5g==}
engines: {node: '>=16'}
'@esbuild/aix-ppc64@0.25.2': '@esbuild/aix-ppc64@0.25.2':
resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==}
engines: {node: '>=18'} engines: {node: '>=18'}
@@ -567,6 +641,9 @@ packages:
'@types/json-schema@7.0.15': '@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
'@types/node@22.14.1':
resolution: {integrity: sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==}
'@typescript-eslint/eslint-plugin@8.30.1': '@typescript-eslint/eslint-plugin@8.30.1':
resolution: {integrity: sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==} resolution: {integrity: sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -624,6 +701,10 @@ packages:
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
hasBin: true hasBin: true
agent-base@7.1.3:
resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==}
engines: {node: '>= 14'}
ajv@6.12.6: ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
@@ -655,6 +736,13 @@ packages:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'} engines: {node: '>=8'}
buffer-equal-constant-time@1.0.1:
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
bundle-name@4.1.0:
resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
engines: {node: '>=18'}
callsites@3.1.0: callsites@3.1.0:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -710,6 +798,18 @@ packages:
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
default-browser-id@5.0.0:
resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==}
engines: {node: '>=18'}
default-browser@5.2.1:
resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==}
engines: {node: '>=18'}
define-lazy-prop@3.0.0:
resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
engines: {node: '>=12'}
detect-libc@2.0.3: detect-libc@2.0.3:
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -717,6 +817,9 @@ packages:
devalue@5.1.1: devalue@5.1.1:
resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==} resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==}
ecdsa-sig-formatter@1.0.11:
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
enhanced-resolve@5.18.1: enhanced-resolve@5.18.1:
resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==}
engines: {node: '>=10.13.0'} engines: {node: '>=10.13.0'}
@@ -868,6 +971,14 @@ packages:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
http-proxy-agent@7.0.2:
resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
engines: {node: '>= 14'}
https-proxy-agent@7.0.6:
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
engines: {node: '>= 14'}
ignore@5.3.2: ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'} engines: {node: '>= 4'}
@@ -883,6 +994,11 @@ packages:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'} engines: {node: '>=0.8.19'}
is-docker@3.0.0:
resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
hasBin: true
is-extglob@2.1.1: is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -891,6 +1007,11 @@ packages:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
is-inside-container@1.0.0:
resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
engines: {node: '>=14.16'}
hasBin: true
is-number@7.0.0: is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'} engines: {node: '>=0.12.0'}
@@ -898,6 +1019,10 @@ packages:
is-reference@3.0.3: is-reference@3.0.3:
resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==}
is-wsl@3.1.0:
resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==}
engines: {node: '>=16'}
isexe@2.0.0: isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
@@ -918,6 +1043,16 @@ packages:
json-stable-stringify-without-jsonify@1.0.1: json-stable-stringify-without-jsonify@1.0.1:
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
jsonwebtoken@9.0.2:
resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
engines: {node: '>=12', npm: '>=6'}
jwa@1.4.1:
resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==}
jws@3.2.2:
resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==}
keyv@4.5.4: keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
@@ -1010,12 +1145,30 @@ packages:
lodash.castarray@4.4.0: lodash.castarray@4.4.0:
resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==}
lodash.includes@4.3.0:
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
lodash.isboolean@3.0.3:
resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
lodash.isinteger@4.0.4:
resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
lodash.isnumber@3.0.3:
resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
lodash.isplainobject@4.0.6: lodash.isplainobject@4.0.6:
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
lodash.isstring@4.0.1:
resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
lodash.merge@4.6.2: lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
lodash.once@4.1.1:
resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
magic-string@0.30.17: magic-string@0.30.17:
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
@@ -1053,6 +1206,10 @@ packages:
natural-compare@1.4.0: natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
open@10.1.1:
resolution: {integrity: sha512-zy1wx4+P3PfhXSEPJNtZmJXfhkkIaxU1VauWIrDZw1O7uJRDRJtKr9n3Ic4NgbA16KyOxOXO2ng9gYwCdXuSXA==}
engines: {node: '>=18'}
optionator@0.9.4: optionator@0.9.4:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
@@ -1218,6 +1375,10 @@ packages:
engines: {node: '>=18.0.0', npm: '>=8.0.0'} engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true hasBin: true
run-applescript@7.0.0:
resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==}
engines: {node: '>=18'}
run-parallel@1.2.0: run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
@@ -1225,6 +1386,9 @@ packages:
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
engines: {node: '>=6'} engines: {node: '>=6'}
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
semver@7.7.1: semver@7.7.1:
resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==}
engines: {node: '>=10'} engines: {node: '>=10'}
@@ -1303,6 +1467,9 @@ packages:
peerDependencies: peerDependencies:
typescript: '>=4.8.4' typescript: '>=4.8.4'
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
type-check@0.4.0: type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
@@ -1319,12 +1486,19 @@ packages:
engines: {node: '>=14.17'} engines: {node: '>=14.17'}
hasBin: true hasBin: true
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
uri-js@4.4.1: uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
util-deprecate@1.0.2: util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
uuid@8.3.2:
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
hasBin: true
vite@6.3.0: vite@6.3.0:
resolution: {integrity: sha512-9aC0n4pr6hIbvi1YOpFjwQ+QOTGssvbJKoeYkuHHGWwlXfdxQlI8L2qNMo9awEEcCPSiS+5mJZk5jH1PAqoDeQ==} resolution: {integrity: sha512-9aC0n4pr6hIbvi1YOpFjwQ+QOTGssvbJKoeYkuHHGWwlXfdxQlI8L2qNMo9awEEcCPSiS+5mJZk5jH1PAqoDeQ==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -1400,6 +1574,124 @@ snapshots:
'@jridgewell/gen-mapping': 0.3.8 '@jridgewell/gen-mapping': 0.3.8
'@jridgewell/trace-mapping': 0.3.25 '@jridgewell/trace-mapping': 0.3.25
'@azure-rest/core-client@2.3.5':
dependencies:
'@azure/abort-controller': 2.1.2
'@azure/core-auth': 1.9.0
'@azure/core-rest-pipeline': 1.19.1
'@azure/core-tracing': 1.2.0
'@azure/core-util': 1.11.0
tslib: 2.8.1
transitivePeerDependencies:
- supports-color
'@azure/abort-controller@2.1.2':
dependencies:
tslib: 2.8.1
'@azure/ai-projects@1.0.0-beta.4':
dependencies:
'@azure-rest/core-client': 2.3.5
'@azure/abort-controller': 2.1.2
'@azure/core-auth': 1.9.0
'@azure/core-lro': 3.2.0
'@azure/core-paging': 1.6.2
'@azure/core-rest-pipeline': 1.19.1
'@azure/core-sse': 2.2.0
'@azure/core-tracing': 1.2.0
'@azure/core-util': 1.11.0
'@azure/logger': 1.1.4
tslib: 2.8.1
transitivePeerDependencies:
- supports-color
'@azure/core-auth@1.9.0':
dependencies:
'@azure/abort-controller': 2.1.2
'@azure/core-util': 1.11.0
tslib: 2.8.1
'@azure/core-client@1.9.3':
dependencies:
'@azure/abort-controller': 2.1.2
'@azure/core-auth': 1.9.0
'@azure/core-rest-pipeline': 1.19.1
'@azure/core-tracing': 1.2.0
'@azure/core-util': 1.11.0
'@azure/logger': 1.1.4
tslib: 2.8.1
transitivePeerDependencies:
- supports-color
'@azure/core-lro@3.2.0':
dependencies:
'@azure/abort-controller': 2.1.2
'@azure/core-util': 1.11.0
'@azure/logger': 1.1.4
tslib: 2.8.1
'@azure/core-paging@1.6.2':
dependencies:
tslib: 2.8.1
'@azure/core-rest-pipeline@1.19.1':
dependencies:
'@azure/abort-controller': 2.1.2
'@azure/core-auth': 1.9.0
'@azure/core-tracing': 1.2.0
'@azure/core-util': 1.11.0
'@azure/logger': 1.1.4
http-proxy-agent: 7.0.2
https-proxy-agent: 7.0.6
tslib: 2.8.1
transitivePeerDependencies:
- supports-color
'@azure/core-sse@2.2.0':
dependencies:
tslib: 2.8.1
'@azure/core-tracing@1.2.0':
dependencies:
tslib: 2.8.1
'@azure/core-util@1.11.0':
dependencies:
'@azure/abort-controller': 2.1.2
tslib: 2.8.1
'@azure/identity@4.9.0':
dependencies:
'@azure/abort-controller': 2.1.2
'@azure/core-auth': 1.9.0
'@azure/core-client': 1.9.3
'@azure/core-rest-pipeline': 1.19.1
'@azure/core-tracing': 1.2.0
'@azure/core-util': 1.11.0
'@azure/logger': 1.1.4
'@azure/msal-browser': 4.11.0
'@azure/msal-node': 3.5.1
open: 10.1.1
tslib: 2.8.1
transitivePeerDependencies:
- supports-color
'@azure/logger@1.1.4':
dependencies:
tslib: 2.8.1
'@azure/msal-browser@4.11.0':
dependencies:
'@azure/msal-common': 15.5.1
'@azure/msal-common@15.5.1': {}
'@azure/msal-node@3.5.1':
dependencies:
'@azure/msal-common': 15.5.1
jsonwebtoken: 9.0.2
uuid: 8.3.2
'@esbuild/aix-ppc64@0.25.2': '@esbuild/aix-ppc64@0.25.2':
optional: true optional: true
@@ -1635,14 +1927,14 @@ snapshots:
dependencies: dependencies:
acorn: 8.14.1 acorn: 8.14.1
'@sveltejs/adapter-auto@4.0.0(@sveltejs/kit@2.20.7(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)))': '@sveltejs/adapter-auto@4.0.0(@sveltejs/kit@2.20.7(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)))':
dependencies: dependencies:
'@sveltejs/kit': 2.20.7(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)) '@sveltejs/kit': 2.20.7(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2))
import-meta-resolve: 4.1.0 import-meta-resolve: 4.1.0
'@sveltejs/kit@2.20.7(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2))': '@sveltejs/kit@2.20.7(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2))':
dependencies: dependencies:
'@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)) '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2))
'@types/cookie': 0.6.0 '@types/cookie': 0.6.0
cookie: 0.6.0 cookie: 0.6.0
devalue: 5.1.1 devalue: 5.1.1
@@ -1655,27 +1947,27 @@ snapshots:
set-cookie-parser: 2.7.1 set-cookie-parser: 2.7.1
sirv: 3.0.1 sirv: 3.0.1
svelte: 5.27.0 svelte: 5.27.0
vite: 6.3.0(jiti@2.4.2)(lightningcss@1.29.2) vite: 6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)
'@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2))': '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2))':
dependencies: dependencies:
'@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)) '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2))
debug: 4.4.0 debug: 4.4.0
svelte: 5.27.0 svelte: 5.27.0
vite: 6.3.0(jiti@2.4.2)(lightningcss@1.29.2) vite: 6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2))': '@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2))':
dependencies: dependencies:
'@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)) '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.27.0)(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2))
debug: 4.4.0 debug: 4.4.0
deepmerge: 4.3.1 deepmerge: 4.3.1
kleur: 4.1.5 kleur: 4.1.5
magic-string: 0.30.17 magic-string: 0.30.17
svelte: 5.27.0 svelte: 5.27.0
vite: 6.3.0(jiti@2.4.2)(lightningcss@1.29.2) vite: 6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)
vitefu: 1.0.6(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)) vitefu: 1.0.6(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2))
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@@ -1745,12 +2037,12 @@ snapshots:
postcss-selector-parser: 6.0.10 postcss-selector-parser: 6.0.10
tailwindcss: 4.1.4 tailwindcss: 4.1.4
'@tailwindcss/vite@4.1.4(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2))': '@tailwindcss/vite@4.1.4(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2))':
dependencies: dependencies:
'@tailwindcss/node': 4.1.4 '@tailwindcss/node': 4.1.4
'@tailwindcss/oxide': 4.1.4 '@tailwindcss/oxide': 4.1.4
tailwindcss: 4.1.4 tailwindcss: 4.1.4
vite: 6.3.0(jiti@2.4.2)(lightningcss@1.29.2) vite: 6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)
'@types/cookie@0.6.0': {} '@types/cookie@0.6.0': {}
@@ -1758,6 +2050,10 @@ snapshots:
'@types/json-schema@7.0.15': {} '@types/json-schema@7.0.15': {}
'@types/node@22.14.1':
dependencies:
undici-types: 6.21.0
'@typescript-eslint/eslint-plugin@8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.8.3)': '@typescript-eslint/eslint-plugin@8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies: dependencies:
'@eslint-community/regexpp': 4.12.1 '@eslint-community/regexpp': 4.12.1
@@ -1841,6 +2137,8 @@ snapshots:
acorn@8.14.1: {} acorn@8.14.1: {}
agent-base@7.1.3: {}
ajv@6.12.6: ajv@6.12.6:
dependencies: dependencies:
fast-deep-equal: 3.1.3 fast-deep-equal: 3.1.3
@@ -1873,6 +2171,12 @@ snapshots:
dependencies: dependencies:
fill-range: 7.1.1 fill-range: 7.1.1
buffer-equal-constant-time@1.0.1: {}
bundle-name@4.1.0:
dependencies:
run-applescript: 7.0.0
callsites@3.1.0: {} callsites@3.1.0: {}
chalk@4.1.2: chalk@4.1.2:
@@ -1912,10 +2216,23 @@ snapshots:
deepmerge@4.3.1: {} deepmerge@4.3.1: {}
default-browser-id@5.0.0: {}
default-browser@5.2.1:
dependencies:
bundle-name: 4.1.0
default-browser-id: 5.0.0
define-lazy-prop@3.0.0: {}
detect-libc@2.0.3: {} detect-libc@2.0.3: {}
devalue@5.1.1: {} devalue@5.1.1: {}
ecdsa-sig-formatter@1.0.11:
dependencies:
safe-buffer: 5.2.1
enhanced-resolve@5.18.1: enhanced-resolve@5.18.1:
dependencies: dependencies:
graceful-fs: 4.2.11 graceful-fs: 4.2.11
@@ -2110,6 +2427,20 @@ snapshots:
has-flag@4.0.0: {} has-flag@4.0.0: {}
http-proxy-agent@7.0.2:
dependencies:
agent-base: 7.1.3
debug: 4.4.0
transitivePeerDependencies:
- supports-color
https-proxy-agent@7.0.6:
dependencies:
agent-base: 7.1.3
debug: 4.4.0
transitivePeerDependencies:
- supports-color
ignore@5.3.2: {} ignore@5.3.2: {}
import-fresh@3.3.1: import-fresh@3.3.1:
@@ -2121,18 +2452,28 @@ snapshots:
imurmurhash@0.1.4: {} imurmurhash@0.1.4: {}
is-docker@3.0.0: {}
is-extglob@2.1.1: {} is-extglob@2.1.1: {}
is-glob@4.0.3: is-glob@4.0.3:
dependencies: dependencies:
is-extglob: 2.1.1 is-extglob: 2.1.1
is-inside-container@1.0.0:
dependencies:
is-docker: 3.0.0
is-number@7.0.0: {} is-number@7.0.0: {}
is-reference@3.0.3: is-reference@3.0.3:
dependencies: dependencies:
'@types/estree': 1.0.7 '@types/estree': 1.0.7
is-wsl@3.1.0:
dependencies:
is-inside-container: 1.0.0
isexe@2.0.0: {} isexe@2.0.0: {}
jiti@2.4.2: {} jiti@2.4.2: {}
@@ -2147,6 +2488,30 @@ snapshots:
json-stable-stringify-without-jsonify@1.0.1: {} json-stable-stringify-without-jsonify@1.0.1: {}
jsonwebtoken@9.0.2:
dependencies:
jws: 3.2.2
lodash.includes: 4.3.0
lodash.isboolean: 3.0.3
lodash.isinteger: 4.0.4
lodash.isnumber: 3.0.3
lodash.isplainobject: 4.0.6
lodash.isstring: 4.0.1
lodash.once: 4.1.1
ms: 2.1.3
semver: 7.7.1
jwa@1.4.1:
dependencies:
buffer-equal-constant-time: 1.0.1
ecdsa-sig-formatter: 1.0.11
safe-buffer: 5.2.1
jws@3.2.2:
dependencies:
jwa: 1.4.1
safe-buffer: 5.2.1
keyv@4.5.4: keyv@4.5.4:
dependencies: dependencies:
json-buffer: 3.0.1 json-buffer: 3.0.1
@@ -2215,10 +2580,22 @@ snapshots:
lodash.castarray@4.4.0: {} lodash.castarray@4.4.0: {}
lodash.includes@4.3.0: {}
lodash.isboolean@3.0.3: {}
lodash.isinteger@4.0.4: {}
lodash.isnumber@3.0.3: {}
lodash.isplainobject@4.0.6: {} lodash.isplainobject@4.0.6: {}
lodash.isstring@4.0.1: {}
lodash.merge@4.6.2: {} lodash.merge@4.6.2: {}
lodash.once@4.1.1: {}
magic-string@0.30.17: magic-string@0.30.17:
dependencies: dependencies:
'@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/sourcemap-codec': 1.5.0
@@ -2248,6 +2625,13 @@ snapshots:
natural-compare@1.4.0: {} natural-compare@1.4.0: {}
open@10.1.1:
dependencies:
default-browser: 5.2.1
define-lazy-prop: 3.0.0
is-inside-container: 1.0.0
is-wsl: 3.1.0
optionator@0.9.4: optionator@0.9.4:
dependencies: dependencies:
deep-is: 0.1.4 deep-is: 0.1.4
@@ -2361,6 +2745,8 @@ snapshots:
'@rollup/rollup-win32-x64-msvc': 4.40.0 '@rollup/rollup-win32-x64-msvc': 4.40.0
fsevents: 2.3.3 fsevents: 2.3.3
run-applescript@7.0.0: {}
run-parallel@1.2.0: run-parallel@1.2.0:
dependencies: dependencies:
queue-microtask: 1.2.3 queue-microtask: 1.2.3
@@ -2369,6 +2755,8 @@ snapshots:
dependencies: dependencies:
mri: 1.2.0 mri: 1.2.0
safe-buffer@5.2.1: {}
semver@7.7.1: {} semver@7.7.1: {}
set-cookie-parser@2.7.1: {} set-cookie-parser@2.7.1: {}
@@ -2452,6 +2840,8 @@ snapshots:
dependencies: dependencies:
typescript: 5.8.3 typescript: 5.8.3
tslib@2.8.1: {}
type-check@0.4.0: type-check@0.4.0:
dependencies: dependencies:
prelude-ls: 1.2.1 prelude-ls: 1.2.1
@@ -2468,13 +2858,17 @@ snapshots:
typescript@5.8.3: {} typescript@5.8.3: {}
undici-types@6.21.0: {}
uri-js@4.4.1: uri-js@4.4.1:
dependencies: dependencies:
punycode: 2.3.1 punycode: 2.3.1
util-deprecate@1.0.2: {} util-deprecate@1.0.2: {}
vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2): uuid@8.3.2: {}
vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2):
dependencies: dependencies:
esbuild: 0.25.2 esbuild: 0.25.2
fdir: 6.4.3(picomatch@4.0.2) fdir: 6.4.3(picomatch@4.0.2)
@@ -2483,13 +2877,14 @@ snapshots:
rollup: 4.40.0 rollup: 4.40.0
tinyglobby: 0.2.12 tinyglobby: 0.2.12
optionalDependencies: optionalDependencies:
'@types/node': 22.14.1
fsevents: 2.3.3 fsevents: 2.3.3
jiti: 2.4.2 jiti: 2.4.2
lightningcss: 1.29.2 lightningcss: 1.29.2
vitefu@1.0.6(vite@6.3.0(jiti@2.4.2)(lightningcss@1.29.2)): vitefu@1.0.6(vite@6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)):
optionalDependencies: optionalDependencies:
vite: 6.3.0(jiti@2.4.2)(lightningcss@1.29.2) vite: 6.3.0(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)
which@2.0.2: which@2.0.2:
dependencies: dependencies:
+47
View File
@@ -0,0 +1,47 @@
import { DefaultAzureCredential } from '@azure/identity';
import { AIProjectsClient } from '@azure/ai-projects';
import { rubricMatcherTool } from '../tools/rubricMatcherTool';
import { essayAnalyzerTool } from '../tools/essayAnalyzerTool';
import { ToolUtility } from '@azure/ai-projects';
import { AI_FOUNDRY_PROJECT_CONNECTION_STRING, AI_MODEL } from '$env/static/private';
const connectionString = AI_FOUNDRY_PROJECT_CONNECTION_STRING;
if (!connectionString) {
throw new Error('AI_FOUNDRY_PROJECT_CONNECTION_STRING is not set in environment variables');
}
const aiModel = AI_MODEL || '';
if (!connectionString) {
throw new Error('AI_MODEL is not set in environment variables');
}
const client = AIProjectsClient.fromConnectionString(
connectionString,
new DefaultAzureCredential()
);
const codeInterpreterTool = ToolUtility.createCodeInterpreterTool([]);
const tools = [codeInterpreterTool.definition, rubricMatcherTool.definition, essayAnalyzerTool.definition];
const instructions = "You are a helpful agent that can assist with providing feedback on a student's work for a teacher.";
const toolResources = {
...codeInterpreterTool.resources,
matchRubric: {},
analyzeEssay: {}
};
const agent = await client.agents.createAgent(aiModel, {
name: `agent-assessment-feedback`,
instructions,
temperature: 0.5,
tools,
toolResources,
requestOptions: {
headers: { "x-ms-enable-preview": "true" },
},
});
export { client, agent };
+13
View File
@@ -0,0 +1,13 @@
import { ToolUtility } from '@azure/ai-projects';
export const essayAnalyzerTool = ToolUtility.createFunctionTool({
name: 'analyzeEssay',
description: 'Analyzes an essay for structure, argument, and evidence.',
parameters: {
type: 'object',
properties: {
essay: { type: 'string', description: 'The essay text' }
},
required: ['essay']
}
});
+14
View File
@@ -0,0 +1,14 @@
import { ToolUtility } from '@azure/ai-projects';
export const rubricMatcherTool = ToolUtility.createFunctionTool({
name: 'matchRubric',
description: 'Matches a submission to a rubric and returns a score/criteria breakdown.',
parameters: {
type: 'object',
properties: {
submission: { type: 'string', description: 'The student submission text' },
rubric: { type: 'string', description: 'The rubric criteria' }
},
required: ['submission', 'rubric']
}
});
+154 -60
View File
@@ -1,4 +1,5 @@
import type { OpenAIResponse } from './types'; import { client, agent } from '../agent/services/agentService';
import type { MessageTextContentOutput, ToolOutput } from '@azure/ai-projects';
const OPENAI_API_KEY = process.env['AZURE_OPENAI_API_KEY']; const OPENAI_API_KEY = process.env['AZURE_OPENAI_API_KEY'];
const OPENAI_ENDPOINT = process.env['AZURE_OPENAI_ENDPOINT']; const OPENAI_ENDPOINT = process.env['AZURE_OPENAI_ENDPOINT'];
@@ -26,69 +27,162 @@ Follow these steps:
6. Suggest to the teacher one way to support this student in the next lesson. 6. Suggest to the teacher one way to support this student in the next lesson.
7. Show your reasoning step by step (chain-of-thought). 7. Show your reasoning step by step (chain-of-thought).
RESPONSE FORMAT: RESPONSE FORMAT (respond with a single JSON object, no extra text):
Grade: <number>/10
Strengths: <text> {
Areas for Improvement: <text> "grade": "<number or string, e.g. 8/10 or 8>",
Individualized Activity: <text> "strengths": "<text>",
Reflection Question: <text> "areas_for_improvement": "<text>",
Teacher Suggestion: <text> "individualized_activity": "<text>",
Reasoning: <step-by-step explanation>`; "reflection_question": "<text>",
"teacher_suggestion": "<text>",
"reasoning": "<step-by-step explanation>"
} }
export async function gradeWithOpenAI(submission: string, task: string): Promise<OpenAIResponse> { Respond ONLY with the JSON object, with no preamble or explanation.
if (!OPENAI_API_KEY || !OPENAI_ENDPOINT) { `;
// Fallback for local/demo mode }
return {
grade: '7/10',
strengths: 'Clear argument and good evidence (in response to the task: ' + task + ").",
areas_for_improvement: 'Needs deeper analysis and more examples.',
individualized_activity: 'Write a paragraph expanding on your main point and provide two additional examples to support your argument.',
reflection_question: 'What was the most challenging part of this assignment for you, and why?',
teacher_suggestion: 'In the next lesson, review how to develop arguments with supporting evidence and provide a model answer for comparison.',
reasoning: 'The submission demonstrates a good structure and evidence, but lacks depth and breadth of analysis. The activity and suggestions are designed to target this gap.'
};
}
const prompt = buildGradingPrompt(submission, task); export type OpenAIResponse = {
grade: string;
const res = await fetch(`${OPENAI_ENDPOINT}/openai/deployments/${OPENAI_DEPLOYMENT}/chat/completions?api-version=2024-02-15-preview`, { strengths: string;
method: 'POST', areas_for_improvement: string;
headers: { individualized_activity: string;
'Content-Type': 'application/json', reflection_question: string;
'api-key': OPENAI_API_KEY teacher_suggestion: string;
}, reasoning: string;
body: JSON.stringify({ };
messages: [
{ role: 'system', content: 'You are a helpful, fair, and transparent grading assistant.' },
{ role: 'user', content: prompt }
],
max_tokens: 500,
temperature: 0.2,
stream: false
})
});
if (!res.ok) throw new Error('OpenAI API error');
const data = await res.json();
const content = data.choices?.[0]?.message?.content || '';
// Parse the response using regex
const gradeMatch = content.match(/Grade:\s*(.*)/i);
const strengthsMatch = content.match(/Strengths:\s*([\s\S]*?)Areas for Improvement:/i);
const improvementMatch = content.match(/Areas for Improvement:\s*([\s\S]*?)Individualized Activity:/i);
const activityMatch = content.match(/Individualized Activity:\s*([\s\S]*?)Reflection Question:/i);
const reflectionMatch = content.match(/Reflection Question:\s*([\s\S]*?)Teacher Suggestion:/i);
const teacherSuggestionMatch = content.match(/Teacher Suggestion:\s*([\s\S]*?)Reasoning:/i);
const reasoningMatch = content.match(/Reasoning:\s*([\s\S]*)/i);
function fallbackGrade(submission: string, task: string): OpenAIResponse {
console.log('using fallback');
return { return {
grade: gradeMatch?.[1]?.trim() || '', grade: '7/10',
strengths: strengthsMatch?.[1]?.trim() || '', strengths: 'Clear argument and good evidence (in response to the task: ' + task + ").",
areas_for_improvement: improvementMatch?.[1]?.trim() || '', areas_for_improvement: 'Needs deeper analysis and more examples.',
individualized_activity: activityMatch?.[1]?.trim() || '', individualized_activity: 'Write a paragraph expanding on your main point and provide two additional examples to support your argument.',
reflection_question: reflectionMatch?.[1]?.trim() || '', reflection_question: 'What was the most challenging part of this assignment for you, and why?',
teacher_suggestion: teacherSuggestionMatch?.[1]?.trim() || '', teacher_suggestion: 'In the next lesson, review how to develop arguments with supporting evidence and provide a model answer for comparison.',
reasoning: reasoningMatch?.[1]?.trim() || '' reasoning: 'The submission demonstrates a good structure and evidence, but lacks depth and breadth of analysis. The activity and suggestions are designed to target this gap.'
}; };
} }
export async function gradeSubmissionWithAgent(submission: string, task: string): Promise<OpenAIResponse> {
try {
if (!client || !agent) throw new Error('Agent not available');
// 1. Create a new thread
const thread = await client.agents.createThread();
// 2. Add a message to the thread
await client.agents.createMessage(thread.id, {
role: 'user',
content: buildGradingPrompt(submission, task)
});
// 3. Run the agent
const run = await client.agents.createRun(thread.id, agent.id, {});
// 4. Poll for run completion
let runResult;
for (let i = 0; i < 60; i++) { // up to ~60 seconds
runResult = await client.agents.getRun(thread.id, run.id);
console.log('Agent run status:', runResult.status);
if (runResult.status === 'completed') break;
if (runResult.status === 'failed') {
const messages = await client.agents.listMessages(thread.id);
const agentMessage = messages.data.find((m: { role: string; content: any[] }) => m.role === 'agent');
let errorText = '';
if (agentMessage && Array.isArray(agentMessage.content) && agentMessage.content.length > 0) {
const contentItem = agentMessage.content[0];
if (contentItem.type === 'text' && contentItem.text && typeof contentItem.text.value === 'string') {
errorText = contentItem.text.value;
} else if (typeof contentItem.value === 'string') {
errorText = contentItem.value;
}
}
throw new Error(`Agent run failed. Status: failed. Message: ${errorText}`);
}
// Handle tool calls if agent requires action
if (runResult.status === 'requires_action' && runResult.requiredAction?.submitToolOutputs.toolCalls) {
const toolCalls = runResult.requiredAction.submitToolOutputs.toolCalls;
const toolOutputs: ToolOutput[] = await Promise.all(toolCalls.map(async (call: any) => {
let output = '';
const args = JSON.parse(call.function.arguments);
if (
call.function.name === 'matchRubric' ||
call.function.name === 'analyzeEssay'
) {
// LLM will handle the tool logic, just submit empty output
output = '';
} else {
output = `Unknown tool: ${call.function.name}`;
}
return {
toolCallId: call.id,
output: typeof output === 'string' ? output : JSON.stringify(output)
};
}));
await client.agents.submitToolOutputsToRun(thread.id, run.id, toolOutputs);
}
await new Promise(res => setTimeout(res, 1000));
}
if (!runResult || runResult.status !== 'completed') {
const messages = await client.agents.listMessages(thread.id);
const agentMessage = messages.data.find((m: { role: string; content: any[] }) => m.role === 'agent');
let errorText = '';
if (agentMessage && Array.isArray(agentMessage.content) && agentMessage.content.length > 0) {
const contentItem = agentMessage.content[0];
if (contentItem.type === 'text' && contentItem.text && typeof contentItem.text.value === 'string') {
errorText = contentItem.text.value;
} else if (typeof contentItem.value === 'string') {
errorText = contentItem.value;
}
}
throw new Error(`Agent run did not complete in time. Last status: ${runResult?.status}. Last message: ${errorText}`);
}
// 5. Get agent's feedback message
const messages = await client.agents.listMessages(thread.id);
const agentMessage = messages.data.find((m: { role: string; content: any[] }) => m.role === 'assistant');
// Safely extract text content from agent message
let text = '';
if (agentMessage && Array.isArray(agentMessage.content) && agentMessage.content.length > 0) {
const contentItem = agentMessage.content[0];
if (contentItem.type === 'text' && 'text' in contentItem) {
text = (contentItem as MessageTextContentOutput).text.value;
} else if ('value' in contentItem && typeof (contentItem as any).value === 'string') {
text = (contentItem as any).value;
}
}
// 6. Parse agent's response into OpenAIResponse format
let parsed: OpenAIResponse | null = null;
try {
parsed = JSON.parse(text);
} catch (err) {
console.error(err);
}
if (parsed && typeof parsed === 'object' && parsed.grade) {
return parsed;
}
// If parsing fails, return raw text in reasoning
return {
grade: '',
strengths: '',
areas_for_improvement: '',
individualized_activity: '',
reflection_question: '',
teacher_suggestion: '',
reasoning: text || 'No feedback generated.'
};
} catch (err) {
console.error(err);
// Fallback to local/demo logic
return fallbackGrade(submission, task);
}
}
+3 -3
View File
@@ -1,6 +1,6 @@
import type { RequestHandler } from '@sveltejs/kit'; import type { RequestHandler } from '@sveltejs/kit';
import type { RequestEvent } from '@sveltejs/kit'; import type { RequestEvent } from '@sveltejs/kit';
import { gradeWithOpenAI } from '$lib/utils/ai'; import { gradeSubmissionWithAgent } from '$lib/utils/ai';
export const POST: RequestHandler = async (event: RequestEvent) => { export const POST: RequestHandler = async (event: RequestEvent) => {
try { try {
@@ -28,8 +28,8 @@ export const POST: RequestHandler = async (event: RequestEvent) => {
return new Response(JSON.stringify({ error: 'No valid input provided.' }), { status: 400 }); return new Response(JSON.stringify({ error: 'No valid input provided.' }), { status: 400 });
} }
// Call the AI grading agent // Call the AI grading agent with threading and fallback
const aiResult = await gradeWithOpenAI(submission, task.trim()); const aiResult = await gradeSubmissionWithAgent(submission, task.trim());
return new Response(JSON.stringify({ return new Response(JSON.stringify({
success: true, success: true,