openvibers/openvibe.ai Commits

openvibe-sdk v0.35.0 (was v0.26.0) (#26)

OP OpenVibers committed 8 Oct 2026 · ba0df55b8f · 7 files, +12 −12

* openvibe-sdk v0.35.0 (was v0.26.0)

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

* AI reads SDK 0.35's usage record: govern's onUsage gives quantity (was amount), and both governors name the service ('ai') platform.usage-sample@1 requires.

Changes

ddiff --git a/README.md b/README.md
iindex 1dec5ef..f6c8b8b 100644
---- a/README.md
++++ b/README.md
@@@ -43,7 +43,7 @@ owns publication truth: Wiki, Blog, News, Live, … decide what to publish.
- OpenVibe.Media (recordings `media.analyze` reads, over allow-listed https URLs or signed URLs)
- provider APIs configured by the operator (OpenAI-compatible, OpenAI Responses, Anthropic, the HTTP seam), whisper.cpp
and the local model server `openvibe-llm.service` on this host
--- `openvibe-contracts` v0.86.0, `openvibe-sdk` v0.26.0 (service tokens, events outbox),
++- `openvibe-contracts` v0.86.0, `openvibe-sdk` v0.35.0 (service tokens, events outbox),
`openvibe-shared` v2.3.1, pinned by release tarball
## Capabilities
@@@ -483,6 +483,6 @@ Part of the [OpenVibe network](https://openvibe.network). Built in the open by [
<!-- versions:start -->
- openvibe-contracts: v0.112.0
--- openvibe-sdk: v0.26.0
++- openvibe-sdk: v0.35.0
- openvibe-shared: v2.13.0
<!-- versions:end -->
ddiff --git a/STATUS.json b/STATUS.json
iindex e64e541..62bb9f7 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -8,7 +8,7 @@
"port": 4700,
"domain": "ai.openvibe.network still serves the OpenVibe.Sites placeholder; the service runs on openvibe-ovh (/opt/openvibe.ai, unit openvibe-ai) on 127.0.0.1:4700, loopback only, used by OpenVibe.Live and OpenVibe.Network",
"contracts": "openvibe-contracts v0.112.0",
-- "sdk": "openvibe-sdk v0.26.0",
++ "sdk": "openvibe-sdk v0.35.0",
"shared": "openvibe-shared v2.13.0",
"capabilities": [
"ai.run.create",
ddiff --git a/package-lock.json b/package-lock.json
iindex 7dadacc..9b39196 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -14,7 +14,7 @@
"express": "^4.21.2",
"iovalkey": "^0.4.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.112.0",
-- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.26.0",
++ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.35.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.13.0",
"pg": "^8.23.0"
},
@@@ -1281,9 +1281,9 @@
}
},
"node_modules/openvibe-sdk": {
-- "version": "0.26.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.26.0",
-- "integrity": "sha512-+RK89ZG4WAKIRh89yr3ieIvnyJVNSOI+dsbBqGNcr9UHsJStdxtM75zSDq8cUNpBPQ1X6ElatZrjU9S3s0aEkg==",
++ "version": "0.35.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.35.0",
++ "integrity": "sha512-IF7XB97tU7Q+ccwssGx6QXXcfDPcVpl+mX3BjIr7C6NJlcmoqj9DbHiKrBxlVav0eG44Jf8zuXEwokrHDq3J0w==",
"license": "MIT",
"engines": {
"node": ">=20"
ddiff --git a/package.json b/package.json
iindex 9988b8e..e5a4b02 100644
---- a/package.json
++++ b/package.json
@@@ -26,7 +26,7 @@
"express": "^4.21.2",
"iovalkey": "^0.4.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.112.0",
-- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.26.0",
++ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.35.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.13.0",
"pg": "^8.23.0"
},
ddiff --git a/server/govern.js b/server/govern.js
iindex 78ee1a3..e12f4f3 100644
---- a/server/govern.js
++++ b/server/govern.js
@@@ -80,7 +80,7 @@ function createTiers({ config, valkey = null, clock = { now: () => Date.now() },
if (owned) valkey = createValkey({ url: g.valkeyUrl, prefix: g.valkeyPrefix, log });
if (!valkey && config.isProduction) throw new Error('AI_GOVERN_TIERS=1 needs VALKEY_URL: the tier budgets are counted in Valkey');
if (!valkey) log.warn('[govern] no VALKEY_URL: tier budgets are counted in this process only');
-- const gov = createGovernor({ policy: g.policy, valkey, now: () => clock.now() });
++ const gov = createGovernor({ service: 'ai', policy: g.policy, valkey, now: () => clock.now(), log });
const free = freeCounters(valkey);
const tierOf = (...keys) => { for (const k of keys) if (k && g.tiers[k]) return g.tiers[k]; return g.defaultTier; };
let lastError = null;
@@@ -160,7 +160,7 @@ function createTiers({ config, valkey = null, clock = { now: () => Date.now() },
*/
function createMeter() {
const seen = new Map();
-- const gov = createGovernor({ onUsage: (e) => { if (seen.has(e.idempotency_key)) seen.set(e.idempotency_key, e); } });
++ const gov = createGovernor({ service: 'ai', onUsage: (e) => { if (seen.has(e.idempotency_key)) seen.set(e.idempotency_key, e); } });
return async function reading({ subject, quantity, key }) {
if (seen.has(key)) return null;
seen.set(key, null);
ddiff --git a/server/usage-samples.js b/server/usage-samples.js
iindex 8e7801e..871ff01 100644
---- a/server/usage-samples.js
++++ b/server/usage-samples.js
@@@ -54,7 +54,7 @@ function sampleOf({ runId, attempt, kind, workflowKey, requester, project = null
}
/** The reading: govern's onUsage record (id, subject, quantity) on the attempt's own fields. */
function sampleFromUsage(e, fields) {
-- return { ...sampleOf(fields), id: e.idempotency_key, idempotency_key: e.idempotency_key, subject: e.subject, quantity: e.amount };
++ return { ...sampleOf(fields), id: e.idempotency_key, idempotency_key: e.idempotency_key, subject: e.subject, quantity: e.quantity };
}
/**
* MUST be awaited inside the transaction that accounts the run. `readings` are the run's per-attempt,
ddiff --git a/test/govern-tiers.test.js b/test/govern-tiers.test.js
iindex 9bdfe03..c2cf630 100644
---- a/test/govern-tiers.test.js
++++ b/test/govern-tiers.test.js
@@@ -140,7 +140,7 @@ t.test('the meter: one onUsage record per idempotency key at once', async () =>
const reading = createMeter();
const got = await Promise.all([reading({ subject: 'service:live', quantity: 5, key: 'ai:run_m:tokens' }), reading({ subject: 'service:live', quantity: 5, key: 'ai:run_m:tokens' })]);
assert.strictEqual(got.filter(Boolean).length, 1);
-- assert.deepStrictEqual([got.find(Boolean).idempotency_key, got.find(Boolean).amount, got.find(Boolean).subject], ['ai:run_m:tokens', 5, 'service:live']);
++ assert.deepStrictEqual([got.find(Boolean).idempotency_key, got.find(Boolean).quantity, got.find(Boolean).subject, got.find(Boolean).service], ['ai:run_m:tokens', 5, 'service:live', 'ai']);
});
// On the containers' Valkey (OV_TEST_VALKEY_URL, set by openvibe-sdk/scripts/test-services.sh): govern's Lua and the