openvibers/openvibe.ai Commits

Search: the OpenVibe engine answers (its real host and fields) (#498)

OP OpenVibers committed 1 days ago · 67534552cc · 3 files, +25 −14

The owner, 11-12, a screenshot of openvibe.exchange/search: both engines "unavailable
or does not support this search kind" for any query.

The OpenVibe engine asked https://openvibe.search, a host that does not exist, and
read `url` and `snippet` where OpenVibe Search answers `canonical_url` and `summary`,
so every result would have failed the result contract even on the right host. Its
fixture had both mistakes, so the adapter tests passed.

- The adapter asks search.openvibe.network/api/v1/search and maps canonical_url and
  summary; rows without a title or an https address are left out.
- The fixture is OpenVibe Search's real response shape.

Changes

ddiff --git a/server/search/adapters/openvibe.js b/server/search/adapters/openvibe.js
iindex ae0f4b4..ab65496 100644
---- a/server/search/adapters/openvibe.js
++++ b/server/search/adapters/openvibe.js
@@@ -1,22 +1,28 @@
'use strict';
const { requestFor } = require('../transport');
++// OpenVibe's own index (OpenVibe.Search's public search API). Until 11-12 this asked https://openvibe.search, a host
++// that does not exist, and read `url`/`snippet` where Search answers `canonical_url`/`summary`: the engine never
++// answered, and Exchange's search page said "This engine is unavailable" for every query.
++const HOST = 'search.openvibe.network';
module.exports = {
id: 'openvibe',
-- price_per_1000: 0, byok: false, checked_on: '2026-11-09', source: 'https://openvibe.search',
++ price_per_1000: 0, byok: false, checked_on: '2026-11-12', source: `https://${HOST}`,
freshness: [],
-- hosts: ['openvibe.search'],
++ hosts: [HOST],
kinds: ['web'],
async search(b, { fetchImpl }) {
const get = requestFor(this.hosts, fetchImpl);
const out = await get(
-- 'https://openvibe.search/api/v1/search?' +
++ `https://${HOST}/api/v1/search?` +
new URLSearchParams({ q: b.q, limit: String(b.limit) }),
);
-- return (out.results || []).map((r) => ({
-- title: r.title,
-- url: r.url,
-- snippet: r.snippet || r.description || '',
-- published: r.published_at || null,
-- }));
++ return (out.results || [])
++ .map((r) => ({
++ title: String(r.title || '').trim(),
++ url: r.canonical_url || r.url || '',
++ snippet: r.summary || r.snippet || r.description || '',
++ published: r.published_at || null,
++ }))
++ .filter((r) => r.title && /^https:\/\//.test(r.url));
},
};
ddiff --git a/test/fixtures/search/openvibe.json b/test/fixtures/search/openvibe.json
iindex bd1c38f..9223e71 100644
---- a/test/fixtures/search/openvibe.json
++++ b/test/fixtures/search/openvibe.json
@@@ -2,15 +2,20 @@
"response": {
"results": [
{
++ "owner": "wiki",
++ "type": "article",
++ "id": "art_01",
++ "visibility": "public",
"title": "Lantern",
-- "url": "https://example.org/article",
-- "description": "A new lantern",
++ "summary": "A new lantern",
++ "canonical_url": "https://example.org/article",
"published_at": "2026-11-08T12:00:00Z"
}
-- ]
++ ],
++ "next_cursor": null
},
"request": {
-- "host": "openvibe.search",
++ "host": "search.openvibe.network",
"path": "/api/v1/search",
"method": "GET"
},
ddiff --git a/test/search-adapters.test.js b/test/search-adapters.test.js
iindex 9e499d3..df8c46e 100644
---- a/test/search-adapters.test.js
++++ b/test/search-adapters.test.js
@@@ -49,7 +49,7 @@ const json = value => new Response(JSON.stringify(value), { status: 200 });
const card = (await search.engines()).find(e => e.id === a.id);
assert.equal(card.price_per_1000, a.price_per_1000);
assert.equal(card.source, a.source);
-- assert.equal(card.checked_on, ['meta', 'serper-images'].includes(a.id) ? '2026-11-10' : '2026-11-09');
++ assert.equal(card.checked_on, a.id === 'openvibe' ? '2026-11-12' : ['meta', 'serper-images'].includes(a.id) ? '2026-11-10' : '2026-11-09');
if (a.byok) {
assert.equal((await createSearch({ env: {} }).engines()).find(e => e.id === a.id).available, false);
await assert.rejects(createSearch({ env: {}, fetchImpl: () => assert.fail('unconfigured engine called') }).search(kind, { q: 'x', engine: a.id }));