├── .gitignore ├── htmx-ai ├── .gitignore ├── .vscode │ ├── extensions.json │ └── launch.json ├── README.md ├── astro.config.mjs ├── diagrams.excalidraw ├── package-lock.json ├── package.json ├── public │ ├── favicon.svg │ └── htmx.js ├── src │ ├── env.d.ts │ ├── middleware.ts │ ├── openai.ts │ ├── pages │ │ ├── index.astro │ │ └── prompt.astro │ └── request.ts ├── tailwind.config.cjs └── tsconfig.json ├── htmx-express ├── index.js ├── input.css ├── openai.js ├── package.json ├── pnpm-lock.yaml ├── public │ ├── htmx.js │ ├── index.html │ ├── sse.js │ └── tailwind.css └── tailwind.config.js └── nextjs-ai ├── .eslintrc.json ├── .gitignore ├── README.md ├── app ├── _lib │ ├── openai.ts │ └── request.ts ├── api │ └── gpt │ │ ├── [requestId] │ │ └── route.ts │ │ └── route.ts ├── favicon.ico ├── globals.css ├── layout.tsx └── page.tsx ├── next.config.js ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── public ├── next.svg └── vercel.svg ├── tailwind.config.js └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /htmx-ai/.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | # generated types 4 | .astro/ 5 | 6 | # dependencies 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | -------------------------------------------------------------------------------- /htmx-ai/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /htmx-ai/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /htmx-ai/README.md: -------------------------------------------------------------------------------- 1 | # Astro Starter Kit: Minimal 2 | 3 | ``` 4 | npm create astro@latest -- --template minimal 5 | ``` 6 | 7 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/minimal) 8 | [![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/minimal) 9 | [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/minimal/devcontainer.json) 10 | 11 | > 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! 12 | 13 | ## 🚀 Project Structure 14 | 15 | Inside of your Astro project, you'll see the following folders and files: 16 | 17 | ``` 18 | / 19 | ├── public/ 20 | ├── src/ 21 | │ └── pages/ 22 | │ └── index.astro 23 | └── package.json 24 | ``` 25 | 26 | Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. 27 | 28 | There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. 29 | 30 | Any static assets, like images, can be placed in the `public/` directory. 31 | 32 | ## 🧞 Commands 33 | 34 | All commands are run from the root of the project, from a terminal: 35 | 36 | | Command | Action | 37 | | :------------------------ | :----------------------------------------------- | 38 | | `npm install` | Installs dependencies | 39 | | `npm run dev` | Starts local dev server at `localhost:3000` | 40 | | `npm run build` | Build your production site to `./dist/` | 41 | | `npm run preview` | Preview your build locally, before deploying | 42 | | `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | 43 | | `npm run astro -- --help` | Get help using the Astro CLI | 44 | 45 | ## 👀 Want to learn more? 46 | 47 | Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat). 48 | -------------------------------------------------------------------------------- /htmx-ai/astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "astro/config"; 2 | 3 | import tailwind from "@astrojs/tailwind"; 4 | 5 | // https://astro.build/config 6 | export default defineConfig({ 7 | output: "server", 8 | integrations: [tailwind()], 9 | }); 10 | -------------------------------------------------------------------------------- /htmx-ai/diagrams.excalidraw: -------------------------------------------------------------------------------- 1 | { 2 | "type": "excalidraw", 3 | "version": 2, 4 | "source": "https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor", 5 | "elements": [ 6 | { 7 | "id": "tZ1Tdhkr_7t8gPwRNsvkl", 8 | "type": "arrow", 9 | "x": 264.2513122558594, 10 | "y": 153.84768343508586, 11 | "width": 327.236328125, 12 | "height": 24.92271485120975, 13 | "angle": 0, 14 | "strokeColor": "#000000", 15 | "backgroundColor": "transparent", 16 | "fillStyle": "hachure", 17 | "strokeWidth": 1, 18 | "strokeStyle": "solid", 19 | "roughness": 1, 20 | "opacity": 100, 21 | "groupIds": [], 22 | "roundness": { 23 | "type": 2 24 | }, 25 | "seed": 2020323279, 26 | "version": 452, 27 | "versionNonce": 871905921, 28 | "isDeleted": false, 29 | "boundElements": null, 30 | "updated": 1691330433657, 31 | "link": null, 32 | "locked": false, 33 | "points": [ 34 | [ 35 | 0, 36 | 0 37 | ], 38 | [ 39 | 322.6302185058594, 40 | 1.0178357610287232 41 | ], 42 | [ 43 | 323.8899841308594, 44 | 24.92271485120975 45 | ], 46 | [ 47 | -3.346343994140625, 48 | 24.716606082252603 49 | ] 50 | ], 51 | "lastCommittedPoint": null, 52 | "startBinding": null, 53 | "endBinding": null, 54 | "startArrowhead": null, 55 | "endArrowhead": "arrow" 56 | }, 57 | { 58 | "id": "mfhvUgTRy7ODdCBtTQG7i", 59 | "type": "text", 60 | "x": 287.0279846191406, 61 | "y": 122.98696899414062, 62 | "width": 171.25982666015625, 63 | "height": 25, 64 | "angle": 0, 65 | "strokeColor": "#000000", 66 | "backgroundColor": "transparent", 67 | "fillStyle": "hachure", 68 | "strokeWidth": 1, 69 | "strokeStyle": "solid", 70 | "roughness": 1, 71 | "opacity": 100, 72 | "groupIds": [], 73 | "roundness": null, 74 | "seed": 1279565985, 75 | "version": 145, 76 | "versionNonce": 1386179087, 77 | "isDeleted": false, 78 | "boundElements": null, 79 | "updated": 1691330433657, 80 | "link": null, 81 | "locked": false, 82 | "text": "hx-post=\"/prompt\"", 83 | "fontSize": 20, 84 | "fontFamily": 1, 85 | "textAlign": "left", 86 | "verticalAlign": "top", 87 | "baseline": 18, 88 | "containerId": null, 89 | "originalText": "hx-post=\"/prompt\"", 90 | "lineHeight": 1.25 91 | }, 92 | { 93 | "type": "arrow", 94 | "version": 554, 95 | "versionNonce": 955204193, 96 | "isDeleted": false, 97 | "id": "EQbU4keWRX5MlbwlurhVT", 98 | "fillStyle": "hachure", 99 | "strokeWidth": 1, 100 | "strokeStyle": "solid", 101 | "roughness": 1, 102 | "opacity": 100, 103 | "angle": 0, 104 | "x": 266.69740213845324, 105 | "y": 245.43297186727818, 106 | "strokeColor": "#000000", 107 | "backgroundColor": "transparent", 108 | "width": 327.236328125, 109 | "height": 25.310895370911506, 110 | "seed": 2020323279, 111 | "groupIds": [], 112 | "roundness": { 113 | "type": 2 114 | }, 115 | "boundElements": [], 116 | "updated": 1691330433657, 117 | "link": null, 118 | "locked": false, 119 | "startBinding": null, 120 | "endBinding": null, 121 | "lastCommittedPoint": null, 122 | "startArrowhead": null, 123 | "endArrowhead": "arrow", 124 | "points": [ 125 | [ 126 | 0, 127 | 0 128 | ], 129 | [ 130 | 322.6302185058594, 131 | 1.0336889301977306 132 | ], 133 | [ 134 | 323.8899841308594, 135 | 25.310895370911506 136 | ], 137 | [ 138 | -3.346343994140625, 139 | 25.10157638149778 140 | ] 141 | ] 142 | }, 143 | { 144 | "type": "text", 145 | "version": 294, 146 | "versionNonce": 40194095, 147 | "isDeleted": false, 148 | "id": "cmRDVD72l33GcI4sRz0np", 149 | "fillStyle": "hachure", 150 | "strokeWidth": 1, 151 | "strokeStyle": "solid", 152 | "roughness": 1, 153 | "opacity": 100, 154 | "angle": 0, 155 | "x": 283.0027305075939, 156 | "y": 215.72107032242866, 157 | "strokeColor": "#000000", 158 | "backgroundColor": "transparent", 159 | "width": 335.69976806640625, 160 | "height": 25, 161 | "seed": 1279565985, 162 | "groupIds": [], 163 | "roundness": null, 164 | "boundElements": [], 165 | "updated": 1691330433657, 166 | "link": null, 167 | "locked": false, 168 | "fontSize": 20, 169 | "fontFamily": 1, 170 | "text": "hx-get=\"/prompt/requestID=NNNN\"", 171 | "textAlign": "left", 172 | "verticalAlign": "top", 173 | "containerId": null, 174 | "originalText": "hx-get=\"/prompt/requestID=NNNN\"", 175 | "lineHeight": 1.25, 176 | "baseline": 18 177 | }, 178 | { 179 | "id": "XjFjwfgl2ynxq6HsgCvJa", 180 | "type": "text", 181 | "x": 495.37109375, 182 | "y": 120.79032893099546, 183 | "width": 108.17988586425781, 184 | "height": 25, 185 | "angle": 0, 186 | "strokeColor": "#000000", 187 | "backgroundColor": "transparent", 188 | "fillStyle": "hachure", 189 | "strokeWidth": 1, 190 | "strokeStyle": "solid", 191 | "roughness": 1, 192 | "opacity": 100, 193 | "groupIds": [], 194 | "roundness": null, 195 | "seed": 725740001, 196 | "version": 80, 197 | "versionNonce": 1031425601, 198 | "isDeleted": false, 199 | "boundElements": null, 200 | "updated": 1691330433657, 201 | "link": null, 202 | "locked": false, 203 | "text": "prompt=dog", 204 | "fontSize": 20, 205 | "fontFamily": 1, 206 | "textAlign": "left", 207 | "verticalAlign": "top", 208 | "baseline": 18, 209 | "containerId": null, 210 | "originalText": "prompt=dog", 211 | "lineHeight": 1.25 212 | }, 213 | { 214 | "id": "i8G17JSH0z-KSkR-fD3Ei", 215 | "type": "line", 216 | "x": 252.2005157470703, 217 | "y": 114.765625, 218 | "width": 2.842170943040401e-14, 219 | "height": 280.5695685264637, 220 | "angle": 0, 221 | "strokeColor": "#000000", 222 | "backgroundColor": "transparent", 223 | "fillStyle": "hachure", 224 | "strokeWidth": 1, 225 | "strokeStyle": "dashed", 226 | "roughness": 2, 227 | "opacity": 100, 228 | "groupIds": [], 229 | "roundness": { 230 | "type": 2 231 | }, 232 | "seed": 2038389697, 233 | "version": 180, 234 | "versionNonce": 684290639, 235 | "isDeleted": false, 236 | "boundElements": null, 237 | "updated": 1691330433657, 238 | "link": null, 239 | "locked": false, 240 | "points": [ 241 | [ 242 | 0, 243 | 0 244 | ], 245 | [ 246 | -2.842170943040401e-14, 247 | 280.5695685264637 248 | ] 249 | ], 250 | "lastCommittedPoint": null, 251 | "startBinding": null, 252 | "endBinding": null, 253 | "startArrowhead": null, 254 | "endArrowhead": null 255 | }, 256 | { 257 | "id": "bx1uzfUcCezao1WMQW1o7", 258 | "type": "text", 259 | "x": 213.96938851570866, 260 | "y": 71.90020161066546, 261 | "width": 76.7999267578125, 262 | "height": 25, 263 | "angle": 0, 264 | "strokeColor": "#000000", 265 | "backgroundColor": "transparent", 266 | "fillStyle": "hachure", 267 | "strokeWidth": 1, 268 | "strokeStyle": "dashed", 269 | "roughness": 2, 270 | "opacity": 100, 271 | "groupIds": [], 272 | "roundness": null, 273 | "seed": 141265647, 274 | "version": 55, 275 | "versionNonce": 947445281, 276 | "isDeleted": false, 277 | "boundElements": null, 278 | "updated": 1691330433657, 279 | "link": null, 280 | "locked": false, 281 | "text": "Browser", 282 | "fontSize": 20, 283 | "fontFamily": 1, 284 | "textAlign": "left", 285 | "verticalAlign": "top", 286 | "baseline": 18, 287 | "containerId": null, 288 | "originalText": "Browser", 289 | "lineHeight": 1.25 290 | }, 291 | { 292 | "type": "line", 293 | "version": 223, 294 | "versionNonce": 1319391343, 295 | "isDeleted": false, 296 | "id": "Zv54BSI4jnxu0Ecco9f7j", 297 | "fillStyle": "hachure", 298 | "strokeWidth": 1, 299 | "strokeStyle": "dashed", 300 | "roughness": 2, 301 | "opacity": 100, 302 | "angle": 0, 303 | "x": 650.0320118116124, 304 | "y": 111.03929265693675, 305 | "strokeColor": "#000000", 306 | "backgroundColor": "transparent", 307 | "width": 0, 308 | "height": 275.41165068830554, 309 | "seed": 2038389697, 310 | "groupIds": [], 311 | "roundness": { 312 | "type": 2 313 | }, 314 | "boundElements": [], 315 | "updated": 1691330433657, 316 | "link": null, 317 | "locked": false, 318 | "startBinding": null, 319 | "endBinding": null, 320 | "lastCommittedPoint": null, 321 | "startArrowhead": null, 322 | "endArrowhead": null, 323 | "points": [ 324 | [ 325 | 0, 326 | 0 327 | ], 328 | [ 329 | 0, 330 | 275.41165068830554 331 | ] 332 | ] 333 | }, 334 | { 335 | "type": "text", 336 | "version": 140, 337 | "versionNonce": 416969217, 338 | "isDeleted": false, 339 | "id": "MlaPs2mOsRnB5tCCqSJ9E", 340 | "fillStyle": "hachure", 341 | "strokeWidth": 1, 342 | "strokeStyle": "dashed", 343 | "roughness": 2, 344 | "opacity": 100, 345 | "angle": 0, 346 | "x": 611.4661552354693, 347 | "y": 71.90020161066546, 348 | "strokeColor": "#000000", 349 | "backgroundColor": "transparent", 350 | "width": 61.69993591308594, 351 | "height": 25, 352 | "seed": 141265647, 353 | "groupIds": [], 354 | "roundness": null, 355 | "boundElements": [], 356 | "updated": 1691330433657, 357 | "link": null, 358 | "locked": false, 359 | "fontSize": 20, 360 | "fontFamily": 1, 361 | "text": "Server", 362 | "textAlign": "left", 363 | "verticalAlign": "top", 364 | "containerId": null, 365 | "originalText": "Server", 366 | "lineHeight": 1.25, 367 | "baseline": 18 368 | }, 369 | { 370 | "type": "line", 371 | "version": 329, 372 | "versionNonce": 852508847, 373 | "isDeleted": false, 374 | "id": "0Zul1m5mTo6XtkEbZ49JU", 375 | "fillStyle": "hachure", 376 | "strokeWidth": 1, 377 | "strokeStyle": "dashed", 378 | "roughness": 2, 379 | "opacity": 100, 380 | "angle": 0, 381 | "x": 868.2173596869725, 382 | "y": 112.04224285941908, 383 | "strokeColor": "#000000", 384 | "backgroundColor": "transparent", 385 | "width": 0, 386 | "height": 270.28292109847496, 387 | "seed": 2038389697, 388 | "groupIds": [], 389 | "roundness": { 390 | "type": 2 391 | }, 392 | "boundElements": [], 393 | "updated": 1691330433657, 394 | "link": null, 395 | "locked": false, 396 | "startBinding": null, 397 | "endBinding": null, 398 | "lastCommittedPoint": null, 399 | "startArrowhead": null, 400 | "endArrowhead": null, 401 | "points": [ 402 | [ 403 | 0, 404 | 0 405 | ], 406 | [ 407 | 0, 408 | 270.28292109847496 409 | ] 410 | ] 411 | }, 412 | { 413 | "type": "text", 414 | "version": 250, 415 | "versionNonce": 1372890561, 416 | "isDeleted": false, 417 | "id": "UKr3Y9qNN-vrxABBOfjvR", 418 | "fillStyle": "hachure", 419 | "strokeWidth": 1, 420 | "strokeStyle": "dashed", 421 | "roughness": 2, 422 | "opacity": 100, 423 | "angle": 0, 424 | "x": 829.9862324556109, 425 | "y": 71.90020161066546, 426 | "strokeColor": "#000000", 427 | "backgroundColor": "transparent", 428 | "width": 61.69993591308594, 429 | "height": 25, 430 | "seed": 141265647, 431 | "groupIds": [], 432 | "roundness": null, 433 | "boundElements": [], 434 | "updated": 1691330433657, 435 | "link": null, 436 | "locked": false, 437 | "fontSize": 20, 438 | "fontFamily": 1, 439 | "text": "Server", 440 | "textAlign": "left", 441 | "verticalAlign": "top", 442 | "containerId": null, 443 | "originalText": "Server", 444 | "lineHeight": 1.25, 445 | "baseline": 18 446 | }, 447 | { 448 | "id": "XIPJ_NjlpMGsn7fjo_XxJ", 449 | "type": "arrow", 450 | "x": 658.8162557668018, 451 | "y": 149.7345303687673, 452 | "width": 192.22788573439072, 453 | "height": 0.5229042993720441, 454 | "angle": 0, 455 | "strokeColor": "#000000", 456 | "backgroundColor": "transparent", 457 | "fillStyle": "hachure", 458 | "strokeWidth": 1, 459 | "strokeStyle": "solid", 460 | "roughness": 2, 461 | "opacity": 100, 462 | "groupIds": [], 463 | "roundness": { 464 | "type": 2 465 | }, 466 | "seed": 2125993327, 467 | "version": 64, 468 | "versionNonce": 1602376399, 469 | "isDeleted": false, 470 | "boundElements": null, 471 | "updated": 1691330433657, 472 | "link": null, 473 | "locked": false, 474 | "points": [ 475 | [ 476 | 0, 477 | 0 478 | ], 479 | [ 480 | 192.22788573439072, 481 | 0.5229042993720441 482 | ] 483 | ], 484 | "lastCommittedPoint": null, 485 | "startBinding": null, 486 | "endBinding": null, 487 | "startArrowhead": null, 488 | "endArrowhead": "arrow" 489 | }, 490 | { 491 | "id": "cgdroscIzIrXTtZTIIHXM", 492 | "type": "text", 493 | "x": 712.10626557221, 494 | "y": 115.17250681581527, 495 | "width": 79.87992858886719, 496 | "height": 25, 497 | "angle": 0, 498 | "strokeColor": "#000000", 499 | "backgroundColor": "transparent", 500 | "fillStyle": "hachure", 501 | "strokeWidth": 1, 502 | "strokeStyle": "solid", 503 | "roughness": 2, 504 | "opacity": 100, 505 | "groupIds": [], 506 | "roundness": null, 507 | "seed": 1307342369, 508 | "version": 63, 509 | "versionNonce": 245122465, 510 | "isDeleted": false, 511 | "boundElements": null, 512 | "updated": 1691330433657, 513 | "link": null, 514 | "locked": false, 515 | "text": "Request", 516 | "fontSize": 20, 517 | "fontFamily": 1, 518 | "textAlign": "left", 519 | "verticalAlign": "top", 520 | "baseline": 18, 521 | "containerId": null, 522 | "originalText": "Request", 523 | "lineHeight": 1.25 524 | }, 525 | { 526 | "id": "jBDTjhDB3Epf2qeJ4TRRD", 527 | "type": "arrow", 528 | "x": 850.4885844185607, 529 | "y": 199.33951666812627, 530 | "width": 187.10850729021286, 531 | "height": 1.9033932198536263, 532 | "angle": 0, 533 | "strokeColor": "#000000", 534 | "backgroundColor": "transparent", 535 | "fillStyle": "hachure", 536 | "strokeWidth": 1, 537 | "strokeStyle": "solid", 538 | "roughness": 2, 539 | "opacity": 100, 540 | "groupIds": [], 541 | "roundness": { 542 | "type": 2 543 | }, 544 | "seed": 876352911, 545 | "version": 88, 546 | "versionNonce": 1819091183, 547 | "isDeleted": false, 548 | "boundElements": [], 549 | "updated": 1691330433657, 550 | "link": null, 551 | "locked": false, 552 | "points": [ 553 | [ 554 | 0, 555 | 0 556 | ], 557 | [ 558 | -187.10850729021286, 559 | -1.9033932198536263 560 | ] 561 | ], 562 | "lastCommittedPoint": null, 563 | "startBinding": null, 564 | "endBinding": null, 565 | "startArrowhead": null, 566 | "endArrowhead": "arrow" 567 | }, 568 | { 569 | "id": "cCfyvdM6_FdAymJ0UJszj", 570 | "type": "text", 571 | "x": 726.7739603523269, 572 | "y": 165.60493200011402, 573 | "width": 53.199951171875, 574 | "height": 25, 575 | "angle": 0, 576 | "strokeColor": "#000000", 577 | "backgroundColor": "transparent", 578 | "fillStyle": "hachure", 579 | "strokeWidth": 1, 580 | "strokeStyle": "solid", 581 | "roughness": 2, 582 | "opacity": 100, 583 | "groupIds": [], 584 | "roundness": null, 585 | "seed": 2101882863, 586 | "version": 33, 587 | "versionNonce": 1259940623, 588 | "isDeleted": false, 589 | "boundElements": null, 590 | "updated": 1691330433657, 591 | "link": null, 592 | "locked": false, 593 | "text": "Chunk", 594 | "fontSize": 20, 595 | "fontFamily": 1, 596 | "textAlign": "left", 597 | "verticalAlign": "top", 598 | "baseline": 18, 599 | "containerId": null, 600 | "originalText": "Chunk", 601 | "lineHeight": 1.25 602 | }, 603 | { 604 | "type": "arrow", 605 | "version": 147, 606 | "versionNonce": 1856901473, 607 | "isDeleted": false, 608 | "id": "hkyZn97qH2cYcjmUzuMdH", 609 | "fillStyle": "hachure", 610 | "strokeWidth": 1, 611 | "strokeStyle": "solid", 612 | "roughness": 2, 613 | "opacity": 100, 614 | "angle": 0, 615 | "x": 850.0162748087364, 616 | "y": 245.82471430036577, 617 | "strokeColor": "#000000", 618 | "backgroundColor": "transparent", 619 | "width": 187.10850729021286, 620 | "height": 1.9033932198536263, 621 | "seed": 876352911, 622 | "groupIds": [], 623 | "roundness": { 624 | "type": 2 625 | }, 626 | "boundElements": [], 627 | "updated": 1691330433658, 628 | "link": null, 629 | "locked": false, 630 | "startBinding": null, 631 | "endBinding": null, 632 | "lastCommittedPoint": null, 633 | "startArrowhead": null, 634 | "endArrowhead": "arrow", 635 | "points": [ 636 | [ 637 | 0, 638 | 0 639 | ], 640 | [ 641 | -187.10850729021286, 642 | -1.9033932198536263 643 | ] 644 | ] 645 | }, 646 | { 647 | "type": "text", 648 | "version": 92, 649 | "versionNonce": 277298497, 650 | "isDeleted": false, 651 | "id": "Rviw5kR1Obx6iGpyD55t2", 652 | "fillStyle": "hachure", 653 | "strokeWidth": 1, 654 | "strokeStyle": "solid", 655 | "roughness": 2, 656 | "opacity": 100, 657 | "angle": 0, 658 | "x": 726.3016507425025, 659 | "y": 212.09012963235344, 660 | "strokeColor": "#000000", 661 | "backgroundColor": "transparent", 662 | "width": 53.199951171875, 663 | "height": 25, 664 | "seed": 2101882863, 665 | "groupIds": [], 666 | "roundness": null, 667 | "boundElements": [], 668 | "updated": 1691330433658, 669 | "link": null, 670 | "locked": false, 671 | "fontSize": 20, 672 | "fontFamily": 1, 673 | "text": "Chunk", 674 | "textAlign": "left", 675 | "verticalAlign": "top", 676 | "containerId": null, 677 | "originalText": "Chunk", 678 | "lineHeight": 1.25, 679 | "baseline": 18 680 | }, 681 | { 682 | "type": "arrow", 683 | "version": 207, 684 | "versionNonce": 210170703, 685 | "isDeleted": false, 686 | "id": "sUOEw4wbbKkmQPqEa0Xab", 687 | "fillStyle": "hachure", 688 | "strokeWidth": 1, 689 | "strokeStyle": "solid", 690 | "roughness": 2, 691 | "opacity": 100, 692 | "angle": 0, 693 | "x": 852.8704401882148, 694 | "y": 293.2756398723128, 695 | "strokeColor": "#000000", 696 | "backgroundColor": "transparent", 697 | "width": 187.10850729021286, 698 | "height": 1.9033932198536263, 699 | "seed": 876352911, 700 | "groupIds": [], 701 | "roundness": { 702 | "type": 2 703 | }, 704 | "boundElements": [], 705 | "updated": 1691330433658, 706 | "link": null, 707 | "locked": false, 708 | "startBinding": null, 709 | "endBinding": null, 710 | "lastCommittedPoint": null, 711 | "startArrowhead": null, 712 | "endArrowhead": "arrow", 713 | "points": [ 714 | [ 715 | 0, 716 | 0 717 | ], 718 | [ 719 | -187.10850729021286, 720 | -1.9033932198536263 721 | ] 722 | ] 723 | }, 724 | { 725 | "type": "text", 726 | "version": 152, 727 | "versionNonce": 1091154287, 728 | "isDeleted": false, 729 | "id": "KMfXfKwuQ_FKkwt0WdEMD", 730 | "fillStyle": "hachure", 731 | "strokeWidth": 1, 732 | "strokeStyle": "solid", 733 | "roughness": 2, 734 | "opacity": 100, 735 | "angle": 0, 736 | "x": 729.1558161219808, 737 | "y": 259.5410552043005, 738 | "strokeColor": "#000000", 739 | "backgroundColor": "transparent", 740 | "width": 53.199951171875, 741 | "height": 25, 742 | "seed": 2101882863, 743 | "groupIds": [], 744 | "roundness": null, 745 | "boundElements": [], 746 | "updated": 1691330433658, 747 | "link": null, 748 | "locked": false, 749 | "fontSize": 20, 750 | "fontFamily": 1, 751 | "text": "Chunk", 752 | "textAlign": "left", 753 | "verticalAlign": "top", 754 | "containerId": null, 755 | "originalText": "Chunk", 756 | "lineHeight": 1.25, 757 | "baseline": 18 758 | }, 759 | { 760 | "type": "arrow", 761 | "version": 273, 762 | "versionNonce": 1924636929, 763 | "isDeleted": false, 764 | "id": "sqpkp3ExOlJpQ7FY_EOPS", 765 | "fillStyle": "hachure", 766 | "strokeWidth": 1, 767 | "strokeStyle": "solid", 768 | "roughness": 2, 769 | "opacity": 100, 770 | "angle": 0, 771 | "x": 853.6364049939763, 772 | "y": 341.90079026036074, 773 | "strokeColor": "#000000", 774 | "backgroundColor": "transparent", 775 | "width": 187.10850729021286, 776 | "height": 1.9033932198536263, 777 | "seed": 876352911, 778 | "groupIds": [], 779 | "roundness": { 780 | "type": 2 781 | }, 782 | "boundElements": [], 783 | "updated": 1691330433658, 784 | "link": null, 785 | "locked": false, 786 | "startBinding": null, 787 | "endBinding": null, 788 | "lastCommittedPoint": null, 789 | "startArrowhead": null, 790 | "endArrowhead": "arrow", 791 | "points": [ 792 | [ 793 | 0, 794 | 0 795 | ], 796 | [ 797 | -187.10850729021286, 798 | -1.9033932198536263 799 | ] 800 | ] 801 | }, 802 | { 803 | "type": "text", 804 | "version": 218, 805 | "versionNonce": 1744689377, 806 | "isDeleted": false, 807 | "id": "o0LsQcCUCsxP7eVytgK8v", 808 | "fillStyle": "hachure", 809 | "strokeWidth": 1, 810 | "strokeStyle": "solid", 811 | "roughness": 2, 812 | "opacity": 100, 813 | "angle": 0, 814 | "x": 729.9217809277417, 815 | "y": 308.16620559234843, 816 | "strokeColor": "#000000", 817 | "backgroundColor": "transparent", 818 | "width": 53.199951171875, 819 | "height": 25, 820 | "seed": 2101882863, 821 | "groupIds": [], 822 | "roundness": null, 823 | "boundElements": [], 824 | "updated": 1691330433658, 825 | "link": null, 826 | "locked": false, 827 | "fontSize": 20, 828 | "fontFamily": 1, 829 | "text": "Chunk", 830 | "textAlign": "left", 831 | "verticalAlign": "top", 832 | "containerId": null, 833 | "originalText": "Chunk", 834 | "lineHeight": 1.25, 835 | "baseline": 18 836 | }, 837 | { 838 | "type": "arrow", 839 | "version": 588, 840 | "versionNonce": 34693551, 841 | "isDeleted": false, 842 | "id": "O9htuWnm3V5Xott_eKFX6", 843 | "fillStyle": "hachure", 844 | "strokeWidth": 1, 845 | "strokeStyle": "solid", 846 | "roughness": 1, 847 | "opacity": 100, 848 | "angle": 0, 849 | "x": 268.337276711934, 850 | "y": 341.717015481894, 851 | "strokeColor": "#000000", 852 | "backgroundColor": "transparent", 853 | "width": 327.236328125, 854 | "height": 25.310895370911506, 855 | "seed": 2020323279, 856 | "groupIds": [], 857 | "roundness": { 858 | "type": 2 859 | }, 860 | "boundElements": [], 861 | "updated": 1691330433658, 862 | "link": null, 863 | "locked": false, 864 | "startBinding": null, 865 | "endBinding": null, 866 | "lastCommittedPoint": null, 867 | "startArrowhead": null, 868 | "endArrowhead": "arrow", 869 | "points": [ 870 | [ 871 | 0, 872 | 0 873 | ], 874 | [ 875 | 322.6302185058594, 876 | 1.0336889301977306 877 | ], 878 | [ 879 | 323.8899841308594, 880 | 25.310895370911506 881 | ], 882 | [ 883 | -3.346343994140625, 884 | 25.10157638149778 885 | ] 886 | ] 887 | }, 888 | { 889 | "type": "text", 890 | "version": 340, 891 | "versionNonce": 1802638529, 892 | "isDeleted": false, 893 | "id": "PwQ4l4YAHb9qarM8MR2H6", 894 | "fillStyle": "hachure", 895 | "strokeWidth": 1, 896 | "strokeStyle": "solid", 897 | "roughness": 1, 898 | "opacity": 100, 899 | "angle": 0, 900 | "x": 284.64260508107475, 901 | "y": 300.0051139370445, 902 | "strokeColor": "#000000", 903 | "backgroundColor": "transparent", 904 | "width": 335.69976806640625, 905 | "height": 25, 906 | "seed": 1279565985, 907 | "groupIds": [], 908 | "roundness": null, 909 | "boundElements": [], 910 | "updated": 1691330433658, 911 | "link": null, 912 | "locked": false, 913 | "fontSize": 20, 914 | "fontFamily": 1, 915 | "text": "hx-get=\"/prompt/requestID=NNNN\"", 916 | "textAlign": "left", 917 | "verticalAlign": "top", 918 | "containerId": null, 919 | "originalText": "hx-get=\"/prompt/requestID=NNNN\"", 920 | "lineHeight": 1.25, 921 | "baseline": 18 922 | }, 923 | { 924 | "type": "arrow", 925 | "version": 535, 926 | "versionNonce": 1790508655, 927 | "isDeleted": false, 928 | "id": "1oNFWffh13MwWUn0O7tiQ", 929 | "fillStyle": "hachure", 930 | "strokeWidth": 1, 931 | "strokeStyle": "solid", 932 | "roughness": 1, 933 | "opacity": 100, 934 | "angle": 0, 935 | "x": 269.7836362017575, 936 | "y": 512.9120389992769, 937 | "strokeColor": "#000000", 938 | "backgroundColor": "#fd7e14", 939 | "width": 327.236328125, 940 | "height": 24.92271485120975, 941 | "seed": 2020323279, 942 | "groupIds": [], 943 | "roundness": { 944 | "type": 2 945 | }, 946 | "boundElements": [], 947 | "updated": 1691330610215, 948 | "link": null, 949 | "locked": false, 950 | "startBinding": null, 951 | "endBinding": null, 952 | "lastCommittedPoint": null, 953 | "startArrowhead": null, 954 | "endArrowhead": "arrow", 955 | "points": [ 956 | [ 957 | 0, 958 | 0 959 | ], 960 | [ 961 | 322.6302185058594, 962 | 1.0178357610287232 963 | ], 964 | [ 965 | 323.8899841308594, 966 | 24.92271485120975 967 | ], 968 | [ 969 | -3.346343994140625, 970 | 24.716606082252603 971 | ] 972 | ] 973 | }, 974 | { 975 | "type": "text", 976 | "version": 234, 977 | "versionNonce": 2016388097, 978 | "isDeleted": false, 979 | "id": "cK9Dg3iHLA8Ni0ltstKS9", 980 | "fillStyle": "hachure", 981 | "strokeWidth": 1, 982 | "strokeStyle": "solid", 983 | "roughness": 1, 984 | "opacity": 100, 985 | "angle": 0, 986 | "x": 292.5603085650387, 987 | "y": 485.33385917342815, 988 | "strokeColor": "#000000", 989 | "backgroundColor": "#fd7e14", 990 | "width": 159.267578125, 991 | "height": 23, 992 | "seed": 1279565985, 993 | "groupIds": [], 994 | "roundness": null, 995 | "boundElements": [], 996 | "updated": 1691330610215, 997 | "link": null, 998 | "locked": false, 999 | "fontSize": 20, 1000 | "fontFamily": 2, 1001 | "text": "hx-post=\"/prompt\"", 1002 | "textAlign": "left", 1003 | "verticalAlign": "top", 1004 | "containerId": null, 1005 | "originalText": "hx-post=\"/prompt\"", 1006 | "lineHeight": 1.15, 1007 | "baseline": 18 1008 | }, 1009 | { 1010 | "type": "arrow", 1011 | "version": 660, 1012 | "versionNonce": 520968335, 1013 | "isDeleted": false, 1014 | "id": "NfGdU2Zmgs6_CRWh93Jh8", 1015 | "fillStyle": "hachure", 1016 | "strokeWidth": 1, 1017 | "strokeStyle": "solid", 1018 | "roughness": 1, 1019 | "opacity": 100, 1020 | "angle": 0, 1021 | "x": 272.5122193145621, 1022 | "y": 582.2147928163727, 1023 | "strokeColor": "#000000", 1024 | "backgroundColor": "#fd7e14", 1025 | "width": 327.236328125, 1026 | "height": 25.310895370911506, 1027 | "seed": 2020323279, 1028 | "groupIds": [], 1029 | "roundness": { 1030 | "type": 2 1031 | }, 1032 | "boundElements": [], 1033 | "updated": 1691330610215, 1034 | "link": null, 1035 | "locked": false, 1036 | "startBinding": null, 1037 | "endBinding": null, 1038 | "lastCommittedPoint": null, 1039 | "startArrowhead": null, 1040 | "endArrowhead": "arrow", 1041 | "points": [ 1042 | [ 1043 | 0, 1044 | 0 1045 | ], 1046 | [ 1047 | 322.6302185058594, 1048 | 1.0336889301977306 1049 | ], 1050 | [ 1051 | 323.8899841308594, 1052 | 25.310895370911506 1053 | ], 1054 | [ 1055 | -3.346343994140625, 1056 | 25.10157638149778 1057 | ] 1058 | ] 1059 | }, 1060 | { 1061 | "type": "text", 1062 | "version": 438, 1063 | "versionNonce": 628980705, 1064 | "isDeleted": false, 1065 | "id": "bfOBIawez-YEn6X6qP4aY", 1066 | "fillStyle": "hachure", 1067 | "strokeWidth": 1, 1068 | "strokeStyle": "solid", 1069 | "roughness": 1, 1070 | "opacity": 100, 1071 | "angle": 0, 1072 | "x": 365.2652186808823, 1073 | "y": 554.7854258866198, 1074 | "strokeColor": "#000000", 1075 | "backgroundColor": "#fd7e14", 1076 | "width": 149.267578125, 1077 | "height": 23, 1078 | "seed": 1279565985, 1079 | "groupIds": [], 1080 | "roundness": null, 1081 | "boundElements": [], 1082 | "updated": 1691330610215, 1083 | "link": null, 1084 | "locked": false, 1085 | "fontSize": 20, 1086 | "fontFamily": 2, 1087 | "text": "hx-get=\"/prompt\"", 1088 | "textAlign": "left", 1089 | "verticalAlign": "top", 1090 | "containerId": null, 1091 | "originalText": "hx-get=\"/prompt\"", 1092 | "lineHeight": 1.15, 1093 | "baseline": 18 1094 | }, 1095 | { 1096 | "type": "text", 1097 | "version": 215, 1098 | "versionNonce": 403795631, 1099 | "isDeleted": false, 1100 | "id": "YLTqkMAHZ33l-3KvJ0_NT", 1101 | "fillStyle": "hachure", 1102 | "strokeWidth": 1, 1103 | "strokeStyle": "solid", 1104 | "roughness": 1, 1105 | "opacity": 100, 1106 | "angle": 0, 1107 | "x": 473.90341769589816, 1108 | "y": 484.137219110283, 1109 | "strokeColor": "#000000", 1110 | "backgroundColor": "#fd7e14", 1111 | "width": 107.294921875, 1112 | "height": 23, 1113 | "seed": 725740001, 1114 | "groupIds": [], 1115 | "roundness": null, 1116 | "boundElements": [], 1117 | "updated": 1691330610215, 1118 | "link": null, 1119 | "locked": false, 1120 | "fontSize": 20, 1121 | "fontFamily": 2, 1122 | "text": "prompt=dog", 1123 | "textAlign": "left", 1124 | "verticalAlign": "top", 1125 | "containerId": null, 1126 | "originalText": "prompt=dog", 1127 | "lineHeight": 1.15, 1128 | "baseline": 18 1129 | }, 1130 | { 1131 | "type": "line", 1132 | "version": 282, 1133 | "versionNonce": 1057314753, 1134 | "isDeleted": false, 1135 | "id": "9RecD00waicbu6REPpvte", 1136 | "fillStyle": "hachure", 1137 | "strokeWidth": 1, 1138 | "strokeStyle": "dashed", 1139 | "roughness": 2, 1140 | "opacity": 100, 1141 | "angle": 0, 1142 | "x": 257.7328396929684, 1143 | "y": 482.8299805641911, 1144 | "strokeColor": "#000000", 1145 | "backgroundColor": "#fd7e14", 1146 | "width": 2.842170943040401e-14, 1147 | "height": 280.5695685264637, 1148 | "seed": 2038389697, 1149 | "groupIds": [], 1150 | "roundness": { 1151 | "type": 2 1152 | }, 1153 | "boundElements": [], 1154 | "updated": 1691330610215, 1155 | "link": null, 1156 | "locked": false, 1157 | "startBinding": null, 1158 | "endBinding": null, 1159 | "lastCommittedPoint": null, 1160 | "startArrowhead": null, 1161 | "endArrowhead": null, 1162 | "points": [ 1163 | [ 1164 | 0, 1165 | 0 1166 | ], 1167 | [ 1168 | -2.842170943040401e-14, 1169 | 280.5695685264637 1170 | ] 1171 | ] 1172 | }, 1173 | { 1174 | "type": "text", 1175 | "version": 129, 1176 | "versionNonce": 544063695, 1177 | "isDeleted": false, 1178 | "id": "-BXIVo0DZuDy39_jvhSIS", 1179 | "fillStyle": "hachure", 1180 | "strokeWidth": 1, 1181 | "strokeStyle": "dashed", 1182 | "roughness": 2, 1183 | "opacity": 100, 1184 | "angle": 0, 1185 | "x": 219.50171246160676, 1186 | "y": 439.96455717485657, 1187 | "strokeColor": "#000000", 1188 | "backgroundColor": "#fd7e14", 1189 | "width": 76.7999267578125, 1190 | "height": 25, 1191 | "seed": 141265647, 1192 | "groupIds": [], 1193 | "roundness": null, 1194 | "boundElements": [], 1195 | "updated": 1691330610215, 1196 | "link": null, 1197 | "locked": false, 1198 | "fontSize": 20, 1199 | "fontFamily": 1, 1200 | "text": "Browser", 1201 | "textAlign": "left", 1202 | "verticalAlign": "top", 1203 | "containerId": null, 1204 | "originalText": "Browser", 1205 | "lineHeight": 1.25, 1206 | "baseline": 18 1207 | }, 1208 | { 1209 | "type": "line", 1210 | "version": 297, 1211 | "versionNonce": 921089953, 1212 | "isDeleted": false, 1213 | "id": "jFODt25008dI3Kluo65nl", 1214 | "fillStyle": "hachure", 1215 | "strokeWidth": 1, 1216 | "strokeStyle": "dashed", 1217 | "roughness": 2, 1218 | "opacity": 100, 1219 | "angle": 0, 1220 | "x": 655.5643357575104, 1221 | "y": 479.10364822112786, 1222 | "strokeColor": "#000000", 1223 | "backgroundColor": "#fd7e14", 1224 | "width": 0, 1225 | "height": 275.41165068830554, 1226 | "seed": 2038389697, 1227 | "groupIds": [], 1228 | "roundness": { 1229 | "type": 2 1230 | }, 1231 | "boundElements": [], 1232 | "updated": 1691330610215, 1233 | "link": null, 1234 | "locked": false, 1235 | "startBinding": null, 1236 | "endBinding": null, 1237 | "lastCommittedPoint": null, 1238 | "startArrowhead": null, 1239 | "endArrowhead": null, 1240 | "points": [ 1241 | [ 1242 | 0, 1243 | 0 1244 | ], 1245 | [ 1246 | 0, 1247 | 275.41165068830554 1248 | ] 1249 | ] 1250 | }, 1251 | { 1252 | "type": "text", 1253 | "version": 214, 1254 | "versionNonce": 431673071, 1255 | "isDeleted": false, 1256 | "id": "249QOK2801bbT5bMRo0aX", 1257 | "fillStyle": "hachure", 1258 | "strokeWidth": 1, 1259 | "strokeStyle": "dashed", 1260 | "roughness": 2, 1261 | "opacity": 100, 1262 | "angle": 0, 1263 | "x": 616.9984791813674, 1264 | "y": 439.96455717485657, 1265 | "strokeColor": "#000000", 1266 | "backgroundColor": "#fd7e14", 1267 | "width": 61.69993591308594, 1268 | "height": 25, 1269 | "seed": 141265647, 1270 | "groupIds": [], 1271 | "roundness": null, 1272 | "boundElements": [], 1273 | "updated": 1691330610215, 1274 | "link": null, 1275 | "locked": false, 1276 | "fontSize": 20, 1277 | "fontFamily": 1, 1278 | "text": "Server", 1279 | "textAlign": "left", 1280 | "verticalAlign": "top", 1281 | "containerId": null, 1282 | "originalText": "Server", 1283 | "lineHeight": 1.25, 1284 | "baseline": 18 1285 | }, 1286 | { 1287 | "type": "arrow", 1288 | "version": 734, 1289 | "versionNonce": 256973697, 1290 | "isDeleted": false, 1291 | "id": "tBGtGiL2bl8MIOxAIJxrG", 1292 | "fillStyle": "hachure", 1293 | "strokeWidth": 1, 1294 | "strokeStyle": "solid", 1295 | "roughness": 1, 1296 | "opacity": 100, 1297 | "angle": 0, 1298 | "x": 276.30866693037655, 1299 | "y": 645.6770657694974, 1300 | "strokeColor": "#000000", 1301 | "backgroundColor": "#fd7e14", 1302 | "width": 327.236328125, 1303 | "height": 25.310895370911506, 1304 | "seed": 2020323279, 1305 | "groupIds": [], 1306 | "roundness": { 1307 | "type": 2 1308 | }, 1309 | "boundElements": [], 1310 | "updated": 1691330610215, 1311 | "link": null, 1312 | "locked": false, 1313 | "startBinding": null, 1314 | "endBinding": null, 1315 | "lastCommittedPoint": null, 1316 | "startArrowhead": null, 1317 | "endArrowhead": "arrow", 1318 | "points": [ 1319 | [ 1320 | 0, 1321 | 0 1322 | ], 1323 | [ 1324 | 322.6302185058594, 1325 | 1.0336889301977306 1326 | ], 1327 | [ 1328 | 323.8899841308594, 1329 | 25.310895370911506 1330 | ], 1331 | [ 1332 | -3.346343994140625, 1333 | 25.10157638149778 1334 | ] 1335 | ] 1336 | }, 1337 | { 1338 | "type": "text", 1339 | "version": 536, 1340 | "versionNonce": 511777039, 1341 | "isDeleted": false, 1342 | "id": "RotnmZphMKJ6SIlhmugVz", 1343 | "fillStyle": "hachure", 1344 | "strokeWidth": 1, 1345 | "strokeStyle": "solid", 1346 | "roughness": 1, 1347 | "opacity": 100, 1348 | "angle": 0, 1349 | "x": 369.0660530945875, 1350 | "y": 620.1626823963662, 1351 | "strokeColor": "#000000", 1352 | "backgroundColor": "#fd7e14", 1353 | "width": 149.267578125, 1354 | "height": 23, 1355 | "seed": 1279565985, 1356 | "groupIds": [], 1357 | "roundness": null, 1358 | "boundElements": [], 1359 | "updated": 1691330610215, 1360 | "link": null, 1361 | "locked": false, 1362 | "fontSize": 20, 1363 | "fontFamily": 2, 1364 | "text": "hx-get=\"/prompt\"", 1365 | "textAlign": "left", 1366 | "verticalAlign": "top", 1367 | "containerId": null, 1368 | "originalText": "hx-get=\"/prompt\"", 1369 | "lineHeight": 1.15, 1370 | "baseline": 18 1371 | }, 1372 | { 1373 | "type": "arrow", 1374 | "version": 828, 1375 | "versionNonce": 1485046625, 1376 | "isDeleted": false, 1377 | "id": "QV6dIEjF2o5cGzTJDOIsd", 1378 | "fillStyle": "hachure", 1379 | "strokeWidth": 1, 1380 | "strokeStyle": "solid", 1381 | "roughness": 1, 1382 | "opacity": 100, 1383 | "angle": 0, 1384 | "x": 277.59242608671076, 1385 | "y": 707.9111189747364, 1386 | "strokeColor": "#000000", 1387 | "backgroundColor": "#fd7e14", 1388 | "width": 327.236328125, 1389 | "height": 25.310895370911506, 1390 | "seed": 2020323279, 1391 | "groupIds": [], 1392 | "roundness": { 1393 | "type": 2 1394 | }, 1395 | "boundElements": [], 1396 | "updated": 1691330610215, 1397 | "link": null, 1398 | "locked": false, 1399 | "startBinding": null, 1400 | "endBinding": null, 1401 | "lastCommittedPoint": null, 1402 | "startArrowhead": null, 1403 | "endArrowhead": "arrow", 1404 | "points": [ 1405 | [ 1406 | 0, 1407 | 0 1408 | ], 1409 | [ 1410 | 322.6302185058594, 1411 | 1.0336889301977306 1412 | ], 1413 | [ 1414 | 323.8899841308594, 1415 | 25.310895370911506 1416 | ], 1417 | [ 1418 | -3.346343994140625, 1419 | 25.10157638149778 1420 | ] 1421 | ] 1422 | }, 1423 | { 1424 | "type": "text", 1425 | "version": 622, 1426 | "versionNonce": 1681465135, 1427 | "isDeleted": false, 1428 | "id": "4nMS8Yr5xwWLlIbDgtLnQ", 1429 | "fillStyle": "hachure", 1430 | "strokeWidth": 1, 1431 | "strokeStyle": "solid", 1432 | "roughness": 1, 1433 | "opacity": 100, 1434 | "angle": 0, 1435 | "x": 370.34542545303094, 1436 | "y": 681.6356771835632, 1437 | "strokeColor": "#000000", 1438 | "backgroundColor": "#fd7e14", 1439 | "width": 149.267578125, 1440 | "height": 23, 1441 | "seed": 1279565985, 1442 | "groupIds": [], 1443 | "roundness": null, 1444 | "boundElements": [], 1445 | "updated": 1691330610215, 1446 | "link": null, 1447 | "locked": false, 1448 | "fontSize": 20, 1449 | "fontFamily": 2, 1450 | "text": "hx-get=\"/prompt\"", 1451 | "textAlign": "left", 1452 | "verticalAlign": "top", 1453 | "containerId": null, 1454 | "originalText": "hx-get=\"/prompt\"", 1455 | "lineHeight": 1.15, 1456 | "baseline": 18 1457 | }, 1458 | { 1459 | "id": "t3BTB_IpDKyxBDb8Qnbdh", 1460 | "type": "arrow", 1461 | "x": 119.09676891007024, 1462 | "y": 508.4940223166074, 1463 | "width": 118.17756238978194, 1464 | "height": 0.39286672053776783, 1465 | "angle": 0, 1466 | "strokeColor": "#000000", 1467 | "backgroundColor": "#fd7e14", 1468 | "fillStyle": "hachure", 1469 | "strokeWidth": 1, 1470 | "strokeStyle": "solid", 1471 | "roughness": 2, 1472 | "opacity": 100, 1473 | "groupIds": [], 1474 | "roundness": { 1475 | "type": 2 1476 | }, 1477 | "seed": 1219944463, 1478 | "version": 303, 1479 | "versionNonce": 1859055425, 1480 | "isDeleted": false, 1481 | "boundElements": null, 1482 | "updated": 1691330610215, 1483 | "link": null, 1484 | "locked": false, 1485 | "points": [ 1486 | [ 1487 | 0, 1488 | 0 1489 | ], 1490 | [ 1491 | 118.17756238978194, 1492 | -0.39286672053776783 1493 | ] 1494 | ], 1495 | "lastCommittedPoint": null, 1496 | "startBinding": { 1497 | "elementId": "krFCl6XBNQ47F5H02XbQf", 1498 | "focus": 1.542179362045189, 1499 | "gap": 7.2587396076770005 1500 | }, 1501 | "endBinding": null, 1502 | "startArrowhead": null, 1503 | "endArrowhead": "arrow" 1504 | }, 1505 | { 1506 | "id": "krFCl6XBNQ47F5H02XbQf", 1507 | "type": "text", 1508 | "x": 118.62440182398382, 1509 | "y": 476.2352827089304, 1510 | "width": 111.1328125, 1511 | "height": 23, 1512 | "angle": 0, 1513 | "strokeColor": "#000000", 1514 | "backgroundColor": "#fd7e14", 1515 | "fillStyle": "hachure", 1516 | "strokeWidth": 1, 1517 | "strokeStyle": "solid", 1518 | "roughness": 2, 1519 | "opacity": 100, 1520 | "groupIds": [], 1521 | "roundness": null, 1522 | "seed": 668400111, 1523 | "version": 68, 1524 | "versionNonce": 1565221199, 1525 | "isDeleted": false, 1526 | "boundElements": [ 1527 | { 1528 | "id": "t3BTB_IpDKyxBDb8Qnbdh", 1529 | "type": "arrow" 1530 | } 1531 | ], 1532 | "updated": 1691330610215, 1533 | "link": null, 1534 | "locked": false, 1535 | "text": "Click Submit", 1536 | "fontSize": 20, 1537 | "fontFamily": 2, 1538 | "textAlign": "left", 1539 | "verticalAlign": "top", 1540 | "baseline": 18, 1541 | "containerId": null, 1542 | "originalText": "Click Submit", 1543 | "lineHeight": 1.15 1544 | }, 1545 | { 1546 | "type": "arrow", 1547 | "version": 294, 1548 | "versionNonce": 2022792993, 1549 | "isDeleted": false, 1550 | "id": "IF5ujMJ9opuF1ZnXTCtF_", 1551 | "fillStyle": "hachure", 1552 | "strokeWidth": 1, 1553 | "strokeStyle": "solid", 1554 | "roughness": 2, 1555 | "opacity": 100, 1556 | "angle": 0, 1557 | "x": 121.07442844597438, 1558 | "y": 583.8136104162263, 1559 | "strokeColor": "#000000", 1560 | "backgroundColor": "#fd7e14", 1561 | "width": 116.17540159421804, 1562 | "height": 0, 1563 | "seed": 1219944463, 1564 | "groupIds": [], 1565 | "roundness": { 1566 | "type": 2 1567 | }, 1568 | "boundElements": [], 1569 | "updated": 1691330610215, 1570 | "link": null, 1571 | "locked": false, 1572 | "startBinding": { 1573 | "elementId": "LdFRHzmarEzcZlgKJn4T7", 1574 | "focus": 2.0448647401583275, 1575 | "gap": 13.060809251979094 1576 | }, 1577 | "endBinding": null, 1578 | "lastCommittedPoint": null, 1579 | "startArrowhead": null, 1580 | "endArrowhead": "arrow", 1581 | "points": [ 1582 | [ 1583 | 0, 1584 | 0 1585 | ], 1586 | [ 1587 | 116.17540159421804, 1588 | 0 1589 | ] 1590 | ] 1591 | }, 1592 | { 1593 | "type": "text", 1594 | "version": 164, 1595 | "versionNonce": 454057839, 1596 | "isDeleted": false, 1597 | "id": "LdFRHzmarEzcZlgKJn4T7", 1598 | "fillStyle": "hachure", 1599 | "strokeWidth": 1, 1600 | "strokeStyle": "solid", 1601 | "roughness": 2, 1602 | "opacity": 100, 1603 | "angle": 0, 1604 | "x": 120.08312878210933, 1605 | "y": 545.7528011642472, 1606 | "strokeColor": "#000000", 1607 | "backgroundColor": "#fd7e14", 1608 | "width": 108.3984375, 1609 | "height": 23, 1610 | "seed": 668400111, 1611 | "groupIds": [], 1612 | "roundness": null, 1613 | "boundElements": [ 1614 | { 1615 | "id": "IF5ujMJ9opuF1ZnXTCtF_", 1616 | "type": "arrow" 1617 | } 1618 | ], 1619 | "updated": 1691330610215, 1620 | "link": null, 1621 | "locked": false, 1622 | "fontSize": 20, 1623 | "fontFamily": 2, 1624 | "text": "delay=50ms", 1625 | "textAlign": "left", 1626 | "verticalAlign": "top", 1627 | "containerId": null, 1628 | "originalText": "delay=50ms", 1629 | "lineHeight": 1.15, 1630 | "baseline": 18 1631 | }, 1632 | { 1633 | "type": "arrow", 1634 | "version": 428, 1635 | "versionNonce": 607834881, 1636 | "isDeleted": false, 1637 | "id": "TsjGxoE2szClsEh32KdM_", 1638 | "fillStyle": "hachure", 1639 | "strokeWidth": 1, 1640 | "strokeStyle": "solid", 1641 | "roughness": 2, 1642 | "opacity": 100, 1643 | "angle": 0, 1644 | "x": 122.40944207968043, 1645 | "y": 647.3450737580084, 1646 | "strokeColor": "#000000", 1647 | "backgroundColor": "#fd7e14", 1648 | "width": 116.17540159421804, 1649 | "height": 0, 1650 | "seed": 1219944463, 1651 | "groupIds": [], 1652 | "roundness": { 1653 | "type": 2 1654 | }, 1655 | "boundElements": [], 1656 | "updated": 1691330610215, 1657 | "link": null, 1658 | "locked": false, 1659 | "startBinding": { 1660 | "elementId": "cmdcry4sPvZ_tQ9yxdzAG", 1661 | "focus": 2.0448647401583187, 1662 | "gap": 13.06080925197898 1663 | }, 1664 | "endBinding": null, 1665 | "lastCommittedPoint": null, 1666 | "startArrowhead": null, 1667 | "endArrowhead": "arrow", 1668 | "points": [ 1669 | [ 1670 | 0, 1671 | 0 1672 | ], 1673 | [ 1674 | 116.17540159421804, 1675 | 0 1676 | ] 1677 | ] 1678 | }, 1679 | { 1680 | "type": "text", 1681 | "version": 231, 1682 | "versionNonce": 1875941775, 1683 | "isDeleted": false, 1684 | "id": "cmdcry4sPvZ_tQ9yxdzAG", 1685 | "fillStyle": "hachure", 1686 | "strokeWidth": 1, 1687 | "strokeStyle": "solid", 1688 | "roughness": 2, 1689 | "opacity": 100, 1690 | "angle": 0, 1691 | "x": 121.41814241581532, 1692 | "y": 609.2842645060294, 1693 | "strokeColor": "#000000", 1694 | "backgroundColor": "#fd7e14", 1695 | "width": 108.3984375, 1696 | "height": 23, 1697 | "seed": 668400111, 1698 | "groupIds": [], 1699 | "roundness": null, 1700 | "boundElements": [ 1701 | { 1702 | "id": "TsjGxoE2szClsEh32KdM_", 1703 | "type": "arrow" 1704 | } 1705 | ], 1706 | "updated": 1691330610215, 1707 | "link": null, 1708 | "locked": false, 1709 | "fontSize": 20, 1710 | "fontFamily": 2, 1711 | "text": "delay=50ms", 1712 | "textAlign": "left", 1713 | "verticalAlign": "top", 1714 | "containerId": null, 1715 | "originalText": "delay=50ms", 1716 | "lineHeight": 1.15, 1717 | "baseline": 18 1718 | }, 1719 | { 1720 | "type": "arrow", 1721 | "version": 550, 1722 | "versionNonce": 642435809, 1723 | "isDeleted": false, 1724 | "id": "Z5YtutYl9IZV0WxIhDrMk", 1725 | "fillStyle": "hachure", 1726 | "strokeWidth": 1, 1727 | "strokeStyle": "solid", 1728 | "roughness": 2, 1729 | "opacity": 100, 1730 | "angle": 0, 1731 | "x": 123.8520778124547, 1732 | "y": 710.8098720809203, 1733 | "strokeColor": "#000000", 1734 | "backgroundColor": "#fd7e14", 1735 | "width": 116.17540159421804, 1736 | "height": 0, 1737 | "seed": 1219944463, 1738 | "groupIds": [], 1739 | "roundness": { 1740 | "type": 2 1741 | }, 1742 | "boundElements": [], 1743 | "updated": 1691330610215, 1744 | "link": null, 1745 | "locked": false, 1746 | "startBinding": { 1747 | "elementId": "m0dSu4vbhIEyBwQDmjabX", 1748 | "focus": 2.0448647401583004, 1749 | "gap": 13.060809251978753 1750 | }, 1751 | "endBinding": null, 1752 | "lastCommittedPoint": null, 1753 | "startArrowhead": null, 1754 | "endArrowhead": "arrow", 1755 | "points": [ 1756 | [ 1757 | 0, 1758 | 0 1759 | ], 1760 | [ 1761 | 116.17540159421804, 1762 | 0 1763 | ] 1764 | ] 1765 | }, 1766 | { 1767 | "type": "text", 1768 | "version": 292, 1769 | "versionNonce": 1355059119, 1770 | "isDeleted": false, 1771 | "id": "m0dSu4vbhIEyBwQDmjabX", 1772 | "fillStyle": "hachure", 1773 | "strokeWidth": 1, 1774 | "strokeStyle": "solid", 1775 | "roughness": 2, 1776 | "opacity": 100, 1777 | "angle": 0, 1778 | "x": 122.86077814858959, 1779 | "y": 672.7490628289415, 1780 | "strokeColor": "#000000", 1781 | "backgroundColor": "#fd7e14", 1782 | "width": 108.3984375, 1783 | "height": 23, 1784 | "seed": 668400111, 1785 | "groupIds": [], 1786 | "roundness": null, 1787 | "boundElements": [ 1788 | { 1789 | "id": "Z5YtutYl9IZV0WxIhDrMk", 1790 | "type": "arrow" 1791 | } 1792 | ], 1793 | "updated": 1691330610215, 1794 | "link": null, 1795 | "locked": false, 1796 | "fontSize": 20, 1797 | "fontFamily": 2, 1798 | "text": "delay=50ms", 1799 | "textAlign": "left", 1800 | "verticalAlign": "top", 1801 | "containerId": null, 1802 | "originalText": "delay=50ms", 1803 | "lineHeight": 1.15, 1804 | "baseline": 18 1805 | } 1806 | ], 1807 | "appState": { 1808 | "gridSize": null, 1809 | "viewBackgroundColor": "#ffffff" 1810 | }, 1811 | "files": {} 1812 | } -------------------------------------------------------------------------------- /htmx-ai/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "htmx-ai", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro build", 9 | "preview": "astro preview", 10 | "astro": "astro" 11 | }, 12 | "dependencies": { 13 | "@astrojs/tailwind": "^4.0.0", 14 | "astro": "^2.10.1", 15 | "tailwindcss": "^3.3.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /htmx-ai/public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /htmx-ai/public/htmx.js: -------------------------------------------------------------------------------- 1 | (function(e,t){if(typeof define==="function"&&define.amd){define([],t)}else if(typeof module==="object"&&module.exports){module.exports=t()}else{e.htmx=e.htmx||t()}})(typeof self!=="undefined"?self:this,function(){return function(){"use strict";var G={onLoad:t,process:Nt,on:ue,off:fe,trigger:oe,ajax:mr,find:b,findAll:f,closest:d,values:function(e,t){var r=Qt(e,t||"post");return r.values},remove:B,addClass:V,removeClass:n,toggleClass:j,takeClass:W,defineExtension:Er,removeExtension:Cr,logAll:F,logNone:U,logger:null,config:{historyEnabled:true,historyCacheSize:10,refreshOnHistoryMiss:false,defaultSwapStyle:"innerHTML",defaultSwapDelay:0,defaultSettleDelay:20,includeIndicatorStyles:true,indicatorClass:"htmx-indicator",requestClass:"htmx-request",addedClass:"htmx-added",settlingClass:"htmx-settling",swappingClass:"htmx-swapping",allowEval:true,inlineScriptNonce:"",attributesToSettle:["class","style","width","height"],withCredentials:false,timeout:0,wsReconnectDelay:"full-jitter",wsBinaryType:"blob",disableSelector:"[hx-disable], [data-hx-disable]",useTemplateFragments:false,scrollBehavior:"smooth",defaultFocusScroll:false,getCacheBusterParam:false,globalViewTransitions:false,methodsThatUseUrlParams:["get"]},parseInterval:v,_:e,createEventSource:function(e){return new EventSource(e,{withCredentials:true})},createWebSocket:function(e){var t=new WebSocket(e,[]);t.binaryType=G.config.wsBinaryType;return t},version:"1.9.3"};var C={addTriggerHandler:bt,bodyContains:re,canAccessLocalStorage:D,findThisElement:de,filterValues:ir,hasAttribute:q,getAttributeValue:Z,getClosestAttributeValue:Y,getClosestMatch:c,getExpressionVars:vr,getHeaders:nr,getInputValues:Qt,getInternalData:ee,getSwapSpecification:or,getTriggerSpecs:Ge,getTarget:ve,makeFragment:l,mergeObjects:ne,makeSettleInfo:S,oobSwap:xe,querySelectorExt:ie,selectAndSwap:Xe,settleImmediately:Wt,shouldCancel:Qe,triggerEvent:oe,triggerErrorEvent:ae,withExtensions:w};var R=["get","post","put","delete","patch"];var O=R.map(function(e){return"[hx-"+e+"], [data-hx-"+e+"]"}).join(", ");function v(e){if(e==undefined){return undefined}if(e.slice(-2)=="ms"){return parseFloat(e.slice(0,-2))||undefined}if(e.slice(-1)=="s"){return parseFloat(e.slice(0,-1))*1e3||undefined}if(e.slice(-1)=="m"){return parseFloat(e.slice(0,-1))*1e3*60||undefined}return parseFloat(e)||undefined}function J(e,t){return e.getAttribute&&e.getAttribute(t)}function q(e,t){return e.hasAttribute&&(e.hasAttribute(t)||e.hasAttribute("data-"+t))}function Z(e,t){return J(e,t)||J(e,"data-"+t)}function u(e){return e.parentElement}function K(){return document}function c(e,t){while(e&&!t(e)){e=u(e)}return e?e:null}function T(e,t,r){var n=Z(t,r);var i=Z(t,"hx-disinherit");if(e!==t&&i&&(i==="*"||i.split(" ").indexOf(r)>=0)){return"unset"}else{return n}}function Y(t,r){var n=null;c(t,function(e){return n=T(t,e,r)});if(n!=="unset"){return n}}function h(e,t){var r=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector;return r&&r.call(e,t)}function H(e){var t=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i;var r=t.exec(e);if(r){return r[1].toLowerCase()}else{return""}}function i(e,t){var r=new DOMParser;var n=r.parseFromString(e,"text/html");var i=n.body;while(t>0){t--;i=i.firstChild}if(i==null){i=K().createDocumentFragment()}return i}function L(e){return e.match(/",0);return r.querySelector("template").content}else{var n=H(e);switch(n){case"thead":case"tbody":case"tfoot":case"colgroup":case"caption":return i(""+e+"
",1);case"col":return i(""+e+"
",2);case"tr":return i(""+e+"
",2);case"td":case"th":return i(""+e+"
",3);case"script":return i("
"+e+"
",1);default:return i(e,0)}}}function Q(e){if(e){e()}}function A(e,t){return Object.prototype.toString.call(e)==="[object "+t+"]"}function N(e){return A(e,"Function")}function I(e){return A(e,"Object")}function ee(e){var t="htmx-internal-data";var r=e[t];if(!r){r=e[t]={}}return r}function k(e){var t=[];if(e){for(var r=0;r=0}function re(e){if(e.getRootNode&&e.getRootNode()instanceof ShadowRoot){return K().body.contains(e.getRootNode().host)}else{return K().body.contains(e)}}function M(e){return e.trim().split(/\s+/)}function ne(e,t){for(var r in t){if(t.hasOwnProperty(r)){e[r]=t[r]}}return e}function y(e){try{return JSON.parse(e)}catch(e){x(e);return null}}function D(){var e="htmx:localStorageTest";try{localStorage.setItem(e,e);localStorage.removeItem(e);return true}catch(e){return false}}function X(t){try{var e=new URL(t);if(e){t=e.pathname+e.search}if(!t.match("^/$")){t=t.replace(/\/+$/,"")}return t}catch(e){return t}}function e(e){return cr(K().body,function(){return eval(e)})}function t(t){var e=G.on("htmx:load",function(e){t(e.detail.elt)});return e}function F(){G.logger=function(e,t,r){if(console){console.log(t,e,r)}}}function U(){G.logger=null}function b(e,t){if(t){return e.querySelector(t)}else{return b(K(),e)}}function f(e,t){if(t){return e.querySelectorAll(t)}else{return f(K(),e)}}function B(e,t){e=s(e);if(t){setTimeout(function(){B(e);e=null},t)}else{e.parentElement.removeChild(e)}}function V(e,t,r){e=s(e);if(r){setTimeout(function(){V(e,t);e=null},r)}else{e.classList&&e.classList.add(t)}}function n(e,t,r){e=s(e);if(r){setTimeout(function(){n(e,t);e=null},r)}else{if(e.classList){e.classList.remove(t);if(e.classList.length===0){e.removeAttribute("class")}}}}function j(e,t){e=s(e);e.classList.toggle(t)}function W(e,t){e=s(e);te(e.parentElement.children,function(e){n(e,t)});V(e,t)}function d(e,t){e=s(e);if(e.closest){return e.closest(t)}else{do{if(e==null||h(e,t)){return e}}while(e=e&&u(e));return null}}function r(e){var t=e.trim();if(t.startsWith("<")&&t.endsWith("/>")){return t.substring(1,t.length-2)}else{return t}}function _(e,t){if(t.indexOf("closest ")===0){return[d(e,r(t.substr(8)))]}else if(t.indexOf("find ")===0){return[b(e,r(t.substr(5)))]}else if(t.indexOf("next ")===0){return[z(e,r(t.substr(5)))]}else if(t.indexOf("previous ")===0){return[$(e,r(t.substr(9)))]}else if(t==="document"){return[document]}else if(t==="window"){return[window]}else{return K().querySelectorAll(r(t))}}var z=function(e,t){var r=K().querySelectorAll(t);for(var n=0;n=0;n--){var i=r[n];if(i.compareDocumentPosition(e)===Node.DOCUMENT_POSITION_FOLLOWING){return i}}};function ie(e,t){if(t){return _(e,t)[0]}else{return _(K().body,e)[0]}}function s(e){if(A(e,"String")){return b(e)}else{return e}}function le(e,t,r){if(N(t)){return{target:K().body,event:e,listener:t}}else{return{target:s(e),event:t,listener:r}}}function ue(t,r,n){Or(function(){var e=le(t,r,n);e.target.addEventListener(e.event,e.listener)});var e=N(r);return e?r:n}function fe(t,r,n){Or(function(){var e=le(t,r,n);e.target.removeEventListener(e.event,e.listener)});return N(r)?r:n}var ce=K().createElement("output");function he(e,t){var r=Y(e,t);if(r){if(r==="this"){return[de(e,t)]}else{var n=_(e,r);if(n.length===0){x('The selector "'+r+'" on '+t+" returned no matches!");return[ce]}else{return n}}}}function de(e,t){return c(e,function(e){return Z(e,t)!=null})}function ve(e){var t=Y(e,"hx-target");if(t){if(t==="this"){return de(e,"hx-target")}else{return ie(e,t)}}else{var r=ee(e);if(r.boosted){return K().body}else{return e}}}function ge(e){var t=G.config.attributesToSettle;for(var r=0;r0){o=e.substr(0,e.indexOf(":"));t=e.substr(e.indexOf(":")+1,e.length)}else{o=e}var r=K().querySelectorAll(t);if(r){te(r,function(e){var t;var r=i.cloneNode(true);t=K().createDocumentFragment();t.appendChild(r);if(!me(o,e)){t=r}var n={shouldSwap:true,target:e,fragment:t};if(!oe(e,"htmx:oobBeforeSwap",n))return;e=n.target;if(n["shouldSwap"]){Me(o,e,e,t,a)}te(a.elts,function(e){oe(e,"htmx:oobAfterSwap",n)})});i.parentNode.removeChild(i)}else{i.parentNode.removeChild(i);ae(K().body,"htmx:oobErrorNoTarget",{content:i})}return e}function ye(e,t,r){var n=Y(e,"hx-select-oob");if(n){var i=n.split(",");for(let e=0;e0){var t=e.id.replace("'","\\'");var r=e.tagName.replace(":","\\:");var n=a.querySelector(r+"[id='"+t+"']");if(n&&n!==a){var i=e.cloneNode();pe(e,n);o.tasks.push(function(){pe(e,i)})}}})}function Se(e){return function(){n(e,G.config.addedClass);Nt(e);St(e);Ee(e);oe(e,"htmx:load")}}function Ee(e){var t="[autofocus]";var r=h(e,t)?e:e.querySelector(t);if(r!=null){r.focus()}}function a(e,t,r,n){we(e,r,n);while(r.childNodes.length>0){var i=r.firstChild;V(i,G.config.addedClass);e.insertBefore(i,t);if(i.nodeType!==Node.TEXT_NODE&&i.nodeType!==Node.COMMENT_NODE){n.tasks.push(Se(i))}}}function Ce(e,t){var r=0;while(re!=t);while(n&&n!==t){if(n.nodeType===Node.ELEMENT_NODE){r.elts.push(n)}n=n.nextElementSibling}o(t);u(t).removeChild(t)}}function He(e,t,r){return a(e,e.firstChild,t,r)}function Le(e,t,r){return a(u(e),e,t,r)}function Ae(e,t,r){return a(e,null,t,r)}function Ne(e,t,r){return a(u(e),e.nextSibling,t,r)}function Ie(e,t,r){o(e);return u(e).removeChild(e)}function ke(e,t,r){var n=e.firstChild;a(e,n,t,r);if(n){while(n.nextSibling){o(n.nextSibling);e.removeChild(n.nextSibling)}o(n);e.removeChild(n)}}function Pe(e,t,r){var n=r||Y(e,"hx-select");if(n){var i=K().createDocumentFragment();te(t.querySelectorAll(n),function(e){i.appendChild(e)});t=i}return t}function Me(e,t,r,n,i){switch(e){case"none":return;case"outerHTML":Te(r,n,i);return;case"afterbegin":He(r,n,i);return;case"beforebegin":Le(r,n,i);return;case"beforeend":Ae(r,n,i);return;case"afterend":Ne(r,n,i);return;case"delete":Ie(r,n,i);return;default:var a=Rr(t);for(var o=0;o-1){var t=e.replace(/]*>|>)([\s\S]*?)<\/svg>/gim,"");var r=t.match(/]*>|>)([\s\S]*?)<\/title>/im);if(r){return r[2]}}}function Xe(e,t,r,n,i,a){i.title=De(n);var o=l(n);if(o){ye(r,o,i);o=Pe(r,o,a);be(o);return Me(e,r,t,o,i)}}function Fe(e,t,r){var n=e.getResponseHeader(t);if(n.indexOf("{")===0){var i=y(n);for(var a in i){if(i.hasOwnProperty(a)){var o=i[a];if(!I(o)){o={value:o}}oe(r,a,o)}}}else{oe(r,n,[])}}var Ue=/\s/;var g=/[\s,]/;var Be=/[_$a-zA-Z]/;var Ve=/[_$a-zA-Z0-9]/;var je=['"',"'","/"];var p=/[^\s]/;function We(e){var t=[];var r=0;while(r0){var o=t[0];if(o==="]"){n--;if(n===0){if(a===null){i=i+"true"}t.shift();i+=")})";try{var s=cr(e,function(){return Function(i)()},function(){return true});s.source=i;return s}catch(e){ae(K().body,"htmx:syntax:error",{error:e,source:i});return null}}}else if(o==="["){n++}if(_e(o,a,r)){i+="(("+r+"."+o+") ? ("+r+"."+o+") : (window."+o+"))"}else{i=i+o}a=t.shift()}}}function m(e,t){var r="";while(e.length>0&&!e[0].match(t)){r+=e.shift()}return r}var $e="input, textarea, select";function Ge(e){var t=Z(e,"hx-trigger");var r=[];if(t){var n=We(t);do{m(n,p);var i=n.length;var a=m(n,/[,\[\s]/);if(a!==""){if(a==="every"){var o={trigger:"every"};m(n,p);o.pollInterval=v(m(n,/[,\[\s]/));m(n,p);var s=ze(e,n,"event");if(s){o.eventFilter=s}r.push(o)}else if(a.indexOf("sse:")===0){r.push({trigger:"sse",sseEvent:a.substr(4)})}else{var l={trigger:a};var s=ze(e,n,"event");if(s){l.eventFilter=s}while(n.length>0&&n[0]!==","){m(n,p);var u=n.shift();if(u==="changed"){l.changed=true}else if(u==="once"){l.once=true}else if(u==="consume"){l.consume=true}else if(u==="delay"&&n[0]===":"){n.shift();l.delay=v(m(n,g))}else if(u==="from"&&n[0]===":"){n.shift();var f=m(n,g);if(f==="closest"||f==="find"||f==="next"||f==="previous"){n.shift();f+=" "+m(n,g)}l.from=f}else if(u==="target"&&n[0]===":"){n.shift();l.target=m(n,g)}else if(u==="throttle"&&n[0]===":"){n.shift();l.throttle=v(m(n,g))}else if(u==="queue"&&n[0]===":"){n.shift();l.queue=m(n,g)}else if((u==="root"||u==="threshold")&&n[0]===":"){n.shift();l[u]=m(n,g)}else{ae(e,"htmx:syntax:error",{token:n.shift()})}}r.push(l)}}if(n.length===i){ae(e,"htmx:syntax:error",{token:n.shift()})}m(n,p)}while(n[0]===","&&n.shift())}if(r.length>0){return r}else if(h(e,"form")){return[{trigger:"submit"}]}else if(h(e,'input[type="button"]')){return[{trigger:"click"}]}else if(h(e,$e)){return[{trigger:"change"}]}else{return[{trigger:"click"}]}}function Je(e){ee(e).cancelled=true}function Ze(e,t,r){var n=ee(e);n.timeout=setTimeout(function(){if(re(e)&&n.cancelled!==true){if(!tt(r,e,kt("hx:poll:trigger",{triggerSpec:r,target:e}))){t(e)}Ze(e,t,r)}},r.pollInterval)}function Ke(e){return location.hostname===e.hostname&&J(e,"href")&&J(e,"href").indexOf("#")!==0}function Ye(t,r,e){if(t.tagName==="A"&&Ke(t)&&(t.target===""||t.target==="_self")||t.tagName==="FORM"){r.boosted=true;var n,i;if(t.tagName==="A"){n="get";i=t.href}else{var a=J(t,"method");n=a?a.toLowerCase():"get";if(n==="get"){}i=J(t,"action")}e.forEach(function(e){rt(t,function(e,t){se(n,i,e,t)},r,e,true)})}}function Qe(e,t){if(e.type==="submit"||e.type==="click"){if(t.tagName==="FORM"){return true}if(h(t,'input[type="submit"], button')&&d(t,"form")!==null){return true}if(t.tagName==="A"&&t.href&&(t.getAttribute("href")==="#"||t.getAttribute("href").indexOf("#")!==0)){return true}}return false}function et(e,t){return ee(e).boosted&&e.tagName==="A"&&t.type==="click"&&(t.ctrlKey||t.metaKey)}function tt(e,t,r){var n=e.eventFilter;if(n){try{return n.call(t,r)!==true}catch(e){ae(K().body,"htmx:eventFilter:error",{error:e,source:n.source});return true}}return false}function rt(i,a,e,o,s){var l=ee(i);var t;if(o.from){t=_(i,o.from)}else{t=[i]}if(o.changed){l.lastValue=i.value}te(t,function(r){var n=function(e){if(!re(i)){r.removeEventListener(o.trigger,n);return}if(et(i,e)){return}if(s||Qe(e,i)){e.preventDefault()}if(tt(o,i,e)){return}var t=ee(e);t.triggerSpec=o;if(t.handledFor==null){t.handledFor=[]}if(t.handledFor.indexOf(i)<0){t.handledFor.push(i);if(o.consume){e.stopPropagation()}if(o.target&&e.target){if(!h(e.target,o.target)){return}}if(o.once){if(l.triggeredOnce){return}else{l.triggeredOnce=true}}if(o.changed){if(l.lastValue===i.value){return}else{l.lastValue=i.value}}if(l.delayed){clearTimeout(l.delayed)}if(l.throttle){return}if(o.throttle){if(!l.throttle){a(i,e);l.throttle=setTimeout(function(){l.throttle=null},o.throttle)}}else if(o.delay){l.delayed=setTimeout(function(){a(i,e)},o.delay)}else{oe(i,"htmx:trigger");a(i,e)}}};if(e.listenerInfos==null){e.listenerInfos=[]}e.listenerInfos.push({trigger:o.trigger,listener:n,on:r});r.addEventListener(o.trigger,n)})}var nt=false;var it=null;function at(){if(!it){it=function(){nt=true};window.addEventListener("scroll",it);setInterval(function(){if(nt){nt=false;te(K().querySelectorAll("[hx-trigger='revealed'],[data-hx-trigger='revealed']"),function(e){ot(e)})}},200)}}function ot(t){if(!q(t,"data-hx-revealed")&&P(t)){t.setAttribute("data-hx-revealed","true");var e=ee(t);if(e.initHash){oe(t,"revealed")}else{t.addEventListener("htmx:afterProcessNode",function(e){oe(t,"revealed")},{once:true})}}}function st(e,t,r){var n=M(r);for(var i=0;i=0){var t=ct(n);setTimeout(function(){lt(s,r,n+1)},t)}};t.onopen=function(e){n=0};ee(s).webSocket=t;t.addEventListener("message",function(e){if(ut(s)){return}var t=e.data;w(s,function(e){t=e.transformResponse(t,null,s)});var r=S(s);var n=l(t);var i=k(n.children);for(var a=0;a0){oe(u,"htmx:validation:halted",i);return}t.send(JSON.stringify(l));if(Qe(e,u)){e.preventDefault()}})}else{ae(u,"htmx:noWebSocketSourceError")}}function ct(e){var t=G.config.wsReconnectDelay;if(typeof t==="function"){return t(e)}if(t==="full-jitter"){var r=Math.min(e,6);var n=1e3*Math.pow(2,r);return n*Math.random()}x('htmx.config.wsReconnectDelay must either be a function or the string "full-jitter"')}function ht(e,t,r){var n=M(r);for(var i=0;i0){var o=n.shift();var s=o.match(/^\s*([a-zA-Z:\-]+:)(.*)/);if(a===0&&s){o.split(":");i=s[1].slice(0,-1);r[i]=s[2]}else{r[i]+=o}a+=qt(o)}for(var l in r){Tt(e,l,r[l])}}}function Lt(t){Oe(t);for(const e of t.attributes){const{name:r,value:n}=e;if(r.startsWith("hx-on:")||r.startsWith("data-hx-on:")){let e=r.slice(r.indexOf(":")+1);if(e.startsWith(":"))e="htmx"+e;Tt(t,e,n)}}}function At(t){if(t.closest&&t.closest(G.config.disableSelector)){return}var r=ee(t);if(r.initHash!==Re(t)){r.initHash=Re(t);qe(t);Ht(t);oe(t,"htmx:beforeProcessNode");if(t.value){r.lastValue=t.value}var e=Ge(t);var n=yt(t,r,e);if(!n){if(Y(t,"hx-boost")==="true"){Ye(t,r,e)}else if(q(t,"hx-trigger")){e.forEach(function(e){bt(t,e,r,function(){})})}}if(t.tagName==="FORM"){Ot(t)}var i=Z(t,"hx-sse");if(i){ht(t,r,i)}var a=Z(t,"hx-ws");if(a){st(t,r,a)}oe(t,"htmx:afterProcessNode")}}function Nt(e){e=s(e);At(e);te(Rt(e),function(e){At(e)});te(Ct(e),Lt)}function It(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()}function kt(e,t){var r;if(window.CustomEvent&&typeof window.CustomEvent==="function"){r=new CustomEvent(e,{bubbles:true,cancelable:true,detail:t})}else{r=K().createEvent("CustomEvent");r.initCustomEvent(e,true,true,t)}return r}function ae(e,t,r){oe(e,t,ne({error:t},r))}function Pt(e){return e==="htmx:afterProcessNode"}function w(e,t){te(Rr(e),function(e){try{t(e)}catch(e){x(e)}})}function x(e){if(console.error){console.error(e)}else if(console.log){console.log("ERROR: ",e)}}function oe(e,t,r){e=s(e);if(r==null){r={}}r["elt"]=e;var n=kt(t,r);if(G.logger&&!Pt(t)){G.logger(e,t,r)}if(r.error){x(r.error);oe(e,"htmx:error",{errorInfo:r})}var i=e.dispatchEvent(n);var a=It(t);if(i&&a!==t){var o=kt(a,n.detail);i=i&&e.dispatchEvent(o)}w(e,function(e){i=i&&e.onEvent(t,n)!==false});return i}var Mt=location.pathname+location.search;function Dt(){var e=K().querySelector("[hx-history-elt],[data-hx-history-elt]");return e||K().body}function Xt(e,t,r,n){if(!D()){return}e=X(e);var i=y(localStorage.getItem("htmx-history-cache"))||[];for(var a=0;aG.config.historyCacheSize){i.shift()}while(i.length>0){try{localStorage.setItem("htmx-history-cache",JSON.stringify(i));break}catch(e){ae(K().body,"htmx:historyCacheError",{cause:e,cache:i});i.shift()}}}function Ft(e){if(!D()){return null}e=X(e);var t=y(localStorage.getItem("htmx-history-cache"))||[];for(var r=0;r=200&&this.status<400){oe(K().body,"htmx:historyCacheMissLoad",o);var e=l(this.response);e=e.querySelector("[hx-history-elt],[data-hx-history-elt]")||e;var t=Dt();var r=S(t);var n=De(this.response);if(n){var i=b("title");if(i){i.innerHTML=n}else{window.document.title=n}}ke(t,e,r);Wt(r.tasks);Mt=a;oe(K().body,"htmx:historyRestore",{path:a,cacheMiss:true,serverResponse:this.response})}else{ae(K().body,"htmx:historyCacheMissLoadError",o)}};e.send()}function zt(e){Bt();e=e||location.pathname+location.search;var t=Ft(e);if(t){var r=l(t.content);var n=Dt();var i=S(n);ke(n,r,i);Wt(i.tasks);document.title=t.title;setTimeout(function(){window.scrollTo(0,t.scroll)},0);Mt=e;oe(K().body,"htmx:historyRestore",{path:e,item:t})}else{if(G.config.refreshOnHistoryMiss){window.location.reload(true)}else{_t(e)}}}function $t(e){var t=he(e,"hx-indicator");if(t==null){t=[e]}te(t,function(e){var t=ee(e);t.requestCount=(t.requestCount||0)+1;e.classList["add"].call(e.classList,G.config.requestClass)});return t}function Gt(e){te(e,function(e){var t=ee(e);t.requestCount=(t.requestCount||0)-1;if(t.requestCount===0){e.classList["remove"].call(e.classList,G.config.requestClass)}})}function Jt(e,t){for(var r=0;r=0}function or(e,t){var r=t?t:Y(e,"hx-swap");var n={swapStyle:ee(e).boosted?"innerHTML":G.config.defaultSwapStyle,swapDelay:G.config.defaultSwapDelay,settleDelay:G.config.defaultSettleDelay};if(ee(e).boosted&&!ar(e)){n["show"]="top"}if(r){var i=M(r);if(i.length>0){n["swapStyle"]=i[0];for(var a=1;a0?l.join(":"):null;n["scroll"]=u;n["scrollTarget"]=f}if(o.indexOf("show:")===0){var c=o.substr(5);var l=c.split(":");var h=l.pop();var f=l.length>0?l.join(":"):null;n["show"]=h;n["showTarget"]=f}if(o.indexOf("focus-scroll:")===0){var d=o.substr("focus-scroll:".length);n["focusScroll"]=d=="true"}}}}return n}function sr(e){return Y(e,"hx-encoding")==="multipart/form-data"||h(e,"form")&&J(e,"enctype")==="multipart/form-data"}function lr(t,r,n){var i=null;w(r,function(e){if(i==null){i=e.encodeParameters(t,n,r)}});if(i!=null){return i}else{if(sr(r)){return rr(n)}else{return tr(n)}}}function S(e){return{tasks:[],elts:[e]}}function ur(e,t){var r=e[0];var n=e[e.length-1];if(t.scroll){var i=null;if(t.scrollTarget){i=ie(r,t.scrollTarget)}if(t.scroll==="top"&&(r||i)){i=i||r;i.scrollTop=0}if(t.scroll==="bottom"&&(n||i)){i=i||n;i.scrollTop=i.scrollHeight}}if(t.show){var i=null;if(t.showTarget){var a=t.showTarget;if(t.showTarget==="window"){a="body"}i=ie(r,a)}if(t.show==="top"&&(r||i)){i=i||r;i.scrollIntoView({block:"start",behavior:G.config.scrollBehavior})}if(t.show==="bottom"&&(n||i)){i=i||n;i.scrollIntoView({block:"end",behavior:G.config.scrollBehavior})}}}function fr(e,t,r,n){if(n==null){n={}}if(e==null){return n}var i=Z(e,t);if(i){var a=i.trim();var o=r;if(a==="unset"){return null}if(a.indexOf("javascript:")===0){a=a.substr(11);o=true}else if(a.indexOf("js:")===0){a=a.substr(3);o=true}if(a.indexOf("{")!==0){a="{"+a+"}"}var s;if(o){s=cr(e,function(){return Function("return ("+a+")")()},{})}else{s=y(a)}for(var l in s){if(s.hasOwnProperty(l)){if(n[l]==null){n[l]=s[l]}}}}return fr(u(e),t,r,n)}function cr(e,t,r){if(G.config.allowEval){return t()}else{ae(e,"htmx:evalDisallowedError");return r}}function hr(e,t){return fr(e,"hx-vars",true,t)}function dr(e,t){return fr(e,"hx-vals",false,t)}function vr(e){return ne(hr(e),dr(e))}function gr(t,r,n){if(n!==null){try{t.setRequestHeader(r,n)}catch(e){t.setRequestHeader(r,encodeURIComponent(n));t.setRequestHeader(r+"-URI-AutoEncoded","true")}}}function pr(t){if(t.responseURL&&typeof URL!=="undefined"){try{var e=new URL(t.responseURL);return e.pathname+e.search}catch(e){ae(K().body,"htmx:badResponseUrl",{url:t.responseURL})}}}function E(e,t){return e.getAllResponseHeaders().match(t)}function mr(e,t,r){e=e.toLowerCase();if(r){if(r instanceof Element||A(r,"String")){return se(e,t,null,null,{targetOverride:s(r),returnPromise:true})}else{return se(e,t,s(r.source),r.event,{handler:r.handler,headers:r.headers,values:r.values,targetOverride:s(r.target),swapOverride:r.swap,returnPromise:true})}}else{return se(e,t,null,null,{returnPromise:true})}}function xr(e){var t=[];while(e){t.push(e);e=e.parentElement}return t}function se(e,t,n,r,i,M){var a=null;var o=null;i=i!=null?i:{};if(i.returnPromise&&typeof Promise!=="undefined"){var s=new Promise(function(e,t){a=e;o=t})}if(n==null){n=K().body}var D=i.handler||br;if(!re(n)){return}var l=i.targetOverride||ve(n);if(l==null||l==ce){ae(n,"htmx:targetError",{target:Z(n,"hx-target")});return}if(!M){var X=function(){return se(e,t,n,r,i,true)};var F={target:l,elt:n,path:t,verb:e,triggeringEvent:r,etc:i,issueRequest:X};if(oe(n,"htmx:confirm",F)===false){return}}var u=n;var f=ee(n);var c=Y(n,"hx-sync");var h=null;var d=false;if(c){var v=c.split(":");var g=v[0].trim();if(g==="this"){u=de(n,"hx-sync")}else{u=ie(n,g)}c=(v[1]||"drop").trim();f=ee(u);if(c==="drop"&&f.xhr&&f.abortable!==true){return}else if(c==="abort"){if(f.xhr){return}else{d=true}}else if(c==="replace"){oe(u,"htmx:abort")}else if(c.indexOf("queue")===0){var U=c.split(" ");h=(U[1]||"last").trim()}}if(f.xhr){if(f.abortable){oe(u,"htmx:abort")}else{if(h==null){if(r){var p=ee(r);if(p&&p.triggerSpec&&p.triggerSpec.queue){h=p.triggerSpec.queue}}if(h==null){h="last"}}if(f.queuedRequests==null){f.queuedRequests=[]}if(h==="first"&&f.queuedRequests.length===0){f.queuedRequests.push(function(){se(e,t,n,r,i)})}else if(h==="all"){f.queuedRequests.push(function(){se(e,t,n,r,i)})}else if(h==="last"){f.queuedRequests=[];f.queuedRequests.push(function(){se(e,t,n,r,i)})}return}}var m=new XMLHttpRequest;f.xhr=m;f.abortable=d;var x=function(){f.xhr=null;f.abortable=false;if(f.queuedRequests!=null&&f.queuedRequests.length>0){var e=f.queuedRequests.shift();e()}};var y=Y(n,"hx-prompt");if(y){var b=prompt(y);if(b===null||!oe(n,"htmx:prompt",{prompt:b,target:l})){Q(a);x();return s}}var w=Y(n,"hx-confirm");if(w){if(!confirm(w)){Q(a);x();return s}}var S=nr(n,l,b);if(i.headers){S=ne(S,i.headers)}var E=Qt(n,e);var C=E.errors;var R=E.values;if(i.values){R=ne(R,i.values)}var B=vr(n);var O=ne(R,B);var q=ir(O,n);if(e!=="get"&&!sr(n)){S["Content-Type"]="application/x-www-form-urlencoded"}if(G.config.getCacheBusterParam&&e==="get"){q["org.htmx.cache-buster"]=J(l,"id")||"true"}if(t==null||t===""){t=K().location.href}var T=fr(n,"hx-request");var V=ee(n).boosted;var H=G.config.methodsThatUseUrlParams.indexOf(e)>=0;var L={boosted:V,useUrlParams:H,parameters:q,unfilteredParameters:O,headers:S,target:l,verb:e,errors:C,withCredentials:i.credentials||T.credentials||G.config.withCredentials,timeout:i.timeout||T.timeout||G.config.timeout,path:t,triggeringEvent:r};if(!oe(n,"htmx:configRequest",L)){Q(a);x();return s}t=L.path;e=L.verb;S=L.headers;q=L.parameters;C=L.errors;H=L.useUrlParams;if(C&&C.length>0){oe(n,"htmx:validation:halted",L);Q(a);x();return s}var j=t.split("#");var W=j[0];var A=j[1];var N=t;if(H){N=W;var _=Object.keys(q).length!==0;if(_){if(N.indexOf("?")<0){N+="?"}else{N+="&"}N+=tr(q);if(A){N+="#"+A}}}m.open(e.toUpperCase(),N,true);m.overrideMimeType("text/html");m.withCredentials=L.withCredentials;m.timeout=L.timeout;if(T.noHeaders){}else{for(var I in S){if(S.hasOwnProperty(I)){var z=S[I];gr(m,I,z)}}}var k={xhr:m,target:l,requestConfig:L,etc:i,boosted:V,pathInfo:{requestPath:t,finalRequestPath:N,anchor:A}};m.onload=function(){try{var e=xr(n);k.pathInfo.responsePath=pr(m);D(n,k);Gt(P);oe(n,"htmx:afterRequest",k);oe(n,"htmx:afterOnLoad",k);if(!re(n)){var t=null;while(e.length>0&&t==null){var r=e.shift();if(re(r)){t=r}}if(t){oe(t,"htmx:afterRequest",k);oe(t,"htmx:afterOnLoad",k)}}Q(a);x()}catch(e){ae(n,"htmx:onLoadError",ne({error:e},k));throw e}};m.onerror=function(){Gt(P);ae(n,"htmx:afterRequest",k);ae(n,"htmx:sendError",k);Q(o);x()};m.onabort=function(){Gt(P);ae(n,"htmx:afterRequest",k);ae(n,"htmx:sendAbort",k);Q(o);x()};m.ontimeout=function(){Gt(P);ae(n,"htmx:afterRequest",k);ae(n,"htmx:timeout",k);Q(o);x()};if(!oe(n,"htmx:beforeRequest",k)){Q(a);x();return s}var P=$t(n);te(["loadstart","loadend","progress","abort"],function(t){te([m,m.upload],function(e){e.addEventListener(t,function(e){oe(n,"htmx:xhr:"+t,{lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total})})})});oe(n,"htmx:beforeSend",k);var $=H?null:lr(m,n,q);m.send($);return s}function yr(e,t){var r=t.xhr;var n=null;var i=null;if(E(r,/HX-Push:/i)){n=r.getResponseHeader("HX-Push");i="push"}else if(E(r,/HX-Push-Url:/i)){n=r.getResponseHeader("HX-Push-Url");i="push"}else if(E(r,/HX-Replace-Url:/i)){n=r.getResponseHeader("HX-Replace-Url");i="replace"}if(n){if(n==="false"){return{}}else{return{type:i,path:n}}}var a=t.pathInfo.finalRequestPath;var o=t.pathInfo.responsePath;var s=Y(e,"hx-push-url");var l=Y(e,"hx-replace-url");var u=ee(e).boosted;var f=null;var c=null;if(s){f="push";c=s}else if(l){f="replace";c=l}else if(u){f="push";c=o||a}if(c){if(c==="false"){return{}}if(c==="true"){c=o||a}if(t.pathInfo.anchor&&c.indexOf("#")===-1){c=c+"#"+t.pathInfo.anchor}return{type:f,path:c}}else{return{}}}function br(l,u){var f=u.xhr;var c=u.target;var e=u.etc;if(!oe(l,"htmx:beforeOnLoad",u))return;if(E(f,/HX-Trigger:/i)){Fe(f,"HX-Trigger",l)}if(E(f,/HX-Location:/i)){Bt();var t=f.getResponseHeader("HX-Location");var h;if(t.indexOf("{")===0){h=y(t);t=h["path"];delete h["path"]}mr("GET",t,h).then(function(){Vt(t)});return}if(E(f,/HX-Redirect:/i)){location.href=f.getResponseHeader("HX-Redirect");return}if(E(f,/HX-Refresh:/i)){if("true"===f.getResponseHeader("HX-Refresh")){location.reload();return}}if(E(f,/HX-Retarget:/i)){u.target=K().querySelector(f.getResponseHeader("HX-Retarget"))}var d=yr(l,u);var r=f.status>=200&&f.status<400&&f.status!==204;var v=f.response;var n=f.status>=400;var i=ne({shouldSwap:r,serverResponse:v,isError:n},u);if(!oe(c,"htmx:beforeSwap",i))return;c=i.target;v=i.serverResponse;n=i.isError;u.target=c;u.failed=n;u.successful=!n;if(i.shouldSwap){if(f.status===286){Je(l)}w(l,function(e){v=e.transformResponse(v,f,l)});if(d.type){Bt()}var a=e.swapOverride;if(E(f,/HX-Reswap:/i)){a=f.getResponseHeader("HX-Reswap")}var h=or(l,a);c.classList.add(G.config.swappingClass);var g=null;var p=null;var o=function(){try{var e=document.activeElement;var t={};try{t={elt:e,start:e?e.selectionStart:null,end:e?e.selectionEnd:null}}catch(e){}var r;if(E(f,/HX-Reselect:/i)){r=f.getResponseHeader("HX-Reselect")}var n=S(c);Xe(h.swapStyle,c,l,v,n,r);if(t.elt&&!re(t.elt)&&t.elt.id){var i=document.getElementById(t.elt.id);var a={preventScroll:h.focusScroll!==undefined?!h.focusScroll:!G.config.defaultFocusScroll};if(i){if(t.start&&i.setSelectionRange){try{i.setSelectionRange(t.start,t.end)}catch(e){}}i.focus(a)}}c.classList.remove(G.config.swappingClass);te(n.elts,function(e){if(e.classList){e.classList.add(G.config.settlingClass)}oe(e,"htmx:afterSwap",u)});if(E(f,/HX-Trigger-After-Swap:/i)){var o=l;if(!re(l)){o=K().body}Fe(f,"HX-Trigger-After-Swap",o)}var s=function(){te(n.tasks,function(e){e.call()});te(n.elts,function(e){if(e.classList){e.classList.remove(G.config.settlingClass)}oe(e,"htmx:afterSettle",u)});if(d.type){if(d.type==="push"){Vt(d.path);oe(K().body,"htmx:pushedIntoHistory",{path:d.path})}else{jt(d.path);oe(K().body,"htmx:replacedInHistory",{path:d.path})}}if(u.pathInfo.anchor){var e=b("#"+u.pathInfo.anchor);if(e){e.scrollIntoView({block:"start",behavior:"auto"})}}if(n.title){var t=b("title");if(t){t.innerHTML=n.title}else{window.document.title=n.title}}ur(n.elts,h);if(E(f,/HX-Trigger-After-Settle:/i)){var r=l;if(!re(l)){r=K().body}Fe(f,"HX-Trigger-After-Settle",r)}Q(g)};if(h.settleDelay>0){setTimeout(s,h.settleDelay)}else{s()}}catch(e){ae(l,"htmx:swapError",u);Q(p);throw e}};var s=G.config.globalViewTransitions;if(h.hasOwnProperty("transition")){s=h.transition}if(s&&oe(l,"htmx:beforeTransition",u)&&typeof Promise!=="undefined"&&document.startViewTransition){var m=new Promise(function(e,t){g=e;p=t});var x=o;o=function(){document.startViewTransition(function(){x();return m})}}if(h.swapDelay>0){setTimeout(o,h.swapDelay)}else{o()}}if(n){ae(l,"htmx:responseError",ne({error:"Response Status Error Code "+f.status+" from "+u.pathInfo.requestPath},u))}}var wr={};function Sr(){return{init:function(e){return null},onEvent:function(e,t){return true},transformResponse:function(e,t,r){return e},isInlineSwap:function(e){return false},handleSwap:function(e,t,r,n){return false},encodeParameters:function(e,t,r){return null}}}function Er(e,t){if(t.init){t.init(C)}wr[e]=ne(Sr(),t)}function Cr(e){delete wr[e]}function Rr(e,r,n){if(e==undefined){return r}if(r==undefined){r=[]}if(n==undefined){n=[]}var t=Z(e,"hx-ext");if(t){te(t.split(","),function(e){e=e.replace(/ /g,"");if(e.slice(0,7)=="ignore:"){n.push(e.slice(7));return}if(n.indexOf(e)<0){var t=wr[e];if(t&&r.indexOf(t)<0){r.push(t)}}})}return Rr(u(e),r,n)}function Or(e){if(K().readyState!=="loading"){e()}else{K().addEventListener("DOMContentLoaded",e)}}function qr(){if(G.config.includeIndicatorStyles!==false){K().head.insertAdjacentHTML("beforeend","")}}function Tr(){var e=K().querySelector('meta[name="htmx-config"]');if(e){return y(e.content)}else{return null}}function Hr(){var e=Tr();if(e){G.config=ne(G.config,e)}}Or(function(){Hr();qr();var e=K().body;Nt(e);var t=K().querySelectorAll("[hx-trigger='restored'],[data-hx-trigger='restored']");e.addEventListener("htmx:abort",function(e){var t=e.target;var r=ee(t);if(r&&r.xhr){r.xhr.abort()}});var r=window.onpopstate;window.onpopstate=function(e){if(e.state&&e.state.htmx){zt();te(t,function(e){oe(e,"htmx:restored",{document:K(),triggerEvent:oe})})}else{if(r){r(e)}}};setTimeout(function(){oe(e,"htmx:load",{});e=null},0)});return G}()}); -------------------------------------------------------------------------------- /htmx-ai/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /htmx-ai/src/middleware.ts: -------------------------------------------------------------------------------- 1 | /* 2 | There is currently no way to get a `.astro` route to just return the HTML 3 | without the CSS and JS. This is a workaround to remove the CSS and JS from 4 | the HTML response of HTMX fragment routes. 5 | 6 | The premise here is that HTMX fragments won't required additional styles because 7 | the Tailwind for the entire experience is alreay precomputed. And second that it will 8 | not require additional JS because ... HTMX. 9 | */ 10 | const HTMX_FRAGMENT_ROUTES = ["/prompt"]; 11 | 12 | export const onRequest = async (context, next) => { 13 | if ( 14 | !HTMX_FRAGMENT_ROUTES.find((route) => context.request.url.includes(route)) 15 | ) { 16 | return next(); 17 | } 18 | 19 | const response = await next(); 20 | let html = await response.text(); 21 | 22 | // Delete the CSS and JS from the HTML response 23 | html = html.replace(/")}}function Tr(){var e=K().querySelector('meta[name="htmx-config"]');if(e){return y(e.content)}else{return null}}function Hr(){var e=Tr();if(e){G.config=ne(G.config,e)}}Or(function(){Hr();qr();var e=K().body;Nt(e);var t=K().querySelectorAll("[hx-trigger='restored'],[data-hx-trigger='restored']");e.addEventListener("htmx:abort",function(e){var t=e.target;var r=ee(t);if(r&&r.xhr){r.xhr.abort()}});var r=window.onpopstate;window.onpopstate=function(e){if(e.state&&e.state.htmx){zt();te(t,function(e){oe(e,"htmx:restored",{document:K(),triggerEvent:oe})})}else{if(r){r(e)}}};setTimeout(function(){oe(e,"htmx:load",{});e=null},0)});return G}()}); -------------------------------------------------------------------------------- /htmx-express/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Astro HTMX AI 8 | 9 | 10 | 11 | 12 |
13 |
Funny story about a
14 | 21 | 27 |
28 |
29 |
30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /htmx-express/public/sse.js: -------------------------------------------------------------------------------- 1 | /* 2 | Server Sent Events Extension 3 | ============================ 4 | This extension adds support for Server Sent Events to htmx. See /www/extensions/sse.md for usage instructions. 5 | 6 | */ 7 | 8 | (function () { 9 | /** @type {import("../htmx").HtmxInternalApi} */ 10 | var api; 11 | 12 | htmx.defineExtension("sse", { 13 | /** 14 | * Init saves the provided reference to the internal HTMX API. 15 | * 16 | * @param {import("../htmx").HtmxInternalApi} api 17 | * @returns void 18 | */ 19 | init: function (apiRef) { 20 | // store a reference to the internal API. 21 | api = apiRef; 22 | 23 | // set a function in the public API for creating new EventSource objects 24 | if (htmx.createEventSource == undefined) { 25 | htmx.createEventSource = createEventSource; 26 | } 27 | }, 28 | 29 | /** 30 | * onEvent handles all events passed to this extension. 31 | * 32 | * @param {string} name 33 | * @param {Event} evt 34 | * @returns void 35 | */ 36 | onEvent: function (name, evt) { 37 | switch (name) { 38 | // Try to remove remove an EventSource when elements are removed 39 | case "htmx:beforeCleanupElement": 40 | var internalData = api.getInternalData(evt.target); 41 | if (internalData.sseEventSource) { 42 | internalData.sseEventSource.close(); 43 | } 44 | return; 45 | 46 | // Try to create EventSources when elements are processed 47 | case "htmx:afterProcessNode": 48 | createEventSourceOnElement(evt.target); 49 | } 50 | }, 51 | }); 52 | 53 | /////////////////////////////////////////////// 54 | // HELPER FUNCTIONS 55 | /////////////////////////////////////////////// 56 | 57 | /** 58 | * createEventSource is the default method for creating new EventSource objects. 59 | * it is hoisted into htmx.config.createEventSource to be overridden by the user, if needed. 60 | * 61 | * @param {string} url 62 | * @returns EventSource 63 | */ 64 | function createEventSource(url) { 65 | return new EventSource(url, { withCredentials: true }); 66 | } 67 | 68 | function splitOnWhitespace(trigger) { 69 | return trigger.trim().split(/\s+/); 70 | } 71 | 72 | function getLegacySSEURL(elt) { 73 | var legacySSEValue = api.getAttributeValue(elt, "hx-sse"); 74 | if (legacySSEValue) { 75 | var values = splitOnWhitespace(legacySSEValue); 76 | for (var i = 0; i < values.length; i++) { 77 | var value = values[i].split(/:(.+)/); 78 | if (value[0] === "connect") { 79 | return value[1]; 80 | } 81 | } 82 | } 83 | } 84 | 85 | function getLegacySSESwaps(elt) { 86 | var legacySSEValue = api.getAttributeValue(elt, "hx-sse"); 87 | var returnArr = []; 88 | if (legacySSEValue) { 89 | var values = splitOnWhitespace(legacySSEValue); 90 | for (var i = 0; i < values.length; i++) { 91 | var value = values[i].split(/:(.+)/); 92 | if (value[0] === "swap") { 93 | returnArr.push(value[1]); 94 | } 95 | } 96 | } 97 | return returnArr; 98 | } 99 | 100 | /** 101 | * createEventSourceOnElement creates a new EventSource connection on the provided element. 102 | * If a usable EventSource already exists, then it is returned. If not, then a new EventSource 103 | * is created and stored in the element's internalData. 104 | * @param {HTMLElement} elt 105 | * @param {number} retryCount 106 | * @returns {EventSource | null} 107 | */ 108 | function createEventSourceOnElement(elt, retryCount) { 109 | if (elt == null) { 110 | return null; 111 | } 112 | 113 | var internalData = api.getInternalData(elt); 114 | 115 | // get URL from element's attribute 116 | var sseURL = api.getAttributeValue(elt, "sse-connect"); 117 | 118 | if (sseURL == undefined) { 119 | var legacyURL = getLegacySSEURL(elt); 120 | if (legacyURL) { 121 | sseURL = legacyURL; 122 | } else { 123 | return null; 124 | } 125 | } 126 | 127 | // Connect to the EventSource 128 | var source = htmx.createEventSource(sseURL); 129 | internalData.sseEventSource = source; 130 | 131 | // Create event handlers 132 | source.onerror = function (err) { 133 | // Log an error event 134 | api.triggerErrorEvent(elt, "htmx:sseError", { 135 | error: err, 136 | source: source, 137 | }); 138 | 139 | // If parent no longer exists in the document, then clean up this EventSource 140 | if (maybeCloseSSESource(elt)) { 141 | return; 142 | } 143 | 144 | // Otherwise, try to reconnect the EventSource 145 | if (source.readyState === EventSource.CLOSED) { 146 | retryCount = retryCount || 0; 147 | var timeout = Math.random() * (2 ^ retryCount) * 500; 148 | window.setTimeout(function () { 149 | createEventSourceOnElement(elt, Math.min(7, retryCount + 1)); 150 | }, timeout); 151 | } 152 | }; 153 | 154 | source.onopen = function (evt) { 155 | api.triggerEvent(elt, "htmx:sseOpen", { source: source }); 156 | }; 157 | 158 | // Add message handlers for every `sse-swap` attribute 159 | queryAttributeOnThisOrChildren(elt, "sse-swap").forEach(function (child) { 160 | var sseSwapAttr = api.getAttributeValue(child, "sse-swap"); 161 | if (sseSwapAttr) { 162 | var sseEventNames = sseSwapAttr.split(","); 163 | } else { 164 | var sseEventNames = getLegacySSESwaps(child); 165 | } 166 | 167 | for (var i = 0; i < sseEventNames.length; i++) { 168 | var sseEventName = sseEventNames[i].trim(); 169 | var listener = function (event) { 170 | // If the parent is missing then close SSE and remove listener 171 | if (maybeCloseSSESource(elt)) { 172 | source.removeEventListener(sseEventName, listener); 173 | return; 174 | } 175 | 176 | // swap the response into the DOM and trigger a notification 177 | swap(child, event.data); 178 | api.triggerEvent(elt, "htmx:sseMessage", event); 179 | }; 180 | 181 | // Register the new listener 182 | api.getInternalData(elt).sseEventListener = listener; 183 | source.addEventListener(sseEventName, listener); 184 | } 185 | }); 186 | 187 | // Add message handlers for every `hx-trigger="sse:*"` attribute 188 | queryAttributeOnThisOrChildren(elt, "hx-trigger").forEach(function (child) { 189 | var sseEventName = api.getAttributeValue(child, "hx-trigger"); 190 | if (sseEventName == null) { 191 | return; 192 | } 193 | 194 | // Only process hx-triggers for events with the "sse:" prefix 195 | if (sseEventName.slice(0, 4) != "sse:") { 196 | return; 197 | } 198 | 199 | var listener = function (event) { 200 | // If parent is missing, then close SSE and remove listener 201 | if (maybeCloseSSESource(elt)) { 202 | source.removeEventListener(sseEventName, listener); 203 | return; 204 | } 205 | 206 | // Trigger events to be handled by the rest of htmx 207 | htmx.trigger(child, sseEventName, event); 208 | htmx.trigger(child, "htmx:sseMessage", event); 209 | }; 210 | 211 | // Register the new listener 212 | api.getInternalData(elt).sseEventListener = listener; 213 | source.addEventListener(sseEventName.slice(4), listener); 214 | }); 215 | } 216 | 217 | /** 218 | * maybeCloseSSESource confirms that the parent element still exists. 219 | * If not, then any associated SSE source is closed and the function returns true. 220 | * 221 | * @param {HTMLElement} elt 222 | * @returns boolean 223 | */ 224 | function maybeCloseSSESource(elt) { 225 | if (!api.bodyContains(elt)) { 226 | var source = api.getInternalData(elt).sseEventSource; 227 | if (source != undefined) { 228 | source.close(); 229 | // source = null 230 | return true; 231 | } 232 | } 233 | return false; 234 | } 235 | 236 | /** 237 | * queryAttributeOnThisOrChildren returns all nodes that contain the requested attributeName, INCLUDING THE PROVIDED ROOT ELEMENT. 238 | * 239 | * @param {HTMLElement} elt 240 | * @param {string} attributeName 241 | */ 242 | function queryAttributeOnThisOrChildren(elt, attributeName) { 243 | var result = []; 244 | 245 | // If the parent element also contains the requested attribute, then add it to the results too. 246 | if ( 247 | api.hasAttribute(elt, attributeName) || 248 | api.hasAttribute(elt, "hx-sse") 249 | ) { 250 | result.push(elt); 251 | } 252 | 253 | // Search all child nodes that match the requested attribute 254 | elt 255 | .querySelectorAll( 256 | "[" + 257 | attributeName + 258 | "], [data-" + 259 | attributeName + 260 | "], [hx-sse], [data-hx-sse]" 261 | ) 262 | .forEach(function (node) { 263 | result.push(node); 264 | }); 265 | 266 | return result; 267 | } 268 | 269 | /** 270 | * @param {HTMLElement} elt 271 | * @param {string} content 272 | */ 273 | function swap(elt, content) { 274 | api.withExtensions(elt, function (extension) { 275 | content = extension.transformResponse(content, null, elt); 276 | }); 277 | 278 | var swapSpec = api.getSwapSpecification(elt); 279 | var target = api.getTarget(elt); 280 | var settleInfo = api.makeSettleInfo(elt); 281 | 282 | api.selectAndSwap(swapSpec.swapStyle, target, elt, content, settleInfo); 283 | 284 | settleInfo.elts.forEach(function (elt) { 285 | if (elt.classList) { 286 | elt.classList.add(htmx.config.settlingClass); 287 | } 288 | api.triggerEvent(elt, "htmx:beforeSettle"); 289 | }); 290 | 291 | // Handle settle tasks (with delay if requested) 292 | if (swapSpec.settleDelay > 0) { 293 | setTimeout(doSettle(settleInfo), swapSpec.settleDelay); 294 | } else { 295 | doSettle(settleInfo)(); 296 | } 297 | } 298 | 299 | /** 300 | * doSettle mirrors much of the functionality in htmx that 301 | * settles elements after their content has been swapped. 302 | * TODO: this should be published by htmx, and not duplicated here 303 | * @param {import("../htmx").HtmxSettleInfo} settleInfo 304 | * @returns () => void 305 | */ 306 | function doSettle(settleInfo) { 307 | return function () { 308 | settleInfo.tasks.forEach(function (task) { 309 | task.call(); 310 | }); 311 | 312 | settleInfo.elts.forEach(function (elt) { 313 | if (elt.classList) { 314 | elt.classList.remove(htmx.config.settlingClass); 315 | } 316 | api.triggerEvent(elt, "htmx:afterSettle"); 317 | }); 318 | }; 319 | } 320 | })(); 321 | -------------------------------------------------------------------------------- /htmx-express/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./**/*.{html,js}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | -------------------------------------------------------------------------------- /nextjs-ai/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /nextjs-ai/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env*.local 29 | 30 | # vercel 31 | .vercel 32 | 33 | # typescript 34 | *.tsbuildinfo 35 | next-env.d.ts 36 | -------------------------------------------------------------------------------- /nextjs-ai/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | ``` 14 | 15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 16 | 17 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 18 | 19 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 20 | 21 | ## Learn More 22 | 23 | To learn more about Next.js, take a look at the following resources: 24 | 25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 27 | 28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 29 | 30 | ## Deploy on Vercel 31 | 32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 33 | 34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 35 | -------------------------------------------------------------------------------- /nextjs-ai/app/_lib/openai.ts: -------------------------------------------------------------------------------- 1 | import https from "node:https"; 2 | 3 | export const completeWithChatGPT = ( 4 | prompt: string, 5 | tokenCallback: (text: string) => void, 6 | endCallback: () => void, 7 | options: object = {} 8 | ) => { 9 | let text = ""; 10 | const req = https.request( 11 | { 12 | hostname: "api.openai.com", 13 | port: 443, 14 | path: "/v1/completions", 15 | method: "POST", 16 | headers: { 17 | "Content-Type": "application/json", 18 | Authorization: `Bearer ${process.env.OPENAI_API_KEY}`, 19 | }, 20 | }, 21 | function (res) { 22 | res.on("data", (chunk) => { 23 | if (chunk.toString().startsWith("data: ")) { 24 | const data = chunk.toString().replace(/^data: /, ""); 25 | try { 26 | JSON.parse(data).choices.forEach((choice: { text: string }) => { 27 | text += choice.text; 28 | }); 29 | tokenCallback(text); 30 | } catch (e) {} 31 | } 32 | }); 33 | res.on("end", endCallback); 34 | } 35 | ); 36 | 37 | const body = JSON.stringify({ 38 | model: "text-davinci-003", 39 | temperature: 0.9, 40 | max_tokens: 512, 41 | top_p: 1.0, 42 | frequency_penalty: 0.5, 43 | presence_penalty: 0.7, 44 | stream: true, 45 | ...options, 46 | prompt, 47 | }); 48 | 49 | req.on("error", (e) => { 50 | console.error("problem with request:" + e.message); 51 | }); 52 | 53 | req.write(body); 54 | req.end(); 55 | }; 56 | -------------------------------------------------------------------------------- /nextjs-ai/app/_lib/request.ts: -------------------------------------------------------------------------------- 1 | import { completeWithChatGPT } from "./openai"; 2 | 3 | const requests: Record< 4 | string, 5 | { 6 | completion: string; 7 | pending: boolean; 8 | } 9 | > = {}; 10 | 11 | export const getRequest = (requestId: string) => { 12 | return requests[requestId]; 13 | }; 14 | 15 | export const startRequest = async (prompt: string) => { 16 | const requestId = Math.random().toString(36).substring(2, 15); 17 | requests[requestId] = { 18 | completion: "", 19 | pending: true, 20 | }; 21 | 22 | completeWithChatGPT( 23 | `Funny story about a ${prompt}`, 24 | (text) => { 25 | requests[requestId].completion = text; 26 | }, 27 | () => { 28 | requests[requestId].pending = false; 29 | } 30 | ); 31 | 32 | return requestId; 33 | }; 34 | -------------------------------------------------------------------------------- /nextjs-ai/app/api/gpt/[requestId]/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | import { getRequest } from "@/app/_lib/request"; 4 | 5 | export async function GET( 6 | _req: Request, 7 | { params: { requestId } }: { params: { requestId: string } } 8 | ) { 9 | const request = getRequest(requestId); 10 | if (!request) { 11 | return NextResponse.json( 12 | { 13 | error: "Request not found", 14 | }, 15 | { status: 404 } 16 | ); 17 | } 18 | return NextResponse.json(request); 19 | } 20 | -------------------------------------------------------------------------------- /nextjs-ai/app/api/gpt/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | import { startRequest } from "@/app/_lib/request"; 4 | 5 | export async function POST(req: Request) { 6 | const body = await req.json(); 7 | const { prompt } = body; 8 | const requestId = await startRequest(prompt); 9 | return NextResponse.json(requestId); 10 | } 11 | -------------------------------------------------------------------------------- /nextjs-ai/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/htmx-nextjs-ai/ceb532f4dcde6ef5abb1c0406ad84f7d4dd419f6/nextjs-ai/app/favicon.ico -------------------------------------------------------------------------------- /nextjs-ai/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /nextjs-ai/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "./globals.css"; 2 | import type { Metadata } from "next"; 3 | import { Inter } from "next/font/google"; 4 | 5 | const inter = Inter({ subsets: ["latin"] }); 6 | 7 | export const metadata: Metadata = { 8 | title: "Create Next App", 9 | description: "Generated by create next app", 10 | }; 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: { 15 | children: React.ReactNode; 16 | }) { 17 | return ( 18 | 19 | 20 | {children} 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /nextjs-ai/app/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { useState } from "react"; 3 | 4 | export default function Home() { 5 | const [prompt, setPrompt] = useState("dog"); 6 | const [result, setResult] = useState(""); 7 | const [running, setRunning] = useState(false); 8 | 9 | const onSubmit = async () => { 10 | setRunning(true); 11 | 12 | // Start the request 13 | const requestIdReq = await fetch("/api/gpt", { 14 | method: "POST", 15 | cache: "no-cache", 16 | body: JSON.stringify({ prompt }), 17 | }); 18 | const requestId = await requestIdReq.json(); 19 | 20 | // Poll the requestID until it's done 21 | const interval = setInterval(async () => { 22 | const resultReq = await fetch(`/api/gpt/${requestId}`, { 23 | cache: "no-cache", 24 | }); 25 | if (!resultReq.ok) { 26 | console.error(resultReq.statusText); 27 | clearInterval(interval); 28 | setRunning(false); 29 | return; 30 | } 31 | const result = (await resultReq.json()) as { 32 | completion: string; 33 | pending: boolean; 34 | }; 35 | if (result) { 36 | setResult(result.completion); 37 | if (!result.pending) { 38 | setRunning(false); 39 | clearInterval(interval); 40 | } 41 | } 42 | }, 100); 43 | }; 44 | 45 | return ( 46 | <> 47 |
48 |
Funny story about a
49 | setPrompt(e.target.value)} 55 | className="border border-gray-400 p-2 rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" 56 | /> 57 | 65 |
66 |
67 | {result} 68 |
69 | 70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /nextjs-ai/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {} 3 | 4 | module.exports = nextConfig 5 | -------------------------------------------------------------------------------- /nextjs-ai/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs-ai", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@types/node": "20.4.5", 13 | "@types/react": "18.2.17", 14 | "@types/react-dom": "18.2.7", 15 | "autoprefixer": "10.4.14", 16 | "eslint": "8.45.0", 17 | "eslint-config-next": "13.4.12", 18 | "next": "13.4.12", 19 | "postcss": "8.4.27", 20 | "react": "18.2.0", 21 | "react-dom": "18.2.0", 22 | "tailwindcss": "3.3.3", 23 | "typescript": "5.1.6" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /nextjs-ai/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /nextjs-ai/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nextjs-ai/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nextjs-ai/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | './pages/**/*.{js,ts,jsx,tsx,mdx}', 5 | './components/**/*.{js,ts,jsx,tsx,mdx}', 6 | './app/**/*.{js,ts,jsx,tsx,mdx}', 7 | ], 8 | theme: { 9 | extend: { 10 | backgroundImage: { 11 | 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', 12 | 'gradient-conic': 13 | 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', 14 | }, 15 | }, 16 | }, 17 | plugins: [], 18 | } 19 | -------------------------------------------------------------------------------- /nextjs-ai/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "bundler", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true, 17 | "plugins": [ 18 | { 19 | "name": "next" 20 | } 21 | ], 22 | "paths": { 23 | "@/*": ["./*"] 24 | } 25 | }, 26 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 27 | "exclude": ["node_modules"] 28 | } 29 | --------------------------------------------------------------------------------