mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
gwuh
This commit is contained in:
@@ -105,12 +105,68 @@ function buildMessage(socket, text, meta = {}) {
|
|||||||
discordUserId: meta.discordUserId || null,
|
discordUserId: meta.discordUserId || null,
|
||||||
discordUserName: meta.discordUserName || null,
|
discordUserName: meta.discordUserName || null,
|
||||||
discordUserAvatarUrl: meta.discordUserAvatarUrl || null,
|
discordUserAvatarUrl: meta.discordUserAvatarUrl || null,
|
||||||
|
roverCtx: meta.roverCtx || null,
|
||||||
text,
|
text,
|
||||||
tts: meta.tts || null,
|
tts: meta.tts || null,
|
||||||
system: Boolean(meta.system),
|
system: Boolean(meta.system),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isChargingFromSensors(sensors = {}) {
|
||||||
|
const label = String(sensors?.chargingState?.label || '').toLowerCase();
|
||||||
|
if (label === 'waiting' || label === 'full charging' || label === 'trickle charging') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const code = sensors?.chargingState?.code;
|
||||||
|
return code === 2 || code === 3 || code === 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildRoverCtxSnapshot(roverId) {
|
||||||
|
if (!roverId) return null;
|
||||||
|
const key = String(roverId);
|
||||||
|
const record = roverManager.rovers.get(key);
|
||||||
|
if (!record) return null;
|
||||||
|
const sensors = record?.lastSensor?.decoded || {};
|
||||||
|
const batteryState = record?.batteryState || null;
|
||||||
|
const { getActiveDrivers } = require('./turnService');
|
||||||
|
const activeDrivers = getActiveDrivers();
|
||||||
|
const driverSocketId = activeDrivers[key] || record?.drivers?.values?.().next?.().value || null;
|
||||||
|
const charging = isChargingFromSensors(sensors);
|
||||||
|
const docked = Boolean(sensors?.chargingSources?.homeBase);
|
||||||
|
const wheelsOffGround = Boolean(
|
||||||
|
sensors?.bumpsAndWheelDrops?.wheelDropLeft && sensors?.bumpsAndWheelDrops?.wheelDropRight,
|
||||||
|
);
|
||||||
|
const latestDistanceM = Math.round((Math.abs(Number(sensors?.distanceMm) || 0) / 1000) * 10) / 10;
|
||||||
|
const latestTurnDeg = Math.round(Math.abs(Number(sensors?.angleDeg) || 0));
|
||||||
|
const latestBumps =
|
||||||
|
(sensors?.bumpsAndWheelDrops?.bumpLeft ? 0.5 : 0) +
|
||||||
|
(sensors?.bumpsAndWheelDrops?.bumpRight ? 0.5 : 0);
|
||||||
|
const moving = latestDistanceM > 0.05 || latestTurnDeg > 10;
|
||||||
|
let statusTag = 'idle';
|
||||||
|
if (charging) {
|
||||||
|
statusTag = 'charging';
|
||||||
|
} else if (docked) {
|
||||||
|
statusTag = 'docked';
|
||||||
|
} else if (driverSocketId && moving) {
|
||||||
|
statusTag = 'driving';
|
||||||
|
} else if (driverSocketId) {
|
||||||
|
statusTag = 'active-idle';
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id: key,
|
||||||
|
status_tag: statusTag,
|
||||||
|
battery_low: Boolean(batteryState?.warnActive || batteryState?.urgentActive),
|
||||||
|
docked,
|
||||||
|
charging,
|
||||||
|
wheels_off_ground: wheelsOffGround,
|
||||||
|
activity_30s: {
|
||||||
|
distance_m: latestDistanceM,
|
||||||
|
turn_deg: latestTurnDeg,
|
||||||
|
bumps: latestBumps,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function buildTypingPayload(socket, meta = {}) {
|
function buildTypingPayload(socket, meta = {}) {
|
||||||
const roverId = meta.roverId || resolveRoverId(socket?.id);
|
const roverId = meta.roverId || resolveRoverId(socket?.id);
|
||||||
const socketId = socket?.id || null;
|
const socketId = socket?.id || null;
|
||||||
@@ -282,7 +338,12 @@ function handleIncoming({ text, tts } = {}, socket, cb = () => {}) {
|
|||||||
// }
|
// }
|
||||||
const roverId = resolveRoverId(socket?.id);
|
const roverId = resolveRoverId(socket?.id);
|
||||||
const ttsOptions = normalizeTtsOptions(tts);
|
const ttsOptions = normalizeTtsOptions(tts);
|
||||||
const message = buildMessage(socket, clean, { fromDiscord: false, roverId, tts: ttsOptions });
|
const message = buildMessage(socket, clean, {
|
||||||
|
fromDiscord: false,
|
||||||
|
roverId,
|
||||||
|
roverCtx: buildRoverCtxSnapshot(roverId),
|
||||||
|
tts: ttsOptions,
|
||||||
|
});
|
||||||
logger.info('Chat message', { socket: socket.id, roverId: message.roverId });
|
logger.info('Chat message', { socket: socket.id, roverId: message.roverId });
|
||||||
playTypingNote(roverId, TYPING_SEND_NOTE, socket?.id);
|
playTypingNote(roverId, TYPING_SEND_NOTE, socket?.id);
|
||||||
broadcastMessage(message);
|
broadcastMessage(message);
|
||||||
@@ -349,6 +410,7 @@ function sendExternalMessage({
|
|||||||
nickname,
|
nickname,
|
||||||
role,
|
role,
|
||||||
roverId,
|
roverId,
|
||||||
|
roverCtx: buildRoverCtxSnapshot(roverId),
|
||||||
fromDiscord: true,
|
fromDiscord: true,
|
||||||
discordGuildId,
|
discordGuildId,
|
||||||
discordGuildName,
|
discordGuildName,
|
||||||
|
|||||||
@@ -477,12 +477,8 @@ function compactRoverForContext(rover) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildSnapshot() {
|
function buildRoversNow(nowMs = Date.now()) {
|
||||||
const now = new Date();
|
|
||||||
const nowMs = now.getTime();
|
|
||||||
const activeDrivers = getActiveDrivers();
|
const activeDrivers = getActiveDrivers();
|
||||||
const driverEntries = collectActiveDriverEntries();
|
|
||||||
|
|
||||||
const roster = roverManager.getRoster().slice(0, MAX_ROVERS);
|
const roster = roverManager.getRoster().slice(0, MAX_ROVERS);
|
||||||
const nextRoverStateById = new Map();
|
const nextRoverStateById = new Map();
|
||||||
const rovers = roster.map((entry) => {
|
const rovers = roster.map((entry) => {
|
||||||
@@ -537,6 +533,14 @@ function buildSnapshot() {
|
|||||||
nextRoverStateById.forEach((value, roverId) => {
|
nextRoverStateById.forEach((value, roverId) => {
|
||||||
lastRoverStateById.set(roverId, value);
|
lastRoverStateById.set(roverId, value);
|
||||||
});
|
});
|
||||||
|
return { rovers, activeDrivers, roster };
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildSnapshot() {
|
||||||
|
const now = new Date();
|
||||||
|
const nowMs = now.getTime();
|
||||||
|
const driverEntries = collectActiveDriverEntries();
|
||||||
|
const { rovers } = buildRoversNow(nowMs);
|
||||||
const roverById = new Map(rovers.map((rover) => [String(rover.id), rover]));
|
const roverById = new Map(rovers.map((rover) => [String(rover.id), rover]));
|
||||||
const allRecentMessages = getRecentMessages(300, { includeSystem: true })
|
const allRecentMessages = getRecentMessages(300, { includeSystem: true })
|
||||||
.filter((entry) => Number(entry?.ts) >= contextResetAt);
|
.filter((entry) => Number(entry?.ts) >= contextResetAt);
|
||||||
@@ -571,7 +575,7 @@ function buildSnapshot() {
|
|||||||
nickname: entry.nickname || entry.socketId?.slice(0, 6) || 'unknown',
|
nickname: entry.nickname || entry.socketId?.slice(0, 6) || 'unknown',
|
||||||
text: entry.text || '',
|
text: entry.text || '',
|
||||||
rover_id: roverId,
|
rover_id: roverId,
|
||||||
rover_ctx: compactRoverForContext(rover),
|
rover_ctx: entry?.roverCtx || entry?.rover_ctx || compactRoverForContext(rover),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const hasRecentChat = eventStream.some((event) => event.type === 'chat');
|
const hasRecentChat = eventStream.some((event) => event.type === 'chat');
|
||||||
@@ -604,6 +608,17 @@ function buildSnapshot() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function refreshFinalSnapshotForSend(snapshot) {
|
||||||
|
const { rovers } = buildRoversNow(Date.now());
|
||||||
|
return {
|
||||||
|
...(snapshot || {}),
|
||||||
|
current_snapshot: {
|
||||||
|
...(snapshot?.current_snapshot || {}),
|
||||||
|
rovers,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeCommentary(rawText) {
|
function normalizeCommentary(rawText) {
|
||||||
if (typeof rawText !== 'string') return null;
|
if (typeof rawText !== 'string') return null;
|
||||||
const trimmed = rawText.trim();
|
const trimmed = rawText.trim();
|
||||||
@@ -832,14 +847,15 @@ async function runTick() {
|
|||||||
lastInfoSnapshot: snapshot,
|
lastInfoSnapshot: snapshot,
|
||||||
});
|
});
|
||||||
const systemPrompt = await readSystemPrompt();
|
const systemPrompt = await readSystemPrompt();
|
||||||
const modelMessages = buildModelMessages(systemPrompt, snapshot);
|
const snapshotForSend = refreshFinalSnapshotForSend(snapshot);
|
||||||
|
const modelMessages = buildModelMessages(systemPrompt, snapshotForSend);
|
||||||
const modelInputAt = Date.now();
|
const modelInputAt = Date.now();
|
||||||
patchCurrentRun({
|
patchCurrentRun({
|
||||||
phase: 'input_ready',
|
phase: 'input_ready',
|
||||||
input: {
|
input: {
|
||||||
...(currentRun?.input || {}),
|
...(currentRun?.input || {}),
|
||||||
systemPrompt,
|
systemPrompt,
|
||||||
infoSnapshot: snapshot,
|
infoSnapshot: snapshotForSend,
|
||||||
modelMessages,
|
modelMessages,
|
||||||
modelInputAt,
|
modelInputAt,
|
||||||
},
|
},
|
||||||
@@ -848,6 +864,7 @@ async function runTick() {
|
|||||||
lastModelMessages: modelMessages,
|
lastModelMessages: modelMessages,
|
||||||
lastModelInputAt: modelInputAt,
|
lastModelInputAt: modelInputAt,
|
||||||
lastModelInputTickId: tickId,
|
lastModelInputTickId: tickId,
|
||||||
|
lastInfoSnapshot: snapshotForSend,
|
||||||
lastModelRawOutput: null,
|
lastModelRawOutput: null,
|
||||||
lastModelOutputAt: null,
|
lastModelOutputAt: null,
|
||||||
lastModelOutputTickId: null,
|
lastModelOutputTickId: null,
|
||||||
|
|||||||
Reference in New Issue
Block a user