openvibers/openvibe.ai Commits
Search: the OpenVibe engine answers (its real host and fields) (#498)
Changes
@@@ -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));},};@@@ -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"},@@@ -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 }));
@@ -1,22 +1,28 @@
@@ -1,22 +1,28 @@
'use strict';
'use strict';
const { requestFor } = require('../transport');
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 = {
module.exports = {
id: 'openvibe',
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: [],
freshness: [],
- hosts: ['openvibe.search'],
+ hosts: [HOST],
kinds: ['web'],
kinds: ['web'],
async search(b, { fetchImpl }) {
async search(b, { fetchImpl }) {
const get = requestFor(this.hosts, fetchImpl);
const get = requestFor(this.hosts, fetchImpl);
const out = await get(
const out = await get(
- 'https://openvibe.search/api/v1/search?' +
+ `https://${HOST}/api/v1/search?` +
new URLSearchParams({ q: b.q, limit: String(b.limit) }),
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));
},
},
};
};
@@ -2,15 +2,20 @@
@@ -2,15 +2,20 @@
"response": {
"response": {
"results": [
"results": [
{
{
+ "owner": "wiki",
+ "type": "article",
+ "id": "art_01",
+ "visibility": "public",
"title": "Lantern",
"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"
"published_at": "2026-11-08T12:00:00Z"
}
}
- ]
+ ],
+ "next_cursor": null
},
},
"request": {
"request": {
- "host": "openvibe.search",
+ "host": "search.openvibe.network",
"path": "/api/v1/search",
"path": "/api/v1/search",
"method": "GET"
"method": "GET"
},
},
@@ -49,7 +49,7 @@ const json = value => new Response(JSON.stringify(value), { status: 200 });
@@ -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);
const card = (await search.engines()).find(e => e.id === a.id);
assert.equal(card.price_per_1000, a.price_per_1000);
assert.equal(card.price_per_1000, a.price_per_1000);
assert.equal(card.source, a.source);
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) {
if (a.byok) {
assert.equal((await createSearch({ env: {} }).engines()).find(e => e.id === a.id).available, false);
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 }));
await assert.rejects(createSearch({ env: {}, fetchImpl: () => assert.fail('unconfigured engine called') }).search(kind, { q: 'x', engine: a.id }));