openvibers/openvibe.connect Commits

openvibe-shared v4.108.0 (was v4.107.4) (#32)

OP OpenVibers committed 10 days ago · ddb5ddee4e · 6 files, +37 −24

* openvibe-shared v4.108.0 (was v4.107.4)

Opened by scripts/pin-bump.js in OpenVibers/OpenVibe.Shared after the v4.108.0 release.

* llms.txt links each page at its Markdown twin, with an ## Optional section (AGT-5)

Changes

ddiff --git a/README.md b/README.md
iindex be1cd1e..bf20228 100644
---- a/README.md
++++ b/README.md
@@@ -213,5 +213,5 @@ AGPL-3.0-only. The client (`public/ov-connect.js`) is part of this repository un
<!-- versions:start -->
- openvibe-contracts: v0.279.0
- openvibe-sdk: v0.82.0
--- openvibe-shared: v4.107.4
++- openvibe-shared: v4.108.0
<!-- versions:end -->
ddiff --git a/STATUS.json b/STATUS.json
iindex ee947b6..c8891e8 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -9,11 +9,11 @@
"domain": "connect.openvibe.website",
"contracts": "openvibe-contracts v0.279.0",
"sdk": "openvibe-sdk v0.82.0",
-- "shared": "openvibe-shared v4.107.4",
++ "shared": "openvibe-shared v4.108.0",
"packages": [
"openvibe-contracts v0.279.0",
"openvibe-sdk v0.82.0",
-- "openvibe-shared v4.107.4"
++ "openvibe-shared v4.108.0"
],
"summary": "OpenVibe Connect puts one port on a person's computer on the web at its own HTTPS address, behind OpenVibe sign-in. A one-file client (Node 22, no dependencies) opens one outgoing WebSocket through Cloudflare and carries requests to localhost: HTTP with streaming both ways, server-sent events and WebSocket upgrades. Every visitor signs in and must be allowed by the share's policy (only the owner, named people, or anyone signed in); the share host keeps its own host-only signed cookie. Nothing that passes through is stored.",
"works": [
ddiff --git a/package-lock.json b/package-lock.json
iindex bf60b1e..2c2db7b 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -17,7 +17,7 @@
"iovalkey": "^0.4.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.279.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.82.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.107.4",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.108.0",
"pg": "^8.23.1",
"ws": "^8.18.0"
},
@@@ -1202,9 +1202,9 @@
}
},
"node_modules/openvibe-shared": {
-- "version": "4.107.4",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.107.4",
-- "integrity": "sha512-tThN0m3KMncEHVcBOvE+ysHjsZTlVIDLG1P+/i2Mulmxfc/AUpebAXhpWWrut50OChZ8o+HeePxsSrPI8mUQOQ==",
++ "version": "4.108.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.108.0",
++ "integrity": "sha512-NPzwjxpzGIpFpIm4uw3+VwHfsxbJ2+cD9yuhRzSwolSwqv2kCmwaVtHJ0DA9gKO3K8PCBfIP3UpKzpuSbYEJ+g==",
"license": "MIT",
"dependencies": {
"jsonwebtoken": "^9.0.0",
ddiff --git a/package.json b/package.json
iindex 8eae995..b1cae17 100644
---- a/package.json
++++ b/package.json
@@@ -27,7 +27,7 @@
"iovalkey": "^0.4.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.279.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.82.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.107.4",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.108.0",
"pg": "^8.23.1",
"ws": "^8.18.0"
},
ddiff --git a/server/http/pages.js b/server/http/pages.js
iindex 9ccd9e9..c70ff5b 100644
---- a/server/http/pages.js
++++ b/server/http/pages.js
@@@ -28,6 +28,7 @@ const { ApiKeyError } = require('../api-keys');
// Connect's README, its full public documentation, for /llms-full.txt (read once; empty if it is not shipped).
const README = (() => { try { return require('fs').readFileSync(require('path').join(__dirname, '..', '..', 'README.md'), 'utf8').trim(); } catch { return ''; } })();
const { OAuthError } = require('../oauth');
++const seo = require('openvibe-shared/seo');
function createPageRoutes(ctx) {
const { config, shares, tunnels, gate, proxy, machines, hooks, apiKeys } = ctx;
@@@ -305,7 +306,6 @@ function createPageRoutes(ctx) {
}
});
-- const site = String(config.baseUrl).replace(/\/+$/, '');
r.get('/robots.txt', (req, res) => {
res.type('text/plain').set('Cache-Control', 'public, max-age=3600').send(`User-agent: *\nAllow: /$\nDisallow: /shares\nDisallow: /grant\nDisallow: /auth\nDisallow: /api\n\nSitemap: ${site}/sitemap.xml\n`);
});
@@@ -314,24 +314,34 @@ function createPageRoutes(ctx) {
res.type('application/xml').set('Cache-Control', 'public, max-age=3600')
.send(`<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n <url><loc>${site}/</loc></url>\n</urlset>\n`);
});
++ const site = String(config.baseUrl).replace(/\/+$/, '');
++ const abs = (p) => `${site}${p}`;
++
// What llms.txt says (SEO-33: /llms-full.txt adds the README, Connect's full documentation, after it).
-- const LLMS_LINES = [
-- '# OpenVibe Connect',
-- '',
-- '> Share one port on your computer at https://<name>--<username>.openvibe.website, behind OpenVibe sign-in.',
-- '',
-- '- Client: one file, Node 22+: curl -fsSLO https://connect.openvibe.website/ov-connect.js; node ov-connect.js --key ovc_… --port 8080',
-- '- Who can open a share: only the owner, the owner and named OpenVibe usernames, or anyone signed in to OpenVibe. No public shares yet.',
-- '- The app behind a share receives X-OpenVibe-User and X-OpenVibe-Subject; Host is localhost:<port>.',
-- '- API (a person\'s Network token as a Bearer): GET/POST /api/v1/shares, GET/PATCH/DELETE /api/v1/shares/{id}, POST /api/v1/shares/{id}/key',
-- '- Source: https://github.com/OpenVibers/OpenVibe.Connect (AGPL-3.0)',
-- '',
-- ];
++ const NAME = 'OpenVibe Connect';
++ const SUMMARY = 'Share one port on your computer at https://<name>--<username>.openvibe.website, behind OpenVibe sign-in.';
++ const DETAILS = [
++ 'Client: one file, Node 22+: curl -fsSLO https://connect.openvibe.website/ov-connect.js; node ov-connect.js --key ovc_… --port 8080.',
++ 'Who can open a share: only the owner, the owner and named OpenVibe usernames, or anyone signed in to OpenVibe. No public shares yet.',
++ 'The app behind a share receives X-OpenVibe-User and X-OpenVibe-Subject; Host is localhost:<port>.',
++ 'API (a person\'s Network token as a Bearer): GET/POST /api/v1/shares, GET/PATCH/DELETE /api/v1/shares/{id}, POST /api/v1/shares/{id}/key.',
++ 'Source: https://github.com/OpenVibers/OpenVibe.Connect (AGPL-3.0).',
++ ].join(' ');
++ const LLMS_SECTIONS = [{ title: 'Start here', links: [{ title: NAME, url: abs('/'), note: 'your shares and the form to make one' }] }];
++ const LLMS_OPTIONAL = [
++ { title: 'Client download', url: abs('/ov-connect.js'), note: 'one file, Node 22+' },
++ { title: 'Sitemap', url: abs('/sitemap.xml') },
++ { title: 'Full text for language models', url: abs('/llms-full.txt') },
++ ];
++ const LLMS_HEADER = seo.llmsTxt({
++ name: NAME, summary: SUMMARY, details: DETAILS, markdown: true, base: config.baseUrl,
++ sections: LLMS_SECTIONS, optional: LLMS_OPTIONAL,
++ });
r.get('/llms.txt', (req, res) => {
-- res.type('text/plain').set('Cache-Control', 'public, max-age=3600').send(LLMS_LINES.join('\n'));
++ res.type('text/plain').set('Cache-Control', 'public, max-age=3600').send(LLMS_HEADER);
});
r.get('/llms-full.txt', (req, res) => {
-- res.type('text/plain').set('Cache-Control', 'public, max-age=3600').send(`${LLMS_LINES.join('\n')}\n\n## The documentation (README)\n\n${README}\n`);
++ res.type('text/plain').set('Cache-Control', 'public, max-age=3600').send(`${LLMS_HEADER}\n\n## The documentation (README)\n\n${README}\n`);
});
return r;
ddiff --git a/test/pages.test.js b/test/pages.test.js
iindex 98aa4d4..11e94e9 100644
---- a/test/pages.test.js
++++ b/test/pages.test.js
@@@ -103,7 +103,10 @@ const { check, done } = require('./helpers/check');
const map = await t.get('/sitemap.xml');
assert.strictEqual(map.status, 200, 'the sitemap agent.json names answers');
assert.match(map.text, /<urlset xmlns="http:\/\/www\.sitemaps\.org\/schemas\/sitemap\/0\.9">\n <url><loc>https?:\/\/[^<]+\/<\/loc><\/url>\n<\/urlset>/);
-- assert.match((await t.get('/llms.txt')).text, /OpenVibe Connect/);
++ const llms = await t.get('/llms.txt');
++ assert.match(llms.text, /OpenVibe Connect/);
++ assert.match(llms.text, /\n## Optional\n/);
++ assert.match(llms.text, /\(https:\/\/connect\.openvibe\.website\/index\.md\)/);
// SEO-2: the agent manifest is served (11-03: the mount had landed inside the share-host middleware, after its
// return, so it never ran while the source check passed).
const agent = await t.get('/.well-known/agent.json');