overseer v2 3

This commit is contained in:
legop3
2026-05-03 23:20:09 -04:00
parent e97b623b43
commit 5b48b10971
16 changed files with 196 additions and 118 deletions
@@ -1,6 +1,13 @@
module.exports = {
id: 'chat_say',
signature: 'chat_say(text)',
availability() {
return { available: true, reason: null };
},
async execute({ args = {}, sendSystemMessage, name }) {
const text = String(args?.text || '').trim();
if (!text) throw new Error('chat_say requires args.text');
sendSystemMessage(text, { nickname: name });
return { ok: true };
},
};
@@ -1,4 +1,5 @@
module.exports = {
id: 'ha_set_entity',
signature: 'ha_set_entity(entity_id, state)',
availability(ctx = {}) {
const mode = String(ctx.mode || '');
@@ -11,4 +12,12 @@ module.exports = {
if (!ctx.homeAssistantState?.connected) return { available: false, reason: 'unavailable' };
return { available: true, reason: null };
},
async execute({ args = {}, homeAssistantService }) {
const entityId = String(args?.entity_id || args?.entityId || '').trim();
if (!entityId) throw new Error('ha_set_entity requires args.entity_id');
const state = String(args?.state || '').toLowerCase();
if (state !== 'on' && state !== 'off') throw new Error('ha_set_entity requires args.state of on/off');
await homeAssistantService.setEntityState(entityId, state, { source: 'overseerControl' });
return { ok: true };
},
};
@@ -21,6 +21,7 @@ const TOOL_DEFINITIONS = [
neatoClearErrors,
haSetEntity,
];
const TOOL_BY_ID = new Map(TOOL_DEFINITIONS.map((tool) => [tool.id, tool]));
function evaluateTools(context = {}) {
const available = [];
@@ -36,7 +37,20 @@ function evaluateTools(context = {}) {
return { available, blocked };
}
async function executeToolAction(action = {}, context = {}) {
const toolId = String(action?.tool || '').trim();
const tool = TOOL_BY_ID.get(toolId);
if (!tool) {
throw new Error(`Unknown tool: ${toolId}`);
}
if (typeof tool.execute !== 'function') {
throw new Error(`Tool ${toolId} is not executable`);
}
return tool.execute({ ...context, args: action?.args || {} });
}
module.exports = {
TOOL_DEFINITIONS,
evaluateTools,
executeToolAction,
};
@@ -1,4 +1,5 @@
module.exports = {
id: 'lift_down',
signature: 'lift_down()',
availability(ctx = {}) {
const mode = String(ctx.mode || '');
@@ -9,4 +10,8 @@ module.exports = {
if (ctx.liftState?.busy) return { available: false, reason: 'busy' };
return { available: true, reason: null };
},
async execute({ liftService, actor = 'overseerControl' }) {
const resp = await liftService.moveDown(actor);
return { ok: true, resp };
},
};
@@ -1,4 +1,5 @@
module.exports = {
id: 'lift_up',
signature: 'lift_up()',
availability(ctx = {}) {
const mode = String(ctx.mode || '');
@@ -9,4 +10,8 @@ module.exports = {
if (ctx.liftState?.busy) return { available: false, reason: 'busy' };
return { available: true, reason: null };
},
async execute({ liftService, actor = 'overseerControl' }) {
const resp = await liftService.moveUp(actor);
return { ok: true, resp };
},
};
@@ -1,6 +1,10 @@
module.exports = {
id: 'memory_read',
signature: 'memory_read()',
availability() {
return { available: true, reason: null };
},
async execute({ memoryStore }) {
return { ok: true, slots: memoryStore || ['', '', ''] };
},
};
@@ -1,6 +1,17 @@
module.exports = {
id: 'memory_write',
signature: 'memory_write(slot, text)',
availability() {
return { available: true, reason: null };
},
async execute({ args = {}, memoryStore }) {
const slot = Math.max(1, Math.min(3, Number(args?.slot) || 0));
if (!slot) throw new Error('memory_write requires args.slot 1..3');
const text = String(args?.text || '').trim();
if (!text) throw new Error('memory_write requires args.text');
const next = Array.isArray(memoryStore) ? [...memoryStore] : ['', '', ''];
while (next.length < 3) next.push('');
next[slot - 1] = text.slice(0, 180);
return { ok: true, slots: next };
},
};
@@ -1,4 +1,5 @@
module.exports = {
id: 'neato_clear_errors',
signature: 'neato_clear_errors()',
availability(ctx = {}) {
const mode = String(ctx.mode || '');
@@ -8,4 +9,8 @@ module.exports = {
if (!ctx.neatoState?.connected) return { available: false, reason: 'unavailable' };
return { available: true, reason: null };
},
async execute({ neatoService }) {
await neatoService.clearErrors();
return { ok: true };
},
};
@@ -1,4 +1,5 @@
module.exports = {
id: 'neato_locate',
signature: 'neato_locate()',
availability(ctx = {}) {
const mode = String(ctx.mode || '');
@@ -8,4 +9,8 @@ module.exports = {
if (!ctx.neatoState?.connected) return { available: false, reason: 'unavailable' };
return { available: true, reason: null };
},
async execute({ neatoService }) {
await neatoService.locateRobot();
return { ok: true };
},
};
@@ -1,4 +1,5 @@
module.exports = {
id: 'neato_send_home',
signature: 'neato_send_home()',
availability(ctx = {}) {
const mode = String(ctx.mode || '');
@@ -8,4 +9,8 @@ module.exports = {
if (!ctx.neatoState?.connected) return { available: false, reason: 'unavailable' };
return { available: true, reason: null };
},
async execute({ neatoService }) {
await neatoService.sendHome();
return { ok: true };
},
};
@@ -1,4 +1,5 @@
module.exports = {
id: 'neato_start',
signature: 'neato_start()',
availability(ctx = {}) {
const mode = String(ctx.mode || '');
@@ -8,4 +9,8 @@ module.exports = {
if (!ctx.neatoState?.connected) return { available: false, reason: 'unavailable' };
return { available: true, reason: null };
},
async execute({ neatoService }) {
await neatoService.startCleaning();
return { ok: true };
},
};