openvibers/openvibe.chat Commits
Vibe sources: date a page at the time Vibe read it (#262)
Changes
@@@ -85,7 +85,16 @@ function step(acc, tool, raw = null) {if (!args || typeof args !== 'object') args = {};const line = STEP[tool](args);if (acc.steps[acc.steps.length - 1] !== line) acc.steps.push(line); // the same step twice in a row reads once-- if (tool === 'read_page' && /^https?:\/\//.test(String(args.url || '')) && acc.sources.length < 6 && !acc.sources.includes(args.url)) acc.sources.push(String(args.url).slice(0, 500));++ if (tool === 'read_page' && /^https?:\/\//.test(String(args.url || ''))) {++ const url = String(args.url).slice(0, 500);++ if (!Array.isArray(acc.sources)) acc.sources = [];++ if (acc.sources.length < 6 && !acc.sources.includes(url)) acc.sources.push(url);++ if (!Array.isArray(acc.citations)) acc.citations = [];++ // A page read has no publication date of its own: the chip shows the date Vibe read it (11-01).++ if (!acc.citations.some((c) => c && c.url === url) && acc.citations.length < MAX_CITES) {++ acc.citations.push({ url, site: hostOf(url), title: null, provider: null, published_at: null, retrieved_at: new Date().toISOString() });++ }++ }}function ofMessage(raw) {const how = typeof raw === 'string' ? json(raw, null) : raw;@@@ -57,7 +57,7 @@ t('the tools Vibe used are kept with its answer, in plain words, with the pagesconst page = await fetch(`${h.base}/vibe/${r.body.room.slug}`, { headers: { cookie: `ov_token=${ann.token}` } }).then((x) => x.text());assert.ok(page.includes('<ul class="vb-sources" aria-label="Sources">'), 'source chips under the answer');assert.match(page, /<a class="vb-source" href="https:\/\/openvibe\.deals\/d\/k2"[^>]*>[\s\S]*?openvibe\.deals[\s\S]*?Oct 20, 2026/);-- assert.ok(page.includes('href="https://www.example.com/kb"'), 'the page it read is a source too');++ assert.match(page, /<a class="vb-source" href="https:\/\/www\.example\.com\/kb"[^>]*><span class="vb-source-site">example\.com<\/span><span class="vb-source-date">[^<]+<\/span><\/a>/, 'the page it read is a source too, dated when it was read');assert.ok(page.includes('<details class="vb-how"><summary>How Vibe did this</summary>'), 'folded under the answer');assert.match(page, /<li class="vb-how-sources"><span>Sources:<\/span> [\s\S]*?openvibe\.deals[\s\S]*?Oct 20, 2026[\s\S]*?example\.com/);assert.strictEqual((page.match(/openvibe\.deals\/d\/k2/g) || []).length, 2, 'the chip and How list the same source');
@@ -85,7 +85,16 @@ function step(acc, tool, raw = null) {
@@ -85,7 +85,16 @@ function step(acc, tool, raw = null) {
if (!args || typeof args !== 'object') args = {};
if (!args || typeof args !== 'object') args = {};
const line = STEP[tool](args);
const line = STEP[tool](args);
if (acc.steps[acc.steps.length - 1] !== line) acc.steps.push(line); // the same step twice in a row reads once
if (acc.steps[acc.steps.length - 1] !== line) acc.steps.push(line); // the same step twice in a row reads once
- if (tool === 'read_page' && /^https?:\/\//.test(String(args.url || '')) && acc.sources.length < 6 && !acc.sources.includes(args.url)) acc.sources.push(String(args.url).slice(0, 500));
+ if (tool === 'read_page' && /^https?:\/\//.test(String(args.url || ''))) {
+ const url = String(args.url).slice(0, 500);
+ if (!Array.isArray(acc.sources)) acc.sources = [];
+ if (acc.sources.length < 6 && !acc.sources.includes(url)) acc.sources.push(url);
+ if (!Array.isArray(acc.citations)) acc.citations = [];
+ // A page read has no publication date of its own: the chip shows the date Vibe read it (11-01).
+ if (!acc.citations.some((c) => c && c.url === url) && acc.citations.length < MAX_CITES) {
+ acc.citations.push({ url, site: hostOf(url), title: null, provider: null, published_at: null, retrieved_at: new Date().toISOString() });
+ }
+ }
}
}
function ofMessage(raw) {
function ofMessage(raw) {
const how = typeof raw === 'string' ? json(raw, null) : raw;
const how = typeof raw === 'string' ? json(raw, null) : raw;
@@ -57,7 +57,7 @@ t('the tools Vibe used are kept with its answer, in plain words, with the pages
@@ -57,7 +57,7 @@ t('the tools Vibe used are kept with its answer, in plain words, with the pages
const page = await fetch(`${h.base}/vibe/${r.body.room.slug}`, { headers: { cookie: `ov_token=${ann.token}` } }).then((x) => x.text());
const page = await fetch(`${h.base}/vibe/${r.body.room.slug}`, { headers: { cookie: `ov_token=${ann.token}` } }).then((x) => x.text());
assert.ok(page.includes('<ul class="vb-sources" aria-label="Sources">'), 'source chips under the answer');
assert.ok(page.includes('<ul class="vb-sources" aria-label="Sources">'), 'source chips under the answer');
assert.match(page, /<a class="vb-source" href="https:\/\/openvibe\.deals\/d\/k2"[^>]*>[\s\S]*?openvibe\.deals[\s\S]*?Oct 20, 2026/);
assert.match(page, /<a class="vb-source" href="https:\/\/openvibe\.deals\/d\/k2"[^>]*>[\s\S]*?openvibe\.deals[\s\S]*?Oct 20, 2026/);
- assert.ok(page.includes('href="https://www.example.com/kb"'), 'the page it read is a source too');
+ assert.match(page, /<a class="vb-source" href="https:\/\/www\.example\.com\/kb"[^>]*><span class="vb-source-site">example\.com<\/span><span class="vb-source-date">[^<]+<\/span><\/a>/, 'the page it read is a source too, dated when it was read');
assert.ok(page.includes('<details class="vb-how"><summary>How Vibe did this</summary>'), 'folded under the answer');
assert.ok(page.includes('<details class="vb-how"><summary>How Vibe did this</summary>'), 'folded under the answer');
assert.match(page, /<li class="vb-how-sources"><span>Sources:<\/span> [\s\S]*?openvibe\.deals[\s\S]*?Oct 20, 2026[\s\S]*?example\.com/);
assert.match(page, /<li class="vb-how-sources"><span>Sources:<\/span> [\s\S]*?openvibe\.deals[\s\S]*?Oct 20, 2026[\s\S]*?example\.com/);
assert.strictEqual((page.match(/openvibe\.deals\/d\/k2/g) || []).length, 2, 'the chip and How list the same source');
assert.strictEqual((page.match(/openvibe\.deals\/d\/k2/g) || []).length, 2, 'the chip and How list the same source');