openvibers/openvibe.actor Commits

The answer checker knows today's date, so a correct web answer about a recent release is not refused as 'in the future' (#107)

OP OpenVibers committed 20 days ago · 1832f3aeee · 3 files, +27 −3

Changes

ddiff --git a/server/agents/check.js b/server/agents/check.js
iindex 3afff71..dcf8a2b 100644
---- a/server/agents/check.js
++++ b/server/agents/check.js
@@@ -45,7 +45,10 @@ const checkerFor = (agentId, checkers, opts) => checkersFor(agentId, checkers, o
* Ask each checker in turn until one gives a verdict: a checker that answers nothing usable (a provider error, no JSON)
* passes the turn to the next; only when none gives a verdict is the result unavailable (and never delivered).
*/
--async function check({ task, answer, sources = [], evidence = [], agentId, mode, checkers, signal }) {
++async function check({ task, answer, sources = [], evidence = [], agentId, mode, checkers, signal, now = Date.now }) {
++ // The checker knows today's date: without it, a model whose training ends earlier refused a correct web answer for a
++ // release "dated Oct 21, 2026, which is in the future and plainly impossible" (2026-10-24, a task from Chat's Vibe).
++ const today = new Date(now()).toISOString().slice(0, 10);
const list = checkersFor(agentId, checkers, { mode, grounded: evidence.length > 0 });
if (!list.length) return { ok: false, unavailable: true, reason: 'no model is available to check this answer', cost_usd: 0 };
let cost = 0;
@@@ -65,7 +68,7 @@ async function check({ task, answer, sources = [], evidence = [], agentId, mode,
for (const c of list) {
try {
const r = await c.chat({
-- messages: [{ role: 'system', content: SYSTEM }, { role: 'user', content: `=== Task ===\n${String(task).slice(0, 6000)}\n\n=== The agent's answer (prose to the person) ===\n${String(answer).slice(0, 12000)}\n=== End of answer ===${cited}${tools}` }],
++ messages: [{ role: 'system', content: `${SYSTEM}\nToday is ${today} (UTC). A date on or before today is in the past or present, never in the future; recent releases, prices and events up to today are possible.` }, { role: 'user', content: `=== Task ===\n${String(task).slice(0, 6000)}\n\n=== The agent's answer (prose to the person) ===\n${String(answer).slice(0, 12000)}\n=== End of answer ===${cited}${tools}` }],
json: true, maxTokens: 160, signal,
});
cost += r.cost_usd || 0;
ddiff --git a/server/tasks/engine.js b/server/tasks/engine.js
iindex 6a259a3..452de7e 100644
---- a/server/tasks/engine.js
++++ b/server/tasks/engine.js
@@@ -154,7 +154,7 @@ function createEngine({ config, s, adapters, stream, webhooks = null, now = () =
continue;
}
await setState(id, 'verifying', { agentForEvent: agentId });
-- const verdict = await check({ task: row.task, answer: out.text, sources: out.sources || [], evidence: out.evidence || [], agentId, mode: row.mode, checkers: adapters.checkers, signal });
++ const verdict = await check({ task: row.task, answer: out.text, sources: out.sources || [], evidence: out.evidence || [], agentId, mode: row.mode, checkers: adapters.checkers, signal, now: () => now() });
await meter(verdict.cost_usd);
await emit(id, { kind: 'output', step: 'check', agent: agentId, text: `${verdict.ok ? 'Checked' : 'Check failed'}${verdict.by ? ` by ${verdict.by}${verdict.cross ? '' : ' (same family)'}` : ''}: ${verdict.reason || ''}`.slice(0, 2000), is_error: !verdict.ok });
if (verdict.ok) {
ddiff --git a/test/check-today.test.js b/test/check-today.test.js
nnew file mode 100644
iindex 0000000..3e57600
---- /dev/null
++++ b/test/check-today.test.js
@@@ -0,0 +1,21 @@
++'use strict';
++// The answer checker (server/agents/check.js) is told today's date: a checker model whose training ends earlier refused
++// a correct web answer for a release "dated Oct 21, 2026, which is in the future and plainly impossible" (2026-10-24, a
++// web search from Vibe on openvibe.chat). The date is UTC, from the clock the engine passes.
++const assert = require('assert');
++const { check: checkAnswer } = require('../server/agents/check');
++
++(async () => {
++ const seen = [];
++ const deepseek = async (o) => { seen.push(o.messages[0].content); return { text: '{"ok": true, "reason": "addresses the task"}', cost_usd: 0.0001, model: 'deepseek-flash' }; };
++ const verdict = await checkAnswer({
++ task: 'What is the latest Node.js release?', answer: 'Node.js v24.22.1, released Oct 21, 2026 (https://nodejs.org).',
++ sources: ['https://nodejs.org'], agentId: 'openai-agent', mode: 'balanced', checkers: { deepseek },
++ now: () => Date.UTC(2026, 9, 24, 22, 30),
++ });
++ assert.strictEqual(verdict.ok, true);
++ assert.strictEqual(verdict.by, 'deepseek');
++ assert.ok(seen[0].includes('Today is 2026-10-24 (UTC). A date on or before today is in the past or present, never in the future'), seen[0].slice(-300));
++ assert.ok(seen[0].startsWith('You check an AI agent\'s answer'), 'the rules come first, the date after them');
++ console.log('check today: all checks passed');
++})().catch((e) => { console.error(e); process.exit(1); });