jakubrada commited on
Commit
30f1ff2
·
verified ·
1 Parent(s): 054645c

Upload 57 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +9 -0
  2. Dockerfile +12 -0
  3. README.md +1 -10
  4. assets/assets/bar_sprite.png +0 -0
  5. assets/assets/barman.jpeg +0 -0
  6. assets/assets/barman_old.png +0 -0
  7. assets/assets/dj.jpeg +0 -0
  8. assets/assets/dj_old.png +3 -0
  9. assets/assets/dj_sprite.png +0 -0
  10. assets/assets/door_sprite.png +0 -0
  11. assets/assets/floor-tile.png +0 -0
  12. assets/assets/game-over-8bit-music-danijel-zambo-1-00-16.mp3 +0 -0
  13. assets/assets/game-over.png +3 -0
  14. assets/assets/image.webp +0 -0
  15. assets/assets/intro-image.jpg +0 -0
  16. assets/assets/jessica.jpeg +0 -0
  17. assets/assets/jessica_old.png +0 -0
  18. assets/assets/jessica_sprite.png +0 -0
  19. assets/assets/moonlit-whispers-theo-gerard-main-version-35960-02-34.mp3 +3 -0
  20. assets/assets/player.png +0 -0
  21. assets/assets/shyguy-headshot_old.png +0 -0
  22. assets/assets/shyguy.jpeg +0 -0
  23. assets/assets/shyguy.png +0 -0
  24. assets/assets/shyguy_headshot.jpeg +0 -0
  25. assets/assets/shyguy_left.png +0 -0
  26. assets/assets/shyguy_right.png +0 -0
  27. assets/assets/shyguy_sprite.png +0 -0
  28. assets/assets/sister.jpeg +0 -0
  29. assets/assets/sister_old.png +0 -0
  30. assets/assets/sister_sprite.png +0 -0
  31. assets/assets/still-waters-night-drift-main-version-34884-02-09.mp3 +3 -0
  32. assets/assets/sunshine-danijel-zambo-main-version-01-54-1403.mp3 +3 -0
  33. assets/assets/tiny-steps-danijel-zambo-main-version-1433-01-48.mp3 +3 -0
  34. assets/assets/title-screen.png +3 -0
  35. assets/assets/tragic-piano-game-over-music-gfx-sounds-1-00-08.mp3 +0 -0
  36. assets/assets/victory.png +3 -0
  37. assets/assets/wall_sprite.png +0 -0
  38. assets/assets/wingman.jpeg +0 -0
  39. assets/assets/wingman_left.png +0 -0
  40. assets/assets/wingman_old.png +3 -0
  41. assets/assets/wingman_right.png +0 -0
  42. assets/assets/wingman_sprite.png +0 -0
  43. index.html +98 -0
  44. package-lock.json +1688 -0
  45. package.json +17 -0
  46. src/constants.js +7 -0
  47. src/conversation_llm.js +76 -0
  48. src/eleven_labs.js +91 -0
  49. src/game.js +64 -0
  50. src/game_engine.js +1167 -0
.gitattributes CHANGED
@@ -33,3 +33,12 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ assets/assets/dj_old.png filter=lfs diff=lfs merge=lfs -text
37
+ assets/assets/game-over.png filter=lfs diff=lfs merge=lfs -text
38
+ assets/assets/moonlit-whispers-theo-gerard-main-version-35960-02-34.mp3 filter=lfs diff=lfs merge=lfs -text
39
+ assets/assets/still-waters-night-drift-main-version-34884-02-09.mp3 filter=lfs diff=lfs merge=lfs -text
40
+ assets/assets/sunshine-danijel-zambo-main-version-01-54-1403.mp3 filter=lfs diff=lfs merge=lfs -text
41
+ assets/assets/tiny-steps-danijel-zambo-main-version-1433-01-48.mp3 filter=lfs diff=lfs merge=lfs -text
42
+ assets/assets/title-screen.png filter=lfs diff=lfs merge=lfs -text
43
+ assets/assets/victory.png filter=lfs diff=lfs merge=lfs -text
44
+ assets/assets/wingman_old.png filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM node:18
2
+
3
+ WORKDIR /app
4
+
5
+ COPY package.json package.json
6
+ COPY package-lock.json package-lock.json
7
+
8
+ RUN npm install
9
+
10
+ COPY . .
11
+
12
+ CMD ["npm", "run", "dev"]
README.md CHANGED
@@ -1,10 +1 @@
1
- ---
2
- title: ShyguysWingmanJS
3
- emoji: 🌍
4
- colorFrom: indigo
5
- colorTo: gray
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ # ShyguysWingmanJS
 
 
 
 
 
 
 
 
 
assets/assets/bar_sprite.png ADDED
assets/assets/barman.jpeg ADDED
assets/assets/barman_old.png ADDED
assets/assets/dj.jpeg ADDED
assets/assets/dj_old.png ADDED

Git LFS Details

  • SHA256: 0efd462632a8002e38c7dc4ed3cddbce21bdb6684575700b22699c50112037d8
  • Pointer size: 132 Bytes
  • Size of remote file: 2.76 MB
assets/assets/dj_sprite.png ADDED
assets/assets/door_sprite.png ADDED
assets/assets/floor-tile.png ADDED
assets/assets/game-over-8bit-music-danijel-zambo-1-00-16.mp3 ADDED
Binary file (683 kB). View file
 
assets/assets/game-over.png ADDED

Git LFS Details

  • SHA256: b432c55365bb67d10381d935929e4fcb6d3e6e1d0b707601b30b1952b1a063fd
  • Pointer size: 132 Bytes
  • Size of remote file: 3.34 MB
assets/assets/image.webp ADDED
assets/assets/intro-image.jpg ADDED
assets/assets/jessica.jpeg ADDED
assets/assets/jessica_old.png ADDED
assets/assets/jessica_sprite.png ADDED
assets/assets/moonlit-whispers-theo-gerard-main-version-35960-02-34.mp3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:042c696678781cbd276979868386b81d49e5623dc1bb0471d4a8a9db672d8c92
3
+ size 6224789
assets/assets/player.png ADDED
assets/assets/shyguy-headshot_old.png ADDED
assets/assets/shyguy.jpeg ADDED
assets/assets/shyguy.png ADDED
assets/assets/shyguy_headshot.jpeg ADDED
assets/assets/shyguy_left.png ADDED
assets/assets/shyguy_right.png ADDED
assets/assets/shyguy_sprite.png ADDED
assets/assets/sister.jpeg ADDED
assets/assets/sister_old.png ADDED
assets/assets/sister_sprite.png ADDED
assets/assets/still-waters-night-drift-main-version-34884-02-09.mp3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b9c75e89fc006b5f65a1e6bbd753d718276c047e382110e3defdb2da948cd810
3
+ size 9634996
assets/assets/sunshine-danijel-zambo-main-version-01-54-1403.mp3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:20861a5ba975478289de19e3c04d27d6186c4f62bfe8a996f20225c1951dbd92
3
+ size 4584812
assets/assets/tiny-steps-danijel-zambo-main-version-1433-01-48.mp3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:dd1bc1cfcdebe9999f561dd4cdd5a9bd32760764a7634ab11f13a9c53b2febd9
3
+ size 4334026
assets/assets/title-screen.png ADDED

Git LFS Details

  • SHA256: bf87396234fba30571a24ac0abb67b0cac1e4e993f8db5732cee2bf008f6204a
  • Pointer size: 132 Bytes
  • Size of remote file: 4.01 MB
assets/assets/tragic-piano-game-over-music-gfx-sounds-1-00-08.mp3 ADDED
Binary file (339 kB). View file
 
assets/assets/victory.png ADDED

Git LFS Details

  • SHA256: bfee3e2b474d892abe75a0bc6aa10e4efa8ae159114fd59b46255dc38fdc107a
  • Pointer size: 132 Bytes
  • Size of remote file: 3.35 MB
assets/assets/wall_sprite.png ADDED
assets/assets/wingman.jpeg ADDED
assets/assets/wingman_left.png ADDED
assets/assets/wingman_old.png ADDED

Git LFS Details

  • SHA256: 39d93bdc4e63c00c879ab5627832352a1eaf12f7f66157b80b57703612e3f80d
  • Pointer size: 132 Bytes
  • Size of remote file: 1.28 MB
