From 7add8db89efa78ea5900572baaea03085e88088a Mon Sep 17 00:00:00 2001 From: Jeff Clement Date: Wed, 28 Jan 2026 16:26:32 -0700 Subject: [PATCH 1/5] release notes generator --- generator/.gitignore | 3 + generator/CLAUDE.md | 46 ++ generator/README.md | 85 +++ generator/package-lock.json | 1438 +++++++++++++++++++++++++++++++++++ generator/package.json | 9 + generator/worker.js | 1170 ++++++++++++++++++++++++++++ generator/wrangler.toml | 19 + 7 files changed, 2770 insertions(+) create mode 100644 generator/.gitignore create mode 100644 generator/CLAUDE.md create mode 100644 generator/README.md create mode 100644 generator/package-lock.json create mode 100644 generator/package.json create mode 100644 generator/worker.js create mode 100644 generator/wrangler.toml diff --git a/generator/.gitignore b/generator/.gitignore new file mode 100644 index 0000000..073e02d --- /dev/null +++ b/generator/.gitignore @@ -0,0 +1,3 @@ +node_modules +.wrangler +.dev.vars diff --git a/generator/CLAUDE.md b/generator/CLAUDE.md new file mode 100644 index 0000000..6292505 --- /dev/null +++ b/generator/CLAUDE.md @@ -0,0 +1,46 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Release Note Generator - a Cloudflare Worker that generates release notes by combining Azure DevOps work items with GitHub commits, using OpenAI for AI-enhanced title generation. + +## Commands + +```bash +# Local development +npm run dev # Start local Cloudflare Worker (requires .dev.vars with secrets) + +# Deployment +npm run deploy # Deploy to Cloudflare Workers + +# Set production secrets +npx wrangler secret put DEVOPS_PAT +npx wrangler secret put GITHUB_TOKEN +npx wrangler secret put OPENAI_API_KEY +``` + +## Architecture + +**Single-file Worker** ([worker.js](worker.js)) - The entire application is in one file: + +- **Routes**: `/` serves the UI, `/api/generate` returns SSE stream of generation progress +- **Data Flow**: + 1. Fetch DevOps work items via saved query (`DEVOPS_SAVED_QUERY_ID`) + 2. Fetch GitHub commits from master branch since last release tag + 3. Match commits to DevOps items via `AB#{id}` pattern in commit messages + 4. Enhance titles using OpenAI (`gpt-4.1-mini`) + 5. Stream results back via Server-Sent Events + +**Key Functions**: +- `fetchDevOpsItems()` - Queries Azure DevOps API using saved query +- `fetchGithubCommits()` - Gets commits after current release version tag from `updates.aucerna.app/execute/21/current.txt` +- `enhanceTitle()` - Sends items to OpenAI for release note generation +- `extractTags()` - Auto-tags items based on content keywords + +**Environment Variables** (non-secrets in `wrangler.toml`, secrets in `.dev.vars` locally): +- `DEVOPS_PAT`, `GITHUB_TOKEN`, `OPENAI_API_KEY` - API credentials (secrets) +- `GITHUB_REPO`, `DEVOPS_ORG`, `DEVOPS_PROJECT`, `DEVOPS_SAVED_QUERY_ID` - Config (in wrangler.toml) + +**UI**: Windows 95-style interface embedded in `serveUI()`, uses EventSource for real-time progress updates. diff --git a/generator/README.md b/generator/README.md new file mode 100644 index 0000000..b74df3f --- /dev/null +++ b/generator/README.md @@ -0,0 +1,85 @@ +# Release Note Generator + +Cloudflare Worker that generates release notes by combining Azure DevOps work items and GitHub commits, with AI-enhanced summaries. + +**Production URL:** https://release-notes-generator.deliveryraptor.net + +## How It Works + +1. Queries Azure DevOps using a saved query (configured in `wrangler.toml`) to get pending work items +2. Fetches GitHub commits since the last release tag +3. Matches commits to DevOps items by `AB#123` references in commit messages +4. Uses OpenAI to generate user-friendly release note titles +5. Returns a CSV with the combined data + +## Hosting + +Runs on Cloudflare Workers under the Execute account (formerly Jeff's). To manage: +- Log into Cloudflare dashboard +- Go to Workers & Pages > release-note-generator +- Because this is under `deliveryraptor.net` it's only accessible for those with a @quorumsoftware.com address! + +## Setup + +### Local Development + +1. Install dependencies: + ```bash + npm install + ``` + +2. Create a `.dev.vars` file with your secrets (see Environment Variables below). + +3. Run locally: + ```bash + npm run dev + ``` + +### Production Deployment + +1. Set secrets in Cloudflare: + ```bash + npx wrangler secret put DEVOPS_PAT + npx wrangler secret put GITHUB_TOKEN + npx wrangler secret put OPENAI_API_KEY + ``` + +2. Deploy: + ```bash + npm run deploy + ``` + +### Environment Variables + +Non-private variables are baked into `wrangler.toml` + +#### DEVOPS_PAT +Azure DevOps Personal Access Token with read access to work items. + +To create one: +1. Go to Azure DevOps > User Settings (top right) > Personal Access Tokens +2. Click "New Token" +3. Set scope to "Work Items: Read" +4. Copy the generated token + +#### GITHUB_TOKEN +GitHub Personal Access Token with repo read access. + +To create one: +1. Go to GitHub > Settings > Developer settings > Personal access tokens > Tokens (classic) +2. Click "Generate new token (classic)" +3. Set scope to "repo" (for private repos) or "public_repo" (for public only) +4. Copy the generated token + +#### OPENAI_API_KEY +OpenAI API key for AI-enhanced title generation. + +**Action Required:** Currently uses Jeff Clement's personal OpenAI account. This will need to be migrated to either: +- A company OpenAI account, or +- Azure OpenAI once that's configured + +To update: generate a new API key and run `npx wrangler secret put OPENAI_API_KEY` + +## Usage + +Make a GET request to your worker URL to download the CSV file with pending release items. \ No newline at end of file diff --git a/generator/package-lock.json b/generator/package-lock.json new file mode 100644 index 0000000..542c12a --- /dev/null +++ b/generator/package-lock.json @@ -0,0 +1,1438 @@ +{ + "name": "generator", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "wrangler": "^4.52.1" + } + }, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.1.tgz", + "integrity": "sha512-Nu8ahitGFFJztxUml9oD/DLb7Z28C8cd8F46IVQ7y5Btz575pvMY8AqZsXkX7Gds29eCKdMgIHjIvzskHgPSFg==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "mime": "^3.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@cloudflare/unenv-preset": { + "version": "2.7.12", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.7.12.tgz", + "integrity": "sha512-SIBo+k58R9OyBsxF1jL6GdL7XHbzatT86c0be+UY5v5tg6TAuJ1/2QsRuC3pHgKVHile1HcJqEEORoS9hv8hNw==", + "license": "MIT OR Apache-2.0", + "peerDependencies": { + "unenv": "2.0.0-rc.24", + "workerd": "^1.20251125.0" + }, + "peerDependenciesMeta": { + "workerd": { + "optional": true + } + } + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20251202.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20251202.0.tgz", + "integrity": "sha512-/uvEAWEukTWb1geHhbjGUeZqcSSSyYzp0mvoPUBl+l0ont4NVGao3fgwM0q8wtKvgoKCHSG6zcG23wj9Opj3Nw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20251202.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20251202.0.tgz", + "integrity": "sha512-f52xRvcI9cWRd6400EZStRtXiRC5XKEud7K5aFIbbUv0VeINltujFQQ9nHWtsF6g1quIXWkjhh5u01gPAYNNXA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20251202.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20251202.0.tgz", + "integrity": "sha512-HYXinF5RBH7oXbsFUMmwKCj+WltpYbf5mRKUBG5v3EuPhUjSIFB84U+58pDyfBJjcynHdy3EtvTWcvh/+lcgow==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20251202.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20251202.0.tgz", + "integrity": "sha512-++L02Jdoxz7hEA9qDaQjbVU1RzQS+S+eqIi22DkPe2Tgiq2M3UfNpeu+75k5L9DGRIkZPYvwMBMbcmKvQqdIIg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20251202.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20251202.0.tgz", + "integrity": "sha512-gzeU6eDydTi7ib+Q9DD/c0hpXtqPucnHk2tfGU03mljPObYxzMkkPGgB5qxpksFvub3y4K0ChjqYxGJB4F+j3g==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", + "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz", + "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz", + "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz", + "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz", + "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz", + "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz", + "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz", + "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz", + "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz", + "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz", + "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz", + "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz", + "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz", + "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz", + "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz", + "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz", + "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz", + "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz", + "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz", + "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz", + "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz", + "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz", + "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz", + "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz", + "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz", + "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.2.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "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==", + "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==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@poppinss/colors": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.5.tgz", + "integrity": "sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw==", + "license": "MIT", + "dependencies": { + "kleur": "^4.1.5" + } + }, + "node_modules/@poppinss/dumper": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz", + "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@sindresorhus/is": "^7.0.2", + "supports-color": "^10.0.0" + } + }, + "node_modules/@poppinss/exception": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.2.tgz", + "integrity": "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg==", + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.1.1.tgz", + "integrity": "sha512-rO92VvpgMc3kfiTjGT52LEtJ8Yc5kCWhZjLQ3LwlA4pSgPpQO7bVpYXParOD8Jwf+cVQECJo3yP/4I8aZtUQTQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@speed-highlight/core": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.12.tgz", + "integrity": "sha512-uilwrK0Ygyri5dToHYdZSjcvpS2ZwX0w5aSt3GCEN9hrjxWCoeV4Z2DTXuxjwbntaLQIEEAlCeNQss5SoHvAEA==", + "license": "CC0-1.0" + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "license": "MIT" + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/esbuild": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", + "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.0", + "@esbuild/android-arm": "0.27.0", + "@esbuild/android-arm64": "0.27.0", + "@esbuild/android-x64": "0.27.0", + "@esbuild/darwin-arm64": "0.27.0", + "@esbuild/darwin-x64": "0.27.0", + "@esbuild/freebsd-arm64": "0.27.0", + "@esbuild/freebsd-x64": "0.27.0", + "@esbuild/linux-arm": "0.27.0", + "@esbuild/linux-arm64": "0.27.0", + "@esbuild/linux-ia32": "0.27.0", + "@esbuild/linux-loong64": "0.27.0", + "@esbuild/linux-mips64el": "0.27.0", + "@esbuild/linux-ppc64": "0.27.0", + "@esbuild/linux-riscv64": "0.27.0", + "@esbuild/linux-s390x": "0.27.0", + "@esbuild/linux-x64": "0.27.0", + "@esbuild/netbsd-arm64": "0.27.0", + "@esbuild/netbsd-x64": "0.27.0", + "@esbuild/openbsd-arm64": "0.27.0", + "@esbuild/openbsd-x64": "0.27.0", + "@esbuild/openharmony-arm64": "0.27.0", + "@esbuild/sunos-x64": "0.27.0", + "@esbuild/win32-arm64": "0.27.0", + "@esbuild/win32-ia32": "0.27.0", + "@esbuild/win32-x64": "0.27.0" + } + }, + "node_modules/exit-hook": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" + }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/miniflare": { + "version": "4.20251202.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20251202.0.tgz", + "integrity": "sha512-Pa5iBAVzzVT/yr7rcyr75ETm5IGCpdT61foGx+6jDj+vzISNfWZgEcSxWk1nlJboJumUJ10kC498hQudpdbDWg==", + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "acorn": "8.14.0", + "acorn-walk": "8.3.2", + "exit-hook": "2.2.1", + "glob-to-regexp": "0.4.1", + "sharp": "^0.33.5", + "stoppable": "1.1.0", + "undici": "7.14.0", + "workerd": "1.20251202.0", + "ws": "8.18.0", + "youch": "4.1.0-beta.10", + "zod": "3.22.3" + }, + "bin": { + "miniflare": "bootstrap.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "license": "MIT", + "engines": { + "node": ">=4", + "npm": ">=6" + } + }, + "node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/undici": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", + "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/unenv": { + "version": "2.0.0-rc.24", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", + "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3" + } + }, + "node_modules/workerd": { + "version": "1.20251202.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20251202.0.tgz", + "integrity": "sha512-p08YfrUMHkjCECNdT36r+6DpJIZX4kixbZ4n6GMUcLR5Gh18fakSCsiQrh72iOm4M9QHv/rM7P8YvCrUPWT5sg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20251202.0", + "@cloudflare/workerd-darwin-arm64": "1.20251202.0", + "@cloudflare/workerd-linux-64": "1.20251202.0", + "@cloudflare/workerd-linux-arm64": "1.20251202.0", + "@cloudflare/workerd-windows-64": "1.20251202.0" + } + }, + "node_modules/wrangler": { + "version": "4.52.1", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.52.1.tgz", + "integrity": "sha512-rIzDxzPnLAaqBF+SdHGd9Az0ELEWtIBwPp5diCR58p2F4C+KgNGGpPMFswMntuViQ2RKRgGbk4jIzStJoUUfjQ==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "@cloudflare/kv-asset-handler": "0.4.1", + "@cloudflare/unenv-preset": "2.7.12", + "blake3-wasm": "2.1.5", + "esbuild": "0.27.0", + "miniflare": "4.20251202.0", + "path-to-regexp": "6.3.0", + "unenv": "2.0.0-rc.24", + "workerd": "1.20251202.0" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=20.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^4.20251202.0" + }, + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/youch": { + "version": "4.1.0-beta.10", + "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", + "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@poppinss/dumper": "^0.6.4", + "@speed-highlight/core": "^1.2.7", + "cookie": "^1.0.2", + "youch-core": "^0.3.3" + } + }, + "node_modules/youch-core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", + "license": "MIT", + "dependencies": { + "@poppinss/exception": "^1.2.2", + "error-stack-parser-es": "^1.0.5" + } + }, + "node_modules/zod": { + "version": "3.22.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", + "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/generator/package.json b/generator/package.json new file mode 100644 index 0000000..1399eba --- /dev/null +++ b/generator/package.json @@ -0,0 +1,9 @@ +{ + "scripts": { + "dev": "wrangler dev", + "deploy": "wrangler deploy" + }, + "dependencies": { + "wrangler": "^4.52.1" + } +} diff --git a/generator/worker.js b/generator/worker.js new file mode 100644 index 0000000..d15a548 --- /dev/null +++ b/generator/worker.js @@ -0,0 +1,1170 @@ +export default { + async fetch(request, env) { + const url = new URL(request.url); + const path = url.pathname; + + try { + validateEnvironment(env); + + if (path === '/') { + return serveUI(); + } else if (path === '/api/generate' && request.method === 'GET') { + return await handleGenerateSSE(env); + } else { + return new Response('Not Found', { status: 404 }); + } + } catch (error) { + console.error('Worker error:', error); + return new Response(JSON.stringify({ error: error.message }), { + status: 500, + headers: { 'Content-Type': 'application/json' } + }); + } + } +}; + +async function handleGenerateSSE(env) { + const { readable, writable } = new TransformStream(); + const writer = writable.getWriter(); + + // Start the generation process + generateWithProgress(env, writer).finally(() => writer.close()); + + return new Response(readable, { + headers: { + 'Content-Type': 'text/event-stream', + 'Cache-Control': 'no-cache', + 'Connection': 'keep-alive', + }, + }); +} + +async function generateWithProgress(env, writer) { + try { + await sendSSE(writer, 'status', '🔍 Querying DevOps for issues...'); + + const devOpsItems = await fetchDevOpsItems(env); + await sendSSE(writer, 'status', `✅ Found ${devOpsItems.length} new items from DevOps`); + + await sendSSE(writer, 'status', '🌐 Getting current release version...'); + const currentVersionResponse = await fetch('https://updates.aucerna.app/execute/21/current.txt'); + const currentVersion = currentVersionResponse.ok ? (await currentVersionResponse.text()).trim() : '2021.1.302.0'; + + await sendSSE(writer, 'status', `📦 Current release is ${currentVersion}`); + await sendSSE(writer, 'status', `🔍 Querying GitHub for commits after ${currentVersion}_master tag...`); + + const githubCommits = await fetchGithubCommits(env, devOpsItems); + const matchedGithubCommits = githubCommits.filter(c => c.itemNumber); + const standaloneGithubCommits = githubCommits.filter(c => !c.itemNumber); + + await sendSSE(writer, 'status', `✅ Found ${matchedGithubCommits.length} commits matching DevOps items and ${standaloneGithubCommits.length} standalone commits`); + + // Log specific commits found + if (matchedGithubCommits.length > 0) { + await sendSSE(writer, 'status', '📋 GitHub commits linked to DevOps:'); + for (const commit of matchedGithubCommits) { + await sendSSE(writer, 'status', ` • DevOps #${commit.itemNumber}: ${commit.title.substring(0, 80)}...`); + } + } + + if (standaloneGithubCommits.length > 0) { + await sendSSE(writer, 'status', '📋 Standalone GitHub commits:'); + for (const commit of standaloneGithubCommits) { + await sendSSE(writer, 'status', ` • ${commit.id}: ${commit.title.substring(0, 80)}...`); + } + } + + // Merge items - GitHub commits should be linked to existing DevOps items by ID + const itemsMap = new Map(); + devOpsItems.forEach(item => itemsMap.set(item.id.toString(), item)); + + // Process GitHub commits + githubCommits.forEach(commit => { + if (commit.itemNumber && itemsMap.has(commit.itemNumber)) { + // Link to existing DevOps item + const existingItem = itemsMap.get(commit.itemNumber); + existingItem.hasGitHubCommit = true; + existingItem.gitHubCommitTitle = commit.title; + existingItem.gitHubCommitDate = commit.commitDate; + } else if (!commit.itemNumber) { + // Add standalone GitHub commit as separate item + itemsMap.set(commit.id, commit); + } + }); + + const allItems = Array.from(itemsMap.values()); + await sendSSE(writer, 'status', `📝 Total items to process: ${allItems.length}`); + + // Process with AI + for (let i = 0; i < allItems.length; i++) { + await sendSSE(writer, 'status', `🤖 Summarizing item ${i + 1} of ${allItems.length}: ${allItems[i].title.substring(0, 50)}...`); + + try { + const enhanced = await enhanceTitle(allItems[i], env); + allItems[i].title = enhanced.title; + allItems[i].type = enhanced.type; + allItems[i].tags = enhanced.tags; + + await sendSSE(writer, 'progress', { + current: i + 1, + total: allItems.length, + item: { + id: allItems[i].id, + type: allItems[i].type, + title: allItems[i].title, + source: allItems[i].source + } + }); + } catch (error) { + await sendSSE(writer, 'status', `❌ Failed to enhance item ${allItems[i].id}: ${error.message}`); + } + } + + await sendSSE(writer, 'status', '✅ Generation complete!'); + await sendSSE(writer, 'complete', allItems); + + } catch (error) { + await sendSSE(writer, 'error', error.message); + } +} + +async function sendSSE(writer, type, data) { + const message = `data: ${JSON.stringify({ type, data })}\n\n`; + await writer.write(new TextEncoder().encode(message)); +} + +function serveUI() { + const html = ` + + + + + + Release Notes Generator + + + +
+
+
$ release-notes-generator
+
Automated release notes from DevOps and GitHub
+
+ + + +
+ + + +
+
+
📋 Generated Release Notes
+ + +
+ + + + + + + + + + + + +
TypeItem #TitleTagsSource
+
+
+ + + +`; + + return new Response(html, { + headers: { 'Content-Type': 'text/html' } + }); +} + +function validateEnvironment(env) { + const required = ['DEVOPS_PAT', 'GITHUB_TOKEN', 'GITHUB_REPO', 'OPENAI_API_KEY', 'DEVOPS_SAVED_QUERY_ID', 'DEVOPS_ORG', 'DEVOPS_PROJECT']; + const missing = required.filter(key => !env[key]); + + if (missing.length > 0) { + throw new Error(`Missing environment variables: ${missing.join(', ')}`); + } +} + +async function fetchDevOpsItems(env) { + console.log('Fetching DevOps work items using saved query...'); + + try { + // Use the saved query to get work item IDs + const savedQueryId = env.DEVOPS_SAVED_QUERY_ID; + const queryUrl = `https://dev.azure.com/${env.DEVOPS_ORG}/${env.DEVOPS_PROJECT}/_apis/wit/wiql/${savedQueryId}?api-version=7.0`; + + console.log('Making saved query request to:', queryUrl); + console.log('Using PAT for auth:', env.DEVOPS_PAT?.substring(0, 10) + '...'); + + const queryResponse = await fetch(queryUrl, { + method: 'GET', + headers: { + 'Authorization': `Basic ${btoa(':' + env.DEVOPS_PAT)}`, + 'Accept': 'application/json' + } + }); + + console.log('Saved query response status:', queryResponse.status); + + if (!queryResponse.ok) { + const errorText = await queryResponse.text(); + console.error('Saved query API error response:', errorText); + throw new Error(`Saved query API error: ${queryResponse.status} - ${errorText}`); + } + + const responseText = await queryResponse.text(); + console.log('Saved query raw response:', responseText); + + let queryData; + try { + queryData = JSON.parse(responseText); + } catch (parseError) { + console.error('Failed to parse saved query response as JSON:', parseError); + throw new Error(`Saved query response is not JSON (status ${queryResponse.status}): ${responseText.substring(0, 200)}...`); + } + + console.log('Saved query response:', JSON.stringify(queryData, null, 2)); + + if (!queryData.workItems || queryData.workItems.length === 0) { + console.log('No work items found in saved query'); + return []; + } + + // Get the work item IDs + const workItemIds = queryData.workItems.map(item => item.id); + console.log('Found work item IDs:', workItemIds); + + // Now fetch the full work item details + const batchUrl = `https://dev.azure.com/${env.DEVOPS_ORG}/${env.DEVOPS_PROJECT}/_apis/wit/workitems?ids=${workItemIds.join(',')}&api-version=7.0`; + console.log('Fetching work item details from:', batchUrl); + + const detailsResponse = await fetch(batchUrl, { + headers: { + 'Authorization': `Basic ${btoa(':' + env.DEVOPS_PAT)}`, + 'Content-Type': 'application/json', + 'Accept': 'application/json' + } + }); + + console.log('Work items details response status:', detailsResponse.status); + + if (!detailsResponse.ok) { + const errorText = await detailsResponse.text(); + console.error('Work items API error response:', errorText); + throw new Error(`Work items API error: ${detailsResponse.status} - ${errorText}`); + } + + const detailsData = await detailsResponse.json(); + console.log('Work items details response structure:', Object.keys(detailsData)); + + const items = detailsData.value?.map(item => { + const workItemType = item.fields['System.WorkItemType']?.toLowerCase(); + return { + id: item.id, + type: workItemType === 'bug' ? 'bug' : 'enhancement', // Will be inferred by AI later, but bugs stay as bugs + title: item.fields['System.Title'], + tags: extractTags(item.fields['System.Tags'] || '', item.fields['System.Title'] || '', item.fields['System.Description'] || '', item.fields['Custom.ReleaseNotes'] || '', item.fields['Custom.ReleaseNotesTitle'] || ''), + source: 'devops', + releaseNotes: item.fields['Custom.ReleaseNotes'] || item.fields['Microsoft.VSTS.Common.ReleaseNotes'] || '', + releaseNotesTitle: item.fields['Custom.ReleaseNotesTitle'] || item.fields['Microsoft.VSTS.Common.ReleaseNotesTitle'] || '', + description: item.fields['System.Description'] || '', + workItemType: workItemType, // Store original work item type for AI prompt + rawData: item + }; + }) || []; + + console.log('Mapped DevOps items:', items); + return items; + } catch (error) { + console.error('Error fetching DevOps items:', error); + throw error; + } +} + + +async function fetchGithubCommits(env, devOpsItems) { + console.log('=== GITHUB COMMIT FETCHING DEBUG ==='); + + const devOpsItemIds = devOpsItems.map(item => item.id.toString()); + console.log('🔍 Looking for GitHub commits containing these DevOps item IDs:', devOpsItemIds); + + try { + // Get current release version from updates.aucerna.app + const currentVersionResponse = await fetch('https://updates.aucerna.app/execute/21/current.txt'); + + let currentVersion = '2021.1.302.0'; // fallback version + if (currentVersionResponse.ok) { + currentVersion = (await currentVersionResponse.text()).trim(); + console.log('✓ Current Execute release version from updates.aucerna.app:', currentVersion); + } else { + console.log('❌ Failed to fetch current version, using fallback:', currentVersion); + } + + // Get the tag/commit for this version from GitHub + let since = ''; + let tagDate = null; + // If current version doesn't have _master, add it for GitHub tag lookup + let lastReleaseTag = currentVersion.includes('_master') ? currentVersion : currentVersion + '_master'; + console.log('🏷️ Looking for GitHub tag:', lastReleaseTag); + + try { + // Try to find the tag/commit for this version + const tagUrl = `https://api.github.com/repos/${env.GITHUB_REPO}/git/refs/tags/${lastReleaseTag}`; + console.log('📍 Tag lookup URL:', tagUrl); + + const tagResponse = await fetch(tagUrl, { + headers: { + 'Authorization': `token ${env.GITHUB_TOKEN}`, + 'Accept': 'application/vnd.github.v3+json', + 'User-Agent': 'Release-Note-Generator/1.0' + } + }); + + console.log('🏷️ Tag response status:', tagResponse.status); + + if (tagResponse.ok) { + const tagData = await tagResponse.json(); + console.log('✓ Found tag, object type:', tagData.object.type, 'sha:', tagData.object.sha); + + // For lightweight tags, the object.url points directly to the commit + // For annotated tags, we need to get the tag object first, then the commit + let targetCommitUrl = tagData.object.url; + + if (tagData.object.type === 'tag') { + // This is an annotated tag, get the tag object to find the actual commit + console.log('📅 This is an annotated tag, fetching tag object...'); + const annotatedTagResponse = await fetch(tagData.object.url, { + headers: { + 'Authorization': `token ${env.GITHUB_TOKEN}`, + 'Accept': 'application/vnd.github.v3+json', + 'User-Agent': 'Release-Note-Generator/1.0' + } + }); + + if (annotatedTagResponse.ok) { + const annotatedTagData = await annotatedTagResponse.json(); + console.log('📅 Tag creation date:', annotatedTagData.tagger?.date); + console.log('📅 Tag target commit:', annotatedTagData.object.sha); + targetCommitUrl = annotatedTagData.object.url; + + // Use tag creation date, not commit date + if (annotatedTagData.tagger?.date) { + tagDate = annotatedTagData.tagger.date; + const afterTagDate = new Date(tagDate); + afterTagDate.setSeconds(afterTagDate.getSeconds() + 1); + since = `&since=${afterTagDate.toISOString()}`; + console.log('✅ Using tag creation date:', tagDate); + console.log('✅ Will fetch commits AFTER:', afterTagDate.toISOString()); + } + } + } + + // If we haven't set the date yet, use the commit date + if (!tagDate) { + console.log('📅 Fetching commit details from:', targetCommitUrl); + const commitResponse = await fetch(targetCommitUrl, { + headers: { + 'Authorization': `token ${env.GITHUB_TOKEN}`, + 'Accept': 'application/vnd.github.v3+json', + 'User-Agent': 'Release-Note-Generator/1.0' + } + }); + + console.log('📅 Commit details response status:', commitResponse.status); + + if (commitResponse.ok) { + const commitData = await commitResponse.json(); + const commitDate = commitData.committer?.date || commitData.author?.date; + tagDate = commitDate; + + // Add 1 second to ensure we get commits AFTER the tag + const afterTagDate = new Date(commitDate); + afterTagDate.setSeconds(afterTagDate.getSeconds() + 1); + const afterTagISO = afterTagDate.toISOString(); + + since = `&since=${afterTagISO}`; + console.log('✓ Using commit date:', commitDate); + console.log('✅ Will fetch commits AFTER:', afterTagISO); + } + } + } else { + const errorText = await tagResponse.text(); + console.log('❌ Tag not found, response:', errorText.substring(0, 200)); + console.log('⚠️ Falling back to 30 days'); + const thirtyDaysAgo = new Date(); + thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30); + since = `&since=${thirtyDaysAgo.toISOString()}`; + tagDate = thirtyDaysAgo.toISOString(); + console.log('📅 Fallback date:', tagDate); + } + } catch (tagError) { + console.log('❌ Error finding tag:', tagError.message); + console.log('⚠️ Falling back to 30 days'); + const thirtyDaysAgo = new Date(); + thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30); + since = `&since=${thirtyDaysAgo.toISOString()}`; + tagDate = thirtyDaysAgo.toISOString(); + console.log('📅 Fallback date:', tagDate); + } + + // Fetch commits since the last release + const commitsUrl = `https://api.github.com/repos/${env.GITHUB_REPO}/commits?sha=master${since}&per_page=100`; + console.log('🔍 Commits URL:', commitsUrl); + console.log('📊 Fetching commits AFTER date:', tagDate); + + const commitsResponse = await fetch(commitsUrl, { + headers: { + 'Authorization': `token ${env.GITHUB_TOKEN}`, + 'Accept': 'application/vnd.github.v3+json', + 'User-Agent': 'Release-Note-Generator/1.0' + } + }); + + console.log('GitHub commits API response status:', commitsResponse.status); + + if (!commitsResponse.ok) { + const errorText = await commitsResponse.text(); + console.error('GitHub API error response:', errorText); + throw new Error(`GitHub API error: ${commitsResponse.status} - ${errorText}`); + } + + const commits = await commitsResponse.json(); + console.log(`📊 Fetched ${commits.length} raw commits from GitHub`); + console.log(`🔍 Filtering commits after tag date: ${tagDate}`); + + // Log first few commits for debugging with date comparison + console.log('🔍 Examining first few commits for AB# patterns:'); + commits.slice(0, 5).forEach((commit, i) => { + const title = commit.commit.message.split('\n')[0]; + const commitDate = commit.commit.committer.date; + const isAfterTag = tagDate ? new Date(commitDate) > new Date(tagDate) : true; + const hasAB = /AB#\d+/i.test(title); + console.log(`📝 Commit ${i + 1}: "${title}" (${commitDate}) - After tag: ${isAfterTag}, Contains AB#: ${hasAB}`); + }); + + // Process all commits after the tag date + const allValidCommits = []; + + commits.forEach((commit) => { + const fullMessage = commit.commit.message; + const title = fullMessage.split('\n')[0]; + const commitDate = commit.commit.committer.date; + + // Additional client-side date filtering to ensure we only get commits after the tag + if (tagDate) { + const commitDateTime = new Date(commitDate); + const tagDateTime = new Date(tagDate); + const isAfterTag = commitDateTime > tagDateTime; + + if (!isAfterTag) { + console.log(`🚫 Excluding commit - made BEFORE tag (${commitDate} <= ${tagDate}): "${title}"`); + return; + } + } + + // Check if this commit title contains any of our DevOps item IDs + const matchedItemId = devOpsItemIds.find(itemId => { + // Look for AB#{itemId} or just {itemId} in the title + const hasABPrefix = title.includes(`AB#${itemId}`); + const hasPlainNumber = title.includes(itemId); + return hasABPrefix || hasPlainNumber; + }); + + if (matchedItemId) { + console.log(`✅ Found commit for DevOps item ${matchedItemId}: "${title}" (${commitDate})`); + } else { + console.log(`📝 Found commit without DevOps match: "${title}" (${commitDate})`); + } + + allValidCommits.push({ + id: matchedItemId || commit.sha.substring(0, 8), + type: 'enhancement', // Will be inferred by AI later + title: title, + tags: extractTags('', title, fullMessage), + source: 'github', + rawData: commit, + itemNumber: matchedItemId || '', // Empty string if no match + commitDate: commitDate + }); + }); + + const filteredCommits = allValidCommits; + + const matchedCommits = filteredCommits.filter(c => c.itemNumber); + const unmatchedCommits = filteredCommits.filter(c => !c.itemNumber); + + console.log(`✅ Found ${matchedCommits.length} commits matching DevOps items and ${unmatchedCommits.length} standalone commits AFTER tag date`); + console.log('📋 Matched commits:'); + matchedCommits.forEach(commit => { + console.log(` - DevOps #${commit.itemNumber}: ${commit.title} (${commit.commitDate})`); + }); + + if (unmatchedCommits.length > 0) { + console.log('📋 Standalone commits:'); + unmatchedCommits.forEach(commit => { + console.log(` - ${commit.id}: ${commit.title} (${commit.commitDate})`); + }); + } + + return filteredCommits; + } catch (error) { + console.error('Error fetching GitHub commits:', error); + throw error; + } +} + + +async function enhanceTitle(item, env) { + console.log('Making OpenAI request for item:', item.id); + + // Build context for AI based on available information + let context = `Title: ${item.title}\nSource: ${item.source}`; + + if (item.workItemType) { + context += `\nDevOps Work Item Type: ${item.workItemType}`; + } + + if (item.releaseNotesTitle) { + context += `\nRelease Notes Title: ${item.releaseNotesTitle}`; + } + + if (item.releaseNotes) { + context += `\nExisting Release Notes: ${item.releaseNotes}`; + } + + if (item.description) { + context += `\nDescription: ${item.description.substring(0, 1000)}${item.description.length > 1000 ? '...' : ''}`; + } + + const prompt = `Based on the following item information, please provide: +1. A detailed, conversational release note description +2. The item type: "bug", "enhancement", or "feature" +3. Appropriate tags from the predefined list + +${context} + +Guidelines: +- PRIORITY ORDER for content: 1) Release Notes Title (if present), 2) Existing Release Notes, 3) Generate from Title/Description +- If "Release Notes Title" exists, use it as the primary source and expand on it +- If "Existing Release Notes" exist, use them as the foundation and enhance with more detail +- Use the Description field to add context and detail to your release note +- Write for super users who understand the application but not technical details +- Write concise, complete sentences that explain the change clearly +- Keep descriptions to 1-2 sentences maximum - be direct and focused +- Use a conversational but professional tone +- Explain what the change means for users without unnecessary detail +- NEVER include company names, staff names, or specific internal references +- Use generic scenarios if needed: "when multiple users edit the same document" not "when Jim edits the document" +- A touch of gentle humor is welcome but keep it brief and generic +- For type classification: IMPORTANT - If "DevOps Work Item Type" is "bug", you MUST classify as "bug". Otherwise: "bug" = fixes/corrections, "enhancement" = improvements to existing features, "feature" = MAJOR new functionality. In general, most new things are enhancements unless they sound big and impressive. +- Always write complete sentences that can stand alone as release note items + +For tags, select 1-3 most appropriate tags from this EXACT list (use these exact strings): +security, manual step, integration, afe, well, workflow, opsched, budget, well delivery, integration agent, wellez, enersight, peloton, valnav, dashboard, attachments, admin, system, plugins, reporting, formula, api, performance, loader, odata, saas, ui, email + +Tag selection hints: +- "afe" for AFE-related functionality +- "well delivery" for well operations or RTx or Job +- "workflow" for process/task-related changes or anything referencing workflows +- "budget" for capital management, budgeting and forecasting and projects +- "dashboard" for the main landing page +- "admin" for administrative functions +- "system" for core system changes (default if unsure) +- "ui" for user interface improvements +- "api" for integration/API changes +- "performance" for speed/optimization improvements +- "security" for security-related changes +- "reporting" for report generation features +- Product names: "wellez", "enersight", "peloton", "valnav" for those specific integrations + +Respond in JSON format: +{ + "title": "your detailed release note description here", + "type": "bug|enhancement|feature", + "tags": ["tag1", "tag2"] +}`; + + try { + const response = await fetch('https://api.openai.com/v1/chat/completions', { + method: 'POST', + headers: { + 'Authorization': `Bearer ${env.OPENAI_API_KEY}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + model: 'gpt-4.1-mini', + messages: [{ role: 'user', content: prompt }], + max_tokens: 200, + temperature: 0.3 + }) + }); + + console.log('OpenAI response status:', response.status); + + if (response.ok) { + const data = await response.json(); + const responseText = data.choices[0]?.message?.content?.trim(); + + try { + // Remove markdown code blocks if present + let cleanedResponse = responseText; + if (responseText.includes('```json')) { + cleanedResponse = responseText.replace(/```json\n?/g, '').replace(/```/g, '').trim(); + } else if (responseText.includes('```')) { + cleanedResponse = responseText.replace(/```\n?/g, '').trim(); + } + + const result = JSON.parse(cleanedResponse); + console.log('OpenAI result:', result); + return { + title: result.title || item.title, + type: result.type || item.type, + tags: result.tags || item.tags || ['system'] + }; + } catch (parseError) { + console.warn('Failed to parse OpenAI JSON response:', responseText); + return { + title: item.title, + type: item.type, + tags: item.tags || ['system'] + }; + } + } else { + const errorText = await response.text(); + console.error('OpenAI API error:', response.status, errorText); + return { + title: item.title, + type: item.type, + tags: item.tags || ['system'] + }; + } + } catch (error) { + console.error('Error calling OpenAI:', error); + return { + title: item.title, + type: item.type, + tags: item.tags || ['system'] + }; + } +} + +function extractTags(tagString, title = '', description = '', releaseNotes = '', releaseNotesTitle = '') { + console.log('Extracting tags from:', { tagString, title: title.substring(0, 50), description: description.substring(0, 50) }); + + const tags = []; + + // Combine all text content for analysis + const allContent = `${tagString} ${title} ${description} ${releaseNotes} ${releaseNotesTitle}`.toLowerCase(); + + // Basic tag mappings from existing tag fields + const basicTagMap = { + 'admin': 'admin', + 'afe': 'afe', + 'budget': 'budget', + 'well': 'well delivery', + 'delivery': 'well delivery', + 'system': 'system', + 'security': 'security' + }; + + // Check basic tags + Object.entries(basicTagMap).forEach(([key, value]) => { + if (allContent.includes(key)) { + if (!tags.includes(value)) tags.push(value); + } + }); + + // Content-based tag hints + const contentHints = { + 'workflow': ['workflow', 'task', 'job'], + 'budget': ['project'], // "budget" already covered above, but "project" should also trigger it + 'afe': ['afe'] // This will catch "AFE" (case insensitive) + }; + + Object.entries(contentHints).forEach(([tag, keywords]) => { + keywords.forEach(keyword => { + if (allContent.includes(keyword)) { + if (!tags.includes(tag)) tags.push(tag); + } + }); + }); + + // Default to 'system' if no tags found + const result = tags.length > 0 ? [...new Set(tags)] : ['system']; // Remove duplicates + console.log('Extracted tags:', result); + return result; +} + + + diff --git a/generator/wrangler.toml b/generator/wrangler.toml new file mode 100644 index 0000000..bad56fa --- /dev/null +++ b/generator/wrangler.toml @@ -0,0 +1,19 @@ +name = "release-note-generator" +main = "worker.js" +compatibility_date = "2024-01-15" + +# Non-secret configuration variables +[vars] +GITHUB_REPO = "aucerna/afe-navigator" +DEVOPS_SAVED_QUERY_ID = "f6d10a61-5543-494f-9b75-a45750d8aad9" +DEVOPS_ORG = "Aucerna" +DEVOPS_PROJECT = "Aucerna" + + [[routes]] + pattern = "release-notes-generator.deliveryraptor.net" + custom_domain = true + +# For production, use wrangler secret commands: +# wrangler secret put DEVOPS_PAT +# wrangler secret put GITHUB_TOKEN +# wrangler secret put OPENAI_API_KEY From 763c79e68fde6159281efeeacea10aa9cca117f8 Mon Sep 17 00:00:00 2001 From: Jeff Clement Date: Thu, 29 Jan 2026 12:59:33 -0700 Subject: [PATCH 2/5] version bump --- generator/package-lock.json | 552 +++++++++++++++++------------------- 1 file changed, 263 insertions(+), 289 deletions(-) diff --git a/generator/package-lock.json b/generator/package-lock.json index 542c12a..1c3db8d 100644 --- a/generator/package-lock.json +++ b/generator/package-lock.json @@ -9,25 +9,22 @@ } }, "node_modules/@cloudflare/kv-asset-handler": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.1.tgz", - "integrity": "sha512-Nu8ahitGFFJztxUml9oD/DLb7Z28C8cd8F46IVQ7y5Btz575pvMY8AqZsXkX7Gds29eCKdMgIHjIvzskHgPSFg==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.2.tgz", + "integrity": "sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==", "license": "MIT OR Apache-2.0", - "dependencies": { - "mime": "^3.0.0" - }, "engines": { "node": ">=18.0.0" } }, "node_modules/@cloudflare/unenv-preset": { - "version": "2.7.12", - "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.7.12.tgz", - "integrity": "sha512-SIBo+k58R9OyBsxF1jL6GdL7XHbzatT86c0be+UY5v5tg6TAuJ1/2QsRuC3pHgKVHile1HcJqEEORoS9hv8hNw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.11.0.tgz", + "integrity": "sha512-z3hxFajL765VniNPGV0JRStZolNz63gU3B3AktwoGdDlnQvz5nP+Ah4RL04PONlZQjwmDdGHowEStJ94+RsaJg==", "license": "MIT OR Apache-2.0", "peerDependencies": { "unenv": "2.0.0-rc.24", - "workerd": "^1.20251125.0" + "workerd": "^1.20260115.0" }, "peerDependenciesMeta": { "workerd": { @@ -36,9 +33,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20251202.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20251202.0.tgz", - "integrity": "sha512-/uvEAWEukTWb1geHhbjGUeZqcSSSyYzp0mvoPUBl+l0ont4NVGao3fgwM0q8wtKvgoKCHSG6zcG23wj9Opj3Nw==", + "version": "1.20260124.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260124.0.tgz", + "integrity": "sha512-VuqscLhiiVIf7t/dcfkjtT0LKJH+a06KUFwFTHgdTcqyLbFZ44u1SLpOONu5fyva4A9MdaKh9a+Z/tBC1d76nw==", "cpu": [ "x64" ], @@ -52,9 +49,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20251202.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20251202.0.tgz", - "integrity": "sha512-f52xRvcI9cWRd6400EZStRtXiRC5XKEud7K5aFIbbUv0VeINltujFQQ9nHWtsF6g1quIXWkjhh5u01gPAYNNXA==", + "version": "1.20260124.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260124.0.tgz", + "integrity": "sha512-PfnjoFooPgRKFUIZcEP9irnn5Y7OgXinjM+IMlKTdEyLWjMblLsbsqAgydf75+ii0715xAeUlWQjZrWdyOZjMw==", "cpu": [ "arm64" ], @@ -68,9 +65,9 @@ } }, "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20251202.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20251202.0.tgz", - "integrity": "sha512-HYXinF5RBH7oXbsFUMmwKCj+WltpYbf5mRKUBG5v3EuPhUjSIFB84U+58pDyfBJjcynHdy3EtvTWcvh/+lcgow==", + "version": "1.20260124.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260124.0.tgz", + "integrity": "sha512-KSkZl4kwcWeFXI7qsaLlMnKwjgdZwI0OEARjyZpiHCxJCqAqla9XxQKNDscL2Z3qUflIo30i+uteGbFrhzuVGQ==", "cpu": [ "x64" ], @@ -84,9 +81,9 @@ } }, "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20251202.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20251202.0.tgz", - "integrity": "sha512-++L02Jdoxz7hEA9qDaQjbVU1RzQS+S+eqIi22DkPe2Tgiq2M3UfNpeu+75k5L9DGRIkZPYvwMBMbcmKvQqdIIg==", + "version": "1.20260124.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260124.0.tgz", + "integrity": "sha512-61xjSUNk745EVV4vXZP0KGyLCatcmamfBB+dcdQ8kDr6PrNU4IJ1kuQFSJdjybyDhJRm4TpGVywq+9hREuF7xA==", "cpu": [ "arm64" ], @@ -100,9 +97,9 @@ } }, "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20251202.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20251202.0.tgz", - "integrity": "sha512-gzeU6eDydTi7ib+Q9DD/c0hpXtqPucnHk2tfGU03mljPObYxzMkkPGgB5qxpksFvub3y4K0ChjqYxGJB4F+j3g==", + "version": "1.20260124.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260124.0.tgz", + "integrity": "sha512-j9O11pwQQV6Vi3peNrJoyIas3SrZHlPj0Ah+z1hDW9o1v35euVBQJw/PuzjPOXxTFUlGQoMJdfzPsO9xP86g7A==", "cpu": [ "x64" ], @@ -128,9 +125,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", - "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", "license": "MIT", "optional": true, "dependencies": { @@ -553,10 +550,19 @@ "node": ">=18" } }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", "cpu": [ "arm64" ], @@ -572,13 +578,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" + "@img/sharp-libvips-darwin-arm64": "1.2.4" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", "cpu": [ "x64" ], @@ -594,13 +600,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" + "@img/sharp-libvips-darwin-x64": "1.2.4" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", "cpu": [ "arm64" ], @@ -614,9 +620,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", "cpu": [ "x64" ], @@ -630,9 +636,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", "cpu": [ "arm" ], @@ -646,9 +652,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", "cpu": [ "arm64" ], @@ -661,10 +667,42 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", "cpu": [ "s390x" ], @@ -678,9 +716,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", "cpu": [ "x64" ], @@ -694,9 +732,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", "cpu": [ "arm64" ], @@ -710,9 +748,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", "cpu": [ "x64" ], @@ -726,9 +764,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", "cpu": [ "arm" ], @@ -744,13 +782,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" + "@img/sharp-libvips-linux-arm": "1.2.4" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", "cpu": [ "arm64" ], @@ -766,13 +804,57 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", "cpu": [ "s390x" ], @@ -788,13 +870,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" + "@img/sharp-libvips-linux-s390x": "1.2.4" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", "cpu": [ "x64" ], @@ -810,13 +892,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" + "@img/sharp-libvips-linux-x64": "1.2.4" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", "cpu": [ "arm64" ], @@ -832,13 +914,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", "cpu": [ "x64" ], @@ -854,20 +936,20 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", "cpu": [ "wasm32" ], "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.2.0" + "@emnapi/runtime": "^1.7.0" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -876,10 +958,29 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", "cpu": [ "ia32" ], @@ -896,9 +997,9 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", "cpu": [ "x64" ], @@ -940,9 +1041,9 @@ } }, "node_modules/@poppinss/colors": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.5.tgz", - "integrity": "sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz", + "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", "license": "MIT", "dependencies": { "kleur": "^4.1.5" @@ -960,15 +1061,15 @@ } }, "node_modules/@poppinss/exception": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.2.tgz", - "integrity": "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", + "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", "license": "MIT" }, "node_modules/@sindresorhus/is": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.1.1.tgz", - "integrity": "sha512-rO92VvpgMc3kfiTjGT52LEtJ8Yc5kCWhZjLQ3LwlA4pSgPpQO7bVpYXParOD8Jwf+cVQECJo3yP/4I8aZtUQTQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", "license": "MIT", "engines": { "node": ">=18" @@ -978,79 +1079,17 @@ } }, "node_modules/@speed-highlight/core": { - "version": "1.2.12", - "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.12.tgz", - "integrity": "sha512-uilwrK0Ygyri5dToHYdZSjcvpS2ZwX0w5aSt3GCEN9hrjxWCoeV4Z2DTXuxjwbntaLQIEEAlCeNQss5SoHvAEA==", + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.14.tgz", + "integrity": "sha512-G4ewlBNhUtlLvrJTb88d2mdy2KRijzs4UhnlrOSRT4bmjh/IqNElZa3zkrZ+TC47TwtlDWzVLFADljF1Ijp5hA==", "license": "CC0-1.0" }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/blake3-wasm": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", "license": "MIT" }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "license": "MIT", - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, "node_modules/cookie": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", @@ -1123,18 +1162,6 @@ "@esbuild/win32-x64": "0.27.0" } }, - "node_modules/exit-hook": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", - "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -1149,18 +1176,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "license": "BSD-2-Clause" - }, - "node_modules/is-arrayish": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", - "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", - "license": "MIT" - }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -1170,36 +1185,18 @@ "node": ">=6" } }, - "node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/miniflare": { - "version": "4.20251202.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20251202.0.tgz", - "integrity": "sha512-Pa5iBAVzzVT/yr7rcyr75ETm5IGCpdT61foGx+6jDj+vzISNfWZgEcSxWk1nlJboJumUJ10kC498hQudpdbDWg==", + "version": "4.20260124.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260124.0.tgz", + "integrity": "sha512-Co8onUh+POwOuLty4myQg+Nzg9/xZ5eAJc1oqYBzRovHd/XIpb5WAnRVaubcfAQJ85awWtF3yXUHCDx6cIaN3w==", "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "0.8.1", - "acorn": "8.14.0", - "acorn-walk": "8.3.2", - "exit-hook": "2.2.1", - "glob-to-regexp": "0.4.1", - "sharp": "^0.33.5", - "stoppable": "1.1.0", - "undici": "7.14.0", - "workerd": "1.20251202.0", + "sharp": "^0.34.5", + "undici": "7.18.2", + "workerd": "1.20260124.0", "ws": "8.18.0", - "youch": "4.1.0-beta.10", - "zod": "3.22.3" + "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" @@ -1233,15 +1230,15 @@ } }, "node_modules/sharp": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.6.3" + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -1250,44 +1247,30 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.33.5", - "@img/sharp-darwin-x64": "0.33.5", - "@img/sharp-libvips-darwin-arm64": "1.0.4", - "@img/sharp-libvips-darwin-x64": "1.0.4", - "@img/sharp-libvips-linux-arm": "1.0.5", - "@img/sharp-libvips-linux-arm64": "1.0.4", - "@img/sharp-libvips-linux-s390x": "1.0.4", - "@img/sharp-libvips-linux-x64": "1.0.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", - "@img/sharp-linux-arm": "0.33.5", - "@img/sharp-linux-arm64": "0.33.5", - "@img/sharp-linux-s390x": "0.33.5", - "@img/sharp-linux-x64": "0.33.5", - "@img/sharp-linuxmusl-arm64": "0.33.5", - "@img/sharp-linuxmusl-x64": "0.33.5", - "@img/sharp-wasm32": "0.33.5", - "@img/sharp-win32-ia32": "0.33.5", - "@img/sharp-win32-x64": "0.33.5" - } - }, - "node_modules/simple-swizzle": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", - "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/stoppable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", - "license": "MIT", - "engines": { - "node": ">=4", - "npm": ">=6" + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" } }, "node_modules/supports-color": { @@ -1310,9 +1293,9 @@ "optional": true }, "node_modules/undici": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", - "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.18.2.tgz", + "integrity": "sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -1328,9 +1311,9 @@ } }, "node_modules/workerd": { - "version": "1.20251202.0", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20251202.0.tgz", - "integrity": "sha512-p08YfrUMHkjCECNdT36r+6DpJIZX4kixbZ4n6GMUcLR5Gh18fakSCsiQrh72iOm4M9QHv/rM7P8YvCrUPWT5sg==", + "version": "1.20260124.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260124.0.tgz", + "integrity": "sha512-JN6voV/fUQK342a39Rl+20YVmtIXZVbpxc7V/m809lUnlTGPy4aa5MI7PMoc+9qExgAEOw9cojvN5zOfqmMWLg==", "hasInstallScript": true, "license": "Apache-2.0", "bin": { @@ -1340,27 +1323,27 @@ "node": ">=16" }, "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20251202.0", - "@cloudflare/workerd-darwin-arm64": "1.20251202.0", - "@cloudflare/workerd-linux-64": "1.20251202.0", - "@cloudflare/workerd-linux-arm64": "1.20251202.0", - "@cloudflare/workerd-windows-64": "1.20251202.0" + "@cloudflare/workerd-darwin-64": "1.20260124.0", + "@cloudflare/workerd-darwin-arm64": "1.20260124.0", + "@cloudflare/workerd-linux-64": "1.20260124.0", + "@cloudflare/workerd-linux-arm64": "1.20260124.0", + "@cloudflare/workerd-windows-64": "1.20260124.0" } }, "node_modules/wrangler": { - "version": "4.52.1", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.52.1.tgz", - "integrity": "sha512-rIzDxzPnLAaqBF+SdHGd9Az0ELEWtIBwPp5diCR58p2F4C+KgNGGpPMFswMntuViQ2RKRgGbk4jIzStJoUUfjQ==", + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.61.0.tgz", + "integrity": "sha512-Kb8NMe1B/HM7/ds3hU+fcV1U7T996vRKJ0UU/qqgNUMwdemTRA+sSaH3mQvQslIBbprHHU81s0huA6fDIcwiaQ==", "license": "MIT OR Apache-2.0", "dependencies": { - "@cloudflare/kv-asset-handler": "0.4.1", - "@cloudflare/unenv-preset": "2.7.12", + "@cloudflare/kv-asset-handler": "0.4.2", + "@cloudflare/unenv-preset": "2.11.0", "blake3-wasm": "2.1.5", "esbuild": "0.27.0", - "miniflare": "4.20251202.0", + "miniflare": "4.20260124.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", - "workerd": "1.20251202.0" + "workerd": "1.20260124.0" }, "bin": { "wrangler": "bin/wrangler.js", @@ -1373,7 +1356,7 @@ "fsevents": "~2.3.2" }, "peerDependencies": { - "@cloudflare/workers-types": "^4.20251202.0" + "@cloudflare/workers-types": "^4.20260124.0" }, "peerDependenciesMeta": { "@cloudflare/workers-types": { @@ -1424,15 +1407,6 @@ "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } - }, - "node_modules/zod": { - "version": "3.22.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", - "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } } } From 3766daf72fce28ed81337421e134d891d78507eb Mon Sep 17 00:00:00 2001 From: Jeff Clement Date: Thu, 29 Jan 2026 13:31:54 -0700 Subject: [PATCH 3/5] better handling when LLM generates ; separated tags. --- generator/worker.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/generator/worker.js b/generator/worker.js index d15a548..52da888 100644 --- a/generator/worker.js +++ b/generator/worker.js @@ -1087,10 +1087,15 @@ Respond in JSON format: const result = JSON.parse(cleanedResponse); console.log('OpenAI result:', result); + // Normalize tags: handle both array and semicolon/comma-separated string formats + let tags = result.tags || item.tags || ['system']; + if (typeof tags === 'string') { + tags = tags.split(/[;,]/).map(t => t.trim()).filter(t => t); + } return { title: result.title || item.title, type: result.type || item.type, - tags: result.tags || item.tags || ['system'] + tags: tags }; } catch (parseError) { console.warn('Failed to parse OpenAI JSON response:', responseText); From d08d5f2c465a077b84f23da4770414543a498436 Mon Sep 17 00:00:00 2001 From: Jeff Clement Date: Thu, 29 Jan 2026 13:32:03 -0700 Subject: [PATCH 4/5] hugo version upgrade --- .github/workflows/master.yml | 2 +- .github/workflows/staging.yml | 2 +- content/21.1.317/index.md | 3 +++ content/21.1.317/items.csv | 27 +++++++++++++++++++++++++++ mise.toml | 4 ++-- 5 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 content/21.1.317/index.md create mode 100644 content/21.1.317/items.csv diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index af19fac..fd37299 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -19,7 +19,7 @@ jobs: - name: Hugo setup uses: peaceiris/actions-hugo@v2.6.0 with: - hugo-version: '0.140.2' # optional, default is latest + hugo-version: '0.152.2' # optional, default is latest extended: true # optional, default is false - name: NPM run: npm install diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml index 2b5ef56..380a5b4 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/staging.yml @@ -19,7 +19,7 @@ jobs: - name: Hugo setup uses: peaceiris/actions-hugo@v2.6.0 with: - hugo-version: '0.140.2' # optional, default is latest + hugo-version: '0.152.2' # optional, default is latest extended: true # optional, default is false - name: NPM run: npm install diff --git a/content/21.1.317/index.md b/content/21.1.317/index.md new file mode 100644 index 0000000..448b604 --- /dev/null +++ b/content/21.1.317/index.md @@ -0,0 +1,3 @@ +--- +date: 2026-01-29 +--- diff --git a/content/21.1.317/items.csv b/content/21.1.317/items.csv new file mode 100644 index 0000000..5976abc --- /dev/null +++ b/content/21.1.317/items.csv @@ -0,0 +1,27 @@ +type,tags,title,weight,detail,item# +bug,"security,integration,system",Improvements to error message reporting when the Integration Agent encounters a TLS certificate error.,,,353967 +bug,"afe,reporting,budget",The AFE Project Allocation Report now correctly allocates actuals and field costs in systems where an account-level filter is not in use.,,,351841 +bug,"workflow,system",Fixed an issue where the Auto-release process was not updating the 'Next Reviewing Position' and 'Next Approving Position' fields.,,,355395 +bug,"ui,system",Fixed a critical issue where selecting blocks in Blockly was not working in the latest versions of Chrome and Edge.,,,356620 +bug,"reporting,ui",Fixed an issue where the browse reports screen incorrectly showed a calculated field edit icon next to every field.,,,355095 +enhancement,"integration,security,api","SharePoint authentication has been updated to use certificate-based authentication instead of username and password, aligning with modern SharePoint security standards. ",,,356724 +bug,"reporting,attachments,system",Fixed an issue where very long field names could break the Excel sheets downloaded from the browse screen.,,,353469 +bug,"ui,system","Fixed an issue where Custom Tab Text Sections did not support multiple line input, allowing users to now enter and display text across several lines as intended.",,,295772 +feature,"integration,workflow,system","Introducing Databricks Data Selectors & Sync (Beta), a new feature that allows users to easily select and synchronize data with a Databricks environment (via. the Databricks API). This is beta functionality and not yet suitable for production use.",,,356515 +bug,"ui,system","If you set your preferred date format to 'mmm dd yyyy' (a reasonable choice), you can now actually enter dates in that format like you'd expect.",,,349499 +bug,"email,ui","Fixed an issue where emails appeared distorted or improperly formatted when viewed in Gmail Web, ensuring a cleaner and more consistent email display for users.",,,353687 +bug,"ui,system","Error messages now display correctly without incorrect HTML escaping, making it easier to understand issues when they occur.",,,353996 +bug,"integration,system","Fixed errors occurring when copying data from PostgreSQL to MSSQL using the database tool, ensuring smoother and more reliable data transfers between these systems.",,,355211 +bug,"ui,reporting,opsched","The Job Report dropdown in the Schedule Editor now only displays Global reports, making it easier to find the right report without clutter from other report types.",,,306212 +enhancement,"system,performance","The BallotUpload process now properly cleans up its temporary files after streaming rendered forms, helping keep the system tidy and preventing unnecessary file buildup.",,,296318 +enhancement,"ui,system,security,admin",The custom business rule configuration interface has been migrated from Angular to jQuery.,,,350023 +enhancement,"ui,system,security",The Comments view has been migrated from Angular to jQuery.,,,350025 +enhancement,"admin,ui,system,security",The Document Types management tool has been migrated from Angular to jQuery.,,,350017 +enhancement,"ui,system,security,admin",The reminder time selection interface has been migrated from Angular to jQuery.,,,350024 +enhancement,"security,system,ui",Updated DataTables JavaScript from version 1.9.4 to 1.13 to address security concerns and improve compatibility.,,,352852 +bug,"workflow,ui","The response date for a partner now correctly clears when the status is removed, ensuring your data stays accurate and up to date without any extra clicks.",,,354221 +bug,"workflow,ui",Fixed an issue where slashes in text sections and separators within the workflow task modal would hide the text or separator.,,,353990 +enhancement,"security,performance,ui","The marked.js library has been updated to the latest stable v12.x, bringing improved security, better performance, and new features to Markdown rendering across the application. This update affects areas like the MOTD banner, help text, and help page viewer, ensuring a smoother and safer user experience when viewing Markdown content.",,,354511 +bug,"workflow,reporting,performance","We've resolved a performance issue affecting workflow reporting, so generating your reports should now be faster and smoother, even when handling large data sets.",,,355718 +bug,"workflow,ui,security",Workflow tasks now correctly disable fields when you don't have edit rights.,,,354592 +bug,"workflow,email,system",Workflow task reminders now correctly send notifications even when the underlying workflow definition was deleted.,,,355065 \ No newline at end of file diff --git a/mise.toml b/mise.toml index 4fa5c50..66597a0 100644 --- a/mise.toml +++ b/mise.toml @@ -1,7 +1,7 @@ [tools] go = "1.24" -hugo-extended = "0.140.2" -node = "latest" +hugo-extended = "0.152.2" +node = "24" [tasks.server] description = "Run Hugo Server in Development Mode" From 88098be2e95bfeac12824725c3443426de408341 Mon Sep 17 00:00:00 2001 From: Kelly Sankey Date: Thu, 29 Jan 2026 13:54:44 -0700 Subject: [PATCH 5/5] fix typo --- content/21.1.317/items.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/21.1.317/items.csv b/content/21.1.317/items.csv index 5976abc..d6aa6de 100644 --- a/content/21.1.317/items.csv +++ b/content/21.1.317/items.csv @@ -7,7 +7,7 @@ bug,"reporting,ui",Fixed an issue where the browse reports screen incorrectly sh enhancement,"integration,security,api","SharePoint authentication has been updated to use certificate-based authentication instead of username and password, aligning with modern SharePoint security standards. ",,,356724 bug,"reporting,attachments,system",Fixed an issue where very long field names could break the Excel sheets downloaded from the browse screen.,,,353469 bug,"ui,system","Fixed an issue where Custom Tab Text Sections did not support multiple line input, allowing users to now enter and display text across several lines as intended.",,,295772 -feature,"integration,workflow,system","Introducing Databricks Data Selectors & Sync (Beta), a new feature that allows users to easily select and synchronize data with a Databricks environment (via. the Databricks API). This is beta functionality and not yet suitable for production use.",,,356515 +feature,"integration,workflow,system","Introducing Databricks Data Selectors & Sync (Beta), a new feature that allows users to easily select and synchronize data with a Databricks environment (via the Databricks API). This is beta functionality and not yet suitable for production use.",,,356515 bug,"ui,system","If you set your preferred date format to 'mmm dd yyyy' (a reasonable choice), you can now actually enter dates in that format like you'd expect.",,,349499 bug,"email,ui","Fixed an issue where emails appeared distorted or improperly formatted when viewed in Gmail Web, ensuring a cleaner and more consistent email display for users.",,,353687 bug,"ui,system","Error messages now display correctly without incorrect HTML escaping, making it easier to understand issues when they occur.",,,353996