openvibers/openvibe.ai Commits

openvibe-shared v1.5.0 (Track R release manifest), openvibe-contracts v0.32.0

OP OpenVibers committed 23 Sept 2026 · 772262c303 · 5 files, +21 −12

- /release.json is mounted with release.mount(app, { registry }), which also answers POST
  /release-metrics (release_client_updates_total in /metrics). On contracts 0.32.0 the manifest
  carries the release-manifest 1.1.0 fields; no components are declared. The observability test
  validates the served manifest against the contracts.
- Contracts 0.29.0 -> 0.32.0 is additive for AI (0.30.0 adds ai.run-request@1/ai.run@1 as the
  schemas of ai.run.create/read and lists the planned ai.run.* events); the tests and the contracts
  check pass unchanged.

Changes

ddiff --git a/STATUS.json b/STATUS.json
iindex 7645ad9..b0e4e5b 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -7,7 +7,7 @@
"runtime": "node 22, express, better-sqlite3",
"port": 4700,
"domain": "ai.openvibe.network still serves the OpenVibe.Sites placeholder; the service runs on openvibe-ovh (/opt/openvibe.ai, release bdca064, unit openvibe-ai) on 127.0.0.1:4700, loopback only, used by OpenVibe.Live and OpenVibe.Network",
-- "contracts": "openvibe-contracts v0.29.0",
++ "contracts": "openvibe-contracts v0.32.0",
"capabilities": ["ai.run.create", "ai.run.read", "ai.workflow.manage", "ai.provider.manage", "ai.usage.read"],
"capabilitiesRegistered": true,
"providers": ["stub", "openai-compatible", "anthropic", "http-seam", "whisper.cpp"],
ddiff --git a/package-lock.json b/package-lock.json
iindex b22bc6e..aa17343 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -13,8 +13,8 @@
"better-sqlite3": "^11.10.0",
"dotenv": "^16.4.7",
"express": "^4.21.2",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.29.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.3.0"
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.32.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.0"
},
"engines": {
"node": ">=20.0.0"
@@@ -1394,9 +1394,9 @@
}
},
"node_modules/openvibe-contracts": {
-- "version": "0.29.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.29.0",
-- "integrity": "sha512-IJhCi0qY7AuvFUt3+QMLkA0vi4WbUecIyQ3rdT7mF0U+pMTDxHZm2XHxpjfF0t7XPhoRCfgnKRZ4M7q7vLlkIA==",
++ "version": "0.32.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.32.0",
++ "integrity": "sha512-ntN58SIG03YDxbhsiIzOM5GRH19jRMHZUYWI3xU2VwovExagF5DdwApLVfezsu84UTJ+V2Jfn+LWDc+Oz8ab+g==",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
@@@ -1410,9 +1410,9 @@
}
},
"node_modules/openvibe-shared": {
-- "version": "1.3.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.3.0",
-- "integrity": "sha512-w8yl/5+9eend8I2O/DzAJnEAL2N3GTUY7c7pzK+MLJuLAGD8FmJJQ9gwbgyrq70Snjt3ebrg3TlpORhRAp2kgA==",
++ "version": "1.5.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.0",
++ "integrity": "sha512-cehnscuYMkJwuCYGcI6wPSswbUn0bhTyGAaD5feNCoO//2e9gyC7cgjkEcIOtM8DQF3yTuUNyXnOwckIeM4fUg==",
"license": "MIT",
"dependencies": {
"jsonwebtoken": "^9.0.0"
ddiff --git a/package.json b/package.json
iindex 6a2b3ce..cf7d82e 100644
---- a/package.json
++++ b/package.json
@@@ -19,8 +19,8 @@
"better-sqlite3": "^11.10.0",
"dotenv": "^16.4.7",
"express": "^4.21.2",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.29.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.3.0"
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.32.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.5.0"
},
"optionalDependencies": {
"sharp": "^0.33.5"
ddiff --git a/server/app.js b/server/app.js
iindex 5d80da6..f63703f 100644
---- a/server/app.js
++++ b/server/app.js
@@@ -36,7 +36,8 @@ function createApp({ config, db, registry, pool, quotas, cache, runs, auth, keys
// fail; provider configuration is optional and degrades it (see observability.js).
const readiness = createAiReadiness({ db, registry, pool, keys, runs, release: release.release });
app.get('/api/ready', readiness.handler);
-- app.get('/release.json', release.handler);
++ // GET /release.json (ADR-016) and POST /release-metrics (open tabs' update reports into /metrics).
++ release.mount(app, { registry: metrics.registry });
app.use(runsRouter({ runs, registry, auth, config, log }));
app.use(adminRouter({ db, registry, pool, quotas, cache, runs, auth, log }));
ddiff --git a/test/observability.test.js b/test/observability.test.js
iindex 982341e..e34a51b 100644
---- a/test/observability.test.js
++++ b/test/observability.test.js
@@@ -45,6 +45,14 @@ t.test('/api/ready: every check reports; providers is the only optional one', as
assert.ok(!r.text.includes('sk-test-not-real'));
});
++t.test('/release.json: a registry.release-manifest@1 that names where tabs report updates', async () => {
++ const r = await request(h.base, 'GET', '/release.json');
++ assert.strictEqual(r.status, 200, r.text);
++ assert.strictEqual(r.body.service, 'ai');
++ assert.deepStrictEqual(require('openvibe-contracts').validate('registry.release-manifest@1', r.body).errors, []);
++ assert.strictEqual(r.body.metrics_url, '/release-metrics');
++});
++
t.test('/metrics: 404 through a proxy; queued and running runs, route templates, circuit state direct', async () => {
const ids = [];
for (let i = 0; i < 3; i++) {