diff --git a/server/prompts/commentary_system.txt b/server/prompts/commentary_system.txt index 9107ba65..a9f9edf3 100644 --- a/server/prompts/commentary_system.txt +++ b/server/prompts/commentary_system.txt @@ -43,6 +43,7 @@ Rover context hints: - CHAT `rover_now` and SNAPSHOT FINAL include qualitative tags: - status, battery_low, docked, charging, wheels_off_ground, contact, hazard, mobility, activity_band, activity_trend - `activity_score` may be present for internal significance checks only. +- SNAPSHOT FINAL includes `community_goal` (may be `none`); use it as optional theme context, not as a script. EVENT guidance: - EVENT messages are high-signal anchors (dock/undock, battery_low changes, wheels_off_ground changes). @@ -108,4 +109,4 @@ Style: Behavior framing: - Treat rover activity as ongoing test-chamber behavior, but keep it light. - Be collaborative with chat, not a scolding safety announcer. -- Only use hazard-like language when there is an immediate clear issue. \ No newline at end of file +- Only use hazard-like language when there is an immediate clear issue. diff --git a/server/src/services/llmCommentaryService.js b/server/src/services/llmCommentaryService.js index 91d9b1af..23dfb698 100644 --- a/server/src/services/llmCommentaryService.js +++ b/server/src/services/llmCommentaryService.js @@ -9,6 +9,7 @@ const roverManager = require('./roverManager'); const { getActiveDrivers } = require('./turnService'); const { getNickname } = require('./nicknameService'); const { getRecentMessages, sendSystemMessage } = require('./chatService'); +const { getCommunityGoal } = require('./communityGoalService'); const PROMPT_PATH = path.join(__dirname, '..', '..', 'prompts', 'commentary_system.txt'); const DEFAULT_FREQUENCY_MS = 0; @@ -26,6 +27,7 @@ const MAX_CONTEXT_EVENTS = 10; const MAX_RUN_HISTORY = 30; const MAX_ROVER_EVENTS = 400; const POST_COOLDOWN_MS = 10000; +const MAX_GOAL_CONTEXT_CHARS = 220; const config = loadConfig(); const commentaryConfig = config.llmCommentary || {}; @@ -768,8 +770,13 @@ function buildSnapshot() { }); } + const goal = getCommunityGoal(); + const goalTextRaw = goal?.text ? String(goal.text).trim() : ''; + const goalText = goalTextRaw ? goalTextRaw.slice(0, MAX_GOAL_CONTEXT_CHARS) : null; + const currentSnapshot = { rovers, + community_goal: goalText, }; if (!hasRecentChat) { currentSnapshot.chat_recent = chatRecent; @@ -790,12 +797,16 @@ function buildSnapshot() { } function refreshFinalSnapshotForSend(snapshot) { + const goal = getCommunityGoal(); + const goalTextRaw = goal?.text ? String(goal.text).trim() : ''; + const goalText = goalTextRaw ? goalTextRaw.slice(0, MAX_GOAL_CONTEXT_CHARS) : null; const { rovers } = buildRoversNow(Date.now()); return { ...(snapshot || {}), current_snapshot: { ...(snapshot?.current_snapshot || {}), rovers, + community_goal: goalText, }, }; } @@ -883,6 +894,10 @@ function formatSnapshotMessage(event) { function formatSnapshotFinalMessage(currentSnapshot = {}) { const rovers = Array.isArray(currentSnapshot?.rovers) ? currentSnapshot.rovers : []; const lines = ['SNAPSHOT FINAL']; + const goalText = currentSnapshot?.community_goal + ? String(currentSnapshot.community_goal).trim() + : ''; + lines.push(`community_goal: ${goalText || 'none'}`); rovers.forEach((rover) => { lines.push(formatRoverSnapshotLine(rover)); });