wording and overseer tool embeds

This commit is contained in:
legop3
2026-05-19 16:51:02 -04:00
parent e432e3de79
commit f9e472c832
10 changed files with 133 additions and 19 deletions
@@ -100,6 +100,21 @@ function buildRoverCtxSnapshot(roverId) {
function buildMessage(socket, text, meta = {}) {
const roverId = meta.roverId || resolveRoverId(socket?.id);
const roverColor = meta.roverColor ?? resolveRoverColor(roverId);
const toolCalls = Array.isArray(meta.toolCalls)
? meta.toolCalls
.map((entry) => {
if (!entry || typeof entry !== 'object') return null;
return {
tool: String(entry.tool || '').trim() || 'unknown',
status: String(entry.status || '').trim() || 'unknown',
args: entry.args && typeof entry.args === 'object' ? entry.args : {},
result: entry.result && typeof entry.result === 'object' ? entry.result : null,
error: entry.error ? String(entry.error) : null,
durationMs: Number.isFinite(entry.durationMs) ? Math.max(0, Math.round(entry.durationMs)) : null,
};
})
.filter(Boolean)
: null;
return {
id: uuidv4(),
ts: Date.now(),
@@ -119,6 +134,7 @@ function buildMessage(socket, text, meta = {}) {
profileImage: normalizeProfileImageUrl(meta.profileImage),
roverCtx: meta.roverCtx || null,
text,
toolCalls,
tts: meta.tts || null,
bot: Boolean(meta.bot),
};
+3 -1
View File
@@ -11,7 +11,8 @@ const { registerChatSocketHooks } = require('./socketHooks');
function sendSystemMessage(text, options = {}) {
const normalized = normalizeUserText(text);
const clean = normalized.trim();
if (!clean) return null;
const hasToolCalls = Array.isArray(options.toolCalls) && options.toolCalls.length > 0;
if (!clean && !hasToolCalls) return null;
const safe = clean;
const message = buildMessage(null, safe, {
nickname: String(options.nickname || 'The Overseer'),
@@ -19,6 +20,7 @@ function sendSystemMessage(text, options = {}) {
fromDiscord: false,
bot: options.bot !== false,
profileImage: options.profileImage || null,
toolCalls: hasToolCalls ? options.toolCalls : null,
});
broadcastMessage(message);
return message;
@@ -3,6 +3,21 @@
// Scope: Handles inbound Discord messages plus outbound webhook and typing relay.
const { WebhookClient } = require('discord.js');
function summarizeToolCall(entry = {}) {
const tool = String(entry?.tool || 'unknown');
const status = String(entry?.status || 'unknown').toLowerCase();
if (status === 'ok') return `${tool}`;
if (status === 'blocked') return `${tool}${String(entry?.error || 'blocked')}`;
if (status === 'error') return `${tool}${String(entry?.error || 'failed')}`;
return `${tool}`;
}
function formatToolCallsCodeBlock(toolCalls = []) {
const rows = (toolCalls || []).map((entry) => summarizeToolCall(entry));
if (!rows.length) return '';
return `\`\`\`txt\nTool calls:\n${rows.join('\n')}\n\`\`\``;
}
function createChatBridgeHandlers(deps) {
const {
logger,
@@ -48,7 +63,15 @@ function createChatBridgeHandlers(deps) {
const guildConfigs = listGuildConfigs();
if (!guildConfigs.length) return;
const text = payload.text?.length > 1900 ? `${payload.text.slice(0, 1897)}...` : payload.text;
const baseText = String(payload.text || '');
const toolCalls = Array.isArray(payload.toolCalls) ? payload.toolCalls : [];
const toolsBlock = formatToolCallsCodeBlock(toolCalls);
let text = baseText;
if (toolsBlock) {
text = text ? `${text}\n\n${toolsBlock}` : `Overseer ran tools (no chat line).\n\n${toolsBlock}`;
}
if (text.length > 1900) text = `${text.slice(0, 1897)}...`;
if (!text.trim()) return;
const username = formatWebhookUsername(payload);
const avatarURL = payload.profileImage || (payload.fromDiscord ? payload.discordUserAvatarUrl || null : client.user?.displayAvatarURL?.({ extension: 'png', size: 128 }) || null);
const typingId = getTypingId(payload);
@@ -207,6 +207,44 @@ function normalizeChatDraft(text) {
return next;
}
function summarizeResult(result) {
if (!result || typeof result !== 'object') return null;
if (Object.prototype.hasOwnProperty.call(result, 'ok')) return { ok: Boolean(result.ok) };
return null;
}
function buildToolCallFeedEntries(requestedActions = [], actionResults = []) {
const resultsByTool = new Map();
(actionResults || []).forEach((entry) => {
if (!entry || entry.kind !== 'tool') return;
const key = String(entry.tool || '');
if (!key) return;
if (!resultsByTool.has(key)) resultsByTool.set(key, []);
resultsByTool.get(key).push(entry);
});
return (requestedActions || []).map((action) => {
const tool = String(action?.tool || '').trim() || 'unknown';
const bucket = resultsByTool.get(tool) || [];
const resultEntry = bucket.length ? bucket.shift() : null;
const ok = Boolean(resultEntry?.ok);
const errText = resultEntry?.error ? String(resultEntry.error) : '';
const status = resultEntry
? ok
? 'ok'
: errText.includes('blocked') || errText.includes('unavailable')
? 'blocked'
: 'error'
: 'started';
return {
tool,
status,
args: action?.args && typeof action.args === 'object' ? action.args : {},
result: summarizeResult(resultEntry?.result),
error: errText || null,
};
});
}
async function runDecision(triggerReason) {
const runId = runtime.tickCount;
updateStatus({ phase: 'context_build', currentRunId: runId, lastTriggerReason: triggerReason, lastError: null, lastErrorDetails: null });
@@ -280,11 +318,6 @@ async function runDecision(triggerReason) {
const reason = observeOnly ? 'observe-only mode' : null;
if (!observeOnly) {
if ((decision === 'CHAT' || decision === 'ACTION+CHAT') && chatDraft) {
sendSystemMessage(chatDraft, { nickname: name, bot: true, profileImage: profileImageUrl });
actionResults.push({ kind: 'chat', ok: true });
}
if (decision === 'ACTION' || decision === 'ACTION+CHAT') {
for (const action of requestedActions) {
pushLiveToolCall({ phase: 'start', tool: action.tool, args: action.args });
@@ -315,6 +348,17 @@ async function runDecision(triggerReason) {
}
}
}
const toolCallFeed = buildToolCallFeedEntries(requestedActions, actionResults);
if (toolCallFeed.length > 0) {
if ((decision === 'CHAT' || decision === 'ACTION+CHAT') && chatDraft) {
sendSystemMessage(chatDraft, { nickname: name, bot: true, profileImage: profileImageUrl, toolCalls: toolCallFeed });
} else {
sendSystemMessage('', { nickname: name, bot: true, profileImage: profileImageUrl, toolCalls: toolCallFeed });
}
} else if ((decision === 'CHAT' || decision === 'ACTION+CHAT') && chatDraft) {
sendSystemMessage(chatDraft, { nickname: name, bot: true, profileImage: profileImageUrl });
}
}
updateStatus({