assets/assets/wingman_right.png ADDED
assets/assets/wingman_sprite.png ADDED
index.html ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Shyguy's Wingman</title>
7
+ <link rel="stylesheet" href="/styles/style.css" />
8
+ <!-- Font Awesome for microphone icon -->
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" />
10
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
11
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
12
+ <link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet" />
13
+ </head>
14
+ <body>
15
+ <div class="intro-view active" id="introView">
16
+ <div class="intro-content">
17
+ <img src="/assets/assets/intro-image.jpg" alt="Game Intro" class="intro-image" />
18
+ <button id="startGameBtn" class="start-game-button">Start Game</button>
19
+ </div>
20
+ </div>
21
+
22
+ <div class="status-bar">
23
+ <div class="status-text" id="statusText">
24
+ You are playing as the Wingman. You need to help your friend get the girl of his dreams. Don't let him leave!
25
+ </div>
26
+ </div>
27
+
28
+ <div class="game-view active" id="gameView">
29
+ <div class="container">
30
+ <div class="game-section">
31
+ <canvas id="gameCanvas"></canvas>
32
+ </div>
33
+ <div class="chat-section">
34
+ <div class="chat-messages" id="chatMessages">
35
+ <!-- Messages will be added here -->
36
+ </div>
37
+ <div class="input-area">
38
+ <textarea id="messageInput" placeholder="Type your message here..." rows="3"></textarea>
39
+ <div class="button-group">
40
+ <button id="sendButton" class="send-button">Send</button>
41
+ <button id="micButton" class="mic-button">
42
+ <i class="fas fa-microphone"></i>
43
+ </button>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </div>
49
+
50
+ <div class="dialogue-view" id="dialogueView">
51
+ <div class="character-section">
52
+ <div class="character left-character">
53
+ <img id="leftCharacterImg" class="character-img" />
54
+ </div>
55
+ <div class="dialogue-box">
56
+ <div class="dialogue-messages" id="dialogueMessages">
57
+ <!-- Dialogue messages will be added here -->
58
+ </div>
59
+ <div class="loading-indicator"><span>Loading</span><span class="loading-dots"></span></div>
60
+ </div>
61
+ <div class="character right-character">
62
+ <img id="rightCharacterImg" class="character-img" />
63
+ </div>
64
+ </div>
65
+ <div class="dialogue-controls">
66
+ <button id="dialogueContinueButton" class="continue-button">Continue</button>
67
+ <button id="dialogueNextButton" class="next-button">Next</button>
68
+ </div>
69
+ </div>
70
+
71
+ <div class="game-over-view" id="gameOverView">
72
+ <div class="game-over-content">
73
+ <img id="gameOverImage" class="game-over-image" src="" alt="Game Over" />
74
+ <div class="game-over-text" id="gameOverText">
75
+ <!-- Text will be set via JS -->
76
+ </div>
77
+ <div class="game-over-controls">
78
+ <button id="playAgainBtn" class="play-again-button">Play Again</button>
79
+ </div>
80
+ </div>
81
+ </div>
82
+
83
+ <div class="debug-controls" id="debugControls">
84
+ <div class="game-controls">
85
+ <button id="targetDoorBtn" class="debug-button">Target Door</button>
86
+ <button id="targetGirlBtn" class="debug-button">Target Girl</button>
87
+ <button id="targetBarBtn" class="debug-button">Target Bar</button>
88
+ <button id="targetDjBtn" class="debug-button">Target Dj</button>
89
+ <button id="targetSisterBtn" class="debug-button">Target Sister</button>
90
+ <button id="stopNavBtn" class="debug-button">Stop Navigation</button>
91
+ <button id="togglePushBtn" class="debug-button">Enable Push</button>
92
+ <button id="speedBoostBtn" class="debug-button">Speed Boost</button>
93
+ <button id="toggleVoiceBtn" class="debug-button">Enable Voice</button>
94
+ </div>
95
+ </div>
96
+ <script src="./src/index.js" type="module"></script>
97
+ </body>
98
+ </html>
package-lock.json ADDED
@@ -0,0 +1,1688 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "shyguys-wingman-js",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "shyguys-wingman-js",
9
+ "version": "1.0.0",
10
+ "dependencies": {
11
+ "elevenlabs": "^1.50.4"
12
+ },
13
+ "devDependencies": {
14
+ "vite": "^6.0.11"
15
+ }
16
+ },
17
+ "node_modules/@esbuild/aix-ppc64": {
18
+ "version": "0.24.2",
19
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz",
20
+ "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==",
21
+ "cpu": [
22
+ "ppc64"
23
+ ],
24
+ "dev": true,
25
+ "license": "MIT",
26
+ "optional": true,
27
+ "os": [
28
+ "aix"
29
+ ],
30
+ "engines": {
31
+ "node": ">=18"
32
+ }
33
+ },
34
+ "node_modules/@esbuild/android-arm": {
35
+ "version": "0.24.2",
36
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz",
37
+ "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==",
38
+ "cpu": [
39
+ "arm"
40
+ ],
41
+ "dev": true,
42
+ "license": "MIT",
43
+ "optional": true,
44
+ "os": [
45
+ "android"
46
+ ],
47
+ "engines": {
48
+ "node": ">=18"
49
+ }
50
+ },
51
+ "node_modules/@esbuild/android-arm64": {
52
+ "version": "0.24.2",
53
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz",
54
+ "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==",
55
+ "cpu": [
56
+ "arm64"
57
+ ],
58
+ "dev": true,
59
+ "license": "MIT",
60
+ "optional": true,
61
+ "os": [
62
+ "android"
63
+ ],
64
+ "engines": {
65
+ "node": ">=18"
66
+ }
67
+ },
68
+ "node_modules/@esbuild/android-x64": {
69
+ "version": "0.24.2",
70
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz",
71
+ "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==",
72
+ "cpu": [
73
+ "x64"
74
+ ],
75
+ "dev": true,
76
+ "license": "MIT",
77
+ "optional": true,
78
+ "os": [
79
+ "android"
80
+ ],
81
+ "engines": {
82
+ "node": ">=18"
83
+ }
84
+ },
85
+ "node_modules/@esbuild/darwin-arm64": {
86
+ "version": "0.24.2",
87
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz",
88
+ "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==",
89
+ "cpu": [
90
+ "arm64"
91
+ ],
92
+ "dev": true,
93
+ "license": "MIT",
94
+ "optional": true,
95
+ "os": [
96
+ "darwin"
97
+ ],
98
+ "engines": {
99
+ "node": ">=18"
100
+ }
101
+ },
102
+ "node_modules/@esbuild/darwin-x64": {
103
+ "version": "0.24.2",
104
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz",
105
+ "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==",
106
+ "cpu": [
107
+ "x64"
108
+ ],
109
+ "dev": true,
110
+ "license": "MIT",
111
+ "optional": true,
112
+ "os": [
113
+ "darwin"
114
+ ],
115
+ "engines": {
116
+ "node": ">=18"
117
+ }
118
+ },
119
+ "node_modules/@esbuild/freebsd-arm64": {
120
+ "version": "0.24.2",
121
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz",
122
+ "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==",
123
+ "cpu": [
124
+ "arm64"
125
+ ],
126
+ "dev": true,
127
+ "license": "MIT",
128
+ "optional": true,
129
+ "os": [
130
+ "freebsd"
131
+ ],
132
+ "engines": {
133
+ "node": ">=18"
134
+ }
135
+ },
136
+ "node_modules/@esbuild/freebsd-x64": {
137
+ "version": "0.24.2",
138
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz",
139
+ "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==",
140
+ "cpu": [
141
+ "x64"
142
+ ],
143
+ "dev": true,
144
+ "license": "MIT",
145
+ "optional": true,
146
+ "os": [
147
+ "freebsd"
148
+ ],
149
+ "engines": {
150
+ "node": ">=18"
151
+ }
152
+ },
153
+ "node_modules/@esbuild/linux-arm": {
154
+ "version": "0.24.2",
155
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz",
156
+ "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==",
157
+ "cpu": [
158
+ "arm"
159
+ ],
160
+ "dev": true,
161
+ "license": "MIT",
162
+ "optional": true,
163
+ "os": [
164
+ "linux"
165
+ ],
166
+ "engines": {
167
+ "node": ">=18"
168
+ }
169
+ },
170
+ "node_modules/@esbuild/linux-arm64": {
171
+ "version": "0.24.2",
172
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz",
173
+ "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==",
174
+ "cpu": [
175
+ "arm64"
176
+ ],
177
+ "dev": true,
178
+ "license": "MIT",
179
+ "optional": true,
180
+ "os": [
181
+ "linux"
182
+ ],
183
+ "engines": {
184
+ "node": ">=18"
185
+ }
186
+ },
187
+ "node_modules/@esbuild/linux-ia32": {
188
+ "version": "0.24.2",
189
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz",
190
+ "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==",
191
+ "cpu": [
192
+ "ia32"
193
+ ],
194
+ "dev": true,
195
+ "license": "MIT",
196
+ "optional": true,
197
+ "os": [
198
+ "linux"
199
+ ],
200
+ "engines": {
201
+ "node": ">=18"
202
+ }
203
+ },
204
+ "node_modules/@esbuild/linux-loong64": {
205
+ "version": "0.24.2",
206
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz",
207
+ "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==",
208
+ "cpu": [
209
+ "loong64"
210
+ ],
211
+ "dev": true,
212
+ "license": "MIT",
213
+ "optional": true,
214
+ "os": [
215
+ "linux"
216
+ ],
217
+ "engines": {
218
+ "node": ">=18"
219
+ }
220
+ },
221
+ "node_modules/@esbuild/linux-mips64el": {
222
+ "version": "0.24.2",
223
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz",
224
+ "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==",
225
+ "cpu": [
226
+ "mips64el"
227
+ ],
228
+ "dev": true,
229
+ "license": "MIT",
230
+ "optional": true,
231
+ "os": [
232
+ "linux"
233
+ ],
234
+ "engines": {
235
+ "node": ">=18"
236
+ }
237
+ },
238
+ "node_modules/@esbuild/linux-ppc64": {
239
+ "version": "0.24.2",
240
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz",
241
+ "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==",
242
+ "cpu": [
243
+ "ppc64"
244
+ ],
245
+ "dev": true,
246
+ "license": "MIT",
247
+ "optional": true,
248
+ "os": [
249
+ "linux"
250
+ ],
251
+ "engines": {
252
+ "node": ">=18"
253
+ }
254
+ },
255
+ "node_modules/@esbuild/linux-riscv64": {
256
+ "version": "0.24.2",
257
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz",
258
+ "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==",
259
+ "cpu": [
260
+ "riscv64"
261
+ ],
262
+ "dev": true,
263
+ "license": "MIT",
264
+ "optional": true,
265
+ "os": [
266
+ "linux"
267
+ ],
268
+ "engines": {
269
+ "node": ">=18"
270
+ }
271
+ },
272
+ "node_modules/@esbuild/linux-s390x": {
273
+ "version": "0.24.2",
274
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz",
275
+ "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==",
276
+ "cpu": [
277
+ "s390x"
278
+ ],
279
+ "dev": true,
280
+ "license": "MIT",
281
+ "optional": true,
282
+ "os": [
283
+ "linux"
284
+ ],
285
+ "engines": {
286
+ "node": ">=18"
287
+ }
288
+ },
289
+ "node_modules/@esbuild/linux-x64": {
290
+ "version": "0.24.2",
291
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz",
292
+ "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==",
293
+ "cpu": [
294
+ "x64"
295
+ ],
296
+ "dev": true,
297
+ "license": "MIT",
298
+ "optional": true,
299
+ "os": [
300
+ "linux"
301
+ ],
302
+ "engines": {
303
+ "node": ">=18"
304
+ }
305
+ },
306
+ "node_modules/@esbuild/netbsd-arm64": {
307
+ "version": "0.24.2",
308
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz",
309
+ "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==",
310
+ "cpu": [
311
+ "arm64"
312
+ ],
313
+ "dev": true,
314
+ "license": "MIT",
315
+ "optional": true,
316
+ "os": [
317
+ "netbsd"
318
+ ],
319
+ "engines": {
320
+ "node": ">=18"
321
+ }
322
+ },
323
+ "node_modules/@esbuild/netbsd-x64": {
324
+ "version": "0.24.2",
325
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz",
326
+ "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==",
327
+ "cpu": [
328
+ "x64"
329
+ ],
330
+ "dev": true,
331
+ "license": "MIT",
332
+ "optional": true,
333
+ "os": [
334
+ "netbsd"
335
+ ],
336
+ "engines": {
337
+ "node": ">=18"
338
+ }
339
+ },
340
+ "node_modules/@esbuild/openbsd-arm64": {
341
+ "version": "0.24.2",
342
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz",
343
+ "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==",
344
+ "cpu": [
345
+ "arm64"
346
+ ],
347
+ "dev": true,
348
+ "license": "MIT",
349
+ "optional": true,
350
+ "os": [
351
+ "openbsd"
352
+ ],
353
+ "engines": {
354
+ "node": ">=18"
355
+ }
356
+ },
357
+ "node_modules/@esbuild/openbsd-x64": {
358
+ "version": "0.24.2",
359
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz",
360
+ "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==",
361
+ "cpu": [
362
+ "x64"
363
+ ],
364
+ "dev": true,
365
+ "license": "MIT",
366
+ "optional": true,
367
+ "os": [
368
+ "openbsd"
369
+ ],
370
+ "engines": {
371
+ "node": ">=18"
372
+ }
373
+ },
374
+ "node_modules/@esbuild/sunos-x64": {
375
+ "version": "0.24.2",
376
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz",
377
+ "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==",
378
+ "cpu": [
379
+ "x64"
380
+ ],
381
+ "dev": true,
382
+ "license": "MIT",
383
+ "optional": true,
384
+ "os": [
385
+ "sunos"
386
+ ],
387
+ "engines": {
388
+ "node": ">=18"
389
+ }
390
+ },
391
+ "node_modules/@esbuild/win32-arm64": {
392
+ "version": "0.24.2",
393
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz",
394
+ "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==",
395
+ "cpu": [
396
+ "arm64"
397
+ ],
398
+ "dev": true,
399
+ "license": "MIT",
400
+ "optional": true,
401
+ "os": [
402
+ "win32"
403
+ ],
404
+ "engines": {
405
+ "node": ">=18"
406
+ }
407
+ },
408
+ "node_modules/@esbuild/win32-ia32": {
409
+ "version": "0.24.2",
410
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz",
411
+ "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==",
412
+ "cpu": [
413
+ "ia32"
414
+ ],
415
+ "dev": true,
416
+ "license": "MIT",
417
+ "optional": true,
418
+ "os": [
419
+ "win32"
420
+ ],
421
+ "engines": {
422
+ "node": ">=18"
423
+ }
424
+ },
425
+ "node_modules/@esbuild/win32-x64": {
426
+ "version": "0.24.2",
427
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz",
428
+ "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==",
429
+ "cpu": [
430
+ "x64"
431
+ ],
432
+ "dev": true,
433
+ "license": "MIT",
434
+ "optional": true,
435
+ "os": [
436
+ "win32"
437
+ ],
438
+ "engines": {
439
+ "node": ">=18"
440
+ }
441
+ },
442
+ "node_modules/@rollup/rollup-android-arm-eabi": {
443
+ "version": "4.32.0",
444
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.0.tgz",
445
+ "integrity": "sha512-G2fUQQANtBPsNwiVFg4zKiPQyjVKZCUdQUol53R8E71J7AsheRMV/Yv/nB8giOcOVqP7//eB5xPqieBYZe9bGg==",
446
+ "cpu": [
447
+ "arm"
448
+ ],
449
+ "dev": true,
450
+ "license": "MIT",
451
+ "optional": true,
452
+ "os": [
453
+ "android"
454
+ ]
455
+ },
456
+ "node_modules/@rollup/rollup-android-arm64": {
457
+ "version": "4.32.0",
458
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.0.tgz",
459
+ "integrity": "sha512-qhFwQ+ljoymC+j5lXRv8DlaJYY/+8vyvYmVx074zrLsu5ZGWYsJNLjPPVJJjhZQpyAKUGPydOq9hRLLNvh1s3A==",
460
+ "cpu": [
461
+ "arm64"
462
+ ],
463
+ "dev": true,
464
+ "license": "MIT",
465
+ "optional": true,
466
+ "os": [
467
+ "android"
468
+ ]
469
+ },
470
+ "node_modules/@rollup/rollup-darwin-arm64": {
471
+ "version": "4.32.0",
472
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.0.tgz",
473
+ "integrity": "sha512-44n/X3lAlWsEY6vF8CzgCx+LQaoqWGN7TzUfbJDiTIOjJm4+L2Yq+r5a8ytQRGyPqgJDs3Rgyo8eVL7n9iW6AQ==",
474
+ "cpu": [
475
+ "arm64"
476
+ ],
477
+ "dev": true,
478
+ "license": "MIT",
479
+ "optional": true,
480
+ "os": [
481
+ "darwin"
482
+ ]
483
+ },
484
+ "node_modules/@rollup/rollup-darwin-x64": {
485
+ "version": "4.32.0",
486
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.0.tgz",
487
+ "integrity": "sha512-F9ct0+ZX5Np6+ZDztxiGCIvlCaW87HBdHcozUfsHnj1WCUTBUubAoanhHUfnUHZABlElyRikI0mgcw/qdEm2VQ==",
488
+ "cpu": [
489
+ "x64"
490
+ ],
491
+ "dev": true,
492
+ "license": "MIT",
493
+ "optional": true,
494
+ "os": [
495
+ "darwin"
496
+ ]
497
+ },
498
+ "node_modules/@rollup/rollup-freebsd-arm64": {
499
+ "version": "4.32.0",
500
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.0.tgz",
501
+ "integrity": "sha512-JpsGxLBB2EFXBsTLHfkZDsXSpSmKD3VxXCgBQtlPcuAqB8TlqtLcbeMhxXQkCDv1avgwNjF8uEIbq5p+Cee0PA==",
502
+ "cpu": [
503
+ "arm64"
504
+ ],
505
+ "dev": true,
506
+ "license": "MIT",
507
+ "optional": true,
508
+ "os": [
509
+ "freebsd"
510
+ ]
511
+ },
512
+ "node_modules/@rollup/rollup-freebsd-x64": {
513
+ "version": "4.32.0",
514
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.0.tgz",
515
+ "integrity": "sha512-wegiyBT6rawdpvnD9lmbOpx5Sph+yVZKHbhnSP9MqUEDX08G4UzMU+D87jrazGE7lRSyTRs6NEYHtzfkJ3FjjQ==",
516
+ "cpu": [
517
+ "x64"
518
+ ],
519
+ "dev": true,
520
+ "license": "MIT",
521
+ "optional": true,
522
+ "os": [
523
+ "freebsd"
524
+ ]
525
+ },
526
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
527
+ "version": "4.32.0",
528
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.0.tgz",
529
+ "integrity": "sha512-3pA7xecItbgOs1A5H58dDvOUEboG5UfpTq3WzAdF54acBbUM+olDJAPkgj1GRJ4ZqE12DZ9/hNS2QZk166v92A==",
530
+ "cpu": [
531
+ "arm"
532
+ ],
533
+ "dev": true,
534
+ "license": "MIT",
535
+ "optional": true,
536
+ "os": [
537
+ "linux"
538
+ ]
539
+ },
540
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
541
+ "version": "4.32.0",
542
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.0.tgz",
543
+ "integrity": "sha512-Y7XUZEVISGyge51QbYyYAEHwpGgmRrAxQXO3siyYo2kmaj72USSG8LtlQQgAtlGfxYiOwu+2BdbPjzEpcOpRmQ==",
544
+ "cpu": [
545
+ "arm"
546
+ ],
547
+ "dev": true,
548
+ "license": "MIT",
549
+ "optional": true,
550
+ "os": [
551
+ "linux"
552
+ ]
553
+ },
554
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
555
+ "version": "4.32.0",
556
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.0.tgz",
557
+ "integrity": "sha512-r7/OTF5MqeBrZo5omPXcTnjvv1GsrdH8a8RerARvDFiDwFpDVDnJyByYM/nX+mvks8XXsgPUxkwe/ltaX2VH7w==",
558
+ "cpu": [
559
+ "arm64"
560
+ ],
561
+ "dev": true,
562
+ "license": "MIT",
563
+ "optional": true,
564
+ "os": [
565
+ "linux"
566
+ ]
567
+ },
568
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
569
+ "version": "4.32.0",
570
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.0.tgz",
571
+ "integrity": "sha512-HJbifC9vex9NqnlodV2BHVFNuzKL5OnsV2dvTw6e1dpZKkNjPG6WUq+nhEYV6Hv2Bv++BXkwcyoGlXnPrjAKXw==",
572
+ "cpu": [
573
+ "arm64"
574
+ ],
575
+ "dev": true,
576
+ "license": "MIT",
577
+ "optional": true,
578
+ "os": [
579
+ "linux"
580
+ ]
581
+ },
582
+ "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
583
+ "version": "4.32.0",
584
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.0.tgz",
585
+ "integrity": "sha512-VAEzZTD63YglFlWwRj3taofmkV1V3xhebDXffon7msNz4b14xKsz7utO6F8F4cqt8K/ktTl9rm88yryvDpsfOw==",
586
+ "cpu": [
587
+ "loong64"
588
+ ],
589
+ "dev": true,
590
+ "license": "MIT",
591
+ "optional": true,
592
+ "os": [
593
+ "linux"
594
+ ]
595
+ },
596
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
597
+ "version": "4.32.0",
598
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.0.tgz",
599
+ "integrity": "sha512-Sts5DST1jXAc9YH/iik1C9QRsLcCoOScf3dfbY5i4kH9RJpKxiTBXqm7qU5O6zTXBTEZry69bGszr3SMgYmMcQ==",
600
+ "cpu": [
601
+ "ppc64"
602
+ ],
603
+ "dev": true,
604
+ "license": "MIT",
605
+ "optional": true,
606
+ "os": [
607
+ "linux"
608
+ ]
609
+ },
610
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
611
+ "version": "4.32.0",
612
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.0.tgz",
613
+ "integrity": "sha512-qhlXeV9AqxIyY9/R1h1hBD6eMvQCO34ZmdYvry/K+/MBs6d1nRFLm6BOiITLVI+nFAAB9kUB6sdJRKyVHXnqZw==",
614
+ "cpu": [
615
+ "riscv64"
616
+ ],
617
+ "dev": true,
618
+ "license": "MIT",
619
+ "optional": true,
620
+ "os": [
621
+ "linux"
622
+ ]
623
+ },
624
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
625
+ "version": "4.32.0",
626
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.0.tgz",
627
+ "integrity": "sha512-8ZGN7ExnV0qjXa155Rsfi6H8M4iBBwNLBM9lcVS+4NcSzOFaNqmt7djlox8pN1lWrRPMRRQ8NeDlozIGx3Omsw==",
628
+ "cpu": [
629
+ "s390x"
630
+ ],
631
+ "dev": true,
632
+ "license": "MIT",
633
+ "optional": true,
634
+ "os": [
635
+ "linux"
636
+ ]
637
+ },
638
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
639
+ "version": "4.32.0",
640
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.32.0.tgz",
641
+ "integrity": "sha512-VDzNHtLLI5s7xd/VubyS10mq6TxvZBp+4NRWoW+Hi3tgV05RtVm4qK99+dClwTN1McA6PHwob6DEJ6PlXbY83A==",
642
+ "cpu": [
643
+ "x64"
644
+ ],
645
+ "dev": true,
646
+ "license": "MIT",
647
+ "optional": true,
648
+ "os": [
649
+ "linux"
650
+ ]
651
+ },
652
+ "node_modules/@rollup/rollup-linux-x64-musl": {
653
+ "version": "4.32.0",
654
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.32.0.tgz",
655
+ "integrity": "sha512-qcb9qYDlkxz9DxJo7SDhWxTWV1gFuwznjbTiov289pASxlfGbaOD54mgbs9+z94VwrXtKTu+2RqwlSTbiOqxGg==",
656
+ "cpu": [
657
+ "x64"
658
+ ],
659
+ "dev": true,
660
+ "license": "MIT",
661
+ "optional": true,
662
+ "os": [
663
+ "linux"
664
+ ]
665
+ },
666
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
667
+ "version": "4.32.0",
668
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.0.tgz",
669
+ "integrity": "sha512-pFDdotFDMXW2AXVbfdUEfidPAk/OtwE/Hd4eYMTNVVaCQ6Yl8et0meDaKNL63L44Haxv4UExpv9ydSf3aSayDg==",
670
+ "cpu": [
671
+ "arm64"
672
+ ],
673
+ "dev": true,
674
+ "license": "MIT",
675
+ "optional": true,
676
+ "os": [
677
+ "win32"
678
+ ]
679
+ },
680
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
681
+ "version": "4.32.0",
682
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.0.tgz",
683
+ "integrity": "sha512-/TG7WfrCAjeRNDvI4+0AAMoHxea/USWhAzf9PVDFHbcqrQ7hMMKp4jZIy4VEjk72AAfN5k4TiSMRXRKf/0akSw==",
684
+ "cpu": [
685
+ "ia32"
686
+ ],
687
+ "dev": true,
688
+ "license": "MIT",
689
+ "optional": true,
690
+ "os": [
691
+ "win32"
692
+ ]
693
+ },
694
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
695
+ "version": "4.32.0",
696
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.32.0.tgz",
697
+ "integrity": "sha512-5hqO5S3PTEO2E5VjCePxv40gIgyS2KvO7E7/vvC/NbIW4SIRamkMr1hqj+5Y67fbBWv/bQLB6KelBQmXlyCjWA==",
698
+ "cpu": [
699
+ "x64"
700
+ ],
701
+ "dev": true,
702
+ "license": "MIT",
703
+ "optional": true,
704
+ "os": [
705
+ "win32"
706
+ ]
707
+ },
708
+ "node_modules/@types/estree": {
709
+ "version": "1.0.6",
710
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
711
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
712
+ "dev": true,
713
+ "license": "MIT"
714
+ },
715
+ "node_modules/abort-controller": {
716
+ "version": "3.0.0",
717
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
718
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
719
+ "license": "MIT",
720
+ "dependencies": {
721
+ "event-target-shim": "^5.0.0"
722
+ },
723
+ "engines": {
724
+ "node": ">=6.5"
725
+ }
726
+ },
727
+ "node_modules/asynckit": {
728
+ "version": "0.4.0",
729
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
730
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
731
+ "license": "MIT"
732
+ },
733
+ "node_modules/base64-js": {
734
+ "version": "1.5.1",
735
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
736
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
737
+ "funding": [
738
+ {
739
+ "type": "github",
740
+ "url": "https://github.com/sponsors/feross"
741
+ },
742
+ {
743
+ "type": "patreon",
744
+ "url": "https://www.patreon.com/feross"
745
+ },
746
+ {
747
+ "type": "consulting",
748
+ "url": "https://feross.org/support"
749
+ }
750
+ ],
751
+ "license": "MIT"
752
+ },
753
+ "node_modules/buffer": {
754
+ "version": "6.0.3",
755
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
756
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
757
+ "funding": [
758
+ {
759
+ "type": "github",
760
+ "url": "https://github.com/sponsors/feross"
761
+ },
762
+ {
763
+ "type": "patreon",
764
+ "url": "https://www.patreon.com/feross"
765
+ },
766
+ {
767
+ "type": "consulting",
768
+ "url": "https://feross.org/support"
769
+ }
770
+ ],
771
+ "license": "MIT",
772
+ "dependencies": {
773
+ "base64-js": "^1.3.1",
774
+ "ieee754": "^1.2.1"
775
+ }
776
+ },
777
+ "node_modules/call-bind-apply-helpers": {
778
+ "version": "1.0.1",
779
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
780
+ "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
781
+ "license": "MIT",
782
+ "dependencies": {
783
+ "es-errors": "^1.3.0",
784
+ "function-bind": "^1.1.2"
785
+ },
786
+ "engines": {
787
+ "node": ">= 0.4"
788
+ }
789
+ },
790
+ "node_modules/call-bound": {
791
+ "version": "1.0.3",
792
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
793
+ "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
794
+ "license": "MIT",
795
+ "dependencies": {
796
+ "call-bind-apply-helpers": "^1.0.1",
797
+ "get-intrinsic": "^1.2.6"
798
+ },
799
+ "engines": {
800
+ "node": ">= 0.4"
801
+ },
802
+ "funding": {
803
+ "url": "https://github.com/sponsors/ljharb"
804
+ }
805
+ },
806
+ "node_modules/combined-stream": {
807
+ "version": "1.0.8",
808
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
809
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
810
+ "license": "MIT",
811
+ "dependencies": {
812
+ "delayed-stream": "~1.0.0"
813
+ },
814
+ "engines": {
815
+ "node": ">= 0.8"
816
+ }
817
+ },
818
+ "node_modules/command-exists": {
819
+ "version": "1.2.9",
820
+ "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz",
821
+ "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==",
822
+ "license": "MIT"
823
+ },
824
+ "node_modules/cross-spawn": {
825
+ "version": "7.0.6",
826
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
827
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
828
+ "license": "MIT",
829
+ "dependencies": {
830
+ "path-key": "^3.1.0",
831
+ "shebang-command": "^2.0.0",
832
+ "which": "^2.0.1"
833
+ },
834
+ "engines": {
835
+ "node": ">= 8"
836
+ }
837
+ },
838
+ "node_modules/delayed-stream": {
839
+ "version": "1.0.0",
840
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
841
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
842
+ "license": "MIT",
843
+ "engines": {
844
+ "node": ">=0.4.0"
845
+ }
846
+ },
847
+ "node_modules/dunder-proto": {
848
+ "version": "1.0.1",
849
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
850
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
851
+ "license": "MIT",
852
+ "dependencies": {
853
+ "call-bind-apply-helpers": "^1.0.1",
854
+ "es-errors": "^1.3.0",
855
+ "gopd": "^1.2.0"
856
+ },
857
+ "engines": {
858
+ "node": ">= 0.4"
859
+ }
860
+ },
861
+ "node_modules/elevenlabs": {
862
+ "version": "1.50.4",
863
+ "resolved": "https://registry.npmjs.org/elevenlabs/-/elevenlabs-1.50.4.tgz",
864
+ "integrity": "sha512-c/g9tORpzi/5wd//2avzRvnZ0ujEKSZi3Jn6FO93gcWXHvftTuundGBwgNcIAyzZo9oRW5VlNxMYFHEZOdc1Fg==",
865
+ "license": "MIT",
866
+ "dependencies": {
867
+ "command-exists": "^1.2.9",
868
+ "execa": "^5.1.1",
869
+ "form-data": "^4.0.0",
870
+ "form-data-encoder": "^4.0.2",
871
+ "formdata-node": "^6.0.3",
872
+ "node-fetch": "2.7.0",
873
+ "qs": "6.11.2",
874
+ "readable-stream": "^4.5.2",
875
+ "url-join": "4.0.1"
876
+ }
877
+ },
878
+ "node_modules/es-define-property": {
879
+ "version": "1.0.1",
880
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
881
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
882
+ "license": "MIT",
883
+ "engines": {
884
+ "node": ">= 0.4"
885
+ }
886
+ },
887
+ "node_modules/es-errors": {
888
+ "version": "1.3.0",
889
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
890
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
891
+ "license": "MIT",
892
+ "engines": {
893
+ "node": ">= 0.4"
894
+ }
895
+ },
896
+ "node_modules/es-object-atoms": {
897
+ "version": "1.1.1",
898
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
899
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
900
+ "license": "MIT",
901
+ "dependencies": {
902
+ "es-errors": "^1.3.0"
903
+ },
904
+ "engines": {
905
+ "node": ">= 0.4"
906
+ }
907
+ },
908
+ "node_modules/esbuild": {
909
+ "version": "0.24.2",
910
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
911
+ "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==",
912
+ "dev": true,
913
+ "hasInstallScript": true,
914
+ "license": "MIT",
915
+ "bin": {
916
+ "esbuild": "bin/esbuild"
917
+ },
918
+ "engines": {
919
+ "node": ">=18"
920
+ },
921
+ "optionalDependencies": {
922
+ "@esbuild/aix-ppc64": "0.24.2",
923
+ "@esbuild/android-arm": "0.24.2",
924
+ "@esbuild/android-arm64": "0.24.2",
925
+ "@esbuild/android-x64": "0.24.2",
926
+ "@esbuild/darwin-arm64": "0.24.2",
927
+ "@esbuild/darwin-x64": "0.24.2",
928
+ "@esbuild/freebsd-arm64": "0.24.2",
929
+ "@esbuild/freebsd-x64": "0.24.2",
930
+ "@esbuild/linux-arm": "0.24.2",
931
+ "@esbuild/linux-arm64": "0.24.2",
932
+ "@esbuild/linux-ia32": "0.24.2",
933
+ "@esbuild/linux-loong64": "0.24.2",
934
+ "@esbuild/linux-mips64el": "0.24.2",
935
+ "@esbuild/linux-ppc64": "0.24.2",
936
+ "@esbuild/linux-riscv64": "0.24.2",
937
+ "@esbuild/linux-s390x": "0.24.2",
938
+ "@esbuild/linux-x64": "0.24.2",
939
+ "@esbuild/netbsd-arm64": "0.24.2",
940
+ "@esbuild/netbsd-x64": "0.24.2",
941
+ "@esbuild/openbsd-arm64": "0.24.2",
942
+ "@esbuild/openbsd-x64": "0.24.2",
943
+ "@esbuild/sunos-x64": "0.24.2",
944
+ "@esbuild/win32-arm64": "0.24.2",
945
+ "@esbuild/win32-ia32": "0.24.2",
946
+ "@esbuild/win32-x64": "0.24.2"
947
+ }
948
+ },
949
+ "node_modules/event-target-shim": {
950
+ "version": "5.0.1",
951
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
952
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
953
+ "license": "MIT",
954
+ "engines": {
955
+ "node": ">=6"
956
+ }
957
+ },
958
+ "node_modules/events": {
959
+ "version": "3.3.0",
960
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
961
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
962
+ "license": "MIT",
963
+ "engines": {
964
+ "node": ">=0.8.x"
965
+ }
966
+ },
967
+ "node_modules/execa": {
968
+ "version": "5.1.1",
969
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
970
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
971
+ "license": "MIT",
972
+ "dependencies": {
973
+ "cross-spawn": "^7.0.3",
974
+ "get-stream": "^6.0.0",
975
+ "human-signals": "^2.1.0",
976
+ "is-stream": "^2.0.0",
977
+ "merge-stream": "^2.0.0",
978
+ "npm-run-path": "^4.0.1",
979
+ "onetime": "^5.1.2",
980
+ "signal-exit": "^3.0.3",
981
+ "strip-final-newline": "^2.0.0"
982
+ },
983
+ "engines": {
984
+ "node": ">=10"
985
+ },
986
+ "funding": {
987
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
988
+ }
989
+ },
990
+ "node_modules/form-data": {
991
+ "version": "4.0.1",
992
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
993
+ "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
994
+ "license": "MIT",
995
+ "dependencies": {
996
+ "asynckit": "^0.4.0",
997
+ "combined-stream": "^1.0.8",
998
+ "mime-types": "^2.1.12"
999
+ },
1000
+ "engines": {
1001
+ "node": ">= 6"
1002
+ }
1003
+ },
1004
+ "node_modules/form-data-encoder": {
1005
+ "version": "4.0.2",
1006
+ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-4.0.2.tgz",
1007
+ "integrity": "sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw==",
1008
+ "license": "MIT",
1009
+ "engines": {
1010
+ "node": ">= 18"
1011
+ }
1012
+ },
1013
+ "node_modules/formdata-node": {
1014
+ "version": "6.0.3",
1015
+ "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-6.0.3.tgz",
1016
+ "integrity": "sha512-8e1++BCiTzUno9v5IZ2J6bv4RU+3UKDmqWUQD0MIMVCd9AdhWkO1gw57oo1mNEX1dMq2EGI+FbWz4B92pscSQg==",
1017
+ "license": "MIT",
1018
+ "engines": {
1019
+ "node": ">= 18"
1020
+ }
1021
+ },
1022
+ "node_modules/fsevents": {
1023
+ "version": "2.3.3",
1024
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
1025
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
1026
+ "dev": true,
1027
+ "hasInstallScript": true,
1028
+ "license": "MIT",
1029
+ "optional": true,
1030
+ "os": [
1031
+ "darwin"
1032
+ ],
1033
+ "engines": {
1034
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1035
+ }
1036
+ },
1037
+ "node_modules/function-bind": {
1038
+ "version": "1.1.2",
1039
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
1040
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
1041
+ "license": "MIT",
1042
+ "funding": {
1043
+ "url": "https://github.com/sponsors/ljharb"
1044
+ }
1045
+ },
1046
+ "node_modules/get-intrinsic": {
1047
+ "version": "1.2.7",
1048
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz",
1049
+ "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==",
1050
+ "license": "MIT",
1051
+ "dependencies": {
1052
+ "call-bind-apply-helpers": "^1.0.1",
1053
+ "es-define-property": "^1.0.1",
1054
+ "es-errors": "^1.3.0",
1055
+ "es-object-atoms": "^1.0.0",
1056
+ "function-bind": "^1.1.2",
1057
+ "get-proto": "^1.0.0",
1058
+ "gopd": "^1.2.0",
1059
+ "has-symbols": "^1.1.0",
1060
+ "hasown": "^2.0.2",
1061
+ "math-intrinsics": "^1.1.0"
1062
+ },
1063
+ "engines": {
1064
+ "node": ">= 0.4"
1065
+ },
1066
+ "funding": {
1067
+ "url": "https://github.com/sponsors/ljharb"
1068
+ }
1069
+ },
1070
+ "node_modules/get-proto": {
1071
+ "version": "1.0.1",
1072
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
1073
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
1074
+ "license": "MIT",
1075
+ "dependencies": {
1076
+ "dunder-proto": "^1.0.1",
1077
+ "es-object-atoms": "^1.0.0"
1078
+ },
1079
+ "engines": {
1080
+ "node": ">= 0.4"
1081
+ }
1082
+ },
1083
+ "node_modules/get-stream": {
1084
+ "version": "6.0.1",
1085
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
1086
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
1087
+ "license": "MIT",
1088
+ "engines": {
1089
+ "node": ">=10"
1090
+ },
1091
+ "funding": {
1092
+ "url": "https://github.com/sponsors/sindresorhus"
1093
+ }
1094
+ },
1095
+ "node_modules/gopd": {
1096
+ "version": "1.2.0",
1097
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
1098
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
1099
+ "license": "MIT",
1100
+ "engines": {
1101
+ "node": ">= 0.4"
1102
+ },
1103
+ "funding": {
1104
+ "url": "https://github.com/sponsors/ljharb"
1105
+ }
1106
+ },
1107
+ "node_modules/has-symbols": {
1108
+ "version": "1.1.0",
1109
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
1110
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
1111
+ "license": "MIT",
1112
+ "engines": {
1113
+ "node": ">= 0.4"
1114
+ },
1115
+ "funding": {
1116
+ "url": "https://github.com/sponsors/ljharb"
1117
+ }
1118
+ },
1119
+ "node_modules/hasown": {
1120
+ "version": "2.0.2",
1121
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
1122
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
1123
+ "license": "MIT",
1124
+ "dependencies": {
1125
+ "function-bind": "^1.1.2"
1126
+ },
1127
+ "engines": {
1128
+ "node": ">= 0.4"
1129
+ }
1130
+ },
1131
+ "node_modules/human-signals": {
1132
+ "version": "2.1.0",
1133
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
1134
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
1135
+ "license": "Apache-2.0",
1136
+ "engines": {
1137
+ "node": ">=10.17.0"
1138
+ }
1139
+ },
1140
+ "node_modules/ieee754": {
1141
+ "version": "1.2.1",
1142
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
1143
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
1144
+ "funding": [
1145
+ {
1146
+ "type": "github",
1147
+ "url": "https://github.com/sponsors/feross"
1148
+ },
1149
+ {
1150
+ "type": "patreon",
1151
+ "url": "https://www.patreon.com/feross"
1152
+ },
1153
+ {
1154
+ "type": "consulting",
1155
+ "url": "https://feross.org/support"
1156
+ }
1157
+ ],
1158
+ "license": "BSD-3-Clause"
1159
+ },
1160
+ "node_modules/is-stream": {
1161
+ "version": "2.0.1",
1162
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
1163
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
1164
+ "license": "MIT",
1165
+ "engines": {
1166
+ "node": ">=8"
1167
+ },
1168
+ "funding": {
1169
+ "url": "https://github.com/sponsors/sindresorhus"
1170
+ }
1171
+ },
1172
+ "node_modules/isexe": {
1173
+ "version": "2.0.0",
1174
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
1175
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
1176
+ "license": "ISC"
1177
+ },
1178
+ "node_modules/math-intrinsics": {
1179
+ "version": "1.1.0",
1180
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
1181
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
1182
+ "license": "MIT",
1183
+ "engines": {
1184
+ "node": ">= 0.4"
1185
+ }
1186
+ },
1187
+ "node_modules/merge-stream": {
1188
+ "version": "2.0.0",
1189
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
1190
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
1191
+ "license": "MIT"
1192
+ },
1193
+ "node_modules/mime-db": {
1194
+ "version": "1.52.0",
1195
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
1196
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
1197
+ "license": "MIT",
1198
+ "engines": {
1199
+ "node": ">= 0.6"
1200
+ }
1201
+ },
1202
+ "node_modules/mime-types": {
1203
+ "version": "2.1.35",
1204
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
1205
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
1206
+ "license": "MIT",
1207
+ "dependencies": {
1208
+ "mime-db": "1.52.0"
1209
+ },
1210
+ "engines": {
1211
+ "node": ">= 0.6"
1212
+ }
1213
+ },
1214
+ "node_modules/mimic-fn": {
1215
+ "version": "2.1.0",
1216
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
1217
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
1218
+ "license": "MIT",
1219
+ "engines": {
1220
+ "node": ">=6"
1221
+ }
1222
+ },
1223
+ "node_modules/nanoid": {
1224
+ "version": "3.3.8",
1225
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
1226
+ "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
1227
+ "dev": true,
1228
+ "funding": [
1229
+ {
1230
+ "type": "github",
1231
+ "url": "https://github.com/sponsors/ai"
1232
+ }
1233
+ ],
1234
+ "license": "MIT",
1235
+ "bin": {
1236
+ "nanoid": "bin/nanoid.cjs"
1237
+ },
1238
+ "engines": {
1239
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
1240
+ }
1241
+ },
1242
+ "node_modules/node-fetch": {
1243
+ "version": "2.7.0",
1244
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
1245
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
1246
+ "license": "MIT",
1247
+ "dependencies": {
1248
+ "whatwg-url": "^5.0.0"
1249
+ },
1250
+ "engines": {
1251
+ "node": "4.x || >=6.0.0"
1252
+ },
1253
+ "peerDependencies": {
1254
+ "encoding": "^0.1.0"
1255
+ },
1256
+ "peerDependenciesMeta": {
1257
+ "encoding": {
1258
+ "optional": true
1259
+ }
1260
+ }
1261
+ },
1262
+ "node_modules/npm-run-path": {
1263
+ "version": "4.0.1",
1264
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
1265
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
1266
+ "license": "MIT",
1267
+ "dependencies": {
1268
+ "path-key": "^3.0.0"
1269
+ },
1270
+ "engines": {
1271
+ "node": ">=8"
1272
+ }
1273
+ },
1274
+ "node_modules/object-inspect": {
1275
+ "version": "1.13.3",
1276
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
1277
+ "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
1278
+ "license": "MIT",
1279
+ "engines": {
1280
+ "node": ">= 0.4"
1281
+ },
1282
+ "funding": {
1283
+ "url": "https://github.com/sponsors/ljharb"
1284
+ }
1285
+ },
1286
+ "node_modules/onetime": {
1287
+ "version": "5.1.2",
1288
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
1289
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
1290
+ "license": "MIT",
1291
+ "dependencies": {
1292
+ "mimic-fn": "^2.1.0"
1293
+ },
1294
+ "engines": {
1295
+ "node": ">=6"
1296
+ },
1297
+ "funding": {
1298
+ "url": "https://github.com/sponsors/sindresorhus"
1299
+ }
1300
+ },
1301
+ "node_modules/path-key": {
1302
+ "version": "3.1.1",
1303
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
1304
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
1305
+ "license": "MIT",
1306
+ "engines": {
1307
+ "node": ">=8"
1308
+ }
1309
+ },
1310
+ "node_modules/picocolors": {
1311
+ "version": "1.1.1",
1312
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
1313
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
1314
+ "dev": true,
1315
+ "license": "ISC"
1316
+ },
1317
+ "node_modules/postcss": {
1318
+ "version": "8.5.1",
1319
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz",
1320
+ "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==",
1321
+ "dev": true,
1322
+ "funding": [
1323
+ {
1324
+ "type": "opencollective",
1325
+ "url": "https://opencollective.com/postcss/"
1326
+ },
1327
+ {
1328
+ "type": "tidelift",
1329
+ "url": "https://tidelift.com/funding/github/npm/postcss"
1330
+ },
1331
+ {
1332
+ "type": "github",
1333
+ "url": "https://github.com/sponsors/ai"
1334
+ }
1335
+ ],
1336
+ "license": "MIT",
1337
+ "dependencies": {
1338
+ "nanoid": "^3.3.8",
1339
+ "picocolors": "^1.1.1",
1340
+ "source-map-js": "^1.2.1"
1341
+ },
1342
+ "engines": {
1343
+ "node": "^10 || ^12 || >=14"
1344
+ }
1345
+ },
1346
+ "node_modules/process": {
1347
+ "version": "0.11.10",
1348
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
1349
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
1350
+ "license": "MIT",
1351
+ "engines": {
1352
+ "node": ">= 0.6.0"
1353
+ }
1354
+ },
1355
+ "node_modules/qs": {
1356
+ "version": "6.11.2",
1357
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz",
1358
+ "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==",
1359
+ "license": "BSD-3-Clause",
1360
+ "dependencies": {
1361
+ "side-channel": "^1.0.4"
1362
+ },
1363
+ "engines": {
1364
+ "node": ">=0.6"
1365
+ },
1366
+ "funding": {
1367
+ "url": "https://github.com/sponsors/ljharb"
1368
+ }
1369
+ },
1370
+ "node_modules/readable-stream": {
1371
+ "version": "4.7.0",
1372
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz",
1373
+ "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==",
1374
+ "license": "MIT",
1375
+ "dependencies": {
1376
+ "abort-controller": "^3.0.0",
1377
+ "buffer": "^6.0.3",
1378
+ "events": "^3.3.0",
1379
+ "process": "^0.11.10",
1380
+ "string_decoder": "^1.3.0"
1381
+ },
1382
+ "engines": {
1383
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1384
+ }
1385
+ },
1386
+ "node_modules/rollup": {
1387
+ "version": "4.32.0",
1388
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.32.0.tgz",
1389
+ "integrity": "sha512-JmrhfQR31Q4AuNBjjAX4s+a/Pu/Q8Q9iwjWBsjRH1q52SPFE2NqRMK6fUZKKnvKO6id+h7JIRf0oYsph53eATg==",
1390
+ "dev": true,
1391
+ "license": "MIT",
1392
+ "dependencies": {
1393
+ "@types/estree": "1.0.6"
1394
+ },
1395
+ "bin": {
1396
+ "rollup": "dist/bin/rollup"
1397
+ },
1398
+ "engines": {
1399
+ "node": ">=18.0.0",
1400
+ "npm": ">=8.0.0"
1401
+ },
1402
+ "optionalDependencies": {
1403
+ "@rollup/rollup-android-arm-eabi": "4.32.0",
1404
+ "@rollup/rollup-android-arm64": "4.32.0",
1405
+ "@rollup/rollup-darwin-arm64": "4.32.0",
1406
+ "@rollup/rollup-darwin-x64": "4.32.0",
1407
+ "@rollup/rollup-freebsd-arm64": "4.32.0",
1408
+ "@rollup/rollup-freebsd-x64": "4.32.0",
1409
+ "@rollup/rollup-linux-arm-gnueabihf": "4.32.0",
1410
+ "@rollup/rollup-linux-arm-musleabihf": "4.32.0",
1411
+ "@rollup/rollup-linux-arm64-gnu": "4.32.0",
1412
+ "@rollup/rollup-linux-arm64-musl": "4.32.0",
1413
+ "@rollup/rollup-linux-loongarch64-gnu": "4.32.0",
1414
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.32.0",
1415
+ "@rollup/rollup-linux-riscv64-gnu": "4.32.0",
1416
+ "@rollup/rollup-linux-s390x-gnu": "4.32.0",
1417
+ "@rollup/rollup-linux-x64-gnu": "4.32.0",
1418
+ "@rollup/rollup-linux-x64-musl": "4.32.0",
1419
+ "@rollup/rollup-win32-arm64-msvc": "4.32.0",
1420
+ "@rollup/rollup-win32-ia32-msvc": "4.32.0",
1421
+ "@rollup/rollup-win32-x64-msvc": "4.32.0",
1422
+ "fsevents": "~2.3.2"
1423
+ }
1424
+ },
1425
+ "node_modules/safe-buffer": {
1426
+ "version": "5.2.1",
1427
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1428
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
1429
+ "funding": [
1430
+ {
1431
+ "type": "github",
1432
+ "url": "https://github.com/sponsors/feross"
1433
+ },
1434
+ {
1435
+ "type": "patreon",
1436
+ "url": "https://www.patreon.com/feross"
1437
+ },
1438
+ {
1439
+ "type": "consulting",
1440
+ "url": "https://feross.org/support"
1441
+ }
1442
+ ],
1443
+ "license": "MIT"
1444
+ },
1445
+ "node_modules/shebang-command": {
1446
+ "version": "2.0.0",
1447
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
1448
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
1449
+ "license": "MIT",
1450
+ "dependencies": {
1451
+ "shebang-regex": "^3.0.0"
1452
+ },
1453
+ "engines": {
1454
+ "node": ">=8"
1455
+ }
1456
+ },
1457
+ "node_modules/shebang-regex": {
1458
+ "version": "3.0.0",
1459
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
1460
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
1461
+ "license": "MIT",
1462
+ "engines": {
1463
+ "node": ">=8"
1464
+ }
1465
+ },
1466
+ "node_modules/side-channel": {
1467
+ "version": "1.1.0",
1468
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
1469
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
1470
+ "license": "MIT",
1471
+ "dependencies": {
1472
+ "es-errors": "^1.3.0",
1473
+ "object-inspect": "^1.13.3",
1474
+ "side-channel-list": "^1.0.0",
1475
+ "side-channel-map": "^1.0.1",
1476
+ "side-channel-weakmap": "^1.0.2"
1477
+ },
1478
+ "engines": {
1479
+ "node": ">= 0.4"
1480
+ },
1481
+ "funding": {
1482
+ "url": "https://github.com/sponsors/ljharb"
1483
+ }
1484
+ },
1485
+ "node_modules/side-channel-list": {
1486
+ "version": "1.0.0",
1487
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
1488
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
1489
+ "license": "MIT",
1490
+ "dependencies": {
1491
+ "es-errors": "^1.3.0",
1492
+ "object-inspect": "^1.13.3"
1493
+ },
1494
+ "engines": {
1495
+ "node": ">= 0.4"
1496
+ },
1497
+ "funding": {
1498
+ "url": "https://github.com/sponsors/ljharb"
1499
+ }
1500
+ },
1501
+ "node_modules/side-channel-map": {
1502
+ "version": "1.0.1",
1503
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
1504
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
1505
+ "license": "MIT",
1506
+ "dependencies": {
1507
+ "call-bound": "^1.0.2",
1508
+ "es-errors": "^1.3.0",
1509
+ "get-intrinsic": "^1.2.5",
1510
+ "object-inspect": "^1.13.3"
1511
+ },
1512
+ "engines": {
1513
+ "node": ">= 0.4"
1514
+ },
1515
+ "funding": {
1516
+ "url": "https://github.com/sponsors/ljharb"
1517
+ }
1518
+ },
1519
+ "node_modules/side-channel-weakmap": {
1520
+ "version": "1.0.2",
1521
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
1522
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
1523
+ "license": "MIT",
1524
+ "dependencies": {
1525
+ "call-bound": "^1.0.2",
1526
+ "es-errors": "^1.3.0",
1527
+ "get-intrinsic": "^1.2.5",
1528
+ "object-inspect": "^1.13.3",
1529
+ "side-channel-map": "^1.0.1"
1530
+ },
1531
+ "engines": {
1532
+ "node": ">= 0.4"
1533
+ },
1534
+ "funding": {
1535
+ "url": "https://github.com/sponsors/ljharb"
1536
+ }
1537
+ },
1538
+ "node_modules/signal-exit": {
1539
+ "version": "3.0.7",
1540
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
1541
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
1542
+ "license": "ISC"
1543
+ },
1544
+ "node_modules/source-map-js": {
1545
+ "version": "1.2.1",
1546
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
1547
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
1548
+ "dev": true,
1549
+ "license": "BSD-3-Clause",
1550
+ "engines": {
1551
+ "node": ">=0.10.0"
1552
+ }
1553
+ },
1554
+ "node_modules/string_decoder": {
1555
+ "version": "1.3.0",
1556
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
1557
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
1558
+ "license": "MIT",
1559
+ "dependencies": {
1560
+ "safe-buffer": "~5.2.0"
1561
+ }
1562
+ },
1563
+ "node_modules/strip-final-newline": {
1564
+ "version": "2.0.0",
1565
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
1566
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
1567
+ "license": "MIT",
1568
+ "engines": {
1569
+ "node": ">=6"
1570
+ }
1571
+ },
1572
+ "node_modules/tr46": {
1573
+ "version": "0.0.3",
1574
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
1575
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
1576
+ "license": "MIT"
1577
+ },
1578
+ "node_modules/url-join": {
1579
+ "version": "4.0.1",
1580
+ "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
1581
+ "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
1582
+ "license": "MIT"
1583
+ },
1584
+ "node_modules/vite": {
1585
+ "version": "6.0.11",
1586
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz",
1587
+ "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==",
1588
+ "dev": true,
1589
+ "license": "MIT",
1590
+ "dependencies": {
1591
+ "esbuild": "^0.24.2",
1592
+ "postcss": "^8.4.49",
1593
+ "rollup": "^4.23.0"
1594
+ },
1595
+ "bin": {
1596
+ "vite": "bin/vite.js"
1597
+ },
1598
+ "engines": {
1599
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
1600
+ },
1601
+ "funding": {
1602
+ "url": "https://github.com/vitejs/vite?sponsor=1"
1603
+ },
1604
+ "optionalDependencies": {
1605
+ "fsevents": "~2.3.3"
1606
+ },
1607
+ "peerDependencies": {
1608
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
1609
+ "jiti": ">=1.21.0",
1610
+ "less": "*",
1611
+ "lightningcss": "^1.21.0",
1612
+ "sass": "*",
1613
+ "sass-embedded": "*",
1614
+ "stylus": "*",
1615
+ "sugarss": "*",
1616
+ "terser": "^5.16.0",
1617
+ "tsx": "^4.8.1",
1618
+ "yaml": "^2.4.2"
1619
+ },
1620
+ "peerDependenciesMeta": {
1621
+ "@types/node": {
1622
+ "optional": true
1623
+ },
1624
+ "jiti": {
1625
+ "optional": true
1626
+ },
1627
+ "less": {
1628
+ "optional": true
1629
+ },
1630
+ "lightningcss": {
1631
+ "optional": true
1632
+ },
1633
+ "sass": {
1634
+ "optional": true
1635
+ },
1636
+ "sass-embedded": {
1637
+ "optional": true
1638
+ },
1639
+ "stylus": {
1640
+ "optional": true
1641
+ },
1642
+ "sugarss": {
1643
+ "optional": true
1644
+ },
1645
+ "terser": {
1646
+ "optional": true
1647
+ },
1648
+ "tsx": {
1649
+ "optional": true
1650
+ },
1651
+ "yaml": {
1652
+ "optional": true
1653
+ }
1654
+ }
1655
+ },
1656
+ "node_modules/webidl-conversions": {
1657
+ "version": "3.0.1",
1658
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
1659
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
1660
+ "license": "BSD-2-Clause"
1661
+ },
1662
+ "node_modules/whatwg-url": {
1663
+ "version": "5.0.0",
1664
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
1665
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
1666
+ "license": "MIT",
1667
+ "dependencies": {
1668
+ "tr46": "~0.0.3",
1669
+ "webidl-conversions": "^3.0.0"
1670
+ }
1671
+ },
1672
+ "node_modules/which": {
1673
+ "version": "2.0.2",
1674
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
1675
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
1676
+ "license": "ISC",
1677
+ "dependencies": {
1678
+ "isexe": "^2.0.0"
1679
+ },
1680
+ "bin": {
1681
+ "node-which": "bin/node-which"
1682
+ },
1683
+ "engines": {
1684
+ "node": ">= 8"
1685
+ }
1686
+ }
1687
+ }
1688
+ }
package.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "shyguys-wingman-js",
3
+ "version": "1.0.0",
4
+ "description": "ShyguysWingmanJS project",
5
+ "main": "src/index.js",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "elevenlabs": "^1.50.4"
13
+ },
14
+ "devDependencies": {
15
+ "vite": "^6.0.11"
16
+ }
17
+ }
src/constants.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ export const WINGMAN_LABEL = "wingman";
2
+ export const SHYGUY_LABEL = "shyguy";
3
+ export const SISTER_LABEL = "sister";
4
+ export const GIRL_LABEL = "girl";
5
+ export const BAR_LABEL = "barman";
6
+ export const DJ_LABEL = "dj";
7
+ export const EXIT_LABEL = "exit";
src/conversation_llm.js ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import LLM from "./llm";
2
+
3
+ export class ConversationLLM {
4
+ constructor(character1Name, character2Name, character1Prompt, character2Prompt, situation_prompt, outputFormatPrompt, functionDescriptions, functionPrompt) {
5
+ this.character1Name = character1Name;
6
+ this.character2Name = character2Name;
7
+ this.character1Prompt = character1Prompt;
8
+ this.character2Prompt = character2Prompt;
9
+ this.situation_prompt = situation_prompt;
10
+ this.outputFormatPrompt = outputFormatPrompt;
11
+ this.functionDescriptions = functionDescriptions;
12
+ this.functionPrompt = functionPrompt;
13
+
14
+ }
15
+
16
+ async generateConversation(numTurns = 3) {
17
+ try {
18
+ let conversation = [];
19
+ const llm = new LLM();
20
+
21
+ for (let i = 0; i < numTurns; i++) {
22
+
23
+ // Alternate between characters for each turn
24
+ const isCharacter1Turn = i % 2 === 0;
25
+ const currentSpeaker = isCharacter1Turn ? this.character1Prompt : this.character2Prompt;
26
+ const currentListener = isCharacter1Turn ? this.character2Prompt : this.character1Prompt;
27
+ const currentSpeakerName = isCharacter1Turn ? this.character1Name : this.character2Name;
28
+ const currentListenerName = isCharacter1Turn ? this.character2Name : this.character1Name;
29
+
30
+ // Format the conversation history as a proper chat message array
31
+ const conversationHistory = [...conversation];
32
+
33
+ // Create system message for current speaker
34
+ const systemMessage = {
35
+ role: 'system',
36
+ content: `${this.situation_prompt}\nRoleplay as: ${currentSpeakerName}\nMake only the response to the user. Only speech, no speech style. You have the following personality: ${currentSpeaker}. You talk to ${currentListenerName}.`
37
+ };
38
+
39
+ // Get response from LLM with proper message format
40
+ const response = await llm.getChatCompletion(
41
+ systemMessage.content,
42
+ conversationHistory.length > 0
43
+ ? JSON.stringify(conversationHistory)
44
+ : "Start the conversation"
45
+ );
46
+
47
+ // Ensure the response is in the correct format with the proper character role
48
+ const parsedResponse = {
49
+ role: currentSpeakerName, // Use the character name instead of prompt
50
+ content: this.parseConversation(response)
51
+ };
52
+
53
+ conversation.push(parsedResponse);
54
+ }
55
+
56
+ const analysis = await llm.getFunctionKey(
57
+ this.functionDescriptions,
58
+ this.functionPrompt + JSON.stringify(conversation)
59
+ );
60
+
61
+ return {
62
+ conversation,
63
+ analysis
64
+ };
65
+ } catch (error) {
66
+ console.error('Error generating conversation:', error);
67
+ throw error;
68
+ }
69
+ }
70
+ parseConversation(llmResponse) {
71
+
72
+ return llmResponse;
73
+ }
74
+ }
75
+
76
+
src/eleven_labs.js ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { SHYGUY_LABEL, SISTER_LABEL, GIRL_LABEL, BAR_LABEL, DJ_LABEL, WINGMAN_LABEL } from "./constants.js";
2
+
3
+ export class ElevenLabsClient {
4
+ constructor() {
5
+ this.apiKey = "sk_62d0fc2ccddb1a4036f624dd8c411383fd9b9990755ea086";
6
+ this.baseUrl = "https://api.elevenlabs.io/v1";
7
+ }
8
+
9
+ static characterToVoiceIdMapping = {
10
+ [SHYGUY_LABEL]: "bGNROVfU5WbK6F0AyHII",
11
+ [SISTER_LABEL]: "VfTRhexMRVuPmOe9aogj",
12
+ [GIRL_LABEL]: "zQPM9vJjjzGxbs457rQj",
13
+ [BAR_LABEL]: "XA2bIQ92TabjGbpO2xRr",
14
+ [DJ_LABEL]: "T0pkYhIZ7UMOc26gqqeX",
15
+ [WINGMAN_LABEL]: "XA2bIQ92TabjGbpO2xRr",
16
+ };
17
+
18
+ async playAudioForCharacter(character, text) {
19
+ const voiceId = ElevenLabsClient.characterToVoiceIdMapping[character];
20
+ if (!voiceId) {
21
+ throw new Error(`No voice mapping found for character: ${character}`);
22
+ }
23
+ const audioBlob = await this.createSpeech({
24
+ text: text,
25
+ voiceId: voiceId,
26
+ });
27
+ const audioUrl = URL.createObjectURL(audioBlob);
28
+ const audio = new Audio(audioUrl);
29
+
30
+ // hack to wait for the audio to finish playing
31
+ return new Promise((res) => {
32
+ audio.play();
33
+ audio.onended = res;
34
+ });
35
+ }
36
+
37
+ async createSpeech({
38
+ text,
39
+ voiceId,
40
+ modelId = "eleven_multilingual_v2",
41
+ outputFormat = "mp3_44100_128",
42
+ voiceSettings = null,
43
+ pronunciationDictionaryLocators = null,
44
+ seed = null,
45
+ previousText = null,
46
+ nextText = null,
47
+ previousRequestIds = null,
48
+ nextRequestIds = null,
49
+ usePvcAsIvc = false,
50
+ applyTextNormalization = "auto",
51
+ }) {
52
+ const url = `${this.baseUrl}/text-to-speech/${voiceId}?output_format=${outputFormat}`;
53
+
54
+ const requestBody = {
55
+ text,
56
+ model_id: modelId,
57
+ voice_settings: voiceSettings,
58
+ pronunciation_dictionary_locators: pronunciationDictionaryLocators,
59
+ seed,
60
+ previous_text: previousText,
61
+ next_text: nextText,
62
+ previous_request_ids: previousRequestIds,
63
+ next_request_ids: nextRequestIds,
64
+ use_pvc_as_ivc: usePvcAsIvc,
65
+ apply_text_normalization: applyTextNormalization,
66
+ };
67
+
68
+ // Remove null values from request body
69
+ Object.keys(requestBody).forEach((key) => requestBody[key] === null && delete requestBody[key]);
70
+
71
+ try {
72
+ const response = await fetch(url, {
73
+ method: "POST",
74
+ headers: {
75
+ "xi-api-key": this.apiKey,
76
+ "Content-Type": "application/json",
77
+ },
78
+ body: JSON.stringify(requestBody),
79
+ });
80
+
81
+ if (!response.ok) {
82
+ throw new Error(`ElevenLabs API error: ${response.status} ${response.statusText}`);
83
+ }
84
+
85
+ // Return audio blob
86
+ return await response.blob();
87
+ } catch (error) {
88
+ throw new Error(`Failed to create speech: ${error.message}`);
89
+ }
90
+ }
91
+ }
src/game.js ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Shyguy } from "./shyguy.js";
2
+ import { GameEngine } from "./game_engine.js";
3
+ import { ShyGuyLLM } from "./shyguy_llm.js";
4
+ import { StoryEngine } from "./story_engine.js";
5
+ import { SpeechToTextClient } from "./speech_to_text.js";
6
+ import { ElevenLabsClient } from "./eleven_labs.js";
7
+
8
+ export class Game {
9
+ constructor() {
10
+ this.firstRun = true;
11
+
12
+ this.reset = this.reset.bind(this);
13
+ this.initializeComponents();
14
+ }
15
+
16
+ initializeComponents() {
17
+ // Create fresh instances of all components
18
+ this.shyguy = new Shyguy();
19
+ this.speechToTextClient = new SpeechToTextClient();
20
+ this.elevenLabsClient = new ElevenLabsClient();
21
+ this.shyguyLLM = new ShyGuyLLM(this.shyguy);
22
+ this.storyEngine = new StoryEngine(this.shyguy);
23
+ this.gameEngine = new GameEngine(
24
+ this.shyguy,
25
+ this.shyguyLLM,
26
+ this.storyEngine,
27
+ this.speechToTextClient,
28
+ this.elevenLabsClient
29
+ );
30
+ }
31
+
32
+ async run() {
33
+ this.gameEngine.init(this.firstRun);
34
+ this.gameEngine.setResetCallback(this.reset);
35
+ this.gameEngine.playBackgroundMusic();
36
+ this.gameEngine.lowerMusicVolume();
37
+ }
38
+
39
+ reset() {
40
+ this.firstRun = false;
41
+ // Clean up old game engine
42
+ if (this.gameEngine) {
43
+ // Remove event listeners and clean up
44
+ document.removeEventListener("keydown", this.gameEngine.handleKeyDown);
45
+ document.removeEventListener("keyup", this.gameEngine.handleKeyUp);
46
+ this.gameEngine.sendButton?.removeEventListener("click", this.gameEngine.handleSendMessage);
47
+ this.gameEngine.dialogueContinueButton?.removeEventListener("click", this.gameEngine.handleDialogueContinue);
48
+ this.gameEngine.playAgainBtn?.removeEventListener("click", this.gameEngine.handlePlayAgain);
49
+ this.gameEngine.microphoneButton?.removeEventListener("click", this.gameEngine.handleMicrophone);
50
+ this.gameEngine.startGameBtn?.removeEventListener("click", this.gameEngine.handleStartGame);
51
+ this.gameEngine.dialogueNextButton?.removeEventListener("click", this.gameEngine.handleDialogueNext);
52
+
53
+ // Stop the game loop
54
+ this.gameEngine.shouldContinue = false;
55
+ }
56
+
57
+ setTimeout(() => {
58
+ // Create fresh instances
59
+ this.initializeComponents();
60
+
61
+ this.run();
62
+ }, 100);
63
+ }
64
+ }
src/game_engine.js ADDED
@@ -0,0 +1,1167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { BAR_LABEL, DJ_LABEL, EXIT_LABEL, GIRL_LABEL, SISTER_LABEL, WINGMAN_LABEL, SHYGUY_LABEL } from "./constants";
2
+ import { nameToLabel } from "./story_engine.js";
3
+
4
+ const WINGMAN_SPEED = 5;
5
+ const SHYGUY_SPEED = 1;
6
+
7
+ const IS_DEBUG = false;
8
+
9
+ class SpriteEntity {
10
+ constructor(x0, y0, imageSrc, speed = 0, width = 24, height = 64, frameRate = 8, frameCount = 1) {
11
+ this.x = x0;
12
+ this.y = y0;
13
+ this.width = width;
14
+ this.height = height;
15
+ this.image = new Image();
16
+ this.image.src = imageSrc;
17
+ this.frameRate = frameRate;
18
+ this.frameCount = frameCount;
19
+
20
+ // properties for the game engine
21
+ this.moving = false;
22
+ this.speed = speed;
23
+
24
+ // frame index in the sprite sheet
25
+ this.frameX = 0;
26
+ this.frameY = 0; // 0 for right, 1 for left
27
+ }
28
+
29
+ stop() {
30
+ this.moving = false;
31
+ }
32
+
33
+ start() {
34
+ this.moving = true;
35
+ }
36
+
37
+ setSpeed(speed) {
38
+ this.speed = speed;
39
+ }
40
+ }
41
+
42
+ class GuidedSpriteEntity extends SpriteEntity {
43
+ constructor(x0, y0, imageSrc, speed = 0, width = 24, height = 64, frameRate = 8, frameCount = 1) {
44
+ super(x0, y0, imageSrc, speed, width, height, frameRate, frameCount);
45
+ this.target = null;
46
+ }
47
+
48
+ setTarget(target) {
49
+ this.target = target;
50
+ }
51
+ }
52
+
53
+ class SpriteImage {
54
+ constructor(imageSrc, width = 32, height = 32) {
55
+ this.image = new Image();
56
+ this.image.src = imageSrc;
57
+ this.width = width;
58
+ this.height = height;
59
+ }
60
+ }
61
+
62
+ class Target {
63
+ constructor(label, x, y, width, height, color, enabled = true) {
64
+ this.label = label;
65
+ this.x = x;
66
+ this.y = y;
67
+ this.width = width;
68
+ this.height = height;
69
+ this.debugColor = color;
70
+ this.enabled = enabled;
71
+ }
72
+ }
73
+
74
+ export class GameEngine {
75
+ static introMessages = [
76
+ {
77
+ message:
78
+ "Hey man, this is really not my cup of tea. I see Jessica in the corner, I wonder if I can finally tell her I love her.",
79
+ character: SHYGUY_LABEL,
80
+ },
81
+ {
82
+ message: "Man, tonight is your night. I'll get you through it and you'll go home with Jessica.",
83
+ character: WINGMAN_LABEL,
84
+ },
85
+ {
86
+ message: "Geez, that's impossible! Even if I replay the night a million times, I couldn't do it.",
87
+ character: SHYGUY_LABEL,
88
+ },
89
+ {
90
+ message: "Okay, just follow my advice! I'll push you around if needed.",
91
+ character: WINGMAN_LABEL,
92
+ },
93
+ ];
94
+
95
+ constructor(shyguy, shyguyLLM, storyEngine, speechToTextClient, elevenLabsClient) {
96
+ this.shyguy = shyguy;
97
+ this.shyguyLLM = shyguyLLM;
98
+ this.storyEngine = storyEngine;
99
+ this.speechToTextClient = speechToTextClient;
100
+ this.elevenLabsClient = elevenLabsClient;
101
+
102
+ this.canvasWidth = 960;
103
+ this.canvasHeight = 640;
104
+ this.canvas = document.getElementById("gameCanvas");
105
+ if (!this.canvas) {
106
+ console.error("Canvas not found");
107
+ }
108
+ this.ctx = this.canvas.getContext("2d");
109
+
110
+ // View management
111
+ this.gameView = document.getElementById("gameView");
112
+ this.dialogueView = document.getElementById("dialogueView");
113
+ this.currentView = "game";
114
+
115
+ this.shouldContinue = true;
116
+
117
+ this.gameOver = false;
118
+ this.gameSuccessful = false;
119
+
120
+ this.gameChatContainer = document.getElementById("chatMessages");
121
+ this.messageInput = document.getElementById("messageInput");
122
+ this.sendButton = document.getElementById("sendButton");
123
+ this.microphoneButton = document.getElementById("micButton");
124
+ this.gameOverImage = document.getElementById("gameOverImage");
125
+ this.gameOverText = document.getElementById("gameOverText");
126
+
127
+ this.dialogueChatContainer = document.getElementById("dialogueMessages");
128
+ this.dialogueContinueButton = document.getElementById("dialogueContinueButton");
129
+ this.dialogueNextButton = document.getElementById("dialogueNextButton");
130
+
131
+ this.gameFrame = 0;
132
+ this.keys = {
133
+ ArrowUp: false,
134
+ ArrowDown: false,
135
+ ArrowLeft: false,
136
+ ArrowRight: false,
137
+ };
138
+
139
+ // Bind methods
140
+ this.switchView = this.switchView.bind(this);
141
+ this.update = this.update.bind(this);
142
+ this.draw = this.draw.bind(this);
143
+ this.run = this.run.bind(this);
144
+ this.handleKeyDown = this.handleKeyDown.bind(this);
145
+ this.handleKeyUp = this.handleKeyUp.bind(this);
146
+ this.setNewTarget = this.setNewTarget.bind(this);
147
+ this.checkTargetReached = this.checkTargetReached.bind(this);
148
+ this.updateGuidedSpriteDirection = this.updateGuidedSpriteDirection.bind(this);
149
+ this.updateSprite = this.updateSprite.bind(this);
150
+ this.handleSpriteCollision = this.handleSpriteCollision.bind(this);
151
+ this.initDebugControls = this.initDebugControls.bind(this);
152
+ this.stopShyguyAnimation = this.stopShyguyAnimation.bind(this);
153
+ this.handlePlayAgain = this.handlePlayAgain.bind(this);
154
+ this.handleMicrophone = this.handleMicrophone.bind(this);
155
+ this.handleSendMessage = this.handleSendMessage.bind(this);
156
+ this.handleMicrophone = this.handleMicrophone.bind(this);
157
+ this.handleDialogueContinue = this.handleDialogueContinue.bind(this);
158
+ this.handleFirstStartGame = this.handleFirstStartGame.bind(this);
159
+ this.setGameOver = this.setGameOver.bind(this);
160
+ this.handleDialogueNext = this.handleDialogueNext.bind(this);
161
+
162
+ this.pushEnabled = false;
163
+ this.voiceEnabled = !IS_DEBUG;
164
+
165
+ // Debug controls
166
+ this.initDebugControls();
167
+
168
+ // if we have other obstacles, we can add them here
169
+ this.gridMapTypes = {
170
+ floor: 0,
171
+ wall: 1,
172
+ door: 2,
173
+ };
174
+
175
+ // load assets for drawing the scene
176
+ this.wall = new SpriteImage("/assets/assets/wall_sprite.png");
177
+ this.floor = new SpriteImage("/assets/assets/floor-tile.png");
178
+ this.door = new SpriteImage("/assets/assets/door_sprite.png");
179
+
180
+ this.gridCols = Math.ceil(this.canvasWidth / this.wall.width);
181
+ this.gridRows = Math.ceil(this.canvasHeight / this.wall.height);
182
+
183
+ // initialize grid map
184
+ this.backgroundGridMap = [];
185
+ this.initBackgroundGridMap();
186
+
187
+ // initialize players
188
+ const cx = this.canvasWidth / 2;
189
+ const cy = this.canvasHeight / 2;
190
+ this.shyguySprite = new GuidedSpriteEntity(cx, cy, "/assets/assets/shyguy_sprite.png", SHYGUY_SPEED);
191
+ this.wingmanSprite = new SpriteEntity(
192
+ this.wall.width,
193
+ this.canvasHeight - this.wall.height - 64,
194
+ "/assets/assets/wingman_sprite.png",
195
+ WINGMAN_SPEED
196
+ );
197
+
198
+ this.jessicaSprite = new SpriteImage("/assets/assets/jessica_sprite.png", 64, 64);
199
+ this.djSprite = new SpriteImage("/assets/assets/dj_sprite.png", 64, 64);
200
+ this.barSprite = new SpriteImage("/assets/assets/bar_sprite.png", 64, 64);
201
+ this.sisterSprite = new SpriteImage("/assets/assets/sister_sprite.png", 64, 64);
202
+
203
+ this.targets = {
204
+ exit: new Target(EXIT_LABEL, this.wall.width, this.wall.height, this.wall.width, this.wall.height, "red", true),
205
+ girl: new Target(
206
+ GIRL_LABEL,
207
+ this.canvasWidth - this.wall.width - this.jessicaSprite.width,
208
+ (this.canvasHeight - this.wall.height - this.jessicaSprite.height) / 2,
209
+ this.jessicaSprite.width,
210
+ this.jessicaSprite.height,
211
+ "pink",
212
+ true
213
+ ),
214
+ bar: new Target(
215
+ BAR_LABEL,
216
+ (this.canvasWidth - this.wall.width - this.barSprite.width) / 2,
217
+ this.wall.height,
218
+ this.barSprite.width,
219
+ this.barSprite.height,
220
+ "blue",
221
+ true
222
+ ),
223
+ dj: new Target(
224
+ DJ_LABEL,
225
+ this.wall.width,
226
+ (this.canvasHeight - this.wall.height - this.djSprite.height) / 2,
227
+ this.djSprite.width,
228
+ this.djSprite.height,
229
+ "green",
230
+ true
231
+ ),
232
+ sister: new Target(
233
+ SISTER_LABEL,
234
+ this.canvasWidth - this.wall.width - this.sisterSprite.width,
235
+ this.wall.height,
236
+ this.sisterSprite.width,
237
+ this.sisterSprite.height,
238
+ "yellow",
239
+ true
240
+ ),
241
+ };
242
+
243
+ // Add game over view
244
+ this.gameOverView = document.getElementById("gameOverView");
245
+ this.playAgainBtn = document.getElementById("playAgainBtn");
246
+
247
+ this.isRecording = false;
248
+
249
+ // Add these lines
250
+ this.introView = document.getElementById("introView");
251
+ this.startGameBtn = document.getElementById("startGameBtn");
252
+
253
+ this.backgroundMusic = new Audio("assets/assets/tiny-steps-danijel-zambo-main-version-1433-01-48.mp3");
254
+ this.backgroundMusic.loop = true;
255
+
256
+ this.gameOverMusic = new Audio("/assets/assets/game-over-8bit-music-danijel-zambo-1-00-16.mp3");
257
+ this.gameOverMusic.loop = false;
258
+
259
+ this.victoryMusic = new Audio("/assets/assets/moonlit-whispers-theo-gerard-main-version-35960-02-34.mp3");
260
+ this.victoryMusic.loop = false;
261
+
262
+ // Move character images to class state
263
+ this.leftCharacterImg = document.getElementById("leftCharacterImg");
264
+ this.rightCharacterImg = document.getElementById("rightCharacterImg");
265
+ this.hideCharacterImages();
266
+ }
267
+
268
+ showCharacterImages() {
269
+ this.leftCharacterImg.style.display = "block";
270
+ this.rightCharacterImg.style.display = "block";
271
+ }
272
+
273
+ hideCharacterImages() {
274
+ this.leftCharacterImg.style.display = "none";
275
+ this.rightCharacterImg.style.display = "none";
276
+ }
277
+
278
+ init(firstRun = true) {
279
+ this.canvas.width = this.canvasWidth;
280
+ this.canvas.height = this.canvasHeight;
281
+
282
+ document.addEventListener("keydown", this.handleKeyDown);
283
+ document.addEventListener("keyup", this.handleKeyUp);
284
+
285
+ // Initialize with game view
286
+
287
+ this.sendButton.addEventListener("click", this.handleSendMessage);
288
+ this.dialogueContinueButton.addEventListener("click", this.handleDialogueContinue);
289
+ this.dialogueNextButton.addEventListener("click", this.handleDialogueNext);
290
+ this.playAgainBtn.addEventListener("click", this.handlePlayAgain);
291
+ this.microphoneButton.addEventListener("click", this.handleMicrophone);
292
+
293
+ if (firstRun) {
294
+ this.startGameBtn.addEventListener("click", this.handleFirstStartGame);
295
+ this.switchView("intro");
296
+ } else {
297
+ if (this.currentView !== "game") {
298
+ this.switchView("game");
299
+ }
300
+ this.run();
301
+ this.shyguySprite.setTarget(this.targets.exit);
302
+ }
303
+ }
304
+
305
+ async handleFirstStartGame() {
306
+ this.switchView("dialogue");
307
+ this.leftCharacterImg.src = "/assets/assets/wingman.jpeg";
308
+ this.rightCharacterImg.src = "/assets/assets/shyguy_headshot.jpeg";
309
+ this.showCharacterImages();
310
+ this.hideContinueButton();
311
+
312
+ for (const introMessage of GameEngine.introMessages) {
313
+ const { message, character } = introMessage;
314
+ this.addChatMessage(this.dialogueChatContainer, message, character, true);
315
+ if (this.voiceEnabled) {
316
+ await this.elevenLabsClient.playAudioForCharacter(character, message);
317
+ } else {
318
+ await new Promise((resolve) => setTimeout(resolve, 1000));
319
+ }
320
+ }
321
+
322
+ this.showNextButton();
323
+ }
324
+
325
+ showNextButton() {
326
+ if (this.dialogueNextButton) {
327
+ this.dialogueNextButton.style.display = "block";
328
+ }
329
+ }
330
+
331
+ hideNextButton() {
332
+ if (this.dialogueNextButton) {
333
+ this.dialogueNextButton.style.display = "none";
334
+ }
335
+ }
336
+
337
+ handleDialogueNext() {
338
+ this.clearChat(this.dialogueChatContainer);
339
+ this.leftCharacterImg.src = "";
340
+ this.rightCharacterImg.src = "";
341
+ this.hideCharacterImages();
342
+ this.hideNextButton();
343
+ this.showContinueButton();
344
+ this.handleStartGame();
345
+ }
346
+
347
+ async handleStartGame() {
348
+ this.switchView("game");
349
+ this.playBackgroundMusic();
350
+ this.run();
351
+ this.shyguySprite.setTarget(this.targets.exit);
352
+ }
353
+
354
+ setResetCallback(func) {
355
+ this.resetCallback = func;
356
+ }
357
+
358
+ resetGame() {
359
+ if (this.resetCallback) {
360
+ this.resetCallback();
361
+ }
362
+ }
363
+
364
+ initBackgroundGridMap() {
365
+ for (let row = 0; row < this.gridRows; row++) {
366
+ this.backgroundGridMap[row] = [];
367
+ for (let col = 0; col < this.gridCols; col++) {
368
+ // Set walls and obstacles (in future)
369
+ if (row === 0 || row === this.gridRows - 1 || col === 0 || col === this.gridCols - 1) {
370
+ this.backgroundGridMap[row][col] = this.gridMapTypes.wall;
371
+ } else {
372
+ this.backgroundGridMap[row][col] = this.gridMapTypes.floor;
373
+ }
374
+ }
375
+ }
376
+ this.backgroundGridMap[0][1] = this.gridMapTypes.door;
377
+ }
378
+
379
+ checkWallCollision(sprite, newX, newY) {
380
+ const x = newX;
381
+ const y = newY;
382
+ // For a sprite twice as big as grid, divide by half the sprite width/height
383
+ const gridX = Math.floor(x / (sprite.width * 1.33));
384
+ const gridY = Math.floor(y / (sprite.height / 2));
385
+
386
+ // Check all grid cells the sprite overlaps
387
+ // For a sprite twice as big, it can overlap up to 4 cells
388
+ for (let row = gridY; row <= Math.floor((y + sprite.height) / (sprite.height / 2)); row++) {
389
+ for (let col = gridX; col <= Math.floor((x + sprite.width) / (sprite.width * 1.33)); col++) {
390
+ if (row >= 0 && row < this.gridRows && col >= 0 && col < this.gridCols) {
391
+ if (this.backgroundGridMap[row][col] === this.gridMapTypes.wall) {
392
+ return true;
393
+ }
394
+ }
395
+ }
396
+ }
397
+
398
+ return false;
399
+ }
400
+
401
+ checkSpriteCollision(newX, newY, sprite1, sprite2) {
402
+ return (
403
+ newX < sprite2.x + sprite2.width &&
404
+ newX + sprite1.width > sprite2.x &&
405
+ newY < sprite2.y + sprite2.height &&
406
+ newY + sprite1.height > sprite2.y
407
+ );
408
+ }
409
+
410
+ handleSpriteCollision(sprite1, sprite2) {
411
+ if (!this.pushEnabled) {
412
+ return true; // Return true to block movement as before
413
+ }
414
+
415
+ // Calculate velocity difference
416
+ let dx = 0;
417
+ let dy = 0;
418
+ if (this.keys.ArrowUp) dy = -sprite1.speed;
419
+ else if (this.keys.ArrowDown) dy = sprite1.speed;
420
+ else if (this.keys.ArrowLeft) dx = -sprite1.speed;
421
+ else if (this.keys.ArrowRight) dx = sprite1.speed;
422
+
423
+ // If arrow player isn't moving, stop button player
424
+ if (dx === 0 && dy === 0) {
425
+ return true;
426
+ }
427
+
428
+ // Calculate effective push speed (difference in velocities)
429
+ const pushSpeed = Math.max(0, sprite1.speed - sprite2.speed);
430
+
431
+ // If arrow player is faster, push button player
432
+ if (pushSpeed > 0) {
433
+ let newX = sprite2.x + (dx !== 0 ? dx : 0);
434
+ let newY = sprite2.y + (dy !== 0 ? dy : 0);
435
+
436
+ // Only apply the push if it won't result in a wall collision
437
+ if (!this.checkWallCollision(sprite2, newX, newY)) {
438
+ sprite2.x = newX;
439
+ sprite2.y = newY;
440
+ }
441
+ }
442
+
443
+ return true; // Still prevent arrow player from moving through button player
444
+ }
445
+
446
+ updateGuidedSprite() {
447
+ if (!this.shyguySprite.target) return;
448
+
449
+ const dx = this.shyguySprite.target.x - this.shyguySprite.x;
450
+ const dy = this.shyguySprite.target.y - this.shyguySprite.y;
451
+ const distance = Math.sqrt(dx * dx + dy * dy);
452
+
453
+ const moveX = (dx / distance) * this.shyguySprite.speed;
454
+ const moveY = (dy / distance) * this.shyguySprite.speed;
455
+
456
+ let newX = this.shyguySprite.x + moveX;
457
+ let newY = this.shyguySprite.y + moveY;
458
+
459
+ // Check wall collision first
460
+ if (!this.checkWallCollision(this.shyguySprite, newX, newY)) {
461
+ const willCollide = this.checkSpriteCollision(newX, newY, this.shyguySprite, this.wingmanSprite);
462
+
463
+ if (willCollide) {
464
+ if (this.pushEnabled) {
465
+ // Push mechanics enabled - try to push wingman
466
+ const pushSpeed = Math.max(0, this.shyguySprite.speed - this.wingmanSprite.speed);
467
+
468
+ if (pushSpeed > 0) {
469
+ let wingmanNewX = this.wingmanSprite.x + moveX;
470
+ let wingmanNewY = this.wingmanSprite.y + moveY;
471
+
472
+ if (!this.checkWallCollision(this.wingmanSprite, wingmanNewX, wingmanNewY)) {
473
+ this.wingmanSprite.x = wingmanNewX;
474
+ this.wingmanSprite.y = wingmanNewY;
475
+ this.shyguySprite.x = newX;
476
+ this.shyguySprite.y = newY;
477
+ this.shyguySprite.moving = true;
478
+ }
479
+ }
480
+ }
481
+
482
+ // If push is disabled or push failed, try to path around
483
+ if (this.shyguySprite.x === newX && this.shyguySprite.y === newY) {
484
+ const leftPath = { x: newX - this.wingmanSprite.width, y: newY };
485
+ const rightPath = { x: newX + this.wingmanSprite.width, y: newY };
486
+ const upPath = { x: newX, y: newY - this.wingmanSprite.height };
487
+ const downPath = { x: newX, y: newY + this.wingmanSprite.height };
488
+
489
+ const paths = [leftPath, rightPath, upPath, downPath];
490
+ let bestPath = null;
491
+ let bestDistance = Infinity;
492
+
493
+ for (const path of paths) {
494
+ if (
495
+ !this.checkWallCollision(this.shyguySprite, path.x, path.y) &&
496
+ !this.checkSpriteCollision(path.x, path.y, this.shyguySprite, this.wingmanSprite)
497
+ ) {
498
+ const pathDistance = Math.sqrt(
499
+ Math.pow(this.shyguySprite.target.x - path.x, 2) + Math.pow(this.shyguySprite.target.y - path.y, 2)
500
+ );
501
+ if (pathDistance < bestDistance) {
502
+ bestDistance = pathDistance;
503
+ bestPath = path;
504
+ }
505
+ }
506
+ }
507
+
508
+ if (bestPath) {
509
+ this.shyguySprite.x = bestPath.x;
510
+ this.shyguySprite.y = bestPath.y;
511
+ this.shyguySprite.moving = true;
512
+ }
513
+ }
514
+ } else {
515
+ // No collision, proceed normally
516
+ this.shyguySprite.x = newX;
517
+ this.shyguySprite.y = newY;
518
+ this.shyguySprite.moving = true;
519
+ }
520
+ }
521
+ }
522
+
523
+ updateSprite() {
524
+ let newX = this.wingmanSprite.x;
525
+ let newY = this.wingmanSprite.y;
526
+ let isMoving = false;
527
+
528
+ if (this.keys.ArrowUp) {
529
+ newY -= this.wingmanSprite.speed;
530
+ isMoving = true;
531
+ }
532
+ if (this.keys.ArrowDown) {
533
+ newY += this.wingmanSprite.speed;
534
+ isMoving = true;
535
+ }
536
+ if (this.keys.ArrowLeft) {
537
+ newX -= this.wingmanSprite.speed;
538
+ this.wingmanSprite.frameY = 0; // left
539
+ isMoving = true;
540
+ }
541
+ if (this.keys.ArrowRight) {
542
+ newX += this.wingmanSprite.speed;
543
+ this.wingmanSprite.frameY = 1; // right
544
+ isMoving = true;
545
+ }
546
+
547
+ // Check wall collision first
548
+ if (!this.checkWallCollision(this.wingmanSprite, newX, newY)) {
549
+ // Check collision with shyguy
550
+ const willCollide = this.checkSpriteCollision(newX, newY, this.wingmanSprite, this.shyguySprite);
551
+
552
+ if (willCollide) {
553
+ if (this.pushEnabled) {
554
+ // Try to push shyguy if push is enabled
555
+ this.handleSpriteCollision(this.wingmanSprite, this.shyguySprite);
556
+ }
557
+ // If push is disabled or push failed, don't move
558
+ return;
559
+ }
560
+
561
+ // No collision, proceed with movement
562
+ this.wingmanSprite.x = newX;
563
+ this.wingmanSprite.y = newY;
564
+ }
565
+
566
+ this.wingmanSprite.moving = isMoving;
567
+ }
568
+
569
+ handleKeyDown(e) {
570
+ if (e.key in this.keys) {
571
+ this.keys[e.key] = true;
572
+ this.wingmanSprite.moving = true;
573
+ } else if (e.key === "Enter" && this.currentView === "game" && !e.shiftKey) {
574
+ e.preventDefault();
575
+ this.handleSendMessage();
576
+ }
577
+ }
578
+
579
+ handleKeyUp(e) {
580
+ if (e.key in this.keys) {
581
+ this.keys[e.key] = false;
582
+ this.wingmanSprite.moving = Object.values(this.keys).some((key) => key);
583
+ }
584
+ }
585
+
586
+ setNewTarget(target) {
587
+ if (target && target.enabled) {
588
+ this.shyguySprite.setTarget(target);
589
+ this.updateGuidedSpriteDirection(this.shyguySprite);
590
+ }
591
+ if (!target) {
592
+ this.shyguySprite.setTarget(null);
593
+ }
594
+ }
595
+
596
+ checkTargetReached(sprite, target) {
597
+ // Check if sprite overlaps with target using AABB collision detection
598
+ const spriteLeft = sprite.x;
599
+ const spriteRight = sprite.x + sprite.width;
600
+ const spriteTop = sprite.y;
601
+ const spriteBottom = sprite.y + sprite.height;
602
+
603
+ const targetLeft = target.x;
604
+ const targetRight = target.x + target.width;
605
+ const targetTop = target.y;
606
+ const targetBottom = target.y + target.height;
607
+
608
+ // Check for overlap on both x and y axes
609
+ const xOverlap = spriteRight >= targetLeft && spriteLeft <= targetRight;
610
+ const yOverlap = spriteBottom >= targetTop && spriteTop <= targetBottom;
611
+
612
+ return xOverlap && yOverlap;
613
+ }
614
+
615
+ updateGuidedSpriteDirection(sprite) {
616
+ if (!sprite.target) return;
617
+
618
+ const dx = sprite.target.x - sprite.x;
619
+
620
+ // Update direction based only on horizontal movement
621
+ if (dx !== 0) {
622
+ sprite.frameY = dx > 0 ? 1 : 0; // 0 for right, 1 for left
623
+ }
624
+ }
625
+
626
+ updateSpriteAnimation(sprite) {
627
+ if (sprite.moving) {
628
+ if (this.gameFrame % sprite.frameRate === 0) {
629
+ sprite.frameX = (sprite.frameX + 1) % sprite.frameCount;
630
+ }
631
+ } else {
632
+ sprite.frameX = 0;
633
+ }
634
+ }
635
+
636
+ async update() {
637
+ this.gameFrame++;
638
+
639
+ // Update Shyguy position
640
+ if (this.shyguySprite.target && this.shyguySprite.target.enabled) {
641
+ this.updateGuidedSprite(this.shyguySprite);
642
+ if (this.shyguySprite.moving) {
643
+ this.updateSpriteAnimation(this.shyguySprite);
644
+ }
645
+ }
646
+
647
+ // update Wingman position
648
+ this.updateSprite(this.wingmanSprite);
649
+ if (this.wingmanSprite.moving) {
650
+ this.updateSpriteAnimation(this.wingmanSprite);
651
+ }
652
+
653
+ for (const target of Object.values(this.targets)) {
654
+ const isClose = this.checkTargetReached(this.shyguySprite, target);
655
+
656
+ // TODO: reenable the target so the player can visit it again
657
+ if (!target.enabled) {
658
+ if (!isClose) {
659
+ target.enabled = true;
660
+ }
661
+ continue;
662
+ }
663
+
664
+ if (isClose) {
665
+ // pause the game
666
+ target.enabled = false;
667
+ this.stopShyguyAnimation(target);
668
+
669
+ if (target.label === EXIT_LABEL) {
670
+ this.gameOver = true;
671
+ this.gameSuccessful = false;
672
+ this.setGameOver(true);
673
+ this.switchView("gameOver");
674
+ } else {
675
+ await this.handleDialogueWithStoryEngine(target.label);
676
+ }
677
+ break;
678
+ }
679
+ }
680
+ }
681
+
682
+ async handleDialogueWithStoryEngine(label) {
683
+ this.switchView("dialogue");
684
+ this.hideContinueButton();
685
+
686
+ // Show loading indicator
687
+ const dialogueBox = document.querySelector(".dialogue-box");
688
+ dialogueBox.classList.add("loading");
689
+
690
+ const response = await this.storyEngine.onEncounter(label);
691
+
692
+ // Hide loading indicator
693
+ dialogueBox.classList.remove("loading");
694
+
695
+ // Update character images using class properties
696
+ if (this.leftCharacterImg && response.char2imgpath) {
697
+ this.leftCharacterImg.src = response.char2imgpath;
698
+ this.leftCharacterImg.style.display = "block";
699
+ }
700
+
701
+ if (this.rightCharacterImg && response.char1imgpath) {
702
+ this.rightCharacterImg.src = response.char1imgpath;
703
+ this.rightCharacterImg.style.display = "block";
704
+ }
705
+
706
+ const conversation = response.conversation;
707
+
708
+ // TODO: set the images if they are available
709
+
710
+ for (const message of conversation) {
711
+ const { role, content } = message;
712
+ const label = nameToLabel(role);
713
+ this.addChatMessage(this.dialogueChatContainer, content, label, true);
714
+
715
+ // Only play audio if voice is enabled
716
+ if (this.voiceEnabled) {
717
+ try {
718
+ this.lowerMusicVolumeALot();
719
+ await this.elevenLabsClient.playAudioForCharacter(label, content);
720
+ this.restoreMusicVolume();
721
+ } catch (error) {
722
+ console.error("Error playing audio:", label);
723
+ }
724
+ }
725
+ }
726
+
727
+ if (response.gameSuccesful) {
728
+ this.gameOver = true;
729
+ this.gameSuccessful = true;
730
+ } else if (response.gameOver) {
731
+ this.gameOver = true;
732
+ this.gameSuccessful = false;
733
+ } else {
734
+ this.gameOver = false;
735
+ this.gameSuccessful = false;
736
+ }
737
+
738
+ this.showContinueButton();
739
+ }
740
+
741
+ stopShyguyAnimation(target) {
742
+ this.shyguySprite.moving = false;
743
+ this.shyguySprite.frameX = 0;
744
+ this.shyguySprite.target = null;
745
+ }
746
+
747
+ draw() {
748
+ this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
749
+
750
+ // Draw grid map
751
+ for (let row = 0; row < this.gridRows; row++) {
752
+ for (let col = 0; col < this.gridCols; col++) {
753
+ const x = col * this.wall.width;
754
+ const y = row * this.wall.height;
755
+
756
+ if (this.backgroundGridMap[row][col] === this.gridMapTypes.wall) {
757
+ this.ctx.drawImage(this.wall.image, x, y, this.wall.width, this.wall.height);
758
+ } else if (this.backgroundGridMap[row][col] === this.gridMapTypes.floor) {
759
+ this.ctx.drawImage(this.floor.image, x, y, this.floor.width, this.floor.height);
760
+ } else if (this.backgroundGridMap[row][col] === this.gridMapTypes.door) {
761
+ this.ctx.drawImage(this.door.image, x, y, this.door.width, this.door.height);
762
+ }
763
+ }
764
+ }
765
+
766
+ this.drawTargetSprite(this.jessicaSprite, this.targets.girl);
767
+ this.drawTargetSprite(this.barSprite, this.targets.bar);
768
+ this.drawTargetSprite(this.djSprite, this.targets.dj);
769
+ this.drawTargetSprite(this.sisterSprite, this.targets.sister);
770
+
771
+ // Draw shyguy
772
+ this.ctx.drawImage(
773
+ this.shyguySprite.image,
774
+ this.shyguySprite.frameX * this.shyguySprite.width,
775
+ this.shyguySprite.frameY * this.shyguySprite.height,
776
+ this.shyguySprite.width,
777
+ this.shyguySprite.height,
778
+ this.shyguySprite.x,
779
+ this.shyguySprite.y,
780
+ this.shyguySprite.width,
781
+ this.shyguySprite.height
782
+ );
783
+
784
+ // Draw wingman
785
+ this.ctx.drawImage(
786
+ this.wingmanSprite.image,
787
+ this.wingmanSprite.frameX * this.wingmanSprite.width,
788
+ this.wingmanSprite.frameY * this.wingmanSprite.height,
789
+ this.wingmanSprite.width,
790
+ this.wingmanSprite.height,
791
+ this.wingmanSprite.x,
792
+ this.wingmanSprite.y,
793
+ this.wingmanSprite.width,
794
+ this.wingmanSprite.height
795
+ );
796
+ }
797
+
798
+ drawTargetSprite(sprite, target) {
799
+ this.ctx.drawImage(sprite.image, target.x, target.y, target.width, target.height);
800
+ }
801
+
802
+ switchView(viewName) {
803
+ if (viewName === this.currentView) return;
804
+
805
+ this.currentView = viewName;
806
+
807
+ // Hide all views first
808
+ this.introView.classList.remove("active");
809
+ this.gameView.classList.remove("active");
810
+ this.dialogueView.classList.remove("active");
811
+ this.gameOverView.classList.remove("active");
812
+
813
+ // Show the requested view
814
+ switch (viewName) {
815
+ case "intro":
816
+ this.introView.classList.add("active");
817
+ break;
818
+ case "game":
819
+ this.gameView.classList.add("active");
820
+ break;
821
+ case "dialogue":
822
+ this.dialogueView.classList.add("active");
823
+ break;
824
+ case "gameOver":
825
+ this.gameOverView.classList.add("active");
826
+ break;
827
+ }
828
+ }
829
+
830
+ enablePush() {
831
+ this.pushEnabled = true;
832
+ }
833
+
834
+ disablePush() {
835
+ this.pushEnabled = false;
836
+ }
837
+
838
+ initDebugControls() {
839
+ const debugControls = document.getElementById("debugControls");
840
+ if (!IS_DEBUG) {
841
+ if (debugControls) {
842
+ debugControls.style.display = "none";
843
+ }
844
+ return;
845
+ }
846
+
847
+ const targetDoorBtn = document.getElementById("targetDoorBtn");
848
+ const targetGirlBtn = document.getElementById("targetGirlBtn");
849
+ const targetBarBtn = document.getElementById("targetBarBtn");
850
+ const targetDjBtn = document.getElementById("targetDjBtn");
851
+ const targetSisterBtn = document.getElementById("targetSisterBtn");
852
+ const stopNavBtn = document.getElementById("stopNavBtn");
853
+ const togglePushBtn = document.getElementById("togglePushBtn");
854
+ const speedBoostBtn = document.getElementById("speedBoostBtn");
855
+ const toggleVoiceBtn = document.getElementById("toggleVoiceBtn");
856
+
857
+ targetDoorBtn.addEventListener("click", () => this.setNewTarget(this.targets.exit));
858
+ targetGirlBtn.addEventListener("click", () => this.setNewTarget(this.targets.girl));
859
+ targetBarBtn.addEventListener("click", () => this.setNewTarget(this.targets.bar));
860
+ targetDjBtn.addEventListener("click", () => this.setNewTarget(this.targets.dj));
861
+ targetSisterBtn.addEventListener("click", () => this.setNewTarget(this.targets.sister));
862
+ stopNavBtn.addEventListener("click", () => this.setNewTarget(null));
863
+
864
+ // Add push mechanics toggle
865
+ togglePushBtn.addEventListener("click", () => {
866
+ if (this.pushEnabled) {
867
+ this.disablePush();
868
+ } else {
869
+ this.enablePush();
870
+ }
871
+ togglePushBtn.textContent = this.pushEnabled ? "Disable Push" : "Enable Push";
872
+ });
873
+
874
+ // Add speed boost toggle
875
+ speedBoostBtn.addEventListener("click", () => {
876
+ if (this.shyguySprite.speed === SHYGUY_SPEED) {
877
+ this.shyguySprite.setSpeed(10);
878
+ speedBoostBtn.textContent = "Normal Speed";
879
+ } else {
880
+ this.shyguySprite.setSpeed(SHYGUY_SPEED);
881
+ speedBoostBtn.textContent = "Speed Boost";
882
+ }
883
+ });
884
+
885
+ // Add voice toggle handler
886
+ toggleVoiceBtn.addEventListener("click", () => {
887
+ this.voiceEnabled = !this.voiceEnabled;
888
+ toggleVoiceBtn.textContent = this.voiceEnabled ? "Disable Voice" : "Enable Voice";
889
+ });
890
+ }
891
+
892
+ // Update status text
893
+ updateStatus(message) {
894
+ const statusText = document.getElementById("statusText");
895
+ if (statusText) {
896
+ statusText.textContent = message;
897
+ }
898
+ }
899
+
900
+ clearChat(container) {
901
+ if (container) {
902
+ container.innerHTML = "";
903
+ }
904
+ }
905
+
906
+ addChatMessage(container, message, character, shyguyIsMain) {
907
+ if (!container) return;
908
+
909
+ const isMain = shyguyIsMain ? character === SHYGUY_LABEL : character !== SHYGUY_LABEL;
910
+
911
+ const messageDiv = document.createElement("div");
912
+ messageDiv.className = `chat-message ${isMain ? "right-user" : "left-user"}`;
913
+
914
+ const bubble = document.createElement("div");
915
+ bubble.className = "message-bubble";
916
+ bubble.textContent = message;
917
+
918
+ messageDiv.appendChild(bubble);
919
+ container.appendChild(messageDiv);
920
+
921
+ // Auto scroll to bottom
922
+ container.scrollTop = container.scrollHeight;
923
+ }
924
+
925
+ resolveAction(action) {
926
+ // TODO: resolve the action
927
+ switch (action) {
928
+ case "stay_idle":
929
+ this.setNewTarget(null);
930
+ break;
931
+ case "go_bar":
932
+ this.setNewTarget(this.targets.bar);
933
+ break;
934
+ case "go_dj":
935
+ this.setNewTarget(this.targets.dj);
936
+ break;
937
+ case "go_sister":
938
+ this.setNewTarget(this.targets.sister);
939
+ break;
940
+ case "go_girl":
941
+ this.setNewTarget(this.targets.girl);
942
+ break;
943
+ case "go_home":
944
+ this.setNewTarget(this.targets.exit);
945
+ break;
946
+ default:
947
+ break;
948
+ }
949
+ }
950
+
951
+ async sendMessageToShyguy(message) {
952
+ this.addChatMessage(this.gameChatContainer, message, WINGMAN_LABEL, false);
953
+ this.messageInput.value = "";
954
+
955
+ this.shyguyLLM.getShyGuyResponse(message).then(async (response) => {
956
+ const dialogue = response.dialogue;
957
+ const action = response.action;
958
+
959
+ this.addChatMessage(this.gameChatContainer, dialogue, SHYGUY_LABEL, false);
960
+
961
+ // Only play audio if voice is enabled
962
+ if (this.voiceEnabled) {
963
+ this.disableGameInput();
964
+ this.lowerMusicVolumeALot();
965
+ await this.elevenLabsClient.playAudioForCharacter(SHYGUY_LABEL, dialogue);
966
+ this.enableGameInput();
967
+ this.restoreMusicVolume();
968
+ }
969
+
970
+ // TODO: save conversation history
971
+ await this.shyguy.learnFromWingman(message);
972
+ console.log("[ShyguyLLM]: Next action: ", action);
973
+ this.resolveAction(action);
974
+ });
975
+ }
976
+
977
+ async handleSendMessage() {
978
+ const message = this.messageInput.value.trim();
979
+ if (message.length === 0) return;
980
+ this.sendMessageToShyguy(message);
981
+ }
982
+
983
+ async run() {
984
+ // wait for 16ms
985
+ await new Promise((resolve) => setTimeout(resolve, 16));
986
+ await this.update();
987
+ this.draw();
988
+ if (this.shouldContinue) {
989
+ requestAnimationFrame(this.run);
990
+ }
991
+ }
992
+
993
+ handlePlayAgain() {
994
+ this.clearChat(this.gameChatContainer);
995
+ this.resetGame();
996
+ this.switchView("game");
997
+ }
998
+
999
+ async handleMicrophone() {
1000
+ if (!this.isRecording) {
1001
+ // Start recording
1002
+ this.isRecording = true;
1003
+ this.microphoneButton.classList.add("recording");
1004
+ this.microphoneButton.innerHTML = '<i class="fas fa-stop"></i>';
1005
+
1006
+ // Lower music volume while recording
1007
+ this.lowerMusicVolumeALot();
1008
+ await this.speechToTextClient.startRecording();
1009
+ } else {
1010
+ // Stop recording
1011
+ this.isRecording = false;
1012
+ this.microphoneButton.classList.remove("recording");
1013
+ this.microphoneButton.innerHTML = '<i class="fas fa-microphone"></i>';
1014
+
1015
+ const result = await this.speechToTextClient.stopRecording();
1016
+ // Restore music volume after recording
1017
+ this.restoreMusicVolume();
1018
+ this.sendMessageToShyguy(result.text);
1019
+ }
1020
+ }
1021
+
1022
+ showContinueButton() {
1023
+ this.dialogueContinueButton.style.display = "block";
1024
+ }
1025
+
1026
+ hideContinueButton() {
1027
+ this.dialogueContinueButton.style.display = "none";
1028
+ }
1029
+
1030
+ setGameOver(fromExit) {
1031
+ this.stopBackgroundMusic();
1032
+
1033
+ if (this.gameSuccessful) {
1034
+ this.gameOverImage.src = "assets/assets/victory.png";
1035
+ this.playVictoryMusic();
1036
+ } else {
1037
+ this.gameOverImage.src = "assets/assets/game-over.png";
1038
+ this.playGameOverMusic();
1039
+ }
1040
+
1041
+ if (fromExit) {
1042
+ this.gameOverText.textContent = "You lost! Shyguy ran away!";
1043
+ return;
1044
+ }
1045
+
1046
+ this.gameOverText.textContent = this.gameSuccessful
1047
+ ? "You won! Shyguy got a date!"
1048
+ : "You lost! Shyguy got rejected!";
1049
+ }
1050
+
1051
+ handleDialogueContinue() {
1052
+ this.clearChat(this.dialogueChatContainer);
1053
+
1054
+ // Hide character images
1055
+ const leftCharacterImg = document.getElementById("leftCharacterImg");
1056
+ const rightCharacterImg = document.getElementById("rightCharacterImg");
1057
+
1058
+ if (leftCharacterImg) {
1059
+ leftCharacterImg.style.display = "none";
1060
+ }
1061
+ if (rightCharacterImg) {
1062
+ rightCharacterImg.style.display = "none";
1063
+ }
1064
+
1065
+ // decide if game is over
1066
+ if (this.gameOver) {
1067
+ this.setGameOver(false);
1068
+ this.switchView("gameOver");
1069
+ return;
1070
+ }
1071
+
1072
+ // Enable push if shyguy has had at least one beer
1073
+ if (this.shyguy.num_beers > 0) {
1074
+ this.enablePush();
1075
+ }
1076
+
1077
+ this.switchView("game");
1078
+ this.shyguyLLM.getShyGuyResponse("").then((response) => {
1079
+ const next_action = response.action;
1080
+
1081
+ this.resolveAction(next_action);
1082
+ });
1083
+ }
1084
+
1085
+ disableGameInput() {
1086
+ this.sendButton.setAttribute("disabled", "");
1087
+ this.microphoneButton.setAttribute("disabled", "");
1088
+ this.messageInput.setAttribute("disabled", "");
1089
+ }
1090
+
1091
+ enableGameInput() {
1092
+ this.sendButton.removeAttribute("disabled");
1093
+ this.microphoneButton.removeAttribute("disabled");
1094
+ this.messageInput.removeAttribute("disabled");
1095
+ }
1096
+
1097
+ playBackgroundMusic() {
1098
+ this.backgroundMusic.play().catch((error) => {
1099
+ console.error("Error playing background music:", error);
1100
+ });
1101
+ }
1102
+
1103
+ stopBackgroundMusic() {
1104
+ this.backgroundMusic.pause();
1105
+ this.backgroundMusic.currentTime = 0;
1106
+ }
1107
+
1108
+ playGameOverMusic() {
1109
+ this.gameOverMusic.play().catch((error) => {
1110
+ console.error("Error playing game over music:", error);
1111
+ });
1112
+ }
1113
+
1114
+ playVictoryMusic() {
1115
+ this.victoryMusic.play().catch((error) => {
1116
+ console.error("Error playing victory music:", error);
1117
+ });
1118
+ }
1119
+
1120
+ stopAllMusic() {
1121
+ this.stopBackgroundMusic();
1122
+ this.gameOverMusic.pause();
1123
+ this.gameOverMusic.currentTime = 0;
1124
+ this.victoryMusic.pause();
1125
+ this.victoryMusic.currentTime = 0;
1126
+ }
1127
+
1128
+ lowerMusicVolume() {
1129
+ // Store original volumes if not already stored
1130
+ if (!this.originalVolumes) {
1131
+ this.originalVolumes = {
1132
+ background: this.backgroundMusic.volume,
1133
+ gameOver: this.gameOverMusic.volume,
1134
+ victory: this.victoryMusic.volume,
1135
+ };
1136
+ }
1137
+
1138
+ // Lower all music volumes to 20% of their original values
1139
+ this.backgroundMusic.volume = this.originalVolumes.background * 0.2;
1140
+ this.gameOverMusic.volume = this.originalVolumes.gameOver * 0.2;
1141
+ this.victoryMusic.volume = this.originalVolumes.victory * 0.2;
1142
+ }
1143
+ lowerMusicVolumeALot() {
1144
+ // Store original volumes if not already stored
1145
+ if (!this.originalVolumes) {
1146
+ this.originalVolumes = {
1147
+ background: this.backgroundMusic.volume,
1148
+ gameOver: this.gameOverMusic.volume,
1149
+ victory: this.victoryMusic.volume,
1150
+ };
1151
+ }
1152
+
1153
+ // Lower all music volumes to 20% of their original values
1154
+ this.backgroundMusic.volume = this.originalVolumes.background * 0.01;
1155
+ this.gameOverMusic.volume = this.originalVolumes.gameOver * 0.01;
1156
+ this.victoryMusic.volume = this.originalVolumes.victory * 0.01;
1157
+ }
1158
+
1159
+ restoreMusicVolume() {
1160
+ // Restore original volumes if they exist
1161
+ if (this.originalVolumes) {
1162
+ this.backgroundMusic.volume = this.originalVolumes.background * 0.2;
1163
+ this.gameOverMusic.volume = this.originalVolumes.gameOver * 0.2;
1164
+ this.victoryMusic.volume = this.originalVolumes.victory * 0.2;
1165
+ }
1166
+ }
1167
+ }