Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions deep-sea-stories/packages/backend/src/agent/gemini/session.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
Behavior,
type GoogleGenAI,
type LiveConnectParameters,
type LiveServerMessage,
Expand Down Expand Up @@ -98,23 +99,18 @@ export class GeminiSession implements VoiceAgentSession {
systemInstruction: getInstructionsForStory(this.config.story),
outputAudioTranscription: {},
temperature: 0.5,
thinkingConfig: {
thinkingBudget: -1,
},
tools: [
{
functionDeclarations: [
{
behavior: Behavior.BLOCKING,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question:
whats blocking behavior?
Imagewhen you try to duck duck go your way to an answer

@Tay0108 Tay0108 Sep 18, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When Gemini calls endGame, generation pauses until our backend returns the tool result. Gemini 3.8 defaults to non-blocking tool calls, so setting this explicitly preserves the previous behavior and prevents the agent from continuing while the game is closing.

from docs on migrating from 3.1:

Asynchronous function calling: Async execution (behavior: NON_BLOCKING) is now the default function calling mode. You can still use synchronous blocking mode for backwards compatibility by setting behavior: BLOCKING on your tool declarations. Function scheduling (SILENT, WHEN_IDLE, INTERRUPTED) is supported.

https://ai.google.dev/gemini-api/docs/models/gemini-3.8-live

name: 'endGame',
description:
'Call this function to end the game session. You MUST call this when: 1) The players have correctly solved the riddle, 2) The game time has expired, 3) You are saying goodbye or ending the conversation. Always call this function after delivering your final message to players.',
},
],
},
],
proactivity: {
proactiveAudio: true,
},
sessionResumption: { handle: this.previousHandle },
},
callbacks: {
Expand Down
2 changes: 1 addition & 1 deletion deep-sea-stories/packages/backend/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const configSchema = z.object({
GOOGLE_CLOUD_LOCATION: z.string().optional(),
});

export const GEMINI_MODEL = 'gemini-2.5-flash-native-audio-preview-12-2025';
export const GEMINI_MODEL = 'gemini-3.8-live';

export const stories: Story[] = JSON.parse(
fs.readFileSync(join(__dirname, 'prompts', 'stories.json'), 'utf8'),
Expand Down
1 change: 0 additions & 1 deletion deep-sea-stories/packages/backend/src/game/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ export class GameRoom {
vertexai: CONFIG.GOOGLE_GENAI_USE_VERTEXAI,
project: CONFIG.GOOGLE_CLOUD_PROJECT,
location: CONFIG.GOOGLE_CLOUD_LOCATION,
httpOptions: { apiVersion: 'v1alpha' },
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { X } from 'lucide-react';
import { type PropsWithChildren, useState } from 'react';

export function AnnouncementBanner({ children }: PropsWithChildren) {
const [isVisible, setIsVisible] = useState(true);

if (!isVisible) return null;

return (
<aside className="fixed inset-x-0 top-0 z-50 bg-linear-to-r from-[#4285f4] via-[#8e75ff] to-[#d96570] text-white shadow-lg">
<div className="relative flex min-h-10 items-center justify-center px-12 py-2 text-center text-sm">
<div>{children}</div>
<button
type="button"
onClick={() => setIsVisible(false)}
className="absolute right-3 rounded-full p-1 text-white/80 transition-colors hover:bg-white/15 hover:text-white"
aria-label="Dismiss announcement"
>
<X className="size-4" aria-hidden="true" />
</button>
</div>
</aside>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const GameControlPanel: FC<GameControlPanelProps> = ({
onVolumeChange={onVolumeChange}
/>
</div>
<div className="flex-none md:flex-none md:w-1/4 border rounded-3xl p-2 md:p-3 lg:p-4 overflow-hidden">
<div className="flex-none md:flex-none md:w-1/4 min-h-0 border rounded-3xl p-2 md:p-3 lg:p-4 overflow-hidden">
<RoomControls roomId={roomId} userName={userName} />
</div>
</section>
Expand Down
17 changes: 8 additions & 9 deletions deep-sea-stories/packages/web/src/components/RoomControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ const RoomControls: FC<RoomControlsProps> = ({ roomId, userName }) => {
};

return (
<div className="flex flex-col h-full py-2 md:py-2 lg:py-3 gap-2 md:gap-2 lg:gap-3">
<div className="flex h-full flex-col py-2 md:py-1 lg:py-2 gap-2">
<DeepSeaLogo className="hidden md:block flex-none" />
<section className="w-full flex-none grid grid-cols-2 md:flex md:flex-col gap-2">
{!isStorySelected ? (
<Button
size="large"
className="col-span-2 md:w-full text-xs md:text-base h-9 md:h-11 lg:h-12"
className="col-span-2 md:w-full text-xs md:text-sm lg:text-base h-9 md:h-9 lg:h-10"
onClick={() => setIsStoryPanelOpen(true)}
>
Choose a story
Expand All @@ -85,7 +85,7 @@ const RoomControls: FC<RoomControlsProps> = ({ roomId, userName }) => {
<Button
size="large"
variant="outline"
className="col-span-2 md:w-full text-xs md:text-base h-9 md:h-11 lg:h-12"
className="col-span-2 md:w-full text-xs md:text-sm lg:text-base h-9 md:h-9 lg:h-10"
onClick={handleCancelGame}
disabled={isCanceling}
>
Expand All @@ -94,14 +94,14 @@ const RoomControls: FC<RoomControlsProps> = ({ roomId, userName }) => {
) : (
<>
<Button
className="col-span-2 md:w-full text-xs md:text-base h-9 md:h-10 lg:h-11"
className="col-span-2 md:w-full text-xs md:text-sm lg:text-base h-9 lg:h-10"
onClick={handleStartGame}
disabled={isStarting}
>
{isStarting ? 'Starting...' : 'Start the Game'}
</Button>
<Button
className="col-span-2 md:w-full text-xs md:text-base h-9 md:h-10 lg:h-11"
className="col-span-2 md:w-full text-xs md:text-sm lg:text-base h-9 lg:h-10"
variant="outline"
onClick={() => setIsStoryPanelOpen(true)}
>
Expand All @@ -110,14 +110,13 @@ const RoomControls: FC<RoomControlsProps> = ({ roomId, userName }) => {
</>
)}
</section>
<div className="flex-1 min-h-0" />
<section className="w-full flex-none flex flex-col gap-2">
<HowToPlay className="w-full text-xs md:text-base h-9 md:h-10 lg:h-11" />
<HowItWorks className="w-full text-xs md:text-base h-9 md:h-10 lg:h-11" />
<HowToPlay className="w-full text-xs md:text-sm lg:text-base h-9 lg:h-10" />
<HowItWorks className="w-full text-xs md:text-sm lg:text-base h-9 lg:h-10" />

<CopyButton
variant="outline"
className="col-span-2 md:col-span-1 text-xs md:text-base h-9 md:h-10 lg:h-11"
className="col-span-2 md:col-span-1 text-xs md:text-sm lg:text-base h-9 lg:h-10"
onCopy={() => toast('Gameroom link copied to clipboard', Check)}
value={url}
>
Expand Down
13 changes: 13 additions & 0 deletions deep-sea-stories/packages/web/src/views/HomeView.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useState } from 'react';
import { useNavigate } from 'react-router';
import { AnnouncementBanner } from '@/components/AnnouncementBanner';
import Footer from '@/components/Footer';
import TitleBar from '@/components/TitleBar';
import { Button } from '@/components/ui/button';
Expand Down Expand Up @@ -27,6 +28,18 @@ export default function HomeView() {

return (
<section className="h-full w-full flex justify-between flex-col py-16 px-4 lg:px-16">
<AnnouncementBanner>
Deep Sea Stories is now powered by{' '}
<a
href="https://ai.google.dev/gemini-api/docs/models/gemini-3.8-live"
target="_blank"
rel="noreferrer"
className="font-semibold underline decoration-white/70 underline-offset-2 transition-colors hover:decoration-white"
>
Gemini 3.8 Live
</a>
.
</AnnouncementBanner>
<TitleBar />
<section className="flex-1 py-16 grid place-items-center">
<Button
Expand Down
Loading