Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | /**
* Game mode — a game is active on the number line.
*
* Games with sessionTools/sessionInstructions (e.g. Nim) get focused
* tools + instructions. Legacy games get a minimal prompt with agentRules
* and restricted tools.
*/
import type { AgentMode, RealtimeTool } from './types'
import { GAME_MAP } from '../gameRegistry'
import {
TOOL_INDICATE,
TOOL_LOOK_AT,
TOOL_END_GAME,
TOOL_HANG_UP,
TOOL_REQUEST_MORE_TIME,
TOOL_MARK_MOMENT,
} from './tools'
export const gameMode: AgentMode = {
id: 'game',
getInstructions: (ctx) => {
const game = ctx.activeGameId ? GAME_MAP.get(ctx.activeGameId) : null
if (!game) {
// Fallback — shouldn't happen, but be safe
const displayN = Number.isInteger(ctx.calledNumber)
? ctx.calledNumber.toString()
: ctx.calledNumber.toPrecision(6)
return `You are the number ${displayN}, on a phone call with a child. A game was active but couldn't be found. Call end_game to return to conversation.`
}
// Session-mode game: use its dedicated instructions
if (game.sessionInstructions) {
// For trick games, prepend a universal anti-spoiler rule
if (game.category === 'trick') {
return (
'🎩 UNIVERSAL TRICK RULE: The magic depends on secrecy. ' +
'NEVER ask "what did you get?", "what\'s your answer?", or "what number did you write down?" ' +
'unless the game instructions specifically say to. ' +
'Ask "are you ready?" or "tell me when you\'re done" to pace steps. ' +
"The child keeps their work secret — that's what makes the reveal magical.\n\n" +
game.sessionInstructions
)
}
return game.sessionInstructions
}
// Legacy game: abbreviated identity + game rules
const displayN = Number.isInteger(ctx.calledNumber)
? ctx.calledNumber.toString()
: ctx.calledNumber.toPrecision(6)
return `You are the number ${displayN}, on a phone call with a child.\n\nACTIVE GAME: ${game.name}\n${game.agentRules}\n\nKeep responses short. Be encouraging.`
},
getTools: (ctx) => {
const game = ctx.activeGameId ? GAME_MAP.get(ctx.activeGameId) : null
// Session-mode game: use its dedicated tools + shared tools.
// look_at and indicate are NOT in sessionTools (so the game's onToolCall
// won't intercept them) — they fall through to the built-in handlers.
if (game?.sessionTools) {
return [
...(game.sessionTools as RealtimeTool[]),
TOOL_LOOK_AT,
TOOL_INDICATE,
TOOL_END_GAME,
TOOL_HANG_UP,
TOOL_MARK_MOMENT,
]
}
// Legacy game: restricted tool set
return [
TOOL_INDICATE,
TOOL_LOOK_AT,
TOOL_END_GAME,
TOOL_HANG_UP,
TOOL_REQUEST_MORE_TIME,
TOOL_MARK_MOMENT,
]
},
}
|