better battle
Browse files
src/lib/components/Battle/BattleField.svelte
CHANGED
@@ -22,25 +22,43 @@
|
|
22 |
export let enemyFaint: boolean = false;
|
23 |
export let playerLunge: boolean = false;
|
24 |
export let enemyLunge: boolean = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
|
26 |
// Animation states
|
27 |
let playerVisible = false;
|
28 |
let enemyVisible = false;
|
29 |
let trainerVisible = true;
|
30 |
|
|
|
|
|
|
|
|
|
31 |
// Calculate player XP percentage (0-100% of current level)
|
32 |
const playerXpPercentage = (playerPiclet.xp / 100) * 100; // Simplified, should use actual XP curve
|
33 |
|
34 |
onMount(() => {
|
35 |
if (showIntro) {
|
36 |
-
// Intro animation sequence
|
37 |
setTimeout(() => {
|
38 |
trainerVisible = false;
|
39 |
-
|
|
|
|
|
|
|
|
|
40 |
}, 500);
|
41 |
|
42 |
setTimeout(() => {
|
43 |
-
|
|
|
|
|
|
|
|
|
44 |
}, 1000);
|
45 |
} else {
|
46 |
// Skip intro
|
@@ -49,9 +67,41 @@
|
|
49 |
trainerVisible = false;
|
50 |
}
|
51 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
</script>
|
53 |
|
54 |
<div class="battle-field">
|
|
|
|
|
|
|
|
|
|
|
55 |
<!-- Trainer intro image -->
|
56 |
{#if showIntro && trainerVisible}
|
57 |
<div class="trainer-intro" transition:fade={{ duration: 300 }}>
|
@@ -59,6 +109,20 @@
|
|
59 |
</div>
|
60 |
{/if}
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
<div class="battle-content">
|
63 |
<!-- Field Effects Display -->
|
64 |
{#if battleState?.fieldEffects}
|
@@ -181,6 +245,16 @@
|
|
181 |
);
|
182 |
}
|
183 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
.trainer-intro {
|
185 |
position: absolute;
|
186 |
top: 50%;
|
@@ -195,6 +269,41 @@
|
|
195 |
animation: trainerPulse 0.5s ease-in-out;
|
196 |
}
|
197 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
@keyframes trainerPulse {
|
199 |
0% {
|
200 |
transform: scale(1);
|
|
|
22 |
export let enemyFaint: boolean = false;
|
23 |
export let playerLunge: boolean = false;
|
24 |
export let enemyLunge: boolean = false;
|
25 |
+
export let isWildBattle: boolean = true;
|
26 |
+
export let showWhiteFlash: boolean = false;
|
27 |
+
export let playerTrainerVisible: boolean = false;
|
28 |
+
export let enemyTrainerVisible: boolean = false;
|
29 |
+
export let playerTrainerSlideOut: boolean = false;
|
30 |
+
export let enemyTrainerSlideOut: boolean = false;
|
31 |
|
32 |
// Animation states
|
33 |
let playerVisible = false;
|
34 |
let enemyVisible = false;
|
35 |
let trainerVisible = true;
|
36 |
|
37 |
+
// Trainer animation states
|
38 |
+
let playerTrainerSliding = false;
|
39 |
+
let enemyTrainerSliding = false;
|
40 |
+
|
41 |
// Calculate player XP percentage (0-100% of current level)
|
42 |
const playerXpPercentage = (playerPiclet.xp / 100) * 100; // Simplified, should use actual XP curve
|
43 |
|
44 |
onMount(() => {
|
45 |
if (showIntro) {
|
46 |
+
// Intro animation sequence - show trainers first
|
47 |
setTimeout(() => {
|
48 |
trainerVisible = false;
|
49 |
+
if (!isWildBattle) {
|
50 |
+
enemyTrainerVisible = true;
|
51 |
+
} else {
|
52 |
+
enemyVisible = true;
|
53 |
+
}
|
54 |
}, 500);
|
55 |
|
56 |
setTimeout(() => {
|
57 |
+
if (!isWildBattle) {
|
58 |
+
playerTrainerVisible = true;
|
59 |
+
} else {
|
60 |
+
playerTrainerVisible = true; // Show player trainer even in wild battles
|
61 |
+
}
|
62 |
}, 1000);
|
63 |
} else {
|
64 |
// Skip intro
|
|
|
67 |
trainerVisible = false;
|
68 |
}
|
69 |
});
|
70 |
+
|
71 |
+
// Watch for trainer slide-out triggers
|
72 |
+
$: if (playerTrainerSlideOut && !playerTrainerSliding) {
|
73 |
+
playerTrainerSliding = true;
|
74 |
+
setTimeout(() => {
|
75 |
+
playerTrainerVisible = false;
|
76 |
+
// Trigger white flash then show player monster
|
77 |
+
showWhiteFlash = true;
|
78 |
+
setTimeout(() => {
|
79 |
+
showWhiteFlash = false;
|
80 |
+
playerVisible = true;
|
81 |
+
}, 300);
|
82 |
+
}, 600); // Time for slide-out animation
|
83 |
+
}
|
84 |
+
|
85 |
+
$: if (enemyTrainerSlideOut && !enemyTrainerSliding) {
|
86 |
+
enemyTrainerSliding = true;
|
87 |
+
setTimeout(() => {
|
88 |
+
enemyTrainerVisible = false;
|
89 |
+
// Trigger white flash then show enemy monster
|
90 |
+
showWhiteFlash = true;
|
91 |
+
setTimeout(() => {
|
92 |
+
showWhiteFlash = false;
|
93 |
+
enemyVisible = true;
|
94 |
+
}, 300);
|
95 |
+
}, 600); // Time for slide-out animation
|
96 |
+
}
|
97 |
</script>
|
98 |
|
99 |
<div class="battle-field">
|
100 |
+
<!-- White flash overlay -->
|
101 |
+
{#if showWhiteFlash}
|
102 |
+
<div class="white-flash" transition:fade={{ duration: 300 }}></div>
|
103 |
+
{/if}
|
104 |
+
|
105 |
<!-- Trainer intro image -->
|
106 |
{#if showIntro && trainerVisible}
|
107 |
<div class="trainer-intro" transition:fade={{ duration: 300 }}>
|
|
|
109 |
</div>
|
110 |
{/if}
|
111 |
|
112 |
+
<!-- Player Trainer -->
|
113 |
+
{#if playerTrainerVisible}
|
114 |
+
<div class="player-trainer" class:slide-out-left={playerTrainerSlideOut} transition:fade={{ duration: 300 }}>
|
115 |
+
<img src="/assets/default_trainer.png" alt="Player Trainer" />
|
116 |
+
</div>
|
117 |
+
{/if}
|
118 |
+
|
119 |
+
<!-- Enemy Trainer (only for trainer battles) -->
|
120 |
+
{#if !isWildBattle && enemyTrainerVisible}
|
121 |
+
<div class="enemy-trainer" class:slide-out-right={enemyTrainerSlideOut} transition:fade={{ duration: 300 }}>
|
122 |
+
<img src="/assets/default_trainer.png" alt="Enemy Trainer" />
|
123 |
+
</div>
|
124 |
+
{/if}
|
125 |
+
|
126 |
<div class="battle-content">
|
127 |
<!-- Field Effects Display -->
|
128 |
{#if battleState?.fieldEffects}
|
|
|
245 |
);
|
246 |
}
|
247 |
|
248 |
+
.white-flash {
|
249 |
+
position: fixed;
|
250 |
+
top: 0;
|
251 |
+
left: 0;
|
252 |
+
right: 0;
|
253 |
+
bottom: 0;
|
254 |
+
background: white;
|
255 |
+
z-index: 50;
|
256 |
+
}
|
257 |
+
|
258 |
.trainer-intro {
|
259 |
position: absolute;
|
260 |
top: 50%;
|
|
|
269 |
animation: trainerPulse 0.5s ease-in-out;
|
270 |
}
|
271 |
|
272 |
+
.player-trainer {
|
273 |
+
position: absolute;
|
274 |
+
bottom: 20px;
|
275 |
+
left: 20px;
|
276 |
+
z-index: 10;
|
277 |
+
transition: transform 0.6s ease-in-out;
|
278 |
+
}
|
279 |
+
|
280 |
+
.player-trainer img {
|
281 |
+
width: 120px;
|
282 |
+
height: auto;
|
283 |
+
transform: scaleX(-1); /* Face right */
|
284 |
+
}
|
285 |
+
|
286 |
+
.player-trainer.slide-out-left {
|
287 |
+
transform: translateX(-200px);
|
288 |
+
}
|
289 |
+
|
290 |
+
.enemy-trainer {
|
291 |
+
position: absolute;
|
292 |
+
top: 20px;
|
293 |
+
right: 20px;
|
294 |
+
z-index: 10;
|
295 |
+
transition: transform 0.6s ease-in-out;
|
296 |
+
}
|
297 |
+
|
298 |
+
.enemy-trainer img {
|
299 |
+
width: 120px;
|
300 |
+
height: auto;
|
301 |
+
}
|
302 |
+
|
303 |
+
.enemy-trainer.slide-out-right {
|
304 |
+
transform: translateX(200px);
|
305 |
+
}
|
306 |
+
|
307 |
@keyframes trainerPulse {
|
308 |
0% {
|
309 |
transform: scale(1);
|
src/lib/components/Pages/Battle.svelte
CHANGED
@@ -31,6 +31,13 @@
|
|
31 |
let processingTurn = false;
|
32 |
let battleEnded = false;
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
// HP animation states
|
35 |
let playerHpPercentage = playerPiclet.currentHp / playerPiclet.maxHp;
|
36 |
let enemyHpPercentage = enemyPiclet.currentHp / enemyPiclet.maxHp;
|
@@ -81,11 +88,27 @@
|
|
81 |
|
82 |
// Start intro sequence
|
83 |
setTimeout(() => {
|
84 |
-
|
85 |
-
|
86 |
-
currentMessage = `
|
87 |
-
|
88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
}, 2000);
|
90 |
});
|
91 |
|
@@ -185,13 +208,13 @@
|
|
185 |
// Update UI state from battle engine
|
186 |
updateUIFromBattleState();
|
187 |
|
188 |
-
// Check for battle end
|
189 |
if (battleState.winner) {
|
190 |
battleEnded = true;
|
191 |
-
const
|
192 |
-
|
193 |
-
|
194 |
-
currentMessage =
|
195 |
|
196 |
// Trigger faint animation for the defeated Piclet
|
197 |
if (battleState.winner === 'player') {
|
@@ -200,10 +223,18 @@
|
|
200 |
playerFaint = true;
|
201 |
}
|
202 |
|
203 |
-
//
|
204 |
-
setTimeout(
|
205 |
-
|
206 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
207 |
} else {
|
208 |
setTimeout(() => {
|
209 |
currentMessage = `What will ${currentPlayerPiclet.nickname} do?`;
|
@@ -303,14 +334,8 @@
|
|
303 |
triggerEffect('both', 'miss', '💫', 800);
|
304 |
}
|
305 |
|
306 |
-
// Faint effects
|
307 |
-
|
308 |
-
if (message.includes(playerInternalName)) {
|
309 |
-
triggerFaintAnimation('player');
|
310 |
-
} else if (message.includes(enemyInternalName)) {
|
311 |
-
triggerFaintAnimation('enemy');
|
312 |
-
}
|
313 |
-
}
|
314 |
}
|
315 |
|
316 |
function triggerDamageFlash(target: 'player' | 'enemy') {
|
@@ -387,10 +412,16 @@
|
|
387 |
return;
|
388 |
}
|
389 |
|
390 |
-
//
|
391 |
-
currentPlayerPiclet = piclet;
|
392 |
-
playerHpPercentage = piclet.currentHp / piclet.maxHp;
|
393 |
currentMessage = `Go, ${piclet.nickname}!`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
394 |
|
395 |
const switchAction: SwitchAction = {
|
396 |
type: 'switch',
|
@@ -467,13 +498,13 @@
|
|
467 |
// Update UI state from battle engine
|
468 |
updateUIFromBattleState();
|
469 |
|
470 |
-
// Check for battle end
|
471 |
if (battleState.winner) {
|
472 |
battleEnded = true;
|
473 |
-
const
|
474 |
-
|
475 |
-
|
476 |
-
currentMessage =
|
477 |
|
478 |
// Trigger faint animation for the defeated Piclet
|
479 |
if (battleState.winner === 'player') {
|
@@ -482,10 +513,18 @@
|
|
482 |
playerFaint = true;
|
483 |
}
|
484 |
|
485 |
-
//
|
486 |
-
setTimeout(
|
487 |
-
|
488 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
489 |
} else {
|
490 |
setTimeout(() => {
|
491 |
currentMessage = `What will ${currentPlayerPiclet.nickname} do?`;
|
@@ -586,6 +625,12 @@
|
|
586 |
{enemyFaint}
|
587 |
{playerLunge}
|
588 |
{enemyLunge}
|
|
|
|
|
|
|
|
|
|
|
|
|
589 |
/>
|
590 |
|
591 |
<BattleControls
|
|
|
31 |
let processingTurn = false;
|
32 |
let battleEnded = false;
|
33 |
|
34 |
+
// Trainer animation states
|
35 |
+
let showWhiteFlash = false;
|
36 |
+
let playerTrainerVisible = false;
|
37 |
+
let enemyTrainerVisible = false;
|
38 |
+
let playerTrainerSlideOut = false;
|
39 |
+
let enemyTrainerSlideOut = false;
|
40 |
+
|
41 |
// HP animation states
|
42 |
let playerHpPercentage = playerPiclet.currentHp / playerPiclet.maxHp;
|
43 |
let enemyHpPercentage = enemyPiclet.currentHp / enemyPiclet.maxHp;
|
|
|
88 |
|
89 |
// Start intro sequence
|
90 |
setTimeout(() => {
|
91 |
+
if (!isWildBattle) {
|
92 |
+
// Enemy trainer sends out first
|
93 |
+
currentMessage = `Go, ${enemyPiclet.nickname}!`;
|
94 |
+
enemyTrainerSlideOut = true;
|
95 |
+
setTimeout(() => {
|
96 |
+
currentMessage = `Go, ${playerPiclet.nickname}!`;
|
97 |
+
playerTrainerSlideOut = true;
|
98 |
+
setTimeout(() => {
|
99 |
+
currentMessage = `What will ${playerPiclet.nickname} do?`;
|
100 |
+
battlePhase = 'main';
|
101 |
+
}, 2000); // Wait for trainer slide + flash + monster appear
|
102 |
+
}, 2000); // Wait for enemy trainer sequence
|
103 |
+
} else {
|
104 |
+
// Wild battle - player sends out
|
105 |
+
currentMessage = `Go, ${playerPiclet.nickname}!`;
|
106 |
+
playerTrainerSlideOut = true;
|
107 |
+
setTimeout(() => {
|
108 |
+
currentMessage = `What will ${playerPiclet.nickname} do?`;
|
109 |
+
battlePhase = 'main';
|
110 |
+
}, 2000); // Wait for trainer slide + flash + monster appear
|
111 |
+
}
|
112 |
}, 2000);
|
113 |
});
|
114 |
|
|
|
208 |
// Update UI state from battle engine
|
209 |
updateUIFromBattleState();
|
210 |
|
211 |
+
// Check for battle end - but handle faint message sequence properly
|
212 |
if (battleState.winner) {
|
213 |
battleEnded = true;
|
214 |
+
const defeatedPiclet = battleState.winner === 'player' ? currentEnemyPiclet : currentPlayerPiclet;
|
215 |
+
|
216 |
+
// First show the faint message and trigger animation
|
217 |
+
currentMessage = `${defeatedPiclet.nickname} fainted!`;
|
218 |
|
219 |
// Trigger faint animation for the defeated Piclet
|
220 |
if (battleState.winner === 'player') {
|
|
|
223 |
playerFaint = true;
|
224 |
}
|
225 |
|
226 |
+
// Wait for faint animation, then show win/loss message
|
227 |
+
setTimeout(() => {
|
228 |
+
const winMessage = battleState.winner === 'player'
|
229 |
+
? 'You won!'
|
230 |
+
: 'You lost!';
|
231 |
+
currentMessage = winMessage;
|
232 |
+
|
233 |
+
// Process battle results with XP and level ups
|
234 |
+
setTimeout(async () => {
|
235 |
+
await handleBattleResults(battleState.winner === 'player');
|
236 |
+
}, 1500);
|
237 |
+
}, 2000); // Wait for faint animation
|
238 |
} else {
|
239 |
setTimeout(() => {
|
240 |
currentMessage = `What will ${currentPlayerPiclet.nickname} do?`;
|
|
|
334 |
triggerEffect('both', 'miss', '💫', 800);
|
335 |
}
|
336 |
|
337 |
+
// Faint effects - only trigger when we see the faint message from battle log
|
338 |
+
// Don't trigger here since we handle it in finalizeTurn for proper sequencing
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
}
|
340 |
|
341 |
function triggerDamageFlash(target: 'player' | 'enemy') {
|
|
|
412 |
return;
|
413 |
}
|
414 |
|
415 |
+
// Show the switch message and trigger white flash animation
|
|
|
|
|
416 |
currentMessage = `Go, ${piclet.nickname}!`;
|
417 |
+
showWhiteFlash = true;
|
418 |
+
|
419 |
+
// After flash, update display
|
420 |
+
setTimeout(() => {
|
421 |
+
currentPlayerPiclet = piclet;
|
422 |
+
playerHpPercentage = piclet.currentHp / piclet.maxHp;
|
423 |
+
showWhiteFlash = false;
|
424 |
+
}, 300);
|
425 |
|
426 |
const switchAction: SwitchAction = {
|
427 |
type: 'switch',
|
|
|
498 |
// Update UI state from battle engine
|
499 |
updateUIFromBattleState();
|
500 |
|
501 |
+
// Check for battle end - but handle faint message sequence properly
|
502 |
if (battleState.winner) {
|
503 |
battleEnded = true;
|
504 |
+
const defeatedPiclet = battleState.winner === 'player' ? currentEnemyPiclet : currentPlayerPiclet;
|
505 |
+
|
506 |
+
// First show the faint message and trigger animation
|
507 |
+
currentMessage = `${defeatedPiclet.nickname} fainted!`;
|
508 |
|
509 |
// Trigger faint animation for the defeated Piclet
|
510 |
if (battleState.winner === 'player') {
|
|
|
513 |
playerFaint = true;
|
514 |
}
|
515 |
|
516 |
+
// Wait for faint animation, then show win/loss message
|
517 |
+
setTimeout(() => {
|
518 |
+
const winMessage = battleState.winner === 'player'
|
519 |
+
? 'You won!'
|
520 |
+
: 'You lost!';
|
521 |
+
currentMessage = winMessage;
|
522 |
+
|
523 |
+
// Process battle results with XP and level ups
|
524 |
+
setTimeout(async () => {
|
525 |
+
await handleBattleResults(battleState.winner === 'player');
|
526 |
+
}, 1500);
|
527 |
+
}, 2000); // Wait for faint animation
|
528 |
} else {
|
529 |
setTimeout(() => {
|
530 |
currentMessage = `What will ${currentPlayerPiclet.nickname} do?`;
|
|
|
625 |
{enemyFaint}
|
626 |
{playerLunge}
|
627 |
{enemyLunge}
|
628 |
+
{isWildBattle}
|
629 |
+
{showWhiteFlash}
|
630 |
+
{playerTrainerVisible}
|
631 |
+
{enemyTrainerVisible}
|
632 |
+
{playerTrainerSlideOut}
|
633 |
+
{enemyTrainerSlideOut}
|
634 |
/>
|
635 |
|
636 |
<BattleControls
|
src/lib/components/PicletGenerator/PicletGenerator.svelte
CHANGED
@@ -215,11 +215,11 @@ Format your response exactly as follows:
|
|
215 |
"conversation_id": "",
|
216 |
};
|
217 |
|
218 |
-
// Create default settings based on qwen.html with
|
219 |
const defaultSettings = {
|
220 |
"model": "qwen3-235b-a22b",
|
221 |
"sys_prompt": "You are a creative monster designer specializing in transforming everyday objects into imaginative Pokémon-style creatures. Follow the exact format provided and create detailed, engaging descriptions that bring these monsters to life.",
|
222 |
-
"thinking_budget":
|
223 |
};
|
224 |
|
225 |
// Create thinking button state
|
@@ -312,11 +312,11 @@ Create a concise visual description (1-3 sentences, max 100 words). Focus only o
|
|
312 |
"conversation_id": "",
|
313 |
};
|
314 |
|
315 |
-
// Create default settings based on qwen.html
|
316 |
const defaultSettings = {
|
317 |
"model": "qwen3-235b-a22b",
|
318 |
"sys_prompt": "You are an expert at creating concise visual descriptions for image generation. Extract ONLY visual appearance details and describe them in 1-2 sentences (max 50 words). Focus on colors, shape, eyes, limbs, and distinctive features. Omit all non-visual information like abilities, personality, or backstory.",
|
319 |
-
"thinking_budget":
|
320 |
};
|
321 |
|
322 |
// Create thinking button state
|
@@ -676,11 +676,11 @@ Write your response within \`\`\`json\`\`\``;
|
|
676 |
"conversation_id": "",
|
677 |
};
|
678 |
|
679 |
-
// Create default settings based on qwen.html
|
680 |
const defaultSettings = {
|
681 |
"model": "qwen3-235b-a22b",
|
682 |
"sys_prompt": "You are a game designer specializing in monster stats and abilities. You must ONLY output valid JSON that matches the provided schema exactly. Do not include any text before or after the JSON. Do not include null values in your JSON response. Your entire response should be wrapped in a ```json``` code block.",
|
683 |
-
"thinking_budget":
|
684 |
};
|
685 |
|
686 |
// Create thinking button state
|
|
|
215 |
"conversation_id": "",
|
216 |
};
|
217 |
|
218 |
+
// Create default settings based on qwen.html with minimal thinking tokens
|
219 |
const defaultSettings = {
|
220 |
"model": "qwen3-235b-a22b",
|
221 |
"sys_prompt": "You are a creative monster designer specializing in transforming everyday objects into imaginative Pokémon-style creatures. Follow the exact format provided and create detailed, engaging descriptions that bring these monsters to life.",
|
222 |
+
"thinking_budget": 3
|
223 |
};
|
224 |
|
225 |
// Create thinking button state
|
|
|
312 |
"conversation_id": "",
|
313 |
};
|
314 |
|
315 |
+
// Create default settings based on qwen.html with minimal thinking tokens
|
316 |
const defaultSettings = {
|
317 |
"model": "qwen3-235b-a22b",
|
318 |
"sys_prompt": "You are an expert at creating concise visual descriptions for image generation. Extract ONLY visual appearance details and describe them in 1-2 sentences (max 50 words). Focus on colors, shape, eyes, limbs, and distinctive features. Omit all non-visual information like abilities, personality, or backstory.",
|
319 |
+
"thinking_budget": 3
|
320 |
};
|
321 |
|
322 |
// Create thinking button state
|
|
|
676 |
"conversation_id": "",
|
677 |
};
|
678 |
|
679 |
+
// Create default settings based on qwen.html with minimal thinking tokens
|
680 |
const defaultSettings = {
|
681 |
"model": "qwen3-235b-a22b",
|
682 |
"sys_prompt": "You are a game designer specializing in monster stats and abilities. You must ONLY output valid JSON that matches the provided schema exactly. Do not include any text before or after the JSON. Do not include null values in your JSON response. Your entire response should be wrapped in a ```json``` code block.",
|
683 |
+
"thinking_budget": 3
|
684 |
};
|
685 |
|
686 |
// Create thinking button state
|