Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
4 changes: 2 additions & 2 deletions .github/workflows/deep-sea-stories-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Deploy deep-sea-stories

on:
push:
branches: ["main"]
branches: ["main", "2161"]

jobs:
deploy:
Expand All @@ -17,7 +17,7 @@ jobs:
key: ${{ secrets.VM_SSH_KEY }}
script: |
cd ~/examples/deep-sea-stories
git switch main
git switch 2161
git pull

umask 077
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Black Stories is a storytelling and guessing game designed to challenge players'

Gameplay:

The riddle master reads the initial scenario or mystery to the guessers.
The riddle master waits for questions from the guessers. Assume that all participants already understand the full story and game rules—no further explanations are needed.

The guessers ask the riddle master questions that can only be answered with "yes" or "no".

Expand Down
46 changes: 26 additions & 20 deletions deep-sea-stories/packages/backend/src/service/elevenlabs-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
import { roomService } from './room.js';
import { getInstructionsForStory } from '../utils.js';
import { AGENT_CLIENT_TOOL_INSTRUCTIONS, CONFIG } from '../config.js';
import type { VoiceAgentSessionManager } from '../types.js';
import type { Story, VoiceAgentSessionManager } from '../types.js';
import {
GameSessionNotFoundError,
StoryNotFoundError,
Expand Down Expand Up @@ -63,24 +63,8 @@ export class ElevenLabsSessionManager implements VoiceAgentSessionManager {
const toolId = await this.ensureGameEndingTool();

const story = await this.resolveStory(roomId);
const instructions = getInstructionsForStory(story);

const { agentId } = await elevenLabs.conversationalAi.agents.create({
conversationConfig: {
agent: {
firstMessage: 'Welcome to Deepsea stories',
language: 'en',
prompt: toolId
? {
prompt: instructions,
toolIds: [toolId],
}
: {
prompt: instructions,
},
},
},
});
const agentId = await this.createAgent(story, toolId);

const session = new ElevenLabsConversation(
agentId,
Expand All @@ -94,7 +78,29 @@ export class ElevenLabsSessionManager implements VoiceAgentSessionManager {
return session;
}

private async ensureGameEndingTool(): Promise<string | undefined> {
private async createAgent(story: Story, toolId: string): Promise<string> {
const instructions = getInstructionsForStory(story);

console.log(
`Creating ElevenLabs agent for story "${story.title}" (ID: ${story.id})`,
);

const prompt = { prompt: instructions, toolIds: [toolId] };

const config = {
conversationConfig: {
agent: {
language: 'en',
prompt,
},
},
};

const { agentId } = await elevenLabs.conversationalAi.agents.create(config);
return agentId;
}

private async ensureGameEndingTool(): Promise<string> {
if (this.gameEndingToolId) {
return this.gameEndingToolId;
}
Expand Down Expand Up @@ -142,8 +148,8 @@ export class ElevenLabsSessionManager implements VoiceAgentSessionManager {
if (this.endingRooms.has(roomId)) {
return;
}

this.endingRooms.add(roomId);

const gameSession = roomService.getGameSession(roomId);

if (!gameSession) {
Expand Down
31 changes: 31 additions & 0 deletions deep-sea-stories/packages/backend/src/service/game-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,37 @@ export class GameSession {
);

orchestrator.setupAudioPipelines();

this.sendInitMessage();
}

private sendInitMessage(): void {
const firstPeerId = this.connectedPeers.values().next().value;
if (!firstPeerId) {
console.error(
`Cannot send init message: no connected peers in room ${this.roomId}`,
);
return;
}

if (!this.voiceSessionManager) {
console.error(
`Cannot send init message: missing session manager for room ${this.roomId}`,
);
return;
}

const session = this.voiceSessionManager.getSession(firstPeerId);
if (!session) {
console.error(
`Cannot send init message: no session for peer ${firstPeerId} in room ${this.roomId}`,
);
return;
}

session.sendUserMessage(
"The riddle master welcomes all players saying 'Welcome to Deep Sea Stories' and then reads the initial scenario or mystery to the guessers. ",
);
}

async stopGame(): Promise<void> {
Expand Down
1 change: 1 addition & 0 deletions deep-sea-stories/packages/backend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface Story {

export interface Conversation extends EventEmitter {
sendAudio(audioBuffer: Buffer): void;
sendUserMessage(message: string): void;
}

export interface VoiceAgentSessionManager {
Expand Down
1 change: 1 addition & 0 deletions deep-sea-stories/packages/web/src/views/JoinView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const JoinView: FC<JoinViewProps> = ({ roomId }) => {

const handleEnterRoom = useCallback(async () => {
if (!roomId) return;
if (!name) return;

try {
const { token } = await trpcClient.createPeer.mutate({ roomId });
Expand Down