mirror of
https://github.com/HeyPuter/puter.git
synced 2026-10-07 04:12:36 +00:00
fix: backend tests breaking with permision (#2067)
Docker Image CI / build-and-push-image (push) Has been cancelled
Maintain Release Merge PR / update-release-pr (push) Has been cancelled
release-please / release-please (push) Has been cancelled
test / test-backend (20.x) (push) Has been cancelled
test / test-backend (22.x) (push) Has been cancelled
test / backend (node env, api-test) (22.x) (push) Has been cancelled
test / puterjs (browser env, playwright) (22.x) (push) Has been cancelled
test / puterjs (node env, vitest) (22.x) (push) Has been cancelled
Docker Image CI / build-and-push-image (push) Has been cancelled
Maintain Release Merge PR / update-release-pr (push) Has been cancelled
release-please / release-please (push) Has been cancelled
test / test-backend (20.x) (push) Has been cancelled
test / test-backend (22.x) (push) Has been cancelled
test / backend (node env, api-test) (22.x) (push) Has been cancelled
test / puterjs (browser env, playwright) (22.x) (push) Has been cancelled
test / puterjs (node env, vitest) (22.x) (push) Has been cancelled
This commit is contained in:
1 parent
e8f00e1121
commit
cea94d16cb
7 files changed
+56
-16
No files matched your search
@@ -156,14 +156,21 @@ class TogetherAIService extends BaseService {
|
||||
};
|
||||
}
|
||||
|
||||
// return completion.choices[0];
|
||||
const ret = completion.choices[0];
|
||||
|
||||
ret.usage = {
|
||||
input_tokens: completion.usage.prompt_tokens,
|
||||
output_tokens: completion.usage.completion_tokens,
|
||||
};
|
||||
|
||||
const trackedUsage = OpenAIUtil.extractMeteredUsage(completion.usage);
|
||||
const costOverrides = {
|
||||
prompt_tokens: trackedUsage.prompt_tokens * (modelDetails?.cost?.input ?? 0),
|
||||
completion_tokens: trackedUsage.completion_tokens * (modelDetails?.cost?.output ?? 0),
|
||||
};
|
||||
// Metering: record usage for non-streamed completion
|
||||
this.meteringService.utilRecordUsageObject(completion.usage, actor, modelId);
|
||||
this.meteringService.utilRecordUsageObject(completion.usage, actor, modelId, costOverrides);
|
||||
|
||||
return ret;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
const { AnomalyService } = require('../../services/AnomalyService');
|
||||
const { GroupService } = require('../../services/auth/GroupService');
|
||||
const { PermissionService } = require('../../services/auth/PermissionService');
|
||||
const { CommandService } = require('../../services/CommandService');
|
||||
const { SqliteDatabaseAccessService } = require('../../services/database/SqliteDatabaseAccessService');
|
||||
const { DetailProviderService } = require('../../services/DetailProviderService');
|
||||
const { EventService } = require('../../services/EventService');
|
||||
const { GetUserService } = require('../../services/GetUserService');
|
||||
const { MeteringServiceWrapper } = require('../../services/MeteringService/MeteringServiceWrapper.mjs');
|
||||
const { DBKVServiceWrapper } = require('../../services/repositories/DBKVStore/index.mjs');
|
||||
const { SUService } = require('../../services/SUService');
|
||||
const { TraceService } = require('../../services/TraceService');
|
||||
const { AlarmService } = require('../core/AlarmService');
|
||||
@@ -18,6 +23,11 @@ class TestCoreModule {
|
||||
services.registerService('alarm', AlarmService);
|
||||
services.registerService('event', EventService);
|
||||
services.registerService('commands', CommandService);
|
||||
services.registerService('meteringService', MeteringServiceWrapper);
|
||||
services.registerService('puter-kvstore', DBKVServiceWrapper);
|
||||
services.registerService('permission', PermissionService);
|
||||
services.registerService('group', GroupService);
|
||||
services.registerService('anomaly', AnomalyService);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -223,5 +223,5 @@ describe('MeteringService', async () => {
|
||||
count: 1,
|
||||
});
|
||||
}
|
||||
});
|
||||
}, 10000);
|
||||
});
|
||||
@@ -2,7 +2,6 @@ import { describe, expect, it } from 'vitest';
|
||||
import { createTestKernel } from '../../../../tools/test.mjs';
|
||||
import * as config from '../../../config';
|
||||
import { Actor } from '../../auth/Actor';
|
||||
import { MeteringServiceWrapper } from '../../MeteringService/MeteringServiceWrapper.mjs';
|
||||
import { DBKVServiceWrapper } from './index.mjs';
|
||||
|
||||
describe('DBKVStore', async () => {
|
||||
@@ -18,10 +17,7 @@ describe('DBKVStore', async () => {
|
||||
});
|
||||
|
||||
const testKernel = await createTestKernel({
|
||||
serviceMap: {
|
||||
meteringService: MeteringServiceWrapper,
|
||||
'puter-kvstore': DBKVServiceWrapper,
|
||||
},
|
||||
serviceMap: {},
|
||||
initLevelString: 'init',
|
||||
testCore: true,
|
||||
});
|
||||
@@ -64,6 +60,29 @@ describe('DBKVStore', async () => {
|
||||
expect(fromTwo).toBe('two');
|
||||
});
|
||||
|
||||
it('retrieves single and multiple keys respecting app vs global scope', async () => {
|
||||
const userId = 12;
|
||||
const globalActor = makeActor(userId);
|
||||
const appActor = makeActor(userId, 'scoped-app');
|
||||
|
||||
await su.sudo(globalActor, () => kvStore.set({ key: 'shared', value: 'global-shared' }));
|
||||
await su.sudo(globalActor, () => kvStore.set({ key: 'global-only', value: 'global' }));
|
||||
await su.sudo(appActor, () => kvStore.set({ key: 'shared', value: 'app-shared' }));
|
||||
await su.sudo(appActor, () => kvStore.set({ key: 'app-only', value: 'app' }));
|
||||
|
||||
const globalSingle = await su.sudo(globalActor, () => kvStore.get({ key: 'shared' }));
|
||||
const appSingle = await su.sudo(appActor, () => kvStore.get({ key: 'shared' }));
|
||||
|
||||
expect(globalSingle).toBe('global-shared');
|
||||
expect(appSingle).toBe('app-shared');
|
||||
|
||||
const globalList = await su.sudo(globalActor, () => kvStore.get({ key: ['shared', 'app-only', 'global-only'] }));
|
||||
const appList = await su.sudo(appActor, () => kvStore.get({ key: ['shared', 'app-only', 'global-only'] }));
|
||||
|
||||
expect(globalList).toEqual(['global-shared', null, 'global']);
|
||||
expect(appList).toEqual(['app-shared', 'app', null]);
|
||||
});
|
||||
|
||||
it('increments nested numeric paths and persists the aggregated totals', async () => {
|
||||
const actor = makeActor(3);
|
||||
const key = 'counter-key';
|
||||
|
||||
@@ -53,10 +53,14 @@ export class DBKVStore implements IDBKVStore {
|
||||
if ( Array.isArray(key) ) {
|
||||
const keys = key;
|
||||
const key_hashes = keys.map((key: string) => murmurhash.v3(key));
|
||||
const placeholders = key_hashes.map(() => '?').join(',');
|
||||
const params = app
|
||||
? [user.id, app.uid, ...key_hashes]
|
||||
: [user.id, ...key_hashes];
|
||||
const rows = app
|
||||
? await this.#db.read('SELECT kkey, value, expireAt FROM kv WHERE user_id=? AND app=? AND kkey_hash IN (?)', [user.id, app.uid, key_hashes])
|
||||
: await this.#db.read(`SELECT kkey, value, expireAt FROM kv WHERE user_id=? AND (app IS NULL OR app = '${GLOBAL_APP_KEY}') AND kkey_hash IN (${key_hashes.map(() => '?').join(',')})`,
|
||||
[user.id, key_hashes]);
|
||||
? await this.#db.read(`SELECT kkey, value, expireAt FROM kv WHERE user_id=? AND app=? AND kkey_hash IN (${placeholders})`, params)
|
||||
: await this.#db.read(`SELECT kkey, value, expireAt FROM kv WHERE user_id=? AND (app IS NULL OR app = '${GLOBAL_APP_KEY}') AND kkey_hash IN (${placeholders})`,
|
||||
params);
|
||||
|
||||
const kvPairs: Record<string, unknown> = {};
|
||||
rows.forEach((row: { kkey: string, value: string }) => {
|
||||
@@ -82,7 +86,7 @@ export class DBKVStore implements IDBKVStore {
|
||||
deleteExpired(expiredKeys);
|
||||
}
|
||||
|
||||
return keys.map((key: string) => kvPairs[key]) as unknown[];
|
||||
return keys.map((key: string) => Object.prototype.hasOwnProperty.call(kvPairs, key) ? kvPairs[key] : null) as unknown[];
|
||||
}
|
||||
|
||||
const key_hash = murmurhash.v3(key);
|
||||
|
||||
Reference in new issue
Block a user