openvibers/openvibe.directory Commits

Keep Directory model entries fresh and link every status (#7)

OP OpenVibers committed 2 days ago · 8d4cfb67d3 · 2 files, +14 −6

Changes

ddiff --git a/server/sources.js b/server/sources.js
iindex 3839a7f..73bee38 100644
---- a/server/sources.js
++++ b/server/sources.js
@@@ -25,9 +25,11 @@ function models(data, checked) {
const out=[], makers=new Map();
for (const m of data.models||data.things||[]) {
const id=m.slug||m.id, maker=m.maker||String(id).split('/')[0];
-- const source=safeUrl(m.url)||URLS.models;
-- const website=m.slug ? `https://openvibe.exchange/m/${m.slug.split('/').map(encodeURIComponent).join('/')}` : `https://openvibe.compare/things/${encodeURIComponent(id)}`;
-- const e=entry('models',id,m.name,`AI model from ${maker}. See current provider offers, prices and measured results.`,website,source,iso(data.generated_at||data.updated_at)||checked,{provider:maker,context:m.context||null,modalities:m.modalities||[]});
++ const source=safeUrl(m.source)||safeUrl(m.url)||URLS.models;
++ const website=m.routing_enabled && m.slug
++ ? `https://openvibe.exchange/m/${m.slug.split('/').map(encodeURIComponent).join('/')}`
++ : `https://openvibe.exchange/models/${encodeURIComponent(id)}`;
++ const e=entry('models',id,m.name,`AI model from ${maker}. See current provider offers, prices and measured results.`,website,source,iso(data.generated_at||data.updated_at)||checked,{provider:maker,context:m.context_window??m.context??null,modalities:m.modalities||[],status:m.status||null});
if(e) out.push(e);
if(maker && !makers.has(maker)) makers.set(maker,entry('providers',maker,maker,'AI model provider.',source,URLS.models,iso(data.updated_at)||checked));
}
@@@ -54,7 +56,7 @@ function businesses(xml, checked) {
}
function toArray(value){return value==null?[]:Array.isArray(value)?value:[value];}
const parsers={sites,tools,models,projects,businesses};
--function createStore({fetchImpl=fetch,now=()=>new Date(),intervalMs=6*60*60*1000}={}){
++function createStore({fetchImpl=fetch,now=()=>new Date(),intervalMs=10*60*1000}={}){
const state={entries:new Map(Object.keys(kinds).map(k=>[k,[]])),status:{},refreshed_at:null};
let pending=null, timer=null;
async function refresh(){
ddiff --git a/test/directory.test.js b/test/directory.test.js
iindex 975c291..8b78b69 100644
---- a/test/directory.test.js
++++ b/test/directory.test.js
@@@ -9,11 +9,17 @@ test('unverified OSM phone tags are not published and business source is attribu
assert.equal(rows.length,1);assert.equal(rows[0].phone,undefined);assert.match(rows[0].sources[0].url,/openstreetmap/);assert.match(rows[0].osm_attribution,/ODbL/);
});
test('AI directory reads Exchange model ids and links to their model pages',()=>{
-- const rows=models({generated_at:'2026-11-11T00:00:00Z',models:[{slug:'google/gemini-3',name:'Gemini 3',context:1000000,modalities:['text','image']}]},'2026-11-11T01:00:00Z');
++ const rows=models({generated_at:'2026-11-11T00:00:00Z',models:[
++ {slug:'google/gemini-3',name:'Gemini 3',routing_enabled:true,context_window:1000000,modalities:['text','image']},
++ {id:'google/gemini-4',name:'Gemini 4',status:'spotted',routing_enabled:false,source:'https://aistudio.google.com/docs/changelog'}
++ ]},'2026-11-11T01:00:00Z');
assert.equal(URLS.models,'https://openvibe.exchange/api/v1/models');
assert.equal(rows[0].website,'https://openvibe.exchange/m/google/gemini-3');
assert.equal(rows[0].context,1000000);
-- assert.equal(rows[1].kind,'providers');
++ assert.equal(rows[1].website,'https://openvibe.exchange/models/google%2Fgemini-4');
++ assert.equal(rows[1].status,'spotted');
++ assert.equal(rows[1].sources[0].url,'https://aistudio.google.com/docs/changelog');
++ assert.equal(rows[2].kind,'providers');
});
test('failed refresh retains the last successful source and reports stale status',async()=>{
let fail=false;const fetchImpl=async(url)=>{if(fail)throw Error('source down');return {ok:true,json:async()=>url.includes('frame?')?{nav:[{id:'live',name:'Live',url:'https://openvibe.live/'}]}:{tools:[{id:'yaml',name:'YAML',docs:'https://openvibe.tools/tool/yaml'}],things:[{id:'a/b',name:'B',maker:'A',url:'https://example.com'}],items:[{full_name:'OpenVibers/Test',name:'Test',html_url:'https://github.com/OpenVibers/Test'}]},text:async()=>'<osm><node id="1"><tag k="shop" v="books"/><tag k="name" v="Books"/></node></osm>'};};